aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--python/requirements.txt2
-rw-r--r--python/servo/lints/wpt_lint.py2
-rw-r--r--tests/wpt/include.ini2
-rw-r--r--tests/wpt/metadata/2dcontext/imagebitmap/createImageBitmap-invalid-args.html.ini7
-rw-r--r--tests/wpt/metadata/FileAPI/blob/Blob-Request-revoke-fetch.html.ini4
-rw-r--r--tests/wpt/metadata/FileAPI/blob/Blob-constructor-endings.html.ini4
-rw-r--r--tests/wpt/metadata/FileAPI/blob/Blob-constructor.html.ini3
-rw-r--r--tests/wpt/metadata/FileAPI/file/File-constructor-endings.html.ini4
-rw-r--r--tests/wpt/metadata/FileAPI/file/File-constructor.html.ini9
-rw-r--r--tests/wpt/metadata/FileAPI/file/send-file-form-iso-2022-jp.tentative.html.ini4
-rw-r--r--tests/wpt/metadata/FileAPI/file/send-file-form-utf-8.html.ini4
-rw-r--r--tests/wpt/metadata/FileAPI/file/send-file-form-windows-1252.tentative.html.ini4
-rw-r--r--tests/wpt/metadata/FileAPI/file/send-file-form-x-user-defined.tentative.html.ini4
-rw-r--r--tests/wpt/metadata/FileAPI/file/send-file-form.html.ini4
-rw-r--r--tests/wpt/metadata/FileAPI/unicode.html.ini4
-rw-r--r--tests/wpt/metadata/MANIFEST.json19012
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/failures.worker.js.ini5
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-CBC.https.worker.js.ini4
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-CBC.worker.js.ini5
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-CTR.https.worker.js.ini4
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-CTR.worker.js.ini5
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-GCM.https.worker.js.ini4
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-GCM.worker.js.ini5
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-KW.https.worker.js.ini4
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-KW.worker.js.ini5
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/failures_ECDH.https.worker.js.ini4
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/failures_ECDH.worker.js.ini5
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/failures_ECDSA.https.worker.js.ini4
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/failures_ECDSA.worker.js.ini5
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/failures_HMAC.https.worker.js.ini4
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/failures_HMAC.worker.js.ini5
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/failures_RSA-OAEP.https.worker.js.ini4
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/failures_RSA-OAEP.worker.js.ini5
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/failures_RSA-PSS.https.worker.js.ini4
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/failures_RSA-PSS.worker.js.ini5
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/failures_RSASSA-PKCS1-v1_5.https.worker.js.ini4
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/failures_RSASSA-PKCS1-v1_5.worker.js.ini5
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/successes.worker.js.ini5
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-CBC.https.worker.js.ini4
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-CBC.worker.js.ini5
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-CTR.https.worker.js.ini4
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-CTR.worker.js.ini5
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-GCM.https.worker.js.ini4
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-GCM.worker.js.ini5
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-KW.https.worker.js.ini4
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-KW.worker.js.ini5
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/successes_ECDH.https.worker.js.ini4
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/successes_ECDH.worker.js.ini5
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/successes_ECDSA.https.worker.js.ini4
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/successes_ECDSA.worker.js.ini5
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/successes_HMAC.https.worker.js.ini4
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/successes_HMAC.worker.js.ini5
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/successes_RSA-OAEP.https.worker.js.ini4
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/successes_RSA-OAEP.worker.js.ini5
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/successes_RSA-PSS.https.worker.js.ini4
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/successes_RSA-PSS.worker.js.ini5
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.https.worker.js.ini4
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.worker.js.ini5
-rw-r--r--tests/wpt/metadata/WebCryptoAPI/generateKey/test_failures.https.html.ini5
-rw-r--r--tests/wpt/metadata/WebIDL/ecmascript-binding/no-regexp-special-casing.any.js.ini9
-rw-r--r--tests/wpt/metadata/XMLHttpRequest/send-redirect-post-upload.htm.ini6
-rw-r--r--tests/wpt/metadata/css/CSS2/backgrounds/background-color-030.xht.ini3
-rw-r--r--tests/wpt/metadata/css/CSS2/backgrounds/background-color-174.xht.ini3
-rw-r--r--tests/wpt/metadata/css/CSS2/backgrounds/background-image-002.xht.ini3
-rw-r--r--tests/wpt/metadata/css/CSS2/colors/color-083.xht.ini3
-rw-r--r--tests/wpt/metadata/css/CSS2/colors/color-084.xht.ini3
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/after-inheritable-001.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/after-inheritable-002.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/before-inheritable-002.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-004.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-010.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-011.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-012.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-014.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-015.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-016.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-017.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-026.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-027.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-028.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-030.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-031.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-032.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-033.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-037.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-038.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-039.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-040.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-041.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-042.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-043.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-046.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-047.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-048.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-050.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-052.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-053.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-054.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-056.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-057.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-063.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-065.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-067.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-068.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-070.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-072.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-073.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-075.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-076.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-077.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-080.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-081.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-082.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-083.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-085.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-086.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-089.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-090.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-091.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-096.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-097.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-099.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-100.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-103.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-105.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-109.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-113.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-122.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-123.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-126.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-127.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-129.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-131.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-132.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-135.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-136.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-138.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-141.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-143.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-144.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-145.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-146.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-147.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-149.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-150.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-152.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-153.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-155.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-158.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-attr-case-001.html.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/content-white-space-002.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/counters-hidden-002.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/counters-multi-000.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/counters-multi-001.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/generated-content/counters-order-000.xht.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/visudet/line-height-204.html.ini2
-rw-r--r--tests/wpt/metadata/css/CSS2/visudet/line-height-205.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-animations/animation-delay-011.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-backgrounds/background-color-body-propagation-003.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-backgrounds/background-image-none-gradient-repaint.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-backgrounds/border-radius-011.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-backgrounds/box-shadow-syntax-001.xht.ini2
-rw-r--r--tests/wpt/metadata/css/css-block/quotes-applies-to-011.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-abspos-between-001.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-abspos-between-002.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-basic-001.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-basic-002.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-basic-003.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-basic-004.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-basic-005.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-basic-006.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-basic-007.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-basic-008.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-basic-009.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-basic-010.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-basic-011.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-basic-012.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-basic-013.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-basic-018.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-block-between-003.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-breaking-001.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-breaking-002.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-clear-001.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-clear-002.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-contains-abspos-001.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-contains-block-003.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-contains-block-005.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-contains-block-inside-inline-003.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-contains-float-001.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-contains-inline-001.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-contains-inline-002.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-contains-inline-003.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-contains-inline-004.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-contains-inline-005.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-contains-inline-006.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-contains-inline-007.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-contains-inline-block-001.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-contains-inline-table-001.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-contains-relpos-block-003.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-contains-run-in-003.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-contains-table-003.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-contains-table-caption-001.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-contains-table-cell-001.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-contains-table-column-001.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-contains-table-column-group-001.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-contains-table-inside-inline-003.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-contains-table-row-001.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-contains-table-row-group-001.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-display-none-between-001.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-display-none-between-002.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-fixedpos-between-001.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-fixedpos-between-002.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-float-between-001.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-float-between-002.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-inherit-001.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-inline-between-003.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-inline-block-between-003.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-inline-table-between-003.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-listitem-between-001.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-listitem-between-002.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-listitem-between-003.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-relpos-between-003.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-replaced-001.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-restyle-003.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-run-in-between-003.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-run-in-between-004.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-run-in-between-005.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-run-in-between-006.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-run-in-between-007.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-table-between-003.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-table-cell-between-003.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-table-row-between-003.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-text-between-004.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-block/run-in-text-between-005.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-color/color-001.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-color/color-003.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-color/currentcolor-001.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-color/currentcolor-002.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-color/hex-001.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-color/hex-002.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-flexbox/anonymous-flex-item-001.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-flexbox/anonymous-flex-item-003.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-flexbox/anonymous-flex-item-005.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-flexbox/anonymous-flex-item-006.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-flexbox/percentage-heights-004.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-flexbox/table-as-item-narrow-content.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-flexbox/table-as-item-wide-content.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-multicol/multicol-count-computed-001.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-multicol/multicol-count-computed-002.xht.ini2
-rw-r--r--tests/wpt/metadata/css/css-multicol/multicol-count-large-001.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-multicol/multicol-count-large-002.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-multicol/multicol-fill-auto.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-multicol/multicol-inherit-004.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-multicol/multicol-rule-style-groove-001.xht.ini2
-rw-r--r--tests/wpt/metadata/css/css-multicol/multicol-rule-style-inset-001.xht.ini2
-rw-r--r--tests/wpt/metadata/css/css-multicol/multicol-rule-style-outset-001.xht.ini2
-rw-r--r--tests/wpt/metadata/css/css-multicol/multicol-rule-style-ridge-001.xht.ini2
-rw-r--r--tests/wpt/metadata/css/css-multicol/multicol-span-all-child-001.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-multicol/multicol-span-all-child-002.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-multicol/multicol-span-all-margin-nested-003.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-multicol/multicol-width-ems-001.xht.ini3
-rw-r--r--tests/wpt/metadata/css/css-style-attr/style-attr-urls-003.xht.ini2
-rw-r--r--tests/wpt/metadata/css/css-text-decor/text-decoration-color.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-text-decor/text-decoration-line-012.xht.ini4
-rw-r--r--tests/wpt/metadata/css/css-text-decor/text-decoration-serialization.tentative.html.ini4
-rw-r--r--tests/wpt/metadata/css/css-transforms/transform-box/fill-box-mutation.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-transforms/transform-box/fill-box.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-transforms/transform-box/value-changed.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-transforms/transform-box/view-box-nested.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-transforms/transform-box/view-box-viewbox-nested.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-transforms/transform-box/view-box-viewbox.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-transforms/transform-box/view-box.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-ui/outline-014.html.ini1
-rw-r--r--tests/wpt/metadata/css/css-values/vh_not_refreshing_on_chrome.html.ini2
-rw-r--r--tests/wpt/metadata/css/cssom-view/scroll-behavior-smooth.html.ini5
-rw-r--r--tests/wpt/metadata/css/cssom/getComputedStyle-pseudo.html.ini3
-rw-r--r--tests/wpt/metadata/css/cssom/medialist-dynamic-001.html.ini2
-rw-r--r--tests/wpt/metadata/css/mediaqueries/test_media_queries.html.ini411
-rw-r--r--tests/wpt/metadata/css/selectors/any-link-dynamic-001.html.ini2
-rw-r--r--tests/wpt/metadata/css/selectors/invalidation/any-link-pseudo.html.ini4
-rw-r--r--tests/wpt/metadata/custom-elements/microtasks-and-constructors.html.ini1
-rw-r--r--tests/wpt/metadata/custom-elements/parser/parser-fallsback-to-unknown-element.html.ini1
-rw-r--r--tests/wpt/metadata/custom-elements/parser/parser-uses-registry-of-owner-document.html.ini6
-rw-r--r--tests/wpt/metadata/dom/events/Event-subclasses-constructors.html.ini18
-rw-r--r--tests/wpt/metadata/dom/events/EventListener-invoke-legacy.html.ini3
-rw-r--r--tests/wpt/metadata/fetch/api/redirect/redirect-method-worker.html.ini6
-rw-r--r--tests/wpt/metadata/fetch/api/redirect/redirect-method.html.ini6
-rw-r--r--tests/wpt/metadata/fetch/api/request/destination/fetch-destination.https.html.ini4
-rw-r--r--tests/wpt/metadata/fetch/api/request/request-keepalive-quota.html.ini3
-rw-r--r--tests/wpt/metadata/fetch/http-cache/partial.html.ini1
-rw-r--r--tests/wpt/metadata/hr-time/idlharness.html.ini6
-rw-r--r--tests/wpt/metadata/hr-time/performance-tojson.html.ini4
-rw-r--r--tests/wpt/metadata/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload.tentative.html.ini3
-rw-r--r--tests/wpt/metadata/html/browsers/the-window-object/window-properties.html.ini1
-rw-r--r--tests/wpt/metadata/html/dom/interfaces.html.ini15
-rw-r--r--tests/wpt/metadata/html/dom/reflection-misc.html.ini336
-rw-r--r--tests/wpt/metadata/html/dom/usvstring-reflection.html.ini19
-rw-r--r--tests/wpt/metadata/html/form-elements/the-textarea-element/multiline-placeholder-cr.html.ini2
-rw-r--r--tests/wpt/metadata/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/crossOrigin.html.ini31
-rw-r--r--tests/wpt/metadata/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/readyState.html.ini3
-rw-r--r--tests/wpt/metadata/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/constructor.html.ini7
-rw-r--r--tests/wpt/metadata/html/semantics/forms/the-input-element/date.html.ini1
-rw-r--r--tests/wpt/metadata/html/semantics/forms/the-input-element/datetime-local.html.ini1
-rw-r--r--tests/wpt/metadata/html/semantics/forms/the-input-element/month.html.ini1
-rw-r--r--tests/wpt/metadata/html/semantics/forms/the-input-element/type-change-state.html.ini1
-rw-r--r--tests/wpt/metadata/html/semantics/forms/the-select-element/select-add.html.ini7
-rw-r--r--tests/wpt/metadata/html/semantics/interactive-elements/the-dialog-element/abspos-dialog-layout.html.ini43
-rw-r--r--tests/wpt/metadata/html/semantics/interactive-elements/the-dialog-element/dialog-scrolled-viewport.html.ini4
-rw-r--r--tests/wpt/metadata/html/semantics/interactive-elements/the-dialog-element/inert-does-not-match-disabled-selector.html.ini4
-rw-r--r--tests/wpt/metadata/html/semantics/interactive-elements/the-dialog-element/inert-node-is-unfocusable.html.ini4
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/choice-of-error-1.html.ini4
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/choice-of-error-2.html.ini4
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/choice-of-error-3.html.ini4
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-classic.html.ini5
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-classic.html.ini4
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-module.html.ini2
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-classic.html.ini4
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-module.html.ini2
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-module.html.ini3
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-integrity-classic.html.ini2
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-integrity-module.html.ini2
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-classic.html.ini20
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-module.html.ini2
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/error-type-1.html.ini4
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/error-type-2.html.ini4
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/error-type-3.html.ini4
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/instantiation-error-1.html.ini3
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/instantiation-error-2.html.ini3
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/instantiation-error-3.html.ini3
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/instantiation-error-4.html.ini3
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/instantiation-error-5.html.ini3
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/referrer-no-referrer.sub.html.ini2
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/referrer-origin-when-cross-origin.sub.html.ini2
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/referrer-origin.sub.html.ini2
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/referrer-same-origin.sub.html.ini2
-rw-r--r--tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/referrer-unsafe-url.sub.html.ini2
-rw-r--r--tests/wpt/metadata/html/semantics/text-level-semantics/the-a-element/a-download-click-404.html.ini4
-rw-r--r--tests/wpt/metadata/html/semantics/text-level-semantics/the-a-element/a-download-click.html.ini4
-rw-r--r--tests/wpt/metadata/html/semantics/text-level-semantics/the-ruby-element/ruby-usage.html.ini2
-rw-r--r--tests/wpt/metadata/mozilla-sync4
-rw-r--r--tests/wpt/metadata/navigation-timing/idlharness.html.ini3
-rw-r--r--tests/wpt/metadata/performance-timeline/performanceentry-tojson.html.ini4
-rw-r--r--tests/wpt/metadata/quirks-mode/hashless-hex-color.html.ini47
-rw-r--r--tests/wpt/metadata/quirks/blocks-ignore-line-height.html.ini (renamed from tests/wpt/metadata/quirks-mode/blocks-ignore-line-height.html.ini)0
-rw-r--r--tests/wpt/metadata/quirks/line-height-calculation.html.ini (renamed from tests/wpt/metadata/quirks-mode/line-height-calculation.html.ini)0
-rw-r--r--tests/wpt/metadata/quirks/percentage-height-calculation.html.ini (renamed from tests/wpt/metadata/quirks-mode/percentage-height-calculation.html.ini)0
-rw-r--r--tests/wpt/metadata/quirks/supports.html.ini (renamed from tests/wpt/metadata/quirks-mode/supports.html.ini)0
-rw-r--r--tests/wpt/metadata/quirks/table-cell-nowrap-minimum-width-calculation.html.ini (renamed from tests/wpt/metadata/quirks-mode/table-cell-nowrap-minimum-width-calculation.html.ini)0
-rw-r--r--tests/wpt/metadata/quirks/table-cell-width-calculation.html.ini (renamed from tests/wpt/metadata/quirks-mode/table-cell-width-calculation.html.ini)0
-rw-r--r--tests/wpt/metadata/quirks/unitless-length.html.ini (renamed from tests/wpt/metadata/quirks-mode/unitless-length.html.ini)0
-rw-r--r--tests/wpt/metadata/url/a-element-xhtml.xhtml.ini24
-rw-r--r--tests/wpt/metadata/url/a-element.html.ini24
-rw-r--r--tests/wpt/metadata/url/url-constructor.html.ini24
-rw-r--r--tests/wpt/metadata/url/url-setters.html.ini45
-rw-r--r--tests/wpt/metadata/workers/SharedWorker_dataUrl.html.ini8
-rw-r--r--tests/wpt/metadata/workers/data-url-shared.html.ini3
-rw-r--r--tests/wpt/mozilla/meta/MANIFEST.json2
-rw-r--r--tests/wpt/mozilla/meta/webgl/conformance-1.0.3/conformance/glsl/bugs/long-expressions-should-not-crash.html.ini1
-rw-r--r--tests/wpt/mozilla/tests/lint.whitelist4
-rw-r--r--tests/wpt/web-platform-tests/.travis.yml4
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.invalidcolour.html9
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/imagebitmap/createImageBitmap-invalid-args.html48
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/tools/tests2d.yaml9
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/blob/Blob-Request-revoke-fetch.html41
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/blob/Blob-constructor-endings.html104
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/blob/Blob-constructor.html64
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/file/File-constructor-endings.html104
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/file/File-constructor.html116
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/file/send-file-form-iso-2022-jp.tentative.html71
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/file/send-file-form-utf-8.html61
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/file/send-file-form-windows-1252.tentative.html70
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/file/send-file-form-x-user-defined.tentative.html70
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/file/send-file-form.html25
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/idlharness.html2
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/support/send-file-form-helper.js249
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/unicode.html46
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/url/url_xmlhttprequest_img.html3
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/interfaces.html2
-rw-r--r--tests/wpt/web-platform-tests/README.md22
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures.worker.js5
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_AES-CBC.https.worker.js (renamed from tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_AES-CBC.worker.js)0
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_AES-CTR.https.worker.js (renamed from tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_AES-CTR.worker.js)0
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_AES-GCM.https.worker.js (renamed from tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_AES-GCM.worker.js)0
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_AES-KW.https.worker.js (renamed from tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_AES-KW.worker.js)0
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_ECDH.https.worker.js (renamed from tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_ECDH.worker.js)0
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_ECDSA.https.worker.js (renamed from tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_ECDSA.worker.js)0
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_HMAC.https.worker.js (renamed from tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_HMAC.worker.js)0
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_RSA-OAEP.https.worker.js (renamed from tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_RSA-OAEP.worker.js)0
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_RSA-PSS.https.worker.js (renamed from tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_RSA-PSS.worker.js)0
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_RSASSA-PKCS1-v1_5.https.worker.js (renamed from tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_RSASSA-PKCS1-v1_5.worker.js)0
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes.worker.js6
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_AES-CBC.https.worker.js (renamed from tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_AES-CBC.worker.js)0
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_AES-CTR.https.worker.js (renamed from tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_AES-CTR.worker.js)0
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_AES-GCM.https.worker.js (renamed from tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_AES-GCM.worker.js)0
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_AES-KW.https.worker.js (renamed from tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_AES-KW.worker.js)0
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_ECDH.https.worker.js (renamed from tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_ECDH.worker.js)0
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_ECDSA.https.worker.js (renamed from tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_ECDSA.worker.js)0
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_HMAC.https.worker.js (renamed from tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_HMAC.worker.js)0
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_RSA-OAEP.https.worker.js (renamed from tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_RSA-OAEP.worker.js)0
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_RSA-PSS.https.worker.js (renamed from tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_RSA-PSS.worker.js)0
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.https.worker.js (renamed from tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.worker.js)0
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/test_failures.https.html18
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/test_successes_RSA-OAEP.https.html4
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/idlharness.html5
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/idlharness.https.html5
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/tools/generate.py8
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/no-regexp-special-casing.any.js47
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-network-error-sync-events.sub.htm10
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-post-upload.htm32
-rw-r--r--tests/wpt/web-platform-tests/accelerometer/Accelerometer-disabled-by-feature-policy.https.html14
-rw-r--r--tests/wpt/web-platform-tests/accelerometer/Accelerometer-disabled-by-feature-policy.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/accelerometer/Accelerometer-enabled-by-feature-policy-attribute-redirect-on-load.https.html14
-rw-r--r--tests/wpt/web-platform-tests/accelerometer/Accelerometer-enabled-by-feature-policy-attribute.https.html14
-rw-r--r--tests/wpt/web-platform-tests/accelerometer/Accelerometer-enabled-by-feature-policy.https.html14
-rw-r--r--tests/wpt/web-platform-tests/accelerometer/Accelerometer-enabled-by-feature-policy.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/accelerometer/Accelerometer-enabled-on-self-origin-by-feature-policy.https.html14
-rw-r--r--tests/wpt/web-platform-tests/accelerometer/Accelerometer-enabled-on-self-origin-by-feature-policy.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/accelerometer/Accelerometer.https.html1
-rw-r--r--tests/wpt/web-platform-tests/accelerometer/Accelerometer_insecure_context.html1
-rw-r--r--tests/wpt/web-platform-tests/accelerometer/Accelerometer_onerror-manual.https.html1
-rw-r--r--tests/wpt/web-platform-tests/acid/acid3/test.html10
-rw-r--r--tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-disabled-by-feature-policy.https.html12
-rw-r--r--tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-disabled-by-feature-policy.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html12
-rw-r--r--tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-enabled-by-feature-policy-attribute.https.html12
-rw-r--r--tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-enabled-by-feature-policy.https.html12
-rw-r--r--tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-enabled-by-feature-policy.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-enabled-on-self-origin-by-feature-policy.https.html12
-rw-r--r--tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-enabled-on-self-origin-by-feature-policy.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/beacon/OWNERS2
-rw-r--r--tests/wpt/web-platform-tests/bluetooth/README.md12
-rw-r--r--tests/wpt/web-platform-tests/bluetooth/idl/idl-Bluetooth.html (renamed from tests/wpt/web-platform-tests/bluetooth/idl-Bluetooth.html)0
-rw-r--r--tests/wpt/web-platform-tests/bluetooth/idl/idl-BluetoothUUID.html166
-rw-r--r--tests/wpt/web-platform-tests/bluetooth/idl/idl-NavigatorBluetooth.html15
-rw-r--r--tests/wpt/web-platform-tests/bluetooth/resources/bluetooth-helpers.js800
-rw-r--r--tests/wpt/web-platform-tests/common/media.js11
-rw-r--r--tests/wpt/web-platform-tests/common/performance-timeline-utils.js6
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/ariatree.html6
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/ariatree2.html6
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/673.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/674.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/675.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/676.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/677.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/678.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/679.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/680.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/681.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/682.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/683.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/684.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/685.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/686.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/687.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/688.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/689.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/690.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/691.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/692.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/693.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/694.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/695.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/696.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/697.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/698.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/699.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/700.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/701.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/702.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/703.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/704.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/705.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/706.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/707.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/708.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/709.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/710.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/711.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/712.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/713.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/714.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/715.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/716.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/717.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/718.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/719.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/720.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/567.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/568.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/571-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/572-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/573-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/580.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-1.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-2.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-3.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-4.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-5.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-6.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/659.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/660.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/661.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/662.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/663.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-listbox-parent-combobox.html6
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/670.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/671.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/672.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/setsize-posinset-level/setsize-posinset-level-1.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/stability-of-dom/669.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-A.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-B.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-C.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-multiselectable-D.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-tree-multiselectable-C.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue4html.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue5html.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue6html.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue7html.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/animate-elem-33-t-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/animate-elem-90-b-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/animate-elem-91-t-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/filters-turb-02-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/fonts-elem-03-b-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/fonts-elem-04-b-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/fonts-elem-07-b-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/interact-pevents-10-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/interact-pointer-04-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/masking-mask-01-b-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/masking-path-12-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/painting-marker-03-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/painting-marker-05-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/painting-marker-properties-01-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/pservers-grad-08-b-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/render-elems-06-t-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/render-elems-07-t-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/render-elems-08-t-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/render-groups-01-b-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/render-groups-03-t-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-dom-13-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-dom-16-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-dom-17-f-novalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-dom-18-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-dom-19-f-novalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-svg-01-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-svg-02-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-use-10-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-use-11-f-novalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-use-14-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-use-15-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-class-01-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-01-b-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-02-b-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-03-b-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-04-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-05-b-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-06-b-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-08-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-09-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-10-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-pres-04-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-pres-05-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-align-08-b-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-dom-02-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-dom-05-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-fonts-204-t-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-intro-06-t-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-intro-09-b-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-intro-12-t-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-path-02-b-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-text-04-t-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-text-05-t-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-text-06-t-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-text-12-t-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-tselect-03-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/types-dom-svgfittoviewbox-01-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/types-dom-svglengthlist-01-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/types-dom-svgnumberlist-01-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/types-dom-svgstringlist-01-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-svg/types-dom-svgtransformable-01-f-isvalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/html-spec-comms-isvalid.html276
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/model-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/type-novalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/index.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/messages.json1
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/base-uri/report-uri-does-not-respect-base-uri.sub.html27
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/base-uri/report-uri-does-not-respect-base-uri.sub.html.sub.headers5
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/generic/policy-inherited-correctly-by-plznavigate.html39
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/generic/policy-inherited-correctly-by-plznavigate.html.sub.headers5
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/inheritance/inherited-csp-list-modifications-are-local.html49
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/nonce-hiding/script-nonces-hidden.tentative.html40
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/reporting/securitypolicyviolation-idl.html80
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/script-src/nonce-enforce-blocked.html63
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/securitypolicyviolation/idl.html3
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-imported-style-blocked.html7
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/support/fail.html3
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/support/nonce-should-be-blocked.js1
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/svg/including.sub.svg3
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/OWNERS2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/README.md2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/cookieStore_delete_arguments.tentative.window.js171
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/cookieStore_getAll_arguments.tentative.window.js119
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/cookieStore_getAll_set_basic.tentative.window.js22
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/cookieStore_get_arguments.tentative.window.js86
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/cookieStore_get_delete_basic.tentative.window.js20
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/cookieStore_get_set_basic.tentative.window.js21
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/cookieStore_has_arguments.tentative.window.js92
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/cookieStore_has_basic.tentative.window.js25
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/cookieStore_in_detached_frame.tentative.html19
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/cookieStore_set_arguments.tentative.window.js215
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/cookieStore_special_names.tentative.html35
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/cookie_store_tests.tentative.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/cookie_store_tests.tentative.https.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/cookie_store_tests_static.tentative.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/cookie_store_tests_static.tentative.https.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/delete_cookies.tentative.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/delete_cookies.tentative.https.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/delete_cookies_static.tentative.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/delete_cookies_static.tentative.https.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/document_cookie.tentative.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/document_cookie.tentative.https.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/document_cookie_static.tentative.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/document_cookie_static.tentative.https.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/document_getAll_multiple.tentative.html41
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/expiration.tentative.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/expiration.tentative.https.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/expiration_static.tentative.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/expiration_static.tentative.https.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/get_set_get_all.tentative.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/get_set_get_all.tentative.https.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/get_set_get_all_static.tentative.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/get_set_get_all_static.tentative.https.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/http_cookie_and_set_cookie_headers.tentative.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/http_cookie_and_set_cookie_headers.tentative.https.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie.tentative.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie.tentative.https.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie_static.tentative.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie_static.tentative.https.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value.tentative.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value.tentative.https.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value_static.tentative.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value_static.tentative.https.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value.tentative.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value.tentative.https.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value_static.tentative.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value_static.tentative.https.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values.tentative.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values.tentative.https.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values_static.tentative.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values_static.tentative.https.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/observation.tentative.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/observation.tentative.https.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/observation_static.tentative.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/observation_static.tentative.https.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie.tentative.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie.tentative.https.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie_static.tentative.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie_static.tentative.https.html2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/resources/cookie-store-tests.js101
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/resources/testharness-helpers.js2
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_arguments.js14
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_arguments.tentative.https.html22
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_basic.js13
-rw-r--r--tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_basic.tentative.https.html22
-rw-r--r--tests/wpt/web-platform-tests/cookies/OWNERS2
-rw-r--r--tests/wpt/web-platform-tests/cookies/README.md2
-rw-r--r--tests/wpt/web-platform-tests/cookies/meta-blocked.html13
-rw-r--r--tests/wpt/web-platform-tests/cookies/path/echo-cookie.html24
-rw-r--r--tests/wpt/web-platform-tests/cookies/path/match.html24
-rw-r--r--tests/wpt/web-platform-tests/cookies/resources/echo-cookie.html24
-rw-r--r--tests/wpt/web-platform-tests/cookies/secure/set-from-ws.sub.html (renamed from tests/wpt/web-platform-tests/cookies/secure/set-from-ws.https.sub.html)0
-rw-r--r--tests/wpt/web-platform-tests/core-aam/aria-checked_value_changes-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/core-aam/aria-expanded_value_changes-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/core-aam/aria-flowto-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/core-aam/aria-owns_may_need_manual_verification-manual.html10
-rw-r--r--tests/wpt/web-platform-tests/core-aam/aria-roledescription_is_empty_or_whitespace_characters_new-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/core-aam/aria-valuenow_value_changes-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/core-aam/progressbar-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/core-aam/region_without_an_accessible_name_new-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/core-aam/scrollbar-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/core-aam/slider-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/core-aam/spinbutton-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/credential-management/credentialscontainer-create-basics.https.html29
-rw-r--r--tests/wpt/web-platform-tests/credential-management/federatedcredential-framed-get.sub.https.html74
-rw-r--r--tests/wpt/web-platform-tests/credential-management/passwordcredential-framed-get.sub.https.html74
-rw-r--r--tests/wpt/web-platform-tests/credential-management/support/echoing-nester.html16
-rw-r--r--tests/wpt/web-platform-tests/credential-management/support/federatedcredential-get.html17
-rw-r--r--tests/wpt/web-platform-tests/credential-management/support/passwordcredential-get.html17
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/backgrounds/background-color-030.xht4
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/backgrounds/background-color-174.xht4
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/backgrounds/background-image-002.xht4
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/colors/color-083-ref.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/fonts/font-148-ref.xht25
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/fonts/font-148.xht24
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/after-inheritable-001-ref.html14
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/after-inheritable-001.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/after-inheritable-002-ref.html17
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/after-inheritable-002.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/after-location-001-ref.html7
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/after-location-001.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/before-after-002.xht5
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/before-inheritable-001.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/before-inheritable-002.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/before-location-001-ref.html7
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/before-location-001.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/bidi-generated-content-001-ref.html8
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/bidi-generated-content-001.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/bidi-generated-content-002-ref.html8
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/bidi-generated-content-002.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-001-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-001.xht4
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-002.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-003-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-003.xht4
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-004.xht5
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-005-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-005.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-006-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-006.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-007-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-007.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-009.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-010-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-010.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-011-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-011.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-012-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-012.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-013-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-013.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-014-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-014.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-015-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-015.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-016-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-016.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-017-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-017.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-018.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-019.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-020.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-021-ref.html12
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-021.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-022-ref.html12
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-022.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-023-ref.html12
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-023.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-025.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-026-ref.html12
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-026.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-027-ref.html12
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-027.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-028-ref.html12
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-028.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-029-ref.html12
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-029.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-030-ref.html12
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-030.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-031-ref.html12
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-031.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-032-ref.html12
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-032.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-033-ref.html12
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-033.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-034.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-035.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-036.xht5
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-037-ref.html17
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-037.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-038.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-039.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-040-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-040.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-041-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-041.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-042-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-042.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-043-ref.html12
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-043.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-046.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-047-ref.html18
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-047.xht12
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-048-ref.html15
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-048.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-050-ref.html20
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-050.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-052-ref.html17
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-052.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-053-ref.html17
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-053.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-054.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-056.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-057.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-063-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-063.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-065.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-067.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-068-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-068.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-070-ref.html14
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-070.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-072-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-072.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-073-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-073.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-075-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-075.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-076.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-077.xht5
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-080-ref.html17
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-080.xht5
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-081-ref.html17
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-081.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-082-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-082.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-083-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-083.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-085.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-086.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-089-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-089.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-090-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-090.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-091-ref.html12
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-091.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-096-ref.html18
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-096.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-097-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-097.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-099.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-100-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-100.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-103-ref.html17
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-103.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-105.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-109.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-113-ref.html12
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-113.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-122.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-123.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-126-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-126.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-127.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-129.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-131.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-132-ref.html17
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-132.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-135-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-135.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-136-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-136.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-138.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-141-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-141.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-143-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-143.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-144-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-144.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-145.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-146.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-147-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-147.xht5
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-149-ref.html17
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-149.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-150-ref.html16
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-150.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-152.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-153.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-155-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-155.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-156-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-156.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-157.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-158-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-158.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-159-ref.html12
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-159.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-attr-001.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-attr-case-001.html2
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-attr-case-002.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-auto-reset-001-ref.html7
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-auto-reset-001.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-newline-001-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-newline-001.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-001-ref.html17
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-001.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-002-ref.html23
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-002.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-003-ref.html16
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-003.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-004-ref.html17
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-004.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-hidden-000-ref.html8
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-hidden-000.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-hidden-001.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-hidden-002-ref.html8
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-hidden-002.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-multi-000-ref.html8
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-multi-000.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-multi-001.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-order-000-ref.html8
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-order-000.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-root-000-ref.html8
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-root-000.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/linebox/line-height-oof-descendants-001-ref.html14
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/linebox/line-height-oof-descendants-001.html17
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/values/numbers-units-011.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/visudet/content-height-001.html22
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/visudet/content-height-002.html42
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/visudet/content-height-003.html42
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/visudet/content-height-004.html50
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/visudet/content-height-005.html41
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/visudet/line-height-201.html55
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/visudet/line-height-202.html56
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/visudet/line-height-203.html52
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/visudet/line-height-204.html60
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/visudet/line-height-205.html53
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/visudet/line-height-206.html46
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/visudet/reference/content-height-001-ref.html16
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/visudet/reference/content-height-002-ref.html35
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/visudet/reference/content-height-003-ref.html35
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/visudet/reference/content-height-004-ref.html34
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/visudet/reference/content-height-005-ref.html22
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/visudet/reference/line-height-201-ref.html16
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/visudet/reference/line-height-202-ref.html6
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/visudet/reference/line-height-203-ref.html6
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/visudet/reference/line-height-206-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/visudet/support/1x1-green.pngbin0 -> 135 bytes
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/visudet/support/AD.woffbin0 -> 15368 bytes
-rw-r--r--tests/wpt/web-platform-tests/css/CSS2/visudet/support/Revalia.woffbin0 -> 15588 bytes
-rw-r--r--tests/wpt/web-platform-tests/css/OWNERS2
-rw-r--r--tests/wpt/web-platform-tests/css/README.md23
-rw-r--r--tests/wpt/web-platform-tests/css/compositing/mix-blend-mode/mix-blend-mode-transition.html37
-rw-r--r--tests/wpt/web-platform-tests/css/compositing/mix-blend-mode/reference/mix-blend-mode-transition-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/css/css-animations/animation-delay-011.html24
-rw-r--r--tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-001.html16
-rw-r--r--tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-002.html19
-rw-r--r--tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-003.html11
-rw-r--r--tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-ref.html6
-rw-r--r--tests/wpt/web-platform-tests/css/css-backgrounds/background-image-none-gradient-repaint.html29
-rw-r--r--tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-001-ref.xht26
-rw-r--r--tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-001.xht66
-rw-r--r--tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-002-ref.xht36
-rw-r--r--tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-002.xht68
-rw-r--r--tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-003-ref.xht36
-rw-r--r--tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-003.xht68
-rw-r--r--tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-004-ref.xht35
-rw-r--r--tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-004.xht67
-rw-r--r--tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-005-ref.xht35
-rw-r--r--tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-005.xht66
-rw-r--r--tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-006-ref.xht36
-rw-r--r--tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-006.xht68
-rw-r--r--tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-007-ref.xht36
-rw-r--r--tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-007.xht68
-rw-r--r--tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-008.xht68
-rw-r--r--tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-009-ref.xht35
-rw-r--r--tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-009.xht73
-rw-r--r--tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-010-ref.xht35
-rw-r--r--tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-010.xht77
-rw-r--r--tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-011-ref.xht33
-rw-r--r--tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-011.xht56
-rw-r--r--tests/wpt/web-platform-tests/css/css-block/counter-increment-applies-to-011.xht27
-rw-r--r--tests/wpt/web-platform-tests/css/css-block/counter-reset-applies-to-011.xht27
-rw-r--r--tests/wpt/web-platform-tests/css/css-block/font-style-applies-to-004.xht24
-rw-r--r--tests/wpt/web-platform-tests/css/css-block/font-variant-applies-to-004.xht28
-rw-r--r--tests/wpt/web-platform-tests/css/css-block/font-weight-applies-to-004.xht28
-rw-r--r--tests/wpt/web-platform-tests/css/css-block/height-applies-to-011.xht25
-rw-r--r--tests/wpt/web-platform-tests/css/css-block/letter-spacing-applies-to-004.xht36
-rw-r--r--tests/wpt/web-platform-tests/css/css-block/list-style-applies-to-011.xht30
-rw-r--r--tests/wpt/web-platform-tests/css/css-block/list-style-type-applies-to-011.xht30
-rw-r--r--tests/wpt/web-platform-tests/css/css-block/max-height-applies-to-011.xht26
-rw-r--r--tests/wpt/web-platform-tests/css/css-block/max-width-applies-to-011.xht26
-rw-r--r--tests/wpt/web-platform-tests/css/css-block/min-height-applies-to-011.xht25
-rw-r--r--tests/wpt/web-platform-tests/css/css-block/min-width-applies-to-011.xht31
-rw-r--r--tests/wpt/web-platform-tests/css/css-block/quotes-applies-to-011.xht27
-rw-r--r--tests/wpt/web-platform-tests/css/css-block/text-decoration-applies-to-004.xht23
-rw-r--r--tests/wpt/web-platform-tests/css/css-block/text-transform-applies-to-004.xht23
-rw-r--r--tests/wpt/web-platform-tests/css/css-block/width-applies-to-011.xht25
-rw-r--r--tests/wpt/web-platform-tests/css/css-break/OWNERS1
-rw-r--r--tests/wpt/web-platform-tests/css/css-break/break-before-always-001.xht2
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/blacktext-ref.html2
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/color-001.html2
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/color-002.html2
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/color-003.html4
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/color-resolving-hsl.html80
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/color-resolving-keywords.html205
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/color-resolving.html180
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/currentcolor-001.html6
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/currentcolor-002.html8
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/greensquare-ref.html10
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/hex-001.html2
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/hex-002.html2
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/hex-003-ref.html9
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/hex-003.html4
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/hex-004.html4
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/hsl-001.html13
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/hsl-002.html13
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/hsl-003.html13
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/hsl-004.html13
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/hsl-005.html13
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/hsl-006.html13
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/hsl-007.html13
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/hsl-008.html13
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/hsla-001.html13
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/hsla-002.html13
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/hsla-003.html13
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/hsla-004.html13
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/hsla-005.html13
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/hsla-006.html13
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/hsla-007.html13
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/hsla-008.html13
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/lab-001.html4
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/lab-002.html4
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/lab-003.html6
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/lab-004.html8
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/lab-005.html8
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/lab-006.html8
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/lab-007.html8
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/lch-001.html4
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/lch-002.html4
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/lch-003.html6
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/lch-004.html8
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/lch-005.html8
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/lch-006.html8
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/lch-007.html8
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/named-001.html4
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/rebeccapurple-ref.html2
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t32-opacity-basic-0.0-a-ref.html6
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t32-opacity-basic-0.0-a.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t32-opacity-basic-1.0-a-ref.html7
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t32-opacity-basic-1.0-a.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t32-opacity-clamping-0.0-b.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t32-opacity-clamping-1.0-b-ref.html11
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t32-opacity-clamping-1.0-b.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t32-opacity-offscreen-b-ref.html16
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t32-opacity-offscreen-b.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t32-opacity-offscreen-with-alpha-c-ref.html15
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t32-opacity-offscreen-with-alpha-c.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t41-html4-keywords-a-ref.html32
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t41-html4-keywords-a.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t421-rgb-clip-outside-gamut-b-ref.html42
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t421-rgb-clip-outside-gamut-b.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t421-rgb-hex3-expand-b-ref.html24
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t421-rgb-values-meaning-b-ref.html1539
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t421-rgb-values-meaning-b.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t422-rgba-a0.0-a.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t422-rgba-values-meaning-b-ref.html432
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t422-rgba-values-meaning-b.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t424-hsl-h-rotating-b-ref.html62
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t424-hsl-h-rotating-b.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t425-hsla-h-rotating-b-ref.html63
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t425-hsla-h-rotating-b.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t425-hsla-onscreen-b.xht3
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t43-svg-keywords-a-ref.html165
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/t43-svg-keywords-a.xht1
-rw-r--r--tests/wpt/web-platform-tests/css/css-color/whitetext-ref.html2
-rw-r--r--tests/wpt/web-platform-tests/css/css-conditional/test_group_insertRule.html21
-rw-r--r--tests/wpt/web-platform-tests/css/css-contain/contain-style-counters-ref.html4
-rw-r--r--tests/wpt/web-platform-tests/css/css-contain/contain-style-counters.html22
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/display-contents-before-after-003.html17
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/display-contents-button.html15
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/display-contents-details.html15
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/display-contents-dynamic-pseudo-insertion-001-ref.html5
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/display-contents-dynamic-pseudo-insertion-001.html26
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/display-contents-fieldset.html15
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/display-contents-first-letter-002.html14
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/display-contents-first-line-002.html16
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/display-contents-line-height-ref.html9
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/display-contents-line-height.html14
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/display-contents-replaced-001-ref.html17
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/display-contents-replaced-001.html19
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/display-contents-svg-elements-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/display-contents-svg-elements.html22
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/display-contents-text-inherit-ref.html7
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/display-contents-text-inherit.html15
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/display-contents-unusual-html-elements-none.html31
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/OWNERS (renamed from tests/wpt/web-platform-tests/css/css-block/OWNERS)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/after-content-display-004.xht (renamed from tests/wpt/web-platform-tests/css/css-block/after-content-display-004.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/anonymous-box-generation-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/anonymous-box-generation-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/background-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/background-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/background-attachment-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/background-attachment-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/background-color-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/background-color-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/background-image-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/background-image-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/background-position-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/background-position-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/background-repeat-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/background-repeat-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/before-content-display-004.xht (renamed from tests/wpt/web-platform-tests/css/css-block/before-content-display-004.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/border-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/border-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/border-bottom-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/border-bottom-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/border-bottom-color-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/border-bottom-color-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/border-bottom-style-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/border-bottom-style-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/border-bottom-width-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/border-bottom-width-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/border-collapse-applies-to-004.xht (renamed from tests/wpt/web-platform-tests/css/css-block/border-collapse-applies-to-004.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/border-color-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/border-color-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/border-left-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/border-left-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/border-left-color-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/border-left-color-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/border-left-style-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/border-left-style-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/border-left-width-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/border-left-width-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/border-right-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/border-right-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/border-right-color-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/border-right-color-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/border-right-style-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/border-right-style-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/border-right-width-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/border-right-width-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/border-spacing-applies-to-004.xht (renamed from tests/wpt/web-platform-tests/css/css-block/border-spacing-applies-to-004.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/border-style-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/border-style-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/border-top-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/border-top-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/border-top-color-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/border-top-color-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/border-top-style-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/border-top-style-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/border-top-width-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/border-top-width-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/border-width-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/border-width-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/bottom-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/bottom-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/caption-side-applies-to-004.xht (renamed from tests/wpt/web-platform-tests/css/css-block/caption-side-applies-to-004.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/clear-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/clear-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/clear-runin-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/clear-runin-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/color-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/color-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/counter-increment-applies-to-011.xht27
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/counter-reset-applies-to-011.xht27
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/cursor-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/cursor-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/direction-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/direction-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/display-004.xht (renamed from tests/wpt/web-platform-tests/css/css-block/display-004.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/empty-cells-applies-to-004.xht (renamed from tests/wpt/web-platform-tests/css/css-block/empty-cells-applies-to-004.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/first-line-pseudo-009.xht (renamed from tests/wpt/web-platform-tests/css/css-block/first-line-pseudo-009.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/float-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/float-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/font-applies-to-004.xht (renamed from tests/wpt/web-platform-tests/css/css-block/font-applies-to-004.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/font-family-applies-to-004.xht (renamed from tests/wpt/web-platform-tests/css/css-block/font-family-applies-to-004.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/font-size-applies-to-004.xht (renamed from tests/wpt/web-platform-tests/css/css-block/font-size-applies-to-004.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/font-style-applies-to-004.xht24
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/font-variant-applies-to-004.xht28
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/font-weight-applies-to-004.xht28
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/height-applies-to-011.xht25
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/left-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/left-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/letter-spacing-applies-to-004.xht36
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/line-height-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/line-height-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/list-style-applies-to-011.xht30
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/list-style-image-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/list-style-image-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/list-style-position-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/list-style-position-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/list-style-type-applies-to-011.xht30
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/margin-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/margin-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/margin-bottom-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/margin-bottom-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/margin-left-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/margin-left-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/margin-right-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/margin-right-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/margin-top-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/margin-top-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/max-height-applies-to-011.xht26
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/max-width-applies-to-011.xht26
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/min-height-applies-to-011.xht25
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/min-width-applies-to-011.xht31
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/outline-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/outline-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/outline-color-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/outline-color-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/outline-style-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/outline-style-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/outline-width-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/outline-width-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/overflow-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/overflow-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/padding-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/padding-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/padding-bottom-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/padding-bottom-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/padding-left-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/padding-left-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/padding-right-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/padding-right-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/padding-top-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/padding-top-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/position-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/position-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/quotes-applies-to-011.xht27
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/right-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/right-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-003.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-003.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-004.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-004.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-005.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-005.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-006.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-006.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-007.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-007.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-008.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-008.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-009.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-009.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-010.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-010.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-012.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-012.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-013.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-013.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-abspos-between-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-abspos-between-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-abspos-between-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-abspos-between-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-abspos-between-003.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-abspos-between-003.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-basic-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-basic-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-003.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-basic-003.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-004.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-basic-004.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-005.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-basic-005.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-006.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-basic-006.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-007-ref.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-basic-007-ref.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-007.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-basic-007.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-008.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-basic-008.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-009.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-basic-009.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-010.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-basic-010.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-basic-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-012.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-basic-012.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-013.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-basic-013.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-014.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-basic-014.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-015.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-basic-015.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-016.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-basic-016.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-017.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-basic-017.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-018.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-basic-018.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-ref.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-basic-ref.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-block-between-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-block-between-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-block-between-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-block-between-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-block-between-003.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-block-between-003.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-block-ref.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-block-ref.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-breaking-001-ref.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-breaking-001-ref.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-breaking-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-breaking-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-breaking-002-ref.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-breaking-002-ref.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-breaking-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-breaking-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-clear-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-clear-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-clear-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-clear-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-abspos-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-abspos-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-block-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-block-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-block-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-block-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-block-003.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-block-003.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-block-004.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-block-004.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-block-005.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-block-005.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-block-inside-inline-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-block-inside-inline-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-block-inside-inline-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-block-inside-inline-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-block-inside-inline-003.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-block-inside-inline-003.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-float-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-float-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-003.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-003.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-004.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-004.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-005.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-005.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-006.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-006.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-007.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-007.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-block-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-block-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-table-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-table-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-relpos-block-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-relpos-block-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-relpos-block-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-relpos-block-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-relpos-block-003.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-relpos-block-003.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-run-in-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-run-in-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-run-in-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-run-in-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-run-in-003.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-run-in-003.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-003.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-003.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-caption-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-caption-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-cell-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-cell-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-column-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-column-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-column-group-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-column-group-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-inside-inline-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-inside-inline-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-inside-inline-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-inside-inline-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-inside-inline-003.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-inside-inline-003.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-row-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-row-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-row-group-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-row-group-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-display-none-between-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-display-none-between-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-display-none-between-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-display-none-between-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-display-none-between-003.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-display-none-between-003.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-fixedpos-between-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-fixedpos-between-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-fixedpos-between-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-fixedpos-between-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-fixedpos-between-003.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-fixedpos-between-003.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-float-between-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-float-between-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-float-between-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-float-between-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-float-between-003.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-float-between-003.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inherit-001-ref.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-inherit-001-ref.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inherit-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-inherit-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inheritance-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-inheritance-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-between-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-inline-between-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-between-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-inline-between-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-between-003.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-inline-between-003.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-block-between-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-inline-block-between-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-block-between-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-inline-block-between-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-block-between-003.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-inline-block-between-003.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-table-between-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-inline-table-between-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-table-between-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-inline-table-between-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-table-between-003.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-inline-table-between-003.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-linebox-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-linebox-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-linebox-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-linebox-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-listitem-between-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-listitem-between-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-listitem-between-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-listitem-between-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-listitem-between-003.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-listitem-between-003.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-pre-ref.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-pre-ref.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-relpos-between-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-relpos-between-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-relpos-between-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-relpos-between-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-relpos-between-003.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-relpos-between-003.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-replaced-001-ref.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-replaced-001-ref.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-replaced-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-replaced-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-restyle-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-restyle-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-restyle-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-restyle-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-restyle-003.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-restyle-003.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-run-in-between-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-run-in-between-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-run-in-between-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-run-in-between-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-run-in-between-003.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-run-in-between-003.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-run-in-between-004.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-run-in-between-004.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-run-in-between-005.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-run-in-between-005.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-run-in-between-006.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-run-in-between-006.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-run-in-between-007.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-run-in-between-007.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-run-in-between-008.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-run-in-between-008.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-between-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-table-between-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-between-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-table-between-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-between-003.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-table-between-003.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-cell-between-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-table-cell-between-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-cell-between-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-table-cell-between-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-cell-between-003.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-table-cell-between-003.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-row-between-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-table-row-between-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-row-between-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-table-row-between-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-row-between-003.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-table-row-between-003.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-text-between-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-text-between-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-text-between-002.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-text-between-002.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-text-between-003.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-text-between-003.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-text-between-004.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-text-between-004.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-text-between-005.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-text-between-005.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/run-in-text-ref.xht (renamed from tests/wpt/web-platform-tests/css/css-block/run-in-text-ref.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/support/black15x15.png (renamed from tests/wpt/web-platform-tests/css/css-block/support/black15x15.png)bin168 -> 168 bytes
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/support/blue15x15.png (renamed from tests/wpt/web-platform-tests/css/css-block/support/blue15x15.png)bin185 -> 185 bytes
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/support/blue96x96.png (renamed from tests/wpt/web-platform-tests/css/css-block/support/blue96x96.png)bin1010 -> 1010 bytes
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/support/green15x15.png (renamed from tests/wpt/web-platform-tests/css/css-block/support/green15x15.png)bin170 -> 170 bytes
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/support/swatch-blue.png (renamed from tests/wpt/web-platform-tests/css/css-block/support/swatch-blue.png)bin84 -> 84 bytes
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/table-anonymous-block-001.xht (renamed from tests/wpt/web-platform-tests/css/css-block/table-anonymous-block-001.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/table-layout-applies-to-004.xht (renamed from tests/wpt/web-platform-tests/css/css-block/table-layout-applies-to-004.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/text-align-applies-to-004.xht (renamed from tests/wpt/web-platform-tests/css/css-block/text-align-applies-to-004.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/text-decoration-applies-to-004.xht23
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/text-indent-applies-to-004.xht (renamed from tests/wpt/web-platform-tests/css/css-block/text-indent-applies-to-004.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/text-transform-applies-to-004.xht23
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/top-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/top-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/unicode-bidi-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/unicode-bidi-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/vertical-align-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/vertical-align-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/visibility-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/visibility-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/white-space-applies-to-004.xht (renamed from tests/wpt/web-platform-tests/css/css-block/white-space-applies-to-004.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/width-applies-to-011.xht25
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/word-spacing-applies-to-004.xht (renamed from tests/wpt/web-platform-tests/css/css-block/word-spacing-applies-to-004.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-display/run-in/z-index-applies-to-011.xht (renamed from tests/wpt/web-platform-tests/css/css-block/z-index-applies-to-011.xht)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-001.html12
-rw-r--r--tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-002.html8
-rw-r--r--tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-003.html12
-rw-r--r--tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-004.html8
-rw-r--r--tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-005.html12
-rw-r--r--tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-006.html13
-rw-r--r--tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-ref.html6
-rw-r--r--tests/wpt/web-platform-tests/css/css-flexbox/percentage-heights-004-ref.html57
-rw-r--r--tests/wpt/web-platform-tests/css/css-flexbox/percentage-heights-004.html61
-rw-r--r--tests/wpt/web-platform-tests/css/css-flexbox/table-as-item-narrow-content.html13
-rw-r--r--tests/wpt/web-platform-tests/css/css-flexbox/table-as-item-wide-content.html12
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/first-available-font-001-ref.html25
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/first-available-font-001.html44
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/first-available-font-002-ref.html25
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/first-available-font-002.html44
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/first-available-font-003-ref.html28
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/first-available-font-003.html50
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/first-available-font-004.html55
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/first-available-font-005-ref.html5
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/first-available-font-005.html64
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/first-available-font-006.html66
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/first-available-font-007.html52
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/font-default-01-ref.html24
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/font-default-01.html27
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/font-default-02-ref.html28
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/font-default-02.html32
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/font-default-03-ref.html28
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/font-default-03.html32
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/font-default-04-a-ref.html32
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/font-default-04-b-ref.html32
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/font-default-04-c-ref.html32
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/font-default-04.html45
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/font-display/font-display-change-ref.html72
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/font-display/font-display-change.html84
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/font-variant-01.html6
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/font-variant-02.html6
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/font-variant-03.html4
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/font-variant-04.html4
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/font-variant-alternates-parsing.html18
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/support/AD.woffbin0 -> 15368 bytes
-rw-r--r--tests/wpt/web-platform-tests/css/css-fonts/support/Revalia.woffbin0 -> 15588 bytes
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-001.html39
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-002.html39
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-003.html39
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-004.html40
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-005.html40
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-006.html40
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-007.html40
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-017.html85
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-017.html85
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/grid-definition/grid-template-columns-fit-content-001-ref.html96
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/grid-definition/grid-template-columns-fit-content-001.html2
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/grid-definition/grid-template-rows-fit-content-001-ref.html96
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/grid-items/explicitly-sized-grid-item-as-table.html12
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-minimum-size-grid-items-017.html14
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-minimum-size-grid-items-018.html2
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-minimum-size-grid-items-022.html137
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-minimum-size-grid-items-023.html248
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/grid-layout-properties.html4
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/grid-model/grid-container-ignores-first-letter-001.html108
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/grid-model/grid-container-ignores-first-line-001.html92
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/grid-model/grid-item-accepts-first-letter-001.html30
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/grid-model/grid-item-accepts-first-line-001.html30
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/reference/grid-collapsed-row-gutters-ref.html1
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/reference/grid-different-gutters-ref.html1
-rw-r--r--tests/wpt/web-platform-tests/css/css-grid/reference/grid-equal-gutters-ref.html1
-rw-r--r--tests/wpt/web-platform-tests/css/css-lists/counter-7-ref.html6
-rw-r--r--tests/wpt/web-platform-tests/css/css-lists/counter-increment-inside-display-contents.html20
-rw-r--r--tests/wpt/web-platform-tests/css/css-lists/counter-reset-increment-display-contents.html19
-rw-r--r--tests/wpt/web-platform-tests/css/css-lists/counter-reset-increment-display-none.html19
-rw-r--r--tests/wpt/web-platform-tests/css/css-lists/counter-reset-inside-display-contents.html21
-rw-r--r--tests/wpt/web-platform-tests/css/css-masking/clip/clip-rect-auto-001.html2
-rw-r--r--tests/wpt/web-platform-tests/css/css-masking/clip/clip-rect-comma-002.html2
-rw-r--r--tests/wpt/web-platform-tests/css/css-masking/clip/reference/clip-horizontal-stripe-ref.html2
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/OWNERS1
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-br-inside-avoidcolumn-001.xht52
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-br-inside-avoidcolumn-ref.xht30
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-break-001-ref.xht6
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-break-001.xht4
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-count-computed-001.xht50
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-count-computed-002.xht50
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-count-computed-2-ref.xht58
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-count-computed-ref.xht69
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-count-large-001.xht42
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-count-large-002.xht42
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-count-large-2-ref.xht40
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-count-large-ref.xht30
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-fill-auto-block-children-002-ref.xht48
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-fill-auto-block-children-002.xht27
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-fill-auto-ref.xht53
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-fill-auto.xht49
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-fill-ref.xht21
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-gap-animation-001.html45
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-gap-animation-002.html34
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-gap-animation-003.html33
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-gap-fraction-002.html68
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-height-block-child-001-ref.xht53
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-height-block-child-001.xht55
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-inherit-004.xht55
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-inherit-4-ref.xht37
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-nested-column-rule-001-ref.xht37
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-nested-column-rule-001.xht2
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-fraction-3-ref.xht4
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-samelength-001.xht4
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-style-groove-001-ref.xht44
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-style-groove-001.xht71
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-style-inset-001.xht71
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-style-outset-001.xht71
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-style-ridge-001-ref.xht44
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-style-ridge-001.xht71
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-003.xht4
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-child-001-ref.xht109
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-child-001.xht53
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-child-002-ref.xht32
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-child-002.xht86
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-margin-nested-003.xht39
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-margin-nested-3-ref.xht23
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-table-cell-vertical-align-001.xht4
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-table-cell-vertical-align-ref.xht6
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-width-ch-001.xht34
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-width-ch-ref.xht49
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-width-ems-001.xht42
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-width-ems-ref.xht59
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-width-small-001.xht21
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-zero-height-001-ref.xht8
-rw-r--r--tests/wpt/web-platform-tests/css/css-multicol/multicol-zero-height-001.xht18
-rw-r--r--tests/wpt/web-platform-tests/css/css-overflow/input-scrollable-region-001.html26
-rw-r--r--tests/wpt/web-platform-tests/css/css-overflow/reference/input-scrollable-region-001-ref.html21
-rw-r--r--tests/wpt/web-platform-tests/css/css-paint-api/geometry-with-float-size-ref.html12
-rw-r--r--tests/wpt/web-platform-tests/css/css-paint-api/geometry-with-float-size.https.html35
-rw-r--r--tests/wpt/web-platform-tests/css/css-paint-api/registered-properties-in-custom-paint.https.html2
-rw-r--r--tests/wpt/web-platform-tests/css/css-paint-api/style-background-image.https.html2
-rw-r--r--tests/wpt/web-platform-tests/css/css-paint-api/style-before-pseudo.https.html2
-rw-r--r--tests/wpt/web-platform-tests/css/css-position/position-sticky-offset-overflow.html60
-rw-r--r--tests/wpt/web-platform-tests/css/css-position/position-sticky-table-parts-ref.html48
-rw-r--r--tests/wpt/web-platform-tests/css/css-position/position-sticky-table-parts.html72
-rw-r--r--tests/wpt/web-platform-tests/css/css-pseudo/marker-font-properties-ref.html4
-rw-r--r--tests/wpt/web-platform-tests/css/css-pseudo/marker-font-properties.html4
-rw-r--r--tests/wpt/web-platform-tests/css/css-shapes/shape-outside/values/shape-image-threshold-003.html2
-rw-r--r--tests/wpt/web-platform-tests/css/css-style-attr/reference/ref-green-on-green2.xht14
-rw-r--r--tests/wpt/web-platform-tests/css/css-style-attr/style-attr-urls-003.xht23
-rw-r--r--tests/wpt/web-platform-tests/css/css-tables/zero-rowspan-001-ref.html11
-rw-r--r--tests/wpt/web-platform-tests/css/css-tables/zero-rowspan-001.html12
-rw-r--r--tests/wpt/web-platform-tests/css/css-tables/zero-rowspan-002-ref.html9
-rw-r--r--tests/wpt/web-platform-tests/css/css-tables/zero-rowspan-002.html11
-rw-r--r--tests/wpt/web-platform-tests/css/css-text-decor/line-through-vertical.html16
-rw-r--r--tests/wpt/web-platform-tests/css/css-text-decor/reference/line-through-vertical-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/css/css-text-decor/reference/text-decoration-color-recalc-ref.html12
-rw-r--r--tests/wpt/web-platform-tests/css/css-text-decor/reference/text-decoration-color-ref.html43
-rw-r--r--tests/wpt/web-platform-tests/css/css-text-decor/reference/text-decoration-line-recalc-ref.html12
-rw-r--r--tests/wpt/web-platform-tests/css/css-text-decor/reference/text-decoration-line-ref.html33
-rw-r--r--tests/wpt/web-platform-tests/css/css-text-decor/reference/text-decoration-style-multiple-ref.html19
-rw-r--r--tests/wpt/web-platform-tests/css/css-text-decor/reference/text-decoration-style-recalc-ref.html12
-rw-r--r--tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-color-recalc.html19
-rw-r--r--tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-color.html64
-rw-r--r--tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-line-recalc.html19
-rw-r--r--tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-line.html35
-rw-r--r--tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-serialization.tentative.html17
-rw-r--r--tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-style-multiple.html21
-rw-r--r--tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-style-recalc.html19
-rw-r--r--tests/wpt/web-platform-tests/css/css-transforms/css-transform-inherit-scale.html75
-rw-r--r--tests/wpt/web-platform-tests/css/css-transforms/transform-2d-getComputedStyle-001.html9
-rw-r--r--tests/wpt/web-platform-tests/css/css-transforms/transform-box/fill-box-mutation.html24
-rw-r--r--tests/wpt/web-platform-tests/css/css-transforms/transform-box/fill-box.html33
-rw-r--r--tests/wpt/web-platform-tests/css/css-transforms/transform-box/support/greensquare200x200.html3
-rw-r--r--tests/wpt/web-platform-tests/css/css-transforms/transform-box/value-changed.html19
-rw-r--r--tests/wpt/web-platform-tests/css/css-transforms/transform-box/view-box-nested.html17
-rw-r--r--tests/wpt/web-platform-tests/css/css-transforms/transform-box/view-box-viewbox-nested.html17
-rw-r--r--tests/wpt/web-platform-tests/css/css-transforms/transform-box/view-box-viewbox.html15
-rw-r--r--tests/wpt/web-platform-tests/css/css-transforms/transform-box/view-box.html33
-rw-r--r--tests/wpt/web-platform-tests/css/css-transitions/before-DOMContentLoaded-001.html7
-rw-r--r--tests/wpt/web-platform-tests/css/css-transitions/before-load-001.html7
-rw-r--r--tests/wpt/web-platform-tests/css/css-transitions/changing-while-transition.html7
-rw-r--r--tests/wpt/web-platform-tests/css/css-transitions/currentcolor-animation-001.html1
-rw-r--r--tests/wpt/web-platform-tests/css/css-transitions/detached-container-001.html7
-rw-r--r--tests/wpt/web-platform-tests/css/css-transitions/hidden-container-001.html7
-rw-r--r--tests/wpt/web-platform-tests/css/css-transitions/properties-value-001.html567
-rw-r--r--tests/wpt/web-platform-tests/css/css-transitions/properties-value-002.html23
-rw-r--r--tests/wpt/web-platform-tests/css/css-transitions/properties-value-003.html197
-rw-r--r--tests/wpt/web-platform-tests/css/css-transitions/properties-value-auto-001.html57
-rw-r--r--tests/wpt/web-platform-tests/css/css-transitions/properties-value-implicit-001.html65
-rw-r--r--tests/wpt/web-platform-tests/css/css-transitions/properties-value-inherit-001.html567
-rw-r--r--tests/wpt/web-platform-tests/css/css-transitions/properties-value-inherit-002.html567
-rw-r--r--tests/wpt/web-platform-tests/css/css-transitions/properties-value-inherit-003.html65
-rw-r--r--tests/wpt/web-platform-tests/css/css-transitions/pseudo-elements-001.html9
-rw-r--r--tests/wpt/web-platform-tests/css/css-transitions/transition-001.html17
-rw-r--r--tests/wpt/web-platform-tests/css/css-transitions/transition-delay-001.html26
-rw-r--r--tests/wpt/web-platform-tests/css/css-transitions/transition-duration-001.html26
-rw-r--r--tests/wpt/web-platform-tests/css/css-transitions/transition-property-001.html10
-rw-r--r--tests/wpt/web-platform-tests/css/css-transitions/transition-property-002.html12
-rw-r--r--tests/wpt/web-platform-tests/css/css-transitions/transition-timing-function-001.html25
-rw-r--r--tests/wpt/web-platform-tests/css/css-typed-om/factory-absolute-length.html4
-rw-r--r--tests/wpt/web-platform-tests/css/css-typed-om/styleMap-update-function.html2
-rw-r--r--tests/wpt/web-platform-tests/css/css-typed-om/stylevalue-objects/interface.html21
-rw-r--r--tests/wpt/web-platform-tests/css/css-typed-om/stylevalue-subclasses/cssKeywordValue-interface.html24
-rw-r--r--tests/wpt/web-platform-tests/css/css-values/calc-unit-analysis.html13
-rw-r--r--tests/wpt/web-platform-tests/css/css-values/support/vh-support-transform-origin-iframe.html (renamed from tests/wpt/web-platform-tests/css/css-values/iframe/vh-support-transform-origin-iframe.html)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-values/support/vh-support-transform-translate-iframe.html (renamed from tests/wpt/web-platform-tests/css/css-values/iframe/vh-support-transform-translate-iframe.html)0
-rw-r--r--tests/wpt/web-platform-tests/css/css-values/vh-support-transform-origin.html2
-rw-r--r--tests/wpt/web-platform-tests/css/css-values/vh-support-transform-translate.html2
-rw-r--r--tests/wpt/web-platform-tests/css/css-variables/test_variable_legal_values.html27
-rw-r--r--tests/wpt/web-platform-tests/css/css-writing-modes/bidi-table-001.html3
-rw-r--r--tests/wpt/web-platform-tests/css/css-writing-modes/block-plaintext-006.html8
-rw-r--r--tests/wpt/web-platform-tests/css/cssom-view/elementFromPosition.html22
-rw-r--r--tests/wpt/web-platform-tests/css/cssom-view/offsetParent_element_test.html6
-rw-r--r--tests/wpt/web-platform-tests/css/cssom-view/overscrollBehavior-manual.html1
-rw-r--r--tests/wpt/web-platform-tests/css/cssom-view/scroll-behavior-smooth.html60
-rw-r--r--tests/wpt/web-platform-tests/css/cssom-view/scrollTop-display-change-ref.html8
-rw-r--r--tests/wpt/web-platform-tests/css/cssom-view/scrollTop-display-change.html17
-rw-r--r--tests/wpt/web-platform-tests/css/cssom-view/scrollWidthHeight.xht15
-rw-r--r--tests/wpt/web-platform-tests/css/cssom-view/scrollWidthHeightWhenNotScrollable.xht15
-rw-r--r--tests/wpt/web-platform-tests/css/cssom-view/window-interface.xht16
-rw-r--r--tests/wpt/web-platform-tests/css/cssom/MediaList2.xhtml9
-rw-r--r--tests/wpt/web-platform-tests/css/cssom/computed-style-001.html8
-rw-r--r--tests/wpt/web-platform-tests/css/cssom/getComputedStyle-pseudo.html18
-rw-r--r--tests/wpt/web-platform-tests/css/cssom/inline-style-001.html16
-rw-r--r--tests/wpt/web-platform-tests/css/cssom/medialist-dynamic-001-ref.html5
-rw-r--r--tests/wpt/web-platform-tests/css/cssom/medialist-dynamic-001.html12
-rw-r--r--tests/wpt/web-platform-tests/css/cssom/medialist-interfaces-001.html24
-rw-r--r--tests/wpt/web-platform-tests/css/cssom/medialist-interfaces-002.html9
-rw-r--r--tests/wpt/web-platform-tests/css/cssom/medialist-interfaces-003.html10
-rw-r--r--tests/wpt/web-platform-tests/css/cssom/medialist-interfaces-004.html8
-rw-r--r--tests/wpt/web-platform-tests/css/cssom/setproperty-null-undefined.html47
-rw-r--r--tests/wpt/web-platform-tests/css/cssom/style-sheet-interfaces-001.html25
-rw-r--r--tests/wpt/web-platform-tests/css/cssom/style-sheet-interfaces-002.html9
-rw-r--r--tests/wpt/web-platform-tests/css/cssom/ttwf-cssom-doc-ext-load-count.html7
-rw-r--r--tests/wpt/web-platform-tests/css/mediaqueries/mq-calc-002.html10
-rw-r--r--tests/wpt/web-platform-tests/css/mediaqueries/mq-calc-003.html10
-rw-r--r--tests/wpt/web-platform-tests/css/mediaqueries/mq-calc-004.html11
-rw-r--r--tests/wpt/web-platform-tests/css/mediaqueries/mq-calc-005.html11
-rw-r--r--tests/wpt/web-platform-tests/css/mediaqueries/relative-units-001.html15
-rw-r--r--tests/wpt/web-platform-tests/css/mediaqueries/relative-units-002.html15
-rw-r--r--tests/wpt/web-platform-tests/css/mediaqueries/relative-units-003.html15
-rw-r--r--tests/wpt/web-platform-tests/css/mediaqueries/relative-units-004.html15
-rw-r--r--tests/wpt/web-platform-tests/css/mediaqueries/test_media_queries.html369
-rw-r--r--tests/wpt/web-platform-tests/css/motion/animation/offset-path-interpolation-001.html110
-rw-r--r--tests/wpt/web-platform-tests/css/motion/animation/offset-path-interpolation-002.html93
-rw-r--r--tests/wpt/web-platform-tests/css/motion/animation/offset-path-interpolation-003.html118
-rw-r--r--tests/wpt/web-platform-tests/css/motion/animation/offset-path-interpolation-004.html123
-rw-r--r--tests/wpt/web-platform-tests/css/motion/animation/offset-path-interpolation-005.html81
-rw-r--r--tests/wpt/web-platform-tests/css/reference/nothing.html4
-rw-r--r--tests/wpt/web-platform-tests/css/reference/ref-filled-green-100px-square-only.html4
-rw-r--r--tests/wpt/web-platform-tests/css/selectors/any-link-dynamic-001-ref.html10
-rw-r--r--tests/wpt/web-platform-tests/css/selectors/any-link-dynamic-001.html14
-rw-r--r--tests/wpt/web-platform-tests/css/selectors/invalidation/any-link-pseudo.html36
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/parser/parser-uses-registry-of-owner-document.html46
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/reactions/Document.html12
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/reactions/with-exceptions.html31
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/resources/my-custom-element-html-document.html6
-rw-r--r--tests/wpt/web-platform-tests/dom/events/Event-subclasses-constructors.html26
-rw-r--r--tests/wpt/web-platform-tests/dom/events/EventListener-invoke-legacy.html14
-rw-r--r--tests/wpt/web-platform-tests/dom/historical.html10
-rw-r--r--tests/wpt/web-platform-tests/encoding/big5-encoder.html8
-rw-r--r--tests/wpt/web-platform-tests/encoding/gbk-encoder.html2
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-check-initdata-type.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-check-initdata-type.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-events-session-closed-event.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-events-session-closed-event.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-events.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-events.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-generate-request-disallowed-input.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-generate-request-disallowed-input.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-invalid-license.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-invalid-license.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-keystatuses-multiple-sessions.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-keystatuses-multiple-sessions.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-keystatuses.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-keystatuses.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-destroy-persistent-license.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-destroy-persistent-license.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-persistent-license-events.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-persistent-license-events.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-persistent-license.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-persistent-license.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-persistent-usage-record.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-persistent-usage-record.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-events.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-events.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-multikey.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-multikey.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-multisession.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-multisession.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-two-videos.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-two-videos.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-requestmediakeysystemaccess.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-requestmediakeysystemaccess.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-at-same-time.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-at-same-time.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-syntax-mediakeys.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-syntax-mediakeys.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-syntax-mediakeysession.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-syntax-mediakeysession.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-unique-origin.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-unique-origin.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-update-disallowed-input.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-update-disallowed-input.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-waiting-for-a-key.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-waiting-for-a-key.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-not-callable-after-createsession.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-not-callable-after-createsession.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/clearkey-update-non-ascii-input.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/clearkey-update-non-ascii-input.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-check-initdata-type.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-check-initdata-type.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-events-session-closed-event.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-events-session-closed-event.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-events.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-events.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-expiration.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-expiration.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-generate-request-disallowed-input.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-generate-request-disallowed-input.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-invalid-license.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-invalid-license.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-keystatuses-multiple-sessions.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-keystatuses-multiple-sessions.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-keystatuses.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-keystatuses.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-onencrypted.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-onencrypted.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-destroy-persistent-license.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-destroy-persistent-license.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-persistent-license-events.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-persistent-license-events.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-persistent-license.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-persistent-license.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-persistent-usage-record-events.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-persistent-usage-record-events.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-persistent-usage-record.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-persistent-usage-record.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-retrieve-persistent-license.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-retrieve-persistent-license.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-clear-encrypted.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-clear-encrypted.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-encrypted-clear.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-encrypted-clear.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-events.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-events.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-expired.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-expired.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-multikey-sequential.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-multikey-sequential.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-multikey.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-multikey.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-multisession.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-multisession.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-two-videos.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-two-videos.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-waitingforkey.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-waitingforkey.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-requestmediakeysystemaccess.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-requestmediakeysystemaccess.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-reset-src-after-setmediakeys.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-reset-src-after-setmediakeys.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-again-after-playback.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-again-after-playback.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-at-same-time.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-at-same-time.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-syntax-mediakeys.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-syntax-mediakeys.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-syntax-mediakeysession.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-syntax-mediakeysession.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-syntax-mediakeysystemaccess.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-syntax-mediakeysystemaccess.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-unique-origin.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-unique-origin.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-mp4-waiting-for-a-key.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-mp4-waiting-for-a-key.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-not-callable-after-createsession.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-not-callable-after-createsession.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/drm-temporary-license-type.https.html (renamed from tests/wpt/web-platform-tests/encrypted-media/drm-temporary-license-type.html)0
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/idlharness.html51
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/idlharness.https.html49
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/resources/clearkey-retrieve-destroy-persistent-license.html2
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/resources/clearkey-retrieve-persistent-license.html7
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/resources/drm-retrieve-destroy-persistent-license.html2
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/resources/drm-retrieve-persistent-license.html7
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/resources/drm-retrieve-persistent-usage-record.html6
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/resources/retrieve-persistent-usage-record.html6
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/scripts/playback-retrieve-persistent-license.js17
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/scripts/playback-retrieve-persistent-usage-record.js18
-rw-r--r--tests/wpt/web-platform-tests/encrypted-media/scripts/unique-origin.js6
-rw-r--r--tests/wpt/web-platform-tests/feature-policy/README.md2
-rw-r--r--tests/wpt/web-platform-tests/feature-policy/autoplay-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html35
-rw-r--r--tests/wpt/web-platform-tests/feature-policy/autoplay-allowed-by-feature-policy-attribute.https.sub.html34
-rw-r--r--tests/wpt/web-platform-tests/feature-policy/autoplay-allowed-by-feature-policy.https.sub.html39
-rw-r--r--tests/wpt/web-platform-tests/feature-policy/autoplay-allowed-by-feature-policy.https.sub.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/feature-policy/autoplay-default-feature-policy.https.sub.html39
-rw-r--r--tests/wpt/web-platform-tests/feature-policy/autoplay-disabled-by-feature-policy.https.sub.html39
-rw-r--r--tests/wpt/web-platform-tests/feature-policy/autoplay-disabled-by-feature-policy.https.sub.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/feature-policy/payment-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html8
-rw-r--r--tests/wpt/web-platform-tests/feature-policy/resources/autoplay.js28
-rw-r--r--tests/wpt/web-platform-tests/feature-policy/resources/feature-policy-autoplay.html11
-rw-r--r--tests/wpt/web-platform-tests/feature-policy/resources/feature-policy-generic-sensor.html11
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/cors/cors-expose-star.js2
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/redirect/redirect-method.js32
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/request/destination/fetch-destination.https.html134
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy (renamed from tests/wpt/web-platform-tests/tools/py/testing/log/__init__.py)0
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy.pngbin0 -> 18299 bytes
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_audio.mp3bin0 -> 20498 bytes
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_audio.ogabin0 -> 18541 bytes
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_video.mp4bin0 -> 67369 bytes
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_video.ogvbin0 -> 94372 bytes
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/request/destination/resources/empty.https.html (renamed from tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/__init__.py)0
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/request/destination/resources/fetch-destination-worker.js11
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/request/request-idl.html6
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/request/request-keepalive-quota.html71
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/resources/trickle.py2
-rw-r--r--tests/wpt/web-platform-tests/fetch/api/response/response-idl.html6
-rw-r--r--tests/wpt/web-platform-tests/fetch/nosniff/resources/css.py26
-rw-r--r--tests/wpt/web-platform-tests/fetch/nosniff/stylesheet.html26
-rw-r--r--tests/wpt/web-platform-tests/fullscreen/model/move-to-fullscreen-iframe-manual.html32
-rw-r--r--tests/wpt/web-platform-tests/fullscreen/rendering/ua-style-iframe-manual.html35
-rw-r--r--tests/wpt/web-platform-tests/generic-sensor/generic-sensor-feature-policy-test.sub.js159
-rw-r--r--tests/wpt/web-platform-tests/generic-sensor/generic-sensor-tests.js249
-rw-r--r--tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-disabled-by-feature-policy.https.html12
-rw-r--r--tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-disabled-by-feature-policy.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html12
-rw-r--r--tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-enabled-by-feature-policy-attribute.https.html12
-rw-r--r--tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-enabled-by-feature-policy.https.html12
-rw-r--r--tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-enabled-by-feature-policy.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-enabled-on-self-origin-by-feature-policy.https.html12
-rw-r--r--tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-enabled-on-self-origin-by-feature-policy.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor.https.html13
-rw-r--r--tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor_insecure_context.html13
-rw-r--r--tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor_onerror-manual.https.html19
-rw-r--r--tests/wpt/web-platform-tests/geolocation-sensor/OWNERS1
-rw-r--r--tests/wpt/web-platform-tests/geolocation-sensor/idlharness.https.html23
-rw-r--r--tests/wpt/web-platform-tests/gyroscope/Gyroscope-disabled-by-feature-policy.https.html12
-rw-r--r--tests/wpt/web-platform-tests/gyroscope/Gyroscope-disabled-by-feature-policy.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/gyroscope/Gyroscope-enabled-by-feature-policy-attribute-redirect-on-load.https.html12
-rw-r--r--tests/wpt/web-platform-tests/gyroscope/Gyroscope-enabled-by-feature-policy-attribute.https.html12
-rw-r--r--tests/wpt/web-platform-tests/gyroscope/Gyroscope-enabled-by-feature-policy.https.html12
-rw-r--r--tests/wpt/web-platform-tests/gyroscope/Gyroscope-enabled-by-feature-policy.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/gyroscope/Gyroscope-enabled-on-self-origin-by-feature-policy.https.html12
-rw-r--r--tests/wpt/web-platform-tests/gyroscope/Gyroscope-enabled-on-self-origin-by-feature-policy.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/hr-time/idlharness.html75
-rw-r--r--tests/wpt/web-platform-tests/hr-time/performance-tojson.html76
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/PopStateEvent.html5
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/hashchange_event.html6
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html25
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-media/pageload-video.html41
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload.tentative.html6
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload_form-submission-2.tentative.html6
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/sandboxing/noscript-iframe.html3
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/sandboxing/sandbox-parse-noscript-ref.html6
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/sandboxing/sandbox-parse-noscript.html7
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/windows/browsing-context.html5
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements-embedded.js1
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements-forms.js16
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements-metadata.js15
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements-misc.js4
-rw-r--r--tests/wpt/web-platform-tests/html/dom/reflection.js8
-rw-r--r--tests/wpt/web-platform-tests/html/dom/usvstring-reflection.html89
-rw-r--r--tests/wpt/web-platform-tests/html/form-elements/the-textarea-element/multiline-placeholder-cr.html1
-rw-r--r--tests/wpt/web-platform-tests/html/form-elements/the-textarea-element/multiline-placeholder-crlf.html21
-rw-r--r--tests/wpt/web-platform-tests/html/form-elements/the-textarea-element/multiline-placeholder-ref.html15
-rw-r--r--tests/wpt/web-platform-tests/html/form-elements/the-textarea-element/multiline-placeholder.html22
-rw-r--r--tests/wpt/web-platform-tests/html/form-elements/the-textarea-element/support/placeholder.css6
-rw-r--r--tests/wpt/web-platform-tests/html/input/the-placeholder-attribute/multiline-cr.html1
-rw-r--r--tests/wpt/web-platform-tests/html/input/the-placeholder-attribute/multiline-crlf.html19
-rw-r--r--tests/wpt/web-platform-tests/html/input/the-placeholder-attribute/multiline-ref.html5
-rw-r--r--tests/wpt/web-platform-tests/html/input/the-placeholder-attribute/multiline.html19
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/crossOrigin.html60
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/readyState.html7
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/constructor.html23
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-positioning-bad.vtt20
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-positioning.vtt20
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-text-line-position-bad.vtt21
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-text-line-position.vtt28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/alignment-bad.vtt22
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/alignment-ltr.vtt22
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/alignment.vtt22
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/bom.vtt10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions-fast.vtt13
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions-gaps.vtt18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions-html.vtt18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions.vtt18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/class-bad.vtt17
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/class.vtt14
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-id-error.vtt14
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-id.vtt18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-no-id-error.vtt14
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-no-id.vtt11
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-cuetext.vtt6
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-header.vtt6
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-note.vtt9
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-align-bad.vtt18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-align.vtt19
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-bad.vtt17
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size.vtt19
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues-no-separation.vtt11
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues-overlapping.vtt14
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues.vtt17
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/default-styles.vtt19
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/degenerate-cues.vtt5
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/empty-cue.vtt11
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/entities-wrong.vtt15
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/entities.vtt30
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/interspersed-non-cue.vtt9
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/iso2022jp3.vtt10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/large-timestamp.vtt5
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/line-position-bad.vtt30
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/line-position.vtt37
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/markup-bad.vtt22
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/markup.vtt22
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/metadata-area.vtt14
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/metadata.vtt38
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/missed-cues.vtt31
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/no-newline-at-eof.vtt6
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/no-timings.vtt13
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/no-webvtt.vtt10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/positioning-bad.vtt39
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/positioning-ltr.vtt21
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/positioning.vtt21
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/settings-bad-separation.vtt20
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/settings.vtt18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/simple-captions.vtt17
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/sorted-dispatch.vtt34
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timestamp-bad.vtt17
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timestamp.vtt14
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-hour-error.vtt22
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-hour.vtt14
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-no-hour-errors.vtt22
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-no-hour.vtt18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-whitespace.vtt51
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/unsupported-markup.vtt23
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/utf8.vtt10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/valign-bad.vtt17
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/valign-ltr.vtt20
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/valign.vtt20
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/voice-bad.vtt17
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/voice.vtt15
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/vp8-vorbis-webvtt.webmbin0 -> 143662 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/webvtt-file.vtt9
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/webvtt-rubbish.vtt10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-active-cues.html39
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-add-remove-cue.html92
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-add-track.html34
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-addtrack-kind.html25
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-empty.html19
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-inline.html16
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable-fragment.html85
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable.html99
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-missed.html59
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-pause-on-exit.html35
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-seeking.html31
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-sorted-before-dispatch.html48
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-disabled-addcue.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-disabled.html28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-dom-change.html16
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change-error.html92
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change.html57
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-helpers.js83
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-large-timestamp.html19
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-load-error-readyState.html15
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-load-from-element-readyState.html15
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-load-from-src-readyState.html20
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode-disabled.html34
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode-not-changed-by-new-track.html73
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode-triggers-loading.html37
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode.html61
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-active-cue.html35
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-by-setting-innerHTML.html31
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-insert-ready-state.html38
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-quickly.html14
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-track.html105
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-align-positioning.html52
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-align-text-line-position.html54
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-alignment.html31
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-blank-lines.html26
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-bom.html34
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-class-markup.html55
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-identifiers.html27
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-no-id.html19
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-recovery.html19
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-size-align.html26
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-size.html26
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-degenerate-cues.html16
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-empty-cue.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-entities.html42
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-header-comment.html50
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-interspersed-non-cue.html15
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-line-position.html58
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-magic-header.html57
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-markup.html89
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-newlines.html26
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-no-timings.html17
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-positioning.html35
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-settings.html28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timestamp.html36
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-hour.html61
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-no-hours.html67
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-whitespace.html25
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-unsupported-markup.html37
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-utf8.html57
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-valign.html28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-voice.html54
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-area-element/area-download-click.html29
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-area-element/resources/area-download-click.html5
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html27
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-progress-element/progress.html4
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/select-add.html36
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/selected-index.html4
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/abspos-dialog-layout.html223
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/dialog-scrolled-viewport.html45
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/inert-does-not-match-disabled-selector.html35
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/inert-node-is-unfocusable.html58
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/defer.js4
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1.html36
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1a.js2
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1b.js2
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2.html36
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2a.js2
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2b.js2
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3.html37
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3a.js2
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3b.js2
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-script-error.html2
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/Function.js1
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/eval.js1
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/inline-event-handlers-UA-code.js2
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/reflected-inline-event-handlers.js2
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/setTimeout.js1
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-classic.html56
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-classic.html52
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-module.html53
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-classic.html56
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-module.html56
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-module.html56
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-integrity-classic.html52
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-integrity-module.html52
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-classic.html103
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-module.html102
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-1.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-1.js2
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-2.html34
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-2.js2
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-3.html34
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-3.js2
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-1.html18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-2.html18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-3.html18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-4.html16
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-5.html18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/referrer-no-referrer.sub.html59
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/referrer-origin-when-cross-origin.sub.html66
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/referrer-origin.sub.html62
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/referrer-same-origin.sub.html62
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/referrer-unsafe-url.sub.html68
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js2
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/resources/import-remote-origin-referrer-checker.sub.js2
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py6
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/throw2.js2
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-defer.html26
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/a-download-click-404.html6
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/a-download-click.html25
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/resources/a-download-click.html2
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-b-element/b-usage-notref.html6
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-b-element/b-usage.html8
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-ruby-element/ruby-usage-notref.html6
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-ruby-element/ruby-usage.html8
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/animation-frames/idlharness.html2
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/events/event-handler-spec-example.html2
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.html8
-rw-r--r--tests/wpt/web-platform-tests/http/resources/securedimage.py2
-rw-r--r--tests/wpt/web-platform-tests/infrastructure/assumptions/ahem-notref.html316
-rw-r--r--tests/wpt/web-platform-tests/infrastructure/assumptions/ahem-ref.html18
-rw-r--r--tests/wpt/web-platform-tests/infrastructure/assumptions/ahem.html9
-rw-r--r--tests/wpt/web-platform-tests/infrastructure/assumptions/tools/ahem-generate-table.py101
-rw-r--r--tests/wpt/web-platform-tests/interfaces/dom.idl52
-rw-r--r--tests/wpt/web-platform-tests/interfaces/geolocation-sensor.idl2
-rw-r--r--tests/wpt/web-platform-tests/interfaces/hr-time.idl13
-rw-r--r--tests/wpt/web-platform-tests/interfaces/html.idl247
-rw-r--r--tests/wpt/web-platform-tests/interfaces/webrtc-pc.idl2
-rw-r--r--tests/wpt/web-platform-tests/lint.whitelist148
-rw-r--r--tests/wpt/web-platform-tests/longtask-timing/longtask-in-childiframe-crossorigin.html9
-rw-r--r--tests/wpt/web-platform-tests/longtask-timing/longtask-in-parentiframe.html7
-rw-r--r--tests/wpt/web-platform-tests/longtask-timing/longtask-in-sibling-iframe-crossorigin.html33
-rw-r--r--tests/wpt/web-platform-tests/longtask-timing/longtask-in-sibling-iframe.html30
-rw-r--r--tests/wpt/web-platform-tests/longtask-timing/longtask-tojson.html71
-rw-r--r--tests/wpt/web-platform-tests/longtask-timing/resources/subframe-observing-longtask.html11
-rw-r--r--tests/wpt/web-platform-tests/magnetometer/Magnetometer-disabled-by-feature-policy.https.html13
-rw-r--r--tests/wpt/web-platform-tests/magnetometer/Magnetometer-disabled-by-feature-policy.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/magnetometer/Magnetometer-enabled-by-feature-policy-attribute-redirect-on-load.https.html13
-rw-r--r--tests/wpt/web-platform-tests/magnetometer/Magnetometer-enabled-by-feature-policy-attribute.https.html13
-rw-r--r--tests/wpt/web-platform-tests/magnetometer/Magnetometer-enabled-by-feature-policy.https.html13
-rw-r--r--tests/wpt/web-platform-tests/magnetometer/Magnetometer-enabled-by-feature-policy.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/magnetometer/Magnetometer-enabled-on-self-origin-by-feature-policy.https.html13
-rw-r--r--tests/wpt/web-platform-tests/magnetometer/Magnetometer-enabled-on-self-origin-by-feature-policy.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/magnetometer/Magnetometer.https.html1
-rw-r--r--tests/wpt/web-platform-tests/magnetometer/Magnetometer_insecure_context.html1
-rw-r--r--tests/wpt/web-platform-tests/magnetometer/Magnetometer_onerror-manual.https.html1
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-fraktur-ref.html104
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-fraktur.html106
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-italic-ref.html220
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-italic.html222
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-ref.html244
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-sans-serif-ref.html240
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-sans-serif.html242
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-script-ref.html104
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-script.html106
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold.html246
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-double-struck-ref.html174
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-double-struck.html176
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-fraktur-ref.html104
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-fraktur.html106
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-initial-ref.html40
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-initial.html42
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-italic-ref.html224
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-italic.html226
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-looped-ref.html54
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-looped.html56
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-monospace-ref.html124
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-monospace.html126
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif-bold-italic-ref.html220
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif-bold-italic.html222
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif-italic-ref.html104
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif-italic.html106
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif-ref.html124
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif.html126
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-script-ref.html104
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-script.html106
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-stretched-ref.html46
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-stretched.html48
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-tailed-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-tailed.html32
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/html5-tree/unique-identifier-1-iframe-1.html (renamed from tests/wpt/web-platform-tests/mathml/relations/html5-tree/unique-identifier-1-iframe.html)0
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/html5-tree/unique-identifier-1-iframe-2.html (renamed from tests/wpt/web-platform-tests/mathml/relations/html5-tree/unique-identifier-1-ref-iframe.html)0
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/html5-tree/unique-identifier-1-ref.html2
-rw-r--r--tests/wpt/web-platform-tests/mathml/relations/html5-tree/unique-identifier-1.html2
-rw-r--r--tests/wpt/web-platform-tests/mathml/tools/mathvariant-transforms.py6
-rw-r--r--tests/wpt/web-platform-tests/media-capabilities/decodingInfo.html127
-rw-r--r--tests/wpt/web-platform-tests/media-capabilities/idlharness.html2
-rw-r--r--tests/wpt/web-platform-tests/media/counting.mp4bin0 -> 311336 bytes
-rw-r--r--tests/wpt/web-platform-tests/media/counting.ogvbin0 -> 187773 bytes
-rw-r--r--tests/wpt/web-platform-tests/media/test.mp4bin0 -> 192844 bytes
-rw-r--r--tests/wpt/web-platform-tests/media/test.ogvbin0 -> 146510 bytes
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-fromelement/capture.html4
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-fromelement/creation.html6
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-fromelement/ended.html6
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-video-is-black.https.html2
-rw-r--r--tests/wpt/web-platform-tests/mediasession/idlharness.html2
-rw-r--r--tests/wpt/web-platform-tests/mimesniff/OWNERS1
-rw-r--r--tests/wpt/web-platform-tests/mimesniff/README.md1
-rw-r--r--tests/wpt/web-platform-tests/mimesniff/mime-types/README.md34
-rw-r--r--tests/wpt/web-platform-tests/mimesniff/mime-types/charset-parameter.window.js57
-rw-r--r--tests/wpt/web-platform-tests/mimesniff/mime-types/parsing.any.js51
-rw-r--r--tests/wpt/web-platform-tests/mimesniff/mime-types/resources/generated-mime-types.json3526
-rw-r--r--tests/wpt/web-platform-tests/mimesniff/mime-types/resources/generated-mime-types.py45
-rw-r--r--tests/wpt/web-platform-tests/mimesniff/mime-types/resources/mime-charset.py3
-rw-r--r--tests/wpt/web-platform-tests/mimesniff/mime-types/resources/mime-types.json262
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html40
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html.headers (renamed from tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers)0
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html40
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html40
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html.headers (renamed from tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html.headers)0
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html40
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html40
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html.headers (renamed from tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers)0
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html40
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html40
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html.headers (renamed from tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers)0
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html40
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html40
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html.headers (renamed from tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html.headers)0
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html40
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html40
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html.headers (renamed from tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers)0
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html40
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/meta-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html41
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/meta-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html41
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/meta-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html41
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/meta-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html41
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/keep-scheme-redirect/blockable/no-opt-in-blocks.https.html40
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html40
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/no-redirect/blockable/no-opt-in-blocks.https.html40
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/no-redirect/optionally-blockable/no-opt-in-allows.https.html40
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/swap-scheme-redirect/blockable/no-opt-in-blocks.https.html40
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html40
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/keep-scheme-redirect/blockable/no-opt-in-blocks.https.html40
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html40
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/no-redirect/blockable/no-opt-in-blocks.https.html40
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/no-redirect/optionally-blockable/no-opt-in-allows.https.html40
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/swap-scheme-redirect/blockable/no-opt-in-blocks.https.html40
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html40
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/spec.src.json6
-rw-r--r--tests/wpt/web-platform-tests/mixed-content/spec_json.js2
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/idlharness.html8
-rw-r--r--tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-disabled-by-feature-policy.https.html12
-rw-r--r--tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-disabled-by-feature-policy.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html12
-rw-r--r--tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy-attribute.https.html12
-rw-r--r--tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy.https.html12
-rw-r--r--tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html12
-rw-r--r--tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/orientation-sensor/OrientationSensor.https.html87
-rw-r--r--tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-disabled-by-feature-policy.https.html12
-rw-r--r--tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-disabled-by-feature-policy.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html12
-rw-r--r--tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy-attribute.https.html12
-rw-r--r--tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy.https.html12
-rw-r--r--tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html12
-rw-r--r--tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/paint-timing/child-painting-first-image.html2
-rw-r--r--tests/wpt/web-platform-tests/paint-timing/sibling-painting-first-image.html34
-rw-r--r--tests/wpt/web-platform-tests/payment-request/payment-request-constructor.https.html25
-rw-r--r--tests/wpt/web-platform-tests/payment-request/payment-request-not-exposed.https.worker.js11
-rw-r--r--tests/wpt/web-platform-tests/performance-timeline/performanceentry-tojson.html33
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/extension/idlharness.html2
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/idlharness.html2
-rw-r--r--tests/wpt/web-platform-tests/preload/OWNERS2
-rw-r--r--tests/wpt/web-platform-tests/preload/fetch-destination.https.html35
-rw-r--r--tests/wpt/web-platform-tests/preload/modulepreload.html36
-rw-r--r--tests/wpt/web-platform-tests/preload/resources/fetch-destination-worker.js9
-rw-r--r--tests/wpt/web-platform-tests/proximity/idlharness.html2
-rw-r--r--tests/wpt/web-platform-tests/quirks-mode/OWNERS1
-rw-r--r--tests/wpt/web-platform-tests/quirks/active-and-hover-manual.html (renamed from tests/wpt/web-platform-tests/quirks-mode/active-and-hover-manual.html)0
-rw-r--r--tests/wpt/web-platform-tests/quirks/blocks-ignore-line-height.html (renamed from tests/wpt/web-platform-tests/quirks-mode/blocks-ignore-line-height.html)0
-rw-r--r--tests/wpt/web-platform-tests/quirks/classname-query-after-sibling-adoption.html (renamed from tests/wpt/web-platform-tests/quirks-mode/classname-query-after-sibling-adoption.html)0
-rw-r--r--tests/wpt/web-platform-tests/quirks/hashless-hex-color.html (renamed from tests/wpt/web-platform-tests/quirks-mode/hashless-hex-color.html)0
-rw-r--r--tests/wpt/web-platform-tests/quirks/historical/list-item-bullet-size-ref.html (renamed from tests/wpt/web-platform-tests/quirks-mode/historical/list-item-bullet-size-ref.html)0
-rw-r--r--tests/wpt/web-platform-tests/quirks/historical/list-item-bullet-size.html (renamed from tests/wpt/web-platform-tests/quirks-mode/historical/list-item-bullet-size.html)0
-rw-r--r--tests/wpt/web-platform-tests/quirks/line-height-calculation.html (renamed from tests/wpt/web-platform-tests/quirks-mode/line-height-calculation.html)0
-rw-r--r--tests/wpt/web-platform-tests/quirks/percentage-height-calculation.html (renamed from tests/wpt/web-platform-tests/quirks-mode/percentage-height-calculation.html)0
-rw-r--r--tests/wpt/web-platform-tests/quirks/supports.html (renamed from tests/wpt/web-platform-tests/quirks-mode/supports.html)0
-rw-r--r--tests/wpt/web-platform-tests/quirks/table-cell-nowrap-minimum-width-calculation.html (renamed from tests/wpt/web-platform-tests/quirks-mode/table-cell-nowrap-minimum-width-calculation.html)0
-rw-r--r--tests/wpt/web-platform-tests/quirks/table-cell-width-calculation.html (renamed from tests/wpt/web-platform-tests/quirks-mode/table-cell-width-calculation.html)0
-rw-r--r--tests/wpt/web-platform-tests/quirks/unitless-length.html (renamed from tests/wpt/web-platform-tests/quirks-mode/unitless-length.html)0
-rw-r--r--tests/wpt/web-platform-tests/requestidlecallback/idlharness.html2
-rw-r--r--tests/wpt/web-platform-tests/resource-timing/resource-timing-tojson.html51
-rw-r--r--tests/wpt/web-platform-tests/resources/chromium/fake_bluetooth.mojom.js3554
-rw-r--r--tests/wpt/web-platform-tests/resources/chromium/fake_bluetooth.mojom.js.headers (renamed from tests/wpt/web-platform-tests/common/vendor-prefix.js.headers)0
-rw-r--r--tests/wpt/web-platform-tests/resources/chromium/mojo_layouttest_test.mojom.js264
-rw-r--r--tests/wpt/web-platform-tests/resources/chromium/mojo_layouttest_test.mojom.js.headers1
-rw-r--r--tests/wpt/web-platform-tests/resources/chromium/uuid.mojom.js82
-rw-r--r--tests/wpt/web-platform-tests/resources/chromium/uuid.mojom.js.headers1
-rw-r--r--tests/wpt/web-platform-tests/resources/chromium/web-bluetooth-test.js370
-rw-r--r--tests/wpt/web-platform-tests/resources/chromium/web-bluetooth-test.js.headers1
-rw-r--r--tests/wpt/web-platform-tests/resources/idlharness.js99
-rw-r--r--tests/wpt/web-platform-tests/resources/readme.md24
-rw-r--r--tests/wpt/web-platform-tests/resources/test/README.md4
-rw-r--r--tests/wpt/web-platform-tests/resources/test/tests/api-tests-1.html924
-rw-r--r--tests/wpt/web-platform-tests/resources/test/tests/api-tests-2.html2
-rw-r--r--tests/wpt/web-platform-tests/resources/test/tests/api-tests-3.html2
-rw-r--r--tests/wpt/web-platform-tests/resources/test/tests/force_timeout.html64
-rw-r--r--tests/wpt/web-platform-tests/resources/test/tests/generate-callback.html28
-rw-r--r--tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlArray/is_json_type.html3
-rw-r--r--tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlDictionary/get_inheritance_stack.html5
-rw-r--r--tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlInterface/get_inheritance_stack.html5
-rw-r--r--tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlInterface/has_to_json_regular_operation.html5
-rw-r--r--tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlInterface/test_immutable_prototype.html2
-rw-r--r--tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlInterface/test_to_json_operation.html4
-rw-r--r--tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlInterface/traverse_inherited_and_consequential_interfaces.html5
-rw-r--r--tests/wpt/web-platform-tests/resources/test/tests/iframe-consolidate-errors.html4
-rw-r--r--tests/wpt/web-platform-tests/resources/test/tests/iframe-consolidate-tests.html4
-rw-r--r--tests/wpt/web-platform-tests/resources/testdriver-vendor.js1
-rw-r--r--tests/wpt/web-platform-tests/resources/testharness.js21
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/.travis.yml3
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/CHANGELOG.md216
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/README.md301
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/lib/webidl2.js801
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/lib/writer.js16
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/package-lock.json647
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/package.json19
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid.js68
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/array.widl6
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/caller.widl7
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/duplicate.widl5
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/exception.widl6
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/maplike-1type.widl2
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/promise-with-extended-attribute.widl3
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/readonly-iterable.widl2
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/record-key-with-extended-attribute.widl3
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/setlike-2types.widl2
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/setter-creator.widl4
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/special-omittable.widl2
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/typedef-nested.widl2
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/array.json4
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/caller.json4
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/duplicate.json4
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/exception.json4
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/promise-with-extended-attribute.json4
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/record-key-with-extended-attribute.json4
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/setter-creator.json4
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax.js72
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/array.widl5
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/attributes.widl5
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/caller.widl5
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/constants.widl7
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/equivalent-decl.widl2
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/exception-inheritance.widl7
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/exception.widl8
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/extended-attributes.widl14
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/generic.widl4
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/identifier-qualified-names.widl14
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/indexed-properties.widl4
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/iterable.widl8
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/legacyiterable.widl2
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/linecomment.widl2
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/maplike.widl10
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/mixin.widl12
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/overloading.widl4
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/primitives.widl10
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/record.widl4
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/reg-operations.widl2
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/sequence.widl8
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/serializer.widl64
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/setlike.widl8
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/stringifier.widl2
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/typesuffixes.widl2
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/allowany.json17
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/array.json34
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/attributes.json29
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/callback.json11
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/caller.json47
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/constants.json51
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/constructor.json15
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/dictionary-inherits.json4
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/dictionary.json8
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/enum.json21
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/equivalent-decl.json33
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/exception-inheritance.json1
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/exception.json35
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/extended-attributes.json105
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/generic.json24
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/getter-setter.json12
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/identifier-qualified-names.json47
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/implements.json9
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/indexed-properties.json29
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/inherits-getter.json3
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/interface-inherits.json3
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/iterable.json31
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/iterator.json27
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/legacyiterable.json1
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/linecomment.json14
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/maplike.json50
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/mixin.json62
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/namedconstructor.json3
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/namespace.json13
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nointerfaceobject.json10
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nullable.json1
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nullableobjects.json10
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/operation-optional-arg.json11
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/overloading.json36
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/overridebuiltins.json11
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/partial-interface.json2
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/primitives.json17
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/prototyperoot.json7
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/putforwards.json3
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/record.json74
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/reg-operations.json23
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/replaceable.json10
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/sequence.json72
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/serializer.json591
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/setlike.json31
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/static.json12
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier-attribute.json8
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier-custom.json12
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier.json9
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/treatasnull.json9
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/treatasundefined.json9
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/typedef.json20
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/typesuffixes.json8
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/uniontype.json23
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/variadic-operations.json11
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/opt/linecomment.json3
-rw-r--r--tests/wpt/web-platform-tests/secure-contexts/shared-worker-insecure-first.https.html18
-rw-r--r--tests/wpt/web-platform-tests/server-timing/resources/blue.png.sub.headers2
-rw-r--r--tests/wpt/web-platform-tests/server-timing/resources/green.png.sub.headers2
-rw-r--r--tests/wpt/web-platform-tests/server-timing/test_server_timing.html.sub.headers2
-rw-r--r--tests/wpt/web-platform-tests/service-workers/OWNERS1
-rw-r--r--tests/wpt/web-platform-tests/service-workers/cache-storage/script-tests/cache-match.js19
-rw-r--r--tests/wpt/web-platform-tests/service-workers/cache-storage/window/cache-match.https.html1
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/about-blank-replacement.https.html146
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/fetch-cors-exposed-header-names.https.html30
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-respond-with-custom-response.https.html82
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-respond-with-readable-stream.https.html59
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/foreign-fetch-basics.https.html241
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/foreign-fetch-cors.https.html306
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/foreign-fetch-event.https.html9
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/foreign-fetch-workers.https.html88
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/iframe-sandbox-register-link-element.https.html53
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/link-element-register-basic.https.html11
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/link-element-register-mime-types.https.html11
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/link-element-register-scope.https.html12
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/link-element-register-script-url.https.html11
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/link-element-register-script.https.html11
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/link-element-register-security-error.https.html11
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/navigation-redirect.https.html58
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/postmessage.https.html18
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/register-foreign-fetch-errors.https.html8
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/register-link-header.https.html73
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/registration-updateviacache.https.html148
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resource-timing.https.html38
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/about-blank-replacement-frame.py31
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/about-blank-replacement-ping-frame.py48
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/about-blank-replacement-popup-frame.py32
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/about-blank-replacement-uncontrolled-nested-frame.html22
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/about-blank-replacement-worker.js95
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/clients-get-worker.js4
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-cors-exposed-header-names-worker.js3
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-respond-with-custom-response-worker.js45
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-respond-with-readable-stream-iframe.html9
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-respond-with-readable-stream-worker.js36
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-test-worker.js2
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-cors-worker.js30
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-event-worker.js31
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-helper-iframe.html17
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-helper-script.js11
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-helper-worker.js8
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-helpers.js44
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-worker.js78
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/iframe-register-link-element.html16
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/install-worker-helper.html21
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/interfaces-idls.js1
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/interfaces-worker.sub.js15
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/link-header.py4
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/pass.txt1
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/register-foreign-fetch-errors-worker.js134
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/resource-timing-iframe.html4
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/resource-timing-iframe.sub.html6
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/sandboxed-iframe-fetch-event-iframe.html56
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/sandboxed-iframe-fetch-event-worker.js19
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/resources/test-helpers.sub.js24
-rw-r--r--tests/wpt/web-platform-tests/service-workers/service-worker/sandboxed-iframe-fetch-event.https.html216
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/event-composed-path-after-dom-mutation.html59
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/event-inside-shadow-tree.html8
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/slots-fallback.html33
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/slots.html20
-rw-r--r--tests/wpt/web-platform-tests/storage/estimate-parallel.https.html19
-rw-r--r--tests/wpt/web-platform-tests/storage/interfaces.idl10
-rw-r--r--tests/wpt/web-platform-tests/streams/readable-byte-streams/general.js49
-rw-r--r--tests/wpt/web-platform-tests/streams/readable-byte-streams/properties.js2
-rw-r--r--tests/wpt/web-platform-tests/streams/readable-streams/bad-underlying-sources.js26
-rw-r--r--tests/wpt/web-platform-tests/streams/readable-streams/general.js10
-rw-r--r--tests/wpt/web-platform-tests/streams/readable-streams/tee.js14
-rw-r--r--tests/wpt/web-platform-tests/streams/transform-streams/properties.dedicatedworker.html11
-rw-r--r--tests/wpt/web-platform-tests/streams/transform-streams/properties.html10
-rw-r--r--tests/wpt/web-platform-tests/streams/transform-streams/properties.js194
-rw-r--r--tests/wpt/web-platform-tests/streams/transform-streams/properties.serviceworker.https.html12
-rw-r--r--tests/wpt/web-platform-tests/streams/transform-streams/properties.sharedworker.html11
-rw-r--r--tests/wpt/web-platform-tests/streams/transform-streams/strategies.js65
-rw-r--r--tests/wpt/web-platform-tests/streams/writable-streams/bad-strategies.js7
-rw-r--r--tests/wpt/web-platform-tests/streams/writable-streams/bad-underlying-sinks.js46
-rw-r--r--tests/wpt/web-platform-tests/streams/writable-streams/properties.js52
-rw-r--r--tests/wpt/web-platform-tests/svg/extensibility/foreignObject/properties.svg51
-rw-r--r--tests/wpt/web-platform-tests/svg/foreignobject/position-svg-root-in-foreign-object-ref.html6
-rw-r--r--tests/wpt/web-platform-tests/svg/foreignobject/position-svg-root-in-foreign-object.html13
-rw-r--r--tests/wpt/web-platform-tests/svg/import/animate-elem-33-t-manual.svg2
-rw-r--r--tests/wpt/web-platform-tests/svg/interfaces.html2
-rw-r--r--tests/wpt/web-platform-tests/svg/path/bearing/absolute-ref.svg9
-rw-r--r--tests/wpt/web-platform-tests/svg/path/bearing/absolute.svg16
-rw-r--r--tests/wpt/web-platform-tests/svg/path/bearing/relative-ref.svg9
-rw-r--r--tests/wpt/web-platform-tests/svg/path/bearing/relative.svg16
-rw-r--r--tests/wpt/web-platform-tests/svg/path/bearing/zero-ref.svg9
-rw-r--r--tests/wpt/web-platform-tests/svg/path/bearing/zero.svg16
-rw-r--r--tests/wpt/web-platform-tests/svg/path/property/d-interpolation-discrete.svg43
-rw-r--r--tests/wpt/web-platform-tests/svg/path/property/d-interpolation-relative-absolute.svg122
-rw-r--r--tests/wpt/web-platform-tests/svg/path/property/d-interpolation-single.svg245
-rw-r--r--tests/wpt/web-platform-tests/svg/path/property/getComputedStyle.svg52
-rw-r--r--tests/wpt/web-platform-tests/svg/path/property/priority-ref.svg11
-rw-r--r--tests/wpt/web-platform-tests/svg/path/property/priority.svg20
-rw-r--r--tests/wpt/web-platform-tests/svg/path/property/resources/interpolation-test-common.js71
-rw-r--r--tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGClipPathElement.html40
-rw-r--r--tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGComponentTransferFunctionElement.html55
-rw-r--r--tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFEBlendElement.html61
-rw-r--r--tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFEColorMatrixElement.html50
-rw-r--r--tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFECompositeElement.html65
-rw-r--r--tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFEConvolveMatrixElement.html45
-rw-r--r--tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFEDisplacementMapElement.html91
-rw-r--r--tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFEMorphologyElement.html40
-rw-r--r--tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFETurbulenceElement.html71
-rw-r--r--tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFilterElement.html71
-rw-r--r--tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGGradientElement.html76
-rw-r--r--tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGMarkerElement.html113
-rw-r--r--tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGMaskElement.html71
-rw-r--r--tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGPatternElement.html71
-rw-r--r--tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGTextContentElement.html40
-rw-r--r--tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGTextPathElement.html71
-rw-r--r--tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration.html41
-rw-r--r--tests/wpt/web-platform-tests/tools/ci/ci_wpt.sh2
-rw-r--r--tests/wpt/web-platform-tests/tools/ci/lib.sh4
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/lint.py58
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/a-ref.html (renamed from tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/a-ref.html)0
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/a.html (renamed from tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/a.html)0
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/match/a-ref.html (renamed from tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/match/a-ref.html)0
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/match/a.html (renamed from tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/match/a.html)0
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/match/support/a.html (renamed from tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/match/support/a.html)0
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/match/support/tools/a.html (renamed from tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/match/support/tools/a.html)0
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/match/tools/a.html (renamed from tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/match/tools/a.html)0
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/not-match/a-ref.html (renamed from tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/not-match/a-ref.html)0
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/not-match/a.html (renamed from tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/not-match/a.html)0
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/not-match/support/a.html (renamed from tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/not-match/support/a.html)0
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/not-match/tools/a.html (renamed from tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/not-match/tools/a.html)0
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/selectors/a.html (renamed from tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/selectors/a.html)0
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/support/a.html (renamed from tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/support/a.html)0
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/support/tools/a.html (renamed from tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/support/tools/a.html)0
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/tools/a.html (renamed from tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/tools/a.html)0
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/work-in-progress/foo/support/a.html1
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/tests/test_file_lints.py55
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/tests/test_lint.py60
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/tests/test_path_lints.py6
-rw-r--r--tests/wpt/web-platform-tests/tools/localpaths.py7
-rw-r--r--tests/wpt/web-platform-tests/tools/manifest/download.py13
-rw-r--r--tests/wpt/web-platform-tests/tools/manifest/sourcefile.py6
-rw-r--r--tests/wpt/web-platform-tests/tools/manifest/tests/test_sourcefile.py3
-rw-r--r--tests/wpt/web-platform-tests/tools/py/.hgtags67
-rw-r--r--tests/wpt/web-platform-tests/tools/py/CHANGELOG1089
-rw-r--r--tests/wpt/web-platform-tests/tools/py/MANIFEST.in9
-rw-r--r--tests/wpt/web-platform-tests/tools/py/README.txt21
-rw-r--r--tests/wpt/web-platform-tests/tools/py/conftest.py71
-rw-r--r--tests/wpt/web-platform-tests/tools/py/doc/index.txt43
-rw-r--r--tests/wpt/web-platform-tests/tools/py/doc/install.txt88
-rw-r--r--tests/wpt/web-platform-tests/tools/py/doc/misc.txt93
-rw-r--r--tests/wpt/web-platform-tests/tools/py/doc/path.txt260
-rw-r--r--tests/wpt/web-platform-tests/tools/py/py/__init__.py150
-rw-r--r--tests/wpt/web-platform-tests/tools/py/py/_apipkg.py181
-rw-r--r--tests/wpt/web-platform-tests/tools/py/py/_code/_assertionnew.py339
-rw-r--r--tests/wpt/web-platform-tests/tools/py/py/_code/_assertionold.py555
-rw-r--r--tests/wpt/web-platform-tests/tools/py/py/_code/assertion.py94
-rw-r--r--tests/wpt/web-platform-tests/tools/py/py/_code/code.py787
-rw-r--r--tests/wpt/web-platform-tests/tools/py/py/_code/source.py419
-rw-r--r--tests/wpt/web-platform-tests/tools/py/py/_error.py88
-rw-r--r--tests/wpt/web-platform-tests/tools/py/py/_iniconfig.py162
-rw-r--r--tests/wpt/web-platform-tests/tools/py/py/_io/terminalwriter.py348
-rw-r--r--tests/wpt/web-platform-tests/tools/py/py/_log/log.py186
-rw-r--r--tests/wpt/web-platform-tests/tools/py/py/_log/warning.py76
-rw-r--r--tests/wpt/web-platform-tests/tools/py/py/_path/common.py403
-rw-r--r--tests/wpt/web-platform-tests/tools/py/py/_path/local.py911
-rw-r--r--tests/wpt/web-platform-tests/tools/py/py/_path/svnurl.py380
-rw-r--r--tests/wpt/web-platform-tests/tools/py/py/_path/svnwc.py1240
-rw-r--r--tests/wpt/web-platform-tests/tools/py/py/_std.py18
-rw-r--r--tests/wpt/web-platform-tests/tools/py/py/_xmlgen.py253
-rw-r--r--tests/wpt/web-platform-tests/tools/py/setup.cfg5
-rw-r--r--tests/wpt/web-platform-tests/tools/py/setup.py38
-rw-r--r--tests/wpt/web-platform-tests/tools/py/testing/code/test_assertion.py308
-rw-r--r--tests/wpt/web-platform-tests/tools/py/testing/code/test_excinfo.py909
-rw-r--r--tests/wpt/web-platform-tests/tools/py/testing/code/test_source.py651
-rw-r--r--tests/wpt/web-platform-tests/tools/py/testing/io_/test_capture.py501
-rw-r--r--tests/wpt/web-platform-tests/tools/py/testing/io_/test_saferepr.py78
-rw-r--r--tests/wpt/web-platform-tests/tools/py/testing/io_/test_terminalwriter.py271
-rw-r--r--tests/wpt/web-platform-tests/tools/py/testing/log/test_log.py190
-rw-r--r--tests/wpt/web-platform-tests/tools/py/testing/log/test_warning.py76
-rw-r--r--tests/wpt/web-platform-tests/tools/py/testing/path/common.py470
-rw-r--r--tests/wpt/web-platform-tests/tools/py/testing/path/conftest.py80
-rw-r--r--tests/wpt/web-platform-tests/tools/py/testing/path/test_cacheutil.py84
-rw-r--r--tests/wpt/web-platform-tests/tools/py/testing/path/test_local.py860
-rw-r--r--tests/wpt/web-platform-tests/tools/py/testing/path/test_svnauth.py454
-rw-r--r--tests/wpt/web-platform-tests/tools/py/testing/path/test_svnwc.py549
-rw-r--r--tests/wpt/web-platform-tests/tools/py/testing/process/test_cmdexec.py39
-rw-r--r--tests/wpt/web-platform-tests/tools/py/testing/process/test_forkedfunc.py177
-rw-r--r--tests/wpt/web-platform-tests/tools/py/testing/process/test_killproc.py16
-rw-r--r--tests/wpt/web-platform-tests/tools/py/testing/root/test_error.py37
-rw-r--r--tests/wpt/web-platform-tests/tools/py/testing/root/test_py_imports.py68
-rw-r--r--tests/wpt/web-platform-tests/tools/py/testing/root/test_xmlgen.py145
-rw-r--r--tests/wpt/web-platform-tests/tools/py/testing/test_iniconfig.py299
-rw-r--r--tests/wpt/web-platform-tests/tools/py/tox.ini39
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest.ini2
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/.coveragerc7
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/.github/ISSUE_TEMPLATE.md8
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/.github/PULL_REQUEST_TEMPLATE.md8
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/.gitignore34
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/.travis.yml40
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/AUTHORS87
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/CHANGELOG.rst2586
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/CONTRIBUTING.rst253
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/HOWTORELEASE.rst92
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/ISSUES.txt365
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/LICENSE21
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/MANIFEST.in34
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/README.rst102
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/__init__.py2
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/_argcomplete.py101
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/_code/__init__.py12
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/_code/_py2traceback.py81
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/_code/code.py795
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/_code/source.py421
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/_pluggy.py11
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/assertion/__init__.py176
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/assertion/reinterpret.py407
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/assertion/rewrite.py885
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/assertion/util.py332
-rwxr-xr-xtests/wpt/web-platform-tests/tools/pytest/_pytest/cacheprovider.py245
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/capture.py472
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/config.py1192
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/doctest.py290
-rwxr-xr-xtests/wpt/web-platform-tests/tools/pytest/_pytest/genscript.py132
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/helpconfig.py139
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/hookspec.py295
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/impl254
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/junitxml.py387
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/main.py744
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/mark.py311
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/monkeypatch.py254
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/nose.py71
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/pastebin.py92
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/pdb.py109
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/pytester.py1110
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/python.py2302
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/recwarn.py221
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/resultlog.py104
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/runner.py515
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/skipping.py354
-rwxr-xr-xtests/wpt/web-platform-tests/tools/pytest/_pytest/standalonetemplate.py89
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/terminal.py593
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/tmpdir.py123
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/unittest.py205
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/README.md13
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/DESCRIPTION.rst10
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/METADATA39
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/RECORD8
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/metadata.json1
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/pbr.json1
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/top_level.txt1
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy.py777
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/appveyor.yml28
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/Makefile164
-rwxr-xr-xtests/wpt/web-platform-tests/tools/pytest/doc/en/_getdoctarget.py16
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/_templates/globaltoc.html18
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/_templates/layout.html34
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/_templates/links.html16
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/adopt.rst78
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/index.rst48
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.0.2.rst73
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.0.3.rst40
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.2.1.rst41
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.2.4.rst39
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.3.0.rst134
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.3.2.rst57
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.3.3.rst62
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.3.5.rst97
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.4.0.rst225
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.5.0.rst175
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.5.2.rst64
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.6.3.rst52
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.7.0.rst101
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.7.1.rst58
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.9.0.rst159
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.9.1.rst65
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/sprint2016.rst105
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/assert.rst289
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/bash-completion.rst28
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/builtin.rst134
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/cache.rst278
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/capture.rst118
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/conf.py326
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/contact.rst51
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/contents.rst39
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/customize.rst228
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/doctest.rst105
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/example/assertion/failure_demo.py238
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/example/assertion/test_setup_flow_example.py42
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/example/attic.rst79
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/example/costlysetup/conftest.py18
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/example/index.rst34
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/example/layout1/setup.cfg4
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/example/markers.rst592
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/example/multipython.py52
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/example/nonpython.rst91
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/example/nonpython/conftest.py40
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/example/parametrize.rst475
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/example/pythoncollection.py11
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/example/pythoncollection.rst192
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/example/reportingdemo.rst598
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/example/simple.rst751
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/example/special.rst72
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/faq.rst165
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/feedback.rst8
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/fixture.rst987
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/funcarg_compare.rst217
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/genapi.py41
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/getting-started.rst237
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/goodpractices.rst278
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/index.rst61
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/license.rst32
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/links.inc21
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/mark.rst40
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/monkeypatch.rst82
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/nose.rst55
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/overview.rst13
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/parametrize.rst219
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/plugins.rst159
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/projects.rst85
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/recwarn.rst130
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/setup.rst10
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/skipping.rst373
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/status.rst5
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/talks.rst116
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/test/attic.rst117
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/test/mission.rst13
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/cov.rst230
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/coverage.rst51
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/figleaf.rst44
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/genscript.rst28
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/helpconfig.rst38
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/links.rst47
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/nose.rst56
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/terminal.rst40
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/xdist.rst172
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/tmpdir.rst111
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/unittest.rst190
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/usage.rst275
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/writing_plugins.rst575
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/xdist.rst197
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/xunit_setup.rst90
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/doc/en/yieldfixture.rst100
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/extra/get_issues.py74
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/plugin-test.sh20
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/pytest.py28
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/requirements-docs.txt3
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/runtox.py8
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/setup.cfg13
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/setup.py122
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/acceptance_test.py695
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/code/test_code.py174
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/code/test_excinfo.py911
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/code/test_source.py659
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/cx_freeze/install_cx_freeze.py64
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/cx_freeze/runtests_script.py9
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/cx_freeze/runtests_setup.py15
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/cx_freeze/tests/test_trivial.py6
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/cx_freeze/tox_run.py15
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/python/collect.py1200
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/python/fixture.py2693
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/python/integration.py369
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/python/metafunc.py1094
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/python/raises.py78
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_argcomplete.py90
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_assertinterpret.py274
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_assertion.py628
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_assertrewrite.py716
-rwxr-xr-xtests/wpt/web-platform-tests/tools/pytest/testing/test_cache.py386
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_capture.py1068
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_collection.py641
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_config.py570
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_conftest.py409
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_doctest.py715
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_genscript.py51
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_helpconfig.py69
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_junitxml.py816
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_mark.py672
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_monkeypatch.py330
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_nose.py394
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_parseopt.py287
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_pastebin.py115
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_pdb.py313
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_pluginmanager.py340
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_pytester.py122
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_recwarn.py227
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_resultlog.py236
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_runner.py634
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_runner_xunit.py252
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_session.py244
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_skipping.py917
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_terminal.py880
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_tmpdir.py183
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/testing/test_unittest.py737
-rw-r--r--tests/wpt/web-platform-tests/tools/pytest/tox.ini160
-rw-r--r--tests/wpt/web-platform-tests/tools/serve/serve.py87
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/.gitignore9
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/.travis.yml56
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/AUTHORS.rst11
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/CHANGELOG.rst326
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/CODE_OF_CONDUCT.rst55
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/CONTRIBUTING.rst220
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/LICENSE21
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/MANIFEST.in19
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/PULL_REQUEST_TEMPLATE.md12
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/README.rst129
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/.gitignore (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/example/nonpython/__init__.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/261.change.rst4
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/284.change.rst2
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/285.change.rst2
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/286.change.rst2
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/287.change.rst2
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/291.change.rst1
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/292.change.rst1
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/295.change.rst4
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/296.change.rst4
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/conftest.py28
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/dev-requirements.txt6
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/docs-requirements.txt3
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/docs/Makefile177
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/docs/_static/attrs_logo.pngbin0 -> 7639 bytes
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/docs/_static/attrs_logo.svg1
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/docs/api.rst428
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/docs/backward-compatibility.rst19
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/docs/changelog.rst1
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/docs/conf.py155
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/docs/contributing.rst5
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/docs/docutils.conf3
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/docs/examples.rst705
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/docs/extending.rst112
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/docs/how-does-it-work.rst79
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/docs/index.rst80
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/docs/license.rst8
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/docs/overview.rst87
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/docs/why.rst251
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/pyproject.toml26
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/setup.cfg26
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/setup.py95
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/__init__.py55
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/_compat.py139
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/_config.py23
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/_funcs.py212
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/_make.py1395
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/converters.py24
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/exceptions.py48
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/filters.py52
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/validators.py166
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/tests/__init__.py (renamed from tests/wpt/web-platform-tests/webdriver/tests/retrieval/__init__.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_annotations.py156
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_config.py43
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_converters.py36
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_dark_magic.py382
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_dunders.py502
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_filters.py94
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_funcs.py527
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_init_subclass.py44
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_make.py866
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_slots.py423
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_validators.py266
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/tests/utils.py237
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/attrs/tox.ini83
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/funcsigs/.travis.yml17
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/funcsigs/CHANGELOG19
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/funcsigs/LICENSE13
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/funcsigs/MANIFEST.in7
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/funcsigs/Makefile39
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/funcsigs/README.rst83
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/funcsigs/docs/Makefile153
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/funcsigs/docs/_templates/page.html9
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/funcsigs/docs/conf.py251
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/funcsigs/docs/index.rst315
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/funcsigs/funcsigs/__init__.py818
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/funcsigs/funcsigs/odict.py261
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/funcsigs/funcsigs/version.py1
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/funcsigs/requirements/development.txt6
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/funcsigs/requirements/production.txt0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/funcsigs/setup.cfg2
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/funcsigs/setup.py55
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/funcsigs/tests/__init__.py0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/funcsigs/tests/test_formatannotation.py27
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/funcsigs/tests/test_funcsigs.py93
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/funcsigs/tests/test_inspect.py1019
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pluggy/.gitignore58
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pluggy/.travis.yml48
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pluggy/CHANGELOG.rst152
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pluggy/LICENSE22
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pluggy/MANIFEST.in7
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pluggy/README.rst80
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pluggy/appveyor.yml34
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pluggy/docs/_static/img/plug.pngbin0 -> 9350 bytes
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pluggy/docs/api_reference.rst14
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pluggy/docs/conf.py71
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pluggy/docs/examples/firstexample.py44
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pluggy/docs/index.rst705
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pluggy/pluggy/__init__.py684
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pluggy/pluggy/callers.py201
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pluggy/setup.cfg8
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pluggy/setup.py51
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/benchmark.py59
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/conftest.py30
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_details.py103
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_helpers.py68
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_hookrelay.py210
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_method_ordering.py322
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_multicall.py194
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_pluginmanager.py374
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_tracer.py89
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pluggy/tox.ini44
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/.gitattributes1
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/.gitignore12
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/.hgignore (renamed from tests/wpt/web-platform-tests/tools/py/.hgignore)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/.hgtags68
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/.travis.yml27
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/AUTHORS (renamed from tests/wpt/web-platform-tests/tools/py/AUTHORS)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/CHANGELOG1149
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/LICENSE (renamed from tests/wpt/web-platform-tests/tools/py/LICENSE)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/MANIFEST.in10
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/README.rst34
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/appveyor.yml26
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/bench/localpath.py (renamed from tests/wpt/web-platform-tests/tools/py/bench/localpath.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/conftest.py60
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/Makefile (renamed from tests/wpt/web-platform-tests/tools/py/doc/Makefile)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/_templates/layout.html (renamed from tests/wpt/web-platform-tests/tools/py/doc/_templates/layout.html)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-0.9.0.txt (renamed from tests/wpt/web-platform-tests/tools/py/doc/announce/release-0.9.0.txt)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-0.9.2.txt (renamed from tests/wpt/web-platform-tests/tools/py/doc/announce/release-0.9.2.txt)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.0.0.txt (renamed from tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.0.0.txt)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.0.1.txt (renamed from tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.0.1.txt)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.0.2.txt (renamed from tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.0.2.txt)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.1.0.txt (renamed from tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.1.0.txt)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.1.1.txt (renamed from tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.1.1.txt)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.2.0.txt (renamed from tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.2.0.txt)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.2.1.txt (renamed from tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.2.1.txt)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.3.0.txt (renamed from tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.0.txt)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.3.1.txt (renamed from tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.1.txt)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.3.2.txt (renamed from tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.2.txt)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.3.3.txt (renamed from tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.3.txt)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.3.4.txt (renamed from tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.4.txt)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.4.0.txt (renamed from tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.4.0.txt)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.4.1.txt (renamed from tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.4.1.txt)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/releases.txt (renamed from tests/wpt/web-platform-tests/tools/py/doc/announce/releases.txt)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/changelog.txt (renamed from tests/wpt/web-platform-tests/tools/py/doc/changelog.txt)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/code.txt (renamed from tests/wpt/web-platform-tests/tools/py/doc/code.txt)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/conf.py (renamed from tests/wpt/web-platform-tests/tools/py/doc/conf.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/download.html (renamed from tests/wpt/web-platform-tests/tools/py/doc/download.html)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/example/genhtml.py (renamed from tests/wpt/web-platform-tests/tools/py/doc/example/genhtml.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/example/genhtmlcss.py (renamed from tests/wpt/web-platform-tests/tools/py/doc/example/genhtmlcss.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/example/genxml.py (renamed from tests/wpt/web-platform-tests/tools/py/doc/example/genxml.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/faq.txt (renamed from tests/wpt/web-platform-tests/tools/py/doc/faq.txt)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/img/pylib.png (renamed from tests/wpt/web-platform-tests/tools/py/doc/img/pylib.png)bin8276 -> 8276 bytes
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/index.txt39
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/install.txt88
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/io.txt (renamed from tests/wpt/web-platform-tests/tools/py/doc/io.txt)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/links.inc (renamed from tests/wpt/web-platform-tests/tools/py/doc/links.inc)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/log.txt (renamed from tests/wpt/web-platform-tests/tools/py/doc/log.txt)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/misc.txt93
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/path.txt258
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/style.css (renamed from tests/wpt/web-platform-tests/tools/py/doc/style.css)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/doc/xml.txt (renamed from tests/wpt/web-platform-tests/tools/py/doc/xml.txt)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/__init__.py154
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/__metainfo.py (renamed from tests/wpt/web-platform-tests/tools/py/py/__metainfo.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_builtin.py (renamed from tests/wpt/web-platform-tests/tools/py/py/_builtin.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_code/__init__.py (renamed from tests/wpt/web-platform-tests/tools/py/py/_code/__init__.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_code/_assertionnew.py322
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_code/_assertionold.py556
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_code/_py2traceback.py (renamed from tests/wpt/web-platform-tests/tools/py/py/_code/_py2traceback.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_code/assertion.py90
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_code/code.py796
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_code/source.py410
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_error.py91
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_io/__init__.py (renamed from tests/wpt/web-platform-tests/tools/py/py/_io/__init__.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_io/capture.py (renamed from tests/wpt/web-platform-tests/tools/py/py/_io/capture.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_io/saferepr.py (renamed from tests/wpt/web-platform-tests/tools/py/py/_io/saferepr.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_io/terminalwriter.py384
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_log/__init__.py (renamed from tests/wpt/web-platform-tests/tools/py/py/_log/__init__.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_log/log.py206
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_log/warning.py79
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_path/__init__.py (renamed from tests/wpt/web-platform-tests/tools/py/py/_path/__init__.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_path/cacheutil.py (renamed from tests/wpt/web-platform-tests/tools/py/py/_path/cacheutil.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_path/common.py453
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_path/local.py992
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_path/svnurl.py380
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_path/svnwc.py1240
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_process/__init__.py (renamed from tests/wpt/web-platform-tests/tools/py/py/_process/__init__.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_process/cmdexec.py (renamed from tests/wpt/web-platform-tests/tools/py/py/_process/cmdexec.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_process/forkedfunc.py (renamed from tests/wpt/web-platform-tests/tools/py/py/_process/forkedfunc.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_process/killproc.py (renamed from tests/wpt/web-platform-tests/tools/py/py/_process/killproc.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_std.py26
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/__init__.py0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/DESCRIPTION.rst87
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/INSTALLER1
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/METADATA109
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/RECORD9
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/WHEEL (renamed from tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/WHEEL)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/metadata.json1
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/top_level.txt1
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg.py205
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/DESCRIPTION.rst53
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/INSTALLER1
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/METADATA78
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/RECORD9
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/WHEEL5
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/metadata.json1
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/top_level.txt1
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig.py165
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/_xmlgen.py255
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/py/test.py (renamed from tests/wpt/web-platform-tests/tools/py/py/test.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/setup.cfg8
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/setup.py53
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/tasks/__init__.py12
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/tasks/vendoring.py23
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/code/test_assertion.py305
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/code/test_code.py (renamed from tests/wpt/web-platform-tests/tools/py/testing/code/test_code.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/code/test_excinfo.py956
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/code/test_source.py648
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/conftest.py (renamed from tests/wpt/web-platform-tests/tools/py/testing/conftest.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/io_/__init__.py (renamed from tests/wpt/web-platform-tests/tools/py/testing/io_/__init__.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/io_/test_capture.py501
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/io_/test_saferepr.py75
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/io_/test_terminalwriter.py292
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/log/__init__.py0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/log/test_log.py191
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/log/test_warning.py86
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/path/common.py492
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/path/conftest.py80
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/path/repotest.dump (renamed from tests/wpt/web-platform-tests/tools/py/testing/path/repotest.dump)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/path/svntestbase.py (renamed from tests/wpt/web-platform-tests/tools/py/testing/path/svntestbase.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/path/test_cacheutil.py89
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/path/test_local.py977
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/path/test_svnauth.py460
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/path/test_svnurl.py (renamed from tests/wpt/web-platform-tests/tools/py/testing/path/test_svnurl.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/path/test_svnwc.py557
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/process/__init__.py (renamed from tests/wpt/web-platform-tests/tools/py/testing/process/__init__.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/process/test_cmdexec.py41
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/process/test_forkedfunc.py173
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/process/test_killproc.py18
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/root/__init__.py (renamed from tests/wpt/web-platform-tests/tools/py/testing/root/__init__.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/root/test_builtin.py (renamed from tests/wpt/web-platform-tests/tools/py/testing/root/test_builtin.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/root/test_error.py68
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/root/test_py_imports.py71
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/root/test_std.py (renamed from tests/wpt/web-platform-tests/tools/py/testing/root/test_std.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/testing/root/test_xmlgen.py146
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/py/tox.ini33
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/.gitattributes (renamed from tests/wpt/web-platform-tests/tools/pytest/.gitattributes)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/.github/ISSUE_TEMPLATE.md8
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/.github/PULL_REQUEST_TEMPLATE.md15
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/.gitignore39
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/.travis.yml56
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/AUTHORS189
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/CHANGELOG.rst4194
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/CONTRIBUTING.rst278
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/HOWTORELEASE.rst65
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/LICENSE21
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/README.rst109
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/__init__.py8
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/_argcomplete.py103
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/_code/__init__.py10
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/_code/_py2traceback.py85
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/_code/code.py906
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/_code/source.py415
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/assertion/__init__.py146
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/assertion/rewrite.py948
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/assertion/truncate.py102
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/assertion/util.py308
-rwxr-xr-xtests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/cacheprovider.py260
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/capture.py683
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/compat.py322
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/config.py1400
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/debugging.py123
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/deprecated.py52
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/doctest.py369
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/fixtures.py1147
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/freeze_support.py43
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/helpconfig.py184
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/hookspec.py423
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/junitxml.py453
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/logging.py337
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/main.py821
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/mark.py496
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/monkeypatch.py258
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/nodes.py37
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/nose.py72
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/outcomes.py147
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/pastebin.py100
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/pytester.py1187
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/python.py1175
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/python_api.py619
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/recwarn.py236
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/resultlog.py113
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/runner.py506
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/setuponly.py74
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/setupplan.py25
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/skipping.py397
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/terminal.py703
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/tmpdir.py126
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/unittest.py237
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/warnings.py96
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/appveyor.yml44
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/bench/bench.py (renamed from tests/wpt/web-platform-tests/tools/pytest/bench/bench.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/bench/bench_argcomplete.py (renamed from tests/wpt/web-platform-tests/tools/pytest/bench/bench_argcomplete.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/bench/empty.py (renamed from tests/wpt/web-platform-tests/tools/pytest/bench/empty.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/bench/manyparam.py (renamed from tests/wpt/web-platform-tests/tools/pytest/bench/manyparam.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/bench/skip.py (renamed from tests/wpt/web-platform-tests/tools/pytest/bench/skip.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2920.bugfix1
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2949.trivial1
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2956.bugfix1
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2957.bugfix1
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2963.doc1
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2971.bugfix1
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2984.bugfix1
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/_template.rst40
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/Makefile150
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_templates/globaltoc.html19
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_templates/layout.html20
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_templates/links.html11
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_templates/sidebarintro.html (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/_templates/sidebarintro.html)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_themes/.gitignore (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/_themes/.gitignore)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_themes/LICENSE (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/_themes/LICENSE)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_themes/README (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/_themes/README)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_themes/flask/layout.html (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/_themes/flask/layout.html)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_themes/flask/relations.html (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/_themes/flask/relations.html)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_themes/flask/static/flasky.css_t (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/_themes/flask/static/flasky.css_t)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_themes/flask/theme.conf (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/_themes/flask/theme.conf)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_themes/flask_theme_support.py (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/_themes/flask_theme_support.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/adopt.rst82
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/index.rst68
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.0.0.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.0.0.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.0.1.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.0.1.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.0.2.rst73
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.0.3.rst40
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.1.0.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.1.0.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.1.1.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.1.1.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.1.2.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.1.2.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.1.3.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.1.3.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.2.0.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.2.0.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.2.1.rst41
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.2.2.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.2.2.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.2.4.rst39
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.3.0.rst134
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.3.1.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.3.1.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.3.2.rst57
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.3.3.rst62
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.3.4.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.3.4.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.3.5.rst97
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.4.0.rst225
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.4.1.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.4.1.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.4.2.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.4.2.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.5.0.rst175
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.5.1.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.5.1.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.5.2.rst64
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.6.0.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.6.0.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.6.1.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.6.1.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.6.2.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.6.2.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.6.3.rst52
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.7.0.rst101
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.7.1.rst58
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.7.2.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.7.2.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.8.2.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.8.2.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.8.3.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.8.3.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.8.4.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.8.4.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.8.5.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.8.5.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.8.6.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.8.6.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.8.7.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.8.7.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.9.0.rst159
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.9.1.rst67
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.9.2.rst78
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.0.rst82
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.1.rst26
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.2.rst24
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.3.rst27
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.4.rst29
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.5.rst27
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.6.rst33
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.7.rst33
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.1.0.rst61
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.1.1.rst23
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.1.2.rst23
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.1.3.rst23
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.2.0.rst48
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.2.1.rst22
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.2.2.rst28
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.2.3.rst23
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.2.4.rst36
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.2.5.rst18
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.3.0.rst50
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/sprint2016.rst64
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/assert.rst299
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/backwards-compatibility.rst105
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/bash-completion.rst28
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/builtin.rst161
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/cache.rst268
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/capture.rst148
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/changelog.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/changelog.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/check_sphinx.py (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/check_sphinx.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/conf.py323
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/conftest.py (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/conftest.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/contact.rst50
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/contents.rst65
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/contributing.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/contributing.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/customize.rst333
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/development_guide.rst108
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/doctest.rst165
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/assertion/failure_demo.py238
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/assertion/global_testmodule_config/conftest.py (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/example/assertion/global_testmodule_config/conftest.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/assertion/global_testmodule_config/test_hello.py (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/example/assertion/global_testmodule_config/test_hello.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/assertion/test_failures.py (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/example/assertion/test_failures.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/assertion/test_setup_flow_example.py42
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/attic.rst79
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/conftest.py (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/example/conftest.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/costlysetup/conftest.py18
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/costlysetup/sub1/__init__.py (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/example/costlysetup/sub1/__init__.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/costlysetup/sub1/test_quick.py (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/example/costlysetup/sub1/test_quick.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/costlysetup/sub2/__init__.py (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/example/costlysetup/sub2/__init__.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/costlysetup/sub2/test_two.py (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/example/costlysetup/sub2/test_two.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/index.rst34
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/markers.rst642
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/multipython.py52
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/nonpython.rst91
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/nonpython/__init__.py0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/nonpython/conftest.py40
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/nonpython/test_simple.yml (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/example/nonpython/test_simple.yml)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/parametrize.rst536
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/py2py3/conftest.py (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/example/py2py3/conftest.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/py2py3/test_py2.py (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/example/py2py3/test_py2.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/py2py3/test_py3.py (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/example/py2py3/test_py3.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/pythoncollection.py11
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/pythoncollection.rst239
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/reportingdemo.rst604
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/simple.rst847
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/special.rst72
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/xfail_demo.py (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/example/xfail_demo.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/existingtestsuite.rst34
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/faq.rst156
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/fixture.rst1088
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/funcarg_compare.rst218
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/funcargs.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/funcargs.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/genapi.py41
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/getting-started.rst198
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/goodpractices.rst299
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/historical-notes.rst177
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/cramer2.png (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/img/cramer2.png)bin25291 -> 25291 bytes
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/freiburg2.jpg (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/img/freiburg2.jpg)bin104057 -> 104057 bytes
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/gaynor3.png (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/img/gaynor3.png)bin23032 -> 23032 bytes
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/keleshev.png (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/img/keleshev.png)bin23246 -> 23246 bytes
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/pullrequest.png (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/img/pullrequest.png)bin17035 -> 17035 bytes
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/pylib.png (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/img/pylib.png)bin8276 -> 8276 bytes
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/pytest1.png (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/img/pytest1.png)bin6010 -> 6010 bytes
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/pytest1favi.ico (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/img/pytest1favi.ico)bin3742 -> 3742 bytes
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/theuni.png (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/img/theuni.png)bin31476 -> 31476 bytes
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/index.rst90
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/license.rst32
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/links.inc21
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/logging.rst192
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/mark.rst41
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/monkeypatch.rst75
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/naming20.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/naming20.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/nose.rst75
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/parametrize.rst217
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/plugins.rst154
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/projects.rst85
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/proposals/parametrize_with_fixtures.rst160
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/pytest.ini (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/pytest.ini)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/pythonpath.rst76
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/recwarn.rst3
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/requirements.txt3
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/skipping.rst378
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/talks.rst105
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/attic.rst117
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/config.html (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/test/config.html)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/dist.html (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/test/dist.html)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/extend.html (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/test/extend.html)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/index.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/test/index.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/mission.rst13
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/cov.rst230
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/coverage.rst51
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/django.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/django.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/figleaf.rst44
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/helpconfig.rst36
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/index.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/index.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/links.rst45
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/nose.rst56
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/oejskit.rst (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/oejskit.rst)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/terminal.rst38
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/xdist.rst172
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/test.html (renamed from tests/wpt/web-platform-tests/tools/pytest/doc/en/test/test.html)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/tmpdir.rst111
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/unittest.rst245
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/usage.rst392
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/warnings.rst299
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/writing_plugins.rst739
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/xunit_setup.rst99
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/yieldfixture.rst18
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/extra/get_issues.py84
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/extra/setup-py.test/setup.py (renamed from tests/wpt/web-platform-tests/tools/pytest/extra/setup-py.test/setup.py)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/pyproject.toml35
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/pytest.py77
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/scripts/call-tox.bat8
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/scripts/check-rst.py11
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/scripts/install-pypy.bat6
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/setup.cfg20
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/setup.py114
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/tasks/__init__.py12
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/tasks/generate.py162
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/tasks/release.minor.rst27
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/tasks/release.patch.rst17
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/tasks/requirements.txt5
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/acceptance_test.py850
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/code/test_code.py196
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/code/test_excinfo.py1245
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/code/test_source.py680
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/code/test_source_multiline_block.py26
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/deprecated_test.py127
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/freeze/.gitignore3
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/freeze/create_executable.py12
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/freeze/runtests_script.py9
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/freeze/tests/test_doctest.txt (renamed from tests/wpt/web-platform-tests/tools/pytest/testing/cx_freeze/tests/test_doctest.txt)0
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/freeze/tests/test_trivial.py7
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/freeze/tox_run.py12
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/logging/test_fixture.py70
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/logging/test_reporting.py398
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/approx.py392
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/collect.py1402
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/fixture.py3171
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/integration.py384
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/metafunc.py1561
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/raises.py134
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/setup_only.py243
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/setup_plan.py19
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/show_fixtures_per_test.py158
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/test_deprecations.py22
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_argcomplete.py97
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_assertion.py1066
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_assertrewrite.py996
-rwxr-xr-xtests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_cache.py605
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_capture.py1274
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_collection.py857
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_compat.py101
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_config.py862
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_conftest.py478
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_doctest.py1003
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_entry_points.py14
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_helpconfig.py77
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_junitxml.py1062
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_mark.py878
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_modimport.py25
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_monkeypatch.py329
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_nodes.py18
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_nose.py409
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_parseopt.py309
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_pastebin.py117
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_pdb.py406
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_pluginmanager.py361
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_pytester.py149
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_recwarn.py310
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_resultlog.py228
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_runner.py813
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_runner_xunit.py319
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_session.py255
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_skipping.py1067
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_terminal.py1039
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_tmpdir.py188
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_unittest.py830
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_warnings.py258
-rw-r--r--tests/wpt/web-platform-tests/tools/third_party/pytest/tox.ini220
-rw-r--r--tests/wpt/web-platform-tests/tools/tox.ini2
-rw-r--r--tests/wpt/web-platform-tests/tools/webdriver/webdriver/client.py15
-rw-r--r--tests/wpt/web-platform-tests/tools/webdriver/webdriver/error.py20
-rw-r--r--tests/wpt/web-platform-tests/tools/webdriver/webdriver/transport.py1
-rw-r--r--tests/wpt/web-platform-tests/tools/wptrunner/OWNERS1
-rw-r--r--tests/wpt/web-platform-tests/tools/wptrunner/docs/conf.py2
-rw-r--r--tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/firefox.py5
-rw-r--r--tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/ie.py2
-rw-r--r--tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/servo.py2
-rw-r--r--tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/environment.py12
-rw-r--r--tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/executors/base.py12
-rw-r--r--tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/executors/executormarionette.py54
-rw-r--r--tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py59
-rw-r--r--tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/stability.py42
-rw-r--r--tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testdriver-vendor.js1
-rw-r--r--tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testloader.py6
-rw-r--r--tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testrunner.py29
-rw-r--r--tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/update/sync.py1
-rw-r--r--tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/update/update.py5
-rw-r--r--tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptcommandline.py5
-rw-r--r--tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptlogging.py17
-rw-r--r--tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptrunner.py10
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/docs/pipes.rst4
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_pipes.py6
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/wptserve/pipes.py7
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/wptserve/server.py3
-rw-r--r--tests/wpt/web-platform-tests/touch-events/multi-touch-interactions-manual.html44
-rw-r--r--tests/wpt/web-platform-tests/touch-events/multi-touch-interactions.js674
-rw-r--r--tests/wpt/web-platform-tests/touch-events/multi-touch-interfaces-manual.html186
-rw-r--r--tests/wpt/web-platform-tests/uievents/mouse/layout_change_should_fire_mouseover-manual.html83
-rwxr-xr-xtests/wpt/web-platform-tests/update-built-tests.sh1
-rw-r--r--tests/wpt/web-platform-tests/url/setters_tests.json44
-rw-r--r--tests/wpt/web-platform-tests/url/urltestdata.json80
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/alertdialog_modal_false-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/alertdialog_modal_true-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/application_activedescendant-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/application_activedescendant_value_changes-manual.html6
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/aria-current_not_declared-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_changes-manual.html6
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_date-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_location-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_page-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_step-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_time-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_true-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_unspecified-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/article_in_feed_posinset_and_setsize-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/article_in_feed_setsize_-1-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/article_not_in_feed_posinset_and_setsize-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/button_haspopup_unspecified-manual.html8
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/button_roledescription_empty-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/button_roledescription_valid-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/button_roledescription_whitespace_only-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/cell-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/cell_aria-colspan_2_on_div-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/cell_aria-colspan_2_on_td_html_colspan_3-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/cell_aria-colspan_2_on_td_html_colspan_3_with_headers_and_border-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/cell_aria-colspan_2_on_td_html_colspan_3_with_three_actual_columns-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/cell_aria-colspan_2_on_td_with_html_colspan_not_specified-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/cell_aria-rowspan_2_on_div-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/cell_aria-rowspan_2_on_td_html_rowspan_3-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/cell_aria-rowspan_2_on_td_html_rowspan_3_with_three_actual_rows-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/cell_aria-rowspan_2_on_td_with_html_rowspan_not_specified-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/cell_colindex_4-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/cell_rowindex_4-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/checkbox_readonly_false-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/checkbox_readonly_true-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/checkbox_readonly_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/columnheader_aria-colspan_2_on_div-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/columnheader_aria-colspan_2_on_th_html_colspan_3-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/columnheader_aria-colspan_2_on_th_html_colspan_3_with_three_actual_columns-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/columnheader_aria-colspan_2_on_th_with_html_colspan_not_specified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/columnheader_aria-rowspan_2_on_div-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/columnheader_aria-rowspan_2_on_th_html_rowspan_3-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/columnheader_aria-rowspan_2_on_th_html_rowspan_3_with_three_actual_rows-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/columnheader_aria-rowspan_2_on_th_with_html_rowspan_not_specified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/columnheader_colindex_4-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/columnheader_rowindex_4-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/columnheader_selected_false_not_automatically_propagated-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/columnheader_selected_true_not_automatically_propagated-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_dialog-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_false-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_grid-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_listbox-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_menu-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_tree-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_true-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/combobox_orientation_horizontal-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/combobox_orientation_unspecified-manual.html12
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/combobox_orientation_vertical-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/combobox_readonly_false-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/combobox_readonly_true-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/combobox_readonly_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/dialog_modal_false-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/dialog_modal_true-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/dialog_modal_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/div_element_without_role_roledescription_valid-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/errormessage_object_in_valid_state-manual.html6
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/feed-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/figure-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/grid_aria-readonly_false_automatically_propagated-manual.html6
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/grid_aria-readonly_true_automatically_propagated-manual.html8
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/grid_busy_false-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/grid_busy_true-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/grid_busy_value_changes-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/grid_colcount_8-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/grid_columnheader_readonly_false-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/grid_columnheader_readonly_true-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/grid_columnheader_readonly_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/grid_columnheader_required_false-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/grid_columnheader_required_true-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/grid_columnheader_required_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/grid_rowcount_3-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/grid_rowheader_readonly_false-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/grid_rowheader_readonly_true-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/grid_rowheader_readonly_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/grid_rowheader_required_false-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/grid_rowheader_required_true-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/grid_rowheader_required_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/gridcell_aria-colspan_2_on_div-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/gridcell_aria-rowspan_2_on_div-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/gridcell_colindex_4-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/gridcell_rowindex_4-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/group_hidden_undefined_element_not_rendered-manual.html10
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/group_hidden_undefined_element_rendered-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/heading_level_unspecified-manual.html6
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/keyshortcuts_multiple_shortcuts-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/keyshortcuts_one_shortcut-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/listbox_busy_false-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/listbox_busy_true-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/listbox_orientation_horizontal-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/listbox_orientation_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/listbox_orientation_vertical-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/listbox_readonly_false-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/listbox_readonly_true-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/listbox_readonly_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/listitem_setsize_-1-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/menu_orientation_horizontal-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/menu_orientation_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/menu_orientation_vertical-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/menubar_busy_false-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/menubar_busy_true-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/menubar_orientation_horizontal-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/menubar_orientation_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/menubar_orientation_vertical-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/menuitem_posinset_and_setsize-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/menuitemcheckbox_posinset_and_setsize-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/menuitemcheckbox_readonly_false-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/menuitemcheckbox_readonly_true-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/menuitemcheckbox_readonly_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/menuitemradio_posinset_and_setsize-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/menuitemradio_readonly_false-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/menuitemradio_readonly_true-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/menuitemradio_readonly_unspecified-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/none-manual.html10
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/option_selected_false-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/option_selected_true-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/option_selected_undefined-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/radiogroup_orientation_horizontal-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/radiogroup_orientation_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/radiogroup_orientation_vertical-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/radiogroup_readonly_false-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/radiogroup_readonly_true-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/radiogroup_readonly_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/row_colindex_4-manual.html16
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/row_rowindex_4-manual.html16
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/rowheader_aria-colspan_2_on_div-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/rowheader_aria-rowspan_2_on_div-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/rowheader_colindex_4-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/rowheader_rowindex_4-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/rowheader_selected_false_not_automatically_propagated-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/rowheader_selected_true_not_automatically_propagated-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/scrollbar_all_values_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/scrollbar_only_valuenow_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/scrollbar_orientation_unspecified-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/searchbox-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/searchbox_activedescendant-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/searchbox_activedescendant_value_changes-manual.html6
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/searchbox_autocomplete_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/searchbox_multiline_false-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/searchbox_multiline_true-manual.html10
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/searchbox_multiline_unspecified-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/searchbox_placeholder-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/searchbox_readonly_false-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/searchbox_readonly_true-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/searchbox_readonly_unspecified-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/searchbox_required_false-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/searchbox_required_true-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/searchbox_required_unspecified-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/separator_focusable_all_values_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/separator_focusable_only_valuenow_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/separator_focusable_valuetext-manual.html8
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/separator_orientation_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/separator_unfocusable_all_values_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/separator_unfocusable_valuetext-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/slider_all_values_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/slider_only_valuenow_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/slider_orientation_unspecified-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/slider_readonly_false-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/slider_readonly_true-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/slider_readonly_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/spinbutton_all_values_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/spinbutton_only_aria-valuenow_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/spinbutton_readonly_false-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/spinbutton_readonly_true-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/spinbutton_readonly_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/switch_checked_false-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/switch_checked_mixed-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/switch_checked_true-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/switch_checked_undefined-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/switch_checked_value_changes-manual.html6
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/switch_readonly_false-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/switch_readonly_true-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/switch_readonly_unspecified-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/tab_posinset_and_setsize-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/table_colcount_-1-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/table_colcount_8-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/table_rowcount_-1-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/table_rowcount_3-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/tablist_orientation_horizontal-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/tablist_orientation_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/tablist_orientation_vertical-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/term_role-manual.html4
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/textbox_placeholder-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/toolbar_orientation_horizontal-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/toolbar_orientation_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/toolbar_orientation_vertical-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/tree_orientation_horizontal-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/tree_orientation_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/tree_orientation_vertical-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/treegrid_colcount_8-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/treegrid_orientation_horizontal-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/treegrid_orientation_unspecified-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/treegrid_orientation_vertical-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/treegrid_rowcount_3-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/treeitem_selected_false-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/treeitem_selected_true-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wai-aria/treeitem_selected_undefined-manual.html2
-rw-r--r--tests/wpt/web-platform-tests/wake-lock/wakelock-api.https.html6
-rw-r--r--tests/wpt/web-platform-tests/wake-lock/wakelock-applicability-manual.https.html51
-rw-r--r--tests/wpt/web-platform-tests/wake-lock/wakelock-cancel-twice.https.html20
-rw-r--r--tests/wpt/web-platform-tests/wake-lock/wakelock-disabled-by-feature-policy.https.sub.html6
-rw-r--r--tests/wpt/web-platform-tests/wake-lock/wakelock-document-hidden.https.html27
-rw-r--r--tests/wpt/web-platform-tests/wake-lock/wakelock-enabled-by-feature-policy-attribute-redirect-on-load.https.sub.html6
-rw-r--r--tests/wpt/web-platform-tests/wake-lock/wakelock-enabled-by-feature-policy-attribute.https.sub.html6
-rw-r--r--tests/wpt/web-platform-tests/wake-lock/wakelock-enabled-by-feature-policy.https.sub.html6
-rw-r--r--tests/wpt/web-platform-tests/wake-lock/wakelock-enabled-on-self-origin-by-feature-policy.https.sub.html6
-rw-r--r--tests/wpt/web-platform-tests/wake-lock/wakelock-insecure-context.html13
-rw-r--r--tests/wpt/web-platform-tests/wake-lock/wakelock-object-is-independent.https.html85
-rw-r--r--tests/wpt/web-platform-tests/wake-lock/wakelock-onactivechange.https.html4
-rw-r--r--tests/wpt/web-platform-tests/wake-lock/wakelock-promise.https.html13
-rw-r--r--tests/wpt/web-platform-tests/wake-lock/wakelock-state-is-global.https.html73
-rw-r--r--tests/wpt/web-platform-tests/wake-lock/wakelock-type.https.html4
-rw-r--r--tests/wpt/web-platform-tests/wake-lock/wakelockrequest-is-independent.https.html15
-rw-r--r--tests/wpt/web-platform-tests/wasm/many-memories.window.js4
-rw-r--r--tests/wpt/web-platform-tests/wasm/wasm_local_iframe_test.html24
-rw-r--r--tests/wpt/web-platform-tests/web-animations/README.md12
-rw-r--r--tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/accumulation-per-property.html23
-rw-r--r--tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/addition-per-property.html23
-rw-r--r--tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/discrete-animation.html135
-rw-r--r--tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/discrete.html135
-rw-r--r--tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/interpolation-per-property.html23
-rw-r--r--tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/property-list.js54
-rw-r--r--tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/property-types.js2062
-rw-r--r--tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/visibility.html57
-rw-r--r--tests/wpt/web-platform-tests/web-animations/animation-model/combining-effects/effect-composition.html56
-rw-r--r--tests/wpt/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-context.html60
-rw-r--r--tests/wpt/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html819
-rw-r--r--tests/wpt/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-overlapping-keyframes.html38
-rw-r--r--tests/wpt/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance.html29
-rw-r--r--tests/wpt/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-visibility.html55
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/Animatable/animate-no-browsing-context.html13
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/Animatable/animate.html152
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/Animatable/getAnimations.html156
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/Animation/cancel.html36
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/Animation/constructor.html87
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/Animation/effect.html28
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/Animation/finish.html140
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/Animation/finished.html273
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/Animation/id.html16
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/Animation/idlharness.html3
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/Animation/oncancel.html16
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/Animation/onfinish.html70
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/Animation/pause.html60
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/Animation/pending.html35
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/Animation/play.html18
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/Animation/playState.html53
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/Animation/playbackRate.html46
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/Animation/ready.html36
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/Animation/startTime.html36
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/delay.html77
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/direction.html104
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/duration.html186
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/easing.html70
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/endDelay.html84
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/fill.html25
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/getAnimations.html91
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/getComputedStyle.html172
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/getComputedTiming.html201
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/idlharness.html4
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/iterationStart.html84
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/iterations.html89
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/AnimationPlaybackEvent/constructor.html6
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/AnimationPlaybackEvent/idlharness.html2
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/Document/getAnimations.html32
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/Document/timeline.html4
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/DocumentTimeline/constructor.html20
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/DocumentTimeline/idlharness.html2
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/composite.html24
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/constructor.html108
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/copy-constructor.html14
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/getComputedTiming.html212
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/idlharness.html4
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/iterationComposite.html824
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001.html6
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-002.html4
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/setKeyframes.html36
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/setTarget.html89
-rw-r--r--tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/target.html89
-rw-r--r--tests/wpt/web-platform-tests/web-animations/resources/easing-tests.js4
-rw-r--r--tests/wpt/web-platform-tests/web-animations/resources/effect-tests.js4
-rw-r--r--tests/wpt/web-platform-tests/web-animations/testcommon.js120
-rw-r--r--tests/wpt/web-platform-tests/web-animations/timing-model/animation-effects/active-time.html123
-rw-r--r--tests/wpt/web-platform-tests/web-animations/timing-model/animation-effects/current-iteration.html12
-rw-r--r--tests/wpt/web-platform-tests/web-animations/timing-model/animation-effects/local-time.html19
-rw-r--r--tests/wpt/web-platform-tests/web-animations/timing-model/animation-effects/phases-and-states.html177
-rw-r--r--tests/wpt/web-platform-tests/web-animations/timing-model/animation-effects/simple-iteration-progress.html4
-rw-r--r--tests/wpt/web-platform-tests/web-animations/timing-model/animations/canceling-an-animation.html54
-rw-r--r--tests/wpt/web-platform-tests/web-animations/timing-model/animations/current-time.html37
-rw-r--r--tests/wpt/web-platform-tests/web-animations/timing-model/animations/finishing-an-animation.html4
-rw-r--r--tests/wpt/web-platform-tests/web-animations/timing-model/animations/pausing-an-animation.html6
-rw-r--r--tests/wpt/web-platform-tests/web-animations/timing-model/animations/play-states.html157
-rw-r--r--tests/wpt/web-platform-tests/web-animations/timing-model/animations/playing-an-animation.html18
-rw-r--r--tests/wpt/web-platform-tests/web-animations/timing-model/animations/reversing-an-animation.html132
-rw-r--r--tests/wpt/web-platform-tests/web-animations/timing-model/animations/set-the-animation-start-time.html63
-rw-r--r--tests/wpt/web-platform-tests/web-animations/timing-model/animations/set-the-target-effect-of-an-animation.html60
-rw-r--r--tests/wpt/web-platform-tests/web-animations/timing-model/animations/set-the-timeline-of-an-animation.html150
-rw-r--r--tests/wpt/web-platform-tests/web-animations/timing-model/animations/updating-the-finished-state.html200
-rw-r--r--tests/wpt/web-platform-tests/web-animations/timing-model/time-transformations/transformed-progress.html36
-rw-r--r--tests/wpt/web-platform-tests/web-animations/timing-model/timelines/document-timelines.html8
-rw-r--r--tests/wpt/web-platform-tests/web-animations/timing-model/timelines/timelines.html31
-rw-r--r--tests/wpt/web-platform-tests/webaudio/resources/audit.js5
-rw-r--r--tests/wpt/web-platform-tests/webdriver/OWNERS1
-rw-r--r--tests/wpt/web-platform-tests/webdriver/interface/interface.html21
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/actions/key_shortcuts.py49
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/actions/modifier_click.py99
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/actions/mouse.py24
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/actions/mouse_dblclick.py108
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/actions/sequence.py42
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/actions/support/keys.py6
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/actions/support/mouse.py13
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/cookies/add_cookie.py113
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/cookies/get_named_cookie.py6
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/document_handling/page_source.py14
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/element_click/bubbling.py152
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/element_click/stale.py22
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/element_retrieval/__init__.py0
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/element_retrieval/find_element.py83
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/element_retrieval/find_element_from_element.py82
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/element_retrieval/find_elements.py91
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/element_retrieval/find_elements_from_element.py87
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/element_retrieval/get_active_element.py8
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/element_send_keys/__init__.py0
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/element_send_keys/interactability.py136
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/element_send_keys/scroll_into_view.py78
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/execute_async_script/user_prompts.py60
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/execute_script/cyclic.py48
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/execute_script/user_prompts.py60
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/get_window_rect.py15
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/interaction/element_clear.py12
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/interface.html43
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/navigation/current_url.py6
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/retrieval/find_element.py73
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/retrieval/find_element_from_element.py74
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/retrieval/find_element_from_elements.py77
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/retrieval/find_elements.py79
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/sessions/status.py45
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/status.py21
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/support/asserts.py29
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/support/fixtures.py22
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/support/wait.py14
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/user_prompts/accept_alert.py7
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/user_prompts/dismiss_alert.py7
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/user_prompts/get_alert_text.py7
-rw-r--r--tests/wpt/web-platform-tests/webdriver/tests/user_prompts/send_alert_text.py11
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/event.origin.sub.htm4
-rw-r--r--tests/wpt/web-platform-tests/webrtc/OWNERS1
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCCertificate.html5
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCConfiguration-iceTransportPolicy.html6
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCDTMFSender-helper.js4
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCDtlsTransport-getRemoteCertificates.html2
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-addTransceiver.html39
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-constructor.html2
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-createDataChannel.html4
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-createOffer-offerToReceive.html169
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-getStats.https.html228
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-idl.html108
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-peerIdentity.html2
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-tracks.https.html244
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCRtpCapabilities-helper.js2
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCRtpSender-getStats.html54
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCRtpSender-getStats.https.html65
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCSctpTransport-maxMessageSize.html181
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCStats-helper.js535
-rw-r--r--tests/wpt/web-platform-tests/webrtc/RTCTrackEvent-constructor.html1
-rw-r--r--tests/wpt/web-platform-tests/webrtc/datachannel-idlharness.html75
-rw-r--r--tests/wpt/web-platform-tests/webrtc/tools/.eslintrc.js156
-rw-r--r--tests/wpt/web-platform-tests/webrtc/tools/README.md14
-rw-r--r--tests/wpt/web-platform-tests/webrtc/tools/package-lock.json1213
-rw-r--r--tests/wpt/web-platform-tests/webrtc/tools/package.json14
-rw-r--r--tests/wpt/web-platform-tests/websockets/constants.js3
-rw-r--r--tests/wpt/web-platform-tests/websockets/handlers/referrer_wsh.py12
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-defineProperty-getter.html2
-rw-r--r--tests/wpt/web-platform-tests/websockets/referrer.any.js13
-rw-r--r--tests/wpt/web-platform-tests/webstorage/idlharness.html2
-rw-r--r--tests/wpt/web-platform-tests/webvr/idlharness.html2
-rw-r--r--tests/wpt/web-platform-tests/webvtt/api/VTTCue/constructor-exceptions.html25
-rw-r--r--tests/wpt/web-platform-tests/webvtt/parsing/file-parsing/tests/regions-edge-case.html55
-rw-r--r--tests/wpt/web-platform-tests/webvtt/parsing/file-parsing/tests/support/regions-edge-case.vtt44
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-center-ref.html36
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-center.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-left-ref.html36
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-left.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-right-ref.html36
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-right.html30
-rw-r--r--tests/wpt/web-platform-tests/webxr/OWNERS3
-rw-r--r--tests/wpt/web-platform-tests/webxr/resources/webxr_check.html17
-rw-r--r--tests/wpt/web-platform-tests/webxr/resources/webxr_util.js27
-rw-r--r--tests/wpt/web-platform-tests/webxr/webxr_availability.http.sub.html39
-rw-r--r--tests/wpt/web-platform-tests/workers/SharedWorker_dataUrl.html63
-rw-r--r--tests/wpt/web-platform-tests/workers/data-url-shared-window.html25
-rw-r--r--tests/wpt/web-platform-tests/workers/data-url-shared.html37
-rw-r--r--tests/wpt/web-platform-tests/workers/support/iframe_sw_dataUrl.html13
-rw-r--r--tests/wpt/web-platform-tests/workers/worker-performance.worker.js6
-rw-r--r--tests/wpt/web-platform-tests/worklets/resources/credentials-tests.js182
-rw-r--r--tests/wpt/web-platform-tests/worklets/resources/credentials.py34
-rw-r--r--tests/wpt/web-platform-tests/worklets/resources/csp-tests.js68
-rw-r--r--tests/wpt/web-platform-tests/worklets/resources/empty-worklet-script-with-cors-header.js1
-rw-r--r--tests/wpt/web-platform-tests/worklets/resources/empty-worklet-script-with-cors-header.js.headers1
-rw-r--r--tests/wpt/web-platform-tests/worklets/resources/import-empty-worklet-script-with-cors-header.js3
-rw-r--r--tests/wpt/web-platform-tests/worklets/resources/import-empty-worklet-script-with-cors-header.js.headers1
-rw-r--r--tests/wpt/web-platform-tests/worklets/resources/import-empty-worklet-script.js3
-rw-r--r--tests/wpt/web-platform-tests/worklets/resources/import-insecure-origin-empty-worklet-script.sub.js5
-rw-r--r--tests/wpt/web-platform-tests/worklets/resources/import-referrer-checker-worklet-script.sub.js2
-rw-r--r--tests/wpt/web-platform-tests/worklets/resources/import-referrer-checker-worklet-script.sub.js.headers1
-rw-r--r--tests/wpt/web-platform-tests/worklets/resources/import-remote-origin-referrer-checker-worklet-script.sub.js2
-rw-r--r--tests/wpt/web-platform-tests/worklets/resources/import-remote-origin-referrer-checker-worklet-script.sub.js.headers1
-rw-r--r--tests/wpt/web-platform-tests/worklets/resources/referrer-checker.py26
-rw-r--r--tests/wpt/web-platform-tests/worklets/resources/referrer-tests.js187
-rw-r--r--tests/wpt/web-platform-tests/worklets/resources/referrer-window.html91
-rw-r--r--tests/wpt/web-platform-tests/worklets/resources/referrer.py30
-rw-r--r--tests/wpt/web-platform-tests/worklets/resources/set-cookie.py11
3679 files changed, 163070 insertions, 95382 deletions
diff --git a/python/requirements.txt b/python/requirements.txt
index 11d7910b94d..162e68787d1 100644
--- a/python/requirements.txt
+++ b/python/requirements.txt
@@ -5,7 +5,7 @@ blessings == 1.6
mach == 0.6.0
mozdebug == 0.1
mozinfo == 0.8
-mozlog == 3.5
+mozlog == 3.6
setuptools == 18.5
toml == 0.9.2
diff --git a/python/servo/lints/wpt_lint.py b/python/servo/lints/wpt_lint.py
index b1b98eec97a..a1c7e528c77 100644
--- a/python/servo/lints/wpt_lint.py
+++ b/python/servo/lints/wpt_lint.py
@@ -36,6 +36,6 @@ class Lint(LintRunner):
from tools.lint import lint
sys.path.remove(wpt_working_dir)
file_dir = os.path.abspath(os.path.join(WPT_PATH, suite))
- returncode = lint.lint(file_dir, list(files), output_format="json", css_mode=False)
+ returncode = lint.lint(file_dir, list(files), output_format="json")
if returncode:
yield ("WPT Lint Tool", "", "lint error(s) in Web Platform Tests: exit status %s" % returncode)
diff --git a/tests/wpt/include.ini b/tests/wpt/include.ini
index de71a08fec6..2b197be5984 100644
--- a/tests/wpt/include.ini
+++ b/tests/wpt/include.ini
@@ -93,7 +93,7 @@ skip: true
skip: false
[performance-timeline]
skip: false
-[quirks-mode]
+[quirks]
skip: false
[referrer-policy]
skip: false
diff --git a/tests/wpt/metadata/2dcontext/imagebitmap/createImageBitmap-invalid-args.html.ini b/tests/wpt/metadata/2dcontext/imagebitmap/createImageBitmap-invalid-args.html.ini
index 02038e45fee..e1fe300a6b9 100644
--- a/tests/wpt/metadata/2dcontext/imagebitmap/createImageBitmap-invalid-args.html.ini
+++ b/tests/wpt/metadata/2dcontext/imagebitmap/createImageBitmap-invalid-args.html.ini
@@ -1,5 +1,6 @@
[createImageBitmap-invalid-args.html]
type: testharness
+ expected: TIMEOUT
[createImageBitmap with a HTMLImageElement source and sw set to 0 rejects with a RangeError.]
expected: FAIL
@@ -84,3 +85,9 @@
[createImageBitmap with an undecodable blob source rejects with an InvalidStateError.]
expected: FAIL
+ [createImageBitmap with a broken image source rejects with an InvalidStateError.]
+ expected: FAIL
+
+ [createImageBitmap with an available but undecodable image source rejects with an InvalidStateError.]
+ expected: TIMEOUT
+
diff --git a/tests/wpt/metadata/FileAPI/blob/Blob-Request-revoke-fetch.html.ini b/tests/wpt/metadata/FileAPI/blob/Blob-Request-revoke-fetch.html.ini
new file mode 100644
index 00000000000..ea8d27f50c0
--- /dev/null
+++ b/tests/wpt/metadata/FileAPI/blob/Blob-Request-revoke-fetch.html.ini
@@ -0,0 +1,4 @@
+[Blob-Request-revoke-fetch.html]
+ [Revoke blob URL after creating Request, will fetch]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/FileAPI/blob/Blob-constructor-endings.html.ini b/tests/wpt/metadata/FileAPI/blob/Blob-constructor-endings.html.ini
new file mode 100644
index 00000000000..53c933ca61f
--- /dev/null
+++ b/tests/wpt/metadata/FileAPI/blob/Blob-constructor-endings.html.ini
@@ -0,0 +1,4 @@
+[Blob-constructor-endings.html]
+ [Blob constructor: endings option]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/FileAPI/blob/Blob-constructor.html.ini b/tests/wpt/metadata/FileAPI/blob/Blob-constructor.html.ini
index 99cce5caae3..193d306bf54 100644
--- a/tests/wpt/metadata/FileAPI/blob/Blob-constructor.html.ini
+++ b/tests/wpt/metadata/FileAPI/blob/Blob-constructor.html.ini
@@ -32,3 +32,6 @@
expected: FAIL
bug: https://github.com/servo/servo/issues/10911
+ [options properties should be accessed in lexicographic order.]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/FileAPI/file/File-constructor-endings.html.ini b/tests/wpt/metadata/FileAPI/file/File-constructor-endings.html.ini
new file mode 100644
index 00000000000..6f01cc277ba
--- /dev/null
+++ b/tests/wpt/metadata/FileAPI/file/File-constructor-endings.html.ini
@@ -0,0 +1,4 @@
+[File-constructor-endings.html]
+ [File constructor: endings option]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/FileAPI/file/File-constructor.html.ini b/tests/wpt/metadata/FileAPI/file/File-constructor.html.ini
index 1134394834f..3e76435960d 100644
--- a/tests/wpt/metadata/FileAPI/file/File-constructor.html.ini
+++ b/tests/wpt/metadata/FileAPI/file/File-constructor.html.ini
@@ -12,3 +12,12 @@
expected: FAIL
bug: https://github.com/servo/servo/issues/10911
+ [HTMLDocument in fileBits]
+ expected: FAIL
+
+ [Invalid bits argument: "hello"]
+ expected: FAIL
+
+ [Using object fileName]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/FileAPI/file/send-file-form-iso-2022-jp.tentative.html.ini b/tests/wpt/metadata/FileAPI/file/send-file-form-iso-2022-jp.tentative.html.ini
new file mode 100644
index 00000000000..384ddd6aef8
--- /dev/null
+++ b/tests/wpt/metadata/FileAPI/file/send-file-form-iso-2022-jp.tentative.html.ini
@@ -0,0 +1,4 @@
+[send-file-form-iso-2022-jp.tentative.html]
+ [Upload files in ISO-2022-JP form (tentative)]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/FileAPI/file/send-file-form-utf-8.html.ini b/tests/wpt/metadata/FileAPI/file/send-file-form-utf-8.html.ini
new file mode 100644
index 00000000000..66bd7e9ed4b
--- /dev/null
+++ b/tests/wpt/metadata/FileAPI/file/send-file-form-utf-8.html.ini
@@ -0,0 +1,4 @@
+[send-file-form-utf-8.html]
+ [Upload files in UTF-8 form]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/FileAPI/file/send-file-form-windows-1252.tentative.html.ini b/tests/wpt/metadata/FileAPI/file/send-file-form-windows-1252.tentative.html.ini
new file mode 100644
index 00000000000..d022b9dc34f
--- /dev/null
+++ b/tests/wpt/metadata/FileAPI/file/send-file-form-windows-1252.tentative.html.ini
@@ -0,0 +1,4 @@
+[send-file-form-windows-1252.tentative.html]
+ [Upload files in Windows-1252 form (tentative)]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/FileAPI/file/send-file-form-x-user-defined.tentative.html.ini b/tests/wpt/metadata/FileAPI/file/send-file-form-x-user-defined.tentative.html.ini
new file mode 100644
index 00000000000..bb7738135d3
--- /dev/null
+++ b/tests/wpt/metadata/FileAPI/file/send-file-form-x-user-defined.tentative.html.ini
@@ -0,0 +1,4 @@
+[send-file-form-x-user-defined.tentative.html]
+ [Upload files in x-user-defined form (tentative)]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/FileAPI/file/send-file-form.html.ini b/tests/wpt/metadata/FileAPI/file/send-file-form.html.ini
new file mode 100644
index 00000000000..464056abd50
--- /dev/null
+++ b/tests/wpt/metadata/FileAPI/file/send-file-form.html.ini
@@ -0,0 +1,4 @@
+[send-file-form.html]
+ [Upload ASCII-named file in UTF-8 form]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/FileAPI/unicode.html.ini b/tests/wpt/metadata/FileAPI/unicode.html.ini
new file mode 100644
index 00000000000..bb84bb80b87
--- /dev/null
+++ b/tests/wpt/metadata/FileAPI/unicode.html.ini
@@ -0,0 +1,4 @@
+[unicode.html]
+ [Blob/Unicode interaction: normalization and encoding]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json
index af456269a80..baaa27bed20 100644
--- a/tests/wpt/metadata/MANIFEST.json
+++ b/tests/wpt/metadata/MANIFEST.json
@@ -7315,12 +7315,6 @@
{}
]
],
- "css/css-block/cursor-applies-to-011.xht": [
- [
- "/css/css-block/cursor-applies-to-011.xht",
- {}
- ]
- ],
"css/css-counter-styles/arabic-indic/css3-counter-styles-101.html": [
[
"/css/css-counter-styles/arabic-indic/css3-counter-styles-101.html",
@@ -8263,6 +8257,12 @@
{}
]
],
+ "css/css-display/run-in/cursor-applies-to-011.xht": [
+ [
+ "/css/css-display/run-in/cursor-applies-to-011.xht",
+ {}
+ ]
+ ],
"css/css-flexbox/css-flexbox-height-animation-stretch.html": [
[
"/css/css-flexbox/css-flexbox-height-animation-stretch.html",
@@ -12139,6 +12139,12 @@
{}
]
],
+ "fullscreen/model/move-to-fullscreen-iframe-manual.html": [
+ [
+ "/fullscreen/model/move-to-fullscreen-iframe-manual.html",
+ {}
+ ]
+ ],
"fullscreen/model/move-to-iframe-manual.html": [
[
"/fullscreen/model/move-to-iframe-manual.html",
@@ -12187,6 +12193,12 @@
{}
]
],
+ "fullscreen/rendering/ua-style-iframe-manual.html": [
+ [
+ "/fullscreen/rendering/ua-style-iframe-manual.html",
+ {}
+ ]
+ ],
"gamepad/events-manual.html": [
[
"/gamepad/events-manual.html",
@@ -12235,6 +12247,12 @@
{}
]
],
+ "geolocation-sensor/GeolocationSensor_onerror-manual.https.html": [
+ [
+ "/geolocation-sensor/GeolocationSensor_onerror-manual.https.html",
+ {}
+ ]
+ ],
"gyroscope/Gyroscope_onerror-manual.https.html": [
[
"/gyroscope/Gyroscope_onerror-manual.https.html",
@@ -14497,9 +14515,9 @@
{}
]
],
- "quirks-mode/active-and-hover-manual.html": [
+ "quirks/active-and-hover-manual.html": [
[
- "/quirks-mode/active-and-hover-manual.html",
+ "/quirks/active-and-hover-manual.html",
{}
]
],
@@ -17701,6 +17719,12 @@
{}
]
],
+ "uievents/mouse/layout_change_should_fire_mouseover-manual.html": [
+ [
+ "/uievents/mouse/layout_change_should_fire_mouseover-manual.html",
+ {}
+ ]
+ ],
"uievents/mouse/mouseevent_move_button-manual.html": [
[
"/uievents/mouse/mouseevent_move_button-manual.html",
@@ -19255,6 +19279,12 @@
{}
]
],
+ "wake-lock/wakelock-applicability-manual.https.html": [
+ [
+ "/wake-lock/wakelock-applicability-manual.https.html",
+ {}
+ ]
+ ],
"web-nfc/nfc_hw_disabled-manual.https.html": [
[
"/web-nfc/nfc_hw_disabled-manual.https.html",
@@ -48549,6 +48579,18 @@
{}
]
],
+ "css/CSS2/fonts/font-148.xht": [
+ [
+ "/css/CSS2/fonts/font-148.xht",
+ [
+ [
+ "/css/CSS2/fonts/font-148-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/CSS2/fonts/font-applies-to-001.xht": [
[
"/css/CSS2/fonts/font-applies-to-001.xht",
@@ -50457,6 +50499,42 @@
{}
]
],
+ "css/CSS2/generated-content/after-inheritable-001.xht": [
+ [
+ "/css/CSS2/generated-content/after-inheritable-001.xht",
+ [
+ [
+ "/css/CSS2/generated-content/after-inheritable-001-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/after-inheritable-002.xht": [
+ [
+ "/css/CSS2/generated-content/after-inheritable-002.xht",
+ [
+ [
+ "/css/CSS2/generated-content/after-inheritable-002-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/after-location-001.xht": [
+ [
+ "/css/CSS2/generated-content/after-location-001.xht",
+ [
+ [
+ "/css/CSS2/generated-content/after-location-001-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/CSS2/generated-content/before-after-001.xht": [
[
"/css/CSS2/generated-content/before-after-001.xht",
@@ -50469,6 +50547,18 @@
{}
]
],
+ "css/CSS2/generated-content/before-after-002.xht": [
+ [
+ "/css/CSS2/generated-content/before-after-002.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-003-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/CSS2/generated-content/before-after-011.xht": [
[
"/css/CSS2/generated-content/before-after-011.xht",
@@ -50817,12 +50907,456 @@
{}
]
],
+ "css/CSS2/generated-content/before-inheritable-001.xht": [
+ [
+ "/css/CSS2/generated-content/before-inheritable-001.xht",
+ [
+ [
+ "/css/CSS2/generated-content/after-inheritable-001-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/before-inheritable-002.xht": [
+ [
+ "/css/CSS2/generated-content/before-inheritable-002.xht",
+ [
+ [
+ "/css/CSS2/generated-content/after-inheritable-002-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/before-location-001.xht": [
+ [
+ "/css/CSS2/generated-content/before-location-001.xht",
+ [
+ [
+ "/css/CSS2/generated-content/before-location-001-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/bidi-generated-content-001.xht": [
+ [
+ "/css/CSS2/generated-content/bidi-generated-content-001.xht",
+ [
+ [
+ "/css/CSS2/generated-content/bidi-generated-content-001-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/bidi-generated-content-002.xht": [
+ [
+ "/css/CSS2/generated-content/bidi-generated-content-002.xht",
+ [
+ [
+ "/css/CSS2/generated-content/bidi-generated-content-002-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/CSS2/generated-content/content-001.xht": [
[
"/css/CSS2/generated-content/content-001.xht",
[
[
- "/css/CSS2/reference/no-red-on-blank-page-ref.xht",
+ "/css/CSS2/generated-content/content-001-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-002.xht": [
+ [
+ "/css/CSS2/generated-content/content-002.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-001-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-003.xht": [
+ [
+ "/css/CSS2/generated-content/content-003.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-003-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-004.xht": [
+ [
+ "/css/CSS2/generated-content/content-004.xht",
+ [
+ [
+ "/css/reference/ref-filled-green-100px-square-only.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-005.xht": [
+ [
+ "/css/CSS2/generated-content/content-005.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-005-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-006.xht": [
+ [
+ "/css/CSS2/generated-content/content-006.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-006-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-007.xht": [
+ [
+ "/css/CSS2/generated-content/content-007.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-007-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-009.xht": [
+ [
+ "/css/CSS2/generated-content/content-009.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-005-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-010.xht": [
+ [
+ "/css/CSS2/generated-content/content-010.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-010-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-011.xht": [
+ [
+ "/css/CSS2/generated-content/content-011.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-011-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-012.xht": [
+ [
+ "/css/CSS2/generated-content/content-012.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-012-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-013.xht": [
+ [
+ "/css/CSS2/generated-content/content-013.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-013-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-014.xht": [
+ [
+ "/css/CSS2/generated-content/content-014.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-014-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-015.xht": [
+ [
+ "/css/CSS2/generated-content/content-015.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-015-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-016.xht": [
+ [
+ "/css/CSS2/generated-content/content-016.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-016-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-017.xht": [
+ [
+ "/css/CSS2/generated-content/content-017.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-017-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-018.xht": [
+ [
+ "/css/CSS2/generated-content/content-018.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-014-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-019.xht": [
+ [
+ "/css/CSS2/generated-content/content-019.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-015-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-020.xht": [
+ [
+ "/css/CSS2/generated-content/content-020.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-001-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-021.xht": [
+ [
+ "/css/CSS2/generated-content/content-021.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-021-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-022.xht": [
+ [
+ "/css/CSS2/generated-content/content-022.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-022-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-023.xht": [
+ [
+ "/css/CSS2/generated-content/content-023.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-023-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-025.xht": [
+ [
+ "/css/CSS2/generated-content/content-025.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-021-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-026.xht": [
+ [
+ "/css/CSS2/generated-content/content-026.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-026-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-027.xht": [
+ [
+ "/css/CSS2/generated-content/content-027.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-027-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-028.xht": [
+ [
+ "/css/CSS2/generated-content/content-028.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-028-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-029.xht": [
+ [
+ "/css/CSS2/generated-content/content-029.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-029-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-030.xht": [
+ [
+ "/css/CSS2/generated-content/content-030.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-030-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-031.xht": [
+ [
+ "/css/CSS2/generated-content/content-031.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-031-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-032.xht": [
+ [
+ "/css/CSS2/generated-content/content-032.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-032-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-033.xht": [
+ [
+ "/css/CSS2/generated-content/content-033.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-033-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-034.xht": [
+ [
+ "/css/CSS2/generated-content/content-034.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-030-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-035.xht": [
+ [
+ "/css/CSS2/generated-content/content-035.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-031-ref.html",
"=="
]
],
@@ -50834,7 +51368,499 @@
"/css/CSS2/generated-content/content-036.xht",
[
[
- "/css/CSS2/reference/no-red-on-blank-page-ref.xht",
+ "/css/CSS2/generated-content/content-001-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-037.xht": [
+ [
+ "/css/CSS2/generated-content/content-037.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-037-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-038.xht": [
+ [
+ "/css/CSS2/generated-content/content-038.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-003-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-039.xht": [
+ [
+ "/css/CSS2/generated-content/content-039.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-003-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-040.xht": [
+ [
+ "/css/CSS2/generated-content/content-040.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-040-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-041.xht": [
+ [
+ "/css/CSS2/generated-content/content-041.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-041-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-042.xht": [
+ [
+ "/css/CSS2/generated-content/content-042.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-042-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-043.xht": [
+ [
+ "/css/CSS2/generated-content/content-043.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-043-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-046.xht": [
+ [
+ "/css/CSS2/generated-content/content-046.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-037-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-047.xht": [
+ [
+ "/css/CSS2/generated-content/content-047.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-047-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-048.xht": [
+ [
+ "/css/CSS2/generated-content/content-048.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-048-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-050.xht": [
+ [
+ "/css/CSS2/generated-content/content-050.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-050-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-052.xht": [
+ [
+ "/css/CSS2/generated-content/content-052.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-052-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-053.xht": [
+ [
+ "/css/CSS2/generated-content/content-053.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-053-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-054.xht": [
+ [
+ "/css/CSS2/generated-content/content-054.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-003-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-056.xht": [
+ [
+ "/css/CSS2/generated-content/content-056.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-003-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-057.xht": [
+ [
+ "/css/CSS2/generated-content/content-057.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-003-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-063.xht": [
+ [
+ "/css/CSS2/generated-content/content-063.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-063-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-065.xht": [
+ [
+ "/css/CSS2/generated-content/content-065.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-053-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-067.xht": [
+ [
+ "/css/CSS2/generated-content/content-067.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-047-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-068.xht": [
+ [
+ "/css/CSS2/generated-content/content-068.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-068-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-070.xht": [
+ [
+ "/css/CSS2/generated-content/content-070.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-070-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-072.xht": [
+ [
+ "/css/CSS2/generated-content/content-072.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-072-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-073.xht": [
+ [
+ "/css/CSS2/generated-content/content-073.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-073-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-075.xht": [
+ [
+ "/css/CSS2/generated-content/content-075.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-075-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-076.xht": [
+ [
+ "/css/CSS2/generated-content/content-076.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-003-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-077.xht": [
+ [
+ "/css/CSS2/generated-content/content-077.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-041-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-080.xht": [
+ [
+ "/css/CSS2/generated-content/content-080.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-080-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-081.xht": [
+ [
+ "/css/CSS2/generated-content/content-081.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-081-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-082.xht": [
+ [
+ "/css/CSS2/generated-content/content-082.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-082-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-083.xht": [
+ [
+ "/css/CSS2/generated-content/content-083.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-083-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-085.xht": [
+ [
+ "/css/CSS2/generated-content/content-085.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-047-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-086.xht": [
+ [
+ "/css/CSS2/generated-content/content-086.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-041-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-089.xht": [
+ [
+ "/css/CSS2/generated-content/content-089.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-089-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-090.xht": [
+ [
+ "/css/CSS2/generated-content/content-090.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-090-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-091.xht": [
+ [
+ "/css/CSS2/generated-content/content-091.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-091-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-096.xht": [
+ [
+ "/css/CSS2/generated-content/content-096.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-096-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-097.xht": [
+ [
+ "/css/CSS2/generated-content/content-097.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-097-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-099.xht": [
+ [
+ "/css/CSS2/generated-content/content-099.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-041-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-100.xht": [
+ [
+ "/css/CSS2/generated-content/content-100.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-100-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-103.xht": [
+ [
+ "/css/CSS2/generated-content/content-103.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-103-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-105.xht": [
+ [
+ "/css/CSS2/generated-content/content-105.xht",
+ [
+ [
+ "/css/reference/only_pass_parens_semicolon.html",
"=="
]
],
@@ -50865,6 +51891,18 @@
{}
]
],
+ "css/CSS2/generated-content/content-109.xht": [
+ [
+ "/css/CSS2/generated-content/content-109.xht",
+ [
+ [
+ "/css/reference/only_pass_parens_semicolon.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/CSS2/generated-content/content-110.xht": [
[
"/css/CSS2/generated-content/content-110.xht",
@@ -50901,6 +51939,18 @@
{}
]
],
+ "css/CSS2/generated-content/content-113.xht": [
+ [
+ "/css/CSS2/generated-content/content-113.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-113-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/CSS2/generated-content/content-114.xht": [
[
"/css/CSS2/generated-content/content-114.xht",
@@ -50985,6 +52035,306 @@
{}
]
],
+ "css/CSS2/generated-content/content-122.xht": [
+ [
+ "/css/CSS2/generated-content/content-122.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-113-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-123.xht": [
+ [
+ "/css/CSS2/generated-content/content-123.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-047-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-126.xht": [
+ [
+ "/css/CSS2/generated-content/content-126.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-126-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-127.xht": [
+ [
+ "/css/CSS2/generated-content/content-127.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-126-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-129.xht": [
+ [
+ "/css/CSS2/generated-content/content-129.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-053-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-131.xht": [
+ [
+ "/css/CSS2/generated-content/content-131.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-047-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-132.xht": [
+ [
+ "/css/CSS2/generated-content/content-132.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-132-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-135.xht": [
+ [
+ "/css/CSS2/generated-content/content-135.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-135-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-136.xht": [
+ [
+ "/css/CSS2/generated-content/content-136.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-136-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-138.xht": [
+ [
+ "/css/CSS2/generated-content/content-138.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-003-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-141.xht": [
+ [
+ "/css/CSS2/generated-content/content-141.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-141-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-143.xht": [
+ [
+ "/css/CSS2/generated-content/content-143.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-143-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-144.xht": [
+ [
+ "/css/CSS2/generated-content/content-144.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-144-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-145.xht": [
+ [
+ "/css/CSS2/generated-content/content-145.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-091-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-146.xht": [
+ [
+ "/css/CSS2/generated-content/content-146.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-003-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-147.xht": [
+ [
+ "/css/CSS2/generated-content/content-147.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-147-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-149.xht": [
+ [
+ "/css/CSS2/generated-content/content-149.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-149-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-150.xht": [
+ [
+ "/css/CSS2/generated-content/content-150.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-150-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-152.xht": [
+ [
+ "/css/CSS2/generated-content/content-152.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-047-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-153.xht": [
+ [
+ "/css/CSS2/generated-content/content-153.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-091-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-155.xht": [
+ [
+ "/css/CSS2/generated-content/content-155.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-155-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-156.xht": [
+ [
+ "/css/CSS2/generated-content/content-156.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-156-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-157.xht": [
+ [
+ "/css/CSS2/generated-content/content-157.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-156-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-158.xht": [
+ [
+ "/css/CSS2/generated-content/content-158.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-158-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-159.xht": [
+ [
+ "/css/CSS2/generated-content/content-159.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-159-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/CSS2/generated-content/content-171.xht": [
[
"/css/CSS2/generated-content/content-171.xht",
@@ -51057,6 +52407,54 @@
{}
]
],
+ "css/CSS2/generated-content/content-attr-001.xht": [
+ [
+ "/css/CSS2/generated-content/content-attr-001.xht",
+ [
+ [
+ "/css/CSS2/reference/ref-nothing-below.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-attr-case-001.html": [
+ [
+ "/css/CSS2/generated-content/content-attr-case-001.html",
+ [
+ [
+ "/css/reference/pass_if_pass_below.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-attr-case-002.xht": [
+ [
+ "/css/CSS2/generated-content/content-attr-case-002.xht",
+ [
+ [
+ "/css/CSS2/reference/no-red-on-blank-page-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-auto-reset-001.xht": [
+ [
+ "/css/CSS2/generated-content/content-auto-reset-001.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-auto-reset-001-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/CSS2/generated-content/content-counter-000.xht": [
[
"/css/CSS2/generated-content/content-counter-000.xht",
@@ -51273,6 +52671,150 @@
{}
]
],
+ "css/CSS2/generated-content/content-newline-001.xht": [
+ [
+ "/css/CSS2/generated-content/content-newline-001.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-newline-001-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-white-space-001.xht": [
+ [
+ "/css/CSS2/generated-content/content-white-space-001.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-white-space-001-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-white-space-002.xht": [
+ [
+ "/css/CSS2/generated-content/content-white-space-002.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-white-space-002-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-white-space-003.xht": [
+ [
+ "/css/CSS2/generated-content/content-white-space-003.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-white-space-003-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-white-space-004.xht": [
+ [
+ "/css/CSS2/generated-content/content-white-space-004.xht",
+ [
+ [
+ "/css/CSS2/generated-content/content-white-space-004-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/counters-hidden-000.xht": [
+ [
+ "/css/CSS2/generated-content/counters-hidden-000.xht",
+ [
+ [
+ "/css/CSS2/generated-content/counters-hidden-000-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/counters-hidden-001.xht": [
+ [
+ "/css/CSS2/generated-content/counters-hidden-001.xht",
+ [
+ [
+ "/css/CSS2/generated-content/counters-hidden-000-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/counters-hidden-002.xht": [
+ [
+ "/css/CSS2/generated-content/counters-hidden-002.xht",
+ [
+ [
+ "/css/CSS2/generated-content/counters-hidden-002-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/counters-multi-000.xht": [
+ [
+ "/css/CSS2/generated-content/counters-multi-000.xht",
+ [
+ [
+ "/css/CSS2/generated-content/counters-multi-000-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/counters-multi-001.xht": [
+ [
+ "/css/CSS2/generated-content/counters-multi-001.xht",
+ [
+ [
+ "/css/CSS2/generated-content/counters-multi-000-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/counters-order-000.xht": [
+ [
+ "/css/CSS2/generated-content/counters-order-000.xht",
+ [
+ [
+ "/css/CSS2/generated-content/counters-order-000-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/counters-root-000.xht": [
+ [
+ "/css/CSS2/generated-content/counters-root-000.xht",
+ [
+ [
+ "/css/CSS2/generated-content/counters-root-000-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/CSS2/generated-content/multiple-content-values-001.xht": [
[
"/css/CSS2/generated-content/multiple-content-values-001.xht",
@@ -52749,6 +54291,18 @@
{}
]
],
+ "css/CSS2/linebox/line-height-oof-descendants-001.html": [
+ [
+ "/css/CSS2/linebox/line-height-oof-descendants-001.html",
+ [
+ [
+ "/css/CSS2/linebox/line-height-oof-descendants-001-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/CSS2/linebox/vertical-align-004.xht": [
[
"/css/CSS2/linebox/vertical-align-004.xht",
@@ -94341,6 +95895,66 @@
{}
]
],
+ "css/CSS2/visudet/content-height-001.html": [
+ [
+ "/css/CSS2/visudet/content-height-001.html",
+ [
+ [
+ "/css/CSS2/visudet/reference/content-height-001-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/visudet/content-height-002.html": [
+ [
+ "/css/CSS2/visudet/content-height-002.html",
+ [
+ [
+ "/css/CSS2/visudet/reference/content-height-002-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/visudet/content-height-003.html": [
+ [
+ "/css/CSS2/visudet/content-height-003.html",
+ [
+ [
+ "/css/CSS2/visudet/reference/content-height-003-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/visudet/content-height-004.html": [
+ [
+ "/css/CSS2/visudet/content-height-004.html",
+ [
+ [
+ "/css/CSS2/visudet/reference/content-height-004-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/visudet/content-height-005.html": [
+ [
+ "/css/CSS2/visudet/content-height-005.html",
+ [
+ [
+ "/css/CSS2/visudet/reference/content-height-005-ref.html",
+ "!="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/CSS2/visudet/height-applies-to-010a.xht": [
[
"/css/CSS2/visudet/height-applies-to-010a.xht",
@@ -94401,6 +96015,78 @@
{}
]
],
+ "css/CSS2/visudet/line-height-201.html": [
+ [
+ "/css/CSS2/visudet/line-height-201.html",
+ [
+ [
+ "/css/CSS2/visudet/reference/line-height-201-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/visudet/line-height-202.html": [
+ [
+ "/css/CSS2/visudet/line-height-202.html",
+ [
+ [
+ "/css/CSS2/visudet/reference/line-height-202-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/visudet/line-height-203.html": [
+ [
+ "/css/CSS2/visudet/line-height-203.html",
+ [
+ [
+ "/css/CSS2/visudet/reference/line-height-203-ref.html",
+ "!="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/visudet/line-height-204.html": [
+ [
+ "/css/CSS2/visudet/line-height-204.html",
+ [
+ [
+ "/css/CSS2/visudet/reference/line-height-202-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/visudet/line-height-205.html": [
+ [
+ "/css/CSS2/visudet/line-height-205.html",
+ [
+ [
+ "/css/CSS2/visudet/reference/line-height-202-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/CSS2/visudet/line-height-206.html": [
+ [
+ "/css/CSS2/visudet/line-height-206.html",
+ [
+ [
+ "/css/CSS2/visudet/reference/line-height-206-ref.html",
+ "!="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/CSS2/visufx/clip-001.xht": [
[
"/css/CSS2/visufx/clip-001.xht",
@@ -96009,18 +97695,6 @@
{}
]
],
- "css/compositing/mix-blend-mode/mix-blend-mode-transition.html": [
- [
- "/css/compositing/mix-blend-mode/mix-blend-mode-transition.html",
- [
- [
- "/css/compositing/mix-blend-mode/reference/mix-blend-mode-transition-ref.html",
- "=="
- ]
- ],
- {}
- ]
- ],
"css/compositing/mix-blend-mode/mix-blend-mode-video-sibling.html": [
[
"/css/compositing/mix-blend-mode/mix-blend-mode-video-sibling.html",
@@ -96129,6 +97803,18 @@
{}
]
],
+ "css/css-animations/animation-delay-011.html": [
+ [
+ "/css/css-animations/animation-delay-011.html",
+ [
+ [
+ "/css/css-animations/animation-common-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/css-backgrounds/background-334.html": [
[
"/css/css-backgrounds/background-334.html",
@@ -96513,6 +98199,42 @@
{}
]
],
+ "css/css-backgrounds/background-color-body-propagation-001.html": [
+ [
+ "/css/css-backgrounds/background-color-body-propagation-001.html",
+ [
+ [
+ "/css/css-backgrounds/background-color-body-propagation-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-backgrounds/background-color-body-propagation-002.html": [
+ [
+ "/css/css-backgrounds/background-color-body-propagation-002.html",
+ [
+ [
+ "/css/css-backgrounds/background-color-body-propagation-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-backgrounds/background-color-body-propagation-003.html": [
+ [
+ "/css/css-backgrounds/background-color-body-propagation-003.html",
+ [
+ [
+ "/css/css-backgrounds/background-color-body-propagation-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/css-backgrounds/background-image-001.html": [
[
"/css/css-backgrounds/background-image-001.html",
@@ -96621,6 +98343,18 @@
{}
]
],
+ "css/css-backgrounds/background-image-none-gradient-repaint.html": [
+ [
+ "/css/css-backgrounds/background-image-none-gradient-repaint.html",
+ [
+ [
+ "/css/css-backgrounds/background-clip-color-repaint-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/css-backgrounds/background-origin-002.html": [
[
"/css/css-backgrounds/background-origin-002.html",
@@ -100557,3780 +102291,4308 @@
{}
]
],
- "css/css-block/counter-increment-applies-to-011.xht": [
+ "css/css-cascade/all-prop-001.html": [
[
- "/css/css-block/counter-increment-applies-to-011.xht",
+ "/css/css-cascade/all-prop-001.html",
[
[
- "/css/reference/pass_if_number_5.xht",
+ "/css/css-cascade/all-prop-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/counter-reset-applies-to-011.xht": [
+ "css/css-cascade/all-prop-002.html": [
[
- "/css/css-block/counter-reset-applies-to-011.xht",
+ "/css/css-cascade/all-prop-002.html",
[
[
- "/css/reference/pass_if_number_5.xht",
+ "/css/css-cascade/reference/ref-filled-green-100px-square.xht",
"=="
]
],
{}
]
],
- "css/css-block/font-style-applies-to-004.xht": [
+ "css/css-cascade/initial-color-background-001.html": [
[
- "/css/css-block/font-style-applies-to-004.xht",
+ "/css/css-cascade/initial-color-background-001.html",
[
[
- "/css/reference/pass_if_filler_text_slanted.xht",
+ "/css/css-cascade/initial-color-background-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/font-variant-applies-to-004.xht": [
+ "css/css-cascade/revert-val-001.html": [
[
- "/css/css-block/font-variant-applies-to-004.xht",
+ "/css/css-cascade/revert-val-001.html",
[
[
- "/css/reference/pass_if_filler_text_match_smallcaps.xht",
+ "/css/css-cascade/reference/ref-filled-green-100px-square.xht",
"=="
]
],
{}
]
],
- "css/css-block/font-weight-applies-to-004.xht": [
+ "css/css-cascade/unset-val-001.html": [
[
- "/css/css-block/font-weight-applies-to-004.xht",
+ "/css/css-cascade/unset-val-001.html",
[
[
- "/css/reference/pass_if_filler_text_match_bold.xht",
+ "/css/css-cascade/reference/ref-filled-green-100px-square.xht",
"=="
]
],
{}
]
],
- "css/css-block/height-applies-to-011.xht": [
+ "css/css-cascade/unset-val-002.html": [
[
- "/css/css-block/height-applies-to-011.xht",
+ "/css/css-cascade/unset-val-002.html",
[
[
- "/css/reference/pass_if_square_96px_black.html",
+ "/css/css-cascade/reference/ref-filled-green-100px-square.xht",
"=="
]
],
{}
]
],
- "css/css-block/letter-spacing-applies-to-004.xht": [
+ "css/css-color/border-bottom-color.xht": [
[
- "/css/css-block/letter-spacing-applies-to-004.xht",
+ "/css/css-color/border-bottom-color.xht",
[
[
- "/css/reference/black_box_ends_when_blue_box_ends_6_boxes_ahem.html",
+ "/css/css-color/border-color-ref.xht",
"=="
]
],
{}
]
],
- "css/css-block/list-style-applies-to-011.xht": [
+ "css/css-color/border-left-color.xht": [
[
- "/css/css-block/list-style-applies-to-011.xht",
+ "/css/css-color/border-left-color.xht",
[
[
- "/css/reference/single_square_list_marker.xht",
+ "/css/css-color/border-color-ref.xht",
"=="
]
],
{}
]
],
- "css/css-block/list-style-type-applies-to-011.xht": [
+ "css/css-color/border-right-color.xht": [
[
- "/css/css-block/list-style-type-applies-to-011.xht",
+ "/css/css-color/border-right-color.xht",
[
[
- "/css/reference/single_square_list_marker.xht",
+ "/css/css-color/border-color-ref.xht",
"=="
]
],
{}
]
],
- "css/css-block/max-height-applies-to-011.xht": [
+ "css/css-color/border-top-color.xht": [
[
- "/css/css-block/max-height-applies-to-011.xht",
+ "/css/css-color/border-top-color.xht",
[
[
- "/css/reference/pass_if_square_96px_black.html",
+ "/css/css-color/border-color-ref.xht",
"=="
]
],
{}
]
],
- "css/css-block/max-width-applies-to-011.xht": [
+ "css/css-color/color-001.html": [
[
- "/css/css-block/max-width-applies-to-011.xht",
+ "/css/css-color/color-001.html",
[
[
- "/css/reference/pass_if_square_96px_black.html",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/min-height-applies-to-011.xht": [
+ "css/css-color/color-002.html": [
[
- "/css/css-block/min-height-applies-to-011.xht",
+ "/css/css-color/color-002.html",
[
[
- "/css/reference/pass_if_square_96px_black.html",
+ "/css/css-color/blacktext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/min-width-applies-to-011.xht": [
+ "css/css-color/color-003.html": [
[
- "/css/css-block/min-width-applies-to-011.xht",
+ "/css/css-color/color-003.html",
[
[
- "/css/reference/pass_if_square_96px_black.html",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/quotes-applies-to-011.xht": [
+ "css/css-color/currentcolor-001.html": [
[
- "/css/css-block/quotes-applies-to-011.xht",
+ "/css/css-color/currentcolor-001.html",
[
[
- "/css/reference/pass_if_pass_below.html",
+ "/css/css-color/greensquare-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-abspos-between-001.xht": [
+ "css/css-color/currentcolor-002.html": [
[
- "/css/css-block/run-in-abspos-between-001.xht",
+ "/css/css-color/currentcolor-002.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/greensquare-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-abspos-between-002.xht": [
+ "css/css-color/hex-001.html": [
[
- "/css/css-block/run-in-abspos-between-002.xht",
+ "/css/css-color/hex-001.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-abspos-between-003.xht": [
+ "css/css-color/hex-002.html": [
[
- "/css/css-block/run-in-abspos-between-003.xht",
+ "/css/css-color/hex-002.html",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-basic-001.xht": [
+ "css/css-color/hex-003.html": [
[
- "/css/css-block/run-in-basic-001.xht",
+ "/css/css-color/hex-003.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/hex-003-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-basic-002.xht": [
+ "css/css-color/hex-004.html": [
[
- "/css/css-block/run-in-basic-002.xht",
+ "/css/css-color/hex-004.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/hex-003-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-basic-003.xht": [
+ "css/css-color/hsl-001.html": [
[
- "/css/css-block/run-in-basic-003.xht",
+ "/css/css-color/hsl-001.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-basic-004.xht": [
+ "css/css-color/hsl-002.html": [
[
- "/css/css-block/run-in-basic-004.xht",
+ "/css/css-color/hsl-002.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-basic-005.xht": [
+ "css/css-color/hsl-003.html": [
[
- "/css/css-block/run-in-basic-005.xht",
+ "/css/css-color/hsl-003.html",
[
[
- "/css/css-block/run-in-block-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-basic-006.xht": [
+ "css/css-color/hsl-004.html": [
[
- "/css/css-block/run-in-basic-006.xht",
+ "/css/css-color/hsl-004.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-basic-007.xht": [
+ "css/css-color/hsl-005.html": [
[
- "/css/css-block/run-in-basic-007.xht",
+ "/css/css-color/hsl-005.html",
[
[
- "/css/css-block/run-in-basic-007-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-basic-008.xht": [
+ "css/css-color/hsl-006.html": [
[
- "/css/css-block/run-in-basic-008.xht",
+ "/css/css-color/hsl-006.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-basic-009.xht": [
+ "css/css-color/hsl-007.html": [
[
- "/css/css-block/run-in-basic-009.xht",
+ "/css/css-color/hsl-007.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-basic-010.xht": [
+ "css/css-color/hsl-008.html": [
[
- "/css/css-block/run-in-basic-010.xht",
+ "/css/css-color/hsl-008.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-basic-011.xht": [
+ "css/css-color/hsla-001.html": [
[
- "/css/css-block/run-in-basic-011.xht",
+ "/css/css-color/hsla-001.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-basic-012.xht": [
+ "css/css-color/hsla-002.html": [
[
- "/css/css-block/run-in-basic-012.xht",
+ "/css/css-color/hsla-002.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-basic-013.xht": [
+ "css/css-color/hsla-003.html": [
[
- "/css/css-block/run-in-basic-013.xht",
+ "/css/css-color/hsla-003.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-basic-014.xht": [
+ "css/css-color/hsla-004.html": [
[
- "/css/css-block/run-in-basic-014.xht",
+ "/css/css-color/hsla-004.html",
[
[
- "/css/css-block/run-in-pre-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-basic-015.xht": [
+ "css/css-color/hsla-005.html": [
[
- "/css/css-block/run-in-basic-015.xht",
+ "/css/css-color/hsla-005.html",
[
[
- "/css/css-block/run-in-pre-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-basic-016.xht": [
+ "css/css-color/hsla-006.html": [
[
- "/css/css-block/run-in-basic-016.xht",
+ "/css/css-color/hsla-006.html",
[
[
- "/css/css-block/run-in-pre-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-basic-017.xht": [
+ "css/css-color/hsla-007.html": [
[
- "/css/css-block/run-in-basic-017.xht",
+ "/css/css-color/hsla-007.html",
[
[
- "/css/css-block/run-in-pre-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-basic-018.xht": [
+ "css/css-color/hsla-008.html": [
[
- "/css/css-block/run-in-basic-018.xht",
+ "/css/css-color/hsla-008.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-block-between-001.xht": [
+ "css/css-color/lab-001.html": [
[
- "/css/css-block/run-in-block-between-001.xht",
+ "/css/css-color/lab-001.html",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-block-between-002.xht": [
+ "css/css-color/lab-002.html": [
[
- "/css/css-block/run-in-block-between-002.xht",
+ "/css/css-color/lab-002.html",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/blacktext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-block-between-003.xht": [
+ "css/css-color/lab-003.html": [
[
- "/css/css-block/run-in-block-between-003.xht",
+ "/css/css-color/lab-003.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/whitetext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-breaking-001.xht": [
+ "css/css-color/lab-004.html": [
[
- "/css/css-block/run-in-breaking-001.xht",
+ "/css/css-color/lab-004.html",
[
[
- "/css/css-block/run-in-breaking-001-ref.xht",
+ "/css/css-color/blacktext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-breaking-002.xht": [
+ "css/css-color/lab-005.html": [
[
- "/css/css-block/run-in-breaking-002.xht",
+ "/css/css-color/lab-005.html",
[
[
- "/css/css-block/run-in-breaking-002-ref.xht",
+ "/css/css-color/blacktext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-clear-001.xht": [
+ "css/css-color/lab-006.html": [
[
- "/css/css-block/run-in-clear-001.xht",
+ "/css/css-color/lab-006.html",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/blacktext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-clear-002.xht": [
+ "css/css-color/lab-007.html": [
[
- "/css/css-block/run-in-clear-002.xht",
+ "/css/css-color/lab-007.html",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/blacktext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-abspos-001.xht": [
+ "css/css-color/lch-001.html": [
[
- "/css/css-block/run-in-contains-abspos-001.xht",
+ "/css/css-color/lch-001.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-block-001.xht": [
+ "css/css-color/lch-002.html": [
[
- "/css/css-block/run-in-contains-block-001.xht",
+ "/css/css-color/lch-002.html",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/blacktext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-block-002.xht": [
+ "css/css-color/lch-003.html": [
[
- "/css/css-block/run-in-contains-block-002.xht",
+ "/css/css-color/lch-003.html",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/whitetext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-block-003.xht": [
+ "css/css-color/lch-004.html": [
[
- "/css/css-block/run-in-contains-block-003.xht",
+ "/css/css-color/lch-004.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/blacktext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-block-004.xht": [
+ "css/css-color/lch-005.html": [
[
- "/css/css-block/run-in-contains-block-004.xht",
+ "/css/css-color/lch-005.html",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/blacktext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-block-005.xht": [
+ "css/css-color/lch-006.html": [
[
- "/css/css-block/run-in-contains-block-005.xht",
+ "/css/css-color/lch-006.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/blacktext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-block-inside-inline-001.xht": [
+ "css/css-color/lch-007.html": [
[
- "/css/css-block/run-in-contains-block-inside-inline-001.xht",
+ "/css/css-color/lch-007.html",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/blacktext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-block-inside-inline-002.xht": [
+ "css/css-color/named-001.html": [
[
- "/css/css-block/run-in-contains-block-inside-inline-002.xht",
+ "/css/css-color/named-001.html",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/rebeccapurple-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-block-inside-inline-003.xht": [
+ "css/css-color/rgb-001.html": [
[
- "/css/css-block/run-in-contains-block-inside-inline-003.xht",
+ "/css/css-color/rgb-001.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-float-001.xht": [
+ "css/css-color/rgb-002.html": [
[
- "/css/css-block/run-in-contains-float-001.xht",
+ "/css/css-color/rgb-002.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-inline-001.xht": [
+ "css/css-color/rgb-003.html": [
[
- "/css/css-block/run-in-contains-inline-001.xht",
+ "/css/css-color/rgb-003.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-inline-002.xht": [
+ "css/css-color/rgb-004.html": [
[
- "/css/css-block/run-in-contains-inline-002.xht",
+ "/css/css-color/rgb-004.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-inline-003.xht": [
+ "css/css-color/rgb-005.html": [
[
- "/css/css-block/run-in-contains-inline-003.xht",
+ "/css/css-color/rgb-005.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-inline-004.xht": [
+ "css/css-color/rgb-006.html": [
[
- "/css/css-block/run-in-contains-inline-004.xht",
+ "/css/css-color/rgb-006.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-inline-005.xht": [
+ "css/css-color/rgb-007.html": [
[
- "/css/css-block/run-in-contains-inline-005.xht",
+ "/css/css-color/rgb-007.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-inline-006.xht": [
+ "css/css-color/rgb-008.html": [
[
- "/css/css-block/run-in-contains-inline-006.xht",
+ "/css/css-color/rgb-008.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-inline-007.xht": [
+ "css/css-color/rgba-001.html": [
[
- "/css/css-block/run-in-contains-inline-007.xht",
+ "/css/css-color/rgba-001.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-inline-block-001.xht": [
+ "css/css-color/rgba-002.html": [
[
- "/css/css-block/run-in-contains-inline-block-001.xht",
+ "/css/css-color/rgba-002.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-inline-table-001.xht": [
+ "css/css-color/rgba-003.html": [
[
- "/css/css-block/run-in-contains-inline-table-001.xht",
+ "/css/css-color/rgba-003.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-relpos-block-001.xht": [
+ "css/css-color/rgba-004.html": [
[
- "/css/css-block/run-in-contains-relpos-block-001.xht",
+ "/css/css-color/rgba-004.html",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-relpos-block-002.xht": [
+ "css/css-color/rgba-005.html": [
[
- "/css/css-block/run-in-contains-relpos-block-002.xht",
+ "/css/css-color/rgba-005.html",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-relpos-block-003.xht": [
+ "css/css-color/rgba-006.html": [
[
- "/css/css-block/run-in-contains-relpos-block-003.xht",
+ "/css/css-color/rgba-006.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-run-in-001.xht": [
+ "css/css-color/rgba-007.html": [
[
- "/css/css-block/run-in-contains-run-in-001.xht",
+ "/css/css-color/rgba-007.html",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-run-in-002.xht": [
+ "css/css-color/rgba-008.html": [
[
- "/css/css-block/run-in-contains-run-in-002.xht",
+ "/css/css-color/rgba-008.html",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/greentext-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-run-in-003.xht": [
+ "css/css-color/t31-color-currentColor-b.xht": [
[
- "/css/css-block/run-in-contains-run-in-003.xht",
+ "/css/css-color/t31-color-currentColor-b.xht",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/t31-color-currentColor-b-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-table-001.xht": [
+ "css/css-color/t31-color-text-a.xht": [
+ [
+ "/css/css-color/t31-color-text-a.xht",
+ [
+ [
+ "/css/css-color/t31-color-text-a-ref.xht",
+ "!="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-color/t32-opacity-basic-0.0-a.xht": [
[
- "/css/css-block/run-in-contains-table-001.xht",
+ "/css/css-color/t32-opacity-basic-0.0-a.xht",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t32-opacity-basic-0.0-a-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-table-002.xht": [
+ "css/css-color/t32-opacity-basic-1.0-a.xht": [
[
- "/css/css-block/run-in-contains-table-002.xht",
+ "/css/css-color/t32-opacity-basic-1.0-a.xht",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t32-opacity-basic-1.0-a-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-table-003.xht": [
+ "css/css-color/t32-opacity-clamping-0.0-b.xht": [
[
- "/css/css-block/run-in-contains-table-003.xht",
+ "/css/css-color/t32-opacity-clamping-0.0-b.xht",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/t32-opacity-basic-0.0-a-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-table-caption-001.xht": [
+ "css/css-color/t32-opacity-clamping-1.0-b.xht": [
[
- "/css/css-block/run-in-contains-table-caption-001.xht",
+ "/css/css-color/t32-opacity-clamping-1.0-b.xht",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/t32-opacity-clamping-1.0-b-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-table-cell-001.xht": [
+ "css/css-color/t32-opacity-offscreen-b.xht": [
[
- "/css/css-block/run-in-contains-table-cell-001.xht",
+ "/css/css-color/t32-opacity-offscreen-b.xht",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/t32-opacity-offscreen-b-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-table-column-001.xht": [
+ "css/css-color/t32-opacity-offscreen-multiple-boxes-1-c.xht": [
[
- "/css/css-block/run-in-contains-table-column-001.xht",
+ "/css/css-color/t32-opacity-offscreen-multiple-boxes-1-c.xht",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/t32-opacity-offscreen-multiple-boxes-1-c-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-table-column-group-001.xht": [
+ "css/css-color/t32-opacity-offscreen-multiple-boxes-2-c.xht": [
[
- "/css/css-block/run-in-contains-table-column-group-001.xht",
+ "/css/css-color/t32-opacity-offscreen-multiple-boxes-2-c.xht",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/t32-opacity-offscreen-multiple-boxes-2-c-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-table-inside-inline-001.xht": [
+ "css/css-color/t32-opacity-offscreen-with-alpha-c.xht": [
[
- "/css/css-block/run-in-contains-table-inside-inline-001.xht",
+ "/css/css-color/t32-opacity-offscreen-with-alpha-c.xht",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t32-opacity-offscreen-with-alpha-c-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-table-inside-inline-002.xht": [
+ "css/css-color/t41-html4-keywords-a.xht": [
[
- "/css/css-block/run-in-contains-table-inside-inline-002.xht",
+ "/css/css-color/t41-html4-keywords-a.xht",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t41-html4-keywords-a-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-table-inside-inline-003.xht": [
+ "css/css-color/t421-rgb-clip-outside-gamut-b.xht": [
[
- "/css/css-block/run-in-contains-table-inside-inline-003.xht",
+ "/css/css-color/t421-rgb-clip-outside-gamut-b.xht",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/t421-rgb-clip-outside-gamut-b-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-table-row-001.xht": [
+ "css/css-color/t421-rgb-func-int-a.xht": [
[
- "/css/css-block/run-in-contains-table-row-001.xht",
+ "/css/css-color/t421-rgb-func-int-a.xht",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/t422-rgba-func-int-a-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-contains-table-row-group-001.xht": [
+ "css/css-color/t421-rgb-func-no-mixed-f.xht": [
[
- "/css/css-block/run-in-contains-table-row-group-001.xht",
+ "/css/css-color/t421-rgb-func-no-mixed-f.xht",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/t422-rgba-func-no-mixed-f-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-display-none-between-001.xht": [
+ "css/css-color/t421-rgb-func-pct-a.xht": [
[
- "/css/css-block/run-in-display-none-between-001.xht",
+ "/css/css-color/t421-rgb-func-pct-a.xht",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/t422-rgba-func-int-a-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-display-none-between-002.xht": [
+ "css/css-color/t421-rgb-func-whitespace-b.xht": [
[
- "/css/css-block/run-in-display-none-between-002.xht",
+ "/css/css-color/t421-rgb-func-whitespace-b.xht",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/t422-rgba-func-whitespace-b-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-display-none-between-003.xht": [
+ "css/css-color/t421-rgb-hex-parsing-f.xht": [
[
- "/css/css-block/run-in-display-none-between-003.xht",
+ "/css/css-color/t421-rgb-hex-parsing-f.xht",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t422-rgba-func-no-mixed-f-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-fixedpos-between-001.xht": [
+ "css/css-color/t421-rgb-hex3-a.xht": [
[
- "/css/css-block/run-in-fixedpos-between-001.xht",
+ "/css/css-color/t421-rgb-hex3-a.xht",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/t422-rgba-func-int-a-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-fixedpos-between-002.xht": [
+ "css/css-color/t421-rgb-hex6-a.xht": [
[
- "/css/css-block/run-in-fixedpos-between-002.xht",
+ "/css/css-color/t421-rgb-hex6-a.xht",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/t422-rgba-func-int-a-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-fixedpos-between-003.xht": [
+ "css/css-color/t421-rgb-values-meaning-b.xht": [
[
- "/css/css-block/run-in-fixedpos-between-003.xht",
+ "/css/css-color/t421-rgb-values-meaning-b.xht",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t421-rgb-values-meaning-b-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-float-between-001.xht": [
+ "css/css-color/t422-rgba-a0.0-a.xht": [
[
- "/css/css-block/run-in-float-between-001.xht",
+ "/css/css-color/t422-rgba-a0.0-a.xht",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/t32-opacity-basic-0.0-a-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-float-between-002.xht": [
+ "css/css-color/t422-rgba-a1.0-a.xht": [
[
- "/css/css-block/run-in-float-between-002.xht",
+ "/css/css-color/t422-rgba-a1.0-a.xht",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/t422-rgba-a1.0-a-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-float-between-003.xht": [
+ "css/css-color/t422-rgba-clamping-a0.0-b.xht": [
[
- "/css/css-block/run-in-float-between-003.xht",
+ "/css/css-color/t422-rgba-clamping-a0.0-b.xht",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t422-rgba-clamping-a0.0-b-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-inherit-001.xht": [
+ "css/css-color/t422-rgba-clamping-a1.0-b.xht": [
[
- "/css/css-block/run-in-inherit-001.xht",
+ "/css/css-color/t422-rgba-clamping-a1.0-b.xht",
[
[
- "/css/css-block/run-in-inherit-001-ref.xht",
+ "/css/css-color/t422-rgba-clamping-a1.0-b-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-inline-between-001.xht": [
+ "css/css-color/t422-rgba-clip-outside-device-gamut-b.xht": [
[
- "/css/css-block/run-in-inline-between-001.xht",
+ "/css/css-color/t422-rgba-clip-outside-device-gamut-b.xht",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t422-rgba-clip-outside-device-gamut-b-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-inline-between-002.xht": [
+ "css/css-color/t422-rgba-func-int-a.xht": [
[
- "/css/css-block/run-in-inline-between-002.xht",
+ "/css/css-color/t422-rgba-func-int-a.xht",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t422-rgba-func-int-a-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-inline-between-003.xht": [
+ "css/css-color/t422-rgba-func-no-mixed-f.xht": [
[
- "/css/css-block/run-in-inline-between-003.xht",
+ "/css/css-color/t422-rgba-func-no-mixed-f.xht",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/t422-rgba-func-no-mixed-f-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-inline-block-between-001.xht": [
+ "css/css-color/t422-rgba-func-pct-a.xht": [
[
- "/css/css-block/run-in-inline-block-between-001.xht",
+ "/css/css-color/t422-rgba-func-pct-a.xht",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t422-rgba-func-int-a-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-inline-block-between-002.xht": [
+ "css/css-color/t422-rgba-func-whitespace-b.xht": [
[
- "/css/css-block/run-in-inline-block-between-002.xht",
+ "/css/css-color/t422-rgba-func-whitespace-b.xht",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t422-rgba-func-whitespace-b-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-inline-block-between-003.xht": [
+ "css/css-color/t422-rgba-onscreen-b.xht": [
[
- "/css/css-block/run-in-inline-block-between-003.xht",
+ "/css/css-color/t422-rgba-onscreen-b.xht",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/t422-rgba-onscreen-b-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-inline-table-between-001.xht": [
+ "css/css-color/t422-rgba-onscreen-multiple-boxes-c.xht": [
[
- "/css/css-block/run-in-inline-table-between-001.xht",
+ "/css/css-color/t422-rgba-onscreen-multiple-boxes-c.xht",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t422-rgba-onscreen-multiple-boxes-c-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-inline-table-between-002.xht": [
+ "css/css-color/t422-rgba-values-meaning-b.xht": [
[
- "/css/css-block/run-in-inline-table-between-002.xht",
+ "/css/css-color/t422-rgba-values-meaning-b.xht",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t422-rgba-values-meaning-b-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-inline-table-between-003.xht": [
+ "css/css-color/t423-transparent-1-a.xht": [
[
- "/css/css-block/run-in-inline-table-between-003.xht",
+ "/css/css-color/t423-transparent-1-a.xht",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/t422-rgba-clamping-a0.0-b-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-listitem-between-001.xht": [
+ "css/css-color/t423-transparent-2-a.xht": [
[
- "/css/css-block/run-in-listitem-between-001.xht",
+ "/css/css-color/t423-transparent-2-a.xht",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t423-transparent-2-a-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-listitem-between-002.xht": [
+ "css/css-color/t424-hsl-basic-a.xht": [
[
- "/css/css-block/run-in-listitem-between-002.xht",
+ "/css/css-color/t424-hsl-basic-a.xht",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t424-hsl-basic-a-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-listitem-between-003.xht": [
+ "css/css-color/t424-hsl-clip-outside-gamut-b.xht": [
[
- "/css/css-block/run-in-listitem-between-003.xht",
+ "/css/css-color/t424-hsl-clip-outside-gamut-b.xht",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/t424-hsl-clip-outside-gamut-b-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-relpos-between-001.xht": [
+ "css/css-color/t424-hsl-h-rotating-b.xht": [
[
- "/css/css-block/run-in-relpos-between-001.xht",
+ "/css/css-color/t424-hsl-h-rotating-b.xht",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t424-hsl-h-rotating-b-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-relpos-between-002.xht": [
+ "css/css-color/t424-hsl-parsing-f.xht": [
[
- "/css/css-block/run-in-relpos-between-002.xht",
+ "/css/css-color/t424-hsl-parsing-f.xht",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t424-hsl-parsing-f-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-relpos-between-003.xht": [
+ "css/css-color/t424-hsl-values-b-1.html": [
[
- "/css/css-block/run-in-relpos-between-003.xht",
+ "/css/css-color/t424-hsl-values-b-1.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/t424-hsl-values-b-1-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-replaced-001.xht": [
+ "css/css-color/t424-hsl-values-b-10.html": [
[
- "/css/css-block/run-in-replaced-001.xht",
+ "/css/css-color/t424-hsl-values-b-10.html",
[
[
- "/css/css-block/run-in-replaced-001-ref.xht",
+ "/css/css-color/t424-hsl-values-b-10-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-restyle-001.xht": [
+ "css/css-color/t424-hsl-values-b-11.html": [
[
- "/css/css-block/run-in-restyle-001.xht",
+ "/css/css-color/t424-hsl-values-b-11.html",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t424-hsl-values-b-11-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-restyle-002.xht": [
+ "css/css-color/t424-hsl-values-b-12.html": [
[
- "/css/css-block/run-in-restyle-002.xht",
+ "/css/css-color/t424-hsl-values-b-12.html",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t424-hsl-values-b-12-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-restyle-003.xht": [
+ "css/css-color/t424-hsl-values-b-13.html": [
[
- "/css/css-block/run-in-restyle-003.xht",
+ "/css/css-color/t424-hsl-values-b-13.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/t424-hsl-values-b-13-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-run-in-between-001.xht": [
+ "css/css-color/t424-hsl-values-b-14.html": [
[
- "/css/css-block/run-in-run-in-between-001.xht",
+ "/css/css-color/t424-hsl-values-b-14.html",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t424-hsl-values-b-14-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-run-in-between-002.xht": [
+ "css/css-color/t424-hsl-values-b-15.html": [
[
- "/css/css-block/run-in-run-in-between-002.xht",
+ "/css/css-color/t424-hsl-values-b-15.html",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t424-hsl-values-b-15-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-run-in-between-003.xht": [
+ "css/css-color/t424-hsl-values-b-2.html": [
[
- "/css/css-block/run-in-run-in-between-003.xht",
+ "/css/css-color/t424-hsl-values-b-2.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/t424-hsl-values-b-2-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-run-in-between-004.xht": [
+ "css/css-color/t424-hsl-values-b-3.html": [
[
- "/css/css-block/run-in-run-in-between-004.xht",
+ "/css/css-color/t424-hsl-values-b-3.html",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t424-hsl-values-b-3-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-run-in-between-005.xht": [
+ "css/css-color/t424-hsl-values-b-4.html": [
[
- "/css/css-block/run-in-run-in-between-005.xht",
+ "/css/css-color/t424-hsl-values-b-4.html",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t424-hsl-values-b-4-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-run-in-between-006.xht": [
+ "css/css-color/t424-hsl-values-b-5.html": [
[
- "/css/css-block/run-in-run-in-between-006.xht",
+ "/css/css-color/t424-hsl-values-b-5.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/t424-hsl-values-b-5-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-run-in-between-007.xht": [
+ "css/css-color/t424-hsl-values-b-6.html": [
[
- "/css/css-block/run-in-run-in-between-007.xht",
+ "/css/css-color/t424-hsl-values-b-6.html",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t424-hsl-values-b-6-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-run-in-between-008.xht": [
+ "css/css-color/t424-hsl-values-b-7.html": [
[
- "/css/css-block/run-in-run-in-between-008.xht",
+ "/css/css-color/t424-hsl-values-b-7.html",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t424-hsl-values-b-7-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-table-between-001.xht": [
+ "css/css-color/t424-hsl-values-b-8.html": [
[
- "/css/css-block/run-in-table-between-001.xht",
+ "/css/css-color/t424-hsl-values-b-8.html",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t424-hsl-values-b-8-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-table-between-002.xht": [
+ "css/css-color/t424-hsl-values-b-9.html": [
[
- "/css/css-block/run-in-table-between-002.xht",
+ "/css/css-color/t424-hsl-values-b-9.html",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t424-hsl-values-b-9-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-table-between-003.xht": [
+ "css/css-color/t425-hsla-clip-outside-device-gamut-b.xht": [
[
- "/css/css-block/run-in-table-between-003.xht",
+ "/css/css-color/t425-hsla-clip-outside-device-gamut-b.xht",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/t425-hsla-clip-outside-device-gamut-b-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-table-cell-between-001.xht": [
+ "css/css-color/t425-hsla-h-rotating-b.xht": [
[
- "/css/css-block/run-in-table-cell-between-001.xht",
+ "/css/css-color/t425-hsla-h-rotating-b.xht",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t425-hsla-h-rotating-b-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-table-cell-between-002.xht": [
+ "css/css-color/t425-hsla-onscreen-b.xht": [
[
- "/css/css-block/run-in-table-cell-between-002.xht",
+ "/css/css-color/t425-hsla-onscreen-b.xht",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t422-rgba-onscreen-b-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-table-cell-between-003.xht": [
+ "css/css-color/t425-hsla-onscreen-multiple-boxes-c.xht": [
[
- "/css/css-block/run-in-table-cell-between-003.xht",
+ "/css/css-color/t425-hsla-onscreen-multiple-boxes-c.xht",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/t422-rgba-onscreen-multiple-boxes-c-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-table-row-between-001.xht": [
+ "css/css-color/t425-hsla-parsing-f.xht": [
[
- "/css/css-block/run-in-table-row-between-001.xht",
+ "/css/css-color/t425-hsla-parsing-f.xht",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t424-hsl-parsing-f-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-table-row-between-002.xht": [
+ "css/css-color/t425-hsla-values-b.xht": [
[
- "/css/css-block/run-in-table-row-between-002.xht",
+ "/css/css-color/t425-hsla-values-b.xht",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t425-hsla-values-b-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-table-row-between-003.xht": [
+ "css/css-color/t43-svg-keywords-a.xht": [
[
- "/css/css-block/run-in-table-row-between-003.xht",
+ "/css/css-color/t43-svg-keywords-a.xht",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-color/t43-svg-keywords-a-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-text-between-001.xht": [
+ "css/css-color/t44-currentcolor-background-b.xht": [
[
- "/css/css-block/run-in-text-between-001.xht",
+ "/css/css-color/t44-currentcolor-background-b.xht",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t44-currentcolor-background-b-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-text-between-002.xht": [
+ "css/css-color/t44-currentcolor-border-b.xht": [
[
- "/css/css-block/run-in-text-between-002.xht",
+ "/css/css-color/t44-currentcolor-border-b.xht",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t44-currentcolor-border-b-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-text-between-003.xht": [
+ "css/css-color/t44-currentcolor-inherited-c.xht": [
[
- "/css/css-block/run-in-text-between-003.xht",
+ "/css/css-color/t44-currentcolor-inherited-c.xht",
[
[
- "/css/css-block/run-in-text-ref.xht",
+ "/css/css-color/t44-currentcolor-inherited-c-ref.xht",
"=="
]
],
{}
]
],
- "css/css-block/run-in-text-between-004.xht": [
+ "css/css-conditional/at-media-whitespace-optional-001.html": [
[
- "/css/css-block/run-in-text-between-004.xht",
+ "/css/css-conditional/at-media-whitespace-optional-001.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-conditional/reference/background-lime.html",
"=="
]
],
{}
]
],
- "css/css-block/run-in-text-between-005.xht": [
+ "css/css-conditional/at-media-whitespace-optional-002.html": [
[
- "/css/css-block/run-in-text-between-005.xht",
+ "/css/css-conditional/at-media-whitespace-optional-002.html",
[
[
- "/css/css-block/run-in-basic-ref.xht",
+ "/css/css-conditional/reference/background-lime.html",
"=="
]
],
{}
]
],
- "css/css-block/text-decoration-applies-to-004.xht": [
+ "css/css-conditional/at-supports-001.html": [
[
- "/css/css-block/text-decoration-applies-to-004.xht",
+ "/css/css-conditional/at-supports-001.html",
[
[
- "/css/reference/pass_if_filler_text_underlined.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/text-transform-applies-to-004.xht": [
+ "css/css-conditional/at-supports-002.html": [
[
- "/css/css-block/text-transform-applies-to-004.xht",
+ "/css/css-conditional/at-supports-002.html",
[
[
- "/css/reference/pass_if_letter_uppercase.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-block/width-applies-to-011.xht": [
+ "css/css-conditional/at-supports-003.html": [
[
- "/css/css-block/width-applies-to-011.xht",
+ "/css/css-conditional/at-supports-003.html",
[
[
- "/css/reference/pass_if_square_96px_black.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-cascade/all-prop-001.html": [
+ "css/css-conditional/at-supports-004.html": [
[
- "/css/css-cascade/all-prop-001.html",
+ "/css/css-conditional/at-supports-004.html",
[
[
- "/css/css-cascade/all-prop-001-ref.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-cascade/all-prop-002.html": [
+ "css/css-conditional/at-supports-005.html": [
[
- "/css/css-cascade/all-prop-002.html",
+ "/css/css-conditional/at-supports-005.html",
[
[
- "/css/css-cascade/reference/ref-filled-green-100px-square.xht",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-cascade/initial-color-background-001.html": [
+ "css/css-conditional/at-supports-006.html": [
[
- "/css/css-cascade/initial-color-background-001.html",
+ "/css/css-conditional/at-supports-006.html",
[
[
- "/css/css-cascade/initial-color-background-001-ref.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-cascade/revert-val-001.html": [
+ "css/css-conditional/at-supports-007.html": [
[
- "/css/css-cascade/revert-val-001.html",
+ "/css/css-conditional/at-supports-007.html",
[
[
- "/css/css-cascade/reference/ref-filled-green-100px-square.xht",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-cascade/unset-val-001.html": [
+ "css/css-conditional/at-supports-008.html": [
[
- "/css/css-cascade/unset-val-001.html",
+ "/css/css-conditional/at-supports-008.html",
[
[
- "/css/css-cascade/reference/ref-filled-green-100px-square.xht",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-cascade/unset-val-002.html": [
+ "css/css-conditional/at-supports-009.html": [
[
- "/css/css-cascade/unset-val-002.html",
+ "/css/css-conditional/at-supports-009.html",
[
[
- "/css/css-cascade/reference/ref-filled-green-100px-square.xht",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/border-bottom-color.xht": [
+ "css/css-conditional/at-supports-010.html": [
[
- "/css/css-color/border-bottom-color.xht",
+ "/css/css-conditional/at-supports-010.html",
[
[
- "/css/css-color/border-color-ref.xht",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/border-left-color.xht": [
+ "css/css-conditional/at-supports-011.html": [
[
- "/css/css-color/border-left-color.xht",
+ "/css/css-conditional/at-supports-011.html",
[
[
- "/css/css-color/border-color-ref.xht",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/border-right-color.xht": [
+ "css/css-conditional/at-supports-012.html": [
[
- "/css/css-color/border-right-color.xht",
+ "/css/css-conditional/at-supports-012.html",
[
[
- "/css/css-color/border-color-ref.xht",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/border-top-color.xht": [
+ "css/css-conditional/at-supports-013.html": [
[
- "/css/css-color/border-top-color.xht",
+ "/css/css-conditional/at-supports-013.html",
[
[
- "/css/css-color/border-color-ref.xht",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/color-001.html": [
+ "css/css-conditional/at-supports-014.html": [
[
- "/css/css-color/color-001.html",
+ "/css/css-conditional/at-supports-014.html",
[
[
- "/css/css-color/greentext-ref.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/color-002.html": [
+ "css/css-conditional/at-supports-015.html": [
[
- "/css/css-color/color-002.html",
+ "/css/css-conditional/at-supports-015.html",
[
[
- "/css/css-color/blacktext-ref.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/color-003.html": [
+ "css/css-conditional/at-supports-016.html": [
[
- "/css/css-color/color-003.html",
+ "/css/css-conditional/at-supports-016.html",
[
[
- "/css/css-color/greentext-ref.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/currentcolor-001.html": [
+ "css/css-conditional/at-supports-017.html": [
[
- "/css/css-color/currentcolor-001.html",
+ "/css/css-conditional/at-supports-017.html",
[
[
- "/css/css-color/greentext-ref.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/currentcolor-002.html": [
+ "css/css-conditional/at-supports-018.html": [
[
- "/css/css-color/currentcolor-002.html",
+ "/css/css-conditional/at-supports-018.html",
[
[
- "/css/css-color/greentext-ref.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/hex-001.html": [
+ "css/css-conditional/at-supports-019.html": [
[
- "/css/css-color/hex-001.html",
+ "/css/css-conditional/at-supports-019.html",
[
[
- "/css/css-color/greentext-ref.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/hex-002.html": [
+ "css/css-conditional/at-supports-020.html": [
[
- "/css/css-color/hex-002.html",
+ "/css/css-conditional/at-supports-020.html",
[
[
- "/css/css-color/greentext-ref.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/lab-001.html": [
+ "css/css-conditional/at-supports-021.html": [
[
- "/css/css-color/lab-001.html",
+ "/css/css-conditional/at-supports-021.html",
[
[
- "/css/css-color/greentext-ref.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/lab-002.html": [
+ "css/css-conditional/at-supports-022.html": [
[
- "/css/css-color/lab-002.html",
+ "/css/css-conditional/at-supports-022.html",
[
[
- "/css/css-color/blacktext-ref.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/lab-003.html": [
+ "css/css-conditional/at-supports-023.html": [
[
- "/css/css-color/lab-003.html",
+ "/css/css-conditional/at-supports-023.html",
[
[
- "/css/css-color/whitetext-ref.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/lab-004.html": [
+ "css/css-conditional/at-supports-024.html": [
[
- "/css/css-color/lab-004.html",
+ "/css/css-conditional/at-supports-024.html",
[
[
- "/css/css-color/blacktext-ref.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/lab-005.html": [
+ "css/css-conditional/at-supports-025.html": [
[
- "/css/css-color/lab-005.html",
+ "/css/css-conditional/at-supports-025.html",
[
[
- "/css/css-color/blacktext-ref.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/lab-006.html": [
+ "css/css-conditional/at-supports-026.html": [
[
- "/css/css-color/lab-006.html",
+ "/css/css-conditional/at-supports-026.html",
[
[
- "/css/css-color/blacktext-ref.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/lab-007.html": [
+ "css/css-conditional/at-supports-027.html": [
[
- "/css/css-color/lab-007.html",
+ "/css/css-conditional/at-supports-027.html",
[
[
- "/css/css-color/blacktext-ref.html",
+ "/css/css-conditional/at-supports-027-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/lch-001.html": [
+ "css/css-conditional/at-supports-028.html": [
[
- "/css/css-color/lch-001.html",
+ "/css/css-conditional/at-supports-028.html",
[
[
- "/css/css-color/greentext-ref.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/lch-002.html": [
+ "css/css-conditional/at-supports-029.html": [
[
- "/css/css-color/lch-002.html",
+ "/css/css-conditional/at-supports-029.html",
[
[
- "/css/css-color/blacktext-ref.html",
+ "/css/css-conditional/at-supports-027-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/lch-003.html": [
+ "css/css-conditional/at-supports-030.html": [
[
- "/css/css-color/lch-003.html",
+ "/css/css-conditional/at-supports-030.html",
[
[
- "/css/css-color/whitetext-ref.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/lch-004.html": [
+ "css/css-conditional/at-supports-031.html": [
[
- "/css/css-color/lch-004.html",
+ "/css/css-conditional/at-supports-031.html",
[
[
- "/css/css-color/blacktext-ref.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/lch-005.html": [
+ "css/css-conditional/at-supports-032.html": [
[
- "/css/css-color/lch-005.html",
+ "/css/css-conditional/at-supports-032.html",
[
[
- "/css/css-color/blacktext-ref.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/lch-006.html": [
+ "css/css-conditional/at-supports-033.html": [
[
- "/css/css-color/lch-006.html",
+ "/css/css-conditional/at-supports-033.html",
[
[
- "/css/css-color/blacktext-ref.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/lch-007.html": [
+ "css/css-conditional/at-supports-034.html": [
[
- "/css/css-color/lch-007.html",
+ "/css/css-conditional/at-supports-034.html",
[
[
- "/css/css-color/blacktext-ref.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/named-001.html": [
+ "css/css-conditional/at-supports-035.html": [
[
- "/css/css-color/named-001.html",
+ "/css/css-conditional/at-supports-035.html",
[
[
- "/css/css-color/rebeccapurple-ref.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/rgb-001.html": [
+ "css/css-conditional/at-supports-036.html": [
[
- "/css/css-color/rgb-001.html",
+ "/css/css-conditional/at-supports-036.html",
[
[
- "/css/css-color/greentext-ref.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/rgb-002.html": [
+ "css/css-conditional/at-supports-037.html": [
[
- "/css/css-color/rgb-002.html",
+ "/css/css-conditional/at-supports-037.html",
[
[
- "/css/css-color/greentext-ref.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/rgb-003.html": [
+ "css/css-conditional/at-supports-038.html": [
[
- "/css/css-color/rgb-003.html",
+ "/css/css-conditional/at-supports-038.html",
[
[
- "/css/css-color/greentext-ref.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/rgb-004.html": [
+ "css/css-conditional/at-supports-039.html": [
[
- "/css/css-color/rgb-004.html",
+ "/css/css-conditional/at-supports-039.html",
[
[
- "/css/css-color/greentext-ref.html",
+ "/css/css-conditional/at-supports-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/rgb-005.html": [
+ "css/css-contain/contain-style-counters.html": [
[
- "/css/css-color/rgb-005.html",
+ "/css/css-contain/contain-style-counters.html",
[
[
- "/css/css-color/greentext-ref.html",
+ "/css/css-contain/contain-style-counters-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/rgb-006.html": [
+ "css/css-display/display-contents-alignment-001.html": [
[
- "/css/css-color/rgb-006.html",
+ "/css/css-display/display-contents-alignment-001.html",
[
[
- "/css/css-color/greentext-ref.html",
+ "/css/css-display/display-contents-alignment-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/rgb-007.html": [
+ "css/css-display/display-contents-alignment-002.html": [
[
- "/css/css-color/rgb-007.html",
+ "/css/css-display/display-contents-alignment-002.html",
[
[
- "/css/css-color/greentext-ref.html",
+ "/css/css-display/display-contents-alignment-002-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/rgb-008.html": [
+ "css/css-display/display-contents-before-after-001.html": [
[
- "/css/css-color/rgb-008.html",
+ "/css/css-display/display-contents-before-after-001.html",
[
[
- "/css/css-color/greentext-ref.html",
+ "/css/css-display/display-contents-pass-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/rgba-001.html": [
+ "css/css-display/display-contents-before-after-002.html": [
[
- "/css/css-color/rgba-001.html",
+ "/css/css-display/display-contents-before-after-002.html",
[
[
- "/css/css-color/greentext-ref.html",
+ "/css/css-display/display-contents-pass-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/rgba-002.html": [
+ "css/css-display/display-contents-before-after-003.html": [
[
- "/css/css-color/rgba-002.html",
+ "/css/css-display/display-contents-before-after-003.html",
[
[
- "/css/css-color/greentext-ref.html",
+ "/css/css-display/display-contents-pass-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/rgba-003.html": [
+ "css/css-display/display-contents-block-001.html": [
[
- "/css/css-color/rgba-003.html",
+ "/css/css-display/display-contents-block-001.html",
[
[
- "/css/css-color/greentext-ref.html",
+ "/css/css-display/display-contents-pass-no-red-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/rgba-004.html": [
+ "css/css-display/display-contents-block-002.html": [
[
- "/css/css-color/rgba-004.html",
+ "/css/css-display/display-contents-block-002.html",
[
[
- "/css/css-color/greentext-ref.html",
+ "/css/css-display/display-contents-block-002-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/rgba-005.html": [
+ "css/css-display/display-contents-button.html": [
[
- "/css/css-color/rgba-005.html",
+ "/css/css-display/display-contents-button.html",
[
[
- "/css/css-color/greentext-ref.html",
+ "/css/css-display/display-contents-pass-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/rgba-006.html": [
+ "css/css-display/display-contents-details.html": [
[
- "/css/css-color/rgba-006.html",
+ "/css/css-display/display-contents-details.html",
[
[
- "/css/css-color/greentext-ref.html",
+ "/css/css-display/display-contents-pass-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/rgba-007.html": [
+ "css/css-display/display-contents-dynamic-before-after-001.html": [
[
- "/css/css-color/rgba-007.html",
+ "/css/css-display/display-contents-dynamic-before-after-001.html",
[
[
- "/css/css-color/greentext-ref.html",
+ "/css/css-display/display-contents-pass-green-no-red-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/rgba-008.html": [
+ "css/css-display/display-contents-dynamic-before-after-first-letter-001.html": [
[
- "/css/css-color/rgba-008.html",
+ "/css/css-display/display-contents-dynamic-before-after-first-letter-001.html",
[
[
- "/css/css-color/greentext-ref.html",
+ "/css/css-display/display-contents-pass-green-no-red-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t31-color-currentColor-b.xht": [
+ "css/css-display/display-contents-dynamic-flex-001-inline.html": [
[
- "/css/css-color/t31-color-currentColor-b.xht",
+ "/css/css-display/display-contents-dynamic-flex-001-inline.html",
[
[
- "/css/css-color/t31-color-currentColor-b-ref.html",
+ "/css/css-display/display-contents-flex-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t31-color-text-a.xht": [
+ "css/css-display/display-contents-dynamic-flex-001-none.html": [
[
- "/css/css-color/t31-color-text-a.xht",
+ "/css/css-display/display-contents-dynamic-flex-001-none.html",
[
[
- "/css/css-color/t31-color-text-a-ref.xht",
- "!="
+ "/css/css-display/display-contents-flex-001-ref.html",
+ "=="
]
],
{}
]
],
- "css/css-color/t32-opacity-offscreen-multiple-boxes-1-c.xht": [
+ "css/css-display/display-contents-dynamic-flex-002-inline.html": [
[
- "/css/css-color/t32-opacity-offscreen-multiple-boxes-1-c.xht",
+ "/css/css-display/display-contents-dynamic-flex-002-inline.html",
[
[
- "/css/css-color/t32-opacity-offscreen-multiple-boxes-1-c-ref.html",
+ "/css/css-display/display-contents-flex-002-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t32-opacity-offscreen-multiple-boxes-2-c.xht": [
+ "css/css-display/display-contents-dynamic-flex-002-none.html": [
[
- "/css/css-color/t32-opacity-offscreen-multiple-boxes-2-c.xht",
+ "/css/css-display/display-contents-dynamic-flex-002-none.html",
[
[
- "/css/css-color/t32-opacity-offscreen-multiple-boxes-2-c-ref.html",
+ "/css/css-display/display-contents-flex-002-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t421-rgb-func-int-a.xht": [
+ "css/css-display/display-contents-dynamic-flex-003-inline.html": [
[
- "/css/css-color/t421-rgb-func-int-a.xht",
+ "/css/css-display/display-contents-dynamic-flex-003-inline.html",
[
[
- "/css/css-color/t422-rgba-func-int-a-ref.html",
+ "/css/css-display/display-contents-flex-002-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t421-rgb-func-no-mixed-f.xht": [
+ "css/css-display/display-contents-dynamic-flex-003-none.html": [
[
- "/css/css-color/t421-rgb-func-no-mixed-f.xht",
+ "/css/css-display/display-contents-dynamic-flex-003-none.html",
[
[
- "/css/css-color/t422-rgba-func-no-mixed-f-ref.html",
+ "/css/css-display/display-contents-flex-002-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t421-rgb-func-pct-a.xht": [
+ "css/css-display/display-contents-dynamic-generated-content-fieldset-001.html": [
[
- "/css/css-color/t421-rgb-func-pct-a.xht",
+ "/css/css-display/display-contents-dynamic-generated-content-fieldset-001.html",
[
[
- "/css/css-color/t422-rgba-func-int-a-ref.html",
+ "/css/css-display/display-contents-dynamic-generated-content-fieldset-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t421-rgb-func-whitespace-b.xht": [
+ "css/css-display/display-contents-dynamic-inline-flex-001-inline.html": [
[
- "/css/css-color/t421-rgb-func-whitespace-b.xht",
+ "/css/css-display/display-contents-dynamic-inline-flex-001-inline.html",
[
[
- "/css/css-color/t422-rgba-func-whitespace-b-ref.html",
+ "/css/css-display/display-contents-inline-flex-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t421-rgb-hex-parsing-f.xht": [
+ "css/css-display/display-contents-dynamic-inline-flex-001-none.html": [
[
- "/css/css-color/t421-rgb-hex-parsing-f.xht",
+ "/css/css-display/display-contents-dynamic-inline-flex-001-none.html",
[
[
- "/css/css-color/t422-rgba-func-no-mixed-f-ref.html",
+ "/css/css-display/display-contents-inline-flex-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t421-rgb-hex3-a.xht": [
+ "css/css-display/display-contents-dynamic-list-001-inline.html": [
[
- "/css/css-color/t421-rgb-hex3-a.xht",
+ "/css/css-display/display-contents-dynamic-list-001-inline.html",
[
[
- "/css/css-color/t422-rgba-func-int-a-ref.html",
+ "/css/css-display/display-contents-list-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t421-rgb-hex6-a.xht": [
+ "css/css-display/display-contents-dynamic-list-001-none.html": [
[
- "/css/css-color/t421-rgb-hex6-a.xht",
+ "/css/css-display/display-contents-dynamic-list-001-none.html",
[
[
- "/css/css-color/t422-rgba-func-int-a-ref.html",
+ "/css/css-display/display-contents-list-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t422-rgba-a1.0-a.xht": [
+ "css/css-display/display-contents-dynamic-multicol-001-inline.html": [
[
- "/css/css-color/t422-rgba-a1.0-a.xht",
+ "/css/css-display/display-contents-dynamic-multicol-001-inline.html",
[
[
- "/css/css-color/t422-rgba-a1.0-a-ref.html",
+ "/css/css-display/display-contents-multicol-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t422-rgba-clamping-a0.0-b.xht": [
+ "css/css-display/display-contents-dynamic-multicol-001-none.html": [
[
- "/css/css-color/t422-rgba-clamping-a0.0-b.xht",
+ "/css/css-display/display-contents-dynamic-multicol-001-none.html",
[
[
- "/css/css-color/t422-rgba-clamping-a0.0-b-ref.html",
+ "/css/css-display/display-contents-multicol-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t422-rgba-clamping-a1.0-b.xht": [
+ "css/css-display/display-contents-dynamic-pseudo-insertion-001.html": [
[
- "/css/css-color/t422-rgba-clamping-a1.0-b.xht",
+ "/css/css-display/display-contents-dynamic-pseudo-insertion-001.html",
[
[
- "/css/css-color/t422-rgba-clamping-a1.0-b-ref.html",
+ "/css/css-display/display-contents-dynamic-pseudo-insertion-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t422-rgba-clip-outside-device-gamut-b.xht": [
+ "css/css-display/display-contents-dynamic-table-001-inline.html": [
[
- "/css/css-color/t422-rgba-clip-outside-device-gamut-b.xht",
+ "/css/css-display/display-contents-dynamic-table-001-inline.html",
[
[
- "/css/css-color/t422-rgba-clip-outside-device-gamut-b-ref.html",
+ "/css/css-display/display-contents-table-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t422-rgba-func-int-a.xht": [
+ "css/css-display/display-contents-dynamic-table-001-none.html": [
[
- "/css/css-color/t422-rgba-func-int-a.xht",
+ "/css/css-display/display-contents-dynamic-table-001-none.html",
[
[
- "/css/css-color/t422-rgba-func-int-a-ref.html",
+ "/css/css-display/display-contents-table-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t422-rgba-func-no-mixed-f.xht": [
+ "css/css-display/display-contents-dynamic-table-002-inline.html": [
[
- "/css/css-color/t422-rgba-func-no-mixed-f.xht",
+ "/css/css-display/display-contents-dynamic-table-002-inline.html",
[
[
- "/css/css-color/t422-rgba-func-no-mixed-f-ref.html",
+ "/css/css-display/display-contents-table-002-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t422-rgba-func-pct-a.xht": [
+ "css/css-display/display-contents-dynamic-table-002-none.html": [
[
- "/css/css-color/t422-rgba-func-pct-a.xht",
+ "/css/css-display/display-contents-dynamic-table-002-none.html",
[
[
- "/css/css-color/t422-rgba-func-int-a-ref.html",
+ "/css/css-display/display-contents-table-002-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t422-rgba-func-whitespace-b.xht": [
+ "css/css-display/display-contents-fieldset.html": [
[
- "/css/css-color/t422-rgba-func-whitespace-b.xht",
+ "/css/css-display/display-contents-fieldset.html",
[
[
- "/css/css-color/t422-rgba-func-whitespace-b-ref.html",
+ "/css/css-display/display-contents-pass-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t422-rgba-onscreen-b.xht": [
+ "css/css-display/display-contents-first-letter-001.html": [
[
- "/css/css-color/t422-rgba-onscreen-b.xht",
+ "/css/css-display/display-contents-first-letter-001.html",
[
[
- "/css/css-color/t422-rgba-onscreen-b-ref.html",
+ "/css/css-display/display-contents-pass-green-no-red-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t422-rgba-onscreen-multiple-boxes-c.xht": [
+ "css/css-display/display-contents-first-letter-002.html": [
[
- "/css/css-color/t422-rgba-onscreen-multiple-boxes-c.xht",
+ "/css/css-display/display-contents-first-letter-002.html",
[
[
- "/css/css-color/t422-rgba-onscreen-multiple-boxes-c-ref.html",
+ "/css/css-display/display-contents-pass-green-no-red-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t423-transparent-1-a.xht": [
+ "css/css-display/display-contents-first-line-001.html": [
[
- "/css/css-color/t423-transparent-1-a.xht",
+ "/css/css-display/display-contents-first-line-001.html",
[
[
- "/css/css-color/t422-rgba-clamping-a0.0-b-ref.html",
+ "/css/css-display/display-contents-pass-green-no-red-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t423-transparent-2-a.xht": [
+ "css/css-display/display-contents-first-line-002.html": [
[
- "/css/css-color/t423-transparent-2-a.xht",
+ "/css/css-display/display-contents-first-line-002.html",
[
[
- "/css/css-color/t423-transparent-2-a-ref.html",
+ "/css/css-display/display-contents-pass-green-no-red-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t424-hsl-basic-a.xht": [
+ "css/css-display/display-contents-flex-001.html": [
[
- "/css/css-color/t424-hsl-basic-a.xht",
+ "/css/css-display/display-contents-flex-001.html",
[
[
- "/css/css-color/t424-hsl-basic-a-ref.html",
+ "/css/css-display/display-contents-flex-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t424-hsl-clip-outside-gamut-b.xht": [
+ "css/css-display/display-contents-flex-002.html": [
[
- "/css/css-color/t424-hsl-clip-outside-gamut-b.xht",
+ "/css/css-display/display-contents-flex-002.html",
[
[
- "/css/css-color/t424-hsl-clip-outside-gamut-b-ref.html",
+ "/css/css-display/display-contents-flex-002-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t424-hsl-parsing-f.xht": [
+ "css/css-display/display-contents-flex-003.html": [
[
- "/css/css-color/t424-hsl-parsing-f.xht",
+ "/css/css-display/display-contents-flex-003.html",
[
[
- "/css/css-color/t424-hsl-parsing-f-ref.html",
+ "/css/css-display/display-contents-flex-002-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t424-hsl-values-b-1.html": [
+ "css/css-display/display-contents-float-001.html": [
[
- "/css/css-color/t424-hsl-values-b-1.html",
+ "/css/css-display/display-contents-float-001.html",
[
[
- "/css/css-color/t424-hsl-values-b-1-ref.html",
+ "/css/css-display/display-contents-pass-no-red-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t424-hsl-values-b-10.html": [
+ "css/css-display/display-contents-inline-001.html": [
[
- "/css/css-color/t424-hsl-values-b-10.html",
+ "/css/css-display/display-contents-inline-001.html",
[
[
- "/css/css-color/t424-hsl-values-b-10-ref.html",
+ "/css/css-display/display-contents-pass-no-red-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t424-hsl-values-b-11.html": [
+ "css/css-display/display-contents-inline-flex-001.html": [
[
- "/css/css-color/t424-hsl-values-b-11.html",
+ "/css/css-display/display-contents-inline-flex-001.html",
[
[
- "/css/css-color/t424-hsl-values-b-11-ref.html",
+ "/css/css-display/display-contents-inline-flex-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t424-hsl-values-b-12.html": [
+ "css/css-display/display-contents-line-height.html": [
[
- "/css/css-color/t424-hsl-values-b-12.html",
+ "/css/css-display/display-contents-line-height.html",
[
[
- "/css/css-color/t424-hsl-values-b-12-ref.html",
+ "/css/css-display/display-contents-line-height-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t424-hsl-values-b-13.html": [
+ "css/css-display/display-contents-list-001.html": [
[
- "/css/css-color/t424-hsl-values-b-13.html",
+ "/css/css-display/display-contents-list-001.html",
[
[
- "/css/css-color/t424-hsl-values-b-13-ref.html",
+ "/css/css-display/display-contents-list-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t424-hsl-values-b-14.html": [
+ "css/css-display/display-contents-multicol-001.html": [
[
- "/css/css-color/t424-hsl-values-b-14.html",
+ "/css/css-display/display-contents-multicol-001.html",
[
[
- "/css/css-color/t424-hsl-values-b-14-ref.html",
+ "/css/css-display/display-contents-multicol-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t424-hsl-values-b-15.html": [
+ "css/css-display/display-contents-oof-001.html": [
[
- "/css/css-color/t424-hsl-values-b-15.html",
+ "/css/css-display/display-contents-oof-001.html",
[
[
- "/css/css-color/t424-hsl-values-b-15-ref.html",
+ "/css/css-display/display-contents-pass-no-red-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t424-hsl-values-b-2.html": [
+ "css/css-display/display-contents-oof-002.html": [
[
- "/css/css-color/t424-hsl-values-b-2.html",
+ "/css/css-display/display-contents-oof-002.html",
[
[
- "/css/css-color/t424-hsl-values-b-2-ref.html",
+ "/css/css-display/display-contents-pass-no-red-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t424-hsl-values-b-3.html": [
+ "css/css-display/display-contents-state-change-001.html": [
[
- "/css/css-color/t424-hsl-values-b-3.html",
+ "/css/css-display/display-contents-state-change-001.html",
[
[
- "/css/css-color/t424-hsl-values-b-3-ref.html",
+ "/css/css-display/display-contents-state-change-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t424-hsl-values-b-4.html": [
+ "css/css-display/display-contents-svg-elements.html": [
[
- "/css/css-color/t424-hsl-values-b-4.html",
+ "/css/css-display/display-contents-svg-elements.html",
[
[
- "/css/css-color/t424-hsl-values-b-4-ref.html",
+ "/css/css-display/display-contents-svg-elements-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t424-hsl-values-b-5.html": [
+ "css/css-display/display-contents-table-001.html": [
[
- "/css/css-color/t424-hsl-values-b-5.html",
+ "/css/css-display/display-contents-table-001.html",
[
[
- "/css/css-color/t424-hsl-values-b-5-ref.html",
+ "/css/css-display/display-contents-table-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t424-hsl-values-b-6.html": [
+ "css/css-display/display-contents-table-002.html": [
[
- "/css/css-color/t424-hsl-values-b-6.html",
+ "/css/css-display/display-contents-table-002.html",
[
[
- "/css/css-color/t424-hsl-values-b-6-ref.html",
+ "/css/css-display/display-contents-table-002-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t424-hsl-values-b-7.html": [
+ "css/css-display/display-contents-td-001.html": [
[
- "/css/css-color/t424-hsl-values-b-7.html",
+ "/css/css-display/display-contents-td-001.html",
[
[
- "/css/css-color/t424-hsl-values-b-7-ref.html",
+ "/css/css-display/display-contents-pass-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t424-hsl-values-b-8.html": [
+ "css/css-display/display-contents-text-inherit.html": [
[
- "/css/css-color/t424-hsl-values-b-8.html",
+ "/css/css-display/display-contents-text-inherit.html",
[
[
- "/css/css-color/t424-hsl-values-b-8-ref.html",
+ "/css/css-display/display-contents-text-inherit-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t424-hsl-values-b-9.html": [
+ "css/css-display/display-contents-text-only-001.html": [
[
- "/css/css-color/t424-hsl-values-b-9.html",
+ "/css/css-display/display-contents-text-only-001.html",
[
[
- "/css/css-color/t424-hsl-values-b-9-ref.html",
+ "/css/css-display/display-contents-text-only-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t425-hsla-clip-outside-device-gamut-b.xht": [
+ "css/css-display/display-contents-tr-001.html": [
[
- "/css/css-color/t425-hsla-clip-outside-device-gamut-b.xht",
+ "/css/css-display/display-contents-tr-001.html",
[
[
- "/css/css-color/t425-hsla-clip-outside-device-gamut-b-ref.html",
+ "/css/css-display/display-contents-tr-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t425-hsla-onscreen-multiple-boxes-c.xht": [
+ "css/css-display/display-contents-unusual-html-elements-none.html": [
[
- "/css/css-color/t425-hsla-onscreen-multiple-boxes-c.xht",
+ "/css/css-display/display-contents-unusual-html-elements-none.html",
[
[
- "/css/css-color/t422-rgba-onscreen-multiple-boxes-c-ref.html",
+ "/css/css-display/display-contents-pass-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t425-hsla-parsing-f.xht": [
+ "css/css-display/display-flow-root-001.html": [
[
- "/css/css-color/t425-hsla-parsing-f.xht",
+ "/css/css-display/display-flow-root-001.html",
[
[
- "/css/css-color/t424-hsl-parsing-f-ref.html",
+ "/css/css-display/display-flow-root-001-ref.html",
"=="
]
],
{}
]
],
- "css/css-color/t425-hsla-values-b.xht": [
+ "css/css-display/run-in/counter-increment-applies-to-011.xht": [
[
- "/css/css-color/t425-hsla-values-b.xht",
+ "/css/css-display/run-in/counter-increment-applies-to-011.xht",
[
[
- "/css/css-color/t425-hsla-values-b-ref.html",
+ "/css/reference/pass_if_number_5.xht",
"=="
]
],
{}
]
],
- "css/css-color/t44-currentcolor-background-b.xht": [
+ "css/css-display/run-in/counter-reset-applies-to-011.xht": [
[
- "/css/css-color/t44-currentcolor-background-b.xht",
+ "/css/css-display/run-in/counter-reset-applies-to-011.xht",
[
[
- "/css/css-color/t44-currentcolor-background-b-ref.html",
+ "/css/reference/pass_if_number_5.xht",
"=="
]
],
{}
]
],
- "css/css-color/t44-currentcolor-border-b.xht": [
+ "css/css-display/run-in/font-style-applies-to-004.xht": [
[
- "/css/css-color/t44-currentcolor-border-b.xht",
+ "/css/css-display/run-in/font-style-applies-to-004.xht",
[
[
- "/css/css-color/t44-currentcolor-border-b-ref.html",
+ "/css/reference/pass_if_filler_text_slanted.xht",
"=="
]
],
{}
]
],
- "css/css-color/t44-currentcolor-inherited-c.xht": [
+ "css/css-display/run-in/font-variant-applies-to-004.xht": [
[
- "/css/css-color/t44-currentcolor-inherited-c.xht",
+ "/css/css-display/run-in/font-variant-applies-to-004.xht",
[
[
- "/css/css-color/t44-currentcolor-inherited-c-ref.xht",
+ "/css/reference/pass_if_filler_text_match_smallcaps.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-media-whitespace-optional-001.html": [
+ "css/css-display/run-in/font-weight-applies-to-004.xht": [
[
- "/css/css-conditional/at-media-whitespace-optional-001.html",
+ "/css/css-display/run-in/font-weight-applies-to-004.xht",
[
[
- "/css/css-conditional/reference/background-lime.html",
+ "/css/reference/pass_if_filler_text_match_bold.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-media-whitespace-optional-002.html": [
+ "css/css-display/run-in/height-applies-to-011.xht": [
[
- "/css/css-conditional/at-media-whitespace-optional-002.html",
+ "/css/css-display/run-in/height-applies-to-011.xht",
[
[
- "/css/css-conditional/reference/background-lime.html",
+ "/css/reference/pass_if_square_96px_black.html",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-001.html": [
+ "css/css-display/run-in/letter-spacing-applies-to-004.xht": [
[
- "/css/css-conditional/at-supports-001.html",
+ "/css/css-display/run-in/letter-spacing-applies-to-004.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/reference/black_box_ends_when_blue_box_ends_6_boxes_ahem.html",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-002.html": [
+ "css/css-display/run-in/list-style-applies-to-011.xht": [
[
- "/css/css-conditional/at-supports-002.html",
+ "/css/css-display/run-in/list-style-applies-to-011.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/reference/single_square_list_marker.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-003.html": [
+ "css/css-display/run-in/list-style-type-applies-to-011.xht": [
[
- "/css/css-conditional/at-supports-003.html",
+ "/css/css-display/run-in/list-style-type-applies-to-011.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/reference/single_square_list_marker.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-004.html": [
+ "css/css-display/run-in/max-height-applies-to-011.xht": [
[
- "/css/css-conditional/at-supports-004.html",
+ "/css/css-display/run-in/max-height-applies-to-011.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/reference/pass_if_square_96px_black.html",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-005.html": [
+ "css/css-display/run-in/max-width-applies-to-011.xht": [
[
- "/css/css-conditional/at-supports-005.html",
+ "/css/css-display/run-in/max-width-applies-to-011.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/reference/pass_if_square_96px_black.html",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-006.html": [
+ "css/css-display/run-in/min-height-applies-to-011.xht": [
[
- "/css/css-conditional/at-supports-006.html",
+ "/css/css-display/run-in/min-height-applies-to-011.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/reference/pass_if_square_96px_black.html",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-007.html": [
+ "css/css-display/run-in/min-width-applies-to-011.xht": [
[
- "/css/css-conditional/at-supports-007.html",
+ "/css/css-display/run-in/min-width-applies-to-011.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/reference/pass_if_square_96px_black.html",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-008.html": [
+ "css/css-display/run-in/quotes-applies-to-011.xht": [
[
- "/css/css-conditional/at-supports-008.html",
+ "/css/css-display/run-in/quotes-applies-to-011.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/reference/pass_if_pass_below.html",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-009.html": [
+ "css/css-display/run-in/run-in-abspos-between-001.xht": [
[
- "/css/css-conditional/at-supports-009.html",
+ "/css/css-display/run-in/run-in-abspos-between-001.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-010.html": [
+ "css/css-display/run-in/run-in-abspos-between-002.xht": [
[
- "/css/css-conditional/at-supports-010.html",
+ "/css/css-display/run-in/run-in-abspos-between-002.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-011.html": [
+ "css/css-display/run-in/run-in-abspos-between-003.xht": [
[
- "/css/css-conditional/at-supports-011.html",
+ "/css/css-display/run-in/run-in-abspos-between-003.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-text-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-012.html": [
+ "css/css-display/run-in/run-in-basic-001.xht": [
[
- "/css/css-conditional/at-supports-012.html",
+ "/css/css-display/run-in/run-in-basic-001.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-013.html": [
+ "css/css-display/run-in/run-in-basic-002.xht": [
[
- "/css/css-conditional/at-supports-013.html",
+ "/css/css-display/run-in/run-in-basic-002.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-014.html": [
+ "css/css-display/run-in/run-in-basic-003.xht": [
[
- "/css/css-conditional/at-supports-014.html",
+ "/css/css-display/run-in/run-in-basic-003.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-015.html": [
+ "css/css-display/run-in/run-in-basic-004.xht": [
[
- "/css/css-conditional/at-supports-015.html",
+ "/css/css-display/run-in/run-in-basic-004.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-016.html": [
+ "css/css-display/run-in/run-in-basic-005.xht": [
[
- "/css/css-conditional/at-supports-016.html",
+ "/css/css-display/run-in/run-in-basic-005.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-block-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-017.html": [
+ "css/css-display/run-in/run-in-basic-006.xht": [
[
- "/css/css-conditional/at-supports-017.html",
+ "/css/css-display/run-in/run-in-basic-006.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-018.html": [
+ "css/css-display/run-in/run-in-basic-007.xht": [
[
- "/css/css-conditional/at-supports-018.html",
+ "/css/css-display/run-in/run-in-basic-007.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-007-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-019.html": [
+ "css/css-display/run-in/run-in-basic-008.xht": [
[
- "/css/css-conditional/at-supports-019.html",
+ "/css/css-display/run-in/run-in-basic-008.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-020.html": [
+ "css/css-display/run-in/run-in-basic-009.xht": [
[
- "/css/css-conditional/at-supports-020.html",
+ "/css/css-display/run-in/run-in-basic-009.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-021.html": [
+ "css/css-display/run-in/run-in-basic-010.xht": [
[
- "/css/css-conditional/at-supports-021.html",
+ "/css/css-display/run-in/run-in-basic-010.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-022.html": [
+ "css/css-display/run-in/run-in-basic-011.xht": [
[
- "/css/css-conditional/at-supports-022.html",
+ "/css/css-display/run-in/run-in-basic-011.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-023.html": [
+ "css/css-display/run-in/run-in-basic-012.xht": [
[
- "/css/css-conditional/at-supports-023.html",
+ "/css/css-display/run-in/run-in-basic-012.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-024.html": [
+ "css/css-display/run-in/run-in-basic-013.xht": [
[
- "/css/css-conditional/at-supports-024.html",
+ "/css/css-display/run-in/run-in-basic-013.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-025.html": [
+ "css/css-display/run-in/run-in-basic-014.xht": [
[
- "/css/css-conditional/at-supports-025.html",
+ "/css/css-display/run-in/run-in-basic-014.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-pre-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-026.html": [
+ "css/css-display/run-in/run-in-basic-015.xht": [
[
- "/css/css-conditional/at-supports-026.html",
+ "/css/css-display/run-in/run-in-basic-015.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-pre-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-027.html": [
+ "css/css-display/run-in/run-in-basic-016.xht": [
[
- "/css/css-conditional/at-supports-027.html",
+ "/css/css-display/run-in/run-in-basic-016.xht",
[
[
- "/css/css-conditional/at-supports-027-ref.html",
+ "/css/css-display/run-in/run-in-pre-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-028.html": [
+ "css/css-display/run-in/run-in-basic-017.xht": [
[
- "/css/css-conditional/at-supports-028.html",
+ "/css/css-display/run-in/run-in-basic-017.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-pre-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-029.html": [
+ "css/css-display/run-in/run-in-basic-018.xht": [
[
- "/css/css-conditional/at-supports-029.html",
+ "/css/css-display/run-in/run-in-basic-018.xht",
[
[
- "/css/css-conditional/at-supports-027-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-030.html": [
+ "css/css-display/run-in/run-in-block-between-001.xht": [
[
- "/css/css-conditional/at-supports-030.html",
+ "/css/css-display/run-in/run-in-block-between-001.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-text-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-031.html": [
+ "css/css-display/run-in/run-in-block-between-002.xht": [
[
- "/css/css-conditional/at-supports-031.html",
+ "/css/css-display/run-in/run-in-block-between-002.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-text-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-032.html": [
+ "css/css-display/run-in/run-in-block-between-003.xht": [
[
- "/css/css-conditional/at-supports-032.html",
+ "/css/css-display/run-in/run-in-block-between-003.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-033.html": [
+ "css/css-display/run-in/run-in-breaking-001.xht": [
[
- "/css/css-conditional/at-supports-033.html",
+ "/css/css-display/run-in/run-in-breaking-001.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-breaking-001-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-034.html": [
+ "css/css-display/run-in/run-in-breaking-002.xht": [
[
- "/css/css-conditional/at-supports-034.html",
+ "/css/css-display/run-in/run-in-breaking-002.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-breaking-002-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-035.html": [
+ "css/css-display/run-in/run-in-clear-001.xht": [
[
- "/css/css-conditional/at-supports-035.html",
+ "/css/css-display/run-in/run-in-clear-001.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-text-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-036.html": [
+ "css/css-display/run-in/run-in-clear-002.xht": [
[
- "/css/css-conditional/at-supports-036.html",
+ "/css/css-display/run-in/run-in-clear-002.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-text-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-037.html": [
+ "css/css-display/run-in/run-in-contains-abspos-001.xht": [
[
- "/css/css-conditional/at-supports-037.html",
+ "/css/css-display/run-in/run-in-contains-abspos-001.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-038.html": [
+ "css/css-display/run-in/run-in-contains-block-001.xht": [
[
- "/css/css-conditional/at-supports-038.html",
+ "/css/css-display/run-in/run-in-contains-block-001.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-text-ref.xht",
"=="
]
],
{}
]
],
- "css/css-conditional/at-supports-039.html": [
+ "css/css-display/run-in/run-in-contains-block-002.xht": [
[
- "/css/css-conditional/at-supports-039.html",
+ "/css/css-display/run-in/run-in-contains-block-002.xht",
[
[
- "/css/css-conditional/at-supports-001-ref.html",
+ "/css/css-display/run-in/run-in-text-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-alignment-001.html": [
+ "css/css-display/run-in/run-in-contains-block-003.xht": [
[
- "/css/css-display/display-contents-alignment-001.html",
+ "/css/css-display/run-in/run-in-contains-block-003.xht",
[
[
- "/css/css-display/display-contents-alignment-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-alignment-002.html": [
+ "css/css-display/run-in/run-in-contains-block-004.xht": [
[
- "/css/css-display/display-contents-alignment-002.html",
+ "/css/css-display/run-in/run-in-contains-block-004.xht",
[
[
- "/css/css-display/display-contents-alignment-002-ref.html",
+ "/css/css-display/run-in/run-in-text-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-before-after-001.html": [
+ "css/css-display/run-in/run-in-contains-block-005.xht": [
[
- "/css/css-display/display-contents-before-after-001.html",
+ "/css/css-display/run-in/run-in-contains-block-005.xht",
[
[
- "/css/css-display/display-contents-pass-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-before-after-002.html": [
+ "css/css-display/run-in/run-in-contains-block-inside-inline-001.xht": [
[
- "/css/css-display/display-contents-before-after-002.html",
+ "/css/css-display/run-in/run-in-contains-block-inside-inline-001.xht",
[
[
- "/css/css-display/display-contents-pass-ref.html",
+ "/css/css-display/run-in/run-in-text-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-block-001.html": [
+ "css/css-display/run-in/run-in-contains-block-inside-inline-002.xht": [
[
- "/css/css-display/display-contents-block-001.html",
+ "/css/css-display/run-in/run-in-contains-block-inside-inline-002.xht",
[
[
- "/css/css-display/display-contents-pass-no-red-ref.html",
+ "/css/css-display/run-in/run-in-text-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-block-002.html": [
+ "css/css-display/run-in/run-in-contains-block-inside-inline-003.xht": [
[
- "/css/css-display/display-contents-block-002.html",
+ "/css/css-display/run-in/run-in-contains-block-inside-inline-003.xht",
[
[
- "/css/css-display/display-contents-block-002-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-dynamic-before-after-001.html": [
+ "css/css-display/run-in/run-in-contains-float-001.xht": [
[
- "/css/css-display/display-contents-dynamic-before-after-001.html",
+ "/css/css-display/run-in/run-in-contains-float-001.xht",
[
[
- "/css/css-display/display-contents-pass-green-no-red-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-dynamic-before-after-first-letter-001.html": [
+ "css/css-display/run-in/run-in-contains-inline-001.xht": [
[
- "/css/css-display/display-contents-dynamic-before-after-first-letter-001.html",
+ "/css/css-display/run-in/run-in-contains-inline-001.xht",
[
[
- "/css/css-display/display-contents-pass-green-no-red-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-dynamic-flex-001-inline.html": [
+ "css/css-display/run-in/run-in-contains-inline-002.xht": [
[
- "/css/css-display/display-contents-dynamic-flex-001-inline.html",
+ "/css/css-display/run-in/run-in-contains-inline-002.xht",
[
[
- "/css/css-display/display-contents-flex-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-dynamic-flex-001-none.html": [
+ "css/css-display/run-in/run-in-contains-inline-003.xht": [
[
- "/css/css-display/display-contents-dynamic-flex-001-none.html",
+ "/css/css-display/run-in/run-in-contains-inline-003.xht",
[
[
- "/css/css-display/display-contents-flex-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-dynamic-flex-002-inline.html": [
+ "css/css-display/run-in/run-in-contains-inline-004.xht": [
[
- "/css/css-display/display-contents-dynamic-flex-002-inline.html",
+ "/css/css-display/run-in/run-in-contains-inline-004.xht",
[
[
- "/css/css-display/display-contents-flex-002-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-dynamic-flex-002-none.html": [
+ "css/css-display/run-in/run-in-contains-inline-005.xht": [
[
- "/css/css-display/display-contents-dynamic-flex-002-none.html",
+ "/css/css-display/run-in/run-in-contains-inline-005.xht",
[
[
- "/css/css-display/display-contents-flex-002-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-dynamic-flex-003-inline.html": [
+ "css/css-display/run-in/run-in-contains-inline-006.xht": [
[
- "/css/css-display/display-contents-dynamic-flex-003-inline.html",
+ "/css/css-display/run-in/run-in-contains-inline-006.xht",
[
[
- "/css/css-display/display-contents-flex-002-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-dynamic-flex-003-none.html": [
+ "css/css-display/run-in/run-in-contains-inline-007.xht": [
[
- "/css/css-display/display-contents-dynamic-flex-003-none.html",
+ "/css/css-display/run-in/run-in-contains-inline-007.xht",
[
[
- "/css/css-display/display-contents-flex-002-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-dynamic-generated-content-fieldset-001.html": [
+ "css/css-display/run-in/run-in-contains-inline-block-001.xht": [
[
- "/css/css-display/display-contents-dynamic-generated-content-fieldset-001.html",
+ "/css/css-display/run-in/run-in-contains-inline-block-001.xht",
[
[
- "/css/css-display/display-contents-dynamic-generated-content-fieldset-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-dynamic-inline-flex-001-inline.html": [
+ "css/css-display/run-in/run-in-contains-inline-table-001.xht": [
[
- "/css/css-display/display-contents-dynamic-inline-flex-001-inline.html",
+ "/css/css-display/run-in/run-in-contains-inline-table-001.xht",
[
[
- "/css/css-display/display-contents-inline-flex-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-dynamic-inline-flex-001-none.html": [
+ "css/css-display/run-in/run-in-contains-relpos-block-001.xht": [
[
- "/css/css-display/display-contents-dynamic-inline-flex-001-none.html",
+ "/css/css-display/run-in/run-in-contains-relpos-block-001.xht",
[
[
- "/css/css-display/display-contents-inline-flex-001-ref.html",
+ "/css/css-display/run-in/run-in-text-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-dynamic-list-001-inline.html": [
+ "css/css-display/run-in/run-in-contains-relpos-block-002.xht": [
[
- "/css/css-display/display-contents-dynamic-list-001-inline.html",
+ "/css/css-display/run-in/run-in-contains-relpos-block-002.xht",
[
[
- "/css/css-display/display-contents-list-001-ref.html",
+ "/css/css-display/run-in/run-in-text-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-dynamic-list-001-none.html": [
+ "css/css-display/run-in/run-in-contains-relpos-block-003.xht": [
[
- "/css/css-display/display-contents-dynamic-list-001-none.html",
+ "/css/css-display/run-in/run-in-contains-relpos-block-003.xht",
[
[
- "/css/css-display/display-contents-list-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-dynamic-multicol-001-inline.html": [
+ "css/css-display/run-in/run-in-contains-run-in-001.xht": [
[
- "/css/css-display/display-contents-dynamic-multicol-001-inline.html",
+ "/css/css-display/run-in/run-in-contains-run-in-001.xht",
[
[
- "/css/css-display/display-contents-multicol-001-ref.html",
+ "/css/css-display/run-in/run-in-text-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-dynamic-multicol-001-none.html": [
+ "css/css-display/run-in/run-in-contains-run-in-002.xht": [
[
- "/css/css-display/display-contents-dynamic-multicol-001-none.html",
+ "/css/css-display/run-in/run-in-contains-run-in-002.xht",
[
[
- "/css/css-display/display-contents-multicol-001-ref.html",
+ "/css/css-display/run-in/run-in-text-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-dynamic-table-001-inline.html": [
+ "css/css-display/run-in/run-in-contains-run-in-003.xht": [
[
- "/css/css-display/display-contents-dynamic-table-001-inline.html",
+ "/css/css-display/run-in/run-in-contains-run-in-003.xht",
[
[
- "/css/css-display/display-contents-table-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-dynamic-table-001-none.html": [
+ "css/css-display/run-in/run-in-contains-table-001.xht": [
[
- "/css/css-display/display-contents-dynamic-table-001-none.html",
+ "/css/css-display/run-in/run-in-contains-table-001.xht",
[
[
- "/css/css-display/display-contents-table-001-ref.html",
+ "/css/css-display/run-in/run-in-text-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-dynamic-table-002-inline.html": [
+ "css/css-display/run-in/run-in-contains-table-002.xht": [
[
- "/css/css-display/display-contents-dynamic-table-002-inline.html",
+ "/css/css-display/run-in/run-in-contains-table-002.xht",
[
[
- "/css/css-display/display-contents-table-002-ref.html",
+ "/css/css-display/run-in/run-in-text-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-dynamic-table-002-none.html": [
+ "css/css-display/run-in/run-in-contains-table-003.xht": [
[
- "/css/css-display/display-contents-dynamic-table-002-none.html",
+ "/css/css-display/run-in/run-in-contains-table-003.xht",
[
[
- "/css/css-display/display-contents-table-002-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-first-letter-001.html": [
+ "css/css-display/run-in/run-in-contains-table-caption-001.xht": [
[
- "/css/css-display/display-contents-first-letter-001.html",
+ "/css/css-display/run-in/run-in-contains-table-caption-001.xht",
[
[
- "/css/css-display/display-contents-pass-green-no-red-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-first-line-001.html": [
+ "css/css-display/run-in/run-in-contains-table-cell-001.xht": [
[
- "/css/css-display/display-contents-first-line-001.html",
+ "/css/css-display/run-in/run-in-contains-table-cell-001.xht",
[
[
- "/css/css-display/display-contents-pass-green-no-red-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-flex-001.html": [
+ "css/css-display/run-in/run-in-contains-table-column-001.xht": [
[
- "/css/css-display/display-contents-flex-001.html",
+ "/css/css-display/run-in/run-in-contains-table-column-001.xht",
[
[
- "/css/css-display/display-contents-flex-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-flex-002.html": [
+ "css/css-display/run-in/run-in-contains-table-column-group-001.xht": [
[
- "/css/css-display/display-contents-flex-002.html",
+ "/css/css-display/run-in/run-in-contains-table-column-group-001.xht",
[
[
- "/css/css-display/display-contents-flex-002-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-flex-003.html": [
+ "css/css-display/run-in/run-in-contains-table-inside-inline-001.xht": [
[
- "/css/css-display/display-contents-flex-003.html",
+ "/css/css-display/run-in/run-in-contains-table-inside-inline-001.xht",
[
[
- "/css/css-display/display-contents-flex-002-ref.html",
+ "/css/css-display/run-in/run-in-text-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-float-001.html": [
+ "css/css-display/run-in/run-in-contains-table-inside-inline-002.xht": [
[
- "/css/css-display/display-contents-float-001.html",
+ "/css/css-display/run-in/run-in-contains-table-inside-inline-002.xht",
[
[
- "/css/css-display/display-contents-pass-no-red-ref.html",
+ "/css/css-display/run-in/run-in-text-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-inline-001.html": [
+ "css/css-display/run-in/run-in-contains-table-inside-inline-003.xht": [
[
- "/css/css-display/display-contents-inline-001.html",
+ "/css/css-display/run-in/run-in-contains-table-inside-inline-003.xht",
[
[
- "/css/css-display/display-contents-pass-no-red-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-inline-flex-001.html": [
+ "css/css-display/run-in/run-in-contains-table-row-001.xht": [
[
- "/css/css-display/display-contents-inline-flex-001.html",
+ "/css/css-display/run-in/run-in-contains-table-row-001.xht",
[
[
- "/css/css-display/display-contents-inline-flex-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-list-001.html": [
+ "css/css-display/run-in/run-in-contains-table-row-group-001.xht": [
[
- "/css/css-display/display-contents-list-001.html",
+ "/css/css-display/run-in/run-in-contains-table-row-group-001.xht",
[
[
- "/css/css-display/display-contents-list-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-multicol-001.html": [
+ "css/css-display/run-in/run-in-display-none-between-001.xht": [
[
- "/css/css-display/display-contents-multicol-001.html",
+ "/css/css-display/run-in/run-in-display-none-between-001.xht",
[
[
- "/css/css-display/display-contents-multicol-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-oof-001.html": [
+ "css/css-display/run-in/run-in-display-none-between-002.xht": [
[
- "/css/css-display/display-contents-oof-001.html",
+ "/css/css-display/run-in/run-in-display-none-between-002.xht",
[
[
- "/css/css-display/display-contents-pass-no-red-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-oof-002.html": [
+ "css/css-display/run-in/run-in-display-none-between-003.xht": [
[
- "/css/css-display/display-contents-oof-002.html",
+ "/css/css-display/run-in/run-in-display-none-between-003.xht",
[
[
- "/css/css-display/display-contents-pass-no-red-ref.html",
+ "/css/css-display/run-in/run-in-text-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-replaced-001.html": [
+ "css/css-display/run-in/run-in-fixedpos-between-001.xht": [
[
- "/css/css-display/display-contents-replaced-001.html",
+ "/css/css-display/run-in/run-in-fixedpos-between-001.xht",
[
[
- "/css/css-display/display-contents-replaced-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-state-change-001.html": [
+ "css/css-display/run-in/run-in-fixedpos-between-002.xht": [
[
- "/css/css-display/display-contents-state-change-001.html",
+ "/css/css-display/run-in/run-in-fixedpos-between-002.xht",
[
[
- "/css/css-display/display-contents-state-change-001-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-table-001.html": [
+ "css/css-display/run-in/run-in-fixedpos-between-003.xht": [
[
- "/css/css-display/display-contents-table-001.html",
+ "/css/css-display/run-in/run-in-fixedpos-between-003.xht",
[
[
- "/css/css-display/display-contents-table-001-ref.html",
+ "/css/css-display/run-in/run-in-text-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-table-002.html": [
+ "css/css-display/run-in/run-in-float-between-001.xht": [
[
- "/css/css-display/display-contents-table-002.html",
+ "/css/css-display/run-in/run-in-float-between-001.xht",
[
[
- "/css/css-display/display-contents-table-002-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-td-001.html": [
+ "css/css-display/run-in/run-in-float-between-002.xht": [
[
- "/css/css-display/display-contents-td-001.html",
+ "/css/css-display/run-in/run-in-float-between-002.xht",
[
[
- "/css/css-display/display-contents-pass-ref.html",
+ "/css/css-display/run-in/run-in-basic-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-text-only-001.html": [
+ "css/css-display/run-in/run-in-float-between-003.xht": [
[
- "/css/css-display/display-contents-text-only-001.html",
+ "/css/css-display/run-in/run-in-float-between-003.xht",
[
[
- "/css/css-display/display-contents-text-only-001-ref.html",
+ "/css/css-display/run-in/run-in-text-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-contents-tr-001.html": [
+ "css/css-display/run-in/run-in-inherit-001.xht": [
[
- "/css/css-display/display-contents-tr-001.html",
+ "/css/css-display/run-in/run-in-inherit-001.xht",
[
[
- "/css/css-display/display-contents-tr-001-ref.html",
+ "/css/css-display/run-in/run-in-inherit-001-ref.xht",
"=="
]
],
{}
]
],
- "css/css-display/display-flow-root-001.html": [
+ "css/css-display/run-in/run-in-inline-between-001.xht": [
[
- "/css/css-display/display-flow-root-001.html",
+ "/css/css-display/run-in/run-in-inline-between-001.xht",
[
[
- "/css/css-display/display-flow-root-001-ref.html",
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-inline-between-002.xht": [
+ [
+ "/css/css-display/run-in/run-in-inline-between-002.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-inline-between-003.xht": [
+ [
+ "/css/css-display/run-in/run-in-inline-between-003.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-basic-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-inline-block-between-001.xht": [
+ [
+ "/css/css-display/run-in/run-in-inline-block-between-001.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-inline-block-between-002.xht": [
+ [
+ "/css/css-display/run-in/run-in-inline-block-between-002.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-inline-block-between-003.xht": [
+ [
+ "/css/css-display/run-in/run-in-inline-block-between-003.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-basic-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-inline-table-between-001.xht": [
+ [
+ "/css/css-display/run-in/run-in-inline-table-between-001.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-inline-table-between-002.xht": [
+ [
+ "/css/css-display/run-in/run-in-inline-table-between-002.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-inline-table-between-003.xht": [
+ [
+ "/css/css-display/run-in/run-in-inline-table-between-003.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-basic-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-listitem-between-001.xht": [
+ [
+ "/css/css-display/run-in/run-in-listitem-between-001.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-listitem-between-002.xht": [
+ [
+ "/css/css-display/run-in/run-in-listitem-between-002.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-listitem-between-003.xht": [
+ [
+ "/css/css-display/run-in/run-in-listitem-between-003.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-basic-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-relpos-between-001.xht": [
+ [
+ "/css/css-display/run-in/run-in-relpos-between-001.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-relpos-between-002.xht": [
+ [
+ "/css/css-display/run-in/run-in-relpos-between-002.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-relpos-between-003.xht": [
+ [
+ "/css/css-display/run-in/run-in-relpos-between-003.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-basic-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-replaced-001.xht": [
+ [
+ "/css/css-display/run-in/run-in-replaced-001.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-replaced-001-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-restyle-001.xht": [
+ [
+ "/css/css-display/run-in/run-in-restyle-001.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-restyle-002.xht": [
+ [
+ "/css/css-display/run-in/run-in-restyle-002.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-restyle-003.xht": [
+ [
+ "/css/css-display/run-in/run-in-restyle-003.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-basic-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-run-in-between-001.xht": [
+ [
+ "/css/css-display/run-in/run-in-run-in-between-001.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-run-in-between-002.xht": [
+ [
+ "/css/css-display/run-in/run-in-run-in-between-002.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-run-in-between-003.xht": [
+ [
+ "/css/css-display/run-in/run-in-run-in-between-003.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-basic-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-run-in-between-004.xht": [
+ [
+ "/css/css-display/run-in/run-in-run-in-between-004.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-run-in-between-005.xht": [
+ [
+ "/css/css-display/run-in/run-in-run-in-between-005.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-run-in-between-006.xht": [
+ [
+ "/css/css-display/run-in/run-in-run-in-between-006.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-basic-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-run-in-between-007.xht": [
+ [
+ "/css/css-display/run-in/run-in-run-in-between-007.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-run-in-between-008.xht": [
+ [
+ "/css/css-display/run-in/run-in-run-in-between-008.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-table-between-001.xht": [
+ [
+ "/css/css-display/run-in/run-in-table-between-001.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-table-between-002.xht": [
+ [
+ "/css/css-display/run-in/run-in-table-between-002.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-table-between-003.xht": [
+ [
+ "/css/css-display/run-in/run-in-table-between-003.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-basic-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-table-cell-between-001.xht": [
+ [
+ "/css/css-display/run-in/run-in-table-cell-between-001.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-table-cell-between-002.xht": [
+ [
+ "/css/css-display/run-in/run-in-table-cell-between-002.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-table-cell-between-003.xht": [
+ [
+ "/css/css-display/run-in/run-in-table-cell-between-003.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-basic-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-table-row-between-001.xht": [
+ [
+ "/css/css-display/run-in/run-in-table-row-between-001.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-table-row-between-002.xht": [
+ [
+ "/css/css-display/run-in/run-in-table-row-between-002.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-table-row-between-003.xht": [
+ [
+ "/css/css-display/run-in/run-in-table-row-between-003.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-basic-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-text-between-001.xht": [
+ [
+ "/css/css-display/run-in/run-in-text-between-001.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-text-between-002.xht": [
+ [
+ "/css/css-display/run-in/run-in-text-between-002.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-text-between-003.xht": [
+ [
+ "/css/css-display/run-in/run-in-text-between-003.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-text-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-text-between-004.xht": [
+ [
+ "/css/css-display/run-in/run-in-text-between-004.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-basic-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-text-between-005.xht": [
+ [
+ "/css/css-display/run-in/run-in-text-between-005.xht",
+ [
+ [
+ "/css/css-display/run-in/run-in-basic-ref.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/text-decoration-applies-to-004.xht": [
+ [
+ "/css/css-display/run-in/text-decoration-applies-to-004.xht",
+ [
+ [
+ "/css/reference/pass_if_filler_text_underlined.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/text-transform-applies-to-004.xht": [
+ [
+ "/css/css-display/run-in/text-transform-applies-to-004.xht",
+ [
+ [
+ "/css/reference/pass_if_letter_uppercase.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-display/run-in/width-applies-to-011.xht": [
+ [
+ "/css/css-display/run-in/width-applies-to-011.xht",
+ [
+ [
+ "/css/reference/pass_if_square_96px_black.html",
"=="
]
],
@@ -104673,6 +106935,78 @@
{}
]
],
+ "css/css-flexbox/anonymous-flex-item-001.html": [
+ [
+ "/css/css-flexbox/anonymous-flex-item-001.html",
+ [
+ [
+ "/css/css-flexbox/anonymous-flex-item-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-flexbox/anonymous-flex-item-002.html": [
+ [
+ "/css/css-flexbox/anonymous-flex-item-002.html",
+ [
+ [
+ "/css/css-flexbox/anonymous-flex-item-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-flexbox/anonymous-flex-item-003.html": [
+ [
+ "/css/css-flexbox/anonymous-flex-item-003.html",
+ [
+ [
+ "/css/css-flexbox/anonymous-flex-item-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-flexbox/anonymous-flex-item-004.html": [
+ [
+ "/css/css-flexbox/anonymous-flex-item-004.html",
+ [
+ [
+ "/css/css-flexbox/anonymous-flex-item-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-flexbox/anonymous-flex-item-005.html": [
+ [
+ "/css/css-flexbox/anonymous-flex-item-005.html",
+ [
+ [
+ "/css/css-flexbox/anonymous-flex-item-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-flexbox/anonymous-flex-item-006.html": [
+ [
+ "/css/css-flexbox/anonymous-flex-item-006.html",
+ [
+ [
+ "/css/css-flexbox/anonymous-flex-item-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/css-flexbox/auto-margins-001.html": [
[
"/css/css-flexbox/auto-margins-001.html",
@@ -108429,6 +110763,18 @@
{}
]
],
+ "css/css-flexbox/percentage-heights-004.html": [
+ [
+ "/css/css-flexbox/percentage-heights-004.html",
+ [
+ [
+ "/css/css-flexbox/percentage-heights-004-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/css-flexbox/percentage-widths-001.html": [
[
"/css/css-flexbox/percentage-widths-001.html",
@@ -108453,6 +110799,30 @@
{}
]
],
+ "css/css-flexbox/table-as-item-narrow-content.html": [
+ [
+ "/css/css-flexbox/table-as-item-narrow-content.html",
+ [
+ [
+ "/css/reference/ref-filled-green-100px-square-only.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-flexbox/table-as-item-wide-content.html": [
+ [
+ "/css/css-flexbox/table-as-item-wide-content.html",
+ [
+ [
+ "/css/reference/ref-filled-green-100px-square-only.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/css-flexbox/ttwf-reftest-flex-align-content-center.html": [
[
"/css/css-flexbox/ttwf-reftest-flex-align-content-center.html",
@@ -108633,6 +111003,158 @@
{}
]
],
+ "css/css-fonts/first-available-font-001.html": [
+ [
+ "/css/css-fonts/first-available-font-001.html",
+ [
+ [
+ "/css/css-fonts/first-available-font-001-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-fonts/first-available-font-002.html": [
+ [
+ "/css/css-fonts/first-available-font-002.html",
+ [
+ [
+ "/css/css-fonts/first-available-font-002-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-fonts/first-available-font-003.html": [
+ [
+ "/css/css-fonts/first-available-font-003.html",
+ [
+ [
+ "/css/css-fonts/first-available-font-003-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-fonts/first-available-font-004.html": [
+ [
+ "/css/css-fonts/first-available-font-004.html",
+ [
+ [
+ "/css/css-fonts/first-available-font-003-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-fonts/first-available-font-005.html": [
+ [
+ "/css/css-fonts/first-available-font-005.html",
+ [
+ [
+ "/css/css-fonts/first-available-font-005-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-fonts/first-available-font-006.html": [
+ [
+ "/css/css-fonts/first-available-font-006.html",
+ [
+ [
+ "/css/css-fonts/first-available-font-005-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-fonts/first-available-font-007.html": [
+ [
+ "/css/css-fonts/first-available-font-007.html",
+ [
+ [
+ "/css/css-fonts/first-available-font-005-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-fonts/font-default-01.html": [
+ [
+ "/css/css-fonts/font-default-01.html",
+ [
+ [
+ "/css/css-fonts/font-default-01-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-fonts/font-default-02.html": [
+ [
+ "/css/css-fonts/font-default-02.html",
+ [
+ [
+ "/css/css-fonts/font-default-02-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-fonts/font-default-03.html": [
+ [
+ "/css/css-fonts/font-default-03.html",
+ [
+ [
+ "/css/css-fonts/font-default-03-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-fonts/font-default-04.html": [
+ [
+ "/css/css-fonts/font-default-04.html",
+ [
+ [
+ "/css/css-fonts/font-default-04-a-ref.html",
+ "=="
+ ],
+ [
+ "/css/css-fonts/font-default-04-b-ref.html",
+ "=="
+ ],
+ [
+ "/css/css-fonts/font-default-04-c-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-fonts/font-display/font-display-change.html": [
+ [
+ "/css/css-fonts/font-display/font-display-change.html",
+ [
+ [
+ "/css/css-fonts/font-display/font-display-change-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/css-fonts/font-display/font-display.html": [
[
"/css/css-fonts/font-display/font-display.html",
@@ -111357,6 +113879,18 @@
{}
]
],
+ "css/css-grid/grid-items/explicitly-sized-grid-item-as-table.html": [
+ [
+ "/css/css-grid/grid-items/explicitly-sized-grid-item-as-table.html",
+ [
+ [
+ "/css/reference/ref-filled-green-100px-square-only.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/css-grid/grid-items/grid-inline-items-001.html": [
[
"/css/css-grid/grid-items/grid-inline-items-001.html",
@@ -112905,6 +115439,54 @@
{}
]
],
+ "css/css-lists/counter-increment-inside-display-contents.html": [
+ [
+ "/css/css-lists/counter-increment-inside-display-contents.html",
+ [
+ [
+ "/css/css-lists/counter-7-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-lists/counter-reset-increment-display-contents.html": [
+ [
+ "/css/css-lists/counter-reset-increment-display-contents.html",
+ [
+ [
+ "/css/css-lists/counter-7-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-lists/counter-reset-increment-display-none.html": [
+ [
+ "/css/css-lists/counter-reset-increment-display-none.html",
+ [
+ [
+ "/css/css-lists/counter-7-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-lists/counter-reset-inside-display-contents.html": [
+ [
+ "/css/css-lists/counter-reset-inside-display-contents.html",
+ [
+ [
+ "/css/css-lists/counter-7-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/css-logical/cascading-001.html": [
[
"/css/css-logical/cascading-001.html",
@@ -114854,7 +117436,7 @@
"/css/css-multicol/multicol-br-inside-avoidcolumn-001.xht",
[
[
- "/css/css-multicol/multicol-br-inside-avoidcolumn-ref.xht",
+ "/css/reference/ref-filled-green-200px-square.html",
"=="
]
],
@@ -115089,30 +117671,6 @@
{}
]
],
- "css/css-multicol/multicol-count-computed-001.xht": [
- [
- "/css/css-multicol/multicol-count-computed-001.xht",
- [
- [
- "/css/css-multicol/multicol-count-computed-ref.xht",
- "=="
- ]
- ],
- {}
- ]
- ],
- "css/css-multicol/multicol-count-computed-002.xht": [
- [
- "/css/css-multicol/multicol-count-computed-002.xht",
- [
- [
- "/css/css-multicol/multicol-count-computed-2-ref.xht",
- "=="
- ]
- ],
- {}
- ]
- ],
"css/css-multicol/multicol-count-computed-003.xht": [
[
"/css/css-multicol/multicol-count-computed-003.xht",
@@ -115149,30 +117707,6 @@
{}
]
],
- "css/css-multicol/multicol-count-large-001.xht": [
- [
- "/css/css-multicol/multicol-count-large-001.xht",
- [
- [
- "/css/css-multicol/multicol-count-large-ref.xht",
- "=="
- ]
- ],
- {}
- ]
- ],
- "css/css-multicol/multicol-count-large-002.xht": [
- [
- "/css/css-multicol/multicol-count-large-002.xht",
- [
- [
- "/css/css-multicol/multicol-count-large-2-ref.xht",
- "=="
- ]
- ],
- {}
- ]
- ],
"css/css-multicol/multicol-count-negative-001.xht": [
[
"/css/css-multicol/multicol-count-negative-001.xht",
@@ -115317,18 +117851,6 @@
{}
]
],
- "css/css-multicol/multicol-fill-auto.xht": [
- [
- "/css/css-multicol/multicol-fill-auto.xht",
- [
- [
- "/css/css-multicol/multicol-fill-ref.xht",
- "=="
- ]
- ],
- {}
- ]
- ],
"css/css-multicol/multicol-fill-balance-001.xht": [
[
"/css/css-multicol/multicol-fill-balance-001.xht",
@@ -115401,6 +117923,18 @@
{}
]
],
+ "css/css-multicol/multicol-gap-fraction-002.html": [
+ [
+ "/css/css-multicol/multicol-gap-fraction-002.html",
+ [
+ [
+ "/css/reference/nothing.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/css-multicol/multicol-gap-large-001.xht": [
[
"/css/css-multicol/multicol-gap-large-001.xht",
@@ -115497,18 +118031,6 @@
{}
]
],
- "css/css-multicol/multicol-inherit-004.xht": [
- [
- "/css/css-multicol/multicol-inherit-004.xht",
- [
- [
- "/css/css-multicol/multicol-inherit-4-ref.xht",
- "=="
- ]
- ],
- {}
- ]
- ],
"css/css-multicol/multicol-list-item-001.xht": [
[
"/css/css-multicol/multicol-list-item-001.xht",
@@ -116025,54 +118547,6 @@
{}
]
],
- "css/css-multicol/multicol-rule-style-groove-001.xht": [
- [
- "/css/css-multicol/multicol-rule-style-groove-001.xht",
- [
- [
- "/css/css-multicol/multicol-rule-style-groove-001-ref.xht",
- "=="
- ]
- ],
- {}
- ]
- ],
- "css/css-multicol/multicol-rule-style-inset-001.xht": [
- [
- "/css/css-multicol/multicol-rule-style-inset-001.xht",
- [
- [
- "/css/css-multicol/multicol-rule-style-ridge-001-ref.xht",
- "=="
- ]
- ],
- {}
- ]
- ],
- "css/css-multicol/multicol-rule-style-outset-001.xht": [
- [
- "/css/css-multicol/multicol-rule-style-outset-001.xht",
- [
- [
- "/css/css-multicol/multicol-rule-style-groove-001-ref.xht",
- "=="
- ]
- ],
- {}
- ]
- ],
- "css/css-multicol/multicol-rule-style-ridge-001.xht": [
- [
- "/css/css-multicol/multicol-rule-style-ridge-001.xht",
- [
- [
- "/css/css-multicol/multicol-rule-style-ridge-001-ref.xht",
- "=="
- ]
- ],
- {}
- ]
- ],
"css/css-multicol/multicol-shorthand-001.xht": [
[
"/css/css-multicol/multicol-shorthand-001.xht",
@@ -116145,30 +118619,6 @@
{}
]
],
- "css/css-multicol/multicol-span-all-child-001.xht": [
- [
- "/css/css-multicol/multicol-span-all-child-001.xht",
- [
- [
- "/css/css-multicol/multicol-span-all-child-001-ref.xht",
- "=="
- ]
- ],
- {}
- ]
- ],
- "css/css-multicol/multicol-span-all-child-002.xht": [
- [
- "/css/css-multicol/multicol-span-all-child-002.xht",
- [
- [
- "/css/css-multicol/multicol-span-all-child-002-ref.xht",
- "=="
- ]
- ],
- {}
- ]
- ],
"css/css-multicol/multicol-span-all-margin-001.xht": [
[
"/css/css-multicol/multicol-span-all-margin-001.xht",
@@ -116229,18 +118679,6 @@
{}
]
],
- "css/css-multicol/multicol-span-all-margin-nested-003.xht": [
- [
- "/css/css-multicol/multicol-span-all-margin-nested-003.xht",
- [
- [
- "/css/css-multicol/multicol-span-all-margin-nested-3-ref.xht",
- "=="
- ]
- ],
- {}
- ]
- ],
"css/css-multicol/multicol-span-all-margin-nested-firstchild-001.xht": [
[
"/css/css-multicol/multicol-span-all-margin-nested-firstchild-001.xht",
@@ -116361,36 +118799,36 @@
{}
]
],
- "css/css-multicol/multicol-width-count-001.xht": [
+ "css/css-multicol/multicol-width-ch-001.xht": [
[
- "/css/css-multicol/multicol-width-count-001.xht",
+ "/css/css-multicol/multicol-width-ch-001.xht",
[
[
- "/css/css-multicol/multicol-width-001-ref.xht",
+ "/css/css-multicol/multicol-width-ch-ref.xht",
"=="
]
],
{}
]
],
- "css/css-multicol/multicol-width-count-002.xht": [
+ "css/css-multicol/multicol-width-count-001.xht": [
[
- "/css/css-multicol/multicol-width-count-002.xht",
+ "/css/css-multicol/multicol-width-count-001.xht",
[
[
- "/css/css-multicol/multicol-count-002-ref.xht",
+ "/css/css-multicol/multicol-width-001-ref.xht",
"=="
]
],
{}
]
],
- "css/css-multicol/multicol-width-ems-001.xht": [
+ "css/css-multicol/multicol-width-count-002.xht": [
[
- "/css/css-multicol/multicol-width-ems-001.xht",
+ "/css/css-multicol/multicol-width-count-002.xht",
[
[
- "/css/css-multicol/multicol-width-ems-ref.xht",
+ "/css/css-multicol/multicol-count-002-ref.xht",
"=="
]
],
@@ -116745,6 +119183,18 @@
{}
]
],
+ "css/css-overflow/input-scrollable-region-001.html": [
+ [
+ "/css/css-overflow/input-scrollable-region-001.html",
+ [
+ [
+ "/css/css-overflow/reference/input-scrollable-region-001-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/css-paint-api/background-image-alpha.https.html": [
[
"/css/css-paint-api/background-image-alpha.https.html",
@@ -116889,6 +119339,18 @@
{}
]
],
+ "css/css-paint-api/geometry-with-float-size.https.html": [
+ [
+ "/css/css-paint-api/geometry-with-float-size.https.html",
+ [
+ [
+ "/css/css-paint-api/geometry-with-float-size-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/css-paint-api/hidpi/device-pixel-ratio.https.html": [
[
"/css/css-paint-api/hidpi/device-pixel-ratio.https.html",
@@ -117825,6 +120287,18 @@
{}
]
],
+ "css/css-position/position-sticky-table-parts.html": [
+ [
+ "/css/css-position/position-sticky-table-parts.html",
+ [
+ [
+ "/css/css-position/position-sticky-table-parts-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/css-position/position-sticky-table-tfoot-bottom.html": [
[
"/css/css-position/position-sticky-table-tfoot-bottom.html",
@@ -121986,7 +124460,7 @@
"/css/css-style-attr/style-attr-urls-003.xht",
[
[
- "/css/css-style-attr/reference/ref-green-on-green2.xht",
+ "/css/css-style-attr/reference/ref-green-on-green.xht",
"=="
]
],
@@ -122041,6 +124515,66 @@
{}
]
],
+ "css/css-tables/zero-rowspan-001.html": [
+ [
+ "/css/css-tables/zero-rowspan-001.html",
+ [
+ [
+ "/css/css-tables/zero-rowspan-001-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-tables/zero-rowspan-002.html": [
+ [
+ "/css/css-tables/zero-rowspan-002.html",
+ [
+ [
+ "/css/css-tables/zero-rowspan-002-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-text-decor/line-through-vertical.html": [
+ [
+ "/css/css-text-decor/line-through-vertical.html",
+ [
+ [
+ "/css/css-text-decor/reference/line-through-vertical-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-text-decor/text-decoration-color-recalc.html": [
+ [
+ "/css/css-text-decor/text-decoration-color-recalc.html",
+ [
+ [
+ "/css/css-text-decor/reference/text-decoration-color-recalc-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-text-decor/text-decoration-color.html": [
+ [
+ "/css/css-text-decor/text-decoration-color.html",
+ [
+ [
+ "/css/css-text-decor/reference/text-decoration-color-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/css-text-decor/text-decoration-line-010.xht": [
[
"/css/css-text-decor/text-decoration-line-010.xht",
@@ -122089,6 +124623,54 @@
{}
]
],
+ "css/css-text-decor/text-decoration-line-recalc.html": [
+ [
+ "/css/css-text-decor/text-decoration-line-recalc.html",
+ [
+ [
+ "/css/css-text-decor/reference/text-decoration-line-recalc-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-text-decor/text-decoration-line.html": [
+ [
+ "/css/css-text-decor/text-decoration-line.html",
+ [
+ [
+ "/css/css-text-decor/reference/text-decoration-line-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-text-decor/text-decoration-style-multiple.html": [
+ [
+ "/css/css-text-decor/text-decoration-style-multiple.html",
+ [
+ [
+ "/css/css-text-decor/reference/text-decoration-style-multiple-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-text-decor/text-decoration-style-recalc.html": [
+ [
+ "/css/css-text-decor/text-decoration-style-recalc.html",
+ [
+ [
+ "/css/css-text-decor/reference/text-decoration-style-recalc-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/css-text-decor/text-emphasis-color-001.xht": [
[
"/css/css-text-decor/text-emphasis-color-001.xht",
@@ -130645,6 +133227,18 @@
{}
]
],
+ "css/css-transforms/css-transform-inherit-scale.html": [
+ [
+ "/css/css-transforms/css-transform-inherit-scale.html",
+ [
+ [
+ "/css/reference/ref-filled-green-200px-square.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/css-transforms/css-transform-scale-001.html": [
[
"/css/css-transforms/css-transform-scale-001.html",
@@ -136373,6 +138967,90 @@
{}
]
],
+ "css/css-transforms/transform-box/fill-box-mutation.html": [
+ [
+ "/css/css-transforms/transform-box/fill-box-mutation.html",
+ [
+ [
+ "/css/css-transforms/transform-box/support/greensquare200x200.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-transforms/transform-box/fill-box.html": [
+ [
+ "/css/css-transforms/transform-box/fill-box.html",
+ [
+ [
+ "/css/css-transforms/transform-box/support/greensquare200x200.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-transforms/transform-box/value-changed.html": [
+ [
+ "/css/css-transforms/transform-box/value-changed.html",
+ [
+ [
+ "/css/css-transforms/transform-box/support/greensquare200x200.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-transforms/transform-box/view-box-nested.html": [
+ [
+ "/css/css-transforms/transform-box/view-box-nested.html",
+ [
+ [
+ "/css/css-transforms/transform-box/support/greensquare200x200.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-transforms/transform-box/view-box-viewbox-nested.html": [
+ [
+ "/css/css-transforms/transform-box/view-box-viewbox-nested.html",
+ [
+ [
+ "/css/css-transforms/transform-box/support/greensquare200x200.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-transforms/transform-box/view-box-viewbox.html": [
+ [
+ "/css/css-transforms/transform-box/view-box-viewbox.html",
+ [
+ [
+ "/css/css-transforms/transform-box/support/greensquare200x200.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "css/css-transforms/transform-box/view-box.html": [
+ [
+ "/css/css-transforms/transform-box/view-box.html",
+ [
+ [
+ "/css/css-transforms/transform-box/support/greensquare200x200.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/css-transforms/transform-compound-001.html": [
[
"/css/css-transforms/transform-compound-001.html",
@@ -148169,6 +150847,18 @@
{}
]
],
+ "css/css-writing-modes/bidi-table-001.html": [
+ [
+ "/css/css-writing-modes/bidi-table-001.html",
+ [
+ [
+ "/css/css-writing-modes/reference/bidi-table-001.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/css-writing-modes/bidi-unset-001.html": [
[
"/css/css-writing-modes/bidi-unset-001.html",
@@ -149069,6 +151759,18 @@
{}
]
],
+ "css/css-writing-modes/block-plaintext-006.html": [
+ [
+ "/css/css-writing-modes/block-plaintext-006.html",
+ [
+ [
+ "/css/css-writing-modes/reference/block-plaintext-006.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/css-writing-modes/border-conflict-element-vlr-003.xht": [
[
"/css/css-writing-modes/border-conflict-element-vlr-003.xht",
@@ -155041,6 +157743,18 @@
{}
]
],
+ "css/cssom-view/scrollTop-display-change.html": [
+ [
+ "/css/cssom-view/scrollTop-display-change.html",
+ [
+ [
+ "/css/cssom-view/scrollTop-display-change-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/cssom-view/scrollingElement-quirks-dynamic-001.html": [
[
"/css/cssom-view/scrollingElement-quirks-dynamic-001.html",
@@ -155065,6 +157779,18 @@
{}
]
],
+ "css/cssom/medialist-dynamic-001.html": [
+ [
+ "/css/cssom/medialist-dynamic-001.html",
+ [
+ [
+ "/css/cssom/medialist-dynamic-001-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/cssom/selectorText-modification-restyle-001.html": [
[
"/css/cssom/selectorText-modification-restyle-001.html",
@@ -155881,6 +158607,18 @@
{}
]
],
+ "css/selectors/any-link-dynamic-001.html": [
+ [
+ "/css/selectors/any-link-dynamic-001.html",
+ [
+ [
+ "/css/selectors/any-link-dynamic-001-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"css/selectors/focus-within-001.html": [
[
"/css/selectors/focus-within-001.html",
@@ -170557,6 +173295,18 @@
{}
]
],
+ "html/browsers/sandboxing/sandbox-parse-noscript.html": [
+ [
+ "/html/browsers/sandboxing/sandbox-parse-noscript.html",
+ [
+ [
+ "/html/browsers/sandboxing/sandbox-parse-noscript-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"html/dom/elements/global-attributes/dir_auto-EN-L.html": [
[
"/html/dom/elements/global-attributes/dir_auto-EN-L.html",
@@ -171745,6 +174495,78 @@
{}
]
],
+ "html/form-elements/the-textarea-element/multiline-placeholder-cr.html": [
+ [
+ "/html/form-elements/the-textarea-element/multiline-placeholder-cr.html",
+ [
+ [
+ "/html/form-elements/the-textarea-element/multiline-placeholder-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "html/form-elements/the-textarea-element/multiline-placeholder-crlf.html": [
+ [
+ "/html/form-elements/the-textarea-element/multiline-placeholder-crlf.html",
+ [
+ [
+ "/html/form-elements/the-textarea-element/multiline-placeholder-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "html/form-elements/the-textarea-element/multiline-placeholder.html": [
+ [
+ "/html/form-elements/the-textarea-element/multiline-placeholder.html",
+ [
+ [
+ "/html/form-elements/the-textarea-element/multiline-placeholder-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "html/input/the-placeholder-attribute/multiline-cr.html": [
+ [
+ "/html/input/the-placeholder-attribute/multiline-cr.html",
+ [
+ [
+ "/html/input/the-placeholder-attribute/multiline-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "html/input/the-placeholder-attribute/multiline-crlf.html": [
+ [
+ "/html/input/the-placeholder-attribute/multiline-crlf.html",
+ [
+ [
+ "/html/input/the-placeholder-attribute/multiline-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "html/input/the-placeholder-attribute/multiline.html": [
+ [
+ "/html/input/the-placeholder-attribute/multiline.html",
+ [
+ [
+ "/html/input/the-placeholder-attribute/multiline-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"html/rendering/bindings/the-button-element/button-type-menu-historical.html": [
[
"/html/rendering/bindings/the-button-element/button-type-menu-historical.html",
@@ -173461,6 +176283,18 @@
{}
]
],
+ "html/semantics/text-level-semantics/the-b-element/b-usage.html": [
+ [
+ "/html/semantics/text-level-semantics/the-b-element/b-usage.html",
+ [
+ [
+ "/html/semantics/text-level-semantics/the-b-element/b-usage-notref.html",
+ "!="
+ ]
+ ],
+ {}
+ ]
+ ],
"html/semantics/text-level-semantics/the-bdi-element/bdi-auto-dir-default.html": [
[
"/html/semantics/text-level-semantics/the-bdi-element/bdi-auto-dir-default.html",
@@ -173725,6 +176559,18 @@
{}
]
],
+ "html/semantics/text-level-semantics/the-ruby-element/ruby-usage.html": [
+ [
+ "/html/semantics/text-level-semantics/the-ruby-element/ruby-usage.html",
+ [
+ [
+ "/html/semantics/text-level-semantics/the-ruby-element/ruby-usage-notref.html",
+ "!="
+ ]
+ ],
+ {}
+ ]
+ ],
"html/semantics/text-level-semantics/the-wbr-element/wbr-element.html": [
[
"/html/semantics/text-level-semantics/the-wbr-element/wbr-element.html",
@@ -174241,12 +177087,12 @@
{}
]
],
- "quirks-mode/historical/list-item-bullet-size.html": [
+ "quirks/historical/list-item-bullet-size.html": [
[
- "/quirks-mode/historical/list-item-bullet-size.html",
+ "/quirks/historical/list-item-bullet-size.html",
[
[
- "/quirks-mode/historical/list-item-bullet-size-ref.html",
+ "/quirks/historical/list-item-bullet-size-ref.html",
"=="
]
],
@@ -174325,6 +177171,18 @@
{}
]
],
+ "svg/foreignobject/position-svg-root-in-foreign-object.html": [
+ [
+ "/svg/foreignobject/position-svg-root-in-foreign-object.html",
+ [
+ [
+ "/svg/foreignobject/position-svg-root-in-foreign-object-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"svg/linking/reftests/href-a-element-attr-change.html": [
[
"/svg/linking/reftests/href-a-element-attr-change.html",
@@ -174445,6 +177303,54 @@
{}
]
],
+ "svg/path/bearing/absolute.svg": [
+ [
+ "/svg/path/bearing/absolute.svg",
+ [
+ [
+ "/svg/path/bearing/absolute-ref.svg",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "svg/path/bearing/relative.svg": [
+ [
+ "/svg/path/bearing/relative.svg",
+ [
+ [
+ "/svg/path/bearing/absolute-ref.svg",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "svg/path/bearing/zero.svg": [
+ [
+ "/svg/path/bearing/zero.svg",
+ [
+ [
+ "/svg/path/bearing/zero-ref.svg",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "svg/path/property/priority.svg": [
+ [
+ "/svg/path/property/priority.svg",
+ [
+ [
+ "/svg/path/property/priority-ref.svg",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"svg/shapes/rect-01.svg": [
[
"/svg/shapes/rect-01.svg",
@@ -177168,6 +180074,42 @@
],
{}
]
+ ],
+ "webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-center.html": [
+ [
+ "/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-center.html",
+ [
+ [
+ "/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-center-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-left.html": [
+ [
+ "/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-left.html",
+ [
+ [
+ "/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-left-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-right.html": [
+ [
+ "/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-right.html",
+ [
+ [
+ "/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-right-ref.html",
+ "=="
+ ]
+ ],
+ {}
+ ]
]
},
"reftest_node": {
@@ -178202,6 +181144,18 @@
],
{}
]
+ ],
+ "infrastructure/assumptions/ahem-ref.html": [
+ [
+ "/infrastructure/assumptions/ahem-ref.html",
+ [
+ [
+ "/infrastructure/assumptions/ahem-notref.html",
+ "!="
+ ]
+ ],
+ {}
+ ]
]
},
"stub": {
@@ -179747,6 +182701,11 @@
{}
]
],
+ "FileAPI/support/send-file-form-helper.js": [
+ [
+ {}
+ ]
+ ],
"FileAPI/support/upload.txt": [
[
{}
@@ -181017,6 +183976,21 @@
{}
]
],
+ "accelerometer/Accelerometer-disabled-by-feature-policy.https.html.headers": [
+ [
+ {}
+ ]
+ ],
+ "accelerometer/Accelerometer-enabled-by-feature-policy.https.html.headers": [
+ [
+ {}
+ ]
+ ],
+ "accelerometer/Accelerometer-enabled-on-self-origin-by-feature-policy.https.html.headers": [
+ [
+ {}
+ ]
+ ],
"accelerometer/OWNERS": [
[
{}
@@ -181157,6 +184131,21 @@
{}
]
],
+ "ambient-light/AmbientLightSensor-disabled-by-feature-policy.https.html.headers": [
+ [
+ {}
+ ]
+ ],
+ "ambient-light/AmbientLightSensor-enabled-by-feature-policy.https.html.headers": [
+ [
+ {}
+ ]
+ ],
+ "ambient-light/AmbientLightSensor-enabled-on-self-origin-by-feature-policy.https.html.headers": [
+ [
+ {}
+ ]
+ ],
"ambient-light/OWNERS": [
[
{}
@@ -183632,6 +186621,11 @@
{}
]
],
+ "beacon/OWNERS": [
+ [
+ {}
+ ]
+ ],
"beacon/beacon-common.sub.js": [
[
{}
@@ -183667,6 +186661,16 @@
{}
]
],
+ "bluetooth/README.md": [
+ [
+ {}
+ ]
+ ],
+ "bluetooth/resources/bluetooth-helpers.js": [
+ [
+ {}
+ ]
+ ],
"clear-site-data/support/echo-clear-site-data.py": [
[
{}
@@ -183917,11 +186921,6 @@
{}
]
],
- "common/vendor-prefix.js.headers": [
- [
- {}
- ]
- ],
"compat/OWNERS": [
[
{}
@@ -203057,6 +206056,11 @@
{}
]
],
+ "conformance-checkers/html/elements/style/html-spec-comms-isvalid.html": [
+ [
+ {}
+ ]
+ ],
"conformance-checkers/html/elements/style/model-isvalid.html": [
[
{}
@@ -203092,6 +206096,11 @@
{}
]
],
+ "conformance-checkers/html/elements/style/type-novalid.html": [
+ [
+ {}
+ ]
+ ],
"conformance-checkers/html/elements/sub/model-isvalid.html": [
[
{}
@@ -206012,6 +209021,11 @@
{}
]
],
+ "content-security-policy/base-uri/report-uri-does-not-respect-base-uri.sub.html.sub.headers": [
+ [
+ {}
+ ]
+ ],
"content-security-policy/connect-src/resources/simple-event-stream": [
[
{}
@@ -206147,6 +209161,11 @@
{}
]
],
+ "content-security-policy/generic/policy-inherited-correctly-by-plznavigate.html.sub.headers": [
+ [
+ {}
+ ]
+ ],
"content-security-policy/generic/positiveTest.js": [
[
{}
@@ -206612,6 +209631,11 @@
{}
]
],
+ "content-security-policy/support/fail.html": [
+ [
+ {}
+ ]
+ ],
"content-security-policy/support/fail.js": [
[
{}
@@ -206657,6 +209681,11 @@
{}
]
],
+ "content-security-policy/support/nonce-should-be-blocked.js": [
+ [
+ {}
+ ]
+ ],
"content-security-policy/support/pass.png": [
[
{}
@@ -206727,6 +209756,16 @@
{}
]
],
+ "cookie-store/OWNERS": [
+ [
+ {}
+ ]
+ ],
+ "cookie-store/README.md": [
+ [
+ {}
+ ]
+ ],
"cookie-store/resources/cookie-store-tests.js": [
[
{}
@@ -206742,7 +209781,27 @@
{}
]
],
- "cookies/path/echo-cookie.html": [
+ "cookie-store/serviceworker_cookieStore_arguments.js": [
+ [
+ {}
+ ]
+ ],
+ "cookie-store/serviceworker_cookieStore_basic.js": [
+ [
+ {}
+ ]
+ ],
+ "cookies/OWNERS": [
+ [
+ {}
+ ]
+ ],
+ "cookies/README.md": [
+ [
+ {}
+ ]
+ ],
+ "cookies/resources/echo-cookie.html": [
[
{}
]
@@ -206852,6 +209911,21 @@
{}
]
],
+ "credential-management/support/echoing-nester.html": [
+ [
+ {}
+ ]
+ ],
+ "credential-management/support/federatedcredential-get.html": [
+ [
+ {}
+ ]
+ ],
+ "credential-management/support/passwordcredential-get.html": [
+ [
+ {}
+ ]
+ ],
"css/.gitignore": [
[
{}
@@ -214017,6 +217091,11 @@
{}
]
],
+ "css/CSS2/fonts/font-148-ref.xht": [
+ [
+ {}
+ ]
+ ],
"css/CSS2/fonts/font-applies-to-001-ref.xht": [
[
{}
@@ -214552,6 +217631,21 @@
{}
]
],
+ "css/CSS2/generated-content/after-inheritable-001-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/after-inheritable-002-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/after-location-001-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/CSS2/generated-content/before-after-011-ref.xht": [
[
{}
@@ -214612,6 +217706,351 @@
{}
]
],
+ "css/CSS2/generated-content/before-location-001-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/bidi-generated-content-001-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/bidi-generated-content-002-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-001-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-003-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-005-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-006-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-007-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-010-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-011-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-012-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-013-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-014-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-015-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-016-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-017-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-021-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-022-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-023-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-026-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-027-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-028-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-029-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-030-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-031-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-032-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-033-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-037-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-040-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-041-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-042-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-043-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-047-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-048-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-050-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-052-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-053-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-063-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-068-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-070-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-072-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-073-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-075-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-080-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-081-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-082-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-083-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-089-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-090-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-091-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-096-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-097-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-100-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-103-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-113-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-126-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-132-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-135-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-136-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-141-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-143-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-144-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-147-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-149-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-150-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-155-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-156-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-158-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-159-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/CSS2/generated-content/content-171-ref.xht": [
[
{}
@@ -214642,6 +218081,11 @@
{}
]
],
+ "css/CSS2/generated-content/content-auto-reset-001-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/CSS2/generated-content/content-counter-000-ref.xht": [
[
{}
@@ -214712,6 +218156,56 @@
{}
]
],
+ "css/CSS2/generated-content/content-newline-001-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-white-space-001-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-white-space-002-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-white-space-003-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/content-white-space-004-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/counters-hidden-000-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/counters-hidden-002-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/counters-multi-000-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/counters-order-000-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/generated-content/counters-root-000-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/CSS2/generated-content/quotes-035-ref.xht": [
[
{}
@@ -215767,6 +219261,11 @@
{}
]
],
+ "css/CSS2/linebox/line-height-oof-descendants-001-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/CSS2/linebox/support/1x1-green.png": [
[
{}
@@ -224407,6 +227906,66 @@
{}
]
],
+ "css/CSS2/visudet/reference/content-height-001-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/visudet/reference/content-height-002-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/visudet/reference/content-height-003-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/visudet/reference/content-height-004-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/visudet/reference/content-height-005-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/visudet/reference/line-height-201-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/visudet/reference/line-height-202-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/visudet/reference/line-height-203-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/visudet/reference/line-height-206-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/visudet/support/1x1-green.png": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/visudet/support/AD.woff": [
+ [
+ {}
+ ]
+ ],
+ "css/CSS2/visudet/support/Revalia.woff": [
+ [
+ {}
+ ]
+ ],
"css/CSS2/visudet/support/swatch-blue.png": [
[
{}
@@ -224712,11 +228271,6 @@
{}
]
],
- "css/OWNERS": [
- [
- {}
- ]
- ],
"css/README.md": [
[
{}
@@ -227977,11 +231531,6 @@
{}
]
],
- "css/compositing/mix-blend-mode/reference/mix-blend-mode-transition-ref.html": [
- [
- {}
- ]
- ],
"css/compositing/mix-blend-mode/reference/mix-blend-mode-video-notref.html": [
[
{}
@@ -228212,6 +231761,11 @@
{}
]
],
+ "css/css-backgrounds/background-color-body-propagation-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/css-backgrounds/background-image-centered-ref.html": [
[
{}
@@ -229362,152 +232916,137 @@
{}
]
],
- "css/css-block/OWNERS": [
- [
- {}
- ]
- ],
- "css/css-block/run-in-basic-007-ref.xht": [
+ "css/css-break/OWNERS": [
[
{}
]
],
- "css/css-block/run-in-basic-ref.xht": [
- [
- {}
- ]
- ],
- "css/css-block/run-in-block-ref.xht": [
- [
- {}
- ]
- ],
- "css/css-block/run-in-breaking-001-ref.xht": [
+ "css/css-cascade/OWNERS": [
[
{}
]
],
- "css/css-block/run-in-breaking-002-ref.xht": [
+ "css/css-cascade/all-prop-001-ref.html": [
[
{}
]
],
- "css/css-block/run-in-inherit-001-ref.xht": [
+ "css/css-cascade/initial-color-background-001-ref.html": [
[
{}
]
],
- "css/css-block/run-in-pre-ref.xht": [
+ "css/css-cascade/reference/ref-filled-green-100px-square.xht": [
[
{}
]
],
- "css/css-block/run-in-replaced-001-ref.xht": [
+ "css/css-color/LICENSE": [
[
{}
]
],
- "css/css-block/run-in-text-ref.xht": [
+ "css/css-color/OWNERS": [
[
{}
]
],
- "css/css-block/support/black15x15.png": [
+ "css/css-color/blacktext-ref.html": [
[
{}
]
],
- "css/css-block/support/blue15x15.png": [
+ "css/css-color/border-color-ref.xht": [
[
{}
]
],
- "css/css-block/support/blue96x96.png": [
+ "css/css-color/greensquare-ref.html": [
[
{}
]
],
- "css/css-block/support/green15x15.png": [
+ "css/css-color/greentext-ref.html": [
[
{}
]
],
- "css/css-block/support/swatch-blue.png": [
+ "css/css-color/hex-003-ref.html": [
[
{}
]
],
- "css/css-cascade/OWNERS": [
+ "css/css-color/htaccess": [
[
{}
]
],
- "css/css-cascade/all-prop-001-ref.html": [
+ "css/css-color/rebeccapurple-ref.html": [
[
{}
]
],
- "css/css-cascade/initial-color-background-001-ref.html": [
+ "css/css-color/t31-color-currentColor-b-ref.html": [
[
{}
]
],
- "css/css-cascade/reference/ref-filled-green-100px-square.xht": [
+ "css/css-color/t31-color-text-a-ref.xht": [
[
{}
]
],
- "css/css-color/LICENSE": [
+ "css/css-color/t32-opacity-basic-0.0-a-ref.html": [
[
{}
]
],
- "css/css-color/OWNERS": [
+ "css/css-color/t32-opacity-basic-1.0-a-ref.html": [
[
{}
]
],
- "css/css-color/blacktext-ref.html": [
+ "css/css-color/t32-opacity-clamping-1.0-b-ref.html": [
[
{}
]
],
- "css/css-color/border-color-ref.xht": [
+ "css/css-color/t32-opacity-offscreen-b-ref.html": [
[
{}
]
],
- "css/css-color/greentext-ref.html": [
+ "css/css-color/t32-opacity-offscreen-multiple-boxes-1-c-ref.html": [
[
{}
]
],
- "css/css-color/htaccess": [
+ "css/css-color/t32-opacity-offscreen-multiple-boxes-2-c-ref.html": [
[
{}
]
],
- "css/css-color/rebeccapurple-ref.html": [
+ "css/css-color/t32-opacity-offscreen-with-alpha-c-ref.html": [
[
{}
]
],
- "css/css-color/t31-color-currentColor-b-ref.html": [
+ "css/css-color/t41-html4-keywords-a-ref.html": [
[
{}
]
],
- "css/css-color/t31-color-text-a-ref.xht": [
+ "css/css-color/t421-rgb-clip-outside-gamut-b-ref.html": [
[
{}
]
],
- "css/css-color/t32-opacity-offscreen-multiple-boxes-1-c-ref.html": [
+ "css/css-color/t421-rgb-hex3-expand-b-ref.html": [
[
{}
]
],
- "css/css-color/t32-opacity-offscreen-multiple-boxes-2-c-ref.html": [
+ "css/css-color/t421-rgb-values-meaning-b-ref.html": [
[
{}
]
@@ -229557,6 +233096,11 @@
{}
]
],
+ "css/css-color/t422-rgba-values-meaning-b-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/css-color/t423-transparent-2-a-ref.html": [
[
{}
@@ -229572,6 +233116,11 @@
{}
]
],
+ "css/css-color/t424-hsl-h-rotating-b-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/css-color/t424-hsl-parsing-f-ref.html": [
[
{}
@@ -229657,11 +233206,21 @@
{}
]
],
+ "css/css-color/t425-hsla-h-rotating-b-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/css-color/t425-hsla-values-b-ref.html": [
[
{}
]
],
+ "css/css-color/t43-svg-keywords-a-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/css-color/t44-currentcolor-background-b-ref.html": [
[
{}
@@ -229702,6 +233261,11 @@
{}
]
],
+ "css/css-contain/contain-style-counters-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/css-counter-styles/OWNERS": [
[
{}
@@ -229737,6 +233301,11 @@
{}
]
],
+ "css/css-display/display-contents-dynamic-pseudo-insertion-001-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/css-display/display-contents-flex-001-ref.html": [
[
{}
@@ -229752,6 +233321,11 @@
{}
]
],
+ "css/css-display/display-contents-line-height-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/css-display/display-contents-list-001-ref.html": [
[
{}
@@ -229777,12 +233351,12 @@
{}
]
],
- "css/css-display/display-contents-replaced-001-ref.html": [
+ "css/css-display/display-contents-state-change-001-ref.html": [
[
{}
]
],
- "css/css-display/display-contents-state-change-001-ref.html": [
+ "css/css-display/display-contents-svg-elements-ref.html": [
[
{}
]
@@ -229797,6 +233371,11 @@
{}
]
],
+ "css/css-display/display-contents-text-inherit-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/css-display/display-contents-text-only-001-ref.html": [
[
{}
@@ -229812,6 +233391,81 @@
{}
]
],
+ "css/css-display/run-in/OWNERS": [
+ [
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-basic-007-ref.xht": [
+ [
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-basic-ref.xht": [
+ [
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-block-ref.xht": [
+ [
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-breaking-001-ref.xht": [
+ [
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-breaking-002-ref.xht": [
+ [
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-inherit-001-ref.xht": [
+ [
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-pre-ref.xht": [
+ [
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-replaced-001-ref.xht": [
+ [
+ {}
+ ]
+ ],
+ "css/css-display/run-in/run-in-text-ref.xht": [
+ [
+ {}
+ ]
+ ],
+ "css/css-display/run-in/support/black15x15.png": [
+ [
+ {}
+ ]
+ ],
+ "css/css-display/run-in/support/blue15x15.png": [
+ [
+ {}
+ ]
+ ],
+ "css/css-display/run-in/support/blue96x96.png": [
+ [
+ {}
+ ]
+ ],
+ "css/css-display/run-in/support/green15x15.png": [
+ [
+ {}
+ ]
+ ],
+ "css/css-display/run-in/support/swatch-blue.png": [
+ [
+ {}
+ ]
+ ],
"css/css-display/support/acid.css": [
[
{}
@@ -229862,6 +233516,11 @@
{}
]
],
+ "css/css-flexbox/anonymous-flex-item-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/css-flexbox/auto-margins-001-ref.html": [
[
{}
@@ -230732,6 +234391,11 @@
{}
]
],
+ "css/css-flexbox/percentage-heights-004-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/css-flexbox/percentage-widths-001-ref.html": [
[
{}
@@ -231182,6 +234846,61 @@
{}
]
],
+ "css/css-fonts/first-available-font-001-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/css-fonts/first-available-font-002-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/css-fonts/first-available-font-003-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/css-fonts/first-available-font-005-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/css-fonts/font-default-01-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/css-fonts/font-default-02-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/css-fonts/font-default-03-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/css-fonts/font-default-04-a-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/css-fonts/font-default-04-b-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/css-fonts/font-default-04-c-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/css-fonts/font-display/font-display-change-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/css-fonts/font-display/font-display-ref.html": [
[
{}
@@ -231722,11 +235441,21 @@
{}
]
],
+ "css/css-fonts/support/AD.woff": [
+ [
+ {}
+ ]
+ ],
"css/css-fonts/support/README": [
[
{}
]
],
+ "css/css-fonts/support/Revalia.woff": [
+ [
+ {}
+ ]
+ ],
"css/css-fonts/support/bar_with_corner_dot.png": [
[
{}
@@ -239917,6 +243646,11 @@
{}
]
],
+ "css/css-lists/counter-7-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/css-logical/OWNERS": [
[
{}
@@ -240197,11 +243931,6 @@
{}
]
],
- "css/css-multicol/multicol-br-inside-avoidcolumn-ref.xht": [
- [
- {}
- ]
- ],
"css/css-multicol/multicol-break-000-ref.xht": [
[
{}
@@ -240262,26 +243991,6 @@
{}
]
],
- "css/css-multicol/multicol-count-computed-2-ref.xht": [
- [
- {}
- ]
- ],
- "css/css-multicol/multicol-count-computed-ref.xht": [
- [
- {}
- ]
- ],
- "css/css-multicol/multicol-count-large-2-ref.xht": [
- [
- {}
- ]
- ],
- "css/css-multicol/multicol-count-large-ref.xht": [
- [
- {}
- ]
- ],
"css/css-multicol/multicol-fill-000-ref.xht": [
[
{}
@@ -240317,21 +244026,11 @@
{}
]
],
- "css/css-multicol/multicol-fill-auto-ref.xht": [
- [
- {}
- ]
- ],
"css/css-multicol/multicol-fill-balance-001-ref.xht": [
[
{}
]
],
- "css/css-multicol/multicol-fill-ref.xht": [
- [
- {}
- ]
- ],
"css/css-multicol/multicol-gap-000-ref.xht": [
[
{}
@@ -240387,11 +244086,6 @@
{}
]
],
- "css/css-multicol/multicol-inherit-4-ref.xht": [
- [
- {}
- ]
- ],
"css/css-multicol/multicol-list-item-001-ref.xht": [
[
{}
@@ -240562,16 +244256,6 @@
{}
]
],
- "css/css-multicol/multicol-rule-style-groove-001-ref.xht": [
- [
- {}
- ]
- ],
- "css/css-multicol/multicol-rule-style-ridge-001-ref.xht": [
- [
- {}
- ]
- ],
"css/css-multicol/multicol-span-000-ref.xht": [
[
{}
@@ -240592,16 +244276,6 @@
{}
]
],
- "css/css-multicol/multicol-span-all-child-001-ref.xht": [
- [
- {}
- ]
- ],
- "css/css-multicol/multicol-span-all-child-002-ref.xht": [
- [
- {}
- ]
- ],
"css/css-multicol/multicol-span-all-margin-001-ref.xht": [
[
{}
@@ -240622,11 +244296,6 @@
{}
]
],
- "css/css-multicol/multicol-span-all-margin-nested-3-ref.xht": [
- [
- {}
- ]
- ],
"css/css-multicol/multicol-span-all-margin-nested-firstchild-ref.xht": [
[
{}
@@ -240667,7 +244336,7 @@
{}
]
],
- "css/css-multicol/multicol-width-ems-ref.xht": [
+ "css/css-multicol/multicol-width-ch-ref.xht": [
[
{}
]
@@ -240972,6 +244641,11 @@
{}
]
],
+ "css/css-overflow/reference/input-scrollable-region-001-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/css-page/OWNERS": [
[
{}
@@ -241222,6 +244896,11 @@
{}
]
],
+ "css/css-paint-api/geometry-with-float-size-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/css-paint-api/hidpi/device-pixel-ratio-ref.html": [
[
{}
@@ -241432,6 +245111,11 @@
{}
]
],
+ "css/css-position/position-sticky-table-parts-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/css-position/position-sticky-table-tfoot-bottom-ref.html": [
[
{}
@@ -243177,11 +246861,6 @@
{}
]
],
- "css/css-style-attr/reference/ref-green-on-green2.xht": [
- [
- {}
- ]
- ],
"css/css-style-attr/reference/ref-green.html": [
[
{}
@@ -243542,11 +247221,36 @@
{}
]
],
+ "css/css-tables/zero-rowspan-001-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/css-tables/zero-rowspan-002-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/css-text-decor/OWNERS": [
[
{}
]
],
+ "css/css-text-decor/reference/line-through-vertical-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/css-text-decor/reference/text-decoration-color-recalc-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/css-text-decor/reference/text-decoration-color-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/css-text-decor/reference/text-decoration-line-010-ref.xht": [
[
{}
@@ -243567,6 +247271,26 @@
{}
]
],
+ "css/css-text-decor/reference/text-decoration-line-recalc-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/css-text-decor/reference/text-decoration-line-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/css-text-decor/reference/text-decoration-style-multiple-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "css/css-text-decor/reference/text-decoration-style-recalc-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/css-text-decor/reference/text-emphasis-color-001-ref.xht": [
[
{}
@@ -247732,6 +251456,11 @@
{}
]
],
+ "css/css-transforms/transform-box/support/greensquare200x200.html": [
+ [
+ {}
+ ]
+ ],
"css/css-transforms/transform-compound-notref-1.html": [
[
{}
@@ -250267,6 +253996,16 @@
{}
]
],
+ "css/css-values/support/vh-support-transform-origin-iframe.html": [
+ [
+ {}
+ ]
+ ],
+ "css/css-values/support/vh-support-transform-translate-iframe.html": [
+ [
+ {}
+ ]
+ ],
"css/css-values/support/vh_not_refreshing_on_chrome_iframe.html": [
[
{}
@@ -252987,6 +256726,11 @@
{}
]
],
+ "css/cssom-view/scrollTop-display-change-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/cssom-view/scrollingElement-quirks-dynamic-001-ref.html": [
[
{}
@@ -253222,6 +256966,11 @@
{}
]
],
+ "css/cssom/medialist-dynamic-001-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/cssom/selectorText-modification-restyle-001-ref.html": [
[
{}
@@ -254297,6 +258046,11 @@
{}
]
],
+ "css/reference/nothing.html": [
+ [
+ {}
+ ]
+ ],
"css/reference/only_pass_parens_semicolon.html": [
[
{}
@@ -254342,6 +258096,11 @@
{}
]
],
+ "css/reference/ref-filled-green-100px-square-only.html": [
+ [
+ {}
+ ]
+ ],
"css/reference/ref-filled-green-100px-square.xht": [
[
{}
@@ -254392,6 +258151,11 @@
{}
]
],
+ "css/selectors/any-link-dynamic-001-ref.html": [
+ [
+ {}
+ ]
+ ],
"css/selectors/attribute-selectors/attribute-case/resources/semantics-quirks.html": [
[
{}
@@ -260472,6 +264236,11 @@
{}
]
],
+ "custom-elements/resources/my-custom-element-html-document.html": [
+ [
+ {}
+ ]
+ ],
"docs/.gitignore": [
[
{}
@@ -262882,6 +266651,16 @@
{}
]
],
+ "feature-policy/autoplay-allowed-by-feature-policy.https.sub.html.headers": [
+ [
+ {}
+ ]
+ ],
+ "feature-policy/autoplay-disabled-by-feature-policy.https.sub.html.headers": [
+ [
+ {}
+ ]
+ ],
"feature-policy/payment-allowed-by-feature-policy.https.sub.html.headers": [
[
{}
@@ -262892,6 +266671,21 @@
{}
]
],
+ "feature-policy/resources/autoplay.js": [
+ [
+ {}
+ ]
+ ],
+ "feature-policy/resources/feature-policy-autoplay.html": [
+ [
+ {}
+ ]
+ ],
+ "feature-policy/resources/feature-policy-generic-sensor.html": [
+ [
+ {}
+ ]
+ ],
"feature-policy/resources/feature-policy-payment.html": [
[
{}
@@ -263092,6 +266886,46 @@
{}
]
],
+ "fetch/api/request/destination/resources/dummy": [
+ [
+ {}
+ ]
+ ],
+ "fetch/api/request/destination/resources/dummy.png": [
+ [
+ {}
+ ]
+ ],
+ "fetch/api/request/destination/resources/dummy_audio.mp3": [
+ [
+ {}
+ ]
+ ],
+ "fetch/api/request/destination/resources/dummy_audio.oga": [
+ [
+ {}
+ ]
+ ],
+ "fetch/api/request/destination/resources/dummy_video.mp4": [
+ [
+ {}
+ ]
+ ],
+ "fetch/api/request/destination/resources/dummy_video.ogv": [
+ [
+ {}
+ ]
+ ],
+ "fetch/api/request/destination/resources/empty.https.html": [
+ [
+ {}
+ ]
+ ],
+ "fetch/api/request/destination/resources/fetch-destination-worker.js": [
+ [
+ {}
+ ]
+ ],
"fetch/api/request/multi-globals/current/current.html": [
[
{}
@@ -263707,6 +267541,11 @@
{}
]
],
+ "generic-sensor/generic-sensor-feature-policy-test.sub.js": [
+ [
+ {}
+ ]
+ ],
"generic-sensor/generic-sensor-tests.js": [
[
{}
@@ -263722,11 +267561,41 @@
{}
]
],
+ "geolocation-sensor/GeolocationSensor-disabled-by-feature-policy.https.html.headers": [
+ [
+ {}
+ ]
+ ],
+ "geolocation-sensor/GeolocationSensor-enabled-by-feature-policy.https.html.headers": [
+ [
+ {}
+ ]
+ ],
+ "geolocation-sensor/GeolocationSensor-enabled-on-self-origin-by-feature-policy.https.html.headers": [
+ [
+ {}
+ ]
+ ],
"geolocation-sensor/OWNERS": [
[
{}
]
],
+ "gyroscope/Gyroscope-disabled-by-feature-policy.https.html.headers": [
+ [
+ {}
+ ]
+ ],
+ "gyroscope/Gyroscope-enabled-by-feature-policy.https.html.headers": [
+ [
+ {}
+ ]
+ ],
+ "gyroscope/Gyroscope-enabled-on-self-origin-by-feature-policy.https.html.headers": [
+ [
+ {}
+ ]
+ ],
"gyroscope/OWNERS": [
[
{}
@@ -265002,6 +268871,16 @@
{}
]
],
+ "html/browsers/sandboxing/noscript-iframe.html": [
+ [
+ {}
+ ]
+ ],
+ "html/browsers/sandboxing/sandbox-parse-noscript-ref.html": [
+ [
+ {}
+ ]
+ ],
"html/browsers/the-window-object/.gitkeep": [
[
{}
@@ -270652,6 +274531,16 @@
{}
]
],
+ "html/form-elements/the-textarea-element/multiline-placeholder-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "html/form-elements/the-textarea-element/support/placeholder.css": [
+ [
+ {}
+ ]
+ ],
"html/iana/.gitkeep": [
[
{}
@@ -271137,6 +275026,11 @@
{}
]
],
+ "html/input/the-placeholder-attribute/multiline-ref.html": [
+ [
+ {}
+ ]
+ ],
"html/introduction/.gitkeep": [
[
{}
@@ -272142,6 +276036,306 @@
{}
]
],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/align-positioning-bad.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/align-positioning.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/align-text-line-position-bad.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/align-text-line-position.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/alignment-bad.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/alignment-ltr.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/alignment.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/bom.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/captions-fast.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/captions-gaps.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/captions-html.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/captions.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/class-bad.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/class.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cue-id-error.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cue-id.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cue-no-id-error.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cue-no-id.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-cuetext.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-header.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-note.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-align-bad.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-align.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-bad.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cues-no-separation.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cues-overlapping.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cues.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/default-styles.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/degenerate-cues.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/empty-cue.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/entities-wrong.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/entities.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/interspersed-non-cue.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/iso2022jp3.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/large-timestamp.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/line-position-bad.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/line-position.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/markup-bad.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/markup.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/metadata-area.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/metadata.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/missed-cues.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/no-newline-at-eof.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/no-timings.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/no-webvtt.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/positioning-bad.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/positioning-ltr.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/positioning.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/settings-bad-separation.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/settings.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/simple-captions.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/sorted-dispatch.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/timestamp-bad.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/timestamp.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/timings-hour-error.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/timings-hour.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/timings-no-hour-errors.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/timings-no-hour.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/timings-whitespace.vtt": [
+ [
+ {}
+ ]
+ ],
"html/semantics/embedded-content/media-elements/track/track-element/resources/track.de.vtt": [
[
{}
@@ -272162,6 +276356,61 @@
{}
]
],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/unsupported-markup.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/utf8.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/valign-bad.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/valign-ltr.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/valign.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/voice-bad.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/voice.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/vp8-vorbis-webvtt.webm": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/webvtt-file.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/webvtt-rubbish.vtt": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-helpers.js": [
+ [
+ {}
+ ]
+ ],
"html/semantics/embedded-content/resources/should-load.html": [
[
{}
@@ -272182,6 +276431,11 @@
{}
]
],
+ "html/semantics/embedded-content/the-area-element/resources/area-download-click.html": [
+ [
+ {}
+ ]
+ ],
"html/semantics/embedded-content/the-area-element/support/hit-test.js": [
[
{}
@@ -273357,6 +277611,11 @@
{}
]
],
+ "html/semantics/scripting-1/the-script-element/defer.js": [
+ [
+ {}
+ ]
+ ],
"html/semantics/scripting-1/the-script-element/execution-timing/102.html": [
[
{}
@@ -273492,6 +277751,36 @@
{}
]
],
+ "html/semantics/scripting-1/the-script-element/module/choice-of-error-1a.js": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/scripting-1/the-script-element/module/choice-of-error-1b.js": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/scripting-1/the-script-element/module/choice-of-error-2a.js": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/scripting-1/the-script-element/module/choice-of-error-2b.js": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/scripting-1/the-script-element/module/choice-of-error-3a.js": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/scripting-1/the-script-element/module/choice-of-error-3b.js": [
+ [
+ {}
+ ]
+ ],
"html/semantics/scripting-1/the-script-element/module/crossorigin-common.js": [
[
{}
@@ -273572,6 +277861,46 @@
{}
]
],
+ "html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/Function.js": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/eval.js": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/inline-event-handlers-UA-code.js": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/reflected-inline-event-handlers.js": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/setTimeout.js": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/scripting-1/the-script-element/module/error-type-1.js": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/scripting-1/the-script-element/module/error-type-2.js": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/scripting-1/the-script-element/module/error-type-3.js": [
+ [
+ {}
+ ]
+ ],
"html/semantics/scripting-1/the-script-element/module/errorhandling-parseerror-common.js": [
[
{}
@@ -273907,6 +278236,21 @@
{}
]
],
+ "html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js.headers": [
+ [
+ {}
+ ]
+ ],
+ "html/semantics/scripting-1/the-script-element/module/resources/import-remote-origin-referrer-checker.sub.js": [
+ [
+ {}
+ ]
+ ],
"html/semantics/scripting-1/the-script-element/module/resources/import-utf8-with-charset-header.js": [
[
{}
@@ -273932,6 +278276,11 @@
{}
]
],
+ "html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py": [
+ [
+ {}
+ ]
+ ],
"html/semantics/scripting-1/the-script-element/module/set-currentScript-on-window.js": [
[
{}
@@ -273982,6 +278331,11 @@
{}
]
],
+ "html/semantics/scripting-1/the-script-element/module/throw2.js": [
+ [
+ {}
+ ]
+ ],
"html/semantics/scripting-1/the-script-element/resources/bom-utf-16be.js": [
[
{}
@@ -274397,6 +278751,11 @@
{}
]
],
+ "html/semantics/text-level-semantics/the-a-element/resources/a-download-click.html": [
+ [
+ {}
+ ]
+ ],
"html/semantics/text-level-semantics/the-abbr-element/.gitkeep": [
[
{}
@@ -274407,6 +278766,11 @@
{}
]
],
+ "html/semantics/text-level-semantics/the-b-element/b-usage-notref.html": [
+ [
+ {}
+ ]
+ ],
"html/semantics/text-level-semantics/the-bdi-element/.gitkeep": [
[
{}
@@ -274572,6 +278936,11 @@
{}
]
],
+ "html/semantics/text-level-semantics/the-ruby-element/ruby-usage-notref.html": [
+ [
+ {}
+ ]
+ ],
"html/semantics/text-level-semantics/the-s-element/.gitkeep": [
[
{}
@@ -275372,7 +279741,7 @@
{}
]
],
- "infrastructure/assumptions/ahem-ref.html": [
+ "infrastructure/assumptions/ahem-notref.html": [
[
{}
]
@@ -275497,6 +279866,11 @@
{}
]
],
+ "interfaces/hr-time.idl": [
+ [
+ {}
+ ]
+ ],
"interfaces/html.idl": [
[
{}
@@ -275642,6 +280016,21 @@
{}
]
],
+ "magnetometer/Magnetometer-disabled-by-feature-policy.https.html.headers": [
+ [
+ {}
+ ]
+ ],
+ "magnetometer/Magnetometer-enabled-by-feature-policy.https.html.headers": [
+ [
+ {}
+ ]
+ ],
+ "magnetometer/Magnetometer-enabled-on-self-origin-by-feature-policy.https.html.headers": [
+ [
+ {}
+ ]
+ ],
"magnetometer/OWNERS": [
[
{}
@@ -275817,12 +280206,12 @@
{}
]
],
- "mathml/relations/html5-tree/unique-identifier-1-iframe.html": [
+ "mathml/relations/html5-tree/unique-identifier-1-iframe-1.html": [
[
{}
]
],
- "mathml/relations/html5-tree/unique-identifier-1-ref-iframe.html": [
+ "mathml/relations/html5-tree/unique-identifier-1-iframe-2.html": [
[
{}
]
@@ -276182,6 +280571,16 @@
{}
]
],
+ "media/counting.mp4": [
+ [
+ {}
+ ]
+ ],
+ "media/counting.ogv": [
+ [
+ {}
+ ]
+ ],
"media/foo.vtt": [
[
{}
@@ -276252,6 +280651,16 @@
{}
]
],
+ "media/test.mp4": [
+ [
+ {}
+ ]
+ ],
+ "media/test.ogv": [
+ [
+ {}
+ ]
+ ],
"media/white.mp4": [
[
{}
@@ -276277,6 +280686,41 @@
{}
]
],
+ "mimesniff/OWNERS": [
+ [
+ {}
+ ]
+ ],
+ "mimesniff/README.md": [
+ [
+ {}
+ ]
+ ],
+ "mimesniff/mime-types/README.md": [
+ [
+ {}
+ ]
+ ],
+ "mimesniff/mime-types/resources/generated-mime-types.json": [
+ [
+ {}
+ ]
+ ],
+ "mimesniff/mime-types/resources/generated-mime-types.py": [
+ [
+ {}
+ ]
+ ],
+ "mimesniff/mime-types/resources/mime-charset.py": [
+ [
+ {}
+ ]
+ ],
+ "mimesniff/mime-types/resources/mime-types.json": [
+ [
+ {}
+ ]
+ ],
"mixed-content/OWNERS": [
[
{}
@@ -276527,32 +280971,32 @@
{}
]
],
- "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers": [
+ "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html.headers": [
[
{}
]
],
- "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html.headers": [
+ "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html.headers": [
[
{}
]
],
- "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers": [
+ "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html.headers": [
[
{}
]
],
- "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers": [
+ "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html.headers": [
[
{}
]
],
- "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html.headers": [
+ "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html.headers": [
[
{}
]
],
- "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers": [
+ "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html.headers": [
[
{}
]
@@ -277037,11 +281481,41 @@
{}
]
],
+ "orientation-sensor/AbsoluteOrientationSensor-disabled-by-feature-policy.https.html.headers": [
+ [
+ {}
+ ]
+ ],
+ "orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy.https.html.headers": [
+ [
+ {}
+ ]
+ ],
+ "orientation-sensor/AbsoluteOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html.headers": [
+ [
+ {}
+ ]
+ ],
"orientation-sensor/OWNERS": [
[
{}
]
],
+ "orientation-sensor/RelativeOrientationSensor-disabled-by-feature-policy.https.html.headers": [
+ [
+ {}
+ ]
+ ],
+ "orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy.https.html.headers": [
+ [
+ {}
+ ]
+ ],
+ "orientation-sensor/RelativeOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html.headers": [
+ [
+ {}
+ ]
+ ],
"page-visibility/OWNERS": [
[
{}
@@ -277212,6 +281686,11 @@
{}
]
],
+ "preload/OWNERS": [
+ [
+ {}
+ ]
+ ],
"preload/dynamic-adding-preload-nonce.html.headers": [
[
{}
@@ -277302,11 +281781,6 @@
{}
]
],
- "preload/resources/fetch-destination-worker.js": [
- [
- {}
- ]
- ],
"preload/resources/foo.vtt": [
[
{}
@@ -277497,12 +281971,7 @@
{}
]
],
- "quirks-mode/OWNERS": [
- [
- {}
- ]
- ],
- "quirks-mode/historical/list-item-bullet-size-ref.html": [
+ "quirks/historical/list-item-bullet-size-ref.html": [
[
{}
]
@@ -280717,6 +285186,31 @@
{}
]
],
+ "service-workers/service-worker/resources/about-blank-replacement-frame.py": [
+ [
+ {}
+ ]
+ ],
+ "service-workers/service-worker/resources/about-blank-replacement-ping-frame.py": [
+ [
+ {}
+ ]
+ ],
+ "service-workers/service-worker/resources/about-blank-replacement-popup-frame.py": [
+ [
+ {}
+ ]
+ ],
+ "service-workers/service-worker/resources/about-blank-replacement-uncontrolled-nested-frame.html": [
+ [
+ {}
+ ]
+ ],
+ "service-workers/service-worker/resources/about-blank-replacement-worker.js": [
+ [
+ {}
+ ]
+ ],
"service-workers/service-worker/resources/appcache-ordering.install.html": [
[
{}
@@ -280957,6 +285451,11 @@
{}
]
],
+ "service-workers/service-worker/resources/fetch-cors-exposed-header-names-worker.js": [
+ [
+ {}
+ ]
+ ],
"service-workers/service-worker/resources/fetch-cors-xhr-iframe.html": [
[
{}
@@ -281002,12 +285501,12 @@
{}
]
],
- "service-workers/service-worker/resources/fetch-event-respond-with-partial-stream-worker.js": [
+ "service-workers/service-worker/resources/fetch-event-respond-with-custom-response-worker.js": [
[
{}
]
],
- "service-workers/service-worker/resources/fetch-event-respond-with-readable-stream-iframe.html": [
+ "service-workers/service-worker/resources/fetch-event-respond-with-partial-stream-worker.js": [
[
{}
]
@@ -281207,41 +285706,6 @@
{}
]
],
- "service-workers/service-worker/resources/foreign-fetch-cors-worker.js": [
- [
- {}
- ]
- ],
- "service-workers/service-worker/resources/foreign-fetch-event-worker.js": [
- [
- {}
- ]
- ],
- "service-workers/service-worker/resources/foreign-fetch-helper-iframe.html": [
- [
- {}
- ]
- ],
- "service-workers/service-worker/resources/foreign-fetch-helper-script.js": [
- [
- {}
- ]
- ],
- "service-workers/service-worker/resources/foreign-fetch-helper-worker.js": [
- [
- {}
- ]
- ],
- "service-workers/service-worker/resources/foreign-fetch-helpers.js": [
- [
- {}
- ]
- ],
- "service-workers/service-worker/resources/foreign-fetch-worker.js": [
- [
- {}
- ]
- ],
"service-workers/service-worker/resources/frame-for-getregistrations.html": [
[
{}
@@ -281252,11 +285716,6 @@
{}
]
],
- "service-workers/service-worker/resources/iframe-register-link-element.html": [
- [
- {}
- ]
- ],
"service-workers/service-worker/resources/immutable-prototype-serviceworker.js": [
[
{}
@@ -281307,11 +285766,6 @@
{}
]
],
- "service-workers/service-worker/resources/install-worker-helper.html": [
- [
- {}
- ]
- ],
"service-workers/service-worker/resources/interfaces-idls.js": [
[
{}
@@ -281362,11 +285816,6 @@
{}
]
],
- "service-workers/service-worker/resources/link-header.py": [
- [
- {}
- ]
- ],
"service-workers/service-worker/resources/load_worker.js": [
[
{}
@@ -281527,6 +285976,11 @@
{}
]
],
+ "service-workers/service-worker/resources/pass.txt": [
+ [
+ {}
+ ]
+ ],
"service-workers/service-worker/resources/performance-timeline-worker.js": [
[
{}
@@ -281582,11 +286036,6 @@
{}
]
],
- "service-workers/service-worker/resources/register-foreign-fetch-errors-worker.js": [
- [
- {}
- ]
- ],
"service-workers/service-worker/resources/register-iframe.html": [
[
{}
@@ -281647,7 +286096,7 @@
{}
]
],
- "service-workers/service-worker/resources/resource-timing-iframe.html": [
+ "service-workers/service-worker/resources/resource-timing-iframe.sub.html": [
[
{}
]
@@ -281677,6 +286126,16 @@
{}
]
],
+ "service-workers/service-worker/resources/sandboxed-iframe-fetch-event-iframe.html": [
+ [
+ {}
+ ]
+ ],
+ "service-workers/service-worker/resources/sandboxed-iframe-fetch-event-worker.js": [
+ [
+ {}
+ ]
+ ],
"service-workers/service-worker/resources/sandboxed-iframe-navigator-serviceworker-iframe.html": [
[
{}
@@ -282157,6 +286616,11 @@
{}
]
],
+ "streams/transform-streams/properties.js": [
+ [
+ {}
+ ]
+ ],
"streams/transform-streams/reentrant-strategies.js": [
[
{}
@@ -282477,6 +286941,11 @@
{}
]
],
+ "svg/foreignobject/position-svg-root-in-foreign-object-ref.html": [
+ [
+ {}
+ ]
+ ],
"svg/import/woffs/Blocky.woff": [
[
{}
@@ -282687,6 +287156,31 @@
{}
]
],
+ "svg/path/bearing/absolute-ref.svg": [
+ [
+ {}
+ ]
+ ],
+ "svg/path/bearing/relative-ref.svg": [
+ [
+ {}
+ ]
+ ],
+ "svg/path/bearing/zero-ref.svg": [
+ [
+ {}
+ ]
+ ],
+ "svg/path/property/priority-ref.svg": [
+ [
+ {}
+ ]
+ ],
+ "svg/path/property/resources/interpolation-test-common.js": [
+ [
+ {}
+ ]
+ ],
"svg/shapes/rect-01-ref.html": [
[
{}
@@ -283587,6 +288081,11 @@
{}
]
],
+ "webdriver/tests/actions/support/mouse.py": [
+ [
+ {}
+ ]
+ ],
"webdriver/tests/actions/support/refine.py": [
[
{}
@@ -283607,7 +288106,12 @@
{}
]
],
- "webdriver/tests/retrieval/__init__.py": [
+ "webdriver/tests/element_retrieval/__init__.py": [
+ [
+ {}
+ ]
+ ],
+ "webdriver/tests/element_send_keys/__init__.py": [
[
{}
]
@@ -283802,6 +288306,26 @@
{}
]
],
+ "webrtc/tools/.eslintrc.js": [
+ [
+ {}
+ ]
+ ],
+ "webrtc/tools/README.md": [
+ [
+ {}
+ ]
+ ],
+ "webrtc/tools/package-lock.json": [
+ [
+ {}
+ ]
+ ],
+ "webrtc/tools/package.json": [
+ [
+ {}
+ ]
+ ],
"websockets/OWNERS": [
[
{}
@@ -283897,6 +288421,11 @@
{}
]
],
+ "websockets/handlers/referrer_wsh.py": [
+ [
+ {}
+ ]
+ ],
"websockets/handlers/set-cookie-secure_wsh.py": [
[
{}
@@ -284502,6 +289031,11 @@
{}
]
],
+ "webvtt/parsing/file-parsing/tests/support/regions-edge-case.vtt": [
+ [
+ {}
+ ]
+ ],
"webvtt/parsing/file-parsing/tests/support/regions-id.vtt": [
[
{}
@@ -286182,11 +290716,41 @@
{}
]
],
+ "webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-center-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-left-ref.html": [
+ [
+ {}
+ ]
+ ],
+ "webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-right-ref.html": [
+ [
+ {}
+ ]
+ ],
"webvtt/tools/categorize_results.py": [
[
{}
]
],
+ "webxr/OWNERS": [
+ [
+ {}
+ ]
+ ],
+ "webxr/resources/webxr_check.html": [
+ [
+ {}
+ ]
+ ],
+ "webxr/resources/webxr_util.js": [
+ [
+ {}
+ ]
+ ],
"workers/OWNERS": [
[
{}
@@ -286317,6 +290881,11 @@
{}
]
],
+ "workers/data-url-shared-window.html": [
+ [
+ {}
+ ]
+ ],
"workers/interfaces/DedicatedWorkerGlobalScope/postMessage/message-event.js": [
[
{}
@@ -286562,6 +291131,11 @@
{}
]
],
+ "workers/support/iframe_sw_dataUrl.html": [
+ [
+ {}
+ ]
+ ],
"workers/support/name-as-accidental-global.js": [
[
{}
@@ -286612,6 +291186,16 @@
{}
]
],
+ "worklets/resources/empty-worklet-script-with-cors-header.js": [
+ [
+ {}
+ ]
+ ],
+ "worklets/resources/empty-worklet-script-with-cors-header.js.headers": [
+ [
+ {}
+ ]
+ ],
"worklets/resources/empty-worklet-script.js": [
[
{}
@@ -286622,7 +291206,17 @@
{}
]
],
- "worklets/resources/import-empty-worklet-script.js": [
+ "worklets/resources/import-empty-worklet-script-with-cors-header.js": [
+ [
+ {}
+ ]
+ ],
+ "worklets/resources/import-empty-worklet-script-with-cors-header.js.headers": [
+ [
+ {}
+ ]
+ ],
+ "worklets/resources/import-insecure-origin-empty-worklet-script.sub.js": [
[
{}
]
@@ -286642,11 +291236,31 @@
{}
]
],
+ "worklets/resources/import-referrer-checker-worklet-script.sub.js": [
+ [
+ {}
+ ]
+ ],
+ "worklets/resources/import-referrer-checker-worklet-script.sub.js.headers": [
+ [
+ {}
+ ]
+ ],
"worklets/resources/import-remote-origin-empty-worklet-script.sub.js": [
[
{}
]
],
+ "worklets/resources/import-remote-origin-referrer-checker-worklet-script.sub.js": [
+ [
+ {}
+ ]
+ ],
+ "worklets/resources/import-remote-origin-referrer-checker-worklet-script.sub.js.headers": [
+ [
+ {}
+ ]
+ ],
"worklets/resources/import-syntax-error-worklet-script.js": [
[
{}
@@ -286657,17 +291271,17 @@
{}
]
],
- "worklets/resources/referrer-tests.js": [
+ "worklets/resources/referrer-checker.py": [
[
{}
]
],
- "worklets/resources/referrer-window.html": [
+ "worklets/resources/referrer-tests.js": [
[
{}
]
],
- "worklets/resources/referrer.py": [
+ "worklets/resources/referrer-window.html": [
[
{}
]
@@ -291435,12 +296049,24 @@
{}
]
],
+ "FileAPI/blob/Blob-Request-revoke-fetch.html": [
+ [
+ "/FileAPI/blob/Blob-Request-revoke-fetch.html",
+ {}
+ ]
+ ],
"FileAPI/blob/Blob-XHR-revoke.html": [
[
"/FileAPI/blob/Blob-XHR-revoke.html",
{}
]
],
+ "FileAPI/blob/Blob-constructor-endings.html": [
+ [
+ "/FileAPI/blob/Blob-constructor-endings.html",
+ {}
+ ]
+ ],
"FileAPI/blob/Blob-constructor.html": [
[
"/FileAPI/blob/Blob-constructor.html",
@@ -291465,6 +296091,12 @@
{}
]
],
+ "FileAPI/file/File-constructor-endings.html": [
+ [
+ "/FileAPI/file/File-constructor-endings.html",
+ {}
+ ]
+ ],
"FileAPI/file/File-constructor.html": [
[
"/FileAPI/file/File-constructor.html",
@@ -291477,6 +296109,36 @@
{}
]
],
+ "FileAPI/file/send-file-form-iso-2022-jp.tentative.html": [
+ [
+ "/FileAPI/file/send-file-form-iso-2022-jp.tentative.html",
+ {}
+ ]
+ ],
+ "FileAPI/file/send-file-form-utf-8.html": [
+ [
+ "/FileAPI/file/send-file-form-utf-8.html",
+ {}
+ ]
+ ],
+ "FileAPI/file/send-file-form-windows-1252.tentative.html": [
+ [
+ "/FileAPI/file/send-file-form-windows-1252.tentative.html",
+ {}
+ ]
+ ],
+ "FileAPI/file/send-file-form-x-user-defined.tentative.html": [
+ [
+ "/FileAPI/file/send-file-form-x-user-defined.tentative.html",
+ {}
+ ]
+ ],
+ "FileAPI/file/send-file-form.html": [
+ [
+ "/FileAPI/file/send-file-form.html",
+ {}
+ ]
+ ],
"FileAPI/fileReader.html": [
[
"/FileAPI/fileReader.html",
@@ -291567,6 +296229,12 @@
{}
]
],
+ "FileAPI/unicode.html": [
+ [
+ "/FileAPI/unicode.html",
+ {}
+ ]
+ ],
"FileAPI/url/blob-url-in-sandboxed-iframe.html": [
[
"/FileAPI/url/blob-url-in-sandboxed-iframe.html",
@@ -293927,173 +298595,161 @@
}
]
],
- "WebCryptoAPI/generateKey/failures.worker.js": [
- [
- "/WebCryptoAPI/generateKey/failures.worker.html",
- {}
- ]
- ],
- "WebCryptoAPI/generateKey/failures_AES-CBC.worker.js": [
+ "WebCryptoAPI/generateKey/failures_AES-CBC.https.worker.js": [
[
- "/WebCryptoAPI/generateKey/failures_AES-CBC.worker.html",
+ "/WebCryptoAPI/generateKey/failures_AES-CBC.https.worker.html",
{
"timeout": "long"
}
]
],
- "WebCryptoAPI/generateKey/failures_AES-CTR.worker.js": [
+ "WebCryptoAPI/generateKey/failures_AES-CTR.https.worker.js": [
[
- "/WebCryptoAPI/generateKey/failures_AES-CTR.worker.html",
+ "/WebCryptoAPI/generateKey/failures_AES-CTR.https.worker.html",
{
"timeout": "long"
}
]
],
- "WebCryptoAPI/generateKey/failures_AES-GCM.worker.js": [
+ "WebCryptoAPI/generateKey/failures_AES-GCM.https.worker.js": [
[
- "/WebCryptoAPI/generateKey/failures_AES-GCM.worker.html",
+ "/WebCryptoAPI/generateKey/failures_AES-GCM.https.worker.html",
{
"timeout": "long"
}
]
],
- "WebCryptoAPI/generateKey/failures_AES-KW.worker.js": [
+ "WebCryptoAPI/generateKey/failures_AES-KW.https.worker.js": [
[
- "/WebCryptoAPI/generateKey/failures_AES-KW.worker.html",
+ "/WebCryptoAPI/generateKey/failures_AES-KW.https.worker.html",
{
"timeout": "long"
}
]
],
- "WebCryptoAPI/generateKey/failures_ECDH.worker.js": [
+ "WebCryptoAPI/generateKey/failures_ECDH.https.worker.js": [
[
- "/WebCryptoAPI/generateKey/failures_ECDH.worker.html",
+ "/WebCryptoAPI/generateKey/failures_ECDH.https.worker.html",
{
"timeout": "long"
}
]
],
- "WebCryptoAPI/generateKey/failures_ECDSA.worker.js": [
+ "WebCryptoAPI/generateKey/failures_ECDSA.https.worker.js": [
[
- "/WebCryptoAPI/generateKey/failures_ECDSA.worker.html",
+ "/WebCryptoAPI/generateKey/failures_ECDSA.https.worker.html",
{
"timeout": "long"
}
]
],
- "WebCryptoAPI/generateKey/failures_HMAC.worker.js": [
+ "WebCryptoAPI/generateKey/failures_HMAC.https.worker.js": [
[
- "/WebCryptoAPI/generateKey/failures_HMAC.worker.html",
+ "/WebCryptoAPI/generateKey/failures_HMAC.https.worker.html",
{
"timeout": "long"
}
]
],
- "WebCryptoAPI/generateKey/failures_RSA-OAEP.worker.js": [
+ "WebCryptoAPI/generateKey/failures_RSA-OAEP.https.worker.js": [
[
- "/WebCryptoAPI/generateKey/failures_RSA-OAEP.worker.html",
+ "/WebCryptoAPI/generateKey/failures_RSA-OAEP.https.worker.html",
{
"timeout": "long"
}
]
],
- "WebCryptoAPI/generateKey/failures_RSA-PSS.worker.js": [
+ "WebCryptoAPI/generateKey/failures_RSA-PSS.https.worker.js": [
[
- "/WebCryptoAPI/generateKey/failures_RSA-PSS.worker.html",
+ "/WebCryptoAPI/generateKey/failures_RSA-PSS.https.worker.html",
{
"timeout": "long"
}
]
],
- "WebCryptoAPI/generateKey/failures_RSASSA-PKCS1-v1_5.worker.js": [
+ "WebCryptoAPI/generateKey/failures_RSASSA-PKCS1-v1_5.https.worker.js": [
[
- "/WebCryptoAPI/generateKey/failures_RSASSA-PKCS1-v1_5.worker.html",
+ "/WebCryptoAPI/generateKey/failures_RSASSA-PKCS1-v1_5.https.worker.html",
{
"timeout": "long"
}
]
],
- "WebCryptoAPI/generateKey/successes.worker.js": [
+ "WebCryptoAPI/generateKey/successes_AES-CBC.https.worker.js": [
[
- "/WebCryptoAPI/generateKey/successes.worker.html",
- {}
- ]
- ],
- "WebCryptoAPI/generateKey/successes_AES-CBC.worker.js": [
- [
- "/WebCryptoAPI/generateKey/successes_AES-CBC.worker.html",
+ "/WebCryptoAPI/generateKey/successes_AES-CBC.https.worker.html",
{
"timeout": "long"
}
]
],
- "WebCryptoAPI/generateKey/successes_AES-CTR.worker.js": [
+ "WebCryptoAPI/generateKey/successes_AES-CTR.https.worker.js": [
[
- "/WebCryptoAPI/generateKey/successes_AES-CTR.worker.html",
+ "/WebCryptoAPI/generateKey/successes_AES-CTR.https.worker.html",
{
"timeout": "long"
}
]
],
- "WebCryptoAPI/generateKey/successes_AES-GCM.worker.js": [
+ "WebCryptoAPI/generateKey/successes_AES-GCM.https.worker.js": [
[
- "/WebCryptoAPI/generateKey/successes_AES-GCM.worker.html",
+ "/WebCryptoAPI/generateKey/successes_AES-GCM.https.worker.html",
{
"timeout": "long"
}
]
],
- "WebCryptoAPI/generateKey/successes_AES-KW.worker.js": [
+ "WebCryptoAPI/generateKey/successes_AES-KW.https.worker.js": [
[
- "/WebCryptoAPI/generateKey/successes_AES-KW.worker.html",
+ "/WebCryptoAPI/generateKey/successes_AES-KW.https.worker.html",
{
"timeout": "long"
}
]
],
- "WebCryptoAPI/generateKey/successes_ECDH.worker.js": [
+ "WebCryptoAPI/generateKey/successes_ECDH.https.worker.js": [
[
- "/WebCryptoAPI/generateKey/successes_ECDH.worker.html",
+ "/WebCryptoAPI/generateKey/successes_ECDH.https.worker.html",
{
"timeout": "long"
}
]
],
- "WebCryptoAPI/generateKey/successes_ECDSA.worker.js": [
+ "WebCryptoAPI/generateKey/successes_ECDSA.https.worker.js": [
[
- "/WebCryptoAPI/generateKey/successes_ECDSA.worker.html",
+ "/WebCryptoAPI/generateKey/successes_ECDSA.https.worker.html",
{
"timeout": "long"
}
]
],
- "WebCryptoAPI/generateKey/successes_HMAC.worker.js": [
+ "WebCryptoAPI/generateKey/successes_HMAC.https.worker.js": [
[
- "/WebCryptoAPI/generateKey/successes_HMAC.worker.html",
+ "/WebCryptoAPI/generateKey/successes_HMAC.https.worker.html",
{
"timeout": "long"
}
]
],
- "WebCryptoAPI/generateKey/successes_RSA-OAEP.worker.js": [
+ "WebCryptoAPI/generateKey/successes_RSA-OAEP.https.worker.js": [
[
- "/WebCryptoAPI/generateKey/successes_RSA-OAEP.worker.html",
+ "/WebCryptoAPI/generateKey/successes_RSA-OAEP.https.worker.html",
{
"timeout": "long"
}
]
],
- "WebCryptoAPI/generateKey/successes_RSA-PSS.worker.js": [
+ "WebCryptoAPI/generateKey/successes_RSA-PSS.https.worker.js": [
[
- "/WebCryptoAPI/generateKey/successes_RSA-PSS.worker.html",
+ "/WebCryptoAPI/generateKey/successes_RSA-PSS.https.worker.html",
{
"timeout": "long"
}
]
],
- "WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.worker.js": [
+ "WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.https.worker.js": [
[
- "/WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.worker.html",
+ "/WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.https.worker.html",
{
"timeout": "long"
}
@@ -294115,14 +298771,6 @@
}
]
],
- "WebCryptoAPI/generateKey/test_failures.https.html": [
- [
- "/WebCryptoAPI/generateKey/test_failures.https.html",
- {
- "timeout": "long"
- }
- ]
- ],
"WebCryptoAPI/generateKey/test_failures_AES-CBC.https.html": [
[
"/WebCryptoAPI/generateKey/test_failures_AES-CBC.https.html",
@@ -294513,6 +299161,16 @@
{}
]
],
+ "WebIDL/ecmascript-binding/no-regexp-special-casing.any.js": [
+ [
+ "/WebIDL/ecmascript-binding/no-regexp-special-casing.any.html",
+ {}
+ ],
+ [
+ "/WebIDL/ecmascript-binding/no-regexp-special-casing.any.worker.html",
+ {}
+ ]
+ ],
"WebIDL/ecmascript-binding/put-forwards.html": [
[
"/WebIDL/ecmascript-binding/put-forwards.html",
@@ -296233,6 +300891,36 @@
{}
]
],
+ "accelerometer/Accelerometer-disabled-by-feature-policy.https.html": [
+ [
+ "/accelerometer/Accelerometer-disabled-by-feature-policy.https.html",
+ {}
+ ]
+ ],
+ "accelerometer/Accelerometer-enabled-by-feature-policy-attribute-redirect-on-load.https.html": [
+ [
+ "/accelerometer/Accelerometer-enabled-by-feature-policy-attribute-redirect-on-load.https.html",
+ {}
+ ]
+ ],
+ "accelerometer/Accelerometer-enabled-by-feature-policy-attribute.https.html": [
+ [
+ "/accelerometer/Accelerometer-enabled-by-feature-policy-attribute.https.html",
+ {}
+ ]
+ ],
+ "accelerometer/Accelerometer-enabled-by-feature-policy.https.html": [
+ [
+ "/accelerometer/Accelerometer-enabled-by-feature-policy.https.html",
+ {}
+ ]
+ ],
+ "accelerometer/Accelerometer-enabled-on-self-origin-by-feature-policy.https.html": [
+ [
+ "/accelerometer/Accelerometer-enabled-on-self-origin-by-feature-policy.https.html",
+ {}
+ ]
+ ],
"accelerometer/Accelerometer.https.html": [
[
"/accelerometer/Accelerometer.https.html",
@@ -296251,6 +300939,36 @@
{}
]
],
+ "ambient-light/AmbientLightSensor-disabled-by-feature-policy.https.html": [
+ [
+ "/ambient-light/AmbientLightSensor-disabled-by-feature-policy.https.html",
+ {}
+ ]
+ ],
+ "ambient-light/AmbientLightSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html": [
+ [
+ "/ambient-light/AmbientLightSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html",
+ {}
+ ]
+ ],
+ "ambient-light/AmbientLightSensor-enabled-by-feature-policy-attribute.https.html": [
+ [
+ "/ambient-light/AmbientLightSensor-enabled-by-feature-policy-attribute.https.html",
+ {}
+ ]
+ ],
+ "ambient-light/AmbientLightSensor-enabled-by-feature-policy.https.html": [
+ [
+ "/ambient-light/AmbientLightSensor-enabled-by-feature-policy.https.html",
+ {}
+ ]
+ ],
+ "ambient-light/AmbientLightSensor-enabled-on-self-origin-by-feature-policy.https.html": [
+ [
+ "/ambient-light/AmbientLightSensor-enabled-on-self-origin-by-feature-policy.https.html",
+ {}
+ ]
+ ],
"ambient-light/AmbientLightSensor.https.html": [
[
"/ambient-light/AmbientLightSensor.https.html",
@@ -296503,9 +301221,21 @@
{}
]
],
- "bluetooth/idl-Bluetooth.html": [
+ "bluetooth/idl/idl-Bluetooth.html": [
+ [
+ "/bluetooth/idl/idl-Bluetooth.html",
+ {}
+ ]
+ ],
+ "bluetooth/idl/idl-BluetoothUUID.html": [
+ [
+ "/bluetooth/idl/idl-BluetoothUUID.html",
+ {}
+ ]
+ ],
+ "bluetooth/idl/idl-NavigatorBluetooth.html": [
[
- "/bluetooth/idl-Bluetooth.html",
+ "/bluetooth/idl/idl-NavigatorBluetooth.html",
{}
]
],
@@ -296615,6 +301345,12 @@
{}
]
],
+ "content-security-policy/base-uri/report-uri-does-not-respect-base-uri.sub.html": [
+ [
+ "/content-security-policy/base-uri/report-uri-does-not-respect-base-uri.sub.html",
+ {}
+ ]
+ ],
"content-security-policy/blob/blob-urls-do-not-match-self.sub.html": [
[
"/content-security-policy/blob/blob-urls-do-not-match-self.sub.html",
@@ -297275,6 +302011,12 @@
{}
]
],
+ "content-security-policy/generic/policy-inherited-correctly-by-plznavigate.html": [
+ [
+ "/content-security-policy/generic/policy-inherited-correctly-by-plznavigate.html",
+ {}
+ ]
+ ],
"content-security-policy/img-src/icon-allowed.sub.html": [
[
"/content-security-policy/img-src/icon-allowed.sub.html",
@@ -297341,6 +302083,12 @@
{}
]
],
+ "content-security-policy/inheritance/inherited-csp-list-modifications-are-local.html": [
+ [
+ "/content-security-policy/inheritance/inherited-csp-list-modifications-are-local.html",
+ {}
+ ]
+ ],
"content-security-policy/inheritance/window.html": [
[
"/content-security-policy/inheritance/window.html",
@@ -297647,6 +302395,12 @@
{}
]
],
+ "content-security-policy/script-src/nonce-enforce-blocked.html": [
+ [
+ "/content-security-policy/script-src/nonce-enforce-blocked.html",
+ {}
+ ]
+ ],
"content-security-policy/script-src/script-src-1_1.html": [
[
"/content-security-policy/script-src/script-src-1_1.html",
@@ -298469,6 +303223,72 @@
{}
]
],
+ "cookie-store/cookieStore_delete_arguments.tentative.window.js": [
+ [
+ "/cookie-store/cookieStore_delete_arguments.tentative.window.html",
+ {}
+ ]
+ ],
+ "cookie-store/cookieStore_getAll_arguments.tentative.window.js": [
+ [
+ "/cookie-store/cookieStore_getAll_arguments.tentative.window.html",
+ {}
+ ]
+ ],
+ "cookie-store/cookieStore_getAll_set_basic.tentative.window.js": [
+ [
+ "/cookie-store/cookieStore_getAll_set_basic.tentative.window.html",
+ {}
+ ]
+ ],
+ "cookie-store/cookieStore_get_arguments.tentative.window.js": [
+ [
+ "/cookie-store/cookieStore_get_arguments.tentative.window.html",
+ {}
+ ]
+ ],
+ "cookie-store/cookieStore_get_delete_basic.tentative.window.js": [
+ [
+ "/cookie-store/cookieStore_get_delete_basic.tentative.window.html",
+ {}
+ ]
+ ],
+ "cookie-store/cookieStore_get_set_basic.tentative.window.js": [
+ [
+ "/cookie-store/cookieStore_get_set_basic.tentative.window.html",
+ {}
+ ]
+ ],
+ "cookie-store/cookieStore_has_arguments.tentative.window.js": [
+ [
+ "/cookie-store/cookieStore_has_arguments.tentative.window.html",
+ {}
+ ]
+ ],
+ "cookie-store/cookieStore_has_basic.tentative.window.js": [
+ [
+ "/cookie-store/cookieStore_has_basic.tentative.window.html",
+ {}
+ ]
+ ],
+ "cookie-store/cookieStore_in_detached_frame.tentative.html": [
+ [
+ "/cookie-store/cookieStore_in_detached_frame.tentative.html",
+ {}
+ ]
+ ],
+ "cookie-store/cookieStore_set_arguments.tentative.window.js": [
+ [
+ "/cookie-store/cookieStore_set_arguments.tentative.window.html",
+ {}
+ ]
+ ],
+ "cookie-store/cookieStore_special_names.tentative.html": [
+ [
+ "/cookie-store/cookieStore_special_names.tentative.html",
+ {}
+ ]
+ ],
"cookie-store/cookie_store_tests.tentative.html": [
[
"/cookie-store/cookie_store_tests.tentative.html",
@@ -298565,6 +303385,12 @@
}
]
],
+ "cookie-store/document_getAll_multiple.tentative.html": [
+ [
+ "/cookie-store/document_getAll_multiple.tentative.html",
+ {}
+ ]
+ ],
"cookie-store/expiration.tentative.html": [
[
"/cookie-store/expiration.tentative.html",
@@ -298837,6 +303663,24 @@
}
]
],
+ "cookie-store/serviceworker_cookieStore_arguments.tentative.https.html": [
+ [
+ "/cookie-store/serviceworker_cookieStore_arguments.tentative.https.html",
+ {}
+ ]
+ ],
+ "cookie-store/serviceworker_cookieStore_basic.tentative.https.html": [
+ [
+ "/cookie-store/serviceworker_cookieStore_basic.tentative.https.html",
+ {}
+ ]
+ ],
+ "cookies/meta-blocked.html": [
+ [
+ "/cookies/meta-blocked.html",
+ {}
+ ]
+ ],
"cookies/path/match.html": [
[
"/cookies/path/match.html",
@@ -298867,9 +303711,9 @@
{}
]
],
- "cookies/secure/set-from-ws.https.sub.html": [
+ "cookies/secure/set-from-ws.sub.html": [
[
- "/cookies/secure/set-from-ws.https.sub.html",
+ "/cookies/secure/set-from-ws.sub.html",
{}
]
],
@@ -299007,12 +303851,24 @@
{}
]
],
+ "credential-management/federatedcredential-framed-get.sub.https.html": [
+ [
+ "/credential-management/federatedcredential-framed-get.sub.https.html",
+ {}
+ ]
+ ],
"credential-management/idl.https.html": [
[
"/credential-management/idl.https.html",
{}
]
],
+ "credential-management/passwordcredential-framed-get.sub.https.html": [
+ [
+ "/credential-management/passwordcredential-framed-get.sub.https.html",
+ {}
+ ]
+ ],
"css/compositing/mix-blend-mode/mix-blend-mode-creates-stacking-context.html": [
[
"/css/compositing/mix-blend-mode/mix-blend-mode-creates-stacking-context.html",
@@ -299219,6 +304075,26 @@
{}
]
],
+ "css/css-color/color-resolving-hsl.html": [
+ [
+ "/css/css-color/color-resolving-hsl.html",
+ {
+ "timeout": "long"
+ }
+ ]
+ ],
+ "css/css-color/color-resolving-keywords.html": [
+ [
+ "/css/css-color/color-resolving-keywords.html",
+ {}
+ ]
+ ],
+ "css/css-color/color-resolving.html": [
+ [
+ "/css/css-color/color-resolving.html",
+ {}
+ ]
+ ],
"css/css-conditional/js/001.html": [
[
"/css/css-conditional/js/001.html",
@@ -299795,6 +304671,12 @@
{}
]
],
+ "css/css-fonts/font-variant-alternates-parsing.html": [
+ [
+ "/css/css-fonts/font-variant-alternates-parsing.html",
+ {}
+ ]
+ ],
"css/css-fonts/test_datafont_same_origin.html": [
[
"/css/css-fonts/test_datafont_same_origin.html",
@@ -299837,6 +304719,48 @@
{}
]
],
+ "css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-001.html": [
+ [
+ "/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-001.html",
+ {}
+ ]
+ ],
+ "css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-002.html": [
+ [
+ "/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-002.html",
+ {}
+ ]
+ ],
+ "css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-003.html": [
+ [
+ "/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-003.html",
+ {}
+ ]
+ ],
+ "css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-004.html": [
+ [
+ "/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-004.html",
+ {}
+ ]
+ ],
+ "css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-005.html": [
+ [
+ "/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-005.html",
+ {}
+ ]
+ ],
+ "css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-006.html": [
+ [
+ "/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-006.html",
+ {}
+ ]
+ ],
+ "css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-007.html": [
+ [
+ "/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-007.html",
+ {}
+ ]
+ ],
"css/css-grid/abspos/grid-positioned-items-content-alignment-001.html": [
[
"/css/css-grid/abspos/grid-positioned-items-content-alignment-001.html",
@@ -300221,6 +305145,12 @@
{}
]
],
+ "css/css-grid/alignment/grid-column-axis-alignment-positioned-items-017.html": [
+ [
+ "/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-017.html",
+ {}
+ ]
+ ],
"css/css-grid/alignment/grid-fit-content-tracks-dont-stretch-001.html": [
[
"/css/css-grid/alignment/grid-fit-content-tracks-dont-stretch-001.html",
@@ -300323,6 +305253,12 @@
{}
]
],
+ "css/css-grid/alignment/grid-row-axis-alignment-positioned-items-017.html": [
+ [
+ "/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-017.html",
+ {}
+ ]
+ ],
"css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-001.html": [
[
"/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-001.html",
@@ -300869,6 +305805,18 @@
{}
]
],
+ "css/css-grid/grid-items/grid-minimum-size-grid-items-022.html": [
+ [
+ "/css/css-grid/grid-items/grid-minimum-size-grid-items-022.html",
+ {}
+ ]
+ ],
+ "css/css-grid/grid-items/grid-minimum-size-grid-items-023.html": [
+ [
+ "/css/css-grid/grid-items/grid-minimum-size-grid-items-023.html",
+ {}
+ ]
+ ],
"css/css-grid/grid-layout-properties.html": [
[
"/css/css-grid/grid-layout-properties.html",
@@ -300887,6 +305835,30 @@
{}
]
],
+ "css/css-grid/grid-model/grid-container-ignores-first-letter-001.html": [
+ [
+ "/css/css-grid/grid-model/grid-container-ignores-first-letter-001.html",
+ {}
+ ]
+ ],
+ "css/css-grid/grid-model/grid-container-ignores-first-line-001.html": [
+ [
+ "/css/css-grid/grid-model/grid-container-ignores-first-line-001.html",
+ {}
+ ]
+ ],
+ "css/css-grid/grid-model/grid-item-accepts-first-letter-001.html": [
+ [
+ "/css/css-grid/grid-model/grid-item-accepts-first-letter-001.html",
+ {}
+ ]
+ ],
+ "css/css-grid/grid-model/grid-item-accepts-first-line-001.html": [
+ [
+ "/css/css-grid/grid-model/grid-item-accepts-first-line-001.html",
+ {}
+ ]
+ ],
"css/css-grid/grid-model/grid-support-display-001.html": [
[
"/css/css-grid/grid-model/grid-support-display-001.html",
@@ -300923,6 +305895,24 @@
{}
]
],
+ "css/css-multicol/multicol-gap-animation-001.html": [
+ [
+ "/css/css-multicol/multicol-gap-animation-001.html",
+ {}
+ ]
+ ],
+ "css/css-multicol/multicol-gap-animation-002.html": [
+ [
+ "/css/css-multicol/multicol-gap-animation-002.html",
+ {}
+ ]
+ ],
+ "css/css-multicol/multicol-gap-animation-003.html": [
+ [
+ "/css/css-multicol/multicol-gap-animation-003.html",
+ {}
+ ]
+ ],
"css/css-position/position-sticky-get-bounding-client-rect.html": [
[
"/css/css-position/position-sticky-get-bounding-client-rect.html",
@@ -300935,6 +305925,12 @@
{}
]
],
+ "css/css-position/position-sticky-offset-overflow.html": [
+ [
+ "/css/css-position/position-sticky-offset-overflow.html",
+ {}
+ ]
+ ],
"css/css-position/position-sticky-offset-top-left.html": [
[
"/css/css-position/position-sticky-offset-top-left.html",
@@ -302117,6 +307113,12 @@
{}
]
],
+ "css/css-text-decor/text-decoration-serialization.tentative.html": [
+ [
+ "/css/css-text-decor/text-decoration-serialization.tentative.html",
+ {}
+ ]
+ ],
"css/css-text-decor/text-decoration-skip-ink.html": [
[
"/css/css-text-decor/text-decoration-skip-ink.html",
@@ -303293,6 +308295,18 @@
{}
]
],
+ "css/css-typed-om/stylevalue-objects/interface.html": [
+ [
+ "/css/css-typed-om/stylevalue-objects/interface.html",
+ {}
+ ]
+ ],
+ "css/css-typed-om/stylevalue-subclasses/cssKeywordValue-interface.html": [
+ [
+ "/css/css-typed-om/stylevalue-subclasses/cssKeywordValue-interface.html",
+ {}
+ ]
+ ],
"css/css-ui/box-sizing-027.html": [
[
"/css/css-ui/box-sizing-027.html",
@@ -304223,6 +309237,12 @@
{}
]
],
+ "css/cssom-view/scroll-behavior-smooth.html": [
+ [
+ "/css/cssom-view/scroll-behavior-smooth.html",
+ {}
+ ]
+ ],
"css/cssom-view/scrollIntoView-shadow.html": [
[
"/css/cssom-view/scrollIntoView-shadow.html",
@@ -304571,6 +309591,12 @@
{}
]
],
+ "css/cssom/setproperty-null-undefined.html": [
+ [
+ "/css/cssom/setproperty-null-undefined.html",
+ {}
+ ]
+ ],
"css/cssom/shorthand-serialization.html": [
[
"/css/cssom/shorthand-serialization.html",
@@ -304817,6 +309843,36 @@
{}
]
],
+ "css/motion/animation/offset-path-interpolation-001.html": [
+ [
+ "/css/motion/animation/offset-path-interpolation-001.html",
+ {}
+ ]
+ ],
+ "css/motion/animation/offset-path-interpolation-002.html": [
+ [
+ "/css/motion/animation/offset-path-interpolation-002.html",
+ {}
+ ]
+ ],
+ "css/motion/animation/offset-path-interpolation-003.html": [
+ [
+ "/css/motion/animation/offset-path-interpolation-003.html",
+ {}
+ ]
+ ],
+ "css/motion/animation/offset-path-interpolation-004.html": [
+ [
+ "/css/motion/animation/offset-path-interpolation-004.html",
+ {}
+ ]
+ ],
+ "css/motion/animation/offset-path-interpolation-005.html": [
+ [
+ "/css/motion/animation/offset-path-interpolation-005.html",
+ {}
+ ]
+ ],
"css/motion/animation/offset-position-interpolation.html": [
[
"/css/motion/animation/offset-position-interpolation.html",
@@ -305201,6 +310257,12 @@
{}
]
],
+ "css/selectors/invalidation/any-link-pseudo.html": [
+ [
+ "/css/selectors/invalidation/any-link-pseudo.html",
+ {}
+ ]
+ ],
"css/selectors/missing-right-token.html": [
[
"/css/selectors/missing-right-token.html",
@@ -305483,6 +310545,12 @@
{}
]
],
+ "custom-elements/reactions/with-exceptions.html": [
+ [
+ "/custom-elements/reactions/with-exceptions.html",
+ {}
+ ]
+ ],
"custom-elements/upgrading.html": [
[
"/custom-elements/upgrading.html",
@@ -308685,659 +313753,659 @@
{}
]
],
- "encrypted-media/clearkey-check-initdata-type.html": [
+ "encrypted-media/clearkey-check-initdata-type.https.html": [
[
- "/encrypted-media/clearkey-check-initdata-type.html",
+ "/encrypted-media/clearkey-check-initdata-type.https.html",
{}
]
],
- "encrypted-media/clearkey-events-session-closed-event.html": [
+ "encrypted-media/clearkey-events-session-closed-event.https.html": [
[
- "/encrypted-media/clearkey-events-session-closed-event.html",
+ "/encrypted-media/clearkey-events-session-closed-event.https.html",
{}
]
],
- "encrypted-media/clearkey-events.html": [
+ "encrypted-media/clearkey-events.https.html": [
[
- "/encrypted-media/clearkey-events.html",
+ "/encrypted-media/clearkey-events.https.html",
{}
]
],
- "encrypted-media/clearkey-generate-request-disallowed-input.html": [
+ "encrypted-media/clearkey-generate-request-disallowed-input.https.html": [
[
- "/encrypted-media/clearkey-generate-request-disallowed-input.html",
+ "/encrypted-media/clearkey-generate-request-disallowed-input.https.html",
{}
]
],
- "encrypted-media/clearkey-invalid-license.html": [
+ "encrypted-media/clearkey-invalid-license.https.html": [
[
- "/encrypted-media/clearkey-invalid-license.html",
+ "/encrypted-media/clearkey-invalid-license.https.html",
{}
]
],
- "encrypted-media/clearkey-keystatuses-multiple-sessions.html": [
+ "encrypted-media/clearkey-keystatuses-multiple-sessions.https.html": [
[
- "/encrypted-media/clearkey-keystatuses-multiple-sessions.html",
+ "/encrypted-media/clearkey-keystatuses-multiple-sessions.https.html",
{}
]
],
- "encrypted-media/clearkey-keystatuses.html": [
+ "encrypted-media/clearkey-keystatuses.https.html": [
[
- "/encrypted-media/clearkey-keystatuses.html",
+ "/encrypted-media/clearkey-keystatuses.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-playback-destroy-persistent-license.html": [
+ "encrypted-media/clearkey-mp4-playback-destroy-persistent-license.https.html": [
[
- "/encrypted-media/clearkey-mp4-playback-destroy-persistent-license.html",
+ "/encrypted-media/clearkey-mp4-playback-destroy-persistent-license.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-playback-persistent-license-events.html": [
+ "encrypted-media/clearkey-mp4-playback-persistent-license-events.https.html": [
[
- "/encrypted-media/clearkey-mp4-playback-persistent-license-events.html",
+ "/encrypted-media/clearkey-mp4-playback-persistent-license-events.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-playback-persistent-license.html": [
+ "encrypted-media/clearkey-mp4-playback-persistent-license.https.html": [
[
- "/encrypted-media/clearkey-mp4-playback-persistent-license.html",
+ "/encrypted-media/clearkey-mp4-playback-persistent-license.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.html": [
+ "encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.https.html": [
[
- "/encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.html",
+ "/encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-playback-persistent-usage-record.html": [
+ "encrypted-media/clearkey-mp4-playback-persistent-usage-record.https.html": [
[
- "/encrypted-media/clearkey-mp4-playback-persistent-usage-record.html",
+ "/encrypted-media/clearkey-mp4-playback-persistent-usage-record.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.html": [
+ "encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.https.html": [
[
- "/encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.html",
+ "/encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.html": [
+ "encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.https.html": [
[
- "/encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.html",
+ "/encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.html": [
+ "encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.https.html": [
[
- "/encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.html",
+ "/encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.https.html": [
[
- "/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.html",
+ "/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.https.html": [
[
- "/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.html",
+ "/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.https.html": [
[
- "/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.html",
+ "/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-playback-temporary-events.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-events.https.html": [
[
- "/encrypted-media/clearkey-mp4-playback-temporary-events.html",
+ "/encrypted-media/clearkey-mp4-playback-temporary-events.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.https.html": [
[
- "/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.html",
+ "/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.https.html": [
[
- "/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.html",
+ "/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/clearkey-mp4-playback-temporary-multikey.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-multikey.https.html": [
[
- "/encrypted-media/clearkey-mp4-playback-temporary-multikey.html",
+ "/encrypted-media/clearkey-mp4-playback-temporary-multikey.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-playback-temporary-multisession.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-multisession.https.html": [
[
- "/encrypted-media/clearkey-mp4-playback-temporary-multisession.html",
+ "/encrypted-media/clearkey-mp4-playback-temporary-multisession.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.https.html": [
[
- "/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.html",
+ "/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.https.html": [
[
- "/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.html",
+ "/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.https.html": [
[
- "/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.html",
+ "/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.https.html": [
[
- "/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.html",
+ "/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-playback-temporary-two-videos.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-two-videos.https.html": [
[
- "/encrypted-media/clearkey-mp4-playback-temporary-two-videos.html",
+ "/encrypted-media/clearkey-mp4-playback-temporary-two-videos.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.https.html": [
[
- "/encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.html",
+ "/encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-playback-temporary.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary.https.html": [
[
- "/encrypted-media/clearkey-mp4-playback-temporary.html",
+ "/encrypted-media/clearkey-mp4-playback-temporary.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-requestmediakeysystemaccess.html": [
+ "encrypted-media/clearkey-mp4-requestmediakeysystemaccess.https.html": [
[
- "/encrypted-media/clearkey-mp4-requestmediakeysystemaccess.html",
+ "/encrypted-media/clearkey-mp4-requestmediakeysystemaccess.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.html": [
+ "encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.https.html": [
[
- "/encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.html",
+ "/encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.html": [
+ "encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.https.html": [
[
- "/encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.html",
+ "/encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.html": [
+ "encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.https.html": [
[
- "/encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.html",
+ "/encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-setmediakeys-at-same-time.html": [
+ "encrypted-media/clearkey-mp4-setmediakeys-at-same-time.https.html": [
[
- "/encrypted-media/clearkey-mp4-setmediakeys-at-same-time.html",
+ "/encrypted-media/clearkey-mp4-setmediakeys-at-same-time.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.html": [
+ "encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html": [
[
- "/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.html",
+ "/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html": [
+ "encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html": [
[
- "/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html",
+ "/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.html": [
+ "encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.https.html": [
[
- "/encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.html",
+ "/encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-setmediakeys.html": [
+ "encrypted-media/clearkey-mp4-setmediakeys.https.html": [
[
- "/encrypted-media/clearkey-mp4-setmediakeys.html",
+ "/encrypted-media/clearkey-mp4-setmediakeys.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-syntax-mediakeys.html": [
+ "encrypted-media/clearkey-mp4-syntax-mediakeys.https.html": [
[
- "/encrypted-media/clearkey-mp4-syntax-mediakeys.html",
+ "/encrypted-media/clearkey-mp4-syntax-mediakeys.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-syntax-mediakeysession.html": [
+ "encrypted-media/clearkey-mp4-syntax-mediakeysession.https.html": [
[
- "/encrypted-media/clearkey-mp4-syntax-mediakeysession.html",
+ "/encrypted-media/clearkey-mp4-syntax-mediakeysession.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.html": [
+ "encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.https.html": [
[
- "/encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.html",
+ "/encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-unique-origin.html": [
+ "encrypted-media/clearkey-mp4-unique-origin.https.html": [
[
- "/encrypted-media/clearkey-mp4-unique-origin.html",
+ "/encrypted-media/clearkey-mp4-unique-origin.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-update-disallowed-input.html": [
+ "encrypted-media/clearkey-mp4-update-disallowed-input.https.html": [
[
- "/encrypted-media/clearkey-mp4-update-disallowed-input.html",
+ "/encrypted-media/clearkey-mp4-update-disallowed-input.https.html",
{}
]
],
- "encrypted-media/clearkey-mp4-waiting-for-a-key.html": [
+ "encrypted-media/clearkey-mp4-waiting-for-a-key.https.html": [
[
- "/encrypted-media/clearkey-mp4-waiting-for-a-key.html",
+ "/encrypted-media/clearkey-mp4-waiting-for-a-key.https.html",
{}
]
],
- "encrypted-media/clearkey-not-callable-after-createsession.html": [
+ "encrypted-media/clearkey-not-callable-after-createsession.https.html": [
[
- "/encrypted-media/clearkey-not-callable-after-createsession.html",
+ "/encrypted-media/clearkey-not-callable-after-createsession.https.html",
{}
]
],
- "encrypted-media/clearkey-update-non-ascii-input.html": [
+ "encrypted-media/clearkey-update-non-ascii-input.https.html": [
[
- "/encrypted-media/clearkey-update-non-ascii-input.html",
+ "/encrypted-media/clearkey-update-non-ascii-input.https.html",
{}
]
],
- "encrypted-media/drm-check-initdata-type.html": [
+ "encrypted-media/drm-check-initdata-type.https.html": [
[
- "/encrypted-media/drm-check-initdata-type.html",
+ "/encrypted-media/drm-check-initdata-type.https.html",
{}
]
],
- "encrypted-media/drm-events-session-closed-event.html": [
+ "encrypted-media/drm-events-session-closed-event.https.html": [
[
- "/encrypted-media/drm-events-session-closed-event.html",
+ "/encrypted-media/drm-events-session-closed-event.https.html",
{}
]
],
- "encrypted-media/drm-events.html": [
+ "encrypted-media/drm-events.https.html": [
[
- "/encrypted-media/drm-events.html",
+ "/encrypted-media/drm-events.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-expiration.html": [
+ "encrypted-media/drm-expiration.https.html": [
[
- "/encrypted-media/drm-expiration.html",
+ "/encrypted-media/drm-expiration.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-generate-request-disallowed-input.html": [
+ "encrypted-media/drm-generate-request-disallowed-input.https.html": [
[
- "/encrypted-media/drm-generate-request-disallowed-input.html",
+ "/encrypted-media/drm-generate-request-disallowed-input.https.html",
{}
]
],
- "encrypted-media/drm-invalid-license.html": [
+ "encrypted-media/drm-invalid-license.https.html": [
[
- "/encrypted-media/drm-invalid-license.html",
+ "/encrypted-media/drm-invalid-license.https.html",
{}
]
],
- "encrypted-media/drm-keystatuses-multiple-sessions.html": [
+ "encrypted-media/drm-keystatuses-multiple-sessions.https.html": [
[
- "/encrypted-media/drm-keystatuses-multiple-sessions.html",
+ "/encrypted-media/drm-keystatuses-multiple-sessions.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-keystatuses.html": [
+ "encrypted-media/drm-keystatuses.https.html": [
[
- "/encrypted-media/drm-keystatuses.html",
+ "/encrypted-media/drm-keystatuses.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-onencrypted.html": [
+ "encrypted-media/drm-mp4-onencrypted.https.html": [
[
- "/encrypted-media/drm-mp4-onencrypted.html",
+ "/encrypted-media/drm-mp4-onencrypted.https.html",
{}
]
],
- "encrypted-media/drm-mp4-playback-destroy-persistent-license.html": [
+ "encrypted-media/drm-mp4-playback-destroy-persistent-license.https.html": [
[
- "/encrypted-media/drm-mp4-playback-destroy-persistent-license.html",
+ "/encrypted-media/drm-mp4-playback-destroy-persistent-license.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-playback-persistent-license-events.html": [
+ "encrypted-media/drm-mp4-playback-persistent-license-events.https.html": [
[
- "/encrypted-media/drm-mp4-playback-persistent-license-events.html",
+ "/encrypted-media/drm-mp4-playback-persistent-license-events.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-playback-persistent-license.html": [
+ "encrypted-media/drm-mp4-playback-persistent-license.https.html": [
[
- "/encrypted-media/drm-mp4-playback-persistent-license.html",
+ "/encrypted-media/drm-mp4-playback-persistent-license.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-playback-persistent-usage-record-events.html": [
+ "encrypted-media/drm-mp4-playback-persistent-usage-record-events.https.html": [
[
- "/encrypted-media/drm-mp4-playback-persistent-usage-record-events.html",
+ "/encrypted-media/drm-mp4-playback-persistent-usage-record-events.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-playback-persistent-usage-record.html": [
+ "encrypted-media/drm-mp4-playback-persistent-usage-record.https.html": [
[
- "/encrypted-media/drm-mp4-playback-persistent-usage-record.html",
+ "/encrypted-media/drm-mp4-playback-persistent-usage-record.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.html": [
+ "encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.https.html": [
[
- "/encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.html",
+ "/encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-playback-retrieve-persistent-license.html": [
+ "encrypted-media/drm-mp4-playback-retrieve-persistent-license.https.html": [
[
- "/encrypted-media/drm-mp4-playback-retrieve-persistent-license.html",
+ "/encrypted-media/drm-mp4-playback-retrieve-persistent-license.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.html": [
+ "encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.https.html": [
[
- "/encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.html",
+ "/encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-playback-temporary-clear-encrypted.html": [
+ "encrypted-media/drm-mp4-playback-temporary-clear-encrypted.https.html": [
[
- "/encrypted-media/drm-mp4-playback-temporary-clear-encrypted.html",
+ "/encrypted-media/drm-mp4-playback-temporary-clear-encrypted.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.html": [
+ "encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.https.html": [
[
- "/encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.html",
+ "/encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-playback-temporary-encrypted-clear.html": [
+ "encrypted-media/drm-mp4-playback-temporary-encrypted-clear.https.html": [
[
- "/encrypted-media/drm-mp4-playback-temporary-encrypted-clear.html",
+ "/encrypted-media/drm-mp4-playback-temporary-encrypted-clear.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-playback-temporary-events.html": [
+ "encrypted-media/drm-mp4-playback-temporary-events.https.html": [
[
- "/encrypted-media/drm-mp4-playback-temporary-events.html",
+ "/encrypted-media/drm-mp4-playback-temporary-events.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-playback-temporary-expired.html": [
+ "encrypted-media/drm-mp4-playback-temporary-expired.https.html": [
[
- "/encrypted-media/drm-mp4-playback-temporary-expired.html",
+ "/encrypted-media/drm-mp4-playback-temporary-expired.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.html": [
+ "encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.https.html": [
[
- "/encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.html",
+ "/encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-playback-temporary-multikey-sequential.html": [
+ "encrypted-media/drm-mp4-playback-temporary-multikey-sequential.https.html": [
[
- "/encrypted-media/drm-mp4-playback-temporary-multikey-sequential.html",
+ "/encrypted-media/drm-mp4-playback-temporary-multikey-sequential.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-playback-temporary-multikey.html": [
+ "encrypted-media/drm-mp4-playback-temporary-multikey.https.html": [
[
- "/encrypted-media/drm-mp4-playback-temporary-multikey.html",
+ "/encrypted-media/drm-mp4-playback-temporary-multikey.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-playback-temporary-multisession.html": [
+ "encrypted-media/drm-mp4-playback-temporary-multisession.https.html": [
[
- "/encrypted-media/drm-mp4-playback-temporary-multisession.html",
+ "/encrypted-media/drm-mp4-playback-temporary-multisession.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.html": [
+ "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.https.html": [
[
- "/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.html",
+ "/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.html": [
+ "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.https.html": [
[
- "/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.html",
+ "/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.html": [
+ "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.https.html": [
[
- "/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.html",
+ "/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.html": [
+ "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.https.html": [
[
- "/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.html",
+ "/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-playback-temporary-two-videos.html": [
+ "encrypted-media/drm-mp4-playback-temporary-two-videos.https.html": [
[
- "/encrypted-media/drm-mp4-playback-temporary-two-videos.html",
+ "/encrypted-media/drm-mp4-playback-temporary-two-videos.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-playback-temporary-waitingforkey.html": [
+ "encrypted-media/drm-mp4-playback-temporary-waitingforkey.https.html": [
[
- "/encrypted-media/drm-mp4-playback-temporary-waitingforkey.html",
+ "/encrypted-media/drm-mp4-playback-temporary-waitingforkey.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-playback-temporary.html": [
+ "encrypted-media/drm-mp4-playback-temporary.https.html": [
[
- "/encrypted-media/drm-mp4-playback-temporary.html",
+ "/encrypted-media/drm-mp4-playback-temporary.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-requestmediakeysystemaccess.html": [
+ "encrypted-media/drm-mp4-requestmediakeysystemaccess.https.html": [
[
- "/encrypted-media/drm-mp4-requestmediakeysystemaccess.html",
+ "/encrypted-media/drm-mp4-requestmediakeysystemaccess.https.html",
{}
]
],
- "encrypted-media/drm-mp4-reset-src-after-setmediakeys.html": [
+ "encrypted-media/drm-mp4-reset-src-after-setmediakeys.https.html": [
[
- "/encrypted-media/drm-mp4-reset-src-after-setmediakeys.html",
+ "/encrypted-media/drm-mp4-reset-src-after-setmediakeys.https.html",
{}
]
],
- "encrypted-media/drm-mp4-setmediakeys-again-after-playback.html": [
+ "encrypted-media/drm-mp4-setmediakeys-again-after-playback.https.html": [
[
- "/encrypted-media/drm-mp4-setmediakeys-again-after-playback.html",
+ "/encrypted-media/drm-mp4-setmediakeys-again-after-playback.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.html": [
+ "encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.https.html": [
[
- "/encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.html",
+ "/encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-setmediakeys-at-same-time.html": [
+ "encrypted-media/drm-mp4-setmediakeys-at-same-time.https.html": [
[
- "/encrypted-media/drm-mp4-setmediakeys-at-same-time.html",
+ "/encrypted-media/drm-mp4-setmediakeys-at-same-time.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.html": [
+ "encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html": [
[
- "/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.html",
+ "/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html": [
+ "encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html": [
[
- "/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html",
+ "/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.html": [
+ "encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.https.html": [
[
- "/encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.html",
+ "/encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-mp4-setmediakeys.html": [
+ "encrypted-media/drm-mp4-setmediakeys.https.html": [
[
- "/encrypted-media/drm-mp4-setmediakeys.html",
+ "/encrypted-media/drm-mp4-setmediakeys.https.html",
{}
]
],
- "encrypted-media/drm-mp4-syntax-mediakeys.html": [
+ "encrypted-media/drm-mp4-syntax-mediakeys.https.html": [
[
- "/encrypted-media/drm-mp4-syntax-mediakeys.html",
+ "/encrypted-media/drm-mp4-syntax-mediakeys.https.html",
{}
]
],
- "encrypted-media/drm-mp4-syntax-mediakeysession.html": [
+ "encrypted-media/drm-mp4-syntax-mediakeysession.https.html": [
[
- "/encrypted-media/drm-mp4-syntax-mediakeysession.html",
+ "/encrypted-media/drm-mp4-syntax-mediakeysession.https.html",
{}
]
],
- "encrypted-media/drm-mp4-syntax-mediakeysystemaccess.html": [
+ "encrypted-media/drm-mp4-syntax-mediakeysystemaccess.https.html": [
[
- "/encrypted-media/drm-mp4-syntax-mediakeysystemaccess.html",
+ "/encrypted-media/drm-mp4-syntax-mediakeysystemaccess.https.html",
{}
]
],
- "encrypted-media/drm-mp4-unique-origin.html": [
+ "encrypted-media/drm-mp4-unique-origin.https.html": [
[
- "/encrypted-media/drm-mp4-unique-origin.html",
+ "/encrypted-media/drm-mp4-unique-origin.https.html",
{}
]
],
- "encrypted-media/drm-mp4-waiting-for-a-key.html": [
+ "encrypted-media/drm-mp4-waiting-for-a-key.https.html": [
[
- "/encrypted-media/drm-mp4-waiting-for-a-key.html",
+ "/encrypted-media/drm-mp4-waiting-for-a-key.https.html",
{
"timeout": "long"
}
]
],
- "encrypted-media/drm-not-callable-after-createsession.html": [
+ "encrypted-media/drm-not-callable-after-createsession.https.html": [
[
- "/encrypted-media/drm-not-callable-after-createsession.html",
+ "/encrypted-media/drm-not-callable-after-createsession.https.html",
{}
]
],
- "encrypted-media/drm-temporary-license-type.html": [
+ "encrypted-media/drm-temporary-license-type.https.html": [
[
- "/encrypted-media/drm-temporary-license-type.html",
+ "/encrypted-media/drm-temporary-license-type.https.html",
{
"timeout": "long"
}
@@ -309349,9 +314417,9 @@
{}
]
],
- "encrypted-media/idlharness.html": [
+ "encrypted-media/idlharness.https.html": [
[
- "/encrypted-media/idlharness.html",
+ "/encrypted-media/idlharness.https.html",
{}
]
],
@@ -309733,6 +314801,46 @@
{}
]
],
+ "feature-policy/autoplay-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html": [
+ [
+ "/feature-policy/autoplay-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html",
+ {
+ "testdriver": true
+ }
+ ]
+ ],
+ "feature-policy/autoplay-allowed-by-feature-policy-attribute.https.sub.html": [
+ [
+ "/feature-policy/autoplay-allowed-by-feature-policy-attribute.https.sub.html",
+ {
+ "testdriver": true
+ }
+ ]
+ ],
+ "feature-policy/autoplay-allowed-by-feature-policy.https.sub.html": [
+ [
+ "/feature-policy/autoplay-allowed-by-feature-policy.https.sub.html",
+ {
+ "testdriver": true
+ }
+ ]
+ ],
+ "feature-policy/autoplay-default-feature-policy.https.sub.html": [
+ [
+ "/feature-policy/autoplay-default-feature-policy.https.sub.html",
+ {
+ "testdriver": true
+ }
+ ]
+ ],
+ "feature-policy/autoplay-disabled-by-feature-policy.https.sub.html": [
+ [
+ "/feature-policy/autoplay-disabled-by-feature-policy.https.sub.html",
+ {
+ "testdriver": true
+ }
+ ]
+ ],
"feature-policy/payment-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html": [
[
"/feature-policy/payment-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html",
@@ -310457,6 +315565,12 @@
{}
]
],
+ "fetch/api/request/destination/fetch-destination.https.html": [
+ [
+ "/fetch/api/request/destination/fetch-destination.https.html",
+ {}
+ ]
+ ],
"fetch/api/request/multi-globals/url-parsing.html": [
[
"/fetch/api/request/multi-globals/url-parsing.html",
@@ -310953,12 +316067,84 @@
{}
]
],
+ "geolocation-sensor/GeolocationSensor-disabled-by-feature-policy.https.html": [
+ [
+ "/geolocation-sensor/GeolocationSensor-disabled-by-feature-policy.https.html",
+ {}
+ ]
+ ],
+ "geolocation-sensor/GeolocationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html": [
+ [
+ "/geolocation-sensor/GeolocationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html",
+ {}
+ ]
+ ],
+ "geolocation-sensor/GeolocationSensor-enabled-by-feature-policy-attribute.https.html": [
+ [
+ "/geolocation-sensor/GeolocationSensor-enabled-by-feature-policy-attribute.https.html",
+ {}
+ ]
+ ],
+ "geolocation-sensor/GeolocationSensor-enabled-by-feature-policy.https.html": [
+ [
+ "/geolocation-sensor/GeolocationSensor-enabled-by-feature-policy.https.html",
+ {}
+ ]
+ ],
+ "geolocation-sensor/GeolocationSensor-enabled-on-self-origin-by-feature-policy.https.html": [
+ [
+ "/geolocation-sensor/GeolocationSensor-enabled-on-self-origin-by-feature-policy.https.html",
+ {}
+ ]
+ ],
+ "geolocation-sensor/GeolocationSensor.https.html": [
+ [
+ "/geolocation-sensor/GeolocationSensor.https.html",
+ {}
+ ]
+ ],
+ "geolocation-sensor/GeolocationSensor_insecure_context.html": [
+ [
+ "/geolocation-sensor/GeolocationSensor_insecure_context.html",
+ {}
+ ]
+ ],
"geolocation-sensor/idlharness.https.html": [
[
"/geolocation-sensor/idlharness.https.html",
{}
]
],
+ "gyroscope/Gyroscope-disabled-by-feature-policy.https.html": [
+ [
+ "/gyroscope/Gyroscope-disabled-by-feature-policy.https.html",
+ {}
+ ]
+ ],
+ "gyroscope/Gyroscope-enabled-by-feature-policy-attribute-redirect-on-load.https.html": [
+ [
+ "/gyroscope/Gyroscope-enabled-by-feature-policy-attribute-redirect-on-load.https.html",
+ {}
+ ]
+ ],
+ "gyroscope/Gyroscope-enabled-by-feature-policy-attribute.https.html": [
+ [
+ "/gyroscope/Gyroscope-enabled-by-feature-policy-attribute.https.html",
+ {}
+ ]
+ ],
+ "gyroscope/Gyroscope-enabled-by-feature-policy.https.html": [
+ [
+ "/gyroscope/Gyroscope-enabled-by-feature-policy.https.html",
+ {}
+ ]
+ ],
+ "gyroscope/Gyroscope-enabled-on-self-origin-by-feature-policy.https.html": [
+ [
+ "/gyroscope/Gyroscope-enabled-on-self-origin-by-feature-policy.https.html",
+ {}
+ ]
+ ],
"gyroscope/Gyroscope.https.html": [
[
"/gyroscope/Gyroscope.https.html",
@@ -311003,6 +316189,12 @@
{}
]
],
+ "hr-time/performance-tojson.html": [
+ [
+ "/hr-time/performance-tojson.html",
+ {}
+ ]
+ ],
"hr-time/test_cross_frame_start.html": [
[
"/hr-time/test_cross_frame_start.html",
@@ -314005,6 +319197,12 @@
{}
]
],
+ "html/dom/usvstring-reflection.html": [
+ [
+ "/html/dom/usvstring-reflection.html",
+ {}
+ ]
+ ],
"html/editing/activation/click.html": [
[
"/html/editing/activation/click.html",
@@ -314987,6 +320185,12 @@
{}
]
],
+ "html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/crossOrigin.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/crossOrigin.html",
+ {}
+ ]
+ ],
"html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/textTracks.html": [
[
"/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/textTracks.html",
@@ -315095,6 +320299,12 @@
{}
]
],
+ "html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/constructor.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/constructor.html",
+ {}
+ ]
+ ],
"html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/endTime.html": [
[
"/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/endTime.html",
@@ -315887,24 +321097,390 @@
{}
]
],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-active-cues.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-active-cues.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-add-remove-cue.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-add-remove-cue.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-add-track.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-add-track.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-addtrack-kind.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-addtrack-kind.html",
+ {}
+ ]
+ ],
"html/semantics/embedded-content/media-elements/track/track-element/track-api-texttracks.html": [
[
"/html/semantics/embedded-content/media-elements/track/track-element/track-api-texttracks.html",
{}
]
],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-cue-empty.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-cue-empty.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-cue-inline.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-cue-inline.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable-fragment.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable-fragment.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable.html",
+ {}
+ ]
+ ],
"html/semantics/embedded-content/media-elements/track/track-element/track-cue-order.html": [
[
"/html/semantics/embedded-content/media-elements/track/track-element/track-cue-order.html",
{}
]
],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-cues-missed.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-cues-missed.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-cues-pause-on-exit.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-cues-pause-on-exit.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-cues-seeking.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-cues-seeking.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-cues-sorted-before-dispatch.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-cues-sorted-before-dispatch.html",
+ {}
+ ]
+ ],
"html/semantics/embedded-content/media-elements/track/track-element/track-data-url.html": [
[
"/html/semantics/embedded-content/media-elements/track/track-element/track-data-url.html",
{}
]
],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-disabled-addcue.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-disabled-addcue.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-disabled.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-disabled.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-element-dom-change.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-element-dom-change.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change-error.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change-error.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-large-timestamp.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-large-timestamp.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-load-error-readyState.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-load-error-readyState.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-load-from-element-readyState.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-load-from-element-readyState.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-load-from-src-readyState.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-load-from-src-readyState.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-mode-disabled.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-mode-disabled.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-mode-not-changed-by-new-track.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-mode-not-changed-by-new-track.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-mode-triggers-loading.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-mode-triggers-loading.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-mode.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-mode.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-remove-active-cue.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-remove-active-cue.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-remove-by-setting-innerHTML.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-remove-by-setting-innerHTML.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-remove-insert-ready-state.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-remove-insert-ready-state.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-remove-quickly.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-remove-quickly.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-remove-track.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-remove-track.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-align-positioning.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-align-positioning.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-align-text-line-position.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-align-text-line-position.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-alignment.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-alignment.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-blank-lines.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-blank-lines.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-bom.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-bom.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-class-markup.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-class-markup.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-identifiers.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-identifiers.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-no-id.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-no-id.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-recovery.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-recovery.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-size-align.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-size-align.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-size.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-size.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-degenerate-cues.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-degenerate-cues.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-empty-cue.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-empty-cue.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-entities.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-entities.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-header-comment.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-header-comment.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-interspersed-non-cue.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-interspersed-non-cue.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-line-position.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-line-position.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-magic-header.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-magic-header.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-markup.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-markup.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-newlines.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-newlines.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-no-timings.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-no-timings.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-positioning.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-positioning.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-settings.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-settings.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timestamp.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timestamp.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-hour.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-hour.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-no-hours.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-no-hours.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-whitespace.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-whitespace.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-unsupported-markup.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-unsupported-markup.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-utf8.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-utf8.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-valign.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-valign.html",
+ {}
+ ]
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-voice.html": [
+ [
+ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-voice.html",
+ {}
+ ]
+ ],
"html/semantics/embedded-content/media-elements/user-interface/muted.html": [
[
"/html/semantics/embedded-content/media-elements/user-interface/muted.html",
@@ -318221,6 +323797,12 @@
{}
]
],
+ "html/semantics/forms/the-select-element/select-add.html": [
+ [
+ "/html/semantics/forms/the-select-element/select-add.html",
+ {}
+ ]
+ ],
"html/semantics/forms/the-select-element/select-ask-for-reset.html": [
[
"/html/semantics/forms/the-select-element/select-ask-for-reset.html",
@@ -318395,6 +323977,12 @@
{}
]
],
+ "html/semantics/interactive-elements/the-dialog-element/abspos-dialog-layout.html": [
+ [
+ "/html/semantics/interactive-elements/the-dialog-element/abspos-dialog-layout.html",
+ {}
+ ]
+ ],
"html/semantics/interactive-elements/the-dialog-element/centering.html": [
[
"/html/semantics/interactive-elements/the-dialog-element/centering.html",
@@ -318437,12 +324025,30 @@
{}
]
],
+ "html/semantics/interactive-elements/the-dialog-element/dialog-scrolled-viewport.html": [
+ [
+ "/html/semantics/interactive-elements/the-dialog-element/dialog-scrolled-viewport.html",
+ {}
+ ]
+ ],
"html/semantics/interactive-elements/the-dialog-element/dialog-showModal.html": [
[
"/html/semantics/interactive-elements/the-dialog-element/dialog-showModal.html",
{}
]
],
+ "html/semantics/interactive-elements/the-dialog-element/inert-does-not-match-disabled-selector.html": [
+ [
+ "/html/semantics/interactive-elements/the-dialog-element/inert-does-not-match-disabled-selector.html",
+ {}
+ ]
+ ],
+ "html/semantics/interactive-elements/the-dialog-element/inert-node-is-unfocusable.html": [
+ [
+ "/html/semantics/interactive-elements/the-dialog-element/inert-node-is-unfocusable.html",
+ {}
+ ]
+ ],
"html/semantics/interactive-elements/the-dialog-element/show-modal-focusing-steps.html": [
[
"/html/semantics/interactive-elements/the-dialog-element/show-modal-focusing-steps.html",
@@ -319517,6 +325123,24 @@
{}
]
],
+ "html/semantics/scripting-1/the-script-element/module/choice-of-error-1.html": [
+ [
+ "/html/semantics/scripting-1/the-script-element/module/choice-of-error-1.html",
+ {}
+ ]
+ ],
+ "html/semantics/scripting-1/the-script-element/module/choice-of-error-2.html": [
+ [
+ "/html/semantics/scripting-1/the-script-element/module/choice-of-error-2.html",
+ {}
+ ]
+ ],
+ "html/semantics/scripting-1/the-script-element/module/choice-of-error-3.html": [
+ [
+ "/html/semantics/scripting-1/the-script-element/module/choice-of-error-3.html",
+ {}
+ ]
+ ],
"html/semantics/scripting-1/the-script-element/module/compilation-error-1.html": [
[
"/html/semantics/scripting-1/the-script-element/module/compilation-error-1.html",
@@ -319601,15 +325225,27 @@
{}
]
],
- "html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-classic.html": [
+ "html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-classic.html": [
[
- "/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-classic.html",
+ "/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-classic.html",
{}
]
],
- "html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-module.html": [
+ "html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-module.html": [
[
- "/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-module.html",
+ "/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-module.html",
+ {}
+ ]
+ ],
+ "html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-classic.html": [
+ [
+ "/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-classic.html",
+ {}
+ ]
+ ],
+ "html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-module.html": [
+ [
+ "/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-module.html",
{}
]
],
@@ -319619,18 +325255,60 @@
{}
]
],
+ "html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-integrity-classic.html": [
+ [
+ "/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-integrity-classic.html",
+ {}
+ ]
+ ],
+ "html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-integrity-module.html": [
+ [
+ "/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-integrity-module.html",
+ {}
+ ]
+ ],
"html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-module.html": [
[
"/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-module.html",
{}
]
],
+ "html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-classic.html": [
+ [
+ "/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-classic.html",
+ {}
+ ]
+ ],
+ "html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-module.html": [
+ [
+ "/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-module.html",
+ {}
+ ]
+ ],
"html/semantics/scripting-1/the-script-element/module/error-and-slow-dependency.html": [
[
"/html/semantics/scripting-1/the-script-element/module/error-and-slow-dependency.html",
{}
]
],
+ "html/semantics/scripting-1/the-script-element/module/error-type-1.html": [
+ [
+ "/html/semantics/scripting-1/the-script-element/module/error-type-1.html",
+ {}
+ ]
+ ],
+ "html/semantics/scripting-1/the-script-element/module/error-type-2.html": [
+ [
+ "/html/semantics/scripting-1/the-script-element/module/error-type-2.html",
+ {}
+ ]
+ ],
+ "html/semantics/scripting-1/the-script-element/module/error-type-3.html": [
+ [
+ "/html/semantics/scripting-1/the-script-element/module/error-type-3.html",
+ {}
+ ]
+ ],
"html/semantics/scripting-1/the-script-element/module/errorhandling.html": [
[
"/html/semantics/scripting-1/the-script-element/module/errorhandling.html",
@@ -319801,6 +325479,36 @@
{}
]
],
+ "html/semantics/scripting-1/the-script-element/module/referrer-no-referrer.sub.html": [
+ [
+ "/html/semantics/scripting-1/the-script-element/module/referrer-no-referrer.sub.html",
+ {}
+ ]
+ ],
+ "html/semantics/scripting-1/the-script-element/module/referrer-origin-when-cross-origin.sub.html": [
+ [
+ "/html/semantics/scripting-1/the-script-element/module/referrer-origin-when-cross-origin.sub.html",
+ {}
+ ]
+ ],
+ "html/semantics/scripting-1/the-script-element/module/referrer-origin.sub.html": [
+ [
+ "/html/semantics/scripting-1/the-script-element/module/referrer-origin.sub.html",
+ {}
+ ]
+ ],
+ "html/semantics/scripting-1/the-script-element/module/referrer-same-origin.sub.html": [
+ [
+ "/html/semantics/scripting-1/the-script-element/module/referrer-same-origin.sub.html",
+ {}
+ ]
+ ],
+ "html/semantics/scripting-1/the-script-element/module/referrer-unsafe-url.sub.html": [
+ [
+ "/html/semantics/scripting-1/the-script-element/module/referrer-unsafe-url.sub.html",
+ {}
+ ]
+ ],
"html/semantics/scripting-1/the-script-element/module/script-for-event.html": [
[
"/html/semantics/scripting-1/the-script-element/module/script-for-event.html",
@@ -319897,6 +325605,12 @@
{}
]
],
+ "html/semantics/scripting-1/the-script-element/script-defer.html": [
+ [
+ "/html/semantics/scripting-1/the-script-element/script-defer.html",
+ {}
+ ]
+ ],
"html/semantics/scripting-1/the-script-element/script-for-event-xhtml.xhtml": [
[
"/html/semantics/scripting-1/the-script-element/script-for-event-xhtml.xhtml",
@@ -322863,12 +328577,48 @@
{}
]
],
+ "longtask-timing/longtask-tojson.html": [
+ [
+ "/longtask-timing/longtask-tojson.html",
+ {}
+ ]
+ ],
"longtask-timing/shared-renderer/longtask-in-new-window.html": [
[
"/longtask-timing/shared-renderer/longtask-in-new-window.html",
{}
]
],
+ "magnetometer/Magnetometer-disabled-by-feature-policy.https.html": [
+ [
+ "/magnetometer/Magnetometer-disabled-by-feature-policy.https.html",
+ {}
+ ]
+ ],
+ "magnetometer/Magnetometer-enabled-by-feature-policy-attribute-redirect-on-load.https.html": [
+ [
+ "/magnetometer/Magnetometer-enabled-by-feature-policy-attribute-redirect-on-load.https.html",
+ {}
+ ]
+ ],
+ "magnetometer/Magnetometer-enabled-by-feature-policy-attribute.https.html": [
+ [
+ "/magnetometer/Magnetometer-enabled-by-feature-policy-attribute.https.html",
+ {}
+ ]
+ ],
+ "magnetometer/Magnetometer-enabled-by-feature-policy.https.html": [
+ [
+ "/magnetometer/Magnetometer-enabled-by-feature-policy.https.html",
+ {}
+ ]
+ ],
+ "magnetometer/Magnetometer-enabled-on-self-origin-by-feature-policy.https.html": [
+ [
+ "/magnetometer/Magnetometer-enabled-on-self-origin-by-feature-policy.https.html",
+ {}
+ ]
+ ],
"magnetometer/Magnetometer.https.html": [
[
"/magnetometer/Magnetometer.https.html",
@@ -323643,6 +329393,26 @@
{}
]
],
+ "mimesniff/mime-types/charset-parameter.window.js": [
+ [
+ "/mimesniff/mime-types/charset-parameter.window.html",
+ {}
+ ]
+ ],
+ "mimesniff/mime-types/parsing.any.js": [
+ [
+ "/mimesniff/mime-types/parsing.any.html",
+ {
+ "timeout": "long"
+ }
+ ],
+ [
+ "/mimesniff/mime-types/parsing.any.worker.html",
+ {
+ "timeout": "long"
+ }
+ ]
+ ],
"mixed-content/audio-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html": [
[
"/mixed-content/audio-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html",
@@ -324105,39 +329875,39 @@
{}
]
],
- "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html": [
+ "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html": [
[
- "/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html",
+ "/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html",
{}
]
],
- "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html": [
+ "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html": [
[
- "/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html",
+ "/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html",
{}
]
],
- "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html": [
+ "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html": [
[
- "/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html",
+ "/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html",
{}
]
],
- "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html": [
+ "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html": [
[
- "/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html",
+ "/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html",
{}
]
],
- "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html": [
+ "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html": [
[
- "/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html",
+ "/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html",
{}
]
],
- "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html": [
+ "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html": [
[
- "/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html",
+ "/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html",
{}
]
],
@@ -324153,15 +329923,15 @@
{}
]
],
- "mixed-content/link-prefetch-tag/meta-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html": [
+ "mixed-content/link-prefetch-tag/meta-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html": [
[
- "/mixed-content/link-prefetch-tag/meta-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html",
+ "/mixed-content/link-prefetch-tag/meta-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html",
{}
]
],
- "mixed-content/link-prefetch-tag/meta-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html": [
+ "mixed-content/link-prefetch-tag/meta-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html": [
[
- "/mixed-content/link-prefetch-tag/meta-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html",
+ "/mixed-content/link-prefetch-tag/meta-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html",
{}
]
],
@@ -324171,39 +329941,39 @@
{}
]
],
- "mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html": [
+ "mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/keep-scheme-redirect/blockable/no-opt-in-blocks.https.html": [
[
- "/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html",
+ "/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/keep-scheme-redirect/blockable/no-opt-in-blocks.https.html",
{}
]
],
- "mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/no-redirect/optionally-blockable/no-opt-in-allows.https.html": [
+ "mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/no-redirect/blockable/no-opt-in-blocks.https.html": [
[
- "/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/no-redirect/optionally-blockable/no-opt-in-allows.https.html",
+ "/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/no-redirect/blockable/no-opt-in-blocks.https.html",
{}
]
],
- "mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html": [
+ "mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/swap-scheme-redirect/blockable/no-opt-in-blocks.https.html": [
[
- "/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html",
+ "/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/swap-scheme-redirect/blockable/no-opt-in-blocks.https.html",
{}
]
],
- "mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html": [
+ "mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/keep-scheme-redirect/blockable/no-opt-in-blocks.https.html": [
[
- "/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html",
+ "/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/keep-scheme-redirect/blockable/no-opt-in-blocks.https.html",
{}
]
],
- "mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/no-redirect/optionally-blockable/no-opt-in-allows.https.html": [
+ "mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/no-redirect/blockable/no-opt-in-blocks.https.html": [
[
- "/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/no-redirect/optionally-blockable/no-opt-in-allows.https.html",
+ "/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/no-redirect/blockable/no-opt-in-blocks.https.html",
{}
]
],
- "mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html": [
+ "mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/swap-scheme-redirect/blockable/no-opt-in-blocks.https.html": [
[
- "/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html",
+ "/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/swap-scheme-redirect/blockable/no-opt-in-blocks.https.html",
{}
]
],
@@ -334137,6 +339907,36 @@
{}
]
],
+ "orientation-sensor/AbsoluteOrientationSensor-disabled-by-feature-policy.https.html": [
+ [
+ "/orientation-sensor/AbsoluteOrientationSensor-disabled-by-feature-policy.https.html",
+ {}
+ ]
+ ],
+ "orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html": [
+ [
+ "/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html",
+ {}
+ ]
+ ],
+ "orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy-attribute.https.html": [
+ [
+ "/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy-attribute.https.html",
+ {}
+ ]
+ ],
+ "orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy.https.html": [
+ [
+ "/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy.https.html",
+ {}
+ ]
+ ],
+ "orientation-sensor/AbsoluteOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html": [
+ [
+ "/orientation-sensor/AbsoluteOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html",
+ {}
+ ]
+ ],
"orientation-sensor/OrientationSensor.https.html": [
[
"/orientation-sensor/OrientationSensor.https.html",
@@ -334149,6 +339949,36 @@
{}
]
],
+ "orientation-sensor/RelativeOrientationSensor-disabled-by-feature-policy.https.html": [
+ [
+ "/orientation-sensor/RelativeOrientationSensor-disabled-by-feature-policy.https.html",
+ {}
+ ]
+ ],
+ "orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html": [
+ [
+ "/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html",
+ {}
+ ]
+ ],
+ "orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy-attribute.https.html": [
+ [
+ "/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy-attribute.https.html",
+ {}
+ ]
+ ],
+ "orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy.https.html": [
+ [
+ "/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy.https.html",
+ {}
+ ]
+ ],
+ "orientation-sensor/RelativeOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html": [
+ [
+ "/orientation-sensor/RelativeOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html",
+ {}
+ ]
+ ],
"orientation-sensor/idlharness.https.html": [
[
"/orientation-sensor/idlharness.https.html",
@@ -334275,6 +340105,12 @@
{}
]
],
+ "paint-timing/sibling-painting-first-image.html": [
+ [
+ "/paint-timing/sibling-painting-first-image.html",
+ {}
+ ]
+ ],
"payment-handler/interfaces.https.any.js": [
[
"/payment-handler/interfaces.https.any.html",
@@ -334425,6 +340261,12 @@
{}
]
],
+ "payment-request/payment-request-not-exposed.https.worker.js": [
+ [
+ "/payment-request/payment-request-not-exposed.https.worker.html",
+ {}
+ ]
+ ],
"payment-request/payment-request-onshippingaddresschange-attribute.https.html": [
[
"/payment-request/payment-request-onshippingaddresschange-attribute.https.html",
@@ -334483,6 +340325,12 @@
{}
]
],
+ "performance-timeline/performanceentry-tojson.html": [
+ [
+ "/performance-timeline/performanceentry-tojson.html",
+ {}
+ ]
+ ],
"performance-timeline/po-callback-mutate.any.js": [
[
"/performance-timeline/po-callback-mutate.any.html",
@@ -334651,12 +340499,6 @@
{}
]
],
- "preload/fetch-destination.https.html": [
- [
- "/preload/fetch-destination.https.html",
- {}
- ]
- ],
"preload/link-header-on-subresource.html": [
[
"/preload/link-header-on-subresource.html",
@@ -334831,59 +340673,59 @@
{}
]
],
- "quirks-mode/blocks-ignore-line-height.html": [
+ "quirks/blocks-ignore-line-height.html": [
[
- "/quirks-mode/blocks-ignore-line-height.html",
+ "/quirks/blocks-ignore-line-height.html",
{}
]
],
- "quirks-mode/classname-query-after-sibling-adoption.html": [
+ "quirks/classname-query-after-sibling-adoption.html": [
[
- "/quirks-mode/classname-query-after-sibling-adoption.html",
+ "/quirks/classname-query-after-sibling-adoption.html",
{}
]
],
- "quirks-mode/hashless-hex-color.html": [
+ "quirks/hashless-hex-color.html": [
[
- "/quirks-mode/hashless-hex-color.html",
+ "/quirks/hashless-hex-color.html",
{
"timeout": "long"
}
]
],
- "quirks-mode/line-height-calculation.html": [
+ "quirks/line-height-calculation.html": [
[
- "/quirks-mode/line-height-calculation.html",
+ "/quirks/line-height-calculation.html",
{}
]
],
- "quirks-mode/percentage-height-calculation.html": [
+ "quirks/percentage-height-calculation.html": [
[
- "/quirks-mode/percentage-height-calculation.html",
+ "/quirks/percentage-height-calculation.html",
{}
]
],
- "quirks-mode/supports.html": [
+ "quirks/supports.html": [
[
- "/quirks-mode/supports.html",
+ "/quirks/supports.html",
{}
]
],
- "quirks-mode/table-cell-nowrap-minimum-width-calculation.html": [
+ "quirks/table-cell-nowrap-minimum-width-calculation.html": [
[
- "/quirks-mode/table-cell-nowrap-minimum-width-calculation.html",
+ "/quirks/table-cell-nowrap-minimum-width-calculation.html",
{}
]
],
- "quirks-mode/table-cell-width-calculation.html": [
+ "quirks/table-cell-width-calculation.html": [
[
- "/quirks-mode/table-cell-width-calculation.html",
+ "/quirks/table-cell-width-calculation.html",
{}
]
],
- "quirks-mode/unitless-length.html": [
+ "quirks/unitless-length.html": [
[
- "/quirks-mode/unitless-length.html",
+ "/quirks/unitless-length.html",
{}
]
],
@@ -343071,6 +348913,12 @@
{}
]
],
+ "resource-timing/resource-timing-tojson.html": [
+ [
+ "/resource-timing/resource-timing-tojson.html",
+ {}
+ ]
+ ],
"resource-timing/resource-timing.html": [
[
"/resource-timing/resource-timing.html",
@@ -343813,6 +349661,14 @@
{}
]
],
+ "service-workers/service-worker/about-blank-replacement.https.html": [
+ [
+ "/service-workers/service-worker/about-blank-replacement.https.html",
+ {
+ "timeout": "long"
+ }
+ ]
+ ],
"service-workers/service-worker/activate-event-after-install-state-change.https.html": [
[
"/service-workers/service-worker/activate-event-after-install-state-change.https.html",
@@ -343999,6 +349855,12 @@
{}
]
],
+ "service-workers/service-worker/fetch-cors-exposed-header-names.https.html": [
+ [
+ "/service-workers/service-worker/fetch-cors-exposed-header-names.https.html",
+ {}
+ ]
+ ],
"service-workers/service-worker/fetch-cors-xhr.https.html": [
[
"/service-workers/service-worker/fetch-cors-xhr.https.html",
@@ -344049,6 +349911,12 @@
{}
]
],
+ "service-workers/service-worker/fetch-event-respond-with-custom-response.https.html": [
+ [
+ "/service-workers/service-worker/fetch-event-respond-with-custom-response.https.html",
+ {}
+ ]
+ ],
"service-workers/service-worker/fetch-event-respond-with-partial-stream.https.html": [
[
"/service-workers/service-worker/fetch-event-respond-with-partial-stream.https.html",
@@ -344205,30 +350073,6 @@
}
]
],
- "service-workers/service-worker/foreign-fetch-basics.https.html": [
- [
- "/service-workers/service-worker/foreign-fetch-basics.https.html",
- {}
- ]
- ],
- "service-workers/service-worker/foreign-fetch-cors.https.html": [
- [
- "/service-workers/service-worker/foreign-fetch-cors.https.html",
- {}
- ]
- ],
- "service-workers/service-worker/foreign-fetch-event.https.html": [
- [
- "/service-workers/service-worker/foreign-fetch-event.https.html",
- {}
- ]
- ],
- "service-workers/service-worker/foreign-fetch-workers.https.html": [
- [
- "/service-workers/service-worker/foreign-fetch-workers.https.html",
- {}
- ]
- ],
"service-workers/service-worker/getregistration.https.html": [
[
"/service-workers/service-worker/getregistration.https.html",
@@ -344247,12 +350091,6 @@
{}
]
],
- "service-workers/service-worker/iframe-sandbox-register-link-element.https.html": [
- [
- "/service-workers/service-worker/iframe-sandbox-register-link-element.https.html",
- {}
- ]
- ],
"service-workers/service-worker/immutable-prototype-serviceworker.https.html": [
[
"/service-workers/service-worker/immutable-prototype-serviceworker.https.html",
@@ -344325,42 +350163,6 @@
{}
]
],
- "service-workers/service-worker/link-element-register-basic.https.html": [
- [
- "/service-workers/service-worker/link-element-register-basic.https.html",
- {}
- ]
- ],
- "service-workers/service-worker/link-element-register-mime-types.https.html": [
- [
- "/service-workers/service-worker/link-element-register-mime-types.https.html",
- {}
- ]
- ],
- "service-workers/service-worker/link-element-register-scope.https.html": [
- [
- "/service-workers/service-worker/link-element-register-scope.https.html",
- {}
- ]
- ],
- "service-workers/service-worker/link-element-register-script-url.https.html": [
- [
- "/service-workers/service-worker/link-element-register-script-url.https.html",
- {}
- ]
- ],
- "service-workers/service-worker/link-element-register-script.https.html": [
- [
- "/service-workers/service-worker/link-element-register-script.https.html",
- {}
- ]
- ],
- "service-workers/service-worker/link-element-register-security-error.https.html": [
- [
- "/service-workers/service-worker/link-element-register-security-error.https.html",
- {}
- ]
- ],
"service-workers/service-worker/mime-sniffing.https.html": [
[
"/service-workers/service-worker/mime-sniffing.https.html",
@@ -344543,18 +350345,6 @@
{}
]
],
- "service-workers/service-worker/register-foreign-fetch-errors.https.html": [
- [
- "/service-workers/service-worker/register-foreign-fetch-errors.https.html",
- {}
- ]
- ],
- "service-workers/service-worker/register-link-header.https.html": [
- [
- "/service-workers/service-worker/register-link-header.https.html",
- {}
- ]
- ],
"service-workers/service-worker/register-same-scope-different-script-url.https.html": [
[
"/service-workers/service-worker/register-same-scope-different-script-url.https.html",
@@ -344657,6 +350447,12 @@
{}
]
],
+ "service-workers/service-worker/sandboxed-iframe-fetch-event.https.html": [
+ [
+ "/service-workers/service-worker/sandboxed-iframe-fetch-event.https.html",
+ {}
+ ]
+ ],
"service-workers/service-worker/sandboxed-iframe-navigator-serviceworker.https.html": [
[
"/service-workers/service-worker/sandboxed-iframe-navigator-serviceworker.https.html",
@@ -344903,6 +350699,12 @@
{}
]
],
+ "shadow-dom/event-composed-path-after-dom-mutation.html": [
+ [
+ "/shadow-dom/event-composed-path-after-dom-mutation.html",
+ {}
+ ]
+ ],
"shadow-dom/event-composed-path-with-related-target.html": [
[
"/shadow-dom/event-composed-path-with-related-target.html",
@@ -345377,6 +351179,12 @@
{}
]
],
+ "storage/estimate-parallel.https.html": [
+ [
+ "/storage/estimate-parallel.https.html",
+ {}
+ ]
+ ],
"storage/interfaces.https.html": [
[
"/storage/interfaces.https.html",
@@ -346253,6 +352061,30 @@
{}
]
],
+ "streams/transform-streams/properties.dedicatedworker.html": [
+ [
+ "/streams/transform-streams/properties.dedicatedworker.html",
+ {}
+ ]
+ ],
+ "streams/transform-streams/properties.html": [
+ [
+ "/streams/transform-streams/properties.html",
+ {}
+ ]
+ ],
+ "streams/transform-streams/properties.serviceworker.https.html": [
+ [
+ "/streams/transform-streams/properties.serviceworker.https.html",
+ {}
+ ]
+ ],
+ "streams/transform-streams/properties.sharedworker.html": [
+ [
+ "/streams/transform-streams/properties.sharedworker.html",
+ {}
+ ]
+ ],
"streams/transform-streams/reentrant-strategies.dedicatedworker.html": [
[
"/streams/transform-streams/reentrant-strategies.dedicatedworker.html",
@@ -346709,6 +352541,12 @@
{}
]
],
+ "svg/extensibility/foreignObject/properties.svg": [
+ [
+ "/svg/extensibility/foreignObject/properties.svg",
+ {}
+ ]
+ ],
"svg/extensibility/interfaces/foreignObject-graphics.svg": [
[
"/svg/extensibility/interfaces/foreignObject-graphics.svg",
@@ -346753,12 +352591,138 @@
{}
]
],
+ "svg/path/property/d-interpolation-discrete.svg": [
+ [
+ "/svg/path/property/d-interpolation-discrete.svg",
+ {}
+ ]
+ ],
+ "svg/path/property/d-interpolation-relative-absolute.svg": [
+ [
+ "/svg/path/property/d-interpolation-relative-absolute.svg",
+ {}
+ ]
+ ],
+ "svg/path/property/d-interpolation-single.svg": [
+ [
+ "/svg/path/property/d-interpolation-single.svg",
+ {}
+ ]
+ ],
+ "svg/path/property/getComputedStyle.svg": [
+ [
+ "/svg/path/property/getComputedStyle.svg",
+ {}
+ ]
+ ],
"svg/struct/UnknownElement/interface.svg": [
[
"/svg/struct/UnknownElement/interface.svg",
{}
]
],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGClipPathElement.html": [
+ [
+ "/svg/types/scripted/SVGAnimatedEnumeration-SVGClipPathElement.html",
+ {}
+ ]
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGComponentTransferFunctionElement.html": [
+ [
+ "/svg/types/scripted/SVGAnimatedEnumeration-SVGComponentTransferFunctionElement.html",
+ {}
+ ]
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGFEBlendElement.html": [
+ [
+ "/svg/types/scripted/SVGAnimatedEnumeration-SVGFEBlendElement.html",
+ {}
+ ]
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGFEColorMatrixElement.html": [
+ [
+ "/svg/types/scripted/SVGAnimatedEnumeration-SVGFEColorMatrixElement.html",
+ {}
+ ]
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGFECompositeElement.html": [
+ [
+ "/svg/types/scripted/SVGAnimatedEnumeration-SVGFECompositeElement.html",
+ {}
+ ]
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGFEConvolveMatrixElement.html": [
+ [
+ "/svg/types/scripted/SVGAnimatedEnumeration-SVGFEConvolveMatrixElement.html",
+ {}
+ ]
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGFEDisplacementMapElement.html": [
+ [
+ "/svg/types/scripted/SVGAnimatedEnumeration-SVGFEDisplacementMapElement.html",
+ {}
+ ]
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGFEMorphologyElement.html": [
+ [
+ "/svg/types/scripted/SVGAnimatedEnumeration-SVGFEMorphologyElement.html",
+ {}
+ ]
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGFETurbulenceElement.html": [
+ [
+ "/svg/types/scripted/SVGAnimatedEnumeration-SVGFETurbulenceElement.html",
+ {}
+ ]
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGFilterElement.html": [
+ [
+ "/svg/types/scripted/SVGAnimatedEnumeration-SVGFilterElement.html",
+ {}
+ ]
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGGradientElement.html": [
+ [
+ "/svg/types/scripted/SVGAnimatedEnumeration-SVGGradientElement.html",
+ {}
+ ]
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGMarkerElement.html": [
+ [
+ "/svg/types/scripted/SVGAnimatedEnumeration-SVGMarkerElement.html",
+ {}
+ ]
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGMaskElement.html": [
+ [
+ "/svg/types/scripted/SVGAnimatedEnumeration-SVGMaskElement.html",
+ {}
+ ]
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGPatternElement.html": [
+ [
+ "/svg/types/scripted/SVGAnimatedEnumeration-SVGPatternElement.html",
+ {}
+ ]
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGTextContentElement.html": [
+ [
+ "/svg/types/scripted/SVGAnimatedEnumeration-SVGTextContentElement.html",
+ {}
+ ]
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGTextPathElement.html": [
+ [
+ "/svg/types/scripted/SVGAnimatedEnumeration-SVGTextPathElement.html",
+ {}
+ ]
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration.html": [
+ [
+ "/svg/types/scripted/SVGAnimatedEnumeration.html",
+ {}
+ ]
+ ],
"svg/types/scripted/SVGLength-px-with-context.html": [
[
"/svg/types/scripted/SVGLength-px-with-context.html",
@@ -347429,12 +353393,24 @@
{}
]
],
+ "wake-lock/wakelock-cancel-twice.https.html": [
+ [
+ "/wake-lock/wakelock-cancel-twice.https.html",
+ {}
+ ]
+ ],
"wake-lock/wakelock-disabled-by-feature-policy.https.sub.html": [
[
"/wake-lock/wakelock-disabled-by-feature-policy.https.sub.html",
{}
]
],
+ "wake-lock/wakelock-document-hidden.https.html": [
+ [
+ "/wake-lock/wakelock-document-hidden.https.html",
+ {}
+ ]
+ ],
"wake-lock/wakelock-enabled-by-feature-policy-attribute-redirect-on-load.https.sub.html": [
[
"/wake-lock/wakelock-enabled-by-feature-policy-attribute-redirect-on-load.https.sub.html",
@@ -347459,9 +353435,9 @@
{}
]
],
- "wake-lock/wakelock-object-is-independent.https.html": [
+ "wake-lock/wakelock-insecure-context.html": [
[
- "/wake-lock/wakelock-object-is-independent.https.html",
+ "/wake-lock/wakelock-insecure-context.html",
{}
]
],
@@ -347471,12 +353447,30 @@
{}
]
],
+ "wake-lock/wakelock-promise.https.html": [
+ [
+ "/wake-lock/wakelock-promise.https.html",
+ {}
+ ]
+ ],
+ "wake-lock/wakelock-state-is-global.https.html": [
+ [
+ "/wake-lock/wakelock-state-is-global.https.html",
+ {}
+ ]
+ ],
"wake-lock/wakelock-type.https.html": [
[
"/wake-lock/wakelock-type.https.html",
{}
]
],
+ "wake-lock/wakelockrequest-is-independent.https.html": [
+ [
+ "/wake-lock/wakelockrequest-is-independent.https.html",
+ {}
+ ]
+ ],
"wasm/create_multiple_memory.worker.js": [
[
"/wasm/create_multiple_memory.worker.html",
@@ -347525,9 +353519,9 @@
{}
]
],
- "web-animations/animation-model/animation-types/discrete-animation.html": [
+ "web-animations/animation-model/animation-types/discrete.html": [
[
- "/web-animations/animation-model/animation-types/discrete-animation.html",
+ "/web-animations/animation-model/animation-types/discrete.html",
{}
]
],
@@ -347537,6 +353531,12 @@
{}
]
],
+ "web-animations/animation-model/animation-types/visibility.html": [
+ [
+ "/web-animations/animation-model/animation-types/visibility.html",
+ {}
+ ]
+ ],
"web-animations/animation-model/combining-effects/effect-composition.html": [
[
"/web-animations/animation-model/combining-effects/effect-composition.html",
@@ -347549,21 +353549,21 @@
{}
]
],
- "web-animations/animation-model/keyframe-effects/effect-value-overlapping-keyframes.html": [
+ "web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html": [
[
- "/web-animations/animation-model/keyframe-effects/effect-value-overlapping-keyframes.html",
+ "/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html",
{}
]
],
- "web-animations/animation-model/keyframe-effects/effect-value-transformed-distance.html": [
+ "web-animations/animation-model/keyframe-effects/effect-value-overlapping-keyframes.html": [
[
- "/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance.html",
+ "/web-animations/animation-model/keyframe-effects/effect-value-overlapping-keyframes.html",
{}
]
],
- "web-animations/animation-model/keyframe-effects/effect-value-visibility.html": [
+ "web-animations/animation-model/keyframe-effects/effect-value-transformed-distance.html": [
[
- "/web-animations/animation-model/keyframe-effects/effect-value-visibility.html",
+ "/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance.html",
{}
]
],
@@ -347645,15 +353645,15 @@
{}
]
],
- "web-animations/interfaces/Animation/play.html": [
+ "web-animations/interfaces/Animation/pending.html": [
[
- "/web-animations/interfaces/Animation/play.html",
+ "/web-animations/interfaces/Animation/pending.html",
{}
]
],
- "web-animations/interfaces/Animation/playState.html": [
+ "web-animations/interfaces/Animation/play.html": [
[
- "/web-animations/interfaces/Animation/playState.html",
+ "/web-animations/interfaces/Animation/play.html",
{}
]
],
@@ -347711,15 +353711,9 @@
{}
]
],
- "web-animations/interfaces/AnimationEffectTiming/getAnimations.html": [
+ "web-animations/interfaces/AnimationEffectTiming/getComputedTiming.html": [
[
- "/web-animations/interfaces/AnimationEffectTiming/getAnimations.html",
- {}
- ]
- ],
- "web-animations/interfaces/AnimationEffectTiming/getComputedStyle.html": [
- [
- "/web-animations/interfaces/AnimationEffectTiming/getComputedStyle.html",
+ "/web-animations/interfaces/AnimationEffectTiming/getComputedTiming.html",
{}
]
],
@@ -347795,12 +353789,6 @@
{}
]
],
- "web-animations/interfaces/KeyframeEffect/getComputedTiming.html": [
- [
- "/web-animations/interfaces/KeyframeEffect/getComputedTiming.html",
- {}
- ]
- ],
"web-animations/interfaces/KeyframeEffect/idlharness.html": [
[
"/web-animations/interfaces/KeyframeEffect/idlharness.html",
@@ -347831,9 +353819,9 @@
{}
]
],
- "web-animations/interfaces/KeyframeEffect/setTarget.html": [
+ "web-animations/interfaces/KeyframeEffect/target.html": [
[
- "/web-animations/interfaces/KeyframeEffect/setTarget.html",
+ "/web-animations/interfaces/KeyframeEffect/target.html",
{}
]
],
@@ -347891,6 +353879,12 @@
{}
]
],
+ "web-animations/timing-model/animations/play-states.html": [
+ [
+ "/web-animations/timing-model/animations/play-states.html",
+ {}
+ ]
+ ],
"web-animations/timing-model/animations/playing-an-animation.html": [
[
"/web-animations/timing-model/animations/playing-an-animation.html",
@@ -348197,12 +354191,6 @@
{}
]
],
- "webdriver/interface/interface.html": [
- [
- "/webdriver/interface/interface.html",
- {}
- ]
- ],
"webdriver/tests/interface.html": [
[
"/webdriver/tests/interface.html",
@@ -348979,6 +354967,12 @@
{}
]
],
+ "webrtc/RTCPeerConnection-createOffer-offerToReceive.html": [
+ [
+ "/webrtc/RTCPeerConnection-createOffer-offerToReceive.html",
+ {}
+ ]
+ ],
"webrtc/RTCPeerConnection-createOffer.html": [
[
"/webrtc/RTCPeerConnection-createOffer.html",
@@ -349027,12 +355021,6 @@
{}
]
],
- "webrtc/RTCPeerConnection-idl.html": [
- [
- "/webrtc/RTCPeerConnection-idl.html",
- {}
- ]
- ],
"webrtc/RTCPeerConnection-ondatachannel.html": [
[
"/webrtc/RTCPeerConnection-ondatachannel.html",
@@ -349213,9 +355201,9 @@
{}
]
],
- "webrtc/RTCRtpSender-getStats.html": [
+ "webrtc/RTCRtpSender-getStats.https.html": [
[
- "/webrtc/RTCRtpSender-getStats.html",
+ "/webrtc/RTCRtpSender-getStats.https.html",
{}
]
],
@@ -349249,21 +355237,21 @@
{}
]
],
- "webrtc/RTCTrackEvent-constructor.html": [
+ "webrtc/RTCSctpTransport-maxMessageSize.html": [
[
- "/webrtc/RTCTrackEvent-constructor.html",
+ "/webrtc/RTCSctpTransport-maxMessageSize.html",
{}
]
],
- "webrtc/datachannel-emptystring.html": [
+ "webrtc/RTCTrackEvent-constructor.html": [
[
- "/webrtc/datachannel-emptystring.html",
+ "/webrtc/RTCTrackEvent-constructor.html",
{}
]
],
- "webrtc/datachannel-idlharness.html": [
+ "webrtc/datachannel-emptystring.html": [
[
- "/webrtc/datachannel-idlharness.html",
+ "/webrtc/datachannel-emptystring.html",
{}
]
],
@@ -350947,6 +356935,16 @@
{}
]
],
+ "websockets/referrer.any.js": [
+ [
+ "/websockets/referrer.any.html",
+ {}
+ ],
+ [
+ "/websockets/referrer.any.worker.html",
+ {}
+ ]
+ ],
"websockets/security/001.html": [
[
"/websockets/security/001.html",
@@ -351435,6 +357433,12 @@
{}
]
],
+ "webvtt/api/VTTCue/constructor-exceptions.html": [
+ [
+ "/webvtt/api/VTTCue/constructor-exceptions.html",
+ {}
+ ]
+ ],
"webvtt/api/VTTCue/constructor.html": [
[
"/webvtt/api/VTTCue/constructor.html",
@@ -351651,6 +357655,12 @@
{}
]
],
+ "webvtt/parsing/file-parsing/tests/regions-edge-case.html": [
+ [
+ "/webvtt/parsing/file-parsing/tests/regions-edge-case.html",
+ {}
+ ]
+ ],
"webvtt/parsing/file-parsing/tests/regions-id.html": [
[
"/webvtt/parsing/file-parsing/tests/regions-id.html",
@@ -351825,12 +357835,24 @@
{}
]
],
+ "webxr/webxr_availability.http.sub.html": [
+ [
+ "/webxr/webxr_availability.http.sub.html",
+ {}
+ ]
+ ],
"workers/SharedWorker_blobUrl.html": [
[
"/workers/SharedWorker_blobUrl.html",
{}
]
],
+ "workers/SharedWorker_dataUrl.html": [
+ [
+ "/workers/SharedWorker_dataUrl.html",
+ {}
+ ]
+ ],
"workers/WorkerGlobalScope_ErrorEvent_colno.htm": [
[
"/workers/WorkerGlobalScope_ErrorEvent_colno.htm",
@@ -356939,720 +362961,66 @@
{}
]
],
- "css/CSS2/generated-content/after-inheritable-001.xht": [
- [
- "/css/CSS2/generated-content/after-inheritable-001.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/after-inheritable-002.xht": [
- [
- "/css/CSS2/generated-content/after-inheritable-002.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/after-location-001.xht": [
- [
- "/css/CSS2/generated-content/after-location-001.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/before-after-002.xht": [
- [
- "/css/CSS2/generated-content/before-after-002.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/before-inheritable-001.xht": [
- [
- "/css/CSS2/generated-content/before-inheritable-001.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/before-inheritable-002.xht": [
- [
- "/css/CSS2/generated-content/before-inheritable-002.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/before-location-001.xht": [
- [
- "/css/CSS2/generated-content/before-location-001.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/bidi-generated-content-001.xht": [
- [
- "/css/CSS2/generated-content/bidi-generated-content-001.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/bidi-generated-content-002.xht": [
- [
- "/css/CSS2/generated-content/bidi-generated-content-002.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-002.xht": [
- [
- "/css/CSS2/generated-content/content-002.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-003.xht": [
- [
- "/css/CSS2/generated-content/content-003.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-004.xht": [
- [
- "/css/CSS2/generated-content/content-004.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-005.xht": [
- [
- "/css/CSS2/generated-content/content-005.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-006.xht": [
- [
- "/css/CSS2/generated-content/content-006.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-007.xht": [
- [
- "/css/CSS2/generated-content/content-007.xht",
- {}
- ]
- ],
"css/CSS2/generated-content/content-008.xht": [
[
"/css/CSS2/generated-content/content-008.xht",
{}
]
],
- "css/CSS2/generated-content/content-009.xht": [
- [
- "/css/CSS2/generated-content/content-009.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-010.xht": [
- [
- "/css/CSS2/generated-content/content-010.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-011.xht": [
- [
- "/css/CSS2/generated-content/content-011.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-012.xht": [
- [
- "/css/CSS2/generated-content/content-012.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-013.xht": [
- [
- "/css/CSS2/generated-content/content-013.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-014.xht": [
- [
- "/css/CSS2/generated-content/content-014.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-015.xht": [
- [
- "/css/CSS2/generated-content/content-015.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-016.xht": [
- [
- "/css/CSS2/generated-content/content-016.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-017.xht": [
- [
- "/css/CSS2/generated-content/content-017.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-018.xht": [
- [
- "/css/CSS2/generated-content/content-018.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-019.xht": [
- [
- "/css/CSS2/generated-content/content-019.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-020.xht": [
- [
- "/css/CSS2/generated-content/content-020.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-021.xht": [
- [
- "/css/CSS2/generated-content/content-021.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-022.xht": [
- [
- "/css/CSS2/generated-content/content-022.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-023.xht": [
- [
- "/css/CSS2/generated-content/content-023.xht",
- {}
- ]
- ],
"css/CSS2/generated-content/content-024.xht": [
[
"/css/CSS2/generated-content/content-024.xht",
{}
]
],
- "css/CSS2/generated-content/content-025.xht": [
- [
- "/css/CSS2/generated-content/content-025.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-026.xht": [
- [
- "/css/CSS2/generated-content/content-026.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-027.xht": [
- [
- "/css/CSS2/generated-content/content-027.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-028.xht": [
- [
- "/css/CSS2/generated-content/content-028.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-029.xht": [
- [
- "/css/CSS2/generated-content/content-029.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-030.xht": [
- [
- "/css/CSS2/generated-content/content-030.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-031.xht": [
- [
- "/css/CSS2/generated-content/content-031.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-032.xht": [
- [
- "/css/CSS2/generated-content/content-032.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-033.xht": [
- [
- "/css/CSS2/generated-content/content-033.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-034.xht": [
- [
- "/css/CSS2/generated-content/content-034.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-035.xht": [
- [
- "/css/CSS2/generated-content/content-035.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-037.xht": [
- [
- "/css/CSS2/generated-content/content-037.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-038.xht": [
- [
- "/css/CSS2/generated-content/content-038.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-039.xht": [
- [
- "/css/CSS2/generated-content/content-039.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-040.xht": [
- [
- "/css/CSS2/generated-content/content-040.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-041.xht": [
- [
- "/css/CSS2/generated-content/content-041.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-042.xht": [
- [
- "/css/CSS2/generated-content/content-042.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-043.xht": [
- [
- "/css/CSS2/generated-content/content-043.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-046.xht": [
- [
- "/css/CSS2/generated-content/content-046.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-047.xht": [
- [
- "/css/CSS2/generated-content/content-047.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-048.xht": [
- [
- "/css/CSS2/generated-content/content-048.xht",
- {}
- ]
- ],
"css/CSS2/generated-content/content-049.xht": [
[
"/css/CSS2/generated-content/content-049.xht",
{}
]
],
- "css/CSS2/generated-content/content-050.xht": [
- [
- "/css/CSS2/generated-content/content-050.xht",
- {}
- ]
- ],
"css/CSS2/generated-content/content-051.xht": [
[
"/css/CSS2/generated-content/content-051.xht",
{}
]
],
- "css/CSS2/generated-content/content-052.xht": [
- [
- "/css/CSS2/generated-content/content-052.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-053.xht": [
- [
- "/css/CSS2/generated-content/content-053.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-054.xht": [
- [
- "/css/CSS2/generated-content/content-054.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-056.xht": [
- [
- "/css/CSS2/generated-content/content-056.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-057.xht": [
- [
- "/css/CSS2/generated-content/content-057.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-063.xht": [
- [
- "/css/CSS2/generated-content/content-063.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-065.xht": [
- [
- "/css/CSS2/generated-content/content-065.xht",
- {}
- ]
- ],
"css/CSS2/generated-content/content-066.xht": [
[
"/css/CSS2/generated-content/content-066.xht",
{}
]
],
- "css/CSS2/generated-content/content-067.xht": [
- [
- "/css/CSS2/generated-content/content-067.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-068.xht": [
- [
- "/css/CSS2/generated-content/content-068.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-070.xht": [
- [
- "/css/CSS2/generated-content/content-070.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-072.xht": [
- [
- "/css/CSS2/generated-content/content-072.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-073.xht": [
- [
- "/css/CSS2/generated-content/content-073.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-075.xht": [
- [
- "/css/CSS2/generated-content/content-075.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-076.xht": [
- [
- "/css/CSS2/generated-content/content-076.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-077.xht": [
- [
- "/css/CSS2/generated-content/content-077.xht",
- {}
- ]
- ],
"css/CSS2/generated-content/content-078.xht": [
[
"/css/CSS2/generated-content/content-078.xht",
{}
]
],
- "css/CSS2/generated-content/content-080.xht": [
- [
- "/css/CSS2/generated-content/content-080.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-081.xht": [
- [
- "/css/CSS2/generated-content/content-081.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-082.xht": [
- [
- "/css/CSS2/generated-content/content-082.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-083.xht": [
- [
- "/css/CSS2/generated-content/content-083.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-085.xht": [
- [
- "/css/CSS2/generated-content/content-085.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-086.xht": [
- [
- "/css/CSS2/generated-content/content-086.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-089.xht": [
- [
- "/css/CSS2/generated-content/content-089.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-090.xht": [
- [
- "/css/CSS2/generated-content/content-090.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-091.xht": [
- [
- "/css/CSS2/generated-content/content-091.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-096.xht": [
- [
- "/css/CSS2/generated-content/content-096.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-097.xht": [
- [
- "/css/CSS2/generated-content/content-097.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-099.xht": [
- [
- "/css/CSS2/generated-content/content-099.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-100.xht": [
- [
- "/css/CSS2/generated-content/content-100.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-103.xht": [
- [
- "/css/CSS2/generated-content/content-103.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-105.xht": [
- [
- "/css/CSS2/generated-content/content-105.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-109.xht": [
- [
- "/css/CSS2/generated-content/content-109.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-113.xht": [
- [
- "/css/CSS2/generated-content/content-113.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-122.xht": [
- [
- "/css/CSS2/generated-content/content-122.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-123.xht": [
- [
- "/css/CSS2/generated-content/content-123.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-126.xht": [
- [
- "/css/CSS2/generated-content/content-126.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-127.xht": [
- [
- "/css/CSS2/generated-content/content-127.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-129.xht": [
- [
- "/css/CSS2/generated-content/content-129.xht",
- {}
- ]
- ],
"css/CSS2/generated-content/content-130.xht": [
[
"/css/CSS2/generated-content/content-130.xht",
{}
]
],
- "css/CSS2/generated-content/content-131.xht": [
- [
- "/css/CSS2/generated-content/content-131.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-132.xht": [
- [
- "/css/CSS2/generated-content/content-132.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-135.xht": [
- [
- "/css/CSS2/generated-content/content-135.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-136.xht": [
- [
- "/css/CSS2/generated-content/content-136.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-138.xht": [
- [
- "/css/CSS2/generated-content/content-138.xht",
- {}
- ]
- ],
"css/CSS2/generated-content/content-140.xht": [
[
"/css/CSS2/generated-content/content-140.xht",
{}
]
],
- "css/CSS2/generated-content/content-141.xht": [
- [
- "/css/CSS2/generated-content/content-141.xht",
- {}
- ]
- ],
"css/CSS2/generated-content/content-142.xht": [
[
"/css/CSS2/generated-content/content-142.xht",
{}
]
],
- "css/CSS2/generated-content/content-143.xht": [
- [
- "/css/CSS2/generated-content/content-143.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-144.xht": [
- [
- "/css/CSS2/generated-content/content-144.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-145.xht": [
- [
- "/css/CSS2/generated-content/content-145.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-146.xht": [
- [
- "/css/CSS2/generated-content/content-146.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-147.xht": [
- [
- "/css/CSS2/generated-content/content-147.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-149.xht": [
- [
- "/css/CSS2/generated-content/content-149.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-150.xht": [
- [
- "/css/CSS2/generated-content/content-150.xht",
- {}
- ]
- ],
"css/CSS2/generated-content/content-151.xht": [
[
"/css/CSS2/generated-content/content-151.xht",
{}
]
],
- "css/CSS2/generated-content/content-152.xht": [
- [
- "/css/CSS2/generated-content/content-152.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-153.xht": [
- [
- "/css/CSS2/generated-content/content-153.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-155.xht": [
- [
- "/css/CSS2/generated-content/content-155.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-156.xht": [
- [
- "/css/CSS2/generated-content/content-156.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-157.xht": [
- [
- "/css/CSS2/generated-content/content-157.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-158.xht": [
- [
- "/css/CSS2/generated-content/content-158.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-159.xht": [
- [
- "/css/CSS2/generated-content/content-159.xht",
- {}
- ]
- ],
"css/CSS2/generated-content/content-160.xht": [
[
"/css/CSS2/generated-content/content-160.xht",
@@ -357665,36 +363033,12 @@
{}
]
],
- "css/CSS2/generated-content/content-attr-001.xht": [
- [
- "/css/CSS2/generated-content/content-attr-001.xht",
- {}
- ]
- ],
"css/CSS2/generated-content/content-attr-002.xht": [
[
"/css/CSS2/generated-content/content-attr-002.xht",
{}
]
],
- "css/CSS2/generated-content/content-attr-case-001.html": [
- [
- "/css/CSS2/generated-content/content-attr-case-001.html",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-attr-case-002.xht": [
- [
- "/css/CSS2/generated-content/content-attr-case-002.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-auto-reset-001.xht": [
- [
- "/css/CSS2/generated-content/content-auto-reset-001.xht",
- {}
- ]
- ],
"css/CSS2/generated-content/content-counters-000.xht": [
[
"/css/CSS2/generated-content/content-counters-000.xht",
@@ -357815,42 +363159,12 @@
{}
]
],
- "css/CSS2/generated-content/content-newline-001.xht": [
- [
- "/css/CSS2/generated-content/content-newline-001.xht",
- {}
- ]
- ],
"css/CSS2/generated-content/content-uri-001.xht": [
[
"/css/CSS2/generated-content/content-uri-001.xht",
{}
]
],
- "css/CSS2/generated-content/content-white-space-001.xht": [
- [
- "/css/CSS2/generated-content/content-white-space-001.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-white-space-002.xht": [
- [
- "/css/CSS2/generated-content/content-white-space-002.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-white-space-003.xht": [
- [
- "/css/CSS2/generated-content/content-white-space-003.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/content-white-space-004.xht": [
- [
- "/css/CSS2/generated-content/content-white-space-004.xht",
- {}
- ]
- ],
"css/CSS2/generated-content/counter-increment-000.xht": [
[
"/css/CSS2/generated-content/counter-increment-000.xht",
@@ -357887,54 +363201,12 @@
{}
]
],
- "css/CSS2/generated-content/counters-hidden-000.xht": [
- [
- "/css/CSS2/generated-content/counters-hidden-000.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/counters-hidden-001.xht": [
- [
- "/css/CSS2/generated-content/counters-hidden-001.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/counters-hidden-002.xht": [
- [
- "/css/CSS2/generated-content/counters-hidden-002.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/counters-multi-000.xht": [
- [
- "/css/CSS2/generated-content/counters-multi-000.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/counters-multi-001.xht": [
- [
- "/css/CSS2/generated-content/counters-multi-001.xht",
- {}
- ]
- ],
- "css/CSS2/generated-content/counters-order-000.xht": [
- [
- "/css/CSS2/generated-content/counters-order-000.xht",
- {}
- ]
- ],
"css/CSS2/generated-content/counters-order-001.xht": [
[
"/css/CSS2/generated-content/counters-order-001.xht",
{}
]
],
- "css/CSS2/generated-content/counters-root-000.xht": [
- [
- "/css/CSS2/generated-content/counters-root-000.xht",
- {}
- ]
- ],
"css/CSS2/generated-content/counters-scope-000.xht": [
[
"/css/CSS2/generated-content/counters-scope-000.xht",
@@ -371465,699 +376737,597 @@
{}
]
],
- "css/css-block/after-content-display-004.xht": [
- [
- "/css/css-block/after-content-display-004.xht",
- {}
- ]
- ],
- "css/css-block/anonymous-box-generation-002.xht": [
- [
- "/css/css-block/anonymous-box-generation-002.xht",
- {}
- ]
- ],
- "css/css-block/background-applies-to-011.xht": [
- [
- "/css/css-block/background-applies-to-011.xht",
- {}
- ]
- ],
- "css/css-block/background-attachment-applies-to-011.xht": [
- [
- "/css/css-block/background-attachment-applies-to-011.xht",
- {}
- ]
- ],
- "css/css-block/background-color-applies-to-011.xht": [
- [
- "/css/css-block/background-color-applies-to-011.xht",
- {}
- ]
- ],
- "css/css-block/background-image-applies-to-011.xht": [
- [
- "/css/css-block/background-image-applies-to-011.xht",
- {}
- ]
- ],
- "css/css-block/background-position-applies-to-011.xht": [
- [
- "/css/css-block/background-position-applies-to-011.xht",
- {}
- ]
- ],
- "css/css-block/background-repeat-applies-to-011.xht": [
- [
- "/css/css-block/background-repeat-applies-to-011.xht",
- {}
- ]
- ],
- "css/css-block/before-content-display-004.xht": [
- [
- "/css/css-block/before-content-display-004.xht",
- {}
- ]
- ],
- "css/css-block/border-applies-to-011.xht": [
+ "css/css-break/break-before-always-001.xht": [
[
- "/css/css-block/border-applies-to-011.xht",
+ "/css/css-break/break-before-always-001.xht",
{}
]
],
- "css/css-block/border-bottom-applies-to-011.xht": [
+ "css/css-color/t32-opacity-basic-0.6-a.xht": [
[
- "/css/css-block/border-bottom-applies-to-011.xht",
+ "/css/css-color/t32-opacity-basic-0.6-a.xht",
{}
]
],
- "css/css-block/border-bottom-color-applies-to-011.xht": [
+ "css/css-color/t32-opacity-zorder-c.xht": [
[
- "/css/css-block/border-bottom-color-applies-to-011.xht",
+ "/css/css-color/t32-opacity-zorder-c.xht",
{}
]
],
- "css/css-block/border-bottom-style-applies-to-011.xht": [
+ "css/css-color/t421-rgb-hex3-expand-b.xht": [
[
- "/css/css-block/border-bottom-style-applies-to-011.xht",
+ "/css/css-color/t421-rgb-hex3-expand-b.xht",
{}
]
],
- "css/css-block/border-bottom-width-applies-to-011.xht": [
+ "css/css-color/t422-rgba-a0.6-a.xht": [
[
- "/css/css-block/border-bottom-width-applies-to-011.xht",
+ "/css/css-color/t422-rgba-a0.6-a.xht",
{}
]
],
- "css/css-block/border-collapse-applies-to-004.xht": [
+ "css/css-color/t425-hsla-basic-a.xht": [
[
- "/css/css-block/border-collapse-applies-to-004.xht",
+ "/css/css-color/t425-hsla-basic-a.xht",
{}
]
],
- "css/css-block/border-color-applies-to-011.xht": [
+ "css/css-color/t451-system-colors-a.xht": [
[
- "/css/css-block/border-color-applies-to-011.xht",
+ "/css/css-color/t451-system-colors-a.xht",
{}
]
],
- "css/css-block/border-left-applies-to-011.xht": [
+ "css/css-display/run-in/after-content-display-004.xht": [
[
- "/css/css-block/border-left-applies-to-011.xht",
+ "/css/css-display/run-in/after-content-display-004.xht",
{}
]
],
- "css/css-block/border-left-color-applies-to-011.xht": [
+ "css/css-display/run-in/anonymous-box-generation-002.xht": [
[
- "/css/css-block/border-left-color-applies-to-011.xht",
+ "/css/css-display/run-in/anonymous-box-generation-002.xht",
{}
]
],
- "css/css-block/border-left-style-applies-to-011.xht": [
+ "css/css-display/run-in/background-applies-to-011.xht": [
[
- "/css/css-block/border-left-style-applies-to-011.xht",
+ "/css/css-display/run-in/background-applies-to-011.xht",
{}
]
],
- "css/css-block/border-left-width-applies-to-011.xht": [
+ "css/css-display/run-in/background-attachment-applies-to-011.xht": [
[
- "/css/css-block/border-left-width-applies-to-011.xht",
+ "/css/css-display/run-in/background-attachment-applies-to-011.xht",
{}
]
],
- "css/css-block/border-right-applies-to-011.xht": [
+ "css/css-display/run-in/background-color-applies-to-011.xht": [
[
- "/css/css-block/border-right-applies-to-011.xht",
+ "/css/css-display/run-in/background-color-applies-to-011.xht",
{}
]
],
- "css/css-block/border-right-color-applies-to-011.xht": [
+ "css/css-display/run-in/background-image-applies-to-011.xht": [
[
- "/css/css-block/border-right-color-applies-to-011.xht",
+ "/css/css-display/run-in/background-image-applies-to-011.xht",
{}
]
],
- "css/css-block/border-right-style-applies-to-011.xht": [
+ "css/css-display/run-in/background-position-applies-to-011.xht": [
[
- "/css/css-block/border-right-style-applies-to-011.xht",
+ "/css/css-display/run-in/background-position-applies-to-011.xht",
{}
]
],
- "css/css-block/border-right-width-applies-to-011.xht": [
+ "css/css-display/run-in/background-repeat-applies-to-011.xht": [
[
- "/css/css-block/border-right-width-applies-to-011.xht",
+ "/css/css-display/run-in/background-repeat-applies-to-011.xht",
{}
]
],
- "css/css-block/border-spacing-applies-to-004.xht": [
+ "css/css-display/run-in/before-content-display-004.xht": [
[
- "/css/css-block/border-spacing-applies-to-004.xht",
+ "/css/css-display/run-in/before-content-display-004.xht",
{}
]
],
- "css/css-block/border-style-applies-to-011.xht": [
+ "css/css-display/run-in/border-applies-to-011.xht": [
[
- "/css/css-block/border-style-applies-to-011.xht",
+ "/css/css-display/run-in/border-applies-to-011.xht",
{}
]
],
- "css/css-block/border-top-applies-to-011.xht": [
+ "css/css-display/run-in/border-bottom-applies-to-011.xht": [
[
- "/css/css-block/border-top-applies-to-011.xht",
+ "/css/css-display/run-in/border-bottom-applies-to-011.xht",
{}
]
],
- "css/css-block/border-top-color-applies-to-011.xht": [
+ "css/css-display/run-in/border-bottom-color-applies-to-011.xht": [
[
- "/css/css-block/border-top-color-applies-to-011.xht",
+ "/css/css-display/run-in/border-bottom-color-applies-to-011.xht",
{}
]
],
- "css/css-block/border-top-style-applies-to-011.xht": [
+ "css/css-display/run-in/border-bottom-style-applies-to-011.xht": [
[
- "/css/css-block/border-top-style-applies-to-011.xht",
+ "/css/css-display/run-in/border-bottom-style-applies-to-011.xht",
{}
]
],
- "css/css-block/border-top-width-applies-to-011.xht": [
+ "css/css-display/run-in/border-bottom-width-applies-to-011.xht": [
[
- "/css/css-block/border-top-width-applies-to-011.xht",
+ "/css/css-display/run-in/border-bottom-width-applies-to-011.xht",
{}
]
],
- "css/css-block/border-width-applies-to-011.xht": [
+ "css/css-display/run-in/border-collapse-applies-to-004.xht": [
[
- "/css/css-block/border-width-applies-to-011.xht",
+ "/css/css-display/run-in/border-collapse-applies-to-004.xht",
{}
]
],
- "css/css-block/bottom-applies-to-011.xht": [
+ "css/css-display/run-in/border-color-applies-to-011.xht": [
[
- "/css/css-block/bottom-applies-to-011.xht",
+ "/css/css-display/run-in/border-color-applies-to-011.xht",
{}
]
],
- "css/css-block/caption-side-applies-to-004.xht": [
+ "css/css-display/run-in/border-left-applies-to-011.xht": [
[
- "/css/css-block/caption-side-applies-to-004.xht",
+ "/css/css-display/run-in/border-left-applies-to-011.xht",
{}
]
],
- "css/css-block/clear-applies-to-011.xht": [
+ "css/css-display/run-in/border-left-color-applies-to-011.xht": [
[
- "/css/css-block/clear-applies-to-011.xht",
+ "/css/css-display/run-in/border-left-color-applies-to-011.xht",
{}
]
],
- "css/css-block/clear-runin-001.xht": [
+ "css/css-display/run-in/border-left-style-applies-to-011.xht": [
[
- "/css/css-block/clear-runin-001.xht",
+ "/css/css-display/run-in/border-left-style-applies-to-011.xht",
{}
]
],
- "css/css-block/color-applies-to-011.xht": [
+ "css/css-display/run-in/border-left-width-applies-to-011.xht": [
[
- "/css/css-block/color-applies-to-011.xht",
+ "/css/css-display/run-in/border-left-width-applies-to-011.xht",
{}
]
],
- "css/css-block/direction-applies-to-011.xht": [
+ "css/css-display/run-in/border-right-applies-to-011.xht": [
[
- "/css/css-block/direction-applies-to-011.xht",
+ "/css/css-display/run-in/border-right-applies-to-011.xht",
{}
]
],
- "css/css-block/display-004.xht": [
+ "css/css-display/run-in/border-right-color-applies-to-011.xht": [
[
- "/css/css-block/display-004.xht",
+ "/css/css-display/run-in/border-right-color-applies-to-011.xht",
{}
]
],
- "css/css-block/empty-cells-applies-to-004.xht": [
+ "css/css-display/run-in/border-right-style-applies-to-011.xht": [
[
- "/css/css-block/empty-cells-applies-to-004.xht",
+ "/css/css-display/run-in/border-right-style-applies-to-011.xht",
{}
]
],
- "css/css-block/first-line-pseudo-009.xht": [
+ "css/css-display/run-in/border-right-width-applies-to-011.xht": [
[
- "/css/css-block/first-line-pseudo-009.xht",
+ "/css/css-display/run-in/border-right-width-applies-to-011.xht",
{}
]
],
- "css/css-block/float-applies-to-011.xht": [
+ "css/css-display/run-in/border-spacing-applies-to-004.xht": [
[
- "/css/css-block/float-applies-to-011.xht",
+ "/css/css-display/run-in/border-spacing-applies-to-004.xht",
{}
]
],
- "css/css-block/font-applies-to-004.xht": [
+ "css/css-display/run-in/border-style-applies-to-011.xht": [
[
- "/css/css-block/font-applies-to-004.xht",
+ "/css/css-display/run-in/border-style-applies-to-011.xht",
{}
]
],
- "css/css-block/font-family-applies-to-004.xht": [
+ "css/css-display/run-in/border-top-applies-to-011.xht": [
[
- "/css/css-block/font-family-applies-to-004.xht",
+ "/css/css-display/run-in/border-top-applies-to-011.xht",
{}
]
],
- "css/css-block/font-size-applies-to-004.xht": [
+ "css/css-display/run-in/border-top-color-applies-to-011.xht": [
[
- "/css/css-block/font-size-applies-to-004.xht",
+ "/css/css-display/run-in/border-top-color-applies-to-011.xht",
{}
]
],
- "css/css-block/left-applies-to-011.xht": [
+ "css/css-display/run-in/border-top-style-applies-to-011.xht": [
[
- "/css/css-block/left-applies-to-011.xht",
+ "/css/css-display/run-in/border-top-style-applies-to-011.xht",
{}
]
],
- "css/css-block/line-height-applies-to-011.xht": [
+ "css/css-display/run-in/border-top-width-applies-to-011.xht": [
[
- "/css/css-block/line-height-applies-to-011.xht",
+ "/css/css-display/run-in/border-top-width-applies-to-011.xht",
{}
]
],
- "css/css-block/list-style-image-applies-to-011.xht": [
+ "css/css-display/run-in/border-width-applies-to-011.xht": [
[
- "/css/css-block/list-style-image-applies-to-011.xht",
+ "/css/css-display/run-in/border-width-applies-to-011.xht",
{}
]
],
- "css/css-block/list-style-position-applies-to-011.xht": [
+ "css/css-display/run-in/bottom-applies-to-011.xht": [
[
- "/css/css-block/list-style-position-applies-to-011.xht",
+ "/css/css-display/run-in/bottom-applies-to-011.xht",
{}
]
],
- "css/css-block/margin-applies-to-011.xht": [
+ "css/css-display/run-in/caption-side-applies-to-004.xht": [
[
- "/css/css-block/margin-applies-to-011.xht",
+ "/css/css-display/run-in/caption-side-applies-to-004.xht",
{}
]
],
- "css/css-block/margin-bottom-applies-to-011.xht": [
+ "css/css-display/run-in/clear-applies-to-011.xht": [
[
- "/css/css-block/margin-bottom-applies-to-011.xht",
+ "/css/css-display/run-in/clear-applies-to-011.xht",
{}
]
],
- "css/css-block/margin-left-applies-to-011.xht": [
+ "css/css-display/run-in/clear-runin-001.xht": [
[
- "/css/css-block/margin-left-applies-to-011.xht",
+ "/css/css-display/run-in/clear-runin-001.xht",
{}
]
],
- "css/css-block/margin-right-applies-to-011.xht": [
+ "css/css-display/run-in/color-applies-to-011.xht": [
[
- "/css/css-block/margin-right-applies-to-011.xht",
+ "/css/css-display/run-in/color-applies-to-011.xht",
{}
]
],
- "css/css-block/margin-top-applies-to-011.xht": [
+ "css/css-display/run-in/direction-applies-to-011.xht": [
[
- "/css/css-block/margin-top-applies-to-011.xht",
+ "/css/css-display/run-in/direction-applies-to-011.xht",
{}
]
],
- "css/css-block/outline-applies-to-011.xht": [
+ "css/css-display/run-in/display-004.xht": [
[
- "/css/css-block/outline-applies-to-011.xht",
+ "/css/css-display/run-in/display-004.xht",
{}
]
],
- "css/css-block/outline-color-applies-to-011.xht": [
+ "css/css-display/run-in/empty-cells-applies-to-004.xht": [
[
- "/css/css-block/outline-color-applies-to-011.xht",
+ "/css/css-display/run-in/empty-cells-applies-to-004.xht",
{}
]
],
- "css/css-block/outline-style-applies-to-011.xht": [
+ "css/css-display/run-in/first-line-pseudo-009.xht": [
[
- "/css/css-block/outline-style-applies-to-011.xht",
+ "/css/css-display/run-in/first-line-pseudo-009.xht",
{}
]
],
- "css/css-block/outline-width-applies-to-011.xht": [
+ "css/css-display/run-in/float-applies-to-011.xht": [
[
- "/css/css-block/outline-width-applies-to-011.xht",
+ "/css/css-display/run-in/float-applies-to-011.xht",
{}
]
],
- "css/css-block/overflow-applies-to-011.xht": [
+ "css/css-display/run-in/font-applies-to-004.xht": [
[
- "/css/css-block/overflow-applies-to-011.xht",
+ "/css/css-display/run-in/font-applies-to-004.xht",
{}
]
],
- "css/css-block/padding-applies-to-011.xht": [
+ "css/css-display/run-in/font-family-applies-to-004.xht": [
[
- "/css/css-block/padding-applies-to-011.xht",
+ "/css/css-display/run-in/font-family-applies-to-004.xht",
{}
]
],
- "css/css-block/padding-bottom-applies-to-011.xht": [
+ "css/css-display/run-in/font-size-applies-to-004.xht": [
[
- "/css/css-block/padding-bottom-applies-to-011.xht",
+ "/css/css-display/run-in/font-size-applies-to-004.xht",
{}
]
],
- "css/css-block/padding-left-applies-to-011.xht": [
+ "css/css-display/run-in/left-applies-to-011.xht": [
[
- "/css/css-block/padding-left-applies-to-011.xht",
+ "/css/css-display/run-in/left-applies-to-011.xht",
{}
]
],
- "css/css-block/padding-right-applies-to-011.xht": [
+ "css/css-display/run-in/line-height-applies-to-011.xht": [
[
- "/css/css-block/padding-right-applies-to-011.xht",
+ "/css/css-display/run-in/line-height-applies-to-011.xht",
{}
]
],
- "css/css-block/padding-top-applies-to-011.xht": [
+ "css/css-display/run-in/list-style-image-applies-to-011.xht": [
[
- "/css/css-block/padding-top-applies-to-011.xht",
+ "/css/css-display/run-in/list-style-image-applies-to-011.xht",
{}
]
],
- "css/css-block/position-applies-to-011.xht": [
+ "css/css-display/run-in/list-style-position-applies-to-011.xht": [
[
- "/css/css-block/position-applies-to-011.xht",
+ "/css/css-display/run-in/list-style-position-applies-to-011.xht",
{}
]
],
- "css/css-block/right-applies-to-011.xht": [
+ "css/css-display/run-in/margin-applies-to-011.xht": [
[
- "/css/css-block/right-applies-to-011.xht",
+ "/css/css-display/run-in/margin-applies-to-011.xht",
{}
]
],
- "css/css-block/run-in-001.xht": [
+ "css/css-display/run-in/margin-bottom-applies-to-011.xht": [
[
- "/css/css-block/run-in-001.xht",
+ "/css/css-display/run-in/margin-bottom-applies-to-011.xht",
{}
]
],
- "css/css-block/run-in-002.xht": [
+ "css/css-display/run-in/margin-left-applies-to-011.xht": [
[
- "/css/css-block/run-in-002.xht",
+ "/css/css-display/run-in/margin-left-applies-to-011.xht",
{}
]
],
- "css/css-block/run-in-003.xht": [
+ "css/css-display/run-in/margin-right-applies-to-011.xht": [
[
- "/css/css-block/run-in-003.xht",
+ "/css/css-display/run-in/margin-right-applies-to-011.xht",
{}
]
],
- "css/css-block/run-in-004.xht": [
+ "css/css-display/run-in/margin-top-applies-to-011.xht": [
[
- "/css/css-block/run-in-004.xht",
+ "/css/css-display/run-in/margin-top-applies-to-011.xht",
{}
]
],
- "css/css-block/run-in-005.xht": [
+ "css/css-display/run-in/outline-applies-to-011.xht": [
[
- "/css/css-block/run-in-005.xht",
+ "/css/css-display/run-in/outline-applies-to-011.xht",
{}
]
],
- "css/css-block/run-in-006.xht": [
+ "css/css-display/run-in/outline-color-applies-to-011.xht": [
[
- "/css/css-block/run-in-006.xht",
+ "/css/css-display/run-in/outline-color-applies-to-011.xht",
{}
]
],
- "css/css-block/run-in-007.xht": [
+ "css/css-display/run-in/outline-style-applies-to-011.xht": [
[
- "/css/css-block/run-in-007.xht",
+ "/css/css-display/run-in/outline-style-applies-to-011.xht",
{}
]
],
- "css/css-block/run-in-008.xht": [
+ "css/css-display/run-in/outline-width-applies-to-011.xht": [
[
- "/css/css-block/run-in-008.xht",
+ "/css/css-display/run-in/outline-width-applies-to-011.xht",
{}
]
],
- "css/css-block/run-in-009.xht": [
+ "css/css-display/run-in/overflow-applies-to-011.xht": [
[
- "/css/css-block/run-in-009.xht",
+ "/css/css-display/run-in/overflow-applies-to-011.xht",
{}
]
],
- "css/css-block/run-in-010.xht": [
+ "css/css-display/run-in/padding-applies-to-011.xht": [
[
- "/css/css-block/run-in-010.xht",
+ "/css/css-display/run-in/padding-applies-to-011.xht",
{}
]
],
- "css/css-block/run-in-011.xht": [
+ "css/css-display/run-in/padding-bottom-applies-to-011.xht": [
[
- "/css/css-block/run-in-011.xht",
+ "/css/css-display/run-in/padding-bottom-applies-to-011.xht",
{}
]
],
- "css/css-block/run-in-012.xht": [
+ "css/css-display/run-in/padding-left-applies-to-011.xht": [
[
- "/css/css-block/run-in-012.xht",
+ "/css/css-display/run-in/padding-left-applies-to-011.xht",
{}
]
],
- "css/css-block/run-in-013.xht": [
+ "css/css-display/run-in/padding-right-applies-to-011.xht": [
[
- "/css/css-block/run-in-013.xht",
+ "/css/css-display/run-in/padding-right-applies-to-011.xht",
{}
]
],
- "css/css-block/run-in-inheritance-001.xht": [
+ "css/css-display/run-in/padding-top-applies-to-011.xht": [
[
- "/css/css-block/run-in-inheritance-001.xht",
+ "/css/css-display/run-in/padding-top-applies-to-011.xht",
{}
]
],
- "css/css-block/run-in-linebox-001.xht": [
+ "css/css-display/run-in/position-applies-to-011.xht": [
[
- "/css/css-block/run-in-linebox-001.xht",
+ "/css/css-display/run-in/position-applies-to-011.xht",
{}
]
],
- "css/css-block/run-in-linebox-002.xht": [
+ "css/css-display/run-in/right-applies-to-011.xht": [
[
- "/css/css-block/run-in-linebox-002.xht",
+ "/css/css-display/run-in/right-applies-to-011.xht",
{}
]
],
- "css/css-block/table-anonymous-block-001.xht": [
+ "css/css-display/run-in/run-in-001.xht": [
[
- "/css/css-block/table-anonymous-block-001.xht",
+ "/css/css-display/run-in/run-in-001.xht",
{}
]
],
- "css/css-block/table-layout-applies-to-004.xht": [
+ "css/css-display/run-in/run-in-002.xht": [
[
- "/css/css-block/table-layout-applies-to-004.xht",
+ "/css/css-display/run-in/run-in-002.xht",
{}
]
],
- "css/css-block/text-align-applies-to-004.xht": [
+ "css/css-display/run-in/run-in-003.xht": [
[
- "/css/css-block/text-align-applies-to-004.xht",
+ "/css/css-display/run-in/run-in-003.xht",
{}
]
],
- "css/css-block/text-indent-applies-to-004.xht": [
+ "css/css-display/run-in/run-in-004.xht": [
[
- "/css/css-block/text-indent-applies-to-004.xht",
+ "/css/css-display/run-in/run-in-004.xht",
{}
]
],
- "css/css-block/top-applies-to-011.xht": [
+ "css/css-display/run-in/run-in-005.xht": [
[
- "/css/css-block/top-applies-to-011.xht",
+ "/css/css-display/run-in/run-in-005.xht",
{}
]
],
- "css/css-block/unicode-bidi-applies-to-011.xht": [
+ "css/css-display/run-in/run-in-006.xht": [
[
- "/css/css-block/unicode-bidi-applies-to-011.xht",
+ "/css/css-display/run-in/run-in-006.xht",
{}
]
],
- "css/css-block/vertical-align-applies-to-011.xht": [
+ "css/css-display/run-in/run-in-007.xht": [
[
- "/css/css-block/vertical-align-applies-to-011.xht",
+ "/css/css-display/run-in/run-in-007.xht",
{}
]
],
- "css/css-block/visibility-applies-to-011.xht": [
+ "css/css-display/run-in/run-in-008.xht": [
[
- "/css/css-block/visibility-applies-to-011.xht",
+ "/css/css-display/run-in/run-in-008.xht",
{}
]
],
- "css/css-block/white-space-applies-to-004.xht": [
+ "css/css-display/run-in/run-in-009.xht": [
[
- "/css/css-block/white-space-applies-to-004.xht",
+ "/css/css-display/run-in/run-in-009.xht",
{}
]
],
- "css/css-block/word-spacing-applies-to-004.xht": [
+ "css/css-display/run-in/run-in-010.xht": [
[
- "/css/css-block/word-spacing-applies-to-004.xht",
+ "/css/css-display/run-in/run-in-010.xht",
{}
]
],
- "css/css-block/z-index-applies-to-011.xht": [
+ "css/css-display/run-in/run-in-011.xht": [
[
- "/css/css-block/z-index-applies-to-011.xht",
+ "/css/css-display/run-in/run-in-011.xht",
{}
]
],
- "css/css-break/break-before-always-001.xht": [
+ "css/css-display/run-in/run-in-012.xht": [
[
- "/css/css-break/break-before-always-001.xht",
+ "/css/css-display/run-in/run-in-012.xht",
{}
]
],
- "css/css-color/hex-003.html": [
+ "css/css-display/run-in/run-in-013.xht": [
[
- "/css/css-color/hex-003.html",
+ "/css/css-display/run-in/run-in-013.xht",
{}
]
],
- "css/css-color/hex-004.html": [
+ "css/css-display/run-in/run-in-inheritance-001.xht": [
[
- "/css/css-color/hex-004.html",
+ "/css/css-display/run-in/run-in-inheritance-001.xht",
{}
]
],
- "css/css-color/t32-opacity-basic-0.0-a.xht": [
+ "css/css-display/run-in/run-in-linebox-001.xht": [
[
- "/css/css-color/t32-opacity-basic-0.0-a.xht",
+ "/css/css-display/run-in/run-in-linebox-001.xht",
{}
]
],
- "css/css-color/t32-opacity-basic-0.6-a.xht": [
+ "css/css-display/run-in/run-in-linebox-002.xht": [
[
- "/css/css-color/t32-opacity-basic-0.6-a.xht",
+ "/css/css-display/run-in/run-in-linebox-002.xht",
{}
]
],
- "css/css-color/t32-opacity-basic-1.0-a.xht": [
+ "css/css-display/run-in/table-anonymous-block-001.xht": [
[
- "/css/css-color/t32-opacity-basic-1.0-a.xht",
+ "/css/css-display/run-in/table-anonymous-block-001.xht",
{}
]
],
- "css/css-color/t32-opacity-clamping-0.0-b.xht": [
+ "css/css-display/run-in/table-layout-applies-to-004.xht": [
[
- "/css/css-color/t32-opacity-clamping-0.0-b.xht",
+ "/css/css-display/run-in/table-layout-applies-to-004.xht",
{}
]
],
- "css/css-color/t32-opacity-clamping-1.0-b.xht": [
+ "css/css-display/run-in/text-align-applies-to-004.xht": [
[
- "/css/css-color/t32-opacity-clamping-1.0-b.xht",
+ "/css/css-display/run-in/text-align-applies-to-004.xht",
{}
]
],
- "css/css-color/t32-opacity-offscreen-b.xht": [
+ "css/css-display/run-in/text-indent-applies-to-004.xht": [
[
- "/css/css-color/t32-opacity-offscreen-b.xht",
+ "/css/css-display/run-in/text-indent-applies-to-004.xht",
{}
]
],
- "css/css-color/t32-opacity-offscreen-with-alpha-c.xht": [
+ "css/css-display/run-in/top-applies-to-011.xht": [
[
- "/css/css-color/t32-opacity-offscreen-with-alpha-c.xht",
+ "/css/css-display/run-in/top-applies-to-011.xht",
{}
]
],
- "css/css-color/t32-opacity-zorder-c.xht": [
+ "css/css-display/run-in/unicode-bidi-applies-to-011.xht": [
[
- "/css/css-color/t32-opacity-zorder-c.xht",
+ "/css/css-display/run-in/unicode-bidi-applies-to-011.xht",
{}
]
],
- "css/css-color/t41-html4-keywords-a.xht": [
+ "css/css-display/run-in/vertical-align-applies-to-011.xht": [
[
- "/css/css-color/t41-html4-keywords-a.xht",
+ "/css/css-display/run-in/vertical-align-applies-to-011.xht",
{}
]
],
- "css/css-color/t421-rgb-clip-outside-gamut-b.xht": [
+ "css/css-display/run-in/visibility-applies-to-011.xht": [
[
- "/css/css-color/t421-rgb-clip-outside-gamut-b.xht",
+ "/css/css-display/run-in/visibility-applies-to-011.xht",
{}
]
],
- "css/css-color/t421-rgb-hex3-expand-b.xht": [
+ "css/css-display/run-in/white-space-applies-to-004.xht": [
[
- "/css/css-color/t421-rgb-hex3-expand-b.xht",
+ "/css/css-display/run-in/white-space-applies-to-004.xht",
{}
]
],
- "css/css-color/t421-rgb-values-meaning-b.xht": [
+ "css/css-display/run-in/word-spacing-applies-to-004.xht": [
[
- "/css/css-color/t421-rgb-values-meaning-b.xht",
+ "/css/css-display/run-in/word-spacing-applies-to-004.xht",
{}
]
],
- "css/css-color/t422-rgba-a0.0-a.xht": [
+ "css/css-display/run-in/z-index-applies-to-011.xht": [
[
- "/css/css-color/t422-rgba-a0.0-a.xht",
- {}
- ]
- ],
- "css/css-color/t422-rgba-a0.6-a.xht": [
- [
- "/css/css-color/t422-rgba-a0.6-a.xht",
- {}
- ]
- ],
- "css/css-color/t422-rgba-values-meaning-b.xht": [
- [
- "/css/css-color/t422-rgba-values-meaning-b.xht",
- {}
- ]
- ],
- "css/css-color/t424-hsl-h-rotating-b.xht": [
- [
- "/css/css-color/t424-hsl-h-rotating-b.xht",
- {}
- ]
- ],
- "css/css-color/t425-hsla-basic-a.xht": [
- [
- "/css/css-color/t425-hsla-basic-a.xht",
- {}
- ]
- ],
- "css/css-color/t425-hsla-h-rotating-b.xht": [
- [
- "/css/css-color/t425-hsla-h-rotating-b.xht",
- {}
- ]
- ],
- "css/css-color/t425-hsla-onscreen-b.xht": [
- [
- "/css/css-color/t425-hsla-onscreen-b.xht",
- {}
- ]
- ],
- "css/css-color/t43-svg-keywords-a.xht": [
- [
- "/css/css-color/t43-svg-keywords-a.xht",
- {}
- ]
- ],
- "css/css-color/t451-system-colors-a.xht": [
- [
- "/css/css-color/t451-system-colors-a.xht",
+ "/css/css-display/run-in/z-index-applies-to-011.xht",
{}
]
],
@@ -372791,12 +377961,6 @@
{}
]
],
- "css/css-transforms/css-transform-inherit-scale.html": [
- [
- "/css/css-transforms/css-transform-inherit-scale.html",
- {}
- ]
- ],
"css/css-transforms/rotate-180-degrees-001.html": [
[
"/css/css-transforms/rotate-180-degrees-001.html",
@@ -372821,36 +377985,12 @@
{}
]
],
- "css/css-values/iframe/vh-support-transform-origin-iframe.html": [
- [
- "/css/css-values/iframe/vh-support-transform-origin-iframe.html",
- {}
- ]
- ],
- "css/css-values/iframe/vh-support-transform-translate-iframe.html": [
- [
- "/css/css-values/iframe/vh-support-transform-translate-iframe.html",
- {}
- ]
- ],
- "css/css-writing-modes/bidi-table-001.html": [
- [
- "/css/css-writing-modes/bidi-table-001.html",
- {}
- ]
- ],
"css/css-writing-modes/block-plaintext-005.html": [
[
"/css/css-writing-modes/block-plaintext-005.html",
{}
]
],
- "css/css-writing-modes/block-plaintext-006.html": [
- [
- "/css/css-writing-modes/block-plaintext-006.html",
- {}
- ]
- ],
"css/css-writing-modes/form-controls-slr-004.xht": [
[
"/css/css-writing-modes/form-controls-slr-004.xht",
@@ -373291,6 +378431,12 @@
{}
]
],
+ "webdriver/tests/actions/key_shortcuts.py": [
+ [
+ "/webdriver/tests/actions/key_shortcuts.py",
+ {}
+ ]
+ ],
"webdriver/tests/actions/modifier_click.py": [
[
"/webdriver/tests/actions/modifier_click.py",
@@ -373305,6 +378451,12 @@
{}
]
],
+ "webdriver/tests/actions/mouse_dblclick.py": [
+ [
+ "/webdriver/tests/actions/mouse_dblclick.py",
+ {}
+ ]
+ ],
"webdriver/tests/actions/sequence.py": [
[
"/webdriver/tests/actions/sequence.py",
@@ -373361,18 +378513,90 @@
{}
]
],
+ "webdriver/tests/document_handling/page_source.py": [
+ [
+ "/webdriver/tests/document_handling/page_source.py",
+ {}
+ ]
+ ],
+ "webdriver/tests/element_click/bubbling.py": [
+ [
+ "/webdriver/tests/element_click/bubbling.py",
+ {}
+ ]
+ ],
"webdriver/tests/element_click/select.py": [
[
"/webdriver/tests/element_click/select.py",
{}
]
],
+ "webdriver/tests/element_click/stale.py": [
+ [
+ "/webdriver/tests/element_click/stale.py",
+ {}
+ ]
+ ],
+ "webdriver/tests/element_retrieval/find_element.py": [
+ [
+ "/webdriver/tests/element_retrieval/find_element.py",
+ {}
+ ]
+ ],
+ "webdriver/tests/element_retrieval/find_element_from_element.py": [
+ [
+ "/webdriver/tests/element_retrieval/find_element_from_element.py",
+ {}
+ ]
+ ],
+ "webdriver/tests/element_retrieval/find_elements.py": [
+ [
+ "/webdriver/tests/element_retrieval/find_elements.py",
+ {}
+ ]
+ ],
+ "webdriver/tests/element_retrieval/find_elements_from_element.py": [
+ [
+ "/webdriver/tests/element_retrieval/find_elements_from_element.py",
+ {}
+ ]
+ ],
"webdriver/tests/element_retrieval/get_active_element.py": [
[
"/webdriver/tests/element_retrieval/get_active_element.py",
{}
]
],
+ "webdriver/tests/element_send_keys/interactability.py": [
+ [
+ "/webdriver/tests/element_send_keys/interactability.py",
+ {}
+ ]
+ ],
+ "webdriver/tests/element_send_keys/scroll_into_view.py": [
+ [
+ "/webdriver/tests/element_send_keys/scroll_into_view.py",
+ {}
+ ]
+ ],
+ "webdriver/tests/execute_async_script/user_prompts.py": [
+ [
+ "/webdriver/tests/execute_async_script/user_prompts.py",
+ {}
+ ]
+ ],
+ "webdriver/tests/execute_script/cyclic.py": [
+ [
+ "/webdriver/tests/execute_script/cyclic.py",
+ {}
+ ]
+ ],
+ "webdriver/tests/execute_script/user_prompts.py": [
+ [
+ "/webdriver/tests/execute_script/user_prompts.py",
+ {}
+ ]
+ ],
"webdriver/tests/fullscreen_window.py": [
[
"/webdriver/tests/fullscreen_window.py",
@@ -373417,30 +378641,6 @@
{}
]
],
- "webdriver/tests/retrieval/find_element.py": [
- [
- "/webdriver/tests/retrieval/find_element.py",
- {}
- ]
- ],
- "webdriver/tests/retrieval/find_element_from_element.py": [
- [
- "/webdriver/tests/retrieval/find_element_from_element.py",
- {}
- ]
- ],
- "webdriver/tests/retrieval/find_element_from_elements.py": [
- [
- "/webdriver/tests/retrieval/find_element_from_elements.py",
- {}
- ]
- ],
- "webdriver/tests/retrieval/find_elements.py": [
- [
- "/webdriver/tests/retrieval/find_elements.py",
- {}
- ]
- ],
"webdriver/tests/sessions/get_timeouts.py": [
[
"/webdriver/tests/sessions/get_timeouts.py",
@@ -373495,6 +378695,12 @@
}
]
],
+ "webdriver/tests/sessions/status.py": [
+ [
+ "/webdriver/tests/sessions/status.py",
+ {}
+ ]
+ ],
"webdriver/tests/set_window_rect.py": [
[
"/webdriver/tests/set_window_rect.py",
@@ -373533,12 +378739,6 @@
{}
]
],
- "webdriver/tests/status.py": [
- [
- "/webdriver/tests/status.py",
- {}
- ]
- ],
"webdriver/tests/switch_to_parent_frame.py": [
[
"/webdriver/tests/switch_to_parent_frame.py",
@@ -373585,7 +378785,7 @@
"support"
],
"./.travis.yml": [
- "ee7a0f7a54701f7cc9a5cb192a9400b864805371",
+ "5713c525560fa7419944eb6fae32bb62f0c9e3fe",
"support"
],
"./CONTRIBUTING.md": [
@@ -373601,7 +378801,7 @@
"support"
],
"./README.md": [
- "2a2ab5b7d22a1e65e52bdb2cc2b787b8fa03472b",
+ "c58b661f8a9377baf6d71b9e2b704441b127ef5d",
"support"
],
"./check_stability.ini": [
@@ -373613,7 +378813,7 @@
"support"
],
"./lint.whitelist": [
- "b5d3ae0d3de0f8332904829ef0070f547dd3bc83",
+ "466e640065159fe12574aec8682dc74cf67fe49a",
"support"
],
"./serve.py": [
@@ -373625,7 +378825,7 @@
"support"
],
"./update-built-tests.sh": [
- "d0184e7d0761064d0acaae095a50c0b1dfd9c3b6",
+ "e632acfa68de35b71b650db172ffff6d048399a7",
"support"
],
"./wpt": [
@@ -375785,7 +380985,7 @@
"support"
],
"2dcontext/fill-and-stroke-styles/2d.gradient.object.invalidcolour.html": [
- "9208f03b80abcf89354a56f913acf5aeb1b0edfe",
+ "80cf63aa87d02a9618094c822b18c83b235222ae",
"testharness"
],
"2dcontext/fill-and-stroke-styles/2d.gradient.object.invalidoffset.html": [
@@ -376113,7 +381313,7 @@
"testharness"
],
"2dcontext/imagebitmap/createImageBitmap-invalid-args.html": [
- "e839d537057d03f55108b871d2d32272cac7bc7f",
+ "badef04a0354c9e41f99370b86e5f757b1926ea7",
"testharness"
],
"2dcontext/imagebitmap/createImageBitmap-sizeOverflow.html": [
@@ -377605,7 +382805,7 @@
"support"
],
"2dcontext/tools/tests2d.yaml": [
- "99a4d558b9ad07ae18fa71a6276d0b08db0f49e1",
+ "057e6bc1199bb897e84a0d2ed7efefb616ba978c",
"support"
],
"2dcontext/tools/tests2dtext.yaml": [
@@ -377772,12 +382972,20 @@
"f1d0cf569f445712d986e9a85f3cbc717137d7fe",
"support"
],
+ "FileAPI/blob/Blob-Request-revoke-fetch.html": [
+ "54df50603ac5ff79f60d50a85c26339483da297b",
+ "testharness"
+ ],
"FileAPI/blob/Blob-XHR-revoke.html": [
"5858a79442dcad6325b3ab4bb6a20fc302fcf64c",
"testharness"
],
+ "FileAPI/blob/Blob-constructor-endings.html": [
+ "5ba751f75b52359a021da7b3f6c2f2a304f36d7f",
+ "testharness"
+ ],
"FileAPI/blob/Blob-constructor.html": [
- "fc5f5ef1deff60ceb2e2db86b511cdc03f19072f",
+ "96eb93bd23ec6b1f1faf5b7ba617fdf5f0eb75f7",
"testharness"
],
"FileAPI/blob/Blob-in-worker.worker.js": [
@@ -377792,14 +383000,38 @@
"7fc333cf82539fab242e421b8d486c6d406dfaa0",
"testharness"
],
+ "FileAPI/file/File-constructor-endings.html": [
+ "70e8d8b794e92f9b5c1c05d11af391468a82498a",
+ "testharness"
+ ],
"FileAPI/file/File-constructor.html": [
- "052ea42d7c68ca7d1d2f84de88e747c37e5deb10",
+ "95198c8156dadc851d279a863b883c8befdc3930",
"testharness"
],
"FileAPI/file/Worker-read-file-constructor.worker.js": [
"187acfc89c6123286cd759aac390c7de3b25c5a1",
"testharness"
],
+ "FileAPI/file/send-file-form-iso-2022-jp.tentative.html": [
+ "89f7e08e63145e07f06a5c45f6ba5e4835a75ece",
+ "testharness"
+ ],
+ "FileAPI/file/send-file-form-utf-8.html": [
+ "f2cfbcc800aacd8a98ee496db7d123a35d2a1b2c",
+ "testharness"
+ ],
+ "FileAPI/file/send-file-form-windows-1252.tentative.html": [
+ "43b967a2543c07ed8349db572eb10fc589b202fc",
+ "testharness"
+ ],
+ "FileAPI/file/send-file-form-x-user-defined.tentative.html": [
+ "f07b9491bf42650379f187c36c8c306f88928120",
+ "testharness"
+ ],
+ "FileAPI/file/send-file-form.html": [
+ "3bc42189304cd2ae051cfb015d8209176c699f0b",
+ "testharness"
+ ],
"FileAPI/fileReader.html": [
"fdfa73b1182058d10c1eb1b447885ecdce77fa6a",
"testharness"
@@ -377833,7 +383065,7 @@
"manual"
],
"FileAPI/idlharness.html": [
- "0eb0d3b2f6c394a6b30f71102bd002ae6e339283",
+ "66720cf090912985b9ea4e9cfe01126778f61e36",
"testharness"
],
"FileAPI/idlharness.idl": [
@@ -377916,6 +383148,10 @@
"36ccc5cb2de09589d02430b1c0582280d3240f32",
"support"
],
+ "FileAPI/support/send-file-form-helper.js": [
+ "f9bf42d1296f4fc6410b3bf77f3e29530bc58ad8",
+ "support"
+ ],
"FileAPI/support/upload.txt": [
"f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0",
"support"
@@ -377924,6 +383160,10 @@
"18972f4ed024eb5e1494ac466426ae32b3f5525f",
"support"
],
+ "FileAPI/unicode.html": [
+ "99a52f519e0d12bb9ece822f1480e0b08dca77e3",
+ "testharness"
+ ],
"FileAPI/url/blob-url-in-sandboxed-iframe.html": [
"59188b2e679f56d5eb7ea01428ce06ff0068111a",
"testharness"
@@ -377957,7 +383197,7 @@
"support"
],
"FileAPI/url/url_xmlhttprequest_img.html": [
- "ce325c9fcefab1864c9943d7d1dcc77c1d22390f",
+ "33c65ffbbe2ab33fa1d5ce946d0be536dd7d0a69",
"reftest"
],
"IndexedDB/OWNERS": [
@@ -379169,7 +384409,7 @@
"testharness"
],
"IndexedDB/interfaces.html": [
- "d2ff3cf10fbaf798d3bf5868699979829703d859",
+ "ad40586fec970a4907546e3a33aef14f23e378ff",
"testharness"
],
"IndexedDB/interfaces.idl": [
@@ -379556,47 +384796,43 @@
"61db89f7b21982628428d274dd238ad0f56a3c6d",
"support"
],
- "WebCryptoAPI/generateKey/failures.worker.js": [
- "248df758c6a92939799690abfd991fe888f90257",
- "testharness"
- ],
- "WebCryptoAPI/generateKey/failures_AES-CBC.worker.js": [
+ "WebCryptoAPI/generateKey/failures_AES-CBC.https.worker.js": [
"d462df4da1958c1a7a923f4f6f8d74fc7e20f2bb",
"testharness"
],
- "WebCryptoAPI/generateKey/failures_AES-CTR.worker.js": [
+ "WebCryptoAPI/generateKey/failures_AES-CTR.https.worker.js": [
"b745bb807622e053d8e5b2ad8f77ebdd1a5caa05",
"testharness"
],
- "WebCryptoAPI/generateKey/failures_AES-GCM.worker.js": [
+ "WebCryptoAPI/generateKey/failures_AES-GCM.https.worker.js": [
"c65c0c81ea710e071df9bbb36796c65c09023b2f",
"testharness"
],
- "WebCryptoAPI/generateKey/failures_AES-KW.worker.js": [
+ "WebCryptoAPI/generateKey/failures_AES-KW.https.worker.js": [
"aba136c70512155f57879d90e8387f468cd08eb0",
"testharness"
],
- "WebCryptoAPI/generateKey/failures_ECDH.worker.js": [
+ "WebCryptoAPI/generateKey/failures_ECDH.https.worker.js": [
"24ad2f00216f7dfbf0488e7fe0096877b7126093",
"testharness"
],
- "WebCryptoAPI/generateKey/failures_ECDSA.worker.js": [
+ "WebCryptoAPI/generateKey/failures_ECDSA.https.worker.js": [
"1fcde344bd6f05a1aec5ba568f5d6d7ede8c1b8c",
"testharness"
],
- "WebCryptoAPI/generateKey/failures_HMAC.worker.js": [
+ "WebCryptoAPI/generateKey/failures_HMAC.https.worker.js": [
"0c8d20aff7988acd571156f83be3825c6078686a",
"testharness"
],
- "WebCryptoAPI/generateKey/failures_RSA-OAEP.worker.js": [
+ "WebCryptoAPI/generateKey/failures_RSA-OAEP.https.worker.js": [
"06527a268ef2e009517230aae7e0c027ab94377b",
"testharness"
],
- "WebCryptoAPI/generateKey/failures_RSA-PSS.worker.js": [
+ "WebCryptoAPI/generateKey/failures_RSA-PSS.https.worker.js": [
"76553f02e30a990b521d51b3a13447459b5360ab",
"testharness"
],
- "WebCryptoAPI/generateKey/failures_RSASSA-PKCS1-v1_5.worker.js": [
+ "WebCryptoAPI/generateKey/failures_RSASSA-PKCS1-v1_5.https.worker.js": [
"f1b875ecbe690db60e4e0706ed35f25cbd996d85",
"testharness"
],
@@ -379604,47 +384840,43 @@
"9623250b44a270bd23f6d892e8a8296351fac708",
"support"
],
- "WebCryptoAPI/generateKey/successes.worker.js": [
- "03f20782f7615881757c5febe211383e7ef19ebf",
- "testharness"
- ],
- "WebCryptoAPI/generateKey/successes_AES-CBC.worker.js": [
+ "WebCryptoAPI/generateKey/successes_AES-CBC.https.worker.js": [
"c7f1d0c5e7ecf28cfc052c56739aaa3bc949ffca",
"testharness"
],
- "WebCryptoAPI/generateKey/successes_AES-CTR.worker.js": [
+ "WebCryptoAPI/generateKey/successes_AES-CTR.https.worker.js": [
"4b388cfe97d99300e7f9c4514140e3b030ba4553",
"testharness"
],
- "WebCryptoAPI/generateKey/successes_AES-GCM.worker.js": [
+ "WebCryptoAPI/generateKey/successes_AES-GCM.https.worker.js": [
"5502fcb3da8257d28e3c49d1d391e3f6dfd3c022",
"testharness"
],
- "WebCryptoAPI/generateKey/successes_AES-KW.worker.js": [
+ "WebCryptoAPI/generateKey/successes_AES-KW.https.worker.js": [
"19c0af9024a49ce6e1b2c884c0806960686509e0",
"testharness"
],
- "WebCryptoAPI/generateKey/successes_ECDH.worker.js": [
+ "WebCryptoAPI/generateKey/successes_ECDH.https.worker.js": [
"751da81c9530a7dc5c31b02ed7c6e3dab8d997b4",
"testharness"
],
- "WebCryptoAPI/generateKey/successes_ECDSA.worker.js": [
+ "WebCryptoAPI/generateKey/successes_ECDSA.https.worker.js": [
"900abdfba6c8a142d0cea1af9c1f6417bf05eb25",
"testharness"
],
- "WebCryptoAPI/generateKey/successes_HMAC.worker.js": [
+ "WebCryptoAPI/generateKey/successes_HMAC.https.worker.js": [
"90bdffb8858c79694521cb9a831bc658b2c72834",
"testharness"
],
- "WebCryptoAPI/generateKey/successes_RSA-OAEP.worker.js": [
+ "WebCryptoAPI/generateKey/successes_RSA-OAEP.https.worker.js": [
"e74fcd1eaa98078c3f1bb6c16fbf82a754397d4b",
"testharness"
],
- "WebCryptoAPI/generateKey/successes_RSA-PSS.worker.js": [
+ "WebCryptoAPI/generateKey/successes_RSA-PSS.https.worker.js": [
"bccff0d804b1d06ae9b183ebc38c72b3031c7f8a",
"testharness"
],
- "WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.worker.js": [
+ "WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.https.worker.js": [
"b9e9790245742b8eeb4af7679cc0144710380c07",
"testharness"
],
@@ -379656,10 +384888,6 @@
"3804433a5bd2c382c8bd9afbd1b41792d9f927c1",
"testharness"
],
- "WebCryptoAPI/generateKey/test_failures.https.html": [
- "a1458bc27b594b9051bfbb7e537aebe2c95b6859",
- "testharness"
- ],
"WebCryptoAPI/generateKey/test_failures_AES-CBC.https.html": [
"bf4b12efa09c2602bed73b4ae2b94ebdf5bf9749",
"testharness"
@@ -379729,7 +384957,7 @@
"testharness"
],
"WebCryptoAPI/generateKey/test_successes_RSA-OAEP.https.html": [
- "04b89d631e81fd7822049c8513984c3af3711efd",
+ "7ebe1df33a5df5f5a2cead014af5502246b6b833",
"testharness"
],
"WebCryptoAPI/generateKey/test_successes_RSA-PSS.https.html": [
@@ -379745,11 +384973,11 @@
"testharness"
],
"WebCryptoAPI/idlharness.html": [
- "52b5381311cc0e2595d251273e054fa826de9765",
+ "f97da6e12fbd08b0fe93a6bc0fb9724053d147a8",
"testharness"
],
"WebCryptoAPI/idlharness.https.html": [
- "52b5381311cc0e2595d251273e054fa826de9765",
+ "f97da6e12fbd08b0fe93a6bc0fb9724053d147a8",
"testharness"
],
"WebCryptoAPI/idlharness.worker.js": [
@@ -379861,7 +385089,7 @@
"testharness"
],
"WebCryptoAPI/tools/generate.py": [
- "e7b1269e1b432d017256eb200540c7fabeadff25",
+ "058fc13d71d3d030477593591d4119b59fa3cd54",
"support"
],
"WebCryptoAPI/util/helpers.js": [
@@ -379932,6 +385160,10 @@
"24807487f4acea28e3b1315e0876d99a79fb592d",
"testharness"
],
+ "WebIDL/ecmascript-binding/no-regexp-special-casing.any.js": [
+ "21d817e7095ae8b6ce3b661aeb339ed6e96ceb1a",
+ "testharness"
+ ],
"WebIDL/ecmascript-binding/put-forwards.html": [
"95fcfc28dae32ab9aadf21d2512a519d6a9fd5ab",
"testharness"
@@ -381617,7 +386849,7 @@
"testharness"
],
"XMLHttpRequest/send-network-error-sync-events.sub.htm": [
- "c455c57e952ca5d44843b42840becd2c56f11213",
+ "8dd189e5d654c1fc46808dbd860ed0b055851227",
"testharness"
],
"XMLHttpRequest/send-no-response-event-loadend.htm": [
@@ -381661,7 +386893,7 @@
"testharness"
],
"XMLHttpRequest/send-redirect-post-upload.htm": [
- "381627d16e8ad618b3dd9d31c51466a154ad7200",
+ "504168881ffa74378fc151f01fe53a177fc89633",
"testharness"
],
"XMLHttpRequest/send-redirect-to-cors.htm": [
@@ -381908,16 +387140,48 @@
"8051e72ea6d92c55fa457eb88f00da3b7a873225",
"testharness"
],
+ "accelerometer/Accelerometer-disabled-by-feature-policy.https.html": [
+ "37ec335921c5e3cb6011986e76da04254106f4f6",
+ "testharness"
+ ],
+ "accelerometer/Accelerometer-disabled-by-feature-policy.https.html.headers": [
+ "bde03e5f36844e0818f4d1092c4fe6788cb4e194",
+ "support"
+ ],
+ "accelerometer/Accelerometer-enabled-by-feature-policy-attribute-redirect-on-load.https.html": [
+ "b03ee7c22f1dd78e2681632f2f67598da67a09cb",
+ "testharness"
+ ],
+ "accelerometer/Accelerometer-enabled-by-feature-policy-attribute.https.html": [
+ "6f5a595f9ee8d8e0dcd29eae9816210846c43557",
+ "testharness"
+ ],
+ "accelerometer/Accelerometer-enabled-by-feature-policy.https.html": [
+ "9997d07beb3ef1c711dcfd6308c58d11c938244d",
+ "testharness"
+ ],
+ "accelerometer/Accelerometer-enabled-by-feature-policy.https.html.headers": [
+ "18a6f86070b21bff87cc9dc37194cdb6113af198",
+ "support"
+ ],
+ "accelerometer/Accelerometer-enabled-on-self-origin-by-feature-policy.https.html": [
+ "3b4500e2ff0f8a3efae8ace952a8993ed3005bd6",
+ "testharness"
+ ],
+ "accelerometer/Accelerometer-enabled-on-self-origin-by-feature-policy.https.html.headers": [
+ "c1723ad9944cf2393a5519a91e4e47a0255bcaf4",
+ "support"
+ ],
"accelerometer/Accelerometer.https.html": [
- "cdf386711da6ef6a795bcf179e7c7ce373751f56",
+ "c0ca55250886c6a8c6194b658ed362e8b10ccae3",
"testharness"
],
"accelerometer/Accelerometer_insecure_context.html": [
- "da374eab5cbc963d8e5e2f2025d9fb1a94043643",
+ "ad29f70c8f506002154e6ffa430b87f5e5ae0923",
"testharness"
],
"accelerometer/Accelerometer_onerror-manual.https.html": [
- "e03faad7d297ce2c5d6fefa66a2397c3d9a32e2d",
+ "f20acb4b4e2f774fc13c870f972aaa2ca82afd27",
"manual"
],
"accelerometer/OWNERS": [
@@ -382017,7 +387281,7 @@
"support"
],
"acid/acid3/test.html": [
- "1822fb86b9af47dd384398e56afb6d8ed2f0565b",
+ "67435e96f4240675943bad5ca296a1020cf04fe5",
"reftest"
],
"acid/acid3/xhtml.1": [
@@ -382044,6 +387308,38 @@
"889fd09853f091aba8fea3b45cfeb36437be1c2b",
"support"
],
+ "ambient-light/AmbientLightSensor-disabled-by-feature-policy.https.html": [
+ "0e09d27c24fa43fa4b854597f2eebc7589d565b3",
+ "testharness"
+ ],
+ "ambient-light/AmbientLightSensor-disabled-by-feature-policy.https.html.headers": [
+ "60c9a6457eebafad8ac6c139f80ababb6efd1ceb",
+ "support"
+ ],
+ "ambient-light/AmbientLightSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html": [
+ "c062b275f18a69d092fe4f8d20d01f93a631556f",
+ "testharness"
+ ],
+ "ambient-light/AmbientLightSensor-enabled-by-feature-policy-attribute.https.html": [
+ "e719162b3001f7a6ef307a1f3af9ac048a0f7ce3",
+ "testharness"
+ ],
+ "ambient-light/AmbientLightSensor-enabled-by-feature-policy.https.html": [
+ "605f76f34e24f91ca9e2a6538624ec89633c6d1a",
+ "testharness"
+ ],
+ "ambient-light/AmbientLightSensor-enabled-by-feature-policy.https.html.headers": [
+ "00f610fe390dc2bd24b76170cf268a08483fe4aa",
+ "support"
+ ],
+ "ambient-light/AmbientLightSensor-enabled-on-self-origin-by-feature-policy.https.html": [
+ "6ed23575a7dc16c7044970d81d7768796e9968d4",
+ "testharness"
+ ],
+ "ambient-light/AmbientLightSensor-enabled-on-self-origin-by-feature-policy.https.html.headers": [
+ "9c9b554e33d34e1513dd315ecd6299f756d68b43",
+ "support"
+ ],
"ambient-light/AmbientLightSensor.https.html": [
"86a1f84e2e034d58b2a7f6fc01880028b444c7cd",
"testharness"
@@ -384184,6 +389480,10 @@
"61b61d09a21daee964e0ebd26f7bdfdd1964c8ae",
"support"
],
+ "beacon/OWNERS": [
+ "500e8f078ef1f3e56bf3e2590a2799046832f573",
+ "support"
+ ],
"beacon/beacon-basic-blob.html": [
"60262cdcf9a58117db70f2afdeed195c820b04c7",
"testharness"
@@ -384296,10 +389596,26 @@
"ef497e5da8691971c612980bb94eae44fc17c509",
"support"
],
- "bluetooth/idl-Bluetooth.html": [
+ "bluetooth/README.md": [
+ "570b51035ed737c73da8b266cbe0eb658745286e",
+ "support"
+ ],
+ "bluetooth/idl/idl-Bluetooth.html": [
"5d4d8278b1f24798765974c35777f70fcbfc9cfa",
"testharness"
],
+ "bluetooth/idl/idl-BluetoothUUID.html": [
+ "4feb7657e77a18489bbe2d7a98405470c6ce0b82",
+ "testharness"
+ ],
+ "bluetooth/idl/idl-NavigatorBluetooth.html": [
+ "9367593c5bfe07afb4629791cf6aab70460dcd4c",
+ "testharness"
+ ],
+ "bluetooth/resources/bluetooth-helpers.js": [
+ "bca57dea31c477c56e8323919f45df6a755101f5",
+ "support"
+ ],
"clear-site-data/navigation-insecure.html": [
"97c069cf7c938e1ebdba3f243ad48369a7fb5542",
"testharness"
@@ -384473,7 +389789,7 @@
"support"
],
"common/media.js": [
- "a575b8135e6ddb1501fc2a082d7544ee86011b7d",
+ "33c78c9c056dc4879c2503075e6cedbf2211b6d2",
"support"
],
"common/media.js.headers": [
@@ -384489,7 +389805,7 @@
"support"
],
"common/performance-timeline-utils.js": [
- "cf06f5a0e00f29d862753144634b4e1d0f074fb8",
+ "8a914a75398a2865da676183a62b00753607fbca",
"support"
],
"common/performance-timeline-utils.js.headers": [
@@ -384540,10 +389856,6 @@
"e3593850f8098d3f3ff82c042deab15f51c66a52",
"support"
],
- "common/vendor-prefix.js.headers": [
- "e3593850f8098d3f3ff82c042deab15f51c66a52",
- "support"
- ],
"compat/OWNERS": [
"e714708a95e56bc556b64d991cb72f0ccace4f92",
"support"
@@ -384653,11 +389965,11 @@
"support"
],
"conformance-checkers/html-aria/_functional/tree/ariatree.html": [
- "f9e85f04e0e2342a2dc3441a25c238f6db577139",
+ "3db4a5ff2c0d9be937ea32bf061951b2a09c996e",
"support"
],
"conformance-checkers/html-aria/_functional/tree/ariatree2.html": [
- "3c4cb0fe40016f75f90a1e58b7952ea4b34f6e63",
+ "6860d66ea736a7b3044242f24692669bec6c22a5",
"support"
],
"conformance-checkers/html-aria/_functional/tree/css/img/expander.gif": [
@@ -384705,195 +390017,195 @@
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/673.html": [
- "1a576c12517202a5d943f602d29d84678a73b59c",
+ "cfcfde79147f7d295571623600c90f639e6efb4f",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/674.html": [
- "d0a1e8fb30dfc582472b412dcf17ee760234dcda",
+ "dd12a4c0d1fa1b51606c7aee9fa7abb02bf76767",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/675.html": [
- "7c75478bf0536dbc0f3c605d98521a954cd299d7",
+ "e63b719817288c9d064942f310ac3bae6f25d473",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/676.html": [
- "42a1256f62fbb4940a4c5e180bbbdd9debb622ff",
+ "955c4e95fe420685d172408590f03f6d69cca725",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/677.html": [
- "07baaad9d0c60f94aa5ac9ca9cc17333b0aa654e",
+ "1eeca423944499c0f2896c06aa4d2fce849db199",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/678.html": [
- "3ef183bb165bbeebb9c0907514a3fb4dfd85c8a0",
+ "da67c23ee1f6a090d6abd7f91fc06b2d94fbc25d",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/679.html": [
- "9d23235020d67bb17357b19aea6aa9bc90b8113a",
+ "9a791faa521cc1b240f6801a0406fcf5219527a1",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/680.html": [
- "81d90ec378ca4cdf16238235c9602c86f3ad23a2",
+ "f8a7dd3acc810386f9a6b1a76243e986c9976a7e",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/681.html": [
- "6bb2c295a11d12e83ed792d2de3dafa7d805fc20",
+ "72b29b7292f02cea663478c838567d6ac7fe3170",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/682.html": [
- "f4052c03fda369769050267868e57e75ffb8870a",
+ "68b34220f7ddf88ea55c3b0850e2f3773941d4b8",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/683.html": [
- "49d439774c8911452a2bc149f4e7fb5b18b241ce",
+ "60aa9176d5e117fc46019758ce514b1a64d39ef6",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/684.html": [
- "850500dedc5d3f6f26ad00c7e957afbbd66f495d",
+ "abf8162860876fd5244fe460d9080c5da2fc7f45",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/685.html": [
- "93a467c8a0f92d4181220a32adaf7fef5c45539f",
+ "994daef845049f08d75545f8bba27e7cf117fe91",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/686.html": [
- "3f273b86aa88e8b9ed82a5765ba7f051b4c4c114",
+ "2feab848a496557a0ad9b786927f198d0dfacc41",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/687.html": [
- "3b72b339456f16c61dc6a31a05cff0b8d3b0fd7c",
+ "59a2193fda29ef228e82fb47b69e6fa8cb1a124a",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/688.html": [
- "5b9277b49901add92345009fdece487793596de2",
+ "ec660350987878ba0c54a5ae235d16d9ed4183e0",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/689.html": [
- "ec2f320c14352a85fddc6e4aeed3ce55e14ae6ef",
+ "043954301260b11673803f817ac4aaa5b22398a3",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/690.html": [
- "5bd040685231ced758210f56234baa26acdf00c1",
+ "f1b0d87a1b11241cc1d7d7613f7b3700001a55a4",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/691.html": [
- "9af038de68bc193a12958418971714e85d6f0d52",
+ "80917ea366906c9ebb4b1bc24a1f4dde5e9e765f",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/692.html": [
- "a97b4a4853756e245dadfb2521ef58d36565328f",
+ "fdca97a7ef4448d2743be36718df5a1d3972035d",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/693.html": [
- "a21c65bb0e28d0a8c65dc729ad958deafb8fe8aa",
+ "450b2ed97e4225bb7dd7ab06d9e4398b910a16b8",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/694.html": [
- "877a162fa7495c40a675d8df9cac5bfd1913c50a",
+ "7cbd07132cd55a39e3e8a0615864fe0d6249b4a3",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/695.html": [
- "3399fe6f5e20b47d8999225ff45860f0c780af64",
+ "b0608580f623674105f735d764af5179623664c1",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/696.html": [
- "1a115b5def088c8992a172ff6dd70b1bfbff8f5c",
+ "d62c9ea4ca6ef04cdb3c1a633a297f01171f39d9",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/697.html": [
- "5c9f91b552f4d2eeb6baca10c22fb9db0802896a",
+ "fbf369f993893bf97e924e08853dee6cbf5c7a20",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/698.html": [
- "8731402b6f2ff8180a70673f73d4a3c72c176ade",
+ "da4c27037d56bb296956bbd754b3fed93e14f9ad",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/699.html": [
- "3f2768c03515ed34c5c98cbc91092de51c949170",
+ "2efbc0d35b5f81927a8aa47c71cea034b534e213",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/700.html": [
- "67289abb6e8fd4dadc00e2bd49ce4d95fb33f8b0",
+ "b891f3bdf8e175147bd340f730752a3ccc1231d7",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/701.html": [
- "81e336700dd18b844e275081e0c41e02c57dcf05",
+ "586b9acb8f174ac53e21c480da9a9949940c0cd0",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/702.html": [
- "f9d9473c4bbf68fb3fede8f537df88e9bea1baa9",
+ "1b9d66be9d95b632e34abf69f0be0dbc68f8fa3c",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/703.html": [
- "572612434ee452c9d1c1377cd2feeae00f7a3f49",
+ "d9472daeb7024354f20e38016857995651cf131b",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/704.html": [
- "57ee82c925e403a1d5b79591ba2b71b15f23f032",
+ "f82e4d39ae101a43b6ade90c0ada017b5f80bebe",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/705.html": [
- "89a99ab74e99b35d0f91f4927a4bcb233bdaf24e",
+ "04cdd01ff1555dff235c5c7ae91cd147c81de299",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/706.html": [
- "37cac6282727d0ba82b245254af56de86097d1bd",
+ "a1ba506851d2c0427451f45b8d5cabfde18f9e4a",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/707.html": [
- "b71460bdc499131298ca82224c304e5605d303ea",
+ "b378aab84338105f9aeed36cd3606ff4736942df",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/708.html": [
- "dfae811bf6784caf26035e77f3a9df0b1e01b8ba",
+ "94f336593fb6d4a1f417c73ec673bb0de5b70176",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/709.html": [
- "18c678ef080f49549a8c9abe5a2264c73c008ccc",
+ "33461017ccda24eb09fb236edacebd01507ac956",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/710.html": [
- "3c764065fde0deea537183c07dbf1eee79d3a216",
+ "f020f0224c86139407adf34155398bb9c1718b92",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/711.html": [
- "9824adccf8c14a07cffdab79174312ab1ea6316e",
+ "0787df1ced7c0e9e67612aade934483e135774a7",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/712.html": [
- "789eec3d5e875de0b47683f44707ac81a95e64ca",
+ "33076074760742b435a4fa8ceb751eaa59179a69",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/713.html": [
- "057e9d9dc6a29c26392f427a5532d98af90c8b3e",
+ "4941ac15aa8a4239e8a2ec7d7202ea94f5cde8d0",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/714.html": [
- "ba5893d78efa51dfa67598836a177e8c7d0b18f5",
+ "addd44a63339378290ef8ce844073a6b9417ba43",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/715.html": [
- "f7b2a149a027de9f7088cd064e1d5c3771c8b531",
+ "77d138ee6917d10f3edb3cb79846a5986c09fe56",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/716.html": [
- "f1436c18795e2dadf36fe93f6e4d2be74a0cd338",
+ "114823344ddb18c21e81cf6c3745f97fc8198e5f",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/717.html": [
- "f8df430d2df817bbe9804b8e2d1bc231c5792abd",
+ "c6c9aff3de53b00a02b7832e44b2563f41650ac1",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/718.html": [
- "a7cb893fc65215c91b8489efa6ab6a3d418653a8",
+ "091e2e2f3250ac792c52509a842253f6a6c05212",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/719.html": [
- "b9daf582eb8ed45cdabc90df8a49c5feaeb2a817",
+ "ac48074d746edf167e5bd0342ad3d888435b99ba",
"support"
],
"conformance-checkers/html-aria/accessible-name-updates/720.html": [
- "7f17c0c016e8c6410b25097f943980396903524c",
+ "ba2bfa7c4508ccf9672a41a591ef1d050220acfe",
"support"
],
"conformance-checkers/html-aria/aria-describedby/772.html": [
@@ -384913,11 +390225,11 @@
"support"
],
"conformance-checkers/html-aria/author-requirements/567.html": [
- "2089b053bce7f3d2b11f0bad964e5cb31460052e",
+ "d4a6d547d0b6abc3cad927cd2e5ffbe465b58ab6",
"support"
],
"conformance-checkers/html-aria/author-requirements/568.html": [
- "1da280ec0c5039680965616577e772e93bedb4f1",
+ "926e47114e9ff9230336dffcb1236e5fed7e0e3d",
"support"
],
"conformance-checkers/html-aria/author-requirements/569.html": [
@@ -384925,15 +390237,15 @@
"support"
],
"conformance-checkers/html-aria/author-requirements/571-haswarn.html": [
- "706508247ce630c6c5b3295bfbb6a58110ba8439",
+ "3f069b431d4a68609e6d7884c57d6de4d031d333",
"support"
],
"conformance-checkers/html-aria/author-requirements/572-haswarn.html": [
- "d036b8971cc46b496550fd98bf45dfb613e18d76",
+ "6a5bf9157bd1c711c8fcf74c3eab2a243f34959b",
"support"
],
"conformance-checkers/html-aria/author-requirements/573-haswarn.html": [
- "39bcd0438b81208daf037e3880cbb5f8e24fd892",
+ "e8e253c5515fc9e2e2f7759e6420f8bb9f1ef0d8",
"support"
],
"conformance-checkers/html-aria/author-requirements/574.html": [
@@ -384961,7 +390273,7 @@
"support"
],
"conformance-checkers/html-aria/author-requirements/580.html": [
- "779bed9dc84d13dbe7222fd60e8e8648629d71aa",
+ "d605c2af2645bab6c0c480a02854d5e6f0216ac9",
"support"
],
"conformance-checkers/html-aria/author-requirements/581.html": [
@@ -385029,27 +390341,27 @@
"support"
],
"conformance-checkers/html-aria/live-events/test-case-live-event-1.html": [
- "1d141e5e8c03df30877e2f00d08bd18763241118",
+ "d66547dc32b127d7d8662ebb7f87a0b7991cb006",
"support"
],
"conformance-checkers/html-aria/live-events/test-case-live-event-2.html": [
- "5ddf6c2bfd7b9adfc45720ef4f28f47724027adc",
+ "80182786fa25c32827b336aa263b689e29852a49",
"support"
],
"conformance-checkers/html-aria/live-events/test-case-live-event-3.html": [
- "e5e9ddbeaa5fb6722f87e53e0cfe257682bdf0ec",
+ "54ed58aa6f57947eab81b097fe25c2f18d3c8e05",
"support"
],
"conformance-checkers/html-aria/live-events/test-case-live-event-4.html": [
- "0f45ecb2dbf86b1c32ef33709cb2a9cf338dcaca",
+ "81b6d75109141ea494aa835a7a7b5266ee1076da",
"support"
],
"conformance-checkers/html-aria/live-events/test-case-live-event-5.html": [
- "407fccfc2a953c5fef01799e25be3a900bf8b145",
+ "f3d25d49ceaace70d0434c94a8b709db916278dd",
"support"
],
"conformance-checkers/html-aria/live-events/test-case-live-event-6.html": [
- "e17f8497bf864ec1cee44f0acb251adaaee33fe3",
+ "ffdc39a54d106141486677160983f4f5efbf98af",
"support"
],
"conformance-checkers/html-aria/mixed-value/585.html": [
@@ -385201,23 +390513,23 @@
"support"
],
"conformance-checkers/html-aria/name-computation-input/659.html": [
- "c5e402b9f6d80d697f7afd6fc94fb872954f9945",
+ "b1ce4a674402c8f833f815deb6906ac6ab76f13b",
"support"
],
"conformance-checkers/html-aria/name-computation-input/660.html": [
- "901b68c26bbb9a723837ebea2b91fa880536f0e4",
+ "07f0d9c33c16b0da5e4b64051d305eeca59aa3de",
"support"
],
"conformance-checkers/html-aria/name-computation-input/661.html": [
- "6b6990e01092bdeba015637ad3a3cdc1d36a8ead",
+ "4eeb3fe92494a3636914a37ae561fa025723597b",
"support"
],
"conformance-checkers/html-aria/name-computation-input/662.html": [
- "18e091c8ad97eaa09cfc834419e40528eaeb695b",
+ "33f668ed9d283c0806c8ac3844ce2d98e4c145d7",
"support"
],
"conformance-checkers/html-aria/name-computation-input/663.html": [
- "21a67cd21457ca61435c44b099ea071bd8d5af35",
+ "1da9833691a26f99579a817dc0849bdd19576117",
"support"
],
"conformance-checkers/html-aria/name-computation-input/721.html": [
@@ -385785,7 +391097,7 @@
"support"
],
"conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-listbox-parent-combobox.html": [
- "c2b471304af885d0d3715b03c5e8fca750d016af",
+ "e2cb06bfa3ec9533a4d9fc87e56856a29609f627",
"support"
],
"conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-listbox.html": [
@@ -387145,19 +392457,19 @@
"support"
],
"conformance-checkers/html-aria/selected-state/670.html": [
- "6e65f4d28d029ff94679718f7f21efadaed177f1",
+ "467c82ca654e35c80ca3dc0bb62239b9c011840c",
"support"
],
"conformance-checkers/html-aria/selected-state/671.html": [
- "e28f109690756a7ae95680948f00a2720d2415e7",
+ "358c29bbd3d615d6f875f740702e3aad19e0d8cd",
"support"
],
"conformance-checkers/html-aria/selected-state/672.html": [
- "9cf2912de31390727c02a52502f44e78db4b4112",
+ "526c1f37f668f15abdfbb9d95c04c8fb9cd67ba8",
"support"
],
"conformance-checkers/html-aria/setsize-posinset-level/setsize-posinset-level-1.html": [
- "2d62f1e7e2659cd05a4ab0f46c0193283bdd2701",
+ "daff5d78defe7e27254c8857755aae200a79e9f0",
"support"
],
"conformance-checkers/html-aria/setsize-posinset-level/setsize-posinset-level-5.html": [
@@ -387173,27 +392485,27 @@
"support"
],
"conformance-checkers/html-aria/stability-of-dom/669.html": [
- "c0e6c5137b8d4ae90235be5b23c0ac360fdff5eb",
+ "45b9ba0e7447419112c86890b3526c172eccdc43",
"support"
],
"conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-A.html": [
- "f135227d46a5449ee75552301926c325b520d33c",
+ "104b0f3ff63f518dd2dadff1c6a07520608b2e4b",
"support"
],
"conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-B.html": [
- "aa44fffaa89c2769c3ebf9497c4933993eb3db1f",
+ "fa808d143b2dc7a596b1de9e993ede72ec96fbc5",
"support"
],
"conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-C.html": [
- "b8c96a991f0db6f3890c534aa572560547c30e0b",
+ "cb549a4c278d9de823a983137665e561f09cfd55",
"support"
],
"conformance-checkers/html-aria/testcases-multiselectable/testcase-multiselectable-D.html": [
- "bd50bab315f21422d9a70a5a17c835c12046a303",
+ "2bce50e8b66893dc2d155e1dd251aa4099e6f248",
"support"
],
"conformance-checkers/html-aria/testcases-multiselectable/testcase-tree-multiselectable-C.html": [
- "55cfc48c6f3dc254a36d939553d135ff2885cc0f",
+ "19d77de4bcfe5c42a7a5eb77a16ab1289613ca2a",
"support"
],
"conformance-checkers/html-its/allowedcharacters/html/allowedcharacters1html.html": [
@@ -387797,19 +393109,19 @@
"support"
],
"conformance-checkers/html-its/locqualityissue/html/locqualityissue4html.html": [
- "f416ac2b181cc1a1e03c2b9713c0ec0e99248254",
+ "76ee9f93525f88e97b3259d0f7a5dc610039d575",
"support"
],
"conformance-checkers/html-its/locqualityissue/html/locqualityissue5html.html": [
- "f4cb3fac343ac3141ca9490c19715cd4cbd9b802",
+ "c18b1507e44586881c422f380054cdba334544c0",
"support"
],
"conformance-checkers/html-its/locqualityissue/html/locqualityissue6html.html": [
- "e18daf5bb1e9eda592f9bb0c48e18775daba1766",
+ "5c507b9dbf2e5637b6a461a60fc39d9e852fa309",
"support"
],
"conformance-checkers/html-its/locqualityissue/html/locqualityissue7html.html": [
- "e595c25de0a0ae226cd40d889f296adedeb96552",
+ "875b6a8f81ad179eda3344e9baa2b14d09a3bc8e",
"support"
],
"conformance-checkers/html-its/locqualityissue/html/locqualityissue8html.html": [
@@ -389677,7 +394989,7 @@
"support"
],
"conformance-checkers/html-svg/animate-elem-33-t-isvalid.html": [
- "a30177e9b3a709eaa1d28fcdada39ced5a417601",
+ "39c155e80765b020b7916e3c32359f2aed72fd4b",
"support"
],
"conformance-checkers/html-svg/animate-elem-34-t-isvalid.html": [
@@ -389821,11 +395133,11 @@
"support"
],
"conformance-checkers/html-svg/animate-elem-90-b-isvalid.html": [
- "5c18ff07cb929e65eb9222831d1e109255f9f078",
+ "1211f66d533725e2ae8d9bddb1964a26c9ab5820",
"support"
],
"conformance-checkers/html-svg/animate-elem-91-t-isvalid.html": [
- "b9acbaeeb5866c191915143dafbb88db16899035",
+ "0f6f9a118e0727d846c07e3c6aafebca695b8a1d",
"support"
],
"conformance-checkers/html-svg/animate-elem-92-t-isvalid.html": [
@@ -390185,7 +395497,7 @@
"support"
],
"conformance-checkers/html-svg/filters-turb-02-f-isvalid.html": [
- "78d5a333b247e1c8c02530cf495f6a7feed634a5",
+ "ae4310846727cebacc09c028529a716f8cf09ddb",
"support"
],
"conformance-checkers/html-svg/fonts-desc-01-t-isvalid.html": [
@@ -390217,11 +395529,11 @@
"support"
],
"conformance-checkers/html-svg/fonts-elem-03-b-isvalid.html": [
- "45fd874162b71ccee5ae5fc3054b33f573d56c08",
+ "1406ce68111c8628588e8af93a816b80ced7792e",
"support"
],
"conformance-checkers/html-svg/fonts-elem-04-b-isvalid.html": [
- "3382c4004e5fc216eaf033732c44fac3ebb6961c",
+ "8fdaa02b1fb57a278997dfcfd8de59358c1a8c20",
"support"
],
"conformance-checkers/html-svg/fonts-elem-05-t-isvalid.html": [
@@ -390233,7 +395545,7 @@
"support"
],
"conformance-checkers/html-svg/fonts-elem-07-b-isvalid.html": [
- "99e555d3c6e39a62bfbeecd5a96acdf6d1a4f875",
+ "13246af933d7c55942b73947ab3504995b1bb744",
"support"
],
"conformance-checkers/html-svg/fonts-glyph-02-t-isvalid.html": [
@@ -390325,7 +395637,7 @@
"support"
],
"conformance-checkers/html-svg/interact-pevents-10-f-isvalid.html": [
- "5d137aff8110099676359bdb43bef36f0ee8f6b6",
+ "fda3638dafcca97f305c6056cbad755f8e4b43c7",
"support"
],
"conformance-checkers/html-svg/interact-pointer-01-t-isvalid.html": [
@@ -390341,7 +395653,7 @@
"support"
],
"conformance-checkers/html-svg/interact-pointer-04-f-isvalid.html": [
- "fc5923a5d8e74c0900e64425aa9c3116d71e5415",
+ "76a6c30090943843d2607992e2d7a6dea36134f9",
"support"
],
"conformance-checkers/html-svg/interact-zoom-01-t-isvalid.html": [
@@ -390413,7 +395725,7 @@
"support"
],
"conformance-checkers/html-svg/masking-mask-01-b-isvalid.html": [
- "86f649ce812d1754013761b1578333f28aefc6cc",
+ "6d916c4fb24db24f4e244a3906e2750b73d4e36f",
"support"
],
"conformance-checkers/html-svg/masking-mask-02-f-isvalid.html": [
@@ -390469,7 +395781,7 @@
"support"
],
"conformance-checkers/html-svg/masking-path-12-f-isvalid.html": [
- "b0387378e21fb9ef1450b18426924c5e3ddc2063",
+ "f13dace7dce3470b076d9bf77af872e9ee874004",
"support"
],
"conformance-checkers/html-svg/masking-path-13-f-isvalid.html": [
@@ -390537,7 +395849,7 @@
"support"
],
"conformance-checkers/html-svg/painting-marker-03-f-isvalid.html": [
- "19c5504836dfb92d40510cde6f467cca6ed12cde",
+ "bb3871c8cc0cfdba81ef4ec08e827b77f54240cc",
"support"
],
"conformance-checkers/html-svg/painting-marker-04-f-novalid.html": [
@@ -390545,7 +395857,7 @@
"support"
],
"conformance-checkers/html-svg/painting-marker-05-f-isvalid.html": [
- "9aba948fb721bc5b074772e9326b11324bae2479",
+ "4001dd917f17d7085197b0472549a5411a9fd6b9",
"support"
],
"conformance-checkers/html-svg/painting-marker-06-f-isvalid.html": [
@@ -390557,7 +395869,7 @@
"support"
],
"conformance-checkers/html-svg/painting-marker-properties-01-f-isvalid.html": [
- "894b51da314acdbbf80c278e6c053f91c5520ae8",
+ "ef266c0e0c0ce7b73c03dc5ca927f98b86cde4e8",
"support"
],
"conformance-checkers/html-svg/painting-render-01-b-isvalid.html": [
@@ -390721,7 +396033,7 @@
"support"
],
"conformance-checkers/html-svg/pservers-grad-08-b-isvalid.html": [
- "45817568696bffd2c59c1b29c349e9bc35a14f27",
+ "5f425fd090508b9bb2f893134fef4b24dc62efe9",
"support"
],
"conformance-checkers/html-svg/pservers-grad-09-b-isvalid.html": [
@@ -390833,23 +396145,23 @@
"support"
],
"conformance-checkers/html-svg/render-elems-06-t-isvalid.html": [
- "374e29a6204f48b53608d58a06b42897d4eec2e7",
+ "ce7ae0d43978a2177871ef36c0b79578b265188e",
"support"
],
"conformance-checkers/html-svg/render-elems-07-t-isvalid.html": [
- "c7173373d787b8c0936603ef031fcff2cacde09e",
+ "dd067362aa8447e5d0cacab7c49bc757ed57b862",
"support"
],
"conformance-checkers/html-svg/render-elems-08-t-isvalid.html": [
- "cbd577e886e322e5ee292aeb12951c5c6e209db2",
+ "454ca0e9274c07dabe2616560210d3e8f30c9592",
"support"
],
"conformance-checkers/html-svg/render-groups-01-b-isvalid.html": [
- "fb6a45936a926dd4358ffaf3e1fecc481cfe966c",
+ "670cca23fb6eaed1f0b830bfc66612cb3247172a",
"support"
],
"conformance-checkers/html-svg/render-groups-03-t-isvalid.html": [
- "f82e73ed07769f73e7c058672e36a0ad28bba701",
+ "aae614973c8471f0f840ebd9b0c84a5f889549ec",
"support"
],
"conformance-checkers/html-svg/script-handle-01-b-isvalid.html": [
@@ -391037,7 +396349,7 @@
"support"
],
"conformance-checkers/html-svg/struct-dom-13-f-isvalid.html": [
- "6a2a71827d9d0e6b5f8f7101d088ba7598cc6164",
+ "1eb76a92a5f8821af0e4feb66197f0b5b30f7834",
"support"
],
"conformance-checkers/html-svg/struct-dom-14-f-isvalid.html": [
@@ -391049,19 +396361,19 @@
"support"
],
"conformance-checkers/html-svg/struct-dom-16-f-isvalid.html": [
- "3d0e1a2fb739c745dff8e986dfd90abeab3b94c5",
+ "6d144891e2a947b723f7d4125943bd29b5a5979b",
"support"
],
"conformance-checkers/html-svg/struct-dom-17-f-novalid.html": [
- "9c80ab5c4313f6db48f9f749624d8b5bf74a9d79",
+ "050c76ad66ded814a0bad0843588526ec463261a",
"support"
],
"conformance-checkers/html-svg/struct-dom-18-f-isvalid.html": [
- "b10b2269cb2b28fbb0acfefbba99d09e9726d884",
+ "0c6df2c514de06387e6e15ac61f26d70406632db",
"support"
],
"conformance-checkers/html-svg/struct-dom-19-f-novalid.html": [
- "562c226f83e41995bdf5d636aee52742baa535b4",
+ "a0201a7da16de8bb775e218f2037cedb38c42d63",
"support"
],
"conformance-checkers/html-svg/struct-dom-20-f-isvalid.html": [
@@ -391181,11 +396493,11 @@
"support"
],
"conformance-checkers/html-svg/struct-svg-01-f-isvalid.html": [
- "11a7bc3c616311e2fd8a9cd38c786ff0719e5702",
+ "5bc007fad67cc5b1081730c69ad1ed7bf3ef82c6",
"support"
],
"conformance-checkers/html-svg/struct-svg-02-f-isvalid.html": [
- "4126b74298f58742d9185cc14f023159926c7f26",
+ "2cfbeb2364a6de41f9641c41441843bcff9f644b",
"support"
],
"conformance-checkers/html-svg/struct-svg-03-f-isvalid.html": [
@@ -391229,11 +396541,11 @@
"support"
],
"conformance-checkers/html-svg/struct-use-10-f-isvalid.html": [
- "0903f45dbc87b29b14e4237e41e36fc8ee65f884",
+ "eeb7439fb70da73249e803b8e8480da0ccc194fd",
"support"
],
"conformance-checkers/html-svg/struct-use-11-f-novalid.html": [
- "54766246e44dfd53548ceb733fbdf9074581f8e6",
+ "4b185477eab79704b455aed8d5bab2afdae9991e",
"support"
],
"conformance-checkers/html-svg/struct-use-12-f-novalid.html": [
@@ -391245,39 +396557,39 @@
"support"
],
"conformance-checkers/html-svg/struct-use-14-f-isvalid.html": [
- "1a73e4b3afec59a3b1bb078df4b9173a1493c617",
+ "b9b52218645613654a1246777aa52077f3c86047",
"support"
],
"conformance-checkers/html-svg/struct-use-15-f-isvalid.html": [
- "60bc0106463fdeaf97bf1ffce0284baed7c1aad3",
+ "d40145cab642bf8bf5dd588e8bee0f56a21cd85d",
"support"
],
"conformance-checkers/html-svg/styling-class-01-f-isvalid.html": [
- "b25098191314cb5a528665fbbab8ec529d723469",
+ "0f592aac2c8ff79e7b8a96b6f61346c56fc3b050",
"support"
],
"conformance-checkers/html-svg/styling-css-01-b-isvalid.html": [
- "65456b1c4ea7f5d0cce1610eb35387db89b62d97",
+ "502137765bb11ee3d5290a62ab25e8162b0d01d0",
"support"
],
"conformance-checkers/html-svg/styling-css-02-b-isvalid.html": [
- "4e2fc40cc418fd59598b5fe656fbb5ba44e9db30",
+ "0686e1ea236b67c301fa258a244cbcb8e19dffb9",
"support"
],
"conformance-checkers/html-svg/styling-css-03-b-isvalid.html": [
- "1ceb14dc956bbd243308a7ce2b9f0dbaf677ebe9",
+ "0e001287f80c7ae63836b25760577562c9794741",
"support"
],
"conformance-checkers/html-svg/styling-css-04-f-isvalid.html": [
- "377ffc2b8f1c3c07113d549ecc9a36898e93a1d9",
+ "079aed55ff1e69da19f2f2a11daa03d28ef05c00",
"support"
],
"conformance-checkers/html-svg/styling-css-05-b-isvalid.html": [
- "ed1ce9cabf6bd7d04620a8d7ff23dbf814ff0ae0",
+ "b4523f395a30231b663380713f9136d86db9199f",
"support"
],
"conformance-checkers/html-svg/styling-css-06-b-isvalid.html": [
- "ac602ee8848bdeb0329b44f38441c8c54f858256",
+ "4c2ef4d223d71a89cdab39dfee3af30a7e20947e",
"support"
],
"conformance-checkers/html-svg/styling-css-07-f-isvalid.html": [
@@ -391285,15 +396597,15 @@
"support"
],
"conformance-checkers/html-svg/styling-css-08-f-isvalid.html": [
- "46df1bccf4665493887a587d187edb631c666a09",
+ "a89e2936dc2dc57c7b0cef59d87295db4fc7b1f6",
"support"
],
"conformance-checkers/html-svg/styling-css-09-f-isvalid.html": [
- "6dbbcdfdfc6ce72bd29f8aefc75853026c1cc901",
+ "987a5a85c90666ba7c88f0a34f41b00970606e64",
"support"
],
"conformance-checkers/html-svg/styling-css-10-f-isvalid.html": [
- "63e67a1071cb83fa384578c4c5080039e11a0fb4",
+ "38c267e1ed3632cb6af81000b30f7b429856a2ff",
"support"
],
"conformance-checkers/html-svg/styling-elem-01-b-isvalid.html": [
@@ -391317,11 +396629,11 @@
"support"
],
"conformance-checkers/html-svg/styling-pres-04-f-isvalid.html": [
- "3ca9ada2290ec7db5d8c2480b18df505799c596c",
+ "76478896e0022cc5b647825a8ac7c167cbf52b98",
"support"
],
"conformance-checkers/html-svg/styling-pres-05-f-isvalid.html": [
- "3cb1fd7f158bef03fc4893f6c99a3db0cba3dfa1",
+ "700a9d92bf2f649e325ef3ddaf1292adab443a89",
"support"
],
"conformance-checkers/html-svg/svgdom-over-01-f-novalid.html": [
@@ -391357,7 +396669,7 @@
"support"
],
"conformance-checkers/html-svg/text-align-08-b-isvalid.html": [
- "92aeb0eaa3468c34910b62ccf833d066463c239b",
+ "821fa951273afd7899d3ab3179b274d85f47adee",
"support"
],
"conformance-checkers/html-svg/text-altglyph-01-b-isvalid.html": [
@@ -391385,7 +396697,7 @@
"support"
],
"conformance-checkers/html-svg/text-dom-02-f-isvalid.html": [
- "c555e032b8d6e50e121ccb22a0bb367b19c30f3a",
+ "f4d8ef1f3b7978bed5ac416683be55780e9c2919",
"support"
],
"conformance-checkers/html-svg/text-dom-03-f-novalid.html": [
@@ -391397,7 +396709,7 @@
"support"
],
"conformance-checkers/html-svg/text-dom-05-f-isvalid.html": [
- "a467dbf921d7886c7f2ed1ed24bcd2aaca3b4f26",
+ "56fb513d999d2bb5b04838bcb433e7b8484cc753",
"support"
],
"conformance-checkers/html-svg/text-fonts-01-t-isvalid.html": [
@@ -391429,7 +396741,7 @@
"support"
],
"conformance-checkers/html-svg/text-fonts-204-t-isvalid.html": [
- "fa3d50e70395fd486a0b0b9662edca2f1bdfc9df",
+ "344bbda75a9b43f3773481fdb8ebdc02ca88c139",
"support"
],
"conformance-checkers/html-svg/text-intro-01-t-isvalid.html": [
@@ -391453,7 +396765,7 @@
"support"
],
"conformance-checkers/html-svg/text-intro-06-t-isvalid.html": [
- "47a36baa657b2ab4cf19157bcf91a8920c090a50",
+ "a05ed454500df7ea92095806199ac128e8808c70",
"support"
],
"conformance-checkers/html-svg/text-intro-07-t-isvalid.html": [
@@ -391461,7 +396773,7 @@
"support"
],
"conformance-checkers/html-svg/text-intro-09-b-isvalid.html": [
- "313f648a45a65000ffbe6a829686190b169cb0de",
+ "48df2f1d46ab3d9f4185f03a1a3d0e3b4c3e5176",
"support"
],
"conformance-checkers/html-svg/text-intro-10-f-isvalid.html": [
@@ -391473,7 +396785,7 @@
"support"
],
"conformance-checkers/html-svg/text-intro-12-t-isvalid.html": [
- "21ba8ee506fb4a9f9cdc80cb85a185840d6bcf03",
+ "ee4e586b2eb44204ede5354466df0ec1335a5a2d",
"support"
],
"conformance-checkers/html-svg/text-path-01-b-isvalid.html": [
@@ -391481,7 +396793,7 @@
"support"
],
"conformance-checkers/html-svg/text-path-02-b-isvalid.html": [
- "d1d7e408a6a464bcff5e8555610099549b6804cc",
+ "f77392b5da7a2163f64495963e4e87d6e0fc4d63",
"support"
],
"conformance-checkers/html-svg/text-spacing-01-b-isvalid.html": [
@@ -391497,15 +396809,15 @@
"support"
],
"conformance-checkers/html-svg/text-text-04-t-isvalid.html": [
- "49ca6d0539d8610cd50522b646129442cb1b1d4e",
+ "88ccdd31ecbf13986c3cd336f0d66f85ab3182b3",
"support"
],
"conformance-checkers/html-svg/text-text-05-t-isvalid.html": [
- "3fddf7f8c6fe485fc80ea6467f66037e3c63a4eb",
+ "5173e61b13f9f62b20b99743dca202da11345771",
"support"
],
"conformance-checkers/html-svg/text-text-06-t-isvalid.html": [
- "384a8f470255e3cf8f0e725ed2495281e7ef960f",
+ "842a8dbc81ef460e4d9f0b19244e5ca611584984",
"support"
],
"conformance-checkers/html-svg/text-text-07-t-isvalid.html": [
@@ -391529,7 +396841,7 @@
"support"
],
"conformance-checkers/html-svg/text-text-12-t-isvalid.html": [
- "3e5cd8bd712619121082c9f265cf17e5f48845db",
+ "e922e41c86c881d63e7360ffaa5ae91915d3aa5e",
"support"
],
"conformance-checkers/html-svg/text-tref-01-b-isvalid.html": [
@@ -391545,7 +396857,7 @@
"support"
],
"conformance-checkers/html-svg/text-tselect-03-f-isvalid.html": [
- "5c123a50b6afdd52852170f6ffd8b2e1ee88e27d",
+ "6980a2c8b5f4e006893d6df5a91922ae775516ea",
"support"
],
"conformance-checkers/html-svg/text-tspan-01-b-isvalid.html": [
@@ -391597,23 +396909,23 @@
"support"
],
"conformance-checkers/html-svg/types-dom-svgfittoviewbox-01-f-isvalid.html": [
- "51915fa4c49e811bdf6fafb3609f91ae487581eb",
+ "42a856696a25493f49818e4cc68e5dd6af473ba7",
"support"
],
"conformance-checkers/html-svg/types-dom-svglengthlist-01-f-isvalid.html": [
- "5b166a8070280178591e90b7326a046e1b447b3a",
+ "9536d27904a04d03920476f7c5300fc2ca22ccd5",
"support"
],
"conformance-checkers/html-svg/types-dom-svgnumberlist-01-f-isvalid.html": [
- "fc3c1a8a8e39529941f21a215c9360b9c43060a0",
+ "9c40558341d0c92f34b7d9c0462e8463185703d0",
"support"
],
"conformance-checkers/html-svg/types-dom-svgstringlist-01-f-isvalid.html": [
- "b528dadf838e7862d851262e6f04ec46f3e5ea83",
+ "40cd5ddffd205fb2bdc14a64e4ff92cbd5c8660b",
"support"
],
"conformance-checkers/html-svg/types-dom-svgtransformable-01-f-isvalid.html": [
- "6d496e2790f0d7623bd6e3c0988539a459cc3d5b",
+ "14c50bec4c35e0b8b3dfd03e5b7362f4dc95073f",
"support"
],
"conformance-checkers/html/Makefile": [
@@ -399912,8 +405224,12 @@
"7a669924345c81629052168ee70e7b82035bf25d",
"support"
],
+ "conformance-checkers/html/elements/style/html-spec-comms-isvalid.html": [
+ "5a5c97af316b5eedb093cea453ba58a1a32e975a",
+ "support"
+ ],
"conformance-checkers/html/elements/style/model-isvalid.html": [
- "95edf20c9686883cbc6e715fc8654f0bf1071de5",
+ "00b0870d863f5512002fe8af7d8e9874676e5d4c",
"support"
],
"conformance-checkers/html/elements/style/scoped-as-div-child-novalid.html": [
@@ -399940,6 +405256,10 @@
"198284a6acc5e69361554fa8d9a6720ee77996c2",
"support"
],
+ "conformance-checkers/html/elements/style/type-novalid.html": [
+ "1dd8d1cf5c9165209cb211d0d9c154d02b413636",
+ "support"
+ ],
"conformance-checkers/html/elements/sub/model-isvalid.html": [
"9993643406c23f0f5f607cc7895cd35ff00ae919",
"support"
@@ -401793,11 +407113,11 @@
"support"
],
"conformance-checkers/index.html": [
- "7a82e657e375abbdd2794ae24db859c4bda7cd08",
+ "7eaf95edd9b09087f815850be12dc8efa5592f76",
"support"
],
"conformance-checkers/messages.json": [
- "77e43d470fe6884315c194bb64b0acec88e29827",
+ "17e9506c7b34532366ba3f473a01e0a7e88eefdd",
"support"
],
"conformance-checkers/tools/build-svg-tests.py": [
@@ -402308,6 +407628,14 @@
"19d2027dc8784a479722b7f405fee31973808e2f",
"testharness"
],
+ "content-security-policy/base-uri/report-uri-does-not-respect-base-uri.sub.html": [
+ "7dd8bccbd166c7ac938699c406bc2209a7f5677f",
+ "testharness"
+ ],
+ "content-security-policy/base-uri/report-uri-does-not-respect-base-uri.sub.html.sub.headers": [
+ "6adacb07a9ade6e135b5c24ef658384d26ed2dff",
+ "support"
+ ],
"content-security-policy/blob/blob-urls-do-not-match-self.sub.html": [
"8fb0231ccaff9062464119096a4ae89c04216b42",
"testharness"
@@ -402856,6 +408184,14 @@
"7e092f21440fffed98068f59bd2ddfd09a683515",
"testharness"
],
+ "content-security-policy/generic/policy-inherited-correctly-by-plznavigate.html": [
+ "11de7fcc2fd1ca6e2277b22a53a2c2c7ba11aa2c",
+ "testharness"
+ ],
+ "content-security-policy/generic/policy-inherited-correctly-by-plznavigate.html.sub.headers": [
+ "0ca17bc3c1370af097fdb2ee803cc802c7e58718",
+ "support"
+ ],
"content-security-policy/generic/positiveTest.js": [
"92b715fcc3269e189318734739a5e4fb620d9dff",
"support"
@@ -402940,6 +408276,10 @@
"3121f2277196e721af7d8cd522be148c875c79bd",
"testharness"
],
+ "content-security-policy/inheritance/inherited-csp-list-modifications-are-local.html": [
+ "b11ead62cbc23529449cdfd5dceba1058c1127b8",
+ "testharness"
+ ],
"content-security-policy/inheritance/window.html": [
"5a59b9b239186ad49aa1928f0beb9cf4234b4a6e",
"testharness"
@@ -403061,7 +408401,7 @@
"testharness"
],
"content-security-policy/nonce-hiding/script-nonces-hidden.tentative.html": [
- "c3265d6ead066201f712aa06beac162f365dd058",
+ "44982a605aaef57edfd9bbd9af98b1eee8d9ba1d",
"testharness"
],
"content-security-policy/nonce-hiding/script-nonces-hidden.tentative.html.headers": [
@@ -403177,7 +408517,7 @@
"support"
],
"content-security-policy/reporting/securitypolicyviolation-idl.html": [
- "3f0b501b2ef45c7c59b3654b4f2aa2fed7710a7a",
+ "831948d2397790fa68e6d8bc96454dcb2f3e3280",
"testharness"
],
"content-security-policy/sandbox/iframe-inside-csp.sub.html": [
@@ -403276,6 +408616,10 @@
"e8583f7292cd90aa13e0e997aedf41763eb18928",
"support"
],
+ "content-security-policy/script-src/nonce-enforce-blocked.html": [
+ "79bb6635e0964eef935cc2c9e93ff68034353f55",
+ "testharness"
+ ],
"content-security-policy/script-src/script-src-1_1.html": [
"b4285b63b3f9a8fab266ac93b3b7c1a70a7bdfcc",
"testharness"
@@ -403613,7 +408957,7 @@
"testharness"
],
"content-security-policy/securitypolicyviolation/idl.html": [
- "5f2ff4a87aa476168cf3d13b10a8d81a387b8e42",
+ "fb8f2938d76a29cc68c46fb49a12feebc0031e54",
"testharness"
],
"content-security-policy/securitypolicyviolation/img-src-redirect-upgrade-reporting.https.html": [
@@ -403769,7 +409113,7 @@
"testharness"
],
"content-security-policy/style-src/style-src-imported-style-blocked.html": [
- "e59517d75d3fbc29b701ffa296b7dd007a05c79d",
+ "a7d3453f54478b773e4d5702a7d83f0a38664f19",
"testharness"
],
"content-security-policy/style-src/style-src-injected-inline-style-allowed.html": [
@@ -403888,6 +409232,10 @@
"76e9a5bdd43e13f9665135c7178dbca3114eb11e",
"support"
],
+ "content-security-policy/support/fail.html": [
+ "7825725abb38ec93b6d9122f05ea58f3b1bc4601",
+ "support"
+ ],
"content-security-policy/support/fail.js": [
"90d888b42df7812ab893788918fac7cdaf27d1d6",
"support"
@@ -403924,6 +409272,10 @@
"53203da2c93399cdc4c3355a60d098c203cc7c85",
"support"
],
+ "content-security-policy/support/nonce-should-be-blocked.js": [
+ "ec8990a2902e37798bb3dc6b0ba66495066c6e6b",
+ "support"
+ ],
"content-security-policy/support/pass.png": [
"c06160c04726a02f1583caa0f380d632b6019179",
"support"
@@ -403965,7 +409317,7 @@
"support"
],
"content-security-policy/svg/including.sub.svg": [
- "4a7db45f8feeee77456ef0f837210b6f2f734a47",
+ "6e6534212bf7ac65d317b06ad7d9b719e6123b09",
"support"
],
"content-security-policy/svg/including.sub.svg.sub.headers": [
@@ -404112,192 +409464,248 @@
"ff4d7ca289ea20fa00bca535fdcf929876a2278b",
"testharness"
],
+ "cookie-store/OWNERS": [
+ "9e68d9eb0784e10786bd8b0c6009afb42516acdc",
+ "support"
+ ],
+ "cookie-store/README.md": [
+ "f2c101203c2a2d82a4191164943e79734530d124",
+ "support"
+ ],
+ "cookie-store/cookieStore_delete_arguments.tentative.window.js": [
+ "f33ce9a975c759ce6da8a5caa371ca026dd537c4",
+ "testharness"
+ ],
+ "cookie-store/cookieStore_getAll_arguments.tentative.window.js": [
+ "cf818fe92c16dfe42f0ac778f665094533d8ab10",
+ "testharness"
+ ],
+ "cookie-store/cookieStore_getAll_set_basic.tentative.window.js": [
+ "e6349dab874b99050cbbf5012db93de50612ce56",
+ "testharness"
+ ],
+ "cookie-store/cookieStore_get_arguments.tentative.window.js": [
+ "944e71f01e0d9b9b00f36fff2b84d6a9b93538e1",
+ "testharness"
+ ],
+ "cookie-store/cookieStore_get_delete_basic.tentative.window.js": [
+ "0b8c7725e0824d82c049a45e428a332212419bfd",
+ "testharness"
+ ],
+ "cookie-store/cookieStore_get_set_basic.tentative.window.js": [
+ "7439e63ae3e5b06a43ab168ece73123f90712f25",
+ "testharness"
+ ],
+ "cookie-store/cookieStore_has_arguments.tentative.window.js": [
+ "7512c46b8c7ec0b3ce33e3182671cc8c726a5e4e",
+ "testharness"
+ ],
+ "cookie-store/cookieStore_has_basic.tentative.window.js": [
+ "c53d313cebc3970e28d87c69a5d13a1b5e81529b",
+ "testharness"
+ ],
+ "cookie-store/cookieStore_in_detached_frame.tentative.html": [
+ "600452c1a496b8335b27bd24943b8834e37bf4d5",
+ "testharness"
+ ],
+ "cookie-store/cookieStore_set_arguments.tentative.window.js": [
+ "27019d0e79b6754715a292f40e064de53daaf5e8",
+ "testharness"
+ ],
+ "cookie-store/cookieStore_special_names.tentative.html": [
+ "d1cfe7619cc915b17dbf4d358363b16ec8ba9666",
+ "testharness"
+ ],
"cookie-store/cookie_store_tests.tentative.html": [
- "a370f31b8f2c0953e0230f377f3a06b5f6c74d9e",
+ "245e7096ba810ae0c2311a801845ce0355f1ff75",
"testharness"
],
"cookie-store/cookie_store_tests.tentative.https.html": [
- "706f99692c2712fefc6555693bd8193ef824af2b",
+ "80e5f99d4e0b66f2d610c1f2826cb4553d532676",
"testharness"
],
"cookie-store/cookie_store_tests_static.tentative.html": [
- "b8c90332eb487b2084a0ca011d2acda868fc1a36",
+ "4c02698eec209e52ba2203f9e0a82d84a029ee0f",
"testharness"
],
"cookie-store/cookie_store_tests_static.tentative.https.html": [
- "92b427911ef551a8fe45ba9815806ece173dcf2a",
+ "3ab3e4103cc30105fbab3db789891309d0e76428",
"testharness"
],
"cookie-store/delete_cookies.tentative.html": [
- "f78bef2c934bac010d000331d69aa923a6c2d6fb",
+ "0ca53252ef4ee4609613775229d3365ad1ffeafc",
"testharness"
],
"cookie-store/delete_cookies.tentative.https.html": [
- "553e933c0aec3eacb23f02994f4ccf598391fc49",
+ "5c5323abea15eb3649fa9b8ccc5075964bcf157b",
"testharness"
],
"cookie-store/delete_cookies_static.tentative.html": [
- "8657475cda36f15a81a3aa83aff32d5eb680d05d",
+ "c2869a65f9ca8834e8b3e463ace14e651bafd4aa",
"testharness"
],
"cookie-store/delete_cookies_static.tentative.https.html": [
- "f5ad565786a1d54dc445ac7249cbb4159957df7c",
+ "77f4da0946bbe53224a33014dd17216fdd20a07d",
"testharness"
],
"cookie-store/document_cookie.tentative.html": [
- "336ba25988a44701027c7cfd70efa9f11d8a389b",
+ "6664e739c03c46c164cfc5dbfdb786123417e5a8",
"testharness"
],
"cookie-store/document_cookie.tentative.https.html": [
- "db08e7cbb72b5e1af56a58458fc0cff6415fbd91",
+ "a51cc13bdb5b92a535fee3fec1b130e3b27cbcba",
"testharness"
],
"cookie-store/document_cookie_static.tentative.html": [
- "d7844a369785a2150a81f95bba4bfe7fc4bfc687",
+ "1ea750d2ba36d4f90e2c586f3ead9d80d8b353ac",
"testharness"
],
"cookie-store/document_cookie_static.tentative.https.html": [
- "4af584983ef1c52accab44a23ad543bbd7291404",
+ "fbd6d1a628df1b8afa6941f2279697ff0a2677a8",
+ "testharness"
+ ],
+ "cookie-store/document_getAll_multiple.tentative.html": [
+ "179f3ffe69715f9767ec2d2ef661c429fef52bc6",
"testharness"
],
"cookie-store/expiration.tentative.html": [
- "18435a38d1239d8b12b892018ea00e2fe0fd92f4",
+ "9bfb18862c9b9f6ace5f97ceb4f9d1da15eed64d",
"testharness"
],
"cookie-store/expiration.tentative.https.html": [
- "1c123dd08eb978ceb09263df4b512b5a321c132b",
+ "8f1aaa4a1b0ebf0c99f6d92f1e70e02d9a23c249",
"testharness"
],
"cookie-store/expiration_static.tentative.html": [
- "f71f95dec014e89bfaf8a26baf2d60c4d72a9611",
+ "7a308f48f5c51ddf4df04069259f7d3feff4cc8e",
"testharness"
],
"cookie-store/expiration_static.tentative.https.html": [
- "e7fe4735b9ccbadde6829e10109234bb7fa59328",
+ "d708add276da0fc58b6b628f05bacaa2965795ca",
"testharness"
],
"cookie-store/get_set_get_all.tentative.html": [
- "70e71c3cba821a1d97d53876b72bbd4ed0f6e976",
+ "dc66cbf2b2a939179cae29aaeb39cb44eb488e2a",
"testharness"
],
"cookie-store/get_set_get_all.tentative.https.html": [
- "61ec0e51fc907c4dd6186c8499cf0bdfd6aad8fe",
+ "8359d66bc5de963f57596033d29eca513f30ef79",
"testharness"
],
"cookie-store/get_set_get_all_static.tentative.html": [
- "4a339b426b1cc31af1d2b252fb728784de82c0c9",
+ "17f09f2aa4f41bdfc7e0541309ea36b6af232380",
"testharness"
],
"cookie-store/get_set_get_all_static.tentative.https.html": [
- "efc155bfff9280aa6b782270a99b32d4943e95d8",
+ "d8f03ba31699bfad79e4d4870208fa3ad94c261a",
"testharness"
],
"cookie-store/http_cookie_and_set_cookie_headers.tentative.html": [
- "93a9d4fbbda70461745f7f62f9b6fe23f73b0c7e",
+ "42c03466979c5e6d94803d5e69b6c07a595e9728",
"testharness"
],
"cookie-store/http_cookie_and_set_cookie_headers.tentative.https.html": [
- "95e61ca3ce90e4665f7061f7739c01772e6852fe",
+ "11c763dd1b7b3a1bff14b9f65538fb33ca97b81b",
"testharness"
],
"cookie-store/meta_http_equiv_set_cookie.tentative.html": [
- "99d220e96f28fbd4b3cef89323e687e18e95ccf4",
+ "6b7dc5aaa1f3c765c45886017163b70520e5f367",
"testharness"
],
"cookie-store/meta_http_equiv_set_cookie.tentative.https.html": [
- "b632f52614c1ffcd9e460282c2b6ddc6408b941e",
+ "c1d942ff3fb24b77fd659f9e60bd385bbbfe2279",
"testharness"
],
"cookie-store/meta_http_equiv_set_cookie_static.tentative.html": [
- "52973785d2e988fb6543c1aa8f4cd093e9075afb",
+ "991dae7d02c9c1f03842bd9f43fdc21bfbf9f261",
"testharness"
],
"cookie-store/meta_http_equiv_set_cookie_static.tentative.https.html": [
- "9d9d04519d9a4916b28f7567a830c3a96bf163ed",
+ "36d0c3672f44335eb6a0a294b55cf61b9efecd03",
"testharness"
],
"cookie-store/no_name_and_no_value.tentative.html": [
- "97068e2af8b42537e75990dbd9138de530dc8d5f",
+ "634ceaac54e40d7227772abb097f029ce901876b",
"testharness"
],
"cookie-store/no_name_and_no_value.tentative.https.html": [
- "bd1fdaa9c1e5266987d3b85bcecd5fe47fb2e6aa",
+ "c943068f523d6345abfeec24135438fc88fad8de",
"testharness"
],
"cookie-store/no_name_and_no_value_static.tentative.html": [
- "040357b08945c44bb8453deec5ed97393ecc8361",
+ "073a939169dafa7685c02ebdd51653d8f5c49df5",
"testharness"
],
"cookie-store/no_name_and_no_value_static.tentative.https.html": [
- "4e9a265483bbcc0469ecb22db4bb61a28ba7ae3c",
+ "a67b186ef0d5393c0bcf8dab8870a76384e14bcf",
"testharness"
],
"cookie-store/no_name_equals_in_value.tentative.html": [
- "189c847e82ff403f2d1836d88e2af8c5db345f3d",
+ "22273b9be0e44dc35a59b701733265d8f538aeb1",
"testharness"
],
"cookie-store/no_name_equals_in_value.tentative.https.html": [
- "cd6a35a4763ba7b0bca2d29a21b4800c5b6424eb",
+ "351b8ac618717bb7a8205cee65678a72a7df7450",
"testharness"
],
"cookie-store/no_name_equals_in_value_static.tentative.html": [
- "b12e7a43303372ddde410688e26ae027228dea09",
+ "84f03808a8c20ed1809c682982719c5fab1d6b34",
"testharness"
],
"cookie-store/no_name_equals_in_value_static.tentative.https.html": [
- "f1ee338299654bb44f4e867dcbacd3aafe4acef5",
+ "cb98e1c8c370e1415dd51cec75be7c4f1c933a18",
"testharness"
],
"cookie-store/no_name_multiple_values.tentative.html": [
- "7e65cf3f0ed8e5e2722279805a34ed95444413d5",
+ "864d3955cf9a92ec4bddf00b19fdb471c691e3cd",
"testharness"
],
"cookie-store/no_name_multiple_values.tentative.https.html": [
- "0b5bd1414b928dedaa72db393a0a7bc79bb04f98",
+ "e4671297e2474c38e73cd76268f7cdd53eb46b28",
"testharness"
],
"cookie-store/no_name_multiple_values_static.tentative.html": [
- "daebad2df149f4b79998d7e10d51c27d34596487",
+ "2bb6d547e7ac220a1c36172dfd2c59e36b49c520",
"testharness"
],
"cookie-store/no_name_multiple_values_static.tentative.https.html": [
- "3e45ea4cde17c549f8761e143472e0862797fd6d",
+ "e10639064527c376420fb51cc5ef5137069dec7b",
"testharness"
],
"cookie-store/observation.tentative.html": [
- "f2b16274bdd2c2f2117a0bfa126ae2d783211169",
+ "e0029a6a2cbe1e696cc3afeae9c30b245218d672",
"testharness"
],
"cookie-store/observation.tentative.https.html": [
- "06f7ca48269b7bdc9a408c99df687e3af1eae5c4",
+ "954a81b8bac1fae57b8074ca3f15210806622bfb",
"testharness"
],
"cookie-store/observation_static.tentative.html": [
- "8137d847b0d091dfb6a0cec6275942fb5234b296",
+ "8f6c1a6cc4e671162c6aa7d26d829dc9866d69bd",
"testharness"
],
"cookie-store/observation_static.tentative.https.html": [
- "6779d29a8e11c88f8adf2327c54b397d8d5b3fd9",
+ "007ec0bb007aa3b2d6855e9364ea0d8e269999a2",
"testharness"
],
"cookie-store/one_simple_origin_cookie.tentative.html": [
- "56737fe668c83b89b967c8a9edbbcbd314a7c087",
+ "f96fb6627746fd1e586d959249b28886ea8ba504",
"testharness"
],
"cookie-store/one_simple_origin_cookie.tentative.https.html": [
- "943f3a50da17574a393af9a18c791b80c9f6209e",
+ "b31ea6c06f2e5ecaabdaa3e28efef0e012a65cb4",
"testharness"
],
"cookie-store/one_simple_origin_cookie_static.tentative.html": [
- "f28f4dfd2cac6be784ff106080d59962d6a1d2f8",
+ "d9064910e2771a2ea5337f5470299c71d831b62a",
"testharness"
],
"cookie-store/one_simple_origin_cookie_static.tentative.https.html": [
- "4d8ffa9f27e62e5893777b8a6c35a97fa002709b",
+ "15449e84b8a2854243b0efabca7e893d1ab427dd",
"testharness"
],
"cookie-store/resources/cookie-store-tests.js": [
- "5d779c03a170a2a3fe210c28c027b90d7e74dbda",
+ "5f314a536820d78418a558e588af478154e33369",
"support"
],
"cookie-store/resources/cookie_helper.py": [
@@ -404305,17 +409713,45 @@
"support"
],
"cookie-store/resources/testharness-helpers.js": [
- "ace8944b16bb4b7d1b2261b4f8ef549daff7fc7e",
+ "b7bc4516ad4ac7ae1bb572191c0c3932c29eb863",
+ "support"
+ ],
+ "cookie-store/serviceworker_cookieStore_arguments.js": [
+ "a90956237d63fd51556f2d9e50967522870816d4",
+ "support"
+ ],
+ "cookie-store/serviceworker_cookieStore_arguments.tentative.https.html": [
+ "3b74e70504793eb570fd15851fac53146af4b86d",
+ "testharness"
+ ],
+ "cookie-store/serviceworker_cookieStore_basic.js": [
+ "38fe0bc6fbf08e5387f81e32348252c481af03c0",
+ "support"
+ ],
+ "cookie-store/serviceworker_cookieStore_basic.tentative.https.html": [
+ "0700dc72bc1e00832546d4a6826a5474600af06c",
+ "testharness"
+ ],
+ "cookies/OWNERS": [
+ "15417c1a9e90762ae826b0258fe3619cc6a78b0e",
"support"
],
- "cookies/path/echo-cookie.html": [
- "cbb91823a75f6e5c5ae435c5bc4c3b15a09c483e",
+ "cookies/README.md": [
+ "1949878db1be4093ec8d9595710f9fd8887434ba",
"support"
],
+ "cookies/meta-blocked.html": [
+ "1ece2f38a340ff4ff4713ada5568281d0e1c5be2",
+ "testharness"
+ ],
"cookies/path/match.html": [
- "f0a64d36154617213cbe846eb5ef0c93f7a65556",
+ "a54ac9afd9c176da2c8844389feb3cb0150fcf5c",
"testharness"
],
+ "cookies/resources/echo-cookie.html": [
+ "ac15291ad85804f61bf690525bad958bb2672ca0",
+ "support"
+ ],
"cookies/resources/echo-json.py": [
"c5b3d11bdfc3a4092d0ed53648d58e0e3bbd2d91",
"support"
@@ -404352,7 +409788,7 @@
"b1b6ee4d317f108574453da7410f91d52eecdf83",
"support"
],
- "cookies/secure/set-from-ws.https.sub.html": [
+ "cookies/secure/set-from-ws.sub.html": [
"2d60b86d8beaa5b3329c804949c7ee0d51d929c3",
"testharness"
],
@@ -404433,7 +409869,7 @@
"manual"
],
"core-aam/aria-checked_value_changes-manual.html": [
- "1b60088a1e7441cd4074fec2f674d9f055e5841e",
+ "ab6b990cc593eb6f135b78af886b41e4a69fb752",
"manual"
],
"core-aam/aria-colcount_new-manual.html": [
@@ -404525,11 +409961,11 @@
"manual"
],
"core-aam/aria-expanded_value_changes-manual.html": [
- "4695aed01e4473c45e723f1e21bfff74c1231a98",
+ "b1e42b76a3088ce00494366f53a5d696d4ee914e",
"manual"
],
"core-aam/aria-flowto-manual.html": [
- "ab781f7aed85fbb840bb3b38e1b16897d0cb9b20",
+ "aa2b63438ffe1ce2dad9073cd0065f70b4002630",
"manual"
],
"core-aam/aria-grabbed_false-manual.html": [
@@ -404673,7 +410109,7 @@
"manual"
],
"core-aam/aria-owns_may_need_manual_verification-manual.html": [
- "13e3796ff854b458a0319709f04f1aae2a11f39a",
+ "4c6e3d6fedc2ed371b957e99c286c78983d19898",
"manual"
],
"core-aam/aria-placeholder_new-manual.html": [
@@ -404737,7 +410173,7 @@
"manual"
],
"core-aam/aria-roledescription_is_empty_or_whitespace_characters_new-manual.html": [
- "3962c1149025fb57e6e2ab3968c945f34a8d93f4",
+ "00496d1c81b91a2431606f4452a6084e312b0a81",
"manual"
],
"core-aam/aria-roledescription_new-manual.html": [
@@ -404801,7 +410237,7 @@
"manual"
],
"core-aam/aria-valuenow_value_changes-manual.html": [
- "25b56657fd81c6d75967b4e70e304d6c6e001e1e",
+ "313c1fa7c20afbc3047ab251ed32b860b5d5e15f",
"manual"
],
"core-aam/aria-valuetext-manual.html": [
@@ -405125,7 +410561,7 @@
"manual"
],
"core-aam/progressbar-manual.html": [
- "c4fd3f1c2a0762700aa7b05dff80b47123fdc2c5",
+ "0d0e4c44b9e953a00898a4c57a507bd976fa4aeb",
"manual"
],
"core-aam/radio-manual.html": [
@@ -405141,7 +410577,7 @@
"manual"
],
"core-aam/region_without_an_accessible_name_new-manual.html": [
- "a2a6f7766fe0b57726b6f7fb76de982b5830d510",
+ "2e89a57d2f7edd723224cc80695d57af2543b5b1",
"manual"
],
"core-aam/row_inside_treegrid-manual.html": [
@@ -405161,7 +410597,7 @@
"manual"
],
"core-aam/scrollbar-manual.html": [
- "1cec55790cb5b7394872df2b9003fde85b0ba176",
+ "a62bdc1ae12a5683d033925934287e44e4a3b94c",
"manual"
],
"core-aam/search-manual.html": [
@@ -405181,11 +410617,11 @@
"manual"
],
"core-aam/slider-manual.html": [
- "07890401b354c4374c234567296e6e3e8002b5da",
+ "b30c6f0835349083b3d8e5b4f45433cea928b26b",
"manual"
],
"core-aam/spinbutton-manual.html": [
- "d1b86e8184d1f4bf0120c14314d38b2b21db6155",
+ "d206a25f2379cd22b2394f92b4a52ac388e4667e",
"manual"
],
"core-aam/status-manual.html": [
@@ -405385,13 +410821,33 @@
"support"
],
"credential-management/credentialscontainer-create-basics.https.html": [
- "ee1e63bbe0d74a932650c2c32ed26d7ca41e1c7d",
+ "4889217f5e821965907d4d60a9ffdd19d4bc79af",
+ "testharness"
+ ],
+ "credential-management/federatedcredential-framed-get.sub.https.html": [
+ "561636e62d50da2d14e50516c62cbaea1c5bb924",
"testharness"
],
"credential-management/idl.https.html": [
"e9a108beef51c52bbaaf2e53371aec57e69541c0",
"testharness"
],
+ "credential-management/passwordcredential-framed-get.sub.https.html": [
+ "3ce3b0a2eaa10928aec1f32c9e3bcbe2af5fafba",
+ "testharness"
+ ],
+ "credential-management/support/echoing-nester.html": [
+ "408bf741f31a9f69a2a9a50d93877f6a999cd9d9",
+ "support"
+ ],
+ "credential-management/support/federatedcredential-get.html": [
+ "59b8314b8cb9044bfccf6a2a0e520a879fdf9f66",
+ "support"
+ ],
+ "credential-management/support/passwordcredential-get.html": [
+ "cfed192579bfc57c2d266b9d4f30b669c3fccc0c",
+ "support"
+ ],
"css/.gitignore": [
"3f645ca3bf6a77220d48e3e07b6dc3e1653d883c",
"support"
@@ -407337,7 +412793,7 @@
"reftest"
],
"css/CSS2/backgrounds/background-color-030.xht": [
- "9e0fe96277f3ecbf27b966e7484e600f26bc946a",
+ "1ee6e42bf37f7ecd91e6bd7b962cc52413dd534f",
"reftest"
],
"css/CSS2/backgrounds/background-color-031.xht": [
@@ -407989,7 +413445,7 @@
"reftest"
],
"css/CSS2/backgrounds/background-color-174.xht": [
- "b81fb760dd55ffac95b733cb2d6ca7034c502cc7",
+ "c42029d2c4d36d343bb75c7e12134008a8a4f838",
"reftest"
],
"css/CSS2/backgrounds/background-color-175-ref.xht": [
@@ -408085,7 +413541,7 @@
"reftest"
],
"css/CSS2/backgrounds/background-image-002.xht": [
- "12608a885087556cbf0ac4bd5d7e75756cb522c6",
+ "d828cc277fdfd302c8dc371d29138277a1043a41",
"reftest"
],
"css/CSS2/backgrounds/background-image-003.xht": [
@@ -419141,7 +424597,7 @@
"reftest"
],
"css/CSS2/colors/color-083-ref.xht": [
- "185b1887a6a4a8102f9f6ce5fb395fcb1598967b",
+ "314b144d6b2d0aecd2f53b419ff24a55181a31fe",
"support"
],
"css/CSS2/colors/color-083.xht": [
@@ -424032,6 +429488,14 @@
"040b4663df4744881121a6f88756cf562bedc50a",
"visual"
],
+ "css/CSS2/fonts/font-148-ref.xht": [
+ "9470c3fd45cff44705702939516ef69348bad4a5",
+ "support"
+ ],
+ "css/CSS2/fonts/font-148.xht": [
+ "1520e8283eb0769fba63e9dda3f0b8b0b6a8da00",
+ "reftest"
+ ],
"css/CSS2/fonts/font-applies-to-001-ref.xht": [
"e4c2fbe9a73859fb46ff14ce2d6f4401aca9d783",
"support"
@@ -425664,25 +431128,37 @@
"f5aa12ce214ee0b04a4e43248b990f95be97ece8",
"reftest"
],
+ "css/CSS2/generated-content/after-inheritable-001-ref.html": [
+ "31930c4d11b3f4afc155fd3a2a6cd7e0d376bb59",
+ "support"
+ ],
"css/CSS2/generated-content/after-inheritable-001.xht": [
- "39d768f9b5cafe0a283d99395b2b6c7950202387",
- "visual"
+ "5b82f2a029d5fea4fb52e66b83bb26b3ee8a5407",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/after-inheritable-002-ref.html": [
+ "6a8902b2e38e799bd4516c04ab1b01e4eb055145",
+ "support"
],
"css/CSS2/generated-content/after-inheritable-002.xht": [
- "7996c7ca5f496c41382ce154d74a8f1014cd80b4",
- "visual"
+ "6faa8965a8fb8e662c77bb14b06424a92aa65a74",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/after-location-001-ref.html": [
+ "646907ab4468bf43ee30e1ca353b1cd4efe8c820",
+ "support"
],
"css/CSS2/generated-content/after-location-001.xht": [
- "19df667583b6d3a485ea7e8e0df15e5ac8a8614e",
- "visual"
+ "d969663cc21c4af514775eea9951169aed497850",
+ "reftest"
],
"css/CSS2/generated-content/before-after-001.xht": [
"983f20158f5653741e31e47b1e0bc866a8c26d52",
"reftest"
],
"css/CSS2/generated-content/before-after-002.xht": [
- "cea0b058b3c03ad494203e0bcc1873f056bb714a",
- "visual"
+ "1f6aed90dd4e09b998b913340a567605c7afe961",
+ "reftest"
],
"css/CSS2/generated-content/before-after-011-ref.xht": [
"72e71292a7df5b9a1a331254ce8c73237ebdf7f7",
@@ -425849,348 +431325,564 @@
"reftest"
],
"css/CSS2/generated-content/before-inheritable-001.xht": [
- "6f51b953584ad5a49dc11a6708545d8e18d0a9c1",
- "visual"
+ "6d57c8a72b38e751272fad7bcf1ac374e53fe9aa",
+ "reftest"
],
"css/CSS2/generated-content/before-inheritable-002.xht": [
- "63b9021bbf0b17ee036967c1dc49723dc1eb063a",
- "visual"
+ "7b9a71f88f52594315361deec12d9edf25d21df7",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/before-location-001-ref.html": [
+ "4a53e1180a69dae0d67cff4df345758378ea0e63",
+ "support"
],
"css/CSS2/generated-content/before-location-001.xht": [
- "7820bcf75995b761c9ef1aeba78c4a0117fd5fe6",
- "visual"
+ "398d7d80114075a0d3eb2b2c03c6f14b6cd013fa",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/bidi-generated-content-001-ref.html": [
+ "839ce12dc8d07ec2a33c2ed2ed66cdeac0aa902c",
+ "support"
],
"css/CSS2/generated-content/bidi-generated-content-001.xht": [
- "147176473aa56d200a2d4400fe476c2d78850312",
- "visual"
+ "7cf0ae8a07a01eea46d28095b8f1aa85be1f6f4b",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/bidi-generated-content-002-ref.html": [
+ "8824d77b3266e1fd40b7c1ed59dfa0cc56a5fb9d",
+ "support"
],
"css/CSS2/generated-content/bidi-generated-content-002.xht": [
- "e7c38d8e6c9347720ec18e134ec02c994904365c",
- "visual"
+ "e3bbe0f13e25353f8eb9f54038ff64f306032d75",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-001-ref.html": [
+ "93a9c212d449144e303f708a1d72346bcf83dd07",
+ "support"
],
"css/CSS2/generated-content/content-001.xht": [
- "a1e2c7403bb38d914d75ce20a62cf34ae86a589c",
+ "4ce4769352e20029ea31afeebe45a9ef7bf194ff",
"reftest"
],
"css/CSS2/generated-content/content-002.xht": [
- "3b347a4ac345610c51f04540a75fe07221e196a4",
- "visual"
+ "c6d49cf18b8094de65776e1deccb8d177123dd3d",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-003-ref.html": [
+ "5818d7301c754c2bafe11d3b1a6a5ec79b07b19b",
+ "support"
],
"css/CSS2/generated-content/content-003.xht": [
- "14d906642d5324d77acfa4817d63c3c22ecdee03",
- "visual"
+ "117764df465bd2bbf22d39b6f1a1ad209c4ff34c",
+ "reftest"
],
"css/CSS2/generated-content/content-004.xht": [
- "53fdc7d929fc457d2bf573be9e59165c55808fc3",
- "visual"
+ "21997d31183dc6961f23989f4b12fe90691dad86",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-005-ref.html": [
+ "22bb38fe67f503dd7aa5fec0e20352af0c85d00b",
+ "support"
],
"css/CSS2/generated-content/content-005.xht": [
- "ec5833380097c44dfa69ee5203cdc48f3acd816a",
- "visual"
+ "8ee433c9daff5151f3c3f52fc27922d6f7a388a5",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-006-ref.html": [
+ "3c6876aef8774cfa74e9971dfde4c3ec0da158a5",
+ "support"
],
"css/CSS2/generated-content/content-006.xht": [
- "ab7ab5b6a454651b999f73646ff5b20745b3a8c0",
- "visual"
+ "aa16a2cb5927b546d8f09fd562a124fcc3385054",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-007-ref.html": [
+ "1660a6b021adc24afeb52310aaee0bcac6397989",
+ "support"
],
"css/CSS2/generated-content/content-007.xht": [
- "fee3a5c4c9d6e5d81e4158c16ba2bd25ba7028be",
- "visual"
+ "338f7087bafa52754e0592d26693095b61a03ec8",
+ "reftest"
],
"css/CSS2/generated-content/content-008.xht": [
"3770e069a5b6a715cafb661af0ee44466b91e791",
"visual"
],
"css/CSS2/generated-content/content-009.xht": [
- "37ccb387b372b9077956072af6bf817820a43bba",
- "visual"
+ "926489232d05e398ad7c7c50a20283d2e5dec918",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-010-ref.html": [
+ "4adda8b8a32a4a050175ae27a54da774ce553c39",
+ "support"
],
"css/CSS2/generated-content/content-010.xht": [
- "5c4856460e89aa1b5a147082680f5828b413cc37",
- "visual"
+ "52f5f24bcb4ada8bf4d9438621b96f409ff715f2",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-011-ref.html": [
+ "f717c9ae23b12737878dc5d97fea9b8a5ac0ac47",
+ "support"
],
"css/CSS2/generated-content/content-011.xht": [
- "741b60f98e5e3c5f97eedec19dd56a8b3e7cc787",
- "visual"
+ "4ebde6055cd2c7276ae16618c1df8f0cf31aa0f5",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-012-ref.html": [
+ "05f93132e832d9344022267ca6e9522553686053",
+ "support"
],
"css/CSS2/generated-content/content-012.xht": [
- "214b59371e4749d459bb9439b5ff8c2d7ba68d9b",
- "visual"
+ "181ef189694fd15289f92b4c2165fb33ce86a447",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-013-ref.html": [
+ "b9de627614b112803aec90f7a73bdce794bd76dd",
+ "support"
],
"css/CSS2/generated-content/content-013.xht": [
- "212751b945f41da74f72f48d2d0282aba3733b7f",
- "visual"
+ "0864b92a8885099c7959c7853e9516aa42a5b563",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-014-ref.html": [
+ "543ef35a8221d4379ff0710bf9deb1cc7dc91914",
+ "support"
],
"css/CSS2/generated-content/content-014.xht": [
- "a2fa5bc09d08820da4091b5178c6cdfe04b7b221",
- "visual"
+ "1a95c6e9079c0116fbcc31f7a7698de9d130e74f",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-015-ref.html": [
+ "826552c48dc4e1d3e044a6f2cec68ebe660787d9",
+ "support"
],
"css/CSS2/generated-content/content-015.xht": [
- "e199bdfae50d1c3d66caaed8eab5e13adf9e2291",
- "visual"
+ "ac3f726c3c99ed2dd043eb552e545f257300cb73",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-016-ref.html": [
+ "ba303e06fd91d2d07a518f16ea75af0b1c4593c9",
+ "support"
],
"css/CSS2/generated-content/content-016.xht": [
- "a8c1772ab662bb0b76477926fb4b383830c4ac69",
- "visual"
+ "c76a77d3459cb8e3e2e38e772e489bb661cfaa7b",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-017-ref.html": [
+ "df027694d825f1d0716e48b19dab17a50dd09c63",
+ "support"
],
"css/CSS2/generated-content/content-017.xht": [
- "181338f2fb322ffddaf34452f3999aa60919cb6b",
- "visual"
+ "00cf1b752bf5b543bb9c44f9ba7e254e1d23987a",
+ "reftest"
],
"css/CSS2/generated-content/content-018.xht": [
- "c120672727fe40f5e0cad473acf19814bb9acfa0",
- "visual"
+ "b380a9bd79aa112365c5cd5eae6e15c1062194eb",
+ "reftest"
],
"css/CSS2/generated-content/content-019.xht": [
- "d8c76bebee3c841798b04689890c0786304f89b3",
- "visual"
+ "54a8f681e366a9c7b55626022085a27a09f54517",
+ "reftest"
],
"css/CSS2/generated-content/content-020.xht": [
- "20b5bdaecf1868aac94fee9e75b6677587218dd5",
- "visual"
+ "50e31e8432f235f2934bf0b6e8efc44ce36c370c",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-021-ref.html": [
+ "5e5b948acdae134afa74c8d37f80bea17d57eae0",
+ "support"
],
"css/CSS2/generated-content/content-021.xht": [
- "bc80777ed501696c6c0fd074f004c2393e73e0e3",
- "visual"
+ "eb42cda01574eff595d74c90b1f6768271cc965f",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-022-ref.html": [
+ "96bc3b3586262089474cf4cb3aa10bb3f842756c",
+ "support"
],
"css/CSS2/generated-content/content-022.xht": [
- "26d4e35551a3f1176563581df5547686b9a1fbb0",
- "visual"
+ "44e1524f55081bdfdcea42f20ea082568341c663",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-023-ref.html": [
+ "0359aef7ae2a2189581f19eb8ebeac5b975e5db2",
+ "support"
],
"css/CSS2/generated-content/content-023.xht": [
- "51715072e84329216fd1ccb9cdedcff1d5fc3f18",
- "visual"
+ "35e0bc59499836398520ee4b7b7c877f142630d8",
+ "reftest"
],
"css/CSS2/generated-content/content-024.xht": [
"10efece3a5c890164161a9bc3e72b6ee71be397c",
"visual"
],
"css/CSS2/generated-content/content-025.xht": [
- "e53e136793f9edd724bc744d85b4382af318d88f",
- "visual"
+ "550ca31894f42c2c6f7fbc1b88ad0061675d953d",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-026-ref.html": [
+ "3b200a8ae2e285aa16a5047d35137c5f6740610e",
+ "support"
],
"css/CSS2/generated-content/content-026.xht": [
- "b5a04d2916a376d51bed18ae3f04cd8a323a1c6d",
- "visual"
+ "6d4cece80b6c51204f2c67fd5eca7aeb51955957",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-027-ref.html": [
+ "879f868bc759b40f3a7fccfc6a16059353943786",
+ "support"
],
"css/CSS2/generated-content/content-027.xht": [
- "e9002676f06e5e10aca8b71f36e379c2657ae30e",
- "visual"
+ "41158698b7ee2c739e1662a97e575522e915b309",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-028-ref.html": [
+ "d1177c25bf3b2dd88aed726ae80588b7bbcbfb76",
+ "support"
],
"css/CSS2/generated-content/content-028.xht": [
- "1c906d005941683b6c42ea8b8332b04b4dde87a8",
- "visual"
+ "5a96e52e350ec3430afcebbd3814ebb6ce016c46",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-029-ref.html": [
+ "8ed7eb2b13d5706f7b22d6558e5a0e730385737a",
+ "support"
],
"css/CSS2/generated-content/content-029.xht": [
- "54f4b50b857ca248fe9c65112c3a4095dbed6426",
- "visual"
+ "a017cb5dc161aa360491a6cfb73af24b10d6ff13",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-030-ref.html": [
+ "9ca0d2b85476c4c09f79fecb97550929f6a77952",
+ "support"
],
"css/CSS2/generated-content/content-030.xht": [
- "9e8a118f741d55a0530f540cfb802e40ff654d09",
- "visual"
+ "c0d8d1340786d83caf40fad6761661f8bfc1fc7f",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-031-ref.html": [
+ "5c300548e9b351318caf1386db375a09eae74f4d",
+ "support"
],
"css/CSS2/generated-content/content-031.xht": [
- "ddc2214e9105c0aae96669d312f444693e3a85cc",
- "visual"
+ "0f62044d086fb070be37a9c5de4678ee087f9e59",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-032-ref.html": [
+ "deed41afc9c76923db16f4e351684474423ca96b",
+ "support"
],
"css/CSS2/generated-content/content-032.xht": [
- "9c3de37f82b299b68ee11f10e824e42487104da4",
- "visual"
+ "5c6e1c2c116425235e140cfa143af3424c49e422",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-033-ref.html": [
+ "af29f781fa1ca5a27e57e11a38ad8191b982e9b3",
+ "support"
],
"css/CSS2/generated-content/content-033.xht": [
- "b4ded13cd6ec12cf8ace6754efaf05c1e89bab28",
- "visual"
+ "599e3bd6d66ad6e74595d5a30f98ec3a4c65d82a",
+ "reftest"
],
"css/CSS2/generated-content/content-034.xht": [
- "21c8472ca8ae11d70068bdb599811a0734ba8f7c",
- "visual"
+ "0257b3ae5475f02121d6a6978ee6379fcc618623",
+ "reftest"
],
"css/CSS2/generated-content/content-035.xht": [
- "0ce2c23a32794c8e2ecb281d14e52375c0212751",
- "visual"
+ "739bfad28f7e62a4cdf6ad7a788d0b927ce9a0b4",
+ "reftest"
],
"css/CSS2/generated-content/content-036.xht": [
- "8bcf7ef6ed2ce487e69f29c22a551d2e4eb13122",
+ "e680f99e5671de0a762a2ca5b3b2e7aa09f330be",
"reftest"
],
+ "css/CSS2/generated-content/content-037-ref.html": [
+ "c76cc63fc5f36f4e76653ef8f0d7d8be5277fc6c",
+ "support"
+ ],
"css/CSS2/generated-content/content-037.xht": [
- "a63c9f042e04a27af77b067f277f1bd9b9cd2e59",
- "visual"
+ "c2ce76e7979c49c1549a705399aa56318016679f",
+ "reftest"
],
"css/CSS2/generated-content/content-038.xht": [
- "6a6d611b02e02ae216fdc66444f4d2738a950509",
- "visual"
+ "9a14fbd8c1e1a82953711dc5d2f695b5d67a6691",
+ "reftest"
],
"css/CSS2/generated-content/content-039.xht": [
- "7e5164cfa7c70dceb46a300a82e8334e0e7caec3",
- "visual"
+ "28951d4bdf7b44f7402f16ac972fa554e9906078",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-040-ref.html": [
+ "ecf41fb1f3395c1eb2b8fb56758c857623c85e60",
+ "support"
],
"css/CSS2/generated-content/content-040.xht": [
- "fbbc6e5198621db722ea0aa3f615795c470fd28a",
- "visual"
+ "b5ab90ad8e509840667b36dc83c23054795081e1",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-041-ref.html": [
+ "fbf3ce185004461878f9bfbbdaaf767f558893a1",
+ "support"
],
"css/CSS2/generated-content/content-041.xht": [
- "0883dba7ee1badc06107161f1676f01462a878b6",
- "visual"
+ "7759d9a42ca36d78ed16dae70ba3628c1bea1d40",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-042-ref.html": [
+ "a386fcddc0374a4e1af91120497b710d5978251e",
+ "support"
],
"css/CSS2/generated-content/content-042.xht": [
- "9c2f61cf8021a084f9c49216e60b2e464f6ba2dd",
- "visual"
+ "30541d06303ab8bc5e9e3e3de38710fb4b4f7c75",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-043-ref.html": [
+ "743d51de79b34d1fa3a968cb74ad276c987ee1be",
+ "support"
],
"css/CSS2/generated-content/content-043.xht": [
- "61132ef01363d09ae0f1231dc921bf42fcc3aad2",
- "visual"
+ "1b15927db3f9ddbf9e3505ee9366248435775dd5",
+ "reftest"
],
"css/CSS2/generated-content/content-046.xht": [
- "4e9449dc08d1b89b810b31ead6edc9444eac4341",
- "visual"
+ "40dd644e4dd5e53dbe64e201d642a12b66b60203",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-047-ref.html": [
+ "b0ab85d0ce594bfc1cde1e18197bc4b05f5f4cea",
+ "support"
],
"css/CSS2/generated-content/content-047.xht": [
- "ffb5b0dee84d27f63e392f6a96407e41be5168ff",
- "visual"
+ "9b6b48213c74d8fa872d06b601511c9a14b23908",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-048-ref.html": [
+ "1229f7ea7299fd5da63258fb5499437182f723bb",
+ "support"
],
"css/CSS2/generated-content/content-048.xht": [
- "cfb2eaf73a19c1bb87ff750f0087190d0b47c486",
- "visual"
+ "7f40b8c09bdea5f7d418cd6039293fa2abf14fa7",
+ "reftest"
],
"css/CSS2/generated-content/content-049.xht": [
"e8e22935c15c5e3e7630b127f6cc1beca6045dbf",
"visual"
],
+ "css/CSS2/generated-content/content-050-ref.html": [
+ "6eb034f12c30a7e0c84cb3c39fbdd3651f87f80b",
+ "support"
+ ],
"css/CSS2/generated-content/content-050.xht": [
- "6e203fa1ba4145d12cdee485838a07789ad0c2e0",
- "visual"
+ "e9555b95a424c5336b8801d19bc27b3d077fa31a",
+ "reftest"
],
"css/CSS2/generated-content/content-051.xht": [
"2c93ec9775d6eb6a48afe4ac6b99a04f0b2010da",
"visual"
],
+ "css/CSS2/generated-content/content-052-ref.html": [
+ "dfe0e1de0057ba29e659e70fd43a4a087992478a",
+ "support"
+ ],
"css/CSS2/generated-content/content-052.xht": [
- "169705cf0437c9443461cf43315401ea17b86c8a",
- "visual"
+ "5b1aee2698b432e1f989c8af620796b8bf607eea",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-053-ref.html": [
+ "f15be1a7dda4372a0aebf05be4b19d9096104865",
+ "support"
],
"css/CSS2/generated-content/content-053.xht": [
- "6872d2b4f196ba7798df752199cef64c77f532de",
- "visual"
+ "bdbd119ec900516a0f740cdbbe2a8c1b185ab645",
+ "reftest"
],
"css/CSS2/generated-content/content-054.xht": [
- "b7515674ecd0d1b73ee6b623a9fdd47f6783cf09",
- "visual"
+ "2aa0d9feeeb9d2dc11046ca2a3103d9444a3616c",
+ "reftest"
],
"css/CSS2/generated-content/content-056.xht": [
- "b21aadc4b6dc60bddf3a0f873fa89c06c874f5d5",
- "visual"
+ "2ef418a9da41cb3fec3c57ad0bff13bece26d9eb",
+ "reftest"
],
"css/CSS2/generated-content/content-057.xht": [
- "b70de2922b0d0f38dca52bfcbacfca050303646f",
- "visual"
+ "5229125f5dba23adae84e7dc6527df1c56cd78aa",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-063-ref.html": [
+ "58d7f0ba6b947822a01fce09550ac8d58cba35e3",
+ "support"
],
"css/CSS2/generated-content/content-063.xht": [
- "87fa18402bfa277b8dade28c82214ac0272c2c32",
- "visual"
+ "efd852940a661635aedef1cf02db0a1994c7bceb",
+ "reftest"
],
"css/CSS2/generated-content/content-065.xht": [
- "f1f5391d2f0189a797adb7274a486b4f04920bd8",
- "visual"
+ "401ff2e38c88f277ef3c1260c60d94d44849c383",
+ "reftest"
],
"css/CSS2/generated-content/content-066.xht": [
"5d3a82eaa195d0f51c46986816d6fda6f9eb9244",
"visual"
],
"css/CSS2/generated-content/content-067.xht": [
- "bf9937a869f2246442c212efe8716db9f0f251ff",
- "visual"
+ "856fba5ec96fb16d8cca26801835255a55172066",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-068-ref.html": [
+ "d339dca8b16a0f36c8a20931a487609aacefc5cf",
+ "support"
],
"css/CSS2/generated-content/content-068.xht": [
- "0ece41a5b5d229016d10cd75b2986b9cf6ef101f",
- "visual"
+ "542fb2c65fd75d6842c35da306d26f6465717bf5",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-070-ref.html": [
+ "6dfdade2b1e132c2dd25b88443305ade7e62900a",
+ "support"
],
"css/CSS2/generated-content/content-070.xht": [
- "2ceab78104c8e49a115b3818d7ff373168d69bdb",
- "visual"
+ "6086e831ebf324e4a871fdb684d13feedb53675d",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-072-ref.html": [
+ "463e7ee546a4067f322a88582f3b9d147dd4faf5",
+ "support"
],
"css/CSS2/generated-content/content-072.xht": [
- "31ed9dc7725aeb0dd9279e4c946c143111ace418",
- "visual"
+ "fd1d10397fa8308332f3dcec0ca75bb02a399a41",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-073-ref.html": [
+ "e3f703e323482f230146824ef83d2db369462f56",
+ "support"
],
"css/CSS2/generated-content/content-073.xht": [
- "dd994d7a6051582295c9f1e4f20daf0110669a0a",
- "visual"
+ "bc4e2d4e21ecccb68ed31283a9970f5d18465fca",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-075-ref.html": [
+ "661e739a38e1173a6745e2f52d0437b35ef7b19f",
+ "support"
],
"css/CSS2/generated-content/content-075.xht": [
- "13b6235db663ed80aa7e5d2f175133407036a01a",
- "visual"
+ "733eaaf078eed89c182f42278da5c05a59bb8090",
+ "reftest"
],
"css/CSS2/generated-content/content-076.xht": [
- "398946563f71f1fb45a900dbdc16c22e7165377c",
- "visual"
+ "41774972bafc2815ca9ec1fc66286d60998ab10e",
+ "reftest"
],
"css/CSS2/generated-content/content-077.xht": [
- "7df5236558794e41c5986e141da3d88f5dd84c86",
- "visual"
+ "a0f5aed7a09062f7f554db78badfa4a0f3cab9c0",
+ "reftest"
],
"css/CSS2/generated-content/content-078.xht": [
"1e4d5027858c09a1f020a6043092ca75839cb05d",
"visual"
],
+ "css/CSS2/generated-content/content-080-ref.html": [
+ "789dac38a057e2d3f874ed847116a08808dbddb5",
+ "support"
+ ],
"css/CSS2/generated-content/content-080.xht": [
- "331353d73e1d0169c56f3be2813dbe0b617907cf",
- "visual"
+ "78a19448df490617c45920895bb9cd2e501e6011",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-081-ref.html": [
+ "641518632420ac6281381ce9ee766ac9c3f4443f",
+ "support"
],
"css/CSS2/generated-content/content-081.xht": [
- "92126a03c26e7c9316d496e0ef871cb008641169",
- "visual"
+ "2cda22c21c23f42119bb9281c703d35e55a4e975",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-082-ref.html": [
+ "817efad77b46cfb731f879c4868d9b871c11bdca",
+ "support"
],
"css/CSS2/generated-content/content-082.xht": [
- "8441670c152b4c53db4610ce83f32fc1f85fe0e8",
- "visual"
+ "d42e394f5c0f283adbcd718f853f785e23a818c1",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-083-ref.html": [
+ "1615f4404ba11036ac880526aabac89a82daccc3",
+ "support"
],
"css/CSS2/generated-content/content-083.xht": [
- "15f66ed7e28ccf9f1b78574eabd9df2a64b81d89",
- "visual"
+ "e494972b8b586c7ab9e65992974e9b8d38a560b7",
+ "reftest"
],
"css/CSS2/generated-content/content-085.xht": [
- "8538fb8763391d556c96643517ed7148bd9d9212",
- "visual"
+ "666258b96d1f85fe599b01efea029b719d6dd6ab",
+ "reftest"
],
"css/CSS2/generated-content/content-086.xht": [
- "74a94c5349c8b1c9c82d7e943b40996557475eaf",
- "visual"
+ "df8b06374e8155336167b9084ffe107d4d1f9c6b",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-089-ref.html": [
+ "1615f4404ba11036ac880526aabac89a82daccc3",
+ "support"
],
"css/CSS2/generated-content/content-089.xht": [
- "c33267a9b785e3991572d9bfd4e00b91f7cdade7",
- "visual"
+ "8de7cb8c3bcfdf082190803e8e712f588bd1a9c8",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-090-ref.html": [
+ "b78d605d096c45b73ba48200e8f035334c7fcd54",
+ "support"
],
"css/CSS2/generated-content/content-090.xht": [
- "92ecdb49178d7d0c2274c031d254e1cfe59df81c",
- "visual"
+ "b81d78f38ee5bd49c86872c65d4948b7c2b54225",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-091-ref.html": [
+ "78e364761d4adcc4a0031ad77954b7613ecb0b83",
+ "support"
],
"css/CSS2/generated-content/content-091.xht": [
- "672d790b5178a20275f9c6c0ba168ac65c5d2a71",
- "visual"
+ "907808e77b61cf6375079e924b0b1bef51bcc70b",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-096-ref.html": [
+ "e1a38c6c2fe87293817cde5856a1bfff5f6287f8",
+ "support"
],
"css/CSS2/generated-content/content-096.xht": [
- "64537cca3e2afb89e70abd5759c5ce9ce88b9f3e",
- "visual"
+ "4627b242c53af5ce27d5d79767e704ac1a336bc5",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-097-ref.html": [
+ "d7c0cc6a11ab55c60cb97d38387defc56a870a58",
+ "support"
],
"css/CSS2/generated-content/content-097.xht": [
- "eda4e9b3ddc0ca0e1a8fce2d1cb5293dc8dee9b9",
- "visual"
+ "6561f554c77b4cedf0ae0cc5721d59f83c777465",
+ "reftest"
],
"css/CSS2/generated-content/content-099.xht": [
- "d9f2345256809e3bb355927e796621e48732723b",
- "visual"
+ "972320f0d6931738959302a637579a7e79accf82",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-100-ref.html": [
+ "bf886ae366ffaa3969bbd734f22167cb7e5a0c44",
+ "support"
],
"css/CSS2/generated-content/content-100.xht": [
- "ab0784494c860de119bbd4bc9c965c319f467725",
- "visual"
+ "f24bdf6751fec913b10a871c65db70fa54ce600e",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-103-ref.html": [
+ "422b7a53469fd26d03d6c1c7f0742da4941b8e22",
+ "support"
],
"css/CSS2/generated-content/content-103.xht": [
- "1ecd167094cf1964fc1f76bcab5d82790fd627bc",
- "visual"
+ "0095da1df3314f77ec68daa72c6419358d7e259c",
+ "reftest"
],
"css/CSS2/generated-content/content-105.xht": [
- "953a0ad087d94d09f5f0d3eda22721ad2885f0b7",
- "visual"
+ "4c23e629f3cbec501abd618605fecb5ef8a90293",
+ "reftest"
],
"css/CSS2/generated-content/content-107.xht": [
"d96ac86bbe47ff4b4a3ee7f068ee6de21492c424",
@@ -426201,8 +431893,8 @@
"reftest"
],
"css/CSS2/generated-content/content-109.xht": [
- "8aa12c850f21d77792975d4d7093b4a7f961a8b5",
- "visual"
+ "14489af88fd985aef47708073c55c0c725d0e6d9",
+ "reftest"
],
"css/CSS2/generated-content/content-110.xht": [
"3456d0c765afca85552f869373a8d218deb4a2c8",
@@ -426216,9 +431908,13 @@
"44143b958137423ca4d95b86a7a8c0948339ed56",
"reftest"
],
+ "css/CSS2/generated-content/content-113-ref.html": [
+ "18c8f08f2c880c033e0824039d8bf1904ade89b1",
+ "support"
+ ],
"css/CSS2/generated-content/content-113.xht": [
- "86bf0e3d425a75baaf53f25aa921bf736ea801ed",
- "visual"
+ "9eed15c15502e92ffed9d5e3795bc0e23e74d4d4",
+ "reftest"
],
"css/CSS2/generated-content/content-114.xht": [
"264aa0d3d3b36fbb9008d184f3b14c7077c1a716",
@@ -426249,120 +431945,176 @@
"reftest"
],
"css/CSS2/generated-content/content-122.xht": [
- "00a7b7c48b3f8d9bcfd4022b5b13d174aed24165",
- "visual"
+ "db510090fbec6df00ee70ba9d5ebc0deb50816c9",
+ "reftest"
],
"css/CSS2/generated-content/content-123.xht": [
- "5a8c7966f5cd6a2ff63733071a034f5e191b7b66",
- "visual"
+ "60d0552ec4647f9b85c7122567a051790e8c9ad3",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-126-ref.html": [
+ "1aa43fca0f1d4b0e10a706ed380483073d0d9f7b",
+ "support"
],
"css/CSS2/generated-content/content-126.xht": [
- "b1cb68fa02044bb5bafe2aa744a28fe8f378cdc7",
- "visual"
+ "4fa9e583f43ef8f5422ec203241e07b79396ee5f",
+ "reftest"
],
"css/CSS2/generated-content/content-127.xht": [
- "2f36ae9ffe2bf84b5f2563066f3c547b93dc4153",
- "visual"
+ "bf971e547f0fb47630cb4cfa6e91299253e83d34",
+ "reftest"
],
"css/CSS2/generated-content/content-129.xht": [
- "9878e5260ca4c3bd6565eabe2434a1c1786d1748",
- "visual"
+ "8d6a3fe5125fba825e1b7dbaddf56f8fcf92f23f",
+ "reftest"
],
"css/CSS2/generated-content/content-130.xht": [
"326219b3a69cb1718e50525212ebf960c1490847",
"visual"
],
"css/CSS2/generated-content/content-131.xht": [
- "22b0f29f51e2868bffb0524814647bc196d777a3",
- "visual"
+ "1039bc76db903dc5ceba39426604a6aba5b18569",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-132-ref.html": [
+ "3384039df388d1a3981a631221a4c4efbcb6c89a",
+ "support"
],
"css/CSS2/generated-content/content-132.xht": [
- "f7fa99cca43357b27cd5cfc37dfa82227984d441",
- "visual"
+ "05f1eb8fae82f4a6ea14643eea3646a484698cb5",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-135-ref.html": [
+ "dd7757d53f233f8de44c4333e43f17249ca3394f",
+ "support"
],
"css/CSS2/generated-content/content-135.xht": [
- "788aae94056f4cbafa83fb9a2233d757d4147994",
- "visual"
+ "6a1f11d890b45b577c7594688cf9723537506adb",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-136-ref.html": [
+ "94e6d3ca39b0eeebbb6a11728370998751457142",
+ "support"
],
"css/CSS2/generated-content/content-136.xht": [
- "5d3c3f4d5ac3a0808b677848b6225e9a9d4efe9d",
- "visual"
+ "e33d8ca80475ef988c5d45315fd20c7d9830fa25",
+ "reftest"
],
"css/CSS2/generated-content/content-138.xht": [
- "155ce600c88f114db512c29027fa3471b933efa1",
- "visual"
+ "7650618dff9b734b894710101c2ab917fe86d42c",
+ "reftest"
],
"css/CSS2/generated-content/content-140.xht": [
"9261e82f6b3bffaa2950764848989c1629577494",
"visual"
],
+ "css/CSS2/generated-content/content-141-ref.html": [
+ "8e87f38d4d12389f99f64fc027941d9782310447",
+ "support"
+ ],
"css/CSS2/generated-content/content-141.xht": [
- "fa0892854f36543a210481286c6b7b26dc07093b",
- "visual"
+ "943de06685610b2d5eb7c5859e747b96dd0cbfa1",
+ "reftest"
],
"css/CSS2/generated-content/content-142.xht": [
"d9c9efd22ac0fdae887c535221a6a87638fd8874",
"visual"
],
+ "css/CSS2/generated-content/content-143-ref.html": [
+ "0f74a336125f7db1dc9a43d78ae165b4e109a495",
+ "support"
+ ],
"css/CSS2/generated-content/content-143.xht": [
- "2ca23d4fa513db422107a58435e4900bfc02a811",
- "visual"
+ "fb0c58246015480076432896d147286b66869539",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-144-ref.html": [
+ "d53cb4a28dd17903a68cb69b1bcb75d02bc63dc8",
+ "support"
],
"css/CSS2/generated-content/content-144.xht": [
- "17a3c64a1ff4d4965c2b6d113c0b72a465cd13be",
- "visual"
+ "911a497bb282a3487a69862d9e865599c3cf9b02",
+ "reftest"
],
"css/CSS2/generated-content/content-145.xht": [
- "906369b33e89a868076e3caa079b5e0db4835dc8",
- "visual"
+ "860389d53cb820ea19857628eb195990e59a3b7a",
+ "reftest"
],
"css/CSS2/generated-content/content-146.xht": [
- "2e534c23b7074b417269aca88354a4470b1fdf84",
- "visual"
+ "a845bd2ea468178550efe67abc3bec7eaa5427ce",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-147-ref.html": [
+ "bf1ac303d8f397dd054955f310672f743f938aed",
+ "support"
],
"css/CSS2/generated-content/content-147.xht": [
- "78c4d6bdb6d75caf889ac8ec99b0239b3a85fcfb",
- "visual"
+ "4a545de935292410d7200a74c7c169032d396e2f",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-149-ref.html": [
+ "ec4228da18bd5dc7eafd90b7d0b982e1ea6c186f",
+ "support"
],
"css/CSS2/generated-content/content-149.xht": [
- "f666d03ec21135bf652f81fb141b26f0a32c3e2d",
- "visual"
+ "1ad87ccce1e4ccea7d1e5f3098e6e2ff224491cc",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-150-ref.html": [
+ "32a30eda299be341a1b66cc0f948142ceae42e82",
+ "support"
],
"css/CSS2/generated-content/content-150.xht": [
- "0bd549aa9b3003954366dd9319d3ea0a9bf96abc",
- "visual"
+ "18d432e51b1a88d89396ba4b6959e337eaca92b0",
+ "reftest"
],
"css/CSS2/generated-content/content-151.xht": [
"9efb22636e2e5bd06f8393b68c41f3420c6a1e0e",
"visual"
],
"css/CSS2/generated-content/content-152.xht": [
- "0ef4f8b1f7bc845feddfe99a584e21f122667d20",
- "visual"
+ "6b802ad4b702d2eecb1830cb35741e650f5afe61",
+ "reftest"
],
"css/CSS2/generated-content/content-153.xht": [
- "eed73f671c227e458211890cea12adfdd2d96fda",
- "visual"
+ "d93e9404202426e0f97925c68cab21992fa384fd",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-155-ref.html": [
+ "ca516f6671b877e517b491010f72c09486259a17",
+ "support"
],
"css/CSS2/generated-content/content-155.xht": [
- "08fc985b4ba22412c52d4b498fb78a44f6180148",
- "visual"
+ "af8d68287b18f944d3523c4b913b78134aa241cd",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-156-ref.html": [
+ "36e4844e8174f3cc69af8add5418dd79eaa54933",
+ "support"
],
"css/CSS2/generated-content/content-156.xht": [
- "6b7ce278cd19a3db9965c0390ec04945bdc45938",
- "visual"
+ "fa1e87875c24ce51397c293e7a701e2127b9b8e3",
+ "reftest"
],
"css/CSS2/generated-content/content-157.xht": [
- "7904b65d5172f464785b28cc5551db4f043e9405",
- "visual"
+ "21d82565bfe80ddf117b21920949d127a83af581",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-158-ref.html": [
+ "fdcdd9ada31d57e1f7b150780ce3bbe3bbe16041",
+ "support"
],
"css/CSS2/generated-content/content-158.xht": [
- "2f0bb55cd06cf0b5fcaef6eb00321c329a36213f",
- "visual"
+ "bf8d47b7849c698e1f0417890198cefa352b5d9c",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-159-ref.html": [
+ "847e1ac3da66a0673323ec5dc1e3885b42f0bef4",
+ "support"
],
"css/CSS2/generated-content/content-159.xht": [
- "b470b94294f0f23f8a590c82a2a7372aaded3bfc",
- "visual"
+ "441e31aa08a4fe28e66be7e3a7fc063a70af9662",
+ "reftest"
],
"css/CSS2/generated-content/content-160.xht": [
"723f35be2a0ac3db0c0b11de0b580b95aeeed37f",
@@ -426425,24 +432177,28 @@
"visual"
],
"css/CSS2/generated-content/content-attr-001.xht": [
- "06a4b3449c026f018e5591ec25e6bbcf947f0842",
- "visual"
+ "e1c68833536e23d0e0da86611ebaa26488f67de5",
+ "reftest"
],
"css/CSS2/generated-content/content-attr-002.xht": [
"67ff295748a46db75ba6b6bcf9b3fc955cdb6054",
"visual"
],
"css/CSS2/generated-content/content-attr-case-001.html": [
- "0c1a92a7119fafa091ca269edb6ba7a6cef7d3ca",
- "visual"
+ "868e1fb639f2b3cdbfd6f6c361ccb796bef0f2a3",
+ "reftest"
],
"css/CSS2/generated-content/content-attr-case-002.xht": [
- "ccf14b1d669032191372e955f77e7f63d0718739",
- "visual"
+ "fa2ffef772d90ce1f358da9a5dafca0fc8a46b31",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-auto-reset-001-ref.html": [
+ "bbe6c8ce25e9a27aa2fcb0843b1f5a6b2432de80",
+ "support"
],
"css/CSS2/generated-content/content-auto-reset-001.xht": [
- "8f2962d27daa66dc5d548a6e440684c013639f65",
- "visual"
+ "5d1245c7101997a54b03f34a28ad7aad8aa1618d",
+ "reftest"
],
"css/CSS2/generated-content/content-counter-000-ref.xht": [
"cb947dd17c994e66de34b41b2bd4062948d04930",
@@ -426652,29 +432408,49 @@
"f80bd32d1bc8955ff00de66d211b9df6f0a4a9f2",
"reftest"
],
+ "css/CSS2/generated-content/content-newline-001-ref.html": [
+ "792d23ddadd740eb4a05c60efbb0b71e2922c716",
+ "support"
+ ],
"css/CSS2/generated-content/content-newline-001.xht": [
- "4387d521d200a5cba6edff04463dbe8847be5cc3",
- "visual"
+ "bfdd3ccf6338c835532368b80fbeacc6ffc1a5c3",
+ "reftest"
],
"css/CSS2/generated-content/content-uri-001.xht": [
"470ee7c21508137d4ca15dd35a57f9414a567ce0",
"visual"
],
+ "css/CSS2/generated-content/content-white-space-001-ref.html": [
+ "e7ea132de591d986bff01f230f8e272f6e195d27",
+ "support"
+ ],
"css/CSS2/generated-content/content-white-space-001.xht": [
- "8cf7294e169bb708d922735a0cba4172ce8a95dd",
- "visual"
+ "bbca6fac952179359b6740193b6e4430473c0ce2",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-white-space-002-ref.html": [
+ "66023264d1a4f82e92c68c8618a5005dd8101aaf",
+ "support"
],
"css/CSS2/generated-content/content-white-space-002.xht": [
- "a5d1f5ab5002b969bd3a420d54a4c29385544b9e",
- "visual"
+ "2efbae79cf35d90bd31e0a8a06876ce2630096c1",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-white-space-003-ref.html": [
+ "e2b4d4fe25d44d431dbac408125629a8b6f4e58d",
+ "support"
],
"css/CSS2/generated-content/content-white-space-003.xht": [
- "bfa9f8e591f609a783099ed6fec777e5da06edf6",
- "visual"
+ "38728ce5af93a5a8c0c1395dc741fb6e716a8dc1",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/content-white-space-004-ref.html": [
+ "7546cec8f1d7147ecc363d8c2bfaf977befcd74c",
+ "support"
],
"css/CSS2/generated-content/content-white-space-004.xht": [
- "c25e18c139b53e46a92c55072e3a4b460193139f",
- "visual"
+ "6f9f59377ea5f4917dea5a363647bb0ecb4074b1",
+ "reftest"
],
"css/CSS2/generated-content/counter-increment-000.xht": [
"3499696cf5d953dd6d075d0b7c084b41c28a79d3",
@@ -426700,37 +432476,57 @@
"a8dbf7e6a480189cae384fab758a507781c7a01b",
"visual"
],
+ "css/CSS2/generated-content/counters-hidden-000-ref.html": [
+ "ed9cd1beda8d45ce136775410594de083d66c80c",
+ "support"
+ ],
"css/CSS2/generated-content/counters-hidden-000.xht": [
- "fa75afe23cc29aca9b9955417c7fdc843d86b638",
- "visual"
+ "5e793dcfb16d24a00d35229cda6c360d2ce4a048",
+ "reftest"
],
"css/CSS2/generated-content/counters-hidden-001.xht": [
- "251485e38dc64c4f5e620d363b2821402d64e131",
- "visual"
+ "47699481449894ac7c0a6c57de85753f92a9bae9",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/counters-hidden-002-ref.html": [
+ "4305621626ec39ad5476511b832d0127c4e43749",
+ "support"
],
"css/CSS2/generated-content/counters-hidden-002.xht": [
- "1326e94220ba6d78fb3a573f0574bab182d8eba9",
- "visual"
+ "79ffca13df20085a7bb534ac2a8d15f7400d3f0d",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/counters-multi-000-ref.html": [
+ "53eda0a7e918513fef73aefcad2c02e24113e4c3",
+ "support"
],
"css/CSS2/generated-content/counters-multi-000.xht": [
- "9afc27360f8b3b727718e52ea71bf60c6ba1fb0d",
- "visual"
+ "3ab2fa7b87beeb5dfe2ca4afcd01fb497e1573af",
+ "reftest"
],
"css/CSS2/generated-content/counters-multi-001.xht": [
- "817db5ac6b5d748b035c666495f7f60a239f2e3c",
- "visual"
+ "a98c00491e1af2bc2b76d2da9dd49e55f0f7605b",
+ "reftest"
+ ],
+ "css/CSS2/generated-content/counters-order-000-ref.html": [
+ "f062712e8662f81340a0014fc4cc382804d77884",
+ "support"
],
"css/CSS2/generated-content/counters-order-000.xht": [
- "311345cea8c6b2f851d76ab9548576d55b8de8a4",
- "visual"
+ "053eb6c18101f6ce18056e6facb7e9b9b7b5f886",
+ "reftest"
],
"css/CSS2/generated-content/counters-order-001.xht": [
"8a439c13b321576d85708a4ee361bca7a2efcb3a",
"visual"
],
+ "css/CSS2/generated-content/counters-root-000-ref.html": [
+ "006f12f97aa57a0a16aa29a62d50c1de4bea479f",
+ "support"
+ ],
"css/CSS2/generated-content/counters-root-000.xht": [
- "d43c7dc5b402a0d493d8bc5d15ebbbfbb7e268c8",
- "visual"
+ "91291e98d2e03e0db1865844c8795402b491a4af",
+ "reftest"
],
"css/CSS2/generated-content/counters-scope-000.xht": [
"418ed951641c85d3c23330987fd48e0a980c6400",
@@ -428628,6 +434424,14 @@
"2927ed2a8c86f6a791db5d6eb670ad1961b17e9e",
"visual"
],
+ "css/CSS2/linebox/line-height-oof-descendants-001-ref.html": [
+ "284fd0f610f5428bea7a5f9c0dee1bdde3a4670b",
+ "support"
+ ],
+ "css/CSS2/linebox/line-height-oof-descendants-001.html": [
+ "bb8949f890f140305ac76beb3f3ae1f2d15b16a3",
+ "reftest"
+ ],
"css/CSS2/linebox/support/1x1-green.png": [
"51e7b6974a09eda6cb31337717c5eaeb9c44b443",
"support"
@@ -457765,7 +463569,7 @@
"support"
],
"css/CSS2/values/numbers-units-011.xht": [
- "e7ec181207bbc94c6aad4175d19f11debc7cab67",
+ "17c979afd18db2ae6c76c85290ecac491c8b8269",
"reftest"
],
"css/CSS2/values/numbers-units-012-ref.xht": [
@@ -458032,6 +463836,26 @@
"0f9684f5b6f8a289b4ed680f10c2460b701f93fe",
"reftest"
],
+ "css/CSS2/visudet/content-height-001.html": [
+ "a5eacd7718cf4c9772eec96bdeebc5117274764f",
+ "reftest"
+ ],
+ "css/CSS2/visudet/content-height-002.html": [
+ "1446a35470b7119d688a60d4254f82277704568f",
+ "reftest"
+ ],
+ "css/CSS2/visudet/content-height-003.html": [
+ "4f161ed93fe5facaca17bb0d6ea1ec95db8fdeea",
+ "reftest"
+ ],
+ "css/CSS2/visudet/content-height-004.html": [
+ "85ce343a8af7e564e76e49e4efd68248639cf3cb",
+ "reftest"
+ ],
+ "css/CSS2/visudet/content-height-005.html": [
+ "5f417858f0d8b45b0d728bdc12cecbeb5fd8f4ce",
+ "reftest"
+ ],
"css/CSS2/visudet/height-applies-to-010a-ref.xht": [
"581de95a4963b6b2333aa52ffaa40d8602d4a69f",
"support"
@@ -458072,10 +463896,82 @@
"7de15523c5a70277df00ce5c36cf0495796e8834",
"reftest"
],
+ "css/CSS2/visudet/line-height-201.html": [
+ "819c633cbf3c9f9f90dfad4b994805a0bf9c39b6",
+ "reftest"
+ ],
+ "css/CSS2/visudet/line-height-202.html": [
+ "5cdd43dfb4521c879fd5f71f5c8e729175acb592",
+ "reftest"
+ ],
+ "css/CSS2/visudet/line-height-203.html": [
+ "cadcb023d118268729b1dac65da5c58aee767841",
+ "reftest"
+ ],
+ "css/CSS2/visudet/line-height-204.html": [
+ "542b71b278592fc511ab946185b8adaf1caea638",
+ "reftest"
+ ],
+ "css/CSS2/visudet/line-height-205.html": [
+ "b7abe6f77d1dbd251f332fb6f3b0c719badef9f5",
+ "reftest"
+ ],
+ "css/CSS2/visudet/line-height-206.html": [
+ "3fb676d1813f4b8b7e6ee4a0aa30aa19b94b74d6",
+ "reftest"
+ ],
"css/CSS2/visudet/max-width-109.xht": [
"f16a156aae237e8f41a03692776f4f62ec38e52b",
"visual"
],
+ "css/CSS2/visudet/reference/content-height-001-ref.html": [
+ "3f269c5eec17d12e97e26c53a4e576aaa72877d0",
+ "support"
+ ],
+ "css/CSS2/visudet/reference/content-height-002-ref.html": [
+ "fb5af8b1620174a1e7346477ea5f0d00a98cc74e",
+ "support"
+ ],
+ "css/CSS2/visudet/reference/content-height-003-ref.html": [
+ "1f3e8ae567881df8d0f07c2df56a0528a8367526",
+ "support"
+ ],
+ "css/CSS2/visudet/reference/content-height-004-ref.html": [
+ "dc50725289cbdb628635f7b1a2854326bbada4bf",
+ "support"
+ ],
+ "css/CSS2/visudet/reference/content-height-005-ref.html": [
+ "46615347aa82e74273e8580a04a0944a3f82e232",
+ "support"
+ ],
+ "css/CSS2/visudet/reference/line-height-201-ref.html": [
+ "2f285902b55a9a2bcd7e09f7437e3aae6d0269bc",
+ "support"
+ ],
+ "css/CSS2/visudet/reference/line-height-202-ref.html": [
+ "66d52a0c9bfde0b1bef9ac5054f7cf400fef1573",
+ "support"
+ ],
+ "css/CSS2/visudet/reference/line-height-203-ref.html": [
+ "ffa2e91fd888edf5598cb0ac19ff2c65078fb4a1",
+ "support"
+ ],
+ "css/CSS2/visudet/reference/line-height-206-ref.html": [
+ "221b497ef9262ecc61cbe97cdc533d00cca8b231",
+ "support"
+ ],
+ "css/CSS2/visudet/support/1x1-green.png": [
+ "51e7b6974a09eda6cb31337717c5eaeb9c44b443",
+ "support"
+ ],
+ "css/CSS2/visudet/support/AD.woff": [
+ "2bff1f1a01ce7c959341300952b2467e87e60dd5",
+ "support"
+ ],
+ "css/CSS2/visudet/support/Revalia.woff": [
+ "f2b20022818e53e9c9c5f22bcc52703c6858eb1c",
+ "support"
+ ],
"css/CSS2/visudet/support/swatch-blue.png": [
"e79958e10feeeed3db88dee9bae9ea80055593c5",
"support"
@@ -459084,12 +464980,8 @@
"b96e97be7cc4eb1e5e40d037895cb81735f78ec6",
"reftest"
],
- "css/OWNERS": [
- "77e15937dd2bef6cf8ffb55f2698e8b1f0a3f065",
- "support"
- ],
"css/README.md": [
- "17ea0b79a120fb33e736c10fa967cfd001f9b181",
+ "ab97108074d4c07c5333ff1148fe9a5e425484ca",
"support"
],
"css/WOFF2/OWNERS": [
@@ -462960,10 +468852,6 @@
"b0cf703533a323305eb772c6def00afe21cdcdb8",
"reftest"
],
- "css/compositing/mix-blend-mode/mix-blend-mode-transition.html": [
- "2a9c826f5db1d9eb5a4748351a7d411b4c65a93b",
- "reftest"
- ],
"css/compositing/mix-blend-mode/mix-blend-mode-video-sibling.html": [
"d9682264f4ce1859b0d7f22b8dfca5cc482028a8",
"reftest"
@@ -463100,10 +468988,6 @@
"543892c3466ace307bd125801a2231dae3a95b92",
"support"
],
- "css/compositing/mix-blend-mode/reference/mix-blend-mode-transition-ref.html": [
- "2fdce2d337a053453bc339ffb7f9e0560c1f0095",
- "support"
- ],
"css/compositing/mix-blend-mode/reference/mix-blend-mode-video-notref.html": [
"4407e55ee0412f2064caeee74acad93424a849c7",
"support"
@@ -463340,6 +469224,10 @@
"d41b539ff28c250e1b7fe0c810e026f2fe57a67e",
"reftest"
],
+ "css/css-animations/animation-delay-011.html": [
+ "60f8a0ee02c497dc3ea7e24d6a2d722261e86990",
+ "reftest"
+ ],
"css/css-animations/animation-direction-001.html": [
"0bf1bfdcb407dc77beaedb5e0468e6913230f831",
"manual"
@@ -463900,6 +469788,22 @@
"da703cf56e71cd9dc8ff4f7ca34b11963eb5afb3",
"visual"
],
+ "css/css-backgrounds/background-color-body-propagation-001.html": [
+ "26f2d7efeb2063e8672f3f831d2bd382976a099d",
+ "reftest"
+ ],
+ "css/css-backgrounds/background-color-body-propagation-002.html": [
+ "0b9b3ffa3574c8f5e6202c5177dd5d6cfe636b16",
+ "reftest"
+ ],
+ "css/css-backgrounds/background-color-body-propagation-003.html": [
+ "f87fe8066c21356425c1eab1129a5a5c0f64b1f4",
+ "reftest"
+ ],
+ "css/css-backgrounds/background-color-body-propagation-ref.html": [
+ "843bae3267a34e4160763b16c59ea63036cd9e0b",
+ "support"
+ ],
"css/css-backgrounds/background-color-border-box.htm": [
"d638cc24e5598d10acfbf6d0c3a25552141a2ad5",
"visual"
@@ -463944,6 +469848,10 @@
"7e296a53a2abebcd5fcee2431b182efe6f148c64",
"reftest"
],
+ "css/css-backgrounds/background-image-none-gradient-repaint.html": [
+ "d2d9cb520ad7bb14b1499f2fbb6a87a20ff96d44",
+ "reftest"
+ ],
"css/css-backgrounds/background-origin-001.html": [
"11fa7ee04754b43a0837115bb223966351eaaad8",
"testharness"
@@ -465745,87 +471653,87 @@
"visual"
],
"css/css-backgrounds/border-radius-001-ref.xht": [
- "ef1308b55e3c17000ad94cf85a03d05ece24f66c",
+ "565982e400e9a1b62f6224ed655c977064ef3952",
"support"
],
"css/css-backgrounds/border-radius-001.xht": [
- "3f669ee04eca21655211dd4ec317e5f1cf4dfe39",
+ "448d22583ccdf4d4b245a219014eded8666a7bfa",
"reftest"
],
"css/css-backgrounds/border-radius-002-ref.xht": [
- "f8f2373accc3cfbcaf84a07aa6f850ac047931da",
+ "4bf3a05d4e3f531f59d1a8bb434d9ae8df3e089c",
"support"
],
"css/css-backgrounds/border-radius-002.xht": [
- "5f9bb278ae68dbdc0b85c54dfff2a8c5c2d6a576",
+ "54bdc142548fe5cd71336e3757f6b9ad8d8f75ef",
"reftest"
],
"css/css-backgrounds/border-radius-003-ref.xht": [
- "780b37d4e473e1e73b3c1221441f5c00cc9b64ba",
+ "21d3674eef4a60927e3849770a391e6b7a46f81a",
"support"
],
"css/css-backgrounds/border-radius-003.xht": [
- "77439d7aad5f3e58f2d85b034119c8907038545a",
+ "e27aa9bc45c17c77aeab571a581933bc97bcb95f",
"reftest"
],
"css/css-backgrounds/border-radius-004-ref.xht": [
- "c7e269aa1a07c964d1f78c943563856344789098",
+ "5e26e7f77aa27fcbef6636eb498fb9b0fa1e92e6",
"support"
],
"css/css-backgrounds/border-radius-004.xht": [
- "953b456c7aa306c9420d0d70d889bdf4207bcd53",
+ "eaf678007f7d5f8ca6751916638e509aea9909f5",
"reftest"
],
"css/css-backgrounds/border-radius-005-ref.xht": [
- "c2a6c35eba7c158f86922bab340cf20285ecdc0e",
+ "7dd0c30f5445c9f16cd575b7a48ebd0b8f407560",
"support"
],
"css/css-backgrounds/border-radius-005.xht": [
- "62e1da7ba92b46dffb2f0ee9a5fd725ae878af5b",
+ "59c424eed52f033c8c2f695107f44ae5a20b295e",
"reftest"
],
"css/css-backgrounds/border-radius-006-ref.xht": [
- "63a490cba1adaa2450e9a03edde3d1d3416703a1",
+ "28fcb03b46a25236eb58f057f056e7718dcf32e1",
"support"
],
"css/css-backgrounds/border-radius-006.xht": [
- "5d2a76914f94c10bf8d907d863365ee3d63c9d7c",
+ "4a9190103806f526f570f95ef824e007804fd645",
"reftest"
],
"css/css-backgrounds/border-radius-007-ref.xht": [
- "a8c78252ac61b36d0631aca15e8ec6ad3a3c16db",
+ "f547b82c811905504be2e37e4983d4dab8a5b31b",
"support"
],
"css/css-backgrounds/border-radius-007.xht": [
- "811f971181c1cf3fece208d6989567ed84d08070",
+ "1f7e0dc63717b1c6caa414d5ada7129510dd979c",
"reftest"
],
"css/css-backgrounds/border-radius-008.xht": [
- "193de4a55be9f442995b0adeabed0e14664e3f62",
+ "593d270ff4e46a92517459aa9992507f4b3e6c6a",
"reftest"
],
"css/css-backgrounds/border-radius-009-ref.xht": [
- "6c9457e7c251b0eb933edfc4be10e5bcb405ec57",
+ "013f339641d80aebee0ea3a97e44753806fdbd41",
"support"
],
"css/css-backgrounds/border-radius-009.xht": [
- "0b25cce5f284dcc2dac3e87c3419575ee84f764f",
+ "f4371415c6f2b4edf2bcf4920408d73493904519",
"reftest"
],
"css/css-backgrounds/border-radius-010-ref.xht": [
- "1039ef9b8bbe885c440ac80f017ac28567f3dc00",
+ "281bea790d41ae2cc3adbb8938130f75181f828c",
"support"
],
"css/css-backgrounds/border-radius-010.xht": [
- "6cd9f8f4f2fa156948f05be417d6e9e20f160b89",
+ "aa88a59894c5a73470221edaa02e0eadbc1a426b",
"reftest"
],
"css/css-backgrounds/border-radius-011-ref.xht": [
- "7a708c587aa874ea1bbd7a4862e1eb11eaa0f88f",
+ "d94d45fb036ee95933d251cdfd2ed491ab0405d2",
"support"
],
"css/css-backgrounds/border-radius-011.xht": [
- "1fcb231f6b7b8eb638bdcadace732ef80d274f6b",
+ "8e9493ba18bde48b0ad9e03adab856b54aae1f3b",
"reftest"
],
"css/css-backgrounds/border-radius-applies-to-001.htm": [
@@ -466832,972 +472740,12 @@
"ceb5773fc9d6264d1f9210d8675b7bf48764d296",
"reftest"
],
- "css/css-block/OWNERS": [
- "6634529fb114ab2e29cb2fa4a633289ee9038c22",
+ "css/css-break/OWNERS": [
+ "77055bd48cd1e192db8b2c6c47d736d7b1fcbe65",
"support"
],
- "css/css-block/after-content-display-004.xht": [
- "61fd73789062cb65193cd3e2ab535151b2565b8b",
- "visual"
- ],
- "css/css-block/anonymous-box-generation-002.xht": [
- "d8b897bec271896fa3362a6aef4a2c628ebbe0b3",
- "visual"
- ],
- "css/css-block/background-applies-to-011.xht": [
- "a4f27fa89ec568aaeeccd6867b5dd1afcb4b86f6",
- "visual"
- ],
- "css/css-block/background-attachment-applies-to-011.xht": [
- "02c5f4feaf50905f325b00d2635a77e631cbfe84",
- "visual"
- ],
- "css/css-block/background-color-applies-to-011.xht": [
- "8b3b119f15080301b1314ea5b45e270b2823df89",
- "visual"
- ],
- "css/css-block/background-image-applies-to-011.xht": [
- "9e9a51ef23a8968edc5d4a4c6f0305f6ddf0d7ed",
- "visual"
- ],
- "css/css-block/background-position-applies-to-011.xht": [
- "ff1707da202a90261724386b16a401aef3b48f6e",
- "visual"
- ],
- "css/css-block/background-repeat-applies-to-011.xht": [
- "88339d4a1b2cfc2fdff0905e592dcfaf75750cbb",
- "visual"
- ],
- "css/css-block/before-content-display-004.xht": [
- "d7f0c8005d0ab64c13b48c0589c1c0083bcb254b",
- "visual"
- ],
- "css/css-block/border-applies-to-011.xht": [
- "36eded364e030b01fe560e74e50f8fa8c118a433",
- "visual"
- ],
- "css/css-block/border-bottom-applies-to-011.xht": [
- "daad8099c06632a6423a90a913fef6643bef2366",
- "visual"
- ],
- "css/css-block/border-bottom-color-applies-to-011.xht": [
- "1f06ae35fa63cdc01c50754e945135cd65c81336",
- "visual"
- ],
- "css/css-block/border-bottom-style-applies-to-011.xht": [
- "f14782efe820b83b706b3ff6ecf1893bff256e42",
- "visual"
- ],
- "css/css-block/border-bottom-width-applies-to-011.xht": [
- "20389e139890e0e699712d9d9fc967ea0cb81d97",
- "visual"
- ],
- "css/css-block/border-collapse-applies-to-004.xht": [
- "44cbf688dbc21665f0cab3f608521293fc562796",
- "visual"
- ],
- "css/css-block/border-color-applies-to-011.xht": [
- "29ae73e9211b753a7d687ba7e73e30daf052d169",
- "visual"
- ],
- "css/css-block/border-left-applies-to-011.xht": [
- "74d022f4145b07d71c0ac5cd008df29138ae4d31",
- "visual"
- ],
- "css/css-block/border-left-color-applies-to-011.xht": [
- "08bd2a4ec6c575b8121e96bbdb8a0b2aa74140e3",
- "visual"
- ],
- "css/css-block/border-left-style-applies-to-011.xht": [
- "6270c843418d4eb40cccb1705ab2b17ac0f92f3d",
- "visual"
- ],
- "css/css-block/border-left-width-applies-to-011.xht": [
- "7496c6f5f5b46eb69de37176935cca76ad56d6bb",
- "visual"
- ],
- "css/css-block/border-right-applies-to-011.xht": [
- "78cd49b2e855a61cecb4e1b523841cab00081643",
- "visual"
- ],
- "css/css-block/border-right-color-applies-to-011.xht": [
- "e2391f060977badec62709241a824f97e597eccd",
- "visual"
- ],
- "css/css-block/border-right-style-applies-to-011.xht": [
- "ae3f43f85ef5266eeda294bf4524d125e871a317",
- "visual"
- ],
- "css/css-block/border-right-width-applies-to-011.xht": [
- "3209cbf4c1aa5d5c023ed13a17eac529052652a8",
- "visual"
- ],
- "css/css-block/border-spacing-applies-to-004.xht": [
- "862913eace05677ad332a5c76532599694bf69f6",
- "visual"
- ],
- "css/css-block/border-style-applies-to-011.xht": [
- "2ddc53bf2d5b8ab1e5c3b16e48ae5a2036fe31ea",
- "visual"
- ],
- "css/css-block/border-top-applies-to-011.xht": [
- "ba40b08236b9c5993613af13f8dd96d3932c8475",
- "visual"
- ],
- "css/css-block/border-top-color-applies-to-011.xht": [
- "b5184bc4fde674a806dccd7a061bd86fdb2f15a0",
- "visual"
- ],
- "css/css-block/border-top-style-applies-to-011.xht": [
- "75e780e649cac1c0e695ac8275a8a588751b939a",
- "visual"
- ],
- "css/css-block/border-top-width-applies-to-011.xht": [
- "9d5bedf58e1f861eab96f9d0b9fe90b58e021413",
- "visual"
- ],
- "css/css-block/border-width-applies-to-011.xht": [
- "a7126e39d2d60e8f4d2f018cea4d001b8cc94066",
- "visual"
- ],
- "css/css-block/bottom-applies-to-011.xht": [
- "f8e7490e71cf3899de316e306cea3947a17e1f77",
- "visual"
- ],
- "css/css-block/caption-side-applies-to-004.xht": [
- "ce42ae349ae0e76af642f7e7ad19c812690562df",
- "visual"
- ],
- "css/css-block/clear-applies-to-011.xht": [
- "3279ebd7562dcbf8c29f872e4d3ce76447c6d9c8",
- "visual"
- ],
- "css/css-block/clear-runin-001.xht": [
- "bcaed5391dc08f90de390194e84df4db9b0d8e38",
- "visual"
- ],
- "css/css-block/color-applies-to-011.xht": [
- "605a38365b79fa452ab47c9d1b7e77e68bc96218",
- "visual"
- ],
- "css/css-block/counter-increment-applies-to-011.xht": [
- "e040221f01a337cc4bd5294dfa665ca34be3c716",
- "reftest"
- ],
- "css/css-block/counter-reset-applies-to-011.xht": [
- "44aefba5a24f432500773763f95f45ca0887d7e8",
- "reftest"
- ],
- "css/css-block/cursor-applies-to-011.xht": [
- "cc19264db7880b0a52412e501cb2852d33fd175d",
- "manual"
- ],
- "css/css-block/direction-applies-to-011.xht": [
- "44512ff84708807b22f18a79bb18623a4b933f27",
- "visual"
- ],
- "css/css-block/display-004.xht": [
- "7471ec0ca8d4f375feb49136e468dc06ab52f265",
- "visual"
- ],
- "css/css-block/empty-cells-applies-to-004.xht": [
- "1a5763fed630b9d731f2af9961514be9af9f907e",
- "visual"
- ],
- "css/css-block/first-line-pseudo-009.xht": [
- "5636f5b08a197f797debed5dea6726315578828f",
- "visual"
- ],
- "css/css-block/float-applies-to-011.xht": [
- "01efe6f3b3298581cb45d2850b1f9732868fd381",
- "visual"
- ],
- "css/css-block/font-applies-to-004.xht": [
- "9b51369f7b55b2be28ae1c472a446e0de5e476e0",
- "visual"
- ],
- "css/css-block/font-family-applies-to-004.xht": [
- "627f012fde5832fa4fc098b2b1423e4db05ce95b",
- "visual"
- ],
- "css/css-block/font-size-applies-to-004.xht": [
- "a3bcca3e7c843c4e0fa6ccb72a2b5ce6a193eecf",
- "visual"
- ],
- "css/css-block/font-style-applies-to-004.xht": [
- "f759dd69c263ca2a976eeeadefc40f2c5c0364d8",
- "reftest"
- ],
- "css/css-block/font-variant-applies-to-004.xht": [
- "b254e27e04e40d32596c2a1171a5979c8f0e28c6",
- "reftest"
- ],
- "css/css-block/font-weight-applies-to-004.xht": [
- "8cbbee85603d1aa5db4e2d4abc6057254aadc30e",
- "reftest"
- ],
- "css/css-block/height-applies-to-011.xht": [
- "cef91dff5dd646f563a484fe329f62ea5d89d50d",
- "reftest"
- ],
- "css/css-block/left-applies-to-011.xht": [
- "ac86f465cdda1d482a5d336e3055d219b7547b9c",
- "visual"
- ],
- "css/css-block/letter-spacing-applies-to-004.xht": [
- "b2eef03d34f7698ece360bf0fe379e8024b30e37",
- "reftest"
- ],
- "css/css-block/line-height-applies-to-011.xht": [
- "5a504d5186b825f7a3ce231e7467319ecde7864c",
- "visual"
- ],
- "css/css-block/list-style-applies-to-011.xht": [
- "d6b3f818f50f92e6bd71742d8abc52c2ce40e13d",
- "reftest"
- ],
- "css/css-block/list-style-image-applies-to-011.xht": [
- "e6d6ef7fcfe75338a9f4c5d74bcf8695602417d8",
- "visual"
- ],
- "css/css-block/list-style-position-applies-to-011.xht": [
- "86092ff94df9f7268dce918a9edcc6ff86b570e0",
- "visual"
- ],
- "css/css-block/list-style-type-applies-to-011.xht": [
- "1b171ea4ced44a6bb7cd089088e2a156ff904ff7",
- "reftest"
- ],
- "css/css-block/margin-applies-to-011.xht": [
- "23b14b25f9629a21eb30d27e9d8dadb15fc05b4e",
- "visual"
- ],
- "css/css-block/margin-bottom-applies-to-011.xht": [
- "c528dcd41815a387a9e3625821135da92d7f032b",
- "visual"
- ],
- "css/css-block/margin-left-applies-to-011.xht": [
- "124c70029386ebd9a72571a2177d968544d46421",
- "visual"
- ],
- "css/css-block/margin-right-applies-to-011.xht": [
- "e819e775b2b1395c5f8210bb37beee1f1f8859b9",
- "visual"
- ],
- "css/css-block/margin-top-applies-to-011.xht": [
- "dd48bef2f6e5fec6a57cef62997affd1a9d882c7",
- "visual"
- ],
- "css/css-block/max-height-applies-to-011.xht": [
- "406878c807bd16c6c66f3fbb9455d7efef771fbc",
- "reftest"
- ],
- "css/css-block/max-width-applies-to-011.xht": [
- "eab9c01bea21c0e0196d6dc118d6a988ab79a8ca",
- "reftest"
- ],
- "css/css-block/min-height-applies-to-011.xht": [
- "6cd2f4f6ab2dde7b8887d2ba93ca4e246584939e",
- "reftest"
- ],
- "css/css-block/min-width-applies-to-011.xht": [
- "b78b3c65ed834da92ac60b55ebbead516d2aa7ee",
- "reftest"
- ],
- "css/css-block/outline-applies-to-011.xht": [
- "191fa8aafcab7760a159b1e4bb4f1e763d79ec22",
- "visual"
- ],
- "css/css-block/outline-color-applies-to-011.xht": [
- "c8ef9366d397901fc7cfc60fcfeb7e779cc2b629",
- "visual"
- ],
- "css/css-block/outline-style-applies-to-011.xht": [
- "395b8328ab7ffe7a8e542b377383c6f2fc23e168",
- "visual"
- ],
- "css/css-block/outline-width-applies-to-011.xht": [
- "d367fcd30a2a5cace628c6414bdaea814c64434f",
- "visual"
- ],
- "css/css-block/overflow-applies-to-011.xht": [
- "94ec0236bb7babe73b3bfa3135ef59077792a14c",
- "visual"
- ],
- "css/css-block/padding-applies-to-011.xht": [
- "06043f0bc1ee56f9c9aa14ee894c7f71ae66d08c",
- "visual"
- ],
- "css/css-block/padding-bottom-applies-to-011.xht": [
- "1f99d22839b620ead278902451b4393d16320cdf",
- "visual"
- ],
- "css/css-block/padding-left-applies-to-011.xht": [
- "c46dcccd743de4c4af7e159cdab344e9e6e8c943",
- "visual"
- ],
- "css/css-block/padding-right-applies-to-011.xht": [
- "b828450be59f1a3f52a60dec63f98255b21901ed",
- "visual"
- ],
- "css/css-block/padding-top-applies-to-011.xht": [
- "9674c7b62e79e1cd886db2b4b84f5cbb5514aece",
- "visual"
- ],
- "css/css-block/position-applies-to-011.xht": [
- "0720bf370b26ef35c9e2ea50c9faead2c98b8139",
- "visual"
- ],
- "css/css-block/quotes-applies-to-011.xht": [
- "6af5a17886b29abdce4fb2aef1b4fcf1f5c4f776",
- "reftest"
- ],
- "css/css-block/right-applies-to-011.xht": [
- "a80a4cee631686ec8df21372dacd609be35b8fa6",
- "visual"
- ],
- "css/css-block/run-in-001.xht": [
- "b0a4627e8ac492cd231537db0bdc18dc27dc7104",
- "visual"
- ],
- "css/css-block/run-in-002.xht": [
- "544419a0449424193f44b911e248fbfd0de23246",
- "visual"
- ],
- "css/css-block/run-in-003.xht": [
- "e9a318519677aab01514814a6ba97c9a936807fb",
- "visual"
- ],
- "css/css-block/run-in-004.xht": [
- "7b0837c9ee4571e49f97b083b855fcd691865bb3",
- "visual"
- ],
- "css/css-block/run-in-005.xht": [
- "5b97ec05a44c1d7cf7895808255ba2fc18c80f86",
- "visual"
- ],
- "css/css-block/run-in-006.xht": [
- "a59419542724e65457923d0389004a3eec2a4f77",
- "visual"
- ],
- "css/css-block/run-in-007.xht": [
- "c175c5311ac085143da2e59f54f5774ed5f2f5e9",
- "visual"
- ],
- "css/css-block/run-in-008.xht": [
- "1d0865927beea6342fff5c4fc69040acc9489512",
- "visual"
- ],
- "css/css-block/run-in-009.xht": [
- "71095c3996aff8d47fe520ff8fee2fa3b1cb2ebf",
- "visual"
- ],
- "css/css-block/run-in-010.xht": [
- "49213be77399f1a831d5b4b1a2f34fddeaa79b22",
- "visual"
- ],
- "css/css-block/run-in-011.xht": [
- "1974e33d93c187081046429312c76ea134df919e",
- "visual"
- ],
- "css/css-block/run-in-012.xht": [
- "ee5dac6b692fd283d7a097682dadfa6b626a05e1",
- "visual"
- ],
- "css/css-block/run-in-013.xht": [
- "11bc7fde7caf907343151062bb9ae809bae8c82d",
- "visual"
- ],
- "css/css-block/run-in-abspos-between-001.xht": [
- "3e1ad3faad361d1d2d593768a443910cf4cd490b",
- "reftest"
- ],
- "css/css-block/run-in-abspos-between-002.xht": [
- "c107b4fb41bd56638a0eb720131f91d4e5538a78",
- "reftest"
- ],
- "css/css-block/run-in-abspos-between-003.xht": [
- "23dea7a79da74d238e1c25a8c28296de817bc59b",
- "reftest"
- ],
- "css/css-block/run-in-basic-001.xht": [
- "0c34f3144766492c0cb309877d6db143697d9e02",
- "reftest"
- ],
- "css/css-block/run-in-basic-002.xht": [
- "09c62f1052efe44790ec822550e8e3cd835beb6a",
- "reftest"
- ],
- "css/css-block/run-in-basic-003.xht": [
- "087430960604e40634bba7dc932f788570b8c598",
- "reftest"
- ],
- "css/css-block/run-in-basic-004.xht": [
- "3831b02ab852d1d9f0c9417921ab4ca927896dc4",
- "reftest"
- ],
- "css/css-block/run-in-basic-005.xht": [
- "b2135f56d2885505eb44dcaaf2160ce29df7e4fa",
- "reftest"
- ],
- "css/css-block/run-in-basic-006.xht": [
- "01817fa44e367c4a7a020513aeb7c3456161cdd5",
- "reftest"
- ],
- "css/css-block/run-in-basic-007-ref.xht": [
- "11014cb21bcdf13e85c4d0086df9a25507613808",
- "support"
- ],
- "css/css-block/run-in-basic-007.xht": [
- "43dd105bde7f2e41c15d36b33e6554e391dc079f",
- "reftest"
- ],
- "css/css-block/run-in-basic-008.xht": [
- "f24259a5fed7bf8cab18b9184e35212e02800c96",
- "reftest"
- ],
- "css/css-block/run-in-basic-009.xht": [
- "e98daeb42c3a54d32b97d843addfa5d2dda44828",
- "reftest"
- ],
- "css/css-block/run-in-basic-010.xht": [
- "0bc99c24b856b18ea3fa55869db75a67de43ab8d",
- "reftest"
- ],
- "css/css-block/run-in-basic-011.xht": [
- "a1b654d27c1dab2ad1e4703b67e38d3e9bd2a188",
- "reftest"
- ],
- "css/css-block/run-in-basic-012.xht": [
- "c81ee8a2132c0ba8a6b21724d096cdafb847378b",
- "reftest"
- ],
- "css/css-block/run-in-basic-013.xht": [
- "2531d2898252313a9fe2f58723b88dd8fc687db3",
- "reftest"
- ],
- "css/css-block/run-in-basic-014.xht": [
- "59d9c7c29da0b266a4ff93650fb5d6a7855ec4e8",
- "reftest"
- ],
- "css/css-block/run-in-basic-015.xht": [
- "8a07cf400198531a7967b5902c2bc2d54619ab43",
- "reftest"
- ],
- "css/css-block/run-in-basic-016.xht": [
- "6e253d56c74265591f9f8f56975698e88c2f14fc",
- "reftest"
- ],
- "css/css-block/run-in-basic-017.xht": [
- "a2146b35df1dc7bd6a6ea30600576d66523c1934",
- "reftest"
- ],
- "css/css-block/run-in-basic-018.xht": [
- "62720b81190790760a9bc1fab01a5643cdf10395",
- "reftest"
- ],
- "css/css-block/run-in-basic-ref.xht": [
- "5c7bf6627792ff8dfa7898148318478fc9397673",
- "support"
- ],
- "css/css-block/run-in-block-between-001.xht": [
- "8bd7a8465542fdddf4a766566058ea858094f3c0",
- "reftest"
- ],
- "css/css-block/run-in-block-between-002.xht": [
- "5dc15f0706212f0231f83f98f6625041f8cbd2f1",
- "reftest"
- ],
- "css/css-block/run-in-block-between-003.xht": [
- "4a6ffa1bc42e3730571f20877d486ee8787168a5",
- "reftest"
- ],
- "css/css-block/run-in-block-ref.xht": [
- "071c80df59c30b1d27eb71bf640dc1851c82caae",
- "support"
- ],
- "css/css-block/run-in-breaking-001-ref.xht": [
- "2340373520e5da7655abe63565a265dc5cb033b9",
- "support"
- ],
- "css/css-block/run-in-breaking-001.xht": [
- "5fc81726a11c8dacd0836d7c58e6d3b2e6520de9",
- "reftest"
- ],
- "css/css-block/run-in-breaking-002-ref.xht": [
- "0a7d186899713e3176f1fec521fdba32aec23c75",
- "support"
- ],
- "css/css-block/run-in-breaking-002.xht": [
- "845947b845f9ac605a6be41e2159c0f5940017da",
- "reftest"
- ],
- "css/css-block/run-in-clear-001.xht": [
- "7a2c163d274376ebc920d4861a6050f2ee150ae7",
- "reftest"
- ],
- "css/css-block/run-in-clear-002.xht": [
- "150555e798c6a601b272f4f399ac59bf01181d49",
- "reftest"
- ],
- "css/css-block/run-in-contains-abspos-001.xht": [
- "505db18a1ef6306f55d3ccb0da91468eb1832e45",
- "reftest"
- ],
- "css/css-block/run-in-contains-block-001.xht": [
- "14a094004359b5d82a346789d943a10986a219ca",
- "reftest"
- ],
- "css/css-block/run-in-contains-block-002.xht": [
- "da1db69ceba2cbeb435c05d2b0db72400e7da3d6",
- "reftest"
- ],
- "css/css-block/run-in-contains-block-003.xht": [
- "3cd68ce6725aea4a8dc0d9c0a2c0f9a6d11fd9d9",
- "reftest"
- ],
- "css/css-block/run-in-contains-block-004.xht": [
- "7db957af8ab1c8baa83fe1c80030038c24a1a7f5",
- "reftest"
- ],
- "css/css-block/run-in-contains-block-005.xht": [
- "f9edbb5b1931152f0fc59a49fa7ceaf562907e10",
- "reftest"
- ],
- "css/css-block/run-in-contains-block-inside-inline-001.xht": [
- "8acc13aafb56c42ea28056d89c75ec7abf5ded8a",
- "reftest"
- ],
- "css/css-block/run-in-contains-block-inside-inline-002.xht": [
- "c2819892d00974d39407022d3999dc0e3a99cc86",
- "reftest"
- ],
- "css/css-block/run-in-contains-block-inside-inline-003.xht": [
- "66cbe19763f9d390ec7c059ea290abc8594cdde8",
- "reftest"
- ],
- "css/css-block/run-in-contains-float-001.xht": [
- "c761acc50f08e90f703a81ae8f22ff6e42709491",
- "reftest"
- ],
- "css/css-block/run-in-contains-inline-001.xht": [
- "4d7b0268d78bfbd575a2b83d0c220bb9773a0b68",
- "reftest"
- ],
- "css/css-block/run-in-contains-inline-002.xht": [
- "51c1489ef21996a11c5fb2b316fb33e0382eedb9",
- "reftest"
- ],
- "css/css-block/run-in-contains-inline-003.xht": [
- "cc4c7b96db888e2c4b5c72500b826d8594b2e131",
- "reftest"
- ],
- "css/css-block/run-in-contains-inline-004.xht": [
- "153dba85a8e212106ba545d91e769bfa7ed01f75",
- "reftest"
- ],
- "css/css-block/run-in-contains-inline-005.xht": [
- "a405159d3ad1841125d71fb1da1f20b48a4be773",
- "reftest"
- ],
- "css/css-block/run-in-contains-inline-006.xht": [
- "36ec63fd75a421d0fe020a97a786cd368ad7d247",
- "reftest"
- ],
- "css/css-block/run-in-contains-inline-007.xht": [
- "f7496dd5eefa7fda7438936dcaeff54a95a8aa0d",
- "reftest"
- ],
- "css/css-block/run-in-contains-inline-block-001.xht": [
- "bf9e2c4e86d11e99389f283977b2c5b112e73587",
- "reftest"
- ],
- "css/css-block/run-in-contains-inline-table-001.xht": [
- "e7d121beeb034e758fb5efa0082dc93b3efedbf1",
- "reftest"
- ],
- "css/css-block/run-in-contains-relpos-block-001.xht": [
- "675a88d85b722cc515fb158584b7572cc140fb4e",
- "reftest"
- ],
- "css/css-block/run-in-contains-relpos-block-002.xht": [
- "2be9a77b6a4e838cc08fcfc8f9920ddc28261381",
- "reftest"
- ],
- "css/css-block/run-in-contains-relpos-block-003.xht": [
- "c60fcf48a612655bea93d03a072f21c072f8c0f0",
- "reftest"
- ],
- "css/css-block/run-in-contains-run-in-001.xht": [
- "440555c995389809c51c646d540bf5d48d300e70",
- "reftest"
- ],
- "css/css-block/run-in-contains-run-in-002.xht": [
- "04fa874c1d0d2a26de77421e484ef222def2ea24",
- "reftest"
- ],
- "css/css-block/run-in-contains-run-in-003.xht": [
- "d9777e903841d7473f21e7d8132194fd2670aac4",
- "reftest"
- ],
- "css/css-block/run-in-contains-table-001.xht": [
- "89f16b25b8c73fd543936890c24e6359f14a0d26",
- "reftest"
- ],
- "css/css-block/run-in-contains-table-002.xht": [
- "c681daf1640dfae048990cb4ffe6a66783d6efff",
- "reftest"
- ],
- "css/css-block/run-in-contains-table-003.xht": [
- "452fe200c9b557ba8a5425d352c52f718dd01c5d",
- "reftest"
- ],
- "css/css-block/run-in-contains-table-caption-001.xht": [
- "555a7a80b7b13ed6694e6752702098088beefcb7",
- "reftest"
- ],
- "css/css-block/run-in-contains-table-cell-001.xht": [
- "f48afe1c718d9b6d17a6d0ae866ee47e5e9daf46",
- "reftest"
- ],
- "css/css-block/run-in-contains-table-column-001.xht": [
- "5211a09e5126d906b54970831fafae37fd361903",
- "reftest"
- ],
- "css/css-block/run-in-contains-table-column-group-001.xht": [
- "506b7828e6d6d602f5a47b0a67555bd8efeec352",
- "reftest"
- ],
- "css/css-block/run-in-contains-table-inside-inline-001.xht": [
- "1a080c99fd25e1095b4664aa5f001d10eeea371e",
- "reftest"
- ],
- "css/css-block/run-in-contains-table-inside-inline-002.xht": [
- "9937c034bdb0df12da9f2d6305ab9c5ab70b91fd",
- "reftest"
- ],
- "css/css-block/run-in-contains-table-inside-inline-003.xht": [
- "da81ad5da653c2d560371b339a9dae72b33fbdae",
- "reftest"
- ],
- "css/css-block/run-in-contains-table-row-001.xht": [
- "7f8c6603b1ab5fd9a3845769eefda2c367a20c02",
- "reftest"
- ],
- "css/css-block/run-in-contains-table-row-group-001.xht": [
- "24a7f43411f93088fd94d0322eb05a0cec39c31c",
- "reftest"
- ],
- "css/css-block/run-in-display-none-between-001.xht": [
- "b41224b028d9ae055937b119af885dfb5c4a5e43",
- "reftest"
- ],
- "css/css-block/run-in-display-none-between-002.xht": [
- "8ae5b5743c4c54adcac5b4aeef00f3706147cf57",
- "reftest"
- ],
- "css/css-block/run-in-display-none-between-003.xht": [
- "76901ba7cda655b286e0d384efc94314175e44a9",
- "reftest"
- ],
- "css/css-block/run-in-fixedpos-between-001.xht": [
- "898efaa60daf1d5174b884cf862c1e82ee3fcc43",
- "reftest"
- ],
- "css/css-block/run-in-fixedpos-between-002.xht": [
- "419a3aed33847413f5a7761d24c4597dd11c6eb8",
- "reftest"
- ],
- "css/css-block/run-in-fixedpos-between-003.xht": [
- "429c6d9258d12321dfc5b754e2b4ae75a3015c98",
- "reftest"
- ],
- "css/css-block/run-in-float-between-001.xht": [
- "3698456919cf966b8dd2ba8d5fae67cc5f1cdb4b",
- "reftest"
- ],
- "css/css-block/run-in-float-between-002.xht": [
- "44ad6dcae26aba095987e299b81af4568d4ef7b1",
- "reftest"
- ],
- "css/css-block/run-in-float-between-003.xht": [
- "d561aa7cb5206de8c3c314160c19814d800640ad",
- "reftest"
- ],
- "css/css-block/run-in-inherit-001-ref.xht": [
- "697462c36a68eb8f60abed93a5be18b58bcf0626",
- "support"
- ],
- "css/css-block/run-in-inherit-001.xht": [
- "f2382fbf93f981da1a585c60e9b377c29329a47c",
- "reftest"
- ],
- "css/css-block/run-in-inheritance-001.xht": [
- "c3496a363e7ff9fff53261d8878523fa2687b8e6",
- "visual"
- ],
- "css/css-block/run-in-inline-between-001.xht": [
- "4ea2d35766d3ae38fb2eecbc1c47ae36896a4b47",
- "reftest"
- ],
- "css/css-block/run-in-inline-between-002.xht": [
- "f1c06805cb2b657e3816837e00f45c3e4bfe4ea9",
- "reftest"
- ],
- "css/css-block/run-in-inline-between-003.xht": [
- "3c9fefe6a78fc7707e4148f9e4a083126036135c",
- "reftest"
- ],
- "css/css-block/run-in-inline-block-between-001.xht": [
- "63bb102ca896d3c1d95a798c647d4692f21bb96f",
- "reftest"
- ],
- "css/css-block/run-in-inline-block-between-002.xht": [
- "80c99eaa8dfd7e3ae7a18a8be5a6076ed32863a7",
- "reftest"
- ],
- "css/css-block/run-in-inline-block-between-003.xht": [
- "787b437e8448491b487fdef488dc1fff6e13c608",
- "reftest"
- ],
- "css/css-block/run-in-inline-table-between-001.xht": [
- "76f06b29154391ac6a94dc709e91b2ab3fe421d0",
- "reftest"
- ],
- "css/css-block/run-in-inline-table-between-002.xht": [
- "14398c440ddc0ebc8b649f19d83fd52a9bba1055",
- "reftest"
- ],
- "css/css-block/run-in-inline-table-between-003.xht": [
- "0bd512b2a4f512fa2e991fa947966a0ad6f74f81",
- "reftest"
- ],
- "css/css-block/run-in-linebox-001.xht": [
- "62239e5b0ef406a4d2eacf31cfb52d1c70f380d1",
- "visual"
- ],
- "css/css-block/run-in-linebox-002.xht": [
- "5a195c18d8f5b4121a5a87bc9d6bbf9bd863054c",
- "visual"
- ],
- "css/css-block/run-in-listitem-between-001.xht": [
- "9a1bd8d93df3eda014ac0d009f3ec3c04201c5cb",
- "reftest"
- ],
- "css/css-block/run-in-listitem-between-002.xht": [
- "2b1ad094020092479869a101d67964651db56cb3",
- "reftest"
- ],
- "css/css-block/run-in-listitem-between-003.xht": [
- "9bae8b25156e91b853c23eb15a70a91689b704c3",
- "reftest"
- ],
- "css/css-block/run-in-pre-ref.xht": [
- "865e5119c67a888f29e39928703eb3eb5b504b50",
- "support"
- ],
- "css/css-block/run-in-relpos-between-001.xht": [
- "18b879ea165db1e5f2ed01932296eda41d191b42",
- "reftest"
- ],
- "css/css-block/run-in-relpos-between-002.xht": [
- "d6397646005cf36745e392cc594a84005af830c2",
- "reftest"
- ],
- "css/css-block/run-in-relpos-between-003.xht": [
- "814503160217e264ae2d1f8e56dbd02a86ddb672",
- "reftest"
- ],
- "css/css-block/run-in-replaced-001-ref.xht": [
- "b09db13a8b6f0eaaa0d3e131181f0a39996bde4c",
- "support"
- ],
- "css/css-block/run-in-replaced-001.xht": [
- "cc3f7375e8dd13b8d0ceb718c76d8ce65fe249cd",
- "reftest"
- ],
- "css/css-block/run-in-restyle-001.xht": [
- "5c98c0ad78d612a4c69ad57ef721edaff8b169d2",
- "reftest"
- ],
- "css/css-block/run-in-restyle-002.xht": [
- "01a20be11ad94ad9f1b5dd6f0669b2204424dc27",
- "reftest"
- ],
- "css/css-block/run-in-restyle-003.xht": [
- "7b2a2bec64ebb168810307923fd585230ea32dec",
- "reftest"
- ],
- "css/css-block/run-in-run-in-between-001.xht": [
- "31b481c5e327aa5dee982f945ddacb293706bbf3",
- "reftest"
- ],
- "css/css-block/run-in-run-in-between-002.xht": [
- "7ff81653276feab32759c15c08547833aca86196",
- "reftest"
- ],
- "css/css-block/run-in-run-in-between-003.xht": [
- "5983122a9e015f2f08dc0cb565194869fc23d505",
- "reftest"
- ],
- "css/css-block/run-in-run-in-between-004.xht": [
- "a0e8126ec2ef495c62b48649c4b7c3eb766d4b8c",
- "reftest"
- ],
- "css/css-block/run-in-run-in-between-005.xht": [
- "1adb32a3078b7fb14015c6e5699545bf39f2a10f",
- "reftest"
- ],
- "css/css-block/run-in-run-in-between-006.xht": [
- "8dc1e460d109bb643382c4c39047f823d7b83a2a",
- "reftest"
- ],
- "css/css-block/run-in-run-in-between-007.xht": [
- "2a9efa67d02de0d9e687b6bb986a1593779866de",
- "reftest"
- ],
- "css/css-block/run-in-run-in-between-008.xht": [
- "4b3cf802de5cfe62f840fb43e1588d2ee0225f85",
- "reftest"
- ],
- "css/css-block/run-in-table-between-001.xht": [
- "5523b17d807abc82410cd68e1eeb9df64c497483",
- "reftest"
- ],
- "css/css-block/run-in-table-between-002.xht": [
- "2a3123b181e1840be435a47de3f9dfc5e0fbfa1a",
- "reftest"
- ],
- "css/css-block/run-in-table-between-003.xht": [
- "e815c990a75d09b1f899389d5766ffe88ef2b420",
- "reftest"
- ],
- "css/css-block/run-in-table-cell-between-001.xht": [
- "5a64485f150b9486ea8fc8b44b36eba0281843e4",
- "reftest"
- ],
- "css/css-block/run-in-table-cell-between-002.xht": [
- "e2f59a56f7d1ed153b10c7b2f471cdda5c3f2fdc",
- "reftest"
- ],
- "css/css-block/run-in-table-cell-between-003.xht": [
- "9575344b73ff90ee0a05e34f5981d757004b0f38",
- "reftest"
- ],
- "css/css-block/run-in-table-row-between-001.xht": [
- "c920f933e6e9c5c7c255cdc1c2f430e01563c9ea",
- "reftest"
- ],
- "css/css-block/run-in-table-row-between-002.xht": [
- "aa84045c62142d355f8a33b44ce06823cf70e058",
- "reftest"
- ],
- "css/css-block/run-in-table-row-between-003.xht": [
- "cc9b62f52ffa918b1889ae1d4927212fe61327da",
- "reftest"
- ],
- "css/css-block/run-in-text-between-001.xht": [
- "6c067847c8447b757c1cf7eca13cccb4591d7e8f",
- "reftest"
- ],
- "css/css-block/run-in-text-between-002.xht": [
- "9f07e1ed65b5967d410210bcd6881fe7a3dd26a4",
- "reftest"
- ],
- "css/css-block/run-in-text-between-003.xht": [
- "b71cecbbdda717bfe03a16b1ff06429b625187ef",
- "reftest"
- ],
- "css/css-block/run-in-text-between-004.xht": [
- "380f0d7df62fec663a6e56d0a2861f9a48f9c477",
- "reftest"
- ],
- "css/css-block/run-in-text-between-005.xht": [
- "a40c10072687534c2f57c3911647a64995dfd51f",
- "reftest"
- ],
- "css/css-block/run-in-text-ref.xht": [
- "4162c4ee8fe9a3609065054e1aff017e89608c61",
- "support"
- ],
- "css/css-block/support/black15x15.png": [
- "9252cae16138e45c07796fa5a10b6100ae703eaa",
- "support"
- ],
- "css/css-block/support/blue15x15.png": [
- "eb48032c07bfeb1d3b6be6e5c9c34d2fe2180767",
- "support"
- ],
- "css/css-block/support/blue96x96.png": [
- "99949c515749e66f471c3589ee7a0ef518aaccb5",
- "support"
- ],
- "css/css-block/support/green15x15.png": [
- "de1830c21195763f7327f270b14b6d50dfdfb21d",
- "support"
- ],
- "css/css-block/support/swatch-blue.png": [
- "e79958e10feeeed3db88dee9bae9ea80055593c5",
- "support"
- ],
- "css/css-block/table-anonymous-block-001.xht": [
- "4f471b69edd2465deffc9d925a74ee0b30ad6824",
- "visual"
- ],
- "css/css-block/table-layout-applies-to-004.xht": [
- "97f74eaf88a289c89d9c08e1c6865d28806cfbbb",
- "visual"
- ],
- "css/css-block/text-align-applies-to-004.xht": [
- "e223bc1cc7a84ac02fc8b9ee157903bf3b3c9d3f",
- "visual"
- ],
- "css/css-block/text-decoration-applies-to-004.xht": [
- "93eaff37aac086249c2f23d25289d4bd86f5f6da",
- "reftest"
- ],
- "css/css-block/text-indent-applies-to-004.xht": [
- "86911ad06c2b5172e6aa5cf793661dac00ad02ac",
- "visual"
- ],
- "css/css-block/text-transform-applies-to-004.xht": [
- "a0fdc00076eda2506592514656f7cb8ad66be948",
- "reftest"
- ],
- "css/css-block/top-applies-to-011.xht": [
- "2b585ecb53fd1c84ef92a93ab66ccbc921f34440",
- "visual"
- ],
- "css/css-block/unicode-bidi-applies-to-011.xht": [
- "11fab4558a7a3d43bf3f53759d02cc8834af7110",
- "visual"
- ],
- "css/css-block/vertical-align-applies-to-011.xht": [
- "99f448c1a05cbd9bb9bd1cec7797812608aec98e",
- "visual"
- ],
- "css/css-block/visibility-applies-to-011.xht": [
- "20695d8ba19bac1a499d973d5185e05b0bd4c1d8",
- "visual"
- ],
- "css/css-block/white-space-applies-to-004.xht": [
- "f387077d9b2071510cfbafcc5bf6476c0342a89c",
- "visual"
- ],
- "css/css-block/width-applies-to-011.xht": [
- "52820db0b9c9219535a52fe8a39c29139f2b4294",
- "reftest"
- ],
- "css/css-block/word-spacing-applies-to-004.xht": [
- "ea4e80bc4e560a727ac60983e17b85fcdfaa06e0",
- "visual"
- ],
- "css/css-block/z-index-applies-to-011.xht": [
- "71adc3eabed66929d71c1003ea9d5e10fee4f1a5",
- "visual"
- ],
"css/css-break/break-before-always-001.xht": [
- "4dab2b2a55f0636df539abe73688480c78e6901d",
+ "926ed3f96ba7b5c6dee79ea417746cbd60342579",
"visual"
],
"css/css-cascade/OWNERS": [
@@ -467853,7 +472801,7 @@
"support"
],
"css/css-color/blacktext-ref.html": [
- "89c791a3d59db9086af0eaab70052bfa69898740",
+ "5541159a1753a7e249c36d31f65e47d02e98f848",
"support"
],
"css/css-color/border-bottom-color.xht": [
@@ -467877,111 +472825,195 @@
"reftest"
],
"css/css-color/color-001.html": [
- "648bebf2d7f06bfa25de3446ed288e2ae13fb68f",
+ "7b4dfc7ef8867e578571db07d05ca18c77936c89",
"reftest"
],
"css/css-color/color-002.html": [
- "733b41bdddc8c8d6f1a1a3b61d13da22f0c30e0a",
+ "3ec299abc57c6ff6a55c604c751182abdadd6c8a",
"reftest"
],
"css/css-color/color-003.html": [
- "3c50885ef6132633e2f1976bbbfaecda21036980",
+ "ec85953fb0594db50a69ca9952092aeab403cf2c",
"reftest"
],
+ "css/css-color/color-resolving-hsl.html": [
+ "672137820a0289306d53b3866ffa1f00daacc019",
+ "testharness"
+ ],
+ "css/css-color/color-resolving-keywords.html": [
+ "2789a985787f59179c9bf1ad49ccb8dbbb8fea11",
+ "testharness"
+ ],
+ "css/css-color/color-resolving.html": [
+ "6eb90c067520ae0d2a9e52bccba6e03981007958",
+ "testharness"
+ ],
"css/css-color/currentcolor-001.html": [
- "60faf68f62cf5908218af340b6f4986d46df1c69",
+ "9563fc2934a198076ba32ec8659f0eca0515d953",
"reftest"
],
"css/css-color/currentcolor-002.html": [
- "050328d9f03f4db7f06dcdc330b5218b3e2ccdc7",
+ "aa684b5e5cb28456a345a315b1de546b8e6cd512",
"reftest"
],
+ "css/css-color/greensquare-ref.html": [
+ "5427df5d60b9ae063094858cfc8a7d3fcf22361a",
+ "support"
+ ],
"css/css-color/greentext-ref.html": [
"249e669a27d0b23de6267626566c5ce8af58bc25",
"support"
],
"css/css-color/hex-001.html": [
- "00628d82c36f5f40d85d81a2f1b288e7ff9bec0f",
+ "283cee2f6d5f11a89504abae29a3dece7495f177",
"reftest"
],
"css/css-color/hex-002.html": [
- "885e4684bc1c9e8cf9c0879f4852f17a7be4c6e0",
+ "2d8036af7162bb8d5bf6f58aeb208e5b59a5c603",
"reftest"
],
+ "css/css-color/hex-003-ref.html": [
+ "ae310bf928918fbfaeb9321492d64ca51b8d5b9d",
+ "support"
+ ],
"css/css-color/hex-003.html": [
- "36f6270be7b0e549fc523437651d3e2818293ce2",
- "visual"
+ "00a369523764c1e142b1443e334f9e2bb757c641",
+ "reftest"
],
"css/css-color/hex-004.html": [
- "3373d1578c9ee3c123dab1fef0930c950fc0f7cb",
- "visual"
+ "1faab141bd125d7e6652deed6ca23771989580cf",
+ "reftest"
+ ],
+ "css/css-color/hsl-001.html": [
+ "fa05f869ed6143538c863ca399affee8e12e33d5",
+ "reftest"
+ ],
+ "css/css-color/hsl-002.html": [
+ "e4ae3cf55bf9c28e6caaeb32f33910c7d83a85d8",
+ "reftest"
+ ],
+ "css/css-color/hsl-003.html": [
+ "2c2098102a8515449d82b152d4f56dbf405d05b9",
+ "reftest"
+ ],
+ "css/css-color/hsl-004.html": [
+ "e4d1bf5ebdf8073e56d471808f3e38972fef551e",
+ "reftest"
+ ],
+ "css/css-color/hsl-005.html": [
+ "942d3daaf06d625bb567a0349fee304b5a556f53",
+ "reftest"
+ ],
+ "css/css-color/hsl-006.html": [
+ "9a5e95f174ca185439f681b42d460af24ec64786",
+ "reftest"
+ ],
+ "css/css-color/hsl-007.html": [
+ "95f2428b37fd02dfb83e3b9b962c3a15bffbeedb",
+ "reftest"
+ ],
+ "css/css-color/hsl-008.html": [
+ "aa39a32dba60c9073dfe370cbedf4a048772429a",
+ "reftest"
+ ],
+ "css/css-color/hsla-001.html": [
+ "a25a2a4b85ddc4bf416241902f507063137b2661",
+ "reftest"
+ ],
+ "css/css-color/hsla-002.html": [
+ "13b556990055a877180547042a55cfd179f36238",
+ "reftest"
+ ],
+ "css/css-color/hsla-003.html": [
+ "6dfa73021a4d7557c15051e2047023288df3e713",
+ "reftest"
+ ],
+ "css/css-color/hsla-004.html": [
+ "c3d1639b537d79c9cf778f2bb512fa9e23f6bf1b",
+ "reftest"
+ ],
+ "css/css-color/hsla-005.html": [
+ "953e2dd5ec00c16b77510b62f9e349bdf837154e",
+ "reftest"
+ ],
+ "css/css-color/hsla-006.html": [
+ "7ff9ba828aec73405305ced18c9293d86b50690d",
+ "reftest"
+ ],
+ "css/css-color/hsla-007.html": [
+ "6e1fd3eef32751dc914448a565f222cadbbeb356",
+ "reftest"
+ ],
+ "css/css-color/hsla-008.html": [
+ "279600290a3969b44259ea5f5c53253998c6adbe",
+ "reftest"
],
"css/css-color/htaccess": [
"b7599c7f62cb964ae36008d5f7fa4b82b14cc3e9",
"support"
],
"css/css-color/lab-001.html": [
- "d5b7ae9e433101eca928b8ad4cfadc051ee2ccc2",
+ "a2a7c21f7a14b48cbeaaff2d88058ed3fee5d93d",
"reftest"
],
"css/css-color/lab-002.html": [
- "877761ad909cac559305c225f7e556288d031188",
+ "d3019fc562d3e2ae69e6efd3dbf4d0e1e3f8b1ad",
"reftest"
],
"css/css-color/lab-003.html": [
- "84158f12dfb72223d37e3b5559eb157f28a6217b",
+ "0723ed9d6c7414565e3dfed19b133f8450d6c092",
"reftest"
],
"css/css-color/lab-004.html": [
- "ae569fde05db02779297c871c507d6f5881e0676",
+ "51f4804db8a2f9e0e388c81cb1fee589e1bbdd28",
"reftest"
],
"css/css-color/lab-005.html": [
- "da99776896644f5b1ec799e4e4fd5e3bf2c6d5c8",
+ "db07745d8a25a48ea3bcf1b8d3ea56c58cdbc9af",
"reftest"
],
"css/css-color/lab-006.html": [
- "cfcdd14e2116de527a0dd961dcbaca89f8b027bd",
+ "eea09960176bb28aba7a05bde9acacb1960db649",
"reftest"
],
"css/css-color/lab-007.html": [
- "6f875b291924b0e4268bca4f4292a5a51001de78",
+ "c65ede9c328ddf85fc607a5ac78fd4897d25c926",
"reftest"
],
"css/css-color/lch-001.html": [
- "8149a8db744fe40d3ad76fd8091c2d0bece691d4",
+ "5b18f33c3947d8d9be59b886442f6e51248c5db6",
"reftest"
],
"css/css-color/lch-002.html": [
- "decd69eb8ce41f0e717b6eb3b219428fe1ee96ea",
+ "71aa14524a1b605daef298be6ac18f91a5740098",
"reftest"
],
"css/css-color/lch-003.html": [
- "bbba716dad9213c444a62c20ee1d6c4bf6b581d9",
+ "95d2f1189d42df113b964377bc69aa29cce3d134",
"reftest"
],
"css/css-color/lch-004.html": [
- "6e4e639970fdc83935f4a3adc10be76bc90a3c82",
+ "5e3588caa84df218f959bcf3fa98908e7a97c5a2",
"reftest"
],
"css/css-color/lch-005.html": [
- "4d4477a4dd83778dbedd67502175cee5d2de809f",
+ "9ed500d2841d09b3db270f4c4c6624e231fa5915",
"reftest"
],
"css/css-color/lch-006.html": [
- "9ef709aa95792f6e5acb7df3ef68f9e36f46d664",
+ "7eb1d1e686a1bc99621e2ecaa3b691eb7b81915b",
"reftest"
],
"css/css-color/lch-007.html": [
- "8f9a89d13ba8b510bd1b1d9db4ef3e68ea1f68e4",
+ "597f775935650c4259de1cdc85afdacb496aa3bb",
"reftest"
],
"css/css-color/named-001.html": [
- "b128c069ecd946774cd1a99636616b4608ce9126",
+ "fad454c9b86d70e19fb89265c8e131ff381ed2a0",
"reftest"
],
"css/css-color/rebeccapurple-ref.html": [
- "17e2ef8ba560dbe1791473759fb8580528c8df79",
+ "e089e2daad5e5db7131015bf45739e64050c6b36",
"support"
],
"css/css-color/rgb-001.html": [
@@ -468064,29 +473096,45 @@
"6ef52952d60deab37c102778a0fb56db704d98ed",
"reftest"
],
+ "css/css-color/t32-opacity-basic-0.0-a-ref.html": [
+ "97a8963a38c6dbbb18a594f11c9bb2c7e5f0a2b1",
+ "support"
+ ],
"css/css-color/t32-opacity-basic-0.0-a.xht": [
- "641b6fe0e8b58160019ac388a1882258c8c3b119",
- "visual"
+ "36abb11ff05c7968832d741f9a02269ce87ff141",
+ "reftest"
],
"css/css-color/t32-opacity-basic-0.6-a.xht": [
"9d9df3be674bb5f1337be87670d46c0eed026e67",
"visual"
],
+ "css/css-color/t32-opacity-basic-1.0-a-ref.html": [
+ "0d121aca3970b1271f2b4849dfe49ef5798e7920",
+ "support"
+ ],
"css/css-color/t32-opacity-basic-1.0-a.xht": [
- "a7a452594764791117888b0dcd3739d42ffd5796",
- "visual"
+ "182ecc55a7ea82037c5999cbd51b51aab1c7809a",
+ "reftest"
],
"css/css-color/t32-opacity-clamping-0.0-b.xht": [
- "7c70a818e5bb401e2960972859c52c159c95b876",
- "visual"
+ "3e797a55789abf7162b65f30bbf550a27a7ee314",
+ "reftest"
+ ],
+ "css/css-color/t32-opacity-clamping-1.0-b-ref.html": [
+ "c138f6411fd49193a8cbbe74c920dc64c2851a43",
+ "support"
],
"css/css-color/t32-opacity-clamping-1.0-b.xht": [
- "aa6bfc4d262295dbc51b9bb0487c969eae00bddc",
- "visual"
+ "b8fa4d8d0e54a0a2fc8f945af7f436181fa30b7b",
+ "reftest"
+ ],
+ "css/css-color/t32-opacity-offscreen-b-ref.html": [
+ "f727493bfcd31d29a98b0b69982c85e7785bdf23",
+ "support"
],
"css/css-color/t32-opacity-offscreen-b.xht": [
- "47f51b98cb3789796bec5e8eccf3a304c2cfb0c4",
- "visual"
+ "dc3520769d1c6b310602423121d7cbe7a6349bbb",
+ "reftest"
],
"css/css-color/t32-opacity-offscreen-multiple-boxes-1-c-ref.html": [
"3594dd7b57e2b39cab4cb628f6477b2b2a4f8cfb",
@@ -468104,21 +473152,33 @@
"e02af1fea5690440983c959a6dd94fef08f41ad7",
"reftest"
],
+ "css/css-color/t32-opacity-offscreen-with-alpha-c-ref.html": [
+ "d1b756d83fdf8e3aa27a37a600c0939166b1ce43",
+ "support"
+ ],
"css/css-color/t32-opacity-offscreen-with-alpha-c.xht": [
- "bd319bbe03dabc9b0bf609a9ed179a4fd8f50ba2",
- "visual"
+ "8834024cf1e7d6743af492fd1d1526963b795186",
+ "reftest"
],
"css/css-color/t32-opacity-zorder-c.xht": [
"d9c0793e3afa75b3e5b7860b1f0361b25a2490f4",
"visual"
],
+ "css/css-color/t41-html4-keywords-a-ref.html": [
+ "fe35d8991f77bec0c5b9e29354001650fc0939e3",
+ "support"
+ ],
"css/css-color/t41-html4-keywords-a.xht": [
- "bd840b00197a086e255e50efe597725f70f167ef",
- "visual"
+ "e08edc3b93fbfd9b7161aa0cc28485af280b8a3e",
+ "reftest"
+ ],
+ "css/css-color/t421-rgb-clip-outside-gamut-b-ref.html": [
+ "8806ba740a49bef0d53dc49bfb24a525373bf64a",
+ "support"
],
"css/css-color/t421-rgb-clip-outside-gamut-b.xht": [
- "1a8665f07bc06176ec3e395656db26a87ca1884b",
- "visual"
+ "6e82b4076c59aa8a9c43f26c07dd14c33e0bc39c",
+ "reftest"
],
"css/css-color/t421-rgb-func-int-a.xht": [
"affae2fcb347e5945b7341b8228d8e1009729977",
@@ -468144,6 +473204,10 @@
"84148b6e86b2a3a68aacdec844019436d0f836c7",
"reftest"
],
+ "css/css-color/t421-rgb-hex3-expand-b-ref.html": [
+ "dbbee69e8d5443b8ef7a4efd2401c5c24b3e81cb",
+ "support"
+ ],
"css/css-color/t421-rgb-hex3-expand-b.xht": [
"771ed736fef0db765beb042a658e55784c96c843",
"visual"
@@ -468152,13 +473216,17 @@
"ee949724f35b9e5579f821bbff4a708b2528dd7d",
"reftest"
],
+ "css/css-color/t421-rgb-values-meaning-b-ref.html": [
+ "dfdf69248220eb810031c2be74d8a58ee7990eac",
+ "support"
+ ],
"css/css-color/t421-rgb-values-meaning-b.xht": [
- "ee4de49d2eb086958078f75ad87c1111f7de7ad7",
- "visual"
+ "39c64ce7bd432b452fa970ff3147cf2eb5938c80",
+ "reftest"
],
"css/css-color/t422-rgba-a0.0-a.xht": [
- "c99a9fc1f4193b0757a5ab704425ee761eadba16",
- "visual"
+ "9c724ccc138d206374d86de3c07f75097d05c8e3",
+ "reftest"
],
"css/css-color/t422-rgba-a0.6-a.xht": [
"b113473c73598e0ac6f54669c0b69bf35315dd74",
@@ -468240,9 +473308,13 @@
"52cd48c468414a3e6d94a31c0bab6f5d04bfcc3c",
"reftest"
],
+ "css/css-color/t422-rgba-values-meaning-b-ref.html": [
+ "68e97f16df077b9103bfaf9380b6741141391982",
+ "support"
+ ],
"css/css-color/t422-rgba-values-meaning-b.xht": [
- "cf37fdfa70940f3892d1bae3882a99a4512f58aa",
- "visual"
+ "acf8b78878f7e802ea942ef971bd1488ad7c3421",
+ "reftest"
],
"css/css-color/t423-transparent-1-a.xht": [
"3cc81ffe93d23180f24b7379c37276214074846b",
@@ -468272,9 +473344,13 @@
"0ed35609de1852fa2870276606ab042291bd02bb",
"reftest"
],
+ "css/css-color/t424-hsl-h-rotating-b-ref.html": [
+ "9ca080fa1c31a9c7245c0d6451d8965500e77efd",
+ "support"
+ ],
"css/css-color/t424-hsl-h-rotating-b.xht": [
- "acae31c06007d39c80b2796c99c1946ccde209bb",
- "visual"
+ "b4f0e1c01af1a7c3c9ab31a34307e8f1ac70ec55",
+ "reftest"
],
"css/css-color/t424-hsl-parsing-f-ref.html": [
"286da104ec5ceaac14c64fec235b2cc109ae6d3a",
@@ -468416,13 +473492,17 @@
"257c0df648f50c198036a710151aca334522fed5",
"reftest"
],
+ "css/css-color/t425-hsla-h-rotating-b-ref.html": [
+ "cd455e72ebe236dc65f86dc9f480d9952c6730b7",
+ "support"
+ ],
"css/css-color/t425-hsla-h-rotating-b.xht": [
- "07a0c79524074b22ac7ae73f9bcb56d8ba2bc70d",
- "visual"
+ "1be1bd816dc4e2ee02a129879dfc53e571222a82",
+ "reftest"
],
"css/css-color/t425-hsla-onscreen-b.xht": [
- "de76f1a5104324c95c59eee4cdb2601790e178c5",
- "visual"
+ "544cf0bbf9cf4330090f559b0f5609b3dc44015c",
+ "reftest"
],
"css/css-color/t425-hsla-onscreen-multiple-boxes-c.xht": [
"d2dc37794501b0ef2b05409c89367c4e01ac4ccb",
@@ -468440,9 +473520,13 @@
"a9e194307d3ed4ee0f9aacf3c780598bd18d7d40",
"reftest"
],
+ "css/css-color/t43-svg-keywords-a-ref.html": [
+ "9119ed188422f341e6f6f7befbcac55cc24d890b",
+ "support"
+ ],
"css/css-color/t43-svg-keywords-a.xht": [
- "b779696e6c036e877bb84cd978f1e944ce0fd788",
- "visual"
+ "13a33016ff37bc8750efad1c4ef7357427d69f3f",
+ "reftest"
],
"css/css-color/t44-currentcolor-background-b-ref.html": [
"53ee23e6007353180358a3291698fa66ae3d43b7",
@@ -468473,7 +473557,7 @@
"visual"
],
"css/css-color/whitetext-ref.html": [
- "fceb01c868ef9ac8be432bec04c9ef1c9939221d",
+ "e832afff6067587e429b47ed0ea1756a4bad3b81",
"support"
],
"css/css-conditional/OWNERS": [
@@ -468661,9 +473745,17 @@
"support"
],
"css/css-conditional/test_group_insertRule.html": [
- "948230661efe702e443fe7e973d7c4995144588e",
+ "c805d45e2361bd67ebf1ca0605807d7384b09a7d",
"testharness"
],
+ "css/css-contain/contain-style-counters-ref.html": [
+ "295abc8d8c2490f3ff16566e49e9c77bf125461f",
+ "support"
+ ],
+ "css/css-contain/contain-style-counters.html": [
+ "056b3597f3555c803c74a8f6277a06626efd12ea",
+ "reftest"
+ ],
"css/css-counter-styles/OWNERS": [
"820cad495f069d1badb3a727b9a2514269c6008e",
"support"
@@ -469328,6 +474420,10 @@
"ab66821c508ced9656c769ff2647c7f9d57e4b15",
"reftest"
],
+ "css/css-display/display-contents-before-after-003.html": [
+ "2c15d52fdcb0ef9de97beb7bff8fdd2a733f1d67",
+ "reftest"
+ ],
"css/css-display/display-contents-block-001.html": [
"c26501b3a2da59dd1615a492d580e26e401da485",
"reftest"
@@ -469340,10 +474436,18 @@
"a2ebae461e59f93107b1abcf88f38fa2e484371c",
"reftest"
],
+ "css/css-display/display-contents-button.html": [
+ "31f559d839f47e4034910ecf9224cccb3d44cac4",
+ "reftest"
+ ],
"css/css-display/display-contents-computed-style.html": [
"bf523ee19c5ff481a3f91f8eb124eb83301738c5",
"testharness"
],
+ "css/css-display/display-contents-details.html": [
+ "d1f62084c5adc3ba7a86306704f804d4cbe0428c",
+ "reftest"
+ ],
"css/css-display/display-contents-dynamic-before-after-001.html": [
"9142d9f1ad5b5e9a5f5705a44c962084f023a3c6",
"reftest"
@@ -469408,6 +474512,14 @@
"4fe143c25be9ecc08e58428f0c588f72c5cb8a3f",
"reftest"
],
+ "css/css-display/display-contents-dynamic-pseudo-insertion-001-ref.html": [
+ "d64e6fa233d294236f1a773e2d5a3ea214c64d25",
+ "support"
+ ],
+ "css/css-display/display-contents-dynamic-pseudo-insertion-001.html": [
+ "221fb940d34860f62541ad53bb4b3834f3552577",
+ "reftest"
+ ],
"css/css-display/display-contents-dynamic-table-001-inline.html": [
"5c105a711c083e61eefc4121c707d3ca2ffda3ec",
"reftest"
@@ -469424,14 +474536,26 @@
"c874f59947d37659e640d4e0abb8a0dc0f03927d",
"reftest"
],
+ "css/css-display/display-contents-fieldset.html": [
+ "5532214fa9e6d5b8a6423701760204f96efd65fe",
+ "reftest"
+ ],
"css/css-display/display-contents-first-letter-001.html": [
"acfaf8f68595c7eb36585309b9d6b0bc5c0ffe41",
"reftest"
],
+ "css/css-display/display-contents-first-letter-002.html": [
+ "26a464c21e2dc798ef1b0187e93959b80633acc3",
+ "reftest"
+ ],
"css/css-display/display-contents-first-line-001.html": [
"19f4bc895d895a6dd62b638960b4b7f2f26f5752",
"reftest"
],
+ "css/css-display/display-contents-first-line-002.html": [
+ "2344b7ec5bf451951069ff9ac3587a6338bd3196",
+ "reftest"
+ ],
"css/css-display/display-contents-flex-001-ref.html": [
"30689a922a0172d3379e947a47b55e49d95c83cb",
"support"
@@ -469468,6 +474592,14 @@
"f235a8a06a76d156322822961609a9366f573536",
"reftest"
],
+ "css/css-display/display-contents-line-height-ref.html": [
+ "68d18b2d72b79547a2433ec8c7b230907906a0d4",
+ "support"
+ ],
+ "css/css-display/display-contents-line-height.html": [
+ "6efd30ecfce1a5f1b2175847a36ea6cc4af148b2",
+ "reftest"
+ ],
"css/css-display/display-contents-list-001-ref.html": [
"e5c5e9599b5f52c3ee9662bb70ae0c3c35b06530",
"support"
@@ -469504,14 +474636,6 @@
"f9d1eaa996cfe84ba9600383bd6c38d179fcbe91",
"support"
],
- "css/css-display/display-contents-replaced-001-ref.html": [
- "09008a1d912eb30702be95db99b8e5fd6604a768",
- "support"
- ],
- "css/css-display/display-contents-replaced-001.html": [
- "4030618381ad36d2c03be81b3b97cdb87977ddec",
- "reftest"
- ],
"css/css-display/display-contents-state-change-001-ref.html": [
"f7e25855cc7ef1896a9a52005d3c1379bf74746b",
"support"
@@ -469520,6 +474644,14 @@
"0a689fbe90be794772c66d59b033d15336e6dfe3",
"reftest"
],
+ "css/css-display/display-contents-svg-elements-ref.html": [
+ "3e4ddf5f740d8fa688bcbb24201be0a6d4349017",
+ "support"
+ ],
+ "css/css-display/display-contents-svg-elements.html": [
+ "93573e17090a860bb09c2a208d925afac9cb17fd",
+ "reftest"
+ ],
"css/css-display/display-contents-table-001-ref.html": [
"9de4ee8151dbfa3c8e2c381ddd213e51b04f70c1",
"support"
@@ -469540,6 +474672,14 @@
"95db05421f7ca48ed528db9fa2c23cfd5ccbac97",
"reftest"
],
+ "css/css-display/display-contents-text-inherit-ref.html": [
+ "b248e78a0255b923c4ed4aa269e65f53b6386bf4",
+ "support"
+ ],
+ "css/css-display/display-contents-text-inherit.html": [
+ "c88c1d5fe8d2895ba3774d09ccb7a6adbe6c391b",
+ "reftest"
+ ],
"css/css-display/display-contents-text-only-001-ref.html": [
"31474dc32adce5d808657170841e3307215f8105",
"support"
@@ -469556,6 +474696,10 @@
"f51f4df4bc1e93e84fc53a0d3352f737f6a68c0f",
"reftest"
],
+ "css/css-display/display-contents-unusual-html-elements-none.html": [
+ "dc354fb4f1896f655186cf57dd100f475a4ce5f0",
+ "reftest"
+ ],
"css/css-display/display-flow-root-001-ref.html": [
"a9d3c569ae10db047d3f6ff3b0888a6d74cece61",
"support"
@@ -469564,6 +474708,970 @@
"f7d3cda238b0209165a77571c59af0701bcede17",
"reftest"
],
+ "css/css-display/run-in/OWNERS": [
+ "6634529fb114ab2e29cb2fa4a633289ee9038c22",
+ "support"
+ ],
+ "css/css-display/run-in/after-content-display-004.xht": [
+ "61fd73789062cb65193cd3e2ab535151b2565b8b",
+ "visual"
+ ],
+ "css/css-display/run-in/anonymous-box-generation-002.xht": [
+ "d8b897bec271896fa3362a6aef4a2c628ebbe0b3",
+ "visual"
+ ],
+ "css/css-display/run-in/background-applies-to-011.xht": [
+ "a4f27fa89ec568aaeeccd6867b5dd1afcb4b86f6",
+ "visual"
+ ],
+ "css/css-display/run-in/background-attachment-applies-to-011.xht": [
+ "02c5f4feaf50905f325b00d2635a77e631cbfe84",
+ "visual"
+ ],
+ "css/css-display/run-in/background-color-applies-to-011.xht": [
+ "8b3b119f15080301b1314ea5b45e270b2823df89",
+ "visual"
+ ],
+ "css/css-display/run-in/background-image-applies-to-011.xht": [
+ "9e9a51ef23a8968edc5d4a4c6f0305f6ddf0d7ed",
+ "visual"
+ ],
+ "css/css-display/run-in/background-position-applies-to-011.xht": [
+ "ff1707da202a90261724386b16a401aef3b48f6e",
+ "visual"
+ ],
+ "css/css-display/run-in/background-repeat-applies-to-011.xht": [
+ "88339d4a1b2cfc2fdff0905e592dcfaf75750cbb",
+ "visual"
+ ],
+ "css/css-display/run-in/before-content-display-004.xht": [
+ "d7f0c8005d0ab64c13b48c0589c1c0083bcb254b",
+ "visual"
+ ],
+ "css/css-display/run-in/border-applies-to-011.xht": [
+ "36eded364e030b01fe560e74e50f8fa8c118a433",
+ "visual"
+ ],
+ "css/css-display/run-in/border-bottom-applies-to-011.xht": [
+ "daad8099c06632a6423a90a913fef6643bef2366",
+ "visual"
+ ],
+ "css/css-display/run-in/border-bottom-color-applies-to-011.xht": [
+ "1f06ae35fa63cdc01c50754e945135cd65c81336",
+ "visual"
+ ],
+ "css/css-display/run-in/border-bottom-style-applies-to-011.xht": [
+ "f14782efe820b83b706b3ff6ecf1893bff256e42",
+ "visual"
+ ],
+ "css/css-display/run-in/border-bottom-width-applies-to-011.xht": [
+ "20389e139890e0e699712d9d9fc967ea0cb81d97",
+ "visual"
+ ],
+ "css/css-display/run-in/border-collapse-applies-to-004.xht": [
+ "44cbf688dbc21665f0cab3f608521293fc562796",
+ "visual"
+ ],
+ "css/css-display/run-in/border-color-applies-to-011.xht": [
+ "29ae73e9211b753a7d687ba7e73e30daf052d169",
+ "visual"
+ ],
+ "css/css-display/run-in/border-left-applies-to-011.xht": [
+ "74d022f4145b07d71c0ac5cd008df29138ae4d31",
+ "visual"
+ ],
+ "css/css-display/run-in/border-left-color-applies-to-011.xht": [
+ "08bd2a4ec6c575b8121e96bbdb8a0b2aa74140e3",
+ "visual"
+ ],
+ "css/css-display/run-in/border-left-style-applies-to-011.xht": [
+ "6270c843418d4eb40cccb1705ab2b17ac0f92f3d",
+ "visual"
+ ],
+ "css/css-display/run-in/border-left-width-applies-to-011.xht": [
+ "7496c6f5f5b46eb69de37176935cca76ad56d6bb",
+ "visual"
+ ],
+ "css/css-display/run-in/border-right-applies-to-011.xht": [
+ "78cd49b2e855a61cecb4e1b523841cab00081643",
+ "visual"
+ ],
+ "css/css-display/run-in/border-right-color-applies-to-011.xht": [
+ "e2391f060977badec62709241a824f97e597eccd",
+ "visual"
+ ],
+ "css/css-display/run-in/border-right-style-applies-to-011.xht": [
+ "ae3f43f85ef5266eeda294bf4524d125e871a317",
+ "visual"
+ ],
+ "css/css-display/run-in/border-right-width-applies-to-011.xht": [
+ "3209cbf4c1aa5d5c023ed13a17eac529052652a8",
+ "visual"
+ ],
+ "css/css-display/run-in/border-spacing-applies-to-004.xht": [
+ "862913eace05677ad332a5c76532599694bf69f6",
+ "visual"
+ ],
+ "css/css-display/run-in/border-style-applies-to-011.xht": [
+ "2ddc53bf2d5b8ab1e5c3b16e48ae5a2036fe31ea",
+ "visual"
+ ],
+ "css/css-display/run-in/border-top-applies-to-011.xht": [
+ "ba40b08236b9c5993613af13f8dd96d3932c8475",
+ "visual"
+ ],
+ "css/css-display/run-in/border-top-color-applies-to-011.xht": [
+ "b5184bc4fde674a806dccd7a061bd86fdb2f15a0",
+ "visual"
+ ],
+ "css/css-display/run-in/border-top-style-applies-to-011.xht": [
+ "75e780e649cac1c0e695ac8275a8a588751b939a",
+ "visual"
+ ],
+ "css/css-display/run-in/border-top-width-applies-to-011.xht": [
+ "9d5bedf58e1f861eab96f9d0b9fe90b58e021413",
+ "visual"
+ ],
+ "css/css-display/run-in/border-width-applies-to-011.xht": [
+ "a7126e39d2d60e8f4d2f018cea4d001b8cc94066",
+ "visual"
+ ],
+ "css/css-display/run-in/bottom-applies-to-011.xht": [
+ "f8e7490e71cf3899de316e306cea3947a17e1f77",
+ "visual"
+ ],
+ "css/css-display/run-in/caption-side-applies-to-004.xht": [
+ "ce42ae349ae0e76af642f7e7ad19c812690562df",
+ "visual"
+ ],
+ "css/css-display/run-in/clear-applies-to-011.xht": [
+ "3279ebd7562dcbf8c29f872e4d3ce76447c6d9c8",
+ "visual"
+ ],
+ "css/css-display/run-in/clear-runin-001.xht": [
+ "bcaed5391dc08f90de390194e84df4db9b0d8e38",
+ "visual"
+ ],
+ "css/css-display/run-in/color-applies-to-011.xht": [
+ "605a38365b79fa452ab47c9d1b7e77e68bc96218",
+ "visual"
+ ],
+ "css/css-display/run-in/counter-increment-applies-to-011.xht": [
+ "868b48e97ad5644be25a5456cf5c9529f01e72e1",
+ "reftest"
+ ],
+ "css/css-display/run-in/counter-reset-applies-to-011.xht": [
+ "7f634aa09cfad1aaa1e9fb7fa9e316fa33608da8",
+ "reftest"
+ ],
+ "css/css-display/run-in/cursor-applies-to-011.xht": [
+ "cc19264db7880b0a52412e501cb2852d33fd175d",
+ "manual"
+ ],
+ "css/css-display/run-in/direction-applies-to-011.xht": [
+ "44512ff84708807b22f18a79bb18623a4b933f27",
+ "visual"
+ ],
+ "css/css-display/run-in/display-004.xht": [
+ "7471ec0ca8d4f375feb49136e468dc06ab52f265",
+ "visual"
+ ],
+ "css/css-display/run-in/empty-cells-applies-to-004.xht": [
+ "1a5763fed630b9d731f2af9961514be9af9f907e",
+ "visual"
+ ],
+ "css/css-display/run-in/first-line-pseudo-009.xht": [
+ "5636f5b08a197f797debed5dea6726315578828f",
+ "visual"
+ ],
+ "css/css-display/run-in/float-applies-to-011.xht": [
+ "01efe6f3b3298581cb45d2850b1f9732868fd381",
+ "visual"
+ ],
+ "css/css-display/run-in/font-applies-to-004.xht": [
+ "9b51369f7b55b2be28ae1c472a446e0de5e476e0",
+ "visual"
+ ],
+ "css/css-display/run-in/font-family-applies-to-004.xht": [
+ "627f012fde5832fa4fc098b2b1423e4db05ce95b",
+ "visual"
+ ],
+ "css/css-display/run-in/font-size-applies-to-004.xht": [
+ "a3bcca3e7c843c4e0fa6ccb72a2b5ce6a193eecf",
+ "visual"
+ ],
+ "css/css-display/run-in/font-style-applies-to-004.xht": [
+ "777b8cb354110c153f8319035c1fe5c9d345a890",
+ "reftest"
+ ],
+ "css/css-display/run-in/font-variant-applies-to-004.xht": [
+ "cf8abd6c2c6b0140672662d13a5609b8a903d0b2",
+ "reftest"
+ ],
+ "css/css-display/run-in/font-weight-applies-to-004.xht": [
+ "65df6e8576ac3677d9a496919c4ef438b82732af",
+ "reftest"
+ ],
+ "css/css-display/run-in/height-applies-to-011.xht": [
+ "dd0d58d2cf6409c453e3671be60704be870bb4d9",
+ "reftest"
+ ],
+ "css/css-display/run-in/left-applies-to-011.xht": [
+ "ac86f465cdda1d482a5d336e3055d219b7547b9c",
+ "visual"
+ ],
+ "css/css-display/run-in/letter-spacing-applies-to-004.xht": [
+ "cfd1860e79789d3f6b083fcbfd87863f9c5d6bdf",
+ "reftest"
+ ],
+ "css/css-display/run-in/line-height-applies-to-011.xht": [
+ "5a504d5186b825f7a3ce231e7467319ecde7864c",
+ "visual"
+ ],
+ "css/css-display/run-in/list-style-applies-to-011.xht": [
+ "01a3a5f312f88eaf8e2db2b63547b62fc3d40c30",
+ "reftest"
+ ],
+ "css/css-display/run-in/list-style-image-applies-to-011.xht": [
+ "e6d6ef7fcfe75338a9f4c5d74bcf8695602417d8",
+ "visual"
+ ],
+ "css/css-display/run-in/list-style-position-applies-to-011.xht": [
+ "86092ff94df9f7268dce918a9edcc6ff86b570e0",
+ "visual"
+ ],
+ "css/css-display/run-in/list-style-type-applies-to-011.xht": [
+ "4a32082111b2e4ce95fe634b6533d9150345d9d2",
+ "reftest"
+ ],
+ "css/css-display/run-in/margin-applies-to-011.xht": [
+ "23b14b25f9629a21eb30d27e9d8dadb15fc05b4e",
+ "visual"
+ ],
+ "css/css-display/run-in/margin-bottom-applies-to-011.xht": [
+ "c528dcd41815a387a9e3625821135da92d7f032b",
+ "visual"
+ ],
+ "css/css-display/run-in/margin-left-applies-to-011.xht": [
+ "124c70029386ebd9a72571a2177d968544d46421",
+ "visual"
+ ],
+ "css/css-display/run-in/margin-right-applies-to-011.xht": [
+ "e819e775b2b1395c5f8210bb37beee1f1f8859b9",
+ "visual"
+ ],
+ "css/css-display/run-in/margin-top-applies-to-011.xht": [
+ "dd48bef2f6e5fec6a57cef62997affd1a9d882c7",
+ "visual"
+ ],
+ "css/css-display/run-in/max-height-applies-to-011.xht": [
+ "8d828771e67e4024c7d048b788b6111f49cf8be7",
+ "reftest"
+ ],
+ "css/css-display/run-in/max-width-applies-to-011.xht": [
+ "4e1a5517a853ccedaa8e2d8e93dfcf8692d6d228",
+ "reftest"
+ ],
+ "css/css-display/run-in/min-height-applies-to-011.xht": [
+ "07465372180e85e3d265f445a2fcd6c9b967bd14",
+ "reftest"
+ ],
+ "css/css-display/run-in/min-width-applies-to-011.xht": [
+ "c4088a9a0785e4ab882e66f8e5e54888aec562ae",
+ "reftest"
+ ],
+ "css/css-display/run-in/outline-applies-to-011.xht": [
+ "191fa8aafcab7760a159b1e4bb4f1e763d79ec22",
+ "visual"
+ ],
+ "css/css-display/run-in/outline-color-applies-to-011.xht": [
+ "c8ef9366d397901fc7cfc60fcfeb7e779cc2b629",
+ "visual"
+ ],
+ "css/css-display/run-in/outline-style-applies-to-011.xht": [
+ "395b8328ab7ffe7a8e542b377383c6f2fc23e168",
+ "visual"
+ ],
+ "css/css-display/run-in/outline-width-applies-to-011.xht": [
+ "d367fcd30a2a5cace628c6414bdaea814c64434f",
+ "visual"
+ ],
+ "css/css-display/run-in/overflow-applies-to-011.xht": [
+ "94ec0236bb7babe73b3bfa3135ef59077792a14c",
+ "visual"
+ ],
+ "css/css-display/run-in/padding-applies-to-011.xht": [
+ "06043f0bc1ee56f9c9aa14ee894c7f71ae66d08c",
+ "visual"
+ ],
+ "css/css-display/run-in/padding-bottom-applies-to-011.xht": [
+ "1f99d22839b620ead278902451b4393d16320cdf",
+ "visual"
+ ],
+ "css/css-display/run-in/padding-left-applies-to-011.xht": [
+ "c46dcccd743de4c4af7e159cdab344e9e6e8c943",
+ "visual"
+ ],
+ "css/css-display/run-in/padding-right-applies-to-011.xht": [
+ "b828450be59f1a3f52a60dec63f98255b21901ed",
+ "visual"
+ ],
+ "css/css-display/run-in/padding-top-applies-to-011.xht": [
+ "9674c7b62e79e1cd886db2b4b84f5cbb5514aece",
+ "visual"
+ ],
+ "css/css-display/run-in/position-applies-to-011.xht": [
+ "0720bf370b26ef35c9e2ea50c9faead2c98b8139",
+ "visual"
+ ],
+ "css/css-display/run-in/quotes-applies-to-011.xht": [
+ "42ac25a7df37605934ea5ce84a74b43829dcfce8",
+ "reftest"
+ ],
+ "css/css-display/run-in/right-applies-to-011.xht": [
+ "a80a4cee631686ec8df21372dacd609be35b8fa6",
+ "visual"
+ ],
+ "css/css-display/run-in/run-in-001.xht": [
+ "b0a4627e8ac492cd231537db0bdc18dc27dc7104",
+ "visual"
+ ],
+ "css/css-display/run-in/run-in-002.xht": [
+ "544419a0449424193f44b911e248fbfd0de23246",
+ "visual"
+ ],
+ "css/css-display/run-in/run-in-003.xht": [
+ "e9a318519677aab01514814a6ba97c9a936807fb",
+ "visual"
+ ],
+ "css/css-display/run-in/run-in-004.xht": [
+ "7b0837c9ee4571e49f97b083b855fcd691865bb3",
+ "visual"
+ ],
+ "css/css-display/run-in/run-in-005.xht": [
+ "5b97ec05a44c1d7cf7895808255ba2fc18c80f86",
+ "visual"
+ ],
+ "css/css-display/run-in/run-in-006.xht": [
+ "a59419542724e65457923d0389004a3eec2a4f77",
+ "visual"
+ ],
+ "css/css-display/run-in/run-in-007.xht": [
+ "c175c5311ac085143da2e59f54f5774ed5f2f5e9",
+ "visual"
+ ],
+ "css/css-display/run-in/run-in-008.xht": [
+ "1d0865927beea6342fff5c4fc69040acc9489512",
+ "visual"
+ ],
+ "css/css-display/run-in/run-in-009.xht": [
+ "71095c3996aff8d47fe520ff8fee2fa3b1cb2ebf",
+ "visual"
+ ],
+ "css/css-display/run-in/run-in-010.xht": [
+ "49213be77399f1a831d5b4b1a2f34fddeaa79b22",
+ "visual"
+ ],
+ "css/css-display/run-in/run-in-011.xht": [
+ "1974e33d93c187081046429312c76ea134df919e",
+ "visual"
+ ],
+ "css/css-display/run-in/run-in-012.xht": [
+ "ee5dac6b692fd283d7a097682dadfa6b626a05e1",
+ "visual"
+ ],
+ "css/css-display/run-in/run-in-013.xht": [
+ "11bc7fde7caf907343151062bb9ae809bae8c82d",
+ "visual"
+ ],
+ "css/css-display/run-in/run-in-abspos-between-001.xht": [
+ "3e1ad3faad361d1d2d593768a443910cf4cd490b",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-abspos-between-002.xht": [
+ "c107b4fb41bd56638a0eb720131f91d4e5538a78",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-abspos-between-003.xht": [
+ "23dea7a79da74d238e1c25a8c28296de817bc59b",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-basic-001.xht": [
+ "0c34f3144766492c0cb309877d6db143697d9e02",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-basic-002.xht": [
+ "09c62f1052efe44790ec822550e8e3cd835beb6a",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-basic-003.xht": [
+ "087430960604e40634bba7dc932f788570b8c598",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-basic-004.xht": [
+ "3831b02ab852d1d9f0c9417921ab4ca927896dc4",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-basic-005.xht": [
+ "b2135f56d2885505eb44dcaaf2160ce29df7e4fa",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-basic-006.xht": [
+ "01817fa44e367c4a7a020513aeb7c3456161cdd5",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-basic-007-ref.xht": [
+ "11014cb21bcdf13e85c4d0086df9a25507613808",
+ "support"
+ ],
+ "css/css-display/run-in/run-in-basic-007.xht": [
+ "43dd105bde7f2e41c15d36b33e6554e391dc079f",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-basic-008.xht": [
+ "f24259a5fed7bf8cab18b9184e35212e02800c96",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-basic-009.xht": [
+ "e98daeb42c3a54d32b97d843addfa5d2dda44828",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-basic-010.xht": [
+ "0bc99c24b856b18ea3fa55869db75a67de43ab8d",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-basic-011.xht": [
+ "a1b654d27c1dab2ad1e4703b67e38d3e9bd2a188",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-basic-012.xht": [
+ "c81ee8a2132c0ba8a6b21724d096cdafb847378b",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-basic-013.xht": [
+ "2531d2898252313a9fe2f58723b88dd8fc687db3",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-basic-014.xht": [
+ "59d9c7c29da0b266a4ff93650fb5d6a7855ec4e8",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-basic-015.xht": [
+ "8a07cf400198531a7967b5902c2bc2d54619ab43",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-basic-016.xht": [
+ "6e253d56c74265591f9f8f56975698e88c2f14fc",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-basic-017.xht": [
+ "a2146b35df1dc7bd6a6ea30600576d66523c1934",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-basic-018.xht": [
+ "62720b81190790760a9bc1fab01a5643cdf10395",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-basic-ref.xht": [
+ "5c7bf6627792ff8dfa7898148318478fc9397673",
+ "support"
+ ],
+ "css/css-display/run-in/run-in-block-between-001.xht": [
+ "8bd7a8465542fdddf4a766566058ea858094f3c0",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-block-between-002.xht": [
+ "5dc15f0706212f0231f83f98f6625041f8cbd2f1",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-block-between-003.xht": [
+ "4a6ffa1bc42e3730571f20877d486ee8787168a5",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-block-ref.xht": [
+ "071c80df59c30b1d27eb71bf640dc1851c82caae",
+ "support"
+ ],
+ "css/css-display/run-in/run-in-breaking-001-ref.xht": [
+ "2340373520e5da7655abe63565a265dc5cb033b9",
+ "support"
+ ],
+ "css/css-display/run-in/run-in-breaking-001.xht": [
+ "5fc81726a11c8dacd0836d7c58e6d3b2e6520de9",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-breaking-002-ref.xht": [
+ "0a7d186899713e3176f1fec521fdba32aec23c75",
+ "support"
+ ],
+ "css/css-display/run-in/run-in-breaking-002.xht": [
+ "845947b845f9ac605a6be41e2159c0f5940017da",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-clear-001.xht": [
+ "7a2c163d274376ebc920d4861a6050f2ee150ae7",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-clear-002.xht": [
+ "150555e798c6a601b272f4f399ac59bf01181d49",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-abspos-001.xht": [
+ "505db18a1ef6306f55d3ccb0da91468eb1832e45",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-block-001.xht": [
+ "14a094004359b5d82a346789d943a10986a219ca",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-block-002.xht": [
+ "da1db69ceba2cbeb435c05d2b0db72400e7da3d6",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-block-003.xht": [
+ "3cd68ce6725aea4a8dc0d9c0a2c0f9a6d11fd9d9",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-block-004.xht": [
+ "7db957af8ab1c8baa83fe1c80030038c24a1a7f5",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-block-005.xht": [
+ "f9edbb5b1931152f0fc59a49fa7ceaf562907e10",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-block-inside-inline-001.xht": [
+ "8acc13aafb56c42ea28056d89c75ec7abf5ded8a",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-block-inside-inline-002.xht": [
+ "c2819892d00974d39407022d3999dc0e3a99cc86",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-block-inside-inline-003.xht": [
+ "66cbe19763f9d390ec7c059ea290abc8594cdde8",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-float-001.xht": [
+ "c761acc50f08e90f703a81ae8f22ff6e42709491",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-inline-001.xht": [
+ "4d7b0268d78bfbd575a2b83d0c220bb9773a0b68",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-inline-002.xht": [
+ "51c1489ef21996a11c5fb2b316fb33e0382eedb9",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-inline-003.xht": [
+ "cc4c7b96db888e2c4b5c72500b826d8594b2e131",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-inline-004.xht": [
+ "153dba85a8e212106ba545d91e769bfa7ed01f75",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-inline-005.xht": [
+ "a405159d3ad1841125d71fb1da1f20b48a4be773",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-inline-006.xht": [
+ "36ec63fd75a421d0fe020a97a786cd368ad7d247",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-inline-007.xht": [
+ "f7496dd5eefa7fda7438936dcaeff54a95a8aa0d",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-inline-block-001.xht": [
+ "bf9e2c4e86d11e99389f283977b2c5b112e73587",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-inline-table-001.xht": [
+ "e7d121beeb034e758fb5efa0082dc93b3efedbf1",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-relpos-block-001.xht": [
+ "675a88d85b722cc515fb158584b7572cc140fb4e",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-relpos-block-002.xht": [
+ "2be9a77b6a4e838cc08fcfc8f9920ddc28261381",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-relpos-block-003.xht": [
+ "c60fcf48a612655bea93d03a072f21c072f8c0f0",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-run-in-001.xht": [
+ "440555c995389809c51c646d540bf5d48d300e70",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-run-in-002.xht": [
+ "04fa874c1d0d2a26de77421e484ef222def2ea24",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-run-in-003.xht": [
+ "d9777e903841d7473f21e7d8132194fd2670aac4",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-table-001.xht": [
+ "89f16b25b8c73fd543936890c24e6359f14a0d26",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-table-002.xht": [
+ "c681daf1640dfae048990cb4ffe6a66783d6efff",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-table-003.xht": [
+ "452fe200c9b557ba8a5425d352c52f718dd01c5d",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-table-caption-001.xht": [
+ "555a7a80b7b13ed6694e6752702098088beefcb7",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-table-cell-001.xht": [
+ "f48afe1c718d9b6d17a6d0ae866ee47e5e9daf46",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-table-column-001.xht": [
+ "5211a09e5126d906b54970831fafae37fd361903",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-table-column-group-001.xht": [
+ "506b7828e6d6d602f5a47b0a67555bd8efeec352",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-table-inside-inline-001.xht": [
+ "1a080c99fd25e1095b4664aa5f001d10eeea371e",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-table-inside-inline-002.xht": [
+ "9937c034bdb0df12da9f2d6305ab9c5ab70b91fd",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-table-inside-inline-003.xht": [
+ "da81ad5da653c2d560371b339a9dae72b33fbdae",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-table-row-001.xht": [
+ "7f8c6603b1ab5fd9a3845769eefda2c367a20c02",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-contains-table-row-group-001.xht": [
+ "24a7f43411f93088fd94d0322eb05a0cec39c31c",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-display-none-between-001.xht": [
+ "b41224b028d9ae055937b119af885dfb5c4a5e43",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-display-none-between-002.xht": [
+ "8ae5b5743c4c54adcac5b4aeef00f3706147cf57",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-display-none-between-003.xht": [
+ "76901ba7cda655b286e0d384efc94314175e44a9",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-fixedpos-between-001.xht": [
+ "898efaa60daf1d5174b884cf862c1e82ee3fcc43",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-fixedpos-between-002.xht": [
+ "419a3aed33847413f5a7761d24c4597dd11c6eb8",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-fixedpos-between-003.xht": [
+ "429c6d9258d12321dfc5b754e2b4ae75a3015c98",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-float-between-001.xht": [
+ "3698456919cf966b8dd2ba8d5fae67cc5f1cdb4b",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-float-between-002.xht": [
+ "44ad6dcae26aba095987e299b81af4568d4ef7b1",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-float-between-003.xht": [
+ "d561aa7cb5206de8c3c314160c19814d800640ad",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-inherit-001-ref.xht": [
+ "697462c36a68eb8f60abed93a5be18b58bcf0626",
+ "support"
+ ],
+ "css/css-display/run-in/run-in-inherit-001.xht": [
+ "f2382fbf93f981da1a585c60e9b377c29329a47c",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-inheritance-001.xht": [
+ "c3496a363e7ff9fff53261d8878523fa2687b8e6",
+ "visual"
+ ],
+ "css/css-display/run-in/run-in-inline-between-001.xht": [
+ "4ea2d35766d3ae38fb2eecbc1c47ae36896a4b47",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-inline-between-002.xht": [
+ "f1c06805cb2b657e3816837e00f45c3e4bfe4ea9",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-inline-between-003.xht": [
+ "3c9fefe6a78fc7707e4148f9e4a083126036135c",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-inline-block-between-001.xht": [
+ "63bb102ca896d3c1d95a798c647d4692f21bb96f",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-inline-block-between-002.xht": [
+ "80c99eaa8dfd7e3ae7a18a8be5a6076ed32863a7",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-inline-block-between-003.xht": [
+ "787b437e8448491b487fdef488dc1fff6e13c608",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-inline-table-between-001.xht": [
+ "76f06b29154391ac6a94dc709e91b2ab3fe421d0",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-inline-table-between-002.xht": [
+ "14398c440ddc0ebc8b649f19d83fd52a9bba1055",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-inline-table-between-003.xht": [
+ "0bd512b2a4f512fa2e991fa947966a0ad6f74f81",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-linebox-001.xht": [
+ "62239e5b0ef406a4d2eacf31cfb52d1c70f380d1",
+ "visual"
+ ],
+ "css/css-display/run-in/run-in-linebox-002.xht": [
+ "5a195c18d8f5b4121a5a87bc9d6bbf9bd863054c",
+ "visual"
+ ],
+ "css/css-display/run-in/run-in-listitem-between-001.xht": [
+ "9a1bd8d93df3eda014ac0d009f3ec3c04201c5cb",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-listitem-between-002.xht": [
+ "2b1ad094020092479869a101d67964651db56cb3",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-listitem-between-003.xht": [
+ "9bae8b25156e91b853c23eb15a70a91689b704c3",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-pre-ref.xht": [
+ "865e5119c67a888f29e39928703eb3eb5b504b50",
+ "support"
+ ],
+ "css/css-display/run-in/run-in-relpos-between-001.xht": [
+ "18b879ea165db1e5f2ed01932296eda41d191b42",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-relpos-between-002.xht": [
+ "d6397646005cf36745e392cc594a84005af830c2",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-relpos-between-003.xht": [
+ "814503160217e264ae2d1f8e56dbd02a86ddb672",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-replaced-001-ref.xht": [
+ "b09db13a8b6f0eaaa0d3e131181f0a39996bde4c",
+ "support"
+ ],
+ "css/css-display/run-in/run-in-replaced-001.xht": [
+ "cc3f7375e8dd13b8d0ceb718c76d8ce65fe249cd",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-restyle-001.xht": [
+ "5c98c0ad78d612a4c69ad57ef721edaff8b169d2",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-restyle-002.xht": [
+ "01a20be11ad94ad9f1b5dd6f0669b2204424dc27",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-restyle-003.xht": [
+ "7b2a2bec64ebb168810307923fd585230ea32dec",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-run-in-between-001.xht": [
+ "31b481c5e327aa5dee982f945ddacb293706bbf3",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-run-in-between-002.xht": [
+ "7ff81653276feab32759c15c08547833aca86196",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-run-in-between-003.xht": [
+ "5983122a9e015f2f08dc0cb565194869fc23d505",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-run-in-between-004.xht": [
+ "a0e8126ec2ef495c62b48649c4b7c3eb766d4b8c",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-run-in-between-005.xht": [
+ "1adb32a3078b7fb14015c6e5699545bf39f2a10f",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-run-in-between-006.xht": [
+ "8dc1e460d109bb643382c4c39047f823d7b83a2a",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-run-in-between-007.xht": [
+ "2a9efa67d02de0d9e687b6bb986a1593779866de",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-run-in-between-008.xht": [
+ "4b3cf802de5cfe62f840fb43e1588d2ee0225f85",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-table-between-001.xht": [
+ "5523b17d807abc82410cd68e1eeb9df64c497483",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-table-between-002.xht": [
+ "2a3123b181e1840be435a47de3f9dfc5e0fbfa1a",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-table-between-003.xht": [
+ "e815c990a75d09b1f899389d5766ffe88ef2b420",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-table-cell-between-001.xht": [
+ "5a64485f150b9486ea8fc8b44b36eba0281843e4",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-table-cell-between-002.xht": [
+ "e2f59a56f7d1ed153b10c7b2f471cdda5c3f2fdc",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-table-cell-between-003.xht": [
+ "9575344b73ff90ee0a05e34f5981d757004b0f38",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-table-row-between-001.xht": [
+ "c920f933e6e9c5c7c255cdc1c2f430e01563c9ea",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-table-row-between-002.xht": [
+ "aa84045c62142d355f8a33b44ce06823cf70e058",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-table-row-between-003.xht": [
+ "cc9b62f52ffa918b1889ae1d4927212fe61327da",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-text-between-001.xht": [
+ "6c067847c8447b757c1cf7eca13cccb4591d7e8f",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-text-between-002.xht": [
+ "9f07e1ed65b5967d410210bcd6881fe7a3dd26a4",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-text-between-003.xht": [
+ "b71cecbbdda717bfe03a16b1ff06429b625187ef",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-text-between-004.xht": [
+ "380f0d7df62fec663a6e56d0a2861f9a48f9c477",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-text-between-005.xht": [
+ "a40c10072687534c2f57c3911647a64995dfd51f",
+ "reftest"
+ ],
+ "css/css-display/run-in/run-in-text-ref.xht": [
+ "4162c4ee8fe9a3609065054e1aff017e89608c61",
+ "support"
+ ],
+ "css/css-display/run-in/support/black15x15.png": [
+ "9252cae16138e45c07796fa5a10b6100ae703eaa",
+ "support"
+ ],
+ "css/css-display/run-in/support/blue15x15.png": [
+ "eb48032c07bfeb1d3b6be6e5c9c34d2fe2180767",
+ "support"
+ ],
+ "css/css-display/run-in/support/blue96x96.png": [
+ "99949c515749e66f471c3589ee7a0ef518aaccb5",
+ "support"
+ ],
+ "css/css-display/run-in/support/green15x15.png": [
+ "de1830c21195763f7327f270b14b6d50dfdfb21d",
+ "support"
+ ],
+ "css/css-display/run-in/support/swatch-blue.png": [
+ "e79958e10feeeed3db88dee9bae9ea80055593c5",
+ "support"
+ ],
+ "css/css-display/run-in/table-anonymous-block-001.xht": [
+ "4f471b69edd2465deffc9d925a74ee0b30ad6824",
+ "visual"
+ ],
+ "css/css-display/run-in/table-layout-applies-to-004.xht": [
+ "97f74eaf88a289c89d9c08e1c6865d28806cfbbb",
+ "visual"
+ ],
+ "css/css-display/run-in/text-align-applies-to-004.xht": [
+ "e223bc1cc7a84ac02fc8b9ee157903bf3b3c9d3f",
+ "visual"
+ ],
+ "css/css-display/run-in/text-decoration-applies-to-004.xht": [
+ "38ae3b84fa8182edde9764d68d9783c4f046cc56",
+ "reftest"
+ ],
+ "css/css-display/run-in/text-indent-applies-to-004.xht": [
+ "86911ad06c2b5172e6aa5cf793661dac00ad02ac",
+ "visual"
+ ],
+ "css/css-display/run-in/text-transform-applies-to-004.xht": [
+ "aa82154d3f6db37736e98cc5b89f5b8ffca81fb9",
+ "reftest"
+ ],
+ "css/css-display/run-in/top-applies-to-011.xht": [
+ "2b585ecb53fd1c84ef92a93ab66ccbc921f34440",
+ "visual"
+ ],
+ "css/css-display/run-in/unicode-bidi-applies-to-011.xht": [
+ "11fab4558a7a3d43bf3f53759d02cc8834af7110",
+ "visual"
+ ],
+ "css/css-display/run-in/vertical-align-applies-to-011.xht": [
+ "99f448c1a05cbd9bb9bd1cec7797812608aec98e",
+ "visual"
+ ],
+ "css/css-display/run-in/visibility-applies-to-011.xht": [
+ "20695d8ba19bac1a499d973d5185e05b0bd4c1d8",
+ "visual"
+ ],
+ "css/css-display/run-in/white-space-applies-to-004.xht": [
+ "f387077d9b2071510cfbafcc5bf6476c0342a89c",
+ "visual"
+ ],
+ "css/css-display/run-in/width-applies-to-011.xht": [
+ "8befc8e83d65818546a39a6950b602bd854fe049",
+ "reftest"
+ ],
+ "css/css-display/run-in/word-spacing-applies-to-004.xht": [
+ "ea4e80bc4e560a727ac60983e17b85fcdfaa06e0",
+ "visual"
+ ],
+ "css/css-display/run-in/z-index-applies-to-011.xht": [
+ "71adc3eabed66929d71c1003ea9d5e10fee4f1a5",
+ "visual"
+ ],
"css/css-display/support/acid.css": [
"5be41ca173eada98ac9b52b3b00732347690934e",
"support"
@@ -469776,6 +475884,34 @@
"55ac1cc272d6feaba627f45e402671e7bc83487d",
"reftest"
],
+ "css/css-flexbox/anonymous-flex-item-001.html": [
+ "9f89496f6e78f756d9ab4121bd032aea9b1a391a",
+ "reftest"
+ ],
+ "css/css-flexbox/anonymous-flex-item-002.html": [
+ "8bdb3608043b55769a271795dcc9c93fbd4d54cb",
+ "reftest"
+ ],
+ "css/css-flexbox/anonymous-flex-item-003.html": [
+ "03705ffe4b6521b7a66852923ab12cd55428e726",
+ "reftest"
+ ],
+ "css/css-flexbox/anonymous-flex-item-004.html": [
+ "d27625d34f2efa147415ef4e78f01cdc154ea579",
+ "reftest"
+ ],
+ "css/css-flexbox/anonymous-flex-item-005.html": [
+ "c967afaa14aff2a6d2a32346c12b3c1b4fbdc7c6",
+ "reftest"
+ ],
+ "css/css-flexbox/anonymous-flex-item-006.html": [
+ "d3d0c005dc2b121906f40e9a093d0feec9182355",
+ "reftest"
+ ],
+ "css/css-flexbox/anonymous-flex-item-ref.html": [
+ "e8b1580d36b15778ca903fefa1ccccaef31b099f",
+ "support"
+ ],
"css/css-flexbox/auto-margins-001-ref.html": [
"dfc6fe046906c564110225d01572aa6aa1e40858",
"support"
@@ -472220,6 +478356,14 @@
"8a868450fe85cd33deaf1e0960fa607125ead2dd",
"testharness"
],
+ "css/css-flexbox/percentage-heights-004-ref.html": [
+ "19ed01c4b89e39f9ab6c72085e9a29ed30b2f0c2",
+ "support"
+ ],
+ "css/css-flexbox/percentage-heights-004.html": [
+ "210a01e299109975376cef799599967709758481",
+ "reftest"
+ ],
"css/css-flexbox/percentage-widths-001-ref.html": [
"a139951dbeb1676b7add9a43d154595dc2e9859b",
"support"
@@ -472588,6 +478732,14 @@
"078e1dd6dd61d36cec239ed75d02051f61fe60a5",
"support"
],
+ "css/css-flexbox/table-as-item-narrow-content.html": [
+ "ccee1a24278c3177809a09009c2f15973908fa83",
+ "reftest"
+ ],
+ "css/css-flexbox/table-as-item-wide-content.html": [
+ "b25764f22999464e3e65780f01f4adb784ce56d2",
+ "reftest"
+ ],
"css/css-flexbox/ttwf-reftest-flex-align-content-center.html": [
"4e094e9c286479386a39eacfc975b78bef311c63",
"reftest"
@@ -472676,6 +478828,98 @@
"b4992b381f6a8f83ee043f379e614b43c7ead393",
"reftest"
],
+ "css/css-fonts/first-available-font-001-ref.html": [
+ "b908d93443cee9e64628e85a29d288d567f19e5a",
+ "support"
+ ],
+ "css/css-fonts/first-available-font-001.html": [
+ "b766a6b03eda1f84317330e4144efda1fe11877e",
+ "reftest"
+ ],
+ "css/css-fonts/first-available-font-002-ref.html": [
+ "1d2b31f4624182d4e1451a7af73e11a049faba75",
+ "support"
+ ],
+ "css/css-fonts/first-available-font-002.html": [
+ "85d82a4b714deac3ab2dc15cf1c90d340039ea0e",
+ "reftest"
+ ],
+ "css/css-fonts/first-available-font-003-ref.html": [
+ "561cd0ffcb017ae0a5cd8489cc335afaa43fd95d",
+ "support"
+ ],
+ "css/css-fonts/first-available-font-003.html": [
+ "60fa4838cce77f2516689b368cf9058adcab22e9",
+ "reftest"
+ ],
+ "css/css-fonts/first-available-font-004.html": [
+ "449a20a6fecb03821cdb5253fa09a70340b8321c",
+ "reftest"
+ ],
+ "css/css-fonts/first-available-font-005-ref.html": [
+ "460dc6967318b4c75c9776ef4d4e76e39f51534e",
+ "support"
+ ],
+ "css/css-fonts/first-available-font-005.html": [
+ "6c4d33aa1d766da74c5d0ad6cbcda3793c3df926",
+ "reftest"
+ ],
+ "css/css-fonts/first-available-font-006.html": [
+ "9cf39bd6493745a35b586046ffb3ad98334ba1b7",
+ "reftest"
+ ],
+ "css/css-fonts/first-available-font-007.html": [
+ "955b6034a43ed937c87df87b35e37d6cdb4f1e0d",
+ "reftest"
+ ],
+ "css/css-fonts/font-default-01-ref.html": [
+ "4c9d7b41e3677da2c9fab71098a34463f4ecdf06",
+ "support"
+ ],
+ "css/css-fonts/font-default-01.html": [
+ "631cc38f77f522b8f7483313e6f72478048c7f5b",
+ "reftest"
+ ],
+ "css/css-fonts/font-default-02-ref.html": [
+ "c82b34b553a4884e8855e72d53fbb4e2a188150d",
+ "support"
+ ],
+ "css/css-fonts/font-default-02.html": [
+ "65c7f00a58f50eaa8318197ead5bfd090a3b9fe3",
+ "reftest"
+ ],
+ "css/css-fonts/font-default-03-ref.html": [
+ "9d058bd5f6ff7c1ae78c30971d4ccbc300bb9659",
+ "support"
+ ],
+ "css/css-fonts/font-default-03.html": [
+ "6904aa08cd31f40a1025cdca5fd67c80adb766c2",
+ "reftest"
+ ],
+ "css/css-fonts/font-default-04-a-ref.html": [
+ "e19a9893bd2a3324359fee3221463fde0cda83c1",
+ "support"
+ ],
+ "css/css-fonts/font-default-04-b-ref.html": [
+ "be7941d593507cacc4dd0e6f7ea965da5028e17a",
+ "support"
+ ],
+ "css/css-fonts/font-default-04-c-ref.html": [
+ "d7cbdc050d5bf76b2d2d1e9ef7e6bf2b0ab949fc",
+ "support"
+ ],
+ "css/css-fonts/font-default-04.html": [
+ "4f5d1d1f375f61a09d30ef28deda1b2a54f4c620",
+ "reftest"
+ ],
+ "css/css-fonts/font-display/font-display-change-ref.html": [
+ "e155492a8b8dbaa1477fddfaeea520b3a8b3fd37",
+ "support"
+ ],
+ "css/css-fonts/font-display/font-display-change.html": [
+ "c5fd3f31aca59b36b12aea67bfcd13f9fd5751b6",
+ "reftest"
+ ],
"css/css-fonts/font-display/font-display-failure-fallback.html": [
"9fbf0c808f338c5d668554ab62f10cfe0ca93c91",
"testharness"
@@ -473025,7 +479269,7 @@
"support"
],
"css/css-fonts/font-variant-01.html": [
- "0d0a249db6c2ddaad1e4de702834020aa4ab45fa",
+ "6803a83b4ab93a9ad442a0e339d536edd85ab5df",
"reftest"
],
"css/css-fonts/font-variant-02-ref.html": [
@@ -473033,7 +479277,7 @@
"support"
],
"css/css-fonts/font-variant-02.html": [
- "4fd6a59d04fde5e82ec12fa4c89bf07c611ddd21",
+ "74980d099860a038f1e42ad62cb7f2eb8cbca02c",
"reftest"
],
"css/css-fonts/font-variant-03-ref.html": [
@@ -473041,7 +479285,7 @@
"support"
],
"css/css-fonts/font-variant-03.html": [
- "78e21fc51d91d4ee0ec8e0838dab863a08aa1f83",
+ "c42d2410101bf0be8832a0f84ce6ee4b75e96a66",
"reftest"
],
"css/css-fonts/font-variant-04-ref.html": [
@@ -473049,7 +479293,7 @@
"support"
],
"css/css-fonts/font-variant-04.html": [
- "0431694dc7064c9af5c1881484796b750b15b63c",
+ "b5417f15f571c21e754df033a597193384cf8610",
"reftest"
],
"css/css-fonts/font-variant-alternates-01-ref.html": [
@@ -473196,6 +479440,10 @@
"de45acb63b567c5318b014ebab07098ca8c317b6",
"reftest"
],
+ "css/css-fonts/font-variant-alternates-parsing.html": [
+ "5a15ca070dbddff6e28995c13db825244080fc25",
+ "testharness"
+ ],
"css/css-fonts/font-variant-caps-01-ref.html": [
"dfc1e1995e9841ecfa8889ad25c6ef7a6a2d992f",
"support"
@@ -473672,10 +479920,18 @@
"415b835abaaab822aab11880354296e7356bbb0a",
"support"
],
+ "css/css-fonts/support/AD.woff": [
+ "2bff1f1a01ce7c959341300952b2467e87e60dd5",
+ "support"
+ ],
"css/css-fonts/support/README": [
"c46bfcee920aef0b9167764ec78c699ed217c8f2",
"support"
],
+ "css/css-fonts/support/Revalia.woff": [
+ "f2b20022818e53e9c9c5f22bcc52703c6858eb1c",
+ "support"
+ ],
"css/css-fonts/support/bar_with_corner_dot.png": [
"76cb66964d085f70c0c91635c9369ea8fb41f2a3",
"support"
@@ -479896,6 +486152,34 @@
"9aa0e70e845521fd7127581a4cd017e1ba3dc15c",
"reftest"
],
+ "css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-001.html": [
+ "b15d1db43efd2b8f15aab17dbbcf3afc262baa76",
+ "testharness"
+ ],
+ "css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-002.html": [
+ "6efd2dfea5027aca510f7a92e8cec16b3fddef2d",
+ "testharness"
+ ],
+ "css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-003.html": [
+ "d485183a7ea0bfcf92503a3e420ae68470593995",
+ "testharness"
+ ],
+ "css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-004.html": [
+ "aacc2daef0aae211a8ffa433ff6684d037afd4c8",
+ "testharness"
+ ],
+ "css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-005.html": [
+ "fc2cfee0c523129d8cb0bbee1685786a72031e84",
+ "testharness"
+ ],
+ "css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-006.html": [
+ "7408735464c2da7fa7916ee5a739518866e5b7a2",
+ "testharness"
+ ],
+ "css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-007.html": [
+ "4c50565bb7adf5074f57da937954c3e95ee00d7a",
+ "testharness"
+ ],
"css/css-grid/abspos/grid-positioned-items-background-001-ref.html": [
"4094fef3dedb631dfb06f600ce44ccfbfdb78d02",
"support"
@@ -480416,6 +486700,10 @@
"e9dccb31be383803835caebaffb42242aeb4941a",
"testharness"
],
+ "css/css-grid/alignment/grid-column-axis-alignment-positioned-items-017.html": [
+ "6c58deabf758bee4d8223403d0f7edffede54f64",
+ "testharness"
+ ],
"css/css-grid/alignment/grid-content-distribution-001.html": [
"5622a264eb2dbd6cf621ac97aa4a8ae5db82c6b3",
"reftest"
@@ -480720,6 +487008,10 @@
"9b9190bbcc6ce8f74480918a68fb73e6849fb441",
"testharness"
],
+ "css/css-grid/alignment/grid-row-axis-alignment-positioned-items-017.html": [
+ "c75eb3edc97f8f01429a26698337c6e3b869563b",
+ "testharness"
+ ],
"css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-001.html": [
"cafc54256ea9d0cbf8990a0e04904c7ada8c5894",
"testharness"
@@ -481145,11 +487437,11 @@
"testharness"
],
"css/css-grid/grid-definition/grid-template-columns-fit-content-001-ref.html": [
- "518f7a0d17c565fda7903d1abfac794fbc03191d",
+ "5f2f68b7cf046593760e6668a3d7fca58bae263e",
"support"
],
"css/css-grid/grid-definition/grid-template-columns-fit-content-001.html": [
- "64c4a2aef9e86f623fede6185ba1d6b4eaa2be17",
+ "adffbd4b734ae719675cb5bee7fd6bc3fbde5d5b",
"reftest"
],
"css/css-grid/grid-definition/grid-template-columns-rows-resolved-values-001.html": [
@@ -481157,7 +487449,7 @@
"testharness"
],
"css/css-grid/grid-definition/grid-template-rows-fit-content-001-ref.html": [
- "8aa844e9ae3fb1f8b359b8dcc43bbf605bc726c4",
+ "0599be38ec7525b925d2c42dad8f6c09efff1612",
"support"
],
"css/css-grid/grid-definition/grid-template-rows-fit-content-001.html": [
@@ -481168,6 +487460,10 @@
"7d6dc5106777942ad83e6bc570368af113f32d5f",
"support"
],
+ "css/css-grid/grid-items/explicitly-sized-grid-item-as-table.html": [
+ "2d713db8aa5f79164259a2c7b2b3f6b89f8aeed4",
+ "reftest"
+ ],
"css/css-grid/grid-items/grid-inline-items-001.html": [
"026bebd69ed8b67da6b08de73b6f6bf2c1cdae7d",
"reftest"
@@ -481385,11 +487681,11 @@
"reftest"
],
"css/css-grid/grid-items/grid-minimum-size-grid-items-017.html": [
- "14950654a15677b2845d6e40738872f10a627f9f",
+ "72c56c685b4251feac161d7928a2ebbfdbf1ac78",
"reftest"
],
"css/css-grid/grid-items/grid-minimum-size-grid-items-018.html": [
- "10b954d9b6ddf50a0c910caa7ce6924fa15c006a",
+ "800c76ae88f02741160c06039cfc0c122aa50f43",
"reftest"
],
"css/css-grid/grid-items/grid-minimum-size-grid-items-019.html": [
@@ -481404,6 +487700,14 @@
"205f2292e788eee87490530488e2f1575e809ade",
"testharness"
],
+ "css/css-grid/grid-items/grid-minimum-size-grid-items-022.html": [
+ "c2aca9084809e053c5f96dbe4eff7a7131fdde5a",
+ "testharness"
+ ],
+ "css/css-grid/grid-items/grid-minimum-size-grid-items-023.html": [
+ "40fe5eeb537a999e24ae7b653b364e58e2d59e35",
+ "testharness"
+ ],
"css/css-grid/grid-items/grid-order-property-auto-placement-001.html": [
"15a3eec22bb5f55e3e7a73730e95011f4efbaf73",
"reftest"
@@ -481517,7 +487821,7 @@
"support"
],
"css/css-grid/grid-layout-properties.html": [
- "3ab6d064073e659de4fa0ceb1d2b20a5d0cd42ab",
+ "d30ee96245cf3d25bffc64347a4ee60bfb2b2049",
"testharness"
],
"css/css-grid/grid-model/display-grid.html": [
@@ -481536,6 +487840,14 @@
"f94336e80a72225b05970dec330508c33445c87a",
"testharness"
],
+ "css/css-grid/grid-model/grid-container-ignores-first-letter-001.html": [
+ "e46492228ce6fdf83d9661c06db745e9c6689bb4",
+ "testharness"
+ ],
+ "css/css-grid/grid-model/grid-container-ignores-first-line-001.html": [
+ "8e8895681b8f7e8f5d416faedf5b081f7fc42243",
+ "testharness"
+ ],
"css/css-grid/grid-model/grid-display-grid-001.html": [
"4eb94a6ac52aec622d55911c68677263d9533246",
"reftest"
@@ -481620,6 +487932,14 @@
"2075376b219560fbf9b9e6c3cb125ba2d066e966",
"reftest"
],
+ "css/css-grid/grid-model/grid-item-accepts-first-letter-001.html": [
+ "bc3aa0022584b2dc6253aeb1bbca50b6b7c05f54",
+ "testharness"
+ ],
+ "css/css-grid/grid-model/grid-item-accepts-first-line-001.html": [
+ "0af2d39207188e1398e69f1e2d81848ba1bee2ee",
+ "testharness"
+ ],
"css/css-grid/grid-model/grid-margins-no-collapse-001.html": [
"f68bfb76a8158d9bd8c9e3ef2e8aab11401b0360",
"reftest"
@@ -481693,15 +488013,15 @@
"support"
],
"css/css-grid/reference/grid-collapsed-row-gutters-ref.html": [
- "917e355f17681c9f511fc5cfbfe7996cddb05f6b",
+ "15a431efb881d37ce24ab376ee3709bd4333bb11",
"support"
],
"css/css-grid/reference/grid-different-gutters-ref.html": [
- "d37b7409505ce811a7a76db76ab7185c611fd278",
+ "bd1aecfb426cde332794b9657a7d7a905ff1b292",
"support"
],
"css/css-grid/reference/grid-equal-gutters-ref.html": [
- "61df6964c4743d585e47e0e683c55b5cf3f10c92",
+ "9db6eaa6f9569ada08d3c231ec364f4d7e7faf6b",
"support"
],
"css/css-grid/reference/grid-filled-blue-yellow-green-overlapped-100px-squares.html": [
@@ -482068,6 +488388,26 @@
"d9c8054b356c9273a054a83abeb9be0626c23921",
"support"
],
+ "css/css-lists/counter-7-ref.html": [
+ "6391e214ad5262afaab7cd6caaf57e7f2506fb4d",
+ "support"
+ ],
+ "css/css-lists/counter-increment-inside-display-contents.html": [
+ "d137a61e9cdacdf9130412675f0365e78719e93e",
+ "reftest"
+ ],
+ "css/css-lists/counter-reset-increment-display-contents.html": [
+ "7e8737c7342ada38a67c25bebf7731ab906a6161",
+ "reftest"
+ ],
+ "css/css-lists/counter-reset-increment-display-none.html": [
+ "dce0a0b569b475c150c7d8dcbcee19bed57beee6",
+ "reftest"
+ ],
+ "css/css-lists/counter-reset-inside-display-contents.html": [
+ "8b5c11c194f7038209d9f9aa9d844d496e89658e",
+ "reftest"
+ ],
"css/css-lists/list-style-type-armenian-002.xht": [
"93eca7b91e63950fc593fdcdf8e6900f89a8c609",
"visual"
@@ -482829,7 +489169,7 @@
"reftest"
],
"css/css-masking/clip/clip-rect-auto-001.html": [
- "d69112f2753d67ce03f9562a5177c402952619d0",
+ "e736cd6a808b66b8eefc9f7713d958834b32c1b0",
"reftest"
],
"css/css-masking/clip/clip-rect-auto-002.html": [
@@ -482857,7 +489197,7 @@
"reftest"
],
"css/css-masking/clip/clip-rect-comma-002.html": [
- "60ad4c9641c8a20c51bfe826dde19e6756c3275a",
+ "70d6467b21e7a4b82665231413624b100e1b0926",
"reftest"
],
"css/css-masking/clip/clip-rect-comma-003.html": [
@@ -482877,7 +489217,7 @@
"support"
],
"css/css-masking/clip/reference/clip-horizontal-stripe-ref.html": [
- "d52b44feeaa257ce0df29de754c1c5ea83a00a1d",
+ "beb646fbeacdcb1339925b6d58a51bfbb1ede256",
"support"
],
"css/css-masking/clip/reference/clip-no-clipping-ref.html": [
@@ -482917,7 +489257,7 @@
"reftest"
],
"css/css-multicol/OWNERS": [
- "721c176d7b1e3d610405ea043c93288f7c09ebd0",
+ "7dc7d3872831592215162aff9196d55032c5c31f",
"support"
],
"css/css-multicol/multicol-basic-001.html": [
@@ -482969,13 +489309,9 @@
"reftest"
],
"css/css-multicol/multicol-br-inside-avoidcolumn-001.xht": [
- "f2fe604ad53155fe3ba1eaaaadad7d4842aef239",
+ "934a25d72288a1400325662a7b3b9c47ceadd88d",
"reftest"
],
- "css/css-multicol/multicol-br-inside-avoidcolumn-ref.xht": [
- "d6c09e048d1a938cbf814a9e88b9ba0877b0222f",
- "support"
- ],
"css/css-multicol/multicol-break-000-ref.xht": [
"213ce08f5d1294ce5ed571eca674886e20a10bde",
"support"
@@ -482985,11 +489321,11 @@
"reftest"
],
"css/css-multicol/multicol-break-001-ref.xht": [
- "9063897562e11c61d96174d63fa1111f42c40aa3",
+ "a7826c6d21887999991961d09e61fb4569378470",
"support"
],
"css/css-multicol/multicol-break-001.xht": [
- "225895c702c7e5b91d9f167463410b795bd5bc2d",
+ "435a5b7f4bb2013c837b0bd67b16e67fa0e609f4",
"reftest"
],
"css/css-multicol/multicol-clip-001-ref.xht": [
@@ -483092,14 +489428,6 @@
"6703b66b9696faa2d9efb86c93a5127952d52484",
"reftest"
],
- "css/css-multicol/multicol-count-computed-001.xht": [
- "0b899eed278c7427523cdabd0b4f73d1f70f4c8a",
- "reftest"
- ],
- "css/css-multicol/multicol-count-computed-002.xht": [
- "76581613fb9ec4c0cf786361cb9f5b3d2977537b",
- "reftest"
- ],
"css/css-multicol/multicol-count-computed-003-ref.xht": [
"80e54fbeedd11f39d9041d45d266cf87a69d28b1",
"support"
@@ -483120,30 +489448,6 @@
"fdc0811616680d44203af48c16fcbd91f5e2d9ea",
"reftest"
],
- "css/css-multicol/multicol-count-computed-2-ref.xht": [
- "c56592171fc03c060391ed79cdc07504e3331110",
- "support"
- ],
- "css/css-multicol/multicol-count-computed-ref.xht": [
- "6709a84fd18a48dfb086fc16f9c5c88e428ba19d",
- "support"
- ],
- "css/css-multicol/multicol-count-large-001.xht": [
- "c2a6c85790cc1bb26a55ac35ce7c180540bcf303",
- "reftest"
- ],
- "css/css-multicol/multicol-count-large-002.xht": [
- "016c0844708c869edffdf611d7e667ed18fc044c",
- "reftest"
- ],
- "css/css-multicol/multicol-count-large-2-ref.xht": [
- "892602e263ebef316e45bb0ab539bf7dc8fbfde6",
- "support"
- ],
- "css/css-multicol/multicol-count-large-ref.xht": [
- "d3aacae3172978f58c957e99553b1ab3edea2188",
- "support"
- ],
"css/css-multicol/multicol-count-negative-001.xht": [
"cfd975860e259b71f8034c5d46f895af3b87b8c3",
"reftest"
@@ -483209,25 +489513,17 @@
"reftest"
],
"css/css-multicol/multicol-fill-auto-block-children-002-ref.xht": [
- "8deeba9e92df8ce4bb47e5cf3a0ccd1e1bc28b43",
+ "f11616ee8273a29f09430115311b455f8bad4d41",
"support"
],
"css/css-multicol/multicol-fill-auto-block-children-002.xht": [
- "33c1a5516a1c5697e0e8fd71c77345291dead62d",
+ "6aad056909cb697560558d7511d970cc47e10514",
"reftest"
],
"css/css-multicol/multicol-fill-auto-block-children-ref.xht": [
"f63446929f6a4a1f7ba2dba47af786c487fa03d7",
"support"
],
- "css/css-multicol/multicol-fill-auto-ref.xht": [
- "d97337c9c5fe4ff3ab4472b1c0f9f459f9d7cf8e",
- "support"
- ],
- "css/css-multicol/multicol-fill-auto.xht": [
- "54fe8ec972a87ea83b6ea770ac5975bcb1868412",
- "reftest"
- ],
"css/css-multicol/multicol-fill-balance-001-ref.xht": [
"dfdc227760f0fb524232d65ee792f108d32fc7de",
"support"
@@ -483236,10 +489532,6 @@
"cd580ac2b2ddf85cb1f3e14b554e4e3ce357f012",
"reftest"
],
- "css/css-multicol/multicol-fill-ref.xht": [
- "a5f5c85453df52637a510c3f6ae5e5c65fdec50c",
- "support"
- ],
"css/css-multicol/multicol-gap-000-ref.xht": [
"1fe1e1d56fb2336ae63544a4bb568ee6f6daa053",
"support"
@@ -483268,6 +489560,18 @@
"16067366a3c1922e9c8415b21e513edd47c2305f",
"reftest"
],
+ "css/css-multicol/multicol-gap-animation-001.html": [
+ "5f2cf6d10c4624d44e81bfa9e9c97bcaf229ca80",
+ "testharness"
+ ],
+ "css/css-multicol/multicol-gap-animation-002.html": [
+ "5e83250f2f2ff49682eae68056330aa3b4c673c7",
+ "testharness"
+ ],
+ "css/css-multicol/multicol-gap-animation-003.html": [
+ "6d5c81b2277c34bac89e8cde247dd9aabbdd505f",
+ "testharness"
+ ],
"css/css-multicol/multicol-gap-fraction-001-ref.xht": [
"91139e0fa20ce6211d5199ba60312f5f7ab308d8",
"support"
@@ -483276,6 +489580,10 @@
"9d12dc2b311ab4bf2dfda4565fcdfab0008754c5",
"reftest"
],
+ "css/css-multicol/multicol-gap-fraction-002.html": [
+ "67b2d75607ac68ad08012ad282ac4234946a1051",
+ "reftest"
+ ],
"css/css-multicol/multicol-gap-large-001-ref.xht": [
"a502a720a1ac5a28f3857caf36ccb2a9fec02776",
"support"
@@ -483305,11 +489613,11 @@
"reftest"
],
"css/css-multicol/multicol-height-block-child-001-ref.xht": [
- "c5dff10fd039a8e642e19a5a21da05d33d491945",
+ "44429ae1c09226083fd84aa26c617e7ee71a6e91",
"support"
],
"css/css-multicol/multicol-height-block-child-001.xht": [
- "7f8870a893846cb52f69bd4259cbc96646723702",
+ "5cf388bfc8537ce63bae3148cc9702f556e6852b",
"reftest"
],
"css/css-multicol/multicol-inherit-001-ref.xht": [
@@ -483332,18 +489640,10 @@
"bfb8f201623a96cf2737bef1ba1c0d6b08bc54e4",
"reftest"
],
- "css/css-multicol/multicol-inherit-004.xht": [
- "eaf2a8ba48e8f8dc5ead28a675bfa5ff478df734",
- "reftest"
- ],
"css/css-multicol/multicol-inherit-3-ref.xht": [
"56158a2fdc63c2e534672679c81c8de93a5730d1",
"support"
],
- "css/css-multicol/multicol-inherit-4-ref.xht": [
- "0423d597aaed6efc746fd7c9cccc21b3901cfae8",
- "support"
- ],
"css/css-multicol/multicol-list-item-001-ref.xht": [
"6f5adc6cc216feef55920d97595d32cf68be5ed4",
"support"
@@ -483385,11 +489685,11 @@
"reftest"
],
"css/css-multicol/multicol-nested-column-rule-001-ref.xht": [
- "e045b4bb02989ec16c6b1fc10bd9717b9daf0224",
+ "d53e71b2a82e6d519fa7fffcc62ba832717cd7a5",
"support"
],
"css/css-multicol/multicol-nested-column-rule-001.xht": [
- "2052bad4a14f5d52b369751d5a7eee955dcca92b",
+ "7157a7f0a6dc740d9a12561118c2aa71923511c7",
"reftest"
],
"css/css-multicol/multicol-nested-margin-001-ref.xht": [
@@ -483557,7 +489857,7 @@
"reftest"
],
"css/css-multicol/multicol-rule-fraction-3-ref.xht": [
- "95c5bb1a096aa9e2508561849528200c6e794783",
+ "840335fafb6bbf23f2cff696145c5e4f093a077f",
"support"
],
"css/css-multicol/multicol-rule-groove-000-ref.xht": [
@@ -483625,7 +489925,7 @@
"support"
],
"css/css-multicol/multicol-rule-samelength-001.xht": [
- "cd4022578abdf3520e603336c7f812a9a5315926",
+ "f76c5c3a3989ba945c36f9b5f60d65157675ff65",
"reftest"
],
"css/css-multicol/multicol-rule-shorthand-001.xht": [
@@ -483656,30 +489956,6 @@
"b16e79ec96569a463be9b47b2f8f7f214f8500f7",
"support"
],
- "css/css-multicol/multicol-rule-style-groove-001-ref.xht": [
- "2529f1c9842f1bc415221dddc350b5f96a84c25a",
- "support"
- ],
- "css/css-multicol/multicol-rule-style-groove-001.xht": [
- "e6e56b0328c105ff123c33d3d552f00922e490d2",
- "reftest"
- ],
- "css/css-multicol/multicol-rule-style-inset-001.xht": [
- "40dba383e061009d8a63a3b239534a51f777d86d",
- "reftest"
- ],
- "css/css-multicol/multicol-rule-style-outset-001.xht": [
- "c2a1d8fef6176e0d87198a8784bb9ea7e3eef94a",
- "reftest"
- ],
- "css/css-multicol/multicol-rule-style-ridge-001-ref.xht": [
- "f09150d0eb9cca3c1479d7e240624e7913fb0a18",
- "support"
- ],
- "css/css-multicol/multicol-rule-style-ridge-001.xht": [
- "b75870bee5f5ec6f4669f9de58ea95393c686752",
- "reftest"
- ],
"css/css-multicol/multicol-shorthand-001.xht": [
"2be00be60652208da1a87c2175b02f1fbda381c9",
"reftest"
@@ -483709,7 +489985,7 @@
"reftest"
],
"css/css-multicol/multicol-span-all-003.xht": [
- "79ab6a7b47537d3dadcd0aa707ad045563d03165",
+ "c88e3393a8c0a214ed11e85736d35b5a383a03ac",
"reftest"
],
"css/css-multicol/multicol-span-all-block-sibling-003.xht": [
@@ -483720,22 +489996,6 @@
"60152a8e281cefc766c4313f707ad12da60504fa",
"support"
],
- "css/css-multicol/multicol-span-all-child-001-ref.xht": [
- "59a8a527b2f443c77d8b97ce8d7a2c538a80c688",
- "support"
- ],
- "css/css-multicol/multicol-span-all-child-001.xht": [
- "24bfd53c6017627df936b137d499af5ece0d20ca",
- "reftest"
- ],
- "css/css-multicol/multicol-span-all-child-002-ref.xht": [
- "7c41deb3000f9c7076b947d1b0195ef24e49d9ce",
- "support"
- ],
- "css/css-multicol/multicol-span-all-child-002.xht": [
- "913856821a569f7f6927fc0e042b6c4f87e90765",
- "reftest"
- ],
"css/css-multicol/multicol-span-all-margin-001-ref.xht": [
"e9950c32ce08fb3a56925c548c6efd1698dd10fe",
"support"
@@ -483772,14 +490032,6 @@
"8bdc105a0b441556da0b287dd5d6b98a3fedc7ad",
"reftest"
],
- "css/css-multicol/multicol-span-all-margin-nested-003.xht": [
- "a8f61138dc6e68e7910a29e4eaeac6f2d20adae4",
- "reftest"
- ],
- "css/css-multicol/multicol-span-all-margin-nested-3-ref.xht": [
- "d18c55ffc3c4a490ebe37c2c5fdf8e22e8710800",
- "support"
- ],
"css/css-multicol/multicol-span-all-margin-nested-firstchild-001.xht": [
"d912a7254753afebe5ade2f58af29484d2fd8d51",
"reftest"
@@ -483825,11 +490077,11 @@
"reftest"
],
"css/css-multicol/multicol-table-cell-vertical-align-001.xht": [
- "c60f477324d7ca5b73f19b637c965c20cc6764b4",
+ "b6323036968dbf0584f94e116bb019347c0d6a42",
"reftest"
],
"css/css-multicol/multicol-table-cell-vertical-align-ref.xht": [
- "6376bfbeb38858740053cdc384a5a8d2d49d0c7e",
+ "7515baa6b82894146207efaae85aaf832ff41a36",
"support"
],
"css/css-multicol/multicol-width-001-ref.xht": [
@@ -483852,6 +490104,14 @@
"39784428d2c56586d65f81a413aba4002d6ee752",
"reftest"
],
+ "css/css-multicol/multicol-width-ch-001.xht": [
+ "28b3c4f81e92185bbc9f26c9e594bdfb8cc994df",
+ "reftest"
+ ],
+ "css/css-multicol/multicol-width-ch-ref.xht": [
+ "0a6035ffd02299dfd16336d6c8919c54b2293e21",
+ "support"
+ ],
"css/css-multicol/multicol-width-count-001.xht": [
"4d09efe797f9b164e19fda16d6491fa99a855141",
"reftest"
@@ -483860,14 +490120,6 @@
"3fd4fd27cd2432bf388f08fb009cd5cd7cded59f",
"reftest"
],
- "css/css-multicol/multicol-width-ems-001.xht": [
- "1de2ecbb10805a48b831091cbee976b653899316",
- "reftest"
- ],
- "css/css-multicol/multicol-width-ems-ref.xht": [
- "16f14c6750b7afa4deb8b2c0e70a602723753794",
- "support"
- ],
"css/css-multicol/multicol-width-invalid-001-ref.xht": [
"da0d8783395284175b7f7b2ece6f8050aae10829",
"support"
@@ -483893,15 +490145,15 @@
"support"
],
"css/css-multicol/multicol-width-small-001.xht": [
- "0962e4c7c6f3698ccbf6c82fa0664b9817ffe208",
+ "c552224d18ceccc91b84936e3e7355ec513c0d3a",
"reftest"
],
"css/css-multicol/multicol-zero-height-001-ref.xht": [
- "77a1ed4066efbb3d248a899f327b3de37723f5db",
+ "12787b95e22d180606eb24b9cf43eaeb0ca9fe3f",
"support"
],
"css/css-multicol/multicol-zero-height-001.xht": [
- "88922e252f8ec0437ee747fe161f12983e94bd6f",
+ "81373bbae307e030054a54a6685793ae794e07f0",
"reftest"
],
"css/css-multicol/reference/multicol-basic-005-ref.xht": [
@@ -484228,6 +490480,14 @@
"0cba1aed016d08e4706bffb8a4f4169c9cfd2108",
"visual"
],
+ "css/css-overflow/input-scrollable-region-001.html": [
+ "f51bc673da28b0471018cdf945b4449ab00ce717",
+ "reftest"
+ ],
+ "css/css-overflow/reference/input-scrollable-region-001-ref.html": [
+ "31e24bb1a2cb6f42703cc05e055fcb345c770a22",
+ "support"
+ ],
"css/css-page/OWNERS": [
"d4ee6029cc9c064e0e8b2c76becf3b59c4f7b62b",
"support"
@@ -484548,6 +490808,14 @@
"368a9d855ffc46457e6c54cddfbc934e92096ee0",
"reftest"
],
+ "css/css-paint-api/geometry-with-float-size-ref.html": [
+ "4ccf13c66fbd9ce8a2f04eab8b5f6cd24a6601fa",
+ "support"
+ ],
+ "css/css-paint-api/geometry-with-float-size.https.html": [
+ "911b7945792a8d3157cf183e4eb02e6e10ffa80a",
+ "reftest"
+ ],
"css/css-paint-api/hidpi/device-pixel-ratio-ref.html": [
"18f9d4d369de750ceb92c2e275ede5fcb3bf6f49",
"support"
@@ -484765,7 +491033,7 @@
"support"
],
"css/css-paint-api/registered-properties-in-custom-paint.https.html": [
- "3855c8c28ea3a24bade81080f3f288ef75243dce",
+ "4eee3e45f32779df4464132fa43717a3afc135b2",
"reftest"
],
"css/css-paint-api/style-background-image-ref.html": [
@@ -484773,7 +491041,7 @@
"support"
],
"css/css-paint-api/style-background-image.https.html": [
- "a3202db04922cc2527436fa319ea9e8432eecdcd",
+ "54f213635749ffeae4d21a5e3d4391901fbfe984",
"reftest"
],
"css/css-paint-api/style-before-pseudo-ref.html": [
@@ -484781,7 +491049,7 @@
"support"
],
"css/css-paint-api/style-before-pseudo.https.html": [
- "7808e4e86a0556202a0e2ea5574d60c94bf2c537",
+ "7e8263880905e254e7c27274d6314ba23bd1cb04",
"reftest"
],
"css/css-paint-api/style-first-letter-pseudo-ref.html": [
@@ -485004,6 +491272,10 @@
"88e35164b6ede3adf9727989cf59ff9956bdbae7",
"reftest"
],
+ "css/css-position/position-sticky-offset-overflow.html": [
+ "cab620b2008a9df57abc6907b1199e35a4099241",
+ "testharness"
+ ],
"css/css-position/position-sticky-offset-top-left.html": [
"a25b64d016644c272ea92b6129a59eefb21d2fa0",
"testharness"
@@ -485044,6 +491316,14 @@
"ac1e643ac9f03d0fe415c3f52a4db7c407dd3537",
"reftest"
],
+ "css/css-position/position-sticky-table-parts-ref.html": [
+ "fb0cfd30f01c7184753057a9b98560e7b5b53f4b",
+ "support"
+ ],
+ "css/css-position/position-sticky-table-parts.html": [
+ "1558a0c2e628727143fb3368490a180947a631f9",
+ "reftest"
+ ],
"css/css-position/position-sticky-table-tfoot-bottom-ref.html": [
"b902bec7e12fd6d9cad02c61f332a44f5818f8ee",
"support"
@@ -485177,11 +491457,11 @@
"reftest"
],
"css/css-pseudo/marker-font-properties-ref.html": [
- "d83c1ae2c21ad4c20961725589481f046e108a99",
+ "4aadcf9f85ad69757f8cde95a198bf7c4ab118d1",
"support"
],
"css/css-pseudo/marker-font-properties.html": [
- "ac3d673508fb9578d0a1d363b82021df8a1b9fbd",
+ "7d4739f2252956461b38d8b8566a84ead3c1d8b1",
"reftest"
],
"css/css-pseudo/marker-inherit-values-ref.html": [
@@ -488185,7 +494465,7 @@
"testharness"
],
"css/css-shapes/shape-outside/values/shape-image-threshold-003.html": [
- "2e81c6f4c0a29148086e50052edd03566fe231b4",
+ "d0415a0b89188f1456b0c2d58e26d8dbed9d9188",
"testharness"
],
"css/css-shapes/shape-outside/values/shape-margin-000.html": [
@@ -488704,10 +494984,6 @@
"3db4dec22e96cce52c575f4adb7a05f79917d4ea",
"support"
],
- "css/css-style-attr/reference/ref-green-on-green2.xht": [
- "9a4067fbea6534ad20a0354457eb7ade8053bbf6",
- "support"
- ],
"css/css-style-attr/reference/ref-green.html": [
"8bc36f756c7ae32af5c52021c92bb04d1a0de876",
"support"
@@ -488781,7 +495057,7 @@
"reftest"
],
"css/css-style-attr/style-attr-urls-003.xht": [
- "3131ef4985d72c3a70461d451ff0f6b2a253895f",
+ "e7575e77570089b0b73e518e94fc3d69ce1184cc",
"reftest"
],
"css/css-style-attr/support/1x1-green.png": [
@@ -489384,10 +495660,42 @@
"9eeb49d2d78c3f81825de0d9e24de2a097275175",
"testharness"
],
+ "css/css-tables/zero-rowspan-001-ref.html": [
+ "b7886acdf8a380f85ebbcab0ded1e927fd509600",
+ "support"
+ ],
+ "css/css-tables/zero-rowspan-001.html": [
+ "829a239706861a54c5df555d201dc420c4f10e3b",
+ "reftest"
+ ],
+ "css/css-tables/zero-rowspan-002-ref.html": [
+ "07e79fd25abfc9bf0564131759fdda36596146d5",
+ "support"
+ ],
+ "css/css-tables/zero-rowspan-002.html": [
+ "8af937e93ee34799939632b4aed0083cb7d2c0ca",
+ "reftest"
+ ],
"css/css-text-decor/OWNERS": [
"a19d2032ed9435567cd11ccbb860515ad5d14f71",
"support"
],
+ "css/css-text-decor/line-through-vertical.html": [
+ "d3fb9b272eafcfd36cefcc6a030c6ae3795a669c",
+ "reftest"
+ ],
+ "css/css-text-decor/reference/line-through-vertical-ref.html": [
+ "f38d583fbcd41470cefb566d7b18c49758b2ebd2",
+ "support"
+ ],
+ "css/css-text-decor/reference/text-decoration-color-recalc-ref.html": [
+ "f97bae89c262da57e45294db7638159114047da3",
+ "support"
+ ],
+ "css/css-text-decor/reference/text-decoration-color-ref.html": [
+ "4ef765ae8d80ac3eab177109e9bd5b2b7142880f",
+ "support"
+ ],
"css/css-text-decor/reference/text-decoration-line-010-ref.xht": [
"ba55218db818b208176448c9ae0adb4ee101ea53",
"support"
@@ -489404,6 +495712,22 @@
"065a1c1af6c12c7d2043c3d318330ba3028cdd87",
"support"
],
+ "css/css-text-decor/reference/text-decoration-line-recalc-ref.html": [
+ "8e8c434546c5f4b6184d935f16b8e1479c39eb11",
+ "support"
+ ],
+ "css/css-text-decor/reference/text-decoration-line-ref.html": [
+ "3612462ad5a2c5447adf1fc80f6aa2b4ee5cb001",
+ "support"
+ ],
+ "css/css-text-decor/reference/text-decoration-style-multiple-ref.html": [
+ "e23906652f3abb2123d70b11a7002262ba661f8b",
+ "support"
+ ],
+ "css/css-text-decor/reference/text-decoration-style-recalc-ref.html": [
+ "6c6057bb2fd3e94e6141426a9de282120e354bb5",
+ "support"
+ ],
"css/css-text-decor/reference/text-emphasis-color-001-ref.xht": [
"999f10b2466d839871ca9e974de158b84f5e2a90",
"support"
@@ -489492,6 +495816,14 @@
"fa665f1520b2148805c182feda36860ef5647c65",
"support"
],
+ "css/css-text-decor/text-decoration-color-recalc.html": [
+ "333110782c52aa29f0ac547164cf754025a285b9",
+ "reftest"
+ ],
+ "css/css-text-decor/text-decoration-color.html": [
+ "7a11633ef29f67fc2242a265a63749bd9e5c1cfe",
+ "reftest"
+ ],
"css/css-text-decor/text-decoration-line-010.xht": [
"f6c9486f8482db4566b88ccaa4ace97dec8062b1",
"reftest"
@@ -489512,10 +495844,30 @@
"e0d6dbb039133f5aee07cc8dd3d96942727bdec0",
"manual"
],
+ "css/css-text-decor/text-decoration-line-recalc.html": [
+ "ab48a5baca2e14a4618dc57f2b96badf98dfd077",
+ "reftest"
+ ],
+ "css/css-text-decor/text-decoration-line.html": [
+ "2b56bc3ac545e449d4beff61d5c7c1fd97060042",
+ "reftest"
+ ],
+ "css/css-text-decor/text-decoration-serialization.tentative.html": [
+ "9266aa2318ae1e023fd287cf3f89e3f62851a8b2",
+ "testharness"
+ ],
"css/css-text-decor/text-decoration-skip-ink.html": [
"a633a231d8fd6b5408add5fab972046651889b09",
"testharness"
],
+ "css/css-text-decor/text-decoration-style-multiple.html": [
+ "4f6e24cfb87dd4b8efb51154e70fbc14e35124da",
+ "reftest"
+ ],
+ "css/css-text-decor/text-decoration-style-recalc.html": [
+ "9dbfa25a35ae3959b51b28f71a29cbd9188322b3",
+ "reftest"
+ ],
"css/css-text-decor/text-decoration-visibility-001.xht": [
"98b6617c1bc20a207de477eb33defb8922192e17",
"visual"
@@ -495877,8 +502229,8 @@
"visual"
],
"css/css-transforms/css-transform-inherit-scale.html": [
- "79bf0552c20649ba4f4c8442176ce349616bf750",
- "visual"
+ "1afd10f480afbd37ba7f55daae31003146fd22c1",
+ "reftest"
],
"css/css-transforms/css-transform-property-existence.html": [
"c34a6640c14cb4267030b85277060a160fe78b78",
@@ -498245,7 +504597,7 @@
"support"
],
"css/css-transforms/transform-2d-getComputedStyle-001.html": [
- "0ecbf50593b1516a04578fd0bb1c9da207eee968",
+ "b4ed47027bac6bafad816e6bf8d5b179b8c5a90d",
"testharness"
],
"css/css-transforms/transform-3d-rotateY-stair-above-001.xht": [
@@ -498344,6 +504696,38 @@
"ce510cf7f18b469b45a3176d92b56ad91fd79f3c",
"support"
],
+ "css/css-transforms/transform-box/fill-box-mutation.html": [
+ "80011b1eba63c4b374e4aeed1990ed4707955704",
+ "reftest"
+ ],
+ "css/css-transforms/transform-box/fill-box.html": [
+ "76eadff35072aeca5d276a62c13f2a259d13347f",
+ "reftest"
+ ],
+ "css/css-transforms/transform-box/support/greensquare200x200.html": [
+ "f58dd69d9f2997d23ed30f45296751115205aec6",
+ "support"
+ ],
+ "css/css-transforms/transform-box/value-changed.html": [
+ "dc7ddb4aaf7a37cf4619795e64a54472607b2de2",
+ "reftest"
+ ],
+ "css/css-transforms/transform-box/view-box-nested.html": [
+ "88856f064883fb794c83278333f8ea0df992111f",
+ "reftest"
+ ],
+ "css/css-transforms/transform-box/view-box-viewbox-nested.html": [
+ "9e0cfd6e001d551ca530d736c5aebfb2c3076178",
+ "reftest"
+ ],
+ "css/css-transforms/transform-box/view-box-viewbox.html": [
+ "0e552a16a701bb982d31375559fa4d595729b4c6",
+ "reftest"
+ ],
+ "css/css-transforms/transform-box/view-box.html": [
+ "90101f67d24beab0c86e940bde79dfb553902e85",
+ "reftest"
+ ],
"css/css-transforms/transform-compound-001.html": [
"511cf5f6aaf6ca25dd6afd5286df771535fb1abc",
"reftest"
@@ -500989,23 +507373,23 @@
"support"
],
"css/css-transitions/before-DOMContentLoaded-001.html": [
- "ce73650ab61ae0244f7d7aab2aef1a30c4ed66cc",
+ "d9a08984058da3dbedada7d0dff2d4743e3dd15b",
"testharness"
],
"css/css-transitions/before-load-001.html": [
- "eb57025c206784ff80e57d558b41fa5f195dc8ec",
+ "7f5f54505f119b0b491df50fcf23d60909f41126",
"testharness"
],
"css/css-transitions/changing-while-transition.html": [
- "961c630579d590e3fd8e270ea8b63b9495a4d60b",
+ "49ca30de94a41c9228189c44267bdf36a6e8bde2",
"testharness"
],
"css/css-transitions/currentcolor-animation-001.html": [
- "91cab6789a46df4fb4b1e2baeddf3aa9eaea378f",
+ "aee4e4f0e0154f9390333e4db21904a2cda67b52",
"testharness"
],
"css/css-transitions/detached-container-001.html": [
- "09b5e9b570fcb9ca52ec9bb8d651e0c22fbe4980",
+ "45f59afdc4636ed26417999abf206382a2913968",
"testharness"
],
"css/css-transitions/events-001.html": [
@@ -501037,43 +507421,43 @@
"testharness"
],
"css/css-transitions/hidden-container-001.html": [
- "a256ef1efbfd088de9771835ecec7b5aefcc1495",
+ "971be3c362daabff565737c0d98be96e2356adb8",
"testharness"
],
"css/css-transitions/properties-value-001.html": [
- "ce0c9c0f5ebb844fd931e5b5e3345b3dab6531c0",
+ "66853fd915a18b3a8eb78e5d551fc7eb529b72cf",
"testharness"
],
"css/css-transitions/properties-value-002.html": [
- "f4558ff21eb2f06df7b6127ec7d1b0c3944647af",
+ "e2b14b1a6a08e6453f5b040e7be1212b13aa92e2",
"testharness"
],
"css/css-transitions/properties-value-003.html": [
- "bb593998dbb2d0e8cc2cf20dcf0dc70a6bf0d4fb",
+ "71274e78c1c5fc7ced69e9d9bb2fcf076c3806dd",
"testharness"
],
"css/css-transitions/properties-value-auto-001.html": [
- "436ce4d98c82a6cacb9e1a242013bb1803a84c87",
+ "4e1c0fa89888d91e1b5085cb19624eba843a5905",
"testharness"
],
"css/css-transitions/properties-value-implicit-001.html": [
- "5d00e4d4ab32234b66d20feb177b06f74b1a2864",
+ "30fdd86871362bfdca019a5c339f80ebff49d2b2",
"testharness"
],
"css/css-transitions/properties-value-inherit-001.html": [
- "0f2b37271a64887682e10c37123867f9f14c4af8",
+ "63ddc6510fa07988df7f11d6d0070563ded61887",
"testharness"
],
"css/css-transitions/properties-value-inherit-002.html": [
- "722ebf1da22eab5920d3e4b7704bb80247ad3bcd",
+ "da354ecb506958e9b0d8c1224b05e19f551cb072",
"testharness"
],
"css/css-transitions/properties-value-inherit-003.html": [
- "c5704809d884d5f6216191543e7d0809cf913b27",
+ "85156d3741f742f7d621b27354d941d72bc949f1",
"testharness"
],
"css/css-transitions/pseudo-elements-001.html": [
- "4f42cf7e196e1a7afb25a231fb3ce64e8c9bd194",
+ "43108935a5bf1e23ed8a61688843c7246b77b752",
"testharness"
],
"css/css-transitions/reference/transition-test-ref.html": [
@@ -501285,7 +507669,7 @@
"support"
],
"css/css-transitions/transition-001.html": [
- "806d0704847c4d383a09afe8a2c26c9b6ecca30b",
+ "2068fe442683e6242633527409c89940d4e04bda",
"testharness"
],
"css/css-transitions/transition-delay-000.html": [
@@ -501293,7 +507677,7 @@
"manual"
],
"css/css-transitions/transition-delay-001.html": [
- "54ee8c0690235dc4028a485d26edfbdcd05a405b",
+ "8da706562352ef5aa455be87a1a35246513976d5",
"testharness"
],
"css/css-transitions/transition-delay-002.html": [
@@ -501305,7 +507689,7 @@
"manual"
],
"css/css-transitions/transition-duration-001.html": [
- "8fe9e0c26be9546616a5fb478cb923ba01443534",
+ "9d8ed6ae2885604c7358936ac3890085e4cd9943",
"testharness"
],
"css/css-transitions/transition-duration-002.html": [
@@ -501321,11 +507705,11 @@
"manual"
],
"css/css-transitions/transition-property-001.html": [
- "365990e00895d721f63d1922de7a135d0e1da442",
+ "8977177635cae901a9f7540c94c6cc74f0ca8d6f",
"testharness"
],
"css/css-transitions/transition-property-002.html": [
- "aec901f17b242ea20e4f9a0000afc721e3b1afe5",
+ "e4019e8e5ec748cdf5c1112ab87fcfb8478c6410",
"testharness"
],
"css/css-transitions/transition-property-003.html": [
@@ -501505,7 +507889,7 @@
"reftest"
],
"css/css-transitions/transition-timing-function-001.html": [
- "4311e0f7879579130ebf9a540b3b116ed3a9c6d1",
+ "4b2e7ebb296da03f72f509e3cbc8d647c162c449",
"testharness"
],
"css/css-transitions/transition-timing-function-002.html": [
@@ -501573,7 +507957,7 @@
"testharness"
],
"css/css-typed-om/factory-absolute-length.html": [
- "a0049b74fea0fc581ca9896792cbc35568e68771",
+ "2d4f84c4ad1121b5415edcbaab6918a933dfdd60",
"testharness"
],
"css/css-typed-om/factory-duration.html": [
@@ -501585,7 +507969,15 @@
"testharness"
],
"css/css-typed-om/styleMap-update-function.html": [
- "537fbd8e64906ce91b3ed387ede6abdc790750a3",
+ "a1dee75d914b68753af742ce8e6dbbac0397a9a6",
+ "testharness"
+ ],
+ "css/css-typed-om/stylevalue-objects/interface.html": [
+ "5c9086db5b7f3a9d6e3109f1ce47385ad345f474",
+ "testharness"
+ ],
+ "css/css-typed-om/stylevalue-subclasses/cssKeywordValue-interface.html": [
+ "53394d04d67fa9526240c2c0af8b71f54a60a0c3",
"testharness"
],
"css/css-ui/OWNERS": [
@@ -503957,7 +510349,7 @@
"testharness"
],
"css/css-values/calc-unit-analysis.html": [
- "995e7d094cb02f142d28ff0ca7de9d98f9a298e3",
+ "c5fd567b4fa257ce53c48ebf8c444bf382459fec",
"testharness"
],
"css/css-values/ch-unit-001.html": [
@@ -504000,14 +510392,6 @@
"ea1f5256caff0fc42f8dbf843322e51189cee065",
"reftest"
],
- "css/css-values/iframe/vh-support-transform-origin-iframe.html": [
- "e295875de4bc58b51c45db9a87648749bdfc7e8d",
- "visual"
- ],
- "css/css-values/iframe/vh-support-transform-translate-iframe.html": [
- "3d8502cd78bacbdddb771bed8f028c880f9b105b",
- "visual"
- ],
"css/css-values/initial-background-color.html": [
"5e071d71a9cc355a62d0165b4ca2840ba0ab8c66",
"reftest"
@@ -504220,6 +510604,14 @@
"078e1dd6dd61d36cec239ed75d02051f61fe60a5",
"support"
],
+ "css/css-values/support/vh-support-transform-origin-iframe.html": [
+ "e295875de4bc58b51c45db9a87648749bdfc7e8d",
+ "support"
+ ],
+ "css/css-values/support/vh-support-transform-translate-iframe.html": [
+ "3d8502cd78bacbdddb771bed8f028c880f9b105b",
+ "support"
+ ],
"css/css-values/support/vh_not_refreshing_on_chrome_iframe.html": [
"95f9582bf94c0bc60ddee79415b763af8762faf0",
"support"
@@ -504265,11 +510657,11 @@
"reftest"
],
"css/css-values/vh-support-transform-origin.html": [
- "2fc033c3d515ae1afd364f72818cd814d15779c8",
+ "2ddd949c507d93d280e61fc3aaed35463ee1fed0",
"reftest"
],
"css/css-values/vh-support-transform-translate.html": [
- "11ade5a7670dbfe781dfaa14d9a2476a586ce34c",
+ "337a80ea54be900454c296910d38254bf20589e6",
"reftest"
],
"css/css-values/vh-support.html": [
@@ -504333,7 +510725,7 @@
"support"
],
"css/css-variables/test_variable_legal_values.html": [
- "a6ffd6e1e3479aad164dcf678e7382b365473448",
+ "fb40b2d7cf51500c180568709cedb5203c2e7ebf",
"testharness"
],
"css/css-variables/variable-animation-from-to.html": [
@@ -506009,8 +512401,8 @@
"reftest"
],
"css/css-writing-modes/bidi-table-001.html": [
- "cfad37ee8ded9dc4eec6aa5d615c73bba9ca039f",
- "visual"
+ "f6a6a6ddac6c82a0734ec8af418c140ead454c1d",
+ "reftest"
],
"css/css-writing-modes/bidi-unset-001.html": [
"3558315a55357f817a95aa0ecbd8d62a8b1ae7a9",
@@ -506341,8 +512733,8 @@
"visual"
],
"css/css-writing-modes/block-plaintext-006.html": [
- "cadc2347f3c345f4e1ea08ec1950641416585a07",
- "visual"
+ "de33a946a26b9ab6f4b04b486ca02cbfc2944d90",
+ "reftest"
],
"css/css-writing-modes/border-conflict-element-vlr-003.xht": [
"2272a00893c883362930f93fff7677c1cde6532e",
@@ -510929,7 +517321,7 @@
"testharness"
],
"css/cssom-view/elementFromPosition.html": [
- "2bb07e21ddfbc24dabc39fa261c720a36f56a933",
+ "f033a1ec4b1f0636897c4ee16b67c1c13f0eac4e",
"testharness"
],
"css/cssom-view/elementScroll.html": [
@@ -511001,7 +517393,7 @@
"testharness"
],
"css/cssom-view/offsetParent_element_test.html": [
- "b2261ec702116c211ab5ac6fbb53698dfe60a7be",
+ "2c3a4481d0ed7773420bf2059047d1d337c899dd",
"testharness"
],
"css/cssom-view/offsetTopLeftInScrollableParent.html": [
@@ -511009,7 +517401,7 @@
"testharness"
],
"css/cssom-view/overscrollBehavior-manual.html": [
- "ca369af991f1e1c34116f2effe0d53a806ed9df5",
+ "65cb71ca6b606dc8b0b527c58902566539e771b2",
"manual"
],
"css/cssom-view/resources/elementsFromPoint.js": [
@@ -511024,6 +517416,10 @@
"0a8784c474ccdd4a3e76cb936855a8ef59566217",
"support"
],
+ "css/cssom-view/scroll-behavior-smooth.html": [
+ "966ebff69f91c0ea92f4bc2f943df9ef9dc3bcf9",
+ "testharness"
+ ],
"css/cssom-view/scrollIntoView-shadow.html": [
"3c4a18992105fd7bf19cbf29f0b6d80cb12ca98c",
"testharness"
@@ -511032,12 +517428,20 @@
"0561564f185dcaf2ad3a8e14e081efb3c2c273e3",
"testharness"
],
+ "css/cssom-view/scrollTop-display-change-ref.html": [
+ "bb9079ba597cbcc27604cf8cc5556b4e6e0cda93",
+ "support"
+ ],
+ "css/cssom-view/scrollTop-display-change.html": [
+ "68d33e9669be4db95ea9016a8893212e588189fd",
+ "reftest"
+ ],
"css/cssom-view/scrollWidthHeight.xht": [
- "06ec592720f3db3c04cdd792177179b11a097a23",
+ "503316b6ea12a881566cce0e2e78ddfc942297f0",
"testharness"
],
"css/cssom-view/scrollWidthHeightWhenNotScrollable.xht": [
- "dfac20693a9d2bcbc74e372177b1a04472de8f8f",
+ "897d0db30122018a1b71c52d12f16c41ea845954",
"testharness"
],
"css/cssom-view/scrolling-no-browsing-context.html": [
@@ -511253,7 +517657,7 @@
"testharness"
],
"css/cssom-view/window-interface.xht": [
- "4d8c4ddb997d85ca2c971602a3096f57565c01eb",
+ "b51ac4828be890736faee8ce42fd95c4bbb844ef",
"testharness"
],
"css/cssom-view/window-screen-height-immutable.html": [
@@ -511309,7 +517713,7 @@
"testharness"
],
"css/cssom/MediaList2.xhtml": [
- "277ec40d3a64d9881e594901a6bcdcd6b70405db",
+ "c7481f3c0fe943abb6d67004d6c4aaff12180e34",
"testharness"
],
"css/cssom/OWNERS": [
@@ -511321,7 +517725,7 @@
"testharness"
],
"css/cssom/computed-style-001.html": [
- "a940a84552ddcd716af743e0e8746c7582b5c760",
+ "0331a648e6b0d56f0e7365f1ff7d991ea77ce3e4",
"testharness"
],
"css/cssom/css-style-attribute-modifications.html": [
@@ -511373,7 +517777,7 @@
"testharness"
],
"css/cssom/getComputedStyle-pseudo.html": [
- "98f4a9a445621ae328a317402bdfb62c83de6b43",
+ "a2033405d6852cdeb4c3b8cf628f7c1d8f7cd1aa",
"testharness"
],
"css/cssom/historical.html": [
@@ -511389,7 +517793,7 @@
"testharness"
],
"css/cssom/inline-style-001.html": [
- "377c8610bc597d47a93f70a9cf95b3c7657d8319",
+ "da50f9738f161a0bb9af5a5636634346bb683fa9",
"testharness"
],
"css/cssom/insertRule-charset-no-index.html": [
@@ -511412,20 +517816,28 @@
"c1dfd96239986c9c57d7b07caebbd1fc9654e0b9",
"testharness"
],
+ "css/cssom/medialist-dynamic-001-ref.html": [
+ "bdf98c994adcebff3a3434260dfe71e99c8441e1",
+ "support"
+ ],
+ "css/cssom/medialist-dynamic-001.html": [
+ "8c62d1e6b5791b68240551c0c9cd115f4d16a892",
+ "reftest"
+ ],
"css/cssom/medialist-interfaces-001.html": [
- "dfaea262508d72d123006409174e3e21832a305f",
+ "32d486ecdd41418e734be028c150b0183b8d3316",
"testharness"
],
"css/cssom/medialist-interfaces-002.html": [
- "114fac94342afe2e7fe432a67c4b0bbf03d24bc4",
+ "20d4d9e76e0331816aed5f70182dee6966e568e7",
"testharness"
],
"css/cssom/medialist-interfaces-003.html": [
- "b9ddd611cc585202b1e76382666b04197af334b0",
+ "42c6fb48a67af381e09995e27dcd8795557345dd",
"testharness"
],
"css/cssom/medialist-interfaces-004.html": [
- "e3cdc88670ca46b3752fd8118d94dae2cc95258d",
+ "9558544a6785ac732150b8a50bedbaf3615fa890",
"testharness"
],
"css/cssom/overflow-serialization.html": [
@@ -511460,16 +517872,20 @@
"5e83f084efc82184c3052a40bb4a061fd4a1336f",
"testharness"
],
+ "css/cssom/setproperty-null-undefined.html": [
+ "8521d827e1e641c3b856854c38eac66a97ddf690",
+ "testharness"
+ ],
"css/cssom/shorthand-serialization.html": [
"bd514834dbd48c267c16a4329af6fec7f6cbc081",
"testharness"
],
"css/cssom/style-sheet-interfaces-001.html": [
- "e77ec7de74baa901cc15a3b90d2b29125c282562",
+ "6dbb52cd85cb3bbc711a3569e0f253d7086a43a0",
"testharness"
],
"css/cssom/style-sheet-interfaces-002.html": [
- "875598ca4271d4adaa11fbb01981b290e6235019",
+ "8fc091c20efd7fc71c6c357278977ee6137fd8d4",
"testharness"
],
"css/cssom/stylesheet-replacedata-dynamic-ref.html": [
@@ -511673,7 +518089,7 @@
"support"
],
"css/cssom/ttwf-cssom-doc-ext-load-count.html": [
- "800db5cd4f7342d8c4e5309d4035182ce42f7251",
+ "035984ef66730a2f87c08dbcba76a2620cf70775",
"testharness"
],
"css/cssom/ttwf-cssom-doc-ext-load-tree-order.html": [
@@ -512645,19 +519061,19 @@
"reftest"
],
"css/mediaqueries/mq-calc-002.html": [
- "58c831e53e5aed91da4ba4ed1375a25624f5d9b8",
+ "6b77bc8b8fec58a8fa0d246532a86282ee30a81a",
"reftest"
],
"css/mediaqueries/mq-calc-003.html": [
- "41fe79a4d2fd208c8f9b503efed122e2f6d25f25",
+ "21320b601e3c91f1d4e8ad72e53861af2c184f18",
"reftest"
],
"css/mediaqueries/mq-calc-004.html": [
- "9602d9f7bd90031890850032572a25ab51c2ed17",
+ "7cad13aa87e8a0d95dc9e35eb7d1dec7930939fb",
"reftest"
],
"css/mediaqueries/mq-calc-005.html": [
- "154fc9c31ab6b50f54214bc2198a7e5d8c66b2a1",
+ "75334bbcf4ef412b9976c59e1efe2177ad62b465",
"reftest"
],
"css/mediaqueries/mq-invalid-media-type-001.html": [
@@ -512681,19 +519097,19 @@
"support"
],
"css/mediaqueries/relative-units-001.html": [
- "e776e9d66ce2a71e9dc156c8e9566ab51ee632c9",
+ "d5a9cddad47e67048e8ba5d54c3cd0abca93efbe",
"reftest"
],
"css/mediaqueries/relative-units-002.html": [
- "c533d6fead2ed27d02b826aeba0d8abbb45031a2",
+ "1542d3980b34ff68437c734a98dd6452eae51eb0",
"reftest"
],
"css/mediaqueries/relative-units-003.html": [
- "e42e3e16ae2cc3c2c9679c653fcb9d6ab49e1c15",
+ "12e3a8ff864ad507bd9f7ad860434682b9c23cba",
"reftest"
],
"css/mediaqueries/relative-units-004.html": [
- "1db0c6b7ee4aa554328cda73a7fab0bd373598c8",
+ "8cf95c93cfdb225588ffa2218a2f5948a48bb849",
"reftest"
],
"css/mediaqueries/support/media_queries_iframe.html": [
@@ -512705,7 +519121,7 @@
"support"
],
"css/mediaqueries/test_media_queries.html": [
- "4f4f13f66e77a41e97ee5035568f1e0944ec8b2e",
+ "7b0a2c7025dd0bd6aee14935760f88cd1f09c7dc",
"testharness"
],
"css/motion/animation/offset-anchor-interpolation.html": [
@@ -512716,6 +519132,26 @@
"f242f67f0d1a1c25a871d4ae949d42f9d1df0027",
"testharness"
],
+ "css/motion/animation/offset-path-interpolation-001.html": [
+ "89e4b811c0125ead111206b150b26c97e684ad5b",
+ "testharness"
+ ],
+ "css/motion/animation/offset-path-interpolation-002.html": [
+ "63ad6fda28ca9e980c55467de211bb39569b9c62",
+ "testharness"
+ ],
+ "css/motion/animation/offset-path-interpolation-003.html": [
+ "f6b4dbbb04e9e22358aaa121b7a718e71e0fa973",
+ "testharness"
+ ],
+ "css/motion/animation/offset-path-interpolation-004.html": [
+ "dee154d12679ba899879dae5ee35f05f408bfab9",
+ "testharness"
+ ],
+ "css/motion/animation/offset-path-interpolation-005.html": [
+ "1d688f56be81a4c5197590c4930608b95e535952",
+ "testharness"
+ ],
"css/motion/animation/offset-position-interpolation.html": [
"6c21c93c0715af758033d7b582f072988b379b15",
"testharness"
@@ -512820,6 +519256,10 @@
"4aced258fbe6ada965f2a0707fad78878af7f162",
"support"
],
+ "css/reference/nothing.html": [
+ "c761e386839fbcc7eb1fc9c66f8839b3cd15ec95",
+ "support"
+ ],
"css/reference/only_pass_parens_semicolon.html": [
"eec4a0a2b3f8f77c8b7c124e33617ce42c6e5209",
"support"
@@ -512868,6 +519308,10 @@
"c5f3a64d83b3f35ac627d9428eeb03668ad2865e",
"support"
],
+ "css/reference/ref-filled-green-100px-square-only.html": [
+ "b78537c1c18697493412ca96bbb6e6d67304e0d7",
+ "support"
+ ],
"css/reference/ref-filled-green-100px-square.xht": [
"2f6ee60666fbb65497dc8749683d66ae543bad12",
"support"
@@ -512908,6 +519352,14 @@
"b45da5560d0eb821b5552f1b67fab5cead4508b1",
"support"
],
+ "css/selectors/any-link-dynamic-001-ref.html": [
+ "342d89969da0ca3782efacee0ecbf882c718d6c6",
+ "support"
+ ],
+ "css/selectors/any-link-dynamic-001.html": [
+ "c33602e863151182d29afd88a8878374bb118b69",
+ "reftest"
+ ],
"css/selectors/attribute-selectors/attribute-case/cssom.html": [
"d5e05750213fbf7959125d64e9ea1a26948ba91d",
"testharness"
@@ -514492,6 +520944,10 @@
"394ad01c928f8a15796bc6c29cdbc5e2dc37fd52",
"testharness"
],
+ "css/selectors/invalidation/any-link-pseudo.html": [
+ "9593a7d2dddc79525edb801748a28b1a5a1837c7",
+ "testharness"
+ ],
"css/selectors/missing-right-token.html": [
"d961e801f7df57161cd8c7b5a4b26ae24013c3e9",
"testharness"
@@ -523109,7 +529565,7 @@
"testharness"
],
"custom-elements/parser/parser-uses-registry-of-owner-document.html": [
- "492b05763f5c94429bc2ea6cc2db9cb01417695a",
+ "a62669ffcc75d54df38b65e33463566238c8644c",
"testharness"
],
"custom-elements/reaction-timing.html": [
@@ -523137,7 +529593,7 @@
"testharness"
],
"custom-elements/reactions/Document.html": [
- "ab7d3d84305f1261e41a76d08296950fd3e5a483",
+ "96a008a0fe4513986fec1d1329b0f90689b1d504",
"testharness"
],
"custom-elements/reactions/Element.html": [
@@ -523220,6 +529676,10 @@
"e966b6c608ee9b4183e040b8be7adb2b73722c7b",
"support"
],
+ "custom-elements/reactions/with-exceptions.html": [
+ "b72ee82a3d98c61683e62c4834f54269898e12d5",
+ "testharness"
+ ],
"custom-elements/resources/custom-elements-helpers.js": [
"875838d63f7d44c7a958a03c494ba709c53816c9",
"support"
@@ -523228,6 +529688,10 @@
"c436e35464c8c32f3afb191c46ef599b4986a395",
"support"
],
+ "custom-elements/resources/my-custom-element-html-document.html": [
+ "8d2ac097525aca96f01e3bf73f5e3c144d43fa27",
+ "support"
+ ],
"custom-elements/upgrading.html": [
"da38f84be26bb7f33d949f65ebe26153f9631b45",
"testharness"
@@ -523625,7 +530089,7 @@
"testharness"
],
"dom/events/Event-subclasses-constructors.html": [
- "5da96a9be09ad5dc69438ba9bd6b2ab58cf77ca1",
+ "52382c89b67be3c3fbb8bccccb6f75a4aaa7975b",
"testharness"
],
"dom/events/Event-timestamp-high-resolution.html": [
@@ -523669,7 +530133,7 @@
"support"
],
"dom/events/EventListener-invoke-legacy.html": [
- "e56b332acb454ab76964b78588536777946ddff8",
+ "13cb3802cb2722417b876ded17fddd222c69564a",
"testharness"
],
"dom/events/EventListenerOptions-capture.html": [
@@ -523697,7 +530161,7 @@
"testharness"
],
"dom/historical.html": [
- "99cd2739cdfcb5b2c6bf0df098abdfcc4203b891",
+ "ccf3d9d2d8eb3e7353ecedd8a4d8ba232f9374ec",
"testharness"
],
"dom/interface-objects.html": [
@@ -525697,7 +532161,7 @@
"testharness"
],
"encoding/big5-encoder.html": [
- "b9635c43ce159e1961106b039dce0e3d04fade34",
+ "c5fec0f733b77620267488917cf54554c766801f",
"testharness"
],
"encoding/eof-shift_jis-ref.html": [
@@ -525737,7 +532201,7 @@
"testharness"
],
"encoding/gbk-encoder.html": [
- "30bdfc96ffaff0277ceca69aad43d82d5ac691b6",
+ "d099c6f374df5e68dd44bd6fe6115c415e74e91c",
"testharness"
],
"encoding/idlharness.html": [
@@ -526876,191 +533340,191 @@
"4cdfcbd7d8243d6cb61dbeb73535cc561cc44766",
"support"
],
- "encrypted-media/clearkey-check-initdata-type.html": [
+ "encrypted-media/clearkey-check-initdata-type.https.html": [
"edf050cdd617f5e1b9de04c3c77b2bb92b22a74f",
"testharness"
],
- "encrypted-media/clearkey-events-session-closed-event.html": [
+ "encrypted-media/clearkey-events-session-closed-event.https.html": [
"df3718598584c8ac59be5d4b8ef85083e1e9ddcf",
"testharness"
],
- "encrypted-media/clearkey-events.html": [
+ "encrypted-media/clearkey-events.https.html": [
"75c9904a525c4bb1ec495445660671ad5279f0a7",
"testharness"
],
- "encrypted-media/clearkey-generate-request-disallowed-input.html": [
+ "encrypted-media/clearkey-generate-request-disallowed-input.https.html": [
"4426b44b87b52f17c8dff8027c61e3e39ac9e321",
"testharness"
],
- "encrypted-media/clearkey-invalid-license.html": [
+ "encrypted-media/clearkey-invalid-license.https.html": [
"4fa0b5af9fce24e3f6abd932f2352ff4deb0f90f",
"testharness"
],
- "encrypted-media/clearkey-keystatuses-multiple-sessions.html": [
+ "encrypted-media/clearkey-keystatuses-multiple-sessions.https.html": [
"aa361d04cfd38448bde43102860cb67c92378217",
"testharness"
],
- "encrypted-media/clearkey-keystatuses.html": [
+ "encrypted-media/clearkey-keystatuses.https.html": [
"0da720e35be9913eff72ca4686d09447a8b0baae",
"testharness"
],
- "encrypted-media/clearkey-mp4-playback-destroy-persistent-license.html": [
+ "encrypted-media/clearkey-mp4-playback-destroy-persistent-license.https.html": [
"31f911c3795711d1ff315baa035adbf9b82063b1",
"testharness"
],
- "encrypted-media/clearkey-mp4-playback-persistent-license-events.html": [
+ "encrypted-media/clearkey-mp4-playback-persistent-license-events.https.html": [
"77839f9d494a4ab72d19ab6d0f8c87600af78b83",
"testharness"
],
- "encrypted-media/clearkey-mp4-playback-persistent-license.html": [
+ "encrypted-media/clearkey-mp4-playback-persistent-license.https.html": [
"82870fec532dfca22931614b62104d82f361948d",
"testharness"
],
- "encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.html": [
+ "encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.https.html": [
"778a2d9d48f080b497359f18f7fe5505fc1a95a6",
"testharness"
],
- "encrypted-media/clearkey-mp4-playback-persistent-usage-record.html": [
+ "encrypted-media/clearkey-mp4-playback-persistent-usage-record.https.html": [
"0ba42cf14754d5f5a72b1bed5c4e584d98367a13",
"testharness"
],
- "encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.html": [
+ "encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.https.html": [
"fe1e7fd17a30f52936fb533e6553f09cbd9ce954",
"testharness"
],
- "encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.html": [
+ "encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.https.html": [
"c82925a064bcd0eadb81a6b92a7fac35e76b35d8",
"testharness"
],
- "encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.html": [
+ "encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.https.html": [
"3db3dfc846598a30218f740201e48ca6112f4d93",
"testharness"
],
- "encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.https.html": [
"bade72126b9a42409ef2b1901b84aef7778b2eac",
"testharness"
],
- "encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.https.html": [
"df277e779299caa92f7b82d2f8a51eb71a77eba1",
"testharness"
],
- "encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.https.html": [
"8a2c68dafa32348f869ffeffaa8952123f4cb539",
"testharness"
],
- "encrypted-media/clearkey-mp4-playback-temporary-events.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-events.https.html": [
"8a4fdf2f0ae55cc9b4c137ada2c2721701a34e89",
"testharness"
],
- "encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.https.html": [
"4252b999d028092862f18663a9ab8fe654439b8c",
"testharness"
],
- "encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.https.html": [
"3d6d572a21f7380bd69fa52360dfbde527241440",
"testharness"
],
- "encrypted-media/clearkey-mp4-playback-temporary-multikey.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-multikey.https.html": [
"8649ac8a23f45a0c8f34a31e3df58b8da786f68e",
"testharness"
],
- "encrypted-media/clearkey-mp4-playback-temporary-multisession.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-multisession.https.html": [
"6e12223723edeb54e41128c1c86b9ae04091b448",
"testharness"
],
- "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.https.html": [
"0acbe39273cd4dfffc0580ae821b4f880323ef35",
"testharness"
],
- "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.https.html": [
"a416bd41c485e4f0e48ad870cc4ddad40d194509",
"testharness"
],
- "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.https.html": [
"a1051de265005fd205ab71ccc863ab429fe1b11e",
"testharness"
],
- "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.https.html": [
"c2356c4d5fc4be3d6b096f1cc9ca026b9d2989d1",
"testharness"
],
- "encrypted-media/clearkey-mp4-playback-temporary-two-videos.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-two-videos.https.html": [
"03954e9c2ddc20b37d858bdcb29d4fb197fc2f9a",
"testharness"
],
- "encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.https.html": [
"2b195d087a715ed3b5d9803dded1b9d25c135789",
"testharness"
],
- "encrypted-media/clearkey-mp4-playback-temporary.html": [
+ "encrypted-media/clearkey-mp4-playback-temporary.https.html": [
"2d2c14ac3e4147c2ce54665ac84c102906df15bc",
"testharness"
],
- "encrypted-media/clearkey-mp4-requestmediakeysystemaccess.html": [
+ "encrypted-media/clearkey-mp4-requestmediakeysystemaccess.https.html": [
"ccd431ebc1212c33953f273a4a1665124da3b2f1",
"testharness"
],
- "encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.html": [
+ "encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.https.html": [
"ea428a6fd609c5f3243b0cb89171f23484475c60",
"testharness"
],
- "encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.html": [
+ "encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.https.html": [
"09b19346bccb01a63e3b1a509f0104f99a5723a8",
"testharness"
],
- "encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.html": [
+ "encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.https.html": [
"cba1dca366654371b3b2d046c3505d10235b9e8d",
"testharness"
],
- "encrypted-media/clearkey-mp4-setmediakeys-at-same-time.html": [
+ "encrypted-media/clearkey-mp4-setmediakeys-at-same-time.https.html": [
"6c3e3659fe5fd7ae063371f13e6a284cdcc06019",
"testharness"
],
- "encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.html": [
+ "encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html": [
"9edb8596073d8dd0a34db9398e0966f29d73b425",
"testharness"
],
- "encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html": [
+ "encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html": [
"9e177ca8da585c867cf3b9c8f08afaa914c203bc",
"testharness"
],
- "encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.html": [
+ "encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.https.html": [
"161653f14df5c4c883922a253457cc3e711dc997",
"testharness"
],
- "encrypted-media/clearkey-mp4-setmediakeys.html": [
+ "encrypted-media/clearkey-mp4-setmediakeys.https.html": [
"a3a30ffbe0c946b3dd3f50f46c819c94aefcb470",
"testharness"
],
- "encrypted-media/clearkey-mp4-syntax-mediakeys.html": [
+ "encrypted-media/clearkey-mp4-syntax-mediakeys.https.html": [
"d8cd90ecb4094e6866796edb40e50a0bfecf03d2",
"testharness"
],
- "encrypted-media/clearkey-mp4-syntax-mediakeysession.html": [
+ "encrypted-media/clearkey-mp4-syntax-mediakeysession.https.html": [
"040914ccaba738cfc9a97f4c4a839883cde8bcef",
"testharness"
],
- "encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.html": [
+ "encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.https.html": [
"b7115f8d8bbd2da5f4b2635f66909fd4e4252747",
"testharness"
],
- "encrypted-media/clearkey-mp4-unique-origin.html": [
+ "encrypted-media/clearkey-mp4-unique-origin.https.html": [
"26d01bff637c6321f4d12aa8a50722f3e30b3b40",
"testharness"
],
- "encrypted-media/clearkey-mp4-update-disallowed-input.html": [
+ "encrypted-media/clearkey-mp4-update-disallowed-input.https.html": [
"7396b7380f22845aaf66da67be5ce19a93a90259",
"testharness"
],
- "encrypted-media/clearkey-mp4-waiting-for-a-key.html": [
+ "encrypted-media/clearkey-mp4-waiting-for-a-key.https.html": [
"349ae6a759b23051e83c7dbbf96c4938d2482429",
"testharness"
],
- "encrypted-media/clearkey-not-callable-after-createsession.html": [
+ "encrypted-media/clearkey-not-callable-after-createsession.https.html": [
"2f0a96c7fa9927f95ff1634cb08457ef305d4e7f",
"testharness"
],
- "encrypted-media/clearkey-update-non-ascii-input.html": [
+ "encrypted-media/clearkey-update-non-ascii-input.https.html": [
"93e7cb2f9fa4e5d0696e3f9e02e88c2adf41fbd9",
"testharness"
],
@@ -527108,199 +533572,199 @@
"0fb6d575a357dd5fdc4544a55cb8ef4e25f0f449",
"support"
],
- "encrypted-media/drm-check-initdata-type.html": [
+ "encrypted-media/drm-check-initdata-type.https.html": [
"ae0f79ae94465890ded3e3a6bfd60f320b23ad44",
"testharness"
],
- "encrypted-media/drm-events-session-closed-event.html": [
+ "encrypted-media/drm-events-session-closed-event.https.html": [
"b5061558a5860289fd81ab806179fc3bdde06d22",
"testharness"
],
- "encrypted-media/drm-events.html": [
+ "encrypted-media/drm-events.https.html": [
"aca0d0624fc6cf16eac0c86723aa680c2fa8006c",
"testharness"
],
- "encrypted-media/drm-expiration.html": [
+ "encrypted-media/drm-expiration.https.html": [
"d071ca11388305cd8296f1183b1c5f3e3804c468",
"testharness"
],
- "encrypted-media/drm-generate-request-disallowed-input.html": [
+ "encrypted-media/drm-generate-request-disallowed-input.https.html": [
"4d5e1c39a7dec2ae4c2f8706d54696d456180ed4",
"testharness"
],
- "encrypted-media/drm-invalid-license.html": [
+ "encrypted-media/drm-invalid-license.https.html": [
"74afa97cd841401cd4b8ed18ea83499f410d17bf",
"testharness"
],
- "encrypted-media/drm-keystatuses-multiple-sessions.html": [
+ "encrypted-media/drm-keystatuses-multiple-sessions.https.html": [
"2ec2ce19b8f1f52ee33450f89cec546d4524403e",
"testharness"
],
- "encrypted-media/drm-keystatuses.html": [
+ "encrypted-media/drm-keystatuses.https.html": [
"777476ed7189626623fe6046e67a6d9359ce5783",
"testharness"
],
- "encrypted-media/drm-mp4-onencrypted.html": [
+ "encrypted-media/drm-mp4-onencrypted.https.html": [
"400ea20b213af0d1b5f415744ec3d48534fce7e7",
"testharness"
],
- "encrypted-media/drm-mp4-playback-destroy-persistent-license.html": [
+ "encrypted-media/drm-mp4-playback-destroy-persistent-license.https.html": [
"b1bd421f82ee615d7a994256363d7daf1990f74e",
"testharness"
],
- "encrypted-media/drm-mp4-playback-persistent-license-events.html": [
+ "encrypted-media/drm-mp4-playback-persistent-license-events.https.html": [
"5f2bf9c9cc1404be0f7c948c436a60483d662600",
"testharness"
],
- "encrypted-media/drm-mp4-playback-persistent-license.html": [
+ "encrypted-media/drm-mp4-playback-persistent-license.https.html": [
"421ab3065f65e9cd88ba318a50bbbf84beef4966",
"testharness"
],
- "encrypted-media/drm-mp4-playback-persistent-usage-record-events.html": [
+ "encrypted-media/drm-mp4-playback-persistent-usage-record-events.https.html": [
"508a4e777bd6c050028e76b8ebfb8da36e92f613",
"testharness"
],
- "encrypted-media/drm-mp4-playback-persistent-usage-record.html": [
+ "encrypted-media/drm-mp4-playback-persistent-usage-record.https.html": [
"bac4592aa70ea169e6424d571293dcbf10be9eda",
"testharness"
],
- "encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.html": [
+ "encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.https.html": [
"4be63a706c6af42c22a2d8eef94d227ca7af5cbb",
"testharness"
],
- "encrypted-media/drm-mp4-playback-retrieve-persistent-license.html": [
+ "encrypted-media/drm-mp4-playback-retrieve-persistent-license.https.html": [
"3c605d585e46f34b9cea3cda2caae72e93bb00ef",
"testharness"
],
- "encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.html": [
+ "encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.https.html": [
"8783b5efb95e95f5547acb29fb5950ebdde498e8",
"testharness"
],
- "encrypted-media/drm-mp4-playback-temporary-clear-encrypted.html": [
+ "encrypted-media/drm-mp4-playback-temporary-clear-encrypted.https.html": [
"b1825fbafaa400cd8672ca34d36e30ded98d2b9b",
"testharness"
],
- "encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.html": [
+ "encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.https.html": [
"db48c1ef4d91eaec6787c6c95e2dbb9faaf41965",
"testharness"
],
- "encrypted-media/drm-mp4-playback-temporary-encrypted-clear.html": [
+ "encrypted-media/drm-mp4-playback-temporary-encrypted-clear.https.html": [
"5f23926a2ed2692b3fee95ef613e02668b919106",
"testharness"
],
- "encrypted-media/drm-mp4-playback-temporary-events.html": [
+ "encrypted-media/drm-mp4-playback-temporary-events.https.html": [
"b893677d6c12f1b05f564dbbf1c43362da9ff6e7",
"testharness"
],
- "encrypted-media/drm-mp4-playback-temporary-expired.html": [
+ "encrypted-media/drm-mp4-playback-temporary-expired.https.html": [
"cb4a33c98fed06054e4acce8a65a0dc8e6d1b4c3",
"testharness"
],
- "encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.html": [
+ "encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.https.html": [
"320fb185d71e4f76cc865c63ff99f508d994465c",
"testharness"
],
- "encrypted-media/drm-mp4-playback-temporary-multikey-sequential.html": [
+ "encrypted-media/drm-mp4-playback-temporary-multikey-sequential.https.html": [
"e4616953865577bd08ba566f0487c5e7a793d291",
"testharness"
],
- "encrypted-media/drm-mp4-playback-temporary-multikey.html": [
+ "encrypted-media/drm-mp4-playback-temporary-multikey.https.html": [
"b7fd2a7ec0adc0b5be46242af0df83fab9dda5af",
"testharness"
],
- "encrypted-media/drm-mp4-playback-temporary-multisession.html": [
+ "encrypted-media/drm-mp4-playback-temporary-multisession.https.html": [
"15a0b2950e25edcbff1b5b2e3d5807cb91d9e531",
"testharness"
],
- "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.html": [
+ "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.https.html": [
"09ba82feb85a73a1aa275164bfacd722f893075e",
"testharness"
],
- "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.html": [
+ "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.https.html": [
"d6ba354d7c2c02775827fa1f896af5b4916a77fd",
"testharness"
],
- "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.html": [
+ "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.https.html": [
"eae1bd6fba6709856bf43e9506abf2128f79ced7",
"testharness"
],
- "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.html": [
+ "encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.https.html": [
"52facbc71172a79ab84416ae249780abfa48e970",
"testharness"
],
- "encrypted-media/drm-mp4-playback-temporary-two-videos.html": [
+ "encrypted-media/drm-mp4-playback-temporary-two-videos.https.html": [
"a8fb7e599f125c4ea3f665a9cc8be0b91a3df076",
"testharness"
],
- "encrypted-media/drm-mp4-playback-temporary-waitingforkey.html": [
+ "encrypted-media/drm-mp4-playback-temporary-waitingforkey.https.html": [
"82d4432235e45c61cca1fa371dcb83dfe99a3060",
"testharness"
],
- "encrypted-media/drm-mp4-playback-temporary.html": [
+ "encrypted-media/drm-mp4-playback-temporary.https.html": [
"14db930f09d86257aea6d653805b600da772726d",
"testharness"
],
- "encrypted-media/drm-mp4-requestmediakeysystemaccess.html": [
+ "encrypted-media/drm-mp4-requestmediakeysystemaccess.https.html": [
"2119ef0d22c25f8f3704732c6908ed2c5ac87e03",
"testharness"
],
- "encrypted-media/drm-mp4-reset-src-after-setmediakeys.html": [
+ "encrypted-media/drm-mp4-reset-src-after-setmediakeys.https.html": [
"f3c6f6c10c7dc7938a9c90309aecc7643de3603a",
"testharness"
],
- "encrypted-media/drm-mp4-setmediakeys-again-after-playback.html": [
+ "encrypted-media/drm-mp4-setmediakeys-again-after-playback.https.html": [
"d0799ef8ecf2198e97af8863828cf00455ccb643",
"testharness"
],
- "encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.html": [
+ "encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.https.html": [
"60cf1a74b1aa5eff4c817d78a6bf133588e9c9ec",
"testharness"
],
- "encrypted-media/drm-mp4-setmediakeys-at-same-time.html": [
+ "encrypted-media/drm-mp4-setmediakeys-at-same-time.https.html": [
"a475403fef02570be2815cc02572fc2afe7b6d55",
"testharness"
],
- "encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.html": [
+ "encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html": [
"0011bd6d2447f59d19844cb27c0248846dfc4a56",
"testharness"
],
- "encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html": [
+ "encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html": [
"6b60d7967a71112f476700d8ce3570b40cf51f08",
"testharness"
],
- "encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.html": [
+ "encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.https.html": [
"2681878f110de7841fba6123ceb785820b596474",
"testharness"
],
- "encrypted-media/drm-mp4-setmediakeys.html": [
+ "encrypted-media/drm-mp4-setmediakeys.https.html": [
"c66a641651351e92d47a6e149618117eeabfaff8",
"testharness"
],
- "encrypted-media/drm-mp4-syntax-mediakeys.html": [
+ "encrypted-media/drm-mp4-syntax-mediakeys.https.html": [
"ab9db64508f7181eef25898cfceacdc351c299ef",
"testharness"
],
- "encrypted-media/drm-mp4-syntax-mediakeysession.html": [
+ "encrypted-media/drm-mp4-syntax-mediakeysession.https.html": [
"51fcd7900ced0c4c50ef1b1fc8f50e69db021f55",
"testharness"
],
- "encrypted-media/drm-mp4-syntax-mediakeysystemaccess.html": [
+ "encrypted-media/drm-mp4-syntax-mediakeysystemaccess.https.html": [
"3718f25e30379509466117157f5ab7af705458a3",
"testharness"
],
- "encrypted-media/drm-mp4-unique-origin.html": [
+ "encrypted-media/drm-mp4-unique-origin.https.html": [
"f1a76980453dfce0c9e27774c2763295c2f8eb11",
"testharness"
],
- "encrypted-media/drm-mp4-waiting-for-a-key.html": [
+ "encrypted-media/drm-mp4-waiting-for-a-key.https.html": [
"52e710dd8e9f90e0a1a2a922bba042ea6e53a439",
"testharness"
],
- "encrypted-media/drm-not-callable-after-createsession.html": [
+ "encrypted-media/drm-not-callable-after-createsession.https.html": [
"82c70015b32240304ab410b4a57791bb3d8c45e5",
"testharness"
],
- "encrypted-media/drm-temporary-license-type.html": [
+ "encrypted-media/drm-temporary-license-type.https.html": [
"85124d35b37f14c143e1fcb2965f131a8f2a3391",
"testharness"
],
@@ -527308,8 +533772,8 @@
"d7627e2017ae8ac994a6bc8a2a00df0dd2332c59",
"testharness"
],
- "encrypted-media/idlharness.html": [
- "69456d56a5485b04465f4f6ee4abc80388703fd9",
+ "encrypted-media/idlharness.https.html": [
+ "eece848c772a39b29d6d8ece532e7807d737f50d",
"testharness"
],
"encrypted-media/polyfill/cast-polyfill.js": [
@@ -527341,27 +533805,27 @@
"support"
],
"encrypted-media/resources/clearkey-retrieve-destroy-persistent-license.html": [
- "a7638aacda006d42a622fc604d1b428443eb7722",
+ "ed8678213a798f04b01decf94014121986ec544a",
"support"
],
"encrypted-media/resources/clearkey-retrieve-persistent-license.html": [
- "20355904d2f71d222c4837da1331d643ab5d0098",
+ "04f30afdd5aa85dfa66e7b1424489276c7b3e8a8",
"support"
],
"encrypted-media/resources/drm-retrieve-destroy-persistent-license.html": [
- "0058c9807f20acbc5762c99b42e5406dddb88216",
+ "c628a38a59d96614b36ca396c8ce822c4bcb8a68",
"support"
],
"encrypted-media/resources/drm-retrieve-persistent-license.html": [
- "44dd2ebae1e0fb9997b9c4dc9ae6bf7cd24b87c7",
+ "21258d2eb390b5843e93563bd3a702d633c6585a",
"support"
],
"encrypted-media/resources/drm-retrieve-persistent-usage-record.html": [
- "f17de07ac51e592b88bddbfe87689a7699ec5a07",
+ "6bf8b93750744b323a584a767c2bebb68c74fb6b",
"support"
],
"encrypted-media/resources/retrieve-persistent-usage-record.html": [
- "855c3c92754d777c85167f15314de212b69daf4d",
+ "33818bb3302ccd50b2af5eafb2c5c05eb337a655",
"support"
],
"encrypted-media/scripts/check-initdata-type.js": [
@@ -527429,11 +533893,11 @@
"support"
],
"encrypted-media/scripts/playback-retrieve-persistent-license.js": [
- "bdd878f11a98e79058e2a7b0fab56f9b2006f5a8",
+ "a729fe90e843d8344db1e3c6c4a235d5bb9da59a",
"support"
],
"encrypted-media/scripts/playback-retrieve-persistent-usage-record.js": [
- "319a9a73255aca2b77a5f9f384ba5de5d7ebfbb3",
+ "bfe606669dc2c87c3813c119860f00317102a5bd",
"support"
],
"encrypted-media/scripts/playback-temporary-encrypted-clear-sources.js": [
@@ -527525,7 +533989,7 @@
"support"
],
"encrypted-media/scripts/unique-origin.js": [
- "781b4c4e6e48f3941e52856e3d5486b7b4a1a7a9",
+ "ddbdf009d11297918fe66e0b58498bd863be8333",
"support"
],
"encrypted-media/scripts/update-disallowed-input.js": [
@@ -527973,11 +534437,39 @@
"support"
],
"feature-policy/README.md": [
- "711c323f1690b0dbe780461241ad825cdd3cf274",
+ "67e317403163eb2f7b4d9599d21da97635fc14cf",
+ "support"
+ ],
+ "feature-policy/autoplay-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html": [
+ "4dc3b753b880e3c36b346fef5f605ca30a26081c",
+ "testharness"
+ ],
+ "feature-policy/autoplay-allowed-by-feature-policy-attribute.https.sub.html": [
+ "09531b990314460b4ee70b3535f27dafd654e5bc",
+ "testharness"
+ ],
+ "feature-policy/autoplay-allowed-by-feature-policy.https.sub.html": [
+ "a7c55fc4a17ba1e33a1758359c866345070ed8cd",
+ "testharness"
+ ],
+ "feature-policy/autoplay-allowed-by-feature-policy.https.sub.html.headers": [
+ "c563cecd38f12aaaf24c56d578e0cc9d7e7ad87f",
+ "support"
+ ],
+ "feature-policy/autoplay-default-feature-policy.https.sub.html": [
+ "946f76ab8d48394b33b9980b1411eee1fbf8e083",
+ "testharness"
+ ],
+ "feature-policy/autoplay-disabled-by-feature-policy.https.sub.html": [
+ "172558a2135fc066b69d91d4b340a3fc5e49d2c1",
+ "testharness"
+ ],
+ "feature-policy/autoplay-disabled-by-feature-policy.https.sub.html.headers": [
+ "4239ec4ef240e199f15a38145d478d2c0aa43ad2",
"support"
],
"feature-policy/payment-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html": [
- "8595732f7794f10107ef234fe6e37cc12c80eeaa",
+ "22d155755cd7aaff8a1c40c597468066f01eb13b",
"testharness"
],
"feature-policy/payment-allowed-by-feature-policy-attribute.https.sub.html": [
@@ -528004,6 +534496,18 @@
"09f612159dc367bad5febc8e0a724f0a284517d5",
"support"
],
+ "feature-policy/resources/autoplay.js": [
+ "6b1dd45e19dff4759b4d165cdfd59970e4212058",
+ "support"
+ ],
+ "feature-policy/resources/feature-policy-autoplay.html": [
+ "34eb416a1b8981460d2055108b255bec7f639f04",
+ "support"
+ ],
+ "feature-policy/resources/feature-policy-generic-sensor.html": [
+ "5d4a1f3eaf253211128f35990a94e1e0c91c1391",
+ "support"
+ ],
"feature-policy/resources/feature-policy-payment.html": [
"958b32f77b02f2ff80cf174aadac62237d79056b",
"support"
@@ -528209,7 +534713,7 @@
"testharness"
],
"fetch/api/cors/cors-expose-star.js": [
- "2403a7d229377d03230f32383e71960e32a84271",
+ "338dc1bf4cfe3b61209b5ffd362ecc3175890c1b",
"support"
],
"fetch/api/cors/cors-filtering-worker.html": [
@@ -528489,7 +534993,7 @@
"testharness"
],
"fetch/api/redirect/redirect-method.js": [
- "d663a3e4f32d0b48cf33d31a83c841ef55b52032",
+ "6e1d7ec853ecc7f15af9119cd1ff30027fd6beb2",
"support"
],
"fetch/api/redirect/redirect-mode-worker.html": [
@@ -528544,6 +535048,42 @@
"3099fb27913f11a983f955cb2a883a882911bfe4",
"support"
],
+ "fetch/api/request/destination/fetch-destination.https.html": [
+ "94437d1ca32c798817b73be9d726b171c68252b0",
+ "testharness"
+ ],
+ "fetch/api/request/destination/resources/dummy": [
+ "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+ "support"
+ ],
+ "fetch/api/request/destination/resources/dummy.png": [
+ "fa547a180b73a5422d52c1702c9d1e43b1083f9c",
+ "support"
+ ],
+ "fetch/api/request/destination/resources/dummy_audio.mp3": [
+ "b9171c72fedef62f2b3b0ade70b6d085ba94f7e5",
+ "support"
+ ],
+ "fetch/api/request/destination/resources/dummy_audio.oga": [
+ "167093849b93b142723513ac72a725c97da635a8",
+ "support"
+ ],
+ "fetch/api/request/destination/resources/dummy_video.mp4": [
+ "c9828d21efc0898635b693bf3e2f34041d7e8ddb",
+ "support"
+ ],
+ "fetch/api/request/destination/resources/dummy_video.ogv": [
+ "cb9a48e1d53911d5be214320adfbf7596632a316",
+ "support"
+ ],
+ "fetch/api/request/destination/resources/empty.https.html": [
+ "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+ "support"
+ ],
+ "fetch/api/request/destination/resources/fetch-destination-worker.js": [
+ "e10bc6423b2ee29387b1153546ae765449aa1ae4",
+ "support"
+ ],
"fetch/api/request/multi-globals/current/current.html": [
"2d9ab238e07a88d19365f78bfd5db84d32854de1",
"support"
@@ -528621,7 +535161,7 @@
"testharness"
],
"fetch/api/request/request-idl.html": [
- "b2f1431738bd7f389ab43cf8c10aed3b0d12abb8",
+ "679ff0c44a0ece1c480f5296e738b7a15f4c79cb",
"testharness"
],
"fetch/api/request/request-init-001.sub.html": [
@@ -528637,7 +535177,7 @@
"testharness"
],
"fetch/api/request/request-keepalive-quota.html": [
- "d839fec1d761688db807be2dfddf6b8b6932c46b",
+ "0b9786a3878a361ba8ec3291216d475bd5148541",
"testharness"
],
"fetch/api/request/request-keepalive.html": [
@@ -528741,7 +535281,7 @@
"support"
],
"fetch/api/resources/trickle.py": [
- "adb1bc80366cf924cfe13f6c73555d999d1d8e4f",
+ "87a83b390ae91e4419dc580d8426277be48c92d8",
"support"
],
"fetch/api/resources/utils.js": [
@@ -528789,7 +535329,7 @@
"testharness"
],
"fetch/api/response/response-idl.html": [
- "e0e32634b7e0271ff3566cb66b358e46c9fb8d21",
+ "d94cfadf60dc146f80f7c1dc9937d7841600f9ef",
"testharness"
],
"fetch/api/response/response-init-001.html": [
@@ -528897,7 +535437,7 @@
"testharness"
],
"fetch/nosniff/resources/css.py": [
- "0c3da6d761e72fe49ed883935d84cd4bc4db86bc",
+ "4ae9ff638587fcc96472709e31466a469061a3b0",
"support"
],
"fetch/nosniff/resources/image.py": [
@@ -528941,7 +535481,7 @@
"testharness"
],
"fetch/nosniff/stylesheet.html": [
- "707b1031fc7594d49b6f1487c8ef71864791ea80",
+ "2c5801cbf150010da8ef42a1f9e37b93540a8f04",
"testharness"
],
"fetch/nosniff/worker.html": [
@@ -529424,6 +535964,10 @@
"f6f0dbc8a505896a0e7ec7aca2746bbd5c1eb7d9",
"testharness"
],
+ "fullscreen/model/move-to-fullscreen-iframe-manual.html": [
+ "0fc5409f5e44177e1153fb61c25506c05114dc35",
+ "manual"
+ ],
"fullscreen/model/move-to-iframe-manual.html": [
"818cb1b5db729db4959591dc75d4bb1ae3c7542d",
"manual"
@@ -529460,6 +536004,10 @@
"0cdfe5cf8321b6c46a75a2f75f6224970368d4ae",
"support"
],
+ "fullscreen/rendering/ua-style-iframe-manual.html": [
+ "5264e24899d4cf72c54edd39d47715beebebe355",
+ "manual"
+ ],
"fullscreen/trusted-click.js": [
"e401e8e8bcd97446991398d6021a9bd712c923c5",
"support"
@@ -529496,8 +536044,12 @@
"99bcfb42c91e084a3b847ab4bab2bad80e548540",
"testharness"
],
+ "generic-sensor/generic-sensor-feature-policy-test.sub.js": [
+ "c7c9c4d1c578f267cbb4241d7ea7a981be6f49ee",
+ "support"
+ ],
"generic-sensor/generic-sensor-tests.js": [
- "09c6bf8a8fe005d467b522d5daf254c34c60b925",
+ "2209b4cc293aefecded2d325b664d494820d38af",
"support"
],
"generic-sensor/idlharness.https.html": [
@@ -529564,14 +536116,90 @@
"ca3036737a662e8673477b1a09b6fce89f0f98f4",
"testharness"
],
+ "geolocation-sensor/GeolocationSensor-disabled-by-feature-policy.https.html": [
+ "ae1bdcf06fbf8dc8189950593b83bdd749e37880",
+ "testharness"
+ ],
+ "geolocation-sensor/GeolocationSensor-disabled-by-feature-policy.https.html.headers": [
+ "0c75673594dd70e5f27fdc7f56a7ca1bb2d3f7ec",
+ "support"
+ ],
+ "geolocation-sensor/GeolocationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html": [
+ "6b0ea48ea2fb1cb6b81348bf5e28618716a34166",
+ "testharness"
+ ],
+ "geolocation-sensor/GeolocationSensor-enabled-by-feature-policy-attribute.https.html": [
+ "f1b108ddd2f5b1ea915410f4cdb28c2e1a812cf9",
+ "testharness"
+ ],
+ "geolocation-sensor/GeolocationSensor-enabled-by-feature-policy.https.html": [
+ "35fea3e77f992df2861bea97405e9c75f7a1f994",
+ "testharness"
+ ],
+ "geolocation-sensor/GeolocationSensor-enabled-by-feature-policy.https.html.headers": [
+ "6e06db043adf50307b8fa209a7008fdb7d290921",
+ "support"
+ ],
+ "geolocation-sensor/GeolocationSensor-enabled-on-self-origin-by-feature-policy.https.html": [
+ "a9da2c50d4bde9eb24ef343979afcbc6547684e2",
+ "testharness"
+ ],
+ "geolocation-sensor/GeolocationSensor-enabled-on-self-origin-by-feature-policy.https.html.headers": [
+ "1c523e7cd5741e4a515119b129b041b11cbc92cc",
+ "support"
+ ],
+ "geolocation-sensor/GeolocationSensor.https.html": [
+ "c9d32faca641ec784acf9096a079d73781330216",
+ "testharness"
+ ],
+ "geolocation-sensor/GeolocationSensor_insecure_context.html": [
+ "58fd65d3a72e6734392381fe225e3fbd7007fc06",
+ "testharness"
+ ],
+ "geolocation-sensor/GeolocationSensor_onerror-manual.https.html": [
+ "2b7aac7d60271e12ce71f6293405ffafb471c8c8",
+ "manual"
+ ],
"geolocation-sensor/OWNERS": [
- "8a972af50fbb0a8cc4688385174a28e5d7a29734",
+ "fabf35173a8bd10c7e5ffe348dd92532199ab51a",
"support"
],
"geolocation-sensor/idlharness.https.html": [
- "2f7f2b6879eab3add1ea962b02eb264ebb3f0154",
+ "ea9edf12752af0a97cd9fe825ae927bd07090a56",
+ "testharness"
+ ],
+ "gyroscope/Gyroscope-disabled-by-feature-policy.https.html": [
+ "03457271ec8c254bf74f89afa7532a595b837404",
"testharness"
],
+ "gyroscope/Gyroscope-disabled-by-feature-policy.https.html.headers": [
+ "b4767ccc5e319ec08705af56990c8d8093640ff0",
+ "support"
+ ],
+ "gyroscope/Gyroscope-enabled-by-feature-policy-attribute-redirect-on-load.https.html": [
+ "68df44bc71f1aaba74188f70dc916e9ee1dcc330",
+ "testharness"
+ ],
+ "gyroscope/Gyroscope-enabled-by-feature-policy-attribute.https.html": [
+ "e7c53323038c11a977e547ebe9d7ae94646f1a06",
+ "testharness"
+ ],
+ "gyroscope/Gyroscope-enabled-by-feature-policy.https.html": [
+ "e4e170946a0289e8b1b6be83083aeeb92ddc4a8f",
+ "testharness"
+ ],
+ "gyroscope/Gyroscope-enabled-by-feature-policy.https.html.headers": [
+ "b0ce79c08e8b5908485a8bb4c6d86e8d20b2a44c",
+ "support"
+ ],
+ "gyroscope/Gyroscope-enabled-on-self-origin-by-feature-policy.https.html": [
+ "f48401e0e04294624ebb864224a6d2126e849870",
+ "testharness"
+ ],
+ "gyroscope/Gyroscope-enabled-on-self-origin-by-feature-policy.https.html.headers": [
+ "59acbd3ef447d2197c4a9af2837dbacdf1e31885",
+ "support"
+ ],
"gyroscope/Gyroscope.https.html": [
"504abfa42529e08576e49c3296464bcea5fe0b8a",
"testharness"
@@ -529601,13 +536229,17 @@
"testharness"
],
"hr-time/idlharness.html": [
- "337a75247a6b53a7649c7fdf41c2dcdcf093ac11",
+ "f2cdcba041df089206cc9c811167c41a771905df",
"testharness"
],
"hr-time/monotonic-clock.any.js": [
"4aef47650d5cbc750393c3ac9423dbff24a15917",
"testharness"
],
+ "hr-time/performance-tojson.html": [
+ "2d45889944dab7b0489a03a649a70e1177bca428",
+ "testharness"
+ ],
"hr-time/resources/now_frame.html": [
"031edb78f5ab21f51005fdb30a99a605669254ce",
"support"
@@ -529921,7 +536553,7 @@
"testharness"
],
"html/browsers/browsing-the-web/history-traversal/PopStateEvent.html": [
- "5a9c575a86adbbbca30734992b4d80c22f3973a1",
+ "f150a04f6eaed460e3f979c879683ef4ff44e02c",
"testharness"
],
"html/browsers/browsing-the-web/history-traversal/browsing_context_name-0.html": [
@@ -529973,7 +536605,7 @@
"testharness"
],
"html/browsers/browsing-the-web/history-traversal/hashchange_event.html": [
- "c337192292ab48083ede981bcfad4a15c5eb7478",
+ "4471d424840818a9e3bc5507680a20a6707530b9",
"testharness"
],
"html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resources/blank1.html": [
@@ -530001,7 +536633,7 @@
"testharness"
],
"html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html": [
- "0f8425ba4fcdd12e357ec975c6439c89c72c1c3e",
+ "a94f2df91002c5cf36e6a4607c2f95e3ba130c30",
"testharness"
],
"html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-samedoc.html": [
@@ -530329,7 +536961,7 @@
"testharness"
],
"html/browsers/browsing-the-web/read-media/pageload-video.html": [
- "2d8749e1d5f585ba60ce0a20367d116d126df475",
+ "2ae6e21db438a657afd934bb8fb8a21de5f5f2cf",
"testharness"
],
"html/browsers/browsing-the-web/read-multipart-x-mixed-replace/.gitkeep": [
@@ -531381,7 +538013,7 @@
"support"
],
"html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload.tentative.html": [
- "63421792e4f1f654149d48775b1f2574398bba1a",
+ "fbb1c40a56f513dd66084f780eb650664188ec4f",
"testharness"
],
"html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload_form-submission-1.tentative.html": [
@@ -531389,7 +538021,7 @@
"support"
],
"html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload_form-submission-2.tentative.html": [
- "e45de51132ab221732295759e9f704466fd22557",
+ "35a8b04947b420a51e31fbc74ab0d6cd058a443a",
"support"
],
"html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload_form-submission-dynamic-iframe.tentative.html": [
@@ -531704,6 +538336,10 @@
"ba143e41121916fba5522d5e1dca29d04ab5f4ce",
"support"
],
+ "html/browsers/sandboxing/noscript-iframe.html": [
+ "cfa4043bfda350a0906cd94f3c9c9a3578e72575",
+ "support"
+ ],
"html/browsers/sandboxing/sandbox-allow-same-origin.html": [
"3aa5996022d6ca80f085981190811efc490aa2e0",
"testharness"
@@ -531720,6 +538356,14 @@
"bbb480a9ca5139877fbab165f9356b2a67305a9c",
"testharness"
],
+ "html/browsers/sandboxing/sandbox-parse-noscript-ref.html": [
+ "4f185501effadf33e7d90e4c3990ec06ee936b43",
+ "support"
+ ],
+ "html/browsers/sandboxing/sandbox-parse-noscript.html": [
+ "b6345b32377ff05bc7e5261b2fc14e8c875b2245",
+ "reftest"
+ ],
"html/browsers/the-window-object/.gitkeep": [
"da39a3ee5e6b4b0d3255bfef95601890afd80709",
"support"
@@ -532305,7 +538949,7 @@
"testharness"
],
"html/browsers/windows/browsing-context.html": [
- "ad718fb943e000ad5d2f376ea5ac8a011661ab37",
+ "8fe21ad8cdacd39594f6d01880689d1c94c617b2",
"testharness"
],
"html/browsers/windows/groupings-of-browsing-contexts/.gitkeep": [
@@ -533209,11 +539853,11 @@
"testharness"
],
"html/dom/elements-embedded.js": [
- "2c20b7d2856d8f7f72b7835b2677ed47abc43629",
+ "99489e3a8ac2be0d7dcfb22f7f45c30b00511358",
"support"
],
"html/dom/elements-forms.js": [
- "ed722f36a003a8407c1c4a13f8c75880c4fa9c11",
+ "062e50a0665b90c3b77aaca744b65036054569f5",
"support"
],
"html/dom/elements-grouping.js": [
@@ -533221,11 +539865,11 @@
"support"
],
"html/dom/elements-metadata.js": [
- "f7d5c16c0e69c67a1b49b7a4ed28c14e4f3cf469",
+ "4fac3184d50253baecd987ded8b1bb86d82967d9",
"support"
],
"html/dom/elements-misc.js": [
- "42b4ea21148dd17c442932ba8cb5e6e49db81a93",
+ "700331e76eb4de08018ef2939c750567e6a1ead5",
"support"
],
"html/dom/elements-obsolete.js": [
@@ -534101,7 +540745,7 @@
"testharness"
],
"html/dom/reflection.js": [
- "4d841fe21eb604a563fc4d864e7db13c43de4621",
+ "b26e0872e1b4d6e8aba7d18e2740eb6c5ecf311c",
"support"
],
"html/dom/resources/self-origin-subframe.html": [
@@ -534116,6 +540760,10 @@
"482b716c4e76fd71e99720e3b82658a5db010a5a",
"testharness"
],
+ "html/dom/usvstring-reflection.html": [
+ "f12c4ee1c2b07b2cc559b672436450c349ef8498",
+ "testharness"
+ ],
"html/editing/.gitkeep": [
"da39a3ee5e6b4b0d3255bfef95601890afd80709",
"support"
@@ -538200,6 +544848,26 @@
"175e662819cfcc1f528fd8c0e3ed149eeba02e70",
"reftest"
],
+ "html/form-elements/the-textarea-element/multiline-placeholder-cr.html": [
+ "e8f7683568ad37b625fb32d97e80f4e15a9b6f66",
+ "reftest"
+ ],
+ "html/form-elements/the-textarea-element/multiline-placeholder-crlf.html": [
+ "e0fbe39e2376e17611ec89f6f9a1b79b912cfe1a",
+ "reftest"
+ ],
+ "html/form-elements/the-textarea-element/multiline-placeholder-ref.html": [
+ "69fe9939aea706500232485a2e105ae67fca6783",
+ "support"
+ ],
+ "html/form-elements/the-textarea-element/multiline-placeholder.html": [
+ "3372eef00fd32ced307dbfa63f4b5c9cc6363f94",
+ "reftest"
+ ],
+ "html/form-elements/the-textarea-element/support/placeholder.css": [
+ "3b200a40e2b7ba13f060772e821328db1de82cd0",
+ "support"
+ ],
"html/iana/.gitkeep": [
"da39a3ee5e6b4b0d3255bfef95601890afd80709",
"support"
@@ -538728,6 +545396,22 @@
"da39a3ee5e6b4b0d3255bfef95601890afd80709",
"support"
],
+ "html/input/the-placeholder-attribute/multiline-cr.html": [
+ "687054d9b221998ff4c4071ccc0733faeeb129b7",
+ "reftest"
+ ],
+ "html/input/the-placeholder-attribute/multiline-crlf.html": [
+ "f953c175dce74670a915534fb513feb960fb5152",
+ "reftest"
+ ],
+ "html/input/the-placeholder-attribute/multiline-ref.html": [
+ "e497f7bbe3359c11265619a439dc97756131e827",
+ "support"
+ ],
+ "html/input/the-placeholder-attribute/multiline.html": [
+ "bc7c64db1dfdb3084a7c3606005a41fd71a20a9b",
+ "reftest"
+ ],
"html/introduction/.gitkeep": [
"da39a3ee5e6b4b0d3255bfef95601890afd80709",
"support"
@@ -540348,6 +547032,10 @@
"03c507419d6aca82952aeaf21bb6ab732cb379ff",
"testharness"
],
+ "html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/crossOrigin.html": [
+ "17313a24fb209ad5a79910f92fb295357b07eed3",
+ "testharness"
+ ],
"html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/textTracks.html": [
"88948beef7ec893585ada062daeafad4554afa92",
"testharness"
@@ -540365,7 +547053,7 @@
"testharness"
],
"html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/readyState.html": [
- "4ec33f119348303282ffe7c7e2b5538b2b63db87",
+ "1b18c4e70f84197083ab79c2868ec750d4d72168",
"testharness"
],
"html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/src.html": [
@@ -540420,6 +547108,10 @@
"d539c5792d2c2816b5953d6aa76c78a33f2eb89c",
"testharness"
],
+ "html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/constructor.html": [
+ "21807b992193648f9d9ae3619b437521f9ea5bfc",
+ "testharness"
+ ],
"html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/endTime.html": [
"e713191a3603ca8ecfabe1afeb69ee0dd0dd2959",
"testharness"
@@ -540976,6 +547668,246 @@
"ac9c4dbaad4c8740e384629696ac4ae16a560b00",
"support"
],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/align-positioning-bad.vtt": [
+ "b2662fae4fd302fa2e5ad7ff8a6431ac93ae6629",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/align-positioning.vtt": [
+ "8128961a5a57e9eff6d09fdb7a89dab39141d301",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/align-text-line-position-bad.vtt": [
+ "5c5d32740e44043d7f8f2a384223840fe132c6f9",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/align-text-line-position.vtt": [
+ "3a3d06cf92020726080c5980eb23007c5033e137",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/alignment-bad.vtt": [
+ "8e595d046661094c5bee5b62ee2d4ccce9c3db37",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/alignment-ltr.vtt": [
+ "28a410f7cee1329cfa19acb71a4a86a393b54234",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/alignment.vtt": [
+ "18c8baeed94a38eb9310db3bbfbf8cff5d59cd14",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/bom.vtt": [
+ "2278f4ae0dd2697d522e725241e1a1357017bb6d",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/captions-fast.vtt": [
+ "68ae570e941a5b8993c163a84aca0f758d65ab01",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/captions-gaps.vtt": [
+ "fa81809c654054d8f9d4e942782e7a4bc2826ed9",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/captions-html.vtt": [
+ "fd0df8d0f2800bd9097fe7a293a12c47ed1ad3bd",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/captions.vtt": [
+ "14d8e68a891fa652c44711158c1f4fe652c841b1",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/class-bad.vtt": [
+ "48b56cffac57d58ed363c6de43123cf46b9a61c4",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/class.vtt": [
+ "e3ebad0f6068acc7fd11a5969c1753c4ef86c1b9",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cue-id-error.vtt": [
+ "e1e8e96b61a5ef48aec96a6c605929f39300e9d9",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cue-id.vtt": [
+ "f67139c3fea2a888cd10500ee4ac1d3882d5df01",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cue-no-id-error.vtt": [
+ "4353f327dbfcfec5bcf99aaad28fde328b0c34a8",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cue-no-id.vtt": [
+ "6954c71972bfbdab36c94c44190cc2259971adb0",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-cuetext.vtt": [
+ "befc0d2b1bfb79cd79c2b09af9d35f1db02e59ff",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-header.vtt": [
+ "8ba9c1290b73e11a46b983c10848d14c82a70062",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-note.vtt": [
+ "842da18a789e67bd1dd78c3389581552e0e23c68",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-align-bad.vtt": [
+ "a1bf60ed37f7bce2e3a5bec919664633780e60ed",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-align.vtt": [
+ "0da4144c1b7ac7c363a5ff3c27708480fe6c560c",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-bad.vtt": [
+ "c665e6044bdcc16956fabb78720a2c59028d9e2a",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size.vtt": [
+ "fee519ec5f5afc13be7c7f5a4387e746135c3747",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cues-no-separation.vtt": [
+ "251de0c5026da00c2b18469ee99924cf70ad1b4e",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cues-overlapping.vtt": [
+ "8966b84320ad89eb883946392dd2a6bc3d12711d",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/cues.vtt": [
+ "4fc146831b7c10f721b77a4bdec99953aa40454b",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/default-styles.vtt": [
+ "db041f1a659ab39530144bb68e0ab76d14ca9b90",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/degenerate-cues.vtt": [
+ "01c28a312767c6ca41751a58b227dc80bbff54dc",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/empty-cue.vtt": [
+ "65fdbcdc5a88cc9208cfd5b0bf2e1396b23432a7",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/entities-wrong.vtt": [
+ "9941f3c18ac34d852ab7f882c06d10a874453c14",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/entities.vtt": [
+ "5913b038e7d6341b19c21d0bb81008057656d929",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/interspersed-non-cue.vtt": [
+ "bfe46bfea8af95d5dc54324ac9e202eb9e5e0b2b",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/iso2022jp3.vtt": [
+ "e929f8e1755f72ecae96dd40430bc07c5a4a433c",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/large-timestamp.vtt": [
+ "0b8a4e4d4d5fdbf5a873e5ecc134469393bf3b7c",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/line-position-bad.vtt": [
+ "d75633c173c91a1f8a6a0fe1d173165ae92905f1",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/line-position.vtt": [
+ "eb83dd089934f5e72039eebd57ed17f775408377",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/markup-bad.vtt": [
+ "7caf06d65f3e6c9ba305b4a2b162efbeb68b7a86",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/markup.vtt": [
+ "25514f3b659150b7536890cf5bbaff19c57437fe",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/metadata-area.vtt": [
+ "778ac955bd2e01b8c6c8fdf540c99f4513390f5e",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/metadata.vtt": [
+ "ea18a5275465fd2eaf68f066f085551c3035ccaa",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/missed-cues.vtt": [
+ "28c9acd7f24cc07d15c0685bdef1d435ffbbc89a",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/no-newline-at-eof.vtt": [
+ "9cc9424c093198fedb44a2361f704ce299288f71",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/no-timings.vtt": [
+ "63bb8c56d7e75cc84b4e6b06b476fb4d9b395316",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/no-webvtt.vtt": [
+ "9d5d51eddc30891a0b25a628fffad6bc19d720de",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/positioning-bad.vtt": [
+ "59571852499c3cf14cddc874d1344754e3bb007f",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/positioning-ltr.vtt": [
+ "9fe212e89eb20c152574de81823b7fdf01900b2d",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/positioning.vtt": [
+ "91f3c4375e6fe9f4968e9059ecec21c4743cf483",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/settings-bad-separation.vtt": [
+ "0733d08db0cf06caac571b388a811899f79252d4",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/settings.vtt": [
+ "af042c5468830fbdcd9b9c7cbc32eb0c6d660311",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/simple-captions.vtt": [
+ "fa3e12c456c77d1327b90b1a8f32416245268e7a",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/sorted-dispatch.vtt": [
+ "6555a536c404112c6057458edfad26d398f95d19",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/timestamp-bad.vtt": [
+ "6852fb1bfcddce00b4acba93716d7358957a74e5",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/timestamp.vtt": [
+ "ed03dac0cac2e0b79c8b98e1e460b24fb7b2daeb",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/timings-hour-error.vtt": [
+ "e2cf1290a06473ac1592e8da4d8261d392f14606",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/timings-hour.vtt": [
+ "a846d7e878ab08d111e4d68dd67b02d210db0273",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/timings-no-hour-errors.vtt": [
+ "4c80839a264bc93e3787211790e6062f35ad1f22",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/timings-no-hour.vtt": [
+ "09948fb59cd9e1702ba869f0b444ca36d1ec0bf2",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/timings-whitespace.vtt": [
+ "2d9b2479193680a334da8001254f17105b7a13aa",
+ "support"
+ ],
"html/semantics/embedded-content/media-elements/track/track-element/resources/track.de.vtt": [
"f83f36449d6a7e9db28bba9e39dc7a4bf7458927",
"support"
@@ -540992,22 +547924,310 @@
"329c3f585e5e89dfc1f44fde85a1d9601e61aef2",
"support"
],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/unsupported-markup.vtt": [
+ "e6f5fddd1ff13f6e9f81931af691a0ad1c9a55a9",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/utf8.vtt": [
+ "b15aef44ae1726c362448bc561899c7dc554a767",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/valign-bad.vtt": [
+ "3517a6189833600e6db45a8c7fed79d38859b1c1",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/valign-ltr.vtt": [
+ "2c1f48f5098da305b6fe6c362a94c4a2a5e13c38",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/valign.vtt": [
+ "357f4306f5b5c83b712d0a0bbb098827c3802196",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/voice-bad.vtt": [
+ "f80e328090068ef96781468e107de3afe947d840",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/voice.vtt": [
+ "61997c207efb09802c9022fcea544f4196094df6",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/vp8-vorbis-webvtt.webm": [
+ "aae8ea4cf4b4fa88b0e88094f2e64c63df4bceb9",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/webvtt-file.vtt": [
+ "943c4ca7d7ba197815ad5732222558e30195b022",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/resources/webvtt-rubbish.vtt": [
+ "e0522c50ed645cbc7d483d5c410ae5d925ef4b47",
+ "support"
+ ],
"html/semantics/embedded-content/media-elements/track/track-element/src-clear-cues.html": [
"9e5b2fa642544c20e04d542d9a8f701d1fa2d165",
"testharness"
],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-active-cues.html": [
+ "ee900652dced5cb21fde825760c7ee3450ffba00",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-add-remove-cue.html": [
+ "74ce8542b9041d77633c59484916186ced0f065f",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-add-track.html": [
+ "ba19b96decf95cb69fe8da86ace3b6c757edc269",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-addtrack-kind.html": [
+ "a760d3d1b73313db91a6551bdf0061cf0729186d",
+ "testharness"
+ ],
"html/semantics/embedded-content/media-elements/track/track-element/track-api-texttracks.html": [
"f7576ff332cac04a4e2b663b6fdd40aef154b6b5",
"testharness"
],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-cue-empty.html": [
+ "8836253fa3f97ff0b8b4c7af2078f667d2bd0738",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-cue-inline.html": [
+ "1af5ab84eeec88145bccec3adc829c41a27aa647",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable-fragment.html": [
+ "08de3e2e541f95a91f984d90d4a078d45cb057c4",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable.html": [
+ "c8ab03c7d84d150befa8152e552d99e889ce4ec0",
+ "testharness"
+ ],
"html/semantics/embedded-content/media-elements/track/track-element/track-cue-order.html": [
"eeab6b02e728aea21878cf72664929766be057b7",
"testharness"
],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-cues-missed.html": [
+ "a87ad9da0dad43e1b68183feeabce59a5c864087",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-cues-pause-on-exit.html": [
+ "ec7abb777a4ae9276bd047e66c3c3560e881ed38",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-cues-seeking.html": [
+ "8efe764fcdcfa0568b7566e1855f115282dc9800",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-cues-sorted-before-dispatch.html": [
+ "314f2768b879dfd1496992d7cb13c724331cf609",
+ "testharness"
+ ],
"html/semantics/embedded-content/media-elements/track/track-element/track-data-url.html": [
"e9c8849350512b1247543939ee0e529947e47c2d",
"testharness"
],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-disabled-addcue.html": [
+ "50932e2a3ce52440fa5e3af935f11120267bc4dd",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-disabled.html": [
+ "7e62481158e3d571c7180b5c80376336ff77615a",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-element-dom-change.html": [
+ "04ade2498b9ea6d3f576e47867a5ac6c91c3e424",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change-error.html": [
+ "f8b49876351834df6f98b73d79039ec45a9940d1",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change.html": [
+ "b6d8d45a74cb90c0a4a63ca169867982ac235b15",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-helpers.js": [
+ "b84cd1d9f96ee9b00cef2bd219e6da5b1ba1df8b",
+ "support"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-large-timestamp.html": [
+ "fd1683cc93142f971a2b0c37321adf2e9911a4b8",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-load-error-readyState.html": [
+ "6736b48cb3b591479c9589e50261290541177c51",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-load-from-element-readyState.html": [
+ "82ae61caf89327293f566acc794f9c193aec122f",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-load-from-src-readyState.html": [
+ "a4a3afae537fca943d343add9780ae3eb1f160bc",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-mode-disabled.html": [
+ "e79126149eb97f0975a32fdaec6225d4c6c74957",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-mode-not-changed-by-new-track.html": [
+ "2a494b59e2ec82dc881b913aaae4e773f47afb22",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-mode-triggers-loading.html": [
+ "82b09068a101ec059a383a6b656eb85788e90fa3",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-mode.html": [
+ "0fd7a0385671be222873aac3b1ebd4f21f4000ae",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-remove-active-cue.html": [
+ "dd3ab2e0e4f4ac3b4f83e5dfd539dd9c3aa5c961",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-remove-by-setting-innerHTML.html": [
+ "9ab3f009fe7464e26df571ec8e66dde7205fa0db",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-remove-insert-ready-state.html": [
+ "9d6735eaf36145ceeefec0630f30be49ff37d676",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-remove-quickly.html": [
+ "e955322b149ecb74471bc972a4662972fa287516",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-remove-track.html": [
+ "931cfc4d06107dfccb001fbeaeef987cca528747",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-align-positioning.html": [
+ "9283a8233cfc10c0c1745815b3f6bd970ffdde2a",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-align-text-line-position.html": [
+ "5985538ecba666dd2bcf1287e60f267c83d64a6e",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-alignment.html": [
+ "fa581025c7ca552f23441869eb76bffcf1cd7f7a",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-blank-lines.html": [
+ "2266bc2a923ceb56a90abd034087efe24a958c3b",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-bom.html": [
+ "26343f09d663d1558881507f89eecc606304b41f",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-class-markup.html": [
+ "8876395c46181acafb7712b1fcdff7cae28c0b18",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-identifiers.html": [
+ "d21e8cd62cc5a7bf9275b2f46282cd3f73714c21",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-no-id.html": [
+ "f12b9b7384f445b817f1d049d7bff05ec0f2d3d9",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-recovery.html": [
+ "ba273b161cbdd6cfeec6be75f08bb510a13bf9e1",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-size-align.html": [
+ "519039bd4e00da6802f03f9a9695b96019ef6df0",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-size.html": [
+ "5f91fd3c078343aee9ee72c1b60bf8a8f82682e2",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-degenerate-cues.html": [
+ "bcc7f1b103a7d0896ba19a84de6b41f4758a8837",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-empty-cue.html": [
+ "d8b948ecac4da42f43896cda9902718130a5a0e6",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-entities.html": [
+ "b995f43c4dfef791a95bc0dfcd30721e955fce85",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-header-comment.html": [
+ "3e83c514cb2d18b2238f03e3d85a21f69a60d5c0",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-interspersed-non-cue.html": [
+ "ee7e65642ed06f89c2413278fad652dcfb78d740",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-line-position.html": [
+ "410feb59cf264571fb347bbfcb1f14150bbaea8f",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-magic-header.html": [
+ "ef8442f73c4aae5728a8790d6a7dbc075bb09a25",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-markup.html": [
+ "6d8f7b9e8e3cb87581844b5dd61e46cc508b616c",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-newlines.html": [
+ "24d79495469c698e1e0296b503e44a3ee6b5db34",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-no-timings.html": [
+ "baa44683fe0d00e691f536309a7772347301d57a",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-positioning.html": [
+ "852584f301e1ab52359e3344120149d65a35d5f7",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-settings.html": [
+ "25f3286199d565d58b3e4545a5f3cbb212541a34",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timestamp.html": [
+ "d18cd2431e189249d1210ba5ef87c081f3d355ee",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-hour.html": [
+ "b52de7d267cce4c480353c188173c6bbc5e3e70e",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-no-hours.html": [
+ "ebae3e9d5dc11b91b53439ee4871df86c3a80822",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-whitespace.html": [
+ "c42b3e45318e167bf00edf77528d56e2d107d5e8",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-unsupported-markup.html": [
+ "c43ab0c10e1de3af01f6137c044c73cfcbc6d339",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-utf8.html": [
+ "65241920becf512c35f78b335de90c00af03195d",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-valign.html": [
+ "4f6e049d97dc81065df13e66e40cf945ff0914dd",
+ "testharness"
+ ],
+ "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-voice.html": [
+ "c016678eb1f14aad834d4e6e3bbca1818760284a",
+ "testharness"
+ ],
"html/semantics/embedded-content/media-elements/user-interface/muted.html": [
"74deefbbc4b8f96ff4856db1c32c6428183cc040",
"testharness"
@@ -541069,7 +548289,7 @@
"testharness"
],
"html/semantics/embedded-content/the-area-element/area-download-click.html": [
- "b3172223ac173b65870f5d061cc8600a67956e10",
+ "693a6830b022c9b57a6bc06259f2312d049a22e7",
"testharness"
],
"html/semantics/embedded-content/the-area-element/area-processing.html": [
@@ -541084,6 +548304,10 @@
"25afa430800ce1439fddd06920a64353c8559764",
"testharness"
],
+ "html/semantics/embedded-content/the-area-element/resources/area-download-click.html": [
+ "4dee38d117f36f1e22648fa74f02fe87488aa31b",
+ "support"
+ ],
"html/semantics/embedded-content/the-area-element/support/hit-test.js": [
"d6128e676d8584222248b03ae2e868136377d799",
"support"
@@ -542881,7 +550105,7 @@
"testharness"
],
"html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html": [
- "a3f85905acb42372806d07259e09d75e2fd8db1f",
+ "4ca73ff5658b3512784e9e1b236c78861ca4ecc9",
"testharness"
],
"html/semantics/forms/the-button-element/.gitkeep": [
@@ -543413,7 +550637,7 @@
"testharness"
],
"html/semantics/forms/the-progress-element/progress.html": [
- "ae4f3f8d86b720ba8f6c1fe7443cc425519de5da",
+ "786e7998c0a1e10ba76b26a87d45ea9c3c9893b4",
"testharness"
],
"html/semantics/forms/the-progress-element/progress.window.js": [
@@ -543436,6 +550660,10 @@
"b5a01e973e4d4c97c6fa06bd9fd1e535e8c622e8",
"testharness"
],
+ "html/semantics/forms/the-select-element/select-add.html": [
+ "1ce71758263439d50dbabb5f1e78fafa6c7ba35b",
+ "testharness"
+ ],
"html/semantics/forms/the-select-element/select-ask-for-reset.html": [
"e9689464e9ffa86ac5cd9364a4e8fb9ed6af065e",
"testharness"
@@ -543465,7 +550693,7 @@
"testharness"
],
"html/semantics/forms/the-select-element/selected-index.html": [
- "0753a7487a10bde3b879d4c2ed10ba3d0260a48a",
+ "3dbf338e9065f7f4ad2abfbaa55cf50329768cc2",
"testharness"
],
"html/semantics/forms/the-textarea-element/.gitkeep": [
@@ -543836,6 +551064,10 @@
"8fe77deb43d14d0a6b306dc903d56dcda1e80d50",
"testharness"
],
+ "html/semantics/interactive-elements/the-dialog-element/abspos-dialog-layout.html": [
+ "898d5888cea62972b9810606595949cac792ce0d",
+ "testharness"
+ ],
"html/semantics/interactive-elements/the-dialog-element/centering-iframe.sub.html": [
"eb00778210365e13b33e194da1b9e870d7e39153",
"support"
@@ -543872,10 +551104,22 @@
"1b77c8ff31c1a38afb3a9fa9bf77bf85ac4a264b",
"testharness"
],
+ "html/semantics/interactive-elements/the-dialog-element/dialog-scrolled-viewport.html": [
+ "529cf6c2cf2daf031f7d41aef93e6f5645e30ec2",
+ "testharness"
+ ],
"html/semantics/interactive-elements/the-dialog-element/dialog-showModal.html": [
"c00ac5b6d038b45b1a7cfbef94a4527757fa74e6",
"testharness"
],
+ "html/semantics/interactive-elements/the-dialog-element/inert-does-not-match-disabled-selector.html": [
+ "f0187a4040dbbd430b6945947475c152f1eeed7b",
+ "testharness"
+ ],
+ "html/semantics/interactive-elements/the-dialog-element/inert-node-is-unfocusable.html": [
+ "93879f898f01060ffd6c6d67543f4cc5b7de6ac0",
+ "testharness"
+ ],
"html/semantics/interactive-elements/the-dialog-element/resources/common.js": [
"15580f3e0243093710d4914224ca3963992e3f5b",
"support"
@@ -544056,6 +551300,10 @@
"1fe7fe27c3680b24fbbb9c09c849ecb007637d3f",
"testharness"
],
+ "html/semantics/scripting-1/the-script-element/defer.js": [
+ "a3a0ec93c287c9925d8da6303ae99af3953f81b8",
+ "support"
+ ],
"html/semantics/scripting-1/the-script-element/execution-timing/001.html": [
"d23ee4e0c5c00c5d7d4391ebb346536706667759",
"testharness"
@@ -544800,6 +552048,42 @@
"364c6d3b48ef8143d62d6f6bb02aa5554b0bd367",
"testharness"
],
+ "html/semantics/scripting-1/the-script-element/module/choice-of-error-1.html": [
+ "b7c603ed3b3acdcb45f4274f5c7a85d13f251994",
+ "testharness"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/choice-of-error-1a.js": [
+ "addc3cbacaa9a439d8cd082677ce3df8a3e1e861",
+ "support"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/choice-of-error-1b.js": [
+ "cf2e69b160a03622816b7e9ed8b3396a10cd3756",
+ "support"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/choice-of-error-2.html": [
+ "9e4650e461e3436316233e769a0cde49179e46fe",
+ "testharness"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/choice-of-error-2a.js": [
+ "849aec6ec6b5a556c991c95e8715b9112022d5fd",
+ "support"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/choice-of-error-2b.js": [
+ "6e5ed4042eeb4bc49c9c6f339cec73acbd5eda44",
+ "support"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/choice-of-error-3.html": [
+ "65dc20f79e348097cec23b814d2b2f918214647b",
+ "testharness"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/choice-of-error-3a.js": [
+ "5a6fa0aa0d9836150cd0c49c6c52c66844974033",
+ "support"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/choice-of-error-3b.js": [
+ "55f3f75425cd6277852f89148285a618fba542f6",
+ "support"
+ ],
"html/semantics/scripting-1/the-script-element/module/compilation-error-1.html": [
"e36eda2e9941e0cfefbfd867d36da6de4dfe7b2e",
"testharness"
@@ -544889,7 +552173,7 @@
"testharness"
],
"html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-script-error.html": [
- "24f8c20c79cdaa6d81e9447e4f616ec5626d36ca",
+ "9d59895901b04cbef1b7263da1b974336bfa524f",
"testharness"
],
"html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports.html": [
@@ -544920,26 +552204,94 @@
"997859fce8ed8854053d089a78ab999b3f88a072",
"testharness"
],
- "html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-classic.html": [
- "c5e3bf053403a49ee72c7464b1c1d0758f0fc8be",
+ "html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/Function.js": [
+ "be1ecd94299f35bb000eb5e9df53e9c057231982",
+ "support"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/eval.js": [
+ "686728d887fbb65f9b5c7498edf1a1dfc6611ebd",
+ "support"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/inline-event-handlers-UA-code.js": [
+ "b2f41c32fc88183500ab3069a51894d62873dd7b",
+ "support"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/reflected-inline-event-handlers.js": [
+ "15125c9e98e59d191acee4dcadece1b2986d7ec1",
+ "support"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/setTimeout.js": [
+ "03ee5763c6e62da7d49e058edb58292f4f496a3f",
+ "support"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-classic.html": [
+ "70f97beb38cf958bd2234e3b580712c8436b8095",
"testharness"
],
- "html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-module.html": [
- "a33d3b405b1a826f51dadb18431c855b13aee612",
+ "html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-module.html": [
+ "7386a90307c33bdaad34002c865b4ad8793c10a2",
+ "testharness"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-classic.html": [
+ "928c333bf9c50213175095ceb06f1afdd690bd8a",
+ "testharness"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-module.html": [
+ "1daf837d2d9ee258dfc5c9648b1a0f5b0b6e93e4",
"testharness"
],
"html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-classic.html": [
"e22e6f200162000f043d114c89def6667097d13d",
"testharness"
],
+ "html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-integrity-classic.html": [
+ "0295db34d953b716151726188ac467a948f0d955",
+ "testharness"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-integrity-module.html": [
+ "cfc2375f7a8abe67eae4213b2f0c5224ba25337d",
+ "testharness"
+ ],
"html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-module.html": [
"b332499d43e0768b5ddf1d5dbb5cd8ca702c3c64",
"testharness"
],
+ "html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-classic.html": [
+ "20a6c6de42fe72fe375ccd8c9c8763191afa78f9",
+ "testharness"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-module.html": [
+ "93f2cc8f3e88e0cbf508acd64f9a28bdcaff25b0",
+ "testharness"
+ ],
"html/semantics/scripting-1/the-script-element/module/error-and-slow-dependency.html": [
"32455a1418d94fa68368bae3b1c0291204f6b4e3",
"testharness"
],
+ "html/semantics/scripting-1/the-script-element/module/error-type-1.html": [
+ "f376310fd56bf105c9c9cbe822a706e60faf4284",
+ "testharness"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/error-type-1.js": [
+ "917c96082ae3686c6409004ecafeba24bab9603a",
+ "support"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/error-type-2.html": [
+ "80bd1639df6d35b3e5eeeec009e1eb85000f0037",
+ "testharness"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/error-type-2.js": [
+ "6f2248a9d0bfd63251c838df4c92e7174a55605d",
+ "support"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/error-type-3.html": [
+ "f71b506e6a9bf1b9bf1cb8db518a590f7e7c90ed",
+ "testharness"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/error-type-3.js": [
+ "3c76f2c8466a6fb5cc307c0fc03e5d759e4c99c1",
+ "support"
+ ],
"html/semantics/scripting-1/the-script-element/module/errorhandling-parseerror-common.js": [
"ff9af4e5253db096cd5de8d2e7ed74cd05ed2561",
"support"
@@ -545117,7 +552469,7 @@
"testharness"
],
"html/semantics/scripting-1/the-script-element/module/instantiation-error-1.html": [
- "2b4fa3b558dccb50bf0aee12a78e3320501ea1b5",
+ "b48335aa61dc13c34d2a77806f20663e2156bc6f",
"testharness"
],
"html/semantics/scripting-1/the-script-element/module/instantiation-error-1.js": [
@@ -545125,15 +552477,15 @@
"support"
],
"html/semantics/scripting-1/the-script-element/module/instantiation-error-2.html": [
- "70271ef6fbf9f6e4f6e61438691b6fce317137e9",
+ "e2c860b1b348148fc6b9d77f918894b1bac42c94",
"testharness"
],
"html/semantics/scripting-1/the-script-element/module/instantiation-error-3.html": [
- "80fa90a214bb4839703c36f9db36e07f3a2ca7f2",
+ "996d1aa45c5975e13ac0f1e9c9249b3d452ed2e2",
"testharness"
],
"html/semantics/scripting-1/the-script-element/module/instantiation-error-4.html": [
- "dbb8eb640576cd4f658e32dec441919e943f8d21",
+ "224fe5510f09c3dd6d58f9dcf61b4d6fca04c96c",
"testharness"
],
"html/semantics/scripting-1/the-script-element/module/instantiation-error-4a.js": [
@@ -545153,7 +552505,7 @@
"support"
],
"html/semantics/scripting-1/the-script-element/module/instantiation-error-5.html": [
- "fcc8da57e88ee87592a02888c54bb6d66e5172f6",
+ "7239ae9f5705f7baf5630e67cf4bfdc6c25b108d",
"testharness"
],
"html/semantics/scripting-1/the-script-element/module/instantiation-error-5a.js": [
@@ -545292,6 +552644,26 @@
"4ce8bcce2537785c41f054175119e39169ed6110",
"testharness"
],
+ "html/semantics/scripting-1/the-script-element/module/referrer-no-referrer.sub.html": [
+ "24c02b3a6564a12611bbccd1fa80fa5632ff4efe",
+ "testharness"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/referrer-origin-when-cross-origin.sub.html": [
+ "77ba562a5284c421c4baeaf810215bc0d54adf01",
+ "testharness"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/referrer-origin.sub.html": [
+ "aeba47babafecffdd618a4758d6883cb47b0eff8",
+ "testharness"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/referrer-same-origin.sub.html": [
+ "6a931d34d1415144c1faac0d0135faebd8a2151a",
+ "testharness"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/referrer-unsafe-url.sub.html": [
+ "abd1f2d309b721f7bbb1f3ca07ae77a204f4ed66",
+ "testharness"
+ ],
"html/semantics/scripting-1/the-script-element/module/resources/404-but-js.asis": [
"a83137f4c22cadb41ca631a8a8cca17c01021f34",
"support"
@@ -545320,6 +552692,18 @@
"263589f24f862c862ac8f47ba2de71b77bd9e5bd",
"support"
],
+ "html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js": [
+ "6c49153dcd5e4ca5084f0b61eff3b3618a56ef3b",
+ "support"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js.headers": [
+ "90d51a5e46cc58404dd5ec1e9e4e10934a6c0707",
+ "support"
+ ],
+ "html/semantics/scripting-1/the-script-element/module/resources/import-remote-origin-referrer-checker.sub.js": [
+ "c0f62a331cb7197a6abf1b465afd35b624d722fa",
+ "support"
+ ],
"html/semantics/scripting-1/the-script-element/module/resources/import-utf8-with-charset-header.js": [
"23ca0a693a1d6ee4eca34bf27c55764e769437c6",
"support"
@@ -545340,6 +552724,10 @@
"edf619abb179fc343162bc585c4582ab0d4b0c8f",
"support"
],
+ "html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py": [
+ "a148d34314c2734fd49bf69d201006618fdac78f",
+ "support"
+ ],
"html/semantics/scripting-1/the-script-element/module/script-for-event.html": [
"c225684e0c7d09f9628aab589c8673b140994243",
"testharness"
@@ -545400,6 +552788,10 @@
"d071fd2e76896c4b66636f359d4426fe101f6d0f",
"support"
],
+ "html/semantics/scripting-1/the-script-element/module/throw2.js": [
+ "34c282c0357c639400877b65bf21f30db3b99ea5",
+ "support"
+ ],
"html/semantics/scripting-1/the-script-element/nomodule-reflect.html": [
"ac2b3c16e9e9263cd4c14de205b63709c14ec2e3",
"testharness"
@@ -545484,6 +552876,10 @@
"e3209904d340a7f9803af6828cd830f2bd26cbc5",
"testharness"
],
+ "html/semantics/scripting-1/the-script-element/script-defer.html": [
+ "c9e0e3a71a522a42be3b3da51999c9762d06e3e6",
+ "testharness"
+ ],
"html/semantics/scripting-1/the-script-element/script-for-event-xhtml.xhtml": [
"e7de020976ea907ce3a0460f0ad3ba6ad322b5ed",
"testharness"
@@ -546125,11 +553521,11 @@
"support"
],
"html/semantics/text-level-semantics/the-a-element/a-download-click-404.html": [
- "9c9b5c7f78d9c06707d4aaca8256f1fb3da9f06f",
+ "a5368cce11f6fcaf4d220fabe17685ca1cc4953d",
"testharness"
],
"html/semantics/text-level-semantics/the-a-element/a-download-click.html": [
- "64cd3f544c42f21c33456e000788aeaab2fed3eb",
+ "d1ff2de258b01a46afb04901c53b0603ce92cc9f",
"testharness"
],
"html/semantics/text-level-semantics/the-a-element/a-stringifier.html": [
@@ -546156,6 +553552,10 @@
"f703d9a7ce1e09e0c9ef9ea2bd2cd2b318613f6d",
"support"
],
+ "html/semantics/text-level-semantics/the-a-element/resources/a-download-click.html": [
+ "187ff7074f9d52e59177a3c3dafabe2823b60257",
+ "support"
+ ],
"html/semantics/text-level-semantics/the-abbr-element/.gitkeep": [
"da39a3ee5e6b4b0d3255bfef95601890afd80709",
"support"
@@ -546164,6 +553564,14 @@
"da39a3ee5e6b4b0d3255bfef95601890afd80709",
"support"
],
+ "html/semantics/text-level-semantics/the-b-element/b-usage-notref.html": [
+ "325d5278bce87086f1a1e4a8ba5181ffd9604d9b",
+ "support"
+ ],
+ "html/semantics/text-level-semantics/the-b-element/b-usage.html": [
+ "7e600b3b69a8d8afe1939262a4e83d0b22a5e3b6",
+ "reftest"
+ ],
"html/semantics/text-level-semantics/the-bdi-element/.gitkeep": [
"da39a3ee5e6b4b0d3255bfef95601890afd80709",
"support"
@@ -546388,6 +553796,14 @@
"da39a3ee5e6b4b0d3255bfef95601890afd80709",
"support"
],
+ "html/semantics/text-level-semantics/the-ruby-element/ruby-usage-notref.html": [
+ "2db31a9c9bb7a301dbb579332a7870315e4521f8",
+ "support"
+ ],
+ "html/semantics/text-level-semantics/the-ruby-element/ruby-usage.html": [
+ "c20a6cff72623ce86f1139dff58faa88f42673f4",
+ "reftest"
+ ],
"html/semantics/text-level-semantics/the-s-element/.gitkeep": [
"da39a3ee5e6b4b0d3255bfef95601890afd80709",
"support"
@@ -547141,7 +554557,7 @@
"testharness"
],
"html/webappapis/animation-frames/idlharness.html": [
- "03aebad24e8289a02f8336931825dc34039e83cc",
+ "8210ec5e16b79035472198220d39596404dab310",
"testharness"
],
"html/webappapis/animation-frames/same-dispatch-time.html": [
@@ -547309,7 +554725,7 @@
"testharness"
],
"html/webappapis/scripting/events/event-handler-spec-example.html": [
- "8d4d0bfdf447591695ac134cd243277ea2326c84",
+ "a0ab0a1eb5a6aa3cffcb06e2f8ea97ddfcaa6c52",
"testharness"
],
"html/webappapis/scripting/events/eventhandler-cancellation.html": [
@@ -547637,7 +555053,7 @@
"testharness"
],
"html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.html": [
- "9ab91396894612ad2a71643cd5253fcc8572983a",
+ "d87ec96d53353fc63b9d3db4775414c6335cdd2d",
"testharness"
],
"html/webappapis/the-windoworworkerglobalscope-mixin/Worker_Self_Origin.html": [
@@ -547737,7 +555153,7 @@
"testharness"
],
"http/resources/securedimage.py": [
- "bc4c7a8b5eef0e082a5fa7c8c763957d92730747",
+ "b03f45c4dad3a9cd0f0fb67a99a79be3ba64b199",
"support"
],
"imagebitmap-renderingcontext/bitmaprenderer-as-imagesource.html": [
@@ -547936,12 +555352,16 @@
"946f23f945163bf9f9da080291b21473f6e1cbd0",
"support"
],
- "infrastructure/assumptions/ahem-ref.html": [
- "65ecf705ea9804f42a2503941afe96a0c06dd3b7",
+ "infrastructure/assumptions/ahem-notref.html": [
+ "944e5db7eb0d7274ed547002410c25c9fbdc20b3",
"support"
],
+ "infrastructure/assumptions/ahem-ref.html": [
+ "427377782d24933d87d2b33538a178eaf4d911be",
+ "reftest_node"
+ ],
"infrastructure/assumptions/ahem.html": [
- "770fd700c20d041fcfc2d01b53b3f0671c95ec15",
+ "ca9b8811c489f8fa27e74f3e64937da7c28bf434",
"reftest"
],
"infrastructure/assumptions/canvas-background-ref.html": [
@@ -547981,7 +555401,7 @@
"reftest"
],
"infrastructure/assumptions/tools/ahem-generate-table.py": [
- "7057b804e191b4c1a53df3b631042f9726eb8309",
+ "24ddd1f2cbd478653820899aa63c35f02d0a551c",
"support"
],
"infrastructure/assumptions/tools/build.sh": [
@@ -548077,7 +555497,7 @@
"support"
],
"interfaces/dom.idl": [
- "915affb8d20dcc9055d3f453efbb893d14fc529b",
+ "52236516620dac45213fa06dc169f0c02e63a0c5",
"support"
],
"interfaces/fullscreen.idl": [
@@ -548089,7 +555509,7 @@
"support"
],
"interfaces/geolocation-sensor.idl": [
- "3927181a988c0a95cff9813d5074112265e9d263",
+ "158edb1945e5b3cefdb92953c6b3caf191d86986",
"support"
],
"interfaces/geometry.idl": [
@@ -548100,8 +555520,12 @@
"77d4d59d0e83928f02b4652636d64df448b388d1",
"support"
],
+ "interfaces/hr-time.idl": [
+ "61bd84c720a00b5dfaff8a98ace54cb476a4ed18",
+ "support"
+ ],
"interfaces/html.idl": [
- "30bf215678945a0b5732673d0364cbd64867095e",
+ "b93b108cc7ce46595b701a6631b5b8536f0e7eb2",
"support"
],
"interfaces/magnetometer.idl": [
@@ -548149,7 +555573,7 @@
"support"
],
"interfaces/webrtc-pc.idl": [
- "67ca220dbed4271371f67a7a7e2a0a9734288ab6",
+ "f3bcd13429b9ab477f7b2422fa4e3ede0bfac88a",
"support"
],
"interfaces/webusb.idl": [
@@ -548369,7 +555793,7 @@
"testharness"
],
"longtask-timing/longtask-in-childiframe-crossorigin.html": [
- "1a461ce9d7283157047127312135a218044ec5c0",
+ "218c69b5395af1590fea4216ec71aae5434e265d",
"testharness"
],
"longtask-timing/longtask-in-childiframe.html": [
@@ -548381,7 +555805,7 @@
"testharness"
],
"longtask-timing/longtask-in-parentiframe.html": [
- "7b1a7373902b68ebcf8f5119cfe7904dd32acd03",
+ "4914c53c30b9670e103db4bee78b80d8d35af968",
"testharness"
],
"longtask-timing/longtask-in-raf.html": [
@@ -548389,11 +555813,15 @@
"testharness"
],
"longtask-timing/longtask-in-sibling-iframe-crossorigin.html": [
- "6f9971d082ffa24a31e57697ea6bf929b237c62b",
+ "4443396532adac8bc3a9012553bc7dedc328d710",
"testharness"
],
"longtask-timing/longtask-in-sibling-iframe.html": [
- "24fd1e4ce58d824d29a65edc913075ca98fe71d6",
+ "e9c7f9671fba6eba939a3241bbddffb2a6c2bb13",
+ "testharness"
+ ],
+ "longtask-timing/longtask-tojson.html": [
+ "c80d01bb7d3825dbdad09137b47ab4e5327f7fbf",
"testharness"
],
"longtask-timing/resources/makelongtask.js": [
@@ -548405,7 +555833,7 @@
"support"
],
"longtask-timing/resources/subframe-observing-longtask.html": [
- "f2f852a5ec5aeb478b578948a301210f9ad12878",
+ "f1dc339127ee2441a6dbcbde4bbbcd1861801208",
"support"
],
"longtask-timing/resources/subframe-with-longtask.html": [
@@ -548420,16 +555848,48 @@
"2901b02184fb36d620782fb7fd4a565124580e81",
"support"
],
+ "magnetometer/Magnetometer-disabled-by-feature-policy.https.html": [
+ "e7c3f45ece750fd22149ea34ee968a6f7f795ac3",
+ "testharness"
+ ],
+ "magnetometer/Magnetometer-disabled-by-feature-policy.https.html.headers": [
+ "9a930b1268bf30ce845ba6671dbb2f44faa92bb2",
+ "support"
+ ],
+ "magnetometer/Magnetometer-enabled-by-feature-policy-attribute-redirect-on-load.https.html": [
+ "d9963541021955e037dec0b443e4a80f4ffe4ee0",
+ "testharness"
+ ],
+ "magnetometer/Magnetometer-enabled-by-feature-policy-attribute.https.html": [
+ "2ff0ea0df581c878201bc89e05dfc3e82ffadc01",
+ "testharness"
+ ],
+ "magnetometer/Magnetometer-enabled-by-feature-policy.https.html": [
+ "ef9490c36c40ee6fe2f1bb09c6fd30519d70796c",
+ "testharness"
+ ],
+ "magnetometer/Magnetometer-enabled-by-feature-policy.https.html.headers": [
+ "2be01ba1805ae8fd8038a70763b29e2070a96f78",
+ "support"
+ ],
+ "magnetometer/Magnetometer-enabled-on-self-origin-by-feature-policy.https.html": [
+ "3e96f42d58b119e42b261f0ae641f56a7c685f47",
+ "testharness"
+ ],
+ "magnetometer/Magnetometer-enabled-on-self-origin-by-feature-policy.https.html.headers": [
+ "2099d254fa4bb019404df56ec1a99e84459c77e2",
+ "support"
+ ],
"magnetometer/Magnetometer.https.html": [
- "3fbdbbd6c3db9b1a44d7490101bea34045f1945e",
+ "240e7d0af55b8681f2f45ca22283634acc406325",
"testharness"
],
"magnetometer/Magnetometer_insecure_context.html": [
- "417e00b969ea887ee4d3d4d9b0dc7af4d786e365",
+ "0eeb95340d7c74a0243eac8d3f004b6e06b87a92",
"testharness"
],
"magnetometer/Magnetometer_onerror-manual.https.html": [
- "6adfb807ff2c1b24dad702b21f636e7805543704",
+ "da4e6b8975beecdcae24da26920a56a652f781e4",
"manual"
],
"magnetometer/OWNERS": [
@@ -548569,139 +556029,139 @@
"testharness"
],
"mathml/relations/css-styling/mathvariant-bold-fraktur-ref.html": [
- "40e52bb1ecb0845350bf5189f7dcd3b0da412247",
+ "fa251bee74521ce8b994e41eee3b1bc5b688bcab",
"support"
],
"mathml/relations/css-styling/mathvariant-bold-fraktur.html": [
- "3915dde4053df2960a4611dbc9974cbd73c23c54",
+ "330fd8e22586c5063f4d6cb19679c99e38ab43fc",
"reftest"
],
"mathml/relations/css-styling/mathvariant-bold-italic-ref.html": [
- "2cbec8cdbfb8dd88f28c46ee027d451730529367",
+ "be1bcdd743e3239a5653aeb3b79c5cd247526601",
"support"
],
"mathml/relations/css-styling/mathvariant-bold-italic.html": [
- "ef64020b7a0b19c718680fba0de4d36269842a36",
+ "bda1fae3d50812ca2f8d2d6a4d2ac9de27ae9a61",
"reftest"
],
"mathml/relations/css-styling/mathvariant-bold-ref.html": [
- "3569268cf64f013a44fbc20e1c967324d6e682ab",
+ "109e487d88b404d5ee2b93cd8957ed6f3d3fc8b0",
"support"
],
"mathml/relations/css-styling/mathvariant-bold-sans-serif-ref.html": [
- "95167d752b578e5c4dd754f7d873c225056fc8de",
+ "dcdc13abb1c6dff74ff49a2a90b0947e240419a5",
"support"
],
"mathml/relations/css-styling/mathvariant-bold-sans-serif.html": [
- "0c0be201714de4c1cf205c365331d49d8799347f",
+ "6fb64e6e9238974f8a0243fde67a6bf61b76bc5f",
"reftest"
],
"mathml/relations/css-styling/mathvariant-bold-script-ref.html": [
- "e882071165d8108fea748be4823260302ef0bb19",
+ "fc121463c63e74c00ed21d6c708a4fbbbdfe812f",
"support"
],
"mathml/relations/css-styling/mathvariant-bold-script.html": [
- "30730343ac624b27392bf1a4fc49f9ef3273c0b5",
+ "8e808e39f8f4183b237032ddbafe79574bb76255",
"reftest"
],
"mathml/relations/css-styling/mathvariant-bold.html": [
- "c52ff122dc0fa7b9c37ca6b95364c212ff475033",
+ "9ff9f0b9c5dd91c1f7a1cc8dc1112247c9f5480b",
"reftest"
],
"mathml/relations/css-styling/mathvariant-double-struck-ref.html": [
- "f2d0b2f7469926fc7144a8f4576f891b0864da21",
+ "30d9cea222663a7356c18a6c50f4899d9b031ba3",
"support"
],
"mathml/relations/css-styling/mathvariant-double-struck.html": [
- "50015cb963ac68bfcb51d35adcac9057e62bf2b9",
+ "ea4e3d48c63e70c547c0ae48c9222ed59337ddae",
"reftest"
],
"mathml/relations/css-styling/mathvariant-fraktur-ref.html": [
- "2ae8154b3af0d85f3d3f6535aa1b010d5461e24b",
+ "3b282059025b62e8a2215f42b4b0d44e22df04f4",
"support"
],
"mathml/relations/css-styling/mathvariant-fraktur.html": [
- "630006bc1643063c56736c5ba187a1fa3582b9b1",
+ "8d5370ce182f7aabc36e00f3a7cf9db85562a439",
"reftest"
],
"mathml/relations/css-styling/mathvariant-initial-ref.html": [
- "64d17f049b2ecfa195b6d8fd4981e8dec1d93239",
+ "2081d39bb893c3706c1fb04920528c87b04e1984",
"support"
],
"mathml/relations/css-styling/mathvariant-initial.html": [
- "97a650b9e6e2850ad50c25f1a9689a705ce2d613",
+ "b0ba80237bbd87151f32b478ee40e0db03624a0f",
"reftest"
],
"mathml/relations/css-styling/mathvariant-italic-ref.html": [
- "d0b6d7386fc49e3a12bb435337fe8b13a6bec6dd",
+ "396b57a917ab987981448147ca943bfd1325338b",
"support"
],
"mathml/relations/css-styling/mathvariant-italic.html": [
- "96c4b5cb3c1050b01191af462d1c9bcf2d6e7825",
+ "2b30f12c18c48679b776d43f11e60af84ab2da98",
"reftest"
],
"mathml/relations/css-styling/mathvariant-looped-ref.html": [
- "ac54af1752395cfb327d19d81d1fff4090ffe012",
+ "0117e2b19a34fd78ba30adc0c61ab87c378ad084",
"support"
],
"mathml/relations/css-styling/mathvariant-looped.html": [
- "336fd6c7018b87d48a65b16839c2e9acdec15be9",
+ "1329a965d5ad23d1cb6ff0b32c8acba4dc12d094",
"reftest"
],
"mathml/relations/css-styling/mathvariant-monospace-ref.html": [
- "489036f178eae6a525c9fe2169ad415177ab43d8",
+ "08381a23b783380059c333a652c8566b60e23c58",
"support"
],
"mathml/relations/css-styling/mathvariant-monospace.html": [
- "4a7ae605eca6e9db5d75a66274c6c00727402ba2",
+ "e9be2e98731c8a3d2f5db4baa9823c67459e53da",
"reftest"
],
"mathml/relations/css-styling/mathvariant-sans-serif-bold-italic-ref.html": [
- "e6f97248889b2f8bb56088e47a1d201259fc7105",
+ "a2f25713ca05a8a3cc2c53f90698d7f7af8d29aa",
"support"
],
"mathml/relations/css-styling/mathvariant-sans-serif-bold-italic.html": [
- "5c1be25a2cb8f38c6f5cbbf3b4ef45a9350509d5",
+ "f7cb0d9e8feae82ce7bf22a654bd848b69ed0be3",
"reftest"
],
"mathml/relations/css-styling/mathvariant-sans-serif-italic-ref.html": [
- "dfa452732d4cc9889db307683e140705638cd859",
+ "f7b6a41c2bf8f07aae4637167505af3dee1d5367",
"support"
],
"mathml/relations/css-styling/mathvariant-sans-serif-italic.html": [
- "2499fea7af08b4ca4d7eb33cb2d8de7b4fae794c",
+ "15832d96f720c7175e94043c7c8a63ba97c32818",
"reftest"
],
"mathml/relations/css-styling/mathvariant-sans-serif-ref.html": [
- "d178cc3954b7bc4190f743a77a7b60193bc0b593",
+ "6108ffa455435a222746104a582539b7e018754f",
"support"
],
"mathml/relations/css-styling/mathvariant-sans-serif.html": [
- "3db38fed4f252fb896f03a1c0b562d8dcba13181",
+ "34850eac5b5bb52eb024033d3ad8aec019604a63",
"reftest"
],
"mathml/relations/css-styling/mathvariant-script-ref.html": [
- "21949960ba7656b0318102126423217870b64b1e",
+ "5cde52d1011ce23f1b27632237a01181c9ed93ff",
"support"
],
"mathml/relations/css-styling/mathvariant-script.html": [
- "a4ae7f0e3c49b32666b97709d314abd1c789df26",
+ "312d2bb7704c2194ace3660a7ccbadce527ab5a3",
"reftest"
],
"mathml/relations/css-styling/mathvariant-stretched-ref.html": [
- "7a8a969c582e53f329e4a48cead5d5852403565a",
+ "e12b152facef44aba781d57593e63e9ef2bd6883",
"support"
],
"mathml/relations/css-styling/mathvariant-stretched.html": [
- "e9c229ca6189eed571e244123110ee5bec07282b",
+ "bd83169e1c88e4e49a71c29fd2c5b48e7e2dbc86",
"reftest"
],
"mathml/relations/css-styling/mathvariant-tailed-ref.html": [
- "94c4c9a8946ca2df797d5f4a570f9046179e65f4",
+ "deda9219cd87c16edf341f1313b9981a36f69102",
"support"
],
"mathml/relations/css-styling/mathvariant-tailed.html": [
- "d7f523065d5480705a5a16d23e797665d163ff21",
+ "c51e8b7f0df2f273753d985fc65b90d0ef2a2364",
"reftest"
],
"mathml/relations/css-styling/visibility-1-ref.html": [
@@ -548800,20 +556260,20 @@
"e3be84d69ecef76bb21d8d1135e24c8265f040e5",
"reftest"
],
- "mathml/relations/html5-tree/unique-identifier-1-iframe.html": [
+ "mathml/relations/html5-tree/unique-identifier-1-iframe-1.html": [
"4bcb11441203d9c147e0be7da821e2dd0b9f4507",
"support"
],
- "mathml/relations/html5-tree/unique-identifier-1-ref-iframe.html": [
+ "mathml/relations/html5-tree/unique-identifier-1-iframe-2.html": [
"22a82eb8f312a3f2461d75e480197e0c2894c10e",
"support"
],
"mathml/relations/html5-tree/unique-identifier-1-ref.html": [
- "2b8e4f0079792594f764a05f8ad032985a9ede65",
+ "f03271e615e182893a13b6f5b55a9dc05abcec41",
"support"
],
"mathml/relations/html5-tree/unique-identifier-1.html": [
- "4a966f83afa727682fe392da126aa042e2520f96",
+ "05c9bbfc6e8c7a1c003f1721cdd1540b89ab107e",
"reftest"
],
"mathml/relations/html5-tree/unique-identifier-2.html": [
@@ -548853,7 +556313,7 @@
"support"
],
"mathml/tools/mathvariant-transforms.py": [
- "413f1df7163f28b93702491e7aa538758c278572",
+ "27fa2d287a5d407322ba3d1d795acae8df7b0a92",
"support"
],
"mathml/tools/radicals.py": [
@@ -548901,11 +556361,11 @@
"support"
],
"media-capabilities/decodingInfo.html": [
- "80c20b9a3c3c055aff8afa64472e44b2e7c4c34c",
+ "3cafa5d2375c8f42abee8f22293705eaa6dca019",
"testharness"
],
"media-capabilities/idlharness.html": [
- "0c34bb1872cc16b21c8c1f33d6dfd796f59500c8",
+ "396430dee8bc806e95a218e03f767b34efe8fe83",
"testharness"
],
"media-source/OWNERS": [
@@ -549352,6 +556812,14 @@
"30004bfb49495e067cf71c702ac5985d24589c06",
"support"
],
+ "media/counting.mp4": [
+ "ee7fc48592720df569acc537d3d3b04b28f72d0b",
+ "support"
+ ],
+ "media/counting.ogv": [
+ "caa14c32214a9cac3bac4273c0b89148e3f79f50",
+ "support"
+ ],
"media/foo.vtt": [
"fbfdfb2648866047d0fa2a4ad4fde3462a491857",
"support"
@@ -549408,6 +556876,14 @@
"30080b0409424f065a1b286709c87c04c29fbb22",
"support"
],
+ "media/test.mp4": [
+ "94bb77512a183c8f32c8fcac0637c2e0b1cd2411",
+ "support"
+ ],
+ "media/test.ogv": [
+ "1edab53c83e53140002aa2a6349d0226be7f5c74",
+ "support"
+ ],
"media/white.mp4": [
"577f031289beb30fa38824950ea297818bab8e81",
"support"
@@ -549417,15 +556893,15 @@
"support"
],
"mediacapture-fromelement/capture.html": [
- "d5ccd840a00ed4a77dda172663cd39a035565873",
+ "ff450ec02ee509df7a022a490bfc818c20983743",
"testharness"
],
"mediacapture-fromelement/creation.html": [
- "f21413b0d01844dd41776c9a3b417a665b497e20",
+ "18289cfde81c16db6d3e728623113be0bde3454f",
"testharness"
],
"mediacapture-fromelement/ended.html": [
- "5d400556089e656fdf481a033cfadf0a2dc1f2e3",
+ "c816abe4302804f8e3ba65bad23443812111acb1",
"testharness"
],
"mediacapture-fromelement/idlharness.html": [
@@ -549541,7 +557017,7 @@
"testharness"
],
"mediacapture-streams/MediaStreamTrack-MediaElement-disabled-video-is-black.https.html": [
- "9f8b4811f67bd0c9ed67327e9589db68432e3117",
+ "e3358344a76f874b68bdba743f113caa3b61ec88",
"testharness"
],
"mediacapture-streams/MediaStreamTrack-end-manual.https.html": [
@@ -549581,7 +557057,7 @@
"support"
],
"mediasession/idlharness.html": [
- "9aa84a0143daf03d9a95108d0407fda2443c9849",
+ "8db3276ecfd3f02e55b89171f61e45e6af540614",
"testharness"
],
"mediasession/mediametadata.html": [
@@ -549596,6 +557072,42 @@
"70a1f9e81faa3dbbe320a71a008e4594a29878a8",
"testharness"
],
+ "mimesniff/OWNERS": [
+ "69591fe91d93bf0a6b171734b119274a8c69bbde",
+ "support"
+ ],
+ "mimesniff/README.md": [
+ "d0b95d2e21e80df8b65d5bc8217f79d862229ae2",
+ "support"
+ ],
+ "mimesniff/mime-types/README.md": [
+ "f3cd8bf009de6ceb297af8bfdecb851f817fa02d",
+ "support"
+ ],
+ "mimesniff/mime-types/charset-parameter.window.js": [
+ "baa985ca1fd0aed6644d9d1cef21764cfe826a8b",
+ "testharness"
+ ],
+ "mimesniff/mime-types/parsing.any.js": [
+ "b40a3e56406cd6f3303877b1da07a74d0d2f9deb",
+ "testharness"
+ ],
+ "mimesniff/mime-types/resources/generated-mime-types.json": [
+ "e4610646e4a1a417e9fccf868150aed3c5688942",
+ "support"
+ ],
+ "mimesniff/mime-types/resources/generated-mime-types.py": [
+ "1a3357e9bd14bc90cfa45f6844a270b7b3b93db4",
+ "support"
+ ],
+ "mimesniff/mime-types/resources/mime-charset.py": [
+ "635c7dd3564ddec8c7a18c9eb1dae4c01cab75c4",
+ "support"
+ ],
+ "mimesniff/mime-types/resources/mime-types.json": [
+ "e036eb74e27d8f35c411bb4d29d0b0621778e882",
+ "support"
+ ],
"mixed-content/OWNERS": [
"167112f19752c9c180831820b6e348427606b63b",
"support"
@@ -550104,51 +557616,51 @@
"0e215b6c8f95aea079d53dca4e18e513c50ef9c0",
"testharness"
],
- "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html": [
- "013eb078c215d37a8a52f266beaf9d3871fee401",
+ "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html": [
+ "1adabf38a9a679da7696f12d61ce50c4c75bec16",
"testharness"
],
- "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers": [
+ "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html.headers": [
"562977daf4fd9e09dc6153058804bc247cbe5354",
"support"
],
- "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html": [
- "c10fe679c6cb2d69d5c6eaaa985d7d0aebf9e86a",
+ "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html": [
+ "41049d21e59f6b84f45096796e6b3d1e8ca25553",
"testharness"
],
- "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html.headers": [
+ "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html.headers": [
"562977daf4fd9e09dc6153058804bc247cbe5354",
"support"
],
- "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html": [
- "f07bd06527b7c4210c408a3593f5142f5ad47213",
+ "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html": [
+ "1d240c95fbfd0394b5458e1dae0394bdbf2bb4e1",
"testharness"
],
- "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers": [
+ "mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html.headers": [
"562977daf4fd9e09dc6153058804bc247cbe5354",
"support"
],
- "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html": [
- "82b2035593f5408f7c3e53b640cca2f14214c606",
+ "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html": [
+ "4fb46872ee82b2d2355069dac1e56599b76e429f",
"testharness"
],
- "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers": [
+ "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html.headers": [
"562977daf4fd9e09dc6153058804bc247cbe5354",
"support"
],
- "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html": [
- "0671d48855fd3fc222e13579c7b9cc10ec822898",
+ "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html": [
+ "2fa674993a988fa52ceffe2168536387997fa205",
"testharness"
],
- "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html.headers": [
+ "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html.headers": [
"562977daf4fd9e09dc6153058804bc247cbe5354",
"support"
],
- "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html": [
- "11a64084b74832bef705a46b1ef006b2e51d9bca",
+ "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html": [
+ "d6a6c64b7c530b04edd4ddf553ce5db363a5dfdd",
"testharness"
],
- "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers": [
+ "mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html.headers": [
"562977daf4fd9e09dc6153058804bc247cbe5354",
"support"
],
@@ -550168,40 +557680,40 @@
"562977daf4fd9e09dc6153058804bc247cbe5354",
"support"
],
- "mixed-content/link-prefetch-tag/meta-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html": [
- "bc56ec3ab4cc4e13527189fb43f36ebb27fa71c0",
+ "mixed-content/link-prefetch-tag/meta-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html": [
+ "92ae912bff02681d40f206c2c9b11c1f9e8e192c",
"testharness"
],
- "mixed-content/link-prefetch-tag/meta-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html": [
- "ce3eb59ff993f2731c6af61806217caf7f6c3bbd",
+ "mixed-content/link-prefetch-tag/meta-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html": [
+ "925c41353886a9abf6d96c4679635a91a74408db",
"testharness"
],
"mixed-content/link-prefetch-tag/meta-csp/same-host-https/top-level/no-redirect/allowed/allowed.https.html": [
"d1fea7e4b5e32b88797cdfaea1deaced699e3a80",
"testharness"
],
- "mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html": [
- "baed43b2d575d296fea4d71452adea468bd02fc0",
+ "mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/keep-scheme-redirect/blockable/no-opt-in-blocks.https.html": [
+ "b4c2ffb1cdc781e479582136d58b32d071efed26",
"testharness"
],
- "mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/no-redirect/optionally-blockable/no-opt-in-allows.https.html": [
- "8995bfa6816c2697dc449675768727abd5ecb266",
+ "mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/no-redirect/blockable/no-opt-in-blocks.https.html": [
+ "4a9452a6b58037094692565900cb3370c9f360f9",
"testharness"
],
- "mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html": [
- "2b4266e2798cffa4df8085d85dc6192151125d13",
+ "mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/swap-scheme-redirect/blockable/no-opt-in-blocks.https.html": [
+ "8f406983e28a48e47288eff8a120cec7ef603b67",
"testharness"
],
- "mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html": [
- "34f1424d91ee6bbe1f0c6aa46e307104443f70bd",
+ "mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/keep-scheme-redirect/blockable/no-opt-in-blocks.https.html": [
+ "842695f8ba053fd92766d65f27bcbc18442abbaa",
"testharness"
],
- "mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/no-redirect/optionally-blockable/no-opt-in-allows.https.html": [
- "62a276c360cb5540fe5decc2f388d4c667007a9b",
+ "mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/no-redirect/blockable/no-opt-in-blocks.https.html": [
+ "ee62d9adad2f7be55ed6274c6609aa03387bc8b1",
"testharness"
],
- "mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html": [
- "b98e1a5a55b229fabc73ff520e93d1aae5786a84",
+ "mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/swap-scheme-redirect/blockable/no-opt-in-blocks.https.html": [
+ "ced5cade402abdd4fd34b295a8c72dd674b2c6e7",
"testharness"
],
"mixed-content/link-prefetch-tag/no-opt-in/same-host-https/top-level/keep-scheme-redirect/allowed/allowed.https.html": [
@@ -550537,11 +558049,11 @@
"testharness"
],
"mixed-content/spec.src.json": [
- "5edaa65af1b7d9f8941442dfec71e087d521c22e",
+ "1e46012ca5e1f0892e6c80572fa28c5358596c57",
"support"
],
"mixed-content/spec_json.js": [
- "212f362ad9a8828575eaca2b003a83a2276b3faa",
+ "f3b78849f97e307c39f81cf9cebb01b367c91b79",
"support"
],
"mixed-content/video-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html": [
@@ -550981,7 +558493,7 @@
"support"
],
"navigation-timing/idlharness.html": [
- "d05e1d10939fa6509bd7299d03d32d59f69a03f6",
+ "7b09fdf79c4166eaf21bcf2f92973c80b2864f32",
"testharness"
],
"navigation-timing/nav2_data_uri.html": [
@@ -557312,12 +564824,44 @@
"6948dbbdc88ffd9aa84ad5a6c822b354809561b2",
"manual"
],
+ "orientation-sensor/AbsoluteOrientationSensor-disabled-by-feature-policy.https.html": [
+ "a87d0228b022235fd00eb345cc39f764afd8a64a",
+ "testharness"
+ ],
+ "orientation-sensor/AbsoluteOrientationSensor-disabled-by-feature-policy.https.html.headers": [
+ "86af2e7ee455898629df466e7084ab6e909ec313",
+ "support"
+ ],
+ "orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html": [
+ "7b827dd86f0ec3fd63e7f37d90c9eb85a61be8e2",
+ "testharness"
+ ],
+ "orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy-attribute.https.html": [
+ "7bd1a53f63f8ce9cf4421dd173ee9772dd8ab739",
+ "testharness"
+ ],
+ "orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy.https.html": [
+ "8eaf4b91ba622a454a1f4bae08b5e59905b0deeb",
+ "testharness"
+ ],
+ "orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy.https.html.headers": [
+ "f96008f4d28eec8c158a31c8e5c2bbc9ff55ef05",
+ "support"
+ ],
+ "orientation-sensor/AbsoluteOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html": [
+ "02840fd195f2891fcb9d2159e92dad004ec94608",
+ "testharness"
+ ],
+ "orientation-sensor/AbsoluteOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html.headers": [
+ "cb27e0f09caa38fc80b29580be4b0c06c1024a18",
+ "support"
+ ],
"orientation-sensor/OWNERS": [
"b119dbb984792f33c6e7463f3105d37c3c3b7ad8",
"support"
],
"orientation-sensor/OrientationSensor.https.html": [
- "145b750c49bf703c68bcf4ad645448bc284d393b",
+ "ea9a61f9d526183071a0336e11ca844f59c284a9",
"testharness"
],
"orientation-sensor/OrientationSensor_insecure_context.html": [
@@ -557328,6 +564872,38 @@
"6f0eb976affc21e49f48c42c1bd9d9eb0083ee40",
"manual"
],
+ "orientation-sensor/RelativeOrientationSensor-disabled-by-feature-policy.https.html": [
+ "721b7ba79a90408c073a00383e84966368602b0e",
+ "testharness"
+ ],
+ "orientation-sensor/RelativeOrientationSensor-disabled-by-feature-policy.https.html.headers": [
+ "8795ff5458374246ec69928cf9545cb17be3c641",
+ "support"
+ ],
+ "orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html": [
+ "69bcd956cb76f80481eb867a34fc755f96963d4c",
+ "testharness"
+ ],
+ "orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy-attribute.https.html": [
+ "2c86a4a1a9d71e1ebc8909cedc3cd11a82d59db1",
+ "testharness"
+ ],
+ "orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy.https.html": [
+ "14c83011b5ebcc04b64a3b958e272801f7cd2895",
+ "testharness"
+ ],
+ "orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy.https.html.headers": [
+ "644b0398e76ea06dd5cd012338555b608da02122",
+ "support"
+ ],
+ "orientation-sensor/RelativeOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html": [
+ "a469f03dcf3ce4c8b93fe1498935c6507b1bde87",
+ "testharness"
+ ],
+ "orientation-sensor/RelativeOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html.headers": [
+ "e6e93a77c618e8477d79f6cf1ff05d0f5865821c",
+ "support"
+ ],
"orientation-sensor/idlharness.https.html": [
"30f9a5f56c1eb360be09b2a7f2fd1d5148469e12",
"testharness"
@@ -557413,7 +564989,7 @@
"testharness"
],
"paint-timing/child-painting-first-image.html": [
- "53429c63e77999dbcc633ff45469b869d2005d5e",
+ "a2b3a8fd7cf8a700f7dd6b7f044eb6d6deb9ceee",
"testharness"
],
"paint-timing/first-contentful-bg-image.html": [
@@ -557468,6 +565044,10 @@
"14013a37d0f6496ab3d793c4c51eb8d22c1aec57",
"support"
],
+ "paint-timing/sibling-painting-first-image.html": [
+ "e820a430d03a1ceb40f96f91982eea9ed1d6ac75",
+ "testharness"
+ ],
"payment-handler/OWNERS": [
"c5e5d0fd086bbe946f99aa8836785c81a2bccb3d",
"support"
@@ -557609,7 +565189,7 @@
"testharness"
],
"payment-request/payment-request-constructor.https.html": [
- "1cda9bee85f3afe53e492a7f0e98b12cbfcd9b98",
+ "511c4d25939d344f187fe4a8daa4a8ff926b613d",
"testharness"
],
"payment-request/payment-request-ctor-currency-code-checks.https.html": [
@@ -557624,6 +565204,10 @@
"9a8a1ffc3cd7ba3c29380c4a9962bd17f35087c3",
"testharness"
],
+ "payment-request/payment-request-not-exposed.https.worker.js": [
+ "b1c3cdc182cb967ec11b1cad826b333511203d77",
+ "testharness"
+ ],
"payment-request/payment-request-onshippingaddresschange-attribute.https.html": [
"c9e3679232a83abe6a9eefcb28e3387d2c7810e5",
"testharness"
@@ -557724,6 +565308,10 @@
"30e6893af2cda301efb45fa7cfe16cec04701445",
"testharness"
],
+ "performance-timeline/performanceentry-tojson.html": [
+ "bc8a6f3fb13af9df11781a21b96f342e7d7ddf4e",
+ "testharness"
+ ],
"performance-timeline/performanceobservers.js": [
"0faeecf506da5b8a5c722a1ce8c7b5854227bca0",
"support"
@@ -557789,7 +565377,7 @@
"manual"
],
"pointerevents/extension/idlharness.html": [
- "64ed6d6c201773f0b5ab4b81369a2d601fe3363a",
+ "83ee5397ece0126d71c235cecb554b024e3515d1",
"testharness"
],
"pointerevents/extension/pointerevent_coalesced_events_attributes-manual.html": [
@@ -557805,7 +565393,7 @@
"manual"
],
"pointerevents/idlharness.html": [
- "6ca74eb661910c27ed6cb8bbbb819b749007a75f",
+ "7db1757e519a8ebb9123dd150f17bf5c6f23e311",
"testharness"
],
"pointerevents/pointerevent_attributes_hoverable_pointers-manual.html": [
@@ -558168,6 +565756,10 @@
"9e687345acc5b9966172bab7da04e3e7019e34c5",
"manual"
],
+ "preload/OWNERS": [
+ "fefa8b1bf9f0411b14792bc392711a38a71e91d2",
+ "support"
+ ],
"preload/avoid-delaying-onload-link-preload.html": [
"7f7c89ffad6f9bc2909d56e36b238ffcba260849",
"testharness"
@@ -558192,10 +565784,6 @@
"b69da90e272530d4f42bf6d9c5b3b772d1ffce48",
"testharness"
],
- "preload/fetch-destination.https.html": [
- "d24a50f1f0a52371f84ec35ccc1d99df63c7da44",
- "testharness"
- ],
"preload/link-header-on-subresource.html": [
"ea2f018b648d77b13b8010b4ebe63cdc5f846603",
"testharness"
@@ -558225,7 +565813,7 @@
"support"
],
"preload/modulepreload.html": [
- "82adb9e31fca47cf16908fc41890d74979f1680f",
+ "05d5b064cf231613ef1942eaa77803da37fabea4",
"testharness"
],
"preload/onerror-event.html": [
@@ -558308,10 +565896,6 @@
"ac876cf9750337fcde99e547f5dc1223bb200772",
"support"
],
- "preload/resources/fetch-destination-worker.js": [
- "04e1fd5f1b1829ab9df389f9497681c585b42b78",
- "support"
- ],
"preload/resources/foo.vtt": [
"fbfdfb2648866047d0fa2a4ad4fde3462a491857",
"support"
@@ -558617,58 +566201,54 @@
"support"
],
"proximity/idlharness.html": [
- "f18af9519e53f3d0932d563681e6cc047aad91e3",
+ "8505e5ef30a561c82b7732fd24789387cf8f654e",
"testharness"
],
- "quirks-mode/OWNERS": [
- "adc83b19e793491b1c6ea0fd8b46cd9f32e592fc",
- "support"
- ],
- "quirks-mode/active-and-hover-manual.html": [
+ "quirks/active-and-hover-manual.html": [
"b82c3af04387a133935d1eed50be37fdc34474b2",
"manual"
],
- "quirks-mode/blocks-ignore-line-height.html": [
+ "quirks/blocks-ignore-line-height.html": [
"01c5b2e89c88d4145429e8860eaa88f728d0601b",
"testharness"
],
- "quirks-mode/classname-query-after-sibling-adoption.html": [
+ "quirks/classname-query-after-sibling-adoption.html": [
"a9fd790c46562057d00b9a042f548d28259042d0",
"testharness"
],
- "quirks-mode/hashless-hex-color.html": [
+ "quirks/hashless-hex-color.html": [
"161c0bfaabbfb59c426e855b9dcfa746ea9e8f95",
"testharness"
],
- "quirks-mode/historical/list-item-bullet-size-ref.html": [
+ "quirks/historical/list-item-bullet-size-ref.html": [
"2579fff5cb55faf66c71dfed695f05db8774d98d",
"support"
],
- "quirks-mode/historical/list-item-bullet-size.html": [
+ "quirks/historical/list-item-bullet-size.html": [
"4874e6e43c91378da1ecf1d4e9534339e8bed9ec",
"reftest"
],
- "quirks-mode/line-height-calculation.html": [
+ "quirks/line-height-calculation.html": [
"aa1ccb57bd83d8dd5f61a5571ae790993a3708c0",
"testharness"
],
- "quirks-mode/percentage-height-calculation.html": [
+ "quirks/percentage-height-calculation.html": [
"de9964d89f79db9a85df6bf65b5bc039aa244380",
"testharness"
],
- "quirks-mode/supports.html": [
+ "quirks/supports.html": [
"cac590a930dab33ba0ab7981c31b868861931493",
"testharness"
],
- "quirks-mode/table-cell-nowrap-minimum-width-calculation.html": [
+ "quirks/table-cell-nowrap-minimum-width-calculation.html": [
"958b1856aa89ee5d5600163b22a75333be2c099e",
"testharness"
],
- "quirks-mode/table-cell-width-calculation.html": [
+ "quirks/table-cell-width-calculation.html": [
"b7a8466a3842237ddf9446bd3ab49de043001526",
"testharness"
],
- "quirks-mode/unitless-length.html": [
+ "quirks/unitless-length.html": [
"578d2aed4afa7cd6739610d353aebc591d832418",
"testharness"
],
@@ -566201,7 +573781,7 @@
"testharness"
],
"requestidlecallback/idlharness.html": [
- "970dac3de43bddedb88e22c438fc01f76a6b9a41",
+ "99fabb2abdc8aef189bd8c972a7501223517f932",
"testharness"
],
"requestidlecallback/resources/post_name_on_load.html": [
@@ -566252,6 +573832,10 @@
"b15a57e2eee61f2748bf758e6f3e06e84234f1e3",
"support"
],
+ "resource-timing/resource-timing-tojson.html": [
+ "643ce44bcf4a279853f07bde1abb376314e0b3bf",
+ "testharness"
+ ],
"resource-timing/resource-timing.html": [
"eb3e3064aa55df9ce9a0679a51d0b01d2fb63422",
"testharness"
@@ -566505,7 +574089,7 @@
"support"
],
"secure-contexts/shared-worker-insecure-first.https.html": [
- "81c9cd152b620dd70b11b72db021f4324dad16fa",
+ "7f227dd604a4568946475b5dfee87d04329fd169",
"testharness"
],
"secure-contexts/shared-worker-secure-first.https.html": [
@@ -566717,7 +574301,7 @@
"support"
],
"server-timing/resources/blue.png.sub.headers": [
- "7ae842dc0c2e6a26e68aea5867214eb2dbd2b08b",
+ "549289fb534722e17eea4477638e8da59e043c13",
"support"
],
"server-timing/resources/green.png": [
@@ -566725,7 +574309,7 @@
"support"
],
"server-timing/resources/green.png.sub.headers": [
- "827dfe4dedd1d3854048b1b13e336200a05cc0da",
+ "ed768e3cc679a1fef5c47088443fdaec83838394",
"support"
],
"server-timing/test_server_timing.html": [
@@ -566733,11 +574317,11 @@
"testharness"
],
"server-timing/test_server_timing.html.sub.headers": [
- "ffca8e9271c6760a63ca331c541799a537411994",
+ "77000d65537ef522a3471002118a120d2faf296a",
"support"
],
"service-workers/OWNERS": [
- "b74dce201157af7f50d382583674e1b979237f9b",
+ "84acd30c6a2c1cea23afd9f046ee5c34ae885828",
"support"
],
"service-workers/cache-storage/OWNERS": [
@@ -566793,7 +574377,7 @@
"support"
],
"service-workers/cache-storage/script-tests/cache-match.js": [
- "0204ef8205dd31a9af01b3dacd0f2608fa6eb35d",
+ "2e56e6185845e752fb828e20e2f1e10143c95073",
"support"
],
"service-workers/cache-storage/script-tests/cache-matchAll.js": [
@@ -566869,7 +574453,7 @@
"testharness"
],
"service-workers/cache-storage/window/cache-match.https.html": [
- "511502a763c53d3fd642aca9e1e1c0c4b610f8ce",
+ "43346c7dbd6592a33c35146d7ea6fa4495f9a353",
"testharness"
],
"service-workers/cache-storage/window/cache-matchAll.https.html": [
@@ -567032,6 +574616,10 @@
"f574c7a96a1ca766445cd0b427b9963b18c62795",
"testharness"
],
+ "service-workers/service-worker/about-blank-replacement.https.html": [
+ "345259908d040e4f5d810ae7089dab8a8c909b0a",
+ "testharness"
+ ],
"service-workers/service-worker/activate-event-after-install-state-change.https.html": [
"9d1971d9b5dcb52a14a0d2313065e27766c0489a",
"testharness"
@@ -567156,6 +574744,10 @@
"9c2e160f95d2915a961bd7da840ac53779c9387d",
"testharness"
],
+ "service-workers/service-worker/fetch-cors-exposed-header-names.https.html": [
+ "2013c1862eb3fd63187f570239a0cc64001fc34c",
+ "testharness"
+ ],
"service-workers/service-worker/fetch-cors-xhr.https.html": [
"448c071ddeaaaf828800d8fad20d8ce672e56590",
"testharness"
@@ -567188,12 +574780,16 @@
"ce7e7cf76aace24a92d455cdb6b54fc9048960e8",
"testharness"
],
+ "service-workers/service-worker/fetch-event-respond-with-custom-response.https.html": [
+ "fc304fa03a33021e4141d940835824883415279e",
+ "testharness"
+ ],
"service-workers/service-worker/fetch-event-respond-with-partial-stream.https.html": [
"c0e976149cf49c09f52b81159d2a48c301a4aa4b",
"testharness"
],
"service-workers/service-worker/fetch-event-respond-with-readable-stream.https.html": [
- "cf31c2b1cba37a016dc9e9a3ddb2429a5d518052",
+ "37c7959e58af70f3feea0f4fb46d778734a0296b",
"testharness"
],
"service-workers/service-worker/fetch-event-respond-with-response-body-with-invalid-chunk.https.html": [
@@ -567288,22 +574884,6 @@
"04eeedc3f074aff32281a438acda62b7a6d86e2d",
"testharness"
],
- "service-workers/service-worker/foreign-fetch-basics.https.html": [
- "6600d201f205fe3586cbfab088cf9f2be7d96b87",
- "testharness"
- ],
- "service-workers/service-worker/foreign-fetch-cors.https.html": [
- "aac5e2b6b096af5fb5edd9b8c5193774089afac2",
- "testharness"
- ],
- "service-workers/service-worker/foreign-fetch-event.https.html": [
- "8fbf910205f175a457846100deb34a01c02b00ab",
- "testharness"
- ],
- "service-workers/service-worker/foreign-fetch-workers.https.html": [
- "4838204f935a89eccb333e347dd56f30846460fe",
- "testharness"
- ],
"service-workers/service-worker/getregistration.https.html": [
"989c30567eb1dd650dc7e2bf807e18961c991087",
"testharness"
@@ -567316,10 +574896,6 @@
"95aee5b0d561467fb5da27f62210be9808539706",
"testharness"
],
- "service-workers/service-worker/iframe-sandbox-register-link-element.https.html": [
- "6cafc3245c88f7d96f6a4672b327d3b58ee4a0ee",
- "testharness"
- ],
"service-workers/service-worker/immutable-prototype-serviceworker.https.html": [
"5c17042fa54cd1fdba6f7aae513412d4a223b432",
"testharness"
@@ -567368,30 +574944,6 @@
"3c75caa66d3906602d10b07ff22e7d0f210cfee9",
"testharness"
],
- "service-workers/service-worker/link-element-register-basic.https.html": [
- "c38709eafae1c43fb6de9c90ad41634bfb749d14",
- "testharness"
- ],
- "service-workers/service-worker/link-element-register-mime-types.https.html": [
- "7f09c63104e39c76638e9193ac07e383ac0435ad",
- "testharness"
- ],
- "service-workers/service-worker/link-element-register-scope.https.html": [
- "c29407cfdce522c6a576d866ece6fffe831c85ac",
- "testharness"
- ],
- "service-workers/service-worker/link-element-register-script-url.https.html": [
- "f3920a47686a1e4792f097f52cf51531dccd58a8",
- "testharness"
- ],
- "service-workers/service-worker/link-element-register-script.https.html": [
- "9751dfe02dff339124352311115e61b19e7edf66",
- "testharness"
- ],
- "service-workers/service-worker/link-element-register-security-error.https.html": [
- "026a444eb0ff60e7885f70c7a4c3fa03a2510de3",
- "testharness"
- ],
"service-workers/service-worker/mime-sniffing.https.html": [
"d61a859a111dea758efb91480817fa1a029c152b",
"testharness"
@@ -567541,7 +575093,7 @@
"testharness"
],
"service-workers/service-worker/navigation-redirect.https.html": [
- "f8e79356467abba33e8008054c32baabc770fe65",
+ "109f463deeaad2d60d4dab644c782ad633e97a7d",
"testharness"
],
"service-workers/service-worker/onactivate-script-error.https.html": [
@@ -567577,7 +575129,7 @@
"testharness"
],
"service-workers/service-worker/postmessage.https.html": [
- "ea380417fcad1583f764473c554bf519e5beecde",
+ "dfd851992c1ab3be263bce6f669fceda47d0f410",
"testharness"
],
"service-workers/service-worker/ready.https.html": [
@@ -567604,14 +575156,6 @@
"864f5435fc40124dbe2c1ffb0e1942fee58228d2",
"testharness"
],
- "service-workers/service-worker/register-foreign-fetch-errors.https.html": [
- "785f0ea662160a5b7b3fe6a7580e62f793e100cf",
- "testharness"
- ],
- "service-workers/service-worker/register-link-header.https.html": [
- "fa97635d3a16a0f2a0a0bae8e4b81c8b5100d9cd",
- "testharness"
- ],
"service-workers/service-worker/register-same-scope-different-script-url.https.html": [
"2d337b2252fc4235830de53fcb3dc280d3aca82c",
"testharness"
@@ -567661,7 +575205,7 @@
"testharness"
],
"service-workers/service-worker/registration-updateviacache.https.html": [
- "90c97975a11fc639e775d26e9d0354d514ae7a9b",
+ "c1caf6840bc36eed4f4ece8e42702151e08b3754",
"testharness"
],
"service-workers/service-worker/rejections.https.html": [
@@ -567673,13 +575217,33 @@
"testharness"
],
"service-workers/service-worker/resource-timing.https.html": [
- "9ca1caf0b8216eda8956be0d98eb7b5ab2d92a43",
+ "a835a0baeb4fcc0c44e6be28502f89308464acc5",
"testharness"
],
"service-workers/service-worker/resources/404.py": [
"567d0a7de3ef54adaa8339bb04632a2ecfcc57a5",
"support"
],
+ "service-workers/service-worker/resources/about-blank-replacement-frame.py": [
+ "2f22a4c92cfb7c7e8cfbe6f168872c2f5875867d",
+ "support"
+ ],
+ "service-workers/service-worker/resources/about-blank-replacement-ping-frame.py": [
+ "d632f7a565cb9619db802bff4cbc61310f6ddf4d",
+ "support"
+ ],
+ "service-workers/service-worker/resources/about-blank-replacement-popup-frame.py": [
+ "498a08b652ec0d867e8d2e173be954f69354a208",
+ "support"
+ ],
+ "service-workers/service-worker/resources/about-blank-replacement-uncontrolled-nested-frame.html": [
+ "ab2ce3693bbc40943b7390c8d76f3601f52410ca",
+ "support"
+ ],
+ "service-workers/service-worker/resources/about-blank-replacement-worker.js": [
+ "487ea5fe465410ba3e88f3c8bd657009a99e6ad0",
+ "support"
+ ],
"service-workers/service-worker/resources/appcache-ordering.install.html": [
"2fbe9f464383783774f08276b8e2cc7103fee83c",
"support"
@@ -567777,7 +575341,7 @@
"support"
],
"service-workers/service-worker/resources/clients-get-worker.js": [
- "a48201939523eb5eb0357a8354f7770f44b941a0",
+ "bc72471e16df1507a2cebd4c32f7f995299ebd4e",
"support"
],
"service-workers/service-worker/resources/clients-matchall-client-types-dedicated-worker.js": [
@@ -567872,6 +575436,10 @@
"aee62d5b6ee22664c493036c879ed8d530b5ba1d",
"support"
],
+ "service-workers/service-worker/resources/fetch-cors-exposed-header-names-worker.js": [
+ "39aa0c0af84872b5910afd933bfb1642fc28a60d",
+ "support"
+ ],
"service-workers/service-worker/resources/fetch-cors-xhr-iframe.html": [
"604a64021a30d3cb9ecef7c3d8d6ec14bc75f5e8",
"support"
@@ -567908,16 +575476,16 @@
"b58b92a145a89f71c414de5e837c1db026beb1d6",
"support"
],
- "service-workers/service-worker/resources/fetch-event-respond-with-partial-stream-worker.js": [
- "6054d723ad0d0d310b02841b696d2357e7137398",
+ "service-workers/service-worker/resources/fetch-event-respond-with-custom-response-worker.js": [
+ "a5d0d55ccfa7c3c4c285153aa14b81ef205329c9",
"support"
],
- "service-workers/service-worker/resources/fetch-event-respond-with-readable-stream-iframe.html": [
- "16fe2d0f84bb7898f7a89182e24001b3bc64775e",
+ "service-workers/service-worker/resources/fetch-event-respond-with-partial-stream-worker.js": [
+ "6054d723ad0d0d310b02841b696d2357e7137398",
"support"
],
"service-workers/service-worker/resources/fetch-event-respond-with-readable-stream-worker.js": [
- "7f120661c9b24647f33dc41c36610ad3a1afef6a",
+ "052da5a0a6b26098fe745fd6d9ca8de0f4dfdc5b",
"support"
],
"service-workers/service-worker/resources/fetch-event-respond-with-response-body-with-invalid-chunk-iframe.html": [
@@ -567933,7 +575501,7 @@
"support"
],
"service-workers/service-worker/resources/fetch-event-test-worker.js": [
- "c8493c87ef1877a9a5dcb1335187233b78d44485",
+ "bba096216d8fbca6d4ddb6b7e9352a095a5e5db8",
"support"
],
"service-workers/service-worker/resources/fetch-event-within-sw-worker.js": [
@@ -568072,34 +575640,6 @@
"a557b92d3119f43bbbe10d46effc240d7f11c784",
"support"
],
- "service-workers/service-worker/resources/foreign-fetch-cors-worker.js": [
- "0bee2a7495fd8590c65fbdb10c02bb4024f729a9",
- "support"
- ],
- "service-workers/service-worker/resources/foreign-fetch-event-worker.js": [
- "7e9998ebcf657391c041d2904c06048214602ac2",
- "support"
- ],
- "service-workers/service-worker/resources/foreign-fetch-helper-iframe.html": [
- "42af5ea03adf25de9d5237a75e913ac726d72c3b",
- "support"
- ],
- "service-workers/service-worker/resources/foreign-fetch-helper-script.js": [
- "6c1d3bdec7490bec2581fb8936170be95cb3e692",
- "support"
- ],
- "service-workers/service-worker/resources/foreign-fetch-helper-worker.js": [
- "94061830f3d478ac53d9eeb03af662c3635f7860",
- "support"
- ],
- "service-workers/service-worker/resources/foreign-fetch-helpers.js": [
- "ce8886f4e8b8e97155c76f7b4e69f1b872c1e7dd",
- "support"
- ],
- "service-workers/service-worker/resources/foreign-fetch-worker.js": [
- "1464189c2e0ab1344227c69363aef9d44df98848",
- "support"
- ],
"service-workers/service-worker/resources/frame-for-getregistrations.html": [
"c5f88c11333ff1faba5d57812a36553d174ab711",
"support"
@@ -568108,10 +575648,6 @@
"b1a69bedbfbcb8f5b38d35f637f75f167d80118a",
"support"
],
- "service-workers/service-worker/resources/iframe-register-link-element.html": [
- "9ea5eb8893ae3d75c18566f5862c66df6bc831c0",
- "support"
- ],
"service-workers/service-worker/resources/immutable-prototype-serviceworker.js": [
"0a428649e0ceaaacdea5d156e829c63668bc3f72",
"support"
@@ -568152,16 +575688,12 @@
"fd486a19472f142bbd2909929a67ac3d39adc845",
"support"
],
- "service-workers/service-worker/resources/install-worker-helper.html": [
- "9682ae01719d07e5713307a26b1b825087c4cf65",
- "support"
- ],
"service-workers/service-worker/resources/interfaces-idls.js": [
- "ffb2cb87ff6a02509423027f254a7057c3cbb23f",
+ "c14274bca020d4dfe3df95e0fd36eedae403f99d",
"support"
],
"service-workers/service-worker/resources/interfaces-worker.sub.js": [
- "0ac0f813b692f2e6ab6a8337427427d1c33a128f",
+ "229dd043c0e98e9f70f54277bba7c4c3db6d000d",
"support"
],
"service-workers/service-worker/resources/invalid-blobtype-iframe.https.html": [
@@ -568196,10 +575728,6 @@
"3af11938ec23e1989785be2da453922686e5ace1",
"support"
],
- "service-workers/service-worker/resources/link-header.py": [
- "5717930bd579b9a63f1b3619195d65b46aa044cf",
- "support"
- ],
"service-workers/service-worker/resources/load_worker.js": [
"08525451705224fd78993adaed33a345d514c9a1",
"support"
@@ -568328,6 +575856,10 @@
"df15579b54fc14412435eee789c81a6523a394fc",
"support"
],
+ "service-workers/service-worker/resources/pass.txt": [
+ "27d2303f215d7d1a8f12f0b80b9b56a2cdf6c9a7",
+ "support"
+ ],
"service-workers/service-worker/resources/performance-timeline-worker.js": [
"fc275abc58d82c338ff369ba62994bd3d5609a67",
"support"
@@ -568372,10 +575904,6 @@
"18ee27c8d6a5497bf16b3315ba9eee2b474154b5",
"support"
],
- "service-workers/service-worker/resources/register-foreign-fetch-errors-worker.js": [
- "20cbfcd09c00c81c0a3c433a6257f62237fecd64",
- "support"
- ],
"service-workers/service-worker/resources/register-iframe.html": [
"b137bd995f0ca7b0ecc6ee6f5dc87a3a4e524364",
"support"
@@ -568424,8 +575952,8 @@
"c939271e717288203a5a298b95a7328100bd7c80",
"support"
],
- "service-workers/service-worker/resources/resource-timing-iframe.html": [
- "0fc85a13c536aad45a87fb073fdcebf371d4476d",
+ "service-workers/service-worker/resources/resource-timing-iframe.sub.html": [
+ "c18c96a25dec48ae9d53359d4ca987ba857878a1",
"support"
],
"service-workers/service-worker/resources/resource-timing-worker.js": [
@@ -568448,6 +575976,14 @@
"d2d9bf76453767aaaf7df973a26bd507b6ab42aa",
"support"
],
+ "service-workers/service-worker/resources/sandboxed-iframe-fetch-event-iframe.html": [
+ "57b43f9bb4a11505dd11c187134519d60bc7c026",
+ "support"
+ ],
+ "service-workers/service-worker/resources/sandboxed-iframe-fetch-event-worker.js": [
+ "f92786baf9a1ad0be21afd10f1343fd7220fd965",
+ "support"
+ ],
"service-workers/service-worker/resources/sandboxed-iframe-navigator-serviceworker-iframe.html": [
"b935f6d8fea362c4aceb713fcde91343d3e4bfa7",
"support"
@@ -568497,7 +576033,7 @@
"support"
],
"service-workers/service-worker/resources/test-helpers.sub.js": [
- "d1fae09808cce3b97e13ac73e7b781c5b51592a6",
+ "55acaa1edd73a39a834e1a1ee0952f47a03e3c78",
"support"
],
"service-workers/service-worker/resources/testharness-helpers.js": [
@@ -568568,6 +576104,10 @@
"e2e9b5d70f141e71f3617a11a336affea66662db",
"testharness"
],
+ "service-workers/service-worker/sandboxed-iframe-fetch-event.https.html": [
+ "04d08798c3d1b5b158951c4243a4ab68ebea42e9",
+ "testharness"
+ ],
"service-workers/service-worker/sandboxed-iframe-navigator-serviceworker.https.html": [
"1573ac5b39502f4b736d951e9fb781a348f4f70d",
"testharness"
@@ -568944,6 +576484,10 @@
"61f7da763fa4eb6f21077868caf0a07a4a9e44ae",
"testharness"
],
+ "shadow-dom/event-composed-path-after-dom-mutation.html": [
+ "69ea3efc8230a0ed31968f24379289c6691d77d1",
+ "testharness"
+ ],
"shadow-dom/event-composed-path-with-related-target.html": [
"6a5cbb21645faf8f18ed4b14799a6d01b326f998",
"testharness"
@@ -568957,7 +576501,7 @@
"testharness"
],
"shadow-dom/event-inside-shadow-tree.html": [
- "e468ca13b5a76659fc163010ece09b7708acdc1a",
+ "cffa15908bacddff66f5584490e28dcea02483e9",
"testharness"
],
"shadow-dom/event-inside-slotted-node.html": [
@@ -569025,11 +576569,11 @@
"testharness"
],
"shadow-dom/slots-fallback.html": [
- "d39644486f8c5307d8095cc32396ca146881320b",
+ "2899d1565ffcf998c24847e5b43f8e1f48a830a7",
"testharness"
],
"shadow-dom/slots.html": [
- "1eadf08acc6340f9ebd46d7df1ced3dedb1c5915",
+ "fdc26c0c0e8fa50ff4095e8acb273142edd01ce4",
"testharness"
],
"shadow-dom/untriaged/LICENSE": [
@@ -569356,6 +576900,10 @@
"6e5db2d0c2f5d2d8f1e2d04da953a3f2c50bec7a",
"testharness"
],
+ "storage/estimate-parallel.https.html": [
+ "6018a8d5ecb29b6c011b20a3afb38669e41f9323",
+ "testharness"
+ ],
"storage/interfaces.https.html": [
"76fa61c3a87485266a7f9d6f66e5d08bb7881ff7",
"testharness"
@@ -569365,7 +576913,7 @@
"testharness"
],
"storage/interfaces.idl": [
- "d3ac8afefe85ca580a514349060b8019f6fccc36",
+ "fe2e879ca5662f3b1714404734fd033faf3268ec",
"support"
],
"storage/opaque-origin.https.html": [
@@ -569701,7 +577249,7 @@
"testharness"
],
"streams/readable-byte-streams/general.js": [
- "4617fdb8c1ef68600f476dadcf47090100fc9ce8",
+ "8d37d5948078b71d3f80e3799ea0dd6d818e933b",
"support"
],
"streams/readable-byte-streams/general.serviceworker.https.html": [
@@ -569721,7 +577269,7 @@
"testharness"
],
"streams/readable-byte-streams/properties.js": [
- "4fd71882c2a1b8c35fb24a10599a6b90a0f32730",
+ "5eacc7507c71c43bb0f64dc8a7145cd9d3fda167",
"support"
],
"streams/readable-byte-streams/properties.serviceworker.https.html": [
@@ -569761,7 +577309,7 @@
"testharness"
],
"streams/readable-streams/bad-underlying-sources.js": [
- "f6eeb95c1eb3cf9d60cb7e8f1b44a4c460c5bbaf",
+ "ad4715f225949b4405dea61c0bff003d572e8afa",
"support"
],
"streams/readable-streams/bad-underlying-sources.serviceworker.https.html": [
@@ -569901,7 +577449,7 @@
"testharness"
],
"streams/readable-streams/general.js": [
- "e5ea14274f267ba4579627dd12b81e0863271328",
+ "72e37e692a88f6dd06f037f07e0d4fbd975f8aae",
"support"
],
"streams/readable-streams/general.serviceworker.https.html": [
@@ -569941,7 +577489,7 @@
"testharness"
],
"streams/readable-streams/tee.js": [
- "857f81daaf24847be71386d53ecc992820104683",
+ "c51e839b1d3075975c428f7a1bea4a8e36caec2e",
"support"
],
"streams/readable-streams/tee.serviceworker.https.html": [
@@ -570128,6 +577676,26 @@
"477cc1ed4cc94ff6ee29dcd6f96c16768a2c7567",
"testharness"
],
+ "streams/transform-streams/properties.dedicatedworker.html": [
+ "0d766237560b16ddb1bfcd02e701089132f1b3ec",
+ "testharness"
+ ],
+ "streams/transform-streams/properties.html": [
+ "82a278a1e8599b5bbd1ab8abadfb13d85f45aa5e",
+ "testharness"
+ ],
+ "streams/transform-streams/properties.js": [
+ "8bf21998fc6b9d26e79e1fdf541a2efb8f566d36",
+ "support"
+ ],
+ "streams/transform-streams/properties.serviceworker.https.html": [
+ "2ef8fc878249c429a89e0748e6a98fac47c1a99a",
+ "testharness"
+ ],
+ "streams/transform-streams/properties.sharedworker.html": [
+ "5c855e897d1143092ecc10b58268e6a576882184",
+ "testharness"
+ ],
"streams/transform-streams/reentrant-strategies.dedicatedworker.html": [
"6f9350ce1caf4fa9e6239693ec91b2249c2adab5",
"testharness"
@@ -570157,7 +577725,7 @@
"testharness"
],
"streams/transform-streams/strategies.js": [
- "7ec0963bacab2e94607efc4e171431643ba1d6ff",
+ "9535bb4835eb3124d1c621e11c4ae4b5dff08365",
"support"
],
"streams/transform-streams/strategies.serviceworker.https.html": [
@@ -570217,7 +577785,7 @@
"testharness"
],
"streams/writable-streams/bad-strategies.js": [
- "58cf46e9e07c61e2a7d170cb93837b9e16aa66e3",
+ "8eeca0627f291a0fd2ab6a21d882b66973a0502b",
"support"
],
"streams/writable-streams/bad-strategies.serviceworker.https.html": [
@@ -570237,7 +577805,7 @@
"testharness"
],
"streams/writable-streams/bad-underlying-sinks.js": [
- "d031fddb5a84f15c60e09416cd8d45609828691e",
+ "f09d495d577ff9904adbcfc4746acfd5f70860ff",
"support"
],
"streams/writable-streams/bad-underlying-sinks.serviceworker.https.html": [
@@ -570417,7 +577985,7 @@
"testharness"
],
"streams/writable-streams/properties.js": [
- "cc5f851c607b8dc681cbdacb20362689d7259dea",
+ "81af0a954d0c12677f28ea55636a3de5bf8d3cfa",
"support"
],
"streams/writable-streams/properties.serviceworker.https.html": [
@@ -570688,10 +578256,22 @@
"ce9e3471676d5a50b91f6b274d648b481e509223",
"support"
],
+ "svg/extensibility/foreignObject/properties.svg": [
+ "946999ca1917a5069103c025197c2903ab0bae64",
+ "testharness"
+ ],
"svg/extensibility/interfaces/foreignObject-graphics.svg": [
"16a7ef4c64dab3706120a2221dd6bec5ca8e9062",
"testharness"
],
+ "svg/foreignobject/position-svg-root-in-foreign-object-ref.html": [
+ "1dc201dc096298f81fd21646fd3bc018c127d0c1",
+ "support"
+ ],
+ "svg/foreignobject/position-svg-root-in-foreign-object.html": [
+ "c14ce9ff2df60975888de9c5cc31755325701d71",
+ "reftest"
+ ],
"svg/historical.html": [
"f18f89f68fdf1266768700235f08e7181ce0e0e1",
"testharness"
@@ -570821,7 +578401,7 @@
"manual"
],
"svg/import/animate-elem-33-t-manual.svg": [
- "b8b7fba97c72781ae8f4e383d72a1839d9981934",
+ "53612df3253d6eb90d6efefdaf1ec7eaee531fba",
"manual"
],
"svg/import/animate-elem-34-t-manual.svg": [
@@ -572897,7 +580477,7 @@
"support"
],
"svg/interfaces.html": [
- "3f659056fc469cb96bccd516a596fb183f005e9f",
+ "6045de5e5dc7810f89ca2c9a526f9e4380ae365c",
"testharness"
],
"svg/linking/reftests/href-a-element-attr-change.html": [
@@ -573008,6 +580588,58 @@
"1367de727c679521d6b7237b97b86c5516e9363c",
"support"
],
+ "svg/path/bearing/absolute-ref.svg": [
+ "6ad5320a05fcc31fd2af98d2bbd0bd6fbc558daa",
+ "support"
+ ],
+ "svg/path/bearing/absolute.svg": [
+ "e1c8d4bca5ab9519936a96521006baa176296c27",
+ "reftest"
+ ],
+ "svg/path/bearing/relative-ref.svg": [
+ "6ad5320a05fcc31fd2af98d2bbd0bd6fbc558daa",
+ "support"
+ ],
+ "svg/path/bearing/relative.svg": [
+ "75322c3ce1cc60339014301518a966e2e9f35360",
+ "reftest"
+ ],
+ "svg/path/bearing/zero-ref.svg": [
+ "8a192b68d131f467d291b277c55c205972db1738",
+ "support"
+ ],
+ "svg/path/bearing/zero.svg": [
+ "e7e8508ebb527e97e1f4e289652121b1d070c219",
+ "reftest"
+ ],
+ "svg/path/property/d-interpolation-discrete.svg": [
+ "6e27bfe4467b16b9e8c29bb66894bbb9dfbaf077",
+ "testharness"
+ ],
+ "svg/path/property/d-interpolation-relative-absolute.svg": [
+ "c67d063d92eb26e14138142a76b9b3640fb663bb",
+ "testharness"
+ ],
+ "svg/path/property/d-interpolation-single.svg": [
+ "566a60053980aad644e656029177f8a6026deb03",
+ "testharness"
+ ],
+ "svg/path/property/getComputedStyle.svg": [
+ "9914f645d2f34cf65cfad16b65d4308b9688e381",
+ "testharness"
+ ],
+ "svg/path/property/priority-ref.svg": [
+ "ee3fa5281b093737f014acae082fbfa5b66737a6",
+ "support"
+ ],
+ "svg/path/property/priority.svg": [
+ "c3f4fa37aaa87fb064a8962656e9ed53df4b1f8c",
+ "reftest"
+ ],
+ "svg/path/property/resources/interpolation-test-common.js": [
+ "b85e9086b134478e4c4b468cb19cc4e57aca06ae",
+ "support"
+ ],
"svg/shapes/rect-01-ref.html": [
"f22176bd9807ed4a8cb38ce8481e1aaaecd6bb9b",
"support"
@@ -573044,6 +580676,74 @@
"42ecd7bc94a3379d920687c79c12e2d3c55b9e98",
"testharness"
],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGClipPathElement.html": [
+ "0f81d16badaade09929ca0b35faf89cc420ef199",
+ "testharness"
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGComponentTransferFunctionElement.html": [
+ "22f7526c060cb0c83df59e428ed29cc2bce3ebf7",
+ "testharness"
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGFEBlendElement.html": [
+ "e6f4a72c37fe814031e2dcd41d6657f8fe7850db",
+ "testharness"
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGFEColorMatrixElement.html": [
+ "a553ecccebe90248889d6b8b9fc34938a99837d2",
+ "testharness"
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGFECompositeElement.html": [
+ "129e0acf47ece9eaee3c3e9ab261ff40e3821c06",
+ "testharness"
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGFEConvolveMatrixElement.html": [
+ "0324d2f34208aecc2f25a6d1bb9e4439dff2a1c5",
+ "testharness"
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGFEDisplacementMapElement.html": [
+ "771cad718da79e918777adb71b08252328ac0b0b",
+ "testharness"
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGFEMorphologyElement.html": [
+ "508373a8b938b92d92459a89b7eaae190c032f37",
+ "testharness"
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGFETurbulenceElement.html": [
+ "4b9b753ac3f8f376a46b049f6f19b102647a7763",
+ "testharness"
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGFilterElement.html": [
+ "4afbeed7802bc7fd7f9e0a0466d146c3de338c03",
+ "testharness"
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGGradientElement.html": [
+ "231b67d164deefa59e7bf8287bf3e74e592fdbb1",
+ "testharness"
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGMarkerElement.html": [
+ "456ed5965e68757c1856c82317f50320bb38bbe5",
+ "testharness"
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGMaskElement.html": [
+ "ba88d01b12250036cf43f9a868ddf32f277aa1f8",
+ "testharness"
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGPatternElement.html": [
+ "8d010c462455324b2acfccba1e6d1c09992c0692",
+ "testharness"
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGTextContentElement.html": [
+ "9b2b9a359f58adf8fc072e6291d2a3ebc0777dff",
+ "testharness"
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration-SVGTextPathElement.html": [
+ "e80379cf14711d78c7661684862139cecbca83ea",
+ "testharness"
+ ],
+ "svg/types/scripted/SVGAnimatedEnumeration.html": [
+ "b2c5c52669b802412b085529a2babf0ec2ec3ee1",
+ "testharness"
+ ],
"svg/types/scripted/SVGLength-px-with-context.html": [
"a605dba2368aa00a3cd3343739c05cdbbd930205",
"testharness"
@@ -573089,15 +580789,15 @@
"testharness"
],
"touch-events/multi-touch-interactions-manual.html": [
- "cb701ce5ebfd16c62b774334d5375bc8d5e68f51",
+ "c9f99610d07a8bc64512d2f309f404a8da4b99d2",
"manual"
],
"touch-events/multi-touch-interactions.js": [
- "0947ffb2a11a171d8396d23898c04dac11222594",
+ "ebd23ef9b71a949ba6f45a08b342ec569626fd82",
"support"
],
"touch-events/multi-touch-interfaces-manual.html": [
- "51ff04d8bd977ca94eb5a4e51f60affa5dc1ff50",
+ "ed96c462404889ad1115b8efb65226282ce058bf",
"manual"
],
"touch-events/single-touch-manual.html": [
@@ -573524,6 +581224,10 @@
"6b1d7bce96ca023959d5248aa8af0aa83c6d3aa5",
"testharness"
],
+ "uievents/mouse/layout_change_should_fire_mouseover-manual.html": [
+ "4e96209d99278b974347c6bd636454b0e7daf3c4",
+ "manual"
+ ],
"uievents/mouse/mouseevent_move_button-manual.html": [
"9cc673035fef3c2e8677e8d6679babfe8a1af854",
"manual"
@@ -573669,7 +581373,7 @@
"testharness"
],
"url/setters_tests.json": [
- "4b01281c0f8811cf57f261f9328d7916c52f3619",
+ "8d58bd1c98f4d987e6abe66659c812591b197e60",
"support"
],
"url/toascii.json": [
@@ -573741,7 +581445,7 @@
"testharness"
],
"url/urltestdata.json": [
- "d93eea5fddec950368ce502e2f895174b2b847f5",
+ "59d1f7c678f29a70df885bdfbf9d491899f0038c",
"support"
],
"user-timing/OWNERS": [
@@ -573993,55 +581697,55 @@
"support"
],
"wai-aria/alertdialog_modal_false-manual.html": [
- "754cdc408ed8152fa00cb22ae9148798e3b6f719",
+ "68c8a71cadc32818bf2f4ae2e1b5b06c3dfbc169",
"manual"
],
"wai-aria/alertdialog_modal_true-manual.html": [
- "1cc6b8748e46ffbeaaf19123d489895049831393",
+ "81119cf76329ec2e7134a77ea964ad29a31fd5c4",
"manual"
],
"wai-aria/application_activedescendant-manual.html": [
- "d8308fd422f658779a864616093e904e42c847da",
+ "14fa698d19749083c7f3ca357e554495f22248c9",
"manual"
],
"wai-aria/application_activedescendant_value_changes-manual.html": [
- "4e71505531d12c69f9a982712c1d67cef0ef0f48",
+ "898ce622e52ed46ce58b8923a757d4c0f0a1705a",
"manual"
],
"wai-aria/aria-current_not_declared-manual.html": [
- "06f2576c3fe1e9ac32c7a85cd5e40342a3a4f253",
+ "0f63350ee33dd244b71b5b076211d2bf0fa1b20a",
"manual"
],
"wai-aria/aria-current_with_value_changes-manual.html": [
- "e8b6e2e2e5f690867e3334f7c45a4724d00a757f",
+ "9278b8da982531f967d200c5dcbd3d374c78458e",
"manual"
],
"wai-aria/aria-current_with_value_date-manual.html": [
- "13bb4f08afdc600bf5b13d3264985bb7815a346e",
+ "5142568284f266a990aaac4d3be3cdb7774cd815",
"manual"
],
"wai-aria/aria-current_with_value_location-manual.html": [
- "7aa384eb87ce58bdfb9dc1d937b1c8d32b47d813",
+ "9c74ddcabcd68a3a33c4b722a951d548e7381cb2",
"manual"
],
"wai-aria/aria-current_with_value_page-manual.html": [
- "91847017d79ff79ddbdfe694e8fea0da78ac579d",
+ "3e52165dbf19d8b51740b21b56a9ac8da9f22dbc",
"manual"
],
"wai-aria/aria-current_with_value_step-manual.html": [
- "749b289dfb529cbfb3b356540086f463965aae55",
+ "aa1d055ed14a4801b5b750531227f3b275be90e0",
"manual"
],
"wai-aria/aria-current_with_value_time-manual.html": [
- "f49a8f3a2467ad3bc0dc3cbaaf9e1cfa31766be1",
+ "46c451ab94f2d7df1d86ae9d5e34b8a484582744",
"manual"
],
"wai-aria/aria-current_with_value_true-manual.html": [
- "ec3f2cd6a59d63f6efe753d2ab34293cec84173e",
+ "cce63c887ce3da546bcf14b2238c8ec27abfaf49",
"manual"
],
"wai-aria/aria-current_with_value_unspecified-manual.html": [
- "3b5b8471080a303f0eca9e872bcf72ae9f141561",
+ "4bcd84c4da792c0cc9bdf4f9e70b4e403af06c96",
"manual"
],
"wai-aria/aria-details_pointing_to_details_element-manual.html": [
@@ -574053,15 +581757,15 @@
"manual"
],
"wai-aria/article_in_feed_posinset_and_setsize-manual.html": [
- "9e09b859a5000bef790a60856cf5ca8e20766094",
+ "55b95ad109f110b888856193aeb949bbb48b2422",
"manual"
],
"wai-aria/article_in_feed_setsize_-1-manual.html": [
- "76452d5ae4d5945c45c9b7ebda1624af3eee591d",
+ "bc8588586ea12e4f6ea32bc993cb7e6820503273",
"manual"
],
"wai-aria/article_not_in_feed_posinset_and_setsize-manual.html": [
- "7f3b8130f9b8a421b48e25a67dd49a3760176d0f",
+ "ea70af19b8e0e3fc98b511161cabda07a9b1456d",
"manual"
],
"wai-aria/button_haspopup_dialog-manual.html": [
@@ -574101,127 +581805,127 @@
"manual"
],
"wai-aria/button_haspopup_unspecified-manual.html": [
- "ba242824494f6269d0d2c992037748bcd481953f",
+ "abaf3e93a69898fd35917fcc98d8828dfa1b99a0",
"manual"
],
"wai-aria/button_roledescription_empty-manual.html": [
- "854033b2e291d4ed0e8553906305073aa5062fff",
+ "17b0e96fad091190986d6329e57c0a4ec6f29059",
"manual"
],
"wai-aria/button_roledescription_valid-manual.html": [
- "609c9df2513fd3447ba7677e5fc8bef73d834847",
+ "eb0a2a85cddceeb1bd107a4e4d43cc9ddfae5fbc",
"manual"
],
"wai-aria/button_roledescription_whitespace_only-manual.html": [
- "b65b913b13e8065cb2dc3ec11fd9802ef7c1dddb",
+ "b6d27fa239c4031ad4bb9fb93fc0eccf391c244b",
"manual"
],
"wai-aria/cell-manual.html": [
- "0ec4a1d6fa6fe674fd59e8ee12119a26c0617d55",
+ "2369dfd3f4f5b8e6af8f325b547f13ecb9e28859",
"manual"
],
"wai-aria/cell_aria-colspan_2_on_div-manual.html": [
- "20ed3d7c616a5df83b7ccb5348a0ec8910ea14e5",
+ "9783e733d27321c5c3f84d863043fe0849412a68",
"manual"
],
"wai-aria/cell_aria-colspan_2_on_td_html_colspan_3-manual.html": [
- "b7a0f0c405f7054650888757ef2e2414777d147a",
+ "cba6254e6306b3647733b1823b1f5543fb6064a9",
"manual"
],
"wai-aria/cell_aria-colspan_2_on_td_html_colspan_3_with_headers_and_border-manual.html": [
- "a9c6472baa2a60c2405be20e6cdfb25321d71a35",
+ "8c1afae9c0188db50ce4205892d23aedf565cc52",
"manual"
],
"wai-aria/cell_aria-colspan_2_on_td_html_colspan_3_with_three_actual_columns-manual.html": [
- "f11c49f1db6d5246a3e14923a9bfadb1f2bb5ca4",
+ "3392bae47ac091fc13dde3b0f456956862b51779",
"manual"
],
"wai-aria/cell_aria-colspan_2_on_td_with_html_colspan_not_specified-manual.html": [
- "49a9a8d79c91b840d4fa7c652437f34508c27825",
+ "d3a95edb251182a03f3484052a037bb406185118",
"manual"
],
"wai-aria/cell_aria-rowspan_2_on_div-manual.html": [
- "766a462e63e40ede31b5bcb28dfe4160199e4d6e",
+ "cb4f984d568e04062c9088a60dc0aacf889ea673",
"manual"
],
"wai-aria/cell_aria-rowspan_2_on_td_html_rowspan_3-manual.html": [
- "a906e8899c1131aeb6d12fac8ba6021d3ac35531",
+ "25e0bd008d159211311ee22406364943a93d05cb",
"manual"
],
"wai-aria/cell_aria-rowspan_2_on_td_html_rowspan_3_with_three_actual_rows-manual.html": [
- "f977cc8e1100ca85b4251c2c08e7ed259c856e4f",
+ "752117c6c50282b6e63f31ca2ebe28471c94f333",
"manual"
],
"wai-aria/cell_aria-rowspan_2_on_td_with_html_rowspan_not_specified-manual.html": [
- "62fc9761f1df3c93d97915ccb0296a27c4847b91",
+ "1fe80df91327bd67d4a16cf48b4c6b20e04d10b9",
"manual"
],
"wai-aria/cell_colindex_4-manual.html": [
- "2951c871b311f443b3ef63119299a3b7d15494e9",
+ "41702551c72d187a2d3f0605923065aaa635b302",
"manual"
],
"wai-aria/cell_rowindex_4-manual.html": [
- "0237b24b6e6cbfd5e35c20ddd3358821d57ab243",
+ "5fc16311adf938a1c3961d3e27254061ceab2570",
"manual"
],
"wai-aria/checkbox_readonly_false-manual.html": [
- "2ccf421bea917a7081b0e07179189ad47193cbe4",
+ "058bb4a14ac1a1893e0acbe12e4e1476299940c9",
"manual"
],
"wai-aria/checkbox_readonly_true-manual.html": [
- "7d58401c763fa71fb51351948ce90c32d77bef06",
+ "725838c76624e45f116938df24308807b042e4c5",
"manual"
],
"wai-aria/checkbox_readonly_unspecified-manual.html": [
- "b9c43e4c8c1913c6cdfc1e18a6cb4a26bd470555",
+ "d024eb792e244e844972a729983a63ddba4762b6",
"manual"
],
"wai-aria/columnheader_aria-colspan_2_on_div-manual.html": [
- "0e259f88585602885fd753d9b3ce732f9d31a4a5",
+ "8af44c7fa3c79d6f414bf5ee927e423770dd066e",
"manual"
],
"wai-aria/columnheader_aria-colspan_2_on_th_html_colspan_3-manual.html": [
- "7b7d5ec0b8a57880e9699d590acb212f69245b42",
+ "099b9973f09a33a0976693c9410efa4824767780",
"manual"
],
"wai-aria/columnheader_aria-colspan_2_on_th_html_colspan_3_with_three_actual_columns-manual.html": [
- "2aa3893e949c87bd709273a0ef30e46147b8b2eb",
+ "bef87265d36cfa93b037746087e9074c44743641",
"manual"
],
"wai-aria/columnheader_aria-colspan_2_on_th_with_html_colspan_not_specified-manual.html": [
- "5dd455653d81c7cf1bd9aea69cffea8a0d7a4aaa",
+ "272c32c2f62d34a87a626f788ab428e71ad7b3e5",
"manual"
],
"wai-aria/columnheader_aria-rowspan_2_on_div-manual.html": [
- "c8ad953daf6925bc14e04ad76e947cd27dee5c7e",
+ "88e831f09c24bb87c250643b272955973244966e",
"manual"
],
"wai-aria/columnheader_aria-rowspan_2_on_th_html_rowspan_3-manual.html": [
- "beb80b0e82adf83da89213b9d1f7126560dad7e2",
+ "9e95976e9856c87c4aab9ec18cedc1c2b18b7413",
"manual"
],
"wai-aria/columnheader_aria-rowspan_2_on_th_html_rowspan_3_with_three_actual_rows-manual.html": [
- "08e65dcc8fe5e6b641f9dcaa71c3ba0c98ede206",
+ "6391733367e9dbffe58c784e510d02850a2b8837",
"manual"
],
"wai-aria/columnheader_aria-rowspan_2_on_th_with_html_rowspan_not_specified-manual.html": [
- "2ad181f5319b77d9db45fcbdabc8934cb9fa24aa",
+ "c8d79061be3616bef54668c6788b86e029ecf563",
"manual"
],
"wai-aria/columnheader_colindex_4-manual.html": [
- "8289dc10e5f66c304fc370119bc29aaaa3e8ed8a",
+ "b5754c7fd7f67bbd0fe304a3c492805c8c808407",
"manual"
],
"wai-aria/columnheader_rowindex_4-manual.html": [
- "fee6e82ce2af5dccdec2c730ea9988cbc3d4e1d8",
+ "761ee820e9284c1b37683155a9b372ed0d3652df",
"manual"
],
"wai-aria/columnheader_selected_false_not_automatically_propagated-manual.html": [
- "e869f2b1aa85c5e2e203d5521f9b08feb1f663ca",
+ "a5194b21acc10f7ce439cc2730cd2c14884905da",
"manual"
],
"wai-aria/columnheader_selected_true_not_automatically_propagated-manual.html": [
- "04f91ea9c7bc2376fcb510a692b35d2a5070b590",
+ "5a2daef90b1ef37b62f66802e3e4611657443510",
"manual"
],
"wai-aria/combobox_controls_an_invalid_id-manual.html": [
@@ -574229,75 +581933,75 @@
"manual"
],
"wai-aria/combobox_haspopup_dialog-manual.html": [
- "961821dd5ce25610394362df85805695295045bf",
+ "84712f94d0952c201ec3a510f07a5c30ea45fa90",
"manual"
],
"wai-aria/combobox_haspopup_false-manual.html": [
- "3f84b71eb40d187db111a82f0441d97cbc976a2e",
+ "cfd88ca222c07f255ed566c56660fc9681cce69c",
"manual"
],
"wai-aria/combobox_haspopup_grid-manual.html": [
- "018eb1a5e3acec237eaa2aff418b943e4db652e2",
+ "aa45fe6a5877bbfbe7a418513a5efe2279889313",
"manual"
],
"wai-aria/combobox_haspopup_listbox-manual.html": [
- "fb411bd4b8308fee78d6e1723b9de63751da4e1e",
+ "3e4c72e9b5601b834395a5dcd8c9e317e071f079",
"manual"
],
"wai-aria/combobox_haspopup_menu-manual.html": [
- "7becc965e84d0a68d15b3db779a7f9644bde46b4",
+ "c9a582516c3d701af6d73211315b713ac4f7953f",
"manual"
],
"wai-aria/combobox_haspopup_tree-manual.html": [
- "cca6e5a853d8609855cf1d230c174bc66abd5e86",
+ "c21fd5d22a2b9a6baa22a44bc5319412b35f89cd",
"manual"
],
"wai-aria/combobox_haspopup_true-manual.html": [
- "5586489253d14dba054db05683dfcaa0bb0da56a",
+ "5c37cccbe5a4a642d0344a61bf6949e0fb773fed",
"manual"
],
"wai-aria/combobox_haspopup_unspecified-manual.html": [
- "44e5de398426acb874cc1937e5183216ec35a712",
+ "2e7f0d5ed6da38621543c09019bbbab6e0a21a55",
"manual"
],
"wai-aria/combobox_orientation_horizontal-manual.html": [
- "5bcd8c6c417fd7893bd56f454d5c68ab39da454e",
+ "2c42a67ab05697533fae78a33406a9abd0397478",
"manual"
],
"wai-aria/combobox_orientation_unspecified-manual.html": [
- "38ce5005fbffaff4101e23118510309c044dc59b",
+ "59bbe7645fa43dcf8b05db1677fd4de4baf01e4a",
"manual"
],
"wai-aria/combobox_orientation_vertical-manual.html": [
- "b5c0f055a83c6ab23212c64f610c08def3e19e50",
+ "281ae8a1d54636527974d722341347e1c2df0d57",
"manual"
],
"wai-aria/combobox_readonly_false-manual.html": [
- "e7ddb2787f3cd24d722f41cbed0e46f1829a84fb",
+ "c0f42748cd164b12fb8b2a02afada5ecb88b93e0",
"manual"
],
"wai-aria/combobox_readonly_true-manual.html": [
- "a8ed48eb1686c4d7d36da309a76c772d894fd886",
+ "bc0c9f2f8bf72d41bdf94ed276e3ae58c5c988f7",
"manual"
],
"wai-aria/combobox_readonly_unspecified-manual.html": [
- "33d47bc7569c9deace942d36f85167af931943f9",
+ "c9d7c778a4249153fbd6ea7744e4231e3a4f58b2",
"manual"
],
"wai-aria/dialog_modal_false-manual.html": [
- "b4705c5d80e52baac15c0c068663a02a925660f0",
+ "58f1b7506b1b77d71943d9718584e961914dd746",
"manual"
],
"wai-aria/dialog_modal_true-manual.html": [
- "55dcbad3c1757ffa5fd666c4362ddbc499224064",
+ "db0066cf92f7eb9b2b209c078f5039992c4c1dab",
"manual"
],
"wai-aria/dialog_modal_unspecified-manual.html": [
- "a0405a2af36d1400d7a83aa2a5eeb6e92fdc1928",
+ "38fa5a8ff1627cbfb35978d190422eb2d50dab6d",
"manual"
],
"wai-aria/div_element_without_role_roledescription_valid-manual.html": [
- "a1878222bfe58fa9e40760d6ea8f362633875936",
+ "0856d271322865f790130e958c3f1529f7527e62",
"manual"
],
"wai-aria/errormessage_object_in_invalid_state-manual.html": [
@@ -574305,247 +582009,247 @@
"manual"
],
"wai-aria/errormessage_object_in_valid_state-manual.html": [
- "ee7427b441edad9bc599fd287860eb28a6e56f14",
+ "a8cbccf6b396b44067876244f98d0b62f83774f5",
"manual"
],
"wai-aria/feed-manual.html": [
- "5314038686453e25354d5444fcbdf5ad945cc965",
+ "1ec93583fcd22913d4650b23f93df495ba7eb940",
"manual"
],
"wai-aria/figure-manual.html": [
- "296f20edcfa4c2de5826af97e18b846b920c30a6",
+ "e082e00d346e721471f03b73374b4c38526be0a9",
"manual"
],
"wai-aria/grid_aria-readonly_false_automatically_propagated-manual.html": [
- "56b668db545c7b8cb1599c3d205b28218e19cf74",
+ "13716046d5ca45cb13583922b40fabc705672b21",
"manual"
],
"wai-aria/grid_aria-readonly_true_automatically_propagated-manual.html": [
- "d02baf60fcebee6dd6e52e4884c8bb4e6729cfc1",
+ "96b04b9751b434510f85bbcb61af7875318e80fc",
"manual"
],
"wai-aria/grid_busy_false-manual.html": [
- "1e2a8ede68c23c6b308253546c3d25619318a4d9",
+ "9f5aba26e274bfac88ca011fd67afeefd82dc573",
"manual"
],
"wai-aria/grid_busy_true-manual.html": [
- "8734b76e71476acf2c71f9bb7a714f890fd337cd",
+ "fbd73fad52937eaecc80cceb381f2c460d961234",
"manual"
],
"wai-aria/grid_busy_value_changes-manual.html": [
- "e5df53e46628117c5fe0e12d58334c845a9e404f",
+ "f419a3519d0c3355e9262c2a4468a327f54dbd8d",
"manual"
],
"wai-aria/grid_colcount_8-manual.html": [
- "b66693301f389b525ad6e933c5474505b56ab7b3",
+ "25a8241b4c86a07ab24d639bd7465246ed6e342a",
"manual"
],
"wai-aria/grid_columnheader_readonly_false-manual.html": [
- "2c4a43cd02609acc031d33eb4e689648370abd59",
+ "25d164213bf6bceb17d8c1592a9e32aaec8bc879",
"manual"
],
"wai-aria/grid_columnheader_readonly_true-manual.html": [
- "f935328efc9d08b5af2e10f1259963b416bbaae6",
+ "369312f28ca1c8686177e634a449b2bf5f0089d0",
"manual"
],
"wai-aria/grid_columnheader_readonly_unspecified-manual.html": [
- "4cc660c0363fa6a4d4ab7542ee60a8f3617be879",
+ "45d9897d73f16fdc19ac25e6a304836d503e044b",
"manual"
],
"wai-aria/grid_columnheader_required_false-manual.html": [
- "5b2b2bb0ec6562b83dbf6356e6569d8c8ecf5217",
+ "e40b2a1e0b14713978b55b16bb87bc597f4b8550",
"manual"
],
"wai-aria/grid_columnheader_required_true-manual.html": [
- "45d1ab83024a4c88fa16985c58fe99ff44a8c3da",
+ "7d3b2cdacc03e0e9b575c57009eefd13d9bdb784",
"manual"
],
"wai-aria/grid_columnheader_required_unspecified-manual.html": [
- "4f516fcd837222a86d2ecfb431b36361c73dc8a2",
+ "866dc8878b90126c09538726413c7f768ee48dd4",
"manual"
],
"wai-aria/grid_rowcount_3-manual.html": [
- "beb0b7e7c70aec7a1c40c6a04bc0d58aff45d874",
+ "47a0ce3042898e15e03ee2746b6586767e76066f",
"manual"
],
"wai-aria/grid_rowheader_readonly_false-manual.html": [
- "cab82961b14adc4c99e9321c0dc94b38eea2028a",
+ "69ecf3bb059feb1d33475b0b762f2db4a9e46aa7",
"manual"
],
"wai-aria/grid_rowheader_readonly_true-manual.html": [
- "9ebdaa97febbe584b1e44bf048a29814a24381ea",
+ "6f2e76bfbb203ab92ede1fd6de820a4037d79c4f",
"manual"
],
"wai-aria/grid_rowheader_readonly_unspecified-manual.html": [
- "c50f645b458fba36b881bc85474ea7b3c1710e45",
+ "6b0d9a86da3b08110240bf212312e0d2152b74ef",
"manual"
],
"wai-aria/grid_rowheader_required_false-manual.html": [
- "56f954adf8783d91ce550c71b876850a3ea19521",
+ "33520550b7acf017941c8e2c22c02e085849de21",
"manual"
],
"wai-aria/grid_rowheader_required_true-manual.html": [
- "bd031d825385c77efea8479087b407cae84164c0",
+ "85eb3649a12956bb0f06f23642899f526e1fe693",
"manual"
],
"wai-aria/grid_rowheader_required_unspecified-manual.html": [
- "0ce55c3222ff79ccfe99dbb18332fc67d96eaaa9",
+ "948edf09c08b89aa6e3d11d4539a56a23bf7a6af",
"manual"
],
"wai-aria/gridcell_aria-colspan_2_on_div-manual.html": [
- "1a7d9b0cc28bfaef446972e0fd42f4f51c4be3fa",
+ "e463c3b895a445aa3ddeff7f6d53b86be8f2d405",
"manual"
],
"wai-aria/gridcell_aria-rowspan_2_on_div-manual.html": [
- "44a9be247679dd52a94f28a1d5147c953867fad0",
+ "dd18af945e17147bb2b639831c92900c0ec5d9ef",
"manual"
],
"wai-aria/gridcell_colindex_4-manual.html": [
- "3f2cc5549c8c48bed4482eef4d15016a866a432e",
+ "a6c675d773c11685b6bdb9a52141f483779277a9",
"manual"
],
"wai-aria/gridcell_rowindex_4-manual.html": [
- "3ab620afeb2de8c158c1420949d151a2e98f061d",
+ "29615e12a755dedd0c486028ea58b7a4210953cd",
"manual"
],
"wai-aria/group_hidden_undefined_element_not_rendered-manual.html": [
- "862b7a9ba1a34dbf9346b2fedeeb52a1a5502784",
+ "5a83d0417dbc93b6795ea0bd4f58080dbf70b1be",
"manual"
],
"wai-aria/group_hidden_undefined_element_rendered-manual.html": [
- "2adf0911f14a94eccd19cc8fdf71c7dc2ee4a2e7",
+ "b7d21c9cd9ce418ad1e85c90a72aaea74350bf5a",
"manual"
],
"wai-aria/heading_level_unspecified-manual.html": [
- "08fb0566ab4c31b346e61359a4726df4e358f3b5",
+ "3776012458f8cbdce68e503f2a56e79512e7825f",
"manual"
],
"wai-aria/keyshortcuts_multiple_shortcuts-manual.html": [
- "f9dc1d5552aadb665b546fe8b72783220b431c8a",
+ "d2ac7049387ae7bd4f0d38dfca46e38b4d0a68f7",
"manual"
],
"wai-aria/keyshortcuts_one_shortcut-manual.html": [
- "2bab844538a414aa5abb4768d50923bff544fcb0",
+ "cf820ebb599b8097edb69be4c1551b24ab43a55f",
"manual"
],
"wai-aria/listbox_busy_false-manual.html": [
- "5569cc12e3b9d2b8fde247c790d72e11015ae78b",
+ "44b35c288b1ba06c5d1c59599ef2c8be6b14b61d",
"manual"
],
"wai-aria/listbox_busy_true-manual.html": [
- "10359f9d21d1fce801fcdd959a12cc5d3f959515",
+ "b20396f47215f777c5351ac998b8e7d438a341a0",
"manual"
],
"wai-aria/listbox_orientation_horizontal-manual.html": [
- "4eac9ea9de1faaf6b4edf0d39453ed0c142d8229",
+ "8d6f01eb9bbd232968163683d086f81dabd6e03d",
"manual"
],
"wai-aria/listbox_orientation_unspecified-manual.html": [
- "4429e641a1c432347fa0989f1b4a912c238f81fd",
+ "757b5f1983cfddce21316ffc6efc8c7d3b473245",
"manual"
],
"wai-aria/listbox_orientation_vertical-manual.html": [
- "3392029434e2f8a8e65fc06960e47f62c3d3224e",
+ "9f3b0e23df678ea853a38fd036708a5c99b1dad8",
"manual"
],
"wai-aria/listbox_readonly_false-manual.html": [
- "13f5c9c82beafb26b084dffbf9765cbc1b09a717",
+ "6f5fc88fbcd65713a2b11d2995efe4fefa6bcdad",
"manual"
],
"wai-aria/listbox_readonly_true-manual.html": [
- "133b4d223e1c74ef642b8d627c3f04b7742cd4df",
+ "a9bec885bc448239ce5fc4810d1ba1ce3b374f2c",
"manual"
],
"wai-aria/listbox_readonly_unspecified-manual.html": [
- "4f4e9ef883e7bf9d5e4c719cfec417a4ba427a55",
+ "d9f6aabfe918604ad7358f9cd5dbd0c8660e0d51",
"manual"
],
"wai-aria/listitem_setsize_-1-manual.html": [
- "bde65a9d5a00ceed56cbce667a541570100c7279",
+ "52df1676c1c1ffc3083c1f4660a70df8ac8c5dec",
"manual"
],
"wai-aria/menu_orientation_horizontal-manual.html": [
- "cb4012affde2f37218f511c11e92a24e987eba89",
+ "207ea1baeac038d05aa63b4acfb2b4bfee95a6a1",
"manual"
],
"wai-aria/menu_orientation_unspecified-manual.html": [
- "24903e47b6a6ae1be0a49df8a2ea2abfffd5cf72",
+ "8667ad48461e0d9c48d48fbb32f9bbd6113ea218",
"manual"
],
"wai-aria/menu_orientation_vertical-manual.html": [
- "e7be595d08ccb2f6e94f1c5e3bd66e74f07a04e6",
+ "4946be44782f6172c2d3453cbe206e49c0685665",
"manual"
],
"wai-aria/menubar_busy_false-manual.html": [
- "f036c27a389e2680551846a5def6a9d56d398a43",
+ "8a03b7ae3025ab854b322c12d528162e3467d030",
"manual"
],
"wai-aria/menubar_busy_true-manual.html": [
- "27a589285c997241c506cbb4aa2a05b546422e8d",
+ "51e683d83464e09e894b5c037da9aa4e812fa7e4",
"manual"
],
"wai-aria/menubar_orientation_horizontal-manual.html": [
- "f38cd16c8da078230397b8845b0584a087bd6a83",
+ "0dce46771c55df1e9f2f2b00ac958e3602340759",
"manual"
],
"wai-aria/menubar_orientation_unspecified-manual.html": [
- "6281641a562dc090ec2a31cb3569d3a0708b7ec4",
+ "bc4dc9287e5a95fdd3fed9199499f2b947d036ee",
"manual"
],
"wai-aria/menubar_orientation_vertical-manual.html": [
- "a9f61de067b3e926fb51fd0c0f1d8007ccc33857",
+ "c7115c655a70aeb4d35ce1f9eac9a2c687123758",
"manual"
],
"wai-aria/menuitem_posinset_and_setsize-manual.html": [
- "b444b779d3f65b58bed822e6cc1440828f63557a",
+ "5dce1f03cc4961eed0ec6813b42653a1229b5d7b",
"manual"
],
"wai-aria/menuitemcheckbox_posinset_and_setsize-manual.html": [
- "39781006ca59817acf455d556b8c76cd6b489445",
+ "b0f48dfef7fc382d75bc1aea29bfb15c6bc1940e",
"manual"
],
"wai-aria/menuitemcheckbox_readonly_false-manual.html": [
- "b8841fa91199dcc5662c06780d31cb8261ff92a6",
+ "d207839d0ef1761a186aeefff4d7fa53a0f41040",
"manual"
],
"wai-aria/menuitemcheckbox_readonly_true-manual.html": [
- "71b4785cf69375262139df7f18025f55d97774e6",
+ "b6c26c26e07770f4279c530ce3354b449ffe4bfc",
"manual"
],
"wai-aria/menuitemcheckbox_readonly_unspecified-manual.html": [
- "3359f715e3d96cadb2eaf8f07904caeaff36846f",
+ "f5435462f1dbaa7e2493b453b5183bbbea333fbd",
"manual"
],
"wai-aria/menuitemradio_posinset_and_setsize-manual.html": [
- "81ced2031a3f8119f415b6ade261dc47b4c54852",
+ "3cc12d0ddcddecbf870a3a0615914b4c4ca3a741",
"manual"
],
"wai-aria/menuitemradio_readonly_false-manual.html": [
- "ae7976e8c538e0e712f9ad91ad056a78c258df11",
+ "88fc3c5514fa07e2ad3641224a3ebbb61778b2e8",
"manual"
],
"wai-aria/menuitemradio_readonly_true-manual.html": [
- "1b1959ce48d2f765952210b507213e7842c57152",
+ "5e082185bd8bfacca8da1dd7b2d147a6b1c528e1",
"manual"
],
"wai-aria/menuitemradio_readonly_unspecified-manual.html": [
- "1ba57d551c68d52dc75748717106f7c1a30204c4",
+ "e3b521691a02724bef7025eecfac91b47a71875d",
"manual"
],
"wai-aria/none-manual.html": [
- "2d2a19bfb7d55f8cb69fd8cbabf10f9d43fc36f7",
+ "6f177f7c60f6063074cb7b22ff4798818a088a57",
"manual"
],
"wai-aria/option_selected_false-manual.html": [
- "a9236aa03abaef97f1af1d9f3011b76d36100487",
+ "147b98f2d89560a1c4ab30166ac7df25392ff751",
"manual"
],
"wai-aria/option_selected_true-manual.html": [
- "fc5f2c6ddb47c33d9e732e0de6a023b25a196618",
+ "1e96b25c9464122c2fdd55c491c8c5f4d8d5041c",
"manual"
],
"wai-aria/option_selected_undefined-manual.html": [
- "7c7f968fdcfbacf6e63aff45f89cfc283de7259f",
+ "48e855811cefd7ea8d7744db5031fe32321978c5",
"manual"
],
"wai-aria/option_selected_value_changes-manual.html": [
@@ -574553,27 +582257,27 @@
"manual"
],
"wai-aria/radiogroup_orientation_horizontal-manual.html": [
- "5b2f86e5454bf00e02c0b7a728524c7d7c30c55a",
+ "c373a9f15b9c108a03cec7662d92ca21b98cb006",
"manual"
],
"wai-aria/radiogroup_orientation_unspecified-manual.html": [
- "59b1f62489854443d46e1349f27261a36670fbe9",
+ "771cdca0240576bcc253df114799de995c81e0ad",
"manual"
],
"wai-aria/radiogroup_orientation_vertical-manual.html": [
- "a7c523b054a176f529b66b13bc26a987c7f9e5b6",
+ "efc922127513bda2d553331f33c4c077053b42e0",
"manual"
],
"wai-aria/radiogroup_readonly_false-manual.html": [
- "8ff1ac067d0d41ef96b629ecd66f00ed37ef9f27",
+ "be82d9478bf8d8f7292daaf0a53af4841c5a34a7",
"manual"
],
"wai-aria/radiogroup_readonly_true-manual.html": [
- "ab0a26eff7d0815ae76ca0ea38e57134703cfccd",
+ "b2bfef17fa599d5f25fac4811bbe43e615e117ee",
"manual"
],
"wai-aria/radiogroup_readonly_unspecified-manual.html": [
- "87bb3a459e24471da03f95c65ff283013e9bed83",
+ "0d4fc6e2740c3d8b0f20f4edd632637f5e7b9542",
"manual"
],
"wai-aria/region_with_name-manual.html": [
@@ -574585,35 +582289,35 @@
"manual"
],
"wai-aria/row_colindex_4-manual.html": [
- "28ca687e2b8da7e3dd2e0fcb3dfc0bb5ffb63840",
+ "d3db5c738273004b2390a0ff49a8637425968626",
"manual"
],
"wai-aria/row_rowindex_4-manual.html": [
- "35f2f062b8997476241dac74c1996aecb401c1bc",
+ "e668877bd45fc7d249ad8915671d738bf0646cc8",
"manual"
],
"wai-aria/rowheader_aria-colspan_2_on_div-manual.html": [
- "80d410187bb0a6384322f95bd27c967191fef80e",
+ "3a6b424100bc0e94a6970a18ff21a5be54931721",
"manual"
],
"wai-aria/rowheader_aria-rowspan_2_on_div-manual.html": [
- "af1896c0909c5c486a622f31a4a64a11cfa1bf1d",
+ "4b50fd0b4054963cfc2711e2b7c6987aba1ec75a",
"manual"
],
"wai-aria/rowheader_colindex_4-manual.html": [
- "a4468840e263a5bf7224e058e7099377f418fe09",
+ "84c0f043ee5f87fc478fce61055d8bf3c8bdc4a6",
"manual"
],
"wai-aria/rowheader_rowindex_4-manual.html": [
- "a832405f0127c6761ad76ffd5141e4361a85c4ee",
+ "f4b4d80cc2c804cd03f85db6e2f01408662922b1",
"manual"
],
"wai-aria/rowheader_selected_false_not_automatically_propagated-manual.html": [
- "4a57e83377abd3d66d3d8d26232e702b6b53e87f",
+ "1ac89c790fc77941821d5b25fa9f80bbc4512421",
"manual"
],
"wai-aria/rowheader_selected_true_not_automatically_propagated-manual.html": [
- "b5fbf74482276815c2df2d0bd78beadafd6bd804",
+ "adedbbf77b2b1881dc97e41365ede3159b7c0745",
"manual"
],
"wai-aria/scripts/ATTAcomm.js": [
@@ -574625,27 +582329,27 @@
"support"
],
"wai-aria/scrollbar_all_values_unspecified-manual.html": [
- "c6b90c5767929eb353fc0670886650562ee6eae6",
+ "4fe8f7a1640e7343ee583991b5bf93467aa2df52",
"manual"
],
"wai-aria/scrollbar_only_valuenow_unspecified-manual.html": [
- "4f501f675fe735b7d32929764beccb87648bf25b",
+ "476de611a9d3437254cbb75aafe0b74fc2eb40de",
"manual"
],
"wai-aria/scrollbar_orientation_unspecified-manual.html": [
- "951dc98f02cd790fa6fa0c540e4d03a3a88173ae",
+ "0b232b5bf4c14c11ae57f90b533cfbaae559a7ad",
"manual"
],
"wai-aria/searchbox-manual.html": [
- "0138026be588d9279fe7e086e1d672ef0266abde",
+ "feb163a6b4c81d6c76381aeae8048ed5578151bd",
"manual"
],
"wai-aria/searchbox_activedescendant-manual.html": [
- "1f7614531432509aaedc910bae517bfa3bb0867c",
+ "dd14675cec701d0f5c06c8bf03d5837aeebe9a7f",
"manual"
],
"wai-aria/searchbox_activedescendant_value_changes-manual.html": [
- "0e5e9c0947ba355f832d15609a3b8a73ba7a61ad",
+ "a8de5f8f1116e4009d158fc2e0c4dc2ebf0b30c5",
"manual"
],
"wai-aria/searchbox_autocomplete_both-manual.html": [
@@ -574665,199 +582369,199 @@
"manual"
],
"wai-aria/searchbox_autocomplete_unspecified-manual.html": [
- "e0a9bff6a5e9c0eec42f0e5e0f0ad905ff7ff953",
+ "a92974567bbb8a7762abbcc726393cad8ccece73",
"manual"
],
"wai-aria/searchbox_multiline_false-manual.html": [
- "699b2b06af38cd8be622ccc75b6d7fbe80ee0b6e",
+ "d75e8e7b1f0abee0ff159a5085d399c29c3b8973",
"manual"
],
"wai-aria/searchbox_multiline_true-manual.html": [
- "7bb4f2752ef7e03bb217e8e1b12f4a40b638bde1",
+ "ae24cec0788402b73330d86c80f0e1a91def537a",
"manual"
],
"wai-aria/searchbox_multiline_unspecified-manual.html": [
- "f2f175d68df0e97b598ed7a47d44a53cd87b5b19",
+ "492dc789fed40c60776f8dffa6022c7bb6ac5f36",
"manual"
],
"wai-aria/searchbox_placeholder-manual.html": [
- "0e92a02e93b59778595fc4b6d1847fad1040c924",
+ "e417f86e61db8cfcea05661654a53a6846c33f90",
"manual"
],
"wai-aria/searchbox_readonly_false-manual.html": [
- "fc1678fc0b32e648e8e7b9a7b63570b09ca8d360",
+ "074c62ee94902d39ae5c934f0e60efb9d7316e92",
"manual"
],
"wai-aria/searchbox_readonly_true-manual.html": [
- "adb59b597333f72b18ebd3f2a81832544254d9de",
+ "00c08ed1b329fd47a8c3f95147436c525e552201",
"manual"
],
"wai-aria/searchbox_readonly_unspecified-manual.html": [
- "65c71f924f6f39e7fea8176c4a3fc88fe188a8bd",
+ "ea8a4407904b1e3e0157007ac960cf2899a24c68",
"manual"
],
"wai-aria/searchbox_required_false-manual.html": [
- "24e7a5f334ae398fdd6f64233b3ce9211894cc5e",
+ "d0bc17a378163abe1763b868434a6e3f1b44f963",
"manual"
],
"wai-aria/searchbox_required_true-manual.html": [
- "c3e7a012036938ce5a4f4dc05a6f6bc0b7416b37",
+ "30dcd28acda9f5aa6554b63bd2a3017cbc1fa575",
"manual"
],
"wai-aria/searchbox_required_unspecified-manual.html": [
- "d34be4256f960a77708588f48ab1a9e79db9b60e",
+ "24e3b6cb84507de31c4583bb74752873eaa16258",
"manual"
],
"wai-aria/separator_focusable_all_values_unspecified-manual.html": [
- "f46996bb772c14320ea7e10cb8df4faf6bf9861c",
+ "eff36944c37a10d6aaef3667e6fb0dcd83eeb3ac",
"manual"
],
"wai-aria/separator_focusable_only_valuenow_unspecified-manual.html": [
- "8c559244f82b6d5ae1fc8ddacfb51d56cf26aa53",
+ "50270b9571dec5504619eed1b126d3930de113d1",
"manual"
],
"wai-aria/separator_focusable_valuetext-manual.html": [
- "09ab4cb8eaabb21f727965f880dc2b82c28a270f",
+ "46b37611b28860f380d4ae3ae5cf8e94f8ff58fe",
"manual"
],
"wai-aria/separator_orientation_unspecified-manual.html": [
- "9b453b2ca005003e705a0ee8449a16380220e67f",
+ "72cf219215e0f9602f305200b211d4b3f846e780",
"manual"
],
"wai-aria/separator_unfocusable_all_values_unspecified-manual.html": [
- "a9c2ed95d25b3bf5d80d1ddbbae44a16abadf235",
+ "de8a98e36d471c02024d5e51402f73ab4bd19747",
"manual"
],
"wai-aria/separator_unfocusable_valuetext-manual.html": [
- "f4a30a6c4302e52e626ac509d4f094d4b602f6ee",
+ "cb5ded5679f9dee5737bbe56aca270863885b9ed",
"manual"
],
"wai-aria/slider_all_values_unspecified-manual.html": [
- "d2db25aca78f1ceeefcdfffd12e7d2e1ef53faef",
+ "0a151a69f4b3eac15d9af37f65782ab63c9f80c6",
"manual"
],
"wai-aria/slider_only_valuenow_unspecified-manual.html": [
- "cd760f95d6c09bc1783c5b98511d3bffb03318f4",
+ "b9ef4db978d658eb6b3abd661987160cc845abb7",
"manual"
],
"wai-aria/slider_orientation_unspecified-manual.html": [
- "933b0fc2abab6066680289a7cab1fa0e301b2270",
+ "2ac72cd52bf16d3d82cd061297653110d5879be3",
"manual"
],
"wai-aria/slider_readonly_false-manual.html": [
- "ec57379556314d03d41b1ebc70452b00d5ab92e6",
+ "d8aa26c156de9f4a97a4a31cf115a570813811b8",
"manual"
],
"wai-aria/slider_readonly_true-manual.html": [
- "55beb79ef5f7022741306fea89f75a027b01abca",
+ "954d5fb2adc0429a240d48fb5c323e6228a30fc8",
"manual"
],
"wai-aria/slider_readonly_unspecified-manual.html": [
- "07ea9b783b15a51be94553da194f6b6db024433f",
+ "8a98ae32d296dc966833679d638dbaf7ae18995e",
"manual"
],
"wai-aria/spinbutton_all_values_unspecified-manual.html": [
- "729333014db5518140bb08f62975ab1c12a2f72b",
+ "cb8639bbf923f16a1d626e194e8ebfbbd684f9fc",
"manual"
],
"wai-aria/spinbutton_only_aria-valuenow_unspecified-manual.html": [
- "3730099c5a4509a410781c7f11ddac12f604a0dc",
+ "3674425097ac4819c6ba9c1177dfac2b4e561d69",
"manual"
],
"wai-aria/spinbutton_readonly_false-manual.html": [
- "44ee2f47d72e7f7df372f9841bd8049ab5696348",
+ "0403e092e86dcb6378453b0127a9b54e634b28de",
"manual"
],
"wai-aria/spinbutton_readonly_true-manual.html": [
- "78cbceb43c560e143a91b658bd8f050d9ab79883",
+ "47193688d79a6f9d46c22646b237a98eb5690fe1",
"manual"
],
"wai-aria/spinbutton_readonly_unspecified-manual.html": [
- "902d7279671f0ff0e4b73513af163e79ab0448e2",
+ "fbf40e53e2f991c6aaf515659bf71c6a090a92ac",
"manual"
],
"wai-aria/switch_checked_false-manual.html": [
- "9ee1f6b66ff6e43d213a8c996cd93c31b294b8d0",
+ "36c819b01b491f4ecdf6b84fd672699eb9c345b9",
"manual"
],
"wai-aria/switch_checked_mixed-manual.html": [
- "e5b099f54de006e948a935b8d98d911377b7ff31",
+ "f1a95385e6d02c40d8714fc0ae7c363ca92874e5",
"manual"
],
"wai-aria/switch_checked_true-manual.html": [
- "3366919521e536e6f9d3b6489c6a51d95f45b3e5",
+ "80360ed1af6019dbcf507ca9b2583f473ac292e5",
"manual"
],
"wai-aria/switch_checked_undefined-manual.html": [
- "5dfc172e54c67598ce4b0c0df1add788f9a99d5f",
+ "0cb7f30250e94a430a1d6a823dc56d123ff9a26d",
"manual"
],
"wai-aria/switch_checked_value_changes-manual.html": [
- "7f85dcd0690edb960ebd2b3adace2682ff614dd7",
+ "42f4203b9c3dda7512e628603c2989a096fb3200",
"manual"
],
"wai-aria/switch_readonly_false-manual.html": [
- "76e454316863a8c989b0ee5b2ccab7320674f3eb",
+ "8aaf6c375293c37f652b10de9887341c75aae74b",
"manual"
],
"wai-aria/switch_readonly_true-manual.html": [
- "3b54c61992fbdf640cd972a84a2ceb35be62ff17",
+ "35e4ed5ac27e810cfed0fc23383e1ca57663e0b5",
"manual"
],
"wai-aria/switch_readonly_unspecified-manual.html": [
- "95e6d14c9306e80b4415e3518d6beba1f6eaa08c",
+ "52979509b5daa2aa436e28d609dbb2e186e39320",
"manual"
],
"wai-aria/tab_posinset_and_setsize-manual.html": [
- "442fb6861b70e2566f758a9385a473aa6c15981f",
+ "561a5b5d3785e26252b633da3900fb88af0705db",
"manual"
],
"wai-aria/table_colcount_-1-manual.html": [
- "9ed42e5dc32bdbedfe1852ffd7cbd66ac37df0bb",
+ "b387f7abc0b1f6bb98ff075ff161dd73e0b694cc",
"manual"
],
"wai-aria/table_colcount_8-manual.html": [
- "d5aaadf2fecad13b133beea57edcd9f28543df75",
+ "2935a284b72da21579cf03dd6192becb85143f87",
"manual"
],
"wai-aria/table_rowcount_-1-manual.html": [
- "c96a3fb3b42852171d6f2bd8c49d34f287e90ed2",
+ "c537fa6393815df461dcf979fa2ffd2170e688db",
"manual"
],
"wai-aria/table_rowcount_3-manual.html": [
- "4bff8cd970877b57ddedcf1f71b40ded7dbd0a96",
+ "7a00f028a3fb4d57f27acdf0033120ac1621cc55",
"manual"
],
"wai-aria/tablist_orientation_horizontal-manual.html": [
- "8d28e4582bb14282f678d1864771ae454ca69891",
+ "2874e38a586fe85df586eb4f63fd1b47ee5b9691",
"manual"
],
"wai-aria/tablist_orientation_unspecified-manual.html": [
- "214c8fdb2eb888844f762d62e3551448d822fa35",
+ "0f476db12e0a08e8f9a59a92f91ce2321be8194e",
"manual"
],
"wai-aria/tablist_orientation_vertical-manual.html": [
- "273cf3ae78293cff630a04a90d7eac6aad2476a4",
+ "8114fc4112021e280b3ae0d4148099c9a274bbec",
"manual"
],
"wai-aria/term_role-manual.html": [
- "d7b1c0188f53083cfebd2d87c79b632396325169",
+ "8f6b3bfa5c5c2edcad6b5de867a957ffcd021999",
"manual"
],
"wai-aria/textbox_placeholder-manual.html": [
- "f9227242ec8f69d8380781be4be14c96f1a780af",
+ "d027578eb8bab6f98a45fa37ecebf54ddf7310bc",
"manual"
],
"wai-aria/toolbar_orientation_horizontal-manual.html": [
- "9134ff1b2b7d54ffdad94c777bd764f457e7b7c3",
+ "e1a0e1b40d281ccabfa66b50eb7c20c396d4c1e9",
"manual"
],
"wai-aria/toolbar_orientation_unspecified-manual.html": [
- "415df0e6f4e3873ef988cef4fe398bd32f825743",
+ "7b4b9bdc5997a34558b4db149ffd53f017933dbc",
"manual"
],
"wai-aria/toolbar_orientation_vertical-manual.html": [
- "53624df73eb9115bd3e57b8194d4bb23f8ce7d7a",
+ "dc6cf78657dacad6c2a547c07df672b147d03b2a",
"manual"
],
"wai-aria/tools/convert_wiki.pl": [
@@ -574869,47 +582573,47 @@
"support"
],
"wai-aria/tree_orientation_horizontal-manual.html": [
- "95a3a84f9380386ad8b0050d8aa227fe9e584e39",
+ "6a8bfea8cb1970f9b1a3db6cf226b1cf2028a1cf",
"manual"
],
"wai-aria/tree_orientation_unspecified-manual.html": [
- "9df862f7bc55d7d003b3607eae80b941e8f82d17",
+ "3561b3619dbc9e8f501eed1ba11a641748090b04",
"manual"
],
"wai-aria/tree_orientation_vertical-manual.html": [
- "9d43cbb3cd327485e5228b9fda834dacf08e31b3",
+ "76339d1518a278b4ee2f101fd3aec2d5d6d49736",
"manual"
],
"wai-aria/treegrid_colcount_8-manual.html": [
- "9022552296ca199d57141412c0ff0b147f8404ba",
+ "0570ea3de9fe899cd7f235dd594e84f286ed01e2",
"manual"
],
"wai-aria/treegrid_orientation_horizontal-manual.html": [
- "6265daaff71fc45f8ca14b9b6f197a1d412e3d30",
+ "3040b777d962f2bdfb45ee45a6a12df6faa9bfc7",
"manual"
],
"wai-aria/treegrid_orientation_unspecified-manual.html": [
- "bdb06eadbb33032340bf43359196a9b8631e258e",
+ "790b9a0ad5f7200b6ada1c6b2c8b809e3a0a8449",
"manual"
],
"wai-aria/treegrid_orientation_vertical-manual.html": [
- "1c7923e0c408a40d2cbd42a5b29a1c56ffa19f48",
+ "2cf7399d1a07559a25b24e9444dfca83797a1056",
"manual"
],
"wai-aria/treegrid_rowcount_3-manual.html": [
- "cd96f68e1a1b06d46023cae8dba0141d562b049e",
+ "7dd93febb3cf0264e0806146f24fc01bc65db093",
"manual"
],
"wai-aria/treeitem_selected_false-manual.html": [
- "325e783812c348e3b2797fbe3335057972bed6b0",
+ "f8415c67231925ead8b95d4c1d0b99e70631a118",
"manual"
],
"wai-aria/treeitem_selected_true-manual.html": [
- "cce5c060e2e7ad826dcce7996cf4496e48874085",
+ "036b95e2f0c9c94e95889486b98d778254c1a600",
"manual"
],
"wai-aria/treeitem_selected_undefined-manual.html": [
- "d8a7dacf9e21a1f5b25b4f17f575270cf593abcb",
+ "cbc6184c2b9cd7ee1e45a99b9aef9849b383fced",
"manual"
],
"wai-aria/treeitem_selected_value_changes-manual.html": [
@@ -574925,27 +582629,39 @@
"testharness"
],
"wake-lock/wakelock-api.https.html": [
- "a80557f44c8381495d80030ee8868153bfffd3da",
+ "7941cce9345916fbdafe3dd0b3edde680320b01c",
+ "testharness"
+ ],
+ "wake-lock/wakelock-applicability-manual.https.html": [
+ "bbed9a382c8e9a9a26f7690b06fdbffc5ef4a794",
+ "manual"
+ ],
+ "wake-lock/wakelock-cancel-twice.https.html": [
+ "a9850a6eb525af1c37e06686df1b8a075f2456f8",
"testharness"
],
"wake-lock/wakelock-disabled-by-feature-policy.https.sub.html": [
- "5ba667dc3f35e64b39be7cc938cf1cb93fc6f464",
+ "d3786da8619cfc0409f979235af29e587e4c41bc",
"testharness"
],
"wake-lock/wakelock-disabled-by-feature-policy.https.sub.html.headers": [
"199fe1ce290a8570204cc58027f7b808d7ef3500",
"support"
],
+ "wake-lock/wakelock-document-hidden.https.html": [
+ "ae8838e5fb164218f7dbf431546ed20b820f7c0c",
+ "testharness"
+ ],
"wake-lock/wakelock-enabled-by-feature-policy-attribute-redirect-on-load.https.sub.html": [
- "bba2a95be9eeba9a4b67a9db92dc7d793fc26759",
+ "6f7fd8d684092ad53058a2bdfe4ae4070a18e290",
"testharness"
],
"wake-lock/wakelock-enabled-by-feature-policy-attribute.https.sub.html": [
- "37f30f21addedbe30955eefe22f65302a2a97ed5",
+ "ca6f005d18f1193fc1bc141d58e76248e93b66d8",
"testharness"
],
"wake-lock/wakelock-enabled-by-feature-policy.https.sub.html": [
- "ee3386a75ce86ebec42032712acde03ebc064eda",
+ "98b988fc7fd156c756c4c430f2c50cd0110a124a",
"testharness"
],
"wake-lock/wakelock-enabled-by-feature-policy.https.sub.html.headers": [
@@ -574953,23 +582669,35 @@
"support"
],
"wake-lock/wakelock-enabled-on-self-origin-by-feature-policy.https.sub.html": [
- "328c6459efefdb2ed1f33522c8c51c5aa2aa1496",
+ "f928dc7732050e52152ccfb1c5a9a4282216b70f",
"testharness"
],
"wake-lock/wakelock-enabled-on-self-origin-by-feature-policy.https.sub.html.headers": [
"7a77973dc947ef10abe33be288fd610c42d96e97",
"support"
],
- "wake-lock/wakelock-object-is-independent.https.html": [
- "b104d9af062710134b69474008b583706eee7978",
+ "wake-lock/wakelock-insecure-context.html": [
+ "527a75868eab39b899113cae81601630f9850790",
"testharness"
],
"wake-lock/wakelock-onactivechange.https.html": [
- "c85d61aca951edc5378028c1c120222683744de6",
+ "cbf4c5d6351e01ccc1a3e0e3e05afb16968a7edd",
+ "testharness"
+ ],
+ "wake-lock/wakelock-promise.https.html": [
+ "2cf40b55e8875b3d2d0dc215f0547e9fc8c23389",
+ "testharness"
+ ],
+ "wake-lock/wakelock-state-is-global.https.html": [
+ "7a8179b74d81b3ebda85aa440c183358b0ebe50b",
"testharness"
],
"wake-lock/wakelock-type.https.html": [
- "6fac8079855d7aedb52aee508cb866de51c41c0c",
+ "583647213b49b7bc67cad08192db3e6abcd1de9f",
+ "testharness"
+ ],
+ "wake-lock/wakelockrequest-is-independent.https.html": [
+ "caaf2634451eb9228c0b20f0ac817d7a3d3fa685",
"testharness"
],
"wasm/compile_worker.js": [
@@ -574985,7 +582713,7 @@
"support"
],
"wasm/many-memories.window.js": [
- "591b015662a6d181677892ec9c87f39bb36bbc23",
+ "84e98a89e653c39dab16e096286457268dccd195",
"testharness"
],
"wasm/resources/blank.html": [
@@ -575021,7 +582749,7 @@
"support"
],
"wasm/wasm_local_iframe_test.html": [
- "dd715a4da792b9d8d634536d938b278230c66df5",
+ "e7b86a731b7cf7c122a1e37118cebce7342291fc",
"testharness"
],
"wasm/wasm_serialization_tests.html": [
@@ -575045,239 +582773,235 @@
"support"
],
"web-animations/README.md": [
- "d6cb0e31dc3cc6d83b5051cee38a0b8e118fd43f",
+ "6344565e53b2f9e8d6ee7658d1c5c5670e68fc98",
"support"
],
"web-animations/animation-model/animation-types/accumulation-per-property.html": [
- "316dd15ce99cbfb5754c236210ac9e04dfc0c7ba",
+ "b26f3961d1913de731906ff0eed9a8548df7bbb2",
"testharness"
],
"web-animations/animation-model/animation-types/addition-per-property.html": [
- "24fae46b5f7b47e1d098fa446037bf9cc52e050e",
+ "c16ee3be3338bd5831ff3eab455cbf6943aa8d5b",
"testharness"
],
- "web-animations/animation-model/animation-types/discrete-animation.html": [
- "5a63e9f2a369a476f56e3b792928083e83fab7ec",
+ "web-animations/animation-model/animation-types/discrete.html": [
+ "f3e48d8ddd42f1eecb36af2a8e1cfade6d0a02d4",
"testharness"
],
"web-animations/animation-model/animation-types/interpolation-per-property.html": [
- "55100f7d505bc8cbc966ced0d1337ed78534a553",
+ "2bcb2919b3034042d8a61d7af5de099a42386451",
"testharness"
],
"web-animations/animation-model/animation-types/property-list.js": [
- "6a1aafd6077aa656cfba4bba48f7ceca8344b810",
+ "7f20ed34cf9c72b53db3206639367eff69f0e226",
"support"
],
"web-animations/animation-model/animation-types/property-types.js": [
- "4b9e06fc9014110a711c590f866a149d31a9a6fa",
+ "ceaeb9c4a67019e68423f7cde888067c3384d756",
"support"
],
+ "web-animations/animation-model/animation-types/visibility.html": [
+ "da3370704ca9e83a1171a64320a240e3145fab2c",
+ "testharness"
+ ],
"web-animations/animation-model/combining-effects/effect-composition.html": [
- "8ac06085132d822e908d48de4c1109b66323f19f",
+ "5d6c3904de02eb3b6c890163ccdc6b8cb6499e56",
"testharness"
],
"web-animations/animation-model/keyframe-effects/effect-value-context.html": [
- "10d9ee521240475a1729c2facfcea8b50342614e",
+ "da405e4bfc35d5d0b4c151706b09eb1a84d2f0da",
"testharness"
],
- "web-animations/animation-model/keyframe-effects/effect-value-overlapping-keyframes.html": [
- "a79db70a385ad767263f285c9401b66611087e42",
+ "web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html": [
+ "bda186b311457e58c48ca5cf4619f485a41f8e2d",
"testharness"
],
- "web-animations/animation-model/keyframe-effects/effect-value-transformed-distance.html": [
- "a0f0dc7d2f4833a68c6f8a5f908c498b05c6b22e",
+ "web-animations/animation-model/keyframe-effects/effect-value-overlapping-keyframes.html": [
+ "2b10d6fb1cb925290caf57e4cefc3c3f8161777c",
"testharness"
],
- "web-animations/animation-model/keyframe-effects/effect-value-visibility.html": [
- "b01c7c5145c183fdca80dec4ca1966b0f72a7003",
+ "web-animations/animation-model/keyframe-effects/effect-value-transformed-distance.html": [
+ "8fd7dbbaf98947f8101c760e41d9cc909c844d2d",
"testharness"
],
"web-animations/interfaces/Animatable/animate-no-browsing-context.html": [
- "3a5538db728127970721e20e3b2eaea59fac3afc",
+ "5c30bc76f60eb479cba967f91c6a80af7df8e2e7",
"testharness"
],
"web-animations/interfaces/Animatable/animate.html": [
- "99868d179c69091aa63631a27d98df4ee957a746",
+ "8d76a26de47494600da40e756a26de61329ff3aa",
"testharness"
],
"web-animations/interfaces/Animatable/getAnimations.html": [
- "92503fce725fcffce188df9c8e1da9d9ca281213",
+ "9c03f9a6410dc8463a3e3acb3b6e38c26d79b097",
"testharness"
],
"web-animations/interfaces/Animation/cancel.html": [
- "a28589129c6a2665295695f786b7beb2dd887fb3",
+ "38d509e24fa224fc8b937e4a63dd1c404e72b466",
"testharness"
],
"web-animations/interfaces/Animation/constructor.html": [
- "20604949fc295efc398e297b9e4f755a116f0fbb",
+ "f4dc4fdca61255557ed346412e134745bce1a3ed",
"testharness"
],
"web-animations/interfaces/Animation/effect.html": [
- "9e2551bfd9238ff99f30eabbd119a05fcf6dbeb9",
+ "4445fc8bd2120fb1e212dfc6a1fcf786a531ee6f",
"testharness"
],
"web-animations/interfaces/Animation/finish.html": [
- "61ab2a2d822c25f2311756baeaaa98b44c3b3a62",
+ "64acecec8528b4d241d5dcb9248ef82eafa02810",
"testharness"
],
"web-animations/interfaces/Animation/finished.html": [
- "5e3d8fa48b2737202f6bd7c2e21589e904982a6f",
+ "ffcba3379db7094455a7798e4d5972d8e52caec5",
"testharness"
],
"web-animations/interfaces/Animation/id.html": [
- "395dad4a877ef4af20649d6bcfece102a22b3059",
+ "4e3dd92351d76c5c7d09ddd1ca025520f4c8875d",
"testharness"
],
"web-animations/interfaces/Animation/idlharness.html": [
- "b9784215a32d3d00d9a2c17c115ec9048d67c779",
+ "989e773dbf3d7d57f26b41108bc3d7f0b3ea3168",
"testharness"
],
"web-animations/interfaces/Animation/oncancel.html": [
- "0477d2fef7fc64bbc969b29d4ba542574c4c3706",
+ "82abc08a0b416f5198239464fb4fc01d2edd6e1c",
"testharness"
],
"web-animations/interfaces/Animation/onfinish.html": [
- "43ecf628f6e7a6088ad4cc25e3a6468957049ae0",
+ "db82fabeaf2b646647f134634fef30f05e5ec7f8",
"testharness"
],
"web-animations/interfaces/Animation/pause.html": [
- "8cadcbc313fd6ed171298529c71d555cc2c43a2d",
+ "f044cc7ac09c38f127e399f7d6f9a0714046aa8e",
"testharness"
],
- "web-animations/interfaces/Animation/play.html": [
- "0c8069de75d1c15f1d8167b433ad4c7e51f424db",
+ "web-animations/interfaces/Animation/pending.html": [
+ "5677f7e8b076dc096d636aaaa4d4191c286f1d90",
"testharness"
],
- "web-animations/interfaces/Animation/playState.html": [
- "9dda649e8c668b4afbc6e683e2d853622650796a",
+ "web-animations/interfaces/Animation/play.html": [
+ "54edbdd6c0e1953f8d0e2bfbb92bfe318114ab74",
"testharness"
],
"web-animations/interfaces/Animation/playbackRate.html": [
- "d0c73c24ed6ea6d43565ef81a3b200336a2133cd",
+ "27d289f603953b3e39322287fb2a55f84dd8dc54",
"testharness"
],
"web-animations/interfaces/Animation/ready.html": [
- "b23b76881f4d38c07710d0e59c1f6c8569de9060",
+ "bd4a18205791b2b0271a6266dba3ebc8482c835b",
"testharness"
],
"web-animations/interfaces/Animation/startTime.html": [
- "284d55c141e4a93def32393577888ffc215a8b15",
+ "01f669542434f03d37e9f148a4f3135fe3122d46",
"testharness"
],
"web-animations/interfaces/AnimationEffectTiming/delay.html": [
- "ee2d870fae13e77e500e7067b89dbb79bd2d209a",
+ "4de5b0a692d645961de27df67efa8257adb0a031",
"testharness"
],
"web-animations/interfaces/AnimationEffectTiming/direction.html": [
- "87eb8b9a7b954e0eb77566eefb3034cd6235296f",
+ "11398d5ea40bb4137b4f5d4e6e6238af64caf3c5",
"testharness"
],
"web-animations/interfaces/AnimationEffectTiming/duration.html": [
- "54858f64784c74a3d112e559fb765a1dbb9ba279",
+ "315810a1e73f9b4ef2cffea868fb766af5ee5c93",
"testharness"
],
"web-animations/interfaces/AnimationEffectTiming/easing.html": [
- "a4b8b1c715795d5e66c0e32c2415a2e8fb587147",
+ "b3ad4c78c9bce0e17db0ce780cd1260de1ce7cb0",
"testharness"
],
"web-animations/interfaces/AnimationEffectTiming/endDelay.html": [
- "fde46c549f70439c80e3990ebf6897d6d6dfb76e",
+ "b36d9c8a4e4082e6a75ac5d8f336cf474cd75aab",
"testharness"
],
"web-animations/interfaces/AnimationEffectTiming/fill.html": [
- "adc56d3ce3595154045cb87e1cb89fe7ce2096ba",
+ "1cef601cde33eea3b591a0826ad52f379bb31d0d",
"testharness"
],
- "web-animations/interfaces/AnimationEffectTiming/getAnimations.html": [
- "83175d02d1a09e91189fab2ccb19f8e0f242cb2a",
- "testharness"
- ],
- "web-animations/interfaces/AnimationEffectTiming/getComputedStyle.html": [
- "28819fe9fe3d38ae6d4aa2b4db4f58e8a16f0588",
+ "web-animations/interfaces/AnimationEffectTiming/getComputedTiming.html": [
+ "020e9faaae05de5a25829a05558ea72672b04f63",
"testharness"
],
"web-animations/interfaces/AnimationEffectTiming/idlharness.html": [
- "a4e72d3ebf93a0bb6934f887c3da250a2ab67b63",
+ "aa9823e5a06c76921b49aa5f5e61fd1dedfac3af",
"testharness"
],
"web-animations/interfaces/AnimationEffectTiming/iterationStart.html": [
- "05e327706937df8319e3a8c655ee743a15902ecd",
+ "734743adeec628da907ea2f6cc4ae3be3aab7329",
"testharness"
],
"web-animations/interfaces/AnimationEffectTiming/iterations.html": [
- "9a6eae75862dec36b7839dc68edc31891a651284",
+ "c8705eb209d8a4912b5d3fd94a05c763b7707eca",
"testharness"
],
"web-animations/interfaces/AnimationPlaybackEvent/constructor.html": [
- "1bc5f4dda96078a08a4b06ab0f6bf7b10e0acce3",
+ "5aff03b7fa469e5ec0dc02a389eca963ae24b470",
"testharness"
],
"web-animations/interfaces/AnimationPlaybackEvent/idlharness.html": [
- "37bd201a374913d0cd580b89b07688b5b655776d",
+ "bfdfc896fb5fe4451419464e35fe94b5e4938c2c",
"testharness"
],
"web-animations/interfaces/Document/getAnimations.html": [
- "bd39d7f28dd03ba22a32ce09226dc263180254eb",
+ "12fdbce3e75f5a7d7771d9337089255ef73f9712",
"testharness"
],
"web-animations/interfaces/Document/timeline.html": [
- "65303d138e6b9afdb5b28117ef8e1c6ba35903e3",
+ "2577a2d5c89fa0eec3cae2fd07b66e576ee6a483",
"testharness"
],
"web-animations/interfaces/DocumentTimeline/constructor.html": [
- "3a626b145f4eb77e816b9020f6fc67630088a00b",
+ "b11caf0a1766818a168a7f91b01ccd6ae9a7e4f0",
"testharness"
],
"web-animations/interfaces/DocumentTimeline/idlharness.html": [
- "fde7ae3f320a94619c9bb879d77d1de392212846",
+ "72cb7900f86611e9c2a1b0f4acd0f634555310b9",
"testharness"
],
"web-animations/interfaces/KeyframeEffect/composite.html": [
- "2580086b2da9b29d1645484c5ad4e59636a370e5",
+ "7dd18327d8da81914adaf443086891ba3646d882",
"testharness"
],
"web-animations/interfaces/KeyframeEffect/constructor.html": [
- "54a4185fd23ac4b3afe010157d4b8b766483d8f6",
+ "4a80ea073da0a9c62dcb9587676445a2fba234e1",
"testharness"
],
"web-animations/interfaces/KeyframeEffect/copy-constructor.html": [
- "65047bfed537a69659851a9fcdd7fb2ba5c4f790",
- "testharness"
- ],
- "web-animations/interfaces/KeyframeEffect/getComputedTiming.html": [
- "c9dcf7c17010e5495007e000b33aeb4dc89f92b7",
+ "6ef462ddc696269f132d596188ffd5e8da1e1164",
"testharness"
],
"web-animations/interfaces/KeyframeEffect/idlharness.html": [
- "d51dfde748bfdf12a1b06452099ea74fe2951a34",
+ "f05c9bd1cdee77ff6be143b0eb4f982c7218908b",
"testharness"
],
"web-animations/interfaces/KeyframeEffect/iterationComposite.html": [
- "2ed50cdb27335345015d8b13c64ef86c67048757",
+ "65cd746596a6770d1101b030769712be433bf6f3",
"testharness"
],
"web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001.html": [
- "83e58d986208b6cbc51e4124a2b17269a26e0520",
+ "165b651cea12ab9e0825f4335e7f697ce1fc6247",
"testharness"
],
"web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-002.html": [
- "38b350320a08cc2a9ae4449944eea427bfbe6f9d",
+ "e9237e244034845f6f902f8149a0e66e5b6164f2",
"testharness"
],
"web-animations/interfaces/KeyframeEffect/setKeyframes.html": [
- "477e983fcef02361c305918d10a67f2909cfa561",
+ "a346e0e004010a6f51e06ffd30d0b6eddd45421d",
"testharness"
],
- "web-animations/interfaces/KeyframeEffect/setTarget.html": [
- "8c75e6605a134c96e261e5383414b7e15b32d121",
+ "web-animations/interfaces/KeyframeEffect/target.html": [
+ "94bad3b00de7591e9faa7bd479a457b7b76f76b5",
"testharness"
],
"web-animations/resources/easing-tests.js": [
- "c255d606d00296b4c6957435773a20a9d8d0bd0b",
+ "77f747cef865fd5eba6ea621881706f801c812c0",
"support"
],
"web-animations/resources/effect-tests.js": [
- "5cdc52caac1d1db2249155e91591c983a746102e",
+ "2eb26f4cb0e65282b8e82014ac8ebe87a4209c6a",
"support"
],
"web-animations/resources/keyframe-tests.js": [
@@ -575293,79 +583017,83 @@
"support"
],
"web-animations/testcommon.js": [
- "d057ad66c4561ef32f83770e4948f2019da89d48",
+ "94130b39fda8e95ca495d297f9d47eefa6430a04",
"support"
],
"web-animations/timing-model/animation-effects/active-time.html": [
- "42eb1a23e89ae60ccd0a3664a9a583df1eb30d49",
+ "68ca985984ed6f868cebb539dfde6d7ddba6c824",
"testharness"
],
"web-animations/timing-model/animation-effects/current-iteration.html": [
- "a83e4dbd359774de7e6dbea4ae0b8d28d16d62e5",
+ "617bfd8c533d159c4e56ea823917d580fe262bf6",
"testharness"
],
"web-animations/timing-model/animation-effects/local-time.html": [
- "4b24cf2374a690395398f8caed9d340667dd0a9d",
+ "cd76b6be13cba0bc7d3b1a0e87b70c6a66222f40",
"testharness"
],
"web-animations/timing-model/animation-effects/phases-and-states.html": [
- "ce3652c8a6fdd8a6019fd665bca28ed725bacd71",
+ "3edd2c4bdd8409c2c12f08bc998dd8d532e0fd7d",
"testharness"
],
"web-animations/timing-model/animation-effects/simple-iteration-progress.html": [
- "521524358dabafea8e78c36829f9cd7d4115400a",
+ "602fe7e6880e0b18329262699872c696f451d744",
"testharness"
],
"web-animations/timing-model/animations/canceling-an-animation.html": [
- "079bc0e0f7ea60b94999ed1b4f92c1aa2fc2c7bb",
+ "d82cbc5caf654b9811c90d5165fb0429891cb149",
"testharness"
],
"web-animations/timing-model/animations/current-time.html": [
- "b1ea8e490cbfb69fd71b91a90e7e2d9ce99f42d3",
+ "390e2ba8d6de9bfea5f26cd2e7a42ccdf73f1a35",
"testharness"
],
"web-animations/timing-model/animations/finishing-an-animation.html": [
- "570ec579c6118866b888b1384e21977c9cfb0ec0",
+ "8d430adcb97bf3dab9703bc2d31be23e1adaec85",
"testharness"
],
"web-animations/timing-model/animations/pausing-an-animation.html": [
- "a000d8f86fa62b90ec7a60c289066aaaa1758377",
+ "c46fbcb8bc40fc3ee26e10802a205926ab97a84f",
+ "testharness"
+ ],
+ "web-animations/timing-model/animations/play-states.html": [
+ "3ec76eff991e306699b21fb03bc1f346ffd9cee3",
"testharness"
],
"web-animations/timing-model/animations/playing-an-animation.html": [
- "2b4f51977d43f9bf90c066bfcc57728ae096b6e9",
+ "6ee1b850154ce22fffafa686fc2fdfef9dded38b",
"testharness"
],
"web-animations/timing-model/animations/reversing-an-animation.html": [
- "2b5631893d0d0846e5e57097ce4ae54dfa8a03e3",
+ "3afdb3cc9a9dafb28ebe46902276c19c24aeb9a8",
"testharness"
],
"web-animations/timing-model/animations/set-the-animation-start-time.html": [
- "84afa495b1a4c467e27b1394f6449a18c58ed98d",
+ "10fea7d0b0dbe046d72b4048607816c9ebe37f7f",
"testharness"
],
"web-animations/timing-model/animations/set-the-target-effect-of-an-animation.html": [
- "840be610db4bce6d6fd1c22710e494a75ee95eba",
+ "3b7f1f60cd771ff8587daf7ab76ccbecff59f781",
"testharness"
],
"web-animations/timing-model/animations/set-the-timeline-of-an-animation.html": [
- "6e8e029f813046c3da69b4ff0c9d03d2a56b38a4",
+ "ef8ce243226296718453e10d89b4cfd68b2d765e",
"testharness"
],
"web-animations/timing-model/animations/updating-the-finished-state.html": [
- "266f1b793aa74a59486081f3ba8f6cbb482e714b",
+ "c30161f7d5a20db616ade354133ae6a8989d149f",
"testharness"
],
"web-animations/timing-model/time-transformations/transformed-progress.html": [
- "66e2277c77e4bd7b2d8981a725fb5083a8f5e0f6",
+ "2e55f43def584a67eeb313f050154cd146002938",
"testharness"
],
"web-animations/timing-model/timelines/document-timelines.html": [
- "cfa1e9ab84cb4901068e6305f69d8987cdda69cd",
+ "d0fcb390c19c9ede7288278dc11ea5b3d33671cb",
"testharness"
],
"web-animations/timing-model/timelines/timelines.html": [
- "6f0a9efcce6d5438996b650c022d6723dbccf58b",
+ "29d7fe91c355fc22f563ca17315d2ab493dc0566",
"testharness"
],
"web-nfc/OWNERS": [
@@ -575545,7 +583273,7 @@
"support"
],
"webaudio/resources/audit.js": [
- "20b0d0bc30f4d0f41828f579b4dd4f71a60fcde4",
+ "1e7c1c4169bc54bd2046ff5b3392f846c6b7b40f",
"support"
],
"webaudio/resources/sin_440Hz_-6dBFS_1s.wav": [
@@ -575801,17 +583529,13 @@
"testharness"
],
"webdriver/OWNERS": [
- "4986cd1bfa1e4c8e5c836581871745b5b2cc440e",
+ "020bcd036daed8eb8928c2924ea1d04050cf1939",
"support"
],
"webdriver/README.md": [
"185acb69e9516e0564e16bf7d7f8dc2a4c48d3c7",
"support"
],
- "webdriver/interface/interface.html": [
- "ff6f1ffa851eed97a5a2ba4e247058bc3982111e",
- "testharness"
- ],
"webdriver/tests/__init__.py": [
"da39a3ee5e6b4b0d3255bfef95601890afd80709",
"support"
@@ -575828,16 +583552,24 @@
"d589b53f0096893600e696b43ec19ca84e5ee2ab",
"wdspec"
],
+ "webdriver/tests/actions/key_shortcuts.py": [
+ "dbe27dd0b1625169fc8cc2055f8fb49d5a4a78d2",
+ "wdspec"
+ ],
"webdriver/tests/actions/modifier_click.py": [
- "2ec22f44973e6da3b9506ad7cc9fd0949f3ef8b5",
+ "88a384182fdd9df1515b9d8cfda8f56aed138ec7",
"wdspec"
],
"webdriver/tests/actions/mouse.py": [
- "c3cf09eaad1f24b2946c0ef865b10c5ac2e52700",
+ "0af689cee458ed260b2b9cc6f3231c314a3a6638",
+ "wdspec"
+ ],
+ "webdriver/tests/actions/mouse_dblclick.py": [
+ "61bab159bf1ccc7d44e4034a3e67d60b13fc1607",
"wdspec"
],
"webdriver/tests/actions/sequence.py": [
- "8c948c12cea1e2e8f2de845555817910904f757a",
+ "d43caf0f8607a76c3baed7806664b686bde21fda",
"wdspec"
],
"webdriver/tests/actions/special_keys.py": [
@@ -575849,7 +583581,11 @@
"support"
],
"webdriver/tests/actions/support/keys.py": [
- "636991372c21e52b623ed4ada9dfb675dd7f7e14",
+ "528ab8473914c14f9671d89b8a888d30162714ec",
+ "support"
+ ],
+ "webdriver/tests/actions/support/mouse.py": [
+ "0a6fca5e3fe20db114dbee1dd9d290ec343f6f9c",
"support"
],
"webdriver/tests/actions/support/refine.py": [
@@ -575877,7 +583613,7 @@
"wdspec"
],
"webdriver/tests/cookies/add_cookie.py": [
- "8da2db1e4d4110fd4bd5705b8e36f35a3dea049a",
+ "c58e50480aa3189bd4f1c52050cff6fcfcdf8d8b",
"wdspec"
],
"webdriver/tests/cookies/delete_cookie.py": [
@@ -575885,19 +583621,75 @@
"wdspec"
],
"webdriver/tests/cookies/get_named_cookie.py": [
- "9455d1504590154ad2a540f102455baff602aefb",
+ "12e1f83275fbfe6926380b267689fbfa55d6b93a",
+ "wdspec"
+ ],
+ "webdriver/tests/document_handling/page_source.py": [
+ "5dddfce0a5e43f02b8a050afda8c9a07c43cf797",
"wdspec"
],
"webdriver/tests/element_click/__init__.py": [
"da39a3ee5e6b4b0d3255bfef95601890afd80709",
"support"
],
+ "webdriver/tests/element_click/bubbling.py": [
+ "5437f5ca12b93e9a0087e9b341d63af6bace4ffd",
+ "wdspec"
+ ],
"webdriver/tests/element_click/select.py": [
"5ba51b660c7203bba3ada597c2f56fe094358e1f",
"wdspec"
],
+ "webdriver/tests/element_click/stale.py": [
+ "37af63203540dfe11d36fe05d74694f05c6505f2",
+ "wdspec"
+ ],
+ "webdriver/tests/element_retrieval/__init__.py": [
+ "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+ "support"
+ ],
+ "webdriver/tests/element_retrieval/find_element.py": [
+ "699b97bd31eed625e2f0bed145aaf94c3e646853",
+ "wdspec"
+ ],
+ "webdriver/tests/element_retrieval/find_element_from_element.py": [
+ "34f356f2579391289edb31adf5b4d4eb88ffc643",
+ "wdspec"
+ ],
+ "webdriver/tests/element_retrieval/find_elements.py": [
+ "284ae53c5c94d02fb46b26dcd70af02d7917e7b4",
+ "wdspec"
+ ],
+ "webdriver/tests/element_retrieval/find_elements_from_element.py": [
+ "b062b9f044268f0d9e092def81afae1277a91cd8",
+ "wdspec"
+ ],
"webdriver/tests/element_retrieval/get_active_element.py": [
- "74bb0beec41ab857f6814d47191f29065a536802",
+ "7d40a7641dbf04cd78f1dba630afa2e8d80dad13",
+ "wdspec"
+ ],
+ "webdriver/tests/element_send_keys/__init__.py": [
+ "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+ "support"
+ ],
+ "webdriver/tests/element_send_keys/interactability.py": [
+ "bd7cd6c009c86fe93c0e132c30fb9674413962d4",
+ "wdspec"
+ ],
+ "webdriver/tests/element_send_keys/scroll_into_view.py": [
+ "fb192d5d1d93aa729b07cadcadfa630587bd0b39",
+ "wdspec"
+ ],
+ "webdriver/tests/execute_async_script/user_prompts.py": [
+ "e31edd4537f9b7479a348465154381f5b18f938c",
+ "wdspec"
+ ],
+ "webdriver/tests/execute_script/cyclic.py": [
+ "cbebfbd2413ea0b10f547ab66fcc7159898e684a",
+ "wdspec"
+ ],
+ "webdriver/tests/execute_script/user_prompts.py": [
+ "901487f8270dcce693867ca090393e093d26f22b",
"wdspec"
],
"webdriver/tests/fullscreen_window.py": [
@@ -575905,11 +583697,11 @@
"wdspec"
],
"webdriver/tests/get_window_rect.py": [
- "5d907b2a16b9ff7dba8e39bba19ea7f85f29f71e",
+ "c9139c16aa950c734c776887d6a762b867790812",
"wdspec"
],
"webdriver/tests/interaction/element_clear.py": [
- "c8b700458df1767111f6648b6c1388ecd87555bb",
+ "9b598e993e404275f1fe4bdb1967d8e1950e25cb",
"wdspec"
],
"webdriver/tests/interaction/send_keys_content_editable.py": [
@@ -575917,7 +583709,7 @@
"wdspec"
],
"webdriver/tests/interface.html": [
- "d783d0dd370f58b264ef238d8da5cd8601dc3c7f",
+ "6625887cfa7f461dc428c11861fce71c47bef57d",
"testharness"
],
"webdriver/tests/minimize_window.py": [
@@ -575925,33 +583717,13 @@
"wdspec"
],
"webdriver/tests/navigation/current_url.py": [
- "cec2987258d9c807a247da9e0216b3af1f171484",
+ "828e40301838c99aa2978733bbce3db3acc185a0",
"wdspec"
],
"webdriver/tests/navigation/get_title.py": [
"2ee18932a8ae3c4190b37e2b28141a6af49cc507",
"wdspec"
],
- "webdriver/tests/retrieval/__init__.py": [
- "da39a3ee5e6b4b0d3255bfef95601890afd80709",
- "support"
- ],
- "webdriver/tests/retrieval/find_element.py": [
- "2a4cdf4c703493f7c90fc3473daa27660ac61e11",
- "wdspec"
- ],
- "webdriver/tests/retrieval/find_element_from_element.py": [
- "f036ef93adff21a7c83eeb8b131c96b6553b9fcb",
- "wdspec"
- ],
- "webdriver/tests/retrieval/find_element_from_elements.py": [
- "131c25ffbde611f98e29b778d7c861ae9619b2f6",
- "wdspec"
- ],
- "webdriver/tests/retrieval/find_elements.py": [
- "2d5c3c98b00e21a36f91e5797bb97835a8b63f2e",
- "wdspec"
- ],
"webdriver/tests/sessions/get_timeouts.py": [
"eaee354d16aa8c3a0fc960198fa4c5d9365bdee5",
"wdspec"
@@ -575992,6 +583764,10 @@
"440d88462cc418e4d5e1df6f73074d3a722bd2fd",
"support"
],
+ "webdriver/tests/sessions/status.py": [
+ "75edf0e629d9cd494c63585408c76217ff953722",
+ "wdspec"
+ ],
"webdriver/tests/set_window_rect.py": [
"8a124f80e6e7732a651a80da3f6cdf8e2ed99e3e",
"wdspec"
@@ -576024,20 +583800,16 @@
"570274d59020c4d8d0b8ecd604660ee7d710a165",
"wdspec"
],
- "webdriver/tests/status.py": [
- "5d3ae3da2967072dff274f384cceaecc07b6aa4b",
- "wdspec"
- ],
"webdriver/tests/support/__init__.py": [
"5a31a3917a5157516c10951a3b3d5ffb43b992d9",
"support"
],
"webdriver/tests/support/asserts.py": [
- "fd28bb9531b1644b726b7baba00a09871bd0dd3f",
+ "68bb420a9d85810c9fd8b6eaa569b855dfb83638",
"support"
],
"webdriver/tests/support/fixtures.py": [
- "765dd3821da0724024cdd61523f3d2fd79e8be28",
+ "b9b62366cd60ae7167ad2d0efdf3790ae2e780a4",
"support"
],
"webdriver/tests/support/http_request.py": [
@@ -576053,7 +583825,7 @@
"support"
],
"webdriver/tests/support/wait.py": [
- "a4b0c9c340ea7055139d9fcab3246ee836d6a441",
+ "511d4ba0ff21325b7503440b4111fac325139edc",
"support"
],
"webdriver/tests/switch_to_parent_frame.py": [
@@ -576061,19 +583833,19 @@
"wdspec"
],
"webdriver/tests/user_prompts/accept_alert.py": [
- "30aa726664c6228dd5901bef862d3d55b3474e41",
+ "9cd5e82f18455062ec07a5c8a0bef31cfe4ea86f",
"wdspec"
],
"webdriver/tests/user_prompts/dismiss_alert.py": [
- "bf75a630194dee1d619cb2818d71f9fb06a5dbbc",
+ "f200db4350a738fc14c9aed853fd3011141e8f3a",
"wdspec"
],
"webdriver/tests/user_prompts/get_alert_text.py": [
- "2eabe61f38757fd377e9773b7697a9a1ed21ceb6",
+ "5547f710db1787eb44454988d32a4b52c758e9c2",
"wdspec"
],
"webdriver/tests/user_prompts/send_alert_text.py": [
- "16d3219eb2404c06e7a6574508a789cb842fc89b",
+ "e6878e7923b1cdddff2450057020de0bf2e6aa7c",
"wdspec"
],
"webgl/bufferSubData.html": [
@@ -576213,7 +583985,7 @@
"testharness"
],
"webmessaging/event.origin.sub.htm": [
- "68a1bfc42c565f9ec482fbc539f8d3f2ac78e413",
+ "ef14b99d3eac8c17623f3ba531605fa2abda99d7",
"testharness"
],
"webmessaging/event.ports.sub.htm": [
@@ -576549,11 +584321,11 @@
"testharness"
],
"webrtc/OWNERS": [
- "afb3b4b35f06e38d392fc2ffd57025471a03eec1",
+ "b9739bfca307233dd72555b30e8492d47680d2af",
"support"
],
"webrtc/RTCCertificate.html": [
- "95e54d7fb8b37b9f1719137a4245cb25263336e0",
+ "cc1191d16707c4a5126291850414800cacb76199",
"testharness"
],
"webrtc/RTCConfiguration-bundlePolicy.html": [
@@ -576573,7 +584345,7 @@
"testharness"
],
"webrtc/RTCConfiguration-iceTransportPolicy.html": [
- "f95cceffe7485aac7b53d3f891ad87d50ccc8b1d",
+ "a3cdf93a5c3da4552c616f43e1fca01b9261dd38",
"testharness"
],
"webrtc/RTCConfiguration-rtcpMuxPolicy.html": [
@@ -576581,7 +584353,7 @@
"testharness"
],
"webrtc/RTCDTMFSender-helper.js": [
- "0c2e8862deffeec71ac925642647bb9ee4ad70ff",
+ "205469a5d95d35c0cdc091afafa49ecaccac7e2d",
"support"
],
"webrtc/RTCDTMFSender-insertDTMF.https.html": [
@@ -576613,7 +584385,7 @@
"testharness"
],
"webrtc/RTCDtlsTransport-getRemoteCertificates.html": [
- "76eb9e89291ce2aa8fa81dd7216a853193abd6e2",
+ "7d6ea59253879cac114e2a7b162fa67926a39635",
"testharness"
],
"webrtc/RTCIceCandidate-constructor.html": [
@@ -576633,7 +584405,7 @@
"testharness"
],
"webrtc/RTCPeerConnection-addTransceiver.html": [
- "d4f7108629c221c95fcaafa554ecd820c27a6922",
+ "c2d5766daa3ea4050ccb2777d7c08af1a1bd176f",
"testharness"
],
"webrtc/RTCPeerConnection-canTrickleIceCandidates.html": [
@@ -576645,7 +584417,7 @@
"testharness"
],
"webrtc/RTCPeerConnection-constructor.html": [
- "2152cb1835b1afe939504e934a7f19d30b17ba3d",
+ "c229347757f56d239925915ed9e6227086e75b84",
"testharness"
],
"webrtc/RTCPeerConnection-createAnswer.html": [
@@ -576653,7 +584425,11 @@
"testharness"
],
"webrtc/RTCPeerConnection-createDataChannel.html": [
- "0e2c9ab2b4900aa7955d75f867bb5958c7c70ce3",
+ "102de47ea13e20fe6d196077e47a525911957a00",
+ "testharness"
+ ],
+ "webrtc/RTCPeerConnection-createOffer-offerToReceive.html": [
+ "91905d7efc95500ebba085ca4b1fc682a496e228",
"testharness"
],
"webrtc/RTCPeerConnection-createOffer.html": [
@@ -576673,7 +584449,7 @@
"testharness"
],
"webrtc/RTCPeerConnection-getStats.https.html": [
- "1fc0c03ebd989d77c9d721b027a12a0cbbf24d53",
+ "9446d7bc1aefa7edd28b425415d983d69311e0ca",
"testharness"
],
"webrtc/RTCPeerConnection-getTransceivers.html": [
@@ -576692,10 +584468,6 @@
"ed3226f9673bc0b69c2a9f9ec6e1ccfa8e83e2e2",
"testharness"
],
- "webrtc/RTCPeerConnection-idl.html": [
- "9d67664cde55f701e2b15c0e801e79a5bd16110a",
- "testharness"
- ],
"webrtc/RTCPeerConnection-ondatachannel.html": [
"6096ee14d729894e39eb2217828e8b0a5abc7f19",
"testharness"
@@ -576709,7 +584481,7 @@
"testharness"
],
"webrtc/RTCPeerConnection-peerIdentity.html": [
- "2e6808671da699ad3a61f7ebd766b92686ddb17c",
+ "1cc5702e0aee887d925d2bf3471ac759d7430874",
"testharness"
],
"webrtc/RTCPeerConnection-removeTrack.https.html": [
@@ -576757,7 +584529,7 @@
"testharness"
],
"webrtc/RTCPeerConnection-setRemoteDescription-tracks.https.html": [
- "f309fe97cd3954e5f2b337e16f48339d3bb359bd",
+ "16fe3b155e55d1b66181788c93e570b36e5cc67d",
"testharness"
],
"webrtc/RTCPeerConnection-setRemoteDescription.html": [
@@ -576769,7 +584541,7 @@
"testharness"
],
"webrtc/RTCRtpCapabilities-helper.js": [
- "f66e7842a8b761612e40ef1a825357d9e21d5af5",
+ "22881ddd3cda1a64ff22474562de1568522e9745",
"support"
],
"webrtc/RTCRtpParameters-codecs.html": [
@@ -576824,8 +584596,8 @@
"27f083617973770f0d42efb93813f0112fc68ad2",
"testharness"
],
- "webrtc/RTCRtpSender-getStats.html": [
- "9a95fe0a2bd44fda187b586303a95dd5eb7db0cf",
+ "webrtc/RTCRtpSender-getStats.https.html": [
+ "5c480c0d64de4e3ee041b95e5ccaec6264b878b8",
"testharness"
],
"webrtc/RTCRtpSender-replaceTrack.html": [
@@ -576848,12 +584620,16 @@
"b92f3acf5113a475b58892f48406aafc9634be07",
"testharness"
],
+ "webrtc/RTCSctpTransport-maxMessageSize.html": [
+ "95a1a701ff1ea46c782131dcd2012d3b4d5d57d2",
+ "testharness"
+ ],
"webrtc/RTCStats-helper.js": [
- "8fa8b228d3b6ee861c843a5f6b7aa2a1c8260763",
+ "1c18bc44f5694a5a273807c06b7ab8f025dd1530",
"support"
],
"webrtc/RTCTrackEvent-constructor.html": [
- "a73dde79625035cdd40d5abd8856cd44161dfdf9",
+ "4e9060c8c67de3a13f9d5727a8140a8ecfb8dfbf",
"testharness"
],
"webrtc/coverage/RTCDTMFSender.txt": [
@@ -576872,10 +584648,6 @@
"56a37968e489d6ee39a1234ca888dd628f17648e",
"testharness"
],
- "webrtc/datachannel-idlharness.html": [
- "a1753a9a537a626775194ccc5dfdbf6829c5df35",
- "testharness"
- ],
"webrtc/dictionary-helper.js": [
"9a43fcdfda7da1c281cbb221d1c463d1e280ee3a",
"support"
@@ -576908,6 +584680,22 @@
"6194af79f137d59334da2193cc6f24b9458344be",
"testharness"
],
+ "webrtc/tools/.eslintrc.js": [
+ "ceb052e89c7e9bef32fd37942515b2d38d59d269",
+ "support"
+ ],
+ "webrtc/tools/README.md": [
+ "4a7dfd32e2129c362e153a83e4645fcc77b74247",
+ "support"
+ ],
+ "webrtc/tools/package-lock.json": [
+ "731c41b82c17db5d5c3e0c636c197fcba01df344",
+ "support"
+ ],
+ "webrtc/tools/package.json": [
+ "67474f98b40d247ebac9cdee2146019a8e0b10b1",
+ "support"
+ ],
"websockets/Close-1000-reason.htm": [
"a3733fc46f0a5358cc8dbfd74d422e1a598bdf64",
"testharness"
@@ -577245,7 +585033,7 @@
"testharness"
],
"websockets/constants.js": [
- "d1aff62046b7ade8beb6bb762adc3a7871b3c71f",
+ "18bf7dad370e0dbe3cdc3d738448ebae87673b35",
"support"
],
"websockets/constructor.html": [
@@ -577432,6 +585220,10 @@
"b9faa29fb3d2bff4a373f0baf3b9c1e95b091f26",
"support"
],
+ "websockets/handlers/referrer_wsh.py": [
+ "b3eba9c69741d3d542129ba89f49acab76df89dc",
+ "support"
+ ],
"websockets/handlers/set-cookie-secure_wsh.py": [
"30b03b63d7b12371f6283ed89f967d2ffb66e372",
"support"
@@ -577481,7 +585273,7 @@
"testharness"
],
"websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-defineProperty-getter.html": [
- "466630e990131ebf0b1cd5df8f992a40e52eb6f2",
+ "bbc86a74509e00ca248826c853d3cf5c9270b06f",
"testharness"
],
"websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-defineProperty-setter.html": [
@@ -577788,6 +585580,10 @@
"bf330ce240331f39f78a34f638119d5f7b434347",
"testharness"
],
+ "websockets/referrer.any.js": [
+ "3d855fd4f80ce7a30e4eb601fb5ba1ca640a114d",
+ "testharness"
+ ],
"websockets/security/001.html": [
"4de87e1c2660aa70754059971045ca86a6417ae5",
"testharness"
@@ -577961,7 +585757,7 @@
"support"
],
"webstorage/idlharness.html": [
- "9eec3559fc7cfba33bbeb280c392ee0af9d6755b",
+ "e57413a1868e8d84ba7c500ff13b7e68675cbe66",
"testharness"
],
"webstorage/missing_arguments.html": [
@@ -578205,7 +586001,7 @@
"support"
],
"webvr/idlharness.html": [
- "ef6ad8bff43a6423b9b3e7deb8017a8b3fa0c112",
+ "3505e27e1b2668010bf61f05f6b8a759cf42cece",
"testharness"
],
"webvr/webvr-disabled-by-feature-policy.https.sub.html": [
@@ -578260,6 +586056,10 @@
"e88f3e9ddc5a5d4d9597403e8f7ef01d1daa339a",
"support"
],
+ "webvtt/api/VTTCue/constructor-exceptions.html": [
+ "0d7efaa2a234a5913412890517fa4722922c08ea",
+ "testharness"
+ ],
"webvtt/api/VTTCue/constructor.html": [
"c844f513868cbf4053c70f37bbb630b53a763a2a",
"testharness"
@@ -578652,6 +586452,10 @@
"527b1f144e3af92dddb0746afff4cffc6004a08d",
"testharness"
],
+ "webvtt/parsing/file-parsing/tests/regions-edge-case.html": [
+ "dfb3f01d6f6fcb175426446f347fa31f129b42d1",
+ "testharness"
+ ],
"webvtt/parsing/file-parsing/tests/regions-id.html": [
"b795ab2a5e12895569d24c2828b265d6f9d296fb",
"testharness"
@@ -578768,6 +586572,10 @@
"f25f0892d6da6d7268a7bbc271c6f1a74924d076",
"support"
],
+ "webvtt/parsing/file-parsing/tests/support/regions-edge-case.vtt": [
+ "1c5034a082535379df1ef67978bf97486d53e61e",
+ "support"
+ ],
"webvtt/parsing/file-parsing/tests/support/regions-id.vtt": [
"8cf754c33225fe4cf905bf5b2198a9e30fa8ec67",
"support"
@@ -581036,10 +588844,50 @@
"f2372a492268a1b17763a42a808351128128fd89",
"reftest"
],
+ "webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-center-ref.html": [
+ "1b9fc8a0086673fc5021c873c58b920c718a3d6f",
+ "support"
+ ],
+ "webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-center.html": [
+ "3ed80bf703c919ce5774208a6bc947bf1f37e6ce",
+ "reftest"
+ ],
+ "webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-left-ref.html": [
+ "79e0c0df8f6262ced630c78206b2115be9e02df0",
+ "support"
+ ],
+ "webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-left.html": [
+ "88864a2cb30622b3566f4f1b402cbd1b6b5fb33f",
+ "reftest"
+ ],
+ "webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-right-ref.html": [
+ "c756d183319554a551482692b0e265165894995d",
+ "support"
+ ],
+ "webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-right.html": [
+ "e0945f78441ab2676e652d6bc2ca13d0bb2b98b3",
+ "reftest"
+ ],
"webvtt/tools/categorize_results.py": [
"339f3f5f0e968076031f4a7c4361f9dba14d485d",
"support"
],
+ "webxr/OWNERS": [
+ "13f9441d368248225df5adc3396a05061ba2924d",
+ "support"
+ ],
+ "webxr/resources/webxr_check.html": [
+ "3fa96e39a073bda2e813f0b2c2411c26b73d374e",
+ "support"
+ ],
+ "webxr/resources/webxr_util.js": [
+ "2e92835bb77e028fffc597767528a4a3548f27e8",
+ "support"
+ ],
+ "webxr/webxr_availability.http.sub.html": [
+ "d8aa0ef8b7b3363fd23af2700dc6d9186201c408",
+ "testharness"
+ ],
"workers/OWNERS": [
"424c4c3664d3eb0c5123b4a05c55ee78a1dbbba5",
"support"
@@ -581052,6 +588900,10 @@
"d74620a63e7d911ef60b995cabf6b360c2c46a4f",
"testharness"
],
+ "workers/SharedWorker_dataUrl.html": [
+ "285538767c2c79223f12b58da4e347eee8101ccc",
+ "testharness"
+ ],
"workers/WorkerGlobalScope_ErrorEvent_colno.htm": [
"8ceb41543f928c918010000d638099faeb674980",
"testharness"
@@ -581464,8 +589316,12 @@
"23ed9eb3cf4b65bdd0301570677a6d89af0e551b",
"testharness"
],
+ "workers/data-url-shared-window.html": [
+ "69d590693c5f161176ba2e1f36d89df284a766e4",
+ "support"
+ ],
"workers/data-url-shared.html": [
- "0fee4678c53e3f30e0f6090b5b9fc51b7bb74806",
+ "3650dbf419d8bbfe7380a36426793336998975cc",
"testharness"
],
"workers/data-url.html": [
@@ -582056,6 +589912,10 @@
"b0e679dd7720701364abeaca6870d94db5d7ee74",
"support"
],
+ "workers/support/iframe_sw_dataUrl.html": [
+ "2cd66112b612e7b861af00af5ccc26cc7c5a76f8",
+ "support"
+ ],
"workers/support/name-as-accidental-global.js": [
"530670268fae610b60066773ee475743b8498b53",
"support"
@@ -582077,7 +589937,7 @@
"support"
],
"workers/worker-performance.worker.js": [
- "d1759a707897f66bf013e888ed188023145e2622",
+ "513fd99e7c523b710386b7e3736d1cbbc6a20e7a",
"testharness"
],
"worklets/README.md": [
@@ -582129,15 +589989,23 @@
"support"
],
"worklets/resources/credentials-tests.js": [
- "3554b8fcf13239de2b89afde1cb0fe97ef5d2124",
+ "642b8039439a20609788d36a0bc7d116fc8e4f6d",
"support"
],
"worklets/resources/credentials.py": [
- "6ce932e1cdc3626efc85ba0fe4a517b6308c67bd",
+ "94a8b7d91f30cf9bc7b7473841dc49b9b7251d7f",
"support"
],
"worklets/resources/csp-tests.js": [
- "160eff495b94f445098a2764b94841e557b0bc47",
+ "57332b3e82704f8259e5f748e7195c10bb5ebb2c",
+ "support"
+ ],
+ "worklets/resources/empty-worklet-script-with-cors-header.js": [
+ "4b78be9f257ad243eb6ca72f84084081267c46a1",
+ "support"
+ ],
+ "worklets/resources/empty-worklet-script-with-cors-header.js.headers": [
+ "90d51a5e46cc58404dd5ec1e9e4e10934a6c0707",
"support"
],
"worklets/resources/empty-worklet-script.js": [
@@ -582148,8 +590016,16 @@
"f32abb012c93bb69087688f31a0c243d9e6d1060",
"support"
],
- "worklets/resources/import-empty-worklet-script.js": [
- "4add9359940f440fb2c66d17096a45ffbf77975d",
+ "worklets/resources/import-empty-worklet-script-with-cors-header.js": [
+ "f4c82399ef85e69e24a7a1a3b27448e3f3722b70",
+ "support"
+ ],
+ "worklets/resources/import-empty-worklet-script-with-cors-header.js.headers": [
+ "90d51a5e46cc58404dd5ec1e9e4e10934a6c0707",
+ "support"
+ ],
+ "worklets/resources/import-insecure-origin-empty-worklet-script.sub.js": [
+ "d38fb85065c1f48864807fd84a87651eecaecd35",
"support"
],
"worklets/resources/import-nested-internal-worklet-script.js": [
@@ -582164,10 +590040,26 @@
"2d8af6c2e0e7bc3f7feaa5f333824fea94314353",
"support"
],
+ "worklets/resources/import-referrer-checker-worklet-script.sub.js": [
+ "8d42d00b53b014c5b0ac6d0702be168b5069d659",
+ "support"
+ ],
+ "worklets/resources/import-referrer-checker-worklet-script.sub.js.headers": [
+ "90d51a5e46cc58404dd5ec1e9e4e10934a6c0707",
+ "support"
+ ],
"worklets/resources/import-remote-origin-empty-worklet-script.sub.js": [
"e048bbd38d7348edd6e487ba2381b57530a5cba6",
"support"
],
+ "worklets/resources/import-remote-origin-referrer-checker-worklet-script.sub.js": [
+ "1e60785a8948f090541731edc67b5a2c21419c2c",
+ "support"
+ ],
+ "worklets/resources/import-remote-origin-referrer-checker-worklet-script.sub.js.headers": [
+ "90d51a5e46cc58404dd5ec1e9e4e10934a6c0707",
+ "support"
+ ],
"worklets/resources/import-syntax-error-worklet-script.js": [
"e2f65e87d6d7b885201b4371ce0c4f21af5efe90",
"support"
@@ -582176,16 +590068,16 @@
"fdc5ee273fa5b4bf3b820f8c0404a5ca9580e2b4",
"support"
],
- "worklets/resources/referrer-tests.js": [
- "47d8ae6d90b88ab8fb856e305b1599a34173852f",
+ "worklets/resources/referrer-checker.py": [
+ "9e4cce637b7402da3b6a17d4cb33dc706f222c41",
"support"
],
- "worklets/resources/referrer-window.html": [
- "0b8b7424014190af51d310b9f843471a3b5fb37f",
+ "worklets/resources/referrer-tests.js": [
+ "bfa2e28259a44abf3aac6be528e51976c9ff782d",
"support"
],
- "worklets/resources/referrer.py": [
- "ed296faa934f89efcca9a116f6a2e931cafd831e",
+ "worklets/resources/referrer-window.html": [
+ "adfb1c116fedb6396f970ed8072ee73edfc755fc",
"support"
],
"worklets/resources/service-worker-interception-tests.js": [
@@ -582197,7 +590089,7 @@
"support"
],
"worklets/resources/set-cookie.py": [
- "3152f5d79b6f362f5aaf738d7d2454de94a6159d",
+ "aa55d9ed286809c8d808c102dd409afb75cbe554",
"support"
],
"worklets/resources/syntax-error-worklet-script.js": [
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures.worker.js.ini
deleted file mode 100644
index 1068757f3a5..00000000000
--- a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures.worker.js.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[failures.worker.html]
- type: testharness
- [Untitled]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-CBC.https.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-CBC.https.worker.js.ini
new file mode 100644
index 00000000000..8ac82d02f13
--- /dev/null
+++ b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-CBC.https.worker.js.ini
@@ -0,0 +1,4 @@
+[failures_AES-CBC.https.worker.html]
+ [Untitled]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-CBC.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-CBC.worker.js.ini
deleted file mode 100644
index c59cf0b37b1..00000000000
--- a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-CBC.worker.js.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[failures_AES-CBC.worker.html]
- type: testharness
- [Untitled]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-CTR.https.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-CTR.https.worker.js.ini
new file mode 100644
index 00000000000..965b8f24038
--- /dev/null
+++ b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-CTR.https.worker.js.ini
@@ -0,0 +1,4 @@
+[failures_AES-CTR.https.worker.html]
+ [Untitled]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-CTR.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-CTR.worker.js.ini
deleted file mode 100644
index e1d07f1f70b..00000000000
--- a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-CTR.worker.js.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[failures_AES-CTR.worker.html]
- type: testharness
- [Untitled]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-GCM.https.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-GCM.https.worker.js.ini
new file mode 100644
index 00000000000..2dfaeb46c7e
--- /dev/null
+++ b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-GCM.https.worker.js.ini
@@ -0,0 +1,4 @@
+[failures_AES-GCM.https.worker.html]
+ [Untitled]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-GCM.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-GCM.worker.js.ini
deleted file mode 100644
index b20a0793579..00000000000
--- a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-GCM.worker.js.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[failures_AES-GCM.worker.html]
- type: testharness
- [Untitled]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-KW.https.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-KW.https.worker.js.ini
new file mode 100644
index 00000000000..d1de9f827a0
--- /dev/null
+++ b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-KW.https.worker.js.ini
@@ -0,0 +1,4 @@
+[failures_AES-KW.https.worker.html]
+ [Untitled]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-KW.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-KW.worker.js.ini
deleted file mode 100644
index b8aa1b6cae5..00000000000
--- a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_AES-KW.worker.js.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[failures_AES-KW.worker.html]
- type: testharness
- [Untitled]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_ECDH.https.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_ECDH.https.worker.js.ini
new file mode 100644
index 00000000000..b5483769a8a
--- /dev/null
+++ b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_ECDH.https.worker.js.ini
@@ -0,0 +1,4 @@
+[failures_ECDH.https.worker.html]
+ [Untitled]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_ECDH.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_ECDH.worker.js.ini
deleted file mode 100644
index ae9af4e8a34..00000000000
--- a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_ECDH.worker.js.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[failures_ECDH.worker.html]
- type: testharness
- [Untitled]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_ECDSA.https.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_ECDSA.https.worker.js.ini
new file mode 100644
index 00000000000..41afcd71a30
--- /dev/null
+++ b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_ECDSA.https.worker.js.ini
@@ -0,0 +1,4 @@
+[failures_ECDSA.https.worker.html]
+ [Untitled]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_ECDSA.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_ECDSA.worker.js.ini
deleted file mode 100644
index cfba6f7c221..00000000000
--- a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_ECDSA.worker.js.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[failures_ECDSA.worker.html]
- type: testharness
- [Untitled]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_HMAC.https.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_HMAC.https.worker.js.ini
new file mode 100644
index 00000000000..e9b1b81046d
--- /dev/null
+++ b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_HMAC.https.worker.js.ini
@@ -0,0 +1,4 @@
+[failures_HMAC.https.worker.html]
+ [Untitled]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_HMAC.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_HMAC.worker.js.ini
deleted file mode 100644
index deb887a2321..00000000000
--- a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_HMAC.worker.js.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[failures_HMAC.worker.html]
- type: testharness
- [Untitled]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_RSA-OAEP.https.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_RSA-OAEP.https.worker.js.ini
new file mode 100644
index 00000000000..caa72afe819
--- /dev/null
+++ b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_RSA-OAEP.https.worker.js.ini
@@ -0,0 +1,4 @@
+[failures_RSA-OAEP.https.worker.html]
+ [Untitled]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_RSA-OAEP.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_RSA-OAEP.worker.js.ini
deleted file mode 100644
index 1de70f23558..00000000000
--- a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_RSA-OAEP.worker.js.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[failures_RSA-OAEP.worker.html]
- type: testharness
- [Untitled]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_RSA-PSS.https.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_RSA-PSS.https.worker.js.ini
new file mode 100644
index 00000000000..e0caa79ea4f
--- /dev/null
+++ b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_RSA-PSS.https.worker.js.ini
@@ -0,0 +1,4 @@
+[failures_RSA-PSS.https.worker.html]
+ [Untitled]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_RSA-PSS.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_RSA-PSS.worker.js.ini
deleted file mode 100644
index cc03a108192..00000000000
--- a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_RSA-PSS.worker.js.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[failures_RSA-PSS.worker.html]
- type: testharness
- [Untitled]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_RSASSA-PKCS1-v1_5.https.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_RSASSA-PKCS1-v1_5.https.worker.js.ini
new file mode 100644
index 00000000000..18d6ba47d03
--- /dev/null
+++ b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_RSASSA-PKCS1-v1_5.https.worker.js.ini
@@ -0,0 +1,4 @@
+[failures_RSASSA-PKCS1-v1_5.https.worker.html]
+ [Untitled]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_RSASSA-PKCS1-v1_5.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_RSASSA-PKCS1-v1_5.worker.js.ini
deleted file mode 100644
index 8f65dda379d..00000000000
--- a/tests/wpt/metadata/WebCryptoAPI/generateKey/failures_RSASSA-PKCS1-v1_5.worker.js.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[failures_RSASSA-PKCS1-v1_5.worker.html]
- type: testharness
- [Untitled]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes.worker.js.ini
deleted file mode 100644
index ed342a2b9c3..00000000000
--- a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes.worker.js.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[successes.worker.html]
- type: testharness
- [Untitled]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-CBC.https.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-CBC.https.worker.js.ini
new file mode 100644
index 00000000000..1e211bb6f65
--- /dev/null
+++ b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-CBC.https.worker.js.ini
@@ -0,0 +1,4 @@
+[successes_AES-CBC.https.worker.html]
+ [Untitled]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-CBC.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-CBC.worker.js.ini
deleted file mode 100644
index 3dc1a08cbb7..00000000000
--- a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-CBC.worker.js.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[successes_AES-CBC.worker.html]
- type: testharness
- [Untitled]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-CTR.https.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-CTR.https.worker.js.ini
new file mode 100644
index 00000000000..a2883df07a6
--- /dev/null
+++ b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-CTR.https.worker.js.ini
@@ -0,0 +1,4 @@
+[successes_AES-CTR.https.worker.html]
+ [Untitled]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-CTR.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-CTR.worker.js.ini
deleted file mode 100644
index 16542c965e1..00000000000
--- a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-CTR.worker.js.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[successes_AES-CTR.worker.html]
- type: testharness
- [Untitled]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-GCM.https.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-GCM.https.worker.js.ini
new file mode 100644
index 00000000000..0dd50458c8a
--- /dev/null
+++ b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-GCM.https.worker.js.ini
@@ -0,0 +1,4 @@
+[successes_AES-GCM.https.worker.html]
+ [Untitled]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-GCM.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-GCM.worker.js.ini
deleted file mode 100644
index 38f1036a947..00000000000
--- a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-GCM.worker.js.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[successes_AES-GCM.worker.html]
- type: testharness
- [Untitled]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-KW.https.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-KW.https.worker.js.ini
new file mode 100644
index 00000000000..6a3dc9d94c2
--- /dev/null
+++ b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-KW.https.worker.js.ini
@@ -0,0 +1,4 @@
+[successes_AES-KW.https.worker.html]
+ [Untitled]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-KW.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-KW.worker.js.ini
deleted file mode 100644
index 61332e4ac7d..00000000000
--- a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_AES-KW.worker.js.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[successes_AES-KW.worker.html]
- type: testharness
- [Untitled]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_ECDH.https.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_ECDH.https.worker.js.ini
new file mode 100644
index 00000000000..e4ed8296c89
--- /dev/null
+++ b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_ECDH.https.worker.js.ini
@@ -0,0 +1,4 @@
+[successes_ECDH.https.worker.html]
+ [Untitled]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_ECDH.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_ECDH.worker.js.ini
deleted file mode 100644
index c7c0cd21980..00000000000
--- a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_ECDH.worker.js.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[successes_ECDH.worker.html]
- type: testharness
- [Untitled]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_ECDSA.https.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_ECDSA.https.worker.js.ini
new file mode 100644
index 00000000000..605c0e88f46
--- /dev/null
+++ b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_ECDSA.https.worker.js.ini
@@ -0,0 +1,4 @@
+[successes_ECDSA.https.worker.html]
+ [Untitled]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_ECDSA.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_ECDSA.worker.js.ini
deleted file mode 100644
index 4c46593c798..00000000000
--- a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_ECDSA.worker.js.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[successes_ECDSA.worker.html]
- type: testharness
- [Untitled]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_HMAC.https.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_HMAC.https.worker.js.ini
new file mode 100644
index 00000000000..10ad8a77ee0
--- /dev/null
+++ b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_HMAC.https.worker.js.ini
@@ -0,0 +1,4 @@
+[successes_HMAC.https.worker.html]
+ [Untitled]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_HMAC.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_HMAC.worker.js.ini
deleted file mode 100644
index 2194d88cbd1..00000000000
--- a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_HMAC.worker.js.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[successes_HMAC.worker.html]
- type: testharness
- [Untitled]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_RSA-OAEP.https.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_RSA-OAEP.https.worker.js.ini
new file mode 100644
index 00000000000..ba0c117f6a9
--- /dev/null
+++ b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_RSA-OAEP.https.worker.js.ini
@@ -0,0 +1,4 @@
+[successes_RSA-OAEP.https.worker.html]
+ [Untitled]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_RSA-OAEP.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_RSA-OAEP.worker.js.ini
deleted file mode 100644
index b27a732c5ff..00000000000
--- a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_RSA-OAEP.worker.js.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[successes_RSA-OAEP.worker.html]
- type: testharness
- [Untitled]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_RSA-PSS.https.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_RSA-PSS.https.worker.js.ini
new file mode 100644
index 00000000000..e931d698970
--- /dev/null
+++ b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_RSA-PSS.https.worker.js.ini
@@ -0,0 +1,4 @@
+[successes_RSA-PSS.https.worker.html]
+ [Untitled]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_RSA-PSS.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_RSA-PSS.worker.js.ini
deleted file mode 100644
index aca82094e98..00000000000
--- a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_RSA-PSS.worker.js.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[successes_RSA-PSS.worker.html]
- type: testharness
- [Untitled]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.https.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.https.worker.js.ini
new file mode 100644
index 00000000000..46f5a9c5953
--- /dev/null
+++ b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.https.worker.js.ini
@@ -0,0 +1,4 @@
+[successes_RSASSA-PKCS1-v1_5.https.worker.html]
+ [Untitled]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.worker.js.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.worker.js.ini
deleted file mode 100644
index 4d73a575efa..00000000000
--- a/tests/wpt/metadata/WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.worker.js.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[successes_RSASSA-PKCS1-v1_5.worker.html]
- type: testharness
- [Untitled]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/WebCryptoAPI/generateKey/test_failures.https.html.ini b/tests/wpt/metadata/WebCryptoAPI/generateKey/test_failures.https.html.ini
deleted file mode 100644
index 584ab56284e..00000000000
--- a/tests/wpt/metadata/WebCryptoAPI/generateKey/test_failures.https.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[test_failures.https.html]
- type: testharness
- [WebCryptoAPI: generateKey() for Failures]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/WebIDL/ecmascript-binding/no-regexp-special-casing.any.js.ini b/tests/wpt/metadata/WebIDL/ecmascript-binding/no-regexp-special-casing.any.js.ini
new file mode 100644
index 00000000000..e44c35b2e8a
--- /dev/null
+++ b/tests/wpt/metadata/WebIDL/ecmascript-binding/no-regexp-special-casing.any.js.ini
@@ -0,0 +1,9 @@
+[no-regexp-special-casing.any.worker.html]
+ [Untitled]
+ expected: FAIL
+
+
+[no-regexp-special-casing.any.html]
+ [Untitled]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/XMLHttpRequest/send-redirect-post-upload.htm.ini b/tests/wpt/metadata/XMLHttpRequest/send-redirect-post-upload.htm.ini
index c3b3c67c601..343465b443c 100644
--- a/tests/wpt/metadata/XMLHttpRequest/send-redirect-post-upload.htm.ini
+++ b/tests/wpt/metadata/XMLHttpRequest/send-redirect-post-upload.htm.ini
@@ -12,3 +12,9 @@
[XMLHttpRequest: The send() method: POSTing to URL that redirects (307)]
expected: FAIL
+ [XMLHttpRequest: The send() method: POSTing to URL that redirects (307 (string))]
+ expected: FAIL
+
+ [XMLHttpRequest: The send() method: POSTing to URL that redirects (307 (blob))]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/css/CSS2/backgrounds/background-color-030.xht.ini b/tests/wpt/metadata/css/CSS2/backgrounds/background-color-030.xht.ini
deleted file mode 100644
index 0b1da424bb7..00000000000
--- a/tests/wpt/metadata/css/CSS2/backgrounds/background-color-030.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[background-color-030.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/backgrounds/background-color-174.xht.ini b/tests/wpt/metadata/css/CSS2/backgrounds/background-color-174.xht.ini
deleted file mode 100644
index 586e9e4fa6d..00000000000
--- a/tests/wpt/metadata/css/CSS2/backgrounds/background-color-174.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[background-color-174.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/backgrounds/background-image-002.xht.ini b/tests/wpt/metadata/css/CSS2/backgrounds/background-image-002.xht.ini
deleted file mode 100644
index d672e211cd6..00000000000
--- a/tests/wpt/metadata/css/CSS2/backgrounds/background-image-002.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[background-image-002.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/colors/color-083.xht.ini b/tests/wpt/metadata/css/CSS2/colors/color-083.xht.ini
deleted file mode 100644
index 9fa48494a27..00000000000
--- a/tests/wpt/metadata/css/CSS2/colors/color-083.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[color-083.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/colors/color-084.xht.ini b/tests/wpt/metadata/css/CSS2/colors/color-084.xht.ini
deleted file mode 100644
index ccff2657d29..00000000000
--- a/tests/wpt/metadata/css/CSS2/colors/color-084.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[color-084.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/after-inheritable-001.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/after-inheritable-001.xht.ini
new file mode 100644
index 00000000000..262bcf9ca31
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/after-inheritable-001.xht.ini
@@ -0,0 +1,2 @@
+[after-inheritable-001.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/after-inheritable-002.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/after-inheritable-002.xht.ini
new file mode 100644
index 00000000000..da9f319fb18
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/after-inheritable-002.xht.ini
@@ -0,0 +1,2 @@
+[after-inheritable-002.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/before-inheritable-002.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/before-inheritable-002.xht.ini
new file mode 100644
index 00000000000..819aada9757
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/before-inheritable-002.xht.ini
@@ -0,0 +1,2 @@
+[before-inheritable-002.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-004.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-004.xht.ini
new file mode 100644
index 00000000000..b8c378c2311
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-004.xht.ini
@@ -0,0 +1,2 @@
+[content-004.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-010.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-010.xht.ini
new file mode 100644
index 00000000000..53d86009692
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-010.xht.ini
@@ -0,0 +1,2 @@
+[content-010.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-011.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-011.xht.ini
new file mode 100644
index 00000000000..88b04433aab
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-011.xht.ini
@@ -0,0 +1,2 @@
+[content-011.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-012.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-012.xht.ini
new file mode 100644
index 00000000000..13962b4f1b2
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-012.xht.ini
@@ -0,0 +1,2 @@
+[content-012.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-014.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-014.xht.ini
new file mode 100644
index 00000000000..882942b7e4b
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-014.xht.ini
@@ -0,0 +1,2 @@
+[content-014.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-015.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-015.xht.ini
new file mode 100644
index 00000000000..13b5ff2c3d0
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-015.xht.ini
@@ -0,0 +1,2 @@
+[content-015.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-016.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-016.xht.ini
new file mode 100644
index 00000000000..b0fff3c6e74
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-016.xht.ini
@@ -0,0 +1,2 @@
+[content-016.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-017.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-017.xht.ini
new file mode 100644
index 00000000000..5e77a7c159d
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-017.xht.ini
@@ -0,0 +1,2 @@
+[content-017.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-026.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-026.xht.ini
new file mode 100644
index 00000000000..79b39dcaf91
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-026.xht.ini
@@ -0,0 +1,2 @@
+[content-026.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-027.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-027.xht.ini
new file mode 100644
index 00000000000..12a23e99a95
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-027.xht.ini
@@ -0,0 +1,2 @@
+[content-027.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-028.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-028.xht.ini
new file mode 100644
index 00000000000..c3440a23a36
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-028.xht.ini
@@ -0,0 +1,2 @@
+[content-028.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-030.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-030.xht.ini
new file mode 100644
index 00000000000..0ad1d84145d
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-030.xht.ini
@@ -0,0 +1,2 @@
+[content-030.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-031.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-031.xht.ini
new file mode 100644
index 00000000000..3186dd6b061
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-031.xht.ini
@@ -0,0 +1,2 @@
+[content-031.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-032.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-032.xht.ini
new file mode 100644
index 00000000000..19bd40696b7
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-032.xht.ini
@@ -0,0 +1,2 @@
+[content-032.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-033.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-033.xht.ini
new file mode 100644
index 00000000000..bec98d50d89
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-033.xht.ini
@@ -0,0 +1,2 @@
+[content-033.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-037.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-037.xht.ini
new file mode 100644
index 00000000000..8d581a62d55
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-037.xht.ini
@@ -0,0 +1,2 @@
+[content-037.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-038.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-038.xht.ini
new file mode 100644
index 00000000000..55dbc005478
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-038.xht.ini
@@ -0,0 +1,2 @@
+[content-038.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-039.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-039.xht.ini
new file mode 100644
index 00000000000..914b3392422
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-039.xht.ini
@@ -0,0 +1,2 @@
+[content-039.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-040.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-040.xht.ini
new file mode 100644
index 00000000000..1574f541d85
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-040.xht.ini
@@ -0,0 +1,2 @@
+[content-040.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-041.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-041.xht.ini
new file mode 100644
index 00000000000..6c4ed008895
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-041.xht.ini
@@ -0,0 +1,2 @@
+[content-041.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-042.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-042.xht.ini
new file mode 100644
index 00000000000..be86618b552
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-042.xht.ini
@@ -0,0 +1,2 @@
+[content-042.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-043.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-043.xht.ini
new file mode 100644
index 00000000000..0548440f58a
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-043.xht.ini
@@ -0,0 +1,2 @@
+[content-043.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-046.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-046.xht.ini
new file mode 100644
index 00000000000..77b3181f52f
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-046.xht.ini
@@ -0,0 +1,2 @@
+[content-046.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-047.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-047.xht.ini
new file mode 100644
index 00000000000..b2e2661878e
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-047.xht.ini
@@ -0,0 +1,2 @@
+[content-047.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-048.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-048.xht.ini
new file mode 100644
index 00000000000..f59c49831af
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-048.xht.ini
@@ -0,0 +1,2 @@
+[content-048.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-050.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-050.xht.ini
new file mode 100644
index 00000000000..d56f7c171ca
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-050.xht.ini
@@ -0,0 +1,2 @@
+[content-050.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-052.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-052.xht.ini
new file mode 100644
index 00000000000..d97829257fd
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-052.xht.ini
@@ -0,0 +1,2 @@
+[content-052.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-053.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-053.xht.ini
new file mode 100644
index 00000000000..f563db1b2ed
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-053.xht.ini
@@ -0,0 +1,2 @@
+[content-053.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-054.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-054.xht.ini
new file mode 100644
index 00000000000..4f9cbcc7586
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-054.xht.ini
@@ -0,0 +1,2 @@
+[content-054.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-056.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-056.xht.ini
new file mode 100644
index 00000000000..02a73baf31e
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-056.xht.ini
@@ -0,0 +1,2 @@
+[content-056.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-057.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-057.xht.ini
new file mode 100644
index 00000000000..3cd26ca3bc8
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-057.xht.ini
@@ -0,0 +1,2 @@
+[content-057.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-063.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-063.xht.ini
new file mode 100644
index 00000000000..72352e9b5a8
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-063.xht.ini
@@ -0,0 +1,2 @@
+[content-063.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-065.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-065.xht.ini
new file mode 100644
index 00000000000..2b7544e293c
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-065.xht.ini
@@ -0,0 +1,2 @@
+[content-065.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-067.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-067.xht.ini
new file mode 100644
index 00000000000..69df6c0eee6
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-067.xht.ini
@@ -0,0 +1,2 @@
+[content-067.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-068.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-068.xht.ini
new file mode 100644
index 00000000000..fac5b5d46f4
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-068.xht.ini
@@ -0,0 +1,2 @@
+[content-068.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-070.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-070.xht.ini
new file mode 100644
index 00000000000..397ef880c7e
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-070.xht.ini
@@ -0,0 +1,2 @@
+[content-070.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-072.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-072.xht.ini
new file mode 100644
index 00000000000..1a48e77c1ca
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-072.xht.ini
@@ -0,0 +1,2 @@
+[content-072.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-073.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-073.xht.ini
new file mode 100644
index 00000000000..64f361a4929
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-073.xht.ini
@@ -0,0 +1,2 @@
+[content-073.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-075.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-075.xht.ini
new file mode 100644
index 00000000000..8d777f9e0cc
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-075.xht.ini
@@ -0,0 +1,2 @@
+[content-075.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-076.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-076.xht.ini
new file mode 100644
index 00000000000..5c7f2cdc4d8
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-076.xht.ini
@@ -0,0 +1,2 @@
+[content-076.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-077.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-077.xht.ini
new file mode 100644
index 00000000000..bb0c2878460
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-077.xht.ini
@@ -0,0 +1,2 @@
+[content-077.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-080.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-080.xht.ini
new file mode 100644
index 00000000000..24fca12d0dd
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-080.xht.ini
@@ -0,0 +1,2 @@
+[content-080.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-081.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-081.xht.ini
new file mode 100644
index 00000000000..b7e84a0ae3d
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-081.xht.ini
@@ -0,0 +1,2 @@
+[content-081.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-082.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-082.xht.ini
new file mode 100644
index 00000000000..b7fe80a3612
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-082.xht.ini
@@ -0,0 +1,2 @@
+[content-082.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-083.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-083.xht.ini
new file mode 100644
index 00000000000..98d9750ca56
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-083.xht.ini
@@ -0,0 +1,2 @@
+[content-083.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-085.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-085.xht.ini
new file mode 100644
index 00000000000..c36c5f28065
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-085.xht.ini
@@ -0,0 +1,2 @@
+[content-085.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-086.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-086.xht.ini
new file mode 100644
index 00000000000..4bcc74b9e98
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-086.xht.ini
@@ -0,0 +1,2 @@
+[content-086.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-089.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-089.xht.ini
new file mode 100644
index 00000000000..9be53ac8af7
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-089.xht.ini
@@ -0,0 +1,2 @@
+[content-089.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-090.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-090.xht.ini
new file mode 100644
index 00000000000..8f692e0192e
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-090.xht.ini
@@ -0,0 +1,2 @@
+[content-090.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-091.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-091.xht.ini
new file mode 100644
index 00000000000..8c44f8a727e
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-091.xht.ini
@@ -0,0 +1,2 @@
+[content-091.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-096.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-096.xht.ini
new file mode 100644
index 00000000000..e290d19a5d7
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-096.xht.ini
@@ -0,0 +1,2 @@
+[content-096.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-097.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-097.xht.ini
new file mode 100644
index 00000000000..17fe2fa1b34
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-097.xht.ini
@@ -0,0 +1,2 @@
+[content-097.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-099.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-099.xht.ini
new file mode 100644
index 00000000000..eee1288f410
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-099.xht.ini
@@ -0,0 +1,2 @@
+[content-099.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-100.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-100.xht.ini
new file mode 100644
index 00000000000..639d5fcdc8d
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-100.xht.ini
@@ -0,0 +1,2 @@
+[content-100.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-103.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-103.xht.ini
new file mode 100644
index 00000000000..7df6c41cff5
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-103.xht.ini
@@ -0,0 +1,2 @@
+[content-103.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-105.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-105.xht.ini
new file mode 100644
index 00000000000..29fae9eec9e
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-105.xht.ini
@@ -0,0 +1,2 @@
+[content-105.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-109.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-109.xht.ini
new file mode 100644
index 00000000000..3fed7d41624
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-109.xht.ini
@@ -0,0 +1,2 @@
+[content-109.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-113.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-113.xht.ini
new file mode 100644
index 00000000000..13bd3922dbb
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-113.xht.ini
@@ -0,0 +1,2 @@
+[content-113.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-122.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-122.xht.ini
new file mode 100644
index 00000000000..82275f32b5f
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-122.xht.ini
@@ -0,0 +1,2 @@
+[content-122.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-123.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-123.xht.ini
new file mode 100644
index 00000000000..87d67c7ed86
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-123.xht.ini
@@ -0,0 +1,2 @@
+[content-123.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-126.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-126.xht.ini
new file mode 100644
index 00000000000..309532c3473
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-126.xht.ini
@@ -0,0 +1,2 @@
+[content-126.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-127.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-127.xht.ini
new file mode 100644
index 00000000000..e91e9bc86ed
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-127.xht.ini
@@ -0,0 +1,2 @@
+[content-127.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-129.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-129.xht.ini
new file mode 100644
index 00000000000..176fb737186
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-129.xht.ini
@@ -0,0 +1,2 @@
+[content-129.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-131.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-131.xht.ini
new file mode 100644
index 00000000000..d8fafac4a1f
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-131.xht.ini
@@ -0,0 +1,2 @@
+[content-131.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-132.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-132.xht.ini
new file mode 100644
index 00000000000..018ba9b20de
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-132.xht.ini
@@ -0,0 +1,2 @@
+[content-132.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-135.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-135.xht.ini
new file mode 100644
index 00000000000..7afbb752485
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-135.xht.ini
@@ -0,0 +1,2 @@
+[content-135.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-136.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-136.xht.ini
new file mode 100644
index 00000000000..1c9ecc23cd1
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-136.xht.ini
@@ -0,0 +1,2 @@
+[content-136.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-138.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-138.xht.ini
new file mode 100644
index 00000000000..f27ea134f5a
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-138.xht.ini
@@ -0,0 +1,2 @@
+[content-138.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-141.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-141.xht.ini
new file mode 100644
index 00000000000..3ceb8673e6a
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-141.xht.ini
@@ -0,0 +1,2 @@
+[content-141.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-143.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-143.xht.ini
new file mode 100644
index 00000000000..3bbf03acd0f
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-143.xht.ini
@@ -0,0 +1,2 @@
+[content-143.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-144.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-144.xht.ini
new file mode 100644
index 00000000000..d13329af770
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-144.xht.ini
@@ -0,0 +1,2 @@
+[content-144.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-145.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-145.xht.ini
new file mode 100644
index 00000000000..fd45b0a544a
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-145.xht.ini
@@ -0,0 +1,2 @@
+[content-145.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-146.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-146.xht.ini
new file mode 100644
index 00000000000..dbf1acbb8bf
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-146.xht.ini
@@ -0,0 +1,2 @@
+[content-146.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-147.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-147.xht.ini
new file mode 100644
index 00000000000..1d1b252a89c
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-147.xht.ini
@@ -0,0 +1,2 @@
+[content-147.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-149.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-149.xht.ini
new file mode 100644
index 00000000000..1f2bcb42bb9
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-149.xht.ini
@@ -0,0 +1,2 @@
+[content-149.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-150.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-150.xht.ini
new file mode 100644
index 00000000000..0c2f70e8202
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-150.xht.ini
@@ -0,0 +1,2 @@
+[content-150.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-152.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-152.xht.ini
new file mode 100644
index 00000000000..5c40b2c07ab
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-152.xht.ini
@@ -0,0 +1,2 @@
+[content-152.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-153.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-153.xht.ini
new file mode 100644
index 00000000000..42275aa9af4
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-153.xht.ini
@@ -0,0 +1,2 @@
+[content-153.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-155.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-155.xht.ini
new file mode 100644
index 00000000000..bdfb2ac2935
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-155.xht.ini
@@ -0,0 +1,2 @@
+[content-155.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-158.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-158.xht.ini
new file mode 100644
index 00000000000..27b90b85080
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-158.xht.ini
@@ -0,0 +1,2 @@
+[content-158.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-attr-case-001.html.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-attr-case-001.html.ini
new file mode 100644
index 00000000000..1cb6c0fdb8a
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-attr-case-001.html.ini
@@ -0,0 +1,2 @@
+[content-attr-case-001.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/content-white-space-002.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/content-white-space-002.xht.ini
new file mode 100644
index 00000000000..d9895725434
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/content-white-space-002.xht.ini
@@ -0,0 +1,2 @@
+[content-white-space-002.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/counters-hidden-002.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/counters-hidden-002.xht.ini
new file mode 100644
index 00000000000..d78930678da
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/counters-hidden-002.xht.ini
@@ -0,0 +1,2 @@
+[counters-hidden-002.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/counters-multi-000.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/counters-multi-000.xht.ini
new file mode 100644
index 00000000000..e7d4eb1814f
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/counters-multi-000.xht.ini
@@ -0,0 +1,2 @@
+[counters-multi-000.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/counters-multi-001.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/counters-multi-001.xht.ini
new file mode 100644
index 00000000000..3d3bb16b81c
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/counters-multi-001.xht.ini
@@ -0,0 +1,2 @@
+[counters-multi-001.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/generated-content/counters-order-000.xht.ini b/tests/wpt/metadata/css/CSS2/generated-content/counters-order-000.xht.ini
new file mode 100644
index 00000000000..f3def3f9f20
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/generated-content/counters-order-000.xht.ini
@@ -0,0 +1,2 @@
+[counters-order-000.xht]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/visudet/line-height-204.html.ini b/tests/wpt/metadata/css/CSS2/visudet/line-height-204.html.ini
new file mode 100644
index 00000000000..3d28990c283
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/visudet/line-height-204.html.ini
@@ -0,0 +1,2 @@
+[line-height-204.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/CSS2/visudet/line-height-205.html.ini b/tests/wpt/metadata/css/CSS2/visudet/line-height-205.html.ini
new file mode 100644
index 00000000000..540feb5e7ee
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/visudet/line-height-205.html.ini
@@ -0,0 +1,2 @@
+[line-height-205.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/css-animations/animation-delay-011.html.ini b/tests/wpt/metadata/css/css-animations/animation-delay-011.html.ini
new file mode 100644
index 00000000000..78b88159561
--- /dev/null
+++ b/tests/wpt/metadata/css/css-animations/animation-delay-011.html.ini
@@ -0,0 +1,2 @@
+[animation-delay-011.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/css-backgrounds/background-color-body-propagation-003.html.ini b/tests/wpt/metadata/css/css-backgrounds/background-color-body-propagation-003.html.ini
new file mode 100644
index 00000000000..1a916e0c7d8
--- /dev/null
+++ b/tests/wpt/metadata/css/css-backgrounds/background-color-body-propagation-003.html.ini
@@ -0,0 +1,2 @@
+[background-color-body-propagation-003.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/css-backgrounds/background-image-none-gradient-repaint.html.ini b/tests/wpt/metadata/css/css-backgrounds/background-image-none-gradient-repaint.html.ini
new file mode 100644
index 00000000000..edbd34d5956
--- /dev/null
+++ b/tests/wpt/metadata/css/css-backgrounds/background-image-none-gradient-repaint.html.ini
@@ -0,0 +1,2 @@
+[background-image-none-gradient-repaint.html]
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/css/css-backgrounds/border-radius-011.xht.ini b/tests/wpt/metadata/css/css-backgrounds/border-radius-011.xht.ini
deleted file mode 100644
index 092cc2c9a25..00000000000
--- a/tests/wpt/metadata/css/css-backgrounds/border-radius-011.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[border-radius-011.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-backgrounds/box-shadow-syntax-001.xht.ini b/tests/wpt/metadata/css/css-backgrounds/box-shadow-syntax-001.xht.ini
index bb9b1b76687..47a52ac2420 100644
--- a/tests/wpt/metadata/css/css-backgrounds/box-shadow-syntax-001.xht.ini
+++ b/tests/wpt/metadata/css/css-backgrounds/box-shadow-syntax-001.xht.ini
@@ -1,3 +1,3 @@
[box-shadow-syntax-001.xht]
type: reftest
- expected: FAIL
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/css/css-block/quotes-applies-to-011.xht.ini b/tests/wpt/metadata/css/css-block/quotes-applies-to-011.xht.ini
deleted file mode 100644
index ed5af0a4bf5..00000000000
--- a/tests/wpt/metadata/css/css-block/quotes-applies-to-011.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[quotes-applies-to-011.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-abspos-between-001.xht.ini b/tests/wpt/metadata/css/css-block/run-in-abspos-between-001.xht.ini
deleted file mode 100644
index c63f10d6610..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-abspos-between-001.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-abspos-between-001.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-abspos-between-002.xht.ini b/tests/wpt/metadata/css/css-block/run-in-abspos-between-002.xht.ini
deleted file mode 100644
index 532fd4a6c64..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-abspos-between-002.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-abspos-between-002.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-basic-001.xht.ini b/tests/wpt/metadata/css/css-block/run-in-basic-001.xht.ini
deleted file mode 100644
index d1facc3ff9d..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-basic-001.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-basic-001.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-basic-002.xht.ini b/tests/wpt/metadata/css/css-block/run-in-basic-002.xht.ini
deleted file mode 100644
index 5e0f7cab79d..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-basic-002.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-basic-002.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-basic-003.xht.ini b/tests/wpt/metadata/css/css-block/run-in-basic-003.xht.ini
deleted file mode 100644
index d842dfe24fa..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-basic-003.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-basic-003.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-basic-004.xht.ini b/tests/wpt/metadata/css/css-block/run-in-basic-004.xht.ini
deleted file mode 100644
index 89d86cda3ba..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-basic-004.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-basic-004.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-basic-005.xht.ini b/tests/wpt/metadata/css/css-block/run-in-basic-005.xht.ini
deleted file mode 100644
index 9f3549d7d72..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-basic-005.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-basic-005.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-basic-006.xht.ini b/tests/wpt/metadata/css/css-block/run-in-basic-006.xht.ini
deleted file mode 100644
index e013afeb14a..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-basic-006.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-basic-006.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-basic-007.xht.ini b/tests/wpt/metadata/css/css-block/run-in-basic-007.xht.ini
deleted file mode 100644
index 8b7061b2d6d..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-basic-007.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-basic-007.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-basic-008.xht.ini b/tests/wpt/metadata/css/css-block/run-in-basic-008.xht.ini
deleted file mode 100644
index a6aa69fbbb2..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-basic-008.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-basic-008.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-basic-009.xht.ini b/tests/wpt/metadata/css/css-block/run-in-basic-009.xht.ini
deleted file mode 100644
index 317f92249b8..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-basic-009.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-basic-009.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-basic-010.xht.ini b/tests/wpt/metadata/css/css-block/run-in-basic-010.xht.ini
deleted file mode 100644
index d5e21f21a5e..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-basic-010.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-basic-010.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-basic-011.xht.ini b/tests/wpt/metadata/css/css-block/run-in-basic-011.xht.ini
deleted file mode 100644
index a7bf9a8cda3..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-basic-011.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-basic-011.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-basic-012.xht.ini b/tests/wpt/metadata/css/css-block/run-in-basic-012.xht.ini
deleted file mode 100644
index 46f20410883..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-basic-012.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-basic-012.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-basic-013.xht.ini b/tests/wpt/metadata/css/css-block/run-in-basic-013.xht.ini
deleted file mode 100644
index c3c3fc25883..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-basic-013.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-basic-013.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-basic-018.xht.ini b/tests/wpt/metadata/css/css-block/run-in-basic-018.xht.ini
deleted file mode 100644
index 4123f0e8e4c..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-basic-018.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-basic-018.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-block-between-003.xht.ini b/tests/wpt/metadata/css/css-block/run-in-block-between-003.xht.ini
deleted file mode 100644
index afb953280aa..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-block-between-003.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-block-between-003.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-breaking-001.xht.ini b/tests/wpt/metadata/css/css-block/run-in-breaking-001.xht.ini
deleted file mode 100644
index 047bc8a9530..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-breaking-001.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-breaking-001.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-breaking-002.xht.ini b/tests/wpt/metadata/css/css-block/run-in-breaking-002.xht.ini
deleted file mode 100644
index 0a4a610bd8e..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-breaking-002.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-breaking-002.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-clear-001.xht.ini b/tests/wpt/metadata/css/css-block/run-in-clear-001.xht.ini
deleted file mode 100644
index d78f8082fa1..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-clear-001.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-clear-001.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-clear-002.xht.ini b/tests/wpt/metadata/css/css-block/run-in-clear-002.xht.ini
deleted file mode 100644
index 25dc6f9c838..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-clear-002.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-clear-002.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-contains-abspos-001.xht.ini b/tests/wpt/metadata/css/css-block/run-in-contains-abspos-001.xht.ini
deleted file mode 100644
index 7b81ce1acbb..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-contains-abspos-001.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-contains-abspos-001.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-contains-block-003.xht.ini b/tests/wpt/metadata/css/css-block/run-in-contains-block-003.xht.ini
deleted file mode 100644
index cc3d96209b9..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-contains-block-003.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-contains-block-003.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-contains-block-005.xht.ini b/tests/wpt/metadata/css/css-block/run-in-contains-block-005.xht.ini
deleted file mode 100644
index 837636b3ae2..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-contains-block-005.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-contains-block-005.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-contains-block-inside-inline-003.xht.ini b/tests/wpt/metadata/css/css-block/run-in-contains-block-inside-inline-003.xht.ini
deleted file mode 100644
index 06ca32d3539..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-contains-block-inside-inline-003.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-contains-block-inside-inline-003.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-contains-float-001.xht.ini b/tests/wpt/metadata/css/css-block/run-in-contains-float-001.xht.ini
deleted file mode 100644
index a23d51a45be..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-contains-float-001.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-contains-float-001.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-contains-inline-001.xht.ini b/tests/wpt/metadata/css/css-block/run-in-contains-inline-001.xht.ini
deleted file mode 100644
index 0b7c5a95abf..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-contains-inline-001.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-contains-inline-001.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-contains-inline-002.xht.ini b/tests/wpt/metadata/css/css-block/run-in-contains-inline-002.xht.ini
deleted file mode 100644
index 5080238f437..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-contains-inline-002.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-contains-inline-002.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-contains-inline-003.xht.ini b/tests/wpt/metadata/css/css-block/run-in-contains-inline-003.xht.ini
deleted file mode 100644
index 8509249a633..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-contains-inline-003.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-contains-inline-003.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-contains-inline-004.xht.ini b/tests/wpt/metadata/css/css-block/run-in-contains-inline-004.xht.ini
deleted file mode 100644
index c754f9757a5..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-contains-inline-004.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-contains-inline-004.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-contains-inline-005.xht.ini b/tests/wpt/metadata/css/css-block/run-in-contains-inline-005.xht.ini
deleted file mode 100644
index aefb8f516ce..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-contains-inline-005.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-contains-inline-005.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-contains-inline-006.xht.ini b/tests/wpt/metadata/css/css-block/run-in-contains-inline-006.xht.ini
deleted file mode 100644
index 94b62103c4b..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-contains-inline-006.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-contains-inline-006.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-contains-inline-007.xht.ini b/tests/wpt/metadata/css/css-block/run-in-contains-inline-007.xht.ini
deleted file mode 100644
index e89498c8345..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-contains-inline-007.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-contains-inline-007.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-contains-inline-block-001.xht.ini b/tests/wpt/metadata/css/css-block/run-in-contains-inline-block-001.xht.ini
deleted file mode 100644
index 82dd3400196..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-contains-inline-block-001.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-contains-inline-block-001.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-contains-inline-table-001.xht.ini b/tests/wpt/metadata/css/css-block/run-in-contains-inline-table-001.xht.ini
deleted file mode 100644
index c4fe591657c..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-contains-inline-table-001.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-contains-inline-table-001.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-contains-relpos-block-003.xht.ini b/tests/wpt/metadata/css/css-block/run-in-contains-relpos-block-003.xht.ini
deleted file mode 100644
index 1bcdcc4bf6a..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-contains-relpos-block-003.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-contains-relpos-block-003.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-contains-run-in-003.xht.ini b/tests/wpt/metadata/css/css-block/run-in-contains-run-in-003.xht.ini
deleted file mode 100644
index 4f151c9ee33..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-contains-run-in-003.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-contains-run-in-003.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-contains-table-003.xht.ini b/tests/wpt/metadata/css/css-block/run-in-contains-table-003.xht.ini
deleted file mode 100644
index 14445ee94b8..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-contains-table-003.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-contains-table-003.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-contains-table-caption-001.xht.ini b/tests/wpt/metadata/css/css-block/run-in-contains-table-caption-001.xht.ini
deleted file mode 100644
index 894f7801570..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-contains-table-caption-001.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-contains-table-caption-001.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-contains-table-cell-001.xht.ini b/tests/wpt/metadata/css/css-block/run-in-contains-table-cell-001.xht.ini
deleted file mode 100644
index 65009b73029..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-contains-table-cell-001.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-contains-table-cell-001.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-contains-table-column-001.xht.ini b/tests/wpt/metadata/css/css-block/run-in-contains-table-column-001.xht.ini
deleted file mode 100644
index 28ccae4a7d4..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-contains-table-column-001.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-contains-table-column-001.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-contains-table-column-group-001.xht.ini b/tests/wpt/metadata/css/css-block/run-in-contains-table-column-group-001.xht.ini
deleted file mode 100644
index eea7c6b24e4..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-contains-table-column-group-001.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-contains-table-column-group-001.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-contains-table-inside-inline-003.xht.ini b/tests/wpt/metadata/css/css-block/run-in-contains-table-inside-inline-003.xht.ini
deleted file mode 100644
index 8ba292cc3bb..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-contains-table-inside-inline-003.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-contains-table-inside-inline-003.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-contains-table-row-001.xht.ini b/tests/wpt/metadata/css/css-block/run-in-contains-table-row-001.xht.ini
deleted file mode 100644
index 025135439a9..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-contains-table-row-001.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-contains-table-row-001.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-contains-table-row-group-001.xht.ini b/tests/wpt/metadata/css/css-block/run-in-contains-table-row-group-001.xht.ini
deleted file mode 100644
index bd77b3d2fed..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-contains-table-row-group-001.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-contains-table-row-group-001.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-display-none-between-001.xht.ini b/tests/wpt/metadata/css/css-block/run-in-display-none-between-001.xht.ini
deleted file mode 100644
index 4d330f1bbfc..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-display-none-between-001.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-display-none-between-001.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-display-none-between-002.xht.ini b/tests/wpt/metadata/css/css-block/run-in-display-none-between-002.xht.ini
deleted file mode 100644
index b82c5fec663..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-display-none-between-002.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-display-none-between-002.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-fixedpos-between-001.xht.ini b/tests/wpt/metadata/css/css-block/run-in-fixedpos-between-001.xht.ini
deleted file mode 100644
index 23a614fa29b..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-fixedpos-between-001.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-fixedpos-between-001.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-fixedpos-between-002.xht.ini b/tests/wpt/metadata/css/css-block/run-in-fixedpos-between-002.xht.ini
deleted file mode 100644
index 84fb7c576b6..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-fixedpos-between-002.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-fixedpos-between-002.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-float-between-001.xht.ini b/tests/wpt/metadata/css/css-block/run-in-float-between-001.xht.ini
deleted file mode 100644
index 16c2e40fcb8..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-float-between-001.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-float-between-001.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-float-between-002.xht.ini b/tests/wpt/metadata/css/css-block/run-in-float-between-002.xht.ini
deleted file mode 100644
index 5d1ae86d452..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-float-between-002.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-float-between-002.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-inherit-001.xht.ini b/tests/wpt/metadata/css/css-block/run-in-inherit-001.xht.ini
deleted file mode 100644
index e4d5c3718ff..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-inherit-001.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-inherit-001.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-inline-between-003.xht.ini b/tests/wpt/metadata/css/css-block/run-in-inline-between-003.xht.ini
deleted file mode 100644
index 4cbb1927126..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-inline-between-003.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-inline-between-003.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-inline-block-between-003.xht.ini b/tests/wpt/metadata/css/css-block/run-in-inline-block-between-003.xht.ini
deleted file mode 100644
index 94e42aacc1a..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-inline-block-between-003.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-inline-block-between-003.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-inline-table-between-003.xht.ini b/tests/wpt/metadata/css/css-block/run-in-inline-table-between-003.xht.ini
deleted file mode 100644
index 5e58af7fd2b..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-inline-table-between-003.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-inline-table-between-003.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-listitem-between-001.xht.ini b/tests/wpt/metadata/css/css-block/run-in-listitem-between-001.xht.ini
deleted file mode 100644
index c8cf3528516..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-listitem-between-001.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-listitem-between-001.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-listitem-between-002.xht.ini b/tests/wpt/metadata/css/css-block/run-in-listitem-between-002.xht.ini
deleted file mode 100644
index b1cf7538d12..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-listitem-between-002.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-listitem-between-002.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-listitem-between-003.xht.ini b/tests/wpt/metadata/css/css-block/run-in-listitem-between-003.xht.ini
deleted file mode 100644
index 7fa6fa57f86..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-listitem-between-003.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-listitem-between-003.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-relpos-between-003.xht.ini b/tests/wpt/metadata/css/css-block/run-in-relpos-between-003.xht.ini
deleted file mode 100644
index ee18b60783a..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-relpos-between-003.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-relpos-between-003.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-replaced-001.xht.ini b/tests/wpt/metadata/css/css-block/run-in-replaced-001.xht.ini
deleted file mode 100644
index 8e2460e8a0a..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-replaced-001.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-replaced-001.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-restyle-003.xht.ini b/tests/wpt/metadata/css/css-block/run-in-restyle-003.xht.ini
deleted file mode 100644
index 99060956c70..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-restyle-003.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-restyle-003.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-run-in-between-003.xht.ini b/tests/wpt/metadata/css/css-block/run-in-run-in-between-003.xht.ini
deleted file mode 100644
index 913bd257979..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-run-in-between-003.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-run-in-between-003.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-run-in-between-004.xht.ini b/tests/wpt/metadata/css/css-block/run-in-run-in-between-004.xht.ini
deleted file mode 100644
index 27b01f4dfab..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-run-in-between-004.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-run-in-between-004.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-run-in-between-005.xht.ini b/tests/wpt/metadata/css/css-block/run-in-run-in-between-005.xht.ini
deleted file mode 100644
index a27522207f3..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-run-in-between-005.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-run-in-between-005.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-run-in-between-006.xht.ini b/tests/wpt/metadata/css/css-block/run-in-run-in-between-006.xht.ini
deleted file mode 100644
index a89e0e18cfe..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-run-in-between-006.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-run-in-between-006.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-run-in-between-007.xht.ini b/tests/wpt/metadata/css/css-block/run-in-run-in-between-007.xht.ini
deleted file mode 100644
index e9740569069..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-run-in-between-007.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-run-in-between-007.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-table-between-003.xht.ini b/tests/wpt/metadata/css/css-block/run-in-table-between-003.xht.ini
deleted file mode 100644
index 764fe74a9ea..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-table-between-003.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-table-between-003.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-table-cell-between-003.xht.ini b/tests/wpt/metadata/css/css-block/run-in-table-cell-between-003.xht.ini
deleted file mode 100644
index 46da2ca4125..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-table-cell-between-003.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-table-cell-between-003.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-table-row-between-003.xht.ini b/tests/wpt/metadata/css/css-block/run-in-table-row-between-003.xht.ini
deleted file mode 100644
index e2bf1c42371..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-table-row-between-003.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-table-row-between-003.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-text-between-004.xht.ini b/tests/wpt/metadata/css/css-block/run-in-text-between-004.xht.ini
deleted file mode 100644
index fac83125988..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-text-between-004.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-text-between-004.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-block/run-in-text-between-005.xht.ini b/tests/wpt/metadata/css/css-block/run-in-text-between-005.xht.ini
deleted file mode 100644
index 2e94491740e..00000000000
--- a/tests/wpt/metadata/css/css-block/run-in-text-between-005.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[run-in-text-between-005.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-color/color-001.html.ini b/tests/wpt/metadata/css/css-color/color-001.html.ini
deleted file mode 100644
index ffaf684f384..00000000000
--- a/tests/wpt/metadata/css/css-color/color-001.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[color-001.html]
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-color/color-003.html.ini b/tests/wpt/metadata/css/css-color/color-003.html.ini
deleted file mode 100644
index 0e638df7b46..00000000000
--- a/tests/wpt/metadata/css/css-color/color-003.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[color-003.html]
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-color/currentcolor-001.html.ini b/tests/wpt/metadata/css/css-color/currentcolor-001.html.ini
deleted file mode 100644
index c9861c726c5..00000000000
--- a/tests/wpt/metadata/css/css-color/currentcolor-001.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[currentcolor-001.html]
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-color/currentcolor-002.html.ini b/tests/wpt/metadata/css/css-color/currentcolor-002.html.ini
deleted file mode 100644
index 6eb6550c070..00000000000
--- a/tests/wpt/metadata/css/css-color/currentcolor-002.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[currentcolor-002.html]
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-color/hex-001.html.ini b/tests/wpt/metadata/css/css-color/hex-001.html.ini
deleted file mode 100644
index 5b223d8822f..00000000000
--- a/tests/wpt/metadata/css/css-color/hex-001.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[hex-001.html]
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-color/hex-002.html.ini b/tests/wpt/metadata/css/css-color/hex-002.html.ini
deleted file mode 100644
index 7d7e587c206..00000000000
--- a/tests/wpt/metadata/css/css-color/hex-002.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[hex-002.html]
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-flexbox/anonymous-flex-item-001.html.ini b/tests/wpt/metadata/css/css-flexbox/anonymous-flex-item-001.html.ini
new file mode 100644
index 00000000000..b22638a8537
--- /dev/null
+++ b/tests/wpt/metadata/css/css-flexbox/anonymous-flex-item-001.html.ini
@@ -0,0 +1,2 @@
+[anonymous-flex-item-001.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/css-flexbox/anonymous-flex-item-003.html.ini b/tests/wpt/metadata/css/css-flexbox/anonymous-flex-item-003.html.ini
new file mode 100644
index 00000000000..331eec32683
--- /dev/null
+++ b/tests/wpt/metadata/css/css-flexbox/anonymous-flex-item-003.html.ini
@@ -0,0 +1,2 @@
+[anonymous-flex-item-003.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/css-flexbox/anonymous-flex-item-005.html.ini b/tests/wpt/metadata/css/css-flexbox/anonymous-flex-item-005.html.ini
new file mode 100644
index 00000000000..f5db1aa1610
--- /dev/null
+++ b/tests/wpt/metadata/css/css-flexbox/anonymous-flex-item-005.html.ini
@@ -0,0 +1,2 @@
+[anonymous-flex-item-005.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/css-flexbox/anonymous-flex-item-006.html.ini b/tests/wpt/metadata/css/css-flexbox/anonymous-flex-item-006.html.ini
new file mode 100644
index 00000000000..5865ea15bc8
--- /dev/null
+++ b/tests/wpt/metadata/css/css-flexbox/anonymous-flex-item-006.html.ini
@@ -0,0 +1,2 @@
+[anonymous-flex-item-006.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/css-flexbox/percentage-heights-004.html.ini b/tests/wpt/metadata/css/css-flexbox/percentage-heights-004.html.ini
new file mode 100644
index 00000000000..988af23e1f6
--- /dev/null
+++ b/tests/wpt/metadata/css/css-flexbox/percentage-heights-004.html.ini
@@ -0,0 +1,2 @@
+[percentage-heights-004.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/css-flexbox/table-as-item-narrow-content.html.ini b/tests/wpt/metadata/css/css-flexbox/table-as-item-narrow-content.html.ini
new file mode 100644
index 00000000000..194e30876c1
--- /dev/null
+++ b/tests/wpt/metadata/css/css-flexbox/table-as-item-narrow-content.html.ini
@@ -0,0 +1,2 @@
+[table-as-item-narrow-content.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/css-flexbox/table-as-item-wide-content.html.ini b/tests/wpt/metadata/css/css-flexbox/table-as-item-wide-content.html.ini
new file mode 100644
index 00000000000..f6def90a63b
--- /dev/null
+++ b/tests/wpt/metadata/css/css-flexbox/table-as-item-wide-content.html.ini
@@ -0,0 +1,2 @@
+[table-as-item-wide-content.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/css-multicol/multicol-count-computed-001.xht.ini b/tests/wpt/metadata/css/css-multicol/multicol-count-computed-001.xht.ini
deleted file mode 100644
index 0ec74934be1..00000000000
--- a/tests/wpt/metadata/css/css-multicol/multicol-count-computed-001.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[multicol-count-computed-001.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-multicol/multicol-count-computed-002.xht.ini b/tests/wpt/metadata/css/css-multicol/multicol-count-computed-002.xht.ini
deleted file mode 100644
index 08c18e5950c..00000000000
--- a/tests/wpt/metadata/css/css-multicol/multicol-count-computed-002.xht.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[multicol-count-computed-002.xht]
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-multicol/multicol-count-large-001.xht.ini b/tests/wpt/metadata/css/css-multicol/multicol-count-large-001.xht.ini
deleted file mode 100644
index ab7602c8729..00000000000
--- a/tests/wpt/metadata/css/css-multicol/multicol-count-large-001.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[multicol-count-large-001.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-multicol/multicol-count-large-002.xht.ini b/tests/wpt/metadata/css/css-multicol/multicol-count-large-002.xht.ini
deleted file mode 100644
index e5ea24727e4..00000000000
--- a/tests/wpt/metadata/css/css-multicol/multicol-count-large-002.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[multicol-count-large-002.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-multicol/multicol-fill-auto.xht.ini b/tests/wpt/metadata/css/css-multicol/multicol-fill-auto.xht.ini
deleted file mode 100644
index 2444eb2c3d9..00000000000
--- a/tests/wpt/metadata/css/css-multicol/multicol-fill-auto.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[multicol-fill-auto.xht]
- type: reftest
- expected: TIMEOUT
diff --git a/tests/wpt/metadata/css/css-multicol/multicol-inherit-004.xht.ini b/tests/wpt/metadata/css/css-multicol/multicol-inherit-004.xht.ini
deleted file mode 100644
index 7091b9d314d..00000000000
--- a/tests/wpt/metadata/css/css-multicol/multicol-inherit-004.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[multicol-inherit-004.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-multicol/multicol-rule-style-groove-001.xht.ini b/tests/wpt/metadata/css/css-multicol/multicol-rule-style-groove-001.xht.ini
deleted file mode 100644
index 86b889128e3..00000000000
--- a/tests/wpt/metadata/css/css-multicol/multicol-rule-style-groove-001.xht.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[multicol-rule-style-groove-001.xht]
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-multicol/multicol-rule-style-inset-001.xht.ini b/tests/wpt/metadata/css/css-multicol/multicol-rule-style-inset-001.xht.ini
deleted file mode 100644
index da85daf7e38..00000000000
--- a/tests/wpt/metadata/css/css-multicol/multicol-rule-style-inset-001.xht.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[multicol-rule-style-inset-001.xht]
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-multicol/multicol-rule-style-outset-001.xht.ini b/tests/wpt/metadata/css/css-multicol/multicol-rule-style-outset-001.xht.ini
deleted file mode 100644
index 9755d370914..00000000000
--- a/tests/wpt/metadata/css/css-multicol/multicol-rule-style-outset-001.xht.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[multicol-rule-style-outset-001.xht]
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-multicol/multicol-rule-style-ridge-001.xht.ini b/tests/wpt/metadata/css/css-multicol/multicol-rule-style-ridge-001.xht.ini
deleted file mode 100644
index 3163cb42b9d..00000000000
--- a/tests/wpt/metadata/css/css-multicol/multicol-rule-style-ridge-001.xht.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[multicol-rule-style-ridge-001.xht]
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-multicol/multicol-span-all-child-001.xht.ini b/tests/wpt/metadata/css/css-multicol/multicol-span-all-child-001.xht.ini
deleted file mode 100644
index 3c4d7203d21..00000000000
--- a/tests/wpt/metadata/css/css-multicol/multicol-span-all-child-001.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[multicol-span-all-child-001.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-multicol/multicol-span-all-child-002.xht.ini b/tests/wpt/metadata/css/css-multicol/multicol-span-all-child-002.xht.ini
deleted file mode 100644
index 867a42a30ea..00000000000
--- a/tests/wpt/metadata/css/css-multicol/multicol-span-all-child-002.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[multicol-span-all-child-002.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-multicol/multicol-span-all-margin-nested-003.xht.ini b/tests/wpt/metadata/css/css-multicol/multicol-span-all-margin-nested-003.xht.ini
deleted file mode 100644
index 190b2195d7e..00000000000
--- a/tests/wpt/metadata/css/css-multicol/multicol-span-all-margin-nested-003.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[multicol-span-all-margin-nested-003.xht]
- type: reftest
- expected: TIMEOUT
diff --git a/tests/wpt/metadata/css/css-multicol/multicol-width-ems-001.xht.ini b/tests/wpt/metadata/css/css-multicol/multicol-width-ems-001.xht.ini
deleted file mode 100644
index 9aa34c830da..00000000000
--- a/tests/wpt/metadata/css/css-multicol/multicol-width-ems-001.xht.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[multicol-width-ems-001.xht]
- type: reftest
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-style-attr/style-attr-urls-003.xht.ini b/tests/wpt/metadata/css/css-style-attr/style-attr-urls-003.xht.ini
deleted file mode 100644
index d656c060555..00000000000
--- a/tests/wpt/metadata/css/css-style-attr/style-attr-urls-003.xht.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[style-attr-urls-003.xht]
- expected: FAIL
diff --git a/tests/wpt/metadata/css/css-text-decor/text-decoration-color.html.ini b/tests/wpt/metadata/css/css-text-decor/text-decoration-color.html.ini
new file mode 100644
index 00000000000..81c110041f6
--- /dev/null
+++ b/tests/wpt/metadata/css/css-text-decor/text-decoration-color.html.ini
@@ -0,0 +1,2 @@
+[text-decoration-color.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/css-text-decor/text-decoration-line-012.xht.ini b/tests/wpt/metadata/css/css-text-decor/text-decoration-line-012.xht.ini
deleted file mode 100644
index 1eacec34566..00000000000
--- a/tests/wpt/metadata/css/css-text-decor/text-decoration-line-012.xht.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[text-decoration-line-012.xht]
- type: reftest
- expected:
- if os == "mac": FAIL
diff --git a/tests/wpt/metadata/css/css-text-decor/text-decoration-serialization.tentative.html.ini b/tests/wpt/metadata/css/css-text-decor/text-decoration-serialization.tentative.html.ini
new file mode 100644
index 00000000000..501b9848c78
--- /dev/null
+++ b/tests/wpt/metadata/css/css-text-decor/text-decoration-serialization.tentative.html.ini
@@ -0,0 +1,4 @@
+[text-decoration-serialization.tentative.html]
+ [text-decoration shorthand serialization]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/css/css-transforms/transform-box/fill-box-mutation.html.ini b/tests/wpt/metadata/css/css-transforms/transform-box/fill-box-mutation.html.ini
new file mode 100644
index 00000000000..2a8fe8adfe7
--- /dev/null
+++ b/tests/wpt/metadata/css/css-transforms/transform-box/fill-box-mutation.html.ini
@@ -0,0 +1,2 @@
+[fill-box-mutation.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/css-transforms/transform-box/fill-box.html.ini b/tests/wpt/metadata/css/css-transforms/transform-box/fill-box.html.ini
new file mode 100644
index 00000000000..536029e626b
--- /dev/null
+++ b/tests/wpt/metadata/css/css-transforms/transform-box/fill-box.html.ini
@@ -0,0 +1,2 @@
+[fill-box.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/css-transforms/transform-box/value-changed.html.ini b/tests/wpt/metadata/css/css-transforms/transform-box/value-changed.html.ini
new file mode 100644
index 00000000000..0067c94bc23
--- /dev/null
+++ b/tests/wpt/metadata/css/css-transforms/transform-box/value-changed.html.ini
@@ -0,0 +1,2 @@
+[value-changed.html]
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/css/css-transforms/transform-box/view-box-nested.html.ini b/tests/wpt/metadata/css/css-transforms/transform-box/view-box-nested.html.ini
new file mode 100644
index 00000000000..d7b29996b28
--- /dev/null
+++ b/tests/wpt/metadata/css/css-transforms/transform-box/view-box-nested.html.ini
@@ -0,0 +1,2 @@
+[view-box-nested.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/css-transforms/transform-box/view-box-viewbox-nested.html.ini b/tests/wpt/metadata/css/css-transforms/transform-box/view-box-viewbox-nested.html.ini
new file mode 100644
index 00000000000..74ff4a1dfe9
--- /dev/null
+++ b/tests/wpt/metadata/css/css-transforms/transform-box/view-box-viewbox-nested.html.ini
@@ -0,0 +1,2 @@
+[view-box-viewbox-nested.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/css-transforms/transform-box/view-box-viewbox.html.ini b/tests/wpt/metadata/css/css-transforms/transform-box/view-box-viewbox.html.ini
new file mode 100644
index 00000000000..d628df64758
--- /dev/null
+++ b/tests/wpt/metadata/css/css-transforms/transform-box/view-box-viewbox.html.ini
@@ -0,0 +1,2 @@
+[view-box-viewbox.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/css-transforms/transform-box/view-box.html.ini b/tests/wpt/metadata/css/css-transforms/transform-box/view-box.html.ini
new file mode 100644
index 00000000000..53b0567e12d
--- /dev/null
+++ b/tests/wpt/metadata/css/css-transforms/transform-box/view-box.html.ini
@@ -0,0 +1,2 @@
+[view-box.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/css-ui/outline-014.html.ini b/tests/wpt/metadata/css/css-ui/outline-014.html.ini
index c07eb92e12b..89f88d32926 100644
--- a/tests/wpt/metadata/css/css-ui/outline-014.html.ini
+++ b/tests/wpt/metadata/css/css-ui/outline-014.html.ini
@@ -2,4 +2,3 @@
type: reftest
expected: FAIL
bug: https://github.com/servo/servo/issues/19508
-
diff --git a/tests/wpt/metadata/css/css-values/vh_not_refreshing_on_chrome.html.ini b/tests/wpt/metadata/css/css-values/vh_not_refreshing_on_chrome.html.ini
new file mode 100644
index 00000000000..26435e28b09
--- /dev/null
+++ b/tests/wpt/metadata/css/css-values/vh_not_refreshing_on_chrome.html.ini
@@ -0,0 +1,2 @@
+[vh_not_refreshing_on_chrome.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/cssom-view/scroll-behavior-smooth.html.ini b/tests/wpt/metadata/css/cssom-view/scroll-behavior-smooth.html.ini
new file mode 100644
index 00000000000..e1a609649d6
--- /dev/null
+++ b/tests/wpt/metadata/css/cssom-view/scroll-behavior-smooth.html.ini
@@ -0,0 +1,5 @@
+[scroll-behavior-smooth.html]
+ expected: ERROR
+ [scroll-behavior: smooth on DIV element]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/css/cssom/getComputedStyle-pseudo.html.ini b/tests/wpt/metadata/css/cssom/getComputedStyle-pseudo.html.ini
index f0d704bf616..114f59a0286 100644
--- a/tests/wpt/metadata/css/cssom/getComputedStyle-pseudo.html.ini
+++ b/tests/wpt/metadata/css/cssom/getComputedStyle-pseudo.html.ini
@@ -8,3 +8,6 @@
[Item-based blockification of nonexistent pseudo-elements]
expected: FAIL
+ [display: contents on pseudo-elements]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/css/cssom/medialist-dynamic-001.html.ini b/tests/wpt/metadata/css/cssom/medialist-dynamic-001.html.ini
new file mode 100644
index 00000000000..0d28942060d
--- /dev/null
+++ b/tests/wpt/metadata/css/cssom/medialist-dynamic-001.html.ini
@@ -0,0 +1,2 @@
+[medialist-dynamic-001.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/mediaqueries/test_media_queries.html.ini b/tests/wpt/metadata/css/mediaqueries/test_media_queries.html.ini
index 8210ee452cd..63f757ce648 100644
--- a/tests/wpt/metadata/css/mediaqueries/test_media_queries.html.ini
+++ b/tests/wpt/metadata/css/mediaqueries/test_media_queries.html.ini
@@ -227,600 +227,561 @@
[subtest_78]
expected: FAIL
- [subtest_79]
- expected: FAIL
-
- [subtest_82]
- expected: FAIL
-
- [subtest_84]
- expected: FAIL
-
- [subtest_85]
- expected: FAIL
-
- [subtest_86]
- expected: FAIL
-
- [subtest_89]
- expected: FAIL
-
- [subtest_90]
- expected: FAIL
-
- [subtest_92]
- expected: FAIL
-
- [subtest_95]
- expected: FAIL
-
- [subtest_97]
- expected: FAIL
-
- [subtest_98]
- expected: FAIL
-
- [subtest_99]
- expected: FAIL
-
- [subtest_102]
- expected: FAIL
-
- [subtest_103]
+ [subtest_141]
expected: FAIL
- [subtest_105]
+ [subtest_142]
expected: FAIL
- [subtest_108]
+ [subtest_143]
expected: FAIL
- [subtest_110]
+ [subtest_144]
expected: FAIL
- [subtest_111]
+ [subtest_145]
expected: FAIL
- [subtest_112]
+ [subtest_146]
expected: FAIL
- [subtest_115]
+ [subtest_147]
expected: FAIL
- [subtest_116]
+ [subtest_148]
expected: FAIL
- [subtest_118]
+ [subtest_149]
expected: FAIL
- [subtest_121]
+ [subtest_176]
expected: FAIL
- [subtest_123]
+ [subtest_182]
expected: FAIL
- [subtest_124]
+ [subtest_194]
expected: FAIL
- [subtest_125]
+ [subtest_200]
expected: FAIL
- [subtest_128]
+ [subtest_201]
expected: FAIL
- [subtest_129]
+ [subtest_202]
expected: FAIL
- [subtest_131]
+ [subtest_203]
expected: FAIL
- [subtest_135]
+ [subtest_204]
expected: FAIL
- [subtest_136]
+ [subtest_205]
expected: FAIL
- [subtest_138]
+ [subtest_206]
expected: FAIL
- [subtest_139]
+ [subtest_207]
expected: FAIL
- [subtest_140]
+ [subtest_208]
expected: FAIL
- [subtest_141]
+ [subtest_209]
expected: FAIL
- [subtest_142]
+ [subtest_210]
expected: FAIL
- [subtest_143]
+ [subtest_211]
expected: FAIL
- [subtest_144]
+ [subtest_212]
expected: FAIL
- [subtest_145]
+ [subtest_213]
expected: FAIL
- [subtest_146]
+ [subtest_214]
expected: FAIL
- [subtest_147]
+ [subtest_215]
expected: FAIL
- [subtest_148]
+ [subtest_216]
expected: FAIL
- [subtest_149]
+ [subtest_217]
expected: FAIL
- [subtest_150]
+ [subtest_218]
expected: FAIL
- [subtest_151]
+ [subtest_219]
expected: FAIL
- [subtest_153]
+ [subtest_220]
expected: FAIL
- [subtest_154]
+ [subtest_221]
expected: FAIL
- [subtest_156]
+ [subtest_222]
expected: FAIL
- [subtest_157]
+ [subtest_223]
expected: FAIL
- [subtest_158]
+ [subtest_224]
expected: FAIL
- [subtest_163]
+ [subtest_225]
expected: FAIL
- [subtest_164]
+ [subtest_226]
expected: FAIL
- [subtest_165]
+ [subtest_227]
expected: FAIL
- [subtest_170]
+ [subtest_228]
expected: FAIL
- [subtest_171]
+ [subtest_229]
expected: FAIL
- [subtest_172]
+ [subtest_230]
expected: FAIL
- [subtest_173]
+ [monochrome_and_color]
expected: FAIL
- [subtest_176]
+ [subtest_238]
expected: FAIL
- [subtest_177]
+ [subtest_239]
expected: FAIL
- [subtest_180]
+ [subtest_240]
expected: FAIL
- [subtest_181]
+ [subtest_241]
expected: FAIL
- [subtest_182]
+ [subtest_242]
expected: FAIL
- [subtest_183]
+ [subtest_244]
expected: FAIL
- [subtest_184]
+ [subtest_246]
expected: FAIL
- [subtest_187]
+ [subtest_247]
expected: FAIL
- [subtest_188]
+ [subtest_248]
expected: FAIL
- [subtest_189]
+ [subtest_249]
expected: FAIL
- [subtest_191]
+ [subtest_250]
expected: FAIL
- [subtest_193]
+ [subtest_251]
expected: FAIL
- [subtest_194]
+ [subtest_252]
expected: FAIL
- [subtest_195]
+ [subtest_253]
expected: FAIL
- [subtest_196]
+ [subtest_254]
expected: FAIL
- [subtest_197]
+ [subtest_255]
expected: FAIL
- [subtest_199]
+ [subtest_256]
expected: FAIL
- [subtest_200]
+ [subtest_257]
expected: FAIL
- [subtest_201]
+ [subtest_258]
expected: FAIL
- [subtest_202]
+ [subtest_259]
expected: FAIL
- [subtest_203]
+ [subtest_260]
expected: FAIL
- [subtest_204]
+ [subtest_261]
expected: FAIL
- [subtest_205]
+ [subtest_262]
expected: FAIL
- [subtest_206]
+ [subtest_263]
expected: FAIL
- [subtest_207]
+ [subtest_264]
expected: FAIL
- [subtest_208]
+ [subtest_272]
expected: FAIL
- [subtest_209]
+ [subtest_273]
expected: FAIL
- [subtest_210]
+ [subtest_274]
expected: FAIL
- [subtest_211]
+ [subtest_275]
expected: FAIL
- [subtest_212]
+ [subtest_276]
expected: FAIL
- [subtest_213]
+ [subtest_277]
expected: FAIL
- [subtest_214]
+ [subtest_278]
expected: FAIL
- [subtest_215]
+ [subtest_279]
expected: FAIL
- [subtest_216]
+ [subtest_280]
expected: FAIL
- [subtest_217]
+ [subtest_281]
expected: FAIL
- [subtest_218]
+ [subtest_282]
expected: FAIL
- [subtest_219]
+ [subtest_283]
expected: FAIL
- [subtest_220]
+ [subtest_284]
expected: FAIL
- [subtest_221]
+ [subtest_285]
expected: FAIL
- [subtest_222]
+ [subtest_286]
expected: FAIL
- [subtest_223]
+ [subtest_287]
expected: FAIL
- [subtest_224]
+ [subtest_288]
expected: FAIL
- [subtest_225]
+ [subtest_289]
expected: FAIL
- [subtest_226]
+ [subtest_290]
expected: FAIL
- [subtest_227]
+ [subtest_291]
expected: FAIL
- [subtest_228]
+ [subtest_292]
expected: FAIL
- [subtest_229]
+ [subtest_295]
expected: FAIL
- [subtest_230]
+ [subtest_297]
expected: FAIL
- [monochrome_and_color]
+ [subtest_299]
expected: FAIL
- [subtest_231]
+ [subtest_302]
expected: FAIL
- [subtest_234]
+ [subtest_304]
expected: FAIL
- [subtest_236]
+ [subtest_305]
expected: FAIL
- [subtest_238]
+ [subtest_306]
expected: FAIL
- [subtest_239]
+ [subtest_307]
expected: FAIL
- [subtest_240]
+ [subtest_308]
expected: FAIL
- [subtest_241]
+ [subtest_309]
expected: FAIL
- [subtest_242]
+ [subtest_313]
expected: FAIL
- [subtest_244]
+ [subtest_317]
expected: FAIL
- [subtest_246]
+ [subtest_318]
expected: FAIL
- [subtest_247]
+ [subtest_319]
expected: FAIL
- [subtest_248]
+ [subtest_320]
expected: FAIL
- [subtest_249]
+ [subtest_321]
expected: FAIL
- [subtest_250]
+ [subtest_322]
expected: FAIL
- [subtest_251]
+ [subtest_323]
expected: FAIL
- [subtest_252]
+ [subtest_324]
expected: FAIL
- [subtest_253]
+ [subtest_326]
expected: FAIL
- [subtest_254]
+ [subtest_330]
expected: FAIL
- [subtest_255]
+ [subtest_333]
expected: FAIL
- [subtest_256]
+ [subtest_335]
expected: FAIL
- [subtest_257]
+ [subtest_338]
expected: FAIL
- [subtest_258]
+ [subtest_340]
expected: FAIL
- [subtest_259]
+ [subtest_346]
expected: FAIL
- [subtest_260]
+ [subtest_350]
expected: FAIL
- [subtest_261]
+ [subtest_80]
expected: FAIL
- [subtest_262]
+ [subtest_81]
expected: FAIL
- [subtest_263]
+ [subtest_83]
expected: FAIL
- [subtest_264]
+ [subtest_87]
expected: FAIL
- [subtest_265]
+ [subtest_88]
expected: FAIL
- [subtest_267]
+ [subtest_91]
expected: FAIL
- [subtest_269]
+ [subtest_93]
expected: FAIL
- [subtest_270]
+ [subtest_94]
expected: FAIL
- [subtest_271]
+ [subtest_96]
expected: FAIL
- [subtest_272]
+ [subtest_100]
expected: FAIL
- [subtest_273]
+ [subtest_101]
expected: FAIL
- [subtest_274]
+ [subtest_104]
expected: FAIL
- [subtest_275]
+ [subtest_106]
expected: FAIL
- [subtest_276]
+ [subtest_107]
expected: FAIL
- [subtest_277]
+ [subtest_109]
expected: FAIL
- [subtest_278]
+ [subtest_113]
expected: FAIL
- [subtest_279]
+ [subtest_114]
expected: FAIL
- [subtest_280]
+ [subtest_117]
expected: FAIL
- [subtest_281]
+ [subtest_119]
expected: FAIL
- [subtest_282]
+ [subtest_120]
expected: FAIL
- [subtest_283]
+ [subtest_122]
expected: FAIL
- [subtest_284]
+ [subtest_126]
expected: FAIL
- [subtest_285]
+ [subtest_127]
expected: FAIL
- [subtest_286]
+ [subtest_130]
expected: FAIL
- [subtest_287]
+ [subtest_132]
expected: FAIL
- [subtest_288]
+ [subtest_133]
expected: FAIL
- [subtest_289]
+ [subtest_134]
expected: FAIL
- [subtest_290]
+ [subtest_137]
expected: FAIL
- [subtest_291]
+ [subtest_152]
expected: FAIL
- [subtest_292]
+ [subtest_155]
expected: FAIL
- [find_resolution]
+ [subtest_159]
expected: FAIL
- [subtest_295]
+ [subtest_160]
expected: FAIL
- [subtest_297]
+ [subtest_161]
expected: FAIL
- [subtest_299]
+ [subtest_162]
expected: FAIL
- [subtest_300]
+ [subtest_166]
expected: FAIL
- [subtest_302]
+ [subtest_167]
expected: FAIL
- [subtest_303]
+ [subtest_168]
expected: FAIL
- [subtest_304]
+ [subtest_169]
expected: FAIL
- [subtest_305]
+ [subtest_174]
expected: FAIL
- [subtest_306]
+ [subtest_175]
expected: FAIL
- [subtest_307]
+ [subtest_178]
expected: FAIL
- [subtest_308]
+ [subtest_179]
expected: FAIL
- [subtest_309]
+ [subtest_185]
expected: FAIL
- [subtest_313]
+ [subtest_186]
expected: FAIL
- [subtest_314]
+ [subtest_190]
expected: FAIL
- [subtest_315]
+ [subtest_192]
expected: FAIL
- [subtest_316]
+ [subtest_198]
expected: FAIL
- [subtest_317]
+ [find_depth]
expected: FAIL
- [subtest_318]
+ [subtest_232]
expected: FAIL
- [subtest_319]
+ [subtest_233]
expected: FAIL
- [subtest_320]
+ [subtest_235]
expected: FAIL
- [subtest_321]
+ [subtest_266]
expected: FAIL
- [subtest_322]
+ [subtest_268]
expected: FAIL
- [subtest_323]
+ [subtest_294]
expected: FAIL
- [subtest_324]
+ [subtest_310]
expected: FAIL
- [subtest_326]
+ [subtest_311]
expected: FAIL
- [subtest_330]
+ [subtest_312]
expected: FAIL
- [subtest_333]
+ [subtest_325]
expected: FAIL
- [subtest_335]
+ [subtest_328]
expected: FAIL
- [subtest_338]
+ [subtest_329]
expected: FAIL
- [subtest_340]
+ [subtest_332]
expected: FAIL
- [subtest_341]
+ [subtest_337]
expected: FAIL
- [subtest_342]
+ [subtest_349]
expected: FAIL
- [subtest_343]
+ [subtest_353]
expected: FAIL
- [subtest_344]
+ [subtest_354]
expected: FAIL
- [subtest_346]
+ [subtest_357]
expected: FAIL
- [subtest_347]
+ [subtest_358]
expected: FAIL
- [subtest_350]
+ [subtest_359]
expected: FAIL
- [subtest_351]
+ [subtest_360]
expected: FAIL
diff --git a/tests/wpt/metadata/css/selectors/any-link-dynamic-001.html.ini b/tests/wpt/metadata/css/selectors/any-link-dynamic-001.html.ini
new file mode 100644
index 00000000000..586972d310f
--- /dev/null
+++ b/tests/wpt/metadata/css/selectors/any-link-dynamic-001.html.ini
@@ -0,0 +1,2 @@
+[any-link-dynamic-001.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/css/selectors/invalidation/any-link-pseudo.html.ini b/tests/wpt/metadata/css/selectors/invalidation/any-link-pseudo.html.ini
new file mode 100644
index 00000000000..7cf5d1b77a2
--- /dev/null
+++ b/tests/wpt/metadata/css/selectors/invalidation/any-link-pseudo.html.ini
@@ -0,0 +1,4 @@
+[any-link-pseudo.html]
+ [Style was recalculated for the :any-link pseudo class.]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/custom-elements/microtasks-and-constructors.html.ini b/tests/wpt/metadata/custom-elements/microtasks-and-constructors.html.ini
index 00638b8a8c2..22111c6cb3d 100644
--- a/tests/wpt/metadata/custom-elements/microtasks-and-constructors.html.ini
+++ b/tests/wpt/metadata/custom-elements/microtasks-and-constructors.html.ini
@@ -1,4 +1,3 @@
[microtasks-and-constructors.html]
expected: CRASH
bug: https://github.com/servo/servo/issues/19392
-
diff --git a/tests/wpt/metadata/custom-elements/parser/parser-fallsback-to-unknown-element.html.ini b/tests/wpt/metadata/custom-elements/parser/parser-fallsback-to-unknown-element.html.ini
index b8c0c4d4172..9f8fb480445 100644
--- a/tests/wpt/metadata/custom-elements/parser/parser-fallsback-to-unknown-element.html.ini
+++ b/tests/wpt/metadata/custom-elements/parser/parser-fallsback-to-unknown-element.html.ini
@@ -1,4 +1,3 @@
[parser-fallsback-to-unknown-element.html]
expected: CRASH
bug: https://github.com/servo/servo/issues/19392
-
diff --git a/tests/wpt/metadata/custom-elements/parser/parser-uses-registry-of-owner-document.html.ini b/tests/wpt/metadata/custom-elements/parser/parser-uses-registry-of-owner-document.html.ini
index aea72a43f87..f682fd43fb6 100644
--- a/tests/wpt/metadata/custom-elements/parser/parser-uses-registry-of-owner-document.html.ini
+++ b/tests/wpt/metadata/custom-elements/parser/parser-uses-registry-of-owner-document.html.ini
@@ -6,3 +6,9 @@
[HTML parser must use the registry of window.document in a document created by document.implementation.createHTMLDocument()]
expected: FAIL
+ [document.write() must not instantiate a custom element without a defined insertion point]
+ expected: FAIL
+
+ [document.writeln() must not instantiate a custom element without a defined insertion point]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/dom/events/Event-subclasses-constructors.html.ini b/tests/wpt/metadata/dom/events/Event-subclasses-constructors.html.ini
index f25d6555b66..c8c3c5ec618 100644
--- a/tests/wpt/metadata/dom/events/Event-subclasses-constructors.html.ini
+++ b/tests/wpt/metadata/dom/events/Event-subclasses-constructors.html.ini
@@ -57,3 +57,21 @@
[CompositionEvent constructor (argument with non-default values)]
expected: FAIL
+ [SubclassedEvent constructor (no argument)]
+ expected: FAIL
+
+ [SubclassedEvent constructor (undefined argument)]
+ expected: FAIL
+
+ [SubclassedEvent constructor (null argument)]
+ expected: FAIL
+
+ [SubclassedEvent constructor (empty argument)]
+ expected: FAIL
+
+ [SubclassedEvent constructor (argument with default values)]
+ expected: FAIL
+
+ [SubclassedEvent constructor (argument with non-default values)]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/dom/events/EventListener-invoke-legacy.html.ini b/tests/wpt/metadata/dom/events/EventListener-invoke-legacy.html.ini
index ff1b7c039c6..c7ff398c924 100644
--- a/tests/wpt/metadata/dom/events/EventListener-invoke-legacy.html.ini
+++ b/tests/wpt/metadata/dom/events/EventListener-invoke-legacy.html.ini
@@ -1,9 +1,6 @@
[EventListener-invoke-legacy.html]
type: testharness
expected: TIMEOUT
- [Listener of transitionend]
- expected: FAIL
-
[Legacy listener of transitionend]
expected: TIMEOUT
diff --git a/tests/wpt/metadata/fetch/api/redirect/redirect-method-worker.html.ini b/tests/wpt/metadata/fetch/api/redirect/redirect-method-worker.html.ini
index 672f5a8635a..37435990814 100644
--- a/tests/wpt/metadata/fetch/api/redirect/redirect-method-worker.html.ini
+++ b/tests/wpt/metadata/fetch/api/redirect/redirect-method-worker.html.ini
@@ -36,3 +36,9 @@
[Redirect 307 with HEAD]
expected: FAIL
+ [Redirect 307 with POST (string body)]
+ expected: FAIL
+
+ [Redirect 307 with POST (blob body)]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/fetch/api/redirect/redirect-method.html.ini b/tests/wpt/metadata/fetch/api/redirect/redirect-method.html.ini
index de315047f46..3f92aa3540c 100644
--- a/tests/wpt/metadata/fetch/api/redirect/redirect-method.html.ini
+++ b/tests/wpt/metadata/fetch/api/redirect/redirect-method.html.ini
@@ -36,3 +36,9 @@
[Redirect 307 with HEAD]
expected: FAIL
+ [Redirect 307 with POST (string body)]
+ expected: FAIL
+
+ [Redirect 307 with POST (blob body)]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/fetch/api/request/destination/fetch-destination.https.html.ini b/tests/wpt/metadata/fetch/api/request/destination/fetch-destination.https.html.ini
new file mode 100644
index 00000000000..c61b4930e0c
--- /dev/null
+++ b/tests/wpt/metadata/fetch/api/request/destination/fetch-destination.https.html.ini
@@ -0,0 +1,4 @@
+[fetch-destination.https.html]
+ [Service Worker: the body of FetchEvent using XMLHttpRequest]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/fetch/api/request/request-keepalive-quota.html.ini b/tests/wpt/metadata/fetch/api/request/request-keepalive-quota.html.ini
index 53ccea0d402..e4d7c3be226 100644
--- a/tests/wpt/metadata/fetch/api/request/request-keepalive-quota.html.ini
+++ b/tests/wpt/metadata/fetch/api/request/request-keepalive-quota.html.ini
@@ -6,3 +6,6 @@
[A Keep-Alive fetch() should not be allowed if the Quota is used up.]
expected: FAIL
+ [A Keep-Alive fetch() should return only its allocated Quota upon promise resolution.]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/fetch/http-cache/partial.html.ini b/tests/wpt/metadata/fetch/http-cache/partial.html.ini
index 65c7f3ebc0c..d3f8a45038e 100644
--- a/tests/wpt/metadata/fetch/http-cache/partial.html.ini
+++ b/tests/wpt/metadata/fetch/http-cache/partial.html.ini
@@ -1,6 +1,5 @@
[partial.html]
type: testharness
-
[HTTP cache stores partial content and completes it.]
expected: FAIL
diff --git a/tests/wpt/metadata/hr-time/idlharness.html.ini b/tests/wpt/metadata/hr-time/idlharness.html.ini
index 028cee6abc5..1b082bfa85f 100644
--- a/tests/wpt/metadata/hr-time/idlharness.html.ini
+++ b/tests/wpt/metadata/hr-time/idlharness.html.ini
@@ -21,3 +21,9 @@
[Test default toJSON operation of Performance]
expected: FAIL
+ [Performance interface: window.performance must inherit property "timeOrigin" with the proper type]
+ expected: FAIL
+
+ [Performance interface: window.performance must inherit property "toJSON()" with the proper type]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/hr-time/performance-tojson.html.ini b/tests/wpt/metadata/hr-time/performance-tojson.html.ini
new file mode 100644
index 00000000000..f04c6c49fa6
--- /dev/null
+++ b/tests/wpt/metadata/hr-time/performance-tojson.html.ini
@@ -0,0 +1,4 @@
+[performance-tojson.html]
+ [Untitled]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload.tentative.html.ini b/tests/wpt/metadata/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload.tentative.html.ini
index 37a316d60be..2d6b8fa2546 100644
--- a/tests/wpt/metadata/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload.tentative.html.ini
+++ b/tests/wpt/metadata/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload.tentative.html.ini
@@ -1,4 +1,5 @@
[navigation-in-onload.tentative.html]
+ expected: ERROR
[Navigation in onload handler]
- expected: FAIL
+ expected: NOTRUN
diff --git a/tests/wpt/metadata/html/browsers/the-window-object/window-properties.html.ini b/tests/wpt/metadata/html/browsers/the-window-object/window-properties.html.ini
index 905abfcd492..a8a3946b8e7 100644
--- a/tests/wpt/metadata/html/browsers/the-window-object/window-properties.html.ini
+++ b/tests/wpt/metadata/html/browsers/the-window-object/window-properties.html.ini
@@ -1,5 +1,6 @@
[window-properties.html]
type: testharness
+ expected: TIMEOUT
[Window method: stop]
expected: FAIL
diff --git a/tests/wpt/metadata/html/dom/interfaces.html.ini b/tests/wpt/metadata/html/dom/interfaces.html.ini
index 30512680019..d58a1b90b02 100644
--- a/tests/wpt/metadata/html/dom/interfaces.html.ini
+++ b/tests/wpt/metadata/html/dom/interfaces.html.ini
@@ -14316,3 +14316,18 @@
[History interface: window.history must inherit property "index" with the proper type]
expected: FAIL
+ [HTMLElement interface: attribute inputMode]
+ expected: FAIL
+
+ [HTMLElement interface: document.createElement("noscript") must inherit property "inputMode" with the proper type]
+ expected: FAIL
+
+ [HTMLSlotElement interface: operation assignedElements(AssignedNodesOptions)]
+ expected: FAIL
+
+ [HTMLSlotElement interface: document.createElement("slot") must inherit property "assignedElements(AssignedNodesOptions)" with the proper type]
+ expected: FAIL
+
+ [HTMLSlotElement interface: calling assignedElements(AssignedNodesOptions) on document.createElement("slot") with too few arguments must throw TypeError]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/dom/reflection-misc.html.ini b/tests/wpt/metadata/html/dom/reflection-misc.html.ini
index 91808fec6d2..eb6cf13e977 100644
--- a/tests/wpt/metadata/html/dom/reflection-misc.html.ini
+++ b/tests/wpt/metadata/html/dom/reflection-misc.html.ini
@@ -18540,3 +18540,339 @@
[slot.name: IDL set to object "test-valueOf"]
expected: FAIL
+ [undefinedelement.inputMode: typeof IDL attribute]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL get with DOM attribute unset]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to ""]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to " \\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07 \\b\\t\\n\\v\\f\\r\\x0e\\x0f \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17 \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f foo "]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to undefined]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to 7]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to 1.5]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to true]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to false]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to object "[object Object\]"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to NaN]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to Infinity]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to -Infinity]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "\\0"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to null]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to object "test-toString"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to object "test-valueOf"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "none"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "xnone"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "none\\0"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "one"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "NONE"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "text"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "xtext"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "text\\0"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "ext"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "TEXT"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "tel"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "xtel"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "tel\\0"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "el"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "TEL"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "url"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "xurl"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "url\\0"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "rl"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "URL"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "email"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "xemail"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "email\\0"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "mail"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "EMAIL"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "numeric"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "xnumeric"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "numeric\\0"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "umeric"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "NUMERIC"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "decimal"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "xdecimal"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "decimal\\0"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "ecimal"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "DECIMAL"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "search"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "xsearch"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "search\\0"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "earch"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: setAttribute() to "SEARCH"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to ""]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to " \\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07 \\b\\t\\n\\v\\f\\r\\x0e\\x0f \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17 \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f foo "]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to undefined]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to 7]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to 1.5]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to true]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to false]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to object "[object Object\]"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to NaN]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to Infinity]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to -Infinity]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "\\0"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to null]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to object "test-toString"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to object "test-valueOf"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "none"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "xnone"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "none\\0"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "one"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "NONE"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "text"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "xtext"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "text\\0"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "ext"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "TEXT"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "tel"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "xtel"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "tel\\0"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "el"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "TEL"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "url"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "xurl"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "url\\0"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "rl"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "URL"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "email"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "xemail"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "email\\0"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "mail"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "EMAIL"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "numeric"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "xnumeric"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "numeric\\0"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "umeric"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "NUMERIC"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "decimal"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "xdecimal"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "decimal\\0"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "ecimal"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "DECIMAL"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "search"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "xsearch"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "search\\0"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "earch"]
+ expected: FAIL
+
+ [undefinedelement.inputMode: IDL set to "SEARCH"]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/dom/usvstring-reflection.html.ini b/tests/wpt/metadata/html/dom/usvstring-reflection.html.ini
new file mode 100644
index 00000000000..fabbe8f8ca0
--- /dev/null
+++ b/tests/wpt/metadata/html/dom/usvstring-reflection.html.ini
@@ -0,0 +1,19 @@
+[usvstring-reflection.html]
+ [window.open : unpaired surrogate codepoint should be replaced with U+FFFD]
+ expected: FAIL
+
+ [anchor : unpaired surrogate codepoint should be replaced with U+FFFD]
+ expected: FAIL
+
+ [area : unpaired surrogate codepoint should be replaced with U+FFFD]
+ expected: FAIL
+
+ [frame : unpaired surrogate codepoint should be replaced with U+FFFD]
+ expected: FAIL
+
+ [iframe : unpaired surrogate codepoint should be replaced with U+FFFD]
+ expected: FAIL
+
+ [source : unpaired surrogate codepoint should be replaced with U+FFFD]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/form-elements/the-textarea-element/multiline-placeholder-cr.html.ini b/tests/wpt/metadata/html/form-elements/the-textarea-element/multiline-placeholder-cr.html.ini
new file mode 100644
index 00000000000..341c31c230c
--- /dev/null
+++ b/tests/wpt/metadata/html/form-elements/the-textarea-element/multiline-placeholder-cr.html.ini
@@ -0,0 +1,2 @@
+[multiline-placeholder-cr.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/crossOrigin.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/crossOrigin.html.ini
new file mode 100644
index 00000000000..684d8638fcc
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/crossOrigin.html.ini
@@ -0,0 +1,31 @@
+[crossOrigin.html]
+ [HTMLMediaElement.crossOrigin]
+ expected: FAIL
+
+ [HTMLMediaElement.crossOrigin, content attribute missing]
+ expected: FAIL
+
+ [HTMLMediaElement.crossOrigin, content attribute invalid value]
+ expected: FAIL
+
+ [HTMLMediaElement.crossOrigin, content attribute empty string]
+ expected: FAIL
+
+ [HTMLMediaElement.crossOrigin, content attribute uppercase ANONYMOUS]
+ expected: FAIL
+
+ [HTMLMediaElement.crossOrigin, content attribute use-credentials]
+ expected: FAIL
+
+ [HTMLMediaElement.crossOrigin, setting to empty string]
+ expected: FAIL
+
+ [HTMLMediaElement.crossOrigin, setting to invalid value]
+ expected: FAIL
+
+ [HTMLMediaElement.crossOrigin, setting to uppercase ANONYMOUS]
+ expected: FAIL
+
+ [HTMLMediaElement.crossOrigin, setting to use-credentials]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/readyState.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/readyState.html.ini
index 27cb06d6489..db492bf4d80 100644
--- a/tests/wpt/metadata/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/readyState.html.ini
+++ b/tests/wpt/metadata/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/readyState.html.ini
@@ -3,3 +3,6 @@
[HTMLTrackElement.readyState default value]
expected: FAIL
+ [HTMLTrackElement.readyState values]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/constructor.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/constructor.html.ini
new file mode 100644
index 00000000000..9bef795b52a
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/constructor.html.ini
@@ -0,0 +1,7 @@
+[constructor.html]
+ [TextTrackCue and VTTCue are separate interfaces]
+ expected: FAIL
+
+ [TextTrackCue constructor should not be supported]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/forms/the-input-element/date.html.ini b/tests/wpt/metadata/html/semantics/forms/the-input-element/date.html.ini
index 99eb0c7bba3..1354ae61137 100644
--- a/tests/wpt/metadata/html/semantics/forms/the-input-element/date.html.ini
+++ b/tests/wpt/metadata/html/semantics/forms/the-input-element/date.html.ini
@@ -5,3 +5,4 @@
[The max attribute, if specified, must have a value that is a valid date string.]
expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/forms/the-input-element/datetime-local.html.ini b/tests/wpt/metadata/html/semantics/forms/the-input-element/datetime-local.html.ini
index ed93cfbd3d9..10d425b9e86 100644
--- a/tests/wpt/metadata/html/semantics/forms/the-input-element/datetime-local.html.ini
+++ b/tests/wpt/metadata/html/semantics/forms/the-input-element/datetime-local.html.ini
@@ -1,6 +1,5 @@
[datetime-local.html]
type: testharness
-
[Value < min attribute]
expected: FAIL
diff --git a/tests/wpt/metadata/html/semantics/forms/the-input-element/month.html.ini b/tests/wpt/metadata/html/semantics/forms/the-input-element/month.html.ini
index dd41c559298..b688bb4eb9c 100644
--- a/tests/wpt/metadata/html/semantics/forms/the-input-element/month.html.ini
+++ b/tests/wpt/metadata/html/semantics/forms/the-input-element/month.html.ini
@@ -2,3 +2,4 @@
type: testharness
[When step attribute is given invalid value, it must ignore the invalid value and use defaul value instead.]
expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/forms/the-input-element/type-change-state.html.ini b/tests/wpt/metadata/html/semantics/forms/the-input-element/type-change-state.html.ini
index da29acb8975..887b455d261 100644
--- a/tests/wpt/metadata/html/semantics/forms/the-input-element/type-change-state.html.ini
+++ b/tests/wpt/metadata/html/semantics/forms/the-input-element/type-change-state.html.ini
@@ -329,3 +329,4 @@
[change state from color to range]
expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/forms/the-select-element/select-add.html.ini b/tests/wpt/metadata/html/semantics/forms/the-select-element/select-add.html.ini
new file mode 100644
index 00000000000..510c23a07de
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/forms/the-select-element/select-add.html.ini
@@ -0,0 +1,7 @@
+[select-add.html]
+ [test that HTMLSelectElement.add method can add option element]
+ expected: FAIL
+
+ [test that HierarchyRequestError exception must be thrown when element is an ancestor of the element into which it is to be inserted]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/interactive-elements/the-dialog-element/abspos-dialog-layout.html.ini b/tests/wpt/metadata/html/semantics/interactive-elements/the-dialog-element/abspos-dialog-layout.html.ini
new file mode 100644
index 00000000000..6cfa67fcebc
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/interactive-elements/the-dialog-element/abspos-dialog-layout.html.ini
@@ -0,0 +1,43 @@
+[abspos-dialog-layout.html]
+ [showModal() should center in the viewport]
+ expected: FAIL
+
+ [The dialog is a positioned element, so the top and bottom should not have style auto.]
+ expected: FAIL
+
+ [Dialog should be recentered if showModal() is called after close()]
+ expected: FAIL
+
+ [Dialog should not recenter on relayout.]
+ expected: FAIL
+
+ [A tall dialog should be positioned at the top of the viewport.]
+ expected: FAIL
+
+ [The dialog should be centered regardless of the presence of a horizontal scrollbar.]
+ expected: FAIL
+
+ [Centering should work when dialog is inside positioned containers.]
+ expected: FAIL
+
+ [A centered dialog's position should survive becoming display:none temporarily.]
+ expected: FAIL
+
+ [Dialog should lose centering when removed from the document.]
+ expected: FAIL
+
+ [Dialog's specified position should survive after close() and showModal().]
+ expected: FAIL
+
+ [Dialog should be recentered if showModal() is called after removing 'open'.]
+ expected: FAIL
+
+ [Dialog should not be centered if showModal() was called when an ancestor had display 'none'.]
+ expected: FAIL
+
+ [A dialog with specified 'top' should be positioned as usual]
+ expected: FAIL
+
+ [A dialog with specified 'bottom' should be positioned as usual]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/interactive-elements/the-dialog-element/dialog-scrolled-viewport.html.ini b/tests/wpt/metadata/html/semantics/interactive-elements/the-dialog-element/dialog-scrolled-viewport.html.ini
new file mode 100644
index 00000000000..998744525b3
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/interactive-elements/the-dialog-element/dialog-scrolled-viewport.html.ini
@@ -0,0 +1,4 @@
+[dialog-scrolled-viewport.html]
+ [Tests modal dialog's containing block is the initial containing block]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/interactive-elements/the-dialog-element/inert-does-not-match-disabled-selector.html.ini b/tests/wpt/metadata/html/semantics/interactive-elements/the-dialog-element/inert-does-not-match-disabled-selector.html.ini
new file mode 100644
index 00000000000..43c91c1a01e
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/interactive-elements/the-dialog-element/inert-does-not-match-disabled-selector.html.ini
@@ -0,0 +1,4 @@
+[inert-does-not-match-disabled-selector.html]
+ [Tests inert elements do not match the :disabled selector.]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/interactive-elements/the-dialog-element/inert-node-is-unfocusable.html.ini b/tests/wpt/metadata/html/semantics/interactive-elements/the-dialog-element/inert-node-is-unfocusable.html.ini
new file mode 100644
index 00000000000..92fe79a8971
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/interactive-elements/the-dialog-element/inert-node-is-unfocusable.html.ini
@@ -0,0 +1,4 @@
+[inert-node-is-unfocusable.html]
+ [Test that inert nodes are not focusable.]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/choice-of-error-1.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/choice-of-error-1.html.ini
new file mode 100644
index 00000000000..2046faa6ed8
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/choice-of-error-1.html.ini
@@ -0,0 +1,4 @@
+[choice-of-error-1.html]
+ [Parse errors in different files should be reported depending on different roots]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/choice-of-error-2.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/choice-of-error-2.html.ini
new file mode 100644
index 00000000000..9d55b00ff31
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/choice-of-error-2.html.ini
@@ -0,0 +1,4 @@
+[choice-of-error-2.html]
+ [Instantiation errors in different files should be reported depending on different roots]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/choice-of-error-3.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/choice-of-error-3.html.ini
new file mode 100644
index 00000000000..19e185bb343
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/choice-of-error-3.html.ini
@@ -0,0 +1,4 @@
+[choice-of-error-3.html]
+ [Evaluation errors are cached in intermediate module scripts]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-classic.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-classic.html.ini
deleted file mode 100644
index 01ce266ac9e..00000000000
--- a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-classic.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[string-compilation-base-url-classic.html]
- type: testharness
- [import() inside compiled strings uses the document base URL inside a classic script]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-classic.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-classic.html.ini
new file mode 100644
index 00000000000..01f5651e9e1
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-classic.html.ini
@@ -0,0 +1,4 @@
+[string-compilation-base-url-external-classic.html]
+ [import() inside compiled strings uses the script base URL inside a classic script that is loaded from a file]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-module.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-module.html.ini
new file mode 100644
index 00000000000..2dbf1ad6e29
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-module.html.ini
@@ -0,0 +1,2 @@
+[string-compilation-base-url-external-module.html]
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-classic.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-classic.html.ini
new file mode 100644
index 00000000000..e27c6b06a0c
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-classic.html.ini
@@ -0,0 +1,4 @@
+[string-compilation-base-url-inline-classic.html]
+ [import() inside compiled strings uses the script base URL (= document base URL) inside an inline classic script]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-module.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-module.html.ini
new file mode 100644
index 00000000000..238b8a863f4
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-module.html.ini
@@ -0,0 +1,2 @@
+[string-compilation-base-url-inline-module.html]
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-module.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-module.html.ini
deleted file mode 100644
index d5cadc8673b..00000000000
--- a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-module.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[string-compilation-base-url-module.html]
- type: testharness
- expected: TIMEOUT
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-integrity-classic.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-integrity-classic.html.ini
new file mode 100644
index 00000000000..bb7e3e4779f
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-integrity-classic.html.ini
@@ -0,0 +1,2 @@
+[string-compilation-integrity-classic.html]
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-integrity-module.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-integrity-module.html.ini
new file mode 100644
index 00000000000..da1840b68fb
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-integrity-module.html.ini
@@ -0,0 +1,2 @@
+[string-compilation-integrity-module.html]
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-classic.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-classic.html.ini
new file mode 100644
index 00000000000..2432b79d461
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-classic.html.ini
@@ -0,0 +1,20 @@
+[string-compilation-nonce-classic.html]
+ expected: ERROR
+ [setTimeout must inherit the nonce from the triggering script, thus execute]
+ expected: TIMEOUT
+
+ [direct eval must inherit the nonce from the triggering script, thus execute]
+ expected: NOTRUN
+
+ [indirect eval must inherit the nonce from the triggering script, thus execute]
+ expected: NOTRUN
+
+ [the Function constructor must inherit the nonce from the triggering script, thus execute]
+ expected: NOTRUN
+
+ [reflected inline event handlers must inherit the nonce from the triggering script, thus execute]
+ expected: NOTRUN
+
+ [inline event handlers triggered via UA code must inherit the nonce from the triggering script, thus execute]
+ expected: NOTRUN
+
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-module.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-module.html.ini
new file mode 100644
index 00000000000..d87f8ba32d7
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-module.html.ini
@@ -0,0 +1,2 @@
+[string-compilation-nonce-module.html]
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/error-type-1.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/error-type-1.html.ini
new file mode 100644
index 00000000000..c756960b09d
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/error-type-1.html.ini
@@ -0,0 +1,4 @@
+[error-type-1.html]
+ [network error has higher priority than parse error]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/error-type-2.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/error-type-2.html.ini
new file mode 100644
index 00000000000..e24139fb1a2
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/error-type-2.html.ini
@@ -0,0 +1,4 @@
+[error-type-2.html]
+ [parse error has higher priority than instantiation error]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/error-type-3.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/error-type-3.html.ini
new file mode 100644
index 00000000000..58cc436ec05
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/error-type-3.html.ini
@@ -0,0 +1,4 @@
+[error-type-3.html]
+ [instantiation error has higher priority than evaluation error]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/instantiation-error-1.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/instantiation-error-1.html.ini
index c9c35bb3976..b3fdd6f764e 100644
--- a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/instantiation-error-1.html.ini
+++ b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/instantiation-error-1.html.ini
@@ -3,3 +3,6 @@
[Test that missing exports lead to SyntaxError events on window and load events on script, and that exceptions are remembered]
expected: FAIL
+ [Test that missing exports lead to SyntaxError events on window and load events on script]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/instantiation-error-2.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/instantiation-error-2.html.ini
index b00561ef5eb..c5e6fec931a 100644
--- a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/instantiation-error-2.html.ini
+++ b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/instantiation-error-2.html.ini
@@ -3,3 +3,6 @@
[Test that missing exports lead to SyntaxError events on window and load events on script, and that exceptions are remembered]
expected: FAIL
+ [Test that missing exports lead to SyntaxError events on window and load events on script]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/instantiation-error-3.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/instantiation-error-3.html.ini
index 38c8188c8b2..25019f2ce0f 100644
--- a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/instantiation-error-3.html.ini
+++ b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/instantiation-error-3.html.ini
@@ -3,3 +3,6 @@
[Test that unresolvable cycles lead to SyntaxError events on window and load events on script, and that exceptions are remembered]
expected: FAIL
+ [Test that unresolvable cycles lead to SyntaxError events on window and load events on script]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/instantiation-error-4.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/instantiation-error-4.html.ini
index 3e63cc081c9..8acedfbc746 100644
--- a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/instantiation-error-4.html.ini
+++ b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/instantiation-error-4.html.ini
@@ -3,3 +3,6 @@
[Test that loading a graph in which a module is already errored results in that module's error.]
expected: FAIL
+ [Test that loading a graph in which a module is already errored results in an error.]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/instantiation-error-5.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/instantiation-error-5.html.ini
index d9bb17db2ce..44be8de5091 100644
--- a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/instantiation-error-5.html.ini
+++ b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/instantiation-error-5.html.ini
@@ -3,3 +3,6 @@
[Test that loading a graph in which a module is already errored results in that module's error.]
expected: FAIL
+ [Test that loading a graph in which a module is already errored results an error.]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/referrer-no-referrer.sub.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/referrer-no-referrer.sub.html.ini
new file mode 100644
index 00000000000..634cf356318
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/referrer-no-referrer.sub.html.ini
@@ -0,0 +1,2 @@
+[referrer-no-referrer.sub.html]
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/referrer-origin-when-cross-origin.sub.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/referrer-origin-when-cross-origin.sub.html.ini
new file mode 100644
index 00000000000..92d04781a2e
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/referrer-origin-when-cross-origin.sub.html.ini
@@ -0,0 +1,2 @@
+[referrer-origin-when-cross-origin.sub.html]
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/referrer-origin.sub.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/referrer-origin.sub.html.ini
new file mode 100644
index 00000000000..9a2db3d8993
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/referrer-origin.sub.html.ini
@@ -0,0 +1,2 @@
+[referrer-origin.sub.html]
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/referrer-same-origin.sub.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/referrer-same-origin.sub.html.ini
new file mode 100644
index 00000000000..d499edb6fc8
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/referrer-same-origin.sub.html.ini
@@ -0,0 +1,2 @@
+[referrer-same-origin.sub.html]
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/referrer-unsafe-url.sub.html.ini b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/referrer-unsafe-url.sub.html.ini
new file mode 100644
index 00000000000..2b700b1c9b4
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/scripting-1/the-script-element/module/referrer-unsafe-url.sub.html.ini
@@ -0,0 +1,2 @@
+[referrer-unsafe-url.sub.html]
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/html/semantics/text-level-semantics/the-a-element/a-download-click-404.html.ini b/tests/wpt/metadata/html/semantics/text-level-semantics/the-a-element/a-download-click-404.html.ini
index f69644f7477..d173f7601cd 100644
--- a/tests/wpt/metadata/html/semantics/text-level-semantics/the-a-element/a-download-click-404.html.ini
+++ b/tests/wpt/metadata/html/semantics/text-level-semantics/the-a-element/a-download-click-404.html.ini
@@ -1,3 +1,5 @@
[a-download-click-404.html]
type: testharness
- expected: ERROR
+ [Do not navigate to 404 for anchor with download]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/text-level-semantics/the-a-element/a-download-click.html.ini b/tests/wpt/metadata/html/semantics/text-level-semantics/the-a-element/a-download-click.html.ini
new file mode 100644
index 00000000000..b4d12d613ab
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/text-level-semantics/the-a-element/a-download-click.html.ini
@@ -0,0 +1,4 @@
+[a-download-click.html]
+ [Clicking on an <a> element with a download attribute must not throw an exception]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/semantics/text-level-semantics/the-ruby-element/ruby-usage.html.ini b/tests/wpt/metadata/html/semantics/text-level-semantics/the-ruby-element/ruby-usage.html.ini
new file mode 100644
index 00000000000..1dac9f70200
--- /dev/null
+++ b/tests/wpt/metadata/html/semantics/text-level-semantics/the-ruby-element/ruby-usage.html.ini
@@ -0,0 +1,2 @@
+[ruby-usage.html]
+ expected: FAIL
diff --git a/tests/wpt/metadata/mozilla-sync b/tests/wpt/metadata/mozilla-sync
index 530ceee0029..48dce5e5051 100644
--- a/tests/wpt/metadata/mozilla-sync
+++ b/tests/wpt/metadata/mozilla-sync
@@ -1,2 +1,2 @@
-local: 85fa6409bb699647b4f5e22952538365e87418d7
-upstream: 40ee9a4553dca805163766c5970979a23e357292
+local: 9187c9a093860d9f3c31b5a5f402458aa4a607cb
+upstream: 1b93a7d98bc4849fa8f365d9bd13fb2a0448c6e1
diff --git a/tests/wpt/metadata/navigation-timing/idlharness.html.ini b/tests/wpt/metadata/navigation-timing/idlharness.html.ini
index 3abacf64d64..30f14482254 100644
--- a/tests/wpt/metadata/navigation-timing/idlharness.html.ini
+++ b/tests/wpt/metadata/navigation-timing/idlharness.html.ini
@@ -342,3 +342,6 @@
[Test default toJSON operation of PerformanceNavigation]
expected: FAIL
+ [Performance interface: window.performance must inherit property "navigation" with the proper type]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/performance-timeline/performanceentry-tojson.html.ini b/tests/wpt/metadata/performance-timeline/performanceentry-tojson.html.ini
new file mode 100644
index 00000000000..c212efca8e8
--- /dev/null
+++ b/tests/wpt/metadata/performance-timeline/performanceentry-tojson.html.ini
@@ -0,0 +1,4 @@
+[performanceentry-tojson.html]
+ [Untitled]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/quirks-mode/hashless-hex-color.html.ini b/tests/wpt/metadata/quirks-mode/hashless-hex-color.html.ini
deleted file mode 100644
index 78f1bc1f4c9..00000000000
--- a/tests/wpt/metadata/quirks-mode/hashless-hex-color.html.ini
+++ /dev/null
@@ -1,47 +0,0 @@
-[hashless-hex-color.html]
- type: testharness
- [rgb(calc(100 + 155), 255, 255) (quirks)]
- expected: FAIL
-
- [rgb(calc(100 + 155), 255, 255) (almost standards)]
- expected: FAIL
-
- [rgb(calc(100 + 155), 255, 255) (standards)]
- expected: FAIL
-
- [rgba(calc(100 + 155), 255, 255, 001) (quirks)]
- expected: FAIL
-
- [rgba(calc(100 + 155), 255, 255, 001) (almost standards)]
- expected: FAIL
-
- [rgba(calc(100 + 155), 255, 255, 001) (standards)]
- expected: FAIL
-
- [hsl(calc(050 + 050), 100%, 100%) (quirks)]
- expected: FAIL
-
- [hsl(calc(050 + 050), 100%, 100%) (almost standards)]
- expected: FAIL
-
- [hsl(calc(050 + 050), 100%, 100%) (standards)]
- expected: FAIL
-
- [hsla(calc(050 + 050), 100%, 100%, 001) (quirks)]
- expected: FAIL
-
- [hsla(calc(050 + 050), 100%, 100%, 001) (almost standards)]
- expected: FAIL
-
- [hsla(calc(050 + 050), 100%, 100%, 001) (standards)]
- expected: FAIL
-
- [rgb(calc(/**/100/**/ + /**/155/**/), 255, 255) (quirks)]
- expected: FAIL
-
- [rgb(calc(/**/100/**/ + /**/155/**/), 255, 255) (almost standards)]
- expected: FAIL
-
- [rgb(calc(/**/100/**/ + /**/155/**/), 255, 255) (standards)]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/quirks-mode/blocks-ignore-line-height.html.ini b/tests/wpt/metadata/quirks/blocks-ignore-line-height.html.ini
index 3979d3098e2..3979d3098e2 100644
--- a/tests/wpt/metadata/quirks-mode/blocks-ignore-line-height.html.ini
+++ b/tests/wpt/metadata/quirks/blocks-ignore-line-height.html.ini
diff --git a/tests/wpt/metadata/quirks-mode/line-height-calculation.html.ini b/tests/wpt/metadata/quirks/line-height-calculation.html.ini
index 59aa0a298ce..59aa0a298ce 100644
--- a/tests/wpt/metadata/quirks-mode/line-height-calculation.html.ini
+++ b/tests/wpt/metadata/quirks/line-height-calculation.html.ini
diff --git a/tests/wpt/metadata/quirks-mode/percentage-height-calculation.html.ini b/tests/wpt/metadata/quirks/percentage-height-calculation.html.ini
index 5837be3bd93..5837be3bd93 100644
--- a/tests/wpt/metadata/quirks-mode/percentage-height-calculation.html.ini
+++ b/tests/wpt/metadata/quirks/percentage-height-calculation.html.ini
diff --git a/tests/wpt/metadata/quirks-mode/supports.html.ini b/tests/wpt/metadata/quirks/supports.html.ini
index f1968d02eba..f1968d02eba 100644
--- a/tests/wpt/metadata/quirks-mode/supports.html.ini
+++ b/tests/wpt/metadata/quirks/supports.html.ini
diff --git a/tests/wpt/metadata/quirks-mode/table-cell-nowrap-minimum-width-calculation.html.ini b/tests/wpt/metadata/quirks/table-cell-nowrap-minimum-width-calculation.html.ini
index 8ef6f809d1a..8ef6f809d1a 100644
--- a/tests/wpt/metadata/quirks-mode/table-cell-nowrap-minimum-width-calculation.html.ini
+++ b/tests/wpt/metadata/quirks/table-cell-nowrap-minimum-width-calculation.html.ini
diff --git a/tests/wpt/metadata/quirks-mode/table-cell-width-calculation.html.ini b/tests/wpt/metadata/quirks/table-cell-width-calculation.html.ini
index 64f7a867cc9..64f7a867cc9 100644
--- a/tests/wpt/metadata/quirks-mode/table-cell-width-calculation.html.ini
+++ b/tests/wpt/metadata/quirks/table-cell-width-calculation.html.ini
diff --git a/tests/wpt/metadata/quirks-mode/unitless-length.html.ini b/tests/wpt/metadata/quirks/unitless-length.html.ini
index 132f45e8141..132f45e8141 100644
--- a/tests/wpt/metadata/quirks-mode/unitless-length.html.ini
+++ b/tests/wpt/metadata/quirks/unitless-length.html.ini
diff --git a/tests/wpt/metadata/url/a-element-xhtml.xhtml.ini b/tests/wpt/metadata/url/a-element-xhtml.xhtml.ini
index 55bf5603369..939b2644d3e 100644
--- a/tests/wpt/metadata/url/a-element-xhtml.xhtml.ini
+++ b/tests/wpt/metadata/url/a-element-xhtml.xhtml.ini
@@ -186,3 +186,27 @@
[Parsing: <test-a-slash-slash.html> against <a//>]
expected: FAIL
+ [Parsing: <http://f:21/ b ? d # e > against <http://example.org/foo/bar>]
+ expected: FAIL
+
+ [Parsing: <lolscheme:x x#x x> against <about:blank>]
+ expected: FAIL
+
+ [Parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank>]
+ expected: FAIL
+
+ [Parsing: <data:test# »> against <about:blank>]
+ expected: FAIL
+
+ [Parsing: <http://foo.bar/baz?qux#foo"bar> against <about:blank>]
+ expected: FAIL
+
+ [Parsing: <http://foo.bar/baz?qux#foo<bar> against <about:blank>]
+ expected: FAIL
+
+ [Parsing: <http://foo.bar/baz?qux#foo>bar> against <about:blank>]
+ expected: FAIL
+
+ [Parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank>]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/url/a-element.html.ini b/tests/wpt/metadata/url/a-element.html.ini
index c3fe798ea76..aa7e1be63e1 100644
--- a/tests/wpt/metadata/url/a-element.html.ini
+++ b/tests/wpt/metadata/url/a-element.html.ini
@@ -186,3 +186,27 @@
[Parsing: <test-a-slash-slash.html> against <a//>]
expected: FAIL
+ [Parsing: <http://f:21/ b ? d # e > against <http://example.org/foo/bar>]
+ expected: FAIL
+
+ [Parsing: <lolscheme:x x#x x> against <about:blank>]
+ expected: FAIL
+
+ [Parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank>]
+ expected: FAIL
+
+ [Parsing: <data:test# »> against <about:blank>]
+ expected: FAIL
+
+ [Parsing: <http://foo.bar/baz?qux#foo"bar> against <about:blank>]
+ expected: FAIL
+
+ [Parsing: <http://foo.bar/baz?qux#foo<bar> against <about:blank>]
+ expected: FAIL
+
+ [Parsing: <http://foo.bar/baz?qux#foo>bar> against <about:blank>]
+ expected: FAIL
+
+ [Parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank>]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/url/url-constructor.html.ini b/tests/wpt/metadata/url/url-constructor.html.ini
index fcd43bcda1a..c3b9ceadc63 100644
--- a/tests/wpt/metadata/url/url-constructor.html.ini
+++ b/tests/wpt/metadata/url/url-constructor.html.ini
@@ -177,3 +177,27 @@
[Parsing: <file:\\c:\\foo\\bar> against <file:///c:/baz/qux>]
expected: FAIL
+ [Parsing: <http://f:21/ b ? d # e > against <http://example.org/foo/bar>]
+ expected: FAIL
+
+ [Parsing: <lolscheme:x x#x x> against <about:blank>]
+ expected: FAIL
+
+ [Parsing: <http://www.google.com/foo?bar=baz# »> against <about:blank>]
+ expected: FAIL
+
+ [Parsing: <data:test# »> against <about:blank>]
+ expected: FAIL
+
+ [Parsing: <http://foo.bar/baz?qux#foo"bar> against <about:blank>]
+ expected: FAIL
+
+ [Parsing: <http://foo.bar/baz?qux#foo<bar> against <about:blank>]
+ expected: FAIL
+
+ [Parsing: <http://foo.bar/baz?qux#foo>bar> against <about:blank>]
+ expected: FAIL
+
+ [Parsing: <http://foo.bar/baz?qux#foo`bar> against <about:blank>]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/url/url-setters.html.ini b/tests/wpt/metadata/url/url-setters.html.ini
index 138d36a1f2c..dcb7cf62196 100644
--- a/tests/wpt/metadata/url/url-setters.html.ini
+++ b/tests/wpt/metadata/url/url-setters.html.ini
@@ -933,3 +933,48 @@
[<area>: Setting <http://foo.com:443/>.protocol = 'https' Port is set to null if it is the default for new scheme.]
expected: FAIL
+ [URL: Setting <http://example.net>.hash = '#foo bar']
+ expected: FAIL
+
+ [<a>: Setting <http://example.net>.hash = '#foo bar']
+ expected: FAIL
+
+ [<area>: Setting <http://example.net>.hash = '#foo bar']
+ expected: FAIL
+
+ [URL: Setting <http://example.net>.hash = '#foo"bar']
+ expected: FAIL
+
+ [<a>: Setting <http://example.net>.hash = '#foo"bar']
+ expected: FAIL
+
+ [<area>: Setting <http://example.net>.hash = '#foo"bar']
+ expected: FAIL
+
+ [URL: Setting <http://example.net>.hash = '#foo<bar']
+ expected: FAIL
+
+ [<a>: Setting <http://example.net>.hash = '#foo<bar']
+ expected: FAIL
+
+ [<area>: Setting <http://example.net>.hash = '#foo<bar']
+ expected: FAIL
+
+ [URL: Setting <http://example.net>.hash = '#foo>bar']
+ expected: FAIL
+
+ [<a>: Setting <http://example.net>.hash = '#foo>bar']
+ expected: FAIL
+
+ [<area>: Setting <http://example.net>.hash = '#foo>bar']
+ expected: FAIL
+
+ [URL: Setting <http://example.net>.hash = '#foo`bar']
+ expected: FAIL
+
+ [<a>: Setting <http://example.net>.hash = '#foo`bar']
+ expected: FAIL
+
+ [<area>: Setting <http://example.net>.hash = '#foo`bar']
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/workers/SharedWorker_dataUrl.html.ini b/tests/wpt/metadata/workers/SharedWorker_dataUrl.html.ini
new file mode 100644
index 00000000000..b3bd1e4649f
--- /dev/null
+++ b/tests/wpt/metadata/workers/SharedWorker_dataUrl.html.ini
@@ -0,0 +1,8 @@
+[SharedWorker_dataUrl.html]
+ expected: TIMEOUT
+ [Data URL not shared by cross-origin SharedWorkers]
+ expected: TIMEOUT
+
+ [Data URLs shared by same-origin SharedWorkers]
+ expected: NOTRUN
+
diff --git a/tests/wpt/metadata/workers/data-url-shared.html.ini b/tests/wpt/metadata/workers/data-url-shared.html.ini
index 35294e6609f..036709be081 100644
--- a/tests/wpt/metadata/workers/data-url-shared.html.ini
+++ b/tests/wpt/metadata/workers/data-url-shared.html.ini
@@ -27,3 +27,6 @@
[worker has opaque origin]
expected: FAIL
+ [A data: URL shared worker should not be shared among origins.]
+ expected: FAIL
+
diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json
index 72d9560b7b2..9f3589df210 100644
--- a/tests/wpt/mozilla/meta/MANIFEST.json
+++ b/tests/wpt/mozilla/meta/MANIFEST.json
@@ -59973,7 +59973,7 @@
},
"paths": {
"./lint.whitelist": [
- "28c20b33fcbd818a46005dcbf53473f8b8346c89",
+ "3e30a95c5b79cc3752c21739da62f47b37c025e5",
"support"
],
"bluetooth/advertisingEvent/watchAdvertisements-succeeds.html": [
diff --git a/tests/wpt/mozilla/meta/webgl/conformance-1.0.3/conformance/glsl/bugs/long-expressions-should-not-crash.html.ini b/tests/wpt/mozilla/meta/webgl/conformance-1.0.3/conformance/glsl/bugs/long-expressions-should-not-crash.html.ini
index fafbedda0a6..17dcfea137f 100644
--- a/tests/wpt/mozilla/meta/webgl/conformance-1.0.3/conformance/glsl/bugs/long-expressions-should-not-crash.html.ini
+++ b/tests/wpt/mozilla/meta/webgl/conformance-1.0.3/conformance/glsl/bugs/long-expressions-should-not-crash.html.ini
@@ -2,3 +2,4 @@
expected: TIMEOUT
[Overall test]
expected: NOTRUN
+
diff --git a/tests/wpt/mozilla/tests/lint.whitelist b/tests/wpt/mozilla/tests/lint.whitelist
index 1bd7f2d23df..4e9dcc5ddf8 100644
--- a/tests/wpt/mozilla/tests/lint.whitelist
+++ b/tests/wpt/mozilla/tests/lint.whitelist
@@ -29,3 +29,7 @@ LAYOUTTESTS APIS:*
## CSSWG-only checks ##
SUPPORT-WRONG-DIR:*
+
+## Unnecessary checks ##
+
+WEB-PLATFORM.TEST:* \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/.travis.yml b/tests/wpt/web-platform-tests/.travis.yml
index 933183f9a4b..dfad9bb136c 100644
--- a/tests/wpt/web-platform-tests/.travis.yml
+++ b/tests/wpt/web-platform-tests/.travis.yml
@@ -63,7 +63,7 @@ matrix:
- fonts-liberation
env:
- secure: "YTSXPwI0DyCA1GhYrLT9KMEV6b7QQKuEeaQgeFDP38OTzJ1+cIj3CC4SRNqbnJ/6SJwPGcdqSxLuV8m4e5HFFnyCcQnJe6h8EMsTehZ7W3j/fP9UYrJqYqvGpe3Vj3xblO5pwBYmq7sg3jAmmuCgAgOW6VGf7cRMucrsmFeo7VM="
- - JOB=stability SCRIPT=tools/ci/ci_stability.sh PRODUCT=chrome:unstable
+ - JOB=stability SCRIPT=tools/ci/ci_stability.sh PRODUCT=chrome:dev
- os: linux
python: "2.7"
env:
@@ -94,7 +94,7 @@ matrix:
- env: JOB=build_css SCRIPT=css/build-css-testsuites.sh
- env:
- secure: "YTSXPwI0DyCA1GhYrLT9KMEV6b7QQKuEeaQgeFDP38OTzJ1+cIj3CC4SRNqbnJ/6SJwPGcdqSxLuV8m4e5HFFnyCcQnJe6h8EMsTehZ7W3j/fP9UYrJqYqvGpe3Vj3xblO5pwBYmq7sg3jAmmuCgAgOW6VGf7cRMucrsmFeo7VM="
- - JOB=stability SCRIPT=tools/ci/ci_stability.sh PRODUCT=chrome:unstable
+ - JOB=stability SCRIPT=tools/ci/ci_stability.sh PRODUCT=chrome:dev
- env:
- secure: "YTSXPwI0DyCA1GhYrLT9KMEV6b7QQKuEeaQgeFDP38OTzJ1+cIj3CC4SRNqbnJ/6SJwPGcdqSxLuV8m4e5HFFnyCcQnJe6h8EMsTehZ7W3j/fP9UYrJqYqvGpe3Vj3xblO5pwBYmq7sg3jAmmuCgAgOW6VGf7cRMucrsmFeo7VM="
- JOB=stability SCRIPT=tools/ci/ci_stability.sh PRODUCT=sauce:MicrosoftEdge:14.14393 PLATFORM='Windows 10'
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.invalidcolour.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.invalidcolour.html
index 7687d0b94ea..7ea349e74bc 100644
--- a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.invalidcolour.html
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.invalidcolour.html
@@ -21,6 +21,15 @@ _addTest(function(canvas, ctx) {
var g = ctx.createLinearGradient(0, 0, 100, 0);
assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, ""); });
+assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, 'rgb(NaN%, NaN%, NaN%)'); });
+assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, 'null'); });
+assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, 'undefined'); });
+assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, null); });
+assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, undefined); });
+
+var g = ctx.createRadialGradient(0, 0, 0, 100, 0, 0);
+assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, ""); });
+assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, 'rgb(NaN%, NaN%, NaN%)'); });
assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, 'null'); });
assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, 'undefined'); });
assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, null); });
diff --git a/tests/wpt/web-platform-tests/2dcontext/imagebitmap/createImageBitmap-invalid-args.html b/tests/wpt/web-platform-tests/2dcontext/imagebitmap/createImageBitmap-invalid-args.html
index a0bcf48fb6c..ad8618a5ce0 100644
--- a/tests/wpt/web-platform-tests/2dcontext/imagebitmap/createImageBitmap-invalid-args.html
+++ b/tests/wpt/web-platform-tests/2dcontext/imagebitmap/createImageBitmap-invalid-args.html
@@ -1,10 +1,6 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html>
-<head>
+<!doctype html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-</head>
-<body>
<script>
function makeCanvas() {
@@ -86,6 +82,22 @@ function makeInvalidBlob() {
});
}
+function makeBrokenImage() {
+ return new Promise(resolve => {
+ const image = new Image();
+ image.src = "data,x";
+ image.onerror = () => resolve(image);
+ });
+}
+
+function makeAvailableButBrokenImage() {
+ return new Promise(resolve => {
+ const image = new Image();
+ image.src = "/images/broken.png";
+ image.onload = () => resolve(image);
+ });
+}
+
imageSourceTypes = [
{ name: 'HTMLImageElement', factory: makeImage },
{ name: 'HTMLVideoElement', factory: makeVideo },
@@ -152,36 +164,48 @@ promise_test( t => {
}, "createImageBitmap with null image source rejects with a TypeError.");
promise_test( t => {
- return promise_rejects(t, new DOMException('', 'InvalidStateError'),
+ return promise_rejects(t, "InvalidStateError",
createImageBitmap(new Image()));
}, "createImageBitmap with empty image source rejects with a InvalidStateError.");
promise_test( t => {
- return promise_rejects(t, new DOMException('', 'InvalidStateError'),
+ return promise_rejects(t, "InvalidStateError",
createImageBitmap(document.createElement('video')));
}, "createImageBitmap with empty video source rejects with a InvalidStateError.");
promise_test( t => {
return makeOversizedCanvas().then(canvas => {
- return promise_rejects(t, new DOMException('', 'InvalidStateError'),
+ return promise_rejects(t, "InvalidStateError",
createImageBitmap(canvas));
});
}, "createImageBitmap with an oversized canvas source rejects with a RangeError.");
promise_test( t => {
return makeOversizedOffscreenCanvas().then(offscreenCanvas => {
- return promise_rejects(t, new DOMException('', 'InvalidStateError'),
+ return promise_rejects(t, "InvalidStateError",
createImageBitmap(offscreenCanvas));
});
}, "createImageBitmap with an invalid OffscreenCanvas source rejects with a RangeError.");
promise_test( t => {
return makeInvalidBlob().then(blob => {
- return promise_rejects(t, new DOMException('', 'InvalidStateError'),
+ return promise_rejects(t, "InvalidStateError",
createImageBitmap(blob));
});
}, "createImageBitmap with an undecodable blob source rejects with an InvalidStateError.");
+promise_test( t => {
+ return makeBrokenImage().then(image => {
+ return promise_rejects(t, "InvalidStateError",
+ createImageBitmap(image));
+ });
+}, "createImageBitmap with a broken image source rejects with an InvalidStateError.");
+
+promise_test( t => {
+ return makeAvailableButBrokenImage().then(image => {
+ return promise_rejects(t, "InvalidStateError",
+ createImageBitmap(image));
+ });
+}, "createImageBitmap with an available but undecodable image source rejects with an InvalidStateError.");
+
</script>
-</body>
-</html>
diff --git a/tests/wpt/web-platform-tests/2dcontext/tools/tests2d.yaml b/tests/wpt/web-platform-tests/2dcontext/tools/tests2d.yaml
index 63ffe9d5db8..7da08f96c1b 100644
--- a/tests/wpt/web-platform-tests/2dcontext/tools/tests2d.yaml
+++ b/tests/wpt/web-platform-tests/2dcontext/tools/tests2d.yaml
@@ -2092,6 +2092,15 @@
code: |
var g = ctx.createLinearGradient(0, 0, 100, 0);
@assert throws SYNTAX_ERR g.addColorStop(0, "");
+ @assert throws SYNTAX_ERR g.addColorStop(0, 'rgb(NaN%, NaN%, NaN%)');
+ @assert throws SYNTAX_ERR g.addColorStop(0, 'null');
+ @assert throws SYNTAX_ERR g.addColorStop(0, 'undefined');
+ @assert throws SYNTAX_ERR g.addColorStop(0, null);
+ @assert throws SYNTAX_ERR g.addColorStop(0, undefined);
+
+ var g = ctx.createRadialGradient(0, 0, 0, 100, 0, 0);
+ @assert throws SYNTAX_ERR g.addColorStop(0, "");
+ @assert throws SYNTAX_ERR g.addColorStop(0, 'rgb(NaN%, NaN%, NaN%)');
@assert throws SYNTAX_ERR g.addColorStop(0, 'null');
@assert throws SYNTAX_ERR g.addColorStop(0, 'undefined');
@assert throws SYNTAX_ERR g.addColorStop(0, null);
diff --git a/tests/wpt/web-platform-tests/FileAPI/blob/Blob-Request-revoke-fetch.html b/tests/wpt/web-platform-tests/FileAPI/blob/Blob-Request-revoke-fetch.html
new file mode 100644
index 00000000000..2cac5343cd8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/blob/Blob-Request-revoke-fetch.html
@@ -0,0 +1,41 @@
+<!doctype html>
+<title>Revoking blob URL used with Request/fetch</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<script>
+promise_test(function(t) {
+ const blob = new Blob(["test"]);
+ const url = URL.createObjectURL(blob);
+ const request = new Request(url);
+
+ // Revoke the object URL. Request should take a reference to the blob as
+ // soon as it receives it in open(), so the request succeeds even though we
+ // revoke the URL before calling fetch().
+ URL.revokeObjectURL(url);
+
+ return fetch(request).then(response => response.text()).then(text => {
+ assert_equals(text, 'test');
+ });
+}, "Revoke blob URL after creating Request, will fetch");
+
+promise_test(function(t) {
+ const blob = new Blob(["test"]);
+ const url = URL.createObjectURL(blob);
+
+ return fetch(url).then(response => response.text()).then(text => {
+ assert_equals(text, 'test');
+ });
+
+ // Revoke the object URL. fetch should have already resolved the blob URL.
+ URL.revokeObjectURL(url);
+}, "Revoke blob URL after fetch, will fetch");
+
+promise_test(t => {
+ const blob = new Blob(["test"]);
+ const url = URL.createObjectURL(blob);
+ URL.revokeObjectURL(url);
+ const request = new Request(url);
+ return promise_rejects(t, new TypeError, fetch(request));
+}, "Revoke blob URL before creating Request, network error (after fetch)")
+</script>
diff --git a/tests/wpt/web-platform-tests/FileAPI/blob/Blob-constructor-endings.html b/tests/wpt/web-platform-tests/FileAPI/blob/Blob-constructor-endings.html
new file mode 100644
index 00000000000..1dee99ff775
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/blob/Blob-constructor-endings.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Blob constructor: endings option</title>
+<link rel=help href="https://w3c.github.io/FileAPI/#constructorBlob">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+// Windows platforms use CRLF as the native line ending. All others use LF.
+const crlf = navigator.platform.startsWith('Win');
+const native_ending = crlf ? '\r\n' : '\n';
+
+function readBlobAsPromise(blob) {
+ return new Promise((resolve, reject) => {
+ const reader = new FileReader();
+ reader.readAsText(blob);
+ reader.onload = e => resolve(reader.result);
+ reader.onerror = e => reject(reader.error);
+ });
+}
+
+[
+ 'transparent',
+ 'native'
+].forEach(value => test(t => {
+ assert_class_string(new Blob([], {endings: value}), 'Blob',
+ `Constructor should allow "${value}" endings`);
+}, `Valid "endings" value: ${JSON.stringify(value)}`));
+
+[
+ null,
+ '',
+ 'invalidEnumValue',
+ 'Transparent',
+ 'NATIVE',
+ 0,
+ {}
+].forEach(value => test(t => {
+ assert_throws(new TypeError(), () => new Blob([], {endings: value}),
+ 'Blob constructor should throw');
+}, `Invalid "endings" value: ${JSON.stringify(value)}`));
+
+test(t => {
+ const test_error = {name: 'test'};
+ assert_throws(
+ test_error,
+ () => new Blob([], { get endings() { throw test_error; }}),
+ 'Blob constructor should propagate exceptions from "endings" property');
+}, 'Exception propagation from options');
+
+test(t => {
+ let got = false;
+ new Blob([], { get endings() { got = true; } });
+ assert_true(got, 'The "endings" property was accessed during construction.');
+}, 'The "endings" options property is used');
+
+[
+ {name: 'LF', input: '\n', native: native_ending},
+ {name: 'CR', input: '\r', native: native_ending},
+
+ {name: 'CRLF', input: '\r\n', native: native_ending},
+ {name: 'CRCR', input: '\r\r', native: native_ending.repeat(2)},
+ {name: 'LFCR', input: '\n\r', native: native_ending.repeat(2)},
+ {name: 'LFLF', input: '\n\n', native: native_ending.repeat(2)},
+
+ {name: 'CRCRLF', input: '\r\r\n', native: native_ending.repeat(2)},
+ {name: 'CRLFLF', input: '\r\n\n', native: native_ending.repeat(2)},
+ {name: 'CRLFCR', input: '\r\n\r\n', native: native_ending.repeat(2)},
+
+ {name: 'CRLFCRLF', input: '\r\n\r\n', native: native_ending.repeat(2)},
+ {name: 'LFCRLFCR', input: '\n\r\n\r', native: native_ending.repeat(3)},
+
+].forEach(testCase => {
+ promise_test(async t => {
+ const blob = new Blob([testCase.input]);
+ assert_equals(
+ await readBlobAsPromise(blob), testCase.input,
+ 'Newlines should not change with endings unspecified');
+ }, `Input ${testCase.name} with endings unspecified`);
+
+ promise_test(async t => {
+ const blob = new Blob([testCase.input], {endings: 'transparent'});
+ assert_equals(
+ await readBlobAsPromise(blob), testCase.input,
+ 'Newlines should not change with endings "transparent"');
+ }, `Input ${testCase.name} with endings 'transparent'`);
+
+ promise_test(async t => {
+ const blob = new Blob([testCase.input], {endings: 'native'});
+ assert_equals(
+ await readBlobAsPromise(blob), testCase.native,
+ 'Newlines should match the platform with endings "native"');
+ }, `Input ${testCase.name} with endings 'native'`);
+});
+
+promise_test(async t => {
+ const blob = new Blob(['\r', '\n'], {endings: 'native'});
+ const expected = native_ending.repeat(2);
+ assert_equals(
+ await readBlobAsPromise(blob), expected,
+ 'CR/LF in adjacent strings should be converted to two platform newlines');
+}, `CR/LF in adjacent input strings`);
+
+</script>
diff --git a/tests/wpt/web-platform-tests/FileAPI/blob/Blob-constructor.html b/tests/wpt/web-platform-tests/FileAPI/blob/Blob-constructor.html
index d8375c2a6e8..4d39ed78e0e 100644
--- a/tests/wpt/web-platform-tests/FileAPI/blob/Blob-constructor.html
+++ b/tests/wpt/web-platform-tests/FileAPI/blob/Blob-constructor.html
@@ -74,6 +74,20 @@ test_blob(function() {
type: "",
desc: "A plain object with @@iterator should be treated as a sequence for the blobParts argument."
});
+test(t => {
+ const blob = new Blob({
+ [Symbol.iterator]() {
+ var i = 0;
+ return {next: () => [
+ {done:false, value:'ab'},
+ {done:false, value:'cde'},
+ {done:true}
+ ][i++]
+ };
+ }
+ });
+ assert_equals(blob.size, 5, 'Custom @@iterator should be treated as a sequence');
+}, "A plain object with custom @@iterator should be treated as a sequence for the blobParts argument.");
test_blob(function() {
return new Blob({
[Symbol.iterator]: Array.prototype[Symbol.iterator],
@@ -392,26 +406,20 @@ test_blob(function() {
desc: "Array with mixed types"
});
-// options argument
test(function() {
- new Blob([], { endings: "invalidEnumValue" });
- new Blob([], { endings: null });
- new Blob([], { endings: undefined });
- new Blob([], { endings: 0 });
- new Blob([], { get endings() { assert_unreached("Should not call getter"); } });
-}, "The 'endings' property should be ignored.");
+ const accessed = [];
+ const stringified = [];
-test(function() {
- assert_throws(test_error, function() {
- new Blob([], {
- get type() { throw test_error; }
- });
+ new Blob([], {
+ get type() { accessed.push('type'); },
+ get endings() { accessed.push('endings'); }
});
- assert_throws(test_error, function() {
- new Blob([], {
- type: { toString: function() { throw test_error; } }
- });
+ new Blob([], {
+ type: { toString: () => { stringified.push('type'); return ''; } },
+ endings: { toString: () => { stringified.push('endings'); return 'transparent'; } }
});
+ assert_array_equals(accessed, ['endings', 'type']);
+ assert_array_equals(stringified, ['endings', 'type']);
}, "options properties should be accessed in lexicographic order.");
test(function() {
@@ -449,19 +457,16 @@ test(function() {
});
});
-test_blob(function() {
- return new Blob(["\na\r\nb\n\rc\r"], { endings: "transparent" });
-}, {
- expected: "\na\r\nb\n\rc\r",
- type: "",
- desc: "Newlines should not change when endings is 'transparent'."
-});
-test_blob(function() {
- return new Blob(["\na\r\nb\n\rc\r"], { endings: "native" });
-}, {
- expected: "\na\r\nb\n\rc\r",
- type: "",
- desc: "Newlines should not change when endings is 'native'."
+[
+ 123,
+ 123.4,
+ true,
+ 'abc'
+].forEach(arg => {
+ test(t => {
+ assert_throws(new TypeError(), () => new Blob([], arg),
+ 'Blob constructor should throw with invalid property bag');
+ }, `Passing ${JSON.stringify(arg)} for options should throw`);
});
var type_tests = [
@@ -471,6 +476,7 @@ var type_tests = [
[[], 'A', 'a'],
[[], 'text/html', 'text/html'],
[[], 'TEXT/HTML', 'text/html'],
+ [[], 'text/plain;charset=utf-8', 'text/plain;charset=utf-8'],
[[], '\u00E5', ''],
[[], '\uD801\uDC7E', ''], // U+1047E
[[], ' image/gif ', ' image/gif '],
diff --git a/tests/wpt/web-platform-tests/FileAPI/file/File-constructor-endings.html b/tests/wpt/web-platform-tests/FileAPI/file/File-constructor-endings.html
new file mode 100644
index 00000000000..f0f9090768f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/file/File-constructor-endings.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>File constructor: endings option</title>
+<link rel=help href="https://w3c.github.io/FileAPI/#file-constructor">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+// Windows platforms use CRLF as the native line ending. All others use LF.
+const crlf = navigator.platform.startsWith('Win');
+const native_ending = crlf ? '\r\n' : '\n';
+
+function readBlobAsPromise(blob) {
+ return new Promise((resolve, reject) => {
+ const reader = new FileReader();
+ reader.readAsText(blob);
+ reader.onload = e => resolve(reader.result);
+ reader.onerror = e => reject(reader.error);
+ });
+}
+
+[
+ 'transparent',
+ 'native'
+].forEach(value => test(t => {
+ assert_class_string(new File([], "name", {endings: value}), 'File',
+ `Constructor should allow "${value}" endings`);
+}, `Valid "endings" value: ${JSON.stringify(value)}`));
+
+[
+ null,
+ '',
+ 'invalidEnumValue',
+ 'Transparent',
+ 'NATIVE',
+ 0,
+ {}
+].forEach(value => test(t => {
+ assert_throws(new TypeError(), () => new File([], "name", {endings: value}),
+ 'File constructor should throw');
+}, `Invalid "endings" value: ${JSON.stringify(value)}`));
+
+test(t => {
+ const test_error = {name: 'test'};
+ assert_throws(
+ test_error,
+ () => new File([], "name", { get endings() { throw test_error; }}),
+ 'File constructor should propagate exceptions from "endings" property');
+}, 'Exception propagation from options');
+
+test(t => {
+ let got = false;
+ new File([], "name", { get endings() { got = true; } });
+ assert_true(got, 'The "endings" property was accessed during construction.');
+}, 'The "endings" options property is used');
+
+[
+ {name: 'LF', input: '\n', native: native_ending},
+ {name: 'CR', input: '\r', native: native_ending},
+
+ {name: 'CRLF', input: '\r\n', native: native_ending},
+ {name: 'CRCR', input: '\r\r', native: native_ending.repeat(2)},
+ {name: 'LFCR', input: '\n\r', native: native_ending.repeat(2)},
+ {name: 'LFLF', input: '\n\n', native: native_ending.repeat(2)},
+
+ {name: 'CRCRLF', input: '\r\r\n', native: native_ending.repeat(2)},
+ {name: 'CRLFLF', input: '\r\n\n', native: native_ending.repeat(2)},
+ {name: 'CRLFCR', input: '\r\n\r\n', native: native_ending.repeat(2)},
+
+ {name: 'CRLFCRLF', input: '\r\n\r\n', native: native_ending.repeat(2)},
+ {name: 'LFCRLFCR', input: '\n\r\n\r', native: native_ending.repeat(3)},
+
+].forEach(testCase => {
+ promise_test(async t => {
+ const file = new File([testCase.input], "name");
+ assert_equals(
+ await readBlobAsPromise(file), testCase.input,
+ 'Newlines should not change with endings unspecified');
+ }, `Input ${testCase.name} with endings unspecified`);
+
+ promise_test(async t => {
+ const file = new File([testCase.input], "name", {endings: 'transparent'});
+ assert_equals(
+ await readBlobAsPromise(file), testCase.input,
+ 'Newlines should not change with endings "transparent"');
+ }, `Input ${testCase.name} with endings 'transparent'`);
+
+ promise_test(async t => {
+ const file = new File([testCase.input], "name", {endings: 'native'});
+ assert_equals(
+ await readBlobAsPromise(file), testCase.native,
+ 'Newlines should match the platform with endings "native"');
+ }, `Input ${testCase.name} with endings 'native'`);
+});
+
+promise_test(async t => {
+ const file = new File(['\r', '\n'], "name", {endings: 'native'});
+ const expected = native_ending.repeat(2);
+ assert_equals(
+ await readBlobAsPromise(file), expected,
+ 'CR/LF in adjacent strings should be converted to two platform newlines');
+}, `CR/LF in adjacent input strings`);
+
+</script>
diff --git a/tests/wpt/web-platform-tests/FileAPI/file/File-constructor.html b/tests/wpt/web-platform-tests/FileAPI/file/File-constructor.html
index 97c08b6546e..9c1a940662a 100644
--- a/tests/wpt/web-platform-tests/FileAPI/file/File-constructor.html
+++ b/tests/wpt/web-platform-tests/FileAPI/file/File-constructor.html
@@ -6,10 +6,20 @@
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
<script>
+const to_string_obj = { toString: () => 'a string' };
+const to_string_throws = { toString: () => { throw new Error('expected'); } };
+
test(function() {
assert_true("File" in window, "window should have a File property.");
}, "File interface object exists");
+test(t => {
+ assert_throws(new TypeError(), () => new File(),
+ 'Bits argument is required');
+ assert_throws(new TypeError(), () => new File([]),
+ 'Name argument is required');
+}, 'Required arguments');
+
function test_first_argument(arg1, expectedSize, testName) {
test(function() {
var file = new File(arg1, "dummy");
@@ -22,14 +32,48 @@ function test_first_argument(arg1, expectedSize, testName) {
}, testName);
}
+test_first_argument([], 0, "empty fileBits");
test_first_argument(["bits"], 4, "DOMString fileBits");
test_first_argument(["𝓽𝓮𝔁𝓽"], 16, "Unicode DOMString fileBits");
+test_first_argument([new String('string object')], 13, "String object fileBits");
test_first_argument([new Blob()], 0, "Empty Blob fileBits");
test_first_argument([new Blob(["bits"])], 4, "Blob fileBits");
+test_first_argument([new File([], 'world.txt')], 0, "Empty File fileBits");
+test_first_argument([new File(["bits"], 'world.txt')], 4, "File fileBits");
test_first_argument([new ArrayBuffer(8)], 8, "ArrayBuffer fileBits");
test_first_argument([new Uint8Array([0x50, 0x41, 0x53, 0x53])], 4, "Typed array fileBits");
test_first_argument(["bits", new Blob(["bits"]), new Blob(), new Uint8Array([0x50, 0x41]),
new Uint16Array([0x5353]), new Uint32Array([0x53534150])], 16, "Various fileBits");
+test_first_argument([12], 2, "Number in fileBits");
+test_first_argument([[1,2,3]], 5, "Array in fileBits");
+test_first_argument([{}], 15, "Object in fileBits"); // "[object Object]"
+test_first_argument([document], 21, "HTMLDocument in fileBits"); // "[object HTMLDocument]"
+test_first_argument([to_string_obj], 8, "Object with toString in fileBits");
+test_first_argument({[Symbol.iterator]() {
+ let i = 0;
+ return {next: () => [
+ {done:false, value:'ab'},
+ {done:false, value:'cde'},
+ {done:true}
+ ][i++]};
+}}, 5, 'Custom @@iterator');
+
+[
+ 'hello',
+ 0,
+ null
+].forEach(arg => {
+ test(t => {
+ assert_throws(new TypeError(), () => new File(arg, 'world.html'),
+ 'Constructor should throw for invalid bits argument');
+ }, `Invalid bits argument: ${JSON.stringify(arg)}`);
+});
+
+test(t => {
+ assert_throws(new Error(), () => new File([to_string_throws], 'name.txt'),
+ 'Constructor should propagate exceptions');
+}, 'Bits argument: object that throws');
+
function test_second_argument(arg2, expectedFileName, testName) {
test(function() {
@@ -41,23 +85,29 @@ function test_second_argument(arg2, expectedFileName, testName) {
test_second_argument("dummy", "dummy", "Using fileName");
test_second_argument("dummy/foo", "dummy:foo", "Using special character in fileName");
+test_second_argument(null, "null", "Using null fileName");
+test_second_argument(1, "1", "Using number fileName");
+test_second_argument('', '', "Using empty string fileName");
+test_second_argument(document, '[object HTMLDocument]', "Using object fileName");
// testing the third argument
-test(function() {
- var file = new File(["bits"], "dummy", { type: "text/plain"});
- assert_true(file instanceof File);
- assert_equals(file.type, "text/plain");
-}, "Using type on the File constructor");
-test(function() {
- var file = new File(["bits"], "dummy", { type: "TEXT/PLAIN"});
- assert_true(file instanceof File);
- assert_equals(file.type, "text/plain");
-}, "Using uppercase characters in type");
-test(function() {
- var file = new File(["bits"], "dummy", { type: "𝓽𝓮𝔁𝓽/𝔭𝔩𝔞𝔦𝔫"});
- assert_true(file instanceof File);
- assert_equals(file.type, "");
-}, "Using illegal character for type");
+[
+ {type: 'text/plain', expected: 'text/plain'},
+ {type: 'text/plain;charset=UTF-8', expected: 'text/plain;charset=utf-8'},
+ {type: 'TEXT/PLAIN', expected: 'text/plain'},
+ {type: '𝓽𝓮𝔁𝓽/𝔭𝔩𝔞𝔦𝔫', expected: ''},
+ {type: 'ascii/nonprintable\u001F', expected: ''},
+ {type: 'ascii/nonprintable\u007F', expected: ''},
+ {type: 'nonascii\u00EE', expected: ''},
+ {type: 'nonascii\u1234', expected: ''},
+ {type: 'nonparsable', expected: 'nonparsable'}
+].forEach(testCase => {
+ test(t => {
+ var file = new File(["bits"], "dummy", { type: testCase.type});
+ assert_true(file instanceof File);
+ assert_equals(file.type, testCase.expected);
+ }, `Using type in File constructor: ${testCase.type}`);
+});
test(function() {
var file = new File(["bits"], "dummy", { lastModified: 42 });
assert_true(file instanceof File);
@@ -68,5 +118,41 @@ test(function() {
assert_true(file instanceof File);
assert_equals(file.name, "dummy");
}, "Misusing name");
+test(function() {
+ var file = new File(["bits"], "dummy", { unknownKey: "value" });
+ assert_true(file instanceof File);
+ assert_equals(file.name, "dummy");
+}, "Unknown properties are ignored");
+
+[
+ 123,
+ 123.4,
+ true,
+ 'abc'
+].forEach(arg => {
+ test(t => {
+ assert_throws(new TypeError(), () => new File(['bits'], 'name.txt', arg),
+ 'Constructor should throw for invalid property bag type');
+ }, `Invalid property bag: ${JSON.stringify(arg)}`);
+});
+
+[
+ null,
+ undefined,
+ [1,2,3],
+ /regex/,
+ function() {}
+].forEach(arg => {
+ test(t => {
+ assert_equals(new File(['bits'], 'name.txt', arg).size, 4,
+ 'Constructor should accept object-ish property bag type');
+ }, `Unusual but valid property bag: ${arg}`);
+});
+
+test(t => {
+ assert_throws(new Error(),
+ () => new File(['bits'], 'name.txt', {type: to_string_throws}),
+ 'Constructor should propagate exceptions');
+}, 'Property bag propagates exceptions');
</script>
diff --git a/tests/wpt/web-platform-tests/FileAPI/file/send-file-form-iso-2022-jp.tentative.html b/tests/wpt/web-platform-tests/FileAPI/file/send-file-form-iso-2022-jp.tentative.html
new file mode 100644
index 00000000000..421de301298
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/file/send-file-form-iso-2022-jp.tentative.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Upload files in ISO-2022-JP form (tentative)</title>
+<!--
+ NOTE: This test is tentative because encoding for filename
+ characters unrepresentable in the form charset is not yet
+ standardized.
+ -->
+<link rel="help"
+ href="https://github.com/whatwg/html/issues/3223">
+<link rel="help"
+ href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data">
+<link rel="help"
+ href="https://html.spec.whatwg.org/multipage/dnd.html#datatransferitemlist">
+<link rel="help"
+ href="https://w3c.github.io/FileAPI/#file-constructor">
+<link rel="author" title="Benjamin C. Wiley Sittler"
+ href="mailto:bsittler@chromium.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../support/send-file-form-helper.js"></script>
+<script>
+'use strict';
+
+formPostFileUploadTest({
+ fileNameSource: 'ASCII',
+ fileBaseName: 'file-for-upload-in-form.txt',
+ formEncoding: 'ISO-2022-JP',
+ expectedEncodedBaseName: 'file-for-upload-in-form.txt',
+});
+
+formPostFileUploadTest({
+ fileNameSource: 'x-user-defined',
+ fileBaseName: 'file-for-upload-in-form-\uF7F0\uF793\uF783\uF7A0.txt',
+ formEncoding: 'ISO-2022-JP',
+ expectedEncodedBaseName: (
+ 'file-for-upload-in-form-&#63472;&#63379;&#63363;&#63392;.txt'),
+});
+
+formPostFileUploadTest({
+ fileNameSource: 'windows-1252',
+ fileBaseName: 'file-for-upload-in-form-☺😂.txt',
+ formEncoding: 'ISO-2022-JP',
+ expectedEncodedBaseName: (
+ 'file-for-upload-in-form-&#226;&#732;&#186;&#240;&#376;&#732;&#8218;.txt'),
+});
+
+formPostFileUploadTest({
+ fileNameSource: 'JIS X 0201 and JIS X 0208',
+ fileBaseName: 'file-for-upload-in-form-★星★.txt',
+ formEncoding: 'ISO-2022-JP',
+ expectedEncodedBaseName: 'file-for-upload-in-form-\x1B$B!z@1!z\x1B(B.txt',
+});
+
+formPostFileUploadTest({
+ fileNameSource: 'Unicode',
+ fileBaseName: 'file-for-upload-in-form-☺😂.txt',
+ formEncoding: 'ISO-2022-JP',
+ expectedEncodedBaseName: 'file-for-upload-in-form-&#9786;&#128514;.txt',
+});
+
+formPostFileUploadTest({
+ fileNameSource: 'Unicode',
+ fileBaseName: `file-for-upload-in-form-${kTestChars}.txt`,
+ formEncoding: 'ISO-2022-JP',
+ expectedEncodedBaseName: `file-for-upload-in-form-${
+ kTestFallbackIso2022jp
+ }.txt`,
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/FileAPI/file/send-file-form-utf-8.html b/tests/wpt/web-platform-tests/FileAPI/file/send-file-form-utf-8.html
new file mode 100644
index 00000000000..03417ba72e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/file/send-file-form-utf-8.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Upload files in UTF-8 form</title>
+<link rel="help"
+ href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data">
+<link rel="help"
+ href="https://html.spec.whatwg.org/multipage/dnd.html#datatransferitemlist">
+<link rel="help"
+ href="https://w3c.github.io/FileAPI/#file-constructor">
+<link rel="author" title="Benjamin C. Wiley Sittler"
+ href="mailto:bsittler@chromium.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../support/send-file-form-helper.js"></script>
+<script>
+'use strict';
+
+formPostFileUploadTest({
+ fileNameSource: 'ASCII',
+ fileBaseName: 'file-for-upload-in-form.txt',
+ formEncoding: 'UTF-8',
+ expectedEncodedBaseName: 'file-for-upload-in-form.txt',
+});
+
+formPostFileUploadTest({
+ fileNameSource: 'x-user-defined',
+ fileBaseName: 'file-for-upload-in-form-\uF7F0\uF793\uF783\uF7A0.txt',
+ formEncoding: 'UTF-8',
+ expectedEncodedBaseName: (
+ 'file-for-upload-in-form-\uF7F0\uF793\uF783\uF7A0.txt'),
+});
+
+formPostFileUploadTest({
+ fileNameSource: 'windows-1252',
+ fileBaseName: 'file-for-upload-in-form-☺😂.txt',
+ formEncoding: 'UTF-8',
+ expectedEncodedBaseName: 'file-for-upload-in-form-☺😂.txt',
+});
+
+formPostFileUploadTest({
+ fileNameSource: 'JIS X 0201 and JIS X 0208',
+ fileBaseName: 'file-for-upload-in-form-★星★.txt',
+ formEncoding: 'UTF-8',
+ expectedEncodedBaseName: 'file-for-upload-in-form-★星★.txt',
+});
+
+formPostFileUploadTest({
+ fileNameSource: 'Unicode',
+ fileBaseName: 'file-for-upload-in-form-☺😂.txt',
+ formEncoding: 'UTF-8',
+ expectedEncodedBaseName: 'file-for-upload-in-form-☺😂.txt',
+});
+
+formPostFileUploadTest({
+ fileNameSource: 'Unicode',
+ fileBaseName: `file-for-upload-in-form-${kTestChars}.txt`,
+ formEncoding: 'UTF-8',
+ expectedEncodedBaseName: `file-for-upload-in-form-${kTestChars}.txt`,
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/FileAPI/file/send-file-form-windows-1252.tentative.html b/tests/wpt/web-platform-tests/FileAPI/file/send-file-form-windows-1252.tentative.html
new file mode 100644
index 00000000000..8e9463f83ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/file/send-file-form-windows-1252.tentative.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Upload files in Windows-1252 form (tentative)</title>
+<!--
+ NOTE: This test is tentative because encoding for filename
+ characters unrepresentable in the form charset is not yet
+ standardized.
+ -->
+<link rel="help"
+ href="https://github.com/whatwg/html/issues/3223">
+<link rel="help"
+ href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data">
+<link rel="help"
+ href="https://html.spec.whatwg.org/multipage/dnd.html#datatransferitemlist">
+<link rel="help"
+ href="https://w3c.github.io/FileAPI/#file-constructor">
+<link rel="author" title="Benjamin C. Wiley Sittler"
+ href="mailto:bsittler@chromium.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../support/send-file-form-helper.js"></script>
+<script>
+'use strict';
+
+formPostFileUploadTest({
+ fileNameSource: 'ASCII',
+ fileBaseName: 'file-for-upload-in-form.txt',
+ formEncoding: 'windows-1252',
+ expectedEncodedBaseName: 'file-for-upload-in-form.txt',
+});
+
+formPostFileUploadTest({
+ fileNameSource: 'x-user-defined',
+ fileBaseName: 'file-for-upload-in-form-\uF7F0\uF793\uF783\uF7A0.txt',
+ formEncoding: 'windows-1252',
+ expectedEncodedBaseName: (
+ 'file-for-upload-in-form-&#63472;&#63379;&#63363;&#63392;.txt'),
+});
+
+formPostFileUploadTest({
+ fileNameSource: 'windows-1252',
+ fileBaseName: 'file-for-upload-in-form-☺😂.txt',
+ formEncoding: 'windows-1252',
+ expectedEncodedBaseName: 'file-for-upload-in-form-☺😂.txt',
+});
+
+formPostFileUploadTest({
+ fileNameSource: 'JIS X 0201 and JIS X 0208',
+ fileBaseName: 'file-for-upload-in-form-★星★.txt',
+ formEncoding: 'windows-1252',
+ expectedEncodedBaseName: 'file-for-upload-in-form-&#9733;&#26143;&#9733;.txt',
+});
+
+formPostFileUploadTest({
+ fileNameSource: 'Unicode',
+ fileBaseName: 'file-for-upload-in-form-☺😂.txt',
+ formEncoding: 'windows-1252',
+ expectedEncodedBaseName: 'file-for-upload-in-form-&#9786;&#128514;.txt',
+});
+
+formPostFileUploadTest({
+ fileNameSource: 'Unicode',
+ fileBaseName: `file-for-upload-in-form-${kTestChars}.txt`,
+ formEncoding: 'windows-1252',
+ expectedEncodedBaseName: `file-for-upload-in-form-${
+ kTestFallbackWindows1252
+ }.txt`,
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/FileAPI/file/send-file-form-x-user-defined.tentative.html b/tests/wpt/web-platform-tests/FileAPI/file/send-file-form-x-user-defined.tentative.html
new file mode 100644
index 00000000000..072e3bb1e02
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/file/send-file-form-x-user-defined.tentative.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Upload files in x-user-defined form (tentative)</title>
+<!--
+ NOTE: This test is tentative because encoding for filename
+ characters unrepresentable in the form charset is not yet
+ standardized.
+ -->
+<link rel="help"
+ href="https://github.com/whatwg/html/issues/3223">
+<link rel="help"
+ href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data">
+<link rel="help"
+ href="https://html.spec.whatwg.org/multipage/dnd.html#datatransferitemlist">
+<link rel="help"
+ href="https://w3c.github.io/FileAPI/#file-constructor">
+<link rel="author" title="Benjamin C. Wiley Sittler"
+ href="mailto:bsittler@chromium.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../support/send-file-form-helper.js"></script>
+<script>
+'use strict';
+
+formPostFileUploadTest({
+ fileNameSource: 'ASCII',
+ fileBaseName: 'file-for-upload-in-form.txt',
+ formEncoding: 'x-user-defined',
+ expectedEncodedBaseName: 'file-for-upload-in-form.txt',
+});
+
+formPostFileUploadTest({
+ fileNameSource: 'x-user-defined',
+ fileBaseName: 'file-for-upload-in-form-\uF7F0\uF793\uF783\uF7A0.txt',
+ formEncoding: 'x-user-defined',
+ expectedEncodedBaseName: 'file-for-upload-in-form-𓃠.txt',
+});
+
+formPostFileUploadTest({
+ fileNameSource: 'windows-1252',
+ fileBaseName: 'file-for-upload-in-form-☺😂.txt',
+ formEncoding: 'x-user-defined',
+ expectedEncodedBaseName: ('file-for-upload-in-form-' +
+ '&#226;&#732;&#186;&#240;&#376;&#732;&#8218;.txt'),
+});
+
+formPostFileUploadTest({
+ fileNameSource: 'JIS X 0201 and JIS X 0208',
+ fileBaseName: 'file-for-upload-in-form-★星★.txt',
+ formEncoding: 'x-user-defined',
+ expectedEncodedBaseName: 'file-for-upload-in-form-&#9733;&#26143;&#9733;.txt',
+});
+
+formPostFileUploadTest({
+ fileNameSource: 'Unicode',
+ fileBaseName: 'file-for-upload-in-form-☺😂.txt',
+ formEncoding: 'x-user-defined',
+ expectedEncodedBaseName: 'file-for-upload-in-form-&#9786;&#128514;.txt',
+});
+
+formPostFileUploadTest({
+ fileNameSource: 'Unicode',
+ fileBaseName: `file-for-upload-in-form-${kTestChars}.txt`,
+ formEncoding: 'x-user-defined',
+ expectedEncodedBaseName: `file-for-upload-in-form-${
+ kTestFallbackXUserDefined
+ }.txt`,
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/FileAPI/file/send-file-form.html b/tests/wpt/web-platform-tests/FileAPI/file/send-file-form.html
new file mode 100644
index 00000000000..baa8d4286c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/file/send-file-form.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Upload ASCII-named file in UTF-8 form</title>
+<link rel="help"
+ href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data">
+<link rel="help"
+ href="https://html.spec.whatwg.org/multipage/dnd.html#datatransferitemlist">
+<link rel="help"
+ href="https://w3c.github.io/FileAPI/#file-constructor">
+<link rel="author" title="Benjamin C. Wiley Sittler"
+ href="mailto:bsittler@chromium.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../support/send-file-form-helper.js"></script>
+<script>
+'use strict';
+
+formPostFileUploadTest({
+ fileNameSource: 'ASCII',
+ fileBaseName: 'file-for-upload-in-form.txt',
+ formEncoding: 'UTF-8',
+ expectedEncodedBaseName: 'file-for-upload-in-form.txt',
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/FileAPI/idlharness.html b/tests/wpt/web-platform-tests/FileAPI/idlharness.html
index b88a7521688..7b706ad0dd8 100644
--- a/tests/wpt/web-platform-tests/FileAPI/idlharness.html
+++ b/tests/wpt/web-platform-tests/FileAPI/idlharness.html
@@ -30,8 +30,6 @@ setup(function() {
request.onload = function() {
var idls = request.responseText;
- idl_array.add_untested_idls("[PrimaryGlobal] interface Window { };");
-
idl_array.add_untested_idls("[Exposed=(Window,Worker)] interface ArrayBuffer {};");
idl_array.add_untested_idls("interface URL {};");
idl_array.add_untested_idls("[Exposed=(Window,Worker)] interface EventTarget {};");
diff --git a/tests/wpt/web-platform-tests/FileAPI/support/send-file-form-helper.js b/tests/wpt/web-platform-tests/FileAPI/support/send-file-form-helper.js
new file mode 100644
index 00000000000..a7522c7b08e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/support/send-file-form-helper.js
@@ -0,0 +1,249 @@
+'use strict';
+
+// Rationale for this particular test character sequence, which is
+// used in filenames and also in file contents:
+//
+// - ABC~ ensures the string starts with something we can read to
+// ensure it is from the correct source; ~ is used because even
+// some 1-byte otherwise-ASCII-like parts of ISO-2022-JP
+// interpret it differently.
+// - ‾¥ are inside a single-byte range of ISO-2022-JP and help
+// diagnose problems due to filesystem encoding or locale
+// - ≈ is inside IBM437 and helps diagnose problems due to filesystem
+// encoding or locale
+// - ¤ is inside Latin-1 and helps diagnose problems due to
+// filesystem encoding or locale; it is also the "simplest" case
+// needing substitution in ISO-2022-JP
+// - ・ is inside a single-byte range of ISO-2022-JP in some variants
+// and helps diagnose problems due to filesystem encoding or locale;
+// on the web it is distinct when decoding but unified when encoding
+// - ・ is inside a double-byte range of ISO-2022-JP and helps
+// diagnose problems due to filesystem encoding or locale
+// - • is inside Windows-1252 and helps diagnose problems due to
+// filesystem encoding or locale and also ensures these aren't
+// accidentally turned into e.g. control codes
+// - ∙ is inside IBM437 and helps diagnose problems due to filesystem
+// encoding or locale
+// - · is inside Latin-1 and helps diagnose problems due to
+// filesystem encoding or locale and also ensures HTML named
+// character references (e.g. &middot;) are not used
+// - ☼ is inside IBM437 shadowing C0 and helps diagnose problems due to
+// filesystem encoding or locale and also ensures these aren't
+// accidentally turned into e.g. control codes
+// - ★ is inside ISO-2022-JP on a non-Kanji page and makes correct
+// output easier to spot
+// - 星 is inside ISO-2022-JP on a Kanji page and makes correct
+// output easier to spot
+// - 🌟 is outside the BMP and makes incorrect surrogate pair
+// substitution detectable and ensures substitutions work
+// correctly immediately after Kanji 2-byte ISO-2022-JP
+// - 星 repeated here ensures the correct codec state is used
+// after a non-BMP substitution
+// - ★ repeated here also makes correct output easier to spot
+// - ☼ is inside IBM437 shadowing C0 and helps diagnose problems due to
+// filesystem encoding or locale and also ensures these aren't
+// accidentally turned into e.g. control codes and also ensures
+// substitutions work correctly immediately after non-Kanji
+// 2-byte ISO-2022-JP
+// - · is inside Latin-1 and helps diagnose problems due to
+// filesystem encoding or locale and also ensures HTML named
+// character references (e.g. &middot;) are not used
+// - ∙ is inside IBM437 and helps diagnose problems due to filesystem
+// encoding or locale
+// - • is inside Windows-1252 and again helps diagnose problems
+// due to filesystem encoding or locale
+// - ・ is inside a double-byte range of ISO-2022-JP and helps
+// diagnose problems due to filesystem encoding or locale
+// - ・ is inside a single-byte range of ISO-2022-JP in some variants
+// and helps diagnose problems due to filesystem encoding or locale;
+// on the web it is distinct when decoding but unified when encoding
+// - ¤ is inside Latin-1 and helps diagnose problems due to
+// filesystem encoding or locale; again it is a "simple"
+// substitution case
+// - ≈ is inside IBM437 and helps diagnose problems due to filesystem
+// encoding or locale
+// - ¥‾ are inside a single-byte range of ISO-2022-JP and help
+// diagnose problems due to filesystem encoding or locale
+// - ~XYZ ensures earlier errors don't lead to misencoding of
+// simple ASCII
+//
+// Overall the near-symmetry makes common I18N mistakes like
+// off-by-1-after-non-BMP easier to spot. All the characters
+// are also allowed in Windows Unicode filenames.
+const kTestChars = 'ABC~‾¥≈¤・・•∙·☼★星🌟星★☼·∙•・・¤≈¥‾~XYZ';
+
+// NOTE: The expected interpretation of ISO-2022-JP according to
+// https://encoding.spec.whatwg.org/#iso-2022-jp-encoder unifies
+// single-byte and double-byte katakana.
+const kTestFallbackIso2022jp =
+ ('ABC~\x1B(J~\\≈¤\x1B$B!&!&\x1B(B•∙·☼\x1B$B!z@1\x1B(B🌟' +
+ '\x1B$B@1!z\x1B(B☼·∙•\x1B$B!&!&\x1B(B¤≈\x1B(J\\~\x1B(B~XYZ').replace(
+ /[^\0-\x7F]/gu,
+ x => `&#${x.codePointAt(0)};`);
+
+// NOTE: \uFFFD is used here to replace Windows-1252 bytes to match
+// how we will see them in the reflected POST bytes in a frame using
+// UTF-8 byte interpretation. The bytes will actually be intact, but
+// this code cannot tell and does not really care.
+const kTestFallbackWindows1252 =
+ 'ABC~‾\xA5≈\xA4・・\x95∙\xB7☼★星🌟星★☼\xB7∙\x95・・\xA4≈\xA5‾~XYZ'.replace(
+ /[^\0-\xFF]/gu,
+ x => `&#${x.codePointAt(0)};`).replace(/[\x80-\xFF]/g, '\uFFFD');
+
+const kTestFallbackXUserDefined =
+ kTestChars.replace(/[^\0-\x7F]/gu, x => `&#${x.codePointAt(0)};`);
+
+// formPostFileUploadTest - verifies multipart upload structure and
+// numeric character reference replacement for filenames, field names,
+// and field values.
+//
+// Uses /fetch/api/resources/echo-content.py to echo the upload
+// POST with UTF-8 byte interpretation, leading to the "UTF-8 goggles"
+// behavior documented below for expectedEncodedBaseName when non-
+// UTF-8-compatible byte sequences appear in the formEncoding-encoded
+// uploaded data.
+//
+// Fields in the parameter object:
+//
+// - fileNameSource: purely explanatory and gives a clue about which
+// character encoding is the source for the non-7-bit-ASCII parts of
+// the fileBaseName, or Unicode if no smaller-than-Unicode source
+// contains all the characters. Used in the test name.
+// - fileBaseName: the not-necessarily-just-7-bit-ASCII file basename
+// used for the constructed test file. Used in the test name.
+// - formEncoding: the acceptCharset of the form used to submit the
+// test file. Used in the test name.
+// - expectedEncodedBaseName: the expected formEncoding-encoded
+// version of fileBaseName with unencodable characters replaced by
+// numeric character references and non-7-bit-ASCII bytes seen
+// through UTF-8 goggles; subsequences not interpretable as UTF-8
+// have each byte represented here by \uFFFD REPLACEMENT CHARACTER.
+const formPostFileUploadTest = ({
+ fileNameSource,
+ fileBaseName,
+ formEncoding,
+ expectedEncodedBaseName,
+}) => {
+ promise_test(async testCase => {
+
+ if (document.readyState !== 'complete') {
+ await new Promise(resolve => addEventListener('load', resolve));
+ }
+
+ const formTargetFrame = Object.assign(document.createElement('iframe'), {
+ name: 'formtargetframe',
+ });
+ document.body.append(formTargetFrame);
+ testCase.add_cleanup(() => {
+ document.body.removeChild(formTargetFrame);
+ });
+
+ const form = Object.assign(document.createElement('form'), {
+ acceptCharset: formEncoding,
+ action: '/fetch/api/resources/echo-content.py',
+ method: 'POST',
+ enctype: 'multipart/form-data',
+ target: formTargetFrame.name,
+ });
+ document.body.append(form);
+ testCase.add_cleanup(() => {
+ document.body.removeChild(form);
+ });
+
+ // Used to verify that the browser agrees with the test about
+ // which form charset is used.
+ form.append(Object.assign(document.createElement('input'), {
+ type: 'hidden',
+ name: '_charset_',
+ }));
+
+ // Used to verify that the browser agrees with the test about
+ // field value replacement and encoding independently of file system
+ // idiosyncracies.
+ form.append(Object.assign(document.createElement('input'), {
+ type: 'hidden',
+ name: 'filename',
+ value: fileBaseName,
+ }));
+
+ // Same, but with name and value reversed to ensure field names
+ // get the same treatment.
+ form.append(Object.assign(document.createElement('input'), {
+ type: 'hidden',
+ name: fileBaseName,
+ value: 'filename',
+ }));
+
+ const fileInput = Object.assign(document.createElement('input'), {
+ type: 'file',
+ name: 'file',
+ });
+ form.append(fileInput);
+
+ // Removes c:\fakepath\ or other pseudofolder and returns just the
+ // final component of filePath; allows both / and \ as segment
+ // delimiters.
+ const baseNameOfFilePath = filePath => filePath.split(/[\/\\]/).pop();
+ await new Promise(resolve => {
+ const dataTransfer = new DataTransfer;
+ dataTransfer.items.add(
+ new File([kTestChars], fileBaseName, {type: 'text/plain'}));
+ fileInput.files = dataTransfer.files;
+ // For historical reasons .value will be prefixed with
+ // c:\fakepath\, but the basename should match the file name
+ // exposed through the newer .files[0].name API. This check
+ // verifies that assumption.
+ assert_equals(
+ fileInput.files[0].name,
+ baseNameOfFilePath(fileInput.value),
+ `The basename of the field's value should match its files[0].name`);
+ form.submit();
+ formTargetFrame.onload = resolve;
+ });
+
+ const formDataText = formTargetFrame.contentDocument.body.textContent;
+ const formDataLines = formDataText.split('\n');
+ if (formDataLines.length && !formDataLines[formDataLines.length - 1]) {
+ --formDataLines.length;
+ }
+ assert_greater_than(
+ formDataLines.length,
+ 2,
+ `${fileBaseName}: multipart form data must have at least 3 lines: ${
+ JSON.stringify(formDataText)
+ }`);
+ const boundary = formDataLines[0];
+ assert_equals(
+ formDataLines[formDataLines.length - 1],
+ boundary + '--',
+ `${fileBaseName}: multipart form data must end with ${boundary}--: ${
+ JSON.stringify(formDataText)
+ }`);
+ const expectedText = [
+ boundary,
+ 'Content-Disposition: form-data; name="_charset_"',
+ '',
+ formEncoding,
+ boundary,
+ 'Content-Disposition: form-data; name="filename"',
+ '',
+ expectedEncodedBaseName,
+ boundary,
+ `Content-Disposition: form-data; name="${expectedEncodedBaseName}"`,
+ '',
+ 'filename',
+ boundary,
+ `Content-Disposition: form-data; name="file"; ` +
+ `filename="${expectedEncodedBaseName}"`,
+ 'Content-Type: text/plain',
+ '',
+ kTestChars,
+ boundary + '--',
+ ].join('\n');
+ assert_true(
+ formDataText.startsWith(expectedText),
+ `Unexpected multipart-shaped form data received:\n${
+ formDataText
+ }\nExpected:\n${expectedText}`);
+ }, `Upload ${fileBaseName} (${fileNameSource}) in ${formEncoding} form`);
+};
diff --git a/tests/wpt/web-platform-tests/FileAPI/unicode.html b/tests/wpt/web-platform-tests/FileAPI/unicode.html
new file mode 100644
index 00000000000..ce3e3579d7c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/unicode.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Blob/Unicode interaction: normalization and encoding</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+'use strict';
+
+const OMICRON_WITH_OXIA = '\u1F79'; // NFC normalized to U+3CC
+const CONTAINS_UNPAIRED_SURROGATES = 'abc\uDC00def\uD800ghi';
+const REPLACED = 'abc\uFFFDdef\uFFFDghi';
+
+function readBlobAsPromise(blob) {
+ return new Promise((resolve, reject) => {
+ const reader = new FileReader();
+ reader.readAsText(blob);
+ reader.onload = () => resolve(reader.result);
+ reader.onerror = () => reject(reader.error);
+ });
+}
+
+promise_test(async t => {
+ const blob = new Blob([OMICRON_WITH_OXIA]);
+ const result = await readBlobAsPromise(blob);
+ assert_equals(result, OMICRON_WITH_OXIA, 'String should not be normalized');
+}, 'Test that strings are not NFC normalized by Blob constructor');
+
+promise_test(async t => {
+ const file = new File([OMICRON_WITH_OXIA], 'name');
+ const result = await readBlobAsPromise(file);
+ assert_equals(result, OMICRON_WITH_OXIA, 'String should not be normalized');
+}, 'Test that strings are not NFC normalized by File constructor');
+
+promise_test(async t => {
+ const blob = new Blob([CONTAINS_UNPAIRED_SURROGATES]);
+ const result = await readBlobAsPromise(blob);
+ assert_equals(result, REPLACED, 'Unpaired surrogates should be replaced.');
+}, 'Test that unpaired surrogates are replaced by Blob constructor');
+
+promise_test(async t => {
+ const file = new File([CONTAINS_UNPAIRED_SURROGATES], 'name');
+ const result = await readBlobAsPromise(file);
+ assert_equals(result, REPLACED, 'Unpaired surrogates should be replaced.');
+}, 'Test that unpaired surrogates are replaced by File constructor');
+
+</script>
diff --git a/tests/wpt/web-platform-tests/FileAPI/url/url_xmlhttprequest_img.html b/tests/wpt/web-platform-tests/FileAPI/url/url_xmlhttprequest_img.html
index 7f26633d81e..468dcb086d7 100644
--- a/tests/wpt/web-platform-tests/FileAPI/url/url_xmlhttprequest_img.html
+++ b/tests/wpt/web-platform-tests/FileAPI/url/url_xmlhttprequest_img.html
@@ -20,9 +20,8 @@
http.onloadend = function() {
var fileDisplay = document.querySelector("#fileDisplay");
fileDisplay.src = window.URL.createObjectURL(http.response);
- takeScreenshot();
+ fileDisplay.onload = takeScreenshot;
};
http.send();
</script>
</html>
-
diff --git a/tests/wpt/web-platform-tests/IndexedDB/interfaces.html b/tests/wpt/web-platform-tests/IndexedDB/interfaces.html
index 6fb37f88e51..30372b6d60b 100644
--- a/tests/wpt/web-platform-tests/IndexedDB/interfaces.html
+++ b/tests/wpt/web-platform-tests/IndexedDB/interfaces.html
@@ -20,7 +20,7 @@ async_test(function(t) {
var idls = request.responseText;
// https://html.spec.whatwg.org/multipage/browsers.html#window
- idlArray.add_untested_idls("[PrimaryGlobal] interface Window { };");
+ idlArray.add_untested_idls("[Global=Window, Exposed=Window] interface Window { };");
// https://html.spec.whatwg.org/multipage/webappapis.html#windoworworkerglobalscope-mixin
idlArray.add_untested_idls(`[NoInterfaceObject, Exposed=(Window,Worker)]
diff --git a/tests/wpt/web-platform-tests/README.md b/tests/wpt/web-platform-tests/README.md
index b67e2082ab7..0247e8c69ce 100644
--- a/tests/wpt/web-platform-tests/README.md
+++ b/tests/wpt/web-platform-tests/README.md
@@ -53,8 +53,15 @@ Running Tests Manually
======================
The test server can be started using
+```
+./wpt serve
+```
- ./wpt serve
+**On Windows**: You will need to preceed the prior command with
+`python` or the path to the python binary.
+```bash
+python wpt serve
+```
This will start HTTP servers on two ports and a websockets server on
one port. By default one web server starts on port 8000 and the other
@@ -82,12 +89,15 @@ file setup documented above, but you must *not* have the
test server already running when calling `wpt run`. The basic command
line syntax is:
-```
+```bash
./wpt run product [tests]
```
**On Windows**: You will need to preceed the prior command with
`python` or the path to the python binary.
+```bash
+python wpt product [tests]
+```
where `product` is currently `firefox` or `chrome` and `[tests]` is a
list of paths to tests. This will attempt to automatically locate a
@@ -114,7 +124,7 @@ brew install nss
On other platforms, download the firefox archive and common.tests.zip
archive for your platform from
-[https://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central/](Mozilla CI)
+[Mozilla CI](https://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central/).
Then extract `certutil[.exe]` from the tests.zip package and
`libnss3[.so|.dll|.dynlib]` and put the former on your path and the latter on
@@ -187,9 +197,13 @@ then remove the `tools` and `resources` directories, as above.
<span id="windows-notes">Windows Notes</span>
=============================================
-On Windows `wpt` commands mut bre prefixed with `python` or the path
+On Windows `wpt` commands must be prefixed with `python` or the path
to the python binary (if `python` is not in your `%PATH%`).
+```bash
+python wpt [command]
+```
+
Alternatively, you may also use
[Bash on Ubuntu on Windows](https://msdn.microsoft.com/en-us/commandline/wsl/about)
in the Windows 10 Anniversary Update build, then access your windows
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures.worker.js b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures.worker.js
deleted file mode 100644
index 705664c2d92..00000000000
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures.worker.js
+++ /dev/null
@@ -1,5 +0,0 @@
-importScripts("/resources/testharness.js");
-importScripts("../util/helpers.js");
-importScripts("failures.js");
-run_test();
-done();
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_AES-CBC.worker.js b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_AES-CBC.https.worker.js
index 7bb3e7f697f..7bb3e7f697f 100644
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_AES-CBC.worker.js
+++ b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_AES-CBC.https.worker.js
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_AES-CTR.worker.js b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_AES-CTR.https.worker.js
index f6766b27bba..f6766b27bba 100644
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_AES-CTR.worker.js
+++ b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_AES-CTR.https.worker.js
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_AES-GCM.worker.js b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_AES-GCM.https.worker.js
index 1383e589559..1383e589559 100644
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_AES-GCM.worker.js
+++ b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_AES-GCM.https.worker.js
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_AES-KW.worker.js b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_AES-KW.https.worker.js
index 04f5bb6edab..04f5bb6edab 100644
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_AES-KW.worker.js
+++ b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_AES-KW.https.worker.js
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_ECDH.worker.js b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_ECDH.https.worker.js
index a7e6a7240bc..a7e6a7240bc 100644
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_ECDH.worker.js
+++ b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_ECDH.https.worker.js
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_ECDSA.worker.js b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_ECDSA.https.worker.js
index a1f471141de..a1f471141de 100644
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_ECDSA.worker.js
+++ b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_ECDSA.https.worker.js
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_HMAC.worker.js b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_HMAC.https.worker.js
index 9dfbbb9c065..9dfbbb9c065 100644
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_HMAC.worker.js
+++ b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_HMAC.https.worker.js
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_RSA-OAEP.worker.js b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_RSA-OAEP.https.worker.js
index 39de6d6efec..39de6d6efec 100644
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_RSA-OAEP.worker.js
+++ b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_RSA-OAEP.https.worker.js
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_RSA-PSS.worker.js b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_RSA-PSS.https.worker.js
index 8b1110d7f09..8b1110d7f09 100644
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_RSA-PSS.worker.js
+++ b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_RSA-PSS.https.worker.js
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_RSASSA-PKCS1-v1_5.worker.js b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_RSASSA-PKCS1-v1_5.https.worker.js
index 4df0b896fe3..4df0b896fe3 100644
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_RSASSA-PKCS1-v1_5.worker.js
+++ b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/failures_RSASSA-PKCS1-v1_5.https.worker.js
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes.worker.js b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes.worker.js
deleted file mode 100644
index 52e34946ef0..00000000000
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes.worker.js
+++ /dev/null
@@ -1,6 +0,0 @@
-importScripts("/resources/testharness.js");
-importScripts("../util/helpers.js");
-importScripts("successes.js");
-
-run_test();
-done();
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_AES-CBC.worker.js b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_AES-CBC.https.worker.js
index 0710c9e7b50..0710c9e7b50 100644
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_AES-CBC.worker.js
+++ b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_AES-CBC.https.worker.js
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_AES-CTR.worker.js b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_AES-CTR.https.worker.js
index 51529f000fd..51529f000fd 100644
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_AES-CTR.worker.js
+++ b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_AES-CTR.https.worker.js
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_AES-GCM.worker.js b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_AES-GCM.https.worker.js
index 1f6a1bc96e0..1f6a1bc96e0 100644
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_AES-GCM.worker.js
+++ b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_AES-GCM.https.worker.js
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_AES-KW.worker.js b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_AES-KW.https.worker.js
index 058cf83d057..058cf83d057 100644
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_AES-KW.worker.js
+++ b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_AES-KW.https.worker.js
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_ECDH.worker.js b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_ECDH.https.worker.js
index a21b7d04e8b..a21b7d04e8b 100644
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_ECDH.worker.js
+++ b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_ECDH.https.worker.js
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_ECDSA.worker.js b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_ECDSA.https.worker.js
index 13f7e3539ec..13f7e3539ec 100644
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_ECDSA.worker.js
+++ b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_ECDSA.https.worker.js
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_HMAC.worker.js b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_HMAC.https.worker.js
index 2b50b909058..2b50b909058 100644
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_HMAC.worker.js
+++ b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_HMAC.https.worker.js
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_RSA-OAEP.worker.js b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_RSA-OAEP.https.worker.js
index 4b3538da689..4b3538da689 100644
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_RSA-OAEP.worker.js
+++ b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_RSA-OAEP.https.worker.js
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_RSA-PSS.worker.js b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_RSA-PSS.https.worker.js
index 52364f5c7f5..52364f5c7f5 100644
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_RSA-PSS.worker.js
+++ b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_RSA-PSS.https.worker.js
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.worker.js b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.https.worker.js
index 4c6a02a98c6..4c6a02a98c6 100644
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.worker.js
+++ b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.https.worker.js
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/test_failures.https.html b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/test_failures.https.html
deleted file mode 100644
index 14e57b25cf2..00000000000
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/test_failures.https.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<meta name="timeout" content="long">
-<title>WebCryptoAPI: generateKey() for Failures</title>
-<link rel="author" title="Charles Engelke" href="mailto:w3c@engelke.com">
-<link rel="help" href="https://www.w3.org/TR/WebCryptoAPI/#dfn-SubtleCrypto-method-generateKey">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-
-<script src="/WebCryptoAPI/util/helpers.js"></script>
-<script src="failures.js"></script>
-
-<h1>generateKey Tests for Bad Parameters</h1>
-
-<div id="log"></div>
-<script>
-run_test();
-</script>
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/test_successes_RSA-OAEP.https.html b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/test_successes_RSA-OAEP.https.html
index 48136260390..db58fd6690a 100644
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/test_successes_RSA-OAEP.https.html
+++ b/tests/wpt/web-platform-tests/WebCryptoAPI/generateKey/test_successes_RSA-OAEP.https.html
@@ -19,5 +19,5 @@
<div id="log"></div>
<script>
-run_test(["RSA-OAEP"], true);
-</script>
+run_test(["RSA-OAEP"]);
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/idlharness.html b/tests/wpt/web-platform-tests/WebCryptoAPI/idlharness.html
index 81e1e04f9c1..53faef26d4d 100644
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/idlharness.html
+++ b/tests/wpt/web-platform-tests/WebCryptoAPI/idlharness.html
@@ -29,11 +29,6 @@ setup(function() {
request.onload = function() {
var idls = request.responseText;
- idl_array.add_untested_idls("[PrimaryGlobal] interface Window { };");
-
- idl_array.add_untested_idls("interface ArrayBuffer {};");
- idl_array.add_untested_idls("interface ArrayBufferView {};");
-
idl_array.add_idls(idls);
idl_array.add_objects({"Crypto":["crypto"], "SubtleCrypto":["crypto.subtle"]});
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/idlharness.https.html b/tests/wpt/web-platform-tests/WebCryptoAPI/idlharness.https.html
index 81e1e04f9c1..53faef26d4d 100644
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/idlharness.https.html
+++ b/tests/wpt/web-platform-tests/WebCryptoAPI/idlharness.https.html
@@ -29,11 +29,6 @@ setup(function() {
request.onload = function() {
var idls = request.responseText;
- idl_array.add_untested_idls("[PrimaryGlobal] interface Window { };");
-
- idl_array.add_untested_idls("interface ArrayBuffer {};");
- idl_array.add_untested_idls("interface ArrayBufferView {};");
-
idl_array.add_idls(idls);
idl_array.add_objects({"Crypto":["crypto"], "SubtleCrypto":["crypto.subtle"]});
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/tools/generate.py b/tests/wpt/web-platform-tests/WebCryptoAPI/tools/generate.py
index 8e06f00054d..728f914bdb2 100644
--- a/tests/wpt/web-platform-tests/WebCryptoAPI/tools/generate.py
+++ b/tests/wpt/web-platform-tests/WebCryptoAPI/tools/generate.py
@@ -66,10 +66,10 @@ done();"""
names = ["AES-CTR", "AES-CBC", "AES-GCM", "AES-KW", "HMAC", "RSASSA-PKCS1-v1_5",
"RSA-PSS", "RSA-OAEP", "ECDSA", "ECDH"]
-for filename_pattern, template in [("test_successes_%s.html", successes_html),
- ("test_failures_%s.html", failures_html),
- ("successes_%s.worker.js", successes_worker),
- ("failures_%s.worker.js", failures_worker)]:
+for filename_pattern, template in [("test_successes_%s.https.html", successes_html),
+ ("test_failures_%s.https.html", failures_html),
+ ("successes_%s.https.worker.js", successes_worker),
+ ("failures_%s.https.worker.js", failures_worker)]:
for name in names:
path = os.path.join(here, os.pardir, "generateKey", filename_pattern % name)
with open(path, "w") as f:
diff --git a/tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/no-regexp-special-casing.any.js b/tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/no-regexp-special-casing.any.js
new file mode 100644
index 00000000000..4446dbf69c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/no-regexp-special-casing.any.js
@@ -0,0 +1,47 @@
+"use strict";
+// RegExps used to be special-cased in Web IDL, but that was removed in
+// https://github.com/heycam/webidl/commit/bbb2bde. These tests check that implementations no longer
+// do any such special-casing.
+
+test(() => {
+ const regExp = new RegExp();
+ regExp.message = "some message";
+
+ const errorEvent = new ErrorEvent("type", regExp);
+
+ assert_equals(errorEvent.message, "some message");
+}, "Conversion to a dictionary works");
+
+test(() => {
+ const messageChannel = new MessageChannel();
+ const regExp = new RegExp();
+ regExp[Symbol.iterator] = function* () {
+ yield messageChannel.port1;
+ };
+
+ const messageEvent = new MessageEvent("type", { ports: regExp });
+
+ assert_array_equals(messageEvent.ports, [messageChannel.port1]);
+}, "Conversion to a sequence works");
+
+promise_test(async () => {
+ const regExp = new RegExp();
+
+ const response = new Response(regExp);
+
+ assert_equals(await response.text(), "/(?:)/");
+}, "Can convert a RegExp to a USVString");
+
+test(() => {
+ let functionCalled = false;
+
+ const regExp = new RegExp();
+ regExp.handleEvent = () => {
+ functionCalled = true;
+ };
+
+ self.addEventListener("testevent", regExp);
+ self.dispatchEvent(new Event("testevent"));
+
+ assert_true(functionCalled);
+}, "Can be used as an object implementing a callback interface");
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-network-error-sync-events.sub.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-network-error-sync-events.sub.htm
index 0ae94069858..b89958060f3 100644
--- a/tests/wpt/web-platform-tests/XMLHttpRequest/send-network-error-sync-events.sub.htm
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-network-error-sync-events.sub.htm
@@ -17,7 +17,7 @@
{
var xhr = new XMLHttpRequest();
- xhr.open("POST", "http://nonexistent-origin.{{host}}}:{{ports[http][0]}}", false);
+ xhr.open("POST", "http://nonexistent-origin.{{host}}:{{ports[http][0]}}", false);
assert_throws("NetworkError", function()
{
@@ -25,6 +25,12 @@
});
assert_equals(xhr.readyState, 4)
+ }, "http URL");
+
+ test(function()
+ {
+ var xhr = new XMLHttpRequest();
+
xhr.open("GET", "data:text/html;charset=utf-8;base64,PT0NUWVBFIGh0bWw%2BDQo8", false);
assert_throws("NetworkError", function()
@@ -33,7 +39,7 @@
});
assert_equals(xhr.readyState, 4)
- });
+ }, "data URL");
</script>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-post-upload.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-post-upload.htm
index 37a90d42cbd..5c1c6387adb 100644
--- a/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-post-upload.htm
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-post-upload.htm
@@ -15,8 +15,8 @@
<div id="log"></div>
<script type="text/javascript">
- function testRedirectPost(code, shouldResendPost) {
- var test = async_test(document.title + " (" + code + ")");
+ function testRedirectPost(params) {
+ var test = async_test(document.title + " (" + params.name + ")");
var actual = [];
// We check upload.onprogress with a boolean because it *might* fire more than once
var progressFiredReadyState1 = false;
@@ -24,13 +24,13 @@
var expectedHeaders, expectedEvents;
// 307 redirects should resend the POST data, and events and headers will be a little different..
- if(shouldResendPost) {
+ if(params.expectResendPost) {
expectedHeaders = {
- "X-Request-Content-Length": "11988",
+ "X-Request-Content-Length": "12000",
"X-Request-Content-Type": "text/plain;charset=UTF-8",
"X-Request-Method": "POST",
"X-Request-Query": "NO",
- "Content-Length": "11988"
+ "Content-Length": "12000"
}
expectedEvents = [
"xhr onreadystatechange 1",
@@ -63,6 +63,10 @@
"xhr loadend 4"
];
}
+ // Override expectations if provided.
+ if(params.expectedContentType)
+ expectedHeaders["X-Request-Content-Type"] = params.expectedContentType;
+
test.step(function()
{
var xhr = new XMLHttpRequest();
@@ -105,20 +109,24 @@
}
assert_array_equals(actual, expectedEvents, "events firing in expected order and states");
+ if (params.expectedBody)
+ assert_equals(xhr.response, params.expectedBody, 'request body was resent');
test.done();
});
- xhr.open("POST", "./resources/redirect.py?location=content.py&code=" + code, true);
- xhr.send((new Array(1000)).join("Test Message"));
+ xhr.open("POST", "./resources/redirect.py?location=content.py&code=" + params.code, true);
+ xhr.send(params.body);
});
}
+ const stringBody = "Test Message".repeat(1000);
+ const blobBody = new Blob(new Array(1000).fill("Test Message"));
- testRedirectPost(301, false);
- testRedirectPost(302, false);
- testRedirectPost(303, false);
- testRedirectPost(307, true);
-
+ testRedirectPost({name: "301", code: 301, expectResendPost: false, body: stringBody});
+ testRedirectPost({name: "302", code: 302, expectResendPost: false, body: stringBody});
+ testRedirectPost({name: "303", code: 303, expectResendPost: false, body: stringBody});
+ testRedirectPost({name: "307 (string)", code: 307, expectResendPost: true, body: stringBody, expectedBody: stringBody });
+ testRedirectPost({name: "307 (blob)", code: 307, expectResendPost: true, body: blobBody, expectedBody: stringBody, expectedContentType: "NO" });
</script>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/accelerometer/Accelerometer-disabled-by-feature-policy.https.html b/tests/wpt/web-platform-tests/accelerometer/Accelerometer-disabled-by-feature-policy.https.html
new file mode 100644
index 00000000000..d849db13359
--- /dev/null
+++ b/tests/wpt/web-platform-tests/accelerometer/Accelerometer-disabled-by-feature-policy.https.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_disabled(Accelerometer);
+run_fp_tests_disabled(LinearAccelerationSensor);
+run_fp_tests_disabled(GravitySensor);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/accelerometer/Accelerometer-disabled-by-feature-policy.https.html.headers b/tests/wpt/web-platform-tests/accelerometer/Accelerometer-disabled-by-feature-policy.https.html.headers
new file mode 100644
index 00000000000..beea0422d92
--- /dev/null
+++ b/tests/wpt/web-platform-tests/accelerometer/Accelerometer-disabled-by-feature-policy.https.html.headers
@@ -0,0 +1 @@
+Feature-Policy: accelerometer 'none'
diff --git a/tests/wpt/web-platform-tests/accelerometer/Accelerometer-enabled-by-feature-policy-attribute-redirect-on-load.https.html b/tests/wpt/web-platform-tests/accelerometer/Accelerometer-enabled-by-feature-policy-attribute-redirect-on-load.https.html
new file mode 100644
index 00000000000..7306ed58ce6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/accelerometer/Accelerometer-enabled-by-feature-policy-attribute-redirect-on-load.https.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled_by_attribute_redirect_on_load(Accelerometer);
+run_fp_tests_enabled_by_attribute_redirect_on_load(LinearAccelerationSensor);
+run_fp_tests_enabled_by_attribute_redirect_on_load(GravitySensor);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/accelerometer/Accelerometer-enabled-by-feature-policy-attribute.https.html b/tests/wpt/web-platform-tests/accelerometer/Accelerometer-enabled-by-feature-policy-attribute.https.html
new file mode 100644
index 00000000000..1ee0f42a510
--- /dev/null
+++ b/tests/wpt/web-platform-tests/accelerometer/Accelerometer-enabled-by-feature-policy-attribute.https.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled_by_attribute(Accelerometer);
+run_fp_tests_enabled_by_attribute(LinearAccelerationSensor);
+run_fp_tests_enabled_by_attribute(GravitySensor);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/accelerometer/Accelerometer-enabled-by-feature-policy.https.html b/tests/wpt/web-platform-tests/accelerometer/Accelerometer-enabled-by-feature-policy.https.html
new file mode 100644
index 00000000000..6dc33c829ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/accelerometer/Accelerometer-enabled-by-feature-policy.https.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled(Accelerometer);
+run_fp_tests_enabled(LinearAccelerationSensor);
+run_fp_tests_enabled(GravitySensor);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/accelerometer/Accelerometer-enabled-by-feature-policy.https.html.headers b/tests/wpt/web-platform-tests/accelerometer/Accelerometer-enabled-by-feature-policy.https.html.headers
new file mode 100644
index 00000000000..5df2754abf5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/accelerometer/Accelerometer-enabled-by-feature-policy.https.html.headers
@@ -0,0 +1 @@
+Feature-Policy: accelerometer *
diff --git a/tests/wpt/web-platform-tests/accelerometer/Accelerometer-enabled-on-self-origin-by-feature-policy.https.html b/tests/wpt/web-platform-tests/accelerometer/Accelerometer-enabled-on-self-origin-by-feature-policy.https.html
new file mode 100644
index 00000000000..fddbca0f5bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/accelerometer/Accelerometer-enabled-on-self-origin-by-feature-policy.https.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled_on_self_origin(Accelerometer);
+run_fp_tests_enabled_on_self_origin(LinearAccelerationSensor);
+run_fp_tests_enabled_on_self_origin(GravitySensor);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/accelerometer/Accelerometer-enabled-on-self-origin-by-feature-policy.https.html.headers b/tests/wpt/web-platform-tests/accelerometer/Accelerometer-enabled-on-self-origin-by-feature-policy.https.html.headers
new file mode 100644
index 00000000000..cdefed843e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/accelerometer/Accelerometer-enabled-on-self-origin-by-feature-policy.https.html.headers
@@ -0,0 +1 @@
+Feature-Policy: accelerometer 'self'
diff --git a/tests/wpt/web-platform-tests/accelerometer/Accelerometer.https.html b/tests/wpt/web-platform-tests/accelerometer/Accelerometer.https.html
index 58355571797..2a9bc543cdf 100644
--- a/tests/wpt/web-platform-tests/accelerometer/Accelerometer.https.html
+++ b/tests/wpt/web-platform-tests/accelerometer/Accelerometer.https.html
@@ -10,5 +10,6 @@
<script>
runGenericSensorTests(Accelerometer);
+runGenericSensorTests(GravitySensor);
</script>
diff --git a/tests/wpt/web-platform-tests/accelerometer/Accelerometer_insecure_context.html b/tests/wpt/web-platform-tests/accelerometer/Accelerometer_insecure_context.html
index d55a62f18e7..96eeef2daf7 100644
--- a/tests/wpt/web-platform-tests/accelerometer/Accelerometer_insecure_context.html
+++ b/tests/wpt/web-platform-tests/accelerometer/Accelerometer_insecure_context.html
@@ -16,5 +16,6 @@
<script>
runGenericSensorInsecureContext("Accelerometer");
+runGenericSensorInsecureContext("GravitySensor");
</script>
diff --git a/tests/wpt/web-platform-tests/accelerometer/Accelerometer_onerror-manual.https.html b/tests/wpt/web-platform-tests/accelerometer/Accelerometer_onerror-manual.https.html
index a3e81500122..8778693ccb2 100644
--- a/tests/wpt/web-platform-tests/accelerometer/Accelerometer_onerror-manual.https.html
+++ b/tests/wpt/web-platform-tests/accelerometer/Accelerometer_onerror-manual.https.html
@@ -16,5 +16,6 @@
<script>
runGenericSensorOnerror(Accelerometer);
+runGenericSensorOnerror(GravitySensor);
</script>
diff --git a/tests/wpt/web-platform-tests/acid/acid3/test.html b/tests/wpt/web-platform-tests/acid/acid3/test.html
index d2f08405af5..1ac8da6838e 100644
--- a/tests/wpt/web-platform-tests/acid/acid3/test.html
+++ b/tests/wpt/web-platform-tests/acid/acid3/test.html
@@ -956,8 +956,8 @@
test('di<v', "http://example.com/", 5);
test('-div', "http://example.com/", 5);
test('.div', "http://example.com/", 5);
- test(':div', null, 14);
- test(':div', "http://example.com/", 14);
+ //test(':div', null, 14);
+ //test(':div', "http://example.com/", 14);
test('d:iv', null, 14);
test('xml:test', "http://example.com/", 14);
test('xmlns:test', "http://example.com/", 14); // (technically a DOM3 Core test)
@@ -978,10 +978,10 @@
document.implementation.createDocumentType('a:', '', ''); /* doesn't contain an illegal character; is malformed */
message = "failed to raise exception";
} catch (e) {
- if (e.code != e.NAMESPACE_ERR)
+ /*if (e.code != e.NAMESPACE_ERR)
message = "wrong exception";
else if (e.INVALID_ACCESS_ERR != 15)
- message = "exceptions don't have all the constants";
+ message = "exceptions don't have all the constants";*/
}
if (message)
fail(message);
@@ -1257,7 +1257,7 @@
var p1 = doc.createElement("p");
doc.body.appendChild(doc.createTextNode(" TEST "));
doc.body.appendChild(p1);
- expect(doc.documentElement, notFirst, "root element, with no parent node, claims to be a :first-child");
+ //expect(doc.documentElement, notFirst, "root element, with no parent node, claims to be a :first-child");
expect(doc.documentElement.firstChild, first, "first child of root node didn't match :first-child");
expect(doc.documentElement.firstChild.firstChild, first, "failure 3");
expect(doc.body, notFirst, "failure 4");
diff --git a/tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-disabled-by-feature-policy.https.html b/tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-disabled-by-feature-policy.https.html
new file mode 100644
index 00000000000..278f520fe22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-disabled-by-feature-policy.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_disabled(AmbientLightSensor);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-disabled-by-feature-policy.https.html.headers b/tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-disabled-by-feature-policy.https.html.headers
new file mode 100644
index 00000000000..b8073a87be0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-disabled-by-feature-policy.https.html.headers
@@ -0,0 +1 @@
+Feature-Policy: ambient-light-sensor 'none'
diff --git a/tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html b/tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html
new file mode 100644
index 00000000000..f5d4b0fdde8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled_by_attribute_redirect_on_load(AmbientLightSensor);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-enabled-by-feature-policy-attribute.https.html b/tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-enabled-by-feature-policy-attribute.https.html
new file mode 100644
index 00000000000..13de3f8b4ee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-enabled-by-feature-policy-attribute.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled_by_attribute(AmbientLightSensor);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-enabled-by-feature-policy.https.html b/tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-enabled-by-feature-policy.https.html
new file mode 100644
index 00000000000..f2c2c3bbae1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-enabled-by-feature-policy.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled(AmbientLightSensor);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-enabled-by-feature-policy.https.html.headers b/tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-enabled-by-feature-policy.https.html.headers
new file mode 100644
index 00000000000..f037f3ff579
--- /dev/null
+++ b/tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-enabled-by-feature-policy.https.html.headers
@@ -0,0 +1 @@
+Feature-Policy: ambient-light-sensor *
diff --git a/tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-enabled-on-self-origin-by-feature-policy.https.html b/tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-enabled-on-self-origin-by-feature-policy.https.html
new file mode 100644
index 00000000000..33d36cb44e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-enabled-on-self-origin-by-feature-policy.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled_on_self_origin(AmbientLightSensor);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-enabled-on-self-origin-by-feature-policy.https.html.headers b/tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-enabled-on-self-origin-by-feature-policy.https.html.headers
new file mode 100644
index 00000000000..1d22667050e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/ambient-light/AmbientLightSensor-enabled-on-self-origin-by-feature-policy.https.html.headers
@@ -0,0 +1 @@
+Feature-Policy: ambient-light-sensor 'self'
diff --git a/tests/wpt/web-platform-tests/beacon/OWNERS b/tests/wpt/web-platform-tests/beacon/OWNERS
new file mode 100644
index 00000000000..719eb69cf52
--- /dev/null
+++ b/tests/wpt/web-platform-tests/beacon/OWNERS
@@ -0,0 +1,2 @@
+@toddreifsteck
+@igrigorik
diff --git a/tests/wpt/web-platform-tests/bluetooth/README.md b/tests/wpt/web-platform-tests/bluetooth/README.md
new file mode 100644
index 00000000000..593967ee089
--- /dev/null
+++ b/tests/wpt/web-platform-tests/bluetooth/README.md
@@ -0,0 +1,12 @@
+# Web Bluetooth Testing
+
+Web Bluetooth testing relies on the [Web Bluetooth Testing API] which must be
+provided by browsers under test.
+
+In this test suite `resources/bluetooth-helpers.js` detects and triggers
+the API to be loaded as needed.
+
+The Chromium implementation is provided by
+`../resources/chromium/web-bluetooth-test.js`.
+
+[Web Bluetooth Testing API]: https://docs.google.com/document/d/1Nhv_oVDCodd1pEH_jj9k8gF4rPGb_84VYaZ9IG8M_WY/
diff --git a/tests/wpt/web-platform-tests/bluetooth/idl-Bluetooth.html b/tests/wpt/web-platform-tests/bluetooth/idl/idl-Bluetooth.html
index b0263f980a8..b0263f980a8 100644
--- a/tests/wpt/web-platform-tests/bluetooth/idl-Bluetooth.html
+++ b/tests/wpt/web-platform-tests/bluetooth/idl/idl-Bluetooth.html
diff --git a/tests/wpt/web-platform-tests/bluetooth/idl/idl-BluetoothUUID.html b/tests/wpt/web-platform-tests/bluetooth/idl/idl-BluetoothUUID.html
new file mode 100644
index 00000000000..efebb15cb25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/bluetooth/idl/idl-BluetoothUUID.html
@@ -0,0 +1,166 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+'use strict'
+
+var base_uuid = '00000000-0000-1000-8000-00805f9b34fb'
+
+test(() => {
+ let base_alias = 0x0
+ assert_equals(BluetoothUUID.getService(base_alias), base_uuid);
+ assert_equals(BluetoothUUID.getCharacteristic(base_alias), base_uuid);
+ assert_equals(BluetoothUUID.getDescriptor(base_alias), base_uuid);
+}, '0x0 should produce valid UUID.');
+
+test(() => {
+ assert_equals(BluetoothUUID.getService(NaN), base_uuid);
+ assert_equals(BluetoothUUID.getCharacteristic(NaN), base_uuid);
+ assert_equals(BluetoothUUID.getDescriptor(NaN), base_uuid);
+}, 'NaN returns basic uuid');
+
+test(() => {
+ let max_uuid = 'ffffffff-0000-1000-8000-00805f9b34fb';
+ let nine_digits = 0xfffffffff;
+ let thirteen_digits = 0xfffffffffffff;
+ let fourteen_digits = 0xffffffffffffff;
+ assert_equals(BluetoothUUID.getService(nine_digits), max_uuid);
+ assert_equals(BluetoothUUID.getCharacteristic(nine_digits), max_uuid);
+ assert_equals(BluetoothUUID.getDescriptor(nine_digits), max_uuid);
+ assert_equals(BluetoothUUID.getService(thirteen_digits), max_uuid);
+ assert_equals(BluetoothUUID.getCharacteristic(thirteen_digits), max_uuid);
+ assert_equals(BluetoothUUID.getDescriptor(thirteen_digits), max_uuid);
+ assert_equals(BluetoothUUID.getService(fourteen_digits), base_uuid);
+ assert_equals(BluetoothUUID.getCharacteristic(fourteen_digits), base_uuid);
+ assert_equals(BluetoothUUID.getDescriptor(fourteen_digits), base_uuid);
+}, 'Values between 0xfffffffff (8 digits) and 0xffffffffffffff (14 digits)' +
+ 'should return max UUID');
+
+test(() => {
+ assert_equals(BluetoothUUID.getService(Infinity), base_uuid);
+ assert_equals(BluetoothUUID.getCharacteristic(Infinity), base_uuid);
+ assert_equals(BluetoothUUID.getDescriptor(Infinity), base_uuid);
+}, 'Infinity returns base UUID');
+
+test(() => {
+ let deadbeef_alias = 0xDEADBEEF;
+ let deadbeef_uuid = 'deadbeef-0000-1000-8000-00805f9b34fb';
+ assert_equals(BluetoothUUID.getService(deadbeef_alias), deadbeef_uuid);
+ assert_equals(BluetoothUUID.getCharacteristic(deadbeef_alias), deadbeef_uuid);
+ assert_equals(BluetoothUUID.getDescriptor(deadbeef_alias), deadbeef_uuid);
+}, '0xdeadbeef should produce valid UUID.');
+
+test(() => {
+ let adeadbeef_alias = 0xADEADBEEF;
+ let adeadbeef_uuid = 'deadbeef-0000-1000-8000-00805f9b34fb';
+ assert_equals(BluetoothUUID.getService(adeadbeef_alias), adeadbeef_uuid);
+ assert_equals(BluetoothUUID.getCharacteristic(adeadbeef_alias), adeadbeef_uuid);
+ assert_equals(BluetoothUUID.getDescriptor(adeadbeef_alias), adeadbeef_uuid);
+}, 'Only first 32bits should be used.');
+
+test(() => {
+ let basic_uuid = '1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d';
+ assert_equals(BluetoothUUID.getService(basic_uuid), basic_uuid);
+ assert_equals(BluetoothUUID.getCharacteristic(basic_uuid), basic_uuid);
+ assert_equals(BluetoothUUID.getDescriptor(basic_uuid), basic_uuid);
+}, 'A valid UUID String should return the same UUID.');
+
+test(() => {
+ let all_caps_uuid = '1A2B3C4D-5E6F-7A8B-9C0D-1E2F3A4B5C6D';
+ assert_throws(TypeError(), () => BluetoothUUID.getService(all_caps_uuid));
+ assert_throws(TypeError(), () => BluetoothUUID.getCharacteristic(all_caps_uuid));
+ assert_throws(TypeError(), () => BluetoothUUID.getDescriptor(all_caps_uuid));
+}, 'A UUID String with uppercase letters is an invalid UUID.');
+
+test(() => {
+ let string_alias = 'deadbeef';
+ assert_throws(TypeError(), () => BluetoothUUID.getService(string_alias));
+ assert_throws(TypeError(), () => BluetoothUUID.getCharacteristic(string_alias));
+ assert_throws(TypeError(), () => BluetoothUUID.getDescriptor(string_alias));
+}, 'A 32bit *String* alias is invalid.');
+
+test(() => {
+ let invalid_character_uuid = '0000000g-0000-1000-8000-00805f9b34fb';
+ assert_throws(TypeError(), () => BluetoothUUID.getService(invalid_character_uuid));
+ assert_throws(TypeError(), () => BluetoothUUID.getCharacteristic(invalid_character_uuid));
+ assert_throws(TypeError(), () => BluetoothUUID.getDescriptor(invalid_character_uuid));
+}, 'A UUID with invalid characters is an invalid UUID.');
+
+test(() => {
+ assert_equals(BluetoothUUID.getService('alert_notification'),
+ '00001811-0000-1000-8000-00805f9b34fb');
+ assert_equals(BluetoothUUID.getCharacteristic('aerobic_heart_rate_lower_limit'),
+ '00002a7e-0000-1000-8000-00805f9b34fb');
+ assert_equals(BluetoothUUID.getDescriptor('gatt.characteristic_extended_properties'),
+ '00002900-0000-1000-8000-00805f9b34fb');
+}, 'A valid UUID from a name.');
+
+test(() => {
+ assert_throws(TypeError(), () => {
+ BluetoothUUID.getService('aerobic_heart_rate_lower_limit');
+ });
+ assert_throws(TypeError(), () => {
+ BluetoothUUID.getService('gatt.characteristic_extended_properties');
+ });
+ assert_throws(TypeError(), () => {
+ BluetoothUUID.getCharacteristic('alert_notification');
+ });
+ assert_throws(TypeError(), () => {
+ BluetoothUUID.getCharacteristic('gatt.characteristic_extended_properties');
+ });
+ assert_throws(TypeError(), () => {
+ BluetoothUUID.getDescriptor('alert_notification');
+ });
+ assert_throws(TypeError(), () => {
+ BluetoothUUID.getDescriptor('aerobic_heart_rate_lower_limit');
+ });
+}, 'Make sure attributes don\'t share a map');
+
+test(() => {
+ let wrong_name = 'wrong_name';
+ assert_throws(TypeError(), () => BluetoothUUID.getService(wrong_name));
+ assert_throws(TypeError(), () => BluetoothUUID.getCharacteristic(wrong_name));
+ assert_throws(TypeError(), () => BluetoothUUID.getDescriptor(wrong_name));
+}, 'Invalid Descriptor name');
+
+test(() => {
+ let object = {};
+ let array = [];
+ let func = () => {};
+
+ // cannonicalUUID
+ assert_throws(new TypeError, () => BluetoothUUID.canonicalUUID(object));
+ // [] converts to '', which converts to 0 before the range check.
+ assert_equals(BluetoothUUID.canonicalUUID(array), base_uuid);
+ assert_throws(new TypeError, () => BluetoothUUID.canonicalUUID(func));
+ assert_throws(new TypeError, () => BluetoothUUID.canonicalUUID(undefined));
+ assert_equals(BluetoothUUID.canonicalUUID(null), base_uuid);
+ assert_equals(BluetoothUUID.canonicalUUID(false), base_uuid);
+ assert_equals(BluetoothUUID.canonicalUUID(true), BluetoothUUID.canonicalUUID(1));
+ assert_throws(new TypeError, () => BluetoothUUID.canonicalUUID(NaN));
+
+ // getService
+ assert_throws(TypeError(), () => BluetoothUUID.getService(object));
+ assert_throws(TypeError(), () => BluetoothUUID.getService(array));
+ assert_throws(TypeError(), () => BluetoothUUID.getService(func));
+ assert_throws(TypeError(), () => BluetoothUUID.getService(undefined));
+ assert_throws(TypeError(), () => BluetoothUUID.getService(null));
+ assert_throws(TypeError(), () => BluetoothUUID.getService(false));
+
+ // getCharacteristic
+ assert_throws(TypeError(), () => BluetoothUUID.getCharacteristic(object));
+ assert_throws(TypeError(), () => BluetoothUUID.getCharacteristic(array));
+ assert_throws(TypeError(), () => BluetoothUUID.getCharacteristic(func));
+ assert_throws(TypeError(), () => BluetoothUUID.getCharacteristic(undefined));
+ assert_throws(TypeError(), () => BluetoothUUID.getCharacteristic(null));
+ assert_throws(TypeError(), () => BluetoothUUID.getCharacteristic(false));
+
+ // getDescriptor
+ assert_throws(TypeError(), () => BluetoothUUID.getDescriptor(object));
+ assert_throws(TypeError(), () => BluetoothUUID.getDescriptor(array));
+ assert_throws(TypeError(), () => BluetoothUUID.getDescriptor(func));
+ assert_throws(TypeError(), () => BluetoothUUID.getDescriptor(undefined));
+ assert_throws(TypeError(), () => BluetoothUUID.getDescriptor(null));
+ assert_throws(TypeError(), () => BluetoothUUID.getDescriptor(false));
+}, 'Non-number and non-strings');
+</script>
diff --git a/tests/wpt/web-platform-tests/bluetooth/idl/idl-NavigatorBluetooth.html b/tests/wpt/web-platform-tests/bluetooth/idl/idl-NavigatorBluetooth.html
new file mode 100644
index 00000000000..9449cf1ec88
--- /dev/null
+++ b/tests/wpt/web-platform-tests/bluetooth/idl/idl-NavigatorBluetooth.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+'use strict';
+
+test(() => {
+ assert_true('bluetooth' in navigator,
+ 'navigator.bluetooth exists.');
+}, 'navigator.bluetooth IDL test');
+
+test(() => {
+ assert_equals(navigator.bluetooth, navigator.bluetooth);
+}, '[SameObject] test for navigator.bluetooth');
+</script>
diff --git a/tests/wpt/web-platform-tests/bluetooth/resources/bluetooth-helpers.js b/tests/wpt/web-platform-tests/bluetooth/resources/bluetooth-helpers.js
new file mode 100644
index 00000000000..3f3ff52189f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/bluetooth/resources/bluetooth-helpers.js
@@ -0,0 +1,800 @@
+'use strict';
+
+function loadScript(path) {
+ let script = document.createElement('script');
+ let promise = new Promise(resolve => script.onload = resolve);
+ script.src = path;
+ script.async = false;
+ document.head.appendChild(script);
+ return promise;
+}
+
+function loadScripts(paths) {
+ let chain = Promise.resolve();
+ for (let path of paths) {
+ chain = chain.then(() => loadScript(path));
+ }
+ return chain;
+}
+
+function performChromiumSetup() {
+ // Make sure we are actually on Chromium.
+ if (!Mojo) {
+ return;
+ }
+
+ // Load the Chromium-specific resources.
+ let prefix = '/resources/chromium';
+ let extra = [];
+ if (window.location.pathname.includes('/LayoutTests/')) {
+ let root = window.location.pathname.match(/.*LayoutTests/);
+ prefix = `${root}/external/wpt/resources/chromium`;
+ extra = [
+ `${root}/resources/bluetooth/bluetooth-fake-adapter.js`,
+ ];
+ } else if (window.location.pathname.startsWith('/bluetooth/https/')) {
+ extra = [
+ '/js-test-resources/bluetooth/bluetooth-fake-adapter.js',
+ ];
+ }
+ return loadScripts([
+ `${prefix}/mojo_bindings.js`,
+ `${prefix}/mojo_layouttest_test.mojom.js`,
+ `${prefix}/uuid.mojom.js`,
+ `${prefix}/fake_bluetooth.mojom.js`,
+ `${prefix}/web-bluetooth-test.js`,
+ ].concat(extra))
+ // Call setBluetoothFakeAdapter() to clean up any fake adapters left over
+ // by legacy tests.
+ // Legacy tests that use setBluetoothFakeAdapter() sometimes fail to clean
+ // their fake adapter. This is not a problem for these tests because the
+ // next setBluetoothFakeAdapter() will clean it up anyway but it is a
+ // problem for the new tests that do not use setBluetoothFakeAdapter().
+ // TODO(crbug.com/569709): Remove once setBluetoothFakeAdapter is no
+ // longer used.
+ .then(() => setBluetoothFakeAdapter ? setBluetoothFakeAdapter('')
+ : undefined);
+}
+
+
+// These tests rely on the User Agent providing an implementation of the
+// Web Bluetooth Testing API.
+// https://docs.google.com/document/d/1Nhv_oVDCodd1pEH_jj9k8gF4rPGb_84VYaZ9IG8M_WY/edit?ts=59b6d823#heading=h.7nki9mck5t64
+function bluetooth_test(func, name, properties) {
+ Promise.resolve()
+ .then(() => promise_test(t => Promise.resolve()
+ // Trigger Chromium-specific setup.
+ .then(performChromiumSetup)
+ .then(() => func(t)), name, properties));
+}
+
+// HCI Error Codes. Used for simulateGATT[Dis]ConnectionResponse.
+// For a complete list of possible error codes see
+// BT 4.2 Vol 2 Part D 1.3 List Of Error Codes.
+const HCI_SUCCESS = 0x0000;
+const HCI_CONNECTION_TIMEOUT = 0x0008;
+
+// GATT Error codes. Used for GATT operations responses.
+// BT 4.2 Vol 3 Part F 3.4.1.1 Error Response
+const GATT_SUCCESS = 0x0000;
+const GATT_INVALID_HANDLE = 0x0001;
+
+// Bluetooth UUID constants:
+// Services:
+var blocklist_test_service_uuid = "611c954a-263b-4f4a-aab6-01ddb953f985";
+var request_disconnection_service_uuid = "01d7d889-7451-419f-aeb8-d65e7b9277af";
+// Characteristics:
+var blocklist_exclude_reads_characteristic_uuid =
+ "bad1c9a2-9a5b-4015-8b60-1579bbbf2135";
+var request_disconnection_characteristic_uuid =
+ "01d7d88a-7451-419f-aeb8-d65e7b9277af";
+// Descriptors:
+var blocklist_test_descriptor_uuid = "bad2ddcf-60db-45cd-bef9-fd72b153cf7c";
+
+// Sometimes we need to test that using either the name, alias, or UUID
+// produces the same result. The following objects help us do that.
+var generic_access = {
+ alias: 0x1800,
+ name: 'generic_access',
+ uuid: '00001800-0000-1000-8000-00805f9b34fb'
+};
+var device_name = {
+ alias: 0x2a00,
+ name: 'gap.device_name',
+ uuid: '00002a00-0000-1000-8000-00805f9b34fb'
+};
+var reconnection_address = {
+ alias: 0x2a03,
+ name: 'gap.reconnection_address',
+ uuid: '00002a03-0000-1000-8000-00805f9b34fb'
+};
+var heart_rate = {
+ alias: 0x180d,
+ name: 'heart_rate',
+ uuid: '0000180d-0000-1000-8000-00805f9b34fb'
+};
+var health_thermometer = {
+ alias: 0x1809,
+ name: 'health_thermometer',
+ uuid: '00001809-0000-1000-8000-00805f9b34fb'
+};
+var body_sensor_location = {
+ alias: 0x2a38,
+ name: 'body_sensor_location',
+ uuid: '00002a38-0000-1000-8000-00805f9b34fb'
+};
+var glucose = {
+ alias: 0x1808,
+ name: 'glucose',
+ uuid: '00001808-0000-1000-8000-00805f9b34fb'
+};
+var battery_service = {
+ alias: 0x180f,
+ name: 'battery_service',
+ uuid: '0000180f-0000-1000-8000-00805f9b34fb'
+};
+var battery_level = {
+ alias: 0x2A19,
+ name: 'battery_level',
+ uuid: '00002a19-0000-1000-8000-00805f9b34fb'
+};
+var user_description = {
+ alias: 0x2901,
+ name: 'gatt.characteristic_user_description',
+ uuid: '00002901-0000-1000-8000-00805f9b34fb'
+};
+var client_characteristic_configuration = {
+ alias: 0x2902,
+ name: 'gatt.client_characteristic_configuration',
+ uuid: '00002902-0000-1000-8000-00805f9b34fb'
+};
+var measurement_interval = {
+ alias: 0x2a21,
+ name: 'measurement_interval',
+ uuid: '00002a21-0000-1000-8000-00805f9b34fb'
+};
+
+// The following tests make sure the Web Bluetooth implementation
+// responds correctly to the different types of errors the
+// underlying platform might return for GATT operations.
+
+// Each browser should map these characteristics to specific code paths
+// that result in different errors thus increasing code coverage
+// when testing. Therefore some of these characteristics might not be useful
+// for all browsers.
+//
+// TODO(ortuno): According to the testing spec errorUUID(0x101) to
+// errorUUID(0x1ff) should be use for the uuids of the characteristics.
+var gatt_errors_tests = [{
+ testName: 'GATT Error: Unknown.',
+ uuid: errorUUID(0xA1),
+ error: new DOMException(
+ 'GATT Error Unknown.',
+ 'NotSupportedError')
+}, {
+ testName: 'GATT Error: Failed.',
+ uuid: errorUUID(0xA2),
+ error: new DOMException(
+ 'GATT operation failed for unknown reason.',
+ 'NotSupportedError')
+}, {
+ testName: 'GATT Error: In Progress.',
+ uuid: errorUUID(0xA3),
+ error: new DOMException(
+ 'GATT operation already in progress.',
+ 'NetworkError')
+}, {
+ testName: 'GATT Error: Invalid Length.',
+ uuid: errorUUID(0xA4),
+ error: new DOMException(
+ 'GATT Error: invalid attribute length.',
+ 'InvalidModificationError')
+}, {
+ testName: 'GATT Error: Not Permitted.',
+ uuid: errorUUID(0xA5),
+ error: new DOMException(
+ 'GATT operation not permitted.',
+ 'NotSupportedError')
+}, {
+ testName: 'GATT Error: Not Authorized.',
+ uuid: errorUUID(0xA6),
+ error: new DOMException(
+ 'GATT operation not authorized.',
+ 'SecurityError')
+}, {
+ testName: 'GATT Error: Not Paired.',
+ uuid: errorUUID(0xA7),
+ // TODO(ortuno): Change to InsufficientAuthenticationError or similiar
+ // once https://github.com/WebBluetoothCG/web-bluetooth/issues/137 is
+ // resolved.
+ error: new DOMException(
+ 'GATT Error: Not paired.',
+ 'NetworkError')
+}, {
+ testName: 'GATT Error: Not Supported.',
+ uuid: errorUUID(0xA8),
+ error: new DOMException(
+ 'GATT Error: Not supported.',
+ 'NotSupportedError')
+}];
+
+function callWithTrustedClick(callback) {
+ return new Promise(resolve => {
+ let button = document.createElement('button');
+ button.textContent = 'click to continue test';
+ button.style.display = 'block';
+ button.style.fontSize = '20px';
+ button.style.padding = '10px';
+ button.onclick = () => {
+ document.body.removeChild(button);
+ resolve(callback());
+ };
+ document.body.appendChild(button);
+ test_driver.click(button);
+ });
+}
+
+// Calls requestDevice() in a context that's 'allowed to show a popup'.
+function requestDeviceWithTrustedClick() {
+ let args = arguments;
+ return callWithTrustedClick(
+ () => navigator.bluetooth.requestDevice.apply(navigator.bluetooth, args));
+}
+
+// errorUUID(alias) returns a UUID with the top 32 bits of
+// '00000000-97e5-4cd7-b9f1-f5a427670c59' replaced with the bits of |alias|.
+// For example, errorUUID(0xDEADBEEF) returns
+// 'deadbeef-97e5-4cd7-b9f1-f5a427670c59'. The bottom 96 bits of error UUIDs
+// were generated as a type 4 (random) UUID.
+function errorUUID(uuidAlias) {
+ // Make the number positive.
+ uuidAlias >>>= 0;
+ // Append the alias as a hex number.
+ var strAlias = '0000000' + uuidAlias.toString(16);
+ // Get last 8 digits of strAlias.
+ strAlias = strAlias.substr(-8);
+ // Append Base Error UUID
+ return strAlias + '-97e5-4cd7-b9f1-f5a427670c59';
+}
+
+// Function to test that a promise rejects with the expected error type and
+// message.
+function assert_promise_rejects_with_message(promise, expected, description) {
+ return promise.then(() => {
+ assert_unreached('Promise should have rejected: ' + description);
+ }, error => {
+ assert_equals(error.name, expected.name, 'Unexpected Error Name:');
+ if (expected.message) {
+ assert_equals(error.message, expected.message, 'Unexpected Error Message:');
+ }
+ });
+}
+
+function runGarbageCollection()
+{
+ // Run gc() as a promise.
+ return new Promise(
+ function(resolve, reject) {
+ GCController.collect();
+ step_timeout(resolve, 0);
+ });
+}
+
+function eventPromise(target, type, options) {
+ return new Promise(resolve => {
+ let wrapper = function(event) {
+ target.removeEventListener(type, wrapper);
+ resolve(event);
+ };
+ target.addEventListener(type, wrapper, options);
+ });
+}
+
+// Helper function to assert that events are fired and a promise resolved
+// in the correct order.
+// 'event' should be passed as |should_be_first| to indicate that the events
+// should be fired first, otherwise 'promiseresolved' should be passed.
+// Attaches |num_listeners| |event| listeners to |object|. If all events have
+// been fired and the promise resolved in the correct order, returns a promise
+// that fulfills with the result of |object|.|func()| and |event.target.value|
+// of each of event listeners. Otherwise throws an error.
+function assert_promise_event_order_(should_be_first, object, func, event, num_listeners) {
+ let order = [];
+ let event_promises = [];
+ for (let i = 0; i < num_listeners; i++) {
+ event_promises.push(new Promise(resolve => {
+ let event_listener = (e) => {
+ object.removeEventListener(event, event_listener);
+ order.push('event');
+ resolve(e.target.value);
+ };
+ object.addEventListener(event, event_listener);
+ }));
+ }
+
+ let func_promise = object[func]().then(result => {
+ order.push('promiseresolved');
+ return result;
+ });
+
+ return Promise.all([func_promise, ...event_promises])
+ .then((result) => {
+ if (should_be_first !== order[0]) {
+ throw should_be_first === 'promiseresolved' ?
+ `'${event}' was fired before promise resolved.` :
+ `Promise resolved before '${event}' was fired.`;
+ }
+
+ if (order[0] !== 'promiseresolved' &&
+ order[order.length - 1] !== 'promiseresolved') {
+ throw 'Promise resolved in between event listeners.';
+ }
+
+ return result;
+ });
+}
+
+// See assert_promise_event_order_ above.
+function assert_promise_resolves_before_event(
+ object, func, event, num_listeners=1) {
+ return assert_promise_event_order_(
+ 'promiseresolved', object, func, event, num_listeners);
+}
+
+// See assert_promise_event_order_ above.
+function assert_promise_resolves_after_event(
+ object, func, event, num_listeners=1) {
+ return assert_promise_event_order_(
+ 'event', object, func, event, num_listeners);
+}
+
+// Returns a promise that resolves after 100ms unless
+// the the event is fired on the object in which case
+// the promise rejects.
+function assert_no_events(object, event_name) {
+ return new Promise((resolve, reject) => {
+ let event_listener = (e) => {
+ object.removeEventListener(event_name, event_listener);
+ assert_unreached('Object should not fire an event.');
+ };
+ object.addEventListener(event_name, event_listener);
+ // TODO: Remove timeout.
+ // http://crbug.com/543884
+ step_timeout(() => {
+ object.removeEventListener(event_name, event_listener);
+ resolve();
+ }, 100);
+ });
+}
+
+class TestCharacteristicProperties {
+ // |properties| is an array of strings for property bits to be set
+ // as true.
+ constructor(properties) {
+ this.broadcast = false;
+ this.read = false;
+ this.writeWithoutResponse = false;
+ this.write = false;
+ this.notify = false;
+ this.indicate = false;
+ this.authenticatedSignedWrites = false;
+ this.reliableWrite = false;
+ this.writableAuxiliaries = false;
+
+ properties.forEach(val => {
+ if (this.hasOwnProperty(val))
+ this[val] = true;
+ else
+ throw `Invalid member '${val}'`;
+ });
+ }
+}
+
+function assert_properties_equal(properties, expected_properties) {
+ for (let key in expected_properties) {
+ assert_equals(properties[key], expected_properties[key]);
+ }
+}
+
+class EventCatcher {
+ constructor(object, event) {
+ this.eventFired = false;
+ let event_listener = () => {
+ object.removeEventListener(event, event_listener);
+ this.eventFired = true;
+ };
+ object.addEventListener(event, event_listener);
+ }
+}
+
+// Returns a function that when called returns a promise that resolves when
+// the device has disconnected. Example:
+// device.gatt.connect()
+// .then(gatt => get_request_disconnection(gatt))
+// .then(requestDisconnection => requestDisconnection())
+// .then(() => // device is now disconnected)
+function get_request_disconnection(gattServer) {
+ return gattServer.getPrimaryService(request_disconnection_service_uuid)
+ .then(service => service.getCharacteristic(request_disconnection_characteristic_uuid))
+ .then(characteristic => {
+ return () => assert_promise_rejects_with_message(
+ characteristic.writeValue(new Uint8Array([0])),
+ new DOMException(
+ 'GATT Server is disconnected. Cannot perform GATT operations. ' +
+ '(Re)connect first with `device.gatt.connect`.',
+ 'NetworkError'));
+ });
+}
+
+function generateRequestDeviceArgsWithServices(services = ['heart_rate']) {
+ return [{
+ filters: [{ services: services }]
+ }, {
+ filters: [{ services: services, name: 'Name' }]
+ }, {
+ filters: [{ services: services, namePrefix: 'Pre' }]
+ }, {
+ filters: [{ services: services, name: 'Name', namePrefix: 'Pre' }]
+ }, {
+ filters: [{ services: services }],
+ optionalServices: ['heart_rate']
+ }, {
+ filters: [{ services: services, name: 'Name' }],
+ optionalServices: ['heart_rate']
+ }, {
+ filters: [{ services: services, namePrefix: 'Pre' }],
+ optionalServices: ['heart_rate']
+ }, {
+ filters: [{ services: services, name: 'Name', namePrefix: 'Pre' }],
+ optionalServices: ['heart_rate']
+ }];
+}
+
+// Simulates a pre-connected device with |address|, |name| and
+// |knownServiceUUIDs|.
+function setUpPreconnectedDevice({
+ address = '00:00:00:00:00:00', name = 'LE Device', knownServiceUUIDs = []}) {
+ return navigator.bluetooth.test.simulateCentral({state: 'powered-on'})
+ .then(fake_central => fake_central.simulatePreconnectedPeripheral({
+ address: address,
+ name: name,
+ knownServiceUUIDs: knownServiceUUIDs,
+ }));
+}
+
+// Returns a FakePeripheral that corresponds to a simulated pre-connected device
+// called 'Health Thermometer'. The device has two known serviceUUIDs:
+// 'generic_access' and 'health_thermometer'.
+function setUpHealthThermometerDevice() {
+ return setUpPreconnectedDevice({
+ address: '09:09:09:09:09:09',
+ name: 'Health Thermometer',
+ knownServiceUUIDs: ['generic_access', 'health_thermometer'],
+ });
+}
+
+// Returns an array containing two FakePeripherals corresponding
+// to the simulated devices.
+function setUpHealthThermometerAndHeartRateDevices() {
+ return navigator.bluetooth.test.simulateCentral({state: 'powered-on'})
+ .then(fake_central => Promise.all([
+ fake_central.simulatePreconnectedPeripheral({
+ address: '09:09:09:09:09:09',
+ name: 'Health Thermometer',
+ knownServiceUUIDs: ['generic_access', 'health_thermometer'],
+ }),
+ fake_central.simulatePreconnectedPeripheral({
+ address: '08:08:08:08:08:08',
+ name: 'Heart Rate',
+ knownServiceUUIDs: ['generic_access', 'heart_rate'],
+ })]));
+}
+
+// Returns the same fake peripheral as setUpHealthThermometerDevice() except
+// that connecting to the peripheral will succeed.
+function setUpConnectableHealthThermometerDevice() {
+ let fake_peripheral;
+ return setUpHealthThermometerDevice()
+ .then(_ => fake_peripheral = _)
+ .then(() => fake_peripheral.setNextGATTConnectionResponse({
+ code: HCI_SUCCESS,
+ }))
+ .then(() => fake_peripheral);
+}
+
+// Returns an object containing a BluetoothDevice discovered using |options|,
+// its corresponding FakePeripheral and FakeRemoteGATTServices.
+// The simulated device is called 'Health Thermometer' it has two known service
+// UUIDs: 'generic_access' and 'health_thermometer' which correspond to two
+// services with the same UUIDs. The 'health thermometer' service contains three
+// characteristics:
+// - 'temperature_measurement' (indicate),
+// - 'temperature_type' (read),
+// - 'measurement_interval' (read, write, indicate)
+// The 'measurement_interval' characteristic contains a
+// 'gatt.client_characteristic_configuration' descriptor and a
+// 'characteristic_user_description' descriptor.
+// The device has been connected to and its attributes are ready to be
+// discovered.
+function getHealthThermometerDevice(options) {
+ let result;
+ return getConnectedHealthThermometerDevice(options)
+ .then(_ => result = _)
+ .then(() => result.fake_peripheral.setNextGATTDiscoveryResponse({
+ code: HCI_SUCCESS,
+ }))
+ .then(() => result);
+}
+
+// Similar to getHealthThermometerDevice except that the peripheral has
+// two 'health_thermometer' services.
+function getTwoHealthThermometerServicesDevice(options) {
+ let device;
+ let fake_peripheral;
+ let fake_generic_access;
+ let fake_health_thermometer1;
+ let fake_health_thermometer2;
+
+ return getConnectedHealthThermometerDevice(options)
+ .then(result => {
+ ({
+ device,
+ fake_peripheral,
+ fake_generic_access,
+ fake_health_thermometer: fake_health_thermometer1,
+ } = result);
+ })
+ .then(() => fake_peripheral.addFakeService({uuid: 'health_thermometer'}))
+ .then(s => fake_health_thermometer2 = s)
+ .then(() => fake_peripheral.setNextGATTDiscoveryResponse({
+ code: HCI_SUCCESS}))
+ .then(() => ({
+ device: device,
+ fake_peripheral: fake_peripheral,
+ fake_generic_access: fake_generic_access,
+ fake_health_thermometer1: fake_health_thermometer1,
+ fake_health_thermometer2: fake_health_thermometer2
+ }));
+}
+
+// Returns an object containing a Health Thermometer BluetoothRemoteGattService
+// and its corresponding FakeRemoteGATTService.
+function getHealthThermometerService() {
+ let result;
+ return getHealthThermometerDevice()
+ .then(r => result = r)
+ .then(() => result.device.gatt.getPrimaryService('health_thermometer'))
+ .then(service => Object.assign(result, {
+ service,
+ fake_service: result.fake_health_thermometer,
+ }));
+}
+
+// Returns an object containing a Measurement Interval
+// BluetoothRemoteGATTCharacteristic and its corresponding
+// FakeRemoteGATTCharacteristic.
+function getMeasurementIntervalCharacteristic() {
+ let result;
+ return getHealthThermometerService()
+ .then(r => result = r)
+ .then(() => result.service.getCharacteristic('measurement_interval'))
+ .then(characteristic => Object.assign(result, {
+ characteristic,
+ fake_characteristic: result.fake_measurement_interval,
+ }));
+}
+
+function getUserDescriptionDescriptor() {
+ let result;
+ return getMeasurementIntervalCharacteristic()
+ .then(r => result = r)
+ .then(() => result.characteristic.getDescriptor(
+ 'gatt.characteristic_user_description'))
+ .then(descriptor => Object.assign(result, {
+ descriptor,
+ fake_descriptor: result.fake_user_description,
+ }));
+}
+
+// Populates a fake_peripheral with various fakes appropriate for a health
+// thermometer. This resolves to an associative array composed of the fakes,
+// including the |fake_peripheral|.
+function populateHealthThermometerFakes(fake_peripheral) {
+ let fake_generic_access, fake_health_thermometer, fake_measurement_interval,
+ fake_user_description, fake_cccd, fake_temperature_measurement,
+ fake_temperature_type;
+ return fake_peripheral.addFakeService({uuid: 'generic_access'})
+ .then(_ => fake_generic_access = _)
+ .then(() => fake_peripheral.addFakeService({
+ uuid: 'health_thermometer',
+ }))
+ .then(_ => fake_health_thermometer = _)
+ .then(() => fake_health_thermometer.addFakeCharacteristic({
+ uuid: 'measurement_interval',
+ properties: ['read', 'write', 'indicate'],
+ }))
+ .then(_ => fake_measurement_interval = _)
+ .then(() => fake_measurement_interval.addFakeDescriptor({
+ uuid: 'gatt.characteristic_user_description',
+ }))
+ .then(_ => fake_user_description = _)
+ .then(() => fake_measurement_interval.addFakeDescriptor({
+ uuid: 'gatt.client_characteristic_configuration',
+ }))
+ .then(_ => fake_cccd = _)
+ .then(() => fake_health_thermometer.addFakeCharacteristic({
+ uuid: 'temperature_measurement',
+ properties: ['indicate'],
+ }))
+ .then(_ => fake_temperature_measurement = _)
+ .then(() => fake_health_thermometer.addFakeCharacteristic({
+ uuid: 'temperature_type',
+ properties: ['read'],
+ }))
+ .then(_ => fake_temperature_type = _)
+ .then(() => ({
+ fake_peripheral,
+ fake_generic_access,
+ fake_health_thermometer,
+ fake_measurement_interval,
+ fake_cccd,
+ fake_user_description,
+ fake_temperature_measurement,
+ fake_temperature_type,
+ }));
+}
+
+// Similar to getHealthThermometerDevice except the GATT discovery
+// response has not been set yet so more attributes can still be added.
+function getConnectedHealthThermometerDevice(options) {
+ let device, fake_peripheral, fakes;
+ return getDiscoveredHealthThermometerDevice(options)
+ .then(_ => ({device, fake_peripheral} = _))
+ .then(() => fake_peripheral.setNextGATTConnectionResponse({
+ code: HCI_SUCCESS,
+ }))
+ .then(() => populateHealthThermometerFakes(fake_peripheral))
+ .then(_ => fakes = _)
+ .then(() => device.gatt.connect())
+ .then(() => Object.assign({device}, fakes));
+}
+
+// Returns the same device and fake peripheral as getHealthThermometerDevice()
+// after another frame (an iframe we insert) discovered the device,
+// connected to it and discovered its services.
+function getHealthThermometerDeviceWithServicesDiscovered(options) {
+ let device, fake_peripheral, fakes;
+ let iframe = document.createElement('iframe');
+ return setUpConnectableHealthThermometerDevice()
+ .then(_ => fake_peripheral = _)
+ .then(() => populateHealthThermometerFakes(fake_peripheral))
+ .then(_ => fakes = _)
+ .then(() => fake_peripheral.setNextGATTDiscoveryResponse({
+ code: HCI_SUCCESS,
+ }))
+ .then(() => new Promise(resolve => {
+ iframe.src = '../../../resources/bluetooth/health-thermometer-iframe.html';
+ document.body.appendChild(iframe);
+ iframe.addEventListener('load', resolve);
+ }))
+ .then(() => new Promise((resolve, reject) => {
+ callWithTrustedClick(() => {
+ iframe.contentWindow.postMessage({
+ type: 'DiscoverServices',
+ options: options
+ }, '*');
+ });
+
+ function messageHandler(messageEvent) {
+ if (messageEvent.data == 'DiscoveryComplete') {
+ window.removeEventListener('message', messageHandler);
+ resolve();
+ } else {
+ reject(new Error(`Unexpected message: ${messageEvent.data}`));
+ }
+ }
+ window.addEventListener('message', messageHandler);
+ }))
+ .then(() => requestDeviceWithTrustedClick(options))
+ .then(_ => device = _)
+ .then(device => device.gatt.connect())
+ .then(_ => Object.assign({device}, fakes));
+}
+
+// Similar to getHealthThermometerDevice() except the device has no services,
+// characteristics, or descriptors.
+function getEmptyHealthThermometerDevice(options) {
+ return getDiscoveredHealthThermometerDevice(options)
+ .then(({device, fake_peripheral}) => {
+ return fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS})
+ .then(() => device.gatt.connect())
+ .then(() => fake_peripheral.setNextGATTDiscoveryResponse({
+ code: HCI_SUCCESS}))
+ .then(() => ({
+ device: device,
+ fake_peripheral: fake_peripheral
+ }));
+ });
+}
+
+// Similar to getHealthThermometerService() except the service has no
+// characteristics or included services.
+function getEmptyHealthThermometerService(options) {
+ let device;
+ let fake_peripheral;
+ let fake_health_thermometer;
+ return getDiscoveredHealthThermometerDevice(options)
+ .then(result => ({device, fake_peripheral} = result))
+ .then(() => fake_peripheral.setNextGATTConnectionResponse({
+ code: HCI_SUCCESS}))
+ .then(() => device.gatt.connect())
+ .then(() => fake_peripheral.addFakeService({uuid: 'health_thermometer'}))
+ .then(s => fake_health_thermometer = s)
+ .then(() => fake_peripheral.setNextGATTDiscoveryResponse({
+ code: HCI_SUCCESS}))
+ .then(() => device.gatt.getPrimaryService('health_thermometer'))
+ .then(service => ({
+ service: service,
+ fake_health_thermometer: fake_health_thermometer,
+ }));
+}
+
+// Returns a BluetoothDevice discovered using |options| and its
+// corresponding FakePeripheral.
+// The simulated device is called 'HID Device' it has three known service
+// UUIDs: 'generic_access', 'device_information', 'human_interface_device'.
+// The primary service with 'device_information' UUID has a characteristics
+// with UUID 'serial_number_string'. The device has been connected to and its
+// attributes are ready to be discovered.
+// TODO(crbug.com/719816): Add descriptors.
+function getHIDDevice(options) {
+ return setUpPreconnectedDevice({
+ address: '10:10:10:10:10:10',
+ name: 'HID Device',
+ knownServiceUUIDs: [
+ 'generic_access',
+ 'device_information',
+ 'human_interface_device'
+ ],
+ })
+ .then(fake_peripheral => {
+ return requestDeviceWithTrustedClick(options)
+ .then(device => {
+ return fake_peripheral
+ .setNextGATTConnectionResponse({
+ code: HCI_SUCCESS})
+ .then(() => device.gatt.connect())
+ .then(() => fake_peripheral.addFakeService({
+ uuid: 'generic_access'}))
+ .then(() => fake_peripheral.addFakeService({
+ uuid: 'device_information'}))
+ // Blocklisted Characteristic:
+ // https://github.com/WebBluetoothCG/registries/blob/master/gatt_blocklist.txt
+ .then(dev_info => dev_info.addFakeCharacteristic({
+ uuid: 'serial_number_string', properties: ['read']}))
+ .then(() => fake_peripheral.addFakeService({
+ uuid: 'human_interface_device'}))
+ .then(() => fake_peripheral.setNextGATTDiscoveryResponse({
+ code: HCI_SUCCESS}))
+ .then(() => ({
+ device: device,
+ fake_peripheral: fake_peripheral
+ }));
+ });
+ });
+}
+
+// Similar to getHealthThermometerDevice() except the device
+// is not connected and thus its services have not been
+// discovered.
+function getDiscoveredHealthThermometerDevice(
+ options = {filters: [{services: ['health_thermometer']}]}) {
+ return setUpHealthThermometerDevice()
+ .then(fake_peripheral => {
+ return requestDeviceWithTrustedClick(options)
+ .then(device => ({
+ device: device,
+ fake_peripheral: fake_peripheral
+ }));
+ });
+}
diff --git a/tests/wpt/web-platform-tests/common/media.js b/tests/wpt/web-platform-tests/common/media.js
index 6bddea5fd92..7cea1ac9b3c 100644
--- a/tests/wpt/web-platform-tests/common/media.js
+++ b/tests/wpt/web-platform-tests/common/media.js
@@ -33,3 +33,14 @@ function getAudioURI(base)
return base + extension;
}
+
+function getMediaContentType(url) {
+ var extension = new URL(url, location).pathname.split(".").pop();
+ var map = {
+ "mp4": "video/mp4",
+ "ogv": "video/ogg",
+ "mp3": "audio/mp3",
+ "oga": "audio/ogg",
+ };
+ return map[extension];
+}
diff --git a/tests/wpt/web-platform-tests/common/performance-timeline-utils.js b/tests/wpt/web-platform-tests/common/performance-timeline-utils.js
index 3beb28e9bf7..6845d6cbc68 100644
--- a/tests/wpt/web-platform-tests/common/performance-timeline-utils.js
+++ b/tests/wpt/web-platform-tests/common/performance-timeline-utils.js
@@ -36,7 +36,9 @@ function test_entries(actualEntries, expectedEntries) {
return actualEntry[key] !== expectedEntry[key]
}) === 'undefined'
})
- test_true(!!foundEntry)
- assert_object_equals(foundEntry.toJSON(), expectedEntry)
+ test_true(!!foundEntry, `Entry ${JSON.stringify(expectedEntry)} could not be found.`)
+ if (foundEntry) {
+ assert_object_equals(foundEntry.toJSON(), expectedEntry)
+ }
})
}
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/ariatree.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/ariatree.html
index d2d57e5082e..d915c55d786 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/ariatree.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/ariatree.html
@@ -4,9 +4,9 @@
<title>ARIA Tree Example</title>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<link rel="stylesheet" href="./css/treesimple.css" type="text/css">
- <script type="text/javascript" src="./js/prototype.js"></script>
- <script type="text/javascript" src="./js/aria.js"></script>
- <script type="text/javascript" src="./js/init.js"></script>
+ <script src="./js/prototype.js"></script>
+ <script src="./js/aria.js"></script>
+ <script src="./js/init.js"></script>
</head>
<body>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/ariatree2.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/ariatree2.html
index b6d809ce61f..3efe2464881 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/ariatree2.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/ariatree2.html
@@ -4,9 +4,9 @@
<title>ARIA Tree Example</title>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<link rel="stylesheet" href="./css/treebox.css" type="text/css">
- <script type="text/javascript" src="./js/prototype.js"></script>
- <script type="text/javascript" src="./js/aria.js"></script>
- <script type="text/javascript" src="./js/init.js"></script>
+ <script src="./js/prototype.js"></script>
+ <script src="./js/aria.js"></script>
+ <script src="./js/init.js"></script>
</head>
<body>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/673.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/673.html
index d24cd6b01e3..38100513da4 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/673.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/673.html
@@ -15,7 +15,7 @@
After the onload event completes a child DOM text node is added to the element with
the aria-live attribute.</p>
- <script type="text/javascript">
+ <script>
function addTextNode() {
var node = document.getElementById('TEST_ID');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/674.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/674.html
index c031ec954f4..52269a560a1 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/674.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/674.html
@@ -15,7 +15,7 @@
After the onload event completes a child DOM text node is added to the element
with the aria-live attribute.</p>
- <script type="text/javascript">
+ <script>
function addTextNode() {
var node = document.getElementById('TEST_ID');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/675.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/675.html
index c762fcfb03b..1c778dd0bd9 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/675.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/675.html
@@ -16,7 +16,7 @@
value 'assertive' is added to the element and a child DOM text
node is added to the element.</p>
- <script type="text/javascript">
+ <script>
function addLiveRegion() {
var node = document.getElementById('TEST_ID');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/676.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/676.html
index 0e193cbe33d..117fc5c5759 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/676.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/676.html
@@ -16,7 +16,7 @@
value 'assertive' is added to the document and a child element and text
node is added to the element with the aria-live attribute.</p>
- <script type="text/javascript">
+ <script>
function addElement() {
var node = document.getElementById('TEST_ID');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/677.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/677.html
index e93361c5838..9a6b48805d0 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/677.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/677.html
@@ -17,7 +17,7 @@
After the onload event completes a child DOM element node with text content has the
CSS dsiplay property changed to display="block".</p>
- <script type="text/javascript">
+ <script>
function showElement() {
var node = document.getElementById('TEST_ID');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/678.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/678.html
index 68699e38c73..6479eca47c0 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/678.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/678.html
@@ -18,7 +18,7 @@
a child DOM element node with text content has the CSS dsiplay property
changed to display="block".</p>
- <script type="text/javascript">
+ <script>
function showElement() {
var node = document.getElementById('TEST_ID');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/679.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/679.html
index 6bb8b2da9ac..0f745965dc8 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/679.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/679.html
@@ -20,7 +20,7 @@
After the onload event completes a child DOM element node with text content has the
CSS dsiplay property changed to visibility="visible".</p>
- <script type="text/javascript">
+ <script>
function showElement() {
var node = document.getElementById('TEST_ID');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/680.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/680.html
index ef774fd3c2d..9a649367550 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/680.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/680.html
@@ -19,7 +19,7 @@
After the onload event completes a child DOM element node with text content has the CSS dsiplay
property changed to visibility="visible".</p>
- <script type="text/javascript">
+ <script>
function showElement() {
var node = document.getElementById('TEST_ID');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/681.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/681.html
index fd8befe760c..e8a60269cbc 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/681.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/681.html
@@ -15,7 +15,7 @@
event with the value="polite". After the onload event completes a child DOM text node is added
to the element with the aria-live attribute.</p>
- <script type="text/javascript">
+ <script>
function addChildTextNode() {
var node = document.getElementById('TEST_ID');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/682.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/682.html
index b8d90ce19d9..85d744de6db 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/682.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/682.html
@@ -15,7 +15,7 @@
event with the value="assertive". After the onload event completes a child DOM text node is
added to the element with the aria-live attribute.</p>
- <script type="text/javascript">
+ <script>
function addChildTextNode() {
var node = document.getElementById('TEST_ID_2');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/683.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/683.html
index ca45f2b55c8..92bde34f7bd 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/683.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/683.html
@@ -15,7 +15,7 @@
event with the value="polite". After the onload event completes a child DOM element node is
added to the element with the aria-live attribute.</p>
- <script type="text/javascript">
+ <script>
function addChildElementNode() {
var node = document.getElementById('TEST_ID_2');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/684.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/684.html
index 2abea5c468d..c77062ca20c 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/684.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/684.html
@@ -15,7 +15,7 @@
the onload event with the value="assertive". After the onload event completes a
child DOM element node is added to the element with the aria-live attribute.</p>
- <script type="text/javascript">
+ <script>
function addChildElementNode() {
var node = document.getElementById('TEST_ID_2');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/685.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/685.html
index 90cb71f025d..f09903944d8 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/685.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/685.html
@@ -16,7 +16,7 @@
that is hidden using CSS display="none". After the onload event completes a child DOM element
node with text content has the CSS display property changed to display="block".</p>
- <script type="text/javascript">
+ <script>
function showElement() {
var node = document.getElementById('TEST_ID_3');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/686.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/686.html
index 9cf141d69cc..ed550077ded 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/686.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/686.html
@@ -16,7 +16,7 @@
that is hidden using CSS display="none". After the onload event completes a child DOM element
node with text content has the CSS display property changed to display="block".</p>
- <script type="text/javascript">
+ <script>
function showElement() {
var node = document.getElementById('TEST_ID_3');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/687.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/687.html
index 2294b4c866a..9503adb54f0 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/687.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/687.html
@@ -17,7 +17,7 @@
event completes a child DOM element node with text content has the CSS display property
changed to visibility="visible".</p>
- <script type="text/javascript">
+ <script>
function showElement() {
var node = document.getElementById('TEST_ID_3');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/688.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/688.html
index cc488b8a239..c21cf2714fc 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/688.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/688.html
@@ -17,7 +17,7 @@
After the onload event completes a child DOM element node with text content
has the CSS display property changed to visibility="visible".</p>
- <script type="text/javascript">
+ <script>
function showElement() {
var node = document.getElementById('TEST_ID_3');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/689.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/689.html
index 714b34b0918..98f20d456ba 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/689.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/689.html
@@ -15,7 +15,7 @@
onload event completes with the value="polite". After the aria-live attribute is added,
a child DOM text node is added to the element with the aria-live attribute.</p>
- <script type="text/javascript">
+ <script>
function addChildTextNode() {
var node = document.getElementById('TEST_ID_2');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/690.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/690.html
index 3f189e59add..d3fb88c8413 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/690.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/690.html
@@ -15,7 +15,7 @@
the onload event completes with the value="assertive". After the aria-live attribute
is added, a child DOM text node is added to the element with the aria-live attribute.</p>
- <script type="text/javascript">
+ <script>
function addChildTextNode() {
var node = document.getElementById('TEST_ID_2');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/691.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/691.html
index 85bd8c9402f..4cb1ab71125 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/691.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/691.html
@@ -16,7 +16,7 @@
attribute is added, a child DOM element node is added to the element with
the aria-live attribute.</p>
- <script type="text/javascript">
+ <script>
function addChildElementNode() {
var node = document.getElementById('TEST_ID_2');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/692.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/692.html
index 13c16d62fec..7f6f3f9ec3d 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/692.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/692.html
@@ -15,7 +15,7 @@
the onload event completes with the value="assertive". After the aria-live attribute
is added, a child DOM element node is added to the element with the aria-live attribute.</p>
- <script type="text/javascript">
+ <script>
function addChildElementNode() {
var node = document.getElementById('TEST_ID_2');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/693.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/693.html
index 8914d7e86ae..9695f25a637 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/693.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/693.html
@@ -17,7 +17,7 @@
aria-live attribute is added, the child DOM element node with text content has the
CSS display property changed to display="block".</p>
- <script type="text/javascript">
+ <script>
function showElement() {
var node = document.getElementById('TEST_ID_2');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/694.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/694.html
index 49ee64c75e9..392e7d22f43 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/694.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/694.html
@@ -17,7 +17,7 @@
the aria-live attribute is added, the child DOM element node with text content has
the CSS display property changed to display="block".</p>
- <script type="text/javascript">
+ <script>
function showElement() {
var node = document.getElementById('TEST_ID_3');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/695.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/695.html
index b2550c6982f..46c1666d1dc 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/695.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/695.html
@@ -17,7 +17,7 @@
visibility="hidden". After the aria-live attribute is added, the child DOM
element node with text content has the CSS display property changed to visibility="visible".</p>
- <script type="text/javascript">
+ <script>
function showElement() {
var node = document.getElementById('TEST_ID_3');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/696.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/696.html
index a577b1d5aac..b66a7214e31 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/696.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/696.html
@@ -18,7 +18,7 @@
the aria-live attribute is added, the child DOM element node with text content has
the CSS display property changed to visibility="visible".</p>
- <script type="text/javascript">
+ <script>
function showElement() {
var node = document.getElementById('TEST_ID_2');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/697.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/697.html
index eed947c4417..c229e74ca0d 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/697.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/697.html
@@ -16,7 +16,7 @@
has a child DOM text node with content. After the onload event completes the child
DOM text node is deleted.</p>
- <script type="text/javascript">
+ <script>
function deleteChildNodes() {
var node = document.getElementById('TEST_ID_1');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/698.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/698.html
index 3e90818997c..3d96ba9f439 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/698.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/698.html
@@ -16,7 +16,7 @@
has a child DOM text node with content. After the onload event completes the child DOM
text node is deleted.</p>
- <script type="text/javascript">
+ <script>
function deleteChildNodes() {
var node = document.getElementById('TEST_ID_1');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/699.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/699.html
index f306cb1c45b..adc1c79b55d 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/699.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/699.html
@@ -16,7 +16,7 @@
has a child DOM element node that contains text content. After the onload event completes
the child DOM element node is deleted.</p>
- <script type="text/javascript">
+ <script>
function deleteChildNodes() {
var node = document.getElementById('TEST_ID_1');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/700.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/700.html
index de12aff296f..4f0af8cc61a 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/700.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/700.html
@@ -16,7 +16,7 @@
value="assertive" has a child DOM element node that contains text content.
After the onload event completes the child DOM element node is deleted.</p>
- <script type="text/javascript">
+ <script>
function deleteChildNodes() {
var node = document.getElementById('TEST_ID_1');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/701.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/701.html
index 942cab36957..755b2269638 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/701.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/701.html
@@ -17,7 +17,7 @@
content. After the onload event completes the CSS 'display' property
of the child DOM element node is changed to display="none".</p>
- <script type="text/javascript">
+ <script>
function hideElement() {
var node = document.getElementById('TEST_ID_1');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/702.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/702.html
index f46eb1d022f..e13b82edcd6 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/702.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/702.html
@@ -16,7 +16,7 @@
has a child DOM element node that contains text content. After the onload event completes
the CSS 'display' property of the child DOM element node is changed to display="none".</p>
- <script type="text/javascript">
+ <script>
function hideElement() {
var node = document.getElementById('TEST_ID_1');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/703.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/703.html
index 661eed254f7..e0a4ed5495d 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/703.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/703.html
@@ -17,7 +17,7 @@
completes the CSS 'visibility' property of the child DOM element node is changed
to visibility="hidden".</p>
- <script type="text/javascript">
+ <script>
function hideElement() {
var node = document.getElementById('TEST_ID_1');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/704.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/704.html
index bb68b58ac3e..c2294a5f54e 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/704.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/704.html
@@ -16,7 +16,7 @@
has a child DOM element node that contains text content. After the onload event completes
the CSS 'visibility' property of the child DOM element node is changed to visibility="hidden".</p>
- <script type="text/javascript">
+ <script>
function hideElement() {
var node = document.getElementById('TEST_ID_1');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/705.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/705.html
index d1f8cb84af1..3ac9831e97a 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/705.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/705.html
@@ -16,7 +16,7 @@
text node with content. After the onload event completes the child DOM text
node is deleted.</p>
- <script type="text/javascript">
+ <script>
function deleteChildNodes() {
var node = document.getElementById('TEST_ID_2');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/706.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/706.html
index 80f605d0ca1..edcc7a960b1 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/706.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/706.html
@@ -15,7 +15,7 @@
event with the value="assertive" and the element has a child DOM text node with content. After
the onload event completes the child DOM text node is deleted.</p>
- <script type="text/javascript">
+ <script>
function deleteChildNodes() {
var node = document.getElementById('TEST_ID_2');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/707.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/707.html
index 8490112b287..ed0de5ffa07 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/707.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/707.html
@@ -16,7 +16,7 @@
DOM element node that contains text content. After the onload event completes
the child DOM element node is deleted.</p>
- <script type="text/javascript">
+ <script>
function deleteChildNodes() {
var node = document.getElementById('TEST_ID_2');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/708.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/708.html
index e1bfcd10ec6..796b729086f 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/708.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/708.html
@@ -16,7 +16,7 @@
node that contains text content. After the onload event completes the child DOM
element node is deleted.</p>
- <script type="text/javascript">
+ <script>
function deleteChildNodes() {
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/709.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/709.html
index 321b85273fd..3306f7e1529 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/709.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/709.html
@@ -16,7 +16,7 @@
that contains text content. After the onload event completes the CSS 'display'
property of the child DOM element node is changed to display="none".</p>
- <script type="text/javascript">
+ <script>
function hideElement() {
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/710.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/710.html
index 872643f66eb..dd947f21d99 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/710.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/710.html
@@ -16,7 +16,7 @@
node that contains text content. After the onload event completes the CSS 'display'
property of the child DOM element node is changed to display="none".</p>
- <script type="text/javascript">
+ <script>
function hideElement() {
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/711.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/711.html
index 7b4375c74d0..af409ce80a3 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/711.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/711.html
@@ -17,7 +17,7 @@
the CSS 'visibility' property of the child DOM element node is changed
to visibility="hidden".</p>
- <script type="text/javascript">
+ <script>
function hideElement() {
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/712.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/712.html
index 3c6d69d3377..11dd2f28b20 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/712.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/712.html
@@ -17,7 +17,7 @@
event completes the CSS 'visibility' property of the child DOM element
node is changed to visibility="hidden".</p>
- <script type="text/javascript">
+ <script>
function hideElement() {
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/713.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/713.html
index 08f8a5b287b..24387f92063 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/713.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/713.html
@@ -16,7 +16,7 @@
the element has a child DOM text node with content. After the
aria-live attribute is added, the child DOM text node is deleted.</p>
- <script type="text/javascript">
+ <script>
function deleteChildNodes() {
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/714.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/714.html
index 56a63f82f20..b2d4f120b70 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/714.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/714.html
@@ -16,7 +16,7 @@
and the element has a child DOM text node with content. After the
aria-live attribute is added, the child DOM text node is deleted.</p>
- <script type="text/javascript">
+ <script>
function deleteChildNodes() {
var node = document.getElementById('TEST_ID_2');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/715.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/715.html
index 82f82b05693..00b26f591b7 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/715.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/715.html
@@ -16,7 +16,7 @@
a child DOM element node that contains text content. After the aria-live
attribute is added, the child DOM element node is deleted.</p>
- <script type="text/javascript">
+ <script>
function deleteChildNodes() {
var node = document.getElementById('TEST_ID_1');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/716.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/716.html
index 3a98fad05c0..80d2b85ecdf 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/716.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/716.html
@@ -17,7 +17,7 @@
a child DOM element node that contains text content. After the aria-live
attribute is added, the child DOM element node is deleted.</p>
- <script type="text/javascript">
+ <script>
function deleteChildNodes() {
var node = document.getElementById('TEST_ID_1');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/717.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/717.html
index e4e65c3868a..aaed8c09d79 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/717.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/717.html
@@ -17,7 +17,7 @@
attribute is added, the CSS 'display' property of the child DOM element
node is changed to display="none".</p>
- <script type="text/javascript">
+ <script>
function hideElement() {
var node = document.getElementById('TEST_ID_2');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/718.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/718.html
index e662390cb05..f6e9a2b1ad9 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/718.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/718.html
@@ -17,7 +17,7 @@
attribute is added, the CSS 'display' property of the child DOM element
node is changed to display="none".</p>
- <script type="text/javascript">
+ <script>
function hideElement() {
var node = document.getElementById('TEST_ID_2');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/719.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/719.html
index 4fd10b746b7..1f132e67aec 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/719.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/719.html
@@ -17,7 +17,7 @@
After the aria-live attribute is added, the CSS 'visibility' property
of the child DOM element node is changed to visibility="hidden".</p>
- <script type="text/javascript">
+ <script>
function hideElement() {
var node = document.getElementById('TEST_ID_2');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/720.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/720.html
index 22ab76a5349..23564ea2474 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/720.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/720.html
@@ -17,7 +17,7 @@
After the aria-live attribute is added, the CSS 'visibility' property
of the child DOM element node is changed to visibility="hidden".</p>
- <script type="text/javascript">
+ <script>
function hideElement() {
var node = document.getElementById('TEST_ID_2');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/567.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/567.html
index ce4c8d4c45b..3800104d526 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/567.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/567.html
@@ -3,7 +3,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>A &lt;div&gt; with role "button" followed by a modification to the value of "checkbox".</title>
- <script type="text/javascript">
+ <script>
function changeRole (/* Element */ element, /* String */ newRole) {
element.setAttribute ('role', newRole);
element.innerHTML = "This &lt;div&gt; has role '" + newRole + "'";
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/568.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/568.html
index d9f06dc27d9..d290ada24c8 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/568.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/568.html
@@ -3,7 +3,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>A &lt;div&gt; with role "button" followed by removal of the element and its children and an insertion of a new div having role="checkbox"</title>
- <script type="text/javascript">
+ <script>
function changeRoleByRemoval (/* Element */ element, /* String */ newRole) {
var parent = element.parentNode;
if (parent) {
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/571-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/571-haswarn.html
index 41b8867616a..92130fbf98a 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/571-haswarn.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/571-haswarn.html
@@ -2,10 +2,10 @@
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>In a &lt;div&gt; element with role="combobox" and aria-autocomplete="none", change values of the combobox by typing.</title>
- <style type="text/css">
+ <style>
.hasFocus { border: 2px solid red; }
</style>
- <script type="text/javascript">
+ <script>
var DEL = 8;
var BACK_SPACE = 72;
var comboInfo = {};
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/572-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/572-haswarn.html
index a317a1c2648..358d14a6170 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/572-haswarn.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/572-haswarn.html
@@ -3,10 +3,10 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>In a &lt;div&gt; element with role="combobox" and aria-autocomplete="inline", change values of the combobox by adjusting the up and down arrow keys with focus on the textfield in the combobox.</title>
- <style type="text/css">
+ <style>
.hasFocus { border: 2px solid red; }
</style>
- <script type="text/javascript">
+ <script>
var UP = 38;
var DOWN = 40;
comboInfo = {};
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/573-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/573-haswarn.html
index 388282c382d..195dc7cdc0c 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/573-haswarn.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/573-haswarn.html
@@ -3,10 +3,10 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>In a &lt;div&gt; element with role="combobox" and aria-autocomplete="both", change values of the combobox by adjusting the up and down arrow keys with focus on the textfield in the combobox.</title>
- <style type="text/css">
+ <style>
.hasFocus { border: 2px solid red; }
</style>
- <script type="text/javascript">
+ <script>
var UP = 38;
var DOWN = 40;
comboInfo = {};
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/580.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/580.html
index 5445050641a..14a2c11bd2c 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/580.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/580.html
@@ -3,7 +3,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>A div element with style="display:none" has aria-hidden="true", and then script sets style to "display: block".</title>
- <script type="text/javascript">
+ <script>
function replaceStyle (/* Element */ element, /* String */ selector, /* String */ newValue) {
element.setAttribute ('style', selector + ':' + newValue);
if (newValue == 'block')
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-1.html
index a04c24aa8fb..58f860520c4 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-1.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-1.html
@@ -3,7 +3,7 @@
<head>
<title>ARIA 1.0 Live Region Event Test Case: Add text content</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <style type="text/css">
+ <style>
div#TEST_ID {
margin: 0.5em;
padding: 0.25em;
@@ -42,7 +42,7 @@
</dl>
- <script type="text/javascript">
+ <script>
function tryAgain() {
var node = document.getElementById('TEST_ID');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-2.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-2.html
index 39cf43d79f5..180ff4c44e9 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-2.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-2.html
@@ -3,7 +3,7 @@
<head>
<title>ARIA 1.0 Live Region Event Test Case: Delete text content</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <style type="text/css">
+ <style>
div#TEST_ID {
margin: 0.5em;
padding: 0.25em;
@@ -44,7 +44,7 @@
</dl>
- <script type="text/javascript">
+ <script>
function tryAgain() {
addText()
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-3.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-3.html
index 8e49ee38e2c..8bd066d9f22 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-3.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-3.html
@@ -3,7 +3,7 @@
<head>
<title>ARIA 1.0 Live Region Event Test Case: Change text content</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <style type="text/css">
+ <style>
div#TEST_ID {
margin: 0.5em;
padding: 0.25em;
@@ -44,7 +44,7 @@
</dl>
- <script type="text/javascript">
+ <script>
function tryAgain() {
changeText('TEST TEXT 1')
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-4.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-4.html
index a5233f3af2e..25609e92c5c 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-4.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-4.html
@@ -3,7 +3,7 @@
<head>
<title>ARIA 1.0 Live Region Event Test Case: Add text content (ALERT role)</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <style type="text/css">
+ <style>
div#TEST_ID {
margin: 0.5em;
padding: 0.25em;
@@ -42,7 +42,7 @@
</dl>
- <script type="text/javascript">
+ <script>
function tryAgain() {
var node = document.getElementById('TEST_ID');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-5.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-5.html
index 914b28222c9..4ca9d33fc6a 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-5.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-5.html
@@ -3,7 +3,7 @@
<head>
<title>ARIA 1.0 Live Region Event Test Case: Change text content (LOG role)</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <style type="text/css">
+ <style>
div#TEST_ID {
margin: 0.5em;
padding: 0.25em;
@@ -44,7 +44,7 @@
</dl>
- <script type="text/javascript">
+ <script>
function tryAgain() {
changeText('LOG ROLE TEST TEXT 1')
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-6.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-6.html
index 8be8f43e633..7fb2a07a01c 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-6.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-6.html
@@ -3,7 +3,7 @@
<head>
<title>ARIA 1.0 Live Region Event Test Case: Delete text content (STATUS role)</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <style type="text/css">
+ <style>
div#TEST_ID {
margin: 0.5em;
padding: 0.25em;
@@ -44,7 +44,7 @@
</dl>
- <script type="text/javascript">
+ <script>
function tryAgain() {
addText()
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/659.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/659.html
index 5e9b439b089..c7700a8d020 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/659.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/659.html
@@ -3,7 +3,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Text input with @title and :before and :after content rule</title>
- <style type="text/css">
+ <style>
label:before { content: "foo"; }
label:after { content: "baz"; }
</style>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/660.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/660.html
index e1d5f9416ff..7fd0d265a30 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/660.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/660.html
@@ -3,7 +3,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Text input with @title and :before and :after content rule</title>
- <style type="text/css">
+ <style>
label:before { content: "foo "; }
label:after { content: " baz"; }
</style>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/661.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/661.html
index 95a3d46f243..7cb28dcf8eb 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/661.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/661.html
@@ -3,7 +3,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Text input with @title and :before and :after content rule</title>
- <style type="text/css">
+ <style>
label:before { content: "foo"; }
label:after { content: "baz"; }
</style>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/662.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/662.html
index 3bca08804f5..a857a155600 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/662.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/662.html
@@ -3,7 +3,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Text input with @title and :before and :after content rule</title>
- <style type="text/css">
+ <style>
label:before { content: "foo"; }
label:after { content: "baz"; }
</style>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/663.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/663.html
index ae70b8532ab..01c56048266 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/663.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/663.html
@@ -3,7 +3,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Text input with @title and :before and :after content rule</title>
- <style type="text/css">
+ <style>
label:before { content: "foo "; }
label:after { content: " baz"; }
</style>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-listbox-parent-combobox.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-listbox-parent-combobox.html
index e2e0135eeb2..43e137fe573 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-listbox-parent-combobox.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-listbox-parent-combobox.html
@@ -3,7 +3,7 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>An element with id=test and role=listbox, which is owned by a combobox</title>
- <style type="text/css">
+ <style>
ul#test {
list-style-type: none;
width: 5em;
@@ -12,9 +12,9 @@
margin-top: 0;
margin-left: 1em;
}
-
+
ul#test > li {
- margin-left -10em;
+ margin-left: -10em;
}
</style>
</head>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/670.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/670.html
index 594bf048fab..de95a2e19da 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/670.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/670.html
@@ -17,7 +17,7 @@
role "listbox", and the value of the "aria-selected" attribute is equal
to "true".</p>
- <script type="text/javascript">
+ <script>
function setFocus() {
var node = document.getElementById('ID_OPTION');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/671.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/671.html
index 2c95a4f5f23..4d36b22cf1c 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/671.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/671.html
@@ -18,7 +18,7 @@
to "true" or the attribute is undefined.</p>
- <script type="text/javascript">
+ <script>
function setFocus() {
var test_node = document.getElementById('ID_OPTION');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/672.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/672.html
index 461d343a0e2..962e6b944b8 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/672.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/672.html
@@ -15,7 +15,7 @@
<p>For an element with role "option" which is a child of an element with role "listbox",
and the value of the "aria-selected" attribute changes (from "true", or to "true").</p>
- <script type="text/javascript">
+ <script>
function changeSelectedState() {
var test_node = document.getElementById('TEST_ID');
var state = test_node.getAttribute('aria-selected');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/setsize-posinset-level/setsize-posinset-level-1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/setsize-posinset-level/setsize-posinset-level-1.html
index 92bf0f4856b..04786b80666 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/setsize-posinset-level/setsize-posinset-level-1.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/setsize-posinset-level/setsize-posinset-level-1.html
@@ -71,7 +71,7 @@
</ul>
- <script type="text/javascript">
+ <script>
function setFocus() {
var node = document.getElementById('ID_TARGET');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/stability-of-dom/669.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/stability-of-dom/669.html
index 6ad0f03522d..2f2e64fb693 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/stability-of-dom/669.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/stability-of-dom/669.html
@@ -17,7 +17,7 @@
and aria-activedescendant set to the id of the first option for which an
assistive technology or API test tool requests to move focus to option 2.</p>
- <script type="text/javascript">
+ <script>
function setFocus() {
var node = document.getElementById('ID_LISTBOX');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-A.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-A.html
index ab66f058f19..3ba81f2c16e 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-A.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-A.html
@@ -35,7 +35,7 @@
<h3>AXAPI</h3>
<p>AXSelected:Yes on option 2 and 3 and AXSelected:No on option 1 and 4</p>
- <script type="text/javascript">
+ <script>
function setFocus() {
var node = document.getElementById('ID_TARGET');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-B.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-B.html
index 7ae3d88dd0a..6d1dcdaae7a 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-B.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-B.html
@@ -35,7 +35,7 @@
<h3>AXAPI</h3>
<p>AXSelected:Yes on option 2 and 3 and AXSelected:No on option 1 and 4</p>
- <script type="text/javascript">
+ <script>
function clearSelection() {
myVar=setTimeout(function(){var node = document.getElementById('ID_TARGET');node.setAttribute("aria-selected","false");} ,3000)
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-C.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-C.html
index 01f8ccfaa1a..88eb11bb419 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-C.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-C.html
@@ -2,7 +2,7 @@
<html><head>
<title>ARIA 1.0 Test Case: Listbox role with multiseclect</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <style type="text/css">
+ <style>
[aria-selected="true"] { font-weight: bold; }
</style>
</head>
@@ -39,7 +39,7 @@
<h3>AXAPI</h3>
<p>AXSelected:Yes on option 2 and 3 and AXSelected:No on option 1 and 4</p>
- <script type="text/javascript">
+ <script>
/*
function setSelection() {
var node = document.getElementById('ID_TARGET');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-multiselectable-D.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-multiselectable-D.html
index cc13b5cfe01..290430acf5c 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-multiselectable-D.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-multiselectable-D.html
@@ -2,7 +2,7 @@
<html><head>
<title>ARIA 1.0 Test Case: Listbox role with multiseclect</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <style type="text/css">
+ <style>
div[aria-selected="true"] {color:white;background-color:black;}
</style>
</head>
@@ -15,7 +15,7 @@
<div role="option" aria-selected="false" id="ID3" onmousedown="handle2(event)">Option 3 (test for shift click selected)</div>
</div>
- <script type="text/javascript">
+ <script>
function handle1(e) {
var node=document.getElementById('ID1');
node.focus();
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-tree-multiselectable-C.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-tree-multiselectable-C.html
index eeb46a0c3f8..da97b2945f2 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-tree-multiselectable-C.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-tree-multiselectable-C.html
@@ -30,7 +30,7 @@
</div>
</div>
- <script type="text/javascript">
+ <script>
function setFocus() {
var node = document.getElementById('ID_TARGET');
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue4html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue4html.html
index 82d2056436f..110585eae3a 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue4html.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue4html.html
@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8"/>
<title>Telharmonium 1897</title>
- <style type="text/css">
+ <style>
[its-loc-quality-issue-type]{
background-color:yellow;
margin:2px;
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue5html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue5html.html
index 951cfddb7eb..7eb28afaf8f 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue5html.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue5html.html
@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8"/>
<title>Telharmonium 1897</title>
- <style type="text/css">
+ <style>
[its-loc-quality-issue-type]{
background-color:yellow;
margin:2px;
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue6html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue6html.html
index ac35ca5ef2d..9658ece5386 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue6html.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue6html.html
@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8"/>
<title>Telharmonium 1897</title>
- <style type="text/css">
+ <style>
[its-loc-quality-issue-type]{
background-color:yellow;
margin:2px;
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue7html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue7html.html
index 01beb027e71..928c65b0f99 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue7html.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue7html.html
@@ -11,7 +11,7 @@
locQualityIssueSeverity="50"/>
</its:locQualityIssues>
</script>
- <style type="text/css">.qaissue { background-color: yellow; } </style>
+ <style>.qaissue { background-color: yellow; } </style>
</head>
<body>
<p>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/animate-elem-33-t-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/animate-elem-33-t-isvalid.html
index b9a460041cd..f8b1d078546 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/animate-elem-33-t-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/animate-elem-33-t-isvalid.html
@@ -66,7 +66,7 @@
</circle>
</g>
<!-- THIRD TEST-->
- <!-- The lenght of the lines in the polyline (motionpath) are 100,50 and 100.
+ <!-- The length of the lines in the polyline (motionpath) are 100,50 and 100.
The animated circle starts at the midpoint of one of the "legs" and also pass
this point at time 1.4 since
1.4 = 4*(0.25) + (4*(0.75-0.25))*(1/5).
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/animate-elem-90-b-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/animate-elem-90-b-isvalid.html
index 6141e62c9ca..40e7face85d 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/animate-elem-90-b-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/animate-elem-90-b-isvalid.html
@@ -26,7 +26,7 @@
<font-face-uri xlink:href="../resources/SVGFreeSans.svg#ascii"/>
</font-face-src>
</font-face>
- <style type="text/css">
+ <style>
.start {visibility: hidden }
.midway {visibility: visible; fill: rgb(0,0,255); }
#test-body-content .final {fill: rgb(128,0,0); }
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/animate-elem-91-t-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/animate-elem-91-t-isvalid.html
index fe95c822e0a..8815c7b40f6 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/animate-elem-91-t-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/animate-elem-91-t-isvalid.html
@@ -51,7 +51,7 @@
<!-- Sub-test 1: class on <rect> -->
<g transform="translate(0,110)">
- <style type="text/css">.on { fill: rgb(204,0,102) } .off { fill: #ccc }</style>
+ <style>.on { fill: rgb(204,0,102) } .off { fill: #ccc }</style>
<text x="30" y="12">class</text>
<rect x="200" width="12" height="12" stroke="black" class="on">
<animate attributeName="class" to="off" begin="2s" dur="2s" fill="freeze"/>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/filters-turb-02-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/filters-turb-02-f-isvalid.html
index 203f6a79e99..42306736a9f 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/filters-turb-02-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/filters-turb-02-f-isvalid.html
@@ -72,7 +72,7 @@
<feTurbulence seed="-2.6" baseFrequency="0.01" type="turbulence"/>
</filter>
- <style type="text/css">
+ <style>
#subtests text { fill: black }
</style>
</defs>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/fonts-elem-03-b-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/fonts-elem-03-b-isvalid.html
index e8e47d4d238..3fc08bcb411 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/fonts-elem-03-b-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/fonts-elem-03-b-isvalid.html
@@ -29,7 +29,7 @@
</defs>
<g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
<defs>
- <!--style type="text/css">
+ <!--style>
<![CDATA[
@font-face {
font-family: 'TestComic';
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/fonts-elem-04-b-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/fonts-elem-04-b-isvalid.html
index 543abe3c983..c14bcc509f0 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/fonts-elem-04-b-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/fonts-elem-04-b-isvalid.html
@@ -29,7 +29,7 @@
</defs>
<g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
<defs>
- <style type="text/css">
+ <style>
@font-face {
font-family: 'TestComic';
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/fonts-elem-07-b-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/fonts-elem-07-b-isvalid.html
index 8bb396fe6a1..bdaa26ff777 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/fonts-elem-07-b-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/fonts-elem-07-b-isvalid.html
@@ -29,7 +29,7 @@
</defs>
<g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
<defs>
- <style type="text/css">
+ <style>
@font-face {
font-family: 'TestComic';
font-weight: normal;
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/interact-pevents-10-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/interact-pevents-10-f-isvalid.html
index 9aec374030b..553f1a3f44d 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/interact-pevents-10-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/interact-pevents-10-f-isvalid.html
@@ -35,7 +35,7 @@
<circle onclick="failTest()" cx="250" cy="200" r="50" />
</g>
<text id="failText" visibility="hidden" x="100" y="100" font-size="80" fill="red">FAIL</text>
- <script type="text/javascript"><![CDATA[
+ <script><![CDATA[
try
{
function failTest()
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/interact-pointer-04-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/interact-pointer-04-f-isvalid.html
index 499797d2176..8e9660b91a5 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/interact-pointer-04-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/interact-pointer-04-f-isvalid.html
@@ -35,7 +35,7 @@
<rect x="0" y="0" width="100" height="100" fill="black" />
</mask>
<rect x="200" y="0" width="100" height="100" fill="#dddddd" mask="url(#opacityMask)" onmouseover="testOpacity()" />
- <script type="text/javascript"><![CDATA[
+ <script><![CDATA[
try
{
function test(testElement)
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/masking-mask-01-b-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/masking-mask-01-b-isvalid.html
index 23590f257b5..d23f6a1b857 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/masking-mask-01-b-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/masking-mask-01-b-isvalid.html
@@ -28,7 +28,7 @@
</font-face>
</defs>
<g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
- <style type="text/css">
+ <style>
@font-face {
font-family: larabie-anglepoise;
src: url(woffs/anglepoi.woff) format("woff");
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/masking-path-12-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/masking-path-12-f-isvalid.html
index 6cf14af1c2e..8ea5703342a 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/masking-path-12-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/masking-path-12-f-isvalid.html
@@ -37,7 +37,7 @@
<rect id="pass" x="200" y="100" width="50" height="50" fill="green"/>
<rect id="fail" x="200" y="100" width="50" height="50" fill="red"/>
- <script type="text/javascript"><![CDATA[
+ <script><![CDATA[
try
{
var test = document.getElementById("testClip");
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/painting-marker-03-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/painting-marker-03-f-isvalid.html
index 0c73e6d0e97..27d15960c4e 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/painting-marker-03-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/painting-marker-03-f-isvalid.html
@@ -35,7 +35,7 @@
<marker id="marker2" markerUnits="strokeWidth" refX="100" refY="100" markerWidth="15" markerHeight="15" viewBox="0 0 200 200">
<rect width="200" height="200" fill="red" stroke="none"/>
</marker>
- <style type="text/css">
+ <style>
#markme { marker: url(#marker1) }
</style>
</defs>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/painting-marker-05-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/painting-marker-05-f-isvalid.html
index 0180187137c..08a85a76958 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/painting-marker-05-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/painting-marker-05-f-isvalid.html
@@ -110,7 +110,7 @@
</marker>
</defs>
- <style type="text/css">
+ <style>
.testpaths {
fill:none;
stroke:black;
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/painting-marker-properties-01-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/painting-marker-properties-01-f-isvalid.html
index 6781359b25f..52a4b4ac2ad 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/painting-marker-properties-01-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/painting-marker-properties-01-f-isvalid.html
@@ -25,7 +25,7 @@
</font-face>
</defs>
<g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
- <style type="text/css"><![CDATA[
+ <style><![CDATA[
.start
{
marker-start: url(#markerTest);
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/pservers-grad-08-b-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/pservers-grad-08-b-isvalid.html
index 561f444ee1f..8afbbc2263a 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/pservers-grad-08-b-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/pservers-grad-08-b-isvalid.html
@@ -29,7 +29,7 @@
</defs>
<g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
- <style type="text/css">
+ <style>
@font-face {
font-family: Blocky;
src: url(woffs/Blocky.woff) format("woff");
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/render-elems-06-t-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/render-elems-06-t-isvalid.html
index fcbebe48d7c..f48ade43a3d 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/render-elems-06-t-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/render-elems-06-t-isvalid.html
@@ -34,7 +34,7 @@
<font-face-uri xlink:href="../resources/Blocky.svg#Blocky"/>
</font-face-src>
</font-face>
- <style type="text/css">
+ <style>
@font-face {
font-family: BlockyWoff;
src: url(woffs/Blocky.woff) format("woff");
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/render-elems-07-t-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/render-elems-07-t-isvalid.html
index a4a0cf575cf..bfb73171a5a 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/render-elems-07-t-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/render-elems-07-t-isvalid.html
@@ -34,7 +34,7 @@
<font-face-uri xlink:href="../resources/Blocky.svg#Blocky"/>
</font-face-src>
</font-face>
- <style type="text/css">
+ <style>
@font-face {
font-family: BlockyWoff;
src: url(woffs/Blocky.woff) format("woff");
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/render-elems-08-t-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/render-elems-08-t-isvalid.html
index 46f409cd5ad..9411b42c136 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/render-elems-08-t-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/render-elems-08-t-isvalid.html
@@ -34,7 +34,7 @@
<font-face-uri xlink:href="../resources/Blocky.svg#Blocky"/>
</font-face-src>
</font-face>
- <style type="text/css">
+ <style>
@font-face {
font-family: BlockyWoff;
src: url(woffs/Blocky.woff) format("woff");
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/render-groups-01-b-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/render-groups-01-b-isvalid.html
index a81e5c59fad..3aa02dc3529 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/render-groups-01-b-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/render-groups-01-b-isvalid.html
@@ -38,7 +38,7 @@
<glyph unicode="G" glyph-name="G" horiz-adv-x="367" d="M355 1H18V564H355V420H125V144H248V211H156V355H355V1Z"/>
<hkern g1="V" g2="G" k="-40"/>
</font>
- <style type="text/css">
+ <style>
@font-face {
font-family: anglepoise;
src: url(woffs/anglepoi.woff) format("woff");
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/render-groups-03-t-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/render-groups-03-t-isvalid.html
index 937a76c867e..257e005df2f 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/render-groups-03-t-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/render-groups-03-t-isvalid.html
@@ -38,7 +38,7 @@
<glyph unicode="G" glyph-name="G" horiz-adv-x="367" d="M355 1H18V564H355V420H125V144H248V211H156V355H355V1Z"/>
<hkern g1="V" g2="G" k="-40"/>
</font>
- <style type="text/css">
+ <style>
@font-face {
font-family: anglepoise;
src: url(woffs/anglepoi.woff) format("woff");
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-dom-13-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-dom-13-f-isvalid.html
index 3d1a44d4f3c..96cf66bf5ce 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-dom-13-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-dom-13-f-isvalid.html
@@ -29,7 +29,7 @@
</defs>
<g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
<defs>
- <style type="text/css">
+ <style>
.passed { fill: lime }
.failed { fill: red }
.result { font: 9px monospace; fill: black }
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-dom-16-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-dom-16-f-isvalid.html
index e16c3a55151..4d132e40a55 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-dom-16-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-dom-16-f-isvalid.html
@@ -31,7 +31,7 @@
<svg id="testSVG" />
<text id="failText" x="350" y="350" font-size="50" fill="red">FAIL</text>
<text id="passText" x="350" y="300" font-size="50" display="none">PASS</text>
- <script type="text/javascript">
+ <script>
<![CDATA[
try
{
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-dom-17-f-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-dom-17-f-novalid.html
index f24a537d0db..066e281baf1 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-dom-17-f-novalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-dom-17-f-novalid.html
@@ -37,7 +37,7 @@
<text id="failText" fill="red">FAIL</text>
<text id="passText" fill="green" display="none">PASS</text>
</g>
- <script type="text/javascript"><![CDATA[
+ <script><![CDATA[
try
{
var passedCount = 0;
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-dom-18-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-dom-18-f-isvalid.html
index 89c29539372..e6b23e25e81 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-dom-18-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-dom-18-f-isvalid.html
@@ -39,7 +39,7 @@
<text x="100" y="100" fill="black" id="testText">Filler text</text>
</svg>
<text id="failText" x="350" y="350" font-size="50" fill="red">FAIL</text>
- <script type="text/javascript"><![CDATA[
+ <script><![CDATA[
try
{
var passedCount = 0;
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-dom-19-f-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-dom-19-f-novalid.html
index 1dabbecde7f..a09f040d8bc 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-dom-19-f-novalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-dom-19-f-novalid.html
@@ -33,7 +33,7 @@
<text id="failText" fill="red">FAIL</text>
<text id="passText" fill="green" display="none">PASS</text>
</g>
- <script type="text/javascript"><![CDATA[
+ <script><![CDATA[
try
{
var passedCount = 0;
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-svg-01-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-svg-01-f-isvalid.html
index 24f927f9da9..db9226a9db5 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-svg-01-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-svg-01-f-isvalid.html
@@ -45,7 +45,7 @@
<text id="failText" x="350" y="350" font-size="50" fill="red">FAIL</text>
- <script type="text/javascript"><![CDATA[
+ <script><![CDATA[
try
{
var testSVG = document.getElementById("testSVG");
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-svg-02-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-svg-02-f-isvalid.html
index b5a4b3f49f7..27753f5d351 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-svg-02-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-svg-02-f-isvalid.html
@@ -42,7 +42,7 @@
<!-- Cover the whole testframe with a simple visual result -->
<rect id="status" width="100%" height="100%" fill="none"/>
- <script type="text/javascript"><![CDATA[
+ <script><![CDATA[
var passes = 0;
var ypos = 50;
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-use-10-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-use-10-f-isvalid.html
index f2da4cd7ece..f477b90a185 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-use-10-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-use-10-f-isvalid.html
@@ -28,7 +28,7 @@
</font-face>
</defs>
<g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
- <style type="text/css">
+ <style>
/* low specificity */
defs &gt; rect {
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-use-11-f-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-use-11-f-novalid.html
index ad303ba7c29..4123aa95a3d 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-use-11-f-novalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-use-11-f-novalid.html
@@ -29,7 +29,7 @@
</defs>
<g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
- <style type="text/css"><![CDATA[
+ <style><![CDATA[
#testId.test1
{
fill: blue;
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-use-14-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-use-14-f-isvalid.html
index 6812e604282..1b634d40b2e 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-use-14-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-use-14-f-isvalid.html
@@ -33,7 +33,7 @@
</defs>
<rect width="100" height="100" fill="red"/>
<use xlink:href="#pass" />
- <script type="text/javascript"><![CDATA[
+ <script><![CDATA[
try
{
var test = document.getElementById("test");
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-use-15-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-use-15-f-isvalid.html
index 2dd2cea81a7..afcef4d179f 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-use-15-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/struct-use-15-f-isvalid.html
@@ -34,7 +34,7 @@
<use xlink:href="#testG" id="testUse1" />
</defs>
<use xlink:href="#testUse1" />
- <script type="text/javascript"><![CDATA[
+ <script><![CDATA[
try
{
var testG = document.getElementById("testG");
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-class-01-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-class-01-f-isvalid.html
index 923205d9150..e680f21e10b 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-class-01-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-class-01-f-isvalid.html
@@ -29,7 +29,7 @@
</defs>
<g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
- <style type="text/css"><![CDATA[
+ <style><![CDATA[
.testClass
{
fill: blue;
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-01-b-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-01-b-isvalid.html
index e5e0ab36043..a8d14dd7edb 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-01-b-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-01-b-isvalid.html
@@ -30,7 +30,7 @@
<g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
<defs>
<defs>
- <style type="text/css">
+ <style>
rect { fill: green }
.warning { fill: green }
.bar {fill: green}
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-02-b-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-02-b-isvalid.html
index 6845ede211d..a0dab05de68 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-02-b-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-02-b-isvalid.html
@@ -29,7 +29,7 @@
</defs>
<g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
<defs>
- <style type="text/css">
+ <style>
#one, #two { fill: green }
[transform="scale(2)"] { fill: green }
#x [points] { fill: green }
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-03-b-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-03-b-isvalid.html
index 2bc98ea6ce5..1bb7a532f2d 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-03-b-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-03-b-isvalid.html
@@ -30,7 +30,7 @@
<g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
<defs>
- <style type="text/css">
+ <style>
.mummy {fill: green } /* least specific */
.mummy rect { fill: red} /* more specific, make rect red */
.mummy &gt; .thischild { fill: green } /* even more specific, rect green */
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-04-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-04-f-isvalid.html
index e9aeb2e1632..11f71118986 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-04-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-04-f-isvalid.html
@@ -31,7 +31,7 @@
<g fill="white">
<text x="240" y="35" font-size="20" text-anchor="middle">CSS selector test</text>
<defs>
- <style type="text/css">
+ <style>
* {stroke:red; stroke-width:1;} /* 0 */
text {stroke:none; fill:black;} /* 1 */
rect {stroke:black; stroke-dasharray:none;} /* 1 */
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-05-b-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-05-b-isvalid.html
index 9b831845f6a..74c7d79e9f9 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-05-b-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-05-b-isvalid.html
@@ -33,7 +33,7 @@
</font-face>
</defs>
<g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
- <style type="text/css">
+ <style>
:lang(en) { fill: green}
:lang(fr) { fill: blue }
:lang(fr-ca) {font-style: italic}
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-06-b-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-06-b-isvalid.html
index 2767329013e..12645819492 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-06-b-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-06-b-isvalid.html
@@ -28,7 +28,7 @@
</font-face>
</defs>
<g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
- <style type="text/css">
+ <style>
svg:hover {fill: none}
text {fill: black}
:link {fill: #33F}
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-08-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-08-f-isvalid.html
index ab31884c8a1..bbdc60d00aa 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-08-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-08-f-isvalid.html
@@ -29,7 +29,7 @@
</defs>
<g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
- <style type="text/css"><![CDATA[
+ <style><![CDATA[
path
{
visibility: hidden;
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-09-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-09-f-isvalid.html
index f7e053ef682..3948d56820c 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-09-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-09-f-isvalid.html
@@ -28,7 +28,7 @@
</font-face>
</defs>
<g id="test-body-content" font-size="18">
- <style type="text/css"><![CDATA[
+ <style><![CDATA[
@import url("../images/selector-types-visibility-hidden.css");]]>
</style>
<path class="reference" d="M 50 125 L 150 125 L 100 75 z" fill="blue" visibility="hidden"/>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-10-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-10-f-isvalid.html
index 1f2f2ff2ab1..e1c9b207667 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-10-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-css-10-f-isvalid.html
@@ -36,7 +36,7 @@
<circle id="c" fill="blue" cx="140" cy="220" r="50"/>
<circle id="d" fill="blue" cx="340" cy="220" r="50"/>
- <style type="text/css">
+ <style>
@import url("../images/case-insensitivity.css");
#c {fill: red }
#c {FiLl: oRaNgE }
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-pres-04-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-pres-04-f-isvalid.html
index 6ddcdb289ef..ef28674e3a7 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-pres-04-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-pres-04-f-isvalid.html
@@ -29,7 +29,7 @@
</defs>
<g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
- <style type="text/css"><![CDATA[
+ <style><![CDATA[
path
{
fill: green;
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-pres-05-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-pres-05-f-isvalid.html
index 226dc0db47c..a0846c013dd 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-pres-05-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/styling-pres-05-f-isvalid.html
@@ -29,7 +29,7 @@
</defs>
<g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
- <style type="text/css"><![CDATA[
+ <style><![CDATA[
@import url("../images/selector-types-fill-green.css");]]>
</style>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-align-08-b-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-align-08-b-isvalid.html
index d94599332e5..48ee3df86a4 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-align-08-b-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-align-08-b-isvalid.html
@@ -35,7 +35,7 @@
</font-face-src>
</font-face>
</defs>
- <style type="text/css">
+ <style>
@font-face {
font-family: Tribase ;
src: url(woffs/Tribase.woff) format("woff");
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-dom-02-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-dom-02-f-isvalid.html
index da0d7228b3c..d70ffc665c2 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-dom-02-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-dom-02-f-isvalid.html
@@ -35,7 +35,7 @@
<font-face-uri xlink:href="../resources/Plane1/PlaneOne.svg#SPlaneOne"/>
</font-face-src>
</font-face>
- <style type="text/css">
+ <style>
@font-face {
font-family: PlaneOne;
src: url(woffs/PlaneOne.woff) format("woff");
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-dom-05-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-dom-05-f-isvalid.html
index af843569ba6..5849399cdc2 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-dom-05-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-dom-05-f-isvalid.html
@@ -35,7 +35,7 @@
<font-face-uri xlink:href="../resources/Plane1/PlaneOne.svg#SPlaneOne"/>
</font-face-src>
</font-face>
- <style type="text/css">
+ <style>
@font-face {
font-family: PlaneOne;
src: url(woffs/PlaneOne.woff) format("woff");
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-fonts-204-t-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-fonts-204-t-isvalid.html
index 7a4b1d63ead..26f5f710cb5 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-fonts-204-t-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-fonts-204-t-isvalid.html
@@ -31,7 +31,7 @@
</defs>
<g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
<defs>
- <style type="text/css">
+ <style>
@font-face {
font-family: ZC;
unicode-range: U+0-7F;
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-intro-06-t-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-intro-06-t-isvalid.html
index 48b50d8d42c..033de9d7451 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-intro-06-t-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-intro-06-t-isvalid.html
@@ -20,7 +20,7 @@
<!--======================================================================-->
<title id="test-title">$RCSfile: text-intro-06-t.svg,v $</title>
- <style type="text/css">
+ <style>
@font-face {
font-family: Scheherezade;
src: url(woffs/ScheherazadeRegOT.woff) format("woff")
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-intro-09-b-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-intro-09-b-isvalid.html
index d6c6f8d325a..1b500ec07e1 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-intro-09-b-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-intro-09-b-isvalid.html
@@ -21,7 +21,7 @@
<title id="test-title">$RCSfile: text-intro-09-b.svg,v $</title>
<defs>
- <style type="text/css">
+ <style>
@font-face {
font-family: Ezra SIL SR;
src: url(woffs/EzraSILSR.woff) format("woff");
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-intro-12-t-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-intro-12-t-isvalid.html
index a2d65e1893b..30203c99215 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-intro-12-t-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-intro-12-t-isvalid.html
@@ -28,7 +28,7 @@
</font-face>
</defs>
<g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
- <style type="text/css">
+ <style>
@font-face {
font-family: Scheherazade;
src: url(woffs/ScheherazadeRegOT.woff) format("woff");
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-path-02-b-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-path-02-b-isvalid.html
index 48dea56fb8e..5a0ca938af8 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-path-02-b-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-path-02-b-isvalid.html
@@ -29,7 +29,7 @@
</defs>
<g id="test-body-content" font-family="SVGFreeSansASCII, FreeSansWoff, sans-serif" font-size="18">
<defs>
- <style type="text/css">
+ <style>
@font-face {
font-family: FreeSansWoff;
src: url(woffs/FreeSans.woff) format("woff");
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-text-04-t-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-text-04-t-isvalid.html
index ab06f0f36f8..91319e57b41 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-text-04-t-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-text-04-t-isvalid.html
@@ -20,7 +20,7 @@
<!--======================================================================-->
<title id="test-title">$RCSfile: text-text-04-t.svg,v $</title>
- <style type="text/css">
+ <style>
@font-face {
font-family: embeded;
src: url(woffs/embeded-text-text-04.woff) format("woff");
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-text-05-t-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-text-05-t-isvalid.html
index 9dd6b49b8d0..8575bf4398a 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-text-05-t-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-text-05-t-isvalid.html
@@ -28,7 +28,7 @@
</font-face>
</defs>
<g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
- <style type="text/css">
+ <style>
@font-face {
font-family: embeded;
src: url(woffs/embeded-text-text-05.woff) format("woff");
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-text-06-t-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-text-06-t-isvalid.html
index 823cbb68db8..0d97c013f77 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-text-06-t-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-text-06-t-isvalid.html
@@ -28,7 +28,7 @@
</font-face>
</defs>
<g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
- <style type="text/css">
+ <style>
@font-face {
font-family: embeded;
src: url(woffs/embeded-text-text-06.woff) format("woff");
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-text-12-t-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-text-12-t-isvalid.html
index d28fd0745dc..c92eb2e74ec 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-text-12-t-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-text-12-t-isvalid.html
@@ -28,7 +28,7 @@
</font-face>
</defs>
<g id="test-body-content" font-family="SVGFreeSansASCII,sans-serif" font-size="18">
- <style type="text/css">
+ <style>
@font-face {
font-family: embeded;
src: url(woffs/embeded-text-text-05.woff) format("woff");
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-tselect-03-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-tselect-03-f-isvalid.html
index 6ce8758c73f..b59de9d1221 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-tselect-03-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/text-tselect-03-f-isvalid.html
@@ -21,7 +21,7 @@
<title id="test-title">$RCSfile: text-tselect-03-f.svg,v $</title>
<defs>
- <style type="text/css">
+ <style>
@font-face {
font-family: Ezra SIL SR;
src: url(woffs/EzraSILSR.woff) format("woff");
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/types-dom-svgfittoviewbox-01-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/types-dom-svgfittoviewbox-01-f-isvalid.html
index a4ec2b6a648..e158b9d8f00 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/types-dom-svgfittoviewbox-01-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/types-dom-svgfittoviewbox-01-f-isvalid.html
@@ -31,7 +31,7 @@
<svg id="testSvg" viewBox="0 0 300 200" preserveAspectRatio="xMinYMin slice" />
<text id="failText" x="100" y="100" font-size="80" fill="red">FAIL</text>
<text id="passText" x="350" y="300" font-size="50" display="none">PASS</text>
- <script type="text/javascript">
+ <script>
<![CDATA[
try
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/types-dom-svglengthlist-01-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/types-dom-svglengthlist-01-f-isvalid.html
index 1b0470c23fe..a6638a77190 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/types-dom-svglengthlist-01-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/types-dom-svglengthlist-01-f-isvalid.html
@@ -31,7 +31,7 @@
<text id="failText" fill="red">FAIL</text>
<text id="passText" fill="green" display="none">PASS</text>
</g>
- <script type="text/javascript"><![CDATA[
+ <script><![CDATA[
try
{
var testElement = document.getElementById("test");
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/types-dom-svgnumberlist-01-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/types-dom-svgnumberlist-01-f-isvalid.html
index 7dbda069fc4..7590ecb8a76 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/types-dom-svgnumberlist-01-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/types-dom-svgnumberlist-01-f-isvalid.html
@@ -31,7 +31,7 @@
<text id="failText" fill="red">FAIL</text>
<text id="passText" fill="green" display="none">PASS</text>
</g>
- <script type="text/javascript"><![CDATA[
+ <script><![CDATA[
try
{
var testElement = document.getElementById("test");
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/types-dom-svgstringlist-01-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/types-dom-svgstringlist-01-f-isvalid.html
index f1ad11693eb..0118e068781 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/types-dom-svgstringlist-01-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/types-dom-svgstringlist-01-f-isvalid.html
@@ -31,7 +31,7 @@
<text id="failText" fill="red">FAIL</text>
<text id="passText" fill="green" display="none">PASS</text>
</g>
- <script type="text/javascript"><![CDATA[
+ <script><![CDATA[
try
{
var testElement = document.getElementById("test");
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/types-dom-svgtransformable-01-f-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/types-dom-svgtransformable-01-f-isvalid.html
index c9ba4eb8425..2e526069738 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html-svg/types-dom-svgtransformable-01-f-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-svg/types-dom-svgtransformable-01-f-isvalid.html
@@ -31,7 +31,7 @@
<text id="failText" fill="red">FAIL</text>
<text id="passText" fill="green" display="none">PASS</text>
</g>
- <script type="text/javascript"><![CDATA[
+ <script><![CDATA[
try
{
var testElement = document.getElementById("test");
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/html-spec-comms-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/html-spec-comms-isvalid.html
new file mode 100644
index 00000000000..69f70d5d667
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/html-spec-comms-isvalid.html
@@ -0,0 +1,276 @@
+<!DOCTYPE html><html class=split lang=en-US-x-hixie><script src=/link-fixup.js defer=""></script><meta charset=utf-8><meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name=viewport><title>HTML Standard</title><meta content=#3c790a name=theme-color><link rel=stylesheet href=https://resources.whatwg.org/standard.css><link rel=icon href=https://resources.whatwg.org/logo.svg><script>
+ function toggleStatus(div) {
+ div.parentNode.classList.toggle('wrapped');
+ }
+ </script><style>
+ .status { min-height: 0.6em; font: 1em sans-serif; width: 9em; padding: 0.3em; position: absolute; z-index: 8; right: 0.3em; background: #EEE; color: black; box-shadow: 0 0 3px #999; overflow: hidden; margin: -2em 0 0 0; border-collapse: initial; border-spacing: initial; }
+ .status:hover { z-index: 9; }
+ .status:focus-within { z-index: 9; }
+ .status.wrapped > :not(input) { display: none; }
+ .status > input { position: absolute; left: 0; top: 0; width: 1em; height: 1em; border: none; background: transparent; padding: 0; margin: 0; }
+ .status > p { font-size: 0.6em; margin: 0; padding: 0; }
+ .status > p + p { padding-top: 0.5em; }
+ .status > p > strong { margin-left: 1.5em; }
+ .status > .support { display: block; }
+ .status > .support > span { padding: 0.2em 0; display: block; display: table; }
+ .status > .support > span.partial { color: #666666; filter: grayscale(50%); }
+ .status > .support > span.no { color: #CCCCCC; filter: grayscale(100%); }
+ .status > .support > span.no::before { opacity: 0.5; }
+ .status > .support > span:first-of-type { padding-top: 0.5em; }
+ .status > .support > span > span { padding: 0 0.5em; display: table-cell; vertical-align: top; }
+ .status > .support > span > span:first-child { width: 100%; }
+ .status > .support > span > span:last-child { width: 100%; white-space: pre; padding: 0; }
+ .status > .support > span::before { content: ' '; display: table-cell; min-width: 1.5em; height: 1.5em; background: no-repeat center center; background-size: contain; text-align: right; font-size: 0.75em; font-weight: bold; }
+ .status > .support > .and_chr::before { background-image: url(https://resources.whatwg.org/browser-logos/chrome.svg); }
+ .status > .support > .and_ff::before { background-image: url(https://resources.whatwg.org/browser-logos/firefox.png); }
+ .status > .support > .and_uc::before { background-image: url(https://resources.whatwg.org/browser-logos/uc.png); } /* UC Browser for Android */
+ .status > .support > .android::before { background-image: url(https://resources.whatwg.org/browser-logos/android.svg); }
+ .status > .support > .bb::before { background-image: url(https://resources.whatwg.org/browser-logos/bb.jpg); } /* Blackberry Browser */
+ .status > .support > .chrome::before { background-image: url(https://resources.whatwg.org/browser-logos/chrome.svg); }
+ .status > .support > .edge::before { background-image: url(https://resources.whatwg.org/browser-logos/edge.svg); }
+ .status > .support > .firefox::before { background-image: url(https://resources.whatwg.org/browser-logos/firefox.png); }
+ .status > .support > .ie::before { background-image: url(https://resources.whatwg.org/browser-logos/ie.png); }
+ .status > .support > .ie_mob::before { background-image: url(https://resources.whatwg.org/browser-logos/ie-mobile.svg); }
+ .status > .support > .ios_saf::before { background-image: url(https://resources.whatwg.org/browser-logos/safari-ios.svg); }
+ .status > .support > .op_mini::before { background-image: url(https://resources.whatwg.org/browser-logos/opera-mini.png); }
+ .status > .support > .op_mob::before { background-image: url(https://resources.whatwg.org/browser-logos/opera.png); }
+ .status > .support > .opera::before { background-image: url(https://resources.whatwg.org/browser-logos/opera.png); }
+ .status > .support > .safari::before { background-image: url(https://resources.whatwg.org/browser-logos/safari.png); }
+ .status > .support > .samsung::before { background-image: url(https://resources.whatwg.org/browser-logos/samsung.png); }
+ .status > .caniuse { text-align: right; font-style: italic; width: 100%; }
+ .status > .caniuse + p { margin-top: 0.5em; border-top: 1px solid silver; }
+
+ @media (max-width: 767px) {
+ .status { right: -9em; }
+ }
+ </style><style>
+ [hidden] { display: none; }
+
+ .bad, .bad *:not(.X\58X) { color: gray; border-color: gray; background: transparent; }
+
+ .fingerprint { position: absolute; right: 0; z-index: 5; }
+ @media (max-width: 767px) {
+ .fingerprint { max-width: 35px; }
+ }
+
+ .applies .yes, .yesno .yes { background: yellow; }
+ .yesno .yes, .yesno .no { text-align: center; }
+
+ .applies thead th > * { display: block; }
+ .applies thead code { display: block; }
+ .applies td { text-align: center; }
+
+ .matrix, .matrix td { border: hidden; text-align: right; }
+ .matrix { margin-left: 2em; }
+
+ .vertical-summary-table tr > th[rowspan="2"]:first-child + th,
+ .vertical-summary-table tr > td[rowspan="2"]:first-child + td { border-bottom: hidden; }
+
+ .dice-example { border-collapse: collapse; border-style: hidden solid solid hidden; border-width: thin; margin-left: 3em; }
+ .dice-example caption { width: 30em; font-size: smaller; font-style: italic; padding: 0.75em 0; text-align: left; }
+ .dice-example td, .dice-example th { border: solid thin; width: 1.35em; height: 1.05em; text-align: center; padding: 0; }
+
+ td.eg { border-width: thin; text-align: center; }
+
+ #table-example-1 { border: solid thin; border-collapse: collapse; margin-left: 3em; }
+ #table-example-1 caption { padding-bottom: 0.5em; }
+ #table-example-1 thead, #table-example-1 tbody { border: none; }
+ #table-example-1 th, #table-example-1 td { border: solid thin; }
+ #table-example-1 th { font-weight: normal; }
+ #table-example-1 td { border-style: none solid; vertical-align: top; }
+ #table-example-1 th { padding: 0.5em; vertical-align: middle; text-align: center; }
+ #table-example-1 tbody tr:first-child td { padding-top: 0.5em; }
+ #table-example-1 tbody tr:last-child td { padding-bottom: 1.5em; }
+ #table-example-1 tbody td:first-child { padding-left: 2.5em; padding-right: 0; width: 9em; }
+ #table-example-1 tbody td:first-child::after { content: leader(". "); }
+ #table-example-1 tbody td { padding-left: 2em; padding-right: 2em; }
+ #table-example-1 tbody td:first-child + td { width: 10em; }
+ #table-example-1 tbody td:first-child + td ~ td { width: 2.5em; }
+ #table-example-1 tbody td:first-child + td + td + td ~ td { width: 1.25em; }
+
+ .apple-table-examples { border: none; border-collapse: separate; border-spacing: 1.5em 0em; width: 40em; margin-left: 3em; }
+ .apple-table-examples * { font-family: "Times", serif; }
+ .apple-table-examples td, .apple-table-examples th { border: none; white-space: nowrap; padding-top: 0; padding-bottom: 0; }
+ .apple-table-examples tbody th:first-child { border-left: none; width: 100%; }
+ .apple-table-examples thead th:first-child ~ th { font-size: smaller; font-weight: bolder; border-bottom: solid 2px; text-align: center; }
+ .apple-table-examples tbody th::after, .apple-table-examples tfoot th::after { content: leader(". ") }
+ .apple-table-examples tbody th, .apple-table-examples tfoot th { font: inherit; text-align: left; }
+ .apple-table-examples td { text-align: right; vertical-align: top; }
+ .apple-table-examples.e1 tbody tr:last-child td { border-bottom: solid 1px; }
+ .apple-table-examples.e1 tbody + tbody tr:last-child td { border-bottom: double 3px; }
+ .apple-table-examples.e2 th[scope=row] { padding-left: 1em; }
+ .apple-table-examples sup { line-height: 0; }
+
+ .three-column-nowrap tr > td:first-child,
+ .three-column-nowrap tr > td:first-child + td,
+ .three-column-nowrap tr > td:first-child + td + td { white-space: nowrap; }
+
+ .details-example img { vertical-align: top; }
+
+ .parse-error-table td > p:first-child { margin-top: 0; }
+
+ #named-character-references-table {
+ white-space: nowrap;
+ font-size: 0.6em;
+ column-width: 30em;
+ column-gap: 1em;
+ -moz-column-width: 30em;
+ -moz-column-gap: 1em;
+ -webkit-column-width: 30em;
+ -webkit-column-gap: 1em;
+ }
+ #named-character-references-table > table > tbody > tr > td:first-child + td,
+ #named-character-references-table > table > tbody > tr > td:last-child { text-align: center; }
+ #named-character-references-table > table > tbody > tr > td:last-child:hover > span { position: absolute; top: auto; left: auto; margin-left: 0.5em; line-height: 1.2; font-size: 5em; border: outset; padding: 0.25em 0.5em; background: white; width: 1.25em; height: auto; text-align: center; }
+ #named-character-references-table > table > tbody > tr#entity-CounterClockwiseContourIntegral > td:first-child { font-size: 0.5em; }
+
+ .glyph.control { color: red; }
+
+ #table-example-1 * { font-family: "Essays1743", serif; line-height: 1.01em; }
+ @font-face {
+ font-family: 'Essays1743';
+ src: url('/fonts/Essays1743.ttf');
+ }
+ @font-face {
+ font-family: 'Essays1743';
+ font-weight: bold;
+ src: url('/fonts/Essays1743-Bold.ttf');
+ }
+ @font-face {
+ font-family: 'Essays1743';
+ font-style: italic;
+ src: url('/fonts/Essays1743-Italic.ttf');
+ }
+ @font-face {
+ font-family: 'Essays1743';
+ font-style: italic;
+ font-weight: bold;
+ src: url('/fonts/Essays1743-BoldItalic.ttf');
+ }
+
+ @media (max-width: 767px) {
+ #abstractimg { width: 100%; }
+ }
+ #abstractimg, #abstractimg text { font: inherit; }
+ #abstractimg rect { fill: #424242; }
+ #abstractimg text { fill: #ffffff; font-size: 18px }
+ #abstractimg .top { word-spacing: 50px; text-anchor: middle; }
+ #abstractimg .left, #abstractimg .bottom { word-spacing: 12px; }
+ #abstractimg .right { font-size: 25px; }
+ </style><body>
+
+ <script async="" src=/html-dfn.js></script>
+ <script data-file-issue-url=https://github.com/whatwg/html/issues/new src=https://resources.whatwg.org/file-issue.js async=""></script>
+ <header id=head class="head with-buttons">
+ <a href=https://whatwg.org/ class=logo><img alt=WHATWG src=https://resources.whatwg.org/logo.svg width=100 height=100></a>
+ <h1 class=allcaps>HTML</h1><h2 id=living-standard class="no-num no-toc">Living Standard — Last Updated <span class=pubdate>9 December 2017</span></h2>
+
+
+
+
+ </header>
+
+
+
+
+
+
+
+
+
+
+
+ <nav><a href=imagebitmap-and-animations.html>← 8.8 Images</a> — <a href=./>Table of Contents</a> — <a href=server-sent-events.html>9.2 Server-sent events →</a></nav><ol class=toc><li id=toc-comms><a href=comms.html#comms><span class=secno>9</span> Communication</a><ol><li><a href=comms.html#the-messageevent-interface><span class=secno>9.1</span> The <code>MessageEvent</code> interface</a></ol></ol><h2 id=comms><span class=secno>9</span> Communication<a href=#comms class=self-link></a></h2>
+
+ <h3 id=the-messageevent-interface><span class=secno>9.1</span> The <code id=the-messageevent-interface:messageevent><a href=#messageevent>MessageEvent</a></code> interface<a href=#the-messageevent-interface class=self-link></a></h3>
+
+ <p>Messages in <a id=the-messageevent-interface:server-sent-events href=server-sent-events.html#server-sent-events>server-sent events</a>, <a id=the-messageevent-interface:network href=web-sockets.html#network>Web sockets</a>, <a id=the-messageevent-interface:web-messaging href=web-messaging.html#web-messaging>cross-document
+ messaging</a>, <a id=the-messageevent-interface:channel-messaging href=web-messaging.html#channel-messaging>channel messaging</a>, and <a id=the-messageevent-interface:broadcasting-to-other-browsing-contexts href=web-messaging.html#broadcasting-to-other-browsing-contexts>broadcast channels</a> use the
+ <code id=the-messageevent-interface:messageevent-2><a href=#messageevent>MessageEvent</a></code> interface for their <code id=the-messageevent-interface:event-message><a href=indices.html#event-message>message</a></code>
+ events:</p>
+
+ <pre class=idl>[Constructor(DOMString type, optional <a href=#messageeventinit id=the-messageevent-interface:messageeventinit>MessageEventInit</a> eventInitDict), Exposed=(Window,Worker,AudioWorklet)]
+interface <dfn id=messageevent>MessageEvent</dfn> : <a id=the-messageevent-interface:event href=https://dom.spec.whatwg.org/#interface-event data-x-internal=event>Event</a> {
+ readonly attribute any <a href=#dom-messageevent-data id=the-messageevent-interface:dom-messageevent-data>data</a>;
+ readonly attribute USVString <a href=#dom-messageevent-origin id=the-messageevent-interface:dom-messageevent-origin>origin</a>;
+ readonly attribute DOMString <a href=#dom-messageevent-lasteventid id=the-messageevent-interface:dom-messageevent-lasteventid>lastEventId</a>;
+ readonly attribute <a href=#messageeventsource id=the-messageevent-interface:messageeventsource>MessageEventSource</a>? <a href=#dom-messageevent-source id=the-messageevent-interface:dom-messageevent-source>source</a>;
+ readonly attribute FrozenArray&lt;<a id=the-messageevent-interface:messageport href=web-messaging.html#messageport>MessagePort</a>> <a href=#dom-messageevent-ports id=the-messageevent-interface:dom-messageevent-ports>ports</a>;
+
+ void <a href=#dom-messageevent-initmessageevent id=the-messageevent-interface:dom-messageevent-initmessageevent>initMessageEvent</a>(DOMString type, optional boolean bubbles = false, optional boolean cancelable = false, optional any data = null, optional USVString origin = "", optional DOMString lastEventId = "", optional <a href=#messageeventsource id=the-messageevent-interface:messageeventsource-2>MessageEventSource</a>? source = null, optional sequence&lt;<a id=the-messageevent-interface:messageport-2 href=web-messaging.html#messageport>MessagePort</a>> ports = []);
+};
+
+dictionary <dfn id=messageeventinit>MessageEventInit</dfn> : <a id=the-messageevent-interface:eventinit href=https://dom.spec.whatwg.org/#dictdef-eventinit data-x-internal=eventinit>EventInit</a> {
+ any data = null;
+ USVString origin = "";
+ DOMString lastEventId = "";
+ <a href=#messageeventsource id=the-messageevent-interface:messageeventsource-3>MessageEventSource</a>? source = null;
+ sequence&lt;<a id=the-messageevent-interface:messageport-3 href=web-messaging.html#messageport>MessagePort</a>> ports = [];
+};
+
+typedef (<a id=the-messageevent-interface:windowproxy href=window-object.html#windowproxy>WindowProxy</a> or <a id=the-messageevent-interface:messageport-4 href=web-messaging.html#messageport>MessagePort</a> or <a id=the-messageevent-interface:serviceworker href=https://w3c.github.io/ServiceWorker/#serviceworker data-x-internal=serviceworker>ServiceWorker</a>) <dfn id=messageeventsource>MessageEventSource</dfn>;</pre>
+
+ <dl class=domintro><dt><var>event</var> . <code id=dom-messageevent-data-dev><a href=#dom-messageevent-data>data</a></code><dd>
+
+ <p>Returns the data of the message.</p>
+
+ <dt><var>event</var> . <code id=dom-messageevent-origin-dev><a href=#dom-messageevent-origin>origin</a></code><dd>
+
+ <p>Returns the origin of the message, for <a id=the-messageevent-interface:server-sent-events-2 href=server-sent-events.html#server-sent-events>server-sent events</a> and
+ <a id=the-messageevent-interface:web-messaging-2 href=web-messaging.html#web-messaging>cross-document messaging</a>.</p>
+
+ <dt><var>event</var> . <code id=dom-messageevent-lasteventid-dev><a href=#dom-messageevent-lasteventid>lastEventId</a></code><dd>
+
+ <p>Returns the <a href=server-sent-events.html#concept-event-stream-last-event-id id=the-messageevent-interface:concept-event-stream-last-event-id>last event ID string</a>, for
+ <a id=the-messageevent-interface:server-sent-events-3 href=server-sent-events.html#server-sent-events>server-sent events</a>.</p>
+
+ <dt><var>event</var> . <code id=dom-messageevent-source-dev><a href=#dom-messageevent-source>source</a></code><dd>
+
+ <p>Returns the <code id=the-messageevent-interface:windowproxy-2><a href=window-object.html#windowproxy>WindowProxy</a></code> of the source window, for <a id=the-messageevent-interface:web-messaging-3 href=web-messaging.html#web-messaging>cross-document
+ messaging</a>, and the <code id=the-messageevent-interface:messageport-5><a href=web-messaging.html#messageport>MessagePort</a></code> being attached, in the <code id=the-messageevent-interface:event-workerglobalscope-connect><a href=indices.html#event-workerglobalscope-connect>connect</a></code> event fired at
+ <code id=the-messageevent-interface:sharedworkerglobalscope><a href=workers.html#sharedworkerglobalscope>SharedWorkerGlobalScope</a></code> objects.</p>
+
+ <dt><var>event</var> . <code id=dom-messageevent-ports-dev><a href=#dom-messageevent-ports>ports</a></code><dd>
+
+ <p>Returns the <code id=the-messageevent-interface:messageport-6><a href=web-messaging.html#messageport>MessagePort</a></code> array sent with the message, for <a id=the-messageevent-interface:web-messaging-4 href=web-messaging.html#web-messaging>cross-document
+ messaging</a> and <a id=the-messageevent-interface:channel-messaging-2 href=web-messaging.html#channel-messaging>channel messaging</a>.</p>
+
+ </dl>
+
+
+
+ <p>The <dfn id=dom-messageevent-data><code>data</code></dfn> attribute must return the value
+ it was initialized to. It represents the message being sent.</p>
+
+ <p>The <dfn id=dom-messageevent-origin><code>origin</code></dfn> attribute must return the
+ value it was initialized to. It represents, in <a id=the-messageevent-interface:server-sent-events-4 href=server-sent-events.html#server-sent-events>server-sent events</a> and
+ <a id=the-messageevent-interface:web-messaging-5 href=web-messaging.html#web-messaging>cross-document messaging</a>, the <a id=the-messageevent-interface:concept-origin href=origin.html#concept-origin>origin</a> of the document that sent the
+ message (typically the scheme, hostname, and port of the document, but not its path or <a href=https://url.spec.whatwg.org/#concept-url-fragment id=the-messageevent-interface:concept-url-fragment data-x-internal=concept-url-fragment>fragment</a>).</p>
+
+ <p>The <dfn id=dom-messageevent-lasteventid><code>lastEventId</code></dfn> attribute must
+ return the value it was initialized to. It represents, in <a id=the-messageevent-interface:server-sent-events-5 href=server-sent-events.html#server-sent-events>server-sent events</a>, the
+ <a href=server-sent-events.html#concept-event-stream-last-event-id id=the-messageevent-interface:concept-event-stream-last-event-id-2>last event ID string</a> of the event
+ source.</p>
+
+ <p>The <dfn id=dom-messageevent-source><code>source</code></dfn> attribute must return the
+ value it was initialized to. It represents, in <a id=the-messageevent-interface:web-messaging-6 href=web-messaging.html#web-messaging>cross-document messaging</a>, the
+ <code id=the-messageevent-interface:windowproxy-3><a href=window-object.html#windowproxy>WindowProxy</a></code> of the <a id=the-messageevent-interface:browsing-context href=browsers.html#browsing-context>browsing context</a> of the <code id=the-messageevent-interface:window><a href=window-object.html#window>Window</a></code> object
+ from which the message came; and in the <code id=the-messageevent-interface:event-workerglobalscope-connect-2><a href=indices.html#event-workerglobalscope-connect>connect</a></code> events used by <a href=workers.html#sharedworkerglobalscope id=the-messageevent-interface:sharedworkerglobalscope-2>shared workers</a>, the newly connecting
+ <code id=the-messageevent-interface:messageport-7><a href=web-messaging.html#messageport>MessagePort</a></code>.</p>
+
+ <p>The <dfn id=dom-messageevent-ports><code>ports</code></dfn> attribute must return the
+ value it was initialized to. It represents, in <a id=the-messageevent-interface:web-messaging-7 href=web-messaging.html#web-messaging>cross-document messaging</a> and
+ <a id=the-messageevent-interface:channel-messaging-3 href=web-messaging.html#channel-messaging>channel messaging</a>, the <code id=the-messageevent-interface:messageport-8><a href=web-messaging.html#messageport>MessagePort</a></code> array being sent.</p>
+
+
+ <p>The <dfn id=dom-messageevent-initmessageevent><code>initMessageEvent()</code></dfn>
+ method must initialize the event in a manner analogous to the similarly-named <code id=the-messageevent-interface:dom-event-initevent><a data-x-internal=dom-event-initevent href=https://dom.spec.whatwg.org/#dom-event-initevent>initEvent()</a></code> method. <a href=references.html#refsDOM>[DOM]</a></p>
+
+
+
+ <p class=note>Various APIs (e.g., <code id=the-messageevent-interface:websocket><a href=web-sockets.html#websocket>WebSocket</a></code>, <code id=the-messageevent-interface:eventsource><a href=server-sent-events.html#eventsource>EventSource</a></code>) use the
+ <code id=the-messageevent-interface:messageevent-3><a href=#messageevent>MessageEvent</a></code> interface for their <code id=the-messageevent-interface:event-message-2><a href=indices.html#event-message>message</a></code> event
+ without using the <code id=the-messageevent-interface:messageport-9><a href=web-messaging.html#messageport>MessagePort</a></code> API.</p>
+
+
+ <nav><a href=imagebitmap-and-animations.html>← 8.8 Images</a> — <a href=./>Table of Contents</a> — <a href=server-sent-events.html>9.2 Server-sent events →</a></nav>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/model-isvalid.html
index f0dd1c23fd1..e55c3e94ec0 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/model-isvalid.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/model-isvalid.html
@@ -4,15 +4,12 @@
<style>
<!--
-Something or other
+.hasFocus { border: 2px solid red; }
-->
</style>
<meta charset=utf-8>
<title>&lt;STYLE&gt;s</title>
- <style type="application/vnd.nonsense" title="My Style">
- Something or other
- </style>
</head>
<body>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/type-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/type-novalid.html
new file mode 100644
index 00000000000..f977b1790ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/type-novalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;STYLE&gt;s</title>
+ <style type="application/vnd.nonsense" title="My Style">
+ Something or other
+ </style>
+</head>
+<body>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/index.html b/tests/wpt/web-platform-tests/conformance-checkers/index.html
index 2dadc40cf1f..fbf944a3cdf 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/index.html
+++ b/tests/wpt/web-platform-tests/conformance-checkers/index.html
@@ -14,7 +14,7 @@
<p>Curious committers should see the makefile.
-<style type="text/css">
+<style>
html {
background: #DDE5D9 url(data:image/gif;base64,R0lGODlhBAAEAIAAANra2v///yH5BAAAAAAALAAAAAAEAAQAAAIFTGB4xlcAOw==) repeat 0 0;
font-family: "Lucida Sans Unicode", "Lucida Sans", verdana, arial, helvetica;
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/messages.json b/tests/wpt/web-platform-tests/conformance-checkers/messages.json
index 7c363b35885..bb183ed4d5b 100644
--- a/tests/wpt/web-platform-tests/conformance-checkers/messages.json
+++ b/tests/wpt/web-platform-tests/conformance-checkers/messages.json
@@ -1980,6 +1980,7 @@
"html/elements/style/scoped-model-novalid.html": "Element \u201cstyle\u201d not allowed as child of element \u201cdiv\u201d in this context. (Suppressing further errors from this subtree.)",
"html/elements/style/scoped-multiple-adjacent-novalid.html": "Element \u201cstyle\u201d not allowed as child of element \u201cdiv\u201d in this context. (Suppressing further errors from this subtree.)",
"html/elements/style/scoped-novalid.html": "Element \u201cstyle\u201d not allowed as child of element \u201cdiv\u201d in this context. (Suppressing further errors from this subtree.)",
+ "html/elements/style/type-novalid.html": " The only allowed value for the \u201ctype\u201d attribute for the \u201cstyle\u201d element is \u201ctext/css\u201d (with no parameters). (But the attribute is not needed and should be omitted altogether.)",
"html/elements/sub/model-novalid.html": "End tag \u201cp\u201d implied, but there were open elements.",
"html/elements/sup/model-novalid.html": "End tag \u201cp\u201d implied, but there were open elements.",
"html/elements/table/integrity/Alexis_of_Russia-novalid.html": "Bad value \u201ccopyright\u201d for attribute \u201crel\u201d on element \u201clink\u201d: Bad list of link-type keywords: The keyword \u201ccopyright\u201d for the \u201crel\u201d attribute should not be used. Consider using \u201clicense\u201d instead.",
diff --git a/tests/wpt/web-platform-tests/content-security-policy/base-uri/report-uri-does-not-respect-base-uri.sub.html b/tests/wpt/web-platform-tests/content-security-policy/base-uri/report-uri-does-not-respect-base-uri.sub.html
new file mode 100644
index 00000000000..6f59016fae3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/base-uri/report-uri-does-not-respect-base-uri.sub.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test that base does not affect report-uri</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <!-- if base is used for resolving the URL to report to then we will not get a report -->
+ <base href="http://nonexistent-origin.web-platform.test">
+</head>
+<body>
+ <script>
+ var t1 = async_test("Test that image does not load");
+ async_test(function(t2) {
+ window.addEventListener("securitypolicyviolation", t2.step_func(function(e) {
+ assert_equals(e.blockedURI, "{{location[scheme]}}://{{location[host]}}/content-security-policy/support/fail.png");
+ assert_equals(e.violatedDirective, "img-src");
+ t2.done();
+ }));
+ }, "Event is fired");
+ </script>
+ <img src='{{location[scheme]}}://{{location[host]}}/content-security-policy/support/fail.png'
+ onload='t1.unreached_func("The image should not have loaded");'
+ onerror='t1.done();'>
+
+ <script async defer src='{{location[scheme]}}://{{location[host]}}/content-security-policy/support/checkReport.sub.js?reportField=violated-directive&reportValue=img-src%20%27none%27'></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/base-uri/report-uri-does-not-respect-base-uri.sub.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/base-uri/report-uri-does-not-respect-base-uri.sub.html.sub.headers
new file mode 100644
index 00000000000..1e3f163730f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/base-uri/report-uri-does-not-respect-base-uri.sub.html.sub.headers
@@ -0,0 +1,5 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Pragma: no-cache
+Set-Cookie: report-uri-does-not-respect-base-uri={{$id:uuid()}}; Path=/content-security-policy/base-uri
+Content-Security-Policy: script-src 'self' 'unsafe-inline'; img-src 'none'; report-uri ../support/report.py?op=put&reportID={{$id}}
diff --git a/tests/wpt/web-platform-tests/content-security-policy/generic/policy-inherited-correctly-by-plznavigate.html b/tests/wpt/web-platform-tests/content-security-policy/generic/policy-inherited-correctly-by-plznavigate.html
new file mode 100644
index 00000000000..700349a8a1d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/generic/policy-inherited-correctly-by-plznavigate.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <!-- This tests a bug that can occur when content layer CSP is not told
+ about the CSP inherited from the parent document which leads to it not
+ applying it to content layer CSP checks (such as frame-src with
+ PlzNavigate on).
+ Also see crbug.com/778658. -->
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+</head>
+<body>
+ <script>
+ var t = async_test("iframe still inherits correct CSP");
+ </script>
+
+ <iframe id="x" srcdoc="<a href='about:blank'>123</a>"></iframe>
+
+ <script>
+ window.onmessage = t.step_func_done(function(e) {
+ assert_equals(e.data, "frame-src");
+ });
+
+ x = document.getElementById('x');
+ x.location = "";
+
+ // While document.write is deprecated I did not find another way to reproduce
+ // the original exploit.
+ x.contentDocument.write(
+ '<script>window.addEventListener("securitypolicyviolation", function(e) {' +
+ ' window.top.postMessage(e.violatedDirective, "*");' +
+ '});</scr' + 'ipt>' +
+ '<iframe src="../support/fail.html"></iframe>'
+ );
+ x.contentDocument.close();
+ </script>
+ <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=frame-src%20%27none%27''></script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/generic/policy-inherited-correctly-by-plznavigate.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/generic/policy-inherited-correctly-by-plznavigate.html.sub.headers
new file mode 100644
index 00000000000..64653e3bf1a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/generic/policy-inherited-correctly-by-plznavigate.html.sub.headers
@@ -0,0 +1,5 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Pragma: no-cache
+Set-Cookie: policy-inherited-correctly-by-plznavigate={{$id:uuid()}}; Path=/content-security-policy/generic/
+Content-Security-Policy: frame-src 'none'; script-src 'self' 'unsafe-inline'; report-uri ../support/report.py?op=put&reportID={{$id}} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/inheritance/inherited-csp-list-modifications-are-local.html b/tests/wpt/web-platform-tests/content-security-policy/inheritance/inherited-csp-list-modifications-are-local.html
new file mode 100644
index 00000000000..c473b3f4262
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/inheritance/inherited-csp-list-modifications-are-local.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<head>
+ <meta http-equiv="Content-Security-Policy" content="script-src 'unsafe-inline' 'self'">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Tests that mutations inside a context that inherits a copy of the CSP list
+ does not affect the parent context -->
+</head>
+<body>
+ <script>
+ var t1 = async_test("Test that parent document image loads");
+ var t2 = async_test("Test that embedded iframe document image does not load");
+ var t3 = async_test("Test that spv event is fired");
+
+ window.onmessage = function(e) {
+ if (e.data.type == 'spv') {
+ t3.step(function() {
+ assert_equals(e.data.violatedDirective, "img-src");
+ t3.done();
+ });
+ } else if (e.data.type == 'imgload') {
+ var img = document.createElement('img');
+ img.src = "../support/pass.png";
+ img.onload = function() { t1.done(); };
+ img.onerror = t1.unreached_func('Should have loaded the image');
+ document.body.appendChild(img);
+
+ t2.step(function() {
+ assert_false(e.data.loaded, "Should not have loaded image inside the frame because of its CSP");
+ t2.done();
+ });
+ }
+ }
+
+ var srcdoc = ['<meta http-equiv="Content-Security-Policy" content="img-src \'none\'">',
+ '<script>',
+ ' window.addEventListener("securitypolicyviolation", function(e) {',
+ ' window.top.postMessage({type: "spv", violatedDirective: e.violatedDirective}, "*");',
+ ' });',
+ '</scr' + 'ipt>',
+ '<img src="../support/fail.png"',
+ ' onload="window.top.postMessage({type: \'imgload\', loaded: true}, \'*\')"',
+ ' onerror="window.top.postMessage({type: \'imgload\', loaded: false}, \'*\')">'].join('\n');
+ var i = document.createElement('iframe');
+ i.srcdoc = srcdoc;
+ document.body.appendChild(i);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/nonce-hiding/script-nonces-hidden.tentative.html b/tests/wpt/web-platform-tests/content-security-policy/nonce-hiding/script-nonces-hidden.tentative.html
index 763e48dddfb..4b717b9b2a0 100644
--- a/tests/wpt/web-platform-tests/content-security-policy/nonce-hiding/script-nonces-hidden.tentative.html
+++ b/tests/wpt/web-platform-tests/content-security-policy/nonce-hiding/script-nonces-hidden.tentative.html
@@ -114,6 +114,46 @@
}, "createElement.setAttribute.");
</script>
+<!-- Custom Element -->
+<script nonce="abc">
+ var eventList = [];
+ class NonceElement extends HTMLElement {
+ static get observedAttributes() {
+ return ['nonce'];
+ }
+
+ constructor() {
+ super();
+ }
+
+ attributeChangedCallback(name, oldValue, newValue) {
+ eventList.push({
+ type: "AttributeChanged",
+ name: name,
+ oldValue: oldValue,
+ newValue: newValue
+ });
+ }
+
+ connectedCallback() {
+ eventList.push({
+ type: "Connected",
+ });
+ }
+ }
+
+ customElements.define("nonce-element", NonceElement);
+</script>
+<nonce-element nonce="abc"></nonce-element>
+<script nonce="abc">
+ test(t => {
+ assert_equals(eventList.length, 3);
+ assert_object_equals(eventList[0], { type: "AttributeChanged", name: "nonce", oldValue: null, newValue: "abc" });
+ assert_object_equals(eventList[1], { type: "Connected" });
+ assert_object_equals(eventList[2], { type: "AttributeChanged", name: "nonce", oldValue: "abc", newValue: "" });
+ }, "Custom elements expose the correct events.");
+</script>
+
<!-- CSS Leakage -->
<style>
#cssTest { display: block; }
diff --git a/tests/wpt/web-platform-tests/content-security-policy/reporting/securitypolicyviolation-idl.html b/tests/wpt/web-platform-tests/content-security-policy/reporting/securitypolicyviolation-idl.html
index 08f244018a2..e6b1e0dbfde 100644
--- a/tests/wpt/web-platform-tests/content-security-policy/reporting/securitypolicyviolation-idl.html
+++ b/tests/wpt/web-platform-tests/content-security-policy/reporting/securitypolicyviolation-idl.html
@@ -38,68 +38,24 @@ dictionary SecurityPolicyViolationEventInit : EventInit {
long lineNumber;
long columnNumber;
};
-
-[
- Constructor(DOMString type, optional EventInit eventInitDict),
- Exposed=(Window,Worker)
-] interface Event {
- readonly attribute DOMString type;
- readonly attribute EventTarget? target;
- readonly attribute EventTarget? currentTarget;
- [MeasureAs=EventComposedPath, CallWith=ScriptState] sequence<EventTarget> composedPath();
-
- const unsigned short NONE = 0;
- const unsigned short CAPTURING_PHASE = 1;
- const unsigned short AT_TARGET = 2;
- const unsigned short BUBBLING_PHASE = 3;
- readonly attribute unsigned short eventPhase;
-
- [Measure] void stopPropagation();
- [Measure] void stopImmediatePropagation();
-
- readonly attribute boolean bubbles;
- readonly attribute boolean cancelable;
- void preventDefault();
- readonly attribute boolean defaultPrevented;
-
- [MeasureAs=EventComposed] readonly attribute boolean composed;
-
- [Unforgeable] readonly attribute boolean isTrusted;
-
- [CallWith=ScriptState] readonly attribute DOMHighResTimeStamp timeStamp;
-
- [Measure] void initEvent(DOMString type, optional boolean bubbles = false, optional boolean cancelable = false);
-
- // Non-standard APIs
- [MeasureAs=EventSrcElement] readonly attribute EventTarget srcElement;
- [MeasureAs=EventReturnValue, CallWith=ScriptState, ImplementedAs=legacyReturnValue] attribute boolean returnValue;
- [MeasureAs=EventCancelBubble, CallWith=ScriptState] attribute boolean cancelBubble;
- [MeasureAs=EventPath, CallWith=ScriptState] readonly attribute EventTarget[] path;
-};
-
-[
- Constructor(),
- CheckSecurity=Receiver,
- Exposed=(Window,Worker),
- ImmutablePrototype
-] interface EventTarget {
- [Custom=(CallPrologue,CallEpilogue)] void addEventListener(DOMString type, EventListener? listener, optional (AddEventListenerOptions or boolean) options);
- [Custom=(CallPrologue,CallEpilogue)] void removeEventListener(DOMString type, EventListener? listener, optional (EventListenerOptions or boolean) options);
- [ImplementedAs=dispatchEventForBindings, RaisesException] boolean dispatchEvent(Event event);
-};
-
</script>
<script>
- (function() {
- var idl_array = new IdlArray();
- var idls = document.getElementById('idl').textContent;
- idl_array.add_idls(idls);
-
- window.event_to_test = new SecurityPolicyViolationEvent({});
-
- idl_array.add_objects({
- SecurityPolicyViolationEvent: ['event_to_test']
- });
- idl_array.test();
- })();
+function do_test(dom_idl) {
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(dom_idl);
+ var idls = document.getElementById('idl').textContent;
+ idl_array.add_idls(idls);
+
+ window.event_to_test = new SecurityPolicyViolationEvent({});
+
+ idl_array.add_objects({
+ SecurityPolicyViolationEvent: ['event_to_test']
+ });
+ idl_array.test();
+}
+
+promise_test(function() {
+ return fetch("/interfaces/dom.idl").then(response => response.text())
+ .then(do_test);
+}, "Test driver");
</script>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/script-src/nonce-enforce-blocked.html b/tests/wpt/web-platform-tests/content-security-policy/script-src/nonce-enforce-blocked.html
new file mode 100644
index 00000000000..25343a5d4dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/script-src/nonce-enforce-blocked.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<meta http-equiv="Content-Security-Policy" content="script-src 'nonce-abc'">
+<script src="/resources/testharness.js" nonce="abc"></script>
+<script src="/resources/testharnessreport.js" nonce="abc"></script>
+<script nonce="abc">
+ var t = async_test("Unnonced scripts generate reports.");
+ var events = 0;
+ var firstLine = 38;
+ var expectations = {}
+ expectations[firstLine] = true;
+ expectations[firstLine + 3] = true;
+ expectations[firstLine + 6] = true;
+ expectations[firstLine + 9] = true;
+ expectations[firstLine + 12] = true;
+ expectations[firstLine + 15] = true;
+ expectations[firstLine + 18] = true;
+ expectations["/content-security-policy/support/nonce-should-be-blocked.js?1"] = true;
+ expectations["/content-security-policy/support/nonce-should-be-blocked.js?2"] = true;
+ expectations["/content-security-policy/support/nonce-should-be-blocked.js?3"] = true;
+ expectations["/content-security-policy/support/nonce-should-be-blocked.js?4"] = true;
+ expectations["/content-security-policy/support/nonce-should-be-blocked.js?5"] = true;
+
+ document.addEventListener('securitypolicyviolation', t.step_func(e => {
+ if (e.lineNumber) {
+ // Verify that the line is expected, then clear the expectation:
+ assert_true(expectations[e.lineNumber], "Line number: " + e.lineNumber);
+ assert_equals(e.blockedURI, "inline");
+ } else {
+ // Otherwise, verify that the URL is expected, then clear the expectation:
+ var url = new URL(e.blockedURI);
+ assert_true(expectations[url.pathname + url.search], "URL: " + e.blockedURI);
+ }
+ events++;
+ if (events == 12)
+ t.done();
+ }));
+</script>
+<script>
+ t.unreached_func("No nonce, no execution.")();
+</script>
+<script nonce="xyz">
+ t.unreached_func("Bad nonce, no execution.")();
+</script>
+<script <script nonce="abc">
+ t.unreached_func("'<script' attribute, no execution.")();
+</script>
+<script attribute<script nonce="abc">
+ t.unreached_func("'attribute<script', no execution.")();
+</script>
+<script attribute=<script nonce="abc">
+ t.unreached_func("'<script' value, no execution.")();
+</script>
+<script attribute=value<script nonce="abc">
+ t.unreached_func("'value<script', no execution.")();
+</script>
+<script attribute="" attribute=<style nonce="abc">
+ t.unreached_func("Duplicate attribute, no execution.")();
+</script>
+<script src="../support/nonce-should-be-blocked.js?1" <script nonce="abc"></script>
+<script src="../support/nonce-should-be-blocked.js?2" attribute=<script nonce="abc"></script>
+<script src="../support/nonce-should-be-blocked.js?3" <style nonce="abc"></script>
+<script src="../support/nonce-should-be-blocked.js?4" attribute=<style nonce="abc"></script>
+<script src="../support/nonce-should-be-blocked.js?5" attribute=<style nonce="abc"></script>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/securitypolicyviolation/idl.html b/tests/wpt/web-platform-tests/content-security-policy/securitypolicyviolation/idl.html
index 17f492e7344..a4f9e68f831 100644
--- a/tests/wpt/web-platform-tests/content-security-policy/securitypolicyviolation/idl.html
+++ b/tests/wpt/web-platform-tests/content-security-policy/securitypolicyviolation/idl.html
@@ -21,6 +21,9 @@
long lineNumber;
long columnNumber;
};
+
+ interface Event {
+ };
</script>
<script type="text/plain" id="tested">
[Constructor(DOMString type, optional SecurityPolicyViolationEventInit eventInitDict)]
diff --git a/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-imported-style-blocked.html b/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-imported-style-blocked.html
index 19066119c4d..a00888098a5 100644
--- a/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-imported-style-blocked.html
+++ b/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-imported-style-blocked.html
@@ -12,8 +12,13 @@
document.addEventListener("securitypolicyviolation", t_spv.step_func_done(function(e) {
assert_equals("style-src", e.violatedDirective);
}));
+
+ var l = document.createElement("link");
+ l.setAttribute("href", "/content-security-policy/style-src/resources/style-src-import.sub.css");
+ l.setAttribute("rel", "stylesheet");
+ l.setAttribute("type", "text/css");
+ document.head.appendChild(l);
</script>
- <link href="/content-security-policy/style-src/resources/style-src-import.sub.css" rel=stylesheet type=text/css>
</head>
<body>
<div id='log'></div>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/support/fail.html b/tests/wpt/web-platform-tests/content-security-policy/support/fail.html
new file mode 100644
index 00000000000..fedcc31bd3d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/support/fail.html
@@ -0,0 +1,3 @@
+<script>
+ test(function() { assert_unreached("FAIL")});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/support/nonce-should-be-blocked.js b/tests/wpt/web-platform-tests/content-security-policy/support/nonce-should-be-blocked.js
new file mode 100644
index 00000000000..501f7a92088
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/support/nonce-should-be-blocked.js
@@ -0,0 +1 @@
+t.unreached_func(document.currentScript.getAttribute('src') + " should not execute.")();
diff --git a/tests/wpt/web-platform-tests/content-security-policy/svg/including.sub.svg b/tests/wpt/web-platform-tests/content-security-policy/svg/including.sub.svg
index 99b416b5ec3..51215d90440 100644
--- a/tests/wpt/web-platform-tests/content-security-policy/svg/including.sub.svg
+++ b/tests/wpt/web-platform-tests/content-security-policy/svg/including.sub.svg
@@ -2,7 +2,8 @@
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="6cm" height="5cm" viewBox="0 0 600 500"
- xmlns="http://www.w3.org/2000/svg" version="1.1">
+ xmlns="http://www.w3.org/2000/svg" version="1.1"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
<desc>using SVG as a resource doc should apply this doc's CSP</desc>
<use xlink:href="scripted.svg#postmessagescript" />
diff --git a/tests/wpt/web-platform-tests/cookie-store/OWNERS b/tests/wpt/web-platform-tests/cookie-store/OWNERS
new file mode 100644
index 00000000000..6e762960c8f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/OWNERS
@@ -0,0 +1,2 @@
+@bsittler
+@pwnall
diff --git a/tests/wpt/web-platform-tests/cookie-store/README.md b/tests/wpt/web-platform-tests/cookie-store/README.md
new file mode 100644
index 00000000000..4ba55f7f946
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/README.md
@@ -0,0 +1,2 @@
+This directory contains tests for the
+[Async Cookies API](https://github.com/WICG/cookie-store).
diff --git a/tests/wpt/web-platform-tests/cookie-store/cookieStore_delete_arguments.tentative.window.js b/tests/wpt/web-platform-tests/cookie-store/cookieStore_delete_arguments.tentative.window.js
new file mode 100644
index 00000000000..8f3f6f5656c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/cookieStore_delete_arguments.tentative.window.js
@@ -0,0 +1,171 @@
+'use strict';
+
+// Workaround because add_cleanup doesn't support async functions yet.
+// See https://github.com/w3c/web-platform-tests/issues/6075
+async function async_cleanup(cleanup_function) {
+ try {
+ await cleanup_function();
+ } catch (e) {
+ // Errors in cleanup functions shouldn't result in test failures.
+ }
+}
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+
+ await cookieStore.delete('cookie-name');
+ const cookie = await cookieStore.get('cookie-name');
+ assert_equals(cookie, null);
+}, 'cookieStore.delete with positional name');
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+
+ await cookieStore.delete({ name: 'cookie-name' });
+ const cookie = await cookieStore.get('cookie-name');
+ assert_equals(cookie, null);
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.delete with name in options');
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+
+ await promise_rejects(testCase, new TypeError(), cookieStore.delete(
+ 'cookie-name', { name: 'cookie-name' }));
+ const cookie = await cookieStore.get('cookie-name');
+ assert_equals(cookie.name, 'cookie-name');
+ assert_equals(cookie.value, 'cookie-value');
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.delete with name in both positional arguments and options');
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+
+ await promise_rejects(testCase, new TypeError(), cookieStore.delete(
+ 'cookie-name', { value: 'cookie-value' }));
+ const cookie = await cookieStore.get('cookie-name');
+ assert_equals(cookie.name, 'cookie-name');
+ assert_equals(cookie.value, 'cookie-value');
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.delete with value in options');
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+
+ const tenYears = 10 * 365 * 24 * 60 * 60 * 1000;
+ const tenYearsAgo = Date.now() - tenYears;
+
+ await promise_rejects(testCase, new TypeError(), cookieStore.delete(
+ 'cookie-name', { expires: tenYearsAgo }));
+ const cookie = await cookieStore.get('cookie-name');
+ assert_equals(cookie.name, 'cookie-name');
+ assert_equals(cookie.value, 'cookie-value');
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.delete with expires in options');
+
+promise_test(async testCase => {
+ const currentUrl = new URL(self.location.href);
+ const currentDomain = currentUrl.hostname;
+ await cookieStore.set(
+ 'cookie-name', 'cookie-value', { domain: currentDomain });
+
+ await cookieStore.delete('cookie-name', { domain: currentDomain });
+ const cookie = await cookieStore.get('cookie-name');
+ assert_equals(cookie, null);
+
+ await async_cleanup(async () => {
+ await cookieStore.delete('cookie-name', { domain: currentDomain })
+ });
+}, 'cookieStore.delete with domain set to the current hostname');
+
+promise_test(async testCase => {
+ const currentUrl = new URL(self.location.href);
+ const currentDomain = currentUrl.hostname;
+ const subDomain = `sub.${currentDomain}`;
+ await cookieStore.set(
+ 'cookie-name', 'cookie-value', { domain: currentDomain });
+
+ await cookieStore.delete('cookie-name', { domain: subDomain });
+ const cookie = await cookieStore.get('cookie-name');
+ assert_equals(cookie.name, 'cookie-name');
+ assert_equals(cookie.value, 'cookie-value');
+
+ await async_cleanup(async () => {
+ await cookieStore.delete('cookie-name', { domain: currentDomain })
+ });
+}, 'cookieStore.delete with domain set to a subdomain of the current hostname');
+
+promise_test(async testCase => {
+ const currentUrl = new URL(self.location.href);
+ const currentDomain = currentUrl.hostname;
+ await cookieStore.set(
+ 'cookie-name', 'cookie-value', { domain: currentDomain });
+
+ await cookieStore.delete({ name: 'cookie-name', domain: currentDomain });
+ const cookie = await cookieStore.get('cookie-name');
+ assert_equals(cookie, null);
+
+ await async_cleanup(async () => {
+ await cookieStore.delete('cookie-name', { domain: currentDomain })
+ });
+}, 'cookieStore.delete with name in options and domain set to the current ' +
+ 'hostname');
+
+promise_test(async testCase => {
+ const currentUrl = new URL(self.location.href);
+ const currentDomain = currentUrl.hostname;
+ const subDomain = `sub.${currentDomain}`;
+ await cookieStore.set(
+ 'cookie-name', 'cookie-value', { domain: currentDomain });
+
+ await cookieStore.delete({ name: 'cookie-name', domain: subDomain });
+ const cookie = await cookieStore.get('cookie-name');
+ assert_equals(cookie.name, 'cookie-name');
+ assert_equals(cookie.value, 'cookie-value');
+
+ await async_cleanup(async () => {
+ await cookieStore.delete('cookie-name', { domain: currentDomain })
+ });
+}, 'cookieStore.delete with name in options and domain set to a subdomain of ' +
+ 'the current hostname');
+
+
+promise_test(async testCase => {
+ const currentUrl = new URL(self.location.href);
+ const currentPath = currentUrl.pathname;
+ const currentDirectory =
+ currentPath.substr(0, currentPath.lastIndexOf('/') + 1);
+ await cookieStore.set(
+ 'cookie-name', 'cookie-value', { path: currentDirectory });
+
+ await cookieStore.delete('cookie-name', { path: currentDirectory });
+ const cookie = await cookieStore.get('cookie-name');
+ assert_equals(cookie, null);
+
+ async_cleanup(async () => {
+ await cookieStore.delete('cookie-name', { path: currentDirectory })
+ });
+}, 'cookieStore.delete with path set to the current directory');
+
+promise_test(async testCase => {
+ const currentUrl = new URL(self.location.href);
+ const currentPath = currentUrl.pathname;
+ const currentDirectory =
+ currentPath.substr(0, currentPath.lastIndexOf('/') + 1);
+ const subDirectory = currentDirectory + "subdir/";
+ await cookieStore.set(
+ 'cookie-name', 'cookie-value', { path: currentDirectory });
+
+ await cookieStore.delete('cookie-name', { path: subDirectory });
+ const cookie = await cookieStore.get('cookie-name');
+ assert_equals(cookie.name, 'cookie-name');
+ assert_equals(cookie.value, 'cookie-value');
+
+ await async_cleanup(async () => {
+ await cookieStore.delete('cookie-name', { path: currentDirectory })
+ });
+}, 'cookieStore.delete with path set to subdirectory of the current directory');
diff --git a/tests/wpt/web-platform-tests/cookie-store/cookieStore_getAll_arguments.tentative.window.js b/tests/wpt/web-platform-tests/cookie-store/cookieStore_getAll_arguments.tentative.window.js
new file mode 100644
index 00000000000..650d6eb901d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/cookieStore_getAll_arguments.tentative.window.js
@@ -0,0 +1,119 @@
+'use strict';
+
+// Workaround because add_cleanup doesn't support async functions yet.
+// See https://github.com/w3c/web-platform-tests/issues/6075
+async function async_cleanup(cleanup_function) {
+ try {
+ await cleanup_function();
+ } catch (e) {
+ // Errors in cleanup functions shouldn't result in test failures.
+ }
+}
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+ await cookieStore.set('cookie-name-2', 'cookie-value-2');
+
+ const cookies = await cookieStore.getAll();
+ cookies.sort((a, b) => a.name.localeCompare(b.name));
+ assert_equals(cookies.length, 2);
+ assert_equals(cookies[0].name, 'cookie-name');
+ assert_equals(cookies[0].value, 'cookie-value');
+ assert_equals(cookies[1].name, 'cookie-name-2');
+ assert_equals(cookies[1].value, 'cookie-value-2');
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+ await async_cleanup(() => cookieStore.delete('cookie-name-2'));
+}, 'cookieStore.getAll with no arguments');
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+ await cookieStore.set('cookie-name-2', 'cookie-value-2');
+
+ const cookies = await cookieStore.getAll('cookie-name');
+ assert_equals(cookies.length, 1);
+ assert_equals(cookies[0].name, 'cookie-name');
+ assert_equals(cookies[0].value, 'cookie-value');
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+ await async_cleanup(() => cookieStore.delete('cookie-name-2'));
+}, 'cookieStore.getAll with positional name');
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+ await cookieStore.set('cookie-name-2', 'cookie-value-2');
+
+ const cookies = await cookieStore.getAll({ name: 'cookie-name' });
+ assert_equals(cookies.length, 1);
+ assert_equals(cookies[0].name, 'cookie-name');
+ assert_equals(cookies[0].value, 'cookie-value');
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+ await async_cleanup(() => cookieStore.delete('cookie-name-2'));
+}, 'cookieStore.getAll with name in options');
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+ await cookieStore.set('cookie-name-2', 'cookie-value-2');
+
+ await promise_rejects(testCase, new TypeError(), cookieStore.get(
+ 'cookie-name', { name: 'cookie-name' }));
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+ await async_cleanup(() => cookieStore.delete('cookie-name-2'));
+}, 'cookieStore.getAll with name in both positional arguments and options');
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+
+ const cookies = await cookieStore.getAll(
+ 'cookie-name', { matchType: 'equals' });
+ assert_equals(cookies.length, 1);
+ assert_equals(cookies[0].name, 'cookie-name');
+ assert_equals(cookies[0].value, 'cookie-value');
+
+ const no_cookies = await cookieStore.getAll(
+ 'cookie-na', { matchType: 'equals' });
+ assert_equals(no_cookies.length, 0);
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.getAll with matchType explicitly set to equals');
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+ await cookieStore.set('cookie-name-2', 'cookie-value-2');
+
+ const cookies = await cookieStore.getAll(
+ 'cookie-name-', { matchType: 'startsWith' });
+ assert_equals(cookies.length, 1);
+ assert_equals(cookies[0].name, 'cookie-name-2');
+ assert_equals(cookies[0].value, 'cookie-value-2');
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+ await async_cleanup(() => cookieStore.delete('cookie-name-2'));
+}, 'cookieStore.getAll with matchType set to startsWith');
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+ await cookieStore.set('cookie-name-2', 'cookie-value-2');
+
+ await promise_rejects(testCase, new TypeError(), cookieStore.getAll(
+ 'cookie-name', { matchType: 'invalid' }));
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+ await async_cleanup(() => cookieStore.delete('cookie-name-2'));
+}, 'cookieStore.getAll with invalid matchType');
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+ await cookieStore.set('cookie-name-2', 'cookie-value-2');
+
+ const cookies = await cookieStore.getAll(
+ { matchType: 'startsWith', name: 'cookie-name-' });
+ assert_equals(cookies.length, 1);
+ assert_equals(cookies[0].name, 'cookie-name-2');
+ assert_equals(cookies[0].value, 'cookie-value-2');
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+ await async_cleanup(() => cookieStore.delete('cookie-name-2'));
+}, 'cookieStore.getAll with matchType set to startsWith and name in options');
diff --git a/tests/wpt/web-platform-tests/cookie-store/cookieStore_getAll_set_basic.tentative.window.js b/tests/wpt/web-platform-tests/cookie-store/cookieStore_getAll_set_basic.tentative.window.js
new file mode 100644
index 00000000000..a70c11975f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/cookieStore_getAll_set_basic.tentative.window.js
@@ -0,0 +1,22 @@
+'use strict';
+
+// Workaround because add_cleanup doesn't support async functions yet.
+// See https://github.com/w3c/web-platform-tests/issues/6075
+async function async_cleanup(cleanup_function) {
+ try {
+ await cleanup_function();
+ } catch (e) {
+ // Errors in cleanup functions shouldn't result in test failures.
+ }
+}
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+ const cookies = await cookieStore.getAll('cookie-name');
+
+ assert_equals(cookies.length, 1);
+ assert_equals(cookies[0].name, 'cookie-name');
+ assert_equals(cookies[0].value, 'cookie-value');
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.getAll returns the cookie written by cookieStore.set');
diff --git a/tests/wpt/web-platform-tests/cookie-store/cookieStore_get_arguments.tentative.window.js b/tests/wpt/web-platform-tests/cookie-store/cookieStore_get_arguments.tentative.window.js
new file mode 100644
index 00000000000..f50bb518ee9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/cookieStore_get_arguments.tentative.window.js
@@ -0,0 +1,86 @@
+'use strict';
+
+// Workaround because add_cleanup doesn't support async functions yet.
+// See https://github.com/w3c/web-platform-tests/issues/6075
+async function async_cleanup(cleanup_function) {
+ try {
+ await cleanup_function();
+ } catch (e) {
+ // Errors in cleanup functions shouldn't result in test failures.
+ }
+}
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+
+ const cookie = await cookieStore.get('cookie-name');
+ assert_equals(cookie.name, 'cookie-name');
+ assert_equals(cookie.value, 'cookie-value');
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.get with positional name');
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+
+ const cookie = await cookieStore.get({ name: 'cookie-name' });
+ assert_equals(cookie.name, 'cookie-name');
+ assert_equals(cookie.value, 'cookie-value');
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.get with name in options');
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+
+ await promise_rejects(testCase, new TypeError(), cookieStore.get(
+ 'cookie-name', { name: 'cookie-name' }));
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.get with name in both positional arguments and options');
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+
+ const cookie = await cookieStore.get(
+ 'cookie-name', { matchType: 'equals' });
+ assert_equals(cookie.name, 'cookie-name');
+ assert_equals(cookie.value, 'cookie-value');
+
+ const no_cookie = await cookieStore.get(
+ 'cookie-na', { matchType: 'equals' });
+ assert_equals(no_cookie, null);
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.get with matchType explicitly set to equals');
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+
+ const cookie = await cookieStore.get(
+ 'cookie-na', { matchType: 'startsWith' });
+ assert_equals(cookie.name, 'cookie-name');
+ assert_equals(cookie.value, 'cookie-value');
+
+ async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.get with matchType set to startsWith');
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+
+ await promise_rejects(testCase, new TypeError(), cookieStore.get(
+ 'cookie-name', { matchType: 'invalid' }));
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.get with invalid matchType');
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+
+ const cookie = await cookieStore.get(
+ { matchType: 'startsWith', name: 'cookie-na' });
+ assert_equals(cookie.name, 'cookie-name');
+ assert_equals(cookie.value, 'cookie-value');
+
+ async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.get with matchType set to startsWith and name in options');
diff --git a/tests/wpt/web-platform-tests/cookie-store/cookieStore_get_delete_basic.tentative.window.js b/tests/wpt/web-platform-tests/cookie-store/cookieStore_get_delete_basic.tentative.window.js
new file mode 100644
index 00000000000..e039d817023
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/cookieStore_get_delete_basic.tentative.window.js
@@ -0,0 +1,20 @@
+'use strict';
+
+// Workaround because add_cleanup doesn't support async functions yet.
+// See https://github.com/w3c/web-platform-tests/issues/6075
+async function async_cleanup(cleanup_function) {
+ try {
+ await cleanup_function();
+ } catch (e) {
+ // Errors in cleanup functions shouldn't result in test failures.
+ }
+}
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+ await cookieStore.delete('cookie-name');
+ const cookie = await cookieStore.get();
+ assert_equals(cookie, null);
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.get returns null for a cookie deleted by cookieStore.delete'); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/cookie-store/cookieStore_get_set_basic.tentative.window.js b/tests/wpt/web-platform-tests/cookie-store/cookieStore_get_set_basic.tentative.window.js
new file mode 100644
index 00000000000..1fa834a354d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/cookieStore_get_set_basic.tentative.window.js
@@ -0,0 +1,21 @@
+'use strict';
+
+// Workaround because add_cleanup doesn't support async functions yet.
+// See https://github.com/w3c/web-platform-tests/issues/6075
+async function async_cleanup(cleanup_function) {
+ try {
+ await cleanup_function();
+ } catch (e) {
+ // Errors in cleanup functions shouldn't result in test failures.
+ }
+}
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+ const cookie = await cookieStore.get('cookie-name');
+
+ assert_equals(cookie.name, 'cookie-name');
+ assert_equals(cookie.value, 'cookie-value');
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.get returns the cookie written by cookieStore.set');
diff --git a/tests/wpt/web-platform-tests/cookie-store/cookieStore_has_arguments.tentative.window.js b/tests/wpt/web-platform-tests/cookie-store/cookieStore_has_arguments.tentative.window.js
new file mode 100644
index 00000000000..443341edc6c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/cookieStore_has_arguments.tentative.window.js
@@ -0,0 +1,92 @@
+'use strict';
+
+// Workaround because add_cleanup doesn't support async functions yet.
+// See https://github.com/w3c/web-platform-tests/issues/6075
+async function async_cleanup(cleanup_function) {
+ try {
+ await cleanup_function();
+ } catch (e) {
+ // Errors in cleanup functions shouldn't result in test failures.
+ }
+}
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+ await cookieStore.delete('cookie-name-2');
+
+ const has_cookie = await cookieStore.has('cookie-name');
+ assert_equals(has_cookie, true);
+ const has_cookie2 = await cookieStore.has('cookie-name-2');
+ assert_equals(has_cookie2, false);
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.has with positional name');
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+ await cookieStore.delete('cookie-name-2');
+
+ const has_cookie = await cookieStore.has({ name: 'cookie-name' });
+ assert_equals(has_cookie, true);
+ const has_cookie2 = await cookieStore.has({ name: 'cookie-name-2' });
+ assert_equals(has_cookie2, false);
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.has with name in options');
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+
+ await promise_rejects(testCase, new TypeError(), cookieStore.has(
+ 'cookie-name', { name: 'cookie-name' }));
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.has with name in both positional arguments and options');
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+
+ const has_cookie = await cookieStore.has(
+ 'cookie-na', { matchType: 'equals' });
+ assert_equals(has_cookie, false);
+ const has_cookie2 = await cookieStore.has(
+ 'cookie-name', { matchType: 'equals' });
+ assert_equals(has_cookie2, true);
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.has with matchType explicitly set to equals');
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+
+ const has_cookie = await cookieStore.has(
+ 'cookie-na', { matchType: 'startsWith' });
+ assert_equals(has_cookie, true);
+ const has_cookie2 = await cookieStore.has(
+ 'cookie-name-', { matchType: 'startsWith' });
+ assert_equals(has_cookie2, false);
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.has with matchType set to startsWith');
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+
+ await promise_rejects(testCase, new TypeError(), cookieStore.has(
+ 'cookie-name', { matchType: 'invalid' }));
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.has with invalid matchType');
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+
+ const has_cookie = await cookieStore.has(
+ { matchType: 'startsWith', name: 'cookie-na' });
+ assert_equals(has_cookie, true);
+ const has_cookie2 = await cookieStore.has(
+ { matchType: 'startsWith', name: 'cookie-name-' });
+ assert_equals(has_cookie2, false);
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.has with matchType set to startsWith and name in options');
diff --git a/tests/wpt/web-platform-tests/cookie-store/cookieStore_has_basic.tentative.window.js b/tests/wpt/web-platform-tests/cookie-store/cookieStore_has_basic.tentative.window.js
new file mode 100644
index 00000000000..0774a71ef8d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/cookieStore_has_basic.tentative.window.js
@@ -0,0 +1,25 @@
+'use strict';
+
+// Workaround because add_cleanup doesn't support async functions yet.
+// See https://github.com/w3c/web-platform-tests/issues/6075
+async function async_cleanup(cleanup_function) {
+ try {
+ await cleanup_function();
+ } catch (e) {
+ // Errors in cleanup functions shouldn't result in test failures.
+ }
+}
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+ assert_equals(await cookieStore.has('cookie-name'), true);
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.has returns true for cookie set by cookieStore.set()');
+
+promise_test(async testCase => {
+ await cookieStore.delete('cookie-name');
+ assert_equals(await cookieStore.has('cookie-name'), false);
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.has returns false for cookie deleted by cookieStore.delete()');
diff --git a/tests/wpt/web-platform-tests/cookie-store/cookieStore_in_detached_frame.tentative.html b/tests/wpt/web-platform-tests/cookie-store/cookieStore_in_detached_frame.tentative.html
new file mode 100644
index 00000000000..08a7b5b8e46
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/cookieStore_in_detached_frame.tentative.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>cookieStore on DOMWindow of detached iframe (crbug.com/774626)</title>
+<link rel="help" href="https://github.com/WICG/cookie-store">
+<link rel="author" href="pwnall@chromium.org" title="Victor Costan">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<iframe id="iframe"></iframe>
+<script>
+'use strict';
+
+test(() => {
+ const iframe = document.getElementById('iframe');
+ const frameWindow = iframe.contentWindow;
+
+ iframe.parentNode.removeChild(iframe);
+ assert_equals(null, frameWindow.cookieStore);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/cookieStore_set_arguments.tentative.window.js b/tests/wpt/web-platform-tests/cookie-store/cookieStore_set_arguments.tentative.window.js
new file mode 100644
index 00000000000..c2564304635
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/cookieStore_set_arguments.tentative.window.js
@@ -0,0 +1,215 @@
+'use strict';
+
+// Workaround because add_cleanup doesn't support async functions yet.
+// See https://github.com/w3c/web-platform-tests/issues/6075
+async function async_cleanup(cleanup_function) {
+ try {
+ await cleanup_function();
+ } catch (e) {
+ // Errors in cleanup functions shouldn't result in test failures.
+ }
+}
+
+promise_test(async testCase => {
+ await cookieStore.delete('cookie-name');
+
+ await cookieStore.set('cookie-name', 'cookie-value');
+
+ const cookie = await cookieStore.get('cookie-name');
+ assert_equals(cookie.name, 'cookie-name');
+ assert_equals(cookie.value, 'cookie-value');
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.set with positional name and value');
+
+promise_test(async testCase => {
+ await cookieStore.delete('cookie-name');
+
+ await cookieStore.set({ name: 'cookie-name', value: 'cookie-value' });
+ const cookie = await cookieStore.get('cookie-name');
+ assert_equals(cookie.name, 'cookie-name');
+ assert_equals(cookie.value, 'cookie-value');
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.set with name and value in options');
+
+promise_test(async testCase => {
+ await cookieStore.delete('cookie-name');
+
+ await promise_rejects(testCase, new TypeError(), cookieStore.set(
+ 'cookie-name', 'cookie-value', { name: 'cookie-name' }));
+ const cookie = await cookieStore.get('cookie-name');
+ assert_equals(cookie, null);
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.set with name in both positional arguments and options');
+
+promise_test(async testCase => {
+ await cookieStore.delete('cookie-name');
+
+ await promise_rejects(testCase, new TypeError(), cookieStore.set(
+ 'cookie-name', 'cookie-value', { value: 'cookie-value' }));
+ const cookie = await cookieStore.get('cookie-name');
+ assert_equals(cookie, null);
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.set with value in both positional arguments and options');
+
+promise_test(async testCase => {
+ const tenYears = 10 * 365 * 24 * 60 * 60 * 1000;
+ const tenYearsFromNow = Date.now() + tenYears;
+ await cookieStore.delete('cookie-name');
+
+ await cookieStore.set(
+ 'cookie-name', 'cookie-value', { expires: tenYearsFromNow });
+ const cookie = await cookieStore.get('cookie-name');
+ assert_equals(cookie.name, 'cookie-name');
+ assert_equals(cookie.value, 'cookie-value');
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.set with expires in the future');
+
+promise_test(async testCase => {
+ const tenYears = 10 * 365 * 24 * 60 * 60 * 1000;
+ const tenYearsAgo = Date.now() - tenYears;
+ await cookieStore.delete('cookie-name');
+
+ await cookieStore.set(
+ 'cookie-name', 'cookie-value', { expires: tenYearsAgo });
+ const cookie = await cookieStore.get('cookie-name');
+ assert_equals(cookie, null);
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.set with expires in the past');
+
+promise_test(async testCase => {
+ const tenYears = 10 * 365 * 24 * 60 * 60 * 1000;
+ const tenYearsFromNow = Date.now() + tenYears;
+ await cookieStore.delete('cookie-name');
+
+ await cookieStore.set(
+ { name: 'cookie-name', value: 'cookie-value', expires: tenYearsFromNow });
+ const cookie = await cookieStore.get('cookie-name');
+ assert_equals(cookie.name, 'cookie-name');
+ assert_equals(cookie.value, 'cookie-value');
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.set with name and value in options and expires in the future');
+
+promise_test(async testCase => {
+ const tenYears = 10 * 365 * 24 * 60 * 60 * 1000;
+ const tenYearsAgo = Date.now() - tenYears;
+ await cookieStore.delete('cookie-name');
+
+ await cookieStore.set(
+ { name: 'cookie-name', value: 'cookie-value', expires: tenYearsAgo });
+ const cookie = await cookieStore.get('cookie-name');
+ assert_equals(cookie, null);
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+}, 'cookieStore.set with name and value in options and expires in the past');
+
+promise_test(async testCase => {
+ const currentUrl = new URL(self.location.href);
+ const currentDomain = currentUrl.hostname;
+ await cookieStore.delete('cookie-name', { domain: currentDomain });
+
+ await cookieStore.set(
+ 'cookie-name', 'cookie-value', { domain: currentDomain });
+ const cookie = await cookieStore.get('cookie-name');
+ assert_equals(cookie.name, 'cookie-name');
+ assert_equals(cookie.value, 'cookie-value');
+
+ await async_cleanup(async () => {
+ await cookieStore.delete('cookie-name', { domain: currentDomain });
+ });
+}, 'cookieStore.set with domain set to the current hostname');
+
+promise_test(async testCase => {
+ const currentUrl = new URL(self.location.href);
+ const currentDomain = currentUrl.hostname;
+ const subDomain = `sub.${currentDomain}`;
+ await cookieStore.delete('cookie-name', { domain: currentDomain });
+ await cookieStore.delete('cookie-name', { domain: subDomain });
+
+ await cookieStore.set(
+ 'cookie-name', 'cookie-value', { domain: subDomain });
+ const cookie = await cookieStore.get('cookie-name');
+ assert_equals(cookie, null);
+
+ await async_cleanup(async () => {
+ await cookieStore.delete('cookie-name', { domain: subDomain });
+ });
+}, 'cookieStore.set with domain set to a subdomain of the current hostname');
+
+promise_test(async testCase => {
+ const currentUrl = new URL(self.location.href);
+ const currentDomain = currentUrl.hostname;
+ await cookieStore.delete('cookie-name');
+
+ await cookieStore.set('cookie-name', 'cookie-old-value');
+ await cookieStore.set(
+ 'cookie-name', 'cookie-new-value', { domain: currentDomain });
+
+ const cookies = await cookieStore.getAll('cookie-name');
+ assert_equals(cookies.length, 1);
+ assert_equals(cookies[0].name, 'cookie-name');
+ assert_equals(cookies[0].value, 'cookie-new-value');
+
+ await async_cleanup(async () => {
+ await cookieStore.delete('cookie-name');
+ await cookieStore.delete('cookie-name', { domain: currentDomain });
+ });
+}, 'cookieStore.set default domain is current hostname');
+
+promise_test(async testCase => {
+ const currentUrl = new URL(self.location.href);
+ const currentPath = currentUrl.pathname;
+ const currentDirectory =
+ currentPath.substr(0, currentPath.lastIndexOf('/') + 1);
+ await cookieStore.delete('cookie-name', { path: currentDirectory });
+
+ await cookieStore.set(
+ 'cookie-name', 'cookie-value', { path: currentDirectory });
+ const cookie = await cookieStore.get('cookie-name');
+ assert_equals(cookie.name, 'cookie-name');
+ assert_equals(cookie.value, 'cookie-value');
+
+ await async_cleanup(async () => {
+ await cookieStore.delete('cookie-name', { path: currentDirectory });
+ });
+}, 'cookieStore.set with path set to the current directory');
+
+promise_test(async testCase => {
+ const currentUrl = new URL(self.location.href);
+ const currentPath = currentUrl.pathname;
+ const currentDirectory =
+ currentPath.substr(0, currentPath.lastIndexOf('/') + 1);
+ const subDirectory = currentDirectory + "subdir/";
+ await cookieStore.delete('cookie-name', { path: currentDirectory });
+ await cookieStore.delete('cookie-name', { path: subDirectory });
+
+ await cookieStore.set(
+ 'cookie-name', 'cookie-value', { path: subDirectory });
+ const cookie = await cookieStore.get('cookie-name');
+ assert_equals(cookie, null);
+
+ await async_cleanup(async () => {
+ await cookieStore.delete('cookie-name', { path: subDirectory });
+ });
+}, 'cookieStore.set with path set to a subdirectory of the current directory');
+
+promise_test(async testCase => {
+ await cookieStore.delete('cookie-name');
+
+ await cookieStore.set('cookie-name', 'cookie-old-value');
+ await cookieStore.set('cookie-name', 'cookie-new-value', { path: '/' });
+
+ const cookies = await cookieStore.getAll('cookie-name');
+ assert_equals(cookies.length, 1);
+ assert_equals(cookies[0].name, 'cookie-name');
+ assert_equals(cookies[0].value, 'cookie-new-value');
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+ await async_cleanup(() => cookieStore.delete('cookie-name', { path: '/' }));
+}, 'cookieStore.set default path is /');
diff --git a/tests/wpt/web-platform-tests/cookie-store/cookieStore_special_names.tentative.html b/tests/wpt/web-platform-tests/cookie-store/cookieStore_special_names.tentative.html
new file mode 100644
index 00000000000..3a80f83a03b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/cookieStore_special_names.tentative.html
@@ -0,0 +1,35 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Async Cookies: cookieStore handles special cookie names correctly</title>
+<link rel="help" href="https://github.com/WICG/cookie-store">
+<link rel="author" href="pwnall@chromium.org" title="Victor Costan">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+'use strict';
+
+promise_test(async testCase => {
+ await promise_rejects(testCase, new TypeError(), cookieStore.set(
+ '__Secure-cookie-name', 'secure-cookie-value'));
+
+ try { await cookieStore.delete('__Secure-cookie-name'); } catch (e) {}
+}, 'cookieStore.set with __Secure- name on insecure origin');
+
+promise_test(async testCase => {
+ await promise_rejects(testCase, new TypeError(), cookieStore.set(
+ '__Host-cookie-name', 'host-cookie-value'));
+
+ try { await cookieStore.delete('__Host-cookie-name'); } catch (e) {}
+}, 'cookieStore.set with __Host- name on insecure origin');
+
+promise_test(async testCase => {
+ await promise_rejects(testCase, new TypeError(), cookieStore.delete(
+ '__Secure-cookie-name', 'secure-cookie-value'));
+}, 'cookieStore.delete with __Secure- name on insecure origin');
+
+promise_test(async testCase => {
+ await promise_rejects(testCase, new TypeError(), cookieStore.delete(
+ '__Host-cookie-name', 'host-cookie-value'));
+}, 'cookieStore.delete with __Host- name on insecure origin');
+
+</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests.tentative.html b/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests.tentative.html
index 383914a118b..39962c750ae 100644
--- a/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests.tentative.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: Basic tests for cookieStore</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests.tentative.https.html
index a892d46c752..3bf592e7fce 100644
--- a/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests.tentative.https.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: Basic tests for cookieStore (HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests_static.tentative.html b/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests_static.tentative.html
index 6a4fa758638..6f0a3c9ecd5 100644
--- a/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests_static.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests_static.tentative.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: Basic tests for cookieStore (Static)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests_static.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests_static.tentative.https.html
index 0776ab38640..08784f87ffe 100644
--- a/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests_static.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/cookie_store_tests_static.tentative.https.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: Basic tests for cookieStore (Static; HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/delete_cookies.tentative.html b/tests/wpt/web-platform-tests/cookie-store/delete_cookies.tentative.html
index db8bd93e3bf..786885ab3c5 100644
--- a/tests/wpt/web-platform-tests/cookie-store/delete_cookies.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/delete_cookies.tentative.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: delete cookies</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/delete_cookies.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/delete_cookies.tentative.https.html
index e042fcffdee..accb4d20d5e 100644
--- a/tests/wpt/web-platform-tests/cookie-store/delete_cookies.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/delete_cookies.tentative.https.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: delete cookies (HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/delete_cookies_static.tentative.html b/tests/wpt/web-platform-tests/cookie-store/delete_cookies_static.tentative.html
index 045a3e74e0d..0ceb517f399 100644
--- a/tests/wpt/web-platform-tests/cookie-store/delete_cookies_static.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/delete_cookies_static.tentative.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: delete cookies (Static)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/delete_cookies_static.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/delete_cookies_static.tentative.https.html
index da8e24f9fd4..a022c28e9c7 100644
--- a/tests/wpt/web-platform-tests/cookie-store/delete_cookies_static.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/delete_cookies_static.tentative.https.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: delete cookies (Static; HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/document_cookie.tentative.html b/tests/wpt/web-platform-tests/cookie-store/document_cookie.tentative.html
index 5bcc0e92482..743f4efb40d 100644
--- a/tests/wpt/web-platform-tests/cookie-store/document_cookie.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/document_cookie.tentative.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: document.cookie</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/document_cookie.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/document_cookie.tentative.https.html
index 27e34d59be7..e19b841d0cf 100644
--- a/tests/wpt/web-platform-tests/cookie-store/document_cookie.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/document_cookie.tentative.https.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: document.cookie (HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/document_cookie_static.tentative.html b/tests/wpt/web-platform-tests/cookie-store/document_cookie_static.tentative.html
index 34c1ed91afc..8f671ddb34c 100644
--- a/tests/wpt/web-platform-tests/cookie-store/document_cookie_static.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/document_cookie_static.tentative.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: document.cookie (Static)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/document_cookie_static.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/document_cookie_static.tentative.https.html
index 0664910df90..065af2a0363 100644
--- a/tests/wpt/web-platform-tests/cookie-store/document_cookie_static.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/document_cookie_static.tentative.https.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: document.cookie (Static; HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/document_getAll_multiple.tentative.html b/tests/wpt/web-platform-tests/cookie-store/document_getAll_multiple.tentative.html
new file mode 100644
index 00000000000..57202da95fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/document_getAll_multiple.tentative.html
@@ -0,0 +1,41 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Async Cookies: cookieStore.getAll() sees cookieStore.set() cookie</title>
+<link rel="help" href="https://github.com/WICG/cookie-store">
+<link rel="author" href="pwnall@chromium.org" title="Victor Costan">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+'use strict';
+
+// Workaround because add_cleanup doesn't support async functions yet.
+// See https://github.com/w3c/web-platform-tests/issues/6075
+async function async_cleanup(cleanup_function) {
+ try {
+ await cleanup_function();
+ } catch (e) {
+ // Errors in cleanup functions shouldn't result in test failures.
+ }
+}
+
+promise_test(async testCase => {
+ await cookieStore.set('cookie-name', 'cookie-value');
+ await cookieStore.set('cookie-name-2', 'cookie-value-2');
+ await cookieStore.set('cookie-name-3', 'cookie-value-3');
+
+ const cookies = await cookieStore.getAll();
+ cookies.sort((a, b) => a.name.localeCompare(b.name));
+ assert_equals(cookies.length, 3);
+ assert_equals(cookies[0].name, 'cookie-name');
+ assert_equals(cookies[0].value, 'cookie-value');
+ assert_equals(cookies[1].name, 'cookie-name-2');
+ assert_equals(cookies[1].value, 'cookie-value-2');
+ assert_equals(cookies[2].name, 'cookie-name-3');
+ assert_equals(cookies[2].value, 'cookie-value-3');
+
+ await async_cleanup(() => cookieStore.delete('cookie-name'));
+ await async_cleanup(() => cookieStore.delete('cookie-name-2'));
+ await async_cleanup(() => cookieStore.delete('cookie-name-3'));
+}, 'cookieStore.getAll returns multiple cookies written by cookieStore.set');
+
+</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/expiration.tentative.html b/tests/wpt/web-platform-tests/cookie-store/expiration.tentative.html
index 3abe909823a..47a628d0633 100644
--- a/tests/wpt/web-platform-tests/cookie-store/expiration.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/expiration.tentative.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: expiration</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/expiration.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/expiration.tentative.https.html
index 50f0e2e160a..e4db1a6cbea 100644
--- a/tests/wpt/web-platform-tests/cookie-store/expiration.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/expiration.tentative.https.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: expiration (HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/expiration_static.tentative.html b/tests/wpt/web-platform-tests/cookie-store/expiration_static.tentative.html
index bfb8320a134..f9c601887d7 100644
--- a/tests/wpt/web-platform-tests/cookie-store/expiration_static.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/expiration_static.tentative.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: expiration (Static)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/expiration_static.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/expiration_static.tentative.https.html
index e582849d849..b6887686f46 100644
--- a/tests/wpt/web-platform-tests/cookie-store/expiration_static.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/expiration_static.tentative.https.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: expiration (Static; HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/get_set_get_all.tentative.html b/tests/wpt/web-platform-tests/cookie-store/get_set_get_all.tentative.html
index cc59bd5beb5..2574ade51b0 100644
--- a/tests/wpt/web-platform-tests/cookie-store/get_set_get_all.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/get_set_get_all.tentative.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: get, set, getAll</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/get_set_get_all.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/get_set_get_all.tentative.https.html
index 3d37ec9cc34..5a52fdd401c 100644
--- a/tests/wpt/web-platform-tests/cookie-store/get_set_get_all.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/get_set_get_all.tentative.https.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: get, set, getAll (HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/get_set_get_all_static.tentative.html b/tests/wpt/web-platform-tests/cookie-store/get_set_get_all_static.tentative.html
index aa7fa312cb6..08921794983 100644
--- a/tests/wpt/web-platform-tests/cookie-store/get_set_get_all_static.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/get_set_get_all_static.tentative.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: get, set, getAll (Static)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/get_set_get_all_static.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/get_set_get_all_static.tentative.https.html
index 31c8c1df950..6e44c0d4ccb 100644
--- a/tests/wpt/web-platform-tests/cookie-store/get_set_get_all_static.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/get_set_get_all_static.tentative.https.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: get, set, getAll (Static; HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/http_cookie_and_set_cookie_headers.tentative.html b/tests/wpt/web-platform-tests/cookie-store/http_cookie_and_set_cookie_headers.tentative.html
index bfe6eaa0663..8784885d2a2 100644
--- a/tests/wpt/web-platform-tests/cookie-store/http_cookie_and_set_cookie_headers.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/http_cookie_and_set_cookie_headers.tentative.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: HTTP Cookie and Set-Cookie headers</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/http_cookie_and_set_cookie_headers.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/http_cookie_and_set_cookie_headers.tentative.https.html
index 56649e5f2d6..9b057790d71 100644
--- a/tests/wpt/web-platform-tests/cookie-store/http_cookie_and_set_cookie_headers.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/http_cookie_and_set_cookie_headers.tentative.https.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: HTTP Cookie and Set-Cookie headers (HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie.tentative.html b/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie.tentative.html
index 69943ec4313..978aa8b3bbd 100644
--- a/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie.tentative.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: <title>Async Cookies: document.cookie</title>lt;Meta Http-Equiv="Set-Cookie" ... <title>Async Cookies: document.cookie</title>gt;</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie.tentative.https.html
index 43bde2eb8eb..38192b1147f 100644
--- a/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie.tentative.https.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: <title>Async Cookies: document.cookie</title>lt;Meta Http-Equiv="Set-Cookie" ... <title>Async Cookies: document.cookie</title>gt; (HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie_static.tentative.html b/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie_static.tentative.html
index 55d90aac01f..a7063e68a4d 100644
--- a/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie_static.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie_static.tentative.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: <title>Async Cookies: document.cookie</title>lt;Meta Http-Equiv="Set-Cookie" ... <title>Async Cookies: document.cookie</title>gt; (Static)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie_static.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie_static.tentative.https.html
index fd07594ca1e..830b92710fe 100644
--- a/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie_static.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/meta_http_equiv_set_cookie_static.tentative.https.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: <title>Async Cookies: document.cookie</title>lt;Meta Http-Equiv="Set-Cookie" ... <title>Async Cookies: document.cookie</title>gt; (Static; HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value.tentative.html b/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value.tentative.html
index e7ea7c837a5..25bbb82054f 100644
--- a/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value.tentative.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: Test No Name and No Value</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value.tentative.https.html
index 07eb950e830..3f2554424f3 100644
--- a/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value.tentative.https.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: Test No Name and No Value (HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value_static.tentative.html b/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value_static.tentative.html
index c40fbec6539..d4a66b0ed50 100644
--- a/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value_static.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value_static.tentative.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: Test No Name and No Value (Static)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value_static.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value_static.tentative.https.html
index 463af00f3ff..46e0bf93cf6 100644
--- a/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value_static.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/no_name_and_no_value_static.tentative.https.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: Test No Name and No Value (Static; HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value.tentative.html b/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value.tentative.html
index 07767a99fa8..849af3c1627 100644
--- a/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value.tentative.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: Test No Name, '=' in Value</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value.tentative.https.html
index 30b3c9e7e01..d352768426f 100644
--- a/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value.tentative.https.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: Test No Name, '=' in Value (HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value_static.tentative.html b/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value_static.tentative.html
index 24a85582dc6..02fd5f71113 100644
--- a/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value_static.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value_static.tentative.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: Test No Name, '=' in Value (Static)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value_static.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value_static.tentative.https.html
index badeae4a1f4..a3d9ec08fef 100644
--- a/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value_static.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/no_name_equals_in_value_static.tentative.https.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: Test No Name, '=' in Value (Static; HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values.tentative.html b/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values.tentative.html
index e1b0aa11afa..e4f208cc974 100644
--- a/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values.tentative.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: Test No Name, Multiple Values</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values.tentative.https.html
index f29e3fa9373..a3ff0cebb8e 100644
--- a/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values.tentative.https.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: Test No Name, Multiple Values (HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values_static.tentative.html b/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values_static.tentative.html
index 3200eb69aef..8e61be6381f 100644
--- a/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values_static.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values_static.tentative.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: Test No Name, Multiple Values (Static)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values_static.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values_static.tentative.https.html
index 1c8e920c5e4..6d2a684922e 100644
--- a/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values_static.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/no_name_multiple_values_static.tentative.https.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: Test No Name, Multiple Values (Static; HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/observation.tentative.html b/tests/wpt/web-platform-tests/cookie-store/observation.tentative.html
index 7a70b2bceb3..d2c9e6a87e7 100644
--- a/tests/wpt/web-platform-tests/cookie-store/observation.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/observation.tentative.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: Test Observation</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/observation.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/observation.tentative.https.html
index c499171e95e..11ee8e46968 100644
--- a/tests/wpt/web-platform-tests/cookie-store/observation.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/observation.tentative.https.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: Test Observation (HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/observation_static.tentative.html b/tests/wpt/web-platform-tests/cookie-store/observation_static.tentative.html
index b524b05efe5..422ab39ed79 100644
--- a/tests/wpt/web-platform-tests/cookie-store/observation_static.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/observation_static.tentative.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: Test Observation (Static)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/observation_static.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/observation_static.tentative.https.html
index 3d953c25c07..323dc86a1ea 100644
--- a/tests/wpt/web-platform-tests/cookie-store/observation_static.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/observation_static.tentative.https.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: Test Observation (Static; HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie.tentative.html b/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie.tentative.html
index 2bf2ae60174..1ca217ee4bc 100644
--- a/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie.tentative.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: One simple origin cookie</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie.tentative.https.html
index 05e586de638..f27f7f4f2b6 100644
--- a/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie.tentative.https.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: One simple origin cookie (HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie_static.tentative.html b/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie_static.tentative.html
index f7e04eacc57..88bd8ba37ca 100644
--- a/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie_static.tentative.html
+++ b/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie_static.tentative.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: One simple origin cookie (Static)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie_static.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie_static.tentative.https.html
index 25e155a88e7..f53d81a21f9 100644
--- a/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie_static.tentative.https.html
+++ b/tests/wpt/web-platform-tests/cookie-store/one_simple_origin_cookie_static.tentative.https.html
@@ -2,7 +2,7 @@
<meta charset="utf-8">
<meta name="timeout" content="long">
<title>Async Cookies: One simple origin cookie (Static; HTTPS)</title>
-<meta name="help" href="https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md">
+<meta name="help" href="https://github.com/WICG/cookie-store/blob/gh-pages/explainer.md">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/testharness-helpers.js"></script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/resources/cookie-store-tests.js b/tests/wpt/web-platform-tests/cookie-store/resources/cookie-store-tests.js
index f9bb78f7555..413dee98f86 100644
--- a/tests/wpt/web-platform-tests/cookie-store/resources/cookie-store-tests.js
+++ b/tests/wpt/web-platform-tests/cookie-store/resources/cookie-store-tests.js
@@ -142,31 +142,31 @@ const suite = ({testName = undefined} = {}) => {
}
await promise_rejects_when_unsecured(
testCase,
- new SyntaxError(),
+ new TypeError(),
testThreeSimpleOriginSessionCookiesSetSequentially(),
'__Host- cookies only writable from secure contexts' +
' (testThreeSimpleOriginSessionCookiesSetSequentially)');
await promise_rejects_when_unsecured(
testCase,
- new SyntaxError(),
+ new TypeError(),
testThreeSimpleOriginSessionCookiesSetNonsequentially(),
'__Host- cookies only writable from secure contexts' +
' (testThreeSimpleOriginSessionCookiesSetNonsequentially)');
await promise_rejects_when_unsecured(
testCase,
- new SyntaxError(),
+ new TypeError(),
setExpiredSecureCookieWithDomainPathAndFallbackValue(),
'Secure cookies only writable from secure contexts' +
' (setExpiredSecureCookieWithDomainPathAndFallbackValue)');
await promise_rejects_when_unsecured(
testCase,
- new SyntaxError(),
+ new TypeError(),
deleteSimpleOriginCookie(),
'__Host- cookies only writable from secure contexts' +
' (deleteSimpleOriginCookie)');
await promise_rejects_when_unsecured(
testCase,
- new SyntaxError(),
+ new TypeError(),
deleteSecureCookieWithDomainAndPath(),
'Secure cookies only writable from secure contexts' +
' (deleteSecureCookieWithDomainAndPath)');
@@ -277,56 +277,41 @@ const suite = ({testName = undefined} = {}) => {
// Parameters:
// - testCase: (TestCase) Context in which the testDeleteCookies is run.
const testDeleteCookies = async testCase => {
- let exceptions = [];
- for (let resetStep of [
- async () => await cookieStore.delete(''),
- async () => await cookieStore.delete('TEST'),
- async () => await cookieStore.delete('META-🍪'),
- async () => await cookieStore.delete('DOCUMENT-🍪'),
- async () => await cookieStore.delete('HTTP-🍪'),
- async () => {
- if (!kIsStatic) await setCookieStringHttp(
- 'HTTPONLY-🍪=DELETED; path=/; max-age=0; httponly');
- },
- async () => await promise_rejects_when_unsecured(
- testCase,
- new SyntaxError(),
- cookieStore.delete('__Host-COOKIENAME')),
- async () => await promise_rejects_when_unsecured(
- testCase,
- new SyntaxError(),
- cookieStore.delete('__Host-1🍪')),
- async () => await promise_rejects_when_unsecured(
- testCase,
- new SyntaxError(),
- cookieStore.delete('__Host-2🌟')),
- async () => await promise_rejects_when_unsecured(
- testCase,
- new SyntaxError(),
- cookieStore.delete('__Host-3🌱')),
- async () => await promise_rejects_when_unsecured(
- testCase,
- new SyntaxError(),
- cookieStore.delete('__Host-unordered1🍪')),
- async () => await promise_rejects_when_unsecured(
- testCase,
- new SyntaxError(),
- cookieStore.delete('__Host-unordered2🌟')),
- async () => await promise_rejects_when_unsecured(
- testCase,
- new SyntaxError(),
- cookieStore.delete('__Host-unordered3🌱')),
- ]) {
- try {
- await resetStep();
- } catch (x) {
- exceptions.push(x);
- };
- }
- assert_equals(
- exceptions.length,
- 0,
- 'testDeleteCookies failures: ' + exceptions);
+ await cookieStore.delete('');
+ await cookieStore.delete('TEST');
+ await cookieStore.delete('META-🍪');
+ await cookieStore.delete('DOCUMENT-🍪');
+ await cookieStore.delete('HTTP-🍪');
+ if (!kIsStatic) await setCookieStringHttp(
+ 'HTTPONLY-🍪=DELETED; path=/; max-age=0; httponly');
+ await promise_rejects_when_unsecured(
+ testCase,
+ new TypeError(),
+ cookieStore.delete('__Host-COOKIENAME'));
+ await promise_rejects_when_unsecured(
+ testCase,
+ new TypeError(),
+ cookieStore.delete('__Host-1🍪'));
+ await promise_rejects_when_unsecured(
+ testCase,
+ new TypeError(),
+ cookieStore.delete('__Host-2🌟'));
+ await promise_rejects_when_unsecured(
+ testCase,
+ new TypeError(),
+ cookieStore.delete('__Host-3🌱'));
+ await promise_rejects_when_unsecured(
+ testCase,
+ new TypeError(),
+ cookieStore.delete('__Host-unordered1🍪'));
+ await promise_rejects_when_unsecured(
+ testCase,
+ new TypeError(),
+ cookieStore.delete('__Host-unordered2🌟'));
+ await promise_rejects_when_unsecured(
+ testCase,
+ new TypeError(),
+ cookieStore.delete('__Host-unordered3🌱'));
};
// Helper to verify first-of-name get using async/await.
@@ -1029,7 +1014,7 @@ const testGetSetGetAll = async () => {
const testOneSimpleOriginCookie = async testCase => {
await promise_rejects_when_unsecured(
testCase,
- new SyntaxError(),
+ new TypeError(),
setOneSimpleOriginSessionCookie(),
'__Host- prefix only writable from' +
' secure contexts (setOneSimpleOriginSessionCookie)');
@@ -1064,7 +1049,7 @@ const testOneSimpleOriginCookie = async testCase => {
const testExpiration = async testCase => {
await promise_rejects_when_unsecured(
testCase,
- new SyntaxError(),
+ new TypeError(),
setOneDaySecureCookieWithDate(),
'Secure cookies only writable' +
' from secure contexts (setOneDaySecureCookieWithDate)');
@@ -1080,7 +1065,7 @@ const testExpiration = async testCase => {
await deleteUnsecuredCookieWithDomainAndPath();
await promise_rejects_when_unsecured(
testCase,
- new SyntaxError(),
+ new TypeError(),
setSecureCookieWithHttpLikeExpirationString(),
'Secure cookies only writable from secure contexts' +
' (setSecureCookieWithHttpLikeExpirationString)');
diff --git a/tests/wpt/web-platform-tests/cookie-store/resources/testharness-helpers.js b/tests/wpt/web-platform-tests/cookie-store/resources/testharness-helpers.js
index a9c2374f95a..7e644c78039 100644
--- a/tests/wpt/web-platform-tests/cookie-store/resources/testharness-helpers.js
+++ b/tests/wpt/web-platform-tests/cookie-store/resources/testharness-helpers.js
@@ -12,7 +12,7 @@ const kExtraObserverDelay = 0; // For builtin implementation
// document.open();
// document.write(`
// <script>delete cookieStore</script>
-// <script src="https://wicg.github.io/async-cookies-api/cookies.js">
+// <script src="https://wicg.github.io/cookie-store/cookies.js">
// </script>
// `);
// document.close()
diff --git a/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_arguments.js b/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_arguments.js
new file mode 100644
index 00000000000..0ffe6f8b0b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_arguments.js
@@ -0,0 +1,14 @@
+self.GLOBAL = {
+ isWindow: function() { return false; },
+ isWorker: function() { return true; },
+};
+importScripts("/resources/testharness.js");
+
+importScripts(
+ "cookieStore_delete_arguments.tentative.window.js",
+ "cookieStore_get_arguments.tentative.window.js",
+ "cookieStore_getAll_arguments.tentative.window.js",
+ "cookieStore_has_arguments.tentative.window.js",
+ "cookieStore_set_arguments.tentative.window.js");
+
+done();
diff --git a/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_arguments.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_arguments.tentative.https.html
new file mode 100644
index 00000000000..06c95014975
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_arguments.tentative.https.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Async Cookies: cookieStore API argument handling in ServiceWorker</title>
+<link rel="help" href="https://github.com/WICG/cookie-store">
+<link rel="author" href="pwnall@chromium.org" title="Victor Costan">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+'use strict';
+
+(async () => {
+ const scope = 'does/not/exist';
+
+ let registration = await navigator.serviceWorker.getRegistration(scope);
+ if (registration)
+ await registration.unregister();
+ registration = await navigator.serviceWorker.register(
+ 'serviceworker_cookieStore_arguments.js', {scope});
+
+ fetch_tests_from_worker(registration.installing);
+})();
+</script>
diff --git a/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_basic.js b/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_basic.js
new file mode 100644
index 00000000000..0d8039f9d33
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_basic.js
@@ -0,0 +1,13 @@
+self.GLOBAL = {
+ isWindow: function() { return false; },
+ isWorker: function() { return true; },
+};
+importScripts("/resources/testharness.js");
+
+importScripts(
+ "cookieStore_get_delete_basic.tentative.window.js",
+ "cookieStore_get_set_basic.tentative.window.js",
+ "cookieStore_getAll_set_basic.tentative.window.js",
+ "cookieStore_has_basic.tentative.window.js");
+
+done();
diff --git a/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_basic.tentative.https.html b/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_basic.tentative.https.html
new file mode 100644
index 00000000000..d4385d64ea9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookie-store/serviceworker_cookieStore_basic.tentative.https.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Async Cookies: cookieStore basic API in ServiceWorker</title>
+<link rel="help" href="https://github.com/WICG/cookie-store">
+<link rel="author" href="pwnall@chromium.org" title="Victor Costan">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+'use strict';
+
+(async () => {
+ const scope = 'does/not/exist';
+
+ let registration = await navigator.serviceWorker.getRegistration(scope);
+ if (registration)
+ await registration.unregister();
+ registration = await navigator.serviceWorker.register(
+ 'serviceworker_cookieStore_basic.js', {scope});
+
+ fetch_tests_from_worker(registration.installing);
+})();
+</script>
diff --git a/tests/wpt/web-platform-tests/cookies/OWNERS b/tests/wpt/web-platform-tests/cookies/OWNERS
new file mode 100644
index 00000000000..570af272851
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookies/OWNERS
@@ -0,0 +1,2 @@
+@inikulin
+@mikewest
diff --git a/tests/wpt/web-platform-tests/cookies/README.md b/tests/wpt/web-platform-tests/cookies/README.md
new file mode 100644
index 00000000000..ed86aebf183
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookies/README.md
@@ -0,0 +1,2 @@
+This directory contains tests for
+[Leave Secure Cookies Alone](https://tools.ietf.org/html/draft-ietf-httpbis-cookie-alone-01).
diff --git a/tests/wpt/web-platform-tests/cookies/meta-blocked.html b/tests/wpt/web-platform-tests/cookies/meta-blocked.html
new file mode 100644
index 00000000000..1b86e65c87c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookies/meta-blocked.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<head>
+ <meta http-equiv="set-cookie" content="meta-set-cookie=1">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <script>
+ test(t => {
+ assert_equals(document.cookie.indexOf('meta-set-cookie'), -1);
+ }, "Cookie is not set from `<meta>`.");
+ </script>
+</body>
diff --git a/tests/wpt/web-platform-tests/cookies/path/echo-cookie.html b/tests/wpt/web-platform-tests/cookies/path/echo-cookie.html
deleted file mode 100644
index dd515a883c8..00000000000
--- a/tests/wpt/web-platform-tests/cookies/path/echo-cookie.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!doctype html>
-<html>
-<head>
- <meta charset=utf-8>
- <title>helper iframe for matching cookie path tests</title>
- <meta name=help href="http://tools.ietf.org/html/rfc6265#section-5.1.4">
-</head>
-<body>
-<script>
-window.setCookie = function (name, path) {
- document.cookie = name + '=1; path = ' + path + ';';
-}
-window.fetchCookieThen = function (name, path) {
- return fetch("/cookies/resources/set-cookie.py?name=" + encodeURIComponent(name) + "&path=" + encodeURIComponent(path));
-};
-window.isCookieSet = function (name, path) {
- return document.cookie.match(name + '=1');
-};
-window.expireCookie = function (name, path) {
- document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=' + path + ';';
-};
-</script>
-</body>
-</html>
diff --git a/tests/wpt/web-platform-tests/cookies/path/match.html b/tests/wpt/web-platform-tests/cookies/path/match.html
index c3f2f8e87ad..54026ef8465 100644
--- a/tests/wpt/web-platform-tests/cookies/path/match.html
+++ b/tests/wpt/web-platform-tests/cookies/path/match.html
@@ -16,32 +16,32 @@
var body = document.getElementsByTagName('body')[0];
var createIframeThen = function (callback) {
var iframe = document.createElement('iframe');
- iframe.src = "echo-cookie.html";
+ iframe.src = "/cookies/resources/echo-cookie.html";
body.appendChild(iframe);
iframe.onload = callback;
return iframe;
};
var testCookiePathFromDOM = function (testCase, test) {
var iframe = createIframeThen(test.step_func(function () {
- iframe.contentWindow.setCookie(testCase.name, testCase.path);
- var cookieSet = iframe.contentWindow.isCookieSet(testCase.name, testCase.path);
+ iframe.contentWindow.setCookie('dom-' + testCase.name, testCase.path);
+ var cookieSet = iframe.contentWindow.isCookieSet('dom-' + testCase.name, testCase.path);
if (testCase.match === false) {
assert_equals(cookieSet, null);
} else {
assert_not_equals(cookieSet, null);
}
- iframe.contentWindow.expireCookie(testCase.name, testCase.path);
+ iframe.contentWindow.expireCookie('dom-' + testCase.name, testCase.path);
test.done();
}));
};
var testCookiePathFromHeader = function (testCase, test) {
var iframe = createIframeThen(test.step_func(function () {
- iframe.contentWindow.fetchCookieThen(testCase.name, testCase.path).then(test.step_func(function (response) {
+ iframe.contentWindow.fetchCookieThen('header-' + testCase.name, testCase.path).then(test.step_func(function (response) {
assert_true(response.ok);
- var cookieSet = iframe.contentWindow.isCookieSet(testCase.name, testCase.path);
- iframe.contentWindow.expireCookie(testCase.name, testCase.path);
+ var cookieSet = iframe.contentWindow.isCookieSet('header-' + testCase.name, testCase.path);
+ iframe.contentWindow.expireCookie('header-' + testCase.name, testCase.path);
if (testCase.match === false) {
assert_equals(cookieSet, null);
} else {
@@ -70,7 +70,7 @@ var tests = [{
"path": "/cookies/",
}, {
"name": "match-exact-page",
- "path": "/cookies/path/echo-cookie.html",
+ "path": "/cookies/resources/echo-cookie.html",
}, {
"name": "no-match",
"path": "/cook",
@@ -82,9 +82,9 @@ var tests = [{
}];
var domTests = tests.map(function (testCase) {
- var testName = "`document.cookie` on /cookies/path/echo-cookie.html sets cookie with path: " + testCase.path;
+ var testName = "`document.cookie` on /cookies/resources/echo-cookie.html sets cookie with path: " + testCase.path;
if (testCase.match === false) {
- testName = "`document.cookie` on /cookies/path/echo-cookie.html DOES NOT set cookie for path: " + testCase.path;
+ testName = "`document.cookie` on /cookies/resources/echo-cookie.html DOES NOT set cookie for path: " + testCase.path;
}
return [
testName,
@@ -95,9 +95,9 @@ var domTests = tests.map(function (testCase) {
});
var headerTests = tests.map(function (testCase) {
- var testName = "`Set-Cookie` on /cookies/path/echo-cookie.html sets cookie with path: " + testCase.path;
+ var testName = "`Set-Cookie` on /cookies/resources/echo-cookie.html sets cookie with path: " + testCase.path;
if (testCase.match === false) {
- testName = "`Set-Cookie` on /cookies/path/echo-cookie.html DOES NOT set cookie for path: " + testCase.path;
+ testName = "`Set-Cookie` on /cookies/resources/echo-cookie.html DOES NOT set cookie for path: " + testCase.path;
}
return [
testName,
diff --git a/tests/wpt/web-platform-tests/cookies/resources/echo-cookie.html b/tests/wpt/web-platform-tests/cookies/resources/echo-cookie.html
new file mode 100644
index 00000000000..a715b8b4294
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cookies/resources/echo-cookie.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>helper iframe for matching cookie path tests</title>
+ <meta name=help href="http://tools.ietf.org/html/rfc6265#section-5.1.4">
+</head>
+<body>
+<script>
+window.setCookie = function (name, path) {
+ document.cookie = name + '=1; Path=' + path + ';';
+}
+window.fetchCookieThen = function (name, path) {
+ return fetch("/cookies/resources/set-cookie.py?name=" + encodeURIComponent(name) + "&path=" + encodeURIComponent(path), {'credentials': 'include'});
+};
+window.isCookieSet = function (name, path) {
+ return document.cookie.match(name + '=1');
+};
+window.expireCookie = function (name, path) {
+ document.cookie = name + '=0; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=' + path + ';';
+};
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/cookies/secure/set-from-ws.https.sub.html b/tests/wpt/web-platform-tests/cookies/secure/set-from-ws.sub.html
index b12504450ee..b12504450ee 100644
--- a/tests/wpt/web-platform-tests/cookies/secure/set-from-ws.https.sub.html
+++ b/tests/wpt/web-platform-tests/cookies/secure/set-from-ws.sub.html
diff --git a/tests/wpt/web-platform-tests/core-aam/aria-checked_value_changes-manual.html b/tests/wpt/web-platform-tests/core-aam/aria-checked_value_changes-manual.html
index e3fb3335739..5de5e8a1111 100644
--- a/tests/wpt/web-platform-tests/core-aam/aria-checked_value_changes-manual.html
+++ b/tests/wpt/web-platform-tests/core-aam/aria-checked_value_changes-manual.html
@@ -59,7 +59,7 @@
"event",
"type",
"is",
- "TBD"
+ "TogglePattern.ToggleStateProperty"
]
]
},
@@ -111,7 +111,7 @@
"event",
"type",
"is",
- "TBD"
+ "TogglePattern.ToggleStateProperty"
]
]
},
diff --git a/tests/wpt/web-platform-tests/core-aam/aria-expanded_value_changes-manual.html b/tests/wpt/web-platform-tests/core-aam/aria-expanded_value_changes-manual.html
index 873094b47ad..e8f58d2dec0 100644
--- a/tests/wpt/web-platform-tests/core-aam/aria-expanded_value_changes-manual.html
+++ b/tests/wpt/web-platform-tests/core-aam/aria-expanded_value_changes-manual.html
@@ -65,7 +65,7 @@
"event",
"type",
"is",
- "TBD"
+ "ExpandCollapsePattern.ExpandCollapseStateProperty"
]
]
},
@@ -123,7 +123,7 @@
"event",
"type",
"is",
- "TBD"
+ "ExpandCollapsePattern.ExpandCollapseStateProperty"
]
]
},
diff --git a/tests/wpt/web-platform-tests/core-aam/aria-flowto-manual.html b/tests/wpt/web-platform-tests/core-aam/aria-flowto-manual.html
index f8e55a4b05f..23816319bc6 100644
--- a/tests/wpt/web-platform-tests/core-aam/aria-flowto-manual.html
+++ b/tests/wpt/web-platform-tests/core-aam/aria-flowto-manual.html
@@ -36,7 +36,7 @@
"IAccessible2" : [
[
"relation",
- "IA2_RELATION_FLOW_TO",
+ "IA2_RELATION_FLOWS_TO",
"is",
"[next]"
]
@@ -67,7 +67,7 @@
"IAccessible2" : [
[
"relation",
- "IA2_RELATION_FLOW_FROM",
+ "IA2_RELATION_FLOWS_FROM",
"is",
"[test]"
]
diff --git a/tests/wpt/web-platform-tests/core-aam/aria-owns_may_need_manual_verification-manual.html b/tests/wpt/web-platform-tests/core-aam/aria-owns_may_need_manual_verification-manual.html
index 9510432fa54..b7752c3d6e4 100644
--- a/tests/wpt/web-platform-tests/core-aam/aria-owns_may_need_manual_verification-manual.html
+++ b/tests/wpt/web-platform-tests/core-aam/aria-owns_may_need_manual_verification-manual.html
@@ -44,15 +44,9 @@
"UIA" : [
[
"property",
- "TBD",
+ "Children",
"is",
- "owned1"
- ],
- [
- "property",
- "TBD",
- "is",
- "owned2"
+ "[owned1, owned2]"
]
]
},
diff --git a/tests/wpt/web-platform-tests/core-aam/aria-roledescription_is_empty_or_whitespace_characters_new-manual.html b/tests/wpt/web-platform-tests/core-aam/aria-roledescription_is_empty_or_whitespace_characters_new-manual.html
index 0703399e4d0..88fb7a8ea80 100644
--- a/tests/wpt/web-platform-tests/core-aam/aria-roledescription_is_empty_or_whitespace_characters_new-manual.html
+++ b/tests/wpt/web-platform-tests/core-aam/aria-roledescription_is_empty_or_whitespace_characters_new-manual.html
@@ -28,7 +28,7 @@
"UIA" : [
[
"property",
- "Localized Control Type",
+ "Localized ControlType",
"is",
"Group"
]
diff --git a/tests/wpt/web-platform-tests/core-aam/aria-valuenow_value_changes-manual.html b/tests/wpt/web-platform-tests/core-aam/aria-valuenow_value_changes-manual.html
index ad3d18693e8..6ef4f522e9a 100644
--- a/tests/wpt/web-platform-tests/core-aam/aria-valuenow_value_changes-manual.html
+++ b/tests/wpt/web-platform-tests/core-aam/aria-valuenow_value_changes-manual.html
@@ -53,7 +53,7 @@
"event",
"type",
"is",
- "TBD"
+ "ValuePattern.ValueProperty"
]
]
},
diff --git a/tests/wpt/web-platform-tests/core-aam/progressbar-manual.html b/tests/wpt/web-platform-tests/core-aam/progressbar-manual.html
index a336fa08607..3d3639254ab 100644
--- a/tests/wpt/web-platform-tests/core-aam/progressbar-manual.html
+++ b/tests/wpt/web-platform-tests/core-aam/progressbar-manual.html
@@ -62,7 +62,7 @@
"property",
"interfaces",
"contains",
- "IAcesssibleValue"
+ "IAccessibleValue"
]
],
"MSAA" : [
diff --git a/tests/wpt/web-platform-tests/core-aam/region_without_an_accessible_name_new-manual.html b/tests/wpt/web-platform-tests/core-aam/region_without_an_accessible_name_new-manual.html
index 05ca5e7b080..f3b41f0ab58 100644
--- a/tests/wpt/web-platform-tests/core-aam/region_without_an_accessible_name_new-manual.html
+++ b/tests/wpt/web-platform-tests/core-aam/region_without_an_accessible_name_new-manual.html
@@ -56,7 +56,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Group"
]
diff --git a/tests/wpt/web-platform-tests/core-aam/scrollbar-manual.html b/tests/wpt/web-platform-tests/core-aam/scrollbar-manual.html
index 3b4b5ff1725..2d1e400b179 100644
--- a/tests/wpt/web-platform-tests/core-aam/scrollbar-manual.html
+++ b/tests/wpt/web-platform-tests/core-aam/scrollbar-manual.html
@@ -56,7 +56,7 @@
"property",
"interfaces",
"contains",
- "IAcesssibleValue"
+ "IAccessibleValue"
]
],
"MSAA" : [
diff --git a/tests/wpt/web-platform-tests/core-aam/slider-manual.html b/tests/wpt/web-platform-tests/core-aam/slider-manual.html
index d0613e65a84..687ae799e3c 100644
--- a/tests/wpt/web-platform-tests/core-aam/slider-manual.html
+++ b/tests/wpt/web-platform-tests/core-aam/slider-manual.html
@@ -56,7 +56,7 @@
"property",
"interfaces",
"contains",
- "IAcesssibleValue"
+ "IAccessibleValue"
]
],
"MSAA" : [
diff --git a/tests/wpt/web-platform-tests/core-aam/spinbutton-manual.html b/tests/wpt/web-platform-tests/core-aam/spinbutton-manual.html
index 80f3f24dece..568faf3135d 100644
--- a/tests/wpt/web-platform-tests/core-aam/spinbutton-manual.html
+++ b/tests/wpt/web-platform-tests/core-aam/spinbutton-manual.html
@@ -56,7 +56,7 @@
"property",
"interfaces",
"contains",
- "IAcesssibleValue"
+ "IAccessibleValue"
]
],
"MSAA" : [
diff --git a/tests/wpt/web-platform-tests/credential-management/credentialscontainer-create-basics.https.html b/tests/wpt/web-platform-tests/credential-management/credentialscontainer-create-basics.https.html
index af304e23bbb..7898ccdc3e1 100644
--- a/tests/wpt/web-platform-tests/credential-management/credentialscontainer-create-basics.https.html
+++ b/tests/wpt/web-platform-tests/credential-management/credentialscontainer-create-basics.https.html
@@ -78,35 +78,6 @@ promise_test(function(t) {
}, "navigator.credentials.create() with bogus publicKey data");
promise_test(function(t) {
- var publicKey = {
- challenge: new TextEncoder().encode("climb a mountain"),
- rp: {
- id: "1098237235409872",
- name: "Acme"
- },
-
- user: {
- id: "1098237235409872",
- name: "avery.a.jones@example.com",
- displayName: "Avery A. Jones",
- icon: "https://pics.acme.com/00/p/aBjjjpqPb.png"
- },
-
- parameters: [{
- type: "public-key",
- algorithm: "ES256",
- },],
-
- timeout: 60000, // 1 minute
- excludeList: [], // No excludeList
- };
-
- return navigator.credentials.create({publicKey}).then(r => {
- assert_true(r instanceof PublicKeyCredential);
- });
-}, "navigator.credentials.create() returns PublicKeyCredential");
-
-promise_test(function(t) {
var credential_data = {
id: 'id',
password: 'pencil',
diff --git a/tests/wpt/web-platform-tests/credential-management/federatedcredential-framed-get.sub.https.html b/tests/wpt/web-platform-tests/credential-management/federatedcredential-framed-get.sub.https.html
new file mode 100644
index 00000000000..08688ab440b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/credential-management/federatedcredential-framed-get.sub.https.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+function create_iframe_test(origin, expectation) {
+ return function (t) {
+ assert_true(!!navigator.credentials, "`navigator.credentials` is supported.");
+ window.addEventListener("load", _ => {
+ var iframe = document.createElement("iframe");
+ iframe.src = origin + "/credential-management/support/federatedcredential-get.html";
+ window.addEventListener("message", t.step_func(e => {
+ if (e.source == iframe.contentWindow) {
+ assert_equals(e.data.status, expectation);
+ if (expectation == "rejected") {
+ assert_equals(e.data.exception, "NotAllowedError");
+ } else {
+ assert_equals(e.data.exception, null);
+ }
+ t.done();
+ }
+ }));
+ document.body.appendChild(iframe);
+ });
+ };
+}
+
+function create_nested_iframe_test(outerOrigin, innerOrigin, expectation) {
+ return function (t) {
+ assert_true(!!navigator.credentials, "`navigator.credentials` is supported.");
+ window.addEventListener("load", _ => {
+ var iframe = document.createElement("iframe");
+ iframe.src = outerOrigin + "/credential-management/support/echoing-nester.html?origin=" + innerOrigin + "&file=federatedcredential-get.html";
+ window.addEventListener("message", t.step_func(e => {
+ if (e.source == iframe.contentWindow) {
+ assert_equals(e.data.status, expectation);
+ if (expectation == "rejected") {
+ assert_equals(e.data.exception, "NotAllowedError");
+ } else {
+ assert_equals(e.data.exception, null);
+ }
+ t.done();
+ }
+ }));
+ document.body.appendChild(iframe);
+ });
+ };
+}
+
+const SAME_ORIGIN = window.origin;
+const CROSS_ORIGIN = "https://{{domains[élève]}}:{{ports[https][0]}}";
+
+async_test(
+ create_iframe_test(SAME_ORIGIN, "resolved"),
+ "Same-origin IFrame does not throw.");
+async_test(
+ create_iframe_test(CROSS_ORIGIN, "rejected"),
+ "Cross-origin IFrame throws 'NotAllowedError'.");
+
+async_test(
+ create_nested_iframe_test(SAME_ORIGIN, SAME_ORIGIN, "resolved"),
+ "Same-origin IFrame in same-origin IFrame does not throw.");
+
+async_test(
+ create_nested_iframe_test(SAME_ORIGIN, CROSS_ORIGIN, "rejected"),
+ "Same-origin IFrame in same-origin IFrame throws 'NotAllowedError'.");
+
+async_test(
+ create_nested_iframe_test(CROSS_ORIGIN, SAME_ORIGIN, "rejected"),
+ "Cross-origin IFrame in same-origin IFrame throws 'NotAllowedError'.");
+
+async_test(
+ create_nested_iframe_test(CROSS_ORIGIN, CROSS_ORIGIN, "rejected"),
+ "Cross-origin IFrame in same-cross-origin throws 'NotAllowedError'.");
+</script>
diff --git a/tests/wpt/web-platform-tests/credential-management/passwordcredential-framed-get.sub.https.html b/tests/wpt/web-platform-tests/credential-management/passwordcredential-framed-get.sub.https.html
new file mode 100644
index 00000000000..04bb16a2670
--- /dev/null
+++ b/tests/wpt/web-platform-tests/credential-management/passwordcredential-framed-get.sub.https.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+function create_iframe_test(origin, expectation) {
+ return function (t) {
+ assert_true(!!navigator.credentials, "`navigator.credentials` is supported.");
+ window.addEventListener("load", _ => {
+ var iframe = document.createElement("iframe");
+ iframe.src = origin + "/credential-management/support/passwordcredential-get.html";
+ window.addEventListener("message", t.step_func(e => {
+ if (e.source == iframe.contentWindow) {
+ assert_equals(e.data.status, expectation);
+ if (expectation == "rejected") {
+ assert_equals(e.data.exception, "NotAllowedError");
+ } else {
+ assert_equals(e.data.exception, null);
+ }
+ t.done();
+ }
+ }));
+ document.body.appendChild(iframe);
+ });
+ };
+}
+
+function create_nested_iframe_test(outerOrigin, innerOrigin, expectation) {
+ return function (t) {
+ assert_true(!!navigator.credentials, "`navigator.credentials` is supported.");
+ window.addEventListener("load", _ => {
+ var iframe = document.createElement("iframe");
+ iframe.src = outerOrigin + "/credential-management/support/echoing-nester.html?origin=" + innerOrigin + "&file=passwordcredential-get.html";
+ window.addEventListener("message", t.step_func(e => {
+ if (e.source == iframe.contentWindow) {
+ assert_equals(e.data.status, expectation);
+ if (expectation == "rejected") {
+ assert_equals(e.data.exception, "NotAllowedError");
+ } else {
+ assert_equals(e.data.exception, null);
+ }
+ t.done();
+ }
+ }));
+ document.body.appendChild(iframe);
+ });
+ };
+}
+
+const SAME_ORIGIN = window.origin;
+const CROSS_ORIGIN = "https://{{domains[élève]}}:{{ports[https][0]}}";
+
+async_test(
+ create_iframe_test(SAME_ORIGIN, "resolved"),
+ "Same-origin IFrame does not throw.");
+async_test(
+ create_iframe_test(CROSS_ORIGIN, "rejected"),
+ "Cross-origin IFrame throws 'NotAllowedError'.");
+
+async_test(
+ create_nested_iframe_test(SAME_ORIGIN, SAME_ORIGIN, "resolved"),
+ "Same-origin IFrame in same-origin IFrame does not throw.");
+
+async_test(
+ create_nested_iframe_test(SAME_ORIGIN, CROSS_ORIGIN, "rejected"),
+ "Same-origin IFrame in same-origin IFrame throws.");
+
+async_test(
+ create_nested_iframe_test(CROSS_ORIGIN, SAME_ORIGIN, "rejected"),
+ "Cross-origin IFrame in same-origin IFrame throws.");
+
+async_test(
+ create_nested_iframe_test(CROSS_ORIGIN, CROSS_ORIGIN, "rejected"),
+ "Cross-origin IFrame in same-cross-origin throws.");
+</script>
diff --git a/tests/wpt/web-platform-tests/credential-management/support/echoing-nester.html b/tests/wpt/web-platform-tests/credential-management/support/echoing-nester.html
new file mode 100644
index 00000000000..d4f5899da78
--- /dev/null
+++ b/tests/wpt/web-platform-tests/credential-management/support/echoing-nester.html
@@ -0,0 +1,16 @@
+<body>
+ <script>
+ window.addEventListener('message', m => {
+ window.parent.postMessage(m.data, '*');
+ });
+
+ var u = new URL(window.location.href);
+ var origin = u.searchParams.has('origin') ? u.searchParams.get('origin') : window.origin;
+ var file = u.searchParams.has('file') ? u.searchParams.get('file') : 'passwordcredential-get.html';
+
+ var url = origin + "/credential-management/support/" + file;
+ var i = document.createElement('iframe');
+ i.src = url;
+ document.body.appendChild(i);
+ </script>
+</body>
diff --git a/tests/wpt/web-platform-tests/credential-management/support/federatedcredential-get.html b/tests/wpt/web-platform-tests/credential-management/support/federatedcredential-get.html
new file mode 100644
index 00000000000..476f32688f9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/credential-management/support/federatedcredential-get.html
@@ -0,0 +1,17 @@
+<script>
+ navigator.credentials.get({ 'federated': { 'providers': ['https://example.com' ] } })
+ .then(c => {
+ window.parent.postMessage({
+ "status": "resolved",
+ "credential": c,
+ "exception": null
+ }, "*");
+ })
+ .catch(omg => {
+ window.parent.postMessage({
+ "status": "rejected",
+ "credential": null,
+ "exception": omg.name
+ }, "*");
+ });
+</script>
diff --git a/tests/wpt/web-platform-tests/credential-management/support/passwordcredential-get.html b/tests/wpt/web-platform-tests/credential-management/support/passwordcredential-get.html
new file mode 100644
index 00000000000..0ec584d73d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/credential-management/support/passwordcredential-get.html
@@ -0,0 +1,17 @@
+<script>
+ navigator.credentials.get({ 'password': true })
+ .then(c => {
+ window.parent.postMessage({
+ "status": "resolved",
+ "credential": c,
+ "exception": null
+ }, "*");
+ })
+ .catch(omg => {
+ window.parent.postMessage({
+ "status": "rejected",
+ "credential": null,
+ "exception": omg.name
+ }, "*");
+ });
+</script>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/backgrounds/background-color-030.xht b/tests/wpt/web-platform-tests/css/CSS2/backgrounds/background-color-030.xht
index 767cb1ff02c..050ad81401d 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/backgrounds/background-color-030.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/backgrounds/background-color-030.xht
@@ -13,8 +13,8 @@
<style type="text/css">
div
{
- height: 1in;
- width: 1in;
+ height: 100px;
+ width: 100px;
}
#wrapper
{
diff --git a/tests/wpt/web-platform-tests/css/CSS2/backgrounds/background-color-174.xht b/tests/wpt/web-platform-tests/css/CSS2/backgrounds/background-color-174.xht
index 8dcd75e0c13..2f8c89244e5 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/backgrounds/background-color-174.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/backgrounds/background-color-174.xht
@@ -13,8 +13,8 @@
<style type="text/css">
div
{
- height: 1in;
- width: 1in;
+ height: 100px;
+ width: 100px;
}
#wrapper
{
diff --git a/tests/wpt/web-platform-tests/css/CSS2/backgrounds/background-image-002.xht b/tests/wpt/web-platform-tests/css/CSS2/backgrounds/background-image-002.xht
index 89d6cb21b9a..285d7efcc3b 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/backgrounds/background-image-002.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/backgrounds/background-image-002.xht
@@ -14,8 +14,8 @@
div
{
background-image: url("support/green_box.png");
- height: 1in;
- width: 1in;
+ height: 100px;
+ width: 100px;
}
</style>
</head>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/colors/color-083-ref.xht b/tests/wpt/web-platform-tests/css/CSS2/colors/color-083-ref.xht
index 65f5c6f76e3..5417ef07e8f 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/colors/color-083-ref.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/colors/color-083-ref.xht
@@ -30,7 +30,6 @@
</div>
<div>
- <br />
<img alt="Image download support must be enabled" src="support/800000_color.png" />
</div>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/fonts/font-148-ref.xht b/tests/wpt/web-platform-tests/css/CSS2/fonts/font-148-ref.xht
new file mode 100644
index 00000000000..22a8e1a263b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/fonts/font-148-ref.xht
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+ <head>
+
+ <title>CSS Reftest Reference</title>
+ <link rel="author" title="Ondřej Žára" href="https://ondras.zarovi.cz/" />
+
+<style type="text/css">
+ div {
+ font: 10px sans-serif;
+ }
+ span {
+ font: 100px sans-serif;
+ }
+</style>
+
+ </head>
+
+ <body>
+ <p>Test passes if letters "def" below are larger than "abc" and "ghi".</p>
+ <div>abc<span class="test">def</span>ghi</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/CSS2/fonts/font-148.xht b/tests/wpt/web-platform-tests/css/CSS2/fonts/font-148.xht
new file mode 100644
index 00000000000..972aa1a7350
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/fonts/font-148.xht
@@ -0,0 +1,24 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>CSS Test: Font shorthand using calc() value for font-size</title>
+ <link rel="author" title="Ondřej Žára" href="https://ondras.zarovi.cz/" />
+ <link rel="help" href="https://www.w3.org/TR/css-fonts-4/#font-prop" />
+ <link rel="help" href="https://www.w3.org/TR/css-values-3/#calc-notation" />
+ <link rel="match" href="font-148-ref.xht"/>
+ <meta name="flags" content="" />
+ <meta name="assert" content="The 'font' shorthand property accepts and sets font-variant, font-size and font-family." />
+ <style type="text/css">
+ div {
+ font: 10px sans-serif;
+ }
+ span {
+ font: calc(10 * 10px) sans-serif;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if letters "def" below are larger than "abc" and "ghi".</p>
+ <div>abc<span class="test">def</span>ghi</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/after-inheritable-001-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/after-inheritable-001-ref.html
new file mode 100644
index 00000000000..77aa2dbd512
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/after-inheritable-001-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: solid;
+ color: green;
+ text-align: center;
+ }
+</style>
+<body>
+ <p>Test passes if the words "PASS PASS" below are green and the words are centered within the box below.</p>
+ <div>PASS PASS</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/after-inheritable-001.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/after-inheritable-001.xht
index 273defe20b3..aa1b4906249 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/after-inheritable-001.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/after-inheritable-001.xht
@@ -4,6 +4,7 @@
<title>CSS Test: Pseudo-element ':after' inherits inheritable values</title>
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#before-after-content" />
+ <link rel="match" href="after-inheritable-001-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The pseudo-element ':after' generated content inherits any inheritable properties from the element." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/after-inheritable-002-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/after-inheritable-002-ref.html
new file mode 100644
index 00000000000..541589be216
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/after-inheritable-002-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 15px solid blue;
+ color: green;
+ }
+ a {
+ border-color: orange;
+ border-style: solid;
+ }
+</style>
+<body>
+ <p>Test passes if the words "PASS PASS" are green, they are contained within an orange box with thinner lines than the blue box.</p>
+ <div><a>PASS PASS</a></div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/after-inheritable-002.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/after-inheritable-002.xht
index 827329382ec..dd56d042fdf 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/after-inheritable-002.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/after-inheritable-002.xht
@@ -4,6 +4,7 @@
<title>CSS Test: Pseudo-element ':after' does not inherit non-inheritable values</title>
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#before-after-content" />
+ <link rel="match" href="after-inheritable-002-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="Non-inherited properties apply their initial value when applying to ':after'." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/after-location-001-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/after-location-001-ref.html
new file mode 100644
index 00000000000..5b4f25f23d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/after-location-001-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<body>
+ <p>Test passes if the words "PASS PASS" appear below and are to the right of the arrow.</p>
+ <div>--&gt;PASS PASS</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/after-location-001.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/after-location-001.xht
index fa80f552774..4b89e88f632 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/after-location-001.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/after-location-001.xht
@@ -4,6 +4,7 @@
<title>CSS Test: After applies after text</title>
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#before-after-content" />
+ <link rel="match" href="after-location-001-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="After places the generated content after the element content." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/before-after-002.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/before-after-002.xht
index 127b6a82977..b99ca9ea3e5 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/before-after-002.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/before-after-002.xht
@@ -4,12 +4,13 @@
<title>CSS Test: Before, after is included in formatting changes</title>
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#before-after-content" />
+ <link rel="match" href="content-003-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="Generated content is included in any formatting changes made to an element." />
<style type="text/css">
div
{
- border: solid;
+ border: 2px solid black;
color: green;
}
div:before
@@ -23,7 +24,7 @@
</style>
</head>
<body>
- <p>Test passes if the words "PASS PASS" appear in green inside the box.</p>
+ <p>Test passes if the words "PASS PASS" appear in the box below.</p>
<div></div>
</body>
</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/before-inheritable-001.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/before-inheritable-001.xht
index 82153e2f5ff..f2407113029 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/before-inheritable-001.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/before-inheritable-001.xht
@@ -4,6 +4,7 @@
<title>CSS Test: Pseudo-element ':before' inherits inheritable values</title>
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#before-after-content" />
+ <link rel="match" href="after-inheritable-001-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The pseudo-element ':before' generated content inherits any inheritable properties from the element." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/before-inheritable-002.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/before-inheritable-002.xht
index ff8ae021965..ad422bfdfbb 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/before-inheritable-002.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/before-inheritable-002.xht
@@ -4,6 +4,7 @@
<title>CSS Test: Pseudo-element ':before' does not inherit non-inheritable values</title>
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#before-after-content" />
+ <link rel="match" href="after-inheritable-002-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="Non-inherited properties apply the initial value when applying to ':before'." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/before-location-001-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/before-location-001-ref.html
new file mode 100644
index 00000000000..d22138abd47
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/before-location-001-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<body>
+ <p>Test passes if the words "PASS PASS" appear below and are to the left of the arrow.</p>
+ <div>PASS PASS&lt;--</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/before-location-001.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/before-location-001.xht
index 222d2e8d8d0..6999ef652c2 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/before-location-001.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/before-location-001.xht
@@ -4,6 +4,7 @@
<title>CSS Test: Before applies before text</title>
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#before-after-content" />
+ <link rel="match" href="before-location-001-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="Before places generated content before the element content." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/bidi-generated-content-001-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/bidi-generated-content-001-ref.html
new file mode 100644
index 00000000000..9ff414acf30
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/bidi-generated-content-001-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<body>
+ <p>The two lines below should be identical:</p>
+ <p>This sentence should be readable</p>
+ <p>This sentence should be readable</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/bidi-generated-content-001.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/bidi-generated-content-001.xht
index 3e2e6f671f1..11e106254f9 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/bidi-generated-content-001.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/bidi-generated-content-001.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Eira Monstad, Opera Software ASA" href="mailto:public-testsuites@opera.com"/>
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content"/>
<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#direction"/>
+ <link rel="match" href="bidi-generated-content-001-ref.html" />
<meta name="assert" content="A right-to-left override should be applied when u+202E is inserted through the content property"/>
<style type="text/css"><![CDATA[
.force:before {
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/bidi-generated-content-002-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/bidi-generated-content-002-ref.html
new file mode 100644
index 00000000000..a7eaddf8164
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/bidi-generated-content-002-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<body>
+ <p>The two lines below should be identical:</p>
+ <p>ab c d</p>
+ <p>ab c d</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/bidi-generated-content-002.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/bidi-generated-content-002.xht
index b10e6415c3d..b9dd46d3cfc 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/bidi-generated-content-002.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/bidi-generated-content-002.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Eira Monstad, Opera Software ASA" href="mailto:public-testsuites@opera.com"/>
<link rel="help" href="http://www.w3.org/TR/CSS21/visuren.html#direction"/>
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content"/>
+ <link rel="match" href="bidi-generated-content-002-ref.html" />
<meta name="flags" content=""/>
<meta name="assert" content="A left-to-right override should be correctly applied when inserted through the content property"/>
<style type="text/css"><![CDATA[
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-001-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-001-ref.html
new file mode 100644
index 00000000000..b55f5fe2d3b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-001-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ height: 30px;
+ }
+</style>
+<body>
+ <p>Test passes if there is no red visible on the page.</p>
+ <div></div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-001.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-001.xht
index efd40d220c0..447d8dabe7c 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-001.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-001.xht
@@ -5,7 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
- <link rel="match" href="../reference/no-red-on-blank-page-ref.xht"/>
+ <link rel="match" href="content-001-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a value of 'none'." />
<style type="text/css">
@@ -15,7 +15,7 @@
content: none;
color: red;
}
- #div1
+ div
{
border: 2px solid black;
height: 30px;
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-002.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-002.xht
index b6ae000c67a..27c4a08a6c2 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-002.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-002.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-001-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a value of 'normal'." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-003-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-003-ref.html
new file mode 100644
index 00000000000..83017ff7e1b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-003-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ color: green;
+ }
+</style>
+<body>
+ <p>Test passes if the words "PASS PASS" appear in the box below.</p>
+ <div>PASS PASS</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-003.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-003.xht
index 9394d90c3e5..93f016a8269 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-003.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-003.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-003-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a string as a value." />
<style type="text/css">
@@ -16,12 +17,11 @@
div
{
border: 2px solid black;
- height: 30px;
}
</style>
</head>
<body>
- <p>Test passes if the words "PASS PASS" are in the box below.</p>
+ <p>Test passes if the words "PASS PASS" appear in the box below.</p>
<div></div>
</body>
</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-004.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-004.xht
index 7a2f183fc1c..1388f76d475 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-004.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-004.xht
@@ -5,17 +5,18 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="../../reference/ref-filled-green-100px-square-only.html" />
<meta name="flags" content="image" />
<meta name="assert" content="The 'content' property properly handles the 'url()' function as a value." />
<style type="text/css">
div:before
{
- content: url('support/green15x15.png');
+ content: url('../support/green_box.png');
}
</style>
</head>
<body>
- <p>Test passes if there is a green box below.</p>
+ <p>Test passes if there is a filled green square.</p>
<div></div>
</body>
</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-005-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-005-ref.html
new file mode 100644
index 00000000000..9947695209b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-005-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ height: 30px;
+ }
+</style>
+<body>
+ <p>Test passes if there is a zero "0" in the box below.</p>
+ <div>0</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-005.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-005.xht
index 7accf9253aa..3036214c3d2 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-005.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-005.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-005-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counter()' function as a value." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-006-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-006-ref.html
new file mode 100644
index 00000000000..1a597251502
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-006-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ height: 30px;
+ }
+</style>
+<body>
+ <p>Test passes if there is a bullet (&#x2022;) in the box below.</p>
+ <div>&#x2022;</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-006.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-006.xht
index bd4584e9037..297e27586af 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-006.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-006.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-006-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counter()' function with a list-style." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-007-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-007-ref.html
new file mode 100644
index 00000000000..7e50aaa9618
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-007-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ height: 30px;
+ }
+</style>
+<body>
+ <p>Test passes if there is a bullet (&#x25E6;) in the box below.</p>
+ <div>&#x25E6;</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-007.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-007.xht
index 9573188a593..c4449d12115 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-007.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-007.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-007-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counter()' function with a list-style." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-009.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-009.xht
index 743d338ff14..a245954e58d 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-009.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-009.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-005-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counter()' function with a list-style." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-010-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-010-ref.html
new file mode 100644
index 00000000000..85979c53b24
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-010-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ height: 30px;
+ }
+</style>
+<body>
+ <p>Test passes if there are double zeros "00" in the box below.</p>
+ <div>00</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-010.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-010.xht
index ac8550c6bb7..f0db8df1dfd 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-010.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-010.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-010-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counter()' function with a list-style." />
<style type="text/css">
@@ -20,7 +21,7 @@
</style>
</head>
<body>
- <p>Test passes if there is are double zeros "00" in the box below.</p>
+ <p>Test passes if there are double zeros "00" in the box below.</p>
<div></div>
</body>
</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-011-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-011-ref.html
new file mode 100644
index 00000000000..8bc5f313b3f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-011-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ height: 30px;
+ }
+</style>
+<body>
+ <p>Test passes if there is a letter "i" in the box below.</p>
+ <div>i</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-011.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-011.xht
index b5f8932b311..8bd626a695a 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-011.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-011.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-011-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counter()' function with a list-style." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-012-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-012-ref.html
new file mode 100644
index 00000000000..e628c5fc7cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-012-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ height: 30px;
+ }
+</style>
+<body>
+ <p>Test passes if there is a letter "I" in the box below.</p>
+ <div>I</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-012.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-012.xht
index 6ba353f3efb..1b57d03357b 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-012.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-012.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-012-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counter()' function with a list-style." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-013-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-013-ref.html
new file mode 100644
index 00000000000..dd22b26d6ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-013-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ height: 30px;
+ }
+</style>
+<body>
+ <p>Test passes if there is a greek letter "&#x03B1;" in the box below.</p>
+ <div>&#x03B1;</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-013.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-013.xht
index 753dcc240e1..9ac30e504c7 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-013.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-013.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-013-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counter()' function with a list-style." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-014-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-014-ref.html
new file mode 100644
index 00000000000..a3b3167a2dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-014-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ height: 30px;
+ }
+</style>
+<body>
+ <p>Test passes if there is a letter "a" in the box below.</p>
+ <div>a</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-014.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-014.xht
index f7fe2d3a612..879b4dd5941 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-014.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-014.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-014-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counter()' function with a list-style." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-015-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-015-ref.html
new file mode 100644
index 00000000000..f452a20e7d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-015-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ height: 30px;
+ }
+</style>
+<body>
+ <p>Test passes if there is a letter "A" in the box below.</p>
+ <div>A</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-015.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-015.xht
index 843350bfc46..089496d16f1 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-015.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-015.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-015-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counter()' function with a list-style." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-016-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-016-ref.html
new file mode 100644
index 00000000000..023c98d56e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-016-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ height: 30px;
+ }
+</style>
+<body>
+ <p>Test passes if there is an Armenian character "&#x0531;" below.</p>
+ <div>&#x0531;</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-016.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-016.xht
index 2ff6f8368a7..75d8bb7c426 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-016.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-016.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-016-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counter()' function with a list-style." />
<style type="text/css">
@@ -21,7 +22,7 @@
</style>
</head>
<body>
- <p>Test passes if there is an Armenian character "&#x0561;" or "&#x0531;" below.</p>
+ <p>Test passes if there is an Armenian character "&#x0531;" below.</p>
<div></div>
</body>
</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-017-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-017-ref.html
new file mode 100644
index 00000000000..25d69f22bea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-017-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ height: 30px;
+ }
+</style>
+<body>
+ <p>Test passes if there is a Georgian character "&#x10d0;" in the box below.</p>
+ <div>&#x10d0;</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-017.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-017.xht
index f887d2c5a5f..adf5b8953f0 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-017.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-017.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-017-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counter()' function with a list-style." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-018.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-018.xht
index bf42051c4c6..039987a822d 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-018.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-018.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-014-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counter()' function with a list-style." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-019.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-019.xht
index 7f85f67d444..2d2b21c53cb 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-019.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-019.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-015-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counter()' function with a list-style." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-020.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-020.xht
index 656d1b5dbc6..7328cb512e4 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-020.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-020.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-001-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counter()' function with a list-style." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-021-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-021-ref.html
new file mode 100644
index 00000000000..5e9cd46e68a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-021-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ }
+</style>
+<body>
+ <p>Test passes if the numbers "0" and "0.0" are in the box below.</p>
+ <div>0<br>0.0</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-021.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-021.xht
index b003a29c84e..cbe53ed8313 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-021.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-021.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-021-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counters()' function with a string value." />
<style type="text/css">
@@ -20,7 +21,7 @@
</style>
</head>
<body>
- <p>Test passes if there are the numbers "0" and "0.0" in the box below.</p>
+ <p>Test passes if the numbers "0" and "0.0" are in the box below.</p>
<div id="div1">
<div></div>
</div>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-022-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-022-ref.html
new file mode 100644
index 00000000000..a7087f7bc6e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-022-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ }
+</style>
+<body>
+ <p>Test passes if there are bullets "&#x2022;" and "&#x2022;.&#x2022;" in the box below.</p>
+ <div>&#x2022;<br>&#x2022;.&#x2022;</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-022.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-022.xht
index 11ac0edd9b1..c5adb66e1f0 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-022.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-022.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-022-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counters()' function with a string and a list style." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-023-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-023-ref.html
new file mode 100644
index 00000000000..c6f8a193097
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-023-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ }
+</style>
+<body>
+ <p>Test passes if there are circles "&#x25E6;" and "&#x25E6;.&#x25E6;" in the box below.</p>
+ <div>&#x25E6;<br>&#x25E6;.&#x25E6;</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-023.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-023.xht
index 6168a5e14d4..319f04cf12a 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-023.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-023.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-023-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counters()' function with a string and a list style." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-025.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-025.xht
index 38e429fd1b6..fdc8229aba8 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-025.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-025.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-021-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counters()' function with a string and a list style." />
<style type="text/css">
@@ -20,7 +21,7 @@
</style>
</head>
<body>
- <p>Test passes if there are numbers "0" and "0.0" in the box below.</p>
+ <p>Test passes if the numbers "0" and "0.0" are in the box below.</p>
<div id="div1">
<div></div>
</div>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-026-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-026-ref.html
new file mode 100644
index 00000000000..c884052e448
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-026-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ }
+</style>
+<body>
+ <p>Test passes if there are numbers "00" and "00.00" in the box below.</p>
+ <div>00<br>00.00</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-026.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-026.xht
index a8222921d0a..54642cd2305 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-026.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-026.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-026-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counters()' function with a string and a list style." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-027-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-027-ref.html
new file mode 100644
index 00000000000..eb09da6bad9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-027-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ }
+</style>
+<body>
+ <p>Test passes if there are letters "i" and "i.i" in the box below.</p>
+ <div>i<br>i.i</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-027.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-027.xht
index b2bc7c010ab..8ee1644af82 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-027.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-027.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-027-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counters()' function with a string and a list style." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-028-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-028-ref.html
new file mode 100644
index 00000000000..78883ada679
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-028-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ }
+</style>
+<body>
+ <p>Test passes if there are letters "I" and "I.I" in the box below.</p>
+ <div>I<br>I.I</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-028.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-028.xht
index 1086c5e09c8..fb36942cbb9 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-028.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-028.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-028-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counters()' function with a string and a list style." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-029-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-029-ref.html
new file mode 100644
index 00000000000..7e8e6c61d04
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-029-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ }
+</style>
+<body>
+ <p>Test passes if there are greek letters "&#x03B1;" and "&#x03B1;.&#x03B1;" in the box below.</p>
+ <div>&#x03B1;<br>&#x03B1;.&#x03B1;</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-029.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-029.xht
index eb8b86273d6..d49a216cf49 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-029.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-029.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-029-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counters()' function with a string and a list style." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-030-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-030-ref.html
new file mode 100644
index 00000000000..2a7a6c2e457
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-030-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ }
+</style>
+<body>
+ <p>Test passes if there are letters "a" and "a.a" in the box below.</p>
+ <div>a<br>a.a</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-030.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-030.xht
index 30fdae91591..619ae0c9585 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-030.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-030.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-030-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counters()' function with a string and a list style." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-031-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-031-ref.html
new file mode 100644
index 00000000000..d97b57ba295
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-031-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ }
+</style>
+<body>
+ <p>Test passes if there are letters "A" and "A.A" in the box below.</p>
+ <div>A<br>A.A</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-031.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-031.xht
index 2771e04c633..305c724c30c 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-031.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-031.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-031-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counters()' function with a string and a list style." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-032-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-032-ref.html
new file mode 100644
index 00000000000..55ea7be06e0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-032-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ }
+</style>
+<body>
+ <p>Test passes if there are Armenian characters "&#x0531;" and "&#x0531;.&#x0531;" in the box below.</p>
+ <div>&#x0531;<br>&#x0531;.&#x0531;</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-032.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-032.xht
index 998223dfbf8..4e74b311fb4 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-032.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-032.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-032-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counters()' function with a string and a list style." />
<style type="text/css">
@@ -21,7 +22,7 @@
</style>
</head>
<body>
- <p>Test passes if there are Armenian characters "&#x0561;" and "&#x0561;.&#x0561;" or "&#x0531;" and "&#x0531;.&#x0531;" in the box below.</p>
+ <p>Test passes if there are Armenian characters "&#x0531;" and "&#x0531;.&#x0531;" in the box below.</p>
<div id="div1">
<div></div>
</div>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-033-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-033-ref.html
new file mode 100644
index 00000000000..fc0aa9eb5fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-033-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ }
+</style>
+<body>
+ <p>Test passes if there are Georgian characters "&#x10d0;" and "&#x10d0;.&#x10d0;" in the box below.</p>
+ <div>&#x10d0;<br>&#x10d0;.&#x10d0;</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-033.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-033.xht
index f915c6081a9..2d41a9fea9d 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-033.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-033.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-033-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counters()' function with a string and a list style." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-034.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-034.xht
index d3c96851d90..a49776e355e 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-034.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-034.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-030-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counters()' function with a string and a list style." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-035.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-035.xht
index 53d126e844d..4595b49c0d1 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-035.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-035.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-031-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counters()' function with a string and a list style." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-036.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-036.xht
index f3c8a444ec0..97808a6b3e7 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-036.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-036.xht
@@ -5,7 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
- <link rel="match" href="../reference/no-red-on-blank-page-ref.xht"/>
+ <link rel="match" href="content-001-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'counters()' function with a string and a list style." />
<style type="text/css">
@@ -16,9 +16,10 @@
counter-reset: test;
color: red;
}
- #div1
+ div
{
border: 2px solid black;
+ height: 30px;
}
</style>
</head>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-037-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-037-ref.html
new file mode 100644
index 00000000000..39b5ba9284f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-037-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ td {
+ border: 2px solid black;
+ color: green;
+ }
+</style>
+<body>
+ <p>Test passes if the words "PASS PASS" appear in the box below.</p>
+ <table>
+ <tr>
+ <td>PASS PASS</td>
+ </tr>
+ </table>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-037.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-037.xht
index d76522579e0..f0f45e1c58e 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-037.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-037.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-037-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property correctly handles the 'attr()' function when calling the attribute 'abbr'." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-038.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-038.xht
index c975fd26a3d..ccb9ab4cd81 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-038.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-038.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-003-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property correctly handles the 'attr()' function when calling the attribute 'accept-charset'." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-039.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-039.xht
index f04ede14721..7b333ce7e98 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-039.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-039.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-003-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property correctly handles the 'attr()' function when calling the attribute 'accept'." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-040-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-040-ref.html
new file mode 100644
index 00000000000..b5f7d0dd76b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-040-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ color: green;
+ }
+</style>
+<body>
+ <p>Test passes if the letter "P" appears in the box below.</p>
+ <div>P</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-040.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-040.xht
index ec011ec902e..79791c98176 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-040.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-040.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-040-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property correctly handles the 'attr()' function when calling the attribute 'accesskey'." />
<style type="text/css">
@@ -13,7 +14,7 @@
content: attr(accesskey);
color: green;
}
- a
+ div
{
border: 2px solid black;
}
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-041-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-041-ref.html
new file mode 100644
index 00000000000..c3868b32594
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-041-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ color: green;
+ }
+</style>
+<body>
+ <p>Test passes if the word "PASS" appears in the box below.</p>
+ <div>PASS</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-041.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-041.xht
index 8bdf075ebdd..9f7745026e2 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-041.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-041.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-041-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property correctly handles the 'attr()' function when calling the attribute 'action'." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-042-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-042-ref.html
new file mode 100644
index 00000000000..3a3c43e8784
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-042-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ color: green;
+ }
+</style>
+<body>
+ <p>Test passes if the words "center" appear in the box below.</p>
+ <div align="center">center</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-042.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-042.xht
index 2b8d00637b7..0f927cc112f 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-042.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-042.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-042-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property correctly handles the 'attr()' function when calling the attribute 'align'." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-043-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-043-ref.html
new file mode 100644
index 00000000000..42f7ab0e61e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-043-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ color: green;
+ }
+</style>
+<body>
+ <div>#ffff00</div>
+ <p>Test passes if there is the text "#ffff00" above.</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-043.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-043.xht
index 5d93f31072b..3ecf8477bf1 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-043.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-043.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-043-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property correctly handles the 'attr()' function when calling the attribute 'alink'." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-046.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-046.xht
index 55b230e067d..b376e3abc6c 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-046.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-046.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-037-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property correctly handles the 'attr()' function when calling the attribute 'axis'." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-047-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-047-ref.html
new file mode 100644
index 00000000000..317170fc0c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-047-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ body {
+ margin: 0px;
+ }
+ .test {
+ color: green;
+ }
+ p {
+ margin-left: 8px;
+ }
+</style>
+<body>
+ <div class="test">PASS PASS</div>
+ <p>Test passes if the words "PASS PASS" appear above this text.</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-047.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-047.xht
index 3c8ef21c326..2b575f8e549 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-047.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-047.xht
@@ -5,17 +5,23 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-047-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property correctly handles the 'attr()' function when calling the attribute 'background'." />
<style type="text/css">
- body:before
- {
+ body:before {
content: attr(background);
color: green;
}
+ body {
+ margin: 0px;
+ }
+ p {
+ margin-left: 8px;
+ }
</style>
</head>
<body background="PASS PASS">
- <p>Test passes if only the words "PASS PASS" appear above.</p>
+ <p>Test passes if the words "PASS PASS" appear above this text.</p>
</body>
</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-048-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-048-ref.html
new file mode 100644
index 00000000000..e871e3be62a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-048-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ body {
+ background: #ffff00;
+ }
+ div {
+ color: green;
+ }
+</style>
+<body>
+ <div>#ffff00</div>
+ <p>Test passes if there is the text "#ffff00" above.</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-048.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-048.xht
index fb906d6f102..9a1e66f1d07 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-048.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-048.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-048-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property correctly handles the 'attr()' function when calling the attribute 'bgcolor'." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-050-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-050-ref.html
new file mode 100644
index 00000000000..bf0b0a81a93
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-050-ref.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ table:before {
+ content: "1";
+ }
+ table {
+ color: green;
+ border: 2px solid black;
+ }
+</style>
+<body>
+ <p>Test passes if the number "1" appears in the box below.</p>
+ <table>
+ <tr>
+ <td></td>
+ </tr>
+ </table>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-050.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-050.xht
index 89d28417990..623ce5aea64 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-050.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-050.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-050-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property correctly handles the 'attr()' function when calling the attribute 'cellpadding'." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-052-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-052-ref.html
new file mode 100644
index 00000000000..630898c845b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-052-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ td {
+ color: green;
+ border: 2px solid black;
+ }
+</style>
+<body>
+ <p>Test passes if the letter "A" appears in the box below.</p>
+ <table>
+ <tr>
+ <td>A</td>
+ </tr>
+ </table>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-052.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-052.xht
index 4b1ed885ebb..e155c2323ba 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-052.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-052.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-052-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property correctly handles the 'attr()' function when calling the attribute 'char'." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-053-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-053-ref.html
new file mode 100644
index 00000000000..6f639b174a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-053-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ td {
+ color: green;
+ border: 2px solid black;
+ }
+</style>
+<body>
+ <p>Test passes if the number "1" appears in the box below.</p>
+ <table>
+ <tr>
+ <td>1</td>
+ </tr>
+ </table>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-053.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-053.xht
index 0cc6b7cd8b6..0c85ab6e375 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-053.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-053.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-053-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property correctly handles the 'attr()' function when calling the attribute 'charoff'." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-054.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-054.xht
index befa87b5755..736453db440 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-054.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-054.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-003-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property correctly handles the 'attr()' function when calling the attribute 'charset'." />
<style type="text/css">
@@ -13,7 +14,7 @@
content: attr(charset);
color: green;
}
- a
+ div
{
border: 2px solid black;
}
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-056.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-056.xht
index d36a8415011..c2c25fa470a 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-056.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-056.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-003-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property correctly handles the 'attr()' function when calling the attribute 'cite'." />
<style type="text/css">
@@ -13,7 +14,7 @@
content: attr(cite);
color: green;
}
- q
+ div
{
border: 2px solid black;
}
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-057.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-057.xht
index 0a39b554b8a..38be14e477f 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-057.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-057.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-003-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'class'." />
<style type="text/css">
@@ -20,7 +21,7 @@
</style>
</head>
<body>
- <p>Test passes if the words "PASS PASS" appears in the box below.</p>
+ <p>Test passes if the words "PASS PASS" appear in the box below.</p>
<div class="PASS PASS"></div>
</body>
</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-063-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-063-ref.html
new file mode 100644
index 00000000000..84a732bb1d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-063-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ color: green;
+ }
+</style>
+<body>
+ <p>Test passes if the word "green" appears in the box below.</p>
+ <div>green</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-063.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-063.xht
index 5ce5a7a453c..a5fdada076d 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-063.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-063.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-063-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property correctly handles the 'attr()' function when calling the attribute 'color'." />
<style type="text/css">
@@ -13,7 +14,7 @@
content: attr(color);
color: green;
}
- font
+ div
{
border: 2px solid black;
}
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-065.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-065.xht
index 9d485a00ec1..46164b4906a 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-065.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-065.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-053-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property correctly handles the 'attr()' function when calling the attribute 'colspan'." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-067.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-067.xht
index 42b64165fea..513a8fa22d0 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-067.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-067.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-047-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property correctly handles the 'attr()' function when calling the attribute 'content'." />
<meta content="PASS PASS" />
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-068-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-068-ref.html
new file mode 100644
index 00000000000..e3c1796412b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-068-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ color: green;
+ }
+</style>
+<body>
+ <p>Test passes if the number "10" appears in the box below.</p>
+ <div>10</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-068.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-068.xht
index c9eb1143556..de2a9dc92b2 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-068.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-068.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-068-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property correctly handles the 'attr()' function when calling the attribute 'coords'." />
<style type="text/css">
@@ -13,7 +14,7 @@
content: attr(coords);
color: green;
}
- a
+ div
{
border: 2px solid black;
}
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-070-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-070-ref.html
new file mode 100644
index 00000000000..2995930fc43
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-070-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ ins {
+ border: 2px solid black;
+ color: green;
+ text-decoration-color: black;
+ }
+</style>
+<body>
+ <p>Test passes if the text "2000-01-01T00:00:00-08:00" appears in the box below.</p>
+ <ins>2000-01-01T00:00:00-08:00</ins>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-070.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-070.xht
index 9b162fbaf28..97aa0a27e1d 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-070.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-070.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-070-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property correctly handles the 'attr()' function when calling the attribute 'datetime'." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-072-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-072-ref.html
new file mode 100644
index 00000000000..c8bc3266d84
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-072-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ color: green;
+ }
+</style>
+<body>
+ <p>Test passes if the word "defer" appears in the box below.</p>
+ <div>defer</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-072.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-072.xht
index 8fd060ec477..755a6d52b18 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-072.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-072.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-072-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property correctly handles the 'attr()' function when calling the attribute 'defer'." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-073-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-073-ref.html
new file mode 100644
index 00000000000..41963db83c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-073-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ color: green;
+ }
+</style>
+<body>
+ <p>Test passes if the letters "ltr" appear in the box below.</p>
+ <div>ltr</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-073.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-073.xht
index d8e0b88f019..8a3c396699a 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-073.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-073.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-073-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'dir'." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-075-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-075-ref.html
new file mode 100644
index 00000000000..2c0b63dbf3c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-075-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ color: green;
+ }
+</style>
+<body>
+ <p>Test passes if the text "multipart/form-data" appear in the box below.</p>
+ <div>multipart/form-data</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-075.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-075.xht
index 222528c3985..4f7a6856689 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-075.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-075.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-075-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'enctype'." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-076.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-076.xht
index d694d532543..bb440025ead 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-076.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-076.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-003-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'face'." />
<style type="text/css">
@@ -13,7 +14,7 @@
content: attr(face);
color: green;
}
- font
+ div
{
border: 2px solid black;
}
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-077.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-077.xht
index 115a9ea3597..10a8523bfdf 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-077.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-077.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-041-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'for'." />
<style type="text/css">
@@ -13,7 +14,7 @@
content: attr(for);
color: green;
}
- label
+ .box
{
border: 2px solid black;
}
@@ -21,7 +22,7 @@
</head>
<body>
<p>Test passes if the word "PASS" appears in the box below.</p>
- <div>
+ <div class="box">
<label for="PASS"></label>
<div id="PASS"></div>
</div>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-080-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-080-ref.html
new file mode 100644
index 00000000000..6f5454c0087
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-080-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ td {
+ border: 2px solid black;
+ color: green;
+ }
+</style>
+<body>
+ <p>Test passes if the word "PASS" appears in the box below.</p>
+ <table>
+ <tr>
+ <td>PASS</td>
+ </tr>
+ </table>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-080.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-080.xht
index 3936e7d5aa3..7dbe2e42310 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-080.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-080.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-080-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'headers'." />
<style type="text/css">
@@ -23,10 +24,10 @@
<p>Test passes if the word "PASS" appears in the box below.</p>
<table>
<tr>
- <th id="PASS"></th>
+ <td headers="PASS"></td>
</tr>
<tr>
- <td headers="PASS"></td>
+ <th id="PASS"></th>
</tr>
</table>
</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-081-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-081-ref.html
new file mode 100644
index 00000000000..7da539a72fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-081-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ td {
+ color: green;
+ border: 2px solid black;
+ }
+</style>
+<body>
+ <p>Test passes if the number "10" appears in the box below.</p>
+ <table>
+ <tr>
+ <td>10</td>
+ </tr>
+ </table>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-081.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-081.xht
index 21cd3041974..937a691eb1b 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-081.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-081.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-081-ref.html" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'height'." />
<style type="text/css">
td:before
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-082-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-082-ref.html
new file mode 100644
index 00000000000..db3242baa7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-082-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ color: green;
+ }
+</style>
+<body>
+ <p>Test passes if the character "#" appears in the box below.</p>
+ <a href="#"><div>#</div></a>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-082.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-082.xht
index 3713792ccd6..9c51a98070f 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-082.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-082.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-082-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'href'." />
<style type="text/css">
@@ -13,7 +14,7 @@
content: attr(href);
color: green;
}
- a
+ div
{
border: 2px solid black;
}
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-083-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-083-ref.html
new file mode 100644
index 00000000000..375572bac55
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-083-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ color: green;
+ }
+</style>
+<body>
+ <p>Test passes if the letters "aa" appear in the box below.</p>
+ <div>aa</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-083.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-083.xht
index 63f73880b50..833a4b6a194 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-083.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-083.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-083-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'hreflang'." />
<style type="text/css">
@@ -13,7 +14,7 @@
content: attr(hreflang);
color: green;
}
- a
+ div
{
border: 2px solid black;
}
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-085.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-085.xht
index fadf73bc6ed..dd10cbb2f86 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-085.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-085.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-047-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property correctly handles the 'attr()' function when calling the attribute 'http-equiv'." />
<meta content="" http-equiv="PASS PASS" />
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-086.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-086.xht
index b790bed8803..0f226f5f8a5 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-086.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-086.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-041-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'id'." />
<style type="text/css">
@@ -20,7 +21,7 @@
</style>
</head>
<body>
- <p>Test passes if the word "PASS" appear in the box below.</p>
+ <p>Test passes if the word "PASS" appears in the box below.</p>
<div id="PASS"></div>
</body>
</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-089-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-089-ref.html
new file mode 100644
index 00000000000..375572bac55
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-089-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ color: green;
+ }
+</style>
+<body>
+ <p>Test passes if the letters "aa" appear in the box below.</p>
+ <div>aa</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-089.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-089.xht
index 51ad578abbd..cd9d500ecbf 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-089.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-089.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-089-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'lang'." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-090-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-090-ref.html
new file mode 100644
index 00000000000..a8d86190593
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-090-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ color: green;
+ }
+</style>
+<body>
+ <p>Test passes if the word "ecmascript" appears in the box below.</p>
+ <div>ecmascript</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-090.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-090.xht
index d4f15c508c3..982023deaad 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-090.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-090.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-090-ref.html" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'language'." />
<style type="text/css">
script:before
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-091-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-091-ref.html
new file mode 100644
index 00000000000..b9cb6dd4bfd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-091-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ color: green;
+ }
+</style>
+<body>
+ <div>green</div>
+ <p>Test passes if the word "green" appears above.</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-091.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-091.xht
index cb6a8decb23..1c1b35239ee 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-091.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-091.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-091-ref.html" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'link'." />
<style type="text/css">
body:before
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-096-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-096-ref.html
new file mode 100644
index 00000000000..9518fe01f8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-096-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ body {
+ margin: 0px;
+ }
+ .test {
+ color: green;
+ }
+ p {
+ margin-left: 8px;
+ }
+</style>
+<body>
+ <div class="test">all</div>
+ <p>Test passes if the word "all" appears above this text.</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-096.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-096.xht
index 24dbcdd0cf8..a968386f10e 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-096.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-096.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-096-ref.html" />
<link media="all" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'media'." />
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-097-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-097-ref.html
new file mode 100644
index 00000000000..d68b7955f5f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-097-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ color: green;
+ }
+</style>
+<body>
+ <p>Test passes if the word "get" appears in the box below.</p>
+ <div>get</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-097.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-097.xht
index f6de01047d3..a95a303e94c 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-097.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-097.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-097-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'method'." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-099.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-099.xht
index 60549d809c3..05bd846147b 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-099.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-099.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-041-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'name'." />
<style type="text/css">
@@ -13,7 +14,7 @@
content: attr(name);
color: green;
}
- a
+ div
{
border: 2px solid black;
}
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-100-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-100-ref.html
new file mode 100644
index 00000000000..91b01cef30b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-100-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ color: green;
+ }
+</style>
+<body>
+ <p>Test passes if the word "nohref" appears in the box below.</p>
+ <div>nohref</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-100.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-100.xht
index e928b353dcc..f067992204d 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-100.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-100.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-100-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'nohref'." />
<style type="text/css">
@@ -21,7 +22,7 @@
</style>
</head>
<body>
- <p>Test passes if the word "nohref" appear in the box below.</p>
+ <p>Test passes if the word "nohref" appears in the box below.</p>
<div>
<map id="test">
<area alt="" nohref="nohref" />
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-103-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-103-ref.html
new file mode 100644
index 00000000000..d538ab4b479
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-103-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ td {
+ color: green;
+ border: 2px solid black;
+ }
+</style>
+<body>
+ <p>Test passes if the word "nowrap" appears in the box below.</p>
+ <table>
+ <tr>
+ <td>nowrap</td>
+ </tr>
+ </table>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-103.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-103.xht
index 9b22daaf663..b8380e4500a 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-103.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-103.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-103-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'nowrap'." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-105.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-105.xht
index 18d097424d2..25eb7796f13 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-105.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-105.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="../../reference/only_pass_parens_semicolon.html" />
<meta name="flags" content="dom" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'onblur'." />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
@@ -14,7 +15,7 @@
content: attr(onblur);
color: green;
}
- a
+ div
{
border: 2px solid black;
}
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-109.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-109.xht
index b9e01f251db..030d38d41d0 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-109.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-109.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="../../reference/only_pass_parens_semicolon.html" />
<meta name="flags" content="dom" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'onfocus'." />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
@@ -14,7 +15,7 @@
content: attr(onfocus);
color: green;
}
- a
+ div
{
border: 2px solid black;
}
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-113-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-113-ref.html
new file mode 100644
index 00000000000..c17bdd7f099
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-113-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ color: green;
+ }
+</style>
+<body>
+ <div>PASS();</div>
+ <p>Test passes if only the word "PASS();" appears above. Fail if there is any other additional text.</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-113.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-113.xht
index 7de819efea3..559b7953d23 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-113.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-113.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-113-ref.html" />
<meta name="flags" content="dom" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'onload'." />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-122.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-122.xht
index 3cf97e3e1f1..a32ce892c37 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-122.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-122.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-113-ref.html" />
<meta name="flags" content="dom" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'onunload'." />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-123.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-123.xht
index 76d726d9907..94399d109a7 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-123.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-123.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-047-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'profile'." />
<style type="text/css">
@@ -20,6 +21,6 @@
</style>
</head>
<body>
- <p>Test passes if only the words "PASS PASS" appear above.</p>
+ <p>Test passes if the words "PASS PASS" appear above this text.</p>
</body>
</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-126-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-126-ref.html
new file mode 100644
index 00000000000..74f46da24c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-126-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ color: green;
+ }
+</style>
+<body>
+ <p>Test passes if only the word "Alternate" appears in the box below.</p>
+ <div>Alternate</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-126.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-126.xht
index a4273a8ebfe..6157e818869 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-126.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-126.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-126-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'rel'." />
<style type="text/css">
@@ -13,7 +14,7 @@
content: attr(rel);
color: green;
}
- a
+ div
{
border: 2px solid black;
}
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-127.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-127.xht
index bc3f7e6a80b..a9b04484d14 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-127.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-127.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-126-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'rev'." />
<style type="text/css">
@@ -13,7 +14,7 @@
content: attr(rev);
color: green;
}
- a
+ div
{
border: 2px solid black;
}
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-129.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-129.xht
index 648f520c002..df6691b41a9 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-129.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-129.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-053-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'rowspan'." />
<style type="text/css">
@@ -20,7 +21,7 @@
</style>
</head>
<body>
- <p>Test passes if only the number "1" appears in the box below.</p>
+ <p>Test passes if the number "1" appears in the box below.</p>
<table>
<tr>
<td rowspan="1"></td>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-131.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-131.xht
index 3e7c5307759..ad6d62830a9 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-131.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-131.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-047-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'scheme'." />
<meta content="" scheme="PASS PASS" />
@@ -21,6 +22,6 @@
</style>
</head>
<body>
- <p>Test passes if only the words "PASS PASS" appear above this text.</p>
+ <p>Test passes if the words "PASS PASS" appear above this text.</p>
</body>
</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-132-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-132-ref.html
new file mode 100644
index 00000000000..6c1736b5c65
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-132-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ td {
+ color: green;
+ border: 2px solid black;
+ }
+</style>
+<body>
+ <p>Test passes if only the word "col" appears in the box below.</p>
+ <table>
+ <tr>
+ <td>col</td>
+ </tr>
+ </table>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-132.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-132.xht
index da7701eebce..389966d079e 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-132.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-132.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-132-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'scope'." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-135-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-135-ref.html
new file mode 100644
index 00000000000..c1be10b7a2f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-135-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ color: green;
+ }
+</style>
+<body>
+ <p>Test passes if only the word "circle" appears in the box below.</p>
+ <div>circle</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-135.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-135.xht
index 9fdce200d5f..3acddbdf2e9 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-135.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-135.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-135-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'shape'." />
<style type="text/css">
@@ -13,7 +14,7 @@
content: attr(shape);
color: green;
}
- a
+ div
{
border: 2px solid black;
}
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-136-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-136-ref.html
new file mode 100644
index 00000000000..2ec806a9624
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-136-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ font {
+ color: green;
+ border: 2px solid black;
+ }
+</style>
+<body>
+ <p>Test passes if the number "5" appears in the box below.</p>
+ <div><font size="5">5</font></div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-136.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-136.xht
index c4d9531f39e..97b36915460 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-136.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-136.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-136-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'size'." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-138.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-138.xht
index 836d5fb8659..21e1c169d2e 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-138.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-138.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-003-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'src'." />
<style type="text/css">
@@ -21,7 +22,7 @@
</style>
</head>
<body>
- <p>Test passes if only the words "PASS PASS" appear in the box below.</p>
+ <p>Test passes if the words "PASS PASS" appear in the box below.</p>
<script src="PASS PASS" type="text/javascript"></script>
</body>
</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-141-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-141-ref.html
new file mode 100644
index 00000000000..9a5d248bc69
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-141-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ color: green;
+ }
+</style>
+<body>
+ <p>Test passes if the words "color: green;" appear in the box below.</p>
+ <div>color: green;</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-141.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-141.xht
index 9f0b2074d5b..1a384c02264 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-141.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-141.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-141-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'style'." />
<meta http-equiv="Content-Style-Type" content="text/css" />
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-143-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-143-ref.html
new file mode 100644
index 00000000000..6a4e3dcf9cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-143-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ color: green;
+ }
+</style>
+<body>
+ <p>Test passes if the number "5" appears in the box below.</p>
+ <div>5</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-143.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-143.xht
index 001b572df3d..ff6b23552af 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-143.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-143.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-143-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'tabindex'." />
<style type="text/css">
@@ -13,7 +14,7 @@
content: attr(tabindex);
color: green;
}
- a
+ div
{
border: 2px solid black;
}
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-144-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-144-ref.html
new file mode 100644
index 00000000000..f89a44c850a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-144-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ color: green;
+ }
+</style>
+<body>
+ <p>Test passes if the word "_blank" appears in the box below.</p>
+ <div>_blank</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-144.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-144.xht
index 71be8cd4b8b..3ca997ae596 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-144.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-144.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-144-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'target'." />
<style type="text/css">
@@ -13,7 +14,7 @@
content: attr(target);
color: green;
}
- a
+ div
{
border: 2px solid black;
}
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-145.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-145.xht
index 1632ff1215a..e36d20f719a 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-145.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-145.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-091-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'text'." />
<style type="text/css">
@@ -19,6 +20,6 @@
</style>
</head>
<body text="green">
- <p>Test passes if there is only the word "green" above.</p>
+ <p>Test passes if the word "green" appears above.</p>
</body>
</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-146.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-146.xht
index 3c2d4fc7474..fdc5166b50d 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-146.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-146.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-003-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'title'." />
<style type="text/css">
@@ -13,7 +14,7 @@
content: attr(title);
color: green;
}
- a
+ div
{
border: 2px solid black;
}
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-147-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-147-ref.html
new file mode 100644
index 00000000000..8c056131d94
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-147-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid black;
+ color: green;
+ }
+</style>
+<body>
+ <p>Test passes if the words "text/plain" appear in the box below.</p>
+ <div>text/plain</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-147.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-147.xht
index a1dc049baa6..12db407512e 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-147.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-147.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-147-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'type'." />
<style type="text/css">
@@ -13,14 +14,14 @@
content: attr(type);
color: green;
}
- a
+ div
{
border: 2px solid black;
}
</style>
</head>
<body>
- <p>Test passes if the words "text/plain"" appear in the box below.</p>
+ <p>Test passes if the words "text/plain" appear in the box below.</p>
<div>
<a type="text/plain"></a>
</div>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-149-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-149-ref.html
new file mode 100644
index 00000000000..55641ccda07
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-149-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ td {
+ color: green;
+ border: 2px solid black;
+ }
+</style>
+<body>
+ <p>Test passes if only the word "baseline" appears in the box below.</p>
+ <table>
+ <tr>
+ <td>baseline</td>
+ </tr>
+ </table>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-149.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-149.xht
index 2685e6cd35c..ab98d48e1c8 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-149.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-149.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-149-ref.html" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'valign'." />
<style type="text/css">
td:before
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-150-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-150-ref.html
new file mode 100644
index 00000000000..2a24d705b0c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-150-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ li {
+ color: green;
+ border: 2px solid black;
+ display: block;
+ }
+</style>
+<body>
+ <p>Test passes if only the number "1" appears in the box below.</p>
+ <ol>
+ <li>1</li>
+ </ol>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-150.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-150.xht
index a82d07dd2fc..258fb9934e8 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-150.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-150.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-150-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'value'." />
<style type="text/css">
@@ -21,7 +22,7 @@
</style>
</head>
<body>
- <p>Test passes if only the number "1" appear in the box below.</p>
+ <p>Test passes if only the number "1" appears in the box below.</p>
<ol>
<li value="1"></li>
</ol>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-152.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-152.xht
index 7da46d4e1dd..78965fb7db6 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-152.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-152.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-047-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'version'." />
<style type="text/css">
@@ -16,6 +17,6 @@
</style>
</head>
<body>
- <p>Test passes if the words "PASS PASS" appear above.</p>
+ <p>Test passes if the words "PASS PASS" appear above this text.</p>
</body>
</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-153.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-153.xht
index 27e18dee899..36c0344763a 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-153.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-153.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-091-ref.html" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'vlink'." />
<style type="text/css">
body:before
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-155-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-155-ref.html
new file mode 100644
index 00000000000..373e467765e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-155-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ pre {
+ border: 2px solid black;
+ color: green;
+ }
+</style>
+<body>
+ <p>Test passes if the number "10" appears in the box below.</p>
+ <pre>10</pre>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-155.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-155.xht
index 8bf60b1b863..7821cadcf41 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-155.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-155.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-155-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles the 'attr()' function when calling the attribute 'width'." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-156-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-156-ref.html
new file mode 100644
index 00000000000..1dab980f979
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-156-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid blue;
+ height: 30px;
+ }
+</style>
+<body>
+ <p>Test passes if there is a quote (") in the blue box below.</p>
+ <div>"</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-156.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-156.xht
index c190e1b29a2..6dcdee90730 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-156.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-156.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-156-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles an 'open-quote' value." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-157.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-157.xht
index 783a7dc5aa2..f42ee591207 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-157.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-157.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-156-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'close-quote' value." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-158-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-158-ref.html
new file mode 100644
index 00000000000..f54324da84a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-158-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid blue;
+ height: 30px;
+ }
+</style>
+<body>
+ <p>Test passes if there is a single quote (') in the blue box below.</p>
+ <div>'</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-158.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-158.xht
index 84cf084568d..d52e18b3d19 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-158.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-158.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-158-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'no-open-quote' value." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-159-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-159-ref.html
new file mode 100644
index 00000000000..bd17b1fe02d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-159-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: 2px solid blue;
+ }
+</style>
+<body>
+ <p>Test passes if there are 3 quotes (" ' ") in the blue box.</p>
+ <div>" ' "</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-159.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-159.xht
index e0e65a47b39..de8ec378618 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-159.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-159.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-159-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="The 'content' property properly handles a 'no-close-quote' value." />
<style type="text/css">
@@ -24,7 +25,7 @@
{
content: no-close-quote;
}
- #span1
+ div
{
border: 2px solid blue;
}
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-attr-001.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-attr-001.xht
index 14a7d4b5be0..636d7ba802f 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-attr-001.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-attr-001.xht
@@ -4,6 +4,7 @@
<title>CSS Test: Content property missing attr(x)</title>
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="../reference/ref-nothing-below.xht" />
<meta name="flags" content="" />
<meta name="assert" content="If attribute (x) does not exist then an empty string is returned for the attr(x) value." />
<style type="text/css">
@@ -14,7 +15,7 @@
</style>
</head>
<body>
- <p>Test passes if there is nothing displayed below.</p>
+ <p>Test passes if there is nothing below.</p>
<div></div>
</body>
</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-attr-case-001.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-attr-case-001.html
index 21361c3f3e7..2ba49f95584 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-attr-case-001.html
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-attr-case-001.html
@@ -4,12 +4,12 @@
<title>CSS Test: Content property attr(x) case sensitivity</title>
<link rel="author" title="Microsoft" href="http://www.microsoft.com/">
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content">
+ <link rel="match" href="../../reference/pass_if_pass_below.html" />
<meta name="flags" content="HTMLonly">
<meta name="assert" content="The attr(x) function selects the attribute even when case does not match.">
<style type="text/css">
div:before
{
- color: green;
content: attr(Title);
}
</style>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-attr-case-002.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-attr-case-002.xht
index 46632f15d08..d3126bafcda 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-attr-case-002.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-attr-case-002.xht
@@ -4,6 +4,7 @@
<title>CSS Test: content attr(x) case sensitivity</title>
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="../reference/no-red-on-blank-page-ref.xht" />
<meta name="flags" content="nonHTML" />
<meta name="assert" content="Verify in XHTML that attr(x) does not select the attribute when the case does not match" />
<style type="text/css">
@@ -16,7 +17,7 @@
</style>
</head>
<body>
- <div>Test Passes if there is no red visible on the page.</div>
+ <p>Test passes if there is no red visible on the page.</p>
<div id="test" title="FAIL"></div>
</body>
</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-auto-reset-001-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-auto-reset-001-ref.html
new file mode 100644
index 00000000000..3a2e1d7e2e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-auto-reset-001-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<body>
+ <p>Test passes if there is the number '0' below.</p>
+ <div>0</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-auto-reset-001.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-auto-reset-001.xht
index c6476035343..6fc8adbb8f2 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-auto-reset-001.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-auto-reset-001.xht
@@ -4,6 +4,7 @@
<title>CSS Test: Content property on out of scope counter</title>
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-auto-reset-001-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="If content refers to a counter that is not in scope, it is assumed that a counter-reset has occurred and the counter is reset to zero." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-newline-001-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-newline-001-ref.html
new file mode 100644
index 00000000000..22d77944e4b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-newline-001-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ height: 100px;
+ width: 200px;
+ }
+</style>
+<body>
+ <p>Test passes if there are exactly two lines of text below.</p>
+ <div>This text<br />should be on two lines.</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-newline-001.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-newline-001.xht
index 5823940f2d8..2e1a3bda0f0 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-newline-001.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-newline-001.xht
@@ -4,6 +4,7 @@
<title>CSS Test: Content property \A creates newline</title>
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-newline-001-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="A '\A' creates a newline for strings in the content property." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-001-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-001-ref.html
new file mode 100644
index 00000000000..cbc297ec131
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-001-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: solid green;
+ width: 25em;
+ }
+ #test {
+ border: solid blue;
+ }
+</style>
+<body>
+ <p>Test passes if the text in the green box and the blue box have the same spacing between words and the lines wrap at the same point.</p>
+ <div>This text<br />should be on two lines.</div>
+ <div id="test">This text<br />should be on two lines.</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-001.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-001.xht
index 2fe179f43fe..92698714036 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-001.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-001.xht
@@ -4,6 +4,7 @@
<title>CSS Test: Content property and white-space: pre-line</title>
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-white-space-001-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="'white-space: pre-line' applies to generated string content." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-002-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-002-ref.html
new file mode 100644
index 00000000000..62b54e2d859
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-002-ref.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: solid silver;
+ margin: 0.5em;
+ padding: 0.2em;
+ color: blue;
+ white-space: pre;
+ }
+</style>
+<body>
+ <p>Test passes if the contents of the two silver boxes are identical.</p>
+ <div>This text
+ should be on
+ four
+ lines.</div>
+ <div>This text
+ should be on
+ four
+ lines.</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-002.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-002.xht
index 131489e4013..52294d27f47 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-002.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-002.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact" />
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-white-space-002-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="'white-space: pre' applies to generated string content." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-003-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-003-ref.html
new file mode 100644
index 00000000000..283bd8186f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-003-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: solid silver;
+ margin: 0.5em;
+ padding: 0.2em;
+ color: blue;
+ }
+</style>
+<body>
+ <p>Test passes if the contents of the two silver boxes are identical.</p>
+ <div>This text should be on one line.</div>
+ <div>This text should be on one line.</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-003.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-003.xht
index dc72283a4b4..83fd21d574f 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-003.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-003.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact" />
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-white-space-003-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="'white-space: nowrap' applies to generated string content." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-004-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-004-ref.html
new file mode 100644
index 00000000000..5c5fa20633d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-004-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div {
+ border: solid silver;
+ margin: 0.5em;
+ padding: 0.2em;
+ color: blue;
+ width: 10em;
+ }
+</style>
+<body>
+ <p>Test passes if the contents of the two silver boxes are identical.</p>
+ <div>This text should wrap normally.</div>
+ <div>This text should wrap normally.</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-004.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-004.xht
index 83561849c28..34c186295a4 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-004.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/content-white-space-004.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact" />
<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#content" />
+ <link rel="match" href="content-white-space-004-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="'white-space: normal' applies to generated string content." />
<style type="text/css">
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-hidden-000-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-hidden-000-ref.html
new file mode 100644
index 00000000000..db63888d610
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-hidden-000-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<body>
+ <p>The following should be identical:</p>
+ <div>0</div>
+ <div>0</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-hidden-000.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-hidden-000.xht
index 0cb724cc916..a3c62481f6b 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-hidden-000.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-hidden-000.xht
@@ -7,6 +7,7 @@
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#counters"/>
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content"/>
<link rel="help" href="http://www.w3.org/TR/CSS21/syndata.html#counter"/>
+ <link rel="match" href="counters-hidden-000-ref.html" />
<style type="text/css">
body { white-space: nowrap; }
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-hidden-001.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-hidden-001.xht
index 7c2be2d6234..b8726093313 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-hidden-001.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-hidden-001.xht
@@ -7,6 +7,7 @@
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#counters"/>
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content"/>
<link rel="help" href="http://www.w3.org/TR/CSS21/syndata.html#counter"/>
+ <link rel="match" href="counters-hidden-000-ref.html" />
<style type="text/css">
body { white-space: nowrap; }
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-hidden-002-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-hidden-002-ref.html
new file mode 100644
index 00000000000..ce3c9fc0c68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-hidden-002-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<body>
+ <p>The following should be identical:</p>
+ <div>1</div>
+ <div>1</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-hidden-002.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-hidden-002.xht
index 12aaa257a6e..3253f3e7d99 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-hidden-002.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-hidden-002.xht
@@ -7,6 +7,7 @@
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#counters"/>
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content"/>
<link rel="help" href="http://www.w3.org/TR/CSS21/syndata.html#counter"/>
+ <link rel="match" href="counters-hidden-002-ref.html" />
<style type="text/css">
body { white-space: nowrap; }
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-multi-000-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-multi-000-ref.html
new file mode 100644
index 00000000000..09c607f67c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-multi-000-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<body>
+ <p>The following should be identical:</p>
+ <div>12</div>
+ <div>12</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-multi-000.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-multi-000.xht
index 23eeff48f4b..1c9bab5a7db 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-multi-000.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-multi-000.xht
@@ -6,6 +6,7 @@
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#counters"/>
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content"/>
<link rel="help" href="http://www.w3.org/TR/CSS21/syndata.html#counter"/>
+ <link rel="match" href="counters-multi-000-ref.html" />
<style type="text/css">
body { white-space: nowrap; }
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-multi-001.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-multi-001.xht
index 743abce3cad..a67d6ce14c7 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-multi-001.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-multi-001.xht
@@ -6,6 +6,7 @@
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#counters"/>
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content"/>
<link rel="help" href="http://www.w3.org/TR/CSS21/syndata.html#counter"/>
+ <link rel="match" href="counters-multi-000-ref.html" />
<style type="text/css">
body { white-space: nowrap; }
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-order-000-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-order-000-ref.html
new file mode 100644
index 00000000000..341484cf543
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-order-000-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<body>
+ <p>The following should be identical:</p>
+ <div>0 1 2 3 4 4 4 4 8 9 10 11 12 12 12 12</div>
+ <div>0 1 2 3 4 4 4 4 8 9 10 11 12 12 12 12</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-order-000.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-order-000.xht
index ce1d154ca89..7fd5bb6b99f 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-order-000.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-order-000.xht
@@ -6,6 +6,7 @@
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#counters"/>
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content"/>
<link rel="help" href="http://www.w3.org/TR/CSS21/syndata.html#counter"/>
+ <link rel="match" href="counters-order-000-ref.html" />
<style type="text/css">
body { white-space: nowrap; }
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-root-000-ref.html b/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-root-000-ref.html
new file mode 100644
index 00000000000..ecf26454666
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-root-000-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<body>
+ <p>The following should be identical:</p>
+ <div>4.8</div>
+ <div>4.8</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-root-000.xht b/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-root-000.xht
index e8fa6e78649..d588241d528 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-root-000.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/generated-content/counters-root-000.xht
@@ -6,6 +6,7 @@
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#counters"/>
<link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-content"/>
<link rel="help" href="http://www.w3.org/TR/CSS21/syndata.html#counter"/>
+ <link rel="match" href="counters-root-000-ref.html" />
<style type="text/css">
body { white-space: nowrap; }
diff --git a/tests/wpt/web-platform-tests/css/CSS2/linebox/line-height-oof-descendants-001-ref.html b/tests/wpt/web-platform-tests/css/CSS2/linebox/line-height-oof-descendants-001-ref.html
new file mode 100644
index 00000000000..c338a1b1152
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/linebox/line-height-oof-descendants-001-ref.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Test Reference</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<style>
+p {
+ font-size: 20px;
+ line-height: 0;
+}
+</style>
+<p>Some paragraph</p>
+<p>Some paragraph</p>
+<p>Some paragraph</p>
+<p>Some other paragraph</p>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/linebox/line-height-oof-descendants-001.html b/tests/wpt/web-platform-tests/css/CSS2/linebox/line-height-oof-descendants-001.html
new file mode 100644
index 00000000000..6663b1949a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/linebox/line-height-oof-descendants-001.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Test: line-height is not affected by out-of-flow descendants</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="help" href="https://www.w3.org/TR/CSS21/visudet.html#line-height">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1426760">
+<link rel="match" href="line-height-oof-descendants-001-ref.html">
+<style>
+p {
+ font-size: 20px;
+ line-height: 0;
+}
+</style>
+<p><span style="position: absolute;"></span>Some paragraph</p>
+<p><span style="float: left;"></span>Some paragraph</p>
+<p><span style="position: fixed;"></span>Some paragraph</p>
+<p>Some other paragraph</p>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/values/numbers-units-011.xht b/tests/wpt/web-platform-tests/css/CSS2/values/numbers-units-011.xht
index ae5737b5e19..eb52c980f84 100644
--- a/tests/wpt/web-platform-tests/css/CSS2/values/numbers-units-011.xht
+++ b/tests/wpt/web-platform-tests/css/CSS2/values/numbers-units-011.xht
@@ -22,6 +22,7 @@
{
font-family: Ahem;
margin-top: 10px;
+ line-height: 1;
}
</style>
</head>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/visudet/content-height-001.html b/tests/wpt/web-platform-tests/css/CSS2/visudet/content-height-001.html
new file mode 100644
index 00000000000..54fc8da4bea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/visudet/content-height-001.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS2 inline level box content height test</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#line-height">
+<link rel="match" href="reference/content-height-001-ref.html">
+<meta name="flags" content="">
+<meta name="assert" content="The height of the content area of an inline-level box does not depend on the value of the line-height property">
+<style>
+
+div { font-size: 50px; display: inline-block; color: transparent; }
+
+span { background: blue; }
+
+div { line-height: 200px; }
+div:nth-of-type(2) { line-height: 30px; }
+div:nth-of-type(3) { line-height: normal; }
+</style>
+
+<p>Test passes if the blue shape below is a rectangle, but not some other polygon.
+
+<div><span>aa</span></div><div><span>aa</span></div><div><span>aa</span></div>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/visudet/content-height-002.html b/tests/wpt/web-platform-tests/css/CSS2/visudet/content-height-002.html
new file mode 100644
index 00000000000..af1ed946c70
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/visudet/content-height-002.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS2 inline level box content height test</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#line-height">
+<link rel="match" href="reference/content-height-002-ref.html">
+<meta name="flags" content="">
+<meta name="assert" content="The height of the content area of an inline-level box does not depend on the value of the line-height property,
+ even when fallback fonts are used">
+<style>
+@font-face {
+ font-family: 'high-a-only';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/Revalia.woff) format('woff');
+ unicode-range: U+0061, U+0020;
+}
+@font-face {
+ font-family: 'deep-b-only';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/AD.woff) format('woff');
+ unicode-range: U+0062, U+0020;
+}
+
+div {
+ font-size: 50px;
+ display: inline-block;
+ color: transparent;
+ font-family: high-a-only, deep-b-only;
+}
+
+span { background: blue; }
+
+div { line-height: 200px; }
+div:nth-of-type(2) { line-height: 30px; }
+div:nth-of-type(3) { line-height: normal; }
+</style>
+
+<p>Test passes if the blue shape below is a rectangle, but not some other polygon.
+
+<div><span>ab</span></div><div><span>ab</span></div><div><span>ab</span></div>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/visudet/content-height-003.html b/tests/wpt/web-platform-tests/css/CSS2/visudet/content-height-003.html
new file mode 100644
index 00000000000..c0247991928
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/visudet/content-height-003.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS2 inline level box content height test</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#line-height">
+<link rel="match" href="reference/content-height-003-ref.html">
+<meta name="flags" content="">
+<meta name="assert" content="The height of the content area of an inline-level box does not depend on the value of the line-height property,
+ even when fallback fonts are used at the exclusion of the first available font">
+<style>
+@font-face {
+ font-family: 'high-a-only';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/Revalia.woff) format('woff');
+ unicode-range: U+0061, U+0020;
+}
+@font-face {
+ font-family: 'deep-b-only';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/AD.woff) format('woff');
+ unicode-range: U+0062, U+0020;
+}
+
+div {
+ font-size: 50px;
+ display: inline-block;
+ color: transparent;
+ font-family: high-a-only, deep-b-only;
+}
+
+span { background: blue; }
+
+div { line-height: 200px; }
+div:nth-of-type(2) { line-height: 30px; }
+div:nth-of-type(3) { line-height: normal; }
+</style>
+
+<p>Test passes if the blue shape below is a rectangle, but not some other polygon.
+
+<div><span>bb</span></div><div><span>bb</span></div><div><span>bb</span></div>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/visudet/content-height-004.html b/tests/wpt/web-platform-tests/css/CSS2/visudet/content-height-004.html
new file mode 100644
index 00000000000..b5823b9f56a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/visudet/content-height-004.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS2 inline level box content height test</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#line-height">
+<link rel="match" href="reference/content-height-004-ref.html">
+<meta name="flags" content="">
+<meta name="assert" content="The height of the content area of an inline-level does not depend on fallback fonts
+ regardless of whether they are used on not.">
+<style>
+@font-face {
+ font-family: 'high-a-only';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/Revalia.woff) format('woff');
+ unicode-range: U+0061, U+0020;
+}
+@font-face {
+ font-family: 'deep-b-only';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/AD.woff) format('woff');
+ unicode-range: U+0062, U+0020;
+}
+
+div {
+ font-size: 50px;
+ display: inline-block;
+ color: transparent;
+ font-family: high-a-only, deep-b-only;
+}
+
+span { background: blue; }
+
+div { }
+div:nth-of-type(2) { }
+div:nth-of-type(3) { }
+div:nth-of-type(4) { font-family: high-a-only }
+aside {
+ max-width: 300px;
+ overflow: hidden;
+ white-space: pre;
+}
+</style>
+
+<p>Test passes if the blue shape below is a rectangle, but not some other polygon.
+
+<aside>
+<div><span>aa</span></div><div><span>bb</span></div><div><span>ab</span></div><div><span>aaa</span></div>
+</aside>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/visudet/content-height-005.html b/tests/wpt/web-platform-tests/css/CSS2/visudet/content-height-005.html
new file mode 100644
index 00000000000..6780f814349
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/visudet/content-height-005.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS2 inline level box content height test</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#line-height">
+<link rel="mismatch" href="reference/content-height-005-ref.html">
+<meta name="flags" content="">
+<meta name="assert" content="The height of the content area of an inline-level depends on the primary font">
+<style>
+@font-face {
+ font-family: 'high';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/Revalia.woff) format('woff');
+}
+@font-face {
+ font-family: 'deep';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/AD.woff) format('woff');
+}
+
+div {
+ font-size: 50px;
+ display: inline-block;
+}
+
+span {
+ padding-left: 1em;
+ color: black;
+ border-top: solid 1px;
+ border-bottom: solid 1px;
+}
+
+div:nth-of-type(1) { font-family: deep; }
+div:nth-of-type(2) { font-family: high; margin-left: -1em; }
+</style>
+
+<p>Test passes if there are <strong>more than 2</strong> lines below.
+
+<div><span></span></div><div><span></span></div>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/visudet/line-height-201.html b/tests/wpt/web-platform-tests/css/CSS2/visudet/line-height-201.html
new file mode 100644
index 00000000000..10b8ae0d9fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/visudet/line-height-201.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS2 Line height test: explicit sizing</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#line-height">
+<link rel="match" href="reference/line-height-201-ref.html">
+<meta name="flags" content="">
+<meta name="assert" content="non-normal values of line-height result in the height of the inline-level box to be exactly the specified dimention,
+ even when fallback fonts with metrics different from the first available font one are used.">
+<style>
+@font-face {
+ font-family: 'high-a-only';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/Revalia.woff) format('woff');
+ unicode-range: U+0020, U+0061;
+}
+@font-face {
+ font-family: 'deep-b-only';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/AD.woff) format('woff');
+ unicode-range: U+0062;
+}
+
+#red { /* red to be uncovered if the test divs aren't tall enough */
+ position: absolute;
+ background: red;
+ width: 100px;
+ height: 100px;
+}
+
+div:not(#red) {
+ position: absolute;
+ width: 50px;
+ line-height: 100px;
+ font-family: high-a-only, deep-b-only;
+ background: url("support/1x1-green.png") 0 0 / 50px 100px no-repeat, red; /* gets red if the div is too large */
+ color: transparent;
+}
+#test {
+ font-size: 20px; /* With a font-size smaller than the line-height */
+}
+#test2 {
+ margin-left: 50px;
+ font-size: 150px; /* With a font-size larger than the line-height */
+}
+</style>
+
+<p>Test passes if there is a <strong>green square</strong> and <strong>no red</strong> below.
+
+<div id=red></div>
+
+<div id=test>ab</div>
+<div id=test2>ab</div>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/visudet/line-height-202.html b/tests/wpt/web-platform-tests/css/CSS2/visudet/line-height-202.html
new file mode 100644
index 00000000000..719cf84aa48
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/visudet/line-height-202.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS2 Line height test: baseline position when explicit sizing</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#line-height">
+<link rel="match" href="reference/line-height-202-ref.html">
+<meta name="flags" content="">
+<meta name="assert" content="The position of the baseline in an inline-level box whose height is determined by a non-normal value of line-height
+ does not depend on fonts other than the first available font">
+<style>
+@font-face {
+ font-family: 'high-a-only';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/Revalia.woff) format('woff');
+ unicode-range: U+0020, U+0061;
+}
+@font-face {
+ font-family: 'deep-b-only';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/AD.woff) format('woff');
+ unicode-range: U+0062;
+}
+
+div {
+ position: absolute;
+ line-height: 100px;
+ font-size: 100px;
+ width: 300px; /* plenty of room for the (invisible) text */
+ text-align: right;
+ color: transparent;
+}
+span { /* visible thing aligned to the baseline, and small enough to not influence its position */
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+
+}
+
+/* white #h is on top of red #hd,
+ and the presence of a fallback font in #hd should not influence the position of the baseline,
+ so #h should completely cover #hd,
+ and no red should be visible. */
+#hd { font-family: high-a-only, deep-b-only; }
+#hd span { background: red; }
+
+#h { font-family: high-a-only; }
+#h span { background: white; }
+
+</style>
+
+<p>Test passes if there is <strong>no red</strong> below.
+
+<div id=hd>ab<span></span></div>
+<div id=h>aa<span></span></div>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/visudet/line-height-203.html b/tests/wpt/web-platform-tests/css/CSS2/visudet/line-height-203.html
new file mode 100644
index 00000000000..4c72aa0000a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/visudet/line-height-203.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS2 Line height test: baseline position with explicit sizing</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#line-height">
+<link rel="mismatch" href="reference/line-height-203-ref.html">
+<meta name="flags" content="">
+<meta name="assert" content="The position of the baseline in an inline-level box whose height is determined by a non-normal value of line-height
+ does depend on the first available font.">
+<style>
+@font-face {
+ font-family: 'high';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/Revalia.woff) format('woff');
+}
+@font-face {
+ font-family: 'deep';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/AD.woff) format('woff');
+}
+
+div {
+ position: absolute;
+ line-height: 100px;
+ font-size: 100px;
+ width: 300px; /* plenty of room for the (invisible) text */
+ text-align: right;
+ color: transparent;
+}
+span { /* visible thing aligned to the baseline, and small enough to not influence its position */
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+}
+
+/* white #h is on top of green #d,
+ but as they have different primary fonts,
+ their baselines should not line up and green #d should be visible.*/
+#d { font-family: deep; }
+#d span { background: green; }
+
+#h { font-family: high; }
+#h span { background: white; }
+
+</style>
+
+<p>Test passes if there is a small green rectangle or square below.
+
+<div id=d>aa<span></span></div>
+<div id=h>aa<span></span></div>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/visudet/line-height-204.html b/tests/wpt/web-platform-tests/css/CSS2/visudet/line-height-204.html
new file mode 100644
index 00000000000..9f16e624526
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/visudet/line-height-204.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<title>CSS2 Line height test: baseline position, normal sizing vs explicit sizing</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#line-height">
+<link rel="match" href="reference/line-height-202-ref.html">
+<meta name="flags" content="">
+<meta name="assert" content="The position of the baseline in an inline-level box whose line-height is normal
+ and the position of the baseline in an inline-level box whose line-height is set to a non normal value resulting in the same height
+ are the same,
+ assuming only the first available font is used.">
+<style>
+@font-face {
+ font-family: 'high';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/Revalia.woff) format('woff');
+}
+
+div {
+ position: absolute;
+ font-size: 100px;
+ width: 2em; /* plenty of room for the (invisible) text */
+ text-align: right;
+ color: transparent;
+}
+span { /* visible thing aligned to the baseline, and small enough to not influence its position */
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+}
+
+/* white #lh-auto is on top of red #lh-manual,
+ and as their baselines should line up
+ #lh-manual should be fully covered,
+ and no red should be visible */
+#lh-manual { font-family: high; }
+#lh-manual span { background: red; }
+
+#lh-auto { font-family: high; line-height: normal; }
+#lh-auto span { background: white; }
+
+</style>
+
+<body onload="measure()">
+<p>Test passes if there is <strong>no red</strong> below.
+
+<div id=lh-manual>a<span></span></div>
+<div id=lh-auto>a<span></span></div>
+
+<script>
+function measure() { /* let layout complete first, so that we can measure things */
+ var lha = document.getElementById("lh-auto");
+ var lhm = document.getElementById("lh-manual")
+ var h = window.getComputedStyle(lha).height; /*getting the used-value of line-height by proxy */
+ lhm.style.lineHeight = h;
+ document.documentElement.className = "";
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/visudet/line-height-205.html b/tests/wpt/web-platform-tests/css/CSS2/visudet/line-height-205.html
new file mode 100644
index 00000000000..506a044d566
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/visudet/line-height-205.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS2 Line height test: normal sizing</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#line-height">
+<link rel="match" href="reference/line-height-202-ref.html">
+<meta name="flags" content="">
+<meta name="assert" content="The height of an inline-level box whose line-height is normal and uses both the first available font and fallback fonts
+ is the same as the union of
+ baseline-aligned adjacent inline-level boxes, each using the various fonts as their primary one.">
+<style>
+@font-face {
+ font-family: 'high-a-only';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/Revalia.woff) format('woff');
+ unicode-range: U+0020, U+0061;
+}
+@font-face {
+ font-family: 'deep-b-only';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/AD.woff) format('woff');
+ unicode-range: U+0020, U+0062;
+}
+
+div {
+ position: absolute;
+ line-height: normal;
+ font-size: 100px;
+ color: transparent;
+}
+
+.h { font-family: high-a-only; }
+.d { font-family: deep-b-only; }
+.hd { font-family: high-a-only, deep-b-only; }
+.white { background: white; }
+.red { background: red; }
+.shift { margin-left: 300px; }
+</style>
+
+<p>Test passes if there is <strong>no red</strong> below.
+
+<!-- Check if the hd div is larger-->
+
+<div class="hd red">ab</div>
+<div class=white><span class=h>a</span><span class=d>b</span></div>
+
+<!-- Same thing, reversed, to check if the hd dix is smaller -->
+
+<div class="red shift"><span class=h>a</span><span class=d>b</span></div>
+<div class="hd white shift">ab</div>
+
diff --git a/tests/wpt/web-platform-tests/css/CSS2/visudet/line-height-206.html b/tests/wpt/web-platform-tests/css/CSS2/visudet/line-height-206.html
new file mode 100644
index 00000000000..25f0ab933f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/visudet/line-height-206.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS2 Line height test: normal sizing with fallback fonts</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/css2/visudet.html#line-height">
+<link rel="mismatch" href="reference/line-height-206-ref.html">
+<meta name="flags" content="">
+<meta name="assert" content="The height of an inline-level box whose line-height is normal and which only uses glyphs from the fallback font
+ must still take the strut from the first available font into account.">
+<style>
+@font-face {
+ font-family: 'high-a-only';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/Revalia.woff) format('woff');
+ unicode-range: U+0061, U+0020;
+}
+@font-face {
+ font-family: 'deep-b-only';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/AD.woff) format('woff');
+ unicode-range: U+0062, U+0020;
+}
+
+div {
+ position: absolute;
+ line-height: normal;
+ font-size: 100px;
+ color: transparent;
+ border: solid black 1px;
+}
+
+.h { font-family: high-a-only; }
+.dh { font-family: deep-b-only, high-a-only; }
+</style>
+
+<p>There should be two stacked rectangles below: a tall one above a short one, both the same width, sharing the edge at which they touch.
+
+<!-- Both divs show the same content with the same font,
+ but the first div has an unused first available font
+ while the second one does not.
+ As the height calculation takes the strut into account,
+ these two boxes should have different heights -->
+<div class="dh">a</div>
+<div class="h">a</div>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/content-height-001-ref.html b/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/content-height-001-ref.html
new file mode 100644
index 00000000000..d6ca716b0cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/content-height-001-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Test Reference file</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<style>
+
+div { font-size: 50px; display: inline-block; color: transparent; }
+
+span { background: blue; }
+
+div { line-height: 200px; }
+</style>
+
+<p>Test passes if the blue shape below is a rectangle, but not some other polygon.
+
+<div><span>aa</span></div><div><span>aa</span></div><div><span>aa</span></div>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/content-height-002-ref.html b/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/content-height-002-ref.html
new file mode 100644
index 00000000000..511eef0549a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/content-height-002-ref.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Test Reference file</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<style>
+@font-face {
+ font-family: 'high-a-only';
+ font-style: normal;
+ font-weight: 400;
+ src: url(../support/Revalia.woff) format('woff');
+ unicode-range: U+0061;
+}
+@font-face {
+ font-family: 'deep-b-only';
+ font-style: normal;
+ font-weight: 400;
+ src: url(../support/AD.woff) format('woff');
+ unicode-range: U+0062;
+}
+
+div {
+ font-size: 50px;
+ display: inline-block;
+ color: transparent;
+ font-family: high-a-only, deep-b-only;
+}
+
+span { background: blue; }
+
+div { line-height: 200px; }
+</style>
+
+<p>Test passes if the blue shape below is a rectangle, but not some other polygon.
+
+<div><span>ab</span></div><div><span>ab</span></div><div><span>ab</span></div>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/content-height-003-ref.html b/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/content-height-003-ref.html
new file mode 100644
index 00000000000..60a805de4e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/content-height-003-ref.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Test Reference file</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<style>
+@font-face {
+ font-family: 'high-a-only';
+ font-style: normal;
+ font-weight: 400;
+ src: url(../support/Revalia.woff) format('woff');
+ unicode-range: U+0061;
+}
+@font-face {
+ font-family: 'deep-b-only';
+ font-style: normal;
+ font-weight: 400;
+ src: url(../support/AD.woff) format('woff');
+ unicode-range: U+0062;
+}
+
+div {
+ font-size: 50px;
+ display: inline-block;
+ color: transparent;
+ font-family: high-a-only, deep-b-only;
+}
+
+span { background: blue; }
+
+div { line-height: 200px; }
+</style>
+
+<p>Test passes if the blue shape below is a rectangle, but not some other polygon.
+
+<div><span>bb</span></div><div><span>bb</span></div><div><span>bb</span></div>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/content-height-004-ref.html b/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/content-height-004-ref.html
new file mode 100644
index 00000000000..10460f018fc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/content-height-004-ref.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS2 Line height test: explicit sizing</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<style>
+@font-face {
+ font-family: 'high-a-only';
+ font-style: normal;
+ font-weight: 400;
+ src: url(../support/Revalia.woff) format('woff');
+ unicode-range: U+0061;
+}
+
+div {
+ font-size: 50px;
+ display: inline-block;
+ color: transparent;
+}
+
+span { background: blue; }
+
+div { font-family: high-a-only }
+aside {
+ max-width: 300px;
+ overflow: hidden;
+ white-space: pre;
+}
+</style>
+
+<p>Test passes if the blue shape below is a rectangle, but not some other polygon.
+
+<aside>
+<div><span>aaaaaaaaa</span></div>
+</aside>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/content-height-005-ref.html b/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/content-height-005-ref.html
new file mode 100644
index 00000000000..70a3ee07840
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/content-height-005-ref.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Test Reference file</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+
+div {
+ font-size: 50px;
+ display: inline-block;
+}
+
+span {
+ padding-left: 1em;
+ color: black;
+ border-top: solid 1px;
+ border-bottom: solid 1px;
+}
+
+</style>
+
+<p>Test passes if there are <strong>more than 2</strong> lines below.
+
+<div><span></span></div>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/line-height-201-ref.html b/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/line-height-201-ref.html
new file mode 100644
index 00000000000..3564bf77858
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/line-height-201-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Test Reference file</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<style>
+div {
+ position: absolute;
+ width: 100px;
+ height: 100px;
+ background: green;
+}
+</style>
+
+<p>Test passes if there is a <strong>green square</strong> and <strong>no red</strong> below.
+
+<div></div>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/line-height-202-ref.html b/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/line-height-202-ref.html
new file mode 100644
index 00000000000..2b77a6b3dd3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/line-height-202-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Test Reference file</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+
+<p>Test passes if there is <strong>no red</strong> below.
diff --git a/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/line-height-203-ref.html b/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/line-height-203-ref.html
new file mode 100644
index 00000000000..ec605c76a91
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/line-height-203-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Test Reference file</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+
+<p>Test passes if there is a small green rectangle or square below.
diff --git a/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/line-height-206-ref.html b/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/line-height-206-ref.html
new file mode 100644
index 00000000000..31ce1a98dc3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/visudet/reference/line-height-206-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Test Reference file</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<style>
+@font-face {
+ font-family: 'high-a-only';
+ font-style: normal;
+ font-weight: 400;
+ src: url(../support/Revalia.woff) format('woff');
+ unicode-range: U+0061;
+}
+
+div {
+ position: absolute;
+ line-height: normal;
+ font-size: 100px;
+ color: transparent;
+ border: solid black 1px;
+ font-family: high-a-only;
+}
+</style>
+
+<p>There should be two stacked rectangles below: a tall one above a short one, both the same width, sharing the edge at which they touch.
+
+<div>a</div>
diff --git a/tests/wpt/web-platform-tests/css/CSS2/visudet/support/1x1-green.png b/tests/wpt/web-platform-tests/css/CSS2/visudet/support/1x1-green.png
new file mode 100644
index 00000000000..b98ca0ba0a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/visudet/support/1x1-green.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/css/CSS2/visudet/support/AD.woff b/tests/wpt/web-platform-tests/css/CSS2/visudet/support/AD.woff
new file mode 100644
index 00000000000..3df8ea8efda
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/visudet/support/AD.woff
Binary files differ
diff --git a/tests/wpt/web-platform-tests/css/CSS2/visudet/support/Revalia.woff b/tests/wpt/web-platform-tests/css/CSS2/visudet/support/Revalia.woff
new file mode 100644
index 00000000000..631bee6de90
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/CSS2/visudet/support/Revalia.woff
Binary files differ
diff --git a/tests/wpt/web-platform-tests/css/OWNERS b/tests/wpt/web-platform-tests/css/OWNERS
deleted file mode 100644
index 7282743f680..00000000000
--- a/tests/wpt/web-platform-tests/css/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-@gsnedders
-
diff --git a/tests/wpt/web-platform-tests/css/README.md b/tests/wpt/web-platform-tests/css/README.md
index 668ba28f4ac..4967f8cf479 100644
--- a/tests/wpt/web-platform-tests/css/README.md
+++ b/tests/wpt/web-platform-tests/css/README.md
@@ -1,12 +1,14 @@
Introduction
------------
-This directory contains all testsuites for all CSS specifications still using
-the [CSS test harness][harness]. These should primarily be considered legacy;
-new testsuites should almost always be put at the top level without any level
-suffix.
+This directory contains testsuites for CSS WG specifications, including ones
+that do not strictly speaking define CSS features, e.g.,
+[Geometry Interfaces](https://drafts.fxtf.org/geometry/).
-As the test harness relies on the largely undocumented(!) old CSS build system,
+The directories should be named like the specification's shortname, but without
+any level suffix.
+
+As the test harness relies on the largely undocumented old CSS build system,
this directory has a number of test requirements specific to it:
* support files for a given test must live in an adjacent `support` directory;
@@ -20,21 +22,14 @@ this directory has a number of test requirements specific to it:
`css` directory.
-Odd Directories
----------------
-
-There are a few special directories that do not map to specifications:
+vendor-imports/ Directory
+-------------------------
vendor-imports/ is a legacy directory where third parties historically imported
their tests that originate and are maintained in an external repo. Files in
this directory should never be modified in this repo, but should go through the
vendor's process to be imported here.
-work-in-progress/ is a legacy directory that contains all the work that was
-once submitted to the repo, but was not yet ready for review. As pull requests
-are now used, no new files should be added here. The subdirectories here are
-named by test author or contributing organization.
-
Importing Old Branches
----------------------
diff --git a/tests/wpt/web-platform-tests/css/compositing/mix-blend-mode/mix-blend-mode-transition.html b/tests/wpt/web-platform-tests/css/compositing/mix-blend-mode/mix-blend-mode-transition.html
deleted file mode 100644
index e3d3501eb5d..00000000000
--- a/tests/wpt/web-platform-tests/css/compositing/mix-blend-mode/mix-blend-mode-transition.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <title>CSS Test: Blended element with transition</title>
- <link rel="author" title="Mihai Tica" href="mailto:mitica@adobe.com">
- <link rel="help" href="https://drafts.fxtf.org/compositing-1/#mix-blend-mode">
- <meta name="assert" content="Test checks that an element having a transition applied on opacity blends with the parent element.">
- <meta name="flags" content="dom"/>
- <link rel="reviewer" title="Rik Cabanier" href="mailto:cabanier@adobe.com">
- <link rel="reviewer" title="Mirela Budaes" href="mailto:mbudaes@adobe.com">
- <link rel="match" href="reference/mix-blend-mode-transition-ref.html">
- <style type="text/css">
- div {
- width: 100px;
- height: 100px;
- background: #FF0;
- }
-
- #blender {
- background: #F00;
- mix-blend-mode: difference;
- transition: opacity 1s ease;
- }
-
- .opaqueBox {
- opacity: 0.4;
- }
- </style>
- </head>
- <body>
- <p>Test passes if you can see a fading green rectangle.</p>
- <div><div id="blender"></div></div>
- <script type="text/javascript">
- setInterval(function(){ document.getElementById('blender').className = 'opaqueBox'; }, 100);
- </script>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/compositing/mix-blend-mode/reference/mix-blend-mode-transition-ref.html b/tests/wpt/web-platform-tests/css/compositing/mix-blend-mode/reference/mix-blend-mode-transition-ref.html
deleted file mode 100644
index bb7d02039c1..00000000000
--- a/tests/wpt/web-platform-tests/css/compositing/mix-blend-mode/reference/mix-blend-mode-transition-ref.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <title>CSS Test: Blended element with transition</title>
- <link rel="author" title="Mihai Tica" href="mailto:mitica@adobe.com">
- <meta name="flags" content="dom"/>
- <style type="text/css">
- div {
- width: 100px;
- height: 100px;
- }
-
- #blender {
- background: #0F0;
- transition: opacity 1s ease;
- }
-
- .opaqueBox {
- opacity: 0.4;
- }
- </style>
- </head>
- <body>
- <p>Test passes if you can see a fading green rectangle.</p>
- <div style="background: #FF0;"><div id="blender"></div></div>
- <script type="text/javascript">
- setInterval(function(){ document.getElementById('blender').className = 'opaqueBox'; }, 100);
- </script>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-animations/animation-delay-011.html b/tests/wpt/web-platform-tests/css/css-animations/animation-delay-011.html
new file mode 100644
index 00000000000..415a5747553
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-animations/animation-delay-011.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Animations Test: inherited animation-delay with mismatched animation-name length</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="help" href="https://drafts.csswg.org/css-animations-1/#animations">
+<link rel="match" href="animation-common-ref.html">
+<style>
+div:after {
+ content: '';
+ display: block;
+ width: 100px;
+ height: 100px;
+ background: red;
+ animation: doesntmatter 50s linear infinite,
+ bg 100s step-end infinite;
+ animation-play-state: paused;
+ animation-delay: inherit;
+}
+
+@keyframes bg {
+ 50% { background: green; }
+}
+</style>
+<div style="animation-delay: -50s"></div>
diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-001.html b/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-001.html
new file mode 100644
index 00000000000..4cfc36033d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-001.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>CSS Backgrounds and Borders Test: propagate body background to viewport</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-backgrounds/#body-background">
+<link rel="match" href="background-color-body-propagation-ref.html">
+<style>
+ html {
+ background-color: transparent;
+ background-image: none;
+ }
+ body {
+ background-color: green;
+ margin: 0;
+ }
+</style>
+<p>The viewport should have a green background.</p>
diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-002.html b/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-002.html
new file mode 100644
index 00000000000..1c42637e505
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-002.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>CSS Backgrounds and Borders Test: body background not propagating when html does</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-backgrounds/#body-background">
+<link rel="match" href="background-color-body-propagation-ref.html">
+<style>
+ html {
+ background-color: green;
+ background-image: none;
+ }
+ body {
+ background-color: red;
+ margin: 0;
+ }
+ p {
+ background: green;
+ }
+</style>
+<p>The viewport should have a green background.</p>
diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-003.html b/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-003.html
new file mode 100644
index 00000000000..8106822a4e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-003.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<title>CSS Backgrounds and Borders Test: propagate body background while display changes</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-backgrounds/#body-background">
+<link rel="match" href="background-color-body-propagation-ref.html">
+<style>body { margin: 0 }</style>
+<p>The viewport should have a green background.</p>
+<script>
+ document.body.offsetTop;
+ document.body.style = "display:inline;background:green";
+</script>
diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-ref.html b/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-ref.html
new file mode 100644
index 00000000000..1a138740de9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-backgrounds/background-color-body-propagation-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html style="background:green">
+<title>CSS Reftest Reference</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<body style="margin:0">
+<p>The viewport should have a green background.</p>
diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/background-image-none-gradient-repaint.html b/tests/wpt/web-platform-tests/css/css-backgrounds/background-image-none-gradient-repaint.html
new file mode 100644
index 00000000000..3f39fb8d850
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-backgrounds/background-image-none-gradient-repaint.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<title>CSS Backgrounds and Borders: Repaint gradient change in second layer</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="match" href="background-clip-color-repaint-ref.html">
+<link rel="help" href="https://drafts.csswg.org/css-backgrounds/#layering">
+<style>
+ #box {
+ width: 150px;
+ height: 150px;
+ }
+ .red {
+ background: none, linear-gradient(to right, red, red);
+ }
+ .green {
+ background: none, linear-gradient(to right, green, green);
+ }
+</style>
+<p>There should be a green square below.</p>
+<div id="box" class="red"></div>
+<script>
+ requestAnimationFrame(function(){
+ requestAnimationFrame(function(){
+ box.className = "green";
+ document.documentElement.classList.remove("reftest-wait");
+ });
+ });
+</script>
diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-001-ref.xht b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-001-ref.xht
index 9c7bc4bd5f3..0d6f4d703e6 100644
--- a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-001-ref.xht
+++ b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-001-ref.xht
@@ -3,29 +3,25 @@
<head>
<title>CSS Test: Border radius reference</title>
<link rel="author" title="Nokia" href="http://www.nokia.com/" />
- <style type="text/css">
- /* <![CDATA[ */
- div
- {
- border:2px solid #a1a1a1;
- background:#dddddd;
- width:200px;
- height: 100px;
- }
- /* ]]> */
+ <style>
+ div {
+ border:2px solid #a1a1a1;
+ background:#dddddd;
+ width:200px;
+ height: 100px;
+ }
</style>
</head>
<body>
- <p>
- There should be two boxes with no rounded corners.</p>
+ <p>There should be two boxes with no rounded corners.</p>
<ul>
<li>PASS if the two boxes below are the same.</li>
<li>FAIL if the output is not as expected.</li>
</ul>
- <div id="test"></div>
- <p><br/></p>
- <div id="reference"></div>
+ <div id="test"></div>
+ <p><br/></p>
+ <div id="reference"></div>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-001.xht b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-001.xht
index 7536df1dc51..5029dd0f151 100644
--- a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-001.xht
@@ -3,65 +3,33 @@
<head>
<title>CSS Test: Borders. border&ndash;radius set to zero</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
- <meta http-equiv="Content-Style-Type" content="text/css"/>
- <meta http-equiv="Content-Script-Type" content="text/javascript"/>
<link rel="author" title="Nokia" href="http://www.nokia.com/" />
<link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius" />
<link rel="match" href="border-radius-001-ref.xht" />
- <meta name="flags" content="" />
<meta name="assert" content="To verify when border-radius property, when set to zero, works as expected." />
- <style type="text/css">
- /* <![CDATA[ */
- div
- {
- border:2px solid #a1a1a1;
- background:#dddddd;
- width:200px;
- height: 100px;
+ <style>
+ div {
+ border: 2px solid #a1a1a1;
+ background: #dddddd;
+ width: 200px;
+ height: 100px;
+ }
+ #test {
+ border-radius: 0;
}
- #test
- {
- border-radius: 0;
- }
- /* ]]> */
</style>
-<!--
- <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
</head>
<body>
- <p>
- There should be two boxes with no rounded corners.
- </p>
- <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
- <ul>
- <li>PASS if the two boxes below are the same.</li>
- <li>FAIL if the output is not as expected.</li>
- </ul>
+ <p>There should be two boxes with no rounded corners.</p>
+ <ul>
+ <li>PASS if the two boxes below are the same.</li>
+ <li>FAIL if the output is not as expected.</li>
+ </ul>
<!-- PLACE TEST CONTENT FROM HERE -->
- <div id="test"></div>
- <p><br/></p>
- <div id="reference"></div>
-<!--
- <script type="text/javascript">
- /* <![CDATA[ */
- var borders = new Array("border-top-left-radius", "border-top-right-radius",
- "border-bottom-right-radius", "border-bottom-left-radius");
- var expectedValues = new Array("0px", "0px", "0px", "0px");
-
- var testResult = check_Multiple_CSS_property(borders, expectedValues);
-
- /* if (testResult.pass)
- // This portion of the code has been removed to ensure that the test case is not automated
- else {
- // This portion of the code has been removed to ensure that the test case is not automated
- } */
-
- if (top.FrameEnabled) top.fnLog(testResult);
- /* ]]> */
- </script>
--->
+ <div id="test"></div>
+ <p><br/></p>
+ <div id="reference"></div>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-002-ref.xht b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-002-ref.xht
index 104c1e15128..b9282343ebb 100644
--- a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-002-ref.xht
+++ b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-002-ref.xht
@@ -3,34 +3,28 @@
<head>
<title>CSS Test: Border radius reference</title>
<link rel="author" title="Nokia" href="http://www.nokia.com/" />
- <style type="text/css">
- /* <![CDATA[ */
- div
- {
- border:2px solid #a1a1a1;
- background:#dddddd;
- width:200px;
- height: 100px;
- border-top-left-radius: 25px;
- border-top-right-radius: 25px;
- border-bottom-right-radius: 25px;
- border-bottom-left-radius: 25px;
- }
- /* ]]> */
+ <style>
+ div {
+ border: 2px solid #a1a1a1;
+ background: #dddddd;
+ width: 200px;
+ height: 100px;
+ border-top-left-radius: 25px;
+ border-top-right-radius: 25px;
+ border-bottom-right-radius: 25px;
+ border-bottom-left-radius: 25px;
+ }
</style>
</head>
<body>
- <p>
- There should be two identical boxes, each with 4 rounded corners.
- </p>
+ <p>There should be two identical boxes, each with 4 rounded corners.</p>
<ul>
<li>PASS if the two boxes below are the same and all 4 corners are rounded.</li>
<li>FAIL if the output is not as expected.</li>
</ul>
- <div id="test"></div>
- <p><br/></p>
- <div id="reference"></div>
+ <div id="test"></div>
+ <p><br/></p>
+ <div id="reference"></div>
</body>
</html>
-
diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-002.xht b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-002.xht
index 1877e082fba..9f53fc37587 100644
--- a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-002.xht
@@ -3,68 +3,36 @@
<head>
<title>CSS Test: Borders. border&ndash;radius using one length value 25px</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
- <meta http-equiv="Content-Style-Type" content="text/css"/>
- <meta http-equiv="Content-Script-Type" content="text/javascript"/>
<link rel="author" title="Nokia" href="http://www.nokia.com/" />
<link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius" />
<link rel="match" href="border-radius-002-ref.xht" />
- <meta name="flags" content="" />
<meta name="assert" content="To verify border-radius property set with one length value, works as expected" />
- <style type="text/css">
- /* <![CDATA[ */
- div
- {
- border:2px solid #a1a1a1;
- background:#dddddd;
- width:200px;
- height: 100px;
- border-radius: 25px;
- }
- #reference
- {
- border-top-left-radius: 25px;
- border-top-right-radius: 25px;
- border-bottom-right-radius: 25px;
- border-bottom-left-radius: 25px;
- }
- /* ]]> */
+ <style>
+ div {
+ border: 2px solid #a1a1a1;
+ background: #dddddd;
+ width: 200px;
+ height: 100px;
+ border-radius: 25px;
+ }
+ #reference {
+ border-top-left-radius: 25px;
+ border-top-right-radius: 25px;
+ border-bottom-right-radius: 25px;
+ border-bottom-left-radius: 25px;
+ }
</style>
-<!--
- <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
</head>
<body>
- <p>
- There should be two identical boxes, each with 4 rounded corners.
- </p>
+ <p>There should be two identical boxes, each with 4 rounded corners.</p>
<ul>
<li>PASS if the two boxes below are the same and all 4 corners are rounded.</li>
<li>FAIL if the output is not as expected.</li>
</ul>
<!-- PLACE TEST CONTENT FROM HERE -->
- <div id="test"></div>
- <p><br/></p>
- <div id="reference"></div>
-<!--
- <script type="text/javascript">
- /* <![CDATA[ */
- var borders = new Array("border-top-left-radius", "border-top-right-radius",
- "border-bottom-right-radius", "border-bottom-left-radius");
- var expectedValues = new Array("25px", "25px", "25px", "25px");
-
- var testResult = check_Multiple_CSS_property(borders, expectedValues);
-
- /* if (testResult.pass)
- // This portion of the code has been removed to ensure that the test case is not automated
- else {
- // This portion of the code has been removed to ensure that the test case is not automated
- } */
-
- if (top.FrameEnabled) top.fnLog(testResult);
- /* ]]> */
- </script>
--->
+ <div id="test"></div>
+ <p><br/></p>
+ <div id="reference"></div>
</body>
</html>
-
diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-003-ref.xht b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-003-ref.xht
index be824c20732..d7017f024f9 100644
--- a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-003-ref.xht
+++ b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-003-ref.xht
@@ -3,34 +3,28 @@
<head>
<title>CSS Test: Border radius reference</title>
<link rel="author" title="Nokia" href="http://www.nokia.com/" />
- <style type="text/css">
- /* <![CDATA[ */
- div
- {
- border:2px solid #a1a1a1;
- background:#dddddd;
- width:200px;
- height: 100px;
- border-top-left-radius: 50px;
- border-top-right-radius: 0;
- border-bottom-right-radius: 50px;
- border-bottom-left-radius: 0;
- }
- /* ]]> */
+ <style>
+ div {
+ border: 2px solid #a1a1a1;
+ background: #dddddd;
+ width: 200px;
+ height: 100px;
+ border-top-left-radius: 50px;
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 50px;
+ border-bottom-left-radius: 0;
+ }
</style>
</head>
<body>
- <p>
- There should be two identical boxes, each with rounded corners at the top left and bottom right only.
- </p>
+ <p>There should be two identical boxes, each with rounded corners at the top left and bottom right only.</p>
<ul>
<li>PASS if the two boxes below are the same and only top left and bottom right corners are rounded.</li>
<li>FAIL if the output is not as expected.</li>
</ul>
- <div id="test"></div>
- <p><br/></p>
- <div id="reference"></div>
+ <div id="test"></div>
+ <p><br/></p>
+ <div id="reference"></div>
</body>
</html>
-
diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-003.xht b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-003.xht
index cfe4d742688..398358f1f1d 100644
--- a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-003.xht
@@ -3,68 +3,36 @@
<head>
<title>CSS Test: Borders. border&ndash;radius set to value: 50px 0</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
- <meta http-equiv="Content-Style-Type" content="text/css"/>
- <meta http-equiv="Content-Script-Type" content="text/javascript"/>
<link rel="author" title="Nokia" href="http://www.nokia.com/" />
<link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius" />
<link rel="match" href="border-radius-003-ref.xht" />
- <meta name="flags" content="" />
<meta name="assert" content="To verify border-radius property set with one length value along with a zero, works as expected" />
- <style type="text/css">
- /* <![CDATA[ */
- div
- {
- border:2px solid #a1a1a1;
- background:#dddddd;
- width:200px;
- height: 100px;
- border-radius: 50px 0;
- }
- #reference
- {
- border-top-left-radius: 50px;
- border-top-right-radius: 0;
- border-bottom-right-radius: 50px;
- border-bottom-left-radius: 0;
- }
- /* ]]> */
+ <style>
+ div {
+ border: 2px solid #a1a1a1;
+ background: #dddddd;
+ width: 200px;
+ height: 100px;
+ border-radius: 50px 0;
+ }
+ #reference {
+ border-top-left-radius: 50px;
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 50px;
+ border-bottom-left-radius: 0;
+ }
</style>
-<!--
- <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
</head>
<body>
- <p>
- There should be two identical boxes, each with rounded corners at the top left and bottom right only.
- </p>
+ <p>There should be two identical boxes, each with rounded corners at the top left and bottom right only.</p>
<ul>
<li>PASS if the two boxes below are the same and only top left and bottom right corners are rounded.</li>
<li>FAIL if the output is not as expected.</li>
</ul>
<!-- PLACE TEST CONTENT FROM HERE -->
- <div id="test"></div>
- <p><br/></p>
- <div id="reference"></div>
-<!--
- <script type="text/javascript">
- /* <![CDATA[ */
- var borders = new Array("border-top-left-radius", "border-top-right-radius",
- "border-bottom-right-radius", "border-bottom-left-radius");
- var expectedValues = new Array("50px", "0px", "50px", "0px");
-
- var testResult = check_Multiple_CSS_property(borders, expectedValues);
-
- /* if (testResult.pass)
- // This portion of the code has been removed to ensure that the test case is not automated
- else {
- // This portion of the code has been removed to ensure that the test case is not automated
- } */
-
- if (top.FrameEnabled) top.fnLog(testResult);
- /* ]]> */
- </script>
--->
+ <div id="test"></div>
+ <p><br/></p>
+ <div id="reference"></div>
</body>
</html>
-
diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-004-ref.xht b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-004-ref.xht
index 74e70ab4917..3062d7832fc 100644
--- a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-004-ref.xht
+++ b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-004-ref.xht
@@ -3,34 +3,29 @@
<head>
<title>CSS Test: Border radius reference</title>
<link rel="author" title="Nokia" href="http://www.nokia.com/" />
- <style type="text/css">
- /* <![CDATA[ */
- div
- {
- border:2px solid #a1a1a1;
- background:#dddddd;
- width:200px;
- height: 100px;
- border-top-left-radius: 50px 25px;
- border-top-right-radius: 50px 25px;
- border-bottom-right-radius: 50px 25px;
- border-bottom-left-radius: 50px 25px;
- }
- /* ]]> */
+ <style>
+ div {
+ border: 2px solid #a1a1a1;
+ background: #dddddd;
+ width: 200px;
+ height: 100px;
+ border-top-left-radius: 50px 25px;
+ border-top-right-radius: 50px 25px;
+ border-bottom-right-radius: 50px 25px;
+ border-bottom-left-radius: 50px 25px;
+ }
</style>
</head>
<body>
- <p>
- There should be two identical boxes, each with 4 rounded corners.
- </p>
+ <p>There should be two identical boxes, each with 4 rounded corners.</p>
<ul>
<li>PASS if the two boxes below are the same and all 4 corners are rounded.</li>
<li>FAIL if the output is not as expected.</li>
</ul>
- <div id="test"></div>
- <p><br/></p>
- <div id="reference"></div>
+ <div id="test"></div>
+ <p><br/></p>
+ <div id="reference"></div>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-004.xht b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-004.xht
index cfd57e29d9f..8a000d909c5 100644
--- a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-004.xht
+++ b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-004.xht
@@ -3,68 +3,37 @@
<head>
<title>CSS Test: Borders. border&ndash;radius using slash: 50px / 25px</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
- <meta http-equiv="Content-Style-Type" content="text/css"/>
- <meta http-equiv="Content-Script-Type" content="text/javascript"/>
<link rel="author" title="Nokia" href="http://www.nokia.com/" />
<link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius" />
<link rel="match" href="border-radius-004-ref.xht" />
- <meta name="flags" content="" />
<meta name="assert" content="To verify border-radius property set with value using slash, works as expected" />
- <style type="text/css">
- /* <![CDATA[ */
- div
- {
- border:2px solid #a1a1a1;
- background:#dddddd;
- width:200px;
- height: 100px;
- border-radius: 50px / 25px;
- }
- #reference
- {
- border-top-left-radius: 50px 25px;
- border-top-right-radius: 50px 25px;
- border-bottom-right-radius: 50px 25px;
- border-bottom-left-radius: 50px 25px;
- }
- /* ]]> */
+ <style>
+ div {
+ border: 2px solid #a1a1a1;
+ background: #dddddd;
+ width: 200px;
+ height: 100px;
+ border-radius: 50px / 25px;
+ }
+ #reference {
+ border-top-left-radius: 50px 25px;
+ border-top-right-radius: 50px 25px;
+ border-bottom-right-radius: 50px 25px;
+ border-bottom-left-radius: 50px 25px;
+ }
</style>
-<!--
- <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
</head>
<body>
- <p>
- There should be two identical boxes, each with 4 rounded corners.
- </p>
+ <p>There should be two identical boxes, each with 4 rounded corners.</p>
<ul>
<li>PASS if the two boxes below are the same and all 4 corners are rounded.</li>
<li>FAIL if the output is not as expected.</li>
</ul>
<!-- PLACE TEST CONTENT FROM HERE -->
- <div id="test"></div>
- <p><br/></p>
- <div id="reference"></div>
-<!--
- <script type="text/javascript">
- /* <![CDATA[ */
- var borders = new Array("border-top-left-radius", "border-top-right-radius",
- "border-bottom-right-radius", "border-bottom-left-radius");
- var expectedValues = new Array("50px 25px", "50px 25px", "50px 25px", "50px 25px");
-
- var testResult = check_Multiple_CSS_property(borders, expectedValues);
-
- /* if (testResult.pass)
- // This portion of the code has been removed to ensure that the test case is not automated
- else {
- // This portion of the code has been removed to ensure that the test case is not automated
- } */
-
- if (top.FrameEnabled) top.fnLog(testResult);
- /* ]]> */
- </script>
--->
+ <div id="test"></div>
+ <p><br/></p>
+ <div id="reference"></div>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-005-ref.xht b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-005-ref.xht
index 378b40ec20b..57605a76f5f 100644
--- a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-005-ref.xht
+++ b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-005-ref.xht
@@ -3,34 +3,29 @@
<head>
<title>CSS Test: Border radius reference</title>
<link rel="author" title="Nokia" href="http://www.nokia.com/" />
- <style type="text/css">
- /* <![CDATA[ */
- div
- {
- border:2px solid #a1a1a1;
- background:#dddddd;
- width:200px;
- height: 100px;
- border-top-left-radius: 50px 20px;
- border-top-right-radius: 15px 25px;
- border-bottom-right-radius: 40px 20px;
- border-bottom-left-radius: 15px 25px;
- }
- /* ]]> */
+ <style>
+ div {
+ border: 2px solid #a1a1a1;
+ background: #dddddd;
+ width: 200px;
+ height: 100px;
+ border-top-left-radius: 50px 20px;
+ border-top-right-radius: 15px 25px;
+ border-bottom-right-radius: 40px 20px;
+ border-bottom-left-radius: 15px 25px;
+ }
</style>
</head>
<body>
- <p>
- There should be two identical boxes, each with 4 rounded corners.
- </p>
+ <p>There should be two identical boxes, each with 4 rounded corners.</p>
<ul>
<li>PASS if the two boxes below are the same and all 4 corners are rounded.</li>
<li>FAIL if the output is not as expected.</li>
</ul>
- <div id="test"></div>
- <p><br/></p>
- <div id="reference"></div>
+ <div id="test"></div>
+ <p><br/></p>
+ <div id="reference"></div>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-005.xht b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-005.xht
index 839d48f91e1..7be93af636d 100644
--- a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-005.xht
+++ b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-005.xht
@@ -3,66 +3,36 @@
<head>
<title>CSS Test: Borders. border&ndash;radius using slash: 50px 15px 40px / 20px 25px</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
- <meta http-equiv="Content-Style-Type" content="text/css"/>
- <meta http-equiv="Content-Script-Type" content="text/javascript"/>
<link rel="author" title="Nokia" href="http://www.nokia.com/"/>
<link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius" />
<link rel="match" href="border-radius-005-ref.xht" />
- <meta name="flags" content="" />
<meta name="assert" content="To verify border-radius property set with value using slash, works as expected" />
- <style type="text/css">
- /* <![CDATA[ */
- div
- {
- border:2px solid #a1a1a1;
- background:#dddddd;
- width:200px;
- height: 100px;
- border-radius: 50px 15px 40px / 20px 25px;
- }
- #reference
- {
- border-top-left-radius: 50px 20px;
- border-top-right-radius: 15px 25px;
- border-bottom-right-radius: 40px 20px;
- border-bottom-left-radius: 15px 25px;
- }
- /* ]]> */
+ <style>
+ div {
+ border: 2px solid #a1a1a1;
+ background: #dddddd;
+ width: 200px;
+ height: 100px;
+ border-radius: 50px 15px 40px / 20px 25px;
+ }
+ #reference {
+ border-top-left-radius: 50px 20px;
+ border-top-right-radius: 15px 25px;
+ border-bottom-right-radius: 40px 20px;
+ border-bottom-left-radius: 15px 25px;
+ }
</style>
-<!--
- <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
</head>
<body>
- <p>
- There should be two identical boxes, each with 4 rounded corners.
- </p>
+ <p>There should be two identical boxes, each with 4 rounded corners.</p>
<ul>
<li>PASS if the two boxes below are the same and all 4 corners are rounded.</li>
<li>FAIL if the output is not as expected.</li>
</ul>
<!-- PLACE TEST CONTENT FROM HERE -->
- <div id="test"></div>
- <p><br/></p>
- <div id="reference"></div>
-<!--
- <script type="text/javascript">
- /* <![CDATA[ */
- var borders = new Array("border-top-left-radius", "border-top-right-radius",
- "border-bottom-right-radius", "border-bottom-left-radius");
- var expectedValues = new Array("50px 20px", "15px 25px", "40px 20px", "15px 25px");
- var testResult = check_Multiple_CSS_property(borders, expectedValues);
- /* if (testResult.pass)
- // This portion of the code has been removed to ensure that the test case is not automated
- else {
- // This portion of the code has been removed to ensure that the test case is not automated
- } */
-
- if (top.FrameEnabled) top.fnLog(testResult);
- /* ]]> */
- </script>
--->
+ <div id="test"></div>
+ <p><br/></p>
+ <div id="reference"></div>
</body>
</html>
-
diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-006-ref.xht b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-006-ref.xht
index 730a19bf121..93c19491eae 100644
--- a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-006-ref.xht
+++ b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-006-ref.xht
@@ -3,34 +3,28 @@
<head>
<title>CSS Test: Border radius reference</title>
<link rel="author" title="Nokia" href="http://www.nokia.com/" />
- <style type="text/css">
- /* <![CDATA[ */
- div
- {
- border:2px solid #a1a1a1;
- background:#dddddd;
- width:200px;
- height: 100px;
- border-top-left-radius: 50px 20px;
- border-top-right-radius: 15px 25px;
- border-bottom-right-radius: 50px 10%;
- border-bottom-left-radius: 15px 25px;
- }
- /* ]]> */
+ <style>
+ div {
+ border: 2px solid #a1a1a1;
+ background: #dddddd;
+ width: 200px;
+ height: 100px;
+ border-top-left-radius: 50px 20px;
+ border-top-right-radius: 15px 25px;
+ border-bottom-right-radius: 50px 10%;
+ border-bottom-left-radius: 15px 25px;
+ }
</style>
</head>
<body>
- <p>
- There should be two identical boxes, each with 4 rounded corners.
- </p>
+ <p>There should be two identical boxes, each with 4 rounded corners.</p>
<ul>
<li>PASS if the two boxes below are the same and all 4 corners are rounded.</li>
<li>FAIL if the output is not as expected.</li>
</ul>
- <div id="test"></div>
- <p><br/></p>
- <div id="reference"></div>
+ <div id="test"></div>
+ <p><br/></p>
+ <div id="reference"></div>
</body>
</html>
-
diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-006.xht b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-006.xht
index e2426d02bbf..89da74c4827 100644
--- a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-006.xht
+++ b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-006.xht
@@ -3,68 +3,36 @@
<head>
<title>CSS Test: Borders. border&ndash;radius using slash: 50px 15px / 20px 25px 10%</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
- <meta http-equiv="Content-Style-Type" content="text/css"/>
- <meta http-equiv="Content-Script-Type" content="text/javascript"/>
<link rel="author" title="Nokia" href="http://www.nokia.com/"/>
<link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius" />
<link rel="match" href="border-radius-006-ref.xht" />
- <meta name="flags" content="" />
<meta name="assert" content="To verify border-radius property set with values using slash, works as expected" />
- <style type="text/css">
- /* <![CDATA[ */
- div
- {
- border:2px solid #a1a1a1;
- background:#dddddd;
- width:200px;
- height: 100px;
- border-radius: 50px 15px / 20px 25px 10%;
- }
- #reference
- {
- border-top-left-radius: 50px 20px;
- border-top-right-radius: 15px 25px;
- border-bottom-right-radius: 50px 10%;
- border-bottom-left-radius: 15px 25px;
- }
- /* ]]> */
+ <style>
+ div {
+ border: 2px solid #a1a1a1;
+ background: #dddddd;
+ width: 200px;
+ height: 100px;
+ border-radius: 50px 15px / 20px 25px 10%;
+ }
+ #reference {
+ border-top-left-radius: 50px 20px;
+ border-top-right-radius: 15px 25px;
+ border-bottom-right-radius: 50px 10%;
+ border-bottom-left-radius: 15px 25px;
+ }
</style>
-<!--
- <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
</head>
<body>
- <p>
- There should be two identical boxes, each with 4 rounded corners.
- </p>
+ <p>There should be two identical boxes, each with 4 rounded corners.</p>
<ul>
<li>PASS if the two boxes below are the same and all 4 corners are rounded.</li>
<li>FAIL if the output is not as expected.</li>
</ul>
<!-- PLACE TEST CONTENT FROM HERE -->
- <div id="test"></div>
- <p><br/></p>
- <div id="reference"></div>
-<!--
- <script type="text/javascript">
- /* <![CDATA[ */
- var borders = new Array("border-top-left-radius", "border-top-right-radius",
- "border-bottom-right-radius", "border-bottom-left-radius");
- var expectedValues = new Array("50px 20px", "15px 25px", "50px 10%", "15px 25px");
-
- var testResult = check_Multiple_CSS_property(borders, expectedValues);
-
- /* if (testResult.pass)
- // This portion of the code has been removed to ensure that the test case is not automated
- else {
- // This portion of the code has been removed to ensure that the test case is not automated
- } */
-
- if (top.FrameEnabled) top.fnLog(testResult);
- /* ]]> */
- </script>
--->
+ <div id="test"></div>
+ <p><br/></p>
+ <div id="reference"></div>
</body>
</html>
-
diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-007-ref.xht b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-007-ref.xht
index 3d3ab1bfc65..c10c0ee848c 100644
--- a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-007-ref.xht
+++ b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-007-ref.xht
@@ -3,34 +3,28 @@
<head>
<title>CSS Test: Border radius reference</title>
<link rel="author" title="Nokia" href="http://www.nokia.com/" />
- <style type="text/css">
- /* <![CDATA[ */
- div
- {
- border:2px solid #a1a1a1;
- background:#dddddd;
- width:200px;
- height: 100px;
- border-top-left-radius: 50px 0.5in;
- border-top-right-radius: 10mm 25px;
- border-bottom-right-radius: 6pc 30%;
- border-bottom-left-radius: 15% 70pt;
- }
- /* ]]> */
+ <style>
+ div {
+ border: 2px solid #a1a1a1;
+ background: #dddddd;
+ width: 200px;
+ height: 100px;
+ border-top-left-radius: 50px 0.5in;
+ border-top-right-radius: 10mm 25px;
+ border-bottom-right-radius: 6pc 30%;
+ border-bottom-left-radius: 15% 70pt;
+ }
</style>
</head>
<body>
- <p>
- There should be two identical boxes, each with 4 rounded corners.
- </p>
+ <p>There should be two identical boxes, each with 4 rounded corners.</p>
<ul>
<li>PASS if the two boxes below are the same and all 4 corners are rounded.</li>
<li>FAIL if the output is not as expected.</li>
</ul>
- <div id="test"></div>
- <p><br/></p>
- <div id="reference"></div>
+ <div id="test"></div>
+ <p><br/></p>
+ <div id="reference"></div>
</body>
</html>
-
diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-007.xht b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-007.xht
index ab0bdf2ee9a..df442e00852 100644
--- a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-007.xht
+++ b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-007.xht
@@ -3,68 +3,36 @@
<head>
<title>CSS Test: Borders. border&ndash;radius using slash: 50px 10mm 3pc 15% / 0.5in 25px 10% 70pt</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
- <meta http-equiv="Content-Style-Type" content="text/css"/>
- <meta http-equiv="Content-Script-Type" content="text/javascript"/>
<link rel="author" title="Nokia" href="http://www.nokia.com/"/>
<link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius" />
<link rel="match" href="border-radius-007-ref.xht" />
- <meta name="flags" content="" />
<meta name="assert" content="To verify border-radius property set with values (in different units) using slash, works as expected" />
- <style type="text/css">
- /* <![CDATA[ */
- div
- {
- border:2px solid #a1a1a1;
- background:#dddddd;
- width:200px;
- height: 100px;
- border-radius: 50px 10mm 6pc 15% / 0.5in 25px 30% 70pt;
- }
- #reference
- {
- border-top-left-radius: 50px 0.5in;
- border-top-right-radius: 10mm 25px;
- border-bottom-right-radius: 6pc 30%;
- border-bottom-left-radius: 15% 70pt;
- }
- /* ]]> */
+ <style>
+ div {
+ border: 2px solid #a1a1a1;
+ background: #dddddd;
+ width: 200px;
+ height: 100px;
+ border-radius: 50px 10mm 6pc 15% / 0.5in 25px 30% 70pt;
+ }
+ #reference {
+ border-top-left-radius: 50px 0.5in;
+ border-top-right-radius: 10mm 25px;
+ border-bottom-right-radius: 6pc 30%;
+ border-bottom-left-radius: 15% 70pt;
+ }
</style>
-<!--
- <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
</head>
<body>
- <p>
- There should be two identical boxes, each with 4 rounded corners.
- </p>
+ <p>There should be two identical boxes, each with 4 rounded corners.</p>
<ul>
<li>PASS if the two boxes below are the same and all 4 corners are rounded.</li>
<li>FAIL if the output is not as expected.</li>
</ul>
<!-- PLACE TEST CONTENT FROM HERE -->
- <div id="test"></div>
- <p><br/></p>
- <div id="reference"></div>
-<!--
- <script type="text/javascript">
- /* <![CDATA[ */
- var borders = new Array("border-top-left-radius", "border-top-right-radius",
- "border-bottom-right-radius", "border-bottom-left-radius");
- var expectedValues = new Array("50px 48px", "37px 25px", "96px 30%", "15% 93px");
-
- var testResult = check_Multiple_CSS_property(borders, expectedValues);
-
- /* if (testResult.pass)
- // This portion of the code has been removed to ensure that the test case is not automated
- else {
- // This portion of the code has been removed to ensure that the test case is not automated
- } */
-
- if (top.FrameEnabled) top.fnLog(testResult);
- /* ]]> */
- </script>
--->
+ <div id="test"></div>
+ <p><br/></p>
+ <div id="reference"></div>
</body>
</html>
-
diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-008.xht b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-008.xht
index 8c5a7a961e1..a4b1408dd30 100644
--- a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-008.xht
+++ b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-008.xht
@@ -3,65 +3,33 @@
<head>
<title>CSS Test: Borders. border&ndash;radius using slash: 50px 15px 40px 30em 25em / 20px 25px</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
- <meta http-equiv="Content-Style-Type" content="text/css"/>
- <meta http-equiv="Content-Script-Type" content="text/javascript"/>
<link rel="author" title="Nokia" href="http://www.nokia.com/"/>
<link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius" />
<link rel="match" href="border-radius-001-ref.xht" />
- <meta name="flags" content="" />
<meta name="assert" content="To verify border-radius property set with excess values, works as expected" />
- <style type="text/css">
- /* <![CDATA[ */
- div
- {
- border:2px solid #a1a1a1;
- background:#dddddd;
- width:200px;
- height: 100px;
+ <style>
+ div {
+ border: 2px solid #a1a1a1;
+ background: #dddddd;
+ width: 200px;
+ height: 100px;
+ }
+ #test {
+ border-radius: 50px 15px 40px 30em 25em / 20px 25px;
}
- #test
- {
- border-radius: 50px 15px 40px 30em 25em / 20px 25px;
- }
- /* ]]> */
</style>
-<!--
- <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
</head>
<body>
- <p>
- There should be two boxes with no rounded corners.
- </p>
- <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
- <ul>
- <li>PASS if the two boxes below are the same.</li>
- <li>FAIL if the output is not as expected.</li>
- </ul>
+ <p>There should be two boxes with no rounded corners.</p>
+ <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
+ <ul>
+ <li>PASS if the two boxes below are the same.</li>
+ <li>FAIL if the output is not as expected.</li>
+ </ul>
<!-- PLACE TEST CONTENT FROM HERE -->
- <div id="test"></div>
- <p><br/></p>
- <div id="reference"></div>
-<!--
- <script type="text/javascript">
- /* <![CDATA[ */
- var borders = new Array("border-top-left-radius", "border-top-right-radius",
- "border-bottom-right-radius", "border-bottom-left-radius");
- var expectedValues = new Array("0px", "0px", "0px", "0px");
-
- var testResult = check_Multiple_CSS_property(borders, expectedValues);
-
- /* if (testResult.pass)
- // This portion of the code has been removed to ensure that the test case is not automated
- else {
- // This portion of the code has been removed to ensure that the test case is not automated
- } */
-
- if (top.FrameEnabled) top.fnLog(testResult);
- /* ]]> */
- </script>
--->
+ <div id="test"></div>
+ <p><br/></p>
+ <div id="reference"></div>
</body>
</html>
-
diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-009-ref.xht b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-009-ref.xht
index 99064998e9c..c86e22d3871 100644
--- a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-009-ref.xht
+++ b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-009-ref.xht
@@ -3,34 +3,29 @@
<head>
<title>CSS Test: Border radius reference</title>
<link rel="author" title="Nokia" href="http://www.nokia.com/" />
- <style type="text/css">
- /* <![CDATA[ */
- div
- {
- border:2px solid #a1a1a1;
- background:#dddddd;
- width:200px;
- height: 100px;
- border-top-left-radius: 20%;
- border-top-right-radius: 25px;
- border-bottom-right-radius: 20%;
- border-bottom-left-radius: 25px;
- }
- /* ]]> */
+ <style>
+ div {
+ border: 2px solid #a1a1a1;
+ background: #dddddd;
+ width: 200px;
+ height: 100px;
+ border-top-left-radius: 20%;
+ border-top-right-radius: 25px;
+ border-bottom-right-radius: 20%;
+ border-bottom-left-radius: 25px;
+ }
</style>
</head>
<body>
- <p>
- There should be two identical boxes, each with 4 rounded corners.
- </p>
+ <p>There should be two identical boxes, each with 4 rounded corners.</p>
<ul>
<li>PASS if the two boxes below are the same and all 4 corners are rounded.</li>
<li>FAIL if the output is not as expected.</li>
</ul>
- <div id="test"></div>
- <p><br/></p>
- <div id="reference"></div>
+ <div id="test"></div>
+ <p><br/></p>
+ <div id="reference"></div>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-009.xht b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-009.xht
index 70169c31854..822f1668596 100644
--- a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-009.xht
+++ b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-009.xht
@@ -3,70 +3,39 @@
<head>
<title>CSS Test: Borders. border&ndash;radius using &quot;inherit&quot;</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
- <meta http-equiv="Content-Style-Type" content="text/css"/>
- <meta http-equiv="Content-Script-Type" content="text/javascript"/>
<link rel="author" title="Nokia" href="http://www.nokia.com/"/>
<link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius" />
<link rel="match" href="border-radius-009-ref.xht" />
- <meta name="flags" content="" />
<meta name="assert" content="To verify inherit feature works, when it is assigned to border-radius" />
- <style type="text/css">
- /* <![CDATA[ */
- body
- {
- border-radius: 20% 25px;
- }
- div
- {
- border:2px solid #a1a1a1;
- background:#dddddd;
- width:200px;
- height: 100px;
- border-radius: inherit;
- }
- #reference
- {
- border-top-left-radius: 20%;
- border-top-right-radius: 25px;
- border-bottom-right-radius: 20%;
- border-bottom-left-radius: 25px;
- }
- /* ]]> */
+ <style>
+ body {
+ border-radius: 20% 25px;
+ }
+ div {
+ border: 2px solid #a1a1a1;
+ background: #dddddd;
+ width: 200px;
+ height: 100px;
+ border-radius: inherit;
+ }
+ #reference {
+ border-top-left-radius: 20%;
+ border-top-right-radius: 25px;
+ border-bottom-right-radius: 20%;
+ border-bottom-left-radius: 25px;
+ }
</style>
-<!--
- <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
</head>
<body>
- <p>
- There should be two identical boxes, each with 4 rounded corners.
- </p>
+ <p>There should be two identical boxes, each with 4 rounded corners.</p>
<ul>
<li>PASS if the two boxes below are the same and all 4 corners are rounded.</li>
<li>FAIL if the output is not as expected.</li>
</ul>
<!-- PLACE TEST CONTENT FROM HERE -->
- <div id="test"></div>
- <p><br/></p>
- <div id="reference"></div>
-<!--
- <script type="text/javascript">
- /* <![CDATA[ */
- var borders = new Array("border-top-left-radius", "border-top-right-radius",
- "border-bottom-right-radius", "border-bottom-left-radius");
- var expectedValues = new Array("20%", "25px", "20%", "25px");
- var testResult = check_Multiple_CSS_property(borders, expectedValues);
- /* if (testResult.pass)
- // This portion of the code has been removed to ensure that the test case is not automated
- else {
- // This portion of the code has been removed to ensure that the test case is not automated
- } */
-
- if (top.FrameEnabled) top.fnLog(testResult);
- /* ]]> */
- </script>
--->
+ <div id="test"></div>
+ <p><br/></p>
+ <div id="reference"></div>
</body>
</html>
-
diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-010-ref.xht b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-010-ref.xht
index 7cb553e7edd..882032bfbc7 100644
--- a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-010-ref.xht
+++ b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-010-ref.xht
@@ -3,34 +3,29 @@
<head>
<title>CSS Test: Border radius reference</title>
<link rel="author" title="Nokia" href="http://www.nokia.com/" />
- <style type="text/css">
- /* <![CDATA[ */
- div
- {
- border:2px solid #a1a1a1;
- background:#dddddd;
- width:200px;
- height: 100px;
- border-top-left-radius: 20% 25px;
- border-top-right-radius: 0;
- border-bottom-right-radius: 20pt 3em;
- border-bottom-left-radius: 0;
- }
- /* ]]> */
+ <style>
+ div {
+ border: 2px solid #a1a1a1;
+ background: #dddddd;
+ width: 200px;
+ height: 100px;
+ border-top-left-radius: 20% 25px;
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 20pt 3em;
+ border-bottom-left-radius: 0;
+ }
</style>
</head>
<body>
- <p>
- There should be two identical boxes, each with rounded corners at the top left and bottom right only.
- </p>
+ <p>There should be two identical boxes, each with rounded corners at the top left and bottom right only.</p>
<ul>
<li>PASS if the two boxes below are the same and only top left and bottom right corners are rounded.</li>
<li>FAIL if the output is not as expected.</li>
</ul>
- <div id="test"></div>
- <p><br/></p>
- <div id="reference"></div>
+ <div id="test"></div>
+ <p><br/></p>
+ <div id="reference"></div>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-010.xht b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-010.xht
index 99791d10a52..32d464673a7 100644
--- a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-010.xht
+++ b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-010.xht
@@ -3,73 +3,40 @@
<head>
<title>CSS Test: Borders. border&ndash;radius using &quot;inherit&quot;</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
- <meta http-equiv="Content-Style-Type" content="text/css"/>
- <meta http-equiv="Content-Script-Type" content="text/javascript"/>
<link rel="author" title="Nokia" href="http://www.nokia.com/"/>
<link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius" />
<link rel="match" href="border-radius-010-ref.xht" />
- <meta name="flags" content="" />
<meta name="assert" content="To verify inherit feature works, when it is assigned to border-radius" />
- <style type="text/css">
- /* <![CDATA[ */
- body
- {
- border-top-left-radius: 20% 25px;
- border-bottom-right-radius: 20pt 3em;
- }
- div
- {
- border:2px solid #a1a1a1;
- background:#dddddd;
- width:200px;
- height: 100px;
- border-radius: inherit;
- }
- #reference
- {
- border-top-left-radius: 20% 25px;
- border-top-right-radius: 0;
- border-bottom-right-radius: 20pt 3em;
- border-bottom-left-radius: 0;
- }
- /* ]]> */
+ <style>
+ body {
+ border-top-left-radius: 20% 25px;
+ border-bottom-right-radius: 20pt 3em;
+ }
+ div {
+ border: 2px solid #a1a1a1;
+ background: #dddddd;
+ width: 200px;
+ height: 100px;
+ border-radius: inherit;
+ }
+ #reference {
+ border-top-left-radius: 20% 25px;
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 20pt 3em;
+ border-bottom-left-radius: 0;
+ }
</style>
-<!--
- <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
</head>
<body>
- <p>
- There should be two identical boxes, each with rounded corners at the top left and bottom right only.
- </p>
+ <p>There should be two identical boxes, each with rounded corners at the top left and bottom right only.</p>
<ul>
<li>PASS if the two boxes below are the same and only top left and bottom right corners are rounded.</li>
<li>FAIL if the output is not as expected.</li>
</ul>
<!-- PLACE TEST CONTENT FROM HERE -->
- <div id="test"></div>
- <p><br/></p>
- <div id="reference"></div>
-<!--
- <script type="text/javascript">
- /* <![CDATA[ */
- var borders = new Array("border-top-left-radius", "border-top-right-radius",
- "border-bottom-right-radius", "border-bottom-left-radius");
- var expectedValues = new Array("20% 25px", "0px", "26px 48px", "0px");
-
- var testResult = check_Multiple_CSS_property(borders, expectedValues);
-
- /* if (testResult.pass)
- // This portion of the code has been removed to ensure that the test case is not automated
- else {
- // This portion of the code has been removed to ensure that the test case is not automated
- } */
-
- if (top.FrameEnabled) top.fnLog(testResult);
- /* ]]> */
- </script>
--->
+ <div id="test"></div>
+ <p><br/></p>
+ <div id="reference"></div>
</body>
</html>
-
diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-011-ref.xht b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-011-ref.xht
index 32120f12ea7..cdeaf1c8e81 100644
--- a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-011-ref.xht
+++ b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-011-ref.xht
@@ -3,29 +3,22 @@
<head>
<title>CSS Test: Border radius reference</title>
<link rel="author" title="Nokia" href="http://www.nokia.com/" />
- <style type="text/css">
- /* <![CDATA[ */
- div
- {
- border:2px solid #a1a1a1;
- background:#dddddd;
- width:200px;
- height: 100px;
- }
- /* ]]> */
+ <style>
+ div {
+ position: absolute;
+ top: 150px;
+ width: 200px;
+ height: 100px;
+ }
</style>
</head>
<body>
- <p>
- There should be two boxes, each with corners that have no rounding.
- </p>
- <ul>
- <li>PASS if the two boxes below are the same, each with sharp corner joins (no rounding).</li>
- <li>FAIL if corner joins have any rounding.</li>
- </ul>
+ <p>A white rectangle with no border-radius property sits exactly on top of an exact same size red rectangle with border-radius set to zero.</p>
+ <ul>
+ <li>PASS if no red is visible on the page.</li>
+ <li>FAIL if any red is visible.</li>
+ </ul>
- <div></div>
- <p><br/></p>
- <div></div>
+ <div></div>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-011.xht b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-011.xht
index 6a5ceab204e..8439302d6bd 100644
--- a/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-backgrounds/border-radius-011.xht
@@ -5,44 +5,36 @@
<link rel="author" title="Nokia" href="http://www.nokia.com/" />
<link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius" />
<link rel="match" href="border-radius-011-ref.xht" />
- <meta name="flags" content="" />
<meta name="assert" content="If border-radius is zero, all corners are square." />
- <style type="text/css"><![CDATA[
- div
- {
- width:200px;
- height: 100px;
+ <style>
+ div {
+ width: 200px;
+ height: 100px;
}
- #reference
- {
- background: red;
- position: absolute;
- top: 100px;
- left: 30px;
+ #reference {
+ background: red;
+ position: absolute;
+ top: 150px;
+ left: 30px;
+ }
+ #test {
+ position: absolute;
+ border-radius: 0;
+ background: white;
+ top: 150px;
+ left: 30px;
}
- #test
- {
- position: absolute;
- border-radius: 0;
- background: white;
- top: 100px;
- left: 30px;
- }
-
- ]]>
</style>
</head>
<body>
- <p>
- A white rectangle with no border-radius property sits exactly on top of an exact same size red rectangle with border-radius set to zero.
- </p>
- <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
- <ul>
- <li>PASS if no red is visible on the page.</li>
- <li>FAIL if any red is visible.</li>
- </ul>
+ <p>A white rectangle with no border-radius property sits exactly on top of an exact same size red rectangle with border-radius set to zero.</p>
+ <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
+ <ul>
+ <li>PASS if no red is visible on the page.</li>
+ <li>FAIL if any red is visible.</li>
+ </ul>
<!-- PLACE TEST CONTENT FROM HERE -->
- <div id="reference"></div>
- <div id="test"></div>
+ <div id="reference"></div>
+ <div id="test"></div>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/counter-increment-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-block/counter-increment-applies-to-011.xht
deleted file mode 100644
index 9c491951568..00000000000
--- a/tests/wpt/web-platform-tests/css/css-block/counter-increment-applies-to-011.xht
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>CSS Test: Counter-increment applied to elements with 'display' set to 'run-in'</title>
- <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-counter-increment" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#counters" />
- <link rel="match" href="../reference/pass_if_number_5.xht"/>
- <meta name="flags" content="" />
- <meta name="assert" content="The 'counter-increment' property applies to elements with a 'display' set to 'run-in'." />
- <style type="text/css">
- div
- {
- counter-increment: test 5;
- display: run-in;
- }
- div:before
- {
- content: counter(test);
- }
- </style>
- </head>
- <body>
- <p>Test passes if there is a number '5' below.</p>
- <div></div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/counter-reset-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-block/counter-reset-applies-to-011.xht
deleted file mode 100644
index 0ea421547cb..00000000000
--- a/tests/wpt/web-platform-tests/css/css-block/counter-reset-applies-to-011.xht
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>CSS Test: Counter-reset applied to elements with 'display' set to 'run-in'</title>
- <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-counter-reset" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#counters" />
- <link rel="match" href="../reference/pass_if_number_5.xht"/>
- <meta name="flags" content="" />
- <meta name="assert" content="The 'counter-reset' property applies to elements with a 'display' set to 'run-in'." />
- <style type="text/css">
- div
- {
- counter-reset: test 5;
- display: run-in;
- }
- div:before
- {
- content: counter(test);
- }
- </style>
- </head>
- <body>
- <p>Test passes if there is a number '5' below.</p>
- <div></div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/font-style-applies-to-004.xht b/tests/wpt/web-platform-tests/css/css-block/font-style-applies-to-004.xht
deleted file mode 100644
index e1a50b7e4dc..00000000000
--- a/tests/wpt/web-platform-tests/css/css-block/font-style-applies-to-004.xht
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>CSS Test: Font-style and 'display: run-in' elements</title>
- <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/fonts.html#propdef-font-style" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/fonts.html#font-styling" />
- <link rel="help" href="http://www.w3.org/TR/css-fonts-3/#font-style-prop"/>
- <link rel="match" href="../reference/pass_if_filler_text_slanted.xht"/>
- <meta name="flags" content="" />
- <meta name="assert" content="The 'font-style' property applies to 'display: run-in' elements." />
- <style type="text/css">
- div
- {
- display: run-in;
- font-style: italic;
- }
- </style>
- </head>
- <body>
- <p>Test passes if the "Filler Text" below is slanted to one side.</p>
- <div>Filler Text</div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/font-variant-applies-to-004.xht b/tests/wpt/web-platform-tests/css/css-block/font-variant-applies-to-004.xht
deleted file mode 100644
index adcc7fe57ae..00000000000
--- a/tests/wpt/web-platform-tests/css/css-block/font-variant-applies-to-004.xht
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>CSS Test: Font-variant and 'display: run-in' elements</title>
- <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/fonts.html#propdef-font-variant" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/fonts.html#small-caps" />
- <link rel="help" href="http://www.w3.org/TR/css-fonts-3/#font-variant-prop" />
- <link rel="match" href="../reference/pass_if_filler_text_match_smallcaps.xht"/>
- <meta name="flags" content="" />
- <meta name="assert" content="The 'font-variant' property applies to 'display: run-in' elements." />
- <style type="text/css">
- div
- {
- font-variant: small-caps;
- }
- #div1
- {
- display: run-in;
- }
- </style>
- </head>
- <body>
- <p>Test passes if the lines of "Filler Text" below match.</p>
- <div>Filler Text</div>
- <div id="div1">Filler Text</div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/font-weight-applies-to-004.xht b/tests/wpt/web-platform-tests/css/css-block/font-weight-applies-to-004.xht
deleted file mode 100644
index 57ac352bb06..00000000000
--- a/tests/wpt/web-platform-tests/css/css-block/font-weight-applies-to-004.xht
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>CSS Test: Font-weight and 'display: run-in' elements</title>
- <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/fonts.html#propdef-font-weight" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/fonts.html#font-boldness" />
- <link rel="help" href="http://www.w3.org/TR/css-fonts-3/#font-weight-prop" />
- <link rel="match" href="../reference/pass_if_filler_text_match_bold.xht"/>
- <meta name="flags" content="" />
- <meta name="assert" content="Font weights apply to 'display: run-in' elements." />
- <style type="text/css">
- div
- {
- font-weight: bold;
- }
- #div1
- {
- display: run-in;
- }
- </style>
- </head>
- <body>
- <p>Test passes if the lines of "Filler Text" below match.</p>
- <div>Filler Text</div>
- <div id="div1">Filler Text</div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/height-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-block/height-applies-to-011.xht
deleted file mode 100644
index ed22bf62c14..00000000000
--- a/tests/wpt/web-platform-tests/css/css-block/height-applies-to-011.xht
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>CSS Test: Height applied to elements with 'display' set to 'run-in'</title>
- <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#propdef-height" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#the-height-property" />
- <link rel="match" href="../reference/pass_if_square_96px_black.html"/>
- <meta name="flags" content="" />
- <meta name="assert" content="The 'height' property applies to elements with 'display' set to 'run-in'." />
- <style type="text/css">
- div
- {
- background: black;
- display: run-in;
- height: 1in;
- width: 1in;
- }
- </style>
- </head>
- <body>
- <p>Test passes if there is a square below.</p>
- <div></div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/letter-spacing-applies-to-004.xht b/tests/wpt/web-platform-tests/css/css-block/letter-spacing-applies-to-004.xht
deleted file mode 100644
index 2c7ec5340f3..00000000000
--- a/tests/wpt/web-platform-tests/css/css-block/letter-spacing-applies-to-004.xht
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>CSS Test: Letter-spacing application on a 'display: run-in' element</title>
- <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/text.html#propdef-letter-spacing" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/text.html#spacing-props" />
- <link rel="match" href="../reference/black_box_ends_when_blue_box_ends_6_boxes_ahem.html"/>
- <meta name="flags" content="ahem" />
- <meta name="assert" content="The 'letter-spacing' property is applied to 'display: run-in' elements." />
- <style type="text/css">
- div
- {
- font: 16px/1em Ahem;
- }
- div div
- {
- display: run-in;
- letter-spacing: 1em;
- }
- #div1
- {
- background: blue;
- height: 1em;
- width: 11em;
- }
- </style>
- </head>
- <body>
- <p>Test passes if there are six black boxes below and the last black box ends when the blue box ends.</p>
- <div>
- <div>XXXXXX</div>
- </div>
- <div id="div1"></div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/list-style-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-block/list-style-applies-to-011.xht
deleted file mode 100644
index 6aa429cc9a1..00000000000
--- a/tests/wpt/web-platform-tests/css/css-block/list-style-applies-to-011.xht
+++ /dev/null
@@ -1,30 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>CSS Test: List-style applied to elements with 'display' set to 'run-in'</title>
- <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-list-style" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#list-style" />
- <link rel="match" href="../reference/single_square_list_marker.xht"/>
- <meta name="flags" content="" />
- <meta name="assert" content="The 'list-style' property applies to elements with 'display' set to 'run-in'." />
- <style type="text/css">
- div
- {
- display: run-in;
- list-style: square;
- margin-left: 1in;
- }
- span
- {
- display: list-item;
- }
- </style>
- </head>
- <body>
- <p>Test passes if there is a single square below.</p>
- <div>
- <span></span>
- </div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/list-style-type-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-block/list-style-type-applies-to-011.xht
deleted file mode 100644
index 642b73982f4..00000000000
--- a/tests/wpt/web-platform-tests/css/css-block/list-style-type-applies-to-011.xht
+++ /dev/null
@@ -1,30 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>CSS Test: List-style-type applied to elements with 'display' set to 'run-in'</title>
- <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-list-style-type" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#list-style" />
- <link rel="match" href="../reference/single_square_list_marker.xht"/>
- <meta name="flags" content="" />
- <meta name="assert" content="The 'list-style-type' property applies to elements with 'display' set to 'run-in'." />
- <style type="text/css">
- div
- {
- display: run-in;
- list-style-type: square;
- margin-left: 1in;
- }
- span
- {
- display: list-item;
- }
- </style>
- </head>
- <body>
- <p>Test passes if there is a single square below.</p>
- <div>
- <span></span>
- </div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/max-height-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-block/max-height-applies-to-011.xht
deleted file mode 100644
index 80bb7ca7fdf..00000000000
--- a/tests/wpt/web-platform-tests/css/css-block/max-height-applies-to-011.xht
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>CSS Test: Max-height applied to elements with 'display' set to 'run-in'</title>
- <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#propdef-max-height" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#min-max-heights" />
- <link rel="match" href="../reference/pass_if_square_96px_black.html"/>
- <meta name="flags" content="" />
- <meta name="assert" content="The 'max-height' property applies to elements with 'display' set to 'run-in'." />
- <style type="text/css">
- div
- {
- background: black;
- display: run-in;
- height: 3in;
- max-height: 1in;
- width: 1in;
- }
- </style>
- </head>
- <body>
- <p>Test passes if there is a square below.</p>
- <div></div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/max-width-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-block/max-width-applies-to-011.xht
deleted file mode 100644
index 926ae993403..00000000000
--- a/tests/wpt/web-platform-tests/css/css-block/max-width-applies-to-011.xht
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>CSS Test: Max-width applied to elements with 'display' set to 'run-in'</title>
- <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#propdef-max-width" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#min-max-widths" />
- <link rel="match" href="../reference/pass_if_square_96px_black.html"/>
- <meta name="flags" content="" />
- <meta name="assert" content="The 'max-width' property applies to elements with 'display' set to 'run-in'." />
- <style type="text/css">
- div
- {
- background: black;
- display: run-in;
- height: 1in;
- max-width: 1in;
- width: 3in;
- }
- </style>
- </head>
- <body>
- <p>Test passes if there is a square below.</p>
- <div></div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/min-height-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-block/min-height-applies-to-011.xht
deleted file mode 100644
index 42fba493a8c..00000000000
--- a/tests/wpt/web-platform-tests/css/css-block/min-height-applies-to-011.xht
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>CSS Test: Min-height applied to elements with 'display' set to 'run-in'</title>
- <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#propdef-min-height" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#min-max-heights" />
- <link rel="match" href="../reference/pass_if_square_96px_black.html"/>
- <meta name="flags" content="" />
- <meta name="assert" content="The 'min-height' property applies to elements with 'display' set to 'run-in'." />
- <style type="text/css">
- div
- {
- background: black;
- display: run-in;
- min-height: 1in;
- width: 1in;
- }
- </style>
- </head>
- <body>
- <p>Test passes if there is a square below.</p>
- <div></div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/min-width-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-block/min-width-applies-to-011.xht
deleted file mode 100644
index 18679a9c1d8..00000000000
--- a/tests/wpt/web-platform-tests/css/css-block/min-width-applies-to-011.xht
+++ /dev/null
@@ -1,31 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>CSS Test: Min-width applied to elements with 'display' set to 'run-in'</title>
- <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#propdef-min-width" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#min-max-widths" />
- <link rel="match" href="../reference/pass_if_square_96px_black.html"/>
- <meta name="flags" content="" />
- <meta name="assert" content="The 'min-width' property applies to elements with 'display' set to 'run-in'." />
- <style type="text/css">
- #div1
- {
- width: 0.5in;
- }
- div div
- {
- background: black;
- display: run-in;
- height: 1in;
- min-width: 1in;
- }
- </style>
- </head>
- <body>
- <p>Test passes if there is a square below.</p>
- <div id="div1">
- <div></div>
- </div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/quotes-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-block/quotes-applies-to-011.xht
deleted file mode 100644
index 6bf2faa1058..00000000000
--- a/tests/wpt/web-platform-tests/css/css-block/quotes-applies-to-011.xht
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>CSS Test: Quotes applied to elements with 'display' set to 'run-in'</title>
- <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-quotes" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#quotes-specify" />
- <link rel="match" href="../reference/pass_if_pass_below.html" />
- <meta name="flags" content="" />
- <meta name="assert" content="The 'quotes' property applies to elements with a 'display' set to 'run-in'." />
- <style type="text/css">
- div
- {
- display: run-in;
- quotes: "P" "S" "A" "S";
- }
- div:before
- {
- content: open-quote open-quote close-quote close-quote;
- }
- </style>
- </head>
- <body>
- <p>Test passes if there is the word "PASS" below.</p>
- <div></div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/text-decoration-applies-to-004.xht b/tests/wpt/web-platform-tests/css/css-block/text-decoration-applies-to-004.xht
deleted file mode 100644
index f06276032e6..00000000000
--- a/tests/wpt/web-platform-tests/css/css-block/text-decoration-applies-to-004.xht
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>CSS Test: Text-decoration application on a 'run-in' element</title>
- <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/text.html#propdef-text-decoration" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/text.html#lining-striking-props" />
- <link rel="match" href="../reference/pass_if_filler_text_underlined.html"/>
- <meta name="flags" content="" />
- <meta name="assert" content="The 'text-decoration' property applies to a 'run-in' element." />
- <style type="text/css">
- div
- {
- display: run-in;
- text-decoration: underline;
- }
- </style>
- </head>
- <body>
- <p>Test passes if the "Filler Text" below has a line under it.</p>
- <div>Filler Text</div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/text-transform-applies-to-004.xht b/tests/wpt/web-platform-tests/css/css-block/text-transform-applies-to-004.xht
deleted file mode 100644
index b6ff7f82ce3..00000000000
--- a/tests/wpt/web-platform-tests/css/css-block/text-transform-applies-to-004.xht
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>CSS Test: Text-transform application to 'display: run-in' element</title>
- <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/text.html#propdef-text-transform" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/text.html#caps-prop" />
- <link rel="match" href="../reference/pass_if_letter_uppercase.html" />
- <meta name="flags" content="" />
- <meta name="assert" content="The 'text-transform' property is applied to 'display: run-in' elements." />
- <style type="text/css">
- div
- {
- display: run-in;
- text-transform: capitalize;
- }
- </style>
- </head>
- <body>
- <p>Test passes if the letter "F" in the words "Filler Text" below is in upper-case.</p>
- <div>filler text</div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/width-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-block/width-applies-to-011.xht
deleted file mode 100644
index 542bdeeae90..00000000000
--- a/tests/wpt/web-platform-tests/css/css-block/width-applies-to-011.xht
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>CSS Test: Width applied to elements with 'display' set to 'run-in'</title>
- <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#propdef-width" />
- <link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#the-width-property" />
- <link rel="match" href="../reference/pass_if_square_96px_black.html"/>
- <meta name="flags" content="" />
- <meta name="assert" content="The 'width' property applies to elements with 'display' set to 'run-in'." />
- <style type="text/css">
- div
- {
- background: black;
- display: run-in;
- height: 1in;
- width: 1in;
- }
- </style>
- </head>
- <body>
- <p>Test passes if there is a square below.</p>
- <div></div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-break/OWNERS b/tests/wpt/web-platform-tests/css/css-break/OWNERS
new file mode 100644
index 00000000000..f4d064aef21
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-break/OWNERS
@@ -0,0 +1 @@
+@mstensho
diff --git a/tests/wpt/web-platform-tests/css/css-break/break-before-always-001.xht b/tests/wpt/web-platform-tests/css/css-break/break-before-always-001.xht
index d97a8c25696..e2e7297d153 100644
--- a/tests/wpt/web-platform-tests/css/css-break/break-before-always-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-break/break-before-always-001.xht
@@ -3,7 +3,7 @@
<head>
<title>CSS Test: 'break-before: always' and paginated multi-column elements</title>
<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact"/>
- <link rel="help" href="http://www.w3.org/TR/css3-multicol/#break-before-break-after-break-inside"/>
+ <link rel="help" href="https://drafts.csswg.org/css-break/#break-between"/>
<meta name="flags" content="page" />
<meta name="assert" content="A forced break of type 'always' will break through both the multi-column context and the pagination context."/>
<style type="text/css"><![CDATA[
diff --git a/tests/wpt/web-platform-tests/css/css-color/blacktext-ref.html b/tests/wpt/web-platform-tests/css/css-color/blacktext-ref.html
index 7db2c1f382a..ddfa9100cbe 100644
--- a/tests/wpt/web-platform-tests/css/css-color/blacktext-ref.html
+++ b/tests/wpt/web-platform-tests/css/css-color/blacktext-ref.html
@@ -5,5 +5,5 @@
.test { color: #000000}
</style>
<body>
- <p class="test">Test passess if this text is black</p>
+ <p class="test">Test passes if this text is black</p>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/color-001.html b/tests/wpt/web-platform-tests/css/css-color/color-001.html
index 5d93d5e2667..580307ba073 100644
--- a/tests/wpt/web-platform-tests/css/css-color/color-001.html
+++ b/tests/wpt/web-platform-tests/css/css-color/color-001.html
@@ -9,5 +9,5 @@
.test {color: green}
</style>
<body>
- <p class="test">Test passess if this text is green</p>
+ <p class="test">Test passes if this text is green</p>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/color-002.html b/tests/wpt/web-platform-tests/css/css-color/color-002.html
index 8b53b6862b6..7d2f5b318e6 100644
--- a/tests/wpt/web-platform-tests/css/css-color/color-002.html
+++ b/tests/wpt/web-platform-tests/css/css-color/color-002.html
@@ -9,5 +9,5 @@
.test {color: initial}
</style>
<body>
- <p class="test">Test passess if this text is black</p>
+ <p class="test">Test passes if this text is black</p>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/color-003.html b/tests/wpt/web-platform-tests/css/css-color/color-003.html
index df01b0a1e92..c9ed7c773ba 100644
--- a/tests/wpt/web-platform-tests/css/css-color/color-003.html
+++ b/tests/wpt/web-platform-tests/css/css-color/color-003.html
@@ -7,8 +7,8 @@
<meta name="assert" content="If the currentcolor keyword is set on the color property itself, it is treated as color: inherit.">
<style>
.outer {color: green;}
- .inner {color: currentcolor;}
+ .inner {color: currentcolor;}
</style>
<body>
- <p class="outer"><span class="inner">Test passess if this text is green</span></p>
+ <p class="outer"><span class="inner">Test passes if this text is green</span></p>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/color-resolving-hsl.html b/tests/wpt/web-platform-tests/css/css-color/color-resolving-hsl.html
new file mode 100644
index 00000000000..d33701759d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/color-resolving-hsl.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Color 4: Resolving HSL color values</title>
+<link rel="author" title="Chris Nardi" href="mailto:csnardi1@gmail.com">
+<link rel="help" href="https://drafts.csswg.org/css-color-4/#resolving-color-values">
+<meta name="assert" content="Tests if HSL color values are resolved properly">
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<div id="parent" style="color: rgb(45, 23, 27)">
+ <div id="inner"></div>
+</div>
+
+<script>
+ function color_test(color, expected, reason) {
+ test(function() {
+ var element = document.getElementById('inner');
+ // Random value not in our test data.
+ fail_value = "rgb(12, 34, 223)"
+ element.style.color = "black";
+ element.style.cssText = "color: " + fail_value + "; color: " + color;
+
+ if (expected === null)
+ assert_equals(getComputedStyle(element).color, fail_value);
+ else
+ assert_equals(getComputedStyle(element).color, expected);
+ }, `${reason}: ${color}`);
+ }
+
+ function expected_value(rgb_channels) {
+ if (rgb_channels === null)
+ return null;
+ else if (rgb_channels.length === 3 || rgb_channels[3] == 1 || rgb_channels[3] === undefined)
+ return "rgb(" + rgb_channels.slice(0, 3).join(", ") + ")";
+ else
+ return "rgba(" + rgb_channels.join(", ") + ")";
+ }
+
+ // Taken mostly from https://drafts.csswg.org/css-color/#hsl-to-rgb
+ function hslToRgb(hue, sat, light) {
+ if (light <= .5) {
+ var t2 = light * (sat + 1);
+ } else {
+ var t2 = light + sat - (light * sat);
+ }
+ var t1 = light * 2 - t2;
+ var r = Math.min(Math.max(Math.round(hueToRgb(t1, t2, hue + 2) * 255), 0), 255);
+ var g = Math.min(Math.max(Math.round(hueToRgb(t1, t2, hue) * 255), 0), 255);
+ var b = Math.min(Math.max(Math.round(hueToRgb(t1, t2, hue - 2) * 255), 0), 255);
+ return [r,g,b];
+ }
+
+ function hueToRgb(t1, t2, hue) {
+ if (hue < 0) hue += 6;
+ if (hue >= 6) hue -= 6;
+
+ if (hue < 1) return (t2 - t1) * hue + t1;
+ else if (hue < 3) return t2;
+ else if (hue < 4) return (t2 - t1) * (4 - hue) + t1;
+ else return t1;
+ }
+
+ // Test HSL parsing
+ for (var hue of [0, 30, 60, 90, 120, 180, 210, 240, 270, 300, 330, 360]) {
+ for (var sat of [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1]) {
+ for (var light of [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1]) {
+ rgb_channels = hslToRgb(hue / 60, sat, light);
+ for (var alpha of [undefined, 0, 0.2, 1]) {
+ hsl_color = "hsl(" + hue + ", " + sat * 100 + "%, " + light * 100 + "%)";
+ rgb_channels[3] = alpha;
+ if (alpha !== undefined) {
+ hsl_color = "hsla(" + hue + ", " + sat * 100 + "%, " + light * 100 + "%, " + alpha + ")";
+ }
+ color_test(hsl_color, expected_value(rgb_channels), "HSL/HSLA value should parse and round correctly");
+ }
+ }
+ }
+ }
+</script>
diff --git a/tests/wpt/web-platform-tests/css/css-color/color-resolving-keywords.html b/tests/wpt/web-platform-tests/css/css-color/color-resolving-keywords.html
new file mode 100644
index 00000000000..5cbdcbe4b07
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/color-resolving-keywords.html
@@ -0,0 +1,205 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Color 4: Resolving keyword color values</title>
+<link rel="author" title="Chris Nardi" href="mailto:csnardi1@gmail.com">
+<link rel="help" href="https://drafts.csswg.org/css-color-4/#resolving-color-values">
+<meta name="assert" content="Tests if keyword color values are resolved properly">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<div id="parent" style="color: rgb(45, 23, 27)">
+ <div id="inner"></div>
+</div>
+
+<script>
+ function color_test(color, expected, reason) {
+ test(function() {
+ var element = document.getElementById('inner');
+ // Random value not in our test data.
+ fail_value = "rgb(12, 34, 223)"
+ element.style.color = "black";
+ element.style.cssText = "color: " + fail_value + "; color: " + color;
+
+ if (expected === null)
+ assert_equals(getComputedStyle(element).color, fail_value);
+ else
+ assert_equals(getComputedStyle(element).color, expected);
+ }, `${reason}: ${color}`);
+ }
+
+ function expected_value(rgb_channels) {
+ if (rgb_channels === null)
+ return null;
+ else if (rgb_channels.length === 3 || rgb_channels[3] == 1)
+ return "rgb(" + rgb_channels.slice(0, 3).join(", ") + ")";
+ else
+ return "rgba(" + rgb_channels.join(", ") + ")";
+ }
+
+ keywords = [
+ ['transparent', [0, 0, 0, 0]],
+ ['aliceblue', [240, 248, 255, 1]],
+ ['antiquewhite', [250, 235, 215, 1]],
+ ['aqua', [0, 255, 255, 1]],
+ ['aquamarine', [127, 255, 212, 1]],
+ ['azure', [240, 255, 255, 1]],
+ ['beige', [245, 245, 220, 1]],
+ ['bisque', [255, 228, 196, 1]],
+ ['black', [0, 0, 0, 1]],
+ ['blanchedalmond', [255, 235, 205, 1]],
+ ['blue', [0, 0, 255, 1]],
+ ['blueviolet', [138, 43, 226, 1]],
+ ['brown', [165, 42, 42, 1]],
+ ['burlywood', [222, 184, 135, 1]],
+ ['cadetblue', [95, 158, 160, 1]],
+ ['chartreuse', [127, 255, 0, 1]],
+ ['chocolate', [210, 105, 30, 1]],
+ ['coral', [255, 127, 80, 1]],
+ ['cornflowerblue', [100, 149, 237, 1]],
+ ['cornsilk', [255, 248, 220, 1]],
+ ['crimson', [220, 20, 60, 1]],
+ ['cyan', [0, 255, 255, 1]],
+ ['darkblue', [0, 0, 139, 1]],
+ ['darkcyan', [0, 139, 139, 1]],
+ ['darkgoldenrod', [184, 134, 11, 1]],
+ ['darkgray', [169, 169, 169, 1]],
+ ['darkgreen', [0, 100, 0, 1]],
+ ['darkgrey', [169, 169, 169, 1]],
+ ['darkkhaki', [189, 183, 107, 1]],
+ ['darkmagenta', [139, 0, 139, 1]],
+ ['darkolivegreen', [85, 107, 47, 1]],
+ ['darkorange', [255, 140, 0, 1]],
+ ['darkorchid', [153, 50, 204, 1]],
+ ['darkred', [139, 0, 0, 1]],
+ ['darksalmon', [233, 150, 122, 1]],
+ ['darkseagreen', [143, 188, 143, 1]],
+ ['darkslateblue', [72, 61, 139, 1]],
+ ['darkslategray', [47, 79, 79, 1]],
+ ['darkslategrey', [47, 79, 79, 1]],
+ ['darkturquoise', [0, 206, 209, 1]],
+ ['darkviolet', [148, 0, 211, 1]],
+ ['deeppink', [255, 20, 147, 1]],
+ ['deepskyblue', [0, 191, 255, 1]],
+ ['dimgray', [105, 105, 105, 1]],
+ ['dimgrey', [105, 105, 105, 1]],
+ ['dodgerblue', [30, 144, 255, 1]],
+ ['firebrick', [178, 34, 34, 1]],
+ ['floralwhite', [255, 250, 240, 1]],
+ ['forestgreen', [34, 139, 34, 1]],
+ ['fuchsia', [255, 0, 255, 1]],
+ ['gainsboro', [220, 220, 220, 1]],
+ ['ghostwhite', [248, 248, 255, 1]],
+ ['gold', [255, 215, 0, 1]],
+ ['goldenrod', [218, 165, 32, 1]],
+ ['gray', [128, 128, 128, 1]],
+ ['green', [0, 128, 0, 1]],
+ ['greenyellow', [173, 255, 47, 1]],
+ ['grey', [128, 128, 128, 1]],
+ ['honeydew', [240, 255, 240, 1]],
+ ['hotpink', [255, 105, 180, 1]],
+ ['indianred', [205, 92, 92, 1]],
+ ['indigo', [75, 0, 130, 1]],
+ ['ivory', [255, 255, 240, 1]],
+ ['khaki', [240, 230, 140, 1]],
+ ['lavender', [230, 230, 250, 1]],
+ ['lavenderblush', [255, 240, 245, 1]],
+ ['lawngreen', [124, 252, 0, 1]],
+ ['lemonchiffon', [255, 250, 205, 1]],
+ ['lightblue', [173, 216, 230, 1]],
+ ['lightcoral', [240, 128, 128, 1]],
+ ['lightcyan', [224, 255, 255, 1]],
+ ['lightgoldenrodyellow', [250, 250, 210, 1]],
+ ['lightgray', [211, 211, 211, 1]],
+ ['lightgreen', [144, 238, 144, 1]],
+ ['lightgrey', [211, 211, 211, 1]],
+ ['lightpink', [255, 182, 193, 1]],
+ ['lightsalmon', [255, 160, 122, 1]],
+ ['lightseagreen', [32, 178, 170, 1]],
+ ['lightskyblue', [135, 206, 250, 1]],
+ ['lightslategray', [119, 136, 153, 1]],
+ ['lightslategrey', [119, 136, 153, 1]],
+ ['lightsteelblue', [176, 196, 222, 1]],
+ ['lightyellow', [255, 255, 224, 1]],
+ ['lime', [0, 255, 0, 1]],
+ ['limegreen', [50, 205, 50, 1]],
+ ['linen', [250, 240, 230, 1]],
+ ['magenta', [255, 0, 255, 1]],
+ ['maroon', [128, 0, 0, 1]],
+ ['mediumaquamarine', [102, 205, 170, 1]],
+ ['mediumblue', [0, 0, 205, 1]],
+ ['mediumorchid', [186, 85, 211, 1]],
+ ['mediumpurple', [147, 112, 219, 1]],
+ ['mediumseagreen', [60, 179, 113, 1]],
+ ['mediumslateblue', [123, 104, 238, 1]],
+ ['mediumspringgreen', [0, 250, 154, 1]],
+ ['mediumturquoise', [72, 209, 204, 1]],
+ ['mediumvioletred', [199, 21, 133, 1]],
+ ['midnightblue', [25, 25, 112, 1]],
+ ['mintcream', [245, 255, 250, 1]],
+ ['mistyrose', [255, 228, 225, 1]],
+ ['moccasin', [255, 228, 181, 1]],
+ ['navajowhite', [255, 222, 173, 1]],
+ ['navy', [0, 0, 128, 1]],
+ ['oldlace', [253, 245, 230, 1]],
+ ['olive', [128, 128, 0, 1]],
+ ['olivedrab', [107, 142, 35, 1]],
+ ['orange', [255, 165, 0, 1]],
+ ['orangered', [255, 69, 0, 1]],
+ ['orchid', [218, 112, 214, 1]],
+ ['palegoldenrod', [238, 232, 170, 1]],
+ ['palegreen', [152, 251, 152, 1]],
+ ['paleturquoise', [175, 238, 238, 1]],
+ ['palevioletred', [219, 112, 147, 1]],
+ ['papayawhip', [255, 239, 213, 1]],
+ ['peachpuff', [255, 218, 185, 1]],
+ ['peru', [205, 133, 63, 1]],
+ ['pink', [255, 192, 203, 1]],
+ ['plum', [221, 160, 221, 1]],
+ ['powderblue', [176, 224, 230, 1]],
+ ['purple', [128, 0, 128, 1]],
+ ['red', [255, 0, 0, 1]],
+ ['rosybrown', [188, 143, 143, 1]],
+ ['royalblue', [65, 105, 225, 1]],
+ ['saddlebrown', [139, 69, 19, 1]],
+ ['salmon', [250, 128, 114, 1]],
+ ['sandybrown', [244, 164, 96, 1]],
+ ['seagreen', [46, 139, 87, 1]],
+ ['seashell', [255, 245, 238, 1]],
+ ['sienna', [160, 82, 45, 1]],
+ ['silver', [192, 192, 192, 1]],
+ ['skyblue', [135, 206, 235, 1]],
+ ['slateblue', [106, 90, 205, 1]],
+ ['slategray', [112, 128, 144, 1]],
+ ['slategrey', [112, 128, 144, 1]],
+ ['snow', [255, 250, 250, 1]],
+ ['springgreen', [0, 255, 127, 1]],
+ ['steelblue', [70, 130, 180, 1]],
+ ['tan', [210, 180, 140, 1]],
+ ['teal', [0, 128, 128, 1]],
+ ['thistle', [216, 191, 216, 1]],
+ ['tomato', [255, 99, 71, 1]],
+ ['turquoise', [64, 224, 208, 1]],
+ ['violet', [238, 130, 238, 1]],
+ ['wheat', [245, 222, 179, 1]],
+ ['white', [255, 255, 255, 1]],
+ ['whitesmoke', [245, 245, 245, 1]],
+ ['yellow', [255, 255, 0, 1]],
+ ['yellowgreen', [154, 205, 50, 1]],
+ ]
+
+ for (var value in keywords) {
+ items_to_test = keywords[value];
+ keyword = items_to_test[0];
+ expected = expected_value(items_to_test[1]);
+ letter = value % keyword.length;
+ replacement = keyword;
+
+ color_test(keyword, expected, "Keyword should parse properly");
+ color_test(keyword.toUpperCase(), expected, "Keywords should be case-insensitive");
+ replacement[letter] = "\\" + keyword.codePointAt(letter);
+ color_test(replacement, expected, "Code point should parse");
+ color_test(keyword.slice(0, letter) + keyword.slice(letter + 1, keyword.length), null, "Partial keywords shouldn't parse");
+ if (keyword.indexOf('k') !== -1)
+ color_test(keyword.replace('k', 'K'), null, "Unicode modification shouldn't parse");
+ }
+</script>
diff --git a/tests/wpt/web-platform-tests/css/css-color/color-resolving.html b/tests/wpt/web-platform-tests/css/css-color/color-resolving.html
new file mode 100644
index 00000000000..b3d1c740c57
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/color-resolving.html
@@ -0,0 +1,180 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Color 4: Resolving color values</title>
+<link rel="author" title="Chris Nardi" href="mailto:csnardi1@gmail.com">
+<link rel="help" href="https://drafts.csswg.org/css-color-4/#resolving-color-values">
+<meta name="assert" content="Tests if color values are resolved properly">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<div id="parent" style="color: rgb(45, 23, 27)">
+ <div id="inner"></div>
+</div>
+
+<script>
+ function color_test(color, expected, reason) {
+ test(function() {
+ var element = document.getElementById('inner');
+ // Random value not in our test data.
+ fail_value = "rgb(12, 34, 223)"
+ element.style.color = "black";
+ element.style.cssText = "color: " + fail_value + "; color: " + color;
+
+ if (expected === null)
+ assert_equals(getComputedStyle(element).color, fail_value);
+ else
+ assert_equals(getComputedStyle(element).color, expected);
+ }, `${reason}: ${color}`);
+ }
+
+ function expected_value(rgb_channels) {
+ if (rgb_channels === null)
+ return null;
+ else if (rgb_channels.length === 3 || rgb_channels[3] == 1)
+ return "rgb(" + rgb_channels.slice(0, 3).join(", ") + ")";
+ else
+ return "rgba(" + rgb_channels.join(", ") + ")";
+ }
+
+ tests = [
+ // Keyword tests
+ ["", null, "Should not parse invalid keyword"],
+ [" /* hey */\n", null, "Should not parse invalid keyword"],
+ ["4", null, "Should not parse invalid keyword"],
+ ["top", null, "Should not parse invalid keyword"],
+ ["/**/transparent", [0, 0, 0, 0], "Should parse to completely transparent"],
+ ["transparent", [0, 0, 0, 0], "Should parse to completely transparent"],
+ [" transparent\n", [0, 0, 0, 0], "Should parse to completely transparent"],
+ ["TransParent", [0, 0, 0, 0], "Should parse to completely transparent"],
+ ["currentColor", [45, 23, 27], "Should be same as parent color"],
+ ["CURRENTcolor", [45, 23, 27], "Should be same as parent color"],
+ ["current-Color", null, "Should not parse invalid keyword"],
+ ["black", [0, 0, 0, 1], "Should parse as correct value"],
+ ["white", [255, 255, 255, 1], "Should parse as correct value"],
+ ["fuchsia", [255, 0, 255, 1], "Should parse as correct value"],
+ ["cyan", [0, 255, 255, 1], "Should parse as correct value"],
+ ["CyAn", [0, 255, 255, 1], "Should parse as cyan"],
+
+ // Hex tests
+ ["#", null, "Should not parse invalid hex"],
+ ["#f", null, "Should not parse invalid hex"],
+ ["#ff", null, "Should not parse invalid hex"],
+ ["#fff", [255, 255, 255, 1], "Valid 3-digit hex"],
+ ["#ffg", null, "Should not parse invalid hex"],
+ ["#ffff", [255, 255, 255, 1], "Valid 4-digit hex"],
+ ["#fffg", null, "Should not parse invalid hex"],
+ ["#fffff", null, "Should not parse invalid hex"],
+ ["#ffffff", [255, 255, 255, 1], "Valid 6-digit hex"],
+ ["#fffffg", null, "Should not parse invalid hex"],
+ ["#fffffff", null, "Should not parse invalid hex"],
+ ["#ffffffff", [255, 255, 255, 1], "Valid 8-digit hex"],
+ ["#fffffffg", null, "Should not parse invalid hex"],
+ ["#fffffffff", null, "Should not parse invalid hex"],
+ ["#FFCc99", [255, 204, 153, 1], "Valid 6-digit hex"],
+ ["#369", [51, 102, 153, 1], "Valid 3-digit hex"],
+
+ // RGB tests
+ ["rgb(00, 51, 102)", [0, 51, 102, 1], "Valid numbers should be parsed"],
+ ["r\\gb(00, 51, 102)", [0, 51, 102, 1], "Correct escape sequences should still parse"],
+ ["r\\67 b(00, 51, 102)", [0, 51, 102, 1], "Correct escape sequences should still parse"],
+ ["RGB(153, 204, 255)", [153, 204, 255, 1], "Capitalization should not affect parsing"],
+ ["rgB(0, 0, 0)", [0, 0, 0, 1], "Capitalization should not affect parsing"],
+ ["rgB(0, 51, 255)", [0, 51, 255, 1], "Capitalization should not affect parsing"],
+ ["rgb(0,51,255)", [0, 51, 255, 1], "Lack of whitespace should not affect parsing"],
+ ["rgb(0\t, 51 ,255)", [0, 51, 255, 1], "Whitespace should not affect parsing"],
+ ["rgb(/* R */0, /* G */51, /* B */255)", [0, 51, 255, 1], "Comments should be allowed within function"],
+ ["rgb(-51, 306, 0)", [0, 255, 0, 1], "Invalid values should be clamped to 0 and 255 respectively"],
+ ["rgb(42%, 3%, 50%)", [107, 8, 128, 1], "Valid percentages should be parsed"],
+ ["RGB(100%, 100%, 100%)", [255, 255, 255, 1], "Capitalization should not affect parsing"],
+ ["rgB(0%, 0%, 0%)", [0, 0, 0, 1], "Capitalization should not affect parsing"],
+ ["rgB(10%, 20%, 30%)", [26, 51, 77, 1], "Capitalization should not affect parsing"],
+ ["rgb(10%,20%,30%)", [26, 51, 77, 1], "Whitespace should not affect parsing"],
+ ["rgb(10%\t, 20% ,30%)", [26, 51, 77, 1], "Whitespace should not affect parsing"],
+ ["rgb(/* R */ 10%, /* G */ 20%, /* B */ 30%)", [26, 51, 77, 1], "Comments should not affect parsing"],
+ ["rgb(-12%, 110%, 1400%)", [0, 255, 255, 1], "Invalid values should be clamped to 0 and 255 respectively"],
+ ["rgb(10%, 50%, 0)", null, "Values must be all numbers or all percentages"],
+ ["rgb(255, 50%, 0%)", null, "Values must be all numbers or all percentages"],
+ ["rgb(0, 0 0)", null, "Comma optional syntax requires no commas at all"],
+ ["rgb(0, 0, 0deg)", null, "Angles are not accepted in the rgb function"],
+ ["rgb(0, 0, light)", null, "Keywords are not accepted in the rgb function"],
+ ["rgb()", null, "The rgb function requires 3 or 4 arguments"],
+ ["rgb(0)", null, "The rgb function requires 3 or 4 arguments"],
+ ["rgb(0, 0)", null, "The rgb function requires 3 or 4 arguments"],
+ ["rgb(0%)", null, "The rgb function requires 3 or 4 arguments"],
+ ["rgb(0%, 0%)", null, "The rgb function requires 3 or 4 arguments"],
+ ["rgb(0, 0, 0, 0)", [0, 0, 0, 0], "RGB and RGBA are synonyms"],
+ ["rgb(0%, 0%, 0%, 0%)", [0, 0, 0, 0], "RGB and RGBA are synonyms"],
+ ["rgb(0%, 0%, 0%, 0)", [0, 0, 0, 0], "RGB and RGBA are synonyms"],
+ ["rgba(0, 0, 0, 0)", [0, 0, 0, 0], "Valid numbers should be parsed"],
+ ["rgba(204, 0, 102, 0.3)", [204, 0, 102, 0.3], "Valid numbers should be parsed"],
+ ["RGBA(255, 255, 255, 0)", [255, 255, 255, 0], "Capitalization should not affect parsing"],
+ ["rgBA(0, 51, 255, 1)", [0, 51, 255, 1], "Capitalization should not affect parsing"],
+ ["rgba(0, 51, 255, 1.1)", [0, 51, 255, 1], "Invalid alpha values should be clamped to 0 and 1 respectively"],
+ ["rgba(0, 51, 255, 37)", [0, 51, 255, 1], "Invalid alpha values should be clamped to 0 and 1 respectively"],
+ ["rgba(0, 51, 255, 0.42)", [0, 51, 255, 0.42], "Valid numbers should be parsed"],
+ ["rgba(0, 51, 255, 0)", [0, 51, 255, 0], "Valid numbers should be parsed"],
+ ["rgba(0, 51, 255, -0.1)", [0, 51, 255, 0], "Invalid alpha values should be clamped to 0 and 1 respectively"],
+ ["rgba(0, 51, 255, -139)", [0, 51, 255, 0], "Invalid alpha values should be clamped to 0 and 1 respectively"],
+ ["RGBA(100%, 100%, 100%, 0)", [255, 255, 255, 0], "Capitalization should not affect parsing"],
+ ["rgba(42%, 3%, 50%, 0.3)", [107, 8, 128, 0.3], "Valid percentages should be parsed"],
+ ["rgBA(0%, 20%, 100%, 1)", [0, 51, 255, 1], "Capitalization should not affect parsing"],
+ ["rgba(0%, 20%, 100%, 1.1)", [0, 51, 255, 1], "Invalid alpha values should be clamped to 0 and 1 respectively"],
+ ["rgba(0%, 20%, 100%, 37)", [0, 51, 255, 1], "Invalid alpha values should be clamped to 0 and 1 respectively"],
+ ["rgba(0%, 20%, 100%, 0.42)", [0, 51, 255, 0.42], "Valid percentages should be parsed"],
+ ["rgba(0%, 20%, 100%, 0)", [0, 51, 255, 0], "Valid percentages should be parsed"],
+ ["rgba(0%, 20%, 100%, -0.1)", [0, 51, 255, 0], "Invalid alpha values should be clamped to 0 and 1 respectively"],
+ ["rgba(0%, 20%, 100%, -139)", [0, 51, 255, 0], "Invalid alpha values should be clamped to 0 and 1 respectively"],
+ ["rgba(255, 255, 255, 0%)", [255, 255, 255, 0], "Percent alpha values are accepted in rgb/rgba"],
+ ["rgba(0%, 0%, 0%, 0%)", [0, 0, 0, 0], "Percent alpha values are accepted in rgb/rgba"],
+ ["rgba(0%, 0%, 0%)", [0, 0, 0, 1], "RGB and RGBA are synonyms"],
+ ["rgba(0, 0, 0)", [0, 0, 0, 1], "RGB and RGBA are synonyms"],
+ ["rgba(10%, 50%, 0, 1)", null, "Values must be all numbers or all percentages"],
+ ["rgba(255, 50%, 0%, 1)", null, "Values must be all numbers or all percentages"],
+ ["rgba(0, 0, 0 0)", null, "Comma optional syntax requires no commas at all"],
+ ["rgba(0, 0, 0, 0deg)", null, "Angles are not accepted in the rgb function"],
+ ["rgba(0, 0, 0, light)", null, "Keywords are not accepted in the rgb function"],
+ ["rgba()", null, "The rgba function requires 3 or 4 arguments"],
+ ["rgba(0)", null, "The rgba function requires 3 or 4 arguments"],
+ ["rgba(0, 0, 0, 0, 0)", null, "The rgba function requires 3 or 4 arguments"],
+ ["rgba(0%)", null, "The rgba function requires 3 or 4 arguments"],
+ ["rgba(0%, 0%)", null, "The rgba function requires 3 or 4 arguments"],
+ ["rgba(0%, 0%, 0%, 0%, 0%)", null, "The rgba function requires 3 or 4 arguments"],
+
+ // HSL tests
+ ["HSL(0, 0%, 0%)", [0, 0, 0, 1], "Capitalization should not affect parsing"],
+ ["hsL(0, 100%, 50%)", [255, 0, 0, 1], "Capitalization should not affect parsing"],
+ ["hsl(60, 100%, 37.5%)", [191, 191, 0, 1], "Valid numbers should be parsed"],
+ ["hsl(780, 100%, 37.5%)", [191, 191, 0, 1], "Angles are represented as a part of a circle and wrap around"],
+ ["hsl(-300, 100%, 37.5%)", [191, 191, 0, 1], "Angles are represented as a part of a circle and wrap around"],
+ ["hsl(300, 50%, 50%)", [191, 64, 191, 1], "Valid numbers should be parsed"],
+ ["hsl(30deg, 100%, 100%)", [255, 255, 255, 1], "Angles are accepted in HSL/HSLA"],
+ ["hsl(0, 0%, 0%, 0%)", [0, 0, 0, 0], "HSL and HSLA are synonyms"],
+ ["hsl(10, 50%, 0)", null, "The second and third parameters of hsl/hsla must be a percent"],
+ ["hsl(50%, 50%, 0%)", null, "The first parameter of hsl/hsla must be a number or angle"],
+ ["hsl(0, 0% 0%)", null, "Comma optional syntax requires no commas at all"],
+ ["hsl(0, 0%, light)", null, "Keywords are not accepted in the hsl function"],
+ ["hsl()", null, "The hsl function requires 3 or 4 arguments"],
+ ["hsl(0)", null, "The hsl function requires 3 or 4 arguments"],
+ ["hsl(0, 0%)", null, "The hsl function requires 3 or 4 arguments"],
+ ["HSLA(-300, 100%, 37.5%, 1)", [191, 191, 0, 1], "Angles are represented as a part of a circle and wrap around"],
+ ["hsLA(-300, 100%, 37.5%, 12)", [191, 191, 0, 1], "Invalid alpha values should be clamped to 0 and 1 respectively"],
+ ["hsla(-300, 100%, 37.5%, 0.2)", [191, 191, 0, 0.2], "Angles are represented as a part of a circle and wrap around"],
+ ["hsla(-300, 100%, 37.5%, 0)", [191, 191, 0, 0], "Angles are represented as a part of a circle and wrap around"],
+ ["hsla(-300, 100%, 37.5%, -3)", [191, 191, 0, 0], "Invalid alpha values should be clamped to 0 and 1 respectively"],
+ ["hsla(0, 0%, 0%, 50%)", [0, 0, 0, 0.5], "Percent alpha values are accepted in hsl/hsla"],
+ ["hsla(30deg, 100%, 100%, 1)", [255, 255, 255, 1], "Angles are accepted in HSL/HSLA"],
+ ["hsla(10, 50%, 0, 1)", null, "The second and third parameters of hsl/hsla must be a percent"],
+ ["hsla(50%, 50%, 0%, 1)", null, "The first parameter of hsl/hsla must be a number or angle"],
+ ["hsla(0, 0% 0%, 1)", null, "Comma optional syntax requires no commas at all"],
+ ["hsla(0, 0%, light, 1)", null, "Keywords are not accepted in the hsla function"],
+ ["hsla()", null, "The hsla function requires 3 or 4 arguments"],
+ ["hsla(0)", null, "The hsla function requires 3 or 4 arguments"],
+ ["hsla(0, 0%)", null, "The hsla function requires 3 or 4 arguments"],
+ ["hsla(0, 0%, 0%, 1, 0%)", null, "The hsla function requires 3 or 4 arguments"]
+ ]
+
+ for (var value in tests) {
+ items_to_test = tests[value];
+ color_test(items_to_test[0], expected_value(items_to_test[1]), items_to_test[2]);
+ }
+</script>
diff --git a/tests/wpt/web-platform-tests/css/css-color/currentcolor-001.html b/tests/wpt/web-platform-tests/css/css-color/currentcolor-001.html
index 355b00fbf2c..e08129ee522 100644
--- a/tests/wpt/web-platform-tests/css/css-color/currentcolor-001.html
+++ b/tests/wpt/web-platform-tests/css/css-color/currentcolor-001.html
@@ -3,13 +3,13 @@
<title>CSS Color 4: currentcolor</title>
<link rel="author" title="Chris Lilley" href="mailto:chris@w3.org">
<link rel="help" href="https://drafts.csswg.org/css-color-4/#currentcolor-color">
-<link rel="match" href="greentext-ref.html">
+<link rel="match" href="greensquare-ref.html">
<meta name="assert" content="The keyword currentcolor takes its value from the value of the color property on the same element.">
<style>
.outer {color: red; background-color: red; font-size: 200%; width: 6em; height: 6em; }
- .inner {color: green; background-color: currentColor; width: 6em; height: 6em; font-weight: bold;}
+ .inner {color: green; background-color: currentColor; width: 6em; height: 6em; font-weight: bold;}
</style>
<body>
<p>Test passes if you see a green square, and no red.</p>
- <div class="outer"><div class="inner">FAIL</div></div>
+ <div class="outer"><div class="inner">FAIL</div></div>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/currentcolor-002.html b/tests/wpt/web-platform-tests/css/css-color/currentcolor-002.html
index 014794b11b8..aa5d736c688 100644
--- a/tests/wpt/web-platform-tests/css/css-color/currentcolor-002.html
+++ b/tests/wpt/web-platform-tests/css/css-color/currentcolor-002.html
@@ -3,14 +3,14 @@
<title>CSS Color 4: currentcolor</title>
<link rel="author" title="Chris Lilley" href="mailto:chris@w3.org">
<link rel="help" href="https://drafts.csswg.org/css-color-4/#currentcolor-color">
-<link rel="match" href="greentext-ref.html">
+<link rel="match" href="greensquare-ref.html">
<meta name="assert" content="This happens at used-value time, which means that if the value is inherited, it’s inherited as currentcolor, not as the value of the color property, so descendants will use their own color property to resolve it.">
<style>
.outer {color: red; background-color: currentColor; font-size: 200%; width: 6em; height: 6em; }
- .middle {background-color: inherit; width: 6em; height: 6em;}
- .inner {color: green; background-color: inherit; width: 6em; height: 6em; font-weight: bold;}
+ .middle {background-color: inherit; width: 6em; height: 6em;}
+ .inner {color: green; background-color: inherit; width: 6em; height: 6em; font-weight: bold;}
</style>
<body>
<p>Test passes if you see a green square, and no red.</p>
- <div class="outer"><div class="middle"><div class="inner">FAIL</div></div></div>
+ <div class="outer"><div class="middle"><div class="inner">FAIL</div></div></div>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/greensquare-ref.html b/tests/wpt/web-platform-tests/css/css-color/greensquare-ref.html
new file mode 100644
index 00000000000..35a31f8f564
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/greensquare-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Green square reference</title>
+<style>
+ .test { background-color: #008000; width: 12em; height: 12em;}
+</style>
+<body>
+ <p>Test passes if you see a green square, and no red.</p>
+ <div class="test"></div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/hex-001.html b/tests/wpt/web-platform-tests/css/css-color/hex-001.html
index b3c10931633..4ff5cdbd9ce 100644
--- a/tests/wpt/web-platform-tests/css/css-color/hex-001.html
+++ b/tests/wpt/web-platform-tests/css/css-color/hex-001.html
@@ -9,5 +9,5 @@
.test {color: #008000}
</style>
<body>
- <p class="test">Test passess if this text is green</p>
+ <p class="test">Test passes if this text is green</p>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/hex-002.html b/tests/wpt/web-platform-tests/css/css-color/hex-002.html
index 53480981707..5e0d48a23d3 100644
--- a/tests/wpt/web-platform-tests/css/css-color/hex-002.html
+++ b/tests/wpt/web-platform-tests/css/css-color/hex-002.html
@@ -9,5 +9,5 @@
.test {color: #008000FF}
</style>
<body>
- <p class="test">Test passess if this text is green</p>
+ <p class="test">Test passes if this text is green</p>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/hex-003-ref.html b/tests/wpt/web-platform-tests/css/css-color/hex-003-ref.html
new file mode 100644
index 00000000000..613528e9260
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/hex-003-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Green text reference for hex shorthand tests</title>
+<style>
+ .test { color: #007700}
+</style>
+<body>
+ <p class="test">Test passes if this text is green</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/hex-003.html b/tests/wpt/web-platform-tests/css/css-color/hex-003.html
index 13889e32528..a6a19ad6191 100644
--- a/tests/wpt/web-platform-tests/css/css-color/hex-003.html
+++ b/tests/wpt/web-platform-tests/css/css-color/hex-003.html
@@ -3,11 +3,11 @@
<title>CSS Color 4: The RGB hexadecimal notations: #RRGGBB</title>
<link rel="author" title="Chris Lilley" href="mailto:chris@w3.org">
<link rel="help" href="https://drafts.csswg.org/css-color-4/#hex-notation">
+<link rel="match" href="hex-003-ref.html">
<meta name="assert" content="3 digit hex">
<style>
.test {color: #070}
</style>
<body>
- <p class="test">Test passess if this text is green</p>
- <!-- #007700, not #008000, but visually similar. Thus, no reftest -->
+ <p class="test">Test passes if this text is green</p>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/hex-004.html b/tests/wpt/web-platform-tests/css/css-color/hex-004.html
index e51a8d96b3c..074fb1d4760 100644
--- a/tests/wpt/web-platform-tests/css/css-color/hex-004.html
+++ b/tests/wpt/web-platform-tests/css/css-color/hex-004.html
@@ -4,10 +4,10 @@
<link rel="author" title="Chris Lilley" href="mailto:chris@w3.org">
<link rel="help" href="https://drafts.csswg.org/css-color-4/#hex-notation">
<meta name="assert" content="4 digit hex, fully opaque">
+<link rel="match" href="hex-003-ref.html">
<style>
.test {color: #070F}
</style>
<body>
- <p class="test">Test passess if this text is green</p>
- <!-- #007700, not #008000, but visually similar. Thus, no reftest -->
+ <p class="test">Test passes if this text is green</p>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/hsl-001.html b/tests/wpt/web-platform-tests/css/css-color/hsl-001.html
new file mode 100644
index 00000000000..842dbb9e713
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/hsl-001.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Color 4: HSL functions hsl() and hsla()</title>
+<link rel="author" title="Chris Nardi" href="mailto:csnardi1@gmail.com">
+<link rel="help" href="https://drafts.csswg.org/css-color-4/#the-hsl-notation">
+<link rel="match" href="greentext-ref.html">
+<meta name="assert" content="hsl() with number and no alpha, also no comma">
+<style>
+ .test {color: hsl(120 100% 25%)}
+</style>
+<body>
+ <p class="test">Test passes if this text is green</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/hsl-002.html b/tests/wpt/web-platform-tests/css/css-color/hsl-002.html
new file mode 100644
index 00000000000..91750d426aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/hsl-002.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Color 4: HSL functions hsl() and hsla()</title>
+<link rel="author" title="Chris Nardi" href="mailto:csnardi1@gmail.com">
+<link rel="help" href="https://drafts.csswg.org/css-color-4/#the-hsl-notation">
+<link rel="match" href="greentext-ref.html">
+<meta name="assert" content="hsl() with angle and no alpha, also no comma">
+<style>
+ .test {color: hsl(120deg 100% 25%)}
+</style>
+<body>
+ <p class="test">Test passes if this text is green</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/hsl-003.html b/tests/wpt/web-platform-tests/css/css-color/hsl-003.html
new file mode 100644
index 00000000000..5b6bb4b1c9a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/hsl-003.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Color 4: HSL functions hsl() and hsla()</title>
+<link rel="author" title="Chris Nardi" href="mailto:csnardi1@gmail.com">
+<link rel="help" href="https://drafts.csswg.org/css-color-4/#the-hsl-notation">
+<link rel="match" href="greentext-ref.html">
+<meta name="assert" content="hsl() with number and numeric alpha, also no comma">
+<style>
+ .test {color: hsl(120 100% 25% / 1.0)}
+</style>
+<body>
+ <p class="test">Test passes if this text is green</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/hsl-004.html b/tests/wpt/web-platform-tests/css/css-color/hsl-004.html
new file mode 100644
index 00000000000..483c821aeca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/hsl-004.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Color 4: HSL functions hsl() and hsla()</title>
+<link rel="author" title="Chris Nardi" href="mailto:csnardi1@gmail.com">
+<link rel="help" href="https://drafts.csswg.org/css-color-4/#the-hsl-notation">
+<link rel="match" href="greentext-ref.html">
+<meta name="assert" content="hsl() with angle and numeric alpha, also no comma">
+<style>
+ .test {color: hsl(120deg 100% 25% / 1)}
+</style>
+<body>
+ <p class="test">Test passes if this text is green</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/hsl-005.html b/tests/wpt/web-platform-tests/css/css-color/hsl-005.html
new file mode 100644
index 00000000000..b0970c316f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/hsl-005.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Color 4: HSL functions hsl() and hsla()</title>
+<link rel="author" title="Chris Nardi" href="mailto:csnardi1@gmail.com">
+<link rel="help" href="https://drafts.csswg.org/css-color-4/#the-hsl-notation">
+<link rel="match" href="greentext-ref.html">
+<meta name="assert" content="hsl() with number and percent alpha, also no comma">
+<style>
+ .test {color: hsl(120 100% 25% / 100%)}
+</style>
+<body>
+ <p class="test">Test passes if this text is green</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/hsl-006.html b/tests/wpt/web-platform-tests/css/css-color/hsl-006.html
new file mode 100644
index 00000000000..389c5a49d4f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/hsl-006.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Color 4: HSL functions hsl() and hsla()</title>
+<link rel="author" title="Chris Nardi" href="mailto:csnardi1@gmail.com">
+<link rel="help" href="https://drafts.csswg.org/css-color-4/#the-hsl-notation">
+<link rel="match" href="greentext-ref.html">
+<meta name="assert" content="hsl() with angle and percent alpha, also no comma">
+<style>
+ .test {color: hsl(120deg 100% 25% / 100%)}
+</style>
+<body>
+ <p class="test">Test passes if this text is green</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/hsl-007.html b/tests/wpt/web-platform-tests/css/css-color/hsl-007.html
new file mode 100644
index 00000000000..18bbe405922
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/hsl-007.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Color 4: HSL functions hsl() and hsla()</title>
+<link rel="author" title="Chris Nardi" href="mailto:csnardi1@gmail.com">
+<link rel="help" href="https://drafts.csswg.org/css-color-4/#the-hsl-notation">
+<link rel="match" href="greentext-ref.html">
+<meta name="assert" content="legacy hsl() with number and percent alpha, and commas">
+<style>
+ .test {color: hsl(120, 100%, 25%, 100%)}
+</style>
+<body>
+ <p class="test">Test passes if this text is green</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/hsl-008.html b/tests/wpt/web-platform-tests/css/css-color/hsl-008.html
new file mode 100644
index 00000000000..89b962171a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/hsl-008.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Color 4: HSL functions hsl() and hsla()</title>
+<link rel="author" title="Chris Nardi" href="mailto:csnardi1@gmail.com">
+<link rel="help" href="https://drafts.csswg.org/css-color-4/#the-hsl-notation">
+<link rel="match" href="greentext-ref.html">
+<meta name="assert" content="legacy hsl() with angle and percent alpha, with commas">
+<style>
+ .test {color: hsl(120deg, 100%, 25%, 100%)}
+</style>
+<body>
+ <p class="test">Test passes if this text is green</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/hsla-001.html b/tests/wpt/web-platform-tests/css/css-color/hsla-001.html
new file mode 100644
index 00000000000..9e5bbfa4772
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/hsla-001.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Color 4: HSL functions hsl() and hsla()</title>
+<link rel="author" title="Chris Nardi" href="mailto:csnardi1@gmail.com">
+<link rel="help" href="https://drafts.csswg.org/css-color-4/#the-hsl-notation">
+<link rel="match" href="greentext-ref.html">
+<meta name="assert" content="legacy hsla() with number and no alpha, also no comma">
+<style>
+ .test {color: hsla(120 100% 25%)}
+</style>
+<body>
+ <p class="test">Test passes if this text is green</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/hsla-002.html b/tests/wpt/web-platform-tests/css/css-color/hsla-002.html
new file mode 100644
index 00000000000..8b9cff818f2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/hsla-002.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Color 4: HSL functions hsl() and hsla()</title>
+<link rel="author" title="Chris Nardi" href="mailto:csnardi1@gmail.com">
+<link rel="help" href="https://drafts.csswg.org/css-color-4/#the-hsl-notation">
+<link rel="match" href="greentext-ref.html">
+<meta name="assert" content="legacy hsla() with angle and no alpha, also no comma">
+<style>
+ .test {color: hsla(120deg 100% 25%)}
+</style>
+<body>
+ <p class="test">Test passes if this text is green</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/hsla-003.html b/tests/wpt/web-platform-tests/css/css-color/hsla-003.html
new file mode 100644
index 00000000000..3aadd8e5b0a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/hsla-003.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Color 4: HSL functions hsl() and hsla()</title>
+<link rel="author" title="Chris Nardi" href="mailto:csnardi1@gmail.com">
+<link rel="help" href="https://drafts.csswg.org/css-color-4/#the-hsl-notation">
+<link rel="match" href="greentext-ref.html">
+<meta name="assert" content="legacy hsla() with number and numeric alpha, also no comma">
+<style>
+ .test {color: hsla(120 100% 25% / 1.0)}
+</style>
+<body>
+ <p class="test">Test passes if this text is green</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/hsla-004.html b/tests/wpt/web-platform-tests/css/css-color/hsla-004.html
new file mode 100644
index 00000000000..e68669fdeac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/hsla-004.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Color 4: HSL functions hsl() and hsla()</title>
+<link rel="author" title="Chris Nardi" href="mailto:csnardi1@gmail.com">
+<link rel="help" href="https://drafts.csswg.org/css-color-4/#the-hsl-notation">
+<link rel="match" href="greentext-ref.html">
+<meta name="assert" content="legacy hsla() with angle and numeric alpha, also no comma">
+<style>
+ .test {color: hsla(120deg 100% 25% / 1)}
+</style>
+<body>
+ <p class="test">Test passes if this text is green</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/hsla-005.html b/tests/wpt/web-platform-tests/css/css-color/hsla-005.html
new file mode 100644
index 00000000000..4efeb1912c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/hsla-005.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Color 4: HSL functions hsl() and hsla()</title>
+<link rel="author" title="Chris Nardi" href="mailto:csnardi1@gmail.com">
+<link rel="help" href="https://drafts.csswg.org/css-color-4/#the-hsl-notation">
+<link rel="match" href="greentext-ref.html">
+<meta name="assert" content="legacy hsla() with number and percent alpha, also no comma">
+<style>
+ .test {color: hsla(120 100% 25% / 100%)}
+</style>
+<body>
+ <p class="test">Test passes if this text is green</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/hsla-006.html b/tests/wpt/web-platform-tests/css/css-color/hsla-006.html
new file mode 100644
index 00000000000..e440ebe5bdb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/hsla-006.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Color 4: HSL functions hsl() and hsla()</title>
+<link rel="author" title="Chris Nardi" href="mailto:csnardi1@gmail.com">
+<link rel="help" href="https://drafts.csswg.org/css-color-4/#the-hsl-notation">
+<link rel="match" href="greentext-ref.html">
+<meta name="assert" content="legacy hsla() with angle and percent alpha, also no comma">
+<style>
+ .test {color: hsla(120deg 100% 25% / 100%)}
+</style>
+<body>
+ <p class="test">Test passes if this text is green</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/hsla-007.html b/tests/wpt/web-platform-tests/css/css-color/hsla-007.html
new file mode 100644
index 00000000000..ba647ae7514
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/hsla-007.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Color 4: HSL functions hsl() and hsla()</title>
+<link rel="author" title="Chris Nardi" href="mailto:csnardi1@gmail.com">
+<link rel="help" href="https://drafts.csswg.org/css-color-4/#the-hsl-notation">
+<link rel="match" href="greentext-ref.html">
+<meta name="assert" content="legacy hsla() with number and percent alpha, and commas">
+<style>
+ .test {color: hsla(120, 100%, 25%, 100%)}
+</style>
+<body>
+ <p class="test">Test passes if this text is green</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/hsla-008.html b/tests/wpt/web-platform-tests/css/css-color/hsla-008.html
new file mode 100644
index 00000000000..8f78f88656e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/hsla-008.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Color 4: HSL functions hsl() and hsla()</title>
+<link rel="author" title="Chris Nardi" href="mailto:csnardi1@gmail.com">
+<link rel="help" href="https://drafts.csswg.org/css-color-4/#the-hsl-notation">
+<link rel="match" href="greentext-ref.html">
+<meta name="assert" content="legacy hsla() with angle and percent alpha, with commas">
+<style>
+ .test {color: hsla(120deg, 100%, 25%, 100%)}
+</style>
+<body>
+ <p class="test">Test passes if this text is green</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/lab-001.html b/tests/wpt/web-platform-tests/css/css-color/lab-001.html
index b8b2a23b53d..70dbd9123c5 100644
--- a/tests/wpt/web-platform-tests/css/css-color/lab-001.html
+++ b/tests/wpt/web-platform-tests/css/css-color/lab-001.html
@@ -6,8 +6,8 @@
<link rel="match" href="greentext-ref.html">
<meta name="assert" content="lab() with no alpha">
<style>
- .test {color: lab(46.277 -47.562 48.583)} // green (sRGB #008000) converted to Lab
+ .test {color: lab(46.277 -47.562 48.583)} /* green (sRGB #008000) converted to Lab */
</style>
<body>
- <p class="test">Test passess if this text is green</p>
+ <p class="test">Test passes if this text is green</p>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/lab-002.html b/tests/wpt/web-platform-tests/css/css-color/lab-002.html
index 592740873b6..1f1b4476814 100644
--- a/tests/wpt/web-platform-tests/css/css-color/lab-002.html
+++ b/tests/wpt/web-platform-tests/css/css-color/lab-002.html
@@ -7,8 +7,8 @@
<meta name="assert" content="lab() with no alpha">
<style>
.test { color: red; }
- .test { color: lab(0 0 0)} // black (sRGB #000000) converted to Lab
+ .test { color: lab(0 0 0)} /* black (sRGB #000000) converted to Lab */
</style>
<body>
- <p class="test">Test passess if this text is black</p>
+ <p class="test">Test passes if this text is black</p>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/lab-003.html b/tests/wpt/web-platform-tests/css/css-color/lab-003.html
index 672c5da799c..072dafa211b 100644
--- a/tests/wpt/web-platform-tests/css/css-color/lab-003.html
+++ b/tests/wpt/web-platform-tests/css/css-color/lab-003.html
@@ -6,9 +6,9 @@
<link rel="match" href="whitetext-ref.html">
<meta name="assert" content="lab() with no alpha">
<style>
- .test { color: red; background-color: #333; padding: 3px;}
- .test { color: lab(100 0 0);} // white (sRGB #FFFFFF) converted to Lab
+ .test { color: red; background-color: #333; padding: 3px;}
+ .test { color: lab(100 0 0);} /* white (sRGB #FFFFFF) converted to Lab */
</style>
<body>
- <p class="test">Test passess if this text is white</p>
+ <p class="test">Test passes if this text is white</p>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/lab-004.html b/tests/wpt/web-platform-tests/css/css-color/lab-004.html
index 4155f1072b8..0037a1e7653 100644
--- a/tests/wpt/web-platform-tests/css/css-color/lab-004.html
+++ b/tests/wpt/web-platform-tests/css/css-color/lab-004.html
@@ -7,11 +7,11 @@
<meta name="assert" content="lab() with no alpha, positive a axis">
<style>
.test { color: red; }
- .test { color: lab(50 50 0)}
- .match { color: rgb(75.62%, 30.45%, 47.56%)} //lab(50,0,0) converted to sRGB
+ .test { color: lab(50 50 0)}
+ .match { color: rgb(75.62%, 30.45%, 47.56%)} /* lab(50,0,0) converted to sRGB */
</style>
<body>
- <p>Test passes if the two lines of filler text are the same color.</p>
+ <p>Test passes if the two lines of filler text are the same color.</p>
<p class="test">Filler text. Filler text. Filler text. </p>
- <p class="match">Filler text. Filler text. Filler text. </p>
+ <p class="match">Filler text. Filler text. Filler text. </p>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/lab-005.html b/tests/wpt/web-platform-tests/css/css-color/lab-005.html
index 990dcb59a95..366cd1bc304 100644
--- a/tests/wpt/web-platform-tests/css/css-color/lab-005.html
+++ b/tests/wpt/web-platform-tests/css/css-color/lab-005.html
@@ -7,11 +7,11 @@
<meta name="assert" content="lab() with no alpha, negative a axis">
<style>
.test { color: red; }
- .test { color: lab(70 -45 0)}
- .match { color: rgb(10.79%, 75.55%, 66.40%)} //lab(70,-45,0) converted to sRGB
+ .test { color: lab(70 -45 0)}
+ .match { color: rgb(10.79%, 75.55%, 66.40%)} /* lab(70,-45,0) converted to sRGB */
</style>
<body>
- <p>Test passes if the two lines of filler text are the same color.</p>
+ <p>Test passes if the two lines of filler text are the same color.</p>
<p class="test">Filler text. Filler text. Filler text. </p>
- <p class="match">Filler text. Filler text. Filler text. </p>
+ <p class="match">Filler text. Filler text. Filler text. </p>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/lab-006.html b/tests/wpt/web-platform-tests/css/css-color/lab-006.html
index 972c3448a25..079c37978f4 100644
--- a/tests/wpt/web-platform-tests/css/css-color/lab-006.html
+++ b/tests/wpt/web-platform-tests/css/css-color/lab-006.html
@@ -7,11 +7,11 @@
<meta name="assert" content="lab() with no alpha, positive b axis">
<style>
.test { color: red; }
- .test { color: lab(70 0 70)}
- .match { color: rgb(76.62%, 66.36%, 5.58%)} //lab(70,0,70) converted to sRGB
+ .test { color: lab(70 0 70)}
+ .match { color: rgb(76.62%, 66.36%, 5.58%)} /* lab(70,0,70) converted to sRGB */
</style>
<body>
- <p>Test passes if the two lines of filler text are the same color.</p>
+ <p>Test passes if the two lines of filler text are the same color.</p>
<p class="test">Filler text. Filler text. Filler text. </p>
- <p class="match">Filler text. Filler text. Filler text. </p>
+ <p class="match">Filler text. Filler text. Filler text. </p>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/lab-007.html b/tests/wpt/web-platform-tests/css/css-color/lab-007.html
index 79a257c1f99..4cdb35788d4 100644
--- a/tests/wpt/web-platform-tests/css/css-color/lab-007.html
+++ b/tests/wpt/web-platform-tests/css/css-color/lab-007.html
@@ -7,11 +7,11 @@
<meta name="assert" content="lab() with no alpha, negative b axis">
<style>
.test { color: red; }
- .test { color: lab(55 0 -60)}
- .match { color: rgb(12.81%, 53.10%, 92.76%)} //lab(55,0,-60) converted to sRGB
+ .test { color: lab(55 0 -60)}
+ .match { color: rgb(12.81%, 53.10%, 92.76%)} /* lab(55,0,-60) converted to sRGB */
</style>
<body>
- <p>Test passes if the two lines of filler text are the same color.</p>
+ <p>Test passes if the two lines of filler text are the same color.</p>
<p class="test">Filler text. Filler text. Filler text. </p>
- <p class="match">Filler text. Filler text. Filler text. </p>
+ <p class="match">Filler text. Filler text. Filler text. </p>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/lch-001.html b/tests/wpt/web-platform-tests/css/css-color/lch-001.html
index 9d824048028..966e1fd4055 100644
--- a/tests/wpt/web-platform-tests/css/css-color/lch-001.html
+++ b/tests/wpt/web-platform-tests/css/css-color/lch-001.html
@@ -6,8 +6,8 @@
<link rel="match" href="greentext-ref.html">
<meta name="assert" content="lch() with no alpha">
<style>
- .test {color: lab(46.277 -67.989 134.391)} // green (sRGB #008000) converted to LCH
+ .test {color: lab(46.277 -67.989 134.391)} /* green (sRGB #008000) converted to LCH */
</style>
<body>
- <p class="test">Test passess if this text is green</p>
+ <p class="test">Test passes if this text is green</p>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/lch-002.html b/tests/wpt/web-platform-tests/css/css-color/lch-002.html
index ae845ace96b..d87d0421a0d 100644
--- a/tests/wpt/web-platform-tests/css/css-color/lch-002.html
+++ b/tests/wpt/web-platform-tests/css/css-color/lch-002.html
@@ -7,8 +7,8 @@
<meta name="assert" content="lch() with no alpha">
<style>
.test { color: red; }
- .test { color: lch(0 0 0)} // black (sRGB #000000) converted to LCH
+ .test { color: lch(0 0 0)} /* black (sRGB #000000) converted to LCH */
</style>
<body>
- <p class="test">Test passess if this text is black</p>
+ <p class="test">Test passes if this text is black</p>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/lch-003.html b/tests/wpt/web-platform-tests/css/css-color/lch-003.html
index 55a35cf2592..eb8f8a25b4a 100644
--- a/tests/wpt/web-platform-tests/css/css-color/lch-003.html
+++ b/tests/wpt/web-platform-tests/css/css-color/lch-003.html
@@ -6,9 +6,9 @@
<link rel="match" href="whitetext-ref.html">
<meta name="assert" content="lch() with no alpha">
<style>
- .test { color: red; background-color: #333; padding: 3px;}
- .test { color: lch(100 0 0);} // white (sRGB #FFFFFF) converted to LCH
+ .test { color: red; background-color: #333; padding: 3px;}
+ .test { color: lch(100 0 0);} /* white (sRGB #FFFFFF) converted to LCH */
</style>
<body>
- <p class="test">Test passess if this text is white</p>
+ <p class="test">Test passes if this text is white</p>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/lch-004.html b/tests/wpt/web-platform-tests/css/css-color/lch-004.html
index 68c634ee2fa..46ac7d3988e 100644
--- a/tests/wpt/web-platform-tests/css/css-color/lch-004.html
+++ b/tests/wpt/web-platform-tests/css/css-color/lch-004.html
@@ -7,11 +7,11 @@
<meta name="assert" content="lch() with no alpha, positive a axis">
<style>
.test { color: red; }
- .test { color: lch(50 50 0)}
- .match { color: rgb(75.62%, 30.45%, 47.56%)} //lch(50,0,0) converted to sRGB
+ .test { color: lch(50 50 0)}
+ .match { color: rgb(75.62%, 30.45%, 47.56%)} /* lch(50,0,0) converted to sRGB */
</style>
<body>
- <p>Test passes if the two lines of filler text are the same color.</p>
+ <p>Test passes if the two lines of filler text are the same color.</p>
<p class="test">Filler text. Filler text. Filler text. </p>
- <p class="match">Filler text. Filler text. Filler text. </p>
+ <p class="match">Filler text. Filler text. Filler text. </p>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/lch-005.html b/tests/wpt/web-platform-tests/css/css-color/lch-005.html
index 93d51163d93..789d4b23fef 100644
--- a/tests/wpt/web-platform-tests/css/css-color/lch-005.html
+++ b/tests/wpt/web-platform-tests/css/css-color/lch-005.html
@@ -7,11 +7,11 @@
<meta name="assert" content="lch() with no alpha, negative a axis">
<style>
.test { color: red; }
- .test { color: lab(70 45 180)}
- .match { color: rgb(10.79%, 75.55%, 66.40%)} //lch(70,45,180) converted to sRGB
+ .test { color: lab(70 45 180)}
+ .match { color: rgb(10.79%, 75.55%, 66.40%)} /* lch(70,45,180) converted to sRGB */
</style>
<body>
- <p>Test passes if the two lines of filler text are the same color.</p>
+ <p>Test passes if the two lines of filler text are the same color.</p>
<p class="test">Filler text. Filler text. Filler text. </p>
- <p class="match">Filler text. Filler text. Filler text. </p>
+ <p class="match">Filler text. Filler text. Filler text. </p>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/lch-006.html b/tests/wpt/web-platform-tests/css/css-color/lch-006.html
index ab96f011585..760362cbf93 100644
--- a/tests/wpt/web-platform-tests/css/css-color/lch-006.html
+++ b/tests/wpt/web-platform-tests/css/css-color/lch-006.html
@@ -7,11 +7,11 @@
<meta name="assert" content="lch() with no alpha, positive b axis">
<style>
.test { color: red; }
- .test { color: lab(70 70 90)}
- .match { color: rgb(76.62%, 66.36%, 5.58%)} //lch(70,70,90) converted to sRGB
+ .test { color: lab(70 70 90)}
+ .match { color: rgb(76.62%, 66.36%, 5.58%)} /* lch(70,70,90) converted to sRGB */
</style>
<body>
- <p>Test passes if the two lines of filler text are the same color.</p>
+ <p>Test passes if the two lines of filler text are the same color.</p>
<p class="test">Filler text. Filler text. Filler text. </p>
- <p class="match">Filler text. Filler text. Filler text. </p>
+ <p class="match">Filler text. Filler text. Filler text. </p>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/lch-007.html b/tests/wpt/web-platform-tests/css/css-color/lch-007.html
index a5ad333185c..7b8c41fa9c7 100644
--- a/tests/wpt/web-platform-tests/css/css-color/lch-007.html
+++ b/tests/wpt/web-platform-tests/css/css-color/lch-007.html
@@ -7,11 +7,11 @@
<meta name="assert" content="lab() with no alpha, negative b axis">
<style>
.test { color: red; }
- .test { color: lch(55 60 270)}
- .match { color: rgb(12.81%, 53.10%, 92.76%)} //lch(55,60,270) converted to sRGB
+ .test { color: lch(55 60 270)}
+ .match { color: rgb(12.81%, 53.10%, 92.76%)} /* lch(55,60,270) converted to sRGB */
</style>
<body>
- <p>Test passes if the two lines of filler text are the same color.</p>
+ <p>Test passes if the two lines of filler text are the same color.</p>
<p class="test">Filler text. Filler text. Filler text. </p>
- <p class="match">Filler text. Filler text. Filler text. </p>
+ <p class="match">Filler text. Filler text. Filler text. </p>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/named-001.html b/tests/wpt/web-platform-tests/css/css-color/named-001.html
index b6c66a7c260..61a98dcb7bb 100644
--- a/tests/wpt/web-platform-tests/css/css-color/named-001.html
+++ b/tests/wpt/web-platform-tests/css/css-color/named-001.html
@@ -7,9 +7,9 @@
<meta name="assert" content="New named color, rebeccapurple">
<style>
.outer {background: red; width: 10em; height: 10em;}
- .inner {background: rebeccapurple; width: 10em; height: 10em;}
+ .inner {background: rebeccapurple; width: 10em; height: 10em;}
</style>
<body>
<p>Test passes if you see a purple square and no red.</p>
- <div class="outer"><div class="inner"></div></div>
+ <div class="outer"><div class="inner"></div></div>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/rebeccapurple-ref.html b/tests/wpt/web-platform-tests/css/css-color/rebeccapurple-ref.html
index 71074541575..8c15364f38e 100644
--- a/tests/wpt/web-platform-tests/css/css-color/rebeccapurple-ref.html
+++ b/tests/wpt/web-platform-tests/css/css-color/rebeccapurple-ref.html
@@ -6,5 +6,5 @@
</style>
<body>
<p>Test passes if you see a purple square and no red.</p>
- <div class="ref"></div>
+ <div class="ref"></div>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/t32-opacity-basic-0.0-a-ref.html b/tests/wpt/web-platform-tests/css/css-color/t32-opacity-basic-0.0-a-ref.html
new file mode 100644
index 00000000000..298c4890dff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/t32-opacity-basic-0.0-a-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<body>
+ <p id="one">This should be the only text visible on this page.</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/t32-opacity-basic-0.0-a.xht b/tests/wpt/web-platform-tests/css/css-color/t32-opacity-basic-0.0-a.xht
index 20a2dd325b6..637638d96a4 100644
--- a/tests/wpt/web-platform-tests/css/css-color/t32-opacity-basic-0.0-a.xht
+++ b/tests/wpt/web-platform-tests/css/css-color/t32-opacity-basic-0.0-a.xht
@@ -5,6 +5,7 @@
<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://www.w3.org/TR/css3-color/#transparency" />
+ <link rel="match" href="t32-opacity-basic-0.0-a-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="Opacity of 0.0 makes box transparent." />
<style type="text/css"><![CDATA[
diff --git a/tests/wpt/web-platform-tests/css/css-color/t32-opacity-basic-1.0-a-ref.html b/tests/wpt/web-platform-tests/css/css-color/t32-opacity-basic-1.0-a-ref.html
new file mode 100644
index 00000000000..b59c82f46da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/t32-opacity-basic-1.0-a-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<body>
+ <p id="one">This text should be the same color as the line below.</p>
+ <p id="two">This text should be the same color as the line above.</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/t32-opacity-basic-1.0-a.xht b/tests/wpt/web-platform-tests/css/css-color/t32-opacity-basic-1.0-a.xht
index 01dc48cfa73..6d8ea9ec127 100644
--- a/tests/wpt/web-platform-tests/css/css-color/t32-opacity-basic-1.0-a.xht
+++ b/tests/wpt/web-platform-tests/css/css-color/t32-opacity-basic-1.0-a.xht
@@ -5,6 +5,7 @@
<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://www.w3.org/TR/css3-color/#transparency" />
+ <link rel="match" href="t32-opacity-basic-1.0-a-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="Opacity of 1.0 makes box fully opaque." />
<style type="text/css"><![CDATA[
diff --git a/tests/wpt/web-platform-tests/css/css-color/t32-opacity-clamping-0.0-b.xht b/tests/wpt/web-platform-tests/css/css-color/t32-opacity-clamping-0.0-b.xht
index 61687c0b036..966f7e0e7e7 100644
--- a/tests/wpt/web-platform-tests/css/css-color/t32-opacity-clamping-0.0-b.xht
+++ b/tests/wpt/web-platform-tests/css/css-color/t32-opacity-clamping-0.0-b.xht
@@ -5,6 +5,7 @@
<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://www.w3.org/TR/css3-color/#transparency" />
+ <link rel="match" href="t32-opacity-basic-0.0-a-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="Opacity values less than 0.0 are clamped to 0.0" />
<style type="text/css"><![CDATA[
diff --git a/tests/wpt/web-platform-tests/css/css-color/t32-opacity-clamping-1.0-b-ref.html b/tests/wpt/web-platform-tests/css/css-color/t32-opacity-clamping-1.0-b-ref.html
new file mode 100644
index 00000000000..08854a18aed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/t32-opacity-clamping-1.0-b-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<body>
+ <p id="one">There should be six lines of text on this page, all the same color. [1 of 6]</p>
+ <p id="two">There should be six lines of text on this page, all the same color. [2 of 6]</p>
+ <p id="three">There should be six lines of text on this page, all the same color. [3 of 6]</p>
+ <p id="four">There should be six lines of text on this page, all the same color. [4 of 6]</p>
+ <p id="five">There should be six lines of text on this page, all the same color. [5 of 6]</p>
+ <p id="six">There should be six lines of text on this page, all the same color. [6 of 6]</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/t32-opacity-clamping-1.0-b.xht b/tests/wpt/web-platform-tests/css/css-color/t32-opacity-clamping-1.0-b.xht
index 56bca60b6d3..31121cb002a 100644
--- a/tests/wpt/web-platform-tests/css/css-color/t32-opacity-clamping-1.0-b.xht
+++ b/tests/wpt/web-platform-tests/css/css-color/t32-opacity-clamping-1.0-b.xht
@@ -5,6 +5,7 @@
<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://www.w3.org/TR/css3-color/#transparency" />
+ <link rel="match" href="t32-opacity-clamping-1.0-b-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="Opacity values greater than 1.0 are clamped to 1.0" />
<style type="text/css"><![CDATA[
diff --git a/tests/wpt/web-platform-tests/css/css-color/t32-opacity-offscreen-b-ref.html b/tests/wpt/web-platform-tests/css/css-color/t32-opacity-offscreen-b-ref.html
new file mode 100644
index 00000000000..2a3ae628b29
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/t32-opacity-offscreen-b-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div { width: 5em; height: 1em; margin: 2px 0; }
+ .test { background: rgb(153, 153, 255); }
+</style>
+<body>
+ <p>The following five boxes should be the same color:</p>
+
+ <div class="test"></div>
+ <div class="test"></div>
+ <div class="test"></div>
+ <div class="test"></div>
+ <div class="test"></div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/t32-opacity-offscreen-b.xht b/tests/wpt/web-platform-tests/css/css-color/t32-opacity-offscreen-b.xht
index 2303facab8a..a373f98980e 100644
--- a/tests/wpt/web-platform-tests/css/css-color/t32-opacity-offscreen-b.xht
+++ b/tests/wpt/web-platform-tests/css/css-color/t32-opacity-offscreen-b.xht
@@ -5,6 +5,7 @@
<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://www.w3.org/TR/css3-color/#transparency" />
+ <link rel="match" href="t32-opacity-offscreen-b-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="That opacity specifies compositing the contents as a single offscreen buffer." />
<style type="text/css"><![CDATA[
diff --git a/tests/wpt/web-platform-tests/css/css-color/t32-opacity-offscreen-with-alpha-c-ref.html b/tests/wpt/web-platform-tests/css/css-color/t32-opacity-offscreen-with-alpha-c-ref.html
new file mode 100644
index 00000000000..923e4495d41
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/t32-opacity-offscreen-with-alpha-c-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ div { width: 5em; height: 1em; margin: 2px 0; }
+ .test { background: rgb(204, 204, 255); }
+</style>
+<body>
+ <p>The following four boxes should be the same color:</p>
+
+ <div class="test"></div>
+ <div class="test"></div>
+ <div class="test"></div>
+ <div class="test"></div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/t32-opacity-offscreen-with-alpha-c.xht b/tests/wpt/web-platform-tests/css/css-color/t32-opacity-offscreen-with-alpha-c.xht
index 5fa074c57b5..fdd9ae27793 100644
--- a/tests/wpt/web-platform-tests/css/css-color/t32-opacity-offscreen-with-alpha-c.xht
+++ b/tests/wpt/web-platform-tests/css/css-color/t32-opacity-offscreen-with-alpha-c.xht
@@ -5,6 +5,7 @@
<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://www.w3.org/TR/css3-color/#transparency" />
+ <link rel="match" href="t32-opacity-offscreen-with-alpha-c-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="That alpha within the offscreen buffer is composited correctly." />
<style type="text/css"><![CDATA[
diff --git a/tests/wpt/web-platform-tests/css/css-color/t41-html4-keywords-a-ref.html b/tests/wpt/web-platform-tests/css/css-color/t41-html4-keywords-a-ref.html
new file mode 100644
index 00000000000..4f95dff21cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/t41-html4-keywords-a-ref.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ html, body { background: #dddddd; color: #000000; }
+ table { border-spacing: 0; padding: 0; border: none; }
+ td { border: none; padding: 0; }
+</style>
+<body>
+ <p>Each row in the following table (except the first and last, to show where the columns are) should have two cells with the same background color. None of them should match the background of the page.</p>
+
+ <table>
+ <tr><td style="background: black">&nbsp;&nbsp;&nbsp;</td><td style="background: white">&nbsp;&nbsp;&nbsp;</td></tr>
+ <tr><td style="background: #000000" colspan=2>&nbsp;</td></tr>
+ <tr><td style="background: #008000" colspan=2>&nbsp;</td></tr>
+ <tr><td style="background: #C0C0C0" colspan=2>&nbsp;</td></tr>
+ <tr><td style="background: #00FF00" colspan=2>&nbsp;</td></tr>
+ <tr><td style="background: #808080" colspan=2>&nbsp;</td></tr>
+ <tr><td style="background: #808000" colspan=2>&nbsp;</td></tr>
+ <tr><td style="background: #FFFFFF" colspan=2>&nbsp;</td></tr>
+ <tr><td style="background: #FFFF00" colspan=2>&nbsp;</td></tr>
+ <tr><td style="background: #800000" colspan=2>&nbsp;</td></tr>
+ <tr><td style="background: #000080" colspan=2>&nbsp;</td></tr>
+ <tr><td style="background: #FF0000" colspan=2>&nbsp;</td></tr>
+ <tr><td style="background: #0000FF" colspan=2>&nbsp;</td></tr>
+ <tr><td style="background: #800080" colspan=2>&nbsp;</td></tr>
+ <tr><td style="background: #008080" colspan=2>&nbsp;</td></tr>
+ <tr><td style="background: #FF00FF" colspan=2>&nbsp;</td></tr>
+ <tr><td style="background: #00FFFF" colspan=2>&nbsp;</td></tr>
+ <tr><td style="background: white">&nbsp;&nbsp;&nbsp;</td><td style="background: black">&nbsp;&nbsp;&nbsp;</td></tr>
+ </table>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/t41-html4-keywords-a.xht b/tests/wpt/web-platform-tests/css/css-color/t41-html4-keywords-a.xht
index 1862f827d30..3a3e332ed56 100644
--- a/tests/wpt/web-platform-tests/css/css-color/t41-html4-keywords-a.xht
+++ b/tests/wpt/web-platform-tests/css/css-color/t41-html4-keywords-a.xht
@@ -5,6 +5,7 @@
<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://www.w3.org/TR/css3-color/#html4" />
+ <link rel="match" href="t41-html4-keywords-a-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="Test that the HTML4 color keywords have the correct values." />
<style type="text/css"><![CDATA[
diff --git a/tests/wpt/web-platform-tests/css/css-color/t421-rgb-clip-outside-gamut-b-ref.html b/tests/wpt/web-platform-tests/css/css-color/t421-rgb-clip-outside-gamut-b-ref.html
new file mode 100644
index 00000000000..81bbc51c30c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/t421-rgb-clip-outside-gamut-b-ref.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ table { border-spacing: 0 2px; padding: 0; border: none; }
+ td { border: none; padding: 0; height: 1.2em; }
+</style>
+<body>
+ <p><strong>WARNING: This test assumes that the device gamut is sRGB
+ (as it will be for many CRT monitors).</strong></p>
+ <p>Every row in this table should have both columns the same color:</p>
+ <table>
+ <tr>
+ <th style="background:white; color: black">Column 1</th>
+ <th style="background:black; color: white">Column 2</th>
+ </tr>
+ <tr>
+ <td colspan='2' style="background: rgb(0, 255, 0)">&nbsp;</td>
+ </tr>
+ <tr>
+ <td colspan='2' style="background: rgb(0, 0, 255)">&nbsp;</td>
+ </tr>
+ <tr>
+ <td colspan='2' style="background: rgb(0, 255, 0)">&nbsp;</td>
+ </tr>
+ <tr>
+ <td colspan='2' style="background: rgb(0, 255, 0)">&nbsp;</td>
+ </tr>
+ <tr>
+ <td colspan='2' style="background: rgb(0, 255, 0)">&nbsp;</td>
+ </tr>
+ <tr>
+ <td colspan='2' style="background: rgb(0, 255, 0)">&nbsp;</td>
+ </tr>
+ <tr>
+ <td colspan='2' style="background: rgb(50, 0, 255)">&nbsp;</td>
+ </tr>
+ <tr>
+ <td colspan='2' style="background: rgb(0, 50, 255)">&nbsp;</td>
+ </tr>
+ </table>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/t421-rgb-clip-outside-gamut-b.xht b/tests/wpt/web-platform-tests/css/css-color/t421-rgb-clip-outside-gamut-b.xht
index 5e00ea63379..1fd50ff3493 100644
--- a/tests/wpt/web-platform-tests/css/css-color/t421-rgb-clip-outside-gamut-b.xht
+++ b/tests/wpt/web-platform-tests/css/css-color/t421-rgb-clip-outside-gamut-b.xht
@@ -5,6 +5,7 @@
<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://www.w3.org/TR/css3-color/#rgb-color" />
+ <link rel="match" href="t421-rgb-clip-outside-gamut-b-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="Test clipping of rgb() values outside the device gamut." />
<style type="text/css"><![CDATA[
diff --git a/tests/wpt/web-platform-tests/css/css-color/t421-rgb-hex3-expand-b-ref.html b/tests/wpt/web-platform-tests/css/css-color/t421-rgb-hex3-expand-b-ref.html
new file mode 100644
index 00000000000..842ead1c0b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/t421-rgb-hex3-expand-b-ref.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ table { border-spacing: 0; padding: 0; border: none; }
+ td { border: none; padding: 0; width: 1.2em; height: 1.2em; }
+</style>
+<body>
+ <p>The left and right cells in each row of the following table should be the <em>same</em> color.</p>
+
+ <table>
+ <tr><td style="background: #ee9922">&nbsp;</td><td style="background: #ee9922">&nbsp;</td></tr>
+ <tr><td style="background: #ffbb00">&nbsp;</td><td style="background: #ffbb00">&nbsp;</td></tr>
+ <tr><td style="background: #338811">&nbsp;</td><td style="background: #338811">&nbsp;</td></tr>
+ </table>
+
+ <p>The left and right cells in each row of the following table should be slightly <em>different</em> colors. The right side should be slightly darker than the left.</p>
+
+ <table>
+ <tr><td style="background: #e09020">&nbsp;</td><td style="background: #e09020">&nbsp;</td></tr>
+ <tr><td style="background: #f0b000">&nbsp;</td><td style="background: #f0b000">&nbsp;</td></tr>
+ <tr><td style="background: #308010">&nbsp;</td><td style="background: #308010">&nbsp;</td></tr>
+ </table>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/t421-rgb-values-meaning-b-ref.html b/tests/wpt/web-platform-tests/css/css-color/t421-rgb-values-meaning-b-ref.html
new file mode 100644
index 00000000000..b468f0eb988
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/t421-rgb-values-meaning-b-ref.html
@@ -0,0 +1,1539 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ table { border-spacing: 0; padding: 0; border: none; }
+ td { border: none; padding: 0; }
+ td { width: 1.2em; height: 1.2em; }
+</style>
+<body>
+ <p>The following table should have four matching rows gradually changing from red at the left to black at the right (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #ff0000">&nbsp;</td>
+ <td style="background: #ee0000">&nbsp;</td>
+ <td style="background: #dd0000">&nbsp;</td>
+ <td style="background: #cc0000">&nbsp;</td>
+ <td style="background: #bb0000">&nbsp;</td>
+ <td style="background: #aa0000">&nbsp;</td>
+ <td style="background: #990000">&nbsp;</td>
+ <td style="background: #880000">&nbsp;</td>
+ <td style="background: #770000">&nbsp;</td>
+ <td style="background: #660000">&nbsp;</td>
+ <td style="background: #550000">&nbsp;</td>
+ <td style="background: #440000">&nbsp;</td>
+ <td style="background: #330000">&nbsp;</td>
+ <td style="background: #220000">&nbsp;</td>
+ <td style="background: #110000">&nbsp;</td>
+ <td style="background: #000000">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #ff0000">&nbsp;</td>
+ <td style="background: #ee0000">&nbsp;</td>
+ <td style="background: #dd0000">&nbsp;</td>
+ <td style="background: #cc0000">&nbsp;</td>
+ <td style="background: #bb0000">&nbsp;</td>
+ <td style="background: #aa0000">&nbsp;</td>
+ <td style="background: #990000">&nbsp;</td>
+ <td style="background: #880000">&nbsp;</td>
+ <td style="background: #770000">&nbsp;</td>
+ <td style="background: #660000">&nbsp;</td>
+ <td style="background: #550000">&nbsp;</td>
+ <td style="background: #440000">&nbsp;</td>
+ <td style="background: #330000">&nbsp;</td>
+ <td style="background: #220000">&nbsp;</td>
+ <td style="background: #110000">&nbsp;</td>
+ <td style="background: #000000">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #ff0000">&nbsp;</td>
+ <td style="background: #ee0000">&nbsp;</td>
+ <td style="background: #dd0000">&nbsp;</td>
+ <td style="background: #cc0000">&nbsp;</td>
+ <td style="background: #bb0000">&nbsp;</td>
+ <td style="background: #aa0000">&nbsp;</td>
+ <td style="background: #990000">&nbsp;</td>
+ <td style="background: #880000">&nbsp;</td>
+ <td style="background: #770000">&nbsp;</td>
+ <td style="background: #660000">&nbsp;</td>
+ <td style="background: #550000">&nbsp;</td>
+ <td style="background: #440000">&nbsp;</td>
+ <td style="background: #330000">&nbsp;</td>
+ <td style="background: #220000">&nbsp;</td>
+ <td style="background: #110000">&nbsp;</td>
+ <td style="background: #000000">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #ff0000">&nbsp;</td>
+ <td style="background: #ee0000">&nbsp;</td>
+ <td style="background: #dd0000">&nbsp;</td>
+ <td style="background: #cc0000">&nbsp;</td>
+ <td style="background: #bb0000">&nbsp;</td>
+ <td style="background: #aa0000">&nbsp;</td>
+ <td style="background: #990000">&nbsp;</td>
+ <td style="background: #880000">&nbsp;</td>
+ <td style="background: #770000">&nbsp;</td>
+ <td style="background: #660000">&nbsp;</td>
+ <td style="background: #550000">&nbsp;</td>
+ <td style="background: #440000">&nbsp;</td>
+ <td style="background: #330000">&nbsp;</td>
+ <td style="background: #220000">&nbsp;</td>
+ <td style="background: #110000">&nbsp;</td>
+ <td style="background: #000000">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+
+ <p>The following table should have four matching rows gradually changing from white at the left to red at the right (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #ffffff">&nbsp;</td>
+ <td style="background: #ffeeee">&nbsp;</td>
+ <td style="background: #ffdddd">&nbsp;</td>
+ <td style="background: #ffcccc">&nbsp;</td>
+ <td style="background: #ffbbbb">&nbsp;</td>
+ <td style="background: #ffaaaa">&nbsp;</td>
+ <td style="background: #ff9999">&nbsp;</td>
+ <td style="background: #ff8888">&nbsp;</td>
+ <td style="background: #ff7777">&nbsp;</td>
+ <td style="background: #ff6666">&nbsp;</td>
+ <td style="background: #ff5555">&nbsp;</td>
+ <td style="background: #ff4444">&nbsp;</td>
+ <td style="background: #ff3333">&nbsp;</td>
+ <td style="background: #ff2222">&nbsp;</td>
+ <td style="background: #ff1111">&nbsp;</td>
+ <td style="background: #ff0000">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #ffffff">&nbsp;</td>
+ <td style="background: #ffeeee">&nbsp;</td>
+ <td style="background: #ffdddd">&nbsp;</td>
+ <td style="background: #ffcccc">&nbsp;</td>
+ <td style="background: #ffbbbb">&nbsp;</td>
+ <td style="background: #ffaaaa">&nbsp;</td>
+ <td style="background: #ff9999">&nbsp;</td>
+ <td style="background: #ff8888">&nbsp;</td>
+ <td style="background: #ff7777">&nbsp;</td>
+ <td style="background: #ff6666">&nbsp;</td>
+ <td style="background: #ff5555">&nbsp;</td>
+ <td style="background: #ff4444">&nbsp;</td>
+ <td style="background: #ff3333">&nbsp;</td>
+ <td style="background: #ff2222">&nbsp;</td>
+ <td style="background: #ff1111">&nbsp;</td>
+ <td style="background: #ff0000">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #ffffff">&nbsp;</td>
+ <td style="background: #ffeeee">&nbsp;</td>
+ <td style="background: #ffdddd">&nbsp;</td>
+ <td style="background: #ffcccc">&nbsp;</td>
+ <td style="background: #ffbbbb">&nbsp;</td>
+ <td style="background: #ffaaaa">&nbsp;</td>
+ <td style="background: #ff9999">&nbsp;</td>
+ <td style="background: #ff8888">&nbsp;</td>
+ <td style="background: #ff7777">&nbsp;</td>
+ <td style="background: #ff6666">&nbsp;</td>
+ <td style="background: #ff5555">&nbsp;</td>
+ <td style="background: #ff4444">&nbsp;</td>
+ <td style="background: #ff3333">&nbsp;</td>
+ <td style="background: #ff2222">&nbsp;</td>
+ <td style="background: #ff1111">&nbsp;</td>
+ <td style="background: #ff0000">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #ffffff">&nbsp;</td>
+ <td style="background: #ffeeee">&nbsp;</td>
+ <td style="background: #ffdddd">&nbsp;</td>
+ <td style="background: #ffcccc">&nbsp;</td>
+ <td style="background: #ffbbbb">&nbsp;</td>
+ <td style="background: #ffaaaa">&nbsp;</td>
+ <td style="background: #ff9999">&nbsp;</td>
+ <td style="background: #ff8888">&nbsp;</td>
+ <td style="background: #ff7777">&nbsp;</td>
+ <td style="background: #ff6666">&nbsp;</td>
+ <td style="background: #ff5555">&nbsp;</td>
+ <td style="background: #ff4444">&nbsp;</td>
+ <td style="background: #ff3333">&nbsp;</td>
+ <td style="background: #ff2222">&nbsp;</td>
+ <td style="background: #ff1111">&nbsp;</td>
+ <td style="background: #ff0000">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+
+ <p>The following table should have four matching rows gradually changing from green at the left to black at the right (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #00ff00">&nbsp;</td>
+ <td style="background: #00ee00">&nbsp;</td>
+ <td style="background: #00dd00">&nbsp;</td>
+ <td style="background: #00cc00">&nbsp;</td>
+ <td style="background: #00bb00">&nbsp;</td>
+ <td style="background: #00aa00">&nbsp;</td>
+ <td style="background: #009900">&nbsp;</td>
+ <td style="background: #008800">&nbsp;</td>
+ <td style="background: #007700">&nbsp;</td>
+ <td style="background: #006600">&nbsp;</td>
+ <td style="background: #005500">&nbsp;</td>
+ <td style="background: #004400">&nbsp;</td>
+ <td style="background: #003300">&nbsp;</td>
+ <td style="background: #002200">&nbsp;</td>
+ <td style="background: #001100">&nbsp;</td>
+ <td style="background: #000000">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #00ff00">&nbsp;</td>
+ <td style="background: #00ee00">&nbsp;</td>
+ <td style="background: #00dd00">&nbsp;</td>
+ <td style="background: #00cc00">&nbsp;</td>
+ <td style="background: #00bb00">&nbsp;</td>
+ <td style="background: #00aa00">&nbsp;</td>
+ <td style="background: #009900">&nbsp;</td>
+ <td style="background: #008800">&nbsp;</td>
+ <td style="background: #007700">&nbsp;</td>
+ <td style="background: #006600">&nbsp;</td>
+ <td style="background: #005500">&nbsp;</td>
+ <td style="background: #004400">&nbsp;</td>
+ <td style="background: #003300">&nbsp;</td>
+ <td style="background: #002200">&nbsp;</td>
+ <td style="background: #001100">&nbsp;</td>
+ <td style="background: #000000">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #00ff00">&nbsp;</td>
+ <td style="background: #00ee00">&nbsp;</td>
+ <td style="background: #00dd00">&nbsp;</td>
+ <td style="background: #00cc00">&nbsp;</td>
+ <td style="background: #00bb00">&nbsp;</td>
+ <td style="background: #00aa00">&nbsp;</td>
+ <td style="background: #009900">&nbsp;</td>
+ <td style="background: #008800">&nbsp;</td>
+ <td style="background: #007700">&nbsp;</td>
+ <td style="background: #006600">&nbsp;</td>
+ <td style="background: #005500">&nbsp;</td>
+ <td style="background: #004400">&nbsp;</td>
+ <td style="background: #003300">&nbsp;</td>
+ <td style="background: #002200">&nbsp;</td>
+ <td style="background: #001100">&nbsp;</td>
+ <td style="background: #000000">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #00ff00">&nbsp;</td>
+ <td style="background: #00ee00">&nbsp;</td>
+ <td style="background: #00dd00">&nbsp;</td>
+ <td style="background: #00cc00">&nbsp;</td>
+ <td style="background: #00bb00">&nbsp;</td>
+ <td style="background: #00aa00">&nbsp;</td>
+ <td style="background: #009900">&nbsp;</td>
+ <td style="background: #008800">&nbsp;</td>
+ <td style="background: #007700">&nbsp;</td>
+ <td style="background: #006600">&nbsp;</td>
+ <td style="background: #005500">&nbsp;</td>
+ <td style="background: #004400">&nbsp;</td>
+ <td style="background: #003300">&nbsp;</td>
+ <td style="background: #002200">&nbsp;</td>
+ <td style="background: #001100">&nbsp;</td>
+ <td style="background: #000000">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+
+ <p>The following table should have four matching rows gradually changing from white at the left to green at the right (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #ffffff">&nbsp;</td>
+ <td style="background: #eeffee">&nbsp;</td>
+ <td style="background: #ddffdd">&nbsp;</td>
+ <td style="background: #ccffcc">&nbsp;</td>
+ <td style="background: #bbffbb">&nbsp;</td>
+ <td style="background: #aaffaa">&nbsp;</td>
+ <td style="background: #99ff99">&nbsp;</td>
+ <td style="background: #88ff88">&nbsp;</td>
+ <td style="background: #77ff77">&nbsp;</td>
+ <td style="background: #66ff66">&nbsp;</td>
+ <td style="background: #55ff55">&nbsp;</td>
+ <td style="background: #44ff44">&nbsp;</td>
+ <td style="background: #33ff33">&nbsp;</td>
+ <td style="background: #22ff22">&nbsp;</td>
+ <td style="background: #11ff11">&nbsp;</td>
+ <td style="background: #00ff00">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #ffffff">&nbsp;</td>
+ <td style="background: #eeffee">&nbsp;</td>
+ <td style="background: #ddffdd">&nbsp;</td>
+ <td style="background: #ccffcc">&nbsp;</td>
+ <td style="background: #bbffbb">&nbsp;</td>
+ <td style="background: #aaffaa">&nbsp;</td>
+ <td style="background: #99ff99">&nbsp;</td>
+ <td style="background: #88ff88">&nbsp;</td>
+ <td style="background: #77ff77">&nbsp;</td>
+ <td style="background: #66ff66">&nbsp;</td>
+ <td style="background: #55ff55">&nbsp;</td>
+ <td style="background: #44ff44">&nbsp;</td>
+ <td style="background: #33ff33">&nbsp;</td>
+ <td style="background: #22ff22">&nbsp;</td>
+ <td style="background: #11ff11">&nbsp;</td>
+ <td style="background: #00ff00">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #ffffff">&nbsp;</td>
+ <td style="background: #eeffee">&nbsp;</td>
+ <td style="background: #ddffdd">&nbsp;</td>
+ <td style="background: #ccffcc">&nbsp;</td>
+ <td style="background: #bbffbb">&nbsp;</td>
+ <td style="background: #aaffaa">&nbsp;</td>
+ <td style="background: #99ff99">&nbsp;</td>
+ <td style="background: #88ff88">&nbsp;</td>
+ <td style="background: #77ff77">&nbsp;</td>
+ <td style="background: #66ff66">&nbsp;</td>
+ <td style="background: #55ff55">&nbsp;</td>
+ <td style="background: #44ff44">&nbsp;</td>
+ <td style="background: #33ff33">&nbsp;</td>
+ <td style="background: #22ff22">&nbsp;</td>
+ <td style="background: #11ff11">&nbsp;</td>
+ <td style="background: #00ff00">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #ffffff">&nbsp;</td>
+ <td style="background: #eeffee">&nbsp;</td>
+ <td style="background: #ddffdd">&nbsp;</td>
+ <td style="background: #ccffcc">&nbsp;</td>
+ <td style="background: #bbffbb">&nbsp;</td>
+ <td style="background: #aaffaa">&nbsp;</td>
+ <td style="background: #99ff99">&nbsp;</td>
+ <td style="background: #88ff88">&nbsp;</td>
+ <td style="background: #77ff77">&nbsp;</td>
+ <td style="background: #66ff66">&nbsp;</td>
+ <td style="background: #55ff55">&nbsp;</td>
+ <td style="background: #44ff44">&nbsp;</td>
+ <td style="background: #33ff33">&nbsp;</td>
+ <td style="background: #22ff22">&nbsp;</td>
+ <td style="background: #11ff11">&nbsp;</td>
+ <td style="background: #00ff00">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+
+ <p>The following table should have four matching rows gradually changing from blue at the left to black at the right (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #0000ff">&nbsp;</td>
+ <td style="background: #0000ee">&nbsp;</td>
+ <td style="background: #0000dd">&nbsp;</td>
+ <td style="background: #0000cc">&nbsp;</td>
+ <td style="background: #0000bb">&nbsp;</td>
+ <td style="background: #0000aa">&nbsp;</td>
+ <td style="background: #000099">&nbsp;</td>
+ <td style="background: #000088">&nbsp;</td>
+ <td style="background: #000077">&nbsp;</td>
+ <td style="background: #000066">&nbsp;</td>
+ <td style="background: #000055">&nbsp;</td>
+ <td style="background: #000044">&nbsp;</td>
+ <td style="background: #000033">&nbsp;</td>
+ <td style="background: #000022">&nbsp;</td>
+ <td style="background: #000011">&nbsp;</td>
+ <td style="background: #000000">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #0000ff">&nbsp;</td>
+ <td style="background: #0000ee">&nbsp;</td>
+ <td style="background: #0000dd">&nbsp;</td>
+ <td style="background: #0000cc">&nbsp;</td>
+ <td style="background: #0000bb">&nbsp;</td>
+ <td style="background: #0000aa">&nbsp;</td>
+ <td style="background: #000099">&nbsp;</td>
+ <td style="background: #000088">&nbsp;</td>
+ <td style="background: #000077">&nbsp;</td>
+ <td style="background: #000066">&nbsp;</td>
+ <td style="background: #000055">&nbsp;</td>
+ <td style="background: #000044">&nbsp;</td>
+ <td style="background: #000033">&nbsp;</td>
+ <td style="background: #000022">&nbsp;</td>
+ <td style="background: #000011">&nbsp;</td>
+ <td style="background: #000000">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #0000ff">&nbsp;</td>
+ <td style="background: #0000ee">&nbsp;</td>
+ <td style="background: #0000dd">&nbsp;</td>
+ <td style="background: #0000cc">&nbsp;</td>
+ <td style="background: #0000bb">&nbsp;</td>
+ <td style="background: #0000aa">&nbsp;</td>
+ <td style="background: #000099">&nbsp;</td>
+ <td style="background: #000088">&nbsp;</td>
+ <td style="background: #000077">&nbsp;</td>
+ <td style="background: #000066">&nbsp;</td>
+ <td style="background: #000055">&nbsp;</td>
+ <td style="background: #000044">&nbsp;</td>
+ <td style="background: #000033">&nbsp;</td>
+ <td style="background: #000022">&nbsp;</td>
+ <td style="background: #000011">&nbsp;</td>
+ <td style="background: #000000">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #0000ff">&nbsp;</td>
+ <td style="background: #0000ee">&nbsp;</td>
+ <td style="background: #0000dd">&nbsp;</td>
+ <td style="background: #0000cc">&nbsp;</td>
+ <td style="background: #0000bb">&nbsp;</td>
+ <td style="background: #0000aa">&nbsp;</td>
+ <td style="background: #000099">&nbsp;</td>
+ <td style="background: #000088">&nbsp;</td>
+ <td style="background: #000077">&nbsp;</td>
+ <td style="background: #000066">&nbsp;</td>
+ <td style="background: #000055">&nbsp;</td>
+ <td style="background: #000044">&nbsp;</td>
+ <td style="background: #000033">&nbsp;</td>
+ <td style="background: #000022">&nbsp;</td>
+ <td style="background: #000011">&nbsp;</td>
+ <td style="background: #000000">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+
+ <p>The following table should have four matching rows gradually changing from white at the left to blue at the right (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #ffffff">&nbsp;</td>
+ <td style="background: #eeeeff">&nbsp;</td>
+ <td style="background: #ddddff">&nbsp;</td>
+ <td style="background: #ccccff">&nbsp;</td>
+ <td style="background: #bbbbff">&nbsp;</td>
+ <td style="background: #aaaaff">&nbsp;</td>
+ <td style="background: #9999ff">&nbsp;</td>
+ <td style="background: #8888ff">&nbsp;</td>
+ <td style="background: #7777ff">&nbsp;</td>
+ <td style="background: #6666ff">&nbsp;</td>
+ <td style="background: #5555ff">&nbsp;</td>
+ <td style="background: #4444ff">&nbsp;</td>
+ <td style="background: #3333ff">&nbsp;</td>
+ <td style="background: #2222ff">&nbsp;</td>
+ <td style="background: #1111ff">&nbsp;</td>
+ <td style="background: #0000ff">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #ffffff">&nbsp;</td>
+ <td style="background: #eeeeff">&nbsp;</td>
+ <td style="background: #ddddff">&nbsp;</td>
+ <td style="background: #ccccff">&nbsp;</td>
+ <td style="background: #bbbbff">&nbsp;</td>
+ <td style="background: #aaaaff">&nbsp;</td>
+ <td style="background: #9999ff">&nbsp;</td>
+ <td style="background: #8888ff">&nbsp;</td>
+ <td style="background: #7777ff">&nbsp;</td>
+ <td style="background: #6666ff">&nbsp;</td>
+ <td style="background: #5555ff">&nbsp;</td>
+ <td style="background: #4444ff">&nbsp;</td>
+ <td style="background: #3333ff">&nbsp;</td>
+ <td style="background: #2222ff">&nbsp;</td>
+ <td style="background: #1111ff">&nbsp;</td>
+ <td style="background: #0000ff">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #ffffff">&nbsp;</td>
+ <td style="background: #eeeeff">&nbsp;</td>
+ <td style="background: #ddddff">&nbsp;</td>
+ <td style="background: #ccccff">&nbsp;</td>
+ <td style="background: #bbbbff">&nbsp;</td>
+ <td style="background: #aaaaff">&nbsp;</td>
+ <td style="background: #9999ff">&nbsp;</td>
+ <td style="background: #8888ff">&nbsp;</td>
+ <td style="background: #7777ff">&nbsp;</td>
+ <td style="background: #6666ff">&nbsp;</td>
+ <td style="background: #5555ff">&nbsp;</td>
+ <td style="background: #4444ff">&nbsp;</td>
+ <td style="background: #3333ff">&nbsp;</td>
+ <td style="background: #2222ff">&nbsp;</td>
+ <td style="background: #1111ff">&nbsp;</td>
+ <td style="background: #0000ff">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #ffffff">&nbsp;</td>
+ <td style="background: #eeeeff">&nbsp;</td>
+ <td style="background: #ddddff">&nbsp;</td>
+ <td style="background: #ccccff">&nbsp;</td>
+ <td style="background: #bbbbff">&nbsp;</td>
+ <td style="background: #aaaaff">&nbsp;</td>
+ <td style="background: #9999ff">&nbsp;</td>
+ <td style="background: #8888ff">&nbsp;</td>
+ <td style="background: #7777ff">&nbsp;</td>
+ <td style="background: #6666ff">&nbsp;</td>
+ <td style="background: #5555ff">&nbsp;</td>
+ <td style="background: #4444ff">&nbsp;</td>
+ <td style="background: #3333ff">&nbsp;</td>
+ <td style="background: #2222ff">&nbsp;</td>
+ <td style="background: #1111ff">&nbsp;</td>
+ <td style="background: #0000ff">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+
+ <p>The following table should have four matching rows gradually changing from yellow at the left to black at the right (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #ffff00">&nbsp;</td>
+ <td style="background: #eeee00">&nbsp;</td>
+ <td style="background: #dddd00">&nbsp;</td>
+ <td style="background: #cccc00">&nbsp;</td>
+ <td style="background: #bbbb00">&nbsp;</td>
+ <td style="background: #aaaa00">&nbsp;</td>
+ <td style="background: #999900">&nbsp;</td>
+ <td style="background: #888800">&nbsp;</td>
+ <td style="background: #777700">&nbsp;</td>
+ <td style="background: #666600">&nbsp;</td>
+ <td style="background: #555500">&nbsp;</td>
+ <td style="background: #444400">&nbsp;</td>
+ <td style="background: #333300">&nbsp;</td>
+ <td style="background: #222200">&nbsp;</td>
+ <td style="background: #111100">&nbsp;</td>
+ <td style="background: #000000">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #ffff00">&nbsp;</td>
+ <td style="background: #eeee00">&nbsp;</td>
+ <td style="background: #dddd00">&nbsp;</td>
+ <td style="background: #cccc00">&nbsp;</td>
+ <td style="background: #bbbb00">&nbsp;</td>
+ <td style="background: #aaaa00">&nbsp;</td>
+ <td style="background: #999900">&nbsp;</td>
+ <td style="background: #888800">&nbsp;</td>
+ <td style="background: #777700">&nbsp;</td>
+ <td style="background: #666600">&nbsp;</td>
+ <td style="background: #555500">&nbsp;</td>
+ <td style="background: #444400">&nbsp;</td>
+ <td style="background: #333300">&nbsp;</td>
+ <td style="background: #222200">&nbsp;</td>
+ <td style="background: #111100">&nbsp;</td>
+ <td style="background: #000000">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #ffff00">&nbsp;</td>
+ <td style="background: #eeee00">&nbsp;</td>
+ <td style="background: #dddd00">&nbsp;</td>
+ <td style="background: #cccc00">&nbsp;</td>
+ <td style="background: #bbbb00">&nbsp;</td>
+ <td style="background: #aaaa00">&nbsp;</td>
+ <td style="background: #999900">&nbsp;</td>
+ <td style="background: #888800">&nbsp;</td>
+ <td style="background: #777700">&nbsp;</td>
+ <td style="background: #666600">&nbsp;</td>
+ <td style="background: #555500">&nbsp;</td>
+ <td style="background: #444400">&nbsp;</td>
+ <td style="background: #333300">&nbsp;</td>
+ <td style="background: #222200">&nbsp;</td>
+ <td style="background: #111100">&nbsp;</td>
+ <td style="background: #000000">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #ffff00">&nbsp;</td>
+ <td style="background: #eeee00">&nbsp;</td>
+ <td style="background: #dddd00">&nbsp;</td>
+ <td style="background: #cccc00">&nbsp;</td>
+ <td style="background: #bbbb00">&nbsp;</td>
+ <td style="background: #aaaa00">&nbsp;</td>
+ <td style="background: #999900">&nbsp;</td>
+ <td style="background: #888800">&nbsp;</td>
+ <td style="background: #777700">&nbsp;</td>
+ <td style="background: #666600">&nbsp;</td>
+ <td style="background: #555500">&nbsp;</td>
+ <td style="background: #444400">&nbsp;</td>
+ <td style="background: #333300">&nbsp;</td>
+ <td style="background: #222200">&nbsp;</td>
+ <td style="background: #111100">&nbsp;</td>
+ <td style="background: #000000">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+
+ <p>The following table should have four matching rows gradually changing from white at the left to yellow at the right (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #ffffff">&nbsp;</td>
+ <td style="background: #ffffee">&nbsp;</td>
+ <td style="background: #ffffdd">&nbsp;</td>
+ <td style="background: #ffffcc">&nbsp;</td>
+ <td style="background: #ffffbb">&nbsp;</td>
+ <td style="background: #ffffaa">&nbsp;</td>
+ <td style="background: #ffff99">&nbsp;</td>
+ <td style="background: #ffff88">&nbsp;</td>
+ <td style="background: #ffff77">&nbsp;</td>
+ <td style="background: #ffff66">&nbsp;</td>
+ <td style="background: #ffff55">&nbsp;</td>
+ <td style="background: #ffff44">&nbsp;</td>
+ <td style="background: #ffff33">&nbsp;</td>
+ <td style="background: #ffff22">&nbsp;</td>
+ <td style="background: #ffff11">&nbsp;</td>
+ <td style="background: #ffff00">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #ffffff">&nbsp;</td>
+ <td style="background: #ffffee">&nbsp;</td>
+ <td style="background: #ffffdd">&nbsp;</td>
+ <td style="background: #ffffcc">&nbsp;</td>
+ <td style="background: #ffffbb">&nbsp;</td>
+ <td style="background: #ffffaa">&nbsp;</td>
+ <td style="background: #ffff99">&nbsp;</td>
+ <td style="background: #ffff88">&nbsp;</td>
+ <td style="background: #ffff77">&nbsp;</td>
+ <td style="background: #ffff66">&nbsp;</td>
+ <td style="background: #ffff55">&nbsp;</td>
+ <td style="background: #ffff44">&nbsp;</td>
+ <td style="background: #ffff33">&nbsp;</td>
+ <td style="background: #ffff22">&nbsp;</td>
+ <td style="background: #ffff11">&nbsp;</td>
+ <td style="background: #ffff00">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #ffffff">&nbsp;</td>
+ <td style="background: #ffffee">&nbsp;</td>
+ <td style="background: #ffffdd">&nbsp;</td>
+ <td style="background: #ffffcc">&nbsp;</td>
+ <td style="background: #ffffbb">&nbsp;</td>
+ <td style="background: #ffffaa">&nbsp;</td>
+ <td style="background: #ffff99">&nbsp;</td>
+ <td style="background: #ffff88">&nbsp;</td>
+ <td style="background: #ffff77">&nbsp;</td>
+ <td style="background: #ffff66">&nbsp;</td>
+ <td style="background: #ffff55">&nbsp;</td>
+ <td style="background: #ffff44">&nbsp;</td>
+ <td style="background: #ffff33">&nbsp;</td>
+ <td style="background: #ffff22">&nbsp;</td>
+ <td style="background: #ffff11">&nbsp;</td>
+ <td style="background: #ffff00">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #ffffff">&nbsp;</td>
+ <td style="background: #ffffee">&nbsp;</td>
+ <td style="background: #ffffdd">&nbsp;</td>
+ <td style="background: #ffffcc">&nbsp;</td>
+ <td style="background: #ffffbb">&nbsp;</td>
+ <td style="background: #ffffaa">&nbsp;</td>
+ <td style="background: #ffff99">&nbsp;</td>
+ <td style="background: #ffff88">&nbsp;</td>
+ <td style="background: #ffff77">&nbsp;</td>
+ <td style="background: #ffff66">&nbsp;</td>
+ <td style="background: #ffff55">&nbsp;</td>
+ <td style="background: #ffff44">&nbsp;</td>
+ <td style="background: #ffff33">&nbsp;</td>
+ <td style="background: #ffff22">&nbsp;</td>
+ <td style="background: #ffff11">&nbsp;</td>
+ <td style="background: #ffff00">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+
+ <p>The following table should have four matching rows gradually changing from fuchsia at the left to black at the right (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #ff00ff">&nbsp;</td>
+ <td style="background: #ee00ee">&nbsp;</td>
+ <td style="background: #dd00dd">&nbsp;</td>
+ <td style="background: #cc00cc">&nbsp;</td>
+ <td style="background: #bb00bb">&nbsp;</td>
+ <td style="background: #aa00aa">&nbsp;</td>
+ <td style="background: #990099">&nbsp;</td>
+ <td style="background: #880088">&nbsp;</td>
+ <td style="background: #770077">&nbsp;</td>
+ <td style="background: #660066">&nbsp;</td>
+ <td style="background: #550055">&nbsp;</td>
+ <td style="background: #440044">&nbsp;</td>
+ <td style="background: #330033">&nbsp;</td>
+ <td style="background: #220022">&nbsp;</td>
+ <td style="background: #110011">&nbsp;</td>
+ <td style="background: #000000">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #ff00ff">&nbsp;</td>
+ <td style="background: #ee00ee">&nbsp;</td>
+ <td style="background: #dd00dd">&nbsp;</td>
+ <td style="background: #cc00cc">&nbsp;</td>
+ <td style="background: #bb00bb">&nbsp;</td>
+ <td style="background: #aa00aa">&nbsp;</td>
+ <td style="background: #990099">&nbsp;</td>
+ <td style="background: #880088">&nbsp;</td>
+ <td style="background: #770077">&nbsp;</td>
+ <td style="background: #660066">&nbsp;</td>
+ <td style="background: #550055">&nbsp;</td>
+ <td style="background: #440044">&nbsp;</td>
+ <td style="background: #330033">&nbsp;</td>
+ <td style="background: #220022">&nbsp;</td>
+ <td style="background: #110011">&nbsp;</td>
+ <td style="background: #000000">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #ff00ff">&nbsp;</td>
+ <td style="background: #ee00ee">&nbsp;</td>
+ <td style="background: #dd00dd">&nbsp;</td>
+ <td style="background: #cc00cc">&nbsp;</td>
+ <td style="background: #bb00bb">&nbsp;</td>
+ <td style="background: #aa00aa">&nbsp;</td>
+ <td style="background: #990099">&nbsp;</td>
+ <td style="background: #880088">&nbsp;</td>
+ <td style="background: #770077">&nbsp;</td>
+ <td style="background: #660066">&nbsp;</td>
+ <td style="background: #550055">&nbsp;</td>
+ <td style="background: #440044">&nbsp;</td>
+ <td style="background: #330033">&nbsp;</td>
+ <td style="background: #220022">&nbsp;</td>
+ <td style="background: #110011">&nbsp;</td>
+ <td style="background: #000000">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #ff00ff">&nbsp;</td>
+ <td style="background: #ee00ee">&nbsp;</td>
+ <td style="background: #dd00dd">&nbsp;</td>
+ <td style="background: #cc00cc">&nbsp;</td>
+ <td style="background: #bb00bb">&nbsp;</td>
+ <td style="background: #aa00aa">&nbsp;</td>
+ <td style="background: #990099">&nbsp;</td>
+ <td style="background: #880088">&nbsp;</td>
+ <td style="background: #770077">&nbsp;</td>
+ <td style="background: #660066">&nbsp;</td>
+ <td style="background: #550055">&nbsp;</td>
+ <td style="background: #440044">&nbsp;</td>
+ <td style="background: #330033">&nbsp;</td>
+ <td style="background: #220022">&nbsp;</td>
+ <td style="background: #110011">&nbsp;</td>
+ <td style="background: #000000">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+
+ <p>The following table should have four matching rows gradually changing from white at the left to fuchsia at the right (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #ffffff">&nbsp;</td>
+ <td style="background: #ffeeff">&nbsp;</td>
+ <td style="background: #ffddff">&nbsp;</td>
+ <td style="background: #ffccff">&nbsp;</td>
+ <td style="background: #ffbbff">&nbsp;</td>
+ <td style="background: #ffaaff">&nbsp;</td>
+ <td style="background: #ff99ff">&nbsp;</td>
+ <td style="background: #ff88ff">&nbsp;</td>
+ <td style="background: #ff77ff">&nbsp;</td>
+ <td style="background: #ff66ff">&nbsp;</td>
+ <td style="background: #ff55ff">&nbsp;</td>
+ <td style="background: #ff44ff">&nbsp;</td>
+ <td style="background: #ff33ff">&nbsp;</td>
+ <td style="background: #ff22ff">&nbsp;</td>
+ <td style="background: #ff11ff">&nbsp;</td>
+ <td style="background: #ff00ff">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #ffffff">&nbsp;</td>
+ <td style="background: #ffeeff">&nbsp;</td>
+ <td style="background: #ffddff">&nbsp;</td>
+ <td style="background: #ffccff">&nbsp;</td>
+ <td style="background: #ffbbff">&nbsp;</td>
+ <td style="background: #ffaaff">&nbsp;</td>
+ <td style="background: #ff99ff">&nbsp;</td>
+ <td style="background: #ff88ff">&nbsp;</td>
+ <td style="background: #ff77ff">&nbsp;</td>
+ <td style="background: #ff66ff">&nbsp;</td>
+ <td style="background: #ff55ff">&nbsp;</td>
+ <td style="background: #ff44ff">&nbsp;</td>
+ <td style="background: #ff33ff">&nbsp;</td>
+ <td style="background: #ff22ff">&nbsp;</td>
+ <td style="background: #ff11ff">&nbsp;</td>
+ <td style="background: #ff00ff">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #ffffff">&nbsp;</td>
+ <td style="background: #ffeeff">&nbsp;</td>
+ <td style="background: #ffddff">&nbsp;</td>
+ <td style="background: #ffccff">&nbsp;</td>
+ <td style="background: #ffbbff">&nbsp;</td>
+ <td style="background: #ffaaff">&nbsp;</td>
+ <td style="background: #ff99ff">&nbsp;</td>
+ <td style="background: #ff88ff">&nbsp;</td>
+ <td style="background: #ff77ff">&nbsp;</td>
+ <td style="background: #ff66ff">&nbsp;</td>
+ <td style="background: #ff55ff">&nbsp;</td>
+ <td style="background: #ff44ff">&nbsp;</td>
+ <td style="background: #ff33ff">&nbsp;</td>
+ <td style="background: #ff22ff">&nbsp;</td>
+ <td style="background: #ff11ff">&nbsp;</td>
+ <td style="background: #ff00ff">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #ffffff">&nbsp;</td>
+ <td style="background: #ffeeff">&nbsp;</td>
+ <td style="background: #ffddff">&nbsp;</td>
+ <td style="background: #ffccff">&nbsp;</td>
+ <td style="background: #ffbbff">&nbsp;</td>
+ <td style="background: #ffaaff">&nbsp;</td>
+ <td style="background: #ff99ff">&nbsp;</td>
+ <td style="background: #ff88ff">&nbsp;</td>
+ <td style="background: #ff77ff">&nbsp;</td>
+ <td style="background: #ff66ff">&nbsp;</td>
+ <td style="background: #ff55ff">&nbsp;</td>
+ <td style="background: #ff44ff">&nbsp;</td>
+ <td style="background: #ff33ff">&nbsp;</td>
+ <td style="background: #ff22ff">&nbsp;</td>
+ <td style="background: #ff11ff">&nbsp;</td>
+ <td style="background: #ff00ff">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+
+ <p>The following table should have four matching rows gradually changing from aqua at the left to black at the right (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #00ffff">&nbsp;</td>
+ <td style="background: #00eeee">&nbsp;</td>
+ <td style="background: #00dddd">&nbsp;</td>
+ <td style="background: #00cccc">&nbsp;</td>
+ <td style="background: #00bbbb">&nbsp;</td>
+ <td style="background: #00aaaa">&nbsp;</td>
+ <td style="background: #009999">&nbsp;</td>
+ <td style="background: #008888">&nbsp;</td>
+ <td style="background: #007777">&nbsp;</td>
+ <td style="background: #006666">&nbsp;</td>
+ <td style="background: #005555">&nbsp;</td>
+ <td style="background: #004444">&nbsp;</td>
+ <td style="background: #003333">&nbsp;</td>
+ <td style="background: #002222">&nbsp;</td>
+ <td style="background: #001111">&nbsp;</td>
+ <td style="background: #000000">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #00ffff">&nbsp;</td>
+ <td style="background: #00eeee">&nbsp;</td>
+ <td style="background: #00dddd">&nbsp;</td>
+ <td style="background: #00cccc">&nbsp;</td>
+ <td style="background: #00bbbb">&nbsp;</td>
+ <td style="background: #00aaaa">&nbsp;</td>
+ <td style="background: #009999">&nbsp;</td>
+ <td style="background: #008888">&nbsp;</td>
+ <td style="background: #007777">&nbsp;</td>
+ <td style="background: #006666">&nbsp;</td>
+ <td style="background: #005555">&nbsp;</td>
+ <td style="background: #004444">&nbsp;</td>
+ <td style="background: #003333">&nbsp;</td>
+ <td style="background: #002222">&nbsp;</td>
+ <td style="background: #001111">&nbsp;</td>
+ <td style="background: #000000">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #00ffff">&nbsp;</td>
+ <td style="background: #00eeee">&nbsp;</td>
+ <td style="background: #00dddd">&nbsp;</td>
+ <td style="background: #00cccc">&nbsp;</td>
+ <td style="background: #00bbbb">&nbsp;</td>
+ <td style="background: #00aaaa">&nbsp;</td>
+ <td style="background: #009999">&nbsp;</td>
+ <td style="background: #008888">&nbsp;</td>
+ <td style="background: #007777">&nbsp;</td>
+ <td style="background: #006666">&nbsp;</td>
+ <td style="background: #005555">&nbsp;</td>
+ <td style="background: #004444">&nbsp;</td>
+ <td style="background: #003333">&nbsp;</td>
+ <td style="background: #002222">&nbsp;</td>
+ <td style="background: #001111">&nbsp;</td>
+ <td style="background: #000000">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #00ffff">&nbsp;</td>
+ <td style="background: #00eeee">&nbsp;</td>
+ <td style="background: #00dddd">&nbsp;</td>
+ <td style="background: #00cccc">&nbsp;</td>
+ <td style="background: #00bbbb">&nbsp;</td>
+ <td style="background: #00aaaa">&nbsp;</td>
+ <td style="background: #009999">&nbsp;</td>
+ <td style="background: #008888">&nbsp;</td>
+ <td style="background: #007777">&nbsp;</td>
+ <td style="background: #006666">&nbsp;</td>
+ <td style="background: #005555">&nbsp;</td>
+ <td style="background: #004444">&nbsp;</td>
+ <td style="background: #003333">&nbsp;</td>
+ <td style="background: #002222">&nbsp;</td>
+ <td style="background: #001111">&nbsp;</td>
+ <td style="background: #000000">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+
+ <p>The following table should have four matching rows gradually changing from white at the left to aqua at the right (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #ffffff">&nbsp;</td>
+ <td style="background: #eeffff">&nbsp;</td>
+ <td style="background: #ddffff">&nbsp;</td>
+ <td style="background: #ccffff">&nbsp;</td>
+ <td style="background: #bbffff">&nbsp;</td>
+ <td style="background: #aaffff">&nbsp;</td>
+ <td style="background: #99ffff">&nbsp;</td>
+ <td style="background: #88ffff">&nbsp;</td>
+ <td style="background: #77ffff">&nbsp;</td>
+ <td style="background: #66ffff">&nbsp;</td>
+ <td style="background: #55ffff">&nbsp;</td>
+ <td style="background: #44ffff">&nbsp;</td>
+ <td style="background: #33ffff">&nbsp;</td>
+ <td style="background: #22ffff">&nbsp;</td>
+ <td style="background: #11ffff">&nbsp;</td>
+ <td style="background: #00ffff">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #ffffff">&nbsp;</td>
+ <td style="background: #eeffff">&nbsp;</td>
+ <td style="background: #ddffff">&nbsp;</td>
+ <td style="background: #ccffff">&nbsp;</td>
+ <td style="background: #bbffff">&nbsp;</td>
+ <td style="background: #aaffff">&nbsp;</td>
+ <td style="background: #99ffff">&nbsp;</td>
+ <td style="background: #88ffff">&nbsp;</td>
+ <td style="background: #77ffff">&nbsp;</td>
+ <td style="background: #66ffff">&nbsp;</td>
+ <td style="background: #55ffff">&nbsp;</td>
+ <td style="background: #44ffff">&nbsp;</td>
+ <td style="background: #33ffff">&nbsp;</td>
+ <td style="background: #22ffff">&nbsp;</td>
+ <td style="background: #11ffff">&nbsp;</td>
+ <td style="background: #00ffff">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #ffffff">&nbsp;</td>
+ <td style="background: #eeffff">&nbsp;</td>
+ <td style="background: #ddffff">&nbsp;</td>
+ <td style="background: #ccffff">&nbsp;</td>
+ <td style="background: #bbffff">&nbsp;</td>
+ <td style="background: #aaffff">&nbsp;</td>
+ <td style="background: #99ffff">&nbsp;</td>
+ <td style="background: #88ffff">&nbsp;</td>
+ <td style="background: #77ffff">&nbsp;</td>
+ <td style="background: #66ffff">&nbsp;</td>
+ <td style="background: #55ffff">&nbsp;</td>
+ <td style="background: #44ffff">&nbsp;</td>
+ <td style="background: #33ffff">&nbsp;</td>
+ <td style="background: #22ffff">&nbsp;</td>
+ <td style="background: #11ffff">&nbsp;</td>
+ <td style="background: #00ffff">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #ffffff">&nbsp;</td>
+ <td style="background: #eeffff">&nbsp;</td>
+ <td style="background: #ddffff">&nbsp;</td>
+ <td style="background: #ccffff">&nbsp;</td>
+ <td style="background: #bbffff">&nbsp;</td>
+ <td style="background: #aaffff">&nbsp;</td>
+ <td style="background: #99ffff">&nbsp;</td>
+ <td style="background: #88ffff">&nbsp;</td>
+ <td style="background: #77ffff">&nbsp;</td>
+ <td style="background: #66ffff">&nbsp;</td>
+ <td style="background: #55ffff">&nbsp;</td>
+ <td style="background: #44ffff">&nbsp;</td>
+ <td style="background: #33ffff">&nbsp;</td>
+ <td style="background: #22ffff">&nbsp;</td>
+ <td style="background: #11ffff">&nbsp;</td>
+ <td style="background: #00ffff">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+
+ <p>The following table should have four matching rows gradually changing from red at the left to green at the right (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #ff0000">&nbsp;</td>
+ <td style="background: #ee1100">&nbsp;</td>
+ <td style="background: #dd2200">&nbsp;</td>
+ <td style="background: #cc3300">&nbsp;</td>
+ <td style="background: #bb4400">&nbsp;</td>
+ <td style="background: #aa5500">&nbsp;</td>
+ <td style="background: #996600">&nbsp;</td>
+ <td style="background: #887700">&nbsp;</td>
+ <td style="background: #778800">&nbsp;</td>
+ <td style="background: #669900">&nbsp;</td>
+ <td style="background: #55aa00">&nbsp;</td>
+ <td style="background: #44bb00">&nbsp;</td>
+ <td style="background: #33cc00">&nbsp;</td>
+ <td style="background: #22dd00">&nbsp;</td>
+ <td style="background: #11ee00">&nbsp;</td>
+ <td style="background: #00ff00">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #ff0000">&nbsp;</td>
+ <td style="background: #ee1100">&nbsp;</td>
+ <td style="background: #dd2200">&nbsp;</td>
+ <td style="background: #cc3300">&nbsp;</td>
+ <td style="background: #bb4400">&nbsp;</td>
+ <td style="background: #aa5500">&nbsp;</td>
+ <td style="background: #996600">&nbsp;</td>
+ <td style="background: #887700">&nbsp;</td>
+ <td style="background: #778800">&nbsp;</td>
+ <td style="background: #669900">&nbsp;</td>
+ <td style="background: #55aa00">&nbsp;</td>
+ <td style="background: #44bb00">&nbsp;</td>
+ <td style="background: #33cc00">&nbsp;</td>
+ <td style="background: #22dd00">&nbsp;</td>
+ <td style="background: #11ee00">&nbsp;</td>
+ <td style="background: #00ff00">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #ff0000">&nbsp;</td>
+ <td style="background: #ee1100">&nbsp;</td>
+ <td style="background: #dd2200">&nbsp;</td>
+ <td style="background: #cc3300">&nbsp;</td>
+ <td style="background: #bb4400">&nbsp;</td>
+ <td style="background: #aa5500">&nbsp;</td>
+ <td style="background: #996600">&nbsp;</td>
+ <td style="background: #887700">&nbsp;</td>
+ <td style="background: #778800">&nbsp;</td>
+ <td style="background: #669900">&nbsp;</td>
+ <td style="background: #55aa00">&nbsp;</td>
+ <td style="background: #44bb00">&nbsp;</td>
+ <td style="background: #33cc00">&nbsp;</td>
+ <td style="background: #22dd00">&nbsp;</td>
+ <td style="background: #11ee00">&nbsp;</td>
+ <td style="background: #00ff00">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #ff0000">&nbsp;</td>
+ <td style="background: #ee1100">&nbsp;</td>
+ <td style="background: #dd2200">&nbsp;</td>
+ <td style="background: #cc3300">&nbsp;</td>
+ <td style="background: #bb4400">&nbsp;</td>
+ <td style="background: #aa5500">&nbsp;</td>
+ <td style="background: #996600">&nbsp;</td>
+ <td style="background: #887700">&nbsp;</td>
+ <td style="background: #778800">&nbsp;</td>
+ <td style="background: #669900">&nbsp;</td>
+ <td style="background: #55aa00">&nbsp;</td>
+ <td style="background: #44bb00">&nbsp;</td>
+ <td style="background: #33cc00">&nbsp;</td>
+ <td style="background: #22dd00">&nbsp;</td>
+ <td style="background: #11ee00">&nbsp;</td>
+ <td style="background: #00ff00">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+
+ <p>The following table should have four matching rows gradually changing from green at the left to blue at the right (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #00ff00">&nbsp;</td>
+ <td style="background: #00ee11">&nbsp;</td>
+ <td style="background: #00dd22">&nbsp;</td>
+ <td style="background: #00cc33">&nbsp;</td>
+ <td style="background: #00bb44">&nbsp;</td>
+ <td style="background: #00aa55">&nbsp;</td>
+ <td style="background: #009966">&nbsp;</td>
+ <td style="background: #008877">&nbsp;</td>
+ <td style="background: #007788">&nbsp;</td>
+ <td style="background: #006699">&nbsp;</td>
+ <td style="background: #0055aa">&nbsp;</td>
+ <td style="background: #0044bb">&nbsp;</td>
+ <td style="background: #0033cc">&nbsp;</td>
+ <td style="background: #0022dd">&nbsp;</td>
+ <td style="background: #0011ee">&nbsp;</td>
+ <td style="background: #0000ff">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #00ff00">&nbsp;</td>
+ <td style="background: #00ee11">&nbsp;</td>
+ <td style="background: #00dd22">&nbsp;</td>
+ <td style="background: #00cc33">&nbsp;</td>
+ <td style="background: #00bb44">&nbsp;</td>
+ <td style="background: #00aa55">&nbsp;</td>
+ <td style="background: #009966">&nbsp;</td>
+ <td style="background: #008877">&nbsp;</td>
+ <td style="background: #007788">&nbsp;</td>
+ <td style="background: #006699">&nbsp;</td>
+ <td style="background: #0055aa">&nbsp;</td>
+ <td style="background: #0044bb">&nbsp;</td>
+ <td style="background: #0033cc">&nbsp;</td>
+ <td style="background: #0022dd">&nbsp;</td>
+ <td style="background: #0011ee">&nbsp;</td>
+ <td style="background: #0000ff">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #00ff00">&nbsp;</td>
+ <td style="background: #00ee11">&nbsp;</td>
+ <td style="background: #00dd22">&nbsp;</td>
+ <td style="background: #00cc33">&nbsp;</td>
+ <td style="background: #00bb44">&nbsp;</td>
+ <td style="background: #00aa55">&nbsp;</td>
+ <td style="background: #009966">&nbsp;</td>
+ <td style="background: #008877">&nbsp;</td>
+ <td style="background: #007788">&nbsp;</td>
+ <td style="background: #006699">&nbsp;</td>
+ <td style="background: #0055aa">&nbsp;</td>
+ <td style="background: #0044bb">&nbsp;</td>
+ <td style="background: #0033cc">&nbsp;</td>
+ <td style="background: #0022dd">&nbsp;</td>
+ <td style="background: #0011ee">&nbsp;</td>
+ <td style="background: #0000ff">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #00ff00">&nbsp;</td>
+ <td style="background: #00ee11">&nbsp;</td>
+ <td style="background: #00dd22">&nbsp;</td>
+ <td style="background: #00cc33">&nbsp;</td>
+ <td style="background: #00bb44">&nbsp;</td>
+ <td style="background: #00aa55">&nbsp;</td>
+ <td style="background: #009966">&nbsp;</td>
+ <td style="background: #008877">&nbsp;</td>
+ <td style="background: #007788">&nbsp;</td>
+ <td style="background: #006699">&nbsp;</td>
+ <td style="background: #0055aa">&nbsp;</td>
+ <td style="background: #0044bb">&nbsp;</td>
+ <td style="background: #0033cc">&nbsp;</td>
+ <td style="background: #0022dd">&nbsp;</td>
+ <td style="background: #0011ee">&nbsp;</td>
+ <td style="background: #0000ff">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+
+ <p>The following table should have four matching rows gradually changing from blue at the left to red at the right (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #00ff00">&nbsp;</td>
+ <td style="background: #00ee11">&nbsp;</td>
+ <td style="background: #00dd22">&nbsp;</td>
+ <td style="background: #00cc33">&nbsp;</td>
+ <td style="background: #00bb44">&nbsp;</td>
+ <td style="background: #00aa55">&nbsp;</td>
+ <td style="background: #009966">&nbsp;</td>
+ <td style="background: #008877">&nbsp;</td>
+ <td style="background: #007788">&nbsp;</td>
+ <td style="background: #006699">&nbsp;</td>
+ <td style="background: #0055aa">&nbsp;</td>
+ <td style="background: #0044bb">&nbsp;</td>
+ <td style="background: #0033cc">&nbsp;</td>
+ <td style="background: #0022dd">&nbsp;</td>
+ <td style="background: #0011ee">&nbsp;</td>
+ <td style="background: #0000ff">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #00ff00">&nbsp;</td>
+ <td style="background: #00ee11">&nbsp;</td>
+ <td style="background: #00dd22">&nbsp;</td>
+ <td style="background: #00cc33">&nbsp;</td>
+ <td style="background: #00bb44">&nbsp;</td>
+ <td style="background: #00aa55">&nbsp;</td>
+ <td style="background: #009966">&nbsp;</td>
+ <td style="background: #008877">&nbsp;</td>
+ <td style="background: #007788">&nbsp;</td>
+ <td style="background: #006699">&nbsp;</td>
+ <td style="background: #0055aa">&nbsp;</td>
+ <td style="background: #0044bb">&nbsp;</td>
+ <td style="background: #0033cc">&nbsp;</td>
+ <td style="background: #0022dd">&nbsp;</td>
+ <td style="background: #0011ee">&nbsp;</td>
+ <td style="background: #0000ff">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #00ff00">&nbsp;</td>
+ <td style="background: #00ee11">&nbsp;</td>
+ <td style="background: #00dd22">&nbsp;</td>
+ <td style="background: #00cc33">&nbsp;</td>
+ <td style="background: #00bb44">&nbsp;</td>
+ <td style="background: #00aa55">&nbsp;</td>
+ <td style="background: #009966">&nbsp;</td>
+ <td style="background: #008877">&nbsp;</td>
+ <td style="background: #007788">&nbsp;</td>
+ <td style="background: #006699">&nbsp;</td>
+ <td style="background: #0055aa">&nbsp;</td>
+ <td style="background: #0044bb">&nbsp;</td>
+ <td style="background: #0033cc">&nbsp;</td>
+ <td style="background: #0022dd">&nbsp;</td>
+ <td style="background: #0011ee">&nbsp;</td>
+ <td style="background: #0000ff">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #00ff00">&nbsp;</td>
+ <td style="background: #00ee11">&nbsp;</td>
+ <td style="background: #00dd22">&nbsp;</td>
+ <td style="background: #00cc33">&nbsp;</td>
+ <td style="background: #00bb44">&nbsp;</td>
+ <td style="background: #00aa55">&nbsp;</td>
+ <td style="background: #009966">&nbsp;</td>
+ <td style="background: #008877">&nbsp;</td>
+ <td style="background: #007788">&nbsp;</td>
+ <td style="background: #006699">&nbsp;</td>
+ <td style="background: #0055aa">&nbsp;</td>
+ <td style="background: #0044bb">&nbsp;</td>
+ <td style="background: #0033cc">&nbsp;</td>
+ <td style="background: #0022dd">&nbsp;</td>
+ <td style="background: #0011ee">&nbsp;</td>
+ <td style="background: #0000ff">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+
+ <p>The following table should have four matching rows gradually changing from fuchsia at the left to aqua at the right (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #ff00ff">&nbsp;</td>
+ <td style="background: #ee11ff">&nbsp;</td>
+ <td style="background: #dd22ff">&nbsp;</td>
+ <td style="background: #cc33ff">&nbsp;</td>
+ <td style="background: #bb44ff">&nbsp;</td>
+ <td style="background: #aa55ff">&nbsp;</td>
+ <td style="background: #9966ff">&nbsp;</td>
+ <td style="background: #8877ff">&nbsp;</td>
+ <td style="background: #7788ff">&nbsp;</td>
+ <td style="background: #6699ff">&nbsp;</td>
+ <td style="background: #55aaff">&nbsp;</td>
+ <td style="background: #44bbff">&nbsp;</td>
+ <td style="background: #33ccff">&nbsp;</td>
+ <td style="background: #22ddff">&nbsp;</td>
+ <td style="background: #11eeff">&nbsp;</td>
+ <td style="background: #00ffff">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #ff00ff">&nbsp;</td>
+ <td style="background: #ee11ff">&nbsp;</td>
+ <td style="background: #dd22ff">&nbsp;</td>
+ <td style="background: #cc33ff">&nbsp;</td>
+ <td style="background: #bb44ff">&nbsp;</td>
+ <td style="background: #aa55ff">&nbsp;</td>
+ <td style="background: #9966ff">&nbsp;</td>
+ <td style="background: #8877ff">&nbsp;</td>
+ <td style="background: #7788ff">&nbsp;</td>
+ <td style="background: #6699ff">&nbsp;</td>
+ <td style="background: #55aaff">&nbsp;</td>
+ <td style="background: #44bbff">&nbsp;</td>
+ <td style="background: #33ccff">&nbsp;</td>
+ <td style="background: #22ddff">&nbsp;</td>
+ <td style="background: #11eeff">&nbsp;</td>
+ <td style="background: #00ffff">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #ff00ff">&nbsp;</td>
+ <td style="background: #ee11ff">&nbsp;</td>
+ <td style="background: #dd22ff">&nbsp;</td>
+ <td style="background: #cc33ff">&nbsp;</td>
+ <td style="background: #bb44ff">&nbsp;</td>
+ <td style="background: #aa55ff">&nbsp;</td>
+ <td style="background: #9966ff">&nbsp;</td>
+ <td style="background: #8877ff">&nbsp;</td>
+ <td style="background: #7788ff">&nbsp;</td>
+ <td style="background: #6699ff">&nbsp;</td>
+ <td style="background: #55aaff">&nbsp;</td>
+ <td style="background: #44bbff">&nbsp;</td>
+ <td style="background: #33ccff">&nbsp;</td>
+ <td style="background: #22ddff">&nbsp;</td>
+ <td style="background: #11eeff">&nbsp;</td>
+ <td style="background: #00ffff">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #ff00ff">&nbsp;</td>
+ <td style="background: #ee11ff">&nbsp;</td>
+ <td style="background: #dd22ff">&nbsp;</td>
+ <td style="background: #cc33ff">&nbsp;</td>
+ <td style="background: #bb44ff">&nbsp;</td>
+ <td style="background: #aa55ff">&nbsp;</td>
+ <td style="background: #9966ff">&nbsp;</td>
+ <td style="background: #8877ff">&nbsp;</td>
+ <td style="background: #7788ff">&nbsp;</td>
+ <td style="background: #6699ff">&nbsp;</td>
+ <td style="background: #55aaff">&nbsp;</td>
+ <td style="background: #44bbff">&nbsp;</td>
+ <td style="background: #33ccff">&nbsp;</td>
+ <td style="background: #22ddff">&nbsp;</td>
+ <td style="background: #11eeff">&nbsp;</td>
+ <td style="background: #00ffff">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+
+ <p>The following table should have four matching rows gradually changing from yellow at the left to fuchsia at the right (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #ffff00">&nbsp;</td>
+ <td style="background: #ffee11">&nbsp;</td>
+ <td style="background: #ffdd22">&nbsp;</td>
+ <td style="background: #ffcc33">&nbsp;</td>
+ <td style="background: #ffbb44">&nbsp;</td>
+ <td style="background: #ffaa55">&nbsp;</td>
+ <td style="background: #ff9966">&nbsp;</td>
+ <td style="background: #ff8877">&nbsp;</td>
+ <td style="background: #ff7788">&nbsp;</td>
+ <td style="background: #ff6699">&nbsp;</td>
+ <td style="background: #ff55aa">&nbsp;</td>
+ <td style="background: #ff44bb">&nbsp;</td>
+ <td style="background: #ff33cc">&nbsp;</td>
+ <td style="background: #ff22dd">&nbsp;</td>
+ <td style="background: #ff11ee">&nbsp;</td>
+ <td style="background: #ff00ff">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #ffff00">&nbsp;</td>
+ <td style="background: #ffee11">&nbsp;</td>
+ <td style="background: #ffdd22">&nbsp;</td>
+ <td style="background: #ffcc33">&nbsp;</td>
+ <td style="background: #ffbb44">&nbsp;</td>
+ <td style="background: #ffaa55">&nbsp;</td>
+ <td style="background: #ff9966">&nbsp;</td>
+ <td style="background: #ff8877">&nbsp;</td>
+ <td style="background: #ff7788">&nbsp;</td>
+ <td style="background: #ff6699">&nbsp;</td>
+ <td style="background: #ff55aa">&nbsp;</td>
+ <td style="background: #ff44bb">&nbsp;</td>
+ <td style="background: #ff33cc">&nbsp;</td>
+ <td style="background: #ff22dd">&nbsp;</td>
+ <td style="background: #ff11ee">&nbsp;</td>
+ <td style="background: #ff00ff">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #ffff00">&nbsp;</td>
+ <td style="background: #ffee11">&nbsp;</td>
+ <td style="background: #ffdd22">&nbsp;</td>
+ <td style="background: #ffcc33">&nbsp;</td>
+ <td style="background: #ffbb44">&nbsp;</td>
+ <td style="background: #ffaa55">&nbsp;</td>
+ <td style="background: #ff9966">&nbsp;</td>
+ <td style="background: #ff8877">&nbsp;</td>
+ <td style="background: #ff7788">&nbsp;</td>
+ <td style="background: #ff6699">&nbsp;</td>
+ <td style="background: #ff55aa">&nbsp;</td>
+ <td style="background: #ff44bb">&nbsp;</td>
+ <td style="background: #ff33cc">&nbsp;</td>
+ <td style="background: #ff22dd">&nbsp;</td>
+ <td style="background: #ff11ee">&nbsp;</td>
+ <td style="background: #ff00ff">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #ffff00">&nbsp;</td>
+ <td style="background: #ffee11">&nbsp;</td>
+ <td style="background: #ffdd22">&nbsp;</td>
+ <td style="background: #ffcc33">&nbsp;</td>
+ <td style="background: #ffbb44">&nbsp;</td>
+ <td style="background: #ffaa55">&nbsp;</td>
+ <td style="background: #ff9966">&nbsp;</td>
+ <td style="background: #ff8877">&nbsp;</td>
+ <td style="background: #ff7788">&nbsp;</td>
+ <td style="background: #ff6699">&nbsp;</td>
+ <td style="background: #ff55aa">&nbsp;</td>
+ <td style="background: #ff44bb">&nbsp;</td>
+ <td style="background: #ff33cc">&nbsp;</td>
+ <td style="background: #ff22dd">&nbsp;</td>
+ <td style="background: #ff11ee">&nbsp;</td>
+ <td style="background: #ff00ff">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+
+ <p>The following table should have four matching rows gradually changing from aqua at the left to yellow at the right (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #00ffff">&nbsp;</td>
+ <td style="background: #11ffee">&nbsp;</td>
+ <td style="background: #22ffdd">&nbsp;</td>
+ <td style="background: #33ffcc">&nbsp;</td>
+ <td style="background: #44ffbb">&nbsp;</td>
+ <td style="background: #55ffaa">&nbsp;</td>
+ <td style="background: #66ff99">&nbsp;</td>
+ <td style="background: #77ff88">&nbsp;</td>
+ <td style="background: #88ff77">&nbsp;</td>
+ <td style="background: #99ff66">&nbsp;</td>
+ <td style="background: #aaff55">&nbsp;</td>
+ <td style="background: #bbff44">&nbsp;</td>
+ <td style="background: #ccff33">&nbsp;</td>
+ <td style="background: #ddff22">&nbsp;</td>
+ <td style="background: #eeff11">&nbsp;</td>
+ <td style="background: #ffff00">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #00ffff">&nbsp;</td>
+ <td style="background: #11ffee">&nbsp;</td>
+ <td style="background: #22ffdd">&nbsp;</td>
+ <td style="background: #33ffcc">&nbsp;</td>
+ <td style="background: #44ffbb">&nbsp;</td>
+ <td style="background: #55ffaa">&nbsp;</td>
+ <td style="background: #66ff99">&nbsp;</td>
+ <td style="background: #77ff88">&nbsp;</td>
+ <td style="background: #88ff77">&nbsp;</td>
+ <td style="background: #99ff66">&nbsp;</td>
+ <td style="background: #aaff55">&nbsp;</td>
+ <td style="background: #bbff44">&nbsp;</td>
+ <td style="background: #ccff33">&nbsp;</td>
+ <td style="background: #ddff22">&nbsp;</td>
+ <td style="background: #eeff11">&nbsp;</td>
+ <td style="background: #ffff00">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: #00ffff">&nbsp;</td>
+ <td style="background: #11ffee">&nbsp;</td>
+ <td style="background: #22ffdd">&nbsp;</td>
+ <td style="background: #33ffcc">&nbsp;</td>
+ <td style="background: #44ffbb">&nbsp;</td>
+ <td style="background: #55ffaa">&nbsp;</td>
+ <td style="background: #66ff99">&nbsp;</td>
+ <td style="background: #77ff88">&nbsp;</td>
+ <td style="background: #88ff77">&nbsp;</td>
+ <td style="background: #99ff66">&nbsp;</td>
+ <td style="background: #aaff55">&nbsp;</td>
+ <td style="background: #bbff44">&nbsp;</td>
+ <td style="background: #ccff33">&nbsp;</td>
+ <td style="background: #ddff22">&nbsp;</td>
+ <td style="background: #eeff11">&nbsp;</td>
+ <td style="background: #ffff00">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: #00ffff">&nbsp;</td>
+ <td style="background: #11ffee">&nbsp;</td>
+ <td style="background: #22ffdd">&nbsp;</td>
+ <td style="background: #33ffcc">&nbsp;</td>
+ <td style="background: #44ffbb">&nbsp;</td>
+ <td style="background: #55ffaa">&nbsp;</td>
+ <td style="background: #66ff99">&nbsp;</td>
+ <td style="background: #77ff88">&nbsp;</td>
+ <td style="background: #88ff77">&nbsp;</td>
+ <td style="background: #99ff66">&nbsp;</td>
+ <td style="background: #aaff55">&nbsp;</td>
+ <td style="background: #bbff44">&nbsp;</td>
+ <td style="background: #ccff33">&nbsp;</td>
+ <td style="background: #ddff22">&nbsp;</td>
+ <td style="background: #eeff11">&nbsp;</td>
+ <td style="background: #ffff00">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/t421-rgb-values-meaning-b.xht b/tests/wpt/web-platform-tests/css/css-color/t421-rgb-values-meaning-b.xht
index 760a4416ac0..b628d3e859c 100644
--- a/tests/wpt/web-platform-tests/css/css-color/t421-rgb-values-meaning-b.xht
+++ b/tests/wpt/web-platform-tests/css/css-color/t421-rgb-values-meaning-b.xht
@@ -5,6 +5,7 @@
<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://www.w3.org/TR/css3-color/#rgb-color" />
+ <link rel="match" href="t421-rgb-values-meaning-b-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="Test that the color components in rgb colors are interpreted correctly." />
<style type="text/css"><![CDATA[
diff --git a/tests/wpt/web-platform-tests/css/css-color/t422-rgba-a0.0-a.xht b/tests/wpt/web-platform-tests/css/css-color/t422-rgba-a0.0-a.xht
index fe3d5c39af0..28f41b8b111 100644
--- a/tests/wpt/web-platform-tests/css/css-color/t422-rgba-a0.0-a.xht
+++ b/tests/wpt/web-platform-tests/css/css-color/t422-rgba-a0.0-a.xht
@@ -5,6 +5,7 @@
<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://www.w3.org/TR/css3-color/#rgba-color" />
+ <link rel="match" href="t32-opacity-basic-0.0-a-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="Opacity of 0.0 makes text transparent." />
<style type="text/css"><![CDATA[
diff --git a/tests/wpt/web-platform-tests/css/css-color/t422-rgba-values-meaning-b-ref.html b/tests/wpt/web-platform-tests/css/css-color/t422-rgba-values-meaning-b-ref.html
new file mode 100644
index 00000000000..08631f2e4a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/t422-rgba-values-meaning-b-ref.html
@@ -0,0 +1,432 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ table { border-spacing: 0; padding: 0; border: none; }
+ td { border: none; padding: 0; }
+ td { width: 1.2em; height: 1.2em; }
+</style>
+<body>
+ <p>The following table should have four matching rows changing (in 5 steps) from red at the left to black at the right: (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <div style="background: black">
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: rgb(255, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(204, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(153, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(102, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(51, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 0)">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: rgb(255, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(204, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(153, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(102, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(51, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 0)">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: rgb(255, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(204, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(153, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(102, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(51, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 0)">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: rgb(255, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(204, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(153, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(102, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(51, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 0)">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+ </div>
+
+ <p>The following table should have four matching rows changing (in 5 steps) from red at the left to white at the right: (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <div style="background: white">
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: rgb(255, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(255, 51, 51)">&nbsp;</td>
+ <td style="background: rgb(255, 102, 102)">&nbsp;</td>
+ <td style="background: rgb(255, 153, 153)">&nbsp;</td>
+ <td style="background: rgb(255, 204, 204)">&nbsp;</td>
+ <td style="background: rgb(255, 255, 255)">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: rgb(255, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(255, 51, 51)">&nbsp;</td>
+ <td style="background: rgb(255, 102, 102)">&nbsp;</td>
+ <td style="background: rgb(255, 153, 153)">&nbsp;</td>
+ <td style="background: rgb(255, 204, 204)">&nbsp;</td>
+ <td style="background: rgb(255, 255, 255)">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: rgb(255, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(255, 51, 51)">&nbsp;</td>
+ <td style="background: rgb(255, 102, 102)">&nbsp;</td>
+ <td style="background: rgb(255, 153, 153)">&nbsp;</td>
+ <td style="background: rgb(255, 204, 204)">&nbsp;</td>
+ <td style="background: rgb(255, 255, 255)">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: rgb(255, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(255, 51, 51)">&nbsp;</td>
+ <td style="background: rgb(255, 102, 102)">&nbsp;</td>
+ <td style="background: rgb(255, 153, 153)">&nbsp;</td>
+ <td style="background: rgb(255, 204, 204)">&nbsp;</td>
+ <td style="background: rgb(255, 255, 255)">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+ </div>
+
+ <p>The following table should have four matching rows changing (in 5 steps) from green at the left to black at the right: (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <div style="background: black">
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: rgb(0, 255, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 204, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 153, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 102, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 51, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 0)">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: rgb(0, 255, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 204, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 153, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 102, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 51, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 0)">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: rgb(0, 255, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 204, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 153, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 102, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 51, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 0)">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: rgb(0, 255, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 204, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 153, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 102, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 51, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 0)">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+ </div>
+
+ <p>The following table should have four matching rows changing (in 5 steps) from green at the left to white at the right: (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <div style="background: white">
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: rgb(0, 255, 0)">&nbsp;</td>
+ <td style="background: rgb(51, 255, 51)">&nbsp;</td>
+ <td style="background: rgb(102, 255, 102)">&nbsp;</td>
+ <td style="background: rgb(153, 255, 153)">&nbsp;</td>
+ <td style="background: rgb(204, 255, 204)">&nbsp;</td>
+ <td style="background: rgb(255, 255, 255)">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: rgb(0, 255, 0)">&nbsp;</td>
+ <td style="background: rgb(51, 255, 51)">&nbsp;</td>
+ <td style="background: rgb(102, 255, 102)">&nbsp;</td>
+ <td style="background: rgb(153, 255, 153)">&nbsp;</td>
+ <td style="background: rgb(204, 255, 204)">&nbsp;</td>
+ <td style="background: rgb(255, 255, 255)">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: rgb(0, 255, 0)">&nbsp;</td>
+ <td style="background: rgb(51, 255, 51)">&nbsp;</td>
+ <td style="background: rgb(102, 255, 102)">&nbsp;</td>
+ <td style="background: rgb(153, 255, 153)">&nbsp;</td>
+ <td style="background: rgb(204, 255, 204)">&nbsp;</td>
+ <td style="background: rgb(255, 255, 255)">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: rgb(0, 255, 0)">&nbsp;</td>
+ <td style="background: rgb(51, 255, 51)">&nbsp;</td>
+ <td style="background: rgb(102, 255, 102)">&nbsp;</td>
+ <td style="background: rgb(153, 255, 153)">&nbsp;</td>
+ <td style="background: rgb(204, 255, 204)">&nbsp;</td>
+ <td style="background: rgb(255, 255, 255)">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+ </div>
+
+ <p>The following table should have four matching rows changing (in 5 steps) from blue at the left to black at the right: (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <div style="background: black">
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: rgb(0, 0, 255)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 204)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 153)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 102)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 51)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 0)">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: rgb(0, 0, 255)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 204)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 153)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 102)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 51)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 0)">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: rgb(0, 0, 255)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 204)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 153)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 102)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 51)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 0)">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: rgb(0, 0, 255)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 204)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 153)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 102)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 51)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 0)">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+ </div>
+
+ <p>The following table should have four matching rows changing (in 5 steps) from blue at the left to white at the right: (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <div style="background: white">
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: rgb(0, 0, 255)">&nbsp;</td>
+ <td style="background: rgb(51, 51, 255)">&nbsp;</td>
+ <td style="background: rgb(102, 102, 255)">&nbsp;</td>
+ <td style="background: rgb(153, 153, 255)">&nbsp;</td>
+ <td style="background: rgb(204, 204, 255)">&nbsp;</td>
+ <td style="background: rgb(255, 255, 255)">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: rgb(0, 0, 255)">&nbsp;</td>
+ <td style="background: rgb(51, 51, 255)">&nbsp;</td>
+ <td style="background: rgb(102, 102, 255)">&nbsp;</td>
+ <td style="background: rgb(153, 153, 255)">&nbsp;</td>
+ <td style="background: rgb(204, 204, 255)">&nbsp;</td>
+ <td style="background: rgb(255, 255, 255)">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: rgb(0, 0, 255)">&nbsp;</td>
+ <td style="background: rgb(51, 51, 255)">&nbsp;</td>
+ <td style="background: rgb(102, 102, 255)">&nbsp;</td>
+ <td style="background: rgb(153, 153, 255)">&nbsp;</td>
+ <td style="background: rgb(204, 204, 255)">&nbsp;</td>
+ <td style="background: rgb(255, 255, 255)">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: rgb(0, 0, 255)">&nbsp;</td>
+ <td style="background: rgb(51, 51, 255)">&nbsp;</td>
+ <td style="background: rgb(102, 102, 255)">&nbsp;</td>
+ <td style="background: rgb(153, 153, 255)">&nbsp;</td>
+ <td style="background: rgb(204, 204, 255)">&nbsp;</td>
+ <td style="background: rgb(255, 255, 255)">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+ </div>
+
+ <p>The following table should have four matching rows changing (in 5 steps) from red at the left to green at the right: (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <div style="background: lime">
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: rgb(255, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(204, 51, 0)">&nbsp;</td>
+ <td style="background: rgb(153, 102, 0)">&nbsp;</td>
+ <td style="background: rgb(102, 153, 0)">&nbsp;</td>
+ <td style="background: rgb(51, 204, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 255, 0)">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: rgb(255, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(204, 51, 0)">&nbsp;</td>
+ <td style="background: rgb(153, 102, 0)">&nbsp;</td>
+ <td style="background: rgb(102, 153, 0)">&nbsp;</td>
+ <td style="background: rgb(51, 204, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 255, 0)">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: rgb(255, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(204, 51, 0)">&nbsp;</td>
+ <td style="background: rgb(153, 102, 0)">&nbsp;</td>
+ <td style="background: rgb(102, 153, 0)">&nbsp;</td>
+ <td style="background: rgb(51, 204, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 255, 0)">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: rgb(255, 0, 0)">&nbsp;</td>
+ <td style="background: rgb(204, 51, 0)">&nbsp;</td>
+ <td style="background: rgb(153, 102, 0)">&nbsp;</td>
+ <td style="background: rgb(102, 153, 0)">&nbsp;</td>
+ <td style="background: rgb(51, 204, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 255, 0)">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+ </div>
+
+ <p>The following table should have four matching rows changing (in 5 steps) from green at the left to blue at the right: (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <div style="background: blue">
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: rgb(0, 255, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 204, 51)">&nbsp;</td>
+ <td style="background: rgb(0, 153, 102)">&nbsp;</td>
+ <td style="background: rgb(0, 102, 153)">&nbsp;</td>
+ <td style="background: rgb(0, 51, 204)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 255)">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: rgb(0, 255, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 204, 51)">&nbsp;</td>
+ <td style="background: rgb(0, 153, 102)">&nbsp;</td>
+ <td style="background: rgb(0, 102, 153)">&nbsp;</td>
+ <td style="background: rgb(0, 51, 204)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 255)">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: rgb(0, 255, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 204, 51)">&nbsp;</td>
+ <td style="background: rgb(0, 153, 102)">&nbsp;</td>
+ <td style="background: rgb(0, 102, 153)">&nbsp;</td>
+ <td style="background: rgb(0, 51, 204)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 255)">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: rgb(0, 255, 0)">&nbsp;</td>
+ <td style="background: rgb(0, 204, 51)">&nbsp;</td>
+ <td style="background: rgb(0, 153, 102)">&nbsp;</td>
+ <td style="background: rgb(0, 102, 153)">&nbsp;</td>
+ <td style="background: rgb(0, 51, 204)">&nbsp;</td>
+ <td style="background: rgb(0, 0, 255)">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+ </div>
+
+ <p>The following table should have four matching rows changing (in 5 steps) from blue at the left to red at the right (plus a checkerboard at both ends to show where the rows are):</p>
+
+ <div style="background: red">
+ <table border="border">
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: rgb(0, 0, 255)">&nbsp;</td>
+ <td style="background: rgb(51, 0, 204)">&nbsp;</td>
+ <td style="background: rgb(102, 0, 153)">&nbsp;</td>
+ <td style="background: rgb(153, 0, 102)">&nbsp;</td>
+ <td style="background: rgb(204, 0, 51)">&nbsp;</td>
+ <td style="background: rgb(255, 0, 0)">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: rgb(0, 0, 255)">&nbsp;</td>
+ <td style="background: rgb(51, 0, 204)">&nbsp;</td>
+ <td style="background: rgb(102, 0, 153)">&nbsp;</td>
+ <td style="background: rgb(153, 0, 102)">&nbsp;</td>
+ <td style="background: rgb(204, 0, 51)">&nbsp;</td>
+ <td style="background: rgb(255, 0, 0)">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td style="background: rgb(0, 0, 255)">&nbsp;</td>
+ <td style="background: rgb(51, 0, 204)">&nbsp;</td>
+ <td style="background: rgb(102, 0, 153)">&nbsp;</td>
+ <td style="background: rgb(153, 0, 102)">&nbsp;</td>
+ <td style="background: rgb(204, 0, 51)">&nbsp;</td>
+ <td style="background: rgb(255, 0, 0)">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td style="background: rgb(0, 0, 255)">&nbsp;</td>
+ <td style="background: rgb(51, 0, 204)">&nbsp;</td>
+ <td style="background: rgb(102, 0, 153)">&nbsp;</td>
+ <td style="background: rgb(153, 0, 102)">&nbsp;</td>
+ <td style="background: rgb(204, 0, 51)">&nbsp;</td>
+ <td style="background: rgb(255, 0, 0)">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ </table>
+ </div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/t422-rgba-values-meaning-b.xht b/tests/wpt/web-platform-tests/css/css-color/t422-rgba-values-meaning-b.xht
index 27e21cfa48f..daea66c47b8 100644
--- a/tests/wpt/web-platform-tests/css/css-color/t422-rgba-values-meaning-b.xht
+++ b/tests/wpt/web-platform-tests/css/css-color/t422-rgba-values-meaning-b.xht
@@ -5,6 +5,7 @@
<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://www.w3.org/TR/css3-color/#rgba-color" />
+ <link rel="match" href="t422-rgba-values-meaning-b-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="Test that the color components in rgba colors are interpreted correctly." />
<style type="text/css"><![CDATA[
diff --git a/tests/wpt/web-platform-tests/css/css-color/t424-hsl-h-rotating-b-ref.html b/tests/wpt/web-platform-tests/css/css-color/t424-hsl-h-rotating-b-ref.html
new file mode 100644
index 00000000000..60585ea91ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/t424-hsl-h-rotating-b-ref.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ table { border-spacing: 0; padding: 0; border: none; }
+ td { border: none; padding: 0; }
+ td { width: 1.2em; height: 1.2em; }
+ #one { background: #FF0000; }
+ #two { background: #FFFF00; }
+ #three { background: #00FF00; }
+ #four { background: #00FFFF; }
+ #five { background: #0000FF; }
+ #six { background: #FF00FF; }
+</style>
+<body>
+ <p>Each column in the following table should have every cell the
+ same color, except for the checkerboard pattern at the right and
+ left used to indicate the row positions.</p>
+
+ <table>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td id="one">&nbsp;</td>
+ <td id="two">&nbsp;</td>
+ <td id="three">&nbsp;</td>
+ <td id="four">&nbsp;</td>
+ <td id="five">&nbsp;</td>
+ <td id="six">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td id="one">&nbsp;</td>
+ <td id="two">&nbsp;</td>
+ <td id="three">&nbsp;</td>
+ <td id="four">&nbsp;</td>
+ <td id="five">&nbsp;</td>
+ <td id="six">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td id="one">&nbsp;</td>
+ <td id="two">&nbsp;</td>
+ <td id="three">&nbsp;</td>
+ <td id="four">&nbsp;</td>
+ <td id="five">&nbsp;</td>
+ <td id="six">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td id="one">&nbsp;</td>
+ <td id="two">&nbsp;</td>
+ <td id="three">&nbsp;</td>
+ <td id="four">&nbsp;</td>
+ <td id="five">&nbsp;</td>
+ <td id="six">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ </table>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/t424-hsl-h-rotating-b.xht b/tests/wpt/web-platform-tests/css/css-color/t424-hsl-h-rotating-b.xht
index 08196e48ab9..4d2d4cf527b 100644
--- a/tests/wpt/web-platform-tests/css/css-color/t424-hsl-h-rotating-b.xht
+++ b/tests/wpt/web-platform-tests/css/css-color/t424-hsl-h-rotating-b.xht
@@ -5,6 +5,7 @@
<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://www.w3.org/TR/css3-color/#hsl-color" />
+ <link rel="match" href="t424-hsl-h-rotating-b-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="H values in hsl() colors should be treated like angles, even when outside [0,360)" />
<style type="text/css"><![CDATA[
diff --git a/tests/wpt/web-platform-tests/css/css-color/t425-hsla-h-rotating-b-ref.html b/tests/wpt/web-platform-tests/css/css-color/t425-hsla-h-rotating-b-ref.html
new file mode 100644
index 00000000000..2aec2f33e18
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/t425-hsla-h-rotating-b-ref.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ table { border-spacing: 0; padding: 0; border: none; }
+ td { border: none; padding: 0; }
+ td { width: 1.2em; height: 1.2em; }
+ #one { background: #FF0000; }
+ #two { background: rgba(255, 255, 0, 0.8); }
+ #three { background: rgba(0, 255, 0, 0.4); }
+ #four { background: rgba(0, 255, 255, 0.6); }
+ #five { background: rgba(0, 0, 255, 0.8); }
+ #six { background: rgba(255, 0, 255, 0.4); }
+</style>
+<body>
+ <p>Each column in the following table should have every cell the
+ same color, except for the checkerboard pattern at the right and
+ left used to indicate the row positions.</p>
+
+ <table>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td id="one">&nbsp;</td>
+ <td id="two">&nbsp;</td>
+ <td id="three">&nbsp;</td>
+ <td id="four">&nbsp;</td>
+ <td id="five">&nbsp;</td>
+ <td id="six">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td id="one">&nbsp;</td>
+ <td id="two">&nbsp;</td>
+ <td id="three">&nbsp;</td>
+ <td id="four">&nbsp;</td>
+ <td id="five">&nbsp;</td>
+ <td id="six">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: white">&nbsp;</td>
+ <td id="one">&nbsp;</td>
+ <td id="two">&nbsp;</td>
+ <td id="three">&nbsp;</td>
+ <td id="four">&nbsp;</td>
+ <td id="five">&nbsp;</td>
+ <td id="six">&nbsp;</td>
+ <td style="background: black">&nbsp;</td>
+ </tr>
+ <tr>
+ <td style="background: black">&nbsp;</td>
+ <td id="one">&nbsp;</td>
+ <td id="two">&nbsp;</td>
+ <td id="three">&nbsp;</td>
+ <td id="four">&nbsp;</td>
+ <td id="five">&nbsp;</td>
+ <td id="six">&nbsp;</td>
+ <td style="background: white">&nbsp;</td>
+ </tr>
+ </table>
+
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/t425-hsla-h-rotating-b.xht b/tests/wpt/web-platform-tests/css/css-color/t425-hsla-h-rotating-b.xht
index b9339ad9835..09747330d55 100644
--- a/tests/wpt/web-platform-tests/css/css-color/t425-hsla-h-rotating-b.xht
+++ b/tests/wpt/web-platform-tests/css/css-color/t425-hsla-h-rotating-b.xht
@@ -6,6 +6,7 @@
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://www.w3.org/TR/css3-color/#hsl-color" />
<link rel="help" href="http://www.w3.org/TR/css3-color/#hsla-color" />
+ <link rel="match" href="t425-hsla-h-rotating-b-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="H values in hsla() colors should be treated like angles, even when outside [0,360)" />
<style type="text/css"><![CDATA[
diff --git a/tests/wpt/web-platform-tests/css/css-color/t425-hsla-onscreen-b.xht b/tests/wpt/web-platform-tests/css/css-color/t425-hsla-onscreen-b.xht
index 3b5c0b5e405..60b9efc9f12 100644
--- a/tests/wpt/web-platform-tests/css/css-color/t425-hsla-onscreen-b.xht
+++ b/tests/wpt/web-platform-tests/css/css-color/t425-hsla-onscreen-b.xht
@@ -5,11 +5,12 @@
<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://www.w3.org/TR/css3-color/#hsla-color" />
+ <link rel="match" href="t422-rgba-onscreen-b-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="Test that hsla() does not behave like opacity and draw in an offscreen buffer." />
<style type="text/css"><![CDATA[
html, body { background: white; }
- table { border-spacing: 0; padding: 0; border: none; }
+ table { border-spacing: 0 2px; padding: 0; border: none; }
td { border: none; padding: 0; }
td, div { height: 1.2em; }
diff --git a/tests/wpt/web-platform-tests/css/css-color/t43-svg-keywords-a-ref.html b/tests/wpt/web-platform-tests/css/css-color/t43-svg-keywords-a-ref.html
new file mode 100644
index 00000000000..cd26c49dc10
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-color/t43-svg-keywords-a-ref.html
@@ -0,0 +1,165 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reference</title>
+<style>
+ html, body { background: #dddddd; color: #000000; }
+ table { border-spacing: 0; padding: 0; border: none; }
+ td { border: none; padding: 0; }
+</style>
+<body>
+ <p>Each row in the following table (except the first and last, to show where the columns are) should have two cells with the same background color. None of them should match the background of the page.</p>
+
+ <table>
+ <tr><td style="background: black">&nbsp;&nbsp;&nbsp;</td><td style="background: white">&nbsp;&nbsp;&nbsp;</td></tr>
+
+ <tr><td style="background: #f0f8ff" colspan=2>&nbsp;</td>
+ <tr><td style="background: #faebd7" colspan=2>&nbsp;</td>
+ <tr><td style="background: #00ffff" colspan=2>&nbsp;</td>
+ <tr><td style="background: #7fffd4" colspan=2>&nbsp;</td>
+ <tr><td style="background: #f0ffff" colspan=2>&nbsp;</td>
+ <tr><td style="background: #f5f5dc" colspan=2>&nbsp;</td>
+ <tr><td style="background: #ffe4c4" colspan=2>&nbsp;</td>
+ <tr><td style="background: #000000" colspan=2>&nbsp;</td>
+ <tr><td style="background: #ffebcd" colspan=2>&nbsp;</td>
+ <tr><td style="background: #0000ff" colspan=2>&nbsp;</td>
+ <tr><td style="background: #8a2be2" colspan=2>&nbsp;</td>
+ <tr><td style="background: #a52a2a" colspan=2>&nbsp;</td>
+ <tr><td style="background: #deb887" colspan=2>&nbsp;</td>
+ <tr><td style="background: #5f9ea0" colspan=2>&nbsp;</td>
+ <tr><td style="background: #7fff00" colspan=2>&nbsp;</td>
+ <tr><td style="background: #d2691e" colspan=2>&nbsp;</td>
+ <tr><td style="background: #ff7f50" colspan=2>&nbsp;</td>
+ <tr><td style="background: #6495ed" colspan=2>&nbsp;</td>
+ <tr><td style="background: #fff8dc" colspan=2>&nbsp;</td>
+ <tr><td style="background: #dc143c" colspan=2>&nbsp;</td>
+ <tr><td style="background: #00ffff" colspan=2>&nbsp;</td>
+ <tr><td style="background: #00008b" colspan=2>&nbsp;</td>
+ <tr><td style="background: #008b8b" colspan=2>&nbsp;</td>
+ <tr><td style="background: #b8860b" colspan=2>&nbsp;</td>
+ <tr><td style="background: #a9a9a9" colspan=2>&nbsp;</td>
+ <tr><td style="background: #006400" colspan=2>&nbsp;</td>
+ <tr><td style="background: #a9a9a9" colspan=2>&nbsp;</td>
+ <tr><td style="background: #bdb76b" colspan=2>&nbsp;</td>
+ <tr><td style="background: #8b008b" colspan=2>&nbsp;</td>
+ <tr><td style="background: #556b2f" colspan=2>&nbsp;</td>
+ <tr><td style="background: #ff8c00" colspan=2>&nbsp;</td>
+ <tr><td style="background: #9932cc" colspan=2>&nbsp;</td>
+ <tr><td style="background: #8b0000" colspan=2>&nbsp;</td>
+ <tr><td style="background: #e9967a" colspan=2>&nbsp;</td>
+ <tr><td style="background: #8fbc8f" colspan=2>&nbsp;</td>
+ <tr><td style="background: #483d8b" colspan=2>&nbsp;</td>
+ <tr><td style="background: #2f4f4f" colspan=2>&nbsp;</td>
+ <tr><td style="background: #2f4f4f" colspan=2>&nbsp;</td>
+ <tr><td style="background: #00ced1" colspan=2>&nbsp;</td>
+ <tr><td style="background: #9400d3" colspan=2>&nbsp;</td>
+ <tr><td style="background: #ff1493" colspan=2>&nbsp;</td>
+ <tr><td style="background: #00bfff" colspan=2>&nbsp;</td>
+ <tr><td style="background: #696969" colspan=2>&nbsp;</td>
+ <tr><td style="background: #696969" colspan=2>&nbsp;</td>
+ <tr><td style="background: #1e90ff" colspan=2>&nbsp;</td>
+ <tr><td style="background: #b22222" colspan=2>&nbsp;</td>
+ <tr><td style="background: #fffaf0" colspan=2>&nbsp;</td>
+ <tr><td style="background: #228b22" colspan=2>&nbsp;</td>
+ <tr><td style="background: #ff00ff" colspan=2>&nbsp;</td>
+ <tr><td style="background: #dcdcdc" colspan=2>&nbsp;</td>
+ <tr><td style="background: #f8f8ff" colspan=2>&nbsp;</td>
+ <tr><td style="background: #ffd700" colspan=2>&nbsp;</td>
+ <tr><td style="background: #daa520" colspan=2>&nbsp;</td>
+ <tr><td style="background: #808080" colspan=2>&nbsp;</td>
+ <tr><td style="background: #008000" colspan=2>&nbsp;</td>
+ <tr><td style="background: #adff2f" colspan=2>&nbsp;</td>
+ <tr><td style="background: #808080" colspan=2>&nbsp;</td>
+ <tr><td style="background: #f0fff0" colspan=2>&nbsp;</td>
+ <tr><td style="background: #ff69b4" colspan=2>&nbsp;</td>
+ <tr><td style="background: #cd5c5c" colspan=2>&nbsp;</td>
+ <tr><td style="background: #4b0082" colspan=2>&nbsp;</td>
+ <tr><td style="background: #fffff0" colspan=2>&nbsp;</td>
+ <tr><td style="background: #f0e68c" colspan=2>&nbsp;</td>
+ <tr><td style="background: #e6e6fa" colspan=2>&nbsp;</td>
+ <tr><td style="background: #fff0f5" colspan=2>&nbsp;</td>
+ <tr><td style="background: #7cfc00" colspan=2>&nbsp;</td>
+ <tr><td style="background: #fffacd" colspan=2>&nbsp;</td>
+ <tr><td style="background: #add8e6" colspan=2>&nbsp;</td>
+ <tr><td style="background: #f08080" colspan=2>&nbsp;</td>
+ <tr><td style="background: #e0ffff" colspan=2>&nbsp;</td>
+ <tr><td style="background: #fafad2" colspan=2>&nbsp;</td>
+ <tr><td style="background: #d3d3d3" colspan=2>&nbsp;</td>
+ <tr><td style="background: #90ee90" colspan=2>&nbsp;</td>
+ <tr><td style="background: #d3d3d3" colspan=2>&nbsp;</td>
+ <tr><td style="background: #ffb6c1" colspan=2>&nbsp;</td>
+ <tr><td style="background: #ffa07a" colspan=2>&nbsp;</td>
+ <tr><td style="background: #20b2aa" colspan=2>&nbsp;</td>
+ <tr><td style="background: #87cefa" colspan=2>&nbsp;</td>
+ <tr><td style="background: #778899" colspan=2>&nbsp;</td>
+ <tr><td style="background: #778899" colspan=2>&nbsp;</td>
+ <tr><td style="background: #b0c4de" colspan=2>&nbsp;</td>
+ <tr><td style="background: #ffffe0" colspan=2>&nbsp;</td>
+ <tr><td style="background: #00ff00" colspan=2>&nbsp;</td>
+ <tr><td style="background: #32cd32" colspan=2>&nbsp;</td>
+ <tr><td style="background: #faf0e6" colspan=2>&nbsp;</td>
+ <tr><td style="background: #ff00ff" colspan=2>&nbsp;</td>
+ <tr><td style="background: #800000" colspan=2>&nbsp;</td>
+ <tr><td style="background: #66cdaa" colspan=2>&nbsp;</td>
+ <tr><td style="background: #0000cd" colspan=2>&nbsp;</td>
+ <tr><td style="background: #ba55d3" colspan=2>&nbsp;</td>
+ <tr><td style="background: #9370db" colspan=2>&nbsp;</td>
+ <tr><td style="background: #3cb371" colspan=2>&nbsp;</td>
+ <tr><td style="background: #7b68ee" colspan=2>&nbsp;</td>
+ <tr><td style="background: #00fa9a" colspan=2>&nbsp;</td>
+ <tr><td style="background: #48d1cc" colspan=2>&nbsp;</td>
+ <tr><td style="background: #c71585" colspan=2>&nbsp;</td>
+ <tr><td style="background: #191970" colspan=2>&nbsp;</td>
+ <tr><td style="background: #f5fffa" colspan=2>&nbsp;</td>
+ <tr><td style="background: #ffe4e1" colspan=2>&nbsp;</td>
+ <tr><td style="background: #ffe4b5" colspan=2>&nbsp;</td>
+ <tr><td style="background: #ffdead" colspan=2>&nbsp;</td>
+ <tr><td style="background: #000080" colspan=2>&nbsp;</td>
+ <tr><td style="background: #fdf5e6" colspan=2>&nbsp;</td>
+ <tr><td style="background: #808000" colspan=2>&nbsp;</td>
+ <tr><td style="background: #6b8e23" colspan=2>&nbsp;</td>
+ <tr><td style="background: #ffa500" colspan=2>&nbsp;</td>
+ <tr><td style="background: #ff4500" colspan=2>&nbsp;</td>
+ <tr><td style="background: #da70d6" colspan=2>&nbsp;</td>
+ <tr><td style="background: #eee8aa" colspan=2>&nbsp;</td>
+ <tr><td style="background: #98fb98" colspan=2>&nbsp;</td>
+ <tr><td style="background: #afeeee" colspan=2>&nbsp;</td>
+ <tr><td style="background: #db7093" colspan=2>&nbsp;</td>
+ <tr><td style="background: #ffefd5" colspan=2>&nbsp;</td>
+ <tr><td style="background: #ffdab9" colspan=2>&nbsp;</td>
+ <tr><td style="background: #cd853f" colspan=2>&nbsp;</td>
+ <tr><td style="background: #ffc0cb" colspan=2>&nbsp;</td>
+ <tr><td style="background: #dda0dd" colspan=2>&nbsp;</td>
+ <tr><td style="background: #b0e0e6" colspan=2>&nbsp;</td>
+ <tr><td style="background: #800080" colspan=2>&nbsp;</td>
+ <tr><td style="background: #ff0000" colspan=2>&nbsp;</td>
+ <tr><td style="background: #bc8f8f" colspan=2>&nbsp;</td>
+ <tr><td style="background: #4169e1" colspan=2>&nbsp;</td>
+ <tr><td style="background: #8b4513" colspan=2>&nbsp;</td>
+ <tr><td style="background: #fa8072" colspan=2>&nbsp;</td>
+ <tr><td style="background: #f4a460" colspan=2>&nbsp;</td>
+ <tr><td style="background: #2e8b57" colspan=2>&nbsp;</td>
+ <tr><td style="background: #fff5ee" colspan=2>&nbsp;</td>
+ <tr><td style="background: #a0522d" colspan=2>&nbsp;</td>
+ <tr><td style="background: #c0c0c0" colspan=2>&nbsp;</td>
+ <tr><td style="background: #87ceeb" colspan=2>&nbsp;</td>
+ <tr><td style="background: #6a5acd" colspan=2>&nbsp;</td>
+ <tr><td style="background: #708090" colspan=2>&nbsp;</td>
+ <tr><td style="background: #708090" colspan=2>&nbsp;</td>
+ <tr><td style="background: #fffafa" colspan=2>&nbsp;</td>
+ <tr><td style="background: #00ff7f" colspan=2>&nbsp;</td>
+ <tr><td style="background: #4682b4" colspan=2>&nbsp;</td>
+ <tr><td style="background: #d2b48c" colspan=2>&nbsp;</td>
+ <tr><td style="background: #008080" colspan=2>&nbsp;</td>
+ <tr><td style="background: #d8bfd8" colspan=2>&nbsp;</td>
+ <tr><td style="background: #ff6347" colspan=2>&nbsp;</td>
+ <tr><td style="background: #40e0d0" colspan=2>&nbsp;</td>
+ <tr><td style="background: #ee82ee" colspan=2>&nbsp;</td>
+ <tr><td style="background: #f5deb3" colspan=2>&nbsp;</td>
+ <tr><td style="background: #ffffff" colspan=2>&nbsp;</td>
+ <tr><td style="background: #f5f5f5" colspan=2>&nbsp;</td>
+ <tr><td style="background: #ffff00" colspan=2>&nbsp;</td>
+ <tr><td style="background: #9acd32" colspan=2>&nbsp;</td>
+
+ <tr><td style="background: white">&nbsp;&nbsp;&nbsp;</td><td style="background: black">&nbsp;&nbsp;&nbsp;</td></tr>
+ </table>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-color/t43-svg-keywords-a.xht b/tests/wpt/web-platform-tests/css/css-color/t43-svg-keywords-a.xht
index 69b6aef6c10..75bbf4f70f1 100644
--- a/tests/wpt/web-platform-tests/css/css-color/t43-svg-keywords-a.xht
+++ b/tests/wpt/web-platform-tests/css/css-color/t43-svg-keywords-a.xht
@@ -5,6 +5,7 @@
<link rel="author" title="L. David Baron" href="https://dbaron.org/" />
<link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
<link rel="help" href="http://www.w3.org/TR/css3-color/#html4" />
+ <link rel="match" href="t43-svg-keywords-a-ref.html" />
<meta name="flags" content="" />
<meta name="assert" content="Test that the HTML4 color keywords have the correct values." />
<style type="text/css"><![CDATA[
diff --git a/tests/wpt/web-platform-tests/css/css-color/whitetext-ref.html b/tests/wpt/web-platform-tests/css/css-color/whitetext-ref.html
index 5cb0997bd8f..0237a810eb9 100644
--- a/tests/wpt/web-platform-tests/css/css-color/whitetext-ref.html
+++ b/tests/wpt/web-platform-tests/css/css-color/whitetext-ref.html
@@ -5,5 +5,5 @@
.test { color: #FFFFFF; background-color: #333; padding: 3px}
</style>
<body>
- <p class="test">Test passess if this text is white</p>
+ <p class="test">Test passes if this text is white</p>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-conditional/test_group_insertRule.html b/tests/wpt/web-platform-tests/css/css-conditional/test_group_insertRule.html
index 85edc2a1a0b..f34245ec472 100644
--- a/tests/wpt/web-platform-tests/css/css-conditional/test_group_insertRule.html
+++ b/tests/wpt/web-platform-tests/css/css-conditional/test_group_insertRule.html
@@ -11,26 +11,6 @@
<style id="style">
@media print {}
</style>
-<script id="metadata_cache">/*
-{
- "rule_type": {},
- "rule_length": {},
- "insert_import_throws": {},
- "insert_index_throws1": {},
- "insert_index_throws2": {},
- "insert_media_succeed": {},
- "insert_style_succeed": {},
- "insert_bad_media_throw": {},
- "insert_empty_throw": {},
- "insert_garbage_after_media_throw": {},
- "insert_garbage_after_style_throw": {},
- "insert_two_media_throw": {},
- "insert_style_media_throw": {},
- "insert_media_style_throw": {},
- "insert_two_style_throw": {},
- "insert_retval": {}
-}
-*/</script>
</head>
<body onload="run()">
<div id=log></div>
@@ -240,4 +220,3 @@
</script>
</body>
</html>
-
diff --git a/tests/wpt/web-platform-tests/css/css-contain/contain-style-counters-ref.html b/tests/wpt/web-platform-tests/css/css-contain/contain-style-counters-ref.html
new file mode 100644
index 00000000000..feef9209f5c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-contain/contain-style-counters-ref.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<title>CSS Containment Reference File</title>
+<div>You should see the number 1 here: 1</div>
+<div>You should see the number 4 here: 4</div>
diff --git a/tests/wpt/web-platform-tests/css/css-contain/contain-style-counters.html b/tests/wpt/web-platform-tests/css/css-contain/contain-style-counters.html
new file mode 100644
index 00000000000..73de6dc9604
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-contain/contain-style-counters.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<title>CSS Containment Test: contain:style for counters</title>
+<link rel="help" href="https://drafts.csswg.org/css-contain/#containment-style">
+<link rel="match" href="contain-style-counters-ref.html">
+<style>
+ #t1 { contain: style }
+ #t1 span::after { content: counter(t1) }
+ .t1-reset { counter-reset: t1 5 }
+ #t1 span { counter-increment: t1 1 }
+
+ #t2 {
+ contain: style;
+ display: contents;
+ }
+ #t2 span::after { content: counter(t2) }
+ .t2-reset { counter-reset: t2 7; }
+ #t2 span { counter-increment: t2 4; }
+</style>
+<div class="t1-reset"></div>
+<div id="t1"><span>You should see the number 1 here: </span></div>
+<div class="t2-reset"></div>
+<div id="t2"><span>You should see the number 4 here: </span></div>
diff --git a/tests/wpt/web-platform-tests/css/css-display/display-contents-before-after-003.html b/tests/wpt/web-platform-tests/css/css-display/display-contents-before-after-003.html
new file mode 100644
index 00000000000..772ad440c26
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/display-contents-before-after-003.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Display: Generated ::before and ::after with display:contents inside flex</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-display-3/#valdef-display-contents">
+<link rel="match" href="display-contents-pass-ref.html">
+<style>
+ .flex { display: inline-flex; flex-direction: column }
+ .flex::before { display: contents; content: "A" }
+ .flex::after { display: contents; content: "S" }
+</style>
+<!-- The before and after pseudo elements do not generate boxes due to
+ display:contents, so that their generated text content constitutes a
+ contiguous sequence of child text runs which means they end up in the same
+ flex item. -->
+<p>You should see the word PASS below.</p>
+P<div class="flex"></div>S
diff --git a/tests/wpt/web-platform-tests/css/css-display/display-contents-button.html b/tests/wpt/web-platform-tests/css/css-display/display-contents-button.html
new file mode 100644
index 00000000000..c166583ff6c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/display-contents-button.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Display: display:contents and HTML button element</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-display/#unbox-html">
+<link rel="match" href="display-contents-pass-ref.html">
+<style>
+ button {
+ all: initial;
+ border: 10px solid red;
+ display: contents;
+ }
+</style>
+<p>You should see the word PASS below.</p>
+<button>P<!---->A<!---->S<!---->S</button>
diff --git a/tests/wpt/web-platform-tests/css/css-display/display-contents-details.html b/tests/wpt/web-platform-tests/css/css-display/display-contents-details.html
new file mode 100644
index 00000000000..b6a6540f013
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/display-contents-details.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Display: display:contents and HTML details and summary elements</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-display/#unbox-html">
+<link rel="match" href="display-contents-pass-ref.html">
+<style>
+ details, summary {
+ all: initial;
+ border: 10px solid red;
+ display: contents;
+ }
+</style>
+<p>You should see the word PASS below.</p>
+P<details open><summary>A</summary><span>S</span></details>S
diff --git a/tests/wpt/web-platform-tests/css/css-display/display-contents-dynamic-pseudo-insertion-001-ref.html b/tests/wpt/web-platform-tests/css/css-display/display-contents-dynamic-pseudo-insertion-001-ref.html
new file mode 100644
index 00000000000..38dd74a744d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/display-contents-dynamic-pseudo-insertion-001-ref.html
@@ -0,0 +1,5 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Test Reference</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+P<span>A</span>SS
diff --git a/tests/wpt/web-platform-tests/css/css-display/display-contents-dynamic-pseudo-insertion-001.html b/tests/wpt/web-platform-tests/css/css-display/display-contents-dynamic-pseudo-insertion-001.html
new file mode 100644
index 00000000000..f35c3cc47b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/display-contents-dynamic-pseudo-insertion-001.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Test: Dynamic insertion on empty display: contents element with pseudo-elements</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="help" href="https://drafts.csswg.org/css-display-3/#valdef-display-contents">
+<link rel=match href="display-contents-dynamic-pseudo-insertion-001-ref.html">
+<style>
+.contents {
+ display: contents;
+ border: 10px solid red;
+}
+.contents::before {
+ content: "A";
+}
+.contents::after {
+ content: "SS";
+}
+</style>
+<div class="contents"></div>
+<script>
+document.body.offsetTop;
+let span = document.createElement('span');
+span.innerHTML = "P";
+let contents = document.querySelector('.contents');
+contents.parentNode.insertBefore(span, contents);
+</script>
diff --git a/tests/wpt/web-platform-tests/css/css-display/display-contents-fieldset.html b/tests/wpt/web-platform-tests/css/css-display/display-contents-fieldset.html
new file mode 100644
index 00000000000..5dcd343143f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/display-contents-fieldset.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Display: display:contents and HTML fieldset and legend elements</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-display/#unbox-html">
+<link rel="match" href="display-contents-pass-ref.html">
+<style>
+ fieldset, legend {
+ all: initial;
+ border: 10px solid red;
+ display: contents;
+ }
+</style>
+<p>You should see the word PASS below.</p>
+P<fieldset>A<legend>S</legend>S</fieldset>
diff --git a/tests/wpt/web-platform-tests/css/css-display/display-contents-first-letter-002.html b/tests/wpt/web-platform-tests/css/css-display/display-contents-first-letter-002.html
new file mode 100644
index 00000000000..8d1d8572ac1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/display-contents-first-letter-002.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Display: display:contents and ::first-letter inheritance</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-display-3/#valdef-display-contents">
+<link rel="help" href="https://drafts.csswg.org/css-pseudo-4/#first-letter-pseudo">
+<link rel="match" href="display-contents-pass-green-no-red-ref.html">
+<style>
+ div { color: red }
+ div::first-letter { background: transparent /* To trigger first-letter pseudo element */ }
+ span { color: green; display: contents; background-color: red }
+</style>
+<p>You should see the word PASS in green and no red below.</p>
+<div><span>PASS</span></div>
diff --git a/tests/wpt/web-platform-tests/css/css-display/display-contents-first-line-002.html b/tests/wpt/web-platform-tests/css/css-display/display-contents-first-line-002.html
new file mode 100644
index 00000000000..ae900235a5e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/display-contents-first-line-002.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Display: display:contents and ::first-line inheritance</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-display-3/#valdef-display-contents">
+<link rel="help" href="https://drafts.csswg.org/css-pseudo-4/#first-line-pseudo">
+<link rel="match" href="display-contents-pass-green-no-red-ref.html">
+<style>
+ span { color: green }
+ .contents { display: contents }
+ #container::first-line { color: red }
+</style>
+<p>You should see the word PASS in green and no red below.</p>
+<div id="container">
+ <span class="contents">P</span><span>ASS</span>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-display/display-contents-line-height-ref.html b/tests/wpt/web-platform-tests/css/css-display/display-contents-line-height-ref.html
new file mode 100644
index 00000000000..d06c63f09f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/display-contents-line-height-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reftest Reference</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<style>
+ span { font-size: 40px; }
+</style>
+<p>The two lines below should not overlap.</p>
+<span>Line 1</span><br><span>Line 2</span>
diff --git a/tests/wpt/web-platform-tests/css/css-display/display-contents-line-height.html b/tests/wpt/web-platform-tests/css/css-display/display-contents-line-height.html
new file mode 100644
index 00000000000..31fd5a6d479
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/display-contents-line-height.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Display: display:contents font-size should affect line-height</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-display-3/#valdef-display-contents">
+<link rel="match" href="display-contents-line-height-ref.html">
+<style>
+ span {
+ display: contents;
+ font-size: 40px;
+ }
+</style>
+<p>The two lines below should not overlap.</p>
+<span>Line 1</span><br><span>Line 2</span>
diff --git a/tests/wpt/web-platform-tests/css/css-display/display-contents-replaced-001-ref.html b/tests/wpt/web-platform-tests/css/css-display/display-contents-replaced-001-ref.html
deleted file mode 100644
index ff807c7575d..00000000000
--- a/tests/wpt/web-platform-tests/css/css-display/display-contents-replaced-001-ref.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Reftest Reference</title>
-<link rel="author" title="Rune Lillesveen" href="mailto:rune@opera.com">
-<style>
- button, img, input, textarea {
- display: contents;
- border: 10px solid green
- }
-</style>
-<p>You should see five form inputs, and an orange image, with green border below.</p>
-<button>Button</button>
-<input type="text" value="text"></input>
-<input type="file"></input>
-<input type="password" value="password"></input>
-<textarea>textarea</textarea>
-<img src="support/swatch-orange.png">
diff --git a/tests/wpt/web-platform-tests/css/css-display/display-contents-replaced-001.html b/tests/wpt/web-platform-tests/css/css-display/display-contents-replaced-001.html
deleted file mode 100644
index 22d3995feb1..00000000000
--- a/tests/wpt/web-platform-tests/css/css-display/display-contents-replaced-001.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Display: display:contents and replaced elements</title>
-<link rel="author" title="Rune Lillesveen" href="mailto:rune@opera.com">
-<link rel="help" href="https://drafts.csswg.org/css-display-3/#valdef-display-contents">
-<link rel="match" href="display-contents-replaced-001-ref.html">
-<style>
- button, img, input, textarea {
- display: contents;
- border: 10px solid green
- }
-</style>
-<p>You should see five form inputs, and an orange image, with green border below.</p>
-<button>Button</button>
-<input type="text" value="text"></input>
-<input type="file"></input>
-<input type="password" value="password"></input>
-<textarea>textarea</textarea>
-<img src="support/swatch-orange.png">
diff --git a/tests/wpt/web-platform-tests/css/css-display/display-contents-svg-elements-ref.html b/tests/wpt/web-platform-tests/css/css-display/display-contents-svg-elements-ref.html
new file mode 100644
index 00000000000..b691e0e80ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/display-contents-svg-elements-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reftest Reference</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<p>You should see the word PASS below.</p>
+<div style="font: 16px monospace">
+ <svg>
+ <text x="0" y="20">P</text>
+ <text x="10" y="20">A</text>
+ <text x="20" y="20">S</text>
+ <text x="30" y="20">S</text>
+ </svg>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-display/display-contents-svg-elements.html b/tests/wpt/web-platform-tests/css/css-display/display-contents-svg-elements.html
new file mode 100644
index 00000000000..7ccc92f7207
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/display-contents-svg-elements.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Display: display:contents and SVG elements</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-display/#unbox-svg">
+<link rel="match" href="display-contents-svg-elements-ref.html">
+<p>You should see the word PASS below.</p>
+<div style="font: 16px monospace">
+ <svg>
+ <defs><text x="20" y="20" id="S">S</text></defs>
+ <text y="40" style="display:contents">FAIL</text>
+ <svg style="display:contents;opacity:0">
+ <text x="0" y="20">P</text>
+ </svg>
+ <g style="display:contents;opacity:0">
+ <text x="10" y="20"><tspan dx="2000" style="display:contents;opacity:0">A</tspan></text>
+ </g>
+ <use xlink:href="#S" style="display:contents;opacity:0"></use>
+ <text x="30" y="20">S</text>
+ </svg>
+ <svg style="display:contents"><text y="40">FAIL</text></svg>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-display/display-contents-text-inherit-ref.html b/tests/wpt/web-platform-tests/css/css-display/display-contents-text-inherit-ref.html
new file mode 100644
index 00000000000..163efd401c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/display-contents-text-inherit-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reftest Reference</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<p>The words "Two" and "lines" should not be on the same line.</p>
+Two<br>
+lines
diff --git a/tests/wpt/web-platform-tests/css/css-display/display-contents-text-inherit.html b/tests/wpt/web-platform-tests/css/css-display/display-contents-text-inherit.html
new file mode 100644
index 00000000000..b7e769cd69f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/display-contents-text-inherit.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Display: Apply display:contents text properties to text children</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-display-3/#valdef-display-contents">
+<link rel="match" href="display-contents-text-inherit-ref.html">
+<style>
+ div {
+ display: contents;
+ white-space: pre;
+ }
+</style>
+<p>The words "Two" and "lines" should not be on the same line.</p>
+<div>Two
+lines</div>
diff --git a/tests/wpt/web-platform-tests/css/css-display/display-contents-unusual-html-elements-none.html b/tests/wpt/web-platform-tests/css/css-display/display-contents-unusual-html-elements-none.html
new file mode 100644
index 00000000000..403ff5ce299
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/display-contents-unusual-html-elements-none.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Display: display:contents and unusual HTML elements as display:none</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-display/#unbox-html">
+<link rel="match" href="display-contents-pass-ref.html">
+<style>
+ body { overflow: hidden }
+ br, wbr, meter, progress, canvas, embed, object, audio, iframe, img, video,
+ input, textarea, select {
+ display: contents;
+ border: 10px solid red;
+ width: 200px; height: 200px;
+ }
+</style>
+<p>You should see the word PASS below.</p>
+<div>
+ <meter></meter>
+ <progress></progress>
+ <canvas></canvas>
+ <embed>
+ <object>FAIL</object>
+ <audio controls></audio>
+ <iframe></iframe>
+ <img>
+ <video></video>
+ <input></input>
+ <textarea></textarea>
+ <select></select>
+</div>
+P<br>A<wbr>S<br>S
diff --git a/tests/wpt/web-platform-tests/css/css-block/OWNERS b/tests/wpt/web-platform-tests/css/css-display/run-in/OWNERS
index 675c2c214b5..675c2c214b5 100644
--- a/tests/wpt/web-platform-tests/css/css-block/OWNERS
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/OWNERS
diff --git a/tests/wpt/web-platform-tests/css/css-block/after-content-display-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/after-content-display-004.xht
index fbcd4e8c265..fbcd4e8c265 100644
--- a/tests/wpt/web-platform-tests/css/css-block/after-content-display-004.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/after-content-display-004.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/anonymous-box-generation-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/anonymous-box-generation-002.xht
index 0a462a93109..0a462a93109 100644
--- a/tests/wpt/web-platform-tests/css/css-block/anonymous-box-generation-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/anonymous-box-generation-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/background-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/background-applies-to-011.xht
index b06a5f537c8..b06a5f537c8 100644
--- a/tests/wpt/web-platform-tests/css/css-block/background-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/background-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/background-attachment-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/background-attachment-applies-to-011.xht
index 9f2c78913bb..9f2c78913bb 100644
--- a/tests/wpt/web-platform-tests/css/css-block/background-attachment-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/background-attachment-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/background-color-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/background-color-applies-to-011.xht
index d2bd6e098a5..d2bd6e098a5 100644
--- a/tests/wpt/web-platform-tests/css/css-block/background-color-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/background-color-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/background-image-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/background-image-applies-to-011.xht
index 84ade797600..84ade797600 100644
--- a/tests/wpt/web-platform-tests/css/css-block/background-image-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/background-image-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/background-position-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/background-position-applies-to-011.xht
index 33b3cb8c16f..33b3cb8c16f 100644
--- a/tests/wpt/web-platform-tests/css/css-block/background-position-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/background-position-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/background-repeat-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/background-repeat-applies-to-011.xht
index 236b30a5ad6..236b30a5ad6 100644
--- a/tests/wpt/web-platform-tests/css/css-block/background-repeat-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/background-repeat-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/before-content-display-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/before-content-display-004.xht
index 708df1d4ff8..708df1d4ff8 100644
--- a/tests/wpt/web-platform-tests/css/css-block/before-content-display-004.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/before-content-display-004.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/border-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/border-applies-to-011.xht
index 2f54995f7b6..2f54995f7b6 100644
--- a/tests/wpt/web-platform-tests/css/css-block/border-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/border-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/border-bottom-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/border-bottom-applies-to-011.xht
index 6585584f98d..6585584f98d 100644
--- a/tests/wpt/web-platform-tests/css/css-block/border-bottom-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/border-bottom-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/border-bottom-color-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/border-bottom-color-applies-to-011.xht
index f68213dabed..f68213dabed 100644
--- a/tests/wpt/web-platform-tests/css/css-block/border-bottom-color-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/border-bottom-color-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/border-bottom-style-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/border-bottom-style-applies-to-011.xht
index 13f2aae3aa0..13f2aae3aa0 100644
--- a/tests/wpt/web-platform-tests/css/css-block/border-bottom-style-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/border-bottom-style-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/border-bottom-width-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/border-bottom-width-applies-to-011.xht
index 6fed0f8359d..6fed0f8359d 100644
--- a/tests/wpt/web-platform-tests/css/css-block/border-bottom-width-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/border-bottom-width-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/border-collapse-applies-to-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/border-collapse-applies-to-004.xht
index 67866148220..67866148220 100644
--- a/tests/wpt/web-platform-tests/css/css-block/border-collapse-applies-to-004.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/border-collapse-applies-to-004.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/border-color-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/border-color-applies-to-011.xht
index 3524867b343..3524867b343 100644
--- a/tests/wpt/web-platform-tests/css/css-block/border-color-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/border-color-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/border-left-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/border-left-applies-to-011.xht
index e6102ba8ff1..e6102ba8ff1 100644
--- a/tests/wpt/web-platform-tests/css/css-block/border-left-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/border-left-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/border-left-color-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/border-left-color-applies-to-011.xht
index 6365a605729..6365a605729 100644
--- a/tests/wpt/web-platform-tests/css/css-block/border-left-color-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/border-left-color-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/border-left-style-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/border-left-style-applies-to-011.xht
index eaf30a45ea2..eaf30a45ea2 100644
--- a/tests/wpt/web-platform-tests/css/css-block/border-left-style-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/border-left-style-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/border-left-width-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/border-left-width-applies-to-011.xht
index 6efb1b1a999..6efb1b1a999 100644
--- a/tests/wpt/web-platform-tests/css/css-block/border-left-width-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/border-left-width-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/border-right-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/border-right-applies-to-011.xht
index 1bcd8ee4b89..1bcd8ee4b89 100644
--- a/tests/wpt/web-platform-tests/css/css-block/border-right-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/border-right-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/border-right-color-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/border-right-color-applies-to-011.xht
index 19cac09e10b..19cac09e10b 100644
--- a/tests/wpt/web-platform-tests/css/css-block/border-right-color-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/border-right-color-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/border-right-style-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/border-right-style-applies-to-011.xht
index bf2b6d32410..bf2b6d32410 100644
--- a/tests/wpt/web-platform-tests/css/css-block/border-right-style-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/border-right-style-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/border-right-width-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/border-right-width-applies-to-011.xht
index 78595a8f876..78595a8f876 100644
--- a/tests/wpt/web-platform-tests/css/css-block/border-right-width-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/border-right-width-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/border-spacing-applies-to-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/border-spacing-applies-to-004.xht
index da6bb3b5d86..da6bb3b5d86 100644
--- a/tests/wpt/web-platform-tests/css/css-block/border-spacing-applies-to-004.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/border-spacing-applies-to-004.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/border-style-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/border-style-applies-to-011.xht
index a7f62b23381..a7f62b23381 100644
--- a/tests/wpt/web-platform-tests/css/css-block/border-style-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/border-style-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/border-top-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/border-top-applies-to-011.xht
index 8e5b6a67c0d..8e5b6a67c0d 100644
--- a/tests/wpt/web-platform-tests/css/css-block/border-top-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/border-top-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/border-top-color-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/border-top-color-applies-to-011.xht
index b3fcb42df89..b3fcb42df89 100644
--- a/tests/wpt/web-platform-tests/css/css-block/border-top-color-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/border-top-color-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/border-top-style-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/border-top-style-applies-to-011.xht
index 1716cca1e0a..1716cca1e0a 100644
--- a/tests/wpt/web-platform-tests/css/css-block/border-top-style-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/border-top-style-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/border-top-width-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/border-top-width-applies-to-011.xht
index 8ec95ca4fcc..8ec95ca4fcc 100644
--- a/tests/wpt/web-platform-tests/css/css-block/border-top-width-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/border-top-width-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/border-width-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/border-width-applies-to-011.xht
index f9431b1ccb4..f9431b1ccb4 100644
--- a/tests/wpt/web-platform-tests/css/css-block/border-width-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/border-width-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/bottom-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/bottom-applies-to-011.xht
index b7e78eeed1e..b7e78eeed1e 100644
--- a/tests/wpt/web-platform-tests/css/css-block/bottom-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/bottom-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/caption-side-applies-to-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/caption-side-applies-to-004.xht
index f725df6e837..f725df6e837 100644
--- a/tests/wpt/web-platform-tests/css/css-block/caption-side-applies-to-004.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/caption-side-applies-to-004.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/clear-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/clear-applies-to-011.xht
index e64864ab880..e64864ab880 100644
--- a/tests/wpt/web-platform-tests/css/css-block/clear-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/clear-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/clear-runin-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/clear-runin-001.xht
index 4bc1165024c..4bc1165024c 100644
--- a/tests/wpt/web-platform-tests/css/css-block/clear-runin-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/clear-runin-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/color-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/color-applies-to-011.xht
index 373de932ecd..373de932ecd 100644
--- a/tests/wpt/web-platform-tests/css/css-block/color-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/color-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-display/run-in/counter-increment-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/counter-increment-applies-to-011.xht
new file mode 100644
index 00000000000..4bf9e1233fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/counter-increment-applies-to-011.xht
@@ -0,0 +1,27 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>CSS Test: Counter-increment applied to elements with 'display' set to 'run-in'</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-counter-increment" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#counters" />
+ <link rel="match" href="../../reference/pass_if_number_5.xht"/>
+ <meta name="flags" content="" />
+ <meta name="assert" content="The 'counter-increment' property applies to elements with a 'display' set to 'run-in'." />
+ <style type="text/css">
+ div
+ {
+ counter-increment: test 5;
+ display: run-in;
+ }
+ div:before
+ {
+ content: counter(test);
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if there is a number '5' below.</p>
+ <div></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-display/run-in/counter-reset-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/counter-reset-applies-to-011.xht
new file mode 100644
index 00000000000..75a54c93086
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/counter-reset-applies-to-011.xht
@@ -0,0 +1,27 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>CSS Test: Counter-reset applied to elements with 'display' set to 'run-in'</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-counter-reset" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#counters" />
+ <link rel="match" href="../../reference/pass_if_number_5.xht"/>
+ <meta name="flags" content="" />
+ <meta name="assert" content="The 'counter-reset' property applies to elements with a 'display' set to 'run-in'." />
+ <style type="text/css">
+ div
+ {
+ counter-reset: test 5;
+ display: run-in;
+ }
+ div:before
+ {
+ content: counter(test);
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if there is a number '5' below.</p>
+ <div></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/cursor-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/cursor-applies-to-011.xht
index d4ed8d2d0c6..d4ed8d2d0c6 100644
--- a/tests/wpt/web-platform-tests/css/css-block/cursor-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/cursor-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/direction-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/direction-applies-to-011.xht
index a5335efefe9..a5335efefe9 100644
--- a/tests/wpt/web-platform-tests/css/css-block/direction-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/direction-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/display-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/display-004.xht
index 244c08c392f..244c08c392f 100644
--- a/tests/wpt/web-platform-tests/css/css-block/display-004.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/display-004.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/empty-cells-applies-to-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/empty-cells-applies-to-004.xht
index eab1b055d0d..eab1b055d0d 100644
--- a/tests/wpt/web-platform-tests/css/css-block/empty-cells-applies-to-004.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/empty-cells-applies-to-004.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/first-line-pseudo-009.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/first-line-pseudo-009.xht
index 690aee9f85c..690aee9f85c 100644
--- a/tests/wpt/web-platform-tests/css/css-block/first-line-pseudo-009.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/first-line-pseudo-009.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/float-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/float-applies-to-011.xht
index 9cd9bd990af..9cd9bd990af 100644
--- a/tests/wpt/web-platform-tests/css/css-block/float-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/float-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/font-applies-to-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/font-applies-to-004.xht
index c0ac0626841..c0ac0626841 100644
--- a/tests/wpt/web-platform-tests/css/css-block/font-applies-to-004.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/font-applies-to-004.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/font-family-applies-to-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/font-family-applies-to-004.xht
index 3abb6579e5b..3abb6579e5b 100644
--- a/tests/wpt/web-platform-tests/css/css-block/font-family-applies-to-004.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/font-family-applies-to-004.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/font-size-applies-to-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/font-size-applies-to-004.xht
index 487a371307b..487a371307b 100644
--- a/tests/wpt/web-platform-tests/css/css-block/font-size-applies-to-004.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/font-size-applies-to-004.xht
diff --git a/tests/wpt/web-platform-tests/css/css-display/run-in/font-style-applies-to-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/font-style-applies-to-004.xht
new file mode 100644
index 00000000000..7e9024362ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/font-style-applies-to-004.xht
@@ -0,0 +1,24 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>CSS Test: Font-style and 'display: run-in' elements</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/fonts.html#propdef-font-style" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/fonts.html#font-styling" />
+ <link rel="help" href="http://www.w3.org/TR/css-fonts-3/#font-style-prop"/>
+ <link rel="match" href="../../reference/pass_if_filler_text_slanted.xht"/>
+ <meta name="flags" content="" />
+ <meta name="assert" content="The 'font-style' property applies to 'display: run-in' elements." />
+ <style type="text/css">
+ div
+ {
+ display: run-in;
+ font-style: italic;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if the "Filler Text" below is slanted to one side.</p>
+ <div>Filler Text</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-display/run-in/font-variant-applies-to-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/font-variant-applies-to-004.xht
new file mode 100644
index 00000000000..15a72afb0e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/font-variant-applies-to-004.xht
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>CSS Test: Font-variant and 'display: run-in' elements</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/fonts.html#propdef-font-variant" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/fonts.html#small-caps" />
+ <link rel="help" href="http://www.w3.org/TR/css-fonts-3/#font-variant-prop" />
+ <link rel="match" href="../../reference/pass_if_filler_text_match_smallcaps.xht"/>
+ <meta name="flags" content="" />
+ <meta name="assert" content="The 'font-variant' property applies to 'display: run-in' elements." />
+ <style type="text/css">
+ div
+ {
+ font-variant: small-caps;
+ }
+ #div1
+ {
+ display: run-in;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if the lines of "Filler Text" below match.</p>
+ <div>Filler Text</div>
+ <div id="div1">Filler Text</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-display/run-in/font-weight-applies-to-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/font-weight-applies-to-004.xht
new file mode 100644
index 00000000000..be108161d15
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/font-weight-applies-to-004.xht
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>CSS Test: Font-weight and 'display: run-in' elements</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/fonts.html#propdef-font-weight" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/fonts.html#font-boldness" />
+ <link rel="help" href="http://www.w3.org/TR/css-fonts-3/#font-weight-prop" />
+ <link rel="match" href="../../reference/pass_if_filler_text_match_bold.xht"/>
+ <meta name="flags" content="" />
+ <meta name="assert" content="Font weights apply to 'display: run-in' elements." />
+ <style type="text/css">
+ div
+ {
+ font-weight: bold;
+ }
+ #div1
+ {
+ display: run-in;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if the lines of "Filler Text" below match.</p>
+ <div>Filler Text</div>
+ <div id="div1">Filler Text</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-display/run-in/height-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/height-applies-to-011.xht
new file mode 100644
index 00000000000..084f4328536
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/height-applies-to-011.xht
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>CSS Test: Height applied to elements with 'display' set to 'run-in'</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#propdef-height" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#the-height-property" />
+ <link rel="match" href="../../reference/pass_if_square_96px_black.html"/>
+ <meta name="flags" content="" />
+ <meta name="assert" content="The 'height' property applies to elements with 'display' set to 'run-in'." />
+ <style type="text/css">
+ div
+ {
+ background: black;
+ display: run-in;
+ height: 1in;
+ width: 1in;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if there is a square below.</p>
+ <div></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/left-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/left-applies-to-011.xht
index de6eae360e5..de6eae360e5 100644
--- a/tests/wpt/web-platform-tests/css/css-block/left-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/left-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-display/run-in/letter-spacing-applies-to-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/letter-spacing-applies-to-004.xht
new file mode 100644
index 00000000000..051a2d8451c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/letter-spacing-applies-to-004.xht
@@ -0,0 +1,36 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>CSS Test: Letter-spacing application on a 'display: run-in' element</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/text.html#propdef-letter-spacing" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/text.html#spacing-props" />
+ <link rel="match" href="../../reference/black_box_ends_when_blue_box_ends_6_boxes_ahem.html"/>
+ <meta name="flags" content="ahem" />
+ <meta name="assert" content="The 'letter-spacing' property is applied to 'display: run-in' elements." />
+ <style type="text/css">
+ div
+ {
+ font: 16px/1em Ahem;
+ }
+ div div
+ {
+ display: run-in;
+ letter-spacing: 1em;
+ }
+ #div1
+ {
+ background: blue;
+ height: 1em;
+ width: 11em;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if there are six black boxes below and the last black box ends when the blue box ends.</p>
+ <div>
+ <div>XXXXXX</div>
+ </div>
+ <div id="div1"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/line-height-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/line-height-applies-to-011.xht
index 2a1cf98b41c..2a1cf98b41c 100644
--- a/tests/wpt/web-platform-tests/css/css-block/line-height-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/line-height-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-display/run-in/list-style-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/list-style-applies-to-011.xht
new file mode 100644
index 00000000000..f56f5e24a41
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/list-style-applies-to-011.xht
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>CSS Test: List-style applied to elements with 'display' set to 'run-in'</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-list-style" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#list-style" />
+ <link rel="match" href="../../reference/single_square_list_marker.xht"/>
+ <meta name="flags" content="" />
+ <meta name="assert" content="The 'list-style' property applies to elements with 'display' set to 'run-in'." />
+ <style type="text/css">
+ div
+ {
+ display: run-in;
+ list-style: square;
+ margin-left: 1in;
+ }
+ span
+ {
+ display: list-item;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if there is a single square below.</p>
+ <div>
+ <span></span>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/list-style-image-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/list-style-image-applies-to-011.xht
index dca032c6e9e..dca032c6e9e 100644
--- a/tests/wpt/web-platform-tests/css/css-block/list-style-image-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/list-style-image-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/list-style-position-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/list-style-position-applies-to-011.xht
index 95117c2c3b7..95117c2c3b7 100644
--- a/tests/wpt/web-platform-tests/css/css-block/list-style-position-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/list-style-position-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-display/run-in/list-style-type-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/list-style-type-applies-to-011.xht
new file mode 100644
index 00000000000..110a0acf304
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/list-style-type-applies-to-011.xht
@@ -0,0 +1,30 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>CSS Test: List-style-type applied to elements with 'display' set to 'run-in'</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-list-style-type" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#list-style" />
+ <link rel="match" href="../../reference/single_square_list_marker.xht"/>
+ <meta name="flags" content="" />
+ <meta name="assert" content="The 'list-style-type' property applies to elements with 'display' set to 'run-in'." />
+ <style type="text/css">
+ div
+ {
+ display: run-in;
+ list-style-type: square;
+ margin-left: 1in;
+ }
+ span
+ {
+ display: list-item;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if there is a single square below.</p>
+ <div>
+ <span></span>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/margin-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/margin-applies-to-011.xht
index 6646d1cda45..6646d1cda45 100644
--- a/tests/wpt/web-platform-tests/css/css-block/margin-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/margin-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/margin-bottom-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/margin-bottom-applies-to-011.xht
index 20f4c6927d9..20f4c6927d9 100644
--- a/tests/wpt/web-platform-tests/css/css-block/margin-bottom-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/margin-bottom-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/margin-left-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/margin-left-applies-to-011.xht
index 37ffdd33755..37ffdd33755 100644
--- a/tests/wpt/web-platform-tests/css/css-block/margin-left-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/margin-left-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/margin-right-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/margin-right-applies-to-011.xht
index 4bee27c0d23..4bee27c0d23 100644
--- a/tests/wpt/web-platform-tests/css/css-block/margin-right-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/margin-right-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/margin-top-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/margin-top-applies-to-011.xht
index 762e34be0a2..762e34be0a2 100644
--- a/tests/wpt/web-platform-tests/css/css-block/margin-top-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/margin-top-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-display/run-in/max-height-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/max-height-applies-to-011.xht
new file mode 100644
index 00000000000..0145ecf186f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/max-height-applies-to-011.xht
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>CSS Test: Max-height applied to elements with 'display' set to 'run-in'</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#propdef-max-height" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#min-max-heights" />
+ <link rel="match" href="../../reference/pass_if_square_96px_black.html"/>
+ <meta name="flags" content="" />
+ <meta name="assert" content="The 'max-height' property applies to elements with 'display' set to 'run-in'." />
+ <style type="text/css">
+ div
+ {
+ background: black;
+ display: run-in;
+ height: 3in;
+ max-height: 1in;
+ width: 1in;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if there is a square below.</p>
+ <div></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-display/run-in/max-width-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/max-width-applies-to-011.xht
new file mode 100644
index 00000000000..089fea0d68f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/max-width-applies-to-011.xht
@@ -0,0 +1,26 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>CSS Test: Max-width applied to elements with 'display' set to 'run-in'</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#propdef-max-width" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#min-max-widths" />
+ <link rel="match" href="../../reference/pass_if_square_96px_black.html"/>
+ <meta name="flags" content="" />
+ <meta name="assert" content="The 'max-width' property applies to elements with 'display' set to 'run-in'." />
+ <style type="text/css">
+ div
+ {
+ background: black;
+ display: run-in;
+ height: 1in;
+ max-width: 1in;
+ width: 3in;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if there is a square below.</p>
+ <div></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-display/run-in/min-height-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/min-height-applies-to-011.xht
new file mode 100644
index 00000000000..8d0f0f2134b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/min-height-applies-to-011.xht
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>CSS Test: Min-height applied to elements with 'display' set to 'run-in'</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#propdef-min-height" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#min-max-heights" />
+ <link rel="match" href="../../reference/pass_if_square_96px_black.html"/>
+ <meta name="flags" content="" />
+ <meta name="assert" content="The 'min-height' property applies to elements with 'display' set to 'run-in'." />
+ <style type="text/css">
+ div
+ {
+ background: black;
+ display: run-in;
+ min-height: 1in;
+ width: 1in;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if there is a square below.</p>
+ <div></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-display/run-in/min-width-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/min-width-applies-to-011.xht
new file mode 100644
index 00000000000..2443442d47d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/min-width-applies-to-011.xht
@@ -0,0 +1,31 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>CSS Test: Min-width applied to elements with 'display' set to 'run-in'</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#propdef-min-width" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#min-max-widths" />
+ <link rel="match" href="../../reference/pass_if_square_96px_black.html"/>
+ <meta name="flags" content="" />
+ <meta name="assert" content="The 'min-width' property applies to elements with 'display' set to 'run-in'." />
+ <style type="text/css">
+ #div1
+ {
+ width: 0.5in;
+ }
+ div div
+ {
+ background: black;
+ display: run-in;
+ height: 1in;
+ min-width: 1in;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if there is a square below.</p>
+ <div id="div1">
+ <div></div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/outline-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/outline-applies-to-011.xht
index c72f7105326..c72f7105326 100644
--- a/tests/wpt/web-platform-tests/css/css-block/outline-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/outline-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/outline-color-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/outline-color-applies-to-011.xht
index 6861863c12e..6861863c12e 100644
--- a/tests/wpt/web-platform-tests/css/css-block/outline-color-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/outline-color-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/outline-style-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/outline-style-applies-to-011.xht
index a3d36b28532..a3d36b28532 100644
--- a/tests/wpt/web-platform-tests/css/css-block/outline-style-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/outline-style-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/outline-width-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/outline-width-applies-to-011.xht
index 6510ed02611..6510ed02611 100644
--- a/tests/wpt/web-platform-tests/css/css-block/outline-width-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/outline-width-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/overflow-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/overflow-applies-to-011.xht
index 28d7d50effa..28d7d50effa 100644
--- a/tests/wpt/web-platform-tests/css/css-block/overflow-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/overflow-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/padding-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/padding-applies-to-011.xht
index 8c2a9d8d086..8c2a9d8d086 100644
--- a/tests/wpt/web-platform-tests/css/css-block/padding-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/padding-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/padding-bottom-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/padding-bottom-applies-to-011.xht
index 65a377c9937..65a377c9937 100644
--- a/tests/wpt/web-platform-tests/css/css-block/padding-bottom-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/padding-bottom-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/padding-left-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/padding-left-applies-to-011.xht
index 68c25d6fa8b..68c25d6fa8b 100644
--- a/tests/wpt/web-platform-tests/css/css-block/padding-left-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/padding-left-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/padding-right-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/padding-right-applies-to-011.xht
index a09e69329d4..a09e69329d4 100644
--- a/tests/wpt/web-platform-tests/css/css-block/padding-right-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/padding-right-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/padding-top-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/padding-top-applies-to-011.xht
index 9f2bb3628c2..9f2bb3628c2 100644
--- a/tests/wpt/web-platform-tests/css/css-block/padding-top-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/padding-top-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/position-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/position-applies-to-011.xht
index b155623cd1a..b155623cd1a 100644
--- a/tests/wpt/web-platform-tests/css/css-block/position-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/position-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-display/run-in/quotes-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/quotes-applies-to-011.xht
new file mode 100644
index 00000000000..42f426993b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/quotes-applies-to-011.xht
@@ -0,0 +1,27 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>CSS Test: Quotes applied to elements with 'display' set to 'run-in'</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#propdef-quotes" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/generate.html#quotes-specify" />
+ <link rel="match" href="../../reference/pass_if_pass_below.html" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="The 'quotes' property applies to elements with a 'display' set to 'run-in'." />
+ <style type="text/css">
+ div
+ {
+ display: run-in;
+ quotes: "P" "S" "A" "S";
+ }
+ div:before
+ {
+ content: open-quote open-quote close-quote close-quote;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if there is the word "PASS" below.</p>
+ <div></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/right-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/right-applies-to-011.xht
index 91159fdc38c..91159fdc38c 100644
--- a/tests/wpt/web-platform-tests/css/css-block/right-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/right-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-001.xht
index 2288df6f12f..2288df6f12f 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-002.xht
index e3e24197a1d..e3e24197a1d 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-003.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-003.xht
index 075523a0868..075523a0868 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-003.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-004.xht
index ccb5994f127..ccb5994f127 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-004.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-004.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-005.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-005.xht
index 87968a36445..87968a36445 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-005.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-005.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-006.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-006.xht
index 8ba2037f434..8ba2037f434 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-006.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-006.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-007.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-007.xht
index 1b8207113e6..1b8207113e6 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-007.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-007.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-008.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-008.xht
index acce1a39cb6..acce1a39cb6 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-008.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-008.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-009.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-009.xht
index bf5223e8caf..bf5223e8caf 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-009.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-009.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-010.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-010.xht
index 0d36201d6ab..0d36201d6ab 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-010.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-010.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-011.xht
index 59bca8052de..59bca8052de 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-012.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-012.xht
index be1bc4445af..be1bc4445af 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-012.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-012.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-013.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-013.xht
index 0ca6e75486d..0ca6e75486d 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-013.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-013.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-abspos-between-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-abspos-between-001.xht
index d48773f9910..d48773f9910 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-abspos-between-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-abspos-between-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-abspos-between-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-abspos-between-002.xht
index 8303df2bf6f..8303df2bf6f 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-abspos-between-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-abspos-between-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-abspos-between-003.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-abspos-between-003.xht
index 5053a7a5ea0..5053a7a5ea0 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-abspos-between-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-abspos-between-003.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-001.xht
index 25e4126b1cb..25e4126b1cb 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-002.xht
index fb4ef0c6e0c..fb4ef0c6e0c 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-003.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-003.xht
index 0b3fe003bf9..0b3fe003bf9 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-003.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-004.xht
index faad2521e23..faad2521e23 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-004.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-004.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-005.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-005.xht
index 5daf9a48044..5daf9a48044 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-005.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-005.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-006.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-006.xht
index c507d793339..c507d793339 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-006.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-006.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-007-ref.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-007-ref.xht
index ba04ce34354..ba04ce34354 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-007-ref.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-007-ref.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-007.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-007.xht
index d9bf7db0682..d9bf7db0682 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-007.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-007.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-008.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-008.xht
index b43decd0b79..b43decd0b79 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-008.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-008.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-009.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-009.xht
index 94ebed7c67b..94ebed7c67b 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-009.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-009.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-010.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-010.xht
index 2dc30223e69..2dc30223e69 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-010.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-010.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-011.xht
index afc85413af3..afc85413af3 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-012.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-012.xht
index 84bc320670e..84bc320670e 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-012.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-012.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-013.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-013.xht
index af810ac289d..af810ac289d 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-013.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-013.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-014.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-014.xht
index 1cf0951f615..1cf0951f615 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-014.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-014.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-015.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-015.xht
index 8eee5e98df1..8eee5e98df1 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-015.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-015.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-016.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-016.xht
index 4e8d71ae890..4e8d71ae890 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-016.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-016.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-017.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-017.xht
index 065fe751f38..065fe751f38 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-017.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-017.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-018.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-018.xht
index d776c2df87c..d776c2df87c 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-018.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-018.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-ref.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-ref.xht
index 597c7237a74..597c7237a74 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-basic-ref.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-basic-ref.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-block-between-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-block-between-001.xht
index 203d9af6ab3..203d9af6ab3 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-block-between-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-block-between-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-block-between-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-block-between-002.xht
index eeace162a0a..eeace162a0a 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-block-between-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-block-between-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-block-between-003.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-block-between-003.xht
index ca901199c68..ca901199c68 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-block-between-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-block-between-003.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-block-ref.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-block-ref.xht
index 48e01902d9b..48e01902d9b 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-block-ref.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-block-ref.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-breaking-001-ref.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-breaking-001-ref.xht
index 71701bf4a45..71701bf4a45 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-breaking-001-ref.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-breaking-001-ref.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-breaking-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-breaking-001.xht
index 51c219e1431..51c219e1431 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-breaking-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-breaking-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-breaking-002-ref.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-breaking-002-ref.xht
index 1dc6994452c..1dc6994452c 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-breaking-002-ref.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-breaking-002-ref.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-breaking-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-breaking-002.xht
index fadf930d93b..fadf930d93b 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-breaking-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-breaking-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-clear-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-clear-001.xht
index c7034384ff4..c7034384ff4 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-clear-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-clear-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-clear-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-clear-002.xht
index f392b4f47d9..f392b4f47d9 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-clear-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-clear-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-abspos-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-abspos-001.xht
index b9bd1a231bd..b9bd1a231bd 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-abspos-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-abspos-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-block-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-block-001.xht
index 109fe47278c..109fe47278c 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-block-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-block-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-block-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-block-002.xht
index d0fcecd4080..d0fcecd4080 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-block-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-block-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-block-003.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-block-003.xht
index 83d04ce737a..83d04ce737a 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-block-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-block-003.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-block-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-block-004.xht
index da9a9e42739..da9a9e42739 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-block-004.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-block-004.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-block-005.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-block-005.xht
index c55842087af..c55842087af 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-block-005.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-block-005.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-block-inside-inline-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-block-inside-inline-001.xht
index be32cd47cf8..be32cd47cf8 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-block-inside-inline-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-block-inside-inline-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-block-inside-inline-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-block-inside-inline-002.xht
index 4c47b020f49..4c47b020f49 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-block-inside-inline-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-block-inside-inline-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-block-inside-inline-003.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-block-inside-inline-003.xht
index a3b56dcb478..a3b56dcb478 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-block-inside-inline-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-block-inside-inline-003.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-float-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-float-001.xht
index de3dfd8495e..de3dfd8495e 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-float-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-float-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-001.xht
index 3b9f05a7f11..3b9f05a7f11 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-002.xht
index 4178b526af9..4178b526af9 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-003.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-003.xht
index f39619f098c..f39619f098c 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-003.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-004.xht
index d7f52d07051..d7f52d07051 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-004.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-004.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-005.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-005.xht
index 2bc8cebeb95..2bc8cebeb95 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-005.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-005.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-006.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-006.xht
index d24dd15f3ea..d24dd15f3ea 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-006.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-006.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-007.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-007.xht
index 8dd899622ae..8dd899622ae 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-007.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-007.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-block-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-block-001.xht
index bde6b1891cd..bde6b1891cd 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-block-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-block-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-table-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-table-001.xht
index d4e64f1b841..d4e64f1b841 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-inline-table-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-inline-table-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-relpos-block-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-relpos-block-001.xht
index e220a1374e9..e220a1374e9 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-relpos-block-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-relpos-block-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-relpos-block-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-relpos-block-002.xht
index 64fa6f6e1ab..64fa6f6e1ab 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-relpos-block-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-relpos-block-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-relpos-block-003.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-relpos-block-003.xht
index c5756fce484..c5756fce484 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-relpos-block-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-relpos-block-003.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-run-in-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-run-in-001.xht
index 2f1a3a7b5e5..2f1a3a7b5e5 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-run-in-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-run-in-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-run-in-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-run-in-002.xht
index e3f978be084..e3f978be084 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-run-in-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-run-in-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-run-in-003.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-run-in-003.xht
index 5a812b382b2..5a812b382b2 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-run-in-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-run-in-003.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-001.xht
index 0182c10de18..0182c10de18 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-002.xht
index 3fd6adda3a6..3fd6adda3a6 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-003.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-003.xht
index ab76e87e2d1..ab76e87e2d1 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-003.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-caption-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-caption-001.xht
index ce29717d875..ce29717d875 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-caption-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-caption-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-cell-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-cell-001.xht
index 4a003d74f67..4a003d74f67 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-cell-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-cell-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-column-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-column-001.xht
index 629f1783d1a..629f1783d1a 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-column-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-column-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-column-group-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-column-group-001.xht
index a62015136e8..a62015136e8 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-column-group-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-column-group-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-inside-inline-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-inside-inline-001.xht
index d9f5c2a07a9..d9f5c2a07a9 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-inside-inline-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-inside-inline-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-inside-inline-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-inside-inline-002.xht
index edd543d45b0..edd543d45b0 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-inside-inline-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-inside-inline-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-inside-inline-003.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-inside-inline-003.xht
index 5df9c526c3b..5df9c526c3b 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-inside-inline-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-inside-inline-003.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-row-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-row-001.xht
index 7051b3ec154..7051b3ec154 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-row-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-row-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-row-group-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-row-group-001.xht
index 681b45f9482..681b45f9482 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-contains-table-row-group-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-contains-table-row-group-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-display-none-between-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-display-none-between-001.xht
index 0c2cf4fa0b3..0c2cf4fa0b3 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-display-none-between-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-display-none-between-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-display-none-between-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-display-none-between-002.xht
index c9dddee3cdc..c9dddee3cdc 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-display-none-between-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-display-none-between-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-display-none-between-003.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-display-none-between-003.xht
index ac28260492b..ac28260492b 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-display-none-between-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-display-none-between-003.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-fixedpos-between-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-fixedpos-between-001.xht
index d12e13d58e0..d12e13d58e0 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-fixedpos-between-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-fixedpos-between-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-fixedpos-between-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-fixedpos-between-002.xht
index e97fe47cad5..e97fe47cad5 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-fixedpos-between-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-fixedpos-between-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-fixedpos-between-003.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-fixedpos-between-003.xht
index 9af28a390c7..9af28a390c7 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-fixedpos-between-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-fixedpos-between-003.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-float-between-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-float-between-001.xht
index b5d006cadd8..b5d006cadd8 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-float-between-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-float-between-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-float-between-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-float-between-002.xht
index a5ad3c7de43..a5ad3c7de43 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-float-between-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-float-between-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-float-between-003.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-float-between-003.xht
index 8d4b9e52f2f..8d4b9e52f2f 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-float-between-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-float-between-003.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-inherit-001-ref.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inherit-001-ref.xht
index 64f0a45e7d9..64f0a45e7d9 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-inherit-001-ref.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inherit-001-ref.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-inherit-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inherit-001.xht
index da72bc2ef8d..da72bc2ef8d 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-inherit-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inherit-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-inheritance-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inheritance-001.xht
index 0e1f0fe6a15..0e1f0fe6a15 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-inheritance-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inheritance-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-inline-between-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-between-001.xht
index 61c726261b9..61c726261b9 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-inline-between-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-between-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-inline-between-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-between-002.xht
index bba6f3b2463..bba6f3b2463 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-inline-between-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-between-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-inline-between-003.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-between-003.xht
index 358b4231c99..358b4231c99 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-inline-between-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-between-003.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-inline-block-between-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-block-between-001.xht
index 9113603240b..9113603240b 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-inline-block-between-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-block-between-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-inline-block-between-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-block-between-002.xht
index 1ceb4bed25a..1ceb4bed25a 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-inline-block-between-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-block-between-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-inline-block-between-003.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-block-between-003.xht
index 351f27756ea..351f27756ea 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-inline-block-between-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-block-between-003.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-inline-table-between-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-table-between-001.xht
index 9e30c852f5f..9e30c852f5f 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-inline-table-between-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-table-between-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-inline-table-between-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-table-between-002.xht
index 49164c05ecf..49164c05ecf 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-inline-table-between-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-table-between-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-inline-table-between-003.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-table-between-003.xht
index 9b73d0cadc3..9b73d0cadc3 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-inline-table-between-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-inline-table-between-003.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-linebox-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-linebox-001.xht
index 128cd3e386e..128cd3e386e 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-linebox-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-linebox-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-linebox-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-linebox-002.xht
index db741a1e8a3..db741a1e8a3 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-linebox-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-linebox-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-listitem-between-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-listitem-between-001.xht
index b46e8b95b72..b46e8b95b72 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-listitem-between-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-listitem-between-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-listitem-between-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-listitem-between-002.xht
index f2c0d32c268..f2c0d32c268 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-listitem-between-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-listitem-between-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-listitem-between-003.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-listitem-between-003.xht
index 06fda02c743..06fda02c743 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-listitem-between-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-listitem-between-003.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-pre-ref.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-pre-ref.xht
index 541d182a5e4..541d182a5e4 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-pre-ref.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-pre-ref.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-relpos-between-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-relpos-between-001.xht
index e8e677fad05..e8e677fad05 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-relpos-between-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-relpos-between-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-relpos-between-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-relpos-between-002.xht
index bb7c91a0c61..bb7c91a0c61 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-relpos-between-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-relpos-between-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-relpos-between-003.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-relpos-between-003.xht
index cea7d4f4b0e..cea7d4f4b0e 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-relpos-between-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-relpos-between-003.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-replaced-001-ref.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-replaced-001-ref.xht
index e6c53abfacd..e6c53abfacd 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-replaced-001-ref.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-replaced-001-ref.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-replaced-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-replaced-001.xht
index 417fe01458b..417fe01458b 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-replaced-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-replaced-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-restyle-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-restyle-001.xht
index 05bd61a0b59..05bd61a0b59 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-restyle-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-restyle-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-restyle-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-restyle-002.xht
index 40d23e4fb0a..40d23e4fb0a 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-restyle-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-restyle-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-restyle-003.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-restyle-003.xht
index 226081278db..226081278db 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-restyle-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-restyle-003.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-run-in-between-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-run-in-between-001.xht
index 7ba600fc98b..7ba600fc98b 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-run-in-between-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-run-in-between-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-run-in-between-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-run-in-between-002.xht
index 220c45ed246..220c45ed246 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-run-in-between-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-run-in-between-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-run-in-between-003.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-run-in-between-003.xht
index 555774420c1..555774420c1 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-run-in-between-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-run-in-between-003.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-run-in-between-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-run-in-between-004.xht
index 4017e8feae1..4017e8feae1 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-run-in-between-004.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-run-in-between-004.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-run-in-between-005.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-run-in-between-005.xht
index 9839d9bd59d..9839d9bd59d 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-run-in-between-005.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-run-in-between-005.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-run-in-between-006.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-run-in-between-006.xht
index ae2bceef2df..ae2bceef2df 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-run-in-between-006.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-run-in-between-006.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-run-in-between-007.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-run-in-between-007.xht
index 910831a7422..910831a7422 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-run-in-between-007.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-run-in-between-007.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-run-in-between-008.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-run-in-between-008.xht
index 00e24408e80..00e24408e80 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-run-in-between-008.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-run-in-between-008.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-table-between-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-between-001.xht
index 2af7f4a73b9..2af7f4a73b9 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-table-between-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-between-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-table-between-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-between-002.xht
index 2ca80275469..2ca80275469 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-table-between-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-between-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-table-between-003.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-between-003.xht
index aa4d9f4497f..aa4d9f4497f 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-table-between-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-between-003.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-table-cell-between-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-cell-between-001.xht
index b302a2586b7..b302a2586b7 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-table-cell-between-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-cell-between-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-table-cell-between-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-cell-between-002.xht
index 04f5e80c534..04f5e80c534 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-table-cell-between-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-cell-between-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-table-cell-between-003.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-cell-between-003.xht
index 49ab6455543..49ab6455543 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-table-cell-between-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-cell-between-003.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-table-row-between-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-row-between-001.xht
index 5fff0a34d2e..5fff0a34d2e 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-table-row-between-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-row-between-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-table-row-between-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-row-between-002.xht
index a5e069daac8..a5e069daac8 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-table-row-between-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-row-between-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-table-row-between-003.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-row-between-003.xht
index 755b46351b7..755b46351b7 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-table-row-between-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-table-row-between-003.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-text-between-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-text-between-001.xht
index 22cf546bc5d..22cf546bc5d 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-text-between-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-text-between-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-text-between-002.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-text-between-002.xht
index 545dee956e0..545dee956e0 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-text-between-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-text-between-002.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-text-between-003.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-text-between-003.xht
index 66a4451d32b..66a4451d32b 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-text-between-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-text-between-003.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-text-between-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-text-between-004.xht
index 9411b648191..9411b648191 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-text-between-004.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-text-between-004.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-text-between-005.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-text-between-005.xht
index e981b9e2d35..e981b9e2d35 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-text-between-005.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-text-between-005.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/run-in-text-ref.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-text-ref.xht
index 88f4930b4a6..88f4930b4a6 100644
--- a/tests/wpt/web-platform-tests/css/css-block/run-in-text-ref.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/run-in-text-ref.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/support/black15x15.png b/tests/wpt/web-platform-tests/css/css-display/run-in/support/black15x15.png
index b1bbef2cd55..b1bbef2cd55 100644
--- a/tests/wpt/web-platform-tests/css/css-block/support/black15x15.png
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/support/black15x15.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/css/css-block/support/blue15x15.png b/tests/wpt/web-platform-tests/css/css-display/run-in/support/blue15x15.png
index 89de32fdb8a..89de32fdb8a 100644
--- a/tests/wpt/web-platform-tests/css/css-block/support/blue15x15.png
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/support/blue15x15.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/css/css-block/support/blue96x96.png b/tests/wpt/web-platform-tests/css/css-display/run-in/support/blue96x96.png
index 820f8cace21..820f8cace21 100644
--- a/tests/wpt/web-platform-tests/css/css-block/support/blue96x96.png
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/support/blue96x96.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/css/css-block/support/green15x15.png b/tests/wpt/web-platform-tests/css/css-display/run-in/support/green15x15.png
index 51741584a07..51741584a07 100644
--- a/tests/wpt/web-platform-tests/css/css-block/support/green15x15.png
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/support/green15x15.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/css/css-block/support/swatch-blue.png b/tests/wpt/web-platform-tests/css/css-display/run-in/support/swatch-blue.png
index bf2759634d4..bf2759634d4 100644
--- a/tests/wpt/web-platform-tests/css/css-block/support/swatch-blue.png
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/support/swatch-blue.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/css/css-block/table-anonymous-block-001.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/table-anonymous-block-001.xht
index d33fad65899..d33fad65899 100644
--- a/tests/wpt/web-platform-tests/css/css-block/table-anonymous-block-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/table-anonymous-block-001.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/table-layout-applies-to-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/table-layout-applies-to-004.xht
index 7a1e33dd7b7..7a1e33dd7b7 100644
--- a/tests/wpt/web-platform-tests/css/css-block/table-layout-applies-to-004.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/table-layout-applies-to-004.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/text-align-applies-to-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/text-align-applies-to-004.xht
index 0f41d405322..0f41d405322 100644
--- a/tests/wpt/web-platform-tests/css/css-block/text-align-applies-to-004.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/text-align-applies-to-004.xht
diff --git a/tests/wpt/web-platform-tests/css/css-display/run-in/text-decoration-applies-to-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/text-decoration-applies-to-004.xht
new file mode 100644
index 00000000000..94aeff8d910
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/text-decoration-applies-to-004.xht
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>CSS Test: Text-decoration application on a 'run-in' element</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/text.html#propdef-text-decoration" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/text.html#lining-striking-props" />
+ <link rel="match" href="../../reference/pass_if_filler_text_underlined.html"/>
+ <meta name="flags" content="" />
+ <meta name="assert" content="The 'text-decoration' property applies to a 'run-in' element." />
+ <style type="text/css">
+ div
+ {
+ display: run-in;
+ text-decoration: underline;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if the "Filler Text" below has a line under it.</p>
+ <div>Filler Text</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/text-indent-applies-to-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/text-indent-applies-to-004.xht
index 778d7ca27db..778d7ca27db 100644
--- a/tests/wpt/web-platform-tests/css/css-block/text-indent-applies-to-004.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/text-indent-applies-to-004.xht
diff --git a/tests/wpt/web-platform-tests/css/css-display/run-in/text-transform-applies-to-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/text-transform-applies-to-004.xht
new file mode 100644
index 00000000000..bfbc7b12863
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/text-transform-applies-to-004.xht
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>CSS Test: Text-transform application to 'display: run-in' element</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/text.html#propdef-text-transform" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/text.html#caps-prop" />
+ <link rel="match" href="../../reference/pass_if_letter_uppercase.html" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="The 'text-transform' property is applied to 'display: run-in' elements." />
+ <style type="text/css">
+ div
+ {
+ display: run-in;
+ text-transform: capitalize;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if the letter "F" in the words "Filler Text" below is in upper-case.</p>
+ <div>filler text</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/top-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/top-applies-to-011.xht
index 31f19b92ef1..31f19b92ef1 100644
--- a/tests/wpt/web-platform-tests/css/css-block/top-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/top-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/unicode-bidi-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/unicode-bidi-applies-to-011.xht
index 194e295bab4..194e295bab4 100644
--- a/tests/wpt/web-platform-tests/css/css-block/unicode-bidi-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/unicode-bidi-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/vertical-align-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/vertical-align-applies-to-011.xht
index 6b6ddd4417f..6b6ddd4417f 100644
--- a/tests/wpt/web-platform-tests/css/css-block/vertical-align-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/vertical-align-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/visibility-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/visibility-applies-to-011.xht
index ae4f8213e97..ae4f8213e97 100644
--- a/tests/wpt/web-platform-tests/css/css-block/visibility-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/visibility-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/white-space-applies-to-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/white-space-applies-to-004.xht
index 855a1706991..855a1706991 100644
--- a/tests/wpt/web-platform-tests/css/css-block/white-space-applies-to-004.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/white-space-applies-to-004.xht
diff --git a/tests/wpt/web-platform-tests/css/css-display/run-in/width-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/width-applies-to-011.xht
new file mode 100644
index 00000000000..9e5da720f83
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/width-applies-to-011.xht
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>CSS Test: Width applied to elements with 'display' set to 'run-in'</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#propdef-width" />
+ <link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#the-width-property" />
+ <link rel="match" href="../../reference/pass_if_square_96px_black.html"/>
+ <meta name="flags" content="" />
+ <meta name="assert" content="The 'width' property applies to elements with 'display' set to 'run-in'." />
+ <style type="text/css">
+ div
+ {
+ background: black;
+ display: run-in;
+ height: 1in;
+ width: 1in;
+ }
+ </style>
+ </head>
+ <body>
+ <p>Test passes if there is a square below.</p>
+ <div></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-block/word-spacing-applies-to-004.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/word-spacing-applies-to-004.xht
index 8386aa94100..8386aa94100 100644
--- a/tests/wpt/web-platform-tests/css/css-block/word-spacing-applies-to-004.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/word-spacing-applies-to-004.xht
diff --git a/tests/wpt/web-platform-tests/css/css-block/z-index-applies-to-011.xht b/tests/wpt/web-platform-tests/css/css-display/run-in/z-index-applies-to-011.xht
index 6f493ba85cb..6f493ba85cb 100644
--- a/tests/wpt/web-platform-tests/css/css-block/z-index-applies-to-011.xht
+++ b/tests/wpt/web-platform-tests/css/css-display/run-in/z-index-applies-to-011.xht
diff --git a/tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-001.html b/tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-001.html
new file mode 100644
index 00000000000..e1c6ec6d8ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-001.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Flexbox Test: Flex item - contiguous text runs - node removal</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-flexbox/#flex-items">
+<link rel="match" href="anonymous-flex-item-ref.html">
+<p>There should be a space between "two" and "words" below.</p>
+<div style="display:flex">two <span id="spanRemove"></span>words</div>
+<script>
+ document.body.offsetTop;
+ spanRemove.remove();
+</script>
diff --git a/tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-002.html b/tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-002.html
new file mode 100644
index 00000000000..4b571fe5fc3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-002.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Flexbox Test: Flex item - contiguous text runs - display:none</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-flexbox/#flex-items">
+<link rel="match" href="anonymous-flex-item-ref.html">
+<p>There should be a space between "two" and "words" below.</p>
+<div style="display:flex">two <span style="display:none"></span>words</div>
diff --git a/tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-003.html b/tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-003.html
new file mode 100644
index 00000000000..1449e1df60e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-003.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Flexbox Test: Flex item - contiguous text runs - display:none dynamic</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-flexbox/#flex-items">
+<link rel="match" href="anonymous-flex-item-ref.html">
+<p>There should be a space between "two" and "words" below.</p>
+<div style="display:flex">two <span id="noneSpan"></span>words</div>
+<script>
+ document.body.offsetTop;
+ noneSpan.style.display = "none";
+</script>
diff --git a/tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-004.html b/tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-004.html
new file mode 100644
index 00000000000..471fce3680e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-004.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Flexbox Test: Flex item - contiguous text runs - position:absolute</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-flexbox/#flex-items">
+<link rel="match" href="anonymous-flex-item-ref.html">
+<p>There should be a space between "two" and "words" below.</p>
+<div style="display:flex">two <span style="position:absolute"></span>words</div>
diff --git a/tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-005.html b/tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-005.html
new file mode 100644
index 00000000000..c4a75e5000b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-005.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Flexbox Test: Flex item - contiguous text runs - position:absolute dynamic</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-flexbox/#flex-items">
+<link rel="match" href="anonymous-flex-item-ref.html">
+<p>There should be a space between "two" and "words" below.</p>
+<div style="display:flex">two <span id="absSpan"></span>words</div>
+<script>
+ document.body.offsetTop;
+ absSpan.style.position = "absolute";
+</script>
diff --git a/tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-006.html b/tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-006.html
new file mode 100644
index 00000000000..8544618efa4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-006.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Flexbox Test: Flex item - contiguous text runs - position:absolute and node removal</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-flexbox/#flex-items">
+<link rel="match" href="anonymous-flex-item-ref.html">
+<style>.abs { position:absolute }</style>
+<p>There should be a space between "two" and "words" below.</p>
+<div style="display:flex">two <span class="abs"></span><span id="spanRemove"></span><span class="abs"></span>words</div>
+<script>
+ document.body.offsetTop;
+ spanRemove.remove();
+</script>
diff --git a/tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-ref.html b/tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-ref.html
new file mode 100644
index 00000000000..4a2285400c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-flexbox/anonymous-flex-item-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Reftest Reference</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<p>There should be a space between "two" and "words" below.</p>
+two words
diff --git a/tests/wpt/web-platform-tests/css/css-flexbox/percentage-heights-004-ref.html b/tests/wpt/web-platform-tests/css/css-flexbox/percentage-heights-004-ref.html
new file mode 100644
index 00000000000..ffb44a82b53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-flexbox/percentage-heights-004-ref.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<title>CSS Flexbox: Percentages in stretched container</title>
+<link rel="author" title="Google" href="https://www.google.com/" />
+
+<style>
+#outer {
+ height: 10em;
+ display: inline-block;
+ background: green;
+ vertical-align: top;
+}
+
+#middle {
+ overflow-x: scroll;
+ height: 100%;
+}
+
+#inner {
+ width: 200px;
+}
+
+#outer2 {
+ height: 10em;
+ display: inline-block;
+}
+
+#middle2 {
+ overflow-x: scroll;
+ height: 10em;
+}
+
+#inner2 {
+ width: 200px;
+ height: 100%;
+ background: green;
+}
+</style>
+
+<p>You should not see red nor a vertical scrollbar</p>
+
+<div id="outer">
+ <div id="middle">
+ <div id="inner">
+ hello
+ </div>
+ </div>
+</div>
+
+<div id="outer2">
+ <div id="middle2">
+ <div id="inner2">
+ hello
+ </div>
+ </div>
+</div>
+
diff --git a/tests/wpt/web-platform-tests/css/css-flexbox/percentage-heights-004.html b/tests/wpt/web-platform-tests/css/css-flexbox/percentage-heights-004.html
new file mode 100644
index 00000000000..4f162487a71
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-flexbox/percentage-heights-004.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+<title>CSS Flexbox: Percentages in stretched container</title>
+<link rel="author" title="Google" href="https://www.google.com/" />
+<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#definite-sizes" />
+<link rel="match" href="percentage-heights-004-ref.html">
+
+<style>
+#outer {
+ height: 10em;
+ display: inline-flex;
+ background: red;
+}
+
+#middle {
+ overflow-x: scroll;
+}
+
+#inner {
+ height: 100%;
+ width: 200px;
+ background: green;
+}
+
+#outer2 {
+ height: 10em;
+ display: inline-flex;
+ flex-direction: column;
+ background: red;
+}
+
+#middle2 {
+ overflow-x: scroll;
+ flex: 1.0;
+}
+
+#inner2 {
+ height: 100%;
+ width: 200px;
+ background: green;
+}
+</style>
+
+<p>You should not see red nor a vertical scrollbar</p>
+
+<div id="outer">
+ <div id="middle">
+ <div id="inner">
+ hello
+ </div>
+ </div>
+</div>
+
+<div id="outer2">
+ <div id="middle2">
+ <div id="inner2">
+ hello
+ </div>
+ </div>
+</div>
+
diff --git a/tests/wpt/web-platform-tests/css/css-flexbox/table-as-item-narrow-content.html b/tests/wpt/web-platform-tests/css/css-flexbox/table-as-item-narrow-content.html
new file mode 100644
index 00000000000..31cf1125181
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-flexbox/table-as-item-narrow-content.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title>CSS Flexbox Test: Flex item as table with narrow content</title>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#layout-algorithm" title="9. Flex Layout Algorithm">
+<meta name="assert" content="A flex item as a table uses the sizing algorithm of the flexbox">
+<link rel="match" href="../reference/ref-filled-green-100px-square-only.html">
+<p>Test passes if there is a filled green square.</p>
+<div style="display:flex; width:200px;">
+ <div style="display:table; flex:1 0; background:green;">
+ <div style="width:10px; height:100px;"></div>
+ </div>
+ <div style="flex:1 0;"></div>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-flexbox/table-as-item-wide-content.html b/tests/wpt/web-platform-tests/css/css-flexbox/table-as-item-wide-content.html
new file mode 100644
index 00000000000..475adf548fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-flexbox/table-as-item-wide-content.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<title>CSS Flexbox Test: Flex item as table with wide content</title>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#layout-algorithm" title="9. Flex Layout Algorithm">
+<meta name="assert" content="A flex item as a table uses the sizing algorithm of the flexbox">
+<link rel="match" href="../reference/ref-filled-green-100px-square-only.html">
+<p>Test passes if there is a filled green square.</p>
+<div style="display:flex; width:100px;">
+ <div style="min-width:0; flex:1 1; display:table; background:green;">
+ <div style="width:500px; height:100px;"></div>
+ </div>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-001-ref.html b/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-001-ref.html
new file mode 100644
index 00000000000..f5cc3bd65bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-001-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS-fonts: reference file</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<style>
+@font-face {
+ font-family: 'B';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/AD.woff) format('woff');
+}
+
+div {
+ width: 1ex;
+ height: 1ex;
+
+ font-size: 200px;
+ background: blue;
+ font-family: 'B';
+}
+</style>
+
+<p>Test passes if there is <strong>a blue square</strong> below.
+
+<div></div>
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-001.html b/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-001.html
new file mode 100644
index 00000000000..065be3a48f2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-001.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS-fonts: first available font and the ex unit</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/css-fonts-3/#first-available-font">
+<link rel="help" href="https://drafts.csswg.org/css-fonts-4/#first-available-font">
+<link rel="match" href="first-available-font-001-ref.html">
+<meta name="flags" content="">
+<meta name="assert" content="Fonts that do not include the U+0020 character are not considered the first available font (used to determine the ex unit), even when at the start of the font list.">
+<style>
+/* Two arbitrary fonts with different metrics */
+@font-face {
+ font-family: 'A-no-space';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/Revalia.woff) format('woff');
+ unicode-range: U+0061; /* Not including U+0020, so it cannot be the first available font*/
+}
+@font-face {
+ font-family: 'B';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/AD.woff) format('woff');
+}
+
+div {
+ width: 1ex;
+ height: 0.5ex;
+
+ font-size: 200px;
+ background: blue;
+ position: absolute;
+}
+#t1 { font-family: 'B', sans-serif; margin-top: 0.5ex; } /* half a square, shifted down */
+#t2 { font-family: 'A-no-space', 'B', monospace; } /* Should use B as the first available font, and therefore be the same size as t1 */
+
+/* Both elements are using different generic fallback fonts, so that they end up being sized differently if web-fonts fail to load. */
+
+</style>
+
+<p>Test passes if there is <strong>a blue square</strong> below.
+
+<div id=t1></div>
+<div id=t2></div>
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-002-ref.html b/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-002-ref.html
new file mode 100644
index 00000000000..cbfcd3112e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-002-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS-fonts: reference file</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<style>
+@font-face {
+ font-family: 'B';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/AD.woff) format('woff');
+}
+
+div {
+ width: 1ch;
+ height: 1ch;
+
+ font-size: 200px;
+ background: blue;
+ font-family: 'B';
+}
+</style>
+
+<p>Test passes if there is <strong>a blue square</strong> below.
+
+<div></div>
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-002.html b/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-002.html
new file mode 100644
index 00000000000..cfd580927cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-002.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS-fonts: first available font and the ch unit</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/css-fonts-3/#first-available-font">
+<link rel="help" href="https://drafts.csswg.org/css-fonts-4/#first-available-font">
+<link rel="match" href="first-available-font-002-ref.html">
+<meta name="flags" content="">
+<meta name="assert" content="Fonts that do not include the U+0020 character are not considered the first available font (used to determine the ch unit), even when at the start of the font list.">
+<style>
+/* Two arbitrary fonts with different metrics */
+@font-face {
+ font-family: 'A-no-space';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/Revalia.woff) format('woff');
+ unicode-range: U+0061; /* Not including U+0020, so it cannot be the first available font*/
+}
+@font-face {
+ font-family: 'B';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/AD.woff) format('woff');
+}
+
+div {
+ width: 1ch;
+ height: 0.5ch;
+
+ font-size: 200px;
+ background: blue;
+ position: absolute;
+}
+#t1 { font-family: 'B', sans-serif; margin-top: 0.5ch; } /* half a square, shifted down */
+#t2 { font-family: 'A-no-space', 'B', monospace; } /* Should use B as the first available font, and therefore be the same size as t1 */
+
+/* Both elements are using different generic fallback fonts, so that they end up being sized differently if web-fonts fail to load. */
+
+</style>
+
+<p>Test passes if there is <strong>a blue square</strong> below.
+
+<div id=t1></div>
+<div id=t2></div>
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-003-ref.html b/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-003-ref.html
new file mode 100644
index 00000000000..afcbe3b4b34
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-003-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS-fonts: reference file</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<style>
+@font-face {
+ font-family: 'A';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/Revalia.woff) format('woff');
+}
+div {
+ position: absolute;
+ line-height: normal;
+ font-size: 100px;
+ color: transparent;
+ border: solid black 1px;
+ width: 100px;
+ font-family: A;
+}
+
+.ba { margin-left: 100px; }
+</style>
+
+<p>There should be <strong>two identically sized rectangles</strong> below.
+
+<div class="ba">a</div>
+<div class="a">a</div>
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-003.html b/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-003.html
new file mode 100644
index 00000000000..948171df258
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-003.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS-fonts: first available font and the strut</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/css-fonts-3/#first-available-font">
+<link rel="help" href="https://drafts.csswg.org/css-fonts-4/#first-available-font">
+<link rel="match" href="first-available-font-003-ref.html">
+<meta name="flags" content="">
+<meta name="assert" content="The strut, which impacts the line height, is taken from the primary font, which is the first font to include the U+0020 character.">
+<style>
+/* Two arbitrary fonts with different metrics */
+@font-face {
+ font-family: 'A';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/Revalia.woff) format('woff');
+}
+@font-face {
+ font-family: 'B-no-space';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/AD.woff) format('woff');
+ unicode-range: U+0062;
+}
+
+div {
+ position: absolute;
+ line-height: normal;
+ font-size: 100px;
+ color: transparent;
+ border: solid black 1px;
+ width: 100px;
+}
+
+.a { font-family: A; }
+.ba { font-family: B-no-space, A; margin-left: 100px; }
+</style>
+
+<p>There should be <strong>two identically sized rectangles</strong> below.
+
+<!-- Both divs show the same content with the same font,
+ but the first div has an unused font earlier in the list,
+ while the second one does not.
+ However, that font does not include the U+0020 character,
+ and can therefore not be the first available font.
+ If it had been, it would affect the height of the strut,
+ making the height different.
+ Since it is not, both boxes are expected to be the same height. -->
+<div class="ba">a</div>
+<div class="a">a</div>
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-004.html b/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-004.html
new file mode 100644
index 00000000000..d2fb1616842
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-004.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS-fonts: first available font and the strut</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/css-fonts-3/#first-available-font">
+<link rel="help" href="https://drafts.csswg.org/css-fonts-4/#first-available-font">
+<link rel="match" href="first-available-font-003-ref.html">
+<meta name="flags" content="">
+<meta name="assert" content="The strut, which impacts the line height, is taken from the primary font, which is the first font to include the U+0020 character.
+The fact that that font is used somewhere else in the page makes no difference.">
+<style>
+/* Two arbitrary fonts with different metrics */
+@font-face {
+ font-family: 'A';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/Revalia.woff) format('woff');
+}
+@font-face {
+ font-family: 'B-no-space';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/AD.woff) format('woff');
+ unicode-range: U+0062;
+}
+
+div {
+ position: absolute;
+ line-height: normal;
+ font-size: 100px;
+ color: transparent;
+ border: solid black 1px;
+ width: 100px;
+}
+
+.a { font-family: A; }
+.ba { font-family: B-no-space, A; margin-left: 100px; }
+.loader { font-family: B-no-space; border: none; }
+</style>
+
+<p>There should be <strong>two identically sized rectangles</strong> below.
+
+<div class=loader>b</div>
+
+<!-- Both divs show the same content with the same font,
+ but the first div has an unused font earlier in the list,
+ while the second one does not.
+ However, that font does not include the U+0020 character,
+ and can therefore not be the first available font.
+ If it had been, it would affect the height of the strut,
+ making the height different.
+ Since it is not, both boxes are expected to be the same height. -->
+<div class="ba">a</div>
+<div class="a">a</div>
+
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-005-ref.html b/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-005-ref.html
new file mode 100644
index 00000000000..9f27c19670c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-005-ref.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS fonts test: baseline position with explicit sizing, no space in first font</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<p>Test passes if there is <strong>no red</strong> below.
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-005.html b/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-005.html
new file mode 100644
index 00000000000..bf46a9f12f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-005.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS fonts test: baseline position with explicit sizing, no space in first font</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/css-fonts-3/#first-available-font">
+<link rel="help" href="https://drafts.csswg.org/css-fonts-4/#first-available-font">
+<link rel="match" href="first-available-font-005-ref.html">
+<meta name="flags" content="">
+<meta name="assert" content="The position of the baseline in an inline-level box whose height is determined by a non-normal value of line-height
+ does depend on the primary font, which is the first that contains U+0020.">
+<style>
+@font-face {
+ font-family: 'A-no-space';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/Revalia.woff) format('woff');
+ unicode-range: U+0061;
+}
+@font-face {
+ font-family: 'B-no-space';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/AD.woff) format('woff');
+ unicode-range: U+0061;
+}
+@font-face {
+ font-family: 'B';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/AD.woff) format('woff');
+}
+
+div {
+ position: absolute;
+ line-height: 100px;
+ font-size: 100px;
+ width: 300px; /* plenty of room for the (invisible) text */
+ text-align: right;
+ color: transparent;
+ outline: solid;
+}
+span { /* visible thing aligned to the baseline, and small enough to not influence its position */
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+}
+
+/* white #a is on top of red #b,
+ The first font in their respective lists do no contain U+0020,
+ and therfore the first available font should be the next one, which is the same.
+ Since the baseline should be based on the primary font,
+ their baselines should line up and red #b should be invisible.*/
+#a { font-family: A-no-space, B; }
+#a span { background: red; }
+
+#b { font-family: B-no-space, B; }
+#b span { background: white; }
+
+</style>
+
+<p>Test passes if there is <strong>no red</strong> below.
+
+<div id=a>bb<span></span></div>
+<div id=b>bb<span></span></div>
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-006.html b/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-006.html
new file mode 100644
index 00000000000..6f543840a50
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-006.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS fonts test: baseline position with explicit sizing, no space in first font</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/css-fonts-3/#first-available-font">
+<link rel="help" href="https://drafts.csswg.org/css-fonts-4/#first-available-font">
+<link rel="match" href="first-available-font-005-ref.html">
+<meta name="flags" content="">
+<meta name="assert" content="The position of the baseline in an inline-level box whose height is determined by a non-normal value of line-height
+ does depend on the primary font, which is the first that contains U+0020.">
+<style>
+@font-face {
+ font-family: 'A-no-space';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/Revalia.woff) format('woff');
+ unicode-range: U+0061;
+}
+@font-face {
+ font-family: 'B-no-space';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/AD.woff) format('woff');
+ unicode-range: U+0061;
+}
+@font-face {
+ font-family: 'B';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/AD.woff) format('woff');
+}
+
+div {
+ position: absolute;
+ line-height: 100px;
+ font-size: 100px;
+ width: 300px; /* plenty of room for the (invisible) text */
+ text-align: right;
+ color: transparent;
+ outline: solid;
+}
+span { /* visible thing aligned to the baseline, and small enough to not influence its position */
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+}
+
+/* white #a is on top of red #b,
+ The first font in their respective lists do no contain U+0020,
+ and therfore the first available font should be the next one, which is the same.
+ Since the baseline should be based on the primary font,
+ their baselines should line up and red #b should be invisible.
+ The fact that that font is used should make no difference.
+ */
+#a { font-family: A-no-space, B; }
+#a span { background: red; }
+
+#b { font-family: B-no-space, B; }
+#b span { background: white; }
+
+</style>
+
+<p>Test passes if there is <strong>no red</strong> below.
+
+<div id=a>aa<span></span></div>
+<div id=b>aa<span></span></div>
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-007.html b/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-007.html
new file mode 100644
index 00000000000..a05b029a0ab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-fonts/first-available-font-007.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS-fonts: inline level box content height and first available font, missing U+0020</title>
+<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
+<link rel="help" href="https://drafts.csswg.org/css-fonts-3/#first-available-font">
+<link rel="help" href="https://drafts.csswg.org/css-fonts-4/#first-available-font">
+<link rel="match" href="first-available-font-005-ref.html">
+<meta name="flags" content="">
+<meta name="assert" content="The height of the content area of an inline-level depends only on the first available font, which is the first one to include U+0020.">
+<style>
+/* Two Arbitrary fonts with different metrics. One has a taller ascender, the other a deeper descender. */
+@font-face {
+ font-family: 'A-no-space';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/Revalia.woff) format('woff');
+ unicode-range: U+0061;
+}
+@font-face {
+ font-family: 'B';
+ font-style: normal;
+ font-weight: 400;
+ src: url(support/AD.woff) format('woff');
+}
+
+div {
+ font-size: 50px;
+ display: inline-block;
+ width: 40px;
+ overflow: hidden;
+}
+
+span { color: transparent; }
+
+div:nth-of-type(1) {
+ font-family: B;
+}
+div:nth-of-type(1) span { background: red; }
+
+/* The second div should have the same first available font as the first one, since A-no-space does no include U+0020.
+ Both div's span's should thefore overflap exactly, with the white one hiding the red.
+ */
+div:nth-of-type(2) {
+ font-family: A-no-space, B;
+ margin-left: -40px;
+}
+div:nth-of-type(2) span { background: white; }
+</style>
+
+<p>Test passes if there is <strong>no red</strong> below.
+
+<div><span>aaaaa</span></div><div><span>aaaaa</span></div>
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/font-default-01-ref.html b/tests/wpt/web-platform-tests/css/css-fonts/font-default-01-ref.html
new file mode 100644
index 00000000000..bbe0251f243
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-fonts/font-default-01-ref.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test: font default features</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<style>
+ @font-face {
+ font-family: fwf;
+ src: url(support/fonts/FontWithFancyFeatures.otf);
+ }
+ .tests {
+ font-family: fwf;
+ font-size: 4em;
+ line-height: 1.1;
+ }
+</style>
+
+<body>
+<!-- test font does not currently test for rlig or locl -->
+<p>Test passes if the two lines below are identical, with six check marks (✓). </p>
+<section class="tests">
+ <p class="ref">AAAAAA</p>
+ <p class="ref">AAAAAA</p>
+</section> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/font-default-01.html b/tests/wpt/web-platform-tests/css/css-fonts/font-default-01.html
new file mode 100644
index 00000000000..99fc58b7e18
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-fonts/font-default-01.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test: font default features</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#default-features">
+<link rel="match" href="font-default-01-ref.html">
+<meta name="assert" content="Required ligatures, common ligatures and contextual forms must be enabled by default (OpenType features: rlig, liga, clig, calt), along with localized forms (OpenType feature: locl), and features required for proper display of composed characters and marks (OpenType features: ccmp, mark, mkmk).">
+<style>
+ @font-face {
+ font-family: fwf;
+ src: url(support/fonts/FontWithFancyFeatures.otf);
+ }
+ .tests {
+ font-family: fwf;
+ font-size: 4em;
+ line-height: 1.1;
+ }
+</style>
+
+<body>
+<!-- test font does not currently test for rlig or locl -->
+<p>Test passes if the two lines below are identical, with six check marks (✓). </p>
+<section class="tests">
+ <p class="test">CDGÂÂÄ</p>
+ <p class="ref">AAAAAA</p>
+</section> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/font-default-02-ref.html b/tests/wpt/web-platform-tests/css/css-fonts/font-default-02-ref.html
new file mode 100644
index 00000000000..6d45ace67e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-fonts/font-default-02-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test: font default features</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<style>
+ @font-face {
+ font-family: fwf;
+ src: url(support/fonts/FontWithFancyFeatures.otf);
+ }
+ .tests {
+ font-family: fwf;
+ font-size: 4em;
+ line-height: 1.1;
+ }
+ .test {
+ font-variant: normal;
+ }
+</style>
+
+<body>
+<!-- test font does not currently test for rlig or locl -->
+<p>Test passes if the three lines below are identical, with six check marks (✓). </p>
+<section class="tests">
+ <p class="ref">AAAAAA</p>
+ <p class="ref">AAAAAA</p>
+ <p class="ref">AAAAAA</p>
+</section> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/font-default-02.html b/tests/wpt/web-platform-tests/css/css-fonts/font-default-02.html
new file mode 100644
index 00000000000..24f61942140
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-fonts/font-default-02.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test: font default features</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#default-features">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-variant-prop">
+<link rel="match" href="font-default-02-ref.html">
+<meta name="assert" content="These features must always be enabled, even when the value of the ‘font-variant’ and ‘font-feature-settings’ properties is ‘normal’. ">
+<style>
+ @font-face {
+ font-family: fwf;
+ src: url(support/fonts/FontWithFancyFeatures.otf);
+ }
+ .tests {
+ font-family: fwf;
+ font-size: 4em;
+ line-height: 1.1;
+ }
+ .test {
+ font-variant: normal;
+ }
+</style>
+
+<body>
+<!-- test font does not currently test for rlig or locl -->
+<p>Test passes if the three lines below are identical, with six check marks (✓). </p>
+<section class="tests">
+ <p class="default">CDGÂÂÄ</p>
+ <p class="test">CDGÂÂÄ</p>
+ <p class="ref">AAAAAA</p>
+</section> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/font-default-03-ref.html b/tests/wpt/web-platform-tests/css/css-fonts/font-default-03-ref.html
new file mode 100644
index 00000000000..2f1d160c123
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-fonts/font-default-03-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test: font default features</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<style>
+ @font-face {
+ font-family: fwf;
+ src: url(support/fonts/FontWithFancyFeatures.otf);
+ }
+ .tests {
+ font-family: fwf;
+ font-size: 4em;
+ line-height: 1.1;
+ }
+ .test {
+ font-feature-settings: normal;
+ }
+</style>
+
+<body>
+<!-- test font does not currently test for rlig or locl -->
+<p>Test passes if the three lines below are identical, with six check marks (✓). </p>
+<section class="tests">
+ <p class="default">CDGÂÂÄ</p>
+ <p class="test">CDGÂÂÄ</p>
+ <p class="ref">AAAAAA</p>
+</section> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/font-default-03.html b/tests/wpt/web-platform-tests/css/css-fonts/font-default-03.html
new file mode 100644
index 00000000000..a72a4bc00d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-fonts/font-default-03.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test: font default features</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#default-features">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-feature-settings-prop">
+<link rel="match" href="font-default-03-ref.html">
+<meta name="assert" content="These features must always be enabled, even when the value of the ‘font-variant’ and ‘font-feature-settings’ properties is ‘normal’. ">
+<style>
+ @font-face {
+ font-family: fwf;
+ src: url(support/fonts/FontWithFancyFeatures.otf);
+ }
+ .tests {
+ font-family: fwf;
+ font-size: 4em;
+ line-height: 1.1;
+ }
+ .test {
+ font-feature-settings: normal;
+ }
+</style>
+
+<body>
+<!-- test font does not currently test for rlig or locl -->
+<p>Test passes if the three lines below are identical, with six check marks (✓). </p>
+<section class="tests">
+ <p class="default">CDGÂÂÄ</p>
+ <p class="test">CDGÂÂÄ</p>
+ <p class="ref">AAAAAA</p>
+</section> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/font-default-04-a-ref.html b/tests/wpt/web-platform-tests/css/css-fonts/font-default-04-a-ref.html
new file mode 100644
index 00000000000..cf428d2cf15
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-fonts/font-default-04-a-ref.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test: font default features</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<meta name="assert" content="For upright text within vertical text runs, vertical alternates (OpenType feature: vert) must be enabled">
+<style>
+ @font-face {
+ font-family: fwf;
+ src: url(support/fonts/FontWithFancyFeatures.otf);
+ }
+ .tests {
+ font-family: fwf;
+ font-size: 4em;
+ line-height: 1.1;
+ writing-mode: vertical-rl;
+ text-orientation: upright;
+ color: green;
+ }
+ .default {
+ color: purple;
+ }
+</style>
+
+<body>
+<p>Test passes if the first <em>vertical</em> line (in purple) has <em>at least one</em> check mark
+and the next two lines (in green) are identical, with two check marks (✓).</p>
+<section class="tests">
+ <p class="default">AB</p>
+ <p><span class="test1">A</span><span class="test2">A</span></p>
+ <p class="ref">AA</p>
+</section> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/font-default-04-b-ref.html b/tests/wpt/web-platform-tests/css/css-fonts/font-default-04-b-ref.html
new file mode 100644
index 00000000000..3051b27365b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-fonts/font-default-04-b-ref.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test: font default features</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<meta name="assert" content="For upright text within vertical text runs, vertical alternates (OpenType feature: vert) must be enabled">
+<style>
+ @font-face {
+ font-family: fwf;
+ src: url(support/fonts/FontWithFancyFeatures.otf);
+ }
+ .tests {
+ font-family: fwf;
+ font-size: 4em;
+ line-height: 1.1;
+ writing-mode: vertical-rl;
+ text-orientation: upright;
+ color: green;
+ }
+ .default {
+ color: purple;
+ }
+</style>
+
+<body>
+<p>Test passes if the first <em>vertical</em> line (in purple) has <em>at least one</em> check mark
+and the next two lines (in green) are identical, with two check marks (✓).</p>
+<section class="tests">
+ <p class="default">BA</p>
+ <p><span class="test1">A</span><span class="test2">A</span></p>
+ <p class="ref">AA</p>
+</section> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/font-default-04-c-ref.html b/tests/wpt/web-platform-tests/css/css-fonts/font-default-04-c-ref.html
new file mode 100644
index 00000000000..773acfc592e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-fonts/font-default-04-c-ref.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test: font default features</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<meta name="assert" content="For upright text within vertical text runs, vertical alternates (OpenType feature: vert) must be enabled">
+<style>
+ @font-face {
+ font-family: fwf;
+ src: url(support/fonts/FontWithFancyFeatures.otf);
+ }
+ .tests {
+ font-family: fwf;
+ font-size: 4em;
+ line-height: 1.1;
+ writing-mode: vertical-rl;
+ text-orientation: upright;
+ color: green;
+ }
+ .default {
+ color: purple;
+ }
+</style>
+
+<body>
+<p>Test passes if the first <em>vertical</em> line (in purple) has <em>at least one</em> check mark
+and the next two lines (in green) are identical, with two check marks (✓).</p>
+<section class="tests">
+ <p class="default">AA</p>
+ <p><span class="test1">A</span><span class="test2">A</span></p>
+ <p class="ref">AA</p>
+</section> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/font-default-04.html b/tests/wpt/web-platform-tests/css/css-fonts/font-default-04.html
new file mode 100644
index 00000000000..5493d7205fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-fonts/font-default-04.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test: font default features</title>
+<link rel="author" title="Chris Lilley" href="chris@w3.org">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#default-features">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#font-feature-settings-prop">
+<link rel="help" href="https://www.w3.org/TR/css-writing-modes-3/#block-flow">
+<link rel="help" href="https://www.w3.org/TR/css-writing-modes-3/#text-orientation">
+<link rel="match" href="font-default-04-a-ref.html">
+<link rel="match" href="font-default-04-b-ref.html">
+<link rel="match" href="font-default-04-c-ref.html">
+<meta name="assert" content="For upright text within vertical text runs, vertical alternates (OpenType feature: vert) must be enabled">
+<style>
+ @font-face {
+ font-family: fwf;
+ src: url(support/fonts/FontWithFancyFeatures.otf);
+ }
+ .tests {
+ font-family: fwf;
+ font-size: 4em;
+ line-height: 1.1;
+ writing-mode: vertical-rl;
+ text-orientation: upright;
+ color: green;
+ }
+ .default {
+ color: purple;
+ }
+ .test1 {
+ font-feature-settings: "vert" on;
+ }
+ .test2 {
+ font-feature-settings: "vert" 2;
+ }
+</style>
+
+<body>
+<p>Test passes if the first <em>vertical</em> line (in purple) has <em>at least one</em> check mark
+and the next two lines (in green) are identical, with two check marks (✓).</p>
+<section class="tests">
+ <p class="default">Å人</p>
+ <p><span class="test1">Å</span><span class="test2">人</span></p>
+ <p class="ref">AA</p>
+</section> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/font-display/font-display-change-ref.html b/tests/wpt/web-platform-tests/css/css-fonts/font-display/font-display-change-ref.html
new file mode 100644
index 00000000000..e06a5593999
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-fonts/font-display/font-display-change-ref.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Updating font-display value while loading</title>
+<script>
+
+window.onload = () => {
+ const displayValues = [ 'auto', 'block', 'swap', 'fallback', 'optional' ];
+
+ for (let value of displayValues) {
+ let face = new FontFace(value,
+ 'url("/fonts/Ahem.ttf?pipe=trickle(d5)")',
+ {display: value});
+ document.fonts.add(face);
+ face.load();
+ }
+
+ setTimeout(() => {
+ document.documentElement.classList.remove("reftest-wait");
+ }, 200);
+};
+
+</script>
+<table>
+ <tr>
+ <th>auto</th>
+ <th>block</th>
+ <th>swap</th>
+ <th>fallback</th>
+ <th>optional</th>
+ </tr>
+ <tr>
+ <td>from auto</td>
+ <td style="font-family: auto">a</td>
+ <td style="font-family: block">a</td>
+ <td style="font-family: swap">a</td>
+ <td style="font-family: fallback">a</td>
+ <td style="font-family: optional">a</td>
+ </tr>
+ <tr>
+ <td>from block</td>
+ <td style="font-family: auto">a</td>
+ <td style="font-family: block">a</td>
+ <td style="font-family: swap">a</td>
+ <td style="font-family: fallback">a</td>
+ <td style="font-family: optional">a</td>
+ </tr>
+ <tr>
+ <td>from swap</td>
+ <td style="font-family: auto">a</td>
+ <td style="font-family: block">a</td>
+ <td style="font-family: swap">a</td>
+ <td style="font-family: fallback">a</td>
+ <td style="font-family: optional">a</td>
+ </tr>
+ <tr>
+ <td>from fallback</td>
+ <td style="font-family: auto">a</td>
+ <td style="font-family: block">a</td>
+ <td style="font-family: swap">a</td>
+ <td style="font-family: fallback">a</td>
+ <td style="font-family: optional">a</td>
+ </tr>
+ <tr>
+ <td>from optional</td>
+ <td style="font-family: auto">a</td>
+ <td style="font-family: block">a</td>
+ <td style="font-family: swap">a</td>
+ <td style="font-family: fallback">a</td>
+ <td style="font-family: optional">a</td>
+ </tr>
+</table>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/font-display/font-display-change.html b/tests/wpt/web-platform-tests/css/css-fonts/font-display/font-display-change.html
new file mode 100644
index 00000000000..64130ca52af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-fonts/font-display/font-display-change.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Updating font-display value while loading</title>
+<link rel="help" href="https://drafts.csswg.org/css-fonts-4/#font-display-desc">
+<link rel="match" href="font-display-change-ref.html">
+<script>
+
+window.onload = () => {
+ const displayValues = [ 'auto', 'block', 'swap', 'fallback', 'optional' ];
+
+ let updateFuncs = [];
+
+ for (let initialValue of displayValues) {
+ for (let targetValue of displayValues) {
+ let face = new FontFace(initialValue + '-' + targetValue,
+ 'url("/fonts/Ahem.ttf?pipe=trickle(d5)")',
+ {display: initialValue});
+ document.fonts.add(face);
+ face.load();
+ updateFuncs.push(() => {
+ face.display = targetValue;
+ });
+ }
+ }
+
+ setTimeout(() => {
+ for (let update of updateFuncs) {
+ update();
+ }
+ document.documentElement.classList.remove("reftest-wait");
+ }, 200);
+};
+
+</script>
+<table>
+ <tr>
+ <th>auto</th>
+ <th>block</th>
+ <th>swap</th>
+ <th>fallback</th>
+ <th>optional</th>
+ </tr>
+ <tr>
+ <td>from auto</td>
+ <td style="font-family: auto-auto">a</td>
+ <td style="font-family: auto-block">a</td>
+ <td style="font-family: auto-swap">a</td>
+ <td style="font-family: auto-fallback">a</td>
+ <td style="font-family: auto-optional">a</td>
+ </tr>
+ <tr>
+ <td>from block</td>
+ <td style="font-family: block-auto">a</td>
+ <td style="font-family: block-block">a</td>
+ <td style="font-family: block-swap">a</td>
+ <td style="font-family: block-fallback">a</td>
+ <td style="font-family: block-optional">a</td>
+ </tr>
+ <tr>
+ <td>from swap</td>
+ <td style="font-family: swap-auto">a</td>
+ <td style="font-family: swap-block">a</td>
+ <td style="font-family: swap-swap">a</td>
+ <td style="font-family: swap-fallback">a</td>
+ <td style="font-family: swap-optional">a</td>
+ </tr>
+ <tr>
+ <td>from fallback</td>
+ <td style="font-family: fallback-auto">a</td>
+ <td style="font-family: fallback-block">a</td>
+ <td style="font-family: fallback-swap">a</td>
+ <td style="font-family: fallback-fallback">a</td>
+ <td style="font-family: fallback-optional">a</td>
+ </tr>
+ <tr>
+ <td>from optional</td>
+ <td style="font-family: optional-auto">a</td>
+ <td style="font-family: optional-block">a</td>
+ <td style="font-family: optional-swap">a</td>
+ <td style="font-family: optional-fallback">a</td>
+ <td style="font-family: optional-optional">a</td>
+ </tr>
+</table>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/font-variant-01.html b/tests/wpt/web-platform-tests/css/css-fonts/font-variant-01.html
index e73b1d517da..ed69967d3b0 100644
--- a/tests/wpt/web-platform-tests/css/css-fonts/font-variant-01.html
+++ b/tests/wpt/web-platform-tests/css/css-fonts/font-variant-01.html
@@ -23,9 +23,9 @@
}
.outer {
font-variant-ligatures: common-ligatures discretionary-ligatures historical-ligatures contextual;
- font-variant-position: sub;
+ font-variant-numeric: oldstyle-nums;
font-variant-caps: small-caps;
- font-variant-east-asian: jis04;
+ font-variant-east-asian: jis90;
}
.child {
color: green;
@@ -36,6 +36,6 @@
<p>Test passes if the two lines below are identical, with (in purple) eight check marks (✓),
and then (in green) three check marks (✓) followed by five crosses (✗). </p>
<section class="test">
- <p class="outer">CDGFEJHa<span class="inner child">CDGFEJHa</span></p>
+ <p class="outer">CDGFEJQa<span class="inner child">CDGFEJQa</span></p>
<p class="ref">AAAAAAAA<span class="child">AAABBBBB</span></p>
</section> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/font-variant-02.html b/tests/wpt/web-platform-tests/css/css-fonts/font-variant-02.html
index 6e1aecc61a7..acda863b7d1 100644
--- a/tests/wpt/web-platform-tests/css/css-fonts/font-variant-02.html
+++ b/tests/wpt/web-platform-tests/css/css-fonts/font-variant-02.html
@@ -23,9 +23,9 @@
}
.outer {
font-variant-ligatures: common-ligatures discretionary-ligatures historical-ligatures contextual;
- font-variant-position: sub;
+ font-variant-numeric: oldstyle-nums;
font-variant-caps: small-caps;
- font-variant-east-asian: jis04;
+ font-variant-east-asian: jis90;
}
.child {
color: green;
@@ -36,6 +36,6 @@
<p>Test passes if the two lines below are identical, with (in purple) eight check marks (✓),
and then (in green) eight crosses (✗). </p>
<section class="test">
- <p class="outer">CDGFEJHa<span class="inner child">CDGFEJHa</span></p>
+ <p class="outer">CDGFEJQa<span class="inner child">CDGFEJQa</span></p>
<p class="ref">AAAAAAAA<span class="child">BBBBBBBB</span></p>
</section> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/font-variant-03.html b/tests/wpt/web-platform-tests/css/css-fonts/font-variant-03.html
index 3da212a542b..7e130cc8317 100644
--- a/tests/wpt/web-platform-tests/css/css-fonts/font-variant-03.html
+++ b/tests/wpt/web-platform-tests/css/css-fonts/font-variant-03.html
@@ -22,7 +22,7 @@
font-variant: normal;
}
.outer {
- font-feature-settings: "liga" on, "clig" on, "calt" on, "hlig" on, "dlig" on, "subs" on, "smcp" on, "jp04" on;
+ font-feature-settings: "liga" on, "clig" on, "calt" on, "hlig" on, "dlig" on, "onum" on, "smcp" on, "jp90" on;
}
.child {
color: green;
@@ -33,6 +33,6 @@
<p>Test passes if the two lines below are identical, with (in purple) eight check marks (✓),
and then (in green) eight check marks (✓). </p>
<section class="test">
- <p class="outer">CDGFEJHa<span class="inner child">CDGFEJHa</span></p>
+ <p class="outer">CDGFEJQa<span class="inner child">CDGFEJQa</span></p>
<p class="ref">AAAAAAAA<span class="child">AAAAAAAA</span></p>
</section> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/font-variant-04.html b/tests/wpt/web-platform-tests/css/css-fonts/font-variant-04.html
index 12aeaf56c45..be426398eee 100644
--- a/tests/wpt/web-platform-tests/css/css-fonts/font-variant-04.html
+++ b/tests/wpt/web-platform-tests/css/css-fonts/font-variant-04.html
@@ -22,7 +22,7 @@
font-variant: none;
}
.outer {
- font-feature-settings: "liga" on, "clig" on, "calt" on, "hlig" on, "dlig" on, "subs" on, "smcp" on, "jp04" on;
+ font-feature-settings: "liga" on, "clig" on, "calt" on, "hlig" on, "dlig" on, "onum" on, "smcp" on, "jp90" on;
}
.child {
color: green;
@@ -33,6 +33,6 @@
<p>Test passes if the two lines below are identical, with (in purple) eight check marks (✓),
and then (in green) eight check marks (✓). </p>
<section class="test">
- <p class="outer">CDGFEJHa<span class="inner child">CDGFEJHa</span></p>
+ <p class="outer">CDGFEJQa<span class="inner child">CDGFEJQa</span></p>
<p class="ref">AAAAAAAA<span class="child">AAAAAAAA</span></p>
</section> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/font-variant-alternates-parsing.html b/tests/wpt/web-platform-tests/css/css-fonts/font-variant-alternates-parsing.html
new file mode 100644
index 00000000000..a02bcedfb6b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-fonts/font-variant-alternates-parsing.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Test: font-variant-alternates: historical-forms; parses case-insensitively</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="emilio@crisal.io">
+<link rel="help" href="https://drafts.csswg.org/css-fonts/#font-variant-alternates-prop">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ let div = document.createElement('div');
+ div.style.fontVariantAlternates = "Historical-Forms";
+ assert_equals(
+ getComputedStyle(div).fontVariantAlternates,
+ "historical-forms",
+ "historical-forms is parsed case-insensitively"
+ );
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/support/AD.woff b/tests/wpt/web-platform-tests/css/css-fonts/support/AD.woff
new file mode 100644
index 00000000000..3df8ea8efda
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-fonts/support/AD.woff
Binary files differ
diff --git a/tests/wpt/web-platform-tests/css/css-fonts/support/Revalia.woff b/tests/wpt/web-platform-tests/css/css-fonts/support/Revalia.woff
new file mode 100644
index 00000000000..631bee6de90
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-fonts/support/Revalia.woff
Binary files differ
diff --git a/tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-001.html b/tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-001.html
new file mode 100644
index 00000000000..849567c600a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-001.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Grid positioned items in auto-fit tracks</title>
+<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="9. Absolute Positioning">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#auto-repeat" title="7.2.2.2. Repeat-to-fill: auto-fill and auto-fit repetitions">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#valdef-repeat-auto-fit">
+<meta name="assert" content="This test checks that positioned items don't avoid auto-fit tracks to collapse.">
+<link rel="stylesheet" href="../support/grid.css">
+<style>
+.container {
+ width: 200px;
+}
+.grid {
+ position: relative;
+ grid: 10px / repeat(auto-fit, 30px);
+}
+span {
+ background: blue;
+}
+.abs {
+ position: absolute;
+ top:0; right:0; bottom:0; left:0;
+ background: pink;
+}
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+<body onload="checkLayout('.grid')">
+<div id="log"></div>
+<br>
+<div class="container">
+ <div class="grid">
+ <span style="grid-column: 1 / 5" class="abs" data-expected-width="30" data-expected-height="10"></span>
+ <span style="grid-column: 1" data-expected-width="30" data-expected-height="10"></span>
+ </div>
+</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-002.html b/tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-002.html
new file mode 100644
index 00000000000..7271081ea6f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-002.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Grid positioned items in auto-fit tracks</title>
+<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="9. Absolute Positioning">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#auto-repeat" title="7.2.2.2. Repeat-to-fill: auto-fill and auto-fit repetitions">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#valdef-repeat-auto-fit">
+<meta name="assert" content="This test checks tracks before the first in-flow item also collapse and positioned items don't have any impact.">
+<link rel="stylesheet" href="../support/grid.css">
+<style>
+.container {
+ width: 200px;
+}
+.grid {
+ position: relative;
+ grid: 10px / repeat(auto-fit, 30px);
+}
+span {
+ background: blue;
+}
+.abs {
+ position: absolute;
+ top:0; right:0; bottom:0; left:0;
+ background: pink;
+}
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+<body onload="checkLayout('.grid')">
+<div id="log"></div>
+<br>
+<div class="container">
+ <div class="grid">
+ <span style="grid-column: 1 / 5" class="abs" data-expected-width="30" data-expected-height="10"></span>
+ <span style="grid-column: 2" data-expected-width="30" data-expected-height="10"></span>
+ </div>
+</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-003.html b/tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-003.html
new file mode 100644
index 00000000000..05ac15dd289
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-003.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Grid positioned items in auto-fit tracks</title>
+<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="9. Absolute Positioning">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#auto-repeat" title="7.2.2.2. Repeat-to-fill: auto-fill and auto-fit repetitions">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#valdef-repeat-auto-fit">
+<meta name="assert" content="This test checks that positioned items will use the area defined by the in-flow items, ignoring any collapsed track.">
+<link rel="stylesheet" href="../support/grid.css">
+<style>
+.container {
+ width: 200px;
+}
+.grid {
+ position: relative;
+ grid: 10px / repeat(auto-fit, 30px);
+}
+span {
+ background: blue;
+}
+.abs {
+ position: absolute;
+ top:0; right:0; bottom:0; left:0;
+ background: pink;
+}
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+<body onload="checkLayout('.grid')">
+<div id="log"></div>
+<br>
+<div class="container">
+ <div class="grid">
+ <span style="grid-column: 1 / 5" class="abs" data-expected-width="60" data-expected-height="10"></span>
+ <span style="grid-column: 2 / 4" data-expected-width="60" data-expected-height="10"></span>
+ </div>
+</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-004.html b/tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-004.html
new file mode 100644
index 00000000000..13b29ea9c53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-004.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Grid positioned items in auto-fit tracks and gaps</title>
+<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="9. Absolute Positioning">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#auto-repeat" title="7.2.2.2. Repeat-to-fill: auto-fill and auto-fit repetitions">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#valdef-repeat-auto-fit">
+<meta name="assert" content="This test checks that positioned items ignore collapsed gaps.">
+<link rel="stylesheet" href="../support/grid.css">
+<style>
+.container {
+ width: 200px;
+}
+.grid {
+ position: relative;
+ grid: 10px / repeat(auto-fit, 30px);
+ grid-gap: 5px;
+}
+span {
+ background: blue;
+}
+.abs {
+ position: absolute;
+ top:0; right:0; bottom:0; left:0;
+ background: pink;
+}
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+<body onload="checkLayout('.grid')">
+<div id="log"></div>
+<br>
+<div class="container">
+ <div class="grid">
+ <span style="grid-column: 1 / 5" class="abs" data-expected-width="30" data-expected-height="10"></span>
+ <span style="grid-column: 1" data-expected-width="30" data-expected-height="10"></span>
+ </div>
+</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-005.html b/tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-005.html
new file mode 100644
index 00000000000..70695c4e128
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-005.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Grid positioned items in auto-fit tracks and gaps</title>
+<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="9. Absolute Positioning">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#auto-repeat" title="7.2.2.2. Repeat-to-fill: auto-fill and auto-fit repetitions">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#valdef-repeat-auto-fit">
+<meta name="assert" content="This test checks that positioned items ignore collapsed gaps, both before and after the first in-flow item .">
+<link rel="stylesheet" href="../support/grid.css">
+<style>
+.container {
+ width: 200px;
+}
+.grid {
+ position: relative;
+ grid: 10px / repeat(auto-fit, 30px);
+ grid-gap: 5px;
+}
+span {
+ background: blue;
+}
+.abs {
+ position: absolute;
+ top:0; right:0; bottom:0; left:0;
+ background: pink;
+}
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+<body onload="checkLayout('.grid')">
+<div id="log"></div>
+<br>
+<div class="container">
+ <div class="grid">
+ <span style="grid-column: 1 / 5" class="abs" data-expected-width="30" data-expected-height="10"></span>
+ <span style="grid-column: 2" data-expected-width="30" data-expected-height="10"></span>
+ </div>
+</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-006.html b/tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-006.html
new file mode 100644
index 00000000000..5b792205ab3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-006.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Grid positioned items in auto-fit tracks and gaps</title>
+<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="9. Absolute Positioning">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#auto-repeat" title="7.2.2.2. Repeat-to-fill: auto-fill and auto-fit repetitions">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#valdef-repeat-auto-fit">
+<meta name="assert" content="This test checks that positioned items ignore collapsed gaps but consider those between in-flow items inside their grid area.">
+<link rel="stylesheet" href="../support/grid.css">
+<style>
+.container {
+ width: 200px;
+}
+.grid {
+ position: relative;
+ grid: 10px / repeat(auto-fit, 30px);
+ grid-gap: 5px;
+}
+span {
+ background: blue;
+}
+.abs {
+ position: absolute;
+ top:0; right:0; bottom:0; left:0;
+ background: pink;
+}
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+<body onload="checkLayout('.grid')">
+<div id="log"></div>
+<br>
+<div class="container">
+ <div class="grid">
+ <span style="grid-column: 2 / 5" class="abs" data-expected-width="65" data-expected-height="10"></span>
+ <span style="grid-column: 2 / 4" data-expected-width="65" data-expected-height="10"></span>
+ </div>
+</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-007.html b/tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-007.html
new file mode 100644
index 00000000000..1f9958029cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-007.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Grid positioned items in auto-fit tracks and gaps</title>
+<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos" title="9. Absolute Positioning">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#auto-repeat" title="7.2.2.2. Repeat-to-fill: auto-fill and auto-fit repetitions">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#valdef-repeat-auto-fit">
+<meta name="assert" content="This test checks that positioned items ignore collapsed gaps even with non-empty tracks before and after.">
+<link rel="stylesheet" href="../support/grid.css">
+<style>
+.container {
+ width: 250px;
+}
+.grid {
+ position: relative;
+ grid: 10px / repeat(auto-fit, 30px) 50px;
+ grid-gap: 5px;
+}
+span {
+ background: blue;
+}
+.abs {
+ position: absolute;
+ top:0; right:0; bottom:0; left:0;
+ background: pink;
+}
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+<body onload="checkLayout('.grid')">
+<div id="log"></div>
+<br>
+<div class="container">
+ <div class="grid">
+ <span style="grid-column: 2 / 5" class="abs" data-expected-width="65" data-expected-height="10"></span>
+ <span style="grid-column: 2 / 4" data-expected-width="65" data-expected-height="10"></span>
+ </div>
+</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-017.html b/tests/wpt/web-platform-tests/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-017.html
new file mode 100644
index 00000000000..2c005e154e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-017.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Self-Alignment along column axis of absolute positioned items with 'definite' grid positions</title>
+<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#column-align">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos-items">
+<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-align-self">
+<link rel="help" href="https://drafts.csswg.org/css-align-3/#valdef-self-position-start">
+<meta name="assert" content="Absolute positioned grid items don't participate in Baseline Alignment, so the value 'baseline' behaves like 'start'.">
+<style>
+.grid {
+ position: relative;
+ display: inline-grid;
+ grid-template-columns: 100px 150px;
+ grid-template-rows: 150px 100px;
+ font: 10px/1 Ahem;
+ background: grey;
+ justify-items: start;
+}
+.grid.RTL { width: 400px; }
+.grid > div { position: absolute; }
+.grid > :nth-child(1) { background: green; }
+.grid > :nth-child(2) { background: blue; }
+.grid > :nth-child(3) { background: yellow; }
+.grid > :nth-child(4) { background: red; }
+
+.RTL { direction: rtl; }
+.verticalLR { writing-mode: vertical-lr; }
+.verticalRL { writing-mode: vertical-rl; }
+
+.firstRowFirstColumn {
+ grid-row: 1 / 2;
+ grid-column: 1 / 2;
+ align-self: baseline;
+}
+.firstRowSecondColumn {
+ grid-row: 1 / 2;
+ grid-column: 2 / 3;
+ align-self: baseline;
+}
+.secondRowFirstColumn {
+ grid-row: 2 / 3;
+ grid-column: 1 / 2;
+ align-self: baseline;
+}
+.secondRowSecondColumn {
+ grid-row: 2 / 3;
+ grid-column: 2 / 3;
+ align-self: baseline;
+}
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+<body onload="checkLayout('.grid')">
+<div class="grid">
+ <div data-offset-x="0" data-offset-y="0" data-expected-width="60" data-expected-height="10" class="firstRowFirstColumn">X XX X</div>
+ <div data-offset-x="100" data-offset-y="0" data-expected-width="70" data-expected-height="30" class="firstRowSecondColumn">XX X<br>X XXX X<br>XX XXX</div>
+ <div data-offset-x="0" data-offset-y="150" data-expected-width="60" data-expected-height="10" class="secondRowFirstColumn">X XX X</div>
+ <div data-offset-x="100" data-offset-y="150" data-expected-width="60" data-expected-height="40" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div>
+</div>
+
+<div class="grid RTL">
+ <div data-offset-x="340" data-offset-y="0" data-expected-width="60" data-expected-height="10" class="firstRowFirstColumn">X XX X</div>
+ <div data-offset-x="230" data-offset-y="0" data-expected-width="70" data-expected-height="30" class="firstRowSecondColumn">XX X<br>X XXX X<br>XX XXX</div>
+ <div data-offset-x="340" data-offset-y="150" data-expected-width="60" data-expected-height="10" class="secondRowFirstColumn">X XX X</div>
+ <div data-offset-x="240" data-offset-y="150" data-expected-width="60" data-expected-height="40" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div>
+</div>
+
+<br><br>
+
+<div class="grid verticalLR">
+ <div data-offset-x="0" data-offset-y="0" data-expected-width="10" data-expected-height="60" class="firstRowFirstColumn">X XX X</div>
+ <div data-offset-x="0" data-offset-y="100" data-expected-width="30" data-expected-height="70" class="firstRowSecondColumn">XX X<br>X XXX X<br>XX XXX</div>
+ <div data-offset-x="150" data-offset-y="0" data-expected-width="10" data-expected-height="60" class="secondRowFirstColumn">X XX X</div>
+ <div data-offset-x="150" data-offset-y="100" data-expected-width="40" data-expected-height="60" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div>
+</div>
+
+<div class="grid verticalRL">
+ <div data-offset-x="240" data-offset-y="0" data-expected-width="10" data-expected-height="60" class="firstRowFirstColumn">X XX X</div>
+ <div data-offset-x="220" data-offset-y="100" data-expected-width="30" data-expected-height="70" class="firstRowSecondColumn">XX X<br>X XXX X<br>XX XXX</div>
+ <div data-offset-x="90" data-offset-y="0" data-expected-width="10" data-expected-height="60" class="secondRowFirstColumn">X XX X</div>
+ <div data-offset-x="60" data-offset-y="100" data-expected-width="40" data-expected-height="60" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div>
+</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-017.html b/tests/wpt/web-platform-tests/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-017.html
new file mode 100644
index 00000000000..6cc1e4e4b7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-017.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Self-Alignment along row axis of absolute positioned items with 'definite' grid positions</title>
+<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#row-align">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#abspos-items">
+<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-justify-self">
+<link rel="help" href="https://drafts.csswg.org/css-align-3/#valdef-self-position-start">
+<meta name="assert" content="Absolute positioned grid items don't participate in Baseline Alignment, so the value 'baseline' behaves like 'start'.">
+<style>
+.grid {
+ position: relative;
+ display: inline-grid;
+ grid-template-columns: 100px 150px;
+ grid-template-rows: 150px 100px;
+ font: 10px/1 Ahem;
+ background: grey;
+ align-items: start;
+}
+.grid.RTL { width: 400px; }
+.grid > div { position: absolute; }
+.grid > :nth-child(1) { background: green; }
+.grid > :nth-child(2) { background: blue; }
+.grid > :nth-child(3) { background: yellow; }
+.grid > :nth-child(4) { background: red; }
+
+.RTL { direction: rtl; }
+.verticalLR { writing-mode: vertical-lr; }
+.verticalRL { writing-mode: vertical-rl; }
+
+.firstRowFirstColumn {
+ grid-row: 1 / 2;
+ grid-column: 1 / 2;
+ justify-self: baseline;
+}
+.firstRowSecondColumn {
+ grid-row: 1 / 2;
+ grid-column: 2 / 3;
+ justify-self: baseline;
+}
+.secondRowFirstColumn {
+ grid-row: 2 / 3;
+ grid-column: 1 / 2;
+ justify-self: baseline;
+}
+.secondRowSecondColumn {
+ grid-row: 2 / 3;
+ grid-column: 2 / 3;
+ justify-self: baseline;
+}
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+<body onload="checkLayout('.grid')">
+<div class="grid">
+ <div data-offset-x="0" data-offset-y="0" data-expected-width="60" data-expected-height="10" class="firstRowFirstColumn">X XX X</div>
+ <div data-offset-x="100" data-offset-y="0" data-expected-width="70" data-expected-height="30" class="firstRowSecondColumn">XX X<br>X XXX X<br>XX XXX</div>
+ <div data-offset-x="0" data-offset-y="150" data-expected-width="60" data-expected-height="10" class="secondRowFirstColumn">X XX X</div>
+ <div data-offset-x="100" data-offset-y="150" data-expected-width="60" data-expected-height="40" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div>
+</div>
+
+<div class="grid RTL">
+ <div data-offset-x="340" data-offset-y="0" data-expected-width="60" data-expected-height="10" class="firstRowFirstColumn">X XX X</div>
+ <div data-offset-x="230" data-offset-y="0" data-expected-width="70" data-expected-height="30" class="firstRowSecondColumn">XX X<br>X XXX X<br>XX XXX</div>
+ <div data-offset-x="340" data-offset-y="150" data-expected-width="60" data-expected-height="10" class="secondRowFirstColumn">X XX X</div>
+ <div data-offset-x="240" data-offset-y="150" data-expected-width="60" data-expected-height="40" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div>
+</div>
+
+<br><br>
+
+<div class="grid verticalLR">
+ <div data-offset-x="0" data-offset-y="0" data-expected-width="10" data-expected-height="60" class="firstRowFirstColumn">X XX X</div>
+ <div data-offset-x="0" data-offset-y="100" data-expected-width="30" data-expected-height="70" class="firstRowSecondColumn">XX X<br>X XXX X<br>XX XXX</div>
+ <div data-offset-x="150" data-offset-y="0" data-expected-width="10" data-expected-height="60" class="secondRowFirstColumn">X XX X</div>
+ <div data-offset-x="150" data-offset-y="100" data-expected-width="40" data-expected-height="60" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div>
+</div>
+
+<div class="grid verticalRL">
+ <div data-offset-x="240" data-offset-y="0" data-expected-width="10" data-expected-height="60" class="firstRowFirstColumn">X XX X</div>
+ <div data-offset-x="220" data-offset-y="100" data-expected-width="30" data-expected-height="70" class="firstRowSecondColumn">XX X<br>X XXX X<br>XX XXX</div>
+ <div data-offset-x="90" data-offset-y="0" data-expected-width="10" data-expected-height="60" class="secondRowFirstColumn">X XX X</div>
+ <div data-offset-x="60" data-offset-y="100" data-expected-width="40" data-expected-height="60" class="secondRowSecondColumn">XX X<br>X XXX<br>X<br>XX XXX</div>
+</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/grid-definition/grid-template-columns-fit-content-001-ref.html b/tests/wpt/web-platform-tests/css/css-grid/grid-definition/grid-template-columns-fit-content-001-ref.html
index 22a293990f6..cb7a582ab10 100644
--- a/tests/wpt/web-platform-tests/css/css-grid/grid-definition/grid-template-columns-fit-content-001-ref.html
+++ b/tests/wpt/web-platform-tests/css/css-grid/grid-definition/grid-template-columns-fit-content-001-ref.html
@@ -15,26 +15,6 @@
grid-column-gap: 5px;
}
-.fc0 { grid-template-columns: minmax(auto, 0px);}
-.fc40 { grid-template-columns: minmax(auto, 40px); }
-.fc80 { grid-template-columns: minmax(auto, 80px); }
-.fc110 { grid-template-columns: auto; }
-
-.fc0x2 { grid-template-columns: repeat(2, minmax(auto, 0px));}
-.fc40x2 { grid-template-columns: repeat(2, minmax(auto, 40px)); }
-.fc80x2 { grid-template-columns: repeat(2, minmax(auto, 80px)); }
-.fc110x2 { grid-template-columns: auto auto; }
-
-.fc0p { grid-template-columns: minmax(auto, 0%); }
-.fc30p { grid-template-columns: minmax(auto, 30%); }
-.fc90p { grid-template-columns: minmax(auto, 90%); }
-.fc110p { grid-template-columns: auto; }
-
-.fc0px2 { grid-template-columns: repeat(2, minmax(auto, 0%)); }
-.fc30px2 { grid-template-columns: repeat(2, minmax(auto, 30%)); }
-.fc90px2 { grid-template-columns: repeat(2, minmax(auto, 90%)); }
-.fc110px2 { grid-template-columns: auto auto; }
-
.item {
font: 10px/1 Ahem;
background: cyan;
@@ -67,19 +47,19 @@ h3 { font-size: 1em; }
<div class="floatLeft">
<h3>Only fit-content() and with fixed size tracks.</h3>
- <div class="grid fc0">
+ <div class="grid">
<div class="item">XXX</div>
<div class="test autoRowFirstColumn"></div>
</div>
- <div class="grid fc0x2">
+ <div class="grid" style="grid-template-columns: 30px 0px;">
<div class="item">XXX</div>
<div class="spanningItem">XXX</div>
<div class="test autoRowFirstColumn"></div>
<div class="test autoRowSecondColumn"></div>
</div>
- <div class="grid fc40">
+ <div class="grid" style="grid-template-columns: 40px;">
<div class="item">XXX XXX</div>
<div class="test autoRowFirstColumn"></div>
</div>
@@ -90,45 +70,45 @@ h3 { font-size: 1em; }
<div class="test autoRowSecondColumn"></div>
</div>
- <div class="grid" style="grid-template-columns: minmax(auto, 40px) auto;">
+ <div class="grid" style="grid-template-columns: 40px auto;">
<div class="item">XXX XXX</div>
<div class="spanningItem">XXX XXX</div>
<div class="test autoRowFirstColumn"></div>
<div class="test autoRowSecondColumn"></div>
</div>
- <div class="grid fc80">
+ <div class="grid" style="grid-template-columns: 80px;">
<div class="item">XXX XXX XXX</div>
<div class="test autoRowFirstColumn"></div>
</div>
- <div class="grid fc80x2">
+ <div class="grid" style="grid-template-columns: auto auto;">
<div class="spanningItem">XXX XXX XXX</div>
<div class="test autoRowFirstColumn"></div>
<div class="test autoRowSecondColumn"></div>
</div>
- <div class="grid" style="grid-template-columns: auto minmax(auto, 80px)">
+ <div class="grid" style="grid-template-columns: 25px 70px;">
<div class="item autoRowSecondColumn">XXX XXX XXX</div>
<div class="spanningItem">XXX XXX XXX</div>
<div class="test autoRowFirstColumn"></div>
<div class="test autoRowSecondColumn"></div>
</div>
- <div class="grid" style="grid-template-columns: minmax(auto, 20px) 50%;">
+ <div class="grid" style="grid-template-columns: 20px 50px;">
<div class="spanningItem">XXX XX XXX</div>
<div class="test autoRowFirstColumn"></div>
<div class="test autoRowSecondColumn"></div>
</div>
- <div class="grid" style="grid-template-columns: minmax(10px, 40px) minmax(auto, 40px);">
+ <div class="grid" style="grid-template-columns: 40px 40px;">
<div class="item">XXXXX</div>
<div class="spanningItem">XXX XX XXX</div>
<div class="test autoRowFirstColumn"></div>
<div class="test autoRowSecondColumn"></div>
</div>
- <div class="grid" style="grid-template-columns: auto minmax(10%, 200px);">
+ <div class="grid" style="grid-template-columns: 15px 80px;">
<div class="item autoRowSecondColumn">XXXXX</div>
<div class="spanningItem">XXX XX XXX</div>
<div class="test autoRowFirstColumn"></div>
@@ -139,68 +119,68 @@ h3 { font-size: 1em; }
<div class="floatLeft">
<h3>fit-content() with other content-sized tracks.</h3>
- <div class="grid" style="grid-template-columns: minmax(auto, 40px) max-content;">
+ <div class="grid" style="grid-template-columns: 12.5px 82.5px;">
<div class="spanningItem">XXX XX XXX</div>
<div class="test autoRowFirstColumn"></div>
<div class="test autoRowSecondColumn"></div>
</div>
- <div class="grid" style="grid-template-columns: minmax(auto, 40px) max-content;">
+ <div class="grid" style="grid-template-columns: 50px 45px;">
<div class="item">XXXXX</div>
<div class="spanningItem">XXX XX XXX</div>
<div class="test autoRowFirstColumn"></div>
<div class="test autoRowSecondColumn"></div>
</div>
- <div class="grid" style="grid-template-columns: minmax(auto, 40px) max-content;">
+ <div class="grid" style="grid-template-columns: 0px 95px;">
<div class="item autoRowSecondColumn">XXXXX</div>
<div class="spanningItem">XXX XX XXX</div>
<div class="test autoRowFirstColumn"></div>
<div class="test autoRowSecondColumn"></div>
</div>
- <div class="grid" style="grid-template-columns: min-content minmax(auto, 40px);">
+ <div class="grid" style="grid-template-columns: 12.5px 40px;">
<div class="spanningItem">XXX XX XXX</div>
<div class="test autoRowFirstColumn"></div>
<div class="test autoRowSecondColumn"></div>
</div>
- <div class="grid" style="grid-template-columns: min-content minmax(auto, 40px);">
+ <div class="grid" style="grid-template-columns: 50px 40px;">
<div class="item">XXXXX</div>
<div class="spanningItem">XXX XX XXX</div>
<div class="test autoRowFirstColumn"></div>
<div class="test autoRowSecondColumn"></div>
</div>
- <div class="grid" style="grid-template-columns: min-content minmax(auto, 40px);">
+ <div class="grid" style="grid-template-columns: 0px 50px;">
<div class="item autoRowSecondColumn">XXXXX</div>
<div class="spanningItem">XXX XX XXX</div>
<div class="test autoRowFirstColumn"></div>
<div class="test autoRowSecondColumn"></div>
</div>
- <div class="grid" style="grid-template-columns: minmax(auto, 30px) min-content max-content">
+ <div class="grid" style="grid-template-columns: auto min-content max-content">
<div class="spanningItem">XXX XX XXX</div>
<div class="test autoRowFirstColumn"></div>
<div class="test autoRowSecondColumn"></div>
<div class="test autoRowThirdColumn"></div>
</div>
- <div class="grid" style="grid-template-columns: min-content minmax(auto, 30px) max-content">
+ <div class="grid" style="grid-template-columns: min-content auto max-content">
<div class="spanningItem">XXX XX XXX</div>
<div class="test autoRowFirstColumn"></div>
<div class="test autoRowSecondColumn"></div>
<div class="test autoRowThirdColumn"></div>
</div>
- <div class="grid" style="grid-template-columns: min-content max-content minmax(auto, 30px)">
+ <div class="grid" style="grid-template-columns: min-content max-content auto">
<div class="spanningItem">XXX XX XXX</div>
<div class="test autoRowFirstColumn"></div>
<div class="test autoRowSecondColumn"></div>
<div class="test autoRowThirdColumn"></div>
</div>
- <div class="grid" style="grid-template-columns: minmax(auto, 30px) min-content max-content">
+ <div class="grid" style="grid-template-columns: 30px 0px 60px;">
<div class="item" style="grid-column: 1">XXX XX</div>
<div class="spanningItem">XXX XX XXX</div>
<div class="test autoRowFirstColumn"></div>
@@ -208,7 +188,7 @@ h3 { font-size: 1em; }
<div class="test autoRowThirdColumn"></div>
</div>
- <div class="grid" style="grid-template-columns: min-content minmax(auto, 30px) max-content">
+ <div class="grid" style="grid-template-columns: 30px 0px 60px;">
<div class="item" style="grid-column: 1">XXX XX</div>
<div class="spanningItem">XXX XX XXX</div>
<div class="test autoRowFirstColumn"></div>
@@ -216,7 +196,7 @@ h3 { font-size: 1em; }
<div class="test autoRowThirdColumn"></div>
</div>
- <div class="grid" style="grid-template-columns: min-content max-content minmax(auto, 30px)">
+ <div class="grid" style="grid-template-columns: 0px 90px 0px;">
<div class="item" style="grid-column: 2">XXX XX</div>
<div class="spanningItem">XXX XX XXX</div>
<div class="test autoRowFirstColumn"></div>
@@ -227,48 +207,48 @@ h3 { font-size: 1em; }
<div class="floatLeft">
<h3>fit-content() with percentage arguments.</h3>
- <div class="grid fc0p">
+ <div class="grid" style="grid-template-columns: 30px;">
<div class="item">XXX</div>
<div class="test autoRowFirstColumn"></div>
</div>
- <div class="grid fc0px2">
+ <div class="grid" style="grid-template-columns: 30px 0px;">
<div class="item">XXX</div>
<div class="spanningItem">XXX</div>
<div class="test autoRowFirstColumn"></div>
<div class="test autoRowSecondColumn"></div>
</div>
- <div class="grid fc30p">
+ <div class="grid" style="grid-template-columns: 30px;">
<div class="item">XX XX</div>
<div class="test autoRowFirstColumn"></div>
</div>
- <div class="grid fc30px2">
+ <div class="grid" style="grid-template-columns: 30px 30px;">
<div class="spanningItem">XXX XXX</div>
<div class="test autoRowFirstColumn"></div>
<div class="test autoRowSecondColumn"></div>
</div>
- <div class="grid fc30px2">
+ <div class="grid" style="grid-template-columns: 30px 30px;">
<div class="item autoRowSecondColumn">X X X</div>
<div class="spanningItem">XXX XXX</div>
<div class="test autoRowFirstColumn"></div>
<div class="test autoRowSecondColumn"></div>
</div>
- <div class="grid fc90p">
+ <div class="grid" style="grid-template-columns: 90px;">
<div class="item">XXX XXX XXX</div>
<div class="test autoRowFirstColumn"></div>
</div>
- <div class="grid fc90px2">
+ <div class="grid" style="grid-template-columns: 47.5px 47.5px;">
<div class="spanningItem">XXX XXX XXX</div>
<div class="test autoRowFirstColumn"></div>
<div class="test autoRowSecondColumn"></div>
</div>
- <div class="grid" style="grid-template-columns: auto minmax(auto, 90%)">
+ <div class="grid" style="grid-template-columns: 15px 80px;">
<div class="item autoRowSecondColumn">XXX XXX XXX</div>
<div class="spanningItem">XXX XXX XXX</div>
<div class="test autoRowFirstColumn"></div>
@@ -277,47 +257,47 @@ h3 { font-size: 1em; }
</div>
<div class="floatLeft">
- <h3>max-content < fit-content() argument.</h3>
+ <h3>max-content &lt; fit-content() argument.</h3>
- <div class="grid fc110">
+ <div class="grid" style="grid-template-columns: 70px;">
<div class="item">XXX XXX</div>
<div class="test autoRowFirstColumn"></div>
</div>
- <div class="grid fc110x2">
+ <div class="grid" style="grid-template-columns: 32.5px 32.5px;">
<div class="spanningItem">XXX XXX</div>
<div class="test autoRowFirstColumn"></div>
<div class="test autoRowSecondColumn"></div>
</div>
- <div class="grid fc110x2">
+ <div class="grid" style="grid-template-columns: 70px 0px;">
<div class="item">XXX XXX</div>
<div class="spanningItem">XXX XXX</div>
<div class="test autoRowFirstColumn"></div>
<div class="test autoRowSecondColumn"></div>
</div>
- <div class="grid" style="grid-template-columns: auto auto;">
+ <div class="grid" style="grid-template-columns: 32.5px 32.5px;">
<div class="spanningItem">XXX XXX</div>
<div class="test autoRowFirstColumn"></div>
<div class="test autoRowSecondColumn"></div>
</div>
- <div class="grid" style="grid-template-columns: auto auto;">
+ <div class="grid" style="grid-template-columns: 45px 20px;">
<div class="item autoRowSecondColumn">XX</div>
<div class="spanningItem">XXX XXX</div>
<div class="test autoRowFirstColumn"></div>
<div class="test autoRowSecondColumn"></div>
</div>
- <div class="grid" style="grid-template-columns: max-content auto;">
+ <div class="grid" style="grid-template-columns: 92.5px 12.5px;">
<div class="spanningItem" style="grid-row: 1;">XX XX XX XX</div>
<div class="spanningItem">XXX XXX</div>
<div class="test autoRowFirstColumn"></div>
<div class="test autoRowSecondColumn"></div>
</div>
- <div class="grid" style="grid-template-columns: auto min-content;">
+ <div class="grid" style="grid-template-columns: 82.5px 12.5px;">
<div class="spanningItem" style="grid-row: 1;">XX XX XX XX</div>
<div class="spanningItem">XXX XXX</div>
<div class="test autoRowFirstColumn"></div>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/grid-definition/grid-template-columns-fit-content-001.html b/tests/wpt/web-platform-tests/css/css-grid/grid-definition/grid-template-columns-fit-content-001.html
index 808b91c32b1..d492d4585f8 100644
--- a/tests/wpt/web-platform-tests/css/css-grid/grid-definition/grid-template-columns-fit-content-001.html
+++ b/tests/wpt/web-platform-tests/css/css-grid/grid-definition/grid-template-columns-fit-content-001.html
@@ -281,7 +281,7 @@ h3 { font-size: 1em; }
</div>
<div class="floatLeft">
- <h3>max-content < fit-content() argument.</h3>
+ <h3>max-content &lt; fit-content() argument.</h3>
<div class="grid fc110">
<div class="item">XXX XXX</div>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/grid-definition/grid-template-rows-fit-content-001-ref.html b/tests/wpt/web-platform-tests/css/css-grid/grid-definition/grid-template-rows-fit-content-001-ref.html
index bff6447c6f7..a1f83dc85af 100644
--- a/tests/wpt/web-platform-tests/css/css-grid/grid-definition/grid-template-rows-fit-content-001-ref.html
+++ b/tests/wpt/web-platform-tests/css/css-grid/grid-definition/grid-template-rows-fit-content-001-ref.html
@@ -18,26 +18,6 @@
float: left;
}
-.fc0 { grid-template-rows: minmax(auto, 0px);}
-.fc40 { grid-template-rows: minmax(auto, 40px); }
-.fc80 { grid-template-rows: minmax(auto, 80px); }
-.fc110 { grid-template-rows: auto; }
-
-.fc0x2 { grid-template-rows: repeat(2, minmax(auto, 0px));}
-.fc40x2 { grid-template-rows: repeat(2, minmax(auto, 40px)); }
-.fc80x2 { grid-template-rows: repeat(2, minmax(auto, 80px)); }
-.fc110x2 { grid-template-rows: auto auto; }
-
-.fc0p { grid-template-rows: minmax(auto, 0%); }
-.fc30p { grid-template-rows: minmax(auto, 30px); }
-.fc90p { grid-template-rows: minmax(auto, 90px); }
-.fc110p { grid-template-rows: auto; }
-
-.fc0px2 { grid-template-rows: repeat(2, minmax(auto, 0%)); }
-.fc30px2 { grid-template-rows: repeat(2, minmax(auto, 30px)); }
-.fc90px2 { grid-template-rows: repeat(2, minmax(auto, 90px)); }
-.fc110px2 { grid-template-rows: auto auto; }
-
.item {
font: 10px/1 Ahem;
background: cyan;
@@ -68,68 +48,68 @@ div.grid > div { writing-mode: vertical-lr; }
<p>The test passes if it has the same output than the reference.</p>
-<div class="grid fc0">
+<div class="grid" style="grid-template-rows: 30px;">
<div class="item">XXX</div>
<div class="test firstRow"></div>
</div>
-<div class="grid fc0x2">
+<div class="grid" style="grid-template-rows: 30px 0px;">
<div class="item">XXX</div>
<div class="spanningItem">XXX</div>
<div class="test firstRow"></div>
<div class="test secondRow"></div>
</div>
-<div class="grid fc40">
+<div class="grid" style="grid-template-rows: 40px;">
<div class="item">XXX XXX</div>
<div class="test firstRow"></div>
</div>
-<div class="grid" style="grid-template-rows: auto auto;">
+<div class="grid" style="grid-template-rows: 32.5px 32.5px;">
<div class="spanningItem">XXX XXX</div>
<div class="test firstRow"></div>
<div class="test secondRow"></div>
</div>
-<div class="grid" style="grid-template-rows: minmax(auto, 40px) auto;">
+<div class="grid" style="grid-template-rows: 40px 25px;">
<div class="item">XXX XXX</div>
<div class="spanningItem">XXX XXX</div>
<div class="test firstRow"></div>
<div class="test secondRow"></div>
</div>
-<div class="grid fc80">
+<div class="grid" style="grid-template-rows: 80px;">
<div class="item">XXX XXX XXX</div>
<div class="test firstRow"></div>
</div>
-<div class="grid fc80x2">
+<div class="grid" style="grid-template-rows: 47.5px 47.5px;">
<div class="spanningItem">XXX XXX XXX</div>
<div class="test firstRow"></div>
<div class="test secondRow"></div>
</div>
-<div class="grid" style="grid-template-rows: auto minmax(auto, 80px)">
+<div class="grid" style="grid-template-rows: 25px 70px;">
<div class="item secondRow">XXX XXX XXX</div>
<div class="spanningItem">XXX XXX XXX</div>
<div class="test firstRow"></div>
<div class="test secondRow"></div>
</div>
-<div class="grid" style="grid-template-rows: minmax(auto, 20px) 50%;">
+<div class="grid" style="grid-template-rows: 20px 50px;">
<div class="spanningItem">XXX XX XXX</div>
<div class="test firstRow"></div>
<div class="test secondRow"></div>
</div>
-<div class="grid" style="grid-template-rows: minmax(10px, 40px) minmax(auto, 40px);">
+<div class="grid" style="grid-template-rows: 40px 40px;">
<div class="item">XXXXX</div>
<div class="spanningItem">XXX XX XXX</div>
<div class="test firstRow"></div>
<div class="test secondRow"></div>
</div>
-<div class="grid" style="grid-template-rows: auto minmax(10%, 200px);">
+<div class="grid" style="grid-template-rows: 15px 80px;">
<div class="item secondRow">XXXXX</div>
<div class="spanningItem">XXX XX XXX</div>
<div class="test firstRow"></div>
@@ -139,68 +119,68 @@ div.grid > div { writing-mode: vertical-lr; }
<br clear="all">
<br clear="all">
-<div class="grid" style="grid-template-rows: minmax(auto, 40px) max-content;">
+<div class="grid" style="grid-template-rows: 12.5px 82.5px;">
<div class="spanningItem">XXX XX XXX</div>
<div class="test firstRow"></div>
<div class="test secondRow"></div>
</div>
-<div class="grid" style="grid-template-rows: minmax(auto, 40px) max-content;">
+<div class="grid" style="grid-template-rows: 50px 45px;">
<div class="item">XXXXX</div>
<div class="spanningItem">XXX XX XXX</div>
<div class="test firstRow"></div>
<div class="test secondRow"></div>
</div>
-<div class="grid" style="grid-template-rows: minmax(auto, 40px) max-content;">
+<div class="grid" style="grid-template-rows: 0px 95px;">
<div class="item secondRow">XXXXX</div>
<div class="spanningItem">XXX XX XXX</div>
<div class="test firstRow"></div>
<div class="test secondRow"></div>
</div>
-<div class="grid" style="grid-template-rows: min-content minmax(auto, 40px);">
+<div class="grid" style="grid-template-rows: 12.5px 40px;">
<div class="spanningItem">XXX XX XXX</div>
<div class="test firstRow"></div>
<div class="test secondRow"></div>
</div>
-<div class="grid" style="grid-template-rows: min-content minmax(auto, 40px);">
+<div class="grid" style="grid-template-rows: 50px 40px;">
<div class="item">XXXXX</div>
<div class="spanningItem">XXX XX XXX</div>
<div class="test firstRow"></div>
<div class="test secondRow"></div>
</div>
-<div class="grid" style="grid-template-rows: min-content minmax(auto, 40px);">
+<div class="grid" style="grid-template-rows: 0px 50px;">
<div class="item secondRow">XXXXX</div>
<div class="spanningItem">XXX XX XXX</div>
<div class="test firstRow"></div>
<div class="test secondRow"></div>
</div>
-<div class="grid" style="grid-template-rows: minmax(auto, 30px) min-content max-content">
+<div class="grid" style="grid-template-rows: auto min-content max-content">
<div class="spanningItem">XXX XX XXX</div>
<div class="test firstRow"></div>
<div class="test secondRow"></div>
<div class="test thirdRow"></div>
</div>
-<div class="grid" style="grid-template-rows: min-content minmax(auto, 30px) max-content">
+<div class="grid" style="grid-template-rows: min-content auto max-content">
<div class="spanningItem">XXX XX XXX</div>
<div class="test firstRow"></div>
<div class="test secondRow"></div>
<div class="test thirdRow"></div>
</div>
-<div class="grid" style="grid-template-rows: min-content max-content minmax(auto, 30px)">
+<div class="grid" style="grid-template-rows: min-content max-content auto">
<div class="spanningItem">XXX XX XXX</div>
<div class="test firstRow"></div>
<div class="test secondRow"></div>
<div class="test thirdRow"></div>
</div>
-<div class="grid" style="grid-template-rows: minmax(auto, 30px) min-content max-content">
+<div class="grid" style="grid-template-rows: 30px 0px 60px;">
<div class="item" style="grid-row: 1">XXX XX</div>
<div class="spanningItem">XXX XX XXX</div>
<div class="test firstRow"></div>
@@ -208,7 +188,7 @@ div.grid > div { writing-mode: vertical-lr; }
<div class="test thirdRow"></div>
</div>
-<div class="grid" style="grid-template-rows: min-content minmax(auto, 30px) max-content">
+<div class="grid" style="grid-template-rows: 30px 0px 60px;">
<div class="item" style="grid-row: 1">XXX XX</div>
<div class="spanningItem">XXX XX XXX</div>
<div class="test firstRow"></div>
@@ -216,7 +196,7 @@ div.grid > div { writing-mode: vertical-lr; }
<div class="test thirdRow"></div>
</div>
-<div class="grid" style="grid-template-rows: min-content max-content minmax(auto, 30px)">
+<div class="grid" style="grid-template-rows: 0px 90px 0px;">
<div class="item" style="grid-row: 2">XXX XX</div>
<div class="spanningItem">XXX XX XXX</div>
<div class="test firstRow"></div>
@@ -227,48 +207,48 @@ div.grid > div { writing-mode: vertical-lr; }
<br clear="all">
<br clear="all">
-<div class="grid fc0p">
+<div class="grid" style="grid-template-rows: 30px;">
<div class="item">XXX</div>
<div class="test firstRow"></div>
</div>
-<div class="grid fc0px2">
+<div class="grid" style="grid-template-rows: 30px 0px;">
<div class="item">XXX</div>
<div class="spanningItem">XXX</div>
<div class="test firstRow"></div>
<div class="test secondRow"></div>
</div>
-<div class="grid fc30p">
+<div class="grid" style="grid-template-rows: 30px;">
<div class="item">XX XX</div>
<div class="test firstRow"></div>
</div>
-<div class="grid fc30px2">
+<div class="grid" style="grid-template-rows: 30px 30px;">
<div class="spanningItem">XXX XXX</div>
<div class="test firstRow"></div>
<div class="test secondRow"></div>
</div>
-<div class="grid fc30px2">
+<div class="grid" style="grid-template-rows: 30px 30px;">
<div class="item secondRow">X X X</div>
<div class="spanningItem">XXX XXX</div>
<div class="test firstRow"></div>
<div class="test secondRow"></div>
</div>
-<div class="grid fc90p">
+<div class="grid" style="grid-template-rows: 90px;">
<div class="item">XXX XXX XXX</div>
<div class="test firstRow"></div>
</div>
-<div class="grid fc90px2">
+<div class="grid" style="grid-template-rows: 47.5px 47.5px;">
<div class="spanningItem">XXX XXX XXX</div>
<div class="test firstRow"></div>
<div class="test secondRow"></div>
</div>
-<div class="grid" style="grid-template-rows: auto minmax(auto, 90px)">
+<div class="grid" style="grid-template-rows: 15px 80px;">
<div class="item secondRow">XXX XXX XXX</div>
<div class="spanningItem">XXX XXX XXX</div>
<div class="test firstRow"></div>
@@ -278,45 +258,45 @@ div.grid > div { writing-mode: vertical-lr; }
<br clear="all">
<br clear="all">
-<div class="grid fc110">
+<div class="grid" style="grid-template-rows: 70px;">
<div class="item">XXX XXX</div>
<div class="test firstRow"></div>
</div>
-<div class="grid fc110x2">
+<div class="grid" style="grid-template-rows: 32.5px 32.5px;">
<div class="spanningItem">XXX XXX</div>
<div class="test firstRow"></div>
<div class="test secondRow"></div>
</div>
-<div class="grid fc110x2">
+<div class="grid" style="grid-template-rows: 70px 0px;">
<div class="item">XXX XXX</div>
<div class="spanningItem">XXX XXX</div>
<div class="test firstRow"></div>
<div class="test secondRow"></div>
</div>
-<div class="grid" style="grid-template-rows: auto auto;">
+<div class="grid" style="grid-template-rows: 32.5px 32.5px;">
<div class="spanningItem">XXX XXX</div>
<div class="test firstRow"></div>
<div class="test secondRow"></div>
</div>
-<div class="grid" style="grid-template-rows: auto auto;">
+<div class="grid" style="grid-template-rows: 45px 20px;">
<div class="item secondRow">XX</div>
<div class="spanningItem">XXX XXX</div>
<div class="test firstRow"></div>
<div class="test secondRow"></div>
</div>
-<div class="grid" style="grid-template-rows: max-content auto;">
+<div class="grid" style="grid-template-rows: 92.5px 12.5px;">
<div class="spanningItem" style="grid-column: 1;">XX XX XX XX</div>
<div class="spanningItem">XXX XXX</div>
<div class="test firstRow"></div>
<div class="test secondRow"></div>
</div>
-<div class="grid" style="grid-template-rows: auto min-content;">
+<div class="grid" style="grid-template-rows: 82.5px 12.5px;">
<div class="spanningItem" style="grid-column: 1;">XX XX XX XX</div>
<div class="spanningItem">XXX XXX</div>
<div class="test firstRow"></div>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/grid-items/explicitly-sized-grid-item-as-table.html b/tests/wpt/web-platform-tests/css/css-grid/grid-items/explicitly-sized-grid-item-as-table.html
new file mode 100644
index 00000000000..53a0979622c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/grid-items/explicitly-sized-grid-item-as-table.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<title>CSS Grid Layout Test: Explicitly sized grid item as table with narrow contents</title>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/css-grid-1/#grid-track-concept" title="3.2. Grid Tracks and Cells">
+<meta name="assert" content="A grid item as a table uses the sizing algorithm of the grid">
+<link rel="match" href="../../reference/ref-filled-green-100px-square-only.html">
+<p>Test passes if there is a filled green square.</p>
+<div style="display:grid; grid-template-columns:50% 50%; width:200px;">
+ <div style="display:table; background:green;">
+ <div style="width:10px; height:100px;"></div>
+ </div>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-minimum-size-grid-items-017.html b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-minimum-size-grid-items-017.html
index 6cd2dfb0f8d..4cb74022aaf 100644
--- a/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-minimum-size-grid-items-017.html
+++ b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-minimum-size-grid-items-017.html
@@ -4,11 +4,11 @@
<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
<link rel="help" href="http://www.w3.org/TR/css-grid-1/#min-size-auto" title="6.5. Implied Minimum Size of Grid Items">
<link rel="match" href="../../reference/ref-filled-green-100px-square.xht">
-<meta name="assert" content="Checks that automatic minimum size is not clamped if the track has an 'auto' min track sizing function.">
+<meta name="assert" content="Checks that automatic minimum size is clamped even if the track has an 'auto' min track sizing function as the max track sizing function is fixed.">
<style>
-#reference-overlapped-red {
+#reference-overlapped-green {
position: absolute;
- background-color: red;
+ background-color: green;
width: 100px;
height: 100px;
z-index: -1;
@@ -21,8 +21,8 @@
grid: minmax(auto, 0px) / minmax(auto, 0px);
}
-#test-grid-item-overlapping-green {
- background-color: green;
+#test-grid-item-overlapping-red {
+ background-color: red;
}
#content-100x100 {
@@ -33,9 +33,9 @@
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
-<div id="reference-overlapped-red"></div>
+<div id="reference-overlapped-green"></div>
<div id="constrained-grid">
- <div id="test-grid-item-overlapping-green">
+ <div id="test-grid-item-overlapping-red">
<div id="content-100x100"></div>
</div>
</div>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-minimum-size-grid-items-018.html b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-minimum-size-grid-items-018.html
index df9d50230ee..4e944295abc 100644
--- a/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-minimum-size-grid-items-018.html
+++ b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-minimum-size-grid-items-018.html
@@ -4,7 +4,7 @@
<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
<link rel="help" href="http://www.w3.org/TR/css-grid-1/#min-size-auto" title="6.5. Implied Minimum Size of Grid Items">
<link rel="match" href="../../reference/ref-filled-green-100px-square.xht">
-<meta name="assert" content="Checks that automatic minimum size is not clamped if the track has an 'auto' min track sizing function.">
+<meta name="assert" content="Checks that automatic minimum size is clamped even if the track has an 'auto' min track sizing function as the max track sizing function is fixed.">
<style>
#reference-overlapped-red {
position: absolute;
diff --git a/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-minimum-size-grid-items-022.html b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-minimum-size-grid-items-022.html
new file mode 100644
index 00000000000..66417a4cd78
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-minimum-size-grid-items-022.html
@@ -0,0 +1,137 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Minimum size of grid items</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="http://www.w3.org/TR/css-grid-1/#min-size-auto" title="6.5. Implied Minimum Size of Grid Items">
+<meta name="assert" content="Checks that automatic minimum size is clamped with different column sizes.">
+<link rel="stylesheet" href="../support/grid.css">
+<style>
+.grid {
+ border: solid thick;
+ font: 10px/1 Ahem;
+ width: 50px;
+ height: 50px;
+ grid-template-rows: 25px 25px;
+}
+
+.grid > div:nth-child(1) {
+ color: blue;
+ background: cyan;
+}
+
+.grid > div:nth-child(2) {
+ background: magenta;
+}
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+
+<body onload="checkLayout('.grid')">
+
+<div id="log"></div>
+
+<pre>grid-template-columns: auto;</pre>
+
+<div class="grid" style="grid-template-columns: auto;">
+ <div data-expected-width="100">XXXXXXXXXX</div>
+ <div data-expected-width="100"></div>
+</div>
+
+<pre>grid-template-columns: 0px;</pre>
+
+<div class="grid" style="grid-template-columns: 0px;">
+ <div data-expected-width="0">XXXXXXXXXX</div>
+ <div data-expected-width="0"></div>
+</div>
+
+<pre>grid-template-columns: 25px;</pre>
+
+<div class="grid" style="grid-template-columns: 25px;">
+ <div data-expected-width="25">XXXXXXXXXX</div>
+ <div data-expected-width="25"></div>
+</div>
+
+<pre>grid-template-columns: minmax(auto, 0px);</pre>
+
+<div class="grid" style="grid-template-columns: minmax(auto, 0px);">
+ <div data-expected-width="0">XXXXXXXXXX</div>
+ <div data-expected-width="0"></div>
+</div>
+
+<pre>grid-template-columns: minmax(auto, 25px);</pre>
+
+<div class="grid" style="grid-template-columns: minmax(auto, 25px);">
+ <div data-expected-width="25">XXXXXXXXXX</div>
+ <div data-expected-width="25"></div>
+</div>
+
+<pre>grid-template-columns: minmax(auto, 0px); item width: 10px;</pre>
+
+<div class="grid" style="grid-template-columns: minmax(auto, 0px);">
+ <div data-expected-width="10" style="width: 10px;">XXXXXXXXXX</div>
+ <div data-expected-width="10"></div>
+</div>
+
+<pre>grid-template-columns: minmax(auto, 25px); item width: 10px;</pre>
+
+<div class="grid" style="grid-template-columns: minmax(auto, 25px);">
+ <div data-expected-width="10" style="width: 10px;">XXXXXXXXXX</div>
+ <div data-expected-width="25"></div>
+</div>
+
+<pre>grid-template-columns: minmax(auto, 0px); item margin width: 10px;</pre>
+
+<div class="grid" style="grid-template-columns: minmax(auto, 0px);">
+ <div data-expected-width="0" style="margin: 0px 5px;"></div>
+ <div data-expected-width="10"></div>
+</div>
+
+<pre>grid-template-columns: minmax(auto, 25px); item margin width: 10px;</pre>
+
+<div class="grid" style="grid-template-columns: minmax(auto, 25px);">
+ <div data-expected-width="15" style="margin: 0px 5px;"></div>
+ <div data-expected-width="25"></div>
+</div>
+
+<pre>grid-template-columns: minmax(auto, 0px); item padding width: 10px;</pre>
+
+<div class="grid" style="grid-template-columns: minmax(auto, 0px);">
+ <div data-expected-width="10" style="padding: 0px 5px;"></div>
+ <div data-expected-width="10"></div>
+</div>
+
+<pre>grid-template-columns: minmax(auto, 25px); item padding width: 10px;</pre>
+
+<div class="grid" style="grid-template-columns: minmax(auto, 25px);">
+ <div data-expected-width="25" style="padding: 0px 5px;"></div>
+ <div data-expected-width="25"></div>
+</div>
+
+<pre>grid-template-columns: minmax(auto, 0px); item border width: 10px;</pre>
+
+<div class="grid" style="grid-template-columns: minmax(auto, 0px);">
+ <div data-expected-width="10" style="border: solid 5px blue;"></div>
+ <div data-expected-width="10"></div>
+</div>
+
+<pre>grid-template-columns: minmax(auto, 25px); item border width: 10px;</pre>
+
+<div class="grid" style="grid-template-columns: minmax(auto, 25px);">
+ <div data-expected-width="25" style="border: solid 5px blue;"></div>
+ <div data-expected-width="25"></div>
+</div>
+
+<pre>grid-template-columns: minmax(auto, 0px); item width + margin + border + padding: 10px;</pre>
+
+<div class="grid" style="grid-template-columns: minmax(auto, 0px);">
+ <div data-expected-width="8" style="width: 4px; margin: 1px; padding: 1px; border: solid 1px blue;"></div>
+ <div data-expected-width="10"></div>
+</div>
+
+<pre>grid-template-columns: minmax(auto, 25px); item width + margin + border + padding: 10px;</pre>
+
+<div class="grid" style="grid-template-columns: minmax(auto, 25px);">
+ <div data-expected-width="8" style="width: 4px; margin: 1px; padding: 1px; border: solid 1px blue;"></div>
+ <div data-expected-width="25"></div>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-minimum-size-grid-items-023.html b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-minimum-size-grid-items-023.html
new file mode 100644
index 00000000000..d821e5c735c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/grid-items/grid-minimum-size-grid-items-023.html
@@ -0,0 +1,248 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: Minimum size of grid items</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="http://www.w3.org/TR/css-grid-1/#min-size-auto" title="6.5. Implied Minimum Size of Grid Items">
+<meta name="assert" content="Checks that automatic minimum size is clamped with different row sizes.">
+<link rel="stylesheet" href="../support/grid.css">
+<style>
+.grid {
+ border: solid thick;
+ font: 10px/1 Ahem;
+ width: 50px;
+ height: 50px;
+ grid-template-columns: 25px 25px;
+ margin: 50px 0px;
+}
+
+.grid > div:nth-child(1) {
+ color: blue;
+ background: cyan;
+}
+
+.grid > div:nth-child(2) {
+ background: magenta;
+}
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+
+<body onload="checkLayout('.grid')">
+
+<div id="log"></div>
+
+<h3>writing-mode: vertical-lr;</h3>
+
+<pre>grid-template-rows: auto;</pre>
+
+<div class="grid" style="grid-template-rows: auto;">
+ <div class="verticalLR" data-expected-height="100">XXXXXXXXXX</div>
+ <div data-expected-height="100"></div>
+</div>
+
+<pre>grid-template-rows: 0px;</pre>
+
+<div class="grid" style="grid-template-rows: 0px;">
+ <div class="verticalLR" data-expected-height="0">XXXXXXXXXX</div>
+ <div data-expected-height="0"></div>
+</div>
+
+<pre>grid-template-rows: 25px;</pre>
+
+<div class="grid" style="grid-template-rows: 25px;">
+ <div class="verticalLR" data-expected-height="25">XXXXXXXXXX</div>
+ <div data-expected-height="25"></div>
+</div>
+
+<pre>grid-template-rows: minmax(auto, 0px);</pre>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 0px);">
+ <div class="verticalLR" data-expected-height="0">XXXXXXXXXX</div>
+ <div data-expected-height="0"></div>
+</div>
+
+<pre>grid-template-rows: minmax(auto, 25px);</pre>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 25px);">
+ <div class="verticalLR" data-expected-height="25">XXXXXXXXXX</div>
+ <div data-expected-height="25"></div>
+</div>
+
+<pre>grid-template-rows: minmax(auto, 0px); item height: 10px;</pre>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 0px);">
+ <div class="verticalLR" data-expected-height="10" style="height: 10px;">XXXXXXXXXX</div>
+ <div data-expected-height="10"></div>
+</div>
+
+<pre>grid-template-rows: minmax(auto, 25px); item height: 10px;</pre>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 25px);">
+ <div class="verticalLR" data-expected-height="10" style="height: 10px;">XXXXXXXXXX</div>
+ <div data-expected-height="25"></div>
+</div>
+
+<pre>grid-template-rows: minmax(auto, 0px); item margin height: 10px;</pre>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 0px);">
+ <div class="verticalLR" data-expected-height="0" style="margin: 5px 0px;"></div>
+ <div data-expected-height="10"></div>
+</div>
+
+<pre>grid-template-rows: minmax(auto, 25px); item margin height: 10px;</pre>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 25px);">
+ <div class="verticalLR" data-expected-height="15" style="margin: 5px 0px;"></div>
+ <div data-expected-height="25"></div>
+</div>
+
+<pre>grid-template-rows: minmax(auto, 0px); item padding height: 10px;</pre>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 0px);">
+ <div class="verticalLR" data-expected-height="10" style="padding: 5px 0px;"></div>
+ <div data-expected-height="10"></div>
+</div>
+
+<pre>grid-template-rows: minmax(auto, 25px); item padding height: 10px;</pre>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 25px);">
+ <div class="verticalLR" data-expected-height="25" style="padding: 5px 0px;"></div>
+ <div data-expected-height="25"></div>
+</div>
+
+<pre>grid-template-rows: minmax(auto, 0px); item border height: 10px;</pre>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 0px);">
+ <div class="verticalLR" data-expected-height="10" style="border: solid 5px blue;"></div>
+ <div data-expected-height="10"></div>
+</div>
+
+<pre>grid-template-rows: minmax(auto, 25px); item border height: 10px;</pre>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 25px);">
+ <div class="verticalLR" data-expected-height="25" style="border: solid 5px blue;"></div>
+ <div data-expected-height="25"></div>
+</div>
+
+<pre>grid-template-rows: minmax(auto, 0px); item height + margin + border + padding: 10px;</pre>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 0px);">
+ <div class="verticalLR" data-expected-height="8" style="height: 4px; margin: 1px; padding: 1px; border: solid 1px blue;"></div>
+ <div data-expected-height="10"></div>
+</div>
+
+<pre>grid-template-rows: minmax(auto, 25px); item height + margin + border + padding: 10px;</pre>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 25px);">
+ <div class="verticalLR" data-expected-height="8" style="height: 4px; margin: 1px; padding: 1px; border: solid 1px blue;"></div>
+ <div data-expected-height="25"></div>
+</div>
+
+<h3>writing-mode: vertical-rl;</h3>
+
+<pre>grid-template-rows: auto;</pre>
+
+<div class="grid" style="grid-template-rows: auto;">
+ <div class="verticalRL" data-expected-height="100">XXXXXXXXXX</div>
+ <div data-expected-height="100"></div>
+</div>
+
+<pre>grid-template-rows: 0px;</pre>
+
+<div class="grid" style="grid-template-rows: 0px;">
+ <div class="verticalRL" data-expected-height="0">XXXXXXXXXX</div>
+ <div data-expected-height="0"></div>
+</div>
+
+<pre>grid-template-rows: 25px;</pre>
+
+<div class="grid" style="grid-template-rows: 25px;">
+ <div class="verticalRL" data-expected-height="25">XXXXXXXXXX</div>
+ <div data-expected-height="25"></div>
+</div>
+
+<pre>grid-template-rows: minmax(auto, 0px);</pre>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 0px);">
+ <div class="verticalRL" data-expected-height="0">XXXXXXXXXX</div>
+ <div data-expected-height="0"></div>
+</div>
+
+<pre>grid-template-rows: minmax(auto, 25px);</pre>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 25px);">
+ <div class="verticalRL" data-expected-height="25">XXXXXXXXXX</div>
+ <div data-expected-height="25"></div>
+</div>
+
+<pre>grid-template-rows: minmax(auto, 0px); item height: 10px;</pre>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 0px);">
+ <div class="verticalRL" data-expected-height="10" style="height: 10px;">XXXXXXXXXX</div>
+ <div data-expected-height="10"></div>
+</div>
+
+<pre>grid-template-rows: minmax(auto, 25px); item height: 10px;</pre>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 25px);">
+ <div class="verticalRL" data-expected-height="10" style="height: 10px;">XXXXXXXXXX</div>
+ <div data-expected-height="25"></div>
+</div>
+
+<pre>grid-template-rows: minmax(auto, 0px); item margin height: 10px;</pre>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 0px);">
+ <div class="verticalRL" data-expected-height="0" style="margin: 5px 0px;"></div>
+ <div data-expected-height="10"></div>
+</div>
+
+<pre>grid-template-rows: minmax(auto, 25px); item margin height: 10px;</pre>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 25px);">
+ <div class="verticalRL" data-expected-height="15" style="margin: 5px 0px;"></div>
+ <div data-expected-height="25"></div>
+</div>
+
+<pre>grid-template-rows: minmax(auto, 0px); item padding height: 10px;</pre>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 0px);">
+ <div class="verticalRL" data-expected-height="10" style="padding: 5px 0px;"></div>
+ <div data-expected-height="10"></div>
+</div>
+
+<pre>grid-template-rows: minmax(auto, 25px); item padding height: 10px;</pre>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 25px);">
+ <div class="verticalRL" data-expected-height="25" style="padding: 5px 0px;"></div>
+ <div data-expected-height="25"></div>
+</div>
+
+<pre>grid-template-rows: minmax(auto, 0px); item border height: 10px;</pre>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 0px);">
+ <div class="verticalRL" data-expected-height="10" style="border: solid 5px blue;"></div>
+ <div data-expected-height="10"></div>
+</div>
+
+<pre>grid-template-rows: minmax(auto, 25px); item border height: 10px;</pre>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 25px);">
+ <div class="verticalRL" data-expected-height="25" style="border: solid 5px blue;"></div>
+ <div data-expected-height="25"></div>
+</div>
+
+<pre>grid-template-rows: minmax(auto, 0px); item height + margin + border + padding: 10px;</pre>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 0px);">
+ <div class="verticalRL" data-expected-height="8" style="height: 4px; margin: 1px; padding: 1px; border: solid 1px blue;"></div>
+ <div data-expected-height="10"></div>
+</div>
+
+<pre>grid-template-rows: minmax(auto, 25px); item height + margin + border + padding: 10px;</pre>
+
+<div class="grid" style="grid-template-rows: minmax(auto, 25px);">
+ <div class="verticalRL" data-expected-height="8" style="height: 4px; margin: 1px; padding: 1px; border: solid 1px blue;"></div>
+ <div data-expected-height="25"></div>
+</div>
+
diff --git a/tests/wpt/web-platform-tests/css/css-grid/grid-layout-properties.html b/tests/wpt/web-platform-tests/css/css-grid/grid-layout-properties.html
index 2e66fb21539..249c4a738f7 100644
--- a/tests/wpt/web-platform-tests/css/css-grid/grid-layout-properties.html
+++ b/tests/wpt/web-platform-tests/css/css-grid/grid-layout-properties.html
@@ -54,7 +54,7 @@
Object.keys(data).forEach(function(prop){
test(function(){
- assert_own_property(myDiv.style, prop)
+ assert_true(prop in myDiv.style)
}, prop)
if ('initial' in data[prop]) test(function(){
@@ -66,7 +66,7 @@
var syntaxTests = data[prop]
Object.keys(syntaxTests).forEach(function(testcase){
test(function(){
- assert_own_property(myDiv.style, prop)
+ assert_true(prop in myDiv.style)
myDiv.style[prop] = syntaxTests[testcase][0]
assert_equals(myDiv.style[prop], syntaxTests[testcase][0], testcase)
assert_equals(getComputedStyle(myDiv)[prop], syntaxTests[testcase][1], testcase)
diff --git a/tests/wpt/web-platform-tests/css/css-grid/grid-model/grid-container-ignores-first-letter-001.html b/tests/wpt/web-platform-tests/css/css-grid/grid-model/grid-container-ignores-first-letter-001.html
new file mode 100644
index 00000000000..f94fdcfe965
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/grid-model/grid-container-ignores-first-letter-001.html
@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: '::first-letter' is ignored in grid containers</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="http://www.w3.org/TR/css-grid-1/#grid-containers">
+<link rel="help" href="http://www.w3.org/TR/css3-selectors/#first-letter">
+<meta name="assert" content="The test checks that grid item should ignore grid container's first-letter pseudo-element.">
+<link href="../support/grid.css" rel="stylesheet">
+<style>
+ body { line-height: 20px; }
+ .grid-first-letter::first-letter { line-height: 100px; color: red; }
+ .container-first-letter::first-letter { line-height: 200px; color: green; }
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+
+<body onload="checkLayout('.container');">
+
+<div id="log"></div>
+
+<div class="container">
+ <div class="grid grid-first-letter">
+ <div class="item" data-expected-height=20>The first item.</div>
+ <div class="item" data-expected-height=20>The second item.</div>
+ </div>
+</div>
+
+<div class="container">
+ <div class="inline-grid grid-first-letter">
+ <div class="item" data-expected-height=20>The first item.</div>
+ <div class="item" data-expected-height=20>The second item.</div>
+ </div>
+</div>
+
+<div class="container">
+ <div class="grid grid-first-letter" data-expected-height=20>
+ Anonymous item.
+ </div>
+</div>
+
+<div class="container">
+ <div class="inline-grid grid-first-letter" data-expected-height=20>
+ Anonymous item.
+ </div>
+</div>
+
+<div class="container container-first-letter">
+ <div class="grid grid-first-letter">
+ <div class="item" data-expected-height=20>The first item.</div>
+ <div class="item" data-expected-height=20>The second item.</div>
+ </div>
+ <div data-expected-height=200>Out of grid.</div>
+</div>
+
+<div class="container container-first-letter">
+ <div class="inline-grid grid-first-letter">
+ <div class="item" data-expected-height=20>The first item.</div>
+ <div class="item" data-expected-height=20>The second item.</div>
+ </div>
+ <div data-expected-height=20>Out of grid.</div>
+</div>
+
+<div class="container container-first-letter">
+ <div class="grid grid-first-letter" data-expected-height=20>
+ Anonymous item.
+ </div>
+ <div data-expected-height=200>Out of grid.</div>
+</div>
+
+<div class="container container-first-letter">
+ <div class="inline-grid grid-first-letter" data-expected-height=20>
+ Anonymous item.
+ </div>
+ <div data-expected-height=20>Out of grid.</div>
+</div>
+
+<div class="container container-first-letter">
+ <div class="grid">
+ <div class="item" data-expected-height=20>The first item.</div>
+ <div class="item" data-expected-height=20>The second item.</div>
+ </div>
+ <div data-expected-height=200>Out of grid.</div>
+</div>
+
+<div class="container container-first-letter">
+ <div class="inline-grid">
+ <div class="item" data-expected-height=20>The first item.</div>
+ <div class="item" data-expected-height=20>The second item.</div>
+ </div>
+ <div data-expected-height=20>Out of grid.</div>
+</div>
+
+<div class="container container-first-letter">
+ <div class="grid" data-expected-height=20>
+ Anonymous item.
+ </div>
+ <div data-expected-height=200>Out of grid.</div>
+</div>
+
+<div class="container container-first-letter">
+ <div class="inline-grid" data-expected-height=20>
+ Anonymous item.
+ </div>
+ <div data-expected-height=20>Out of grid.</div>
+</div>
+
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/grid-model/grid-container-ignores-first-line-001.html b/tests/wpt/web-platform-tests/css/css-grid/grid-model/grid-container-ignores-first-line-001.html
new file mode 100644
index 00000000000..b491298f3ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/grid-model/grid-container-ignores-first-line-001.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: '::first-line' is ignored in grid containers</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="http://www.w3.org/TR/css-grid-1/#grid-containers">
+<link rel="help" href="http://www.w3.org/TR/css3-selectors/#first-formatted-line">
+<meta name="assert" content="The test checks that grid item should ignore grid container's first-line pseudo-element.">
+<link href="../support/grid.css" rel="stylesheet">
+<style>
+ body { line-height: 20px; }
+ .grid-first-line::first-line { line-height: 100px; }
+ .container::first-line { line-height: 200px; }
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+
+<body onload="checkLayout('.grid,.inline-grid');">
+
+<div id="log"></div>
+
+<div class="grid grid-first-line">
+ <div class="item" data-expected-height=20>The first item.</div>
+ <div class="item" data-expected-height=20>The second item.</div>
+</div>
+
+<div class="inline-grid grid-first-line">
+ <div class="item" data-expected-height=20>The first item.</div>
+ <div class="item" data-expected-height=20>The second item.</div>
+</div>
+
+<div class="grid grid-first-line" data-expected-height=20>
+ Anonymous item.
+</div>
+
+<div class="inline-grid grid-first-line" data-expected-height=20>
+ Anonymous item.
+</div>
+
+<div class="container">
+ <div class="grid grid-first-line">
+ <div class="item" data-expected-height=20>The first item.</div>
+ <div class="item" data-expected-height=20>The second item.</div>
+ </div>
+</div>
+
+<div class="container">
+ <div class="inline-grid grid-first-line">
+ <div class="item" data-expected-height=20>The first item.</div>
+ <div class="item" data-expected-height=20>The second item.</div>
+ </div>
+</div>
+
+<div class="container">
+ <div class="grid grid-first-line" data-expected-height=20>
+ Anonymous item.
+ </div>
+</div>
+
+<div class="container">
+ <div class="inline-grid grid-first-line" data-expected-height=20>
+ Anonymous item.
+ </div>
+</div>
+
+<div class="container">
+ <div class="grid">
+ <div class="item" data-expected-height=20>The first item.</div>
+ <div class="item" data-expected-height=20>The second item.</div>
+ </div>
+</div>
+
+<div class="container">
+ <div class="inline-grid">
+ <div class="item" data-expected-height=20>The first item.</div>
+ <div class="item" data-expected-height=20>The second item.</div>
+ </div>
+</div>
+
+<div class="container">
+ <div class="grid" data-expected-height=20>
+ Anonymous item.
+ </div>
+</div>
+
+<div class="container">
+ <div class="inline-grid" data-expected-height=20>
+ Anonymous item.
+ </div>
+</div>
+
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/grid-model/grid-item-accepts-first-letter-001.html b/tests/wpt/web-platform-tests/css/css-grid/grid-model/grid-item-accepts-first-letter-001.html
new file mode 100644
index 00000000000..c9454fe30e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/grid-model/grid-item-accepts-first-letter-001.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: '::first-letter' is valid in grid items</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="http://www.w3.org/TR/css-grid-1/#grid-containers">
+<link rel="help" href="http://www.w3.org/TR/css3-selectors/#first-letter">
+<meta name="assert" content="The test checks that grid items accept first-letter pseudo-element.">
+<link href="../support/grid.css" rel="stylesheet">
+<style>
+ .item::first-letter { line-height: 100px; }
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+
+<body onload="checkLayout('.grid,.inline-grid');">
+
+<div id="log"></div>
+
+<div class="grid">
+ <div class="item" data-expected-height=100>The first item.</div>
+ <div class="item" data-expected-height=100>The second item.</div>
+</div>
+
+<div class="inline-grid">
+ <div class="item" data-expected-height=100>The first item.</div>
+ <div class="item" data-expected-height=100>The second item.</div>
+</div>
+
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/grid-model/grid-item-accepts-first-line-001.html b/tests/wpt/web-platform-tests/css/css-grid/grid-model/grid-item-accepts-first-line-001.html
new file mode 100644
index 00000000000..1330b376318
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-grid/grid-model/grid-item-accepts-first-line-001.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: '::first-line' is valid in grid items</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="http://www.w3.org/TR/css-grid-1/#grid-containers">
+<link rel="help" href="http://www.w3.org/TR/css3-selectors/#first-formatted-line">
+<meta name="assert" content="The test checks that grid items accept first-line pseudo-element.">
+<link href="../support/grid.css" rel="stylesheet">
+<style>
+ .item::first-line { line-height: 100px; }
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+
+<body onload="checkLayout('.grid,.inline-grid');">
+
+<div id="log"></div>
+
+<div class="grid">
+ <div class="item" data-expected-height=100>The first item.</div>
+ <div class="item" data-expected-height=100>The second item.</div>
+</div>
+
+<div class="inline-grid">
+ <div class="item" data-expected-height=100>The first item.</div>
+ <div class="item" data-expected-height=100>The second item.</div>
+</div>
+
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/reference/grid-collapsed-row-gutters-ref.html b/tests/wpt/web-platform-tests/css/css-grid/reference/grid-collapsed-row-gutters-ref.html
index 7d33e57eaff..a0ff682c6a5 100644
--- a/tests/wpt/web-platform-tests/css/css-grid/reference/grid-collapsed-row-gutters-ref.html
+++ b/tests/wpt/web-platform-tests/css/css-grid/reference/grid-collapsed-row-gutters-ref.html
@@ -38,6 +38,7 @@
}
</style>
+<p>The test passes if it has the same visual effect as reference. Column gap should be percentage of width. Row gap should resolve to auto, and therefore collapse to 0 height.</p>
<div id="grid">
<div></div>
<div></div>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/reference/grid-different-gutters-ref.html b/tests/wpt/web-platform-tests/css/css-grid/reference/grid-different-gutters-ref.html
index 52ee9e0676e..57d27ff3aae 100644
--- a/tests/wpt/web-platform-tests/css/css-grid/reference/grid-different-gutters-ref.html
+++ b/tests/wpt/web-platform-tests/css/css-grid/reference/grid-different-gutters-ref.html
@@ -38,6 +38,7 @@
}
</style>
+<p>The test passes if it has the same visual effect as reference.</p>
<div id="grid">
<div></div>
<div></div>
diff --git a/tests/wpt/web-platform-tests/css/css-grid/reference/grid-equal-gutters-ref.html b/tests/wpt/web-platform-tests/css/css-grid/reference/grid-equal-gutters-ref.html
index 3d9952679b1..caea89a8be0 100644
--- a/tests/wpt/web-platform-tests/css/css-grid/reference/grid-equal-gutters-ref.html
+++ b/tests/wpt/web-platform-tests/css/css-grid/reference/grid-equal-gutters-ref.html
@@ -38,6 +38,7 @@
}
</style>
+<p>The test passes if it has the same visual effect as reference.</p>
<div id="grid">
<div></div>
<div></div>
diff --git a/tests/wpt/web-platform-tests/css/css-lists/counter-7-ref.html b/tests/wpt/web-platform-tests/css/css-lists/counter-7-ref.html
new file mode 100644
index 00000000000..3d1b67228fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-lists/counter-7-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Test Reference</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<p>You should see the number 7 below.</p>
+<div>7</div>
diff --git a/tests/wpt/web-platform-tests/css/css-lists/counter-increment-inside-display-contents.html b/tests/wpt/web-platform-tests/css/css-lists/counter-increment-inside-display-contents.html
new file mode 100644
index 00000000000..ebfe1774da6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-lists/counter-increment-inside-display-contents.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Lists: counter-increment on child of display:contents</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-lists/#counters-without-boxes">
+<link rel="match" href="counter-7-ref.html">
+<style>
+ .inc { counter-increment: x }
+ .reset-6 { counter-reset: x 6 }
+ .contents { display: contents }
+ .result::before { content: counter(x) }
+</style>
+<p>You should see the number 7 below.</p>
+<div>
+ <span class="reset-6"></span>
+ <span class="contents">
+ <span class="inc"></span>
+ </span>
+ <span class="result"></span>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-lists/counter-reset-increment-display-contents.html b/tests/wpt/web-platform-tests/css/css-lists/counter-reset-increment-display-contents.html
new file mode 100644
index 00000000000..a59576b2534
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-lists/counter-reset-increment-display-contents.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Lists: counter-reset and counter-increment on display:contents</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-lists/#counters-without-boxes">
+<link rel="match" href="counter-7-ref.html">
+<style>
+ .inc { counter-increment: x }
+ .reset-6 { counter-reset: x 6 }
+ .reset-666 { counter-reset: x 666 }
+ .contents { display: contents }
+ .result::before { content: counter(x) }
+</style>
+<p>You should see the number 7 below.</p>
+<div>
+ <span class="reset-6"></span>
+ <span class="contents reset-666 inc"></span>
+ <span class="inc result"></span>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-lists/counter-reset-increment-display-none.html b/tests/wpt/web-platform-tests/css/css-lists/counter-reset-increment-display-none.html
new file mode 100644
index 00000000000..3b344a751c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-lists/counter-reset-increment-display-none.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Lists: counter-reset and counter-increment on display:none</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-lists/#counters-without-boxes">
+<link rel="match" href="counter-7-ref.html">
+<style>
+ .inc { counter-increment: x }
+ .reset-6 { counter-reset: x 6 }
+ .reset-666 { counter-reset: x 666 }
+ .none { display: none }
+ .result::before { content: counter(x) }
+</style>
+<p>You should see the number 7 below.</p>
+<div>
+ <span class="reset-6"></span>
+ <span class="none reset-666 inc"></span>
+ <span class="inc result"></span>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-lists/counter-reset-inside-display-contents.html b/tests/wpt/web-platform-tests/css/css-lists/counter-reset-inside-display-contents.html
new file mode 100644
index 00000000000..85c137e675e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-lists/counter-reset-inside-display-contents.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Lists: counter-reset on child of display:contents</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-lists/#counters-without-boxes">
+<link rel="match" href="counter-7-ref.html">
+<style>
+ .inc { counter-increment: x }
+ .reset-6 { counter-reset: x 6 }
+ .reset-666 { counter-reset: x 6 }
+ .contents { display: contents }
+ .result::before { content: counter(x) }
+</style>
+<p>You should see the number 7 below.</p>
+<div>
+ <span class="reset-6"></span>
+ <span class="contents">
+ <span class="reset-666"></span>
+ </span>
+ <span class="inc result"></span>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-masking/clip/clip-rect-auto-001.html b/tests/wpt/web-platform-tests/css/css-masking/clip/clip-rect-auto-001.html
index 36cc49d7f3a..6a1a064059b 100644
--- a/tests/wpt/web-platform-tests/css/css-masking/clip/clip-rect-auto-001.html
+++ b/tests/wpt/web-platform-tests/css/css-masking/clip/clip-rect-auto-001.html
@@ -12,7 +12,7 @@
in the bottom right corner of the blue square.">
</head>
<body>
- <p>The test passes if there is a blue square and a smaller green square in the bottom right corner of the blue square .</p>
+ <p>The test passes if there is a blue square and a smaller green square in the bottom right corner of the blue square.</p>
<div style="position: absolute; clip: rect(auto, auto, auto, auto); width: 100px; height: 100px;">
<div style="width: 100px; height: 100px; border: solid blue 50px; background-color: green;"></div>
</div>
diff --git a/tests/wpt/web-platform-tests/css/css-masking/clip/clip-rect-comma-002.html b/tests/wpt/web-platform-tests/css/css-masking/clip/clip-rect-comma-002.html
index abe56bbfa47..aad2aebe673 100644
--- a/tests/wpt/web-platform-tests/css/css-masking/clip/clip-rect-comma-002.html
+++ b/tests/wpt/web-platform-tests/css/css-masking/clip/clip-rect-comma-002.html
@@ -12,6 +12,6 @@
</head>
<body>
<p>The test passes if there is a green square with a blue border.</p>
- <div style="width: 100px; height: 100px; border: solid red 50px; background-color: green; position: absolute; clip: rect(50px 150px, 150px, 50px);"></div>
+ <div style="width: 100px; height: 100px; border: solid blue 50px; background-color: green; position: absolute; clip: rect(50px 150px, 150px, 50px);"></div>
</body>
</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/css-masking/clip/reference/clip-horizontal-stripe-ref.html b/tests/wpt/web-platform-tests/css/css-masking/clip/reference/clip-horizontal-stripe-ref.html
index d90a5ec785d..fccb18318d2 100644
--- a/tests/wpt/web-platform-tests/css/css-masking/clip/reference/clip-horizontal-stripe-ref.html
+++ b/tests/wpt/web-platform-tests/css/css-masking/clip/reference/clip-horizontal-stripe-ref.html
@@ -5,7 +5,7 @@
<link rel="author" title="Dirk Schulze" href="mailto:dschulze@adobe.com">
</head>
<body>
- <p>The test passes if there is only a vertical blue stripe.</p>
+ <p>The test passes if there is only a horizontal blue stripe.</p>
<div style="width: 200px; height: 50px; background-color: blue;"></div>
</body>
</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/OWNERS b/tests/wpt/web-platform-tests/css/css-multicol/OWNERS
index 1048ba69fda..3247ab2dea0 100644
--- a/tests/wpt/web-platform-tests/css/css-multicol/OWNERS
+++ b/tests/wpt/web-platform-tests/css/css-multicol/OWNERS
@@ -1,2 +1,3 @@
@frivoal
+@mstensho
@rachelandrew
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-br-inside-avoidcolumn-001.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-br-inside-avoidcolumn-001.xht
index 419a88bded6..d3f2c9ec5da 100644
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-br-inside-avoidcolumn-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-br-inside-avoidcolumn-001.xht
@@ -5,47 +5,33 @@
<title>multicol | break-inside: avoid-column</title>
<link rel="author" title="Opera Software ASA" href="http://www.opera.com/"/>
<link rel="help" href="http://www.w3.org/TR/css3-multicol/#column-breaks"/>
-<link rel="match" href="multicol-br-inside-avoidcolumn-ref.xht"/>
+<link rel="match" href="../reference/ref-filled-green-200px-square.html"/>
<meta name="flags" content=""/>
<style type="text/css"><![CDATA[
-html {
- width: 800px;
- background: white;
+.multicol {
+ column-count: 2;
+ column-gap: 0;
+ column-fill: auto;
+ overflow: hidden;
+ width: 200px;
+ height: 300px;
}
-body {
- background: black;
- column-count: 3;
- column-gap: 0;
- column-fill: auto;
- height: 300px;
+.multicol > div {
+ height: 200px;
+ break-inside: avoid-column;
+ background: green;
}
-h1 {
- column-span: all;
- color: white;
-}
-div { background: red;
- height: 150px;
- break-inside: avoid-column;
-}
-span {
- float: left;
+.multicol > div.red {
+ background:red;
}
]]></style>
</head>
<body>
-<h1>You should not see the word FAIL</h1>
-
-<div>
- <span>FAIL</span>
-</div>
-
-<div>
- <span>FAIL</span>
-</div>
-
-<div>
- <span>FAIL</span>
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div class="multicol">
+ <div></div>
+ <div></div>
+ <div class="red"></div>
</div>
-
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-br-inside-avoidcolumn-ref.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-br-inside-avoidcolumn-ref.xht
deleted file mode 100644
index fc465568215..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-br-inside-avoidcolumn-ref.xht
+++ /dev/null
@@ -1,30 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>multicol | break-inside: avoid-column</title>
-<link rel="author" title="Opera Software ASA" href="http://www.opera.com/"/>
-<style type="text/css"><![CDATA[
-html {
- width: 800px;
- background: white;
-}
-h1 {
- color: white;
- margin-top: 0;
- padding-top: 0.66em;
-}
-div {
- height: 450px;
- background: black;
- height: 300px;
-}
-]]></style>
-</head>
-<body>
-<div>
- <h1>You should not see the word FAIL</h1>
-</div>
-
-</body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-break-001-ref.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-break-001-ref.xht
index b363c2bffeb..f7535180965 100644
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-break-001-ref.xht
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-break-001-ref.xht
@@ -21,9 +21,9 @@
<p>Test passes if the 2 horizontal bars are <strong>identical</strong>.</p>
- <div>&nbsp; <img src="support/black20x20.png" alt="Image download support must be enabled" /> <img src="support/black20x20.png" alt="Image download support must be enabled" /> <img src="support/black20x20.png" alt="Image download support must be enabled" /></div>
+ <div><img src="support/black20x20.png" alt="Image download support must be enabled" /> <img src="support/black20x20.png" alt="Image download support must be enabled" /> <img src="support/black20x20.png" alt="Image download support must be enabled" /></div>
- <div>&nbsp; <img src="support/black20x20.png" alt="Image download support must be enabled" /> <img src="support/black20x20.png" alt="Image download support must be enabled" /> <img src="support/black20x20.png" alt="Image download support must be enabled" /></div>
+ <div><img src="support/black20x20.png" alt="Image download support must be enabled" /> <img src="support/black20x20.png" alt="Image download support must be enabled" /> <img src="support/black20x20.png" alt="Image download support must be enabled" /></div>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-break-001.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-break-001.xht
index 8c3f6a785ca..a03667411ac 100644
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-break-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-break-001.xht
@@ -47,7 +47,7 @@
<div>C</div>
</div>
- <div id="reference">&nbsp; <img src="support/black20x20.png" alt="Image download support must be enabled" /> <img src="support/black20x20.png" alt="Image download support must be enabled" /> <img src="support/black20x20.png" alt="Image download support must be enabled" /></div>
+ <div id="reference"><img src="support/black20x20.png" alt="Image download support must be enabled" /> <img src="support/black20x20.png" alt="Image download support must be enabled" /> <img src="support/black20x20.png" alt="Image download support must be enabled" /></div>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-count-computed-001.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-count-computed-001.xht
deleted file mode 100644
index 3c9ea3a36b8..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-count-computed-001.xht
+++ /dev/null
@@ -1,50 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>multicolumn | column-rule</title>
-<link rel="author" title="Opera Software ASA" href="http://www.opera.com/"/>
-<link rel="help" href="http://www.w3.org/TR/css3-multicol/#the-number-and-width-of-columns"/>
-<link rel="help" href="http://www.w3.org/TR/css3-multicol/#column-gaps-and-rules"/>
-<link rel="match" href="multicol-count-computed-ref.xht"/>
-<meta name="flags" content="ahem"/>
-<style type="text/css"><![CDATA[
-body {
- margin: 0;
-}
-div {
- font-family: ahem;
- font-size: 1em;
- line-height: 1em;
- color: black;
- background: yellow;
- margin: 1em;
- border: 1em solid gray;
- width: 12em;
- widows: 1;
- orphans: 1;
-
- column-count: 3;
- column-gap: 6em;
- column-rule-color: blue;
- column-rule-width: 1.5em;
- column-rule-style: solid;
-}
-#pink {color: pink;}
-#orange {color: orange;}
-#purple {color: purple;}
-#grey {color: grey;}
-]]></style>
-</head>
-
-<body>
-
-<div>
- <span id="pink">xxxx</span>
- <span id="orange">xxxx</span>
- <span id="purple">xxxx</span>
- <span id="grey">xxxx</span>
-</div>
-
-</body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-count-computed-002.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-count-computed-002.xht
deleted file mode 100644
index 7bd1b3effdf..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-count-computed-002.xht
+++ /dev/null
@@ -1,50 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>multicolumn | column-rule</title>
-<link rel="author" title="Opera Software ASA" href="http://www.opera.com/"/>
-<link rel="help" href="http://www.w3.org/TR/css3-multicol/#the-number-and-width-of-columns"/>
-<link rel="help" href="http://www.w3.org/TR/css3-multicol/#column-gaps-and-rules"/>
-<link rel="match" href="multicol-count-computed-2-ref.xht"/>
-<meta name="flags" content="ahem"/>
-<style type="text/css"><![CDATA[
-body {
- margin: 0;
-}
-div {
- font-family: ahem;
- font-size: 1em;
- line-height: 1em;
- color: black;
- background: yellow;
- margin: 1em;
- border: 1em solid gray;
- width: 12em;
- widows: 1;
- orphans: 1;
-
- column-count: 3;
- column-gap: 7em;
- column-rule-color: red;
- column-rule-width: 1.5em;
- column-rule-style: solid;
-}
-#pink {color: pink;}
-#orange {color: orange;}
-#purple {color: purple;}
-#grey {color: grey;}
-]]></style>
-</head>
-
-<body>
-
-<div>
- <span id="pink">xxxx</span>
- <span id="orange">xxxx</span>
- <span id="purple">xxxx</span>
- <span id="grey">xxxx</span>
-</div>
-
-</body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-count-computed-2-ref.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-count-computed-2-ref.xht
deleted file mode 100644
index 15d365cfcc6..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-count-computed-2-ref.xht
+++ /dev/null
@@ -1,58 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>multicolumn | column-rule</title>
-<link rel="author" title="Opera Software ASA" href="http://www.opera.com/"/>
-<style type="text/css"><![CDATA[
-body {
- margin: 0;
-}
-div {
- font-family: ahem;
- font-size: 1em;
- line-height: 1em;
- color: black;
- background: yellow;
- margin: 1em;
- border: 1em solid gray;
- width: 12em;
- height: 2em;
- position: relative;
- widows: 1;
- orphans: 1;
-}
-#pink {color: pink;}
-#orange {color: orange;}
-#purple {color: purple;}
-#grey {color: grey;}
-span {
- display: block;
- position: absolute;
-}
-#orange {
- left: 5em;
- top: 0;
-}
-#purple {
- left: 0;
- top: 1em;
-}
-#grey {
- left: 5em;
- top: 1em;
-}
-]]></style>
-</head>
-
-<body>
-
-<div>
- <span id="purple">xxxx</span>
- <span id="orange">xxxx</span>
- <span id="grey">xxxx</span>
- <span id="pink">xxxx</span>
-</div>
-
-</body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-count-computed-ref.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-count-computed-ref.xht
deleted file mode 100644
index ac6d8c12114..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-count-computed-ref.xht
+++ /dev/null
@@ -1,69 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>multicolumn | column-rule</title>
-<link rel="author" title="Opera Software ASA" href="http://www.opera.com/"/>
-<style type="text/css"><![CDATA[
-body {
- margin: 0;
-}
-div {
- font-family: ahem;
- font-size: 1em;
- line-height: 1em;
- color: black;
- background: yellow;
- margin: 1em;
- border: 1em solid gray;
- width: 12em;
- height: 2em;
- position: relative;
- widows: 1;
- orphans: 1;
-
-}
-span {
- display: block;
- position: absolute;
-}
-#pink {
- color: pink;
-}
-#orange {
- color: orange;
- left: 0;
- top: 1em;
-}
-#purple {
- color: purple;
- left: 9em;
- top: 0;
-}
-#grey {
- color: grey;
- left: 9em;
- top: 1em;
-}
-#blue {
- left: 5.25em;
- top: 0;
- width: 1.5em;
- height: 2em;
- background: blue;
-}
-]]></style>
-</head>
-
-<body>
-
-<div>
- <span id="pink">xxxx</span>
- <span id="orange">xxxx</span>
- <span id="purple">xxxx</span>
- <span id="grey">xxxx</span>
- <span id="blue"></span>
-</div>
-
-</body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-count-large-001.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-count-large-001.xht
deleted file mode 100644
index 78fff42cf7d..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-count-large-001.xht
+++ /dev/null
@@ -1,42 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>multicolumn | column-count</title>
-<link rel="author" title="Opera Software ASA" href="http://www.opera.com/"/>
-<link rel="help" href="http://www.w3.org/TR/css3-multicol/#the-number-and-width-of-columns"/>
-<link rel="match" href="multicol-count-large-ref.xht"/>
-<meta name="flags" content="ahem"/>
-<style type="text/css"><![CDATA[
-body>div {
- font-family: ahem;
- font-size: 1em;
- line-height: 1em;
- color: red;
- background: yellow;
- margin: 1em;
- border: 1em solid gray;
- width: 12em;
- orphans: 1;
- widows: 1;
-
- column-count: 1000;
- column-gap: 0;
-}
-span {
- color: black;
-}
-]]></style>
-</head>
-
-<body>
-
-<div>
- xx xx
- xx xx
- xx xx
- <span>xx xx</span>
-</div>
-
-</body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-count-large-002.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-count-large-002.xht
deleted file mode 100644
index 09b296ab638..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-count-large-002.xht
+++ /dev/null
@@ -1,42 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>multicolumn | column-count</title>
-<link rel="author" title="Opera Software ASA" href="http://www.opera.com/"/>
-<link rel="help" href="http://www.w3.org/TR/css3-multicol/#the-number-and-width-of-columns"/>
-<link rel="match" href="multicol-count-large-2-ref.xht"/>
-<meta name="flags" content="ahem"/>
-<style type="text/css"><![CDATA[
-body>div {
- font-family: ahem;
- font-size: 1em;
- line-height: 1em;
- color: black;
- background: yellow;
- margin: 1em;
- border: 1em solid gray;
- width: 12em;
- orphans: 1;
- widows: 1;
-
- column-count: 1000;
- column-gap: 0;
-}
-span {
- color: blue;
-}
-]]></style>
-</head>
-
-<body>
-
-<div>
- xx xx
- <span>xx xx</span>
- xx xx
- <span>xx xx</span>
-</div>
-
-</body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-count-large-2-ref.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-count-large-2-ref.xht
deleted file mode 100644
index cb4b26f367e..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-count-large-2-ref.xht
+++ /dev/null
@@ -1,40 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>multicolumn | column-count</title>
-<link rel="author" title="Opera Software ASA" href="http://www.opera.com/"/>
-<style type="text/css"><![CDATA[
-body>div {
- font-family: ahem;
- font-size: 1em;
- line-height: 1em;
- color: black;
- background: yellow;
- margin: 1em;
- border: 1em solid gray;
- width: 12em;
- height: 1em;
- position: relative;
- orphans: 1;
- widows: 1;
-}
-span {
- color: blue;
- background: blue;
- width: 2em;
- position: absolute;
- left: 0;
- top: 0;
-}
-]]></style>
-</head>
-
-<body>
-
-<div>
- <span>x</span>
-</div>
-
-</body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-count-large-ref.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-count-large-ref.xht
deleted file mode 100644
index a561c94c2dd..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-count-large-ref.xht
+++ /dev/null
@@ -1,30 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>multicolumn | column-count</title>
-<link rel="author" title="Opera Software ASA" href="http://www.opera.com/"/>
-<style type="text/css"><![CDATA[
-body>div {
- font-family: ahem;
- font-size: 1em;
- line-height: 1em;
- color: black;
- background: yellow;
- margin: 1em;
- border: 1em solid gray;
- width: 12em;
- height: 1em;
- orphans: 1;
- widows: 1;
-
-}
-]]></style>
-</head>
-
-<body>
-
-<div>xx</div>
-
-</body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-fill-auto-block-children-002-ref.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-fill-auto-block-children-002-ref.xht
index f57fa435920..3cec0f55425 100644
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-fill-auto-block-children-002-ref.xht
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-fill-auto-block-children-002-ref.xht
@@ -6,13 +6,15 @@
<link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2013-08-16 -->
<meta name="flags" content="" />
<style type="text/css"><![CDATA[
- body {margin: 8px;}
+ body {margin:0; margin-top:8px;}
div
{
+ float: left;
background-color: blue;
height: 200px;
- width: 680px;
+ width: 60%;
+ margin-left: 8px;
}
h1
@@ -20,51 +22,19 @@
color: white;
font-size: 2em;
line-height: 1.25; /* or 1.21875 to achieve a 39px tall line box */
- margin-top: 8px; /* The margin-top of body and h1 will collapse into an 8px gap */
- margin-bottom: 21px;
- padding-top: 21px;
+ margin: 21px 0em;
}
span#pass
{
+ float: left;
+ margin-left: 10px;
color: blue;
font-size: 1.5em;
font-weight: bolder;
- left: 698px;
-
- /*
-
- Expected result:
-
- 8px 688px
- v v
- ************************************************
- * *
- * <h1>Test passes if the word "PASS!" is<br />* 1st line box
- * on the right &#8600;</h1> * 2nd line box
- * *
- ************************************************
- * *
- * <h2>nbsp;<h2> <h2>nbsp;<h2> <h2>nbsp;<h2> * <h2>PASS!</h2>
- * *
- ************************************************
- ^ ^
- 228px 458px
-
- */
line-height: 1;
- position: absolute;
- top: 130px;
-
- /*
- 8px : margin-top of body element
- 21px : margin-top of h1 element which must not collapse with body's margin-top
- 80px : content height: 2 line boxes required to render the "Test passes if ..." sentence
- 21px : margin-bottom of h1 element
- ====================================
- 130px : top position of span#pass in document box
- */
+ margin-top: 122px;
}
]]></style>
</head>
@@ -72,8 +42,8 @@
<div>
<h1>Test passes if "PASS!" is<br />on the right &#8600;</h1>
- <span id="pass">PASS!</span>
</div>
+ <span id="pass">PASS!</span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-fill-auto-block-children-002.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-fill-auto-block-children-002.xht
index 9097e3c18c4..d79fa95f16c 100644
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-fill-auto-block-children-002.xht
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-fill-auto-block-children-002.xht
@@ -18,16 +18,11 @@
background-color: blue;
height: 200px;
margin: 8px;
- width: 680px;
+ width: 60%;
column-count: 3;
column-fill: auto;
column-gap: 10px;
-
- /*
- So, each column box should be
- [680px minus (2 mult 10px)] divided by 3 == 220px wide
- */
}
h1
@@ -75,25 +70,5 @@
<h2>PASS!</h2>
- <!--
-
- Expected result:
-
- 8px 688px
- v v
- ************************************************
- * *
- * <h1>Test passes if the word "PASS!" is<br />* 1st line box
- * on the right &#8600;</h1> * 2nd line box
- * *
- ************************************************
- * *
- * <h2>nbsp;<h2> <h2>nbsp;<h2> <h2>nbsp;<h2> * <h2>PASS!</h2>
- * *
- ************************************************
- ^ ^
- 228px 458px
- -->
-
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-fill-auto-ref.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-fill-auto-ref.xht
deleted file mode 100644
index b287fb2805b..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-fill-auto-ref.xht
+++ /dev/null
@@ -1,53 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>multicolumn | column-gap</title>
-<link rel="author" title="Opera Software ASA" href="http://www.opera.com/"/>
-<style type="text/css"><![CDATA[
-body>div {
- font-family: ahem;
- font-size: 0.5em;
- line-height: 1em;
- color: black;
- height: 12em;
- width: 100em;
-
-}
-div div {
- float: left;
- width: 26em;
- margin-right: 5em;
-}
-]]></style>
-</head>
-
-<body>
-
-<div>
- <div>one two three four
- five six seven eight
- nine ten eleven twelve
- thirtn fourtn fiftn sixtn
- seventn eightn ninetn twenty
- hundred thousand million billion
- trillion
- one two three four
- five six seven eight
- nine ten eleven twelve
- thirtn fourtn fiftn sixtn
- seventn eightn ninetn twenty
- hundred</div>
- <div>thousand million billion
- trillion
- one two three four
- five six seven eight
- nine ten eleven twelve
- thirtn fourtn fiftn sixtn
- seventn eightn ninetn twenty
- hundred thousand million billion
- trillion</div>
-</div>
-
-</body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-fill-auto.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-fill-auto.xht
deleted file mode 100644
index 20fe7e47f8c..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-fill-auto.xht
+++ /dev/null
@@ -1,49 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>multicolumn | column-fill-auto</title>
-<meta name="assert" content="This test checks that columns are properly balanced when 'column-fill: auto' is set"/>
-<link rel="author" title="howcome@opera.com" href="http://www.opera.com/"/>
-<link rel="help" href="http://www.w3.org/TR/css3-multicol/#filling-columns"/>
-<link rel="match" href="multicol-fill-ref.xht"/>
-<meta name="flags" content="ahem"/>
-<style type="text/css"><![CDATA[
-body>div {
- font-family: ahem;
- font-size: 1.25em;
- line-height: 1em;
- color: green;
- height: 3em;
- width: 2em;
- orphans: 1;
- widows: 1;
- position: relative;
- margin: 1em;
-}
-div.col {
- column-count: 2;
- column-fill: auto;
- column-gap: 0;
-}
-div.red {
- background: red; position: absolute; z-index: -1;
-}
-]]></style>
-</head>
-
-<body>
-
-<div class='col'>
-<div class='red' style="top: 0; left: 0; height: 3em; width: 1em;"></div>
-<div class='red' style="top: 0; left: 0; height: 1em; width: 2em;"></div>
-o<br/>t<br/>
-o<br/>t<br/>
-</div>
-
-<div class='ref'>
-oo<br/>t<br/>o
-</div>
-
-</body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-fill-ref.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-fill-ref.xht
deleted file mode 100644
index 176631b9ad1..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-fill-ref.xht
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>multicolumn | column-gap</title>
-<link rel="author" title="Opera Software ASA" href="http://www.opera.com/"/>
-<style type="text/css"><![CDATA[
-div {
- background: yellow;
- height: 5em;
- width: 30em;
-}
-]]></style>
-</head>
-
-<body>
-
-<div></div>
-
-</body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-gap-animation-001.html b/tests/wpt/web-platform-tests/css/css-multicol/multicol-gap-animation-001.html
new file mode 100644
index 00000000000..6a3a8d33780
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-gap-animation-001.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Multi-column Layout Test: column-gap test animation</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://www.w3.org/TR/css-multicol-1/#column-gap">
+<link rel="help" href="https://www.w3.org/TR/web-animations-1/#dom-animatable-animate">
+<meta name="assert" content="Test checks that column-gap is an animatable property, and that the computed values during the animation are the expected ones.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ #multicol {
+ column-gap: 0px;
+ }
+</style>
+<body>
+ <div id="multicol"></div>
+ <div id="log"></div>
+
+ <script>
+ test(
+ function(){
+ var multicol = document.getElementById("multicol");
+ assert_equals(getComputedStyle(multicol).columnGap, "0px");
+
+ var keyframes = [
+ { columnGap: "100px" },
+ { columnGap: "200px" }
+ ];
+ var options = {
+ duration: 10,
+ fill: "forwards",
+ easing: "linear"
+ };
+
+ var player = multicol.animate(keyframes, options);
+ player.pause();
+ player.currentTime = 0;
+ assert_equals(getComputedStyle(multicol).columnGap, "100px");
+ player.currentTime = 5;
+ assert_equals(getComputedStyle(multicol).columnGap, "150px");
+ player.currentTime = 10;
+ assert_equals(getComputedStyle(multicol).columnGap, "200px");
+ }, "column-gap property is animatable");
+ </script>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-gap-animation-002.html b/tests/wpt/web-platform-tests/css/css-multicol/multicol-gap-animation-002.html
new file mode 100644
index 00000000000..de3756c67b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-gap-animation-002.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Multi-column Layout Test: column-gap normal test animation</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://www.w3.org/TR/css-multicol-1/#column-gap">
+<link rel="help" href="https://www.w3.org/TR/web-animations-1/#dom-animatable-animate">
+<meta name="assert" content="Test checks that 'normal' value for column-gap property is not interpolable.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ @keyframes column-gap-normal-to-100 {
+ from { column-gap: normal; }
+ to { column-gap: 100px; }
+ }
+
+ #multicol {
+ animation-name: column-gap-normal-to-100;
+ animation-duration: 2s;
+ animation-delay: -1s;
+ animation-play-state: paused;
+ }
+</style>
+<body>
+ <div id="multicol"></div>
+ <div id="log"></div>
+
+ <script>
+ test(
+ function(){
+ var multicol = document.getElementById("multicol");
+ assert_equals(getComputedStyle(multicol).columnGap, "100px");
+ }, "column-gap: normal is not interpolable");
+ </script>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-gap-animation-003.html b/tests/wpt/web-platform-tests/css/css-multicol/multicol-gap-animation-003.html
new file mode 100644
index 00000000000..71182fafbe8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-gap-animation-003.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Multi-column Layout Test: Default column-gap test animation</title>
+<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com">
+<link rel="help" href="https://www.w3.org/TR/css-multicol-1/#column-gap">
+<link rel="help" href="https://www.w3.org/TR/web-animations-1/#dom-animatable-animate">
+<meta name="assert" content="Test checks that the default value for column-gap property, which is 'normal', is not interpolable.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ @keyframes column-gap-to-100 {
+ to { column-gap: 100px; }
+ }
+
+ #multicol {
+ animation-name: column-gap-to-100;
+ animation-duration: 2s;
+ animation-delay: -1s;
+ animation-play-state: paused;
+ }
+</style>
+<body>
+ <div id="multicol"></div>
+ <div id="log"></div>
+
+ <script>
+ test(
+ function(){
+ var multicol = document.getElementById("multicol");
+ assert_equals(getComputedStyle(multicol).columnGap, "100px");
+ }, "Default column-gap is not interpolable");
+ </script>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-gap-fraction-002.html b/tests/wpt/web-platform-tests/css/css-multicol/multicol-gap-fraction-002.html
new file mode 100644
index 00000000000..ae1aaaad774
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-gap-fraction-002.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<title>CSS Multi-column Layout Test: 'column-gap' with sub-pixel values</title>
+<link rel="author" title="Morten Stenshorne" href="mstensho@chromium.org">
+<link rel="help" href="http://www.w3.org/TR/css3-multicol/#column-gap" title="4.1. 'column-gap'">
+<link rel="match" href="../reference/nothing.html" />
+<meta name="assert" content="Specified column-gap should never be rounded up to the nearest integer, or the second column in the tests might overflow the multicol container in the inline direction.">
+<style>
+ .multicol { margin:10px; float:left; columns:2; width:50px; column-gap:10.9px; column-fill:auto; height:50px; background:white; }
+ .filler { height:50px; }
+ .below-everything { position:relative; z-index:-1; float:right; width:20px; height:20px; background:red; }
+</style>
+
+<p>There should be nothing below.</p>
+
+<div class="multicol" style="column-gap:10px;">
+ <div class="filler"></div>
+ <div class="below-everything"></div>
+</div>
+
+<div class="multicol" style="column-gap:10.1px;">
+ <div class="filler"></div>
+ <div class="below-everything"></div>
+</div>
+
+<div class="multicol" style="column-gap:10.2px;">
+ <div class="filler"></div>
+ <div class="below-everything"></div>
+</div>
+
+<div class="multicol" style="column-gap:10.3px;">
+ <div class="filler"></div>
+ <div class="below-everything"></div>
+</div>
+
+<div class="multicol" style="column-gap:10.4px;">
+ <div class="filler"></div>
+ <div class="below-everything"></div>
+</div>
+
+<div class="multicol" style="column-gap:10.5px;">
+ <div class="filler"></div>
+ <div class="below-everything"></div>
+</div>
+
+<div class="multicol" style="column-gap:10.6px;">
+ <div class="filler"></div>
+ <div class="below-everything"></div>
+</div>
+
+<div class="multicol" style="column-gap:10.7px;">
+ <div class="filler"></div>
+ <div class="below-everything"></div>
+</div>
+
+<div class="multicol" style="column-gap:10.8px;">
+ <div class="filler"></div>
+ <div class="below-everything"></div>
+</div>
+
+<div class="multicol" style="column-gap:10.9px;">
+ <div class="filler"></div>
+ <div class="below-everything"></div>
+</div>
+
+<div class="multicol" style="column-gap:11px;">
+ <div class="filler"></div>
+ <div class="below-everything"></div>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-height-block-child-001-ref.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-height-block-child-001-ref.xht
index 27a87c3fe3a..b238d5c94f2 100644
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-height-block-child-001-ref.xht
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-height-block-child-001-ref.xht
@@ -5,51 +5,34 @@
<link rel="author" title="Opera Software ASA" href="http://www.opera.com/" />
<link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2013-08-08 -->
<meta name="flags" content="image" />
- <style type="text/css"><![CDATA[
- div
- {
- background-color: blue;
- font: 1.25em/1 serif;
- }
-
- div#top
- {
- height: 5em;
- width: 22em;
- }
-
- div#bottom
- {
- height: 3em;
- width: 14em;
- }
-
- img {vertical-align: top;}
- ]]></style>
</head>
<body>
- <div id="top"><img src="support/black20x20.png" width="60" height="100" alt="Image download support must be enabled" /></div>
-
- <div id="bottom"><img src="support/swatch-orange.png" width="60" height="60" alt="Image download support must be enabled" /></div>
+ <div style="font:20px/1 Ahem; width:22em; height:5em; background:blue;">
+ <div style="width:3em; height:5em; background:black;"></div>
+ </div>
+ <div style="font:20px/1 Ahem; width:14em; height:3em; background:blue;">
+ <div style="float:left; width:3em; height:3em; margin-right:5em; background:orange;"></div>
+ <div style="float:left; width:3em; height:3em; background:orange;"></div>
+ </div>
<!--
Expected results:
- 0em 14em 22em
- v v v
+ 0em 7em 14em 22em
+ v v v v
0 *********************************************
- * bla | *
- * bla | *
- * bla | *
- * bla | *
-5 * bla | *
-6 * orn |****************
-7 * orn |
-8 * orn |
+ * bla | | *
+ * bla | | *
+ * bla | | *
+ * bla | | *
+5 * bla | | *
+6 * orn | zzz |****************
+7 * orn | zzz |
+8 * orn | zzz |
*****************************
-->
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-height-block-child-001.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-height-block-child-001.xht
index d7dfd3de5fa..b62d92eee53 100644
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-height-block-child-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-height-block-child-001.xht
@@ -54,40 +54,35 @@
</div>
<!--
- Both column boxes of div#inner start in the 1st
- column box of div#outer multi-column element.
- The first 3 lines boxes of 1st
- column box of div#inner will be rendered inside the
- 1st column box of div#outer but not its 2nd.
- Because 1st column box of div#outer is
- 6em wide while the div#inner multi-column element
- is 14em wide, this makes the first 3 line boxes
- (with the 'z' trios) of 2nd column box of div#inner
- clipped.
-
- Then, at this point, the div#inner multi-column
- element should be fragmented in order to continue to
- render the 5 empty line boxes it has into the
- 2nd column box of div#outer. Since those 5 line
- boxes are empty, we only see the extension it
- creates horizontally, which is
- 14em - 6em == 8em horizontally and
- 5 lines boxes == 5em tall
-
+ Both column boxes of div#inner start in the 1st column box of
+ div#outer multi-column element. All the 6 lines of div#inner will
+ be rendered inside the 1st column box of div#outer. The first three
+ lines in the first inner column, and the last three in the second
+ inner column, which will overflow the first outer column, and
+ actually appear as if they were part of the second outer column. No
+ clipping should occur, unless explicitly requested.
+
+ All the 6 lines of #inner fit in a column row that resides in the
+ first outer column. #inner has a fixed height, and is taller than
+ what can fit in the first outer column, so it needs to continue in
+ the second outer column, with no inner column content left to
+ fragment. #inner is a 14em wide block that is put into a 6em wide
+ outer column, so it will overflow the outer column all the way to
+ 22em, relatively to the left edge of the outer multicol container.
Expected results:
- 0em 14em 22em
- v v v
+ 0em 7em 14em 22em
+ v v v v
0 *********************************************
- * bla | *
- * bla | *
- * bla | *
- * bla | *
-5 * bla | *
-6 * orn |****************
-7 * orn |
-8 * orn |
+ * bla | | *
+ * bla | | *
+ * bla | | *
+ * bla | | *
+5 * bla | | *
+6 * orn | zzz |****************
+7 * orn | zzz |
+8 * orn | zzz |
*****************************
-->
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-inherit-004.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-inherit-004.xht
deleted file mode 100644
index 2272c431750..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-inherit-004.xht
+++ /dev/null
@@ -1,55 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>multicolumn | inheritance</title>
-<link rel="author" title="Opera Software ASA" href="http://www.opera.com/"/>
-<link rel="help" href="http://www.w3.org/TR/css3-multicol/#column-gaps-and-rules"/>
-<link rel="match" href="multicol-inherit-4-ref.xht"/>
-<meta name="flags" content="ahem"/>
-<style type="text/css"><![CDATA[
-body>div {
- width: 74em;
- column-rule: 1em solid blue;
-}
-div {
- font-family: ahem;
- font-size: 1em;
- line-height: 1em;
- color: white;
- background: white;
- margin: 1em;
- orphans: 1;
- widows: 1;
-
- column-count: 3;
- column-gap: 7em;
-}
-]]></style>
-</head>
-
-<body>
-
-<div>
- <div>
- xx xx
- xx xx
- xx xx
- xx xx
- </div>
- <div>
- xx xx
- xx xx
- xx xx
- xx xx
- </div>
- <div>
- xx xx
- xx xx
- xx xx
- xx xx
- </div>
-</div>
-
-</body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-inherit-4-ref.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-inherit-4-ref.xht
deleted file mode 100644
index 2972d713206..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-inherit-4-ref.xht
+++ /dev/null
@@ -1,37 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>multicolumn | inheritance</title>
-<link rel="author" title="Opera Software ASA" href="http://www.opera.com/"/>
-<style type="text/css"><![CDATA[
-body>div {
- margin: 1em;
- background: white;
- width: 74em;
- height: 5em;
- position: relative;
-}
-div div {
- background: blue;
- height: 5em;
- width: 1em;
- position: absolute;
- top: 0;
- left: 23em;
-}
-div>div+div {
- left: 50em;
-}
-]]></style>
-</head>
-
-<body>
-
-<div>
- <div></div>
- <div></div>
-</div>
-
-</body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-nested-column-rule-001-ref.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-nested-column-rule-001-ref.xht
index 8d86b42a690..e373c9a60b6 100644
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-nested-column-rule-001-ref.xht
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-nested-column-rule-001-ref.xht
@@ -5,41 +5,8 @@
<link rel="author" title="Opera Software ASA" href="http://www.opera.com/" />
<link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2013-08-09 -->
<meta name="flags" content="" />
- <style type="text/css"><![CDATA[
- div#rel-pos-wrapper
- {
- font: 1.25em/1 serif;
- position: relative;
- }
-
- div#rel-pos-wrapper > div
- {
- background-color: blue;
- font-size: 1em;
- height: 3em;
- position: absolute;
- width: 1em;
- }
-
- div#first-column-rule
- {
- left: 14em;
- top: auto;
- }
-
- div#second-column-rule
- {
- left: 29em;
- top: auto;
- }
- ]]></style>
</head>
<body>
-
- <div id="rel-pos-wrapper">
- <div id="first-column-rule"></div>
- <div id="second-column-rule"></div>
- </div>
-
+ <div style="font: 1.25em/1 Ahem; width:12em; height:3em; margin-left:12em; border-left:1em solid blue; border-right:1em solid blue;"></div>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-nested-column-rule-001.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-nested-column-rule-001.xht
index 11a44f46c2f..322551e185f 100644
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-nested-column-rule-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-nested-column-rule-001.xht
@@ -18,7 +18,7 @@
{
column-rule: blue solid 1em;
font: 1.25em/1 Ahem;
- width: 42em;
+ width: 36em;
}
/*
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-fraction-3-ref.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-fraction-3-ref.xht
index 9189b97d3c5..f4d3b845d0f 100644
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-fraction-3-ref.xht
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-fraction-3-ref.xht
@@ -32,9 +32,9 @@ div div {
background: blue;
width: 1em;
}
-#a1 {left: 2.43em;}
+#a1 {left: 2.4em;}
#a2 {left: 3.75em;}
-#a3 {left: 6.13em;}
+#a3 {left: 6.15em;}
#a4 {left: 7.5em;}
#a5 {left: 9.9em;}
#a6 {left: 11.25em;}
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-samelength-001.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-samelength-001.xht
index 431eb74e4f1..e7eab8e8d47 100644
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-samelength-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-samelength-001.xht
@@ -1,7 +1,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
- <title>CSS Multi-column Layout Test: 'column-rule-width' has same lenght as 'column-gap'</title>
+ <title>CSS Multi-column Layout Test: 'column-rule-width' has same length as 'column-gap'</title>
<link rel="author" title="Opera Software ASA" href="http://www.opera.com/" />
<link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2013-08-15 -->
<link rel="help" href="http://www.w3.org/TR/css3-multicol/#crw" title="4.4. 'column-rule-width'" />
@@ -68,4 +68,4 @@
-->
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-style-groove-001-ref.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-style-groove-001-ref.xht
deleted file mode 100644
index a32a71ef4b6..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-style-groove-001-ref.xht
+++ /dev/null
@@ -1,44 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
- <title>CSS Reftest Reference</title>
- <link rel="author" title="Opera Software ASA" href="http://www.opera.com/" />
- <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2013-08-15 -->
- <meta name="flags" content="ahem" />
- <style type="text/css"><![CDATA[
- body {margin: 8px;}
-
- p
- {
- line-height: 1.25em;
- margin: 1em 0em;
- }
-
- strong {line-height: 1;}
-
- div
- {
- border-collapse: collapse;
- border-left: orange groove 100px;
- color: transparent;
- display: table;
- font: 6.25em/1 Ahem;
- }
-
- div + div
- {
- position: relative;
- top: 10px;
- }
- ]]></style>
- </head>
- <body>
-
- <p>Test passes if the 2 orange squares are <strong>identical</strong>.</p>
-
- <div>T</div>
-
- <div>T</div>
-
- </body>
-</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-style-groove-001.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-style-groove-001.xht
deleted file mode 100644
index 43a4a213ecd..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-style-groove-001.xht
+++ /dev/null
@@ -1,71 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>CSS Multi-column Layout Test: 'column-rule-style' groove</title>
- <link rel="author" title="Opera Software ASA" href="http://www.opera.com/" />
- <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2013-08-15 -->
- <link rel="help" href="http://www.w3.org/TR/css3-multicol/#crs" title="4.3. 'column-rule-style'" />
- <link rel="match" href="multicol-rule-style-groove-001-ref.xht" />
- <meta name="flags" content="ahem" />
- <style type="text/css"><![CDATA[
- body {margin: 8px;}
-
- p
- {
- line-height: 1.25em;
- margin: 1em 0em;
- }
-
- strong {line-height: 1;}
-
- div {color: transparent;}
-
- div#reference
- {
- border-collapse: collapse;
- border-left: orange groove 100px;
- font: 6.25em/1 Ahem;
- display: table;
- }
-
- div#test
- {
- font: 1.25em/1 Ahem; /* equivalent to 20px/1 Ahem */
- position: relative;
- right: 40px;
- top: 0.5em;
- width: 9em;
-
- column-count: 2;
- column-gap: 5em;
- column-rule: orange groove 5em;
- }
- ]]></style>
- </head>
-
- <body>
-
- <p>Test passes if the 2 orange squares are <strong>identical</strong>.</p>
-
- <div id="reference">T</div>
-
- <div id="test">Le ft Co lu mn Ri gh Co lu mn</div>
-
- <!--
-
- Expected results
- column-gap
- column-rule
- v=====v
- *************
- |Le| |Ri|
- |ft| |gh|
- |Co| |Co|
- |lu| |lu|
- |mn| |mn|
- *************
-
- -->
-
- </body>
-</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-style-inset-001.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-style-inset-001.xht
deleted file mode 100644
index d50bec9325d..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-style-inset-001.xht
+++ /dev/null
@@ -1,71 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>CSS Multi-column Layout Test: 'column-rule-style' inset</title>
- <link rel="author" title="Opera Software ASA" href="http://www.opera.com/" />
- <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2013-08-15 -->
- <link rel="help" href="http://www.w3.org/TR/css3-multicol/#crs" title="4.3. 'column-rule-style'" />
- <link rel="match" href="multicol-rule-style-ridge-001-ref.xht" />
- <meta name="flags" content="ahem" />
- <style type="text/css"><![CDATA[
- body {margin: 8px;}
-
- p
- {
- line-height: 1.25em;
- margin: 1em 0em;
- }
-
- strong {line-height: 1;}
-
- div {color: transparent;}
-
- div#reference
- {
- border-collapse: collapse;
- border-left: orange inset 100px;
- font: 6.25em/1 Ahem;
- display: table;
- }
-
- div#test
- {
- font: 1.25em/1 Ahem; /* equivalent to 20px/1 Ahem */
- position: relative;
- right: 40px;
- top: 0.5em;
- width: 9em;
-
- column-count: 2;
- column-gap: 5em;
- column-rule: orange inset 5em;
- }
- ]]></style>
- </head>
-
- <body>
-
- <p>Test passes if the 2 orange squares are <strong>identical</strong>.</p>
-
- <div id="reference">T</div>
-
- <div id="test">Le ft Co lu mn Ri gh Co lu mn</div>
-
- <!--
-
- Expected results
- column-gap
- column-rule
- v=====v
- *************
- |Le| |Ri|
- |ft| |gh|
- |Co| |Co|
- |lu| |lu|
- |mn| |mn|
- *************
-
- -->
-
- </body>
-</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-style-outset-001.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-style-outset-001.xht
deleted file mode 100644
index ea8c3320fff..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-style-outset-001.xht
+++ /dev/null
@@ -1,71 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>CSS Multi-column Layout Test: 'column-rule-style' outset</title>
- <link rel="author" title="Opera Software ASA" href="http://www.opera.com/" />
- <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2013-08-15 -->
- <link rel="help" href="http://www.w3.org/TR/css3-multicol/#crs" title="4.3. 'column-rule-style'" />
- <link rel="match" href="multicol-rule-style-groove-001-ref.xht" />
- <meta name="flags" content="ahem" />
- <style type="text/css"><![CDATA[
- body {margin: 8px;}
-
- p
- {
- line-height: 1.25em;
- margin: 1em 0em;
- }
-
- strong {line-height: 1;}
-
- div {color: transparent;}
-
- div#reference
- {
- border-collapse: collapse;
- border-left: orange outset 100px;
- font: 6.25em/1 Ahem;
- display: table;
- }
-
- div#test
- {
- font: 1.25em/1 Ahem; /* equivalent to 20px/1 Ahem */
- position: relative;
- right: 40px;
- top: 0.5em;
- width: 9em;
-
- column-count: 2;
- column-gap: 5em;
- column-rule: orange outset 5em;
- }
- ]]></style>
- </head>
-
- <body>
-
- <p>Test passes if the 2 orange squares are <strong>identical</strong>.</p>
-
- <div id="reference">T</div>
-
- <div id="test">Le ft Co lu mn Ri gh Co lu mn</div>
-
- <!--
-
- Expected results
- column-gap
- column-rule
- v=====v
- *************
- |Le| |Ri|
- |ft| |gh|
- |Co| |Co|
- |lu| |lu|
- |mn| |mn|
- *************
-
- -->
-
- </body>
-</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-style-ridge-001-ref.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-style-ridge-001-ref.xht
deleted file mode 100644
index 4da6ec849d4..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-style-ridge-001-ref.xht
+++ /dev/null
@@ -1,44 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
- <title>CSS Reftest Reference</title>
- <link rel="author" title="Opera Software ASA" href="http://www.opera.com/" />
- <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2013-08-15 -->
- <meta name="flags" content="ahem" />
- <style type="text/css"><![CDATA[
- body {margin: 8px;}
-
- p
- {
- line-height: 1.25em;
- margin: 1em 0em;
- }
-
- strong {line-height: 1;}
-
- div
- {
- border-collapse: collapse;
- border-left: orange ridge 100px;
- color: transparent;
- display: table;
- font: 6.25em/1 Ahem;
- }
-
- div + div
- {
- position: relative;
- top: 10px;
- }
- ]]></style>
- </head>
- <body>
-
- <p>Test passes if the 2 orange squares are <strong>identical</strong>.</p>
-
- <div>T</div>
-
- <div>T</div>
-
- </body>
-</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-style-ridge-001.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-style-ridge-001.xht
deleted file mode 100644
index 1cc97df5640..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-rule-style-ridge-001.xht
+++ /dev/null
@@ -1,71 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>CSS Multi-column Layout Test: 'column-rule-style' ridge</title>
- <link rel="author" title="Opera Software ASA" href="http://www.opera.com/" />
- <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2013-08-15 -->
- <link rel="help" href="http://www.w3.org/TR/css3-multicol/#crs" title="4.3. 'column-rule-style'" />
- <link rel="match" href="multicol-rule-style-ridge-001-ref.xht" />
- <meta name="flags" content="ahem" />
- <style type="text/css"><![CDATA[
- body {margin: 8px;}
-
- p
- {
- line-height: 1.25em;
- margin: 1em 0em;
- }
-
- strong {line-height: 1;}
-
- div {color: transparent;}
-
- div#reference
- {
- border-collapse: collapse;
- border-left: orange ridge 100px;
- font: 6.25em/1 Ahem;
- display: table;
- }
-
- div#test
- {
- font: 1.25em/1 Ahem; /* equivalent to 20px/1 Ahem */
- position: relative;
- right: 40px;
- top: 0.5em;
- width: 9em;
-
- column-count: 2;
- column-gap: 5em;
- column-rule: orange ridge 5em;
- }
- ]]></style>
- </head>
-
- <body>
-
- <p>Test passes if the 2 orange squares are <strong>identical</strong>.</p>
-
- <div id="reference">T</div>
-
- <div id="test">Le ft Co lu mn Ri gh Co lu mn</div>
-
- <!--
-
- Expected results
- column-gap
- column-rule
- v=====v
- *************
- |Le| |Ri|
- |ft| |gh|
- |Co| |Co|
- |lu| |lu|
- |mn| |mn|
- *************
-
- -->
-
- </body>
-</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-003.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-003.xht
index 9986f930ce4..fb4a508f50a 100644
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-003.xht
@@ -26,6 +26,8 @@
column-count: 4;
column-gap: 0;
+ orphans: 1;
+ widows: 1;
}
h4
@@ -45,4 +47,4 @@
1 22&nbsp; 1 22&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp; 1 333 1 333 1 333 55555 1 22&nbsp; 1 22&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp; 1 22&nbsp; 1 22&nbsp; 1 22&nbsp; 55555 1 333 1 333 1&nbsp;&nbsp;&nbsp;&nbsp; 4444 4444 1&nbsp;&nbsp;&nbsp;&nbsp; 55555 1 333 1 333 1&nbsp;&nbsp;&nbsp;&nbsp; 4444 4444 1&nbsp;&nbsp;&nbsp;&nbsp; 55555
</div>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-child-001-ref.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-child-001-ref.xht
deleted file mode 100644
index fe82d6a1162..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-child-001-ref.xht
+++ /dev/null
@@ -1,109 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
- <title>CSS Reftest Reference</title>
- <link rel="author" title="Opera Software ASA" href="http://www.opera.com/" />
- <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2013-08-19 -->
- <meta name="flags" content="" />
- <style type="text/css"><![CDATA[
- div#rel-pos-wrapper
- {
- background-color: blue;
- font-size: 1.25em;
- height: 10em;
- position: relative;
- width: 12em;
- }
-
- div > div {position: absolute;}
-
- div#first-black
- {
- background-color: black;
- left: 7em;
- height: 1em;
- top: 0em;
- width: 5em;
- }
-
- div#first-yellow
- {
- background-color: yellow;
- left: 7em;
- height: 3em;
- top: 1em;
- width: 1em;
- }
-
- div#first-white
- {
- background-color: white;
- left: 10em;
- height: 9em;
- top: 1em;
- width: 2em;
- }
-
- div#second-black
- {
- background-color: black;
- left: 2em;
- height: 1em;
- top: 2em;
- width: 3em;
- }
-
- div#second-yellow
- {
- background-color: yellow;
- left: 2em;
- height: 3em;
- top: 3em;
- width: 1em;
- }
-
- div#third-black
- {
- background-color: black;
- left: 2em;
- height: 1em;
- top: 6em;
- width: 3em;
- }
-
- div#third-yellow
- {
- background-color: yellow;
- left: 2em;
- height: 3em;
- top: 7em;
- width: 1em;
- }
-
- div#second-white
- {
- background-color: white;
- left: 5em;
- height: 4em;
- top: 6em;
- width: 7em;
- }
- ]]></style>
- </head>
- <body>
-
- <div id="rel-pos-wrapper">
-
- <div id="first-black"></div>
- <div id="first-yellow"></div>
- <div id="first-white"></div>
- <div id="second-black"></div>
- <div id="second-yellow"></div>
- <div id="third-black"></div>
- <div id="third-yellow"></div>
- <div id="second-white"></div>
-
- </div>
-
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-child-001.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-child-001.xht
deleted file mode 100644
index ebc38abf7d6..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-child-001.xht
+++ /dev/null
@@ -1,53 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>CSS Multi-column Layout Test: 'column-span: all' element with block children (complex)</title>
- <link rel="author" title="Opera Software ASA" href="http://www.opera.com/" />
- <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2013-08-19 -->
- <link rel="help" href="http://www.w3.org/TR/css3-multicol/#column-span" title="6.1. 'column-span'" />
- <link rel="bookmark" title="[css3-multicol] spanning element with only block children" href="http://lists.w3.org/Archives/Public/www-style/2013Aug/0318.html" />
- <link rel="match" href="multicol-span-all-child-001-ref.xht" />
- <meta name="flags" content="ahem may" />
- <meta name="assert" content="This test checks how a spanning element with block children is rendered inside a multi-column element with a set height which is insufficient for rendering the entire spanning element. Since the available height (10em)is insufficient to render the spanning element (height needed: 3 times 4em) entirely inside the multi-column element, then UA may treat 'column-span: all' as 'column-span: none'." />
- <style type="text/css"><![CDATA[
- body
- {
- color: black;
- font: 1.25em/1 Ahem;
- height: 10em;
- orphans: 1;
- widows: 1;
- width: 10em;
-
- column-count: 2;
- column-fill: auto;
- column-gap: 0em;
- }
-
- div
- {
- background-color: yellow;
- border: blue solid 2em;
-
- column-span: all;
- }
-
- span
- {
- display: block;
- height: 4em;
- width: 5em;
- }
- ]]></style>
- </head>
-
- <body>
-
- <div>
- <span>block</span>
- <span>block</span>
- <span>block</span>
- </div>
-
- </body>
-</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-child-002-ref.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-child-002-ref.xht
deleted file mode 100644
index 417bbe110fd..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-child-002-ref.xht
+++ /dev/null
@@ -1,32 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
- <title>CSS Reftest Reference</title>
- <link rel="author" title="Opera Software ASA" href="http://www.opera.com/" />
- <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2013-08-19 -->
- <meta name="flags" content="" />
- <style type="text/css"><![CDATA[
- div#multi-column
- {
- background-color: black;
- height: 8em;
- width: 10em;
- }
-
- div#overflow
- {
- bottom: 8em;
- font: 1em/1 serif;
- margin-left: 10em;
- position: relative;
- }
- ]]></style>
- </head>
- <body>
-
- <div id="multi-column"></div>
-
- <div id="overflow">abc deg<br />ghk mno</div>
-
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-child-002.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-child-002.xht
deleted file mode 100644
index 72cd8e6b026..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-child-002.xht
+++ /dev/null
@@ -1,86 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>CSS Multi-column Layout Test: 'column-span: all' element with block children (complex)</title>
- <link rel="author" title="Opera Software ASA" href="http://www.opera.com/" />
- <link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2013-08-19 -->
- <link rel="help" href="http://www.w3.org/TR/css3-multicol/#column-span" title="6.1. 'column-span'" />
- <link rel="bookmark" title="[css3-multicol] spanning element with only block children" href="http://lists.w3.org/Archives/Public/www-style/2013Aug/0318.html" />
- <link rel="match" href="multicol-span-all-child-002-ref.xht" />
- <meta name="flags" content="may" />
- <meta name="assert" content="This test checks how spanning elements with block children is rendered inside a multi-column element with a set height which is insufficient for rendering both spanning elements entirely. Since available space (height of 8em) is insufficient to render both spanning elements (4 times 4em plus 2em) entirely inside the multi-column element, then UA may treat 'column-span: all' as 'column-span: none'." />
- <style type="text/css"><![CDATA[
- html {background-color: white;}
-
- body
- {
- background-color: black;
- height: 8em;
- orphans: 1;
- widows: 1;
- width: 10em;
-
- column-count: 2;
- column-gap: 0em;
-
- /*
-
- N == 2;
-
- W == 5em;
-
- */
-
- }
-
- div, p
- {
- font: 1em/1 serif;
- margin-top: 0em;
-
- column-span: all;
- }
-
- span
- {
- color: black;
- display: block;
- height: 4em;
- width: 5em;
- }
- ]]></style>
- </head>
-
- <body>
-
- <div>
- <span>FAIL</span>
- <span>FAIL</span>
- <span>FAIL</span>
- <span>FAIL</span>
- </div>
-
- <p>abc deg ghk mno</p>
-
- <!--
-
- Expected results:
-
- ************************
- |FAIL |FAIL |abc deg
- | | |ghk mno
- | | |
- | | |
- |FAIL |FAIL |
- | | |
- | | |
- | | |
- ************************
-
- The test presumes, postulates that
- "abc deg" occupies not more than 5em.
-
- -->
-
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-margin-nested-003.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-margin-nested-003.xht
deleted file mode 100644
index 9aef675ccf9..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-margin-nested-003.xht
+++ /dev/null
@@ -1,39 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>multicolomn | column-span inside block</title>
-<link rel="author" title="Opera Software ASA" href="http://www.opera.com/"/>
-<link rel="help" href="http://www.w3.org/TR/css3-multicol/#spanning-columns"/>
-<link rel="match" href="multicol-span-all-margin-nested-3-ref.xht"/>
-<meta name="flags" content="ahem"/>
-<style type="text/css"><![CDATA[
-body>div {
- font-family: ahem;
- font-size: 1em;
- line-height: 1em;
- color: black;
- background: black;
- position: absolute;
- orphans: 1;
- widows: 1;
-
- column-count: 4;
-}
-#spanned {
- column-span: all;
-}
-]]></style>
-</head>
-
-<body>
-
-<div>
- <div>
- <div id="spanned">x</div>
- </div>
- FAIL FAIL FAIL FAIL
-</div>
-
-</body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-margin-nested-3-ref.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-margin-nested-3-ref.xht
deleted file mode 100644
index 105d22bf498..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-span-all-margin-nested-3-ref.xht
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>multicolomn | column-span inside block</title>
-<link rel="author" title="Opera Software ASA" href="http://www.opera.com/"/>
-<style type="text/css"><![CDATA[
-body>div {
- background: black;
- width: 22em;
- height: 2em;
- position: absolute;
-}
-]]></style>
-</head>
-
-<body>
-
-<div>
-</div>
-
-</body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-table-cell-vertical-align-001.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-table-cell-vertical-align-001.xht
index 5f73cec0976..f50d0afe79c 100644
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-table-cell-vertical-align-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-table-cell-vertical-align-001.xht
@@ -10,13 +10,13 @@
<style type="text/css"><![CDATA[
div {
font-family: ahem;
- font-size: 1em;
+ font-size: 20px;
line-height: 1em;
vertical-align: middle;
color: white;
background: #3366CC;
width: 6em;
- height: 400px;
+ height: 20em;
display: table-cell;
column-count: 2;
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-table-cell-vertical-align-ref.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-table-cell-vertical-align-ref.xht
index 023c9c6a0b4..bbb2d3c3aa7 100644
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-table-cell-vertical-align-ref.xht
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-table-cell-vertical-align-ref.xht
@@ -7,16 +7,16 @@
<style type="text/css"><![CDATA[
div {
font-family: ahem;
- font-size: 1em;
+ font-size: 20px;
line-height: 1em;
vertical-align: middle;
color: white;
background: #3366CC;
width: 6em;
- height: 8em;
+ height: 5.5em;
}
div+div {
- margin-top: 10em;
+ margin-top: 9em;
}
]]></style>
</head>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-width-ch-001.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-width-ch-001.xht
new file mode 100644
index 00000000000..c3e3b353028
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-width-ch-001.xht
@@ -0,0 +1,34 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>multicolumn | column-width</title>
+<link rel="author" title="Opera Software ASA" href="http://www.opera.com/"/>
+<link rel="help" href="http://www.w3.org/TR/css3-multicol/#the-number-and-width-of-columns"/>
+<link rel="match" href="multicol-width-ch-ref.xht"/>
+<meta name="flags" content=""/>
+<style type="text/css"><![CDATA[
+.multicol {
+ font: 1em monospace;
+ width: 69ch;
+ column-width: 13ch;
+ column-gap: 1ch;
+ orphans: 1;
+ widows: 1;
+ background: yellow;
+}
+]]></style>
+</head>
+
+<body>
+ <div class="multicol">
+ one two three four
+ five six seven eight
+ nineten eleven twelve
+ thirtn fourtnfiftn sixtn
+ seventn eightn ninetn twenty
+ hundred thousand million billion
+ trillion
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-width-ch-ref.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-width-ch-ref.xht
new file mode 100644
index 00000000000..133ad3e4b24
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-width-ch-ref.xht
@@ -0,0 +1,49 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>multicolumn | column-width</title>
+<link rel="author" title="Opera Software ASA" href="http://www.opera.com/"/>
+<style type="text/css"><![CDATA[
+.multicol-ref {
+ display: flow-root;
+ width: 69ch;
+ font: 1em monospace;
+ background: yellow;
+}
+.multicol-ref > span {
+ float: left;
+ width: 13ch;
+ margin-right: 1ch;
+}
+.multicol-ref > span:last-child {
+ margin: 0;
+}
+]]></style>
+</head>
+
+<body>
+ <div class="multicol-ref">
+ <span>
+ one two three four
+ five six seven eight
+ </span>
+ <span>
+ nineten eleven twelve
+ thirtn
+ </span>
+ <span>
+ fourtnfiftn sixtn
+ seventn eightn ninetn
+ </span>
+ <span>
+ twenty
+ hundred thousand
+ </span>
+ <span>
+ million billion
+ trillion
+ </span>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-width-ems-001.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-width-ems-001.xht
deleted file mode 100644
index c227ab4032e..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-width-ems-001.xht
+++ /dev/null
@@ -1,42 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>multicolumn | column-width</title>
-<link rel="author" title="Opera Software ASA" href="http://www.opera.com/"/>
-<link rel="help" href="http://www.w3.org/TR/css3-multicol/#the-number-and-width-of-columns"/>
-<link rel="match" href="multicol-width-ems-ref.xht"/>
-<meta name="flags" content=""/>
-<style type="text/css"><![CDATA[
-body {
- margin: 0;
- width: 40em;
-}
-div {
- font-family: monospace;
- font-size: 1em;
- line-height: 1em;
- color: black;
- background: yellow;
- orphans: 1;
- widows: 1;
-
- column-width: 8em;
- column-gap: 0;
-}
-]]></style>
-</head>
-
-<body>
-<div>
- one two three four
- five six seven eight
- nineten eleven twelve
- thirtn fourtnfiftn sixtn
- seventn eightn ninetn twenty
- hundred thousand million billion
- trillion
-</div>
-
-</body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-width-ems-ref.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-width-ems-ref.xht
deleted file mode 100644
index b3ca468106a..00000000000
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-width-ems-ref.xht
+++ /dev/null
@@ -1,59 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>multicolumn | column-width</title>
-<link rel="author" title="Opera Software ASA" href="http://www.opera.com/"/>
-<style type="text/css"><![CDATA[
-body {
- margin: 0;
- width: 40em;
-}
-div {
- font-family: monospace;
- font-size: 1em;
- line-height: 1em;
- color: black;
- background: yellow;
- orphans: 1;
- widows: 1;
-}
-span {
- float: left;
- width: 8em;
-}
-div::after {
- content: "";
- clear: both;
- display: block;
-}
-]]></style>
-</head>
-
-<body>
-
-<div>
-<span>
- one two three four
- five six seven eight
-</span>
-<span>
- nineten eleven twelve
- thirtn
-</span>
-<span>
- fourtnfiftn sixtn
- seventn eightn
-</span>
-<span>
- ninetn twenty
- hundred thousand
-</span>
-<span>
- million billion
- trillion
-</span>
-</div>
-
-</body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-width-small-001.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-width-small-001.xht
index 362aeb17f1e..c034815060b 100644
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-width-small-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-width-small-001.xht
@@ -10,7 +10,7 @@
<meta name="flags" content="ahem" />
<meta name="assert" content="This test checks that a set 'column-width' which is small with regards to width of multi-column element." />
<style type="text/css"><![CDATA[
- div
+ body > div
{
background-color: yellow;
border: gray solid 1em;
@@ -23,20 +23,23 @@
column-gap: 0;
column-width: 1em;
}
+ div > div { overflow: hidden; }
span {color: blue;}
]]></style>
</head>
<body>
<div>
- Bl ac
- <span>
- bl ue
- </span>
- <span>
- bl ue
- </span>
- Bl ac
+ <div>
+ Bl ac
+ <span>
+ bl ue
+ </span>
+ <span>
+ bl ue
+ </span>
+ Bl ac
+ </div>
</div>
<!--
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-zero-height-001-ref.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-zero-height-001-ref.xht
index 273bb43eccb..389ff0ad8d5 100644
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-zero-height-001-ref.xht
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-zero-height-001-ref.xht
@@ -4,12 +4,8 @@
<title>CSS Reftest Reference</title>
<link rel="author" title="Opera Software ASA" href="http://www.opera.com/" />
<link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2013-08-24 -->
- <meta name="flags" content="image" />
- <style type="text/css"><![CDATA[
- img {vertical-align: top;}
- ]]></style>
</head>
<body>
- <div><img src="support/swatch-lime.png" width="100" height="300" alt="Image download support must be enabled" /></div>
+ <div style="width:200px; height:1px; background-color:lime;"/>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-multicol/multicol-zero-height-001.xht b/tests/wpt/web-platform-tests/css/css-multicol/multicol-zero-height-001.xht
index 5cf3f12ea6f..4472bc209e2 100644
--- a/tests/wpt/web-platform-tests/css/css-multicol/multicol-zero-height-001.xht
+++ b/tests/wpt/web-platform-tests/css/css-multicol/multicol-zero-height-001.xht
@@ -5,6 +5,7 @@
<link rel="author" title="Opera Software ASA" href="http://www.opera.com/" />
<link rel="reviewer" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2013-08-24 -->
<link rel="help" href="http://www.w3.org/TR/css3-multicol/#cw" title="3.1. 'column-width'" />
+ <link rel="help" href="https://www.w3.org/TR/css-break-3/#breaking-rules" title="4. Rules for Breaking" />
<link rel="match" href="multicol-zero-height-001-ref.xht" />
<meta name="flags" content="" />
<style type="text/css"><![CDATA[
@@ -14,25 +15,18 @@
orphans: 1;
widows: 1;
width: 200px;
+ border-bottom:1px solid red;
- column-count: 2;
+ column-count: 10;
column-gap: 0;
-
- /*
-
- N == 2;
-
- W == 100px;
-
- */
}
div > div
{
background-color: lime;
float: left;
- height: 300px;
- width: 100px;
+ height: 10px;
+ width: 100%;
}
]]></style>
</head>
@@ -41,4 +35,4 @@
<div></div>
</div>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-overflow/input-scrollable-region-001.html b/tests/wpt/web-platform-tests/css/css-overflow/input-scrollable-region-001.html
new file mode 100644
index 00000000000..016f9b9278c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-overflow/input-scrollable-region-001.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Input Text Padding and Overflow: css-overflow-3</title>
+<link rel="author" title="Boaz Sender, Ali Juma, Robert Ma">
+<link rel="help" href="https://drafts.csswg.org/css-overflow-3/#scrollable">
+<link rel="match" href="reference/input-scrollable-region-001-ref.html">
+<meta name="assert" content="input text is preserved when the (input height
+ minus the input padding minus the input border) is
+ smaller than the height of the text">
+<style>
+input {
+ font-family: Ahem;
+ width: 100px;
+ margin: 0px;
+ border: 1px solid black;
+ height: 30px;
+ padding: 10px;
+ font-size: 18px;
+ box-sizing: border-box;
+ line-height: 1;
+}
+
+</style>
+<body>
+ <input type="text" value="foo">
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-overflow/reference/input-scrollable-region-001-ref.html b/tests/wpt/web-platform-tests/css/css-overflow/reference/input-scrollable-region-001-ref.html
new file mode 100644
index 00000000000..de894fab610
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-overflow/reference/input-scrollable-region-001-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Basic User Interface Reference File</title>
+<link rel="author" title="Boaz Sender, Ali Juma, Robert Ma">
+<style>
+input {
+ font-family: Ahem;
+ width: 100px;
+ margin: 0px;
+ border: 1px solid black;
+ height: 30px;
+ padding: 0px 10px;
+ font-size: 18px;
+ box-sizing: border-box;
+ line-height: 1;
+}
+
+</style>
+<body>
+ <input type="text" value="foo">
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-paint-api/geometry-with-float-size-ref.html b/tests/wpt/web-platform-tests/css/css-paint-api/geometry-with-float-size-ref.html
new file mode 100644
index 00000000000..c24a9d7bc0d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-paint-api/geometry-with-float-size-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id="canvas" width="100.5" height="200.5px"></canvas>
+</body>
+<script>
+var canvas = document.getElementById('canvas');
+var context = canvas.getContext('2d');
+context.fillStyle = 'green';
+context.fillRect(0, 0, 50, 50);
+</script>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-paint-api/geometry-with-float-size.https.html b/tests/wpt/web-platform-tests/css/css-paint-api/geometry-with-float-size.https.html
new file mode 100644
index 00000000000..6cd3ecada36
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-paint-api/geometry-with-float-size.https.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<link rel="match" href="geometry-with-float-size-ref.html">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/#dom-css-paintworklet">
+<style>
+.container {
+ width: 100.5px;
+ height: 200.5px;
+}
+#canvas-geometry {
+ background-image: paint(geometry);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/css-paint-tests.js"></script>
+<body>
+<div id="canvas-geometry" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('geometry', class {
+ paint(ctx, geom) {
+ if (geom.width == 101 && geom.height == 201)
+ ctx.fillStyle = 'green';
+ else
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, 50, 50);
+ }
+});
+</script>
+
+<script>
+ importPaintWorkletAndTerminateTestAfterAsyncPaint(document.getElementById('code').textContent);
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-paint-api/registered-properties-in-custom-paint.https.html b/tests/wpt/web-platform-tests/css/css-paint-api/registered-properties-in-custom-paint.https.html
index d77a33f0bc7..c446347557f 100644
--- a/tests/wpt/web-platform-tests/css/css-paint-api/registered-properties-in-custom-paint.https.html
+++ b/tests/wpt/web-platform-tests/css/css-paint-api/registered-properties-in-custom-paint.https.html
@@ -44,7 +44,7 @@ registerPaint('geometry', class {
ctx.strokeStyle = 'red';
if (serializedStrings[1] != "--length-initial: [CSSUnitValue=20px]")
ctx.strokeStyle = 'blue';
- if (serializedStrings[2] != "--number: [CSSStyleValue=10]")
+ if (serializedStrings[2] != "--number: [CSSUnitValue=10]")
ctx.strokeStyle = 'yellow';
ctx.lineWidth = 4;
ctx.strokeRect(0, 0, geom.width, geom.height);
diff --git a/tests/wpt/web-platform-tests/css/css-paint-api/style-background-image.https.html b/tests/wpt/web-platform-tests/css/css-paint-api/style-background-image.https.html
index 716c28c1606..cb894e57f2d 100644
--- a/tests/wpt/web-platform-tests/css/css-paint-api/style-background-image.https.html
+++ b/tests/wpt/web-platform-tests/css/css-paint-api/style-background-image.https.html
@@ -43,7 +43,7 @@ registerPaint('geometry', class {
ctx.strokeStyle = 'green';
if (serializedStrings[0] != "--bar: [null]")
ctx.strokeStyle = 'red';
- if (serializedStrings[1] != "--foo: [CSSStyleValue= bar]")
+ if (serializedStrings[1] != "--foo: [CSSUnparsedValue= bar]")
ctx.strokeStyle = 'blue';
if (serializedStrings[2] != "align-items: [CSSKeywordValue=normal]")
ctx.strokeStyle = 'yellow';
diff --git a/tests/wpt/web-platform-tests/css/css-paint-api/style-before-pseudo.https.html b/tests/wpt/web-platform-tests/css/css-paint-api/style-before-pseudo.https.html
index 8ba4cdbc612..707d02ba41d 100644
--- a/tests/wpt/web-platform-tests/css/css-paint-api/style-before-pseudo.https.html
+++ b/tests/wpt/web-platform-tests/css/css-paint-api/style-before-pseudo.https.html
@@ -46,7 +46,7 @@ registerPaint('geometry', class {
ctx.strokeStyle = 'green';
if (serializedStrings[0] != "--bar: [null]")
ctx.strokeStyle = 'red';
- if (serializedStrings[1] != "--foo: [CSSStyleValue= bar]")
+ if (serializedStrings[1] != "--foo: [CSSUnparsedValue= bar]")
ctx.strokeStyle = 'blue';
if (serializedStrings[2] != "border-radius: [CSSStyleValue=2px]")
ctx.strokeStyle = 'yellow';
diff --git a/tests/wpt/web-platform-tests/css/css-position/position-sticky-offset-overflow.html b/tests/wpt/web-platform-tests/css/css-position/position-sticky-offset-overflow.html
new file mode 100644
index 00000000000..f4afed406ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-position/position-sticky-offset-overflow.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<title>Sticky positioning can cause overflow but must be accessible.</title>
+<link rel="help" href="https://www.w3.org/TR/css-position-3/#sticky-pos" />
+<meta name="assert" content="This test checks that a sticky positioned element
+can cause overflow but must still be accessible through scrolling" />
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+.container {
+ overflow: scroll;
+ width: 100px;
+ height: 100px;
+}
+
+.box {
+ background-color: green;
+ height: 50px;
+ width: 50px;
+}
+
+.sticky {
+ position: sticky;
+ top: 200px; /* Forces the sticky position element below the overflow. */
+}
+</style>
+
+<div id="scroller1" class="container">
+ <div class="sticky box"></div>
+</div>
+
+<div id="scroller2" class="container">
+ <div class="sticky box"></div>
+</div>
+
+<script>
+test(() => {
+ var scroller = document.getElementById('scroller1');
+ var sticky = scroller.querySelector('.sticky');
+
+ var stickyOffset = sticky.offsetTop -
+ scroller.scrollTop - scroller.offsetTop;
+ assert_equals(stickyOffset, 200);
+ assert_equals(scroller.scrollHeight, 250);
+}, 'sticky position offset should be able to cause overflow');
+
+test(() => {
+ var scroller = document.getElementById('scroller2');
+ var sticky = scroller.querySelector('.sticky');
+
+ scroller.scrollTop = 150;
+ var stickyOffset = sticky.offsetTop -
+ scroller.scrollTop - scroller.offsetTop;
+ assert_equals(stickyOffset, 50);
+ // Scroll height should be unaffected.
+ assert_equals(scroller.scrollHeight, 250);
+
+}, 'sticky position offset in overflow should be accessible');
+</script>
diff --git a/tests/wpt/web-platform-tests/css/css-position/position-sticky-table-parts-ref.html b/tests/wpt/web-platform-tests/css/css-position/position-sticky-table-parts-ref.html
new file mode 100644
index 00000000000..e6988eef855
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-position/position-sticky-table-parts-ref.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<title>Nested position:sticky table elements should render correctly</title>
+<style>
+.scroller {
+ width: 100px;
+ height: 250px;
+ overflow-x: hidden;
+ overflow-y: auto;
+}
+
+.contents {
+ height: 700px;
+}
+
+table {
+ border-collapse: collapse;
+}
+
+#child, td, th {
+ height: 50px;
+ width: 50px;
+ padding: 0;
+ background: green;
+}
+
+.prepadding {
+ height: 155px;
+}
+
+</style>
+
+<script>
+window.addEventListener('load', function() {
+ document.getElementById('scroller1').scrollTop = 150;
+});
+</script>
+
+ <div id="scroller1" class="scroller">
+ <div class="contents">
+ <div class="prepadding"></div>
+ <table>
+ <tbody>
+ <tr><td><div id="child"></div></td></tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+<div>There should be a green square at the top of the scroll view and no red visible.</div>
diff --git a/tests/wpt/web-platform-tests/css/css-position/position-sticky-table-parts.html b/tests/wpt/web-platform-tests/css/css-position/position-sticky-table-parts.html
new file mode 100644
index 00000000000..c1cca833325
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-position/position-sticky-table-parts.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<title>Nested position:sticky table elements should render correctly</title>
+<link rel="match" href="position-sticky-table-parts-ref.html" />
+<link rel="help" href="https://www.w3.org/TR/css-position-3/#sticky-pos" />
+<meta name="assert" content="This test checks that nested position:sticky table elements render correctly" />
+
+<style>
+.scroller {
+ position: relative;
+ width: 100px;
+ height: 250px;
+ overflow-x: hidden;
+ overflow-y: auto;
+}
+
+.contents {
+ height: 700px;
+}
+
+table {
+ border-collapse: collapse;
+}
+
+.child, td, th {
+ height: 50px;
+ width: 50px;
+ padding: 0;
+}
+
+.child {
+ background: green;
+}
+
+table * {
+ position: sticky;
+ top: 5px;
+}
+
+.indicator {
+ position: absolute;
+ left: 0;
+ background-color: red;
+ height: 50px;
+ width: 50px;
+}
+
+</style>
+
+<script>
+window.addEventListener('load', function() {
+ document.body.offsetTop;
+ document.getElementById('scroller1').scrollTop = 150;
+});
+</script>
+
+<div id="scroller1" class="scroller">
+ <div class="contents">
+ <div class="indicator" style="top: 155px;"></div>
+ <table>
+ <tbody>
+ <tr><td><div class="child"></div></td></tr>
+ <tr><td></td></tr>
+ <tr><td></td></tr>
+ <tr><td></td></tr>
+ <tr><td></td></tr>
+ <tr><td></td></tr>
+ <tr><td></td></tr>
+ </tbody>
+ </table>
+ </div>
+</div>
+<div>There should be a green square at the top of the scroll view and no red visible.</div>
diff --git a/tests/wpt/web-platform-tests/css/css-pseudo/marker-font-properties-ref.html b/tests/wpt/web-platform-tests/css/css-pseudo/marker-font-properties-ref.html
index 093674d81b2..a8fb980ff09 100644
--- a/tests/wpt/web-platform-tests/css/css-pseudo/marker-font-properties-ref.html
+++ b/tests/wpt/web-platform-tests/css/css-pseudo/marker-font-properties-ref.html
@@ -5,6 +5,10 @@
<title>CSS Test: ::marker formatting with font properties reference file</title>
<link rel="author" title="Daniel Bates" href="mailto:dbates@webkit.org">
<style>
+ol {
+ line-height: 30px;
+}
+
li {
font-family: sans-serif;
font-size: 24px;
diff --git a/tests/wpt/web-platform-tests/css/css-pseudo/marker-font-properties.html b/tests/wpt/web-platform-tests/css/css-pseudo/marker-font-properties.html
index d2570eb3085..a108792fa20 100644
--- a/tests/wpt/web-platform-tests/css/css-pseudo/marker-font-properties.html
+++ b/tests/wpt/web-platform-tests/css/css-pseudo/marker-font-properties.html
@@ -8,6 +8,10 @@
<link rel="help" href="https://drafts.csswg.org/css-pseudo-4/#marker-pseudo">
<meta name="assert" content="Tests ::marker rendering with font properties">
<style>
+ol {
+ line-height: 30px;
+}
+
li {
list-style-type: lower-alpha;
}
diff --git a/tests/wpt/web-platform-tests/css/css-shapes/shape-outside/values/shape-image-threshold-003.html b/tests/wpt/web-platform-tests/css/css-shapes/shape-outside/values/shape-image-threshold-003.html
index b9395697c35..cb4027ce41a 100644
--- a/tests/wpt/web-platform-tests/css/css-shapes/shape-outside/values/shape-image-threshold-003.html
+++ b/tests/wpt/web-platform-tests/css/css-shapes/shape-outside/values/shape-image-threshold-003.html
@@ -42,7 +42,7 @@
test(function() {
var results = setUpTest("0.3", null);
- assert_equals(results[0], null);
+ assert_equals(results[0], "");
assert_equals(results[1], "0");
}, "shape-image-threshold is not inherited and defaults to 0");
diff --git a/tests/wpt/web-platform-tests/css/css-style-attr/reference/ref-green-on-green2.xht b/tests/wpt/web-platform-tests/css/css-style-attr/reference/ref-green-on-green2.xht
deleted file mode 100644
index 141069cfd6e..00000000000
--- a/tests/wpt/web-platform-tests/css/css-style-attr/reference/ref-green-on-green2.xht
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>CSS Reftest Reference</title>
- <link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact"/>
- <style type="text/css"><![CDATA[
- p { color: green; background: lime; }
- ]]></style>
- </head>
- <body>
- <p>This sentence must be green on a green background.</p>
- <p>This sentence must be green on a green background.</p>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/css/css-style-attr/style-attr-urls-003.xht b/tests/wpt/web-platform-tests/css/css-style-attr/style-attr-urls-003.xht
index 893790418ae..d1326f87747 100644
--- a/tests/wpt/web-platform-tests/css/css-style-attr/style-attr-urls-003.xht
+++ b/tests/wpt/web-platform-tests/css/css-style-attr/style-attr-urls-003.xht
@@ -1,28 +1,23 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
- <title>CSS Test: URLs in style attributes (with xml:base and &lt;base&gt;)</title>
- <base href="support/support/"/>
+ <title>CSS Test: URLs in style attributes (with xml:base)</title>
<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact"/>
<link rel="reviewer" title="Arron Eicholz" href="mailto:Arron.Eicholz@microsoft.com"/>
- <link rel="match" href="reference/ref-green-on-green2.xht" xml:base="../../"/>
- <link rel="help" href="http://www.w3.org/TR/css-style-attr/#interpret"/>
- <link rel="help" href="http://www.w3.org/TR/xmlbase"/>
+ <link rel="match" href="reference/ref-green-on-green.xht"/>
+ <link rel="help" href="https://drafts.csswg.org/css-style-attr/#interpret"/>
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="flags" content="image nonHTML" />
- <meta name="assert" content="In the presence of xml:base URL manipulation, URLs in style attributes are relative to the base of the element."/>
+ <meta name="assert" content="xml:base is ignored when resolving URLs in style attributes."/>
+ <!-- This test originally asserted that xml:base works, and xml:base is mentioned in
+ https://www.w3.org/TR/2013/REC-css-style-attr-20131107/. Support for xml:base
+ has been removed from browsers and it's no longer mentioned in the spec. -->
<style type="text/css"><![CDATA[
- p { background: red; color: green; }
- img { background: red; color: white; vertical-align: middle; }
+ p { background-color: lime; color: green; }
]]></style>
</head>
<body>
- <p style="background-image: url(swatch-lime.png)" xml:base="../">
+ <p style="background-image: url(swatch-red.png)" xml:base="support/">
This sentence must be green on a green background.
- <img src="support/swatch-lime.png" alt="[Your UA does not support xml:base. This test is therefore Not Applicable.]"/>
- </p>
- <p xml:base="../" style="background-image: url(swatch-lime.png)">
- This sentence must be green on a green background.
- <img src="support/swatch-lime.png" alt="[Your UA does not support xml:base. This test is therefore Not Applicable.]"/>
</p>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/css-tables/zero-rowspan-001-ref.html b/tests/wpt/web-platform-tests/css/css-tables/zero-rowspan-001-ref.html
new file mode 100644
index 00000000000..4f1dbdf96d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-tables/zero-rowspan-001-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<title>CSS Test: Reference Test</title>
+<link rel="author" title="Robert Hogan" href="mailto:robhogan@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/tables.html#attributes-common-to-td-and-th-elements">
+<table>
+ <tr><td rowspan="4">Foo</td></tr>
+ <tr><td>Foo</td></tr>
+ <tr><td>Foo</td></tr>
+ <tr><td>Foo</td></tr>
+</table>
+
diff --git a/tests/wpt/web-platform-tests/css/css-tables/zero-rowspan-001.html b/tests/wpt/web-platform-tests/css/css-tables/zero-rowspan-001.html
new file mode 100644
index 00000000000..bef5b947fcc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-tables/zero-rowspan-001.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<title>CSS Test: Overflow clipping in cells that span columns</title>
+<link rel="author" title="Robert Hogan" href="mailto:robhogan@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/tables.html#attributes-common-to-td-and-th-elements">
+<link rel="match" href="zero-rowspan-001-ref.html">
+<table>
+ <tr><td rowspan="0">Foo</td></tr>
+ <tr><td>Foo</td></tr>
+ <tr><td>Foo</td></tr>
+ <tr><td>Foo</td></tr>
+</table>
+
diff --git a/tests/wpt/web-platform-tests/css/css-tables/zero-rowspan-002-ref.html b/tests/wpt/web-platform-tests/css/css-tables/zero-rowspan-002-ref.html
new file mode 100644
index 00000000000..3ccac78bd82
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-tables/zero-rowspan-002-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<title>CSS Test: Reference Test</title>
+<link rel="author" title="Robert Hogan" href="mailto:robhogan@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/tables.html#attributes-common-to-td-and-th-elements">
+<table>
+ <tr><td rowspan="3">1</td><td>2</td><td>3</td></tr>
+ <tr><td>1</td><td rowspan="2">2</td><td>3</td></tr>
+ <tr><td>1</td><td>2</td><td>3</td></tr>
+</table>
diff --git a/tests/wpt/web-platform-tests/css/css-tables/zero-rowspan-002.html b/tests/wpt/web-platform-tests/css/css-tables/zero-rowspan-002.html
new file mode 100644
index 00000000000..7a79fc37b0a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-tables/zero-rowspan-002.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<title>CSS Test: Overflow clipping in cells that span columns</title>
+<link rel="author" title="Robert Hogan" href="mailto:robhogan@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/tables.html#attributes-common-to-td-and-th-elements">
+<link rel="match" href="zero-rowspan-002-ref.html">
+<table>
+ <tr><td rowspan="0">1</td><td>2</td><td>3</td></tr>
+ <tr><td>1</td><td rowspan="0">2</td><td>3</td></tr>
+ <tr><td>1</td><td>2</td><td>3</td></tr>
+</table>
+
diff --git a/tests/wpt/web-platform-tests/css/css-text-decor/line-through-vertical.html b/tests/wpt/web-platform-tests/css/css-text-decor/line-through-vertical.html
new file mode 100644
index 00000000000..633c5c00392
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-text-decor/line-through-vertical.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<link rel="help" href="https://www.w3.org/TR/css-text-decor-3/#text-decoration-line">
+<link rel="help" href="https://www.w3.org/TR/css-writing-modes-3/#propdef-writing-mode">
+<link rel="match" href="reference/line-through-vertical-ref.html">
+<style>
+div {
+ writing-mode: vertical-rl;
+ text-decoration: line-through;
+ font-family: Times;
+ font-size: 50px;
+}
+</style>
+<div>
+ <span lang="ja">ABC</span>
+ <span lang="en">ABC</span>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-text-decor/reference/line-through-vertical-ref.html b/tests/wpt/web-platform-tests/css/css-text-decor/reference/line-through-vertical-ref.html
new file mode 100644
index 00000000000..979512787a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-text-decor/reference/line-through-vertical-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<style>
+div {
+ writing-mode: vertical-rl;
+ text-decoration: line-through;
+ font-family: Times;
+ font-size: 50px;
+}
+</style>
+<div>
+ <span lang="en">ABC</span>
+ <span lang="en">ABC</span>
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-text-decor/reference/text-decoration-color-recalc-ref.html b/tests/wpt/web-platform-tests/css/css-text-decor/reference/text-decoration-color-recalc-ref.html
new file mode 100644
index 00000000000..7bc557337f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-text-decor/reference/text-decoration-color-recalc-ref.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<style>
+ div {
+ font-size: 50px;
+ text-decoration: underline solid green;
+ }
+</style>
+<p>Test that changes in text-decoration-color are recalculated correctly. PASS
+if the text below has a solid green underline, and no red.</p>
+<div id="target">
+ Filler text
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-text-decor/reference/text-decoration-color-ref.html b/tests/wpt/web-platform-tests/css/css-text-decor/reference/text-decoration-color-ref.html
new file mode 100644
index 00000000000..33272cbe1da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-text-decor/reference/text-decoration-color-ref.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>CSS Test: CSS3 text-decoration-color</title>
+ <style>
+ .underline {
+ text-decoration: underline;
+ }
+ .overline {
+ text-decoration: overline;
+ }
+ .line-through {
+ text-decoration: line-through;
+ }
+ .black-fill {
+ -webkit-text-fill-color: black;
+ }
+ .transparent-fill {
+ -webkit-text-fill-color: transparent;
+ -webkit-text-stroke-width: 1px;
+ -webkit-text-stroke-color: black;
+ }
+ </style>
+ </head>
+ <body>
+ <h3>Each line of this test should match its text decoration color description:</h3>
+ <div class="underline" style="color: blue;"><span style="-webkit-text-fill-color: gray;">Gray text with blue underline</span></div><br/>
+ <div class="overline" style="color: black;"><span style="-webkit-text-fill-color: green;">Green text with black overline</span></div><br/>
+ <div class="line-through" style="color: gold;"><span style="-webkit-text-fill-color: black;">Black text with gold line-through</span></div><br/>
+ <div class="underline" style="color: blue;">
+ <span class="overline" style="color: gray;">
+ <span class="line-through" style="color: green;">
+ <span class="black-fill">Black text with blue underline, gray overline and green line-through</span>
+ </span>
+ </span>
+ </div><br/>
+ <div class="line-through" style="color: green;">
+ <sub class="overline" style="color: gray;"><span class="black-fill">subscript text</span></sub>
+ <sup class="underline" style="color: blue;"><span class="black-fill">superscript text</span></sup>
+ </div><br/>
+ <div class="underline" style="color: green;"><span class="transparent-fill">Transparent fill with black stroke text and green underline</span></div><br/>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-text-decor/reference/text-decoration-line-recalc-ref.html b/tests/wpt/web-platform-tests/css/css-text-decor/reference/text-decoration-line-recalc-ref.html
new file mode 100644
index 00000000000..92baa6bf433
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-text-decor/reference/text-decoration-line-recalc-ref.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<style>
+ div {
+ font-size: 50px;
+ text-decoration: overline solid green;
+ }
+</style>
+<p>Test that changes in text-decoration-line are recalculated correctly. PASS
+if the text below has a solid green overline, and no underline.</p>
+<div id="target">
+ Filler text
+</div> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/css-text-decor/reference/text-decoration-line-ref.html b/tests/wpt/web-platform-tests/css/css-text-decor/reference/text-decoration-line-ref.html
new file mode 100644
index 00000000000..f14d25a70ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-text-decor/reference/text-decoration-line-ref.html
@@ -0,0 +1,33 @@
+<html>
+<head>
+ <style>
+ .none { text-decoration: none; }
+ .underline { text-decoration: underline; }
+ .overline { text-decoration: overline; }
+ .line-through { text-decoration: line-through; }
+ .all-decorations { text-decoration: underline overline line-through; }
+ </style>
+</head>
+<body>
+ <div>Each line of this test should match its style description (<i>text-decoration-line</i> resets <i>text-decoration</i>, except when the latter is set as <i>important</i>):</div><br/>
+ <div class="underline">This text is underlined <span>(also inside span).</span></div><br/>
+ <div class="overline">This text is overlined <span>(also inside span).</span></div><br/>
+ <div class="line-through">This text has a line-through <span>(also inside span).</span></div><br/>
+ <div class="none">This text contains no decorations.</div><br/>
+ <div class="underline">This text is underlined.</div><br/>
+ <div class="none">This text contains no decorations.</div><br/>
+ <div class="overline">This text is overlined.</div><br/>
+ <div class="none">This text contains no decorations.</div><br/>
+ <div class="line-through">This text has a line-through.</div><br/>
+ <div class="none">This text contains no decorations.</div><br/>
+ <div class="all-decorations">This text is underlined, overlined and has a line-through.</div><br/>
+ <div class="none">This text contains no decorations.</div><br/>
+ <div class="overline">This text is overlined.</div><br/>
+ <div class="overline">This text is overlined.</div><br/>
+ <div class="underline">This text is underlined.</div>
+ <div class="none">This text contains no decorations.</div><br/>
+ <div class="none">This text contains no decorations.</div><br/>
+ <div class="none">This text contains no decorations.</div><br/>
+ <div class="none">This text contains no decorations.</div><br/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-text-decor/reference/text-decoration-style-multiple-ref.html b/tests/wpt/web-platform-tests/css/css-text-decor/reference/text-decoration-style-multiple-ref.html
new file mode 100644
index 00000000000..f80396930e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-text-decor/reference/text-decoration-style-multiple-ref.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<style>
+ div {
+ color: #aaa;
+ font-size: 50px;
+ position: relative;
+ display: inline-block;
+ width: 200px;
+ height: 200px;
+ }
+
+ div > span { position: absolute; }
+
+ div > span:nth-child(1) { text-decoration: underline solid coral; }
+ div > span:nth-child(2) { text-decoration: overline dashed skyblue; }
+ div > span:nth-child(3) { text-decoration: line-through wavy green; }
+
+</style>
+<div><span>AAAA</span><span>AAAA</span><span>AAAA</span></div>
diff --git a/tests/wpt/web-platform-tests/css/css-text-decor/reference/text-decoration-style-recalc-ref.html b/tests/wpt/web-platform-tests/css/css-text-decor/reference/text-decoration-style-recalc-ref.html
new file mode 100644
index 00000000000..30592b44cec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-text-decor/reference/text-decoration-style-recalc-ref.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<style>
+ div {
+ font-size: 50px;
+ text-decoration: underline dashed green;
+ }
+</style>
+<p>Test that changes in text-decoration-style are recalculated correctly. PASS
+if the text below has a dashed green underline, and not a solid green underline.</p>
+<div id="target">
+ Filler text
+</div> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-color-recalc.html b/tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-color-recalc.html
new file mode 100644
index 00000000000..b7cde934fcf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-color-recalc.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<link rel="help" href="https://www.w3.org/TR/css-text-decor-3/#text-decoration-color">
+<link rel="match" href="reference/text-decoration-color-recalc-ref.html">
+<style>
+ div {
+ font-size: 50px;
+ text-decoration: underline solid red;
+ }
+</style>
+<script>
+ onload = function() {
+ target.style.textDecorationColor = "green";
+ };
+</script>
+<p>Test that changes in text-decoration-color are recalculated correctly. PASS
+if the text below has a solid green underline, and no red.</p>
+<div id="target">
+ Filler text
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-color.html b/tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-color.html
new file mode 100644
index 00000000000..fd5bc5da3a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-color.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>CSS Test: CSS3 text-decoration-color</title>
+ <link rel="help" href="https://www.w3.org/TR/css-text-decor-3/#text-decoration-color">
+ <link rel="match" href="reference/text-decoration-color-ref.html">
+ <style>
+ .underline {
+ text-decoration: underline;
+ }
+ .overline {
+ text-decoration: overline;
+ }
+ .line-through {
+ text-decoration: line-through;
+ }
+ #blue-underline {
+ text-decoration: underline;
+ text-decoration-color: blue;
+ }
+ #gray-overline {
+ text-decoration: overline;
+ text-decoration-color: gray;
+ }
+ #green-line-through {
+ text-decoration: line-through;
+ text-decoration-color: green;
+ }
+ #transparent-fill {
+ -webkit-text-fill-color: transparent;
+ -webkit-text-stroke-width: 1px;
+ -webkit-text-stroke-color: black;
+ }
+ </style>
+ </head>
+ <body>
+ <h3>Each line of this test should match its text decoration color description:</h3>
+
+ <!-- Valid values for underline, overline and line-through text decoration lines -->
+ <div class="underline" style="color: gray; text-decoration-color: blue;">Gray text with blue underline</div><br/>
+ <div class="overline" style="color: green; text-decoration-color: black;">Green text with black overline</div><br/>
+ <div class="line-through" style="text-decoration-color: gold;">Black text with gold line-through</div><br/>
+
+ <!-- Mix of underline, overline and line-through with different colors for each -->
+ <div>
+ <span id="blue-underline">
+ <span id="gray-overline">
+ <span id="green-line-through">Black text with blue underline, gray overline and green line-through</span>
+ </span>
+ </span>
+ </div><br/>
+
+ <!-- Test behavior on subscript and superscript text -->
+ <div>
+ <span id="green-line-through">
+ <sub id="gray-overline">subscript text</sub>
+ <sup id="blue-underline">superscript text</sup>
+ </span>
+ </div><br/>
+
+ <!-- Test with text-fill-color and text-stroke-color values set -->
+ <div class="underline" id="transparent-fill" style="text-decoration-color: green;">Transparent fill with black stroke text and green underline</div><br/>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-line-recalc.html b/tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-line-recalc.html
new file mode 100644
index 00000000000..321aea9f3d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-line-recalc.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<link rel="help" href="https://www.w3.org/TR/css-text-decor-3/#text-decoration-line">
+<link rel="match" href="reference/text-decoration-line-recalc-ref.html">
+<style>
+ div {
+ font-size: 50px;
+ text-decoration: underline solid green;
+ }
+</style>
+<script>
+ onload = function() {
+ target.style.textDecorationLine = "overline";
+ };
+</script>
+<p>Test that changes in text-decoration-line are recalculated correctly. PASS
+if the text below has a solid green overline, and no underline.</p>
+<div id="target">
+ Filler text
+</div> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-line.html b/tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-line.html
new file mode 100644
index 00000000000..ea6a0c86c19
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-line.html
@@ -0,0 +1,35 @@
+<html>
+<head>
+ <link rel="help" href="https://www.w3.org/TR/css-text-decor-3/#text-decoration-line">
+ <link rel="match" href="reference/text-decoration-line-ref.html">
+ <style>
+ .none { text-decoration: none; }
+ .underline { text-decoration: underline; }
+ .overline { text-decoration: overline; }
+ .line-through { text-decoration: line-through; }
+ .all-decorations { text-decoration: underline overline line-through; }
+ </style>
+</head>
+<body>
+ <div>Each line of this test should match its style description (<i>text-decoration-line</i> resets <i>text-decoration</i>, except when the latter is set as <i>important</i>):</div><br/>
+ <div style="text-decoration-line: underline;">This text is underlined <span class="none">(also inside span).</span></div><br/>
+ <div style="text-decoration-line: overline;">This text is overlined <span class="none">(also inside span).</span></div><br/>
+ <div style="text-decoration-line: line-through;">This text has a line-through <span class="none">(also inside span).</span></div><br/>
+ <div class="underline" style="text-decoration-line: none;">This text contains no decorations.</div><br/>
+ <div class="underline" style="text-decoration-line: underline;">This text is underlined.</div><br/>
+ <div class="overline" style="text-decoration-line: none;">This text contains no decorations.</div><br/>
+ <div class="overline" style="text-decoration-line: overline;">This text is overlined.</div><br/>
+ <div class="line-through" style="text-decoration-line: none;">This text contains no decorations.</div><br/>
+ <div class="line-through" style="text-decoration-line: line-through;">This text has a line-through.</div><br/>
+ <div class="all-decorations" style="text-decoration-line: none;">This text contains no decorations.</div><br/>
+ <div class="all-decorations" style="text-decoration-line: underline overline line-through;">This text is underlined, overlined and has a line-through.</div><br/>
+ <div style="text-decoration-line: underline; text-decoration: none !important;">This text contains no decorations.</div><br/>
+ <div style="text-decoration-line: underline; text-decoration: overline !important;">This text is overlined.</div><br/>
+ <div style="text-decoration-line: underline !important; text-decoration: overline !important;">This text is overlined.</div><br/>
+ <div style="text-decoration: overline !important; text-decoration-line: underline !important;">This text is underlined.</div>
+ <div style="text-decoration-line: blink blink;">This text contains no decorations.</div><br/>
+ <div style="text-decoration-line: blink underline blink;">This text contains no decorations.</div><br/>
+ <div style="text-decoration-line: blink underline overline blink;">This text contains no decorations.</div><br/>
+ <div style="text-decoration-line: blink underline overline line-through blink;">This text contains no decorations.</div><br/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-serialization.tentative.html b/tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-serialization.tentative.html
new file mode 100644
index 00000000000..2f7b2f55fea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-serialization.tentative.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<title>text-decoration shorthand serialization</title>
+<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#text-decoration-property">
+<link rel="help" href="https://drafts.csswg.org/cssom/#serialize-a-css-declaration-block">
+<script type="text/javascript" src="/resources/testharness.js"></script>
+<script type="text/javascript" src="/resources/testharnessreport.js"></script>
+<div style="text-decoration: underline"></div>
+<script>
+test(() => {
+ const style = getComputedStyle(document.querySelector('div'));
+ // Chrome serializes as "underline solid rgb(0, 0, 0)" while Edge, Firefox an
+ // Safari use "underline", which Chrome used to do as well. The spec should
+ // probably require "underline":
+ // https://github.com/w3c/csswg-drafts/issues/1564
+ assert_equals(style.getPropertyValue("text-decoration"), "underline");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-style-multiple.html b/tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-style-multiple.html
new file mode 100644
index 00000000000..567229f6e57
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-style-multiple.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<link rel="help" href="https://www.w3.org/TR/css-text-decor-3/#text-decoration-style">
+<link rel="match" href="reference/text-decoration-style-multiple-ref.html">
+<style>
+ div {
+ color: #aaa;
+ font-size: 50px;
+ position: relative;
+ display: inline-block;
+ width: 200px;
+ height: 200px;
+ }
+
+ div > span { position: absolute; }
+
+ div > span:nth-child(3) { text-decoration: underline solid coral; }
+ div > span:nth-child(3) > span { text-decoration: overline dashed skyblue; }
+ div > span:nth-child(3) > span > span { text-decoration: line-through wavy green; }
+
+</style>
+<div><span>AAAA</span><span>AAAA</span><span><span><span>AAAA</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-style-recalc.html b/tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-style-recalc.html
new file mode 100644
index 00000000000..d4538e7c7b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-text-decor/text-decoration-style-recalc.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<link rel="help" href="https://www.w3.org/TR/css-text-decor-3/#text-decoration-style">
+<link rel="match" href="reference/text-decoration-style-recalc-ref.html">
+<style>
+ div {
+ font-size: 50px;
+ text-decoration: underline solid green;
+ }
+</style>
+<script>
+ onload = function() {
+ target.style.textDecorationStyle = "dashed";
+ };
+</script>
+<p>Test that changes in text-decoration-style are recalculated correctly. PASS
+if the text below has a dashed green underline, and not a solid green underline.</p>
+<div id="target">
+ Filler text
+</div>
diff --git a/tests/wpt/web-platform-tests/css/css-transforms/css-transform-inherit-scale.html b/tests/wpt/web-platform-tests/css/css-transforms/css-transform-inherit-scale.html
index b4702f8fda2..fa9b5bbbc02 100644
--- a/tests/wpt/web-platform-tests/css/css-transforms/css-transform-inherit-scale.html
+++ b/tests/wpt/web-platform-tests/css/css-transforms/css-transform-inherit-scale.html
@@ -1,50 +1,49 @@
<!DOCTYPE html>
<html>
-<head>
+ <head>
<title>CSS Transforms Test: CSS transforms scale 2 inheritance on div elements</title>
<link rel="author" title="Delong Gao" href="mailto:gaodl@uw.edu">
<link rel="reviewer" title="Rebecca Hauck" href="mailto:rhauck@adobe.com">
<link rel="help" href="http://www.w3.org/TR/css-transforms-1/#transform-property">
<link rel="help" href="http://www.w3.org/TR/css-transforms-1/#two-d-transform-functions">
- <!--<link rel="match" href="reference/ttwf-reftest-tutorial-ref.html">
- <meta name="flags" content="svg">-->
+ <link rel="match" href="../reference/ref-filled-green-200px-square.html">
<meta name="assert" content="While child div inherits property from its parent, scaling 2 on parent div will course the child to scale 4 and totally cover the red div. The test passes if there is a green square and no red. ">
<style type="text/css">
- * {
- margin: 0;
- padding: 0;
- }
- .red {
- position: absolute;
- width: 200px;
- height: 200px;
- background-color: red;
- }
- .parent {
- background: yellow;
- width: 50px;
- height: 50px;
- position: absolute;
- top: 75px;
- left: 75px;
- transform: scale(2);
+ .test {
+ position: relative;
+ }
+ .red {
+ position: absolute;
+ width: 200px;
+ height: 200px;
+ background-color: red;
+ }
+ .parent {
+ background: yellow;
+ width: 50px;
+ height: 50px;
+ position: absolute;
+ top: 75px;
+ left: 75px;
+ transform: scale(2);
- }
- .child {
- position: absolute;
- top: 10px;
- transform: inherit;
- width: 50px;
- height: 50px;
- background-color: green;
- }
+ }
+ .child {
+ position: absolute;
+ transform: inherit;
+ width: 50px;
+ height: 50px;
+ background-color: green;
+ }
</style>
-</head>
-<body>
- <p>The test passes if there is a green square and no red. </p>
- <div class="red"></div>
- <div class="parent">
- <div class="child"></div>
- </div>
-</body>
+ </head>
+ <body>
+ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+ <div class="test">
+ <div class="red"></div>
+ <div class="parent">
+ <div class="child"></div>
+ </div>
+ </div>
+ </body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/css-transforms/transform-2d-getComputedStyle-001.html b/tests/wpt/web-platform-tests/css/css-transforms/transform-2d-getComputedStyle-001.html
index 543dd9a1fee..a085b794fc4 100644
--- a/tests/wpt/web-platform-tests/css/css-transforms/transform-2d-getComputedStyle-001.html
+++ b/tests/wpt/web-platform-tests/css/css-transforms/transform-2d-getComputedStyle-001.html
@@ -45,15 +45,6 @@
transform: matrix(1, 2, 3, 4, 5, 6);
}
</style>
- <script id="metadata_cache">/*
- {
- "Matrix for translation transforms": {},
- "Matrix for rotate": {},
- "Matrix for scaling": {},
- "Matrix for skew": {},
- "Matrix for general transform": {}
- }
- */</script>
<script type="text/javascript" src="/resources/testharness.js"></script>
<script type="text/javascript" src="/resources/testharnessreport.js"></script>
</head>
diff --git a/tests/wpt/web-platform-tests/css/css-transforms/transform-box/fill-box-mutation.html b/tests/wpt/web-platform-tests/css/css-transforms/transform-box/fill-box-mutation.html
new file mode 100644
index 00000000000..ae602e3509d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-transforms/transform-box/fill-box-mutation.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>transform-box: fill-box, shape mutated</title>
+<link rel="match" href="support/greensquare200x200.html">
+<link rel="help" href="https://drafts.csswg.org/css-transforms/#transform-box">
+<style>
+#target {
+ transform-box: fill-box;
+ transform: translate(-50%, 0);
+}
+</style>
+<p>There should be a green 200x200 rectangle below, and no red.</p>
+<svg width="400" height="200">
+ <rect width="200" height="200" fill="red"/>
+ <rect id="target" x="100" width="100" height="200" fill="green"/>
+</svg>
+<script>
+requestAnimationFrame(function() {
+ requestAnimationFrame(function() {
+ document.querySelector('#target').setAttribute('width', 200);
+ document.documentElement.classList.remove('reftest-wait');
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/css/css-transforms/transform-box/fill-box.html b/tests/wpt/web-platform-tests/css/css-transforms/transform-box/fill-box.html
new file mode 100644
index 00000000000..eaea02a5dfe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-transforms/transform-box/fill-box.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>transform-box: fill-box</title>
+<link rel="match" href="support/greensquare200x200.html">
+<link rel="help" href="https://drafts.csswg.org/css-transforms/#transform-box">
+<style>
+svg {
+ background-color: red;
+}
+rect {
+ transform-box: fill-box;
+}
+#target1 {
+ transform: rotate(90deg);
+}
+#target2 {
+ transform: translate(50%, -50%);
+}
+#target3 {
+ transform-origin: 25% 25%;
+ transform: rotate(180deg) translate(-25%, -25%);
+}
+#target4 {
+ transform-origin: 75px 75px;
+ transform: rotate(-180deg) translate(-25%, -25%);
+}
+</style>
+<p>There should be a green 200x200 rectangle below, and no red.</p>
+<svg width="200" height="200">
+ <rect id="target1" x="100" y="100" width="100" height="100" fill="green"/>
+ <rect id="target2" x="50" y="50" width="100" height="100" fill="green"/>
+ <rect id="target3" x="25" y="25" width="100" height="100" fill="green"/>
+ <rect id="target4" x="25" y="25" width="100" height="100" fill="green"/>
+</svg>
diff --git a/tests/wpt/web-platform-tests/css/css-transforms/transform-box/support/greensquare200x200.html b/tests/wpt/web-platform-tests/css/css-transforms/transform-box/support/greensquare200x200.html
new file mode 100644
index 00000000000..bee8bc70fe5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-transforms/transform-box/support/greensquare200x200.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<p>There should be a green 200x200 rectangle below, and no red.</p>
+<div style="width: 200px; height: 200px; background-color: green"></div>
diff --git a/tests/wpt/web-platform-tests/css/css-transforms/transform-box/value-changed.html b/tests/wpt/web-platform-tests/css/css-transforms/transform-box/value-changed.html
new file mode 100644
index 00000000000..825403ef7b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-transforms/transform-box/value-changed.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>transform-box: value change from 'view-box' to 'fill-box'</title>
+<link rel="match" href="support/greensquare200x200.html">
+<link rel="help" href="https://drafts.csswg.org/css-transforms/#transform-box">
+<p>There should be a green 200x200 rectangle below, and no red.</p>
+<svg width="400" height="200">
+ <rect width="200" height="200" fill="red"/>
+ <rect id="target" x="100" width="200" height="200" fill="green"
+ style="transform-box: view-box; transform: translateX(-50%)"/>
+</svg>
+<script>
+requestAnimationFrame(function() {
+ requestAnimationFrame(function() {
+ document.querySelector('#target').style.transformBox = 'fill-box';
+ document.documentElement.classList.remove('reftest-wait');
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/css/css-transforms/transform-box/view-box-nested.html b/tests/wpt/web-platform-tests/css/css-transforms/transform-box/view-box-nested.html
new file mode 100644
index 00000000000..7f59777f15b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-transforms/transform-box/view-box-nested.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>transform-box: view-box, relative to nested viewport</title>
+<link rel="match" href="support/greensquare200x200.html">
+<link rel="help" href="https://drafts.csswg.org/css-transforms/#transform-box">
+<style>
+#target {
+ transform-box: view-box;
+ transform: translate(-50%, -50%);
+}
+</style>
+<p>There should be a green 200x200 rectangle below, and no red.</p>
+<svg width="400" height="200">
+ <rect width="200" height="200" fill="red"/>
+ <svg width="200" height="200">
+ <rect id="target" x="100" y="100" width="200" height="200" fill="green"/>
+ </svg>
+</svg>
diff --git a/tests/wpt/web-platform-tests/css/css-transforms/transform-box/view-box-viewbox-nested.html b/tests/wpt/web-platform-tests/css/css-transforms/transform-box/view-box-viewbox-nested.html
new file mode 100644
index 00000000000..4f667e20ba8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-transforms/transform-box/view-box-viewbox-nested.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>transform-box: view-box, relative to viewport defined by nested viewBox</title>
+<link rel="match" href="support/greensquare200x200.html">
+<link rel="help" href="https://drafts.csswg.org/css-transforms/#transform-box">
+<style>
+#target {
+ transform-box: view-box;
+ transform: translate(-50%, -50%);
+}
+</style>
+<p>There should be a green 200x200 rectangle below, and no red.</p>
+<svg width="400" height="200">
+ <rect width="200" height="200" fill="red"/>
+ <svg viewBox="0 0 200 200" preserveAspectRatio="xMinYMin">
+ <rect id="target" x="100" y="100" width="200" height="200" fill="green"/>
+ </svg>
+</svg>
diff --git a/tests/wpt/web-platform-tests/css/css-transforms/transform-box/view-box-viewbox.html b/tests/wpt/web-platform-tests/css/css-transforms/transform-box/view-box-viewbox.html
new file mode 100644
index 00000000000..cd040c1ba33
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-transforms/transform-box/view-box-viewbox.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>transform-box: view-box, relative to viewport defined by viewBox</title>
+<link rel="match" href="support/greensquare200x200.html">
+<link rel="help" href="https://drafts.csswg.org/css-transforms/#transform-box">
+<style>
+#target {
+ transform-box: view-box;
+ transform: translate(-50%, -50%);
+}
+</style>
+<p>There should be a green 200x200 rectangle below, and no red.</p>
+<svg width="400" height="200" viewBox="0 0 200 200" preserveAspectRatio="xMinYMin">
+ <rect width="200" height="200" fill="red"/>
+ <rect id="target" x="100" y="100" width="200" height="200" fill="green"/>
+</svg>
diff --git a/tests/wpt/web-platform-tests/css/css-transforms/transform-box/view-box.html b/tests/wpt/web-platform-tests/css/css-transforms/transform-box/view-box.html
new file mode 100644
index 00000000000..3345467c904
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-transforms/transform-box/view-box.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>transform-box: view-box</title>
+<link rel="match" href="support/greensquare200x200.html">
+<link rel="help" href="https://drafts.csswg.org/css-transforms/#transform-box">
+<style>
+svg {
+ background-color: red;
+}
+rect {
+ transform-box: view-box;
+}
+#target1 {
+ transform-origin: 25% 25%;
+ transform: scale(2);
+}
+#target2 {
+ transform: translate(50%, 0);
+}
+#target3 {
+ transform: translate(0, 50%);
+}
+#target4 {
+ transform-origin: 50% 50%;
+ transform: rotate(180deg);
+}
+</style>
+<p>There should be a green 200x200 rectangle below, and no red.</p>
+<svg width="200" height="200">
+ <rect id="target1" x="25" y="25" width="50" height="50" fill="green"/>
+ <rect id="target2" width="100" height="100" fill="green"/>
+ <rect id="target3" width="100" height="100" fill="green"/>
+ <rect id="target4" width="100" height="100" fill="green"/>
+</svg>
diff --git a/tests/wpt/web-platform-tests/css/css-transitions/before-DOMContentLoaded-001.html b/tests/wpt/web-platform-tests/css/css-transitions/before-DOMContentLoaded-001.html
index 4e6c3d112d3..152f77760cf 100644
--- a/tests/wpt/web-platform-tests/css/css-transitions/before-DOMContentLoaded-001.html
+++ b/tests/wpt/web-platform-tests/css/css-transitions/before-DOMContentLoaded-001.html
@@ -26,13 +26,6 @@
height: 100000px;
}
</style>
-
- <script id="metadata_cache">/*
- {
- "transition height from 10px to 100px / values": {},
- "transition height from 10px to 100px / events": {}
- }
- */</script>
</head>
<body>
<!-- required by testharnessreport.js -->
diff --git a/tests/wpt/web-platform-tests/css/css-transitions/before-load-001.html b/tests/wpt/web-platform-tests/css/css-transitions/before-load-001.html
index 4cb43708978..ee633cf37c4 100644
--- a/tests/wpt/web-platform-tests/css/css-transitions/before-load-001.html
+++ b/tests/wpt/web-platform-tests/css/css-transitions/before-load-001.html
@@ -26,13 +26,6 @@
height: 100000px;
}
</style>
-
- <script id="metadata_cache">/*
- {
- "transition height from 10px to 100px / values": {},
- "transition height from 10px to 100px / events": {}
- }
- */</script>
</head>
<body>
<!-- required by testharnessreport.js -->
diff --git a/tests/wpt/web-platform-tests/css/css-transitions/changing-while-transition.html b/tests/wpt/web-platform-tests/css/css-transitions/changing-while-transition.html
index 99a2bea201d..2e7d0bb1bf7 100644
--- a/tests/wpt/web-platform-tests/css/css-transitions/changing-while-transition.html
+++ b/tests/wpt/web-platform-tests/css/css-transitions/changing-while-transition.html
@@ -25,13 +25,6 @@
height: 100000px;
}
</style>
-
- <script id="metadata_cache">/*
- {
- "changing transition-duration / values": {},
- "changing transition-property / values": {}
- }
- */</script>
</head>
<body>
<!-- required by testharnessreport.js -->
diff --git a/tests/wpt/web-platform-tests/css/css-transitions/currentcolor-animation-001.html b/tests/wpt/web-platform-tests/css/css-transitions/currentcolor-animation-001.html
index 138fec656b7..e36e7481506 100644
--- a/tests/wpt/web-platform-tests/css/css-transitions/currentcolor-animation-001.html
+++ b/tests/wpt/web-platform-tests/css/css-transitions/currentcolor-animation-001.html
@@ -9,7 +9,6 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style id="style"></style>
-<script id="metadata_cache"></script>
</head>
<body onload="run()">
<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/css/css-transitions/detached-container-001.html b/tests/wpt/web-platform-tests/css/css-transitions/detached-container-001.html
index 096147ea06f..efbc34f7774 100644
--- a/tests/wpt/web-platform-tests/css/css-transitions/detached-container-001.html
+++ b/tests/wpt/web-platform-tests/css/css-transitions/detached-container-001.html
@@ -26,13 +26,6 @@
height: 100000px;
}
</style>
-
- <script id="metadata_cache">/*
- {
- "transition within detached container / values": {},
- "transition within detached container / events": {}
- }
- */</script>
</head>
<body>
<!-- required by testharnessreport.js -->
diff --git a/tests/wpt/web-platform-tests/css/css-transitions/hidden-container-001.html b/tests/wpt/web-platform-tests/css/css-transitions/hidden-container-001.html
index 6bb27ec02cb..4d17d4ad41e 100644
--- a/tests/wpt/web-platform-tests/css/css-transitions/hidden-container-001.html
+++ b/tests/wpt/web-platform-tests/css/css-transitions/hidden-container-001.html
@@ -22,13 +22,6 @@
display: none;
}
</style>
-
- <script id="metadata_cache">/*
- {
- "transition within display:none / values": {},
- "transition within display:none / events": {}
- }
- */</script>
</head>
<body>
<!-- required by testharnessreport.js -->
diff --git a/tests/wpt/web-platform-tests/css/css-transitions/properties-value-001.html b/tests/wpt/web-platform-tests/css/css-transitions/properties-value-001.html
index ade0c0eca35..9182930ed78 100644
--- a/tests/wpt/web-platform-tests/css/css-transitions/properties-value-001.html
+++ b/tests/wpt/web-platform-tests/css/css-transitions/properties-value-001.html
@@ -27,573 +27,6 @@
height: 100000px;
}
</style>
-
- <script id="metadata_cache">/*
- {
- "background-color color(rgba) / values": {},
- "background-color color(rgba) / events": {},
- "background-position length(pt) / values": {},
- "background-position length(pt) / events": {},
- "background-position length(pc) / values": {},
- "background-position length(pc) / events": {},
- "background-position length(px) / values": {},
- "background-position length(px) / events": {},
- "background-position length(em) / values": {},
- "background-position length(em) / events": {},
- "background-position length(ex) / values": {},
- "background-position length(ex) / events": {},
- "background-position length(mm) / values": {},
- "background-position length(mm) / events": {},
- "background-position length(cm) / values": {},
- "background-position length(cm) / events": {},
- "background-position length(in) / values": {},
- "background-position length(in) / events": {},
- "background-position percentage(%) / values": {},
- "background-position percentage(%) / events": {},
- "border-top-width length(pt) / values": {},
- "border-top-width length(pt) / events": {},
- "border-top-width length(pc) / values": {},
- "border-top-width length(pc) / events": {},
- "border-top-width length(px) / values": {},
- "border-top-width length(px) / events": {},
- "border-top-width length(em) / values": {},
- "border-top-width length(em) / events": {},
- "border-top-width length(ex) / values": {},
- "border-top-width length(ex) / events": {},
- "border-top-width length(mm) / values": {},
- "border-top-width length(mm) / events": {},
- "border-top-width length(cm) / values": {},
- "border-top-width length(cm) / events": {},
- "border-top-width length(in) / values": {},
- "border-top-width length(in) / events": {},
- "border-right-width length(pt) / values": {},
- "border-right-width length(pt) / events": {},
- "border-right-width length(pc) / values": {},
- "border-right-width length(pc) / events": {},
- "border-right-width length(px) / values": {},
- "border-right-width length(px) / events": {},
- "border-right-width length(em) / values": {},
- "border-right-width length(em) / events": {},
- "border-right-width length(ex) / values": {},
- "border-right-width length(ex) / events": {},
- "border-right-width length(mm) / values": {},
- "border-right-width length(mm) / events": {},
- "border-right-width length(cm) / values": {},
- "border-right-width length(cm) / events": {},
- "border-right-width length(in) / values": {},
- "border-right-width length(in) / events": {},
- "border-bottom-width length(pt) / values": {},
- "border-bottom-width length(pt) / events": {},
- "border-bottom-width length(pc) / values": {},
- "border-bottom-width length(pc) / events": {},
- "border-bottom-width length(px) / values": {},
- "border-bottom-width length(px) / events": {},
- "border-bottom-width length(em) / values": {},
- "border-bottom-width length(em) / events": {},
- "border-bottom-width length(ex) / values": {},
- "border-bottom-width length(ex) / events": {},
- "border-bottom-width length(mm) / values": {},
- "border-bottom-width length(mm) / events": {},
- "border-bottom-width length(cm) / values": {},
- "border-bottom-width length(cm) / events": {},
- "border-bottom-width length(in) / values": {},
- "border-bottom-width length(in) / events": {},
- "border-left-width length(pt) / values": {},
- "border-left-width length(pt) / events": {},
- "border-left-width length(pc) / values": {},
- "border-left-width length(pc) / events": {},
- "border-left-width length(px) / values": {},
- "border-left-width length(px) / events": {},
- "border-left-width length(em) / values": {},
- "border-left-width length(em) / events": {},
- "border-left-width length(ex) / values": {},
- "border-left-width length(ex) / events": {},
- "border-left-width length(mm) / values": {},
- "border-left-width length(mm) / events": {},
- "border-left-width length(cm) / values": {},
- "border-left-width length(cm) / events": {},
- "border-left-width length(in) / values": {},
- "border-left-width length(in) / events": {},
- "border-top-color color(rgba) / values": {},
- "border-top-color color(rgba) / events": {},
- "border-right-color color(rgba) / values": {},
- "border-right-color color(rgba) / events": {},
- "border-bottom-color color(rgba) / values": {},
- "border-bottom-color color(rgba) / events": {},
- "border-left-color color(rgba) / values": {},
- "border-left-color color(rgba) / events": {},
- "padding-bottom length(pt) / values": {},
- "padding-bottom length(pt) / events": {},
- "padding-bottom length(pc) / values": {},
- "padding-bottom length(pc) / events": {},
- "padding-bottom length(px) / values": {},
- "padding-bottom length(px) / events": {},
- "padding-bottom length(em) / values": {},
- "padding-bottom length(em) / events": {},
- "padding-bottom length(ex) / values": {},
- "padding-bottom length(ex) / events": {},
- "padding-bottom length(mm) / values": {},
- "padding-bottom length(mm) / events": {},
- "padding-bottom length(cm) / values": {},
- "padding-bottom length(cm) / events": {},
- "padding-bottom length(in) / values": {},
- "padding-bottom length(in) / events": {},
- "padding-left length(pt) / values": {},
- "padding-left length(pt) / events": {},
- "padding-left length(pc) / values": {},
- "padding-left length(pc) / events": {},
- "padding-left length(px) / values": {},
- "padding-left length(px) / events": {},
- "padding-left length(em) / values": {},
- "padding-left length(em) / events": {},
- "padding-left length(ex) / values": {},
- "padding-left length(ex) / events": {},
- "padding-left length(mm) / values": {},
- "padding-left length(mm) / events": {},
- "padding-left length(cm) / values": {},
- "padding-left length(cm) / events": {},
- "padding-left length(in) / values": {},
- "padding-left length(in) / events": {},
- "padding-right length(pt) / values": {},
- "padding-right length(pt) / events": {},
- "padding-right length(pc) / values": {},
- "padding-right length(pc) / events": {},
- "padding-right length(px) / values": {},
- "padding-right length(px) / events": {},
- "padding-right length(em) / values": {},
- "padding-right length(em) / events": {},
- "padding-right length(ex) / values": {},
- "padding-right length(ex) / events": {},
- "padding-right length(mm) / values": {},
- "padding-right length(mm) / events": {},
- "padding-right length(cm) / values": {},
- "padding-right length(cm) / events": {},
- "padding-right length(in) / values": {},
- "padding-right length(in) / events": {},
- "padding-top length(pt) / values": {},
- "padding-top length(pt) / events": {},
- "padding-top length(pc) / values": {},
- "padding-top length(pc) / events": {},
- "padding-top length(px) / values": {},
- "padding-top length(px) / events": {},
- "padding-top length(em) / values": {},
- "padding-top length(em) / events": {},
- "padding-top length(ex) / values": {},
- "padding-top length(ex) / events": {},
- "padding-top length(mm) / values": {},
- "padding-top length(mm) / events": {},
- "padding-top length(cm) / values": {},
- "padding-top length(cm) / events": {},
- "padding-top length(in) / values": {},
- "padding-top length(in) / events": {},
- "margin-bottom length(pt) / values": {},
- "margin-bottom length(pt) / events": {},
- "margin-bottom length(pc) / values": {},
- "margin-bottom length(pc) / events": {},
- "margin-bottom length(px) / values": {},
- "margin-bottom length(px) / events": {},
- "margin-bottom length(em) / values": {},
- "margin-bottom length(em) / events": {},
- "margin-bottom length(ex) / values": {},
- "margin-bottom length(ex) / events": {},
- "margin-bottom length(mm) / values": {},
- "margin-bottom length(mm) / events": {},
- "margin-bottom length(cm) / values": {},
- "margin-bottom length(cm) / events": {},
- "margin-bottom length(in) / values": {},
- "margin-bottom length(in) / events": {},
- "margin-left length(pt) / values": {},
- "margin-left length(pt) / events": {},
- "margin-left length(pc) / values": {},
- "margin-left length(pc) / events": {},
- "margin-left length(px) / values": {},
- "margin-left length(px) / events": {},
- "margin-left length(em) / values": {},
- "margin-left length(em) / events": {},
- "margin-left length(ex) / values": {},
- "margin-left length(ex) / events": {},
- "margin-left length(mm) / values": {},
- "margin-left length(mm) / events": {},
- "margin-left length(cm) / values": {},
- "margin-left length(cm) / events": {},
- "margin-left length(in) / values": {},
- "margin-left length(in) / events": {},
- "margin-right length(pt) / values": {},
- "margin-right length(pt) / events": {},
- "margin-right length(pc) / values": {},
- "margin-right length(pc) / events": {},
- "margin-right length(px) / values": {},
- "margin-right length(px) / events": {},
- "margin-right length(em) / values": {},
- "margin-right length(em) / events": {},
- "margin-right length(ex) / values": {},
- "margin-right length(ex) / events": {},
- "margin-right length(mm) / values": {},
- "margin-right length(mm) / events": {},
- "margin-right length(cm) / values": {},
- "margin-right length(cm) / events": {},
- "margin-right length(in) / values": {},
- "margin-right length(in) / events": {},
- "margin-top length(pt) / values": {},
- "margin-top length(pt) / events": {},
- "margin-top length(pc) / values": {},
- "margin-top length(pc) / events": {},
- "margin-top length(px) / values": {},
- "margin-top length(px) / events": {},
- "margin-top length(em) / values": {},
- "margin-top length(em) / events": {},
- "margin-top length(ex) / values": {},
- "margin-top length(ex) / events": {},
- "margin-top length(mm) / values": {},
- "margin-top length(mm) / events": {},
- "margin-top length(cm) / values": {},
- "margin-top length(cm) / events": {},
- "margin-top length(in) / values": {},
- "margin-top length(in) / events": {},
- "height length(pt) / values": {},
- "height length(pt) / events": {},
- "height length(pc) / values": {},
- "height length(pc) / events": {},
- "height length(px) / values": {},
- "height length(px) / events": {},
- "height length(em) / values": {},
- "height length(em) / events": {},
- "height length(ex) / values": {},
- "height length(ex) / events": {},
- "height length(mm) / values": {},
- "height length(mm) / events": {},
- "height length(cm) / values": {},
- "height length(cm) / events": {},
- "height length(in) / values": {},
- "height length(in) / events": {},
- "height percentage(%) / values": {},
- "height percentage(%) / events": {},
- "width length(pt) / values": {},
- "width length(pt) / events": {},
- "width length(pc) / values": {},
- "width length(pc) / events": {},
- "width length(px) / values": {},
- "width length(px) / events": {},
- "width length(em) / values": {},
- "width length(em) / events": {},
- "width length(ex) / values": {},
- "width length(ex) / events": {},
- "width length(mm) / values": {},
- "width length(mm) / events": {},
- "width length(cm) / values": {},
- "width length(cm) / events": {},
- "width length(in) / values": {},
- "width length(in) / events": {},
- "width percentage(%) / values": {},
- "width percentage(%) / events": {},
- "min-height length(pt) / values": {},
- "min-height length(pt) / events": {},
- "min-height length(pc) / values": {},
- "min-height length(pc) / events": {},
- "min-height length(px) / values": {},
- "min-height length(px) / events": {},
- "min-height length(em) / values": {},
- "min-height length(em) / events": {},
- "min-height length(ex) / values": {},
- "min-height length(ex) / events": {},
- "min-height length(mm) / values": {},
- "min-height length(mm) / events": {},
- "min-height length(cm) / values": {},
- "min-height length(cm) / events": {},
- "min-height length(in) / values": {},
- "min-height length(in) / events": {},
- "min-height percentage(%) / values": {},
- "min-height percentage(%) / events": {},
- "min-width length(pt) / values": {},
- "min-width length(pt) / events": {},
- "min-width length(pc) / values": {},
- "min-width length(pc) / events": {},
- "min-width length(px) / values": {},
- "min-width length(px) / events": {},
- "min-width length(em) / values": {},
- "min-width length(em) / events": {},
- "min-width length(ex) / values": {},
- "min-width length(ex) / events": {},
- "min-width length(mm) / values": {},
- "min-width length(mm) / events": {},
- "min-width length(cm) / values": {},
- "min-width length(cm) / events": {},
- "min-width length(in) / values": {},
- "min-width length(in) / events": {},
- "min-width percentage(%) / values": {},
- "min-width percentage(%) / events": {},
- "max-height length(pt) / values": {},
- "max-height length(pt) / events": {},
- "max-height length(pc) / values": {},
- "max-height length(pc) / events": {},
- "max-height length(px) / values": {},
- "max-height length(px) / events": {},
- "max-height length(em) / values": {},
- "max-height length(em) / events": {},
- "max-height length(ex) / values": {},
- "max-height length(ex) / events": {},
- "max-height length(mm) / values": {},
- "max-height length(mm) / events": {},
- "max-height length(cm) / values": {},
- "max-height length(cm) / events": {},
- "max-height length(in) / values": {},
- "max-height length(in) / events": {},
- "max-height percentage(%) / values": {},
- "max-height percentage(%) / events": {},
- "max-width length(pt) / values": {},
- "max-width length(pt) / events": {},
- "max-width length(pc) / values": {},
- "max-width length(pc) / events": {},
- "max-width length(px) / values": {},
- "max-width length(px) / events": {},
- "max-width length(em) / values": {},
- "max-width length(em) / events": {},
- "max-width length(ex) / values": {},
- "max-width length(ex) / events": {},
- "max-width length(mm) / values": {},
- "max-width length(mm) / events": {},
- "max-width length(cm) / values": {},
- "max-width length(cm) / events": {},
- "max-width length(in) / values": {},
- "max-width length(in) / events": {},
- "max-width percentage(%) / values": {},
- "max-width percentage(%) / events": {},
- "top length(pt) / values": {},
- "top length(pt) / events": {},
- "top length(pc) / values": {},
- "top length(pc) / events": {},
- "top length(px) / values": {},
- "top length(px) / events": {},
- "top length(em) / values": {},
- "top length(em) / events": {},
- "top length(ex) / values": {},
- "top length(ex) / events": {},
- "top length(mm) / values": {},
- "top length(mm) / events": {},
- "top length(cm) / values": {},
- "top length(cm) / events": {},
- "top length(in) / values": {},
- "top length(in) / events": {},
- "top percentage(%) / values": {},
- "top percentage(%) / events": {},
- "right length(pt) / values": {},
- "right length(pt) / events": {},
- "right length(pc) / values": {},
- "right length(pc) / events": {},
- "right length(px) / values": {},
- "right length(px) / events": {},
- "right length(em) / values": {},
- "right length(em) / events": {},
- "right length(ex) / values": {},
- "right length(ex) / events": {},
- "right length(mm) / values": {},
- "right length(mm) / events": {},
- "right length(cm) / values": {},
- "right length(cm) / events": {},
- "right length(in) / values": {},
- "right length(in) / events": {},
- "right percentage(%) / values": {},
- "right percentage(%) / events": {},
- "bottom length(pt) / values": {},
- "bottom length(pt) / events": {},
- "bottom length(pc) / values": {},
- "bottom length(pc) / events": {},
- "bottom length(px) / values": {},
- "bottom length(px) / events": {},
- "bottom length(em) / values": {},
- "bottom length(em) / events": {},
- "bottom length(ex) / values": {},
- "bottom length(ex) / events": {},
- "bottom length(mm) / values": {},
- "bottom length(mm) / events": {},
- "bottom length(cm) / values": {},
- "bottom length(cm) / events": {},
- "bottom length(in) / values": {},
- "bottom length(in) / events": {},
- "bottom percentage(%) / values": {},
- "bottom percentage(%) / events": {},
- "left length(pt) / values": {},
- "left length(pt) / events": {},
- "left length(pc) / values": {},
- "left length(pc) / events": {},
- "left length(px) / values": {},
- "left length(px) / events": {},
- "left length(em) / values": {},
- "left length(em) / events": {},
- "left length(ex) / values": {},
- "left length(ex) / events": {},
- "left length(mm) / values": {},
- "left length(mm) / events": {},
- "left length(cm) / values": {},
- "left length(cm) / events": {},
- "left length(in) / values": {},
- "left length(in) / events": {},
- "left percentage(%) / values": {},
- "left percentage(%) / events": {},
- "color color(rgba) / values": {},
- "color color(rgba) / events": {},
- "font-size length(pt) / values": {},
- "font-size length(pt) / events": {},
- "font-size length(pc) / values": {},
- "font-size length(pc) / events": {},
- "font-size length(px) / values": {},
- "font-size length(px) / events": {},
- "font-size length(em) / values": {},
- "font-size length(em) / events": {},
- "font-size length(ex) / values": {},
- "font-size length(ex) / events": {},
- "font-size length(mm) / values": {},
- "font-size length(mm) / events": {},
- "font-size length(cm) / values": {},
- "font-size length(cm) / events": {},
- "font-size length(in) / values": {},
- "font-size length(in) / events": {},
- "font-size percentage(%) / values": {},
- "font-size percentage(%) / events": {},
- "font-weight font-weight(keyword) / values": {},
- "font-weight font-weight(keyword) / events": {},
- "font-weight font-weight(numeric) / values": {},
- "font-weight font-weight(numeric) / events": {},
- "line-height number(integer) / values": {},
- "line-height number(integer) / events": {},
- "line-height number(decimal) / values": {},
- "line-height number(decimal) / events": {},
- "line-height length(pt) / values": {},
- "line-height length(pt) / events": {},
- "line-height length(pc) / values": {},
- "line-height length(pc) / events": {},
- "line-height length(px) / values": {},
- "line-height length(px) / events": {},
- "line-height length(em) / values": {},
- "line-height length(em) / events": {},
- "line-height length(ex) / values": {},
- "line-height length(ex) / events": {},
- "line-height length(mm) / values": {},
- "line-height length(mm) / events": {},
- "line-height length(cm) / values": {},
- "line-height length(cm) / events": {},
- "line-height length(in) / values": {},
- "line-height length(in) / events": {},
- "line-height percentage(%) / values": {},
- "line-height percentage(%) / events": {},
- "letter-spacing length(pt) / values": {},
- "letter-spacing length(pt) / events": {},
- "letter-spacing length(pc) / values": {},
- "letter-spacing length(pc) / events": {},
- "letter-spacing length(px) / values": {},
- "letter-spacing length(px) / events": {},
- "letter-spacing length(em) / values": {},
- "letter-spacing length(em) / events": {},
- "letter-spacing length(ex) / values": {},
- "letter-spacing length(ex) / events": {},
- "letter-spacing length(mm) / values": {},
- "letter-spacing length(mm) / events": {},
- "letter-spacing length(cm) / values": {},
- "letter-spacing length(cm) / events": {},
- "letter-spacing length(in) / values": {},
- "letter-spacing length(in) / events": {},
- "word-spacing length(pt) / values": {},
- "word-spacing length(pt) / events": {},
- "word-spacing length(pc) / values": {},
- "word-spacing length(pc) / events": {},
- "word-spacing length(px) / values": {},
- "word-spacing length(px) / events": {},
- "word-spacing length(em) / values": {},
- "word-spacing length(em) / events": {},
- "word-spacing length(ex) / values": {},
- "word-spacing length(ex) / events": {},
- "word-spacing length(mm) / values": {},
- "word-spacing length(mm) / events": {},
- "word-spacing length(cm) / values": {},
- "word-spacing length(cm) / events": {},
- "word-spacing length(in) / values": {},
- "word-spacing length(in) / events": {},
- "word-spacing percentage(%) / values": {},
- "word-spacing percentage(%) / events": {},
- "text-indent length(pt) / values": {},
- "text-indent length(pt) / events": {},
- "text-indent length(pc) / values": {},
- "text-indent length(pc) / events": {},
- "text-indent length(px) / values": {},
- "text-indent length(px) / events": {},
- "text-indent length(em) / values": {},
- "text-indent length(em) / events": {},
- "text-indent length(ex) / values": {},
- "text-indent length(ex) / events": {},
- "text-indent length(mm) / values": {},
- "text-indent length(mm) / events": {},
- "text-indent length(cm) / values": {},
- "text-indent length(cm) / events": {},
- "text-indent length(in) / values": {},
- "text-indent length(in) / events": {},
- "text-indent percentage(%) / values": {},
- "text-indent percentage(%) / events": {},
- "text-shadow shadow(shadow) / values": {},
- "text-shadow shadow(shadow) / events": {},
- "outline-color color(rgba) / values": {},
- "outline-color color(rgba) / events": {},
- "outline-offset length(pt) / values": {},
- "outline-offset length(pt) / events": {},
- "outline-offset length(pc) / values": {},
- "outline-offset length(pc) / events": {},
- "outline-offset length(px) / values": {},
- "outline-offset length(px) / events": {},
- "outline-offset length(em) / values": {},
- "outline-offset length(em) / events": {},
- "outline-offset length(ex) / values": {},
- "outline-offset length(ex) / events": {},
- "outline-offset length(mm) / values": {},
- "outline-offset length(mm) / events": {},
- "outline-offset length(cm) / values": {},
- "outline-offset length(cm) / events": {},
- "outline-offset length(in) / values": {},
- "outline-offset length(in) / events": {},
- "outline-width length(pt) / values": {},
- "outline-width length(pt) / events": {},
- "outline-width length(pc) / values": {},
- "outline-width length(pc) / events": {},
- "outline-width length(px) / values": {},
- "outline-width length(px) / events": {},
- "outline-width length(em) / values": {},
- "outline-width length(em) / events": {},
- "outline-width length(ex) / values": {},
- "outline-width length(ex) / events": {},
- "outline-width length(mm) / values": {},
- "outline-width length(mm) / events": {},
- "outline-width length(cm) / values": {},
- "outline-width length(cm) / events": {},
- "outline-width length(in) / values": {},
- "outline-width length(in) / events": {},
- "clip rectangle(rectangle) / values": {},
- "clip rectangle(rectangle) / events": {},
- "crop rectangle(rectangle) / values": {},
- "crop rectangle(rectangle) / events": {},
- "vertical-align length(pt) / values": {},
- "vertical-align length(pt) / events": {},
- "vertical-align length(pc) / values": {},
- "vertical-align length(pc) / events": {},
- "vertical-align length(px) / values": {},
- "vertical-align length(px) / events": {},
- "vertical-align length(em) / values": {},
- "vertical-align length(em) / events": {},
- "vertical-align length(ex) / values": {},
- "vertical-align length(ex) / events": {},
- "vertical-align length(mm) / values": {},
- "vertical-align length(mm) / events": {},
- "vertical-align length(cm) / values": {},
- "vertical-align length(cm) / events": {},
- "vertical-align length(in) / values": {},
- "vertical-align length(in) / events": {},
- "vertical-align percentage(%) / values": {},
- "vertical-align percentage(%) / events": {},
- "opacity number[0,1](zero-to-one) / values": {},
- "opacity number[0,1](zero-to-one) / events": {},
- "visibility visibility(keyword) / values": {},
- "visibility visibility(keyword) / events": {},
- "z-index integer(integer) / values": {},
- "z-index integer(integer) / events": {}
- }
- */</script>
</head>
<body>
<!-- required by testharnessreport.js -->
diff --git a/tests/wpt/web-platform-tests/css/css-transitions/properties-value-002.html b/tests/wpt/web-platform-tests/css/css-transitions/properties-value-002.html
index ca0277c8d09..7298070b1e3 100644
--- a/tests/wpt/web-platform-tests/css/css-transitions/properties-value-002.html
+++ b/tests/wpt/web-platform-tests/css/css-transitions/properties-value-002.html
@@ -27,29 +27,6 @@
height: 100000px;
}
</style>
-
- <script id="metadata_cache">/*
- {
- "margin-bottom percentage(%) / values": {},
- "margin-bottom percentage(%) / events": {},
- "margin-left percentage(%) / values": {},
- "margin-left percentage(%) / events": {},
- "margin-right percentage(%) / values": {},
- "margin-right percentage(%) / events": {},
- "margin-top percentage(%) / values": {},
- "margin-top percentage(%) / events": {},
- "padding-bottom percentage(%) / values": {},
- "padding-bottom percentage(%) / events": {},
- "padding-left percentage(%) / values": {},
- "padding-left percentage(%) / events": {},
- "padding-right percentage(%) / values": {},
- "padding-right percentage(%) / events": {},
- "padding-top percentage(%) / values": {},
- "padding-top percentage(%) / events": {},
- "vertical-align vertical(keyword) / values": {},
- "vertical-align vertical(keyword) / events": {}
- }
- */</script>
</head>
<body>
<!-- required by testharnessreport.js -->
diff --git a/tests/wpt/web-platform-tests/css/css-transitions/properties-value-003.html b/tests/wpt/web-platform-tests/css/css-transitions/properties-value-003.html
index e32cd36f211..23385d15817 100644
--- a/tests/wpt/web-platform-tests/css/css-transitions/properties-value-003.html
+++ b/tests/wpt/web-platform-tests/css/css-transitions/properties-value-003.html
@@ -27,203 +27,6 @@
height: 100000px;
}
</style>
-
- <script id="metadata_cache">/*
- {
- "border-top-left-radius border-radius(px) / values": {},
- "border-top-left-radius border-radius(px) / events": {},
- "border-top-left-radius border-radius(px-px) / values": {},
- "border-top-left-radius border-radius(px-px) / events": {},
- "border-top-right-radius border-radius(px) / values": {},
- "border-top-right-radius border-radius(px) / events": {},
- "border-top-right-radius border-radius(px-px) / values": {},
- "border-top-right-radius border-radius(px-px) / events": {},
- "border-bottom-left-radius border-radius(px) / values": {},
- "border-bottom-left-radius border-radius(px) / events": {},
- "border-bottom-left-radius border-radius(px-px) / values": {},
- "border-bottom-left-radius border-radius(px-px) / events": {},
- "border-bottom-right-radius border-radius(px) / values": {},
- "border-bottom-right-radius border-radius(px) / events": {},
- "border-bottom-right-radius border-radius(px-px) / values": {},
- "border-bottom-right-radius border-radius(px-px) / events": {},
- "background-image image(url) / values": {},
- "background-image image(url) / events": {},
- "background-image image(data) / values": {},
- "background-image image(data) / events": {},
- "background-image image(gradient) / values": {},
- "background-image image(gradient) / events": {},
- "background-size background-size(keyword) / values": {},
- "background-size background-size(keyword) / events": {},
- "box-shadow box-shadow(shadow) / values": {},
- "box-shadow box-shadow(shadow) / events": {},
- "font-size-adjust number(integer) / values": {},
- "font-size-adjust number(integer) / events": {},
- "font-size-adjust number(decimal) / values": {},
- "font-size-adjust number(decimal) / events": {},
- "font-stretch font-stretch(keyword) / values": {},
- "font-stretch font-stretch(keyword) / events": {},
- "marker-offset length(pt) / values": {},
- "marker-offset length(pt) / events": {},
- "marker-offset length(pc) / values": {},
- "marker-offset length(pc) / events": {},
- "marker-offset length(px) / values": {},
- "marker-offset length(px) / events": {},
- "marker-offset length(em) / values": {},
- "marker-offset length(em) / events": {},
- "marker-offset length(ex) / values": {},
- "marker-offset length(ex) / events": {},
- "marker-offset length(mm) / values": {},
- "marker-offset length(mm) / events": {},
- "marker-offset length(cm) / values": {},
- "marker-offset length(cm) / events": {},
- "marker-offset length(in) / values": {},
- "marker-offset length(in) / events": {},
- "text-decoration-color color(rgba) / values": {},
- "text-decoration-color color(rgba) / events": {},
- "column-count integer(integer) / values": {},
- "column-count integer(integer) / events": {},
- "column-gap length(pt) / values": {},
- "column-gap length(pt) / events": {},
- "column-gap length(pc) / values": {},
- "column-gap length(pc) / events": {},
- "column-gap length(px) / values": {},
- "column-gap length(px) / events": {},
- "column-gap length(em) / values": {},
- "column-gap length(em) / events": {},
- "column-gap length(ex) / values": {},
- "column-gap length(ex) / events": {},
- "column-gap length(mm) / values": {},
- "column-gap length(mm) / events": {},
- "column-gap length(cm) / values": {},
- "column-gap length(cm) / events": {},
- "column-gap length(in) / values": {},
- "column-gap length(in) / events": {},
- "column-rule-color color(rgba) / values": {},
- "column-rule-color color(rgba) / events": {},
- "column-rule-width length(pt) / values": {},
- "column-rule-width length(pt) / events": {},
- "column-rule-width length(pc) / values": {},
- "column-rule-width length(pc) / events": {},
- "column-rule-width length(px) / values": {},
- "column-rule-width length(px) / events": {},
- "column-rule-width length(em) / values": {},
- "column-rule-width length(em) / events": {},
- "column-rule-width length(ex) / values": {},
- "column-rule-width length(ex) / events": {},
- "column-rule-width length(mm) / values": {},
- "column-rule-width length(mm) / events": {},
- "column-rule-width length(cm) / values": {},
- "column-rule-width length(cm) / events": {},
- "column-rule-width length(in) / values": {},
- "column-rule-width length(in) / events": {},
- "column-width length(pt) / values": {},
- "column-width length(pt) / events": {},
- "column-width length(pc) / values": {},
- "column-width length(pc) / events": {},
- "column-width length(px) / values": {},
- "column-width length(px) / events": {},
- "column-width length(em) / values": {},
- "column-width length(em) / events": {},
- "column-width length(ex) / values": {},
- "column-width length(ex) / events": {},
- "column-width length(mm) / values": {},
- "column-width length(mm) / events": {},
- "column-width length(cm) / values": {},
- "column-width length(cm) / events": {},
- "column-width length(in) / values": {},
- "column-width length(in) / events": {},
- "transform transform(rotate) / values": {},
- "transform transform(rotate) / events": {},
- "transform-origin horizontal(keyword) / values": {},
- "transform-origin horizontal(keyword) / events": {},
- "zoom number(integer) / values": {},
- "zoom number(integer) / events": {},
- "zoom number(decimal) / values": {},
- "zoom number(decimal) / events": {},
- "outline-radius-topleft length(pt) / values": {},
- "outline-radius-topleft length(pt) / events": {},
- "outline-radius-topleft length(pc) / values": {},
- "outline-radius-topleft length(pc) / events": {},
- "outline-radius-topleft length(px) / values": {},
- "outline-radius-topleft length(px) / events": {},
- "outline-radius-topleft length(em) / values": {},
- "outline-radius-topleft length(em) / events": {},
- "outline-radius-topleft length(ex) / values": {},
- "outline-radius-topleft length(ex) / events": {},
- "outline-radius-topleft length(mm) / values": {},
- "outline-radius-topleft length(mm) / events": {},
- "outline-radius-topleft length(cm) / values": {},
- "outline-radius-topleft length(cm) / events": {},
- "outline-radius-topleft length(in) / values": {},
- "outline-radius-topleft length(in) / events": {},
- "outline-radius-topleft percentage(%) / values": {},
- "outline-radius-topleft percentage(%) / events": {},
- "outline-radius-topright length(pt) / values": {},
- "outline-radius-topright length(pt) / events": {},
- "outline-radius-topright length(pc) / values": {},
- "outline-radius-topright length(pc) / events": {},
- "outline-radius-topright length(px) / values": {},
- "outline-radius-topright length(px) / events": {},
- "outline-radius-topright length(em) / values": {},
- "outline-radius-topright length(em) / events": {},
- "outline-radius-topright length(ex) / values": {},
- "outline-radius-topright length(ex) / events": {},
- "outline-radius-topright length(mm) / values": {},
- "outline-radius-topright length(mm) / events": {},
- "outline-radius-topright length(cm) / values": {},
- "outline-radius-topright length(cm) / events": {},
- "outline-radius-topright length(in) / values": {},
- "outline-radius-topright length(in) / events": {},
- "outline-radius-topright percentage(%) / values": {},
- "outline-radius-topright percentage(%) / events": {},
- "outline-radius-bottomright length(pt) / values": {},
- "outline-radius-bottomright length(pt) / events": {},
- "outline-radius-bottomright length(pc) / values": {},
- "outline-radius-bottomright length(pc) / events": {},
- "outline-radius-bottomright length(px) / values": {},
- "outline-radius-bottomright length(px) / events": {},
- "outline-radius-bottomright length(em) / values": {},
- "outline-radius-bottomright length(em) / events": {},
- "outline-radius-bottomright length(ex) / values": {},
- "outline-radius-bottomright length(ex) / events": {},
- "outline-radius-bottomright length(mm) / values": {},
- "outline-radius-bottomright length(mm) / events": {},
- "outline-radius-bottomright length(cm) / values": {},
- "outline-radius-bottomright length(cm) / events": {},
- "outline-radius-bottomright length(in) / values": {},
- "outline-radius-bottomright length(in) / events": {},
- "outline-radius-bottomright percentage(%) / values": {},
- "outline-radius-bottomright percentage(%) / events": {},
- "outline-radius-bottomleft length(pt) / values": {},
- "outline-radius-bottomleft length(pt) / events": {},
- "outline-radius-bottomleft length(pc) / values": {},
- "outline-radius-bottomleft length(pc) / events": {},
- "outline-radius-bottomleft length(px) / values": {},
- "outline-radius-bottomleft length(px) / events": {},
- "outline-radius-bottomleft length(em) / values": {},
- "outline-radius-bottomleft length(em) / events": {},
- "outline-radius-bottomleft length(ex) / values": {},
- "outline-radius-bottomleft length(ex) / events": {},
- "outline-radius-bottomleft length(mm) / values": {},
- "outline-radius-bottomleft length(mm) / events": {},
- "outline-radius-bottomleft length(cm) / values": {},
- "outline-radius-bottomleft length(cm) / events": {},
- "outline-radius-bottomleft length(in) / values": {},
- "outline-radius-bottomleft length(in) / events": {},
- "outline-radius-bottomleft percentage(%) / values": {},
- "outline-radius-bottomleft percentage(%) / events": {},
- "display display(static to absolute) / values": {},
- "display display(static to absolute) / events": {},
- "display display(block to inline-block) / values": {},
- "display display(block to inline-block) / events": {},
- "position position(static to absolute) / values": {},
- "position position(static to absolute) / events": {},
- "position position(relative to absolute) / values": {},
- "position position(relative to absolute) / events": {},
- "position position(absolute to fixed) / values": {},
- "position position(absolute to fixed) / events": {}
- }
- */</script>
</head>
<body>
<!-- required by testharnessreport.js -->
diff --git a/tests/wpt/web-platform-tests/css/css-transitions/properties-value-auto-001.html b/tests/wpt/web-platform-tests/css/css-transitions/properties-value-auto-001.html
index fd4befc055b..087f6bbb3fa 100644
--- a/tests/wpt/web-platform-tests/css/css-transitions/properties-value-auto-001.html
+++ b/tests/wpt/web-platform-tests/css/css-transitions/properties-value-auto-001.html
@@ -26,63 +26,6 @@
height: 100000px;
}
</style>
-
- <script id="metadata_cache">/*
- {
- "margin-top auto(to) / values": {},
- "margin-top auto(to) / events": {},
- "margin-top auto(from) / values": {},
- "margin-top auto(from) / events": {},
- "margin-right auto(to) / values": {},
- "margin-right auto(to) / events": {},
- "margin-right auto(from) / values": {},
- "margin-right auto(from) / events": {},
- "margin-bottom auto(to) / values": {},
- "margin-bottom auto(to) / events": {},
- "margin-bottom auto(from) / values": {},
- "margin-bottom auto(from) / events": {},
- "margin-left auto(to) / values": {},
- "margin-left auto(to) / events": {},
- "margin-left auto(from) / values": {},
- "margin-left auto(from) / events": {},
- "height auto(to) / values": {},
- "height auto(to) / events": {},
- "height auto(from) / values": {},
- "height auto(from) / events": {},
- "width auto(to) / values": {},
- "width auto(to) / events": {},
- "width auto(from) / values": {},
- "width auto(from) / events": {},
- "clip auto(to) / values": {},
- "clip auto(to) / events": {},
- "clip auto(from) / values": {},
- "clip auto(from) / events": {},
- "marker-offset auto(to) / values": {},
- "marker-offset auto(to) / events": {},
- "marker-offset auto(from) / values": {},
- "marker-offset auto(from) / events": {},
- "top auto(to) / values": {},
- "top auto(to) / events": {},
- "top auto(from) / values": {},
- "top auto(from) / events": {},
- "right auto(to) / values": {},
- "right auto(to) / events": {},
- "right auto(from) / values": {},
- "right auto(from) / events": {},
- "left auto(to) / values": {},
- "left auto(to) / events": {},
- "left auto(from) / values": {},
- "left auto(from) / events": {},
- "bottom auto(to) / values": {},
- "bottom auto(to) / events": {},
- "bottom auto(from) / values": {},
- "bottom auto(from) / events": {},
- "z-index auto(to) / values": {},
- "z-index auto(to) / events": {},
- "z-index auto(from) / values": {},
- "z-index auto(from) / events": {}
- }
- */</script>
</head>
<body>
<!-- required by testharnessreport.js -->
diff --git a/tests/wpt/web-platform-tests/css/css-transitions/properties-value-implicit-001.html b/tests/wpt/web-platform-tests/css/css-transitions/properties-value-implicit-001.html
index 26d37803129..4d93083434d 100644
--- a/tests/wpt/web-platform-tests/css/css-transitions/properties-value-implicit-001.html
+++ b/tests/wpt/web-platform-tests/css/css-transitions/properties-value-implicit-001.html
@@ -26,71 +26,6 @@
height: 100000px;
}
</style>
-
- <script id="metadata_cache">/*
- {
- "background-position length-em(em) / values": {},
- "background-position length-em(em) / events": {},
- "border-top-width length-em(em) / values": {},
- "border-top-width length-em(em) / events": {},
- "border-right-width length-em(em) / values": {},
- "border-right-width length-em(em) / events": {},
- "border-bottom-width length-em(em) / values": {},
- "border-bottom-width length-em(em) / events": {},
- "border-left-width length-em(em) / values": {},
- "border-left-width length-em(em) / events": {},
- "padding-bottom length-em(em) / values": {},
- "padding-bottom length-em(em) / events": {},
- "padding-left length-em(em) / values": {},
- "padding-left length-em(em) / events": {},
- "padding-right length-em(em) / values": {},
- "padding-right length-em(em) / events": {},
- "padding-top length-em(em) / values": {},
- "padding-top length-em(em) / events": {},
- "margin-bottom length-em(em) / values": {},
- "margin-bottom length-em(em) / events": {},
- "margin-left length-em(em) / values": {},
- "margin-left length-em(em) / events": {},
- "margin-right length-em(em) / values": {},
- "margin-right length-em(em) / events": {},
- "margin-top length-em(em) / values": {},
- "margin-top length-em(em) / events": {},
- "height length-em(em) / values": {},
- "height length-em(em) / events": {},
- "width length-em(em) / values": {},
- "width length-em(em) / events": {},
- "min-height length-em(em) / values": {},
- "min-height length-em(em) / events": {},
- "min-width length-em(em) / values": {},
- "min-width length-em(em) / events": {},
- "max-height length-em(em) / values": {},
- "max-height length-em(em) / events": {},
- "max-width length-em(em) / values": {},
- "max-width length-em(em) / events": {},
- "top length-em(em) / values": {},
- "top length-em(em) / events": {},
- "right length-em(em) / values": {},
- "right length-em(em) / events": {},
- "bottom length-em(em) / values": {},
- "bottom length-em(em) / events": {},
- "left length-em(em) / values": {},
- "left length-em(em) / events": {},
- "line-height length-em(em) / values": {},
- "line-height length-em(em) / events": {},
- "letter-spacing length-em(em) / values": {},
- "letter-spacing length-em(em) / events": {},
- "word-spacing length-em(em) / values": {},
- "word-spacing length-em(em) / events": {},
- "text-indent length-em(em) / values": {},
- "text-indent length-em(em) / events": {},
- "outline-offset length-em(em) / values": {},
- "outline-offset length-em(em) / events": {},
- "outline-width length-em(em) / values": {},
- "outline-width length-em(em) / events": {},
- "vertical-align length-em(em) / values": {},
- "vertical-align length-em(em) / events": {}
- }
- */</script>
</head>
<body>
<!-- required by testharnessreport.js -->
diff --git a/tests/wpt/web-platform-tests/css/css-transitions/properties-value-inherit-001.html b/tests/wpt/web-platform-tests/css/css-transitions/properties-value-inherit-001.html
index 97d497f036c..2de40b4cc4e 100644
--- a/tests/wpt/web-platform-tests/css/css-transitions/properties-value-inherit-001.html
+++ b/tests/wpt/web-platform-tests/css/css-transitions/properties-value-inherit-001.html
@@ -26,573 +26,6 @@
height: 100000px;
}
</style>
-
- <script id="metadata_cache">/*
- {
- "background-color color(rgba) / values": {},
- "background-color color(rgba) / events": {},
- "background-position length(pt) / values": {},
- "background-position length(pt) / events": {},
- "background-position length(pc) / values": {},
- "background-position length(pc) / events": {},
- "background-position length(px) / values": {},
- "background-position length(px) / events": {},
- "background-position length(em) / values": {},
- "background-position length(em) / events": {},
- "background-position length(ex) / values": {},
- "background-position length(ex) / events": {},
- "background-position length(mm) / values": {},
- "background-position length(mm) / events": {},
- "background-position length(cm) / values": {},
- "background-position length(cm) / events": {},
- "background-position length(in) / values": {},
- "background-position length(in) / events": {},
- "background-position percentage(%) / values": {},
- "background-position percentage(%) / events": {},
- "border-top-width length(pt) / values": {},
- "border-top-width length(pt) / events": {},
- "border-top-width length(pc) / values": {},
- "border-top-width length(pc) / events": {},
- "border-top-width length(px) / values": {},
- "border-top-width length(px) / events": {},
- "border-top-width length(em) / values": {},
- "border-top-width length(em) / events": {},
- "border-top-width length(ex) / values": {},
- "border-top-width length(ex) / events": {},
- "border-top-width length(mm) / values": {},
- "border-top-width length(mm) / events": {},
- "border-top-width length(cm) / values": {},
- "border-top-width length(cm) / events": {},
- "border-top-width length(in) / values": {},
- "border-top-width length(in) / events": {},
- "border-right-width length(pt) / values": {},
- "border-right-width length(pt) / events": {},
- "border-right-width length(pc) / values": {},
- "border-right-width length(pc) / events": {},
- "border-right-width length(px) / values": {},
- "border-right-width length(px) / events": {},
- "border-right-width length(em) / values": {},
- "border-right-width length(em) / events": {},
- "border-right-width length(ex) / values": {},
- "border-right-width length(ex) / events": {},
- "border-right-width length(mm) / values": {},
- "border-right-width length(mm) / events": {},
- "border-right-width length(cm) / values": {},
- "border-right-width length(cm) / events": {},
- "border-right-width length(in) / values": {},
- "border-right-width length(in) / events": {},
- "border-bottom-width length(pt) / values": {},
- "border-bottom-width length(pt) / events": {},
- "border-bottom-width length(pc) / values": {},
- "border-bottom-width length(pc) / events": {},
- "border-bottom-width length(px) / values": {},
- "border-bottom-width length(px) / events": {},
- "border-bottom-width length(em) / values": {},
- "border-bottom-width length(em) / events": {},
- "border-bottom-width length(ex) / values": {},
- "border-bottom-width length(ex) / events": {},
- "border-bottom-width length(mm) / values": {},
- "border-bottom-width length(mm) / events": {},
- "border-bottom-width length(cm) / values": {},
- "border-bottom-width length(cm) / events": {},
- "border-bottom-width length(in) / values": {},
- "border-bottom-width length(in) / events": {},
- "border-left-width length(pt) / values": {},
- "border-left-width length(pt) / events": {},
- "border-left-width length(pc) / values": {},
- "border-left-width length(pc) / events": {},
- "border-left-width length(px) / values": {},
- "border-left-width length(px) / events": {},
- "border-left-width length(em) / values": {},
- "border-left-width length(em) / events": {},
- "border-left-width length(ex) / values": {},
- "border-left-width length(ex) / events": {},
- "border-left-width length(mm) / values": {},
- "border-left-width length(mm) / events": {},
- "border-left-width length(cm) / values": {},
- "border-left-width length(cm) / events": {},
- "border-left-width length(in) / values": {},
- "border-left-width length(in) / events": {},
- "border-top-color color(rgba) / values": {},
- "border-top-color color(rgba) / events": {},
- "border-right-color color(rgba) / values": {},
- "border-right-color color(rgba) / events": {},
- "border-bottom-color color(rgba) / values": {},
- "border-bottom-color color(rgba) / events": {},
- "border-left-color color(rgba) / values": {},
- "border-left-color color(rgba) / events": {},
- "padding-bottom length(pt) / values": {},
- "padding-bottom length(pt) / events": {},
- "padding-bottom length(pc) / values": {},
- "padding-bottom length(pc) / events": {},
- "padding-bottom length(px) / values": {},
- "padding-bottom length(px) / events": {},
- "padding-bottom length(em) / values": {},
- "padding-bottom length(em) / events": {},
- "padding-bottom length(ex) / values": {},
- "padding-bottom length(ex) / events": {},
- "padding-bottom length(mm) / values": {},
- "padding-bottom length(mm) / events": {},
- "padding-bottom length(cm) / values": {},
- "padding-bottom length(cm) / events": {},
- "padding-bottom length(in) / values": {},
- "padding-bottom length(in) / events": {},
- "padding-left length(pt) / values": {},
- "padding-left length(pt) / events": {},
- "padding-left length(pc) / values": {},
- "padding-left length(pc) / events": {},
- "padding-left length(px) / values": {},
- "padding-left length(px) / events": {},
- "padding-left length(em) / values": {},
- "padding-left length(em) / events": {},
- "padding-left length(ex) / values": {},
- "padding-left length(ex) / events": {},
- "padding-left length(mm) / values": {},
- "padding-left length(mm) / events": {},
- "padding-left length(cm) / values": {},
- "padding-left length(cm) / events": {},
- "padding-left length(in) / values": {},
- "padding-left length(in) / events": {},
- "padding-right length(pt) / values": {},
- "padding-right length(pt) / events": {},
- "padding-right length(pc) / values": {},
- "padding-right length(pc) / events": {},
- "padding-right length(px) / values": {},
- "padding-right length(px) / events": {},
- "padding-right length(em) / values": {},
- "padding-right length(em) / events": {},
- "padding-right length(ex) / values": {},
- "padding-right length(ex) / events": {},
- "padding-right length(mm) / values": {},
- "padding-right length(mm) / events": {},
- "padding-right length(cm) / values": {},
- "padding-right length(cm) / events": {},
- "padding-right length(in) / values": {},
- "padding-right length(in) / events": {},
- "padding-top length(pt) / values": {},
- "padding-top length(pt) / events": {},
- "padding-top length(pc) / values": {},
- "padding-top length(pc) / events": {},
- "padding-top length(px) / values": {},
- "padding-top length(px) / events": {},
- "padding-top length(em) / values": {},
- "padding-top length(em) / events": {},
- "padding-top length(ex) / values": {},
- "padding-top length(ex) / events": {},
- "padding-top length(mm) / values": {},
- "padding-top length(mm) / events": {},
- "padding-top length(cm) / values": {},
- "padding-top length(cm) / events": {},
- "padding-top length(in) / values": {},
- "padding-top length(in) / events": {},
- "margin-bottom length(pt) / values": {},
- "margin-bottom length(pt) / events": {},
- "margin-bottom length(pc) / values": {},
- "margin-bottom length(pc) / events": {},
- "margin-bottom length(px) / values": {},
- "margin-bottom length(px) / events": {},
- "margin-bottom length(em) / values": {},
- "margin-bottom length(em) / events": {},
- "margin-bottom length(ex) / values": {},
- "margin-bottom length(ex) / events": {},
- "margin-bottom length(mm) / values": {},
- "margin-bottom length(mm) / events": {},
- "margin-bottom length(cm) / values": {},
- "margin-bottom length(cm) / events": {},
- "margin-bottom length(in) / values": {},
- "margin-bottom length(in) / events": {},
- "margin-left length(pt) / values": {},
- "margin-left length(pt) / events": {},
- "margin-left length(pc) / values": {},
- "margin-left length(pc) / events": {},
- "margin-left length(px) / values": {},
- "margin-left length(px) / events": {},
- "margin-left length(em) / values": {},
- "margin-left length(em) / events": {},
- "margin-left length(ex) / values": {},
- "margin-left length(ex) / events": {},
- "margin-left length(mm) / values": {},
- "margin-left length(mm) / events": {},
- "margin-left length(cm) / values": {},
- "margin-left length(cm) / events": {},
- "margin-left length(in) / values": {},
- "margin-left length(in) / events": {},
- "margin-right length(pt) / values": {},
- "margin-right length(pt) / events": {},
- "margin-right length(pc) / values": {},
- "margin-right length(pc) / events": {},
- "margin-right length(px) / values": {},
- "margin-right length(px) / events": {},
- "margin-right length(em) / values": {},
- "margin-right length(em) / events": {},
- "margin-right length(ex) / values": {},
- "margin-right length(ex) / events": {},
- "margin-right length(mm) / values": {},
- "margin-right length(mm) / events": {},
- "margin-right length(cm) / values": {},
- "margin-right length(cm) / events": {},
- "margin-right length(in) / values": {},
- "margin-right length(in) / events": {},
- "margin-top length(pt) / values": {},
- "margin-top length(pt) / events": {},
- "margin-top length(pc) / values": {},
- "margin-top length(pc) / events": {},
- "margin-top length(px) / values": {},
- "margin-top length(px) / events": {},
- "margin-top length(em) / values": {},
- "margin-top length(em) / events": {},
- "margin-top length(ex) / values": {},
- "margin-top length(ex) / events": {},
- "margin-top length(mm) / values": {},
- "margin-top length(mm) / events": {},
- "margin-top length(cm) / values": {},
- "margin-top length(cm) / events": {},
- "margin-top length(in) / values": {},
- "margin-top length(in) / events": {},
- "height length(pt) / values": {},
- "height length(pt) / events": {},
- "height length(pc) / values": {},
- "height length(pc) / events": {},
- "height length(px) / values": {},
- "height length(px) / events": {},
- "height length(em) / values": {},
- "height length(em) / events": {},
- "height length(ex) / values": {},
- "height length(ex) / events": {},
- "height length(mm) / values": {},
- "height length(mm) / events": {},
- "height length(cm) / values": {},
- "height length(cm) / events": {},
- "height length(in) / values": {},
- "height length(in) / events": {},
- "height percentage(%) / values": {},
- "height percentage(%) / events": {},
- "width length(pt) / values": {},
- "width length(pt) / events": {},
- "width length(pc) / values": {},
- "width length(pc) / events": {},
- "width length(px) / values": {},
- "width length(px) / events": {},
- "width length(em) / values": {},
- "width length(em) / events": {},
- "width length(ex) / values": {},
- "width length(ex) / events": {},
- "width length(mm) / values": {},
- "width length(mm) / events": {},
- "width length(cm) / values": {},
- "width length(cm) / events": {},
- "width length(in) / values": {},
- "width length(in) / events": {},
- "width percentage(%) / values": {},
- "width percentage(%) / events": {},
- "min-height length(pt) / values": {},
- "min-height length(pt) / events": {},
- "min-height length(pc) / values": {},
- "min-height length(pc) / events": {},
- "min-height length(px) / values": {},
- "min-height length(px) / events": {},
- "min-height length(em) / values": {},
- "min-height length(em) / events": {},
- "min-height length(ex) / values": {},
- "min-height length(ex) / events": {},
- "min-height length(mm) / values": {},
- "min-height length(mm) / events": {},
- "min-height length(cm) / values": {},
- "min-height length(cm) / events": {},
- "min-height length(in) / values": {},
- "min-height length(in) / events": {},
- "min-height percentage(%) / values": {},
- "min-height percentage(%) / events": {},
- "min-width length(pt) / values": {},
- "min-width length(pt) / events": {},
- "min-width length(pc) / values": {},
- "min-width length(pc) / events": {},
- "min-width length(px) / values": {},
- "min-width length(px) / events": {},
- "min-width length(em) / values": {},
- "min-width length(em) / events": {},
- "min-width length(ex) / values": {},
- "min-width length(ex) / events": {},
- "min-width length(mm) / values": {},
- "min-width length(mm) / events": {},
- "min-width length(cm) / values": {},
- "min-width length(cm) / events": {},
- "min-width length(in) / values": {},
- "min-width length(in) / events": {},
- "min-width percentage(%) / values": {},
- "min-width percentage(%) / events": {},
- "max-height length(pt) / values": {},
- "max-height length(pt) / events": {},
- "max-height length(pc) / values": {},
- "max-height length(pc) / events": {},
- "max-height length(px) / values": {},
- "max-height length(px) / events": {},
- "max-height length(em) / values": {},
- "max-height length(em) / events": {},
- "max-height length(ex) / values": {},
- "max-height length(ex) / events": {},
- "max-height length(mm) / values": {},
- "max-height length(mm) / events": {},
- "max-height length(cm) / values": {},
- "max-height length(cm) / events": {},
- "max-height length(in) / values": {},
- "max-height length(in) / events": {},
- "max-height percentage(%) / values": {},
- "max-height percentage(%) / events": {},
- "max-width length(pt) / values": {},
- "max-width length(pt) / events": {},
- "max-width length(pc) / values": {},
- "max-width length(pc) / events": {},
- "max-width length(px) / values": {},
- "max-width length(px) / events": {},
- "max-width length(em) / values": {},
- "max-width length(em) / events": {},
- "max-width length(ex) / values": {},
- "max-width length(ex) / events": {},
- "max-width length(mm) / values": {},
- "max-width length(mm) / events": {},
- "max-width length(cm) / values": {},
- "max-width length(cm) / events": {},
- "max-width length(in) / values": {},
- "max-width length(in) / events": {},
- "max-width percentage(%) / values": {},
- "max-width percentage(%) / events": {},
- "top length(pt) / values": {},
- "top length(pt) / events": {},
- "top length(pc) / values": {},
- "top length(pc) / events": {},
- "top length(px) / values": {},
- "top length(px) / events": {},
- "top length(em) / values": {},
- "top length(em) / events": {},
- "top length(ex) / values": {},
- "top length(ex) / events": {},
- "top length(mm) / values": {},
- "top length(mm) / events": {},
- "top length(cm) / values": {},
- "top length(cm) / events": {},
- "top length(in) / values": {},
- "top length(in) / events": {},
- "top percentage(%) / values": {},
- "top percentage(%) / events": {},
- "right length(pt) / values": {},
- "right length(pt) / events": {},
- "right length(pc) / values": {},
- "right length(pc) / events": {},
- "right length(px) / values": {},
- "right length(px) / events": {},
- "right length(em) / values": {},
- "right length(em) / events": {},
- "right length(ex) / values": {},
- "right length(ex) / events": {},
- "right length(mm) / values": {},
- "right length(mm) / events": {},
- "right length(cm) / values": {},
- "right length(cm) / events": {},
- "right length(in) / values": {},
- "right length(in) / events": {},
- "right percentage(%) / values": {},
- "right percentage(%) / events": {},
- "bottom length(pt) / values": {},
- "bottom length(pt) / events": {},
- "bottom length(pc) / values": {},
- "bottom length(pc) / events": {},
- "bottom length(px) / values": {},
- "bottom length(px) / events": {},
- "bottom length(em) / values": {},
- "bottom length(em) / events": {},
- "bottom length(ex) / values": {},
- "bottom length(ex) / events": {},
- "bottom length(mm) / values": {},
- "bottom length(mm) / events": {},
- "bottom length(cm) / values": {},
- "bottom length(cm) / events": {},
- "bottom length(in) / values": {},
- "bottom length(in) / events": {},
- "bottom percentage(%) / values": {},
- "bottom percentage(%) / events": {},
- "left length(pt) / values": {},
- "left length(pt) / events": {},
- "left length(pc) / values": {},
- "left length(pc) / events": {},
- "left length(px) / values": {},
- "left length(px) / events": {},
- "left length(em) / values": {},
- "left length(em) / events": {},
- "left length(ex) / values": {},
- "left length(ex) / events": {},
- "left length(mm) / values": {},
- "left length(mm) / events": {},
- "left length(cm) / values": {},
- "left length(cm) / events": {},
- "left length(in) / values": {},
- "left length(in) / events": {},
- "left percentage(%) / values": {},
- "left percentage(%) / events": {},
- "color color(rgba) / values": {},
- "color color(rgba) / events": {},
- "font-size length(pt) / values": {},
- "font-size length(pt) / events": {},
- "font-size length(pc) / values": {},
- "font-size length(pc) / events": {},
- "font-size length(px) / values": {},
- "font-size length(px) / events": {},
- "font-size length(em) / values": {},
- "font-size length(em) / events": {},
- "font-size length(ex) / values": {},
- "font-size length(ex) / events": {},
- "font-size length(mm) / values": {},
- "font-size length(mm) / events": {},
- "font-size length(cm) / values": {},
- "font-size length(cm) / events": {},
- "font-size length(in) / values": {},
- "font-size length(in) / events": {},
- "font-size percentage(%) / values": {},
- "font-size percentage(%) / events": {},
- "font-weight font-weight(keyword) / values": {},
- "font-weight font-weight(keyword) / events": {},
- "font-weight font-weight(numeric) / values": {},
- "font-weight font-weight(numeric) / events": {},
- "line-height number(integer) / values": {},
- "line-height number(integer) / events": {},
- "line-height number(decimal) / values": {},
- "line-height number(decimal) / events": {},
- "line-height length(pt) / values": {},
- "line-height length(pt) / events": {},
- "line-height length(pc) / values": {},
- "line-height length(pc) / events": {},
- "line-height length(px) / values": {},
- "line-height length(px) / events": {},
- "line-height length(em) / values": {},
- "line-height length(em) / events": {},
- "line-height length(ex) / values": {},
- "line-height length(ex) / events": {},
- "line-height length(mm) / values": {},
- "line-height length(mm) / events": {},
- "line-height length(cm) / values": {},
- "line-height length(cm) / events": {},
- "line-height length(in) / values": {},
- "line-height length(in) / events": {},
- "line-height percentage(%) / values": {},
- "line-height percentage(%) / events": {},
- "letter-spacing length(pt) / values": {},
- "letter-spacing length(pt) / events": {},
- "letter-spacing length(pc) / values": {},
- "letter-spacing length(pc) / events": {},
- "letter-spacing length(px) / values": {},
- "letter-spacing length(px) / events": {},
- "letter-spacing length(em) / values": {},
- "letter-spacing length(em) / events": {},
- "letter-spacing length(ex) / values": {},
- "letter-spacing length(ex) / events": {},
- "letter-spacing length(mm) / values": {},
- "letter-spacing length(mm) / events": {},
- "letter-spacing length(cm) / values": {},
- "letter-spacing length(cm) / events": {},
- "letter-spacing length(in) / values": {},
- "letter-spacing length(in) / events": {},
- "word-spacing length(pt) / values": {},
- "word-spacing length(pt) / events": {},
- "word-spacing length(pc) / values": {},
- "word-spacing length(pc) / events": {},
- "word-spacing length(px) / values": {},
- "word-spacing length(px) / events": {},
- "word-spacing length(em) / values": {},
- "word-spacing length(em) / events": {},
- "word-spacing length(ex) / values": {},
- "word-spacing length(ex) / events": {},
- "word-spacing length(mm) / values": {},
- "word-spacing length(mm) / events": {},
- "word-spacing length(cm) / values": {},
- "word-spacing length(cm) / events": {},
- "word-spacing length(in) / values": {},
- "word-spacing length(in) / events": {},
- "word-spacing percentage(%) / values": {},
- "word-spacing percentage(%) / events": {},
- "text-indent length(pt) / values": {},
- "text-indent length(pt) / events": {},
- "text-indent length(pc) / values": {},
- "text-indent length(pc) / events": {},
- "text-indent length(px) / values": {},
- "text-indent length(px) / events": {},
- "text-indent length(em) / values": {},
- "text-indent length(em) / events": {},
- "text-indent length(ex) / values": {},
- "text-indent length(ex) / events": {},
- "text-indent length(mm) / values": {},
- "text-indent length(mm) / events": {},
- "text-indent length(cm) / values": {},
- "text-indent length(cm) / events": {},
- "text-indent length(in) / values": {},
- "text-indent length(in) / events": {},
- "text-indent percentage(%) / values": {},
- "text-indent percentage(%) / events": {},
- "text-shadow shadow(shadow) / values": {},
- "text-shadow shadow(shadow) / events": {},
- "outline-color color(rgba) / values": {},
- "outline-color color(rgba) / events": {},
- "outline-offset length(pt) / values": {},
- "outline-offset length(pt) / events": {},
- "outline-offset length(pc) / values": {},
- "outline-offset length(pc) / events": {},
- "outline-offset length(px) / values": {},
- "outline-offset length(px) / events": {},
- "outline-offset length(em) / values": {},
- "outline-offset length(em) / events": {},
- "outline-offset length(ex) / values": {},
- "outline-offset length(ex) / events": {},
- "outline-offset length(mm) / values": {},
- "outline-offset length(mm) / events": {},
- "outline-offset length(cm) / values": {},
- "outline-offset length(cm) / events": {},
- "outline-offset length(in) / values": {},
- "outline-offset length(in) / events": {},
- "outline-width length(pt) / values": {},
- "outline-width length(pt) / events": {},
- "outline-width length(pc) / values": {},
- "outline-width length(pc) / events": {},
- "outline-width length(px) / values": {},
- "outline-width length(px) / events": {},
- "outline-width length(em) / values": {},
- "outline-width length(em) / events": {},
- "outline-width length(ex) / values": {},
- "outline-width length(ex) / events": {},
- "outline-width length(mm) / values": {},
- "outline-width length(mm) / events": {},
- "outline-width length(cm) / values": {},
- "outline-width length(cm) / events": {},
- "outline-width length(in) / values": {},
- "outline-width length(in) / events": {},
- "clip rectangle(rectangle) / values": {},
- "clip rectangle(rectangle) / events": {},
- "crop rectangle(rectangle) / values": {},
- "crop rectangle(rectangle) / events": {},
- "vertical-align length(pt) / values": {},
- "vertical-align length(pt) / events": {},
- "vertical-align length(pc) / values": {},
- "vertical-align length(pc) / events": {},
- "vertical-align length(px) / values": {},
- "vertical-align length(px) / events": {},
- "vertical-align length(em) / values": {},
- "vertical-align length(em) / events": {},
- "vertical-align length(ex) / values": {},
- "vertical-align length(ex) / events": {},
- "vertical-align length(mm) / values": {},
- "vertical-align length(mm) / events": {},
- "vertical-align length(cm) / values": {},
- "vertical-align length(cm) / events": {},
- "vertical-align length(in) / values": {},
- "vertical-align length(in) / events": {},
- "vertical-align percentage(%) / values": {},
- "vertical-align percentage(%) / events": {},
- "opacity number[0,1](zero-to-one) / values": {},
- "opacity number[0,1](zero-to-one) / events": {},
- "visibility visibility(keyword) / values": {},
- "visibility visibility(keyword) / events": {},
- "z-index integer(integer) / values": {},
- "z-index integer(integer) / events": {}
- }
- */</script>
</head>
<body>
<!-- required by testharnessreport.js -->
diff --git a/tests/wpt/web-platform-tests/css/css-transitions/properties-value-inherit-002.html b/tests/wpt/web-platform-tests/css/css-transitions/properties-value-inherit-002.html
index 14a36d513e8..f2741bd16e1 100644
--- a/tests/wpt/web-platform-tests/css/css-transitions/properties-value-inherit-002.html
+++ b/tests/wpt/web-platform-tests/css/css-transitions/properties-value-inherit-002.html
@@ -26,573 +26,6 @@
height: 100000px;
}
</style>
-
- <script id="metadata_cache">/*
- {
- "background-color color(rgba) / values": {},
- "background-color color(rgba) / events": {},
- "background-position length(pt) / values": {},
- "background-position length(pt) / events": {},
- "background-position length(pc) / values": {},
- "background-position length(pc) / events": {},
- "background-position length(px) / values": {},
- "background-position length(px) / events": {},
- "background-position length(em) / values": {},
- "background-position length(em) / events": {},
- "background-position length(ex) / values": {},
- "background-position length(ex) / events": {},
- "background-position length(mm) / values": {},
- "background-position length(mm) / events": {},
- "background-position length(cm) / values": {},
- "background-position length(cm) / events": {},
- "background-position length(in) / values": {},
- "background-position length(in) / events": {},
- "background-position percentage(%) / values": {},
- "background-position percentage(%) / events": {},
- "border-top-width length(pt) / values": {},
- "border-top-width length(pt) / events": {},
- "border-top-width length(pc) / values": {},
- "border-top-width length(pc) / events": {},
- "border-top-width length(px) / values": {},
- "border-top-width length(px) / events": {},
- "border-top-width length(em) / values": {},
- "border-top-width length(em) / events": {},
- "border-top-width length(ex) / values": {},
- "border-top-width length(ex) / events": {},
- "border-top-width length(mm) / values": {},
- "border-top-width length(mm) / events": {},
- "border-top-width length(cm) / values": {},
- "border-top-width length(cm) / events": {},
- "border-top-width length(in) / values": {},
- "border-top-width length(in) / events": {},
- "border-right-width length(pt) / values": {},
- "border-right-width length(pt) / events": {},
- "border-right-width length(pc) / values": {},
- "border-right-width length(pc) / events": {},
- "border-right-width length(px) / values": {},
- "border-right-width length(px) / events": {},
- "border-right-width length(em) / values": {},
- "border-right-width length(em) / events": {},
- "border-right-width length(ex) / values": {},
- "border-right-width length(ex) / events": {},
- "border-right-width length(mm) / values": {},
- "border-right-width length(mm) / events": {},
- "border-right-width length(cm) / values": {},
- "border-right-width length(cm) / events": {},
- "border-right-width length(in) / values": {},
- "border-right-width length(in) / events": {},
- "border-bottom-width length(pt) / values": {},
- "border-bottom-width length(pt) / events": {},
- "border-bottom-width length(pc) / values": {},
- "border-bottom-width length(pc) / events": {},
- "border-bottom-width length(px) / values": {},
- "border-bottom-width length(px) / events": {},
- "border-bottom-width length(em) / values": {},
- "border-bottom-width length(em) / events": {},
- "border-bottom-width length(ex) / values": {},
- "border-bottom-width length(ex) / events": {},
- "border-bottom-width length(mm) / values": {},
- "border-bottom-width length(mm) / events": {},
- "border-bottom-width length(cm) / values": {},
- "border-bottom-width length(cm) / events": {},
- "border-bottom-width length(in) / values": {},
- "border-bottom-width length(in) / events": {},
- "border-left-width length(pt) / values": {},
- "border-left-width length(pt) / events": {},
- "border-left-width length(pc) / values": {},
- "border-left-width length(pc) / events": {},
- "border-left-width length(px) / values": {},
- "border-left-width length(px) / events": {},
- "border-left-width length(em) / values": {},
- "border-left-width length(em) / events": {},
- "border-left-width length(ex) / values": {},
- "border-left-width length(ex) / events": {},
- "border-left-width length(mm) / values": {},
- "border-left-width length(mm) / events": {},
- "border-left-width length(cm) / values": {},
- "border-left-width length(cm) / events": {},
- "border-left-width length(in) / values": {},
- "border-left-width length(in) / events": {},
- "border-top-color color(rgba) / values": {},
- "border-top-color color(rgba) / events": {},
- "border-right-color color(rgba) / values": {},
- "border-right-color color(rgba) / events": {},
- "border-bottom-color color(rgba) / values": {},
- "border-bottom-color color(rgba) / events": {},
- "border-left-color color(rgba) / values": {},
- "border-left-color color(rgba) / events": {},
- "padding-bottom length(pt) / values": {},
- "padding-bottom length(pt) / events": {},
- "padding-bottom length(pc) / values": {},
- "padding-bottom length(pc) / events": {},
- "padding-bottom length(px) / values": {},
- "padding-bottom length(px) / events": {},
- "padding-bottom length(em) / values": {},
- "padding-bottom length(em) / events": {},
- "padding-bottom length(ex) / values": {},
- "padding-bottom length(ex) / events": {},
- "padding-bottom length(mm) / values": {},
- "padding-bottom length(mm) / events": {},
- "padding-bottom length(cm) / values": {},
- "padding-bottom length(cm) / events": {},
- "padding-bottom length(in) / values": {},
- "padding-bottom length(in) / events": {},
- "padding-left length(pt) / values": {},
- "padding-left length(pt) / events": {},
- "padding-left length(pc) / values": {},
- "padding-left length(pc) / events": {},
- "padding-left length(px) / values": {},
- "padding-left length(px) / events": {},
- "padding-left length(em) / values": {},
- "padding-left length(em) / events": {},
- "padding-left length(ex) / values": {},
- "padding-left length(ex) / events": {},
- "padding-left length(mm) / values": {},
- "padding-left length(mm) / events": {},
- "padding-left length(cm) / values": {},
- "padding-left length(cm) / events": {},
- "padding-left length(in) / values": {},
- "padding-left length(in) / events": {},
- "padding-right length(pt) / values": {},
- "padding-right length(pt) / events": {},
- "padding-right length(pc) / values": {},
- "padding-right length(pc) / events": {},
- "padding-right length(px) / values": {},
- "padding-right length(px) / events": {},
- "padding-right length(em) / values": {},
- "padding-right length(em) / events": {},
- "padding-right length(ex) / values": {},
- "padding-right length(ex) / events": {},
- "padding-right length(mm) / values": {},
- "padding-right length(mm) / events": {},
- "padding-right length(cm) / values": {},
- "padding-right length(cm) / events": {},
- "padding-right length(in) / values": {},
- "padding-right length(in) / events": {},
- "padding-top length(pt) / values": {},
- "padding-top length(pt) / events": {},
- "padding-top length(pc) / values": {},
- "padding-top length(pc) / events": {},
- "padding-top length(px) / values": {},
- "padding-top length(px) / events": {},
- "padding-top length(em) / values": {},
- "padding-top length(em) / events": {},
- "padding-top length(ex) / values": {},
- "padding-top length(ex) / events": {},
- "padding-top length(mm) / values": {},
- "padding-top length(mm) / events": {},
- "padding-top length(cm) / values": {},
- "padding-top length(cm) / events": {},
- "padding-top length(in) / values": {},
- "padding-top length(in) / events": {},
- "margin-bottom length(pt) / values": {},
- "margin-bottom length(pt) / events": {},
- "margin-bottom length(pc) / values": {},
- "margin-bottom length(pc) / events": {},
- "margin-bottom length(px) / values": {},
- "margin-bottom length(px) / events": {},
- "margin-bottom length(em) / values": {},
- "margin-bottom length(em) / events": {},
- "margin-bottom length(ex) / values": {},
- "margin-bottom length(ex) / events": {},
- "margin-bottom length(mm) / values": {},
- "margin-bottom length(mm) / events": {},
- "margin-bottom length(cm) / values": {},
- "margin-bottom length(cm) / events": {},
- "margin-bottom length(in) / values": {},
- "margin-bottom length(in) / events": {},
- "margin-left length(pt) / values": {},
- "margin-left length(pt) / events": {},
- "margin-left length(pc) / values": {},
- "margin-left length(pc) / events": {},
- "margin-left length(px) / values": {},
- "margin-left length(px) / events": {},
- "margin-left length(em) / values": {},
- "margin-left length(em) / events": {},
- "margin-left length(ex) / values": {},
- "margin-left length(ex) / events": {},
- "margin-left length(mm) / values": {},
- "margin-left length(mm) / events": {},
- "margin-left length(cm) / values": {},
- "margin-left length(cm) / events": {},
- "margin-left length(in) / values": {},
- "margin-left length(in) / events": {},
- "margin-right length(pt) / values": {},
- "margin-right length(pt) / events": {},
- "margin-right length(pc) / values": {},
- "margin-right length(pc) / events": {},
- "margin-right length(px) / values": {},
- "margin-right length(px) / events": {},
- "margin-right length(em) / values": {},
- "margin-right length(em) / events": {},
- "margin-right length(ex) / values": {},
- "margin-right length(ex) / events": {},
- "margin-right length(mm) / values": {},
- "margin-right length(mm) / events": {},
- "margin-right length(cm) / values": {},
- "margin-right length(cm) / events": {},
- "margin-right length(in) / values": {},
- "margin-right length(in) / events": {},
- "margin-top length(pt) / values": {},
- "margin-top length(pt) / events": {},
- "margin-top length(pc) / values": {},
- "margin-top length(pc) / events": {},
- "margin-top length(px) / values": {},
- "margin-top length(px) / events": {},
- "margin-top length(em) / values": {},
- "margin-top length(em) / events": {},
- "margin-top length(ex) / values": {},
- "margin-top length(ex) / events": {},
- "margin-top length(mm) / values": {},
- "margin-top length(mm) / events": {},
- "margin-top length(cm) / values": {},
- "margin-top length(cm) / events": {},
- "margin-top length(in) / values": {},
- "margin-top length(in) / events": {},
- "height length(pt) / values": {},
- "height length(pt) / events": {},
- "height length(pc) / values": {},
- "height length(pc) / events": {},
- "height length(px) / values": {},
- "height length(px) / events": {},
- "height length(em) / values": {},
- "height length(em) / events": {},
- "height length(ex) / values": {},
- "height length(ex) / events": {},
- "height length(mm) / values": {},
- "height length(mm) / events": {},
- "height length(cm) / values": {},
- "height length(cm) / events": {},
- "height length(in) / values": {},
- "height length(in) / events": {},
- "height percentage(%) / values": {},
- "height percentage(%) / events": {},
- "width length(pt) / values": {},
- "width length(pt) / events": {},
- "width length(pc) / values": {},
- "width length(pc) / events": {},
- "width length(px) / values": {},
- "width length(px) / events": {},
- "width length(em) / values": {},
- "width length(em) / events": {},
- "width length(ex) / values": {},
- "width length(ex) / events": {},
- "width length(mm) / values": {},
- "width length(mm) / events": {},
- "width length(cm) / values": {},
- "width length(cm) / events": {},
- "width length(in) / values": {},
- "width length(in) / events": {},
- "width percentage(%) / values": {},
- "width percentage(%) / events": {},
- "min-height length(pt) / values": {},
- "min-height length(pt) / events": {},
- "min-height length(pc) / values": {},
- "min-height length(pc) / events": {},
- "min-height length(px) / values": {},
- "min-height length(px) / events": {},
- "min-height length(em) / values": {},
- "min-height length(em) / events": {},
- "min-height length(ex) / values": {},
- "min-height length(ex) / events": {},
- "min-height length(mm) / values": {},
- "min-height length(mm) / events": {},
- "min-height length(cm) / values": {},
- "min-height length(cm) / events": {},
- "min-height length(in) / values": {},
- "min-height length(in) / events": {},
- "min-height percentage(%) / values": {},
- "min-height percentage(%) / events": {},
- "min-width length(pt) / values": {},
- "min-width length(pt) / events": {},
- "min-width length(pc) / values": {},
- "min-width length(pc) / events": {},
- "min-width length(px) / values": {},
- "min-width length(px) / events": {},
- "min-width length(em) / values": {},
- "min-width length(em) / events": {},
- "min-width length(ex) / values": {},
- "min-width length(ex) / events": {},
- "min-width length(mm) / values": {},
- "min-width length(mm) / events": {},
- "min-width length(cm) / values": {},
- "min-width length(cm) / events": {},
- "min-width length(in) / values": {},
- "min-width length(in) / events": {},
- "min-width percentage(%) / values": {},
- "min-width percentage(%) / events": {},
- "max-height length(pt) / values": {},
- "max-height length(pt) / events": {},
- "max-height length(pc) / values": {},
- "max-height length(pc) / events": {},
- "max-height length(px) / values": {},
- "max-height length(px) / events": {},
- "max-height length(em) / values": {},
- "max-height length(em) / events": {},
- "max-height length(ex) / values": {},
- "max-height length(ex) / events": {},
- "max-height length(mm) / values": {},
- "max-height length(mm) / events": {},
- "max-height length(cm) / values": {},
- "max-height length(cm) / events": {},
- "max-height length(in) / values": {},
- "max-height length(in) / events": {},
- "max-height percentage(%) / values": {},
- "max-height percentage(%) / events": {},
- "max-width length(pt) / values": {},
- "max-width length(pt) / events": {},
- "max-width length(pc) / values": {},
- "max-width length(pc) / events": {},
- "max-width length(px) / values": {},
- "max-width length(px) / events": {},
- "max-width length(em) / values": {},
- "max-width length(em) / events": {},
- "max-width length(ex) / values": {},
- "max-width length(ex) / events": {},
- "max-width length(mm) / values": {},
- "max-width length(mm) / events": {},
- "max-width length(cm) / values": {},
- "max-width length(cm) / events": {},
- "max-width length(in) / values": {},
- "max-width length(in) / events": {},
- "max-width percentage(%) / values": {},
- "max-width percentage(%) / events": {},
- "top length(pt) / values": {},
- "top length(pt) / events": {},
- "top length(pc) / values": {},
- "top length(pc) / events": {},
- "top length(px) / values": {},
- "top length(px) / events": {},
- "top length(em) / values": {},
- "top length(em) / events": {},
- "top length(ex) / values": {},
- "top length(ex) / events": {},
- "top length(mm) / values": {},
- "top length(mm) / events": {},
- "top length(cm) / values": {},
- "top length(cm) / events": {},
- "top length(in) / values": {},
- "top length(in) / events": {},
- "top percentage(%) / values": {},
- "top percentage(%) / events": {},
- "right length(pt) / values": {},
- "right length(pt) / events": {},
- "right length(pc) / values": {},
- "right length(pc) / events": {},
- "right length(px) / values": {},
- "right length(px) / events": {},
- "right length(em) / values": {},
- "right length(em) / events": {},
- "right length(ex) / values": {},
- "right length(ex) / events": {},
- "right length(mm) / values": {},
- "right length(mm) / events": {},
- "right length(cm) / values": {},
- "right length(cm) / events": {},
- "right length(in) / values": {},
- "right length(in) / events": {},
- "right percentage(%) / values": {},
- "right percentage(%) / events": {},
- "bottom length(pt) / values": {},
- "bottom length(pt) / events": {},
- "bottom length(pc) / values": {},
- "bottom length(pc) / events": {},
- "bottom length(px) / values": {},
- "bottom length(px) / events": {},
- "bottom length(em) / values": {},
- "bottom length(em) / events": {},
- "bottom length(ex) / values": {},
- "bottom length(ex) / events": {},
- "bottom length(mm) / values": {},
- "bottom length(mm) / events": {},
- "bottom length(cm) / values": {},
- "bottom length(cm) / events": {},
- "bottom length(in) / values": {},
- "bottom length(in) / events": {},
- "bottom percentage(%) / values": {},
- "bottom percentage(%) / events": {},
- "left length(pt) / values": {},
- "left length(pt) / events": {},
- "left length(pc) / values": {},
- "left length(pc) / events": {},
- "left length(px) / values": {},
- "left length(px) / events": {},
- "left length(em) / values": {},
- "left length(em) / events": {},
- "left length(ex) / values": {},
- "left length(ex) / events": {},
- "left length(mm) / values": {},
- "left length(mm) / events": {},
- "left length(cm) / values": {},
- "left length(cm) / events": {},
- "left length(in) / values": {},
- "left length(in) / events": {},
- "left percentage(%) / values": {},
- "left percentage(%) / events": {},
- "color color(rgba) / values": {},
- "color color(rgba) / events": {},
- "font-size length(pt) / values": {},
- "font-size length(pt) / events": {},
- "font-size length(pc) / values": {},
- "font-size length(pc) / events": {},
- "font-size length(px) / values": {},
- "font-size length(px) / events": {},
- "font-size length(em) / values": {},
- "font-size length(em) / events": {},
- "font-size length(ex) / values": {},
- "font-size length(ex) / events": {},
- "font-size length(mm) / values": {},
- "font-size length(mm) / events": {},
- "font-size length(cm) / values": {},
- "font-size length(cm) / events": {},
- "font-size length(in) / values": {},
- "font-size length(in) / events": {},
- "font-size percentage(%) / values": {},
- "font-size percentage(%) / events": {},
- "font-weight font-weight(keyword) / values": {},
- "font-weight font-weight(keyword) / events": {},
- "font-weight font-weight(numeric) / values": {},
- "font-weight font-weight(numeric) / events": {},
- "line-height number(integer) / values": {},
- "line-height number(integer) / events": {},
- "line-height number(decimal) / values": {},
- "line-height number(decimal) / events": {},
- "line-height length(pt) / values": {},
- "line-height length(pt) / events": {},
- "line-height length(pc) / values": {},
- "line-height length(pc) / events": {},
- "line-height length(px) / values": {},
- "line-height length(px) / events": {},
- "line-height length(em) / values": {},
- "line-height length(em) / events": {},
- "line-height length(ex) / values": {},
- "line-height length(ex) / events": {},
- "line-height length(mm) / values": {},
- "line-height length(mm) / events": {},
- "line-height length(cm) / values": {},
- "line-height length(cm) / events": {},
- "line-height length(in) / values": {},
- "line-height length(in) / events": {},
- "line-height percentage(%) / values": {},
- "line-height percentage(%) / events": {},
- "letter-spacing length(pt) / values": {},
- "letter-spacing length(pt) / events": {},
- "letter-spacing length(pc) / values": {},
- "letter-spacing length(pc) / events": {},
- "letter-spacing length(px) / values": {},
- "letter-spacing length(px) / events": {},
- "letter-spacing length(em) / values": {},
- "letter-spacing length(em) / events": {},
- "letter-spacing length(ex) / values": {},
- "letter-spacing length(ex) / events": {},
- "letter-spacing length(mm) / values": {},
- "letter-spacing length(mm) / events": {},
- "letter-spacing length(cm) / values": {},
- "letter-spacing length(cm) / events": {},
- "letter-spacing length(in) / values": {},
- "letter-spacing length(in) / events": {},
- "word-spacing length(pt) / values": {},
- "word-spacing length(pt) / events": {},
- "word-spacing length(pc) / values": {},
- "word-spacing length(pc) / events": {},
- "word-spacing length(px) / values": {},
- "word-spacing length(px) / events": {},
- "word-spacing length(em) / values": {},
- "word-spacing length(em) / events": {},
- "word-spacing length(ex) / values": {},
- "word-spacing length(ex) / events": {},
- "word-spacing length(mm) / values": {},
- "word-spacing length(mm) / events": {},
- "word-spacing length(cm) / values": {},
- "word-spacing length(cm) / events": {},
- "word-spacing length(in) / values": {},
- "word-spacing length(in) / events": {},
- "word-spacing percentage(%) / values": {},
- "word-spacing percentage(%) / events": {},
- "text-indent length(pt) / values": {},
- "text-indent length(pt) / events": {},
- "text-indent length(pc) / values": {},
- "text-indent length(pc) / events": {},
- "text-indent length(px) / values": {},
- "text-indent length(px) / events": {},
- "text-indent length(em) / values": {},
- "text-indent length(em) / events": {},
- "text-indent length(ex) / values": {},
- "text-indent length(ex) / events": {},
- "text-indent length(mm) / values": {},
- "text-indent length(mm) / events": {},
- "text-indent length(cm) / values": {},
- "text-indent length(cm) / events": {},
- "text-indent length(in) / values": {},
- "text-indent length(in) / events": {},
- "text-indent percentage(%) / values": {},
- "text-indent percentage(%) / events": {},
- "text-shadow shadow(shadow) / values": {},
- "text-shadow shadow(shadow) / events": {},
- "outline-color color(rgba) / values": {},
- "outline-color color(rgba) / events": {},
- "outline-offset length(pt) / values": {},
- "outline-offset length(pt) / events": {},
- "outline-offset length(pc) / values": {},
- "outline-offset length(pc) / events": {},
- "outline-offset length(px) / values": {},
- "outline-offset length(px) / events": {},
- "outline-offset length(em) / values": {},
- "outline-offset length(em) / events": {},
- "outline-offset length(ex) / values": {},
- "outline-offset length(ex) / events": {},
- "outline-offset length(mm) / values": {},
- "outline-offset length(mm) / events": {},
- "outline-offset length(cm) / values": {},
- "outline-offset length(cm) / events": {},
- "outline-offset length(in) / values": {},
- "outline-offset length(in) / events": {},
- "outline-width length(pt) / values": {},
- "outline-width length(pt) / events": {},
- "outline-width length(pc) / values": {},
- "outline-width length(pc) / events": {},
- "outline-width length(px) / values": {},
- "outline-width length(px) / events": {},
- "outline-width length(em) / values": {},
- "outline-width length(em) / events": {},
- "outline-width length(ex) / values": {},
- "outline-width length(ex) / events": {},
- "outline-width length(mm) / values": {},
- "outline-width length(mm) / events": {},
- "outline-width length(cm) / values": {},
- "outline-width length(cm) / events": {},
- "outline-width length(in) / values": {},
- "outline-width length(in) / events": {},
- "clip rectangle(rectangle) / values": {},
- "clip rectangle(rectangle) / events": {},
- "crop rectangle(rectangle) / values": {},
- "crop rectangle(rectangle) / events": {},
- "vertical-align length(pt) / values": {},
- "vertical-align length(pt) / events": {},
- "vertical-align length(pc) / values": {},
- "vertical-align length(pc) / events": {},
- "vertical-align length(px) / values": {},
- "vertical-align length(px) / events": {},
- "vertical-align length(em) / values": {},
- "vertical-align length(em) / events": {},
- "vertical-align length(ex) / values": {},
- "vertical-align length(ex) / events": {},
- "vertical-align length(mm) / values": {},
- "vertical-align length(mm) / events": {},
- "vertical-align length(cm) / values": {},
- "vertical-align length(cm) / events": {},
- "vertical-align length(in) / values": {},
- "vertical-align length(in) / events": {},
- "vertical-align percentage(%) / values": {},
- "vertical-align percentage(%) / events": {},
- "opacity number[0,1](zero-to-one) / values": {},
- "opacity number[0,1](zero-to-one) / events": {},
- "visibility visibility(keyword) / values": {},
- "visibility visibility(keyword) / events": {},
- "z-index integer(integer) / values": {},
- "z-index integer(integer) / events": {}
- }
- */</script>
</head>
<body>
<!-- required by testharnessreport.js -->
diff --git a/tests/wpt/web-platform-tests/css/css-transitions/properties-value-inherit-003.html b/tests/wpt/web-platform-tests/css/css-transitions/properties-value-inherit-003.html
index d8d3e8eb75b..43d0229613a 100644
--- a/tests/wpt/web-platform-tests/css/css-transitions/properties-value-inherit-003.html
+++ b/tests/wpt/web-platform-tests/css/css-transitions/properties-value-inherit-003.html
@@ -26,71 +26,6 @@
height: 100000px;
}
</style>
-
- <script id="metadata_cache">/*
- {
- "background-position length-em(em) / values": {},
- "background-position length-em(em) / events": {},
- "border-top-width length-em(em) / values": {},
- "border-top-width length-em(em) / events": {},
- "border-right-width length-em(em) / values": {},
- "border-right-width length-em(em) / events": {},
- "border-bottom-width length-em(em) / values": {},
- "border-bottom-width length-em(em) / events": {},
- "border-left-width length-em(em) / values": {},
- "border-left-width length-em(em) / events": {},
- "padding-bottom length-em(em) / values": {},
- "padding-bottom length-em(em) / events": {},
- "padding-left length-em(em) / values": {},
- "padding-left length-em(em) / events": {},
- "padding-right length-em(em) / values": {},
- "padding-right length-em(em) / events": {},
- "padding-top length-em(em) / values": {},
- "padding-top length-em(em) / events": {},
- "margin-bottom length-em(em) / values": {},
- "margin-bottom length-em(em) / events": {},
- "margin-left length-em(em) / values": {},
- "margin-left length-em(em) / events": {},
- "margin-right length-em(em) / values": {},
- "margin-right length-em(em) / events": {},
- "margin-top length-em(em) / values": {},
- "margin-top length-em(em) / events": {},
- "height length-em(em) / values": {},
- "height length-em(em) / events": {},
- "width length-em(em) / values": {},
- "width length-em(em) / events": {},
- "min-height length-em(em) / values": {},
- "min-height length-em(em) / events": {},
- "min-width length-em(em) / values": {},
- "min-width length-em(em) / events": {},
- "max-height length-em(em) / values": {},
- "max-height length-em(em) / events": {},
- "max-width length-em(em) / values": {},
- "max-width length-em(em) / events": {},
- "top length-em(em) / values": {},
- "top length-em(em) / events": {},
- "right length-em(em) / values": {},
- "right length-em(em) / events": {},
- "bottom length-em(em) / values": {},
- "bottom length-em(em) / events": {},
- "left length-em(em) / values": {},
- "left length-em(em) / events": {},
- "line-height length-em(em) / values": {},
- "line-height length-em(em) / events": {},
- "letter-spacing length-em(em) / values": {},
- "letter-spacing length-em(em) / events": {},
- "word-spacing length-em(em) / values": {},
- "word-spacing length-em(em) / events": {},
- "text-indent length-em(em) / values": {},
- "text-indent length-em(em) / events": {},
- "outline-offset length-em(em) / values": {},
- "outline-offset length-em(em) / events": {},
- "outline-width length-em(em) / values": {},
- "outline-width length-em(em) / events": {},
- "vertical-align length-em(em) / values": {},
- "vertical-align length-em(em) / events": {}
- }
- */</script>
</head>
<body>
<!-- required by testharnessreport.js -->
diff --git a/tests/wpt/web-platform-tests/css/css-transitions/pseudo-elements-001.html b/tests/wpt/web-platform-tests/css/css-transitions/pseudo-elements-001.html
index ceaff564077..cf1d2545b24 100644
--- a/tests/wpt/web-platform-tests/css/css-transitions/pseudo-elements-001.html
+++ b/tests/wpt/web-platform-tests/css/css-transitions/pseudo-elements-001.html
@@ -28,15 +28,6 @@
height: 100000px;
}
</style>
-
- <script id="metadata_cache">/*
- {
- "transition padding-left on :before / values": {},
- "transition padding-left on :after / values": {},
- "transition padding-left on :before, changing content / values": {},
- "transition padding-left on :after, changing content / values": {}
- }
- */</script>
</head>
<body>
<!-- required by testharnessreport.js -->
diff --git a/tests/wpt/web-platform-tests/css/css-transitions/transition-001.html b/tests/wpt/web-platform-tests/css/css-transitions/transition-001.html
index 8b27eb21596..bf01393bbba 100644
--- a/tests/wpt/web-platform-tests/css/css-transitions/transition-001.html
+++ b/tests/wpt/web-platform-tests/css/css-transitions/transition-001.html
@@ -13,23 +13,6 @@
<script src="./support/vendorPrefix.js" type="text/javascript"></script>
<script src="./support/helper.js" type="text/javascript"></script>
-
- <script id="metadata_cache">/*
- {
- "parse '1s'": {},
- "parse '1s 2s'": {},
- "parse '1s 2s ease-in'": {},
- "parse '1s ease-in 2s'": {},
- "parse 'ease-in 1s 2s'": {},
- "parse '1s width'": {},
- "parse 'width 1s'": {},
- "parse '1s width 2s'": {},
- "parse '1s 2s width ease-in'": {},
- "parse '1s ease-in 2s width'": {},
- "parse 'width ease-in 1s 2s'": {},
- "parse 'width .1s ease-in .2s'": {}
- }
- */</script>
</head>
<body>
<!-- required by testharnessreport.js -->
diff --git a/tests/wpt/web-platform-tests/css/css-transitions/transition-delay-001.html b/tests/wpt/web-platform-tests/css/css-transitions/transition-delay-001.html
index d58b003d974..921525ea72d 100644
--- a/tests/wpt/web-platform-tests/css/css-transitions/transition-delay-001.html
+++ b/tests/wpt/web-platform-tests/css/css-transitions/transition-delay-001.html
@@ -14,32 +14,6 @@
<script src="./support/vendorPrefix.js" type="text/javascript"></script>
<script src="./support/helper.js" type="text/javascript"></script>
-
- <script id="metadata_cache">/*
- {
- "parse '10.2s'": {},
- "parse '1s'": {},
- "parse '0.1s'": {},
- "parse '0.01s'": {},
- "parse '0.001s'": {},
- "parse '0.009s'": {},
- "parse '0s'": {},
- "parse '.0s'": {},
- "parse '0.0s'": {},
- "parse '.3s'": {},
- "parse '-5s'": {},
- "parse '10200ms'": {},
- "parse '1000ms'": {},
- "parse '100ms'": {},
- "parse '10ms'": {},
- "parse '9ms'": {},
- "parse '1ms'": {},
- "parse '0ms'": {},
- "parse '-500ms'": {},
- "parse '1s, 0.1s, 10ms'": {},
- "parse 'foobar'": { "flags": "invalid" }
- }
- */</script>
</head>
<body>
<!-- required by testharnessreport.js -->
diff --git a/tests/wpt/web-platform-tests/css/css-transitions/transition-duration-001.html b/tests/wpt/web-platform-tests/css/css-transitions/transition-duration-001.html
index 9b7fe1e0b4d..b5c095f001e 100644
--- a/tests/wpt/web-platform-tests/css/css-transitions/transition-duration-001.html
+++ b/tests/wpt/web-platform-tests/css/css-transitions/transition-duration-001.html
@@ -14,32 +14,6 @@
<script src="./support/vendorPrefix.js" type="text/javascript"></script>
<script src="./support/helper.js" type="text/javascript"></script>
-
- <script id="metadata_cache">/*
- {
- "parse '10.2s'": {},
- "parse '1s'": {},
- "parse '0.1s'": {},
- "parse '0.01s'": {},
- "parse '0.001s'": {},
- "parse '0.009s'": {},
- "parse '0s'": {},
- "parse '.0s'": {},
- "parse '0.0s'": {},
- "parse '.3s'": {},
- "parse '-5s'": { "flags": "invalid" },
- "parse '10200ms'": {},
- "parse '1000ms'": {},
- "parse '100ms'": {},
- "parse '10ms'": {},
- "parse '9ms'": {},
- "parse '1ms'": {},
- "parse '0ms'": {},
- "parse '-500ms'": { "flags": "invalid" },
- "parse '1s, 0.1s, 10ms'": {},
- "parse 'foobar'": { "flags": "invalid" }
- }
- */</script>
</head>
<body>
<!-- required by testharnessreport.js -->
diff --git a/tests/wpt/web-platform-tests/css/css-transitions/transition-property-001.html b/tests/wpt/web-platform-tests/css/css-transitions/transition-property-001.html
index ad078bc1b45..47a1417070f 100644
--- a/tests/wpt/web-platform-tests/css/css-transitions/transition-property-001.html
+++ b/tests/wpt/web-platform-tests/css/css-transitions/transition-property-001.html
@@ -13,16 +13,6 @@
<script src="./support/vendorPrefix.js" type="text/javascript"></script>
<script src="./support/helper.js" type="text/javascript"></script>
-
- <script id="metadata_cache">/*
- {
- "parse 'none'": {},
- "parse 'all'": {},
- "parse 'width'": {},
- "parse 'all, width'": {},
- "parse 'width, all'": {}
- }
- */</script>
</head>
<body>
<!-- required by testharnessreport.js -->
diff --git a/tests/wpt/web-platform-tests/css/css-transitions/transition-property-002.html b/tests/wpt/web-platform-tests/css/css-transitions/transition-property-002.html
index 504b0a0ba63..99196b6d1d4 100644
--- a/tests/wpt/web-platform-tests/css/css-transitions/transition-property-002.html
+++ b/tests/wpt/web-platform-tests/css/css-transitions/transition-property-002.html
@@ -13,18 +13,6 @@
<script src="./support/vendorPrefix.js" type="text/javascript"></script>
<script src="./support/helper.js" type="text/javascript"></script>
-
- <script id="metadata_cache">/*
- {
- "parse 'none, all'": {},
- "parse 'all, none'": {},
- "parse 'foobar'": {},
- "parse 'all, foobar'": {},
- "parse 'foobar, all'": {},
- "parse 'inherit'": {},
- "parse 'initial'": {}
- }
- */</script>
</head>
<body>
<!-- required by testharnessreport.js -->
diff --git a/tests/wpt/web-platform-tests/css/css-transitions/transition-timing-function-001.html b/tests/wpt/web-platform-tests/css/css-transitions/transition-timing-function-001.html
index c51ac05c711..68669c7d126 100644
--- a/tests/wpt/web-platform-tests/css/css-transitions/transition-timing-function-001.html
+++ b/tests/wpt/web-platform-tests/css/css-transitions/transition-timing-function-001.html
@@ -13,31 +13,6 @@
<script src="./support/vendorPrefix.js" type="text/javascript"></script>
<script src="./support/helper.js" type="text/javascript"></script>
-
- <script id="metadata_cache">/*
- {
- "parse 'ease'": {},
- "parse 'linear'": {},
- "parse 'ease-in'": {},
- "parse 'ease-out'": {},
- "parse 'ease-in-out'": {},
- "parse 'step-start'": {},
- "parse 'step-end'": {},
- "parse 'cubic-bezier(0.1, 0.2, 0.3, 0.4)'": {},
- "parse 'cubic-bezier(0.1, -0.2, 0.3, -0.4)'": {},
- "parse 'cubic-bezier(0.1, 1.2, 0.3, 1.4)'": {},
- "parse 'steps(3, start)'": {},
- "parse 'steps(3, end)'": {},
- "parse 'steps(3)'": {},
- "parse 'cubic-bezier(foobar)'": { "flags": "invalid" },
- "parse 'steps(foobar)'": { "flags": "invalid" },
- "parse 'steps(3.3, end)'": { "flags": "invalid" },
- "parse 'steps(3, top)'": { "flags": "invalid" },
- "parse 'steps(-3, top)'": { "flags": "invalid" },
- "parse 'cubic-bezier(-0.1, -0.2, -0.3, -0.4)'": { "flags": "invalid" },
- "parse 'cubic-bezier(1.1, 1.2, 1.3, 1.4)'": { "flags": "invalid" }
- }
- */</script>
</head>
<body>
<!-- required by testharnessreport.js -->
diff --git a/tests/wpt/web-platform-tests/css/css-typed-om/factory-absolute-length.html b/tests/wpt/web-platform-tests/css/css-typed-om/factory-absolute-length.html
index a65cf5d44e3..5712ca99f8e 100644
--- a/tests/wpt/web-platform-tests/css/css-typed-om/factory-absolute-length.html
+++ b/tests/wpt/web-platform-tests/css/css-typed-om/factory-absolute-length.html
@@ -26,11 +26,11 @@
}, 'CSS.mm() produces mm length');
test(function(){
- var length = CSS.q(30);
+ var length = CSS.Q(30);
assert_true(length instanceof CSSUnitValue);
assert_equals(length.value, 30);
assert_equals(length.unit, 'q');
- }, 'CSS.q() produces q length');
+ }, 'CSS.Q() produces q length');
test(function(){
var length = CSS.in(40);
diff --git a/tests/wpt/web-platform-tests/css/css-typed-om/styleMap-update-function.html b/tests/wpt/web-platform-tests/css/css-typed-om/styleMap-update-function.html
index 4dea0095120..19f63997694 100644
--- a/tests/wpt/web-platform-tests/css/css-typed-om/styleMap-update-function.html
+++ b/tests/wpt/web-platform-tests/css/css-typed-om/styleMap-update-function.html
@@ -10,7 +10,7 @@
<script>
test(function() {
element.attributeStyleMap.set('width', new CSSUnitValue(42, 'px'));
- element.attributeStyleMap.update('width', length => new CSSSimpleLength(length.value + 20, length.type))
+ element.attributeStyleMap.update('width', length => new CSSUnitValue(length.value + 20, length.unit))
assert_equals(element.attributeStyleMap.get('width').value, 62, 'update expected to apply callback to old value in map');
});
</script>
diff --git a/tests/wpt/web-platform-tests/css/css-typed-om/stylevalue-objects/interface.html b/tests/wpt/web-platform-tests/css/css-typed-om/stylevalue-objects/interface.html
new file mode 100644
index 00000000000..8d346b1ab9a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-typed-om/stylevalue-objects/interface.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>CSSStyleValue IDL</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#stylevalue-objects">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+<script type="text/plain" id="idl">
+interface CSSStyleValue {
+ stringifier;
+ static CSSStyleValue? parse(DOMString property, DOMString cssText);
+ static sequence<CSSStyleValue>? parseAll(DOMString property, DOMString cssText);
+};
+</script>
+<script>
+'use strict';
+const idlArray = new IdlArray();
+idlArray.add_idls(document.getElementById('idl').textContent);
+idlArray.test();
+</script>
diff --git a/tests/wpt/web-platform-tests/css/css-typed-om/stylevalue-subclasses/cssKeywordValue-interface.html b/tests/wpt/web-platform-tests/css/css-typed-om/stylevalue-subclasses/cssKeywordValue-interface.html
new file mode 100644
index 00000000000..444e08093ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-typed-om/stylevalue-subclasses/cssKeywordValue-interface.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>CSSKeywordValue IDL</title>
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#keywordvalue-objects">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+<script type="text/plain" id="idl">
+[Constructor(DOMString value)]
+interface CSSKeywordValue : CSSStyleValue {
+ attribute DOMString value;
+};
+</script>
+<script>
+'use strict';
+const idlArray = new IdlArray();
+idlArray.add_untested_idls('interface CSSStyleValue { stringifier; };');
+idlArray.add_idls(document.getElementById('idl').textContent);
+idlArray.add_objects({
+ CSSKeywordValue: ['new CSSKeywordValue("auto")']
+});
+idlArray.test();
+</script>
diff --git a/tests/wpt/web-platform-tests/css/css-values/calc-unit-analysis.html b/tests/wpt/web-platform-tests/css/css-values/calc-unit-analysis.html
index 346a8292ade..1520b4d3fa2 100644
--- a/tests/wpt/web-platform-tests/css/css-values/calc-unit-analysis.html
+++ b/tests/wpt/web-platform-tests/css/css-values/calc-unit-analysis.html
@@ -9,19 +9,6 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style id="style"></style>
-<script id="metadata_cache">/*
-{
- "unitless_zero_in_calc_is_a_numeric_type_not_length": { "assert": "invalid calc expression: unitless zero in calc() is a numeric type, not length" },
- "0px_in_calc": { "assert": "invalid calc expression: 0px in calc()" },
- "addition_of_length_and_number": { "assert": "invalid calc expression: addition of length and number" },
- "addition_of_number_and_length": { "assert": "invalid calc expression: addition of number and length" },
- "subtraction_of_length_and_number": { "assert": "invalid calc expression: subtraction of length and number" },
- "subtraction_of_number_and_length": { "assert": "invalid calc expression: subtraction of number and length" },
- "multiplication_of_length_and_number": { "assert": "invalid calc expression: multiplication of length and number" },
- "multiplication_of_number_and_length": { "assert": "invalid calc expression: multiplication of number and length" },
- "multiplication_of_length_and_length": { "assert": "invalid calc expression: multiplication of length and length" }
-}
-*/</script>
</head>
<body onload="run()">
<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/css/css-values/iframe/vh-support-transform-origin-iframe.html b/tests/wpt/web-platform-tests/css/css-values/support/vh-support-transform-origin-iframe.html
index ce3d4f0c68e..ce3d4f0c68e 100644
--- a/tests/wpt/web-platform-tests/css/css-values/iframe/vh-support-transform-origin-iframe.html
+++ b/tests/wpt/web-platform-tests/css/css-values/support/vh-support-transform-origin-iframe.html
diff --git a/tests/wpt/web-platform-tests/css/css-values/iframe/vh-support-transform-translate-iframe.html b/tests/wpt/web-platform-tests/css/css-values/support/vh-support-transform-translate-iframe.html
index f0b1b54c12d..f0b1b54c12d 100644
--- a/tests/wpt/web-platform-tests/css/css-values/iframe/vh-support-transform-translate-iframe.html
+++ b/tests/wpt/web-platform-tests/css/css-values/support/vh-support-transform-translate-iframe.html
diff --git a/tests/wpt/web-platform-tests/css/css-values/vh-support-transform-origin.html b/tests/wpt/web-platform-tests/css/css-values/vh-support-transform-origin.html
index 4b06a09fc36..38d17d2fdc8 100644
--- a/tests/wpt/web-platform-tests/css/css-values/vh-support-transform-origin.html
+++ b/tests/wpt/web-platform-tests/css/css-values/vh-support-transform-origin.html
@@ -36,7 +36,7 @@
</head>
<body>
- <iframe src="iframe/vh-support-transform-origin-iframe.html"></iframe>
+ <iframe src="support/vh-support-transform-origin-iframe.html"></iframe>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/css-values/vh-support-transform-translate.html b/tests/wpt/web-platform-tests/css/css-values/vh-support-transform-translate.html
index e273026a02c..900b653d494 100644
--- a/tests/wpt/web-platform-tests/css/css-values/vh-support-transform-translate.html
+++ b/tests/wpt/web-platform-tests/css/css-values/vh-support-transform-translate.html
@@ -36,7 +36,7 @@
</head>
<body>
- <iframe src="iframe/vh-support-transform-translate-iframe.html"></iframe>
+ <iframe src="support/vh-support-transform-translate-iframe.html"></iframe>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/css-variables/test_variable_legal_values.html b/tests/wpt/web-platform-tests/css/css-variables/test_variable_legal_values.html
index 0b39c248b57..2e074389f7a 100644
--- a/tests/wpt/web-platform-tests/css/css-variables/test_variable_legal_values.html
+++ b/tests/wpt/web-platform-tests/css/css-variables/test_variable_legal_values.html
@@ -9,33 +9,6 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style id="style"></style>
-<script id="metadata_cache">/*
-{
- "percentage": { "assert": "Value allowed within variable: percentage" },
- "number": { "assert": "Value allowed within variable: number" },
- "length": { "assert": "Value allowed within variable: length" },
- "time": { "assert": "Value allowed within variable: time" },
- "function": { "assert": "Value allowed within variable: function" },
- "nested_function": { "assert": "Value allowed within variable: nested function" },
- "parentheses": { "assert": "Value allowed within variable: parentheses" },
- "braces": { "assert": "Value allowed within variable: braces" },
- "brackets": { "assert": "Value allowed within variable: brackets" },
- "at_keyword_unknown": { "assert": "Value allowed within variable: at-keyword (unknown)" },
- "at_keyword_known": { "assert": "Value allowed within variable: at-keyword (known)" },
- "at_keyword_unknown_and_block": { "assert": "Value allowed within variable: at-keyword (unknown) and block" },
- "at_keyword_known_and_block": { "assert": "Value allowed within variable: at-keyword (known) and block" },
- "unbalanced_close_bracket_at_toplevel": { "assert": "Value not allowed within variable: unbalanced close bracket at toplevel" },
- "unbalanced_close_paren_at_toplevel": { "assert": "Value not allowed within variable: unbalanced close paren at toplevel" },
- "unbalanced_close_bracket_in_something_balanced": { "assert": "Value not allowed within variable: unbalanced close bracket in something balanced" },
- "unbalanced_close_paren_in_something_balanced": { "assert": "Value not allowed within variable: unbalanced close paren in something balanced" },
- "unbalanced_close_brace_in_something_balanced": { "assert": "Value not allowed within variable: unbalanced close brace in something balanced" },
- "CDO_at_top_level": { "assert": "Value allowed within variable: CDO at top level" },
- "CDC_at_top_level": { "assert": "Value allowed within variable: CDC at top level" },
- "semicolon_not_at_top_level_value_unused": { "assert": "Value allowed within variable: semicolon not at top level (value -> unused)" },
- "CDO_not_at_top_level_value_unused": { "assert": "Value allowed within variable: CDO not at top level (value -> unused)" },
- "CDC_not_at_top_level_value_unused": { "assert": "Value allowed within variable: CDC not at top level (value -> unused)" }
-}
-*/</script>
</head>
<body onload="run()">
<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/css/css-writing-modes/bidi-table-001.html b/tests/wpt/web-platform-tests/css/css-writing-modes/bidi-table-001.html
index fc6902a0367..5e2ae76b2c3 100644
--- a/tests/wpt/web-platform-tests/css/css-writing-modes/bidi-table-001.html
+++ b/tests/wpt/web-platform-tests/css/css-writing-modes/bidi-table-001.html
@@ -6,6 +6,7 @@
<link rel="author" title="Richard Ishida" href='mailto:ishida@w3.org'/>
<link rel="help" href='http://www.w3.org/TR/css-writing-modes-3/#text-direction'/>
+<link rel="match" href="reference/bidi-table-001.html"/>
<meta name="assert" content='If direction is applied to the ancestor of a table element, columns will be displayed in that direction.'/>
<style type="text/css">
.test { direction: rtl; }
@@ -46,4 +47,4 @@ The punctuation is moved around in the source to make it easier to do visual com
-</body></html> \ No newline at end of file
+</body></html>
diff --git a/tests/wpt/web-platform-tests/css/css-writing-modes/block-plaintext-006.html b/tests/wpt/web-platform-tests/css/css-writing-modes/block-plaintext-006.html
index c26e420c98a..7eb57e3ccac 100644
--- a/tests/wpt/web-platform-tests/css/css-writing-modes/block-plaintext-006.html
+++ b/tests/wpt/web-platform-tests/css/css-writing-modes/block-plaintext-006.html
@@ -6,6 +6,7 @@
<link rel="author" title="Richard Ishida" href='mailto:ishida@w3.org'/>
<link rel="help" href='http://www.w3.org/TR/css-writing-modes-3/#text-direction'/>
+<link rel="match" href="reference/block-plaintext-006.html"/>
<meta name="assert" content='If unicode-bidi:plaintext is applied to a pre element, each line of characters after a linebreak is displayed according to the first strong character after the linebreak.'/>
<style type="text/css">
.test pre { unicode-bidi: plaintext; }
@@ -20,7 +21,7 @@ input { margin: 5px; }
font-style: normal;
}
.test, .ref { font-family: ezra_silregular, serif; }
-pre { font-family: ezra_silregular, serif; height:5em; width: 100%; border: 0; font-size: 1em; }
+pre { font-family: ezra_silregular, serif; width: 100%; border: 0; margin: 0; font-size: 1em; }
</style>
</head>
<body>
@@ -36,10 +37,11 @@ Key to entities used below:
<div class="test">
-<pre>
+<pre><!-- comment token so following LF character isn't ignored by the HTML parser -->
&gt; a &gt; &#x5d1; &gt; c &gt;
&gt; &#x5d0; &gt; b &gt; &#x5d2; &gt;
&gt; a &gt; &#x5d1; &gt; c &gt;
+<!-- need a blank line for whitespace to appear-->
</pre>
</div>
@@ -55,4 +57,4 @@ Key to entities used below:
-</body></html> \ No newline at end of file
+</body></html>
diff --git a/tests/wpt/web-platform-tests/css/cssom-view/elementFromPosition.html b/tests/wpt/web-platform-tests/css/cssom-view/elementFromPosition.html
index d4da36ff1f7..ed86d16b7de 100644
--- a/tests/wpt/web-platform-tests/css/cssom-view/elementFromPosition.html
+++ b/tests/wpt/web-platform-tests/css/cssom-view/elementFromPosition.html
@@ -8,26 +8,6 @@
<meta name="flags" content="dom" />
<script src="/resources/testharness.js" type="text/javascript"></script>
<script src="/resources/testharnessreport.js" type="text/javascript"></script>
- <script id="metadata_cache">/*
-{
- "document.elementFromPoint": {},
- "document.elementFromPoint is a Function": {},
- "test some point of the element: top left corner": {},
- "test some point of the element: top line": {},
- "test some point of the element: top right corner": {},
- "test some point of the element: left line": {},
- "test some point of the element: inside": {},
- "test some point of the element: right line": {},
- "test some point of the element: bottom left corner": {},
- "test some point of the element: bottom line": {},
- "test some point of the element: bottom right corner": {},
- "Point (0, 0), return root element(HTML)": {},
- " test negative x ": {},
- " test negative y ": {},
- "test outside of viewport": {},
- "test the top of layer": {}
-}
- */</script>
</head>
<body>
<noscript>Test not run - JavaScript required!</noscript>
@@ -139,5 +119,3 @@
</script>
</body>
</html>
-
-
diff --git a/tests/wpt/web-platform-tests/css/cssom-view/offsetParent_element_test.html b/tests/wpt/web-platform-tests/css/cssom-view/offsetParent_element_test.html
index aa4a1e55e27..bb5686d41da 100644
--- a/tests/wpt/web-platform-tests/css/cssom-view/offsetParent_element_test.html
+++ b/tests/wpt/web-platform-tests/css/cssom-view/offsetParent_element_test.html
@@ -8,12 +8,6 @@
<link rel="help" href="http://www.w3.org/TR/cssom-view/#dom-htmlelement-offsetparent">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<script id="metadata_cache">/*
-{
- "Valid the algorithm rule of offsetParent check step 1": { "assert": "The offsetParent attribute algorithm rule checking passed!" },
- "Valid the algorithm rule of offsetParent check step 2": { "assert": "The offsetParent attribute algorithm rule checking passed!" }
-}
-*/</script>
<style>
#fixed {
position: fixed;
diff --git a/tests/wpt/web-platform-tests/css/cssom-view/overscrollBehavior-manual.html b/tests/wpt/web-platform-tests/css/cssom-view/overscrollBehavior-manual.html
index b37c4dc770c..78a5d7e7563 100644
--- a/tests/wpt/web-platform-tests/css/cssom-view/overscrollBehavior-manual.html
+++ b/tests/wpt/web-platform-tests/css/cssom-view/overscrollBehavior-manual.html
@@ -52,6 +52,7 @@
<script>
+setup({explicit_timeout: true});
const container = document.getElementById('container');
const non_scrollable = document.getElementById('non_scrollable');
const root = document.getElementById('root');
diff --git a/tests/wpt/web-platform-tests/css/cssom-view/scroll-behavior-smooth.html b/tests/wpt/web-platform-tests/css/cssom-view/scroll-behavior-smooth.html
new file mode 100644
index 00000000000..f144a5f61cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/cssom-view/scroll-behavior-smooth.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<title>cssom-view - scroll-behavior: smooth</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/cssom-view/#smooth-scrolling">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ .filler { height: 10000px }
+
+ .smooth {
+ scroll-behavior: smooth;
+ }
+
+ #scrollable {
+ overflow: scroll;
+ width: 100px;
+ height: 100px;
+ }
+</style>
+<div id="testContainer">
+ <div id="scrollable">
+ <div class="filler"></div>
+ </div>
+ <div class="filler"></div>
+</div>
+<script>
+ test(() => {
+ scrollable.scrollTo(0, 5000);
+ assert_equals(scrollable.scrollTop, 5000, "Initially scrolls instantly");
+ scrollable.scrollTo(0, 0);
+ scrollable.className = "smooth";
+ scrollable.scrollTo(0, 5000);
+ assert_less_than(scrollable.scrollTop, 5000, "scroll-behavior:smooth should not scroll instantly");
+ scrollable.className = "";
+ scrollable.scrollTo(0, 0);
+ }, "scroll-behavior: smooth on DIV element");
+
+ test(() => {
+ window.scrollTo(0, 5000);
+ assert_equals(window.scrollY, 5000, "Initially scrolls instantly");
+ window.scrollTo(0, 0);
+ document.documentElement.className = "smooth";
+ assert_less_than(window.scrollY, 5000, "scroll-behavior:smooth should not scroll instantly");
+ document.documentElement.className = "";
+ window.scrollTo(0, 0);
+ }, "HTML element scroll-behavior should propagate to viewport");
+
+ test(() => {
+ window.scrollTo(0, 5000);
+ assert_equals(window.scrollY, 5000, "Initially scrolls instantly");
+ window.scrollTo(0, 0);
+ document.body.className = "smooth";
+ window.scrollTo(0, 5000);
+ assert_equals(window.scrollY, 5000, "scroll-behavior:smooth on BODY should scroll viewport instantly");
+ document.body.className = "";
+ window.scrollTo(0, 0);
+ }, "BODY element scroll-behavior should not propagate to viewport");
+
+ testContainer.style.display = "none";
+</script>
diff --git a/tests/wpt/web-platform-tests/css/cssom-view/scrollTop-display-change-ref.html b/tests/wpt/web-platform-tests/css/cssom-view/scrollTop-display-change-ref.html
new file mode 100644
index 00000000000..9f1259787bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/cssom-view/scrollTop-display-change-ref.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<meta charset=utf-8>
+<div id="scroller" style="height: 100px; overflow: scroll">
+ <div style="height: 1000px">
+ I should be visible.
+ </div>
+ I should not be visible.
+</div>
diff --git a/tests/wpt/web-platform-tests/css/cssom-view/scrollTop-display-change.html b/tests/wpt/web-platform-tests/css/cssom-view/scrollTop-display-change.html
new file mode 100644
index 00000000000..916bfecfeb5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/cssom-view/scrollTop-display-change.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Setting scrollTop to 0 immediately after toggling display from "none" on an element that had nonzero scrollTop before should work.</title>
+<link rel=match href="scrollTop-display-change-ref.html">
+<div id="scroller" style="height: 100px; overflow: scroll">
+ <div style="height: 1000px">
+ I should be visible.
+ </div>
+ I should not be visible.
+</div>
+<script>
+ scroller.scrollTop = 1000;
+ scroller.style.display = "none";
+ var win = scroller.scrollTop; // Force layout flush
+ scroller.style.display = "";
+ scroller.scrollTop = 0;
+</script>
diff --git a/tests/wpt/web-platform-tests/css/cssom-view/scrollWidthHeight.xht b/tests/wpt/web-platform-tests/css/cssom-view/scrollWidthHeight.xht
index b4696e13630..77b01dbf50b 100644
--- a/tests/wpt/web-platform-tests/css/cssom-view/scrollWidthHeight.xht
+++ b/tests/wpt/web-platform-tests/css/cssom-view/scrollWidthHeight.xht
@@ -38,21 +38,6 @@
height:150px;
}
]]></style>
- <script id="metadata_cache" type="text/javascript"><![CDATA[/*
-{
- "elemSimple.clientHeight is the height of the padding edge": {},
- "elemSimple.scrollHeight is its clientHeight": {},
- "elemSimple.clientWidth is the width of the padding edge": {},
- "elemSimple.scrollWidth is its clientWidth": {},
- "elemOverflow.clientHeight is the height of the padding edge": {},
- "elemOverflow.scrollHeight is the height of its scrolled contents (ignoring padding, since we overflowed)": {},
- "elemOverflow.clientWidth is the width of the padding edge": {},
- "elemOverflow.scrollHeight is the width of its scrolled contents (ignoring padding, since we overflowed)": {},
- "elemNestedOverflow.clientHeight is the height of the padding edge": {},
- "elemNestedOverflow.scrollHeight is the height of its scrolled contents (ignoring padding, since we overflowed)": {},
- "elemNestedOverflow.clientWidth is the height of the padding edge": {},
- "elemNestedOverflow.scrollWidth is the width of its scrolled contents (ignoring padding, since we overflowed)": {}
-*/ ]]></script>
</head>
<body>
<noscript>Test not run - javascript required.</noscript>
diff --git a/tests/wpt/web-platform-tests/css/cssom-view/scrollWidthHeightWhenNotScrollable.xht b/tests/wpt/web-platform-tests/css/cssom-view/scrollWidthHeightWhenNotScrollable.xht
index e8c7f1298bc..f0fd373b1de 100644
--- a/tests/wpt/web-platform-tests/css/cssom-view/scrollWidthHeightWhenNotScrollable.xht
+++ b/tests/wpt/web-platform-tests/css/cssom-view/scrollWidthHeightWhenNotScrollable.xht
@@ -37,21 +37,6 @@
height:150px;
}
]]></style>
- <script id="metadata_cache" type="text/javascript"><![CDATA[/*
-{
- "elemSimple.clientHeight is the height of the padding edge": {},
- "elemSimple.scrollHeight is its clientHeight": {},
- "elemSimple.clientWidth is the width of the padding edge": {},
- "elemSimple.scrollWidth is its clientWidth": {},
- "elemOverflow.clientHeight is the height of the padding edge": {},
- "elemOverflow.scrollHeight is the height of its scrolled contents (ignoring padding, since we overflowed)": {},
- "elemOverflow.clientWidth is the width of the padding edge": {},
- "elemOverflow.scrollHeight is the width of its scrolled contents (ignoring padding, since we overflowed)": {},
- "elemNestedOverflow.clientHeight is the height of the padding edge": {},
- "elemNestedOverflow.scrollHeight is the height of its scrolled contents (ignoring padding, since we overflowed)": {},
- "elemNestedOverflow.clientWidth is the height of the padding edge": {},
- "elemNestedOverflow.scrollWidth is the width of its scrolled contents (ignoring padding, since we overflowed)": {}
-*/ ]]></script>
</head>
<body>
<noscript>Test not run - javascript required.</noscript>
diff --git a/tests/wpt/web-platform-tests/css/cssom-view/window-interface.xht b/tests/wpt/web-platform-tests/css/cssom-view/window-interface.xht
index 2ed64cba6e6..163124b6e78 100644
--- a/tests/wpt/web-platform-tests/css/cssom-view/window-interface.xht
+++ b/tests/wpt/web-platform-tests/css/cssom-view/window-interface.xht
@@ -13,22 +13,6 @@
<body>
<noscript>Test not run - javascript required.</noscript>
<div id="log" />
- <script id="metadata_cache">/*
- {
- "window_exposed_functions": {
- "assert": ["window functions are exposed"]
- },
- "window_functions": {
- "assert": ["window functions are instances of Function"]
- },
- "window_properties": {
- "assert": ["window properties are owned by window"]
- },
- "window_properties_readonly": {
- "assert": ["window properties are readonly"]
- }
- }
- */</script>
<script type="text/javascript"><![CDATA[
/*
Window Functions
diff --git a/tests/wpt/web-platform-tests/css/cssom/MediaList2.xhtml b/tests/wpt/web-platform-tests/css/cssom/MediaList2.xhtml
index fb1062cba87..73acbdec25c 100644
--- a/tests/wpt/web-platform-tests/css/cssom/MediaList2.xhtml
+++ b/tests/wpt/web-platform-tests/css/cssom/MediaList2.xhtml
@@ -8,15 +8,6 @@
<style media="screen, print" id="test-style"></style>
<script src="/resources/testharness.js"/>
<script src="/resources/testharnessreport.js"/>
-<script id="metadata_cache">/*
-{
- "MediaList": {},
- "MediaList.mediaText": {},
- "MediaList.length": {},
- "MediaList getter": {},
- "MediaList.item": {}
-}
-*/</script>
</head>
<body>
<div id="log"/>
diff --git a/tests/wpt/web-platform-tests/css/cssom/computed-style-001.html b/tests/wpt/web-platform-tests/css/cssom/computed-style-001.html
index 2cdfc9eb8b4..80bf06c300e 100644
--- a/tests/wpt/web-platform-tests/css/cssom/computed-style-001.html
+++ b/tests/wpt/web-platform-tests/css/cssom/computed-style-001.html
@@ -23,14 +23,6 @@
height: 100px;
}
</style>
-<script id="metadata_cache">/*
-{
- "read_only": { "assert": "do not allow modifications to a computed CSSStyleDeclaration" },
- "property_values": { "assert": "Directly set properties are resolved" },
- "inherited_property_values": { "assert": "Inherited properties are resolved" },
- "relative_property_values": { "assert": "Relative properties are resolved" }
-}
-*/</script>
</head>
<body>
<noscript>Test not run - javascript required.</noscript>
diff --git a/tests/wpt/web-platform-tests/css/cssom/getComputedStyle-pseudo.html b/tests/wpt/web-platform-tests/css/cssom/getComputedStyle-pseudo.html
index fa358d6d3d3..ec7a863a94c 100644
--- a/tests/wpt/web-platform-tests/css/cssom/getComputedStyle-pseudo.html
+++ b/tests/wpt/web-platform-tests/css/cssom/getComputedStyle-pseudo.html
@@ -38,12 +38,19 @@
#flex-no-pseudo {
display: flex;
}
+#contents-pseudos::before,
+#contents-pseudos::after {
+ display: contents;
+ content: "foo";
+ position: absolute;
+}
</style>
<div id="test">
<div id="contents"></div>
<div id="none"></div>
<div id="flex"></div>
<div id="flex-no-pseudo"></div>
+ <div id="contents-pseudos"></div>
</div>
<script>
test(function() {
@@ -91,4 +98,15 @@ test(function() {
"Pseudo-styles of display: flex elements should get blockified");
});
}, "Item-based blockification of nonexistent pseudo-elements");
+test(function() {
+ var contentsPseudos = document.getElementById('contents-pseudos');
+ [":before", ":after"].forEach(function(pseudo) {
+ assert_equals(getComputedStyle(contentsPseudos, pseudo).display, "contents",
+ "display: contents in " + pseudo + " should get reflected on CSSOM");
+ assert_equals(getComputedStyle(contentsPseudos, pseudo).width, "auto",
+ pseudo + " with display: contents should have no box");
+ assert_equals(getComputedStyle(contentsPseudos, pseudo).position, "absolute",
+ "display: contents in " + pseudo + " should reflect other non-inherited properties in CSSOM");
+ });
+}, "display: contents on pseudo-elements");
</script>
diff --git a/tests/wpt/web-platform-tests/css/cssom/inline-style-001.html b/tests/wpt/web-platform-tests/css/cssom/inline-style-001.html
index 3a9eebf7e72..b8b1aaaf707 100644
--- a/tests/wpt/web-platform-tests/css/cssom/inline-style-001.html
+++ b/tests/wpt/web-platform-tests/css/cssom/inline-style-001.html
@@ -9,22 +9,6 @@
<script src="/resources/testharness.js" type="text/javascript"></script>
<script src="/resources/testharnessreport.js" type="text/javascript"></script>
</head>
- <script id="metadata_cache">/*
-{
- "CSSStyleDeclaration_accessible": { "assert": "Can access CSSStyleDeclaration through style property" },
- "read": { "assert": "initial property values are correct" },
- "csstext_write": {
- "assert": ["setting cssText adds new properties",
- "setting cssText removes existing properties",
- "properties set through cssText are reflected in the computed style"]
- },
- "property_write": {
- "assert": ["setProperty adds new properties",
- "properties set through setProperty are reflected in the computed style"]
- },
- "shorthand_properties": { "assert": "shorthand property is expanded" }
-}
-*/</script>
<body>
<noscript>Test not run - javascript required.</noscript>
<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/css/cssom/medialist-dynamic-001-ref.html b/tests/wpt/web-platform-tests/css/cssom/medialist-dynamic-001-ref.html
new file mode 100644
index 00000000000..9715b5acb8f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/cssom/medialist-dynamic-001-ref.html
@@ -0,0 +1,5 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Test Reference</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+Should not be red.
diff --git a/tests/wpt/web-platform-tests/css/cssom/medialist-dynamic-001.html b/tests/wpt/web-platform-tests/css/cssom/medialist-dynamic-001.html
new file mode 100644
index 00000000000..ab9c1345680
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/cssom/medialist-dynamic-001.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Test: Dynamic changes to the stylesheet media attributes via CSSOM get reflected</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="match" href="medialist-dynamic-001-ref.html">
+<link rel="help" href="https://drafts.csswg.org/cssom/#dom-medialist-mediatext">
+<style media="all">* { color: red }</style>
+Should not be red.
+<script>
+ document.body.offsetTop;
+ document.styleSheets[0].media.mediaText = "not all";
+</script>
diff --git a/tests/wpt/web-platform-tests/css/cssom/medialist-interfaces-001.html b/tests/wpt/web-platform-tests/css/cssom/medialist-interfaces-001.html
index ad95394d5c5..f5dbb569538 100644
--- a/tests/wpt/web-platform-tests/css/cssom/medialist-interfaces-001.html
+++ b/tests/wpt/web-platform-tests/css/cssom/medialist-interfaces-001.html
@@ -9,30 +9,6 @@
<meta name="assert" content="MediaLists are serialized according to the specification">
<script src="/resources/testharness.js" type="text/javascript"></script>
<script src="/resources/testharnessreport.js" type="text/javascript"></script>
- <script id="metadata_cache">/*
- {
- "mediatest_medialist_serialize_element": {
- "help": ["http://www.w3.org/TR/cssom-1/#the-medialist-interface",
- "http://www.w3.org/TR/cssom-1/#serializing-media-queries"],
- "assert": ["MediaList.mediaText equals the 'media' value of the initial 'style' element."]
- },
- "mediatest_medialist_serialize_comma": {
- "help": ["http://www.w3.org/TR/cssom-1/#the-medialist-interface",
- "http://www.w3.org/TR/cssom-1/#serializing-media-queries"],
- "assert": ["To serialize a comma-separated list concatenate all items of the list in list order while separating them by \",\" (U+002C), followed by a space (U+0020)."]
- },
- "mediatest_medialist_serialize_empty": {
- "help": ["http://www.w3.org/TR/cssom-1/#the-medialist-interface",
- "http://www.w3.org/TR/cssom-1/#serializing-media-queries"],
- "assert": ["If the media query list is empty return the empty string."]
- },
- "mediatest_medialist_serialize_lexicographical": {
- "help": ["http://www.w3.org/TR/cssom-1/#the-medialist-interface",
- "http://www.w3.org/TR/cssom-1/#serializing-media-queries"],
- "assert": ["Each media query in the list of media queries should be sorted in lexicographical order."]
- }
- }
- */</script>
</head>
<body>
<noscript>Test not run - javascript required.</noscript>
diff --git a/tests/wpt/web-platform-tests/css/cssom/medialist-interfaces-002.html b/tests/wpt/web-platform-tests/css/cssom/medialist-interfaces-002.html
index d3dfff8e42b..bba25a1ebb5 100644
--- a/tests/wpt/web-platform-tests/css/cssom/medialist-interfaces-002.html
+++ b/tests/wpt/web-platform-tests/css/cssom/medialist-interfaces-002.html
@@ -9,15 +9,6 @@
<meta name="assert" content="MediaList object has deleteMedium method and it functions properly.">
<script src="/resources/testharness.js" type="text/javascript"></script>
<script src="/resources/testharnessreport.js" type="text/javascript"></script>
-
- <script id="metadata_cache">/*
- {
- "deleteMedium_called_without_argument": { "assert": "MediaList.deleteMedium called without argument throws error." },
- "deleteMedium_removes_correct_medium": { "assert": "MediaList.deleteMedium removes correct medium and updates corresponding properties." },
- "deleteMedium_no_matching_medium_to_remove": { "assert": "MediaList.deleteMedium doesn't modify MediaList when medium is not found." }
- }
-*/</script>
-
</head>
<body>
diff --git a/tests/wpt/web-platform-tests/css/cssom/medialist-interfaces-003.html b/tests/wpt/web-platform-tests/css/cssom/medialist-interfaces-003.html
index 717c39d618f..649f9485f44 100644
--- a/tests/wpt/web-platform-tests/css/cssom/medialist-interfaces-003.html
+++ b/tests/wpt/web-platform-tests/css/cssom/medialist-interfaces-003.html
@@ -10,16 +10,6 @@
<script src="/resources/testharness.js" type="text/javascript"></script>
<script src="/resources/testharnessreport.js" type="text/javascript"></script>
</head>
- <script id="metadata_cache">/*
- {
- "mediatest_mediaquery_serialize_1": {
- "assert": ["First explicit example input (first column) and output (second column) in specification."]
- },
- "mediatest_mediaquery_serialize_2": {
- "assert": ["Second explicit example input (first column) and output (second column) in specification."]
- }
- }
- */</script>
<body>
<noscript>Test not run - javascript required.</noscript>
<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/css/cssom/medialist-interfaces-004.html b/tests/wpt/web-platform-tests/css/cssom/medialist-interfaces-004.html
index 2fe6ff915d7..416addae7b5 100644
--- a/tests/wpt/web-platform-tests/css/cssom/medialist-interfaces-004.html
+++ b/tests/wpt/web-platform-tests/css/cssom/medialist-interfaces-004.html
@@ -8,14 +8,6 @@
<meta name="assert" content="MediaList object has appendMedium method and it functions properly.">
<script src="/resources/testharness.js" type="text/javascript"></script>
<script src="/resources/testharnessreport.js" type="text/javascript"></script>
-
- <script id="metadata_cache">/*
- {
- "appendMedium_correctly_appends_medium_to_empty_MediaList": { "assert": "MediaList.appendMedium correctly adds medium to empty MediaList." },
- "appendMedium_correctly_appends_medium_to_nonempty_MediaList": { "assert": "MediaList.appendMedium correctly adds medium to a MediaList that already has a medium." }
- }
-*/</script>
-
</head>
<body>
diff --git a/tests/wpt/web-platform-tests/css/cssom/setproperty-null-undefined.html b/tests/wpt/web-platform-tests/css/cssom/setproperty-null-undefined.html
new file mode 100644
index 00000000000..3de142c0b46
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/cssom/setproperty-null-undefined.html
@@ -0,0 +1,47 @@
+<!doctype html>
+<html>
+<head>
+<link rel="help" href="https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-setproperty"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+var style = document.body.style;
+
+test(function() {
+ style.color = 'white';
+
+ assert_equals(style.color, 'white');
+ style.setProperty('color', undefined);
+ assert_equals(style.color, 'white');
+}, "Verify that setting a CSS property to undefined has no effect.");
+
+test(function() {
+ style.color = 'white';
+
+ assert_equals(style.color, 'white');
+ assert_equals(style.getPropertyPriority('color'), '');
+ style.setProperty('color', 'red', undefined);
+ assert_equals(style.color, 'red');
+ assert_equals(style.getPropertyPriority('color'), '');
+}, "Verify that setting a CSS property priority to undefined is accepted.");
+
+test(function() {
+ style.color = 'white';
+
+ assert_equals(style.color, 'white');
+ style.setProperty('color', null);
+ assert_equals(style.color, '');
+}, "Verify that setting a CSS property to null is treated like empty string.");
+
+test(function() {
+ style.color = 'white';
+
+ assert_equals(style.color, 'white');
+ style.setProperty('color', 'red', null);
+ assert_equals(style.color, 'red');
+}, "Verify that setting a CSS property priority to null is treated like empty string.");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/cssom/style-sheet-interfaces-001.html b/tests/wpt/web-platform-tests/css/cssom/style-sheet-interfaces-001.html
index fb1fde86eff..79c485038dd 100644
--- a/tests/wpt/web-platform-tests/css/cssom/style-sheet-interfaces-001.html
+++ b/tests/wpt/web-platform-tests/css/cssom/style-sheet-interfaces-001.html
@@ -13,31 +13,6 @@
* { margin: 0; padding: 0; }
</style>
<link id="linkElement" rel="stylesheet" href="support/b-green.css">
-<script id="metadata_cache">/*
-{
- "sheet_property": {
- "help": "http://www.w3.org/TR/cssom-1/#the-linkstyle-interface",
- "assert": ["styleElement.sheet exists",
- "styleElement.sheet is a CSSStyleSheet",
- "linkElement.sheet exists",
- "linkElement.sheet is a CSSStyleSheet"]
- },
- "CSSStyleSheet_properties": {
- "assert": ["ownerRule, cssRules, insertRule and deleteRule properties exist on CSSStyleSheet",
- "ownerRule, cssRules are read only"]
- },
- "CSSStyleSheet_property_values": {
- "help": ["http://www.w3.org/TR/cssom-1/#css-style-sheets",
- "http://www.w3.org/TR/cssom-1/#cssimportrule"],
- "assert": "CSSStyleSheet initial property values are correct"
- },
- "StyleSheet_properties": {
- "assert": ["type, disabled, ownerNode, parentStyleSheet, href, title, and media properties exist on StyleSheet",
- "type, ownerNode, parentStyleSheet, href, title, media properties are read only"]
- },
- "StyleSheet_property_values": { "assert": "StyleSheet initial property values are correct" }
-}
-*/</script>
</head>
<body>
<noscript>Test not run - javascript required.</noscript>
diff --git a/tests/wpt/web-platform-tests/css/cssom/style-sheet-interfaces-002.html b/tests/wpt/web-platform-tests/css/cssom/style-sheet-interfaces-002.html
index ad5b1ac5861..51b0eb336be 100644
--- a/tests/wpt/web-platform-tests/css/cssom/style-sheet-interfaces-002.html
+++ b/tests/wpt/web-platform-tests/css/cssom/style-sheet-interfaces-002.html
@@ -13,15 +13,6 @@
<style id="styleElement" type="text/css" media="all" title="internal style sheet" disabled="disabled">
* { margin: 0; padding: 0; }
</style>
- <script id="metadata_cache">/*
-{
- "add_rule": {
- "assert": ["Initial rule list is of size 1",
- "Can add a rule at first index"]
- },
- "delete_rule": { "assert": "Can delete rules until rule list is empty" }
-}
-*/</script>
</head>
<body>
<noscript>Test not run - javascript required.</noscript>
diff --git a/tests/wpt/web-platform-tests/css/cssom/ttwf-cssom-doc-ext-load-count.html b/tests/wpt/web-platform-tests/css/cssom/ttwf-cssom-doc-ext-load-count.html
index f507a961032..5296aa3a8bc 100644
--- a/tests/wpt/web-platform-tests/css/cssom/ttwf-cssom-doc-ext-load-count.html
+++ b/tests/wpt/web-platform-tests/css/cssom/ttwf-cssom-doc-ext-load-count.html
@@ -11,13 +11,6 @@
<meta name="assert" content="The styleSheets length attribute must reflect the number of sheets at page load and after dynamically">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
- <script id="metadata_cache">/*
- {
- "stylesheet.css should be loaded and styleSheets.length === 1": {},
- "stylesheet.css should be unloaded and styleSheets.length === 0": {},
- "stylesheet-1.css should be loaded and styleSheets.length === 1": {}
- }
- */</script>
</head>
<body>
<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/css/mediaqueries/mq-calc-002.html b/tests/wpt/web-platform-tests/css/mediaqueries/mq-calc-002.html
index 60fb1ca4b25..f6f2fc15039 100644
--- a/tests/wpt/web-platform-tests/css/mediaqueries/mq-calc-002.html
+++ b/tests/wpt/web-platform-tests/css/mediaqueries/mq-calc-002.html
@@ -19,11 +19,19 @@
@media (min-width: calc(1em)){
div { background-color: green; }
}
- </style>
+ </style>
</head>
<body>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div></div>
+ <script>
+ document.body.offsetTop;
+ </script>
+ <style>
+ @media (min-width: calc(1em)){
+ div { background-color: green; }
+ }
+ </style>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/mediaqueries/mq-calc-003.html b/tests/wpt/web-platform-tests/css/mediaqueries/mq-calc-003.html
index 785570c8537..cadc448efe5 100644
--- a/tests/wpt/web-platform-tests/css/mediaqueries/mq-calc-003.html
+++ b/tests/wpt/web-platform-tests/css/mediaqueries/mq-calc-003.html
@@ -19,11 +19,19 @@
@media (min-width: calc(1ex)){
div { background-color: green; }
}
- </style>
+ </style>
</head>
<body>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div></div>
+ <script>
+ document.body.offsetTop;
+ </script>
+ <style>
+ @media (min-width: calc(1ex)){
+ div { background-color: green; }
+ }
+ </style>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/mediaqueries/mq-calc-004.html b/tests/wpt/web-platform-tests/css/mediaqueries/mq-calc-004.html
index f3b5fbf6ed0..63190347b65 100644
--- a/tests/wpt/web-platform-tests/css/mediaqueries/mq-calc-004.html
+++ b/tests/wpt/web-platform-tests/css/mediaqueries/mq-calc-004.html
@@ -16,14 +16,19 @@
height: 100px;
background-color: red;
}
- @media (min-width: calc(1ch)){
- div { background-color: green; }
- }
</style>
</head>
<body>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div></div>
+ <script>
+ document.body.offsetTop;
+ </script>
+ <style>
+ @media (min-width: calc(1ch)){
+ div { background-color: green; }
+ }
+ </style>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/mediaqueries/mq-calc-005.html b/tests/wpt/web-platform-tests/css/mediaqueries/mq-calc-005.html
index 234865f9730..df7409b7481 100644
--- a/tests/wpt/web-platform-tests/css/mediaqueries/mq-calc-005.html
+++ b/tests/wpt/web-platform-tests/css/mediaqueries/mq-calc-005.html
@@ -16,14 +16,19 @@
height: 100px;
background-color: red;
}
- @media (min-width: calc(1rem)){
- div { background-color: green; }
- }
</style>
</head>
<body>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div></div>
+ <script>
+ document.body.offsetTop;
+ </script>
+ <style>
+ @media (min-width: calc(1rem)){
+ div { background-color: green; }
+ }
+ </style>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/mediaqueries/relative-units-001.html b/tests/wpt/web-platform-tests/css/mediaqueries/relative-units-001.html
index 74821418acd..fac94d78edf 100644
--- a/tests/wpt/web-platform-tests/css/mediaqueries/relative-units-001.html
+++ b/tests/wpt/web-platform-tests/css/mediaqueries/relative-units-001.html
@@ -16,11 +16,6 @@
body {
background: red;
}
-@media (min-width: 1rem) {
- body {
- background: green;
- }
-}
p {
font-size: 24px;
}
@@ -28,5 +23,15 @@ p {
</head>
<body>
<p>This should have a green background.</p>
+ <script>
+ document.body.offsetTop;
+ </script>
+ <style>
+ @media (min-width: 1rem) {
+ body {
+ background: green;
+ }
+ }
+ </style>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/mediaqueries/relative-units-002.html b/tests/wpt/web-platform-tests/css/mediaqueries/relative-units-002.html
index 40af3b67631..310e18f5242 100644
--- a/tests/wpt/web-platform-tests/css/mediaqueries/relative-units-002.html
+++ b/tests/wpt/web-platform-tests/css/mediaqueries/relative-units-002.html
@@ -16,11 +16,6 @@
body {
background: red;
}
-@media (min-width: 1em) {
- body {
- background: green;
- }
-}
p {
font-size: 24px;
}
@@ -28,5 +23,15 @@ p {
</head>
<body>
<p>This should have a green background.</p>
+ <script>
+ document.body.offsetTop;
+ </script>
+ <style>
+ @media (min-width: 1em) {
+ body {
+ background: green;
+ }
+ }
+ </style>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/mediaqueries/relative-units-003.html b/tests/wpt/web-platform-tests/css/mediaqueries/relative-units-003.html
index 1ee2a90b63c..461db324224 100644
--- a/tests/wpt/web-platform-tests/css/mediaqueries/relative-units-003.html
+++ b/tests/wpt/web-platform-tests/css/mediaqueries/relative-units-003.html
@@ -16,11 +16,6 @@
body {
background: red;
}
-@media (min-width: 1ex) {
- body {
- background: green;
- }
-}
p {
font-size: 24px;
}
@@ -28,5 +23,15 @@ p {
</head>
<body>
<p>This should have a green background.</p>
+ <script>
+ document.body.offsetTop;
+ </script>
+ <style>
+ @media (min-width: 1ex) {
+ body {
+ background: green;
+ }
+ }
+ </style>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/mediaqueries/relative-units-004.html b/tests/wpt/web-platform-tests/css/mediaqueries/relative-units-004.html
index 9db6821bd02..b0f3765358d 100644
--- a/tests/wpt/web-platform-tests/css/mediaqueries/relative-units-004.html
+++ b/tests/wpt/web-platform-tests/css/mediaqueries/relative-units-004.html
@@ -16,11 +16,6 @@
body {
background: red;
}
-@media (min-width: 1ch) {
- body {
- background: green;
- }
-}
p {
font-size: 24px;
}
@@ -28,5 +23,15 @@ p {
</head>
<body>
<p>This should have a green background.</p>
+ <script>
+ document.body.offsetTop;
+ </script>
+ <style>
+ @media (min-width: 1ch) {
+ body {
+ background: green;
+ }
+ }
+ </style>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/css/mediaqueries/test_media_queries.html b/tests/wpt/web-platform-tests/css/mediaqueries/test_media_queries.html
index 44161acef01..a305d7a032b 100644
--- a/tests/wpt/web-platform-tests/css/mediaqueries/test_media_queries.html
+++ b/tests/wpt/web-platform-tests/css/mediaqueries/test_media_queries.html
@@ -8,373 +8,6 @@
<link rel="help" href="http://www.w3.org/TR/css3-mediaqueries/">
<script type="text/javascript" src="/resources/testharness.js"></script>
<script type="text/javascript" src="/resources/testharnessreport.js"></script>
-<script id="metadata_cache">/*
-{
- "subtest_1": { "assert": "query (orientation) should be parseable" },
- "subtest_2": { "assert": "query not (orientation) should not be parseable" },
- "subtest_3": { "assert": "query only (orientation) should not be parseable" },
- "subtest_4": { "assert": "query all and (orientation) should be parseable" },
- "subtest_5": { "assert": "query not all and (orientation) should be parseable" },
- "subtest_6": { "assert": "query only all and (orientation) should be parseable" },
- "subtest_7": { "assert": "expression width should be parseable" },
- "subtest_8": { "assert": "expression width: 0 should be parseable" },
- "subtest_9": { "assert": "expression width: 0px should be parseable" },
- "subtest_10": { "assert": "expression width: 0em should be parseable" },
- "subtest_11": { "assert": "expression width: -0 should be parseable" },
- "subtest_12": { "assert": "expression min-width: -0 should be parseable" },
- "subtest_13": { "assert": "expression max-width: -0 should be parseable" },
- "subtest_14": { "assert": "expression width: -0cm should be parseable" },
- "subtest_15": { "assert": "expression width: 1px should be parseable" },
- "subtest_16": { "assert": "expression width: 0.001mm should be parseable" },
- "subtest_17": { "assert": "expression width: 100000px should be parseable" },
- "subtest_18": { "assert": "expression width: -1px should not be parseable" },
- "subtest_19": { "assert": "expression min-width: -1px should not be parseable" },
- "subtest_20": { "assert": "expression max-width: -1px should not be parseable" },
- "subtest_21": { "assert": "expression width: -0.00001mm should not be parseable" },
- "subtest_22": { "assert": "expression width: -100000em should not be parseable" },
- "subtest_23": { "assert": "expression min-width should not be parseable" },
- "subtest_24": { "assert": "expression max-width should not be parseable" },
- "subtest_25": { "assert": "expression height should be parseable" },
- "subtest_26": { "assert": "expression height: 0 should be parseable" },
- "subtest_27": { "assert": "expression height: 0px should be parseable" },
- "subtest_28": { "assert": "expression height: 0em should be parseable" },
- "subtest_29": { "assert": "expression height: -0 should be parseable" },
- "subtest_30": { "assert": "expression min-height: -0 should be parseable" },
- "subtest_31": { "assert": "expression max-height: -0 should be parseable" },
- "subtest_32": { "assert": "expression height: -0cm should be parseable" },
- "subtest_33": { "assert": "expression height: 1px should be parseable" },
- "subtest_34": { "assert": "expression height: 0.001mm should be parseable" },
- "subtest_35": { "assert": "expression height: 100000px should be parseable" },
- "subtest_36": { "assert": "expression height: -1px should not be parseable" },
- "subtest_37": { "assert": "expression min-height: -1px should not be parseable" },
- "subtest_38": { "assert": "expression max-height: -1px should not be parseable" },
- "subtest_39": { "assert": "expression height: -0.00001mm should not be parseable" },
- "subtest_40": { "assert": "expression height: -100000em should not be parseable" },
- "subtest_41": { "assert": "expression min-height should not be parseable" },
- "subtest_42": { "assert": "expression max-height should not be parseable" },
- "subtest_43": { "assert": "expression device-width should be parseable" },
- "subtest_44": { "assert": "expression device-width: 0 should be parseable" },
- "subtest_45": { "assert": "expression device-width: 0px should be parseable" },
- "subtest_46": { "assert": "expression device-width: 0em should be parseable" },
- "subtest_47": { "assert": "expression device-width: -0 should be parseable" },
- "subtest_48": { "assert": "expression min-device-width: -0 should be parseable" },
- "subtest_49": { "assert": "expression max-device-width: -0 should be parseable" },
- "subtest_50": { "assert": "expression device-width: -0cm should be parseable" },
- "subtest_51": { "assert": "expression device-width: 1px should be parseable" },
- "subtest_52": { "assert": "expression device-width: 0.001mm should be parseable" },
- "subtest_53": { "assert": "expression device-width: 100000px should be parseable" },
- "subtest_54": { "assert": "expression device-width: -1px should not be parseable" },
- "subtest_55": { "assert": "expression min-device-width: -1px should not be parseable" },
- "subtest_56": { "assert": "expression max-device-width: -1px should not be parseable" },
- "subtest_57": { "assert": "expression device-width: -0.00001mm should not be parseable" },
- "subtest_58": { "assert": "expression device-width: -100000em should not be parseable" },
- "subtest_59": { "assert": "expression min-device-width should not be parseable" },
- "subtest_60": { "assert": "expression max-device-width should not be parseable" },
- "subtest_61": { "assert": "expression device-height should be parseable" },
- "subtest_62": { "assert": "expression device-height: 0 should be parseable" },
- "subtest_63": { "assert": "expression device-height: 0px should be parseable" },
- "subtest_64": { "assert": "expression device-height: 0em should be parseable" },
- "subtest_65": { "assert": "expression device-height: -0 should be parseable" },
- "subtest_66": { "assert": "expression min-device-height: -0 should be parseable" },
- "subtest_67": { "assert": "expression max-device-height: -0 should be parseable" },
- "subtest_68": { "assert": "expression device-height: -0cm should be parseable" },
- "subtest_69": { "assert": "expression device-height: 1px should be parseable" },
- "subtest_70": { "assert": "expression device-height: 0.001mm should be parseable" },
- "subtest_71": { "assert": "expression device-height: 100000px should be parseable" },
- "subtest_72": { "assert": "expression device-height: -1px should not be parseable" },
- "subtest_73": { "assert": "expression min-device-height: -1px should not be parseable" },
- "subtest_74": { "assert": "expression max-device-height: -1px should not be parseable" },
- "subtest_75": { "assert": "expression device-height: -0.00001mm should not be parseable" },
- "subtest_76": { "assert": "expression device-height: -100000em should not be parseable" },
- "subtest_77": { "assert": "expression min-device-height should not be parseable" },
- "subtest_78": { "assert": "expression max-device-height should not be parseable" },
- "subtest_79": { "assert": "all and (width: 117px) should apply" },
- "subtest_80": { "assert": "all and (width: 118px) should not apply" },
- "subtest_81": { "assert": "all and (width: 116px) should not apply" },
- "subtest_82": { "assert": "all and (min-width: 117px) should apply" },
- "subtest_83": { "assert": "all and (min-width: 118px) should not apply" },
- "subtest_84": { "assert": "all and (min-width: 116px) should apply" },
- "subtest_85": { "assert": "all and (max-width: 117px) should apply" },
- "subtest_86": { "assert": "all and (max-width: 118px) should apply" },
- "subtest_87": { "assert": "all and (max-width: 116px) should not apply" },
- "subtest_88": { "assert": "all and (min-width: 9em) should not apply" },
- "subtest_89": { "assert": "all and (min-width: 6em) should apply" },
- "subtest_90": { "assert": "all and (max-width: 9em) should apply" },
- "subtest_91": { "assert": "all and (max-width: 6em) should not apply" },
- "subtest_92": { "assert": "all and (height: 76px) should apply" },
- "subtest_93": { "assert": "all and (height: 77px) should not apply" },
- "subtest_94": { "assert": "all and (height: 75px) should not apply" },
- "subtest_95": { "assert": "all and (min-height: 76px) should apply" },
- "subtest_96": { "assert": "all and (min-height: 77px) should not apply" },
- "subtest_97": { "assert": "all and (min-height: 75px) should apply" },
- "subtest_98": { "assert": "all and (max-height: 76px) should apply" },
- "subtest_99": { "assert": "all and (max-height: 77px) should apply" },
- "subtest_100": { "assert": "all and (max-height: 75px) should not apply" },
- "subtest_101": { "assert": "all and (min-height: 6em) should not apply" },
- "subtest_102": { "assert": "all and (min-height: 3em) should apply" },
- "subtest_103": { "assert": "all and (max-height: 6em) should apply" },
- "subtest_104": { "assert": "all and (max-height: 3em) should not apply" },
- "subtest_105": { "assert": "all and (device-width: 1920px) should apply" },
- "subtest_106": { "assert": "all and (device-width: 1921px) should not apply" },
- "subtest_107": { "assert": "all and (device-width: 1919px) should not apply" },
- "subtest_108": { "assert": "all and (min-device-width: 1920px) should apply" },
- "subtest_109": { "assert": "all and (min-device-width: 1921px) should not apply" },
- "subtest_110": { "assert": "all and (min-device-width: 1919px) should apply" },
- "subtest_111": { "assert": "all and (max-device-width: 1920px) should apply" },
- "subtest_112": { "assert": "all and (max-device-width: 1921px) should apply" },
- "subtest_113": { "assert": "all and (max-device-width: 1919px) should not apply" },
- "subtest_114": { "assert": "all and (min-device-width: 121em) should not apply" },
- "subtest_115": { "assert": "all and (min-device-width: 119em) should apply" },
- "subtest_116": { "assert": "all and (max-device-width: 121em) should apply" },
- "subtest_117": { "assert": "all and (max-device-width: 119em) should not apply" },
- "subtest_118": { "assert": "all and (device-height: 1200px) should apply" },
- "subtest_119": { "assert": "all and (device-height: 1201px) should not apply" },
- "subtest_120": { "assert": "all and (device-height: 1199px) should not apply" },
- "subtest_121": { "assert": "all and (min-device-height: 1200px) should apply" },
- "subtest_122": { "assert": "all and (min-device-height: 1201px) should not apply" },
- "subtest_123": { "assert": "all and (min-device-height: 1199px) should apply" },
- "subtest_124": { "assert": "all and (max-device-height: 1200px) should apply" },
- "subtest_125": { "assert": "all and (max-device-height: 1201px) should apply" },
- "subtest_126": { "assert": "all and (max-device-height: 1199px) should not apply" },
- "subtest_127": { "assert": "all and (min-device-height: 76em) should not apply" },
- "subtest_128": { "assert": "all and (min-device-height: 74em) should apply" },
- "subtest_129": { "assert": "all and (max-device-height: 76em) should apply" },
- "subtest_130": { "assert": "all and (max-device-height: 74em) should not apply" },
- "subtest_131": { "assert": "all and (height) should apply" },
- "subtest_132": { "assert": "all and (width) should not apply" },
- "subtest_133": { "assert": "all and (height) should not apply" },
- "subtest_134": { "assert": "all and (width) should not apply" },
- "subtest_135": { "assert": "all and (device-height) should apply" },
- "subtest_136": { "assert": "all and (device-width) should apply" },
- "subtest_137": { "assert": "all and (height) should not apply" },
- "subtest_138": { "assert": "all and (width) should apply" },
- "subtest_139": { "assert": "all and (height) should apply" },
- "subtest_140": { "assert": "all and (width) should apply" },
- "subtest_141": { "assert": "expression orientation should be parseable" },
- "subtest_142": { "assert": "expression orientation: portrait should be parseable" },
- "subtest_143": { "assert": "expression orientation: landscape should be parseable" },
- "subtest_144": { "assert": "expression min-orientation should not be parseable" },
- "subtest_145": { "assert": "expression min-orientation: portrait should not be parseable" },
- "subtest_146": { "assert": "expression min-orientation: landscape should not be parseable" },
- "subtest_147": { "assert": "expression max-orientation should not be parseable" },
- "subtest_148": { "assert": "expression max-orientation: portrait should not be parseable" },
- "subtest_149": { "assert": "expression max-orientation: landscape should not be parseable" },
- "subtest_150": { "assert": "(orientation) should apply" },
- "subtest_151": { "assert": "(orientation: landscape) should apply" },
- "subtest_152": { "assert": "(orientation: portrait) should not apply" },
- "subtest_153": { "assert": "not all and (orientation: portrait) should apply" },
- "subtest_154": { "assert": "(orientation) should apply" },
- "subtest_155": { "assert": "(orientation: landscape) should not apply" },
- "subtest_156": { "assert": "not all and (orientation: landscape) should apply" },
- "subtest_157": { "assert": "(orientation: portrait) should apply" },
- "subtest_158": { "assert": "(aspect-ratio: 59/80) should apply" },
- "subtest_159": { "assert": "(aspect-ratio: 58/80) should not apply" },
- "subtest_160": { "assert": "(aspect-ratio: 59/81) should not apply" },
- "subtest_161": { "assert": "(aspect-ratio: 60/80) should not apply" },
- "subtest_162": { "assert": "(aspect-ratio: 59/79) should not apply" },
- "subtest_163": { "assert": "(aspect-ratio: 177/240) should apply" },
- "subtest_164": { "assert": "(aspect-ratio: 413/560) should apply" },
- "subtest_165": { "assert": "(aspect-ratio: 5900/8000) should apply" },
- "subtest_166": { "assert": "(aspect-ratio: 5901/8000) should not apply" },
- "subtest_167": { "assert": "(aspect-ratio: 5899/8000) should not apply" },
- "subtest_168": { "assert": "(aspect-ratio: 5900/8001) should not apply" },
- "subtest_169": { "assert": "(aspect-ratio: 5900/7999) should not apply" },
- "subtest_170": { "assert": "(aspect-ratio) should apply" },
- "subtest_171": { "assert": "(min-aspect-ratio: 59/80) should apply" },
- "subtest_172": { "assert": "(min-aspect-ratio: 58/80) should apply" },
- "subtest_173": { "assert": "(min-aspect-ratio: 59/81) should apply" },
- "subtest_174": { "assert": "(min-aspect-ratio: 60/80) should not apply" },
- "subtest_175": { "assert": "(min-aspect-ratio: 59/79) should not apply" },
- "subtest_176": { "assert": "expression min-aspect-ratio should not be parseable" },
- "subtest_177": { "assert": "(max-aspect-ratio: 59/80) should apply" },
- "subtest_178": { "assert": "(max-aspect-ratio: 58/80) should not apply" },
- "subtest_179": { "assert": "(max-aspect-ratio: 59/81) should not apply" },
- "subtest_180": { "assert": "(max-aspect-ratio: 60/80) should apply" },
- "subtest_181": { "assert": "(max-aspect-ratio: 59/79) should apply" },
- "subtest_182": { "assert": "expression max-aspect-ratio should not be parseable" },
- "subtest_183": { "assert": "(device-aspect-ratio: 1920/1200) should apply" },
- "subtest_184": { "assert": "not all and (device-aspect-ratio: 1921/1200) should apply" },
- "subtest_185": { "assert": "all and (device-aspect-ratio: 1920/1199) should not apply" },
- "subtest_186": { "assert": "all and (device-aspect-ratio: 1919/1200) should not apply" },
- "subtest_187": { "assert": "not all and (device-aspect-ratio: 1920/1201) should apply" },
- "subtest_188": { "assert": "(device-aspect-ratio) should apply" },
- "subtest_189": { "assert": "(min-device-aspect-ratio: 1920/1200) should apply" },
- "subtest_190": { "assert": "all and (min-device-aspect-ratio: 1921/1200) should not apply" },
- "subtest_191": { "assert": "not all and (min-device-aspect-ratio: 1920/1199) should apply" },
- "subtest_192": { "assert": "not all and (min-device-aspect-ratio: 1919/1200) should not apply" },
- "subtest_193": { "assert": "all and (min-device-aspect-ratio: 1920/1201) should apply" },
- "subtest_194": { "assert": "expression min-device-aspect-ratio should not be parseable" },
- "subtest_195": { "assert": "all and (max-device-aspect-ratio: 1920/1200) should apply" },
- "subtest_196": { "assert": "(max-device-aspect-ratio: 1921/1200) should apply" },
- "subtest_197": { "assert": "(max-device-aspect-ratio: 1920/1199) should apply" },
- "subtest_198": { "assert": "all and (max-device-aspect-ratio: 1919/1200) should not apply" },
- "subtest_199": { "assert": "not all and (max-device-aspect-ratio: 1920/1201) should apply" },
- "subtest_200": { "assert": "expression max-device-aspect-ratio should not be parseable" },
- "subtest_201": { "assert": "expression max-aspect-ratio: 1/1 should be parseable" },
- "subtest_202": { "assert": "expression max-aspect-ratio: 1 /1 should be parseable" },
- "subtest_203": { "assert": "expression max-aspect-ratio: 1 / \t\n1 should be parseable" },
- "subtest_204": { "assert": "expression max-aspect-ratio: 1/\r1 should be parseable" },
- "subtest_205": { "assert": "expression max-aspect-ratio: 1 should not be parseable" },
- "subtest_206": { "assert": "expression max-aspect-ratio: 0.5 should not be parseable" },
- "subtest_207": { "assert": "expression max-aspect-ratio: 1.0/1 should not be parseable" },
- "subtest_208": { "assert": "expression max-aspect-ratio: 1/1.0 should not be parseable" },
- "subtest_209": { "assert": "expression max-aspect-ratio: 1.0/1.0 should not be parseable" },
- "subtest_210": { "assert": "expression max-aspect-ratio: 0/1 should not be parseable" },
- "subtest_211": { "assert": "expression max-aspect-ratio: 1/0 should not be parseable" },
- "subtest_212": { "assert": "expression max-aspect-ratio: 0/0 should not be parseable" },
- "subtest_213": { "assert": "expression max-aspect-ratio: -1/1 should not be parseable" },
- "subtest_214": { "assert": "expression max-aspect-ratio: 1/-1 should not be parseable" },
- "subtest_215": { "assert": "expression max-aspect-ratio: -1/-1 should not be parseable" },
- "subtest_216": { "assert": "expression device-aspect-ratio: 1/1 should be parseable" },
- "subtest_217": { "assert": "expression device-aspect-ratio: 1 /1 should be parseable" },
- "subtest_218": { "assert": "expression device-aspect-ratio: 1 / \t\n1 should be parseable" },
- "subtest_219": { "assert": "expression device-aspect-ratio: 1/\r1 should be parseable" },
- "subtest_220": { "assert": "expression device-aspect-ratio: 1 should not be parseable" },
- "subtest_221": { "assert": "expression device-aspect-ratio: 0.5 should not be parseable" },
- "subtest_222": { "assert": "expression device-aspect-ratio: 1.0/1 should not be parseable" },
- "subtest_223": { "assert": "expression device-aspect-ratio: 1/1.0 should not be parseable" },
- "subtest_224": { "assert": "expression device-aspect-ratio: 1.0/1.0 should not be parseable" },
- "subtest_225": { "assert": "expression device-aspect-ratio: 0/1 should not be parseable" },
- "subtest_226": { "assert": "expression device-aspect-ratio: 1/0 should not be parseable" },
- "subtest_227": { "assert": "expression device-aspect-ratio: 0/0 should not be parseable" },
- "subtest_228": { "assert": "expression device-aspect-ratio: -1/1 should not be parseable" },
- "subtest_229": { "assert": "expression device-aspect-ratio: 1/-1 should not be parseable" },
- "subtest_230": { "assert": "expression device-aspect-ratio: -1/-1 should not be parseable" },
- "monochrome_and_color": {},
- "find_depth": {},
- "subtest_231": { "assert": "all and (color:8) should apply" },
- "subtest_232": { "assert": "all and (color:7) should not apply" },
- "subtest_233": { "assert": "all and (color:9) should not apply" },
- "subtest_234": { "assert": "all and (max-color:8) should apply" },
- "subtest_235": { "assert": "all and (max-color:7) should not apply" },
- "subtest_236": { "assert": "all and (max-color:9) should apply" },
- "subtest_237": { "assert": "all and (color) should apply" },
- "subtest_238": { "assert": "expression max-color should not be parseable" },
- "subtest_239": { "assert": "expression min-color should not be parseable" },
- "subtest_240": { "assert": "all and (monochrome) should not apply" },
- "subtest_241": { "assert": "expression max-monochrome should not be parseable" },
- "subtest_242": { "assert": "expression min-monochrome should not be parseable" },
- "subtest_243": { "assert": "not all and (monochrome) should apply" },
- "subtest_244": { "assert": "not all and (color) should not apply" },
- "subtest_245": { "assert": "only all and (color) should apply" },
- "subtest_246": { "assert": "only all and (monochrome) should not apply" },
- "subtest_247": { "assert": "expression color: 1 should be parseable" },
- "subtest_248": { "assert": "expression color: 327 should be parseable" },
- "subtest_249": { "assert": "expression color: 0 should be parseable" },
- "subtest_250": { "assert": "expression color: 1.0 should not be parseable" },
- "subtest_251": { "assert": "expression color: -1 should not be parseable" },
- "subtest_252": { "assert": "expression color: 1/1 should not be parseable" },
- "subtest_253": { "assert": "expression min-monochrome: 1 should be parseable" },
- "subtest_254": { "assert": "expression min-monochrome: 327 should be parseable" },
- "subtest_255": { "assert": "expression min-monochrome: 0 should be parseable" },
- "subtest_256": { "assert": "expression min-monochrome: 1.0 should not be parseable" },
- "subtest_257": { "assert": "expression min-monochrome: -1 should not be parseable" },
- "subtest_258": { "assert": "expression min-monochrome: 1/1 should not be parseable" },
- "subtest_259": { "assert": "expression max-color-index: 1 should be parseable" },
- "subtest_260": { "assert": "expression max-color-index: 327 should be parseable" },
- "subtest_261": { "assert": "expression max-color-index: 0 should be parseable" },
- "subtest_262": { "assert": "expression max-color-index: 1.0 should not be parseable" },
- "subtest_263": { "assert": "expression max-color-index: -1 should not be parseable" },
- "subtest_264": { "assert": "expression max-color-index: 1/1 should not be parseable" },
- "subtest_265": { "assert": "(color-index: 0) should apply" },
- "subtest_266": { "assert": "(color-index: 1) should not apply" },
- "subtest_267": { "assert": "(min-color-index: 0) should apply" },
- "subtest_268": { "assert": "(min-color-index: 1) should not apply" },
- "subtest_269": { "assert": "(max-color-index: 0) should apply" },
- "subtest_270": { "assert": "(max-color-index: 1) should apply" },
- "subtest_271": { "assert": "(max-color-index: 157) should apply" },
- "subtest_272": { "assert": "expression resolution: 3dpi should be parseable" },
- "subtest_273": { "assert": "expression resolution:3dpi should be parseable" },
- "subtest_274": { "assert": "expression resolution: 3.0dpi should be parseable" },
- "subtest_275": { "assert": "expression resolution: 3.4dpi should be parseable" },
- "subtest_276": { "assert": "expression resolution\t: 120dpcm should be parseable" },
- "subtest_277": { "assert": "expression resolution: 0dpi should not be parseable" },
- "subtest_278": { "assert": "expression resolution: -3dpi should not be parseable" },
- "subtest_279": { "assert": "expression min-resolution: 3dpi should be parseable" },
- "subtest_280": { "assert": "expression min-resolution:3dpi should be parseable" },
- "subtest_281": { "assert": "expression min-resolution: 3.0dpi should be parseable" },
- "subtest_282": { "assert": "expression min-resolution: 3.4dpi should be parseable" },
- "subtest_283": { "assert": "expression min-resolution\t: 120dpcm should be parseable" },
- "subtest_284": { "assert": "expression min-resolution: 0dpi should not be parseable" },
- "subtest_285": { "assert": "expression min-resolution: -3dpi should not be parseable" },
- "subtest_286": { "assert": "expression max-resolution: 3dpi should be parseable" },
- "subtest_287": { "assert": "expression max-resolution:3dpi should be parseable" },
- "subtest_288": { "assert": "expression max-resolution: 3.0dpi should be parseable" },
- "subtest_289": { "assert": "expression max-resolution: 3.4dpi should be parseable" },
- "subtest_290": { "assert": "expression max-resolution\t: 120dpcm should be parseable" },
- "subtest_291": { "assert": "expression max-resolution: 0dpi should not be parseable" },
- "subtest_292": { "assert": "expression max-resolution: -3dpi should not be parseable" },
- "find_resolution": {},
- "subtest_293": { "assert": "(resolution: 133dpi) should apply" },
- "subtest_294": { "assert": "(resolution: 134dpi) should not apply" },
- "subtest_295": { "assert": "(resolution: 132dpi) should not apply" },
- "subtest_296": { "assert": "(min-resolution: 132dpi) should apply" },
- "subtest_297": { "assert": "not all and (min-resolution: 132dpi) should not apply" },
- "subtest_298": { "assert": "not all and (min-resolution: 134dpi) should apply" },
- "subtest_299": { "assert": "all and (min-resolution: 134dpi) should not apply" },
- "subtest_300": { "assert": "(min-resolution: 51dpcm) should apply" },
- "subtest_301": { "assert": "(max-resolution: 53dpcm) should apply" },
- "subtest_302": { "assert": "(max-resolution: 51dpcm) should not apply" },
- "subtest_303": { "assert": "not all and (min-resolution: 53dpcm) should apply" },
- "subtest_304": { "assert": "expression scan should be parseable" },
- "subtest_305": { "assert": "expression scan: progressive should be parseable" },
- "subtest_306": { "assert": "expression scan:interlace should be parseable" },
- "subtest_307": { "assert": "expression min-scan:interlace should not be parseable" },
- "subtest_308": { "assert": "expression scan: 1 should not be parseable" },
- "subtest_309": { "assert": "expression max-scan should not be parseable" },
- "subtest_310": { "assert": "expression max-scan: progressive should not be parseable" },
- "subtest_311": { "assert": "(scan) should not apply" },
- "subtest_312": { "assert": "(scan: progressive) should not apply" },
- "subtest_313": { "assert": "(scan: interlace) should not apply" },
- "subtest_314": { "assert": "not all and (scan) should apply" },
- "subtest_315": { "assert": "not all and (scan: progressive) should apply" },
- "subtest_316": { "assert": "not all and (scan: interlace) should apply" },
- "subtest_317": { "assert": "expression grid should be parseable" },
- "subtest_318": { "assert": "expression grid: 0 should be parseable" },
- "subtest_319": { "assert": "expression grid: 1 should be parseable" },
- "subtest_320": { "assert": "expression grid: 1 should be parseable" },
- "subtest_321": { "assert": "expression min-grid should not be parseable" },
- "subtest_322": { "assert": "expression min-grid:0 should not be parseable" },
- "subtest_323": { "assert": "expression max-grid: 1 should not be parseable" },
- "subtest_324": { "assert": "expression grid: 2 should not be parseable" },
- "subtest_325": { "assert": "expression grid: -1 should not be parseable" },
- "subtest_326": { "assert": "(grid) should not apply" },
- "subtest_327": { "assert": "(grid: 0) should apply" },
- "subtest_328": { "assert": "(grid: 1) should not apply" },
- "subtest_329": { "assert": "(grid: 2) should not apply" },
- "subtest_330": { "assert": "(grid: -1) should not apply" },
- "subtest_331": { "assert": "(orientation should apply" },
- "subtest_332": { "assert": "not all and (orientation should not apply" },
- "subtest_333": { "assert": "(orientation: should not apply" },
- "subtest_334": { "assert": "all,(orientation: should apply" },
- "subtest_335": { "assert": "(orientation:,all should not apply" },
- "subtest_336": { "assert": "not all and (grid should apply" },
- "subtest_337": { "assert": "only all and (grid should not apply" },
- "subtest_338": { "assert": "(grid should not apply" },
- "subtest_339": { "assert": "all,(grid should apply" },
- "subtest_340": { "assert": "(grid,all should not apply" },
- "subtest_341": { "assert": ",all should apply" },
- "subtest_342": { "assert": "all, should apply" },
- "subtest_343": { "assert": ",all, should apply" },
- "subtest_344": { "assert": "all,badmedium should apply" },
- "subtest_345": { "assert": "badmedium,all should apply" },
- "subtest_346": { "assert": ",badmedium, should not apply" },
- "subtest_347": { "assert": "all,(badexpression) should apply" },
- "subtest_348": { "assert": "(badexpression),all should apply" },
- "subtest_349": { "assert": "(badexpression),badmedium should not apply" },
- "subtest_350": { "assert": "badmedium,(badexpression) should not apply" },
- "subtest_351": { "assert": "all,[badsyntax] should apply" },
- "subtest_352": { "assert": "[badsyntax],all should apply" },
- "subtest_353": { "assert": "badmedium,[badsyntax] should not apply" },
- "subtest_354": { "assert": "[badsyntax],badmedium should not apply" },
- "subtest_355": { "assert": "query all and color : should not be parseable" },
- "subtest_356": { "assert": "query all and color : 1 should not be parseable" },
- "subtest_357": { "assert": "all and min-color : 1 should not apply" },
- "subtest_358": { "assert": "(bogus) should not apply" },
- "subtest_359": { "assert": "not all and (bogus) should not apply" },
- "subtest_360": { "assert": "only all and (bogus) should not apply" }
-}
-*/</script>
</head>
<body onload="run()">
<div id=log></div>
@@ -394,7 +27,7 @@ function run() {
function query_applies(q) {
style.setAttribute("media", q);
- return body_cs.getPropertyValue("text-decoration") == "underline";
+ return body_cs.getPropertyValue("text-decoration-line") == "underline";
}
function should_apply(q) {
diff --git a/tests/wpt/web-platform-tests/css/motion/animation/offset-path-interpolation-001.html b/tests/wpt/web-platform-tests/css/motion/animation/offset-path-interpolation-001.html
new file mode 100644
index 00000000000..279152e1033
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/motion/animation/offset-path-interpolation-001.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>offset-distance interpolation</title>
+ <link rel="author" title="Eric Willigers" href="mailto:ericwilligers@chromium.org">
+ <link rel="help" href="https://drafts.fxtf.org/motion-1/#offset-distance-property">
+ <meta name="assert" content="offset-distance supports animation.">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/interpolation-testcommon.js"></script>
+ </head>
+ <body>
+ <script>
+ 'use strict';
+
+ // Distinct number of path segments
+ test_no_interpolation({
+ property: 'offset-path',
+ from: "path('M 0 0 H 1 H 2')",
+ to: "path('M 0 0 H 3')"
+ });
+
+ test_no_interpolation({
+ property: 'offset-path',
+ from: "path('M 1 2 L 3 4 Z')",
+ to: "none"
+ });
+
+ // Distinct segment types
+ test_no_interpolation({
+ property: 'offset-path',
+ from: "path('M 10 0 H 11')",
+ to: "path('M 20 0 V 2')"
+ });
+
+ test_no_interpolation({
+ property: 'offset-path',
+ from: "path('M 1 2 L 4 6 Z')",
+ to: "path('M 1 2 H 4 V 6')"
+ });
+
+ // Exercise each segment type
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('M 0 0 Z')",
+ to: "path('M 0 0 Z')"
+ }, [
+ {at: -1, expect: "path('M 0 0 Z')"},
+ {at: 0, expect: "path('M 0 0 Z')"},
+ {at: 0.125, expect: "path('M 0 0 Z')"},
+ {at: 0.875, expect: "path('M 0 0 Z')"},
+ {at: 1, expect: "path('M 0 0 Z')"},
+ {at: 2, expect: "path('M 0 0 Z')"}
+ ]);
+
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('M 20 70')",
+ to: "path('M 100 30')"
+ }, [
+ {at: -1, expect: "path('M -60 110')"},
+ {at: 0, expect: "path('M 20 70')"},
+ {at: 0.125, expect: "path('M 30 65')"},
+ {at: 0.875, expect: "path('M 90 35')"},
+ {at: 1, expect: "path('M 100 30')"},
+ {at: 2, expect: "path('M 180 -10')"}
+ ]);
+
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('m 20 70')",
+ to: "path('m 100 30')"
+ }, [
+ {at: -1, expect: "path('M -60 110')"},
+ {at: 0, expect: "path('M 20 70')"},
+ {at: 0.125, expect: "path('M 30 65')"},
+ {at: 0.875, expect: "path('M 90 35')"},
+ {at: 1, expect: "path('M 100 30')"},
+ {at: 2, expect: "path('M 180 -10')"}
+ ]);
+
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('m 100 200 L 120 270')",
+ to: "path('m 100 200 L 200 230')"
+ }, [
+ {at: -1, expect: "path('M 100 200 L 40 310')"},
+ {at: 0, expect: "path('M 100 200 L 120 270')"},
+ {at: 0.125, expect: "path('M 100 200 L 130 265')"},
+ {at: 0.875, expect: "path('M 100 200 L 190 235')"},
+ {at: 1, expect: "path('M 100 200 L 200 230')"},
+ {at: 2, expect: "path('M 100 200 L 280 190')"}
+ ]);
+
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('m 100 200 l 20 70')",
+ to: "path('m 100 200 l 100 30')"
+ }, [
+ {at: -1, expect: "path('M 100 200 L 40 310')"},
+ {at: 0, expect: "path('M 100 200 L 120 270')"},
+ {at: 0.125, expect: "path('M 100 200 L 130 265')"},
+ {at: 0.875, expect: "path('M 100 200 L 190 235')"},
+ {at: 1, expect: "path('M 100 200 L 200 230')"},
+ {at: 2, expect: "path('M 100 200 L 280 190')"}
+ ]);
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/motion/animation/offset-path-interpolation-002.html b/tests/wpt/web-platform-tests/css/motion/animation/offset-path-interpolation-002.html
new file mode 100644
index 00000000000..742e9d0a9ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/motion/animation/offset-path-interpolation-002.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>offset-distance interpolation</title>
+ <link rel="author" title="Eric Willigers" href="mailto:ericwilligers@chromium.org">
+ <link rel="help" href="https://drafts.fxtf.org/motion-1/#offset-distance-property">
+ <meta name="assert" content="offset-distance supports animation.">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/interpolation-testcommon.js"></script>
+ </head>
+ <body>
+ <script>
+ 'use strict';
+
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('M 20 10 C 32 42 52 62 120 2200')",
+ to: "path('M 20 10 C 40 50 60 70 200 3000')",
+ }, [
+ {at: -1, expect: "path('M 20 10 C 24 34 44 54 40 1400')"},
+ {at: 0, expect: "path('M 20 10 C 32 42 52 62 120 2200')"},
+ {at: 0.125, expect: "path('M 20 10 C 33 43 53 63 130 2300')"},
+ {at: 0.875, expect: "path('M 20 10 C 39 49 59 69 190 2900')"},
+ {at: 1, expect: "path('M 20 10 C 40 50 60 70 200 3000')"},
+ {at: 2, expect: "path('M 20 10 C 48 58 68 78 280 3800')"}
+ ]);
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('m 20 10 c 12 32 32 52 100 2190')",
+ to: "path('m 20 10 c 20 40 40 60 180 2990')"
+ }, [
+ {at: -1, expect: "path('M 20 10 C 24 34 44 54 40 1400')"},
+ {at: 0, expect: "path('M 20 10 C 32 42 52 62 120 2200')"},
+ {at: 0.125, expect: "path('M 20 10 C 33 43 53 63 130 2300')"},
+ {at: 0.875, expect: "path('M 20 10 C 39 49 59 69 190 2900')"},
+ {at: 1, expect: "path('M 20 10 C 40 50 60 70 200 3000')"},
+ {at: 2, expect: "path('M 20 10 C 48 58 68 78 280 3800')"}
+ ]);
+
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('M 20 10 Q 32 42 120 2200')",
+ to: "path('M 20 10 Q 40 50 200 3000')"
+ }, [
+ {at: -1, expect: "path('M 20 10 Q 24 34 40 1400')"},
+ {at: 0, expect: "path('M 20 10 Q 32 42 120 2200')"},
+ {at: 0.125, expect: "path('M 20 10 Q 33 43 130 2300')"},
+ {at: 0.875, expect: "path('M 20 10 Q 39 49 190 2900')"},
+ {at: 1, expect: "path('M 20 10 Q 40 50 200 3000')"},
+ {at: 2, expect: "path('M 20 10 Q 48 58 280 3800')"}
+ ]);
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('m 20 10 q 12 32 100 2190')",
+ to: "path('m 20 10 q 20 40 180 2990')"
+ }, [
+ {at: -1, expect: "path('M 20 10 Q 24 34 40 1400')"},
+ {at: 0, expect: "path('M 20 10 Q 32 42 120 2200')"},
+ {at: 0.125, expect: "path('M 20 10 Q 33 43 130 2300')"},
+ {at: 0.875, expect: "path('M 20 10 Q 39 49 190 2900')"},
+ {at: 1, expect: "path('M 20 10 Q 40 50 200 3000')"},
+ {at: 2, expect: "path('M 20 10 Q 48 58 280 3800')"}
+ ]);
+
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('M 100 400 A 10 20 30 1 0 140 450')",
+ to: "path('M 300 200 A 50 60 70 0 1 380 290')"
+ }, [
+ {at: -1, expect: "path('M -100 600 A -30 -20 -10 1 0 -100 610')"},
+ {at: 0, expect: "path('M 100 400 A 10 20 30 1 0 140 450')"},
+ {at: 0.125, expect: "path('M 125 375 A 15 25 35 1 0 170 430')"},
+ {at: 0.875, expect: "path('M 275 225 A 45 55 65 0 1 350 310')"},
+ {at: 1, expect: "path('M 300 200 A 50 60 70 0 1 380 290')"},
+ {at: 2, expect: "path('M 500 0 A 90 100 110 0 1 620 130')"}
+ ]);
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('m 100 400 a 10 20 30 1 0 40 50')",
+ to: "path('m 300 200 a 50 60 70 0 1 80 90')"
+ }, [
+ {at: -1, expect: "path('M -100 600 A -30 -20 -10 1 0 -100 610')"},
+ {at: 0, expect: "path('M 100 400 A 10 20 30 1 0 140 450')"},
+ {at: 0.125, expect: "path('M 125 375 A 15 25 35 1 0 170 430')"},
+ {at: 0.875, expect: "path('M 275 225 A 45 55 65 0 1 350 310')"},
+ {at: 1, expect: "path('M 300 200 A 50 60 70 0 1 380 290')"},
+ {at: 2, expect: "path('M 500 0 A 90 100 110 0 1 620 130')"}
+ ]);
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/motion/animation/offset-path-interpolation-003.html b/tests/wpt/web-platform-tests/css/motion/animation/offset-path-interpolation-003.html
new file mode 100644
index 00000000000..a6d4e89efd0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/motion/animation/offset-path-interpolation-003.html
@@ -0,0 +1,118 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>offset-distance interpolation</title>
+ <link rel="author" title="Eric Willigers" href="mailto:ericwilligers@chromium.org">
+ <link rel="help" href="https://drafts.fxtf.org/motion-1/#offset-distance-property">
+ <meta name="assert" content="offset-distance supports animation.">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/interpolation-testcommon.js"></script>
+ </head>
+ <body>
+ <script>
+ 'use strict';
+
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('M 50 60 H 70')",
+ to: "path('M 10 140 H 270')"
+ }, [
+ {at: -1, expect: "path('M 90 -20 H -130')"},
+ {at: 0, expect: "path('M 50 60 H 70')"},
+ {at: 0.125, expect: "path('M 45 70 H 95')"},
+ {at: 0.875, expect: "path('M 15 130 H 245')"},
+ {at: 1, expect: "path('M 10 140 H 270')"},
+ {at: 2, expect: "path('M -30 220 H 470')"}
+ ]);
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('m 50 60 h 20')",
+ to: "path('m 10 140 h 260')"
+ }, [
+ {at: -1, expect: "path('M 90 -20 H -130')"},
+ {at: 0, expect: "path('M 50 60 H 70')"},
+ {at: 0.125, expect: "path('M 45 70 H 95')"},
+ {at: 0.875, expect: "path('M 15 130 H 245')"},
+ {at: 1, expect: "path('M 10 140 H 270')"},
+ {at: 2, expect: "path('M -30 220 H 470')"}
+ ]);
+
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('M 50 60 V 70')",
+ to: "path('M 10 140 V 270')"
+ }, [
+ {at: -1, expect: "path('M 90 -20 V -130')"},
+ {at: 0, expect: "path('M 50 60 V 70')"},
+ {at: 0.125, expect: "path('M 45 70 V 95')"},
+ {at: 0.875, expect: "path('M 15 130 V 245')"},
+ {at: 1, expect: "path('M 10 140 V 270')"},
+ {at: 2, expect: "path('M -30 220 V 470')"}
+ ]);
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('m 50 60 v 10')",
+ to: "path('m 10 140 v 130')"
+ }, [
+ {at: -1, expect: "path('M 90 -20 V -130')"},
+ {at: 0, expect: "path('M 50 60 V 70')"},
+ {at: 0.125, expect: "path('M 45 70 V 95')"},
+ {at: 0.875, expect: "path('M 15 130 V 245')"},
+ {at: 1, expect: "path('M 10 140 V 270')"},
+ {at: 2, expect: "path('M -30 220 V 470')"}
+ ]);
+
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('M 12 34 S 45 67 89 123')",
+ to: "path('M 20 26 S 61 51 113 99')"
+ }, [
+ {at: -1, expect: "path('M 4 42 S 29 83 65 147')"},
+ {at: 0, expect: "path('M 12 34 S 45 67 89 123')"},
+ {at: 0.125, expect: "path('M 13 33 S 47 65 92 120')"},
+ {at: 0.875, expect: "path('M 19 27 S 59 53 110 102')"},
+ {at: 1, expect: "path('M 20 26 S 61 51 113 99')"},
+ {at: 2, expect: "path('M 28 18 S 77 35 137 75')"},
+ ]);
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('m 12 34 s 33 33 77 89')",
+ to: "path('m 20 26 s 41 25 93 73')"
+ }, [
+ {at: -1, expect: "path('M 4 42 S 29 83 65 147')"},
+ {at: 0, expect: "path('M 12 34 S 45 67 89 123')"},
+ {at: 0.125, expect: "path('M 13 33 S 47 65 92 120')"},
+ {at: 0.875, expect: "path('M 19 27 S 59 53 110 102')"},
+ {at: 1, expect: "path('M 20 26 S 61 51 113 99')"},
+ {at: 2, expect: "path('M 28 18 S 77 35 137 75')"},
+ ]);
+
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('M 12 34 T 45 67')",
+ to: "path('M 20 26 T 61 51')"
+ }, [
+ {at: -1, expect: "path('M 4 42 T 29 83')"},
+ {at: 0, expect: "path('M 12 34 T 45 67')"},
+ {at: 0.125, expect: "path('M 13 33 T 47 65')"},
+ {at: 0.875, expect: "path('M 19 27 T 59 53')"},
+ {at: 1, expect: "path('M 20 26 T 61 51')"},
+ {at: 2, expect: "path('M 28 18 T 77 35')"},
+ ]);
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('m 12 34 t 33 33')",
+ to: "path('m 20 26 t 41 25')"
+ }, [
+ {at: -1, expect: "path('M 4 42 T 29 83')"},
+ {at: 0, expect: "path('M 12 34 T 45 67')"},
+ {at: 0.125, expect: "path('M 13 33 T 47 65')"},
+ {at: 0.875, expect: "path('M 19 27 T 59 53')"},
+ {at: 1, expect: "path('M 20 26 T 61 51')"},
+ {at: 2, expect: "path('M 28 18 T 77 35')"},
+ ]);
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/motion/animation/offset-path-interpolation-004.html b/tests/wpt/web-platform-tests/css/motion/animation/offset-path-interpolation-004.html
new file mode 100644
index 00000000000..f3e07ab97b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/motion/animation/offset-path-interpolation-004.html
@@ -0,0 +1,123 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>offset-distance interpolation</title>
+ <link rel="author" title="Eric Willigers" href="mailto:ericwilligers@chromium.org">
+ <link rel="help" href="https://drafts.fxtf.org/motion-1/#offset-distance-property">
+ <meta name="assert" content="offset-distance supports animation.">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/interpolation-testcommon.js"></script>
+ </head>
+ <body>
+ <script>
+ 'use strict';
+
+ // Mix relative and non-relative
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')",
+ to: "path('M 0 0 L 100 100 m 0 100 l 100 0 z l 300 100 z')"
+ }, [
+ {at: -1, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 0 -100 Z')"},
+ {at: 0, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"},
+ {at: 0.125, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 225 125 Z')"},
+ {at: 0.875, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 375 275 Z')"},
+ {at: 1, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 400 300 Z')"},
+ {at: 2, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 600 500 Z')"},
+ ]);
+
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')",
+ to: "path('M 0 0 L 100 100 m 0 100 l 100 0 z l 100 -100 z')"
+ }, [
+ {at: -1, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"},
+ {at: 0, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"},
+ {at: 0.125, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"},
+ {at: 0.875, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"},
+ {at: 1, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"},
+ {at: 2, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"},
+ ]);
+
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('m 10 20 l 40 50 z l 40 60 z m 60 70 l 90 60 z t 70 130')",
+ to: "path('M 210 220 L 170 190 Z L 90 120 Z M 110 130 L 200 230 Z T 220 220')"
+ }, [
+ {at: -1, expect: "path('M -190 -180 L -70 -50 Z L 10 40 Z M 30 50 L 120 70 Z T 60 220')"},
+ {at: 0, expect: "path('M 10 20 L 50 70 Z L 50 80 Z M 70 90 L 160 150 Z T 140 220')"},
+ {at: 0.125, expect: "path('M 35 45 L 65 85 Z L 55 85 Z M 75 95 L 165 160 Z T 150 220')"},
+ {at: 0.875, expect: "path('M 185 195 L 155 175 Z L 85 115 Z M 105 125 L 195 220 Z T 210 220')"},
+ {at: 1, expect: "path('M 210 220 L 170 190 Z L 90 120 Z M 110 130 L 200 230 Z T 220 220')"},
+ {at: 2, expect: "path('M 410 420 L 290 310 Z L 130 160 Z M 150 170 L 240 310 Z T 300 220')"}
+ ]);
+
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('m 10 20 c 40 50 30 60 80 70 c 120 130 170 140 110 160')",
+ to: "path('M 130 100 C 130 150 120 160 210 170 C 290 300 340 310 320 330')"
+ }, [
+ {at: -1, expect: "path('M -110 -60 C -30 -10 -40 0 -30 10 C 130 140 180 150 80 170')"},
+ {at: 0, expect: "path('M 10 20 C 50 70 40 80 90 90 C 210 220 260 230 200 250')"},
+ {at: 0.125, expect: "path('M 25 30 C 60 80 50 90 105 100 C 220 230 270 240 215 260')"},
+ {at: 0.875, expect: "path('M 115 90 C 120 140 110 150 195 160 C 280 290 330 300 305 320')"},
+ {at: 1, expect: "path('M 130 100 C 130 150 120 160 210 170 C 290 300 340 310 320 330')"},
+ {at: 2, expect: "path('M 250 180 C 210 230 200 240 330 250 C 370 380 420 390 440 410')"}
+ ]);
+
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('m 10 20 q 30 60 40 50 q 110 80 90 80')",
+ to: "path('M 130 100 Q 120 160 130 150 Q 200 150 180 190')"
+ }, [
+ {at: -1, expect: "path('M -110 -60 Q -40 0 -30 -10 Q 120 150 100 110')"},
+ {at: 0, expect: "path('M 10 20 Q 40 80 50 70 Q 160 150 140 150')"},
+ {at: 0.125, expect: "path('M 25 30 Q 50 90 60 80 Q 165 150 145 155')"},
+ {at: 0.875, expect: "path('M 115 90 Q 110 150 120 140 Q 195 150 175 185')"},
+ {at: 1, expect: "path('M 130 100 Q 120 160 130 150 Q 200 150 180 190')"},
+ {at: 2, expect: "path('M 250 180 Q 200 240 210 230 Q 240 150 220 230')"}
+ ]);
+
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('m 10 20 s 30 60 40 50 s 110 60 90 70')",
+ to: "path('M 130 140 S 120 160 130 150 S 200 170 140 180')"
+ }, [
+ {at: -1, expect: "path('M -110 -100 S -40 0 -30 -10 S 120 90 140 100')"},
+ {at: 0, expect: "path('M 10 20 S 40 80 50 70 S 160 130 140 140')"},
+ {at: 0.125, expect: "path('M 25 35 S 50 90 60 80 S 165 135 140 145')"},
+ {at: 0.875, expect: "path('M 115 125 S 110 150 120 140 S 195 165 140 175')"},
+ {at: 1, expect: "path('M 130 140 S 120 160 130 150 S 200 170 140 180')"},
+ {at: 2, expect: "path('M 250 260 S 200 240 210 230 S 240 210 140 220')"}
+ ]);
+
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('m 10 20 h 30 v 60 h 10 v -10 l 110 60')",
+ to: "path('M 130 140 H 120 V 160 H 130 V 150 L 200 170')"
+ }, [
+ {at: -1, expect: "path('M -110 -100 H -40 V 0 H -30 V -10 L 120 90')"},
+ {at: 0, expect: "path('M 10 20 H 40 V 80 H 50 V 70 L 160 130')"},
+ {at: 0.125, expect: "path('M 25 35 H 50 V 90 H 60 V 80 L 165 135')"},
+ {at: 0.875, expect: "path('M 115 125 H 110 V 150 H 120 V 140 L 195 165')"},
+ {at: 1, expect: "path('M 130 140 H 120 V 160 H 130 V 150 L 200 170')"},
+ {at: 2, expect: "path('M 250 260 H 200 V 240 H 210 V 230 L 240 210')"}
+ ]);
+
+ test_interpolation({
+ property: 'offset-path',
+ from: "path('m 10 20 a 10 20 30 1 0 40 50 a 110 120 30 1 1 140 50')",
+ to: "path('M 18 12 A 50 100 70 0 1 90 110 A 150 160 70 0 1 70 80')"
+ }, [
+ {at: -1, expect: "path('M 2 28 A -30 -60 -10 1 0 10 30 A 70 80 -10 1 1 310 160')"},
+ {at: 0, expect: "path('M 10 20 A 10 20 30 1 0 50 70 A 110 120 30 1 1 190 120')"},
+ {at: 0.125, expect: "path('M 11 19 A 15 30 35 1 0 55 75 A 115 125 35 1 1 175 115')"},
+ {at: 0.875, expect: "path('M 17 13 A 45 90 65 0 1 85 105 A 145 155 65 0 1 85 85')"},
+ {at: 1, expect: "path('M 18 12 A 50 100 70 0 1 90 110 A 150 160 70 0 1 70 80')"},
+ {at: 2, expect: "path('M 26 4 A 90 180 110 0 1 130 150 A 190 200 110 0 1 -50 40')"}
+ ]);
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/motion/animation/offset-path-interpolation-005.html b/tests/wpt/web-platform-tests/css/motion/animation/offset-path-interpolation-005.html
new file mode 100644
index 00000000000..617fff0490d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/motion/animation/offset-path-interpolation-005.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>offset-distance interpolation</title>
+ <link rel="author" title="Eric Willigers" href="mailto:ericwilligers@chromium.org">
+ <link rel="help" href="https://drafts.fxtf.org/motion-1/#offset-distance-property">
+ <meta name="assert" content="offset-distance supports animation.">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/interpolation-testcommon.js"></script>
+ </head>
+ <body>
+ <script>
+ 'use strict';
+
+ test_no_interpolation({
+ property: 'offset-path',
+ from: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')",
+ to: "ray(0deg closest-side)",
+ });
+
+ test_no_interpolation({
+ property: 'offset-path',
+ from: "ray(0deg closest-corner)",
+ to: "none",
+ });
+
+ // No interpolation to a ray from the initial value 'none'.
+ test_no_interpolation({
+ property: 'offset-path',
+ from: 'none',
+ to: 'ray(20deg closest-side)',
+ });
+
+ // Interpolation between rays.
+ test_interpolation({
+ property: 'offset-path',
+ from: 'ray(10deg sides contain)',
+ to: 'ray(50deg sides contain)'
+ }, [
+ {at: -1, expect: 'ray(-30deg sides contain)'},
+ {at: 0, expect: 'ray(10deg sides contain)'},
+ {at: 0.125, expect: 'ray(15deg sides contain)'},
+ {at: 0.875, expect: 'ray(45deg sides contain)'},
+ {at: 1, expect: 'ray(50deg sides contain)'},
+ {at: 2, expect: 'ray(90deg sides contain)'},
+ ]);
+
+ test_interpolation({
+ property: 'offset-path',
+ from: 'ray(-10deg farthest-corner)',
+ to: 'ray(-50deg farthest-corner)'
+ }, [
+ {at: -1, expect: 'ray(30deg farthest-corner)'},
+ {at: 0, expect: 'ray(-10deg farthest-corner)'},
+ {at: 0.125, expect: 'ray(-15deg farthest-corner)'},
+ {at: 0.875, expect: 'ray(-45deg farthest-corner)'},
+ {at: 1, expect: 'ray(-50deg farthest-corner)'},
+ {at: 2, expect: 'ray(-90deg farthest-corner)'},
+ ]);
+
+ // No interpolation between different sizes and/or different containment.
+ test_no_interpolation({
+ property: 'offset-path',
+ from: 'ray(200deg farthest-side)',
+ to: 'ray(300deg sides)'
+ });
+ test_no_interpolation({
+ property: 'offset-path',
+ from: 'ray(200deg sides contain)',
+ to: 'ray(300deg sides)'
+ });
+ test_no_interpolation({
+ property: 'offset-path',
+ from: 'ray(200deg farthest-side contain)',
+ to: 'ray(300deg sides)'
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/css/reference/nothing.html b/tests/wpt/web-platform-tests/css/reference/nothing.html
new file mode 100644
index 00000000000..98ee818a846
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/reference/nothing.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<title>CSS Reftest Reference</title>
+<link rel="author" title="Morten Stenshorne" href="mstensho@chromium.org">
+<p>There should be nothing below.</p>
diff --git a/tests/wpt/web-platform-tests/css/reference/ref-filled-green-100px-square-only.html b/tests/wpt/web-platform-tests/css/reference/ref-filled-green-100px-square-only.html
new file mode 100644
index 00000000000..82fcaa3b2aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/reference/ref-filled-green-100px-square-only.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mstensho@chromium.org">
+<p>Test passes if there is a filled green square.</p>
+<div style="width:100px; height:100px; background:green;"></div>
diff --git a/tests/wpt/web-platform-tests/css/selectors/any-link-dynamic-001-ref.html b/tests/wpt/web-platform-tests/css/selectors/any-link-dynamic-001-ref.html
new file mode 100644
index 00000000000..b5407429be8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/selectors/any-link-dynamic-001-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS test reference</title>
+<link rel="author" title="Boris Zbarsky" href="mailto:bzbarsky@mit.edu">
+<style>
+ span { color: green; }
+</style>
+<body>
+ <a></a><span>This should be green</span>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/selectors/any-link-dynamic-001.html b/tests/wpt/web-platform-tests/css/selectors/any-link-dynamic-001.html
new file mode 100644
index 00000000000..e84989fd0c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/selectors/any-link-dynamic-001.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS test: Handling of dynamic changes to :any-link selectors</title>
+<link rel="author" title="Boris Zbarsky" href="mailto:bzbarsky@mit.edu">
+<link rel="match" href="any-link-dynamic-001-ref.html">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#the-any-link-pseudo">
+<style>
+ span { color: green; }
+ :any-link + span { color: red; }
+</style>
+<body onload="window.oldColor = getComputedStyle(document.querySelector('span')).color;
+ document.querySelector('a').removeAttribute('href');">
+ <a href=""></a><span>This should be green</span>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/selectors/invalidation/any-link-pseudo.html b/tests/wpt/web-platform-tests/css/selectors/invalidation/any-link-pseudo.html
new file mode 100644
index 00000000000..9792fd0ebe1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/selectors/invalidation/any-link-pseudo.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>CSS Selectors Invalidation: :any-link</title>
+ <link rel="author" title="Victoria Su" href="mailto:victoriaytsu@google.com">
+ <link rel="help" href="https://drafts.csswg.org/selectors-4/#the-any-link-pseudo">
+ <meta name="assert" content="This tests that the :any-link selector is effective">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style>
+ #link { background-color: red }
+ #link:any-link { background-color: green }
+ #link + div { color: pink }
+ </style>
+ <a id="link">This link should have a green background.</a>
+ <div>
+ <div></div>
+ <div></div>
+ <div></div>
+ <div></div>
+ </div>
+ <script>
+ test(function() {
+ var red = "rgb(255, 0, 0)";
+ var green = "rgb(0, 128, 0)";
+
+ assert_equals(getComputedStyle(link).backgroundColor, red);
+
+ link.href = "not-visited.html";
+
+ assert_equals(getComputedStyle(link).backgroundColor, green);
+ }, "Style was recalculated for the :any-link pseudo class.");
+
+ </script>
+ </head>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/custom-elements/parser/parser-uses-registry-of-owner-document.html b/tests/wpt/web-platform-tests/custom-elements/parser/parser-uses-registry-of-owner-document.html
index efdc3a2a47c..51e3e5ddfb1 100644
--- a/tests/wpt/web-platform-tests/custom-elements/parser/parser-uses-registry-of-owner-document.html
+++ b/tests/wpt/web-platform-tests/custom-elements/parser/parser-uses-registry-of-owner-document.html
@@ -8,6 +8,7 @@
<link rel="help" href="https://dom.spec.whatwg.org/#concept-create-element">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/custom-elements-helpers.js"></script>
</head>
<body>
<div id="log"></div>
@@ -71,17 +72,14 @@ test(function () {
document.body.removeChild(iframe);
test(function () {
- var windowlessDocument = document.implementation.createHTMLDocument();
- windowlessDocument.open();
- windowlessDocument.write('<my-custom-element></my-custom-element>');
- windowlessDocument.close();
+ var windowlessDocument = (new DOMParser()).parseFromString('<my-custom-element></my-custom-element>', "text/html");
var instance = windowlessDocument.querySelector('my-custom-element');
assert_true(instance instanceof HTMLElement);
assert_false(instance instanceof MyCustomElement);
-}, 'HTML parser must use the registry of window.document in a document created by document.implementation.createHTMLDocument()');
+}, 'HTML parser must use the registry of window.document in a document created by DOMParser');
test(function () {
var windowlessDocument = document.implementation.createDocument ('http://www.w3.org/1999/xhtml', 'html', null);
@@ -108,19 +106,51 @@ test(function () {
promise_test(function () {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
- xhr.open('GET', '../resources/empty-html-document.html');
+ xhr.open('GET', '../resources/my-custom-element-html-document.html');
xhr.overrideMimeType('text/xml');
xhr.onload = function () { resolve(xhr.responseXML); }
xhr.onerror = function () { reject('Failed to fetch the document'); }
xhr.send();
}).then(function (doc) {
- doc.documentElement.innerHTML = '<my-custom-element></my-custom-element>';
var instance = doc.querySelector('my-custom-element');
assert_true(instance instanceof Element);
- assert_false(instance instanceof MyCustomElement);
+ assert_false(instance instanceof MyCustomElement);
+
+ doc.documentElement.innerHTML = '<my-custom-element></my-custom-element>';
+ var instance2 = doc.querySelector('my-custom-element');
+ assert_true(instance2 instanceof Element);
+ assert_false(instance2 instanceof MyCustomElement);
});
}, 'HTML parser must use the registry of window.document in a document created by XMLHttpRequest');
+test_with_window(function (contentWindow, contentDocument) {
+ const element = define_custom_element_in_window(contentWindow, 'my-custom-element', []);
+ // document-open-steps spec doesn't match most browsers; see https://github.com/whatwg/html/issues/1698.
+ // However, as explained in https://github.com/whatwg/html/issues/1698#issuecomment-298748641
+ // the custom element registry will be replaced after document-open-steps.
+ contentDocument.write('<my-custom-element></my-custom-element>');
+
+ var instance = contentDocument.querySelector('my-custom-element');
+
+ assert_true(instance instanceof contentWindow.HTMLElement);
+ assert_false(instance instanceof element.class);
+
+}, 'document.write() must not instantiate a custom element without a defined insertion point');
+
+test_with_window(function (contentWindow, contentDocument) {
+ const element = define_custom_element_in_window(contentWindow, 'my-custom-element', []);
+ // document-open-steps spec doesn't match most browsers; see https://github.com/whatwg/html/issues/1698.
+ // However, as explained in https://github.com/whatwg/html/issues/1698#issuecomment-298748641
+ // the custom element registry will be replaced after document-open-steps.
+ contentDocument.writeln('<my-custom-element></my-custom-element>');
+
+ var instance = contentDocument.querySelector('my-custom-element');
+
+ assert_true(instance instanceof contentWindow.HTMLElement);
+ assert_false(instance instanceof element.class);
+
+}, 'document.writeln() must not instantiate a custom element without a defined insertion point');
+
</script>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/reactions/Document.html b/tests/wpt/web-platform-tests/custom-elements/reactions/Document.html
index 98c642bcf26..721ad1f4ced 100644
--- a/tests/wpt/web-platform-tests/custom-elements/reactions/Document.html
+++ b/tests/wpt/web-platform-tests/custom-elements/reactions/Document.html
@@ -129,6 +129,12 @@ test_with_window(function (contentWindow, contentDocument) {
}, 'write on Document must enqueue disconnectedCallback when removing a custom element');
test_with_window(function (contentWindow, contentDocument) {
+ contentWindow.document.open();
+ // document.open()'s spec doesn't match most browsers; see https://github.com/whatwg/html/issues/1698.
+ // However, as explained in https://github.com/whatwg/html/issues/1698#issuecomment-298748641
+ // the custom element registry will be replaced after document.open() call,
+ // So call customElements.define() after that in order to register defintion
+ // to correct custom elements registry.
const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
contentWindow.document.write('<custom-element></custom-element>');
assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
@@ -144,6 +150,12 @@ test_with_window(function (contentWindow, contentDocument) {
}, 'writeln on Document must enqueue disconnectedCallback when removing a custom element');
test_with_window(function (contentWindow) {
+ contentWindow.document.open();
+ // document.open()'s spec doesn't match most browsers; see https://github.com/whatwg/html/issues/1698.
+ // However, as explained in https://github.com/whatwg/html/issues/1698#issuecomment-298748641
+ // the custom element registry will be replaced after document.open() call,
+ // So call customElements.define() after that in order to register defintion
+ // to correct custom elements registry.
const element = define_custom_element_in_window(contentWindow, 'custom-element', []);
contentWindow.document.writeln('<custom-element></custom-element>');
assert_array_equals(element.takeLog().types(), ['constructed', 'connected']);
diff --git a/tests/wpt/web-platform-tests/custom-elements/reactions/with-exceptions.html b/tests/wpt/web-platform-tests/custom-elements/reactions/with-exceptions.html
new file mode 100644
index 00000000000..82e0f59c930
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/reactions/with-exceptions.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Custom Elements: CEReactions interaction with exceptions</title>
+<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
+<meta name="help" content="https://html.spec.whatwg.org/multipage/#cereactions">
+<meta name="help" content="https://github.com/whatwg/html/pull/3235">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/custom-elements-helpers.js"></script>
+
+<div id="log"></div>
+
+<script>
+"use strict";
+// Basically from https://github.com/whatwg/html/issues/3217#issuecomment-343633273
+test_with_window((contentWindow, contentDocument) => {
+ let reactionRan = false;
+ contentWindow.customElements.define("custom-element", class extends contentWindow.HTMLElement {
+ disconnectedCallback() {
+ reactionRan = true;
+ }
+ });
+ const text = contentDocument.createTextNode("");
+ contentDocument.documentElement.appendChild(text);
+ const element = contentDocument.createElement("custom-element");
+ contentDocument.documentElement.appendChild(element);
+ assert_throws("HierarchyRequestError", () => text.before("", contentDocument.documentElement));
+ assert_true(reactionRan);
+}, "Reaction must run even after the exception is thrown");
+</script>
diff --git a/tests/wpt/web-platform-tests/custom-elements/resources/my-custom-element-html-document.html b/tests/wpt/web-platform-tests/custom-elements/resources/my-custom-element-html-document.html
new file mode 100644
index 00000000000..b9bfdf90a2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/resources/my-custom-element-html-document.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html>
+<body>
+<my-custom-element></my-custom-element>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/events/Event-subclasses-constructors.html b/tests/wpt/web-platform-tests/dom/events/Event-subclasses-constructors.html
index 1741b960025..1fd70d4222b 100644
--- a/tests/wpt/web-platform-tests/dom/events/Event-subclasses-constructors.html
+++ b/tests/wpt/web-platform-tests/dom/events/Event-subclasses-constructors.html
@@ -21,6 +21,23 @@ function assert_props(iface, event, defaults) {
}
}
+// Class declarations don't go on the global by default, so put it there ourselves:
+
+self.SubclassedEvent = class SubclassedEvent extends Event {
+ constructor(name, props) {
+ super(name, props);
+ if (props && typeof(props) == "object" && "customProp" in props) {
+ this.customProp = props.customProp;
+ } else {
+ this.customProp = 5;
+ }
+ }
+
+ get fixedProp() {
+ return 17;
+ }
+}
+
var EventModifierInit = [
["ctrlKey", false, true],
["shiftKey", false, true],
@@ -32,6 +49,7 @@ var expected = {
"properties": [
["bubbles", false, true],
["cancelable", false, true],
+ ["isTrusted", false, false],
],
},
@@ -93,6 +111,14 @@ var expected = {
["data", "", "string"],
],
},
+
+ "SubclassedEvent": {
+ "parent": "Event",
+ "properties": [
+ ["customProp", 5, 8],
+ ["fixedProp", 17, 17],
+ ],
+ },
};
Object.keys(expected).forEach(function(iface) {
diff --git a/tests/wpt/web-platform-tests/dom/events/EventListener-invoke-legacy.html b/tests/wpt/web-platform-tests/dom/events/EventListener-invoke-legacy.html
index 85a4b0a5fe6..a01afcd8d19 100644
--- a/tests/wpt/web-platform-tests/dom/events/EventListener-invoke-legacy.html
+++ b/tests/wpt/web-platform-tests/dom/events/EventListener-invoke-legacy.html
@@ -51,22 +51,16 @@ function runLegacyEventTest(type, legacyType, ctor, setup) {
}
function setupTransition(elem) {
- elem.style.transition = '';
- requestAnimationFrame(function() {
- elem.style.color = 'red';
- elem.style.transition = 'color 30ms';
- requestAnimationFrame(function() {
- elem.style.color = 'green';
- });
- });
+ getComputedStyle(elem).color;
+ elem.style.color = 'green';
+ elem.style.transition = 'color 30ms';
}
function setupAnimation(elem) {
- elem.style.animation = 'test 30ms 2';
+ elem.style.animation = 'test 30ms';
}
runLegacyEventTest('transitionend', 'webkitTransitionEnd', "TransitionEvent", setupTransition);
runLegacyEventTest('animationend', 'webkitAnimationEnd', "AnimationEvent", setupAnimation);
-runLegacyEventTest('animationiteration', 'webkitAnimationIteration', "AnimationEvent", setupAnimation);
runLegacyEventTest('animationstart', 'webkitAnimationStart', "AnimationEvent", setupAnimation);
</script>
diff --git a/tests/wpt/web-platform-tests/dom/historical.html b/tests/wpt/web-platform-tests/dom/historical.html
index c6fd00ff55c..388366c084c 100644
--- a/tests/wpt/web-platform-tests/dom/historical.html
+++ b/tests/wpt/web-platform-tests/dom/historical.html
@@ -178,4 +178,14 @@ var EventRemoved = [
"CHANGE"
]
EventRemoved.forEach(isRemovedFromEvent)
+
+var EventPrototypeRemoved = [
+ "getPreventDefault",
+]
+EventPrototypeRemoved.forEach(name => {
+ test(() => {
+ assert_equals(Event.prototype[name], undefined)
+ assert_equals((new Event("test"))[name], undefined)
+ }, "Event.prototype should not have this property: " + name)
+})
</script>
diff --git a/tests/wpt/web-platform-tests/encoding/big5-encoder.html b/tests/wpt/web-platform-tests/encoding/big5-encoder.html
index 7260b6b155b..58d60d50db1 100644
--- a/tests/wpt/web-platform-tests/encoding/big5-encoder.html
+++ b/tests/wpt/web-platform-tests/encoding/big5-encoder.html
@@ -15,8 +15,8 @@
encode("ab", "ab", "very basic")
// edge cases
- encode("\u9EA6", "%26%2340614%3B", "Highest-pointer BMP character excluded from encoder");
- encode("\uD858\uDE6B", "%26%23156267%3B", "Highest-pointer character excluded from encoder");
+ encode("\u9EA6", "&%2340614;", "Highest-pointer BMP character excluded from encoder");
+ encode("\uD858\uDE6B", "&%23156267;", "Highest-pointer character excluded from encoder");
encode("\u3000", "%A1@", "Lowest-pointer character included in encoder");
encode("\u20AC", "%A3%E1", "Euro; the highest-pointer character before a range of 30 unmapped pointers");
encode("\u4E00", "%A4@", "The lowest-pointer character after the range of 30 unmapped pointers");
@@ -24,8 +24,8 @@
encode("\uFFE2", "%C8%CD", "The lowest-pointer character after the range of 41 unmapped pointers");
encode("\u79D4", "%FE%FE", "The last character in the index");
// not in index
- encode("\u2603", "%26%239731%3B", "The canonical BMP test character that is not in the index");
- encode("\uD83D\uDCA9", "%26%23128169%3B", "The canonical astral test character that is not in the index");
+ encode("\u2603", "&%239731;", "The canonical BMP test character that is not in the index");
+ encode("\uD83D\uDCA9", "&%23128169;", "The canonical astral test character that is not in the index");
// duplicate low bits
encode("\uD840\uDFB5", "%FDj", "A Plane 2 character whose low 16 bits match a BMP character that has a lower pointer");
// prefer last
diff --git a/tests/wpt/web-platform-tests/encoding/gbk-encoder.html b/tests/wpt/web-platform-tests/encoding/gbk-encoder.html
index a6074f975d3..90d0824ce23 100644
--- a/tests/wpt/web-platform-tests/encoding/gbk-encoder.html
+++ b/tests/wpt/web-platform-tests/encoding/gbk-encoder.html
@@ -17,5 +17,5 @@
encode("\u4E02", "%81@", "character")
encode("\uE4C6", "%A1@", "PUA")
encode("\uE4C5", "%FE%FE", "PUA #2")
- encode("\ud83d\udca9", "%26%23128169%3B", "poo")
+ encode("\ud83d\udca9", "&%23128169;", "poo")
</script>
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-check-initdata-type.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-check-initdata-type.https.html
index 00894338ae8..00894338ae8 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-check-initdata-type.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-check-initdata-type.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-events-session-closed-event.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-events-session-closed-event.https.html
index ddf3ecbbbf7..ddf3ecbbbf7 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-events-session-closed-event.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-events-session-closed-event.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-events.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-events.https.html
index 4f3b6222b86..4f3b6222b86 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-events.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-events.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-generate-request-disallowed-input.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-generate-request-disallowed-input.https.html
index af6e76c2b33..af6e76c2b33 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-generate-request-disallowed-input.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-generate-request-disallowed-input.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-invalid-license.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-invalid-license.https.html
index 09ff934a04d..09ff934a04d 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-invalid-license.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-invalid-license.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-keystatuses-multiple-sessions.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-keystatuses-multiple-sessions.https.html
index 3474f9d5151..3474f9d5151 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-keystatuses-multiple-sessions.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-keystatuses-multiple-sessions.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-keystatuses.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-keystatuses.https.html
index 6edec35cd02..6edec35cd02 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-keystatuses.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-keystatuses.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-destroy-persistent-license.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-destroy-persistent-license.https.html
index 547f01b3608..547f01b3608 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-destroy-persistent-license.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-destroy-persistent-license.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-persistent-license-events.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-persistent-license-events.https.html
index 99aba6386c9..99aba6386c9 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-persistent-license-events.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-persistent-license-events.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-persistent-license.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-persistent-license.https.html
index 352a2a7b0f8..352a2a7b0f8 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-persistent-license.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-persistent-license.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.https.html
index 795cf5b602f..795cf5b602f 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-persistent-usage-record-events.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-persistent-usage-record.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-persistent-usage-record.https.html
index a2eb397d64d..a2eb397d64d 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-persistent-usage-record.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-persistent-usage-record.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.https.html
index 85510b24bb5..85510b24bb5 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-retrieve-destroy-persistent-license.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.https.html
index 7d8fe57ffb1..7d8fe57ffb1 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-license.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.https.html
index c612b8cd98d..c612b8cd98d 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-retrieve-persistent-usage-record.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.https.html
index 9eca41cc08b..9eca41cc08b 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-clear-encrypted.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.https.html
index 884d22d7577..884d22d7577 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear-sources.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.https.html
index 1e190246372..1e190246372 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-encrypted-clear.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-events.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-events.https.html
index c4d4ea37de6..c4d4ea37de6 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-events.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-events.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.https.html
index 66313e727e1..66313e727e1 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential-readyState.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.https.html
index 64b00cd2902..64b00cd2902 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-multikey-sequential.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-multikey.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-multikey.https.html
index 29d1a2eed5d..29d1a2eed5d 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-multikey.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-multikey.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-multisession.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-multisession.https.html
index 8f32120f14e..8f32120f14e 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-multisession.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-multisession.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.https.html
index bade71626bb..bade71626bb 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-src.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.https.html
index 1085ce4e772..1085ce4e772 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-after-update.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.https.html
index 7f362f44251..7f362f44251 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-immediately.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.https.html
index a49bc28d3d0..a49bc28d3d0 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-setMediaKeys-onencrypted.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-two-videos.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-two-videos.https.html
index 95de680e477..95de680e477 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-two-videos.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-two-videos.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.https.html
index 94d35daa510..94d35daa510 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary-waitingforkey.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary.https.html
index 909f2af6406..909f2af6406 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-playback-temporary.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-requestmediakeysystemaccess.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-requestmediakeysystemaccess.https.html
index f8402c99a56..f8402c99a56 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-requestmediakeysystemaccess.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-requestmediakeysystemaccess.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.https.html
index 61da9d86743..61da9d86743 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-reset-src-after-setmediakeys.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.https.html
index 697cf207cfb..697cf207cfb 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-again-after-playback.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.https.html
index d695445ef1f..d695445ef1f 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-again-after-resetting-src.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-at-same-time.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-at-same-time.https.html
index 91e6b9ec3f3..91e6b9ec3f3 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-at-same-time.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-at-same-time.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html
index 064d7ed05c1..064d7ed05c1 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html
index 9e383afc3cc..9e383afc3cc 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.https.html
index cf73b8085c6..cf73b8085c6 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys-to-multiple-video-elements.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys.https.html
index 14a6a73e07a..14a6a73e07a 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-setmediakeys.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-syntax-mediakeys.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-syntax-mediakeys.https.html
index 6b4a08a9171..6b4a08a9171 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-syntax-mediakeys.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-syntax-mediakeys.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-syntax-mediakeysession.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-syntax-mediakeysession.https.html
index 2748c31a57f..2748c31a57f 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-syntax-mediakeysession.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-syntax-mediakeysession.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.https.html
index 22e72ccc82d..22e72ccc82d 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-syntax-mediakeysystemaccess.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-unique-origin.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-unique-origin.https.html
index 2871862dd40..2871862dd40 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-unique-origin.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-unique-origin.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-update-disallowed-input.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-update-disallowed-input.https.html
index e5061a76542..e5061a76542 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-update-disallowed-input.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-update-disallowed-input.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-waiting-for-a-key.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-waiting-for-a-key.https.html
index 2876a54a479..2876a54a479 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-waiting-for-a-key.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-mp4-waiting-for-a-key.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-not-callable-after-createsession.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-not-callable-after-createsession.https.html
index 22e8b38615c..22e8b38615c 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-not-callable-after-createsession.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-not-callable-after-createsession.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/clearkey-update-non-ascii-input.html b/tests/wpt/web-platform-tests/encrypted-media/clearkey-update-non-ascii-input.https.html
index cc134729140..cc134729140 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/clearkey-update-non-ascii-input.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/clearkey-update-non-ascii-input.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-check-initdata-type.html b/tests/wpt/web-platform-tests/encrypted-media/drm-check-initdata-type.https.html
index 6b3324027b8..6b3324027b8 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-check-initdata-type.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-check-initdata-type.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-events-session-closed-event.html b/tests/wpt/web-platform-tests/encrypted-media/drm-events-session-closed-event.https.html
index 425d17646ca..425d17646ca 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-events-session-closed-event.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-events-session-closed-event.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-events.html b/tests/wpt/web-platform-tests/encrypted-media/drm-events.https.html
index ece798ac87c..ece798ac87c 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-events.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-events.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-expiration.html b/tests/wpt/web-platform-tests/encrypted-media/drm-expiration.https.html
index d907090efe0..d907090efe0 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-expiration.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-expiration.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-generate-request-disallowed-input.html b/tests/wpt/web-platform-tests/encrypted-media/drm-generate-request-disallowed-input.https.html
index 70c46edc7cc..70c46edc7cc 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-generate-request-disallowed-input.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-generate-request-disallowed-input.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-invalid-license.html b/tests/wpt/web-platform-tests/encrypted-media/drm-invalid-license.https.html
index 9584f499ce2..9584f499ce2 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-invalid-license.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-invalid-license.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-keystatuses-multiple-sessions.html b/tests/wpt/web-platform-tests/encrypted-media/drm-keystatuses-multiple-sessions.https.html
index cd14fe38054..cd14fe38054 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-keystatuses-multiple-sessions.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-keystatuses-multiple-sessions.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-keystatuses.html b/tests/wpt/web-platform-tests/encrypted-media/drm-keystatuses.https.html
index 0d98f7411f2..0d98f7411f2 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-keystatuses.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-keystatuses.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-onencrypted.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-onencrypted.https.html
index 9e4aff330d4..9e4aff330d4 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-onencrypted.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-onencrypted.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-destroy-persistent-license.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-destroy-persistent-license.https.html
index b8a1bfd41e1..b8a1bfd41e1 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-destroy-persistent-license.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-destroy-persistent-license.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-persistent-license-events.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-persistent-license-events.https.html
index 4b5956c4086..4b5956c4086 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-persistent-license-events.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-persistent-license-events.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-persistent-license.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-persistent-license.https.html
index a119d3826b0..a119d3826b0 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-persistent-license.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-persistent-license.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-persistent-usage-record-events.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-persistent-usage-record-events.https.html
index 29c44f89591..29c44f89591 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-persistent-usage-record-events.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-persistent-usage-record-events.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-persistent-usage-record.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-persistent-usage-record.https.html
index 1a9f8fb6fad..1a9f8fb6fad 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-persistent-usage-record.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-persistent-usage-record.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.https.html
index d70dc9811f0..d70dc9811f0 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-retrieve-destroy-persistent-license.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-retrieve-persistent-license.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-retrieve-persistent-license.https.html
index 416093c1491..416093c1491 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-retrieve-persistent-license.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-retrieve-persistent-license.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.https.html
index 55736e8c447..55736e8c447 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-retrieve-persistent-usage-record.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-clear-encrypted.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-clear-encrypted.https.html
index e929251978c..e929251978c 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-clear-encrypted.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-clear-encrypted.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.https.html
index 491e32a6fe8..491e32a6fe8 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-encrypted-clear-sources.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-encrypted-clear.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-encrypted-clear.https.html
index 10450f0a6ad..10450f0a6ad 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-encrypted-clear.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-encrypted-clear.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-events.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-events.https.html
index 9846eeeecdc..9846eeeecdc 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-events.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-events.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-expired.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-expired.https.html
index a87687fbaca..a87687fbaca 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-expired.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-expired.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.https.html
index 42d563a5de3..42d563a5de3 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-multikey-sequential-readyState.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-multikey-sequential.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-multikey-sequential.https.html
index 0b23721b6fa..0b23721b6fa 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-multikey-sequential.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-multikey-sequential.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-multikey.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-multikey.https.html
index ba5a586abfc..ba5a586abfc 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-multikey.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-multikey.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-multisession.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-multisession.https.html
index ebb0e66bc34..ebb0e66bc34 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-multisession.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-multisession.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.https.html
index fab98edbbda..fab98edbbda 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-src.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.https.html
index 63de51be68f..63de51be68f 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-after-update.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.https.html
index 59ed1e498de..59ed1e498de 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-immediately.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.https.html
index 45dc70b39fc..45dc70b39fc 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-setMediaKeys-onencrypted.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-two-videos.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-two-videos.https.html
index cf062125f0d..cf062125f0d 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-two-videos.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-two-videos.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-waitingforkey.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-waitingforkey.https.html
index c9b78e615f1..c9b78e615f1 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-waitingforkey.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary-waitingforkey.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary.https.html
index f28a6fe2f0f..f28a6fe2f0f 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-playback-temporary.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-requestmediakeysystemaccess.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-requestmediakeysystemaccess.https.html
index b18a36f0e47..b18a36f0e47 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-requestmediakeysystemaccess.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-requestmediakeysystemaccess.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-reset-src-after-setmediakeys.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-reset-src-after-setmediakeys.https.html
index b91211df444..b91211df444 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-reset-src-after-setmediakeys.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-reset-src-after-setmediakeys.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-again-after-playback.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-again-after-playback.https.html
index 71a1f70afcb..71a1f70afcb 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-again-after-playback.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-again-after-playback.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.https.html
index 749962c62d5..749962c62d5 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-again-after-resetting-src.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-at-same-time.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-at-same-time.https.html
index 135c9893bf7..135c9893bf7 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-at-same-time.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-at-same-time.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html
index b7f2fec65f0..b7f2fec65f0 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-different-mediakeys.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html
index 5cbbe52da9a..5cbbe52da9a 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-multiple-times-with-the-same-mediakeys.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.https.html
index dddbe3059c2..dddbe3059c2 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys-to-multiple-video-elements.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys.https.html
index 447ca60f745..447ca60f745 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-setmediakeys.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-syntax-mediakeys.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-syntax-mediakeys.https.html
index f6d03926132..f6d03926132 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-syntax-mediakeys.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-syntax-mediakeys.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-syntax-mediakeysession.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-syntax-mediakeysession.https.html
index 0c737df9eff..0c737df9eff 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-syntax-mediakeysession.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-syntax-mediakeysession.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-syntax-mediakeysystemaccess.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-syntax-mediakeysystemaccess.https.html
index d54e1943765..d54e1943765 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-syntax-mediakeysystemaccess.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-syntax-mediakeysystemaccess.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-unique-origin.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-unique-origin.https.html
index a344ae5c070..a344ae5c070 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-unique-origin.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-unique-origin.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-waiting-for-a-key.html b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-waiting-for-a-key.https.html
index 772806ae87a..772806ae87a 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-waiting-for-a-key.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-mp4-waiting-for-a-key.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-not-callable-after-createsession.html b/tests/wpt/web-platform-tests/encrypted-media/drm-not-callable-after-createsession.https.html
index 2fcdc839f22..2fcdc839f22 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-not-callable-after-createsession.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-not-callable-after-createsession.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/drm-temporary-license-type.html b/tests/wpt/web-platform-tests/encrypted-media/drm-temporary-license-type.https.html
index dd114659003..dd114659003 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/drm-temporary-license-type.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/drm-temporary-license-type.https.html
diff --git a/tests/wpt/web-platform-tests/encrypted-media/idlharness.html b/tests/wpt/web-platform-tests/encrypted-media/idlharness.html
deleted file mode 100644
index e65ad5e30ba..00000000000
--- a/tests/wpt/web-platform-tests/encrypted-media/idlharness.html
+++ /dev/null
@@ -1,51 +0,0 @@
-<!doctype html>
-<html>
- <head>
- <meta charset=utf-8>
- <title>Encrypted Media Extentions IDL test</title>
- <link rel="help" href="https://w3c.github.io/encrypted-media/">
-
- <script src=/resources/testharness.js></script>
- <script src=/resources/testharnessreport.js></script>
- <script src=/resources/WebIDLParser.js></script>
- <script src=/resources/idlharness.js></script>
- <script src=/encrypted-media/util/fetch.js></script>
- </head>
- <body>
- <h1 class="instructions">Description</h1>
- <p class="instructions">
- This test verifies that implementations of the Encrypted Media Extensions API match its WebIDL definition.
- </p>
-
- <div id='log'></div>
-
- <script>
- setup(function() {
-
- fetch( 'EncryptedMediaExtensions.idl')
- .then( function( response ) {
- if ( !response.ok ) throw new Error( 'IDL fetch failed' );
- return response.text();
- } )
- .then( function( idls ) {
-
- var idl_array = new IdlArray();
- idl_array.add_untested_idls("[PrimaryGlobal] interface Window {};");
- idl_array.add_untested_idls("interface Navigator {};");
- idl_array.add_untested_idls("interface ArrayBuffer {};");
- idl_array.add_untested_idls("interface HTMLMediaElement {};");
- idl_array.add_untested_idls("interface Event {};");
- idl_array.add_untested_idls("interface EventTarget {};");
-
- idl_array.add_idls(idls);
-
- idl_array.test();
-
- done();
-
- } );
-
- }, {explicit_done: true});
- </script>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/encrypted-media/idlharness.https.html b/tests/wpt/web-platform-tests/encrypted-media/idlharness.https.html
new file mode 100644
index 00000000000..e7e035e4576
--- /dev/null
+++ b/tests/wpt/web-platform-tests/encrypted-media/idlharness.https.html
@@ -0,0 +1,49 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Encrypted Media Extentions IDL test</title>
+ <link rel="help" href="https://w3c.github.io/encrypted-media/">
+
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+ <script src=/encrypted-media/util/fetch.js></script>
+ </head>
+ <body>
+ <h1 class="instructions">Description</h1>
+ <p class="instructions">
+ This test verifies that implementations of the Encrypted Media Extensions API match its WebIDL definition.
+ </p>
+
+ <div id='log'></div>
+
+ <script>
+ setup(function() {
+
+ fetch( 'EncryptedMediaExtensions.idl')
+ .then( function( response ) {
+ if ( !response.ok ) throw new Error( 'IDL fetch failed' );
+ return response.text();
+ } )
+ .then( function( idls ) {
+
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls("interface Navigator {};");
+ idl_array.add_untested_idls("interface HTMLMediaElement {};");
+ idl_array.add_untested_idls("interface Event {};");
+ idl_array.add_untested_idls("interface EventTarget {};");
+
+ idl_array.add_idls(idls);
+
+ idl_array.test();
+
+ done();
+
+ } );
+
+ }, {explicit_done: true});
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/encrypted-media/resources/clearkey-retrieve-destroy-persistent-license.html b/tests/wpt/web-platform-tests/encrypted-media/resources/clearkey-retrieve-destroy-persistent-license.html
index b1bec547e99..3178c860150 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/resources/clearkey-retrieve-destroy-persistent-license.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/resources/clearkey-retrieve-destroy-persistent-license.html
@@ -40,7 +40,7 @@
config.messagehandler = (new MessageHandler( 'org.w3.clearkey')).messagehandler;
function onComplete() {
- window.opener.postMessage(assertions, '*');
+ window.opener.postMessage({ testResult: assertions }, '*');
}
function onFailure(error) {
diff --git a/tests/wpt/web-platform-tests/encrypted-media/resources/clearkey-retrieve-persistent-license.html b/tests/wpt/web-platform-tests/encrypted-media/resources/clearkey-retrieve-persistent-license.html
index 78ca4e1bb3a..0562322203c 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/resources/clearkey-retrieve-persistent-license.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/resources/clearkey-retrieve-persistent-license.html
@@ -35,7 +35,7 @@
config.video = document.getElementById('videoelement');
function onComplete() {
- window.opener.postMessage(assertions, '*');
+ window.opener.postMessage({ testResult: assertions }, '*');
}
function onFailure(error) {
@@ -54,9 +54,10 @@
.then(function(access) {
return access.createMediaKeys();
}).then(function(mediaKeys) {
- config.video.setMediaKeys(mediaKeys);
+ return config.video.setMediaKeys(mediaKeys);
+ }).then(function() {
config.video.addEventListener('timeupdate', onTimeupdate, true);
- _mediaKeySession = mediaKeys.createSession( 'persistent-license' );
+ _mediaKeySession = config.video.mediaKeys.createSession( 'persistent-license' );
_mediaKeySession.closed.then(onComplete);
return _mediaKeySession.load(event.data.sessionId);
}).then(function( success ) {
diff --git a/tests/wpt/web-platform-tests/encrypted-media/resources/drm-retrieve-destroy-persistent-license.html b/tests/wpt/web-platform-tests/encrypted-media/resources/drm-retrieve-destroy-persistent-license.html
index 39798fe43ef..0803eb14960 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/resources/drm-retrieve-destroy-persistent-license.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/resources/drm-retrieve-destroy-persistent-license.html
@@ -40,7 +40,7 @@
config.messagehandler = (new MessageHandler(config.keysystem, config.content, 'persistent-license')).messagehandler;
function onComplete() {
- window.opener.postMessage(assertions, '*');
+ window.opener.postMessage({ testResult: assertions }, '*');
}
function onFailure(error) {
diff --git a/tests/wpt/web-platform-tests/encrypted-media/resources/drm-retrieve-persistent-license.html b/tests/wpt/web-platform-tests/encrypted-media/resources/drm-retrieve-persistent-license.html
index 3b7da8e9570..b6a0ae2a6cf 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/resources/drm-retrieve-persistent-license.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/resources/drm-retrieve-persistent-license.html
@@ -33,7 +33,7 @@
config.video = document.getElementById('videoelement');
function onComplete() {
- window.opener.postMessage(assertions, '*');
+ window.opener.postMessage({ testResult: assertions }, '*');
}
function onFailure(error) {
@@ -58,9 +58,10 @@
.then(function(access) {
return access.createMediaKeys();
}).then(function(mediaKeys) {
- config.video.setMediaKeys(mediaKeys);
+ return config.video.setMediaKeys(mediaKeys);
+ }).then(function() {
config.video.addEventListener('timeupdate', onTimeupdate);
- _mediaKeySession = mediaKeys.createSession( 'persistent-license' );
+ _mediaKeySession = config.video.mediaKeys.createSession( 'persistent-license' );
return _mediaKeySession.load(event.data.sessionId);
}).then(function( success ) {
if ( !success ) throw new DOMException( 'Could not load session' );
diff --git a/tests/wpt/web-platform-tests/encrypted-media/resources/drm-retrieve-persistent-usage-record.html b/tests/wpt/web-platform-tests/encrypted-media/resources/drm-retrieve-persistent-usage-record.html
index 935f777488a..a98c438ef5c 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/resources/drm-retrieve-persistent-usage-record.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/resources/drm-retrieve-persistent-usage-record.html
@@ -33,7 +33,7 @@
function onFailure(error) {
assertions.push( { actual: false, expected: true, message: error } );
- window.opener.postMessage(assertions, '*');
+ window.opener.postMessage({ testResult: assertions }, '*');
}
function onMessage( event )
@@ -56,13 +56,13 @@
_mediaKeySession = _mediaKeys.createSession( 'persistent-usage-record' );
_mediaKeySession.addEventListener( 'message', onMessage );
_mediaKeySession.closed.then( function() {
- window.opener.postMessage(assertions, '*');
+ window.opener.postMessage({ testResult: assertions }, '*');
});
return _mediaKeySession.load( event.data.sessionId );
}).then(function( success ) {
if ( !success ) {
assertions.push( { actual: success, expected: true, message: "Error loading session" } );
- window.opener.postMessage(assertions, '*');
+ window.opener.postMessage({ testResult: assertions }, '*');
}
}).catch( onFailure );
});
diff --git a/tests/wpt/web-platform-tests/encrypted-media/resources/retrieve-persistent-usage-record.html b/tests/wpt/web-platform-tests/encrypted-media/resources/retrieve-persistent-usage-record.html
index 339e3c3aed5..3a4262b179c 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/resources/retrieve-persistent-usage-record.html
+++ b/tests/wpt/web-platform-tests/encrypted-media/resources/retrieve-persistent-usage-record.html
@@ -55,7 +55,7 @@
assertions.push( { actual: false, expected: true, message: error } );
- window.opener.postMessage(assertions, '*');
+ window.opener.postMessage({ testResult: assertions }, '*');
});
});
}
@@ -71,7 +71,7 @@
mediaKeySession.addEventListener( 'message', onMessage );
mediaKeySession.closed.then( function() {
- window.opener.postMessage(assertions, '*');
+ window.opener.postMessage({ testResult: assertions }, '*');
});
@@ -81,7 +81,7 @@
assertions.push( { actual: false, expected: true, message: error.toString() } );
- window.opener.postMessage(assertions, '*');
+ window.opener.postMessage({ testResult: assertions }, '*');
});
diff --git a/tests/wpt/web-platform-tests/encrypted-media/scripts/playback-retrieve-persistent-license.js b/tests/wpt/web-platform-tests/encrypted-media/scripts/playback-retrieve-persistent-license.js
index e8d9d02be30..83cba34028e 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/scripts/playback-retrieve-persistent-license.js
+++ b/tests/wpt/web-platform-tests/encrypted-media/scripts/playback-retrieve-persistent-license.js
@@ -74,12 +74,14 @@ function runTest(config,qualifier) {
// Lisen for an event from the new window containing its test assertions
window.addEventListener('message', test.step_func(function(messageEvent) {
- messageEvent.data.forEach(test.step_func(function(assertion) {
- assert_equals(assertion.actual, assertion.expected, assertion.message);
- }));
-
- win.close();
- test.done();
+ if (messageEvent.data.testResult) {
+ messageEvent.data.testResult.forEach(test.step_func(function(assertion) {
+ assert_equals(assertion.actual, assertion.expected, assertion.message);
+ }));
+
+ win.close();
+ test.done();
+ }
}));
// Delete things which can't be cloned and posted over to the new window
@@ -96,7 +98,8 @@ function runTest(config,qualifier) {
return access.createMediaKeys();
}).then(function(mediaKeys) {
_mediaKeys = mediaKeys;
- _video.setMediaKeys( mediaKeys );
+ return _video.setMediaKeys( mediaKeys );
+ }).then(function() {
_mediaKeySession = _mediaKeys.createSession('persistent-license');
waitForEventAndRunStep('encrypted', _video, onEncrypted, test);
waitForEventAndRunStep('playing', _video, onPlaying, test);
diff --git a/tests/wpt/web-platform-tests/encrypted-media/scripts/playback-retrieve-persistent-usage-record.js b/tests/wpt/web-platform-tests/encrypted-media/scripts/playback-retrieve-persistent-usage-record.js
index 9467fd5d867..a04f97d2ca9 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/scripts/playback-retrieve-persistent-usage-record.js
+++ b/tests/wpt/web-platform-tests/encrypted-media/scripts/playback-retrieve-persistent-usage-record.js
@@ -45,7 +45,7 @@ function runTest(config,qualifier) {
config.messagehandler( event.messageType, event.message ).then(function(response) {
return _mediaKeySession.update(response);
}).then(function() {
- _video.setMediaKeys(_mediaKeys);
+ return _video.setMediaKeys(_mediaKeys);
}).catch(onFailure);
}
@@ -70,13 +70,17 @@ function runTest(config,qualifier) {
_video.setMediaKeys( null );
var win = window.open(config.windowscript);
- window.addEventListener('message', test.step_func(function(event) {
- event.data.forEach(test.step_func(function(assertion) {
- assert_equals(assertion.actual, assertion.expected, assertion.message);
- }));
+ assert_not_equals(win, null, "Popup windows not allowed?");
- win.close();
- test.done();
+ window.addEventListener('message', test.step_func(function(event) {
+ if (event.data.testResult) {
+ event.data.testResult.forEach(test.step_func(function(assertion) {
+ assert_equals(assertion.actual, assertion.expected, assertion.message);
+ }));
+
+ win.close();
+ test.done();
+ }
}));
delete config.video;
diff --git a/tests/wpt/web-platform-tests/encrypted-media/scripts/unique-origin.js b/tests/wpt/web-platform-tests/encrypted-media/scripts/unique-origin.js
index ff1122db4de..015ea9d4e92 100644
--- a/tests/wpt/web-platform-tests/encrypted-media/scripts/unique-origin.js
+++ b/tests/wpt/web-platform-tests/encrypted-media/scripts/unique-origin.js
@@ -10,7 +10,7 @@ function runTest(config) {
resolve(iframe);
};
iframe.sandbox = sandbox;
- iframe.src = src;
+ iframe.srcdoc = src;
document.documentElement.appendChild(iframe);
});
}
@@ -25,7 +25,7 @@ function runTest(config) {
}
promise_test(function (test) {
- var script = 'data:text/html,' +
+ var script =
'<script>' +
' window.onmessage = function(e) {' +
' navigator.requestMediaKeySystemAccess("' + config.keysystem + '", [{' +
@@ -53,7 +53,7 @@ function runTest(config) {
return access.createMediaKeys();
}).then(function (mediaKeys) {
// Success, so now create the iframe and try there.
- return load_iframe(script, 'allow-scripts');
+ return load_iframe(script, 'allow-scripts allow-secure-context');
}).then(function (iframe) {
iframe.contentWindow.postMessage({}, '*');
return wait_for_message();
diff --git a/tests/wpt/web-platform-tests/feature-policy/README.md b/tests/wpt/web-platform-tests/feature-policy/README.md
index a5276f0a7f3..48cb95ebf74 100644
--- a/tests/wpt/web-platform-tests/feature-policy/README.md
+++ b/tests/wpt/web-platform-tests/feature-policy/README.md
@@ -28,7 +28,7 @@ HTTP tests are used to test features with header policy.
* Define the header policy in `<feature-name>-<enabled | disabled | enabled-on-self-origin>-by-feature-policy.https.sub.html.headers`. Example:
- Feature-Policy: {"feature-name": ["*"]}
+ Feature-Policy: feature-name *
* In `<feature-name>-<enabled | disabled | enabled-on-self-origin>-by-feature-policy.https.sub.html`:
diff --git a/tests/wpt/web-platform-tests/feature-policy/autoplay-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html b/tests/wpt/web-platform-tests/feature-policy/autoplay-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html
new file mode 100644
index 00000000000..6f11f8995b1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/feature-policy/autoplay-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<body>
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src=/resources/testdriver.js></script>
+ <script src=/resources/testdriver-vendor.js></script>
+ <script src=/common/media.js></script>
+ <script src=/feature-policy/resources/featurepolicy.js></script>
+ <script src=/feature-policy/resources/autoplay.js></script>
+ <script>
+ 'use strict';
+ const relative_path = '/feature-policy/resources/feature-policy-autoplay.html';
+ const base_src = '/feature-policy/resources/redirect-on-load.html#';
+ const same_origin_src = base_src + relative_path;
+ const cross_origin_src = base_src + 'https://{{domains[www]}}:{{ports[https][0]}}' +
+ relative_path;
+ const header = 'Feature-Policy allow="autoplay"';
+
+ async_test(t => {
+ simulateGesture(t, () => {
+ test_feature_availability(
+ 'autoplay', t, same_origin_src,
+ expect_feature_available_default, 'autoplay');
+ });
+ }, header + ' allows same-origin navigation in an iframe.');
+
+ async_test(t => {
+ simulateGesture(t, () => {
+ test_feature_availability(
+ 'autoplay', t, cross_origin_src,
+ expect_feature_unavailable_default, 'autoplay');
+ });
+ }, header + ' disallows cross-origin navigation in an iframe.');
+ </script>
+</body>
diff --git a/tests/wpt/web-platform-tests/feature-policy/autoplay-allowed-by-feature-policy-attribute.https.sub.html b/tests/wpt/web-platform-tests/feature-policy/autoplay-allowed-by-feature-policy-attribute.https.sub.html
new file mode 100644
index 00000000000..59b33d7c4d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/feature-policy/autoplay-allowed-by-feature-policy-attribute.https.sub.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<body>
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src=/resources/testdriver.js></script>
+ <script src=/resources/testdriver-vendor.js></script>
+ <script src=/common/media.js></script>
+ <script src=/feature-policy/resources/featurepolicy.js></script>
+ <script src=/feature-policy/resources/autoplay.js></script>
+ <script>
+ 'use strict';
+ const same_origin_src = '/feature-policy/resources/feature-policy-autoplay.html';
+ const cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+ same_origin_src;
+ const feature_name = 'Feature policy "autoplay"';
+ const header = 'allow="autoplay" attribute';
+
+ async_test(t => {
+ simulateGesture(t, () => {
+ test_feature_availability(
+ 'autoplay', t, same_origin_src,
+ expect_feature_available_default, 'autoplay');
+ });
+ }, feature_name + ' can be enabled in same-origin iframe using ' + header);
+
+ async_test(t => {
+ simulateGesture(t, () => {
+ test_feature_availability(
+ 'autoplay', t, cross_origin_src,
+ expect_feature_available_default, 'autoplay');
+ });
+ }, feature_name + ' can be enabled in cross-origin iframe using ' + header);
+ </script>
+</body>
diff --git a/tests/wpt/web-platform-tests/feature-policy/autoplay-allowed-by-feature-policy.https.sub.html b/tests/wpt/web-platform-tests/feature-policy/autoplay-allowed-by-feature-policy.https.sub.html
new file mode 100644
index 00000000000..63479c0cb6f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/feature-policy/autoplay-allowed-by-feature-policy.https.sub.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<body>
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src=/resources/testdriver.js></script>
+ <script src=/resources/testdriver-vendor.js></script>
+ <script src=/common/media.js></script>
+ <script src=/feature-policy/resources/featurepolicy.js></script>
+ <script src=/feature-policy/resources/autoplay.js></script>
+ <script>
+ 'use strict';
+ const same_origin_src = '/feature-policy/resources/feature-policy-autoplay.html';
+ const cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+ same_origin_src;
+ const header = 'Feature-Policy header: autoplay *';
+
+ async_test(t => {
+ simulateGesture(t, () => {
+ isAutoplayAllowed().then(t.step_func_done((result) => {
+ assert_true(result);
+ }));
+ });
+ }, header + ' allows the top-level document.');
+
+ async_test(t => {
+ simulateGesture(t, () => {
+ test_feature_availability('autoplay', t, same_origin_src,
+ expect_feature_available_default);
+ });
+ }, header + ' allows same-origin iframes.');
+
+ async_test(t => {
+ simulateGesture(t, () => {
+ test_feature_availability('autoplay', t, cross_origin_src,
+ expect_feature_available_default);
+ });
+ }, header + ' allows cross-origin iframes.');
+ </script>
+</body>
diff --git a/tests/wpt/web-platform-tests/feature-policy/autoplay-allowed-by-feature-policy.https.sub.html.headers b/tests/wpt/web-platform-tests/feature-policy/autoplay-allowed-by-feature-policy.https.sub.html.headers
new file mode 100644
index 00000000000..08461fadc28
--- /dev/null
+++ b/tests/wpt/web-platform-tests/feature-policy/autoplay-allowed-by-feature-policy.https.sub.html.headers
@@ -0,0 +1 @@
+Feature-Policy: autoplay *
diff --git a/tests/wpt/web-platform-tests/feature-policy/autoplay-default-feature-policy.https.sub.html b/tests/wpt/web-platform-tests/feature-policy/autoplay-default-feature-policy.https.sub.html
new file mode 100644
index 00000000000..763073e437d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/feature-policy/autoplay-default-feature-policy.https.sub.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<body>
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src=/resources/testdriver.js></script>
+ <script src=/resources/testdriver-vendor.js></script>
+ <script src=/common/media.js></script>
+ <script src=/feature-policy/resources/featurepolicy.js></script>
+ <script src=/feature-policy/resources/autoplay.js></script>
+ <script>
+ 'use strict';
+ const same_origin_src = '/feature-policy/resources/feature-policy-autoplay.html';
+ const cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+ same_origin_src;
+ const header = 'Default "autoplay" feature policy ["self"]';
+
+ async_test(t => {
+ simulateGesture(t, () => {
+ isAutoplayAllowed().then(t.step_func_done((result) => {
+ assert_true(result);
+ }));
+ });
+ }, header + ' allows the top-level document.');
+
+ async_test(t => {
+ simulateGesture(t, () => {
+ test_feature_availability('autoplay', t, same_origin_src,
+ expect_feature_available_default);
+ });
+ }, header + ' allows same-origin iframes.');
+
+ async_test(t => {
+ simulateGesture(t, () => {
+ test_feature_availability('autoplay', t, cross_origin_src,
+ expect_feature_unavailable_default,);
+ });
+ }, header + ' disallows cross-origin iframes.');
+ </script>
+</body>
diff --git a/tests/wpt/web-platform-tests/feature-policy/autoplay-disabled-by-feature-policy.https.sub.html b/tests/wpt/web-platform-tests/feature-policy/autoplay-disabled-by-feature-policy.https.sub.html
new file mode 100644
index 00000000000..3dd3afbf771
--- /dev/null
+++ b/tests/wpt/web-platform-tests/feature-policy/autoplay-disabled-by-feature-policy.https.sub.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<body>
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src=/resources/testdriver.js></script>
+ <script src=/resources/testdriver-vendor.js></script>
+ <script src=/common/media.js></script>
+ <script src=/feature-policy/resources/featurepolicy.js></script>
+ <script src=/feature-policy/resources/autoplay.js></script>
+ <script>
+ 'use strict';
+ const same_origin_src = '/feature-policy/resources/feature-policy-autoplay.html';
+ const cross_origin_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+ same_origin_src;
+ const header = 'Feature-Policy header: autoplay "none"';
+
+ async_test(t => {
+ simulateGesture(t, () => {
+ isAutoplayAllowed().then(t.step_func_done((result) => {
+ assert_true(result);
+ }));
+ });
+ }, header + ' has no effect on the top level document.');
+
+ async_test(t => {
+ simulateGesture(t, () => {
+ test_feature_availability('autoplay', t, same_origin_src,
+ expect_feature_unavailable_default);
+ });
+ }, header + ' disallows same-origin iframes.');
+
+ async_test(t => {
+ simulateGesture(t, () => {
+ test_feature_availability('autoplay', t, cross_origin_src,
+ expect_feature_unavailable_default,);
+ });
+ }, header + ' disallows cross-origin iframes.');
+ </script>
+</body>
diff --git a/tests/wpt/web-platform-tests/feature-policy/autoplay-disabled-by-feature-policy.https.sub.html.headers b/tests/wpt/web-platform-tests/feature-policy/autoplay-disabled-by-feature-policy.https.sub.html.headers
new file mode 100644
index 00000000000..69ce436270a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/feature-policy/autoplay-disabled-by-feature-policy.https.sub.html.headers
@@ -0,0 +1 @@
+Feature-Policy: autoplay 'none'
diff --git a/tests/wpt/web-platform-tests/feature-policy/payment-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html b/tests/wpt/web-platform-tests/feature-policy/payment-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html
index 9a792173f4a..daa2aa182da 100644
--- a/tests/wpt/web-platform-tests/feature-policy/payment-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html
+++ b/tests/wpt/web-platform-tests/feature-policy/payment-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html
@@ -16,24 +16,24 @@
test_feature_availability(
'PaymentRequest()', t, same_origin_src,
expect_feature_available_default, 'payment');
- }, header + ' allows same-origin relocation.');
+ }, header + ' allows same-origin navigation in an iframe.');
async_test(t => {
test_feature_availability(
'PaymentRequest()', t, cross_origin_src,
expect_feature_unavailable_default, 'payment');
- }, header + ' disallows cross-origin relocation.');
+ }, header + ' disallows cross-origin navigation in an iframe.');
async_test(t => {
test_feature_availability(
'PaymentRequest()', t, same_origin_src,
expect_feature_available_default, 'payment', 'allowpaymentrequest');
- }, header + ' allowpaymentrequest=true allows same-origin relocation.');
+ }, header + ' allowpaymentrequest=true allows same-origin navigation in an iframe.');
async_test(t => {
test_feature_availability(
'PaymentRequest()', t, cross_origin_src,
expect_feature_unavailable_default, 'payment', 'allowpaymentrequest');
- }, header + ' allowpaymentrequest=true disallows cross-origin relocation.');
+ }, header + ' allowpaymentrequest=true disallows cross-origin navigation in an iframe.');
</script>
</body>
diff --git a/tests/wpt/web-platform-tests/feature-policy/resources/autoplay.js b/tests/wpt/web-platform-tests/feature-policy/resources/autoplay.js
new file mode 100644
index 00000000000..56780cf6dc0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/feature-policy/resources/autoplay.js
@@ -0,0 +1,28 @@
+
+
+function simulateGesture(t, callback) {
+ // Get or create the target element.
+ let target = document.getElementById('target');
+ if (!target) {
+ target = document.createElement('button');
+ target.setAttribute('id', 'target');
+ document.body.appendChild(target);
+ }
+
+ // Simulate a gesture in the top frame to remove any gesture based autoplay
+ // restrictions.
+ test_driver.click(target).then(callback, t.unreached_func('click failed'));
+}
+
+function isAutoplayAllowed() {
+ return new Promise((resolve, reject) => {
+ const video = document.createElement('video');
+ video.src = getVideoURI('/media/A4');
+ video.play().then(() => resolve(true), (e) => {
+ if (e.name == 'NotAllowedError')
+ resolve(false);
+ else
+ resolve(true);
+ });
+ });
+}
diff --git a/tests/wpt/web-platform-tests/feature-policy/resources/feature-policy-autoplay.html b/tests/wpt/web-platform-tests/feature-policy/resources/feature-policy-autoplay.html
new file mode 100644
index 00000000000..79f8eefb9d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/feature-policy/resources/feature-policy-autoplay.html
@@ -0,0 +1,11 @@
+<script src="/common/media.js"></script>
+<script src=/feature-policy/resources/autoplay.js></script>
+<script>
+'use strict';
+
+window.addEventListener('load', () => {
+ isAutoplayAllowed().then((result) => {
+ window.parent.postMessage({ enabled: result }, '*');
+ });
+}, { once: true });
+</script>
diff --git a/tests/wpt/web-platform-tests/feature-policy/resources/feature-policy-generic-sensor.html b/tests/wpt/web-platform-tests/feature-policy/resources/feature-policy-generic-sensor.html
new file mode 100644
index 00000000000..59652e2e7ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/feature-policy/resources/feature-policy-generic-sensor.html
@@ -0,0 +1,11 @@
+<script>
+"use strict";
+
+try {
+ const sensorName = location.hash.substring(1);
+ const sensor = new window[sensorName]();
+ window.parent.postMessage({ enabled: true }, "*");
+} catch (e) {
+ window.parent.postMessage({ enabled: false }, "*");
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/fetch/api/cors/cors-expose-star.js b/tests/wpt/web-platform-tests/fetch/api/cors/cors-expose-star.js
index e37ddb4c3f2..edf4d424179 100644
--- a/tests/wpt/web-platform-tests/fetch/api/cors/cors-expose-star.js
+++ b/tests/wpt/web-platform-tests/fetch/api/cors/cors-expose-star.js
@@ -31,7 +31,7 @@ promise_test(() => {
}, "* for credentialed fetches only matches literally")
promise_test(() => {
- const headers = "header(Access-Control-Allow-Origin,*)|header(Access-Control-Expose-Headers,set-cookie)"
+ const headers = "header(Access-Control-Allow-Origin,*)|header(Access-Control-Expose-Headers,set-cookie\\,*)"
return fetch(url + sharedHeaders + headers).then(resp => {
assert_equals(resp.status, 200)
assert_equals(resp.type , "cors")
diff --git a/tests/wpt/web-platform-tests/fetch/api/redirect/redirect-method.js b/tests/wpt/web-platform-tests/fetch/api/redirect/redirect-method.js
index 13433a1bb39..0a7f2df2c2b 100644
--- a/tests/wpt/web-platform-tests/fetch/api/redirect/redirect-method.js
+++ b/tests/wpt/web-platform-tests/fetch/api/redirect/redirect-method.js
@@ -3,14 +3,22 @@ if (this.document === undefined) {
importScripts("../resources/utils.js");
}
-function redirectMethod(desc, redirectUrl, redirectLocation, redirectStatus, method, expectedMethod) {
+// Creates a promise_test that fetches a URL that returns a redirect response.
+//
+// |opts| has additional options:
+// |opts.body|: the request body as a string or blob (default is empty body)
+// |opts.expectedBodyAsString|: the expected response body as a string. The
+// server is expected to echo the request body. The default is the empty string
+// if the request after redirection isn't POST; otherwise it's |opts.body|.
+function redirectMethod(desc, redirectUrl, redirectLocation, redirectStatus, method, expectedMethod, opts) {
var url = redirectUrl;
var urlParameters = "?redirect_status=" + redirectStatus;
urlParameters += "&location=" + encodeURIComponent(redirectLocation);
var requestInit = {"method": method, "redirect": "follow"};
- if (method != "GET" && method != "HEAD")
- requestInit.body = "this is my body";
+ opts = opts || {};
+ if (opts.body)
+ requestInit.body = opts.body;
promise_test(function(test) {
return fetch(url + urlParameters, requestInit).then(function(resp) {
@@ -19,7 +27,10 @@ function redirectMethod(desc, redirectUrl, redirectLocation, redirectStatus, met
assert_equals(resp.headers.get("x-request-method"), expectedMethod, "Request method after redirection is " + expectedMethod);
assert_true(resp.redirected);
return resp.text().then(function(text) {
- assert_equals(text, expectedMethod == "POST" ? requestInit.body : "");
+ let expectedBody = "";
+ if (expectedMethod == "POST")
+ expectedBody = opts.expectedBodyAsString || requestInit.body;
+ assert_equals(text, expectedBody, "request body");
});
});
}, desc);
@@ -36,20 +47,25 @@ promise_test(function(test) {
var redirUrl = RESOURCES_DIR + "redirect.py";
var locationUrl = "method.py";
+const stringBody = "this is my body";
+const blobBody = new Blob(["it's me the blob!", " ", "and more blob!"]);
+const blobBodyAsString = "it's me the blob! and more blob!";
+
redirectMethod("Redirect 301 with GET", redirUrl, locationUrl, 301, "GET", "GET");
-redirectMethod("Redirect 301 with POST", redirUrl, locationUrl, 301, "POST", "GET");
+redirectMethod("Redirect 301 with POST", redirUrl, locationUrl, 301, "POST", "GET", { body: stringBody });
redirectMethod("Redirect 301 with HEAD", redirUrl, locationUrl, 301, "HEAD", "HEAD");
redirectMethod("Redirect 302 with GET", redirUrl, locationUrl, 302, "GET", "GET");
-redirectMethod("Redirect 302 with POST", redirUrl, locationUrl, 302, "POST", "GET");
+redirectMethod("Redirect 302 with POST", redirUrl, locationUrl, 302, "POST", "GET", { body: stringBody });
redirectMethod("Redirect 302 with HEAD", redirUrl, locationUrl, 302, "HEAD", "HEAD");
redirectMethod("Redirect 303 with GET", redirUrl, locationUrl, 303, "GET", "GET");
-redirectMethod("Redirect 303 with POST", redirUrl, locationUrl, 303, "POST", "GET");
+redirectMethod("Redirect 303 with POST", redirUrl, locationUrl, 303, "POST", "GET", { body: stringBody });
redirectMethod("Redirect 303 with HEAD", redirUrl, locationUrl, 303, "HEAD", "HEAD");
redirectMethod("Redirect 307 with GET", redirUrl, locationUrl, 307, "GET", "GET");
-redirectMethod("Redirect 307 with POST", redirUrl, locationUrl, 307, "POST", "POST");
+redirectMethod("Redirect 307 with POST (string body)", redirUrl, locationUrl, 307, "POST", "POST", { body: stringBody });
+redirectMethod("Redirect 307 with POST (blob body)", redirUrl, locationUrl, 307, "POST", "POST", { body: blobBody, expectedBodyAsString: blobBodyAsString });
redirectMethod("Redirect 307 with HEAD", redirUrl, locationUrl, 307, "HEAD", "HEAD");
done();
diff --git a/tests/wpt/web-platform-tests/fetch/api/request/destination/fetch-destination.https.html b/tests/wpt/web-platform-tests/fetch/api/request/destination/fetch-destination.https.html
new file mode 100644
index 00000000000..b504bb9c238
--- /dev/null
+++ b/tests/wpt/web-platform-tests/fetch/api/request/destination/fetch-destination.https.html
@@ -0,0 +1,134 @@
+<!DOCTYPE html>
+<title>Service Worker: the body of FetchEvent using XMLHttpRequest</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/common/media.js"></script>
+<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
+<script>
+let frame;
+
+// Set up the service worker and the frame.
+promise_test(t => {
+ const kScope = 'resources/empty.https.html';
+ const kScript = 'resources/fetch-destination-worker.js';
+ return service_worker_unregister_and_register(t, kScript, kScope)
+ .then(registration => {
+ add_completion_callback(() => {
+ registration.unregister();
+ });
+
+ return wait_for_state(t, registration.installing, 'activated');
+ })
+ .then(() => {
+ return with_iframe(kScope);
+ })
+ .then(f => {
+ frame = f;
+ add_completion_callback(() => { f.remove(); });
+ });
+ }, 'Initialize global state');
+
+// Actual tests
+
+// HTMLImageElement - image destination
+promise_test(async t => {
+ await new Promise((resolve, reject) => {
+ var node = frame.contentWindow.document.createElement("img");
+ node.onload = resolve;
+ node.onerror = reject;
+ node.src = "dummy.png?dest=image";
+ }).catch(() => {
+ assert_unreached("Fetch errored.");
+ });
+}, 'HTMLImageElement fetches with an "image" Request.destination');
+
+// fetch() - empty string destination
+promise_test(async t => {
+ let response = await frame.contentWindow.fetch("dummy?dest=");
+ assert_true(response.ok);
+}, 'fetch() fetches with an empty string Request.destination');
+
+// HTMLAudioElement - audio destination
+promise_test(async t => {
+ await new Promise((resolve, reject) => {
+ var audioURL = getAudioURI("dummy_audio");
+ var node = frame.contentWindow.document.createElement("audio");
+ node.onloadeddata = resolve;
+ node.onerror = reject;
+ node.src = audioURL + "?dest=audio";
+ }).catch(() => {
+ assert_unreached("Fetch errored.");
+ });
+}, 'HTMLAudioElement fetches with an "audio" Request.destination');
+
+// HTMLVideoElement - video destination
+promise_test(async t => {
+ await new Promise((resolve, reject) => {
+ var videoURL = getVideoURI("dummy_video");
+ var node = frame.contentWindow.document.createElement("video");
+ node.onloadeddata = resolve;
+ node.onerror = reject;
+ node.src = videoURL + "?dest=video";
+ }).catch(() => {
+ assert_unreached("Fetch errored.");
+ });
+}, 'HTMLVideoElement fetches with a "video" Request.destination');
+
+// HTMLScriptElement - script destination
+promise_test(async t => {
+ await new Promise((resolve, reject) => {
+ var node = frame.contentWindow.document.createElement("script");
+ node.onload = resolve;
+ node.onerror = reject;
+ node.src = "dummy?dest=script";
+ frame.contentWindow.document.body.appendChild(node);
+ }).catch(() => {
+ assert_unreached("Fetch errored.");
+ });
+}, 'HTMLScriptElement fetches with a "script" Request.destination');
+
+// HTMLLinkElement with rel=stylesheet - script destination
+promise_test(async t => {
+ await new Promise((resolve, reject) => {
+ var node = frame.contentWindow.document.createElement("link");
+ node.rel = "stylesheet";
+ node.onload = resolve;
+ node.onerror = reject;
+ node.href = "dummy?dest=style";
+ frame.contentWindow.document.body.appendChild(node);
+ }).catch(() => {
+ assert_unreached("Fetch errored.");
+ });
+}, 'HTMLLinkElement with rel=stylesheet fetches with a "style" Request.destination');
+
+// HTMLLinkElement with rel=preload and as=fetch - empty string destination
+promise_test(async t => {
+ await new Promise((resolve, reject) => {
+ var node = frame.contentWindow.document.createElement("link");
+ node.rel = "preload";
+ node.as = "fetch";
+ node.onload = resolve;
+ node.onerror = reject;
+ node.href = "dummy?t=2&dest=";
+ frame.contentWindow.document.body.appendChild(node);
+ }).catch(() => {
+ assert_unreached("Fetch errored.");
+ });
+}, 'HTMLLinkElement with rel=preload and as=fetch fetches with an empty string Request.destination');
+
+// HTMLLinkElement with rel=preload and as=style - style destination
+promise_test(async t => {
+ await new Promise((resolve, reject) => {
+ var node = frame.contentWindow.document.createElement("link");
+ node.rel = "preload";
+ node.as = "style";
+ node.onload = resolve;
+ node.onerror = reject;
+ node.href = "dummy?t=2&dest=style";
+ frame.contentWindow.document.body.appendChild(node);
+ }).catch(() => {
+ assert_unreached("Fetch errored.");
+ });
+}, 'HTMLLinkElement with rel=preload and as=style fetches with a "style" Request.destination');
+</script>
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/log/__init__.py b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy
index e69de29bb2d..e69de29bb2d 100644
--- a/tests/wpt/web-platform-tests/tools/py/testing/log/__init__.py
+++ b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy
diff --git a/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy.png b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy.png
new file mode 100644
index 00000000000..01c9666a8de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_audio.mp3 b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_audio.mp3
new file mode 100644
index 00000000000..0091330f1ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_audio.mp3
Binary files differ
diff --git a/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_audio.oga b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_audio.oga
new file mode 100644
index 00000000000..239ad2bd08c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_audio.oga
Binary files differ
diff --git a/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_video.mp4 b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_video.mp4
new file mode 100644
index 00000000000..7022e75c15e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_video.mp4
Binary files differ
diff --git a/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_video.ogv b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_video.ogv
new file mode 100644
index 00000000000..de99616eceb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/dummy_video.ogv
Binary files differ
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/__init__.py b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/empty.https.html
index e69de29bb2d..e69de29bb2d 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/__init__.py
+++ b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/empty.https.html
diff --git a/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/fetch-destination-worker.js b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/fetch-destination-worker.js
new file mode 100644
index 00000000000..f8e8e2669d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/fetch/api/request/destination/resources/fetch-destination-worker.js
@@ -0,0 +1,11 @@
+self.addEventListener('fetch', function(event) {
+ if (event.request.url.includes('dummy')) {
+ let destination = new URL(event.request.url).searchParams.get("dest");
+ if (event.request.destination == destination) {
+ event.respondWith(fetch(event.request));
+ } else {
+ event.respondWith(Response.error());
+ }
+ }
+});
+
diff --git a/tests/wpt/web-platform-tests/fetch/api/request/request-idl.html b/tests/wpt/web-platform-tests/fetch/api/request/request-idl.html
index f78f0ca894a..f7833779ce2 100644
--- a/tests/wpt/web-platform-tests/fetch/api/request/request-idl.html
+++ b/tests/wpt/web-platform-tests/fetch/api/request/request-idl.html
@@ -15,9 +15,7 @@
typedef any JSON;
typedef (Blob or BufferSource or FormData or URLSearchParams or USVString) BodyInit;
- [NoInterfaceObject,
- Exposed=(Window,Worker)]
- interface Body {
+ interface mixin Body {
readonly attribute ReadableStream? body;
readonly attribute boolean bodyUsed;
[NewObject] Promise<ArrayBuffer> arrayBuffer();
@@ -48,7 +46,7 @@
[NewObject] Request clone();
};
- Request implements Body;
+ Request includes Body;
dictionary RequestInit {
ByteString method;
diff --git a/tests/wpt/web-platform-tests/fetch/api/request/request-keepalive-quota.html b/tests/wpt/web-platform-tests/fetch/api/request/request-keepalive-quota.html
index dacc6382667..19596cea2c8 100644
--- a/tests/wpt/web-platform-tests/fetch/api/request/request-keepalive-quota.html
+++ b/tests/wpt/web-platform-tests/fetch/api/request/request-keepalive-quota.html
@@ -12,81 +12,80 @@
</head>
<body>
<script>
- "use strict";
+ 'use strict';
// We want to ensure that our keepalive requests hang slightly before completing so we can validate
// the effects of a rolling quota. To do this we will utilize trickle.py with a 1s delay. This should
// prevent any of the Fetch's from finishing in this window.
- var trickleURL = "../resources/trickle.py?count=1&ms=";
- var standardDelay = 1000;
+ const trickleURL = '../resources/trickle.py?count=1&ms=';
+ const noDelay = 0;
+ const standardDelay = 1000;
+ function wait(ms) {
+ return new Promise(resolve => step_timeout(resolve, ms));
+ }
// We should expect 64KiB of rolling quota for any type of keep-alive request sent.
- var expectedQuota = 65536;
+ const expectedQuota = 65536;
- function CreateKeepAliveRequest(delay, bodySize) {
+ function fetchKeepAliveRequest(delay, bodySize) {
// Create a body of the specified size that's filled with *'s
- var requestBody = "*".repeat(bodySize);
- return new Request(trickleURL+delay, {keepalive: true, body: requestBody, method: "POST"});
+ const body = '*'.repeat(bodySize);
+ return fetch(trickleURL + delay, {keepalive: true, body, method: 'POST'}).then(res => {
+ return res.text();
+ }).then(() => {
+ return wait(1);
+ });
}
// Test 1 Byte
promise_test(function(test) {
- return fetch(CreateKeepAliveRequest(0 /* delay */, 1 /* bodySize */));
- }, "A Keep-Alive fetch() with a small body should succeed.");
+ return fetchKeepAliveRequest(noDelay, 1 /* bodySize */);
+ }, 'A Keep-Alive fetch() with a small body should succeed.');
// Test Quota full limit
promise_test(function(test) {
- return fetch(CreateKeepAliveRequest(0 /* delay */, expectedQuota));
- }, "A Keep-Alive fetch() with a body at the Quota Limit should succeed.");
+ return fetchKeepAliveRequest(noDelay, expectedQuota /* bodySize */);
+ }, 'A Keep-Alive fetch() with a body at the Quota Limit should succeed.');
// Test Quota + 1 Byte
promise_test(function(test) {
- return promise_rejects(test, new TypeError(), fetch(CreateKeepAliveRequest(0 /* delay */, expectedQuota + 1)));
- }, "A Keep-Alive fetch() with a body over the Quota Limit should reject.");
+ return promise_rejects(test, TypeError(), fetchKeepAliveRequest(noDelay, expectedQuota + 1));
+ }, 'A Keep-Alive fetch() with a body over the Quota Limit should reject.');
// Test the Quota becomes available upon promise completion.
promise_test(function (test) {
// Fill our Quota then try to send a second fetch.
- var firstFetch = fetch(CreateKeepAliveRequest(standardDelay, expectedQuota)).then(function(response) {
+ return fetchKeepAliveRequest(standardDelay, expectedQuota).then(() => {
// Now validate that we can send another Keep-Alive fetch for the full size of the quota.
- return fetch(CreateKeepAliveRequest(0 /* delay */, expectedQuota));
+ return fetchKeepAliveRequest(noDelay, expectedQuota);
});
-
- return firstFetch;
- }, "A Keep-Alive fetch() should return it's allocated Quota upon promise resolution.");
+ }, 'A Keep-Alive fetch() should return its allocated Quota upon promise resolution.');
// Ensure only the correct amount of Quota becomes available when a fetch completes.
promise_test(function(test) {
- var lastFetchSucceeded = false;
// Create a fetch that uses all but 1 Byte of the Quota and runs for 2x as long as the other requests.
- var firstFetch = fetch(CreateKeepAliveRequest(standardDelay * 2, expectedQuota - 1)).then(function(response) {
- // This should be our last completing fetch(). We need to validate that the last fetch we sent out actually
- // completed.
- assert_true(lastFetchSucceeded, "Out last fetch after gaining Quota back should have succeeded.");
- });
+ const first = fetchKeepAliveRequest(standardDelay * 2, expectedQuota - 1);
// Now create a single Byte request that will complete quicker.
- fetch(CreateKeepAliveRequest(standardDelay, 1 /* bodySize */)).then(function(response) {
+ const second = fetchKeepAliveRequest(standardDelay, 1 /* bodySize */).then(() => {
// We shouldn't be able to create a 2 Byte request right now as only 1 Byte should have freed up.
- assert_throws(new TypeError(), fetch(CreateKeepAliveRequest(0 /* delay */, 2 /* bodySize */)), "Only 1 Byte of Quota should be available right now.");
-
+ return promise_rejects(test, TypeError(), fetchKeepAliveRequest(noDelay, 2 /* bodySize */));
+ }).then(() => {
// Now validate that we can send another Keep-Alive fetch for just 1 Byte.
- fetch(CreateKeepAliveRequest(0 /* delay */, 1 /* bodySize */)).then(function(response) {
- // Flag we got a response from this request.
- lastFetchSucceeded = true;
- });
+ return fetchKeepAliveRequest(noDelay, 1 /* bodySize */);
});
- return firstFetch;
- }, "A Keep-Alive fetch() should return only it's allocated Quota upon promise resolution.");
+ return Promise.all([first, second]);
+ }, 'A Keep-Alive fetch() should return only its allocated Quota upon promise resolution.');
// Test rejecting a fetch() after the quota is used up.
promise_test(function (test) {
// Fill our Quota then try to send a second fetch.
- fetch(CreateKeepAliveRequest(standardDelay, expectedQuota));
+ const p = fetchKeepAliveRequest(standardDelay, expectedQuota);
- return promise_rejects(test, new TypeError(), fetch(CreateKeepAliveRequest(0 /* delay */, 1 /* bodySize */)));
- }, "A Keep-Alive fetch() should not be allowed if the Quota is used up.");
+ const q = promise_rejects(test, TypeError(), fetchKeepAliveRequest(noDelay, 1 /* bodySize */));
+ return Promise.all([p, q]);
+ }, 'A Keep-Alive fetch() should not be allowed if the Quota is used up.');
</script>
</body>
diff --git a/tests/wpt/web-platform-tests/fetch/api/resources/trickle.py b/tests/wpt/web-platform-tests/fetch/api/resources/trickle.py
index 0e709445c59..319ecd21f45 100644
--- a/tests/wpt/web-platform-tests/fetch/api/resources/trickle.py
+++ b/tests/wpt/web-platform-tests/fetch/api/resources/trickle.py
@@ -3,6 +3,8 @@ import time
def main(request, response):
delay = float(request.GET.first("ms", 500)) / 1E3
count = int(request.GET.first("count", 50))
+ # Read request body
+ request.body
time.sleep(delay)
response.headers.set("Content-type", "text/plain")
response.write_status_headers()
diff --git a/tests/wpt/web-platform-tests/fetch/api/response/response-idl.html b/tests/wpt/web-platform-tests/fetch/api/response/response-idl.html
index 3bbf54e6f3c..bd265fa203d 100644
--- a/tests/wpt/web-platform-tests/fetch/api/response/response-idl.html
+++ b/tests/wpt/web-platform-tests/fetch/api/response/response-idl.html
@@ -15,9 +15,7 @@
typedef any JSON;
typedef (Blob or BufferSource or FormData or URLSearchParams or USVString) BodyInit;
- [NoInterfaceObject,
- Exposed=(Window,Worker)]
- interface Body {
+ interface mixin Body {
readonly attribute ReadableStream? body;
readonly attribute boolean bodyUsed;
[NewObject] Promise<ArrayBuffer> arrayBuffer();
@@ -45,7 +43,7 @@
[NewObject] Response clone();
};
- Response implements Body;
+ Response includes Body;
dictionary ResponseInit {
unsigned short status = 200;
diff --git a/tests/wpt/web-platform-tests/fetch/nosniff/resources/css.py b/tests/wpt/web-platform-tests/fetch/nosniff/resources/css.py
index 7c4c63b596a..55712c5e23e 100644
--- a/tests/wpt/web-platform-tests/fetch/nosniff/resources/css.py
+++ b/tests/wpt/web-platform-tests/fetch/nosniff/resources/css.py
@@ -1,15 +1,23 @@
def main(request, response):
- outcome = request.GET.first("outcome", "f")
type = request.GET.first("type", None)
+ is_revalidation = request.headers.get("If-Modified-Since", None)
content = "/* nothing to see here */"
response.add_required_headers = False
- response.writer.write_status(200)
- response.writer.write_header("x-content-type-options", "nosniff")
- response.writer.write_header("content-length", len(content))
- if(type != None):
- response.writer.write_header("content-type", type)
- response.writer.end_headers()
-
- response.writer.write(content)
+ if is_revalidation is not None:
+ response.writer.write_status(304)
+ response.writer.write_header("x-content-type-options", "nosniff")
+ response.writer.write_header("content-length", 0)
+ if(type != None):
+ response.writer.write_header("content-type", type)
+ response.writer.end_headers()
+ response.writer.write("")
+ else:
+ response.writer.write_status(200)
+ response.writer.write_header("x-content-type-options", "nosniff")
+ response.writer.write_header("content-length", len(content))
+ if(type != None):
+ response.writer.write_header("content-type", type)
+ response.writer.end_headers()
+ response.writer.write(content)
diff --git a/tests/wpt/web-platform-tests/fetch/nosniff/stylesheet.html b/tests/wpt/web-platform-tests/fetch/nosniff/stylesheet.html
index 9e47f757b97..3d3c9f088da 100644
--- a/tests/wpt/web-platform-tests/fetch/nosniff/stylesheet.html
+++ b/tests/wpt/web-platform-tests/fetch/nosniff/stylesheet.html
@@ -18,21 +18,43 @@
async_test(function(t) {
var link = document.createElement("link")
link.rel = "stylesheet"
- link.onerror = t.step_func_done(function(){})
+ link.onerror = t.step_func_done()
link.onload = t.unreached_func("Unexpected load event")
link.href = get_url(mime)
document.body.appendChild(link)
}, "URL query: " + mime)
})
+ fails.forEach(function(mime) {
+ async_test(function(t) {
+ var link = document.createElement("link")
+ link.rel = "stylesheet"
+ link.onerror = t.step_func_done()
+ link.onload = t.unreached_func("Unexpected load event")
+ link.href = get_url(mime)
+ document.body.appendChild(link)
+ }, "Revalidated URL query: " + mime)
+ })
+
passes.forEach(function(mime) {
async_test(function(t) {
var link = document.createElement("link")
link.rel = "stylesheet"
link.onerror = t.unreached_func("Unexpected error event")
- link.onload = t.step_func_done(function(){})
+ link.onload = t.step_func_done()
link.href = get_url(mime)
document.body.appendChild(link)
}, "URL query: " + mime)
})
+
+ passes.forEach(function(mime) {
+ async_test(function(t) {
+ var link = document.createElement("link")
+ link.rel = "stylesheet"
+ link.onerror = t.unreached_func("Unexpected error event")
+ link.onload = t.step_func_done()
+ link.href = get_url(mime)
+ document.body.appendChild(link)
+ }, "Revalidated URL query: " + mime)
+ })
</script>
diff --git a/tests/wpt/web-platform-tests/fullscreen/model/move-to-fullscreen-iframe-manual.html b/tests/wpt/web-platform-tests/fullscreen/model/move-to-fullscreen-iframe-manual.html
new file mode 100644
index 00000000000..d152f7d144b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/fullscreen/model/move-to-fullscreen-iframe-manual.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<title>Moving fullscreen document's body into a fullscreen iframe</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../trusted-click.js"></script>
+<iframe allowfullscreen></iframe>
+<script>
+async_test(t => {
+ const iframe = document.querySelector('iframe');
+ const iframeDoc = iframe.contentDocument;
+
+ // Enter fullscreen for the iframe's body element.
+ trusted_request(t, iframeDoc.body, document.body);
+ document.onfullscreenchange = t.step_func(() => {
+
+ // Then, move the outer document's body into the iframe. This is an unusual
+ // thing to do, but means that the iframe is removed from its document and
+ // should trigger fullscreen exit.
+ iframeDoc.documentElement.appendChild(document.body);
+
+ // If we exit in an orderly fashion, that's all one can ask for.
+ document.onfullscreenchange = t.step_func_done(() => {
+ assert_equals(document.fullscreenElement, null, "document's fullscreen element");
+
+ // the iframe's contentDocument has become undefined, but the reference
+ // we're holding on to should not have a fullscreen element either.
+ assert_equals(iframe.contentDocuemnt, undefined, "iframe's content document");
+ assert_equals(iframeDoc.fullscreenElement, null, "iframe's fullscreen element");
+ });
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/fullscreen/rendering/ua-style-iframe-manual.html b/tests/wpt/web-platform-tests/fullscreen/rendering/ua-style-iframe-manual.html
new file mode 100644
index 00000000000..bf93aa28c3f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/fullscreen/rendering/ua-style-iframe-manual.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<title>User-agent levels style sheet defaults for iframe</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../trusted-click.js"></script>
+<style>
+iframe {
+ border: 1px solid blue;
+ padding: 1px;
+ /* transform is also tested because of https://crbug.com/662393 */
+ transform: scale(0.5);
+}
+</style>
+<div id="log"></div>
+<div id="ancestor"><iframe></iframe></div>
+<script>
+async_test(t => {
+ const ancestor = document.getElementById('ancestor');
+ const iframe = ancestor.firstChild;
+
+ const initialStyle = getComputedStyle(iframe);
+ assert_equals(initialStyle.border, '1px solid rgb(0, 0, 255)', 'initial border style');
+ assert_equals(initialStyle.padding, '1px', 'initial padding style');
+ assert_equals(initialStyle.transform, 'matrix(0.5, 0, 0, 0.5, 0, 0)', 'initial transform style');
+
+ trusted_request(t, iframe);
+
+ document.addEventListener('fullscreenchange', t.step_func_done(() => {
+ const fullscreenStyle = getComputedStyle(iframe);
+ assert_equals(fullscreenStyle.border, '0px none rgb(0, 0, 0)', 'fullscreen border style');
+ assert_equals(fullscreenStyle.padding, '0px', 'fullscreen padding style');
+ assert_equals(fullscreenStyle.transform, 'none', 'fullscreen transform style');
+ }));
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/generic-sensor/generic-sensor-feature-policy-test.sub.js b/tests/wpt/web-platform-tests/generic-sensor/generic-sensor-feature-policy-test.sub.js
new file mode 100644
index 00000000000..f722315cfb2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/generic-sensor/generic-sensor-feature-policy-test.sub.js
@@ -0,0 +1,159 @@
+const feature_policies = {
+ "AmbientLightSensor" : ["ambient-light-sensor"],
+ "Accelerometer" : ["accelerometer"],
+ "LinearAccelerationSensor" : ["accelerometer"],
+ "GravitySensor" : ["accelerometer"],
+ "Gyroscope" : ["gyroscope"],
+ "GeolocationSensor" : ["geolocation"],
+ "Magnetometer" : ["magnetometer"],
+ "UncalibratedMagnetometer" : ["magnetometer"],
+ "AbsoluteOrientationSensor" : ["accelerometer", "gyroscope", "magnetometer"],
+ "RelativeOrientationSensor" : ["accelerometer", "gyroscope"]
+};
+
+const same_origin_src =
+ "/feature-policy/resources/feature-policy-generic-sensor.html#";
+const cross_origin_src =
+ "https://{{domains[www]}}:{{ports[https][0]}}" + same_origin_src;
+const base_src = "/feature-policy/resources/redirect-on-load.html#";
+
+function run_fp_tests_disabled(sensorType) {
+ const sensorName = sensorType.name;
+ const featureNameList = feature_policies[sensorName];
+ const header = "Feature-Policy header " + featureNameList.join(" 'none';") + " 'none'";
+ const desc = "'new " + sensorName + "()'";
+
+ test(() => {
+ assert_throws("SecurityError", () => {new sensorType()});
+ }, `${sensorName}: ${header} disallows the top-level document.`);
+
+ async_test(t => {
+ test_feature_availability(
+ desc,
+ t,
+ same_origin_src + sensorName,
+ expect_feature_unavailable_default
+ );
+ }, `${sensorName}: ${header} disallows same-origin iframes.`);
+
+ async_test(t => {
+ test_feature_availability(
+ desc,
+ t,
+ cross_origin_src + sensorName,
+ expect_feature_unavailable_default
+ );
+ }, `${sensorName}: ${header} disallows cross-origin iframes.`);
+}
+
+function run_fp_tests_enabled(sensorType) {
+ const sensorName = sensorType.name;
+ const featureNameList = feature_policies[sensorName];
+ const header = "Feature-Policy header " + featureNameList.join(" *;") + " *";
+ const desc = "'new " + sensorName + "()'";
+
+ test(() => {
+ assert_true(sensorName in window);
+ }, `${sensorName}: ${header} allows the top-level document.`);
+
+ async_test(t => {
+ test_feature_availability(
+ desc,
+ t,
+ same_origin_src + sensorName,
+ expect_feature_available_default
+ );
+ }, `${sensorName}: ${header} allows same-origin iframes.`);
+
+ async_test(t => {
+ test_feature_availability(
+ desc,
+ t,
+ cross_origin_src + sensorName,
+ expect_feature_available_default
+ );
+ }, `${sensorName}: ${header} allows cross-origin iframes.`);
+}
+
+function run_fp_tests_enabled_by_attribute(sensorType) {
+ const sensorName = sensorType.name;
+ const featureNameList = feature_policies[sensorName];
+ const header = "Feature-Policy allow='" + featureNameList.join(" ") + "' attribute";
+ const desc = "'new " + sensorName + "()'";
+
+ async_test(t => {
+ test_feature_availability(
+ desc,
+ t,
+ same_origin_src + sensorName,
+ expect_feature_available_default,
+ featureNameList.join(";")
+ );
+ }, `${sensorName}: ${header} allows same-origin iframe`);
+
+ async_test(t => {
+ test_feature_availability(
+ desc,
+ t,
+ cross_origin_src + sensorName,
+ expect_feature_available_default,
+ featureNameList.join(";")
+ );
+ }, `${sensorName}: ${header} allows cross-origin iframe`);
+}
+
+function run_fp_tests_enabled_by_attribute_redirect_on_load(sensorType) {
+ const sensorName = sensorType.name;
+ const featureNameList = feature_policies[sensorName];
+ const header = "Feature-Policy allow='" + featureNameList.join(" ") + "' attribute";
+ const desc = "'new " + sensorName + "()'";
+
+ async_test(t => {
+ test_feature_availability(
+ desc,
+ t,
+ base_src + same_origin_src + sensorName,
+ expect_feature_available_default,
+ featureNameList.join(";")
+ );
+ }, `${sensorName}: ${header} allows same-origin relocation`);
+
+ async_test(t => {
+ test_feature_availability(
+ desc,
+ t,
+ base_src + cross_origin_src + sensorName,
+ expect_feature_unavailable_default,
+ featureNameList.join(";")
+ );
+ }, `${sensorName}: ${header} disallows cross-origin relocation`);
+}
+
+function run_fp_tests_enabled_on_self_origin(sensorType) {
+ const sensorName = sensorType.name;
+ const featureNameList = feature_policies[sensorName];
+ const header = "Feature-Policy header " + featureNameList.join(" 'self';") + " 'self'";
+ const desc = "'new " + sensorName + "()'";
+
+ test(() => {
+ assert_true(sensorName in window);
+ }, `${sensorName}: ${header} allows the top-level document.`);
+
+ async_test(t => {
+ test_feature_availability(
+ desc,
+ t,
+ same_origin_src + sensorName,
+ expect_feature_available_default
+ );
+ }, `${sensorName}: ${header} allows same-origin iframes.`);
+
+ async_test(t => {
+ test_feature_availability(
+ desc,
+ t,
+ cross_origin_src + sensorName,
+ expect_feature_unavailable_default
+ );
+ }, `${sensorName}: ${header} disallows cross-origin iframes.`);
+}
diff --git a/tests/wpt/web-platform-tests/generic-sensor/generic-sensor-tests.js b/tests/wpt/web-platform-tests/generic-sensor/generic-sensor-tests.js
index afa0f462d90..cde23741d68 100644
--- a/tests/wpt/web-platform-tests/generic-sensor/generic-sensor-tests.js
+++ b/tests/wpt/web-platform-tests/generic-sensor/generic-sensor-tests.js
@@ -1,15 +1,16 @@
-let unreached = event => {
- assert_unreached(event.error.name + ": " + event.error.message);
-};
-
-let properties = {
+const properties = {
'AmbientLightSensor' : ['timestamp', 'illuminance'],
'Accelerometer' : ['timestamp', 'x', 'y', 'z'],
'LinearAccelerationSensor' : ['timestamp', 'x', 'y', 'z'],
+ "GravitySensor" : ['timestamp', 'x', 'y', 'z'],
'Gyroscope' : ['timestamp', 'x', 'y', 'z'],
'Magnetometer' : ['timestamp', 'x', 'y', 'z'],
+ "UncalibratedMagnetometer" : ['timestamp', 'x', 'y', 'z',
+ 'xBias', 'yBias', 'zBias'],
'AbsoluteOrientationSensor' : ['timestamp', 'quaternion'],
- 'RelativeOrientationSensor' : ['timestamp', 'quaternion']
+ 'RelativeOrientationSensor' : ['timestamp', 'quaternion'],
+ 'GeolocationSensor' : ['timestamp', 'latitude', 'longitude', 'altitude',
+ 'accuracy', 'altitudeAccuracy', 'heading', 'speed']
};
function assert_reading_not_null(sensor) {
@@ -27,7 +28,7 @@ function assert_reading_null(sensor) {
}
function reading_to_array(sensor) {
- let arr = new Array();
+ const arr = new Array();
for (let property in properties[sensor.constructor.name]) {
let propertyName = properties[sensor.constructor.name][property];
arr[property] = sensor[propertyName];
@@ -36,159 +37,129 @@ function reading_to_array(sensor) {
}
function runGenericSensorTests(sensorType) {
- async_test(t => {
- let sensor = new sensorType();
- sensor.onreading = t.step_func_done(() => {
- assert_reading_not_null(sensor);
- assert_true(sensor.hasReading);
- sensor.stop();
- assert_reading_null(sensor);
- assert_false(sensor.hasReading);
- });
- sensor.onerror = t.step_func_done(unreached);
+ promise_test(async t => {
+ const sensor = new sensorType();
+ const sensorWatcher = new EventWatcher(t, sensor, ["reading", "error"]);
sensor.start();
+
+ await sensorWatcher.wait_for("reading");
+ assert_reading_not_null(sensor);
+ assert_true(sensor.hasReading);
+
+ sensor.stop();
+ assert_reading_null(sensor);
+ assert_false(sensor.hasReading);
}, `${sensorType.name}: Test that 'onreading' is called and sensor reading is valid`);
- async_test(t => {
- let sensor1 = new sensorType();
- let sensor2 = new sensorType();
- sensor1.onreading = t.step_func_done(() => {
- // Reading values are correct for both sensors.
- assert_reading_not_null(sensor1);
- assert_reading_not_null(sensor2);
-
- //After first sensor stops its reading values are null,
- //reading values for the second sensor remains
- sensor1.stop();
- assert_reading_null(sensor1);
- assert_reading_not_null(sensor2);
- sensor2.stop();
- assert_reading_null(sensor2);
- });
- sensor1.onerror = t.step_func_done(unreached);
- sensor2.onerror = t.step_func_done(unreached);
+ promise_test(async t => {
+ const sensor1 = new sensorType();
+ const sensor2 = new sensorType();
+ const sensorWatcher = new EventWatcher(t, sensor1, ["reading", "error"]);
sensor2.start();
sensor1.start();
+
+ await sensorWatcher.wait_for("reading");
+ // Reading values are correct for both sensors.
+ assert_reading_not_null(sensor1);
+ assert_reading_not_null(sensor2);
+
+ //After first sensor stops its reading values are null,
+ //reading values for the second sensor remains
+ sensor1.stop();
+ assert_reading_null(sensor1);
+ assert_reading_not_null(sensor2);
+ sensor2.stop();
+ assert_reading_null(sensor2);
}, `${sensorType.name}: sensor reading is correct`);
- async_test(t => {
- let sensor = new sensorType();
- let cachedTimeStamp1;
- sensor.onreading = () => {
- cachedTimeStamp1 = sensor.timestamp;
- };
- sensor.onerror = t.step_func_done(unreached);
+ promise_test(async t => {
+ const sensor = new sensorType();
+ const sensorWatcher = new EventWatcher(t, sensor, ["reading", "error"]);
sensor.start();
- t.step_timeout(() => {
- sensor.onreading = t.step_func_done(() => {
- //sensor.timestamp changes.
- let cachedTimeStamp2 = sensor.timestamp;
- assert_greater_than(cachedTimeStamp2, cachedTimeStamp1);
- sensor.stop();
- });
- }, 1000);
+
+ await sensorWatcher.wait_for("reading");
+ const cachedTimeStamp1 = sensor.timestamp;
+
+ await sensorWatcher.wait_for("reading");
+ const cachedTimeStamp2 = sensor.timestamp;
+
+ assert_greater_than(cachedTimeStamp2, cachedTimeStamp1);
+ sensor.stop();
}, `${sensorType.name}: sensor timestamp is updated when time passes`);
- async_test(t => {
- let sensor = new sensorType();
- sensor.onerror = t.step_func_done(unreached);
+ promise_test(async t => {
+ const sensor = new sensorType();
+ const sensorWatcher = new EventWatcher(t, sensor, ["activate", "error"]);
assert_false(sensor.activated);
- sensor.onreading = t.step_func_done(() => {
- assert_true(sensor.activated);
- sensor.stop();
- assert_false(sensor.activated);
- });
sensor.start();
assert_false(sensor.activated);
+
+ await sensorWatcher.wait_for("activate");
+ assert_true(sensor.activated);
+
+ sensor.stop();
+ assert_false(sensor.activated);
}, `${sensorType.name}: Test that sensor can be successfully created and its states are correct.`);
- test(() => {
- let sensor, start_return;
- sensor = new sensorType();
- sensor.onerror = unreached;
- start_return = sensor.start();
+ promise_test(async t => {
+ const sensor = new sensorType();
+ const sensorWatcher = new EventWatcher(t, sensor, ["activate", "error"]);
+ const start_return = sensor.start();
+
+ await sensorWatcher.wait_for("activate");
assert_equals(start_return, undefined);
sensor.stop();
}, `${sensorType.name}: sensor.start() returns undefined`);
- test(() => {
- try {
- let sensor = new sensorType();
- sensor.onerror = unreached;
- sensor.start();
- sensor.start();
- assert_false(sensor.activated);
- sensor.stop();
- } catch (e) {
- assert_unreached(e.name + ": " + e.message);
- }
+ promise_test(async t => {
+ const sensor = new sensorType();
+ const sensorWatcher = new EventWatcher(t, sensor, ["activate", "error"]);
+ sensor.start();
+ sensor.start();
+
+ await sensorWatcher.wait_for("activate");
+ assert_true(sensor.activated);
+ sensor.stop();
}, `${sensorType.name}: no exception is thrown when calling start() on already started sensor`);
- test(() => {
- let sensor, stop_return;
- sensor = new sensorType();
- sensor.onerror = unreached;
+ promise_test(async t => {
+ const sensor = new sensorType();
+ const sensorWatcher = new EventWatcher(t, sensor, ["activate", "error"]);
sensor.start();
- stop_return = sensor.stop();
+
+ await sensorWatcher.wait_for("activate");
+ const stop_return = sensor.stop();
assert_equals(stop_return, undefined);
}, `${sensorType.name}: sensor.stop() returns undefined`);
- test(() => {
- try {
- let sensor = new sensorType();
- sensor.onerror = unreached;
- sensor.start();
- sensor.stop();
- sensor.stop();
- assert_false(sensor.activated);
- } catch (e) {
- assert_unreached(e.name + ": " + e.message);
- }
+ promise_test(async t => {
+ const sensor = new sensorType();
+ const sensorWatcher = new EventWatcher(t, sensor, ["activate", "error"]);
+ sensor.start();
+
+ await sensorWatcher.wait_for("activate");
+ sensor.stop();
+ sensor.stop();
+ assert_false(sensor.activated);
}, `${sensorType.name}: no exception is thrown when calling stop() on already stopped sensor`);
- promise_test(() => {
- return new Promise((resolve,reject) => {
- let iframe = document.createElement('iframe');
- iframe.srcdoc = '<script>' +
- ' window.onmessage = message => {' +
- ' if (message.data === "LOADED") {' +
- ' try {' +
- ' new ' + sensorType.name + '();' +
- ' parent.postMessage("FAIL", "*");' +
- ' } catch (e) {' +
- ' parent.postMessage(e.name, "*");' +
- ' }' +
- ' }' +
- ' };' +
- '<\/script>';
- iframe.onload = () => iframe.contentWindow.postMessage('LOADED', '*');
- document.body.appendChild(iframe);
- window.onmessage = message => {
- if (message.data == 'SecurityError') {
- resolve();
- } else {
- reject();
- }
- }
- });
- }, `${sensorType.name}: throw a 'SecurityError' when constructing sensor object within iframe`);
-
- async_test(t => {
- let sensor = new sensorType();
- sensor.onreading = t.step_func(() => {
- assert_reading_not_null(sensor);
- let cachedSensor1 = reading_to_array(sensor);
- let win = window.open('', '_blank');
- t.step_timeout(() => {
- let cachedSensor2 = reading_to_array(sensor);
- win.close();
- sensor.stop();
- assert_array_equals(cachedSensor1, cachedSensor2);
- t.done();
- }, 1000);
- });
- sensor.onerror = t.step_func_done(unreached);
+ promise_test(async t => {
+ const sensor = new sensorType();
+ const sensorWatcher = new EventWatcher(t, sensor, ["reading", "error"]);
+ const visibilityChangeWatcher = new EventWatcher(t, document, "visibilitychange");
sensor.start();
+
+ await sensorWatcher.wait_for("reading");
+ assert_reading_not_null(sensor);
+ const cachedSensor1 = reading_to_array(sensor);
+
+ const win = window.open('', '_blank');
+ await visibilityChangeWatcher.wait_for("visibilitychange");
+ const cachedSensor2 = reading_to_array(sensor);
+
+ win.close();
+ sensor.stop();
+ assert_array_equals(cachedSensor1, cachedSensor2);
}, `${sensorType.name}: sensor readings can not be fired on the background tab`);
}
@@ -199,13 +170,13 @@ function runGenericSensorInsecureContext(sensorType) {
}
function runGenericSensorOnerror(sensorType) {
- async_test(t => {
- let sensor = new sensorType();
- sensor.onactivate = t.step_func_done(assert_unreached);
- sensor.onerror = t.step_func_done(event => {
- assert_false(sensor.activated);
- assert_equals(event.error.name, 'NotReadableError');
- });
+ promise_test(async t => {
+ const sensor = new sensorType();
+ const sensorWatcher = new EventWatcher(t, sensor, ["error", "activate"]);
sensor.start();
+
+ const event = await sensorWatcher.wait_for("error");
+ assert_false(sensor.activated);
+ assert_equals(event.error.name, 'NotReadableError');
}, `${sensorType.name}: 'onerror' event is fired when sensor is not supported`);
}
diff --git a/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-disabled-by-feature-policy.https.html b/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-disabled-by-feature-policy.https.html
new file mode 100644
index 00000000000..7d5d47fe6c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-disabled-by-feature-policy.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_disabled(GeolocationSensor);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-disabled-by-feature-policy.https.html.headers b/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-disabled-by-feature-policy.https.html.headers
new file mode 100644
index 00000000000..7e75481ea6d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-disabled-by-feature-policy.https.html.headers
@@ -0,0 +1 @@
+Feature-Policy: geolocation 'none'
diff --git a/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html b/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html
new file mode 100644
index 00000000000..62c5d456f0c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled_by_attribute_redirect_on_load(GeolocationSensor);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-enabled-by-feature-policy-attribute.https.html b/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-enabled-by-feature-policy-attribute.https.html
new file mode 100644
index 00000000000..1e5bfb36a2b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-enabled-by-feature-policy-attribute.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled_by_attribute(GeolocationSensor);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-enabled-by-feature-policy.https.html b/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-enabled-by-feature-policy.https.html
new file mode 100644
index 00000000000..afe935efeb0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-enabled-by-feature-policy.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled(GeolocationSensor);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-enabled-by-feature-policy.https.html.headers b/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-enabled-by-feature-policy.https.html.headers
new file mode 100644
index 00000000000..40e9bc16ff9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-enabled-by-feature-policy.https.html.headers
@@ -0,0 +1 @@
+Feature-Policy: geolocation *
diff --git a/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-enabled-on-self-origin-by-feature-policy.https.html b/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-enabled-on-self-origin-by-feature-policy.https.html
new file mode 100644
index 00000000000..46be7fba6f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-enabled-on-self-origin-by-feature-policy.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled_on_self_origin(GeolocationSensor);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-enabled-on-self-origin-by-feature-policy.https.html.headers b/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-enabled-on-self-origin-by-feature-policy.https.html.headers
new file mode 100644
index 00000000000..b83264eee76
--- /dev/null
+++ b/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor-enabled-on-self-origin-by-feature-policy.https.html.headers
@@ -0,0 +1 @@
+Feature-Policy: geolocation 'self'
diff --git a/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor.https.html b/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor.https.html
new file mode 100644
index 00000000000..625963870f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor.https.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>GeolocationSensor Test</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://wicg.github.io/geolocation-sensor/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/generic-sensor/generic-sensor-tests.js"></script>
+<script>
+
+runGenericSensorTests(GeolocationSensor);
+
+</script>
diff --git a/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor_insecure_context.html b/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor_insecure_context.html
new file mode 100644
index 00000000000..6a3a126c785
--- /dev/null
+++ b/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor_insecure_context.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>GeolocationSensor Test: insecure context</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://wicg.github.io/geolocation-sensor/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/generic-sensor/generic-sensor-tests.js"></script>
+<script>
+
+runGenericSensorInsecureContext("GeolocationSensor");
+
+</script>
diff --git a/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor_onerror-manual.https.html b/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor_onerror-manual.https.html
new file mode 100644
index 00000000000..b449346546f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/geolocation-sensor/GeolocationSensor_onerror-manual.https.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>GeolocationSensor Test: onerror</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://wicg.github.io/geolocation-sensor/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/generic-sensor/generic-sensor-tests.js"></script>
+<h2>Precondition</h2>
+<ol>
+ <li>
+ Disable the Geolocation sensor or run test on a device without Geolocation sensor.
+ </li>
+</ol>
+<script>
+
+runGenericSensorOnerror(GeolocationSensor);
+
+</script>
diff --git a/tests/wpt/web-platform-tests/geolocation-sensor/OWNERS b/tests/wpt/web-platform-tests/geolocation-sensor/OWNERS
index a21fb0e4b54..71305991859 100644
--- a/tests/wpt/web-platform-tests/geolocation-sensor/OWNERS
+++ b/tests/wpt/web-platform-tests/geolocation-sensor/OWNERS
@@ -1 +1,2 @@
@anssiko
+@Honry
diff --git a/tests/wpt/web-platform-tests/geolocation-sensor/idlharness.https.html b/tests/wpt/web-platform-tests/geolocation-sensor/idlharness.https.html
index e2aee5c1cb8..183b3f865ce 100644
--- a/tests/wpt/web-platform-tests/geolocation-sensor/idlharness.https.html
+++ b/tests/wpt/web-platform-tests/geolocation-sensor/idlharness.https.html
@@ -1,15 +1,19 @@
<!DOCTYPE html>
+<meta charset="utf-8">
<title>Geolocation Sensor IDL tests</title>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/resources/WebIDLParser.js></script>
-<script src=/resources/idlharness.js></script>
+<link rel="help" href="https://wicg.github.io/geolocation-sensor/">
+<link rel="help" href="https://w3c.github.io/sensors/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
<script>
"use strict";
function doTest([generic_sensor, geolocation_sensor]) {
- var idl_array = new IdlArray();
+ const idl_array = new IdlArray();
idl_array.add_untested_idls('interface EventTarget {};');
+ idl_array.add_untested_idls('interface EventHandler {};');
idl_array.add_idls(generic_sensor, { only: ['Sensor'] });
idl_array.add_idls(geolocation_sensor);
idl_array.add_objects({
@@ -23,8 +27,9 @@ function fetchText(url) {
}
promise_test(() => {
- return Promise.all(["/interfaces/generic-sensor.idl",
- "/interfaces/geolocation-sensor.idl"].map(fetchText))
- .then(doTest);
-}, "Test driver");
+ return Promise.all([
+ "/interfaces/generic-sensor.idl",
+ "/interfaces/geolocation-sensor.idl"
+ ].map(fetchText)).then(doTest);
+}, "Test IDL implementation of Geolocation Sensor");
</script>
diff --git a/tests/wpt/web-platform-tests/gyroscope/Gyroscope-disabled-by-feature-policy.https.html b/tests/wpt/web-platform-tests/gyroscope/Gyroscope-disabled-by-feature-policy.https.html
new file mode 100644
index 00000000000..70add9b38bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/gyroscope/Gyroscope-disabled-by-feature-policy.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_disabled(Gyroscope);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/gyroscope/Gyroscope-disabled-by-feature-policy.https.html.headers b/tests/wpt/web-platform-tests/gyroscope/Gyroscope-disabled-by-feature-policy.https.html.headers
new file mode 100644
index 00000000000..3d91d5840be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/gyroscope/Gyroscope-disabled-by-feature-policy.https.html.headers
@@ -0,0 +1 @@
+Feature-Policy: gyroscope 'none'
diff --git a/tests/wpt/web-platform-tests/gyroscope/Gyroscope-enabled-by-feature-policy-attribute-redirect-on-load.https.html b/tests/wpt/web-platform-tests/gyroscope/Gyroscope-enabled-by-feature-policy-attribute-redirect-on-load.https.html
new file mode 100644
index 00000000000..6d8c48645ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/gyroscope/Gyroscope-enabled-by-feature-policy-attribute-redirect-on-load.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled_by_attribute_redirect_on_load(Gyroscope);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/gyroscope/Gyroscope-enabled-by-feature-policy-attribute.https.html b/tests/wpt/web-platform-tests/gyroscope/Gyroscope-enabled-by-feature-policy-attribute.https.html
new file mode 100644
index 00000000000..07624624ce7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/gyroscope/Gyroscope-enabled-by-feature-policy-attribute.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled_by_attribute(Gyroscope);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/gyroscope/Gyroscope-enabled-by-feature-policy.https.html b/tests/wpt/web-platform-tests/gyroscope/Gyroscope-enabled-by-feature-policy.https.html
new file mode 100644
index 00000000000..1f1418b2014
--- /dev/null
+++ b/tests/wpt/web-platform-tests/gyroscope/Gyroscope-enabled-by-feature-policy.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled(Gyroscope);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/gyroscope/Gyroscope-enabled-by-feature-policy.https.html.headers b/tests/wpt/web-platform-tests/gyroscope/Gyroscope-enabled-by-feature-policy.https.html.headers
new file mode 100644
index 00000000000..0fd938b4aa9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/gyroscope/Gyroscope-enabled-by-feature-policy.https.html.headers
@@ -0,0 +1 @@
+Feature-Policy: gyroscope *
diff --git a/tests/wpt/web-platform-tests/gyroscope/Gyroscope-enabled-on-self-origin-by-feature-policy.https.html b/tests/wpt/web-platform-tests/gyroscope/Gyroscope-enabled-on-self-origin-by-feature-policy.https.html
new file mode 100644
index 00000000000..19ab572b382
--- /dev/null
+++ b/tests/wpt/web-platform-tests/gyroscope/Gyroscope-enabled-on-self-origin-by-feature-policy.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled_on_self_origin(Gyroscope);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/gyroscope/Gyroscope-enabled-on-self-origin-by-feature-policy.https.html.headers b/tests/wpt/web-platform-tests/gyroscope/Gyroscope-enabled-on-self-origin-by-feature-policy.https.html.headers
new file mode 100644
index 00000000000..7cf4fd8f6bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/gyroscope/Gyroscope-enabled-on-self-origin-by-feature-policy.https.html.headers
@@ -0,0 +1 @@
+Feature-Policy: gyroscope 'self'
diff --git a/tests/wpt/web-platform-tests/hr-time/idlharness.html b/tests/wpt/web-platform-tests/hr-time/idlharness.html
index d0c648c1bb7..c3fd9070ad0 100644
--- a/tests/wpt/web-platform-tests/hr-time/idlharness.html
+++ b/tests/wpt/web-platform-tests/hr-time/idlharness.html
@@ -13,63 +13,34 @@
<body>
<h1>High Resolution Time IDL tests</h1>
<div id="log"></div>
-
-<pre id='untested_idl' style='display:none'>
-[Exposed=Windows,Worker]
-interface WindowOrWorkerGlobalScope {
-};
-
-[Exposed=(Window,Worker)]
-interface EventTarget {
-};
-
-[Exposed=Window]
-interface PerformanceTiming {
-};
-
-[Exposed=Window]
-interface PerformanceNavigation {
-};
-
-// from nav-timing
-partial interface Performance {
- [SameObject]
- readonly attribute PerformanceTiming timing;
- [SameObject]
- readonly attribute PerformanceNavigation navigation;
- [Default] object toJSON();
-};
-</pre>
-
-<pre id='idl'>
-typedef double DOMHighResTimeStamp;
-
-[Exposed=(Window,Worker)]
-interface Performance : EventTarget {
- DOMHighResTimeStamp now();
- readonly attribute DOMHighResTimeStamp timeOrigin;
- [Default] object toJSON();
-};
-
-partial interface WindowOrWorkerGlobalScope {
- [Replaceable]
- readonly attribute Performance performance;
-};
-</pre>
-
<script>
+'use strict';
-(function() {
+function doTest([html, hr_time]) {
var idl_array = new IdlArray();
-
- idl_array.add_untested_idls(document.getElementById("untested_idl").textContent);
- idl_array.add_idls(document.getElementById("idl").textContent);
-
- idl_array.add_objects({Performance: [window.performance]});
-
+ // HTML is needed for WindowOrWorkerGlobalScope. Provide dummy interfaces for
+ // things that HTML depends on in turn which are not under tests.
+ idl_array.add_untested_idls('interface Document {};');
+ idl_array.add_untested_idls('interface EventTarget {};');
+ idl_array.add_untested_idls('interface LinkStyle {};');
+ idl_array.add_untested_idls(html);
+ idl_array.add_idls(hr_time);
+ idl_array.add_objects({
+ Performance: ["window.performance"],
+ Window: ["window"],
+ });
idl_array.test();
-})();
+}
+
+function fetchText(url) {
+ return fetch(url).then((response) => response.text());
+}
+promise_test(() => {
+ return Promise.all(['/interfaces/html.idl',
+ '/interfaces/hr-time.idl'].map(fetchText))
+ .then(doTest);
+}, 'Test driver');
</script>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/hr-time/performance-tojson.html b/tests/wpt/web-platform-tests/hr-time/performance-tojson.html
new file mode 100644
index 00000000000..fd8049cb9a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/hr-time/performance-tojson.html
@@ -0,0 +1,76 @@
+<!doctype html>
+<html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+
+test(() => {
+ // Check Performance attributes.
+ assert_equals(typeof(performance.toJSON), 'function');
+ const json = performance.toJSON();
+ assert_equals(typeof(json), 'object');
+ assert_equals(json.timeOrigin, performance.timeOrigin,
+ 'performance.toJSON().timeOrigin should match performance.timeOrigin');
+
+ // Check PerformanceTiming toJSON.
+ const jsonTiming = json.timing;
+ const timing = performance.timing;
+ assert_equals(typeof(timing.toJSON), 'function');
+ const timingJSON = timing.toJSON();
+ assert_equals(typeof(timingJSON), 'object');
+ // Check PerformanceTiming attributes, from both:
+ // 1) |jsonTiming| from Performance.
+ // 2) |timingJSON| from PerformanceTiming.
+ const performanceTimingKeys = [
+ 'navigationStart',
+ 'unloadEventStart',
+ 'unloadEventEnd',
+ 'redirectStart',
+ 'redirectEnd',
+ 'fetchStart',
+ 'domainLookupStart',
+ 'domainLookupEnd',
+ 'connectStart',
+ 'connectEnd',
+ 'secureConnectionStart',
+ 'requestStart',
+ 'responseStart',
+ 'responseEnd',
+ 'domLoading',
+ 'domInteractive',
+ 'domContentLoadedEventStart',
+ 'domContentLoadedEventEnd',
+ 'domComplete',
+ 'loadEventStart',
+ 'loadEventEnd'
+ ];
+ for (const key of performanceTimingKeys) {
+ assert_equals(jsonTiming[key], timing[key],
+ `performance.toJSON().timing.${key} should match performance.timing.${key}`);
+ assert_equals(timingJSON[key], timing[key],
+ `performance.timing.toJSON().${key} should match performance.timing.${key}`);
+ }
+
+ // Check PerformanceNavigation toJSON.
+ const jsonNavigation = json.navigation;
+ const navigation = performance.navigation;
+ assert_equals(typeof(navigation.toJSON), 'function');
+ const navigationJSON = navigation.toJSON();
+ assert_equals(typeof(navigationJSON), 'object');
+ // Check PerformanceNavigation attributes, from both:
+ // 1) |jsonNavigation| from Performance.
+ // 2) |navigationJSON| from PerformanceNavigation.
+ let performanceNavigationKeys = ['type', 'redirectCount'];
+ for (const key of performanceNavigationKeys) {
+ assert_equals(jsonNavigation[key], navigation[key],
+ `performance.toJSON().navigation.${key} should match performance.navigation.${key}`);
+ assert_equals(navigationJSON[key], navigation[key],
+ `performance.navigation.toJSON().${key} should match performance.navigation.${key}`);
+ }
+}, 'Test performance.toJSON()');
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/PopStateEvent.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/PopStateEvent.html
index 85205c1497b..8db1d2788c0 100644
--- a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/PopStateEvent.html
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/PopStateEvent.html
@@ -11,6 +11,11 @@ test(function () {
}, 'initPopStateEvent');
test(function () {
+ var popStateEvent = new PopStateEvent("popstate");
+ assert_equals(popStateEvent.state, null, "the PopStateEvent.state");
+}, "Initial value of PopStateEvent.state must be null");
+
+test(function () {
var state = history.state;
var data;
window.addEventListener('popstate', function (e) {
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/hashchange_event.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/hashchange_event.html
index 4b701ad04e2..287e7a6ef1d 100644
--- a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/hashchange_event.html
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/hashchange_event.html
@@ -18,6 +18,12 @@ window.onload = t.step_func(function () {
location.hash = 'foo';
window.onhashchange = t.step_func(function (e) {
+ assert_true(e.isTrusted);
+ assert_equals(e.target, window);
+ assert_equals(e.type, "hashchange");
+ assert_true(e instanceof HashChangeEvent);
+ assert_true(e.bubbles, "bubble");
+ assert_false(e.cancelable, "cancelable");
oldURLs.push(e.oldURL);
newURLs.push(e.newURL);
if (newURLs.length === 2) {
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html
index 4594a1ed954..7d9a31d0d40 100644
--- a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-cross-origin.html
@@ -1,20 +1,18 @@
<!DOCTYPE html>
<meta name=timeout content=long>
<title>Precedence of scroll restoration mode over fragment scrolling in cross-origin history traversal</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
<style>
iframe {
height: 300px;
width: 300px;
}
</style>
-
-<body>
- <iframe></iframe>
-</body>
-
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script type="text/javascript">
+<div id="log"></div>
+<iframe></iframe>
+<script>
'use strict';
// The test does the following navigation steps for iframe
@@ -23,13 +21,16 @@
// 3. go back to page-with-fragment.html
async_test(function(t) {
var iframe = document.querySelector('iframe');
- var baseURL = location.href.substring(0, location.href.lastIndexOf('/'));
+ var hostInfo = get_host_info();
+ var basePath = location.pathname.substring(0, location.pathname.lastIndexOf('/'));
+ var localURL = hostInfo.HTTP_ORIGIN + basePath + '/resources/page-with-fragment.html#fragment';
+ var remoteURL = hostInfo.HTTP_REMOTE_ORIGIN + basePath + "/resources/blank1.html"
var steps = [
function() {
iframe.src = 'resources/page-with-fragment.html#fragment';
}, function() {
- assert_equals(iframe.contentWindow.location.href, baseURL + '/resources/page-with-fragment.html#fragment', 'should be on page-with-fragment page');
+ assert_equals(iframe.contentWindow.location.href, localURL, 'should be on page-with-fragment page');
// wait one animation frame to ensure layout is run and fragment scrolling is complete
iframe.contentWindow.requestAnimationFrame(function() {
assert_equals(iframe.contentWindow.scrollY, 800, 'should scroll to fragment');
@@ -40,13 +41,13 @@
});
}, function() {
// navigate to a new page from a different origin
- iframe.src = iframe.src.replace("http://", "http://www.").replace("page-with-fragment.html#fragment", "blank1.html");
+ iframe.src = remoteURL;
}, function() {
// going back causes the iframe to traverse back
history.back();
}, function() {
// coming back from history, scrollRestoration should be set to manual and respected
- assert_equals(iframe.contentWindow.location.href, baseURL + '/resources/page-with-fragment.html#fragment', 'should be back on page-with-fragment page');
+ assert_equals(iframe.contentWindow.location.href, localURL, 'should be back on page-with-fragment page');
iframe.contentWindow.requestAnimationFrame(t.step_func_done(function() {
assert_equals(iframe.contentWindow.history.scrollRestoration, 'manual', 'navigating back should retain scrollRestoration value');
assert_equals(iframe.contentWindow.scrollX, 0, 'should not scroll to fragment');
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-media/pageload-video.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-media/pageload-video.html
index 69ef7413b38..1ae414ceb61 100644
--- a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-media/pageload-video.html
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-media/pageload-video.html
@@ -1,30 +1,27 @@
<!DOCTYPE HTML>
-<html>
-<head>
- <title>Media documents: video</title>
- <link rel="author" title="Michael Ventnor" href="mailto:mventnor@mozilla.com">
- <link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
- <link rel="help" href="https://html.spec.whatwg.org/multipage/#read-media">
- <script src="/resources/testharness.js"></script>
- <script src="/resources/testharnessreport.js"></script>
-
+<meta charset="utf-8">
+<title>Media documents: video</title>
+<link rel="author" title="Michael Ventnor" href="mailto:mventnor@mozilla.com">
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#read-media">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id="log"></div>
<script>
- var t = async_test("The document for a standalone media file should have one child in the body.");
-
- function frameLoaded() {
- var testframe = document.getElementById('testframe');
- assert_equals(testframe.contentDocument.contentType, "video/webm");
+async_test(function() {
+ var testframe = document.createElement('iframe');
+ var url = getVideoURI("/media/A4");
+ var contentType = getMediaContentType(url);
+ testframe.onload = this.step_func_done(function() {
+ assert_equals(testframe.contentDocument.contentType, contentType);
var testframeChildren = testframe.contentDocument.body.childNodes;
assert_equals(testframeChildren.length, 1, "Body of image document has 1 child");
assert_equals(testframeChildren[0].nodeName, "VIDEO", "Only child of body must be an <video> element");
assert_equals(testframeChildren[0].namespaceURI, "http://www.w3.org/1999/xhtml",
"Only child of body must be an HTML element");
- t.done();
- }
+ });
+ testframe.src = url;
+ document.body.appendChild(testframe);
+}, "The document for a standalone media file should have one child in the body.");
</script>
-</head>
-<body>
- <div id="log"></div>
- <iframe id="testframe" onload="t.step(frameLoaded)" src="/media/white.webm"></iframe>
-</body>
-</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload.tentative.html b/tests/wpt/web-platform-tests/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload.tentative.html
index 1b7183bd0ed..3e021c65ac8 100644
--- a/tests/wpt/web-platform-tests/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload.tentative.html
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload.tentative.html
@@ -14,7 +14,7 @@
var t = async_test();
function scheduleNextTest() {
- t.step_timeout(runNextTest, 0);
+ setTimeout(runNextTest, 0);
}
function runNextTest() {
@@ -28,9 +28,9 @@
}
function verify(actual, expected, desc) {
- t.step_timeout(function() {
+ setTimeout(t.step_func(function() {
assert_equals(actual, expected, desc);
- }, 0);
+ }), 0);
}
</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload_form-submission-2.tentative.html b/tests/wpt/web-platform-tests/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload_form-submission-2.tentative.html
index 10cc69ae0f4..11fbe2a2ba8 100644
--- a/tests/wpt/web-platform-tests/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload_form-submission-2.tentative.html
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload_form-submission-2.tentative.html
@@ -9,10 +9,10 @@
function verify() {
// Navigation in onload handler through form submission should not
// increse history length.
- var testRunner = window.top.opener;
- testRunner.verify(history.length, 1,
+ var runner = window.top.opener;
+ runner.verify(history.length, 1,
"history.length of subtest '" + top.document.title + "'.");
- testRunner.scheduleNextTest();
+ runner.scheduleNextTest();
setTimeout(window.close.bind(top), 0);
}
</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/sandboxing/noscript-iframe.html b/tests/wpt/web-platform-tests/html/browsers/sandboxing/noscript-iframe.html
new file mode 100644
index 00000000000..677b5fc83aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/sandboxing/noscript-iframe.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<noscript>PASS</noscript>
diff --git a/tests/wpt/web-platform-tests/html/browsers/sandboxing/sandbox-parse-noscript-ref.html b/tests/wpt/web-platform-tests/html/browsers/sandboxing/sandbox-parse-noscript-ref.html
new file mode 100644
index 00000000000..9cf92768f78
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/sandboxing/sandbox-parse-noscript-ref.html
@@ -0,0 +1,6 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>noscript parsing when sandbox disables scripting</title>
+<iframe srcdoc="PASS" sandbox></iframe>
+<iframe srcdoc="PASS" sandbox></iframe>
+<iframe srcdoc="P<b>AS</b>S" sandbox></iframe>
diff --git a/tests/wpt/web-platform-tests/html/browsers/sandboxing/sandbox-parse-noscript.html b/tests/wpt/web-platform-tests/html/browsers/sandboxing/sandbox-parse-noscript.html
new file mode 100644
index 00000000000..bb7ced0a14b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/sandboxing/sandbox-parse-noscript.html
@@ -0,0 +1,7 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>noscript parsing when sandbox disables scripting</title>
+<link rel=match href=/html/browsers/sandboxing/sandbox-parse-noscript-ref.html>
+<iframe srcdoc="<noscript>PASS</noscript>" sandbox></iframe>
+<iframe src="noscript-iframe.html" sandbox></iframe>
+<iframe srcdoc="<noscript>P<b>AS</b>S</noscript>" sandbox></iframe>
diff --git a/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context.html b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context.html
index ad3a01fd3eb..5e99bb522f1 100644
--- a/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context.html
+++ b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context.html
@@ -44,11 +44,6 @@
assert_equals(doc.referrer, document.URL, "The document's referrer should be its creator document's address.");
assert_equals(iframe.contentWindow.parent.document, document);
}, "Check the document properties corresponding to the creator browsing context");
-
- test(function () {
- assert_equals(iframe.contentWindow.history.length, 1, "The history.length should be 1.");
- }, "Check the history.length of the created browsing context");
-
</script>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements-embedded.js b/tests/wpt/web-platform-tests/html/dom/elements-embedded.js
index 176da29d4f6..d0c5dbcb76b 100644
--- a/tests/wpt/web-platform-tests/html/dom/elements-embedded.js
+++ b/tests/wpt/web-platform-tests/html/dom/elements-embedded.js
@@ -11,6 +11,7 @@ var embeddedElements = {
width: {type: "unsigned long", customGetter: true},
height: {type: "unsigned long", customGetter: true},
referrerPolicy: {type: "enum", keywords: ["", "no-referrer", "no-referrer-when-downgrade", "same-origin", "origin", "strict-origin", "origin-when-cross-origin", "strict-origin-when-cross-origin", "unsafe-url"]},
+ decoding: {type: "enum", keywords: ["async", "sync", "auto"], defaultVal: "auto", invalidVal: "auto"},
// Obsolete
name: "string",
diff --git a/tests/wpt/web-platform-tests/html/dom/elements-forms.js b/tests/wpt/web-platform-tests/html/dom/elements-forms.js
index fc455352578..051bc2087f3 100644
--- a/tests/wpt/web-platform-tests/html/dom/elements-forms.js
+++ b/tests/wpt/web-platform-tests/html/dom/elements-forms.js
@@ -1,17 +1,3 @@
-var inputModeKeywords = [
- "verbatim",
- "latin",
- "latin-name",
- "latin-prose",
- "full-width-latin",
- "kana",
- "kana-name",
- "katakana",
- "numeric",
- "tel",
- "email",
- "url",
-];
var formElements = {
form: {
acceptCharset: {type: "string", domAttrName: "accept-charset"},
@@ -52,7 +38,6 @@ var formElements = {
formNoValidate: "boolean",
formTarget: "string",
height: {type: "unsigned long", customGetter: true},
- inputMode: {type: "enum", keywords: inputModeKeywords},
max: "string",
maxLength: "limited long",
min: "string",
@@ -118,7 +103,6 @@ var formElements = {
cols: {type: "limited unsigned long with fallback", defaultVal: 20},
dirName: "string",
disabled: "boolean",
- inputMode: {type: "enum", keywords: inputModeKeywords},
maxLength: "limited long",
minLength: "limited long",
name: "string",
diff --git a/tests/wpt/web-platform-tests/html/dom/elements-metadata.js b/tests/wpt/web-platform-tests/html/dom/elements-metadata.js
index f30459013cb..8af6a6a67c0 100644
--- a/tests/wpt/web-platform-tests/html/dom/elements-metadata.js
+++ b/tests/wpt/web-platform-tests/html/dom/elements-metadata.js
@@ -12,7 +12,7 @@ var metadataElements = {
rel: "string",
as: {
type: "enum",
- keywords: ["fetch", "audio", "document", "embed", "font", "image", "manifest", "object", "report", "script", "serviceworker", "sharedworker", "style", "track", "video", "worker", "xslt"],
+ keywords: ["fetch", "audio", "document", "embed", "font", "image", "manifest", "object", "report", "script", "sharedworker", "style", "track", "video", "worker", "xslt"],
defaultVal: "",
invalidVal: ""
},
@@ -24,19 +24,6 @@ var metadataElements = {
type: "string",
sizes: "settable tokenlist",
referrerPolicy: {type: "enum", keywords: ["", "no-referrer", "no-referrer-when-downgrade", "same-origin", "origin", "strict-origin", "origin-when-cross-origin", "strict-origin-when-cross-origin", "unsafe-url"]},
- scope: "string",
- workerType: {
- type: "enum",
- keywords: ["classic", "module"],
- defaultVal: "classic",
- invalidVal: "",
- },
- updateViaCache: {
- type: "enum",
- keywords: ["imports", "all", "none"],
- defaultVal: "imports",
- invalidVal: "imports"
- },
// Obsolete
charset: "string",
diff --git a/tests/wpt/web-platform-tests/html/dom/elements-misc.js b/tests/wpt/web-platform-tests/html/dom/elements-misc.js
index 43cdf5f32da..df415aef159 100644
--- a/tests/wpt/web-platform-tests/html/dom/elements-misc.js
+++ b/tests/wpt/web-platform-tests/html/dom/elements-misc.js
@@ -52,7 +52,9 @@ var miscElements = {
},
// Global attributes should exist even on unknown elements
- undefinedelement: {},
+ undefinedelement: {
+ inputMode: {type: "enum", keywords: ["none", "text", "tel", "url", "email", "numeric", "decimal", "search"]},
+ },
};
mergeElements(miscElements);
diff --git a/tests/wpt/web-platform-tests/html/dom/reflection.js b/tests/wpt/web-platform-tests/html/dom/reflection.js
index 337e053d0c8..9a98478b9dc 100644
--- a/tests/wpt/web-platform-tests/html/dom/reflection.js
+++ b/tests/wpt/web-platform-tests/html/dom/reflection.js
@@ -669,8 +669,12 @@ ReflectionTests.reflects = function(data, idlName, idlObj, domName, domObj) {
}
if (data.keywords[i].length > 1) {
- domTests.push(data.keywords[i].slice(1));
- idlTests.push(data.keywords[i].slice(1));
+ var sliced = data.keywords[i].slice(1);
+ // If slicing a value yields another valid value, then skip it since it results in duplicate tests.
+ if (data.keywords.indexOf(sliced) == -1) {
+ domTests.push(sliced);
+ idlTests.push(sliced);
+ }
}
if (data.keywords[i] != data.keywords[i].toLowerCase()) {
diff --git a/tests/wpt/web-platform-tests/html/dom/usvstring-reflection.html b/tests/wpt/web-platform-tests/html/dom/usvstring-reflection.html
new file mode 100644
index 00000000000..c3a79e779e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/usvstring-reflection.html
@@ -0,0 +1,89 @@
+<!doctype html>
+<title>USVString test relate to url</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+// Unpaired surrogate codepoints present in USVString are replaced
+// with U+FFFD. %EF%BF%BD is UTF-8 encoding of U+FFFD.
+'use strict';
+test(() => {
+ location.hash = '\uD999';
+ assert_equals(location.hash, '#%EF%BF%BD');
+}, "location : unpaired surrogate codepoint should be replaced with U+FFFD");
+
+test(() => {
+ var w = window.open("about:blank#\uD800");
+ assert_equals(w.location.hash, '#%EF%BF%BD');
+}, "window.open : unpaired surrogate codepoint should be replaced with U+FFFD");
+
+test(() => {
+ var w = document.open("about:blank#\uD800", "", "");
+ assert_equals(w.location.hash, '#%EF%BF%BD');
+}, "document.open : unpaired surrogate codepoint should be replaced with U+FFFD");
+
+test(() => {
+ var element = document.createElement("a");
+ element.ping = '\uD989';
+ assert_equals(element.ping, '\uFFFD');
+}, "anchor : unpaired surrogate codepoint should be replaced with U+FFFD")
+
+test(() => {
+ var element = document.createElement("area");
+ element.ping = '\uDA99';
+ assert_equals(element.ping, '\uFFFD');
+}, "area : unpaired surrogate codepoint should be replaced with U+FFFD")
+
+test(() => {
+ var element = document.createElement("base");
+ element.href = '\uD989';
+ assert_equals(element.href.endsWith('%EF%BF%BD'), true);
+}, "base : unpaired surrogate codepoint should be replaced with U+FFFD")
+
+test(() => {
+ var src = new EventSource('\uD899');
+ assert_equals(src.url.endsWith('%EF%BF%BD'), true);
+}, "EventSource : unpaired surrogate codepoint should be replaced with U+FFFD")
+
+test(() => {
+ var element = document.createElement("frame");
+ element.src = '\uDCA9';
+ element.longDesc = '\uDCA8';
+ assert_equals(element.src.endsWith('%EF%BF%BD'), true);
+ assert_equals(element.longDesc.endsWith('%EF%BF%BD'), true);
+}, "frame : unpaired surrogate codepoint should be replaced with U+FFFD")
+
+test(() => {
+ var element = document.createElement("iframe");
+ element.src = '\uDC89';
+ element.longDesc = '\uDC88';
+ assert_equals(element.src.endsWith('%EF%BF%BD'), true);
+ assert_equals(element.longDesc.endsWith('%EF%BF%BD'), true);
+}, "iframe : unpaired surrogate codepoint should be replaced with U+FFFD")
+
+test(() => {
+ var element = document.createElement("link");
+ element.href = '\uDB89';
+ assert_equals(element.href.endsWith('%EF%BF%BD'), true);
+}, "link : unpaired surrogate codepoint should be replaced with U+FFFD")
+
+test(() => {
+ var element = document.createElement("source");
+ element.src = '\uDDDD';
+ element.srcset = '\uD800';
+ assert_equals(element.src.endsWith('%EF%BF%BD'), true);
+ assert_equals(element.srcset, '\uFFFD');
+}, "source : unpaired surrogate codepoint should be replaced with U+FFFD")
+
+test(() => {
+ const event = new StorageEvent('storage', {
+ url: window.location.href + '\uD999',
+ });
+ assert_equals(event.url, window.location.href + "\uFFFD");
+}, "storage event : unpaired surrogate codepoint should be replaced with U+FFFD")
+
+test(() => {
+ var wsocket = new EventSource('ws://www.example.com/socketserve\uD899/');
+ assert_true(wsocket.url.endsWith('ws://www.example.com/socketserve%EF%BF%BD/'));
+}, "websocket url : unpaired surrogate codepoint should be replaced with U+FFFD")
+</script>
diff --git a/tests/wpt/web-platform-tests/html/form-elements/the-textarea-element/multiline-placeholder-cr.html b/tests/wpt/web-platform-tests/html/form-elements/the-textarea-element/multiline-placeholder-cr.html
new file mode 100644
index 00000000000..8879ca46479
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/form-elements/the-textarea-element/multiline-placeholder-cr.html
@@ -0,0 +1 @@
+<!doctype html> <html class="reftest-wait"> <meta charset="utf-8"> <title>textarea multiline placeholder (CR)</title> <link rel="help" href="https://html.spec.whatwg.org/multipage/form-elements.html#attr-textarea-placeholder"> <meta name="assert" content="textarea element's placeholder preserves newlines (CR)"> <link rel="match" href="/html/form-elements/the-textarea-element/multiline-placeholder-ref.html"> <link rel="stylesheet" href="support/placeholder.css"> <textarea rows="5" placeholder="this is a multiline placeholder"></textarea> <textarea rows="5" placeholder="this is&#xd;a multiline&#xd;&#xd;placeholder"></textarea> <textarea rows="5" id="dynamic"></textarea> <script> document.querySelector("#dynamic") .setAttribute("placeholder", "this is\ra multiline\r\rplaceholder"); document.documentElement.classList.remove("reftest-wait"); </script> </html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/form-elements/the-textarea-element/multiline-placeholder-crlf.html b/tests/wpt/web-platform-tests/html/form-elements/the-textarea-element/multiline-placeholder-crlf.html
new file mode 100644
index 00000000000..9632ef1bb6c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/form-elements/the-textarea-element/multiline-placeholder-crlf.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<title>textarea multiline placeholder (CRLF)</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/form-elements.html#attr-textarea-placeholder">
+<meta name="assert" content="textarea element's placeholder preserves newlines (CRLF)">
+<link rel="match" href="/html/form-elements/the-textarea-element/multiline-placeholder-ref.html">
+<link rel="stylesheet" href="support/placeholder.css">
+<textarea rows="5" placeholder="this is
+a multiline
+
+placeholder"></textarea>
+<textarea rows="5" placeholder="this is&#xd;&#xa;a multiline&#xd;&#xa;&#xd;&#xa;placeholder"></textarea>
+<textarea rows="5" id="dynamic"></textarea>
+<script>
+ document.querySelector("#dynamic")
+ .setAttribute("placeholder", "this is\r\na multiline\r\n\r\nplaceholder");
+ document.documentElement.classList.remove("reftest-wait");
+</script>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/html/form-elements/the-textarea-element/multiline-placeholder-ref.html b/tests/wpt/web-platform-tests/html/form-elements/the-textarea-element/multiline-placeholder-ref.html
new file mode 100644
index 00000000000..0234ed64c9a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/form-elements/the-textarea-element/multiline-placeholder-ref.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<meta charset="utf-8">
+<link rel="stylesheet" href="support/placeholder.css">
+<textarea rows="5" class="placeholder">this is
+a multiline
+
+placeholder</textarea>
+<textarea rows="5" class="placeholder">this is
+a multiline
+
+placeholder</textarea>
+<textarea rows="5" class="placeholder">this is
+a multiline
+
+placeholder</textarea>
diff --git a/tests/wpt/web-platform-tests/html/form-elements/the-textarea-element/multiline-placeholder.html b/tests/wpt/web-platform-tests/html/form-elements/the-textarea-element/multiline-placeholder.html
new file mode 100644
index 00000000000..00bb9696d1a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/form-elements/the-textarea-element/multiline-placeholder.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<title>textarea multiline placeholder</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/form-elements.html#attr-textarea-placeholder">
+<meta name="assert" content="textarea element's placeholder preserves newlines">
+<link rel="match" href="/html/form-elements/the-textarea-element/multiline-placeholder-ref.html">
+<link rel="stylesheet" href="support/placeholder.css">
+<textarea rows="5" placeholder="this is
+a multiline
+
+placeholder"></textarea>
+<textarea rows="5" placeholder="this is&#xa;a multiline&#xa;&#xa;placeholder"></textarea>
+<textarea rows="5" id="dynamic"></textarea>
+<script>
+ document.querySelector("#dynamic")
+ .setAttribute("placeholder", "this is\na multiline\n\nplaceholder");
+ document.documentElement.classList.remove("reftest-wait");
+</script>
+</html>
+
+
diff --git a/tests/wpt/web-platform-tests/html/form-elements/the-textarea-element/support/placeholder.css b/tests/wpt/web-platform-tests/html/form-elements/the-textarea-element/support/placeholder.css
new file mode 100644
index 00000000000..9aaed05c86a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/form-elements/the-textarea-element/support/placeholder.css
@@ -0,0 +1,6 @@
+textarea.placeholder,
+textarea::placeholder {
+ /* revert browser styling of the placeholder */
+ color: GrayText; /* blink/webkit use colour */
+ opacity: 1.0; /* gecko uses opacity */
+}
diff --git a/tests/wpt/web-platform-tests/html/input/the-placeholder-attribute/multiline-cr.html b/tests/wpt/web-platform-tests/html/input/the-placeholder-attribute/multiline-cr.html
new file mode 100644
index 00000000000..4184ab2c5ce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/input/the-placeholder-attribute/multiline-cr.html
@@ -0,0 +1 @@
+<!doctype html> <html class="reftest-wait"> <meta charset="utf-8"> <title>input multiline placeholder (CRLF)</title> <link rel="help" href="https://html.spec.whatwg.org/multipage/input.html#the-placeholder-attribute"> <meta name="assert" content="input element's placeholder strips newlines (CRLF)"> <link rel="match" href="/html/input/the-placeholder-attribute/multiline-ref.html"> <input placeholder="this is a multiline placeholder"> <input placeholder="this is&#xd;a multiline&#xd;&#xd;placeholder"> <input id="dynamic"> <script> document.querySelector("#dynamic") .setAttribute("placeholder", "this is\ra multiline\r\rplaceholder"); document.documentElement.classList.remove("reftest-wait"); </script> </html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/input/the-placeholder-attribute/multiline-crlf.html b/tests/wpt/web-platform-tests/html/input/the-placeholder-attribute/multiline-crlf.html
new file mode 100644
index 00000000000..50c91fbe35e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/input/the-placeholder-attribute/multiline-crlf.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<title>input multiline placeholder (CRLF)</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/input.html#the-placeholder-attribute">
+<meta name="assert" content="input element's placeholder strips newlines (CRLF)">
+<link rel="match" href="/html/input/the-placeholder-attribute/multiline-ref.html">
+<input placeholder="this is
+a multiline
+
+placeholder">
+<input placeholder="this is&#xd;&#xa;a multiline&#xd;&#xa;&#xd;&#xa;placeholder">
+<input id="dynamic">
+<script>
+ document.querySelector("#dynamic")
+ .setAttribute("placeholder", "this is\r\na multiline\r\n\r\nplaceholder");
+ document.documentElement.classList.remove("reftest-wait");
+</script>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/input/the-placeholder-attribute/multiline-ref.html b/tests/wpt/web-platform-tests/html/input/the-placeholder-attribute/multiline-ref.html
new file mode 100644
index 00000000000..2812f86e1e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/input/the-placeholder-attribute/multiline-ref.html
@@ -0,0 +1,5 @@
+<!doctype html>
+<meta charset=utf-8>
+<input placeholder="this isa multilineplaceholder">
+<input placeholder="this isa multilineplaceholder">
+<input placeholder="this isa multilineplaceholder">
diff --git a/tests/wpt/web-platform-tests/html/input/the-placeholder-attribute/multiline.html b/tests/wpt/web-platform-tests/html/input/the-placeholder-attribute/multiline.html
new file mode 100644
index 00000000000..2d7102bd4ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/input/the-placeholder-attribute/multiline.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<title>input multiline placeholder</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/input.html#the-placeholder-attribute">
+<meta name="assert" content="input element's placeholder strips newlines">
+<link rel="match" href="/html/input/the-placeholder-attribute/multiline-ref.html">
+<input placeholder="this is
+a multiline
+
+placeholder">
+<input placeholder="this is&#xa;a multiline&#xa;&#xa;placeholder">
+<input id="dynamic">
+<script>
+ document.querySelector("#dynamic")
+ .setAttribute("placeholder", "this is\na multiline\n\nplaceholder");
+ document.documentElement.classList.remove("reftest-wait");
+</script>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/crossOrigin.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/crossOrigin.html
new file mode 100644
index 00000000000..e29f2b0fbcd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/crossOrigin.html
@@ -0,0 +1,60 @@
+<!doctype html>
+<title>HTMLMediaElement.crossOrigin</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var video = document.createElement('video');
+ assert_true('crossOrigin' in video);
+});
+test(function(){
+ var video = document.createElement('video');
+ assert_equals(video.crossOrigin, null);
+}, document.title+', content attribute missing');
+test(function(){
+ var video = document.createElement('video');
+ video.setAttribute('crossorigin', 'foo');
+ assert_equals(video.crossOrigin, 'anonymous');
+}, document.title+', content attribute invalid value');
+test(function(){
+ var video = document.createElement('video');
+ video.setAttribute('crossorigin', '');
+ assert_equals(video.crossOrigin, 'anonymous');
+}, document.title+', content attribute empty string');
+test(function(){
+ var video = document.createElement('video');
+ video.setAttribute('crossorigin', 'ANONYMOUS');
+ assert_equals(video.crossOrigin, 'anonymous');
+}, document.title+', content attribute uppercase ANONYMOUS');
+test(function(){
+ var video = document.createElement('video');
+ video.setAttribute('crossorigin', 'use-credentials');
+ assert_equals(video.crossOrigin, 'use-credentials');
+}, document.title+', content attribute use-credentials');
+test(function(){
+ var video = document.createElement('video');
+ video.crossOrigin = '';
+ assert_equals(video.getAttribute('crossorigin'), '');
+}, document.title+', setting to empty string');
+test(function(){
+ var video = document.createElement('video');
+ video.crossOrigin = null;
+ assert_false(video.hasAttribute('crossorigin'));
+}, document.title+', setting to null');
+test(function(){
+ var video = document.createElement('video');
+ video.crossOrigin = 'foo';
+ assert_equals(video.getAttribute('crossorigin'), 'foo');
+}, document.title+', setting to invalid value');
+test(function(){
+ var video = document.createElement('video');
+ video.crossOrigin = 'ANONYMOUS';
+ assert_equals(video.getAttribute('crossorigin'), 'ANONYMOUS');
+}, document.title+', setting to uppercase ANONYMOUS');
+test(function(){
+ var video = document.createElement('video');
+ video.crossOrigin = 'use-credentials';
+ assert_equals(video.getAttribute('crossorigin'), 'use-credentials');
+}, document.title+', setting to use-credentials');
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/readyState.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/readyState.html
index e18f21934de..cde21e694e5 100644
--- a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/readyState.html
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/readyState.html
@@ -8,4 +8,11 @@ test(function(){
var track = document.createElement('track');
assert_equals(track.readyState, 0);
}, document.title + ' default value');
+
+test(function(){
+ assert_equals(HTMLTrackElement.NONE, 0);
+ assert_equals(HTMLTrackElement.LOADING, 1);
+ assert_equals(HTMLTrackElement.LOADED, 2);
+ assert_equals(HTMLTrackElement.ERROR, 3);
+}, document.title + ' values');
</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/constructor.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/constructor.html
new file mode 100644
index 00000000000..c066f60399b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/constructor.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>TextTrackCue constructor</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <script>
+ test(function()
+ {
+ assert_not_equals(TextTrackCue, VTTCue);
+ }, "TextTrackCue and VTTCue are separate interfaces");
+ test(function()
+ {
+ assert_throws(new TypeError(), function()
+ {
+ new TextTrackCue(0, 0, "");
+ });
+ }, "TextTrackCue constructor should not be supported");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-positioning-bad.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-positioning-bad.vtt
new file mode 100644
index 00000000000..ff4c3fb5cd4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-positioning-bad.vtt
@@ -0,0 +1,20 @@
+WEBVTT
+Either one or both of positioning and alignment values are invalid.
+
+1
+00:00:00.000 --> 00:00:30.500 position:10% align: start
+Bear is Coming!!!!!
+Positioning on the left bottom, middle aligned,
+because the alignment is mistyped.
+
+2
+00:00:31.000 --> 00:00:45.500 position:200% align:middle
+I said Bear is coming!!!!
+Positioning on the bottom middle, middle aligned,
+because the positioning is off.
+
+3
+00:01:01.000 --> 00:02:00.500 position:-80% align:ends
+I said Bear is coming now!!!!
+Positioning on the bottom middle, middle aligned,
+because both the alignment and positioning don't apply.
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-positioning.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-positioning.vtt
new file mode 100644
index 00000000000..a6e6af2ef96
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-positioning.vtt
@@ -0,0 +1,20 @@
+WEBVTT
+Cues should position at different horizontal positions with different alignments.
+
+1
+00:00:00.000 --> 00:00:30.500 position:10% align:start
+Bear is Coming!!!!!
+Positioning on the left bottom, start aligned, and
+first character rendering position is at 10% of width.
+
+2
+00:00:31.000 --> 00:00:45.500 position:20% align:middle
+I said Bear is coming!!!!
+Positioning on the bottom left, middle aligned, and
+middle character rendering position of each line is at 20% of width.
+
+3
+00:01:01.000 --> 00:02:00.500 align:end position:80%
+I said Bear is coming now!!!!
+Positioning on the bottom right, end aligned, and
+last character rendering position of each line is at 80% of width.
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-text-line-position-bad.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-text-line-position-bad.vtt
new file mode 100644
index 00000000000..b196f13a207
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-text-line-position-bad.vtt
@@ -0,0 +1,21 @@
+WEBVTT
+One or more of line/text positioning and alignment values are invalid (settings are ignored).
+
+1
+00:00:00.000 --> 00:00:30.500 position: 0% align: start line: 0%
+Bear is Coming!!!!!
+None of the cue settings will be applied, just the default.
+
+2
+00:00:31.000 --> 00:00:01.500 position:0% align:end line:-30%
+I said Bear is coming!!!!
+The line position setting is ignored.
+No text is visible though because it's off-screen at position
+0 and the last character is at position 0%.
+
+3
+00:01:01.000 --> 00:01:30.000 line:-3 align:middler position:60%
+I said Bear is coming now!!!!
+Positioning on line 3 from the viewport bottom, middle aligned,
+with middle character of cue at 60% width.
+The alignment is ignored.
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-text-line-position.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-text-line-position.vtt
new file mode 100644
index 00000000000..dd3a6debb89
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/align-text-line-position.vtt
@@ -0,0 +1,28 @@
+WEBVTT
+Cues with valid alignment, line and text position settings.
+
+1
+00:00:00.000 --> 00:00:15.000 position:10% align:start line:0%
+Bear is Coming!!!!!
+Positioning on the top of the viewport at 10% horizontally,
+start aligned.
+
+00:00:15.500 --> 00:00:30.500 line:0 align:start
+Bear is Coming!!!!!
+This is line 0, middle aligned, first character at 50% width.
+
+2
+00:00:31.000 --> 00:00:45.500 position:80% line:80%
+I said Bear is coming!!!!
+Middle aligned, middle of cue's character is at 80% width and 80% height.
+
+00:00:46.000 --> 00:01:00.500 line:5 align:end position:30%
+I said Bear is coming!!!!
+This is line 6 from the top of the video viewport,
+end aligned with last character at 30% of viewport width.
+
+3
+00:01:01.000 --> 00:01:30.000 line:-3 align:middle position:60%
+I said Bear is coming now!!!!
+Positioning on line 3 from the viewport bottom, middle aligned,
+with middle character of cue at 60% width.
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/alignment-bad.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/alignment-bad.vtt
new file mode 100644
index 00000000000..5beb376f450
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/alignment-bad.vtt
@@ -0,0 +1,22 @@
+WEBVTT
+Cue alignment may only be start, middle, or end. These are all misspelled and so will default to middle.
+
+1
+00:00:00.000 --> 00:00:30.500 align:starta
+Bear is Coming!!!!!
+Erroneous alignment value -> middle.
+
+2
+00:00:31.000 --> 00:01:00.500 align:-start
+I said Bear is coming!!!!
+Erroneous alignment value --> middle.
+
+3
+00:01:01.000 --> 00:02:00.500 align: end
+I said Bear is coming now!!!!
+Erroneous alignment value with surplus whitespace --> middle.
+
+4
+00:02:01.000 --> 100:20:00.500 align:piugjk
+I said Bear is coming now!!!!
+Erroneous alignment value -> middle.
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/alignment-ltr.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/alignment-ltr.vtt
new file mode 100644
index 00000000000..673b29ac851
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/alignment-ltr.vtt
@@ -0,0 +1,22 @@
+WEBVTT
+Cue alignment may be start, middle, or end (default is middle).
+
+1
+00:00:00.000 --> 00:00:30.500 align:start
+الدب قادم!!!!!
+بدء محاذاته.
+
+2
+00:00:31.000 --> 00:01:00.500 align:middle
+قلت الدب قادم!!
+محاذاة الوسط.
+
+3
+00:01:01.000 --> 00:02:00.500 align:end
+قلت الدب قادم الآن!!
+محاذاة الغاية.
+
+4
+00:02:01.000 --> 100:20:00.500
+قلت الدب قادم الآن!!
+الافتراضية هي محاذاة الوسط. \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/alignment.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/alignment.vtt
new file mode 100644
index 00000000000..ad7792f7724
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/alignment.vtt
@@ -0,0 +1,22 @@
+WEBVTT
+Cue alignment may be start, middle, or end (default is middle).
+
+1
+00:00:00.000 --> 00:00:30.500 align:start
+Bear is Coming!!!!!
+Start align.
+
+2
+00:00:31.000 --> 00:01:00.500 align:middle
+I said Bear is coming!!!!
+Middle align.
+
+3
+00:01:01.000 --> 00:02:00.500 align:end
+I said Bear is coming now!!!!
+End align.
+
+4
+00:02:01.000 --> 100:20:00.500
+I said Bear is coming now!!!!
+Default is middle alignment. \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/bom.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/bom.vtt
new file mode 100644
index 00000000000..0c8de32bcb7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/bom.vtt
@@ -0,0 +1,10 @@
+WEBVTT FILE
+A BOM character at the start of a file should be ignored.
+
+1
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+
+2
+00:00:31.000 --> 00:20:00.500
+I said Bear is coming!!!! \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions-fast.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions-fast.vtt
new file mode 100644
index 00000000000..cd138fd32af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions-fast.vtt
@@ -0,0 +1,13 @@
+WEBVTT
+
+1
+00:00:00.000 --> 00:00:00.300
+Lorem
+
+2
+00:00:00.300 --> 00:00:00.700
+ipsum
+
+3
+00:00:01.200 --> 00:00:01.500
+dolor
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions-gaps.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions-gaps.vtt
new file mode 100644
index 00000000000..44c74665c25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions-gaps.vtt
@@ -0,0 +1,18 @@
+WEBVTT
+
+1
+00:00:01.000 --> 00:00:02.000
+Lorem ipsum dolor sit amet,
+
+2
+00:00:03.000 --> 00:00:04.000
+consectetuer adipiscing elit,
+
+3
+00:00:05.000 --> 00:00:06.000
+sed diam nonummy nibh euismod tincidunt
+
+4
+00:00:07.000 --> 00:00:08.000
+ut laoreet dolore magna aliquam erat volutpat.
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions-html.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions-html.vtt
new file mode 100644
index 00000000000..0730f8bc40b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions-html.vtt
@@ -0,0 +1,18 @@
+WEBVTT
+
+1
+00:00:00.000 --> 00:00:01.000
+Lorem <b>ipsum</b> <u>dolor</u> <i.sit>sit</i> amet,
+
+2
+00:00:03.000 --> 00:00:04.000
+consectetuer adipiscing elit,
+
+3
+00:00:05.000 --> 00:00:06.000
+sed diam nonummy nibh euismod tincidunt
+
+4
+00:00:07.000 --> 00:00:08.000
+ut laoreet dolore magna aliquam erat volutpat.
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions.vtt
new file mode 100644
index 00000000000..787c4308687
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/captions.vtt
@@ -0,0 +1,18 @@
+WEBVTT
+
+1
+00:00:00.000 --> 00:00:01.000
+Lorem
+
+2
+00:00:01.000 --> 00:00:02.000
+ipsum
+
+3
+00:00:02.000 --> 00:00:03.000
+dolor
+
+4
+00:00:03.000 --> 00:00:04.000
+sit
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/class-bad.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/class-bad.vtt
new file mode 100644
index 00000000000..650ea2c4960
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/class-bad.vtt
@@ -0,0 +1,17 @@
+WEBVTT
+Invalid <c> class markup.
+
+1
+00:00:00.000 --> 00:00:30.500 align:start position:20%
+<c .black>Bear is Coming!!!!!</c>
+The space signified an annotation start.
+
+2
+00:00:31.000 --> 00:01:00.500 align:start position:20%
+<c.red&large>I said Bear is coming!!!!</c>
+Probably should only allow characters that CSS allows in class names.
+
+3
+00:01:01.000 --> 00:02:00.500 align:start position:20%
+I said <c.9red.upper+case>Bear is coming now</c>!!!!
+Probably should only allow characters that CSS allows in class names.
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/class.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/class.vtt
new file mode 100644
index 00000000000..ea3ef623f59
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/class.vtt
@@ -0,0 +1,14 @@
+WEBVTT
+Cue text fragment with <c> class markup is mapped to HTML <span> element with CSS classes.
+
+1
+00:00:00.000 --> 00:00:30.500 align:start position:20%
+<c.black>Bear is Coming!!!!!</c>
+
+2
+00:00:31.000 --> 00:01:00.500 align:start position:20%
+<c.green>I said Bear is coming!!!!</c>
+
+3
+00:01:01.000 --> 00:02:00.500 align:start position:20%
+I said <c.red.uppercase>Bear is coming now</c>!!!!
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-id-error.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-id-error.vtt
new file mode 100644
index 00000000000..2b5db0c1da4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-id-error.vtt
@@ -0,0 +1,14 @@
+WEBVTT
+Cue identifiers cannot contain the string "-->".
+
+-->random_id
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+
+another random identifier-->
+00:00:31.000 --> 00:01:00.500
+I said Bear is coming!!!!
+
+identifier-->too
+00:01:01.000 --> 00:20:00.500
+I said Bear is coming now!!!! \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-id.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-id.vtt
new file mode 100644
index 00000000000..39021186208
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-id.vtt
@@ -0,0 +1,18 @@
+WEBVTT
+Random text is accepted for cue identifiers.
+
+random_id
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+
+another random identifier
+00:00:31.000 --> 00:01:00.500
+I said Bear is coming!!!!
+
+identifier--too
+00:01:01.000 --> 00:02:00.500
+I said Bear is coming now!!!!
+
+identifier--too
+00:02:01.000 --> 00:03:00.500
+Duplicate identifier \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-no-id-error.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-no-id-error.vtt
new file mode 100644
index 00000000000..111bae6344b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-no-id-error.vtt
@@ -0,0 +1,14 @@
+WEBVTT
+Cue identifiers cannot contain "-->". Whole cue is ignored.
+
+-->
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+
+-->
+00:00:31.000 --> 00:01:00.500
+I said Bear is coming!!!!
+
+-->
+00:01:01.000 --> 00:20:00.500
+I said Bear is coming now!!!! \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-no-id.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-no-id.vtt
new file mode 100644
index 00000000000..0d52a70ee4b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-no-id.vtt
@@ -0,0 +1,11 @@
+WEBVTT
+Cues don't have to have identifiers.
+
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+
+00:00:31.000 --> 00:01:00.500
+I said Bear is coming!!!!
+
+00:01:01.000 --> 00:20:00.500
+I said Bear is coming now!!!! \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-cuetext.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-cuetext.vtt
new file mode 100644
index 00000000000..88f56cceca8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-cuetext.vtt
@@ -0,0 +1,6 @@
+WEBVTT
+
+00:00.000 --> 00:01.000
+Valid cue 1
+00:02.000 --> 00:03.000
+Valid cue 2
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-header.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-header.vtt
new file mode 100644
index 00000000000..205955e3e49
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-header.vtt
@@ -0,0 +1,6 @@
+WEBVTT
+00:00.000 --> 00:01.000
+Valid cue 1
+
+00:02.000 --> 00:03.000
+Valid cue 2
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-note.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-note.vtt
new file mode 100644
index 00000000000..56defcc48b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-recovery-note.vtt
@@ -0,0 +1,9 @@
+WEBVTT
+
+00:00.000 --> 00:01.000
+Valid cue 1
+
+NOTE about something
+NOTE or something else - maybe an identifier
+00:02.000 --> 00:03.000
+Valid cue 2
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-align-bad.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-align-bad.vtt
new file mode 100644
index 00000000000..5e4a61a5e40
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-align-bad.vtt
@@ -0,0 +1,18 @@
+WEBVTT
+Either size or alignment are invalid.
+
+1
+00:00:00.000 --> 00:00:30.500 size:100% align:@start
+Bear is Coming!!!!!
+Box for the cue is 100% of the video viewport width, alignment is ignored.
+
+2
+00:00:31.000 --> 00:01:00.500 size:-10% align:end
+I said Bear is coming!!!!
+Box for the cue is as big as the text, no line wrapping,
+(except if viewport is too small) and end aligned.
+
+3
+00:01:01.000 --> 00:02:00.500 size:110% align:@end
+I said Bear is coming now!!!!
+Both cue size and alignment are ignored.
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-align.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-align.vtt
new file mode 100644
index 00000000000..6d365365396
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-align.vtt
@@ -0,0 +1,19 @@
+WEBVTT
+Valid cue size with alignment settings.
+
+1
+00:00:00.000 --> 00:00:30.500 size:100% align:start
+Bear is Coming!!!!!
+Box for the cue is 100% of the video viewport width
+and because of the start align, all text is left aligned on the video viewport.
+
+2
+00:00:31.000 --> 00:01:00.500 size:10% align:end
+I said Bear is coming!!!!
+Box for the cue is 10% of the video viewport width, which will mean that automatic line wrapping will happen
+and the text is aligned to the end.
+
+3
+00:01:01.000 --> 00:02:00.500 size:0% align:middle
+I said Bear is coming now!!!!
+Cue text box size of 0 is acceptable, even if not visible.
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-bad.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-bad.vtt
new file mode 100644
index 00000000000..700600d7a79
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size-bad.vtt
@@ -0,0 +1,17 @@
+WEBVTT
+Invalid cue sizes (all settings are ignored).
+
+1
+00:00:00.000 --> 00:00:30.500 size: 50%
+Bear is Coming!!!!!
+Cue size setting doesn't parse and is ignored.
+
+2
+00:00:31.000 --> 00:01:00.500 size:-10%
+I said Bear is coming!!!!
+Negative cue size setting is not acceptable and is ignored.
+
+3
+00:01:01.000 --> 00:02:00.500 size:4000%
+I said Bear is coming now!!!!
+Cue size beyond 100% is not acceptable and is ignored.
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size.vtt
new file mode 100644
index 00000000000..017d59a18bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cue-size.vtt
@@ -0,0 +1,19 @@
+WEBVTT
+Valid cue size values.
+
+1
+00:00:00.000 --> 00:00:30.500 size:100%
+Bear is Coming!!!!!
+Box for the cue is 100% of the video viewport width,
+exemplified through background color,
+even if the text needs less.
+
+2
+00:00:31.000 --> 00:01:00.500 size:10%
+I said Bear is coming!!!!
+Box for the cue is 10% of the video viewport width, which will mean that automatic line wrapping will happen.
+
+3
+00:01:01.000 --> 00:02:00.500 size:0%
+I said Bear is coming now!!!!
+Cue text box size of 0 is acceptable, even if not visible.
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues-no-separation.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues-no-separation.vtt
new file mode 100644
index 00000000000..9062c67edee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues-no-separation.vtt
@@ -0,0 +1,11 @@
+WEBVTT
+Cues must be separated by at least one blank line, otherwise treated like one big cue.
+
+1
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+2
+00:00:31.000 --> 00:01:00.500
+I said Bear is coming!!!!
+00:01:01.000 --> 100:20:00.500
+I said Bear is coming now!!!! \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues-overlapping.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues-overlapping.vtt
new file mode 100644
index 00000000000..3f035d331f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues-overlapping.vtt
@@ -0,0 +1,14 @@
+WEBVTT
+Cues that have overlapping time ranges.
+
+1
+00:00:01.000 --> 00:00:06.000
+Bear is Coming!!!!!
+
+2
+00:00:01.500 --> 00:00:05.000
+I said Bear is coming!!!!
+
+3
+00:00:02.000 --> 00:00:05.000
+I said Bear is coming now!!!! \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues.vtt
new file mode 100644
index 00000000000..125ed667855
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/cues.vtt
@@ -0,0 +1,17 @@
+WEBVTT
+Cues may be separated by one or more blank lines.
+
+1
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+
+
+2
+00:00:31.000 --> 00:01:00.500
+I said Bear is coming!!!!
+
+
+
+3
+00:01:01.000 --> 100:20:00.500
+I said Bear is coming now!!!! \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/default-styles.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/default-styles.vtt
new file mode 100644
index 00000000000..d890ca3f71a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/default-styles.vtt
@@ -0,0 +1,19 @@
+WEBVTT
+
+COMMENT-->
+this is a comment, that will parse as part of the header;
+the STYLE and DEFAULTS below are parsed as invalid cues
+
+STYLE-->
+::cue(.narration) { color: blue; }
+
+DEFAULTS -->
+line:-1 align:middle size:50%
+
+1
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+
+2
+00:00:31.000 --> 00:20:00.500
+I said Bear is coming!!!! \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/degenerate-cues.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/degenerate-cues.vtt
new file mode 100644
index 00000000000..c04390420f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/degenerate-cues.vtt
@@ -0,0 +1,5 @@
+WEBVTT
+
+00:00.000 --> 00:01.000
+00:02.000 --> 00:03.000
+00:04.000 --> 00:05.000
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/empty-cue.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/empty-cue.vtt
new file mode 100644
index 00000000000..dbfde34b697
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/empty-cue.vtt
@@ -0,0 +1,11 @@
+WEBVTT
+Empty cues should not be discarded.
+
+1
+00:00:00.000 --> 00:00:30.500 align:start position:20%
+
+2
+00:00:31.000 --> 00:01:00.500 align:start position:20%
+
+3
+00:01:01.000 --> 00:02:00.500 align:start position:20%
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/entities-wrong.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/entities-wrong.vtt
new file mode 100644
index 00000000000..f45fee4793f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/entities-wrong.vtt
@@ -0,0 +1,15 @@
+WEBVTT
+Invalid use of < and > characters.
+
+2
+00:00:31.000 --> 00:01:00.500 align:start position:20%
+This cue has a less than < character.
+It turns everything from there on into an annotation
+for an empty tag and ends only at the next &gt; or &amp; character.
+
+
+3
+00:01:01.000 --> 00:02:00.500 align:start position:20%
+This cue has a greater than > character.
+Since it's not related to a &lt; character,
+it's just interpreted as text.
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/entities.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/entities.vtt
new file mode 100644
index 00000000000..a8817954a60
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/entities.vtt
@@ -0,0 +1,30 @@
+WEBVTT
+Cue content with escape characters for &, <, >, LRM, RLM and non-breaking space.
+
+1
+00:00:00.000 --> 00:00:30.500 align:start position:20%
+This cue has an ampersand &amp; character.
+
+2
+00:00:31.000 --> 00:01:00.500 align:start position:20%
+This cue has a less than &lt; character.
+
+3
+00:01:01.000 --> 00:02:00.500 align:start position:20%
+This cue has a greater than &gt; character.
+
+4
+00:02:01.000 --> 00:02:30.500 align:start position:20%
+This cue has a Left-to-Right Mark &lrm;.
+
+5
+00:02:31.000 --> 00:03:00.500 align:start position:20%
+This cue has a Right-to-Left Mark &rlm;.
+
+6
+00:03:01.000 --> 00:03:30.500 align:start position:20%
+This cue has a non-breaking space &nbsp;.
+
+7
+00:03:31.000 --> 00:04:00.500
+This & is parsed to the same as &amp;.
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/interspersed-non-cue.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/interspersed-non-cue.vtt
new file mode 100644
index 00000000000..c825ab32e2e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/interspersed-non-cue.vtt
@@ -0,0 +1,9 @@
+WEBVTT
+
+00:00.000 --> 00:01.000
+First
+
+Stray Id or other non-cue content
+
+00:02.000 --> 00:03.000
+Second
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/iso2022jp3.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/iso2022jp3.vtt
new file mode 100644
index 00000000000..10a16243864
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/iso2022jp3.vtt
@@ -0,0 +1,10 @@
+WEBVTT FILE
+Different encodings (iconv) should not be recognized as WebVTT a file.
+
+1
+00:00:00.000 --> 00:00:30.500
+$B7J5$H=CG(B
+
+2
+00:00:31.000 --> 00:20:00.500
+$BEENOITB-(B
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/large-timestamp.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/large-timestamp.vtt
new file mode 100644
index 00000000000..e6c18ce3bd6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/large-timestamp.vtt
@@ -0,0 +1,5 @@
+WEBVTT
+
+1
+1234567:00:00.000 --> 1234567890:00:00.000
+A very long cue.
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/line-position-bad.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/line-position-bad.vtt
new file mode 100644
index 00000000000..3d52175729d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/line-position-bad.vtt
@@ -0,0 +1,30 @@
+WEBVTT
+Invalid positioning values (all settings are ignored).
+
+1
+00:00:00.000 --> 00:00:15.000 line:-0%
+Bear is Coming!!!!!
+Negative percentages are not allowed.
+Line position is ignored.
+
+2
+00:00:31.000 --> 00:00:45.500 line:+50%
+I said Bear is coming!!!!
+Non-numbers are not allowed.
+Line position is ignored.
+
+00:00:46.000 --> 00:01:00.500 line:+5
+I said Bear is coming!!!!
+Plus sign is not allowed.
+Line position is ignored.
+
+3
+00:01:01.000 --> 00:01:30.000 line:10%0%
+I said Bear is coming now!!!!
+Doesn't parse into a percentage.
+Line position is ignored.
+
+00:01:31.000 --> 00:02:00.500 line:-10l
+I said Bear is coming now!!!!
+Doesn't parse into a number.
+Line position is ignored.
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/line-position.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/line-position.vtt
new file mode 100644
index 00000000000..82f7e2a5234
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/line-position.vtt
@@ -0,0 +1,37 @@
+WEBVTT
+Cues with valid vertical line positioning values.
+
+1
+00:00:00.000 --> 00:00:15.000 line:0%
+Bear is Coming!!!!!
+Positioning on the top of the viewport, in the middle.
+
+00:00:15.500 --> 00:00:30.500 line:0
+Bear is Coming!!!!!
+This is line 0.
+Positioning on the top of the viewport, in the middle.
+
+2
+00:00:31.000 --> 00:00:45.500 line:50%
+I said Bear is coming!!!!
+Positioning on the center of the video.
+
+
+00:00:46.000 --> 00:01:00.500 line:5
+I said Bear is coming!!!!
+This is line 6 from the top of the video viewport.
+
+3
+00:01:01.000 --> 00:01:30.000 line:100%
+I said Bear is coming now!!!!
+Positioning on the bottom middle.
+
+00:01:31.000 --> 00:02:00.500 line:-1
+I said Bear is coming now!!!!
+This is the first line at the bottom of the video viewport.
+Positioning on the bottom middle. Only 1 line shows.
+
+00:02:01.000 --> 00:02:30.000 line:500
+I said Bear is coming now!!!!
+This is legal,
+even though the line will likely not be within the video viewport.
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/markup-bad.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/markup-bad.vtt
new file mode 100644
index 00000000000..4ff7add2d72
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/markup-bad.vtt
@@ -0,0 +1,22 @@
+WEBVTT
+Cue text has invalid markup of <b>, <i>, <u>, <rt> and <ruby>. Has a bad effect on the remainder of the cue.
+
+1
+00:00:00.000 --> 00:00:15.000 align:start position:20%
+The following bear starts bold but end is broken:
+<b>Bear</ b> is Coming!!!!!
+
+00:00:15.500 --> 00:00:30.500 align:start position:20%
+The following bear is not in italics but the markup is removed:
+< i>Bear</i> is Coming!!!!!
+
+2
+00:00:31.000 --> 00:01:00.500 align:start position:20%
+The following bear is not underlined and markup is removed:
+I said < u >Bear</u> is coming!!!!
+
+3
+00:01:01.000 --> 00:01:30.000 align:start position:20%
+The following bear is not ruby annotated and markup is removed:
+I said <ru by>Bear<rt>bear with me</rt></ruby> is coming!!!!
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/markup.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/markup.vtt
new file mode 100644
index 00000000000..252a599b5fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/markup.vtt
@@ -0,0 +1,22 @@
+WEBVTT
+Cues with <b>, <i>, <u>, <rt> and <ruby> tags (all valid).
+
+1
+00:00:00.000 --> 00:00:15.000 align:start position:20%
+The following bear is bold:
+<b>Bear</b> is Coming!!!!!
+
+00:00:15.500 --> 00:00:30.500 align:start position:20%
+The following bear is in italics and has a class of "larger":
+<i.larger>Bear</i> is Coming!!!!!
+
+2
+00:00:31.000 --> 00:01:00.500 align:start position:20%
+The following bear is underlined even though the element has a blank:
+I said <u >Bear</u> is coming!!!!
+
+3
+00:01:01.000 --> 00:01:30.000 align:start position:20%
+The following bear is ruby annotated:
+I said <ruby>Bear<rt>bear with me</rt></ruby> is coming!!!!
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/metadata-area.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/metadata-area.vtt
new file mode 100644
index 00000000000..255298aeb01
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/metadata-area.vtt
@@ -0,0 +1,14 @@
+WEBVTT
+This is where metadata would go and these lines should be skipped.
+author = silviapf@google.com
+COMMENT-->
+this is a comment, that will parse as part of the header;
+the STYLE and DEFAULTS below are parsed as invalid cues
+
+1
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+
+2
+00:00:31.000 --> 00:20:00.500
+I said Bear is coming!!!! \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/metadata.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/metadata.vtt
new file mode 100644
index 00000000000..03d8cf4a1c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/metadata.vtt
@@ -0,0 +1,38 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:01.000
+Lorem ipsum dolor sit amet,
+
+00:00:02.000 --> 00:00:03.000
+consectetuer adipiscing elit,
+
+00:00:04.000 --> 00:00:05.000
+sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
+
+00:00:06.000 --> 00:00:07.000
+Ut wisi enim ad minim veniam,
+
+00:00:08.000 --> 00:00:09.000
+quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
+
+00:00:10.000 --> 00:00:11.000
+Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat,
+
+00:00:12.000 --> 00:00:13.000
+vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio
+
+00:00:14.000 --> 00:00:15.000
+dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
+
+00:00:16.000 --> 00:00:17.000
+Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id
+
+00:00:18.000 --> 00:00:19.000
+quod mazim placerat facer possim assum.
+
+00:00:20.000 --> 00:00:21.000
+Typi non habent claritatem insitam;
+
+00:00:22.000 --> 00:00:23.000
+est usus legentis in iis qui facit eorum claritatem.
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/missed-cues.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/missed-cues.vtt
new file mode 100644
index 00000000000..36e8366e908
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/missed-cues.vtt
@@ -0,0 +1,31 @@
+WEBVTT
+Events should be triggered for missed (skipped) cues during normal playback.
+
+1
+00:00:00.000 --> 00:00:01.500 align:start position:20%
+Bear is Coming!!!!!
+And what kind of a bear it is - just have look.
+
+2
+00:00:02.000 --> 00:00:02.500 align:start position:20%
+I said Bear is coming!!!!
+
+3
+00:00:05.500 --> 00:00:05.501 align:start position:20%
+I said Bear is coming now!!!!
+
+4
+00:00:05.700 --> 00:00:05.701 align:start position:20%
+This is the second missed cue in the test.
+
+5
+00:00:05.800 --> 00:00:05.800 align:start position:20%
+Third missed cue - zero-length cue.
+
+6
+00:00:05.850 --> 00:00:05.851 align:start position:20%
+Fourth missed cue.
+
+7
+00:00:05.950 --> 00:00:01.100
+Negative length cue. Should be treated correctly.
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/no-newline-at-eof.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/no-newline-at-eof.vtt
new file mode 100644
index 00000000000..49e4e9051a2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/no-newline-at-eof.vtt
@@ -0,0 +1,6 @@
+WEBVTT
+A file with no line terminator at the end should be fine (last cue should be recognized).
+
+1
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!! \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/no-timings.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/no-timings.vtt
new file mode 100644
index 00000000000..4cb85b6df27
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/no-timings.vtt
@@ -0,0 +1,13 @@
+WEBVTT
+Cues without timings are ignored.
+
+1
+00:00:00.000
+Bear is Coming!!!!!
+
+2
+00h:00m:31s.000ms
+I said Bear is coming!!!!
+
+3
+I said Bear is coming now!!!! \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/no-webvtt.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/no-webvtt.vtt
new file mode 100644
index 00000000000..12053b2703c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/no-webvtt.vtt
@@ -0,0 +1,10 @@
+AWEBVTT FILE
+A file with wrong file header should not be recognized as a webvtt file.
+
+1
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+
+2
+00:00:31.000 --> 00:20:00.500
+I said Bear is coming!!!! \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/positioning-bad.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/positioning-bad.vtt
new file mode 100644
index 00000000000..58ca6792be7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/positioning-bad.vtt
@@ -0,0 +1,39 @@
+WEBVTT
+Invalid horizontal positioning values (all settings are ignored).
+
+1
+00:00:00.000 --> 00:00:15.500 position:-5%
+Bear is Coming!!!!!
+This would be off screen -> ignored.
+
+00:00:16.000 --> 00:00:30.500 position:150%
+Bear is Coming!!!!!
+This would be off screen -> ignored.
+
+2
+00:00:31.000 --> 00:00:45.500 position:50
+I said Bear is coming!!!!
+Missing percent sign -> ignored.
+
+2
+00:00:46.000 --> 00:01:00.500 position:50a%
+I said Bear is coming!!!!
+Surplus character between number and percent sign -> ignored.
+
+3
+00:01:01.000 --> 00:01:30.500 position:100%-fj
+I said Bear is coming now!!!!
+Surplus characters after percent sign -> ignored.
+
+
+00:01:31.000 --> 00:02:00.500 position:100asdf
+I said Bear is coming now!!!!
+Surplus characters and no percent sign -> ignored.
+
+00:02:01.000 --> 00:02:02.000 position:e50%
+I said Bear is coming now!!!!
+Surplus characters at beginning of size string -> ignored.
+
+00:02:02.100 --> 00:02:02.500 position:5g0%
+I said Bear is coming now!!!!
+Surplus characters in middle of size string -> ignored.
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/positioning-ltr.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/positioning-ltr.vtt
new file mode 100644
index 00000000000..b23a7446b7f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/positioning-ltr.vtt
@@ -0,0 +1,21 @@
+WEBVTT
+Valid horizontal positioning values.
+
+1
+00:00:00.000 --> 00:00:30.500 position:0%
+الدب قادم!!!!!
+تحديد المواقع في أسفل اليمين.
+
+2
+00:00:31.000 --> 00:00:45.500 position:50%
+قلت الدب قادم!!
+تحديد المواقع في منتصف القاع.
+
+00:00:46.000 --> 00:01:00.500
+قلت الدب قادم!!
+المواقع الافتراضية على منتصف أسفل تزال قائمة.
+
+3
+00:01:01.000 --> 00:02:00.500 position:100%
+قلت الدب قادم الآن!!
+غادر لتحديد المواقع في القاع.
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/positioning.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/positioning.vtt
new file mode 100644
index 00000000000..ccf6024da06
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/positioning.vtt
@@ -0,0 +1,21 @@
+WEBVTT
+Valid horizontal positioning values.
+
+1
+00:00:00.000 --> 00:00:30.500 position:0%
+Bear is Coming!!!!!
+Positioning on the left bottom.
+
+2
+00:00:31.000 --> 00:00:45.500 position:50%
+I said Bear is coming!!!!
+Positioning on the bottom middle.
+
+00:00:46.000 --> 00:01:00.500
+I said Bear is coming!!!!
+Default positioning on the bottom middle still.
+
+3
+00:01:01.000 --> 00:02:00.500 position:100%
+I said Bear is coming now!!!!
+Positioning on the bottom right.
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/settings-bad-separation.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/settings-bad-separation.vtt
new file mode 100644
index 00000000000..cbfe6ea6e92
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/settings-bad-separation.vtt
@@ -0,0 +1,20 @@
+WEBVTT
+Cues settings may only be separated by spaces or tabs, but illegal characters
+between settings are ignored.
+
+1
+00:00:00.000 --> 00:00:30.500 - line:43% position:10% -
+Bear is Coming!!!!! Bad separator ignored.
+
+2
+00:00:31.000 --> 00:01:00.500 --> position:50% Vertical:lr align:end
+I said Bear is coming!!!! Bad separator and setting ignored.
+
+3
+00:01:01.000 --> 00:02:00.500 <align:end> <position:90%>
+I said Bear is coming now!!!! Bad setting markup. Not ignored because the settings are
+not delimited by spaces or tabs.
+
+4
+00:02:01.000 --> 100:20:00.500 / vertical:lr | position:90%
+I said Bear is coming now!!!! Bad separator ignored.
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/settings.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/settings.vtt
new file mode 100644
index 00000000000..dd6b02296af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/settings.vtt
@@ -0,0 +1,18 @@
+WEBVTT
+Cue settings may be separated by spaces or tabs.
+
+1
+00:00:00.000 --> 00:00:30.500 line:100% align:start
+Bear is Coming!!!!! One blank.
+
+2
+00:00:31.000 --> 00:01:00.500 position:40% vertical:rl line:15%
+I said Bear is coming!!!! Several blanks.
+
+3
+00:01:01.000 --> 00:02:00.500 align:middle position:10%
+I said Bear is coming now!!!! Tab separator.
+
+4
+00:02:01.000 --> 100:20:00.500 line:95% vertical:lr align:end
+I said Bear is coming now!!!! Tab separators. \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/simple-captions.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/simple-captions.vtt
new file mode 100644
index 00000000000..9815b111da5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/simple-captions.vtt
@@ -0,0 +1,17 @@
+WEBVTT
+
+0
+00:00:04.000 --> 00:00:04.500
+First cue
+
+1
+00:00:04.500 --> 00:00:05.000
+Lorem
+
+2
+00:00:05.000 --> 00:00:05.500
+ipsum
+
+3
+00:00:05.500 --> 00:00:05.501
+Missed cue with pause-on-exit
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/sorted-dispatch.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/sorted-dispatch.vtt
new file mode 100644
index 00000000000..438ea6abf99
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/sorted-dispatch.vtt
@@ -0,0 +1,34 @@
+WEBVTT
+Enter and exit events should be dispatched in a sorted order according to their times.
+
+0
+00:00:04.000 --> 00:00:04.500
+Missed cue that should not be considered because of seeking.
+
+1
+00:00:05.100 --> 00:00:05.800 align:start position:20%
+Bear is Coming!!!!!
+
+2
+00:00:05.100 --> 00:00:05.101
+Missed cue 1
+
+3
+00:00:05.100 --> 00:00:05.301
+And what kind of a bear it is - just have look.
+
+4
+00:00:05.100 --> 00:00:05.101
+Missed Cue 2
+
+5
+00:00:05.300 --> 00:00:05.800 align:start position:20%
+I said Bear is coming!!!!
+
+6
+00:00:05.990 --> 00:00:05.993 align:start position:20%
+I said Bear is coming now!!!!
+
+7
+00:00:05.994 --> 00:00:05.998 align:start position:20%
+Bear is already here
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timestamp-bad.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timestamp-bad.vtt
new file mode 100644
index 00000000000..4479cdb722f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timestamp-bad.vtt
@@ -0,0 +1,17 @@
+WEBVTT
+Invalid <timestamp> markup.
+
+1
+00:00:00.000 --> 00:00:30.500 align:start position:20%
+This <00:00:05.000>cue <00:00:10.000>is <00:00:12.000>painted <00:00:08.000>on.
+But since the last two timestamps are out of order, they are ignored.
+
+2
+00:00:31.000 --> 00:01:00.500 align:start position:20%
+I <00:00:20.000>said <00:00:22.000>Bear <00:00:24.000>is <00:00:26.000>coming!!!!
+All of these timestamps are before the start of the cue, so get ignored.
+
+3
+00:01:01.000 --> 00:02:00.500 align:start position:20%
+I <00:02:05.000>said <00:02:10.000>Bear <00:02:15.000>is <00:02:20.000>coming <00:02:25.000>now!!!!
+All of these timestamps are after the end of the cue, so get ignored.
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timestamp.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timestamp.vtt
new file mode 100644
index 00000000000..17d464bfedf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timestamp.vtt
@@ -0,0 +1,14 @@
+WEBVTT
+Paint-on text in cues with <timestamp> markup.
+
+1
+00:00:00.000 --> 00:00:30.500 align:start position:20%
+This <00:00:05.000>cue <00:00:10.000>is <00:00:15.000>painted <00:00:20.000>on.
+
+2
+00:00:31.000 --> 00:01:00.500 align:start position:20%
+I <00:00:35.000>said <00:00:40.000>Bear <00:00:45.000>is <00:00:50.000>coming!!!!
+
+3
+00:01:01.000 --> 00:02:00.500 align:start position:20%
+I <00:01:05.000>said <00:01:10.000>Bear <00:01:15.000>is <00:01:20.000>coming <00:01:25.000>now!!!!
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-hour-error.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-hour-error.vtt
new file mode 100644
index 00000000000..c33f8a96c3f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-hour-error.vtt
@@ -0,0 +1,22 @@
+WEBVTT
+These timings all have errors and all cues should be ignored.
+
+1
+00:00.00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+
+2
+00:00:31.000 --> 00:01:00:500
+I said Bear is coming!!!!
+
+3
+00:01:01.000 --> 00:120:00.500
+I said Bear is coming now!!!!
+
+4
+00:02:01.000 - 00:03:00.500
+I said Bear is coming now!!!!
+
+5
+00h:03m:01s.000ms --> 00h:03m:00s.500ms
+I said Bear is coming now!!!!
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-hour.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-hour.vtt
new file mode 100644
index 00000000000..b708b83338a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-hour.vtt
@@ -0,0 +1,14 @@
+WEBVTT
+Timings can optionally contain an hour.
+
+1
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+
+2
+00:00:31.000 --> 00:01:00.500
+I said Bear is coming!!!!
+
+3
+00:01:01.000 --> 100:20:00.500
+I said Bear is coming now!!!! \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-no-hour-errors.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-no-hour-errors.vtt
new file mode 100644
index 00000000000..e4bf27d4e6c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-no-hour-errors.vtt
@@ -0,0 +1,22 @@
+WEBVTT
+These timings all have errors and all cues should be ignored.
+
+1
+00.00.000 --> 00:30.500
+Bear is Coming!!!!!
+
+2
+00:31.000 --> 01:00:500
+I said Bear is coming!!!!
+
+3
+01:01.000 --> 120:00.500
+I said Bear is coming now!!!!
+
+4
+01:01.000 - 02:00.500
+I said Bear is coming now!!!!
+
+5
+02:01.000 --> 03m:00.500
+I said Bear is coming now!!!!
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-no-hour.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-no-hour.vtt
new file mode 100644
index 00000000000..745c34ff9fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-no-hour.vtt
@@ -0,0 +1,18 @@
+WEBVTT
+The hour of a timestamp is optional.
+
+1
+00:00.000 --> 00:30.500
+Bear is Coming!!!!!
+
+2
+00:31.000 --> 01:00.500
+I said Bear is coming!!!!
+
+3
+01:01.000 --> 02:00.500
+I said Bear is coming now!!!!
+
+4
+02:01.000 --> 03:00.500
+tab separators \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-whitespace.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-whitespace.vtt
new file mode 100644
index 00000000000..9d9ac9a38a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/timings-whitespace.vtt
@@ -0,0 +1,51 @@
+WEBVTT
+Whitespace (U+0020, U+0009, U+000C) surrounding cue-timings separator ("-->") is optional
+
+1
+00:00:00.100 -->00:00:01.500
+Single U+0020 SPACE left of cue-timings separator
+
+2
+00:00:00.100--> 00:00:01.500
+Single U+0020 SPACE right of cue-timings separator
+
+3
+00:00:00.100 -->00:00:01.500
+Single U+0009 TAB left of cue-timings separator
+
+4
+00:00:00.100--> 00:00:01.500
+Single U+0009 TAB right of cue-timings separator
+
+5
+00:00:00.100 -->00:00:01.500
+Single U+000C FORM FEED left of cue-timings separator
+
+6
+00:00:00.100--> 00:00:01.500
+Single U+000C FORM FEED right of cue-timings separator
+
+7
+00:00:00.100 -->00:00:01.500
+Several U+0020 SPACE left of cue-timings separator
+
+8
+00:00:00.100--> 00:00:01.500
+Several U+0020 SPACE right of cue-timings separator
+
+9
+00:00:00.100 -->00:00:01.500
+Several U+0009 TAB left of cue-timings separator
+
+10
+00:00:00.100--> 00:00:01.500
+Several U+0009 TAB right of cue-timings separator
+
+11
+00:00:00.100 -->00:00:01.500
+Several U+000C FORM FEED left of cue-timings separator
+
+12
+00:00:00.100--> 00:00:01.500
+Several U+000C FORM FEED right of cue-timings separator
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/unsupported-markup.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/unsupported-markup.vtt
new file mode 100644
index 00000000000..b4ea7ea09b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/unsupported-markup.vtt
@@ -0,0 +1,23 @@
+WEBVTT
+Any HTML markup that is not supported should be ignored.
+
+1
+00:00:00.000 --> 00:00:30.500 align:start position:20%
+<h1>Bear is Coming!!!!!</h1>
+<p>And what kind of a bear it is - just have <a href="webpage.html">look</a>.</p>
+
+2
+00:00:31.000 --> 00:01:00.500 align:start position:20%
+<ul>
+ <li>I said Bear is coming!!!!</li>
+ <li>I said Bear is still coming!!!!</li>
+</ul>
+
+
+3
+00:01:01.000 --> 00:02:00.500 align:start position:20%
+<ol>
+ <li>I said Bear is coming now!!!!</li>
+ <li><img src="bear.png" alt="mighty bear"></li>
+ <li><video src="bear_ad.webm" controls></video></li>
+</ol> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/utf8.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/utf8.vtt
new file mode 100644
index 00000000000..8dd8f279488
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/utf8.vtt
@@ -0,0 +1,10 @@
+WEBVTT
+UTF-8 encoded characters should be recognized.
+
+1
+00:00:00.000 --> 00:00:30.500
+景気判断
+
+2
+00:00:31.000 --> 00:20:00.500
+電力不足 \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/valign-bad.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/valign-bad.vtt
new file mode 100644
index 00000000000..8e7b3b738dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/valign-bad.vtt
@@ -0,0 +1,17 @@
+WEBVTT
+Invalid vertical direction settings (all settings are ignored).
+
+1
+00:00:00.000 --> 00:00:30.500 vertical:#vertical
+Bear is Coming!!!!!
+Normal rendering - direction setting is ignored.
+
+2
+00:00:31.000 --> 00:01:00.500 vertical:verticallr
+I said Bear is coming!!!!
+Normal rendering - direction setting is ignored.
+
+3
+00:01:01.000 --> 00:02:00.500 vertical:vertical-rl
+I said Bear is coming now!!!!
+Normal rendering - direction setting is ignored.
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/valign-ltr.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/valign-ltr.vtt
new file mode 100644
index 00000000000..74838369d23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/valign-ltr.vtt
@@ -0,0 +1,20 @@
+WEBVTT
+Valid vertical direction settings.
+
+1
+00:00:00.000 --> 00:00:30.500 vertical:rl
+الدب قادم!!!!!
+يجعل على الجانب الأيمن من المعاينة الفيديو والمتوسطة الانحياز ،
+أسفل إلى أعلى، وتزايد اليسار.
+
+2
+00:00:31.000 --> 00:01:00.500 vertical:lr
+قلت الدب قادم!!
+يجعل على الجانب الأيسر من المعاينة الفيديو والمتوسطة الانحياز ،
+أسفل إلى أعلى، وتنامي اليمين.
+
+3
+00:01:01.000 --> 00:02:00.500 vertical:rl align:start position:0%
+قلت الدب قادم الآن!!
+يجعل على الجانب الأيمن من المعاينة الفيديو ، على حد سواء أسفل محاذاة
+لمربع جديلة والنص داخل النص ، من أسفل إلى أعلى، وتزايد اليسار.
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/valign.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/valign.vtt
new file mode 100644
index 00000000000..f757a365e36
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/valign.vtt
@@ -0,0 +1,20 @@
+WEBVTT
+Valid vertical direction settings.
+
+1
+00:00:00.000 --> 00:00:30.500 vertical:rl
+Bear is Coming!!!!!
+Renders on the right side of the video viewport, middle aligned,
+top to bottom, growing left.
+
+2
+00:00:31.000 --> 00:01:00.500 vertical:lr
+I said Bear is coming!!!!
+Renders on the left side of the video viewport, middle aligned,
+top to bottom, growing right.
+
+3
+00:01:01.000 --> 00:02:00.500 vertical:rl align:start position:0%
+I said Bear is coming now!!!!
+Renders on the right side of the video viewport, top aligned both
+for the cue box and the text within, text from top to bottom, growing left.
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/voice-bad.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/voice-bad.vtt
new file mode 100644
index 00000000000..12ffdeb82ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/voice-bad.vtt
@@ -0,0 +1,17 @@
+WEBVTT
+Invalid <v> voice markup.
+
+1
+00:00:00.000 --> 00:00:30.500 align:start position:20%
+< v Speaker>Bear is Coming!!!!!</v>
+This is two annotations for an empty tag.
+
+2
+00:00:31.000 --> 00:01:00.500 align:start position:20%
+<v&Doe Hunter>I said Bear is coming!!!!</v>
+This does not parse as a voice tag.
+
+3
+00:01:01.000 --> 00:02:00.500 align:start position:20%
+I said <v-Speaker>Bear is coming now</v>!!!!
+This does not parse as a voice tag.
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/voice.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/voice.vtt
new file mode 100644
index 00000000000..d6cfc6887ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/voice.vtt
@@ -0,0 +1,15 @@
+WEBVTT
+Cue text fragment with <v> voice markup mapped to HTML <q> element with @title for annotation.
+
+1
+00:00:00.000 --> 00:00:30.500 align:start position:20%
+<v.blue Speaker>Bear is Coming!!!!!</v>
+Text span with a class and an annotation.
+
+2
+00:00:31.000 --> 00:01:00.500 align:start position:20%
+<v Doe Hunter>I said Bear is coming!!!!</v>
+
+3
+00:01:01.000 --> 00:02:00.500 align:start position:20%
+I said <v.blue Speaker>Bear is coming now</v>!!!!
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/vp8-vorbis-webvtt.webm b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/vp8-vorbis-webvtt.webm
new file mode 100644
index 00000000000..c626f86e336
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/vp8-vorbis-webvtt.webm
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/webvtt-file.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/webvtt-file.vtt
new file mode 100644
index 00000000000..0c1a5fb158c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/webvtt-file.vtt
@@ -0,0 +1,9 @@
+WEBVTT FILE
+
+1
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+
+2
+00:00:31.000 --> 00:20:00.500
+I said Bear is coming!!!! \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/webvtt-rubbish.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/webvtt-rubbish.vtt
new file mode 100644
index 00000000000..dacc215409c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/webvtt-rubbish.vtt
@@ -0,0 +1,10 @@
+WEBVTT asdfasdfauhio
+Rubbish after the WEBVTT header should be ignored.
+
+1
+00:00:00.000 --> 00:00:30.500
+Bear is Coming!!!!!
+
+2
+00:00:31.000 --> 00:20:00.500
+I said Bear is coming!!!! \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-active-cues.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-active-cues.html
new file mode 100644
index 00000000000..67ab3bdb138
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-active-cues.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<title>Ensure that no text track cues are active after the video is unloaded</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+async_test(function(t) {
+ var eventCount = 0;
+
+ function eventCallback() {
+ eventCount++;
+ if (eventCount == 3) {
+ assert_equals(trackElement.track.activeCues.length, 1);
+ video.src = '';
+ }
+ }
+
+ var video = document.createElement('video');
+ video.src = getVideoURI('/media/movie_5');
+ var trackElement = document.createElement('track');
+
+ trackElement.onload = t.step_func(eventCallback);
+ trackElement.oncuechange = t.step_func(eventCallback);
+ video.oncanplaythrough = t.step_func(eventCallback);
+
+ video.onerror = t.step_func_done(function() {
+ assert_equals(event.target, video);
+ assert_not_equals(video.error, null);
+ assert_equals(video.error.code, MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED);
+ assert_equals(video.networkState, HTMLMediaElement.NETWORK_NO_SOURCE);
+ assert_equals(trackElement.track.activeCues.length, 0);
+ });
+
+ trackElement.src = 'resources/captions-fast.vtt';
+ trackElement.kind = 'captions';
+ trackElement.default = true;
+ video.appendChild(trackElement);
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-add-remove-cue.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-add-remove-cue.html
new file mode 100644
index 00000000000..1e6c557fb60
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-add-remove-cue.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<title>TextTrack's addCue and removeCue</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+async_test(function(t) {
+ var video = document.createElement("video");
+ var trackElement = document.createElement("track");
+
+ trackElement.onload = t.step_func_done(function() {
+ var cues = trackElement.track.cues;
+ // Test cues loaded from the file.
+ assert_equals(cues.length, 4);
+ assert_equals(cues.getCueById("1").startTime, 0);
+ assert_equals(cues[1].startTime, 31);
+ assert_equals(cues[2].startTime, 61);
+ assert_equals(cues.getCueById("4").startTime, 121);
+ assert_object_equals(cues.getCueById("junk"), undefined);
+
+ // Create a new cue, check values.
+ var textCue = new VTTCue(33, 3.4, "Sausage?");
+ assert_equals(textCue.track, null);
+ assert_equals(textCue.id, "");
+ assert_equals(textCue.startTime, 33);
+ assert_equals(textCue.endTime, 3.4);
+ assert_equals(textCue.pauseOnExit, false);
+ assert_equals(textCue.vertical, "");
+ assert_equals(textCue.snapToLines, true);
+ assert_equals(textCue.line, "auto");
+ assert_equals(textCue.position, "auto");
+ assert_equals(textCue.size, 100);
+ assert_equals(textCue.align, "center");
+
+ // Remove the unadded track, make sure it throws correctly.
+ assert_throws("NotFoundError", function() { trackElement.track.removeCue(textCue); });
+
+ // Add the new cue to a track, make sure it is inserted correctly.
+ trackElement.track.addCue(textCue);
+ assert_equals(textCue.track, trackElement.track);
+ assert_equals(cues[1].startTime, 31);
+ assert_equals(cues[2].startTime, 33);
+ assert_equals(cues[3].startTime, 61);
+
+ // create a new cue and add it to a track created with
+ // video.addTextTrack, make sure it is inserted correctly.
+ var newTrack = video.addTextTrack("subtitles", "French subtitles", "fr");
+ newTrack.mode = "showing";
+ var newCue = new VTTCue(0, 1, "Test!");
+ newTrack.addCue(newCue);
+ assert_equals(newCue, newTrack.cues[0])
+ assert_equals(newCue.track, newTrack);
+ assert_equals(newCue.id, "");
+ assert_equals(newCue.startTime, 0);
+ assert_equals(newCue.endTime, 1);
+ assert_equals(newCue.pauseOnExit, false);
+ assert_equals(newCue.vertical, "");
+ assert_equals(newCue.snapToLines, true);
+ assert_equals(newCue.line, "auto");
+ assert_equals(newCue.position, "auto");
+ assert_equals(newCue.size, 100);
+ assert_equals(newCue.align, "center");
+
+ trackElement.track.removeCue(textCue);
+ assert_equals(textCue.track, null);
+ assert_equals(cues[1].startTime, 31);
+ assert_equals(cues[2].startTime, 61);
+
+ // Remove a cue added from the WebVTT file.
+ textCue = cues[2];
+ trackElement.track.removeCue(textCue);
+ assert_equals(textCue.track, null);
+ assert_equals(cues[1].startTime, 31);
+ assert_equals(cues[2].startTime, 121);
+
+ // Try to remove the cue again.
+ assert_throws("NotFoundError", function() { trackElement.track.removeCue(textCue); });
+
+ // Add a cue before all the existing cues.
+ trackElement.track.addCue(new VTTCue(0, 31, "I am first"));
+ assert_equals(cues[0].startTime, 0);
+ assert_equals(cues[0].endTime, 31);
+ assert_equals(cues[1].startTime, 0);
+ assert_equals(cues[1].endTime, 30.5);
+ assert_equals(cues[2].startTime, 31);
+ });
+
+ trackElement.src = "resources/settings.vtt";
+ trackElement.kind = "captions";
+ trackElement.default = true;
+ video.appendChild(trackElement);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-add-track.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-add-track.html
new file mode 100644
index 00000000000..7f8ee2fdd47
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-add-track.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<title>'addtrack' event is fired when a TextTrack is created</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+async_test(function(t) {
+ var video = document.createElement('video');
+
+ var trackElement = document.createElement('track');
+ video.appendChild(trackElement);
+ var tracks = [];
+ tracks.push(trackElement.track);
+
+ // Register the 'addtrack' listener after creating the element
+ // to make sure the event is dispatched asynchronously.
+ video.textTracks.onaddtrack = t.step_func(function() {
+ assert_equals(event.target, video.textTracks);
+ assert_true(event instanceof TrackEvent, 'instanceof');
+ assert_equals(event.track, tracks[video.textTracks.length - 1]);
+
+ if (video.textTracks.length == 1) {
+ tracks.push(video.addTextTrack('captions', 'Caption Track', 'en'));
+ assert_equals(video.textTracks.length, 2);
+ } else {
+ t.done();
+ }
+ });
+
+ trackElement.src = 'resources/webvtt-file.vtt';
+ trackElement.track.mode = 'hidden';
+ assert_equals(video.textTracks.length, 1);
+ assert_equals(trackElement.readyState, HTMLTrackElement.NONE);
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-addtrack-kind.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-addtrack-kind.html
new file mode 100644
index 00000000000..4503a06bb2c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-addtrack-kind.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>addTextTrack() only accepts known "kind" values</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ var trackCount = 0;
+
+ function addTrack(type) {
+ video.addTextTrack(type);
+ assert_equals(video.textTracks.length, ++trackCount);
+ }
+
+ var video = document.createElement("video");
+ assert_equals(video.textTracks.length, 0);
+ assert_throws(new TypeError(), function() { video.addTextTrack("kaptions"); });
+ assert_equals(video.textTracks.length, 0);
+
+ addTrack("subtitles");
+ addTrack("captions");
+ addTrack("descriptions");
+ addTrack("chapters");
+ addTrack("metadata");
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-empty.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-empty.html
new file mode 100644
index 00000000000..59f8fc6c7b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-empty.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>Invoke getCueAsHTML() on an empty cue</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ var emptyCue = new VTTCue(0, 0, "");
+ var fragment = emptyCue.getCueAsHTML();
+
+ // The getCueAsHTML() method should return a document fragment.
+ assert_true(fragment instanceof DocumentFragment);
+
+ // The document fragment should have one child, an empty Text node.
+ assert_equals(fragment.childNodes.length, 1);
+ assert_equals(fragment.childNodes[0].constructor.name, Text.name);
+ assert_equals(fragment.childNodes[0].length, 0);
+ assert_equals(fragment.childNodes[0].data, "");
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-inline.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-inline.html
new file mode 100644
index 00000000000..3b4c3542a92
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-inline.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>Add a track and change its mode through JS</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <source src="/media/test.mp4" type="video/mp4">
+ <source src="/media/test.ogv" type="video/ogg">
+</video>
+<script>
+test(function() {
+ var video = document.querySelector('video');
+ var track = video.addTextTrack('captions', 'English', 'en');
+ track.addCue(new VTTCue(0.0, 10.0, 'wow wow'));
+ track.mode = 'showing';
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable-fragment.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable-fragment.html
new file mode 100644
index 00000000000..713e7819962
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable-fragment.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<title>Cue fragment is mutable</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+p, div { display: none; }
+</style>
+<video>
+ <track src="resources/captions-html.vtt" kind="captions" default>
+ <script>
+ async_test(function(t) {
+ var video = document.querySelector("video");
+ var testTrack = document.querySelector("track");
+
+ video.oncanplaythrough = t.step_func(testMutability);
+ testTrack.onload = t.step_func(testMutability);
+
+ var fragment;
+ var eventCount = 0;
+ function testMutability() {
+ eventCount++;
+ if (eventCount != 2)
+ return;
+
+ var testCue = testTrack.track.cues[0];
+
+ // Test initial cue contents.
+ assert_equals(testCue.text, "Lorem <b>ipsum</b> <u>dolor</u> <i.sit>sit</i> amet,");
+
+ // Cue getCueAsHTML() should return a correct fragment.
+ createExpectedFragment(document.createDocumentFragment());
+ assert_true(fragment.isEqualNode(testCue.getCueAsHTML()));
+
+ // Appending getCuesAsHTML() twice to the DOM should be succesful.
+ document.getElementsByTagName("div")[0].appendChild(testCue.getCueAsHTML());
+ document.getElementsByTagName("div")[1].appendChild(testCue.getCueAsHTML());
+
+ createExpectedFragment(document.createElement("div"));
+ assert_true(fragment.isEqualNode(document.getElementsByTagName("div")[0]));
+ assert_true(fragment.isEqualNode(document.getElementsByTagName("div")[1]));
+
+ // The fragment returned by getCuesAsHTML() should be independently mutable.
+ document.getElementsByTagName("div")[0].firstChild.textContent = "Different text ";
+ assert_false(fragment.isEqualNode(document.getElementsByTagName("div")[0]));
+ assert_true(fragment.isEqualNode(document.getElementsByTagName("div")[1]));
+
+ // Calling twice getCueAsHTML() should not return the same fragment.
+ assert_not_equals(testCue.getCueAsHTML(), testCue.getCueAsHTML());
+
+ t.done();
+ }
+
+ function createExpectedFragment(rootNode) {
+ fragment = rootNode;
+ fragment.appendChild(document.createTextNode("Lorem "));
+
+ var bold = document.createElement("b");
+ bold.appendChild(document.createTextNode("ipsum"));
+ fragment.appendChild(bold);
+
+ fragment.appendChild(document.createTextNode(" "));
+
+ var underline = document.createElement("u");
+ underline.appendChild(document.createTextNode("dolor"));
+ fragment.appendChild(underline);
+
+ fragment.appendChild(document.createTextNode(" "));
+
+ var italics = document.createElement("i");
+ italics.className = "sit";
+ italics.appendChild(document.createTextNode("sit"));
+ fragment.appendChild(italics);
+
+ fragment.appendChild(document.createTextNode(" amet,"));
+ }
+
+ video.src = getVideoURI("/media/counting");
+ });
+ </script>
+</video>
+<p>Fragment 1</p>
+<div></div>
+<p>Fragment 2</p>
+<div></div> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable.html
new file mode 100644
index 00000000000..63c3018aa99
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cue-mutable.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<title>Modifying attributes of a VTTCue</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track id="captions" src="resources/captions.vtt" kind="captions" default>
+ <script>
+ async_test(function(t) {
+ var track = document.querySelector("track");
+
+ track.onload = t.step_func_done(function() {
+ var cues = track.track.cues;
+
+ // Test initial values.
+ textCue = cues.getCueById("1");
+
+ assert_equals(textCue.startTime, 0);
+ assert_equals(textCue.endTime, 1.0);
+ assert_equals(textCue.pauseOnExit, false);
+ assert_equals(textCue.vertical, "");
+ assert_equals(textCue.snapToLines, true);
+ assert_equals(textCue.line, "auto");
+ assert_equals(textCue.position, "auto");
+ assert_equals(textCue.size, 100);
+ assert_equals(textCue.align, "center");
+
+ // Modify cue values.
+ textCue.startTime = 1.1;
+ assert_equals(textCue.startTime, 1.1);
+
+ textCue.endTime = 3.9;
+ assert_equals(textCue.endTime, 3.9);
+
+ textCue.pauseOnExit = true;
+ assert_equals(textCue.pauseOnExit, true);
+
+ // http://dev.w3.org/html5/webvtt/#dfn-dom-vttcue-vertical
+ // On setting, the text track cue writing direction must be
+ // set to the value given in the first cell of the row in
+ // the table above whose second cell is a case-sensitive
+ // match for the new value.
+ textCue.vertical = "RL";
+ assert_equals(textCue.vertical, "");
+ textCue.vertical = "rl";
+ assert_equals(textCue.vertical, "rl");
+
+ textCue.snapToLines = false;
+ assert_equals(textCue.snapToLines, false);
+
+ // http://dev.w3.org/html5/webvtt/#dfn-vttcue-line
+ // On setting, the text track cue line position must be set
+ // to the new value; if the new value is the string "auto",
+ // then it must be interpreted as the special value auto.
+ assert_equals(textCue.line, "auto");
+ assert_throws(new TypeError, function() { textCue.line = "gazonk"; });
+ assert_equals(textCue.line, "auto");
+ textCue.line = 42;
+ assert_equals(textCue.line, 42);
+ textCue.line = -2;
+ assert_equals(textCue.line, -2);
+ textCue.line = 102;
+ assert_equals(textCue.line, 102);
+ textCue.snapToLines = true;
+ textCue.line = -2;
+ assert_equals(textCue.line, -2);
+ textCue.line = 102;
+ assert_equals(textCue.line, 102);
+
+ // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#dom-texttrackcue-line
+ // On setting, if the new value is negative or greater than 100,
+ // then throw an IndexSizeError exception.
+ // Otherwise, set the text track cue text position to the new value.
+ assert_throws("IndexSizeError", function() { textCue.position = -200; });
+ assert_throws("IndexSizeError", function() { textCue.position = 110; });
+ textCue.position = 11;
+ assert_equals(textCue.position, 11);
+
+ // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#dom-texttrackcue-size
+ // On setting, if the new value is negative or greater than 100,
+ // then throw an IndexSizeError exception.
+ // Otherwise, set the text track cue size to the new value.
+ assert_throws("IndexSizeError", function() { textCue.size = -200 });
+ assert_throws("IndexSizeError", function() { textCue.size = 110 });
+ textCue.size = 57;
+ assert_equals(textCue.size, 57);
+
+ // http://dev.w3.org/html5/webvtt/#dfn-dom-vttcue-align
+ // On setting, the text track cue text alignment must be
+ // set to the value given in the first cell of the row
+ // in the table above whose second cell is a case-sensitive
+ // match for the new value.
+ textCue.align = "End";
+ assert_equals(textCue.align, "center");
+ textCue.align = "end";
+ assert_equals(textCue.align, "end");
+ });
+ });
+ </script>
+</video>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-missed.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-missed.html
new file mode 100644
index 00000000000..043c941b123
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-missed.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<title>Events are triggered for missed (skipped) cues during normal playback</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/missed-cues.vtt" default>
+ <script>
+ async_test(function(t) {
+ var video = document.querySelector("video");
+ var testTrack = document.querySelector("track");
+
+ video.src = getVideoURI("/media/test");
+
+ video.onended = t.step_func_done();
+
+ video.oncanplaythrough = t.step_func(function() {
+ video.oncanplaythrough = null;
+ video.currentTime = 5.00;
+ runTests();
+ });
+
+ testTrack.onload = t.step_func(runTests);
+
+ var cueCount;
+ var eventCount = 0;
+ function runTests() {
+ eventCount++;
+
+ if(eventCount != 2)
+ return;
+
+ assert_equals(testTrack.track.cues.length, 7);
+
+ for (cueCount = 2; cueCount < testTrack.track.cues.length; cueCount++) {
+ var cue = testTrack.track.cues[cueCount];
+
+ cue.onenter = t.step_func(cueEnteredOrExited);
+ cue.onexit = t.step_func(cueEnteredOrExited);
+ }
+
+ // Test events for missed cues, which are cues with ids
+ // from 3 to 7 in the file resources/missed-cues.vtt.
+ cueCount = 3;
+ video.play();
+ }
+
+ function cueEnteredOrExited() {
+ var currentCue = event.target;
+ assert_equals(testTrack.track.cues.getCueById(cueCount).text, currentCue.text);
+ assert_equals(currentCue.id, cueCount.toString());
+
+ if (event.type == "exit")
+ cueCount++;
+ }
+
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-pause-on-exit.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-pause-on-exit.html
new file mode 100644
index 00000000000..eaf7e2a1d4f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-pause-on-exit.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<title>Video is paused after cues having pause-on-exit flag are processed</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/simple-captions.vtt" default>
+ <script>
+ async_test(function(t) {
+ var video = document.querySelector("video");
+ var track = document.querySelector("track");
+ track.onload = t.step_func(function() {
+ assert_equals(track.track.cues.length, 4);
+ for (var i = 0; i < track.track.cues.length; ++i) {
+ var cue = track.track.cues[i];
+ if (i % 2 == 0) {
+ cue.pauseOnExit = true;
+ cue.onexit = t.step_func(function(event) {
+ assert_true(video.paused);
+
+ video.play();
+
+ if (event.target.id == 2)
+ t.done();
+ });
+ }
+ }
+ video.src = getVideoURI("/media/test");
+ video.currentTime = 4.00;
+ video.play();
+ assert_false(video.paused);
+ });
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-seeking.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-seeking.html
new file mode 100644
index 00000000000..99cd2d550e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-seeking.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<title>TextTrack's activeCues are indexed and updated during video playback</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/cues-overlapping.vtt" kind="subtitles" default>
+ <script>
+ async_test(function(t) {
+ var video = document.querySelector("video");
+ var track = document.querySelector("track");
+ track.onload = t.step_func(function() {
+ assert_equals(track.track.cues.length, 3);
+ video.src = getVideoURI("/media/test");
+ video.currentTime = 0.5;
+ });
+
+ var seekedCount = 0;
+ video.onseeked = t.step_func(function() {
+ ++seekedCount;
+
+ assert_equals(video.currentTime, seekedCount * 0.5);
+ assert_equals(track.track.activeCues.length, seekedCount - 1);
+ video.currentTime = (seekedCount + 1) * 0.5;
+
+ if (seekedCount == 4)
+ t.done();
+ });
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-sorted-before-dispatch.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-sorted-before-dispatch.html
new file mode 100644
index 00000000000..edc202f4358
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-cues-sorted-before-dispatch.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<title>All events are triggered in chronological order</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/sorted-dispatch.vtt" default>
+ <script>
+ async_test(function(t) {
+ var video = document.querySelector("video");
+ video.src = getVideoURI("/media/test");
+ var track = document.querySelector("track");
+
+ track.onload = t.step_func(function() {
+ var cues = track.track.cues;
+ assert_equals(cues.length, 8);
+
+ for (var i = 0; i < cues.length; ++i) {
+ cues[i].onenter = t.step_func(cueEnteredOrExited);
+ cues[i].onexit = t.step_func(cueEnteredOrExited);
+ }
+
+ video.play();
+ });
+
+ var cueTimings = [];
+ function cueEnteredOrExited(event) {
+ var currentCue = event.target;
+
+ if (event.type == "exit")
+ cueTimings.push(currentCue.endTime);
+ else
+ cueTimings.push(currentCue.startTime);
+ }
+
+ video.onended = t.step_func_done(function() {
+ assert_equals(cueTimings.length, 14);
+ var time = 0;
+ for (var i = 0; i < cueTimings.length; ++i) {
+ assert_less_than_equal(time, cueTimings[i], "cueTimings[" + i + "]");
+ time = cueTimings[i];
+ }
+ });
+
+ video.currentTime = 5;
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-disabled-addcue.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-disabled-addcue.html
new file mode 100644
index 00000000000..038e6f6ba71
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-disabled-addcue.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>Adding cues to a disabled text track</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+async_test(function(t) {
+ var cueDuration = 0.1;
+ var video = document.createElement("video");
+ var track = video.addTextTrack("subtitles");
+ track.mode = "disabled";
+
+ for (var i = 0; i < 10; ++i) {
+ var start = i * cueDuration;
+ var end = start + cueDuration;
+ track.addCue(new VTTCue(start, end, "Test Cue " + i));
+ }
+
+ // Waiting for 2 cue durations to elapse.
+ video.ontimeupdate = t.step_func(function(event) {
+ if (event.target.currentTime < (2 * cueDuration))
+ return;
+
+ // End test after at least 2 cueDurations to make sure the test
+ // would have gone through the period where the first 2 cues would
+ // have been rendered if the track was not disabled.
+ t.done();
+ });
+
+ video.src = getVideoURI("/media/test");
+ video.play();
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-disabled.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-disabled.html
new file mode 100644
index 00000000000..d517b9d12c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-disabled.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Disabling a track</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track kind="subtitles" src="resources/captions.vtt"/>
+</video>
+<script>
+async_test(function(t) {
+ var video = document.querySelector("video");
+ video.textTracks[0].mode = "disabled";
+
+ // Waiting for the duration of the first cue to elapse.
+ video.ontimeupdate = t.step_func(function (event) {
+ if (event.target.currentTime < 1)
+ return;
+
+ // End test after the duration of the first cue to make sure
+ // the test would have gone through the period where this cue
+ // would have been rendered if the track was not disabled.
+ t.done();
+ });
+
+ video.src = getVideoURI("/media/test");
+ video.play();
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-dom-change.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-dom-change.html
new file mode 100644
index 00000000000..ff447f33f2e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-dom-change.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>Simple DOM mutations with track element</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ var video = document.createElement("video");
+ var testTrack = document.createElement("track");
+
+ // Append the track element to the video element.
+ video.appendChild(testTrack);
+
+ // Set the mode of the text track to "showing".
+ testTrack.track.mode = "showing";
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change-error.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change-error.html
new file mode 100644
index 00000000000..ffc8ec0682d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change-error.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<title>HTMLTrackElement 'src' attribute mutations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/settings.vtt" default>
+ <script>
+ async_test(function(t) {
+ var cues = null;
+ var testTrack = document.querySelector("track");
+ var stage = 0;
+ var timer = null;
+ function step_onLoad() {
+ switch (stage) {
+ case 0:
+ cues = testTrack.track.cues;
+ assert_equals(testTrack.readyState, HTMLTrackElement.LOADED, "readyState after first loading of the track");
+ assert_equals(cues.length, 4, "Number of cues after first loading of the track");
+ ++stage;
+ testTrack.src = "resources/non-existing-file.vtt"; // this should fail
+ break;
+ case 1:
+ case 3:
+ case 5:
+ assert_unreached("'error' event did not fire, stage = " + stage);
+ break;
+ case 2:
+ assert_equals(testTrack.readyState, HTMLTrackElement.LOADED, "readyState after loading of the second track");
+ assert_equals(cues.length, 4, "Number of cues after loading of the second track");
+ assert_equals(cues[cues.length-1].text, 'I said Bear is coming now!!!! Tab separators.', "Last cue content check");
+ ++stage;
+ testTrack.src = ""; // this should fail
+ // CuesList will be cleared in the next tick. Spec claims that this should happen immediately,
+ // but all implementations are doing this asynchronously.
+ assert_equals(cues.length, 4, "Number of cues immediately after 'src' mutation with the empty URL");
+ // This should raise onError event. If no, we'll know about this after some time.
+ timer = t.step_timeout(t.unreached_func("'error' event is not fired when an empty URL is set"), 100);
+ break;
+ case 4:
+ assert_equals(testTrack.readyState, HTMLTrackElement.LOADED, "readyState after loading of the second track");
+ assert_equals(cues.length, 4, "Number of cues after loading of the second track");
+ assert_equals(cues[cues.length-1].text, 'I said Bear is coming now!!!! Tab separators.', "Last cue content check");
+ ++stage;
+ testTrack.removeAttribute('src');
+ // This should raise onError event, so we'll wait for it for some time
+ timer = t.step_timeout(t.unreached_func("'error' event is not fired when an empty URL is set"), 100);
+ break;
+ default:
+ assert_unreached("unexpected stage number = " + stage);
+ break;
+ }
+ }
+
+ function step_onError() {
+ switch (stage) {
+ case 0:
+ case 2:
+ case 4:
+ assert_unreached("'error' event fired, stage = " + stage);
+ break;
+ case 1:
+ assert_equals(cues, testTrack.track.cues, ".cues object are the same after 'src' attr mutation");
+ assert_equals(cues.length, 0, "Number of cues after trying to load non-existing url");
+ assert_equals(testTrack.readyState, HTMLTrackElement.ERROR, "readyState after trying to load non-existing url");
+ ++stage;
+ testTrack.src = "resources/settings.vtt";
+ break;
+ case 3:
+ clearTimeout(timer);
+ assert_equals(testTrack.readyState, HTMLTrackElement.ERROR, "readyState after setting an empty URL");
+ assert_equals(cues, testTrack.track.cues, ".cues object are the same after 'src' attr mutation");
+ assert_equals(cues.length, 0, "Number of cues with an empty URL set");
+ ++stage;
+ testTrack.src = "resources/settings.vtt";
+ break;
+ case 5:
+ clearTimeout(timer);
+ assert_equals(testTrack.readyState, HTMLTrackElement.ERROR, "readyState after removing 'src' attr");
+ assert_equals(cues.length, 0, "Number of cues after removing 'src' attr");
+ t.done();
+ break;
+ default:
+ assert_unreached("unexpected stage number = " + stage);
+ break;
+ }
+ }
+
+ testTrack.onload = t.step_func(step_onLoad);
+ testTrack.onerror = t.step_func(step_onError);
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change.html
new file mode 100644
index 00000000000..34a53d15319
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-element-src-change.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<title>HTMLTrackElement 'src' attribute mutations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/settings.vtt" default>
+ <script>
+ async_test(function(t) {
+ var cues = null;
+ var testTrack = document.querySelector("track");
+ var stage = 0;
+ function step_onLoad() {
+ switch (stage) {
+ case 0:
+ cues = testTrack.track.cues;
+ assert_equals(testTrack.readyState, HTMLTrackElement.LOADED, "readyState after first loading of the track");
+ assert_equals(cues.length, 4, "Number of cues after first loading of the track");
+ assert_equals(cues[cues.length-1].text, 'I said Bear is coming now!!!! Tab separators.', "Last cue content check");
+ ++stage;
+ testTrack.src = "resources/entities.vtt";
+ // CuesList will be cleared in a microtask. Spec claims that this should happen immediately,
+ // but all known implementations are doing this asynchronously.
+ assert_equals(cues.length, 4, "Number of cues immediately after 'src' mutation with the new URL");
+ break;
+ case 1:
+ assert_equals(testTrack.readyState, HTMLTrackElement.LOADED), "readyState after loading of the second track";
+ assert_equals(cues, testTrack.track.cues, ".cues object are the same after 'src' attr mutation");
+ assert_equals(cues.length, 7, "Number of cues after loading of the second track");
+ assert_equals(cues[cues.length-1].text, 'This & is parsed to the same as &amp;.', "Last cue content check");
+ ++stage;
+ testTrack.src = "resources/settings.vtt";
+ break;
+ case 2:
+ assert_equals(testTrack.readyState, HTMLTrackElement.LOADED, "readyState after after loading of the first track again");
+ assert_equals(cues[cues.length-1].text, 'I said Bear is coming now!!!! Tab separators.', "Last cue content check");
+ assert_equals(cues, testTrack.track.cues, ".cues object are the same after 'src' attr mutation");
+ assert_equals(cues.length, 4, "Number of cues after loading of the first track");
+ ++stage;
+ testTrack.src = "resources/settings.vtt";
+ // This should not raise onLoad or onError event, so we'll wait for it for some time
+ t.step_timeout(t.step_func_done(function() {
+ assert_equals(testTrack.readyState, HTMLTrackElement.LOADED, "readyState after changing 'src' to the same value");
+ assert_equals(cues, testTrack.track.cues, ".cues object are the same after 'src' attr mutation");
+ assert_equals(cues.length, 4, "Number of cues after changing 'src' to the same value");
+ }, 100));
+ break;
+ case 3:
+ assert_unreached("'load' event should not fire, stage = " + stage);
+ break;
+ }
+ }
+
+ testTrack.onload = t.step_func(step_onLoad);
+ testTrack.onerror = t.unreached_func("'error' event should not fire");
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-helpers.js b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-helpers.js
new file mode 100644
index 00000000000..09c85dd7bc1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-helpers.js
@@ -0,0 +1,83 @@
+function enableAllTextTracks(textTracks) {
+ for (var i = 0; i < textTracks.length; i++) {
+ var track = textTracks[i];
+ if (track.mode == "disabled")
+ track.mode = "hidden";
+ }
+}
+
+function assert_cues_equal(cues, expected) {
+ assert_equals(cues.length, expected.length);
+ for (var i = 0; i < cues.length; i++) {
+ assert_equals(cues[i].id, expected[i].id);
+ assert_equals(cues[i].startTime, expected[i].startTime);
+ assert_equals(cues[i].endTime, expected[i].endTime);
+ assert_equals(cues[i].text, expected[i].text);
+ }
+}
+
+function assert_cues_match(cues, expected) {
+ assert_equals(cues.length, expected.length);
+ for (var i = 0; i < cues.length; i++) {
+ var cue = cues[i];
+ var expectedItem = expected[i];
+ for (var property of Object.getOwnPropertyNames(expectedItem))
+ assert_equals(cue[property], expectedItem[property]);
+ }
+}
+
+function assert_cues_html_content(cues, expected) {
+ assert_equals(cues.length, expected.length);
+ for (var i = 0; i < cues.length; i++) {
+ var expectedItem = expected[i];
+ var property = Object.getOwnPropertyNames(expectedItem)[0];
+ var propertyValue = expectedItem[property];
+ assert_equals(propertyValue(cues[i]), expectedItem.expected);
+ }
+}
+
+function check_cues_from_track(src, func) {
+ async_test(function(t) {
+ var video = document.createElement("video");
+ var trackElement = document.createElement("track");
+ trackElement.src = src;
+ trackElement.default = true;
+ video.appendChild(trackElement);
+
+ trackElement.onload = t.step_func_done(function() {
+ func(trackElement.track);
+ });
+ }, "Check cues from " + src);
+}
+
+function assert_cue_fragment(cue, children) {
+ var fragment = createFragment(children);
+ assert_true(fragment.isEqualNode(cue.getCueAsHTML()));
+}
+
+function assert_cue_fragment_as_textcontent(cue, children) {
+ var fragment = createFragment(children);
+ assert_equals(cue.getCueAsHTML().textContent, fragment.textContent);
+}
+
+function createFragment(children) {
+ var fragment = document.createDocumentFragment();
+ cloneChildrenToFragment(fragment, children);
+ return fragment;
+}
+
+function cloneChildrenToFragment(root, children) {
+ for (var child of children) {
+ var childElement;
+ if (child.type == "text") {
+ childElement = document.createTextNode(child.value);
+ } else {
+ childElement = document.createElement(child.type);
+ var styles = child.style || {};
+ for (var attr of Object.getOwnPropertyNames(styles))
+ childElement[attr] = styles[attr];
+ cloneChildrenToFragment(childElement, child.value);
+ }
+ root.appendChild(childElement);
+ }
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-large-timestamp.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-large-timestamp.html
new file mode 100644
index 00000000000..bae1852cf83
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-large-timestamp.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>Very large timestamp is parsed correctly</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/large-timestamp.vtt" default>
+ <script>
+ async_test(function(t) {
+ var testTrack = document.querySelector("track");
+ testTrack.onload = t.step_func_done(function() {
+ assert_equals(testTrack.track.cues.length, 1);
+ var cue = testTrack.track.cues[0];
+ assert_equals(parseInt(cue.id), 1);
+ assert_equals(cue.startTime / 3600, 1234567);
+ assert_equals(cue.endTime / 3600, 1234567890);
+ });
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-load-error-readyState.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-load-error-readyState.html
new file mode 100644
index 00000000000..8e232bff537
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-load-error-readyState.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>Error event on HTMLTrackElement and ERROR readyState on TextTrack</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="junk" default>
+ <script>
+ async_test(function(t) {
+ var track = document.querySelector("track");
+ track.onerror = t.step_func_done(function() {
+ assert_equals(track.readyState, HTMLTrackElement.ERROR);
+ });
+ });
+ </script>
+</video>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-load-from-element-readyState.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-load-from-element-readyState.html
new file mode 100644
index 00000000000..62a68f65439
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-load-from-element-readyState.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>Load event on HTMLTrackElement and LOADED readyState on TextTrack when src is set on the element</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/webvtt-file.vtt" default>
+ <script>
+ async_test(function(t) {
+ var track = document.querySelector("track");
+ track.onload = t.step_func_done(function() {
+ assert_equals(track.readyState, HTMLTrackElement.LOADED);
+ });
+ });
+ </script>
+</video>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-load-from-src-readyState.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-load-from-src-readyState.html
new file mode 100644
index 00000000000..e569eeb96fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-load-from-src-readyState.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title>Load event on HTMLTrackElement and LOADED readyState on TextTrack when src is set from JavaScript</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track>
+</video>
+<script>
+async_test(function(t) {
+ var track = document.querySelector("track");
+ assert_equals(track.readyState, HTMLTrackElement.NONE);
+
+ track.onload = t.step_func_done(function() {
+ assert_equals(track.readyState, HTMLTrackElement.LOADED);
+ });
+
+ track.src = "resources/webvtt-file.vtt";
+ track.track.mode = "hidden";
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode-disabled.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode-disabled.html
new file mode 100644
index 00000000000..6b46bf4e344
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode-disabled.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<title>Cues are properly removed from the active cue list when their track changes mode to disabled</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/captions-gaps.vtt" kind="captions" default >
+ <script>
+ async_test(function(t) {
+ var video = document.querySelector("video");
+ var testTrack = document.querySelector("track");
+
+ video.src = getVideoURI("/media/counting");
+ video.oncanplaythrough = t.step_func(startTest);
+ video.onseeked = t.step_func_done(seeked);
+
+ function startTest() {
+ // Set the mode of the text track to "showing".
+ testTrack.track.mode = "showing";
+ // Seek to a time with a caption.
+ video.currentTime = 1.5;
+ }
+
+ function seeked() {
+ // Set the mode of the text track to "hidden", then to "showing" again.
+ testTrack.track.mode = "hidden";
+ testTrack.track.mode = "showing";
+
+ // Set the mode of the text track to "disabled".
+ testTrack.track.mode = "disabled";
+ }
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode-not-changed-by-new-track.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode-not-changed-by-new-track.html
new file mode 100644
index 00000000000..2902ba90bc9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode-not-changed-by-new-track.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<title>A track appended after the initial track configuration does not change other tracks</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track kind="metadata" src="resources/metadata.vtt">
+</video>
+<script>
+async_test(function(t) {
+ var video = document.querySelector('video');
+
+ var track1 = document.querySelectorAll('track')[0];
+ assert_equals(track1.readyState, HTMLTrackElement.NONE);
+ assert_equals(track1.track.mode, 'disabled');
+
+ video.src = getVideoURI('/media/test');
+ video.oncanplaythrough = t.step_func(canplaythrough);
+ track1.onload = t.step_func(metadataTrackLoaded);
+
+ function canplaythrough() {
+ // check initial metadata track state.
+ assert_equals(track1.readyState, HTMLTrackElement.NONE);
+ assert_equals(track1.track.mode, 'disabled');
+ assert_equals(track1.track.cues, null);
+ track1.track.mode = 'hidden';
+ }
+
+ function metadataTrackLoaded() {
+ // check metadata track state.
+ assert_equals(track1.readyState, HTMLTrackElement.LOADED);
+ assert_equals(track1.track.mode, 'hidden');
+ assert_equals(track1.track.cues.length, 12);
+ assert_equals(track1.track.cues[11].startTime, 22);
+
+ // Add a caption track, configured to load automatically.
+ track2 = document.createElement('track');
+ track2.setAttribute('kind', 'captions');
+ track2.setAttribute('default', 'default');
+ track2.setAttribute('src', 'resources/webvtt-file.vtt');
+ track2.onload = t.step_func(captionsTrackLoaded);
+ video.appendChild(track2);
+ }
+
+ function captionsTrackLoaded() {
+ // Check that metadata track state has not changed.
+ assert_equals(track1.readyState, HTMLTrackElement.LOADED);
+ assert_equals(track1.track.mode, 'hidden');
+ // and that the caption track state is correct.
+ assert_equals(track2.readyState, HTMLTrackElement.LOADED);
+ assert_equals(track2.track.mode, 'showing');
+
+ video.textTracks.onaddtrack = t.step_func_done(trackAdded);
+ // add a subtitle track with video.addTextTrack().
+ track3 = video.addTextTrack('subtitles', 'Subtitle Track', 'en');
+ track3.mode = 'showing';
+ }
+
+ function trackAdded() {
+ // Check that metadata track state has not changed.
+ assert_equals(track1.readyState, HTMLTrackElement.LOADED);
+ assert_equals(track1.track.mode, 'hidden');
+ // and that the caption track state has not changed.
+ assert_equals(track2.readyState, HTMLTrackElement.LOADED);
+ assert_equals(track2.track.mode, 'showing');
+ // and that the subtitle track state is correct.
+ assert_equals(event.target, video.textTracks);
+ assert_true(event instanceof window.TrackEvent);
+ assert_equals(event.track, video.textTracks[video.textTracks.length - 1]);
+ assert_equals(track3.mode, 'showing');
+ }
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode-triggers-loading.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode-triggers-loading.html
new file mode 100644
index 00000000000..2e29d704690
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode-triggers-loading.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<title>A "metadata" track does not load automatically, but it does load when the mode is changed</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track kind="metadata" src="resources/metadata.vtt">
+</video>
+<script>
+async_test(function(t) {
+ var video = document.querySelector("video");
+
+ // Check initial metadata track state.
+ var track = document.querySelectorAll("track")[0];
+ assert_equals(track.readyState, HTMLTrackElement.NONE);
+ assert_equals(video.textTracks[0].mode, "disabled");
+
+ video.src = getVideoURI("/media/test");
+ video.oncanplaythrough = t.step_func(canplaythrough);
+ track.onload = t.step_func_done(trackLoaded);
+
+ function trackLoaded() {
+ assert_equals(track.readyState, HTMLTrackElement.LOADED);
+ assert_equals(track.track.mode, "hidden");
+ assert_equals(video.textTracks[0].cues.length, 12);
+ assert_equals(video.textTracks[0].cues[11].startTime, 22);
+ }
+
+ function canplaythrough() {
+ assert_equals(track.readyState, HTMLTrackElement.NONE);
+ assert_equals(video.textTracks[0].mode, "disabled");
+ assert_equals(video.textTracks[0].cues, null);
+ // Change metadata track mode so it loads.
+ video.textTracks[0].mode = "hidden";
+ }
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode.html
new file mode 100644
index 00000000000..29208a33c21
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-mode.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<title>TextTrack mode attribute</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/captions-fast.vtt" default>
+ <script>
+ async_test(function(t) {
+ var video = document.querySelector("video");
+ var track = document.querySelector("track");
+ track.onload = t.step_func(trackLoaded);
+
+ var cueCount = 0;
+ var textTrack;
+ function trackLoaded() {
+ textTrack = track.track;
+ // Test default attribute value.
+ assert_equals(textTrack.mode, "showing");
+ assert_equals(video.textTracks[0].mode, "showing");
+ // Set to bogus value, should return default.
+ var value = "bogus";
+ textTrack.mode = value;
+ assert_equals(textTrack.mode, "showing");
+ assert_equals(video.textTracks[0].mode, "showing");
+
+ // Set to numeric value (no longer supported), should return default.
+ textTrack.mode = 2;
+ assert_equals(textTrack.mode, "showing");
+ assert_equals(video.textTracks[0].mode, "showing");
+
+ // Set to known values.
+ setModeAndCheck("disabled");
+
+ video.src = getVideoURI("/media/test");
+ video.play();
+ // Wait for end of first cue (no events should fire while track is disabled).
+ t.step_timeout(testHiddenAndShowing, 400);
+ }
+
+ track.oncuechange = t.step_func(function(event) {
+ cueCount++;
+ if (cueCount == textTrack.cues.length)
+ t.done();
+ });
+
+ function setModeAndCheck(value) {
+ textTrack.mode = value;
+ assert_equals(textTrack.mode, value);
+ assert_equals(video.textTracks[0].mode, value);
+ if (value == "disabled")
+ assert_equals(textTrack.cues, null);
+ }
+
+ function testHiddenAndShowing() {
+ setModeAndCheck("hidden");
+ setModeAndCheck("showing");
+ }
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-active-cue.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-active-cue.html
new file mode 100644
index 00000000000..176e0065c59
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-active-cue.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<title>Removing an active cue</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video></video>
+<script>
+async_test(function(t) {
+ var video = document.querySelector("video");
+ video.src = getVideoURI("/media/test");
+
+ // Add a text track to the video element.
+ video.addTextTrack("captions", "regular captions track", "en");
+
+ // Add a cue to the track with enter event listener.
+ var cue = new VTTCue(0, 4, "Random");
+ cue.onenter = t.step_func_done(removeActiveCue);
+
+ var track = video.textTracks[0];
+ track.addCue(cue);
+
+ function removeActiveCue() {
+ assert_equals(track.activeCues.length, 1);
+
+ // Remove the cue while it is active.
+ track.removeCue(track.activeCues[0]);
+
+ // No crash. PASS.
+ }
+
+ // Play the video and remove cue when it becomes active.
+ video.play();
+ track.mode = "showing";
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-by-setting-innerHTML.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-by-setting-innerHTML.html
new file mode 100644
index 00000000000..95929bc83fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-by-setting-innerHTML.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<title>Removing a track by setting video.innerHTML doesn't crash</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track default src="resources/captions-gaps.vtt">
+ <script>
+ // https://bugs.webkit.org/show_bug.cgi?id=100981
+ async_test(function(t) {
+ var firstSeek = true;
+ var video = document.querySelector('video');
+ video.onseeked = t.step_func(function() {
+ if (!firstSeek) {
+ t.done();
+ return;
+ }
+
+ // Remove the text track
+ video.innerHTML = '';
+
+ // Seek again to force a repaint.
+ video.currentTime = 7.9;
+ firstSeek = false;
+ });
+
+ video.currentTime = 0.5;
+ video.src = getVideoURI('/media/counting');
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-insert-ready-state.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-insert-ready-state.html
new file mode 100644
index 00000000000..1c854aca0ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-insert-ready-state.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<title>Attaching a media element again to the document, having a child track that failed loading doesn't block video from playing</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/no-webvtt.vtt" kind="captions" default>
+ <script>
+ async_test(function(t) {
+ var video = document.querySelector('video');
+ video.src = getVideoURI('/media/test');
+ video.oncanplaythrough = t.step_func(canplaythrough);
+
+ function canplaythrough() {
+ video.oncanplaythrough = null;
+ var track = document.querySelector('track');
+
+ // Track should have error as ready state.
+ assert_equals(track.readyState, HTMLTrackElement.ERROR);
+
+ // Remove the video element from body.
+ document.body.removeChild(video);
+
+ // Reset the video src attribute to re-trigger resource selection for tracks.
+ video.src = getVideoURI('/media/test');
+
+ // Append the video element back to the body.
+ document.body.appendChild(video);
+
+ assert_equals(track.readyState, HTMLTrackElement.ERROR);
+
+ video.onplaying = t.step_func_done();
+ video.play();
+ // The video should start playing.
+ }
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-quickly.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-quickly.html
new file mode 100644
index 00000000000..4be040c5f87
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-quickly.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<title>Removing a track element before it has been processed doesn't crash</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="video_container"></div>
+<script>
+var mediaFile = getVideoURI("/media/test");
+document.getElementById("video_container").innerHTML = "<video src='" + mediaFile + "' controls ><track kind='captions' src='resources/simple-captions.vtt' default ></video>";
+test(function() {
+// https://bugs.webkit.org/show_bug.cgi?id=85095
+// Test passes if it doesn't crash.
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-track.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-track.html
new file mode 100644
index 00000000000..29938e31029
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-remove-track.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+ <script src="/common/media.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <script>
+ async_test(function(test)
+ {
+ var video = document.createElement("video");
+ var track;
+
+ function trackRemoved()
+ {
+ assert_equals(event.target, video.textTracks);
+ assert_equals(event instanceof window.TrackEvent, true);
+ assert_equals(event.track, track);
+ test.done();
+ }
+
+ var trackElement = document.createElement('track');
+ video.appendChild(trackElement);
+
+ trackElement.src = 'resources/webvtt-file.vtt';
+ trackElement.track.mode = 'hidden';
+
+ assert_equals(video.textTracks.length, 1);
+
+ track = video.textTracks[0];
+ video.removeChild(trackElement);
+ video.textTracks.addEventListener("removetrack", test.step_func(trackRemoved));
+ }, "Tests that the 'removetrack' event is fired when an out-of-band TextTrack is removed.");
+
+ async_test(function(test)
+ {
+ var video = document.createElement("video");
+
+ // Create an out-of-band text track by adding a track element.
+ var trackElement = document.createElement('track');
+
+ trackElement.addEventListener("error", test.step_func(function()
+ {
+ assert_unreached("'error' event on track element should not fire.")
+ }));
+
+ video.appendChild(trackElement);
+ trackElement.src = 'resources/webvtt-file.vtt';
+ trackElement.track.mode = 'hidden';
+
+ assert_equals(video.textTracks.length, 1);
+ var outOfBandTrack = video.textTracks[0];
+
+ // Load a media file with an inband text track.
+ var inbandTrack = null;
+ var url = "resources/vp8-vorbis-webvtt.webm"
+
+ var firstAddTrackHandler = test.step_func(function()
+ {
+ assert_equals(event.target, video.textTracks);
+ assert_equals(event instanceof window.TrackEvent, true);
+ if (event.track == outOfBandTrack) {
+ return;
+ }
+
+ assert_equals(inbandTrack, null);
+ assert_equals(video.textTracks.length, 2);
+ assert_equals(event.track, video.textTracks[1]);
+ inbandTrack = event.track;
+
+ video.textTracks.removeEventListener("addtrack", firstAddTrackHandler);
+
+ // Clear .src to force the inband track to get destroyed.
+ video.src = "";
+
+ // Verify that the inband track was removed.
+ assert_not_equals(inbandTrack, null);
+ assert_equals(video.textTracks.length, 1);
+ assert_equals(video.textTracks[0], outOfBandTrack);
+
+ // Load the URL again to trigger another 'addtrack' event to make sure
+ // no 'removetrack' event was queued.
+ video.src = url;
+ video.textTracks.addEventListener("addtrack", test.step_func(function()
+ {
+ assert_equals(video.textTracks.length, 2);
+ test.done();
+ }));
+ });
+ video.textTracks.addEventListener("addtrack", firstAddTrackHandler);
+
+ video.textTracks.addEventListener("removetrack", test.step_func(function()
+ {
+ assert_unreached("'removetrack' event should not fire.")
+ }));
+
+ video.src = url;
+ }, "Tests that the 'removetrack' event is NOT fired for inband TextTrack on a failed load.");
+
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-align-positioning.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-align-positioning.html
new file mode 100644
index 00000000000..07ebfd622b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-align-positioning.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<title>Cue text position and alignment from settings</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/align-positioning.vtt">
+ <track src="resources/align-positioning-bad.vtt">
+</video>
+<script>
+async_test(function(t) {
+ var video = document.querySelector("video");
+
+ var trackElements = document.querySelectorAll("track");
+ assert_equals(trackElements.length, video.textTracks.length);
+ for (var i = 0; i < trackElements.length; i++)
+ trackElements[i].onload = t.step_func(trackLoaded);
+
+ enableAllTextTracks(video.textTracks);
+
+ var numberOfTracksLoaded = 0;
+ function trackLoaded() {
+ numberOfTracksLoaded++;
+ if (numberOfTracksLoaded != 2)
+ return;
+
+ testTrack(0);
+ testTrackError(1);
+ t.done();
+ }
+
+ function testTrack(index) {
+ var expected = [
+ { position : 10, align : "start" },
+ { position : 20, align : "center" },
+ { position : 80, align : "end" }
+ ];
+
+ assert_cues_match(video.textTracks[index].cues, expected);
+ }
+
+ function testTrackError(index) {
+ var expected = [
+ { position : 10, align : "center" },
+ { position : "auto", align : "center" },
+ { position : "auto", align : "center" }
+ ];
+
+ assert_cues_match(video.textTracks[index].cues, expected);
+ }
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-align-text-line-position.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-align-text-line-position.html
new file mode 100644
index 00000000000..deb389916ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-align-text-line-position.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<title>Cue alignment, line and text position from settings</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/align-text-line-position.vtt">
+ <track src="resources/align-text-line-position-bad.vtt">
+</video>
+<script>
+async_test(function(t) {
+ var video = document.querySelector("video");
+
+ var trackElements = document.querySelectorAll("track");
+ assert_equals(trackElements.length, video.textTracks.length);
+ for (var i = 0; i < trackElements.length; i++)
+ trackElements[i].onload = t.step_func(trackLoaded);
+
+ enableAllTextTracks(video.textTracks);
+
+ var numberOfTracksLoaded = 0;
+ function trackLoaded() {
+ numberOfTracksLoaded++;
+ if (numberOfTracksLoaded != 2)
+ return;
+
+ testTrack(0);
+ testTrackError(1);
+ t.done();
+ }
+
+ function testTrack(index) {
+ var expected = [
+ { align : "start", position : 10, line : 0, snapToLines : false },
+ { align : "start", position : "auto", line : 0, snapToLines : true },
+ { align : "center", position : 80, line : 80, snapToLines : false },
+ { align : "end", position : 30, line : 5, snapToLines : true },
+ { align : "center", position : 60, line : -3, snapToLines : true }
+ ];
+
+ assert_cues_match(video.textTracks[index].cues, expected);
+ }
+
+ function testTrackError(index) {
+ var expected = [
+ { align : "center", position : "auto", line : "auto", snapToLines : true },
+ { align : "end", position : 0, line : "auto", snapToLines : true },
+ { align : "center", position : 60, line : -3, snapToLines : true }
+ ];
+
+ assert_cues_match(video.textTracks[index].cues, expected);
+ }
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-alignment.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-alignment.html
new file mode 100644
index 00000000000..e8f47e876a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-alignment.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<title>Cue alignment from settings</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/alignment.vtt", testTrack);
+check_cues_from_track("resources/alignment-ltr.vtt", testTrack);
+
+check_cues_from_track("resources/alignment-bad.vtt", function(track) {
+ var expected = [
+ { align: "center" },
+ { align: "center" },
+ { align: "center" },
+ { align: "center" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+
+function testTrack(track) {
+ var expected = [
+ { align: "start" },
+ { align: "center" },
+ { align: "end" },
+ { align: "center" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-blank-lines.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-blank-lines.html
new file mode 100644
index 00000000000..114aebc38c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-blank-lines.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Cues are affected neither by multiple newlines \n, \r, and \r\n nor by the absence of a seperating line</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/cues.vtt", function(track) {
+ var expected = [
+ { id: "1", startTime: 0, endTime: 30.5, text: "Bear is Coming!!!!!" },
+ { id: "2", startTime: 31, endTime: 60.5, text: "I said Bear is coming!!!!" },
+ { id: "3", startTime: 61, endTime: 361200.5, text: "I said Bear is coming now!!!!" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+
+check_cues_from_track("resources/cues-no-separation.vtt", function(track) {
+ var expected = [
+ { id: "1", startTime: 0, endTime: 30.5, text: "Bear is Coming!!!!!\n2" },
+ { id: "", startTime: 31, endTime: 60.5, text: "I said Bear is coming!!!!" },
+ { id: "", startTime: 61, endTime: 361200.5, text: "I said Bear is coming now!!!!" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-bom.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-bom.html
new file mode 100644
index 00000000000..c138f96af57
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-bom.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<title>Parser properly ignores a UTF-8 BOM character at the beginning of a file and all other cues are properly parsed</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/bom.vtt" default>
+ <script>
+ async_test(function(t) {
+ var track = document.querySelector("track");
+
+ track.onload = t.step_func_done(function() {
+ var expected = [
+ {
+ id : "1",
+ startTime : 0,
+ endTime : 30.5,
+ text : "Bear is Coming!!!!!"
+ },
+ {
+ id : "2",
+ startTime : 31,
+ endTime : 1200.5,
+ text : "I said Bear is coming!!!!"
+ }
+ ];
+
+ var cues = track.track.cues;
+ assert_equals(cues.length, 2);
+ assert_cues_equal(cues, expected);
+ });
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-class-markup.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-class-markup.html
new file mode 100644
index 00000000000..fe3c868c587
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-class-markup.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<title>Tests cues with class markup &lt;c&gt;.</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/class.vtt", function(track) {
+ assert_equals(track.cues.length, 3);
+
+ var children = [
+ { type: "span", style: { className: "black" },
+ value: [ { type: "text", value: "Bear is Coming!!!!!" } ] }
+ ];
+ assert_cue_fragment(track.cues[0], children);
+
+ children = [
+ { type: "span", style: { className: "green" },
+ value: [ { type: "text", value: "I said Bear is coming!!!!" } ] }
+ ];
+ assert_cue_fragment(track.cues[1], children);
+
+ children = [
+ { type: "text", value: "I said " },
+ { type: "span", style: { className: "red uppercase" },
+ value: [ { type: "text", value: "Bear is coming now" } ] },
+ { type: "text", value: "!!!!" }
+ ];
+ assert_cue_fragment(track.cues[2], children);
+});
+
+check_cues_from_track("resources/class-bad.vtt", function(track) {
+ assert_equals(track.cues.length, 3);
+
+ var children = [
+ { type: "span", value: [ { type: "text", value: "Bear is Coming!!!!!" } ] },
+ { type: "text", value: "\nThe space signified an annotation start." }
+ ];
+ assert_cue_fragment(track.cues[0], children);
+
+ children = [
+ { type: "span", style: { className: "red&large" },
+ value: [ { type: "text", value: "I said Bear is coming!!!!" } ] },
+ { type: "text", value: "\nProbably should only allow characters that CSS allows in class names." }
+ ];
+ assert_cue_fragment(track.cues[1], children);
+
+ children = [
+ { type: "text", value: "I said " },
+ { type: "span", style: { className: "9red upper+case" },
+ value: [ { type: "text", value: "Bear is coming now" } ] },
+ { type: "text", value: "!!!!\nProbably should only allow characters that CSS allows in class names." }
+ ];
+ assert_cue_fragment(track.cues[2], children);
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-identifiers.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-identifiers.html
new file mode 100644
index 00000000000..02b0a15187a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-identifiers.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Any text other than "-->" is recognized as optional cue identifier</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/cue-id.vtt", function(track) {
+ var expected = [
+ { id: "random_id", startTime: 0, endTime: 30.5, text: "Bear is Coming!!!!!" },
+ { id: "another random identifier", startTime: 31, endTime: 60.5, text: "I said Bear is coming!!!!" },
+ { id: "identifier--too", startTime: 61, endTime: 120.5, text: "I said Bear is coming now!!!!" },
+ { id: "identifier--too", startTime: 121, endTime: 180.5, text: "Duplicate identifier" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+
+check_cues_from_track("resources/cue-id-error.vtt", function(track) {
+ var expected = [
+ { id: "", startTime: 0, endTime: 30.5, text: "Bear is Coming!!!!!" },
+ { id: "", startTime: 31, endTime: 60.5, text: "I said Bear is coming!!!!" },
+ { id: "", startTime: 61, endTime: 1200.5, text: "I said Bear is coming now!!!!" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-no-id.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-no-id.html
new file mode 100644
index 00000000000..b2f4b770831
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-no-id.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>Empty cue identifiers, but having "-->" leads to discarded cue</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/cue-no-id.vtt", testTrack);
+check_cues_from_track("resources/cue-no-id-error.vtt", testTrack);
+
+function testTrack(track) {
+ var expected = [
+ { id: "", startTime: 0, endTime: 30.5, text: "Bear is Coming!!!!!" },
+ { id: "", startTime: 31, endTime: 60.5, text: "I said Bear is coming!!!!" },
+ { id: "", startTime: 61, endTime: 1200.5, text: "I said Bear is coming now!!!!" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+}
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-recovery.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-recovery.html
new file mode 100644
index 00000000000..6a104916b7c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-recovery.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>A cue is recovered when a line with a "-->" is encountered without blank line separator</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/cue-recovery-header.vtt", testTrack);
+check_cues_from_track("resources/cue-recovery-note.vtt", testTrack);
+check_cues_from_track("resources/cue-recovery-cuetext.vtt", testTrack);
+
+function testTrack(track) {
+ var expected = [
+ { startTime: 0, endTime: 1, text: "Valid cue 1" },
+ { startTime: 2, endTime: 3, text: "Valid cue 2" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+}
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-size-align.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-size-align.html
new file mode 100644
index 00000000000..a1243a95e7d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-size-align.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Cue size and alignment from settings</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/cue-size-align.vtt", function(track) {
+ var expected = [
+ { size: 100, align: "start" },
+ { size: 10, align: "end" },
+ { size: 0, align: "center" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+
+check_cues_from_track("resources/cue-size-align-bad.vtt", function(track) {
+ var expected = [
+ { size: 100, align: "center" },
+ { size: 100, align: "end" },
+ { size: 100, align: "center" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-size.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-size.html
new file mode 100644
index 00000000000..d8e03edce7f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-size.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Cue size from settings</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/cue-size.vtt", function(track) {
+ var expected = [
+ { size: 100 },
+ { size: 10 },
+ { size: 0 }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+
+check_cues_from_track("resources/cue-size-bad.vtt", function(track) {
+ var expected = [
+ { size: 100 },
+ { size: 100 },
+ { size: 100 }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-degenerate-cues.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-degenerate-cues.html
new file mode 100644
index 00000000000..8d2569993c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-degenerate-cues.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>Degenerate cues without separating blank lines</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/degenerate-cues.vtt", function(track) {
+ var expected = [
+ { startTime: 0, endTime: 1, text: "" },
+ { startTime: 2, endTime: 3, text: "" },
+ { startTime: 4, endTime: 5, text: "" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-empty-cue.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-empty-cue.html
new file mode 100644
index 00000000000..e1f55702500
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-empty-cue.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<title>Empty cues should not be discarded</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/empty-cue.vtt", function(track) {
+ assert_equals(track.cues.length, 3);
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-entities.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-entities.html
new file mode 100644
index 00000000000..a5295795ef0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-entities.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<title>Entities in the cue text</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+var getCueAsHTMLContent = function(cue) {
+ return cue.getCueAsHTML().textContent;
+};
+
+check_cues_from_track("resources/entities.vtt", function(track) {
+ var expected = [
+ { innerHTML: getCueAsHTMLContent,
+ expected: "This cue has an ampersand & character." },
+ { innerHTML: getCueAsHTMLContent,
+ expected: "This cue has a less than < character." },
+ { innerHTML: getCueAsHTMLContent,
+ expected: "This cue has a greater than > character." },
+ { innerHTML: getCueAsHTMLContent,
+ expected: "This cue has a Left-to-Right Mark \u200e." },
+ { innerHTML: getCueAsHTMLContent,
+ expected: "This cue has a Right-to-Left Mark \u200f." },
+ { innerHTML: getCueAsHTMLContent,
+ expected: "This cue has a non-breaking space \u00a0." },
+ { innerHTML: getCueAsHTMLContent,
+ expected: "This & is parsed to the same as &." }
+ ];
+
+ assert_cues_html_content(track.cues, expected);
+});
+
+check_cues_from_track("resources/entities-wrong.vtt", function(track) {
+ var expected = [
+ { innerHTML: getCueAsHTMLContent,
+ expected: "This cue has a less than ", },
+ { innerHTML: getCueAsHTMLContent,
+ expected: "This cue has a greater than > character.\nSince it's not related to a < character,\nit's just interpreted as text.", }
+ ];
+
+ assert_cues_html_content(track.cues, expected);
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-header-comment.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-header-comment.html
new file mode 100644
index 00000000000..f9b35576f34
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-header-comment.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<title>Optional comment area under the "WEBVTT" file header is properly ignored and also, default settings and styling are currently ignored (treated as faulty cues)</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/default-styles.vtt">
+ <track src="resources/metadata-area.vtt">
+</video>
+<script>
+async_test(function(t) {
+ var video = document.querySelector("video");
+
+ var trackElements = document.querySelectorAll("track");
+ for (var i = 0; i < video.textTracks.length; i++)
+ trackElements[i].onload = t.step_func(trackLoaded);
+
+ enableAllTextTracks(video.textTracks);
+
+ var numberOfTracksLoaded = 0;
+ function trackLoaded() {
+ numberOfTracksLoaded++;
+ if (numberOfTracksLoaded != 2)
+ return;
+
+ testTrack(0);
+ testTrack(1);
+ t.done();
+ }
+
+ function testTrack(index) {
+ var expected = [
+ {
+ id : "1",
+ startTime : 0,
+ endTime : 30.5,
+ text : "Bear is Coming!!!!!"
+ },
+ {
+ id : "2",
+ startTime : 31,
+ endTime : 1200.5,
+ text : "I said Bear is coming!!!!"
+ }
+ ];
+
+ assert_cues_equal(video.textTracks[index].cues, expected);
+ }
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-interspersed-non-cue.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-interspersed-non-cue.html
new file mode 100644
index 00000000000..2287cc2830e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-interspersed-non-cue.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>An empty line after an identifier line discards the current cue and restarts the cue loop</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/interspersed-non-cue.vtt", function(track) {
+ var expected = [
+ { text: "First" },
+ { text: "Second" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-line-position.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-line-position.html
new file mode 100644
index 00000000000..bea4acb917a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-line-position.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<title>Cue line position from settings</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/line-position.vtt">
+ <track src="resources/line-position-bad.vtt">
+</video>
+<script>
+async_test(function(t) {
+ var video = document.querySelector("video");
+
+ var trackElements = document.querySelectorAll("track");
+ assert_equals(trackElements.length, video.textTracks.length);
+ for (var i = 0; i < trackElements.length; i++)
+ trackElements[i].onload = t.step_func(trackLoaded);
+
+ enableAllTextTracks(video.textTracks);
+
+ var numberOfTracksLoaded = 0;
+ function trackLoaded() {
+ numberOfTracksLoaded++;
+ if (numberOfTracksLoaded != 2)
+ return;
+
+ testTrack(0);
+ testTrackError(1);
+ t.done();
+ }
+
+ function testTrack(index) {
+ var expected = [
+ { line : 0, snapToLines : false },
+ { line : 0, snapToLines : true },
+ { line : 50, snapToLines : false },
+ { line : 5, snapToLines : true },
+ { line : 100, snapToLines : false },
+ { line : -1, snapToLines : true },
+ { line : 500, snapToLines : true }
+ ];
+
+ assert_cues_match(video.textTracks[index].cues, expected);
+ }
+
+ function testTrackError(index) {
+ var expected = [
+ { line : "auto", snapToLines : true },
+ { line : "auto", snapToLines : true },
+ { line : "auto", snapToLines : true },
+ { line : "auto", snapToLines : true },
+ { line : "auto", snapToLines : true }
+ ];
+
+ assert_cues_match(video.textTracks[index].cues, expected);
+ }
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-magic-header.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-magic-header.html
new file mode 100644
index 00000000000..ff4637a8a5f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-magic-header.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<title>Magic file header "WEBVTT" leads to the file properly recognized as a WebVTT file</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/webvtt-file.vtt">
+ <track src="resources/webvtt-rubbish.vtt">
+ <track src="resources/no-webvtt.vtt">
+</video>
+<script>
+async_test(function(t) {
+ var video = document.querySelector("video");
+
+ var trackElements = document.querySelectorAll("track");
+ trackElements[0].onload = t.step_func(trackLoaded);
+ trackElements[1].onload = t.step_func(trackLoaded);
+ trackElements[2].onerror = t.step_func(trackLoaded);
+
+ enableAllTextTracks(video.textTracks);
+
+ var numberOfTracksLoaded = 0;
+ function trackLoaded() {
+ numberOfTracksLoaded++;
+ if (numberOfTracksLoaded != 3)
+ return;
+
+ testTrack(0);
+ testTrack(1);
+ testTrackError(2);
+ t.done();
+ }
+
+ function testTrack(index) {
+ var expected = [
+ {
+ id : "1",
+ startTime : 0,
+ endTime : 30.5,
+ text : "Bear is Coming!!!!!"
+ },
+ {
+ id : "2",
+ startTime : 31,
+ endTime : 1200.5,
+ text : "I said Bear is coming!!!!"
+ }
+ ];
+
+ assert_cues_equal(video.textTracks[index].cues, expected);
+ }
+
+ function testTrackError(index) {
+ assert_cues_equal(video.textTracks[index].cues, []);
+ }
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-markup.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-markup.html
new file mode 100644
index 00000000000..2b044379f14
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-markup.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<title>Cues with &lt;b&gt;, &lt;i&gt;, &lt;u&gt;, &lt;rt&gt; and &lt;ruby&gt; tags</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/markup.vtt", function(track) {
+ assert_equals(track.cues.length, 4);
+
+ var children = [
+ { type: "text", value: "The following bear is bold:\n" },
+ { type: "b", value: [ { type: "text", value: "Bear" } ] },
+ { type: "text", value: " is Coming!!!!!" }
+ ];
+ assert_cue_fragment(track.cues[0], children);
+
+ children = [
+ { type: "text", value: "The following bear is in italics and has a class of \"larger\":\n" },
+ { type: "i", value: [ { type: "text", value: "Bear" } ] },
+ { type: "text", value: " is Coming!!!!!" }
+ ];
+
+ var fragment = createFragment(children);
+ fragment.querySelector("i").className = "larger";
+ assert_true(fragment.isEqualNode(track.cues[1].getCueAsHTML()));
+
+ children = [
+ { type: "text", value: "The following bear is underlined even though the element has a blank:\nI said " },
+ { type: "u", value: [ { type: "text", value: "Bear" } ] },
+ { type: "text", value: " is coming!!!!" }
+ ];
+ assert_cue_fragment(track.cues[2], children);
+
+ children = [
+ { type: "text", value: "The following bear is ruby annotated:\nI said " },
+ {
+ type: "ruby",
+ value: [
+ { type: "text", value: "Bear" },
+ {
+ type: "rt",
+ value: [ { type: "text", value: "bear with me" } ]
+ }
+ ]
+ },
+ { type: "text", value: " is coming!!!!" }
+ ];
+ assert_cue_fragment(track.cues[3], children);
+});
+
+check_cues_from_track("resources/markup-bad.vtt", function(track) {
+ assert_equals(track.cues.length, 4);
+
+ var children = [
+ { type: "text", value: "The following bear starts bold but end is broken:\n" },
+ {
+ type: "b",
+ value:
+ [
+ { type: "text", value: "Bear" },
+ { type: "text", value: " is Coming!!!!!" }
+ ]
+ }
+ ];
+ assert_cue_fragment(track.cues[0], children);
+
+ children = [
+ { type: "text", value: "The following bear is not in italics but the markup is removed:\n" },
+ { type: "text", value: "Bear" },
+ { type: "text", value: " is Coming!!!!!" }
+ ];
+ assert_cue_fragment(track.cues[1], children);
+
+ children = [
+ { type: "text", value: "The following bear is not underlined and markup is removed:\nI said " },
+ { type: "text", value : "Bear" },
+ { type: "text", value : " is coming!!!!" }
+ ];
+ assert_cue_fragment(track.cues[2], children);
+
+ children = [
+ { type: "text", value: "The following bear is not ruby annotated and markup is removed:\nI said " },
+ { type: "text", value: "Bear" },
+ { type: "text", value: "bear with me" },
+ { type: "text", value: " is coming!!!!" }
+ ];
+ assert_cue_fragment(track.cues[3], children);
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-newlines.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-newlines.html
new file mode 100644
index 00000000000..4da7e6b1b9c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-newlines.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>A cue with no newline at eof is parsed properly</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/no-newline-at-eof.vtt" default>
+ <script>
+ async_test(function(t) {
+ var track = document.querySelector("track");
+
+ track.onload = t.step_func_done(function() {
+ var expected = [
+ {
+ id : "1",
+ startTime : 0,
+ endTime : 30.5,
+ text : "Bear is Coming!!!!!"
+ }
+ ];
+
+ assert_cues_equal(track.track.cues, expected);
+ });
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-no-timings.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-no-timings.html
new file mode 100644
index 00000000000..a39a2c37aa5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-no-timings.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>Cue without timings are ignored</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/no-timings.vtt" default>
+ <script>
+ async_test(function(t) {
+ var track = document.querySelector("track");
+
+ track.onload = t.step_func_done(function() {
+ assert_cues_equal(track.track.cues, []);
+ });
+ });
+ </script>
+</video> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-positioning.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-positioning.html
new file mode 100644
index 00000000000..d14a5768d3a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-positioning.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<title>Cue text position from settings</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/positioning.vtt", testTrack);
+check_cues_from_track("resources/positioning-ltr.vtt", testTrack);
+
+check_cues_from_track("resources/positioning-bad.vtt", function(track) {
+ var expected = [
+ { position: "auto" },
+ { position: "auto" },
+ { position: "auto" },
+ { position: "auto" },
+ { position: "auto" },
+ { position: "auto" },
+ { position: "auto" },
+ { position: "auto" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+
+function testTrack(track) {
+ var expected = [
+ { position: 0 },
+ { position: 50 },
+ { position: "auto" },
+ { position: 100 }
+ ];
+
+ assert_cues_match(track.cues, expected);
+}
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-settings.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-settings.html
new file mode 100644
index 00000000000..9ad98ffa1aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-settings.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>WebVTT settings</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/settings.vtt", function(track) {
+ var expected = [
+ { line: 100, position: "auto", align: "start", vertical: "" },
+ { line: 15, position: 40, align: "center", vertical: "rl" },
+ { line: "auto", position: 10, align: "center", vertical: "" },
+ { line: 95, position: "auto", align: "end", vertical: "lr" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+
+check_cues_from_track("resources/settings-bad-separation.vtt", function(track) {
+ var expected = [
+ { line: 43, position: 10, align: "center", vertical: "" },
+ { line: "auto", position: 50, align: "end", vertical: "" },
+ { line: "auto", position: "auto", align: "center", vertical: "" },
+ { line: "auto", position: 90, align: "center", vertical: "lr" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timestamp.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timestamp.html
new file mode 100644
index 00000000000..e311f121f25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timestamp.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<title>Cues with &lt;timestamps&gt; tags</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/timestamp.vtt", function(track) {
+ assert_equals(track.cues.length, 3);
+
+ // TODO(srirama.m): Timestamps are handled as ProcessingInstructions,
+ // but because ProcessingInstructions are used in XML and not HTML,
+ // they are ignored here. This should later be tested with oncuechange events.
+
+ var children = [ { type: "text", value: "This cue is painted on." } ];
+ assert_cue_fragment_as_textcontent(track.cues[0], children);
+
+ children = [ { type: "text", value: "I said Bear is coming!!!!" } ];
+ assert_cue_fragment_as_textcontent(track.cues[1], children);
+
+ children = [ { type: "text", value: "I said Bear is coming now!!!!" } ];
+ assert_cue_fragment_as_textcontent(track.cues[2], children);
+});
+
+check_cues_from_track("resources/timestamp-bad.vtt", function(track) {
+ assert_equals(track.cues.length, 3);
+
+ var children = [ { type: "text", value: "This cue is painted on.\nBut since the last two timestamps are out of order, they are ignored." } ];
+ assert_cue_fragment_as_textcontent(track.cues[0], children);
+
+ children = [ { type: "text", value: "I said Bear is coming!!!!\nAll of these timestamps are before the start of the cue, so get ignored." } ];
+ assert_cue_fragment_as_textcontent(track.cues[1], children);
+
+ children = [ { type: "text", value: "I said Bear is coming now!!!!\nAll of these timestamps are after the end of the cue, so get ignored." } ];
+ assert_cue_fragment_as_textcontent(track.cues[2], children);
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-hour.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-hour.html
new file mode 100644
index 00000000000..c03e182c79e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-hour.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<title>Cue timings and various syntax errors in timings, with hours</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/timings-hour.vtt">
+ <track src="resources/timings-hour-error.vtt">
+</video>
+<script>
+async_test(function(t) {
+ var video = document.querySelector("video");
+
+ var trackElements = document.querySelectorAll("track");
+ for (var i = 0; i < video.textTracks.length; i++)
+ trackElements[i].onload = t.step_func(trackLoaded);
+
+ enableAllTextTracks(video.textTracks);
+
+ var numberOfTracksLoaded = 0;
+ function trackLoaded() {
+ numberOfTracksLoaded++;
+ if (numberOfTracksLoaded != 2)
+ return;
+
+ testTrack0();
+ testTrack1();
+ t.done();
+ }
+
+ function testTrack0() {
+ var expected = [
+ {
+ id : "1",
+ startTime : 0,
+ endTime : 30.5,
+ text : "Bear is Coming!!!!!"
+ },
+ {
+ id : "2",
+ startTime : 31,
+ endTime : 60.5,
+ text : "I said Bear is coming!!!!"
+ },
+ {
+ id : "3",
+ startTime : 61,
+ endTime : 361200.5,
+ text : "I said Bear is coming now!!!!"
+ }
+ ];
+
+ assert_cues_equal(video.textTracks[0].cues, expected);
+ }
+
+ function testTrack1() {
+ // Test that all the cues are ignored.
+ assert_cues_equal(video.textTracks[1].cues, []);
+ }
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-no-hours.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-no-hours.html
new file mode 100644
index 00000000000..e81ae03cc24
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-no-hours.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<title>Cue timings and various syntax errors in timings, without hours</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/timings-no-hour.vtt">
+ <track src="resources/timings-no-hour-errors.vtt">
+</video>
+<script>
+async_test(function(t) {
+ var video = document.querySelector("video");
+
+ var trackElements = document.querySelectorAll("track");
+ for (var i = 0; i < video.textTracks.length; i++)
+ trackElements[i].onload = t.step_func(trackLoaded);
+
+ enableAllTextTracks(video.textTracks);
+
+ var numberOfTracksLoaded = 0;
+ function trackLoaded() {
+ numberOfTracksLoaded++;
+ if (numberOfTracksLoaded != 2)
+ return;
+
+ testTrack0();
+ testTrack1();
+ t.done();
+ }
+
+ function testTrack0() {
+ var expected = [
+ {
+ id : "1",
+ startTime : 0,
+ endTime : 30.5,
+ text : "Bear is Coming!!!!!"
+ },
+ {
+ id : "2",
+ startTime : 31,
+ endTime : 60.5,
+ text : "I said Bear is coming!!!!"
+ },
+ {
+ id : "3",
+ startTime : 61,
+ endTime : 120.5,
+ text : "I said Bear is coming now!!!!"
+ },
+ {
+ id : "4",
+ startTime : 121,
+ endTime : 180.5,
+ text : "tab separators"
+ }
+ ];
+
+ assert_cues_equal(video.textTracks[0].cues, expected);
+ }
+
+ function testTrack1() {
+ // Test that all the cues are ignored.
+ assert_cues_equal(video.textTracks[1].cues, []);
+ }
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-whitespace.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-whitespace.html
new file mode 100644
index 00000000000..db1346d23ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-whitespace.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>"Skip whitespace" step around cue-timings separator</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/timings-whitespace.vtt", function(track) {
+ var expected = [
+ { id: "1", startTime: 0.1, endTime: 1.5, text: "Single U+0020 SPACE left of cue-timings separator" },
+ { id: "2", startTime: 0.1, endTime: 1.5, text: "Single U+0020 SPACE right of cue-timings separator" },
+ { id: "3", startTime: 0.1, endTime: 1.5, text: "Single U+0009 TAB left of cue-timings separator" },
+ { id: "4", startTime: 0.1, endTime: 1.5, text: "Single U+0009 TAB right of cue-timings separator" },
+ { id: "5", startTime: 0.1, endTime: 1.5, text: "Single U+000C FORM FEED left of cue-timings separator" },
+ { id: "6", startTime: 0.1, endTime: 1.5, text: "Single U+000C FORM FEED right of cue-timings separator" },
+ { id: "7", startTime: 0.1, endTime: 1.5, text: "Several U+0020 SPACE left of cue-timings separator" },
+ { id: "8", startTime: 0.1, endTime: 1.5, text: "Several U+0020 SPACE right of cue-timings separator" },
+ { id: "9", startTime: 0.1, endTime: 1.5, text: "Several U+0009 TAB left of cue-timings separator" },
+ { id: "10", startTime: 0.1, endTime: 1.5, text: "Several U+0009 TAB right of cue-timings separator" },
+ { id: "11", startTime: 0.1, endTime: 1.5, text: "Several U+000C FORM FEED left of cue-timings separator" },
+ { id: "12", startTime: 0.1, endTime: 1.5, text: "Several U+000C FORM FEED right of cue-timings separator" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-unsupported-markup.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-unsupported-markup.html
new file mode 100644
index 00000000000..ed3107f89b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-unsupported-markup.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<title>Unsupported markup is properly ignored</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+var getCueAsHTMLContent = function(cue) {
+ return cue.getCueAsHTML().textContent;
+};
+
+check_cues_from_track("resources/unsupported-markup.vtt", function(track) {
+ var expected = [
+ {
+ innerHTML: getCueAsHTMLContent,
+ expected: "Bear is Coming!!!!!\nAnd what kind of a bear it is - just have look."
+ },
+ {
+ innerHTML: getCueAsHTMLContent,
+ expected: "\n I said Bear is coming!!!!\n I said Bear is still coming!!!!\n",
+ },
+ {
+ innerHTML: getCueAsHTMLContent,
+ expected: "\n I said Bear is coming now!!!!\n \n \n",
+ }
+ ];
+
+ assert_cues_html_content(track.cues, expected);
+
+ var expected_text = [
+ { text: "<h1>Bear is Coming!!!!!</h1>\n<p>And what kind of a bear it is - just have <a href=\"webpage.html\">look</a>.</p>" },
+ { text: "<ul>\n <li>I said Bear is coming!!!!</li>\n <li>I said Bear is still coming!!!!</li>\n</ul>" },
+ { text: "<ol>\n <li>I said Bear is coming now!!!!</li>\n <li><img src=\"bear.png\" alt=\"mighty bear\"></li>\n <li><video src=\"bear_ad.webm\" controls></video></li>\n</ol>" }
+ ];
+
+ assert_cues_match(track.cues, expected_text);
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-utf8.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-utf8.html
new file mode 100644
index 00000000000..eb44c85ba83
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-utf8.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title>UTF-8 encoded characters are recognized properly and different encodings (iconv) are not recognized as a WebVTT file</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<video>
+ <track src="resources/utf8.vtt">
+ <track src="resources/iso2022jp3.vtt">
+</video>
+<script>
+async_test(function(t) {
+ var video = document.querySelector("video");
+
+ var trackElements = document.querySelectorAll("track");
+ for (var i = 0; i < video.textTracks.length; i++)
+ trackElements[i].onload = t.step_func(trackLoaded);
+
+ enableAllTextTracks(video.textTracks);
+
+ var numberOfTracksLoaded = 0;
+ function trackLoaded() {
+ numberOfTracksLoaded++;
+ if (numberOfTracksLoaded != 2)
+ return;
+
+ testTrack0();
+ testTrack1();
+ t.done();
+ }
+
+ function testTrack0() {
+ var expected = [
+ {
+ id : "1",
+ startTime : 0,
+ endTime : 30.5,
+ text : "景気判断"
+ },
+ {
+ id : "2",
+ startTime : 31,
+ endTime : 1200.5,
+ text : "電力不足"
+ }
+ ];
+
+ var cues = video.textTracks[0].cues;
+ assert_equals(cues.length, 2);
+ assert_cues_equal(cues, expected);
+ }
+
+ function testTrack1() {
+ assert_equals(video.textTracks[1].cues.length, 2);
+ }
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-valign.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-valign.html
new file mode 100644
index 00000000000..ace07607400
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-valign.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Cue vertical alignment (direction) from settings</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/valign.vtt", testTrack);
+check_cues_from_track("resources/valign-ltr.vtt", testTrack);
+check_cues_from_track("resources/valign-bad.vtt", function(track) {
+ var expected = [
+ { vertical: "" },
+ { vertical: "" },
+ { vertical: "" }
+ ];
+
+ assert_cues_match(track.cues, expected);
+});
+
+function testTrack(track) {
+ var expected = [
+ { vertical: "rl", align: "center", position: "auto" },
+ { vertical: "lr", align: "center", position: "auto" },
+ { vertical: "rl", align: "start", position: 0 }
+ ];
+
+ assert_cues_match(track.cues, expected);
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-voice.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-voice.html
new file mode 100644
index 00000000000..5df8b4057ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-voice.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<title>Cues with voice markup &lt;v&gt;</title>
+<script src="track-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+check_cues_from_track("resources/voice.vtt", function(track) {
+ assert_equals(track.cues.length, 3);
+
+ var children = [
+ { type: "span", style: { className: "blue", title: "Speaker" },
+ value: [ { type: "text", value: "Bear is Coming!!!!!" } ] },
+ { type: "text", value: "\nText span with a class and an annotation." }
+ ];
+ assert_cue_fragment(track.cues[0], children);
+
+ children = [
+ { type: "span", style: { title: "Doe Hunter" },
+ value: [ { type: "text", value: "I said Bear is coming!!!!" } ] }
+ ];
+ assert_cue_fragment(track.cues[1], children);
+
+ children = [
+ { type: "text", value: "I said " },
+ { type: "span", style: { className: "blue", title: "Speaker" },
+ value: [ { type: "text", value: "Bear is coming now" } ] },
+ { type: "text", value: "!!!!" }
+ ];
+ assert_cue_fragment(track.cues[2], children);
+});
+
+check_cues_from_track("resources/voice-bad.vtt", function(track) {
+ assert_equals(track.cues.length, 3);
+
+ var children = [
+ { type: "text", value: "Bear is Coming!!!!!" },
+ { type: "text", value: "\nThis is two annotations for an empty tag." }
+ ];
+ assert_cue_fragment(track.cues[0], children);
+
+ children = [
+ { type: "text", value: "I said Bear is coming!!!!" },
+ { type: "text", value: "\nThis does not parse as a voice tag." }
+ ];
+ assert_cue_fragment(track.cues[1], children);
+
+ children = [
+ { type: "text", value: "I said " },
+ { type: "text", value: "Bear is coming now" },
+ { type: "text", value: "!!!!\nThis does not parse as a voice tag." }
+ ];
+ assert_cue_fragment(track.cues[2], children);
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-area-element/area-download-click.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-area-element/area-download-click.html
index 7554c9b03bc..8100ada9d5f 100644
--- a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-area-element/area-download-click.html
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-area-element/area-download-click.html
@@ -6,22 +6,27 @@
<link rel="help" href="https://github.com/whatwg/html/issues/2116">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-
-<img src="/images/threecolors.png" usemap="#x" id="img" width="300" height="300">
-<map name="x">
- <area id="blob-url" download="foo.html" coords="0,0,300,300">
-</map>
-
+<body>
<script>
"use strict";
+async_test(t => {
+ const frame = document.createElement("iframe");
-const string = "test";
-const blob = new Blob([string], { type: "text/html" });
+ frame.addEventListener("load", t.step_func(function () {
+ frame.contentWindow.addEventListener(
+ "beforeunload", t.unreached_func("Navigated instead of downloading"));
+ const string = "test";
+ const blob = new Blob([string], { type: "text/html" });
-const link = document.querySelector("#blob-url");
-link.href = URL.createObjectURL(blob);
+ const link = frame.contentDocument.querySelector("#blob-url");
+ link.href = URL.createObjectURL(blob);
-link.click();
+ link.click();
-done();
+ t.step_timeout(() => t.done(), 1000);
+ }));
+ frame.src = "resources/area-download-click.html";
+ document.body.appendChild(frame);
+}, "Clicking on an <area> element with a download attribute must not throw an exception");
</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-area-element/resources/area-download-click.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-area-element/resources/area-download-click.html
new file mode 100644
index 00000000000..c0679f8233d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-area-element/resources/area-download-click.html
@@ -0,0 +1,5 @@
+<!doctype html>
+<img src="/images/threecolors.png" usemap="#x" id="img" width="300" height="300">
+<map name="x">
+ <area id="blob-url" download="foo.html" coords="0,0,300,300">
+</map>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html
index 8650876207c..3aba6b7adb3 100644
--- a/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html
@@ -10,6 +10,17 @@
<textarea id="b">abcde</textarea>
</div>
<script>
+var expected_direction_none;
+setup(function() {
+ var input = document.createElement("input");
+ input.setSelectionRange(0, 1, "none");
+ var direction = input.selectionDirection;
+ if (direction !== "none" && direction !== "forward") {
+ throw new Error("Unexpected direction");
+ }
+ expected_direction_none = direction;
+});
+
test(function() {
var input = document.getElementById("a");
test(function() {
@@ -67,22 +78,22 @@ test(function() {
test(function() {
input.setSelectionRange(0,1,"none")
- assert_equals(input.selectionDirection, "none", 'The direction of the selection must be set to forward if direction is a case-sensitive match for the string "none"');
+ assert_equals(input.selectionDirection, expected_direction_none);
},'input direction of setSelectionRange(0,1,"none")');
test(function() {
input.setSelectionRange(0,1,"hoge")
- assert_equals(input.selectionDirection, "none", "otherwise");
+ assert_equals(input.selectionDirection, expected_direction_none);
},'input direction of setSelectionRange(0,1,"hoge")');
test(function() {
input.setSelectionRange(0,1,"BACKWARD")
- assert_equals(input.selectionDirection, "none", "selectionDirection should be 'none'");
+ assert_equals(input.selectionDirection, expected_direction_none);
},'input direction of setSelectionRange(0,1,"BACKWARD")');
test(function() {
input.setSelectionRange(0,1)
- assert_equals(input.selectionDirection, "none", "if the argument is omitted");
+ assert_equals(input.selectionDirection, expected_direction_none);
},'input direction of setSelectionRange(0,1)');
test(function() {
@@ -214,22 +225,22 @@ test(function() {
test(function() {
textarea.setSelectionRange(0,1,"none")
- assert_equals(textarea.selectionDirection, "none", 'The direction of the selection must be set to forward if direction is a case-sensitive match for the string "none"');
+ assert_equals(textarea.selectionDirection, expected_direction_none);
},'textarea direction of setSelectionRange(0,1,"none")');
test(function() {
textarea.setSelectionRange(0,1,"hoge")
- assert_equals(textarea.selectionDirection, "none", "otherwise");
+ assert_equals(textarea.selectionDirection, expected_direction_none);
},'textarea direction of setSelectionRange(0,1,"hoge")');
test(function() {
textarea.setSelectionRange(0,1,"BACKWARD")
- assert_equals(textarea.selectionDirection, "none", "selectionDirection should be 'none'");
+ assert_equals(textarea.selectionDirection, expected_direction_none);
},'textarea direction of setSelectionRange(0,1,"BACKWARD")');
test(function() {
textarea.setSelectionRange(0,1)
- assert_equals(textarea.selectionDirection, "none", "if the argument is omitted");
+ assert_equals(textarea.selectionDirection, expected_direction_none);
},'textarea direction of setSelectionRange(0,1)');
test(function() {
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-progress-element/progress.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-progress-element/progress.html
index 0c176d8ea6e..00d63c372f7 100644
--- a/tests/wpt/web-platform-tests/html/semantics/forms/the-progress-element/progress.html
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-progress-element/progress.html
@@ -42,7 +42,7 @@
}, "Indeterminate progress bar should have value 0");
test(function() {
- assert_array_equals(largerthanmax.value, 1);
+ assert_equals(largerthanmax.value, 1);
}, "Value must equal max if the parsed value is larger than max");
test(function() {
@@ -50,7 +50,7 @@
}, "Max must be 1 by default");
test(function() {
- assert_array_equals(largerthanmax.max, 1);
+ assert_equals(largerthanmax.max, 1);
}, "Max must be 1 by default, even if value is specified");
test(function() {
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/select-add.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/select-add.html
new file mode 100644
index 00000000000..84a5442e424
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/select-add.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTMLSelectElement Test: add()</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/form-elements.html#dom-select-add-dev">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<form style="display:none">
+ <option id="testoption">
+ <select id="testselect1">
+ </select>
+ <select id="testselect2">
+ <option>TEST</option>
+ </select>
+ </option>
+</form>
+
+<script>
+
+test(() => {
+ let testselect1 = document.getElementById("testselect1");
+ let opt1 = new Option("Marry","1");
+ testselect1.add(opt1);
+ assert_equals(testselect1.options[0].value, "1");
+}, "test that HTMLSelectElement.add method can add option element");
+
+test(() => {
+ let testselect2 = document.getElementById("testselect2");
+ let opt2 = document.getElementById("testoption");
+ assert_throws("HierarchyRequestError", () => {
+ testselect2.add(opt2);
+ });
+}, "test that HierarchyRequestError exception must be thrown when element is an ancestor of the element into which it is to be inserted");
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/selected-index.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/selected-index.html
index 6c30698a8ae..46f19da7da2 100644
--- a/tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/selected-index.html
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/selected-index.html
@@ -70,7 +70,7 @@ test(function () {
assertSelectedIndex(select, 0);
select.selectedIndex = 2;
assertSelectedIndex(select, 2);
- this.add_cleanup(() => select.selectedIndex = 0);
+ this.add_cleanup(() => { select.selectedIndex = 0; });
}, "set (HTMLSelectElement)");
test(function () {
@@ -78,7 +78,7 @@ test(function () {
assertSelectedIndex(select, 0);
select.options.selectedIndex = 2;
assertSelectedIndex(select, 2);
- this.add_cleanup(() => select.selectedIndex = 0);
+ this.add_cleanup(() => { select.selectedIndex = 0; });
}, "set (HTMLOptionsCollection)");
test(function () {
diff --git a/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/abspos-dialog-layout.html b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/abspos-dialog-layout.html
new file mode 100644
index 00000000000..e97ebee59f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/abspos-dialog-layout.html
@@ -0,0 +1,223 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Tests layout of absolutely positioned modal dialogs.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+/* Remove body margin and dialog styles for easier positioning expected values */
+body {
+ height: 10000px;
+ margin: 0;
+}
+
+dialog {
+ border: 0;
+ padding: 0;
+ height: auto;
+ width: auto;
+}
+
+#absolute-div {
+ position: absolute;
+ top: 800px;
+ height: 50px;
+ width: 90%;
+}
+
+#relative-div {
+ position: relative;
+ top: 20px;
+ height: 30px;
+}
+</style>
+</head>
+<dialog >It is my dialog.</dialog>
+<div id="absolute-div">
+ <div id="relative-div"></div>
+</div>
+<script>
+"use strict";
+
+function checkNotVerticallyCentered(dialog) {
+ var centeredTop = (window.innerHeight - dialog.offsetHeight) / 2;
+ assert_not_equals(dialog.getBoundingClientRect().top, centeredTop);
+}
+
+function checkVerticallyCentered(dialog) {
+ var centeredTop = (window.innerHeight - dialog.offsetHeight) / 2;
+ assert_equals(dialog.getBoundingClientRect().top, centeredTop);
+}
+
+function reset() {
+ if (dialog.open)
+ dialog.close();
+ dialog.remove();
+ document.body.appendChild(dialog);
+ window.scroll(0, 500);
+}
+
+var dialog = document.querySelector('dialog');
+var absoluteContainer = document.querySelector('#absolute-div');
+var relativeContainer = document.querySelector('#relative-div');
+reset();
+
+test(function() {
+ dialog.showModal();
+ checkVerticallyCentered(dialog);
+ reset();
+}, "showModal() should center in the viewport");
+
+test(function() {
+ assert_equals(window.getComputedStyle(dialog).top, 'auto');
+ assert_equals(window.getComputedStyle(dialog).bottom, 'auto');
+
+ dialog.style.height = '20px';
+ dialog.showModal();
+
+ assert_not_equals(window.getComputedStyle(dialog).top, 'auto');
+ assert_not_equals(window.getComputedStyle(dialog).bottom, 'auto');
+
+ // Set back original value to 'height'.
+ dialog.style.height = 'auto';
+ reset();
+}, "The dialog is a positioned element, so the top and bottom should not have style auto.");
+
+test(function() {
+ dialog.showModal();
+ dialog.close();
+ window.scroll(0, 2 * window.scrollY);
+ dialog.showModal();
+ checkVerticallyCentered(dialog);
+ reset();
+}, "Dialog should be recentered if showModal() is called after close()");
+
+test(function() {
+ dialog.showModal();
+ var expectedTop = dialog.getBoundingClientRect().top;
+ window.scroll(0, window.scrollY * 2);
+
+ // Trigger relayout
+ document.body.offsetHeight;
+
+ window.scroll(0, window.scrollY / 2);
+ assert_equals(dialog.getBoundingClientRect().top, expectedTop);
+ reset();
+}, "Dialog should not recenter on relayout.");
+
+test(function() {
+ dialog.style.height = '20000px';
+ dialog.showModal();
+ assert_equals(dialog.getBoundingClientRect().top, 0);
+
+ // Set back original value to 'height'.
+ dialog.style.height = 'auto';
+ reset();
+}, "A tall dialog should be positioned at the top of the viewport.");
+
+test(function() {
+ document.body.style.width = '4000px';
+ dialog.showModal();
+ checkVerticallyCentered(dialog);
+
+ // Set back original value to 'width'.
+ document.body.style.width = 'auto';
+ reset();
+}, "The dialog should be centered regardless of the presence of a horizontal scrollbar.");
+
+test(function() {
+ dialog.remove();
+ absoluteContainer.appendChild(dialog);
+ dialog.showModal();
+ checkVerticallyCentered(dialog);
+ dialog.close();
+
+ dialog.remove();
+ relativeContainer.appendChild(dialog);
+ dialog.showModal();
+ checkVerticallyCentered(dialog);
+
+ reset();
+}, "Centering should work when dialog is inside positioned containers.");
+
+test(function() {
+ dialog.showModal();
+ var expectedTop = dialog.getBoundingClientRect().top;
+ relativeContainer.style.display = 'none';
+ relativeContainer.style.display = 'block';
+ assert_equals(dialog.getBoundingClientRect().top, expectedTop);
+
+ reset();
+}, "A centered dialog's position should survive becoming display:none temporarily.");
+
+test(function() {
+ // Remove and reinsert so that the document position isn't changed by the second remove and reinsert
+ dialog.remove();
+ relativeContainer.appendChild(dialog);
+
+ dialog.showModal();
+ assert_not_equals(dialog.getBoundingClientRect().top, relativeContainer.getBoundingClientRect().top);
+ dialog.remove();
+
+ relativeContainer.appendChild(dialog);
+ assert_equals(dialog.parentNode, relativeContainer);
+ assert_equals(dialog.getBoundingClientRect().top, relativeContainer.getBoundingClientRect().top);
+
+ reset();
+}, "Dialog should lose centering when removed from the document.");
+
+test(function() {
+ dialog.showModal();
+ dialog.style.top = '0px';
+ var expectedTop = dialog.getBoundingClientRect().top;
+ dialog.close();
+ dialog.showModal();
+ assert_equals(dialog.getBoundingClientRect().top, expectedTop);
+
+ // Set back original value to 'top'.
+ dialog.style.top = 'auto';
+ reset();
+}, "Dialog's specified position should survive after close() and showModal().");
+
+test(function() {
+ dialog.showModal();
+ dialog.removeAttribute('open');
+ window.scroll(0, window.scrollY * 2);
+ checkNotVerticallyCentered(dialog);
+ dialog.showModal();
+ checkVerticallyCentered(dialog);
+
+ reset();
+}, "Dialog should be recentered if showModal() is called after removing 'open'.");
+
+test(function() {
+ dialog.remove();
+ absoluteContainer.appendChild(dialog);
+ absoluteContainer.style.display = 'none';
+ dialog.showModal();
+ absoluteContainer.style.display = 'block';
+ // Since dialog's containing block is the ICB, it's statically positioned after <body>.
+ assert_equals(dialog.getBoundingClientRect().top, document.body.getBoundingClientRect().bottom);
+ reset();
+}, "Dialog should not be centered if showModal() was called when an ancestor had display 'none'.");
+
+test(function() {
+ var offset = 50;
+ dialog.style.top = offset + 'px';
+ dialog.showModal();
+ assert_equals(dialog.getBoundingClientRect().top + window.scrollY, offset);
+ // Set back original value to 'top'.
+ dialog.style.top = 'auto';
+ reset();
+}, "A dialog with specified 'top' should be positioned as usual");
+
+test(function() {
+ var offset = 50;
+ dialog.style.bottom = offset + 'px';
+ dialog.showModal();
+ assert_equals(dialog.getBoundingClientRect().bottom + window.scrollY, window.innerHeight - offset);
+ // Set back original value to 'bottom'.
+ dialog.style.bottom = 'auto';
+ reset();
+}, "A dialog with specified 'bottom' should be positioned as usual");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/dialog-scrolled-viewport.html b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/dialog-scrolled-viewport.html
new file mode 100644
index 00000000000..8a59ba23e43
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/dialog-scrolled-viewport.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+body {
+ margin: 0;
+}
+
+dialog {
+ padding : 0;
+}
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body style="height: 10000px; width: 10000px">
+<div style="position: absolute; top: 5000px; left: 5000px; width: 20px;">
+ <dialog style="top: 1200px; left: 1200px; right: auto; height: 100px; width: 50%;">
+ </dialog>
+</div>
+<script>
+"use strict";
+function checkPosition(dialog) {
+ assert_equals(dialog.offsetParent, null);
+ assert_equals(dialog.offsetTop, 1200);
+ assert_equals(dialog.offsetLeft, 1200);
+ // Since dialog's 'width' is '50%', the expected width is half of the
+ // viewport width, but viewport width may be odd.
+ var expectedWidth = document.documentElement.clientWidth / 2;
+ assert_approx_equals(dialog.clientWidth, expectedWidth, 0.5);
+}
+
+test(function() {
+ // The dialog should be onscreen with a width of 50% of the viewport. It is the child of a
+ // narrow element positioned off screen, but its containing block is the initial containing
+ // block, so its position and percent lengths are relative to that.
+ window.scroll(1000, 1000);
+ var dialog = document.querySelector('dialog');
+ dialog.showModal();
+ checkPosition(dialog);
+ dialog.close();
+}, "Tests modal dialog's containing block is the initial containing block");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/inert-does-not-match-disabled-selector.html b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/inert-does-not-match-disabled-selector.html
new file mode 100644
index 00000000000..b3b0c0a9297
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/inert-does-not-match-disabled-selector.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+button {
+ color: green;
+}
+
+button:disabled {
+ color: red;
+}
+
+.trigger-style-recalc {
+ /* No change, we just need a new style recalculation. */
+ font-weight:bold;
+}
+</style>
+</head>
+<body style="color: green">
+<button>The test passes if this is in green.</button>
+<dialog></dialog>
+<script>
+"use strict";
+test(function() {
+ document.querySelector('dialog').showModal();
+ var button = document.querySelector('button');
+ button.classList.add('trigger-style-recalc');
+ var color = document.defaultView.getComputedStyle(button).getPropertyValue('color');
+ assert_equals(color, 'rgb(0, 128, 0)');
+}, "Tests inert elements do not match the :disabled selector.");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/inert-node-is-unfocusable.html b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/inert-node-is-unfocusable.html
new file mode 100644
index 00000000000..49d6690d673
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/inert-node-is-unfocusable.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body id="body" tabindex="1">
+<dialog id="top-dialog" tabindex="1" style="width: 100px; top: 30px"><button id="top-dialog-button">I get focus</button></dialog>
+<dialog id="bottom-dialog" tabindex="-1" style="width: 100px; bottom: 30px"><button id="bottom-dialog-button">I don't get focus.</button></dialog>
+<div id="container">
+ <input id="text" type="text">
+ <input id="datetime" type="datetime">
+ <input id="color" type="color">
+ <select id="select">
+ <optgroup id="optgroup">
+ <option id="option">Option</option>
+ </optgroup>
+ </select>
+ <div id="contenteditable-div" contenteditable>I'm editable</div>
+ <span id="tabindex-span" tabindex="0">I'm tabindexed.</div>
+ <embed id="embed" type="application/x-blink-test-plugin" width=100 height=100></embed>
+ <a id="anchor" href="">Link</a>
+</div>
+<script>
+"use strict";
+// The test passses if only the topmost dialog and its button are focusable.
+
+function testFocus(element, expectFocus) {
+ var focusedElement = null;
+ element.addEventListener('focus', function() { focusedElement = element; }, false);
+ element.focus();
+ var theElement = element;
+ assert_equals(focusedElement === theElement, expectFocus, element.id);
+}
+
+function testTree(element, expectFocus) {
+ if (element.nodeType == Node.ELEMENT_NODE)
+ testFocus(element, expectFocus);
+ var childNodes = element.childNodes;
+ for (var i = 0; i < childNodes.length; i++)
+ testTree(childNodes[i], expectFocus);
+}
+
+test(function() {
+ var bottomDialog = document.getElementById('bottom-dialog');
+ bottomDialog.showModal();
+
+ var topDialog = document.getElementById('top-dialog');
+ topDialog.showModal();
+
+ testFocus(document.body, false);
+ testTree(topDialog, true);
+ testTree(bottomDialog, false);
+ testTree(document.getElementById('container'), false);
+}, "Test that inert nodes are not focusable.");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/defer.js b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/defer.js
new file mode 100644
index 00000000000..c4449ca7c8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/defer.js
@@ -0,0 +1,4 @@
+t.step(() => {
+ assert_equals(script_run_status, "deferred", "the script run status");
+});
+t.done();
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1.html
new file mode 100644
index 00000000000..73a6ce3db00
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<title>Choice of parse errors</title>
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+ setup({allow_uncaught_exception: true});
+
+ window.log = [];
+
+ window.addEventListener("error", ev => log.push(ev.error));
+
+ const test_load = async_test(
+ "Parse errors in different files should be reported " +
+ "depending on different roots");
+ window.addEventListener("load", test_load.step_func_done(ev => {
+ assert_equals(log.length, 4);
+
+ // Two different parse errors from different module scripts
+ // should be reported for each <script> element.
+ assert_equals(log[0].constructor, SyntaxError);
+ assert_equals(log[1], 1);
+
+ assert_equals(log[2].constructor, SyntaxError);
+ assert_equals(log[3], 2);
+
+ assert_not_equals(log[0], log[2],
+ 'two different parse errors should be reported');
+ }));
+
+ function unreachable() { log.push("unexpected"); }
+</script>
+<script type="module" src="./choice-of-error-1a.js"
+ onerror="unreachable()" onload="log.push(1)"></script>
+<script type="module" src="./choice-of-error-1b.js"
+ onerror="unreachable()" onload="log.push(2)"></script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1a.js b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1a.js
new file mode 100644
index 00000000000..f479e5e1fac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1a.js
@@ -0,0 +1,2 @@
+import './choice-of-error-1b.js';
+import './syntaxerror.js?1c';
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1b.js b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1b.js
new file mode 100644
index 00000000000..257f4a46784
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1b.js
@@ -0,0 +1,2 @@
+import './choice-of-error-1a.js';
+import './syntaxerror.js?1d';
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2.html
new file mode 100644
index 00000000000..0d67cb819a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<title>Choice of instantiation errors</title>
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+ setup({allow_uncaught_exception: true});
+
+ window.log = [];
+
+ window.addEventListener("error", ev => log.push(ev.error));
+
+ const test_load = async_test(
+ "Instantiation errors in different files should be reported " +
+ "depending on different roots");
+ window.addEventListener("load", test_load.step_func_done(ev => {
+ assert_equals(log.length, 4);
+
+ // Two different instantiation errors from different module scripts
+ // should be reported for each <script> element.
+ assert_equals(log[0].constructor, SyntaxError);
+ assert_equals(log[1], 1);
+
+ assert_equals(log[2].constructor, SyntaxError);
+ assert_equals(log[3], 2);
+
+ assert_not_equals(log[0], log[2],
+ 'two different instantiation errors should be reported');
+ }));
+
+ function unreachable() { log.push("unexpected"); }
+</script>
+<script type="module" src="./choice-of-error-2a.js"
+ onerror="unreachable()" onload="log.push(1)"></script>
+<script type="module" src="./choice-of-error-2b.js"
+ onerror="unreachable()" onload="log.push(2)"></script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2a.js b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2a.js
new file mode 100644
index 00000000000..2dc7aac11a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2a.js
@@ -0,0 +1,2 @@
+import './choice-of-error-2b.js';
+import './instantiation-error-1.js?2c';
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2b.js b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2b.js
new file mode 100644
index 00000000000..2adb9eea597
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2b.js
@@ -0,0 +1,2 @@
+import './choice-of-error-2a.js';
+import './instantiation-error-1.js?2d';
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3.html
new file mode 100644
index 00000000000..5c0adff6ea8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<title>Choice of evaluation errors</title>
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+ setup({allow_uncaught_exception: true});
+
+ window.log = [];
+
+ window.addEventListener("error", ev => log.push(ev.error));
+
+ const test_load = async_test(
+ "Evaluation errors are cached in intermediate module scripts");
+ window.addEventListener("load", test_load.step_func_done(ev => {
+ assert_equals(log.length, 5);
+
+ // Evaluation errors, unlike parse/instantiation errors, are remembered
+ // and cached in module scripts between the root and the script that
+ // caused an evaluation error, and thus the same evaluation error
+ // is reported for both <script> elements.
+ assert_equals(log[0], "throw2");
+ assert_true(log[1].bar);
+ assert_equals(log[2], 1);
+
+ assert_true(log[3].bar);
+ assert_equals(log[4], 2);
+
+ assert_equals(log[1], log[3], 'evaluation errors must be the same');
+ }));
+
+ function unreachable() { log.push("unexpected"); }
+</script>
+<script type="module" src="./choice-of-error-3a.js"
+ onerror="unreachable()" onload="log.push(1)"></script>
+<script type="module" src="./choice-of-error-3b.js"
+ onerror="unreachable()" onload="log.push(2)"></script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3a.js b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3a.js
new file mode 100644
index 00000000000..71154674a34
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3a.js
@@ -0,0 +1,2 @@
+import './choice-of-error-3b.js';
+import './throw.js?3c';
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3b.js b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3b.js
new file mode 100644
index 00000000000..2131a35eff1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3b.js
@@ -0,0 +1,2 @@
+import './choice-of-error-3a.js';
+import './throw2.js?3d';
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-script-error.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-script-error.html
index 9390ce0a7a8..1578f8570e4 100644
--- a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-script-error.html
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-script-error.html
@@ -9,7 +9,7 @@ const cases = [
["parse error", "../syntaxerror.js", new SyntaxError],
["bad module specifier", "does-not-start-with-dot.js", new TypeError, { differentErrorObjects: true }],
["bad module specifier in a dependency", "../bad-module-specifier.js", new TypeError],
- ["instantiation error", "../instantiation-error-1.js", new SyntaxError],
+ ["instantiation error", "../instantiation-error-1.js", new SyntaxError, { differentErrorObjects: true }],
["evaluation error", "../throw-error.js", new Error]
];
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/Function.js b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/Function.js
new file mode 100644
index 00000000000..bc88bf7bd63
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/Function.js
@@ -0,0 +1 @@
+Function(`import('../../imports-a.js?label=' + window.label).then(window.continueTest, window.errorTest)`)();
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/eval.js b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/eval.js
new file mode 100644
index 00000000000..a8bcffe9f81
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/eval.js
@@ -0,0 +1 @@
+eval(`import('../../imports-a.js?label=' + window.label).then(window.continueTest, window.errorTest)`);
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/inline-event-handlers-UA-code.js b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/inline-event-handlers-UA-code.js
new file mode 100644
index 00000000000..c0bd8655873
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/inline-event-handlers-UA-code.js
@@ -0,0 +1,2 @@
+window.dummyDiv.setAttribute("onclick", `import('../../imports-a.js?label=' + window.label).then(window.continueTest, window.errorTest)`);
+window.dummyDiv.click(); // different from **on**click()
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/reflected-inline-event-handlers.js b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/reflected-inline-event-handlers.js
new file mode 100644
index 00000000000..f19ec2b03f9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/reflected-inline-event-handlers.js
@@ -0,0 +1,2 @@
+window.dummyDiv.setAttribute("onclick", `import('../../imports-a.js?label=' + window.label).then(window.continueTest, window.errorTest)`);
+window.dummyDiv.onclick();
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/setTimeout.js b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/setTimeout.js
new file mode 100644
index 00000000000..c6f2dda55aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/setTimeout.js
@@ -0,0 +1 @@
+setTimeout(`import('../../imports-a.js?label=' + window.label).then(window.continueTest, window.errorTest)`, 0);
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-classic.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-classic.html
deleted file mode 100644
index 062bb620b9e..00000000000
--- a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-classic.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>import() inside compiled strings uses the document base URL inside a classic script</title>
-<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
-
-<base href="..">
-
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-
-<div id="dummy"></div>
-
-<script>
-function createTestPromise() {
- return new Promise((resolve, reject) => {
- window.continueTest = resolve;
- window.errorTest = reject;
- });
-}
-
-const dummyDiv = document.querySelector("#dummy");
-
-const evaluators = {
- eval,
- setTimeout,
- "the Function constructor"(x) {
- Function(x)();
- },
- "reflected inline event handlers"(x) {
- dummyDiv.setAttribute("onclick", x);
- dummyDiv.onclick();
- },
- "inline event handlers triggered via UA code"(x) {
- dummyDiv.setAttribute("onclick", x);
- dummyDiv.click(); // different from .**on**click()
- }
-};
-
-for (const [label, evaluator] of Object.entries(evaluators)) {
- promise_test(t => {
- t.add_cleanup(() => {
- dummyDiv.removeAttribute("onclick");
- delete window.evaluated_imports_a;
- });
-
- const promise = createTestPromise();
-
- evaluator(`import('./imports-a.js?label=${label}').then(window.continueTest, window.errorTest);`);
-
- return promise.then(module => {
- assert_true(window.evaluated_imports_a, "The module must have been evaluated");
- assert_equals(module.A.from, "imports-a.js", "The module namespace object must be correct");
- });
- }, label + " should successfully import");
-};
-</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-classic.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-classic.html
new file mode 100644
index 00000000000..7cf2dac0ac6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-classic.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>import() inside compiled strings uses the script base URL inside a classic script that is loaded from a file</title>
+<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<div id="dummy"></div>
+
+<script>
+function load(scriptSrc) {
+ const el = document.createElement("script");
+ el.src = scriptSrc;
+ document.body.appendChild(el);
+}
+
+function createTestPromise() {
+ return new Promise((resolve, reject) => {
+ window.dummyDiv.removeAttribute("onclick");
+ delete window.evaluated_imports_a;
+ delete window.label;
+
+ window.continueTest = resolve;
+ window.errorTest = reject;
+ });
+}
+
+window.dummyDiv = document.querySelector("#dummy");
+
+const evaluators = [
+ "setTimeout",
+ "eval",
+ "Function",
+ "reflected-inline-event-handlers",
+ "inline-event-handlers-UA-code"
+];
+
+for (const label of evaluators) {
+ promise_test(() => {
+ const promise = createTestPromise();
+
+ window.label = label;
+ load(`scripts/${label}.js`);
+
+ return promise.then(module => {
+ assert_true(window.evaluated_imports_a, "The module must have been evaluated");
+ assert_equals(module.A.from, "imports-a.js", "The module namespace object must be correct");
+ });
+ }, label + " should successfully import");
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-module.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-module.html
new file mode 100644
index 00000000000..73986c2c997
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-module.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>import() inside compiled strings uses the script base URL inside a module script that is loaded from a file</title>
+<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<div id="dummy"></div>
+
+<script type="module">
+function load(scriptSrc) {
+ const el = document.createElement("script");
+ el.type = "module";
+ el.src = scriptSrc;
+ document.body.appendChild(el);
+}
+
+function createTestPromise() {
+ return new Promise((resolve, reject) => {
+ window.dummyDiv.removeAttribute("onclick");
+ delete window.evaluated_imports_a;
+ delete window.label;
+
+ window.continueTest = resolve;
+ window.errorTest = reject;
+ });
+}
+
+window.dummyDiv = document.querySelector("#dummy");
+
+const evaluators = [
+ "setTimeout",
+ "eval",
+ "Function",
+ "reflected-inline-event-handlers",
+ "inline-event-handlers-UA-code"
+];
+
+for (const label of evaluators) {
+ promise_test(() => {
+ const promise = createTestPromise();
+
+ window.label = label;
+ load(`scripts/${label}.js`);
+
+ return promise.then(module => {
+ assert_true(window.evaluated_imports_a, "The module must have been evaluated");
+ assert_equals(module.A.from, "imports-a.js", "The module namespace object must be correct");
+ });
+ }, label + " should successfully import");
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-classic.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-classic.html
new file mode 100644
index 00000000000..1bd6d7dfd75
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-classic.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>import() inside compiled strings uses the script base URL (= document base URL) inside an inline classic script</title>
+<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
+
+<base href="..">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<div id="dummy"></div>
+
+<script>
+function createTestPromise() {
+ return new Promise((resolve, reject) => {
+ window.continueTest = resolve;
+ window.errorTest = reject;
+ });
+}
+
+const dummyDiv = document.querySelector("#dummy");
+
+const evaluators = {
+ setTimeout,
+ eval,
+ "the Function constructor"(x) {
+ Function(x)();
+ },
+ "reflected inline event handlers"(x) {
+ dummyDiv.setAttribute("onclick", x);
+ dummyDiv.onclick();
+ },
+ "inline event handlers triggered via UA code"(x) {
+ dummyDiv.setAttribute("onclick", x);
+ dummyDiv.click(); // different from .**on**click()
+ }
+};
+
+for (const [label, evaluator] of Object.entries(evaluators)) {
+ promise_test(t => {
+ t.add_cleanup(() => {
+ dummyDiv.removeAttribute("onclick");
+ delete window.evaluated_imports_a;
+ });
+
+ const promise = createTestPromise();
+
+ evaluator(`import('./imports-a.js?label=${label}').then(window.continueTest, window.errorTest);`);
+
+ return promise.then(module => {
+ assert_true(window.evaluated_imports_a, "The module must have been evaluated");
+ assert_equals(module.A.from, "imports-a.js", "The module namespace object must be correct");
+ });
+ }, label + " should successfully import");
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-module.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-module.html
new file mode 100644
index 00000000000..f5b85740f55
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-module.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>import() inside compiled strings uses the script base URL (= document base URL) inside an inline module script</title>
+<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
+
+<base href="..">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<div id="dummy"></div>
+
+<script type="module">
+function createTestPromise() {
+ return new Promise((resolve, reject) => {
+ window.continueTest = resolve;
+ window.errorTest = reject;
+ });
+}
+
+const dummyDiv = document.querySelector("#dummy");
+
+const evaluators = {
+ setTimeout,
+ eval,
+ "the Function constructor"(x) {
+ Function(x)();
+ },
+ "reflected inline event handlers"(x) {
+ dummyDiv.setAttribute("onclick", x);
+ dummyDiv.onclick();
+ },
+ "inline event handlers triggered via UA code"(x) {
+ dummyDiv.setAttribute("onclick", x);
+ dummyDiv.click(); // different from .**on**click()
+ }
+};
+
+for (const [label, evaluator] of Object.entries(evaluators)) {
+ promise_test(t => {
+ t.add_cleanup(() => {
+ dummyDiv.removeAttribute("onclick");
+ delete window.evaluated_imports_a;
+ });
+
+ const promise = createTestPromise();
+
+ evaluator(`import('./imports-a.js?label=${label}').then(window.continueTest, window.errorTest);`);
+
+ return promise.then(module => {
+ assert_true(window.evaluated_imports_a, "The module must have been evaluated");
+ assert_equals(module.A.from, "imports-a.js", "The module namespace object must be correct");
+ });
+ }, label + " should successfully import");
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-module.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-module.html
deleted file mode 100644
index de51c9a4cd6..00000000000
--- a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-module.html
+++ /dev/null
@@ -1,56 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>import() inside compiled strings uses the document base URL inside a module script</title>
-<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
-
-<base href="..">
-
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-
-<div id="dummy"></div>
-
-<script type="module">
-function createTestPromise() {
- return new Promise((resolve, reject) => {
- window.continueTest = resolve;
- window.errorTest = reject;
- });
-}
-
-const dummyDiv = document.querySelector("#dummy");
-
-const evaluators = {
- eval,
- setTimeout,
- "the Function constructor"(x) {
- Function(x)();
- },
- "reflected inline event handlers"(x) {
- dummyDiv.setAttribute("onclick", x);
- dummyDiv.onclick();
- },
- "inline event handlers triggered via UA code"(x) {
- dummyDiv.setAttribute("onclick", x);
- dummyDiv.click(); // different from .**on**click()
- }
-};
-
-for (const [label, evaluator] of Object.entries(evaluators)) {
- promise_test(t => {
- t.add_cleanup(() => {
- dummyDiv.removeAttribute("onclick");
- delete window.evaluated_imports_a;
- });
-
- const promise = createTestPromise();
-
- evaluator(`import('./imports-a.js?label=${label}').then(window.continueTest, window.errorTest);`);
-
- return promise.then(module => {
- assert_true(window.evaluated_imports_a, "The module must have been evaluated");
- assert_equals(module.A.from, "imports-a.js", "The module namespace object must be correct");
- });
- }, label + " should successfully import");
-};
-</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-integrity-classic.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-integrity-classic.html
new file mode 100644
index 00000000000..666bc7ce479
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-integrity-classic.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>import() doesn't have any integrity metadata when initiated by compiled strings inside a classic script</title>
+<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
+<meta http-equiv="Content-Security-Policy" content="require-sri-for script">
+
+<script src="/resources/testharness.js" integrity="sha384-4Nybydhnr3tOpv1yrTkDxu3RFpnxWAxlU5kGn7c8ebKvh1iUdfVMjqP6jf0dacrV"></script>
+<script src="/resources/testharnessreport.js" integrity="sha384-GOnHxuyo+nnsFAe4enY+RAl4/+w5NPMJPCQiDroTjxtR7ndRz7Uan8vNbM2qWKmU"></script>
+
+<div id="dummy"></div>
+
+<script>
+function createTestPromise() {
+ return new Promise((resolve, reject) => {
+ window.continueTest = resolve;
+ window.errorTest = reject;
+ });
+}
+
+const dummyDiv = document.querySelector("#dummy");
+
+const evaluators = {
+ eval,
+ setTimeout,
+ "the Function constructor"(x) {
+ Function(x)();
+ },
+ "reflected inline event handlers"(x) {
+ dummyDiv.setAttribute("onclick", x);
+ dummyDiv.onclick();
+ },
+ "inline event handlers triggered via UA code"(x) {
+ dummyDiv.setAttribute("onclick", x);
+ dummyDiv.click(); // different from .**on**click()
+ }
+};
+
+for (const [label, evaluator] of Object.entries(evaluators)) {
+ promise_test(t => {
+ t.add_cleanup(() => {
+ dummyDiv.removeAttribute("onclick");
+ delete window.evaluated_imports_a;
+ });
+
+ const promise = createTestPromise();
+
+ evaluator(`import('../imports-a.js?label=${label}').then(window.continueTest, window.errorTest);`);
+
+ return promise_rejects(t, new TypeError(), promise);
+ }, label + " should fail to import");
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-integrity-module.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-integrity-module.html
new file mode 100644
index 00000000000..497c9d97150
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-integrity-module.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>import() doesn't have any integrity metadata when initiated by compiled strings inside a module script</title>
+<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
+<meta http-equiv="Content-Security-Policy" content="require-sri-for script">
+
+<script src="/resources/testharness.js" integrity="sha384-4Nybydhnr3tOpv1yrTkDxu3RFpnxWAxlU5kGn7c8ebKvh1iUdfVMjqP6jf0dacrV"></script>
+<script src="/resources/testharnessreport.js" integrity="sha384-GOnHxuyo+nnsFAe4enY+RAl4/+w5NPMJPCQiDroTjxtR7ndRz7Uan8vNbM2qWKmU"></script>
+
+<div id="dummy"></div>
+
+<script type="module">
+function createTestPromise() {
+ return new Promise((resolve, reject) => {
+ window.continueTest = resolve;
+ window.errorTest = reject;
+ });
+}
+
+const dummyDiv = document.querySelector("#dummy");
+
+const evaluators = {
+ eval,
+ setTimeout,
+ "the Function constructor"(x) {
+ Function(x)();
+ },
+ "reflected inline event handlers"(x) {
+ dummyDiv.setAttribute("onclick", x);
+ dummyDiv.onclick();
+ },
+ "inline event handlers triggered via UA code"(x) {
+ dummyDiv.setAttribute("onclick", x);
+ dummyDiv.click(); // different from .**on**click()
+ }
+};
+
+for (const [label, evaluator] of Object.entries(evaluators)) {
+ promise_test(t => {
+ t.add_cleanup(() => {
+ dummyDiv.removeAttribute("onclick");
+ delete window.evaluated_imports_a;
+ });
+
+ const promise = createTestPromise();
+
+ evaluator(`import('../imports-a.js?label=${label}').then(window.continueTest, window.errorTest);`);
+
+ return promise_rejects(t, new TypeError(), promise);
+ }, label + " should fail to import");
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-classic.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-classic.html
new file mode 100644
index 00000000000..ba82fe8e7c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-classic.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>import() inside compiled strings uses the appropriate nonce inside a classic script</title>
+<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
+
+<meta http-equiv="content-security-policy" content="script-src 'nonce-correct' 'unsafe-eval' 'unsafe-hashed-attributes' 'sha256-cAMzxBL19bKt4KwKGbxy/ZOFIIjH5AmRjlVbsD5pvNw=' 'sha256-3VjoJYNK/9HJMS8rrZHlqSZgUssDY+GPyc7AU8lNM3k='">
+
+<script nonce="correct" src="/resources/testharness.js"></script>
+<script nonce="correct" src="/resources/testharnessreport.js"></script>
+
+<div id="dummy"></div>
+
+<script nonce="correct">
+"use strict";
+const dummyDiv = document.querySelector("#dummy");
+
+function createTestPromise(t) {
+ t.add_cleanup(() => {
+ delete window.evaluated_imports_a;
+ delete window.unreached;
+ delete window.continueTest;
+ delete window.errorTest;
+ });
+
+ return new Promise((resolve, reject) => {
+ window.unreached = t.unreached_func("Must not reach this");
+ window.continueTest = resolve;
+ window.errorTest = reject;
+ });
+}
+
+function assertSuccessful(module) {
+ assert_true(window.evaluated_imports_a, "The module must have been evaluated");
+ assert_equals(module.A.from, "imports-a.js", "The module namespace object must be correct");
+}
+
+promise_test(t => {
+ const promise = createTestPromise(t);
+
+ setTimeout(`import('../imports-a.js?label=setTimeout').then(window.unreached, window.continueTest)`, 0);
+
+ return promise.then(assertSuccessful);
+}, "setTimeout must inherit the nonce from the triggering script, thus execute");
+
+promise_test(t => {
+ const promise = createTestPromise(t);
+
+ eval(`import('../imports-a.js?label=direct eval').then(window.continueTest, window.errorTest)`);
+
+ return promise.then(assertSuccessful);
+}, "direct eval must inherit the nonce from the triggering script, thus execute");
+
+promise_test(t => {
+ const promise = createTestPromise(t);
+
+ const evalAlias = eval;
+ evalAlias(`import('../imports-a.js?label=indirect eval').then(window.continueTest, window.errorTest)`);
+
+ return promise.then(assertSuccessful);
+}, "indirect eval must inherit the nonce from the triggering script, thus execute");
+
+promise_test(t => {
+ const promise = createTestPromise(t);
+
+ Function(`import('../imports-a.js?label=the Function constructor').then(window.continueTest, window.errorTest)`)();
+
+ return promise.then(assertSuccessful);
+}, "the Function constructor must inherit the nonce from the triggering script, thus execute");
+
+promise_test(t => {
+ t.add_cleanup(() => {
+ dummyDiv.removeAttribute("onclick");
+ });
+
+ const promise = createTestPromise(t);
+
+ // This only works because of the 'unsafe-hashed-attributes' and the hash in the CSP policy
+ dummyDiv.setAttribute(
+ "onclick",
+ `import('../imports-a.js?label=reflected inline event handlers').then(window.continueTest, window.errorTest)`
+ );
+ dummyDiv.onclick();
+
+ return promise.then(assertSuccessful);
+}, "reflected inline event handlers must inherit the nonce from the triggering script, thus execute");
+
+promise_test(t => {
+ t.add_cleanup(() => {
+ dummyDiv.removeAttribute("onclick");
+ });
+
+ const promise = createTestPromise(t);
+
+ // This only works because of the 'unsafe-hashed-attributes' and the hash in the CSP policy
+ dummyDiv.setAttribute(
+ "onclick",
+ `import('../imports-a.js?label=inline event handlers triggered via UA code').then(window.continueTest, window.errorTest)`
+ );
+ dummyDiv.click(); // different from **on**click()
+
+ return promise.then(assertSuccessful);
+}, "inline event handlers triggered via UA code must inherit the nonce from the triggering script, thus execute");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-module.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-module.html
new file mode 100644
index 00000000000..889628f8395
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-module.html
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>import() inside compiled strings uses the appropriate nonce inside a module script</title>
+<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
+
+<meta http-equiv="content-security-policy" content="script-src 'nonce-correct' 'unsafe-eval' 'unsafe-hashed-attributes' 'sha256-cAMzxBL19bKt4KwKGbxy/ZOFIIjH5AmRjlVbsD5pvNw=' 'sha256-3VjoJYNK/9HJMS8rrZHlqSZgUssDY+GPyc7AU8lNM3k='">
+
+<script nonce="correct" src="/resources/testharness.js"></script>
+<script nonce="correct" src="/resources/testharnessreport.js"></script>
+
+<div id="dummy"></div>
+
+<script type="module" nonce="correct">
+const dummyDiv = document.querySelector("#dummy");
+
+function createTestPromise(t) {
+ t.add_cleanup(() => {
+ delete window.evaluated_imports_a;
+ delete window.unreached;
+ delete window.continueTest;
+ delete window.errorTest;
+ });
+
+ return new Promise((resolve, reject) => {
+ window.unreached = t.unreached_func("Must not reach this");
+ window.continueTest = resolve;
+ window.errorTest = reject;
+ });
+}
+
+function assertSuccessful(module) {
+ assert_true(window.evaluated_imports_a, "The module must have been evaluated");
+ assert_equals(module.A.from, "imports-a.js", "The module namespace object must be correct");
+}
+
+promise_test(t => {
+ const promise = createTestPromise(t);
+
+ setTimeout(`import('../imports-a.js?label=setTimeout').then(window.unreached, window.continueTest)`, 0);
+
+ return promise.then(assertSuccessful);
+}, "setTimeout must inherit the nonce from the triggering script, thus execute");
+
+promise_test(t => {
+ const promise = createTestPromise(t);
+
+ eval(`import('../imports-a.js?label=direct eval').then(window.continueTest, window.errorTest)`);
+
+ return promise.then(assertSuccessful);
+}, "direct eval must inherit the nonce from the triggering script, thus execute");
+
+promise_test(t => {
+ const promise = createTestPromise(t);
+
+ const evalAlias = eval;
+ evalAlias(`import('../imports-a.js?label=indirect eval').then(window.continueTest, window.errorTest)`);
+
+ return promise.then(assertSuccessful);
+}, "indirect eval must inherit the nonce from the triggering script, thus execute");
+
+promise_test(t => {
+ const promise = createTestPromise(t);
+
+ Function(`import('../imports-a.js?label=the Function constructor').then(window.continueTest, window.errorTest)`)();
+
+ return promise.then(assertSuccessful);
+}, "the Function constructor must inherit the nonce from the triggering script, thus execute");
+
+promise_test(t => {
+ t.add_cleanup(() => {
+ dummyDiv.removeAttribute("onclick");
+ });
+
+ const promise = createTestPromise(t);
+
+ // This only works because of the 'unsafe-hashed-attributes' and the hash in the CSP policy
+ dummyDiv.setAttribute(
+ "onclick",
+ `import('../imports-a.js?label=reflected inline event handlers').then(window.continueTest, window.errorTest)`
+ );
+ dummyDiv.onclick();
+
+ return promise.then(assertSuccessful);
+}, "reflected inline event handlers must inherit the nonce from the triggering script, thus execute");
+
+promise_test(t => {
+ t.add_cleanup(() => {
+ dummyDiv.removeAttribute("onclick");
+ });
+
+ const promise = createTestPromise(t);
+
+ // This only works because of the 'unsafe-hashed-attributes' and the hash in the CSP policy
+ dummyDiv.setAttribute(
+ "onclick",
+ `import('../imports-a.js?label=inline event handlers triggered via UA code').then(window.continueTest, window.errorTest)`
+ );
+ dummyDiv.click(); // different from **on**click()
+
+ return promise.then(assertSuccessful);
+}, "inline event handlers triggered via UA code must inherit the nonce from the triggering script, thus execute");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-1.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-1.html
new file mode 100644
index 00000000000..6f119e30064
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-1.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>Handling of different types of errors</title>
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+ setup({allow_uncaught_exception: true});
+
+ window.log = [];
+
+ window.addEventListener("error", ev => log.push(ev.error));
+
+ const test_load = async_test(
+ "network error has higher priority than parse error");
+ window.addEventListener("load", test_load.step_func_done(ev => {
+ assert_equals(log.length, 3);
+
+ // A parse error is reported for the first top-level
+ // <script> element for syntaxerror.js.
+ assert_equals(log[0].constructor, SyntaxError);
+ assert_equals(log[1], 1);
+
+ // onerror is called (with no errors reported) due to a network error
+ // for the second top-level <script>.
+ assert_equals(log[2], 2);
+ }));
+
+ function unreachable() { log.push("unexpected"); }
+</script>
+<script type="module" src="./syntaxerror.js"
+ onerror="unreachable()" onload="log.push(1)"></script>
+<script type="module" src="./error-type-1.js"
+ onerror="log.push(2)" onload="unreachable()"></script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-1.js b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-1.js
new file mode 100644
index 00000000000..4882d3f2a56
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-1.js
@@ -0,0 +1,2 @@
+import './syntaxerror.js';
+import './404.js';
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-2.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-2.html
new file mode 100644
index 00000000000..a7df1df0c86
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-2.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<title>Handling of different types of errors</title>
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+ setup({allow_uncaught_exception: true});
+
+ window.log = [];
+
+ window.addEventListener("error", ev => log.push(ev.error));
+
+ const test_load = async_test(
+ "parse error has higher priority than instantiation error");
+ window.addEventListener("load", test_load.step_func_done(ev => {
+ assert_equals(log.length, 4);
+
+ // An instantiation error is reported for the first top-level
+ // <script> element for instantiation-error-1.js.
+ assert_equals(log[0].constructor, SyntaxError);
+ assert_equals(log[1], 1);
+
+ // A parse error is reported for the second top-level <script>.
+ assert_equals(log[2].constructor, SyntaxError);
+ assert_equals(log[3], 2);
+ assert_not_equals(log[0], log[2]);
+ }));
+
+ function unreachable() { log.push("unexpected"); }
+</script>
+<script type="module" src="./instantiation-error-1.js"
+ onerror="unreachable()" onload="log.push(1)"></script>
+<script type="module" src="./error-type-2.js"
+ onerror="unreachable()" onload="log.push(2)"></script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-2.js b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-2.js
new file mode 100644
index 00000000000..6b113973009
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-2.js
@@ -0,0 +1,2 @@
+import './instantiation-error-1.js';
+import './syntaxerror.js';
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-3.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-3.html
new file mode 100644
index 00000000000..9b00df38915
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-3.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<title>Handling of different types of errors</title>
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+ setup({allow_uncaught_exception: true});
+
+ window.log = [];
+
+ window.addEventListener("error", ev => log.push(ev.error));
+
+ const test_load = async_test(
+ "instantiation error has higher priority than evaluation error");
+ window.addEventListener("load", test_load.step_func_done(ev => {
+ assert_equals(log.length, 5);
+
+ // An evaluation error is reported for the first top-level
+ // <script> element for throw.js.
+ assert_equals(log[0], 'throw');
+ assert_true(log[1].foo);
+ assert_equals(log[2], 1);
+
+ // An instantiation error is reported for the second top-level <script>.
+ assert_equals(log[3].constructor, SyntaxError);
+ assert_equals(log[4], 2);
+ }));
+
+ function unreachable() { log.push("unexpected"); }
+</script>
+<script type="module" src="./throw.js"
+ onerror="unreachable()" onload="log.push(1)"></script>
+<script type="module" src="./error-type-3.js"
+ onerror="unreachable()" onload="log.push(2)"></script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-3.js b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-3.js
new file mode 100644
index 00000000000..542be52846a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/error-type-3.js
@@ -0,0 +1,2 @@
+import './throw.js';
+import './instantiation-error-1.js';
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-1.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-1.html
index efdf5879fce..57b40f5baaf 100644
--- a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-1.html
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-1.html
@@ -6,17 +6,19 @@
<script>
setup({allow_uncaught_exception: true});
- window.log = [];
-
- window.addEventListener("error", ev => log.push(ev.error));
-
const test_load = async_test(
"Test that missing exports lead to SyntaxError events on window and " +
- "load events on script, and that exceptions are remembered");
+ "load events on script");
+
+ window.log = [];
+ window.addEventListener("error", ev => {
+ test_load.step(() => assert_equals(ev.error.constructor, SyntaxError));
+ log.push(ev.message);
+ });
+
window.addEventListener("load", test_load.step_func_done(ev => {
- const exn = log[0];
- assert_array_equals(log, [exn, 1, exn, 2, exn, 3, exn, 4, exn, 5]);
- assert_equals(exn.constructor, SyntaxError);
+ const msg = log[0];
+ assert_array_equals(log, [msg, 1, msg, 2, msg, 3, msg, 4, msg, 5]);
}));
function unreachable() { log.push("unexpected"); }
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-2.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-2.html
index 3d50ce63a6b..27ba006fc7a 100644
--- a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-2.html
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-2.html
@@ -6,17 +6,19 @@
<script>
setup({allow_uncaught_exception: true});
- window.log = [];
-
- window.addEventListener("error", ev => log.push(ev.error));
-
const test_load = async_test(
"Test that missing exports lead to SyntaxError events on window and " +
- "load events on script, and that exceptions are remembered");
+ "load events on script");
+
+ window.log = [];
+ window.addEventListener("error", ev => {
+ test_load.step(() => assert_equals(ev.error.constructor, SyntaxError));
+ log.push(ev.message);
+ });
+
window.addEventListener("load", test_load.step_func_done(ev => {
- const exn = log[0];
- assert_array_equals(log, [exn, 1, exn, 2, exn, 3, exn, 4, exn, 5]);
- assert_equals(exn.constructor, SyntaxError);
+ const msg = log[0];
+ assert_array_equals(log, [msg, 1, msg, 2, msg, 3, msg, 4, msg, 5]);
}));
function unreachable() { log.push("unexpected"); }
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-3.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-3.html
index ab510c675ad..e03fcc0ecbb 100644
--- a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-3.html
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-3.html
@@ -6,17 +6,19 @@
<script>
setup({allow_uncaught_exception: true});
- window.log = [];
-
- window.addEventListener("error", ev => log.push(ev.error));
-
const test_load = async_test(
"Test that unresolvable cycles lead to SyntaxError events on window " +
- "and load events on script, and that exceptions are remembered");
+ "and load events on script");
+
+ window.log = [];
+ window.addEventListener("error", ev => {
+ test_load.step(() => assert_equals(ev.error.constructor, SyntaxError));
+ log.push(ev.message);
+ });
+
window.addEventListener("load", test_load.step_func_done(ev => {
- const exn = log[0];
- assert_array_equals(log, [exn, 1, exn, 2, exn, 3]);
- assert_equals(exn.constructor, SyntaxError);
+ const msg = log[0];
+ assert_array_equals(log, [msg, 1, msg, 2, msg, 3]);
}));
function unreachable() { log.push("unexpected"); }
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-4.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-4.html
index 4eb2f9f277b..238e8832c00 100644
--- a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-4.html
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-4.html
@@ -7,16 +7,18 @@
setup({allow_uncaught_exception: true});
window.log = [];
-
- window.addEventListener("error", ev => log.push(ev.error));
-
const test_load = async_test(
"Test that loading a graph in which a module is already " +
- "errored results in that module's error.");
+ "errored results in an error.");
+
+ window.addEventListener("error", ev => {
+ test_load.step(() => assert_equals(ev.error.constructor, SyntaxError));
+ log.push(ev.message);
+ });
+
window.addEventListener("load", test_load.step_func_done(ev => {
- const exn = log[0];
- assert_array_equals(log, [exn, 1, exn, 2]);
- assert_equals(exn.constructor, SyntaxError);
+ const msg = log[0];
+ assert_array_equals(log, [msg, 1, msg, 2]);
}));
function unreachable() { log.push("unexpected"); }
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-5.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-5.html
index 86d0fb3e956..de2b6ba7b34 100644
--- a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-5.html
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-5.html
@@ -6,17 +6,19 @@
<script>
setup({allow_uncaught_exception: true});
- window.log = [];
-
- window.addEventListener("error", ev => log.push(ev.error));
-
const test_load = async_test(
"Test that loading a graph in which a module is already " +
- "errored results in that module's error.");
+ "errored results an error.");
+
+ window.log = [];
+ window.addEventListener("error", ev => {
+ test_load.step(() => assert_equals(ev.error.constructor, SyntaxError));
+ log.push(ev.message);
+ });
+
window.addEventListener("load", test_load.step_func_done(ev => {
- const exn = log[0];
- assert_array_equals(log, [exn, 1, exn, 2]);
- assert_equals(exn.constructor, SyntaxError);
+ const msg = log[0];
+ assert_array_equals(log, [msg, 1, msg, 2]);
}));
function unreachable() { log.push("unexpected"); }
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/referrer-no-referrer.sub.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/referrer-no-referrer.sub.html
new file mode 100644
index 00000000000..e50c7b525b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/referrer-no-referrer.sub.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Referrer with the no-referrer policy</title>
+<meta name="referrer" content="no-referrer">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script type="module">
+
+// "name" parameter is necessary for bypassing the module map.
+
+import { referrer as referrerSame } from "./resources/referrer-checker.py?name=same";
+
+import { referrer as referrerRemote } from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py?name=remote";
+
+import { referrer as referrerSameSame } from "./resources/import-referrer-checker.sub.js?name=same_same";
+
+import { referrer as referrerSameRemote } from "./resources/import-remote-origin-referrer-checker.sub.js?name=same_remote";
+
+import { referrer as referrerRemoteRemote } from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js?name=remote_remote";
+
+test(t => {
+ assert_equals(
+ referrerSame, "",
+ "Referrer should not be sent for the same-origin top-level script.");
+}, "Importing a same-origin top-level script with the no-referrer policy.");
+
+test(t => {
+ assert_equals(
+ referrerRemote, "",
+ "Referrer should not be sent for the remote-origin top-level script.");
+}, "Importing a remote-origin top-level script with the no-referrer policy.");
+
+test(t => {
+ assert_equals(
+ referrerSameSame, "",
+ "Referrer should not be sent for the same-origin descendant script.");
+}, "Importing a same-origin descendant script from a same-origin top-level " +
+ "script with the no-referrer policy.");
+
+test(t => {
+ assert_equals(
+ referrerSameRemote, "",
+ "Referrer should not be sent for the remote-origin descendant script.");
+}, "Importing a remote-origin descendant script from a same-origin top-level " +
+ "script with the no-referrer policy.");
+
+test(t => {
+ assert_equals(
+ referrerRemoteRemote, "",
+ "Referrer should not be sent for the remote-origin descendant script.");
+}, "Importing a remote-origin descendant script from a remote-origin " +
+ "top-level script with the no-referrer policy.");
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/referrer-origin-when-cross-origin.sub.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/referrer-origin-when-cross-origin.sub.html
new file mode 100644
index 00000000000..3623ac2ccb2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/referrer-origin-when-cross-origin.sub.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Referrer with the origin-when-cross-origin policy</title>
+<meta name="referrer" content="origin-when-cross-origin">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script type="module">
+
+// "name" parameter is necessary for bypassing the module map.
+
+import { referrer as referrerSame } from "./resources/referrer-checker.py?name=same";
+
+import { referrer as referrerRemote } from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py?name=remote";
+
+import { referrer as referrerSameSame } from "./resources/import-referrer-checker.sub.js?name=same_same";
+
+import { referrer as referrerSameRemote } from "./resources/import-remote-origin-referrer-checker.sub.js?name=same_remote";
+
+import { referrer as referrerRemoteRemote } from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js?name=remote_remote";
+
+const origin = (new URL(location.href)).origin + "/";
+const remoteOrigin = "http://{{domains[www1]}}:{{ports[http][0]}}/";
+
+test(t => {
+ assert_equals(
+ referrerSame, location.href,
+ "Referrer should be sent for the same-origin top-level script.");
+}, "Importing a same-origin top-level script with the " +
+ "origin-when-cross-origin policy.");
+
+test(t => {
+ assert_equals(
+ referrerRemote, origin,
+ "Referrer should be sent for the remote-origin top-level script.");
+}, "Importing a remote-origin top-level script with the " +
+ "origin-when-cross-origin policy.");
+
+test(t => {
+ const scriptURL =
+ new URL("resources/import-referrer-checker.sub.js", location.href)
+ assert_equals(
+ referrerSameSame, scriptURL + "?name=same_same",
+ "Referrer should be sent for the same-origin descendant script.");
+}, "Importing a same-origin descendant script from a same-origin top-level " +
+ "script with the origin-when-cross-origin policy.");
+
+test(t => {
+ assert_equals(
+ referrerSameRemote, origin,
+ "Referrer should be sent for the remote-origin descendant script.");
+}, "Importing a remote-origin descendant script from a same-origin top-level " +
+ "script with the origin-when-cross-origin policy.");
+
+test(t => {
+ assert_equals(
+ referrerRemoteRemote, remoteOrigin,
+ "Referrer should be sent for the remote-origin descendant script.");
+}, "Importing a remote-origin descendant script from a remote-origin " +
+ "top-level script with the origin-when-cross-origin policy.");
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/referrer-origin.sub.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/referrer-origin.sub.html
new file mode 100644
index 00000000000..f512982a451
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/referrer-origin.sub.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Referrer with the origin policy</title>
+<meta name="referrer" content="origin">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script type="module">
+
+// "name" parameter is necessary for bypassing the module map.
+
+import { referrer as referrerSame } from "./resources/referrer-checker.py?name=same";
+
+import { referrer as referrerRemote } from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py?name=remote";
+
+import { referrer as referrerSameSame } from "./resources/import-referrer-checker.sub.js?name=same_same";
+
+import { referrer as referrerSameRemote } from "./resources/import-remote-origin-referrer-checker.sub.js?name=same_remote";
+
+import { referrer as referrerRemoteRemote } from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js?name=remote_remote";
+
+const origin = (new URL(location.href)).origin + "/";
+const remoteOrigin = "http://{{domains[www1]}}:{{ports[http][0]}}/";
+
+test(t => {
+ assert_equals(
+ referrerSame, origin,
+ "Referrer should be sent for the same-origin top-level script.");
+}, "Importing a same-origin top-level script with the origin policy.");
+
+test(t => {
+ assert_equals(
+ referrerRemote, origin,
+ "Referrer should be sent for the remote-origin top-level script.");
+}, "Importing a remote-origin top-level script with the origin policy.");
+
+test(t => {
+ assert_equals(
+ referrerSameSame, origin,
+ "Referrer should be sent for the same-origin descendant script.");
+}, "Importing a same-origin descendant script from a same-origin top-level " +
+ "script with the origin policy.");
+
+test(t => {
+ assert_equals(
+ referrerSameRemote, origin,
+ "Referrer should be sent for the remote-origin descendant script.");
+}, "Importing a remote-origin descendant script from a same-origin top-level " +
+ "script with the origin policy.");
+
+test(t => {
+ assert_equals(
+ referrerRemoteRemote, remoteOrigin,
+ "Referrer should be sent for the remote-origin descendant script.");
+}, "Importing a remote-origin descendant script from a remote-origin " +
+ "top-level script with the origin policy.");
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/referrer-same-origin.sub.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/referrer-same-origin.sub.html
new file mode 100644
index 00000000000..67b055c217d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/referrer-same-origin.sub.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Referrer with the same-origin policy</title>
+<meta name="referrer" content="same-origin">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script type="module">
+
+// "name" parameter is necessary for bypassing the module map.
+
+import { referrer as referrerSame } from "./resources/referrer-checker.py?name=same";
+
+import { referrer as referrerRemote } from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py?name=remote";
+
+import { referrer as referrerSameSame } from "./resources/import-referrer-checker.sub.js?name=same_same";
+
+import { referrer as referrerSameRemote } from "./resources/import-remote-origin-referrer-checker.sub.js?name=same_remote";
+
+import { referrer as referrerRemoteRemote } from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js?name=remote_remote";
+
+test(t => {
+ assert_equals(
+ referrerSame, location.href,
+ "Referrer should be sent for the same-origin top-level script.");
+}, "Importing a same-origin top-level script with the same-origin policy.");
+
+test(t => {
+ assert_equals(
+ referrerRemote, "",
+ "Referrer should not be sent for the remote-origin top-level script.");
+}, "Importing a remote-origin top-level script with the same-origin policy.");
+
+test(t => {
+ const path =
+ new URL("resources/import-referrer-checker.sub.js", location.href);
+ assert_equals(
+ referrerSameSame, path + `?name=same_same`,
+ "Referrer should be sent for the same-origin descendant script.");
+}, "Importing a same-origin descendant script from a same-origin top-level " +
+ "script with the same-origin policy.");
+
+test(t => {
+ assert_equals(
+ referrerSameRemote, "",
+ "Referrer should not be sent for the remote-origin descendant script.");
+}, "Importing a remote-origin descendant script from a same-origin top-level " +
+ "script with the same-origin policy.");
+
+test(t => {
+ assert_equals(
+ referrerRemoteRemote, "",
+ "Referrer should not be sent for the remote-origin descendant script " +
+ "even if it is imported from the script in the same remote-origin.");
+}, "Importing a remote-origin descendant script from a remote-origin " +
+ "top-level script with the same-origin policy.");
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/referrer-unsafe-url.sub.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/referrer-unsafe-url.sub.html
new file mode 100644
index 00000000000..11f60c010f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/referrer-unsafe-url.sub.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Referrer with the unsafe-url policy</title>
+<meta name="referrer" content="unsafe-url">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script type="module">
+
+// "name" parameter is necessary for bypassing the module map.
+
+import { referrer as referrerSame } from "./resources/referrer-checker.py?name=same";
+
+import { referrer as referrerRemote } from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py?name=remote";
+
+import { referrer as referrerSameSame } from "./resources/import-referrer-checker.sub.js?name=same_same";
+
+import { referrer as referrerSameRemote } from "./resources/import-remote-origin-referrer-checker.sub.js?name=same_remote";
+
+import { referrer as referrerRemoteRemote } from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js?name=remote_remote";
+
+test(t => {
+ assert_equals(
+ referrerSame, location.href,
+ "Referrer should be sent for the same-origin top-level script.");
+}, "Importing a same-origin top-level script with the unsafe-url policy.");
+
+test(t => {
+ assert_equals(
+ referrerRemote, location.href,
+ "Referrer should be sent for the remote-origin top-level script.");
+}, "Importing a remote-origin top-level script with the unsafe-url policy.");
+
+test(t => {
+ const scriptURL =
+ new URL("resources/import-referrer-checker.sub.js", location.href)
+ assert_equals(
+ referrerSameSame, scriptURL + "?name=same_same",
+ "Referrer should be sent for the same-origin descendant script.");
+}, "Importing a same-origin descendant script from a same-origin top-level " +
+ "script with the unsafe-url policy.");
+
+test(t => {
+ const scriptURL =
+ new URL("resources/import-remote-origin-referrer-checker.sub.js",
+ location.href)
+ assert_equals(
+ referrerSameRemote, scriptURL + "?name=same_remote",
+ "Referrer should be sent for the remote-origin descendant script.");
+}, "Importing a remote-origin descendant script from a same-origin top-level " +
+ "script with the unsafe-url policy.");
+
+test(t => {
+ const scriptURL =
+ "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/" +
+ "scripting-1/the-script-element/module/resources/" +
+ "import-referrer-checker.sub.js";
+ assert_equals(
+ referrerRemoteRemote, scriptURL + "?name=remote_remote",
+ "Referrer should be sent for the remote-origin descendant script.");
+}, "Importing a remote-origin descendant script from a remote-origin " +
+ "top-level script with the unsafe-url policy.");
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js
new file mode 100644
index 00000000000..2c7dce9dffa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js
@@ -0,0 +1,2 @@
+import { referrer as referrerImport } from './referrer-checker.py?name={{GET[name]}}';
+export const referrer = referrerImport;
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js.headers b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js.headers
new file mode 100644
index 00000000000..cb762eff806
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js.headers
@@ -0,0 +1 @@
+Access-Control-Allow-Origin: *
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/resources/import-remote-origin-referrer-checker.sub.js b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/resources/import-remote-origin-referrer-checker.sub.js
new file mode 100644
index 00000000000..45a2520b68c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/resources/import-remote-origin-referrer-checker.sub.js
@@ -0,0 +1,2 @@
+import { referrer as referrerImport } from 'http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py?name={{GET[name]}}';
+export const referrer = referrerImport;
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py
new file mode 100644
index 00000000000..b652cbe2c86
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py
@@ -0,0 +1,6 @@
+def main(request, response):
+ referrer = request.headers.get("referer", "")
+ response_headers = [("Content-Type", "text/javascript"),
+ ("Access-Control-Allow-Origin", "*")];
+ return (200, response_headers,
+ "export const referrer = '" + referrer + "';")
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/throw2.js b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/throw2.js
new file mode 100644
index 00000000000..2931eec500d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/module/throw2.js
@@ -0,0 +1,2 @@
+log.push("throw2");
+throw {bar: true}
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-defer.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-defer.html
new file mode 100644
index 00000000000..80eb98dc750
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-defer.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: HTMLScriptElement - defer</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<div id="log"></div>
+
+<script>
+
+let script_run_status = "inline";
+let t = async_test("the defer script run later");
+
+</script>
+
+<script type="text/javascript" src="defer.js" defer></script>
+
+<script>
+
+t.step(() => {
+ assert_equals(script_run_status, "inline", "the script run status");
+ script_run_status = "deferred";
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/a-download-click-404.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/a-download-click-404.html
index db9e1cbfb92..3c8adc0b97e 100644
--- a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/a-download-click-404.html
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/a-download-click-404.html
@@ -11,15 +11,15 @@
async_test(t => {
const errorFrame = document.createElement("iframe");
- errorFrame.addEventListener("load", function () {
+ errorFrame.addEventListener("load", t.step_func(function () {
errorFrame.contentWindow.addEventListener(
"beforeunload", t.unreached_func("Navigated instead of downloading"));
errorFrame.contentDocument.querySelector("#error-url").click();
t.step_timeout(() => t.done(), 1000);
- });
+ }));
errorFrame.src = "resources/a-download-404.html";
document.body.appendChild(errorFrame);
}, "Do not navigate to 404 for anchor with download");
</script>
-</body> \ No newline at end of file
+</body>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/a-download-click.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/a-download-click.html
index ad6a3df001e..22d329f2452 100644
--- a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/a-download-click.html
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/a-download-click.html
@@ -7,18 +7,27 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<a id="blob-url" download="foo.html">Click me</a>
-
+<body>
<script>
"use strict";
+async_test(t => {
+ const frame = document.createElement("iframe");
-const string = "test";
-const blob = new Blob([string], { type: "text/html" });
+ frame.addEventListener("load", t.step_func(function () {
+ frame.contentWindow.addEventListener(
+ "beforeunload", t.unreached_func("Navigated instead of downloading"));
+ const string = "test";
+ const blob = new Blob([string], { type: "text/html" });
-const link = document.querySelector("#blob-url");
-link.href = URL.createObjectURL(blob);
+ const link = frame.contentDocument.querySelector("#blob-url");
+ link.href = URL.createObjectURL(blob);
-link.click();
+ link.click();
-done();
+ t.step_timeout(() => t.done(), 1000);
+ }));
+ frame.src = "resources/a-download-click.html";
+ document.body.appendChild(frame);
+}, "Clicking on an <a> element with a download attribute must not throw an exception");
</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/resources/a-download-click.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/resources/a-download-click.html
new file mode 100644
index 00000000000..7d36c21d1e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/resources/a-download-click.html
@@ -0,0 +1,2 @@
+<!doctype html>
+<a id="blob-url" download="foo.html">Click me</a>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-b-element/b-usage-notref.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-b-element/b-usage-notref.html
new file mode 100644
index 00000000000..3d3c46a281f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-b-element/b-usage-notref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Reference File</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+
+<p>You enter a small room. Your sword glows brighter. A rat scurries past the corner wall.</p>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-b-element/b-usage.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-b-element/b-usage.html
new file mode 100644
index 00000000000..ff2105dcae8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-b-element/b-usage.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML test: b - highlight keywords</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="mismatch" href="b-usage-notref.html">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/text-level-semantics.html#the-b-element"/>
+
+<p>You enter a small room. Your <b>sword</b> glows brighter. A <b>rat</b> scurries past the corner wall.</p>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-ruby-element/ruby-usage-notref.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-ruby-element/ruby-usage-notref.html
new file mode 100644
index 00000000000..f5747811ae4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-ruby-element/ruby-usage-notref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Reference File</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+
+<p>君くん子しは和わして同どうぜず</p>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-ruby-element/ruby-usage.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-ruby-element/ruby-usage.html
new file mode 100644
index 00000000000..59c076cd092
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-ruby-element/ruby-usage.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML test: ruby - mark phrasing content</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="mismatch" href="ruby-usage-notref.html">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/text-level-semantics.html#the-ruby-element"/>
+
+<p><ruby>君<rt>くん</ruby><ruby>子<rt>し</ruby>は<ruby>和<rt>わ</ruby>して<ruby>同<rt>どう</ruby>ぜず</p>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/animation-frames/idlharness.html b/tests/wpt/web-platform-tests/html/webappapis/animation-frames/idlharness.html
index acc6657fac6..3a9d1d9b583 100644
--- a/tests/wpt/web-platform-tests/html/webappapis/animation-frames/idlharness.html
+++ b/tests/wpt/web-platform-tests/html/webappapis/animation-frames/idlharness.html
@@ -15,7 +15,7 @@
<p>This test validates the WebIDL included in the Timing control for script-based animations specification.</p>
<pre id='untested_idl' style='display:none'>
-[PrimaryGlobal]
+[Global=Window, Exposed=Window]
interface Window {
};
</pre>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/events/event-handler-spec-example.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/events/event-handler-spec-example.html
index c06806e3c77..1f3cff42652 100644
--- a/tests/wpt/web-platform-tests/html/webappapis/scripting/events/event-handler-spec-example.html
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/events/event-handler-spec-example.html
@@ -15,6 +15,7 @@ objects.forEach(function(object) {
var uncalled = "t.step(function() { assert_unreached('First event handler.') })"
var button = document.createElement('button');
button.onclick = object; // event handler listener is registered here
+ assert_equals(button.onclick, object);
button.addEventListener('click', t.step_func(function () { assert_equals(++i, 2) }), false);
button.setAttribute('onclick', uncalled);
button.addEventListener('click', t.step_func(function () { assert_equals(++i, 3) }), false);
@@ -35,6 +36,7 @@ primitives.forEach(function(primitive) {
var uncalled = "t.step(function() { assert_unreached('First event handler.') })"
var button = document.createElement('button');
button.onclick = primitive;
+ assert_equals(button.onclick, null);
button.addEventListener('click', t.step_func(function () { assert_equals(++i, 1) }), false);
button.setAttribute('onclick', uncalled); // event handler listener is registered here
button.addEventListener('click', t.step_func(function () { assert_equals(++i, 3) }), false);
diff --git a/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.html b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.html
index a9ceee5a846..d090aad609d 100644
--- a/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.html
+++ b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.html
@@ -58,12 +58,12 @@ test(function () {
}, 'an empty url argument should throw SYNTAX_ERR');
test(function () {
- assert_throws('SYNTAX_ERR', function () { navigator.registerProtocolHandler('mailto', 'http://%s.com', 'foo') } );
-}, '%s instead of domain name should throw SYNTAX_ERR');
+ assert_throws('SECURITY_ERR', function () { navigator.registerProtocolHandler('mailto', 'http://%s.com', 'foo') } );
+}, '%s instead of domain name should throw SECURITY_ERR');
test(function () {
- assert_throws('SYNTAX_ERR', function () { navigator.registerProtocolHandler('mailto', 'http://%s.example.com', 'foo') } );
-}, '%s instead of subdomain name should throw SYNTAX_ERR');
+ assert_throws('SECURITY_ERR', function () { navigator.registerProtocolHandler('mailto', 'http://%s.example.com', 'foo') } );
+}, '%s instead of subdomain name should throw SECURITY_ERR');
test(function () {
assert_throws('SYNTAX_ERR', function () { navigator.registerProtocolHandler('mailto', location.href + '', 'foo') } );
diff --git a/tests/wpt/web-platform-tests/http/resources/securedimage.py b/tests/wpt/web-platform-tests/http/resources/securedimage.py
index 311b0c5259c..89cbd72b134 100644
--- a/tests/wpt/web-platform-tests/http/resources/securedimage.py
+++ b/tests/wpt/web-platform-tests/http/resources/securedimage.py
@@ -6,12 +6,10 @@ def main(request, response):
if "authorization" not in request.headers:
response.status = 401
response.headers.set("WWW-Authenticate", "Basic")
- return response
else:
auth = request.headers.get("Authorization")
if auth != "Basic dGVzdHVzZXI6dGVzdHBhc3M=":
response.set_error(403, "Invalid username or password - " + auth)
- return response
response.status = 301
response.headers.set("Location", image_url)
diff --git a/tests/wpt/web-platform-tests/infrastructure/assumptions/ahem-notref.html b/tests/wpt/web-platform-tests/infrastructure/assumptions/ahem-notref.html
new file mode 100644
index 00000000000..51767c26ea8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/infrastructure/assumptions/ahem-notref.html
@@ -0,0 +1,316 @@
+<!doctype html>
+<title>Ahem checker</title>
+<style>
+* {
+ padding: 0;
+ margin: 0;
+ border: none;
+}
+td {
+ width: 34px;
+}
+table {
+ font-size: 15px;
+ line-height: 1;
+ border-collapse: separate;
+ border-spacing: 1px;
+ table-layout: fixed;
+}
+</style>
+<table>
+ <tr>
+ <td>&#x0020;x <!-- U+0020: SPACE -->
+ <td>&#x0021;x <!-- U+0021: EXCLAMATION MARK -->
+ <td>&#x0022;x <!-- U+0022: QUOTATION MARK -->
+ <td>&#x0023;x <!-- U+0023: NUMBER SIGN -->
+ <td>&#x0024;x <!-- U+0024: DOLLAR SIGN -->
+ <td>&#x0025;x <!-- U+0025: PERCENT SIGN -->
+ <td>&#x0026;x <!-- U+0026: AMPERSAND -->
+ <td>&#x0028;x <!-- U+0028: LEFT PARENTHESIS -->
+ <td>&#x0029;x <!-- U+0029: RIGHT PARENTHESIS -->
+ <td>&#x002A;x <!-- U+002A: ASTERISK -->
+ <td>&#x002B;x <!-- U+002B: PLUS SIGN -->
+ <td>&#x002C;x <!-- U+002C: COMMA -->
+ <td>&#x002D;x <!-- U+002D: HYPHEN-MINUS -->
+ <td>&#x002E;x <!-- U+002E: FULL STOP -->
+ <td>&#x002F;x <!-- U+002F: SOLIDUS -->
+ <td>&#x0030;x <!-- U+0030: DIGIT ZERO -->
+ <td>&#x0031;x <!-- U+0031: DIGIT ONE -->
+ <tr>
+ <td>&#x0032;x <!-- U+0032: DIGIT TWO -->
+ <td>&#x0033;x <!-- U+0033: DIGIT THREE -->
+ <td>&#x0034;x <!-- U+0034: DIGIT FOUR -->
+ <td>&#x0035;x <!-- U+0035: DIGIT FIVE -->
+ <td>&#x0036;x <!-- U+0036: DIGIT SIX -->
+ <td>&#x0037;x <!-- U+0037: DIGIT SEVEN -->
+ <td>&#x0038;x <!-- U+0038: DIGIT EIGHT -->
+ <td>&#x0039;x <!-- U+0039: DIGIT NINE -->
+ <td>&#x003A;x <!-- U+003A: COLON -->
+ <td>&#x003B;x <!-- U+003B: SEMICOLON -->
+ <td>&#x003C;x <!-- U+003C: LESS-THAN SIGN -->
+ <td>&#x003D;x <!-- U+003D: EQUALS SIGN -->
+ <td>&#x003E;x <!-- U+003E: GREATER-THAN SIGN -->
+ <td>&#x003F;x <!-- U+003F: QUESTION MARK -->
+ <td>&#x0040;x <!-- U+0040: COMMERCIAL AT -->
+ <td>&#x0041;x <!-- U+0041: LATIN CAPITAL LETTER A -->
+ <td>&#x0042;x <!-- U+0042: LATIN CAPITAL LETTER B -->
+ <tr>
+ <td>&#x0043;x <!-- U+0043: LATIN CAPITAL LETTER C -->
+ <td>&#x0044;x <!-- U+0044: LATIN CAPITAL LETTER D -->
+ <td>&#x0045;x <!-- U+0045: LATIN CAPITAL LETTER E -->
+ <td>&#x0046;x <!-- U+0046: LATIN CAPITAL LETTER F -->
+ <td>&#x0047;x <!-- U+0047: LATIN CAPITAL LETTER G -->
+ <td>&#x0048;x <!-- U+0048: LATIN CAPITAL LETTER H -->
+ <td>&#x0049;x <!-- U+0049: LATIN CAPITAL LETTER I -->
+ <td>&#x004A;x <!-- U+004A: LATIN CAPITAL LETTER J -->
+ <td>&#x004B;x <!-- U+004B: LATIN CAPITAL LETTER K -->
+ <td>&#x004C;x <!-- U+004C: LATIN CAPITAL LETTER L -->
+ <td>&#x004D;x <!-- U+004D: LATIN CAPITAL LETTER M -->
+ <td>&#x004E;x <!-- U+004E: LATIN CAPITAL LETTER N -->
+ <td>&#x004F;x <!-- U+004F: LATIN CAPITAL LETTER O -->
+ <td>&#x0050;x <!-- U+0050: LATIN CAPITAL LETTER P -->
+ <td>&#x0051;x <!-- U+0051: LATIN CAPITAL LETTER Q -->
+ <td>&#x0052;x <!-- U+0052: LATIN CAPITAL LETTER R -->
+ <td>&#x0053;x <!-- U+0053: LATIN CAPITAL LETTER S -->
+ <tr>
+ <td>&#x0054;x <!-- U+0054: LATIN CAPITAL LETTER T -->
+ <td>&#x0055;x <!-- U+0055: LATIN CAPITAL LETTER U -->
+ <td>&#x0056;x <!-- U+0056: LATIN CAPITAL LETTER V -->
+ <td>&#x0057;x <!-- U+0057: LATIN CAPITAL LETTER W -->
+ <td>&#x0058;x <!-- U+0058: LATIN CAPITAL LETTER X -->
+ <td>&#x0059;x <!-- U+0059: LATIN CAPITAL LETTER Y -->
+ <td>&#x005A;x <!-- U+005A: LATIN CAPITAL LETTER Z -->
+ <td>&#x005B;x <!-- U+005B: LEFT SQUARE BRACKET -->
+ <td>&#x005C;x <!-- U+005C: REVERSE SOLIDUS -->
+ <td>&#x005D;x <!-- U+005D: RIGHT SQUARE BRACKET -->
+ <td>&#x005E;x <!-- U+005E: CIRCUMFLEX ACCENT -->
+ <td>&#x005F;x <!-- U+005F: LOW LINE -->
+ <td>&#x0060;x <!-- U+0060: GRAVE ACCENT -->
+ <td>&#x0061;x <!-- U+0061: LATIN SMALL LETTER A -->
+ <td>&#x0062;x <!-- U+0062: LATIN SMALL LETTER B -->
+ <td>&#x0063;x <!-- U+0063: LATIN SMALL LETTER C -->
+ <td>&#x0064;x <!-- U+0064: LATIN SMALL LETTER D -->
+ <tr>
+ <td>&#x0065;x <!-- U+0065: LATIN SMALL LETTER E -->
+ <td>&#x0066;x <!-- U+0066: LATIN SMALL LETTER F -->
+ <td>&#x0067;x <!-- U+0067: LATIN SMALL LETTER G -->
+ <td>&#x0068;x <!-- U+0068: LATIN SMALL LETTER H -->
+ <td>&#x0069;x <!-- U+0069: LATIN SMALL LETTER I -->
+ <td>&#x006A;x <!-- U+006A: LATIN SMALL LETTER J -->
+ <td>&#x006B;x <!-- U+006B: LATIN SMALL LETTER K -->
+ <td>&#x006C;x <!-- U+006C: LATIN SMALL LETTER L -->
+ <td>&#x006D;x <!-- U+006D: LATIN SMALL LETTER M -->
+ <td>&#x006E;x <!-- U+006E: LATIN SMALL LETTER N -->
+ <td>&#x006F;x <!-- U+006F: LATIN SMALL LETTER O -->
+ <td>&#x0070;x <!-- U+0070: LATIN SMALL LETTER P -->
+ <td>&#x0071;x <!-- U+0071: LATIN SMALL LETTER Q -->
+ <td>&#x0072;x <!-- U+0072: LATIN SMALL LETTER R -->
+ <td>&#x0073;x <!-- U+0073: LATIN SMALL LETTER S -->
+ <td>&#x0074;x <!-- U+0074: LATIN SMALL LETTER T -->
+ <td>&#x0075;x <!-- U+0075: LATIN SMALL LETTER U -->
+ <tr>
+ <td>&#x0076;x <!-- U+0076: LATIN SMALL LETTER V -->
+ <td>&#x0077;x <!-- U+0077: LATIN SMALL LETTER W -->
+ <td>&#x0078;x <!-- U+0078: LATIN SMALL LETTER X -->
+ <td>&#x0079;x <!-- U+0079: LATIN SMALL LETTER Y -->
+ <td>&#x007A;x <!-- U+007A: LATIN SMALL LETTER Z -->
+ <td>&#x007B;x <!-- U+007B: LEFT CURLY BRACKET -->
+ <td>&#x007C;x <!-- U+007C: VERTICAL LINE -->
+ <td>&#x007D;x <!-- U+007D: RIGHT CURLY BRACKET -->
+ <td>&#x007E;x <!-- U+007E: TILDE -->
+ <td>&#x00A0;x <!-- U+00A0: NO-BREAK SPACE -->
+ <td>&#x00A1;x <!-- U+00A1: INVERTED EXCLAMATION MARK -->
+ <td>&#x00A2;x <!-- U+00A2: CENT SIGN -->
+ <td>&#x00A3;x <!-- U+00A3: POUND SIGN -->
+ <td>&#x00A4;x <!-- U+00A4: CURRENCY SIGN -->
+ <td>&#x00A5;x <!-- U+00A5: YEN SIGN -->
+ <td>&#x00A6;x <!-- U+00A6: BROKEN BAR -->
+ <td>&#x00A7;x <!-- U+00A7: SECTION SIGN -->
+ <tr>
+ <td>&#x00A8;x <!-- U+00A8: DIAERESIS -->
+ <td>&#x00A9;x <!-- U+00A9: COPYRIGHT SIGN -->
+ <td>&#x00AA;x <!-- U+00AA: FEMININE ORDINAL INDICATOR -->
+ <td>&#x00AB;x <!-- U+00AB: LEFT-POINTING DOUBLE ANGLE QUOTATION MARK -->
+ <td>&#x00AC;x <!-- U+00AC: NOT SIGN -->
+ <td>&#x00AD;x <!-- U+00AD: SOFT HYPHEN -->
+ <td>&#x00AE;x <!-- U+00AE: REGISTERED SIGN -->
+ <td>&#x00AF;x <!-- U+00AF: MACRON -->
+ <td>&#x00B0;x <!-- U+00B0: DEGREE SIGN -->
+ <td>&#x00B1;x <!-- U+00B1: PLUS-MINUS SIGN -->
+ <td>&#x00B2;x <!-- U+00B2: SUPERSCRIPT TWO -->
+ <td>&#x00B3;x <!-- U+00B3: SUPERSCRIPT THREE -->
+ <td>&#x00B4;x <!-- U+00B4: ACUTE ACCENT -->
+ <td>&#x00B5;x <!-- U+00B5: MICRO SIGN -->
+ <td>&#x00B6;x <!-- U+00B6: PILCROW SIGN -->
+ <td>&#x00B7;x <!-- U+00B7: MIDDLE DOT -->
+ <td>&#x00B8;x <!-- U+00B8: CEDILLA -->
+ <tr>
+ <td>&#x00B9;x <!-- U+00B9: SUPERSCRIPT ONE -->
+ <td>&#x00BA;x <!-- U+00BA: MASCULINE ORDINAL INDICATOR -->
+ <td>&#x00BB;x <!-- U+00BB: RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK -->
+ <td>&#x00BC;x <!-- U+00BC: VULGAR FRACTION ONE QUARTER -->
+ <td>&#x00BD;x <!-- U+00BD: VULGAR FRACTION ONE HALF -->
+ <td>&#x00BE;x <!-- U+00BE: VULGAR FRACTION THREE QUARTERS -->
+ <td>&#x00BF;x <!-- U+00BF: INVERTED QUESTION MARK -->
+ <td>&#x00C0;x <!-- U+00C0: LATIN CAPITAL LETTER A WITH GRAVE -->
+ <td>&#x00C1;x <!-- U+00C1: LATIN CAPITAL LETTER A WITH ACUTE -->
+ <td>&#x00C2;x <!-- U+00C2: LATIN CAPITAL LETTER A WITH CIRCUMFLEX -->
+ <td>&#x00C3;x <!-- U+00C3: LATIN CAPITAL LETTER A WITH TILDE -->
+ <td>&#x00C4;x <!-- U+00C4: LATIN CAPITAL LETTER A WITH DIAERESIS -->
+ <td>&#x00C5;x <!-- U+00C5: LATIN CAPITAL LETTER A WITH RING ABOVE -->
+ <td>&#x00C6;x <!-- U+00C6: LATIN CAPITAL LETTER AE -->
+ <td>&#x00C7;x <!-- U+00C7: LATIN CAPITAL LETTER C WITH CEDILLA -->
+ <td>&#x00C8;x <!-- U+00C8: LATIN CAPITAL LETTER E WITH GRAVE -->
+ <td>&#x00C9;x <!-- U+00C9: LATIN CAPITAL LETTER E WITH ACUTE -->
+ <tr>
+ <td>&#x00CA;x <!-- U+00CA: LATIN CAPITAL LETTER E WITH CIRCUMFLEX -->
+ <td>&#x00CB;x <!-- U+00CB: LATIN CAPITAL LETTER E WITH DIAERESIS -->
+ <td>&#x00CC;x <!-- U+00CC: LATIN CAPITAL LETTER I WITH GRAVE -->
+ <td>&#x00CD;x <!-- U+00CD: LATIN CAPITAL LETTER I WITH ACUTE -->
+ <td>&#x00CE;x <!-- U+00CE: LATIN CAPITAL LETTER I WITH CIRCUMFLEX -->
+ <td>&#x00CF;x <!-- U+00CF: LATIN CAPITAL LETTER I WITH DIAERESIS -->
+ <td>&#x00D0;x <!-- U+00D0: LATIN CAPITAL LETTER ETH -->
+ <td>&#x00D1;x <!-- U+00D1: LATIN CAPITAL LETTER N WITH TILDE -->
+ <td>&#x00D2;x <!-- U+00D2: LATIN CAPITAL LETTER O WITH GRAVE -->
+ <td>&#x00D3;x <!-- U+00D3: LATIN CAPITAL LETTER O WITH ACUTE -->
+ <td>&#x00D4;x <!-- U+00D4: LATIN CAPITAL LETTER O WITH CIRCUMFLEX -->
+ <td>&#x00D5;x <!-- U+00D5: LATIN CAPITAL LETTER O WITH TILDE -->
+ <td>&#x00D6;x <!-- U+00D6: LATIN CAPITAL LETTER O WITH DIAERESIS -->
+ <td>&#x00D7;x <!-- U+00D7: MULTIPLICATION SIGN -->
+ <td>&#x00D8;x <!-- U+00D8: LATIN CAPITAL LETTER O WITH STROKE -->
+ <td>&#x00D9;x <!-- U+00D9: LATIN CAPITAL LETTER U WITH GRAVE -->
+ <td>&#x00DA;x <!-- U+00DA: LATIN CAPITAL LETTER U WITH ACUTE -->
+ <tr>
+ <td>&#x00DB;x <!-- U+00DB: LATIN CAPITAL LETTER U WITH CIRCUMFLEX -->
+ <td>&#x00DC;x <!-- U+00DC: LATIN CAPITAL LETTER U WITH DIAERESIS -->
+ <td>&#x00DD;x <!-- U+00DD: LATIN CAPITAL LETTER Y WITH ACUTE -->
+ <td>&#x00DE;x <!-- U+00DE: LATIN CAPITAL LETTER THORN -->
+ <td>&#x00DF;x <!-- U+00DF: LATIN SMALL LETTER SHARP S -->
+ <td>&#x00E0;x <!-- U+00E0: LATIN SMALL LETTER A WITH GRAVE -->
+ <td>&#x00E1;x <!-- U+00E1: LATIN SMALL LETTER A WITH ACUTE -->
+ <td>&#x00E2;x <!-- U+00E2: LATIN SMALL LETTER A WITH CIRCUMFLEX -->
+ <td>&#x00E3;x <!-- U+00E3: LATIN SMALL LETTER A WITH TILDE -->
+ <td>&#x00E4;x <!-- U+00E4: LATIN SMALL LETTER A WITH DIAERESIS -->
+ <td>&#x00E5;x <!-- U+00E5: LATIN SMALL LETTER A WITH RING ABOVE -->
+ <td>&#x00E6;x <!-- U+00E6: LATIN SMALL LETTER AE -->
+ <td>&#x00E7;x <!-- U+00E7: LATIN SMALL LETTER C WITH CEDILLA -->
+ <td>&#x00E8;x <!-- U+00E8: LATIN SMALL LETTER E WITH GRAVE -->
+ <td>&#x00E9;x <!-- U+00E9: LATIN SMALL LETTER E WITH ACUTE -->
+ <td>&#x00EA;x <!-- U+00EA: LATIN SMALL LETTER E WITH CIRCUMFLEX -->
+ <td>&#x00EB;x <!-- U+00EB: LATIN SMALL LETTER E WITH DIAERESIS -->
+ <tr>
+ <td>&#x00EC;x <!-- U+00EC: LATIN SMALL LETTER I WITH GRAVE -->
+ <td>&#x00ED;x <!-- U+00ED: LATIN SMALL LETTER I WITH ACUTE -->
+ <td>&#x00EE;x <!-- U+00EE: LATIN SMALL LETTER I WITH CIRCUMFLEX -->
+ <td>&#x00EF;x <!-- U+00EF: LATIN SMALL LETTER I WITH DIAERESIS -->
+ <td>&#x00F0;x <!-- U+00F0: LATIN SMALL LETTER ETH -->
+ <td>&#x00F1;x <!-- U+00F1: LATIN SMALL LETTER N WITH TILDE -->
+ <td>&#x00F2;x <!-- U+00F2: LATIN SMALL LETTER O WITH GRAVE -->
+ <td>&#x00F3;x <!-- U+00F3: LATIN SMALL LETTER O WITH ACUTE -->
+ <td>&#x00F4;x <!-- U+00F4: LATIN SMALL LETTER O WITH CIRCUMFLEX -->
+ <td>&#x00F5;x <!-- U+00F5: LATIN SMALL LETTER O WITH TILDE -->
+ <td>&#x00F6;x <!-- U+00F6: LATIN SMALL LETTER O WITH DIAERESIS -->
+ <td>&#x00F7;x <!-- U+00F7: DIVISION SIGN -->
+ <td>&#x00F8;x <!-- U+00F8: LATIN SMALL LETTER O WITH STROKE -->
+ <td>&#x00F9;x <!-- U+00F9: LATIN SMALL LETTER U WITH GRAVE -->
+ <td>&#x00FA;x <!-- U+00FA: LATIN SMALL LETTER U WITH ACUTE -->
+ <td>&#x00FB;x <!-- U+00FB: LATIN SMALL LETTER U WITH CIRCUMFLEX -->
+ <td>&#x00FC;x <!-- U+00FC: LATIN SMALL LETTER U WITH DIAERESIS -->
+ <tr>
+ <td>&#x00FD;x <!-- U+00FD: LATIN SMALL LETTER Y WITH ACUTE -->
+ <td>&#x00FE;x <!-- U+00FE: LATIN SMALL LETTER THORN -->
+ <td>&#x00FF;x <!-- U+00FF: LATIN SMALL LETTER Y WITH DIAERESIS -->
+ <td>&#x0131;x <!-- U+0131: LATIN SMALL LETTER DOTLESS I -->
+ <td>&#x0152;x <!-- U+0152: LATIN CAPITAL LIGATURE OE -->
+ <td>&#x0153;x <!-- U+0153: LATIN SMALL LIGATURE OE -->
+ <td>&#x0178;x <!-- U+0178: LATIN CAPITAL LETTER Y WITH DIAERESIS -->
+ <td>&#x0192;x <!-- U+0192: LATIN SMALL LETTER F WITH HOOK -->
+ <td>&#x02C6;x <!-- U+02C6: MODIFIER LETTER CIRCUMFLEX ACCENT -->
+ <td>&#x02C7;x <!-- U+02C7: CARON -->
+ <td>&#x02C9;x <!-- U+02C9: MODIFIER LETTER MACRON -->
+ <td>&#x02D8;x <!-- U+02D8: BREVE -->
+ <td>&#x02D9;x <!-- U+02D9: DOT ABOVE -->
+ <td>&#x02DA;x <!-- U+02DA: RING ABOVE -->
+ <td>&#x02DB;x <!-- U+02DB: OGONEK -->
+ <td>&#x02DC;x <!-- U+02DC: SMALL TILDE -->
+ <td>&#x02DD;x <!-- U+02DD: DOUBLE ACUTE ACCENT -->
+ <tr>
+ <td>&#x0394;x <!-- U+0394: GREEK CAPITAL LETTER DELTA -->
+ <td>&#x03A5;x <!-- U+03A5: GREEK CAPITAL LETTER UPSILON -->
+ <td>&#x03A7;x <!-- U+03A7: GREEK CAPITAL LETTER CHI -->
+ <td>&#x03A9;x <!-- U+03A9: GREEK CAPITAL LETTER OMEGA -->
+ <td>&#x03BC;x <!-- U+03BC: GREEK SMALL LETTER MU -->
+ <td>&#x03C0;x <!-- U+03C0: GREEK SMALL LETTER PI -->
+ <td>&#x2002;x <!-- U+2002: EN SPACE -->
+ <td>&#x2003;x <!-- U+2003: EM SPACE -->
+ <td>&#x2004;x <!-- U+2004: THREE-PER-EM SPACE -->
+ <td>&#x2005;x <!-- U+2005: FOUR-PER-EM SPACE -->
+ <td>&#x2006;x <!-- U+2006: SIX-PER-EM SPACE -->
+ <td>&#x2009;x <!-- U+2009: THIN SPACE -->
+ <td>&#x200A;x <!-- U+200A: HAIR SPACE -->
+ <td>&#x200B;x <!-- U+200B: ZERO WIDTH SPACE -->
+ <td>&#x200C;x <!-- U+200C: ZERO WIDTH NON-JOINER -->
+ <td>&#x200D;x <!-- U+200D: ZERO WIDTH JOINER -->
+ <td>&#x2010;x <!-- U+2010: HYPHEN -->
+ <tr>
+ <td>&#x2013;x <!-- U+2013: EN DASH -->
+ <td>&#x2014;x <!-- U+2014: EM DASH -->
+ <td>&#x2018;x <!-- U+2018: LEFT SINGLE QUOTATION MARK -->
+ <td>&#x2019;x <!-- U+2019: RIGHT SINGLE QUOTATION MARK -->
+ <td>&#x201A;x <!-- U+201A: SINGLE LOW-9 QUOTATION MARK -->
+ <td>&#x201C;x <!-- U+201C: LEFT DOUBLE QUOTATION MARK -->
+ <td>&#x201D;x <!-- U+201D: RIGHT DOUBLE QUOTATION MARK -->
+ <td>&#x201E;x <!-- U+201E: DOUBLE LOW-9 QUOTATION MARK -->
+ <td>&#x2020;x <!-- U+2020: DAGGER -->
+ <td>&#x2021;x <!-- U+2021: DOUBLE DAGGER -->
+ <td>&#x2022;x <!-- U+2022: BULLET -->
+ <td>&#x2026;x <!-- U+2026: HORIZONTAL ELLIPSIS -->
+ <td>&#x2030;x <!-- U+2030: PER MILLE SIGN -->
+ <td>&#x2039;x <!-- U+2039: SINGLE LEFT-POINTING ANGLE QUOTATION MARK -->
+ <td>&#x203A;x <!-- U+203A: SINGLE RIGHT-POINTING ANGLE QUOTATION MARK -->
+ <td>&#x2044;x <!-- U+2044: FRACTION SLASH -->
+ <td>&#x2122;x <!-- U+2122: TRADE MARK SIGN -->
+ <tr>
+ <td>&#x2126;x <!-- U+2126: OHM SIGN -->
+ <td>&#x2202;x <!-- U+2202: PARTIAL DIFFERENTIAL -->
+ <td>&#x2206;x <!-- U+2206: INCREMENT -->
+ <td>&#x220F;x <!-- U+220F: N-ARY PRODUCT -->
+ <td>&#x2211;x <!-- U+2211: N-ARY SUMMATION -->
+ <td>&#x2212;x <!-- U+2212: MINUS SIGN -->
+ <td>&#x2219;x <!-- U+2219: BULLET OPERATOR -->
+ <td>&#x221A;x <!-- U+221A: SQUARE ROOT -->
+ <td>&#x221E;x <!-- U+221E: INFINITY -->
+ <td>&#x222B;x <!-- U+222B: INTEGRAL -->
+ <td>&#x2248;x <!-- U+2248: ALMOST EQUAL TO -->
+ <td>&#x2260;x <!-- U+2260: NOT EQUAL TO -->
+ <td>&#x2264;x <!-- U+2264: LESS-THAN OR EQUAL TO -->
+ <td>&#x2265;x <!-- U+2265: GREATER-THAN OR EQUAL TO -->
+ <td>&#x22F2;x <!-- U+22F2: ELEMENT OF WITH LONG HORIZONTAL STROKE -->
+ <td>&#x25CA;x <!-- U+25CA: LOZENGE -->
+ <td>&#x3000;x <!-- U+3000: IDEOGRAPHIC SPACE -->
+ <tr>
+ <td>&#x3007;x <!-- U+3007: IDEOGRAPHIC NUMBER ZERO -->
+ <td>&#x4E00;x <!-- U+4E00: CJK UNIFIED IDEOGRAPH-4E00 -->
+ <td>&#x4E03;x <!-- U+4E03: CJK UNIFIED IDEOGRAPH-4E03 -->
+ <td>&#x4E09;x <!-- U+4E09: CJK UNIFIED IDEOGRAPH-4E09 -->
+ <td>&#x4E5D;x <!-- U+4E5D: CJK UNIFIED IDEOGRAPH-4E5D -->
+ <td>&#x4E8C;x <!-- U+4E8C: CJK UNIFIED IDEOGRAPH-4E8C -->
+ <td>&#x4E94;x <!-- U+4E94: CJK UNIFIED IDEOGRAPH-4E94 -->
+ <td>&#x516B;x <!-- U+516B: CJK UNIFIED IDEOGRAPH-516B -->
+ <td>&#x516D;x <!-- U+516D: CJK UNIFIED IDEOGRAPH-516D -->
+ <td>&#x5341;x <!-- U+5341: CJK UNIFIED IDEOGRAPH-5341 -->
+ <td>&#x56D7;x <!-- U+56D7: CJK UNIFIED IDEOGRAPH-56D7 -->
+ <td>&#x56DB;x <!-- U+56DB: CJK UNIFIED IDEOGRAPH-56DB -->
+ <td>&#x571F;x <!-- U+571F: CJK UNIFIED IDEOGRAPH-571F -->
+ <td>&#x6728;x <!-- U+6728: CJK UNIFIED IDEOGRAPH-6728 -->
+ <td>&#x6A2A;x <!-- U+6A2A: CJK UNIFIED IDEOGRAPH-6A2A -->
+ <td>&#x6C34;x <!-- U+6C34: CJK UNIFIED IDEOGRAPH-6C34 -->
+ <td>&#x706B;x <!-- U+706B: CJK UNIFIED IDEOGRAPH-706B -->
+ <tr>
+ <td>&#x7EB5;x <!-- U+7EB5: CJK UNIFIED IDEOGRAPH-7EB5 -->
+ <td>&#x91D1;x <!-- U+91D1: CJK UNIFIED IDEOGRAPH-91D1 -->
+ <td>&#xF000;x <!-- U+F000 -->
+ <td>&#xF001;x <!-- U+F001 -->
+ <td>&#xF002;x <!-- U+F002 -->
+ <td>&#xFEFF;x <!-- U+FEFF: ZERO WIDTH NO-BREAK SPACE -->
+</table>
diff --git a/tests/wpt/web-platform-tests/infrastructure/assumptions/ahem-ref.html b/tests/wpt/web-platform-tests/infrastructure/assumptions/ahem-ref.html
index 971b51c54e4..9116232620f 100644
--- a/tests/wpt/web-platform-tests/infrastructure/assumptions/ahem-ref.html
+++ b/tests/wpt/web-platform-tests/infrastructure/assumptions/ahem-ref.html
@@ -1,27 +1,25 @@
-
<!doctype html>
<title>Ahem checker</title>
+<link rel="mismatch" href="ahem-notref.html">
<style>
-@font-face {
- font-family: Ahem;
- src: url("../../fonts/Ahem.ttf");
-}
* {
padding: 0;
margin: 0;
border: none;
}
-
+td {
+ width: 34px;
+}
+@font-face {
+ font-family: Ahem;
+ src: url("../../fonts/Ahem.ttf");
+}
table {
font: 15px/1 Ahem;
border-collapse: separate;
border-spacing: 1px;
table-layout: fixed;
}
-
-td {
- width: 34px;
-}
</style>
<table>
<tr>
diff --git a/tests/wpt/web-platform-tests/infrastructure/assumptions/ahem.html b/tests/wpt/web-platform-tests/infrastructure/assumptions/ahem.html
index b18cd8e9861..068c1d4dee6 100644
--- a/tests/wpt/web-platform-tests/infrastructure/assumptions/ahem.html
+++ b/tests/wpt/web-platform-tests/infrastructure/assumptions/ahem.html
@@ -1,4 +1,3 @@
-
<!doctype html>
<title>Ahem checker</title>
<link rel="match" href="ahem-ref.html">
@@ -8,17 +7,15 @@
margin: 0;
border: none;
}
-
+td {
+ width: 34px;
+}
table {
font: 15px/1 Ahem;
border-collapse: separate;
border-spacing: 1px;
table-layout: fixed;
}
-
-td {
- width: 34px;
-}
</style>
<table>
<tr>
diff --git a/tests/wpt/web-platform-tests/infrastructure/assumptions/tools/ahem-generate-table.py b/tests/wpt/web-platform-tests/infrastructure/assumptions/tools/ahem-generate-table.py
index d9fb1fbc32d..8790da02e27 100644
--- a/tests/wpt/web-platform-tests/infrastructure/assumptions/tools/ahem-generate-table.py
+++ b/tests/wpt/web-platform-tests/infrastructure/assumptions/tools/ahem-generate-table.py
@@ -30,52 +30,68 @@ chars_sorted = sorted(chars)
per_row = 17
-def build_header(is_test):
- rv = []
-
- rv.append("""
-<!doctype html>
-<title>Ahem checker</title>""")
-
- if is_test:
- rv.append("""
-<link rel="match" href="ahem-ref.html">""")
-
- rv.append("""
-<style>""")
-
- if not is_test:
- rv.append("""
-@font-face {
- font-family: Ahem;
- src: url("../../fonts/Ahem.ttf");
-}""")
-
- rv.append("""
+doctype = "<!doctype html>"
+title = "<title>Ahem checker</title>"
+style_open = """
+<style>
* {
padding: 0;
margin: 0;
border: none;
}
-
+td {
+ width: 34px;
+}""".strip()
+style_close = "</style>"
+style_font_face = """
+@font-face {
+ font-family: Ahem;
+ src: url("../../fonts/Ahem.ttf");
+}""".strip()
+style_table_font_specified = """
table {
font: 15px/1 Ahem;
border-collapse: separate;
border-spacing: 1px;
table-layout: fixed;
-}
+}""".strip()
+style_table_font_unspecified = """
+table {
+ font-size: 15px;
+ line-height: 1;
+ border-collapse: separate;
+ border-spacing: 1px;
+ table-layout: fixed;
+}""".strip()
-td {
- width: 34px;
-}
-</style>
-""")
- return "".join(rv)
+def build_header(is_test, rel, href):
+ rv = [doctype, title]
+
+ if rel != None and href != None:
+ rv.append('<link rel="%s" href="%s">' % (rel, href))
+
+ rv.append(style_open)
+
+ if not is_test:
+ if rel == None and href == None:
+ # ahem-notref.html
+ rv.append(style_table_font_unspecified)
+ else:
+ # ahem-ref.html
+ rv.append(style_font_face)
+ rv.append(style_table_font_specified)
+ else:
+ # ahem.html
+ rv.append(style_table_font_specified)
+
+ rv.append(style_close)
+
+ return "\n".join(rv)
def build_table():
- rv = []
+ rv = ["\n"]
rv.append("<table>\n")
for row in grouper(per_row, chars_sorted):
@@ -93,10 +109,21 @@ def build_table():
return "".join(rv)
-with open("../ahem.html", "w") as f1:
- f1.write(build_header(True))
- f1.write(build_table())
+cases = [
+ # file, is_test, rel
+ ("../ahem.html", True, "match"),
+ ("../ahem-ref.html", False, "mismatch"),
+ ("../ahem-notref.html", False, None),
+]
+
+table = build_table()
+
+for index, case in enumerate(cases):
+ next_index = index + 1
+ file, is_test, rel = case
+ href = cases[next_index][0][3:] if next_index < len(cases) else None
+ header = build_header(is_test, rel, href)
+
+ with open(file, "w") as file:
+ file.write("%s%s" % (header, table))
-with open("../ahem-ref.html", "w") as f1:
- f1.write(build_header(False))
- f1.write(build_table())
diff --git a/tests/wpt/web-platform-tests/interfaces/dom.idl b/tests/wpt/web-platform-tests/interfaces/dom.idl
index fce74328043..25324787d71 100644
--- a/tests/wpt/web-platform-tests/interfaces/dom.idl
+++ b/tests/wpt/web-platform-tests/interfaces/dom.idl
@@ -79,26 +79,20 @@ interface AbortSignal : EventTarget {
};
-[NoInterfaceObject,
- Exposed=Window]
-interface NonElementParentNode {
+interface mixin NonElementParentNode {
Element? getElementById(DOMString elementId);
};
-Document implements NonElementParentNode;
-DocumentFragment implements NonElementParentNode;
+Document includes NonElementParentNode;
+DocumentFragment includes NonElementParentNode;
-[NoInterfaceObject,
- Exposed=Window]
-interface DocumentOrShadowRoot {
+interface mixin DocumentOrShadowRoot {
};
-Document implements DocumentOrShadowRoot;
-ShadowRoot implements DocumentOrShadowRoot;
+Document includes DocumentOrShadowRoot;
+ShadowRoot includes DocumentOrShadowRoot;
-[NoInterfaceObject,
- Exposed=Window]
-interface ParentNode {
+interface mixin ParentNode {
[SameObject] readonly attribute HTMLCollection children;
readonly attribute Element? firstElementChild;
readonly attribute Element? lastElementChild;
@@ -110,41 +104,35 @@ interface ParentNode {
Element? querySelector(DOMString selectors);
[NewObject] NodeList querySelectorAll(DOMString selectors);
};
-Document implements ParentNode;
-DocumentFragment implements ParentNode;
-Element implements ParentNode;
+Document includes ParentNode;
+DocumentFragment includes ParentNode;
+Element includes ParentNode;
-[NoInterfaceObject,
- Exposed=Window]
-interface NonDocumentTypeChildNode {
+interface mixin NonDocumentTypeChildNode {
readonly attribute Element? previousElementSibling;
readonly attribute Element? nextElementSibling;
};
-Element implements NonDocumentTypeChildNode;
-CharacterData implements NonDocumentTypeChildNode;
+Element includes NonDocumentTypeChildNode;
+CharacterData includes NonDocumentTypeChildNode;
-[NoInterfaceObject,
- Exposed=Window]
-interface ChildNode {
+interface mixin ChildNode {
[Unscopable] void before((Node or DOMString)... nodes);
[Unscopable] void after((Node or DOMString)... nodes);
[Unscopable] void replaceWith((Node or DOMString)... nodes);
[Unscopable] void remove();
};
-DocumentType implements ChildNode;
-Element implements ChildNode;
-CharacterData implements ChildNode;
+DocumentType includes ChildNode;
+Element includes ChildNode;
+CharacterData includes ChildNode;
-[NoInterfaceObject,
- Exposed=Window]
-interface Slotable {
+interface mixin Slotable {
readonly attribute HTMLSlotElement? assignedSlot;
};
-Element implements Slotable;
-Text implements Slotable;
+Element includes Slotable;
+Text includes Slotable;
[Exposed=Window]
diff --git a/tests/wpt/web-platform-tests/interfaces/geolocation-sensor.idl b/tests/wpt/web-platform-tests/interfaces/geolocation-sensor.idl
index 7c2e247e46d..81891551e50 100644
--- a/tests/wpt/web-platform-tests/interfaces/geolocation-sensor.idl
+++ b/tests/wpt/web-platform-tests/interfaces/geolocation-sensor.idl
@@ -1,4 +1,4 @@
-[Constructor(optional SensorOptions options), Exposed=Window]
+[Constructor(optional SensorOptions options), SecureContext, Exposed=Window]
interface GeolocationSensor : Sensor {
readonly attribute unrestricted double? latitude;
readonly attribute unrestricted double? longitude;
diff --git a/tests/wpt/web-platform-tests/interfaces/hr-time.idl b/tests/wpt/web-platform-tests/interfaces/hr-time.idl
new file mode 100644
index 00000000000..ccbbc332326
--- /dev/null
+++ b/tests/wpt/web-platform-tests/interfaces/hr-time.idl
@@ -0,0 +1,13 @@
+typedef double DOMHighResTimeStamp;
+
+[Exposed=(Window,Worker)]
+interface Performance : EventTarget {
+ DOMHighResTimeStamp now();
+ readonly attribute DOMHighResTimeStamp timeOrigin;
+ [Default] object toJSON();
+};
+
+partial interface WindowOrWorkerGlobalScope {
+ [Replaceable]
+ readonly attribute Performance performance;
+};
diff --git a/tests/wpt/web-platform-tests/interfaces/html.idl b/tests/wpt/web-platform-tests/interfaces/html.idl
index a8693340e9a..e272fb823bc 100644
--- a/tests/wpt/web-platform-tests/interfaces/html.idl
+++ b/tests/wpt/web-platform-tests/interfaces/html.idl
@@ -4,7 +4,9 @@ interface HTMLAllCollection {
readonly attribute unsigned long length;
getter Element? (unsigned long index);
getter (HTMLCollection or Element)? namedItem(DOMString name);
- legacycaller (HTMLCollection or Element)? item(optional DOMString nameOrIndex);
+ (HTMLCollection or Element)? item(optional DOMString nameOrIndex);
+
+ // Note: HTMLAllCollection objects have a custom [[Call]] internal method and an [[IsHTMLDDA]] internal slot.
};
[Exposed=Window]
@@ -84,8 +86,8 @@ partial interface Document {
// special event handler IDL attributes that only apply to Document objects
[LenientThis] attribute EventHandler onreadystatechange;
};
-Document implements GlobalEventHandlers;
-Document implements DocumentAndElementEventHandlers;
+Document includes GlobalEventHandlers;
+Document includes DocumentAndElementEventHandlers;
[Exposed=Window,
HTMLConstructor]
@@ -115,9 +117,9 @@ dictionary FocusOptions {
boolean preventScroll = false;
};
-HTMLElement implements GlobalEventHandlers;
-HTMLElement implements DocumentAndElementEventHandlers;
-HTMLElement implements ElementContentEditable;
+HTMLElement includes GlobalEventHandlers;
+HTMLElement includes DocumentAndElementEventHandlers;
+HTMLElement includes ElementContentEditable;
// Note: intentionally not [HTMLConstructor]
interface HTMLUnknownElement : HTMLElement { };
@@ -168,13 +170,12 @@ interface HTMLLinkElement : HTMLElement {
[CEReactions] attribute DOMString type;
[SameObject, PutForwards=value] readonly attribute DOMTokenList sizes;
[CEReactions] attribute DOMString referrerPolicy;
- [CEReactions] attribute USVString scope;
[CEReactions] attribute DOMString workerType;
[CEReactions] attribute DOMString updateViaCache;
// also has obsolete members
};
-HTMLLinkElement implements LinkStyle;
+HTMLLinkElement includes LinkStyle;
[Exposed=Window,
HTMLConstructor]
@@ -193,7 +194,7 @@ interface HTMLStyleElement : HTMLElement {
[CEReactions] attribute DOMString nonce;
[CEReactions] attribute DOMString type;
};
-HTMLStyleElement implements LinkStyle;
+HTMLStyleElement includes LinkStyle;
[Exposed=Window,
HTMLConstructor]
@@ -201,7 +202,7 @@ interface HTMLBodyElement : HTMLElement {
// also has obsolete members
};
-HTMLBodyElement implements WindowEventHandlers;
+HTMLBodyElement includes WindowEventHandlers;
[Exposed=Window,
HTMLConstructor]
@@ -293,7 +294,7 @@ interface HTMLAnchorElement : HTMLElement {
// also has obsolete members
};
-HTMLAnchorElement implements HTMLHyperlinkElementUtils;
+HTMLAnchorElement includes HTMLHyperlinkElementUtils;
[Exposed=Window,
HTMLConstructor]
@@ -317,9 +318,7 @@ interface HTMLBRElement : HTMLElement {
// also has obsolete members
};
-[Exposed=Window,
- NoInterfaceObject]
-interface HTMLHyperlinkElementUtils {
+interface mixin HTMLHyperlinkElementUtils {
[CEReactions] stringifier attribute USVString href;
readonly attribute USVString origin;
[CEReactions] attribute USVString protocol;
@@ -686,7 +685,7 @@ interface HTMLAreaElement : HTMLElement {
// also has obsolete members
};
-HTMLAreaElement implements HTMLHyperlinkElementUtils;
+HTMLAreaElement includes HTMLHyperlinkElementUtils;
[Exposed=Window,
HTMLConstructor]
@@ -817,7 +816,6 @@ interface HTMLInputElement : HTMLElement {
[CEReactions] attribute DOMString formTarget;
[CEReactions] attribute unsigned long height;
attribute boolean indeterminate;
- [CEReactions] attribute DOMString inputMode;
readonly attribute HTMLElement? list;
[CEReactions] attribute DOMString max;
[CEReactions] attribute long maxLength;
@@ -961,7 +959,6 @@ interface HTMLTextAreaElement : HTMLElement {
[CEReactions] attribute DOMString dirName;
[CEReactions] attribute boolean disabled;
readonly attribute HTMLFormElement? form;
- [CEReactions] attribute DOMString inputMode;
[CEReactions] attribute long maxLength;
[CEReactions] attribute long minLength;
[CEReactions] attribute DOMString name;
@@ -1129,6 +1126,7 @@ interface HTMLTemplateElement : HTMLElement {
interface HTMLSlotElement : HTMLElement {
[CEReactions] attribute DOMString name;
sequence<Node> assignedNodes(optional AssignedNodesOptions options);
+ sequence<Element> assignedElements(optional AssignedNodesOptions options);
};
dictionary AssignedNodesOptions {
@@ -1174,32 +1172,30 @@ interface CanvasRenderingContext2D {
// back-reference to the canvas
readonly attribute HTMLCanvasElement canvas;
};
-CanvasRenderingContext2D implements CanvasState;
-CanvasRenderingContext2D implements CanvasTransform;
-CanvasRenderingContext2D implements CanvasCompositing;
-CanvasRenderingContext2D implements CanvasImageSmoothing;
-CanvasRenderingContext2D implements CanvasFillStrokeStyles;
-CanvasRenderingContext2D implements CanvasShadowStyles;
-CanvasRenderingContext2D implements CanvasFilters;
-CanvasRenderingContext2D implements CanvasRect;
-CanvasRenderingContext2D implements CanvasDrawPath;
-CanvasRenderingContext2D implements CanvasUserInterface;
-CanvasRenderingContext2D implements CanvasText;
-CanvasRenderingContext2D implements CanvasDrawImage;
-CanvasRenderingContext2D implements CanvasImageData;
-CanvasRenderingContext2D implements CanvasPathDrawingStyles;
-CanvasRenderingContext2D implements CanvasTextDrawingStyles;
-CanvasRenderingContext2D implements CanvasPath;
-
-[NoInterfaceObject, Exposed=(Window,Worker)]
-interface CanvasState {
+CanvasRenderingContext2D includes CanvasState;
+CanvasRenderingContext2D includes CanvasTransform;
+CanvasRenderingContext2D includes CanvasCompositing;
+CanvasRenderingContext2D includes CanvasImageSmoothing;
+CanvasRenderingContext2D includes CanvasFillStrokeStyles;
+CanvasRenderingContext2D includes CanvasShadowStyles;
+CanvasRenderingContext2D includes CanvasFilters;
+CanvasRenderingContext2D includes CanvasRect;
+CanvasRenderingContext2D includes CanvasDrawPath;
+CanvasRenderingContext2D includes CanvasUserInterface;
+CanvasRenderingContext2D includes CanvasText;
+CanvasRenderingContext2D includes CanvasDrawImage;
+CanvasRenderingContext2D includes CanvasImageData;
+CanvasRenderingContext2D includes CanvasPathDrawingStyles;
+CanvasRenderingContext2D includes CanvasTextDrawingStyles;
+CanvasRenderingContext2D includes CanvasPath;
+
+interface mixin CanvasState {
// state
void save(); // push state on state stack
void restore(); // pop state stack and restore state
};
-[NoInterfaceObject, Exposed=(Window,Worker)]
-interface CanvasTransform {
+interface mixin CanvasTransform {
// transformations (default transform is the identity matrix)
void scale(unrestricted double x, unrestricted double y);
void rotate(unrestricted double angle);
@@ -1210,37 +1206,30 @@ interface CanvasTransform {
void setTransform(unrestricted double a, unrestricted double b, unrestricted double c, unrestricted double d, unrestricted double e, unrestricted double f);
void setTransform(optional DOMMatrix2DInit transform);
void resetTransform();
-
};
-[NoInterfaceObject, Exposed=(Window,Worker)]
-interface CanvasCompositing {
+interface mixin CanvasCompositing {
// compositing
attribute unrestricted double globalAlpha; // (default 1.0)
attribute DOMString globalCompositeOperation; // (default source-over)
};
-[NoInterfaceObject, Exposed=(Window,Worker)]
-interface CanvasImageSmoothing {
+interface mixin CanvasImageSmoothing {
// image smoothing
attribute boolean imageSmoothingEnabled; // (default true)
attribute ImageSmoothingQuality imageSmoothingQuality; // (default low)
-
};
-[NoInterfaceObject, Exposed=(Window,Worker)]
-interface CanvasFillStrokeStyles {
+interface mixin CanvasFillStrokeStyles {
// colors and styles (see also the CanvasPathDrawingStyles and CanvasTextDrawingStyles interfaces)
attribute (DOMString or CanvasGradient or CanvasPattern) strokeStyle; // (default black)
attribute (DOMString or CanvasGradient or CanvasPattern) fillStyle; // (default black)
CanvasGradient createLinearGradient(double x0, double y0, double x1, double y1);
CanvasGradient createRadialGradient(double x0, double y0, double r0, double x1, double y1, double r1);
CanvasPattern? createPattern(CanvasImageSource image, [TreatNullAs=EmptyString] DOMString repetition);
-
};
-[NoInterfaceObject, Exposed=(Window,Worker)]
-interface CanvasShadowStyles {
+interface mixin CanvasShadowStyles {
// shadows
attribute unrestricted double shadowOffsetX; // (default 0)
attribute unrestricted double shadowOffsetY; // (default 0)
@@ -1248,22 +1237,19 @@ interface CanvasShadowStyles {
attribute DOMString shadowColor; // (default transparent black)
};
-[NoInterfaceObject, Exposed=(Window,Worker)]
-interface CanvasFilters {
+interface mixin CanvasFilters {
// filters
attribute DOMString filter; // (default "none")
};
-[NoInterfaceObject, Exposed=(Window,Worker)]
-interface CanvasRect {
+interface mixin CanvasRect {
// rects
void clearRect(unrestricted double x, unrestricted double y, unrestricted double w, unrestricted double h);
void fillRect(unrestricted double x, unrestricted double y, unrestricted double w, unrestricted double h);
void strokeRect(unrestricted double x, unrestricted double y, unrestricted double w, unrestricted double h);
};
-[NoInterfaceObject, Exposed=(Window,Worker)]
-interface CanvasDrawPath {
+interface mixin CanvasDrawPath {
// path API (see also CanvasPath)
void beginPath();
void fill(optional CanvasFillRule fillRule = "nonzero");
@@ -1279,34 +1265,28 @@ interface CanvasDrawPath {
boolean isPointInStroke(Path2D path, unrestricted double x, unrestricted double y);
};
-[Exposed=Window,
- NoInterfaceObject]
-interface CanvasUserInterface {
+interface mixin CanvasUserInterface {
void drawFocusIfNeeded(Element element);
void drawFocusIfNeeded(Path2D path, Element element);
void scrollPathIntoView();
void scrollPathIntoView(Path2D path);
};
-[Exposed=Window,
- NoInterfaceObject]
-interface CanvasText {
+interface mixin CanvasText {
// text (see also the CanvasPathDrawingStyles and CanvasTextDrawingStyles interfaces)
void fillText(DOMString text, unrestricted double x, unrestricted double y, optional unrestricted double maxWidth);
void strokeText(DOMString text, unrestricted double x, unrestricted double y, optional unrestricted double maxWidth);
TextMetrics measureText(DOMString text);
};
-[NoInterfaceObject, Exposed=(Window,Worker)]
-interface CanvasDrawImage {
+interface mixin CanvasDrawImage {
// drawing images
void drawImage(CanvasImageSource image, unrestricted double dx, unrestricted double dy);
void drawImage(CanvasImageSource image, unrestricted double dx, unrestricted double dy, unrestricted double dw, unrestricted double dh);
void drawImage(CanvasImageSource image, unrestricted double sx, unrestricted double sy, unrestricted double sw, unrestricted double sh, unrestricted double dx, unrestricted double dy, unrestricted double dw, unrestricted double dh);
};
-[NoInterfaceObject, Exposed=(Window,Worker)]
-interface CanvasImageData {
+interface mixin CanvasImageData {
// pixel manipulation
ImageData createImageData(long sw, long sh);
ImageData createImageData(ImageData imagedata);
@@ -1321,8 +1301,7 @@ enum CanvasTextAlign { "start", "end", "left", "right", "center" };
enum CanvasTextBaseline { "top", "hanging", "middle", "alphabetic", "ideographic", "bottom" };
enum CanvasDirection { "ltr", "rtl", "inherit" };
-[NoInterfaceObject, Exposed=(Window,Worker)]
-interface CanvasPathDrawingStyles {
+interface mixin CanvasPathDrawingStyles {
// line caps/joins
attribute unrestricted double lineWidth; // (default 1)
attribute CanvasLineCap lineCap; // (default "butt")
@@ -1335,9 +1314,7 @@ interface CanvasPathDrawingStyles {
attribute unrestricted double lineDashOffset;
};
-[Exposed=Window,
- NoInterfaceObject]
-interface CanvasTextDrawingStyles {
+interface mixin CanvasTextDrawingStyles {
// text
attribute DOMString font; // (default 10px sans-serif)
attribute CanvasTextAlign textAlign; // (default: "start")
@@ -1345,8 +1322,7 @@ interface CanvasTextDrawingStyles {
attribute CanvasDirection direction; // (default: "inherit")
};
-[NoInterfaceObject, Exposed=(Window,Worker)]
-interface CanvasPath {
+interface mixin CanvasPath {
// shared path API methods
void closePath();
void moveTo(unrestricted double x, unrestricted double y);
@@ -1409,7 +1385,7 @@ interface ImageData {
interface Path2D {
void addPath(Path2D path, optional DOMMatrix2DInit transform);
};
-Path2D implements CanvasPath;
+Path2D includes CanvasPath;
[Exposed=Window]
interface ImageBitmapRenderingContext {
@@ -1448,19 +1424,19 @@ interface OffscreenCanvasRenderingContext2D {
readonly attribute OffscreenCanvas canvas;
};
-OffscreenCanvasRenderingContext2D implements CanvasState;
-OffscreenCanvasRenderingContext2D implements CanvasTransform;
-OffscreenCanvasRenderingContext2D implements CanvasCompositing;
-OffscreenCanvasRenderingContext2D implements CanvasImageSmoothing;
-OffscreenCanvasRenderingContext2D implements CanvasFillStrokeStyles;
-OffscreenCanvasRenderingContext2D implements CanvasShadowStyles;
-OffscreenCanvasRenderingContext2D implements CanvasFilters;
-OffscreenCanvasRenderingContext2D implements CanvasRect;
-OffscreenCanvasRenderingContext2D implements CanvasDrawPath;
-OffscreenCanvasRenderingContext2D implements CanvasDrawImage;
-OffscreenCanvasRenderingContext2D implements CanvasImageData;
-OffscreenCanvasRenderingContext2D implements CanvasPathDrawingStyles;
-OffscreenCanvasRenderingContext2D implements CanvasPath;
+OffscreenCanvasRenderingContext2D includes CanvasState;
+OffscreenCanvasRenderingContext2D includes CanvasTransform;
+OffscreenCanvasRenderingContext2D includes CanvasCompositing;
+OffscreenCanvasRenderingContext2D includes CanvasImageSmoothing;
+OffscreenCanvasRenderingContext2D includes CanvasFillStrokeStyles;
+OffscreenCanvasRenderingContext2D includes CanvasShadowStyles;
+OffscreenCanvasRenderingContext2D includes CanvasFilters;
+OffscreenCanvasRenderingContext2D includes CanvasRect;
+OffscreenCanvasRenderingContext2D includes CanvasDrawPath;
+OffscreenCanvasRenderingContext2D includes CanvasDrawImage;
+OffscreenCanvasRenderingContext2D includes CanvasImageData;
+OffscreenCanvasRenderingContext2D includes CanvasPathDrawingStyles;
+OffscreenCanvasRenderingContext2D includes CanvasPath;
[Exposed=Window]
@@ -1474,11 +1450,10 @@ dictionary ElementDefinitionOptions {
DOMString extends;
};
-[Exposed=Window,
- NoInterfaceObject]
-interface ElementContentEditable {
+interface mixin ElementContentEditable {
[CEReactions] attribute DOMString contentEditable;
readonly attribute boolean isContentEditable;
+ [CEReactions] attribute DOMString inputMode;
};
[Exposed=Window,
@@ -1529,7 +1504,9 @@ dictionary DragEventInit : MouseEventInit {
DataTransfer? dataTransfer = null;
};
-[PrimaryGlobal, LegacyUnenumerableNamedProperties]
+[Global=Window,
+ Exposed=Window,
+ LegacyUnenumerableNamedProperties]
interface Window : EventTarget {
// the current browsing context
[Unforgeable] readonly attribute WindowProxy window;
@@ -1583,8 +1560,8 @@ interface Window : EventTarget {
// also has obsolete members
};
-Window implements GlobalEventHandlers;
-Window implements WindowEventHandlers;
+Window includes GlobalEventHandlers;
+Window includes WindowEventHandlers;
callback FrameRequestCallback = void (DOMHighResTimeStamp time);
@@ -1692,8 +1669,7 @@ interface ApplicationCache : EventTarget {
attribute EventHandler onobsolete;
};
-[NoInterfaceObject, Exposed=(Window,Worker)]
-interface NavigatorOnLine {
+interface mixin NavigatorOnLine {
readonly attribute boolean onLine;
};
@@ -1737,9 +1713,7 @@ typedef OnErrorEventHandlerNonNull? OnErrorEventHandler;
callback OnBeforeUnloadEventHandlerNonNull = DOMString? (Event event);
typedef OnBeforeUnloadEventHandlerNonNull? OnBeforeUnloadEventHandler;
-[Exposed=Window,
- NoInterfaceObject]
-interface GlobalEventHandlers {
+interface mixin GlobalEventHandlers {
attribute EventHandler onabort;
attribute EventHandler onauxclick;
attribute EventHandler onblur;
@@ -1804,9 +1778,7 @@ interface GlobalEventHandlers {
attribute EventHandler onwaiting;
};
-[Exposed=Window,
- NoInterfaceObject]
-interface WindowEventHandlers {
+interface mixin WindowEventHandlers {
attribute EventHandler onafterprint;
attribute EventHandler onbeforeprint;
attribute OnBeforeUnloadEventHandler onbeforeunload;
@@ -1825,9 +1797,7 @@ interface WindowEventHandlers {
attribute EventHandler onunload;
};
-[Exposed=Window,
- NoInterfaceObject]
-interface DocumentAndElementEventHandlers {
+interface mixin DocumentAndElementEventHandlers {
attribute EventHandler oncopy;
attribute EventHandler oncut;
attribute EventHandler onpaste;
@@ -1835,8 +1805,7 @@ interface DocumentAndElementEventHandlers {
typedef (DOMString or Function) TimerHandler;
-[NoInterfaceObject, Exposed=(Window,Worker)]
-interface WindowOrWorkerGlobalScope {
+interface mixin WindowOrWorkerGlobalScope {
[Replaceable] readonly attribute USVString origin;
// base64 utility methods
@@ -1853,23 +1822,22 @@ interface WindowOrWorkerGlobalScope {
Promise<ImageBitmap> createImageBitmap(ImageBitmapSource image, optional ImageBitmapOptions options);
Promise<ImageBitmap> createImageBitmap(ImageBitmapSource image, long sx, long sy, long sw, long sh, optional ImageBitmapOptions options);
};
-Window implements WindowOrWorkerGlobalScope;
-WorkerGlobalScope implements WindowOrWorkerGlobalScope;
+Window includes WindowOrWorkerGlobalScope;
+WorkerGlobalScope includes WindowOrWorkerGlobalScope;
[Exposed=Window]
interface Navigator {
// objects implementing this interface also implement the interfaces given below
};
-Navigator implements NavigatorID;
-Navigator implements NavigatorLanguage;
-Navigator implements NavigatorOnLine;
-Navigator implements NavigatorContentUtils;
-Navigator implements NavigatorCookies;
-Navigator implements NavigatorPlugins;
-Navigator implements NavigatorConcurrentHardware;
+Navigator includes NavigatorID;
+Navigator includes NavigatorLanguage;
+Navigator includes NavigatorOnLine;
+Navigator includes NavigatorContentUtils;
+Navigator includes NavigatorCookies;
+Navigator includes NavigatorPlugins;
+Navigator includes NavigatorConcurrentHardware;
-[NoInterfaceObject, Exposed=(Window,Worker)]
-interface NavigatorID {
+interface mixin NavigatorID {
readonly attribute DOMString appCodeName; // constant "Mozilla"
readonly attribute DOMString appName; // constant "Netscape"
readonly attribute DOMString appVersion;
@@ -1888,28 +1856,21 @@ partial interface NavigatorID {
[Exposed=Window] readonly attribute DOMString oscpu;
};
-[NoInterfaceObject, Exposed=(Window,Worker)]
-interface NavigatorLanguage {
+interface mixin NavigatorLanguage {
readonly attribute DOMString language;
readonly attribute FrozenArray<DOMString> languages;
};
-[Exposed=Window,
- NoInterfaceObject]
-interface NavigatorContentUtils {
+interface mixin NavigatorContentUtils {
void registerProtocolHandler(DOMString scheme, USVString url, DOMString title);
void unregisterProtocolHandler(DOMString scheme, USVString url);
};
-[Exposed=Window,
- NoInterfaceObject]
-interface NavigatorCookies {
+interface mixin NavigatorCookies {
readonly attribute boolean cookieEnabled;
};
-[Exposed=Window,
- NoInterfaceObject]
-interface NavigatorPlugins {
+interface mixin NavigatorPlugins {
[SameObject] readonly attribute PluginArray plugins;
[SameObject] readonly attribute MimeTypeArray mimeTypes;
boolean javaEnabled();
@@ -2124,8 +2085,7 @@ interface SharedWorkerGlobalScope : WorkerGlobalScope {
attribute EventHandler onconnect;
};
-[NoInterfaceObject, Exposed=(Window,Worker)]
-interface AbstractWorker {
+interface mixin AbstractWorker {
attribute EventHandler onerror;
};
@@ -2146,26 +2106,25 @@ dictionary WorkerOptions {
enum WorkerType { "classic", "module" };
-Worker implements AbstractWorker;
+Worker includes AbstractWorker;
[Constructor(USVString scriptURL, optional (DOMString or WorkerOptions) options),
Exposed=(Window,Worker)]
interface SharedWorker : EventTarget {
readonly attribute MessagePort port;
};
-SharedWorker implements AbstractWorker;
+SharedWorker includes AbstractWorker;
-[NoInterfaceObject, Exposed=(Window,Worker)]
-interface NavigatorConcurrentHardware {
+interface mixin NavigatorConcurrentHardware {
readonly attribute unsigned long long hardwareConcurrency;
};
[Exposed=Worker]
interface WorkerNavigator {};
-WorkerNavigator implements NavigatorID;
-WorkerNavigator implements NavigatorLanguage;
-WorkerNavigator implements NavigatorOnLine;
-WorkerNavigator implements NavigatorConcurrentHardware;
+WorkerNavigator includes NavigatorID;
+WorkerNavigator includes NavigatorLanguage;
+WorkerNavigator includes NavigatorOnLine;
+WorkerNavigator includes NavigatorConcurrentHardware;
[Exposed=Worker]
interface WorkerLocation {
@@ -2190,19 +2149,15 @@ interface Storage {
void clear();
};
-[Exposed=Window,
- NoInterfaceObject]
-interface WindowSessionStorage {
+interface mixin WindowSessionStorage {
readonly attribute Storage sessionStorage;
};
-Window implements WindowSessionStorage;
+Window includes WindowSessionStorage;
-[Exposed=Window,
- NoInterfaceObject]
-interface WindowLocalStorage {
+interface mixin WindowLocalStorage {
readonly attribute Storage localStorage;
};
-Window implements WindowLocalStorage;
+Window includes WindowLocalStorage;
[Exposed=Window,
Constructor(DOMString type, optional StorageEventInit eventInitDict)]
@@ -2251,7 +2206,7 @@ interface HTMLFrameSetElement : HTMLElement {
[CEReactions] attribute DOMString cols;
[CEReactions] attribute DOMString rows;
};
-HTMLFrameSetElement implements WindowEventHandlers;
+HTMLFrameSetElement includes WindowEventHandlers;
[Exposed=Window,
HTMLConstructor]
diff --git a/tests/wpt/web-platform-tests/interfaces/webrtc-pc.idl b/tests/wpt/web-platform-tests/interfaces/webrtc-pc.idl
index ae20055920b..d33562b642f 100644
--- a/tests/wpt/web-platform-tests/interfaces/webrtc-pc.idl
+++ b/tests/wpt/web-platform-tests/interfaces/webrtc-pc.idl
@@ -507,7 +507,7 @@ partial interface RTCPeerConnection {
interface RTCSctpTransport {
readonly attribute RTCDtlsTransport transport;
- readonly attribute unsigned long maxMessageSize;
+ readonly attribute unrestricted double maxMessageSize;
};
interface RTCDataChannel : EventTarget {
diff --git a/tests/wpt/web-platform-tests/lint.whitelist b/tests/wpt/web-platform-tests/lint.whitelist
index 3af7264598f..66e3a0e578b 100644
--- a/tests/wpt/web-platform-tests/lint.whitelist
+++ b/tests/wpt/web-platform-tests/lint.whitelist
@@ -18,7 +18,6 @@ INDENT TABS: pointerlock/*
INDENT TABS: shadow-dom/*
INDENT TABS: svg/import/*
INDENT TABS: tools/*
-INDENT TABS: touch-events/*
INDENT TABS: web-animations/*
INDENT TABS: webaudio/*
INDENT TABS: webvtt/*
@@ -70,17 +69,20 @@ TRAILING WHITESPACE, INDENT TABS, CR AT EOL: *.wasm
## Documentation ##
-W3C-TEST.ORG:README.md
-W3C-TEST.ORG:*/README.md
-W3C-TEST.ORG:docs/*
+W3C-TEST.ORG: README.md
+W3C-TEST.ORG: */README.md
+W3C-TEST.ORG: docs/*
SET TIMEOUT: docs/*
+WEB-PLATFORM.TEST:README.md
+WEB-PLATFORM.TEST:*/README.md
+WEB-PLATFORM.TEST:docs/*
## Helper scripts ##
-W3C-TEST.ORG:tools/*
-PRINT STATEMENT:tools/*
-W3C-TEST.ORG:*/tools/*
-PRINT STATEMENT:*/tools/*
+W3C-TEST.ORG: tools/*
+PRINT STATEMENT: tools/*
+W3C-TEST.ORG: */tools/*
+PRINT STATEMENT: */tools/*
## Deliberate copies of Ahem ##
# The allowed copy
@@ -92,42 +94,49 @@ AHEM COPY: css/fonts/ahem-extra/AHEM_*.TTF
# https://github.com/w3c/web-platform-tests/issues/7437
AHEM COPY: css/vendor-imports/mozilla/mozilla-central-reftests/*/Ahem.ttf
-### Test exclusions ##
+## Test exclusions ##
-CR AT EOL:WebIDL/valid/idl/documentation-dos.widl
-CR AT EOL:cors/resources/cors-headers.asis
-CR AT EOL:html/semantics/embedded-content/the-canvas-element/size.attributes.parse.whitespace.html
-INDENT TABS:html/semantics/embedded-content/the-canvas-element/size.attributes.parse.whitespace.html
-CR AT EOL:webvtt/parsing/file-parsing/tests/support/newlines.vtt
-PARSE-FAILED:dom/nodes/Document-createElement-namespace-tests/empty.svg
-PARSE-FAILED:dom/nodes/Document-createElement-namespace-tests/empty.xhtml
-PARSE-FAILED:dom/nodes/Document-createElement-namespace-tests/minimal_html.svg
-PARSE-FAILED:dom/nodes/Document-createElement-namespace-tests/minimal_html.xhtml
+# Intentional use of CRLF
+CR AT EOL: WebIDL/valid/idl/documentation-dos.widl
+CR AT EOL: cors/resources/cors-headers.asis
+CR AT EOL: html/form-elements/the-textarea-element/multiline-placeholder-cr.html
+CR AT EOL: html/form-elements/the-textarea-element/multiline-placeholder-crlf.html
+CR AT EOL: html/input/the-placeholder-attribute/multiline-cr.html
+CR AT EOL: html/input/the-placeholder-attribute/multiline-crlf.html
+CR AT EOL: html/semantics/embedded-content/the-canvas-element/size.attributes.parse.whitespace.html
+CR AT EOL: webvtt/parsing/file-parsing/tests/support/newlines.vtt
+
+# Intentional use of tabs
+INDENT TABS: html/semantics/embedded-content/the-canvas-element/size.attributes.parse.whitespace.html
# Test generation files containing print statements
-PRINT STATEMENT:dom/nodes/Document-createElement-namespace-tests/generate.py
-PRINT STATEMENT:encrypted-media/polyfill/make-polyfill-tests.py
+PRINT STATEMENT: dom/nodes/Document-createElement-namespace-tests/generate.py
+PRINT STATEMENT: encrypted-media/polyfill/make-polyfill-tests.py
# semi-legitimate use of console.*
-CONSOLE:console/*
-CONSOLE:streams/resources/test-utils.js
-CONSOLE:service-workers/service-worker/resources/navigation-redirect-other-origin.html
-CONSOLE:service-workers/service-worker/navigation-redirect.https.html
-CONSOLE:service-workers/service-worker/resources/clients-get-other-origin.html
+CONSOLE: console/*
+CONSOLE: resources/check-layout-th.js
+CONSOLE: resources/chromium/*
+CONSOLE: resources/idlharness.js
+CONSOLE: streams/resources/test-utils.js
+CONSOLE: service-workers/service-worker/resources/navigation-redirect-other-origin.html
+CONSOLE: service-workers/service-worker/navigation-redirect.https.html
+CONSOLE: service-workers/service-worker/resources/clients-get-other-origin.html
# use of console in a public library - annotation-model ensures
# it is not actually used
-CONSOLE:annotation-model/scripts/ajv.min.js
-CONSOLE:annotation-model/scripts/showdown.min.js
+CONSOLE: annotation-model/scripts/ajv.min.js
+CONSOLE: annotation-model/scripts/showdown.min.js
CR AT EOL: annotation-model/scripts/showdown.min.js
-# Lint doesn't know about sub.svg I guess
-PARSE-FAILED:content-security-policy/svg/including.sub.svg
-
-#Helper files that aren't valid XML
-PARSE-FAILED:dom/nodes/Document-createElement-namespace-tests/empty.xml
-PARSE-FAILED:dom/nodes/Document-createElement-namespace-tests/minimal_html.xml
-PARSE-FAILED:acid/acid3/empty.xml
+# Helper files that aren't valid XML
+PARSE-FAILED: acid/acid3/empty.xml
+PARSE-FAILED: dom/nodes/Document-createElement-namespace-tests/empty.svg
+PARSE-FAILED: dom/nodes/Document-createElement-namespace-tests/empty.xhtml
+PARSE-FAILED: dom/nodes/Document-createElement-namespace-tests/empty.xml
+PARSE-FAILED: dom/nodes/Document-createElement-namespace-tests/minimal_html.svg
+PARSE-FAILED: dom/nodes/Document-createElement-namespace-tests/minimal_html.xhtml
+PARSE-FAILED: dom/nodes/Document-createElement-namespace-tests/minimal_html.xml
# setTimeout usage (should probably mostly be fixed)
SET TIMEOUT: *-manual.*
@@ -143,7 +152,6 @@ SET TIMEOUT: css/selectors/selector-placeholder-shown-type-change-002.html
SET TIMEOUT: css/selectors/selector-placeholder-shown-type-change-003.html
SET TIMEOUT: css/selectors/selector-read-write-type-change-002.html
SET TIMEOUT: css/selectors/selector-required-type-change-002.html
-SET TIMEOUT: css/css-fonts/font-display/font-display.html
SET TIMEOUT: encrypted-media/polyfill/chrome-polyfill.js
SET TIMEOUT: encrypted-media/polyfill/clearkey-polyfill.js
SET TIMEOUT: encrypted-media/scripts/playback-temporary-events.js
@@ -155,6 +163,7 @@ SET TIMEOUT: html/browsers/browsing-the-web/scroll-to-fragid/*
SET TIMEOUT: html/browsers/browsing-the-web/unloading-documents/*
SET TIMEOUT: html/browsers/history/the-history-interface/*
SET TIMEOUT: html/browsers/history/the-location-interface/*
+SET TIMEOUT: html/browsers/history/the-session-history-of-browsing-contexts/*
SET TIMEOUT: html/browsers/offline/*
SET TIMEOUT: html/browsers/the-window-object/*
SET TIMEOUT: html/dom/dynamic-markup-insertion/opening-the-input-stream/*
@@ -224,6 +233,10 @@ SET TIMEOUT: workers/*
SET TIMEOUT: XMLHttpRequest/resources/init.htm
SET TIMEOUT: XMLHttpRequest/resources/xmlhttprequest-timeout.js
+# generate_tests implementation and sample usage
+GENERATE_TESTS: resources/test/tests/generate-callback.html
+GENERATE_TESTS: resources/testharness.js
+
# generate_tests usage (should be got rid of)
GENERATE_TESTS: 2dcontext/drawing-images-to-the-canvas/*
GENERATE_TESTS: css/css-shapes/shape-outside/values/*
@@ -294,29 +307,42 @@ GENERATE_TESTS: shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/w
GENERATE_TESTS: shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/window-named-properties-003.html
# Intentional use of setTimeout
-SET TIMEOUT: html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload_form-submission-2.tentative.html
+SET TIMEOUT: css/css-fonts/font-display/font-display.html
+SET TIMEOUT: css/css-fonts/font-display/font-display-change.html
+SET TIMEOUT: css/css-fonts/font-display/font-display-change-ref.html
SET TIMEOUT: html/browsers/windows/auxiliary-browsing-contexts/resources/close-opener.html
SET TIMEOUT: html/dom/documents/dom-tree-accessors/Document.currentScript.html
SET TIMEOUT: html/webappapis/timers/*
+SET TIMEOUT: resources/chromium/*
+SET TIMEOUT: resources/test/tests/add_cleanup.html
+SET TIMEOUT: resources/test/tests/api-tests-1.html
+SET TIMEOUT: resources/test/tests/worker.js
+SET TIMEOUT: resources/testharness.js
# setTimeout use in reftests
SET TIMEOUT: acid/acid3/test.html
# Travis
-W3C-TEST.ORG:.travis.yml
+W3C-TEST.ORG: .travis.yml
+WEB-PLATFORM.TEST: .travis.yml
+
+# Config
+WEB-PLATFORM.TEST: config.default.json
+WEB-PLATFORM.TEST: resources/test/config.test.json
-# Git submodules are not currently scanned
-*:tools/*
-*:resources/*
-*:css/tools/apiclient/*
-*:css/tools/w3ctestlib/*
+# Third party code
+*: css/tools/apiclient/*
+*: css/tools/w3ctestlib/*
+*: resources/webidl2/*
+*: tools/*
# Build system virtualenv
-*:css/tools/_virtualenv/*
+*: css/tools/_virtualenv/*
## Third party data files
TRAILING WHITESPACE: css/css-writing-modes/tools/generators/ucd/Blocks.txt
+TRAILING WHITESPACE: resources/chromium/*
## Test generation files
@@ -447,14 +473,6 @@ CONSOLE: css/cssom/index-002.html
TRAILING WHITESPACE: css/CSS2/generated-content/before-after-positioned-002.html
TRAILING WHITESPACE: css/CSS2/generated-content/before-after-positioned-003.html
TRAILING WHITESPACE: css/CSS2/generated-content/before-after-positioned-004.html
-TRAILING WHITESPACE: css/css-color/lab-004.html
-TRAILING WHITESPACE: css/css-color/lab-005.html
-TRAILING WHITESPACE: css/css-color/lab-006.html
-TRAILING WHITESPACE: css/css-color/lab-007.html
-TRAILING WHITESPACE: css/css-color/lch-004.html
-TRAILING WHITESPACE: css/css-color/lch-005.html
-TRAILING WHITESPACE: css/css-color/lch-006.html
-TRAILING WHITESPACE: css/css-color/lch-007.html
TRAILING WHITESPACE: css/css-fonts/support/fonts/gsubtest-lookup3.ufo/features.fea
TRAILING WHITESPACE: css/css-scoping/css-scoping-shadow-assigned-node-with-before-after.html
TRAILING WHITESPACE: css/css-scoping/css-scoping-shadow-assigned-node-with-rules.html
@@ -925,18 +943,38 @@ MISSING-LINK: css/cssom-view/scrolling-quirks-vs-nonquirks.html
MISSING-LINK: css/cssom-view/scrollingElement.html
MISSING-LINK: css/cssom-view/scrollIntoView-shadow.html
MISSING-LINK: css/cssom-view/scrollIntoView-smooth.html
+MISSING-LINK: css/cssom-view/scrollTop-display-change.html
CSS-COLLIDING-TEST-NAME: css/cssom-view/interfaces.html
CSS-COLLIDING-TEST-NAME: css/cssom/interfaces.html
# TODO https://github.com/w3c/web-platform-tests/issues/5770
MISSING-LINK: css/geometry/*.worker.js
-WEBIDL2.JS:.gitmodules
+WEBIDL2.JS: .gitmodules
# Manual test that uses console.logs for feedback
-CONSOLE:payment-request/payment-request-response-id.html
+CONSOLE: payment-request/payment-request-response-id.html
# Tests that use WebKit/Blink testing APIs
LAYOUTTESTS APIS: css/css-regions/interactivity/*
-# Test that uses the same names as the WebKit/Blink testing APIs
-LAYOUTTESTS APIS: html/browsers/history/the-session-history-of-browsing-contexts/navigation-in-onload_form-submission-2.tentative.html \ No newline at end of file
+
+# Existing use of WEB-PLATFORM.TEST
+WEB-PLATFORM.TEST: clear-site-data/support/test_utils.sub.js
+WEB-PLATFORM.TEST: content-security-policy/base-uri/report-uri-does-not-respect-base-uri.sub.html
+WEB-PLATFORM.TEST: content-security-policy/generic/generic-0_8.sub.html
+WEB-PLATFORM.TEST: content-security-policy/generic/generic-0_8_1.sub.html
+WEB-PLATFORM.TEST: content-security-policy/nonce-hiding/script-nonces-hidden-meta.tentative.html
+WEB-PLATFORM.TEST: content-security-policy/nonce-hiding/svgscript-nonces-hidden-meta.tentative.html
+WEB-PLATFORM.TEST: fetch/api/request/request-structure.html
+WEB-PLATFORM.TEST: html/browsers/origin/relaxing-the-same-origin-restriction/document_domain_setter.html
+WEB-PLATFORM.TEST: html/semantics/embedded-content/the-iframe-element/cross_origin_parentage.html
+WEB-PLATFORM.TEST: html/semantics/forms/the-label-element/label-attributes.html
+WEB-PLATFORM.TEST: longtask-timing/longtask-in-childiframe-crossorigin.html
+WEB-PLATFORM.TEST: longtask-timing/longtask-in-sibling-iframe-crossorigin.html
+WEB-PLATFORM.TEST: navigation-timing/nav2_test_attributes_values.html
+WEB-PLATFORM.TEST: navigation-timing/nav2_test_instance_accessors.html
+WEB-PLATFORM.TEST: service-workers/service-worker/update-bytecheck.https.html
+WEB-PLATFORM.TEST: webdriver/tests/cookies/add_cookie.py
+WEB-PLATFORM.TEST: webdriver/tests/cookies/get_named_cookie.py
+WEB-PLATFORM.TEST: webrtc/RTCPeerConnection-getIdentityAssertion.html
+WEB-PLATFORM.TEST: webrtc/identity-helper.js
diff --git a/tests/wpt/web-platform-tests/longtask-timing/longtask-in-childiframe-crossorigin.html b/tests/wpt/web-platform-tests/longtask-timing/longtask-in-childiframe-crossorigin.html
index 4ad9a740efc..2fa0f780cf6 100644
--- a/tests/wpt/web-platform-tests/longtask-timing/longtask-in-childiframe-crossorigin.html
+++ b/tests/wpt/web-platform-tests/longtask-timing/longtask-in-childiframe-crossorigin.html
@@ -35,7 +35,7 @@
assert_equals(attribution.containerId, 'child-iframe-id');
assert_equals(attribution.containerName, 'child-iframe-name');
assert_equals(attribution.containerSrc,
- 'http://www1.web-platform.test:8000/longtask-timing/resources/subframe-with-longtask.html');
+ 'resources/subframe-with-longtask.html');
observer.disconnect();
t.done();
})
@@ -44,10 +44,11 @@
const iframe = document.createElement('iframe');
iframe.id = 'child-iframe-id';
iframe.name = 'child-iframe-name';
+ // Simulate cross-origin by using sandbox.
+ iframe.sandbox = "allow-scripts";
document.body.appendChild(iframe);
- // TODO(panicker): simulate cross-origin instead
- iframe.src = 'http://www1.web-platform.test:8000/longtask-timing/resources/subframe-with-longtask.html';
-}, 'Performance longtask entries in child iframe are observable in parent.');
+ iframe.src = 'resources/subframe-with-longtask.html';
+}, 'Performance longtask entries in cross-origin child iframe are observable in parent.');
</script>
</body>
diff --git a/tests/wpt/web-platform-tests/longtask-timing/longtask-in-parentiframe.html b/tests/wpt/web-platform-tests/longtask-timing/longtask-in-parentiframe.html
index 71f309a30e0..be29b6c3287 100644
--- a/tests/wpt/web-platform-tests/longtask-timing/longtask-in-parentiframe.html
+++ b/tests/wpt/web-platform-tests/longtask-timing/longtask-in-parentiframe.html
@@ -9,7 +9,12 @@
<script>
const t = async_test(t => {
window.addEventListener('message', t.step_func(e => {
- assert_equals(e.data, 'longtask+same-origin-ancestor+script+++');
+ assert_equals(e.data['entryType'], 'longtask');
+ assert_equals(e.data['frame-attribution'], 'same-origin-ancestor');
+ assert_equals(e.data['task-attribution'], 'script');
+ assert_equals(e.data['containerId'], '');
+ assert_equals(e.data['containerName'], '');
+ assert_equals(e.data['containerSrc'], '');
t.done();
}));
}, 'Performance longtask entries in parent are observable in child iframe.');
diff --git a/tests/wpt/web-platform-tests/longtask-timing/longtask-in-sibling-iframe-crossorigin.html b/tests/wpt/web-platform-tests/longtask-timing/longtask-in-sibling-iframe-crossorigin.html
index 503d8784420..8e922847c25 100644
--- a/tests/wpt/web-platform-tests/longtask-timing/longtask-in-sibling-iframe-crossorigin.html
+++ b/tests/wpt/web-platform-tests/longtask-timing/longtask-in-sibling-iframe-crossorigin.html
@@ -9,21 +9,28 @@
<script>
async_test(t => {
window.addEventListener('message', t.step_func(e => {
- assert_equals(e.data, 'longtask+cross-origin-unreachable+script+++');
+ assert_equals(e.data['entryType'], 'longtask');
+ assert_equals(e.data['frame-attribution'], 'cross-origin-unreachable');
+ assert_equals(e.data['task-attribution'], 'script');
+ assert_equals(e.data['containerId'], '');
+ assert_equals(e.data['containerName'], '');
+ assert_equals(e.data['containerSrc'], '');
t.done();
}));
-}, 'Performance longtask entries in parent are observable in child iframe.');
-</script>
-
-<iframe src="resources/subframe-observing-longtask.html"></iframe>
+ const observingFrame = document.createElement('iframe');
+ observingFrame.id = 'observing-iframe-id';
+ observingFrame.name = 'observing-iframe-name';
+ document.body.appendChild(observingFrame);
+ observingFrame.src = 'resources/subframe-observing-longtask.html'
-<script>
- /* Create a cross-origin iframe that generates a long task. */
- const iframe = document.createElement('iframe');
- iframe.id = 'child-iframe-id';
- iframe.name = 'child-iframe-name';
- document.body.appendChild(iframe);
- iframe.src = 'http://www1.web-platform.test:8000/longtask-timing/resources/subframe-with-longtask.html';
+ /* Create a cross-origin iframe that generates a long task. */
+ const longtaskFrame = document.createElement('iframe');
+ longtaskFrame.id = 'longtask-iframe-id';
+ longtaskFrame.name = 'longtask-iframe-name';
+ // Simulate cross-origin by using sandbox.
+ longtaskFrame.sandbox = "allow-scripts";
+ document.body.appendChild(longtaskFrame);
+ longtaskFrame.src = 'resources/subframe-with-longtask.html'
+}, 'Performance longtask entries from cross-origin iframe are observable in its sibling.');
</script>
-
</body>
diff --git a/tests/wpt/web-platform-tests/longtask-timing/longtask-in-sibling-iframe.html b/tests/wpt/web-platform-tests/longtask-timing/longtask-in-sibling-iframe.html
index 9f536218884..d463810964b 100644
--- a/tests/wpt/web-platform-tests/longtask-timing/longtask-in-sibling-iframe.html
+++ b/tests/wpt/web-platform-tests/longtask-timing/longtask-in-sibling-iframe.html
@@ -9,21 +9,25 @@
<script>
async_test(t => {
window.addEventListener('message', t.step_func(e => {
- assert_equals(e.data, 'longtask+same-origin+script+child-iframe-id+' +
- 'child-iframe-name+resources/subframe-with-longtask.html');
+ assert_equals(e.data['entryType'], 'longtask');
+ assert_equals(e.data['frame-attribution'], 'same-origin');
+ assert_equals(e.data['task-attribution'], 'script');
+ assert_equals(e.data['containerId'], 'longtask-iframe-id');
+ assert_equals(e.data['containerName'], 'longtask-iframe-name');
+ assert_equals(e.data['containerSrc'], 'resources/subframe-with-longtask.html');
t.done();
}));
-}, 'Performance longtask entries in parent are observable in child iframe.');
-</script>
-
-<iframe src="resources/subframe-observing-longtask.html"></iframe>
+ const observingFrame = document.createElement('iframe');
+ observingFrame.id = 'observing-iframe-id';
+ observingFrame.name = 'observing-iframe-name';
+ document.body.appendChild(observingFrame);
+ observingFrame.src = 'resources/subframe-observing-longtask.html'
-<script>
- /* Create an iframe that generates a long task. */
- const iframe = document.createElement('iframe');
- iframe.id = 'child-iframe-id';
- iframe.name = 'child-iframe-name';
- document.body.appendChild(iframe);
- iframe.src = 'resources/subframe-with-longtask.html'
+ const longtaskFrame = document.createElement('iframe');
+ longtaskFrame.id = 'longtask-iframe-id';
+ longtaskFrame.name = 'longtask-iframe-name';
+ document.body.appendChild(longtaskFrame);
+ longtaskFrame.src = 'resources/subframe-with-longtask.html'
+}, 'Performance longtask entries are observable in sibling iframe.');
</script>
</body>
diff --git a/tests/wpt/web-platform-tests/longtask-timing/longtask-tojson.html b/tests/wpt/web-platform-tests/longtask-timing/longtask-tojson.html
new file mode 100644
index 00000000000..bbe0d662c42
--- /dev/null
+++ b/tests/wpt/web-platform-tests/longtask-timing/longtask-tojson.html
@@ -0,0 +1,71 @@
+<!doctype html>
+<html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+ async_test(function (t) {
+ const observer = new PerformanceObserver(
+ t.step_func(function (entryList) {
+ const entries = entryList.getEntries();
+ assert_greater_than_equal(entries.length, 1);
+ const entry = entries[0];
+ assert_equals(typeof(entry.toJSON), 'function');
+ const entryJSON = entry.toJSON();
+ assert_equals(typeof(entryJSON), 'object');
+ // Check attributes inheritted from PerformanceEntry.
+ const performanceEntryKeys = [
+ 'name',
+ 'entryType',
+ 'startTime',
+ 'duration'
+ ];
+ for (const key of performanceEntryKeys) {
+ assert_equals(entryJSON[key], entry[key],
+ `entry.toJSON().${key} should match entry.${key}`);
+ }
+
+ // Check PerformanceLongTaskTiming specific entries.
+ assert_equals(typeof(entryJSON.attribution), 'object');
+ const entryJsonAttribution = entryJSON.attribution[0];
+ assert_equals(typeof(entryJsonAttribution), 'object');
+ assert_equals(entryJSON.attribution.length, entry.attribution.length);
+
+ // Check TaskAttributionTiming toJSON.
+ const entryAttribution = entry.attribution[0];
+ assert_equals(typeof(entryAttribution.toJSON), 'function');
+ const entryAttributionJSON = entryAttribution.toJSON();
+ assert_equals(typeof(entryAttributionJSON), 'object');
+ // Check TaskAttributionTiming attributes, from both:
+ // 1) |entryJsonAttribution| from PerformanceLongTaskTiming.
+ // 2) |entryAttributionJSON| from TaskAttributionTiming.
+ const taskAttributionTimingKeys = [
+ 'name',
+ 'entryType',
+ 'startTime',
+ 'duration',
+ 'containerType',
+ 'containerSrc',
+ 'containerId',
+ 'containerName'
+ ];
+ for (const key of taskAttributionTimingKeys) {
+ assert_equals(entryAttributionJSON[key], entryAttribution[key],
+ `attribution.toJSON().${key} should match attribution.${key}`);
+ assert_equals(entryJsonAttribution[key], entryAttribution[key],
+ `entry.toJSON().attribution[0].${key} should match attribution.${key}`);
+ }
+ t.done();
+ })
+ );
+ observer.observe({entryTypes: ['longtask']});
+
+ // Trigger a long task.
+ const begin = window.performance.now();
+ while (window.performance.now() < begin + 51);
+ }, 'Test toJSON() in PerformanceLongTaskTiming and TaskAttributionTiming');
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/longtask-timing/resources/subframe-observing-longtask.html b/tests/wpt/web-platform-tests/longtask-timing/resources/subframe-observing-longtask.html
index e1e1a934527..b232ecdd47a 100644
--- a/tests/wpt/web-platform-tests/longtask-timing/resources/subframe-observing-longtask.html
+++ b/tests/wpt/web-platform-tests/longtask-timing/resources/subframe-observing-longtask.html
@@ -15,9 +15,14 @@
return;
// TODO(panicker): include containerType.
const attribution = longtask.attribution[0];
- const entryContents = longtask.entryType + '+' + longtask.name + '+' +
- attribution.name + '+' + attribution.containerId + '+' +
- attribution.containerName + '+' + attribution.containerSrc;
+ const entryContents = {
+ 'entryType': longtask.entryType,
+ 'frame-attribution': longtask.name,
+ 'task-attribution': attribution.name,
+ 'containerId': attribution.containerId,
+ 'containerName': attribution.containerName,
+ 'containerSrc': attribution.containerSrc
+ };
top.postMessage(entryContents, '*');
}
});
diff --git a/tests/wpt/web-platform-tests/magnetometer/Magnetometer-disabled-by-feature-policy.https.html b/tests/wpt/web-platform-tests/magnetometer/Magnetometer-disabled-by-feature-policy.https.html
new file mode 100644
index 00000000000..f24b2b35646
--- /dev/null
+++ b/tests/wpt/web-platform-tests/magnetometer/Magnetometer-disabled-by-feature-policy.https.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_disabled(Magnetometer);
+run_fp_tests_disabled(UncalibratedMagnetometer);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/magnetometer/Magnetometer-disabled-by-feature-policy.https.html.headers b/tests/wpt/web-platform-tests/magnetometer/Magnetometer-disabled-by-feature-policy.https.html.headers
new file mode 100644
index 00000000000..afbd45465cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/magnetometer/Magnetometer-disabled-by-feature-policy.https.html.headers
@@ -0,0 +1 @@
+Feature-Policy: magnetometer 'none'
diff --git a/tests/wpt/web-platform-tests/magnetometer/Magnetometer-enabled-by-feature-policy-attribute-redirect-on-load.https.html b/tests/wpt/web-platform-tests/magnetometer/Magnetometer-enabled-by-feature-policy-attribute-redirect-on-load.https.html
new file mode 100644
index 00000000000..08369810f5f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/magnetometer/Magnetometer-enabled-by-feature-policy-attribute-redirect-on-load.https.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled_by_attribute_redirect_on_load(Magnetometer);
+run_fp_tests_enabled_by_attribute_redirect_on_load(UncalibratedMagnetometer);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/magnetometer/Magnetometer-enabled-by-feature-policy-attribute.https.html b/tests/wpt/web-platform-tests/magnetometer/Magnetometer-enabled-by-feature-policy-attribute.https.html
new file mode 100644
index 00000000000..0086222cbc7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/magnetometer/Magnetometer-enabled-by-feature-policy-attribute.https.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled_by_attribute(Magnetometer);
+run_fp_tests_enabled_by_attribute(UncalibratedMagnetometer);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/magnetometer/Magnetometer-enabled-by-feature-policy.https.html b/tests/wpt/web-platform-tests/magnetometer/Magnetometer-enabled-by-feature-policy.https.html
new file mode 100644
index 00000000000..7f8ce1a9675
--- /dev/null
+++ b/tests/wpt/web-platform-tests/magnetometer/Magnetometer-enabled-by-feature-policy.https.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled(Magnetometer);
+run_fp_tests_enabled(UncalibratedMagnetometer);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/magnetometer/Magnetometer-enabled-by-feature-policy.https.html.headers b/tests/wpt/web-platform-tests/magnetometer/Magnetometer-enabled-by-feature-policy.https.html.headers
new file mode 100644
index 00000000000..64ec55e3e40
--- /dev/null
+++ b/tests/wpt/web-platform-tests/magnetometer/Magnetometer-enabled-by-feature-policy.https.html.headers
@@ -0,0 +1 @@
+Feature-Policy: magnetometer *
diff --git a/tests/wpt/web-platform-tests/magnetometer/Magnetometer-enabled-on-self-origin-by-feature-policy.https.html b/tests/wpt/web-platform-tests/magnetometer/Magnetometer-enabled-on-self-origin-by-feature-policy.https.html
new file mode 100644
index 00000000000..a967576eafc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/magnetometer/Magnetometer-enabled-on-self-origin-by-feature-policy.https.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled_on_self_origin(Magnetometer);
+run_fp_tests_enabled_on_self_origin(UncalibratedMagnetometer);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/magnetometer/Magnetometer-enabled-on-self-origin-by-feature-policy.https.html.headers b/tests/wpt/web-platform-tests/magnetometer/Magnetometer-enabled-on-self-origin-by-feature-policy.https.html.headers
new file mode 100644
index 00000000000..4223f53ffa3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/magnetometer/Magnetometer-enabled-on-self-origin-by-feature-policy.https.html.headers
@@ -0,0 +1 @@
+Feature-Policy: magnetometer 'self'
diff --git a/tests/wpt/web-platform-tests/magnetometer/Magnetometer.https.html b/tests/wpt/web-platform-tests/magnetometer/Magnetometer.https.html
index f327ed3c43d..a3cefc26169 100644
--- a/tests/wpt/web-platform-tests/magnetometer/Magnetometer.https.html
+++ b/tests/wpt/web-platform-tests/magnetometer/Magnetometer.https.html
@@ -10,5 +10,6 @@
<script>
runGenericSensorTests(Magnetometer);
+runGenericSensorTests(UncalibratedMagnetometer);
</script>
diff --git a/tests/wpt/web-platform-tests/magnetometer/Magnetometer_insecure_context.html b/tests/wpt/web-platform-tests/magnetometer/Magnetometer_insecure_context.html
index 307c19b101b..45ff584b425 100644
--- a/tests/wpt/web-platform-tests/magnetometer/Magnetometer_insecure_context.html
+++ b/tests/wpt/web-platform-tests/magnetometer/Magnetometer_insecure_context.html
@@ -16,5 +16,6 @@
<script>
runGenericSensorInsecureContext("Magnetometer");
+runGenericSensorInsecureContext("UncalibratedMagnetometer");
</script>
diff --git a/tests/wpt/web-platform-tests/magnetometer/Magnetometer_onerror-manual.https.html b/tests/wpt/web-platform-tests/magnetometer/Magnetometer_onerror-manual.https.html
index 3cd62db8a22..04b987797fa 100644
--- a/tests/wpt/web-platform-tests/magnetometer/Magnetometer_onerror-manual.https.html
+++ b/tests/wpt/web-platform-tests/magnetometer/Magnetometer_onerror-manual.https.html
@@ -16,5 +16,6 @@
<script>
runGenericSensorOnerror(Magnetometer);
+runGenericSensorOnerror(UncalibratedMagnetometer);
</script>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-fraktur-ref.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-fraktur-ref.html
index 0007e012deb..b883b12b57d 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-fraktur-ref.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-fraktur-ref.html
@@ -23,57 +23,57 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi>&#x1D56C;</mi></math>=<span>1D56C</span></span>
- <span><math><mi>&#x1D56D;</mi></math>=<span>1D56D</span></span>
- <span><math><mi>&#x1D56E;</mi></math>=<span>1D56E</span></span>
- <span><math><mi>&#x1D56F;</mi></math>=<span>1D56F</span></span>
- <span><math><mi>&#x1D570;</mi></math>=<span>1D570</span></span>
- <span><math><mi>&#x1D571;</mi></math>=<span>1D571</span></span>
- <span><math><mi>&#x1D572;</mi></math>=<span>1D572</span></span>
- <span><math><mi>&#x1D573;</mi></math>=<span>1D573</span></span>
- <span><math><mi>&#x1D574;</mi></math>=<span>1D574</span></span>
- <span><math><mi>&#x1D575;</mi></math>=<span>1D575</span></span><br/>
- <span><math><mi>&#x1D576;</mi></math>=<span>1D576</span></span>
- <span><math><mi>&#x1D577;</mi></math>=<span>1D577</span></span>
- <span><math><mi>&#x1D578;</mi></math>=<span>1D578</span></span>
- <span><math><mi>&#x1D579;</mi></math>=<span>1D579</span></span>
- <span><math><mi>&#x1D57A;</mi></math>=<span>1D57A</span></span>
- <span><math><mi>&#x1D57B;</mi></math>=<span>1D57B</span></span>
- <span><math><mi>&#x1D57C;</mi></math>=<span>1D57C</span></span>
- <span><math><mi>&#x1D57D;</mi></math>=<span>1D57D</span></span>
- <span><math><mi>&#x1D57E;</mi></math>=<span>1D57E</span></span>
- <span><math><mi>&#x1D57F;</mi></math>=<span>1D57F</span></span><br/>
- <span><math><mi>&#x1D580;</mi></math>=<span>1D580</span></span>
- <span><math><mi>&#x1D581;</mi></math>=<span>1D581</span></span>
- <span><math><mi>&#x1D582;</mi></math>=<span>1D582</span></span>
- <span><math><mi>&#x1D583;</mi></math>=<span>1D583</span></span>
- <span><math><mi>&#x1D584;</mi></math>=<span>1D584</span></span>
- <span><math><mi>&#x1D585;</mi></math>=<span>1D585</span></span>
- <span><math><mi>&#x1D586;</mi></math>=<span>1D586</span></span>
- <span><math><mi>&#x1D587;</mi></math>=<span>1D587</span></span>
- <span><math><mi>&#x1D588;</mi></math>=<span>1D588</span></span>
- <span><math><mi>&#x1D589;</mi></math>=<span>1D589</span></span><br/>
- <span><math><mi>&#x1D58A;</mi></math>=<span>1D58A</span></span>
- <span><math><mi>&#x1D58B;</mi></math>=<span>1D58B</span></span>
- <span><math><mi>&#x1D58C;</mi></math>=<span>1D58C</span></span>
- <span><math><mi>&#x1D58D;</mi></math>=<span>1D58D</span></span>
- <span><math><mi>&#x1D58E;</mi></math>=<span>1D58E</span></span>
- <span><math><mi>&#x1D58F;</mi></math>=<span>1D58F</span></span>
- <span><math><mi>&#x1D590;</mi></math>=<span>1D590</span></span>
- <span><math><mi>&#x1D591;</mi></math>=<span>1D591</span></span>
- <span><math><mi>&#x1D592;</mi></math>=<span>1D592</span></span>
- <span><math><mi>&#x1D593;</mi></math>=<span>1D593</span></span><br/>
- <span><math><mi>&#x1D594;</mi></math>=<span>1D594</span></span>
- <span><math><mi>&#x1D595;</mi></math>=<span>1D595</span></span>
- <span><math><mi>&#x1D596;</mi></math>=<span>1D596</span></span>
- <span><math><mi>&#x1D597;</mi></math>=<span>1D597</span></span>
- <span><math><mi>&#x1D598;</mi></math>=<span>1D598</span></span>
- <span><math><mi>&#x1D599;</mi></math>=<span>1D599</span></span>
- <span><math><mi>&#x1D59A;</mi></math>=<span>1D59A</span></span>
- <span><math><mi>&#x1D59B;</mi></math>=<span>1D59B</span></span>
- <span><math><mi>&#x1D59C;</mi></math>=<span>1D59C</span></span>
- <span><math><mi>&#x1D59D;</mi></math>=<span>1D59D</span></span><br/>
- <span><math><mi>&#x1D59E;</mi></math>=<span>1D59E</span></span>
- <span><math><mi>&#x1D59F;</mi></math>=<span>1D59F</span></span>
+ <span><math><mtext>&#x1D56C;</mtext></math>=<span>1D56C</span></span>
+ <span><math><mtext>&#x1D56D;</mtext></math>=<span>1D56D</span></span>
+ <span><math><mtext>&#x1D56E;</mtext></math>=<span>1D56E</span></span>
+ <span><math><mtext>&#x1D56F;</mtext></math>=<span>1D56F</span></span>
+ <span><math><mtext>&#x1D570;</mtext></math>=<span>1D570</span></span>
+ <span><math><mtext>&#x1D571;</mtext></math>=<span>1D571</span></span>
+ <span><math><mtext>&#x1D572;</mtext></math>=<span>1D572</span></span>
+ <span><math><mtext>&#x1D573;</mtext></math>=<span>1D573</span></span>
+ <span><math><mtext>&#x1D574;</mtext></math>=<span>1D574</span></span>
+ <span><math><mtext>&#x1D575;</mtext></math>=<span>1D575</span></span><br/>
+ <span><math><mtext>&#x1D576;</mtext></math>=<span>1D576</span></span>
+ <span><math><mtext>&#x1D577;</mtext></math>=<span>1D577</span></span>
+ <span><math><mtext>&#x1D578;</mtext></math>=<span>1D578</span></span>
+ <span><math><mtext>&#x1D579;</mtext></math>=<span>1D579</span></span>
+ <span><math><mtext>&#x1D57A;</mtext></math>=<span>1D57A</span></span>
+ <span><math><mtext>&#x1D57B;</mtext></math>=<span>1D57B</span></span>
+ <span><math><mtext>&#x1D57C;</mtext></math>=<span>1D57C</span></span>
+ <span><math><mtext>&#x1D57D;</mtext></math>=<span>1D57D</span></span>
+ <span><math><mtext>&#x1D57E;</mtext></math>=<span>1D57E</span></span>
+ <span><math><mtext>&#x1D57F;</mtext></math>=<span>1D57F</span></span><br/>
+ <span><math><mtext>&#x1D580;</mtext></math>=<span>1D580</span></span>
+ <span><math><mtext>&#x1D581;</mtext></math>=<span>1D581</span></span>
+ <span><math><mtext>&#x1D582;</mtext></math>=<span>1D582</span></span>
+ <span><math><mtext>&#x1D583;</mtext></math>=<span>1D583</span></span>
+ <span><math><mtext>&#x1D584;</mtext></math>=<span>1D584</span></span>
+ <span><math><mtext>&#x1D585;</mtext></math>=<span>1D585</span></span>
+ <span><math><mtext>&#x1D586;</mtext></math>=<span>1D586</span></span>
+ <span><math><mtext>&#x1D587;</mtext></math>=<span>1D587</span></span>
+ <span><math><mtext>&#x1D588;</mtext></math>=<span>1D588</span></span>
+ <span><math><mtext>&#x1D589;</mtext></math>=<span>1D589</span></span><br/>
+ <span><math><mtext>&#x1D58A;</mtext></math>=<span>1D58A</span></span>
+ <span><math><mtext>&#x1D58B;</mtext></math>=<span>1D58B</span></span>
+ <span><math><mtext>&#x1D58C;</mtext></math>=<span>1D58C</span></span>
+ <span><math><mtext>&#x1D58D;</mtext></math>=<span>1D58D</span></span>
+ <span><math><mtext>&#x1D58E;</mtext></math>=<span>1D58E</span></span>
+ <span><math><mtext>&#x1D58F;</mtext></math>=<span>1D58F</span></span>
+ <span><math><mtext>&#x1D590;</mtext></math>=<span>1D590</span></span>
+ <span><math><mtext>&#x1D591;</mtext></math>=<span>1D591</span></span>
+ <span><math><mtext>&#x1D592;</mtext></math>=<span>1D592</span></span>
+ <span><math><mtext>&#x1D593;</mtext></math>=<span>1D593</span></span><br/>
+ <span><math><mtext>&#x1D594;</mtext></math>=<span>1D594</span></span>
+ <span><math><mtext>&#x1D595;</mtext></math>=<span>1D595</span></span>
+ <span><math><mtext>&#x1D596;</mtext></math>=<span>1D596</span></span>
+ <span><math><mtext>&#x1D597;</mtext></math>=<span>1D597</span></span>
+ <span><math><mtext>&#x1D598;</mtext></math>=<span>1D598</span></span>
+ <span><math><mtext>&#x1D599;</mtext></math>=<span>1D599</span></span>
+ <span><math><mtext>&#x1D59A;</mtext></math>=<span>1D59A</span></span>
+ <span><math><mtext>&#x1D59B;</mtext></math>=<span>1D59B</span></span>
+ <span><math><mtext>&#x1D59C;</mtext></math>=<span>1D59C</span></span>
+ <span><math><mtext>&#x1D59D;</mtext></math>=<span>1D59D</span></span><br/>
+ <span><math><mtext>&#x1D59E;</mtext></math>=<span>1D59E</span></span>
+ <span><math><mtext>&#x1D59F;</mtext></math>=<span>1D59F</span></span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-fraktur.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-fraktur.html
index 5182df883d6..487d61d7d85 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-fraktur.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-fraktur.html
@@ -5,7 +5,7 @@
<title>mathvariant bold-fraktur</title>
<link rel="help" href="http://www.mathml-association.org/MathMLinHTML5/S2.html#SS3.SSS1.tab2"/>
<link rel="match" href="mathvariant-bold-fraktur-ref.html"/>
-<meta name="assert" content="Verify that a single-char <mi> with a bold-fraktur mathvariant is equivalent to an <mi> with the transformed unicode character.">
+<meta name="assert" content="Verify that a single-char <mtext> with a bold-fraktur mathvariant is equivalent to an <mtext> with the transformed unicode character.">
<style>
@font-face {
font-family: TestFont;
@@ -26,57 +26,57 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi mathvariant="bold-fraktur">&#x41;</mi></math>=<span>1D56C</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x42;</mi></math>=<span>1D56D</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x43;</mi></math>=<span>1D56E</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x44;</mi></math>=<span>1D56F</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x45;</mi></math>=<span>1D570</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x46;</mi></math>=<span>1D571</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x47;</mi></math>=<span>1D572</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x48;</mi></math>=<span>1D573</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x49;</mi></math>=<span>1D574</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x4A;</mi></math>=<span>1D575</span></span><br/>
- <span><math><mi mathvariant="bold-fraktur">&#x4B;</mi></math>=<span>1D576</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x4C;</mi></math>=<span>1D577</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x4D;</mi></math>=<span>1D578</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x4E;</mi></math>=<span>1D579</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x4F;</mi></math>=<span>1D57A</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x50;</mi></math>=<span>1D57B</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x51;</mi></math>=<span>1D57C</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x52;</mi></math>=<span>1D57D</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x53;</mi></math>=<span>1D57E</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x54;</mi></math>=<span>1D57F</span></span><br/>
- <span><math><mi mathvariant="bold-fraktur">&#x55;</mi></math>=<span>1D580</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x56;</mi></math>=<span>1D581</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x57;</mi></math>=<span>1D582</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x58;</mi></math>=<span>1D583</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x59;</mi></math>=<span>1D584</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x5A;</mi></math>=<span>1D585</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x61;</mi></math>=<span>1D586</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x62;</mi></math>=<span>1D587</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x63;</mi></math>=<span>1D588</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x64;</mi></math>=<span>1D589</span></span><br/>
- <span><math><mi mathvariant="bold-fraktur">&#x65;</mi></math>=<span>1D58A</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x66;</mi></math>=<span>1D58B</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x67;</mi></math>=<span>1D58C</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x68;</mi></math>=<span>1D58D</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x69;</mi></math>=<span>1D58E</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x6A;</mi></math>=<span>1D58F</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x6B;</mi></math>=<span>1D590</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x6C;</mi></math>=<span>1D591</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x6D;</mi></math>=<span>1D592</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x6E;</mi></math>=<span>1D593</span></span><br/>
- <span><math><mi mathvariant="bold-fraktur">&#x6F;</mi></math>=<span>1D594</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x70;</mi></math>=<span>1D595</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x71;</mi></math>=<span>1D596</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x72;</mi></math>=<span>1D597</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x73;</mi></math>=<span>1D598</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x74;</mi></math>=<span>1D599</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x75;</mi></math>=<span>1D59A</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x76;</mi></math>=<span>1D59B</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x77;</mi></math>=<span>1D59C</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x78;</mi></math>=<span>1D59D</span></span><br/>
- <span><math><mi mathvariant="bold-fraktur">&#x79;</mi></math>=<span>1D59E</span></span>
- <span><math><mi mathvariant="bold-fraktur">&#x7A;</mi></math>=<span>1D59F</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x41;</mtext></math>=<span>1D56C</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x42;</mtext></math>=<span>1D56D</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x43;</mtext></math>=<span>1D56E</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x44;</mtext></math>=<span>1D56F</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x45;</mtext></math>=<span>1D570</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x46;</mtext></math>=<span>1D571</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x47;</mtext></math>=<span>1D572</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x48;</mtext></math>=<span>1D573</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x49;</mtext></math>=<span>1D574</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x4A;</mtext></math>=<span>1D575</span></span><br/>
+ <span><math><mtext mathvariant="bold-fraktur">&#x4B;</mtext></math>=<span>1D576</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x4C;</mtext></math>=<span>1D577</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x4D;</mtext></math>=<span>1D578</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x4E;</mtext></math>=<span>1D579</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x4F;</mtext></math>=<span>1D57A</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x50;</mtext></math>=<span>1D57B</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x51;</mtext></math>=<span>1D57C</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x52;</mtext></math>=<span>1D57D</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x53;</mtext></math>=<span>1D57E</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x54;</mtext></math>=<span>1D57F</span></span><br/>
+ <span><math><mtext mathvariant="bold-fraktur">&#x55;</mtext></math>=<span>1D580</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x56;</mtext></math>=<span>1D581</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x57;</mtext></math>=<span>1D582</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x58;</mtext></math>=<span>1D583</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x59;</mtext></math>=<span>1D584</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x5A;</mtext></math>=<span>1D585</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x61;</mtext></math>=<span>1D586</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x62;</mtext></math>=<span>1D587</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x63;</mtext></math>=<span>1D588</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x64;</mtext></math>=<span>1D589</span></span><br/>
+ <span><math><mtext mathvariant="bold-fraktur">&#x65;</mtext></math>=<span>1D58A</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x66;</mtext></math>=<span>1D58B</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x67;</mtext></math>=<span>1D58C</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x68;</mtext></math>=<span>1D58D</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x69;</mtext></math>=<span>1D58E</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x6A;</mtext></math>=<span>1D58F</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x6B;</mtext></math>=<span>1D590</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x6C;</mtext></math>=<span>1D591</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x6D;</mtext></math>=<span>1D592</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x6E;</mtext></math>=<span>1D593</span></span><br/>
+ <span><math><mtext mathvariant="bold-fraktur">&#x6F;</mtext></math>=<span>1D594</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x70;</mtext></math>=<span>1D595</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x71;</mtext></math>=<span>1D596</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x72;</mtext></math>=<span>1D597</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x73;</mtext></math>=<span>1D598</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x74;</mtext></math>=<span>1D599</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x75;</mtext></math>=<span>1D59A</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x76;</mtext></math>=<span>1D59B</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x77;</mtext></math>=<span>1D59C</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x78;</mtext></math>=<span>1D59D</span></span><br/>
+ <span><math><mtext mathvariant="bold-fraktur">&#x79;</mtext></math>=<span>1D59E</span></span>
+ <span><math><mtext mathvariant="bold-fraktur">&#x7A;</mtext></math>=<span>1D59F</span></span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-italic-ref.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-italic-ref.html
index 0d3758d9dc9..1e71e896636 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-italic-ref.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-italic-ref.html
@@ -23,115 +23,115 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi>&#x1D74F;</mi></math>=<span>1D74F</span></span>
- <span><math><mi>&#x1D735;</mi></math>=<span>1D735</span></span>
- <span><math><mi>&#x1D468;</mi></math>=<span>1D468</span></span>
- <span><math><mi>&#x1D469;</mi></math>=<span>1D469</span></span>
- <span><math><mi>&#x1D46A;</mi></math>=<span>1D46A</span></span>
- <span><math><mi>&#x1D46B;</mi></math>=<span>1D46B</span></span>
- <span><math><mi>&#x1D46C;</mi></math>=<span>1D46C</span></span>
- <span><math><mi>&#x1D46D;</mi></math>=<span>1D46D</span></span>
- <span><math><mi>&#x1D46E;</mi></math>=<span>1D46E</span></span>
- <span><math><mi>&#x1D46F;</mi></math>=<span>1D46F</span></span><br/>
- <span><math><mi>&#x1D470;</mi></math>=<span>1D470</span></span>
- <span><math><mi>&#x1D471;</mi></math>=<span>1D471</span></span>
- <span><math><mi>&#x1D472;</mi></math>=<span>1D472</span></span>
- <span><math><mi>&#x1D473;</mi></math>=<span>1D473</span></span>
- <span><math><mi>&#x1D474;</mi></math>=<span>1D474</span></span>
- <span><math><mi>&#x1D475;</mi></math>=<span>1D475</span></span>
- <span><math><mi>&#x1D476;</mi></math>=<span>1D476</span></span>
- <span><math><mi>&#x1D477;</mi></math>=<span>1D477</span></span>
- <span><math><mi>&#x1D478;</mi></math>=<span>1D478</span></span>
- <span><math><mi>&#x1D479;</mi></math>=<span>1D479</span></span><br/>
- <span><math><mi>&#x1D47A;</mi></math>=<span>1D47A</span></span>
- <span><math><mi>&#x1D47B;</mi></math>=<span>1D47B</span></span>
- <span><math><mi>&#x1D47C;</mi></math>=<span>1D47C</span></span>
- <span><math><mi>&#x1D47D;</mi></math>=<span>1D47D</span></span>
- <span><math><mi>&#x1D47E;</mi></math>=<span>1D47E</span></span>
- <span><math><mi>&#x1D47F;</mi></math>=<span>1D47F</span></span>
- <span><math><mi>&#x1D480;</mi></math>=<span>1D480</span></span>
- <span><math><mi>&#x1D481;</mi></math>=<span>1D481</span></span>
- <span><math><mi>&#x1D482;</mi></math>=<span>1D482</span></span>
- <span><math><mi>&#x1D483;</mi></math>=<span>1D483</span></span><br/>
- <span><math><mi>&#x1D484;</mi></math>=<span>1D484</span></span>
- <span><math><mi>&#x1D485;</mi></math>=<span>1D485</span></span>
- <span><math><mi>&#x1D486;</mi></math>=<span>1D486</span></span>
- <span><math><mi>&#x1D487;</mi></math>=<span>1D487</span></span>
- <span><math><mi>&#x1D488;</mi></math>=<span>1D488</span></span>
- <span><math><mi>&#x1D489;</mi></math>=<span>1D489</span></span>
- <span><math><mi>&#x1D48A;</mi></math>=<span>1D48A</span></span>
- <span><math><mi>&#x1D48B;</mi></math>=<span>1D48B</span></span>
- <span><math><mi>&#x1D48C;</mi></math>=<span>1D48C</span></span>
- <span><math><mi>&#x1D48D;</mi></math>=<span>1D48D</span></span><br/>
- <span><math><mi>&#x1D48E;</mi></math>=<span>1D48E</span></span>
- <span><math><mi>&#x1D48F;</mi></math>=<span>1D48F</span></span>
- <span><math><mi>&#x1D490;</mi></math>=<span>1D490</span></span>
- <span><math><mi>&#x1D491;</mi></math>=<span>1D491</span></span>
- <span><math><mi>&#x1D492;</mi></math>=<span>1D492</span></span>
- <span><math><mi>&#x1D493;</mi></math>=<span>1D493</span></span>
- <span><math><mi>&#x1D494;</mi></math>=<span>1D494</span></span>
- <span><math><mi>&#x1D495;</mi></math>=<span>1D495</span></span>
- <span><math><mi>&#x1D496;</mi></math>=<span>1D496</span></span>
- <span><math><mi>&#x1D497;</mi></math>=<span>1D497</span></span><br/>
- <span><math><mi>&#x1D498;</mi></math>=<span>1D498</span></span>
- <span><math><mi>&#x1D499;</mi></math>=<span>1D499</span></span>
- <span><math><mi>&#x1D49A;</mi></math>=<span>1D49A</span></span>
- <span><math><mi>&#x1D49B;</mi></math>=<span>1D49B</span></span>
- <span><math><mi>&#x1D71C;</mi></math>=<span>1D71C</span></span>
- <span><math><mi>&#x1D71D;</mi></math>=<span>1D71D</span></span>
- <span><math><mi>&#x1D71E;</mi></math>=<span>1D71E</span></span>
- <span><math><mi>&#x1D71F;</mi></math>=<span>1D71F</span></span>
- <span><math><mi>&#x1D720;</mi></math>=<span>1D720</span></span>
- <span><math><mi>&#x1D721;</mi></math>=<span>1D721</span></span><br/>
- <span><math><mi>&#x1D722;</mi></math>=<span>1D722</span></span>
- <span><math><mi>&#x1D723;</mi></math>=<span>1D723</span></span>
- <span><math><mi>&#x1D724;</mi></math>=<span>1D724</span></span>
- <span><math><mi>&#x1D725;</mi></math>=<span>1D725</span></span>
- <span><math><mi>&#x1D726;</mi></math>=<span>1D726</span></span>
- <span><math><mi>&#x1D727;</mi></math>=<span>1D727</span></span>
- <span><math><mi>&#x1D728;</mi></math>=<span>1D728</span></span>
- <span><math><mi>&#x1D729;</mi></math>=<span>1D729</span></span>
- <span><math><mi>&#x1D72A;</mi></math>=<span>1D72A</span></span>
- <span><math><mi>&#x1D72B;</mi></math>=<span>1D72B</span></span><br/>
- <span><math><mi>&#x1D72C;</mi></math>=<span>1D72C</span></span>
- <span><math><mi>&#x1D72E;</mi></math>=<span>1D72E</span></span>
- <span><math><mi>&#x1D72F;</mi></math>=<span>1D72F</span></span>
- <span><math><mi>&#x1D730;</mi></math>=<span>1D730</span></span>
- <span><math><mi>&#x1D731;</mi></math>=<span>1D731</span></span>
- <span><math><mi>&#x1D732;</mi></math>=<span>1D732</span></span>
- <span><math><mi>&#x1D733;</mi></math>=<span>1D733</span></span>
- <span><math><mi>&#x1D734;</mi></math>=<span>1D734</span></span>
- <span><math><mi>&#x1D736;</mi></math>=<span>1D736</span></span>
- <span><math><mi>&#x1D737;</mi></math>=<span>1D737</span></span><br/>
- <span><math><mi>&#x1D738;</mi></math>=<span>1D738</span></span>
- <span><math><mi>&#x1D739;</mi></math>=<span>1D739</span></span>
- <span><math><mi>&#x1D73A;</mi></math>=<span>1D73A</span></span>
- <span><math><mi>&#x1D73B;</mi></math>=<span>1D73B</span></span>
- <span><math><mi>&#x1D73C;</mi></math>=<span>1D73C</span></span>
- <span><math><mi>&#x1D73D;</mi></math>=<span>1D73D</span></span>
- <span><math><mi>&#x1D73E;</mi></math>=<span>1D73E</span></span>
- <span><math><mi>&#x1D73F;</mi></math>=<span>1D73F</span></span>
- <span><math><mi>&#x1D740;</mi></math>=<span>1D740</span></span>
- <span><math><mi>&#x1D741;</mi></math>=<span>1D741</span></span><br/>
- <span><math><mi>&#x1D742;</mi></math>=<span>1D742</span></span>
- <span><math><mi>&#x1D743;</mi></math>=<span>1D743</span></span>
- <span><math><mi>&#x1D744;</mi></math>=<span>1D744</span></span>
- <span><math><mi>&#x1D745;</mi></math>=<span>1D745</span></span>
- <span><math><mi>&#x1D746;</mi></math>=<span>1D746</span></span>
- <span><math><mi>&#x1D747;</mi></math>=<span>1D747</span></span>
- <span><math><mi>&#x1D748;</mi></math>=<span>1D748</span></span>
- <span><math><mi>&#x1D749;</mi></math>=<span>1D749</span></span>
- <span><math><mi>&#x1D74A;</mi></math>=<span>1D74A</span></span>
- <span><math><mi>&#x1D74B;</mi></math>=<span>1D74B</span></span><br/>
- <span><math><mi>&#x1D74C;</mi></math>=<span>1D74C</span></span>
- <span><math><mi>&#x1D74D;</mi></math>=<span>1D74D</span></span>
- <span><math><mi>&#x1D74E;</mi></math>=<span>1D74E</span></span>
- <span><math><mi>&#x1D751;</mi></math>=<span>1D751</span></span>
- <span><math><mi>&#x1D753;</mi></math>=<span>1D753</span></span>
- <span><math><mi>&#x1D755;</mi></math>=<span>1D755</span></span>
- <span><math><mi>&#x1D752;</mi></math>=<span>1D752</span></span>
- <span><math><mi>&#x1D754;</mi></math>=<span>1D754</span></span>
- <span><math><mi>&#x1D72D;</mi></math>=<span>1D72D</span></span>
- <span><math><mi>&#x1D750;</mi></math>=<span>1D750</span></span><br/>
+ <span><math><mtext>&#x1D74F;</mtext></math>=<span>1D74F</span></span>
+ <span><math><mtext>&#x1D735;</mtext></math>=<span>1D735</span></span>
+ <span><math><mtext>&#x1D468;</mtext></math>=<span>1D468</span></span>
+ <span><math><mtext>&#x1D469;</mtext></math>=<span>1D469</span></span>
+ <span><math><mtext>&#x1D46A;</mtext></math>=<span>1D46A</span></span>
+ <span><math><mtext>&#x1D46B;</mtext></math>=<span>1D46B</span></span>
+ <span><math><mtext>&#x1D46C;</mtext></math>=<span>1D46C</span></span>
+ <span><math><mtext>&#x1D46D;</mtext></math>=<span>1D46D</span></span>
+ <span><math><mtext>&#x1D46E;</mtext></math>=<span>1D46E</span></span>
+ <span><math><mtext>&#x1D46F;</mtext></math>=<span>1D46F</span></span><br/>
+ <span><math><mtext>&#x1D470;</mtext></math>=<span>1D470</span></span>
+ <span><math><mtext>&#x1D471;</mtext></math>=<span>1D471</span></span>
+ <span><math><mtext>&#x1D472;</mtext></math>=<span>1D472</span></span>
+ <span><math><mtext>&#x1D473;</mtext></math>=<span>1D473</span></span>
+ <span><math><mtext>&#x1D474;</mtext></math>=<span>1D474</span></span>
+ <span><math><mtext>&#x1D475;</mtext></math>=<span>1D475</span></span>
+ <span><math><mtext>&#x1D476;</mtext></math>=<span>1D476</span></span>
+ <span><math><mtext>&#x1D477;</mtext></math>=<span>1D477</span></span>
+ <span><math><mtext>&#x1D478;</mtext></math>=<span>1D478</span></span>
+ <span><math><mtext>&#x1D479;</mtext></math>=<span>1D479</span></span><br/>
+ <span><math><mtext>&#x1D47A;</mtext></math>=<span>1D47A</span></span>
+ <span><math><mtext>&#x1D47B;</mtext></math>=<span>1D47B</span></span>
+ <span><math><mtext>&#x1D47C;</mtext></math>=<span>1D47C</span></span>
+ <span><math><mtext>&#x1D47D;</mtext></math>=<span>1D47D</span></span>
+ <span><math><mtext>&#x1D47E;</mtext></math>=<span>1D47E</span></span>
+ <span><math><mtext>&#x1D47F;</mtext></math>=<span>1D47F</span></span>
+ <span><math><mtext>&#x1D480;</mtext></math>=<span>1D480</span></span>
+ <span><math><mtext>&#x1D481;</mtext></math>=<span>1D481</span></span>
+ <span><math><mtext>&#x1D482;</mtext></math>=<span>1D482</span></span>
+ <span><math><mtext>&#x1D483;</mtext></math>=<span>1D483</span></span><br/>
+ <span><math><mtext>&#x1D484;</mtext></math>=<span>1D484</span></span>
+ <span><math><mtext>&#x1D485;</mtext></math>=<span>1D485</span></span>
+ <span><math><mtext>&#x1D486;</mtext></math>=<span>1D486</span></span>
+ <span><math><mtext>&#x1D487;</mtext></math>=<span>1D487</span></span>
+ <span><math><mtext>&#x1D488;</mtext></math>=<span>1D488</span></span>
+ <span><math><mtext>&#x1D489;</mtext></math>=<span>1D489</span></span>
+ <span><math><mtext>&#x1D48A;</mtext></math>=<span>1D48A</span></span>
+ <span><math><mtext>&#x1D48B;</mtext></math>=<span>1D48B</span></span>
+ <span><math><mtext>&#x1D48C;</mtext></math>=<span>1D48C</span></span>
+ <span><math><mtext>&#x1D48D;</mtext></math>=<span>1D48D</span></span><br/>
+ <span><math><mtext>&#x1D48E;</mtext></math>=<span>1D48E</span></span>
+ <span><math><mtext>&#x1D48F;</mtext></math>=<span>1D48F</span></span>
+ <span><math><mtext>&#x1D490;</mtext></math>=<span>1D490</span></span>
+ <span><math><mtext>&#x1D491;</mtext></math>=<span>1D491</span></span>
+ <span><math><mtext>&#x1D492;</mtext></math>=<span>1D492</span></span>
+ <span><math><mtext>&#x1D493;</mtext></math>=<span>1D493</span></span>
+ <span><math><mtext>&#x1D494;</mtext></math>=<span>1D494</span></span>
+ <span><math><mtext>&#x1D495;</mtext></math>=<span>1D495</span></span>
+ <span><math><mtext>&#x1D496;</mtext></math>=<span>1D496</span></span>
+ <span><math><mtext>&#x1D497;</mtext></math>=<span>1D497</span></span><br/>
+ <span><math><mtext>&#x1D498;</mtext></math>=<span>1D498</span></span>
+ <span><math><mtext>&#x1D499;</mtext></math>=<span>1D499</span></span>
+ <span><math><mtext>&#x1D49A;</mtext></math>=<span>1D49A</span></span>
+ <span><math><mtext>&#x1D49B;</mtext></math>=<span>1D49B</span></span>
+ <span><math><mtext>&#x1D71C;</mtext></math>=<span>1D71C</span></span>
+ <span><math><mtext>&#x1D71D;</mtext></math>=<span>1D71D</span></span>
+ <span><math><mtext>&#x1D71E;</mtext></math>=<span>1D71E</span></span>
+ <span><math><mtext>&#x1D71F;</mtext></math>=<span>1D71F</span></span>
+ <span><math><mtext>&#x1D720;</mtext></math>=<span>1D720</span></span>
+ <span><math><mtext>&#x1D721;</mtext></math>=<span>1D721</span></span><br/>
+ <span><math><mtext>&#x1D722;</mtext></math>=<span>1D722</span></span>
+ <span><math><mtext>&#x1D723;</mtext></math>=<span>1D723</span></span>
+ <span><math><mtext>&#x1D724;</mtext></math>=<span>1D724</span></span>
+ <span><math><mtext>&#x1D725;</mtext></math>=<span>1D725</span></span>
+ <span><math><mtext>&#x1D726;</mtext></math>=<span>1D726</span></span>
+ <span><math><mtext>&#x1D727;</mtext></math>=<span>1D727</span></span>
+ <span><math><mtext>&#x1D728;</mtext></math>=<span>1D728</span></span>
+ <span><math><mtext>&#x1D729;</mtext></math>=<span>1D729</span></span>
+ <span><math><mtext>&#x1D72A;</mtext></math>=<span>1D72A</span></span>
+ <span><math><mtext>&#x1D72B;</mtext></math>=<span>1D72B</span></span><br/>
+ <span><math><mtext>&#x1D72C;</mtext></math>=<span>1D72C</span></span>
+ <span><math><mtext>&#x1D72E;</mtext></math>=<span>1D72E</span></span>
+ <span><math><mtext>&#x1D72F;</mtext></math>=<span>1D72F</span></span>
+ <span><math><mtext>&#x1D730;</mtext></math>=<span>1D730</span></span>
+ <span><math><mtext>&#x1D731;</mtext></math>=<span>1D731</span></span>
+ <span><math><mtext>&#x1D732;</mtext></math>=<span>1D732</span></span>
+ <span><math><mtext>&#x1D733;</mtext></math>=<span>1D733</span></span>
+ <span><math><mtext>&#x1D734;</mtext></math>=<span>1D734</span></span>
+ <span><math><mtext>&#x1D736;</mtext></math>=<span>1D736</span></span>
+ <span><math><mtext>&#x1D737;</mtext></math>=<span>1D737</span></span><br/>
+ <span><math><mtext>&#x1D738;</mtext></math>=<span>1D738</span></span>
+ <span><math><mtext>&#x1D739;</mtext></math>=<span>1D739</span></span>
+ <span><math><mtext>&#x1D73A;</mtext></math>=<span>1D73A</span></span>
+ <span><math><mtext>&#x1D73B;</mtext></math>=<span>1D73B</span></span>
+ <span><math><mtext>&#x1D73C;</mtext></math>=<span>1D73C</span></span>
+ <span><math><mtext>&#x1D73D;</mtext></math>=<span>1D73D</span></span>
+ <span><math><mtext>&#x1D73E;</mtext></math>=<span>1D73E</span></span>
+ <span><math><mtext>&#x1D73F;</mtext></math>=<span>1D73F</span></span>
+ <span><math><mtext>&#x1D740;</mtext></math>=<span>1D740</span></span>
+ <span><math><mtext>&#x1D741;</mtext></math>=<span>1D741</span></span><br/>
+ <span><math><mtext>&#x1D742;</mtext></math>=<span>1D742</span></span>
+ <span><math><mtext>&#x1D743;</mtext></math>=<span>1D743</span></span>
+ <span><math><mtext>&#x1D744;</mtext></math>=<span>1D744</span></span>
+ <span><math><mtext>&#x1D745;</mtext></math>=<span>1D745</span></span>
+ <span><math><mtext>&#x1D746;</mtext></math>=<span>1D746</span></span>
+ <span><math><mtext>&#x1D747;</mtext></math>=<span>1D747</span></span>
+ <span><math><mtext>&#x1D748;</mtext></math>=<span>1D748</span></span>
+ <span><math><mtext>&#x1D749;</mtext></math>=<span>1D749</span></span>
+ <span><math><mtext>&#x1D74A;</mtext></math>=<span>1D74A</span></span>
+ <span><math><mtext>&#x1D74B;</mtext></math>=<span>1D74B</span></span><br/>
+ <span><math><mtext>&#x1D74C;</mtext></math>=<span>1D74C</span></span>
+ <span><math><mtext>&#x1D74D;</mtext></math>=<span>1D74D</span></span>
+ <span><math><mtext>&#x1D74E;</mtext></math>=<span>1D74E</span></span>
+ <span><math><mtext>&#x1D751;</mtext></math>=<span>1D751</span></span>
+ <span><math><mtext>&#x1D753;</mtext></math>=<span>1D753</span></span>
+ <span><math><mtext>&#x1D755;</mtext></math>=<span>1D755</span></span>
+ <span><math><mtext>&#x1D752;</mtext></math>=<span>1D752</span></span>
+ <span><math><mtext>&#x1D754;</mtext></math>=<span>1D754</span></span>
+ <span><math><mtext>&#x1D72D;</mtext></math>=<span>1D72D</span></span>
+ <span><math><mtext>&#x1D750;</mtext></math>=<span>1D750</span></span><br/>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-italic.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-italic.html
index b115fec47a6..640baf34da8 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-italic.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-italic.html
@@ -5,7 +5,7 @@
<title>mathvariant bold-italic</title>
<link rel="help" href="http://www.mathml-association.org/MathMLinHTML5/S2.html#SS3.SSS1.tab2"/>
<link rel="match" href="mathvariant-bold-italic-ref.html"/>
-<meta name="assert" content="Verify that a single-char <mi> with a bold-italic mathvariant is equivalent to an <mi> with the transformed unicode character.">
+<meta name="assert" content="Verify that a single-char <mtext> with a bold-italic mathvariant is equivalent to an <mtext> with the transformed unicode character.">
<style>
@font-face {
font-family: TestFont;
@@ -26,115 +26,115 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi mathvariant="bold-italic">&#x2202;</mi></math>=<span>1D74F</span></span>
- <span><math><mi mathvariant="bold-italic">&#x2207;</mi></math>=<span>1D735</span></span>
- <span><math><mi mathvariant="bold-italic">&#x41;</mi></math>=<span>1D468</span></span>
- <span><math><mi mathvariant="bold-italic">&#x42;</mi></math>=<span>1D469</span></span>
- <span><math><mi mathvariant="bold-italic">&#x43;</mi></math>=<span>1D46A</span></span>
- <span><math><mi mathvariant="bold-italic">&#x44;</mi></math>=<span>1D46B</span></span>
- <span><math><mi mathvariant="bold-italic">&#x45;</mi></math>=<span>1D46C</span></span>
- <span><math><mi mathvariant="bold-italic">&#x46;</mi></math>=<span>1D46D</span></span>
- <span><math><mi mathvariant="bold-italic">&#x47;</mi></math>=<span>1D46E</span></span>
- <span><math><mi mathvariant="bold-italic">&#x48;</mi></math>=<span>1D46F</span></span><br/>
- <span><math><mi mathvariant="bold-italic">&#x49;</mi></math>=<span>1D470</span></span>
- <span><math><mi mathvariant="bold-italic">&#x4A;</mi></math>=<span>1D471</span></span>
- <span><math><mi mathvariant="bold-italic">&#x4B;</mi></math>=<span>1D472</span></span>
- <span><math><mi mathvariant="bold-italic">&#x4C;</mi></math>=<span>1D473</span></span>
- <span><math><mi mathvariant="bold-italic">&#x4D;</mi></math>=<span>1D474</span></span>
- <span><math><mi mathvariant="bold-italic">&#x4E;</mi></math>=<span>1D475</span></span>
- <span><math><mi mathvariant="bold-italic">&#x4F;</mi></math>=<span>1D476</span></span>
- <span><math><mi mathvariant="bold-italic">&#x50;</mi></math>=<span>1D477</span></span>
- <span><math><mi mathvariant="bold-italic">&#x51;</mi></math>=<span>1D478</span></span>
- <span><math><mi mathvariant="bold-italic">&#x52;</mi></math>=<span>1D479</span></span><br/>
- <span><math><mi mathvariant="bold-italic">&#x53;</mi></math>=<span>1D47A</span></span>
- <span><math><mi mathvariant="bold-italic">&#x54;</mi></math>=<span>1D47B</span></span>
- <span><math><mi mathvariant="bold-italic">&#x55;</mi></math>=<span>1D47C</span></span>
- <span><math><mi mathvariant="bold-italic">&#x56;</mi></math>=<span>1D47D</span></span>
- <span><math><mi mathvariant="bold-italic">&#x57;</mi></math>=<span>1D47E</span></span>
- <span><math><mi mathvariant="bold-italic">&#x58;</mi></math>=<span>1D47F</span></span>
- <span><math><mi mathvariant="bold-italic">&#x59;</mi></math>=<span>1D480</span></span>
- <span><math><mi mathvariant="bold-italic">&#x5A;</mi></math>=<span>1D481</span></span>
- <span><math><mi mathvariant="bold-italic">&#x61;</mi></math>=<span>1D482</span></span>
- <span><math><mi mathvariant="bold-italic">&#x62;</mi></math>=<span>1D483</span></span><br/>
- <span><math><mi mathvariant="bold-italic">&#x63;</mi></math>=<span>1D484</span></span>
- <span><math><mi mathvariant="bold-italic">&#x64;</mi></math>=<span>1D485</span></span>
- <span><math><mi mathvariant="bold-italic">&#x65;</mi></math>=<span>1D486</span></span>
- <span><math><mi mathvariant="bold-italic">&#x66;</mi></math>=<span>1D487</span></span>
- <span><math><mi mathvariant="bold-italic">&#x67;</mi></math>=<span>1D488</span></span>
- <span><math><mi mathvariant="bold-italic">&#x68;</mi></math>=<span>1D489</span></span>
- <span><math><mi mathvariant="bold-italic">&#x69;</mi></math>=<span>1D48A</span></span>
- <span><math><mi mathvariant="bold-italic">&#x6A;</mi></math>=<span>1D48B</span></span>
- <span><math><mi mathvariant="bold-italic">&#x6B;</mi></math>=<span>1D48C</span></span>
- <span><math><mi mathvariant="bold-italic">&#x6C;</mi></math>=<span>1D48D</span></span><br/>
- <span><math><mi mathvariant="bold-italic">&#x6D;</mi></math>=<span>1D48E</span></span>
- <span><math><mi mathvariant="bold-italic">&#x6E;</mi></math>=<span>1D48F</span></span>
- <span><math><mi mathvariant="bold-italic">&#x6F;</mi></math>=<span>1D490</span></span>
- <span><math><mi mathvariant="bold-italic">&#x70;</mi></math>=<span>1D491</span></span>
- <span><math><mi mathvariant="bold-italic">&#x71;</mi></math>=<span>1D492</span></span>
- <span><math><mi mathvariant="bold-italic">&#x72;</mi></math>=<span>1D493</span></span>
- <span><math><mi mathvariant="bold-italic">&#x73;</mi></math>=<span>1D494</span></span>
- <span><math><mi mathvariant="bold-italic">&#x74;</mi></math>=<span>1D495</span></span>
- <span><math><mi mathvariant="bold-italic">&#x75;</mi></math>=<span>1D496</span></span>
- <span><math><mi mathvariant="bold-italic">&#x76;</mi></math>=<span>1D497</span></span><br/>
- <span><math><mi mathvariant="bold-italic">&#x77;</mi></math>=<span>1D498</span></span>
- <span><math><mi mathvariant="bold-italic">&#x78;</mi></math>=<span>1D499</span></span>
- <span><math><mi mathvariant="bold-italic">&#x79;</mi></math>=<span>1D49A</span></span>
- <span><math><mi mathvariant="bold-italic">&#x7A;</mi></math>=<span>1D49B</span></span>
- <span><math><mi mathvariant="bold-italic">&#x391;</mi></math>=<span>1D71C</span></span>
- <span><math><mi mathvariant="bold-italic">&#x392;</mi></math>=<span>1D71D</span></span>
- <span><math><mi mathvariant="bold-italic">&#x393;</mi></math>=<span>1D71E</span></span>
- <span><math><mi mathvariant="bold-italic">&#x394;</mi></math>=<span>1D71F</span></span>
- <span><math><mi mathvariant="bold-italic">&#x395;</mi></math>=<span>1D720</span></span>
- <span><math><mi mathvariant="bold-italic">&#x396;</mi></math>=<span>1D721</span></span><br/>
- <span><math><mi mathvariant="bold-italic">&#x397;</mi></math>=<span>1D722</span></span>
- <span><math><mi mathvariant="bold-italic">&#x398;</mi></math>=<span>1D723</span></span>
- <span><math><mi mathvariant="bold-italic">&#x399;</mi></math>=<span>1D724</span></span>
- <span><math><mi mathvariant="bold-italic">&#x39A;</mi></math>=<span>1D725</span></span>
- <span><math><mi mathvariant="bold-italic">&#x39B;</mi></math>=<span>1D726</span></span>
- <span><math><mi mathvariant="bold-italic">&#x39C;</mi></math>=<span>1D727</span></span>
- <span><math><mi mathvariant="bold-italic">&#x39D;</mi></math>=<span>1D728</span></span>
- <span><math><mi mathvariant="bold-italic">&#x39E;</mi></math>=<span>1D729</span></span>
- <span><math><mi mathvariant="bold-italic">&#x39F;</mi></math>=<span>1D72A</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3A0;</mi></math>=<span>1D72B</span></span><br/>
- <span><math><mi mathvariant="bold-italic">&#x3A1;</mi></math>=<span>1D72C</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3A3;</mi></math>=<span>1D72E</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3A4;</mi></math>=<span>1D72F</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3A5;</mi></math>=<span>1D730</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3A6;</mi></math>=<span>1D731</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3A7;</mi></math>=<span>1D732</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3A8;</mi></math>=<span>1D733</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3A9;</mi></math>=<span>1D734</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3B1;</mi></math>=<span>1D736</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3B2;</mi></math>=<span>1D737</span></span><br/>
- <span><math><mi mathvariant="bold-italic">&#x3B3;</mi></math>=<span>1D738</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3B4;</mi></math>=<span>1D739</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3B5;</mi></math>=<span>1D73A</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3B6;</mi></math>=<span>1D73B</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3B7;</mi></math>=<span>1D73C</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3B8;</mi></math>=<span>1D73D</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3B9;</mi></math>=<span>1D73E</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3BA;</mi></math>=<span>1D73F</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3BB;</mi></math>=<span>1D740</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3BC;</mi></math>=<span>1D741</span></span><br/>
- <span><math><mi mathvariant="bold-italic">&#x3BD;</mi></math>=<span>1D742</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3BE;</mi></math>=<span>1D743</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3BF;</mi></math>=<span>1D744</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3C0;</mi></math>=<span>1D745</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3C1;</mi></math>=<span>1D746</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3C2;</mi></math>=<span>1D747</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3C3;</mi></math>=<span>1D748</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3C4;</mi></math>=<span>1D749</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3C5;</mi></math>=<span>1D74A</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3C6;</mi></math>=<span>1D74B</span></span><br/>
- <span><math><mi mathvariant="bold-italic">&#x3C7;</mi></math>=<span>1D74C</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3C8;</mi></math>=<span>1D74D</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3C9;</mi></math>=<span>1D74E</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3D1;</mi></math>=<span>1D751</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3D5;</mi></math>=<span>1D753</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3D6;</mi></math>=<span>1D755</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3F0;</mi></math>=<span>1D752</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3F1;</mi></math>=<span>1D754</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3F4;</mi></math>=<span>1D72D</span></span>
- <span><math><mi mathvariant="bold-italic">&#x3F5;</mi></math>=<span>1D750</span></span><br/>
+ <span><math><mtext mathvariant="bold-italic">&#x2202;</mtext></math>=<span>1D74F</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x2207;</mtext></math>=<span>1D735</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x41;</mtext></math>=<span>1D468</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x42;</mtext></math>=<span>1D469</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x43;</mtext></math>=<span>1D46A</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x44;</mtext></math>=<span>1D46B</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x45;</mtext></math>=<span>1D46C</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x46;</mtext></math>=<span>1D46D</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x47;</mtext></math>=<span>1D46E</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x48;</mtext></math>=<span>1D46F</span></span><br/>
+ <span><math><mtext mathvariant="bold-italic">&#x49;</mtext></math>=<span>1D470</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x4A;</mtext></math>=<span>1D471</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x4B;</mtext></math>=<span>1D472</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x4C;</mtext></math>=<span>1D473</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x4D;</mtext></math>=<span>1D474</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x4E;</mtext></math>=<span>1D475</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x4F;</mtext></math>=<span>1D476</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x50;</mtext></math>=<span>1D477</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x51;</mtext></math>=<span>1D478</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x52;</mtext></math>=<span>1D479</span></span><br/>
+ <span><math><mtext mathvariant="bold-italic">&#x53;</mtext></math>=<span>1D47A</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x54;</mtext></math>=<span>1D47B</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x55;</mtext></math>=<span>1D47C</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x56;</mtext></math>=<span>1D47D</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x57;</mtext></math>=<span>1D47E</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x58;</mtext></math>=<span>1D47F</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x59;</mtext></math>=<span>1D480</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x5A;</mtext></math>=<span>1D481</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x61;</mtext></math>=<span>1D482</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x62;</mtext></math>=<span>1D483</span></span><br/>
+ <span><math><mtext mathvariant="bold-italic">&#x63;</mtext></math>=<span>1D484</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x64;</mtext></math>=<span>1D485</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x65;</mtext></math>=<span>1D486</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x66;</mtext></math>=<span>1D487</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x67;</mtext></math>=<span>1D488</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x68;</mtext></math>=<span>1D489</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x69;</mtext></math>=<span>1D48A</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x6A;</mtext></math>=<span>1D48B</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x6B;</mtext></math>=<span>1D48C</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x6C;</mtext></math>=<span>1D48D</span></span><br/>
+ <span><math><mtext mathvariant="bold-italic">&#x6D;</mtext></math>=<span>1D48E</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x6E;</mtext></math>=<span>1D48F</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x6F;</mtext></math>=<span>1D490</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x70;</mtext></math>=<span>1D491</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x71;</mtext></math>=<span>1D492</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x72;</mtext></math>=<span>1D493</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x73;</mtext></math>=<span>1D494</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x74;</mtext></math>=<span>1D495</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x75;</mtext></math>=<span>1D496</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x76;</mtext></math>=<span>1D497</span></span><br/>
+ <span><math><mtext mathvariant="bold-italic">&#x77;</mtext></math>=<span>1D498</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x78;</mtext></math>=<span>1D499</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x79;</mtext></math>=<span>1D49A</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x7A;</mtext></math>=<span>1D49B</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x391;</mtext></math>=<span>1D71C</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x392;</mtext></math>=<span>1D71D</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x393;</mtext></math>=<span>1D71E</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x394;</mtext></math>=<span>1D71F</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x395;</mtext></math>=<span>1D720</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x396;</mtext></math>=<span>1D721</span></span><br/>
+ <span><math><mtext mathvariant="bold-italic">&#x397;</mtext></math>=<span>1D722</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x398;</mtext></math>=<span>1D723</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x399;</mtext></math>=<span>1D724</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x39A;</mtext></math>=<span>1D725</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x39B;</mtext></math>=<span>1D726</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x39C;</mtext></math>=<span>1D727</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x39D;</mtext></math>=<span>1D728</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x39E;</mtext></math>=<span>1D729</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x39F;</mtext></math>=<span>1D72A</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3A0;</mtext></math>=<span>1D72B</span></span><br/>
+ <span><math><mtext mathvariant="bold-italic">&#x3A1;</mtext></math>=<span>1D72C</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3A3;</mtext></math>=<span>1D72E</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3A4;</mtext></math>=<span>1D72F</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3A5;</mtext></math>=<span>1D730</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3A6;</mtext></math>=<span>1D731</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3A7;</mtext></math>=<span>1D732</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3A8;</mtext></math>=<span>1D733</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3A9;</mtext></math>=<span>1D734</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3B1;</mtext></math>=<span>1D736</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3B2;</mtext></math>=<span>1D737</span></span><br/>
+ <span><math><mtext mathvariant="bold-italic">&#x3B3;</mtext></math>=<span>1D738</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3B4;</mtext></math>=<span>1D739</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3B5;</mtext></math>=<span>1D73A</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3B6;</mtext></math>=<span>1D73B</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3B7;</mtext></math>=<span>1D73C</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3B8;</mtext></math>=<span>1D73D</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3B9;</mtext></math>=<span>1D73E</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3BA;</mtext></math>=<span>1D73F</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3BB;</mtext></math>=<span>1D740</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3BC;</mtext></math>=<span>1D741</span></span><br/>
+ <span><math><mtext mathvariant="bold-italic">&#x3BD;</mtext></math>=<span>1D742</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3BE;</mtext></math>=<span>1D743</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3BF;</mtext></math>=<span>1D744</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3C0;</mtext></math>=<span>1D745</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3C1;</mtext></math>=<span>1D746</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3C2;</mtext></math>=<span>1D747</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3C3;</mtext></math>=<span>1D748</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3C4;</mtext></math>=<span>1D749</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3C5;</mtext></math>=<span>1D74A</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3C6;</mtext></math>=<span>1D74B</span></span><br/>
+ <span><math><mtext mathvariant="bold-italic">&#x3C7;</mtext></math>=<span>1D74C</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3C8;</mtext></math>=<span>1D74D</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3C9;</mtext></math>=<span>1D74E</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3D1;</mtext></math>=<span>1D751</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3D5;</mtext></math>=<span>1D753</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3D6;</mtext></math>=<span>1D755</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3F0;</mtext></math>=<span>1D752</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3F1;</mtext></math>=<span>1D754</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3F4;</mtext></math>=<span>1D72D</span></span>
+ <span><math><mtext mathvariant="bold-italic">&#x3F5;</mtext></math>=<span>1D750</span></span><br/>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-ref.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-ref.html
index f9bbef64a04..11cb2de250d 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-ref.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-ref.html
@@ -23,127 +23,127 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi>&#x1D6DB;</mi></math>=<span>1D6DB</span></span>
- <span><math><mi>&#x1D6C1;</mi></math>=<span>1D6C1</span></span>
- <span><math><mi>&#x1D7CE;</mi></math>=<span>1D7CE</span></span>
- <span><math><mi>&#x1D7CF;</mi></math>=<span>1D7CF</span></span>
- <span><math><mi>&#x1D7D0;</mi></math>=<span>1D7D0</span></span>
- <span><math><mi>&#x1D7D1;</mi></math>=<span>1D7D1</span></span>
- <span><math><mi>&#x1D7D2;</mi></math>=<span>1D7D2</span></span>
- <span><math><mi>&#x1D7D3;</mi></math>=<span>1D7D3</span></span>
- <span><math><mi>&#x1D7D4;</mi></math>=<span>1D7D4</span></span>
- <span><math><mi>&#x1D7D5;</mi></math>=<span>1D7D5</span></span><br/>
- <span><math><mi>&#x1D7D6;</mi></math>=<span>1D7D6</span></span>
- <span><math><mi>&#x1D7D7;</mi></math>=<span>1D7D7</span></span>
- <span><math><mi>&#x1D400;</mi></math>=<span>1D400</span></span>
- <span><math><mi>&#x1D401;</mi></math>=<span>1D401</span></span>
- <span><math><mi>&#x1D402;</mi></math>=<span>1D402</span></span>
- <span><math><mi>&#x1D403;</mi></math>=<span>1D403</span></span>
- <span><math><mi>&#x1D404;</mi></math>=<span>1D404</span></span>
- <span><math><mi>&#x1D405;</mi></math>=<span>1D405</span></span>
- <span><math><mi>&#x1D406;</mi></math>=<span>1D406</span></span>
- <span><math><mi>&#x1D407;</mi></math>=<span>1D407</span></span><br/>
- <span><math><mi>&#x1D408;</mi></math>=<span>1D408</span></span>
- <span><math><mi>&#x1D409;</mi></math>=<span>1D409</span></span>
- <span><math><mi>&#x1D40A;</mi></math>=<span>1D40A</span></span>
- <span><math><mi>&#x1D40B;</mi></math>=<span>1D40B</span></span>
- <span><math><mi>&#x1D40C;</mi></math>=<span>1D40C</span></span>
- <span><math><mi>&#x1D40D;</mi></math>=<span>1D40D</span></span>
- <span><math><mi>&#x1D40E;</mi></math>=<span>1D40E</span></span>
- <span><math><mi>&#x1D40F;</mi></math>=<span>1D40F</span></span>
- <span><math><mi>&#x1D410;</mi></math>=<span>1D410</span></span>
- <span><math><mi>&#x1D411;</mi></math>=<span>1D411</span></span><br/>
- <span><math><mi>&#x1D412;</mi></math>=<span>1D412</span></span>
- <span><math><mi>&#x1D413;</mi></math>=<span>1D413</span></span>
- <span><math><mi>&#x1D414;</mi></math>=<span>1D414</span></span>
- <span><math><mi>&#x1D415;</mi></math>=<span>1D415</span></span>
- <span><math><mi>&#x1D416;</mi></math>=<span>1D416</span></span>
- <span><math><mi>&#x1D417;</mi></math>=<span>1D417</span></span>
- <span><math><mi>&#x1D418;</mi></math>=<span>1D418</span></span>
- <span><math><mi>&#x1D419;</mi></math>=<span>1D419</span></span>
- <span><math><mi>&#x1D41A;</mi></math>=<span>1D41A</span></span>
- <span><math><mi>&#x1D41B;</mi></math>=<span>1D41B</span></span><br/>
- <span><math><mi>&#x1D41C;</mi></math>=<span>1D41C</span></span>
- <span><math><mi>&#x1D41D;</mi></math>=<span>1D41D</span></span>
- <span><math><mi>&#x1D41E;</mi></math>=<span>1D41E</span></span>
- <span><math><mi>&#x1D41F;</mi></math>=<span>1D41F</span></span>
- <span><math><mi>&#x1D420;</mi></math>=<span>1D420</span></span>
- <span><math><mi>&#x1D421;</mi></math>=<span>1D421</span></span>
- <span><math><mi>&#x1D422;</mi></math>=<span>1D422</span></span>
- <span><math><mi>&#x1D423;</mi></math>=<span>1D423</span></span>
- <span><math><mi>&#x1D424;</mi></math>=<span>1D424</span></span>
- <span><math><mi>&#x1D425;</mi></math>=<span>1D425</span></span><br/>
- <span><math><mi>&#x1D426;</mi></math>=<span>1D426</span></span>
- <span><math><mi>&#x1D427;</mi></math>=<span>1D427</span></span>
- <span><math><mi>&#x1D428;</mi></math>=<span>1D428</span></span>
- <span><math><mi>&#x1D429;</mi></math>=<span>1D429</span></span>
- <span><math><mi>&#x1D42A;</mi></math>=<span>1D42A</span></span>
- <span><math><mi>&#x1D42B;</mi></math>=<span>1D42B</span></span>
- <span><math><mi>&#x1D42C;</mi></math>=<span>1D42C</span></span>
- <span><math><mi>&#x1D42D;</mi></math>=<span>1D42D</span></span>
- <span><math><mi>&#x1D42E;</mi></math>=<span>1D42E</span></span>
- <span><math><mi>&#x1D42F;</mi></math>=<span>1D42F</span></span><br/>
- <span><math><mi>&#x1D430;</mi></math>=<span>1D430</span></span>
- <span><math><mi>&#x1D431;</mi></math>=<span>1D431</span></span>
- <span><math><mi>&#x1D432;</mi></math>=<span>1D432</span></span>
- <span><math><mi>&#x1D433;</mi></math>=<span>1D433</span></span>
- <span><math><mi>&#x1D6A8;</mi></math>=<span>1D6A8</span></span>
- <span><math><mi>&#x1D6A9;</mi></math>=<span>1D6A9</span></span>
- <span><math><mi>&#x1D6AA;</mi></math>=<span>1D6AA</span></span>
- <span><math><mi>&#x1D6AB;</mi></math>=<span>1D6AB</span></span>
- <span><math><mi>&#x1D6AC;</mi></math>=<span>1D6AC</span></span>
- <span><math><mi>&#x1D6AD;</mi></math>=<span>1D6AD</span></span><br/>
- <span><math><mi>&#x1D6AE;</mi></math>=<span>1D6AE</span></span>
- <span><math><mi>&#x1D6AF;</mi></math>=<span>1D6AF</span></span>
- <span><math><mi>&#x1D6B0;</mi></math>=<span>1D6B0</span></span>
- <span><math><mi>&#x1D6B1;</mi></math>=<span>1D6B1</span></span>
- <span><math><mi>&#x1D6B2;</mi></math>=<span>1D6B2</span></span>
- <span><math><mi>&#x1D6B3;</mi></math>=<span>1D6B3</span></span>
- <span><math><mi>&#x1D6B4;</mi></math>=<span>1D6B4</span></span>
- <span><math><mi>&#x1D6B5;</mi></math>=<span>1D6B5</span></span>
- <span><math><mi>&#x1D6B6;</mi></math>=<span>1D6B6</span></span>
- <span><math><mi>&#x1D6B7;</mi></math>=<span>1D6B7</span></span><br/>
- <span><math><mi>&#x1D6B8;</mi></math>=<span>1D6B8</span></span>
- <span><math><mi>&#x1D6BA;</mi></math>=<span>1D6BA</span></span>
- <span><math><mi>&#x1D6BB;</mi></math>=<span>1D6BB</span></span>
- <span><math><mi>&#x1D6BC;</mi></math>=<span>1D6BC</span></span>
- <span><math><mi>&#x1D6BD;</mi></math>=<span>1D6BD</span></span>
- <span><math><mi>&#x1D6BE;</mi></math>=<span>1D6BE</span></span>
- <span><math><mi>&#x1D6BF;</mi></math>=<span>1D6BF</span></span>
- <span><math><mi>&#x1D6C0;</mi></math>=<span>1D6C0</span></span>
- <span><math><mi>&#x1D6C2;</mi></math>=<span>1D6C2</span></span>
- <span><math><mi>&#x1D6C3;</mi></math>=<span>1D6C3</span></span><br/>
- <span><math><mi>&#x1D6C4;</mi></math>=<span>1D6C4</span></span>
- <span><math><mi>&#x1D6C5;</mi></math>=<span>1D6C5</span></span>
- <span><math><mi>&#x1D6C6;</mi></math>=<span>1D6C6</span></span>
- <span><math><mi>&#x1D6C7;</mi></math>=<span>1D6C7</span></span>
- <span><math><mi>&#x1D6C8;</mi></math>=<span>1D6C8</span></span>
- <span><math><mi>&#x1D6C9;</mi></math>=<span>1D6C9</span></span>
- <span><math><mi>&#x1D6CA;</mi></math>=<span>1D6CA</span></span>
- <span><math><mi>&#x1D6CB;</mi></math>=<span>1D6CB</span></span>
- <span><math><mi>&#x1D6CC;</mi></math>=<span>1D6CC</span></span>
- <span><math><mi>&#x1D6CD;</mi></math>=<span>1D6CD</span></span><br/>
- <span><math><mi>&#x1D6CE;</mi></math>=<span>1D6CE</span></span>
- <span><math><mi>&#x1D6CF;</mi></math>=<span>1D6CF</span></span>
- <span><math><mi>&#x1D6D0;</mi></math>=<span>1D6D0</span></span>
- <span><math><mi>&#x1D6D1;</mi></math>=<span>1D6D1</span></span>
- <span><math><mi>&#x1D6D2;</mi></math>=<span>1D6D2</span></span>
- <span><math><mi>&#x1D6D3;</mi></math>=<span>1D6D3</span></span>
- <span><math><mi>&#x1D6D4;</mi></math>=<span>1D6D4</span></span>
- <span><math><mi>&#x1D6D5;</mi></math>=<span>1D6D5</span></span>
- <span><math><mi>&#x1D6D6;</mi></math>=<span>1D6D6</span></span>
- <span><math><mi>&#x1D6D7;</mi></math>=<span>1D6D7</span></span><br/>
- <span><math><mi>&#x1D6D8;</mi></math>=<span>1D6D8</span></span>
- <span><math><mi>&#x1D6D9;</mi></math>=<span>1D6D9</span></span>
- <span><math><mi>&#x1D6DA;</mi></math>=<span>1D6DA</span></span>
- <span><math><mi>&#x1D6DD;</mi></math>=<span>1D6DD</span></span>
- <span><math><mi>&#x1D6DF;</mi></math>=<span>1D6DF</span></span>
- <span><math><mi>&#x1D6E1;</mi></math>=<span>1D6E1</span></span>
- <span><math><mi>&#x1D7CA;</mi></math>=<span>1D7CA</span></span>
- <span><math><mi>&#x1D7CB;</mi></math>=<span>1D7CB</span></span>
- <span><math><mi>&#x1D6DE;</mi></math>=<span>1D6DE</span></span>
- <span><math><mi>&#x1D6E0;</mi></math>=<span>1D6E0</span></span><br/>
- <span><math><mi>&#x1D6B9;</mi></math>=<span>1D6B9</span></span>
- <span><math><mi>&#x1D6DC;</mi></math>=<span>1D6DC</span></span>
+ <span><math><mtext>&#x1D6DB;</mtext></math>=<span>1D6DB</span></span>
+ <span><math><mtext>&#x1D6C1;</mtext></math>=<span>1D6C1</span></span>
+ <span><math><mtext>&#x1D7CE;</mtext></math>=<span>1D7CE</span></span>
+ <span><math><mtext>&#x1D7CF;</mtext></math>=<span>1D7CF</span></span>
+ <span><math><mtext>&#x1D7D0;</mtext></math>=<span>1D7D0</span></span>
+ <span><math><mtext>&#x1D7D1;</mtext></math>=<span>1D7D1</span></span>
+ <span><math><mtext>&#x1D7D2;</mtext></math>=<span>1D7D2</span></span>
+ <span><math><mtext>&#x1D7D3;</mtext></math>=<span>1D7D3</span></span>
+ <span><math><mtext>&#x1D7D4;</mtext></math>=<span>1D7D4</span></span>
+ <span><math><mtext>&#x1D7D5;</mtext></math>=<span>1D7D5</span></span><br/>
+ <span><math><mtext>&#x1D7D6;</mtext></math>=<span>1D7D6</span></span>
+ <span><math><mtext>&#x1D7D7;</mtext></math>=<span>1D7D7</span></span>
+ <span><math><mtext>&#x1D400;</mtext></math>=<span>1D400</span></span>
+ <span><math><mtext>&#x1D401;</mtext></math>=<span>1D401</span></span>
+ <span><math><mtext>&#x1D402;</mtext></math>=<span>1D402</span></span>
+ <span><math><mtext>&#x1D403;</mtext></math>=<span>1D403</span></span>
+ <span><math><mtext>&#x1D404;</mtext></math>=<span>1D404</span></span>
+ <span><math><mtext>&#x1D405;</mtext></math>=<span>1D405</span></span>
+ <span><math><mtext>&#x1D406;</mtext></math>=<span>1D406</span></span>
+ <span><math><mtext>&#x1D407;</mtext></math>=<span>1D407</span></span><br/>
+ <span><math><mtext>&#x1D408;</mtext></math>=<span>1D408</span></span>
+ <span><math><mtext>&#x1D409;</mtext></math>=<span>1D409</span></span>
+ <span><math><mtext>&#x1D40A;</mtext></math>=<span>1D40A</span></span>
+ <span><math><mtext>&#x1D40B;</mtext></math>=<span>1D40B</span></span>
+ <span><math><mtext>&#x1D40C;</mtext></math>=<span>1D40C</span></span>
+ <span><math><mtext>&#x1D40D;</mtext></math>=<span>1D40D</span></span>
+ <span><math><mtext>&#x1D40E;</mtext></math>=<span>1D40E</span></span>
+ <span><math><mtext>&#x1D40F;</mtext></math>=<span>1D40F</span></span>
+ <span><math><mtext>&#x1D410;</mtext></math>=<span>1D410</span></span>
+ <span><math><mtext>&#x1D411;</mtext></math>=<span>1D411</span></span><br/>
+ <span><math><mtext>&#x1D412;</mtext></math>=<span>1D412</span></span>
+ <span><math><mtext>&#x1D413;</mtext></math>=<span>1D413</span></span>
+ <span><math><mtext>&#x1D414;</mtext></math>=<span>1D414</span></span>
+ <span><math><mtext>&#x1D415;</mtext></math>=<span>1D415</span></span>
+ <span><math><mtext>&#x1D416;</mtext></math>=<span>1D416</span></span>
+ <span><math><mtext>&#x1D417;</mtext></math>=<span>1D417</span></span>
+ <span><math><mtext>&#x1D418;</mtext></math>=<span>1D418</span></span>
+ <span><math><mtext>&#x1D419;</mtext></math>=<span>1D419</span></span>
+ <span><math><mtext>&#x1D41A;</mtext></math>=<span>1D41A</span></span>
+ <span><math><mtext>&#x1D41B;</mtext></math>=<span>1D41B</span></span><br/>
+ <span><math><mtext>&#x1D41C;</mtext></math>=<span>1D41C</span></span>
+ <span><math><mtext>&#x1D41D;</mtext></math>=<span>1D41D</span></span>
+ <span><math><mtext>&#x1D41E;</mtext></math>=<span>1D41E</span></span>
+ <span><math><mtext>&#x1D41F;</mtext></math>=<span>1D41F</span></span>
+ <span><math><mtext>&#x1D420;</mtext></math>=<span>1D420</span></span>
+ <span><math><mtext>&#x1D421;</mtext></math>=<span>1D421</span></span>
+ <span><math><mtext>&#x1D422;</mtext></math>=<span>1D422</span></span>
+ <span><math><mtext>&#x1D423;</mtext></math>=<span>1D423</span></span>
+ <span><math><mtext>&#x1D424;</mtext></math>=<span>1D424</span></span>
+ <span><math><mtext>&#x1D425;</mtext></math>=<span>1D425</span></span><br/>
+ <span><math><mtext>&#x1D426;</mtext></math>=<span>1D426</span></span>
+ <span><math><mtext>&#x1D427;</mtext></math>=<span>1D427</span></span>
+ <span><math><mtext>&#x1D428;</mtext></math>=<span>1D428</span></span>
+ <span><math><mtext>&#x1D429;</mtext></math>=<span>1D429</span></span>
+ <span><math><mtext>&#x1D42A;</mtext></math>=<span>1D42A</span></span>
+ <span><math><mtext>&#x1D42B;</mtext></math>=<span>1D42B</span></span>
+ <span><math><mtext>&#x1D42C;</mtext></math>=<span>1D42C</span></span>
+ <span><math><mtext>&#x1D42D;</mtext></math>=<span>1D42D</span></span>
+ <span><math><mtext>&#x1D42E;</mtext></math>=<span>1D42E</span></span>
+ <span><math><mtext>&#x1D42F;</mtext></math>=<span>1D42F</span></span><br/>
+ <span><math><mtext>&#x1D430;</mtext></math>=<span>1D430</span></span>
+ <span><math><mtext>&#x1D431;</mtext></math>=<span>1D431</span></span>
+ <span><math><mtext>&#x1D432;</mtext></math>=<span>1D432</span></span>
+ <span><math><mtext>&#x1D433;</mtext></math>=<span>1D433</span></span>
+ <span><math><mtext>&#x1D6A8;</mtext></math>=<span>1D6A8</span></span>
+ <span><math><mtext>&#x1D6A9;</mtext></math>=<span>1D6A9</span></span>
+ <span><math><mtext>&#x1D6AA;</mtext></math>=<span>1D6AA</span></span>
+ <span><math><mtext>&#x1D6AB;</mtext></math>=<span>1D6AB</span></span>
+ <span><math><mtext>&#x1D6AC;</mtext></math>=<span>1D6AC</span></span>
+ <span><math><mtext>&#x1D6AD;</mtext></math>=<span>1D6AD</span></span><br/>
+ <span><math><mtext>&#x1D6AE;</mtext></math>=<span>1D6AE</span></span>
+ <span><math><mtext>&#x1D6AF;</mtext></math>=<span>1D6AF</span></span>
+ <span><math><mtext>&#x1D6B0;</mtext></math>=<span>1D6B0</span></span>
+ <span><math><mtext>&#x1D6B1;</mtext></math>=<span>1D6B1</span></span>
+ <span><math><mtext>&#x1D6B2;</mtext></math>=<span>1D6B2</span></span>
+ <span><math><mtext>&#x1D6B3;</mtext></math>=<span>1D6B3</span></span>
+ <span><math><mtext>&#x1D6B4;</mtext></math>=<span>1D6B4</span></span>
+ <span><math><mtext>&#x1D6B5;</mtext></math>=<span>1D6B5</span></span>
+ <span><math><mtext>&#x1D6B6;</mtext></math>=<span>1D6B6</span></span>
+ <span><math><mtext>&#x1D6B7;</mtext></math>=<span>1D6B7</span></span><br/>
+ <span><math><mtext>&#x1D6B8;</mtext></math>=<span>1D6B8</span></span>
+ <span><math><mtext>&#x1D6BA;</mtext></math>=<span>1D6BA</span></span>
+ <span><math><mtext>&#x1D6BB;</mtext></math>=<span>1D6BB</span></span>
+ <span><math><mtext>&#x1D6BC;</mtext></math>=<span>1D6BC</span></span>
+ <span><math><mtext>&#x1D6BD;</mtext></math>=<span>1D6BD</span></span>
+ <span><math><mtext>&#x1D6BE;</mtext></math>=<span>1D6BE</span></span>
+ <span><math><mtext>&#x1D6BF;</mtext></math>=<span>1D6BF</span></span>
+ <span><math><mtext>&#x1D6C0;</mtext></math>=<span>1D6C0</span></span>
+ <span><math><mtext>&#x1D6C2;</mtext></math>=<span>1D6C2</span></span>
+ <span><math><mtext>&#x1D6C3;</mtext></math>=<span>1D6C3</span></span><br/>
+ <span><math><mtext>&#x1D6C4;</mtext></math>=<span>1D6C4</span></span>
+ <span><math><mtext>&#x1D6C5;</mtext></math>=<span>1D6C5</span></span>
+ <span><math><mtext>&#x1D6C6;</mtext></math>=<span>1D6C6</span></span>
+ <span><math><mtext>&#x1D6C7;</mtext></math>=<span>1D6C7</span></span>
+ <span><math><mtext>&#x1D6C8;</mtext></math>=<span>1D6C8</span></span>
+ <span><math><mtext>&#x1D6C9;</mtext></math>=<span>1D6C9</span></span>
+ <span><math><mtext>&#x1D6CA;</mtext></math>=<span>1D6CA</span></span>
+ <span><math><mtext>&#x1D6CB;</mtext></math>=<span>1D6CB</span></span>
+ <span><math><mtext>&#x1D6CC;</mtext></math>=<span>1D6CC</span></span>
+ <span><math><mtext>&#x1D6CD;</mtext></math>=<span>1D6CD</span></span><br/>
+ <span><math><mtext>&#x1D6CE;</mtext></math>=<span>1D6CE</span></span>
+ <span><math><mtext>&#x1D6CF;</mtext></math>=<span>1D6CF</span></span>
+ <span><math><mtext>&#x1D6D0;</mtext></math>=<span>1D6D0</span></span>
+ <span><math><mtext>&#x1D6D1;</mtext></math>=<span>1D6D1</span></span>
+ <span><math><mtext>&#x1D6D2;</mtext></math>=<span>1D6D2</span></span>
+ <span><math><mtext>&#x1D6D3;</mtext></math>=<span>1D6D3</span></span>
+ <span><math><mtext>&#x1D6D4;</mtext></math>=<span>1D6D4</span></span>
+ <span><math><mtext>&#x1D6D5;</mtext></math>=<span>1D6D5</span></span>
+ <span><math><mtext>&#x1D6D6;</mtext></math>=<span>1D6D6</span></span>
+ <span><math><mtext>&#x1D6D7;</mtext></math>=<span>1D6D7</span></span><br/>
+ <span><math><mtext>&#x1D6D8;</mtext></math>=<span>1D6D8</span></span>
+ <span><math><mtext>&#x1D6D9;</mtext></math>=<span>1D6D9</span></span>
+ <span><math><mtext>&#x1D6DA;</mtext></math>=<span>1D6DA</span></span>
+ <span><math><mtext>&#x1D6DD;</mtext></math>=<span>1D6DD</span></span>
+ <span><math><mtext>&#x1D6DF;</mtext></math>=<span>1D6DF</span></span>
+ <span><math><mtext>&#x1D6E1;</mtext></math>=<span>1D6E1</span></span>
+ <span><math><mtext>&#x1D7CA;</mtext></math>=<span>1D7CA</span></span>
+ <span><math><mtext>&#x1D7CB;</mtext></math>=<span>1D7CB</span></span>
+ <span><math><mtext>&#x1D6DE;</mtext></math>=<span>1D6DE</span></span>
+ <span><math><mtext>&#x1D6E0;</mtext></math>=<span>1D6E0</span></span><br/>
+ <span><math><mtext>&#x1D6B9;</mtext></math>=<span>1D6B9</span></span>
+ <span><math><mtext>&#x1D6DC;</mtext></math>=<span>1D6DC</span></span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-sans-serif-ref.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-sans-serif-ref.html
index 69ef0802f4b..a57fd18bf22 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-sans-serif-ref.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-sans-serif-ref.html
@@ -23,125 +23,125 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi>&#x1D789;</mi></math>=<span>1D789</span></span>
- <span><math><mi>&#x1D76F;</mi></math>=<span>1D76F</span></span>
- <span><math><mi>&#x1D7EC;</mi></math>=<span>1D7EC</span></span>
- <span><math><mi>&#x1D7ED;</mi></math>=<span>1D7ED</span></span>
- <span><math><mi>&#x1D7EE;</mi></math>=<span>1D7EE</span></span>
- <span><math><mi>&#x1D7EF;</mi></math>=<span>1D7EF</span></span>
- <span><math><mi>&#x1D7F0;</mi></math>=<span>1D7F0</span></span>
- <span><math><mi>&#x1D7F1;</mi></math>=<span>1D7F1</span></span>
- <span><math><mi>&#x1D7F2;</mi></math>=<span>1D7F2</span></span>
- <span><math><mi>&#x1D7F3;</mi></math>=<span>1D7F3</span></span><br/>
- <span><math><mi>&#x1D7F4;</mi></math>=<span>1D7F4</span></span>
- <span><math><mi>&#x1D7F5;</mi></math>=<span>1D7F5</span></span>
- <span><math><mi>&#x1D5D4;</mi></math>=<span>1D5D4</span></span>
- <span><math><mi>&#x1D5D5;</mi></math>=<span>1D5D5</span></span>
- <span><math><mi>&#x1D5D6;</mi></math>=<span>1D5D6</span></span>
- <span><math><mi>&#x1D5D7;</mi></math>=<span>1D5D7</span></span>
- <span><math><mi>&#x1D5D8;</mi></math>=<span>1D5D8</span></span>
- <span><math><mi>&#x1D5D9;</mi></math>=<span>1D5D9</span></span>
- <span><math><mi>&#x1D5DA;</mi></math>=<span>1D5DA</span></span>
- <span><math><mi>&#x1D5DB;</mi></math>=<span>1D5DB</span></span><br/>
- <span><math><mi>&#x1D5DC;</mi></math>=<span>1D5DC</span></span>
- <span><math><mi>&#x1D5DD;</mi></math>=<span>1D5DD</span></span>
- <span><math><mi>&#x1D5DE;</mi></math>=<span>1D5DE</span></span>
- <span><math><mi>&#x1D5DF;</mi></math>=<span>1D5DF</span></span>
- <span><math><mi>&#x1D5E0;</mi></math>=<span>1D5E0</span></span>
- <span><math><mi>&#x1D5E1;</mi></math>=<span>1D5E1</span></span>
- <span><math><mi>&#x1D5E2;</mi></math>=<span>1D5E2</span></span>
- <span><math><mi>&#x1D5E3;</mi></math>=<span>1D5E3</span></span>
- <span><math><mi>&#x1D5E4;</mi></math>=<span>1D5E4</span></span>
- <span><math><mi>&#x1D5E5;</mi></math>=<span>1D5E5</span></span><br/>
- <span><math><mi>&#x1D5E6;</mi></math>=<span>1D5E6</span></span>
- <span><math><mi>&#x1D5E7;</mi></math>=<span>1D5E7</span></span>
- <span><math><mi>&#x1D5E8;</mi></math>=<span>1D5E8</span></span>
- <span><math><mi>&#x1D5E9;</mi></math>=<span>1D5E9</span></span>
- <span><math><mi>&#x1D5EA;</mi></math>=<span>1D5EA</span></span>
- <span><math><mi>&#x1D5EB;</mi></math>=<span>1D5EB</span></span>
- <span><math><mi>&#x1D5EC;</mi></math>=<span>1D5EC</span></span>
- <span><math><mi>&#x1D5ED;</mi></math>=<span>1D5ED</span></span>
- <span><math><mi>&#x1D5EE;</mi></math>=<span>1D5EE</span></span>
- <span><math><mi>&#x1D5EF;</mi></math>=<span>1D5EF</span></span><br/>
- <span><math><mi>&#x1D5F0;</mi></math>=<span>1D5F0</span></span>
- <span><math><mi>&#x1D5F1;</mi></math>=<span>1D5F1</span></span>
- <span><math><mi>&#x1D5F2;</mi></math>=<span>1D5F2</span></span>
- <span><math><mi>&#x1D5F3;</mi></math>=<span>1D5F3</span></span>
- <span><math><mi>&#x1D5F4;</mi></math>=<span>1D5F4</span></span>
- <span><math><mi>&#x1D5F5;</mi></math>=<span>1D5F5</span></span>
- <span><math><mi>&#x1D5F6;</mi></math>=<span>1D5F6</span></span>
- <span><math><mi>&#x1D5F7;</mi></math>=<span>1D5F7</span></span>
- <span><math><mi>&#x1D5F8;</mi></math>=<span>1D5F8</span></span>
- <span><math><mi>&#x1D5F9;</mi></math>=<span>1D5F9</span></span><br/>
- <span><math><mi>&#x1D5FA;</mi></math>=<span>1D5FA</span></span>
- <span><math><mi>&#x1D5FB;</mi></math>=<span>1D5FB</span></span>
- <span><math><mi>&#x1D5FC;</mi></math>=<span>1D5FC</span></span>
- <span><math><mi>&#x1D5FD;</mi></math>=<span>1D5FD</span></span>
- <span><math><mi>&#x1D5FE;</mi></math>=<span>1D5FE</span></span>
- <span><math><mi>&#x1D5FF;</mi></math>=<span>1D5FF</span></span>
- <span><math><mi>&#x1D600;</mi></math>=<span>1D600</span></span>
- <span><math><mi>&#x1D601;</mi></math>=<span>1D601</span></span>
- <span><math><mi>&#x1D602;</mi></math>=<span>1D602</span></span>
- <span><math><mi>&#x1D603;</mi></math>=<span>1D603</span></span><br/>
- <span><math><mi>&#x1D604;</mi></math>=<span>1D604</span></span>
- <span><math><mi>&#x1D605;</mi></math>=<span>1D605</span></span>
- <span><math><mi>&#x1D606;</mi></math>=<span>1D606</span></span>
- <span><math><mi>&#x1D607;</mi></math>=<span>1D607</span></span>
- <span><math><mi>&#x1D756;</mi></math>=<span>1D756</span></span>
- <span><math><mi>&#x1D757;</mi></math>=<span>1D757</span></span>
- <span><math><mi>&#x1D758;</mi></math>=<span>1D758</span></span>
- <span><math><mi>&#x1D759;</mi></math>=<span>1D759</span></span>
- <span><math><mi>&#x1D75A;</mi></math>=<span>1D75A</span></span>
- <span><math><mi>&#x1D75B;</mi></math>=<span>1D75B</span></span><br/>
- <span><math><mi>&#x1D75C;</mi></math>=<span>1D75C</span></span>
- <span><math><mi>&#x1D75D;</mi></math>=<span>1D75D</span></span>
- <span><math><mi>&#x1D75E;</mi></math>=<span>1D75E</span></span>
- <span><math><mi>&#x1D75F;</mi></math>=<span>1D75F</span></span>
- <span><math><mi>&#x1D760;</mi></math>=<span>1D760</span></span>
- <span><math><mi>&#x1D761;</mi></math>=<span>1D761</span></span>
- <span><math><mi>&#x1D762;</mi></math>=<span>1D762</span></span>
- <span><math><mi>&#x1D763;</mi></math>=<span>1D763</span></span>
- <span><math><mi>&#x1D764;</mi></math>=<span>1D764</span></span>
- <span><math><mi>&#x1D765;</mi></math>=<span>1D765</span></span><br/>
- <span><math><mi>&#x1D766;</mi></math>=<span>1D766</span></span>
- <span><math><mi>&#x1D768;</mi></math>=<span>1D768</span></span>
- <span><math><mi>&#x1D769;</mi></math>=<span>1D769</span></span>
- <span><math><mi>&#x1D76A;</mi></math>=<span>1D76A</span></span>
- <span><math><mi>&#x1D76B;</mi></math>=<span>1D76B</span></span>
- <span><math><mi>&#x1D76C;</mi></math>=<span>1D76C</span></span>
- <span><math><mi>&#x1D76D;</mi></math>=<span>1D76D</span></span>
- <span><math><mi>&#x1D76E;</mi></math>=<span>1D76E</span></span>
- <span><math><mi>&#x1D770;</mi></math>=<span>1D770</span></span>
- <span><math><mi>&#x1D771;</mi></math>=<span>1D771</span></span><br/>
- <span><math><mi>&#x1D772;</mi></math>=<span>1D772</span></span>
- <span><math><mi>&#x1D773;</mi></math>=<span>1D773</span></span>
- <span><math><mi>&#x1D774;</mi></math>=<span>1D774</span></span>
- <span><math><mi>&#x1D775;</mi></math>=<span>1D775</span></span>
- <span><math><mi>&#x1D776;</mi></math>=<span>1D776</span></span>
- <span><math><mi>&#x1D777;</mi></math>=<span>1D777</span></span>
- <span><math><mi>&#x1D778;</mi></math>=<span>1D778</span></span>
- <span><math><mi>&#x1D779;</mi></math>=<span>1D779</span></span>
- <span><math><mi>&#x1D77A;</mi></math>=<span>1D77A</span></span>
- <span><math><mi>&#x1D77B;</mi></math>=<span>1D77B</span></span><br/>
- <span><math><mi>&#x1D77C;</mi></math>=<span>1D77C</span></span>
- <span><math><mi>&#x1D77D;</mi></math>=<span>1D77D</span></span>
- <span><math><mi>&#x1D77E;</mi></math>=<span>1D77E</span></span>
- <span><math><mi>&#x1D77F;</mi></math>=<span>1D77F</span></span>
- <span><math><mi>&#x1D780;</mi></math>=<span>1D780</span></span>
- <span><math><mi>&#x1D781;</mi></math>=<span>1D781</span></span>
- <span><math><mi>&#x1D782;</mi></math>=<span>1D782</span></span>
- <span><math><mi>&#x1D783;</mi></math>=<span>1D783</span></span>
- <span><math><mi>&#x1D784;</mi></math>=<span>1D784</span></span>
- <span><math><mi>&#x1D785;</mi></math>=<span>1D785</span></span><br/>
- <span><math><mi>&#x1D786;</mi></math>=<span>1D786</span></span>
- <span><math><mi>&#x1D787;</mi></math>=<span>1D787</span></span>
- <span><math><mi>&#x1D788;</mi></math>=<span>1D788</span></span>
- <span><math><mi>&#x1D78B;</mi></math>=<span>1D78B</span></span>
- <span><math><mi>&#x1D78D;</mi></math>=<span>1D78D</span></span>
- <span><math><mi>&#x1D78F;</mi></math>=<span>1D78F</span></span>
- <span><math><mi>&#x1D78C;</mi></math>=<span>1D78C</span></span>
- <span><math><mi>&#x1D78E;</mi></math>=<span>1D78E</span></span>
- <span><math><mi>&#x1D767;</mi></math>=<span>1D767</span></span>
- <span><math><mi>&#x1D78A;</mi></math>=<span>1D78A</span></span><br/>
+ <span><math><mtext>&#x1D789;</mtext></math>=<span>1D789</span></span>
+ <span><math><mtext>&#x1D76F;</mtext></math>=<span>1D76F</span></span>
+ <span><math><mtext>&#x1D7EC;</mtext></math>=<span>1D7EC</span></span>
+ <span><math><mtext>&#x1D7ED;</mtext></math>=<span>1D7ED</span></span>
+ <span><math><mtext>&#x1D7EE;</mtext></math>=<span>1D7EE</span></span>
+ <span><math><mtext>&#x1D7EF;</mtext></math>=<span>1D7EF</span></span>
+ <span><math><mtext>&#x1D7F0;</mtext></math>=<span>1D7F0</span></span>
+ <span><math><mtext>&#x1D7F1;</mtext></math>=<span>1D7F1</span></span>
+ <span><math><mtext>&#x1D7F2;</mtext></math>=<span>1D7F2</span></span>
+ <span><math><mtext>&#x1D7F3;</mtext></math>=<span>1D7F3</span></span><br/>
+ <span><math><mtext>&#x1D7F4;</mtext></math>=<span>1D7F4</span></span>
+ <span><math><mtext>&#x1D7F5;</mtext></math>=<span>1D7F5</span></span>
+ <span><math><mtext>&#x1D5D4;</mtext></math>=<span>1D5D4</span></span>
+ <span><math><mtext>&#x1D5D5;</mtext></math>=<span>1D5D5</span></span>
+ <span><math><mtext>&#x1D5D6;</mtext></math>=<span>1D5D6</span></span>
+ <span><math><mtext>&#x1D5D7;</mtext></math>=<span>1D5D7</span></span>
+ <span><math><mtext>&#x1D5D8;</mtext></math>=<span>1D5D8</span></span>
+ <span><math><mtext>&#x1D5D9;</mtext></math>=<span>1D5D9</span></span>
+ <span><math><mtext>&#x1D5DA;</mtext></math>=<span>1D5DA</span></span>
+ <span><math><mtext>&#x1D5DB;</mtext></math>=<span>1D5DB</span></span><br/>
+ <span><math><mtext>&#x1D5DC;</mtext></math>=<span>1D5DC</span></span>
+ <span><math><mtext>&#x1D5DD;</mtext></math>=<span>1D5DD</span></span>
+ <span><math><mtext>&#x1D5DE;</mtext></math>=<span>1D5DE</span></span>
+ <span><math><mtext>&#x1D5DF;</mtext></math>=<span>1D5DF</span></span>
+ <span><math><mtext>&#x1D5E0;</mtext></math>=<span>1D5E0</span></span>
+ <span><math><mtext>&#x1D5E1;</mtext></math>=<span>1D5E1</span></span>
+ <span><math><mtext>&#x1D5E2;</mtext></math>=<span>1D5E2</span></span>
+ <span><math><mtext>&#x1D5E3;</mtext></math>=<span>1D5E3</span></span>
+ <span><math><mtext>&#x1D5E4;</mtext></math>=<span>1D5E4</span></span>
+ <span><math><mtext>&#x1D5E5;</mtext></math>=<span>1D5E5</span></span><br/>
+ <span><math><mtext>&#x1D5E6;</mtext></math>=<span>1D5E6</span></span>
+ <span><math><mtext>&#x1D5E7;</mtext></math>=<span>1D5E7</span></span>
+ <span><math><mtext>&#x1D5E8;</mtext></math>=<span>1D5E8</span></span>
+ <span><math><mtext>&#x1D5E9;</mtext></math>=<span>1D5E9</span></span>
+ <span><math><mtext>&#x1D5EA;</mtext></math>=<span>1D5EA</span></span>
+ <span><math><mtext>&#x1D5EB;</mtext></math>=<span>1D5EB</span></span>
+ <span><math><mtext>&#x1D5EC;</mtext></math>=<span>1D5EC</span></span>
+ <span><math><mtext>&#x1D5ED;</mtext></math>=<span>1D5ED</span></span>
+ <span><math><mtext>&#x1D5EE;</mtext></math>=<span>1D5EE</span></span>
+ <span><math><mtext>&#x1D5EF;</mtext></math>=<span>1D5EF</span></span><br/>
+ <span><math><mtext>&#x1D5F0;</mtext></math>=<span>1D5F0</span></span>
+ <span><math><mtext>&#x1D5F1;</mtext></math>=<span>1D5F1</span></span>
+ <span><math><mtext>&#x1D5F2;</mtext></math>=<span>1D5F2</span></span>
+ <span><math><mtext>&#x1D5F3;</mtext></math>=<span>1D5F3</span></span>
+ <span><math><mtext>&#x1D5F4;</mtext></math>=<span>1D5F4</span></span>
+ <span><math><mtext>&#x1D5F5;</mtext></math>=<span>1D5F5</span></span>
+ <span><math><mtext>&#x1D5F6;</mtext></math>=<span>1D5F6</span></span>
+ <span><math><mtext>&#x1D5F7;</mtext></math>=<span>1D5F7</span></span>
+ <span><math><mtext>&#x1D5F8;</mtext></math>=<span>1D5F8</span></span>
+ <span><math><mtext>&#x1D5F9;</mtext></math>=<span>1D5F9</span></span><br/>
+ <span><math><mtext>&#x1D5FA;</mtext></math>=<span>1D5FA</span></span>
+ <span><math><mtext>&#x1D5FB;</mtext></math>=<span>1D5FB</span></span>
+ <span><math><mtext>&#x1D5FC;</mtext></math>=<span>1D5FC</span></span>
+ <span><math><mtext>&#x1D5FD;</mtext></math>=<span>1D5FD</span></span>
+ <span><math><mtext>&#x1D5FE;</mtext></math>=<span>1D5FE</span></span>
+ <span><math><mtext>&#x1D5FF;</mtext></math>=<span>1D5FF</span></span>
+ <span><math><mtext>&#x1D600;</mtext></math>=<span>1D600</span></span>
+ <span><math><mtext>&#x1D601;</mtext></math>=<span>1D601</span></span>
+ <span><math><mtext>&#x1D602;</mtext></math>=<span>1D602</span></span>
+ <span><math><mtext>&#x1D603;</mtext></math>=<span>1D603</span></span><br/>
+ <span><math><mtext>&#x1D604;</mtext></math>=<span>1D604</span></span>
+ <span><math><mtext>&#x1D605;</mtext></math>=<span>1D605</span></span>
+ <span><math><mtext>&#x1D606;</mtext></math>=<span>1D606</span></span>
+ <span><math><mtext>&#x1D607;</mtext></math>=<span>1D607</span></span>
+ <span><math><mtext>&#x1D756;</mtext></math>=<span>1D756</span></span>
+ <span><math><mtext>&#x1D757;</mtext></math>=<span>1D757</span></span>
+ <span><math><mtext>&#x1D758;</mtext></math>=<span>1D758</span></span>
+ <span><math><mtext>&#x1D759;</mtext></math>=<span>1D759</span></span>
+ <span><math><mtext>&#x1D75A;</mtext></math>=<span>1D75A</span></span>
+ <span><math><mtext>&#x1D75B;</mtext></math>=<span>1D75B</span></span><br/>
+ <span><math><mtext>&#x1D75C;</mtext></math>=<span>1D75C</span></span>
+ <span><math><mtext>&#x1D75D;</mtext></math>=<span>1D75D</span></span>
+ <span><math><mtext>&#x1D75E;</mtext></math>=<span>1D75E</span></span>
+ <span><math><mtext>&#x1D75F;</mtext></math>=<span>1D75F</span></span>
+ <span><math><mtext>&#x1D760;</mtext></math>=<span>1D760</span></span>
+ <span><math><mtext>&#x1D761;</mtext></math>=<span>1D761</span></span>
+ <span><math><mtext>&#x1D762;</mtext></math>=<span>1D762</span></span>
+ <span><math><mtext>&#x1D763;</mtext></math>=<span>1D763</span></span>
+ <span><math><mtext>&#x1D764;</mtext></math>=<span>1D764</span></span>
+ <span><math><mtext>&#x1D765;</mtext></math>=<span>1D765</span></span><br/>
+ <span><math><mtext>&#x1D766;</mtext></math>=<span>1D766</span></span>
+ <span><math><mtext>&#x1D768;</mtext></math>=<span>1D768</span></span>
+ <span><math><mtext>&#x1D769;</mtext></math>=<span>1D769</span></span>
+ <span><math><mtext>&#x1D76A;</mtext></math>=<span>1D76A</span></span>
+ <span><math><mtext>&#x1D76B;</mtext></math>=<span>1D76B</span></span>
+ <span><math><mtext>&#x1D76C;</mtext></math>=<span>1D76C</span></span>
+ <span><math><mtext>&#x1D76D;</mtext></math>=<span>1D76D</span></span>
+ <span><math><mtext>&#x1D76E;</mtext></math>=<span>1D76E</span></span>
+ <span><math><mtext>&#x1D770;</mtext></math>=<span>1D770</span></span>
+ <span><math><mtext>&#x1D771;</mtext></math>=<span>1D771</span></span><br/>
+ <span><math><mtext>&#x1D772;</mtext></math>=<span>1D772</span></span>
+ <span><math><mtext>&#x1D773;</mtext></math>=<span>1D773</span></span>
+ <span><math><mtext>&#x1D774;</mtext></math>=<span>1D774</span></span>
+ <span><math><mtext>&#x1D775;</mtext></math>=<span>1D775</span></span>
+ <span><math><mtext>&#x1D776;</mtext></math>=<span>1D776</span></span>
+ <span><math><mtext>&#x1D777;</mtext></math>=<span>1D777</span></span>
+ <span><math><mtext>&#x1D778;</mtext></math>=<span>1D778</span></span>
+ <span><math><mtext>&#x1D779;</mtext></math>=<span>1D779</span></span>
+ <span><math><mtext>&#x1D77A;</mtext></math>=<span>1D77A</span></span>
+ <span><math><mtext>&#x1D77B;</mtext></math>=<span>1D77B</span></span><br/>
+ <span><math><mtext>&#x1D77C;</mtext></math>=<span>1D77C</span></span>
+ <span><math><mtext>&#x1D77D;</mtext></math>=<span>1D77D</span></span>
+ <span><math><mtext>&#x1D77E;</mtext></math>=<span>1D77E</span></span>
+ <span><math><mtext>&#x1D77F;</mtext></math>=<span>1D77F</span></span>
+ <span><math><mtext>&#x1D780;</mtext></math>=<span>1D780</span></span>
+ <span><math><mtext>&#x1D781;</mtext></math>=<span>1D781</span></span>
+ <span><math><mtext>&#x1D782;</mtext></math>=<span>1D782</span></span>
+ <span><math><mtext>&#x1D783;</mtext></math>=<span>1D783</span></span>
+ <span><math><mtext>&#x1D784;</mtext></math>=<span>1D784</span></span>
+ <span><math><mtext>&#x1D785;</mtext></math>=<span>1D785</span></span><br/>
+ <span><math><mtext>&#x1D786;</mtext></math>=<span>1D786</span></span>
+ <span><math><mtext>&#x1D787;</mtext></math>=<span>1D787</span></span>
+ <span><math><mtext>&#x1D788;</mtext></math>=<span>1D788</span></span>
+ <span><math><mtext>&#x1D78B;</mtext></math>=<span>1D78B</span></span>
+ <span><math><mtext>&#x1D78D;</mtext></math>=<span>1D78D</span></span>
+ <span><math><mtext>&#x1D78F;</mtext></math>=<span>1D78F</span></span>
+ <span><math><mtext>&#x1D78C;</mtext></math>=<span>1D78C</span></span>
+ <span><math><mtext>&#x1D78E;</mtext></math>=<span>1D78E</span></span>
+ <span><math><mtext>&#x1D767;</mtext></math>=<span>1D767</span></span>
+ <span><math><mtext>&#x1D78A;</mtext></math>=<span>1D78A</span></span><br/>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-sans-serif.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-sans-serif.html
index 2a009507d18..1cab2372ba3 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-sans-serif.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-sans-serif.html
@@ -5,7 +5,7 @@
<title>mathvariant bold-sans-serif</title>
<link rel="help" href="http://www.mathml-association.org/MathMLinHTML5/S2.html#SS3.SSS1.tab2"/>
<link rel="match" href="mathvariant-bold-sans-serif-ref.html"/>
-<meta name="assert" content="Verify that a single-char <mi> with a bold-sans-serif mathvariant is equivalent to an <mi> with the transformed unicode character.">
+<meta name="assert" content="Verify that a single-char <mtext> with a bold-sans-serif mathvariant is equivalent to an <mtext> with the transformed unicode character.">
<style>
@font-face {
font-family: TestFont;
@@ -26,125 +26,125 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi mathvariant="bold-sans-serif">&#x2202;</mi></math>=<span>1D789</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x2207;</mi></math>=<span>1D76F</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x30;</mi></math>=<span>1D7EC</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x31;</mi></math>=<span>1D7ED</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x32;</mi></math>=<span>1D7EE</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x33;</mi></math>=<span>1D7EF</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x34;</mi></math>=<span>1D7F0</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x35;</mi></math>=<span>1D7F1</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x36;</mi></math>=<span>1D7F2</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x37;</mi></math>=<span>1D7F3</span></span><br/>
- <span><math><mi mathvariant="bold-sans-serif">&#x38;</mi></math>=<span>1D7F4</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x39;</mi></math>=<span>1D7F5</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x41;</mi></math>=<span>1D5D4</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x42;</mi></math>=<span>1D5D5</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x43;</mi></math>=<span>1D5D6</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x44;</mi></math>=<span>1D5D7</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x45;</mi></math>=<span>1D5D8</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x46;</mi></math>=<span>1D5D9</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x47;</mi></math>=<span>1D5DA</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x48;</mi></math>=<span>1D5DB</span></span><br/>
- <span><math><mi mathvariant="bold-sans-serif">&#x49;</mi></math>=<span>1D5DC</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x4A;</mi></math>=<span>1D5DD</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x4B;</mi></math>=<span>1D5DE</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x4C;</mi></math>=<span>1D5DF</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x4D;</mi></math>=<span>1D5E0</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x4E;</mi></math>=<span>1D5E1</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x4F;</mi></math>=<span>1D5E2</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x50;</mi></math>=<span>1D5E3</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x51;</mi></math>=<span>1D5E4</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x52;</mi></math>=<span>1D5E5</span></span><br/>
- <span><math><mi mathvariant="bold-sans-serif">&#x53;</mi></math>=<span>1D5E6</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x54;</mi></math>=<span>1D5E7</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x55;</mi></math>=<span>1D5E8</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x56;</mi></math>=<span>1D5E9</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x57;</mi></math>=<span>1D5EA</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x58;</mi></math>=<span>1D5EB</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x59;</mi></math>=<span>1D5EC</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x5A;</mi></math>=<span>1D5ED</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x61;</mi></math>=<span>1D5EE</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x62;</mi></math>=<span>1D5EF</span></span><br/>
- <span><math><mi mathvariant="bold-sans-serif">&#x63;</mi></math>=<span>1D5F0</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x64;</mi></math>=<span>1D5F1</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x65;</mi></math>=<span>1D5F2</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x66;</mi></math>=<span>1D5F3</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x67;</mi></math>=<span>1D5F4</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x68;</mi></math>=<span>1D5F5</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x69;</mi></math>=<span>1D5F6</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x6A;</mi></math>=<span>1D5F7</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x6B;</mi></math>=<span>1D5F8</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x6C;</mi></math>=<span>1D5F9</span></span><br/>
- <span><math><mi mathvariant="bold-sans-serif">&#x6D;</mi></math>=<span>1D5FA</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x6E;</mi></math>=<span>1D5FB</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x6F;</mi></math>=<span>1D5FC</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x70;</mi></math>=<span>1D5FD</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x71;</mi></math>=<span>1D5FE</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x72;</mi></math>=<span>1D5FF</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x73;</mi></math>=<span>1D600</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x74;</mi></math>=<span>1D601</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x75;</mi></math>=<span>1D602</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x76;</mi></math>=<span>1D603</span></span><br/>
- <span><math><mi mathvariant="bold-sans-serif">&#x77;</mi></math>=<span>1D604</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x78;</mi></math>=<span>1D605</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x79;</mi></math>=<span>1D606</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x7A;</mi></math>=<span>1D607</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x391;</mi></math>=<span>1D756</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x392;</mi></math>=<span>1D757</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x393;</mi></math>=<span>1D758</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x394;</mi></math>=<span>1D759</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x395;</mi></math>=<span>1D75A</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x396;</mi></math>=<span>1D75B</span></span><br/>
- <span><math><mi mathvariant="bold-sans-serif">&#x397;</mi></math>=<span>1D75C</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x398;</mi></math>=<span>1D75D</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x399;</mi></math>=<span>1D75E</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x39A;</mi></math>=<span>1D75F</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x39B;</mi></math>=<span>1D760</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x39C;</mi></math>=<span>1D761</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x39D;</mi></math>=<span>1D762</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x39E;</mi></math>=<span>1D763</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x39F;</mi></math>=<span>1D764</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3A0;</mi></math>=<span>1D765</span></span><br/>
- <span><math><mi mathvariant="bold-sans-serif">&#x3A1;</mi></math>=<span>1D766</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3A3;</mi></math>=<span>1D768</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3A4;</mi></math>=<span>1D769</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3A5;</mi></math>=<span>1D76A</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3A6;</mi></math>=<span>1D76B</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3A7;</mi></math>=<span>1D76C</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3A8;</mi></math>=<span>1D76D</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3A9;</mi></math>=<span>1D76E</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3B1;</mi></math>=<span>1D770</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3B2;</mi></math>=<span>1D771</span></span><br/>
- <span><math><mi mathvariant="bold-sans-serif">&#x3B3;</mi></math>=<span>1D772</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3B4;</mi></math>=<span>1D773</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3B5;</mi></math>=<span>1D774</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3B6;</mi></math>=<span>1D775</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3B7;</mi></math>=<span>1D776</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3B8;</mi></math>=<span>1D777</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3B9;</mi></math>=<span>1D778</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3BA;</mi></math>=<span>1D779</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3BB;</mi></math>=<span>1D77A</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3BC;</mi></math>=<span>1D77B</span></span><br/>
- <span><math><mi mathvariant="bold-sans-serif">&#x3BD;</mi></math>=<span>1D77C</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3BE;</mi></math>=<span>1D77D</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3BF;</mi></math>=<span>1D77E</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3C0;</mi></math>=<span>1D77F</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3C1;</mi></math>=<span>1D780</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3C2;</mi></math>=<span>1D781</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3C3;</mi></math>=<span>1D782</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3C4;</mi></math>=<span>1D783</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3C5;</mi></math>=<span>1D784</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3C6;</mi></math>=<span>1D785</span></span><br/>
- <span><math><mi mathvariant="bold-sans-serif">&#x3C7;</mi></math>=<span>1D786</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3C8;</mi></math>=<span>1D787</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3C9;</mi></math>=<span>1D788</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3D1;</mi></math>=<span>1D78B</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3D5;</mi></math>=<span>1D78D</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3D6;</mi></math>=<span>1D78F</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3F0;</mi></math>=<span>1D78C</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3F1;</mi></math>=<span>1D78E</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3F4;</mi></math>=<span>1D767</span></span>
- <span><math><mi mathvariant="bold-sans-serif">&#x3F5;</mi></math>=<span>1D78A</span></span><br/>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x2202;</mtext></math>=<span>1D789</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x2207;</mtext></math>=<span>1D76F</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x30;</mtext></math>=<span>1D7EC</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x31;</mtext></math>=<span>1D7ED</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x32;</mtext></math>=<span>1D7EE</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x33;</mtext></math>=<span>1D7EF</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x34;</mtext></math>=<span>1D7F0</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x35;</mtext></math>=<span>1D7F1</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x36;</mtext></math>=<span>1D7F2</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x37;</mtext></math>=<span>1D7F3</span></span><br/>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x38;</mtext></math>=<span>1D7F4</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x39;</mtext></math>=<span>1D7F5</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x41;</mtext></math>=<span>1D5D4</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x42;</mtext></math>=<span>1D5D5</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x43;</mtext></math>=<span>1D5D6</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x44;</mtext></math>=<span>1D5D7</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x45;</mtext></math>=<span>1D5D8</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x46;</mtext></math>=<span>1D5D9</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x47;</mtext></math>=<span>1D5DA</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x48;</mtext></math>=<span>1D5DB</span></span><br/>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x49;</mtext></math>=<span>1D5DC</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x4A;</mtext></math>=<span>1D5DD</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x4B;</mtext></math>=<span>1D5DE</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x4C;</mtext></math>=<span>1D5DF</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x4D;</mtext></math>=<span>1D5E0</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x4E;</mtext></math>=<span>1D5E1</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x4F;</mtext></math>=<span>1D5E2</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x50;</mtext></math>=<span>1D5E3</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x51;</mtext></math>=<span>1D5E4</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x52;</mtext></math>=<span>1D5E5</span></span><br/>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x53;</mtext></math>=<span>1D5E6</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x54;</mtext></math>=<span>1D5E7</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x55;</mtext></math>=<span>1D5E8</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x56;</mtext></math>=<span>1D5E9</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x57;</mtext></math>=<span>1D5EA</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x58;</mtext></math>=<span>1D5EB</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x59;</mtext></math>=<span>1D5EC</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x5A;</mtext></math>=<span>1D5ED</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x61;</mtext></math>=<span>1D5EE</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x62;</mtext></math>=<span>1D5EF</span></span><br/>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x63;</mtext></math>=<span>1D5F0</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x64;</mtext></math>=<span>1D5F1</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x65;</mtext></math>=<span>1D5F2</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x66;</mtext></math>=<span>1D5F3</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x67;</mtext></math>=<span>1D5F4</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x68;</mtext></math>=<span>1D5F5</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x69;</mtext></math>=<span>1D5F6</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x6A;</mtext></math>=<span>1D5F7</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x6B;</mtext></math>=<span>1D5F8</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x6C;</mtext></math>=<span>1D5F9</span></span><br/>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x6D;</mtext></math>=<span>1D5FA</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x6E;</mtext></math>=<span>1D5FB</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x6F;</mtext></math>=<span>1D5FC</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x70;</mtext></math>=<span>1D5FD</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x71;</mtext></math>=<span>1D5FE</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x72;</mtext></math>=<span>1D5FF</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x73;</mtext></math>=<span>1D600</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x74;</mtext></math>=<span>1D601</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x75;</mtext></math>=<span>1D602</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x76;</mtext></math>=<span>1D603</span></span><br/>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x77;</mtext></math>=<span>1D604</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x78;</mtext></math>=<span>1D605</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x79;</mtext></math>=<span>1D606</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x7A;</mtext></math>=<span>1D607</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x391;</mtext></math>=<span>1D756</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x392;</mtext></math>=<span>1D757</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x393;</mtext></math>=<span>1D758</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x394;</mtext></math>=<span>1D759</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x395;</mtext></math>=<span>1D75A</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x396;</mtext></math>=<span>1D75B</span></span><br/>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x397;</mtext></math>=<span>1D75C</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x398;</mtext></math>=<span>1D75D</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x399;</mtext></math>=<span>1D75E</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x39A;</mtext></math>=<span>1D75F</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x39B;</mtext></math>=<span>1D760</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x39C;</mtext></math>=<span>1D761</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x39D;</mtext></math>=<span>1D762</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x39E;</mtext></math>=<span>1D763</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x39F;</mtext></math>=<span>1D764</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3A0;</mtext></math>=<span>1D765</span></span><br/>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3A1;</mtext></math>=<span>1D766</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3A3;</mtext></math>=<span>1D768</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3A4;</mtext></math>=<span>1D769</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3A5;</mtext></math>=<span>1D76A</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3A6;</mtext></math>=<span>1D76B</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3A7;</mtext></math>=<span>1D76C</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3A8;</mtext></math>=<span>1D76D</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3A9;</mtext></math>=<span>1D76E</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3B1;</mtext></math>=<span>1D770</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3B2;</mtext></math>=<span>1D771</span></span><br/>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3B3;</mtext></math>=<span>1D772</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3B4;</mtext></math>=<span>1D773</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3B5;</mtext></math>=<span>1D774</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3B6;</mtext></math>=<span>1D775</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3B7;</mtext></math>=<span>1D776</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3B8;</mtext></math>=<span>1D777</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3B9;</mtext></math>=<span>1D778</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3BA;</mtext></math>=<span>1D779</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3BB;</mtext></math>=<span>1D77A</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3BC;</mtext></math>=<span>1D77B</span></span><br/>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3BD;</mtext></math>=<span>1D77C</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3BE;</mtext></math>=<span>1D77D</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3BF;</mtext></math>=<span>1D77E</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3C0;</mtext></math>=<span>1D77F</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3C1;</mtext></math>=<span>1D780</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3C2;</mtext></math>=<span>1D781</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3C3;</mtext></math>=<span>1D782</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3C4;</mtext></math>=<span>1D783</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3C5;</mtext></math>=<span>1D784</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3C6;</mtext></math>=<span>1D785</span></span><br/>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3C7;</mtext></math>=<span>1D786</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3C8;</mtext></math>=<span>1D787</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3C9;</mtext></math>=<span>1D788</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3D1;</mtext></math>=<span>1D78B</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3D5;</mtext></math>=<span>1D78D</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3D6;</mtext></math>=<span>1D78F</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3F0;</mtext></math>=<span>1D78C</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3F1;</mtext></math>=<span>1D78E</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3F4;</mtext></math>=<span>1D767</span></span>
+ <span><math><mtext mathvariant="bold-sans-serif">&#x3F5;</mtext></math>=<span>1D78A</span></span><br/>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-script-ref.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-script-ref.html
index 1ae6f1d6e68..4203861f707 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-script-ref.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-script-ref.html
@@ -23,57 +23,57 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi>&#x1D4D0;</mi></math>=<span>1D4D0</span></span>
- <span><math><mi>&#x1D4D1;</mi></math>=<span>1D4D1</span></span>
- <span><math><mi>&#x1D4D2;</mi></math>=<span>1D4D2</span></span>
- <span><math><mi>&#x1D4D3;</mi></math>=<span>1D4D3</span></span>
- <span><math><mi>&#x1D4D4;</mi></math>=<span>1D4D4</span></span>
- <span><math><mi>&#x1D4D5;</mi></math>=<span>1D4D5</span></span>
- <span><math><mi>&#x1D4D6;</mi></math>=<span>1D4D6</span></span>
- <span><math><mi>&#x1D4D7;</mi></math>=<span>1D4D7</span></span>
- <span><math><mi>&#x1D4D8;</mi></math>=<span>1D4D8</span></span>
- <span><math><mi>&#x1D4D9;</mi></math>=<span>1D4D9</span></span><br/>
- <span><math><mi>&#x1D4DA;</mi></math>=<span>1D4DA</span></span>
- <span><math><mi>&#x1D4DB;</mi></math>=<span>1D4DB</span></span>
- <span><math><mi>&#x1D4DC;</mi></math>=<span>1D4DC</span></span>
- <span><math><mi>&#x1D4DD;</mi></math>=<span>1D4DD</span></span>
- <span><math><mi>&#x1D4DE;</mi></math>=<span>1D4DE</span></span>
- <span><math><mi>&#x1D4DF;</mi></math>=<span>1D4DF</span></span>
- <span><math><mi>&#x1D4E0;</mi></math>=<span>1D4E0</span></span>
- <span><math><mi>&#x1D4E1;</mi></math>=<span>1D4E1</span></span>
- <span><math><mi>&#x1D4E2;</mi></math>=<span>1D4E2</span></span>
- <span><math><mi>&#x1D4E3;</mi></math>=<span>1D4E3</span></span><br/>
- <span><math><mi>&#x1D4E4;</mi></math>=<span>1D4E4</span></span>
- <span><math><mi>&#x1D4E5;</mi></math>=<span>1D4E5</span></span>
- <span><math><mi>&#x1D4E6;</mi></math>=<span>1D4E6</span></span>
- <span><math><mi>&#x1D4E7;</mi></math>=<span>1D4E7</span></span>
- <span><math><mi>&#x1D4E8;</mi></math>=<span>1D4E8</span></span>
- <span><math><mi>&#x1D4E9;</mi></math>=<span>1D4E9</span></span>
- <span><math><mi>&#x1D4EA;</mi></math>=<span>1D4EA</span></span>
- <span><math><mi>&#x1D4EB;</mi></math>=<span>1D4EB</span></span>
- <span><math><mi>&#x1D4EC;</mi></math>=<span>1D4EC</span></span>
- <span><math><mi>&#x1D4ED;</mi></math>=<span>1D4ED</span></span><br/>
- <span><math><mi>&#x1D4EE;</mi></math>=<span>1D4EE</span></span>
- <span><math><mi>&#x1D4EF;</mi></math>=<span>1D4EF</span></span>
- <span><math><mi>&#x1D4F0;</mi></math>=<span>1D4F0</span></span>
- <span><math><mi>&#x1D4F1;</mi></math>=<span>1D4F1</span></span>
- <span><math><mi>&#x1D4F2;</mi></math>=<span>1D4F2</span></span>
- <span><math><mi>&#x1D4F3;</mi></math>=<span>1D4F3</span></span>
- <span><math><mi>&#x1D4F4;</mi></math>=<span>1D4F4</span></span>
- <span><math><mi>&#x1D4F5;</mi></math>=<span>1D4F5</span></span>
- <span><math><mi>&#x1D4F6;</mi></math>=<span>1D4F6</span></span>
- <span><math><mi>&#x1D4F7;</mi></math>=<span>1D4F7</span></span><br/>
- <span><math><mi>&#x1D4F8;</mi></math>=<span>1D4F8</span></span>
- <span><math><mi>&#x1D4F9;</mi></math>=<span>1D4F9</span></span>
- <span><math><mi>&#x1D4FA;</mi></math>=<span>1D4FA</span></span>
- <span><math><mi>&#x1D4FB;</mi></math>=<span>1D4FB</span></span>
- <span><math><mi>&#x1D4FC;</mi></math>=<span>1D4FC</span></span>
- <span><math><mi>&#x1D4FD;</mi></math>=<span>1D4FD</span></span>
- <span><math><mi>&#x1D4FE;</mi></math>=<span>1D4FE</span></span>
- <span><math><mi>&#x1D4FF;</mi></math>=<span>1D4FF</span></span>
- <span><math><mi>&#x1D500;</mi></math>=<span>1D500</span></span>
- <span><math><mi>&#x1D501;</mi></math>=<span>1D501</span></span><br/>
- <span><math><mi>&#x1D502;</mi></math>=<span>1D502</span></span>
- <span><math><mi>&#x1D503;</mi></math>=<span>1D503</span></span>
+ <span><math><mtext>&#x1D4D0;</mtext></math>=<span>1D4D0</span></span>
+ <span><math><mtext>&#x1D4D1;</mtext></math>=<span>1D4D1</span></span>
+ <span><math><mtext>&#x1D4D2;</mtext></math>=<span>1D4D2</span></span>
+ <span><math><mtext>&#x1D4D3;</mtext></math>=<span>1D4D3</span></span>
+ <span><math><mtext>&#x1D4D4;</mtext></math>=<span>1D4D4</span></span>
+ <span><math><mtext>&#x1D4D5;</mtext></math>=<span>1D4D5</span></span>
+ <span><math><mtext>&#x1D4D6;</mtext></math>=<span>1D4D6</span></span>
+ <span><math><mtext>&#x1D4D7;</mtext></math>=<span>1D4D7</span></span>
+ <span><math><mtext>&#x1D4D8;</mtext></math>=<span>1D4D8</span></span>
+ <span><math><mtext>&#x1D4D9;</mtext></math>=<span>1D4D9</span></span><br/>
+ <span><math><mtext>&#x1D4DA;</mtext></math>=<span>1D4DA</span></span>
+ <span><math><mtext>&#x1D4DB;</mtext></math>=<span>1D4DB</span></span>
+ <span><math><mtext>&#x1D4DC;</mtext></math>=<span>1D4DC</span></span>
+ <span><math><mtext>&#x1D4DD;</mtext></math>=<span>1D4DD</span></span>
+ <span><math><mtext>&#x1D4DE;</mtext></math>=<span>1D4DE</span></span>
+ <span><math><mtext>&#x1D4DF;</mtext></math>=<span>1D4DF</span></span>
+ <span><math><mtext>&#x1D4E0;</mtext></math>=<span>1D4E0</span></span>
+ <span><math><mtext>&#x1D4E1;</mtext></math>=<span>1D4E1</span></span>
+ <span><math><mtext>&#x1D4E2;</mtext></math>=<span>1D4E2</span></span>
+ <span><math><mtext>&#x1D4E3;</mtext></math>=<span>1D4E3</span></span><br/>
+ <span><math><mtext>&#x1D4E4;</mtext></math>=<span>1D4E4</span></span>
+ <span><math><mtext>&#x1D4E5;</mtext></math>=<span>1D4E5</span></span>
+ <span><math><mtext>&#x1D4E6;</mtext></math>=<span>1D4E6</span></span>
+ <span><math><mtext>&#x1D4E7;</mtext></math>=<span>1D4E7</span></span>
+ <span><math><mtext>&#x1D4E8;</mtext></math>=<span>1D4E8</span></span>
+ <span><math><mtext>&#x1D4E9;</mtext></math>=<span>1D4E9</span></span>
+ <span><math><mtext>&#x1D4EA;</mtext></math>=<span>1D4EA</span></span>
+ <span><math><mtext>&#x1D4EB;</mtext></math>=<span>1D4EB</span></span>
+ <span><math><mtext>&#x1D4EC;</mtext></math>=<span>1D4EC</span></span>
+ <span><math><mtext>&#x1D4ED;</mtext></math>=<span>1D4ED</span></span><br/>
+ <span><math><mtext>&#x1D4EE;</mtext></math>=<span>1D4EE</span></span>
+ <span><math><mtext>&#x1D4EF;</mtext></math>=<span>1D4EF</span></span>
+ <span><math><mtext>&#x1D4F0;</mtext></math>=<span>1D4F0</span></span>
+ <span><math><mtext>&#x1D4F1;</mtext></math>=<span>1D4F1</span></span>
+ <span><math><mtext>&#x1D4F2;</mtext></math>=<span>1D4F2</span></span>
+ <span><math><mtext>&#x1D4F3;</mtext></math>=<span>1D4F3</span></span>
+ <span><math><mtext>&#x1D4F4;</mtext></math>=<span>1D4F4</span></span>
+ <span><math><mtext>&#x1D4F5;</mtext></math>=<span>1D4F5</span></span>
+ <span><math><mtext>&#x1D4F6;</mtext></math>=<span>1D4F6</span></span>
+ <span><math><mtext>&#x1D4F7;</mtext></math>=<span>1D4F7</span></span><br/>
+ <span><math><mtext>&#x1D4F8;</mtext></math>=<span>1D4F8</span></span>
+ <span><math><mtext>&#x1D4F9;</mtext></math>=<span>1D4F9</span></span>
+ <span><math><mtext>&#x1D4FA;</mtext></math>=<span>1D4FA</span></span>
+ <span><math><mtext>&#x1D4FB;</mtext></math>=<span>1D4FB</span></span>
+ <span><math><mtext>&#x1D4FC;</mtext></math>=<span>1D4FC</span></span>
+ <span><math><mtext>&#x1D4FD;</mtext></math>=<span>1D4FD</span></span>
+ <span><math><mtext>&#x1D4FE;</mtext></math>=<span>1D4FE</span></span>
+ <span><math><mtext>&#x1D4FF;</mtext></math>=<span>1D4FF</span></span>
+ <span><math><mtext>&#x1D500;</mtext></math>=<span>1D500</span></span>
+ <span><math><mtext>&#x1D501;</mtext></math>=<span>1D501</span></span><br/>
+ <span><math><mtext>&#x1D502;</mtext></math>=<span>1D502</span></span>
+ <span><math><mtext>&#x1D503;</mtext></math>=<span>1D503</span></span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-script.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-script.html
index 8c2e693252b..9083afa801d 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-script.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold-script.html
@@ -5,7 +5,7 @@
<title>mathvariant bold-script</title>
<link rel="help" href="http://www.mathml-association.org/MathMLinHTML5/S2.html#SS3.SSS1.tab2"/>
<link rel="match" href="mathvariant-bold-script-ref.html"/>
-<meta name="assert" content="Verify that a single-char <mi> with a bold-script mathvariant is equivalent to an <mi> with the transformed unicode character.">
+<meta name="assert" content="Verify that a single-char <mtext> with a bold-script mathvariant is equivalent to an <mtext> with the transformed unicode character.">
<style>
@font-face {
font-family: TestFont;
@@ -26,57 +26,57 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi mathvariant="bold-script">&#x41;</mi></math>=<span>1D4D0</span></span>
- <span><math><mi mathvariant="bold-script">&#x42;</mi></math>=<span>1D4D1</span></span>
- <span><math><mi mathvariant="bold-script">&#x43;</mi></math>=<span>1D4D2</span></span>
- <span><math><mi mathvariant="bold-script">&#x44;</mi></math>=<span>1D4D3</span></span>
- <span><math><mi mathvariant="bold-script">&#x45;</mi></math>=<span>1D4D4</span></span>
- <span><math><mi mathvariant="bold-script">&#x46;</mi></math>=<span>1D4D5</span></span>
- <span><math><mi mathvariant="bold-script">&#x47;</mi></math>=<span>1D4D6</span></span>
- <span><math><mi mathvariant="bold-script">&#x48;</mi></math>=<span>1D4D7</span></span>
- <span><math><mi mathvariant="bold-script">&#x49;</mi></math>=<span>1D4D8</span></span>
- <span><math><mi mathvariant="bold-script">&#x4A;</mi></math>=<span>1D4D9</span></span><br/>
- <span><math><mi mathvariant="bold-script">&#x4B;</mi></math>=<span>1D4DA</span></span>
- <span><math><mi mathvariant="bold-script">&#x4C;</mi></math>=<span>1D4DB</span></span>
- <span><math><mi mathvariant="bold-script">&#x4D;</mi></math>=<span>1D4DC</span></span>
- <span><math><mi mathvariant="bold-script">&#x4E;</mi></math>=<span>1D4DD</span></span>
- <span><math><mi mathvariant="bold-script">&#x4F;</mi></math>=<span>1D4DE</span></span>
- <span><math><mi mathvariant="bold-script">&#x50;</mi></math>=<span>1D4DF</span></span>
- <span><math><mi mathvariant="bold-script">&#x51;</mi></math>=<span>1D4E0</span></span>
- <span><math><mi mathvariant="bold-script">&#x52;</mi></math>=<span>1D4E1</span></span>
- <span><math><mi mathvariant="bold-script">&#x53;</mi></math>=<span>1D4E2</span></span>
- <span><math><mi mathvariant="bold-script">&#x54;</mi></math>=<span>1D4E3</span></span><br/>
- <span><math><mi mathvariant="bold-script">&#x55;</mi></math>=<span>1D4E4</span></span>
- <span><math><mi mathvariant="bold-script">&#x56;</mi></math>=<span>1D4E5</span></span>
- <span><math><mi mathvariant="bold-script">&#x57;</mi></math>=<span>1D4E6</span></span>
- <span><math><mi mathvariant="bold-script">&#x58;</mi></math>=<span>1D4E7</span></span>
- <span><math><mi mathvariant="bold-script">&#x59;</mi></math>=<span>1D4E8</span></span>
- <span><math><mi mathvariant="bold-script">&#x5A;</mi></math>=<span>1D4E9</span></span>
- <span><math><mi mathvariant="bold-script">&#x61;</mi></math>=<span>1D4EA</span></span>
- <span><math><mi mathvariant="bold-script">&#x62;</mi></math>=<span>1D4EB</span></span>
- <span><math><mi mathvariant="bold-script">&#x63;</mi></math>=<span>1D4EC</span></span>
- <span><math><mi mathvariant="bold-script">&#x64;</mi></math>=<span>1D4ED</span></span><br/>
- <span><math><mi mathvariant="bold-script">&#x65;</mi></math>=<span>1D4EE</span></span>
- <span><math><mi mathvariant="bold-script">&#x66;</mi></math>=<span>1D4EF</span></span>
- <span><math><mi mathvariant="bold-script">&#x67;</mi></math>=<span>1D4F0</span></span>
- <span><math><mi mathvariant="bold-script">&#x68;</mi></math>=<span>1D4F1</span></span>
- <span><math><mi mathvariant="bold-script">&#x69;</mi></math>=<span>1D4F2</span></span>
- <span><math><mi mathvariant="bold-script">&#x6A;</mi></math>=<span>1D4F3</span></span>
- <span><math><mi mathvariant="bold-script">&#x6B;</mi></math>=<span>1D4F4</span></span>
- <span><math><mi mathvariant="bold-script">&#x6C;</mi></math>=<span>1D4F5</span></span>
- <span><math><mi mathvariant="bold-script">&#x6D;</mi></math>=<span>1D4F6</span></span>
- <span><math><mi mathvariant="bold-script">&#x6E;</mi></math>=<span>1D4F7</span></span><br/>
- <span><math><mi mathvariant="bold-script">&#x6F;</mi></math>=<span>1D4F8</span></span>
- <span><math><mi mathvariant="bold-script">&#x70;</mi></math>=<span>1D4F9</span></span>
- <span><math><mi mathvariant="bold-script">&#x71;</mi></math>=<span>1D4FA</span></span>
- <span><math><mi mathvariant="bold-script">&#x72;</mi></math>=<span>1D4FB</span></span>
- <span><math><mi mathvariant="bold-script">&#x73;</mi></math>=<span>1D4FC</span></span>
- <span><math><mi mathvariant="bold-script">&#x74;</mi></math>=<span>1D4FD</span></span>
- <span><math><mi mathvariant="bold-script">&#x75;</mi></math>=<span>1D4FE</span></span>
- <span><math><mi mathvariant="bold-script">&#x76;</mi></math>=<span>1D4FF</span></span>
- <span><math><mi mathvariant="bold-script">&#x77;</mi></math>=<span>1D500</span></span>
- <span><math><mi mathvariant="bold-script">&#x78;</mi></math>=<span>1D501</span></span><br/>
- <span><math><mi mathvariant="bold-script">&#x79;</mi></math>=<span>1D502</span></span>
- <span><math><mi mathvariant="bold-script">&#x7A;</mi></math>=<span>1D503</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x41;</mtext></math>=<span>1D4D0</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x42;</mtext></math>=<span>1D4D1</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x43;</mtext></math>=<span>1D4D2</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x44;</mtext></math>=<span>1D4D3</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x45;</mtext></math>=<span>1D4D4</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x46;</mtext></math>=<span>1D4D5</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x47;</mtext></math>=<span>1D4D6</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x48;</mtext></math>=<span>1D4D7</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x49;</mtext></math>=<span>1D4D8</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x4A;</mtext></math>=<span>1D4D9</span></span><br/>
+ <span><math><mtext mathvariant="bold-script">&#x4B;</mtext></math>=<span>1D4DA</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x4C;</mtext></math>=<span>1D4DB</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x4D;</mtext></math>=<span>1D4DC</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x4E;</mtext></math>=<span>1D4DD</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x4F;</mtext></math>=<span>1D4DE</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x50;</mtext></math>=<span>1D4DF</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x51;</mtext></math>=<span>1D4E0</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x52;</mtext></math>=<span>1D4E1</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x53;</mtext></math>=<span>1D4E2</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x54;</mtext></math>=<span>1D4E3</span></span><br/>
+ <span><math><mtext mathvariant="bold-script">&#x55;</mtext></math>=<span>1D4E4</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x56;</mtext></math>=<span>1D4E5</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x57;</mtext></math>=<span>1D4E6</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x58;</mtext></math>=<span>1D4E7</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x59;</mtext></math>=<span>1D4E8</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x5A;</mtext></math>=<span>1D4E9</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x61;</mtext></math>=<span>1D4EA</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x62;</mtext></math>=<span>1D4EB</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x63;</mtext></math>=<span>1D4EC</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x64;</mtext></math>=<span>1D4ED</span></span><br/>
+ <span><math><mtext mathvariant="bold-script">&#x65;</mtext></math>=<span>1D4EE</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x66;</mtext></math>=<span>1D4EF</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x67;</mtext></math>=<span>1D4F0</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x68;</mtext></math>=<span>1D4F1</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x69;</mtext></math>=<span>1D4F2</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x6A;</mtext></math>=<span>1D4F3</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x6B;</mtext></math>=<span>1D4F4</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x6C;</mtext></math>=<span>1D4F5</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x6D;</mtext></math>=<span>1D4F6</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x6E;</mtext></math>=<span>1D4F7</span></span><br/>
+ <span><math><mtext mathvariant="bold-script">&#x6F;</mtext></math>=<span>1D4F8</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x70;</mtext></math>=<span>1D4F9</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x71;</mtext></math>=<span>1D4FA</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x72;</mtext></math>=<span>1D4FB</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x73;</mtext></math>=<span>1D4FC</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x74;</mtext></math>=<span>1D4FD</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x75;</mtext></math>=<span>1D4FE</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x76;</mtext></math>=<span>1D4FF</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x77;</mtext></math>=<span>1D500</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x78;</mtext></math>=<span>1D501</span></span><br/>
+ <span><math><mtext mathvariant="bold-script">&#x79;</mtext></math>=<span>1D502</span></span>
+ <span><math><mtext mathvariant="bold-script">&#x7A;</mtext></math>=<span>1D503</span></span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold.html
index d00e3a1ca5b..b3fe917d23c 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-bold.html
@@ -5,7 +5,7 @@
<title>mathvariant bold</title>
<link rel="help" href="http://www.mathml-association.org/MathMLinHTML5/S2.html#SS3.SSS1.tab2"/>
<link rel="match" href="mathvariant-bold-ref.html"/>
-<meta name="assert" content="Verify that a single-char <mi> with a bold mathvariant is equivalent to an <mi> with the transformed unicode character.">
+<meta name="assert" content="Verify that a single-char <mtext> with a bold mathvariant is equivalent to an <mtext> with the transformed unicode character.">
<style>
@font-face {
font-family: TestFont;
@@ -26,127 +26,127 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi mathvariant="bold">&#x2202;</mi></math>=<span>1D6DB</span></span>
- <span><math><mi mathvariant="bold">&#x2207;</mi></math>=<span>1D6C1</span></span>
- <span><math><mi mathvariant="bold">&#x30;</mi></math>=<span>1D7CE</span></span>
- <span><math><mi mathvariant="bold">&#x31;</mi></math>=<span>1D7CF</span></span>
- <span><math><mi mathvariant="bold">&#x32;</mi></math>=<span>1D7D0</span></span>
- <span><math><mi mathvariant="bold">&#x33;</mi></math>=<span>1D7D1</span></span>
- <span><math><mi mathvariant="bold">&#x34;</mi></math>=<span>1D7D2</span></span>
- <span><math><mi mathvariant="bold">&#x35;</mi></math>=<span>1D7D3</span></span>
- <span><math><mi mathvariant="bold">&#x36;</mi></math>=<span>1D7D4</span></span>
- <span><math><mi mathvariant="bold">&#x37;</mi></math>=<span>1D7D5</span></span><br/>
- <span><math><mi mathvariant="bold">&#x38;</mi></math>=<span>1D7D6</span></span>
- <span><math><mi mathvariant="bold">&#x39;</mi></math>=<span>1D7D7</span></span>
- <span><math><mi mathvariant="bold">&#x41;</mi></math>=<span>1D400</span></span>
- <span><math><mi mathvariant="bold">&#x42;</mi></math>=<span>1D401</span></span>
- <span><math><mi mathvariant="bold">&#x43;</mi></math>=<span>1D402</span></span>
- <span><math><mi mathvariant="bold">&#x44;</mi></math>=<span>1D403</span></span>
- <span><math><mi mathvariant="bold">&#x45;</mi></math>=<span>1D404</span></span>
- <span><math><mi mathvariant="bold">&#x46;</mi></math>=<span>1D405</span></span>
- <span><math><mi mathvariant="bold">&#x47;</mi></math>=<span>1D406</span></span>
- <span><math><mi mathvariant="bold">&#x48;</mi></math>=<span>1D407</span></span><br/>
- <span><math><mi mathvariant="bold">&#x49;</mi></math>=<span>1D408</span></span>
- <span><math><mi mathvariant="bold">&#x4A;</mi></math>=<span>1D409</span></span>
- <span><math><mi mathvariant="bold">&#x4B;</mi></math>=<span>1D40A</span></span>
- <span><math><mi mathvariant="bold">&#x4C;</mi></math>=<span>1D40B</span></span>
- <span><math><mi mathvariant="bold">&#x4D;</mi></math>=<span>1D40C</span></span>
- <span><math><mi mathvariant="bold">&#x4E;</mi></math>=<span>1D40D</span></span>
- <span><math><mi mathvariant="bold">&#x4F;</mi></math>=<span>1D40E</span></span>
- <span><math><mi mathvariant="bold">&#x50;</mi></math>=<span>1D40F</span></span>
- <span><math><mi mathvariant="bold">&#x51;</mi></math>=<span>1D410</span></span>
- <span><math><mi mathvariant="bold">&#x52;</mi></math>=<span>1D411</span></span><br/>
- <span><math><mi mathvariant="bold">&#x53;</mi></math>=<span>1D412</span></span>
- <span><math><mi mathvariant="bold">&#x54;</mi></math>=<span>1D413</span></span>
- <span><math><mi mathvariant="bold">&#x55;</mi></math>=<span>1D414</span></span>
- <span><math><mi mathvariant="bold">&#x56;</mi></math>=<span>1D415</span></span>
- <span><math><mi mathvariant="bold">&#x57;</mi></math>=<span>1D416</span></span>
- <span><math><mi mathvariant="bold">&#x58;</mi></math>=<span>1D417</span></span>
- <span><math><mi mathvariant="bold">&#x59;</mi></math>=<span>1D418</span></span>
- <span><math><mi mathvariant="bold">&#x5A;</mi></math>=<span>1D419</span></span>
- <span><math><mi mathvariant="bold">&#x61;</mi></math>=<span>1D41A</span></span>
- <span><math><mi mathvariant="bold">&#x62;</mi></math>=<span>1D41B</span></span><br/>
- <span><math><mi mathvariant="bold">&#x63;</mi></math>=<span>1D41C</span></span>
- <span><math><mi mathvariant="bold">&#x64;</mi></math>=<span>1D41D</span></span>
- <span><math><mi mathvariant="bold">&#x65;</mi></math>=<span>1D41E</span></span>
- <span><math><mi mathvariant="bold">&#x66;</mi></math>=<span>1D41F</span></span>
- <span><math><mi mathvariant="bold">&#x67;</mi></math>=<span>1D420</span></span>
- <span><math><mi mathvariant="bold">&#x68;</mi></math>=<span>1D421</span></span>
- <span><math><mi mathvariant="bold">&#x69;</mi></math>=<span>1D422</span></span>
- <span><math><mi mathvariant="bold">&#x6A;</mi></math>=<span>1D423</span></span>
- <span><math><mi mathvariant="bold">&#x6B;</mi></math>=<span>1D424</span></span>
- <span><math><mi mathvariant="bold">&#x6C;</mi></math>=<span>1D425</span></span><br/>
- <span><math><mi mathvariant="bold">&#x6D;</mi></math>=<span>1D426</span></span>
- <span><math><mi mathvariant="bold">&#x6E;</mi></math>=<span>1D427</span></span>
- <span><math><mi mathvariant="bold">&#x6F;</mi></math>=<span>1D428</span></span>
- <span><math><mi mathvariant="bold">&#x70;</mi></math>=<span>1D429</span></span>
- <span><math><mi mathvariant="bold">&#x71;</mi></math>=<span>1D42A</span></span>
- <span><math><mi mathvariant="bold">&#x72;</mi></math>=<span>1D42B</span></span>
- <span><math><mi mathvariant="bold">&#x73;</mi></math>=<span>1D42C</span></span>
- <span><math><mi mathvariant="bold">&#x74;</mi></math>=<span>1D42D</span></span>
- <span><math><mi mathvariant="bold">&#x75;</mi></math>=<span>1D42E</span></span>
- <span><math><mi mathvariant="bold">&#x76;</mi></math>=<span>1D42F</span></span><br/>
- <span><math><mi mathvariant="bold">&#x77;</mi></math>=<span>1D430</span></span>
- <span><math><mi mathvariant="bold">&#x78;</mi></math>=<span>1D431</span></span>
- <span><math><mi mathvariant="bold">&#x79;</mi></math>=<span>1D432</span></span>
- <span><math><mi mathvariant="bold">&#x7A;</mi></math>=<span>1D433</span></span>
- <span><math><mi mathvariant="bold">&#x391;</mi></math>=<span>1D6A8</span></span>
- <span><math><mi mathvariant="bold">&#x392;</mi></math>=<span>1D6A9</span></span>
- <span><math><mi mathvariant="bold">&#x393;</mi></math>=<span>1D6AA</span></span>
- <span><math><mi mathvariant="bold">&#x394;</mi></math>=<span>1D6AB</span></span>
- <span><math><mi mathvariant="bold">&#x395;</mi></math>=<span>1D6AC</span></span>
- <span><math><mi mathvariant="bold">&#x396;</mi></math>=<span>1D6AD</span></span><br/>
- <span><math><mi mathvariant="bold">&#x397;</mi></math>=<span>1D6AE</span></span>
- <span><math><mi mathvariant="bold">&#x398;</mi></math>=<span>1D6AF</span></span>
- <span><math><mi mathvariant="bold">&#x399;</mi></math>=<span>1D6B0</span></span>
- <span><math><mi mathvariant="bold">&#x39A;</mi></math>=<span>1D6B1</span></span>
- <span><math><mi mathvariant="bold">&#x39B;</mi></math>=<span>1D6B2</span></span>
- <span><math><mi mathvariant="bold">&#x39C;</mi></math>=<span>1D6B3</span></span>
- <span><math><mi mathvariant="bold">&#x39D;</mi></math>=<span>1D6B4</span></span>
- <span><math><mi mathvariant="bold">&#x39E;</mi></math>=<span>1D6B5</span></span>
- <span><math><mi mathvariant="bold">&#x39F;</mi></math>=<span>1D6B6</span></span>
- <span><math><mi mathvariant="bold">&#x3A0;</mi></math>=<span>1D6B7</span></span><br/>
- <span><math><mi mathvariant="bold">&#x3A1;</mi></math>=<span>1D6B8</span></span>
- <span><math><mi mathvariant="bold">&#x3A3;</mi></math>=<span>1D6BA</span></span>
- <span><math><mi mathvariant="bold">&#x3A4;</mi></math>=<span>1D6BB</span></span>
- <span><math><mi mathvariant="bold">&#x3A5;</mi></math>=<span>1D6BC</span></span>
- <span><math><mi mathvariant="bold">&#x3A6;</mi></math>=<span>1D6BD</span></span>
- <span><math><mi mathvariant="bold">&#x3A7;</mi></math>=<span>1D6BE</span></span>
- <span><math><mi mathvariant="bold">&#x3A8;</mi></math>=<span>1D6BF</span></span>
- <span><math><mi mathvariant="bold">&#x3A9;</mi></math>=<span>1D6C0</span></span>
- <span><math><mi mathvariant="bold">&#x3B1;</mi></math>=<span>1D6C2</span></span>
- <span><math><mi mathvariant="bold">&#x3B2;</mi></math>=<span>1D6C3</span></span><br/>
- <span><math><mi mathvariant="bold">&#x3B3;</mi></math>=<span>1D6C4</span></span>
- <span><math><mi mathvariant="bold">&#x3B4;</mi></math>=<span>1D6C5</span></span>
- <span><math><mi mathvariant="bold">&#x3B5;</mi></math>=<span>1D6C6</span></span>
- <span><math><mi mathvariant="bold">&#x3B6;</mi></math>=<span>1D6C7</span></span>
- <span><math><mi mathvariant="bold">&#x3B7;</mi></math>=<span>1D6C8</span></span>
- <span><math><mi mathvariant="bold">&#x3B8;</mi></math>=<span>1D6C9</span></span>
- <span><math><mi mathvariant="bold">&#x3B9;</mi></math>=<span>1D6CA</span></span>
- <span><math><mi mathvariant="bold">&#x3BA;</mi></math>=<span>1D6CB</span></span>
- <span><math><mi mathvariant="bold">&#x3BB;</mi></math>=<span>1D6CC</span></span>
- <span><math><mi mathvariant="bold">&#x3BC;</mi></math>=<span>1D6CD</span></span><br/>
- <span><math><mi mathvariant="bold">&#x3BD;</mi></math>=<span>1D6CE</span></span>
- <span><math><mi mathvariant="bold">&#x3BE;</mi></math>=<span>1D6CF</span></span>
- <span><math><mi mathvariant="bold">&#x3BF;</mi></math>=<span>1D6D0</span></span>
- <span><math><mi mathvariant="bold">&#x3C0;</mi></math>=<span>1D6D1</span></span>
- <span><math><mi mathvariant="bold">&#x3C1;</mi></math>=<span>1D6D2</span></span>
- <span><math><mi mathvariant="bold">&#x3C2;</mi></math>=<span>1D6D3</span></span>
- <span><math><mi mathvariant="bold">&#x3C3;</mi></math>=<span>1D6D4</span></span>
- <span><math><mi mathvariant="bold">&#x3C4;</mi></math>=<span>1D6D5</span></span>
- <span><math><mi mathvariant="bold">&#x3C5;</mi></math>=<span>1D6D6</span></span>
- <span><math><mi mathvariant="bold">&#x3C6;</mi></math>=<span>1D6D7</span></span><br/>
- <span><math><mi mathvariant="bold">&#x3C7;</mi></math>=<span>1D6D8</span></span>
- <span><math><mi mathvariant="bold">&#x3C8;</mi></math>=<span>1D6D9</span></span>
- <span><math><mi mathvariant="bold">&#x3C9;</mi></math>=<span>1D6DA</span></span>
- <span><math><mi mathvariant="bold">&#x3D1;</mi></math>=<span>1D6DD</span></span>
- <span><math><mi mathvariant="bold">&#x3D5;</mi></math>=<span>1D6DF</span></span>
- <span><math><mi mathvariant="bold">&#x3D6;</mi></math>=<span>1D6E1</span></span>
- <span><math><mi mathvariant="bold">&#x3DC;</mi></math>=<span>1D7CA</span></span>
- <span><math><mi mathvariant="bold">&#x3DD;</mi></math>=<span>1D7CB</span></span>
- <span><math><mi mathvariant="bold">&#x3F0;</mi></math>=<span>1D6DE</span></span>
- <span><math><mi mathvariant="bold">&#x3F1;</mi></math>=<span>1D6E0</span></span><br/>
- <span><math><mi mathvariant="bold">&#x3F4;</mi></math>=<span>1D6B9</span></span>
- <span><math><mi mathvariant="bold">&#x3F5;</mi></math>=<span>1D6DC</span></span>
+ <span><math><mtext mathvariant="bold">&#x2202;</mtext></math>=<span>1D6DB</span></span>
+ <span><math><mtext mathvariant="bold">&#x2207;</mtext></math>=<span>1D6C1</span></span>
+ <span><math><mtext mathvariant="bold">&#x30;</mtext></math>=<span>1D7CE</span></span>
+ <span><math><mtext mathvariant="bold">&#x31;</mtext></math>=<span>1D7CF</span></span>
+ <span><math><mtext mathvariant="bold">&#x32;</mtext></math>=<span>1D7D0</span></span>
+ <span><math><mtext mathvariant="bold">&#x33;</mtext></math>=<span>1D7D1</span></span>
+ <span><math><mtext mathvariant="bold">&#x34;</mtext></math>=<span>1D7D2</span></span>
+ <span><math><mtext mathvariant="bold">&#x35;</mtext></math>=<span>1D7D3</span></span>
+ <span><math><mtext mathvariant="bold">&#x36;</mtext></math>=<span>1D7D4</span></span>
+ <span><math><mtext mathvariant="bold">&#x37;</mtext></math>=<span>1D7D5</span></span><br/>
+ <span><math><mtext mathvariant="bold">&#x38;</mtext></math>=<span>1D7D6</span></span>
+ <span><math><mtext mathvariant="bold">&#x39;</mtext></math>=<span>1D7D7</span></span>
+ <span><math><mtext mathvariant="bold">&#x41;</mtext></math>=<span>1D400</span></span>
+ <span><math><mtext mathvariant="bold">&#x42;</mtext></math>=<span>1D401</span></span>
+ <span><math><mtext mathvariant="bold">&#x43;</mtext></math>=<span>1D402</span></span>
+ <span><math><mtext mathvariant="bold">&#x44;</mtext></math>=<span>1D403</span></span>
+ <span><math><mtext mathvariant="bold">&#x45;</mtext></math>=<span>1D404</span></span>
+ <span><math><mtext mathvariant="bold">&#x46;</mtext></math>=<span>1D405</span></span>
+ <span><math><mtext mathvariant="bold">&#x47;</mtext></math>=<span>1D406</span></span>
+ <span><math><mtext mathvariant="bold">&#x48;</mtext></math>=<span>1D407</span></span><br/>
+ <span><math><mtext mathvariant="bold">&#x49;</mtext></math>=<span>1D408</span></span>
+ <span><math><mtext mathvariant="bold">&#x4A;</mtext></math>=<span>1D409</span></span>
+ <span><math><mtext mathvariant="bold">&#x4B;</mtext></math>=<span>1D40A</span></span>
+ <span><math><mtext mathvariant="bold">&#x4C;</mtext></math>=<span>1D40B</span></span>
+ <span><math><mtext mathvariant="bold">&#x4D;</mtext></math>=<span>1D40C</span></span>
+ <span><math><mtext mathvariant="bold">&#x4E;</mtext></math>=<span>1D40D</span></span>
+ <span><math><mtext mathvariant="bold">&#x4F;</mtext></math>=<span>1D40E</span></span>
+ <span><math><mtext mathvariant="bold">&#x50;</mtext></math>=<span>1D40F</span></span>
+ <span><math><mtext mathvariant="bold">&#x51;</mtext></math>=<span>1D410</span></span>
+ <span><math><mtext mathvariant="bold">&#x52;</mtext></math>=<span>1D411</span></span><br/>
+ <span><math><mtext mathvariant="bold">&#x53;</mtext></math>=<span>1D412</span></span>
+ <span><math><mtext mathvariant="bold">&#x54;</mtext></math>=<span>1D413</span></span>
+ <span><math><mtext mathvariant="bold">&#x55;</mtext></math>=<span>1D414</span></span>
+ <span><math><mtext mathvariant="bold">&#x56;</mtext></math>=<span>1D415</span></span>
+ <span><math><mtext mathvariant="bold">&#x57;</mtext></math>=<span>1D416</span></span>
+ <span><math><mtext mathvariant="bold">&#x58;</mtext></math>=<span>1D417</span></span>
+ <span><math><mtext mathvariant="bold">&#x59;</mtext></math>=<span>1D418</span></span>
+ <span><math><mtext mathvariant="bold">&#x5A;</mtext></math>=<span>1D419</span></span>
+ <span><math><mtext mathvariant="bold">&#x61;</mtext></math>=<span>1D41A</span></span>
+ <span><math><mtext mathvariant="bold">&#x62;</mtext></math>=<span>1D41B</span></span><br/>
+ <span><math><mtext mathvariant="bold">&#x63;</mtext></math>=<span>1D41C</span></span>
+ <span><math><mtext mathvariant="bold">&#x64;</mtext></math>=<span>1D41D</span></span>
+ <span><math><mtext mathvariant="bold">&#x65;</mtext></math>=<span>1D41E</span></span>
+ <span><math><mtext mathvariant="bold">&#x66;</mtext></math>=<span>1D41F</span></span>
+ <span><math><mtext mathvariant="bold">&#x67;</mtext></math>=<span>1D420</span></span>
+ <span><math><mtext mathvariant="bold">&#x68;</mtext></math>=<span>1D421</span></span>
+ <span><math><mtext mathvariant="bold">&#x69;</mtext></math>=<span>1D422</span></span>
+ <span><math><mtext mathvariant="bold">&#x6A;</mtext></math>=<span>1D423</span></span>
+ <span><math><mtext mathvariant="bold">&#x6B;</mtext></math>=<span>1D424</span></span>
+ <span><math><mtext mathvariant="bold">&#x6C;</mtext></math>=<span>1D425</span></span><br/>
+ <span><math><mtext mathvariant="bold">&#x6D;</mtext></math>=<span>1D426</span></span>
+ <span><math><mtext mathvariant="bold">&#x6E;</mtext></math>=<span>1D427</span></span>
+ <span><math><mtext mathvariant="bold">&#x6F;</mtext></math>=<span>1D428</span></span>
+ <span><math><mtext mathvariant="bold">&#x70;</mtext></math>=<span>1D429</span></span>
+ <span><math><mtext mathvariant="bold">&#x71;</mtext></math>=<span>1D42A</span></span>
+ <span><math><mtext mathvariant="bold">&#x72;</mtext></math>=<span>1D42B</span></span>
+ <span><math><mtext mathvariant="bold">&#x73;</mtext></math>=<span>1D42C</span></span>
+ <span><math><mtext mathvariant="bold">&#x74;</mtext></math>=<span>1D42D</span></span>
+ <span><math><mtext mathvariant="bold">&#x75;</mtext></math>=<span>1D42E</span></span>
+ <span><math><mtext mathvariant="bold">&#x76;</mtext></math>=<span>1D42F</span></span><br/>
+ <span><math><mtext mathvariant="bold">&#x77;</mtext></math>=<span>1D430</span></span>
+ <span><math><mtext mathvariant="bold">&#x78;</mtext></math>=<span>1D431</span></span>
+ <span><math><mtext mathvariant="bold">&#x79;</mtext></math>=<span>1D432</span></span>
+ <span><math><mtext mathvariant="bold">&#x7A;</mtext></math>=<span>1D433</span></span>
+ <span><math><mtext mathvariant="bold">&#x391;</mtext></math>=<span>1D6A8</span></span>
+ <span><math><mtext mathvariant="bold">&#x392;</mtext></math>=<span>1D6A9</span></span>
+ <span><math><mtext mathvariant="bold">&#x393;</mtext></math>=<span>1D6AA</span></span>
+ <span><math><mtext mathvariant="bold">&#x394;</mtext></math>=<span>1D6AB</span></span>
+ <span><math><mtext mathvariant="bold">&#x395;</mtext></math>=<span>1D6AC</span></span>
+ <span><math><mtext mathvariant="bold">&#x396;</mtext></math>=<span>1D6AD</span></span><br/>
+ <span><math><mtext mathvariant="bold">&#x397;</mtext></math>=<span>1D6AE</span></span>
+ <span><math><mtext mathvariant="bold">&#x398;</mtext></math>=<span>1D6AF</span></span>
+ <span><math><mtext mathvariant="bold">&#x399;</mtext></math>=<span>1D6B0</span></span>
+ <span><math><mtext mathvariant="bold">&#x39A;</mtext></math>=<span>1D6B1</span></span>
+ <span><math><mtext mathvariant="bold">&#x39B;</mtext></math>=<span>1D6B2</span></span>
+ <span><math><mtext mathvariant="bold">&#x39C;</mtext></math>=<span>1D6B3</span></span>
+ <span><math><mtext mathvariant="bold">&#x39D;</mtext></math>=<span>1D6B4</span></span>
+ <span><math><mtext mathvariant="bold">&#x39E;</mtext></math>=<span>1D6B5</span></span>
+ <span><math><mtext mathvariant="bold">&#x39F;</mtext></math>=<span>1D6B6</span></span>
+ <span><math><mtext mathvariant="bold">&#x3A0;</mtext></math>=<span>1D6B7</span></span><br/>
+ <span><math><mtext mathvariant="bold">&#x3A1;</mtext></math>=<span>1D6B8</span></span>
+ <span><math><mtext mathvariant="bold">&#x3A3;</mtext></math>=<span>1D6BA</span></span>
+ <span><math><mtext mathvariant="bold">&#x3A4;</mtext></math>=<span>1D6BB</span></span>
+ <span><math><mtext mathvariant="bold">&#x3A5;</mtext></math>=<span>1D6BC</span></span>
+ <span><math><mtext mathvariant="bold">&#x3A6;</mtext></math>=<span>1D6BD</span></span>
+ <span><math><mtext mathvariant="bold">&#x3A7;</mtext></math>=<span>1D6BE</span></span>
+ <span><math><mtext mathvariant="bold">&#x3A8;</mtext></math>=<span>1D6BF</span></span>
+ <span><math><mtext mathvariant="bold">&#x3A9;</mtext></math>=<span>1D6C0</span></span>
+ <span><math><mtext mathvariant="bold">&#x3B1;</mtext></math>=<span>1D6C2</span></span>
+ <span><math><mtext mathvariant="bold">&#x3B2;</mtext></math>=<span>1D6C3</span></span><br/>
+ <span><math><mtext mathvariant="bold">&#x3B3;</mtext></math>=<span>1D6C4</span></span>
+ <span><math><mtext mathvariant="bold">&#x3B4;</mtext></math>=<span>1D6C5</span></span>
+ <span><math><mtext mathvariant="bold">&#x3B5;</mtext></math>=<span>1D6C6</span></span>
+ <span><math><mtext mathvariant="bold">&#x3B6;</mtext></math>=<span>1D6C7</span></span>
+ <span><math><mtext mathvariant="bold">&#x3B7;</mtext></math>=<span>1D6C8</span></span>
+ <span><math><mtext mathvariant="bold">&#x3B8;</mtext></math>=<span>1D6C9</span></span>
+ <span><math><mtext mathvariant="bold">&#x3B9;</mtext></math>=<span>1D6CA</span></span>
+ <span><math><mtext mathvariant="bold">&#x3BA;</mtext></math>=<span>1D6CB</span></span>
+ <span><math><mtext mathvariant="bold">&#x3BB;</mtext></math>=<span>1D6CC</span></span>
+ <span><math><mtext mathvariant="bold">&#x3BC;</mtext></math>=<span>1D6CD</span></span><br/>
+ <span><math><mtext mathvariant="bold">&#x3BD;</mtext></math>=<span>1D6CE</span></span>
+ <span><math><mtext mathvariant="bold">&#x3BE;</mtext></math>=<span>1D6CF</span></span>
+ <span><math><mtext mathvariant="bold">&#x3BF;</mtext></math>=<span>1D6D0</span></span>
+ <span><math><mtext mathvariant="bold">&#x3C0;</mtext></math>=<span>1D6D1</span></span>
+ <span><math><mtext mathvariant="bold">&#x3C1;</mtext></math>=<span>1D6D2</span></span>
+ <span><math><mtext mathvariant="bold">&#x3C2;</mtext></math>=<span>1D6D3</span></span>
+ <span><math><mtext mathvariant="bold">&#x3C3;</mtext></math>=<span>1D6D4</span></span>
+ <span><math><mtext mathvariant="bold">&#x3C4;</mtext></math>=<span>1D6D5</span></span>
+ <span><math><mtext mathvariant="bold">&#x3C5;</mtext></math>=<span>1D6D6</span></span>
+ <span><math><mtext mathvariant="bold">&#x3C6;</mtext></math>=<span>1D6D7</span></span><br/>
+ <span><math><mtext mathvariant="bold">&#x3C7;</mtext></math>=<span>1D6D8</span></span>
+ <span><math><mtext mathvariant="bold">&#x3C8;</mtext></math>=<span>1D6D9</span></span>
+ <span><math><mtext mathvariant="bold">&#x3C9;</mtext></math>=<span>1D6DA</span></span>
+ <span><math><mtext mathvariant="bold">&#x3D1;</mtext></math>=<span>1D6DD</span></span>
+ <span><math><mtext mathvariant="bold">&#x3D5;</mtext></math>=<span>1D6DF</span></span>
+ <span><math><mtext mathvariant="bold">&#x3D6;</mtext></math>=<span>1D6E1</span></span>
+ <span><math><mtext mathvariant="bold">&#x3DC;</mtext></math>=<span>1D7CA</span></span>
+ <span><math><mtext mathvariant="bold">&#x3DD;</mtext></math>=<span>1D7CB</span></span>
+ <span><math><mtext mathvariant="bold">&#x3F0;</mtext></math>=<span>1D6DE</span></span>
+ <span><math><mtext mathvariant="bold">&#x3F1;</mtext></math>=<span>1D6E0</span></span><br/>
+ <span><math><mtext mathvariant="bold">&#x3F4;</mtext></math>=<span>1D6B9</span></span>
+ <span><math><mtext mathvariant="bold">&#x3F5;</mtext></math>=<span>1D6DC</span></span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-double-struck-ref.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-double-struck-ref.html
index f13a548b2b3..56db2591dae 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-double-struck-ref.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-double-struck-ref.html
@@ -23,92 +23,92 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi>&#x1EEA1;</mi></math>=<span>1EEA1</span></span>
- <span><math><mi>&#x1EEB5;</mi></math>=<span>1EEB5</span></span>
- <span><math><mi>&#x1EEB6;</mi></math>=<span>1EEB6</span></span>
- <span><math><mi>&#x1EEA2;</mi></math>=<span>1EEA2</span></span>
- <span><math><mi>&#x1EEA7;</mi></math>=<span>1EEA7</span></span>
- <span><math><mi>&#x1EEB7;</mi></math>=<span>1EEB7</span></span>
- <span><math><mi>&#x1EEA3;</mi></math>=<span>1EEA3</span></span>
- <span><math><mi>&#x1EEB8;</mi></math>=<span>1EEB8</span></span>
- <span><math><mi>&#x1EEB3;</mi></math>=<span>1EEB3</span></span>
- <span><math><mi>&#x1EEA6;</mi></math>=<span>1EEA6</span></span><br/>
- <span><math><mi>&#x1D7DB;</mi></math>=<span>1D7DB</span></span>
- <span><math><mi>&#x1D7DC;</mi></math>=<span>1D7DC</span></span>
- <span><math><mi>&#x1D7DD;</mi></math>=<span>1D7DD</span></span>
- <span><math><mi>&#x1EEB9;</mi></math>=<span>1EEB9</span></span>
- <span><math><mi>&#x1EEA8;</mi></math>=<span>1EEA8</span></span>
- <span><math><mi>&#x1EEBA;</mi></math>=<span>1EEBA</span></span>
- <span><math><mi>&#x1D7E1;</mi></math>=<span>1D7E1</span></span>
- <span><math><mi>&#x1EEBB;</mi></math>=<span>1EEBB</span></span>
- <span><math><mi>&#x1EEB0;</mi></math>=<span>1EEB0</span></span>
- <span><math><mi>&#x1EEB2;</mi></math>=<span>1EEB2</span></span><br/>
- <span><math><mi>&#x2102;</mi></math>=<span>02102</span></span>
- <span><math><mi>&#x1EEAB;</mi></math>=<span>1EEAB</span></span>
- <span><math><mi>&#x1EEAC;</mi></math>=<span>1EEAC</span></span>
- <span><math><mi>&#x1EEAD;</mi></math>=<span>1EEAD</span></span>
- <span><math><mi>&#x1D53E;</mi></math>=<span>1D53E</span></span>
- <span><math><mi>&#x1EEA5;</mi></math>=<span>1EEA5</span></span>
- <span><math><mi>&#x1D540;</mi></math>=<span>1D540</span></span>
- <span><math><mi>&#x1EEA9;</mi></math>=<span>1EEA9</span></span>
- <span><math><mi>&#x1D542;</mi></math>=<span>1D542</span></span>
- <span><math><mi>&#x1D543;</mi></math>=<span>1D543</span></span><br/>
- <span><math><mi>&#x1D544;</mi></math>=<span>1D544</span></span>
- <span><math><mi>&#x2115;</mi></math>=<span>02115</span></span>
- <span><math><mi>&#x1D546;</mi></math>=<span>1D546</span></span>
- <span><math><mi>&#x2119;</mi></math>=<span>02119</span></span>
- <span><math><mi>&#x211A;</mi></math>=<span>0211A</span></span>
- <span><math><mi>&#x211D;</mi></math>=<span>0211D</span></span>
- <span><math><mi>&#x1D54A;</mi></math>=<span>1D54A</span></span>
- <span><math><mi>&#x1D54B;</mi></math>=<span>1D54B</span></span>
- <span><math><mi>&#x1D54C;</mi></math>=<span>1D54C</span></span>
- <span><math><mi>&#x1D54D;</mi></math>=<span>1D54D</span></span><br/>
- <span><math><mi>&#x1D54E;</mi></math>=<span>1D54E</span></span>
- <span><math><mi>&#x1D54F;</mi></math>=<span>1D54F</span></span>
- <span><math><mi>&#x1D550;</mi></math>=<span>1D550</span></span>
- <span><math><mi>&#x2124;</mi></math>=<span>02124</span></span>
- <span><math><mi>&#x1D552;</mi></math>=<span>1D552</span></span>
- <span><math><mi>&#x1D553;</mi></math>=<span>1D553</span></span>
- <span><math><mi>&#x1D554;</mi></math>=<span>1D554</span></span>
- <span><math><mi>&#x1D555;</mi></math>=<span>1D555</span></span>
- <span><math><mi>&#x1D556;</mi></math>=<span>1D556</span></span>
- <span><math><mi>&#x1D557;</mi></math>=<span>1D557</span></span><br/>
- <span><math><mi>&#x1D558;</mi></math>=<span>1D558</span></span>
- <span><math><mi>&#x1D559;</mi></math>=<span>1D559</span></span>
- <span><math><mi>&#x1D55A;</mi></math>=<span>1D55A</span></span>
- <span><math><mi>&#x1D55B;</mi></math>=<span>1D55B</span></span>
- <span><math><mi>&#x1D55C;</mi></math>=<span>1D55C</span></span>
- <span><math><mi>&#x1D55D;</mi></math>=<span>1D55D</span></span>
- <span><math><mi>&#x1D55E;</mi></math>=<span>1D55E</span></span>
- <span><math><mi>&#x1D55F;</mi></math>=<span>1D55F</span></span>
- <span><math><mi>&#x1D560;</mi></math>=<span>1D560</span></span>
- <span><math><mi>&#x1D561;</mi></math>=<span>1D561</span></span><br/>
- <span><math><mi>&#x1D562;</mi></math>=<span>1D562</span></span>
- <span><math><mi>&#x1D563;</mi></math>=<span>1D563</span></span>
- <span><math><mi>&#x1D564;</mi></math>=<span>1D564</span></span>
- <span><math><mi>&#x1D565;</mi></math>=<span>1D565</span></span>
- <span><math><mi>&#x1D566;</mi></math>=<span>1D566</span></span>
- <span><math><mi>&#x1D567;</mi></math>=<span>1D567</span></span>
- <span><math><mi>&#x1D568;</mi></math>=<span>1D568</span></span>
- <span><math><mi>&#x1D569;</mi></math>=<span>1D569</span></span>
- <span><math><mi>&#x1D56A;</mi></math>=<span>1D56A</span></span>
- <span><math><mi>&#x1D56B;</mi></math>=<span>1D56B</span></span><br/>
- <span><math><mi>&#x1D7D8;</mi></math>=<span>1D7D8</span></span>
- <span><math><mi>&#x1D7D9;</mi></math>=<span>1D7D9</span></span>
- <span><math><mi>&#x1D7DA;</mi></math>=<span>1D7DA</span></span>
- <span><math><mi>&#x1EEAE;</mi></math>=<span>1EEAE</span></span>
- <span><math><mi>&#x1EEB4;</mi></math>=<span>1EEB4</span></span>
- <span><math><mi>&#x1EEB1;</mi></math>=<span>1EEB1</span></span>
- <span><math><mi>&#x1D7DE;</mi></math>=<span>1D7DE</span></span>
- <span><math><mi>&#x1D7DF;</mi></math>=<span>1D7DF</span></span>
- <span><math><mi>&#x1D7E0;</mi></math>=<span>1D7E0</span></span>
- <span><math><mi>&#x1EEAF;</mi></math>=<span>1EEAF</span></span><br/>
- <span><math><mi>&#x1D538;</mi></math>=<span>1D538</span></span>
- <span><math><mi>&#x1D539;</mi></math>=<span>1D539</span></span>
- <span><math><mi>&#x1D53B;</mi></math>=<span>1D53B</span></span>
- <span><math><mi>&#x1D53C;</mi></math>=<span>1D53C</span></span>
- <span><math><mi>&#x1D53D;</mi></math>=<span>1D53D</span></span>
- <span><math><mi>&#x210D;</mi></math>=<span>0210D</span></span>
- <span><math><mi>&#x1D541;</mi></math>=<span>1D541</span></span>
+ <span><math><mtext>&#x1EEA1;</mtext></math>=<span>1EEA1</span></span>
+ <span><math><mtext>&#x1EEB5;</mtext></math>=<span>1EEB5</span></span>
+ <span><math><mtext>&#x1EEB6;</mtext></math>=<span>1EEB6</span></span>
+ <span><math><mtext>&#x1EEA2;</mtext></math>=<span>1EEA2</span></span>
+ <span><math><mtext>&#x1EEA7;</mtext></math>=<span>1EEA7</span></span>
+ <span><math><mtext>&#x1EEB7;</mtext></math>=<span>1EEB7</span></span>
+ <span><math><mtext>&#x1EEA3;</mtext></math>=<span>1EEA3</span></span>
+ <span><math><mtext>&#x1EEB8;</mtext></math>=<span>1EEB8</span></span>
+ <span><math><mtext>&#x1EEB3;</mtext></math>=<span>1EEB3</span></span>
+ <span><math><mtext>&#x1EEA6;</mtext></math>=<span>1EEA6</span></span><br/>
+ <span><math><mtext>&#x1D7DB;</mtext></math>=<span>1D7DB</span></span>
+ <span><math><mtext>&#x1D7DC;</mtext></math>=<span>1D7DC</span></span>
+ <span><math><mtext>&#x1D7DD;</mtext></math>=<span>1D7DD</span></span>
+ <span><math><mtext>&#x1EEB9;</mtext></math>=<span>1EEB9</span></span>
+ <span><math><mtext>&#x1EEA8;</mtext></math>=<span>1EEA8</span></span>
+ <span><math><mtext>&#x1EEBA;</mtext></math>=<span>1EEBA</span></span>
+ <span><math><mtext>&#x1D7E1;</mtext></math>=<span>1D7E1</span></span>
+ <span><math><mtext>&#x1EEBB;</mtext></math>=<span>1EEBB</span></span>
+ <span><math><mtext>&#x1EEB0;</mtext></math>=<span>1EEB0</span></span>
+ <span><math><mtext>&#x1EEB2;</mtext></math>=<span>1EEB2</span></span><br/>
+ <span><math><mtext>&#x2102;</mtext></math>=<span>02102</span></span>
+ <span><math><mtext>&#x1EEAB;</mtext></math>=<span>1EEAB</span></span>
+ <span><math><mtext>&#x1EEAC;</mtext></math>=<span>1EEAC</span></span>
+ <span><math><mtext>&#x1EEAD;</mtext></math>=<span>1EEAD</span></span>
+ <span><math><mtext>&#x1D53E;</mtext></math>=<span>1D53E</span></span>
+ <span><math><mtext>&#x1EEA5;</mtext></math>=<span>1EEA5</span></span>
+ <span><math><mtext>&#x1D540;</mtext></math>=<span>1D540</span></span>
+ <span><math><mtext>&#x1EEA9;</mtext></math>=<span>1EEA9</span></span>
+ <span><math><mtext>&#x1D542;</mtext></math>=<span>1D542</span></span>
+ <span><math><mtext>&#x1D543;</mtext></math>=<span>1D543</span></span><br/>
+ <span><math><mtext>&#x1D544;</mtext></math>=<span>1D544</span></span>
+ <span><math><mtext>&#x2115;</mtext></math>=<span>02115</span></span>
+ <span><math><mtext>&#x1D546;</mtext></math>=<span>1D546</span></span>
+ <span><math><mtext>&#x2119;</mtext></math>=<span>02119</span></span>
+ <span><math><mtext>&#x211A;</mtext></math>=<span>0211A</span></span>
+ <span><math><mtext>&#x211D;</mtext></math>=<span>0211D</span></span>
+ <span><math><mtext>&#x1D54A;</mtext></math>=<span>1D54A</span></span>
+ <span><math><mtext>&#x1D54B;</mtext></math>=<span>1D54B</span></span>
+ <span><math><mtext>&#x1D54C;</mtext></math>=<span>1D54C</span></span>
+ <span><math><mtext>&#x1D54D;</mtext></math>=<span>1D54D</span></span><br/>
+ <span><math><mtext>&#x1D54E;</mtext></math>=<span>1D54E</span></span>
+ <span><math><mtext>&#x1D54F;</mtext></math>=<span>1D54F</span></span>
+ <span><math><mtext>&#x1D550;</mtext></math>=<span>1D550</span></span>
+ <span><math><mtext>&#x2124;</mtext></math>=<span>02124</span></span>
+ <span><math><mtext>&#x1D552;</mtext></math>=<span>1D552</span></span>
+ <span><math><mtext>&#x1D553;</mtext></math>=<span>1D553</span></span>
+ <span><math><mtext>&#x1D554;</mtext></math>=<span>1D554</span></span>
+ <span><math><mtext>&#x1D555;</mtext></math>=<span>1D555</span></span>
+ <span><math><mtext>&#x1D556;</mtext></math>=<span>1D556</span></span>
+ <span><math><mtext>&#x1D557;</mtext></math>=<span>1D557</span></span><br/>
+ <span><math><mtext>&#x1D558;</mtext></math>=<span>1D558</span></span>
+ <span><math><mtext>&#x1D559;</mtext></math>=<span>1D559</span></span>
+ <span><math><mtext>&#x1D55A;</mtext></math>=<span>1D55A</span></span>
+ <span><math><mtext>&#x1D55B;</mtext></math>=<span>1D55B</span></span>
+ <span><math><mtext>&#x1D55C;</mtext></math>=<span>1D55C</span></span>
+ <span><math><mtext>&#x1D55D;</mtext></math>=<span>1D55D</span></span>
+ <span><math><mtext>&#x1D55E;</mtext></math>=<span>1D55E</span></span>
+ <span><math><mtext>&#x1D55F;</mtext></math>=<span>1D55F</span></span>
+ <span><math><mtext>&#x1D560;</mtext></math>=<span>1D560</span></span>
+ <span><math><mtext>&#x1D561;</mtext></math>=<span>1D561</span></span><br/>
+ <span><math><mtext>&#x1D562;</mtext></math>=<span>1D562</span></span>
+ <span><math><mtext>&#x1D563;</mtext></math>=<span>1D563</span></span>
+ <span><math><mtext>&#x1D564;</mtext></math>=<span>1D564</span></span>
+ <span><math><mtext>&#x1D565;</mtext></math>=<span>1D565</span></span>
+ <span><math><mtext>&#x1D566;</mtext></math>=<span>1D566</span></span>
+ <span><math><mtext>&#x1D567;</mtext></math>=<span>1D567</span></span>
+ <span><math><mtext>&#x1D568;</mtext></math>=<span>1D568</span></span>
+ <span><math><mtext>&#x1D569;</mtext></math>=<span>1D569</span></span>
+ <span><math><mtext>&#x1D56A;</mtext></math>=<span>1D56A</span></span>
+ <span><math><mtext>&#x1D56B;</mtext></math>=<span>1D56B</span></span><br/>
+ <span><math><mtext>&#x1D7D8;</mtext></math>=<span>1D7D8</span></span>
+ <span><math><mtext>&#x1D7D9;</mtext></math>=<span>1D7D9</span></span>
+ <span><math><mtext>&#x1D7DA;</mtext></math>=<span>1D7DA</span></span>
+ <span><math><mtext>&#x1EEAE;</mtext></math>=<span>1EEAE</span></span>
+ <span><math><mtext>&#x1EEB4;</mtext></math>=<span>1EEB4</span></span>
+ <span><math><mtext>&#x1EEB1;</mtext></math>=<span>1EEB1</span></span>
+ <span><math><mtext>&#x1D7DE;</mtext></math>=<span>1D7DE</span></span>
+ <span><math><mtext>&#x1D7DF;</mtext></math>=<span>1D7DF</span></span>
+ <span><math><mtext>&#x1D7E0;</mtext></math>=<span>1D7E0</span></span>
+ <span><math><mtext>&#x1EEAF;</mtext></math>=<span>1EEAF</span></span><br/>
+ <span><math><mtext>&#x1D538;</mtext></math>=<span>1D538</span></span>
+ <span><math><mtext>&#x1D539;</mtext></math>=<span>1D539</span></span>
+ <span><math><mtext>&#x1D53B;</mtext></math>=<span>1D53B</span></span>
+ <span><math><mtext>&#x1D53C;</mtext></math>=<span>1D53C</span></span>
+ <span><math><mtext>&#x1D53D;</mtext></math>=<span>1D53D</span></span>
+ <span><math><mtext>&#x210D;</mtext></math>=<span>0210D</span></span>
+ <span><math><mtext>&#x1D541;</mtext></math>=<span>1D541</span></span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-double-struck.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-double-struck.html
index e0772d20feb..e51908e1ea3 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-double-struck.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-double-struck.html
@@ -5,7 +5,7 @@
<title>mathvariant double-struck</title>
<link rel="help" href="http://www.mathml-association.org/MathMLinHTML5/S2.html#SS3.SSS1.tab2"/>
<link rel="match" href="mathvariant-double-struck-ref.html"/>
-<meta name="assert" content="Verify that a single-char <mi> with a double-struck mathvariant is equivalent to an <mi> with the transformed unicode character.">
+<meta name="assert" content="Verify that a single-char <mtext> with a double-struck mathvariant is equivalent to an <mtext> with the transformed unicode character.">
<style>
@font-face {
font-family: TestFont;
@@ -26,92 +26,92 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi mathvariant="double-struck">&#x628;</mi></math>=<span>1EEA1</span></span>
- <span><math><mi mathvariant="double-struck">&#x62A;</mi></math>=<span>1EEB5</span></span>
- <span><math><mi mathvariant="double-struck">&#x62B;</mi></math>=<span>1EEB6</span></span>
- <span><math><mi mathvariant="double-struck">&#x62C;</mi></math>=<span>1EEA2</span></span>
- <span><math><mi mathvariant="double-struck">&#x62D;</mi></math>=<span>1EEA7</span></span>
- <span><math><mi mathvariant="double-struck">&#x62E;</mi></math>=<span>1EEB7</span></span>
- <span><math><mi mathvariant="double-struck">&#x62F;</mi></math>=<span>1EEA3</span></span>
- <span><math><mi mathvariant="double-struck">&#x630;</mi></math>=<span>1EEB8</span></span>
- <span><math><mi mathvariant="double-struck">&#x631;</mi></math>=<span>1EEB3</span></span>
- <span><math><mi mathvariant="double-struck">&#x632;</mi></math>=<span>1EEA6</span></span><br/>
- <span><math><mi mathvariant="double-struck">&#x33;</mi></math>=<span>1D7DB</span></span>
- <span><math><mi mathvariant="double-struck">&#x34;</mi></math>=<span>1D7DC</span></span>
- <span><math><mi mathvariant="double-struck">&#x35;</mi></math>=<span>1D7DD</span></span>
- <span><math><mi mathvariant="double-struck">&#x636;</mi></math>=<span>1EEB9</span></span>
- <span><math><mi mathvariant="double-struck">&#x637;</mi></math>=<span>1EEA8</span></span>
- <span><math><mi mathvariant="double-struck">&#x638;</mi></math>=<span>1EEBA</span></span>
- <span><math><mi mathvariant="double-struck">&#x39;</mi></math>=<span>1D7E1</span></span>
- <span><math><mi mathvariant="double-struck">&#x63A;</mi></math>=<span>1EEBB</span></span>
- <span><math><mi mathvariant="double-struck">&#x641;</mi></math>=<span>1EEB0</span></span>
- <span><math><mi mathvariant="double-struck">&#x642;</mi></math>=<span>1EEB2</span></span><br/>
- <span><math><mi mathvariant="double-struck">&#x43;</mi></math>=<span>02102</span></span>
- <span><math><mi mathvariant="double-struck">&#x644;</mi></math>=<span>1EEAB</span></span>
- <span><math><mi mathvariant="double-struck">&#x645;</mi></math>=<span>1EEAC</span></span>
- <span><math><mi mathvariant="double-struck">&#x646;</mi></math>=<span>1EEAD</span></span>
- <span><math><mi mathvariant="double-struck">&#x47;</mi></math>=<span>1D53E</span></span>
- <span><math><mi mathvariant="double-struck">&#x648;</mi></math>=<span>1EEA5</span></span>
- <span><math><mi mathvariant="double-struck">&#x49;</mi></math>=<span>1D540</span></span>
- <span><math><mi mathvariant="double-struck">&#x64A;</mi></math>=<span>1EEA9</span></span>
- <span><math><mi mathvariant="double-struck">&#x4B;</mi></math>=<span>1D542</span></span>
- <span><math><mi mathvariant="double-struck">&#x4C;</mi></math>=<span>1D543</span></span><br/>
- <span><math><mi mathvariant="double-struck">&#x4D;</mi></math>=<span>1D544</span></span>
- <span><math><mi mathvariant="double-struck">&#x4E;</mi></math>=<span>02115</span></span>
- <span><math><mi mathvariant="double-struck">&#x4F;</mi></math>=<span>1D546</span></span>
- <span><math><mi mathvariant="double-struck">&#x50;</mi></math>=<span>02119</span></span>
- <span><math><mi mathvariant="double-struck">&#x51;</mi></math>=<span>0211A</span></span>
- <span><math><mi mathvariant="double-struck">&#x52;</mi></math>=<span>0211D</span></span>
- <span><math><mi mathvariant="double-struck">&#x53;</mi></math>=<span>1D54A</span></span>
- <span><math><mi mathvariant="double-struck">&#x54;</mi></math>=<span>1D54B</span></span>
- <span><math><mi mathvariant="double-struck">&#x55;</mi></math>=<span>1D54C</span></span>
- <span><math><mi mathvariant="double-struck">&#x56;</mi></math>=<span>1D54D</span></span><br/>
- <span><math><mi mathvariant="double-struck">&#x57;</mi></math>=<span>1D54E</span></span>
- <span><math><mi mathvariant="double-struck">&#x58;</mi></math>=<span>1D54F</span></span>
- <span><math><mi mathvariant="double-struck">&#x59;</mi></math>=<span>1D550</span></span>
- <span><math><mi mathvariant="double-struck">&#x5A;</mi></math>=<span>02124</span></span>
- <span><math><mi mathvariant="double-struck">&#x61;</mi></math>=<span>1D552</span></span>
- <span><math><mi mathvariant="double-struck">&#x62;</mi></math>=<span>1D553</span></span>
- <span><math><mi mathvariant="double-struck">&#x63;</mi></math>=<span>1D554</span></span>
- <span><math><mi mathvariant="double-struck">&#x64;</mi></math>=<span>1D555</span></span>
- <span><math><mi mathvariant="double-struck">&#x65;</mi></math>=<span>1D556</span></span>
- <span><math><mi mathvariant="double-struck">&#x66;</mi></math>=<span>1D557</span></span><br/>
- <span><math><mi mathvariant="double-struck">&#x67;</mi></math>=<span>1D558</span></span>
- <span><math><mi mathvariant="double-struck">&#x68;</mi></math>=<span>1D559</span></span>
- <span><math><mi mathvariant="double-struck">&#x69;</mi></math>=<span>1D55A</span></span>
- <span><math><mi mathvariant="double-struck">&#x6A;</mi></math>=<span>1D55B</span></span>
- <span><math><mi mathvariant="double-struck">&#x6B;</mi></math>=<span>1D55C</span></span>
- <span><math><mi mathvariant="double-struck">&#x6C;</mi></math>=<span>1D55D</span></span>
- <span><math><mi mathvariant="double-struck">&#x6D;</mi></math>=<span>1D55E</span></span>
- <span><math><mi mathvariant="double-struck">&#x6E;</mi></math>=<span>1D55F</span></span>
- <span><math><mi mathvariant="double-struck">&#x6F;</mi></math>=<span>1D560</span></span>
- <span><math><mi mathvariant="double-struck">&#x70;</mi></math>=<span>1D561</span></span><br/>
- <span><math><mi mathvariant="double-struck">&#x71;</mi></math>=<span>1D562</span></span>
- <span><math><mi mathvariant="double-struck">&#x72;</mi></math>=<span>1D563</span></span>
- <span><math><mi mathvariant="double-struck">&#x73;</mi></math>=<span>1D564</span></span>
- <span><math><mi mathvariant="double-struck">&#x74;</mi></math>=<span>1D565</span></span>
- <span><math><mi mathvariant="double-struck">&#x75;</mi></math>=<span>1D566</span></span>
- <span><math><mi mathvariant="double-struck">&#x76;</mi></math>=<span>1D567</span></span>
- <span><math><mi mathvariant="double-struck">&#x77;</mi></math>=<span>1D568</span></span>
- <span><math><mi mathvariant="double-struck">&#x78;</mi></math>=<span>1D569</span></span>
- <span><math><mi mathvariant="double-struck">&#x79;</mi></math>=<span>1D56A</span></span>
- <span><math><mi mathvariant="double-struck">&#x7A;</mi></math>=<span>1D56B</span></span><br/>
- <span><math><mi mathvariant="double-struck">&#x30;</mi></math>=<span>1D7D8</span></span>
- <span><math><mi mathvariant="double-struck">&#x31;</mi></math>=<span>1D7D9</span></span>
- <span><math><mi mathvariant="double-struck">&#x32;</mi></math>=<span>1D7DA</span></span>
- <span><math><mi mathvariant="double-struck">&#x633;</mi></math>=<span>1EEAE</span></span>
- <span><math><mi mathvariant="double-struck">&#x634;</mi></math>=<span>1EEB4</span></span>
- <span><math><mi mathvariant="double-struck">&#x635;</mi></math>=<span>1EEB1</span></span>
- <span><math><mi mathvariant="double-struck">&#x36;</mi></math>=<span>1D7DE</span></span>
- <span><math><mi mathvariant="double-struck">&#x37;</mi></math>=<span>1D7DF</span></span>
- <span><math><mi mathvariant="double-struck">&#x38;</mi></math>=<span>1D7E0</span></span>
- <span><math><mi mathvariant="double-struck">&#x639;</mi></math>=<span>1EEAF</span></span><br/>
- <span><math><mi mathvariant="double-struck">&#x41;</mi></math>=<span>1D538</span></span>
- <span><math><mi mathvariant="double-struck">&#x42;</mi></math>=<span>1D539</span></span>
- <span><math><mi mathvariant="double-struck">&#x44;</mi></math>=<span>1D53B</span></span>
- <span><math><mi mathvariant="double-struck">&#x45;</mi></math>=<span>1D53C</span></span>
- <span><math><mi mathvariant="double-struck">&#x46;</mi></math>=<span>1D53D</span></span>
- <span><math><mi mathvariant="double-struck">&#x48;</mi></math>=<span>0210D</span></span>
- <span><math><mi mathvariant="double-struck">&#x4A;</mi></math>=<span>1D541</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x628;</mtext></math>=<span>1EEA1</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x62A;</mtext></math>=<span>1EEB5</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x62B;</mtext></math>=<span>1EEB6</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x62C;</mtext></math>=<span>1EEA2</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x62D;</mtext></math>=<span>1EEA7</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x62E;</mtext></math>=<span>1EEB7</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x62F;</mtext></math>=<span>1EEA3</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x630;</mtext></math>=<span>1EEB8</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x631;</mtext></math>=<span>1EEB3</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x632;</mtext></math>=<span>1EEA6</span></span><br/>
+ <span><math><mtext mathvariant="double-struck">&#x33;</mtext></math>=<span>1D7DB</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x34;</mtext></math>=<span>1D7DC</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x35;</mtext></math>=<span>1D7DD</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x636;</mtext></math>=<span>1EEB9</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x637;</mtext></math>=<span>1EEA8</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x638;</mtext></math>=<span>1EEBA</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x39;</mtext></math>=<span>1D7E1</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x63A;</mtext></math>=<span>1EEBB</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x641;</mtext></math>=<span>1EEB0</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x642;</mtext></math>=<span>1EEB2</span></span><br/>
+ <span><math><mtext mathvariant="double-struck">&#x43;</mtext></math>=<span>02102</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x644;</mtext></math>=<span>1EEAB</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x645;</mtext></math>=<span>1EEAC</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x646;</mtext></math>=<span>1EEAD</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x47;</mtext></math>=<span>1D53E</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x648;</mtext></math>=<span>1EEA5</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x49;</mtext></math>=<span>1D540</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x64A;</mtext></math>=<span>1EEA9</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x4B;</mtext></math>=<span>1D542</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x4C;</mtext></math>=<span>1D543</span></span><br/>
+ <span><math><mtext mathvariant="double-struck">&#x4D;</mtext></math>=<span>1D544</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x4E;</mtext></math>=<span>02115</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x4F;</mtext></math>=<span>1D546</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x50;</mtext></math>=<span>02119</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x51;</mtext></math>=<span>0211A</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x52;</mtext></math>=<span>0211D</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x53;</mtext></math>=<span>1D54A</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x54;</mtext></math>=<span>1D54B</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x55;</mtext></math>=<span>1D54C</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x56;</mtext></math>=<span>1D54D</span></span><br/>
+ <span><math><mtext mathvariant="double-struck">&#x57;</mtext></math>=<span>1D54E</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x58;</mtext></math>=<span>1D54F</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x59;</mtext></math>=<span>1D550</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x5A;</mtext></math>=<span>02124</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x61;</mtext></math>=<span>1D552</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x62;</mtext></math>=<span>1D553</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x63;</mtext></math>=<span>1D554</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x64;</mtext></math>=<span>1D555</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x65;</mtext></math>=<span>1D556</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x66;</mtext></math>=<span>1D557</span></span><br/>
+ <span><math><mtext mathvariant="double-struck">&#x67;</mtext></math>=<span>1D558</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x68;</mtext></math>=<span>1D559</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x69;</mtext></math>=<span>1D55A</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x6A;</mtext></math>=<span>1D55B</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x6B;</mtext></math>=<span>1D55C</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x6C;</mtext></math>=<span>1D55D</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x6D;</mtext></math>=<span>1D55E</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x6E;</mtext></math>=<span>1D55F</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x6F;</mtext></math>=<span>1D560</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x70;</mtext></math>=<span>1D561</span></span><br/>
+ <span><math><mtext mathvariant="double-struck">&#x71;</mtext></math>=<span>1D562</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x72;</mtext></math>=<span>1D563</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x73;</mtext></math>=<span>1D564</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x74;</mtext></math>=<span>1D565</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x75;</mtext></math>=<span>1D566</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x76;</mtext></math>=<span>1D567</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x77;</mtext></math>=<span>1D568</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x78;</mtext></math>=<span>1D569</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x79;</mtext></math>=<span>1D56A</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x7A;</mtext></math>=<span>1D56B</span></span><br/>
+ <span><math><mtext mathvariant="double-struck">&#x30;</mtext></math>=<span>1D7D8</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x31;</mtext></math>=<span>1D7D9</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x32;</mtext></math>=<span>1D7DA</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x633;</mtext></math>=<span>1EEAE</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x634;</mtext></math>=<span>1EEB4</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x635;</mtext></math>=<span>1EEB1</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x36;</mtext></math>=<span>1D7DE</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x37;</mtext></math>=<span>1D7DF</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x38;</mtext></math>=<span>1D7E0</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x639;</mtext></math>=<span>1EEAF</span></span><br/>
+ <span><math><mtext mathvariant="double-struck">&#x41;</mtext></math>=<span>1D538</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x42;</mtext></math>=<span>1D539</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x44;</mtext></math>=<span>1D53B</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x45;</mtext></math>=<span>1D53C</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x46;</mtext></math>=<span>1D53D</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x48;</mtext></math>=<span>0210D</span></span>
+ <span><math><mtext mathvariant="double-struck">&#x4A;</mtext></math>=<span>1D541</span></span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-fraktur-ref.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-fraktur-ref.html
index 6067f21c7f9..5e0721cfcea 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-fraktur-ref.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-fraktur-ref.html
@@ -23,57 +23,57 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi>&#x1D504;</mi></math>=<span>1D504</span></span>
- <span><math><mi>&#x1D505;</mi></math>=<span>1D505</span></span>
- <span><math><mi>&#x212D;</mi></math>=<span>0212D</span></span>
- <span><math><mi>&#x1D507;</mi></math>=<span>1D507</span></span>
- <span><math><mi>&#x1D508;</mi></math>=<span>1D508</span></span>
- <span><math><mi>&#x1D509;</mi></math>=<span>1D509</span></span>
- <span><math><mi>&#x1D50A;</mi></math>=<span>1D50A</span></span>
- <span><math><mi>&#x210C;</mi></math>=<span>0210C</span></span>
- <span><math><mi>&#x2111;</mi></math>=<span>02111</span></span>
- <span><math><mi>&#x1D50D;</mi></math>=<span>1D50D</span></span><br/>
- <span><math><mi>&#x1D50E;</mi></math>=<span>1D50E</span></span>
- <span><math><mi>&#x1D50F;</mi></math>=<span>1D50F</span></span>
- <span><math><mi>&#x1D510;</mi></math>=<span>1D510</span></span>
- <span><math><mi>&#x1D511;</mi></math>=<span>1D511</span></span>
- <span><math><mi>&#x1D512;</mi></math>=<span>1D512</span></span>
- <span><math><mi>&#x1D513;</mi></math>=<span>1D513</span></span>
- <span><math><mi>&#x1D514;</mi></math>=<span>1D514</span></span>
- <span><math><mi>&#x211C;</mi></math>=<span>0211C</span></span>
- <span><math><mi>&#x1D516;</mi></math>=<span>1D516</span></span>
- <span><math><mi>&#x1D517;</mi></math>=<span>1D517</span></span><br/>
- <span><math><mi>&#x1D518;</mi></math>=<span>1D518</span></span>
- <span><math><mi>&#x1D519;</mi></math>=<span>1D519</span></span>
- <span><math><mi>&#x1D51A;</mi></math>=<span>1D51A</span></span>
- <span><math><mi>&#x1D51B;</mi></math>=<span>1D51B</span></span>
- <span><math><mi>&#x1D51C;</mi></math>=<span>1D51C</span></span>
- <span><math><mi>&#x2128;</mi></math>=<span>02128</span></span>
- <span><math><mi>&#x1D51E;</mi></math>=<span>1D51E</span></span>
- <span><math><mi>&#x1D51F;</mi></math>=<span>1D51F</span></span>
- <span><math><mi>&#x1D520;</mi></math>=<span>1D520</span></span>
- <span><math><mi>&#x1D521;</mi></math>=<span>1D521</span></span><br/>
- <span><math><mi>&#x1D522;</mi></math>=<span>1D522</span></span>
- <span><math><mi>&#x1D523;</mi></math>=<span>1D523</span></span>
- <span><math><mi>&#x1D524;</mi></math>=<span>1D524</span></span>
- <span><math><mi>&#x1D525;</mi></math>=<span>1D525</span></span>
- <span><math><mi>&#x1D526;</mi></math>=<span>1D526</span></span>
- <span><math><mi>&#x1D527;</mi></math>=<span>1D527</span></span>
- <span><math><mi>&#x1D528;</mi></math>=<span>1D528</span></span>
- <span><math><mi>&#x1D529;</mi></math>=<span>1D529</span></span>
- <span><math><mi>&#x1D52A;</mi></math>=<span>1D52A</span></span>
- <span><math><mi>&#x1D52B;</mi></math>=<span>1D52B</span></span><br/>
- <span><math><mi>&#x1D52C;</mi></math>=<span>1D52C</span></span>
- <span><math><mi>&#x1D52D;</mi></math>=<span>1D52D</span></span>
- <span><math><mi>&#x1D52E;</mi></math>=<span>1D52E</span></span>
- <span><math><mi>&#x1D52F;</mi></math>=<span>1D52F</span></span>
- <span><math><mi>&#x1D530;</mi></math>=<span>1D530</span></span>
- <span><math><mi>&#x1D531;</mi></math>=<span>1D531</span></span>
- <span><math><mi>&#x1D532;</mi></math>=<span>1D532</span></span>
- <span><math><mi>&#x1D533;</mi></math>=<span>1D533</span></span>
- <span><math><mi>&#x1D534;</mi></math>=<span>1D534</span></span>
- <span><math><mi>&#x1D535;</mi></math>=<span>1D535</span></span><br/>
- <span><math><mi>&#x1D536;</mi></math>=<span>1D536</span></span>
- <span><math><mi>&#x1D537;</mi></math>=<span>1D537</span></span>
+ <span><math><mtext>&#x1D504;</mtext></math>=<span>1D504</span></span>
+ <span><math><mtext>&#x1D505;</mtext></math>=<span>1D505</span></span>
+ <span><math><mtext>&#x212D;</mtext></math>=<span>0212D</span></span>
+ <span><math><mtext>&#x1D507;</mtext></math>=<span>1D507</span></span>
+ <span><math><mtext>&#x1D508;</mtext></math>=<span>1D508</span></span>
+ <span><math><mtext>&#x1D509;</mtext></math>=<span>1D509</span></span>
+ <span><math><mtext>&#x1D50A;</mtext></math>=<span>1D50A</span></span>
+ <span><math><mtext>&#x210C;</mtext></math>=<span>0210C</span></span>
+ <span><math><mtext>&#x2111;</mtext></math>=<span>02111</span></span>
+ <span><math><mtext>&#x1D50D;</mtext></math>=<span>1D50D</span></span><br/>
+ <span><math><mtext>&#x1D50E;</mtext></math>=<span>1D50E</span></span>
+ <span><math><mtext>&#x1D50F;</mtext></math>=<span>1D50F</span></span>
+ <span><math><mtext>&#x1D510;</mtext></math>=<span>1D510</span></span>
+ <span><math><mtext>&#x1D511;</mtext></math>=<span>1D511</span></span>
+ <span><math><mtext>&#x1D512;</mtext></math>=<span>1D512</span></span>
+ <span><math><mtext>&#x1D513;</mtext></math>=<span>1D513</span></span>
+ <span><math><mtext>&#x1D514;</mtext></math>=<span>1D514</span></span>
+ <span><math><mtext>&#x211C;</mtext></math>=<span>0211C</span></span>
+ <span><math><mtext>&#x1D516;</mtext></math>=<span>1D516</span></span>
+ <span><math><mtext>&#x1D517;</mtext></math>=<span>1D517</span></span><br/>
+ <span><math><mtext>&#x1D518;</mtext></math>=<span>1D518</span></span>
+ <span><math><mtext>&#x1D519;</mtext></math>=<span>1D519</span></span>
+ <span><math><mtext>&#x1D51A;</mtext></math>=<span>1D51A</span></span>
+ <span><math><mtext>&#x1D51B;</mtext></math>=<span>1D51B</span></span>
+ <span><math><mtext>&#x1D51C;</mtext></math>=<span>1D51C</span></span>
+ <span><math><mtext>&#x2128;</mtext></math>=<span>02128</span></span>
+ <span><math><mtext>&#x1D51E;</mtext></math>=<span>1D51E</span></span>
+ <span><math><mtext>&#x1D51F;</mtext></math>=<span>1D51F</span></span>
+ <span><math><mtext>&#x1D520;</mtext></math>=<span>1D520</span></span>
+ <span><math><mtext>&#x1D521;</mtext></math>=<span>1D521</span></span><br/>
+ <span><math><mtext>&#x1D522;</mtext></math>=<span>1D522</span></span>
+ <span><math><mtext>&#x1D523;</mtext></math>=<span>1D523</span></span>
+ <span><math><mtext>&#x1D524;</mtext></math>=<span>1D524</span></span>
+ <span><math><mtext>&#x1D525;</mtext></math>=<span>1D525</span></span>
+ <span><math><mtext>&#x1D526;</mtext></math>=<span>1D526</span></span>
+ <span><math><mtext>&#x1D527;</mtext></math>=<span>1D527</span></span>
+ <span><math><mtext>&#x1D528;</mtext></math>=<span>1D528</span></span>
+ <span><math><mtext>&#x1D529;</mtext></math>=<span>1D529</span></span>
+ <span><math><mtext>&#x1D52A;</mtext></math>=<span>1D52A</span></span>
+ <span><math><mtext>&#x1D52B;</mtext></math>=<span>1D52B</span></span><br/>
+ <span><math><mtext>&#x1D52C;</mtext></math>=<span>1D52C</span></span>
+ <span><math><mtext>&#x1D52D;</mtext></math>=<span>1D52D</span></span>
+ <span><math><mtext>&#x1D52E;</mtext></math>=<span>1D52E</span></span>
+ <span><math><mtext>&#x1D52F;</mtext></math>=<span>1D52F</span></span>
+ <span><math><mtext>&#x1D530;</mtext></math>=<span>1D530</span></span>
+ <span><math><mtext>&#x1D531;</mtext></math>=<span>1D531</span></span>
+ <span><math><mtext>&#x1D532;</mtext></math>=<span>1D532</span></span>
+ <span><math><mtext>&#x1D533;</mtext></math>=<span>1D533</span></span>
+ <span><math><mtext>&#x1D534;</mtext></math>=<span>1D534</span></span>
+ <span><math><mtext>&#x1D535;</mtext></math>=<span>1D535</span></span><br/>
+ <span><math><mtext>&#x1D536;</mtext></math>=<span>1D536</span></span>
+ <span><math><mtext>&#x1D537;</mtext></math>=<span>1D537</span></span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-fraktur.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-fraktur.html
index a01b0871dcc..124891727cd 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-fraktur.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-fraktur.html
@@ -5,7 +5,7 @@
<title>mathvariant fraktur</title>
<link rel="help" href="http://www.mathml-association.org/MathMLinHTML5/S2.html#SS3.SSS1.tab2"/>
<link rel="match" href="mathvariant-fraktur-ref.html"/>
-<meta name="assert" content="Verify that a single-char <mi> with a fraktur mathvariant is equivalent to an <mi> with the transformed unicode character.">
+<meta name="assert" content="Verify that a single-char <mtext> with a fraktur mathvariant is equivalent to an <mtext> with the transformed unicode character.">
<style>
@font-face {
font-family: TestFont;
@@ -26,57 +26,57 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi mathvariant="fraktur">&#x41;</mi></math>=<span>1D504</span></span>
- <span><math><mi mathvariant="fraktur">&#x42;</mi></math>=<span>1D505</span></span>
- <span><math><mi mathvariant="fraktur">&#x43;</mi></math>=<span>0212D</span></span>
- <span><math><mi mathvariant="fraktur">&#x44;</mi></math>=<span>1D507</span></span>
- <span><math><mi mathvariant="fraktur">&#x45;</mi></math>=<span>1D508</span></span>
- <span><math><mi mathvariant="fraktur">&#x46;</mi></math>=<span>1D509</span></span>
- <span><math><mi mathvariant="fraktur">&#x47;</mi></math>=<span>1D50A</span></span>
- <span><math><mi mathvariant="fraktur">&#x48;</mi></math>=<span>0210C</span></span>
- <span><math><mi mathvariant="fraktur">&#x49;</mi></math>=<span>02111</span></span>
- <span><math><mi mathvariant="fraktur">&#x4A;</mi></math>=<span>1D50D</span></span><br/>
- <span><math><mi mathvariant="fraktur">&#x4B;</mi></math>=<span>1D50E</span></span>
- <span><math><mi mathvariant="fraktur">&#x4C;</mi></math>=<span>1D50F</span></span>
- <span><math><mi mathvariant="fraktur">&#x4D;</mi></math>=<span>1D510</span></span>
- <span><math><mi mathvariant="fraktur">&#x4E;</mi></math>=<span>1D511</span></span>
- <span><math><mi mathvariant="fraktur">&#x4F;</mi></math>=<span>1D512</span></span>
- <span><math><mi mathvariant="fraktur">&#x50;</mi></math>=<span>1D513</span></span>
- <span><math><mi mathvariant="fraktur">&#x51;</mi></math>=<span>1D514</span></span>
- <span><math><mi mathvariant="fraktur">&#x52;</mi></math>=<span>0211C</span></span>
- <span><math><mi mathvariant="fraktur">&#x53;</mi></math>=<span>1D516</span></span>
- <span><math><mi mathvariant="fraktur">&#x54;</mi></math>=<span>1D517</span></span><br/>
- <span><math><mi mathvariant="fraktur">&#x55;</mi></math>=<span>1D518</span></span>
- <span><math><mi mathvariant="fraktur">&#x56;</mi></math>=<span>1D519</span></span>
- <span><math><mi mathvariant="fraktur">&#x57;</mi></math>=<span>1D51A</span></span>
- <span><math><mi mathvariant="fraktur">&#x58;</mi></math>=<span>1D51B</span></span>
- <span><math><mi mathvariant="fraktur">&#x59;</mi></math>=<span>1D51C</span></span>
- <span><math><mi mathvariant="fraktur">&#x5A;</mi></math>=<span>02128</span></span>
- <span><math><mi mathvariant="fraktur">&#x61;</mi></math>=<span>1D51E</span></span>
- <span><math><mi mathvariant="fraktur">&#x62;</mi></math>=<span>1D51F</span></span>
- <span><math><mi mathvariant="fraktur">&#x63;</mi></math>=<span>1D520</span></span>
- <span><math><mi mathvariant="fraktur">&#x64;</mi></math>=<span>1D521</span></span><br/>
- <span><math><mi mathvariant="fraktur">&#x65;</mi></math>=<span>1D522</span></span>
- <span><math><mi mathvariant="fraktur">&#x66;</mi></math>=<span>1D523</span></span>
- <span><math><mi mathvariant="fraktur">&#x67;</mi></math>=<span>1D524</span></span>
- <span><math><mi mathvariant="fraktur">&#x68;</mi></math>=<span>1D525</span></span>
- <span><math><mi mathvariant="fraktur">&#x69;</mi></math>=<span>1D526</span></span>
- <span><math><mi mathvariant="fraktur">&#x6A;</mi></math>=<span>1D527</span></span>
- <span><math><mi mathvariant="fraktur">&#x6B;</mi></math>=<span>1D528</span></span>
- <span><math><mi mathvariant="fraktur">&#x6C;</mi></math>=<span>1D529</span></span>
- <span><math><mi mathvariant="fraktur">&#x6D;</mi></math>=<span>1D52A</span></span>
- <span><math><mi mathvariant="fraktur">&#x6E;</mi></math>=<span>1D52B</span></span><br/>
- <span><math><mi mathvariant="fraktur">&#x6F;</mi></math>=<span>1D52C</span></span>
- <span><math><mi mathvariant="fraktur">&#x70;</mi></math>=<span>1D52D</span></span>
- <span><math><mi mathvariant="fraktur">&#x71;</mi></math>=<span>1D52E</span></span>
- <span><math><mi mathvariant="fraktur">&#x72;</mi></math>=<span>1D52F</span></span>
- <span><math><mi mathvariant="fraktur">&#x73;</mi></math>=<span>1D530</span></span>
- <span><math><mi mathvariant="fraktur">&#x74;</mi></math>=<span>1D531</span></span>
- <span><math><mi mathvariant="fraktur">&#x75;</mi></math>=<span>1D532</span></span>
- <span><math><mi mathvariant="fraktur">&#x76;</mi></math>=<span>1D533</span></span>
- <span><math><mi mathvariant="fraktur">&#x77;</mi></math>=<span>1D534</span></span>
- <span><math><mi mathvariant="fraktur">&#x78;</mi></math>=<span>1D535</span></span><br/>
- <span><math><mi mathvariant="fraktur">&#x79;</mi></math>=<span>1D536</span></span>
- <span><math><mi mathvariant="fraktur">&#x7A;</mi></math>=<span>1D537</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x41;</mtext></math>=<span>1D504</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x42;</mtext></math>=<span>1D505</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x43;</mtext></math>=<span>0212D</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x44;</mtext></math>=<span>1D507</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x45;</mtext></math>=<span>1D508</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x46;</mtext></math>=<span>1D509</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x47;</mtext></math>=<span>1D50A</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x48;</mtext></math>=<span>0210C</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x49;</mtext></math>=<span>02111</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x4A;</mtext></math>=<span>1D50D</span></span><br/>
+ <span><math><mtext mathvariant="fraktur">&#x4B;</mtext></math>=<span>1D50E</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x4C;</mtext></math>=<span>1D50F</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x4D;</mtext></math>=<span>1D510</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x4E;</mtext></math>=<span>1D511</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x4F;</mtext></math>=<span>1D512</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x50;</mtext></math>=<span>1D513</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x51;</mtext></math>=<span>1D514</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x52;</mtext></math>=<span>0211C</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x53;</mtext></math>=<span>1D516</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x54;</mtext></math>=<span>1D517</span></span><br/>
+ <span><math><mtext mathvariant="fraktur">&#x55;</mtext></math>=<span>1D518</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x56;</mtext></math>=<span>1D519</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x57;</mtext></math>=<span>1D51A</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x58;</mtext></math>=<span>1D51B</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x59;</mtext></math>=<span>1D51C</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x5A;</mtext></math>=<span>02128</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x61;</mtext></math>=<span>1D51E</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x62;</mtext></math>=<span>1D51F</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x63;</mtext></math>=<span>1D520</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x64;</mtext></math>=<span>1D521</span></span><br/>
+ <span><math><mtext mathvariant="fraktur">&#x65;</mtext></math>=<span>1D522</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x66;</mtext></math>=<span>1D523</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x67;</mtext></math>=<span>1D524</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x68;</mtext></math>=<span>1D525</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x69;</mtext></math>=<span>1D526</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x6A;</mtext></math>=<span>1D527</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x6B;</mtext></math>=<span>1D528</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x6C;</mtext></math>=<span>1D529</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x6D;</mtext></math>=<span>1D52A</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x6E;</mtext></math>=<span>1D52B</span></span><br/>
+ <span><math><mtext mathvariant="fraktur">&#x6F;</mtext></math>=<span>1D52C</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x70;</mtext></math>=<span>1D52D</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x71;</mtext></math>=<span>1D52E</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x72;</mtext></math>=<span>1D52F</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x73;</mtext></math>=<span>1D530</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x74;</mtext></math>=<span>1D531</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x75;</mtext></math>=<span>1D532</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x76;</mtext></math>=<span>1D533</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x77;</mtext></math>=<span>1D534</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x78;</mtext></math>=<span>1D535</span></span><br/>
+ <span><math><mtext mathvariant="fraktur">&#x79;</mtext></math>=<span>1D536</span></span>
+ <span><math><mtext mathvariant="fraktur">&#x7A;</mtext></math>=<span>1D537</span></span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-initial-ref.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-initial-ref.html
index 17e5c755faa..722ce5f657d 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-initial-ref.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-initial-ref.html
@@ -23,25 +23,25 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi>&#x1EE30;</mi></math>=<span>1EE30</span></span>
- <span><math><mi>&#x1EE32;</mi></math>=<span>1EE32</span></span>
- <span><math><mi>&#x1EE2A;</mi></math>=<span>1EE2A</span></span>
- <span><math><mi>&#x1EE2B;</mi></math>=<span>1EE2B</span></span>
- <span><math><mi>&#x1EE2C;</mi></math>=<span>1EE2C</span></span>
- <span><math><mi>&#x1EE2D;</mi></math>=<span>1EE2D</span></span>
- <span><math><mi>&#x1EE24;</mi></math>=<span>1EE24</span></span>
- <span><math><mi>&#x1EE21;</mi></math>=<span>1EE21</span></span>
- <span><math><mi>&#x1EE29;</mi></math>=<span>1EE29</span></span>
- <span><math><mi>&#x1EE36;</mi></math>=<span>1EE36</span></span><br/>
- <span><math><mi>&#x1EE22;</mi></math>=<span>1EE22</span></span>
- <span><math><mi>&#x1EE27;</mi></math>=<span>1EE27</span></span>
- <span><math><mi>&#x1EE37;</mi></math>=<span>1EE37</span></span>
- <span><math><mi>&#x1EE2E;</mi></math>=<span>1EE2E</span></span>
- <span><math><mi>&#x1EE34;</mi></math>=<span>1EE34</span></span>
- <span><math><mi>&#x1EE31;</mi></math>=<span>1EE31</span></span>
- <span><math><mi>&#x1EE39;</mi></math>=<span>1EE39</span></span>
- <span><math><mi>&#x1EE2F;</mi></math>=<span>1EE2F</span></span>
- <span><math><mi>&#x1EE3B;</mi></math>=<span>1EE3B</span></span>
- <span><math><mi>&#x1EE35;</mi></math>=<span>1EE35</span></span><br/>
+ <span><math><mtext>&#x1EE30;</mtext></math>=<span>1EE30</span></span>
+ <span><math><mtext>&#x1EE32;</mtext></math>=<span>1EE32</span></span>
+ <span><math><mtext>&#x1EE2A;</mtext></math>=<span>1EE2A</span></span>
+ <span><math><mtext>&#x1EE2B;</mtext></math>=<span>1EE2B</span></span>
+ <span><math><mtext>&#x1EE2C;</mtext></math>=<span>1EE2C</span></span>
+ <span><math><mtext>&#x1EE2D;</mtext></math>=<span>1EE2D</span></span>
+ <span><math><mtext>&#x1EE24;</mtext></math>=<span>1EE24</span></span>
+ <span><math><mtext>&#x1EE21;</mtext></math>=<span>1EE21</span></span>
+ <span><math><mtext>&#x1EE29;</mtext></math>=<span>1EE29</span></span>
+ <span><math><mtext>&#x1EE36;</mtext></math>=<span>1EE36</span></span><br/>
+ <span><math><mtext>&#x1EE22;</mtext></math>=<span>1EE22</span></span>
+ <span><math><mtext>&#x1EE27;</mtext></math>=<span>1EE27</span></span>
+ <span><math><mtext>&#x1EE37;</mtext></math>=<span>1EE37</span></span>
+ <span><math><mtext>&#x1EE2E;</mtext></math>=<span>1EE2E</span></span>
+ <span><math><mtext>&#x1EE34;</mtext></math>=<span>1EE34</span></span>
+ <span><math><mtext>&#x1EE31;</mtext></math>=<span>1EE31</span></span>
+ <span><math><mtext>&#x1EE39;</mtext></math>=<span>1EE39</span></span>
+ <span><math><mtext>&#x1EE2F;</mtext></math>=<span>1EE2F</span></span>
+ <span><math><mtext>&#x1EE3B;</mtext></math>=<span>1EE3B</span></span>
+ <span><math><mtext>&#x1EE35;</mtext></math>=<span>1EE35</span></span><br/>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-initial.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-initial.html
index 674820f6cc4..df9e0af7fc5 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-initial.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-initial.html
@@ -5,7 +5,7 @@
<title>mathvariant initial</title>
<link rel="help" href="http://www.mathml-association.org/MathMLinHTML5/S2.html#SS3.SSS1.tab2"/>
<link rel="match" href="mathvariant-initial-ref.html"/>
-<meta name="assert" content="Verify that a single-char <mi> with a initial mathvariant is equivalent to an <mi> with the transformed unicode character.">
+<meta name="assert" content="Verify that a single-char <mtext> with a initial mathvariant is equivalent to an <mtext> with the transformed unicode character.">
<style>
@font-face {
font-family: TestFont;
@@ -26,25 +26,25 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi mathvariant="initial">&#x641;</mi></math>=<span>1EE30</span></span>
- <span><math><mi mathvariant="initial">&#x642;</mi></math>=<span>1EE32</span></span>
- <span><math><mi mathvariant="initial">&#x643;</mi></math>=<span>1EE2A</span></span>
- <span><math><mi mathvariant="initial">&#x644;</mi></math>=<span>1EE2B</span></span>
- <span><math><mi mathvariant="initial">&#x645;</mi></math>=<span>1EE2C</span></span>
- <span><math><mi mathvariant="initial">&#x646;</mi></math>=<span>1EE2D</span></span>
- <span><math><mi mathvariant="initial">&#x647;</mi></math>=<span>1EE24</span></span>
- <span><math><mi mathvariant="initial">&#x628;</mi></math>=<span>1EE21</span></span>
- <span><math><mi mathvariant="initial">&#x64A;</mi></math>=<span>1EE29</span></span>
- <span><math><mi mathvariant="initial">&#x62B;</mi></math>=<span>1EE36</span></span><br/>
- <span><math><mi mathvariant="initial">&#x62C;</mi></math>=<span>1EE22</span></span>
- <span><math><mi mathvariant="initial">&#x62D;</mi></math>=<span>1EE27</span></span>
- <span><math><mi mathvariant="initial">&#x62E;</mi></math>=<span>1EE37</span></span>
- <span><math><mi mathvariant="initial">&#x633;</mi></math>=<span>1EE2E</span></span>
- <span><math><mi mathvariant="initial">&#x634;</mi></math>=<span>1EE34</span></span>
- <span><math><mi mathvariant="initial">&#x635;</mi></math>=<span>1EE31</span></span>
- <span><math><mi mathvariant="initial">&#x636;</mi></math>=<span>1EE39</span></span>
- <span><math><mi mathvariant="initial">&#x639;</mi></math>=<span>1EE2F</span></span>
- <span><math><mi mathvariant="initial">&#x63A;</mi></math>=<span>1EE3B</span></span>
- <span><math><mi mathvariant="initial">&#x62A;</mi></math>=<span>1EE35</span></span><br/>
+ <span><math><mtext mathvariant="initial">&#x641;</mtext></math>=<span>1EE30</span></span>
+ <span><math><mtext mathvariant="initial">&#x642;</mtext></math>=<span>1EE32</span></span>
+ <span><math><mtext mathvariant="initial">&#x643;</mtext></math>=<span>1EE2A</span></span>
+ <span><math><mtext mathvariant="initial">&#x644;</mtext></math>=<span>1EE2B</span></span>
+ <span><math><mtext mathvariant="initial">&#x645;</mtext></math>=<span>1EE2C</span></span>
+ <span><math><mtext mathvariant="initial">&#x646;</mtext></math>=<span>1EE2D</span></span>
+ <span><math><mtext mathvariant="initial">&#x647;</mtext></math>=<span>1EE24</span></span>
+ <span><math><mtext mathvariant="initial">&#x628;</mtext></math>=<span>1EE21</span></span>
+ <span><math><mtext mathvariant="initial">&#x64A;</mtext></math>=<span>1EE29</span></span>
+ <span><math><mtext mathvariant="initial">&#x62B;</mtext></math>=<span>1EE36</span></span><br/>
+ <span><math><mtext mathvariant="initial">&#x62C;</mtext></math>=<span>1EE22</span></span>
+ <span><math><mtext mathvariant="initial">&#x62D;</mtext></math>=<span>1EE27</span></span>
+ <span><math><mtext mathvariant="initial">&#x62E;</mtext></math>=<span>1EE37</span></span>
+ <span><math><mtext mathvariant="initial">&#x633;</mtext></math>=<span>1EE2E</span></span>
+ <span><math><mtext mathvariant="initial">&#x634;</mtext></math>=<span>1EE34</span></span>
+ <span><math><mtext mathvariant="initial">&#x635;</mtext></math>=<span>1EE31</span></span>
+ <span><math><mtext mathvariant="initial">&#x636;</mtext></math>=<span>1EE39</span></span>
+ <span><math><mtext mathvariant="initial">&#x639;</mtext></math>=<span>1EE2F</span></span>
+ <span><math><mtext mathvariant="initial">&#x63A;</mtext></math>=<span>1EE3B</span></span>
+ <span><math><mtext mathvariant="initial">&#x62A;</mtext></math>=<span>1EE35</span></span><br/>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-italic-ref.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-italic-ref.html
index bac033c2603..70643b3e611 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-italic-ref.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-italic-ref.html
@@ -23,117 +23,117 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi>&#x1D715;</mi></math>=<span>1D715</span></span>
- <span><math><mi>&#x1D6FB;</mi></math>=<span>1D6FB</span></span>
- <span><math><mi>&#x1D6A5;</mi></math>=<span>1D6A5</span></span>
- <span><math><mi>&#x1D434;</mi></math>=<span>1D434</span></span>
- <span><math><mi>&#x1D435;</mi></math>=<span>1D435</span></span>
- <span><math><mi>&#x1D436;</mi></math>=<span>1D436</span></span>
- <span><math><mi>&#x1D437;</mi></math>=<span>1D437</span></span>
- <span><math><mi>&#x1D438;</mi></math>=<span>1D438</span></span>
- <span><math><mi>&#x1D439;</mi></math>=<span>1D439</span></span>
- <span><math><mi>&#x1D43A;</mi></math>=<span>1D43A</span></span><br/>
- <span><math><mi>&#x1D43B;</mi></math>=<span>1D43B</span></span>
- <span><math><mi>&#x1D43C;</mi></math>=<span>1D43C</span></span>
- <span><math><mi>&#x1D43D;</mi></math>=<span>1D43D</span></span>
- <span><math><mi>&#x1D43E;</mi></math>=<span>1D43E</span></span>
- <span><math><mi>&#x1D43F;</mi></math>=<span>1D43F</span></span>
- <span><math><mi>&#x1D440;</mi></math>=<span>1D440</span></span>
- <span><math><mi>&#x1D441;</mi></math>=<span>1D441</span></span>
- <span><math><mi>&#x1D442;</mi></math>=<span>1D442</span></span>
- <span><math><mi>&#x1D443;</mi></math>=<span>1D443</span></span>
- <span><math><mi>&#x1D444;</mi></math>=<span>1D444</span></span><br/>
- <span><math><mi>&#x1D445;</mi></math>=<span>1D445</span></span>
- <span><math><mi>&#x1D446;</mi></math>=<span>1D446</span></span>
- <span><math><mi>&#x1D447;</mi></math>=<span>1D447</span></span>
- <span><math><mi>&#x1D448;</mi></math>=<span>1D448</span></span>
- <span><math><mi>&#x1D449;</mi></math>=<span>1D449</span></span>
- <span><math><mi>&#x1D44A;</mi></math>=<span>1D44A</span></span>
- <span><math><mi>&#x1D44B;</mi></math>=<span>1D44B</span></span>
- <span><math><mi>&#x1D44C;</mi></math>=<span>1D44C</span></span>
- <span><math><mi>&#x1D44D;</mi></math>=<span>1D44D</span></span>
- <span><math><mi>&#x1D44E;</mi></math>=<span>1D44E</span></span><br/>
- <span><math><mi>&#x1D44F;</mi></math>=<span>1D44F</span></span>
- <span><math><mi>&#x1D450;</mi></math>=<span>1D450</span></span>
- <span><math><mi>&#x1D451;</mi></math>=<span>1D451</span></span>
- <span><math><mi>&#x1D452;</mi></math>=<span>1D452</span></span>
- <span><math><mi>&#x1D453;</mi></math>=<span>1D453</span></span>
- <span><math><mi>&#x1D454;</mi></math>=<span>1D454</span></span>
- <span><math><mi>&#x210E;</mi></math>=<span>0210E</span></span>
- <span><math><mi>&#x1D456;</mi></math>=<span>1D456</span></span>
- <span><math><mi>&#x1D457;</mi></math>=<span>1D457</span></span>
- <span><math><mi>&#x1D458;</mi></math>=<span>1D458</span></span><br/>
- <span><math><mi>&#x1D459;</mi></math>=<span>1D459</span></span>
- <span><math><mi>&#x1D45A;</mi></math>=<span>1D45A</span></span>
- <span><math><mi>&#x1D45B;</mi></math>=<span>1D45B</span></span>
- <span><math><mi>&#x1D45C;</mi></math>=<span>1D45C</span></span>
- <span><math><mi>&#x1D45D;</mi></math>=<span>1D45D</span></span>
- <span><math><mi>&#x1D45E;</mi></math>=<span>1D45E</span></span>
- <span><math><mi>&#x1D45F;</mi></math>=<span>1D45F</span></span>
- <span><math><mi>&#x1D460;</mi></math>=<span>1D460</span></span>
- <span><math><mi>&#x1D461;</mi></math>=<span>1D461</span></span>
- <span><math><mi>&#x1D462;</mi></math>=<span>1D462</span></span><br/>
- <span><math><mi>&#x1D463;</mi></math>=<span>1D463</span></span>
- <span><math><mi>&#x1D464;</mi></math>=<span>1D464</span></span>
- <span><math><mi>&#x1D465;</mi></math>=<span>1D465</span></span>
- <span><math><mi>&#x1D466;</mi></math>=<span>1D466</span></span>
- <span><math><mi>&#x1D467;</mi></math>=<span>1D467</span></span>
- <span><math><mi>&#x1D6A4;</mi></math>=<span>1D6A4</span></span>
- <span><math><mi>&#x1D6E2;</mi></math>=<span>1D6E2</span></span>
- <span><math><mi>&#x1D6E3;</mi></math>=<span>1D6E3</span></span>
- <span><math><mi>&#x1D6E4;</mi></math>=<span>1D6E4</span></span>
- <span><math><mi>&#x1D6E5;</mi></math>=<span>1D6E5</span></span><br/>
- <span><math><mi>&#x1D6E6;</mi></math>=<span>1D6E6</span></span>
- <span><math><mi>&#x1D6E7;</mi></math>=<span>1D6E7</span></span>
- <span><math><mi>&#x1D6E8;</mi></math>=<span>1D6E8</span></span>
- <span><math><mi>&#x1D6E9;</mi></math>=<span>1D6E9</span></span>
- <span><math><mi>&#x1D6EA;</mi></math>=<span>1D6EA</span></span>
- <span><math><mi>&#x1D6EB;</mi></math>=<span>1D6EB</span></span>
- <span><math><mi>&#x1D6EC;</mi></math>=<span>1D6EC</span></span>
- <span><math><mi>&#x1D6ED;</mi></math>=<span>1D6ED</span></span>
- <span><math><mi>&#x1D6EE;</mi></math>=<span>1D6EE</span></span>
- <span><math><mi>&#x1D6EF;</mi></math>=<span>1D6EF</span></span><br/>
- <span><math><mi>&#x1D6F0;</mi></math>=<span>1D6F0</span></span>
- <span><math><mi>&#x1D6F1;</mi></math>=<span>1D6F1</span></span>
- <span><math><mi>&#x1D6F2;</mi></math>=<span>1D6F2</span></span>
- <span><math><mi>&#x1D6F4;</mi></math>=<span>1D6F4</span></span>
- <span><math><mi>&#x1D6F5;</mi></math>=<span>1D6F5</span></span>
- <span><math><mi>&#x1D6F6;</mi></math>=<span>1D6F6</span></span>
- <span><math><mi>&#x1D6F7;</mi></math>=<span>1D6F7</span></span>
- <span><math><mi>&#x1D6F8;</mi></math>=<span>1D6F8</span></span>
- <span><math><mi>&#x1D6F9;</mi></math>=<span>1D6F9</span></span>
- <span><math><mi>&#x1D6FA;</mi></math>=<span>1D6FA</span></span><br/>
- <span><math><mi>&#x1D6FC;</mi></math>=<span>1D6FC</span></span>
- <span><math><mi>&#x1D6FD;</mi></math>=<span>1D6FD</span></span>
- <span><math><mi>&#x1D6FE;</mi></math>=<span>1D6FE</span></span>
- <span><math><mi>&#x1D6FF;</mi></math>=<span>1D6FF</span></span>
- <span><math><mi>&#x1D700;</mi></math>=<span>1D700</span></span>
- <span><math><mi>&#x1D701;</mi></math>=<span>1D701</span></span>
- <span><math><mi>&#x1D702;</mi></math>=<span>1D702</span></span>
- <span><math><mi>&#x1D703;</mi></math>=<span>1D703</span></span>
- <span><math><mi>&#x1D704;</mi></math>=<span>1D704</span></span>
- <span><math><mi>&#x1D705;</mi></math>=<span>1D705</span></span><br/>
- <span><math><mi>&#x1D706;</mi></math>=<span>1D706</span></span>
- <span><math><mi>&#x1D707;</mi></math>=<span>1D707</span></span>
- <span><math><mi>&#x1D708;</mi></math>=<span>1D708</span></span>
- <span><math><mi>&#x1D709;</mi></math>=<span>1D709</span></span>
- <span><math><mi>&#x1D70A;</mi></math>=<span>1D70A</span></span>
- <span><math><mi>&#x1D70B;</mi></math>=<span>1D70B</span></span>
- <span><math><mi>&#x1D70C;</mi></math>=<span>1D70C</span></span>
- <span><math><mi>&#x1D70D;</mi></math>=<span>1D70D</span></span>
- <span><math><mi>&#x1D70E;</mi></math>=<span>1D70E</span></span>
- <span><math><mi>&#x1D70F;</mi></math>=<span>1D70F</span></span><br/>
- <span><math><mi>&#x1D710;</mi></math>=<span>1D710</span></span>
- <span><math><mi>&#x1D711;</mi></math>=<span>1D711</span></span>
- <span><math><mi>&#x1D712;</mi></math>=<span>1D712</span></span>
- <span><math><mi>&#x1D713;</mi></math>=<span>1D713</span></span>
- <span><math><mi>&#x1D714;</mi></math>=<span>1D714</span></span>
- <span><math><mi>&#x1D717;</mi></math>=<span>1D717</span></span>
- <span><math><mi>&#x1D719;</mi></math>=<span>1D719</span></span>
- <span><math><mi>&#x1D71B;</mi></math>=<span>1D71B</span></span>
- <span><math><mi>&#x1D718;</mi></math>=<span>1D718</span></span>
- <span><math><mi>&#x1D71A;</mi></math>=<span>1D71A</span></span><br/>
- <span><math><mi>&#x1D6F3;</mi></math>=<span>1D6F3</span></span>
- <span><math><mi>&#x1D716;</mi></math>=<span>1D716</span></span>
+ <span><math><mtext>&#x1D715;</mtext></math>=<span>1D715</span></span>
+ <span><math><mtext>&#x1D6FB;</mtext></math>=<span>1D6FB</span></span>
+ <span><math><mtext>&#x1D6A5;</mtext></math>=<span>1D6A5</span></span>
+ <span><math><mtext>&#x1D434;</mtext></math>=<span>1D434</span></span>
+ <span><math><mtext>&#x1D435;</mtext></math>=<span>1D435</span></span>
+ <span><math><mtext>&#x1D436;</mtext></math>=<span>1D436</span></span>
+ <span><math><mtext>&#x1D437;</mtext></math>=<span>1D437</span></span>
+ <span><math><mtext>&#x1D438;</mtext></math>=<span>1D438</span></span>
+ <span><math><mtext>&#x1D439;</mtext></math>=<span>1D439</span></span>
+ <span><math><mtext>&#x1D43A;</mtext></math>=<span>1D43A</span></span><br/>
+ <span><math><mtext>&#x1D43B;</mtext></math>=<span>1D43B</span></span>
+ <span><math><mtext>&#x1D43C;</mtext></math>=<span>1D43C</span></span>
+ <span><math><mtext>&#x1D43D;</mtext></math>=<span>1D43D</span></span>
+ <span><math><mtext>&#x1D43E;</mtext></math>=<span>1D43E</span></span>
+ <span><math><mtext>&#x1D43F;</mtext></math>=<span>1D43F</span></span>
+ <span><math><mtext>&#x1D440;</mtext></math>=<span>1D440</span></span>
+ <span><math><mtext>&#x1D441;</mtext></math>=<span>1D441</span></span>
+ <span><math><mtext>&#x1D442;</mtext></math>=<span>1D442</span></span>
+ <span><math><mtext>&#x1D443;</mtext></math>=<span>1D443</span></span>
+ <span><math><mtext>&#x1D444;</mtext></math>=<span>1D444</span></span><br/>
+ <span><math><mtext>&#x1D445;</mtext></math>=<span>1D445</span></span>
+ <span><math><mtext>&#x1D446;</mtext></math>=<span>1D446</span></span>
+ <span><math><mtext>&#x1D447;</mtext></math>=<span>1D447</span></span>
+ <span><math><mtext>&#x1D448;</mtext></math>=<span>1D448</span></span>
+ <span><math><mtext>&#x1D449;</mtext></math>=<span>1D449</span></span>
+ <span><math><mtext>&#x1D44A;</mtext></math>=<span>1D44A</span></span>
+ <span><math><mtext>&#x1D44B;</mtext></math>=<span>1D44B</span></span>
+ <span><math><mtext>&#x1D44C;</mtext></math>=<span>1D44C</span></span>
+ <span><math><mtext>&#x1D44D;</mtext></math>=<span>1D44D</span></span>
+ <span><math><mtext>&#x1D44E;</mtext></math>=<span>1D44E</span></span><br/>
+ <span><math><mtext>&#x1D44F;</mtext></math>=<span>1D44F</span></span>
+ <span><math><mtext>&#x1D450;</mtext></math>=<span>1D450</span></span>
+ <span><math><mtext>&#x1D451;</mtext></math>=<span>1D451</span></span>
+ <span><math><mtext>&#x1D452;</mtext></math>=<span>1D452</span></span>
+ <span><math><mtext>&#x1D453;</mtext></math>=<span>1D453</span></span>
+ <span><math><mtext>&#x1D454;</mtext></math>=<span>1D454</span></span>
+ <span><math><mtext>&#x210E;</mtext></math>=<span>0210E</span></span>
+ <span><math><mtext>&#x1D456;</mtext></math>=<span>1D456</span></span>
+ <span><math><mtext>&#x1D457;</mtext></math>=<span>1D457</span></span>
+ <span><math><mtext>&#x1D458;</mtext></math>=<span>1D458</span></span><br/>
+ <span><math><mtext>&#x1D459;</mtext></math>=<span>1D459</span></span>
+ <span><math><mtext>&#x1D45A;</mtext></math>=<span>1D45A</span></span>
+ <span><math><mtext>&#x1D45B;</mtext></math>=<span>1D45B</span></span>
+ <span><math><mtext>&#x1D45C;</mtext></math>=<span>1D45C</span></span>
+ <span><math><mtext>&#x1D45D;</mtext></math>=<span>1D45D</span></span>
+ <span><math><mtext>&#x1D45E;</mtext></math>=<span>1D45E</span></span>
+ <span><math><mtext>&#x1D45F;</mtext></math>=<span>1D45F</span></span>
+ <span><math><mtext>&#x1D460;</mtext></math>=<span>1D460</span></span>
+ <span><math><mtext>&#x1D461;</mtext></math>=<span>1D461</span></span>
+ <span><math><mtext>&#x1D462;</mtext></math>=<span>1D462</span></span><br/>
+ <span><math><mtext>&#x1D463;</mtext></math>=<span>1D463</span></span>
+ <span><math><mtext>&#x1D464;</mtext></math>=<span>1D464</span></span>
+ <span><math><mtext>&#x1D465;</mtext></math>=<span>1D465</span></span>
+ <span><math><mtext>&#x1D466;</mtext></math>=<span>1D466</span></span>
+ <span><math><mtext>&#x1D467;</mtext></math>=<span>1D467</span></span>
+ <span><math><mtext>&#x1D6A4;</mtext></math>=<span>1D6A4</span></span>
+ <span><math><mtext>&#x1D6E2;</mtext></math>=<span>1D6E2</span></span>
+ <span><math><mtext>&#x1D6E3;</mtext></math>=<span>1D6E3</span></span>
+ <span><math><mtext>&#x1D6E4;</mtext></math>=<span>1D6E4</span></span>
+ <span><math><mtext>&#x1D6E5;</mtext></math>=<span>1D6E5</span></span><br/>
+ <span><math><mtext>&#x1D6E6;</mtext></math>=<span>1D6E6</span></span>
+ <span><math><mtext>&#x1D6E7;</mtext></math>=<span>1D6E7</span></span>
+ <span><math><mtext>&#x1D6E8;</mtext></math>=<span>1D6E8</span></span>
+ <span><math><mtext>&#x1D6E9;</mtext></math>=<span>1D6E9</span></span>
+ <span><math><mtext>&#x1D6EA;</mtext></math>=<span>1D6EA</span></span>
+ <span><math><mtext>&#x1D6EB;</mtext></math>=<span>1D6EB</span></span>
+ <span><math><mtext>&#x1D6EC;</mtext></math>=<span>1D6EC</span></span>
+ <span><math><mtext>&#x1D6ED;</mtext></math>=<span>1D6ED</span></span>
+ <span><math><mtext>&#x1D6EE;</mtext></math>=<span>1D6EE</span></span>
+ <span><math><mtext>&#x1D6EF;</mtext></math>=<span>1D6EF</span></span><br/>
+ <span><math><mtext>&#x1D6F0;</mtext></math>=<span>1D6F0</span></span>
+ <span><math><mtext>&#x1D6F1;</mtext></math>=<span>1D6F1</span></span>
+ <span><math><mtext>&#x1D6F2;</mtext></math>=<span>1D6F2</span></span>
+ <span><math><mtext>&#x1D6F4;</mtext></math>=<span>1D6F4</span></span>
+ <span><math><mtext>&#x1D6F5;</mtext></math>=<span>1D6F5</span></span>
+ <span><math><mtext>&#x1D6F6;</mtext></math>=<span>1D6F6</span></span>
+ <span><math><mtext>&#x1D6F7;</mtext></math>=<span>1D6F7</span></span>
+ <span><math><mtext>&#x1D6F8;</mtext></math>=<span>1D6F8</span></span>
+ <span><math><mtext>&#x1D6F9;</mtext></math>=<span>1D6F9</span></span>
+ <span><math><mtext>&#x1D6FA;</mtext></math>=<span>1D6FA</span></span><br/>
+ <span><math><mtext>&#x1D6FC;</mtext></math>=<span>1D6FC</span></span>
+ <span><math><mtext>&#x1D6FD;</mtext></math>=<span>1D6FD</span></span>
+ <span><math><mtext>&#x1D6FE;</mtext></math>=<span>1D6FE</span></span>
+ <span><math><mtext>&#x1D6FF;</mtext></math>=<span>1D6FF</span></span>
+ <span><math><mtext>&#x1D700;</mtext></math>=<span>1D700</span></span>
+ <span><math><mtext>&#x1D701;</mtext></math>=<span>1D701</span></span>
+ <span><math><mtext>&#x1D702;</mtext></math>=<span>1D702</span></span>
+ <span><math><mtext>&#x1D703;</mtext></math>=<span>1D703</span></span>
+ <span><math><mtext>&#x1D704;</mtext></math>=<span>1D704</span></span>
+ <span><math><mtext>&#x1D705;</mtext></math>=<span>1D705</span></span><br/>
+ <span><math><mtext>&#x1D706;</mtext></math>=<span>1D706</span></span>
+ <span><math><mtext>&#x1D707;</mtext></math>=<span>1D707</span></span>
+ <span><math><mtext>&#x1D708;</mtext></math>=<span>1D708</span></span>
+ <span><math><mtext>&#x1D709;</mtext></math>=<span>1D709</span></span>
+ <span><math><mtext>&#x1D70A;</mtext></math>=<span>1D70A</span></span>
+ <span><math><mtext>&#x1D70B;</mtext></math>=<span>1D70B</span></span>
+ <span><math><mtext>&#x1D70C;</mtext></math>=<span>1D70C</span></span>
+ <span><math><mtext>&#x1D70D;</mtext></math>=<span>1D70D</span></span>
+ <span><math><mtext>&#x1D70E;</mtext></math>=<span>1D70E</span></span>
+ <span><math><mtext>&#x1D70F;</mtext></math>=<span>1D70F</span></span><br/>
+ <span><math><mtext>&#x1D710;</mtext></math>=<span>1D710</span></span>
+ <span><math><mtext>&#x1D711;</mtext></math>=<span>1D711</span></span>
+ <span><math><mtext>&#x1D712;</mtext></math>=<span>1D712</span></span>
+ <span><math><mtext>&#x1D713;</mtext></math>=<span>1D713</span></span>
+ <span><math><mtext>&#x1D714;</mtext></math>=<span>1D714</span></span>
+ <span><math><mtext>&#x1D717;</mtext></math>=<span>1D717</span></span>
+ <span><math><mtext>&#x1D719;</mtext></math>=<span>1D719</span></span>
+ <span><math><mtext>&#x1D71B;</mtext></math>=<span>1D71B</span></span>
+ <span><math><mtext>&#x1D718;</mtext></math>=<span>1D718</span></span>
+ <span><math><mtext>&#x1D71A;</mtext></math>=<span>1D71A</span></span><br/>
+ <span><math><mtext>&#x1D6F3;</mtext></math>=<span>1D6F3</span></span>
+ <span><math><mtext>&#x1D716;</mtext></math>=<span>1D716</span></span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-italic.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-italic.html
index c3386b8bcd3..e1612a528c8 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-italic.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-italic.html
@@ -5,7 +5,7 @@
<title>mathvariant italic</title>
<link rel="help" href="http://www.mathml-association.org/MathMLinHTML5/S2.html#SS3.SSS1.tab2"/>
<link rel="match" href="mathvariant-italic-ref.html"/>
-<meta name="assert" content="Verify that a single-char <mi> with a italic mathvariant is equivalent to an <mi> with the transformed unicode character.">
+<meta name="assert" content="Verify that a single-char <mtext> with a italic mathvariant is equivalent to an <mtext> with the transformed unicode character.">
<style>
@font-face {
font-family: TestFont;
@@ -26,117 +26,117 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi mathvariant="italic">&#x2202;</mi></math>=<span>1D715</span></span>
- <span><math><mi mathvariant="italic">&#x2207;</mi></math>=<span>1D6FB</span></span>
- <span><math><mi mathvariant="italic">&#x237;</mi></math>=<span>1D6A5</span></span>
- <span><math><mi mathvariant="italic">&#x41;</mi></math>=<span>1D434</span></span>
- <span><math><mi mathvariant="italic">&#x42;</mi></math>=<span>1D435</span></span>
- <span><math><mi mathvariant="italic">&#x43;</mi></math>=<span>1D436</span></span>
- <span><math><mi mathvariant="italic">&#x44;</mi></math>=<span>1D437</span></span>
- <span><math><mi mathvariant="italic">&#x45;</mi></math>=<span>1D438</span></span>
- <span><math><mi mathvariant="italic">&#x46;</mi></math>=<span>1D439</span></span>
- <span><math><mi mathvariant="italic">&#x47;</mi></math>=<span>1D43A</span></span><br/>
- <span><math><mi mathvariant="italic">&#x48;</mi></math>=<span>1D43B</span></span>
- <span><math><mi mathvariant="italic">&#x49;</mi></math>=<span>1D43C</span></span>
- <span><math><mi mathvariant="italic">&#x4A;</mi></math>=<span>1D43D</span></span>
- <span><math><mi mathvariant="italic">&#x4B;</mi></math>=<span>1D43E</span></span>
- <span><math><mi mathvariant="italic">&#x4C;</mi></math>=<span>1D43F</span></span>
- <span><math><mi mathvariant="italic">&#x4D;</mi></math>=<span>1D440</span></span>
- <span><math><mi mathvariant="italic">&#x4E;</mi></math>=<span>1D441</span></span>
- <span><math><mi mathvariant="italic">&#x4F;</mi></math>=<span>1D442</span></span>
- <span><math><mi mathvariant="italic">&#x50;</mi></math>=<span>1D443</span></span>
- <span><math><mi mathvariant="italic">&#x51;</mi></math>=<span>1D444</span></span><br/>
- <span><math><mi mathvariant="italic">&#x52;</mi></math>=<span>1D445</span></span>
- <span><math><mi mathvariant="italic">&#x53;</mi></math>=<span>1D446</span></span>
- <span><math><mi mathvariant="italic">&#x54;</mi></math>=<span>1D447</span></span>
- <span><math><mi mathvariant="italic">&#x55;</mi></math>=<span>1D448</span></span>
- <span><math><mi mathvariant="italic">&#x56;</mi></math>=<span>1D449</span></span>
- <span><math><mi mathvariant="italic">&#x57;</mi></math>=<span>1D44A</span></span>
- <span><math><mi mathvariant="italic">&#x58;</mi></math>=<span>1D44B</span></span>
- <span><math><mi mathvariant="italic">&#x59;</mi></math>=<span>1D44C</span></span>
- <span><math><mi mathvariant="italic">&#x5A;</mi></math>=<span>1D44D</span></span>
- <span><math><mi mathvariant="italic">&#x61;</mi></math>=<span>1D44E</span></span><br/>
- <span><math><mi mathvariant="italic">&#x62;</mi></math>=<span>1D44F</span></span>
- <span><math><mi mathvariant="italic">&#x63;</mi></math>=<span>1D450</span></span>
- <span><math><mi mathvariant="italic">&#x64;</mi></math>=<span>1D451</span></span>
- <span><math><mi mathvariant="italic">&#x65;</mi></math>=<span>1D452</span></span>
- <span><math><mi mathvariant="italic">&#x66;</mi></math>=<span>1D453</span></span>
- <span><math><mi mathvariant="italic">&#x67;</mi></math>=<span>1D454</span></span>
- <span><math><mi mathvariant="italic">&#x68;</mi></math>=<span>0210E</span></span>
- <span><math><mi mathvariant="italic">&#x69;</mi></math>=<span>1D456</span></span>
- <span><math><mi mathvariant="italic">&#x6A;</mi></math>=<span>1D457</span></span>
- <span><math><mi mathvariant="italic">&#x6B;</mi></math>=<span>1D458</span></span><br/>
- <span><math><mi mathvariant="italic">&#x6C;</mi></math>=<span>1D459</span></span>
- <span><math><mi mathvariant="italic">&#x6D;</mi></math>=<span>1D45A</span></span>
- <span><math><mi mathvariant="italic">&#x6E;</mi></math>=<span>1D45B</span></span>
- <span><math><mi mathvariant="italic">&#x6F;</mi></math>=<span>1D45C</span></span>
- <span><math><mi mathvariant="italic">&#x70;</mi></math>=<span>1D45D</span></span>
- <span><math><mi mathvariant="italic">&#x71;</mi></math>=<span>1D45E</span></span>
- <span><math><mi mathvariant="italic">&#x72;</mi></math>=<span>1D45F</span></span>
- <span><math><mi mathvariant="italic">&#x73;</mi></math>=<span>1D460</span></span>
- <span><math><mi mathvariant="italic">&#x74;</mi></math>=<span>1D461</span></span>
- <span><math><mi mathvariant="italic">&#x75;</mi></math>=<span>1D462</span></span><br/>
- <span><math><mi mathvariant="italic">&#x76;</mi></math>=<span>1D463</span></span>
- <span><math><mi mathvariant="italic">&#x77;</mi></math>=<span>1D464</span></span>
- <span><math><mi mathvariant="italic">&#x78;</mi></math>=<span>1D465</span></span>
- <span><math><mi mathvariant="italic">&#x79;</mi></math>=<span>1D466</span></span>
- <span><math><mi mathvariant="italic">&#x7A;</mi></math>=<span>1D467</span></span>
- <span><math><mi mathvariant="italic">&#x131;</mi></math>=<span>1D6A4</span></span>
- <span><math><mi mathvariant="italic">&#x391;</mi></math>=<span>1D6E2</span></span>
- <span><math><mi mathvariant="italic">&#x392;</mi></math>=<span>1D6E3</span></span>
- <span><math><mi mathvariant="italic">&#x393;</mi></math>=<span>1D6E4</span></span>
- <span><math><mi mathvariant="italic">&#x394;</mi></math>=<span>1D6E5</span></span><br/>
- <span><math><mi mathvariant="italic">&#x395;</mi></math>=<span>1D6E6</span></span>
- <span><math><mi mathvariant="italic">&#x396;</mi></math>=<span>1D6E7</span></span>
- <span><math><mi mathvariant="italic">&#x397;</mi></math>=<span>1D6E8</span></span>
- <span><math><mi mathvariant="italic">&#x398;</mi></math>=<span>1D6E9</span></span>
- <span><math><mi mathvariant="italic">&#x399;</mi></math>=<span>1D6EA</span></span>
- <span><math><mi mathvariant="italic">&#x39A;</mi></math>=<span>1D6EB</span></span>
- <span><math><mi mathvariant="italic">&#x39B;</mi></math>=<span>1D6EC</span></span>
- <span><math><mi mathvariant="italic">&#x39C;</mi></math>=<span>1D6ED</span></span>
- <span><math><mi mathvariant="italic">&#x39D;</mi></math>=<span>1D6EE</span></span>
- <span><math><mi mathvariant="italic">&#x39E;</mi></math>=<span>1D6EF</span></span><br/>
- <span><math><mi mathvariant="italic">&#x39F;</mi></math>=<span>1D6F0</span></span>
- <span><math><mi mathvariant="italic">&#x3A0;</mi></math>=<span>1D6F1</span></span>
- <span><math><mi mathvariant="italic">&#x3A1;</mi></math>=<span>1D6F2</span></span>
- <span><math><mi mathvariant="italic">&#x3A3;</mi></math>=<span>1D6F4</span></span>
- <span><math><mi mathvariant="italic">&#x3A4;</mi></math>=<span>1D6F5</span></span>
- <span><math><mi mathvariant="italic">&#x3A5;</mi></math>=<span>1D6F6</span></span>
- <span><math><mi mathvariant="italic">&#x3A6;</mi></math>=<span>1D6F7</span></span>
- <span><math><mi mathvariant="italic">&#x3A7;</mi></math>=<span>1D6F8</span></span>
- <span><math><mi mathvariant="italic">&#x3A8;</mi></math>=<span>1D6F9</span></span>
- <span><math><mi mathvariant="italic">&#x3A9;</mi></math>=<span>1D6FA</span></span><br/>
- <span><math><mi mathvariant="italic">&#x3B1;</mi></math>=<span>1D6FC</span></span>
- <span><math><mi mathvariant="italic">&#x3B2;</mi></math>=<span>1D6FD</span></span>
- <span><math><mi mathvariant="italic">&#x3B3;</mi></math>=<span>1D6FE</span></span>
- <span><math><mi mathvariant="italic">&#x3B4;</mi></math>=<span>1D6FF</span></span>
- <span><math><mi mathvariant="italic">&#x3B5;</mi></math>=<span>1D700</span></span>
- <span><math><mi mathvariant="italic">&#x3B6;</mi></math>=<span>1D701</span></span>
- <span><math><mi mathvariant="italic">&#x3B7;</mi></math>=<span>1D702</span></span>
- <span><math><mi mathvariant="italic">&#x3B8;</mi></math>=<span>1D703</span></span>
- <span><math><mi mathvariant="italic">&#x3B9;</mi></math>=<span>1D704</span></span>
- <span><math><mi mathvariant="italic">&#x3BA;</mi></math>=<span>1D705</span></span><br/>
- <span><math><mi mathvariant="italic">&#x3BB;</mi></math>=<span>1D706</span></span>
- <span><math><mi mathvariant="italic">&#x3BC;</mi></math>=<span>1D707</span></span>
- <span><math><mi mathvariant="italic">&#x3BD;</mi></math>=<span>1D708</span></span>
- <span><math><mi mathvariant="italic">&#x3BE;</mi></math>=<span>1D709</span></span>
- <span><math><mi mathvariant="italic">&#x3BF;</mi></math>=<span>1D70A</span></span>
- <span><math><mi mathvariant="italic">&#x3C0;</mi></math>=<span>1D70B</span></span>
- <span><math><mi mathvariant="italic">&#x3C1;</mi></math>=<span>1D70C</span></span>
- <span><math><mi mathvariant="italic">&#x3C2;</mi></math>=<span>1D70D</span></span>
- <span><math><mi mathvariant="italic">&#x3C3;</mi></math>=<span>1D70E</span></span>
- <span><math><mi mathvariant="italic">&#x3C4;</mi></math>=<span>1D70F</span></span><br/>
- <span><math><mi mathvariant="italic">&#x3C5;</mi></math>=<span>1D710</span></span>
- <span><math><mi mathvariant="italic">&#x3C6;</mi></math>=<span>1D711</span></span>
- <span><math><mi mathvariant="italic">&#x3C7;</mi></math>=<span>1D712</span></span>
- <span><math><mi mathvariant="italic">&#x3C8;</mi></math>=<span>1D713</span></span>
- <span><math><mi mathvariant="italic">&#x3C9;</mi></math>=<span>1D714</span></span>
- <span><math><mi mathvariant="italic">&#x3D1;</mi></math>=<span>1D717</span></span>
- <span><math><mi mathvariant="italic">&#x3D5;</mi></math>=<span>1D719</span></span>
- <span><math><mi mathvariant="italic">&#x3D6;</mi></math>=<span>1D71B</span></span>
- <span><math><mi mathvariant="italic">&#x3F0;</mi></math>=<span>1D718</span></span>
- <span><math><mi mathvariant="italic">&#x3F1;</mi></math>=<span>1D71A</span></span><br/>
- <span><math><mi mathvariant="italic">&#x3F4;</mi></math>=<span>1D6F3</span></span>
- <span><math><mi mathvariant="italic">&#x3F5;</mi></math>=<span>1D716</span></span>
+ <span><math><mtext mathvariant="italic">&#x2202;</mtext></math>=<span>1D715</span></span>
+ <span><math><mtext mathvariant="italic">&#x2207;</mtext></math>=<span>1D6FB</span></span>
+ <span><math><mtext mathvariant="italic">&#x237;</mtext></math>=<span>1D6A5</span></span>
+ <span><math><mtext mathvariant="italic">&#x41;</mtext></math>=<span>1D434</span></span>
+ <span><math><mtext mathvariant="italic">&#x42;</mtext></math>=<span>1D435</span></span>
+ <span><math><mtext mathvariant="italic">&#x43;</mtext></math>=<span>1D436</span></span>
+ <span><math><mtext mathvariant="italic">&#x44;</mtext></math>=<span>1D437</span></span>
+ <span><math><mtext mathvariant="italic">&#x45;</mtext></math>=<span>1D438</span></span>
+ <span><math><mtext mathvariant="italic">&#x46;</mtext></math>=<span>1D439</span></span>
+ <span><math><mtext mathvariant="italic">&#x47;</mtext></math>=<span>1D43A</span></span><br/>
+ <span><math><mtext mathvariant="italic">&#x48;</mtext></math>=<span>1D43B</span></span>
+ <span><math><mtext mathvariant="italic">&#x49;</mtext></math>=<span>1D43C</span></span>
+ <span><math><mtext mathvariant="italic">&#x4A;</mtext></math>=<span>1D43D</span></span>
+ <span><math><mtext mathvariant="italic">&#x4B;</mtext></math>=<span>1D43E</span></span>
+ <span><math><mtext mathvariant="italic">&#x4C;</mtext></math>=<span>1D43F</span></span>
+ <span><math><mtext mathvariant="italic">&#x4D;</mtext></math>=<span>1D440</span></span>
+ <span><math><mtext mathvariant="italic">&#x4E;</mtext></math>=<span>1D441</span></span>
+ <span><math><mtext mathvariant="italic">&#x4F;</mtext></math>=<span>1D442</span></span>
+ <span><math><mtext mathvariant="italic">&#x50;</mtext></math>=<span>1D443</span></span>
+ <span><math><mtext mathvariant="italic">&#x51;</mtext></math>=<span>1D444</span></span><br/>
+ <span><math><mtext mathvariant="italic">&#x52;</mtext></math>=<span>1D445</span></span>
+ <span><math><mtext mathvariant="italic">&#x53;</mtext></math>=<span>1D446</span></span>
+ <span><math><mtext mathvariant="italic">&#x54;</mtext></math>=<span>1D447</span></span>
+ <span><math><mtext mathvariant="italic">&#x55;</mtext></math>=<span>1D448</span></span>
+ <span><math><mtext mathvariant="italic">&#x56;</mtext></math>=<span>1D449</span></span>
+ <span><math><mtext mathvariant="italic">&#x57;</mtext></math>=<span>1D44A</span></span>
+ <span><math><mtext mathvariant="italic">&#x58;</mtext></math>=<span>1D44B</span></span>
+ <span><math><mtext mathvariant="italic">&#x59;</mtext></math>=<span>1D44C</span></span>
+ <span><math><mtext mathvariant="italic">&#x5A;</mtext></math>=<span>1D44D</span></span>
+ <span><math><mtext mathvariant="italic">&#x61;</mtext></math>=<span>1D44E</span></span><br/>
+ <span><math><mtext mathvariant="italic">&#x62;</mtext></math>=<span>1D44F</span></span>
+ <span><math><mtext mathvariant="italic">&#x63;</mtext></math>=<span>1D450</span></span>
+ <span><math><mtext mathvariant="italic">&#x64;</mtext></math>=<span>1D451</span></span>
+ <span><math><mtext mathvariant="italic">&#x65;</mtext></math>=<span>1D452</span></span>
+ <span><math><mtext mathvariant="italic">&#x66;</mtext></math>=<span>1D453</span></span>
+ <span><math><mtext mathvariant="italic">&#x67;</mtext></math>=<span>1D454</span></span>
+ <span><math><mtext mathvariant="italic">&#x68;</mtext></math>=<span>0210E</span></span>
+ <span><math><mtext mathvariant="italic">&#x69;</mtext></math>=<span>1D456</span></span>
+ <span><math><mtext mathvariant="italic">&#x6A;</mtext></math>=<span>1D457</span></span>
+ <span><math><mtext mathvariant="italic">&#x6B;</mtext></math>=<span>1D458</span></span><br/>
+ <span><math><mtext mathvariant="italic">&#x6C;</mtext></math>=<span>1D459</span></span>
+ <span><math><mtext mathvariant="italic">&#x6D;</mtext></math>=<span>1D45A</span></span>
+ <span><math><mtext mathvariant="italic">&#x6E;</mtext></math>=<span>1D45B</span></span>
+ <span><math><mtext mathvariant="italic">&#x6F;</mtext></math>=<span>1D45C</span></span>
+ <span><math><mtext mathvariant="italic">&#x70;</mtext></math>=<span>1D45D</span></span>
+ <span><math><mtext mathvariant="italic">&#x71;</mtext></math>=<span>1D45E</span></span>
+ <span><math><mtext mathvariant="italic">&#x72;</mtext></math>=<span>1D45F</span></span>
+ <span><math><mtext mathvariant="italic">&#x73;</mtext></math>=<span>1D460</span></span>
+ <span><math><mtext mathvariant="italic">&#x74;</mtext></math>=<span>1D461</span></span>
+ <span><math><mtext mathvariant="italic">&#x75;</mtext></math>=<span>1D462</span></span><br/>
+ <span><math><mtext mathvariant="italic">&#x76;</mtext></math>=<span>1D463</span></span>
+ <span><math><mtext mathvariant="italic">&#x77;</mtext></math>=<span>1D464</span></span>
+ <span><math><mtext mathvariant="italic">&#x78;</mtext></math>=<span>1D465</span></span>
+ <span><math><mtext mathvariant="italic">&#x79;</mtext></math>=<span>1D466</span></span>
+ <span><math><mtext mathvariant="italic">&#x7A;</mtext></math>=<span>1D467</span></span>
+ <span><math><mtext mathvariant="italic">&#x131;</mtext></math>=<span>1D6A4</span></span>
+ <span><math><mtext mathvariant="italic">&#x391;</mtext></math>=<span>1D6E2</span></span>
+ <span><math><mtext mathvariant="italic">&#x392;</mtext></math>=<span>1D6E3</span></span>
+ <span><math><mtext mathvariant="italic">&#x393;</mtext></math>=<span>1D6E4</span></span>
+ <span><math><mtext mathvariant="italic">&#x394;</mtext></math>=<span>1D6E5</span></span><br/>
+ <span><math><mtext mathvariant="italic">&#x395;</mtext></math>=<span>1D6E6</span></span>
+ <span><math><mtext mathvariant="italic">&#x396;</mtext></math>=<span>1D6E7</span></span>
+ <span><math><mtext mathvariant="italic">&#x397;</mtext></math>=<span>1D6E8</span></span>
+ <span><math><mtext mathvariant="italic">&#x398;</mtext></math>=<span>1D6E9</span></span>
+ <span><math><mtext mathvariant="italic">&#x399;</mtext></math>=<span>1D6EA</span></span>
+ <span><math><mtext mathvariant="italic">&#x39A;</mtext></math>=<span>1D6EB</span></span>
+ <span><math><mtext mathvariant="italic">&#x39B;</mtext></math>=<span>1D6EC</span></span>
+ <span><math><mtext mathvariant="italic">&#x39C;</mtext></math>=<span>1D6ED</span></span>
+ <span><math><mtext mathvariant="italic">&#x39D;</mtext></math>=<span>1D6EE</span></span>
+ <span><math><mtext mathvariant="italic">&#x39E;</mtext></math>=<span>1D6EF</span></span><br/>
+ <span><math><mtext mathvariant="italic">&#x39F;</mtext></math>=<span>1D6F0</span></span>
+ <span><math><mtext mathvariant="italic">&#x3A0;</mtext></math>=<span>1D6F1</span></span>
+ <span><math><mtext mathvariant="italic">&#x3A1;</mtext></math>=<span>1D6F2</span></span>
+ <span><math><mtext mathvariant="italic">&#x3A3;</mtext></math>=<span>1D6F4</span></span>
+ <span><math><mtext mathvariant="italic">&#x3A4;</mtext></math>=<span>1D6F5</span></span>
+ <span><math><mtext mathvariant="italic">&#x3A5;</mtext></math>=<span>1D6F6</span></span>
+ <span><math><mtext mathvariant="italic">&#x3A6;</mtext></math>=<span>1D6F7</span></span>
+ <span><math><mtext mathvariant="italic">&#x3A7;</mtext></math>=<span>1D6F8</span></span>
+ <span><math><mtext mathvariant="italic">&#x3A8;</mtext></math>=<span>1D6F9</span></span>
+ <span><math><mtext mathvariant="italic">&#x3A9;</mtext></math>=<span>1D6FA</span></span><br/>
+ <span><math><mtext mathvariant="italic">&#x3B1;</mtext></math>=<span>1D6FC</span></span>
+ <span><math><mtext mathvariant="italic">&#x3B2;</mtext></math>=<span>1D6FD</span></span>
+ <span><math><mtext mathvariant="italic">&#x3B3;</mtext></math>=<span>1D6FE</span></span>
+ <span><math><mtext mathvariant="italic">&#x3B4;</mtext></math>=<span>1D6FF</span></span>
+ <span><math><mtext mathvariant="italic">&#x3B5;</mtext></math>=<span>1D700</span></span>
+ <span><math><mtext mathvariant="italic">&#x3B6;</mtext></math>=<span>1D701</span></span>
+ <span><math><mtext mathvariant="italic">&#x3B7;</mtext></math>=<span>1D702</span></span>
+ <span><math><mtext mathvariant="italic">&#x3B8;</mtext></math>=<span>1D703</span></span>
+ <span><math><mtext mathvariant="italic">&#x3B9;</mtext></math>=<span>1D704</span></span>
+ <span><math><mtext mathvariant="italic">&#x3BA;</mtext></math>=<span>1D705</span></span><br/>
+ <span><math><mtext mathvariant="italic">&#x3BB;</mtext></math>=<span>1D706</span></span>
+ <span><math><mtext mathvariant="italic">&#x3BC;</mtext></math>=<span>1D707</span></span>
+ <span><math><mtext mathvariant="italic">&#x3BD;</mtext></math>=<span>1D708</span></span>
+ <span><math><mtext mathvariant="italic">&#x3BE;</mtext></math>=<span>1D709</span></span>
+ <span><math><mtext mathvariant="italic">&#x3BF;</mtext></math>=<span>1D70A</span></span>
+ <span><math><mtext mathvariant="italic">&#x3C0;</mtext></math>=<span>1D70B</span></span>
+ <span><math><mtext mathvariant="italic">&#x3C1;</mtext></math>=<span>1D70C</span></span>
+ <span><math><mtext mathvariant="italic">&#x3C2;</mtext></math>=<span>1D70D</span></span>
+ <span><math><mtext mathvariant="italic">&#x3C3;</mtext></math>=<span>1D70E</span></span>
+ <span><math><mtext mathvariant="italic">&#x3C4;</mtext></math>=<span>1D70F</span></span><br/>
+ <span><math><mtext mathvariant="italic">&#x3C5;</mtext></math>=<span>1D710</span></span>
+ <span><math><mtext mathvariant="italic">&#x3C6;</mtext></math>=<span>1D711</span></span>
+ <span><math><mtext mathvariant="italic">&#x3C7;</mtext></math>=<span>1D712</span></span>
+ <span><math><mtext mathvariant="italic">&#x3C8;</mtext></math>=<span>1D713</span></span>
+ <span><math><mtext mathvariant="italic">&#x3C9;</mtext></math>=<span>1D714</span></span>
+ <span><math><mtext mathvariant="italic">&#x3D1;</mtext></math>=<span>1D717</span></span>
+ <span><math><mtext mathvariant="italic">&#x3D5;</mtext></math>=<span>1D719</span></span>
+ <span><math><mtext mathvariant="italic">&#x3D6;</mtext></math>=<span>1D71B</span></span>
+ <span><math><mtext mathvariant="italic">&#x3F0;</mtext></math>=<span>1D718</span></span>
+ <span><math><mtext mathvariant="italic">&#x3F1;</mtext></math>=<span>1D71A</span></span><br/>
+ <span><math><mtext mathvariant="italic">&#x3F4;</mtext></math>=<span>1D6F3</span></span>
+ <span><math><mtext mathvariant="italic">&#x3F5;</mtext></math>=<span>1D716</span></span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-looped-ref.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-looped-ref.html
index 47c852073a9..49bafef99b8 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-looped-ref.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-looped-ref.html
@@ -23,32 +23,32 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi>&#x1EE80;</mi></math>=<span>1EE80</span></span>
- <span><math><mi>&#x1EE81;</mi></math>=<span>1EE81</span></span>
- <span><math><mi>&#x1EE95;</mi></math>=<span>1EE95</span></span>
- <span><math><mi>&#x1EE96;</mi></math>=<span>1EE96</span></span>
- <span><math><mi>&#x1EE82;</mi></math>=<span>1EE82</span></span>
- <span><math><mi>&#x1EE87;</mi></math>=<span>1EE87</span></span>
- <span><math><mi>&#x1EE97;</mi></math>=<span>1EE97</span></span>
- <span><math><mi>&#x1EE83;</mi></math>=<span>1EE83</span></span>
- <span><math><mi>&#x1EE98;</mi></math>=<span>1EE98</span></span>
- <span><math><mi>&#x1EE93;</mi></math>=<span>1EE93</span></span><br/>
- <span><math><mi>&#x1EE86;</mi></math>=<span>1EE86</span></span>
- <span><math><mi>&#x1EE8E;</mi></math>=<span>1EE8E</span></span>
- <span><math><mi>&#x1EE94;</mi></math>=<span>1EE94</span></span>
- <span><math><mi>&#x1EE91;</mi></math>=<span>1EE91</span></span>
- <span><math><mi>&#x1EE99;</mi></math>=<span>1EE99</span></span>
- <span><math><mi>&#x1EE88;</mi></math>=<span>1EE88</span></span>
- <span><math><mi>&#x1EE9A;</mi></math>=<span>1EE9A</span></span>
- <span><math><mi>&#x1EE8F;</mi></math>=<span>1EE8F</span></span>
- <span><math><mi>&#x1EE9B;</mi></math>=<span>1EE9B</span></span>
- <span><math><mi>&#x1EE90;</mi></math>=<span>1EE90</span></span><br/>
- <span><math><mi>&#x1EE92;</mi></math>=<span>1EE92</span></span>
- <span><math><mi>&#x1EE8B;</mi></math>=<span>1EE8B</span></span>
- <span><math><mi>&#x1EE8C;</mi></math>=<span>1EE8C</span></span>
- <span><math><mi>&#x1EE8D;</mi></math>=<span>1EE8D</span></span>
- <span><math><mi>&#x1EE84;</mi></math>=<span>1EE84</span></span>
- <span><math><mi>&#x1EE85;</mi></math>=<span>1EE85</span></span>
- <span><math><mi>&#x1EE89;</mi></math>=<span>1EE89</span></span>
+ <span><math><mtext>&#x1EE80;</mtext></math>=<span>1EE80</span></span>
+ <span><math><mtext>&#x1EE81;</mtext></math>=<span>1EE81</span></span>
+ <span><math><mtext>&#x1EE95;</mtext></math>=<span>1EE95</span></span>
+ <span><math><mtext>&#x1EE96;</mtext></math>=<span>1EE96</span></span>
+ <span><math><mtext>&#x1EE82;</mtext></math>=<span>1EE82</span></span>
+ <span><math><mtext>&#x1EE87;</mtext></math>=<span>1EE87</span></span>
+ <span><math><mtext>&#x1EE97;</mtext></math>=<span>1EE97</span></span>
+ <span><math><mtext>&#x1EE83;</mtext></math>=<span>1EE83</span></span>
+ <span><math><mtext>&#x1EE98;</mtext></math>=<span>1EE98</span></span>
+ <span><math><mtext>&#x1EE93;</mtext></math>=<span>1EE93</span></span><br/>
+ <span><math><mtext>&#x1EE86;</mtext></math>=<span>1EE86</span></span>
+ <span><math><mtext>&#x1EE8E;</mtext></math>=<span>1EE8E</span></span>
+ <span><math><mtext>&#x1EE94;</mtext></math>=<span>1EE94</span></span>
+ <span><math><mtext>&#x1EE91;</mtext></math>=<span>1EE91</span></span>
+ <span><math><mtext>&#x1EE99;</mtext></math>=<span>1EE99</span></span>
+ <span><math><mtext>&#x1EE88;</mtext></math>=<span>1EE88</span></span>
+ <span><math><mtext>&#x1EE9A;</mtext></math>=<span>1EE9A</span></span>
+ <span><math><mtext>&#x1EE8F;</mtext></math>=<span>1EE8F</span></span>
+ <span><math><mtext>&#x1EE9B;</mtext></math>=<span>1EE9B</span></span>
+ <span><math><mtext>&#x1EE90;</mtext></math>=<span>1EE90</span></span><br/>
+ <span><math><mtext>&#x1EE92;</mtext></math>=<span>1EE92</span></span>
+ <span><math><mtext>&#x1EE8B;</mtext></math>=<span>1EE8B</span></span>
+ <span><math><mtext>&#x1EE8C;</mtext></math>=<span>1EE8C</span></span>
+ <span><math><mtext>&#x1EE8D;</mtext></math>=<span>1EE8D</span></span>
+ <span><math><mtext>&#x1EE84;</mtext></math>=<span>1EE84</span></span>
+ <span><math><mtext>&#x1EE85;</mtext></math>=<span>1EE85</span></span>
+ <span><math><mtext>&#x1EE89;</mtext></math>=<span>1EE89</span></span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-looped.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-looped.html
index 42926690fa5..81206e1facf 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-looped.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-looped.html
@@ -5,7 +5,7 @@
<title>mathvariant looped</title>
<link rel="help" href="http://www.mathml-association.org/MathMLinHTML5/S2.html#SS3.SSS1.tab2"/>
<link rel="match" href="mathvariant-looped-ref.html"/>
-<meta name="assert" content="Verify that a single-char <mi> with a looped mathvariant is equivalent to an <mi> with the transformed unicode character.">
+<meta name="assert" content="Verify that a single-char <mtext> with a looped mathvariant is equivalent to an <mtext> with the transformed unicode character.">
<style>
@font-face {
font-family: TestFont;
@@ -26,32 +26,32 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi mathvariant="looped">&#x627;</mi></math>=<span>1EE80</span></span>
- <span><math><mi mathvariant="looped">&#x628;</mi></math>=<span>1EE81</span></span>
- <span><math><mi mathvariant="looped">&#x62A;</mi></math>=<span>1EE95</span></span>
- <span><math><mi mathvariant="looped">&#x62B;</mi></math>=<span>1EE96</span></span>
- <span><math><mi mathvariant="looped">&#x62C;</mi></math>=<span>1EE82</span></span>
- <span><math><mi mathvariant="looped">&#x62D;</mi></math>=<span>1EE87</span></span>
- <span><math><mi mathvariant="looped">&#x62E;</mi></math>=<span>1EE97</span></span>
- <span><math><mi mathvariant="looped">&#x62F;</mi></math>=<span>1EE83</span></span>
- <span><math><mi mathvariant="looped">&#x630;</mi></math>=<span>1EE98</span></span>
- <span><math><mi mathvariant="looped">&#x631;</mi></math>=<span>1EE93</span></span><br/>
- <span><math><mi mathvariant="looped">&#x632;</mi></math>=<span>1EE86</span></span>
- <span><math><mi mathvariant="looped">&#x633;</mi></math>=<span>1EE8E</span></span>
- <span><math><mi mathvariant="looped">&#x634;</mi></math>=<span>1EE94</span></span>
- <span><math><mi mathvariant="looped">&#x635;</mi></math>=<span>1EE91</span></span>
- <span><math><mi mathvariant="looped">&#x636;</mi></math>=<span>1EE99</span></span>
- <span><math><mi mathvariant="looped">&#x637;</mi></math>=<span>1EE88</span></span>
- <span><math><mi mathvariant="looped">&#x638;</mi></math>=<span>1EE9A</span></span>
- <span><math><mi mathvariant="looped">&#x639;</mi></math>=<span>1EE8F</span></span>
- <span><math><mi mathvariant="looped">&#x63A;</mi></math>=<span>1EE9B</span></span>
- <span><math><mi mathvariant="looped">&#x641;</mi></math>=<span>1EE90</span></span><br/>
- <span><math><mi mathvariant="looped">&#x642;</mi></math>=<span>1EE92</span></span>
- <span><math><mi mathvariant="looped">&#x644;</mi></math>=<span>1EE8B</span></span>
- <span><math><mi mathvariant="looped">&#x645;</mi></math>=<span>1EE8C</span></span>
- <span><math><mi mathvariant="looped">&#x646;</mi></math>=<span>1EE8D</span></span>
- <span><math><mi mathvariant="looped">&#x647;</mi></math>=<span>1EE84</span></span>
- <span><math><mi mathvariant="looped">&#x648;</mi></math>=<span>1EE85</span></span>
- <span><math><mi mathvariant="looped">&#x64A;</mi></math>=<span>1EE89</span></span>
+ <span><math><mtext mathvariant="looped">&#x627;</mtext></math>=<span>1EE80</span></span>
+ <span><math><mtext mathvariant="looped">&#x628;</mtext></math>=<span>1EE81</span></span>
+ <span><math><mtext mathvariant="looped">&#x62A;</mtext></math>=<span>1EE95</span></span>
+ <span><math><mtext mathvariant="looped">&#x62B;</mtext></math>=<span>1EE96</span></span>
+ <span><math><mtext mathvariant="looped">&#x62C;</mtext></math>=<span>1EE82</span></span>
+ <span><math><mtext mathvariant="looped">&#x62D;</mtext></math>=<span>1EE87</span></span>
+ <span><math><mtext mathvariant="looped">&#x62E;</mtext></math>=<span>1EE97</span></span>
+ <span><math><mtext mathvariant="looped">&#x62F;</mtext></math>=<span>1EE83</span></span>
+ <span><math><mtext mathvariant="looped">&#x630;</mtext></math>=<span>1EE98</span></span>
+ <span><math><mtext mathvariant="looped">&#x631;</mtext></math>=<span>1EE93</span></span><br/>
+ <span><math><mtext mathvariant="looped">&#x632;</mtext></math>=<span>1EE86</span></span>
+ <span><math><mtext mathvariant="looped">&#x633;</mtext></math>=<span>1EE8E</span></span>
+ <span><math><mtext mathvariant="looped">&#x634;</mtext></math>=<span>1EE94</span></span>
+ <span><math><mtext mathvariant="looped">&#x635;</mtext></math>=<span>1EE91</span></span>
+ <span><math><mtext mathvariant="looped">&#x636;</mtext></math>=<span>1EE99</span></span>
+ <span><math><mtext mathvariant="looped">&#x637;</mtext></math>=<span>1EE88</span></span>
+ <span><math><mtext mathvariant="looped">&#x638;</mtext></math>=<span>1EE9A</span></span>
+ <span><math><mtext mathvariant="looped">&#x639;</mtext></math>=<span>1EE8F</span></span>
+ <span><math><mtext mathvariant="looped">&#x63A;</mtext></math>=<span>1EE9B</span></span>
+ <span><math><mtext mathvariant="looped">&#x641;</mtext></math>=<span>1EE90</span></span><br/>
+ <span><math><mtext mathvariant="looped">&#x642;</mtext></math>=<span>1EE92</span></span>
+ <span><math><mtext mathvariant="looped">&#x644;</mtext></math>=<span>1EE8B</span></span>
+ <span><math><mtext mathvariant="looped">&#x645;</mtext></math>=<span>1EE8C</span></span>
+ <span><math><mtext mathvariant="looped">&#x646;</mtext></math>=<span>1EE8D</span></span>
+ <span><math><mtext mathvariant="looped">&#x647;</mtext></math>=<span>1EE84</span></span>
+ <span><math><mtext mathvariant="looped">&#x648;</mtext></math>=<span>1EE85</span></span>
+ <span><math><mtext mathvariant="looped">&#x64A;</mtext></math>=<span>1EE89</span></span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-monospace-ref.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-monospace-ref.html
index 713ce69d8da..9b695a1a447 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-monospace-ref.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-monospace-ref.html
@@ -23,67 +23,67 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi>&#x1D7F6;</mi></math>=<span>1D7F6</span></span>
- <span><math><mi>&#x1D7F7;</mi></math>=<span>1D7F7</span></span>
- <span><math><mi>&#x1D7F8;</mi></math>=<span>1D7F8</span></span>
- <span><math><mi>&#x1D7F9;</mi></math>=<span>1D7F9</span></span>
- <span><math><mi>&#x1D7FA;</mi></math>=<span>1D7FA</span></span>
- <span><math><mi>&#x1D7FB;</mi></math>=<span>1D7FB</span></span>
- <span><math><mi>&#x1D7FC;</mi></math>=<span>1D7FC</span></span>
- <span><math><mi>&#x1D7FD;</mi></math>=<span>1D7FD</span></span>
- <span><math><mi>&#x1D7FE;</mi></math>=<span>1D7FE</span></span>
- <span><math><mi>&#x1D7FF;</mi></math>=<span>1D7FF</span></span><br/>
- <span><math><mi>&#x1D670;</mi></math>=<span>1D670</span></span>
- <span><math><mi>&#x1D671;</mi></math>=<span>1D671</span></span>
- <span><math><mi>&#x1D672;</mi></math>=<span>1D672</span></span>
- <span><math><mi>&#x1D673;</mi></math>=<span>1D673</span></span>
- <span><math><mi>&#x1D674;</mi></math>=<span>1D674</span></span>
- <span><math><mi>&#x1D675;</mi></math>=<span>1D675</span></span>
- <span><math><mi>&#x1D676;</mi></math>=<span>1D676</span></span>
- <span><math><mi>&#x1D677;</mi></math>=<span>1D677</span></span>
- <span><math><mi>&#x1D678;</mi></math>=<span>1D678</span></span>
- <span><math><mi>&#x1D679;</mi></math>=<span>1D679</span></span><br/>
- <span><math><mi>&#x1D67A;</mi></math>=<span>1D67A</span></span>
- <span><math><mi>&#x1D67B;</mi></math>=<span>1D67B</span></span>
- <span><math><mi>&#x1D67C;</mi></math>=<span>1D67C</span></span>
- <span><math><mi>&#x1D67D;</mi></math>=<span>1D67D</span></span>
- <span><math><mi>&#x1D67E;</mi></math>=<span>1D67E</span></span>
- <span><math><mi>&#x1D67F;</mi></math>=<span>1D67F</span></span>
- <span><math><mi>&#x1D680;</mi></math>=<span>1D680</span></span>
- <span><math><mi>&#x1D681;</mi></math>=<span>1D681</span></span>
- <span><math><mi>&#x1D682;</mi></math>=<span>1D682</span></span>
- <span><math><mi>&#x1D683;</mi></math>=<span>1D683</span></span><br/>
- <span><math><mi>&#x1D684;</mi></math>=<span>1D684</span></span>
- <span><math><mi>&#x1D685;</mi></math>=<span>1D685</span></span>
- <span><math><mi>&#x1D686;</mi></math>=<span>1D686</span></span>
- <span><math><mi>&#x1D687;</mi></math>=<span>1D687</span></span>
- <span><math><mi>&#x1D688;</mi></math>=<span>1D688</span></span>
- <span><math><mi>&#x1D689;</mi></math>=<span>1D689</span></span>
- <span><math><mi>&#x1D68A;</mi></math>=<span>1D68A</span></span>
- <span><math><mi>&#x1D68B;</mi></math>=<span>1D68B</span></span>
- <span><math><mi>&#x1D68C;</mi></math>=<span>1D68C</span></span>
- <span><math><mi>&#x1D68D;</mi></math>=<span>1D68D</span></span><br/>
- <span><math><mi>&#x1D68E;</mi></math>=<span>1D68E</span></span>
- <span><math><mi>&#x1D68F;</mi></math>=<span>1D68F</span></span>
- <span><math><mi>&#x1D690;</mi></math>=<span>1D690</span></span>
- <span><math><mi>&#x1D691;</mi></math>=<span>1D691</span></span>
- <span><math><mi>&#x1D692;</mi></math>=<span>1D692</span></span>
- <span><math><mi>&#x1D693;</mi></math>=<span>1D693</span></span>
- <span><math><mi>&#x1D694;</mi></math>=<span>1D694</span></span>
- <span><math><mi>&#x1D695;</mi></math>=<span>1D695</span></span>
- <span><math><mi>&#x1D696;</mi></math>=<span>1D696</span></span>
- <span><math><mi>&#x1D697;</mi></math>=<span>1D697</span></span><br/>
- <span><math><mi>&#x1D698;</mi></math>=<span>1D698</span></span>
- <span><math><mi>&#x1D699;</mi></math>=<span>1D699</span></span>
- <span><math><mi>&#x1D69A;</mi></math>=<span>1D69A</span></span>
- <span><math><mi>&#x1D69B;</mi></math>=<span>1D69B</span></span>
- <span><math><mi>&#x1D69C;</mi></math>=<span>1D69C</span></span>
- <span><math><mi>&#x1D69D;</mi></math>=<span>1D69D</span></span>
- <span><math><mi>&#x1D69E;</mi></math>=<span>1D69E</span></span>
- <span><math><mi>&#x1D69F;</mi></math>=<span>1D69F</span></span>
- <span><math><mi>&#x1D6A0;</mi></math>=<span>1D6A0</span></span>
- <span><math><mi>&#x1D6A1;</mi></math>=<span>1D6A1</span></span><br/>
- <span><math><mi>&#x1D6A2;</mi></math>=<span>1D6A2</span></span>
- <span><math><mi>&#x1D6A3;</mi></math>=<span>1D6A3</span></span>
+ <span><math><mtext>&#x1D7F6;</mtext></math>=<span>1D7F6</span></span>
+ <span><math><mtext>&#x1D7F7;</mtext></math>=<span>1D7F7</span></span>
+ <span><math><mtext>&#x1D7F8;</mtext></math>=<span>1D7F8</span></span>
+ <span><math><mtext>&#x1D7F9;</mtext></math>=<span>1D7F9</span></span>
+ <span><math><mtext>&#x1D7FA;</mtext></math>=<span>1D7FA</span></span>
+ <span><math><mtext>&#x1D7FB;</mtext></math>=<span>1D7FB</span></span>
+ <span><math><mtext>&#x1D7FC;</mtext></math>=<span>1D7FC</span></span>
+ <span><math><mtext>&#x1D7FD;</mtext></math>=<span>1D7FD</span></span>
+ <span><math><mtext>&#x1D7FE;</mtext></math>=<span>1D7FE</span></span>
+ <span><math><mtext>&#x1D7FF;</mtext></math>=<span>1D7FF</span></span><br/>
+ <span><math><mtext>&#x1D670;</mtext></math>=<span>1D670</span></span>
+ <span><math><mtext>&#x1D671;</mtext></math>=<span>1D671</span></span>
+ <span><math><mtext>&#x1D672;</mtext></math>=<span>1D672</span></span>
+ <span><math><mtext>&#x1D673;</mtext></math>=<span>1D673</span></span>
+ <span><math><mtext>&#x1D674;</mtext></math>=<span>1D674</span></span>
+ <span><math><mtext>&#x1D675;</mtext></math>=<span>1D675</span></span>
+ <span><math><mtext>&#x1D676;</mtext></math>=<span>1D676</span></span>
+ <span><math><mtext>&#x1D677;</mtext></math>=<span>1D677</span></span>
+ <span><math><mtext>&#x1D678;</mtext></math>=<span>1D678</span></span>
+ <span><math><mtext>&#x1D679;</mtext></math>=<span>1D679</span></span><br/>
+ <span><math><mtext>&#x1D67A;</mtext></math>=<span>1D67A</span></span>
+ <span><math><mtext>&#x1D67B;</mtext></math>=<span>1D67B</span></span>
+ <span><math><mtext>&#x1D67C;</mtext></math>=<span>1D67C</span></span>
+ <span><math><mtext>&#x1D67D;</mtext></math>=<span>1D67D</span></span>
+ <span><math><mtext>&#x1D67E;</mtext></math>=<span>1D67E</span></span>
+ <span><math><mtext>&#x1D67F;</mtext></math>=<span>1D67F</span></span>
+ <span><math><mtext>&#x1D680;</mtext></math>=<span>1D680</span></span>
+ <span><math><mtext>&#x1D681;</mtext></math>=<span>1D681</span></span>
+ <span><math><mtext>&#x1D682;</mtext></math>=<span>1D682</span></span>
+ <span><math><mtext>&#x1D683;</mtext></math>=<span>1D683</span></span><br/>
+ <span><math><mtext>&#x1D684;</mtext></math>=<span>1D684</span></span>
+ <span><math><mtext>&#x1D685;</mtext></math>=<span>1D685</span></span>
+ <span><math><mtext>&#x1D686;</mtext></math>=<span>1D686</span></span>
+ <span><math><mtext>&#x1D687;</mtext></math>=<span>1D687</span></span>
+ <span><math><mtext>&#x1D688;</mtext></math>=<span>1D688</span></span>
+ <span><math><mtext>&#x1D689;</mtext></math>=<span>1D689</span></span>
+ <span><math><mtext>&#x1D68A;</mtext></math>=<span>1D68A</span></span>
+ <span><math><mtext>&#x1D68B;</mtext></math>=<span>1D68B</span></span>
+ <span><math><mtext>&#x1D68C;</mtext></math>=<span>1D68C</span></span>
+ <span><math><mtext>&#x1D68D;</mtext></math>=<span>1D68D</span></span><br/>
+ <span><math><mtext>&#x1D68E;</mtext></math>=<span>1D68E</span></span>
+ <span><math><mtext>&#x1D68F;</mtext></math>=<span>1D68F</span></span>
+ <span><math><mtext>&#x1D690;</mtext></math>=<span>1D690</span></span>
+ <span><math><mtext>&#x1D691;</mtext></math>=<span>1D691</span></span>
+ <span><math><mtext>&#x1D692;</mtext></math>=<span>1D692</span></span>
+ <span><math><mtext>&#x1D693;</mtext></math>=<span>1D693</span></span>
+ <span><math><mtext>&#x1D694;</mtext></math>=<span>1D694</span></span>
+ <span><math><mtext>&#x1D695;</mtext></math>=<span>1D695</span></span>
+ <span><math><mtext>&#x1D696;</mtext></math>=<span>1D696</span></span>
+ <span><math><mtext>&#x1D697;</mtext></math>=<span>1D697</span></span><br/>
+ <span><math><mtext>&#x1D698;</mtext></math>=<span>1D698</span></span>
+ <span><math><mtext>&#x1D699;</mtext></math>=<span>1D699</span></span>
+ <span><math><mtext>&#x1D69A;</mtext></math>=<span>1D69A</span></span>
+ <span><math><mtext>&#x1D69B;</mtext></math>=<span>1D69B</span></span>
+ <span><math><mtext>&#x1D69C;</mtext></math>=<span>1D69C</span></span>
+ <span><math><mtext>&#x1D69D;</mtext></math>=<span>1D69D</span></span>
+ <span><math><mtext>&#x1D69E;</mtext></math>=<span>1D69E</span></span>
+ <span><math><mtext>&#x1D69F;</mtext></math>=<span>1D69F</span></span>
+ <span><math><mtext>&#x1D6A0;</mtext></math>=<span>1D6A0</span></span>
+ <span><math><mtext>&#x1D6A1;</mtext></math>=<span>1D6A1</span></span><br/>
+ <span><math><mtext>&#x1D6A2;</mtext></math>=<span>1D6A2</span></span>
+ <span><math><mtext>&#x1D6A3;</mtext></math>=<span>1D6A3</span></span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-monospace.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-monospace.html
index 8a01d1a8c21..8d4a4ad9234 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-monospace.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-monospace.html
@@ -5,7 +5,7 @@
<title>mathvariant monospace</title>
<link rel="help" href="http://www.mathml-association.org/MathMLinHTML5/S2.html#SS3.SSS1.tab2"/>
<link rel="match" href="mathvariant-monospace-ref.html"/>
-<meta name="assert" content="Verify that a single-char <mi> with a monospace mathvariant is equivalent to an <mi> with the transformed unicode character.">
+<meta name="assert" content="Verify that a single-char <mtext> with a monospace mathvariant is equivalent to an <mtext> with the transformed unicode character.">
<style>
@font-face {
font-family: TestFont;
@@ -26,67 +26,67 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi mathvariant="monospace">&#x30;</mi></math>=<span>1D7F6</span></span>
- <span><math><mi mathvariant="monospace">&#x31;</mi></math>=<span>1D7F7</span></span>
- <span><math><mi mathvariant="monospace">&#x32;</mi></math>=<span>1D7F8</span></span>
- <span><math><mi mathvariant="monospace">&#x33;</mi></math>=<span>1D7F9</span></span>
- <span><math><mi mathvariant="monospace">&#x34;</mi></math>=<span>1D7FA</span></span>
- <span><math><mi mathvariant="monospace">&#x35;</mi></math>=<span>1D7FB</span></span>
- <span><math><mi mathvariant="monospace">&#x36;</mi></math>=<span>1D7FC</span></span>
- <span><math><mi mathvariant="monospace">&#x37;</mi></math>=<span>1D7FD</span></span>
- <span><math><mi mathvariant="monospace">&#x38;</mi></math>=<span>1D7FE</span></span>
- <span><math><mi mathvariant="monospace">&#x39;</mi></math>=<span>1D7FF</span></span><br/>
- <span><math><mi mathvariant="monospace">&#x41;</mi></math>=<span>1D670</span></span>
- <span><math><mi mathvariant="monospace">&#x42;</mi></math>=<span>1D671</span></span>
- <span><math><mi mathvariant="monospace">&#x43;</mi></math>=<span>1D672</span></span>
- <span><math><mi mathvariant="monospace">&#x44;</mi></math>=<span>1D673</span></span>
- <span><math><mi mathvariant="monospace">&#x45;</mi></math>=<span>1D674</span></span>
- <span><math><mi mathvariant="monospace">&#x46;</mi></math>=<span>1D675</span></span>
- <span><math><mi mathvariant="monospace">&#x47;</mi></math>=<span>1D676</span></span>
- <span><math><mi mathvariant="monospace">&#x48;</mi></math>=<span>1D677</span></span>
- <span><math><mi mathvariant="monospace">&#x49;</mi></math>=<span>1D678</span></span>
- <span><math><mi mathvariant="monospace">&#x4A;</mi></math>=<span>1D679</span></span><br/>
- <span><math><mi mathvariant="monospace">&#x4B;</mi></math>=<span>1D67A</span></span>
- <span><math><mi mathvariant="monospace">&#x4C;</mi></math>=<span>1D67B</span></span>
- <span><math><mi mathvariant="monospace">&#x4D;</mi></math>=<span>1D67C</span></span>
- <span><math><mi mathvariant="monospace">&#x4E;</mi></math>=<span>1D67D</span></span>
- <span><math><mi mathvariant="monospace">&#x4F;</mi></math>=<span>1D67E</span></span>
- <span><math><mi mathvariant="monospace">&#x50;</mi></math>=<span>1D67F</span></span>
- <span><math><mi mathvariant="monospace">&#x51;</mi></math>=<span>1D680</span></span>
- <span><math><mi mathvariant="monospace">&#x52;</mi></math>=<span>1D681</span></span>
- <span><math><mi mathvariant="monospace">&#x53;</mi></math>=<span>1D682</span></span>
- <span><math><mi mathvariant="monospace">&#x54;</mi></math>=<span>1D683</span></span><br/>
- <span><math><mi mathvariant="monospace">&#x55;</mi></math>=<span>1D684</span></span>
- <span><math><mi mathvariant="monospace">&#x56;</mi></math>=<span>1D685</span></span>
- <span><math><mi mathvariant="monospace">&#x57;</mi></math>=<span>1D686</span></span>
- <span><math><mi mathvariant="monospace">&#x58;</mi></math>=<span>1D687</span></span>
- <span><math><mi mathvariant="monospace">&#x59;</mi></math>=<span>1D688</span></span>
- <span><math><mi mathvariant="monospace">&#x5A;</mi></math>=<span>1D689</span></span>
- <span><math><mi mathvariant="monospace">&#x61;</mi></math>=<span>1D68A</span></span>
- <span><math><mi mathvariant="monospace">&#x62;</mi></math>=<span>1D68B</span></span>
- <span><math><mi mathvariant="monospace">&#x63;</mi></math>=<span>1D68C</span></span>
- <span><math><mi mathvariant="monospace">&#x64;</mi></math>=<span>1D68D</span></span><br/>
- <span><math><mi mathvariant="monospace">&#x65;</mi></math>=<span>1D68E</span></span>
- <span><math><mi mathvariant="monospace">&#x66;</mi></math>=<span>1D68F</span></span>
- <span><math><mi mathvariant="monospace">&#x67;</mi></math>=<span>1D690</span></span>
- <span><math><mi mathvariant="monospace">&#x68;</mi></math>=<span>1D691</span></span>
- <span><math><mi mathvariant="monospace">&#x69;</mi></math>=<span>1D692</span></span>
- <span><math><mi mathvariant="monospace">&#x6A;</mi></math>=<span>1D693</span></span>
- <span><math><mi mathvariant="monospace">&#x6B;</mi></math>=<span>1D694</span></span>
- <span><math><mi mathvariant="monospace">&#x6C;</mi></math>=<span>1D695</span></span>
- <span><math><mi mathvariant="monospace">&#x6D;</mi></math>=<span>1D696</span></span>
- <span><math><mi mathvariant="monospace">&#x6E;</mi></math>=<span>1D697</span></span><br/>
- <span><math><mi mathvariant="monospace">&#x6F;</mi></math>=<span>1D698</span></span>
- <span><math><mi mathvariant="monospace">&#x70;</mi></math>=<span>1D699</span></span>
- <span><math><mi mathvariant="monospace">&#x71;</mi></math>=<span>1D69A</span></span>
- <span><math><mi mathvariant="monospace">&#x72;</mi></math>=<span>1D69B</span></span>
- <span><math><mi mathvariant="monospace">&#x73;</mi></math>=<span>1D69C</span></span>
- <span><math><mi mathvariant="monospace">&#x74;</mi></math>=<span>1D69D</span></span>
- <span><math><mi mathvariant="monospace">&#x75;</mi></math>=<span>1D69E</span></span>
- <span><math><mi mathvariant="monospace">&#x76;</mi></math>=<span>1D69F</span></span>
- <span><math><mi mathvariant="monospace">&#x77;</mi></math>=<span>1D6A0</span></span>
- <span><math><mi mathvariant="monospace">&#x78;</mi></math>=<span>1D6A1</span></span><br/>
- <span><math><mi mathvariant="monospace">&#x79;</mi></math>=<span>1D6A2</span></span>
- <span><math><mi mathvariant="monospace">&#x7A;</mi></math>=<span>1D6A3</span></span>
+ <span><math><mtext mathvariant="monospace">&#x30;</mtext></math>=<span>1D7F6</span></span>
+ <span><math><mtext mathvariant="monospace">&#x31;</mtext></math>=<span>1D7F7</span></span>
+ <span><math><mtext mathvariant="monospace">&#x32;</mtext></math>=<span>1D7F8</span></span>
+ <span><math><mtext mathvariant="monospace">&#x33;</mtext></math>=<span>1D7F9</span></span>
+ <span><math><mtext mathvariant="monospace">&#x34;</mtext></math>=<span>1D7FA</span></span>
+ <span><math><mtext mathvariant="monospace">&#x35;</mtext></math>=<span>1D7FB</span></span>
+ <span><math><mtext mathvariant="monospace">&#x36;</mtext></math>=<span>1D7FC</span></span>
+ <span><math><mtext mathvariant="monospace">&#x37;</mtext></math>=<span>1D7FD</span></span>
+ <span><math><mtext mathvariant="monospace">&#x38;</mtext></math>=<span>1D7FE</span></span>
+ <span><math><mtext mathvariant="monospace">&#x39;</mtext></math>=<span>1D7FF</span></span><br/>
+ <span><math><mtext mathvariant="monospace">&#x41;</mtext></math>=<span>1D670</span></span>
+ <span><math><mtext mathvariant="monospace">&#x42;</mtext></math>=<span>1D671</span></span>
+ <span><math><mtext mathvariant="monospace">&#x43;</mtext></math>=<span>1D672</span></span>
+ <span><math><mtext mathvariant="monospace">&#x44;</mtext></math>=<span>1D673</span></span>
+ <span><math><mtext mathvariant="monospace">&#x45;</mtext></math>=<span>1D674</span></span>
+ <span><math><mtext mathvariant="monospace">&#x46;</mtext></math>=<span>1D675</span></span>
+ <span><math><mtext mathvariant="monospace">&#x47;</mtext></math>=<span>1D676</span></span>
+ <span><math><mtext mathvariant="monospace">&#x48;</mtext></math>=<span>1D677</span></span>
+ <span><math><mtext mathvariant="monospace">&#x49;</mtext></math>=<span>1D678</span></span>
+ <span><math><mtext mathvariant="monospace">&#x4A;</mtext></math>=<span>1D679</span></span><br/>
+ <span><math><mtext mathvariant="monospace">&#x4B;</mtext></math>=<span>1D67A</span></span>
+ <span><math><mtext mathvariant="monospace">&#x4C;</mtext></math>=<span>1D67B</span></span>
+ <span><math><mtext mathvariant="monospace">&#x4D;</mtext></math>=<span>1D67C</span></span>
+ <span><math><mtext mathvariant="monospace">&#x4E;</mtext></math>=<span>1D67D</span></span>
+ <span><math><mtext mathvariant="monospace">&#x4F;</mtext></math>=<span>1D67E</span></span>
+ <span><math><mtext mathvariant="monospace">&#x50;</mtext></math>=<span>1D67F</span></span>
+ <span><math><mtext mathvariant="monospace">&#x51;</mtext></math>=<span>1D680</span></span>
+ <span><math><mtext mathvariant="monospace">&#x52;</mtext></math>=<span>1D681</span></span>
+ <span><math><mtext mathvariant="monospace">&#x53;</mtext></math>=<span>1D682</span></span>
+ <span><math><mtext mathvariant="monospace">&#x54;</mtext></math>=<span>1D683</span></span><br/>
+ <span><math><mtext mathvariant="monospace">&#x55;</mtext></math>=<span>1D684</span></span>
+ <span><math><mtext mathvariant="monospace">&#x56;</mtext></math>=<span>1D685</span></span>
+ <span><math><mtext mathvariant="monospace">&#x57;</mtext></math>=<span>1D686</span></span>
+ <span><math><mtext mathvariant="monospace">&#x58;</mtext></math>=<span>1D687</span></span>
+ <span><math><mtext mathvariant="monospace">&#x59;</mtext></math>=<span>1D688</span></span>
+ <span><math><mtext mathvariant="monospace">&#x5A;</mtext></math>=<span>1D689</span></span>
+ <span><math><mtext mathvariant="monospace">&#x61;</mtext></math>=<span>1D68A</span></span>
+ <span><math><mtext mathvariant="monospace">&#x62;</mtext></math>=<span>1D68B</span></span>
+ <span><math><mtext mathvariant="monospace">&#x63;</mtext></math>=<span>1D68C</span></span>
+ <span><math><mtext mathvariant="monospace">&#x64;</mtext></math>=<span>1D68D</span></span><br/>
+ <span><math><mtext mathvariant="monospace">&#x65;</mtext></math>=<span>1D68E</span></span>
+ <span><math><mtext mathvariant="monospace">&#x66;</mtext></math>=<span>1D68F</span></span>
+ <span><math><mtext mathvariant="monospace">&#x67;</mtext></math>=<span>1D690</span></span>
+ <span><math><mtext mathvariant="monospace">&#x68;</mtext></math>=<span>1D691</span></span>
+ <span><math><mtext mathvariant="monospace">&#x69;</mtext></math>=<span>1D692</span></span>
+ <span><math><mtext mathvariant="monospace">&#x6A;</mtext></math>=<span>1D693</span></span>
+ <span><math><mtext mathvariant="monospace">&#x6B;</mtext></math>=<span>1D694</span></span>
+ <span><math><mtext mathvariant="monospace">&#x6C;</mtext></math>=<span>1D695</span></span>
+ <span><math><mtext mathvariant="monospace">&#x6D;</mtext></math>=<span>1D696</span></span>
+ <span><math><mtext mathvariant="monospace">&#x6E;</mtext></math>=<span>1D697</span></span><br/>
+ <span><math><mtext mathvariant="monospace">&#x6F;</mtext></math>=<span>1D698</span></span>
+ <span><math><mtext mathvariant="monospace">&#x70;</mtext></math>=<span>1D699</span></span>
+ <span><math><mtext mathvariant="monospace">&#x71;</mtext></math>=<span>1D69A</span></span>
+ <span><math><mtext mathvariant="monospace">&#x72;</mtext></math>=<span>1D69B</span></span>
+ <span><math><mtext mathvariant="monospace">&#x73;</mtext></math>=<span>1D69C</span></span>
+ <span><math><mtext mathvariant="monospace">&#x74;</mtext></math>=<span>1D69D</span></span>
+ <span><math><mtext mathvariant="monospace">&#x75;</mtext></math>=<span>1D69E</span></span>
+ <span><math><mtext mathvariant="monospace">&#x76;</mtext></math>=<span>1D69F</span></span>
+ <span><math><mtext mathvariant="monospace">&#x77;</mtext></math>=<span>1D6A0</span></span>
+ <span><math><mtext mathvariant="monospace">&#x78;</mtext></math>=<span>1D6A1</span></span><br/>
+ <span><math><mtext mathvariant="monospace">&#x79;</mtext></math>=<span>1D6A2</span></span>
+ <span><math><mtext mathvariant="monospace">&#x7A;</mtext></math>=<span>1D6A3</span></span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif-bold-italic-ref.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif-bold-italic-ref.html
index 952bea76a00..f8ef62bd6a2 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif-bold-italic-ref.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif-bold-italic-ref.html
@@ -23,115 +23,115 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi>&#x1D7C3;</mi></math>=<span>1D7C3</span></span>
- <span><math><mi>&#x1D7A9;</mi></math>=<span>1D7A9</span></span>
- <span><math><mi>&#x1D63C;</mi></math>=<span>1D63C</span></span>
- <span><math><mi>&#x1D63D;</mi></math>=<span>1D63D</span></span>
- <span><math><mi>&#x1D63E;</mi></math>=<span>1D63E</span></span>
- <span><math><mi>&#x1D63F;</mi></math>=<span>1D63F</span></span>
- <span><math><mi>&#x1D640;</mi></math>=<span>1D640</span></span>
- <span><math><mi>&#x1D641;</mi></math>=<span>1D641</span></span>
- <span><math><mi>&#x1D642;</mi></math>=<span>1D642</span></span>
- <span><math><mi>&#x1D643;</mi></math>=<span>1D643</span></span><br/>
- <span><math><mi>&#x1D644;</mi></math>=<span>1D644</span></span>
- <span><math><mi>&#x1D645;</mi></math>=<span>1D645</span></span>
- <span><math><mi>&#x1D646;</mi></math>=<span>1D646</span></span>
- <span><math><mi>&#x1D647;</mi></math>=<span>1D647</span></span>
- <span><math><mi>&#x1D648;</mi></math>=<span>1D648</span></span>
- <span><math><mi>&#x1D649;</mi></math>=<span>1D649</span></span>
- <span><math><mi>&#x1D64A;</mi></math>=<span>1D64A</span></span>
- <span><math><mi>&#x1D64B;</mi></math>=<span>1D64B</span></span>
- <span><math><mi>&#x1D64C;</mi></math>=<span>1D64C</span></span>
- <span><math><mi>&#x1D64D;</mi></math>=<span>1D64D</span></span><br/>
- <span><math><mi>&#x1D64E;</mi></math>=<span>1D64E</span></span>
- <span><math><mi>&#x1D64F;</mi></math>=<span>1D64F</span></span>
- <span><math><mi>&#x1D650;</mi></math>=<span>1D650</span></span>
- <span><math><mi>&#x1D651;</mi></math>=<span>1D651</span></span>
- <span><math><mi>&#x1D652;</mi></math>=<span>1D652</span></span>
- <span><math><mi>&#x1D653;</mi></math>=<span>1D653</span></span>
- <span><math><mi>&#x1D654;</mi></math>=<span>1D654</span></span>
- <span><math><mi>&#x1D655;</mi></math>=<span>1D655</span></span>
- <span><math><mi>&#x1D656;</mi></math>=<span>1D656</span></span>
- <span><math><mi>&#x1D657;</mi></math>=<span>1D657</span></span><br/>
- <span><math><mi>&#x1D658;</mi></math>=<span>1D658</span></span>
- <span><math><mi>&#x1D659;</mi></math>=<span>1D659</span></span>
- <span><math><mi>&#x1D65A;</mi></math>=<span>1D65A</span></span>
- <span><math><mi>&#x1D65B;</mi></math>=<span>1D65B</span></span>
- <span><math><mi>&#x1D65C;</mi></math>=<span>1D65C</span></span>
- <span><math><mi>&#x1D65D;</mi></math>=<span>1D65D</span></span>
- <span><math><mi>&#x1D65E;</mi></math>=<span>1D65E</span></span>
- <span><math><mi>&#x1D65F;</mi></math>=<span>1D65F</span></span>
- <span><math><mi>&#x1D660;</mi></math>=<span>1D660</span></span>
- <span><math><mi>&#x1D661;</mi></math>=<span>1D661</span></span><br/>
- <span><math><mi>&#x1D662;</mi></math>=<span>1D662</span></span>
- <span><math><mi>&#x1D663;</mi></math>=<span>1D663</span></span>
- <span><math><mi>&#x1D664;</mi></math>=<span>1D664</span></span>
- <span><math><mi>&#x1D665;</mi></math>=<span>1D665</span></span>
- <span><math><mi>&#x1D666;</mi></math>=<span>1D666</span></span>
- <span><math><mi>&#x1D667;</mi></math>=<span>1D667</span></span>
- <span><math><mi>&#x1D668;</mi></math>=<span>1D668</span></span>
- <span><math><mi>&#x1D669;</mi></math>=<span>1D669</span></span>
- <span><math><mi>&#x1D66A;</mi></math>=<span>1D66A</span></span>
- <span><math><mi>&#x1D66B;</mi></math>=<span>1D66B</span></span><br/>
- <span><math><mi>&#x1D66C;</mi></math>=<span>1D66C</span></span>
- <span><math><mi>&#x1D66D;</mi></math>=<span>1D66D</span></span>
- <span><math><mi>&#x1D66E;</mi></math>=<span>1D66E</span></span>
- <span><math><mi>&#x1D66F;</mi></math>=<span>1D66F</span></span>
- <span><math><mi>&#x1D790;</mi></math>=<span>1D790</span></span>
- <span><math><mi>&#x1D791;</mi></math>=<span>1D791</span></span>
- <span><math><mi>&#x1D792;</mi></math>=<span>1D792</span></span>
- <span><math><mi>&#x1D793;</mi></math>=<span>1D793</span></span>
- <span><math><mi>&#x1D794;</mi></math>=<span>1D794</span></span>
- <span><math><mi>&#x1D795;</mi></math>=<span>1D795</span></span><br/>
- <span><math><mi>&#x1D796;</mi></math>=<span>1D796</span></span>
- <span><math><mi>&#x1D797;</mi></math>=<span>1D797</span></span>
- <span><math><mi>&#x1D798;</mi></math>=<span>1D798</span></span>
- <span><math><mi>&#x1D799;</mi></math>=<span>1D799</span></span>
- <span><math><mi>&#x1D79A;</mi></math>=<span>1D79A</span></span>
- <span><math><mi>&#x1D79B;</mi></math>=<span>1D79B</span></span>
- <span><math><mi>&#x1D79C;</mi></math>=<span>1D79C</span></span>
- <span><math><mi>&#x1D79D;</mi></math>=<span>1D79D</span></span>
- <span><math><mi>&#x1D79E;</mi></math>=<span>1D79E</span></span>
- <span><math><mi>&#x1D79F;</mi></math>=<span>1D79F</span></span><br/>
- <span><math><mi>&#x1D7A0;</mi></math>=<span>1D7A0</span></span>
- <span><math><mi>&#x1D7A2;</mi></math>=<span>1D7A2</span></span>
- <span><math><mi>&#x1D7A3;</mi></math>=<span>1D7A3</span></span>
- <span><math><mi>&#x1D7A4;</mi></math>=<span>1D7A4</span></span>
- <span><math><mi>&#x1D7A5;</mi></math>=<span>1D7A5</span></span>
- <span><math><mi>&#x1D7A6;</mi></math>=<span>1D7A6</span></span>
- <span><math><mi>&#x1D7A7;</mi></math>=<span>1D7A7</span></span>
- <span><math><mi>&#x1D7A8;</mi></math>=<span>1D7A8</span></span>
- <span><math><mi>&#x1D7AA;</mi></math>=<span>1D7AA</span></span>
- <span><math><mi>&#x1D7AB;</mi></math>=<span>1D7AB</span></span><br/>
- <span><math><mi>&#x1D7AC;</mi></math>=<span>1D7AC</span></span>
- <span><math><mi>&#x1D7AD;</mi></math>=<span>1D7AD</span></span>
- <span><math><mi>&#x1D7AE;</mi></math>=<span>1D7AE</span></span>
- <span><math><mi>&#x1D7AF;</mi></math>=<span>1D7AF</span></span>
- <span><math><mi>&#x1D7B0;</mi></math>=<span>1D7B0</span></span>
- <span><math><mi>&#x1D7B1;</mi></math>=<span>1D7B1</span></span>
- <span><math><mi>&#x1D7B2;</mi></math>=<span>1D7B2</span></span>
- <span><math><mi>&#x1D7B3;</mi></math>=<span>1D7B3</span></span>
- <span><math><mi>&#x1D7B4;</mi></math>=<span>1D7B4</span></span>
- <span><math><mi>&#x1D7B5;</mi></math>=<span>1D7B5</span></span><br/>
- <span><math><mi>&#x1D7B6;</mi></math>=<span>1D7B6</span></span>
- <span><math><mi>&#x1D7B7;</mi></math>=<span>1D7B7</span></span>
- <span><math><mi>&#x1D7B8;</mi></math>=<span>1D7B8</span></span>
- <span><math><mi>&#x1D7B9;</mi></math>=<span>1D7B9</span></span>
- <span><math><mi>&#x1D7BA;</mi></math>=<span>1D7BA</span></span>
- <span><math><mi>&#x1D7BB;</mi></math>=<span>1D7BB</span></span>
- <span><math><mi>&#x1D7BC;</mi></math>=<span>1D7BC</span></span>
- <span><math><mi>&#x1D7BD;</mi></math>=<span>1D7BD</span></span>
- <span><math><mi>&#x1D7BE;</mi></math>=<span>1D7BE</span></span>
- <span><math><mi>&#x1D7BF;</mi></math>=<span>1D7BF</span></span><br/>
- <span><math><mi>&#x1D7C0;</mi></math>=<span>1D7C0</span></span>
- <span><math><mi>&#x1D7C1;</mi></math>=<span>1D7C1</span></span>
- <span><math><mi>&#x1D7C2;</mi></math>=<span>1D7C2</span></span>
- <span><math><mi>&#x1D7C5;</mi></math>=<span>1D7C5</span></span>
- <span><math><mi>&#x1D7C7;</mi></math>=<span>1D7C7</span></span>
- <span><math><mi>&#x1D7C9;</mi></math>=<span>1D7C9</span></span>
- <span><math><mi>&#x1D7C6;</mi></math>=<span>1D7C6</span></span>
- <span><math><mi>&#x1D7C8;</mi></math>=<span>1D7C8</span></span>
- <span><math><mi>&#x1D7A1;</mi></math>=<span>1D7A1</span></span>
- <span><math><mi>&#x1D7C4;</mi></math>=<span>1D7C4</span></span><br/>
+ <span><math><mtext>&#x1D7C3;</mtext></math>=<span>1D7C3</span></span>
+ <span><math><mtext>&#x1D7A9;</mtext></math>=<span>1D7A9</span></span>
+ <span><math><mtext>&#x1D63C;</mtext></math>=<span>1D63C</span></span>
+ <span><math><mtext>&#x1D63D;</mtext></math>=<span>1D63D</span></span>
+ <span><math><mtext>&#x1D63E;</mtext></math>=<span>1D63E</span></span>
+ <span><math><mtext>&#x1D63F;</mtext></math>=<span>1D63F</span></span>
+ <span><math><mtext>&#x1D640;</mtext></math>=<span>1D640</span></span>
+ <span><math><mtext>&#x1D641;</mtext></math>=<span>1D641</span></span>
+ <span><math><mtext>&#x1D642;</mtext></math>=<span>1D642</span></span>
+ <span><math><mtext>&#x1D643;</mtext></math>=<span>1D643</span></span><br/>
+ <span><math><mtext>&#x1D644;</mtext></math>=<span>1D644</span></span>
+ <span><math><mtext>&#x1D645;</mtext></math>=<span>1D645</span></span>
+ <span><math><mtext>&#x1D646;</mtext></math>=<span>1D646</span></span>
+ <span><math><mtext>&#x1D647;</mtext></math>=<span>1D647</span></span>
+ <span><math><mtext>&#x1D648;</mtext></math>=<span>1D648</span></span>
+ <span><math><mtext>&#x1D649;</mtext></math>=<span>1D649</span></span>
+ <span><math><mtext>&#x1D64A;</mtext></math>=<span>1D64A</span></span>
+ <span><math><mtext>&#x1D64B;</mtext></math>=<span>1D64B</span></span>
+ <span><math><mtext>&#x1D64C;</mtext></math>=<span>1D64C</span></span>
+ <span><math><mtext>&#x1D64D;</mtext></math>=<span>1D64D</span></span><br/>
+ <span><math><mtext>&#x1D64E;</mtext></math>=<span>1D64E</span></span>
+ <span><math><mtext>&#x1D64F;</mtext></math>=<span>1D64F</span></span>
+ <span><math><mtext>&#x1D650;</mtext></math>=<span>1D650</span></span>
+ <span><math><mtext>&#x1D651;</mtext></math>=<span>1D651</span></span>
+ <span><math><mtext>&#x1D652;</mtext></math>=<span>1D652</span></span>
+ <span><math><mtext>&#x1D653;</mtext></math>=<span>1D653</span></span>
+ <span><math><mtext>&#x1D654;</mtext></math>=<span>1D654</span></span>
+ <span><math><mtext>&#x1D655;</mtext></math>=<span>1D655</span></span>
+ <span><math><mtext>&#x1D656;</mtext></math>=<span>1D656</span></span>
+ <span><math><mtext>&#x1D657;</mtext></math>=<span>1D657</span></span><br/>
+ <span><math><mtext>&#x1D658;</mtext></math>=<span>1D658</span></span>
+ <span><math><mtext>&#x1D659;</mtext></math>=<span>1D659</span></span>
+ <span><math><mtext>&#x1D65A;</mtext></math>=<span>1D65A</span></span>
+ <span><math><mtext>&#x1D65B;</mtext></math>=<span>1D65B</span></span>
+ <span><math><mtext>&#x1D65C;</mtext></math>=<span>1D65C</span></span>
+ <span><math><mtext>&#x1D65D;</mtext></math>=<span>1D65D</span></span>
+ <span><math><mtext>&#x1D65E;</mtext></math>=<span>1D65E</span></span>
+ <span><math><mtext>&#x1D65F;</mtext></math>=<span>1D65F</span></span>
+ <span><math><mtext>&#x1D660;</mtext></math>=<span>1D660</span></span>
+ <span><math><mtext>&#x1D661;</mtext></math>=<span>1D661</span></span><br/>
+ <span><math><mtext>&#x1D662;</mtext></math>=<span>1D662</span></span>
+ <span><math><mtext>&#x1D663;</mtext></math>=<span>1D663</span></span>
+ <span><math><mtext>&#x1D664;</mtext></math>=<span>1D664</span></span>
+ <span><math><mtext>&#x1D665;</mtext></math>=<span>1D665</span></span>
+ <span><math><mtext>&#x1D666;</mtext></math>=<span>1D666</span></span>
+ <span><math><mtext>&#x1D667;</mtext></math>=<span>1D667</span></span>
+ <span><math><mtext>&#x1D668;</mtext></math>=<span>1D668</span></span>
+ <span><math><mtext>&#x1D669;</mtext></math>=<span>1D669</span></span>
+ <span><math><mtext>&#x1D66A;</mtext></math>=<span>1D66A</span></span>
+ <span><math><mtext>&#x1D66B;</mtext></math>=<span>1D66B</span></span><br/>
+ <span><math><mtext>&#x1D66C;</mtext></math>=<span>1D66C</span></span>
+ <span><math><mtext>&#x1D66D;</mtext></math>=<span>1D66D</span></span>
+ <span><math><mtext>&#x1D66E;</mtext></math>=<span>1D66E</span></span>
+ <span><math><mtext>&#x1D66F;</mtext></math>=<span>1D66F</span></span>
+ <span><math><mtext>&#x1D790;</mtext></math>=<span>1D790</span></span>
+ <span><math><mtext>&#x1D791;</mtext></math>=<span>1D791</span></span>
+ <span><math><mtext>&#x1D792;</mtext></math>=<span>1D792</span></span>
+ <span><math><mtext>&#x1D793;</mtext></math>=<span>1D793</span></span>
+ <span><math><mtext>&#x1D794;</mtext></math>=<span>1D794</span></span>
+ <span><math><mtext>&#x1D795;</mtext></math>=<span>1D795</span></span><br/>
+ <span><math><mtext>&#x1D796;</mtext></math>=<span>1D796</span></span>
+ <span><math><mtext>&#x1D797;</mtext></math>=<span>1D797</span></span>
+ <span><math><mtext>&#x1D798;</mtext></math>=<span>1D798</span></span>
+ <span><math><mtext>&#x1D799;</mtext></math>=<span>1D799</span></span>
+ <span><math><mtext>&#x1D79A;</mtext></math>=<span>1D79A</span></span>
+ <span><math><mtext>&#x1D79B;</mtext></math>=<span>1D79B</span></span>
+ <span><math><mtext>&#x1D79C;</mtext></math>=<span>1D79C</span></span>
+ <span><math><mtext>&#x1D79D;</mtext></math>=<span>1D79D</span></span>
+ <span><math><mtext>&#x1D79E;</mtext></math>=<span>1D79E</span></span>
+ <span><math><mtext>&#x1D79F;</mtext></math>=<span>1D79F</span></span><br/>
+ <span><math><mtext>&#x1D7A0;</mtext></math>=<span>1D7A0</span></span>
+ <span><math><mtext>&#x1D7A2;</mtext></math>=<span>1D7A2</span></span>
+ <span><math><mtext>&#x1D7A3;</mtext></math>=<span>1D7A3</span></span>
+ <span><math><mtext>&#x1D7A4;</mtext></math>=<span>1D7A4</span></span>
+ <span><math><mtext>&#x1D7A5;</mtext></math>=<span>1D7A5</span></span>
+ <span><math><mtext>&#x1D7A6;</mtext></math>=<span>1D7A6</span></span>
+ <span><math><mtext>&#x1D7A7;</mtext></math>=<span>1D7A7</span></span>
+ <span><math><mtext>&#x1D7A8;</mtext></math>=<span>1D7A8</span></span>
+ <span><math><mtext>&#x1D7AA;</mtext></math>=<span>1D7AA</span></span>
+ <span><math><mtext>&#x1D7AB;</mtext></math>=<span>1D7AB</span></span><br/>
+ <span><math><mtext>&#x1D7AC;</mtext></math>=<span>1D7AC</span></span>
+ <span><math><mtext>&#x1D7AD;</mtext></math>=<span>1D7AD</span></span>
+ <span><math><mtext>&#x1D7AE;</mtext></math>=<span>1D7AE</span></span>
+ <span><math><mtext>&#x1D7AF;</mtext></math>=<span>1D7AF</span></span>
+ <span><math><mtext>&#x1D7B0;</mtext></math>=<span>1D7B0</span></span>
+ <span><math><mtext>&#x1D7B1;</mtext></math>=<span>1D7B1</span></span>
+ <span><math><mtext>&#x1D7B2;</mtext></math>=<span>1D7B2</span></span>
+ <span><math><mtext>&#x1D7B3;</mtext></math>=<span>1D7B3</span></span>
+ <span><math><mtext>&#x1D7B4;</mtext></math>=<span>1D7B4</span></span>
+ <span><math><mtext>&#x1D7B5;</mtext></math>=<span>1D7B5</span></span><br/>
+ <span><math><mtext>&#x1D7B6;</mtext></math>=<span>1D7B6</span></span>
+ <span><math><mtext>&#x1D7B7;</mtext></math>=<span>1D7B7</span></span>
+ <span><math><mtext>&#x1D7B8;</mtext></math>=<span>1D7B8</span></span>
+ <span><math><mtext>&#x1D7B9;</mtext></math>=<span>1D7B9</span></span>
+ <span><math><mtext>&#x1D7BA;</mtext></math>=<span>1D7BA</span></span>
+ <span><math><mtext>&#x1D7BB;</mtext></math>=<span>1D7BB</span></span>
+ <span><math><mtext>&#x1D7BC;</mtext></math>=<span>1D7BC</span></span>
+ <span><math><mtext>&#x1D7BD;</mtext></math>=<span>1D7BD</span></span>
+ <span><math><mtext>&#x1D7BE;</mtext></math>=<span>1D7BE</span></span>
+ <span><math><mtext>&#x1D7BF;</mtext></math>=<span>1D7BF</span></span><br/>
+ <span><math><mtext>&#x1D7C0;</mtext></math>=<span>1D7C0</span></span>
+ <span><math><mtext>&#x1D7C1;</mtext></math>=<span>1D7C1</span></span>
+ <span><math><mtext>&#x1D7C2;</mtext></math>=<span>1D7C2</span></span>
+ <span><math><mtext>&#x1D7C5;</mtext></math>=<span>1D7C5</span></span>
+ <span><math><mtext>&#x1D7C7;</mtext></math>=<span>1D7C7</span></span>
+ <span><math><mtext>&#x1D7C9;</mtext></math>=<span>1D7C9</span></span>
+ <span><math><mtext>&#x1D7C6;</mtext></math>=<span>1D7C6</span></span>
+ <span><math><mtext>&#x1D7C8;</mtext></math>=<span>1D7C8</span></span>
+ <span><math><mtext>&#x1D7A1;</mtext></math>=<span>1D7A1</span></span>
+ <span><math><mtext>&#x1D7C4;</mtext></math>=<span>1D7C4</span></span><br/>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif-bold-italic.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif-bold-italic.html
index c7990a9a180..70207367e05 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif-bold-italic.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif-bold-italic.html
@@ -5,7 +5,7 @@
<title>mathvariant sans-serif-bold-italic</title>
<link rel="help" href="http://www.mathml-association.org/MathMLinHTML5/S2.html#SS3.SSS1.tab2"/>
<link rel="match" href="mathvariant-sans-serif-bold-italic-ref.html"/>
-<meta name="assert" content="Verify that a single-char <mi> with a sans-serif-bold-italic mathvariant is equivalent to an <mi> with the transformed unicode character.">
+<meta name="assert" content="Verify that a single-char <mtext> with a sans-serif-bold-italic mathvariant is equivalent to an <mtext> with the transformed unicode character.">
<style>
@font-face {
font-family: TestFont;
@@ -26,115 +26,115 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x2202;</mi></math>=<span>1D7C3</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x2207;</mi></math>=<span>1D7A9</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x41;</mi></math>=<span>1D63C</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x42;</mi></math>=<span>1D63D</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x43;</mi></math>=<span>1D63E</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x44;</mi></math>=<span>1D63F</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x45;</mi></math>=<span>1D640</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x46;</mi></math>=<span>1D641</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x47;</mi></math>=<span>1D642</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x48;</mi></math>=<span>1D643</span></span><br/>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x49;</mi></math>=<span>1D644</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x4A;</mi></math>=<span>1D645</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x4B;</mi></math>=<span>1D646</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x4C;</mi></math>=<span>1D647</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x4D;</mi></math>=<span>1D648</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x4E;</mi></math>=<span>1D649</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x4F;</mi></math>=<span>1D64A</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x50;</mi></math>=<span>1D64B</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x51;</mi></math>=<span>1D64C</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x52;</mi></math>=<span>1D64D</span></span><br/>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x53;</mi></math>=<span>1D64E</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x54;</mi></math>=<span>1D64F</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x55;</mi></math>=<span>1D650</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x56;</mi></math>=<span>1D651</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x57;</mi></math>=<span>1D652</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x58;</mi></math>=<span>1D653</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x59;</mi></math>=<span>1D654</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x5A;</mi></math>=<span>1D655</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x61;</mi></math>=<span>1D656</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x62;</mi></math>=<span>1D657</span></span><br/>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x63;</mi></math>=<span>1D658</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x64;</mi></math>=<span>1D659</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x65;</mi></math>=<span>1D65A</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x66;</mi></math>=<span>1D65B</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x67;</mi></math>=<span>1D65C</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x68;</mi></math>=<span>1D65D</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x69;</mi></math>=<span>1D65E</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x6A;</mi></math>=<span>1D65F</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x6B;</mi></math>=<span>1D660</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x6C;</mi></math>=<span>1D661</span></span><br/>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x6D;</mi></math>=<span>1D662</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x6E;</mi></math>=<span>1D663</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x6F;</mi></math>=<span>1D664</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x70;</mi></math>=<span>1D665</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x71;</mi></math>=<span>1D666</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x72;</mi></math>=<span>1D667</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x73;</mi></math>=<span>1D668</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x74;</mi></math>=<span>1D669</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x75;</mi></math>=<span>1D66A</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x76;</mi></math>=<span>1D66B</span></span><br/>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x77;</mi></math>=<span>1D66C</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x78;</mi></math>=<span>1D66D</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x79;</mi></math>=<span>1D66E</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x7A;</mi></math>=<span>1D66F</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x391;</mi></math>=<span>1D790</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x392;</mi></math>=<span>1D791</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x393;</mi></math>=<span>1D792</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x394;</mi></math>=<span>1D793</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x395;</mi></math>=<span>1D794</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x396;</mi></math>=<span>1D795</span></span><br/>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x397;</mi></math>=<span>1D796</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x398;</mi></math>=<span>1D797</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x399;</mi></math>=<span>1D798</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x39A;</mi></math>=<span>1D799</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x39B;</mi></math>=<span>1D79A</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x39C;</mi></math>=<span>1D79B</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x39D;</mi></math>=<span>1D79C</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x39E;</mi></math>=<span>1D79D</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x39F;</mi></math>=<span>1D79E</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3A0;</mi></math>=<span>1D79F</span></span><br/>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3A1;</mi></math>=<span>1D7A0</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3A3;</mi></math>=<span>1D7A2</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3A4;</mi></math>=<span>1D7A3</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3A5;</mi></math>=<span>1D7A4</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3A6;</mi></math>=<span>1D7A5</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3A7;</mi></math>=<span>1D7A6</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3A8;</mi></math>=<span>1D7A7</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3A9;</mi></math>=<span>1D7A8</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3B1;</mi></math>=<span>1D7AA</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3B2;</mi></math>=<span>1D7AB</span></span><br/>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3B3;</mi></math>=<span>1D7AC</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3B4;</mi></math>=<span>1D7AD</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3B5;</mi></math>=<span>1D7AE</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3B6;</mi></math>=<span>1D7AF</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3B7;</mi></math>=<span>1D7B0</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3B8;</mi></math>=<span>1D7B1</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3B9;</mi></math>=<span>1D7B2</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3BA;</mi></math>=<span>1D7B3</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3BB;</mi></math>=<span>1D7B4</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3BC;</mi></math>=<span>1D7B5</span></span><br/>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3BD;</mi></math>=<span>1D7B6</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3BE;</mi></math>=<span>1D7B7</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3BF;</mi></math>=<span>1D7B8</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3C0;</mi></math>=<span>1D7B9</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3C1;</mi></math>=<span>1D7BA</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3C2;</mi></math>=<span>1D7BB</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3C3;</mi></math>=<span>1D7BC</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3C4;</mi></math>=<span>1D7BD</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3C5;</mi></math>=<span>1D7BE</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3C6;</mi></math>=<span>1D7BF</span></span><br/>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3C7;</mi></math>=<span>1D7C0</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3C8;</mi></math>=<span>1D7C1</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3C9;</mi></math>=<span>1D7C2</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3D1;</mi></math>=<span>1D7C5</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3D5;</mi></math>=<span>1D7C7</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3D6;</mi></math>=<span>1D7C9</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3F0;</mi></math>=<span>1D7C6</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3F1;</mi></math>=<span>1D7C8</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3F4;</mi></math>=<span>1D7A1</span></span>
- <span><math><mi mathvariant="sans-serif-bold-italic">&#x3F5;</mi></math>=<span>1D7C4</span></span><br/>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x2202;</mtext></math>=<span>1D7C3</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x2207;</mtext></math>=<span>1D7A9</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x41;</mtext></math>=<span>1D63C</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x42;</mtext></math>=<span>1D63D</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x43;</mtext></math>=<span>1D63E</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x44;</mtext></math>=<span>1D63F</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x45;</mtext></math>=<span>1D640</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x46;</mtext></math>=<span>1D641</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x47;</mtext></math>=<span>1D642</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x48;</mtext></math>=<span>1D643</span></span><br/>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x49;</mtext></math>=<span>1D644</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x4A;</mtext></math>=<span>1D645</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x4B;</mtext></math>=<span>1D646</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x4C;</mtext></math>=<span>1D647</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x4D;</mtext></math>=<span>1D648</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x4E;</mtext></math>=<span>1D649</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x4F;</mtext></math>=<span>1D64A</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x50;</mtext></math>=<span>1D64B</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x51;</mtext></math>=<span>1D64C</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x52;</mtext></math>=<span>1D64D</span></span><br/>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x53;</mtext></math>=<span>1D64E</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x54;</mtext></math>=<span>1D64F</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x55;</mtext></math>=<span>1D650</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x56;</mtext></math>=<span>1D651</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x57;</mtext></math>=<span>1D652</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x58;</mtext></math>=<span>1D653</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x59;</mtext></math>=<span>1D654</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x5A;</mtext></math>=<span>1D655</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x61;</mtext></math>=<span>1D656</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x62;</mtext></math>=<span>1D657</span></span><br/>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x63;</mtext></math>=<span>1D658</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x64;</mtext></math>=<span>1D659</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x65;</mtext></math>=<span>1D65A</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x66;</mtext></math>=<span>1D65B</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x67;</mtext></math>=<span>1D65C</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x68;</mtext></math>=<span>1D65D</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x69;</mtext></math>=<span>1D65E</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x6A;</mtext></math>=<span>1D65F</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x6B;</mtext></math>=<span>1D660</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x6C;</mtext></math>=<span>1D661</span></span><br/>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x6D;</mtext></math>=<span>1D662</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x6E;</mtext></math>=<span>1D663</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x6F;</mtext></math>=<span>1D664</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x70;</mtext></math>=<span>1D665</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x71;</mtext></math>=<span>1D666</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x72;</mtext></math>=<span>1D667</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x73;</mtext></math>=<span>1D668</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x74;</mtext></math>=<span>1D669</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x75;</mtext></math>=<span>1D66A</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x76;</mtext></math>=<span>1D66B</span></span><br/>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x77;</mtext></math>=<span>1D66C</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x78;</mtext></math>=<span>1D66D</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x79;</mtext></math>=<span>1D66E</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x7A;</mtext></math>=<span>1D66F</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x391;</mtext></math>=<span>1D790</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x392;</mtext></math>=<span>1D791</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x393;</mtext></math>=<span>1D792</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x394;</mtext></math>=<span>1D793</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x395;</mtext></math>=<span>1D794</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x396;</mtext></math>=<span>1D795</span></span><br/>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x397;</mtext></math>=<span>1D796</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x398;</mtext></math>=<span>1D797</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x399;</mtext></math>=<span>1D798</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x39A;</mtext></math>=<span>1D799</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x39B;</mtext></math>=<span>1D79A</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x39C;</mtext></math>=<span>1D79B</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x39D;</mtext></math>=<span>1D79C</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x39E;</mtext></math>=<span>1D79D</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x39F;</mtext></math>=<span>1D79E</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3A0;</mtext></math>=<span>1D79F</span></span><br/>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3A1;</mtext></math>=<span>1D7A0</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3A3;</mtext></math>=<span>1D7A2</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3A4;</mtext></math>=<span>1D7A3</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3A5;</mtext></math>=<span>1D7A4</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3A6;</mtext></math>=<span>1D7A5</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3A7;</mtext></math>=<span>1D7A6</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3A8;</mtext></math>=<span>1D7A7</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3A9;</mtext></math>=<span>1D7A8</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3B1;</mtext></math>=<span>1D7AA</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3B2;</mtext></math>=<span>1D7AB</span></span><br/>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3B3;</mtext></math>=<span>1D7AC</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3B4;</mtext></math>=<span>1D7AD</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3B5;</mtext></math>=<span>1D7AE</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3B6;</mtext></math>=<span>1D7AF</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3B7;</mtext></math>=<span>1D7B0</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3B8;</mtext></math>=<span>1D7B1</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3B9;</mtext></math>=<span>1D7B2</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3BA;</mtext></math>=<span>1D7B3</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3BB;</mtext></math>=<span>1D7B4</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3BC;</mtext></math>=<span>1D7B5</span></span><br/>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3BD;</mtext></math>=<span>1D7B6</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3BE;</mtext></math>=<span>1D7B7</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3BF;</mtext></math>=<span>1D7B8</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3C0;</mtext></math>=<span>1D7B9</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3C1;</mtext></math>=<span>1D7BA</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3C2;</mtext></math>=<span>1D7BB</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3C3;</mtext></math>=<span>1D7BC</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3C4;</mtext></math>=<span>1D7BD</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3C5;</mtext></math>=<span>1D7BE</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3C6;</mtext></math>=<span>1D7BF</span></span><br/>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3C7;</mtext></math>=<span>1D7C0</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3C8;</mtext></math>=<span>1D7C1</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3C9;</mtext></math>=<span>1D7C2</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3D1;</mtext></math>=<span>1D7C5</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3D5;</mtext></math>=<span>1D7C7</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3D6;</mtext></math>=<span>1D7C9</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3F0;</mtext></math>=<span>1D7C6</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3F1;</mtext></math>=<span>1D7C8</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3F4;</mtext></math>=<span>1D7A1</span></span>
+ <span><math><mtext mathvariant="sans-serif-bold-italic">&#x3F5;</mtext></math>=<span>1D7C4</span></span><br/>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif-italic-ref.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif-italic-ref.html
index eab1776fe4a..b82cde87e29 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif-italic-ref.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif-italic-ref.html
@@ -23,57 +23,57 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi>&#x1D608;</mi></math>=<span>1D608</span></span>
- <span><math><mi>&#x1D609;</mi></math>=<span>1D609</span></span>
- <span><math><mi>&#x1D60A;</mi></math>=<span>1D60A</span></span>
- <span><math><mi>&#x1D60B;</mi></math>=<span>1D60B</span></span>
- <span><math><mi>&#x1D60C;</mi></math>=<span>1D60C</span></span>
- <span><math><mi>&#x1D60D;</mi></math>=<span>1D60D</span></span>
- <span><math><mi>&#x1D60E;</mi></math>=<span>1D60E</span></span>
- <span><math><mi>&#x1D60F;</mi></math>=<span>1D60F</span></span>
- <span><math><mi>&#x1D610;</mi></math>=<span>1D610</span></span>
- <span><math><mi>&#x1D611;</mi></math>=<span>1D611</span></span><br/>
- <span><math><mi>&#x1D612;</mi></math>=<span>1D612</span></span>
- <span><math><mi>&#x1D613;</mi></math>=<span>1D613</span></span>
- <span><math><mi>&#x1D614;</mi></math>=<span>1D614</span></span>
- <span><math><mi>&#x1D615;</mi></math>=<span>1D615</span></span>
- <span><math><mi>&#x1D616;</mi></math>=<span>1D616</span></span>
- <span><math><mi>&#x1D617;</mi></math>=<span>1D617</span></span>
- <span><math><mi>&#x1D618;</mi></math>=<span>1D618</span></span>
- <span><math><mi>&#x1D619;</mi></math>=<span>1D619</span></span>
- <span><math><mi>&#x1D61A;</mi></math>=<span>1D61A</span></span>
- <span><math><mi>&#x1D61B;</mi></math>=<span>1D61B</span></span><br/>
- <span><math><mi>&#x1D61C;</mi></math>=<span>1D61C</span></span>
- <span><math><mi>&#x1D61D;</mi></math>=<span>1D61D</span></span>
- <span><math><mi>&#x1D61E;</mi></math>=<span>1D61E</span></span>
- <span><math><mi>&#x1D61F;</mi></math>=<span>1D61F</span></span>
- <span><math><mi>&#x1D620;</mi></math>=<span>1D620</span></span>
- <span><math><mi>&#x1D621;</mi></math>=<span>1D621</span></span>
- <span><math><mi>&#x1D622;</mi></math>=<span>1D622</span></span>
- <span><math><mi>&#x1D623;</mi></math>=<span>1D623</span></span>
- <span><math><mi>&#x1D624;</mi></math>=<span>1D624</span></span>
- <span><math><mi>&#x1D625;</mi></math>=<span>1D625</span></span><br/>
- <span><math><mi>&#x1D626;</mi></math>=<span>1D626</span></span>
- <span><math><mi>&#x1D627;</mi></math>=<span>1D627</span></span>
- <span><math><mi>&#x1D628;</mi></math>=<span>1D628</span></span>
- <span><math><mi>&#x1D629;</mi></math>=<span>1D629</span></span>
- <span><math><mi>&#x1D62A;</mi></math>=<span>1D62A</span></span>
- <span><math><mi>&#x1D62B;</mi></math>=<span>1D62B</span></span>
- <span><math><mi>&#x1D62C;</mi></math>=<span>1D62C</span></span>
- <span><math><mi>&#x1D62D;</mi></math>=<span>1D62D</span></span>
- <span><math><mi>&#x1D62E;</mi></math>=<span>1D62E</span></span>
- <span><math><mi>&#x1D62F;</mi></math>=<span>1D62F</span></span><br/>
- <span><math><mi>&#x1D630;</mi></math>=<span>1D630</span></span>
- <span><math><mi>&#x1D631;</mi></math>=<span>1D631</span></span>
- <span><math><mi>&#x1D632;</mi></math>=<span>1D632</span></span>
- <span><math><mi>&#x1D633;</mi></math>=<span>1D633</span></span>
- <span><math><mi>&#x1D634;</mi></math>=<span>1D634</span></span>
- <span><math><mi>&#x1D635;</mi></math>=<span>1D635</span></span>
- <span><math><mi>&#x1D636;</mi></math>=<span>1D636</span></span>
- <span><math><mi>&#x1D637;</mi></math>=<span>1D637</span></span>
- <span><math><mi>&#x1D638;</mi></math>=<span>1D638</span></span>
- <span><math><mi>&#x1D639;</mi></math>=<span>1D639</span></span><br/>
- <span><math><mi>&#x1D63A;</mi></math>=<span>1D63A</span></span>
- <span><math><mi>&#x1D63B;</mi></math>=<span>1D63B</span></span>
+ <span><math><mtext>&#x1D608;</mtext></math>=<span>1D608</span></span>
+ <span><math><mtext>&#x1D609;</mtext></math>=<span>1D609</span></span>
+ <span><math><mtext>&#x1D60A;</mtext></math>=<span>1D60A</span></span>
+ <span><math><mtext>&#x1D60B;</mtext></math>=<span>1D60B</span></span>
+ <span><math><mtext>&#x1D60C;</mtext></math>=<span>1D60C</span></span>
+ <span><math><mtext>&#x1D60D;</mtext></math>=<span>1D60D</span></span>
+ <span><math><mtext>&#x1D60E;</mtext></math>=<span>1D60E</span></span>
+ <span><math><mtext>&#x1D60F;</mtext></math>=<span>1D60F</span></span>
+ <span><math><mtext>&#x1D610;</mtext></math>=<span>1D610</span></span>
+ <span><math><mtext>&#x1D611;</mtext></math>=<span>1D611</span></span><br/>
+ <span><math><mtext>&#x1D612;</mtext></math>=<span>1D612</span></span>
+ <span><math><mtext>&#x1D613;</mtext></math>=<span>1D613</span></span>
+ <span><math><mtext>&#x1D614;</mtext></math>=<span>1D614</span></span>
+ <span><math><mtext>&#x1D615;</mtext></math>=<span>1D615</span></span>
+ <span><math><mtext>&#x1D616;</mtext></math>=<span>1D616</span></span>
+ <span><math><mtext>&#x1D617;</mtext></math>=<span>1D617</span></span>
+ <span><math><mtext>&#x1D618;</mtext></math>=<span>1D618</span></span>
+ <span><math><mtext>&#x1D619;</mtext></math>=<span>1D619</span></span>
+ <span><math><mtext>&#x1D61A;</mtext></math>=<span>1D61A</span></span>
+ <span><math><mtext>&#x1D61B;</mtext></math>=<span>1D61B</span></span><br/>
+ <span><math><mtext>&#x1D61C;</mtext></math>=<span>1D61C</span></span>
+ <span><math><mtext>&#x1D61D;</mtext></math>=<span>1D61D</span></span>
+ <span><math><mtext>&#x1D61E;</mtext></math>=<span>1D61E</span></span>
+ <span><math><mtext>&#x1D61F;</mtext></math>=<span>1D61F</span></span>
+ <span><math><mtext>&#x1D620;</mtext></math>=<span>1D620</span></span>
+ <span><math><mtext>&#x1D621;</mtext></math>=<span>1D621</span></span>
+ <span><math><mtext>&#x1D622;</mtext></math>=<span>1D622</span></span>
+ <span><math><mtext>&#x1D623;</mtext></math>=<span>1D623</span></span>
+ <span><math><mtext>&#x1D624;</mtext></math>=<span>1D624</span></span>
+ <span><math><mtext>&#x1D625;</mtext></math>=<span>1D625</span></span><br/>
+ <span><math><mtext>&#x1D626;</mtext></math>=<span>1D626</span></span>
+ <span><math><mtext>&#x1D627;</mtext></math>=<span>1D627</span></span>
+ <span><math><mtext>&#x1D628;</mtext></math>=<span>1D628</span></span>
+ <span><math><mtext>&#x1D629;</mtext></math>=<span>1D629</span></span>
+ <span><math><mtext>&#x1D62A;</mtext></math>=<span>1D62A</span></span>
+ <span><math><mtext>&#x1D62B;</mtext></math>=<span>1D62B</span></span>
+ <span><math><mtext>&#x1D62C;</mtext></math>=<span>1D62C</span></span>
+ <span><math><mtext>&#x1D62D;</mtext></math>=<span>1D62D</span></span>
+ <span><math><mtext>&#x1D62E;</mtext></math>=<span>1D62E</span></span>
+ <span><math><mtext>&#x1D62F;</mtext></math>=<span>1D62F</span></span><br/>
+ <span><math><mtext>&#x1D630;</mtext></math>=<span>1D630</span></span>
+ <span><math><mtext>&#x1D631;</mtext></math>=<span>1D631</span></span>
+ <span><math><mtext>&#x1D632;</mtext></math>=<span>1D632</span></span>
+ <span><math><mtext>&#x1D633;</mtext></math>=<span>1D633</span></span>
+ <span><math><mtext>&#x1D634;</mtext></math>=<span>1D634</span></span>
+ <span><math><mtext>&#x1D635;</mtext></math>=<span>1D635</span></span>
+ <span><math><mtext>&#x1D636;</mtext></math>=<span>1D636</span></span>
+ <span><math><mtext>&#x1D637;</mtext></math>=<span>1D637</span></span>
+ <span><math><mtext>&#x1D638;</mtext></math>=<span>1D638</span></span>
+ <span><math><mtext>&#x1D639;</mtext></math>=<span>1D639</span></span><br/>
+ <span><math><mtext>&#x1D63A;</mtext></math>=<span>1D63A</span></span>
+ <span><math><mtext>&#x1D63B;</mtext></math>=<span>1D63B</span></span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif-italic.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif-italic.html
index 293d14bbc0a..0576236dbf9 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif-italic.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif-italic.html
@@ -5,7 +5,7 @@
<title>mathvariant sans-serif-italic</title>
<link rel="help" href="http://www.mathml-association.org/MathMLinHTML5/S2.html#SS3.SSS1.tab2"/>
<link rel="match" href="mathvariant-sans-serif-italic-ref.html"/>
-<meta name="assert" content="Verify that a single-char <mi> with a sans-serif-italic mathvariant is equivalent to an <mi> with the transformed unicode character.">
+<meta name="assert" content="Verify that a single-char <mtext> with a sans-serif-italic mathvariant is equivalent to an <mtext> with the transformed unicode character.">
<style>
@font-face {
font-family: TestFont;
@@ -26,57 +26,57 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi mathvariant="sans-serif-italic">&#x41;</mi></math>=<span>1D608</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x42;</mi></math>=<span>1D609</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x43;</mi></math>=<span>1D60A</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x44;</mi></math>=<span>1D60B</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x45;</mi></math>=<span>1D60C</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x46;</mi></math>=<span>1D60D</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x47;</mi></math>=<span>1D60E</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x48;</mi></math>=<span>1D60F</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x49;</mi></math>=<span>1D610</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x4A;</mi></math>=<span>1D611</span></span><br/>
- <span><math><mi mathvariant="sans-serif-italic">&#x4B;</mi></math>=<span>1D612</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x4C;</mi></math>=<span>1D613</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x4D;</mi></math>=<span>1D614</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x4E;</mi></math>=<span>1D615</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x4F;</mi></math>=<span>1D616</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x50;</mi></math>=<span>1D617</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x51;</mi></math>=<span>1D618</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x52;</mi></math>=<span>1D619</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x53;</mi></math>=<span>1D61A</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x54;</mi></math>=<span>1D61B</span></span><br/>
- <span><math><mi mathvariant="sans-serif-italic">&#x55;</mi></math>=<span>1D61C</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x56;</mi></math>=<span>1D61D</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x57;</mi></math>=<span>1D61E</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x58;</mi></math>=<span>1D61F</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x59;</mi></math>=<span>1D620</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x5A;</mi></math>=<span>1D621</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x61;</mi></math>=<span>1D622</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x62;</mi></math>=<span>1D623</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x63;</mi></math>=<span>1D624</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x64;</mi></math>=<span>1D625</span></span><br/>
- <span><math><mi mathvariant="sans-serif-italic">&#x65;</mi></math>=<span>1D626</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x66;</mi></math>=<span>1D627</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x67;</mi></math>=<span>1D628</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x68;</mi></math>=<span>1D629</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x69;</mi></math>=<span>1D62A</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x6A;</mi></math>=<span>1D62B</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x6B;</mi></math>=<span>1D62C</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x6C;</mi></math>=<span>1D62D</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x6D;</mi></math>=<span>1D62E</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x6E;</mi></math>=<span>1D62F</span></span><br/>
- <span><math><mi mathvariant="sans-serif-italic">&#x6F;</mi></math>=<span>1D630</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x70;</mi></math>=<span>1D631</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x71;</mi></math>=<span>1D632</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x72;</mi></math>=<span>1D633</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x73;</mi></math>=<span>1D634</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x74;</mi></math>=<span>1D635</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x75;</mi></math>=<span>1D636</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x76;</mi></math>=<span>1D637</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x77;</mi></math>=<span>1D638</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x78;</mi></math>=<span>1D639</span></span><br/>
- <span><math><mi mathvariant="sans-serif-italic">&#x79;</mi></math>=<span>1D63A</span></span>
- <span><math><mi mathvariant="sans-serif-italic">&#x7A;</mi></math>=<span>1D63B</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x41;</mtext></math>=<span>1D608</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x42;</mtext></math>=<span>1D609</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x43;</mtext></math>=<span>1D60A</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x44;</mtext></math>=<span>1D60B</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x45;</mtext></math>=<span>1D60C</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x46;</mtext></math>=<span>1D60D</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x47;</mtext></math>=<span>1D60E</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x48;</mtext></math>=<span>1D60F</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x49;</mtext></math>=<span>1D610</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x4A;</mtext></math>=<span>1D611</span></span><br/>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x4B;</mtext></math>=<span>1D612</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x4C;</mtext></math>=<span>1D613</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x4D;</mtext></math>=<span>1D614</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x4E;</mtext></math>=<span>1D615</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x4F;</mtext></math>=<span>1D616</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x50;</mtext></math>=<span>1D617</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x51;</mtext></math>=<span>1D618</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x52;</mtext></math>=<span>1D619</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x53;</mtext></math>=<span>1D61A</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x54;</mtext></math>=<span>1D61B</span></span><br/>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x55;</mtext></math>=<span>1D61C</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x56;</mtext></math>=<span>1D61D</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x57;</mtext></math>=<span>1D61E</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x58;</mtext></math>=<span>1D61F</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x59;</mtext></math>=<span>1D620</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x5A;</mtext></math>=<span>1D621</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x61;</mtext></math>=<span>1D622</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x62;</mtext></math>=<span>1D623</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x63;</mtext></math>=<span>1D624</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x64;</mtext></math>=<span>1D625</span></span><br/>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x65;</mtext></math>=<span>1D626</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x66;</mtext></math>=<span>1D627</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x67;</mtext></math>=<span>1D628</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x68;</mtext></math>=<span>1D629</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x69;</mtext></math>=<span>1D62A</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x6A;</mtext></math>=<span>1D62B</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x6B;</mtext></math>=<span>1D62C</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x6C;</mtext></math>=<span>1D62D</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x6D;</mtext></math>=<span>1D62E</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x6E;</mtext></math>=<span>1D62F</span></span><br/>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x6F;</mtext></math>=<span>1D630</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x70;</mtext></math>=<span>1D631</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x71;</mtext></math>=<span>1D632</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x72;</mtext></math>=<span>1D633</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x73;</mtext></math>=<span>1D634</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x74;</mtext></math>=<span>1D635</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x75;</mtext></math>=<span>1D636</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x76;</mtext></math>=<span>1D637</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x77;</mtext></math>=<span>1D638</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x78;</mtext></math>=<span>1D639</span></span><br/>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x79;</mtext></math>=<span>1D63A</span></span>
+ <span><math><mtext mathvariant="sans-serif-italic">&#x7A;</mtext></math>=<span>1D63B</span></span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif-ref.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif-ref.html
index b6bb6f87c35..35e4b6567d2 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif-ref.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif-ref.html
@@ -23,67 +23,67 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi>&#x1D7E2;</mi></math>=<span>1D7E2</span></span>
- <span><math><mi>&#x1D7E3;</mi></math>=<span>1D7E3</span></span>
- <span><math><mi>&#x1D7E4;</mi></math>=<span>1D7E4</span></span>
- <span><math><mi>&#x1D7E5;</mi></math>=<span>1D7E5</span></span>
- <span><math><mi>&#x1D7E6;</mi></math>=<span>1D7E6</span></span>
- <span><math><mi>&#x1D7E7;</mi></math>=<span>1D7E7</span></span>
- <span><math><mi>&#x1D7E8;</mi></math>=<span>1D7E8</span></span>
- <span><math><mi>&#x1D7E9;</mi></math>=<span>1D7E9</span></span>
- <span><math><mi>&#x1D7EA;</mi></math>=<span>1D7EA</span></span>
- <span><math><mi>&#x1D7EB;</mi></math>=<span>1D7EB</span></span><br/>
- <span><math><mi>&#x1D5A0;</mi></math>=<span>1D5A0</span></span>
- <span><math><mi>&#x1D5A1;</mi></math>=<span>1D5A1</span></span>
- <span><math><mi>&#x1D5A2;</mi></math>=<span>1D5A2</span></span>
- <span><math><mi>&#x1D5A3;</mi></math>=<span>1D5A3</span></span>
- <span><math><mi>&#x1D5A4;</mi></math>=<span>1D5A4</span></span>
- <span><math><mi>&#x1D5A5;</mi></math>=<span>1D5A5</span></span>
- <span><math><mi>&#x1D5A6;</mi></math>=<span>1D5A6</span></span>
- <span><math><mi>&#x1D5A7;</mi></math>=<span>1D5A7</span></span>
- <span><math><mi>&#x1D5A8;</mi></math>=<span>1D5A8</span></span>
- <span><math><mi>&#x1D5A9;</mi></math>=<span>1D5A9</span></span><br/>
- <span><math><mi>&#x1D5AA;</mi></math>=<span>1D5AA</span></span>
- <span><math><mi>&#x1D5AB;</mi></math>=<span>1D5AB</span></span>
- <span><math><mi>&#x1D5AC;</mi></math>=<span>1D5AC</span></span>
- <span><math><mi>&#x1D5AD;</mi></math>=<span>1D5AD</span></span>
- <span><math><mi>&#x1D5AE;</mi></math>=<span>1D5AE</span></span>
- <span><math><mi>&#x1D5AF;</mi></math>=<span>1D5AF</span></span>
- <span><math><mi>&#x1D5B0;</mi></math>=<span>1D5B0</span></span>
- <span><math><mi>&#x1D5B1;</mi></math>=<span>1D5B1</span></span>
- <span><math><mi>&#x1D5B2;</mi></math>=<span>1D5B2</span></span>
- <span><math><mi>&#x1D5B3;</mi></math>=<span>1D5B3</span></span><br/>
- <span><math><mi>&#x1D5B4;</mi></math>=<span>1D5B4</span></span>
- <span><math><mi>&#x1D5B5;</mi></math>=<span>1D5B5</span></span>
- <span><math><mi>&#x1D5B6;</mi></math>=<span>1D5B6</span></span>
- <span><math><mi>&#x1D5B7;</mi></math>=<span>1D5B7</span></span>
- <span><math><mi>&#x1D5B8;</mi></math>=<span>1D5B8</span></span>
- <span><math><mi>&#x1D5B9;</mi></math>=<span>1D5B9</span></span>
- <span><math><mi>&#x1D5BA;</mi></math>=<span>1D5BA</span></span>
- <span><math><mi>&#x1D5BB;</mi></math>=<span>1D5BB</span></span>
- <span><math><mi>&#x1D5BC;</mi></math>=<span>1D5BC</span></span>
- <span><math><mi>&#x1D5BD;</mi></math>=<span>1D5BD</span></span><br/>
- <span><math><mi>&#x1D5BE;</mi></math>=<span>1D5BE</span></span>
- <span><math><mi>&#x1D5BF;</mi></math>=<span>1D5BF</span></span>
- <span><math><mi>&#x1D5C0;</mi></math>=<span>1D5C0</span></span>
- <span><math><mi>&#x1D5C1;</mi></math>=<span>1D5C1</span></span>
- <span><math><mi>&#x1D5C2;</mi></math>=<span>1D5C2</span></span>
- <span><math><mi>&#x1D5C3;</mi></math>=<span>1D5C3</span></span>
- <span><math><mi>&#x1D5C4;</mi></math>=<span>1D5C4</span></span>
- <span><math><mi>&#x1D5C5;</mi></math>=<span>1D5C5</span></span>
- <span><math><mi>&#x1D5C6;</mi></math>=<span>1D5C6</span></span>
- <span><math><mi>&#x1D5C7;</mi></math>=<span>1D5C7</span></span><br/>
- <span><math><mi>&#x1D5C8;</mi></math>=<span>1D5C8</span></span>
- <span><math><mi>&#x1D5C9;</mi></math>=<span>1D5C9</span></span>
- <span><math><mi>&#x1D5CA;</mi></math>=<span>1D5CA</span></span>
- <span><math><mi>&#x1D5CB;</mi></math>=<span>1D5CB</span></span>
- <span><math><mi>&#x1D5CC;</mi></math>=<span>1D5CC</span></span>
- <span><math><mi>&#x1D5CD;</mi></math>=<span>1D5CD</span></span>
- <span><math><mi>&#x1D5CE;</mi></math>=<span>1D5CE</span></span>
- <span><math><mi>&#x1D5CF;</mi></math>=<span>1D5CF</span></span>
- <span><math><mi>&#x1D5D0;</mi></math>=<span>1D5D0</span></span>
- <span><math><mi>&#x1D5D1;</mi></math>=<span>1D5D1</span></span><br/>
- <span><math><mi>&#x1D5D2;</mi></math>=<span>1D5D2</span></span>
- <span><math><mi>&#x1D5D3;</mi></math>=<span>1D5D3</span></span>
+ <span><math><mtext>&#x1D7E2;</mtext></math>=<span>1D7E2</span></span>
+ <span><math><mtext>&#x1D7E3;</mtext></math>=<span>1D7E3</span></span>
+ <span><math><mtext>&#x1D7E4;</mtext></math>=<span>1D7E4</span></span>
+ <span><math><mtext>&#x1D7E5;</mtext></math>=<span>1D7E5</span></span>
+ <span><math><mtext>&#x1D7E6;</mtext></math>=<span>1D7E6</span></span>
+ <span><math><mtext>&#x1D7E7;</mtext></math>=<span>1D7E7</span></span>
+ <span><math><mtext>&#x1D7E8;</mtext></math>=<span>1D7E8</span></span>
+ <span><math><mtext>&#x1D7E9;</mtext></math>=<span>1D7E9</span></span>
+ <span><math><mtext>&#x1D7EA;</mtext></math>=<span>1D7EA</span></span>
+ <span><math><mtext>&#x1D7EB;</mtext></math>=<span>1D7EB</span></span><br/>
+ <span><math><mtext>&#x1D5A0;</mtext></math>=<span>1D5A0</span></span>
+ <span><math><mtext>&#x1D5A1;</mtext></math>=<span>1D5A1</span></span>
+ <span><math><mtext>&#x1D5A2;</mtext></math>=<span>1D5A2</span></span>
+ <span><math><mtext>&#x1D5A3;</mtext></math>=<span>1D5A3</span></span>
+ <span><math><mtext>&#x1D5A4;</mtext></math>=<span>1D5A4</span></span>
+ <span><math><mtext>&#x1D5A5;</mtext></math>=<span>1D5A5</span></span>
+ <span><math><mtext>&#x1D5A6;</mtext></math>=<span>1D5A6</span></span>
+ <span><math><mtext>&#x1D5A7;</mtext></math>=<span>1D5A7</span></span>
+ <span><math><mtext>&#x1D5A8;</mtext></math>=<span>1D5A8</span></span>
+ <span><math><mtext>&#x1D5A9;</mtext></math>=<span>1D5A9</span></span><br/>
+ <span><math><mtext>&#x1D5AA;</mtext></math>=<span>1D5AA</span></span>
+ <span><math><mtext>&#x1D5AB;</mtext></math>=<span>1D5AB</span></span>
+ <span><math><mtext>&#x1D5AC;</mtext></math>=<span>1D5AC</span></span>
+ <span><math><mtext>&#x1D5AD;</mtext></math>=<span>1D5AD</span></span>
+ <span><math><mtext>&#x1D5AE;</mtext></math>=<span>1D5AE</span></span>
+ <span><math><mtext>&#x1D5AF;</mtext></math>=<span>1D5AF</span></span>
+ <span><math><mtext>&#x1D5B0;</mtext></math>=<span>1D5B0</span></span>
+ <span><math><mtext>&#x1D5B1;</mtext></math>=<span>1D5B1</span></span>
+ <span><math><mtext>&#x1D5B2;</mtext></math>=<span>1D5B2</span></span>
+ <span><math><mtext>&#x1D5B3;</mtext></math>=<span>1D5B3</span></span><br/>
+ <span><math><mtext>&#x1D5B4;</mtext></math>=<span>1D5B4</span></span>
+ <span><math><mtext>&#x1D5B5;</mtext></math>=<span>1D5B5</span></span>
+ <span><math><mtext>&#x1D5B6;</mtext></math>=<span>1D5B6</span></span>
+ <span><math><mtext>&#x1D5B7;</mtext></math>=<span>1D5B7</span></span>
+ <span><math><mtext>&#x1D5B8;</mtext></math>=<span>1D5B8</span></span>
+ <span><math><mtext>&#x1D5B9;</mtext></math>=<span>1D5B9</span></span>
+ <span><math><mtext>&#x1D5BA;</mtext></math>=<span>1D5BA</span></span>
+ <span><math><mtext>&#x1D5BB;</mtext></math>=<span>1D5BB</span></span>
+ <span><math><mtext>&#x1D5BC;</mtext></math>=<span>1D5BC</span></span>
+ <span><math><mtext>&#x1D5BD;</mtext></math>=<span>1D5BD</span></span><br/>
+ <span><math><mtext>&#x1D5BE;</mtext></math>=<span>1D5BE</span></span>
+ <span><math><mtext>&#x1D5BF;</mtext></math>=<span>1D5BF</span></span>
+ <span><math><mtext>&#x1D5C0;</mtext></math>=<span>1D5C0</span></span>
+ <span><math><mtext>&#x1D5C1;</mtext></math>=<span>1D5C1</span></span>
+ <span><math><mtext>&#x1D5C2;</mtext></math>=<span>1D5C2</span></span>
+ <span><math><mtext>&#x1D5C3;</mtext></math>=<span>1D5C3</span></span>
+ <span><math><mtext>&#x1D5C4;</mtext></math>=<span>1D5C4</span></span>
+ <span><math><mtext>&#x1D5C5;</mtext></math>=<span>1D5C5</span></span>
+ <span><math><mtext>&#x1D5C6;</mtext></math>=<span>1D5C6</span></span>
+ <span><math><mtext>&#x1D5C7;</mtext></math>=<span>1D5C7</span></span><br/>
+ <span><math><mtext>&#x1D5C8;</mtext></math>=<span>1D5C8</span></span>
+ <span><math><mtext>&#x1D5C9;</mtext></math>=<span>1D5C9</span></span>
+ <span><math><mtext>&#x1D5CA;</mtext></math>=<span>1D5CA</span></span>
+ <span><math><mtext>&#x1D5CB;</mtext></math>=<span>1D5CB</span></span>
+ <span><math><mtext>&#x1D5CC;</mtext></math>=<span>1D5CC</span></span>
+ <span><math><mtext>&#x1D5CD;</mtext></math>=<span>1D5CD</span></span>
+ <span><math><mtext>&#x1D5CE;</mtext></math>=<span>1D5CE</span></span>
+ <span><math><mtext>&#x1D5CF;</mtext></math>=<span>1D5CF</span></span>
+ <span><math><mtext>&#x1D5D0;</mtext></math>=<span>1D5D0</span></span>
+ <span><math><mtext>&#x1D5D1;</mtext></math>=<span>1D5D1</span></span><br/>
+ <span><math><mtext>&#x1D5D2;</mtext></math>=<span>1D5D2</span></span>
+ <span><math><mtext>&#x1D5D3;</mtext></math>=<span>1D5D3</span></span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif.html
index fc82e54ecf0..fc880b99aff 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-sans-serif.html
@@ -5,7 +5,7 @@
<title>mathvariant sans-serif</title>
<link rel="help" href="http://www.mathml-association.org/MathMLinHTML5/S2.html#SS3.SSS1.tab2"/>
<link rel="match" href="mathvariant-sans-serif-ref.html"/>
-<meta name="assert" content="Verify that a single-char <mi> with a sans-serif mathvariant is equivalent to an <mi> with the transformed unicode character.">
+<meta name="assert" content="Verify that a single-char <mtext> with a sans-serif mathvariant is equivalent to an <mtext> with the transformed unicode character.">
<style>
@font-face {
font-family: TestFont;
@@ -26,67 +26,67 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi mathvariant="sans-serif">&#x30;</mi></math>=<span>1D7E2</span></span>
- <span><math><mi mathvariant="sans-serif">&#x31;</mi></math>=<span>1D7E3</span></span>
- <span><math><mi mathvariant="sans-serif">&#x32;</mi></math>=<span>1D7E4</span></span>
- <span><math><mi mathvariant="sans-serif">&#x33;</mi></math>=<span>1D7E5</span></span>
- <span><math><mi mathvariant="sans-serif">&#x34;</mi></math>=<span>1D7E6</span></span>
- <span><math><mi mathvariant="sans-serif">&#x35;</mi></math>=<span>1D7E7</span></span>
- <span><math><mi mathvariant="sans-serif">&#x36;</mi></math>=<span>1D7E8</span></span>
- <span><math><mi mathvariant="sans-serif">&#x37;</mi></math>=<span>1D7E9</span></span>
- <span><math><mi mathvariant="sans-serif">&#x38;</mi></math>=<span>1D7EA</span></span>
- <span><math><mi mathvariant="sans-serif">&#x39;</mi></math>=<span>1D7EB</span></span><br/>
- <span><math><mi mathvariant="sans-serif">&#x41;</mi></math>=<span>1D5A0</span></span>
- <span><math><mi mathvariant="sans-serif">&#x42;</mi></math>=<span>1D5A1</span></span>
- <span><math><mi mathvariant="sans-serif">&#x43;</mi></math>=<span>1D5A2</span></span>
- <span><math><mi mathvariant="sans-serif">&#x44;</mi></math>=<span>1D5A3</span></span>
- <span><math><mi mathvariant="sans-serif">&#x45;</mi></math>=<span>1D5A4</span></span>
- <span><math><mi mathvariant="sans-serif">&#x46;</mi></math>=<span>1D5A5</span></span>
- <span><math><mi mathvariant="sans-serif">&#x47;</mi></math>=<span>1D5A6</span></span>
- <span><math><mi mathvariant="sans-serif">&#x48;</mi></math>=<span>1D5A7</span></span>
- <span><math><mi mathvariant="sans-serif">&#x49;</mi></math>=<span>1D5A8</span></span>
- <span><math><mi mathvariant="sans-serif">&#x4A;</mi></math>=<span>1D5A9</span></span><br/>
- <span><math><mi mathvariant="sans-serif">&#x4B;</mi></math>=<span>1D5AA</span></span>
- <span><math><mi mathvariant="sans-serif">&#x4C;</mi></math>=<span>1D5AB</span></span>
- <span><math><mi mathvariant="sans-serif">&#x4D;</mi></math>=<span>1D5AC</span></span>
- <span><math><mi mathvariant="sans-serif">&#x4E;</mi></math>=<span>1D5AD</span></span>
- <span><math><mi mathvariant="sans-serif">&#x4F;</mi></math>=<span>1D5AE</span></span>
- <span><math><mi mathvariant="sans-serif">&#x50;</mi></math>=<span>1D5AF</span></span>
- <span><math><mi mathvariant="sans-serif">&#x51;</mi></math>=<span>1D5B0</span></span>
- <span><math><mi mathvariant="sans-serif">&#x52;</mi></math>=<span>1D5B1</span></span>
- <span><math><mi mathvariant="sans-serif">&#x53;</mi></math>=<span>1D5B2</span></span>
- <span><math><mi mathvariant="sans-serif">&#x54;</mi></math>=<span>1D5B3</span></span><br/>
- <span><math><mi mathvariant="sans-serif">&#x55;</mi></math>=<span>1D5B4</span></span>
- <span><math><mi mathvariant="sans-serif">&#x56;</mi></math>=<span>1D5B5</span></span>
- <span><math><mi mathvariant="sans-serif">&#x57;</mi></math>=<span>1D5B6</span></span>
- <span><math><mi mathvariant="sans-serif">&#x58;</mi></math>=<span>1D5B7</span></span>
- <span><math><mi mathvariant="sans-serif">&#x59;</mi></math>=<span>1D5B8</span></span>
- <span><math><mi mathvariant="sans-serif">&#x5A;</mi></math>=<span>1D5B9</span></span>
- <span><math><mi mathvariant="sans-serif">&#x61;</mi></math>=<span>1D5BA</span></span>
- <span><math><mi mathvariant="sans-serif">&#x62;</mi></math>=<span>1D5BB</span></span>
- <span><math><mi mathvariant="sans-serif">&#x63;</mi></math>=<span>1D5BC</span></span>
- <span><math><mi mathvariant="sans-serif">&#x64;</mi></math>=<span>1D5BD</span></span><br/>
- <span><math><mi mathvariant="sans-serif">&#x65;</mi></math>=<span>1D5BE</span></span>
- <span><math><mi mathvariant="sans-serif">&#x66;</mi></math>=<span>1D5BF</span></span>
- <span><math><mi mathvariant="sans-serif">&#x67;</mi></math>=<span>1D5C0</span></span>
- <span><math><mi mathvariant="sans-serif">&#x68;</mi></math>=<span>1D5C1</span></span>
- <span><math><mi mathvariant="sans-serif">&#x69;</mi></math>=<span>1D5C2</span></span>
- <span><math><mi mathvariant="sans-serif">&#x6A;</mi></math>=<span>1D5C3</span></span>
- <span><math><mi mathvariant="sans-serif">&#x6B;</mi></math>=<span>1D5C4</span></span>
- <span><math><mi mathvariant="sans-serif">&#x6C;</mi></math>=<span>1D5C5</span></span>
- <span><math><mi mathvariant="sans-serif">&#x6D;</mi></math>=<span>1D5C6</span></span>
- <span><math><mi mathvariant="sans-serif">&#x6E;</mi></math>=<span>1D5C7</span></span><br/>
- <span><math><mi mathvariant="sans-serif">&#x6F;</mi></math>=<span>1D5C8</span></span>
- <span><math><mi mathvariant="sans-serif">&#x70;</mi></math>=<span>1D5C9</span></span>
- <span><math><mi mathvariant="sans-serif">&#x71;</mi></math>=<span>1D5CA</span></span>
- <span><math><mi mathvariant="sans-serif">&#x72;</mi></math>=<span>1D5CB</span></span>
- <span><math><mi mathvariant="sans-serif">&#x73;</mi></math>=<span>1D5CC</span></span>
- <span><math><mi mathvariant="sans-serif">&#x74;</mi></math>=<span>1D5CD</span></span>
- <span><math><mi mathvariant="sans-serif">&#x75;</mi></math>=<span>1D5CE</span></span>
- <span><math><mi mathvariant="sans-serif">&#x76;</mi></math>=<span>1D5CF</span></span>
- <span><math><mi mathvariant="sans-serif">&#x77;</mi></math>=<span>1D5D0</span></span>
- <span><math><mi mathvariant="sans-serif">&#x78;</mi></math>=<span>1D5D1</span></span><br/>
- <span><math><mi mathvariant="sans-serif">&#x79;</mi></math>=<span>1D5D2</span></span>
- <span><math><mi mathvariant="sans-serif">&#x7A;</mi></math>=<span>1D5D3</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x30;</mtext></math>=<span>1D7E2</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x31;</mtext></math>=<span>1D7E3</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x32;</mtext></math>=<span>1D7E4</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x33;</mtext></math>=<span>1D7E5</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x34;</mtext></math>=<span>1D7E6</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x35;</mtext></math>=<span>1D7E7</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x36;</mtext></math>=<span>1D7E8</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x37;</mtext></math>=<span>1D7E9</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x38;</mtext></math>=<span>1D7EA</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x39;</mtext></math>=<span>1D7EB</span></span><br/>
+ <span><math><mtext mathvariant="sans-serif">&#x41;</mtext></math>=<span>1D5A0</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x42;</mtext></math>=<span>1D5A1</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x43;</mtext></math>=<span>1D5A2</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x44;</mtext></math>=<span>1D5A3</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x45;</mtext></math>=<span>1D5A4</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x46;</mtext></math>=<span>1D5A5</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x47;</mtext></math>=<span>1D5A6</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x48;</mtext></math>=<span>1D5A7</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x49;</mtext></math>=<span>1D5A8</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x4A;</mtext></math>=<span>1D5A9</span></span><br/>
+ <span><math><mtext mathvariant="sans-serif">&#x4B;</mtext></math>=<span>1D5AA</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x4C;</mtext></math>=<span>1D5AB</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x4D;</mtext></math>=<span>1D5AC</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x4E;</mtext></math>=<span>1D5AD</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x4F;</mtext></math>=<span>1D5AE</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x50;</mtext></math>=<span>1D5AF</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x51;</mtext></math>=<span>1D5B0</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x52;</mtext></math>=<span>1D5B1</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x53;</mtext></math>=<span>1D5B2</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x54;</mtext></math>=<span>1D5B3</span></span><br/>
+ <span><math><mtext mathvariant="sans-serif">&#x55;</mtext></math>=<span>1D5B4</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x56;</mtext></math>=<span>1D5B5</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x57;</mtext></math>=<span>1D5B6</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x58;</mtext></math>=<span>1D5B7</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x59;</mtext></math>=<span>1D5B8</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x5A;</mtext></math>=<span>1D5B9</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x61;</mtext></math>=<span>1D5BA</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x62;</mtext></math>=<span>1D5BB</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x63;</mtext></math>=<span>1D5BC</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x64;</mtext></math>=<span>1D5BD</span></span><br/>
+ <span><math><mtext mathvariant="sans-serif">&#x65;</mtext></math>=<span>1D5BE</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x66;</mtext></math>=<span>1D5BF</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x67;</mtext></math>=<span>1D5C0</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x68;</mtext></math>=<span>1D5C1</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x69;</mtext></math>=<span>1D5C2</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x6A;</mtext></math>=<span>1D5C3</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x6B;</mtext></math>=<span>1D5C4</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x6C;</mtext></math>=<span>1D5C5</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x6D;</mtext></math>=<span>1D5C6</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x6E;</mtext></math>=<span>1D5C7</span></span><br/>
+ <span><math><mtext mathvariant="sans-serif">&#x6F;</mtext></math>=<span>1D5C8</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x70;</mtext></math>=<span>1D5C9</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x71;</mtext></math>=<span>1D5CA</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x72;</mtext></math>=<span>1D5CB</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x73;</mtext></math>=<span>1D5CC</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x74;</mtext></math>=<span>1D5CD</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x75;</mtext></math>=<span>1D5CE</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x76;</mtext></math>=<span>1D5CF</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x77;</mtext></math>=<span>1D5D0</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x78;</mtext></math>=<span>1D5D1</span></span><br/>
+ <span><math><mtext mathvariant="sans-serif">&#x79;</mtext></math>=<span>1D5D2</span></span>
+ <span><math><mtext mathvariant="sans-serif">&#x7A;</mtext></math>=<span>1D5D3</span></span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-script-ref.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-script-ref.html
index 8e5cae85602..725268a84e5 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-script-ref.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-script-ref.html
@@ -23,57 +23,57 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi>&#x1D49C;</mi></math>=<span>1D49C</span></span>
- <span><math><mi>&#x212C;</mi></math>=<span>0212C</span></span>
- <span><math><mi>&#x1D49E;</mi></math>=<span>1D49E</span></span>
- <span><math><mi>&#x1D49F;</mi></math>=<span>1D49F</span></span>
- <span><math><mi>&#x2130;</mi></math>=<span>02130</span></span>
- <span><math><mi>&#x2131;</mi></math>=<span>02131</span></span>
- <span><math><mi>&#x1D4A2;</mi></math>=<span>1D4A2</span></span>
- <span><math><mi>&#x210B;</mi></math>=<span>0210B</span></span>
- <span><math><mi>&#x2110;</mi></math>=<span>02110</span></span>
- <span><math><mi>&#x1D4A5;</mi></math>=<span>1D4A5</span></span><br/>
- <span><math><mi>&#x1D4A6;</mi></math>=<span>1D4A6</span></span>
- <span><math><mi>&#x2112;</mi></math>=<span>02112</span></span>
- <span><math><mi>&#x2133;</mi></math>=<span>02133</span></span>
- <span><math><mi>&#x1D4A9;</mi></math>=<span>1D4A9</span></span>
- <span><math><mi>&#x1D4AA;</mi></math>=<span>1D4AA</span></span>
- <span><math><mi>&#x1D4AB;</mi></math>=<span>1D4AB</span></span>
- <span><math><mi>&#x1D4AC;</mi></math>=<span>1D4AC</span></span>
- <span><math><mi>&#x211B;</mi></math>=<span>0211B</span></span>
- <span><math><mi>&#x1D4AE;</mi></math>=<span>1D4AE</span></span>
- <span><math><mi>&#x1D4AF;</mi></math>=<span>1D4AF</span></span><br/>
- <span><math><mi>&#x1D4B0;</mi></math>=<span>1D4B0</span></span>
- <span><math><mi>&#x1D4B1;</mi></math>=<span>1D4B1</span></span>
- <span><math><mi>&#x1D4B2;</mi></math>=<span>1D4B2</span></span>
- <span><math><mi>&#x1D4B3;</mi></math>=<span>1D4B3</span></span>
- <span><math><mi>&#x1D4B4;</mi></math>=<span>1D4B4</span></span>
- <span><math><mi>&#x1D4B5;</mi></math>=<span>1D4B5</span></span>
- <span><math><mi>&#x1D4B6;</mi></math>=<span>1D4B6</span></span>
- <span><math><mi>&#x1D4B7;</mi></math>=<span>1D4B7</span></span>
- <span><math><mi>&#x1D4B8;</mi></math>=<span>1D4B8</span></span>
- <span><math><mi>&#x1D4B9;</mi></math>=<span>1D4B9</span></span><br/>
- <span><math><mi>&#x212F;</mi></math>=<span>0212F</span></span>
- <span><math><mi>&#x1D4BB;</mi></math>=<span>1D4BB</span></span>
- <span><math><mi>&#x210A;</mi></math>=<span>0210A</span></span>
- <span><math><mi>&#x1D4BD;</mi></math>=<span>1D4BD</span></span>
- <span><math><mi>&#x1D4BE;</mi></math>=<span>1D4BE</span></span>
- <span><math><mi>&#x1D4BF;</mi></math>=<span>1D4BF</span></span>
- <span><math><mi>&#x1D4C0;</mi></math>=<span>1D4C0</span></span>
- <span><math><mi>&#x1D4C1;</mi></math>=<span>1D4C1</span></span>
- <span><math><mi>&#x1D4C2;</mi></math>=<span>1D4C2</span></span>
- <span><math><mi>&#x1D4C3;</mi></math>=<span>1D4C3</span></span><br/>
- <span><math><mi>&#x2134;</mi></math>=<span>02134</span></span>
- <span><math><mi>&#x1D4C5;</mi></math>=<span>1D4C5</span></span>
- <span><math><mi>&#x1D4C6;</mi></math>=<span>1D4C6</span></span>
- <span><math><mi>&#x1D4C7;</mi></math>=<span>1D4C7</span></span>
- <span><math><mi>&#x1D4C8;</mi></math>=<span>1D4C8</span></span>
- <span><math><mi>&#x1D4C9;</mi></math>=<span>1D4C9</span></span>
- <span><math><mi>&#x1D4CA;</mi></math>=<span>1D4CA</span></span>
- <span><math><mi>&#x1D4CB;</mi></math>=<span>1D4CB</span></span>
- <span><math><mi>&#x1D4CC;</mi></math>=<span>1D4CC</span></span>
- <span><math><mi>&#x1D4CD;</mi></math>=<span>1D4CD</span></span><br/>
- <span><math><mi>&#x1D4CE;</mi></math>=<span>1D4CE</span></span>
- <span><math><mi>&#x1D4CF;</mi></math>=<span>1D4CF</span></span>
+ <span><math><mtext>&#x1D49C;</mtext></math>=<span>1D49C</span></span>
+ <span><math><mtext>&#x212C;</mtext></math>=<span>0212C</span></span>
+ <span><math><mtext>&#x1D49E;</mtext></math>=<span>1D49E</span></span>
+ <span><math><mtext>&#x1D49F;</mtext></math>=<span>1D49F</span></span>
+ <span><math><mtext>&#x2130;</mtext></math>=<span>02130</span></span>
+ <span><math><mtext>&#x2131;</mtext></math>=<span>02131</span></span>
+ <span><math><mtext>&#x1D4A2;</mtext></math>=<span>1D4A2</span></span>
+ <span><math><mtext>&#x210B;</mtext></math>=<span>0210B</span></span>
+ <span><math><mtext>&#x2110;</mtext></math>=<span>02110</span></span>
+ <span><math><mtext>&#x1D4A5;</mtext></math>=<span>1D4A5</span></span><br/>
+ <span><math><mtext>&#x1D4A6;</mtext></math>=<span>1D4A6</span></span>
+ <span><math><mtext>&#x2112;</mtext></math>=<span>02112</span></span>
+ <span><math><mtext>&#x2133;</mtext></math>=<span>02133</span></span>
+ <span><math><mtext>&#x1D4A9;</mtext></math>=<span>1D4A9</span></span>
+ <span><math><mtext>&#x1D4AA;</mtext></math>=<span>1D4AA</span></span>
+ <span><math><mtext>&#x1D4AB;</mtext></math>=<span>1D4AB</span></span>
+ <span><math><mtext>&#x1D4AC;</mtext></math>=<span>1D4AC</span></span>
+ <span><math><mtext>&#x211B;</mtext></math>=<span>0211B</span></span>
+ <span><math><mtext>&#x1D4AE;</mtext></math>=<span>1D4AE</span></span>
+ <span><math><mtext>&#x1D4AF;</mtext></math>=<span>1D4AF</span></span><br/>
+ <span><math><mtext>&#x1D4B0;</mtext></math>=<span>1D4B0</span></span>
+ <span><math><mtext>&#x1D4B1;</mtext></math>=<span>1D4B1</span></span>
+ <span><math><mtext>&#x1D4B2;</mtext></math>=<span>1D4B2</span></span>
+ <span><math><mtext>&#x1D4B3;</mtext></math>=<span>1D4B3</span></span>
+ <span><math><mtext>&#x1D4B4;</mtext></math>=<span>1D4B4</span></span>
+ <span><math><mtext>&#x1D4B5;</mtext></math>=<span>1D4B5</span></span>
+ <span><math><mtext>&#x1D4B6;</mtext></math>=<span>1D4B6</span></span>
+ <span><math><mtext>&#x1D4B7;</mtext></math>=<span>1D4B7</span></span>
+ <span><math><mtext>&#x1D4B8;</mtext></math>=<span>1D4B8</span></span>
+ <span><math><mtext>&#x1D4B9;</mtext></math>=<span>1D4B9</span></span><br/>
+ <span><math><mtext>&#x212F;</mtext></math>=<span>0212F</span></span>
+ <span><math><mtext>&#x1D4BB;</mtext></math>=<span>1D4BB</span></span>
+ <span><math><mtext>&#x210A;</mtext></math>=<span>0210A</span></span>
+ <span><math><mtext>&#x1D4BD;</mtext></math>=<span>1D4BD</span></span>
+ <span><math><mtext>&#x1D4BE;</mtext></math>=<span>1D4BE</span></span>
+ <span><math><mtext>&#x1D4BF;</mtext></math>=<span>1D4BF</span></span>
+ <span><math><mtext>&#x1D4C0;</mtext></math>=<span>1D4C0</span></span>
+ <span><math><mtext>&#x1D4C1;</mtext></math>=<span>1D4C1</span></span>
+ <span><math><mtext>&#x1D4C2;</mtext></math>=<span>1D4C2</span></span>
+ <span><math><mtext>&#x1D4C3;</mtext></math>=<span>1D4C3</span></span><br/>
+ <span><math><mtext>&#x2134;</mtext></math>=<span>02134</span></span>
+ <span><math><mtext>&#x1D4C5;</mtext></math>=<span>1D4C5</span></span>
+ <span><math><mtext>&#x1D4C6;</mtext></math>=<span>1D4C6</span></span>
+ <span><math><mtext>&#x1D4C7;</mtext></math>=<span>1D4C7</span></span>
+ <span><math><mtext>&#x1D4C8;</mtext></math>=<span>1D4C8</span></span>
+ <span><math><mtext>&#x1D4C9;</mtext></math>=<span>1D4C9</span></span>
+ <span><math><mtext>&#x1D4CA;</mtext></math>=<span>1D4CA</span></span>
+ <span><math><mtext>&#x1D4CB;</mtext></math>=<span>1D4CB</span></span>
+ <span><math><mtext>&#x1D4CC;</mtext></math>=<span>1D4CC</span></span>
+ <span><math><mtext>&#x1D4CD;</mtext></math>=<span>1D4CD</span></span><br/>
+ <span><math><mtext>&#x1D4CE;</mtext></math>=<span>1D4CE</span></span>
+ <span><math><mtext>&#x1D4CF;</mtext></math>=<span>1D4CF</span></span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-script.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-script.html
index 721052601f9..5725ed51033 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-script.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-script.html
@@ -5,7 +5,7 @@
<title>mathvariant script</title>
<link rel="help" href="http://www.mathml-association.org/MathMLinHTML5/S2.html#SS3.SSS1.tab2"/>
<link rel="match" href="mathvariant-script-ref.html"/>
-<meta name="assert" content="Verify that a single-char <mi> with a script mathvariant is equivalent to an <mi> with the transformed unicode character.">
+<meta name="assert" content="Verify that a single-char <mtext> with a script mathvariant is equivalent to an <mtext> with the transformed unicode character.">
<style>
@font-face {
font-family: TestFont;
@@ -26,57 +26,57 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi mathvariant="script">&#x41;</mi></math>=<span>1D49C</span></span>
- <span><math><mi mathvariant="script">&#x42;</mi></math>=<span>0212C</span></span>
- <span><math><mi mathvariant="script">&#x43;</mi></math>=<span>1D49E</span></span>
- <span><math><mi mathvariant="script">&#x44;</mi></math>=<span>1D49F</span></span>
- <span><math><mi mathvariant="script">&#x45;</mi></math>=<span>02130</span></span>
- <span><math><mi mathvariant="script">&#x46;</mi></math>=<span>02131</span></span>
- <span><math><mi mathvariant="script">&#x47;</mi></math>=<span>1D4A2</span></span>
- <span><math><mi mathvariant="script">&#x48;</mi></math>=<span>0210B</span></span>
- <span><math><mi mathvariant="script">&#x49;</mi></math>=<span>02110</span></span>
- <span><math><mi mathvariant="script">&#x4A;</mi></math>=<span>1D4A5</span></span><br/>
- <span><math><mi mathvariant="script">&#x4B;</mi></math>=<span>1D4A6</span></span>
- <span><math><mi mathvariant="script">&#x4C;</mi></math>=<span>02112</span></span>
- <span><math><mi mathvariant="script">&#x4D;</mi></math>=<span>02133</span></span>
- <span><math><mi mathvariant="script">&#x4E;</mi></math>=<span>1D4A9</span></span>
- <span><math><mi mathvariant="script">&#x4F;</mi></math>=<span>1D4AA</span></span>
- <span><math><mi mathvariant="script">&#x50;</mi></math>=<span>1D4AB</span></span>
- <span><math><mi mathvariant="script">&#x51;</mi></math>=<span>1D4AC</span></span>
- <span><math><mi mathvariant="script">&#x52;</mi></math>=<span>0211B</span></span>
- <span><math><mi mathvariant="script">&#x53;</mi></math>=<span>1D4AE</span></span>
- <span><math><mi mathvariant="script">&#x54;</mi></math>=<span>1D4AF</span></span><br/>
- <span><math><mi mathvariant="script">&#x55;</mi></math>=<span>1D4B0</span></span>
- <span><math><mi mathvariant="script">&#x56;</mi></math>=<span>1D4B1</span></span>
- <span><math><mi mathvariant="script">&#x57;</mi></math>=<span>1D4B2</span></span>
- <span><math><mi mathvariant="script">&#x58;</mi></math>=<span>1D4B3</span></span>
- <span><math><mi mathvariant="script">&#x59;</mi></math>=<span>1D4B4</span></span>
- <span><math><mi mathvariant="script">&#x5A;</mi></math>=<span>1D4B5</span></span>
- <span><math><mi mathvariant="script">&#x61;</mi></math>=<span>1D4B6</span></span>
- <span><math><mi mathvariant="script">&#x62;</mi></math>=<span>1D4B7</span></span>
- <span><math><mi mathvariant="script">&#x63;</mi></math>=<span>1D4B8</span></span>
- <span><math><mi mathvariant="script">&#x64;</mi></math>=<span>1D4B9</span></span><br/>
- <span><math><mi mathvariant="script">&#x65;</mi></math>=<span>0212F</span></span>
- <span><math><mi mathvariant="script">&#x66;</mi></math>=<span>1D4BB</span></span>
- <span><math><mi mathvariant="script">&#x67;</mi></math>=<span>0210A</span></span>
- <span><math><mi mathvariant="script">&#x68;</mi></math>=<span>1D4BD</span></span>
- <span><math><mi mathvariant="script">&#x69;</mi></math>=<span>1D4BE</span></span>
- <span><math><mi mathvariant="script">&#x6A;</mi></math>=<span>1D4BF</span></span>
- <span><math><mi mathvariant="script">&#x6B;</mi></math>=<span>1D4C0</span></span>
- <span><math><mi mathvariant="script">&#x6C;</mi></math>=<span>1D4C1</span></span>
- <span><math><mi mathvariant="script">&#x6D;</mi></math>=<span>1D4C2</span></span>
- <span><math><mi mathvariant="script">&#x6E;</mi></math>=<span>1D4C3</span></span><br/>
- <span><math><mi mathvariant="script">&#x6F;</mi></math>=<span>02134</span></span>
- <span><math><mi mathvariant="script">&#x70;</mi></math>=<span>1D4C5</span></span>
- <span><math><mi mathvariant="script">&#x71;</mi></math>=<span>1D4C6</span></span>
- <span><math><mi mathvariant="script">&#x72;</mi></math>=<span>1D4C7</span></span>
- <span><math><mi mathvariant="script">&#x73;</mi></math>=<span>1D4C8</span></span>
- <span><math><mi mathvariant="script">&#x74;</mi></math>=<span>1D4C9</span></span>
- <span><math><mi mathvariant="script">&#x75;</mi></math>=<span>1D4CA</span></span>
- <span><math><mi mathvariant="script">&#x76;</mi></math>=<span>1D4CB</span></span>
- <span><math><mi mathvariant="script">&#x77;</mi></math>=<span>1D4CC</span></span>
- <span><math><mi mathvariant="script">&#x78;</mi></math>=<span>1D4CD</span></span><br/>
- <span><math><mi mathvariant="script">&#x79;</mi></math>=<span>1D4CE</span></span>
- <span><math><mi mathvariant="script">&#x7A;</mi></math>=<span>1D4CF</span></span>
+ <span><math><mtext mathvariant="script">&#x41;</mtext></math>=<span>1D49C</span></span>
+ <span><math><mtext mathvariant="script">&#x42;</mtext></math>=<span>0212C</span></span>
+ <span><math><mtext mathvariant="script">&#x43;</mtext></math>=<span>1D49E</span></span>
+ <span><math><mtext mathvariant="script">&#x44;</mtext></math>=<span>1D49F</span></span>
+ <span><math><mtext mathvariant="script">&#x45;</mtext></math>=<span>02130</span></span>
+ <span><math><mtext mathvariant="script">&#x46;</mtext></math>=<span>02131</span></span>
+ <span><math><mtext mathvariant="script">&#x47;</mtext></math>=<span>1D4A2</span></span>
+ <span><math><mtext mathvariant="script">&#x48;</mtext></math>=<span>0210B</span></span>
+ <span><math><mtext mathvariant="script">&#x49;</mtext></math>=<span>02110</span></span>
+ <span><math><mtext mathvariant="script">&#x4A;</mtext></math>=<span>1D4A5</span></span><br/>
+ <span><math><mtext mathvariant="script">&#x4B;</mtext></math>=<span>1D4A6</span></span>
+ <span><math><mtext mathvariant="script">&#x4C;</mtext></math>=<span>02112</span></span>
+ <span><math><mtext mathvariant="script">&#x4D;</mtext></math>=<span>02133</span></span>
+ <span><math><mtext mathvariant="script">&#x4E;</mtext></math>=<span>1D4A9</span></span>
+ <span><math><mtext mathvariant="script">&#x4F;</mtext></math>=<span>1D4AA</span></span>
+ <span><math><mtext mathvariant="script">&#x50;</mtext></math>=<span>1D4AB</span></span>
+ <span><math><mtext mathvariant="script">&#x51;</mtext></math>=<span>1D4AC</span></span>
+ <span><math><mtext mathvariant="script">&#x52;</mtext></math>=<span>0211B</span></span>
+ <span><math><mtext mathvariant="script">&#x53;</mtext></math>=<span>1D4AE</span></span>
+ <span><math><mtext mathvariant="script">&#x54;</mtext></math>=<span>1D4AF</span></span><br/>
+ <span><math><mtext mathvariant="script">&#x55;</mtext></math>=<span>1D4B0</span></span>
+ <span><math><mtext mathvariant="script">&#x56;</mtext></math>=<span>1D4B1</span></span>
+ <span><math><mtext mathvariant="script">&#x57;</mtext></math>=<span>1D4B2</span></span>
+ <span><math><mtext mathvariant="script">&#x58;</mtext></math>=<span>1D4B3</span></span>
+ <span><math><mtext mathvariant="script">&#x59;</mtext></math>=<span>1D4B4</span></span>
+ <span><math><mtext mathvariant="script">&#x5A;</mtext></math>=<span>1D4B5</span></span>
+ <span><math><mtext mathvariant="script">&#x61;</mtext></math>=<span>1D4B6</span></span>
+ <span><math><mtext mathvariant="script">&#x62;</mtext></math>=<span>1D4B7</span></span>
+ <span><math><mtext mathvariant="script">&#x63;</mtext></math>=<span>1D4B8</span></span>
+ <span><math><mtext mathvariant="script">&#x64;</mtext></math>=<span>1D4B9</span></span><br/>
+ <span><math><mtext mathvariant="script">&#x65;</mtext></math>=<span>0212F</span></span>
+ <span><math><mtext mathvariant="script">&#x66;</mtext></math>=<span>1D4BB</span></span>
+ <span><math><mtext mathvariant="script">&#x67;</mtext></math>=<span>0210A</span></span>
+ <span><math><mtext mathvariant="script">&#x68;</mtext></math>=<span>1D4BD</span></span>
+ <span><math><mtext mathvariant="script">&#x69;</mtext></math>=<span>1D4BE</span></span>
+ <span><math><mtext mathvariant="script">&#x6A;</mtext></math>=<span>1D4BF</span></span>
+ <span><math><mtext mathvariant="script">&#x6B;</mtext></math>=<span>1D4C0</span></span>
+ <span><math><mtext mathvariant="script">&#x6C;</mtext></math>=<span>1D4C1</span></span>
+ <span><math><mtext mathvariant="script">&#x6D;</mtext></math>=<span>1D4C2</span></span>
+ <span><math><mtext mathvariant="script">&#x6E;</mtext></math>=<span>1D4C3</span></span><br/>
+ <span><math><mtext mathvariant="script">&#x6F;</mtext></math>=<span>02134</span></span>
+ <span><math><mtext mathvariant="script">&#x70;</mtext></math>=<span>1D4C5</span></span>
+ <span><math><mtext mathvariant="script">&#x71;</mtext></math>=<span>1D4C6</span></span>
+ <span><math><mtext mathvariant="script">&#x72;</mtext></math>=<span>1D4C7</span></span>
+ <span><math><mtext mathvariant="script">&#x73;</mtext></math>=<span>1D4C8</span></span>
+ <span><math><mtext mathvariant="script">&#x74;</mtext></math>=<span>1D4C9</span></span>
+ <span><math><mtext mathvariant="script">&#x75;</mtext></math>=<span>1D4CA</span></span>
+ <span><math><mtext mathvariant="script">&#x76;</mtext></math>=<span>1D4CB</span></span>
+ <span><math><mtext mathvariant="script">&#x77;</mtext></math>=<span>1D4CC</span></span>
+ <span><math><mtext mathvariant="script">&#x78;</mtext></math>=<span>1D4CD</span></span><br/>
+ <span><math><mtext mathvariant="script">&#x79;</mtext></math>=<span>1D4CE</span></span>
+ <span><math><mtext mathvariant="script">&#x7A;</mtext></math>=<span>1D4CF</span></span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-stretched-ref.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-stretched-ref.html
index 717ebc2af42..1450e19edf0 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-stretched-ref.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-stretched-ref.html
@@ -23,28 +23,28 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi>&#x1EE7E;</mi></math>=<span>1EE7E</span></span>
- <span><math><mi>&#x1EE61;</mi></math>=<span>1EE61</span></span>
- <span><math><mi>&#x1EE75;</mi></math>=<span>1EE75</span></span>
- <span><math><mi>&#x1EE76;</mi></math>=<span>1EE76</span></span>
- <span><math><mi>&#x1EE62;</mi></math>=<span>1EE62</span></span>
- <span><math><mi>&#x1EE67;</mi></math>=<span>1EE67</span></span>
- <span><math><mi>&#x1EE77;</mi></math>=<span>1EE77</span></span>
- <span><math><mi>&#x1EE6E;</mi></math>=<span>1EE6E</span></span>
- <span><math><mi>&#x1EE74;</mi></math>=<span>1EE74</span></span>
- <span><math><mi>&#x1EE71;</mi></math>=<span>1EE71</span></span><br/>
- <span><math><mi>&#x1EE79;</mi></math>=<span>1EE79</span></span>
- <span><math><mi>&#x1EE68;</mi></math>=<span>1EE68</span></span>
- <span><math><mi>&#x1EE7A;</mi></math>=<span>1EE7A</span></span>
- <span><math><mi>&#x1EE6F;</mi></math>=<span>1EE6F</span></span>
- <span><math><mi>&#x1EE7B;</mi></math>=<span>1EE7B</span></span>
- <span><math><mi>&#x1EE70;</mi></math>=<span>1EE70</span></span>
- <span><math><mi>&#x1EE72;</mi></math>=<span>1EE72</span></span>
- <span><math><mi>&#x1EE6A;</mi></math>=<span>1EE6A</span></span>
- <span><math><mi>&#x1EE6C;</mi></math>=<span>1EE6C</span></span>
- <span><math><mi>&#x1EE6D;</mi></math>=<span>1EE6D</span></span><br/>
- <span><math><mi>&#x1EE64;</mi></math>=<span>1EE64</span></span>
- <span><math><mi>&#x1EE69;</mi></math>=<span>1EE69</span></span>
- <span><math><mi>&#x1EE7C;</mi></math>=<span>1EE7C</span></span>
+ <span><math><mtext>&#x1EE7E;</mtext></math>=<span>1EE7E</span></span>
+ <span><math><mtext>&#x1EE61;</mtext></math>=<span>1EE61</span></span>
+ <span><math><mtext>&#x1EE75;</mtext></math>=<span>1EE75</span></span>
+ <span><math><mtext>&#x1EE76;</mtext></math>=<span>1EE76</span></span>
+ <span><math><mtext>&#x1EE62;</mtext></math>=<span>1EE62</span></span>
+ <span><math><mtext>&#x1EE67;</mtext></math>=<span>1EE67</span></span>
+ <span><math><mtext>&#x1EE77;</mtext></math>=<span>1EE77</span></span>
+ <span><math><mtext>&#x1EE6E;</mtext></math>=<span>1EE6E</span></span>
+ <span><math><mtext>&#x1EE74;</mtext></math>=<span>1EE74</span></span>
+ <span><math><mtext>&#x1EE71;</mtext></math>=<span>1EE71</span></span><br/>
+ <span><math><mtext>&#x1EE79;</mtext></math>=<span>1EE79</span></span>
+ <span><math><mtext>&#x1EE68;</mtext></math>=<span>1EE68</span></span>
+ <span><math><mtext>&#x1EE7A;</mtext></math>=<span>1EE7A</span></span>
+ <span><math><mtext>&#x1EE6F;</mtext></math>=<span>1EE6F</span></span>
+ <span><math><mtext>&#x1EE7B;</mtext></math>=<span>1EE7B</span></span>
+ <span><math><mtext>&#x1EE70;</mtext></math>=<span>1EE70</span></span>
+ <span><math><mtext>&#x1EE72;</mtext></math>=<span>1EE72</span></span>
+ <span><math><mtext>&#x1EE6A;</mtext></math>=<span>1EE6A</span></span>
+ <span><math><mtext>&#x1EE6C;</mtext></math>=<span>1EE6C</span></span>
+ <span><math><mtext>&#x1EE6D;</mtext></math>=<span>1EE6D</span></span><br/>
+ <span><math><mtext>&#x1EE64;</mtext></math>=<span>1EE64</span></span>
+ <span><math><mtext>&#x1EE69;</mtext></math>=<span>1EE69</span></span>
+ <span><math><mtext>&#x1EE7C;</mtext></math>=<span>1EE7C</span></span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-stretched.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-stretched.html
index 4eefff8f9e9..603cfe704fd 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-stretched.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-stretched.html
@@ -5,7 +5,7 @@
<title>mathvariant stretched</title>
<link rel="help" href="http://www.mathml-association.org/MathMLinHTML5/S2.html#SS3.SSS1.tab2"/>
<link rel="match" href="mathvariant-stretched-ref.html"/>
-<meta name="assert" content="Verify that a single-char <mi> with a stretched mathvariant is equivalent to an <mi> with the transformed unicode character.">
+<meta name="assert" content="Verify that a single-char <mtext> with a stretched mathvariant is equivalent to an <mtext> with the transformed unicode character.">
<style>
@font-face {
font-family: TestFont;
@@ -26,28 +26,28 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi mathvariant="stretched">&#x6A1;</mi></math>=<span>1EE7E</span></span>
- <span><math><mi mathvariant="stretched">&#x628;</mi></math>=<span>1EE61</span></span>
- <span><math><mi mathvariant="stretched">&#x62A;</mi></math>=<span>1EE75</span></span>
- <span><math><mi mathvariant="stretched">&#x62B;</mi></math>=<span>1EE76</span></span>
- <span><math><mi mathvariant="stretched">&#x62C;</mi></math>=<span>1EE62</span></span>
- <span><math><mi mathvariant="stretched">&#x62D;</mi></math>=<span>1EE67</span></span>
- <span><math><mi mathvariant="stretched">&#x62E;</mi></math>=<span>1EE77</span></span>
- <span><math><mi mathvariant="stretched">&#x633;</mi></math>=<span>1EE6E</span></span>
- <span><math><mi mathvariant="stretched">&#x634;</mi></math>=<span>1EE74</span></span>
- <span><math><mi mathvariant="stretched">&#x635;</mi></math>=<span>1EE71</span></span><br/>
- <span><math><mi mathvariant="stretched">&#x636;</mi></math>=<span>1EE79</span></span>
- <span><math><mi mathvariant="stretched">&#x637;</mi></math>=<span>1EE68</span></span>
- <span><math><mi mathvariant="stretched">&#x638;</mi></math>=<span>1EE7A</span></span>
- <span><math><mi mathvariant="stretched">&#x639;</mi></math>=<span>1EE6F</span></span>
- <span><math><mi mathvariant="stretched">&#x63A;</mi></math>=<span>1EE7B</span></span>
- <span><math><mi mathvariant="stretched">&#x641;</mi></math>=<span>1EE70</span></span>
- <span><math><mi mathvariant="stretched">&#x642;</mi></math>=<span>1EE72</span></span>
- <span><math><mi mathvariant="stretched">&#x643;</mi></math>=<span>1EE6A</span></span>
- <span><math><mi mathvariant="stretched">&#x645;</mi></math>=<span>1EE6C</span></span>
- <span><math><mi mathvariant="stretched">&#x646;</mi></math>=<span>1EE6D</span></span><br/>
- <span><math><mi mathvariant="stretched">&#x647;</mi></math>=<span>1EE64</span></span>
- <span><math><mi mathvariant="stretched">&#x64A;</mi></math>=<span>1EE69</span></span>
- <span><math><mi mathvariant="stretched">&#x66E;</mi></math>=<span>1EE7C</span></span>
+ <span><math><mtext mathvariant="stretched">&#x6A1;</mtext></math>=<span>1EE7E</span></span>
+ <span><math><mtext mathvariant="stretched">&#x628;</mtext></math>=<span>1EE61</span></span>
+ <span><math><mtext mathvariant="stretched">&#x62A;</mtext></math>=<span>1EE75</span></span>
+ <span><math><mtext mathvariant="stretched">&#x62B;</mtext></math>=<span>1EE76</span></span>
+ <span><math><mtext mathvariant="stretched">&#x62C;</mtext></math>=<span>1EE62</span></span>
+ <span><math><mtext mathvariant="stretched">&#x62D;</mtext></math>=<span>1EE67</span></span>
+ <span><math><mtext mathvariant="stretched">&#x62E;</mtext></math>=<span>1EE77</span></span>
+ <span><math><mtext mathvariant="stretched">&#x633;</mtext></math>=<span>1EE6E</span></span>
+ <span><math><mtext mathvariant="stretched">&#x634;</mtext></math>=<span>1EE74</span></span>
+ <span><math><mtext mathvariant="stretched">&#x635;</mtext></math>=<span>1EE71</span></span><br/>
+ <span><math><mtext mathvariant="stretched">&#x636;</mtext></math>=<span>1EE79</span></span>
+ <span><math><mtext mathvariant="stretched">&#x637;</mtext></math>=<span>1EE68</span></span>
+ <span><math><mtext mathvariant="stretched">&#x638;</mtext></math>=<span>1EE7A</span></span>
+ <span><math><mtext mathvariant="stretched">&#x639;</mtext></math>=<span>1EE6F</span></span>
+ <span><math><mtext mathvariant="stretched">&#x63A;</mtext></math>=<span>1EE7B</span></span>
+ <span><math><mtext mathvariant="stretched">&#x641;</mtext></math>=<span>1EE70</span></span>
+ <span><math><mtext mathvariant="stretched">&#x642;</mtext></math>=<span>1EE72</span></span>
+ <span><math><mtext mathvariant="stretched">&#x643;</mtext></math>=<span>1EE6A</span></span>
+ <span><math><mtext mathvariant="stretched">&#x645;</mtext></math>=<span>1EE6C</span></span>
+ <span><math><mtext mathvariant="stretched">&#x646;</mtext></math>=<span>1EE6D</span></span><br/>
+ <span><math><mtext mathvariant="stretched">&#x647;</mtext></math>=<span>1EE64</span></span>
+ <span><math><mtext mathvariant="stretched">&#x64A;</mtext></math>=<span>1EE69</span></span>
+ <span><math><mtext mathvariant="stretched">&#x66E;</mtext></math>=<span>1EE7C</span></span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-tailed-ref.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-tailed-ref.html
index e53ef329c5f..b8e6160fea5 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-tailed-ref.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-tailed-ref.html
@@ -23,20 +23,20 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi>&#x1EE52;</mi></math>=<span>1EE52</span></span>
- <span><math><mi>&#x1EE4B;</mi></math>=<span>1EE4B</span></span>
- <span><math><mi>&#x1EE4D;</mi></math>=<span>1EE4D</span></span>
- <span><math><mi>&#x1EE49;</mi></math>=<span>1EE49</span></span>
- <span><math><mi>&#x1EE42;</mi></math>=<span>1EE42</span></span>
- <span><math><mi>&#x1EE47;</mi></math>=<span>1EE47</span></span>
- <span><math><mi>&#x1EE57;</mi></math>=<span>1EE57</span></span>
- <span><math><mi>&#x1EE5F;</mi></math>=<span>1EE5F</span></span>
- <span><math><mi>&#x1EE4E;</mi></math>=<span>1EE4E</span></span>
- <span><math><mi>&#x1EE54;</mi></math>=<span>1EE54</span></span><br/>
- <span><math><mi>&#x1EE51;</mi></math>=<span>1EE51</span></span>
- <span><math><mi>&#x1EE59;</mi></math>=<span>1EE59</span></span>
- <span><math><mi>&#x1EE4F;</mi></math>=<span>1EE4F</span></span>
- <span><math><mi>&#x1EE5B;</mi></math>=<span>1EE5B</span></span>
- <span><math><mi>&#x1EE5D;</mi></math>=<span>1EE5D</span></span>
+ <span><math><mtext>&#x1EE52;</mtext></math>=<span>1EE52</span></span>
+ <span><math><mtext>&#x1EE4B;</mtext></math>=<span>1EE4B</span></span>
+ <span><math><mtext>&#x1EE4D;</mtext></math>=<span>1EE4D</span></span>
+ <span><math><mtext>&#x1EE49;</mtext></math>=<span>1EE49</span></span>
+ <span><math><mtext>&#x1EE42;</mtext></math>=<span>1EE42</span></span>
+ <span><math><mtext>&#x1EE47;</mtext></math>=<span>1EE47</span></span>
+ <span><math><mtext>&#x1EE57;</mtext></math>=<span>1EE57</span></span>
+ <span><math><mtext>&#x1EE5F;</mtext></math>=<span>1EE5F</span></span>
+ <span><math><mtext>&#x1EE4E;</mtext></math>=<span>1EE4E</span></span>
+ <span><math><mtext>&#x1EE54;</mtext></math>=<span>1EE54</span></span><br/>
+ <span><math><mtext>&#x1EE51;</mtext></math>=<span>1EE51</span></span>
+ <span><math><mtext>&#x1EE59;</mtext></math>=<span>1EE59</span></span>
+ <span><math><mtext>&#x1EE4F;</mtext></math>=<span>1EE4F</span></span>
+ <span><math><mtext>&#x1EE5B;</mtext></math>=<span>1EE5B</span></span>
+ <span><math><mtext>&#x1EE5D;</mtext></math>=<span>1EE5D</span></span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-tailed.html b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-tailed.html
index b8ae7ea021f..c00417d8d6a 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-tailed.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/css-styling/mathvariant-tailed.html
@@ -5,7 +5,7 @@
<title>mathvariant tailed</title>
<link rel="help" href="http://www.mathml-association.org/MathMLinHTML5/S2.html#SS3.SSS1.tab2"/>
<link rel="match" href="mathvariant-tailed-ref.html"/>
-<meta name="assert" content="Verify that a single-char <mi> with a tailed mathvariant is equivalent to an <mi> with the transformed unicode character.">
+<meta name="assert" content="Verify that a single-char <mtext> with a tailed mathvariant is equivalent to an <mtext> with the transformed unicode character.">
<style>
@font-face {
font-family: TestFont;
@@ -26,20 +26,20 @@
<body>
<!-- Generated by mathml/tools/mathvariant.py; DO NOT EDIT. -->
<p>Test passes if all the equalities below are true.</p>
- <span><math><mi mathvariant="tailed">&#x642;</mi></math>=<span>1EE52</span></span>
- <span><math><mi mathvariant="tailed">&#x644;</mi></math>=<span>1EE4B</span></span>
- <span><math><mi mathvariant="tailed">&#x646;</mi></math>=<span>1EE4D</span></span>
- <span><math><mi mathvariant="tailed">&#x64A;</mi></math>=<span>1EE49</span></span>
- <span><math><mi mathvariant="tailed">&#x62C;</mi></math>=<span>1EE42</span></span>
- <span><math><mi mathvariant="tailed">&#x62D;</mi></math>=<span>1EE47</span></span>
- <span><math><mi mathvariant="tailed">&#x62E;</mi></math>=<span>1EE57</span></span>
- <span><math><mi mathvariant="tailed">&#x66F;</mi></math>=<span>1EE5F</span></span>
- <span><math><mi mathvariant="tailed">&#x633;</mi></math>=<span>1EE4E</span></span>
- <span><math><mi mathvariant="tailed">&#x634;</mi></math>=<span>1EE54</span></span><br/>
- <span><math><mi mathvariant="tailed">&#x635;</mi></math>=<span>1EE51</span></span>
- <span><math><mi mathvariant="tailed">&#x636;</mi></math>=<span>1EE59</span></span>
- <span><math><mi mathvariant="tailed">&#x639;</mi></math>=<span>1EE4F</span></span>
- <span><math><mi mathvariant="tailed">&#x63A;</mi></math>=<span>1EE5B</span></span>
- <span><math><mi mathvariant="tailed">&#x6BA;</mi></math>=<span>1EE5D</span></span>
+ <span><math><mtext mathvariant="tailed">&#x642;</mtext></math>=<span>1EE52</span></span>
+ <span><math><mtext mathvariant="tailed">&#x644;</mtext></math>=<span>1EE4B</span></span>
+ <span><math><mtext mathvariant="tailed">&#x646;</mtext></math>=<span>1EE4D</span></span>
+ <span><math><mtext mathvariant="tailed">&#x64A;</mtext></math>=<span>1EE49</span></span>
+ <span><math><mtext mathvariant="tailed">&#x62C;</mtext></math>=<span>1EE42</span></span>
+ <span><math><mtext mathvariant="tailed">&#x62D;</mtext></math>=<span>1EE47</span></span>
+ <span><math><mtext mathvariant="tailed">&#x62E;</mtext></math>=<span>1EE57</span></span>
+ <span><math><mtext mathvariant="tailed">&#x66F;</mtext></math>=<span>1EE5F</span></span>
+ <span><math><mtext mathvariant="tailed">&#x633;</mtext></math>=<span>1EE4E</span></span>
+ <span><math><mtext mathvariant="tailed">&#x634;</mtext></math>=<span>1EE54</span></span><br/>
+ <span><math><mtext mathvariant="tailed">&#x635;</mtext></math>=<span>1EE51</span></span>
+ <span><math><mtext mathvariant="tailed">&#x636;</mtext></math>=<span>1EE59</span></span>
+ <span><math><mtext mathvariant="tailed">&#x639;</mtext></math>=<span>1EE4F</span></span>
+ <span><math><mtext mathvariant="tailed">&#x63A;</mtext></math>=<span>1EE5B</span></span>
+ <span><math><mtext mathvariant="tailed">&#x6BA;</mtext></math>=<span>1EE5D</span></span>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/html5-tree/unique-identifier-1-iframe.html b/tests/wpt/web-platform-tests/mathml/relations/html5-tree/unique-identifier-1-iframe-1.html
index 6b3ab07f1aa..6b3ab07f1aa 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/html5-tree/unique-identifier-1-iframe.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/html5-tree/unique-identifier-1-iframe-1.html
diff --git a/tests/wpt/web-platform-tests/mathml/relations/html5-tree/unique-identifier-1-ref-iframe.html b/tests/wpt/web-platform-tests/mathml/relations/html5-tree/unique-identifier-1-iframe-2.html
index ade0110a27e..ade0110a27e 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/html5-tree/unique-identifier-1-ref-iframe.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/html5-tree/unique-identifier-1-iframe-2.html
diff --git a/tests/wpt/web-platform-tests/mathml/relations/html5-tree/unique-identifier-1-ref.html b/tests/wpt/web-platform-tests/mathml/relations/html5-tree/unique-identifier-1-ref.html
index 575a27a25ee..a219b2c870a 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/html5-tree/unique-identifier-1-ref.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/html5-tree/unique-identifier-1-ref.html
@@ -10,7 +10,7 @@
<iframe width="100" height="100" frameborder="0" scrolling="no"
marginheight="0" marginwidth="0"
- src="unique-identifier-1-ref-iframe.html#PASS"></iframe>
+ src="unique-identifier-1-iframe-2.html#PASS"></iframe>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/relations/html5-tree/unique-identifier-1.html b/tests/wpt/web-platform-tests/mathml/relations/html5-tree/unique-identifier-1.html
index 357e99229e9..39c49a6b56b 100644
--- a/tests/wpt/web-platform-tests/mathml/relations/html5-tree/unique-identifier-1.html
+++ b/tests/wpt/web-platform-tests/mathml/relations/html5-tree/unique-identifier-1.html
@@ -13,7 +13,7 @@
<iframe width="100" height="100" frameborder="0" scrolling="no"
marginheight="0" marginwidth="0"
- src="unique-identifier-1-iframe.html#PASS"></iframe>
+ src="unique-identifier-1-iframe-1.html#PASS"></iframe>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/mathml/tools/mathvariant-transforms.py b/tests/wpt/web-platform-tests/mathml/tools/mathvariant-transforms.py
index ede678cc1df..6094a74491d 100644
--- a/tests/wpt/web-platform-tests/mathml/tools/mathvariant-transforms.py
+++ b/tests/wpt/web-platform-tests/mathml/tools/mathvariant-transforms.py
@@ -83,7 +83,7 @@ for mathvariant in mathvariantTransforms:
source ='\
<link rel="help" href="http://www.mathml-association.org/MathMLinHTML5/S2.html#SS3.SSS1.tab2"/>\n\
<link rel="match" href="mathvariant-%s-ref.html"/>\n\
-<meta name="assert" content="Verify that a single-char <mi> with a %s mathvariant is equivalent to an <mi> with the transformed unicode character.">\n'
+<meta name="assert" content="Verify that a single-char <mtext> with a %s mathvariant is equivalent to an <mtext> with the transformed unicode character.">\n'
reftest.write(source % (mathvariant, mathvariant))
source = '\
<style>\n\
@@ -111,8 +111,8 @@ for mathvariant in mathvariantTransforms:
charIndex = 0
for baseChar in mathvariantTransforms[mathvariant]:
transformedChar = mathvariantTransforms[mathvariant][baseChar]
- reftest.write(' <span><math><mi mathvariant="%s">&#x%0X;</mi></math>=<span>%05X</span></span>' % (mathvariant, baseChar, transformedChar))
- reftestReference.write(' <span><math><mi>&#x%0X;</mi></math>=<span>%05X</span></span>' % (transformedChar, transformedChar))
+ reftest.write(' <span><math><mtext mathvariant="%s">&#x%0X;</mtext></math>=<span>%05X</span></span>' % (mathvariant, baseChar, transformedChar))
+ reftestReference.write(' <span><math><mtext>&#x%0X;</mtext></math>=<span>%05X</span></span>' % (transformedChar, transformedChar))
charIndex += 1
if charIndex % 10 == 0:
reftest.write('<br/>')
diff --git a/tests/wpt/web-platform-tests/media-capabilities/decodingInfo.html b/tests/wpt/web-platform-tests/media-capabilities/decodingInfo.html
index 85acfe7f613..f3fca4184e4 100644
--- a/tests/wpt/web-platform-tests/media-capabilities/decodingInfo.html
+++ b/tests/wpt/web-platform-tests/media-capabilities/decodingInfo.html
@@ -7,7 +7,7 @@
// Minimal VideoConfiguration that will be allowed per spec. All optional
// properties are missing.
var minimalVideoConfiguration = {
- contentType: 'video/webm; codecs="vp9"',
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
width: 800,
height: 600,
bitrate: 3000,
@@ -45,7 +45,7 @@ promise_test(t => {
return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
type: 'file',
video: {
- contentType: 'video/webm; codecs="vp9"',
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
width: 800,
height: 600,
bitrate: 3000,
@@ -58,7 +58,7 @@ promise_test(t => {
return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
type: 'file',
video: {
- contentType: 'video/webm; codecs="vp9"',
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
width: 800,
height: 600,
bitrate: 3000,
@@ -71,7 +71,7 @@ promise_test(t => {
return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
type: 'file',
video: {
- contentType: 'video/webm; codecs="vp9"',
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
width: 800,
height: 600,
bitrate: 3000,
@@ -110,7 +110,7 @@ promise_test(t => {
return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
type: 'file',
video: {
- contentType: 'video/webm; codecs="vp9"; foo="bar"',
+ contentType: 'video/webm; codecs="vp09.00.10.08"; foo="bar"',
width: 800,
height: 600,
bitrate: 3000,
@@ -133,6 +133,123 @@ promise_test(t => {
}, "Test that decodingInfo rejects if the video configuration contentType has one parameter that isn't codecs");
promise_test(t => {
+ return navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: '24000/1001',
+ }
+ });
+}, "Test that decodingInfo() accepts framerate in the form of x/y");
+
+promise_test(t => {
+ return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: '24000/0',
+ }
+ }));
+}, "Test that decodingInfo() rejects framerate in the form of x/0");
+
+promise_test(t => {
+ return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: '0/10001',
+ }
+ }));
+}, "Test that decodingInfo() rejects framerate in the form of 0/y");
+
+promise_test(t => {
+ return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: '-24000/10001',
+ }
+ }));
+}, "Test that decodingInfo() rejects framerate in the form of -x/y");
+
+promise_test(t => {
+ return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: '24000/-10001',
+ }
+ }));
+}, "Test that decodingInfo() rejects framerate in the form of x/-y");
+
+promise_test(t => {
+ return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: '24000/',
+ }
+ }));
+}, "Test that decodingInfo() rejects framerate in the form of x/");
+
+promise_test(t => {
+ return navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: '24000/1e4',
+ }
+ });
+}, "Test that decodingInfo() accepts framerate with 'e'");
+
+promise_test(t => {
+ return navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: '24/1.0001',
+ }
+ });
+}, "Test that decodingInfo() accepts framerate as fraction with decimals");
+
+promise_test(t => {
+ return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
+ type: 'file',
+ video: {
+ contentType: 'video/webm; codecs="vp09.00.10.08"',
+ width: 800,
+ height: 600,
+ bitrate: 3000,
+ framerate: '1/3x',
+ }
+ }));
+}, "Test that decodingInfo() rejects framerate with trailing unallowed characters");
+
+promise_test(t => {
return promise_rejects(t, new TypeError(), navigator.mediaCapabilities.decodingInfo({
type: 'file',
audio: { contentType: 'fgeoa' },
diff --git a/tests/wpt/web-platform-tests/media-capabilities/idlharness.html b/tests/wpt/web-platform-tests/media-capabilities/idlharness.html
index 3efe5a64488..c4b0b99f88f 100644
--- a/tests/wpt/web-platform-tests/media-capabilities/idlharness.html
+++ b/tests/wpt/web-platform-tests/media-capabilities/idlharness.html
@@ -12,7 +12,7 @@
<body>
<h1>Media Session IDL tests</h1>
<pre id='untested_idl' style='display:none'>
-[PrimaryGlobal]
+[Global=Window, Exposed=Window]
interface Window {
};
interface Worker {
diff --git a/tests/wpt/web-platform-tests/media/counting.mp4 b/tests/wpt/web-platform-tests/media/counting.mp4
new file mode 100644
index 00000000000..5fbd6d97f31
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media/counting.mp4
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media/counting.ogv b/tests/wpt/web-platform-tests/media/counting.ogv
new file mode 100644
index 00000000000..ce03c19e50e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media/counting.ogv
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media/test.mp4 b/tests/wpt/web-platform-tests/media/test.mp4
new file mode 100644
index 00000000000..d278c8ad8cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media/test.mp4
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media/test.ogv b/tests/wpt/web-platform-tests/media/test.ogv
new file mode 100644
index 00000000000..0c55f6c7226
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media/test.ogv
Binary files differ
diff --git a/tests/wpt/web-platform-tests/mediacapture-fromelement/capture.html b/tests/wpt/web-platform-tests/mediacapture-fromelement/capture.html
index 64012687d31..cf6168ba17f 100644
--- a/tests/wpt/web-platform-tests/mediacapture-fromelement/capture.html
+++ b/tests/wpt/web-platform-tests/mediacapture-fromelement/capture.html
@@ -3,10 +3,6 @@
<head>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
-<script src="/common/vendor-prefix.js"
- data-prefixed-prototypes=
- '[{"ancestors":["HTMLMediaElement"],"name":"captureStream"}]'>
-</script>
</head>
<body>
<script>
diff --git a/tests/wpt/web-platform-tests/mediacapture-fromelement/creation.html b/tests/wpt/web-platform-tests/mediacapture-fromelement/creation.html
index 94a22f14729..338611ac078 100644
--- a/tests/wpt/web-platform-tests/mediacapture-fromelement/creation.html
+++ b/tests/wpt/web-platform-tests/mediacapture-fromelement/creation.html
@@ -3,10 +3,6 @@
<head>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
-<script src="/common/vendor-prefix.js"
- data-prefixed-prototypes=
- '[{"ancestors":["HTMLMediaElement"],"name":"captureStream"}]'>
-</script>
</head>
<body>
<script>
@@ -20,6 +16,8 @@ var makeAsyncTest = function(filename, numTracks) {
video.onerror = this.unreached_func("<video> error");
video.play();
+ assert_true('captureStream' in video);
+
var stream = video.captureStream();
assert_not_equals(stream, null, "error generating stream");
diff --git a/tests/wpt/web-platform-tests/mediacapture-fromelement/ended.html b/tests/wpt/web-platform-tests/mediacapture-fromelement/ended.html
index da1451b7d80..845fbcbaa6e 100644
--- a/tests/wpt/web-platform-tests/mediacapture-fromelement/ended.html
+++ b/tests/wpt/web-platform-tests/mediacapture-fromelement/ended.html
@@ -3,10 +3,6 @@
<head>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
-<script src="/common/vendor-prefix.js"
- data-prefixed-prototypes=
- '[{"ancestors":["HTMLMediaElement"],"name":"captureStream"}]'>
-</script>
</head>
<body>
<script>
@@ -21,6 +17,8 @@ var makeAsyncTest = function(filename) {
video.onerror = this.unreached_func("<video> error");
video.play();
+ assert_true('captureStream' in video);
+
var stream = video.captureStream();
stream.onremovetrack = this.step_func_done(function() {
diff --git a/tests/wpt/web-platform-tests/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-video-is-black.https.html b/tests/wpt/web-platform-tests/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-video-is-black.https.html
index 8aee8e2bf12..9f44a34104a 100644
--- a/tests/wpt/web-platform-tests/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-video-is-black.https.html
+++ b/tests/wpt/web-platform-tests/mediacapture-streams/MediaStreamTrack-MediaElement-disabled-video-is-black.https.html
@@ -46,7 +46,7 @@ t.step(function() {
vid.srcObject = stream;
vid.play();
vid.addEventListener("loadeddata", testOnceLoadeddata, false);
- })));
+ }));
});
</script>
</body>
diff --git a/tests/wpt/web-platform-tests/mediasession/idlharness.html b/tests/wpt/web-platform-tests/mediasession/idlharness.html
index a90c83e8319..4991404bb8f 100644
--- a/tests/wpt/web-platform-tests/mediasession/idlharness.html
+++ b/tests/wpt/web-platform-tests/mediasession/idlharness.html
@@ -13,7 +13,7 @@
<h1>Media Session IDL tests</h1>
<pre id='untested_idl' style='display:none'>
-[PrimaryGlobal]
+[Global=Window, Exposed=Global]
interface Window {
};
diff --git a/tests/wpt/web-platform-tests/mimesniff/OWNERS b/tests/wpt/web-platform-tests/mimesniff/OWNERS
new file mode 100644
index 00000000000..e3fa6b69568
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mimesniff/OWNERS
@@ -0,0 +1 @@
+@annevk
diff --git a/tests/wpt/web-platform-tests/mimesniff/README.md b/tests/wpt/web-platform-tests/mimesniff/README.md
new file mode 100644
index 00000000000..80834312243
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mimesniff/README.md
@@ -0,0 +1 @@
+Tests for the [MIME Sniffing Standard](https://mimesniff.spec.whatwg.org/).
diff --git a/tests/wpt/web-platform-tests/mimesniff/mime-types/README.md b/tests/wpt/web-platform-tests/mimesniff/mime-types/README.md
new file mode 100644
index 00000000000..b0b1fbfd211
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mimesniff/mime-types/README.md
@@ -0,0 +1,34 @@
+== MIME types ==
+
+`resources/mime-types.json` and `resources/generated-mime-types.json` contain MIME type tests. The tests are encoded as a JSON array. String values in the array serve as documentation. All other values are objects with the following fields:
+
+* `input`: The string to be parsed.
+* `output`: Null if parsing resulted in failure and the MIME type record serialized as string otherwise.
+* `navigable`: True if the MIME type can be used for a document to be loaded in a browsing context (i.e., does not result in a download) and omitted otherwise.
+* `encoding`: The encoding that can be extracted from the MIME type or null if no encoding can be extracted, and omitted otherwise.
+
+Note: the object description implies that there tests without `navigable` or `encoding` set.
+
+A wrapper for these JSON MIME type tests needs to take care that not all `input` values can be tested in all entrypoints. Some entrypoints only accept bytes and some have further restrictions. A function such as the one below can be used to differentiate:
+
+```js
+function isByteCompatible(str) {
+ for(let i = 0; i < str.length; i++) {
+ const charCode = str.charCodeAt(i);
+ // See https://github.com/w3c/web-platform-tests/issues/8372 for 0x0B and 0x0C
+ // See https://fetch.spec.whatwg.org/#concept-header-value for the remainder
+ if(charCode > 0xFF) {
+ return "incompatible";
+ } else if(charCode === 0x00 || charCode === 0x0A || charCode === 0x0D) {
+ return "header-value-incompatible";
+ } else if(charCode === 0x0B || charCode === 0x0C) {
+ return "wptserve-incompatible";
+ }
+ }
+ return "compatible";
+}
+```
+
+`resources/generated-mime-types.json` is generated by running `resources/generated-mime-types.py`. Modify the latter to correct the former.
+
+These tests are used by resources in this directory to test various aspects of MIME types.
diff --git a/tests/wpt/web-platform-tests/mimesniff/mime-types/charset-parameter.window.js b/tests/wpt/web-platform-tests/mimesniff/mime-types/charset-parameter.window.js
new file mode 100644
index 00000000000..7b4e94669b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mimesniff/mime-types/charset-parameter.window.js
@@ -0,0 +1,57 @@
+promise_test(() => {
+ // Don't load generated-mime-types.json as none of them are navigable
+ return fetch("resources/mime-types.json").then(res => res.json().then(runTests));
+}, "Loading data…");
+
+function isByteCompatible(str) {
+ for(let i = 0; i < str.length; i++) {
+ const charCode = str.charCodeAt(i);
+ // See https://github.com/w3c/web-platform-tests/issues/8372 for 0x0B and 0x0C
+ // See https://fetch.spec.whatwg.org/#concept-header-value for the remainder
+ if(charCode > 0xFF) {
+ return "incompatible";
+ } else if(charCode === 0x00 || charCode === 0x0A || charCode === 0x0D) {
+ return "header-value-incompatible";
+ } else if(charCode === 0x0B || charCode === 0x0C) {
+ return "wptserve-incompatible";
+ }
+ }
+ return "compatible";
+}
+
+function encodeForURL(str) {
+ let output = "";
+ for(let i = 0; i < str.length; i++) {
+ const char = str.charCodeAt(i);
+ if(char > 0xFF) {
+ throw new Error("We cannot deal with input that is not latin1");
+ } else {
+ output += "%" + char.toString(16).padStart(2, "0");
+ }
+ }
+ return output;
+}
+
+function runTests(tests) {
+ tests.forEach(val => {
+ if(typeof val === "string" || val.navigable === undefined || val.encoding === undefined || isByteCompatible(val.input) !== "compatible") {
+ return;
+ }
+ const mime = val.input;
+ async_test(t => {
+ const frame = document.createElement("iframe"),
+ expectedEncoding = val.encoding === null ? "UTF-8" : val.encoding;
+ t.add_cleanup(() => frame.remove());
+ frame.onload = t.step_func(() => {
+ if(frame.contentWindow.location.href === "about:blank") {
+ return;
+ }
+ // Edge fails all these tests due to not using the correct encoding label.
+ assert_equals(frame.contentDocument.characterSet, expectedEncoding);
+ t.done();
+ });
+ frame.src = "resources/mime-charset.py?type=" + encodeForURL(mime);
+ document.body.appendChild(frame);
+ }, mime);
+ });
+}
diff --git a/tests/wpt/web-platform-tests/mimesniff/mime-types/parsing.any.js b/tests/wpt/web-platform-tests/mimesniff/mime-types/parsing.any.js
new file mode 100644
index 00000000000..bd9a62e433a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mimesniff/mime-types/parsing.any.js
@@ -0,0 +1,51 @@
+// META: timeout=long
+
+promise_test(() => {
+ return Promise.all([
+ fetch("resources/mime-types.json"),
+ fetch("resources/generated-mime-types.json")
+ ]).then(([res, res2]) => res.json().then(runTests).then(() => res2.json().then(runTests)));
+}, "Loading data…");
+
+function isByteCompatible(str) {
+ for(let i = 0; i < str.length; i++) {
+ const charCode = str.charCodeAt(i);
+ // See https://github.com/w3c/web-platform-tests/issues/8372 for 0x0B and 0x0C
+ // See https://fetch.spec.whatwg.org/#concept-header-value for the remainder
+ if(charCode > 0xFF) {
+ return "incompatible";
+ } else if(charCode === 0x00 || charCode === 0x0A || charCode === 0x0D) {
+ return "header-value-incompatible";
+ } else if(charCode === 0x0B || charCode === 0x0C) {
+ return "wptserve-incompatible";
+ }
+ }
+ return "compatible";
+}
+
+function runTests(tests) {
+ tests.forEach(val => {
+ if(typeof val === "string") {
+ return;
+ }
+ const output = val.output === null ? "" : val.output
+ test(() => {
+ assert_equals(new Blob([], { type: val.input}).type, output, "Blob");
+ assert_equals(new File([], "noname", { type: val.input}).type, output, "File");
+ }, val.input + " (Blob/File)");
+
+ promise_test(() => {
+ const compatibleNess = isByteCompatible(val.input);
+ if(compatibleNess === "incompatible" || compatibleNess === "header-value-incompatible") {
+ assert_throws(new TypeError(), () => new Request("about:blank", { headers: [["Content-Type", val.input]] }));
+ assert_throws(new TypeError(), () => new Response(null, { headers: [["Content-Type", val.input]] }));
+ return Promise.resolve();
+ } else {
+ return Promise.all([
+ new Request("about:blank", { headers: [["Content-Type", val.input]] }).blob().then(blob => assert_equals(blob.type, output)),
+ new Response(null, { headers: [["Content-Type", val.input]] }).blob().then(blob => assert_equals(blob.type, output))
+ ]);
+ }
+ }, val.input + " (Request/Response)");
+ });
+}
diff --git a/tests/wpt/web-platform-tests/mimesniff/mime-types/resources/generated-mime-types.json b/tests/wpt/web-platform-tests/mimesniff/mime-types/resources/generated-mime-types.json
new file mode 100644
index 00000000000..f8934da46a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mimesniff/mime-types/resources/generated-mime-types.json
@@ -0,0 +1,3526 @@
+[
+ {
+ "input": "\u0000/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0000",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0000=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0000;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0000\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u0001/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0001",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0001=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0001;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0001\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u0002/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0002",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0002=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0002;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0002\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u0003/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0003",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0003=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0003;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0003\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u0004/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0004",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0004=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0004;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0004\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u0005/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0005",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0005=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0005;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0005\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u0006/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0006",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0006=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0006;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0006\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u0007/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0007",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0007=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0007;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0007\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\b/x",
+ "output": null
+ },
+ {
+ "input": "x/\b",
+ "output": null
+ },
+ {
+ "input": "x/x;\b=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\b;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\b\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\t/x",
+ "output": null
+ },
+ {
+ "input": "x/\t",
+ "output": null
+ },
+ {
+ "input": "x/x;\t=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\n/x",
+ "output": null
+ },
+ {
+ "input": "x/\n",
+ "output": null
+ },
+ {
+ "input": "x/x;\n=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\n;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\n\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u000b/x",
+ "output": null
+ },
+ {
+ "input": "x/\u000b",
+ "output": null
+ },
+ {
+ "input": "x/x;\u000b=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u000b;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u000b\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\f/x",
+ "output": null
+ },
+ {
+ "input": "x/\f",
+ "output": null
+ },
+ {
+ "input": "x/x;\f=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\f;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\f\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\r/x",
+ "output": null
+ },
+ {
+ "input": "x/\r",
+ "output": null
+ },
+ {
+ "input": "x/x;\r=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\r;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\r\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u000e/x",
+ "output": null
+ },
+ {
+ "input": "x/\u000e",
+ "output": null
+ },
+ {
+ "input": "x/x;\u000e=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u000e;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u000e\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u000f/x",
+ "output": null
+ },
+ {
+ "input": "x/\u000f",
+ "output": null
+ },
+ {
+ "input": "x/x;\u000f=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u000f;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u000f\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u0010/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0010",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0010=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0010;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0010\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u0011/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0011",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0011=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0011;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0011\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u0012/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0012",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0012=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0012;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0012\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u0013/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0013",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0013=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0013;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0013\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u0014/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0014",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0014=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0014;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0014\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u0015/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0015",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0015=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0015;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0015\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u0016/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0016",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0016=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0016;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0016\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u0017/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0017",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0017=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0017;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0017\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u0018/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0018",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0018=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0018;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0018\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u0019/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0019",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0019=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0019;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0019\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u001a/x",
+ "output": null
+ },
+ {
+ "input": "x/\u001a",
+ "output": null
+ },
+ {
+ "input": "x/x;\u001a=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u001a;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u001a\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u001b/x",
+ "output": null
+ },
+ {
+ "input": "x/\u001b",
+ "output": null
+ },
+ {
+ "input": "x/x;\u001b=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u001b;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u001b\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u001c/x",
+ "output": null
+ },
+ {
+ "input": "x/\u001c",
+ "output": null
+ },
+ {
+ "input": "x/x;\u001c=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u001c;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u001c\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u001d/x",
+ "output": null
+ },
+ {
+ "input": "x/\u001d",
+ "output": null
+ },
+ {
+ "input": "x/x;\u001d=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u001d;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u001d\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u001e/x",
+ "output": null
+ },
+ {
+ "input": "x/\u001e",
+ "output": null
+ },
+ {
+ "input": "x/x;\u001e=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u001e;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u001e\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u001f/x",
+ "output": null
+ },
+ {
+ "input": "x/\u001f",
+ "output": null
+ },
+ {
+ "input": "x/x;\u001f=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u001f;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u001f\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": " /x",
+ "output": null
+ },
+ {
+ "input": "x/ ",
+ "output": null
+ },
+ {
+ "input": "x/x; =x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\"/x",
+ "output": null
+ },
+ {
+ "input": "x/\"",
+ "output": null
+ },
+ {
+ "input": "x/x;\"=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "(/x",
+ "output": null
+ },
+ {
+ "input": "x/(",
+ "output": null
+ },
+ {
+ "input": "x/x;(=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=(;bonus=x",
+ "output": "x/x;x=\"(\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"(\";bonus=x",
+ "output": "x/x;x=\"(\";bonus=x"
+ },
+ {
+ "input": ")/x",
+ "output": null
+ },
+ {
+ "input": "x/)",
+ "output": null
+ },
+ {
+ "input": "x/x;)=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=);bonus=x",
+ "output": "x/x;x=\")\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\")\";bonus=x",
+ "output": "x/x;x=\")\";bonus=x"
+ },
+ {
+ "input": ",/x",
+ "output": null
+ },
+ {
+ "input": "x/,",
+ "output": null
+ },
+ {
+ "input": "x/x;,=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=,;bonus=x",
+ "output": "x/x;x=\",\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\",\";bonus=x",
+ "output": "x/x;x=\",\";bonus=x"
+ },
+ {
+ "input": "x/x;/=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=/;bonus=x",
+ "output": "x/x;x=\"/\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"/\";bonus=x",
+ "output": "x/x;x=\"/\";bonus=x"
+ },
+ {
+ "input": ":/x",
+ "output": null
+ },
+ {
+ "input": "x/:",
+ "output": null
+ },
+ {
+ "input": "x/x;:=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=:;bonus=x",
+ "output": "x/x;x=\":\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\":\";bonus=x",
+ "output": "x/x;x=\":\";bonus=x"
+ },
+ {
+ "input": ";/x",
+ "output": null
+ },
+ {
+ "input": "x/;",
+ "output": null
+ },
+ {
+ "input": "</x",
+ "output": null
+ },
+ {
+ "input": "x/<",
+ "output": null
+ },
+ {
+ "input": "x/x;<=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=<;bonus=x",
+ "output": "x/x;x=\"<\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"<\";bonus=x",
+ "output": "x/x;x=\"<\";bonus=x"
+ },
+ {
+ "input": "=/x",
+ "output": null
+ },
+ {
+ "input": "x/=",
+ "output": null
+ },
+ {
+ "input": "x/x;x==;bonus=x",
+ "output": "x/x;x=\"=\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"=\";bonus=x",
+ "output": "x/x;x=\"=\";bonus=x"
+ },
+ {
+ "input": ">/x",
+ "output": null
+ },
+ {
+ "input": "x/>",
+ "output": null
+ },
+ {
+ "input": "x/x;>=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=>;bonus=x",
+ "output": "x/x;x=\">\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\">\";bonus=x",
+ "output": "x/x;x=\">\";bonus=x"
+ },
+ {
+ "input": "?/x",
+ "output": null
+ },
+ {
+ "input": "x/?",
+ "output": null
+ },
+ {
+ "input": "x/x;?=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=?;bonus=x",
+ "output": "x/x;x=\"?\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"?\";bonus=x",
+ "output": "x/x;x=\"?\";bonus=x"
+ },
+ {
+ "input": "@/x",
+ "output": null
+ },
+ {
+ "input": "x/@",
+ "output": null
+ },
+ {
+ "input": "x/x;@=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=@;bonus=x",
+ "output": "x/x;x=\"@\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"@\";bonus=x",
+ "output": "x/x;x=\"@\";bonus=x"
+ },
+ {
+ "input": "[/x",
+ "output": null
+ },
+ {
+ "input": "x/[",
+ "output": null
+ },
+ {
+ "input": "x/x;[=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=[;bonus=x",
+ "output": "x/x;x=\"[\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"[\";bonus=x",
+ "output": "x/x;x=\"[\";bonus=x"
+ },
+ {
+ "input": "\\/x",
+ "output": null
+ },
+ {
+ "input": "x/\\",
+ "output": null
+ },
+ {
+ "input": "x/x;\\=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "]/x",
+ "output": null
+ },
+ {
+ "input": "x/]",
+ "output": null
+ },
+ {
+ "input": "x/x;]=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=];bonus=x",
+ "output": "x/x;x=\"]\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"]\";bonus=x",
+ "output": "x/x;x=\"]\";bonus=x"
+ },
+ {
+ "input": "{/x",
+ "output": null
+ },
+ {
+ "input": "x/{",
+ "output": null
+ },
+ {
+ "input": "x/x;{=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x={;bonus=x",
+ "output": "x/x;x=\"{\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"{\";bonus=x",
+ "output": "x/x;x=\"{\";bonus=x"
+ },
+ {
+ "input": "}/x",
+ "output": null
+ },
+ {
+ "input": "x/}",
+ "output": null
+ },
+ {
+ "input": "x/x;}=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=};bonus=x",
+ "output": "x/x;x=\"}\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"}\";bonus=x",
+ "output": "x/x;x=\"}\";bonus=x"
+ },
+ {
+ "input": "\u007f/x",
+ "output": null
+ },
+ {
+ "input": "x/\u007f",
+ "output": null
+ },
+ {
+ "input": "x/x;\u007f=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u007f;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u007f\";bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "\u0080/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0080",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0080=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0080;bonus=x",
+ "output": "x/x;x=\"\u0080\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0080\";bonus=x",
+ "output": "x/x;x=\"\u0080\";bonus=x"
+ },
+ {
+ "input": "\u0081/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0081",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0081=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0081;bonus=x",
+ "output": "x/x;x=\"\u0081\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0081\";bonus=x",
+ "output": "x/x;x=\"\u0081\";bonus=x"
+ },
+ {
+ "input": "\u0082/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0082",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0082=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0082;bonus=x",
+ "output": "x/x;x=\"\u0082\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0082\";bonus=x",
+ "output": "x/x;x=\"\u0082\";bonus=x"
+ },
+ {
+ "input": "\u0083/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0083",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0083=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0083;bonus=x",
+ "output": "x/x;x=\"\u0083\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0083\";bonus=x",
+ "output": "x/x;x=\"\u0083\";bonus=x"
+ },
+ {
+ "input": "\u0084/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0084",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0084=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0084;bonus=x",
+ "output": "x/x;x=\"\u0084\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0084\";bonus=x",
+ "output": "x/x;x=\"\u0084\";bonus=x"
+ },
+ {
+ "input": "\u0085/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0085",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0085=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0085;bonus=x",
+ "output": "x/x;x=\"\u0085\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0085\";bonus=x",
+ "output": "x/x;x=\"\u0085\";bonus=x"
+ },
+ {
+ "input": "\u0086/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0086",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0086=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0086;bonus=x",
+ "output": "x/x;x=\"\u0086\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0086\";bonus=x",
+ "output": "x/x;x=\"\u0086\";bonus=x"
+ },
+ {
+ "input": "\u0087/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0087",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0087=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0087;bonus=x",
+ "output": "x/x;x=\"\u0087\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0087\";bonus=x",
+ "output": "x/x;x=\"\u0087\";bonus=x"
+ },
+ {
+ "input": "\u0088/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0088",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0088=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0088;bonus=x",
+ "output": "x/x;x=\"\u0088\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0088\";bonus=x",
+ "output": "x/x;x=\"\u0088\";bonus=x"
+ },
+ {
+ "input": "\u0089/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0089",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0089=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0089;bonus=x",
+ "output": "x/x;x=\"\u0089\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0089\";bonus=x",
+ "output": "x/x;x=\"\u0089\";bonus=x"
+ },
+ {
+ "input": "\u008a/x",
+ "output": null
+ },
+ {
+ "input": "x/\u008a",
+ "output": null
+ },
+ {
+ "input": "x/x;\u008a=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u008a;bonus=x",
+ "output": "x/x;x=\"\u008a\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u008a\";bonus=x",
+ "output": "x/x;x=\"\u008a\";bonus=x"
+ },
+ {
+ "input": "\u008b/x",
+ "output": null
+ },
+ {
+ "input": "x/\u008b",
+ "output": null
+ },
+ {
+ "input": "x/x;\u008b=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u008b;bonus=x",
+ "output": "x/x;x=\"\u008b\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u008b\";bonus=x",
+ "output": "x/x;x=\"\u008b\";bonus=x"
+ },
+ {
+ "input": "\u008c/x",
+ "output": null
+ },
+ {
+ "input": "x/\u008c",
+ "output": null
+ },
+ {
+ "input": "x/x;\u008c=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u008c;bonus=x",
+ "output": "x/x;x=\"\u008c\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u008c\";bonus=x",
+ "output": "x/x;x=\"\u008c\";bonus=x"
+ },
+ {
+ "input": "\u008d/x",
+ "output": null
+ },
+ {
+ "input": "x/\u008d",
+ "output": null
+ },
+ {
+ "input": "x/x;\u008d=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u008d;bonus=x",
+ "output": "x/x;x=\"\u008d\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u008d\";bonus=x",
+ "output": "x/x;x=\"\u008d\";bonus=x"
+ },
+ {
+ "input": "\u008e/x",
+ "output": null
+ },
+ {
+ "input": "x/\u008e",
+ "output": null
+ },
+ {
+ "input": "x/x;\u008e=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u008e;bonus=x",
+ "output": "x/x;x=\"\u008e\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u008e\";bonus=x",
+ "output": "x/x;x=\"\u008e\";bonus=x"
+ },
+ {
+ "input": "\u008f/x",
+ "output": null
+ },
+ {
+ "input": "x/\u008f",
+ "output": null
+ },
+ {
+ "input": "x/x;\u008f=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u008f;bonus=x",
+ "output": "x/x;x=\"\u008f\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u008f\";bonus=x",
+ "output": "x/x;x=\"\u008f\";bonus=x"
+ },
+ {
+ "input": "\u0090/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0090",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0090=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0090;bonus=x",
+ "output": "x/x;x=\"\u0090\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0090\";bonus=x",
+ "output": "x/x;x=\"\u0090\";bonus=x"
+ },
+ {
+ "input": "\u0091/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0091",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0091=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0091;bonus=x",
+ "output": "x/x;x=\"\u0091\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0091\";bonus=x",
+ "output": "x/x;x=\"\u0091\";bonus=x"
+ },
+ {
+ "input": "\u0092/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0092",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0092=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0092;bonus=x",
+ "output": "x/x;x=\"\u0092\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0092\";bonus=x",
+ "output": "x/x;x=\"\u0092\";bonus=x"
+ },
+ {
+ "input": "\u0093/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0093",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0093=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0093;bonus=x",
+ "output": "x/x;x=\"\u0093\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0093\";bonus=x",
+ "output": "x/x;x=\"\u0093\";bonus=x"
+ },
+ {
+ "input": "\u0094/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0094",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0094=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0094;bonus=x",
+ "output": "x/x;x=\"\u0094\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0094\";bonus=x",
+ "output": "x/x;x=\"\u0094\";bonus=x"
+ },
+ {
+ "input": "\u0095/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0095",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0095=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0095;bonus=x",
+ "output": "x/x;x=\"\u0095\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0095\";bonus=x",
+ "output": "x/x;x=\"\u0095\";bonus=x"
+ },
+ {
+ "input": "\u0096/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0096",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0096=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0096;bonus=x",
+ "output": "x/x;x=\"\u0096\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0096\";bonus=x",
+ "output": "x/x;x=\"\u0096\";bonus=x"
+ },
+ {
+ "input": "\u0097/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0097",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0097=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0097;bonus=x",
+ "output": "x/x;x=\"\u0097\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0097\";bonus=x",
+ "output": "x/x;x=\"\u0097\";bonus=x"
+ },
+ {
+ "input": "\u0098/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0098",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0098=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0098;bonus=x",
+ "output": "x/x;x=\"\u0098\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0098\";bonus=x",
+ "output": "x/x;x=\"\u0098\";bonus=x"
+ },
+ {
+ "input": "\u0099/x",
+ "output": null
+ },
+ {
+ "input": "x/\u0099",
+ "output": null
+ },
+ {
+ "input": "x/x;\u0099=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u0099;bonus=x",
+ "output": "x/x;x=\"\u0099\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u0099\";bonus=x",
+ "output": "x/x;x=\"\u0099\";bonus=x"
+ },
+ {
+ "input": "\u009a/x",
+ "output": null
+ },
+ {
+ "input": "x/\u009a",
+ "output": null
+ },
+ {
+ "input": "x/x;\u009a=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u009a;bonus=x",
+ "output": "x/x;x=\"\u009a\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u009a\";bonus=x",
+ "output": "x/x;x=\"\u009a\";bonus=x"
+ },
+ {
+ "input": "\u009b/x",
+ "output": null
+ },
+ {
+ "input": "x/\u009b",
+ "output": null
+ },
+ {
+ "input": "x/x;\u009b=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u009b;bonus=x",
+ "output": "x/x;x=\"\u009b\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u009b\";bonus=x",
+ "output": "x/x;x=\"\u009b\";bonus=x"
+ },
+ {
+ "input": "\u009c/x",
+ "output": null
+ },
+ {
+ "input": "x/\u009c",
+ "output": null
+ },
+ {
+ "input": "x/x;\u009c=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u009c;bonus=x",
+ "output": "x/x;x=\"\u009c\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u009c\";bonus=x",
+ "output": "x/x;x=\"\u009c\";bonus=x"
+ },
+ {
+ "input": "\u009d/x",
+ "output": null
+ },
+ {
+ "input": "x/\u009d",
+ "output": null
+ },
+ {
+ "input": "x/x;\u009d=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u009d;bonus=x",
+ "output": "x/x;x=\"\u009d\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u009d\";bonus=x",
+ "output": "x/x;x=\"\u009d\";bonus=x"
+ },
+ {
+ "input": "\u009e/x",
+ "output": null
+ },
+ {
+ "input": "x/\u009e",
+ "output": null
+ },
+ {
+ "input": "x/x;\u009e=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u009e;bonus=x",
+ "output": "x/x;x=\"\u009e\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u009e\";bonus=x",
+ "output": "x/x;x=\"\u009e\";bonus=x"
+ },
+ {
+ "input": "\u009f/x",
+ "output": null
+ },
+ {
+ "input": "x/\u009f",
+ "output": null
+ },
+ {
+ "input": "x/x;\u009f=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u009f;bonus=x",
+ "output": "x/x;x=\"\u009f\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u009f\";bonus=x",
+ "output": "x/x;x=\"\u009f\";bonus=x"
+ },
+ {
+ "input": "\u00a0/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00a0",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00a0=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00a0;bonus=x",
+ "output": "x/x;x=\"\u00a0\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00a0\";bonus=x",
+ "output": "x/x;x=\"\u00a0\";bonus=x"
+ },
+ {
+ "input": "\u00a1/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00a1",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00a1=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00a1;bonus=x",
+ "output": "x/x;x=\"\u00a1\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00a1\";bonus=x",
+ "output": "x/x;x=\"\u00a1\";bonus=x"
+ },
+ {
+ "input": "\u00a2/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00a2",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00a2=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00a2;bonus=x",
+ "output": "x/x;x=\"\u00a2\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00a2\";bonus=x",
+ "output": "x/x;x=\"\u00a2\";bonus=x"
+ },
+ {
+ "input": "\u00a3/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00a3",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00a3=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00a3;bonus=x",
+ "output": "x/x;x=\"\u00a3\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00a3\";bonus=x",
+ "output": "x/x;x=\"\u00a3\";bonus=x"
+ },
+ {
+ "input": "\u00a4/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00a4",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00a4=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00a4;bonus=x",
+ "output": "x/x;x=\"\u00a4\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00a4\";bonus=x",
+ "output": "x/x;x=\"\u00a4\";bonus=x"
+ },
+ {
+ "input": "\u00a5/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00a5",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00a5=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00a5;bonus=x",
+ "output": "x/x;x=\"\u00a5\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00a5\";bonus=x",
+ "output": "x/x;x=\"\u00a5\";bonus=x"
+ },
+ {
+ "input": "\u00a6/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00a6",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00a6=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00a6;bonus=x",
+ "output": "x/x;x=\"\u00a6\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00a6\";bonus=x",
+ "output": "x/x;x=\"\u00a6\";bonus=x"
+ },
+ {
+ "input": "\u00a7/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00a7",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00a7=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00a7;bonus=x",
+ "output": "x/x;x=\"\u00a7\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00a7\";bonus=x",
+ "output": "x/x;x=\"\u00a7\";bonus=x"
+ },
+ {
+ "input": "\u00a8/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00a8",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00a8=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00a8;bonus=x",
+ "output": "x/x;x=\"\u00a8\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00a8\";bonus=x",
+ "output": "x/x;x=\"\u00a8\";bonus=x"
+ },
+ {
+ "input": "\u00a9/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00a9",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00a9=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00a9;bonus=x",
+ "output": "x/x;x=\"\u00a9\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00a9\";bonus=x",
+ "output": "x/x;x=\"\u00a9\";bonus=x"
+ },
+ {
+ "input": "\u00aa/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00aa",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00aa=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00aa;bonus=x",
+ "output": "x/x;x=\"\u00aa\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00aa\";bonus=x",
+ "output": "x/x;x=\"\u00aa\";bonus=x"
+ },
+ {
+ "input": "\u00ab/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00ab",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00ab=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00ab;bonus=x",
+ "output": "x/x;x=\"\u00ab\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00ab\";bonus=x",
+ "output": "x/x;x=\"\u00ab\";bonus=x"
+ },
+ {
+ "input": "\u00ac/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00ac",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00ac=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00ac;bonus=x",
+ "output": "x/x;x=\"\u00ac\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00ac\";bonus=x",
+ "output": "x/x;x=\"\u00ac\";bonus=x"
+ },
+ {
+ "input": "\u00ad/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00ad",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00ad=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00ad;bonus=x",
+ "output": "x/x;x=\"\u00ad\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00ad\";bonus=x",
+ "output": "x/x;x=\"\u00ad\";bonus=x"
+ },
+ {
+ "input": "\u00ae/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00ae",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00ae=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00ae;bonus=x",
+ "output": "x/x;x=\"\u00ae\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00ae\";bonus=x",
+ "output": "x/x;x=\"\u00ae\";bonus=x"
+ },
+ {
+ "input": "\u00af/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00af",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00af=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00af;bonus=x",
+ "output": "x/x;x=\"\u00af\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00af\";bonus=x",
+ "output": "x/x;x=\"\u00af\";bonus=x"
+ },
+ {
+ "input": "\u00b0/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00b0",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00b0=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00b0;bonus=x",
+ "output": "x/x;x=\"\u00b0\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00b0\";bonus=x",
+ "output": "x/x;x=\"\u00b0\";bonus=x"
+ },
+ {
+ "input": "\u00b1/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00b1",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00b1=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00b1;bonus=x",
+ "output": "x/x;x=\"\u00b1\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00b1\";bonus=x",
+ "output": "x/x;x=\"\u00b1\";bonus=x"
+ },
+ {
+ "input": "\u00b2/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00b2",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00b2=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00b2;bonus=x",
+ "output": "x/x;x=\"\u00b2\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00b2\";bonus=x",
+ "output": "x/x;x=\"\u00b2\";bonus=x"
+ },
+ {
+ "input": "\u00b3/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00b3",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00b3=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00b3;bonus=x",
+ "output": "x/x;x=\"\u00b3\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00b3\";bonus=x",
+ "output": "x/x;x=\"\u00b3\";bonus=x"
+ },
+ {
+ "input": "\u00b4/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00b4",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00b4=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00b4;bonus=x",
+ "output": "x/x;x=\"\u00b4\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00b4\";bonus=x",
+ "output": "x/x;x=\"\u00b4\";bonus=x"
+ },
+ {
+ "input": "\u00b5/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00b5",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00b5=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00b5;bonus=x",
+ "output": "x/x;x=\"\u00b5\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00b5\";bonus=x",
+ "output": "x/x;x=\"\u00b5\";bonus=x"
+ },
+ {
+ "input": "\u00b6/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00b6",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00b6=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00b6;bonus=x",
+ "output": "x/x;x=\"\u00b6\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00b6\";bonus=x",
+ "output": "x/x;x=\"\u00b6\";bonus=x"
+ },
+ {
+ "input": "\u00b7/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00b7",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00b7=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00b7;bonus=x",
+ "output": "x/x;x=\"\u00b7\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00b7\";bonus=x",
+ "output": "x/x;x=\"\u00b7\";bonus=x"
+ },
+ {
+ "input": "\u00b8/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00b8",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00b8=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00b8;bonus=x",
+ "output": "x/x;x=\"\u00b8\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00b8\";bonus=x",
+ "output": "x/x;x=\"\u00b8\";bonus=x"
+ },
+ {
+ "input": "\u00b9/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00b9",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00b9=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00b9;bonus=x",
+ "output": "x/x;x=\"\u00b9\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00b9\";bonus=x",
+ "output": "x/x;x=\"\u00b9\";bonus=x"
+ },
+ {
+ "input": "\u00ba/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00ba",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00ba=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00ba;bonus=x",
+ "output": "x/x;x=\"\u00ba\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00ba\";bonus=x",
+ "output": "x/x;x=\"\u00ba\";bonus=x"
+ },
+ {
+ "input": "\u00bb/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00bb",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00bb=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00bb;bonus=x",
+ "output": "x/x;x=\"\u00bb\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00bb\";bonus=x",
+ "output": "x/x;x=\"\u00bb\";bonus=x"
+ },
+ {
+ "input": "\u00bc/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00bc",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00bc=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00bc;bonus=x",
+ "output": "x/x;x=\"\u00bc\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00bc\";bonus=x",
+ "output": "x/x;x=\"\u00bc\";bonus=x"
+ },
+ {
+ "input": "\u00bd/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00bd",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00bd=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00bd;bonus=x",
+ "output": "x/x;x=\"\u00bd\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00bd\";bonus=x",
+ "output": "x/x;x=\"\u00bd\";bonus=x"
+ },
+ {
+ "input": "\u00be/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00be",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00be=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00be;bonus=x",
+ "output": "x/x;x=\"\u00be\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00be\";bonus=x",
+ "output": "x/x;x=\"\u00be\";bonus=x"
+ },
+ {
+ "input": "\u00bf/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00bf",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00bf=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00bf;bonus=x",
+ "output": "x/x;x=\"\u00bf\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00bf\";bonus=x",
+ "output": "x/x;x=\"\u00bf\";bonus=x"
+ },
+ {
+ "input": "\u00c0/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00c0",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00c0=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00c0;bonus=x",
+ "output": "x/x;x=\"\u00c0\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00c0\";bonus=x",
+ "output": "x/x;x=\"\u00c0\";bonus=x"
+ },
+ {
+ "input": "\u00c1/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00c1",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00c1=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00c1;bonus=x",
+ "output": "x/x;x=\"\u00c1\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00c1\";bonus=x",
+ "output": "x/x;x=\"\u00c1\";bonus=x"
+ },
+ {
+ "input": "\u00c2/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00c2",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00c2=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00c2;bonus=x",
+ "output": "x/x;x=\"\u00c2\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00c2\";bonus=x",
+ "output": "x/x;x=\"\u00c2\";bonus=x"
+ },
+ {
+ "input": "\u00c3/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00c3",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00c3=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00c3;bonus=x",
+ "output": "x/x;x=\"\u00c3\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00c3\";bonus=x",
+ "output": "x/x;x=\"\u00c3\";bonus=x"
+ },
+ {
+ "input": "\u00c4/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00c4",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00c4=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00c4;bonus=x",
+ "output": "x/x;x=\"\u00c4\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00c4\";bonus=x",
+ "output": "x/x;x=\"\u00c4\";bonus=x"
+ },
+ {
+ "input": "\u00c5/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00c5",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00c5=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00c5;bonus=x",
+ "output": "x/x;x=\"\u00c5\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00c5\";bonus=x",
+ "output": "x/x;x=\"\u00c5\";bonus=x"
+ },
+ {
+ "input": "\u00c6/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00c6",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00c6=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00c6;bonus=x",
+ "output": "x/x;x=\"\u00c6\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00c6\";bonus=x",
+ "output": "x/x;x=\"\u00c6\";bonus=x"
+ },
+ {
+ "input": "\u00c7/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00c7",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00c7=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00c7;bonus=x",
+ "output": "x/x;x=\"\u00c7\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00c7\";bonus=x",
+ "output": "x/x;x=\"\u00c7\";bonus=x"
+ },
+ {
+ "input": "\u00c8/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00c8",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00c8=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00c8;bonus=x",
+ "output": "x/x;x=\"\u00c8\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00c8\";bonus=x",
+ "output": "x/x;x=\"\u00c8\";bonus=x"
+ },
+ {
+ "input": "\u00c9/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00c9",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00c9=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00c9;bonus=x",
+ "output": "x/x;x=\"\u00c9\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00c9\";bonus=x",
+ "output": "x/x;x=\"\u00c9\";bonus=x"
+ },
+ {
+ "input": "\u00ca/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00ca",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00ca=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00ca;bonus=x",
+ "output": "x/x;x=\"\u00ca\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00ca\";bonus=x",
+ "output": "x/x;x=\"\u00ca\";bonus=x"
+ },
+ {
+ "input": "\u00cb/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00cb",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00cb=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00cb;bonus=x",
+ "output": "x/x;x=\"\u00cb\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00cb\";bonus=x",
+ "output": "x/x;x=\"\u00cb\";bonus=x"
+ },
+ {
+ "input": "\u00cc/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00cc",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00cc=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00cc;bonus=x",
+ "output": "x/x;x=\"\u00cc\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00cc\";bonus=x",
+ "output": "x/x;x=\"\u00cc\";bonus=x"
+ },
+ {
+ "input": "\u00cd/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00cd",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00cd=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00cd;bonus=x",
+ "output": "x/x;x=\"\u00cd\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00cd\";bonus=x",
+ "output": "x/x;x=\"\u00cd\";bonus=x"
+ },
+ {
+ "input": "\u00ce/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00ce",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00ce=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00ce;bonus=x",
+ "output": "x/x;x=\"\u00ce\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00ce\";bonus=x",
+ "output": "x/x;x=\"\u00ce\";bonus=x"
+ },
+ {
+ "input": "\u00cf/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00cf",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00cf=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00cf;bonus=x",
+ "output": "x/x;x=\"\u00cf\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00cf\";bonus=x",
+ "output": "x/x;x=\"\u00cf\";bonus=x"
+ },
+ {
+ "input": "\u00d0/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00d0",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00d0=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00d0;bonus=x",
+ "output": "x/x;x=\"\u00d0\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00d0\";bonus=x",
+ "output": "x/x;x=\"\u00d0\";bonus=x"
+ },
+ {
+ "input": "\u00d1/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00d1",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00d1=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00d1;bonus=x",
+ "output": "x/x;x=\"\u00d1\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00d1\";bonus=x",
+ "output": "x/x;x=\"\u00d1\";bonus=x"
+ },
+ {
+ "input": "\u00d2/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00d2",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00d2=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00d2;bonus=x",
+ "output": "x/x;x=\"\u00d2\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00d2\";bonus=x",
+ "output": "x/x;x=\"\u00d2\";bonus=x"
+ },
+ {
+ "input": "\u00d3/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00d3",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00d3=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00d3;bonus=x",
+ "output": "x/x;x=\"\u00d3\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00d3\";bonus=x",
+ "output": "x/x;x=\"\u00d3\";bonus=x"
+ },
+ {
+ "input": "\u00d4/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00d4",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00d4=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00d4;bonus=x",
+ "output": "x/x;x=\"\u00d4\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00d4\";bonus=x",
+ "output": "x/x;x=\"\u00d4\";bonus=x"
+ },
+ {
+ "input": "\u00d5/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00d5",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00d5=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00d5;bonus=x",
+ "output": "x/x;x=\"\u00d5\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00d5\";bonus=x",
+ "output": "x/x;x=\"\u00d5\";bonus=x"
+ },
+ {
+ "input": "\u00d6/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00d6",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00d6=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00d6;bonus=x",
+ "output": "x/x;x=\"\u00d6\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00d6\";bonus=x",
+ "output": "x/x;x=\"\u00d6\";bonus=x"
+ },
+ {
+ "input": "\u00d7/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00d7",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00d7=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00d7;bonus=x",
+ "output": "x/x;x=\"\u00d7\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00d7\";bonus=x",
+ "output": "x/x;x=\"\u00d7\";bonus=x"
+ },
+ {
+ "input": "\u00d8/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00d8",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00d8=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00d8;bonus=x",
+ "output": "x/x;x=\"\u00d8\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00d8\";bonus=x",
+ "output": "x/x;x=\"\u00d8\";bonus=x"
+ },
+ {
+ "input": "\u00d9/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00d9",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00d9=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00d9;bonus=x",
+ "output": "x/x;x=\"\u00d9\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00d9\";bonus=x",
+ "output": "x/x;x=\"\u00d9\";bonus=x"
+ },
+ {
+ "input": "\u00da/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00da",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00da=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00da;bonus=x",
+ "output": "x/x;x=\"\u00da\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00da\";bonus=x",
+ "output": "x/x;x=\"\u00da\";bonus=x"
+ },
+ {
+ "input": "\u00db/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00db",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00db=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00db;bonus=x",
+ "output": "x/x;x=\"\u00db\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00db\";bonus=x",
+ "output": "x/x;x=\"\u00db\";bonus=x"
+ },
+ {
+ "input": "\u00dc/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00dc",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00dc=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00dc;bonus=x",
+ "output": "x/x;x=\"\u00dc\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00dc\";bonus=x",
+ "output": "x/x;x=\"\u00dc\";bonus=x"
+ },
+ {
+ "input": "\u00dd/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00dd",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00dd=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00dd;bonus=x",
+ "output": "x/x;x=\"\u00dd\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00dd\";bonus=x",
+ "output": "x/x;x=\"\u00dd\";bonus=x"
+ },
+ {
+ "input": "\u00de/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00de",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00de=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00de;bonus=x",
+ "output": "x/x;x=\"\u00de\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00de\";bonus=x",
+ "output": "x/x;x=\"\u00de\";bonus=x"
+ },
+ {
+ "input": "\u00df/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00df",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00df=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00df;bonus=x",
+ "output": "x/x;x=\"\u00df\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00df\";bonus=x",
+ "output": "x/x;x=\"\u00df\";bonus=x"
+ },
+ {
+ "input": "\u00e0/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00e0",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00e0=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00e0;bonus=x",
+ "output": "x/x;x=\"\u00e0\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00e0\";bonus=x",
+ "output": "x/x;x=\"\u00e0\";bonus=x"
+ },
+ {
+ "input": "\u00e1/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00e1",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00e1=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00e1;bonus=x",
+ "output": "x/x;x=\"\u00e1\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00e1\";bonus=x",
+ "output": "x/x;x=\"\u00e1\";bonus=x"
+ },
+ {
+ "input": "\u00e2/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00e2",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00e2=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00e2;bonus=x",
+ "output": "x/x;x=\"\u00e2\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00e2\";bonus=x",
+ "output": "x/x;x=\"\u00e2\";bonus=x"
+ },
+ {
+ "input": "\u00e3/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00e3",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00e3=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00e3;bonus=x",
+ "output": "x/x;x=\"\u00e3\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00e3\";bonus=x",
+ "output": "x/x;x=\"\u00e3\";bonus=x"
+ },
+ {
+ "input": "\u00e4/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00e4",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00e4=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00e4;bonus=x",
+ "output": "x/x;x=\"\u00e4\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00e4\";bonus=x",
+ "output": "x/x;x=\"\u00e4\";bonus=x"
+ },
+ {
+ "input": "\u00e5/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00e5",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00e5=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00e5;bonus=x",
+ "output": "x/x;x=\"\u00e5\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00e5\";bonus=x",
+ "output": "x/x;x=\"\u00e5\";bonus=x"
+ },
+ {
+ "input": "\u00e6/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00e6",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00e6=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00e6;bonus=x",
+ "output": "x/x;x=\"\u00e6\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00e6\";bonus=x",
+ "output": "x/x;x=\"\u00e6\";bonus=x"
+ },
+ {
+ "input": "\u00e7/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00e7",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00e7=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00e7;bonus=x",
+ "output": "x/x;x=\"\u00e7\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00e7\";bonus=x",
+ "output": "x/x;x=\"\u00e7\";bonus=x"
+ },
+ {
+ "input": "\u00e8/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00e8",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00e8=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00e8;bonus=x",
+ "output": "x/x;x=\"\u00e8\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00e8\";bonus=x",
+ "output": "x/x;x=\"\u00e8\";bonus=x"
+ },
+ {
+ "input": "\u00e9/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00e9",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00e9=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00e9;bonus=x",
+ "output": "x/x;x=\"\u00e9\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00e9\";bonus=x",
+ "output": "x/x;x=\"\u00e9\";bonus=x"
+ },
+ {
+ "input": "\u00ea/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00ea",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00ea=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00ea;bonus=x",
+ "output": "x/x;x=\"\u00ea\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00ea\";bonus=x",
+ "output": "x/x;x=\"\u00ea\";bonus=x"
+ },
+ {
+ "input": "\u00eb/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00eb",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00eb=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00eb;bonus=x",
+ "output": "x/x;x=\"\u00eb\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00eb\";bonus=x",
+ "output": "x/x;x=\"\u00eb\";bonus=x"
+ },
+ {
+ "input": "\u00ec/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00ec",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00ec=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00ec;bonus=x",
+ "output": "x/x;x=\"\u00ec\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00ec\";bonus=x",
+ "output": "x/x;x=\"\u00ec\";bonus=x"
+ },
+ {
+ "input": "\u00ed/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00ed",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00ed=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00ed;bonus=x",
+ "output": "x/x;x=\"\u00ed\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00ed\";bonus=x",
+ "output": "x/x;x=\"\u00ed\";bonus=x"
+ },
+ {
+ "input": "\u00ee/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00ee",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00ee=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00ee;bonus=x",
+ "output": "x/x;x=\"\u00ee\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00ee\";bonus=x",
+ "output": "x/x;x=\"\u00ee\";bonus=x"
+ },
+ {
+ "input": "\u00ef/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00ef",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00ef=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00ef;bonus=x",
+ "output": "x/x;x=\"\u00ef\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00ef\";bonus=x",
+ "output": "x/x;x=\"\u00ef\";bonus=x"
+ },
+ {
+ "input": "\u00f0/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00f0",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00f0=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00f0;bonus=x",
+ "output": "x/x;x=\"\u00f0\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00f0\";bonus=x",
+ "output": "x/x;x=\"\u00f0\";bonus=x"
+ },
+ {
+ "input": "\u00f1/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00f1",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00f1=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00f1;bonus=x",
+ "output": "x/x;x=\"\u00f1\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00f1\";bonus=x",
+ "output": "x/x;x=\"\u00f1\";bonus=x"
+ },
+ {
+ "input": "\u00f2/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00f2",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00f2=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00f2;bonus=x",
+ "output": "x/x;x=\"\u00f2\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00f2\";bonus=x",
+ "output": "x/x;x=\"\u00f2\";bonus=x"
+ },
+ {
+ "input": "\u00f3/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00f3",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00f3=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00f3;bonus=x",
+ "output": "x/x;x=\"\u00f3\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00f3\";bonus=x",
+ "output": "x/x;x=\"\u00f3\";bonus=x"
+ },
+ {
+ "input": "\u00f4/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00f4",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00f4=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00f4;bonus=x",
+ "output": "x/x;x=\"\u00f4\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00f4\";bonus=x",
+ "output": "x/x;x=\"\u00f4\";bonus=x"
+ },
+ {
+ "input": "\u00f5/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00f5",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00f5=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00f5;bonus=x",
+ "output": "x/x;x=\"\u00f5\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00f5\";bonus=x",
+ "output": "x/x;x=\"\u00f5\";bonus=x"
+ },
+ {
+ "input": "\u00f6/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00f6",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00f6=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00f6;bonus=x",
+ "output": "x/x;x=\"\u00f6\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00f6\";bonus=x",
+ "output": "x/x;x=\"\u00f6\";bonus=x"
+ },
+ {
+ "input": "\u00f7/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00f7",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00f7=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00f7;bonus=x",
+ "output": "x/x;x=\"\u00f7\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00f7\";bonus=x",
+ "output": "x/x;x=\"\u00f7\";bonus=x"
+ },
+ {
+ "input": "\u00f8/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00f8",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00f8=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00f8;bonus=x",
+ "output": "x/x;x=\"\u00f8\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00f8\";bonus=x",
+ "output": "x/x;x=\"\u00f8\";bonus=x"
+ },
+ {
+ "input": "\u00f9/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00f9",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00f9=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00f9;bonus=x",
+ "output": "x/x;x=\"\u00f9\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00f9\";bonus=x",
+ "output": "x/x;x=\"\u00f9\";bonus=x"
+ },
+ {
+ "input": "\u00fa/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00fa",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00fa=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00fa;bonus=x",
+ "output": "x/x;x=\"\u00fa\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00fa\";bonus=x",
+ "output": "x/x;x=\"\u00fa\";bonus=x"
+ },
+ {
+ "input": "\u00fb/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00fb",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00fb=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00fb;bonus=x",
+ "output": "x/x;x=\"\u00fb\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00fb\";bonus=x",
+ "output": "x/x;x=\"\u00fb\";bonus=x"
+ },
+ {
+ "input": "\u00fc/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00fc",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00fc=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00fc;bonus=x",
+ "output": "x/x;x=\"\u00fc\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00fc\";bonus=x",
+ "output": "x/x;x=\"\u00fc\";bonus=x"
+ },
+ {
+ "input": "\u00fd/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00fd",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00fd=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00fd;bonus=x",
+ "output": "x/x;x=\"\u00fd\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00fd\";bonus=x",
+ "output": "x/x;x=\"\u00fd\";bonus=x"
+ },
+ {
+ "input": "\u00fe/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00fe",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00fe=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00fe;bonus=x",
+ "output": "x/x;x=\"\u00fe\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00fe\";bonus=x",
+ "output": "x/x;x=\"\u00fe\";bonus=x"
+ },
+ {
+ "input": "\u00ff/x",
+ "output": null
+ },
+ {
+ "input": "x/\u00ff",
+ "output": null
+ },
+ {
+ "input": "x/x;\u00ff=x;bonus=x",
+ "output": "x/x;bonus=x"
+ },
+ {
+ "input": "x/x;x=\u00ff;bonus=x",
+ "output": "x/x;x=\"\u00ff\";bonus=x"
+ },
+ {
+ "input": "x/x;x=\"\u00ff\";bonus=x",
+ "output": "x/x;x=\"\u00ff\";bonus=x"
+ }
+]
diff --git a/tests/wpt/web-platform-tests/mimesniff/mime-types/resources/generated-mime-types.py b/tests/wpt/web-platform-tests/mimesniff/mime-types/resources/generated-mime-types.py
new file mode 100644
index 00000000000..91921149011
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mimesniff/mime-types/resources/generated-mime-types.py
@@ -0,0 +1,45 @@
+import json
+
+def isHTTPTokenCodePoint(cp):
+ if cp in (0x21, 0x23, 0x24, 0x25, 0x26, 0x27, 0x2A, 0x2B, 0x2D, 0x2E, 0x5E, 0x5F, 0x60, 0x7C, 0x7E) or (cp >= 0x30 and cp <= 0x39) or (cp >= 0x41 and cp <= 0x5A) or (cp >= 0x61 and cp <= 0x7A):
+ return True
+ else:
+ return False
+
+def isHTTPQuotedStringTokenCodePoint(cp):
+ if cp == 0x09 or (cp >= 0x20 and cp <= 0x7E) or (cp >= 0x80 and cp <= 0xFF):
+ return True
+ else:
+ return False
+
+tests = []
+
+for cp in range(0x00, 0x100):
+ if isHTTPTokenCodePoint(cp):
+ continue
+ for scenario in ("type", "subtype", "name", "value"):
+ if scenario == "type" or scenario == "subtype":
+ if cp == 0x2F: # /
+ continue
+ if scenario == "type":
+ test = unichr(cp) + "/x"
+ else:
+ test = "x/" + unichr(cp)
+ tests.append({"input": test, "output": None})
+ elif scenario == "name":
+ if cp == 0x3B or cp == 0x3D: # ; =
+ continue
+ tests.append({"input": "x/x;" + unichr(cp) + "=x;bonus=x", "output": "x/x;bonus=x"})
+ elif scenario == "value":
+ if cp == 0x09 or cp == 0x20 or cp == 0x22 or cp == 0x3B or cp == 0x5C: # TAB SP " ; \
+ continue
+ if isHTTPQuotedStringTokenCodePoint(cp):
+ testOutput = "x/x;x=\"" + unichr(cp) + "\";bonus=x"
+ else:
+ testOutput = "x/x;bonus=x"
+ tests.append({"input": "x/x;x=" + unichr(cp) + ";bonus=x", "output": testOutput})
+ tests.append({"input": "x/x;x=\"" + unichr(cp) + "\";bonus=x", "output": testOutput})
+
+handle = open("generated-mime-types.json", "w")
+handle.write(json.dumps(tests, indent=2, separators=(',', ': ')))
+handle.write("\n")
diff --git a/tests/wpt/web-platform-tests/mimesniff/mime-types/resources/mime-charset.py b/tests/wpt/web-platform-tests/mimesniff/mime-types/resources/mime-charset.py
new file mode 100644
index 00000000000..433a5bb74b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mimesniff/mime-types/resources/mime-charset.py
@@ -0,0 +1,3 @@
+def main(request, response):
+ response.headers.set("Content-Type", request.GET.first("type"));
+ response.content = "<meta charset=utf-8>\n<script>document.write(document.characterSet)</script>"
diff --git a/tests/wpt/web-platform-tests/mimesniff/mime-types/resources/mime-types.json b/tests/wpt/web-platform-tests/mimesniff/mime-types/resources/mime-types.json
new file mode 100644
index 00000000000..6bee02daee9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mimesniff/mime-types/resources/mime-types.json
@@ -0,0 +1,262 @@
+[
+ "Basics",
+ {
+ "input": "text/html;charset=gbk",
+ "output": "text/html;charset=gbk",
+ "navigable": true,
+ "encoding": "GBK"
+ },
+ {
+ "input": "TEXT/HTML;CHARSET=GBK",
+ "output": "text/html;charset=GBK",
+ "navigable": true,
+ "encoding": "GBK"
+ },
+ "Legacy comment syntax",
+ {
+ "input": "text/html;charset=gbk(",
+ "output": "text/html;charset=\"gbk(\"",
+ "navigable": true,
+ "encoding": null
+ },
+ {
+ "input": "text/html;x=(;charset=gbk",
+ "output": "text/html;x=\"(\";charset=gbk",
+ "navigable": true,
+ "encoding": "GBK"
+ },
+ "Duplicate parameter",
+ {
+ "input": "text/html;charset=gbk;charset=windows-1255",
+ "output": "text/html;charset=gbk",
+ "navigable": true,
+ "encoding": "GBK"
+ },
+ "Spaces",
+ {
+ "input": "text/html;charset =gbk",
+ "output": "text/html",
+ "navigable": true,
+ "encoding": null
+ },
+ {
+ "input": "text/html ;charset=gbk",
+ "output": "text/html;charset=gbk",
+ "navigable": true,
+ "encoding": "GBK"
+ },
+ {
+ "input": "text/html; charset=gbk",
+ "output": "text/html;charset=gbk",
+ "navigable": true,
+ "encoding": "GBK"
+ },
+ {
+ "input": "text/html;charset= gbk",
+ "output": "text/html;charset=\" gbk\"",
+ "navigable": true,
+ "encoding": "GBK"
+ },
+ "Single quotes are a token, not a delimiter",
+ {
+ "input": "text/html;charset='gbk'",
+ "output": "text/html;charset='gbk'",
+ "navigable": true,
+ "encoding": null
+ },
+ {
+ "input": "text/html;charset='gbk",
+ "output": "text/html;charset='gbk",
+ "navigable": true,
+ "encoding": null
+ },
+ {
+ "input": "text/html;charset=gbk'",
+ "output": "text/html;charset=gbk'",
+ "navigable": true,
+ "encoding": null
+ },
+ "Invalid parameters",
+ {
+ "input": "text/html;test;charset=gbk",
+ "output": "text/html;charset=gbk",
+ "navigable": true,
+ "encoding": "GBK"
+ },
+ {
+ "input": "text/html;test=;charset=gbk",
+ "output": "text/html;charset=gbk",
+ "navigable": true,
+ "encoding": "GBK"
+ },
+ {
+ "input": "text/html;';charset=gbk",
+ "output": "text/html;charset=gbk",
+ "navigable": true,
+ "encoding": "GBK"
+ },
+ {
+ "input": "text/html;\";charset=gbk",
+ "output": "text/html;charset=gbk",
+ "navigable": true,
+ "encoding": "GBK"
+ },
+ {
+ "input": "text/html ; ; charset=gbk",
+ "output": "text/html;charset=gbk",
+ "navigable": true,
+ "encoding": "GBK"
+ },
+ {
+ "input": "text/html;;;;charset=gbk",
+ "output": "text/html;charset=gbk",
+ "navigable": true,
+ "encoding": "GBK"
+ },
+ "Double quotes",
+ {
+ "input": "text/html;charset=\"gbk\"",
+ "output": "text/html;charset=gbk",
+ "navigable": true,
+ "encoding": "GBK"
+ },
+ {
+ "input": "text/html;charset=\"gbk",
+ "output": "text/html;charset=gbk",
+ "navigable": true,
+ "encoding": "GBK"
+ },
+ {
+ "input": "text/html;charset=gbk\"",
+ "output": "text/html;charset=\"gbk\\\"\"",
+ "navigable": true,
+ "encoding": null
+ },
+ {
+ "input": "text/html;charset=\" gbk\"",
+ "output": "text/html;charset=\" gbk\"",
+ "navigable": true,
+ "encoding": "GBK"
+ },
+ {
+ "input": "text/html;charset=\"\\ gbk\"",
+ "output": "text/html;charset=\" gbk\"",
+ "navigable": true,
+ "encoding": "GBK"
+ },
+ {
+ "input": "text/html;charset=\"\\g\\b\\k\"",
+ "output": "text/html;charset=gbk",
+ "navigable": true,
+ "encoding": "GBK"
+ },
+ {
+ "input": "text/html;charset=\"gbk\"x",
+ "output": "text/html;charset=gbk",
+ "navigable": true,
+ "encoding": "GBK"
+ },
+ "Unexpected code points",
+ {
+ "input": "text/html;charset={gbk}",
+ "output": "text/html;charset=\"{gbk}\"",
+ "navigable": true,
+ "encoding": null
+ },
+ "Parameter name longer than 127",
+ {
+ "input": "text/html;0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789=x;charset=gbk",
+ "output": "text/html;0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789=x;charset=gbk",
+ "navigable": true,
+ "encoding": "GBK"
+ },
+ "type/subtype longer than 127",
+ {
+ "input": "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789/0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789",
+ "output": "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789/0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
+ },
+ "Valid",
+ {
+ "input": "!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
+ "output": "!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+ },
+ {
+ "input": "x/x;x=\"\t !\\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008A\u008B\u008C\u008D\u008E\u008F\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009A\u009B\u009C\u009D\u009E\u009F\u00A0\u00A1\u00A2\u00A3\u00A4\u00A5\u00A6\u00A7\u00A8\u00A9\u00AA\u00AB\u00AC\u00AD\u00AE\u00AF\u00B0\u00B1\u00B2\u00B3\u00B4\u00B5\u00B6\u00B7\u00B8\u00B9\u00BA\u00BB\u00BC\u00BD\u00BE\u00BF\u00C0\u00C1\u00C2\u00C3\u00C4\u00C5\u00C6\u00C7\u00C8\u00C9\u00CA\u00CB\u00CC\u00CD\u00CE\u00CF\u00D0\u00D1\u00D2\u00D3\u00D4\u00D5\u00D6\u00D7\u00D8\u00D9\u00DA\u00DB\u00DC\u00DD\u00DE\u00DF\u00E0\u00E1\u00E2\u00E3\u00E4\u00E5\u00E6\u00E7\u00E8\u00E9\u00EA\u00EB\u00EC\u00ED\u00EE\u00EF\u00F0\u00F1\u00F2\u00F3\u00F4\u00F5\u00F6\u00F7\u00F8\u00F9\u00FA\u00FB\u00FC\u00FD\u00FE\u00FF\"",
+ "output": "x/x;x=\"\t !\\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008A\u008B\u008C\u008D\u008E\u008F\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009A\u009B\u009C\u009D\u009E\u009F\u00A0\u00A1\u00A2\u00A3\u00A4\u00A5\u00A6\u00A7\u00A8\u00A9\u00AA\u00AB\u00AC\u00AD\u00AE\u00AF\u00B0\u00B1\u00B2\u00B3\u00B4\u00B5\u00B6\u00B7\u00B8\u00B9\u00BA\u00BB\u00BC\u00BD\u00BE\u00BF\u00C0\u00C1\u00C2\u00C3\u00C4\u00C5\u00C6\u00C7\u00C8\u00C9\u00CA\u00CB\u00CC\u00CD\u00CE\u00CF\u00D0\u00D1\u00D2\u00D3\u00D4\u00D5\u00D6\u00D7\u00D8\u00D9\u00DA\u00DB\u00DC\u00DD\u00DE\u00DF\u00E0\u00E1\u00E2\u00E3\u00E4\u00E5\u00E6\u00E7\u00E8\u00E9\u00EA\u00EB\u00EC\u00ED\u00EE\u00EF\u00F0\u00F1\u00F2\u00F3\u00F4\u00F5\u00F6\u00F7\u00F8\u00F9\u00FA\u00FB\u00FC\u00FD\u00FE\u00FF\""
+ },
+ "End-of-file handling",
+ {
+ "input": "x/x;test",
+ "output": "x/x"
+ },
+ {
+ "input": "x/x;test=\"\\",
+ "output": "x/x;test=\"\\\\\""
+ },
+ "Whitespace (not handled by generated-mime-types.json or above)",
+ {
+ "input": "x/x;x= ",
+ "output": "x/x"
+ },
+ {
+ "input": "x/x;x=\t",
+ "output": "x/x"
+ },
+ "Latin1",
+ {
+ "input": "text/html;test=\u00FF;charset=gbk",
+ "output": "text/html;test=\"\u00FF\";charset=gbk",
+ "navigable": true,
+ "encoding": "GBK"
+ },
+ ">Latin1",
+ {
+ "input": "x/x;test=\uFFFD;x=x",
+ "output": "x/x;x=x"
+ },
+ "Failure",
+ {
+ "input": "",
+ "output": null
+ },
+ {
+ "input": "\t",
+ "output": null
+ },
+ {
+ "input": "bogus",
+ "output": null
+ },
+ {
+ "input": "bogus/",
+ "output": null
+ },
+ {
+ "input": "bogus/ ",
+ "output": null
+ },
+ {
+ "input": "bogus/bogus/;",
+ "output": null
+ },
+ {
+ "input": "</>",
+ "output": null
+ },
+ {
+ "input": "(/)",
+ "output": null
+ },
+ {
+ "input": "text/html(;doesnot=matter",
+ "output": null
+ },
+ {
+ "input": "{/}",
+ "output": null
+ },
+ {
+ "input": "\u0100/\u0100",
+ "output": null
+ }
+]
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html
new file mode 100644
index 00000000000..bcb7abb7c0e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+ <head>
+ <title>Mixed-Content: Blockable content</title>
+ <meta charset='utf-8'>
+ <meta name="description" content="Test behavior of blockable content.">
+ <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+ <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+ <meta name="assert" content="opt_in_method: http-csp
+ origin: cross-origin-http
+ source_scheme: https
+ context_nesting: top-level
+ redirection: keep-scheme-redirect
+ subresource: link-prefetch-tag
+ expectation: blocked">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/mixed-content/generic/common.js"></script>
+ <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+ </head>
+ <body>
+ <script>
+ MixedContentTestCase(
+ {
+ "opt_in_method": "http-csp",
+ "origin": "cross-origin-http",
+ "source_scheme": "https",
+ "context_nesting": "top-level",
+ "redirection": "keep-scheme-redirect",
+ "subresource": "link-prefetch-tag",
+ "expectation": "blocked"
+ },
+ document.querySelector("meta[name=assert]").content,
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html.headers
index 46e2255e388..46e2255e388 100644
--- a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers
+++ b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html.headers
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html
deleted file mode 100644
index 743515ed351..00000000000
--- a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
-<html>
- <head>
- <title>Mixed-Content: Optionally-blockable content</title>
- <meta charset='utf-8'>
- <meta name="description" content="Test behavior of optionally-blockable content">
- <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
- <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-optionally-blockable">
- <meta name="assert" content="opt_in_method: http-csp
- origin: cross-origin-http
- source_scheme: https
- context_nesting: top-level
- redirection: keep-scheme-redirect
- subresource: link-prefetch-tag
- expectation: blocked">
- <script src="/resources/testharness.js"></script>
- <script src="/resources/testharnessreport.js"></script>
- <script src="/mixed-content/generic/common.js"></script>
- <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
- </head>
- <body>
- <script>
- MixedContentTestCase(
- {
- "opt_in_method": "http-csp",
- "origin": "cross-origin-http",
- "source_scheme": "https",
- "context_nesting": "top-level",
- "redirection": "keep-scheme-redirect",
- "subresource": "link-prefetch-tag",
- "expectation": "blocked"
- },
- document.querySelector("meta[name=assert]").content,
- new SanityChecker()
- ).start();
- </script>
- <div id="log"></div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html
new file mode 100644
index 00000000000..3c6de84218b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+ <head>
+ <title>Mixed-Content: Blockable content</title>
+ <meta charset='utf-8'>
+ <meta name="description" content="Test behavior of blockable content.">
+ <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+ <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+ <meta name="assert" content="opt_in_method: http-csp
+ origin: cross-origin-http
+ source_scheme: https
+ context_nesting: top-level
+ redirection: no-redirect
+ subresource: link-prefetch-tag
+ expectation: blocked">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/mixed-content/generic/common.js"></script>
+ <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+ </head>
+ <body>
+ <script>
+ MixedContentTestCase(
+ {
+ "opt_in_method": "http-csp",
+ "origin": "cross-origin-http",
+ "source_scheme": "https",
+ "context_nesting": "top-level",
+ "redirection": "no-redirect",
+ "subresource": "link-prefetch-tag",
+ "expectation": "blocked"
+ },
+ document.querySelector("meta[name=assert]").content,
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html.headers b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html.headers
index 46e2255e388..46e2255e388 100644
--- a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html.headers
+++ b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html.headers
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html
deleted file mode 100644
index 88a54250a12..00000000000
--- a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
-<html>
- <head>
- <title>Mixed-Content: Optionally-blockable content</title>
- <meta charset='utf-8'>
- <meta name="description" content="Test behavior of optionally-blockable content">
- <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
- <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-optionally-blockable">
- <meta name="assert" content="opt_in_method: http-csp
- origin: cross-origin-http
- source_scheme: https
- context_nesting: top-level
- redirection: no-redirect
- subresource: link-prefetch-tag
- expectation: blocked">
- <script src="/resources/testharness.js"></script>
- <script src="/resources/testharnessreport.js"></script>
- <script src="/mixed-content/generic/common.js"></script>
- <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
- </head>
- <body>
- <script>
- MixedContentTestCase(
- {
- "opt_in_method": "http-csp",
- "origin": "cross-origin-http",
- "source_scheme": "https",
- "context_nesting": "top-level",
- "redirection": "no-redirect",
- "subresource": "link-prefetch-tag",
- "expectation": "blocked"
- },
- document.querySelector("meta[name=assert]").content,
- new SanityChecker()
- ).start();
- </script>
- <div id="log"></div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html
new file mode 100644
index 00000000000..1fe904f138a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+ <head>
+ <title>Mixed-Content: Blockable content</title>
+ <meta charset='utf-8'>
+ <meta name="description" content="Test behavior of blockable content.">
+ <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+ <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+ <meta name="assert" content="opt_in_method: http-csp
+ origin: cross-origin-http
+ source_scheme: https
+ context_nesting: top-level
+ redirection: swap-scheme-redirect
+ subresource: link-prefetch-tag
+ expectation: blocked">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/mixed-content/generic/common.js"></script>
+ <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+ </head>
+ <body>
+ <script>
+ MixedContentTestCase(
+ {
+ "opt_in_method": "http-csp",
+ "origin": "cross-origin-http",
+ "source_scheme": "https",
+ "context_nesting": "top-level",
+ "redirection": "swap-scheme-redirect",
+ "subresource": "link-prefetch-tag",
+ "expectation": "blocked"
+ },
+ document.querySelector("meta[name=assert]").content,
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html.headers
index 46e2255e388..46e2255e388 100644
--- a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers
+++ b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html.headers
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html
deleted file mode 100644
index 2098a60b628..00000000000
--- a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
-<html>
- <head>
- <title>Mixed-Content: Optionally-blockable content</title>
- <meta charset='utf-8'>
- <meta name="description" content="Test behavior of optionally-blockable content">
- <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
- <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-optionally-blockable">
- <meta name="assert" content="opt_in_method: http-csp
- origin: cross-origin-http
- source_scheme: https
- context_nesting: top-level
- redirection: swap-scheme-redirect
- subresource: link-prefetch-tag
- expectation: blocked">
- <script src="/resources/testharness.js"></script>
- <script src="/resources/testharnessreport.js"></script>
- <script src="/mixed-content/generic/common.js"></script>
- <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
- </head>
- <body>
- <script>
- MixedContentTestCase(
- {
- "opt_in_method": "http-csp",
- "origin": "cross-origin-http",
- "source_scheme": "https",
- "context_nesting": "top-level",
- "redirection": "swap-scheme-redirect",
- "subresource": "link-prefetch-tag",
- "expectation": "blocked"
- },
- document.querySelector("meta[name=assert]").content,
- new SanityChecker()
- ).start();
- </script>
- <div id="log"></div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html
new file mode 100644
index 00000000000..2db9724a2eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+ <head>
+ <title>Mixed-Content: Blockable content</title>
+ <meta charset='utf-8'>
+ <meta name="description" content="Test behavior of blockable content.">
+ <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+ <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+ <meta name="assert" content="opt_in_method: http-csp
+ origin: same-host-http
+ source_scheme: https
+ context_nesting: top-level
+ redirection: keep-scheme-redirect
+ subresource: link-prefetch-tag
+ expectation: blocked">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/mixed-content/generic/common.js"></script>
+ <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+ </head>
+ <body>
+ <script>
+ MixedContentTestCase(
+ {
+ "opt_in_method": "http-csp",
+ "origin": "same-host-http",
+ "source_scheme": "https",
+ "context_nesting": "top-level",
+ "redirection": "keep-scheme-redirect",
+ "subresource": "link-prefetch-tag",
+ "expectation": "blocked"
+ },
+ document.querySelector("meta[name=assert]").content,
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html.headers
index 46e2255e388..46e2255e388 100644
--- a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers
+++ b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/blockable/opt-in-blocks.https.html.headers
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html
deleted file mode 100644
index fa8bd8a1f49..00000000000
--- a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
-<html>
- <head>
- <title>Mixed-Content: Optionally-blockable content</title>
- <meta charset='utf-8'>
- <meta name="description" content="Test behavior of optionally-blockable content">
- <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
- <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-optionally-blockable">
- <meta name="assert" content="opt_in_method: http-csp
- origin: same-host-http
- source_scheme: https
- context_nesting: top-level
- redirection: keep-scheme-redirect
- subresource: link-prefetch-tag
- expectation: blocked">
- <script src="/resources/testharness.js"></script>
- <script src="/resources/testharnessreport.js"></script>
- <script src="/mixed-content/generic/common.js"></script>
- <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
- </head>
- <body>
- <script>
- MixedContentTestCase(
- {
- "opt_in_method": "http-csp",
- "origin": "same-host-http",
- "source_scheme": "https",
- "context_nesting": "top-level",
- "redirection": "keep-scheme-redirect",
- "subresource": "link-prefetch-tag",
- "expectation": "blocked"
- },
- document.querySelector("meta[name=assert]").content,
- new SanityChecker()
- ).start();
- </script>
- <div id="log"></div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html
new file mode 100644
index 00000000000..ddad38792d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+ <head>
+ <title>Mixed-Content: Blockable content</title>
+ <meta charset='utf-8'>
+ <meta name="description" content="Test behavior of blockable content.">
+ <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+ <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+ <meta name="assert" content="opt_in_method: http-csp
+ origin: same-host-http
+ source_scheme: https
+ context_nesting: top-level
+ redirection: no-redirect
+ subresource: link-prefetch-tag
+ expectation: blocked">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/mixed-content/generic/common.js"></script>
+ <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+ </head>
+ <body>
+ <script>
+ MixedContentTestCase(
+ {
+ "opt_in_method": "http-csp",
+ "origin": "same-host-http",
+ "source_scheme": "https",
+ "context_nesting": "top-level",
+ "redirection": "no-redirect",
+ "subresource": "link-prefetch-tag",
+ "expectation": "blocked"
+ },
+ document.querySelector("meta[name=assert]").content,
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html.headers b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html.headers
index 46e2255e388..46e2255e388 100644
--- a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html.headers
+++ b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html.headers
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html
deleted file mode 100644
index 685f34582a0..00000000000
--- a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
-<html>
- <head>
- <title>Mixed-Content: Optionally-blockable content</title>
- <meta charset='utf-8'>
- <meta name="description" content="Test behavior of optionally-blockable content">
- <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
- <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-optionally-blockable">
- <meta name="assert" content="opt_in_method: http-csp
- origin: same-host-http
- source_scheme: https
- context_nesting: top-level
- redirection: no-redirect
- subresource: link-prefetch-tag
- expectation: blocked">
- <script src="/resources/testharness.js"></script>
- <script src="/resources/testharnessreport.js"></script>
- <script src="/mixed-content/generic/common.js"></script>
- <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
- </head>
- <body>
- <script>
- MixedContentTestCase(
- {
- "opt_in_method": "http-csp",
- "origin": "same-host-http",
- "source_scheme": "https",
- "context_nesting": "top-level",
- "redirection": "no-redirect",
- "subresource": "link-prefetch-tag",
- "expectation": "blocked"
- },
- document.querySelector("meta[name=assert]").content,
- new SanityChecker()
- ).start();
- </script>
- <div id="log"></div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html
new file mode 100644
index 00000000000..d2d15b98dce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+ <head>
+ <title>Mixed-Content: Blockable content</title>
+ <meta charset='utf-8'>
+ <meta name="description" content="Test behavior of blockable content.">
+ <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+ <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+ <meta name="assert" content="opt_in_method: http-csp
+ origin: same-host-http
+ source_scheme: https
+ context_nesting: top-level
+ redirection: swap-scheme-redirect
+ subresource: link-prefetch-tag
+ expectation: blocked">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/mixed-content/generic/common.js"></script>
+ <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+ </head>
+ <body>
+ <script>
+ MixedContentTestCase(
+ {
+ "opt_in_method": "http-csp",
+ "origin": "same-host-http",
+ "source_scheme": "https",
+ "context_nesting": "top-level",
+ "redirection": "swap-scheme-redirect",
+ "subresource": "link-prefetch-tag",
+ "expectation": "blocked"
+ },
+ document.querySelector("meta[name=assert]").content,
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html.headers
index 46e2255e388..46e2255e388 100644
--- a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html.headers
+++ b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/blockable/opt-in-blocks.https.html.headers
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html
deleted file mode 100644
index ab0378461d1..00000000000
--- a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/http-csp/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/opt-in-blocks.https.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
-<html>
- <head>
- <title>Mixed-Content: Optionally-blockable content</title>
- <meta charset='utf-8'>
- <meta name="description" content="Test behavior of optionally-blockable content">
- <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
- <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-optionally-blockable">
- <meta name="assert" content="opt_in_method: http-csp
- origin: same-host-http
- source_scheme: https
- context_nesting: top-level
- redirection: swap-scheme-redirect
- subresource: link-prefetch-tag
- expectation: blocked">
- <script src="/resources/testharness.js"></script>
- <script src="/resources/testharnessreport.js"></script>
- <script src="/mixed-content/generic/common.js"></script>
- <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
- </head>
- <body>
- <script>
- MixedContentTestCase(
- {
- "opt_in_method": "http-csp",
- "origin": "same-host-http",
- "source_scheme": "https",
- "context_nesting": "top-level",
- "redirection": "swap-scheme-redirect",
- "subresource": "link-prefetch-tag",
- "expectation": "blocked"
- },
- document.querySelector("meta[name=assert]").content,
- new SanityChecker()
- ).start();
- </script>
- <div id="log"></div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/meta-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/meta-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html
new file mode 100644
index 00000000000..16c1e07a50e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/meta-csp/cross-origin-http/top-level/no-redirect/blockable/opt-in-blocks.https.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+ <head>
+ <title>Mixed-Content: Blockable content</title>
+ <meta charset='utf-8'>
+ <meta name="description" content="Test behavior of blockable content.">
+ <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+ <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+ <meta name="assert" content="opt_in_method: meta-csp
+ origin: cross-origin-http
+ source_scheme: https
+ context_nesting: top-level
+ redirection: no-redirect
+ subresource: link-prefetch-tag
+ expectation: blocked">
+ <meta http-equiv="Content-Security-Policy" content="block-all-mixed-content">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/mixed-content/generic/common.js"></script>
+ <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+ </head>
+ <body>
+ <script>
+ MixedContentTestCase(
+ {
+ "opt_in_method": "meta-csp",
+ "origin": "cross-origin-http",
+ "source_scheme": "https",
+ "context_nesting": "top-level",
+ "redirection": "no-redirect",
+ "subresource": "link-prefetch-tag",
+ "expectation": "blocked"
+ },
+ document.querySelector("meta[name=assert]").content,
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/meta-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/meta-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html
deleted file mode 100644
index 7f5cc295598..00000000000
--- a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/meta-csp/cross-origin-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html
+++ /dev/null
@@ -1,41 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
-<html>
- <head>
- <title>Mixed-Content: Optionally-blockable content</title>
- <meta charset='utf-8'>
- <meta name="description" content="Test behavior of optionally-blockable content">
- <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
- <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-optionally-blockable">
- <meta name="assert" content="opt_in_method: meta-csp
- origin: cross-origin-http
- source_scheme: https
- context_nesting: top-level
- redirection: no-redirect
- subresource: link-prefetch-tag
- expectation: blocked">
- <meta http-equiv="Content-Security-Policy" content="block-all-mixed-content">
- <script src="/resources/testharness.js"></script>
- <script src="/resources/testharnessreport.js"></script>
- <script src="/mixed-content/generic/common.js"></script>
- <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
- </head>
- <body>
- <script>
- MixedContentTestCase(
- {
- "opt_in_method": "meta-csp",
- "origin": "cross-origin-http",
- "source_scheme": "https",
- "context_nesting": "top-level",
- "redirection": "no-redirect",
- "subresource": "link-prefetch-tag",
- "expectation": "blocked"
- },
- document.querySelector("meta[name=assert]").content,
- new SanityChecker()
- ).start();
- </script>
- <div id="log"></div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/meta-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/meta-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html
new file mode 100644
index 00000000000..f3adaf6cec9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/meta-csp/same-host-http/top-level/no-redirect/blockable/opt-in-blocks.https.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+ <head>
+ <title>Mixed-Content: Blockable content</title>
+ <meta charset='utf-8'>
+ <meta name="description" content="Test behavior of blockable content.">
+ <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+ <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+ <meta name="assert" content="opt_in_method: meta-csp
+ origin: same-host-http
+ source_scheme: https
+ context_nesting: top-level
+ redirection: no-redirect
+ subresource: link-prefetch-tag
+ expectation: blocked">
+ <meta http-equiv="Content-Security-Policy" content="block-all-mixed-content">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/mixed-content/generic/common.js"></script>
+ <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+ </head>
+ <body>
+ <script>
+ MixedContentTestCase(
+ {
+ "opt_in_method": "meta-csp",
+ "origin": "same-host-http",
+ "source_scheme": "https",
+ "context_nesting": "top-level",
+ "redirection": "no-redirect",
+ "subresource": "link-prefetch-tag",
+ "expectation": "blocked"
+ },
+ document.querySelector("meta[name=assert]").content,
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/meta-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/meta-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html
deleted file mode 100644
index 28003d9a1bd..00000000000
--- a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/meta-csp/same-host-http/top-level/no-redirect/optionally-blockable/opt-in-blocks.https.html
+++ /dev/null
@@ -1,41 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
-<html>
- <head>
- <title>Mixed-Content: Optionally-blockable content</title>
- <meta charset='utf-8'>
- <meta name="description" content="Test behavior of optionally-blockable content">
- <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
- <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-optionally-blockable">
- <meta name="assert" content="opt_in_method: meta-csp
- origin: same-host-http
- source_scheme: https
- context_nesting: top-level
- redirection: no-redirect
- subresource: link-prefetch-tag
- expectation: blocked">
- <meta http-equiv="Content-Security-Policy" content="block-all-mixed-content">
- <script src="/resources/testharness.js"></script>
- <script src="/resources/testharnessreport.js"></script>
- <script src="/mixed-content/generic/common.js"></script>
- <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
- </head>
- <body>
- <script>
- MixedContentTestCase(
- {
- "opt_in_method": "meta-csp",
- "origin": "same-host-http",
- "source_scheme": "https",
- "context_nesting": "top-level",
- "redirection": "no-redirect",
- "subresource": "link-prefetch-tag",
- "expectation": "blocked"
- },
- document.querySelector("meta[name=assert]").content,
- new SanityChecker()
- ).start();
- </script>
- <div id="log"></div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/keep-scheme-redirect/blockable/no-opt-in-blocks.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/keep-scheme-redirect/blockable/no-opt-in-blocks.https.html
new file mode 100644
index 00000000000..6db10199649
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/keep-scheme-redirect/blockable/no-opt-in-blocks.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+ <head>
+ <title>Mixed-Content: Blockable content</title>
+ <meta charset='utf-8'>
+ <meta name="description" content="Test behavior of blockable content.">
+ <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+ <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+ <meta name="assert" content="opt_in_method: no-opt-in
+ origin: cross-origin-http
+ source_scheme: https
+ context_nesting: top-level
+ redirection: keep-scheme-redirect
+ subresource: link-prefetch-tag
+ expectation: blocked">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/mixed-content/generic/common.js"></script>
+ <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+ </head>
+ <body>
+ <script>
+ MixedContentTestCase(
+ {
+ "opt_in_method": "no-opt-in",
+ "origin": "cross-origin-http",
+ "source_scheme": "https",
+ "context_nesting": "top-level",
+ "redirection": "keep-scheme-redirect",
+ "subresource": "link-prefetch-tag",
+ "expectation": "blocked"
+ },
+ document.querySelector("meta[name=assert]").content,
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html
deleted file mode 100644
index 76629861437..00000000000
--- a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
-<html>
- <head>
- <title>Mixed-Content: Optionally-blockable content</title>
- <meta charset='utf-8'>
- <meta name="description" content="Test behavior of optionally-blockable content">
- <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
- <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-optionally-blockable">
- <meta name="assert" content="opt_in_method: no-opt-in
- origin: cross-origin-http
- source_scheme: https
- context_nesting: top-level
- redirection: keep-scheme-redirect
- subresource: link-prefetch-tag
- expectation: allowed">
- <script src="/resources/testharness.js"></script>
- <script src="/resources/testharnessreport.js"></script>
- <script src="/mixed-content/generic/common.js"></script>
- <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
- </head>
- <body>
- <script>
- MixedContentTestCase(
- {
- "opt_in_method": "no-opt-in",
- "origin": "cross-origin-http",
- "source_scheme": "https",
- "context_nesting": "top-level",
- "redirection": "keep-scheme-redirect",
- "subresource": "link-prefetch-tag",
- "expectation": "allowed"
- },
- document.querySelector("meta[name=assert]").content,
- new SanityChecker()
- ).start();
- </script>
- <div id="log"></div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/no-redirect/blockable/no-opt-in-blocks.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/no-redirect/blockable/no-opt-in-blocks.https.html
new file mode 100644
index 00000000000..5c41820d55d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/no-redirect/blockable/no-opt-in-blocks.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+ <head>
+ <title>Mixed-Content: Blockable content</title>
+ <meta charset='utf-8'>
+ <meta name="description" content="Test behavior of blockable content.">
+ <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+ <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+ <meta name="assert" content="opt_in_method: no-opt-in
+ origin: cross-origin-http
+ source_scheme: https
+ context_nesting: top-level
+ redirection: no-redirect
+ subresource: link-prefetch-tag
+ expectation: blocked">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/mixed-content/generic/common.js"></script>
+ <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+ </head>
+ <body>
+ <script>
+ MixedContentTestCase(
+ {
+ "opt_in_method": "no-opt-in",
+ "origin": "cross-origin-http",
+ "source_scheme": "https",
+ "context_nesting": "top-level",
+ "redirection": "no-redirect",
+ "subresource": "link-prefetch-tag",
+ "expectation": "blocked"
+ },
+ document.querySelector("meta[name=assert]").content,
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/no-redirect/optionally-blockable/no-opt-in-allows.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/no-redirect/optionally-blockable/no-opt-in-allows.https.html
deleted file mode 100644
index 5bcce0017db..00000000000
--- a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/no-redirect/optionally-blockable/no-opt-in-allows.https.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
-<html>
- <head>
- <title>Mixed-Content: Optionally-blockable content</title>
- <meta charset='utf-8'>
- <meta name="description" content="Test behavior of optionally-blockable content">
- <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
- <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-optionally-blockable">
- <meta name="assert" content="opt_in_method: no-opt-in
- origin: cross-origin-http
- source_scheme: https
- context_nesting: top-level
- redirection: no-redirect
- subresource: link-prefetch-tag
- expectation: allowed">
- <script src="/resources/testharness.js"></script>
- <script src="/resources/testharnessreport.js"></script>
- <script src="/mixed-content/generic/common.js"></script>
- <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
- </head>
- <body>
- <script>
- MixedContentTestCase(
- {
- "opt_in_method": "no-opt-in",
- "origin": "cross-origin-http",
- "source_scheme": "https",
- "context_nesting": "top-level",
- "redirection": "no-redirect",
- "subresource": "link-prefetch-tag",
- "expectation": "allowed"
- },
- document.querySelector("meta[name=assert]").content,
- new SanityChecker()
- ).start();
- </script>
- <div id="log"></div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/swap-scheme-redirect/blockable/no-opt-in-blocks.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/swap-scheme-redirect/blockable/no-opt-in-blocks.https.html
new file mode 100644
index 00000000000..afa70d38e96
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/swap-scheme-redirect/blockable/no-opt-in-blocks.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+ <head>
+ <title>Mixed-Content: Blockable content</title>
+ <meta charset='utf-8'>
+ <meta name="description" content="Test behavior of blockable content.">
+ <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+ <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+ <meta name="assert" content="opt_in_method: no-opt-in
+ origin: cross-origin-http
+ source_scheme: https
+ context_nesting: top-level
+ redirection: swap-scheme-redirect
+ subresource: link-prefetch-tag
+ expectation: blocked">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/mixed-content/generic/common.js"></script>
+ <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+ </head>
+ <body>
+ <script>
+ MixedContentTestCase(
+ {
+ "opt_in_method": "no-opt-in",
+ "origin": "cross-origin-http",
+ "source_scheme": "https",
+ "context_nesting": "top-level",
+ "redirection": "swap-scheme-redirect",
+ "subresource": "link-prefetch-tag",
+ "expectation": "blocked"
+ },
+ document.querySelector("meta[name=assert]").content,
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html
deleted file mode 100644
index 31230323496..00000000000
--- a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/cross-origin-http/top-level/swap-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
-<html>
- <head>
- <title>Mixed-Content: Optionally-blockable content</title>
- <meta charset='utf-8'>
- <meta name="description" content="Test behavior of optionally-blockable content">
- <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
- <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-optionally-blockable">
- <meta name="assert" content="opt_in_method: no-opt-in
- origin: cross-origin-http
- source_scheme: https
- context_nesting: top-level
- redirection: swap-scheme-redirect
- subresource: link-prefetch-tag
- expectation: allowed">
- <script src="/resources/testharness.js"></script>
- <script src="/resources/testharnessreport.js"></script>
- <script src="/mixed-content/generic/common.js"></script>
- <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
- </head>
- <body>
- <script>
- MixedContentTestCase(
- {
- "opt_in_method": "no-opt-in",
- "origin": "cross-origin-http",
- "source_scheme": "https",
- "context_nesting": "top-level",
- "redirection": "swap-scheme-redirect",
- "subresource": "link-prefetch-tag",
- "expectation": "allowed"
- },
- document.querySelector("meta[name=assert]").content,
- new SanityChecker()
- ).start();
- </script>
- <div id="log"></div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/keep-scheme-redirect/blockable/no-opt-in-blocks.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/keep-scheme-redirect/blockable/no-opt-in-blocks.https.html
new file mode 100644
index 00000000000..00241b622cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/keep-scheme-redirect/blockable/no-opt-in-blocks.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+ <head>
+ <title>Mixed-Content: Blockable content</title>
+ <meta charset='utf-8'>
+ <meta name="description" content="Test behavior of blockable content.">
+ <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+ <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+ <meta name="assert" content="opt_in_method: no-opt-in
+ origin: same-host-http
+ source_scheme: https
+ context_nesting: top-level
+ redirection: keep-scheme-redirect
+ subresource: link-prefetch-tag
+ expectation: blocked">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/mixed-content/generic/common.js"></script>
+ <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+ </head>
+ <body>
+ <script>
+ MixedContentTestCase(
+ {
+ "opt_in_method": "no-opt-in",
+ "origin": "same-host-http",
+ "source_scheme": "https",
+ "context_nesting": "top-level",
+ "redirection": "keep-scheme-redirect",
+ "subresource": "link-prefetch-tag",
+ "expectation": "blocked"
+ },
+ document.querySelector("meta[name=assert]").content,
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html
deleted file mode 100644
index 26c76572040..00000000000
--- a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/keep-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
-<html>
- <head>
- <title>Mixed-Content: Optionally-blockable content</title>
- <meta charset='utf-8'>
- <meta name="description" content="Test behavior of optionally-blockable content">
- <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
- <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-optionally-blockable">
- <meta name="assert" content="opt_in_method: no-opt-in
- origin: same-host-http
- source_scheme: https
- context_nesting: top-level
- redirection: keep-scheme-redirect
- subresource: link-prefetch-tag
- expectation: allowed">
- <script src="/resources/testharness.js"></script>
- <script src="/resources/testharnessreport.js"></script>
- <script src="/mixed-content/generic/common.js"></script>
- <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
- </head>
- <body>
- <script>
- MixedContentTestCase(
- {
- "opt_in_method": "no-opt-in",
- "origin": "same-host-http",
- "source_scheme": "https",
- "context_nesting": "top-level",
- "redirection": "keep-scheme-redirect",
- "subresource": "link-prefetch-tag",
- "expectation": "allowed"
- },
- document.querySelector("meta[name=assert]").content,
- new SanityChecker()
- ).start();
- </script>
- <div id="log"></div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/no-redirect/blockable/no-opt-in-blocks.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/no-redirect/blockable/no-opt-in-blocks.https.html
new file mode 100644
index 00000000000..f1be54283e0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/no-redirect/blockable/no-opt-in-blocks.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+ <head>
+ <title>Mixed-Content: Blockable content</title>
+ <meta charset='utf-8'>
+ <meta name="description" content="Test behavior of blockable content.">
+ <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+ <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+ <meta name="assert" content="opt_in_method: no-opt-in
+ origin: same-host-http
+ source_scheme: https
+ context_nesting: top-level
+ redirection: no-redirect
+ subresource: link-prefetch-tag
+ expectation: blocked">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/mixed-content/generic/common.js"></script>
+ <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+ </head>
+ <body>
+ <script>
+ MixedContentTestCase(
+ {
+ "opt_in_method": "no-opt-in",
+ "origin": "same-host-http",
+ "source_scheme": "https",
+ "context_nesting": "top-level",
+ "redirection": "no-redirect",
+ "subresource": "link-prefetch-tag",
+ "expectation": "blocked"
+ },
+ document.querySelector("meta[name=assert]").content,
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/no-redirect/optionally-blockable/no-opt-in-allows.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/no-redirect/optionally-blockable/no-opt-in-allows.https.html
deleted file mode 100644
index 582f6c63a5d..00000000000
--- a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/no-redirect/optionally-blockable/no-opt-in-allows.https.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
-<html>
- <head>
- <title>Mixed-Content: Optionally-blockable content</title>
- <meta charset='utf-8'>
- <meta name="description" content="Test behavior of optionally-blockable content">
- <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
- <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-optionally-blockable">
- <meta name="assert" content="opt_in_method: no-opt-in
- origin: same-host-http
- source_scheme: https
- context_nesting: top-level
- redirection: no-redirect
- subresource: link-prefetch-tag
- expectation: allowed">
- <script src="/resources/testharness.js"></script>
- <script src="/resources/testharnessreport.js"></script>
- <script src="/mixed-content/generic/common.js"></script>
- <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
- </head>
- <body>
- <script>
- MixedContentTestCase(
- {
- "opt_in_method": "no-opt-in",
- "origin": "same-host-http",
- "source_scheme": "https",
- "context_nesting": "top-level",
- "redirection": "no-redirect",
- "subresource": "link-prefetch-tag",
- "expectation": "allowed"
- },
- document.querySelector("meta[name=assert]").content,
- new SanityChecker()
- ).start();
- </script>
- <div id="log"></div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/swap-scheme-redirect/blockable/no-opt-in-blocks.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/swap-scheme-redirect/blockable/no-opt-in-blocks.https.html
new file mode 100644
index 00000000000..bc14146a24b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/swap-scheme-redirect/blockable/no-opt-in-blocks.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+ <head>
+ <title>Mixed-Content: Blockable content</title>
+ <meta charset='utf-8'>
+ <meta name="description" content="Test behavior of blockable content.">
+ <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+ <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+ <meta name="assert" content="opt_in_method: no-opt-in
+ origin: same-host-http
+ source_scheme: https
+ context_nesting: top-level
+ redirection: swap-scheme-redirect
+ subresource: link-prefetch-tag
+ expectation: blocked">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/mixed-content/generic/common.js"></script>
+ <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+ </head>
+ <body>
+ <script>
+ MixedContentTestCase(
+ {
+ "opt_in_method": "no-opt-in",
+ "origin": "same-host-http",
+ "source_scheme": "https",
+ "context_nesting": "top-level",
+ "redirection": "swap-scheme-redirect",
+ "subresource": "link-prefetch-tag",
+ "expectation": "blocked"
+ },
+ document.querySelector("meta[name=assert]").content,
+ new SanityChecker()
+ ).start();
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html b/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html
deleted file mode 100644
index a7feabccba1..00000000000
--- a/tests/wpt/web-platform-tests/mixed-content/link-prefetch-tag/no-opt-in/same-host-http/top-level/swap-scheme-redirect/optionally-blockable/no-opt-in-allows.https.html
+++ /dev/null
@@ -1,40 +0,0 @@
-<!DOCTYPE html>
-<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
-<html>
- <head>
- <title>Mixed-Content: Optionally-blockable content</title>
- <meta charset='utf-8'>
- <meta name="description" content="Test behavior of optionally-blockable content">
- <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
- <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-optionally-blockable">
- <meta name="assert" content="opt_in_method: no-opt-in
- origin: same-host-http
- source_scheme: https
- context_nesting: top-level
- redirection: swap-scheme-redirect
- subresource: link-prefetch-tag
- expectation: allowed">
- <script src="/resources/testharness.js"></script>
- <script src="/resources/testharnessreport.js"></script>
- <script src="/mixed-content/generic/common.js"></script>
- <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
- </head>
- <body>
- <script>
- MixedContentTestCase(
- {
- "opt_in_method": "no-opt-in",
- "origin": "same-host-http",
- "source_scheme": "https",
- "context_nesting": "top-level",
- "redirection": "swap-scheme-redirect",
- "subresource": "link-prefetch-tag",
- "expectation": "allowed"
- },
- document.querySelector("meta[name=assert]").content,
- new SanityChecker()
- ).start();
- </script>
- <div id="log"></div>
- </body>
-</html>
diff --git a/tests/wpt/web-platform-tests/mixed-content/spec.src.json b/tests/wpt/web-platform-tests/mixed-content/spec.src.json
index 536646d3cea..e59fa9f8c4c 100644
--- a/tests/wpt/web-platform-tests/mixed-content/spec.src.json
+++ b/tests/wpt/web-platform-tests/mixed-content/spec.src.json
@@ -239,13 +239,13 @@
"a-tag",
"object-tag",
"picture-tag",
- "websocket-request"
+ "websocket-request",
+ "link-prefetch-tag"
],
"optionally-blockable": [
"img-tag",
"audio-tag",
- "video-tag",
- "link-prefetch-tag"
+ "video-tag"
]
},
"expectation": [
diff --git a/tests/wpt/web-platform-tests/mixed-content/spec_json.js b/tests/wpt/web-platform-tests/mixed-content/spec_json.js
index 44012ee40ab..f70e3ccc000 100644
--- a/tests/wpt/web-platform-tests/mixed-content/spec_json.js
+++ b/tests/wpt/web-platform-tests/mixed-content/spec_json.js
@@ -1 +1 @@
-var SPEC_JSON = {"test_expansion_schema": {"origin": ["same-host-https", "same-host-http", "cross-origin-https", "cross-origin-http", "same-host-wss", "same-host-ws", "cross-origin-wss", "cross-origin-ws"], "subresource": {"blockable": ["script-tag", "link-css-tag", "xhr-request", "worker-request", "fetch-request", "a-tag", "object-tag", "picture-tag", "websocket-request"], "optionally-blockable": ["img-tag", "audio-tag", "video-tag", "link-prefetch-tag"]}, "context_nesting": ["top-level", "sub-level"], "expectation": ["allowed", "blocked"], "expansion": ["default", "override"], "redirection": ["no-redirect", "keep-scheme-redirect", "swap-scheme-redirect"], "opt_in_method": ["no-opt-in", "http-csp", "meta-csp", "img-crossorigin"], "source_scheme": ["http", "https"]}, "specification": [{"test_expansion": [{"origin": ["cross-origin-http", "same-host-http"], "name": "opt-in-blocks", "redirection": "*", "expectation": "blocked", "expansion": "default", "context_nesting": "top-level", "opt_in_method": ["http-csp", "meta-csp"], "source_scheme": "https", "subresource": {"blockable": [], "optionally-blockable": "*"}}, {"origin": ["cross-origin-http", "same-host-http"], "name": "no-opt-in-allows", "redirection": "*", "expectation": "allowed", "expansion": "default", "context_nesting": "top-level", "opt_in_method": "no-opt-in", "source_scheme": "https", "subresource": {"blockable": [], "optionally-blockable": "*"}}], "description": "Test behavior of optionally-blockable content", "specification_url": "http://www.w3.org/TR/mixed-content/#category-optionally-blockable", "name": "optionally-blockable", "title": "Optionally-blockable content"}, {"test_expansion": [{"origin": ["cross-origin-http", "same-host-http"], "name": "opt-in-blocks", "redirection": "*", "expectation": "blocked", "expansion": "default", "context_nesting": "top-level", "opt_in_method": ["http-csp", "meta-csp"], "source_scheme": "https", "subresource": {"blockable": "*", "optionally-blockable": []}}, {"origin": ["cross-origin-http", "same-host-http"], "name": "no-opt-in-blocks", "redirection": "*", "expectation": "blocked", "expansion": "default", "context_nesting": "top-level", "opt_in_method": "no-opt-in", "source_scheme": "https", "subresource": {"blockable": "*", "optionally-blockable": []}}, {"origin": ["cross-origin-ws", "same-host-ws"], "name": "ws-downgrade-blocks", "redirection": "*", "expectation": "blocked", "expansion": "default", "context_nesting": "top-level", "opt_in_method": ["no-opt-in", "http-csp", "meta-csp"], "source_scheme": "https", "subresource": {"blockable": "websocket-request", "optionally-blockable": []}}], "description": "Test behavior of blockable content.", "specification_url": "http://www.w3.org/TR/mixed-content/#category-blockable", "name": "blockable", "title": "Blockable content"}, {"test_expansion": [{"origin": ["same-host-https"], "name": "allowed", "redirection": ["no-redirect", "keep-scheme-redirect"], "expectation": "allowed", "expansion": "default", "context_nesting": "top-level", "opt_in_method": "*", "source_scheme": "https", "subresource": {"blockable": "*", "optionally-blockable": "*"}}, {"origin": ["same-host-wss"], "name": "websocket-allowed", "redirection": ["no-redirect", "keep-scheme-redirect"], "expectation": "allowed", "expansion": "default", "context_nesting": "top-level", "opt_in_method": "*", "source_scheme": "https", "subresource": {"blockable": "websocket-request", "optionally-blockable": []}}], "description": "Test behavior of allowed content.", "specification_url": "http://www.w3.org/TR/mixed-content/", "name": "allowed", "title": "Allowed content"}], "excluded_tests": [{"origin": "*", "name": "Redundant-subresources", "redirection": "*", "expectation": "*", "expansion": "*", "context_nesting": "*", "opt_in_method": "*", "source_scheme": "*", "subresource": {"blockable": ["a-tag"], "optionally-blockable": []}}, {"origin": ["same-host-https", "same-host-http", "cross-origin-https", "cross-origin-http"], "name": "Skip-origins-not-applicable-to-websockets", "redirection": "*", "expectation": "*", "expansion": "*", "context_nesting": "*", "opt_in_method": "*", "source_scheme": "*", "subresource": {"blockable": ["websocket-request"], "optionally-blockable": []}}, {"origin": "*", "name": "TODO-opt-in-method-img-cross-origin", "redirection": "*", "expectation": "*", "expansion": "*", "context_nesting": "*", "opt_in_method": "img-crossorigin", "source_scheme": "*", "subresource": {"blockable": "*", "optionally-blockable": "*"}}, {"origin": "*", "name": "Skip-redundant-for-opt-in-method", "redirection": ["keep-scheme-redirect", "swap-scheme-redirect"], "expectation": "*", "expansion": "*", "context_nesting": "*", "opt_in_method": ["meta-csp", "img-crossorigin"], "source_scheme": "*", "subresource": {"blockable": "*", "optionally-blockable": "*"}}]};
+var SPEC_JSON = {"test_expansion_schema": {"origin": ["same-host-https", "same-host-http", "cross-origin-https", "cross-origin-http", "same-host-wss", "same-host-ws", "cross-origin-wss", "cross-origin-ws"], "subresource": {"blockable": ["script-tag", "link-css-tag", "xhr-request", "worker-request", "fetch-request", "a-tag", "object-tag", "picture-tag", "websocket-request", "link-prefetch-tag"], "optionally-blockable": ["img-tag", "audio-tag", "video-tag"]}, "context_nesting": ["top-level", "sub-level"], "expectation": ["allowed", "blocked"], "expansion": ["default", "override"], "redirection": ["no-redirect", "keep-scheme-redirect", "swap-scheme-redirect"], "opt_in_method": ["no-opt-in", "http-csp", "meta-csp", "img-crossorigin"], "source_scheme": ["http", "https"]}, "specification": [{"test_expansion": [{"origin": ["cross-origin-http", "same-host-http"], "name": "opt-in-blocks", "redirection": "*", "expectation": "blocked", "expansion": "default", "context_nesting": "top-level", "opt_in_method": ["http-csp", "meta-csp"], "source_scheme": "https", "subresource": {"blockable": [], "optionally-blockable": "*"}}, {"origin": ["cross-origin-http", "same-host-http"], "name": "no-opt-in-allows", "redirection": "*", "expectation": "allowed", "expansion": "default", "context_nesting": "top-level", "opt_in_method": "no-opt-in", "source_scheme": "https", "subresource": {"blockable": [], "optionally-blockable": "*"}}], "description": "Test behavior of optionally-blockable content", "specification_url": "http://www.w3.org/TR/mixed-content/#category-optionally-blockable", "name": "optionally-blockable", "title": "Optionally-blockable content"}, {"test_expansion": [{"origin": ["cross-origin-http", "same-host-http"], "name": "opt-in-blocks", "redirection": "*", "expectation": "blocked", "expansion": "default", "context_nesting": "top-level", "opt_in_method": ["http-csp", "meta-csp"], "source_scheme": "https", "subresource": {"blockable": "*", "optionally-blockable": []}}, {"origin": ["cross-origin-http", "same-host-http"], "name": "no-opt-in-blocks", "redirection": "*", "expectation": "blocked", "expansion": "default", "context_nesting": "top-level", "opt_in_method": "no-opt-in", "source_scheme": "https", "subresource": {"blockable": "*", "optionally-blockable": []}}, {"origin": ["cross-origin-ws", "same-host-ws"], "name": "ws-downgrade-blocks", "redirection": "*", "expectation": "blocked", "expansion": "default", "context_nesting": "top-level", "opt_in_method": ["no-opt-in", "http-csp", "meta-csp"], "source_scheme": "https", "subresource": {"blockable": "websocket-request", "optionally-blockable": []}}], "description": "Test behavior of blockable content.", "specification_url": "http://www.w3.org/TR/mixed-content/#category-blockable", "name": "blockable", "title": "Blockable content"}, {"test_expansion": [{"origin": ["same-host-https"], "name": "allowed", "redirection": ["no-redirect", "keep-scheme-redirect"], "expectation": "allowed", "expansion": "default", "context_nesting": "top-level", "opt_in_method": "*", "source_scheme": "https", "subresource": {"blockable": "*", "optionally-blockable": "*"}}, {"origin": ["same-host-wss"], "name": "websocket-allowed", "redirection": ["no-redirect", "keep-scheme-redirect"], "expectation": "allowed", "expansion": "default", "context_nesting": "top-level", "opt_in_method": "*", "source_scheme": "https", "subresource": {"blockable": "websocket-request", "optionally-blockable": []}}], "description": "Test behavior of allowed content.", "specification_url": "http://www.w3.org/TR/mixed-content/", "name": "allowed", "title": "Allowed content"}], "excluded_tests": [{"origin": "*", "name": "Redundant-subresources", "redirection": "*", "expectation": "*", "expansion": "*", "context_nesting": "*", "opt_in_method": "*", "source_scheme": "*", "subresource": {"blockable": ["a-tag"], "optionally-blockable": []}}, {"origin": ["same-host-https", "same-host-http", "cross-origin-https", "cross-origin-http"], "name": "Skip-origins-not-applicable-to-websockets", "redirection": "*", "expectation": "*", "expansion": "*", "context_nesting": "*", "opt_in_method": "*", "source_scheme": "*", "subresource": {"blockable": ["websocket-request"], "optionally-blockable": []}}, {"origin": "*", "name": "TODO-opt-in-method-img-cross-origin", "redirection": "*", "expectation": "*", "expansion": "*", "context_nesting": "*", "opt_in_method": "img-crossorigin", "source_scheme": "*", "subresource": {"blockable": "*", "optionally-blockable": "*"}}, {"origin": "*", "name": "Skip-redundant-for-opt-in-method", "redirection": ["keep-scheme-redirect", "swap-scheme-redirect"], "expectation": "*", "expansion": "*", "context_nesting": "*", "opt_in_method": ["meta-csp", "img-crossorigin"], "source_scheme": "*", "subresource": {"blockable": "*", "optionally-blockable": "*"}}]};
diff --git a/tests/wpt/web-platform-tests/navigation-timing/idlharness.html b/tests/wpt/web-platform-tests/navigation-timing/idlharness.html
index ab8fd74e1f4..6c2d488ddc0 100644
--- a/tests/wpt/web-platform-tests/navigation-timing/idlharness.html
+++ b/tests/wpt/web-platform-tests/navigation-timing/idlharness.html
@@ -19,11 +19,6 @@
<pre id='untested_idl' style='display:none'>
typedef double DOMHighResTimeStamp;
-interface Window {
- [Replaceable]
- readonly attribute Performance performance;
-};
-
[Exposed=(Window,Worker)]
interface Performance {
};
@@ -140,7 +135,8 @@ partial interface Performance {
idl_array.add_untested_idls(document.getElementById("untested_idl").textContent);
idl_array.add_idls(document.getElementById("idl").textContent);
- idl_array.add_objects({PerformanceNavigation: ["window.performance.navigation"],
+ idl_array.add_objects({Performance: ["window.performance"],
+ PerformanceNavigation: ["window.performance.navigation"],
PerformanceTiming: ["window.performance.timing"],
PerformanceNavigationTiming: ["window.performance.getEntriesByType('navigation')[0]"] });
diff --git a/tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-disabled-by-feature-policy.https.html b/tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-disabled-by-feature-policy.https.html
new file mode 100644
index 00000000000..cec214bbc26
--- /dev/null
+++ b/tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-disabled-by-feature-policy.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_disabled(AbsoluteOrientationSensor);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-disabled-by-feature-policy.https.html.headers b/tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-disabled-by-feature-policy.https.html.headers
new file mode 100644
index 00000000000..47d761713ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-disabled-by-feature-policy.https.html.headers
@@ -0,0 +1 @@
+Feature-Policy: accelerometer 'none'; gyroscope 'none'; magnetometer 'none'
diff --git a/tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html b/tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html
new file mode 100644
index 00000000000..2a5debec2cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled_by_attribute_redirect_on_load(AbsoluteOrientationSensor);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy-attribute.https.html b/tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy-attribute.https.html
new file mode 100644
index 00000000000..0b5698f168a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy-attribute.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled_by_attribute(AbsoluteOrientationSensor);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy.https.html b/tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy.https.html
new file mode 100644
index 00000000000..80ed027b09f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled(AbsoluteOrientationSensor);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy.https.html.headers b/tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy.https.html.headers
new file mode 100644
index 00000000000..58366d90bdb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-enabled-by-feature-policy.https.html.headers
@@ -0,0 +1 @@
+Feature-Policy: accelerometer *; gyroscope *; magnetometer *
diff --git a/tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html b/tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html
new file mode 100644
index 00000000000..6e3e4d49ca7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled_on_self_origin(AbsoluteOrientationSensor);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html.headers b/tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html.headers
new file mode 100644
index 00000000000..31cab0de688
--- /dev/null
+++ b/tests/wpt/web-platform-tests/orientation-sensor/AbsoluteOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html.headers
@@ -0,0 +1 @@
+Feature-Policy: accelerometer 'self'; gyroscope 'self'; magnetometer 'self'
diff --git a/tests/wpt/web-platform-tests/orientation-sensor/OrientationSensor.https.html b/tests/wpt/web-platform-tests/orientation-sensor/OrientationSensor.https.html
index dbf0a66038f..5e728a688db 100644
--- a/tests/wpt/web-platform-tests/orientation-sensor/OrientationSensor.https.html
+++ b/tests/wpt/web-platform-tests/orientation-sensor/OrientationSensor.https.html
@@ -15,11 +15,11 @@
const float_precision = 1e-7;
function create_matrix(quat) {
- let X = quat[0];
- let Y = quat[1];
- let Z = quat[2];
- let W = quat[3];
- let mat = new Array(
+ const X = quat[0];
+ const Y = quat[1];
+ const Z = quat[2];
+ const W = quat[3];
+ const mat = new Array(
1-2*Y*Y-2*Z*Z, 2*X*Y-2*Z*W, 2*X*Z+2*Y*W, 0,
2*X*Y+2*Z*W, 1-2*X*X-2*Z*Z, 2*Y*Z-2*X*W, 0,
2*X*Z-2*Y*W, 2*Y*Z+2*W*X, 1-2*X*X-2*Y*Y, 0,
@@ -28,20 +28,20 @@ function create_matrix(quat) {
return mat;
}
-function checkQuaternion(t, sensorType) {
- let sensor = new sensorType();
- sensor.onreading = t.step_func_done(() => {
- assert_equals(sensor.quaternion.length, 4);
- assert_true(sensor.quaternion instanceof Array);
- sensor.stop();
- });
- sensor.onerror = t.step_func_done(unreached);
+async function checkQuaternion(t, sensorType) {
+ const sensor = new sensorType();
+ const eventWatcher = new EventWatcher(t, sensor, ["reading", "error"]);
sensor.start();
+
+ await eventWatcher.wait_for("reading");
+ assert_equals(sensor.quaternion.length, 4);
+ assert_true(sensor.quaternion instanceof Array);
+ sensor.stop();
};
-function checkPopulateMatrix(t, sensorType) {
- let sensor = new sensorType();
- sensor.onerror = t.step_func_done(unreached);
+async function checkPopulateMatrix(t, sensorType) {
+ const sensor = new sensorType();
+ const eventWatcher = new EventWatcher(t, sensor, ["reading", "error"]);
//Throws with insufficient buffer space.
assert_throws({ name: 'TypeError' }, () => sensor.populateMatrix(new Float32Array(15)));
@@ -54,47 +54,46 @@ function checkPopulateMatrix(t, sensorType) {
assert_throws({ name: 'TypeError' }, () => sensor.populateMatrix(new Float32Array(new SharedArrayBuffer(16))));
}
- sensor.onreading = t.step_func_done(() => {
- let quat = sensor.quaternion;
- let mat_expect = create_matrix(quat);
+ sensor.start();
+ await eventWatcher.wait_for("reading");
+ const quat = sensor.quaternion;
+ const mat_expect = create_matrix(quat);
- // Works for all supported types.
- let mat_32 = new Float32Array(16);
- sensor.populateMatrix(mat_32);
- assert_array_approx_equals(mat_32, mat_expect, float_precision);
+ // Works for all supported types.
+ const mat_32 = new Float32Array(16);
+ sensor.populateMatrix(mat_32);
+ assert_array_approx_equals(mat_32, mat_expect, float_precision);
- let mat_64 = new Float64Array(16);
- sensor.populateMatrix(mat_64);
- assert_array_equals(mat_64, mat_expect);
+ const mat_64 = new Float64Array(16);
+ sensor.populateMatrix(mat_64);
+ assert_array_equals(mat_64, mat_expect);
- let mat_dom = new DOMMatrix();
- sensor.populateMatrix(mat_dom);
- assert_array_equals(mat_dom.toFloat64Array(), mat_expect);
+ const mat_dom = new DOMMatrix();
+ sensor.populateMatrix(mat_dom);
+ assert_array_equals(mat_dom.toFloat64Array(), mat_expect);
- // Sets every matrix element.
- mat_64.fill(123);
- sensor.populateMatrix(mat_64);
- assert_array_equals(mat_64, mat_expect);
+ // Sets every matrix element.
+ mat_64.fill(123);
+ sensor.populateMatrix(mat_64);
+ assert_array_equals(mat_64, mat_expect);
- sensor.stop();
- });
- sensor.start();
+ sensor.stop();
}
-async_test(t => {
- checkQuaternion(t, AbsoluteOrientationSensor);
+promise_test(t => {
+ return checkQuaternion(t, AbsoluteOrientationSensor);
}, "Test AbsoluteOrientationSensor.quaternion return a four-element FrozenArray.");
-async_test(t => {
- checkQuaternion(t, RelativeOrientationSensor);
+promise_test(t => {
+ return checkQuaternion(t, RelativeOrientationSensor);
}, "Test RelativeOrientationSensor.quaternion return a four-element FrozenArray.");
-async_test(t => {
- checkPopulateMatrix(t, AbsoluteOrientationSensor);
+promise_test(t => {
+ return checkPopulateMatrix(t, AbsoluteOrientationSensor);
}, "Test AbsoluteOrientationSensor.populateMatrix() method works correctly.");
-async_test(t => {
- checkPopulateMatrix(t, RelativeOrientationSensor);
+promise_test(t => {
+ return checkPopulateMatrix(t, RelativeOrientationSensor);
}, "Test RelativeOrientationSensor.populateMatrix() method works correctly.");
runGenericSensorTests(AbsoluteOrientationSensor);
diff --git a/tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-disabled-by-feature-policy.https.html b/tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-disabled-by-feature-policy.https.html
new file mode 100644
index 00000000000..2c6318fb6af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-disabled-by-feature-policy.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_disabled(RelativeOrientationSensor);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-disabled-by-feature-policy.https.html.headers b/tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-disabled-by-feature-policy.https.html.headers
new file mode 100644
index 00000000000..01f1b4b554c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-disabled-by-feature-policy.https.html.headers
@@ -0,0 +1 @@
+Feature-Policy: accelerometer 'none'; gyroscope 'none'
diff --git a/tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html b/tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html
new file mode 100644
index 00000000000..71d261f0ea9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy-attribute-redirect-on-load.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled_by_attribute_redirect_on_load(RelativeOrientationSensor);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy-attribute.https.html b/tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy-attribute.https.html
new file mode 100644
index 00000000000..88c023d6249
--- /dev/null
+++ b/tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy-attribute.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled_by_attribute(RelativeOrientationSensor);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy.https.html b/tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy.https.html
new file mode 100644
index 00000000000..7ec65e0609d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled(RelativeOrientationSensor);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy.https.html.headers b/tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy.https.html.headers
new file mode 100644
index 00000000000..717e3dd7622
--- /dev/null
+++ b/tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-enabled-by-feature-policy.https.html.headers
@@ -0,0 +1 @@
+Feature-Policy: accelerometer *; gyroscope *
diff --git a/tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html b/tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html
new file mode 100644
index 00000000000..4828d0bc905
--- /dev/null
+++ b/tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
+<script src="/generic-sensor/generic-sensor-feature-policy-test.sub.js"></script>
+<script>
+"use strict";
+
+run_fp_tests_enabled_on_self_origin(RelativeOrientationSensor);
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html.headers b/tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html.headers
new file mode 100644
index 00000000000..ad428b2ea90
--- /dev/null
+++ b/tests/wpt/web-platform-tests/orientation-sensor/RelativeOrientationSensor-enabled-on-self-origin-by-feature-policy.https.html.headers
@@ -0,0 +1 @@
+Feature-Policy: accelerometer 'self'; gyroscope 'self'
diff --git a/tests/wpt/web-platform-tests/paint-timing/child-painting-first-image.html b/tests/wpt/web-platform-tests/paint-timing/child-painting-first-image.html
index 99f761f10a8..4671604cf09 100644
--- a/tests/wpt/web-platform-tests/paint-timing/child-painting-first-image.html
+++ b/tests/wpt/web-platform-tests/paint-timing/child-painting-first-image.html
@@ -7,9 +7,9 @@
async_test(function (t) {
window.addEventListener('message', t.step_func(e => {
assert_equals(e.data, '2 paint first-paint paint first-contentful-paint');
- const bufferedEntries = performance.getEntriesByType('paint');
// When only child frame paints, expect only first-paint.
t.step_timeout( function() {
+ const bufferedEntries = performance.getEntriesByType('paint');
assert_equals(bufferedEntries.length, 1);
assert_equals(bufferedEntries[0].entryType, 'paint');
assert_equals(bufferedEntries[0].name, 'first-paint');
diff --git a/tests/wpt/web-platform-tests/paint-timing/sibling-painting-first-image.html b/tests/wpt/web-platform-tests/paint-timing/sibling-painting-first-image.html
new file mode 100644
index 00000000000..d4197e8a35c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/paint-timing/sibling-painting-first-image.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+ <!-- This iframe will have a sibling that paints, we want to ensure it does not detect that paint. -->
+<iframe id="listening-iframe" src="resources/subframe-sending-paint.html"></iframe>
+<script>
+async_test(function (t) {
+ let paintingIframeHasDispatchedEntries = false;
+ window.addEventListener('message', t.step_func(e => {
+ if (!paintingIframeHasDispatchedEntries) {
+ // Check paint-timing entries from the painting iframe.
+ assert_equals(e.data, '2 paint first-paint paint first-contentful-paint');
+ paintingIframeHasDispatchedEntries = true;
+ // Ask the listening iframe to send its paint-timing entries.
+ document.getElementById('listening-iframe').
+ contentWindow.postMessage('', '*');
+ return;
+ }
+ // Check the paint-timing entries from the listening iframe.
+ assert_equals(e.data, '0');
+ // Check that current frame receives first-paint but not first-contentful-paint.
+ const bufferedEntries = performance.getEntriesByType('paint');
+ assert_equals(bufferedEntries.length, 1);
+ assert_equals(bufferedEntries[0].entryType, 'paint');
+ assert_equals(bufferedEntries[0].name, 'first-paint');
+ t.done();
+ }));
+}, 'Frame ignores paint-timing events fired from sibling frame.');
+</script>
+<!-- This iframe is where all of the painting occurs. -->
+<iframe id="painting-iframe" src="resources/subframe-painting.html"></iframe>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/payment-request/payment-request-constructor.https.html b/tests/wpt/web-platform-tests/payment-request/payment-request-constructor.https.html
index e4e1292f2b9..b5997a0c9be 100644
--- a/tests/wpt/web-platform-tests/payment-request/payment-request-constructor.https.html
+++ b/tests/wpt/web-platform-tests/payment-request/payment-request-constructor.https.html
@@ -15,17 +15,41 @@ const defaultAmount = Object.freeze({
currency: "USD",
value: "1.0",
});
+const defaultNumberAmount = Object.freeze({
+ currency: "USD",
+ value: 1.0,
+});
const defaultTotal = Object.freeze({
label: "Default Total",
amount: defaultAmount,
});
+const defaultNumberTotal = Object.freeze({
+ label: "Default Number Total",
+ amount: defaultNumberAmount,
+});
const defaultDetails = Object.freeze({
total: defaultTotal,
+ displayItems: [
+ {
+ label: "Default Display Item",
+ amount: defaultAmount,
+ },
+ ],
+});
+const defaultNumberDetails = Object.freeze({
+ total: defaultNumberTotal,
+ displayItems: [
+ {
+ label: "Default Display Item",
+ amount: defaultNumberAmount,
+ },
+ ],
});
// Avoid false positives, this should always pass
function smokeTest() {
new PaymentRequest(defaultMethods, defaultDetails);
+ new PaymentRequest(defaultMethods, defaultNumberDetails);
}
test(() => {
smokeTest();
@@ -177,6 +201,7 @@ const invalidTotalAmounts = invalidAmounts.concat([
"-1.0",
"-1.00",
"-1000.000",
+ -10,
]);
test(() => {
smokeTest();
diff --git a/tests/wpt/web-platform-tests/payment-request/payment-request-not-exposed.https.worker.js b/tests/wpt/web-platform-tests/payment-request/payment-request-not-exposed.https.worker.js
new file mode 100644
index 00000000000..df20f801e9d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/payment-request/payment-request-not-exposed.https.worker.js
@@ -0,0 +1,11 @@
+importScripts("/resources/testharness.js");
+
+test(function() {
+ assert_true(isSecureContext);
+ assert_false('PaymentRequest' in self);
+ assert_false('PaymentRequestUpdateEvent' in self);
+ assert_false('PaymentResponse' in self);
+ assert_false('PaymentAddress' in self);
+}, "PaymentRequest constructor must not be exposed in worker global scope");
+
+done();
diff --git a/tests/wpt/web-platform-tests/performance-timeline/performanceentry-tojson.html b/tests/wpt/web-platform-tests/performance-timeline/performanceentry-tojson.html
new file mode 100644
index 00000000000..8576872ec75
--- /dev/null
+++ b/tests/wpt/web-platform-tests/performance-timeline/performanceentry-tojson.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+
+test(() => {
+ performance.mark('markName');
+ performance.measure('measureName');
+
+ const entries = performance.getEntries();
+ const performanceEntryKeys = [
+ 'name',
+ 'entryType',
+ 'startTime',
+ 'duration'
+ ];
+ for (let i = 0; i < entries.length; ++i) {
+ assert_equals(typeof(entries[i].toJSON), 'function');
+ const json = entries[i].toJSON();
+ assert_equals(typeof(json), 'object');
+ for (const key of performanceEntryKeys) {
+ assert_equals(json[key], entries[i][key],
+ `entries[${i}].toJSON().${key} should match entries[${i}].${key}`);
+ }
+ }
+}, 'Test toJSON() in PerformanceEntry');
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/extension/idlharness.html b/tests/wpt/web-platform-tests/pointerevents/extension/idlharness.html
index 985712e5f72..d1bbdebda92 100644
--- a/tests/wpt/web-platform-tests/pointerevents/extension/idlharness.html
+++ b/tests/wpt/web-platform-tests/pointerevents/extension/idlharness.html
@@ -7,7 +7,7 @@
<script src="/resources/idlharness.js"></script>
<pre id='untested_idl' style='display:none'>
-[PrimaryGlobal]
+[Global=Window, Exposed=Window]
interface Window {
};
diff --git a/tests/wpt/web-platform-tests/pointerevents/idlharness.html b/tests/wpt/web-platform-tests/pointerevents/idlharness.html
index a4ba4c35f5b..729d3573e87 100644
--- a/tests/wpt/web-platform-tests/pointerevents/idlharness.html
+++ b/tests/wpt/web-platform-tests/pointerevents/idlharness.html
@@ -7,7 +7,7 @@
<script src="/resources/idlharness.js"></script>
<pre id='untested_idl' style='display:none'>
-[PrimaryGlobal]
+[Global=Window, Exposed=Window]
interface Window {
};
diff --git a/tests/wpt/web-platform-tests/preload/OWNERS b/tests/wpt/web-platform-tests/preload/OWNERS
new file mode 100644
index 00000000000..c65030a6e12
--- /dev/null
+++ b/tests/wpt/web-platform-tests/preload/OWNERS
@@ -0,0 +1,2 @@
+@snuggs
+@yoavweiss
diff --git a/tests/wpt/web-platform-tests/preload/fetch-destination.https.html b/tests/wpt/web-platform-tests/preload/fetch-destination.https.html
deleted file mode 100644
index c7d5142f10e..00000000000
--- a/tests/wpt/web-platform-tests/preload/fetch-destination.https.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<!DOCTYPE html>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/preload/resources/preload_helper.js"></script>
-<script src="../service-workers/service-worker/resources/test-helpers.sub.js"></script>
-<script>
-async_test(function(t) {
- var worker_url = 'resources/fetch-destination-worker.js';
- var scope = 'resources/empty.html';
- var registration;
- verifyPreloadAndRTSupport();
-
- service_worker_unregister_and_register(t, worker_url, scope)
- .then(t.step_func(function(r) {
- registration = r;
- return wait_for_state(t, r.installing, 'activated');
- }))
- .then(t.step_func(function() {
- return with_iframe(scope);
- }))
- .then(t.step_func(function(frame) {
- var link = frame.contentWindow.document.createElement("link");
- link.as = "fetch";
- link.href = "resources/dummy.xml";
- link.rel = "preload";
- link.addEventListener("load", t.step_func_done(function() { registration.unregister(); }));
- link.addEventListener("error", t.step_func_done(function() {
- registration.unregister();
- assert_unreached("Fetch destination preload errored");
- }));
- frame.contentWindow.document.body.appendChild(link);
- }))
- .catch(unreached_rejection(t));
-}, 'Fetch destination preload');
-</script>
diff --git a/tests/wpt/web-platform-tests/preload/modulepreload.html b/tests/wpt/web-platform-tests/preload/modulepreload.html
index 160b37afca2..addd67d46ac 100644
--- a/tests/wpt/web-platform-tests/preload/modulepreload.html
+++ b/tests/wpt/web-platform-tests/preload/modulepreload.html
@@ -53,8 +53,8 @@ promise_test(function(t) {
link.rel = 'modulepreload';
link.href = 'resources/module1.js';
return attachAndWaitForLoad(link).then(() => {
- // Currently, modulepreload doesn't perform submodules fetch.
verifyNumberOfDownloads('resources/module1.js', 1);
+ // The load event fires before (optional) submodules fetch.
verifyNumberOfDownloads('resources/module2.js', 0);
var script = document.createElement('script');
@@ -71,7 +71,7 @@ promise_test(function(t) {
var link = document.createElement('link');
link.rel = 'modulepreload';
link.href = 'resources/syntax-error.js';
- return attachAndWaitForError(link);
+ return attachAndWaitForLoad(link);
}, 'link rel=modulepreload for a module with syntax error');
promise_test(function(t) {
@@ -88,5 +88,37 @@ promise_test(function(t) {
return attachAndWaitForError(link);
}, 'link rel=modulepreload with bad href attribute');
+promise_test(function(t) {
+ var link = document.createElement('link');
+ link.rel = 'modulepreload';
+ link.href = 'resources/module1.js?as-script';
+ link.as = 'script'
+ return attachAndWaitForLoad(link);
+}, 'link rel=modulepreload as=script');
+
+promise_test(function(t) {
+ var link = document.createElement('link');
+ link.rel = 'modulepreload';
+ link.href = 'resources/module1.js?as-image';
+ link.as = 'image'
+ return attachAndWaitForError(link);
+}, 'link rel=modulepreload with invalid as= value');
+
+promise_test(function(t) {
+ var link = document.createElement('link');
+ link.rel = 'modulepreload';
+ link.href = 'resources/module1.js?integrity-match';
+ link.integrity = 'sha256-ZPBZ+J9CiHzZXaBBluSeCpjzuTUkT+rSWIdXUV3AtVo='
+ return attachAndWaitForLoad(link);
+}, 'link rel=modulepreload with integrity match');
+
+promise_test(function(t) {
+ var link = document.createElement('link');
+ link.rel = 'modulepreload';
+ link.href = 'resources/module1.js?integrity-doesnotmatch';
+ link.integrity = 'sha384-doesnotmatch'
+ return attachAndWaitForError(link);
+}, 'link rel=modulepreload with integrity mismatch');
+
</script>
</body>
diff --git a/tests/wpt/web-platform-tests/preload/resources/fetch-destination-worker.js b/tests/wpt/web-platform-tests/preload/resources/fetch-destination-worker.js
deleted file mode 100644
index 57b259e0bf5..00000000000
--- a/tests/wpt/web-platform-tests/preload/resources/fetch-destination-worker.js
+++ /dev/null
@@ -1,9 +0,0 @@
-self.addEventListener('fetch', function(event) {
- if (event.request.url.indexOf('dummy.xml') != -1) {
- if (!event.request.destination || event.request.destination == "")
- event.respondWith(new Response());
- else
- event.respondWith(Response.error());
- }
-});
-
diff --git a/tests/wpt/web-platform-tests/proximity/idlharness.html b/tests/wpt/web-platform-tests/proximity/idlharness.html
index 817aa5c0535..4e30cca04ad 100644
--- a/tests/wpt/web-platform-tests/proximity/idlharness.html
+++ b/tests/wpt/web-platform-tests/proximity/idlharness.html
@@ -15,7 +15,7 @@
<div id="log"></div>
<pre id="untested_idl">
-[PrimaryGlobal]
+[Global=Window, Exposed=Window]
interface Window {
};
diff --git a/tests/wpt/web-platform-tests/quirks-mode/OWNERS b/tests/wpt/web-platform-tests/quirks-mode/OWNERS
deleted file mode 100644
index 8b137891791..00000000000
--- a/tests/wpt/web-platform-tests/quirks-mode/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/tests/wpt/web-platform-tests/quirks-mode/active-and-hover-manual.html b/tests/wpt/web-platform-tests/quirks/active-and-hover-manual.html
index 10d787dd372..10d787dd372 100644
--- a/tests/wpt/web-platform-tests/quirks-mode/active-and-hover-manual.html
+++ b/tests/wpt/web-platform-tests/quirks/active-and-hover-manual.html
diff --git a/tests/wpt/web-platform-tests/quirks-mode/blocks-ignore-line-height.html b/tests/wpt/web-platform-tests/quirks/blocks-ignore-line-height.html
index 608a7c15c79..608a7c15c79 100644
--- a/tests/wpt/web-platform-tests/quirks-mode/blocks-ignore-line-height.html
+++ b/tests/wpt/web-platform-tests/quirks/blocks-ignore-line-height.html
diff --git a/tests/wpt/web-platform-tests/quirks-mode/classname-query-after-sibling-adoption.html b/tests/wpt/web-platform-tests/quirks/classname-query-after-sibling-adoption.html
index 0fcad36776d..0fcad36776d 100644
--- a/tests/wpt/web-platform-tests/quirks-mode/classname-query-after-sibling-adoption.html
+++ b/tests/wpt/web-platform-tests/quirks/classname-query-after-sibling-adoption.html
diff --git a/tests/wpt/web-platform-tests/quirks-mode/hashless-hex-color.html b/tests/wpt/web-platform-tests/quirks/hashless-hex-color.html
index cbda90c0af7..cbda90c0af7 100644
--- a/tests/wpt/web-platform-tests/quirks-mode/hashless-hex-color.html
+++ b/tests/wpt/web-platform-tests/quirks/hashless-hex-color.html
diff --git a/tests/wpt/web-platform-tests/quirks-mode/historical/list-item-bullet-size-ref.html b/tests/wpt/web-platform-tests/quirks/historical/list-item-bullet-size-ref.html
index f449ce9924a..f449ce9924a 100644
--- a/tests/wpt/web-platform-tests/quirks-mode/historical/list-item-bullet-size-ref.html
+++ b/tests/wpt/web-platform-tests/quirks/historical/list-item-bullet-size-ref.html
diff --git a/tests/wpt/web-platform-tests/quirks-mode/historical/list-item-bullet-size.html b/tests/wpt/web-platform-tests/quirks/historical/list-item-bullet-size.html
index bf996edf784..bf996edf784 100644
--- a/tests/wpt/web-platform-tests/quirks-mode/historical/list-item-bullet-size.html
+++ b/tests/wpt/web-platform-tests/quirks/historical/list-item-bullet-size.html
diff --git a/tests/wpt/web-platform-tests/quirks-mode/line-height-calculation.html b/tests/wpt/web-platform-tests/quirks/line-height-calculation.html
index 7e7f03a99b9..7e7f03a99b9 100644
--- a/tests/wpt/web-platform-tests/quirks-mode/line-height-calculation.html
+++ b/tests/wpt/web-platform-tests/quirks/line-height-calculation.html
diff --git a/tests/wpt/web-platform-tests/quirks-mode/percentage-height-calculation.html b/tests/wpt/web-platform-tests/quirks/percentage-height-calculation.html
index 7cadd8b0faf..7cadd8b0faf 100644
--- a/tests/wpt/web-platform-tests/quirks-mode/percentage-height-calculation.html
+++ b/tests/wpt/web-platform-tests/quirks/percentage-height-calculation.html
diff --git a/tests/wpt/web-platform-tests/quirks-mode/supports.html b/tests/wpt/web-platform-tests/quirks/supports.html
index 913f7d9f733..913f7d9f733 100644
--- a/tests/wpt/web-platform-tests/quirks-mode/supports.html
+++ b/tests/wpt/web-platform-tests/quirks/supports.html
diff --git a/tests/wpt/web-platform-tests/quirks-mode/table-cell-nowrap-minimum-width-calculation.html b/tests/wpt/web-platform-tests/quirks/table-cell-nowrap-minimum-width-calculation.html
index 2ff00b9ee79..2ff00b9ee79 100644
--- a/tests/wpt/web-platform-tests/quirks-mode/table-cell-nowrap-minimum-width-calculation.html
+++ b/tests/wpt/web-platform-tests/quirks/table-cell-nowrap-minimum-width-calculation.html
diff --git a/tests/wpt/web-platform-tests/quirks-mode/table-cell-width-calculation.html b/tests/wpt/web-platform-tests/quirks/table-cell-width-calculation.html
index eeb726627b7..eeb726627b7 100644
--- a/tests/wpt/web-platform-tests/quirks-mode/table-cell-width-calculation.html
+++ b/tests/wpt/web-platform-tests/quirks/table-cell-width-calculation.html
diff --git a/tests/wpt/web-platform-tests/quirks-mode/unitless-length.html b/tests/wpt/web-platform-tests/quirks/unitless-length.html
index 944c91fe395..944c91fe395 100644
--- a/tests/wpt/web-platform-tests/quirks-mode/unitless-length.html
+++ b/tests/wpt/web-platform-tests/quirks/unitless-length.html
diff --git a/tests/wpt/web-platform-tests/requestidlecallback/idlharness.html b/tests/wpt/web-platform-tests/requestidlecallback/idlharness.html
index 4007d09fec3..459ce36ebb7 100644
--- a/tests/wpt/web-platform-tests/requestidlecallback/idlharness.html
+++ b/tests/wpt/web-platform-tests/requestidlecallback/idlharness.html
@@ -7,7 +7,7 @@
<script src="/resources/idlharness.js"></script>
<pre id='untested_idl' style='display:none'>
-[PrimaryGlobal]
+[Global=Window, Exposed=Window]
interface Window {
};
</pre>
diff --git a/tests/wpt/web-platform-tests/resource-timing/resource-timing-tojson.html b/tests/wpt/web-platform-tests/resource-timing/resource-timing-tojson.html
new file mode 100644
index 00000000000..77094f4b843
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resource-timing/resource-timing-tojson.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+<head>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+ const img_url = "resources/blue.png";
+ const img = document.createElement("img");
+ img.src = img_url;
+ window.onload = function() {
+ test(() => {
+ const entries = performance.getEntriesByType('resource');
+ assert_greater_than_equal(entries.length, 1);
+ const entry = entries[0];
+ assert_equals(typeof(entry.toJSON), 'function');
+ const json = entry.toJSON();
+ assert_equals(typeof(json), 'object');
+
+ const performanceResourceTimingKeys = [
+ 'name',
+ 'entryType',
+ 'startTime',
+ 'duration',
+ 'initiatorType',
+ 'nextHopProtocol',
+ 'workerStart',
+ 'redirectStart',
+ 'fetchStart',
+ 'domainLookupStart',
+ 'domainLookupEnd',
+ 'connectStart',
+ 'connectEnd',
+ 'secureConnectionStart',
+ 'requestStart',
+ 'responseStart',
+ 'responseEnd',
+ 'transferSize',
+ 'encodedBodySize',
+ 'decodedBodySize'
+ ];
+ for (const key of performanceResourceTimingKeys) {
+ assert_equals(json[key], entry[key],
+ `entry.toJSON().${key} should match entry.${key}`);
+ }
+ }, 'Test toJSON() in PerformanceResourceTiming');
+ };
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/chromium/fake_bluetooth.mojom.js b/tests/wpt/web-platform-tests/resources/chromium/fake_bluetooth.mojom.js
new file mode 100644
index 00000000000..2751e14afe9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/chromium/fake_bluetooth.mojom.js
@@ -0,0 +1,3554 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+(function() {
+ var mojomId = 'device/bluetooth/public/interfaces/test/fake_bluetooth.mojom';
+ if (mojo.internal.isMojomLoaded(mojomId)) {
+ console.warn('The following mojom is loaded multiple times: ' + mojomId);
+ return;
+ }
+ mojo.internal.markMojomLoaded(mojomId);
+
+ // TODO(yzshen): Define these aliases to minimize the differences between the
+ // old/new modes. Remove them when the old mode goes away.
+ var bindings = mojo;
+ var associatedBindings = mojo;
+ var codec = mojo.internal;
+ var validator = mojo.internal;
+
+ var exports = mojo.internal.exposeNamespace('bluetooth.mojom');
+ var uuid$ =
+ mojo.internal.exposeNamespace('bluetooth.mojom');
+ if (mojo.config.autoLoadMojomDeps) {
+ mojo.internal.loadMojomIfNecessary(
+ 'device/bluetooth/public/interfaces/uuid.mojom', '../uuid.mojom.js');
+ }
+
+
+ var kHCISuccess = 0x0000;
+ var kHCIConnectionTimeout = 0x0008;
+ var kGATTSuccess = 0x0000;
+ var kGATTInvalidHandle = 0x0001;
+ var CentralState = {};
+ CentralState.ABSENT = 0;
+ CentralState.POWERED_ON = CentralState.ABSENT + 1;
+ CentralState.POWERED_OFF = CentralState.POWERED_ON + 1;
+
+ CentralState.isKnownEnumValue = function(value) {
+ switch (value) {
+ case 0:
+ case 1:
+ case 2:
+ return true;
+ }
+ return false;
+ };
+
+ CentralState.validate = function(enumValue) {
+ var isExtensible = false;
+ if (isExtensible || this.isKnownEnumValue(enumValue))
+ return validator.validationError.NONE;
+
+ return validator.validationError.UNKNOWN_ENUM_VALUE;
+ };
+
+ function CharacteristicProperties(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ CharacteristicProperties.prototype.initDefaults_ = function() {
+ this.broadcast = false;
+ this.read = false;
+ this.writeWithoutResponse = false;
+ this.write = false;
+ this.notify = false;
+ this.indicate = false;
+ this.authenticatedSignedWrites = false;
+ this.extendedProperties = false;
+ };
+ CharacteristicProperties.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ CharacteristicProperties.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 16}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+
+
+
+
+
+
+
+ return validator.validationError.NONE;
+ };
+
+ CharacteristicProperties.encodedSize = codec.kStructHeaderSize + 8;
+
+ CharacteristicProperties.decode = function(decoder) {
+ var packed;
+ var val = new CharacteristicProperties();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ packed = decoder.readUint8();
+ val.broadcast = (packed >> 0) & 1 ? true : false;
+ val.read = (packed >> 1) & 1 ? true : false;
+ val.writeWithoutResponse = (packed >> 2) & 1 ? true : false;
+ val.write = (packed >> 3) & 1 ? true : false;
+ val.notify = (packed >> 4) & 1 ? true : false;
+ val.indicate = (packed >> 5) & 1 ? true : false;
+ val.authenticatedSignedWrites = (packed >> 6) & 1 ? true : false;
+ val.extendedProperties = (packed >> 7) & 1 ? true : false;
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ return val;
+ };
+
+ CharacteristicProperties.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(CharacteristicProperties.encodedSize);
+ encoder.writeUint32(0);
+ packed = 0;
+ packed |= (val.broadcast & 1) << 0
+ packed |= (val.read & 1) << 1
+ packed |= (val.writeWithoutResponse & 1) << 2
+ packed |= (val.write & 1) << 3
+ packed |= (val.notify & 1) << 4
+ packed |= (val.indicate & 1) << 5
+ packed |= (val.authenticatedSignedWrites & 1) << 6
+ packed |= (val.extendedProperties & 1) << 7
+ encoder.writeUint8(packed);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ };
+ function FakeBluetooth_SetLESupported_Params(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeBluetooth_SetLESupported_Params.prototype.initDefaults_ = function() {
+ this.available = false;
+ };
+ FakeBluetooth_SetLESupported_Params.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeBluetooth_SetLESupported_Params.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 16}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ return validator.validationError.NONE;
+ };
+
+ FakeBluetooth_SetLESupported_Params.encodedSize = codec.kStructHeaderSize + 8;
+
+ FakeBluetooth_SetLESupported_Params.decode = function(decoder) {
+ var packed;
+ var val = new FakeBluetooth_SetLESupported_Params();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ packed = decoder.readUint8();
+ val.available = (packed >> 0) & 1 ? true : false;
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ return val;
+ };
+
+ FakeBluetooth_SetLESupported_Params.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeBluetooth_SetLESupported_Params.encodedSize);
+ encoder.writeUint32(0);
+ packed = 0;
+ packed |= (val.available & 1) << 0
+ encoder.writeUint8(packed);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ };
+ function FakeBluetooth_SetLESupported_ResponseParams(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeBluetooth_SetLESupported_ResponseParams.prototype.initDefaults_ = function() {
+ };
+ FakeBluetooth_SetLESupported_ResponseParams.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeBluetooth_SetLESupported_ResponseParams.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 8}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ return validator.validationError.NONE;
+ };
+
+ FakeBluetooth_SetLESupported_ResponseParams.encodedSize = codec.kStructHeaderSize + 0;
+
+ FakeBluetooth_SetLESupported_ResponseParams.decode = function(decoder) {
+ var packed;
+ var val = new FakeBluetooth_SetLESupported_ResponseParams();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ return val;
+ };
+
+ FakeBluetooth_SetLESupported_ResponseParams.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeBluetooth_SetLESupported_ResponseParams.encodedSize);
+ encoder.writeUint32(0);
+ };
+ function FakeBluetooth_SimulateCentral_Params(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeBluetooth_SimulateCentral_Params.prototype.initDefaults_ = function() {
+ this.state = 0;
+ };
+ FakeBluetooth_SimulateCentral_Params.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeBluetooth_SimulateCentral_Params.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 16}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeBluetooth_SimulateCentral_Params.state
+ err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 0, CentralState);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ return validator.validationError.NONE;
+ };
+
+ FakeBluetooth_SimulateCentral_Params.encodedSize = codec.kStructHeaderSize + 8;
+
+ FakeBluetooth_SimulateCentral_Params.decode = function(decoder) {
+ var packed;
+ var val = new FakeBluetooth_SimulateCentral_Params();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ val.state = decoder.decodeStruct(codec.Int32);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ return val;
+ };
+
+ FakeBluetooth_SimulateCentral_Params.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeBluetooth_SimulateCentral_Params.encodedSize);
+ encoder.writeUint32(0);
+ encoder.encodeStruct(codec.Int32, val.state);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ };
+ function FakeBluetooth_SimulateCentral_ResponseParams(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeBluetooth_SimulateCentral_ResponseParams.prototype.initDefaults_ = function() {
+ this.fakeCentral = new FakeCentralPtr();
+ };
+ FakeBluetooth_SimulateCentral_ResponseParams.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeBluetooth_SimulateCentral_ResponseParams.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 16}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeBluetooth_SimulateCentral_ResponseParams.fakeCentral
+ err = messageValidator.validateInterface(offset + codec.kStructHeaderSize + 0, false);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ return validator.validationError.NONE;
+ };
+
+ FakeBluetooth_SimulateCentral_ResponseParams.encodedSize = codec.kStructHeaderSize + 8;
+
+ FakeBluetooth_SimulateCentral_ResponseParams.decode = function(decoder) {
+ var packed;
+ var val = new FakeBluetooth_SimulateCentral_ResponseParams();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ val.fakeCentral = decoder.decodeStruct(new codec.Interface(FakeCentralPtr));
+ return val;
+ };
+
+ FakeBluetooth_SimulateCentral_ResponseParams.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeBluetooth_SimulateCentral_ResponseParams.encodedSize);
+ encoder.writeUint32(0);
+ encoder.encodeStruct(new codec.Interface(FakeCentralPtr), val.fakeCentral);
+ };
+ function FakeBluetooth_AllResponsesConsumed_Params(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeBluetooth_AllResponsesConsumed_Params.prototype.initDefaults_ = function() {
+ };
+ FakeBluetooth_AllResponsesConsumed_Params.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeBluetooth_AllResponsesConsumed_Params.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 8}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ return validator.validationError.NONE;
+ };
+
+ FakeBluetooth_AllResponsesConsumed_Params.encodedSize = codec.kStructHeaderSize + 0;
+
+ FakeBluetooth_AllResponsesConsumed_Params.decode = function(decoder) {
+ var packed;
+ var val = new FakeBluetooth_AllResponsesConsumed_Params();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ return val;
+ };
+
+ FakeBluetooth_AllResponsesConsumed_Params.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeBluetooth_AllResponsesConsumed_Params.encodedSize);
+ encoder.writeUint32(0);
+ };
+ function FakeBluetooth_AllResponsesConsumed_ResponseParams(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeBluetooth_AllResponsesConsumed_ResponseParams.prototype.initDefaults_ = function() {
+ this.consumed = false;
+ };
+ FakeBluetooth_AllResponsesConsumed_ResponseParams.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeBluetooth_AllResponsesConsumed_ResponseParams.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 16}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ return validator.validationError.NONE;
+ };
+
+ FakeBluetooth_AllResponsesConsumed_ResponseParams.encodedSize = codec.kStructHeaderSize + 8;
+
+ FakeBluetooth_AllResponsesConsumed_ResponseParams.decode = function(decoder) {
+ var packed;
+ var val = new FakeBluetooth_AllResponsesConsumed_ResponseParams();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ packed = decoder.readUint8();
+ val.consumed = (packed >> 0) & 1 ? true : false;
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ return val;
+ };
+
+ FakeBluetooth_AllResponsesConsumed_ResponseParams.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeBluetooth_AllResponsesConsumed_ResponseParams.encodedSize);
+ encoder.writeUint32(0);
+ packed = 0;
+ packed |= (val.consumed & 1) << 0
+ encoder.writeUint8(packed);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ };
+ function FakeCentral_SimulatePreconnectedPeripheral_Params(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_SimulatePreconnectedPeripheral_Params.prototype.initDefaults_ = function() {
+ this.address = null;
+ this.name = null;
+ this.knownServiceUuids = null;
+ };
+ FakeCentral_SimulatePreconnectedPeripheral_Params.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_SimulatePreconnectedPeripheral_Params.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 32}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_SimulatePreconnectedPeripheral_Params.address
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_SimulatePreconnectedPeripheral_Params.name
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_SimulatePreconnectedPeripheral_Params.knownServiceUuids
+ err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 16, 8, new codec.PointerTo(uuid$.UUID), false, [0], 0);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_SimulatePreconnectedPeripheral_Params.encodedSize = codec.kStructHeaderSize + 24;
+
+ FakeCentral_SimulatePreconnectedPeripheral_Params.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_SimulatePreconnectedPeripheral_Params();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ val.address = decoder.decodeStruct(codec.String);
+ val.name = decoder.decodeStruct(codec.String);
+ val.knownServiceUuids = decoder.decodeArrayPointer(new codec.PointerTo(uuid$.UUID));
+ return val;
+ };
+
+ FakeCentral_SimulatePreconnectedPeripheral_Params.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_SimulatePreconnectedPeripheral_Params.encodedSize);
+ encoder.writeUint32(0);
+ encoder.encodeStruct(codec.String, val.address);
+ encoder.encodeStruct(codec.String, val.name);
+ encoder.encodeArrayPointer(new codec.PointerTo(uuid$.UUID), val.knownServiceUuids);
+ };
+ function FakeCentral_SimulatePreconnectedPeripheral_ResponseParams(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_SimulatePreconnectedPeripheral_ResponseParams.prototype.initDefaults_ = function() {
+ };
+ FakeCentral_SimulatePreconnectedPeripheral_ResponseParams.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_SimulatePreconnectedPeripheral_ResponseParams.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 8}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_SimulatePreconnectedPeripheral_ResponseParams.encodedSize = codec.kStructHeaderSize + 0;
+
+ FakeCentral_SimulatePreconnectedPeripheral_ResponseParams.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_SimulatePreconnectedPeripheral_ResponseParams();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ return val;
+ };
+
+ FakeCentral_SimulatePreconnectedPeripheral_ResponseParams.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_SimulatePreconnectedPeripheral_ResponseParams.encodedSize);
+ encoder.writeUint32(0);
+ };
+ function FakeCentral_SetNextGATTConnectionResponse_Params(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_SetNextGATTConnectionResponse_Params.prototype.initDefaults_ = function() {
+ this.address = null;
+ this.code = 0;
+ };
+ FakeCentral_SetNextGATTConnectionResponse_Params.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_SetNextGATTConnectionResponse_Params.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 24}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_SetNextGATTConnectionResponse_Params.address
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_SetNextGATTConnectionResponse_Params.encodedSize = codec.kStructHeaderSize + 16;
+
+ FakeCentral_SetNextGATTConnectionResponse_Params.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_SetNextGATTConnectionResponse_Params();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ val.address = decoder.decodeStruct(codec.String);
+ val.code = decoder.decodeStruct(codec.Uint16);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ return val;
+ };
+
+ FakeCentral_SetNextGATTConnectionResponse_Params.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_SetNextGATTConnectionResponse_Params.encodedSize);
+ encoder.writeUint32(0);
+ encoder.encodeStruct(codec.String, val.address);
+ encoder.encodeStruct(codec.Uint16, val.code);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ };
+ function FakeCentral_SetNextGATTConnectionResponse_ResponseParams(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_SetNextGATTConnectionResponse_ResponseParams.prototype.initDefaults_ = function() {
+ this.success = false;
+ };
+ FakeCentral_SetNextGATTConnectionResponse_ResponseParams.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_SetNextGATTConnectionResponse_ResponseParams.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 16}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_SetNextGATTConnectionResponse_ResponseParams.encodedSize = codec.kStructHeaderSize + 8;
+
+ FakeCentral_SetNextGATTConnectionResponse_ResponseParams.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_SetNextGATTConnectionResponse_ResponseParams();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ packed = decoder.readUint8();
+ val.success = (packed >> 0) & 1 ? true : false;
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ return val;
+ };
+
+ FakeCentral_SetNextGATTConnectionResponse_ResponseParams.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_SetNextGATTConnectionResponse_ResponseParams.encodedSize);
+ encoder.writeUint32(0);
+ packed = 0;
+ packed |= (val.success & 1) << 0
+ encoder.writeUint8(packed);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ };
+ function FakeCentral_SetNextGATTDiscoveryResponse_Params(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_SetNextGATTDiscoveryResponse_Params.prototype.initDefaults_ = function() {
+ this.address = null;
+ this.code = 0;
+ };
+ FakeCentral_SetNextGATTDiscoveryResponse_Params.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_SetNextGATTDiscoveryResponse_Params.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 24}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_SetNextGATTDiscoveryResponse_Params.address
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_SetNextGATTDiscoveryResponse_Params.encodedSize = codec.kStructHeaderSize + 16;
+
+ FakeCentral_SetNextGATTDiscoveryResponse_Params.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_SetNextGATTDiscoveryResponse_Params();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ val.address = decoder.decodeStruct(codec.String);
+ val.code = decoder.decodeStruct(codec.Uint16);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ return val;
+ };
+
+ FakeCentral_SetNextGATTDiscoveryResponse_Params.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_SetNextGATTDiscoveryResponse_Params.encodedSize);
+ encoder.writeUint32(0);
+ encoder.encodeStruct(codec.String, val.address);
+ encoder.encodeStruct(codec.Uint16, val.code);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ };
+ function FakeCentral_SetNextGATTDiscoveryResponse_ResponseParams(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_SetNextGATTDiscoveryResponse_ResponseParams.prototype.initDefaults_ = function() {
+ this.success = false;
+ };
+ FakeCentral_SetNextGATTDiscoveryResponse_ResponseParams.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_SetNextGATTDiscoveryResponse_ResponseParams.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 16}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_SetNextGATTDiscoveryResponse_ResponseParams.encodedSize = codec.kStructHeaderSize + 8;
+
+ FakeCentral_SetNextGATTDiscoveryResponse_ResponseParams.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_SetNextGATTDiscoveryResponse_ResponseParams();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ packed = decoder.readUint8();
+ val.success = (packed >> 0) & 1 ? true : false;
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ return val;
+ };
+
+ FakeCentral_SetNextGATTDiscoveryResponse_ResponseParams.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_SetNextGATTDiscoveryResponse_ResponseParams.encodedSize);
+ encoder.writeUint32(0);
+ packed = 0;
+ packed |= (val.success & 1) << 0
+ encoder.writeUint8(packed);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ };
+ function FakeCentral_SimulateGATTDisconnection_Params(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_SimulateGATTDisconnection_Params.prototype.initDefaults_ = function() {
+ this.address = null;
+ };
+ FakeCentral_SimulateGATTDisconnection_Params.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_SimulateGATTDisconnection_Params.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 16}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_SimulateGATTDisconnection_Params.address
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_SimulateGATTDisconnection_Params.encodedSize = codec.kStructHeaderSize + 8;
+
+ FakeCentral_SimulateGATTDisconnection_Params.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_SimulateGATTDisconnection_Params();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ val.address = decoder.decodeStruct(codec.String);
+ return val;
+ };
+
+ FakeCentral_SimulateGATTDisconnection_Params.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_SimulateGATTDisconnection_Params.encodedSize);
+ encoder.writeUint32(0);
+ encoder.encodeStruct(codec.String, val.address);
+ };
+ function FakeCentral_SimulateGATTDisconnection_ResponseParams(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_SimulateGATTDisconnection_ResponseParams.prototype.initDefaults_ = function() {
+ this.success = false;
+ };
+ FakeCentral_SimulateGATTDisconnection_ResponseParams.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_SimulateGATTDisconnection_ResponseParams.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 16}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_SimulateGATTDisconnection_ResponseParams.encodedSize = codec.kStructHeaderSize + 8;
+
+ FakeCentral_SimulateGATTDisconnection_ResponseParams.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_SimulateGATTDisconnection_ResponseParams();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ packed = decoder.readUint8();
+ val.success = (packed >> 0) & 1 ? true : false;
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ return val;
+ };
+
+ FakeCentral_SimulateGATTDisconnection_ResponseParams.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_SimulateGATTDisconnection_ResponseParams.encodedSize);
+ encoder.writeUint32(0);
+ packed = 0;
+ packed |= (val.success & 1) << 0
+ encoder.writeUint8(packed);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ };
+ function FakeCentral_SimulateGATTServicesChanged_Params(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_SimulateGATTServicesChanged_Params.prototype.initDefaults_ = function() {
+ this.address = null;
+ };
+ FakeCentral_SimulateGATTServicesChanged_Params.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_SimulateGATTServicesChanged_Params.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 16}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_SimulateGATTServicesChanged_Params.address
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_SimulateGATTServicesChanged_Params.encodedSize = codec.kStructHeaderSize + 8;
+
+ FakeCentral_SimulateGATTServicesChanged_Params.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_SimulateGATTServicesChanged_Params();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ val.address = decoder.decodeStruct(codec.String);
+ return val;
+ };
+
+ FakeCentral_SimulateGATTServicesChanged_Params.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_SimulateGATTServicesChanged_Params.encodedSize);
+ encoder.writeUint32(0);
+ encoder.encodeStruct(codec.String, val.address);
+ };
+ function FakeCentral_SimulateGATTServicesChanged_ResponseParams(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_SimulateGATTServicesChanged_ResponseParams.prototype.initDefaults_ = function() {
+ this.success = false;
+ };
+ FakeCentral_SimulateGATTServicesChanged_ResponseParams.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_SimulateGATTServicesChanged_ResponseParams.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 16}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_SimulateGATTServicesChanged_ResponseParams.encodedSize = codec.kStructHeaderSize + 8;
+
+ FakeCentral_SimulateGATTServicesChanged_ResponseParams.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_SimulateGATTServicesChanged_ResponseParams();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ packed = decoder.readUint8();
+ val.success = (packed >> 0) & 1 ? true : false;
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ return val;
+ };
+
+ FakeCentral_SimulateGATTServicesChanged_ResponseParams.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_SimulateGATTServicesChanged_ResponseParams.encodedSize);
+ encoder.writeUint32(0);
+ packed = 0;
+ packed |= (val.success & 1) << 0
+ encoder.writeUint8(packed);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ };
+ function FakeCentral_AddFakeService_Params(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_AddFakeService_Params.prototype.initDefaults_ = function() {
+ this.peripheralAddress = null;
+ this.serviceUuid = null;
+ };
+ FakeCentral_AddFakeService_Params.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_AddFakeService_Params.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 24}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_AddFakeService_Params.peripheralAddress
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_AddFakeService_Params.serviceUuid
+ err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 8, uuid$.UUID, false);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_AddFakeService_Params.encodedSize = codec.kStructHeaderSize + 16;
+
+ FakeCentral_AddFakeService_Params.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_AddFakeService_Params();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ val.peripheralAddress = decoder.decodeStruct(codec.String);
+ val.serviceUuid = decoder.decodeStructPointer(uuid$.UUID);
+ return val;
+ };
+
+ FakeCentral_AddFakeService_Params.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_AddFakeService_Params.encodedSize);
+ encoder.writeUint32(0);
+ encoder.encodeStruct(codec.String, val.peripheralAddress);
+ encoder.encodeStructPointer(uuid$.UUID, val.serviceUuid);
+ };
+ function FakeCentral_AddFakeService_ResponseParams(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_AddFakeService_ResponseParams.prototype.initDefaults_ = function() {
+ this.serviceId = null;
+ };
+ FakeCentral_AddFakeService_ResponseParams.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_AddFakeService_ResponseParams.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 16}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_AddFakeService_ResponseParams.serviceId
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, true)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_AddFakeService_ResponseParams.encodedSize = codec.kStructHeaderSize + 8;
+
+ FakeCentral_AddFakeService_ResponseParams.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_AddFakeService_ResponseParams();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ val.serviceId = decoder.decodeStruct(codec.NullableString);
+ return val;
+ };
+
+ FakeCentral_AddFakeService_ResponseParams.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_AddFakeService_ResponseParams.encodedSize);
+ encoder.writeUint32(0);
+ encoder.encodeStruct(codec.NullableString, val.serviceId);
+ };
+ function FakeCentral_AddFakeCharacteristic_Params(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_AddFakeCharacteristic_Params.prototype.initDefaults_ = function() {
+ this.characteristicUuid = null;
+ this.properties = null;
+ this.serviceId = null;
+ this.peripheralAddress = null;
+ };
+ FakeCentral_AddFakeCharacteristic_Params.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_AddFakeCharacteristic_Params.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 40}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_AddFakeCharacteristic_Params.characteristicUuid
+ err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, uuid$.UUID, false);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_AddFakeCharacteristic_Params.properties
+ err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 8, CharacteristicProperties, false);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_AddFakeCharacteristic_Params.serviceId
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 16, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_AddFakeCharacteristic_Params.peripheralAddress
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 24, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_AddFakeCharacteristic_Params.encodedSize = codec.kStructHeaderSize + 32;
+
+ FakeCentral_AddFakeCharacteristic_Params.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_AddFakeCharacteristic_Params();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ val.characteristicUuid = decoder.decodeStructPointer(uuid$.UUID);
+ val.properties = decoder.decodeStructPointer(CharacteristicProperties);
+ val.serviceId = decoder.decodeStruct(codec.String);
+ val.peripheralAddress = decoder.decodeStruct(codec.String);
+ return val;
+ };
+
+ FakeCentral_AddFakeCharacteristic_Params.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_AddFakeCharacteristic_Params.encodedSize);
+ encoder.writeUint32(0);
+ encoder.encodeStructPointer(uuid$.UUID, val.characteristicUuid);
+ encoder.encodeStructPointer(CharacteristicProperties, val.properties);
+ encoder.encodeStruct(codec.String, val.serviceId);
+ encoder.encodeStruct(codec.String, val.peripheralAddress);
+ };
+ function FakeCentral_AddFakeCharacteristic_ResponseParams(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_AddFakeCharacteristic_ResponseParams.prototype.initDefaults_ = function() {
+ this.characteristicId = null;
+ };
+ FakeCentral_AddFakeCharacteristic_ResponseParams.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_AddFakeCharacteristic_ResponseParams.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 16}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_AddFakeCharacteristic_ResponseParams.characteristicId
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, true)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_AddFakeCharacteristic_ResponseParams.encodedSize = codec.kStructHeaderSize + 8;
+
+ FakeCentral_AddFakeCharacteristic_ResponseParams.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_AddFakeCharacteristic_ResponseParams();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ val.characteristicId = decoder.decodeStruct(codec.NullableString);
+ return val;
+ };
+
+ FakeCentral_AddFakeCharacteristic_ResponseParams.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_AddFakeCharacteristic_ResponseParams.encodedSize);
+ encoder.writeUint32(0);
+ encoder.encodeStruct(codec.NullableString, val.characteristicId);
+ };
+ function FakeCentral_RemoveFakeCharacteristic_Params(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_RemoveFakeCharacteristic_Params.prototype.initDefaults_ = function() {
+ this.identifier = null;
+ this.serviceId = null;
+ this.peripheralAddress = null;
+ };
+ FakeCentral_RemoveFakeCharacteristic_Params.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_RemoveFakeCharacteristic_Params.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 32}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_RemoveFakeCharacteristic_Params.identifier
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_RemoveFakeCharacteristic_Params.serviceId
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_RemoveFakeCharacteristic_Params.peripheralAddress
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 16, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_RemoveFakeCharacteristic_Params.encodedSize = codec.kStructHeaderSize + 24;
+
+ FakeCentral_RemoveFakeCharacteristic_Params.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_RemoveFakeCharacteristic_Params();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ val.identifier = decoder.decodeStruct(codec.String);
+ val.serviceId = decoder.decodeStruct(codec.String);
+ val.peripheralAddress = decoder.decodeStruct(codec.String);
+ return val;
+ };
+
+ FakeCentral_RemoveFakeCharacteristic_Params.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_RemoveFakeCharacteristic_Params.encodedSize);
+ encoder.writeUint32(0);
+ encoder.encodeStruct(codec.String, val.identifier);
+ encoder.encodeStruct(codec.String, val.serviceId);
+ encoder.encodeStruct(codec.String, val.peripheralAddress);
+ };
+ function FakeCentral_RemoveFakeCharacteristic_ResponseParams(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_RemoveFakeCharacteristic_ResponseParams.prototype.initDefaults_ = function() {
+ this.success = false;
+ };
+ FakeCentral_RemoveFakeCharacteristic_ResponseParams.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_RemoveFakeCharacteristic_ResponseParams.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 16}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_RemoveFakeCharacteristic_ResponseParams.encodedSize = codec.kStructHeaderSize + 8;
+
+ FakeCentral_RemoveFakeCharacteristic_ResponseParams.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_RemoveFakeCharacteristic_ResponseParams();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ packed = decoder.readUint8();
+ val.success = (packed >> 0) & 1 ? true : false;
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ return val;
+ };
+
+ FakeCentral_RemoveFakeCharacteristic_ResponseParams.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_RemoveFakeCharacteristic_ResponseParams.encodedSize);
+ encoder.writeUint32(0);
+ packed = 0;
+ packed |= (val.success & 1) << 0
+ encoder.writeUint8(packed);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ };
+ function FakeCentral_AddFakeDescriptor_Params(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_AddFakeDescriptor_Params.prototype.initDefaults_ = function() {
+ this.descriptorUuid = null;
+ this.characteristicId = null;
+ this.serviceId = null;
+ this.peripheralAddress = null;
+ };
+ FakeCentral_AddFakeDescriptor_Params.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_AddFakeDescriptor_Params.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 40}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_AddFakeDescriptor_Params.descriptorUuid
+ err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, uuid$.UUID, false);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_AddFakeDescriptor_Params.characteristicId
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_AddFakeDescriptor_Params.serviceId
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 16, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_AddFakeDescriptor_Params.peripheralAddress
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 24, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_AddFakeDescriptor_Params.encodedSize = codec.kStructHeaderSize + 32;
+
+ FakeCentral_AddFakeDescriptor_Params.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_AddFakeDescriptor_Params();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ val.descriptorUuid = decoder.decodeStructPointer(uuid$.UUID);
+ val.characteristicId = decoder.decodeStruct(codec.String);
+ val.serviceId = decoder.decodeStruct(codec.String);
+ val.peripheralAddress = decoder.decodeStruct(codec.String);
+ return val;
+ };
+
+ FakeCentral_AddFakeDescriptor_Params.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_AddFakeDescriptor_Params.encodedSize);
+ encoder.writeUint32(0);
+ encoder.encodeStructPointer(uuid$.UUID, val.descriptorUuid);
+ encoder.encodeStruct(codec.String, val.characteristicId);
+ encoder.encodeStruct(codec.String, val.serviceId);
+ encoder.encodeStruct(codec.String, val.peripheralAddress);
+ };
+ function FakeCentral_AddFakeDescriptor_ResponseParams(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_AddFakeDescriptor_ResponseParams.prototype.initDefaults_ = function() {
+ this.descriptorId = null;
+ };
+ FakeCentral_AddFakeDescriptor_ResponseParams.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_AddFakeDescriptor_ResponseParams.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 16}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_AddFakeDescriptor_ResponseParams.descriptorId
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, true)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_AddFakeDescriptor_ResponseParams.encodedSize = codec.kStructHeaderSize + 8;
+
+ FakeCentral_AddFakeDescriptor_ResponseParams.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_AddFakeDescriptor_ResponseParams();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ val.descriptorId = decoder.decodeStruct(codec.NullableString);
+ return val;
+ };
+
+ FakeCentral_AddFakeDescriptor_ResponseParams.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_AddFakeDescriptor_ResponseParams.encodedSize);
+ encoder.writeUint32(0);
+ encoder.encodeStruct(codec.NullableString, val.descriptorId);
+ };
+ function FakeCentral_SetNextReadCharacteristicResponse_Params(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_SetNextReadCharacteristicResponse_Params.prototype.initDefaults_ = function() {
+ this.gattCode = 0;
+ this.value = null;
+ this.characteristicId = null;
+ this.serviceId = null;
+ this.peripheralAddress = null;
+ };
+ FakeCentral_SetNextReadCharacteristicResponse_Params.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_SetNextReadCharacteristicResponse_Params.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 48}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+
+ // validate FakeCentral_SetNextReadCharacteristicResponse_Params.value
+ err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 8, 1, codec.Uint8, true, [0], 0);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_SetNextReadCharacteristicResponse_Params.characteristicId
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 16, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_SetNextReadCharacteristicResponse_Params.serviceId
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 24, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_SetNextReadCharacteristicResponse_Params.peripheralAddress
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 32, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_SetNextReadCharacteristicResponse_Params.encodedSize = codec.kStructHeaderSize + 40;
+
+ FakeCentral_SetNextReadCharacteristicResponse_Params.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_SetNextReadCharacteristicResponse_Params();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ val.gattCode = decoder.decodeStruct(codec.Uint16);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ val.value = decoder.decodeArrayPointer(codec.Uint8);
+ val.characteristicId = decoder.decodeStruct(codec.String);
+ val.serviceId = decoder.decodeStruct(codec.String);
+ val.peripheralAddress = decoder.decodeStruct(codec.String);
+ return val;
+ };
+
+ FakeCentral_SetNextReadCharacteristicResponse_Params.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_SetNextReadCharacteristicResponse_Params.encodedSize);
+ encoder.writeUint32(0);
+ encoder.encodeStruct(codec.Uint16, val.gattCode);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.encodeArrayPointer(codec.Uint8, val.value);
+ encoder.encodeStruct(codec.String, val.characteristicId);
+ encoder.encodeStruct(codec.String, val.serviceId);
+ encoder.encodeStruct(codec.String, val.peripheralAddress);
+ };
+ function FakeCentral_SetNextReadCharacteristicResponse_ResponseParams(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_SetNextReadCharacteristicResponse_ResponseParams.prototype.initDefaults_ = function() {
+ this.success = false;
+ };
+ FakeCentral_SetNextReadCharacteristicResponse_ResponseParams.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_SetNextReadCharacteristicResponse_ResponseParams.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 16}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_SetNextReadCharacteristicResponse_ResponseParams.encodedSize = codec.kStructHeaderSize + 8;
+
+ FakeCentral_SetNextReadCharacteristicResponse_ResponseParams.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_SetNextReadCharacteristicResponse_ResponseParams();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ packed = decoder.readUint8();
+ val.success = (packed >> 0) & 1 ? true : false;
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ return val;
+ };
+
+ FakeCentral_SetNextReadCharacteristicResponse_ResponseParams.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_SetNextReadCharacteristicResponse_ResponseParams.encodedSize);
+ encoder.writeUint32(0);
+ packed = 0;
+ packed |= (val.success & 1) << 0
+ encoder.writeUint8(packed);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ };
+ function FakeCentral_SetNextWriteCharacteristicResponse_Params(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_SetNextWriteCharacteristicResponse_Params.prototype.initDefaults_ = function() {
+ this.gattCode = 0;
+ this.characteristicId = null;
+ this.serviceId = null;
+ this.peripheralAddress = null;
+ };
+ FakeCentral_SetNextWriteCharacteristicResponse_Params.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_SetNextWriteCharacteristicResponse_Params.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 40}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+
+ // validate FakeCentral_SetNextWriteCharacteristicResponse_Params.characteristicId
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_SetNextWriteCharacteristicResponse_Params.serviceId
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 16, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_SetNextWriteCharacteristicResponse_Params.peripheralAddress
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 24, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_SetNextWriteCharacteristicResponse_Params.encodedSize = codec.kStructHeaderSize + 32;
+
+ FakeCentral_SetNextWriteCharacteristicResponse_Params.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_SetNextWriteCharacteristicResponse_Params();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ val.gattCode = decoder.decodeStruct(codec.Uint16);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ val.characteristicId = decoder.decodeStruct(codec.String);
+ val.serviceId = decoder.decodeStruct(codec.String);
+ val.peripheralAddress = decoder.decodeStruct(codec.String);
+ return val;
+ };
+
+ FakeCentral_SetNextWriteCharacteristicResponse_Params.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_SetNextWriteCharacteristicResponse_Params.encodedSize);
+ encoder.writeUint32(0);
+ encoder.encodeStruct(codec.Uint16, val.gattCode);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.encodeStruct(codec.String, val.characteristicId);
+ encoder.encodeStruct(codec.String, val.serviceId);
+ encoder.encodeStruct(codec.String, val.peripheralAddress);
+ };
+ function FakeCentral_SetNextWriteCharacteristicResponse_ResponseParams(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_SetNextWriteCharacteristicResponse_ResponseParams.prototype.initDefaults_ = function() {
+ this.success = false;
+ };
+ FakeCentral_SetNextWriteCharacteristicResponse_ResponseParams.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_SetNextWriteCharacteristicResponse_ResponseParams.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 16}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_SetNextWriteCharacteristicResponse_ResponseParams.encodedSize = codec.kStructHeaderSize + 8;
+
+ FakeCentral_SetNextWriteCharacteristicResponse_ResponseParams.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_SetNextWriteCharacteristicResponse_ResponseParams();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ packed = decoder.readUint8();
+ val.success = (packed >> 0) & 1 ? true : false;
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ return val;
+ };
+
+ FakeCentral_SetNextWriteCharacteristicResponse_ResponseParams.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_SetNextWriteCharacteristicResponse_ResponseParams.encodedSize);
+ encoder.writeUint32(0);
+ packed = 0;
+ packed |= (val.success & 1) << 0
+ encoder.writeUint8(packed);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ };
+ function FakeCentral_SetNextSubscribeToNotificationsResponse_Params(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_SetNextSubscribeToNotificationsResponse_Params.prototype.initDefaults_ = function() {
+ this.gattCode = 0;
+ this.characteristicId = null;
+ this.serviceId = null;
+ this.peripheralAddress = null;
+ };
+ FakeCentral_SetNextSubscribeToNotificationsResponse_Params.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_SetNextSubscribeToNotificationsResponse_Params.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 40}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+
+ // validate FakeCentral_SetNextSubscribeToNotificationsResponse_Params.characteristicId
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_SetNextSubscribeToNotificationsResponse_Params.serviceId
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 16, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_SetNextSubscribeToNotificationsResponse_Params.peripheralAddress
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 24, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_SetNextSubscribeToNotificationsResponse_Params.encodedSize = codec.kStructHeaderSize + 32;
+
+ FakeCentral_SetNextSubscribeToNotificationsResponse_Params.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_SetNextSubscribeToNotificationsResponse_Params();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ val.gattCode = decoder.decodeStruct(codec.Uint16);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ val.characteristicId = decoder.decodeStruct(codec.String);
+ val.serviceId = decoder.decodeStruct(codec.String);
+ val.peripheralAddress = decoder.decodeStruct(codec.String);
+ return val;
+ };
+
+ FakeCentral_SetNextSubscribeToNotificationsResponse_Params.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_SetNextSubscribeToNotificationsResponse_Params.encodedSize);
+ encoder.writeUint32(0);
+ encoder.encodeStruct(codec.Uint16, val.gattCode);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.encodeStruct(codec.String, val.characteristicId);
+ encoder.encodeStruct(codec.String, val.serviceId);
+ encoder.encodeStruct(codec.String, val.peripheralAddress);
+ };
+ function FakeCentral_SetNextSubscribeToNotificationsResponse_ResponseParams(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_SetNextSubscribeToNotificationsResponse_ResponseParams.prototype.initDefaults_ = function() {
+ this.success = false;
+ };
+ FakeCentral_SetNextSubscribeToNotificationsResponse_ResponseParams.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_SetNextSubscribeToNotificationsResponse_ResponseParams.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 16}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_SetNextSubscribeToNotificationsResponse_ResponseParams.encodedSize = codec.kStructHeaderSize + 8;
+
+ FakeCentral_SetNextSubscribeToNotificationsResponse_ResponseParams.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_SetNextSubscribeToNotificationsResponse_ResponseParams();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ packed = decoder.readUint8();
+ val.success = (packed >> 0) & 1 ? true : false;
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ return val;
+ };
+
+ FakeCentral_SetNextSubscribeToNotificationsResponse_ResponseParams.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_SetNextSubscribeToNotificationsResponse_ResponseParams.encodedSize);
+ encoder.writeUint32(0);
+ packed = 0;
+ packed |= (val.success & 1) << 0
+ encoder.writeUint8(packed);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ };
+ function FakeCentral_GetLastWrittenValue_Params(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_GetLastWrittenValue_Params.prototype.initDefaults_ = function() {
+ this.characteristicId = null;
+ this.serviceId = null;
+ this.peripheralAddress = null;
+ };
+ FakeCentral_GetLastWrittenValue_Params.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_GetLastWrittenValue_Params.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 32}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_GetLastWrittenValue_Params.characteristicId
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_GetLastWrittenValue_Params.serviceId
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_GetLastWrittenValue_Params.peripheralAddress
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 16, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_GetLastWrittenValue_Params.encodedSize = codec.kStructHeaderSize + 24;
+
+ FakeCentral_GetLastWrittenValue_Params.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_GetLastWrittenValue_Params();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ val.characteristicId = decoder.decodeStruct(codec.String);
+ val.serviceId = decoder.decodeStruct(codec.String);
+ val.peripheralAddress = decoder.decodeStruct(codec.String);
+ return val;
+ };
+
+ FakeCentral_GetLastWrittenValue_Params.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_GetLastWrittenValue_Params.encodedSize);
+ encoder.writeUint32(0);
+ encoder.encodeStruct(codec.String, val.characteristicId);
+ encoder.encodeStruct(codec.String, val.serviceId);
+ encoder.encodeStruct(codec.String, val.peripheralAddress);
+ };
+ function FakeCentral_GetLastWrittenValue_ResponseParams(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_GetLastWrittenValue_ResponseParams.prototype.initDefaults_ = function() {
+ this.success = false;
+ this.value = null;
+ };
+ FakeCentral_GetLastWrittenValue_ResponseParams.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_GetLastWrittenValue_ResponseParams.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 24}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+
+ // validate FakeCentral_GetLastWrittenValue_ResponseParams.value
+ err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 8, 1, codec.Uint8, true, [0], 0);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_GetLastWrittenValue_ResponseParams.encodedSize = codec.kStructHeaderSize + 16;
+
+ FakeCentral_GetLastWrittenValue_ResponseParams.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_GetLastWrittenValue_ResponseParams();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ packed = decoder.readUint8();
+ val.success = (packed >> 0) & 1 ? true : false;
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ val.value = decoder.decodeArrayPointer(codec.Uint8);
+ return val;
+ };
+
+ FakeCentral_GetLastWrittenValue_ResponseParams.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_GetLastWrittenValue_ResponseParams.encodedSize);
+ encoder.writeUint32(0);
+ packed = 0;
+ packed |= (val.success & 1) << 0
+ encoder.writeUint8(packed);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.encodeArrayPointer(codec.Uint8, val.value);
+ };
+ function FakeCentral_SetNextReadDescriptorResponse_Params(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_SetNextReadDescriptorResponse_Params.prototype.initDefaults_ = function() {
+ this.gattCode = 0;
+ this.value = null;
+ this.descriptorId = null;
+ this.characteristicId = null;
+ this.serviceId = null;
+ this.peripheralAddress = null;
+ };
+ FakeCentral_SetNextReadDescriptorResponse_Params.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_SetNextReadDescriptorResponse_Params.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 56}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+
+ // validate FakeCentral_SetNextReadDescriptorResponse_Params.value
+ err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 8, 1, codec.Uint8, true, [0], 0);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_SetNextReadDescriptorResponse_Params.descriptorId
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 16, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_SetNextReadDescriptorResponse_Params.characteristicId
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 24, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_SetNextReadDescriptorResponse_Params.serviceId
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 32, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate FakeCentral_SetNextReadDescriptorResponse_Params.peripheralAddress
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 40, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_SetNextReadDescriptorResponse_Params.encodedSize = codec.kStructHeaderSize + 48;
+
+ FakeCentral_SetNextReadDescriptorResponse_Params.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_SetNextReadDescriptorResponse_Params();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ val.gattCode = decoder.decodeStruct(codec.Uint16);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ val.value = decoder.decodeArrayPointer(codec.Uint8);
+ val.descriptorId = decoder.decodeStruct(codec.String);
+ val.characteristicId = decoder.decodeStruct(codec.String);
+ val.serviceId = decoder.decodeStruct(codec.String);
+ val.peripheralAddress = decoder.decodeStruct(codec.String);
+ return val;
+ };
+
+ FakeCentral_SetNextReadDescriptorResponse_Params.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_SetNextReadDescriptorResponse_Params.encodedSize);
+ encoder.writeUint32(0);
+ encoder.encodeStruct(codec.Uint16, val.gattCode);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.encodeArrayPointer(codec.Uint8, val.value);
+ encoder.encodeStruct(codec.String, val.descriptorId);
+ encoder.encodeStruct(codec.String, val.characteristicId);
+ encoder.encodeStruct(codec.String, val.serviceId);
+ encoder.encodeStruct(codec.String, val.peripheralAddress);
+ };
+ function FakeCentral_SetNextReadDescriptorResponse_ResponseParams(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ FakeCentral_SetNextReadDescriptorResponse_ResponseParams.prototype.initDefaults_ = function() {
+ this.success = false;
+ };
+ FakeCentral_SetNextReadDescriptorResponse_ResponseParams.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ FakeCentral_SetNextReadDescriptorResponse_ResponseParams.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 16}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ return validator.validationError.NONE;
+ };
+
+ FakeCentral_SetNextReadDescriptorResponse_ResponseParams.encodedSize = codec.kStructHeaderSize + 8;
+
+ FakeCentral_SetNextReadDescriptorResponse_ResponseParams.decode = function(decoder) {
+ var packed;
+ var val = new FakeCentral_SetNextReadDescriptorResponse_ResponseParams();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ packed = decoder.readUint8();
+ val.success = (packed >> 0) & 1 ? true : false;
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ decoder.skip(1);
+ return val;
+ };
+
+ FakeCentral_SetNextReadDescriptorResponse_ResponseParams.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(FakeCentral_SetNextReadDescriptorResponse_ResponseParams.encodedSize);
+ encoder.writeUint32(0);
+ packed = 0;
+ packed |= (val.success & 1) << 0
+ encoder.writeUint8(packed);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ encoder.skip(1);
+ };
+ var kFakeBluetooth_SetLESupported_Name = 0;
+ var kFakeBluetooth_SimulateCentral_Name = 1;
+ var kFakeBluetooth_AllResponsesConsumed_Name = 2;
+
+ function FakeBluetoothPtr(handleOrPtrInfo) {
+ this.ptr = new bindings.InterfacePtrController(FakeBluetooth,
+ handleOrPtrInfo);
+ }
+
+ function FakeBluetoothAssociatedPtr(associatedInterfacePtrInfo) {
+ this.ptr = new associatedBindings.AssociatedInterfacePtrController(
+ FakeBluetooth, associatedInterfacePtrInfo);
+ }
+
+ FakeBluetoothAssociatedPtr.prototype =
+ Object.create(FakeBluetoothPtr.prototype);
+ FakeBluetoothAssociatedPtr.prototype.constructor =
+ FakeBluetoothAssociatedPtr;
+
+ function FakeBluetoothProxy(receiver) {
+ this.receiver_ = receiver;
+ }
+ FakeBluetoothPtr.prototype.setLESupported = function() {
+ return FakeBluetoothProxy.prototype.setLESupported
+ .apply(this.ptr.getProxy(), arguments);
+ };
+
+ FakeBluetoothProxy.prototype.setLESupported = function(available) {
+ var params = new FakeBluetooth_SetLESupported_Params();
+ params.available = available;
+ return new Promise(function(resolve, reject) {
+ var builder = new codec.MessageV1Builder(
+ kFakeBluetooth_SetLESupported_Name,
+ codec.align(FakeBluetooth_SetLESupported_Params.encodedSize),
+ codec.kMessageExpectsResponse, 0);
+ builder.encodeStruct(FakeBluetooth_SetLESupported_Params, params);
+ var message = builder.finish();
+ this.receiver_.acceptAndExpectResponse(message).then(function(message) {
+ var reader = new codec.MessageReader(message);
+ var responseParams =
+ reader.decodeStruct(FakeBluetooth_SetLESupported_ResponseParams);
+ resolve(responseParams);
+ }).catch(function(result) {
+ reject(Error("Connection error: " + result));
+ });
+ }.bind(this));
+ };
+ FakeBluetoothPtr.prototype.simulateCentral = function() {
+ return FakeBluetoothProxy.prototype.simulateCentral
+ .apply(this.ptr.getProxy(), arguments);
+ };
+
+ FakeBluetoothProxy.prototype.simulateCentral = function(state) {
+ var params = new FakeBluetooth_SimulateCentral_Params();
+ params.state = state;
+ return new Promise(function(resolve, reject) {
+ var builder = new codec.MessageV1Builder(
+ kFakeBluetooth_SimulateCentral_Name,
+ codec.align(FakeBluetooth_SimulateCentral_Params.encodedSize),
+ codec.kMessageExpectsResponse, 0);
+ builder.encodeStruct(FakeBluetooth_SimulateCentral_Params, params);
+ var message = builder.finish();
+ this.receiver_.acceptAndExpectResponse(message).then(function(message) {
+ var reader = new codec.MessageReader(message);
+ var responseParams =
+ reader.decodeStruct(FakeBluetooth_SimulateCentral_ResponseParams);
+ resolve(responseParams);
+ }).catch(function(result) {
+ reject(Error("Connection error: " + result));
+ });
+ }.bind(this));
+ };
+ FakeBluetoothPtr.prototype.allResponsesConsumed = function() {
+ return FakeBluetoothProxy.prototype.allResponsesConsumed
+ .apply(this.ptr.getProxy(), arguments);
+ };
+
+ FakeBluetoothProxy.prototype.allResponsesConsumed = function() {
+ var params = new FakeBluetooth_AllResponsesConsumed_Params();
+ return new Promise(function(resolve, reject) {
+ var builder = new codec.MessageV1Builder(
+ kFakeBluetooth_AllResponsesConsumed_Name,
+ codec.align(FakeBluetooth_AllResponsesConsumed_Params.encodedSize),
+ codec.kMessageExpectsResponse, 0);
+ builder.encodeStruct(FakeBluetooth_AllResponsesConsumed_Params, params);
+ var message = builder.finish();
+ this.receiver_.acceptAndExpectResponse(message).then(function(message) {
+ var reader = new codec.MessageReader(message);
+ var responseParams =
+ reader.decodeStruct(FakeBluetooth_AllResponsesConsumed_ResponseParams);
+ resolve(responseParams);
+ }).catch(function(result) {
+ reject(Error("Connection error: " + result));
+ });
+ }.bind(this));
+ };
+
+ function FakeBluetoothStub(delegate) {
+ this.delegate_ = delegate;
+ }
+ FakeBluetoothStub.prototype.setLESupported = function(available) {
+ return this.delegate_ && this.delegate_.setLESupported && this.delegate_.setLESupported(available);
+ }
+ FakeBluetoothStub.prototype.simulateCentral = function(state) {
+ return this.delegate_ && this.delegate_.simulateCentral && this.delegate_.simulateCentral(state);
+ }
+ FakeBluetoothStub.prototype.allResponsesConsumed = function() {
+ return this.delegate_ && this.delegate_.allResponsesConsumed && this.delegate_.allResponsesConsumed();
+ }
+
+ FakeBluetoothStub.prototype.accept = function(message) {
+ var reader = new codec.MessageReader(message);
+ switch (reader.messageName) {
+ default:
+ return false;
+ }
+ };
+
+ FakeBluetoothStub.prototype.acceptWithResponder =
+ function(message, responder) {
+ var reader = new codec.MessageReader(message);
+ switch (reader.messageName) {
+ case kFakeBluetooth_SetLESupported_Name:
+ var params = reader.decodeStruct(FakeBluetooth_SetLESupported_Params);
+ this.setLESupported(params.available).then(function(response) {
+ var responseParams =
+ new FakeBluetooth_SetLESupported_ResponseParams();
+ var builder = new codec.MessageV1Builder(
+ kFakeBluetooth_SetLESupported_Name,
+ codec.align(FakeBluetooth_SetLESupported_ResponseParams.encodedSize),
+ codec.kMessageIsResponse, reader.requestID);
+ builder.encodeStruct(FakeBluetooth_SetLESupported_ResponseParams,
+ responseParams);
+ var message = builder.finish();
+ responder.accept(message);
+ });
+ return true;
+ case kFakeBluetooth_SimulateCentral_Name:
+ var params = reader.decodeStruct(FakeBluetooth_SimulateCentral_Params);
+ this.simulateCentral(params.state).then(function(response) {
+ var responseParams =
+ new FakeBluetooth_SimulateCentral_ResponseParams();
+ responseParams.fakeCentral = response.fakeCentral;
+ var builder = new codec.MessageV1Builder(
+ kFakeBluetooth_SimulateCentral_Name,
+ codec.align(FakeBluetooth_SimulateCentral_ResponseParams.encodedSize),
+ codec.kMessageIsResponse, reader.requestID);
+ builder.encodeStruct(FakeBluetooth_SimulateCentral_ResponseParams,
+ responseParams);
+ var message = builder.finish();
+ responder.accept(message);
+ });
+ return true;
+ case kFakeBluetooth_AllResponsesConsumed_Name:
+ var params = reader.decodeStruct(FakeBluetooth_AllResponsesConsumed_Params);
+ this.allResponsesConsumed().then(function(response) {
+ var responseParams =
+ new FakeBluetooth_AllResponsesConsumed_ResponseParams();
+ responseParams.consumed = response.consumed;
+ var builder = new codec.MessageV1Builder(
+ kFakeBluetooth_AllResponsesConsumed_Name,
+ codec.align(FakeBluetooth_AllResponsesConsumed_ResponseParams.encodedSize),
+ codec.kMessageIsResponse, reader.requestID);
+ builder.encodeStruct(FakeBluetooth_AllResponsesConsumed_ResponseParams,
+ responseParams);
+ var message = builder.finish();
+ responder.accept(message);
+ });
+ return true;
+ default:
+ return false;
+ }
+ };
+
+ function validateFakeBluetoothRequest(messageValidator) {
+ var message = messageValidator.message;
+ var paramsClass = null;
+ switch (message.getName()) {
+ case kFakeBluetooth_SetLESupported_Name:
+ if (message.expectsResponse())
+ paramsClass = FakeBluetooth_SetLESupported_Params;
+ break;
+ case kFakeBluetooth_SimulateCentral_Name:
+ if (message.expectsResponse())
+ paramsClass = FakeBluetooth_SimulateCentral_Params;
+ break;
+ case kFakeBluetooth_AllResponsesConsumed_Name:
+ if (message.expectsResponse())
+ paramsClass = FakeBluetooth_AllResponsesConsumed_Params;
+ break;
+ }
+ if (paramsClass === null)
+ return validator.validationError.NONE;
+ return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes());
+ }
+
+ function validateFakeBluetoothResponse(messageValidator) {
+ var message = messageValidator.message;
+ var paramsClass = null;
+ switch (message.getName()) {
+ case kFakeBluetooth_SetLESupported_Name:
+ if (message.isResponse())
+ paramsClass = FakeBluetooth_SetLESupported_ResponseParams;
+ break;
+ case kFakeBluetooth_SimulateCentral_Name:
+ if (message.isResponse())
+ paramsClass = FakeBluetooth_SimulateCentral_ResponseParams;
+ break;
+ case kFakeBluetooth_AllResponsesConsumed_Name:
+ if (message.isResponse())
+ paramsClass = FakeBluetooth_AllResponsesConsumed_ResponseParams;
+ break;
+ }
+ if (paramsClass === null)
+ return validator.validationError.NONE;
+ return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes());
+ }
+
+ var FakeBluetooth = {
+ name: 'bluetooth::mojom::FakeBluetooth',
+ kVersion: 0,
+ ptrClass: FakeBluetoothPtr,
+ proxyClass: FakeBluetoothProxy,
+ stubClass: FakeBluetoothStub,
+ validateRequest: validateFakeBluetoothRequest,
+ validateResponse: validateFakeBluetoothResponse,
+ };
+ FakeBluetoothStub.prototype.validator = validateFakeBluetoothRequest;
+ FakeBluetoothProxy.prototype.validator = validateFakeBluetoothResponse;
+ var kFakeCentral_SimulatePreconnectedPeripheral_Name = 0;
+ var kFakeCentral_SetNextGATTConnectionResponse_Name = 1;
+ var kFakeCentral_SetNextGATTDiscoveryResponse_Name = 2;
+ var kFakeCentral_SimulateGATTDisconnection_Name = 3;
+ var kFakeCentral_SimulateGATTServicesChanged_Name = 4;
+ var kFakeCentral_AddFakeService_Name = 5;
+ var kFakeCentral_AddFakeCharacteristic_Name = 6;
+ var kFakeCentral_RemoveFakeCharacteristic_Name = 7;
+ var kFakeCentral_AddFakeDescriptor_Name = 8;
+ var kFakeCentral_SetNextReadCharacteristicResponse_Name = 9;
+ var kFakeCentral_SetNextWriteCharacteristicResponse_Name = 10;
+ var kFakeCentral_SetNextSubscribeToNotificationsResponse_Name = 11;
+ var kFakeCentral_GetLastWrittenValue_Name = 12;
+ var kFakeCentral_SetNextReadDescriptorResponse_Name = 13;
+
+ function FakeCentralPtr(handleOrPtrInfo) {
+ this.ptr = new bindings.InterfacePtrController(FakeCentral,
+ handleOrPtrInfo);
+ }
+
+ function FakeCentralAssociatedPtr(associatedInterfacePtrInfo) {
+ this.ptr = new associatedBindings.AssociatedInterfacePtrController(
+ FakeCentral, associatedInterfacePtrInfo);
+ }
+
+ FakeCentralAssociatedPtr.prototype =
+ Object.create(FakeCentralPtr.prototype);
+ FakeCentralAssociatedPtr.prototype.constructor =
+ FakeCentralAssociatedPtr;
+
+ function FakeCentralProxy(receiver) {
+ this.receiver_ = receiver;
+ }
+ FakeCentralPtr.prototype.simulatePreconnectedPeripheral = function() {
+ return FakeCentralProxy.prototype.simulatePreconnectedPeripheral
+ .apply(this.ptr.getProxy(), arguments);
+ };
+
+ FakeCentralProxy.prototype.simulatePreconnectedPeripheral = function(address, name, knownServiceUuids) {
+ var params = new FakeCentral_SimulatePreconnectedPeripheral_Params();
+ params.address = address;
+ params.name = name;
+ params.knownServiceUuids = knownServiceUuids;
+ return new Promise(function(resolve, reject) {
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_SimulatePreconnectedPeripheral_Name,
+ codec.align(FakeCentral_SimulatePreconnectedPeripheral_Params.encodedSize),
+ codec.kMessageExpectsResponse, 0);
+ builder.encodeStruct(FakeCentral_SimulatePreconnectedPeripheral_Params, params);
+ var message = builder.finish();
+ this.receiver_.acceptAndExpectResponse(message).then(function(message) {
+ var reader = new codec.MessageReader(message);
+ var responseParams =
+ reader.decodeStruct(FakeCentral_SimulatePreconnectedPeripheral_ResponseParams);
+ resolve(responseParams);
+ }).catch(function(result) {
+ reject(Error("Connection error: " + result));
+ });
+ }.bind(this));
+ };
+ FakeCentralPtr.prototype.setNextGATTConnectionResponse = function() {
+ return FakeCentralProxy.prototype.setNextGATTConnectionResponse
+ .apply(this.ptr.getProxy(), arguments);
+ };
+
+ FakeCentralProxy.prototype.setNextGATTConnectionResponse = function(address, code) {
+ var params = new FakeCentral_SetNextGATTConnectionResponse_Params();
+ params.address = address;
+ params.code = code;
+ return new Promise(function(resolve, reject) {
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_SetNextGATTConnectionResponse_Name,
+ codec.align(FakeCentral_SetNextGATTConnectionResponse_Params.encodedSize),
+ codec.kMessageExpectsResponse, 0);
+ builder.encodeStruct(FakeCentral_SetNextGATTConnectionResponse_Params, params);
+ var message = builder.finish();
+ this.receiver_.acceptAndExpectResponse(message).then(function(message) {
+ var reader = new codec.MessageReader(message);
+ var responseParams =
+ reader.decodeStruct(FakeCentral_SetNextGATTConnectionResponse_ResponseParams);
+ resolve(responseParams);
+ }).catch(function(result) {
+ reject(Error("Connection error: " + result));
+ });
+ }.bind(this));
+ };
+ FakeCentralPtr.prototype.setNextGATTDiscoveryResponse = function() {
+ return FakeCentralProxy.prototype.setNextGATTDiscoveryResponse
+ .apply(this.ptr.getProxy(), arguments);
+ };
+
+ FakeCentralProxy.prototype.setNextGATTDiscoveryResponse = function(address, code) {
+ var params = new FakeCentral_SetNextGATTDiscoveryResponse_Params();
+ params.address = address;
+ params.code = code;
+ return new Promise(function(resolve, reject) {
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_SetNextGATTDiscoveryResponse_Name,
+ codec.align(FakeCentral_SetNextGATTDiscoveryResponse_Params.encodedSize),
+ codec.kMessageExpectsResponse, 0);
+ builder.encodeStruct(FakeCentral_SetNextGATTDiscoveryResponse_Params, params);
+ var message = builder.finish();
+ this.receiver_.acceptAndExpectResponse(message).then(function(message) {
+ var reader = new codec.MessageReader(message);
+ var responseParams =
+ reader.decodeStruct(FakeCentral_SetNextGATTDiscoveryResponse_ResponseParams);
+ resolve(responseParams);
+ }).catch(function(result) {
+ reject(Error("Connection error: " + result));
+ });
+ }.bind(this));
+ };
+ FakeCentralPtr.prototype.simulateGATTDisconnection = function() {
+ return FakeCentralProxy.prototype.simulateGATTDisconnection
+ .apply(this.ptr.getProxy(), arguments);
+ };
+
+ FakeCentralProxy.prototype.simulateGATTDisconnection = function(address) {
+ var params = new FakeCentral_SimulateGATTDisconnection_Params();
+ params.address = address;
+ return new Promise(function(resolve, reject) {
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_SimulateGATTDisconnection_Name,
+ codec.align(FakeCentral_SimulateGATTDisconnection_Params.encodedSize),
+ codec.kMessageExpectsResponse, 0);
+ builder.encodeStruct(FakeCentral_SimulateGATTDisconnection_Params, params);
+ var message = builder.finish();
+ this.receiver_.acceptAndExpectResponse(message).then(function(message) {
+ var reader = new codec.MessageReader(message);
+ var responseParams =
+ reader.decodeStruct(FakeCentral_SimulateGATTDisconnection_ResponseParams);
+ resolve(responseParams);
+ }).catch(function(result) {
+ reject(Error("Connection error: " + result));
+ });
+ }.bind(this));
+ };
+ FakeCentralPtr.prototype.simulateGATTServicesChanged = function() {
+ return FakeCentralProxy.prototype.simulateGATTServicesChanged
+ .apply(this.ptr.getProxy(), arguments);
+ };
+
+ FakeCentralProxy.prototype.simulateGATTServicesChanged = function(address) {
+ var params = new FakeCentral_SimulateGATTServicesChanged_Params();
+ params.address = address;
+ return new Promise(function(resolve, reject) {
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_SimulateGATTServicesChanged_Name,
+ codec.align(FakeCentral_SimulateGATTServicesChanged_Params.encodedSize),
+ codec.kMessageExpectsResponse, 0);
+ builder.encodeStruct(FakeCentral_SimulateGATTServicesChanged_Params, params);
+ var message = builder.finish();
+ this.receiver_.acceptAndExpectResponse(message).then(function(message) {
+ var reader = new codec.MessageReader(message);
+ var responseParams =
+ reader.decodeStruct(FakeCentral_SimulateGATTServicesChanged_ResponseParams);
+ resolve(responseParams);
+ }).catch(function(result) {
+ reject(Error("Connection error: " + result));
+ });
+ }.bind(this));
+ };
+ FakeCentralPtr.prototype.addFakeService = function() {
+ return FakeCentralProxy.prototype.addFakeService
+ .apply(this.ptr.getProxy(), arguments);
+ };
+
+ FakeCentralProxy.prototype.addFakeService = function(peripheralAddress, serviceUuid) {
+ var params = new FakeCentral_AddFakeService_Params();
+ params.peripheralAddress = peripheralAddress;
+ params.serviceUuid = serviceUuid;
+ return new Promise(function(resolve, reject) {
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_AddFakeService_Name,
+ codec.align(FakeCentral_AddFakeService_Params.encodedSize),
+ codec.kMessageExpectsResponse, 0);
+ builder.encodeStruct(FakeCentral_AddFakeService_Params, params);
+ var message = builder.finish();
+ this.receiver_.acceptAndExpectResponse(message).then(function(message) {
+ var reader = new codec.MessageReader(message);
+ var responseParams =
+ reader.decodeStruct(FakeCentral_AddFakeService_ResponseParams);
+ resolve(responseParams);
+ }).catch(function(result) {
+ reject(Error("Connection error: " + result));
+ });
+ }.bind(this));
+ };
+ FakeCentralPtr.prototype.addFakeCharacteristic = function() {
+ return FakeCentralProxy.prototype.addFakeCharacteristic
+ .apply(this.ptr.getProxy(), arguments);
+ };
+
+ FakeCentralProxy.prototype.addFakeCharacteristic = function(characteristicUuid, properties, serviceId, peripheralAddress) {
+ var params = new FakeCentral_AddFakeCharacteristic_Params();
+ params.characteristicUuid = characteristicUuid;
+ params.properties = properties;
+ params.serviceId = serviceId;
+ params.peripheralAddress = peripheralAddress;
+ return new Promise(function(resolve, reject) {
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_AddFakeCharacteristic_Name,
+ codec.align(FakeCentral_AddFakeCharacteristic_Params.encodedSize),
+ codec.kMessageExpectsResponse, 0);
+ builder.encodeStruct(FakeCentral_AddFakeCharacteristic_Params, params);
+ var message = builder.finish();
+ this.receiver_.acceptAndExpectResponse(message).then(function(message) {
+ var reader = new codec.MessageReader(message);
+ var responseParams =
+ reader.decodeStruct(FakeCentral_AddFakeCharacteristic_ResponseParams);
+ resolve(responseParams);
+ }).catch(function(result) {
+ reject(Error("Connection error: " + result));
+ });
+ }.bind(this));
+ };
+ FakeCentralPtr.prototype.removeFakeCharacteristic = function() {
+ return FakeCentralProxy.prototype.removeFakeCharacteristic
+ .apply(this.ptr.getProxy(), arguments);
+ };
+
+ FakeCentralProxy.prototype.removeFakeCharacteristic = function(identifier, serviceId, peripheralAddress) {
+ var params = new FakeCentral_RemoveFakeCharacteristic_Params();
+ params.identifier = identifier;
+ params.serviceId = serviceId;
+ params.peripheralAddress = peripheralAddress;
+ return new Promise(function(resolve, reject) {
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_RemoveFakeCharacteristic_Name,
+ codec.align(FakeCentral_RemoveFakeCharacteristic_Params.encodedSize),
+ codec.kMessageExpectsResponse, 0);
+ builder.encodeStruct(FakeCentral_RemoveFakeCharacteristic_Params, params);
+ var message = builder.finish();
+ this.receiver_.acceptAndExpectResponse(message).then(function(message) {
+ var reader = new codec.MessageReader(message);
+ var responseParams =
+ reader.decodeStruct(FakeCentral_RemoveFakeCharacteristic_ResponseParams);
+ resolve(responseParams);
+ }).catch(function(result) {
+ reject(Error("Connection error: " + result));
+ });
+ }.bind(this));
+ };
+ FakeCentralPtr.prototype.addFakeDescriptor = function() {
+ return FakeCentralProxy.prototype.addFakeDescriptor
+ .apply(this.ptr.getProxy(), arguments);
+ };
+
+ FakeCentralProxy.prototype.addFakeDescriptor = function(descriptorUuid, characteristicId, serviceId, peripheralAddress) {
+ var params = new FakeCentral_AddFakeDescriptor_Params();
+ params.descriptorUuid = descriptorUuid;
+ params.characteristicId = characteristicId;
+ params.serviceId = serviceId;
+ params.peripheralAddress = peripheralAddress;
+ return new Promise(function(resolve, reject) {
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_AddFakeDescriptor_Name,
+ codec.align(FakeCentral_AddFakeDescriptor_Params.encodedSize),
+ codec.kMessageExpectsResponse, 0);
+ builder.encodeStruct(FakeCentral_AddFakeDescriptor_Params, params);
+ var message = builder.finish();
+ this.receiver_.acceptAndExpectResponse(message).then(function(message) {
+ var reader = new codec.MessageReader(message);
+ var responseParams =
+ reader.decodeStruct(FakeCentral_AddFakeDescriptor_ResponseParams);
+ resolve(responseParams);
+ }).catch(function(result) {
+ reject(Error("Connection error: " + result));
+ });
+ }.bind(this));
+ };
+ FakeCentralPtr.prototype.setNextReadCharacteristicResponse = function() {
+ return FakeCentralProxy.prototype.setNextReadCharacteristicResponse
+ .apply(this.ptr.getProxy(), arguments);
+ };
+
+ FakeCentralProxy.prototype.setNextReadCharacteristicResponse = function(gattCode, value, characteristicId, serviceId, peripheralAddress) {
+ var params = new FakeCentral_SetNextReadCharacteristicResponse_Params();
+ params.gattCode = gattCode;
+ params.value = value;
+ params.characteristicId = characteristicId;
+ params.serviceId = serviceId;
+ params.peripheralAddress = peripheralAddress;
+ return new Promise(function(resolve, reject) {
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_SetNextReadCharacteristicResponse_Name,
+ codec.align(FakeCentral_SetNextReadCharacteristicResponse_Params.encodedSize),
+ codec.kMessageExpectsResponse, 0);
+ builder.encodeStruct(FakeCentral_SetNextReadCharacteristicResponse_Params, params);
+ var message = builder.finish();
+ this.receiver_.acceptAndExpectResponse(message).then(function(message) {
+ var reader = new codec.MessageReader(message);
+ var responseParams =
+ reader.decodeStruct(FakeCentral_SetNextReadCharacteristicResponse_ResponseParams);
+ resolve(responseParams);
+ }).catch(function(result) {
+ reject(Error("Connection error: " + result));
+ });
+ }.bind(this));
+ };
+ FakeCentralPtr.prototype.setNextWriteCharacteristicResponse = function() {
+ return FakeCentralProxy.prototype.setNextWriteCharacteristicResponse
+ .apply(this.ptr.getProxy(), arguments);
+ };
+
+ FakeCentralProxy.prototype.setNextWriteCharacteristicResponse = function(gattCode, characteristicId, serviceId, peripheralAddress) {
+ var params = new FakeCentral_SetNextWriteCharacteristicResponse_Params();
+ params.gattCode = gattCode;
+ params.characteristicId = characteristicId;
+ params.serviceId = serviceId;
+ params.peripheralAddress = peripheralAddress;
+ return new Promise(function(resolve, reject) {
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_SetNextWriteCharacteristicResponse_Name,
+ codec.align(FakeCentral_SetNextWriteCharacteristicResponse_Params.encodedSize),
+ codec.kMessageExpectsResponse, 0);
+ builder.encodeStruct(FakeCentral_SetNextWriteCharacteristicResponse_Params, params);
+ var message = builder.finish();
+ this.receiver_.acceptAndExpectResponse(message).then(function(message) {
+ var reader = new codec.MessageReader(message);
+ var responseParams =
+ reader.decodeStruct(FakeCentral_SetNextWriteCharacteristicResponse_ResponseParams);
+ resolve(responseParams);
+ }).catch(function(result) {
+ reject(Error("Connection error: " + result));
+ });
+ }.bind(this));
+ };
+ FakeCentralPtr.prototype.setNextSubscribeToNotificationsResponse = function() {
+ return FakeCentralProxy.prototype.setNextSubscribeToNotificationsResponse
+ .apply(this.ptr.getProxy(), arguments);
+ };
+
+ FakeCentralProxy.prototype.setNextSubscribeToNotificationsResponse = function(gattCode, characteristicId, serviceId, peripheralAddress) {
+ var params = new FakeCentral_SetNextSubscribeToNotificationsResponse_Params();
+ params.gattCode = gattCode;
+ params.characteristicId = characteristicId;
+ params.serviceId = serviceId;
+ params.peripheralAddress = peripheralAddress;
+ return new Promise(function(resolve, reject) {
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_SetNextSubscribeToNotificationsResponse_Name,
+ codec.align(FakeCentral_SetNextSubscribeToNotificationsResponse_Params.encodedSize),
+ codec.kMessageExpectsResponse, 0);
+ builder.encodeStruct(FakeCentral_SetNextSubscribeToNotificationsResponse_Params, params);
+ var message = builder.finish();
+ this.receiver_.acceptAndExpectResponse(message).then(function(message) {
+ var reader = new codec.MessageReader(message);
+ var responseParams =
+ reader.decodeStruct(FakeCentral_SetNextSubscribeToNotificationsResponse_ResponseParams);
+ resolve(responseParams);
+ }).catch(function(result) {
+ reject(Error("Connection error: " + result));
+ });
+ }.bind(this));
+ };
+ FakeCentralPtr.prototype.getLastWrittenValue = function() {
+ return FakeCentralProxy.prototype.getLastWrittenValue
+ .apply(this.ptr.getProxy(), arguments);
+ };
+
+ FakeCentralProxy.prototype.getLastWrittenValue = function(characteristicId, serviceId, peripheralAddress) {
+ var params = new FakeCentral_GetLastWrittenValue_Params();
+ params.characteristicId = characteristicId;
+ params.serviceId = serviceId;
+ params.peripheralAddress = peripheralAddress;
+ return new Promise(function(resolve, reject) {
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_GetLastWrittenValue_Name,
+ codec.align(FakeCentral_GetLastWrittenValue_Params.encodedSize),
+ codec.kMessageExpectsResponse, 0);
+ builder.encodeStruct(FakeCentral_GetLastWrittenValue_Params, params);
+ var message = builder.finish();
+ this.receiver_.acceptAndExpectResponse(message).then(function(message) {
+ var reader = new codec.MessageReader(message);
+ var responseParams =
+ reader.decodeStruct(FakeCentral_GetLastWrittenValue_ResponseParams);
+ resolve(responseParams);
+ }).catch(function(result) {
+ reject(Error("Connection error: " + result));
+ });
+ }.bind(this));
+ };
+ FakeCentralPtr.prototype.setNextReadDescriptorResponse = function() {
+ return FakeCentralProxy.prototype.setNextReadDescriptorResponse
+ .apply(this.ptr.getProxy(), arguments);
+ };
+
+ FakeCentralProxy.prototype.setNextReadDescriptorResponse = function(gattCode, value, descriptorId, characteristicId, serviceId, peripheralAddress) {
+ var params = new FakeCentral_SetNextReadDescriptorResponse_Params();
+ params.gattCode = gattCode;
+ params.value = value;
+ params.descriptorId = descriptorId;
+ params.characteristicId = characteristicId;
+ params.serviceId = serviceId;
+ params.peripheralAddress = peripheralAddress;
+ return new Promise(function(resolve, reject) {
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_SetNextReadDescriptorResponse_Name,
+ codec.align(FakeCentral_SetNextReadDescriptorResponse_Params.encodedSize),
+ codec.kMessageExpectsResponse, 0);
+ builder.encodeStruct(FakeCentral_SetNextReadDescriptorResponse_Params, params);
+ var message = builder.finish();
+ this.receiver_.acceptAndExpectResponse(message).then(function(message) {
+ var reader = new codec.MessageReader(message);
+ var responseParams =
+ reader.decodeStruct(FakeCentral_SetNextReadDescriptorResponse_ResponseParams);
+ resolve(responseParams);
+ }).catch(function(result) {
+ reject(Error("Connection error: " + result));
+ });
+ }.bind(this));
+ };
+
+ function FakeCentralStub(delegate) {
+ this.delegate_ = delegate;
+ }
+ FakeCentralStub.prototype.simulatePreconnectedPeripheral = function(address, name, knownServiceUuids) {
+ return this.delegate_ && this.delegate_.simulatePreconnectedPeripheral && this.delegate_.simulatePreconnectedPeripheral(address, name, knownServiceUuids);
+ }
+ FakeCentralStub.prototype.setNextGATTConnectionResponse = function(address, code) {
+ return this.delegate_ && this.delegate_.setNextGATTConnectionResponse && this.delegate_.setNextGATTConnectionResponse(address, code);
+ }
+ FakeCentralStub.prototype.setNextGATTDiscoveryResponse = function(address, code) {
+ return this.delegate_ && this.delegate_.setNextGATTDiscoveryResponse && this.delegate_.setNextGATTDiscoveryResponse(address, code);
+ }
+ FakeCentralStub.prototype.simulateGATTDisconnection = function(address) {
+ return this.delegate_ && this.delegate_.simulateGATTDisconnection && this.delegate_.simulateGATTDisconnection(address);
+ }
+ FakeCentralStub.prototype.simulateGATTServicesChanged = function(address) {
+ return this.delegate_ && this.delegate_.simulateGATTServicesChanged && this.delegate_.simulateGATTServicesChanged(address);
+ }
+ FakeCentralStub.prototype.addFakeService = function(peripheralAddress, serviceUuid) {
+ return this.delegate_ && this.delegate_.addFakeService && this.delegate_.addFakeService(peripheralAddress, serviceUuid);
+ }
+ FakeCentralStub.prototype.addFakeCharacteristic = function(characteristicUuid, properties, serviceId, peripheralAddress) {
+ return this.delegate_ && this.delegate_.addFakeCharacteristic && this.delegate_.addFakeCharacteristic(characteristicUuid, properties, serviceId, peripheralAddress);
+ }
+ FakeCentralStub.prototype.removeFakeCharacteristic = function(identifier, serviceId, peripheralAddress) {
+ return this.delegate_ && this.delegate_.removeFakeCharacteristic && this.delegate_.removeFakeCharacteristic(identifier, serviceId, peripheralAddress);
+ }
+ FakeCentralStub.prototype.addFakeDescriptor = function(descriptorUuid, characteristicId, serviceId, peripheralAddress) {
+ return this.delegate_ && this.delegate_.addFakeDescriptor && this.delegate_.addFakeDescriptor(descriptorUuid, characteristicId, serviceId, peripheralAddress);
+ }
+ FakeCentralStub.prototype.setNextReadCharacteristicResponse = function(gattCode, value, characteristicId, serviceId, peripheralAddress) {
+ return this.delegate_ && this.delegate_.setNextReadCharacteristicResponse && this.delegate_.setNextReadCharacteristicResponse(gattCode, value, characteristicId, serviceId, peripheralAddress);
+ }
+ FakeCentralStub.prototype.setNextWriteCharacteristicResponse = function(gattCode, characteristicId, serviceId, peripheralAddress) {
+ return this.delegate_ && this.delegate_.setNextWriteCharacteristicResponse && this.delegate_.setNextWriteCharacteristicResponse(gattCode, characteristicId, serviceId, peripheralAddress);
+ }
+ FakeCentralStub.prototype.setNextSubscribeToNotificationsResponse = function(gattCode, characteristicId, serviceId, peripheralAddress) {
+ return this.delegate_ && this.delegate_.setNextSubscribeToNotificationsResponse && this.delegate_.setNextSubscribeToNotificationsResponse(gattCode, characteristicId, serviceId, peripheralAddress);
+ }
+ FakeCentralStub.prototype.getLastWrittenValue = function(characteristicId, serviceId, peripheralAddress) {
+ return this.delegate_ && this.delegate_.getLastWrittenValue && this.delegate_.getLastWrittenValue(characteristicId, serviceId, peripheralAddress);
+ }
+ FakeCentralStub.prototype.setNextReadDescriptorResponse = function(gattCode, value, descriptorId, characteristicId, serviceId, peripheralAddress) {
+ return this.delegate_ && this.delegate_.setNextReadDescriptorResponse && this.delegate_.setNextReadDescriptorResponse(gattCode, value, descriptorId, characteristicId, serviceId, peripheralAddress);
+ }
+
+ FakeCentralStub.prototype.accept = function(message) {
+ var reader = new codec.MessageReader(message);
+ switch (reader.messageName) {
+ default:
+ return false;
+ }
+ };
+
+ FakeCentralStub.prototype.acceptWithResponder =
+ function(message, responder) {
+ var reader = new codec.MessageReader(message);
+ switch (reader.messageName) {
+ case kFakeCentral_SimulatePreconnectedPeripheral_Name:
+ var params = reader.decodeStruct(FakeCentral_SimulatePreconnectedPeripheral_Params);
+ this.simulatePreconnectedPeripheral(params.address, params.name, params.knownServiceUuids).then(function(response) {
+ var responseParams =
+ new FakeCentral_SimulatePreconnectedPeripheral_ResponseParams();
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_SimulatePreconnectedPeripheral_Name,
+ codec.align(FakeCentral_SimulatePreconnectedPeripheral_ResponseParams.encodedSize),
+ codec.kMessageIsResponse, reader.requestID);
+ builder.encodeStruct(FakeCentral_SimulatePreconnectedPeripheral_ResponseParams,
+ responseParams);
+ var message = builder.finish();
+ responder.accept(message);
+ });
+ return true;
+ case kFakeCentral_SetNextGATTConnectionResponse_Name:
+ var params = reader.decodeStruct(FakeCentral_SetNextGATTConnectionResponse_Params);
+ this.setNextGATTConnectionResponse(params.address, params.code).then(function(response) {
+ var responseParams =
+ new FakeCentral_SetNextGATTConnectionResponse_ResponseParams();
+ responseParams.success = response.success;
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_SetNextGATTConnectionResponse_Name,
+ codec.align(FakeCentral_SetNextGATTConnectionResponse_ResponseParams.encodedSize),
+ codec.kMessageIsResponse, reader.requestID);
+ builder.encodeStruct(FakeCentral_SetNextGATTConnectionResponse_ResponseParams,
+ responseParams);
+ var message = builder.finish();
+ responder.accept(message);
+ });
+ return true;
+ case kFakeCentral_SetNextGATTDiscoveryResponse_Name:
+ var params = reader.decodeStruct(FakeCentral_SetNextGATTDiscoveryResponse_Params);
+ this.setNextGATTDiscoveryResponse(params.address, params.code).then(function(response) {
+ var responseParams =
+ new FakeCentral_SetNextGATTDiscoveryResponse_ResponseParams();
+ responseParams.success = response.success;
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_SetNextGATTDiscoveryResponse_Name,
+ codec.align(FakeCentral_SetNextGATTDiscoveryResponse_ResponseParams.encodedSize),
+ codec.kMessageIsResponse, reader.requestID);
+ builder.encodeStruct(FakeCentral_SetNextGATTDiscoveryResponse_ResponseParams,
+ responseParams);
+ var message = builder.finish();
+ responder.accept(message);
+ });
+ return true;
+ case kFakeCentral_SimulateGATTDisconnection_Name:
+ var params = reader.decodeStruct(FakeCentral_SimulateGATTDisconnection_Params);
+ this.simulateGATTDisconnection(params.address).then(function(response) {
+ var responseParams =
+ new FakeCentral_SimulateGATTDisconnection_ResponseParams();
+ responseParams.success = response.success;
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_SimulateGATTDisconnection_Name,
+ codec.align(FakeCentral_SimulateGATTDisconnection_ResponseParams.encodedSize),
+ codec.kMessageIsResponse, reader.requestID);
+ builder.encodeStruct(FakeCentral_SimulateGATTDisconnection_ResponseParams,
+ responseParams);
+ var message = builder.finish();
+ responder.accept(message);
+ });
+ return true;
+ case kFakeCentral_SimulateGATTServicesChanged_Name:
+ var params = reader.decodeStruct(FakeCentral_SimulateGATTServicesChanged_Params);
+ this.simulateGATTServicesChanged(params.address).then(function(response) {
+ var responseParams =
+ new FakeCentral_SimulateGATTServicesChanged_ResponseParams();
+ responseParams.success = response.success;
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_SimulateGATTServicesChanged_Name,
+ codec.align(FakeCentral_SimulateGATTServicesChanged_ResponseParams.encodedSize),
+ codec.kMessageIsResponse, reader.requestID);
+ builder.encodeStruct(FakeCentral_SimulateGATTServicesChanged_ResponseParams,
+ responseParams);
+ var message = builder.finish();
+ responder.accept(message);
+ });
+ return true;
+ case kFakeCentral_AddFakeService_Name:
+ var params = reader.decodeStruct(FakeCentral_AddFakeService_Params);
+ this.addFakeService(params.peripheralAddress, params.serviceUuid).then(function(response) {
+ var responseParams =
+ new FakeCentral_AddFakeService_ResponseParams();
+ responseParams.serviceId = response.serviceId;
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_AddFakeService_Name,
+ codec.align(FakeCentral_AddFakeService_ResponseParams.encodedSize),
+ codec.kMessageIsResponse, reader.requestID);
+ builder.encodeStruct(FakeCentral_AddFakeService_ResponseParams,
+ responseParams);
+ var message = builder.finish();
+ responder.accept(message);
+ });
+ return true;
+ case kFakeCentral_AddFakeCharacteristic_Name:
+ var params = reader.decodeStruct(FakeCentral_AddFakeCharacteristic_Params);
+ this.addFakeCharacteristic(params.characteristicUuid, params.properties, params.serviceId, params.peripheralAddress).then(function(response) {
+ var responseParams =
+ new FakeCentral_AddFakeCharacteristic_ResponseParams();
+ responseParams.characteristicId = response.characteristicId;
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_AddFakeCharacteristic_Name,
+ codec.align(FakeCentral_AddFakeCharacteristic_ResponseParams.encodedSize),
+ codec.kMessageIsResponse, reader.requestID);
+ builder.encodeStruct(FakeCentral_AddFakeCharacteristic_ResponseParams,
+ responseParams);
+ var message = builder.finish();
+ responder.accept(message);
+ });
+ return true;
+ case kFakeCentral_RemoveFakeCharacteristic_Name:
+ var params = reader.decodeStruct(FakeCentral_RemoveFakeCharacteristic_Params);
+ this.removeFakeCharacteristic(params.identifier, params.serviceId, params.peripheralAddress).then(function(response) {
+ var responseParams =
+ new FakeCentral_RemoveFakeCharacteristic_ResponseParams();
+ responseParams.success = response.success;
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_RemoveFakeCharacteristic_Name,
+ codec.align(FakeCentral_RemoveFakeCharacteristic_ResponseParams.encodedSize),
+ codec.kMessageIsResponse, reader.requestID);
+ builder.encodeStruct(FakeCentral_RemoveFakeCharacteristic_ResponseParams,
+ responseParams);
+ var message = builder.finish();
+ responder.accept(message);
+ });
+ return true;
+ case kFakeCentral_AddFakeDescriptor_Name:
+ var params = reader.decodeStruct(FakeCentral_AddFakeDescriptor_Params);
+ this.addFakeDescriptor(params.descriptorUuid, params.characteristicId, params.serviceId, params.peripheralAddress).then(function(response) {
+ var responseParams =
+ new FakeCentral_AddFakeDescriptor_ResponseParams();
+ responseParams.descriptorId = response.descriptorId;
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_AddFakeDescriptor_Name,
+ codec.align(FakeCentral_AddFakeDescriptor_ResponseParams.encodedSize),
+ codec.kMessageIsResponse, reader.requestID);
+ builder.encodeStruct(FakeCentral_AddFakeDescriptor_ResponseParams,
+ responseParams);
+ var message = builder.finish();
+ responder.accept(message);
+ });
+ return true;
+ case kFakeCentral_SetNextReadCharacteristicResponse_Name:
+ var params = reader.decodeStruct(FakeCentral_SetNextReadCharacteristicResponse_Params);
+ this.setNextReadCharacteristicResponse(params.gattCode, params.value, params.characteristicId, params.serviceId, params.peripheralAddress).then(function(response) {
+ var responseParams =
+ new FakeCentral_SetNextReadCharacteristicResponse_ResponseParams();
+ responseParams.success = response.success;
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_SetNextReadCharacteristicResponse_Name,
+ codec.align(FakeCentral_SetNextReadCharacteristicResponse_ResponseParams.encodedSize),
+ codec.kMessageIsResponse, reader.requestID);
+ builder.encodeStruct(FakeCentral_SetNextReadCharacteristicResponse_ResponseParams,
+ responseParams);
+ var message = builder.finish();
+ responder.accept(message);
+ });
+ return true;
+ case kFakeCentral_SetNextWriteCharacteristicResponse_Name:
+ var params = reader.decodeStruct(FakeCentral_SetNextWriteCharacteristicResponse_Params);
+ this.setNextWriteCharacteristicResponse(params.gattCode, params.characteristicId, params.serviceId, params.peripheralAddress).then(function(response) {
+ var responseParams =
+ new FakeCentral_SetNextWriteCharacteristicResponse_ResponseParams();
+ responseParams.success = response.success;
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_SetNextWriteCharacteristicResponse_Name,
+ codec.align(FakeCentral_SetNextWriteCharacteristicResponse_ResponseParams.encodedSize),
+ codec.kMessageIsResponse, reader.requestID);
+ builder.encodeStruct(FakeCentral_SetNextWriteCharacteristicResponse_ResponseParams,
+ responseParams);
+ var message = builder.finish();
+ responder.accept(message);
+ });
+ return true;
+ case kFakeCentral_SetNextSubscribeToNotificationsResponse_Name:
+ var params = reader.decodeStruct(FakeCentral_SetNextSubscribeToNotificationsResponse_Params);
+ this.setNextSubscribeToNotificationsResponse(params.gattCode, params.characteristicId, params.serviceId, params.peripheralAddress).then(function(response) {
+ var responseParams =
+ new FakeCentral_SetNextSubscribeToNotificationsResponse_ResponseParams();
+ responseParams.success = response.success;
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_SetNextSubscribeToNotificationsResponse_Name,
+ codec.align(FakeCentral_SetNextSubscribeToNotificationsResponse_ResponseParams.encodedSize),
+ codec.kMessageIsResponse, reader.requestID);
+ builder.encodeStruct(FakeCentral_SetNextSubscribeToNotificationsResponse_ResponseParams,
+ responseParams);
+ var message = builder.finish();
+ responder.accept(message);
+ });
+ return true;
+ case kFakeCentral_GetLastWrittenValue_Name:
+ var params = reader.decodeStruct(FakeCentral_GetLastWrittenValue_Params);
+ this.getLastWrittenValue(params.characteristicId, params.serviceId, params.peripheralAddress).then(function(response) {
+ var responseParams =
+ new FakeCentral_GetLastWrittenValue_ResponseParams();
+ responseParams.success = response.success;
+ responseParams.value = response.value;
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_GetLastWrittenValue_Name,
+ codec.align(FakeCentral_GetLastWrittenValue_ResponseParams.encodedSize),
+ codec.kMessageIsResponse, reader.requestID);
+ builder.encodeStruct(FakeCentral_GetLastWrittenValue_ResponseParams,
+ responseParams);
+ var message = builder.finish();
+ responder.accept(message);
+ });
+ return true;
+ case kFakeCentral_SetNextReadDescriptorResponse_Name:
+ var params = reader.decodeStruct(FakeCentral_SetNextReadDescriptorResponse_Params);
+ this.setNextReadDescriptorResponse(params.gattCode, params.value, params.descriptorId, params.characteristicId, params.serviceId, params.peripheralAddress).then(function(response) {
+ var responseParams =
+ new FakeCentral_SetNextReadDescriptorResponse_ResponseParams();
+ responseParams.success = response.success;
+ var builder = new codec.MessageV1Builder(
+ kFakeCentral_SetNextReadDescriptorResponse_Name,
+ codec.align(FakeCentral_SetNextReadDescriptorResponse_ResponseParams.encodedSize),
+ codec.kMessageIsResponse, reader.requestID);
+ builder.encodeStruct(FakeCentral_SetNextReadDescriptorResponse_ResponseParams,
+ responseParams);
+ var message = builder.finish();
+ responder.accept(message);
+ });
+ return true;
+ default:
+ return false;
+ }
+ };
+
+ function validateFakeCentralRequest(messageValidator) {
+ var message = messageValidator.message;
+ var paramsClass = null;
+ switch (message.getName()) {
+ case kFakeCentral_SimulatePreconnectedPeripheral_Name:
+ if (message.expectsResponse())
+ paramsClass = FakeCentral_SimulatePreconnectedPeripheral_Params;
+ break;
+ case kFakeCentral_SetNextGATTConnectionResponse_Name:
+ if (message.expectsResponse())
+ paramsClass = FakeCentral_SetNextGATTConnectionResponse_Params;
+ break;
+ case kFakeCentral_SetNextGATTDiscoveryResponse_Name:
+ if (message.expectsResponse())
+ paramsClass = FakeCentral_SetNextGATTDiscoveryResponse_Params;
+ break;
+ case kFakeCentral_SimulateGATTDisconnection_Name:
+ if (message.expectsResponse())
+ paramsClass = FakeCentral_SimulateGATTDisconnection_Params;
+ break;
+ case kFakeCentral_SimulateGATTServicesChanged_Name:
+ if (message.expectsResponse())
+ paramsClass = FakeCentral_SimulateGATTServicesChanged_Params;
+ break;
+ case kFakeCentral_AddFakeService_Name:
+ if (message.expectsResponse())
+ paramsClass = FakeCentral_AddFakeService_Params;
+ break;
+ case kFakeCentral_AddFakeCharacteristic_Name:
+ if (message.expectsResponse())
+ paramsClass = FakeCentral_AddFakeCharacteristic_Params;
+ break;
+ case kFakeCentral_RemoveFakeCharacteristic_Name:
+ if (message.expectsResponse())
+ paramsClass = FakeCentral_RemoveFakeCharacteristic_Params;
+ break;
+ case kFakeCentral_AddFakeDescriptor_Name:
+ if (message.expectsResponse())
+ paramsClass = FakeCentral_AddFakeDescriptor_Params;
+ break;
+ case kFakeCentral_SetNextReadCharacteristicResponse_Name:
+ if (message.expectsResponse())
+ paramsClass = FakeCentral_SetNextReadCharacteristicResponse_Params;
+ break;
+ case kFakeCentral_SetNextWriteCharacteristicResponse_Name:
+ if (message.expectsResponse())
+ paramsClass = FakeCentral_SetNextWriteCharacteristicResponse_Params;
+ break;
+ case kFakeCentral_SetNextSubscribeToNotificationsResponse_Name:
+ if (message.expectsResponse())
+ paramsClass = FakeCentral_SetNextSubscribeToNotificationsResponse_Params;
+ break;
+ case kFakeCentral_GetLastWrittenValue_Name:
+ if (message.expectsResponse())
+ paramsClass = FakeCentral_GetLastWrittenValue_Params;
+ break;
+ case kFakeCentral_SetNextReadDescriptorResponse_Name:
+ if (message.expectsResponse())
+ paramsClass = FakeCentral_SetNextReadDescriptorResponse_Params;
+ break;
+ }
+ if (paramsClass === null)
+ return validator.validationError.NONE;
+ return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes());
+ }
+
+ function validateFakeCentralResponse(messageValidator) {
+ var message = messageValidator.message;
+ var paramsClass = null;
+ switch (message.getName()) {
+ case kFakeCentral_SimulatePreconnectedPeripheral_Name:
+ if (message.isResponse())
+ paramsClass = FakeCentral_SimulatePreconnectedPeripheral_ResponseParams;
+ break;
+ case kFakeCentral_SetNextGATTConnectionResponse_Name:
+ if (message.isResponse())
+ paramsClass = FakeCentral_SetNextGATTConnectionResponse_ResponseParams;
+ break;
+ case kFakeCentral_SetNextGATTDiscoveryResponse_Name:
+ if (message.isResponse())
+ paramsClass = FakeCentral_SetNextGATTDiscoveryResponse_ResponseParams;
+ break;
+ case kFakeCentral_SimulateGATTDisconnection_Name:
+ if (message.isResponse())
+ paramsClass = FakeCentral_SimulateGATTDisconnection_ResponseParams;
+ break;
+ case kFakeCentral_SimulateGATTServicesChanged_Name:
+ if (message.isResponse())
+ paramsClass = FakeCentral_SimulateGATTServicesChanged_ResponseParams;
+ break;
+ case kFakeCentral_AddFakeService_Name:
+ if (message.isResponse())
+ paramsClass = FakeCentral_AddFakeService_ResponseParams;
+ break;
+ case kFakeCentral_AddFakeCharacteristic_Name:
+ if (message.isResponse())
+ paramsClass = FakeCentral_AddFakeCharacteristic_ResponseParams;
+ break;
+ case kFakeCentral_RemoveFakeCharacteristic_Name:
+ if (message.isResponse())
+ paramsClass = FakeCentral_RemoveFakeCharacteristic_ResponseParams;
+ break;
+ case kFakeCentral_AddFakeDescriptor_Name:
+ if (message.isResponse())
+ paramsClass = FakeCentral_AddFakeDescriptor_ResponseParams;
+ break;
+ case kFakeCentral_SetNextReadCharacteristicResponse_Name:
+ if (message.isResponse())
+ paramsClass = FakeCentral_SetNextReadCharacteristicResponse_ResponseParams;
+ break;
+ case kFakeCentral_SetNextWriteCharacteristicResponse_Name:
+ if (message.isResponse())
+ paramsClass = FakeCentral_SetNextWriteCharacteristicResponse_ResponseParams;
+ break;
+ case kFakeCentral_SetNextSubscribeToNotificationsResponse_Name:
+ if (message.isResponse())
+ paramsClass = FakeCentral_SetNextSubscribeToNotificationsResponse_ResponseParams;
+ break;
+ case kFakeCentral_GetLastWrittenValue_Name:
+ if (message.isResponse())
+ paramsClass = FakeCentral_GetLastWrittenValue_ResponseParams;
+ break;
+ case kFakeCentral_SetNextReadDescriptorResponse_Name:
+ if (message.isResponse())
+ paramsClass = FakeCentral_SetNextReadDescriptorResponse_ResponseParams;
+ break;
+ }
+ if (paramsClass === null)
+ return validator.validationError.NONE;
+ return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes());
+ }
+
+ var FakeCentral = {
+ name: 'bluetooth::mojom::FakeCentral',
+ kVersion: 0,
+ ptrClass: FakeCentralPtr,
+ proxyClass: FakeCentralProxy,
+ stubClass: FakeCentralStub,
+ validateRequest: validateFakeCentralRequest,
+ validateResponse: validateFakeCentralResponse,
+ };
+ FakeCentralStub.prototype.validator = validateFakeCentralRequest;
+ FakeCentralProxy.prototype.validator = validateFakeCentralResponse;
+ exports.kHCISuccess = kHCISuccess;
+ exports.kHCIConnectionTimeout = kHCIConnectionTimeout;
+ exports.kGATTSuccess = kGATTSuccess;
+ exports.kGATTInvalidHandle = kGATTInvalidHandle;
+ exports.CentralState = CentralState;
+ exports.CharacteristicProperties = CharacteristicProperties;
+ exports.FakeBluetooth = FakeBluetooth;
+ exports.FakeBluetoothPtr = FakeBluetoothPtr;
+ exports.FakeBluetoothAssociatedPtr = FakeBluetoothAssociatedPtr;
+ exports.FakeCentral = FakeCentral;
+ exports.FakeCentralPtr = FakeCentralPtr;
+ exports.FakeCentralAssociatedPtr = FakeCentralAssociatedPtr;
+})(); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/common/vendor-prefix.js.headers b/tests/wpt/web-platform-tests/resources/chromium/fake_bluetooth.mojom.js.headers
index 6805c323df5..6805c323df5 100644
--- a/tests/wpt/web-platform-tests/common/vendor-prefix.js.headers
+++ b/tests/wpt/web-platform-tests/resources/chromium/fake_bluetooth.mojom.js.headers
diff --git a/tests/wpt/web-platform-tests/resources/chromium/mojo_layouttest_test.mojom.js b/tests/wpt/web-platform-tests/resources/chromium/mojo_layouttest_test.mojom.js
new file mode 100644
index 00000000000..839d42a0f08
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/chromium/mojo_layouttest_test.mojom.js
@@ -0,0 +1,264 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+(function() {
+ var mojomId = 'content/test/data/mojo_layouttest_test.mojom';
+ if (mojo.internal.isMojomLoaded(mojomId)) {
+ console.warn('The following mojom is loaded multiple times: ' + mojomId);
+ return;
+ }
+ mojo.internal.markMojomLoaded(mojomId);
+
+ // TODO(yzshen): Define these aliases to minimize the differences between the
+ // old/new modes. Remove them when the old mode goes away.
+ var bindings = mojo;
+ var associatedBindings = mojo;
+ var codec = mojo.internal;
+ var validator = mojo.internal;
+
+ var exports = mojo.internal.exposeNamespace('content.mojom');
+
+
+
+ function MojoLayoutTestHelper_Reverse_Params(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ MojoLayoutTestHelper_Reverse_Params.prototype.initDefaults_ = function() {
+ this.message = null;
+ };
+ MojoLayoutTestHelper_Reverse_Params.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ MojoLayoutTestHelper_Reverse_Params.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 16}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate MojoLayoutTestHelper_Reverse_Params.message
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ return validator.validationError.NONE;
+ };
+
+ MojoLayoutTestHelper_Reverse_Params.encodedSize = codec.kStructHeaderSize + 8;
+
+ MojoLayoutTestHelper_Reverse_Params.decode = function(decoder) {
+ var packed;
+ var val = new MojoLayoutTestHelper_Reverse_Params();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ val.message = decoder.decodeStruct(codec.String);
+ return val;
+ };
+
+ MojoLayoutTestHelper_Reverse_Params.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(MojoLayoutTestHelper_Reverse_Params.encodedSize);
+ encoder.writeUint32(0);
+ encoder.encodeStruct(codec.String, val.message);
+ };
+ function MojoLayoutTestHelper_Reverse_ResponseParams(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ MojoLayoutTestHelper_Reverse_ResponseParams.prototype.initDefaults_ = function() {
+ this.reversed = null;
+ };
+ MojoLayoutTestHelper_Reverse_ResponseParams.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ MojoLayoutTestHelper_Reverse_ResponseParams.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 16}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate MojoLayoutTestHelper_Reverse_ResponseParams.reversed
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ return validator.validationError.NONE;
+ };
+
+ MojoLayoutTestHelper_Reverse_ResponseParams.encodedSize = codec.kStructHeaderSize + 8;
+
+ MojoLayoutTestHelper_Reverse_ResponseParams.decode = function(decoder) {
+ var packed;
+ var val = new MojoLayoutTestHelper_Reverse_ResponseParams();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ val.reversed = decoder.decodeStruct(codec.String);
+ return val;
+ };
+
+ MojoLayoutTestHelper_Reverse_ResponseParams.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(MojoLayoutTestHelper_Reverse_ResponseParams.encodedSize);
+ encoder.writeUint32(0);
+ encoder.encodeStruct(codec.String, val.reversed);
+ };
+ var kMojoLayoutTestHelper_Reverse_Name = 0;
+
+ function MojoLayoutTestHelperPtr(handleOrPtrInfo) {
+ this.ptr = new bindings.InterfacePtrController(MojoLayoutTestHelper,
+ handleOrPtrInfo);
+ }
+
+ function MojoLayoutTestHelperAssociatedPtr(associatedInterfacePtrInfo) {
+ this.ptr = new associatedBindings.AssociatedInterfacePtrController(
+ MojoLayoutTestHelper, associatedInterfacePtrInfo);
+ }
+
+ MojoLayoutTestHelperAssociatedPtr.prototype =
+ Object.create(MojoLayoutTestHelperPtr.prototype);
+ MojoLayoutTestHelperAssociatedPtr.prototype.constructor =
+ MojoLayoutTestHelperAssociatedPtr;
+
+ function MojoLayoutTestHelperProxy(receiver) {
+ this.receiver_ = receiver;
+ }
+ MojoLayoutTestHelperPtr.prototype.reverse = function() {
+ return MojoLayoutTestHelperProxy.prototype.reverse
+ .apply(this.ptr.getProxy(), arguments);
+ };
+
+ MojoLayoutTestHelperProxy.prototype.reverse = function(message) {
+ var params = new MojoLayoutTestHelper_Reverse_Params();
+ params.message = message;
+ return new Promise(function(resolve, reject) {
+ var builder = new codec.MessageV1Builder(
+ kMojoLayoutTestHelper_Reverse_Name,
+ codec.align(MojoLayoutTestHelper_Reverse_Params.encodedSize),
+ codec.kMessageExpectsResponse, 0);
+ builder.encodeStruct(MojoLayoutTestHelper_Reverse_Params, params);
+ var message = builder.finish();
+ this.receiver_.acceptAndExpectResponse(message).then(function(message) {
+ var reader = new codec.MessageReader(message);
+ var responseParams =
+ reader.decodeStruct(MojoLayoutTestHelper_Reverse_ResponseParams);
+ resolve(responseParams);
+ }).catch(function(result) {
+ reject(Error("Connection error: " + result));
+ });
+ }.bind(this));
+ };
+
+ function MojoLayoutTestHelperStub(delegate) {
+ this.delegate_ = delegate;
+ }
+ MojoLayoutTestHelperStub.prototype.reverse = function(message) {
+ return this.delegate_ && this.delegate_.reverse && this.delegate_.reverse(message);
+ }
+
+ MojoLayoutTestHelperStub.prototype.accept = function(message) {
+ var reader = new codec.MessageReader(message);
+ switch (reader.messageName) {
+ default:
+ return false;
+ }
+ };
+
+ MojoLayoutTestHelperStub.prototype.acceptWithResponder =
+ function(message, responder) {
+ var reader = new codec.MessageReader(message);
+ switch (reader.messageName) {
+ case kMojoLayoutTestHelper_Reverse_Name:
+ var params = reader.decodeStruct(MojoLayoutTestHelper_Reverse_Params);
+ this.reverse(params.message).then(function(response) {
+ var responseParams =
+ new MojoLayoutTestHelper_Reverse_ResponseParams();
+ responseParams.reversed = response.reversed;
+ var builder = new codec.MessageV1Builder(
+ kMojoLayoutTestHelper_Reverse_Name,
+ codec.align(MojoLayoutTestHelper_Reverse_ResponseParams.encodedSize),
+ codec.kMessageIsResponse, reader.requestID);
+ builder.encodeStruct(MojoLayoutTestHelper_Reverse_ResponseParams,
+ responseParams);
+ var message = builder.finish();
+ responder.accept(message);
+ });
+ return true;
+ default:
+ return false;
+ }
+ };
+
+ function validateMojoLayoutTestHelperRequest(messageValidator) {
+ var message = messageValidator.message;
+ var paramsClass = null;
+ switch (message.getName()) {
+ case kMojoLayoutTestHelper_Reverse_Name:
+ if (message.expectsResponse())
+ paramsClass = MojoLayoutTestHelper_Reverse_Params;
+ break;
+ }
+ if (paramsClass === null)
+ return validator.validationError.NONE;
+ return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes());
+ }
+
+ function validateMojoLayoutTestHelperResponse(messageValidator) {
+ var message = messageValidator.message;
+ var paramsClass = null;
+ switch (message.getName()) {
+ case kMojoLayoutTestHelper_Reverse_Name:
+ if (message.isResponse())
+ paramsClass = MojoLayoutTestHelper_Reverse_ResponseParams;
+ break;
+ }
+ if (paramsClass === null)
+ return validator.validationError.NONE;
+ return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes());
+ }
+
+ var MojoLayoutTestHelper = {
+ name: 'content::mojom::MojoLayoutTestHelper',
+ kVersion: 0,
+ ptrClass: MojoLayoutTestHelperPtr,
+ proxyClass: MojoLayoutTestHelperProxy,
+ stubClass: MojoLayoutTestHelperStub,
+ validateRequest: validateMojoLayoutTestHelperRequest,
+ validateResponse: validateMojoLayoutTestHelperResponse,
+ };
+ MojoLayoutTestHelperStub.prototype.validator = validateMojoLayoutTestHelperRequest;
+ MojoLayoutTestHelperProxy.prototype.validator = validateMojoLayoutTestHelperResponse;
+ exports.MojoLayoutTestHelper = MojoLayoutTestHelper;
+ exports.MojoLayoutTestHelperPtr = MojoLayoutTestHelperPtr;
+ exports.MojoLayoutTestHelperAssociatedPtr = MojoLayoutTestHelperAssociatedPtr;
+})(); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/chromium/mojo_layouttest_test.mojom.js.headers b/tests/wpt/web-platform-tests/resources/chromium/mojo_layouttest_test.mojom.js.headers
new file mode 100644
index 00000000000..6805c323df5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/chromium/mojo_layouttest_test.mojom.js.headers
@@ -0,0 +1 @@
+Content-Type: text/javascript; charset=utf-8
diff --git a/tests/wpt/web-platform-tests/resources/chromium/uuid.mojom.js b/tests/wpt/web-platform-tests/resources/chromium/uuid.mojom.js
new file mode 100644
index 00000000000..03a8b8d3c9e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/chromium/uuid.mojom.js
@@ -0,0 +1,82 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+(function() {
+ var mojomId = 'device/bluetooth/public/interfaces/uuid.mojom';
+ if (mojo.internal.isMojomLoaded(mojomId)) {
+ console.warn('The following mojom is loaded multiple times: ' + mojomId);
+ return;
+ }
+ mojo.internal.markMojomLoaded(mojomId);
+
+ // TODO(yzshen): Define these aliases to minimize the differences between the
+ // old/new modes. Remove them when the old mode goes away.
+ var bindings = mojo;
+ var associatedBindings = mojo;
+ var codec = mojo.internal;
+ var validator = mojo.internal;
+
+ var exports = mojo.internal.exposeNamespace('bluetooth.mojom');
+
+
+
+ function UUID(values) {
+ this.initDefaults_();
+ this.initFields_(values);
+ }
+
+
+ UUID.prototype.initDefaults_ = function() {
+ this.uuid = null;
+ };
+ UUID.prototype.initFields_ = function(fields) {
+ for(var field in fields) {
+ if (this.hasOwnProperty(field))
+ this[field] = fields[field];
+ }
+ };
+
+ UUID.validate = function(messageValidator, offset) {
+ var err;
+ err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ var kVersionSizes = [
+ {version: 0, numBytes: 16}
+ ];
+ err = messageValidator.validateStructVersion(offset, kVersionSizes);
+ if (err !== validator.validationError.NONE)
+ return err;
+
+
+ // validate UUID.uuid
+ err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false)
+ if (err !== validator.validationError.NONE)
+ return err;
+
+ return validator.validationError.NONE;
+ };
+
+ UUID.encodedSize = codec.kStructHeaderSize + 8;
+
+ UUID.decode = function(decoder) {
+ var packed;
+ var val = new UUID();
+ var numberOfBytes = decoder.readUint32();
+ var version = decoder.readUint32();
+ val.uuid = decoder.decodeStruct(codec.String);
+ return val;
+ };
+
+ UUID.encode = function(encoder, val) {
+ var packed;
+ encoder.writeUint32(UUID.encodedSize);
+ encoder.writeUint32(0);
+ encoder.encodeStruct(codec.String, val.uuid);
+ };
+ exports.UUID = UUID;
+})(); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/chromium/uuid.mojom.js.headers b/tests/wpt/web-platform-tests/resources/chromium/uuid.mojom.js.headers
new file mode 100644
index 00000000000..6805c323df5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/chromium/uuid.mojom.js.headers
@@ -0,0 +1 @@
+Content-Type: text/javascript; charset=utf-8
diff --git a/tests/wpt/web-platform-tests/resources/chromium/web-bluetooth-test.js b/tests/wpt/web-platform-tests/resources/chromium/web-bluetooth-test.js
new file mode 100644
index 00000000000..1658ff1a14f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/chromium/web-bluetooth-test.js
@@ -0,0 +1,370 @@
+'use strict';
+
+function toMojoCentralState(state) {
+ switch (state) {
+ case 'absent':
+ return bluetooth.mojom.CentralState.ABSENT;
+ case 'powered-off':
+ return bluetooth.mojom.CentralState.POWERED_OFF;
+ case 'powered-on':
+ return bluetooth.mojom.CentralState.POWERED_ON;
+ default:
+ throw `Unsupported value ${state} for state.`;
+ }
+}
+
+// Mapping of the property names of
+// BluetoothCharacteristicProperties defined in
+// https://webbluetoothcg.github.io/web-bluetooth/#characteristicproperties
+// to property names of the CharacteristicProperties mojo struct.
+const CHARACTERISTIC_PROPERTIES_WEB_TO_MOJO = {
+ broadcast: 'broadcast',
+ read: 'read',
+ write_without_response: 'write_without_response',
+ write: 'write',
+ notify: 'notify',
+ indicate: 'indicate',
+ authenticatedSignedWrites: 'authenticated_signed_writes',
+ extended_properties: 'extended_properties',
+};
+
+function ArrayToMojoCharacteristicProperties(arr) {
+ let struct = new bluetooth.mojom.CharacteristicProperties();
+
+ arr.forEach(val => {
+ let mojo_property =
+ CHARACTERISTIC_PROPERTIES_WEB_TO_MOJO[val];
+
+ if (struct.hasOwnProperty(mojo_property))
+ struct[mojo_property] = true;
+ else
+ throw `Invalid member '${val}' for CharacteristicProperties`;
+ });
+
+ return struct;
+}
+
+
+class FakeBluetooth {
+ constructor() {
+ this.fake_bluetooth_ptr_ = new bluetooth.mojom.FakeBluetoothPtr();
+ Mojo.bindInterface(bluetooth.mojom.FakeBluetooth.name,
+ mojo.makeRequest(this.fake_bluetooth_ptr_).handle, "process");
+ }
+
+ // Set it to indicate whether the platform supports BLE. For example,
+ // Windows 7 is a platform that doesn't support Low Energy. On the other
+ // hand Windows 10 is a platform that does support LE, even if there is no
+ // Bluetooth radio present.
+ async setLESupported(supported) {
+ if (typeof supported !== 'boolean') throw 'Type Not Supported';
+ await this.fake_bluetooth_ptr_.setLESupported(supported);
+ }
+
+ // Returns a promise that resolves with a FakeCentral that clients can use
+ // to simulate events that a device in the Central/Observer role would
+ // receive as well as monitor the operations performed by the device in the
+ // Central/Observer role.
+ // Calls sets LE as supported.
+ //
+ // A "Central" object would allow its clients to receive advertising events
+ // and initiate connections to peripherals i.e. operations of two roles
+ // defined by the Bluetooth Spec: Observer and Central.
+ // See Bluetooth 4.2 Vol 3 Part C 2.2.2 "Roles when Operating over an
+ // LE Physical Transport".
+ async simulateCentral({state}) {
+ await this.setLESupported(true);
+
+ let {fakeCentral: fake_central_ptr} =
+ await this.fake_bluetooth_ptr_.simulateCentral(
+ toMojoCentralState(state));
+ return new FakeCentral(fake_central_ptr);
+ }
+
+ // Returns true if there are no pending responses.
+ async allResponsesConsumed() {
+ let {consumed} = await this.fake_bluetooth_ptr_.allResponsesConsumed();
+ return consumed;
+ }
+}
+
+// FakeCentral allows clients to simulate events that a device in the
+// Central/Observer role would receive as well as monitor the operations
+// performed by the device in the Central/Observer role.
+class FakeCentral {
+ constructor(fake_central_ptr) {
+ this.fake_central_ptr_ = fake_central_ptr;
+ this.peripherals_ = new Map();
+ }
+
+ // Simulates a peripheral with |address|, |name| and |known_service_uuids|
+ // that has already been connected to the system. If the peripheral existed
+ // already it updates its name and known UUIDs. |known_service_uuids| should
+ // be an array of BluetoothServiceUUIDs
+ // https://webbluetoothcg.github.io/web-bluetooth/#typedefdef-bluetoothserviceuuid
+ //
+ // Platforms offer methods to retrieve devices that have already been
+ // connected to the system or weren't connected through the UA e.g. a user
+ // connected a peripheral through the system's settings. This method is
+ // intended to simulate peripherals that those methods would return.
+ async simulatePreconnectedPeripheral({
+ address, name, knownServiceUUIDs = []}) {
+
+ // Canonicalize and convert to mojo UUIDs.
+ knownServiceUUIDs.forEach((val, i, arr) => {
+ knownServiceUUIDs[i] = {uuid: BluetoothUUID.getService(val)};
+ });
+
+ await this.fake_central_ptr_.simulatePreconnectedPeripheral(
+ address, name, knownServiceUUIDs);
+
+ let peripheral = this.peripherals_.get(address);
+ if (peripheral === undefined) {
+ peripheral = new FakePeripheral(address, this.fake_central_ptr_);
+ this.peripherals_.set(address, peripheral);
+ }
+
+ return peripheral;
+ }
+}
+
+class FakePeripheral {
+ constructor(address, fake_central_ptr) {
+ this.address = address;
+ this.fake_central_ptr_ = fake_central_ptr;
+ }
+
+ // Adds a fake GATT Service with |uuid| to be discovered when discovering
+ // the peripheral's GATT Attributes. Returns a FakeRemoteGATTService
+ // corresponding to this service. |uuid| should be a BluetoothServiceUUIDs
+ // https://webbluetoothcg.github.io/web-bluetooth/#typedefdef-bluetoothserviceuuid
+ async addFakeService({uuid}) {
+ let {serviceId: service_id} = await this.fake_central_ptr_.addFakeService(
+ this.address, {uuid: BluetoothUUID.getService(uuid)});
+
+ if (service_id === null) throw 'addFakeService failed';
+
+ return new FakeRemoteGATTService(
+ service_id, this.address, this.fake_central_ptr_);
+ }
+
+ // Sets the next GATT Connection request response to |code|. |code| could be
+ // an HCI Error Code from BT 4.2 Vol 2 Part D 1.3 List Of Error Codes or a
+ // number outside that range returned by specific platforms e.g. Android
+ // returns 0x101 to signal a GATT failure
+ // https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#GATT_FAILURE
+ async setNextGATTConnectionResponse({code}) {
+ let {success} =
+ await this.fake_central_ptr_.setNextGATTConnectionResponse(
+ this.address, code);
+
+ if (success !== true) throw 'setNextGATTConnectionResponse failed.';
+ }
+
+ // Sets the next GATT Discovery request response for peripheral with
+ // |address| to |code|. |code| could be an HCI Error Code from
+ // BT 4.2 Vol 2 Part D 1.3 List Of Error Codes or a number outside that
+ // range returned by specific platforms e.g. Android returns 0x101 to signal
+ // a GATT failure
+ // https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#GATT_FAILURE
+ //
+ // The following procedures defined at BT 4.2 Vol 3 Part G Section 4.
+ // "GATT Feature Requirements" are used to discover attributes of the
+ // GATT Server:
+ // - Primary Service Discovery
+ // - Relationship Discovery
+ // - Characteristic Discovery
+ // - Characteristic Descriptor Discovery
+ // This method aims to simulate the response once all of these procedures
+ // have completed or if there was an error during any of them.
+ async setNextGATTDiscoveryResponse({code}) {
+ let {success} =
+ await this.fake_central_ptr_.setNextGATTDiscoveryResponse(
+ this.address, code);
+
+ if (success !== true) throw 'setNextGATTDiscoveryResponse failed.';
+ }
+
+ // Simulates a GATT disconnection from the peripheral with |address|.
+ async simulateGATTDisconnection() {
+ let {success} =
+ await this.fake_central_ptr_.simulateGATTDisconnection(this.address);
+
+ if (success !== true) throw 'simulateGATTDisconnection failed.';
+ }
+
+ // Simulates an Indication from the peripheral's GATT `Service Changed`
+ // Characteristic from BT 4.2 Vol 3 Part G 7.1. This Indication is signaled
+ // when services, characteristics, or descriptors are changed, added, or
+ // removed.
+ //
+ // The value for `Service Changed` is a range of attribute handles that have
+ // changed. However, this testing specification works at an abstracted
+ // level and does not expose setting attribute handles when adding
+ // attributes. Consequently, this simulate method should include the full
+ // range of all the peripheral's attribute handle values.
+ async simulateGATTServicesChanged() {
+ let {success} =
+ await this.fake_central_ptr_.simulateGATTServicesChanged(this.address);
+
+ if (success !== true) throw 'simulateGATTServicesChanged failed.';
+ }
+}
+
+class FakeRemoteGATTService {
+ constructor(service_id, peripheral_address, fake_central_ptr) {
+ this.service_id_ = service_id;
+ this.peripheral_address_ = peripheral_address;
+ this.fake_central_ptr_ = fake_central_ptr;
+ }
+
+ // Adds a fake GATT Characteristic with |uuid| and |properties|
+ // to this fake service. The characteristic will be found when discovering
+ // the peripheral's GATT Attributes. Returns a FakeRemoteGATTCharacteristic
+ // corresponding to the added characteristic.
+ async addFakeCharacteristic({uuid, properties}) {
+ let {characteristicId: characteristic_id} =
+ await this.fake_central_ptr_.addFakeCharacteristic(
+ {uuid: BluetoothUUID.getCharacteristic(uuid)},
+ ArrayToMojoCharacteristicProperties(properties),
+ this.service_id_,
+ this.peripheral_address_);
+
+ if (characteristic_id === null) throw 'addFakeCharacteristic failed';
+
+ return new FakeRemoteGATTCharacteristic(
+ characteristic_id, this.service_id_,
+ this.peripheral_address_, this.fake_central_ptr_);
+ }
+}
+
+class FakeRemoteGATTCharacteristic {
+ constructor(characteristic_id, service_id, peripheral_address,
+ fake_central_ptr) {
+ this.ids_ = [characteristic_id, service_id, peripheral_address];
+ this.descriptors_ = [];
+ this.fake_central_ptr_ = fake_central_ptr;
+ }
+
+ // Adds a fake GATT Descriptor with |uuid| to be discovered when
+ // discovering the peripheral's GATT Attributes. Returns a
+ // FakeRemoteGATTDescriptor corresponding to this descriptor. |uuid| should
+ // be a BluetoothDescriptorUUID
+ // https://webbluetoothcg.github.io/web-bluetooth/#typedefdef-bluetoothdescriptoruuid
+ async addFakeDescriptor({uuid}) {
+ let {descriptorId: descriptor_id} =
+ await this.fake_central_ptr_.addFakeDescriptor(
+ {uuid: BluetoothUUID.getDescriptor(uuid)}, ...this.ids_);
+
+ if (descriptor_id === null) throw 'addFakeDescriptor failed';
+
+ let fake_descriptor = new FakeRemoteGATTDescriptor(
+ descriptor_id, ...this.ids_, this.fake_central_ptr_);
+ this.descriptors_.push(fake_descriptor);
+
+ return fake_descriptor;
+ }
+
+ // Sets the next read response for characteristic to |code| and |value|.
+ // |code| could be a GATT Error Response from
+ // BT 4.2 Vol 3 Part F 3.4.1.1 Error Response or a number outside that range
+ // returned by specific platforms e.g. Android returns 0x101 to signal a GATT
+ // failure.
+ // https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#GATT_FAILURE
+ async setNextReadResponse(gatt_code, value=null) {
+ if (gatt_code === 0 && value === null) {
+ throw '|value| can\'t be null if read should success.';
+ }
+ if (gatt_code !== 0 && value !== null) {
+ throw '|value| must be null if read should fail.';
+ }
+
+ let {success} =
+ await this.fake_central_ptr_.setNextReadCharacteristicResponse(
+ gatt_code, value, ...this.ids_);
+
+ if (!success) throw 'setNextReadCharacteristicResponse failed';
+ }
+
+ // Sets the next write response for this characteristic to |code|. If
+ // writing to a characteristic that only supports 'write_without_response'
+ // the set response will be ignored.
+ // |code| could be a GATT Error Response from
+ // BT 4.2 Vol 3 Part F 3.4.1.1 Error Response or a number outside that range
+ // returned by specific platforms e.g. Android returns 0x101 to signal a GATT
+ // failure.
+ async setNextWriteResponse(gatt_code) {
+ let {success} =
+ await this.fake_central_ptr_.setNextWriteCharacteristicResponse(
+ gatt_code, ...this.ids_);
+
+ if (!success) throw 'setNextWriteResponse failed';
+ }
+
+ // Sets the next subscribe to notifications response for characteristic with
+ // |characteristic_id| in |service_id| and in |peripheral_address| to
+ // |code|. |code| could be a GATT Error Response from BT 4.2 Vol 3 Part F
+ // 3.4.1.1 Error Response or a number outside that range returned by
+ // specific platforms e.g. Android returns 0x101 to signal a GATT failure.
+ async setNextSubscribeToNotificationsResponse(gatt_code) {
+ let {success} =
+ await this.fake_central_ptr_.setNextSubscribeToNotificationsResponse(
+ gatt_code, ...this.ids_);
+
+ if (!success) throw 'setNextSubscribeToNotificationsResponse failed';
+ }
+
+ // Gets the last successfully written value to the characteristic.
+ // Returns null if no value has yet been written to the characteristic.
+ async getLastWrittenValue() {
+ let {success, value} =
+ await this.fake_central_ptr_.getLastWrittenValue(...this.ids_);
+
+ if (!success) throw 'getLastWrittenValue failed';
+
+ return value;
+ }
+
+ // Removes the fake GATT Characteristic from its fake service.
+ async remove() {
+ let {success} =
+ await this.fake_central_ptr_.removeFakeCharacteristic(...this.ids_);
+
+ if (!success) throw 'remove failed';
+ }
+}
+
+class FakeRemoteGATTDescriptor {
+ constructor(descriptor_id,
+ characteristic_id,
+ service_id,
+ peripheral_address,
+ fake_central_ptr) {
+ this.ids_ = [
+ descriptor_id, characteristic_id, service_id, peripheral_address];
+ this.fake_central_ptr_ = fake_central_ptr;
+ }
+
+ // Sets the next read response for descriptor to |code| and |value|.
+ // |code| could be a GATT Error Response from
+ // BT 4.2 Vol 3 Part F 3.4.1.1 Error Response or a number outside that range
+ // returned by specific platforms e.g. Android returns 0x101 to signal a GATT
+ // failure.
+ // https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#GATT_FAILURE
+ async setNextReadResponse(gatt_code, value=null) {
+ if (gatt_code === 0 && value === null) {
+ throw '|value| cannot be null if read should succeed.';
+ }
+ if (gatt_code !== 0 && value !== null) {
+ throw '|value| must be null if read should fail.';
+ }
+
+ let {success} =
+ await this.fake_central_ptr_.setNextReadDescriptorResponse(
+ gatt_code, value, ...this.ids_);
+
+ if (!success) throw 'setNextReadDescriptorResponse failed';
+ }
+}
+
+navigator.bluetooth.test = new FakeBluetooth();
diff --git a/tests/wpt/web-platform-tests/resources/chromium/web-bluetooth-test.js.headers b/tests/wpt/web-platform-tests/resources/chromium/web-bluetooth-test.js.headers
new file mode 100644
index 00000000000..6805c323df5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/chromium/web-bluetooth-test.js.headers
@@ -0,0 +1 @@
+Content-Type: text/javascript; charset=utf-8
diff --git a/tests/wpt/web-platform-tests/resources/idlharness.js b/tests/wpt/web-platform-tests/resources/idlharness.js
index 587325c3aea..a8d4150dbc4 100644
--- a/tests/wpt/web-platform-tests/resources/idlharness.js
+++ b/tests/wpt/web-platform-tests/resources/idlharness.js
@@ -55,6 +55,7 @@ function constValue (cnt)
if (cnt.type === "null") return null;
if (cnt.type === "NaN") return NaN;
if (cnt.type === "Infinity") return cnt.negative ? -Infinity : Infinity;
+ if (cnt.type === "number") return +cnt.value;
return cnt.value;
}
@@ -164,6 +165,7 @@ self.IdlArray = function()
*/
this.partials = [];
this["implements"] = {};
+ this["includes"] = {};
};
//@}
@@ -257,6 +259,20 @@ IdlArray.prototype.internal_add_idls = function(parsed_idls, options)
return;
}
+ if (parsed_idl.type == "includes")
+ {
+ if (should_skip(parsed_idl.target))
+ {
+ return;
+ }
+ if (!(parsed_idl.target in this["includes"]))
+ {
+ this["includes"][parsed_idl.target] = [];
+ }
+ this["includes"][parsed_idl.target].push(parsed_idl["includes"]);
+ return;
+ }
+
parsed_idl.array = this;
if (parsed_idl.name in this.members)
{
@@ -270,7 +286,12 @@ IdlArray.prototype.internal_add_idls = function(parsed_idls, options)
{
case "interface":
this.members[parsed_idl.name] =
- new IdlInterface(parsed_idl, /* is_callback = */ false);
+ new IdlInterface(parsed_idl, /* is_callback = */ false, /* is_mixin = */ false);
+ break;
+
+ case "interface mixin":
+ this.members[parsed_idl.name] =
+ new IdlInterface(parsed_idl, /* is_callback = */ false, /* is_mixin = */ true);
break;
case "dictionary":
@@ -294,7 +315,7 @@ IdlArray.prototype.internal_add_idls = function(parsed_idls, options)
case "callback interface":
this.members[parsed_idl.name] =
- new IdlInterface(parsed_idl, /* is_callback = */ true);
+ new IdlInterface(parsed_idl, /* is_callback = */ true, /* is_mixin = */ false);
break;
default:
@@ -360,6 +381,36 @@ IdlArray.prototype.recursively_get_implements = function(interface_name)
};
//@}
+IdlArray.prototype.recursively_get_includes = function(interface_name)
+//@{
+{
+ /**
+ * Helper function for test(). Returns an array of things that implement
+ * interface_name, so if the IDL contains
+ *
+ * A includes B;
+ * B includes C;
+ * B includes D;
+ *
+ * then recursively_get_includes("A") should return ["B", "C", "D"].
+ */
+ var ret = this["includes"][interface_name];
+ if (ret === undefined)
+ {
+ return [];
+ }
+ for (var i = 0; i < this["includes"][interface_name].length; i++)
+ {
+ ret = ret.concat(this.recursively_get_includes(ret[i]));
+ if (ret.indexOf(ret[i]) != ret.lastIndexOf(ret[i]))
+ {
+ throw "Circular includes statements involving " + ret[i];
+ }
+ }
+ return ret;
+};
+
+//@}
IdlArray.prototype.is_json_type = function(type)
//@{
{
@@ -455,7 +506,7 @@ IdlArray.prototype.is_json_type = function(type)
while (thing)
{
if (thing.has_to_json_regular_operation()) { return true; }
- var mixins = this.implements[thing.name];
+ var mixins = this.implements[thing.name] || this.includes[thing.name];
if (mixins) {
mixins = mixins.map(function(id) {
var mixin = this.members[id];
@@ -565,6 +616,23 @@ IdlArray.prototype.test = function()
}
this["implements"] = {};
+ for (var lhs in this["includes"])
+ {
+ this.recursively_get_includes(lhs).forEach(function(rhs)
+ {
+ var errStr = lhs + " includes " + rhs + ", but ";
+ if (!(lhs in this.members)) throw errStr + lhs + " is undefined.";
+ if (!(this.members[lhs] instanceof IdlInterface)) throw errStr + lhs + " is not an interface.";
+ if (!(rhs in this.members)) throw errStr + rhs + " is undefined.";
+ if (!(this.members[rhs] instanceof IdlInterface)) throw errStr + rhs + " is not an interface.";
+ this.members[rhs].members.forEach(function(member)
+ {
+ this.members[lhs].members.push(new IdlInterfaceMember(member));
+ }.bind(this));
+ }.bind(this));
+ }
+ this["includes"] = {};
+
Object.getOwnPropertyNames(this.members).forEach(function(memberName) {
var member = this.members[memberName];
if (!(member instanceof IdlInterface)) {
@@ -874,7 +942,7 @@ IdlDictionary.prototype.get_inheritance_stack = function() {
};
/// IdlInterface ///
-function IdlInterface(obj, is_callback)
+function IdlInterface(obj, is_callback, is_mixin)
//@{
{
/**
@@ -912,6 +980,7 @@ function IdlInterface(obj, is_callback)
this.base = obj.inheritance;
this._is_callback = is_callback;
+ this._is_mixin = is_mixin;
}
//@}
IdlInterface.prototype = Object.create(IdlObject.prototype);
@@ -922,6 +991,13 @@ IdlInterface.prototype.is_callback = function()
};
//@}
+IdlInterface.prototype.is_mixin = function()
+//@{
+{
+ return this._is_mixin;
+};
+//@}
+
IdlInterface.prototype.has_constants = function()
//@{
{
@@ -935,8 +1011,7 @@ IdlInterface.prototype.is_global = function()
//@{
{
return this.extAttrs.some(function(attribute) {
- return attribute.name === "Global" ||
- attribute.name === "PrimaryGlobal";
+ return attribute.name === "Global";
});
};
//@}
@@ -1046,7 +1121,7 @@ IdlInterface.prototype.traverse_inherited_and_consequential_interfaces = functio
function _traverse_inherited_and_consequential_interfaces(stack, callback) {
var I = stack.pop();
callback(I);
- var mixins = I.array["implements"][I.name];
+ var mixins = I.array["implements"][I.name] || I.array["includes"][I.name];
if (mixins) {
mixins.forEach(function(id) {
var mixin = I.array.members[id];
@@ -1065,7 +1140,7 @@ function _traverse_inherited_and_consequential_interfaces(stack, callback) {
IdlInterface.prototype.test = function()
//@{
{
- if (this.has_extended_attribute("NoInterfaceObject"))
+ if (this.has_extended_attribute("NoInterfaceObject") || this.is_mixin())
{
// No tests to do without an instance. TODO: We should still be able
// to run tests on the prototype object, if we obtain one through some
@@ -1355,7 +1430,7 @@ IdlInterface.prototype.test_self = function()
// "The interface prototype object for a given interface A must have an
// internal [[Prototype]] property whose value is returned from the
// following steps:
- // "If A is declared with the [Global] or [PrimaryGlobal] extended
+ // "If A is declared with the [Global] extended
// attribute, and A supports named properties, then return the named
// properties object for A, as defined in §3.6.4 Named properties
// object.
@@ -1433,7 +1508,7 @@ IdlInterface.prototype.test_self = function()
}
}.bind(this), this.name + " interface: existence and properties of interface prototype object");
- // "If the interface is declared with the [Global] or [PrimaryGlobal]
+ // "If the interface is declared with the [Global]
// extended attribute, or the interface is in the set of inherited
// interfaces for any other interface that is declared with one of these
// attributes, then the interface prototype object must be an immutable
@@ -1779,7 +1854,7 @@ IdlInterface.prototype.test_member_operation = function(member)
"interface object missing static operation");
memberHolderObject = self[this.name];
// "* Otherwise, [...] if the interface was declared with the [Global]
- // or [PrimaryGlobal] extended attribute, then the property exists
+ // extended attribute, then the property exists
// on every object that implements the interface."
} else if (this.is_global()) {
assert_own_property(self, member.name,
@@ -2127,7 +2202,7 @@ IdlInterface.prototype.test_primary_interface_of = function(desc, obj, exception
}
// "The internal [[SetPrototypeOf]] method of every platform object that
- // implements an interface with the [Global] or [PrimaryGlobal] extended
+ // implements an interface with the [Global] extended
// attribute must execute the same algorithm as is defined for the
// [[SetPrototypeOf]] internal method of an immutable prototype exotic
// object."
diff --git a/tests/wpt/web-platform-tests/resources/readme.md b/tests/wpt/web-platform-tests/resources/readme.md
index 8583d5f8d5b..8cf95b4052a 100644
--- a/tests/wpt/web-platform-tests/resources/readme.md
+++ b/tests/wpt/web-platform-tests/resources/readme.md
@@ -1,22 +1,26 @@
-## Introduction ##
+# Resources
-testharness.js provides a framework for writing low-level tests of
+## `testharness.js`
+
+`testharness.js` is a framework for writing low-level tests of
browser functionality in javascript. It provides a convenient API for
making assertions and is intended to work for both simple synchronous
-tests and for tests of asynchronous behaviour.
+tests, and tests of asynchronous behaviour.
-## Getting Started ##
+### Getting started
-To use testharness.js you must include two scripts, in the order given:
+To use `testharness.js` you must include two scripts, in the order given:
``` html
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
```
-## Full documentation ##
+### Full documentation
+
+For detailed API documentation please visit [http://web-platform-tests.org/writing-tests/testharness-api.html](http://web-platform-tests.org/writing-tests/testharness-api.html).
-Full user documentation for the API is at [http://web-platform-tests.org/writing-tests/testharness-api.html](http://web-platform-tests.org/writing-tests/testharness-api.html).
+### Tutorials
-You can also read a tutorial on
+You can also read a tutorial on
[Using testharness.js](http://darobin.github.com/test-harness-tutorial/docs/using-testharness.html).
diff --git a/tests/wpt/web-platform-tests/resources/test/README.md b/tests/wpt/web-platform-tests/resources/test/README.md
index 1010516ad8e..773b83bfc05 100644
--- a/tests/wpt/web-platform-tests/resources/test/README.md
+++ b/tests/wpt/web-platform-tests/resources/test/README.md
@@ -6,7 +6,7 @@ The test suite for the `testharness.js` testing framework.
Install the following dependencies:
-- [Python 2.7](https://www.python.org/)
+- [Python 2.7.9+](https://www.python.org/)
- [the tox Python package](https://tox.readthedocs.io/en/latest/)
- [the Mozilla Firefox web browser](https://mozilla.org/firefox)
- [the GeckoDriver server](https://github.com/mozilla/geckodriver)
@@ -64,4 +64,4 @@ string within a `<script>` tag with an `id` of `"expected"`, e.g.:
</script>
This is useful to test, for example, whether asserations that should fail or
-throw actually do. \ No newline at end of file
+throw actually do.
diff --git a/tests/wpt/web-platform-tests/resources/test/tests/api-tests-1.html b/tests/wpt/web-platform-tests/resources/test/tests/api-tests-1.html
index 53d91c479a2..3c58b01f66f 100644
--- a/tests/wpt/web-platform-tests/resources/test/tests/api-tests-1.html
+++ b/tests/wpt/web-platform-tests/resources/test/tests/api-tests-1.html
@@ -1,462 +1,462 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-<title>Sample HTML5 API Tests</title>
-<meta name="timeout" content="6000">
-</head>
-<body onload="load_test_attr.done()">
-<h1>Sample HTML5 API Tests</h1>
-<div id="log"></div>
-<script src="../../testharness.js"></script>
-<script src="../../testharnessreport.js"></script>
-<script>
- setup_run = false;
- setup(function() {
- setup_run = true;
- });
- test(function() {assert_true(setup_run)}, "Setup function ran");
-
- // Two examples for testing events from handler and attributes
- var load_test_event = async_test("window onload event fires when set from the handler");
-
- function windowLoad()
- {
- load_test_event.done();
- }
- on_event(window, "load", windowLoad);
-
- // see the body onload below
- var load_test_attr = async_test("body element fires the onload event set from the attribute");
-</script>
-<script>
- function bodyElement()
- {
- assert_equals(document.body, document.getElementsByTagName("body")[0]);
- }
- test(bodyElement, "document.body should be the first body element in the document");
-
- test(function() {
- assert_equals(1,1);
- assert_equals(NaN, NaN, "NaN case");
- assert_equals(0, 0, "Zero case");
- }, "assert_equals tests")
-
- test(function() {
- assert_equals(-0, 0, "Zero case");
- }, "assert_equals tests expected to fail")
-
- test(function() {
- assert_not_equals({}, {}, "object case");
- assert_not_equals(-0, 0, "Zero case");
- }, "assert_not_equals tests")
-
- function testAssertPass()
- {
- assert_true(true);
- }
- test(testAssertPass, "assert_true expected to pass");
-
- function testAssertFalse()
- {
- assert_true(false, "false should not be true");
- }
- test(testAssertFalse, "assert_true expected to fail");
-
- function basicAssertArrayEquals()
- {
- assert_array_equals([1, NaN], [1, NaN], "[1, NaN] is equal to [1, NaN]");
- }
- test(basicAssertArrayEquals, "basic assert_array_equals test");
-
- function assertArrayEqualsUndefined()
- {
- assert_array_equals(undefined, [1], "undefined equals [1]?");
- }
- test(assertArrayEqualsUndefined, "assert_array_equals with first param undefined");
-
- function assertArrayEqualsTrue()
- {
- assert_array_equals(true, [1], "true equals [1]?");
- }
- test(assertArrayEqualsTrue, "assert_array_equals with first param true");
-
- function assertArrayEqualsFalse()
- {
- assert_array_equals(false, [1], "false equals [1]?");
- }
- test(assertArrayEqualsFalse, "assert_array_equals with first param false");
-
- function assertArrayEqualsNull()
- {
- assert_array_equals(null, [1], "null equals [1]?");
- }
- test(assertArrayEqualsNull, "assert_array_equals with first param null");
-
- function assertArrayEqualsNumeric()
- {
- assert_array_equals(1, [1], "1 equals [1]?");
- }
- test(assertArrayEqualsNumeric, "assert_array_equals with first param 1");
-
- function basicAssertObjectEquals()
- {
- assert_object_equals([1, 2, [1, 2]], { 0: 1, 1: 2, 2: { 0: 1, 1: 2} }, "array is equal to object")
- }
- test(basicAssertObjectEquals, "basic assert_object_equals test");
-
- function basicAssertArrayApproxEquals()
- {
- assert_array_approx_equals([10, 11], [11, 10], 1, "[10, 11] is approximately (+/- 1) [11, 10]")
- }
- test(basicAssertArrayApproxEquals, "basic assert_array_approx_equals test");
-
- function basicAssertApproxEquals()
- {
- assert_approx_equals(10, 11, 1, "10 is approximately (+/- 1) 11")
- }
- test(basicAssertApproxEquals, "basic assert_approx_equals test");
-
- function basicAssertLessThan()
- {
- assert_less_than(10, 11, "10 is less than 11")
- }
- test(basicAssertApproxEquals, "basic assert_less_than test");
-
- function basicAssertGreaterThan()
- {
- assert_greater_than(10, 11, "10 is not greater than 11");
- }
- test(basicAssertGreaterThan, "assert_greater_than expected to fail");
-
- function basicAssertGreaterThanEqual()
- {
- assert_greater_than_equal(10, 10, "10 is greater than or equal to 10")
- }
- test(basicAssertGreaterThanEqual, "basic assert_greater_than_equal test");
-
- function basicAssertLessThanEqual()
- {
- assert_greater_than_equal('10', 10, "'10' is not a number")
- }
- test(basicAssertLessThanEqual, "assert_less_than_equal expected to fail");
-
- function testAssertInherits() {
- var A = function(){this.a = "a"}
- A.prototype = {b:"b"}
- var a = new A();
- assert_exists(a, "a");
- assert_not_exists(a, "b");
- assert_inherits(a, "b");
- }
- test(testAssertInherits, "test for assert[_not]_exists and insert_inherits")
-
- test(function()
- {
- var a = document.createElement("a")
- var b = document.createElement("b")
- assert_throws("NOT_FOUND_ERR", function () {a.removeChild(b)});
- }, "Test throw DOM exception")
-
- test(function()
- {
- var a = document.createTextNode("a")
- var b = document.createElement("b")
- assert_throws("NOT_FOUND_ERR", function () {a.appendChild(b)});
- }, "Test throw DOM exception expected to fail")
-
- test(function()
- {
- var e = {code:0, name:"TEST_ERR", TEST_ERR:0}
- assert_throws("TEST_ERR", function() {throw e});
- }, "Test assert_throws with non-DOM-exception expected to Fail");
-
- var t = async_test("Test step_func")
- setTimeout(
- t.step_func(
- function () {
- assert_true(true); t.done();
- }), 0);
-
- async_test(function(t) {
- setTimeout(t.step_func(function (){assert_true(true); t.done();}), 0);
- }, "Test async test with callback");
-
- async_test(function() {
- setTimeout(this.step_func(function (){assert_true(true); this.done();}), 0);
- }, "Test async test with callback and `this` obj.");
-
- async_test("test should timeout (fail) with the default of 2 seconds").step(function(){});
-
- async_test("test should timeout (fail) with a custom set timeout value of 1 second",
- {timeout:1000}).step(function(){});
-
- async_test("async test that is never started, should have status Not Run", {timeout:1000});
-
-
- test(function(t) {
- window.global = 1;
- t.add_cleanup(function() {delete window.global});
- assert_equals(window.global, 1);
- },
- "Test that defines a global and cleans it up");
-
- test(function() {assert_equals(window.global, undefined)},
- "Test that cleanup handlers from previous test ran");
-
-</script>
-<script type="text/json" id="expected">
-{
- "summarized_status": {
- "status_string": "TIMEOUT",
- "message": null,
- "stack": null
- },
- "summarized_tests": [
- {
- "status_string": "PASS",
- "name": "Setup function ran",
- "stack": null,
- "message": null,
- "properties": {}
- },
- {
- "status_string": "FAIL",
- "name": "Test assert_throws with non-DOM-exception expected to Fail",
- "stack": "(implementation-defined)",
- "message": "Test bug: unrecognized DOMException code \"TEST_ERR\" passed to assert_throws()",
- "properties": {}
- },
- {
- "status_string": "PASS",
- "name": "Test async test with callback",
- "stack": null,
- "message": null,
- "properties": {}
- },
- {
- "status_string": "PASS",
- "name": "Test async test with callback and `this` obj.",
- "stack": null,
- "message": null,
- "properties": {}
- },
- {
- "status_string": "PASS",
- "name": "Test step_func",
- "stack": null,
- "message": null,
- "properties": {}
- },
- {
- "status_string": "PASS",
- "name": "Test that cleanup handlers from previous test ran",
- "stack": null,
- "message": null,
- "properties": {}
- },
- {
- "status_string": "PASS",
- "name": "Test that defines a global and cleans it up",
- "stack": null,
- "message": null,
- "properties": {}
- },
- {
- "status_string": "PASS",
- "name": "Test throw DOM exception",
- "stack": null,
- "message": null,
- "properties": {}
- },
- {
- "status_string": "FAIL",
- "name": "Test throw DOM exception expected to fail",
- "stack": "(implementation-defined)",
- "message": "assert_throws: function \"function () {a.appendChild(b)}\" threw object \"HierarchyRequestError: Node cannot be inserted at the specified point in the hierarchy\" that is not a DOMException NOT_FOUND_ERR: property \"code\" is equal to 3, expected 8",
- "properties": {}
- },
- {
- "status_string": "FAIL",
- "name": "assert_array_equals with first param 1",
- "stack": "(implementation-defined)",
- "message": "assert_array_equals: 1 equals [1]? value is 1, expected array",
- "properties": {}
- },
- {
- "status_string": "FAIL",
- "name": "assert_array_equals with first param false",
- "stack": "(implementation-defined)",
- "message": "assert_array_equals: false equals [1]? value is false, expected array",
- "properties": {}
- },
- {
- "status_string": "FAIL",
- "name": "assert_array_equals with first param null",
- "stack": "(implementation-defined)",
- "message": "assert_array_equals: null equals [1]? value is null, expected array",
- "properties": {}
- },
- {
- "status_string": "FAIL",
- "name": "assert_array_equals with first param true",
- "stack": "(implementation-defined)",
- "message": "assert_array_equals: true equals [1]? value is true, expected array",
- "properties": {}
- },
- {
- "status_string": "FAIL",
- "name": "assert_array_equals with first param undefined",
- "stack": "(implementation-defined)",
- "message": "assert_array_equals: undefined equals [1]? value is undefined, expected array",
- "properties": {}
- },
- {
- "status_string": "PASS",
- "name": "assert_equals tests",
- "stack": null,
- "message": null,
- "properties": {}
- },
- {
- "status_string": "FAIL",
- "name": "assert_equals tests expected to fail",
- "stack": "(implementation-defined)",
- "message": "assert_equals: Zero case expected 0 but got -0",
- "properties": {}
- },
- {
- "status_string": "FAIL",
- "name": "assert_greater_than expected to fail",
- "stack": "(implementation-defined)",
- "message": "assert_greater_than: 10 is not greater than 11 expected a number greater than 11 but got 10",
- "properties": {}
- },
- {
- "status_string": "FAIL",
- "name": "assert_less_than_equal expected to fail",
- "stack": "(implementation-defined)",
- "message": "assert_greater_than_equal: '10' is not a number expected a number but got a \"string\"",
- "properties": {}
- },
- {
- "status_string": "PASS",
- "name": "assert_not_equals tests",
- "stack": null,
- "message": null,
- "properties": {}
- },
- {
- "status_string": "FAIL",
- "name": "assert_true expected to fail",
- "stack": "(implementation-defined)",
- "message": "assert_true: false should not be true expected true got false",
- "properties": {}
- },
- {
- "status_string": "PASS",
- "name": "assert_true expected to pass",
- "stack": null,
- "message": null,
- "properties": {}
- },
- {
- "status_string": "NOTRUN",
- "name": "async test that is never started, should have status Not Run",
- "stack": null,
- "message": null,
- "properties": {
- "timeout": 1000
- }
- },
- {
- "status_string": "PASS",
- "name": "basic assert_approx_equals test",
- "stack": null,
- "message": null,
- "properties": {}
- },
- {
- "status_string": "PASS",
- "name": "basic assert_array_approx_equals test",
- "stack": null,
- "message": null,
- "properties": {}
- },
- {
- "status_string": "PASS",
- "name": "basic assert_array_equals test",
- "stack": null,
- "message": null,
- "properties": {}
- },
- {
- "status_string": "PASS",
- "name": "basic assert_greater_than_equal test",
- "stack": null,
- "message": null,
- "properties": {}
- },
- {
- "status_string": "PASS",
- "name": "basic assert_less_than test",
- "stack": null,
- "message": null,
- "properties": {}
- },
- {
- "status_string": "PASS",
- "name": "basic assert_object_equals test",
- "stack": null,
- "message": null,
- "properties": {}
- },
- {
- "status_string": "PASS",
- "name": "body element fires the onload event set from the attribute",
- "stack": null,
- "message": null,
- "properties": {}
- },
- {
- "status_string": "PASS",
- "name": "document.body should be the first body element in the document",
- "stack": null,
- "message": null,
- "properties": {}
- },
- {
- "status_string": "PASS",
- "name": "test for assert[_not]_exists and insert_inherits",
- "stack": null,
- "message": null,
- "properties": {}
- },
- {
- "status_string": "TIMEOUT",
- "name": "test should timeout (fail) with a custom set timeout value of 1 second",
- "stack": null,
- "message": "Test timed out",
- "properties": {
- "timeout": 1000
- }
- },
- {
- "status_string": "TIMEOUT",
- "name": "test should timeout (fail) with the default of 2 seconds",
- "stack": null,
- "message": "Test timed out",
- "properties": {}
- },
- {
- "status_string": "PASS",
- "name": "window onload event fires when set from the handler",
- "stack": null,
- "message": null,
- "properties": {}
- }
- ],
- "type": "complete"
-}
-</script>
-</body>
-</html>
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Sample HTML5 API Tests</title>
+<meta name="timeout" content="6000">
+</head>
+<body onload="load_test_attr.done()">
+<h1>Sample HTML5 API Tests</h1>
+<div id="log"></div>
+<script src="../../testharness.js"></script>
+<script src="../../testharnessreport.js"></script>
+<script>
+ setup_run = false;
+ setup(function() {
+ setup_run = true;
+ });
+ test(function() {assert_true(setup_run)}, "Setup function ran");
+
+ // Two examples for testing events from handler and attributes
+ var load_test_event = async_test("window onload event fires when set from the handler");
+
+ function windowLoad()
+ {
+ load_test_event.done();
+ }
+ on_event(window, "load", windowLoad);
+
+ // see the body onload below
+ var load_test_attr = async_test("body element fires the onload event set from the attribute");
+</script>
+<script>
+ function bodyElement()
+ {
+ assert_equals(document.body, document.getElementsByTagName("body")[0]);
+ }
+ test(bodyElement, "document.body should be the first body element in the document");
+
+ test(function() {
+ assert_equals(1,1);
+ assert_equals(NaN, NaN, "NaN case");
+ assert_equals(0, 0, "Zero case");
+ }, "assert_equals tests")
+
+ test(function() {
+ assert_equals(-0, 0, "Zero case");
+ }, "assert_equals tests expected to fail")
+
+ test(function() {
+ assert_not_equals({}, {}, "object case");
+ assert_not_equals(-0, 0, "Zero case");
+ }, "assert_not_equals tests")
+
+ function testAssertPass()
+ {
+ assert_true(true);
+ }
+ test(testAssertPass, "assert_true expected to pass");
+
+ function testAssertFalse()
+ {
+ assert_true(false, "false should not be true");
+ }
+ test(testAssertFalse, "assert_true expected to fail");
+
+ function basicAssertArrayEquals()
+ {
+ assert_array_equals([1, NaN], [1, NaN], "[1, NaN] is equal to [1, NaN]");
+ }
+ test(basicAssertArrayEquals, "basic assert_array_equals test");
+
+ function assertArrayEqualsUndefined()
+ {
+ assert_array_equals(undefined, [1], "undefined equals [1]?");
+ }
+ test(assertArrayEqualsUndefined, "assert_array_equals with first param undefined");
+
+ function assertArrayEqualsTrue()
+ {
+ assert_array_equals(true, [1], "true equals [1]?");
+ }
+ test(assertArrayEqualsTrue, "assert_array_equals with first param true");
+
+ function assertArrayEqualsFalse()
+ {
+ assert_array_equals(false, [1], "false equals [1]?");
+ }
+ test(assertArrayEqualsFalse, "assert_array_equals with first param false");
+
+ function assertArrayEqualsNull()
+ {
+ assert_array_equals(null, [1], "null equals [1]?");
+ }
+ test(assertArrayEqualsNull, "assert_array_equals with first param null");
+
+ function assertArrayEqualsNumeric()
+ {
+ assert_array_equals(1, [1], "1 equals [1]?");
+ }
+ test(assertArrayEqualsNumeric, "assert_array_equals with first param 1");
+
+ function basicAssertObjectEquals()
+ {
+ assert_object_equals([1, 2, [1, 2]], { 0: 1, 1: 2, 2: { 0: 1, 1: 2} }, "array is equal to object")
+ }
+ test(basicAssertObjectEquals, "basic assert_object_equals test");
+
+ function basicAssertArrayApproxEquals()
+ {
+ assert_array_approx_equals([10, 11], [11, 10], 1, "[10, 11] is approximately (+/- 1) [11, 10]")
+ }
+ test(basicAssertArrayApproxEquals, "basic assert_array_approx_equals test");
+
+ function basicAssertApproxEquals()
+ {
+ assert_approx_equals(10, 11, 1, "10 is approximately (+/- 1) 11")
+ }
+ test(basicAssertApproxEquals, "basic assert_approx_equals test");
+
+ function basicAssertLessThan()
+ {
+ assert_less_than(10, 11, "10 is less than 11")
+ }
+ test(basicAssertApproxEquals, "basic assert_less_than test");
+
+ function basicAssertGreaterThan()
+ {
+ assert_greater_than(10, 11, "10 is not greater than 11");
+ }
+ test(basicAssertGreaterThan, "assert_greater_than expected to fail");
+
+ function basicAssertGreaterThanEqual()
+ {
+ assert_greater_than_equal(10, 10, "10 is greater than or equal to 10")
+ }
+ test(basicAssertGreaterThanEqual, "basic assert_greater_than_equal test");
+
+ function basicAssertLessThanEqual()
+ {
+ assert_greater_than_equal('10', 10, "'10' is not a number")
+ }
+ test(basicAssertLessThanEqual, "assert_less_than_equal expected to fail");
+
+ function testAssertInherits() {
+ var A = function(){this.a = "a"}
+ A.prototype = {b:"b"}
+ var a = new A();
+ assert_exists(a, "a");
+ assert_not_exists(a, "b");
+ assert_inherits(a, "b");
+ }
+ test(testAssertInherits, "test for assert[_not]_exists and insert_inherits")
+
+ test(function()
+ {
+ var a = document.createElement("a")
+ var b = document.createElement("b")
+ assert_throws("NOT_FOUND_ERR", function () {a.removeChild(b)});
+ }, "Test throw DOM exception")
+
+ test(function()
+ {
+ var a = document.createTextNode("a")
+ var b = document.createElement("b")
+ assert_throws("NOT_FOUND_ERR", function () {a.appendChild(b)});
+ }, "Test throw DOM exception expected to fail")
+
+ test(function()
+ {
+ var e = {code:0, name:"TEST_ERR", TEST_ERR:0}
+ assert_throws("TEST_ERR", function() {throw e});
+ }, "Test assert_throws with non-DOM-exception expected to Fail");
+
+ var t = async_test("Test step_func")
+ setTimeout(
+ t.step_func(
+ function () {
+ assert_true(true); t.done();
+ }), 0);
+
+ async_test(function(t) {
+ setTimeout(t.step_func(function (){assert_true(true); t.done();}), 0);
+ }, "Test async test with callback");
+
+ async_test(function() {
+ setTimeout(this.step_func(function (){assert_true(true); this.done();}), 0);
+ }, "Test async test with callback and `this` obj.");
+
+ async_test("test should timeout (fail) with the default of 2 seconds").step(function(){});
+
+ async_test("test should timeout (fail) with a custom set timeout value of 1 second",
+ {timeout:1000}).step(function(){});
+
+ async_test("async test that is never started, should have status Not Run", {timeout:1000});
+
+
+ test(function(t) {
+ window.global = 1;
+ t.add_cleanup(function() {delete window.global});
+ assert_equals(window.global, 1);
+ },
+ "Test that defines a global and cleans it up");
+
+ test(function() {assert_equals(window.global, undefined)},
+ "Test that cleanup handlers from previous test ran");
+
+</script>
+<script type="text/json" id="expected">
+{
+ "summarized_status": {
+ "status_string": "TIMEOUT",
+ "message": null,
+ "stack": null
+ },
+ "summarized_tests": [
+ {
+ "status_string": "PASS",
+ "name": "Setup function ran",
+ "stack": null,
+ "message": null,
+ "properties": {}
+ },
+ {
+ "status_string": "FAIL",
+ "name": "Test assert_throws with non-DOM-exception expected to Fail",
+ "stack": "(implementation-defined)",
+ "message": "Test bug: unrecognized DOMException code \"TEST_ERR\" passed to assert_throws()",
+ "properties": {}
+ },
+ {
+ "status_string": "PASS",
+ "name": "Test async test with callback",
+ "stack": null,
+ "message": null,
+ "properties": {}
+ },
+ {
+ "status_string": "PASS",
+ "name": "Test async test with callback and `this` obj.",
+ "stack": null,
+ "message": null,
+ "properties": {}
+ },
+ {
+ "status_string": "PASS",
+ "name": "Test step_func",
+ "stack": null,
+ "message": null,
+ "properties": {}
+ },
+ {
+ "status_string": "PASS",
+ "name": "Test that cleanup handlers from previous test ran",
+ "stack": null,
+ "message": null,
+ "properties": {}
+ },
+ {
+ "status_string": "PASS",
+ "name": "Test that defines a global and cleans it up",
+ "stack": null,
+ "message": null,
+ "properties": {}
+ },
+ {
+ "status_string": "PASS",
+ "name": "Test throw DOM exception",
+ "stack": null,
+ "message": null,
+ "properties": {}
+ },
+ {
+ "status_string": "FAIL",
+ "name": "Test throw DOM exception expected to fail",
+ "stack": "(implementation-defined)",
+ "message": "assert_throws: function \"function () {a.appendChild(b)}\" threw object \"HierarchyRequestError: Node cannot be inserted at the specified point in the hierarchy\" that is not a DOMException NOT_FOUND_ERR: property \"code\" is equal to 3, expected 8",
+ "properties": {}
+ },
+ {
+ "status_string": "FAIL",
+ "name": "assert_array_equals with first param 1",
+ "stack": "(implementation-defined)",
+ "message": "assert_array_equals: 1 equals [1]? value is 1, expected array",
+ "properties": {}
+ },
+ {
+ "status_string": "FAIL",
+ "name": "assert_array_equals with first param false",
+ "stack": "(implementation-defined)",
+ "message": "assert_array_equals: false equals [1]? value is false, expected array",
+ "properties": {}
+ },
+ {
+ "status_string": "FAIL",
+ "name": "assert_array_equals with first param null",
+ "stack": "(implementation-defined)",
+ "message": "assert_array_equals: null equals [1]? value is null, expected array",
+ "properties": {}
+ },
+ {
+ "status_string": "FAIL",
+ "name": "assert_array_equals with first param true",
+ "stack": "(implementation-defined)",
+ "message": "assert_array_equals: true equals [1]? value is true, expected array",
+ "properties": {}
+ },
+ {
+ "status_string": "FAIL",
+ "name": "assert_array_equals with first param undefined",
+ "stack": "(implementation-defined)",
+ "message": "assert_array_equals: undefined equals [1]? value is undefined, expected array",
+ "properties": {}
+ },
+ {
+ "status_string": "PASS",
+ "name": "assert_equals tests",
+ "stack": null,
+ "message": null,
+ "properties": {}
+ },
+ {
+ "status_string": "FAIL",
+ "name": "assert_equals tests expected to fail",
+ "stack": "(implementation-defined)",
+ "message": "assert_equals: Zero case expected 0 but got -0",
+ "properties": {}
+ },
+ {
+ "status_string": "FAIL",
+ "name": "assert_greater_than expected to fail",
+ "stack": "(implementation-defined)",
+ "message": "assert_greater_than: 10 is not greater than 11 expected a number greater than 11 but got 10",
+ "properties": {}
+ },
+ {
+ "status_string": "FAIL",
+ "name": "assert_less_than_equal expected to fail",
+ "stack": "(implementation-defined)",
+ "message": "assert_greater_than_equal: '10' is not a number expected a number but got a \"string\"",
+ "properties": {}
+ },
+ {
+ "status_string": "PASS",
+ "name": "assert_not_equals tests",
+ "stack": null,
+ "message": null,
+ "properties": {}
+ },
+ {
+ "status_string": "FAIL",
+ "name": "assert_true expected to fail",
+ "stack": "(implementation-defined)",
+ "message": "assert_true: false should not be true expected true got false",
+ "properties": {}
+ },
+ {
+ "status_string": "PASS",
+ "name": "assert_true expected to pass",
+ "stack": null,
+ "message": null,
+ "properties": {}
+ },
+ {
+ "status_string": "NOTRUN",
+ "name": "async test that is never started, should have status Not Run",
+ "stack": null,
+ "message": null,
+ "properties": {
+ "timeout": 1000
+ }
+ },
+ {
+ "status_string": "PASS",
+ "name": "basic assert_approx_equals test",
+ "stack": null,
+ "message": null,
+ "properties": {}
+ },
+ {
+ "status_string": "PASS",
+ "name": "basic assert_array_approx_equals test",
+ "stack": null,
+ "message": null,
+ "properties": {}
+ },
+ {
+ "status_string": "PASS",
+ "name": "basic assert_array_equals test",
+ "stack": null,
+ "message": null,
+ "properties": {}
+ },
+ {
+ "status_string": "PASS",
+ "name": "basic assert_greater_than_equal test",
+ "stack": null,
+ "message": null,
+ "properties": {}
+ },
+ {
+ "status_string": "PASS",
+ "name": "basic assert_less_than test",
+ "stack": null,
+ "message": null,
+ "properties": {}
+ },
+ {
+ "status_string": "PASS",
+ "name": "basic assert_object_equals test",
+ "stack": null,
+ "message": null,
+ "properties": {}
+ },
+ {
+ "status_string": "PASS",
+ "name": "body element fires the onload event set from the attribute",
+ "stack": null,
+ "message": null,
+ "properties": {}
+ },
+ {
+ "status_string": "PASS",
+ "name": "document.body should be the first body element in the document",
+ "stack": null,
+ "message": null,
+ "properties": {}
+ },
+ {
+ "status_string": "PASS",
+ "name": "test for assert[_not]_exists and insert_inherits",
+ "stack": null,
+ "message": null,
+ "properties": {}
+ },
+ {
+ "status_string": "TIMEOUT",
+ "name": "test should timeout (fail) with a custom set timeout value of 1 second",
+ "stack": null,
+ "message": "Test timed out",
+ "properties": {
+ "timeout": 1000
+ }
+ },
+ {
+ "status_string": "TIMEOUT",
+ "name": "test should timeout (fail) with the default of 2 seconds",
+ "stack": null,
+ "message": "Test timed out",
+ "properties": {}
+ },
+ {
+ "status_string": "PASS",
+ "name": "window onload event fires when set from the handler",
+ "stack": null,
+ "message": null,
+ "properties": {}
+ }
+ ],
+ "type": "complete"
+}
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/resources/test/tests/api-tests-2.html b/tests/wpt/web-platform-tests/resources/test/tests/api-tests-2.html
index 99fa5be9c85..dd08d1a6e9a 100644
--- a/tests/wpt/web-platform-tests/resources/test/tests/api-tests-2.html
+++ b/tests/wpt/web-platform-tests/resources/test/tests/api-tests-2.html
@@ -3,7 +3,7 @@
<head>
<title>Sample HTML5 API Tests</title>
</head>
-<body onload="load_test_attr.done()">
+<body>
<h1>Sample HTML5 API Tests</h1>
<p>There should be two results</p>
<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/resources/test/tests/api-tests-3.html b/tests/wpt/web-platform-tests/resources/test/tests/api-tests-3.html
index fb571c8ee85..9e87e497b49 100644
--- a/tests/wpt/web-platform-tests/resources/test/tests/api-tests-3.html
+++ b/tests/wpt/web-platform-tests/resources/test/tests/api-tests-3.html
@@ -5,7 +5,7 @@
</head>
<script src="../../testharness.js"></script>
-<body onload="load_test_attr.done()">
+<body>
<h1>Sample HTML5 API Tests</h1>
<div id="log"></div>
<script>
diff --git a/tests/wpt/web-platform-tests/resources/test/tests/force_timeout.html b/tests/wpt/web-platform-tests/resources/test/tests/force_timeout.html
new file mode 100644
index 00000000000..bef53b406e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/test/tests/force_timeout.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Test#force_timeout</title>
+</head>
+<body>
+<h1>Test#force_timeout</h1>
+<div id="log"></div>
+<script src="../../testharness.js"></script>
+<script src="../../testharnessreport.js"></script>
+<script>
+setup({ explicit_timeout: true });
+
+test(function(t) {
+ t.force_timeout();
+ }, 'test (synchronous)');
+
+async_test(function(t) {
+ t.step_timeout(function() {
+ t.force_timeout();
+ }, 0);
+ }, 'async_test');
+
+promise_test(function(t) {
+ t.force_timeout();
+
+ return new Promise(function() {});
+ }, 'promise_test');
+</script>
+<script type="text/json" id="expected">
+{
+ "summarized_status": {
+ "status_string": "OK",
+ "message": null,
+ "stack": null
+ },
+ "summarized_tests": [
+ {
+ "status_string": "TIMEOUT",
+ "name": "async_test",
+ "message": "Test timed out",
+ "stack": null,
+ "properties": {}
+ },
+ {
+ "status_string": "TIMEOUT",
+ "name": "promise_test",
+ "message": "Test timed out",
+ "stack": null,
+ "properties": {}
+ },
+ {
+ "status_string": "TIMEOUT",
+ "name": "test (synchronous)",
+ "message": "Test timed out",
+ "stack": null,
+ "properties": {}
+ }
+ ],
+ "type": "complete"
+}
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/resources/test/tests/generate-callback.html b/tests/wpt/web-platform-tests/resources/test/tests/generate-callback.html
index a72ad62a59f..fe469893c44 100644
--- a/tests/wpt/web-platform-tests/resources/test/tests/generate-callback.html
+++ b/tests/wpt/web-platform-tests/resources/test/tests/generate-callback.html
@@ -10,34 +10,34 @@
// generate_tests takes an array of arrays that define tests
// but lets pass it an empty array and verify it does nothing.
function null_callback() {
- throw "null_callback should not be called.";
+ throw "null_callback should not be called.";
}
generate_tests(null_callback, []);
// Generate 3 tests specifying the name and one parameter
function validate_arguments(arg1) {
- assert_equals(arg1, 1, "Ensure that we get our expected argument");
+ assert_equals(arg1, 1, "Ensure that we get our expected argument");
}
generate_tests(validate_arguments, [
- ["first test", 1],
- ["second test", 1],
- ["third test", 1],
+ ["first test", 1],
+ ["second test", 1],
+ ["third test", 1],
]);
// Generate a test passing in a properties object that is shared across tests.
function validate_properties() {
- assert_true(this.properties.sentinel, "Ensure that we got the right properties object.");
+ assert_true(this.properties.sentinel, "Ensure that we got the right properties object.");
}
generate_tests(validate_properties, [["sentinel check 1"], ["sentinel check 2"]], {sentinel: true});
// Generate a test passing in a properties object that is shared across tests.
function validate_separate_properties() {
- if (this.name === "sentinel check 1 unique properties") {
- assert_true(this.properties.sentinel, "Ensure that we got the right properties object. Expect sentinel: true.");
- }
- else {
- assert_false(this.properties.sentinel, "Ensure that we got the right properties object. Expect sentinel: false.");
- }
+ if (this.name === "sentinel check 1 unique properties") {
+ assert_true(this.properties.sentinel, "Ensure that we got the right properties object. Expect sentinel: true.");
+ }
+ else {
+ assert_false(this.properties.sentinel, "Ensure that we got the right properties object. Expect sentinel: false.");
+ }
}
generate_tests(validate_separate_properties, [["sentinel check 1 unique properties"], ["sentinel check 2 unique properties"]], [{sentinel: true}, {sentinel: false}]);
@@ -45,10 +45,10 @@ generate_tests(validate_separate_properties, [["sentinel check 1 unique properti
var letters = ["a", "b", "c", "d", "e", "f"];
var numbers = [0, 1, 2, 3, 4, 5];
function validate_related_arguments(arg1, arg2) {
- assert_equals(arg1.charCodeAt(0) - "a".charCodeAt(0), arg2, "Ensure that we can map letters to numbers.");
+ assert_equals(arg1.charCodeAt(0) - "a".charCodeAt(0), arg2, "Ensure that we can map letters to numbers.");
}
function format_as_test(letter, index, letters) {
- return ["Test to map " + letter + " to " + numbers[index], letter, numbers[index]];
+ return ["Test to map " + letter + " to " + numbers[index], letter, numbers[index]];
}
generate_tests(validate_related_arguments, letters.map(format_as_test));
</script>
diff --git a/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlArray/is_json_type.html b/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlArray/is_json_type.html
index 42f9dd52c29..f7ebc9dd059 100644
--- a/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlArray/is_json_type.html
+++ b/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlArray/is_json_type.html
@@ -73,7 +73,7 @@
assert_false(idl.is_json_type(typeFrom("sequence<DOMException>")));
assert_true(idl.is_json_type(typeFrom("sequence<DOMString>")));
}, 'should handle sequences according to their inner types');
-
+
test(function() {
var idl = new IdlArray();
assert_false(idl.is_json_type(typeFrom("FrozenArray<DOMException>")));
@@ -192,4 +192,3 @@
</script>
</body>
</html>
-
diff --git a/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlDictionary/get_inheritance_stack.html b/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlDictionary/get_inheritance_stack.html
index 83863fb8d76..3540afb3346 100644
--- a/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlDictionary/get_inheritance_stack.html
+++ b/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlDictionary/get_inheritance_stack.html
@@ -16,12 +16,12 @@
var stack = dictionaryFrom('dictionary A { };').get_inheritance_stack();
assert_array_equals(stack.map(d => d.name), ["A"]);
}, 'should return an array that includes itself.');
-
+
test(function() {
var d = dictionaryFrom('dictionary A : B { };');
assert_throws(new Error(), _ => d.get_inheritance_stack());
}, "should throw for dictionaries which inherit from another dictionary which wasn't added to the IdlArray");
-
+
test(function() {
var idl = new IdlArray();
idl.add_idls('dictionary A : B { };');
@@ -32,4 +32,3 @@
</script>
</body>
</html>
-
diff --git a/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlInterface/get_inheritance_stack.html b/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlInterface/get_inheritance_stack.html
index c1d61415676..57884fba2a3 100644
--- a/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlInterface/get_inheritance_stack.html
+++ b/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlInterface/get_inheritance_stack.html
@@ -16,12 +16,12 @@
var stack = interfaceFrom('interface A { };').get_inheritance_stack();
assert_array_equals(stack.map(i => i.name), ["A"]);
}, 'should return an array that includes itself.');
-
+
test(function() {
var i = interfaceFrom('interface A : B { };');
assert_throws(new Error(), _ => i.get_inheritance_stack());
}, "should throw for interfaces which inherit from another interface which wasn't added to the IdlArray");
-
+
test(function() {
var idl = new IdlArray();
idl.add_idls('interface A : B { };');
@@ -32,4 +32,3 @@
</script>
</body>
</html>
-
diff --git a/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlInterface/has_to_json_regular_operation.html b/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlInterface/has_to_json_regular_operation.html
index a4b4e91b538..bf7d9261a71 100644
--- a/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlInterface/has_to_json_regular_operation.html
+++ b/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlInterface/has_to_json_regular_operation.html
@@ -16,12 +16,12 @@
var i = interfaceFrom('interface A { };');
assert_false(i.has_to_json_regular_operation());
}, 'should return false when the interface declares no toJSON operation.');
-
+
test(function() {
var i = interfaceFrom('interface A { static object toJSON(); };');
assert_false(i.has_to_json_regular_operation());
}, 'should return false when the interface declares a static toJSON operation.');
-
+
test(function() {
var i = interfaceFrom('interface A { object toJSON(); };');
assert_true(i.has_to_json_regular_operation());
@@ -29,4 +29,3 @@
</script>
</body>
</html>
-
diff --git a/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlInterface/test_immutable_prototype.html b/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlInterface/test_immutable_prototype.html
index 16214c4d24f..b3b289bb725 100644
--- a/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlInterface/test_immutable_prototype.html
+++ b/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlInterface/test_immutable_prototype.html
@@ -31,7 +31,7 @@ idlArray.add_idls(
"interface Window : EventTarget {};\n" +
"[Global=Window, Exposed=Window, Constructor()]\n" +
- "interface Foo {};"
+ "interface Foo {};"
);
idlArray.add_objects({
Foo: ["new Foo()"],
diff --git a/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlInterface/test_to_json_operation.html b/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlInterface/test_to_json_operation.html
index 18fc3193ff8..c758d5bd327 100644
--- a/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlInterface/test_to_json_operation.html
+++ b/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlInterface/test_to_json_operation.html
@@ -176,7 +176,7 @@
"status_string": "FAIL"
},
{
- "message": "assert_true: {\"sequence\":false,\"generic\":null,\"nullable\":false,\"array\":false,\"union\":false,\"idlType\":\"DOMException\"} is not an appropriate return value for the toJSON operation of N expected true got false",
+ "message": "assert_true: {\"sequence\":false,\"generic\":null,\"nullable\":false,\"union\":false,\"idlType\":\"DOMException\"} is not an appropriate return value for the toJSON operation of N expected true got false",
"name": "Test toJSON operation of N",
"properties": {},
"stack": "(implementation-defined)",
@@ -187,4 +187,4 @@
}
</script>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlInterface/traverse_inherited_and_consequential_interfaces.html b/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlInterface/traverse_inherited_and_consequential_interfaces.html
index 1a192919af8..667c7911b73 100644
--- a/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlInterface/traverse_inherited_and_consequential_interfaces.html
+++ b/tests/wpt/web-platform-tests/resources/test/tests/idlharness/IdlInterface/traverse_inherited_and_consequential_interfaces.html
@@ -37,7 +37,7 @@
});
assert_array_equals(interfaces, ["A"]);
}, 'should return an array that includes itself.');
-
+
test(function() {
var context = new IdlArray();
context.add_idls("interface A { }; A implements B;");
@@ -49,7 +49,7 @@
context.add_idls("interface A { };");
assert_throws(new TypeError(), _ => context.members["A"].traverse_inherited_and_consequential_interfaces());
}, "should throw if not passed a callback");
-
+
test(function() {
var context = new IdlArray();
context.add_idls(document.getElementById('fragments').textContent);
@@ -62,4 +62,3 @@
</script>
</body>
</html>
-
diff --git a/tests/wpt/web-platform-tests/resources/test/tests/iframe-consolidate-errors.html b/tests/wpt/web-platform-tests/resources/test/tests/iframe-consolidate-errors.html
index fd20d4f71f5..5d697e4c0f4 100644
--- a/tests/wpt/web-platform-tests/resources/test/tests/iframe-consolidate-errors.html
+++ b/tests/wpt/web-platform-tests/resources/test/tests/iframe-consolidate-errors.html
@@ -20,8 +20,8 @@ child context.</p>
<!-- apisample4.html is a failing suite due to an unhandled Error. -->
<script>
- var childContext = document.getElementById("childContext");
- fetch_tests_from_window(childContext.contentWindow);
+ var childContext = document.getElementById("childContext");
+ fetch_tests_from_window(childContext.contentWindow);
</script>
<script type="text/json" id="expected">
{
diff --git a/tests/wpt/web-platform-tests/resources/test/tests/iframe-consolidate-tests.html b/tests/wpt/web-platform-tests/resources/test/tests/iframe-consolidate-tests.html
index 90c5f8ece9f..5611d57e856 100644
--- a/tests/wpt/web-platform-tests/resources/test/tests/iframe-consolidate-tests.html
+++ b/tests/wpt/web-platform-tests/resources/test/tests/iframe-consolidate-tests.html
@@ -20,8 +20,8 @@ executing</p>
<!-- promise-async.html has async tests with promises -->
<script>
- var childContext = document.getElementById("childContext");
- fetch_tests_from_window(childContext.contentWindow);
+ var childContext = document.getElementById("childContext");
+ fetch_tests_from_window(childContext.contentWindow);
</script>
<script type="text/json" id="expected">
{
diff --git a/tests/wpt/web-platform-tests/resources/testdriver-vendor.js b/tests/wpt/web-platform-tests/resources/testdriver-vendor.js
index e69de29bb2d..3e884036363 100644
--- a/tests/wpt/web-platform-tests/resources/testdriver-vendor.js
+++ b/tests/wpt/web-platform-tests/resources/testdriver-vendor.js
@@ -0,0 +1 @@
+// This file intentionally left blank
diff --git a/tests/wpt/web-platform-tests/resources/testharness.js b/tests/wpt/web-platform-tests/resources/testharness.js
index d4d35ff4540..08d97b57223 100644
--- a/tests/wpt/web-platform-tests/resources/testharness.js
+++ b/tests/wpt/web-platform-tests/resources/testharness.js
@@ -1569,11 +1569,6 @@ policies and contribution forms [3].
this._add_cleanup(callback);
};
- Test.prototype.force_timeout = function() {
- this.set_status(this.TIMEOUT);
- this.phase = this.phases.HAS_RESULT;
- };
-
Test.prototype.set_timeout = function()
{
if (this.timeout_length !== null) {
@@ -1600,6 +1595,8 @@ policies and contribution forms [3].
this.done();
};
+ Test.prototype.force_timeout = Test.prototype.timeout;
+
Test.prototype.done = function()
{
if (this.phase == this.phases.COMPLETE) {
@@ -1711,7 +1708,13 @@ policies and contribution forms [3].
this.tests = new Array();
var this_obj = this;
- remote.onerror = function(error) { this_obj.remote_error(error); };
+ // If remote context is cross origin assigning to onerror is not
+ // possible, so silently catch those errors.
+ try {
+ remote.onerror = function(error) { this_obj.remote_error(error); };
+ } catch (e) {
+ // Ignore.
+ }
// Keeping a reference to the remote object and the message handler until
// remote_done() is seen prevents the remote object and its message channel
@@ -2084,11 +2087,7 @@ policies and contribution forms [3].
var message_port;
if (is_service_worker(worker)) {
- // Microsoft Edge's implementation of ServiceWorker doesn't support MessagePort yet.
- // Feature detection isn't a straightforward option here; it's only possible in the
- // worker's script context.
- var isMicrosoftEdgeBrowser = navigator.userAgent.includes("Edge");
- if (window.MessageChannel && !isMicrosoftEdgeBrowser) {
+ if (window.MessageChannel) {
// The ServiceWorker's implicit MessagePort is currently not
// reliably accessible from the ServiceWorkerGlobalScope due to
// Blink setting MessageEvent.source to null for messages sent
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/.travis.yml b/tests/wpt/web-platform-tests/resources/webidl2/.travis.yml
index 6e5919de39a..fc1508961db 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/.travis.yml
+++ b/tests/wpt/web-platform-tests/resources/webidl2/.travis.yml
@@ -1,3 +1,4 @@
language: node_js
node_js:
- - "0.10"
+ - node
+ - lts/*
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/CHANGELOG.md b/tests/wpt/web-platform-tests/resources/webidl2/CHANGELOG.md
new file mode 100644
index 00000000000..e6fa641e560
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/CHANGELOG.md
@@ -0,0 +1,216 @@
+# Change Log
+
+## [v8.0.1](https://github.com/w3c/webidl2.js/tree/v8.0.1) (2017-11-03)
+[Full Changelog](https://github.com/w3c/webidl2.js/compare/v8.0.0...v8.0.1)
+
+**Fixed bugs:**
+
+- Comment order parsing bug [\#107](https://github.com/w3c/webidl2.js/issues/107)
+
+**Merged pull requests:**
+
+- Remove m postfix from all\_ws\(\) [\#108](https://github.com/w3c/webidl2.js/pull/108) ([SaschaNaz](https://github.com/SaschaNaz))
+
+## [v8.0.0](https://github.com/w3c/webidl2.js/tree/v8.0.0) (2017-11-03)
+[Full Changelog](https://github.com/w3c/webidl2.js/compare/v7.0.0...v8.0.0)
+
+**Closed issues:**
+
+- Remove creators support [\#100](https://github.com/w3c/webidl2.js/issues/100)
+- Add mixin support [\#92](https://github.com/w3c/webidl2.js/issues/92)
+
+**Merged pull requests:**
+
+- Support mixins + includes statements [\#105](https://github.com/w3c/webidl2.js/pull/105) ([SaschaNaz](https://github.com/SaschaNaz))
+- chore: drop Node 6 support [\#102](https://github.com/w3c/webidl2.js/pull/102) ([marcoscaceres](https://github.com/marcoscaceres))
+- BREAKING CHANGE: drop creator support [\#101](https://github.com/w3c/webidl2.js/pull/101) ([SaschaNaz](https://github.com/SaschaNaz))
+- Normalize some whitespace to pass wpt's lint [\#99](https://github.com/w3c/webidl2.js/pull/99) ([foolip](https://github.com/foolip))
+
+## [v7.0.0](https://github.com/w3c/webidl2.js/tree/v7.0.0) (2017-10-27)
+[Full Changelog](https://github.com/w3c/webidl2.js/compare/v6.1.0...v7.0.0)
+
+**Closed issues:**
+
+- Type conversion on default values is destructive [\#94](https://github.com/w3c/webidl2.js/issues/94)
+- extended attribute structure missing type [\#89](https://github.com/w3c/webidl2.js/issues/89)
+
+**Merged pull requests:**
+
+- BREAKING CHANGE: argument + default types should be string [\#95](https://github.com/w3c/webidl2.js/pull/95) ([marcoscaceres](https://github.com/marcoscaceres))
+
+## [v6.1.0](https://github.com/w3c/webidl2.js/tree/v6.1.0) (2017-10-23)
+[Full Changelog](https://github.com/w3c/webidl2.js/compare/v6.0.1...v6.1.0)
+
+**Merged pull requests:**
+
+- feat: give extended attributes a type [\#90](https://github.com/w3c/webidl2.js/pull/90) ([marcoscaceres](https://github.com/marcoscaceres))
+
+## [v6.0.1](https://github.com/w3c/webidl2.js/tree/v6.0.1) (2017-10-18)
+[Full Changelog](https://github.com/w3c/webidl2.js/compare/v6.0.0...v6.0.1)
+
+**Closed issues:**
+
+- Enum values should be objects [\#86](https://github.com/w3c/webidl2.js/issues/86)
+
+**Merged pull requests:**
+
+- Use ES2015 syntax for tests [\#88](https://github.com/w3c/webidl2.js/pull/88) ([SaschaNaz](https://github.com/SaschaNaz))
+
+## [v6.0.0](https://github.com/w3c/webidl2.js/tree/v6.0.0) (2017-10-17)
+[Full Changelog](https://github.com/w3c/webidl2.js/compare/v5.0.0...v6.0.0)
+
+**Merged pull requests:**
+
+- BREAKING CHANGE: ret enum value as object [\#87](https://github.com/w3c/webidl2.js/pull/87) ([marcoscaceres](https://github.com/marcoscaceres))
+
+## [v5.0.0](https://github.com/w3c/webidl2.js/tree/v5.0.0) (2017-10-17)
+[Full Changelog](https://github.com/w3c/webidl2.js/compare/v4.2.0...v5.0.0)
+
+**Closed issues:**
+
+- Unable to parse annotated types in generics [\#83](https://github.com/w3c/webidl2.js/issues/83)
+- Drop support for Node 4, move to 6 LTS [\#82](https://github.com/w3c/webidl2.js/issues/82)
+
+**Merged pull requests:**
+
+- BREAKING CHANGE: Use ES2015 syntax [\#84](https://github.com/w3c/webidl2.js/pull/84) ([SaschaNaz](https://github.com/SaschaNaz))
+
+## [v4.2.0](https://github.com/w3c/webidl2.js/tree/v4.2.0) (2017-10-16)
+[Full Changelog](https://github.com/w3c/webidl2.js/compare/v4.1.0...v4.2.0)
+
+**Closed issues:**
+
+- Remove legacy caller support [\#78](https://github.com/w3c/webidl2.js/issues/78)
+- Should report error for using duplicate names [\#77](https://github.com/w3c/webidl2.js/issues/77)
+
+**Merged pull requests:**
+
+- Check duplicated names [\#80](https://github.com/w3c/webidl2.js/pull/80) ([SaschaNaz](https://github.com/SaschaNaz))
+- Remove legacycaller [\#79](https://github.com/w3c/webidl2.js/pull/79) ([SaschaNaz](https://github.com/SaschaNaz))
+- Add "sequence" property to IDL Type AST definition [\#76](https://github.com/w3c/webidl2.js/pull/76) ([lerouche](https://github.com/lerouche))
+
+## [v4.1.0](https://github.com/w3c/webidl2.js/tree/v4.1.0) (2017-07-04)
+[Full Changelog](https://github.com/w3c/webidl2.js/compare/v4.0.0...v4.1.0)
+
+**Closed issues:**
+
+- Parsing error for annonated inner types of generic types [\#71](https://github.com/w3c/webidl2.js/issues/71)
+
+**Merged pull requests:**
+
+- Support TypeWithExtendedAttributes on generics [\#75](https://github.com/w3c/webidl2.js/pull/75) ([SaschaNaz](https://github.com/SaschaNaz))
+
+## [v4.0.0](https://github.com/w3c/webidl2.js/tree/v4.0.0) (2017-06-27)
+[Full Changelog](https://github.com/w3c/webidl2.js/compare/v3.0.2...v4.0.0)
+
+**Closed issues:**
+
+- Remove serializer-related productions [\#73](https://github.com/w3c/webidl2.js/issues/73)
+- Records don't seem to be working right [\#72](https://github.com/w3c/webidl2.js/issues/72)
+- Document namespace member output [\#59](https://github.com/w3c/webidl2.js/issues/59)
+
+**Merged pull requests:**
+
+- BREAKING CHANGE: remove serializers \(closes \#73\) [\#74](https://github.com/w3c/webidl2.js/pull/74) ([marcoscaceres](https://github.com/marcoscaceres))
+- Add documentation for namespaces [\#70](https://github.com/w3c/webidl2.js/pull/70) ([SaschaNaz](https://github.com/SaschaNaz))
+
+## [v3.0.2](https://github.com/w3c/webidl2.js/tree/v3.0.2) (2017-05-29)
+[Full Changelog](https://github.com/w3c/webidl2.js/compare/v3.0.1...v3.0.2)
+
+**Closed issues:**
+
+- Whitespace issues [\#64](https://github.com/w3c/webidl2.js/issues/64)
+
+**Merged pull requests:**
+
+- Test for latest LTS/stable node versions [\#69](https://github.com/w3c/webidl2.js/pull/69) ([SaschaNaz](https://github.com/SaschaNaz))
+
+## [v3.0.1](https://github.com/w3c/webidl2.js/tree/v3.0.1) (2017-05-18)
+[Full Changelog](https://github.com/w3c/webidl2.js/compare/v2.4.0...v3.0.1)
+
+**Closed issues:**
+
+- Is array syntax dead? [\#66](https://github.com/w3c/webidl2.js/issues/66)
+- Remove exceptions support [\#65](https://github.com/w3c/webidl2.js/issues/65)
+
+**Merged pull requests:**
+
+- Fix whitespace error on parsing extended attributes [\#68](https://github.com/w3c/webidl2.js/pull/68) ([SaschaNaz](https://github.com/SaschaNaz))
+- Remove deprecated IDL arrays and exceptions [\#67](https://github.com/w3c/webidl2.js/pull/67) ([SaschaNaz](https://github.com/SaschaNaz))
+
+## [v2.4.0](https://github.com/w3c/webidl2.js/tree/v2.4.0) (2017-04-12)
+[Full Changelog](https://github.com/w3c/webidl2.js/compare/v2.1.0...v2.4.0)
+
+**Closed issues:**
+
+- Add support for Annotated Types [\#60](https://github.com/w3c/webidl2.js/issues/60)
+- Question: Convert WebIDL -\> Javascript [\#56](https://github.com/w3c/webidl2.js/issues/56)
+- Get Robin to give us push permissions on npm [\#54](https://github.com/w3c/webidl2.js/issues/54)
+- Add support for records [\#53](https://github.com/w3c/webidl2.js/issues/53)
+- module not supported? [\#52](https://github.com/w3c/webidl2.js/issues/52)
+- Add support for namespaces [\#51](https://github.com/w3c/webidl2.js/issues/51)
+- Export is not AMD compatible [\#48](https://github.com/w3c/webidl2.js/issues/48)
+- Can't represent large constants [\#21](https://github.com/w3c/webidl2.js/issues/21)
+
+**Merged pull requests:**
+
+- Update webidl2.js [\#63](https://github.com/w3c/webidl2.js/pull/63) ([tqeto](https://github.com/tqeto))
+- Remove support for MapClass \(no longer valid in WebIDL\) [\#62](https://github.com/w3c/webidl2.js/pull/62) ([dontcallmedom](https://github.com/dontcallmedom))
+- Add support for annotated types [\#61](https://github.com/w3c/webidl2.js/pull/61) ([dontcallmedom](https://github.com/dontcallmedom))
+- Support namespaces [\#58](https://github.com/w3c/webidl2.js/pull/58) ([SaschaNaz](https://github.com/SaschaNaz))
+- Add support for records [\#57](https://github.com/w3c/webidl2.js/pull/57) ([TimothyGu](https://github.com/TimothyGu))
+- Refactor [\#50](https://github.com/w3c/webidl2.js/pull/50) ([marcoscaceres](https://github.com/marcoscaceres))
+- feat\(lib\): add AMD export support \(closes \#48\) [\#49](https://github.com/w3c/webidl2.js/pull/49) ([marcoscaceres](https://github.com/marcoscaceres))
+
+## [v2.1.0](https://github.com/w3c/webidl2.js/tree/v2.1.0) (2016-08-12)
+**Closed issues:**
+
+- Exception when parsing test/syntax/idl/typedef.widl [\#46](https://github.com/w3c/webidl2.js/issues/46)
+- Wrong jsondiffpatch location [\#42](https://github.com/w3c/webidl2.js/issues/42)
+- 'npm install' fails on building microtime [\#40](https://github.com/w3c/webidl2.js/issues/40)
+- Can't represent union types in typedefs [\#38](https://github.com/w3c/webidl2.js/issues/38)
+- tokenise\(\) assumes a specific property enumeration order [\#27](https://github.com/w3c/webidl2.js/issues/27)
+- Add support for iterable\<\>, maplike\<\>, setlike\<\> declarations [\#24](https://github.com/w3c/webidl2.js/issues/24)
+- WebIDL2 fails to parse `attribute Promise\<DOMString\>\[\] baz` [\#19](https://github.com/w3c/webidl2.js/issues/19)
+- Support for ExtendedAttributeIdentList \(current editor's draft\) [\#18](https://github.com/w3c/webidl2.js/issues/18)
+- No Licensing Information [\#17](https://github.com/w3c/webidl2.js/issues/17)
+- how to regenerate w3c idl files ? [\#14](https://github.com/w3c/webidl2.js/issues/14)
+- What is lib/writer.js [\#13](https://github.com/w3c/webidl2.js/issues/13)
+- Numerous tests are failing [\#7](https://github.com/w3c/webidl2.js/issues/7)
+- Add support for missing types in ServiceWorker [\#5](https://github.com/w3c/webidl2.js/issues/5)
+- How can I parse just a function? [\#3](https://github.com/w3c/webidl2.js/issues/3)
+- Parser throws on nullable array of nullable array [\#2](https://github.com/w3c/webidl2.js/issues/2)
+- Parser throws on nullable array of any [\#1](https://github.com/w3c/webidl2.js/issues/1)
+
+**Merged pull requests:**
+
+- Fix "default": undefined [\#47](https://github.com/w3c/webidl2.js/pull/47) ([mkwtys](https://github.com/mkwtys))
+- Replace expect.js with expct [\#45](https://github.com/w3c/webidl2.js/pull/45) ([halton](https://github.com/halton))
+- Correct jsondiffpatch location. [\#44](https://github.com/w3c/webidl2.js/pull/44) ([halton](https://github.com/halton))
+- Bump microtime to 2.1.1 [\#43](https://github.com/w3c/webidl2.js/pull/43) ([halton](https://github.com/halton))
+- Expand writer support [\#39](https://github.com/w3c/webidl2.js/pull/39) ([markandrus](https://github.com/markandrus))
+- Accept wider \(but still incomplete\) set of allowed syntax for extended attributes [\#37](https://github.com/w3c/webidl2.js/pull/37) ([mlogan](https://github.com/mlogan))
+- Add test for callback with multiple arguments. [\#36](https://github.com/w3c/webidl2.js/pull/36) ([tobie](https://github.com/tobie))
+- Iterables [\#34](https://github.com/w3c/webidl2.js/pull/34) ([motiz88](https://github.com/motiz88))
+- Allow trailing comma in enum value lists, per spec [\#33](https://github.com/w3c/webidl2.js/pull/33) ([motiz88](https://github.com/motiz88))
+- Allow typedefs within interfaces \(behind an opt-in flag\) [\#32](https://github.com/w3c/webidl2.js/pull/32) ([motiz88](https://github.com/motiz88))
+- In draft [\#31](https://github.com/w3c/webidl2.js/pull/31) ([othree](https://github.com/othree))
+- Add support for extended attributes identifier lists [\#29](https://github.com/w3c/webidl2.js/pull/29) ([tobie](https://github.com/tobie))
+- Make `attribute Promise\<T\>\[\] attr;` work. [\#26](https://github.com/w3c/webidl2.js/pull/26) ([jyasskin](https://github.com/jyasskin))
+- Parse required dictionary fields. [\#25](https://github.com/w3c/webidl2.js/pull/25) ([jyasskin](https://github.com/jyasskin))
+- Define the WebIDL2 property on self rather than window. [\#23](https://github.com/w3c/webidl2.js/pull/23) ([Ms2ger](https://github.com/Ms2ger))
+- Teach WebIDL2 to parse \[\] default values. [\#22](https://github.com/w3c/webidl2.js/pull/22) ([jyasskin](https://github.com/jyasskin))
+- Support ID list in extended attributes [\#20](https://github.com/w3c/webidl2.js/pull/20) ([othree](https://github.com/othree))
+- Make sure that `sequence` property of idl types is set to false if the type is actually `sequence`. [\#16](https://github.com/w3c/webidl2.js/pull/16) ([tobie](https://github.com/tobie))
+- Parametrized [\#15](https://github.com/w3c/webidl2.js/pull/15) ([tobie](https://github.com/tobie))
+- Add promise support [\#12](https://github.com/w3c/webidl2.js/pull/12) ([tobie](https://github.com/tobie))
+- Remove broken coverage support from travis for now. [\#11](https://github.com/w3c/webidl2.js/pull/11) ([tobie](https://github.com/tobie))
+- Add support for \[MapClass\(type, type\)\]. [\#10](https://github.com/w3c/webidl2.js/pull/10) ([tobie](https://github.com/tobie))
+- Incorporate tests from widlproc\[1\] and remove dependency on said project. [\#9](https://github.com/w3c/webidl2.js/pull/9) ([tobie](https://github.com/tobie))
+- README incorrectly recommended updating the widlproc submodule. [\#8](https://github.com/w3c/webidl2.js/pull/8) ([tobie](https://github.com/tobie))
+- Fix bug where instrumented version of webidl2 was loaded. [\#6](https://github.com/w3c/webidl2.js/pull/6) ([tobie](https://github.com/tobie))
+- Use https:// instead of git:// [\#4](https://github.com/w3c/webidl2.js/pull/4) ([Manishearth](https://github.com/Manishearth))
+
+
+
+\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/README.md b/tests/wpt/web-platform-tests/resources/webidl2/README.md
index 5d128ed27ca..93cc78b9c48 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/README.md
+++ b/tests/wpt/web-platform-tests/resources/webidl2/README.md
@@ -1,7 +1,7 @@
# WebIDL 2
-[![NPM version](https://badge.fury.io/js/webidl2.png)](http://badge.fury.io/js/webidl2)
+[![NPM version](https://badge.fury.io/js/webidl2.svg)](http://badge.fury.io/js/webidl2)
## Purpose
@@ -10,26 +10,6 @@ you don't know what that is, then you probably don't need it. It is meant to be
both in Node and in the browser (the parser likely works in other JS environments, but
not the test suite).
-### What of v1?
-
-There was a previous incarnation of this project. I had written it in the most quick
-and dirty manner that was handy because I required it as a dependency in an experiment.
-As these things tend to happen, some people started using that, which then had to be
-maintained. But since it was not built on solid foundations, it was painful to keep
-up to date with the specification, which is a bit of a moving target.
-
-So I started from scratch. Compared to the previous version (which used a parser generator)
-this one is about 6x less code (which translates to 4x smaller minified or 2x smaller
-minizipped) and 4x faster. The test suite is reasonably complete (95% coverage), much more
-than previously. This version is up to date with WebIDL, rather than a couple years' behind.
-It also has *far* better error reporting.
-
-The AST you get from parsing is very similar to the one you got in v1, but some adjustments
-have been made in order to be more systematic, and to map better to what's actually in the spec
-now. If you used v1, you will need to tweak your code but the result ought to be simpler and
-you ought to be able to be a fair bit less defensive against irregularities in the way
-information is represented.
-
## Installation
Just the usual. For Node:
@@ -46,7 +26,6 @@ In the browser:
## Documentation
-
The API to WebIDL2 is trivial: you parse a string of WebIDL and it returns a syntax tree.
### Parsing
@@ -103,7 +82,7 @@ The `parse()` method returns a tree object representing the parse tree of the ID
Comment and white space are not represented in the AST.
The root of this object is always an array of definitions (where definitions are
-any of interfaces, exceptions, callbacks, etc. — anything that can occur at the root
+any of interfaces, dictionaries, callbacks, etc. — anything that can occur at the root
of the IDL).
### IDL Type
@@ -114,7 +93,7 @@ attached to a field called `idlType`:
```JS
{
- "array": false,
+ "sequence": false,
"generic": null,
"idlType": "void",
"nullable": false,
@@ -124,8 +103,7 @@ attached to a field called `idlType`:
Where the fields are as follows:
-* `array`: Either `false` to indicate that it is not an array, or a number for the level of
- array nesting.
+* `sequence`: Boolean indicating if it is a sequence. Same as `generic === "sequence"`.
* `generic`: String indicating the generic type (e.g. "Promise", "sequence"). `null`
otherwise.
* `idlType`: Can be different things depending on context. In most cases, this will just
@@ -136,40 +114,8 @@ Where the fields are as follows:
* `nullable`: Boolean indicating whether this is nullable or not.
* `union`: Boolean indicating whether this is a union type or not.
-#### Interactions between `nullable` and `array`
-
-A more complex data model for our AST would likely represent `Foo[][][]` as a series of
-nested types four levels deep with three anonymous array types eventually containing a
-`Foo` type. But experience shows that such structures are cumbersome to use, and so we
-have a simpler model in which the depth of the array is specified with the `array` field.
-
-This is all fine and well, and in the vast majority of cases is actually simpler. But it
-does run afoul of cases in which it is necessary to distinguish between `Foo[][][]?`,
-`Foo?[][][]`, `Foo[][]?[]`, or even `Foo?[]?[]?[]?`.
-
-For this, when a type is an array type an additional `nullableArray` field is made available
-that captures which of the arrays contain nullable elements. It contains booleans that are
-true if the given array depth contains nullable elements, and false otherwise (mapping that to
-the syntax, and item is true if there is a `?` preceding the `[]`). These examples ought to
-clarify the model:
-
- Foo[][][]?
- -> nullable: true
- -> nullableArray: [false, false, false]
- Foo?[][][]
- -> nullable: false
- -> nullableArray: [true, false, false]
- Foo[][]?[]
- -> nullable: false
- -> nullableArray: [false, false, true]
- Foo?[]?[]?[]?
- -> nullable: true
- -> nullableArray: [true, true, true]
-
-Of particular importance, please note that the overall type is only `nullable` if there is
-a `?` at the end.
-
### Interface
+
Interfaces look like this:
```JS
@@ -193,7 +139,7 @@ Interfaces look like this:
The fields are as follows:
* `type`: Always "interface".
-* `name`: The name of the interface
+* `name`: The name of the interface.
* `partial`: A boolean indicating whether it's a partial interface.
* `members`: An array of interface members (attributes, operations, etc.). Empty if there are none.
* `inheritance`: A string giving the name of an interface this one inherits from, `null` otherwise.
@@ -201,6 +147,56 @@ The fields are as follows:
sense.
* `extAttrs`: A list of [extended attributes](#extended-attributes).
+### Interface mixins
+
+Interfaces mixins look like this:
+
+```JS
+{
+ "type": "interface mixin",
+ "name": "Animal",
+ "partial": false,
+ "members": [...],
+ "extAttrs": [...]
+}, {
+ "type": "interface mixin",
+ "name": "Human",
+ "partial": false,
+ "members": [...],
+ "extAttrs": [...]
+}
+```
+
+The fields are as follows:
+
+* `type`: Always "interface mixin".
+* `name`: The name of the interface mixin.
+* `partial`: A boolean indicating whether it's a partial interface mixin.
+* `members`: An array of interface members (attributes, operations, etc.). Empty if there are none.
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
+### Namespace
+
+Namespaces look like this:
+
+```JS
+{
+ "type": "namespace",
+ "name": "Console",
+ "partial": false,
+ "members": [...],
+ "extAttrs": [...]
+}
+```
+
+The fields are as follows:
+
+* `type`: Always "namespace".
+* `name`: The name of the namespace.
+* `partial`: A boolean indicating whether it's a partial namespace.
+* `members`: An array of namespace members (attributes and operations). Empty if there are none.
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
### Callback Interfaces
These are captured by the same structure as [Interfaces](#interface) except that
@@ -218,7 +214,6 @@ A callback looks like this:
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -252,7 +247,6 @@ A dictionary looks like this:
"sequence": false,
"generic": null,
"nullable": true,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -285,47 +279,6 @@ All the members are fields as follows:
* `extAttrs`: A list of [extended attributes](#extended-attributes).
* `default`: A [default value](#default-and-const-values), absent if there is none.
-### Exception
-
-An exception looks like this:
-
-```JS
-{
- "type": "exception",
- "name": "HierarchyRequestError",
- "members": [{
- "type": "field",
- "name": "code",
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "unsigned short"
- },
- "extAttrs": []
- }],
- "inheritance": "DOMException",
- "extAttrs": []
-}
-```
-
-The fields are as follows:
-
-* `type`: Always "exception".
-* `name`: The exception name.
-* `members`: An array of members (constants or fields, where fields are described below).
-* `inheritance`: A string indicating which exception is being inherited from, `null` otherwise.
-* `extAttrs`: A list of [extended attributes](#extended-attributes).
-
-Members that aren't [constants](#constants) have the following fields:
-
-* `type`: Always "field".
-* `name`: The field's name.
-* `idlType`: An [IDL Type](#idl-type) describing what field's type.
-* `extAttrs`: A list of [extended attributes](#extended-attributes).
-
### Enum
An enum looks like this:
@@ -335,9 +288,9 @@ An enum looks like this:
"type": "enum",
"name": "MealType",
"values": [
- "rice",
- "noodles",
- "other"
+ { "type": "string", "value": "rice" },
+ { "type": "string", "value": "noodles" },
+ { "type": "string", "value": "other" }
],
"extAttrs": []
}
@@ -347,7 +300,7 @@ The fields are as follows:
* `type`: Always "enum".
* `name`: The enum's name.
-* `value`: An array of values (strings).
+* `values`: An array of values.
* `extAttrs`: A list of [extended attributes](#extended-attributes).
### Typedef
@@ -362,13 +315,11 @@ A typedef looks like this:
"sequence": true,
"generic": "sequence",
"nullable": false,
- "array": false,
"union": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Point"
}
@@ -385,7 +336,7 @@ The fields are as follows:
* `name`: The typedef's name.
* `idlType`: An [IDL Type](#idl-type) describing what typedef's type.
* `extAttrs`: A list of [extended attributes](#extended-attributes).
-* `typeExtAttrs`: A list of [extended attributes](#extended-attributes) that apply to the
+* `typeExtAttrs`: A list of [extended attributes](#extended-attributes) that apply to the
type rather than to the typedef as a whole.
### Implements
@@ -408,6 +359,26 @@ The fields are as follows:
* `implements`: The interface that is being implemented by the target.
* `extAttrs`: A list of [extended attributes](#extended-attributes).
+### Includes
+
+An includes definition looks like this:
+
+```JS
+{
+ "type": "includes",
+ "target": "Node",
+ "includes": "EventTarget",
+ "extAttrs": []
+}
+```
+
+The fields are as follows:
+
+* `type`: Always "includes".
+* `target`: The interface that includes an interface mixin.
+* `includes`: The interface mixin that is being included by the target.
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
### Operation Member
An operation looks like this:
@@ -416,16 +387,13 @@ An operation looks like this:
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -438,7 +406,6 @@ An operation looks like this:
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "long"
},
@@ -453,9 +420,7 @@ The fields are as follows:
* `type`: Always "operation".
* `getter`: True if a getter operation.
* `setter`: True if a setter operation.
-* `creator`: True if a creator operation.
* `deleter`: True if a deleter operation.
-* `legacycaller`: True if a legacycaller operation.
* `static`: True if a static operation.
* `stringifier`: True if a stringifier operation.
* `idlType`: An [IDL Type](#idl-type) of what the operation returns. If a stringifier, may be absent.
@@ -478,7 +443,6 @@ An attribute member looks like this:
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "RegExp"
},
@@ -525,96 +489,6 @@ The fields are as follows:
* `value`: The constant value as described by [Const Values](#default-and-const-values)
* `extAttrs`: A list of [extended attributes](#extended-attributes).
-### Serializer Member
-
-Serializers come in many shapes, which are best understood by looking at the
-examples below that map the IDL to the produced AST.
-
-```JS
-// serializer;
-{
- "type": "serializer",
- "extAttrs": []
-}
-
-// serializer DOMString serialize();
-{
- "type": "serializer",
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "DOMString"
- },
- "operation": {
- "name": "serialize",
- "arguments": []
- },
- "extAttrs": []
-}
-
-// serializer = { from, to, amount, description };
-{
- "type": "serializer",
- "patternMap": true,
- "names": [
- "from",
- "to",
- "amount",
- "description"
- ],
- "extAttrs": []
-}
-
-// serializer = number;
-{
- "type": "serializer",
- "name": "number",
- "extAttrs": []
-}
-
-// serializer = [ name, number ];
-{
- "type": "serializer",
- "patternList": true,
- "names": [
- "name",
- "number"
- ],
- "extAttrs": []
-}
-
-```
-
-The common fields are as follows:
-
-* `type`: Always "serializer".
-* `extAttrs`: A list of [extended attributes](#extended-attributes).
-
-For a simple serializer, that's all there is. If the serializer is an operation, it will
-have:
-
-* `idlType`: An [IDL Type](#idl-type) describing what the serializer returns.
-* `operation`: An object with the following fields:
- * `name`: The name of the operation.
- * `arguments`: An array of [arguments](#arguments) for the operation.
-
-If the serializer is a pattern map:
-
-* `patternMap`: Always true.
-* `names`: An array of names in the pattern map.
-
-If the serializer is a pattern list:
-
-* `patternList`: Always true.
-* `names`: An array of names in the pattern list.
-
-Finally, if the serializer is a named serializer:
-
-* `name`: The serializer's name.
-
### Iterator Member
Iterator members look like this
@@ -624,16 +498,13 @@ Iterator members look like this
"type": "iterator",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Session2"
},
@@ -660,7 +531,6 @@ The arguments (e.g. for an operation) look like this:
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "long"
},
@@ -686,6 +556,7 @@ Extended attributes are arrays of items that look like this:
"extAttrs": [{
"name": "TreatNullAs",
"arguments": null,
+ "type": "extended-attribute",
"rhs": {
"type": "identifier",
"value": "EmptyString"
@@ -703,6 +574,7 @@ The fields are as follows:
whereas the lack thereof will yield a `null`. If there is an `rhs` field then
they are the right-hand side's arguments, otherwise they apply to the extended
attribute directly.
+* `type`: Always `"extended-attribute"`.
* `rhs`: If there is a right-hand side, this will capture its `type` (which can be
"identifier" or "identifier-list") and its `value`.
* `typePair`: If the extended attribute is a `MapClass` this will capture the
@@ -717,7 +589,7 @@ values, all of which have the following fields:
For string, number, boolean, and sequence:
-* `value`: The value of the given type. For sequence, the only possible value is `[]`.
+* `value`: The value of the given type, as a string. For sequence, the only possible value is `[]`.
For Infinity:
@@ -787,8 +659,3 @@ In order to test in the browser, get inside `test/web` and run `make-web-tests.j
will generate a `browser-tests.html` file that you can open in a browser. As of this
writing tests pass in the latest Firefox, Chrome, Opera, and Safari. Testing on IE
and older versions will happen progressively.
-
-## TODO
-
-* add some tests to address coverage limitations
-* add a push API for processors that need to process things like comments
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/lib/webidl2.js b/tests/wpt/web-platform-tests/resources/webidl2/lib/webidl2.js
index 0e76174a083..2f116c40d94 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/lib/webidl2.js
+++ b/tests/wpt/web-platform-tests/resources/webidl2/lib/webidl2.js
@@ -1,21 +1,22 @@
-(function() {
- var tokenise = function(str) {
- var tokens = [],
- re = {
- "float": /^-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][-+]?[0-9]+)?|[0-9]+[Ee][-+]?[0-9]+)/,
- "integer": /^-?(0([Xx][0-9A-Fa-f]+|[0-7]*)|[1-9][0-9]*)/,
- "identifier": /^[A-Z_a-z][0-9A-Z_a-z-]*/,
- "string": /^"[^"]*"/,
- "whitespace": /^(?:[\t\n\r ]+|[\t\n\r ]*((\/\/.*|\/\*(.|\n|\r)*?\*\/)[\t\n\r ]*))+/,
- "other": /^[^\t\n\r 0-9A-Z_a-z]/
- },
- types = ["float", "integer", "identifier", "string", "whitespace", "other"];
+"use strict";
+
+(() => {
+ function tokenise(str) {
+ const tokens = [];
+ const re = {
+ "float": /^-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][-+]?[0-9]+)?|[0-9]+[Ee][-+]?[0-9]+)/,
+ "integer": /^-?(0([Xx][0-9A-Fa-f]+|[0-7]*)|[1-9][0-9]*)/,
+ "identifier": /^[A-Z_a-z][0-9A-Z_a-z-]*/,
+ "string": /^"[^"]*"/,
+ "whitespace": /^(?:[\t\n\r ]+|[\t\n\r ]*((\/\/.*|\/\*(.|\n|\r)*?\*\/)[\t\n\r ]*))+/,
+ "other": /^[^\t\n\r 0-9A-Z_a-z]/
+ };
+ const types = ["float", "integer", "identifier", "string", "whitespace", "other"];
while (str.length > 0) {
- var matched = false;
- for (var i = 0, n = types.length; i < n; i++) {
- var type = types[i];
- str = str.replace(re[type], function(tok) {
- tokens.push({ type: type, value: tok });
+ let matched = false;
+ for (const type of types) {
+ str = str.replace(re[type], tok => {
+ tokens.push({ type, value: tok });
matched = true;
return "";
});
@@ -27,42 +28,61 @@
return tokens;
};
- function WebIDLParseError(str, line, input, tokens) {
- this.message = str;
- this.line = line;
- this.input = input;
- this.tokens = tokens;
- };
+ class WebIDLParseError {
+ constructor(str, line, input, tokens) {
+ this.message = str;
+ this.line = line;
+ this.input = input;
+ this.tokens = tokens;
+ }
- WebIDLParseError.prototype.toString = function() {
- return this.message + ", line " + this.line + " (tokens: '" + this.input + "')\n" +
- JSON.stringify(this.tokens, null, 4);
- };
+ toString() {
+ return `${this.message}, line ${this.line} (tokens: '${this.input}')\n${JSON.stringify(this.tokens, null, 4)}`;
+ }
+ }
- var parse = function(tokens, opt) {
- var line = 1;
+ function parse(tokens, opt) {
+ let line = 1;
tokens = tokens.slice();
+ const names = new Map();
- var FLOAT = "float",
- INT = "integer",
- ID = "identifier",
- STR = "string",
- OTHER = "other";
+ const FLOAT = "float";
+ const INT = "integer";
+ const ID = "identifier";
+ const STR = "string";
+ const OTHER = "other";
- var error = function(str) {
- var tok = "";
- var numTokens = 0;
- var maxTokens = 5;
+ const EMPTY_OPERATION = Object.freeze({
+ type: "operation",
+ getter: false,
+ setter: false,
+ deleter: false,
+ "static": false,
+ stringifier: false
+ });
+
+ function error(str) {
+ let tok = "";
+ let numTokens = 0;
+ const maxTokens = 5;
while (numTokens < maxTokens && tokens.length > numTokens) {
tok += tokens[numTokens].value;
numTokens++;
}
- throw new WebIDLParseError(str, line, tok, tokens.slice(0, 5));
+ throw new WebIDLParseError(str, line, tok, tokens.slice(0, maxTokens));
};
- var last_token = null;
+ function sanitize_name(name, type) {
+ if (names.has(name)) {
+ error(`The name "${name}" of type "${names.get(name)}" is already seen`);
+ }
+ names.set(name, type);
+ return name;
+ }
+
+ let last_token = null;
- var consume = function(type, value) {
+ function consume(type, value) {
if (!tokens.length || tokens[0].type !== type) return;
if (typeof value === "undefined" || tokens[0].value === value) {
last_token = tokens.shift();
@@ -71,38 +91,39 @@
}
};
- var ws = function() {
+ function ws() {
if (!tokens.length) return;
if (tokens[0].type === "whitespace") {
- var t = tokens.shift();
- t.value.replace(/\n/g, function(m) { line++;
- return m; });
+ const t = tokens.shift();
+ t.value.replace(/\n/g, m => {
+ line++;
+ return m;
+ });
return t;
}
};
- var all_ws = function(store, pea) { // pea == post extended attribute, tpea = same for types
- var t = { type: "whitespace", value: "" };
+ function all_ws(store, pea) { // pea == post extended attribute, tpea = same for types
+ const t = { type: "whitespace", value: "" };
while (true) {
- var w = ws();
+ const w = ws();
if (!w) break;
t.value += w.value;
}
if (t.value.length > 0) {
if (store) {
- var w = t.value,
- re = {
- "ws": /^([\t\n\r ]+)/,
- "line-comment": /^\/\/(.*)\n?/m,
- "multiline-comment": /^\/\*((?:.|\n|\r)*?)\*\//
- },
- wsTypes = [];
- for (var k in re) wsTypes.push(k);
+ let w = t.value;
+ const re = {
+ "ws": /^([\t\n\r ]+)/,
+ "line-comment": /^\/\/(.*)\r?\n?/,
+ "multiline-comment": /^\/\*((?:.|\n|\r)*?)\*\//
+ };
+ const wsTypes = [];
+ for (const k in re) wsTypes.push(k);
while (w.length) {
- var matched = false;
- for (var i = 0, n = wsTypes.length; i < n; i++) {
- var type = wsTypes[i];
- w = w.replace(re[type], function(tok, m1) {
+ let matched = false;
+ for (const type of wsTypes) {
+ w = w.replace(re[type], (tok, m1) => {
store.push({ type: type + (pea ? ("-" + pea) : ""), value: m1 });
matched = true;
return "";
@@ -117,8 +138,8 @@
}
};
- var integer_type = function() {
- var ret = "";
+ function integer_type() {
+ let ret = "";
all_ws();
if (consume(ID, "unsigned")) ret = "unsigned ";
all_ws();
@@ -132,8 +153,8 @@
if (ret) error("Failed to parse integer type");
};
- var float_type = function() {
- var ret = "";
+ function float_type() {
+ let ret = "";
all_ws();
if (consume(ID, "unrestricted")) ret = "unrestricted ";
all_ws();
@@ -142,8 +163,8 @@
if (ret) error("Failed to parse float type");
};
- var primitive_type = function() {
- var num_type = integer_type() || float_type();
+ function primitive_type() {
+ const num_type = integer_type() || float_type();
if (num_type) return num_type;
all_ws();
if (consume(ID, "boolean")) return "boolean";
@@ -151,46 +172,36 @@
if (consume(ID, "octet")) return "octet";
};
- var const_value = function() {
+ function const_value() {
if (consume(ID, "true")) return { type: "boolean", value: true };
if (consume(ID, "false")) return { type: "boolean", value: false };
if (consume(ID, "null")) return { type: "null" };
if (consume(ID, "Infinity")) return { type: "Infinity", negative: false };
if (consume(ID, "NaN")) return { type: "NaN" };
- var ret = consume(FLOAT) || consume(INT);
- if (ret) return { type: "number", value: 1 * ret.value };
- var tok = consume(OTHER, "-");
+ const ret = consume(FLOAT) || consume(INT);
+ if (ret) return { type: "number", value: ret.value };
+ const tok = consume(OTHER, "-");
if (tok) {
if (consume(ID, "Infinity")) return { type: "Infinity", negative: true };
else tokens.unshift(tok);
}
};
- var type_suffix = function(obj) {
+ function type_suffix(obj) {
while (true) {
all_ws();
if (consume(OTHER, "?")) {
if (obj.nullable) error("Can't nullable more than once");
obj.nullable = true;
- } else if (consume(OTHER, "[")) {
- all_ws();
- consume(OTHER, "]") || error("Unterminated array type");
- if (!obj.array) {
- obj.array = 1;
- obj.nullableArray = [obj.nullable];
- } else {
- obj.array++;
- obj.nullableArray.push(obj.nullable);
- }
- obj.nullable = false;
} else return;
}
};
- var single_type = function() {
- var prim = primitive_type(),
- ret = { sequence: false, generic: null, nullable: false, array: false, union: false },
- name, value;
+ function single_type() {
+ const prim = primitive_type();
+ const ret = { sequence: false, generic: null, nullable: false, union: false };
+ let name;
+ let value;
if (prim) {
ret.idlType = prim;
} else if (name = consume(ID)) {
@@ -203,10 +214,10 @@
ret.sequence = true;
}
ret.generic = value;
- var types = [];
+ const types = [];
do {
all_ws();
- types.push(type() || error("Error parsing generic type " + value));
+ types.push(type_with_extended_attributes() || error("Error parsing generic type " + value));
all_ws();
}
while (consume(OTHER, ","));
@@ -217,6 +228,9 @@
if (!/^(DOMString|USVString|ByteString)$/.test(types[0].idlType)) {
error("Record key must be DOMString, USVString, or ByteString");
}
+ if (types[0].extAttrs) error("Record key cannot have extended attribute");
+ } else if (value === "Promise") {
+ if (types[0].extAttrs) error("Promise type cannot have extended attribute");
}
ret.idlType = types.length === 1 ? types[0] : types;
all_ws();
@@ -230,20 +244,20 @@
return;
}
type_suffix(ret);
- if (ret.nullable && !ret.array && ret.idlType === "any") error("Type any cannot be made nullable");
+ if (ret.nullable && ret.idlType === "any") error("Type any cannot be made nullable");
return ret;
};
- var union_type = function() {
+ function union_type() {
all_ws();
if (!consume(OTHER, "(")) return;
- var ret = { sequence: false, generic: null, nullable: false, array: false, union: true, idlType: [] };
- var fst = type_with_extended_attributes() || error("Union type with no content");
+ const ret = { sequence: false, generic: null, nullable: false, union: true, idlType: [] };
+ const fst = type_with_extended_attributes() || error("Union type with no content");
ret.idlType.push(fst);
while (true) {
all_ws();
if (!consume(ID, "or")) break;
- var typ = type_with_extended_attributes() || error("No type after 'or' in union type");
+ const typ = type_with_extended_attributes() || error("No type after 'or' in union type");
ret.idlType.push(typ);
}
if (!consume(OTHER, ")")) error("Unterminated union type");
@@ -251,22 +265,22 @@
return ret;
};
- var type = function() {
+ function type() {
return single_type() || union_type();
};
- var type_with_extended_attributes = function() {
- var extAttrs = extended_attrs();
- var ret = single_type() || union_type();
+ function type_with_extended_attributes() {
+ const extAttrs = extended_attrs();
+ const ret = single_type() || union_type();
if (extAttrs.length && ret) ret.extAttrs = extAttrs;
return ret;
};
- var argument = function(store) {
- var ret = { optional: false, variadic: false };
+ function argument(store) {
+ const ret = { optional: false, variadic: false };
ret.extAttrs = extended_attrs(store);
all_ws(store, "pea");
- var opt_token = consume(ID, "optional");
+ const opt_token = consume(ID, "optional");
if (opt_token) {
ret.optional = true;
all_ws();
@@ -276,7 +290,7 @@
if (opt_token) tokens.unshift(opt_token);
return;
}
- var type_token = last_token;
+ const type_token = last_token;
if (!ret.optional) {
all_ws();
if (tokens.length >= 3 &&
@@ -291,7 +305,7 @@
}
}
all_ws();
- var name = consume(ID);
+ const name = consume(ID);
if (!name) {
if (opt_token) tokens.unshift(opt_token);
tokens.unshift(type_token);
@@ -300,7 +314,7 @@
ret.name = name.value;
if (ret.optional) {
all_ws();
- var dflt = default_();
+ const dflt = default_();
if (typeof dflt !== "undefined") {
ret["default"] = dflt;
}
@@ -308,59 +322,56 @@
return ret;
};
- var argument_list = function(store) {
- var ret = [],
- arg = argument(store ? ret : null);
+ function argument_list(store) {
+ const ret = [];
+ const arg = argument(store ? ret : null);
if (!arg) return;
ret.push(arg);
while (true) {
all_ws(store ? ret : null);
if (!consume(OTHER, ",")) return ret;
- var nxt = argument(store ? ret : null) || error("Trailing comma in arguments list");
+ const nxt = argument(store ? ret : null) || error("Trailing comma in arguments list");
ret.push(nxt);
}
};
- var simple_extended_attr = function(store) {
+ function simple_extended_attr(store) {
all_ws();
- var name = consume(ID);
+ const name = consume(ID);
if (!name) return;
- var ret = {
+ const ret = {
name: name.value,
- "arguments": null
+ "arguments": null,
+ type: "extended-attribute",
+ rhs: null
};
all_ws();
- var eq = consume(OTHER, "=");
+ const eq = consume(OTHER, "=");
if (eq) {
- var rhs;
all_ws();
- if (rhs = consume(ID)) {
- ret.rhs = rhs;
- } else if (rhs = consume(FLOAT)) {
- ret.rhs = rhs;
- } else if (rhs = consume(INT)) {
- ret.rhs = rhs;
- } else if (rhs = consume(STR)) {
- ret.rhs = rhs;
- } else if (consume(OTHER, "(")) {
+ ret.rhs = consume(ID) ||
+ consume(FLOAT) ||
+ consume(INT) ||
+ consume(STR);
+ if (!ret.rhs && consume(OTHER, "(")) {
// [Exposed=(Window,Worker)]
- rhs = [];
- var id = consume(ID);
+ const rhs_list = [];
+ const id = consume(ID);
if (id) {
- rhs = [id.value];
+ rhs_list.push(id.value);
}
- identifiers(rhs);
+ identifiers(rhs_list);
consume(OTHER, ")") || error("Unexpected token in extended attribute argument list or type pair");
ret.rhs = {
type: "identifier-list",
- value: rhs
+ value: rhs_list
};
}
if (!ret.rhs) return error("No right hand side to extended attribute assignment");
}
all_ws();
if (consume(OTHER, "(")) {
- var args, pair;
+ let args, pair;
// [Constructor(DOMString str)]
if (args = argument_list(store)) {
ret["arguments"] = args;
@@ -377,8 +388,8 @@
// Note: we parse something simpler than the official syntax. It's all that ever
// seems to be used
- var extended_attrs = function(store) {
- var eas = [];
+ function extended_attrs(store) {
+ const eas = [];
all_ws(store);
if (!consume(OTHER, "[")) return eas;
eas[0] = simple_extended_attr(store) || error("Extended attribute with not content");
@@ -390,34 +401,35 @@
eas.push(simple_extended_attr(store) || error("Trailing comma in extended attribute"));
}
}
+ all_ws();
consume(OTHER, "]") || error("No end of extended attribute");
return eas;
};
- var default_ = function() {
+ function default_() {
all_ws();
if (consume(OTHER, "=")) {
all_ws();
- var def = const_value();
+ const def = const_value();
if (def) {
return def;
} else if (consume(OTHER, "[")) {
if (!consume(OTHER, "]")) error("Default sequence value must be empty");
return { type: "sequence", value: [] };
} else {
- var str = consume(STR) || error("No value for default");
+ const str = consume(STR) || error("No value for default");
str.value = str.value.replace(/^"/, "").replace(/"$/, "");
return str;
}
}
};
- var const_ = function(store) {
+ function const_(store) {
all_ws(store, "pea");
if (!consume(ID, "const")) return;
- var ret = { type: "const", nullable: false };
+ const ret = { type: "const", nullable: false };
all_ws();
- var typ = primitive_type();
+ let typ = primitive_type();
if (!typ) {
typ = consume(ID) || error("No type for const");
typ = typ.value;
@@ -428,12 +440,12 @@
ret.nullable = true;
all_ws();
}
- var name = consume(ID) || error("No name for const");
+ const name = consume(ID) || error("No name for const");
ret.name = name.value;
all_ws();
consume(OTHER, "=") || error("No value assignment for const");
all_ws();
- var cnt = const_value();
+ const cnt = const_value();
if (cnt) ret.value = cnt;
else error("No value for const");
all_ws();
@@ -441,19 +453,19 @@
return ret;
};
- var inheritance = function() {
+ function inheritance() {
all_ws();
if (consume(OTHER, ":")) {
all_ws();
- var inh = consume(ID) || error("No type in inheritance");
+ const inh = consume(ID) || error("No type in inheritance");
return inh.value;
}
};
- var operation_rest = function(ret, store) {
+ function operation_rest(ret, store) {
all_ws();
if (!ret) ret = {};
- var name = consume(ID);
+ const name = consume(ID);
ret.name = name ? name.value : null;
all_ws();
consume(OTHER, "(") || error("Invalid operation");
@@ -465,20 +477,19 @@
return ret;
};
- var callback = function(store) {
+ function callback(store) {
all_ws(store, "pea");
- var ret;
+ let ret;
if (!consume(ID, "callback")) return;
all_ws();
- var tok = consume(ID, "interface");
+ const tok = consume(ID, "interface");
if (tok) {
- tokens.unshift(tok);
- ret = interface_();
+ ret = interface_rest();
ret.type = "callback interface";
return ret;
}
- var name = consume(ID) || error("No name for callback");
- ret = { type: "callback", name: name.value };
+ const name = consume(ID) || error("No name for callback");
+ ret = { type: "callback", name: sanitize_name(name.value, "callback") };
all_ws();
consume(OTHER, "=") || error("No assignment in callback");
all_ws();
@@ -493,46 +504,39 @@
return ret;
};
- var attribute = function(store) {
+ function attribute(store) {
all_ws(store, "pea");
- var grabbed = [],
- ret = {
- type: "attribute",
- "static": false,
- stringifier: false,
- inherit: false,
- readonly: false
- };
- if (consume(ID, "static")) {
- ret["static"] = true;
- grabbed.push(last_token);
- } else if (consume(ID, "stringifier")) {
- ret.stringifier = true;
- grabbed.push(last_token);
- }
- var w = all_ws();
+ const grabbed = [];
+ const ret = {
+ type: "attribute",
+ "static": false,
+ stringifier: false,
+ inherit: false,
+ readonly: false
+ };
+ const w = all_ws();
if (w) grabbed.push(w);
if (consume(ID, "inherit")) {
if (ret["static"] || ret.stringifier) error("Cannot have a static or stringifier inherit");
ret.inherit = true;
grabbed.push(last_token);
- var w = all_ws();
+ const w = all_ws();
if (w) grabbed.push(w);
}
if (consume(ID, "readonly")) {
ret.readonly = true;
grabbed.push(last_token);
- var w = all_ws();
+ const w = all_ws();
if (w) grabbed.push(w);
}
- var rest = attribute_rest(ret);
+ const rest = attribute_rest(ret);
if (!rest) {
tokens = grabbed.concat(tokens);
}
return rest;
};
- var attribute_rest = function(ret) {
+ function attribute_rest(ret) {
if (!consume(ID, "attribute")) {
return;
}
@@ -541,15 +545,15 @@
if (ret.idlType.sequence) error("Attributes cannot accept sequence types");
if (ret.idlType.generic === "record") error("Attributes cannot accept record types");
all_ws();
- var name = consume(ID) || error("No name in attribute");
+ const name = consume(ID) || error("No name in attribute");
ret.name = name.value;
all_ws();
consume(OTHER, ";") || error("Unterminated attribute");
return ret;
};
- var return_type = function() {
- var typ = type();
+ function return_type() {
+ const typ = type();
if (!typ) {
if (consume(ID, "void")) {
return "void";
@@ -558,46 +562,22 @@
return typ;
};
- var operation = function(store) {
+ function operation(store) {
all_ws(store, "pea");
- var ret = {
- type: "operation",
- getter: false,
- setter: false,
- creator: false,
- deleter: false,
- legacycaller: false,
- "static": false,
- stringifier: false
- };
+ const ret = Object.assign({}, EMPTY_OPERATION);
while (true) {
all_ws();
if (consume(ID, "getter")) ret.getter = true;
else if (consume(ID, "setter")) ret.setter = true;
- else if (consume(ID, "creator")) ret.creator = true;
else if (consume(ID, "deleter")) ret.deleter = true;
- else if (consume(ID, "legacycaller")) ret.legacycaller = true;
else break;
}
- if (ret.getter || ret.setter || ret.creator || ret.deleter || ret.legacycaller) {
+ if (ret.getter || ret.setter || ret.deleter) {
all_ws();
ret.idlType = return_type();
operation_rest(ret, store);
return ret;
}
- if (consume(ID, "static")) {
- ret["static"] = true;
- ret.idlType = return_type();
- operation_rest(ret, store);
- return ret;
- } else if (consume(ID, "stringifier")) {
- ret.stringifier = true; -
- all_ws();
- if (consume(OTHER, ";")) return ret;
- ret.idlType = return_type();
- operation_rest(ret, store);
- return ret;
- }
ret.idlType = return_type();
all_ws();
if (consume(ID, "iterator")) {
@@ -619,73 +599,39 @@
}
};
- var identifiers = function(arr) {
+ function static_member(store) {
+ all_ws(store, "pea");
+ if (!consume(ID, "static")) return;
+ all_ws();
+ return noninherited_attribute(store, "static") ||
+ regular_operation(store, "static") ||
+ error("No body in static member");
+ }
+
+ function stringifier(store) {
+ all_ws(store, "pea");
+ if (!consume(ID, "stringifier")) return;
+ all_ws();
+ if (consume(OTHER, ";")) {
+ return Object.assign({}, EMPTY_OPERATION, { stringifier: true });
+ }
+ return noninherited_attribute(store, "stringifier") ||
+ regular_operation(store, "stringifier") ||
+ error("Unterminated stringifier");
+ }
+
+ function identifiers(arr) {
while (true) {
all_ws();
if (consume(OTHER, ",")) {
all_ws();
- var name = consume(ID) || error("Trailing comma in identifiers list");
+ const name = consume(ID) || error("Trailing comma in identifiers list");
arr.push(name.value);
} else break;
}
};
- var serialiser = function(store) {
- all_ws(store, "pea");
- if (!consume(ID, "serializer")) return;
- var ret = { type: "serializer" };
- all_ws();
- if (consume(OTHER, "=")) {
- all_ws();
- if (consume(OTHER, "{")) {
- ret.patternMap = true;
- all_ws();
- var id = consume(ID);
- if (id && id.value === "getter") {
- ret.names = ["getter"];
- } else if (id && id.value === "inherit") {
- ret.names = ["inherit"];
- identifiers(ret.names);
- } else if (id) {
- ret.names = [id.value];
- identifiers(ret.names);
- } else {
- ret.names = [];
- }
- all_ws();
- consume(OTHER, "}") || error("Unterminated serializer pattern map");
- } else if (consume(OTHER, "[")) {
- ret.patternList = true;
- all_ws();
- var id = consume(ID);
- if (id && id.value === "getter") {
- ret.names = ["getter"];
- } else if (id) {
- ret.names = [id.value];
- identifiers(ret.names);
- } else {
- ret.names = [];
- }
- all_ws();
- consume(OTHER, "]") || error("Unterminated serializer pattern list");
- } else {
- var name = consume(ID) || error("Invalid serializer");
- ret.name = name.value;
- }
- all_ws();
- consume(OTHER, ";") || error("Unterminated serializer");
- return ret;
- } else if (consume(OTHER, ";")) {
- // noop, just parsing
- } else {
- ret.idlType = return_type();
- all_ws();
- ret.operation = operation_rest(null, store);
- }
- return ret;
- };
-
- var iterable_type = function() {
+ function iterable_type() {
if (consume(ID, "iterable")) return "iterable";
else if (consume(ID, "legacyiterable")) return "legacyiterable";
else if (consume(ID, "maplike")) return "maplike";
@@ -693,41 +639,41 @@
else return;
};
- var readonly_iterable_type = function() {
+ function readonly_iterable_type() {
if (consume(ID, "maplike")) return "maplike";
else if (consume(ID, "setlike")) return "setlike";
else return;
};
- var iterable = function(store) {
+ function iterable(store) {
all_ws(store, "pea");
- var grabbed = [],
- ret = { type: null, idlType: null, readonly: false };
+ const grabbed = [];
+ const ret = { type: null, idlType: null, readonly: false };
if (consume(ID, "readonly")) {
ret.readonly = true;
grabbed.push(last_token);
var w = all_ws();
if (w) grabbed.push(w);
}
- var consumeItType = ret.readonly ? readonly_iterable_type : iterable_type;
+ const consumeItType = ret.readonly ? readonly_iterable_type : iterable_type;
- var ittype = consumeItType();
+ const ittype = consumeItType();
if (!ittype) {
tokens = grabbed.concat(tokens);
return;
}
- var secondTypeRequired = ittype === "maplike";
- var secondTypeAllowed = secondTypeRequired || ittype === "iterable";
+ const secondTypeRequired = ittype === "maplike";
+ const secondTypeAllowed = secondTypeRequired || ittype === "iterable";
ret.type = ittype;
if (ret.type !== 'maplike' && ret.type !== 'setlike')
delete ret.readonly;
all_ws();
if (consume(OTHER, "<")) {
- ret.idlType = type_with_extended_attributes() || error("Error parsing " + ittype + " declaration");
+ ret.idlType = type_with_extended_attributes() || error(`Error parsing ${ittype} declaration`);
all_ws();
if (secondTypeAllowed) {
- var type2 = null;
+ let type2 = null;
if (consume(OTHER, ",")) {
all_ws();
type2 = type_with_extended_attributes();
@@ -736,29 +682,27 @@
if (type2)
ret.idlType = [ret.idlType, type2];
else if (secondTypeRequired)
- error("Missing second type argument in " + ittype + " declaration");
+ error(`Missing second type argument in ${ittype} declaration`);
}
- if (!consume(OTHER, ">")) error("Unterminated " + ittype + " declaration");
+ if (!consume(OTHER, ">")) error(`Unterminated ${ittype} declaration`);
all_ws();
- if (!consume(OTHER, ";")) error("Missing semicolon after " + ittype + " declaration");
+ if (!consume(OTHER, ";")) error(`Missing semicolon after ${ittype} declaration`);
} else
- error("Error parsing " + ittype + " declaration");
+ error(`Error parsing ${ittype} declaration`);
return ret;
};
- var interface_ = function(isPartial, store) {
- all_ws(isPartial ? null : store, "pea");
- if (!consume(ID, "interface")) return;
+ function interface_rest(isPartial, store) {
all_ws();
- var name = consume(ID) || error("No name for interface");
- var mems = [],
- ret = {
- type: "interface",
- name: name.value,
- partial: false,
- members: mems
- };
+ const name = consume(ID) || error("No name for interface");
+ const mems = [];
+ const ret = {
+ type: "interface",
+ name: isPartial ? name.value : sanitize_name(name.value, "interface"),
+ partial: false,
+ members: mems
+ };
if (!isPartial) ret.inheritance = inheritance() || null;
all_ws();
consume(OTHER, "{") || error("Bodyless interface");
@@ -769,17 +713,18 @@
consume(OTHER, ";") || error("Missing semicolon after interface");
return ret;
}
- var ea = extended_attrs(store ? mems : null);
+ const ea = extended_attrs(store ? mems : null);
all_ws();
- var cnt = const_(store ? mems : null);
+ const cnt = const_(store ? mems : null);
if (cnt) {
cnt.extAttrs = ea;
ret.members.push(cnt);
continue;
}
- var mem = (opt.allowNestedTypedefs && typedef(store ? mems : null)) ||
+ const mem = (opt.allowNestedTypedefs && typedef(store ? mems : null)) ||
+ static_member(store ? mems : null) ||
+ stringifier(store ? mems : null) ||
iterable(store ? mems : null) ||
- serialiser(store ? mems : null) ||
attribute(store ? mems : null) ||
operation(store ? mems : null) ||
error("Unknown member");
@@ -788,18 +733,64 @@
}
};
- var namespace = function(isPartial, store) {
+ function mixin_rest(isPartial, store) {
+ all_ws();
+ if (!consume(ID, "mixin")) return;
+ all_ws();
+ const name = consume(ID) || error("No name for interface mixin");
+ const mems = [];
+ const ret = {
+ type: "interface mixin",
+ name: isPartial ? name.value : sanitize_name(name.value, "interface mixin"),
+ partial: false,
+ members: mems
+ };
+ all_ws();
+ consume(OTHER, "{") || error("Bodyless interface mixin");
+ while (true) {
+ all_ws(store ? mems : null);
+ if (consume(OTHER, "}")) {
+ all_ws();
+ consume(OTHER, ";") || error("Missing semicolon after interface mixin");
+ return ret;
+ }
+ const ea = extended_attrs(store ? mems : null);
+ all_ws();
+ const cnt = const_(store ? mems : null);
+ if (cnt) {
+ cnt.extAttrs = ea;
+ ret.members.push(cnt);
+ continue;
+ }
+ const mem = stringifier(store ? mems : null) ||
+ noninherited_attribute(store ? mems : null) ||
+ regular_operation(store ? mems : null) ||
+ error("Unknown member");
+ mem.extAttrs = ea;
+ ret.members.push(mem);
+ }
+ }
+
+ function interface_(isPartial, store) {
+ all_ws(isPartial ? null : store, "pea");
+ if (!consume(ID, "interface")) return;
+ return mixin_rest(isPartial, store) ||
+ interface_rest(isPartial, store) ||
+ error("Interface has no proper body");
+ }
+
+ function namespace(isPartial, store) {
all_ws(isPartial ? null : store, "pea");
if (!consume(ID, "namespace")) return;
all_ws();
- var name = consume(ID) || error("No name for namespace");
- var mems = [],
- ret = {
- type: "namespace",
- name: name.value,
- partial: isPartial,
- members: mems
- };
+ const name = consume(ID) || error("No name for namespace");
+ const mems = [];
+ const ret = {
+ type: "namespace",
+ name: isPartial ? name.value : sanitize_name(name.value, "namespace"),
+ partial: isPartial,
+ members: mems
+ };
all_ws();
consume(OTHER, "{") || error("Bodyless namespace");
while (true) {
@@ -809,60 +800,57 @@
consume(OTHER, ";") || error("Missing semicolon after namespace");
return ret;
}
- var ea = extended_attrs(store ? mems : null);
+ const ea = extended_attrs(store ? mems : null);
all_ws();
- var mem = noninherited_attribute(store ? mems : null) ||
- nonspecial_operation(store ? mems : null) ||
+ const mem = noninherited_attribute(store ? mems : null) ||
+ regular_operation(store ? mems : null) ||
error("Unknown member");
mem.extAttrs = ea;
ret.members.push(mem);
}
}
- var noninherited_attribute = function(store) {
- var w = all_ws(store, "pea"),
- grabbed = [],
- ret = {
- type: "attribute",
- "static": false,
- stringifier: false,
- inherit: false,
- readonly: false
- };
+ function noninherited_attribute(store, prefix) {
+ const w = all_ws(store, "pea");
+ const grabbed = [];
+ const ret = {
+ type: "attribute",
+ "static": false,
+ stringifier: false,
+ inherit: false,
+ readonly: false
+ };
+ if (prefix) {
+ ret[prefix] = true;
+ }
if (w) grabbed.push(w);
if (consume(ID, "readonly")) {
ret.readonly = true;
grabbed.push(last_token);
- var w = all_ws();
+ const w = all_ws();
if (w) grabbed.push(w);
}
- var rest = attribute_rest(ret);
+ const rest = attribute_rest(ret);
if (!rest) {
tokens = grabbed.concat(tokens);
}
return rest;
}
-
- var nonspecial_operation = function(store) {
+
+ function regular_operation(store, prefix) {
all_ws(store, "pea");
- var ret = {
- type: "operation",
- getter: false,
- setter: false,
- creator: false,
- deleter: false,
- legacycaller: false,
- "static": false,
- stringifier: false
- };
+ const ret = Object.assign({}, EMPTY_OPERATION);
+ if (prefix) {
+ ret[prefix] = true;
+ }
ret.idlType = return_type();
return operation_rest(ret, store);
}
- var partial = function(store) {
+ function partial(store) {
all_ws(store, "pea");
if (!consume(ID, "partial")) return;
- var thing = dictionary(true, store) ||
+ const thing = dictionary(true, store) ||
interface_(true, store) ||
namespace(true, store) ||
error("Partial doesn't apply to anything");
@@ -870,18 +858,18 @@
return thing;
};
- var dictionary = function(isPartial, store) {
+ function dictionary(isPartial, store) {
all_ws(isPartial ? null : store, "pea");
if (!consume(ID, "dictionary")) return;
all_ws();
- var name = consume(ID) || error("No name for dictionary");
- var mems = [],
- ret = {
- type: "dictionary",
- name: name.value,
- partial: false,
- members: mems
- };
+ const name = consume(ID) || error("No name for dictionary");
+ const mems = [];
+ const ret = {
+ type: "dictionary",
+ name: isPartial ? name.value : sanitize_name(name.value, "dictionary"),
+ partial: false,
+ members: mems
+ };
if (!isPartial) ret.inheritance = inheritance() || null;
all_ws();
consume(OTHER, "{") || error("Bodyless dictionary");
@@ -892,15 +880,15 @@
consume(OTHER, ";") || error("Missing semicolon after dictionary");
return ret;
}
- var ea = extended_attrs(store ? mems : null);
+ const ea = extended_attrs(store ? mems : null);
all_ws(store ? mems : null, "pea");
- var required = consume(ID, "required");
- var typ = type_with_extended_attributes() || error("No type for dictionary member");
+ const required = consume(ID, "required");
+ const typ = type_with_extended_attributes() || error("No type for dictionary member");
all_ws();
- var name = consume(ID) || error("No name for dictionary member");
- var dflt = default_();
+ const name = consume(ID) || error("No name for dictionary member");
+ const dflt = default_();
if (required && dflt) error("Required member must not have a default");
- var member = {
+ const member = {
type: "field",
name: name.value,
required: !!required,
@@ -916,63 +904,20 @@
}
};
- var exception = function(store) {
- all_ws(store, "pea");
- if (!consume(ID, "exception")) return;
- all_ws();
- var name = consume(ID) || error("No name for exception");
- var mems = [],
- ret = {
- type: "exception",
- name: name.value,
- members: mems
- };
- ret.inheritance = inheritance() || null;
- all_ws();
- consume(OTHER, "{") || error("Bodyless exception");
- while (true) {
- all_ws(store ? mems : null);
- if (consume(OTHER, "}")) {
- all_ws();
- consume(OTHER, ";") || error("Missing semicolon after exception");
- return ret;
- }
- var ea = extended_attrs(store ? mems : null);
- all_ws(store ? mems : null, "pea");
- var cnt = const_();
- if (cnt) {
- cnt.extAttrs = ea;
- ret.members.push(cnt);
- } else {
- var typ = type();
- all_ws();
- var name = consume(ID);
- all_ws();
- if (!typ || !name || !consume(OTHER, ";")) error("Unknown member in exception body");
- ret.members.push({
- type: "field",
- name: name.value,
- idlType: typ,
- extAttrs: ea
- });
- }
- }
- };
-
- var enum_ = function(store) {
+ function enum_(store) {
all_ws(store, "pea");
if (!consume(ID, "enum")) return;
all_ws();
- var name = consume(ID) || error("No name for enum");
- var vals = [],
- ret = {
- type: "enum",
- name: name.value,
- values: vals
- };
+ const name = consume(ID) || error("No name for enum");
+ const vals = [];
+ const ret = {
+ type: "enum",
+ name: sanitize_name(name.value, "enum"),
+ values: vals
+ };
all_ws();
consume(OTHER, "{") || error("No curly for enum");
- var saw_comma = false;
+ let saw_comma = false;
while (true) {
all_ws(store ? vals : null);
if (consume(OTHER, "}")) {
@@ -980,8 +925,9 @@
consume(OTHER, ";") || error("No semicolon after enum");
return ret;
}
- var val = consume(STR) || error("Unexpected value in enum");
- ret.values.push(val.value.replace(/"/g, ""));
+ const val = consume(STR) || error("Unexpected value in enum");
+ val.value = val.value.replace(/"/g, "");
+ ret.values.push(val);
all_ws(store ? vals : null);
if (consume(OTHER, ",")) {
if (store) vals.push({ type: "," });
@@ -993,34 +939,34 @@
}
};
- var typedef = function(store) {
+ function typedef(store) {
all_ws(store, "pea");
if (!consume(ID, "typedef")) return;
- var ret = {
+ const ret = {
type: "typedef"
};
all_ws();
ret.idlType = type_with_extended_attributes() || error("No type in typedef");
all_ws();
- var name = consume(ID) || error("No name in typedef");
- ret.name = name.value;
+ const name = consume(ID) || error("No name in typedef");
+ ret.name = sanitize_name(name.value, "typedef");
all_ws();
consume(OTHER, ";") || error("Unterminated typedef");
return ret;
};
- var implements_ = function(store) {
+ function implements_(store) {
all_ws(store, "pea");
- var target = consume(ID);
+ const target = consume(ID);
if (!target) return;
- var w = all_ws();
+ const w = all_ws();
if (consume(ID, "implements")) {
- var ret = {
+ const ret = {
type: "implements",
target: target.value
};
all_ws();
- var imp = consume(ID) || error("Incomplete implements statement");
+ const imp = consume(ID) || error("Incomplete implements statement");
ret["implements"] = imp.value;
all_ws();
consume(OTHER, ";") || error("No terminating ; for implements statement");
@@ -1032,24 +978,47 @@
}
};
- var definition = function(store) {
+ function includes(store) {
+ all_ws(store, "pea");
+ const target = consume(ID);
+ if (!target) return;
+ const w = all_ws();
+ if (consume(ID, "includes")) {
+ const ret = {
+ type: "includes",
+ target: target.value
+ };
+ all_ws();
+ const imp = consume(ID) || error("Incomplete includes statement");
+ ret["includes"] = imp.value;
+ all_ws();
+ consume(OTHER, ";") || error("No terminating ; for includes statement");
+ return ret;
+ } else {
+ // rollback
+ tokens.unshift(w);
+ tokens.unshift(target);
+ }
+ };
+
+ function definition(store) {
return callback(store) ||
interface_(false, store) ||
partial(store) ||
dictionary(false, store) ||
- exception(store) ||
enum_(store) ||
typedef(store) ||
implements_(store) ||
+ includes(store) ||
namespace(false, store);
};
- var definitions = function(store) {
+ function definitions(store) {
if (!tokens.length) return [];
- var defs = [];
+ const defs = [];
while (true) {
- var ea = extended_attrs(store ? defs : null),
- def = definition(store ? defs : null);
+ const ea = extended_attrs(store ? defs : null);
+ const def = definition(store ? defs : null);
if (!def) {
if (ea.length) error("Stray extended attributes");
break;
@@ -1059,15 +1028,15 @@
}
return defs;
};
- var res = definitions(opt.ws);
+ const res = definitions(opt.ws);
if (tokens.length) error("Unrecognised tokens");
return res;
};
- var obj = {
- parse: function(str, opt) {
+ const obj = {
+ parse(str, opt) {
if (!opt) opt = {};
- var tokens = tokenise(str);
+ const tokens = tokenise(str);
return parse(tokens, opt);
}
};
@@ -1075,10 +1044,8 @@
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
module.exports = obj;
} else if (typeof define === 'function' && define.amd) {
- define([], function() {
- return obj;
- });
+ define([], () => obj);
} else {
(self || window).WebIDL2 = obj;
}
-}());
+})();
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/lib/writer.js b/tests/wpt/web-platform-tests/resources/webidl2/lib/writer.js
index f7c79f82893..5e30e707e13 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/lib/writer.js
+++ b/tests/wpt/web-platform-tests/resources/webidl2/lib/writer.js
@@ -191,21 +191,6 @@
}
return ret + "};";
};
- var serializer = function(it) {
- var ret = "serializer";
- if (it.name) {
- ret += " = " + it.name + ";";
- } else if (it.patternList) {
- ret += " = [ " + it.names.join(", ") + " ];";
- } else if (it.patternMap) {
- ret += " = { " + it.names.join(", ") + " };";
- } else if (it.operation) {
- ret += " " + operation(it);
- } else {
- ret += ";";
- }
- return ret;
- };
var iterable = function(it) {
return "iterable<" + (it.idlType instanceof Array ? it.idlType.map(type).join(", ") : type(it.idlType)) + ">;";
};
@@ -241,7 +226,6 @@
"implements": implements_,
callback: callback,
"enum": enum_,
- serializer: serializer,
iterable: iterable,
legacyiterable: legacyiterable,
maplike: maplike,
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/package-lock.json b/tests/wpt/web-platform-tests/resources/webidl2/package-lock.json
new file mode 100644
index 00000000000..53528713e57
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/package-lock.json
@@ -0,0 +1,647 @@
+{
+ "name": "webidl2",
+ "version": "4.2.0",
+ "lockfileVersion": 1,
+ "dependencies": {
+ "ansi-regex": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz",
+ "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz",
+ "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=",
+ "dev": true
+ },
+ "arr-diff": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
+ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
+ "dev": true
+ },
+ "arr-flatten": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+ "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
+ "dev": true
+ },
+ "array-unique": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
+ "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
+ "dev": true
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
+ "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
+ "dev": true
+ },
+ "braces": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
+ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
+ "dev": true
+ },
+ "browser-stdout": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz",
+ "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz",
+ "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=",
+ "dev": true
+ },
+ "color-convert": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz",
+ "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=",
+ "dev": true
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "commander": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
+ "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "debug": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz",
+ "integrity": "sha1-vFlryr52F/Edn6FTYe3tVgi4SZs=",
+ "dev": true
+ },
+ "diff": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz",
+ "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=",
+ "dev": true
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "expand-brackets": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
+ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
+ "dev": true
+ },
+ "expand-range": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
+ "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
+ "dev": true
+ },
+ "expect": {
+ "version": "21.2.1",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-21.2.1.tgz",
+ "integrity": "sha512-orfQQqFRTX0jH7znRIGi8ZMR8kTNpXklTTz8+HGTpmTKZo3Occ6JNB5FXMb8cRuiiC/GyDqsr30zUa66ACYlYw==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "dev": true
+ }
+ }
+ },
+ "extglob": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
+ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
+ "dev": true
+ },
+ "filename-regex": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
+ "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=",
+ "dev": true
+ },
+ "fill-range": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz",
+ "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=",
+ "dev": true
+ },
+ "for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+ "dev": true
+ },
+ "for-own": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
+ "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=",
+ "dev": true
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+ "dev": true
+ },
+ "glob": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz",
+ "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=",
+ "dev": true
+ },
+ "glob-base": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
+ "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=",
+ "dev": true
+ },
+ "glob-parent": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
+ "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
+ "dev": true
+ },
+ "graceful-readlink": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
+ "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=",
+ "dev": true
+ },
+ "growl": {
+ "version": "1.9.2",
+ "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz",
+ "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=",
+ "dev": true
+ },
+ "has-ansi": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz",
+ "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
+ "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "dev": true
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+ "dev": true
+ },
+ "is-buffer": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz",
+ "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=",
+ "dev": true
+ },
+ "is-dotfile": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
+ "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=",
+ "dev": true
+ },
+ "is-equal-shallow": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
+ "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=",
+ "dev": true
+ },
+ "is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+ "dev": true
+ },
+ "is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+ "dev": true
+ },
+ "is-number": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
+ "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
+ "dev": true
+ },
+ "is-posix-bracket": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
+ "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=",
+ "dev": true
+ },
+ "is-primitive": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
+ "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=",
+ "dev": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+ "dev": true
+ },
+ "isobject": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+ "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+ "dev": true
+ },
+ "jest-diff": {
+ "version": "21.2.1",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-21.2.1.tgz",
+ "integrity": "sha512-E5fu6r7PvvPr5qAWE1RaUwIh/k6Zx/3OOkZ4rk5dBJkEWRrUuSgbMt2EO8IUTPTd6DOqU3LW6uTIwX5FRvXoFA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "dev": true
+ },
+ "chalk": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz",
+ "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz",
+ "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==",
+ "dev": true
+ }
+ }
+ },
+ "jest-get-type": {
+ "version": "21.2.0",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-21.2.0.tgz",
+ "integrity": "sha512-y2fFw3C+D0yjNSDp7ab1kcd6NUYfy3waPTlD8yWkAtiocJdBRQqNoRqVfMNxgj+IjT0V5cBIHJO0z9vuSSZ43Q==",
+ "dev": true
+ },
+ "jest-matcher-utils": {
+ "version": "21.2.1",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-21.2.1.tgz",
+ "integrity": "sha512-kn56My+sekD43dwQPrXBl9Zn9tAqwoy25xxe7/iY4u+mG8P3ALj5IK7MLHZ4Mi3xW7uWVCjGY8cm4PqgbsqMCg==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "dev": true
+ },
+ "chalk": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz",
+ "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz",
+ "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==",
+ "dev": true
+ }
+ }
+ },
+ "jest-message-util": {
+ "version": "21.2.1",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-21.2.1.tgz",
+ "integrity": "sha512-EbC1X2n0t9IdeMECJn2BOg7buOGivCvVNjqKMXTzQOu7uIfLml+keUfCALDh8o4rbtndIeyGU8/BKfoTr/LVDQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "dev": true
+ },
+ "chalk": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz",
+ "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz",
+ "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==",
+ "dev": true
+ }
+ }
+ },
+ "jest-regex-util": {
+ "version": "21.2.0",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-21.2.0.tgz",
+ "integrity": "sha512-BKQ1F83EQy0d9Jen/mcVX7D+lUt2tthhK/2gDWRgLDJRNOdRgSp1iVqFxP8EN1ARuypvDflRfPzYT8fQnoBQFQ==",
+ "dev": true
+ },
+ "json3": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz",
+ "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=",
+ "dev": true
+ },
+ "jsondiffpatch": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/jsondiffpatch/-/jsondiffpatch-0.2.4.tgz",
+ "integrity": "sha1-1LbFOz/H2htLkcHCrsi5MrdRHVw=",
+ "dev": true
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true
+ },
+ "lodash._baseassign": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz",
+ "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=",
+ "dev": true
+ },
+ "lodash._basecopy": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz",
+ "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=",
+ "dev": true
+ },
+ "lodash._basecreate": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz",
+ "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=",
+ "dev": true
+ },
+ "lodash._getnative": {
+ "version": "3.9.1",
+ "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
+ "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=",
+ "dev": true
+ },
+ "lodash._isiterateecall": {
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz",
+ "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=",
+ "dev": true
+ },
+ "lodash.create": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz",
+ "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=",
+ "dev": true
+ },
+ "lodash.isarguments": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
+ "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=",
+ "dev": true
+ },
+ "lodash.isarray": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz",
+ "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=",
+ "dev": true
+ },
+ "lodash.keys": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz",
+ "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=",
+ "dev": true
+ },
+ "micromatch": {
+ "version": "2.3.11",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
+ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
+ "dev": true
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+ "dev": true
+ },
+ "mocha": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.4.1.tgz",
+ "integrity": "sha1-o4ArSqOBk0yss43nDPdxYh2o+a8=",
+ "dev": true,
+ "dependencies": {
+ "supports-color": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz",
+ "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=",
+ "dev": true
+ }
+ }
+ },
+ "ms": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
+ "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
+ "dev": true
+ },
+ "normalize-path": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "dev": true
+ },
+ "object.omit": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
+ "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=",
+ "dev": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dev": true
+ },
+ "parse-glob": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
+ "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=",
+ "dev": true
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "dev": true
+ },
+ "preserve": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
+ "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
+ "dev": true
+ },
+ "pretty-format": {
+ "version": "21.2.1",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-21.2.1.tgz",
+ "integrity": "sha512-ZdWPGYAnYfcVP8yKA3zFjCn8s4/17TeYH28MXuC8vTp0o21eXjbFGcOAXZEaDaOFJjc3h2qa7HQNHNshhvoh2A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "dev": true
+ }
+ }
+ },
+ "randomatic": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz",
+ "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==",
+ "dev": true,
+ "dependencies": {
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "dev": true,
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true
+ }
+ }
+ },
+ "kind-of": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+ "dev": true
+ }
+ }
+ },
+ "regex-cache": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
+ "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==",
+ "dev": true
+ },
+ "remove-trailing-separator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
+ "dev": true
+ },
+ "repeat-element": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz",
+ "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=",
+ "dev": true
+ },
+ "repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
+ "dev": true
+ },
+ "slash": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
+ "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz",
+ "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz",
+ "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=",
+ "dev": true
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ }
+ }
+}
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/package.json b/tests/wpt/web-platform-tests/resources/webidl2/package.json
index 02b2a9d9b16..d7b8a421241 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/package.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/package.json
@@ -1,17 +1,18 @@
{
"name": "webidl2",
"description": "A WebIDL Parser",
- "version": "2.4.0",
- "author": "Robin Berjon <robin@berjon.com>",
- "license": "MIT",
+ "version": "8.1.0",
+ "contributors": [
+ "Robin Berjon <robin@berjon.com> (https://berjon.com)",
+ "Marcos Caceres <marcos@marcosc.com> (https://marcosc.com)",
+ "Kagami Sascha Rosylight <saschaplas@outlook.com>"
+ ],
+ "license": "W3C",
"dependencies": {},
"devDependencies": {
- "mocha": "3.2.0",
- "expect": "1.20.2",
- "underscore": "1.8.3",
- "jsondiffpatch": "0.2.4",
- "benchmark": "*",
- "microtime": "2.1.3"
+ "expect": "21.2.1",
+ "jsondiffpatch": "0.2.5",
+ "mocha": "4.0.1"
},
"scripts": {
"test": "mocha"
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid.js b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid.js
index b8ab3a1866d..548f0ea4b3d 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid.js
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid.js
@@ -1,42 +1,40 @@
-
// NOTES:
// - the errors actually still need to be reviewed to check that they
// are fully correct interpretations of the IDLs
-var wp = process.env.JSCOV ? require("../lib-cov/webidl2") : require("../lib/webidl2")
-, expect = require("expect")
-, pth = require("path")
-, fs = require("fs")
-;
-describe("Parses all of the invalid IDLs to check that they blow up correctly", function () {
- var dir = pth.join(__dirname, "invalid/idl")
- , skip = {}
- , idls = fs.readdirSync(dir)
- .filter(function (it) { return (/\.w?idl$/).test(it) && !skip[it]; })
- .map(function (it) { return pth.join(dir, it); })
- , errors = idls.map(function (it) { return pth.join(__dirname, "invalid", "json", pth.basename(it).replace(/\.w?idl/, ".json")); })
- ;
+"use strict";
+
+const wp = require("../lib/webidl2");
+const expect = require("expect");
+const pth = require("path");
+const fs = require("fs");
+
+describe("Parses all of the invalid IDLs to check that they blow up correctly", () => {
+ const dir = pth.join(__dirname, "invalid/idl");
+ const skip = {};
+ const idls = fs.readdirSync(dir)
+ .filter(it => (/\.w?idl$/).test(it) && !skip[it])
+ .map(it => pth.join(dir, it));
+ const errors = idls.map(it => pth.join(__dirname, "invalid", "json", pth.basename(it).replace(/\.w?idl/, ".json")));
- for (var i = 0, n = idls.length; i < n; i++) {
- var idl = idls[i], error = JSON.parse(fs.readFileSync(errors[i], "utf8"));
- var func = (function (idl, err) {
- return function () {
- var error;
- try {
- var ast = wp.parse(fs.readFileSync(idl, "utf8"));
- console.log(JSON.stringify(ast, null, 4));
- }
- catch (e) {
- error = e;
- }
- finally {
- expect(error).toExist();
- expect(error.message).toEqual(err.message);
- expect(error.line).toEqual(err.line);
- }
+ for (let i = 0, n = idls.length; i < n; i++) {
+ const idl = idls[i];
+ const err = JSON.parse(fs.readFileSync(errors[i], "utf8"));
- };
- }(idl, error));
- it("should produce the right error for " + idl, func);
- }
+ it(`should produce the right error for ${idl}`, () => {
+ let error;
+ try {
+ var ast = wp.parse(fs.readFileSync(idl, "utf8"));
+ console.log(JSON.stringify(ast, null, 4));
+ }
+ catch (e) {
+ error = e;
+ }
+ finally {
+ expect(error).toBeTruthy();
+ expect(error.message).toEqual(err.message);
+ expect(error.line).toEqual(err.line);
+ }
+ });
+ }
});
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/array.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/array.widl
new file mode 100644
index 00000000000..58a8618ab64
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/array.widl
@@ -0,0 +1,6 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+// T[] is removed by https://github.com/heycam/webidl/commit/079cbb861a99e9e857a3f2a169c0beeb49cd020a
+[Constructor]
+interface LotteryResults {
+ readonly attribute unsigned short[][] numbers;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/caller.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/caller.widl
new file mode 100644
index 00000000000..26fedc33f94
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/caller.widl
@@ -0,0 +1,7 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+// legacycallers are removed by https://github.com/heycam/webidl/pull/412
+
+interface NumberQuadrupler {
+ // This operation simply returns four times the given number x.
+ legacycaller float compute(float x);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/duplicate.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/duplicate.widl
new file mode 100644
index 00000000000..4916af34273
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/duplicate.widl
@@ -0,0 +1,5 @@
+typedef int Test;
+
+interface Test {
+ void foo();
+};
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/exception.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/exception.widl
new file mode 100644
index 00000000000..a0ea2e47e20
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/exception.widl
@@ -0,0 +1,6 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+// IDL exceptions are removed by https://github.com/heycam/webidl/commit/50e172ec079db073c3724c9beac1b576fb5dbc47
+
+exception SomeException {
+};
+
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/maplike-1type.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/maplike-1type.widl
index 33c274b8b9a..efb5c14ffd6 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/maplike-1type.widl
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/maplike-1type.widl
@@ -1,3 +1,3 @@
interface MapLikeOneType {
- maplike<long>;
+ maplike<long>;
} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/promise-with-extended-attribute.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/promise-with-extended-attribute.widl
new file mode 100644
index 00000000000..0ce171fec33
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/promise-with-extended-attribute.widl
@@ -0,0 +1,3 @@
+interface Foo {
+ Promise<[XAttr] DOMString> foo(any param);
+};
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/readonly-iterable.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/readonly-iterable.widl
index fc4ae2be908..6057aa1feba 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/readonly-iterable.widl
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/readonly-iterable.widl
@@ -1,3 +1,3 @@
interface ReadonlyIterable {
- readonly iterable<long>;
+ readonly iterable<long>;
} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/record-key-with-extended-attribute.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/record-key-with-extended-attribute.widl
new file mode 100644
index 00000000000..c11eb7414b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/record-key-with-extended-attribute.widl
@@ -0,0 +1,3 @@
+interface Foo {
+ void foo(record<[XAttr] DOMString, any> param);
+};
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/setlike-2types.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/setlike-2types.widl
index 1ecae22c010..c2681bc75f1 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/setlike-2types.widl
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/setlike-2types.widl
@@ -1,3 +1,3 @@
interface SetLikeTwoTypes {
- setlike<long, long>;
+ setlike<long, long>;
} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/setter-creator.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/setter-creator.widl
new file mode 100644
index 00000000000..a70b26774d7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/setter-creator.widl
@@ -0,0 +1,4 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface OrderedMap {
+ setter creator void set(DOMString name, any value);
+};
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/special-omittable.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/special-omittable.widl
index bdfbfa70973..dd0c1b18589 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/special-omittable.widl
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/special-omittable.widl
@@ -1,5 +1,5 @@
// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
-// omittable is no longer a recognized keywoard as of 20110905
+// omittable is no longer a recognized keyword as of 20110905
interface Dictionary {
readonly attribute unsigned long propertyCount;
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/typedef-nested.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/typedef-nested.widl
index 106f30b8f72..dfd377bf932 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/typedef-nested.widl
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/typedef-nested.widl
@@ -19,4 +19,4 @@
boolean allPointsWithinBounds(PointSequence ps);
};
- typedef [Clamp] octet value; \ No newline at end of file
+ typedef [Clamp] octet value; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/array.json b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/array.json
new file mode 100644
index 00000000000..30b377fc71c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/array.json
@@ -0,0 +1,4 @@
+{
+ "message": "No name in attribute",
+ "line": 5
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/caller.json b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/caller.json
new file mode 100644
index 00000000000..79b8ecac04f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/caller.json
@@ -0,0 +1,4 @@
+{
+ "message": "Invalid operation",
+ "line": 6
+}
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/duplicate.json b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/duplicate.json
new file mode 100644
index 00000000000..cef335875c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/duplicate.json
@@ -0,0 +1,4 @@
+{
+ "message": "The name \"Test\" of type \"typedef\" is already seen",
+ "line": 3
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/exception.json b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/exception.json
new file mode 100644
index 00000000000..f52cda13837
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/exception.json
@@ -0,0 +1,4 @@
+{
+ "message": "Unrecognised tokens",
+ "line": 4
+}
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/promise-with-extended-attribute.json b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/promise-with-extended-attribute.json
new file mode 100644
index 00000000000..e9623ce7cc8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/promise-with-extended-attribute.json
@@ -0,0 +1,4 @@
+{
+ "message": "Promise type cannot have extended attribute",
+ "line": 2
+}
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/record-key-with-extended-attribute.json b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/record-key-with-extended-attribute.json
new file mode 100644
index 00000000000..3945825c318
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/record-key-with-extended-attribute.json
@@ -0,0 +1,4 @@
+{
+ "message": "Record key cannot have extended attribute",
+ "line": 2
+}
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/setter-creator.json b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/setter-creator.json
new file mode 100644
index 00000000000..07b9f1f4bc4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/setter-creator.json
@@ -0,0 +1,4 @@
+{
+ "message": "Invalid operation",
+ "line": 3
+}
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax.js b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax.js
index 3b343e4229d..0838f350cd9 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax.js
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax.js
@@ -1,41 +1,39 @@
+"use strict";
-var wp = process.env.JSCOV ? require("../lib-cov/webidl2") : require("../lib/webidl2")
-, expect = require("expect")
-, pth = require("path")
-, fs = require("fs")
-, jdp = require("jsondiffpatch")
-, debug = true
-;
-describe("Parses all of the IDLs to produce the correct ASTs", function () {
- var dir = pth.join(__dirname, "syntax/idl")
- , skip = {} // use if we have a broken test
- , idls = fs.readdirSync(dir)
- .filter(function (it) { return (/\.widl$/).test(it) && !skip[it]; })
- .map(function (it) { return pth.join(dir, it); })
- , jsons = idls.map(function (it) { return pth.join(__dirname, "syntax/json", pth.basename(it).replace(".widl", ".json")); })
- ;
+const wp = require("../lib/webidl2");
+const expect = require("expect");
+const pth = require("path");
+const fs = require("fs");
+const jdp = require("jsondiffpatch");
+const debug = true;
- for (var i = 0, n = idls.length; i < n; i++) {
- var idl = idls[i], json = jsons[i];
+describe("Parses all of the IDLs to produce the correct ASTs", () => {
+ const dir = pth.join(__dirname, "syntax/idl");
+ const skip = {}; // use if we have a broken test
+ const idls = fs.readdirSync(dir)
+ .filter(it => (/\.widl$/).test(it) && !skip[it])
+ .map(it => pth.join(dir, it));
+ const jsons = idls.map(it => pth.join(__dirname, "syntax/json", pth.basename(it).replace(".widl", ".json")));
- var func = (function (idl, json) {
- return function () {
- try {
- var optFile = pth.join(__dirname, "syntax/opt", pth.basename(json));
- var opt = undefined;
- if (fs.existsSync(optFile))
- opt = JSON.parse(fs.readFileSync(optFile, "utf8"));
- var diff = jdp.diff(JSON.parse(fs.readFileSync(json, "utf8")),
- wp.parse(fs.readFileSync(idl, "utf8"), opt));
- if (diff && debug) console.log(JSON.stringify(diff, null, 4));
- expect(diff).toBe(undefined);
- }
- catch (e) {
- console.log(e.toString());
- throw e;
- }
- };
- }(idl, json));
- it("should produce the same AST for " + idl, func);
- }
+ for (let i = 0, n = idls.length; i < n; i++) {
+ const idl = idls[i];
+ const json = jsons[i];
+
+ it(`should produce the same AST for ${idl}`, () => {
+ try {
+ const optFile = pth.join(__dirname, "syntax/opt", pth.basename(json));
+ let opt = undefined;
+ if (fs.existsSync(optFile))
+ opt = JSON.parse(fs.readFileSync(optFile, "utf8"));
+ const diff = jdp.diff(JSON.parse(fs.readFileSync(json, "utf8")),
+ wp.parse(fs.readFileSync(idl, "utf8").replace(/\r\n/g, "\n"), opt));
+ if (diff && debug) console.log(JSON.stringify(diff, null, 4));
+ expect(diff).toBe(undefined);
+ }
+ catch (e) {
+ console.log(e.toString());
+ throw e;
+ }
+ });
+ }
});
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/array.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/array.widl
deleted file mode 100644
index 22e21fb6564..00000000000
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/array.widl
+++ /dev/null
@@ -1,5 +0,0 @@
-// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
-[Constructor]
-interface LotteryResults {
- readonly attribute unsigned short[][] numbers;
-}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/attributes.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/attributes.widl
index 7e1d691cbe2..1d3d5c8e834 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/attributes.widl
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/attributes.widl
@@ -1,9 +1,4 @@
// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
-exception InvalidName {
- DOMString reason;
-};
-
-exception NoSuchPet { };
interface Person {
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/caller.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/caller.widl
deleted file mode 100644
index 92acb1c0176..00000000000
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/caller.widl
+++ /dev/null
@@ -1,5 +0,0 @@
-// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
-interface NumberQuadrupler {
- // This operation simply returns four times the given number x.
- legacycaller float compute(float x);
-}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/constants.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/constants.widl
index 5e28ae9c116..043b022b646 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/constants.widl
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/constants.widl
@@ -8,11 +8,4 @@ interface Util {
const unrestricted float sobig = Infinity;
const unrestricted double minusonedividedbyzero = -Infinity;
const short notanumber = NaN;
-};
-
-exception Error {
- const short ERR_UNKNOWN = 0;
- const short ERR_OUT_OF_MEMORY = 1;
-
- short errorCode;
}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/equivalent-decl.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/equivalent-decl.widl
index 6b3e0eda284..6ffeb3c20a1 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/equivalent-decl.widl
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/equivalent-decl.widl
@@ -7,7 +7,7 @@ interface Dictionary {
};
-interface Dictionary {
+interface Dictionary2 {
readonly attribute unsigned long propertyCount;
float getProperty(DOMString propertyName);
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/exception-inheritance.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/exception-inheritance.widl
deleted file mode 100644
index 258fdeba6f4..00000000000
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/exception-inheritance.widl
+++ /dev/null
@@ -1,7 +0,0 @@
-// from http://lists.w3.org/Archives/Public/public-script-coord/2010OctDec/0112.html
- exception DOMException {
- unsigned short code;
- };
-
- exception HierarchyRequestError : DOMException { };
- exception NoModificationAllowedError : DOMException { }; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/exception.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/exception.widl
deleted file mode 100644
index f4b6ae29e10..00000000000
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/exception.widl
+++ /dev/null
@@ -1,8 +0,0 @@
-// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
-interface Dahut {
- attribute DOMString type;
-};
-
-exception SomeException {
-};
-
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/extended-attributes.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/extended-attributes.widl
index c1df79e142d..a49463b3d76 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/extended-attributes.widl
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/extended-attributes.widl
@@ -2,10 +2,22 @@
[Global=(Worker,ServiceWorker), Exposed=ServiceWorker]
interface ServiceWorkerGlobalScope : WorkerGlobalScope {
-
+
};
// Conformance with ExtendedAttributeList grammar in http://www.w3.org/TR/WebIDL/#idl-extended-attributes
// Section 3.11
[IntAttr=0, FloatAttr=3.14, StringAttr="abc"]
interface IdInterface {};
+
+// Extracted from http://www.w3.org/TR/2016/REC-WebIDL-1-20161215/#Constructor on 2017-5-18 with whitespace differences
+[
+ Constructor,
+ Constructor(double radius)
+]
+interface Circle {
+ attribute double r;
+ attribute double cx;
+ attribute double cy;
+ readonly attribute double circumference;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/generic.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/generic.widl
index 02b64572a42..12a1a3f62b0 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/generic.widl
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/generic.widl
@@ -1,12 +1,12 @@
interface Foo {
Promise<ResponsePromise<sequence<DOMString?>>> bar();
- readonly attribute Promise<DOMString>[] baz;
+ readonly attribute Promise<DOMString> baz;
};
// Extracted from https://slightlyoff.github.io/ServiceWorker/spec/service_worker/ on 2014-05-08
interface ServiceWorkerClients {
- Promise<Client[]?> getServiced();
+ Promise<Client?> getServiced();
Promise<any> reloadAll();
};
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/identifier-qualified-names.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/identifier-qualified-names.widl
index 33893d4c644..986d0bf78c6 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/identifier-qualified-names.widl
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/identifier-qualified-names.widl
@@ -3,18 +3,6 @@
// Qualified name: "::framework::number"
typedef float number;
- // Exception identifier: "FrameworkException"
- // Qualified name: "::framework::FrameworkException"
- exception FrameworkException {
-
- // Constant identifier: "ERR_NOT_FOUND"
- // Qualified name: "::framework::FrameworkException::ERR_NOT_FOUND"
- const long ERR_NOT_FOUND = 1;
-
- // Exception field identifier: "code"
- long code;
- };
-
// Interface identifier: "System"
// Qualified name: "::framework::System"
interface System {
@@ -27,7 +15,7 @@
getter DOMString (DOMString keyName);
};
-
+
// Interface identifier: "TextField"
// Qualified name: "::framework::gui::TextField"
interface TextField {
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/indexed-properties.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/indexed-properties.widl
index acf0ed3bf84..4b8aa9e353f 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/indexed-properties.widl
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/indexed-properties.widl
@@ -7,6 +7,6 @@ interface OrderedMap {
deleter void removeByIndex(unsigned long index);
getter any get(DOMString name);
- setter creator void set(DOMString name, any value);
+ setter void set(DOMString name, any value);
deleter void remove(DOMString name);
-}; \ No newline at end of file
+};
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/iterable.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/iterable.widl
index c7dfafa4daa..7f726f926fd 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/iterable.widl
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/iterable.widl
@@ -1,7 +1,11 @@
interface IterableOne {
- iterable<long>;
+ iterable<long>;
};
interface IterableTwo {
- iterable<short, double?>;
+ iterable<short, double?>;
+};
+
+interface IterableThree {
+ iterable<[XAttr] long>;
}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/legacyiterable.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/legacyiterable.widl
index eafa7cf0445..9e1e9c52744 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/legacyiterable.widl
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/legacyiterable.widl
@@ -1,3 +1,3 @@
interface LegacyIterable {
- legacyiterable<long>;
+ legacyiterable<long>;
};
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/linecomment.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/linecomment.widl
new file mode 100644
index 00000000000..5d31bdb62c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/linecomment.widl
@@ -0,0 +1,2 @@
+/* first */
+// second
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/maplike.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/maplike.widl
index 7b79b388802..437e381fef7 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/maplike.widl
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/maplike.widl
@@ -1,7 +1,13 @@
interface MapLike {
- maplike<long, float>;
+ maplike<long, float>;
};
interface ReadOnlyMapLike {
- readonly maplike<long, float>;
+ readonly maplike<long, float>;
+};
+
+// Extracted from https://heycam.github.io/webidl/#idl-type-extended-attribute-associated-with on 2017-07-01
+
+interface I {
+ maplike<[XAttr2] DOMString, [XAttr3] long>;
};
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/mixin.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/mixin.widl
new file mode 100644
index 00000000000..7c37a6ee420
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/mixin.widl
@@ -0,0 +1,12 @@
+// Extracted from https://heycam.github.io/webidl/#using-mixins-and-partials on 2017-11-02
+
+interface mixin GlobalCrypto {
+ readonly attribute Crypto crypto;
+};
+
+Window includes GlobalCrypto;
+WorkerGlobalScope includes GlobalCrypto;
+
+partial interface mixin WindowOrWorkerGlobalScope {
+ readonly attribute Crypto crypto;
+};
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/overloading.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/overloading.widl
index ef1288a8877..52d8d15c1a1 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/overloading.widl
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/overloading.widl
@@ -12,9 +12,9 @@ interface C {
void f(B x);
};
-interface A {
+interface D {
/* f1 */ void f(DOMString a);
/* f2 */ void f([AllowAny] DOMString a, DOMString b, float... c);
/* f3 */ void f();
/* f4 */ void f(long a, DOMString b, optional DOMString c, float... d);
-}; \ No newline at end of file
+};
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/primitives.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/primitives.widl
index 92939601a1a..a91455ee192 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/primitives.widl
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/primitives.widl
@@ -9,11 +9,11 @@ interface Primitives {
attribute long long bigbig;
attribute unsigned long long bigbigpositive;
attribute float real;
- attribute double bigreal;
+ attribute double bigreal;
attribute unrestricted float realwithinfinity;
- attribute unrestricted double bigrealwithinfinity;
- attribute DOMString string;
- attribute ByteString bytes;
+ attribute unrestricted double bigrealwithinfinity;
+ attribute DOMString string;
+ attribute ByteString bytes;
attribute Date date;
attribute RegExp regexp;
-}; \ No newline at end of file
+};
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/record.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/record.widl
index 6cdedb219be..c8d9343142c 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/record.widl
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/record.widl
@@ -6,3 +6,7 @@ interface Foo {
// Make sure record can still be registered as a type.
record baz();
};
+
+interface Bar {
+ record<DOMString, [XAttr] float> bar();
+};
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/reg-operations.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/reg-operations.widl
index 13997cb1d12..338c8d42763 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/reg-operations.widl
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/reg-operations.widl
@@ -4,8 +4,6 @@ interface Dimensions {
attribute unsigned long height;
};
-exception NoPointerDevice { };
-
interface Button {
// An operation that takes no arguments, returns a boolean
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/sequence.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/sequence.widl
index 6ba0d390d25..d31056cf076 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/sequence.widl
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/sequence.widl
@@ -9,4 +9,10 @@ interface Canvas {
// Make sure sequence can still be registered as a type.
interface Foo {
sequence bar();
-}; \ No newline at end of file
+};
+
+// Extracted from https://heycam.github.io/webidl/#idl-type-extended-attribute-associated-with on 2017-07-01
+
+interface I {
+ void f1(sequence<[XAttr] long> arg);
+};
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/serializer.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/serializer.widl
deleted file mode 100644
index 6f6ccd0e8d5..00000000000
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/serializer.widl
+++ /dev/null
@@ -1,64 +0,0 @@
-interface Transaction {
- readonly attribute Account from;
- readonly attribute Account to;
- readonly attribute float amount;
- readonly attribute DOMString description;
- readonly attribute unsigned long number;
-
- serializer;
-};
-
-interface Account {
- attribute DOMString name;
- attribute unsigned long number;
- serializer DOMString serialize();
-};
-
-interface Transaction2 {
- readonly attribute Account2 from;
- readonly attribute Account2 to;
- readonly attribute float amount;
- readonly attribute DOMString description;
- readonly attribute unsigned long number;
-
- serializer = { from, to, amount, description };
-};
-
-interface Account2 {
- attribute DOMString name;
- attribute unsigned long number;
- serializer = number;
-};
-
-interface Account3 {
- attribute DOMString name;
- attribute unsigned long number;
-
- serializer = { attribute };
-};
-
-interface Account4 {
- getter object getItem(unsigned long index);
- serializer = { getter };
-};
-
-interface Account5 : Account {
- attribute DOMString secondname;
- serializer = { inherit, secondname };
-};
-
-interface Account6 : Account {
- attribute DOMString secondname;
- serializer = { inherit, attribute };
-};
-
-interface Account7 {
- attribute DOMString name;
- attribute unsigned long number;
- serializer = [ name, number ];
-};
-
-interface Account8 {
- getter object getItem(unsigned long index);
- serializer = [ getter ];
-}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/setlike.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/setlike.widl
index 890e8e5a759..4512f286b59 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/setlike.widl
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/setlike.widl
@@ -1,7 +1,11 @@
interface SetLike {
- setlike<long>;
+ setlike<long>;
};
interface ReadOnlySetLike {
- readonly setlike<long>;
+ readonly setlike<long>;
+};
+
+interface SetLikeExt {
+ setlike<[XAttr] long>;
};
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/stringifier.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/stringifier.widl
index 4eb483d9b53..c45277ea8db 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/stringifier.widl
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/stringifier.widl
@@ -3,6 +3,6 @@ interface A {
stringifier DOMString ();
};
-interface A {
+interface B {
stringifier;
}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/typesuffixes.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/typesuffixes.widl
index 95e31c16902..beaaa872600 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/typesuffixes.widl
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/typesuffixes.widl
@@ -1,3 +1,3 @@
interface Suffixes {
- void test(sequence<DOMString[]?>? foo);
+ void test(sequence<DOMString?>? foo);
};
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/allowany.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/allowany.json
index 8abc7f9e092..ee898d68296 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/allowany.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/allowany.json
@@ -8,16 +8,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -29,16 +26,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -52,7 +46,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "B"
},
@@ -65,16 +58,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -86,14 +76,15 @@
"extAttrs": [
{
"name": "AllowAny",
- "arguments": null
+ "arguments": null,
+ "type": "extended-attribute",
+ "rhs": null
}
],
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -106,4 +97,4 @@
"inheritance": null,
"extAttrs": []
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/array.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/array.json
deleted file mode 100644
index 39afaf6c8eb..00000000000
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/array.json
+++ /dev/null
@@ -1,34 +0,0 @@
-[
- {
- "type": "interface",
- "name": "LotteryResults",
- "partial": false,
- "members": [
- {
- "type": "attribute",
- "static": false,
- "stringifier": false,
- "inherit": false,
- "readonly": true,
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": 2,
- "nullableArray": [false, false],
- "union": false,
- "idlType": "unsigned short"
- },
- "name": "numbers",
- "extAttrs": []
- }
- ],
- "inheritance": null,
- "extAttrs": [
- {
- "name": "Constructor",
- "arguments": null
- }
- ]
- }
-] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/attributes.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/attributes.json
index cdf46b0ecc2..86fe9d52dec 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/attributes.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/attributes.json
@@ -1,33 +1,5 @@
[
{
- "type": "exception",
- "name": "InvalidName",
- "members": [
- {
- "type": "field",
- "name": "reason",
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "DOMString"
- },
- "extAttrs": []
- }
- ],
- "inheritance": null,
- "extAttrs": []
- },
- {
- "type": "exception",
- "name": "NoSuchPet",
- "members": [],
- "inheritance": null,
- "extAttrs": []
- },
- {
"type": "interface",
"name": "Person",
"partial": false,
@@ -42,7 +14,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned short"
},
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/callback.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/callback.json
index 43a51751046..5301c40d754 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/callback.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/callback.json
@@ -6,7 +6,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -19,7 +18,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -37,16 +35,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -60,7 +55,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -80,7 +74,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "boolean"
},
@@ -93,7 +86,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "any"
},
@@ -107,7 +99,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "any"
},
@@ -116,4 +107,4 @@
],
"extAttrs": []
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/caller.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/caller.json
deleted file mode 100644
index a0fb5e396a5..00000000000
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/caller.json
+++ /dev/null
@@ -1,47 +0,0 @@
-[
- {
- "type": "interface",
- "name": "NumberQuadrupler",
- "partial": false,
- "members": [
- {
- "type": "operation",
- "getter": false,
- "setter": false,
- "creator": false,
- "deleter": false,
- "legacycaller": true,
- "static": false,
- "stringifier": false,
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "float"
- },
- "name": "compute",
- "arguments": [
- {
- "optional": false,
- "variadic": false,
- "extAttrs": [],
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "float"
- },
- "name": "x"
- }
- ],
- "extAttrs": []
- }
- ],
- "inheritance": null,
- "extAttrs": []
- }
-] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/constants.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/constants.json
index 0fe6e92afc3..75222866443 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/constants.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/constants.json
@@ -22,7 +22,7 @@
"name": "negative",
"value": {
"type": "number",
- "value": -1
+ "value": "-1"
},
"extAttrs": []
},
@@ -33,7 +33,7 @@
"name": "LF",
"value": {
"type": "number",
- "value": 10
+ "value": "10"
},
"extAttrs": []
},
@@ -44,7 +44,7 @@
"name": "BIT_MASK",
"value": {
"type": "number",
- "value": 64512
+ "value": "0x0000fc00"
},
"extAttrs": []
},
@@ -55,7 +55,7 @@
"name": "AVOGADRO",
"value": {
"type": "number",
- "value": 6.022e+23
+ "value": "6.022e23"
},
"extAttrs": []
},
@@ -94,48 +94,5 @@
],
"inheritance": null,
"extAttrs": []
- },
- {
- "type": "exception",
- "name": "Error",
- "members": [
- {
- "type": "const",
- "nullable": false,
- "idlType": "short",
- "name": "ERR_UNKNOWN",
- "value": {
- "type": "number",
- "value": 0
- },
- "extAttrs": []
- },
- {
- "type": "const",
- "nullable": false,
- "idlType": "short",
- "name": "ERR_OUT_OF_MEMORY",
- "value": {
- "type": "number",
- "value": 1
- },
- "extAttrs": []
- },
- {
- "type": "field",
- "name": "errorCode",
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "short"
- },
- "extAttrs": []
- }
- ],
- "inheritance": null,
- "extAttrs": []
}
] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/constructor.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/constructor.json
index e5944f32ee8..ee55ef03e14 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/constructor.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/constructor.json
@@ -14,7 +14,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -31,7 +30,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -48,7 +46,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -65,7 +62,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -77,7 +73,9 @@
"extAttrs": [
{
"name": "Constructor",
- "arguments": null
+ "arguments": null,
+ "type": "extended-attribute",
+ "rhs": null
},
{
"name": "Constructor",
@@ -90,14 +88,15 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
"name": "radius"
}
- ]
+ ],
+ "type": "extended-attribute",
+ "rhs": null
}
]
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/dictionary-inherits.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/dictionary-inherits.json
index fbb2338a8df..ef30b1ab76d 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/dictionary-inherits.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/dictionary-inherits.json
@@ -12,7 +12,6 @@
"sequence": false,
"generic": null,
"nullable": true,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -30,7 +29,6 @@
"sequence": false,
"generic": null,
"nullable": true,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -47,7 +45,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Point"
},
@@ -70,7 +67,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/dictionary.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/dictionary.json
index a7c89caab23..28494ce437c 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/dictionary.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/dictionary.json
@@ -12,7 +12,6 @@
"sequence": false,
"generic": null,
"nullable": true,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -30,7 +29,6 @@
"sequence": false,
"generic": null,
"nullable": true,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -47,7 +45,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Point"
},
@@ -61,13 +58,11 @@
"sequence": true,
"generic": "sequence",
"nullable": false,
- "array": false,
"union": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "long"
}
@@ -86,7 +81,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "long"
},
@@ -109,7 +103,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "long"
},
@@ -123,7 +116,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "long"
},
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/enum.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/enum.json
index 196ee4e6405..88a608ba632 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/enum.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/enum.json
@@ -3,9 +3,9 @@
"type": "enum",
"name": "MealType",
"values": [
- "rice",
- "noodles",
- "other"
+ { "type": "string", "value": "rice" },
+ { "type": "string", "value": "noodles" },
+ { "type": "string", "value": "other" }
],
"extAttrs": []
},
@@ -24,7 +24,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "MealType"
},
@@ -41,7 +40,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -52,16 +50,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -75,7 +70,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "MealType"
},
@@ -89,7 +83,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -106,10 +99,10 @@
"type": "enum",
"name": "AltMealType",
"values": [
- "rice",
- "noodles",
- "other"
+ { "type": "string", "value": "rice" },
+ { "type": "string", "value": "noodles" },
+ { "type": "string", "value": "other" }
],
"extAttrs": []
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/equivalent-decl.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/equivalent-decl.json
index 55a787fdcf0..7ef08bc595f 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/equivalent-decl.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/equivalent-decl.json
@@ -14,7 +14,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned long"
},
@@ -25,16 +24,13 @@
"type": "operation",
"getter": true,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -48,7 +44,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -61,16 +56,13 @@
"type": "operation",
"getter": false,
"setter": true,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -84,7 +76,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -98,7 +89,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -113,7 +103,7 @@
},
{
"type": "interface",
- "name": "Dictionary",
+ "name": "Dictionary2",
"partial": false,
"members": [
{
@@ -126,7 +116,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned long"
},
@@ -137,16 +126,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -160,7 +146,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -173,16 +158,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -196,7 +178,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -210,7 +191,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -223,16 +203,13 @@
"type": "operation",
"getter": true,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -246,7 +223,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -259,16 +235,13 @@
"type": "operation",
"getter": false,
"setter": true,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -282,7 +255,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -296,7 +268,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -309,4 +280,4 @@
"inheritance": null,
"extAttrs": []
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/exception-inheritance.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/exception-inheritance.json
index f4dc68699a6..4a76b982856 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/exception-inheritance.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/exception-inheritance.json
@@ -10,7 +10,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned short"
},
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/exception.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/exception.json
deleted file mode 100644
index 3f16de828ac..00000000000
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/exception.json
+++ /dev/null
@@ -1,35 +0,0 @@
-[
- {
- "type": "interface",
- "name": "Dahut",
- "partial": false,
- "members": [
- {
- "type": "attribute",
- "static": false,
- "stringifier": false,
- "inherit": false,
- "readonly": false,
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "DOMString"
- },
- "name": "type",
- "extAttrs": []
- }
- ],
- "inheritance": null,
- "extAttrs": []
- },
- {
- "type": "exception",
- "name": "SomeException",
- "members": [],
- "inheritance": null,
- "extAttrs": []
- }
-] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/extended-attributes.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/extended-attributes.json
index 3b5a3b2e22b..6526e2a3599 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/extended-attributes.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/extended-attributes.json
@@ -9,6 +9,7 @@
{
"name": "Global",
"arguments": null,
+ "type": "extended-attribute",
"rhs": {
"type": "identifier-list",
"value": [
@@ -20,6 +21,7 @@
{
"name": "Exposed",
"arguments": null,
+ "type": "extended-attribute",
"rhs": {
"type": "identifier",
"value": "ServiceWorker"
@@ -37,6 +39,7 @@
{
"name": "IntAttr",
"arguments": null,
+ "type": "extended-attribute",
"rhs": {
"type": "integer",
"value": "0"
@@ -45,6 +48,7 @@
{
"name": "FloatAttr",
"arguments": null,
+ "type": "extended-attribute",
"rhs": {
"type": "float",
"value": "3.14"
@@ -53,11 +57,112 @@
{
"name": "StringAttr",
"arguments": null,
+ "type": "extended-attribute",
"rhs": {
"type": "string",
"value": "\"abc\""
}
}
]
+ },
+ {
+ "type": "interface",
+ "name": "Circle",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "union": false,
+ "idlType": "double"
+ },
+ "name": "r",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "union": false,
+ "idlType": "double"
+ },
+ "name": "cx",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "union": false,
+ "idlType": "double"
+ },
+ "name": "cy",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "union": false,
+ "idlType": "double"
+ },
+ "name": "circumference",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": [
+ {
+ "name": "Constructor",
+ "arguments": null,
+ "type": "extended-attribute",
+ "rhs": null
+ },
+ {
+ "name": "Constructor",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "union": false,
+ "idlType": "double"
+ },
+ "name": "radius"
+ }
+ ],
+ "type": "extended-attribute",
+ "rhs": null
+ }
+ ]
}
]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/generic.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/generic.json
index e39654ffdb2..214ddd8e994 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/generic.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/generic.json
@@ -8,34 +8,28 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": "Promise",
"nullable": false,
- "array": false,
"union": false,
"idlType": {
"sequence": false,
"generic": "ResponsePromise",
"nullable": false,
- "array": false,
"union": false,
"idlType": {
"sequence": true,
"generic": "sequence",
"nullable": false,
- "array": false,
"union": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": true,
- "array": false,
"union": false,
"idlType": "DOMString"
}
@@ -56,14 +50,11 @@
"sequence": false,
"generic": "Promise",
"nullable": false,
- "array": 1,
- "nullableArray": [false],
"union": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
}
@@ -84,23 +75,18 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": "Promise",
"nullable": false,
- "array": false,
"union": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": true,
- "nullableArray": [false],
- "array": 1,
"union": false,
"idlType": "Client"
}
@@ -113,22 +99,18 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": "Promise",
"nullable": false,
- "array": false,
"union": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "any"
}
@@ -150,22 +132,18 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": "ResponsePromise",
"nullable": false,
- "array": false,
"union": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "any"
}
@@ -178,4 +156,4 @@
"inheritance": "Event",
"extAttrs": []
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/getter-setter.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/getter-setter.json
index 94d20d594db..6268a532d55 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/getter-setter.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/getter-setter.json
@@ -14,7 +14,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned long"
},
@@ -25,16 +24,13 @@
"type": "operation",
"getter": true,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -48,7 +44,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -61,16 +56,13 @@
"type": "operation",
"getter": false,
"setter": true,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -84,7 +76,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -98,7 +89,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -111,4 +101,4 @@
"inheritance": null,
"extAttrs": []
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/identifier-qualified-names.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/identifier-qualified-names.json
index d87ea3b5f36..11568f8cfd8 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/identifier-qualified-names.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/identifier-qualified-names.json
@@ -5,7 +5,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -13,38 +12,6 @@
"extAttrs": []
},
{
- "type": "exception",
- "name": "FrameworkException",
- "members": [
- {
- "type": "const",
- "nullable": false,
- "idlType": "long",
- "name": "ERR_NOT_FOUND",
- "value": {
- "type": "number",
- "value": 1
- },
- "extAttrs": []
- },
- {
- "type": "field",
- "name": "code",
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "long"
- },
- "extAttrs": []
- }
- ],
- "inheritance": null,
- "extAttrs": []
- },
- {
"type": "interface",
"name": "System",
"partial": false,
@@ -53,16 +20,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "object"
},
@@ -76,7 +40,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -89,16 +52,13 @@
"type": "operation",
"getter": true,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -112,7 +72,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -140,7 +99,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "boolean"
},
@@ -157,7 +115,6 @@
"sequence": false,
"generic": null,
"nullable": true,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -177,16 +134,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -200,7 +154,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "object"
},
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/implements.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/implements.json
index fa00e337426..fba05427808 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/implements.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/implements.json
@@ -14,7 +14,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned short"
},
@@ -34,16 +33,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -57,7 +53,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -71,7 +66,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "EventListener"
},
@@ -85,7 +79,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "boolean"
},
@@ -104,4 +97,4 @@
"implements": "EventTarget",
"extAttrs": []
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/indexed-properties.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/indexed-properties.json
index 23cc4ab1023..2676c0efab3 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/indexed-properties.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/indexed-properties.json
@@ -14,7 +14,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned long"
},
@@ -25,16 +24,13 @@
"type": "operation",
"getter": true,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "any"
},
@@ -48,7 +44,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned long"
},
@@ -61,16 +56,13 @@
"type": "operation",
"getter": false,
"setter": true,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -84,7 +76,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned long"
},
@@ -98,7 +89,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "any"
},
@@ -111,16 +101,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": true,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -134,7 +121,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned long"
},
@@ -147,16 +133,13 @@
"type": "operation",
"getter": true,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "any"
},
@@ -170,7 +153,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -183,16 +165,13 @@
"type": "operation",
"getter": false,
"setter": true,
- "creator": true,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -206,7 +185,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -220,7 +198,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "any"
},
@@ -233,16 +210,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": true,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -256,7 +230,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -269,4 +242,4 @@
"inheritance": null,
"extAttrs": []
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/inherits-getter.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/inherits-getter.json
index 468e3caef71..ba6bafdf391 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/inherits-getter.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/inherits-getter.json
@@ -14,7 +14,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -40,7 +39,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned short"
},
@@ -57,7 +55,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/interface-inherits.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/interface-inherits.json
index eee07cd1dec..e78c1cce865 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/interface-inherits.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/interface-inherits.json
@@ -14,7 +14,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -40,7 +39,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Dog"
},
@@ -66,7 +64,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Human"
},
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/iterable.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/iterable.json
index 3e38991dd9d..1e92307dad5 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/iterable.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/iterable.json
@@ -10,7 +10,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "long"
},
@@ -32,7 +31,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "short"
},
@@ -40,7 +38,6 @@
"sequence": false,
"generic": null,
"nullable": true,
- "array": false,
"union": false,
"idlType": "double"
}
@@ -50,6 +47,34 @@
],
"inheritance": null,
"extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "IterableThree",
+ "partial": false,
+ "members": [
+ {
+ "type": "iterable",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "union": false,
+ "idlType": "long",
+ "extAttrs": [
+ {
+ "name": "XAttr",
+ "arguments": null,
+ "type": "extended-attribute",
+ "rhs": null
+ }
+ ]
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
}
]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/iterator.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/iterator.json
index cc3c9ec505d..f9605b83450 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/iterator.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/iterator.json
@@ -8,16 +8,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Session"
},
@@ -31,7 +28,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -50,7 +46,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned long"
},
@@ -61,16 +56,13 @@
"type": "iterator",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Session"
},
@@ -95,7 +87,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -115,16 +106,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Session2"
},
@@ -138,7 +126,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -157,7 +144,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned long"
},
@@ -168,16 +154,13 @@
"type": "iterator",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Session2"
},
@@ -203,7 +186,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -229,7 +211,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned long"
},
@@ -249,16 +230,13 @@
"type": "iterator",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Node"
},
@@ -278,16 +256,13 @@
"type": "iterator",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Node"
},
@@ -298,4 +273,4 @@
"inheritance": null,
"extAttrs": []
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/legacyiterable.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/legacyiterable.json
index e63f99de43f..059ccc11312 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/legacyiterable.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/legacyiterable.json
@@ -10,7 +10,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "long"
},
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/linecomment.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/linecomment.json
new file mode 100644
index 00000000000..11fd14f494b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/linecomment.json
@@ -0,0 +1,14 @@
+[
+ {
+ "type": "multiline-comment",
+ "value": " first "
+ },
+ {
+ "type": "ws",
+ "value": "\n"
+ },
+ {
+ "type": "line-comment",
+ "value": " second"
+ }
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/maplike.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/maplike.json
index 017d8b3f3ec..97e76d5841a 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/maplike.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/maplike.json
@@ -11,7 +11,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "long"
},
@@ -19,7 +18,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
}
@@ -43,7 +41,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "long"
},
@@ -51,7 +48,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
}
@@ -62,6 +58,52 @@
],
"inheritance": null,
"extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "I",
+ "partial": false,
+ "members": [
+ {
+ "type": "maplike",
+ "idlType": [
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "union": false,
+ "idlType": "DOMString",
+ "extAttrs": [
+ {
+ "name": "XAttr2",
+ "arguments": null,
+ "type": "extended-attribute",
+ "rhs": null
+ }
+ ]
+ },
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "union": false,
+ "idlType": "long",
+ "extAttrs": [
+ {
+ "name": "XAttr3",
+ "arguments": null,
+ "type": "extended-attribute",
+ "rhs": null
+ }
+ ]
+ }
+ ],
+ "readonly": false,
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
}
]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/mixin.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/mixin.json
new file mode 100644
index 00000000000..a2afae318dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/mixin.json
@@ -0,0 +1,62 @@
+[
+ {
+ "type": "interface mixin",
+ "name": "GlobalCrypto",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "union": false,
+ "idlType": "Crypto"
+ },
+ "name": "crypto",
+ "extAttrs": []
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "includes",
+ "target": "Window",
+ "includes": "GlobalCrypto",
+ "extAttrs": []
+ },
+ {
+ "type": "includes",
+ "target": "WorkerGlobalScope",
+ "includes": "GlobalCrypto",
+ "extAttrs": []
+ },
+ {
+ "type": "interface mixin",
+ "name": "WindowOrWorkerGlobalScope",
+ "partial": true,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "union": false,
+ "idlType": "Crypto"
+ },
+ "name": "crypto",
+ "extAttrs": []
+ }
+ ],
+ "extAttrs": []
+ }
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/namedconstructor.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/namedconstructor.json
index a947a64a4e2..cee163069d1 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/namedconstructor.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/namedconstructor.json
@@ -9,6 +9,7 @@
{
"name": "NamedConstructor",
"arguments": null,
+ "type": "extended-attribute",
"rhs": {
"type": "identifier",
"value": "Audio"
@@ -25,13 +26,13 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
"name": "src"
}
],
+ "type": "extended-attribute",
"rhs": {
"type": "identifier",
"value": "Audio"
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/namespace.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/namespace.json
index 7c7ba771e1b..8ee7796553e 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/namespace.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/namespace.json
@@ -14,7 +14,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Vector"
},
@@ -25,16 +24,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "double"
},
@@ -48,7 +44,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Vector"
},
@@ -62,7 +57,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Vector"
},
@@ -75,16 +69,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Vector"
},
@@ -98,7 +89,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Vector"
},
@@ -112,7 +102,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Vector"
},
@@ -131,4 +120,4 @@
"members": [],
"extAttrs": []
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nointerfaceobject.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nointerfaceobject.json
index 90f0d63c82e..85987e82de3 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nointerfaceobject.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nointerfaceobject.json
@@ -8,16 +8,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "any"
},
@@ -31,7 +28,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned long"
},
@@ -45,8 +41,10 @@
"extAttrs": [
{
"name": "NoInterfaceObject",
- "arguments": null
+ "arguments": null,
+ "type": "extended-attribute",
+ "rhs": null
}
]
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nullable.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nullable.json
index 300442f0d46..2c83c3dad58 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nullable.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nullable.json
@@ -34,7 +34,6 @@
"sequence": false,
"generic": null,
"nullable": true,
- "array": false,
"union": false,
"idlType": "DOMString"
},
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nullableobjects.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nullableobjects.json
index 40f7db0c1c9..2c875607262 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nullableobjects.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nullableobjects.json
@@ -24,16 +24,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -47,7 +44,6 @@
"sequence": false,
"generic": null,
"nullable": true,
- "array": false,
"union": false,
"idlType": "A"
},
@@ -60,16 +56,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -83,7 +76,6 @@
"sequence": false,
"generic": null,
"nullable": true,
- "array": false,
"union": false,
"idlType": "B"
},
@@ -96,4 +88,4 @@
"inheritance": null,
"extAttrs": []
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/operation-optional-arg.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/operation-optional-arg.json
index 6ca32576b7a..7588d63475f 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/operation-optional-arg.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/operation-optional-arg.json
@@ -8,16 +8,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "object"
},
@@ -31,7 +28,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -45,7 +41,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -59,7 +54,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -73,14 +67,13 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
"name": "alpha",
"default": {
"type": "number",
- "value": 3.5
+ "value": "3.5"
}
}
],
@@ -90,4 +83,4 @@
"inheritance": null,
"extAttrs": []
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/overloading.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/overloading.json
index c3baa439623..8d7e8e286cb 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/overloading.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/overloading.json
@@ -24,16 +24,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -47,7 +44,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "A"
},
@@ -60,16 +56,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -83,7 +76,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "B"
},
@@ -98,23 +90,20 @@
},
{
"type": "interface",
- "name": "A",
+ "name": "D",
"partial": false,
"members": [
{
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -128,7 +117,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -141,16 +129,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -162,14 +147,15 @@
"extAttrs": [
{
"name": "AllowAny",
- "arguments": null
+ "arguments": null,
+ "type": "extended-attribute",
+ "rhs": null
}
],
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -183,7 +169,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -197,7 +182,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -210,16 +194,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -231,16 +212,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -254,7 +232,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "long"
},
@@ -268,7 +245,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -282,7 +258,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -296,7 +271,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -309,4 +283,4 @@
"inheritance": null,
"extAttrs": []
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/overridebuiltins.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/overridebuiltins.json
index 9e2f795e2ae..4ded17c3103 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/overridebuiltins.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/overridebuiltins.json
@@ -14,7 +14,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned long"
},
@@ -25,16 +24,13 @@
"type": "operation",
"getter": true,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -48,7 +44,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -62,8 +57,10 @@
"extAttrs": [
{
"name": "OverrideBuiltins",
- "arguments": null
+ "arguments": null,
+ "type": "extended-attribute",
+ "rhs": null
}
]
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/partial-interface.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/partial-interface.json
index 53c65a453bd..e95af2baa15 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/partial-interface.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/partial-interface.json
@@ -14,7 +14,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -40,7 +39,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/primitives.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/primitives.json
index 7160c2a4ce0..7568542f957 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/primitives.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/primitives.json
@@ -14,7 +14,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "boolean"
},
@@ -31,7 +30,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "byte"
},
@@ -48,7 +46,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "octet"
},
@@ -65,7 +62,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "short"
},
@@ -82,7 +78,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned short"
},
@@ -99,7 +94,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "long"
},
@@ -116,7 +110,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned long"
},
@@ -133,7 +126,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "long long"
},
@@ -150,7 +142,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned long long"
},
@@ -167,7 +158,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -184,7 +174,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "double"
},
@@ -201,7 +190,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unrestricted float"
},
@@ -218,7 +206,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unrestricted double"
},
@@ -235,7 +222,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -252,7 +238,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "ByteString"
},
@@ -269,7 +254,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Date"
},
@@ -286,7 +270,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "RegExp"
},
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/prototyperoot.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/prototyperoot.json
index 666798d94cf..c75f00ed3e8 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/prototyperoot.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/prototyperoot.json
@@ -14,7 +14,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned short"
},
@@ -26,8 +25,10 @@
"extAttrs": [
{
"name": "PrototypeRoot",
- "arguments": null
+ "arguments": null,
+ "type": "extended-attribute",
+ "rhs": null
}
]
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/putforwards.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/putforwards.json
index bd5e619cac5..1b0a7b6b974 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/putforwards.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/putforwards.json
@@ -14,7 +14,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Name"
},
@@ -23,6 +22,7 @@
{
"name": "PutForwards",
"arguments": null,
+ "type": "extended-attribute",
"rhs": {
"type": "identifier",
"value": "full"
@@ -40,7 +40,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned short"
},
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/record.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/record.json
index d2a21a4acd9..339ae08a39f 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/record.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/record.json
@@ -8,16 +8,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -31,20 +28,17 @@
"sequence": true,
"generic": "sequence",
"nullable": false,
- "array": false,
"union": false,
"idlType": {
"sequence": false,
"generic": "record",
"nullable": false,
- "array": false,
"union": false,
"idlType": [
{
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "ByteString"
},
@@ -52,7 +46,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "any"
}
@@ -68,23 +61,19 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": "record",
"nullable": false,
- "array": false,
"union": false,
"idlType": [
{
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -92,14 +81,12 @@
"sequence": false,
"generic": null,
"nullable": true,
- "array": false,
"union": true,
"idlType": [
{
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -107,7 +94,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
}
@@ -123,16 +109,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "record"
},
@@ -154,14 +137,12 @@
"sequence": false,
"generic": "record",
"nullable": false,
- "array": false,
"union": false,
"idlType": [
{
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "USVString"
},
@@ -169,7 +150,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "USVString"
}
@@ -177,8 +157,60 @@
},
"name": "init"
}
- ]
+ ],
+ "type": "extended-attribute",
+ "rhs": null
}
]
+ },
+ {
+ "type": "interface",
+ "name": "Bar",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "deleter": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": "record",
+ "nullable": false,
+ "union": false,
+ "idlType": [
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "union": false,
+ "idlType": "float",
+ "extAttrs": [
+ {
+ "name": "XAttr",
+ "arguments": null,
+ "type": "extended-attribute",
+ "rhs": null
+ }
+ ]
+ }
+ ]
+ },
+ "name": "bar",
+ "arguments": [],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
}
]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/reg-operations.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/reg-operations.json
index c827fff03b6..c1c13c74f1b 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/reg-operations.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/reg-operations.json
@@ -14,7 +14,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned long"
},
@@ -31,7 +30,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned long"
},
@@ -43,13 +41,6 @@
"extAttrs": []
},
{
- "type": "exception",
- "name": "NoPointerDevice",
- "members": [],
- "inheritance": null,
- "extAttrs": []
- },
- {
"type": "interface",
"name": "Button",
"partial": false,
@@ -58,16 +49,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "boolean"
},
@@ -79,16 +67,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -102,7 +87,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Dimensions"
},
@@ -115,16 +99,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -138,7 +119,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned long"
},
@@ -152,7 +132,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned long"
},
@@ -165,4 +144,4 @@
"inheritance": null,
"extAttrs": []
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/replaceable.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/replaceable.json
index 4d25f3d9317..f53009b4baa 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/replaceable.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/replaceable.json
@@ -14,7 +14,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned long"
},
@@ -22,7 +21,9 @@
"extAttrs": [
{
"name": "Replaceable",
- "arguments": null
+ "arguments": null,
+ "type": "extended-attribute",
+ "rhs": null
}
]
},
@@ -30,16 +31,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -51,4 +49,4 @@
"inheritance": null,
"extAttrs": []
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/sequence.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/sequence.json
index 7ddd402b402..79821181a19 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/sequence.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/sequence.json
@@ -8,16 +8,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -31,13 +28,11 @@
"sequence": true,
"generic": "sequence",
"nullable": false,
- "array": false,
"union": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
}
@@ -51,22 +46,18 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": true,
"generic": "sequence",
"nullable": false,
- "array": false,
"union": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
}
@@ -89,16 +80,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "sequence"
},
@@ -109,5 +97,61 @@
],
"inheritance": null,
"extAttrs": []
- }
-] \ No newline at end of file
+ },
+
+ {
+ "type": "interface",
+ "name": "I",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "deleter": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "f1",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": true,
+ "generic": "sequence",
+ "nullable": false,
+ "union": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "union": false,
+ "idlType": "long",
+ "extAttrs": [
+ {
+ "name": "XAttr",
+ "arguments": null,
+ "type": "extended-attribute",
+ "rhs": null
+ }
+ ]
+ }
+ },
+ "name": "arg"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/serializer.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/serializer.json
deleted file mode 100644
index 79b501fcbc4..00000000000
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/serializer.json
+++ /dev/null
@@ -1,591 +0,0 @@
-[
- {
- "type": "interface",
- "name": "Transaction",
- "partial": false,
- "members": [
- {
- "type": "attribute",
- "static": false,
- "stringifier": false,
- "inherit": false,
- "readonly": true,
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "Account"
- },
- "name": "from",
- "extAttrs": []
- },
- {
- "type": "attribute",
- "static": false,
- "stringifier": false,
- "inherit": false,
- "readonly": true,
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "Account"
- },
- "name": "to",
- "extAttrs": []
- },
- {
- "type": "attribute",
- "static": false,
- "stringifier": false,
- "inherit": false,
- "readonly": true,
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "float"
- },
- "name": "amount",
- "extAttrs": []
- },
- {
- "type": "attribute",
- "static": false,
- "stringifier": false,
- "inherit": false,
- "readonly": true,
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "DOMString"
- },
- "name": "description",
- "extAttrs": []
- },
- {
- "type": "attribute",
- "static": false,
- "stringifier": false,
- "inherit": false,
- "readonly": true,
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "unsigned long"
- },
- "name": "number",
- "extAttrs": []
- },
- {
- "type": "serializer",
- "extAttrs": []
- }
- ],
- "inheritance": null,
- "extAttrs": []
- },
- {
- "type": "interface",
- "name": "Account",
- "partial": false,
- "members": [
- {
- "type": "attribute",
- "static": false,
- "stringifier": false,
- "inherit": false,
- "readonly": false,
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "DOMString"
- },
- "name": "name",
- "extAttrs": []
- },
- {
- "type": "attribute",
- "static": false,
- "stringifier": false,
- "inherit": false,
- "readonly": false,
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "unsigned long"
- },
- "name": "number",
- "extAttrs": []
- },
- {
- "type": "serializer",
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "DOMString"
- },
- "operation": {
- "name": "serialize",
- "arguments": []
- },
- "extAttrs": []
- }
- ],
- "inheritance": null,
- "extAttrs": []
- },
- {
- "type": "interface",
- "name": "Transaction2",
- "partial": false,
- "members": [
- {
- "type": "attribute",
- "static": false,
- "stringifier": false,
- "inherit": false,
- "readonly": true,
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "Account2"
- },
- "name": "from",
- "extAttrs": []
- },
- {
- "type": "attribute",
- "static": false,
- "stringifier": false,
- "inherit": false,
- "readonly": true,
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "Account2"
- },
- "name": "to",
- "extAttrs": []
- },
- {
- "type": "attribute",
- "static": false,
- "stringifier": false,
- "inherit": false,
- "readonly": true,
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "float"
- },
- "name": "amount",
- "extAttrs": []
- },
- {
- "type": "attribute",
- "static": false,
- "stringifier": false,
- "inherit": false,
- "readonly": true,
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "DOMString"
- },
- "name": "description",
- "extAttrs": []
- },
- {
- "type": "attribute",
- "static": false,
- "stringifier": false,
- "inherit": false,
- "readonly": true,
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "unsigned long"
- },
- "name": "number",
- "extAttrs": []
- },
- {
- "type": "serializer",
- "patternMap": true,
- "names": [
- "from",
- "to",
- "amount",
- "description"
- ],
- "extAttrs": []
- }
- ],
- "inheritance": null,
- "extAttrs": []
- },
- {
- "type": "interface",
- "name": "Account2",
- "partial": false,
- "members": [
- {
- "type": "attribute",
- "static": false,
- "stringifier": false,
- "inherit": false,
- "readonly": false,
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "DOMString"
- },
- "name": "name",
- "extAttrs": []
- },
- {
- "type": "attribute",
- "static": false,
- "stringifier": false,
- "inherit": false,
- "readonly": false,
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "unsigned long"
- },
- "name": "number",
- "extAttrs": []
- },
- {
- "type": "serializer",
- "name": "number",
- "extAttrs": []
- }
- ],
- "inheritance": null,
- "extAttrs": []
- },
- {
- "type": "interface",
- "name": "Account3",
- "partial": false,
- "members": [
- {
- "type": "attribute",
- "static": false,
- "stringifier": false,
- "inherit": false,
- "readonly": false,
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "DOMString"
- },
- "name": "name",
- "extAttrs": []
- },
- {
- "type": "attribute",
- "static": false,
- "stringifier": false,
- "inherit": false,
- "readonly": false,
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "unsigned long"
- },
- "name": "number",
- "extAttrs": []
- },
- {
- "type": "serializer",
- "patternMap": true,
- "names": [
- "attribute"
- ],
- "extAttrs": []
- }
- ],
- "inheritance": null,
- "extAttrs": []
- },
- {
- "type": "interface",
- "name": "Account4",
- "partial": false,
- "members": [
- {
- "type": "operation",
- "getter": true,
- "setter": false,
- "creator": false,
- "deleter": false,
- "legacycaller": false,
- "static": false,
- "stringifier": false,
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "object"
- },
- "name": "getItem",
- "arguments": [
- {
- "optional": false,
- "variadic": false,
- "extAttrs": [],
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "unsigned long"
- },
- "name": "index"
- }
- ],
- "extAttrs": []
- },
- {
- "type": "serializer",
- "patternMap": true,
- "names": [
- "getter"
- ],
- "extAttrs": []
- }
- ],
- "inheritance": null,
- "extAttrs": []
- },
- {
- "type": "interface",
- "name": "Account5",
- "partial": false,
- "members": [
- {
- "type": "attribute",
- "static": false,
- "stringifier": false,
- "inherit": false,
- "readonly": false,
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "DOMString"
- },
- "name": "secondname",
- "extAttrs": []
- },
- {
- "type": "serializer",
- "patternMap": true,
- "names": [
- "inherit",
- "secondname"
- ],
- "extAttrs": []
- }
- ],
- "inheritance": "Account",
- "extAttrs": []
- },
- {
- "type": "interface",
- "name": "Account6",
- "partial": false,
- "members": [
- {
- "type": "attribute",
- "static": false,
- "stringifier": false,
- "inherit": false,
- "readonly": false,
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "DOMString"
- },
- "name": "secondname",
- "extAttrs": []
- },
- {
- "type": "serializer",
- "patternMap": true,
- "names": [
- "inherit",
- "attribute"
- ],
- "extAttrs": []
- }
- ],
- "inheritance": "Account",
- "extAttrs": []
- },
- {
- "type": "interface",
- "name": "Account7",
- "partial": false,
- "members": [
- {
- "type": "attribute",
- "static": false,
- "stringifier": false,
- "inherit": false,
- "readonly": false,
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "DOMString"
- },
- "name": "name",
- "extAttrs": []
- },
- {
- "type": "attribute",
- "static": false,
- "stringifier": false,
- "inherit": false,
- "readonly": false,
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "unsigned long"
- },
- "name": "number",
- "extAttrs": []
- },
- {
- "type": "serializer",
- "patternList": true,
- "names": [
- "name",
- "number"
- ],
- "extAttrs": []
- }
- ],
- "inheritance": null,
- "extAttrs": []
- },
- {
- "type": "interface",
- "name": "Account8",
- "partial": false,
- "members": [
- {
- "type": "operation",
- "getter": true,
- "setter": false,
- "creator": false,
- "deleter": false,
- "legacycaller": false,
- "static": false,
- "stringifier": false,
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "object"
- },
- "name": "getItem",
- "arguments": [
- {
- "optional": false,
- "variadic": false,
- "extAttrs": [],
- "idlType": {
- "sequence": false,
- "generic": null,
- "nullable": false,
- "array": false,
- "union": false,
- "idlType": "unsigned long"
- },
- "name": "index"
- }
- ],
- "extAttrs": []
- },
- {
- "type": "serializer",
- "patternList": true,
- "names": [
- "getter"
- ],
- "extAttrs": []
- }
- ],
- "inheritance": null,
- "extAttrs": []
- }
-] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/setlike.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/setlike.json
index d44043a944a..3c1591b2372 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/setlike.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/setlike.json
@@ -10,7 +10,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "long"
},
@@ -32,7 +31,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "long"
},
@@ -42,6 +40,35 @@
],
"inheritance": null,
"extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "SetLikeExt",
+ "partial": false,
+ "members": [
+ {
+ "type": "setlike",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "union": false,
+ "idlType": "long",
+ "extAttrs": [
+ {
+ "name": "XAttr",
+ "arguments": null,
+ "type": "extended-attribute",
+ "rhs": null
+ }
+ ]
+ },
+ "readonly": false,
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
}
]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/static.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/static.json
index faab12b2966..034ffda2d54 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/static.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/static.json
@@ -22,7 +22,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -39,7 +38,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -56,7 +54,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -73,7 +70,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "long"
},
@@ -84,16 +80,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": true,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Point"
},
@@ -107,7 +100,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Circle"
},
@@ -121,7 +113,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Circle"
},
@@ -135,7 +126,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Circle"
},
@@ -148,4 +138,4 @@
"inheritance": null,
"extAttrs": []
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier-attribute.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier-attribute.json
index 196ee6f1a7c..acb26c2dda8 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier-attribute.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier-attribute.json
@@ -14,7 +14,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned long"
},
@@ -31,7 +30,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -43,8 +41,10 @@
"extAttrs": [
{
"name": "Constructor",
- "arguments": null
+ "arguments": null,
+ "type": "extended-attribute",
+ "rhs": null
}
]
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier-custom.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier-custom.json
index b4ab7392e5a..3c84305d863 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier-custom.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier-custom.json
@@ -14,7 +14,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned long"
},
@@ -31,7 +30,6 @@
"sequence": false,
"generic": null,
"nullable": true,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -48,7 +46,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -59,16 +56,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": true,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -81,8 +75,10 @@
"extAttrs": [
{
"name": "Constructor",
- "arguments": null
+ "arguments": null,
+ "type": "extended-attribute",
+ "rhs": null
}
]
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier.json
index ad3abde85f4..6b2d133d96f 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier.json
@@ -8,16 +8,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": true,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -31,16 +28,14 @@
},
{
"type": "interface",
- "name": "A",
+ "name": "B",
"partial": false,
"members": [
{
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": true,
"extAttrs": []
@@ -49,4 +44,4 @@
"inheritance": null,
"extAttrs": []
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/treatasnull.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/treatasnull.json
index 8bacb967acc..03dec604fb4 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/treatasnull.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/treatasnull.json
@@ -14,7 +14,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -31,7 +30,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -42,16 +40,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "boolean"
},
@@ -64,6 +59,7 @@
{
"name": "TreatNullAs",
"arguments": null,
+ "type": "extended-attribute",
"rhs": {
"type": "identifier",
"value": "EmptyString"
@@ -74,7 +70,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -87,4 +82,4 @@
"inheritance": null,
"extAttrs": []
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/treatasundefined.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/treatasundefined.json
index 91c4d25f5d1..8699b73c8f2 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/treatasundefined.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/treatasundefined.json
@@ -14,7 +14,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -31,7 +30,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -42,16 +40,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "boolean"
},
@@ -64,6 +59,7 @@
{
"name": "TreatUndefinedAs",
"arguments": null,
+ "type": "extended-attribute",
"rhs": {
"type": "identifier",
"value": "EmptyString"
@@ -74,7 +70,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "DOMString"
},
@@ -87,4 +82,4 @@
"inheritance": null,
"extAttrs": []
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/typedef.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/typedef.json
index d0854fa3d26..612cfe727d9 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/typedef.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/typedef.json
@@ -14,7 +14,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -31,7 +30,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "float"
},
@@ -48,13 +46,11 @@
"sequence": true,
"generic": "sequence",
"nullable": false,
- "array": false,
"union": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Point"
}
@@ -77,7 +73,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Point"
},
@@ -94,7 +89,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Point"
},
@@ -120,7 +114,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Rect"
},
@@ -131,16 +124,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "boolean"
},
@@ -154,7 +144,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "Point"
},
@@ -167,16 +156,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "boolean"
},
@@ -190,7 +176,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "PointSequence"
},
@@ -209,13 +194,14 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "octet",
"extAttrs": [
{
"name": "Clamp",
- "arguments": null
+ "arguments": null,
+ "type": "extended-attribute",
+ "rhs": null
}
]
},
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/typesuffixes.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/typesuffixes.json
index 790c444ef46..0b30830a158 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/typesuffixes.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/typesuffixes.json
@@ -8,16 +8,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -31,14 +28,11 @@
"sequence": true,
"generic": "sequence",
"nullable": true,
- "array": false,
"union": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": true,
- "array": 1,
- "nullableArray": [false],
"union": false,
"idlType": "DOMString"
}
@@ -52,4 +46,4 @@
"inheritance": null,
"extAttrs": []
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/uniontype.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/uniontype.json
index 9da5e79f362..c4725d417b5 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/uniontype.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/uniontype.json
@@ -6,7 +6,6 @@
"idlType": {
"idlType": [
{
- "array": false,
"union": false,
"sequence": false,
"generic": null,
@@ -20,22 +19,19 @@
"idlType": "Date",
"sequence": false,
"generic": null,
- "union": false,
- "array": false
+ "union": false
},
{
"nullable": false,
"idlType": "Event",
"generic": null,
"sequence": false,
- "array": false,
"union": false
}
],
"nullable": false,
"sequence": false,
"generic": null,
- "array": false,
"union": true
},
{
@@ -43,7 +39,6 @@
"sequence": false,
"idlType": [
{
- "array": false,
"union": false,
"sequence": false,
"generic": null,
@@ -55,20 +50,17 @@
"idlType": "DOMString",
"sequence": false,
"generic": null,
- "array": false,
"union": false
}
],
"nullable": true,
- "union": true,
- "array": false
+ "union": true
}
],
"nullable": false,
"generic": null,
"sequence": false,
- "union": true,
- "array": false
+ "union": true
},
"name": "test",
"inherit": false,
@@ -91,18 +83,18 @@
"extAttrs": [
{
"name": "EnforceRange",
- "arguments": null
+ "arguments": null,
+ "type": "extended-attribute",
+ "rhs": null
}
],
"nullable": false,
"idlType": "long",
"generic": null,
"sequence": false,
- "array": false,
"union": false
},
{
- "array": false,
"union": false,
"sequence": false,
"generic": null,
@@ -112,8 +104,7 @@
],
"generic": null,
"sequence": false,
- "union": true,
- "array": false
+ "union": true
},
"inherit": false,
"type": "attribute"
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/variadic-operations.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/variadic-operations.json
index 431ec0cb115..a9560da9ddd 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/variadic-operations.json
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/variadic-operations.json
@@ -14,7 +14,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "unsigned long"
},
@@ -25,16 +24,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -48,7 +44,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "long"
},
@@ -61,16 +56,13 @@
"type": "operation",
"getter": false,
"setter": false,
- "creator": false,
"deleter": false,
- "legacycaller": false,
"static": false,
"stringifier": false,
"idlType": {
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "void"
},
@@ -84,7 +76,6 @@
"sequence": false,
"generic": null,
"nullable": false,
- "array": false,
"union": false,
"idlType": "long"
},
@@ -97,4 +88,4 @@
"inheritance": null,
"extAttrs": []
}
-] \ No newline at end of file
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/opt/linecomment.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/opt/linecomment.json
new file mode 100644
index 00000000000..fbcdbf4b719
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/opt/linecomment.json
@@ -0,0 +1,3 @@
+{
+ "ws": true
+}
diff --git a/tests/wpt/web-platform-tests/secure-contexts/shared-worker-insecure-first.https.html b/tests/wpt/web-platform-tests/secure-contexts/shared-worker-insecure-first.https.html
index 074b21c10a6..00db9517d01 100644
--- a/tests/wpt/web-platform-tests/secure-contexts/shared-worker-insecure-first.https.html
+++ b/tests/wpt/web-platform-tests/secure-contexts/shared-worker-insecure-first.https.html
@@ -46,15 +46,15 @@
// one in the popup or in our subframe.
if (data.fromPopup) {
t3.step(function() {
- assert_false(data.exception);
- assert_false(data.error);
- assert_false(data.isSecureContext);
+ assert_false(data.exception, "SharedWorker should not throw an exception.");
+ assert_false(data.error, "SharedWorker connection should not generate an error.");
+ assert_false(data.isSecureContext, "SharedWorker is not a secure context");
});
t3.done();
} else {
t1.step(function() {
- assert_false(data.exception);
- assert_true(data.error);
+ assert_false(data.exception, "SharedWorker should not throw an exception.");
+ assert_true(data.error, "SharedWorker connection should generate an error.");
});
t1.done();
}
@@ -63,15 +63,15 @@
// check whether it's the one in the popup or in our subframe.
if (data.fromPopup) {
t4.step(function() {
- assert_false(data.exception);
- assert_false(data.error);
+ assert_false(data.exception, "SharedWorker should not throw an exception.");
+ assert_false(data.error, "SharedWorker connection should not generate an error.");
assert_false(data.isSecureContext);
});
t4.done();
} else {
t2.step(function() {
- assert_false(data.exception);
- assert_true(data.error);
+ assert_false(data.exception, "SharedWorker should not throw an exception.");
+ assert_true(data.error, "SharedWorker connection should generate an error.");
});
t2.done();
}
diff --git a/tests/wpt/web-platform-tests/server-timing/resources/blue.png.sub.headers b/tests/wpt/web-platform-tests/server-timing/resources/blue.png.sub.headers
index 23988edc869..948e7f0190a 100644
--- a/tests/wpt/web-platform-tests/server-timing/resources/blue.png.sub.headers
+++ b/tests/wpt/web-platform-tests/server-timing/resources/blue.png.sub.headers
@@ -1 +1 @@
-Server-Timing: metric2=2.1;blue.png
+Server-Timing: metric2; dur=2.1; desc=blue.png
diff --git a/tests/wpt/web-platform-tests/server-timing/resources/green.png.sub.headers b/tests/wpt/web-platform-tests/server-timing/resources/green.png.sub.headers
index d559754e7e8..b135472f865 100644
--- a/tests/wpt/web-platform-tests/server-timing/resources/green.png.sub.headers
+++ b/tests/wpt/web-platform-tests/server-timing/resources/green.png.sub.headers
@@ -1 +1 @@
-Server-Timing: metric3=3.1;green.png
+Server-Timing: metric3; dur=3.1; desc=green.png
diff --git a/tests/wpt/web-platform-tests/server-timing/test_server_timing.html.sub.headers b/tests/wpt/web-platform-tests/server-timing/test_server_timing.html.sub.headers
index c539669710c..ad018b70fd8 100644
--- a/tests/wpt/web-platform-tests/server-timing/test_server_timing.html.sub.headers
+++ b/tests/wpt/web-platform-tests/server-timing/test_server_timing.html.sub.headers
@@ -1 +1 @@
-Server-Timing: metric1=1.1;document, metric1=1.2;document
+Server-Timing: metric1; dur=1.1; desc=document, metric1; dur=1.2; desc=document
diff --git a/tests/wpt/web-platform-tests/service-workers/OWNERS b/tests/wpt/web-platform-tests/service-workers/OWNERS
index f4293642c4b..62f69300dee 100644
--- a/tests/wpt/web-platform-tests/service-workers/OWNERS
+++ b/tests/wpt/web-platform-tests/service-workers/OWNERS
@@ -1,3 +1,4 @@
+@beidson
@ehsan
@mkruisselbrink
@mattto
diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/script-tests/cache-match.js b/tests/wpt/web-platform-tests/service-workers/cache-storage/script-tests/cache-match.js
index 3d00f0f04af..ba359fed142 100644
--- a/tests/wpt/web-platform-tests/service-workers/cache-storage/script-tests/cache-match.js
+++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/script-tests/cache-match.js
@@ -1,6 +1,7 @@
if (self.importScripts) {
importScripts('/resources/testharness.js');
importScripts('../resources/test-helpers.js');
+ importScripts('/common/get-host-info.sub.js');
}
prepopulated_cache_test(simple_entries, function(cache, entries) {
@@ -318,4 +319,22 @@ cache_test(function(cache) {
});
}, 'Cache produces large Responses that can be cloned and read correctly.');
+cache_test(async (cache) => {
+ const url = get_host_info().HTTPS_REMOTE_ORIGIN +
+ '/service-workers/cache-storage/resources/simple.txt?pipe=' +
+ 'header(access-control-allow-origin,*)|' +
+ 'header(access-control-expose-headers,*)|' +
+ 'header(foo,bar)|' +
+ 'header(set-cookie,X)';
+
+ const response = await fetch(url);
+ await cache.put(new Request(url), response);
+ const cached_response = await cache.match(url);
+
+ const headers = cached_response.headers;
+ assert_equals(headers.get('access-control-expose-headers'), '*');
+ assert_equals(headers.get('foo'), 'bar');
+ assert_equals(headers.get('set-cookie'), null);
+ }, 'cors-exposed header should be stored correctly.');
+
done();
diff --git a/tests/wpt/web-platform-tests/service-workers/cache-storage/window/cache-match.https.html b/tests/wpt/web-platform-tests/service-workers/cache-storage/window/cache-match.https.html
index ffc64984ea1..f28efad0b76 100644
--- a/tests/wpt/web-platform-tests/service-workers/cache-storage/window/cache-match.https.html
+++ b/tests/wpt/web-platform-tests/service-workers/cache-storage/window/cache-match.https.html
@@ -4,5 +4,6 @@
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
<script src="../resources/test-helpers.js"></script>
<script src="../script-tests/cache-match.js"></script>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/about-blank-replacement.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/about-blank-replacement.https.html
new file mode 100644
index 00000000000..3acfe1b166a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/about-blank-replacement.https.html
@@ -0,0 +1,146 @@
+<!DOCTYPE html>
+<title>Service Worker: about:blank replacement handling</title>
+<meta name=timeout content=long>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="resources/test-helpers.sub.js"></script>
+<body>
+<script>
+// This test attempts to verify various initial about:blank document
+// creation is accurately reflected via the Clients API. The goal is
+// for Clients API to reflect what the browser actually does and not
+// to make special cases for the API.
+//
+// If your browser does not create an about:blank document in certain
+// cases then please just mark the test expected fail for now. The
+// reuse of globals from about:blank documents to the final load document
+// has particularly bad interop at the moment. Hopefully we can evolve
+// tests like this to eventually align browsers.
+
+const worker = 'resources/about-blank-replacement-worker.js';
+
+// Helper routine that creates an iframe that internally has some kind
+// of nested window. The nested window could be another iframe or
+// it could be a popup window.
+function createFrameWithNestedWindow(url) {
+ return new Promise((resolve, reject) => {
+ let frame = document.createElement('iframe');
+ frame.src = url;
+ document.body.appendChild(frame);
+
+ window.addEventListener('message', function onMsg(evt) {
+ if (evt.data.type !== 'NESTED_LOADED') {
+ return;
+ }
+ window.removeEventListener('message', onMsg);
+ if (evt.data.result && evt.data.result.startsWith('failure:')) {
+ reject(evt.data.result);
+ return;
+ }
+ resolve(frame);
+ });
+ });
+}
+
+// Helper routine to request the given worker find the client with
+// the specified URL using the clients.matchAll() API.
+function getClientIdByURL(worker, url) {
+ return new Promise(resolve => {
+ navigator.serviceWorker.addEventListener('message', function onMsg(evt) {
+ if (evt.data.type !== 'GET_CLIENT_ID') {
+ return;
+ }
+ navigator.serviceWorker.removeEventListener('message', onMsg);
+ resolve(evt.data.result);
+ });
+ worker.postMessage({ type: 'GET_CLIENT_ID', url: url.toString() });
+ });
+}
+
+async function doAsyncTest(t, scope, extraSearchParams) {
+ let reg = await service_worker_unregister_and_register(t, worker, scope);
+ await wait_for_state(t, reg.installing, 'activated');
+
+ // Load the scope as a frame. We expect this in turn to have a nested
+ // iframe. The service worker will intercept the load of the nested
+ // iframe and populate its body with the client ID of the initial
+ // about:blank document it sees via clients.matchAll().
+ let frame = await createFrameWithNestedWindow(scope);
+ let initialResult = frame.contentWindow.nested().document.body.textContent;
+ assert_false(initialResult.startsWith('failure:'), `result: ${initialResult}`);
+
+ // Next, ask the service worker to find the final client ID for the fully
+ // loaded nested frame.
+ let nestedURL = new URL(scope, window.location);
+ nestedURL.searchParams.set('nested', true);
+ extraSearchParams = extraSearchParams || {};
+ for (let p in extraSearchParams) {
+ nestedURL.searchParams.set(p, extraSearchParams[p]);
+ }
+ let finalResult = await getClientIdByURL(reg.active, nestedURL);
+ assert_false(finalResult.startsWith('failure:'), `result: ${finalResult}`);
+
+ // The initial about:blank client and the final loaded client should have
+ // the same ID value.
+ assert_equals(initialResult, finalResult, 'client ID values should match');
+
+ frame.remove();
+ await service_worker_unregister_and_done(t, scope);
+}
+
+promise_test(async function(t) {
+ // Execute a test where the nested frame is simply loaded normally.
+ await doAsyncTest(t, 'resources/about-blank-replacement-frame.py');
+}, 'Initial about:blank is controlled, exposed to clients.matchAll(), and ' +
+ 'matches final Client.');
+
+promise_test(async function(t) {
+ // Execute a test where the nested frame is modified immediately by
+ // its parent. In this case we add a message listener so the service
+ // worker can ping the client to verify its existence. This ping-pong
+ // check is performed during the initial load and when verifying the
+ // final loaded client.
+ await doAsyncTest(t, 'resources/about-blank-replacement-ping-frame.py',
+ { 'ping': true });
+}, 'Initial about:blank modified by parent is controlled, exposed to ' +
+ 'clients.matchAll(), and matches final Client.');
+
+promise_test(async function(t) {
+ // Execute a test where the nested window is a popup window instead of
+ // an iframe. This should behave the same as the simple iframe case.
+ await doAsyncTest(t, 'resources/about-blank-replacement-popup-frame.py');
+}, 'Popup initial about:blank is controlled, exposed to clients.matchAll(), and ' +
+ 'matches final Client.');
+
+promise_test(async function(t) {
+ const scope = 'resources/about-blank-replacement-uncontrolled-nested-frame.html';
+
+ let reg = await service_worker_unregister_and_register(t, worker, scope);
+ await wait_for_state(t, reg.installing, 'activated');
+
+ // Load the scope as a frame. We expect this in turn to have a nested
+ // iframe. Unlike the other tests in this file the nested iframe URL
+ // is not covered by a service worker scope. It should end up as
+ // uncontrolled even though its initial about:blank is controlled.
+ let frame = await createFrameWithNestedWindow(scope);
+ let nested = frame.contentWindow.nested();
+ let initialResult = nested.document.body.textContent;
+
+ // The nested iframe should not have been intercepted by the service
+ // worker. The empty.html nested frame has "hello world" for its body.
+ assert_equals(initialResult.trim(), 'hello world', `result: ${initialResult}`);
+
+ assert_not_equals(frame.contentWindow.navigator.serviceWorker.controller, null,
+ 'outer frame should be controlled');
+
+ assert_equals(nested.navigator.serviceWorker.controller, null,
+ 'nested frame should not be controlled');
+
+ frame.remove();
+ await service_worker_unregister_and_done(t, scope);
+}, 'Initial about:blank is controlled, exposed to clients.matchAll(), and ' +
+ 'final Client is not controlled by a service worker.');
+
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-cors-exposed-header-names.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-cors-exposed-header-names.https.html
new file mode 100644
index 00000000000..317b02175f2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-cors-exposed-header-names.https.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Service Worker: CORS-exposed header names should be transferred correctly</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="resources/test-helpers.sub.js"></script>
+<script>
+promise_test(async function(t) {
+ const SCOPE = 'resources/simple.html';
+ const SCRIPT = 'resources/fetch-cors-exposed-header-names-worker.js';
+ const host_info = get_host_info();
+
+ const URL = get_host_info().HTTPS_REMOTE_ORIGIN +
+ '/service-workers/service-worker/resources/simple.txt?pipe=' +
+ 'header(access-control-allow-origin,*)|' +
+ 'header(access-control-expose-headers,*)|' +
+ 'header(foo,bar)|' +
+ 'header(set-cookie,X)';
+
+ const reg = await service_worker_unregister_and_register(t, SCRIPT, SCOPE);
+ await wait_for_state(t, reg.installing, 'activated');
+ const frame = await with_iframe(SCOPE);
+
+ const response = await frame.contentWindow.fetch(URL);
+ const headers = response.headers;
+ assert_equals(headers.get('foo'), 'bar');
+ assert_equals(headers.get('set-cookie'), null);
+ assert_equals(headers.get('access-control-expose-headers'), '*');
+ }, 'CORS-exposed header names for a response from sw');
+</script>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-respond-with-custom-response.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-respond-with-custom-response.https.html
new file mode 100644
index 00000000000..645a29c9b4f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-respond-with-custom-response.https.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>respondWith with a new Response</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/test-helpers.sub.js"></script>
+<script>
+'use strict';
+
+const WORKER =
+ 'resources/fetch-event-respond-with-custom-response-worker.js';
+const SCOPE =
+ 'resources/blank.html';
+
+// Register a service worker, then create an iframe at url.
+function iframeTest(url, callback, name) {
+ return promise_test(async t => {
+ const reg = await service_worker_unregister_and_register(t, WORKER, SCOPE);
+ add_completion_callback(() => reg.unregister());
+ await wait_for_state(t, reg.installing, 'activated');
+ const iframe = await with_iframe(url);
+ const iwin = iframe.contentWindow;
+ t.add_cleanup(() => iframe.remove());
+ await callback(t, iwin);
+ }, name);
+}
+
+iframeTest(SCOPE, async (t, iwin) => {
+ const response = await iwin.fetch('?type=string');
+ assert_equals(await response.text(), 'PASS');
+}, 'Subresource built from a string');
+
+iframeTest(SCOPE, async (t, iwin) => {
+ const response = await iwin.fetch('?type=blob');
+ assert_equals(await response.text(), 'PASS');
+}, 'Subresource built from a blob');
+
+iframeTest(SCOPE, async (t, iwin) => {
+ const response = await iwin.fetch('?type=buffer');
+ assert_equals(await response.text(), 'PASS');
+}, 'Subresource built from a buffer');
+
+iframeTest(SCOPE, async (t, iwin) => {
+ const response = await iwin.fetch('?type=buffer-view');
+ assert_equals(await response.text(), 'PASS');
+}, 'Subresource built from a buffer-view');
+
+iframeTest(SCOPE, async (t, iwin) => {
+ const response = await iwin.fetch('?type=form-data');
+ const data = await response.formData();
+ assert_equals(data.get('result'), 'PASS');
+}, 'Subresource built from form-data');
+
+iframeTest(SCOPE, async (t, iwin) => {
+ const response = await iwin.fetch('?type=search-params');
+ assert_equals(await response.text(), 'result=PASS');
+}, 'Subresource built from search-params');
+
+// As above, but navigations
+
+iframeTest(SCOPE + '?type=string', (t, iwin) => {
+ assert_equals(iwin.document.body.textContent, 'PASS');
+}, 'Navigation resource built from a string');
+
+iframeTest(SCOPE + '?type=blob', (t, iwin) => {
+ assert_equals(iwin.document.body.textContent, 'PASS');
+}, 'Navigation resource built from a blob');
+
+iframeTest(SCOPE + '?type=buffer', (t, iwin) => {
+ assert_equals(iwin.document.body.textContent, 'PASS');
+}, 'Navigation resource built from a buffer');
+
+iframeTest(SCOPE + '?type=buffer-view', (t, iwin) => {
+ assert_equals(iwin.document.body.textContent, 'PASS');
+}, 'Navigation resource built from a buffer-view');
+
+// Note: not testing form data for a navigation as the boundary header is lost.
+
+iframeTest(SCOPE + '?type=search-params', (t, iwin) => {
+ assert_equals(iwin.document.body.textContent, 'result=PASS');
+}, 'Navigation resource built from search-params');
+</script>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-respond-with-readable-stream.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-respond-with-readable-stream.https.html
index 05afb6bc0fe..75545adbc19 100644
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-respond-with-readable-stream.https.html
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/fetch-event-respond-with-readable-stream.https.html
@@ -10,22 +10,45 @@
const WORKER =
'resources/fetch-event-respond-with-readable-stream-worker.js';
const SCOPE =
- 'resources/fetch-event-respond-with-readable-stream-iframe.html';
-// Called by the iframe when done.
-var done;
-var done_was_called = new Promise(resolve => done = resolve);
-
-promise_test(t => {
- return service_worker_unregister_and_register(t, WORKER, SCOPE)
- .then(reg => {
- add_completion_callback(() => reg.unregister());
- return wait_for_state(t, reg.installing, 'activated');
- })
- .then(() => with_iframe(SCOPE))
- .then(iframe => {
- t.add_cleanup(() => iframe.remove())
- })
- .then(() => done_was_called)
- .then(result => assert_equals(result, 'PASS'));
- }, 'Respond with a Response built from a ReadableStream');
+ 'resources/blank.html';
+
+// Register a service worker, then create an iframe at url.
+function iframeTest(url, callback, name) {
+ return promise_test(async t => {
+ const reg = await service_worker_unregister_and_register(t, WORKER, SCOPE);
+ add_completion_callback(() => reg.unregister());
+ await wait_for_state(t, reg.installing, 'activated');
+ const iframe = await with_iframe(url);
+ const iwin = iframe.contentWindow;
+ t.add_cleanup(() => iframe.remove());
+ await callback(t, iwin);
+ }, name);
+}
+
+iframeTest(SCOPE, async (t, iwin) => {
+ const response = await iwin.fetch('?stream');
+ assert_equals(await response.text(), 'PASS');
+}, 'Subresource built from a ReadableStream');
+
+iframeTest(SCOPE + '?stream', (t, iwin) => {
+ assert_equals(iwin.document.body.textContent, 'PASS');
+}, 'Main resource built from a ReadableStream');
+
+iframeTest(SCOPE, async (t, iwin) => {
+ const response = await iwin.fetch('?stream&delay');
+ assert_equals(await response.text(), 'PASS');
+}, 'Subresource built from a ReadableStream - delayed');
+
+iframeTest(SCOPE + '?stream&delay', (t, iwin) => {
+ assert_equals(iwin.document.body.textContent, 'PASS');
+}, 'Main resource built from a ReadableStream - delayed');
+
+iframeTest(SCOPE, async (t, iwin) => {
+ const response = await iwin.fetch('?stream&use-fetch-stream');
+ assert_equals(await response.text(), 'PASS\n');
+}, 'Subresource built from a ReadableStream - fetch stream');
+
+iframeTest(SCOPE + '?stream&use-fetch-stream', (t, iwin) => {
+ assert_equals(iwin.document.body.textContent, 'PASS\n');
+}, 'Main resource built from a ReadableStream - fetch stream');
</script>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/foreign-fetch-basics.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/foreign-fetch-basics.https.html
deleted file mode 100644
index 8519f8f4575..00000000000
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/foreign-fetch-basics.https.html
+++ /dev/null
@@ -1,241 +0,0 @@
-<!DOCTYPE html>
-<title>Service Worker: basic Foreign Fetch functionality</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/common/get-host-info.sub.js"></script>
-<script src="resources/test-helpers.sub.js"></script>
-<script src="resources/foreign-fetch-helpers.js"></script>
-<body>
-<script>
-var host_info = get_host_info();
-var resource_path = new URL('resources/', location).pathname;
-
-function worker_for_origins(origins) {
- var worker = 'foreign-fetch-worker.js?';
- var params = {origins: origins, relscopes: ['/intercept']};
- return worker + encodeURIComponent(JSON.stringify(params));
-}
-
-function worker_for_scopes(relative_scopes) {
- var worker = 'foreign-fetch-worker.js?';
- var params = {relscopes: relative_scopes};
- return worker + encodeURIComponent(JSON.stringify(params));
-}
-
-function intercepted_url(scope) {
- return host_info.HTTPS_REMOTE_ORIGIN + resource_path + scope + '/intercept/foo?basic';
-}
-
-function non_intercepted_url(scope) {
- return host_info.HTTPS_REMOTE_ORIGIN + resource_path + scope + '/foo?basic';
-}
-
-promise_test(t => {
- var scope = 'foreign-fetch/scope/wildcard';
- return install_cross_origin_worker(t, worker_for_origins(['*']), scope)
- .then(() => promise_rejects(t, new TypeError(),
- fetch(non_intercepted_url(scope))))
- .then(() => fetch(intercepted_url(scope)))
- .then(response => response.text())
- .then(response_text => {
- assert_equals(response_text, 'Foreign Fetch');
- });
- }, 'Service Worker intercepts fetches in scope with wildcard origin.');
-
-promise_test(t => {
- var scope = 'foreign-fetch/scope/match-origin';
- return install_cross_origin_worker(
- t, worker_for_origins([location.origin]), scope)
- .then(() => fetch(intercepted_url(scope)))
- .then(response => response.text())
- .then(response_text => {
- assert_equals(response_text, 'Foreign Fetch');
- });
- }, 'Service Worker intercepts fetches in scope with explicit origin.');
-
-promise_test(t => {
- var scope = 'foreign-fetch/scope/nomatch-origin';
- return install_cross_origin_worker(
- t, worker_for_origins(['https://example.com']), scope)
- .then(() => promise_rejects(t, new TypeError(),
- fetch(non_intercepted_url(scope))));
- }, 'Service Worker doesn\'t intercept fetches with non matching origin.');
-
-promise_test(t => {
- var scope = 'foreign-fetch/scope/origin-list';
- return install_cross_origin_worker(
- t, worker_for_origins([location.origin, 'https://example.com']), scope)
- .then(() => fetch(intercepted_url(scope)))
- .then(response => response.text())
- .then(response_text => {
- assert_equals(response_text, 'Foreign Fetch');
- });
- }, 'Service Worker intercepts fetches in scope with explicit origin list.');
-
-promise_test(t => {
- var scope = 'resources/foreign-fetch/same-origin';
- return service_worker_unregister_and_register(
- t, 'resources/' + worker_for_origins(['*']), scope)
- .then(r => {
- add_completion_callback(() => r.unregister());
- return wait_for_state(t, r.installing, 'activated');
- })
- .then(() => fetch(scope + '/intercept/foo?basic'))
- .then(response => {
- assert_equals(response.status, 404);
- });
- }, 'Service Worker does not intercept same origin fetches.');
-
-promise_test(t => {
- var scope = 'reply-to-message.html?onmessage';
- var remote_url =
- host_info.HTTPS_REMOTE_ORIGIN + resource_path + scope;
- return install_cross_origin_worker(t, worker_for_scopes(['']), scope)
- .then(() => with_iframe(remote_url))
- .then(frame => new Promise(resolve => {
- var channel = new MessageChannel();
- frame.contentWindow.postMessage('ping', '*', [channel.port1]);
- channel.port2.onmessage = reply => resolve(reply.data);
- }))
- .then(reply => {
- assert_equals(reply, 'ping');
- });
- }, 'Service Worker does not intercept navigations.');
-
-promise_test(t => {
- var scope = 'fetch-access-control.py?fallback&ACAOrigin=*';
- var remote_url =
- host_info.HTTPS_REMOTE_ORIGIN + resource_path + scope;
- return install_cross_origin_worker(t, worker_for_scopes(['']), scope)
- .then(() => fetch(remote_url))
- .then(response => response.text())
- .then(response_text => assert_true(response_text.startsWith('report(')));
- }, 'Service Worker that fallback to network should fallback to network.');
-
-promise_test(t => {
- var scope = 'fetch-access-control.py?fetch&ACAOrigin=*';
- var remote_url =
- host_info.HTTPS_REMOTE_ORIGIN + resource_path + scope;
- return install_cross_origin_worker(t, worker_for_scopes(['']), scope)
- .then(() => fetch(remote_url))
- .then(response => response.text())
- .then(response_text => assert_true(response_text.startsWith('report(')));
- }, 'Service Worker that fetch from the network should fallback to network.');
-
-promise_test(t => {
- var scope = 'simple.txt?fallback';
- var remote_url =
- host_info.HTTPS_REMOTE_ORIGIN + resource_path + scope;
- return install_cross_origin_worker(t, worker_for_scopes(['']), scope)
- .then(() => fetch(remote_url, {mode: 'no-cors'}))
- .then(response => assert_equals(response.type, 'opaque'))
- .then(() => promise_rejects(t, new TypeError(), fetch(remote_url)));
- }, 'Falling back to network should still respect CORS.');
-
-promise_test(t => {
- var ff_scope = 'foreign-fetch/scope/controlled?basic';
- var remote_url =
- host_info.HTTPS_REMOTE_ORIGIN + resource_path + ff_scope;
- var scope = 'resources/simple.html?fetch';
- var worker = 'resources/empty-worker.js';
- return install_cross_origin_worker(t, worker_for_scopes(['']), ff_scope)
- .then(() => service_worker_unregister_and_register(t, worker, scope))
- .then(r => {
- add_completion_callback(() => r.unregister());
- return wait_for_state(t, r.installing, 'activated');
- })
- .then(() => with_iframe(scope))
- .then(frame => frame.contentWindow.fetch(remote_url))
- .then(response => response.text())
- .then(response_text => {
- assert_equals(response_text, 'Foreign Fetch');
- });
- }, 'Foreign fetch can intercept fetch requests from SW controlled pages.');
-
-promise_test(t => {
- var ff_scope = 'foreign-fetch/scope/controlled?script';
- var remote_url =
- host_info.HTTPS_REMOTE_ORIGIN + resource_path + ff_scope;
- var scope = 'resources/simple.html?script';
- var worker = 'resources/empty-worker.js';
- return install_cross_origin_worker(t, worker_for_scopes(['']), ff_scope)
- .then(() => service_worker_unregister_and_register(t, worker, scope))
- .then(r => {
- add_completion_callback(() => r.unregister());
- return wait_for_state(t, r.installing, 'activated');
- })
- .then(() => with_iframe(scope))
- .then(frame => new Promise(resolve => {
- frame.contentWindow.DidLoad = resolve;
- let script = frame.contentWindow.document.createElement('script');
- script.setAttribute('src', remote_url);
- script.setAttribute('crossorigin', 'use-credentials');
- frame.contentWindow.document.head.appendChild(script);
- }))
- .then(response_text => {
- assert_equals(response_text, 'Foreign Fetch');
- });
- }, 'Foreign fetch can intercept resource requests from SW controlled pages.');
-
-promise_test(t => {
- var scope = 'simple.txt?meta';
- var remote_url =
- host_info.HTTPS_REMOTE_ORIGIN + resource_path + scope;
- return install_cross_origin_worker(t, worker_for_scopes(['']), scope)
- .then(() => fetch(remote_url, {mode: 'no-cors'}))
- .then(response => response.json())
- .then(response_data => {
- assert_equals(self.location.href, response_data.referrer);
- assert_equals(self.location.origin, response_data.origin);
- })
- .then(() => with_iframe('resources/blank.html'))
- .then(frame => {
- var meta = frame.contentDocument.createElement('meta');
- meta.setAttribute('name', 'referrer');
- meta.setAttribute('content', 'no-referrer');
- frame.contentDocument.head.appendChild(meta);
- return frame.contentWindow.fetch(remote_url, {mode: 'no-cors'});
- })
- .then(response => response.json())
- .then(response_data => {
- assert_equals('', response_data.referrer);
- assert_equals('null', response_data.origin);
- });
- }, 'Referrer and origin are set correctly in ForeignFetchEvent.');
-
-promise_test(t => {
- var scope = 'simple.txt?basic_insecure';
- var remote_url =
- host_info.AUTHENTICATED_ORIGIN + resource_path + scope;
- return install_cross_origin_worker(t, worker_for_scopes(['']), scope,
- host_info.AUTHENTICATED_ORIGIN)
- .then(() => fetch_from_different_origin(host_info.HTTPS_REMOTE_ORIGIN, remote_url))
- .then(response => assert_equals(response, 'Success: Foreign Fetch'))
- .then(() => fetch_from_different_origin(host_info.UNAUTHENTICATED_ORIGIN,
- remote_url))
- .then(response => assert_true(response.startsWith('Error: TypeError')));
- }, 'Service Worker does not intercept fetches from an insecure context.');
-
-promise_test(t => {
- var scope = 'fetch-access-control.py?basic&ACAOrigin=*&ACAMethods=SPECIAL';
- var remote_url =
- host_info.HTTPS_REMOTE_ORIGIN + resource_path + scope;
- return install_cross_origin_worker(t, worker_for_scopes(['']), scope)
- .then(() => fetch(remote_url, {method: 'SPECIAL'}))
- .then(response => response.text())
- .then(response_text => assert_true(response_text.startsWith('report(')))
- // Do the whole thing twice to test CORS preflight cache behavior.
- .then(() => fetch(remote_url, {method: 'SPECIAL'}))
- .then(response => response.text())
- .then(response_text => assert_true(response_text.startsWith('report(')));
- }, 'Service Worker does not intercept fetches with CORS preflight');
-
-promise_test(t => {
- var scope = 'simple.txt?null';
- var remote_url =
- host_info.HTTPS_REMOTE_ORIGIN + resource_path + scope;
- return install_cross_origin_worker(t, worker_for_scopes(['']), scope)
- .then(() => promise_rejects(t, new TypeError(), fetch(remote_url)));
-}, 'Foreign fetch rejects if resolved with a null response.');
-</script>
-</body>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/foreign-fetch-cors.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/foreign-fetch-cors.https.html
deleted file mode 100644
index c111a313576..00000000000
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/foreign-fetch-cors.https.html
+++ /dev/null
@@ -1,306 +0,0 @@
-<!DOCTYPE html>
-<title>Service Worker: Foreign Fetch CORS functionality</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/common/get-host-info.sub.js"></script>
-<script src="resources/test-helpers.sub.js"></script>
-<script src="resources/foreign-fetch-helpers.js"></script>
-<body>
-<script>
-var host_info = get_host_info();
-var origin = new URL(self.location).origin;
-var wrong_origin = 'https://example.com/';
-var test_header = 'X-ServiceWorker-ServerHeader';
-
-function url_to_fetch(scope) {
- return host_info.HTTPS_REMOTE_ORIGIN + new URL('resources/', location).pathname + scope;
-}
-
-function worker_for_response(response) {
- return 'foreign-fetch-cors-worker.js?' +
- encodeURIComponent(JSON.stringify(response));
-}
-
-function scope_for_params(params) {
- return 'simple.txt?' + encodeURIComponent(JSON.stringify(params));
-}
-
-// Method used for tests that expect to result in an opaque response.
-function verify_opaque_fetch(url, t) {
- return promise_rejects(t, new TypeError(), fetch(url))
- .then(() => fetch(url, {mode: 'no-cors'}))
- .then(response => assert_equals(response.type, 'opaque'))
- .then(() => new Promise(resolve => {
- var request = new XMLHttpRequest();
- request.open('GET', url);
- request.onreadystatechange = () => {
- if (request.readyState == 4) resolve(request);
- };
- request.send();
- }))
- .then(xhr => {
- assert_equals(xhr.status, 0);
- assert_equals(xhr.responseText, '');
- });
-}
-
-// Verify that fetching an url results in a network error.
-function verify_network_error(url, t) {
- return promise_rejects(t, new TypeError(), fetch(url))
- .then(() => promise_rejects(t, new TypeError(),
- fetch(url, {mode: 'no-cors'})))
- .then(() => new Promise(resolve => {
- var request = new XMLHttpRequest();
- request.open('GET', url);
- request.onreadystatechange = () => {
- if (request.readyState == 4) resolve(request);
- };
- request.send();
- }))
- .then(xhr => {
- assert_equals(xhr.status, 0);
- assert_equals(xhr.responseText, '');
- });
-}
-
-// Verifies that fetching the URL returns a cors response, with a specific value
-// for a test_header on the response. Also verifies that round-tripping this
-// response through the cache doesn't cause issues.
-function verify_cors_fetch_with_header_value(url, header_value) {
- var response;
- var cache;
- return fetch(url)
- .then(r => {
- response = r.clone();
- assert_equals(r.type, 'cors');
- assert_equals(r.headers.get(test_header), header_value, 'From fetch');
- return r.text();
- })
- .then(response_text => {
- assert_true(response_text.startsWith('report('),
- 'Correct content via fetch');
- return self.caches.open(url);
- })
- .then(c => {
- cache = c;
- return cache.put(url, response);
- })
- .then(() => cache.match(url))
- .then(r => {
- assert_equals(r.type, 'cors');
- assert_equals(r.headers.get(test_header), header_value, 'From cache');
- return r.text();
- })
- .then(response_text => {
- assert_true(response_text.startsWith('report('),
- 'Correct content via cache');
- return self.caches.delete(url);
- })
- .then(() => new Promise(resolve => {
- var request = new XMLHttpRequest();
- request.open('GET', url);
- request.onreadystatechange = () => {
- if (request.readyState == 4) resolve(request);
- };
- request.send();
- }))
- .then(xhr => {
- assert_true(xhr.responseText.startsWith('report('),
- 'Correct content via xhr');
- assert_equals(xhr.getResponseHeader(test_header), header_value);
- var headers = xhr.getAllResponseHeaders().toLowerCase();
- if (header_value) {
- assert_true(headers.includes(test_header.toLowerCase() + ': ' +
- header_value.toLowerCase()));
- } else {
- assert_false(headers.includes(test_header.toLowerCase()));
- }
- });
-}
-
-verify_cors_fetch_with_header =
- url => verify_cors_fetch_with_header_value(url, 'SetInTheServer');
-verify_cors_fetch_without_header =
- url => verify_cors_fetch_with_header_value(url, null);
-
-var tests = [
- {
- description: 'Same origin fetch without CORS headers, not exposed',
- params: {
- cross_origin: false,
- with_aceheaders: false,
- with_acaorigin: false
- },
- response: {},
- expectation: verify_opaque_fetch
- },
- {
- description: 'Same origin fetch without CORS headers, only origin exposed',
- params: {
- cross_origin: false,
- with_aceheaders: false,
- with_acaorigin: false
- },
- response: {origin: origin},
- expectation: verify_cors_fetch_without_header
- },
- {
- description:
- 'Same origin fetch without CORS headers, headers and origin exposed',
- params: {
- cross_origin: false,
- with_aceheaders: false,
- with_acaorigin: false
- },
- response: {origin: origin, headers: [test_header]},
- expectation: verify_cors_fetch_with_header
- },
- {
- description:
- 'Same origin fetch without CORS headers, exposed to wrong origin',
- params: {
- cross_origin: false,
- with_aceheaders: false,
- with_acaorigin: false
- },
- response: {origin: wrong_origin, headers: [test_header]},
- expectation: verify_network_error
- },
- {
- description: 'Same origin fetch with CORS headers, not exposed',
- params: {
- cross_origin: false,
- with_aceheaders: true,
- with_acaorigin: true
- },
- response: {},
- expectation: verify_opaque_fetch
- },
- {
- description: 'Same origin fetch with CORS headers, only origin exposed',
- params: {
- cross_origin: false,
- with_aceheaders: true,
- with_acaorigin: true
- },
- response: {origin: origin},
- expectation: verify_cors_fetch_without_header
- },
- {
- description:
- 'Same origin fetch with CORS headers, headers and origin exposed',
- params: {
- cross_origin: false,
- with_aceheaders: true,
- with_acaorigin: true
- },
- response: {origin: origin, headers: [test_header]},
- expectation: verify_cors_fetch_with_header
- },
- {
- description: 'Same origin fetch with CORS headers, exposed to wrong origin',
- params: {
- cross_origin: false,
- with_aceheaders: true,
- with_acaorigin: true
- },
- response: {origin: wrong_origin, headers: [test_header]},
- expectation: verify_network_error
- },
- {
- description: 'Cross origin fetch without CORS headers, not exposed',
- params: {
- cross_origin: true,
- with_aceheaders: false,
- with_acaorigin: false
- },
- response: {},
- expectation: verify_opaque_fetch
- },
- {
- description: 'Cross origin fetch with ACEHeaders header, not exposed',
- params: {
- cross_origin: true,
- with_aceheaders: true,
- with_acaorigin: true
- },
- response: {},
- expectation: verify_opaque_fetch
- },
- {
- description:
- 'Cross origin fetch with ACEHeaders header, only origin exposed',
- params: {
- cross_origin: true,
- with_aceheaders: true,
- with_acaorigin: true
- },
- response: {origin: origin},
- expectation: verify_cors_fetch_without_header
- },
- {
- description:
- 'Cross origin fetch with ACEHeaders header, headers and origin exposed',
- params: {
- cross_origin: true,
- with_aceheaders: true,
- with_acaorigin: true
- },
- response: {origin: origin, headers: [test_header]},
- expectation: verify_cors_fetch_with_header
- },
- {
- description:
- 'Cross origin fetch with ACEHeaders header, exposed to wrong origin',
- params: {
- cross_origin: true,
- with_aceheaders: true,
- with_acaorigin: true
- },
- response: {origin: wrong_origin, headers: [test_header]},
- expectation: verify_network_error
- },
- {
- description: 'Cross origin fetch without ACEHeaders header, not exposed',
- params: {
- cross_origin: true,
- with_aceheaders: false,
- with_acaorigin: true
- },
- response: {},
- expectation: verify_opaque_fetch
- },
- {
- description:
- 'Cross origin fetch without ACEHeaders header, only origin exposed',
- params: {
- cross_origin: true,
- with_aceheaders: false,
- with_acaorigin: true
- },
- response: {origin: origin},
- expectation: verify_cors_fetch_without_header
- },
- {
- description: 'Cross origin fetch without ACEHeaders header, ' +
- 'headers and origin exposed',
- params: {
- cross_origin: true,
- with_aceheaders: false,
- with_acaorigin: true
- },
- response: {origin: origin, headers: [test_header]},
- expectation: verify_cors_fetch_without_header
- }
-];
-
-for (var i = 0; i < tests.length; ++i) (data => {
- promise_test(t => {
- var scope = scope_for_params(data.params);
- var worker = worker_for_response(data.response);
- return install_cross_origin_worker(t, worker, scope)
- .then(() => data.expectation(url_to_fetch(scope), t));
- }, data.description);
-})(tests[i]);
-</script>
-</body>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/foreign-fetch-event.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/foreign-fetch-event.https.html
deleted file mode 100644
index 94eeda39662..00000000000
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/foreign-fetch-event.https.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<title>Service Worker: ForeignFetchEvent</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/test-helpers.sub.js"></script>
-<script>
-service_worker_test('resources/foreign-fetch-event-worker.js',
- 'ForeignFetchEvent constructor');
-</script>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/foreign-fetch-workers.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/foreign-fetch-workers.https.html
deleted file mode 100644
index 65972900648..00000000000
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/foreign-fetch-workers.https.html
+++ /dev/null
@@ -1,88 +0,0 @@
-<!DOCTYPE html>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/common/get-host-info.sub.js"></script>
-<script src="resources/test-helpers.sub.js"></script>
-<script src="resources/foreign-fetch-helpers.js"></script>
-<body>
-<script>
-var host_info = get_host_info();
-var ff_worker = 'foreign-fetch-worker.js?{}';
-var resource_path = new URL('resources/', location).pathname;
-
-promise_test(t => {
- var ff_scope = 'simple.txt?basic_sw';
- var worker = 'resources/foreign-fetch-helper-worker.js';
- var scope = 'resources/simple.html?foreignfetch';
- return install_cross_origin_worker(t, ff_worker, ff_scope)
- .then(() => service_worker_unregister_and_register(t, worker, scope))
- .then(r => {
- add_completion_callback(() => r.unregister());
- return wait_for_state(t, r.installing, 'activated');
- })
- .then(() => with_iframe(scope))
- .then(frame => {
- assert_equals(frame.contentDocument.body.innerText, 'Foreign Fetch');
- });
- }, 'Foreign fetch can intercept fetches made from a service worker');
-
-promise_test(t => {
- let scope = 'simple.txt?basic_dedicated';
- let remote_url = host_info.HTTPS_REMOTE_ORIGIN + resource_path + scope;
- return install_cross_origin_worker(t, ff_worker, scope)
- .then(() => new Promise(resolve => {
- let worker = new Worker('resources/foreign-fetch-helper-script.js');
- let channel = new MessageChannel();
- worker.postMessage({url: remote_url,
- port: channel.port1},
- [channel.port1]);
- channel.port2.onmessage = reply => resolve(reply.data);
- }))
- .then(response => assert_equals(response, 'Success: Foreign Fetch'));
- }, 'Foreign fetch can intercept fetches made from a dedicated worker');
-
-promise_test(t => {
- let scope = 'simple.txt?basic_shared';
- let remote_url = host_info.HTTPS_REMOTE_ORIGIN + resource_path + scope;
- return install_cross_origin_worker(t, ff_worker, scope)
- .then(() => new Promise(resolve => {
- let worker = new SharedWorker(
- 'resources/foreign-fetch-helper-script.js');
- let channel = new MessageChannel();
- worker.port.postMessage({url: remote_url,
- port: channel.port1},
- [channel.port1]);
- channel.port2.onmessage = reply => resolve(reply.data);
- }))
- .then(response => assert_equals(response, 'Success: Foreign Fetch'));
- }, 'Foreign fetch can intercept fetches made from a shared worker');
-
-promise_test(t => {
- var scope = 'simple.txt?basic_dedicated_insecure';
- var remote_url = host_info.AUTHENTICATED_ORIGIN + resource_path + scope;
- return install_cross_origin_worker(t, ff_worker, scope,
- host_info.AUTHENTICATED_ORIGIN)
- .then(() => fetch_from_different_origin(
- host_info.HTTPS_REMOTE_ORIGIN, remote_url, 'dedicated'))
- .then(response => assert_equals(response, 'Success: Foreign Fetch'))
- .then(() => fetch_from_different_origin(
- host_info.UNAUTHENTICATED_ORIGIN, remote_url, 'dedicated'))
- .then(response => assert_equals(response,
- 'Error: TypeError: Failed to fetch'));
- }, 'Fetches from an insecure dedicated worker aren\'t intercepted.');
-
-promise_test(t => {
- var scope = 'simple.txt?basic_shared_insecure';
- var remote_url = host_info.AUTHENTICATED_ORIGIN + resource_path + scope;
- return install_cross_origin_worker(t, ff_worker, scope,
- host_info.AUTHENTICATED_ORIGIN)
- .then(() => fetch_from_different_origin(
- host_info.HTTPS_REMOTE_ORIGIN, remote_url, 'shared'))
- .then(response => assert_equals(response, 'Success: Foreign Fetch'))
- .then(() => fetch_from_different_origin(
- host_info.UNAUTHENTICATED_ORIGIN, remote_url, 'shared'))
- .then(response => assert_equals(response,
- 'Error: TypeError: Failed to fetch'));
- }, 'Fetches from an insecure shared worker aren\'t intercepted.');
-</script>
-</body>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/iframe-sandbox-register-link-element.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/iframe-sandbox-register-link-element.https.html
deleted file mode 100644
index 1d1c54e3edc..00000000000
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/iframe-sandbox-register-link-element.https.html
+++ /dev/null
@@ -1,53 +0,0 @@
-<!DOCTYPE html>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/test-helpers.sub.js"></script>
-<title>Service worker registration from within sandboxed iframe</title>
-<body>
-<script>
-'use strict';
-function waitForMsg(id) {
- return new Promise(function(resolve) {
- window.addEventListener('message', function onMessage(event) {
- if (!event.data || event.data.id !== id) {
- return;
- }
- window.removeEventListener('message', onMessage);
- resolve(event.data.result);
- });
- });
-}
-
-promise_test(function(t) {
- var iframe = document.createElement('iframe');
- iframe.setAttribute('src', 'resources/iframe-register-link-element.html?subtest1');
- iframe.setAttribute('sandbox', 'allow-scripts');
-
- document.body.appendChild(iframe);
- t.add_cleanup(function() {
- iframe.remove();
- });
-
- return waitForMsg('?subtest1')
- .then(function(data) {
- assert_equals(data, 'error');
- });
- }, 'registration via <link> element `rel` rejected');
-
-promise_test(function(t) {
- var iframe = document.createElement('iframe');
- iframe.setAttribute('src', 'resources/iframe-register-link-element.html?subtest2');
- iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin');
-
- document.body.appendChild(iframe);
- t.add_cleanup(function() {
- iframe.remove();
- });
-
- return waitForMsg('?subtest2')
- .then(function(data) {
- assert_equals(data, 'loaded');
- });
- }, 'registration via <link> element `rel` accepted in presence of `allow-same-origin` directive');
-</script>
-</body>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/link-element-register-basic.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/link-element-register-basic.https.html
deleted file mode 100644
index 83f3f482582..00000000000
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/link-element-register-basic.https.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<title>Service Worker: Register via link element (basic)</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/test-helpers.sub.js"></script>
-<script src="resources/registration-tests-basic.js"></script>
-<body>
-<script>
-registration_tests_basic(register_using_link, false);
-</script>
-</body>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/link-element-register-mime-types.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/link-element-register-mime-types.https.html
deleted file mode 100644
index beb7d58b627..00000000000
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/link-element-register-mime-types.https.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<title>Service Worker: Register via link element (MIME types)</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/test-helpers.sub.js"></script>
-<script src="resources/registration-tests-mime-types.js"></script>
-<body>
-<script>
-registration_tests_mime_types(register_using_link, false);
-</script>
-</body>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/link-element-register-scope.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/link-element-register-scope.https.html
deleted file mode 100644
index 1b75c3865fb..00000000000
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/link-element-register-scope.https.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!DOCTYPE html>
-<title>Service Worker: Register via link element (scope)</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/test-helpers.sub.js"></script>
-<script src="resources/registration-tests-scope.js"></script>
-<body>
-<script>
-registration_tests_scope(register_using_link, false);
-</script>
-</body>
-
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/link-element-register-script-url.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/link-element-register-script-url.https.html
deleted file mode 100644
index 48cb9357a80..00000000000
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/link-element-register-script-url.https.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<title>Service Worker: Register via link element (scriptURL)</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/test-helpers.sub.js"></script>
-<script src="resources/registration-tests-script-url.js"></script>
-<body>
-<script>
-registration_tests_script_url(register_using_link, false);
-</script>
-</body>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/link-element-register-script.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/link-element-register-script.https.html
deleted file mode 100644
index 4a2818df8db..00000000000
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/link-element-register-script.https.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<title>Service Worker: Register via link element (script)</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/test-helpers.sub.js"></script>
-<script src="resources/registration-tests-script.js"></script>
-<body>
-<script>
-registration_tests_script(register_using_link, false);
-</script>
-</body>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/link-element-register-security-error.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/link-element-register-security-error.https.html
deleted file mode 100644
index eae421d87e9..00000000000
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/link-element-register-security-error.https.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html>
-<title>Service Worker: Register via link element (SecurityError)</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/test-helpers.sub.js"></script>
-<script src="resources/registration-tests-security-error.js"></script>
-<body>
-<script>
-registration_tests_security_error(register_using_link, false);
-</script>
-</body>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/navigation-redirect.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/navigation-redirect.https.html
index d840666b8c6..3f12c2fdcca 100644
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/navigation-redirect.https.html
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/navigation-redirect.https.html
@@ -156,6 +156,22 @@ promise_test(function(t) {
promise_test(function(t) {
return setup_environment(t).then(function() {
return test_redirect(
+ OUT_SCOPE + 'url=' + encodeURIComponent(SCOPE1) + '#ref',
+ SCOPE1 + '#ref',
+ [[SCOPE1 + '#ref'], [], []]);
+ });
+ }, 'Normal redirect to same-origin scope with a hash fragment.');
+promise_test(function(t) {
+ return setup_environment(t).then(function() {
+ return test_redirect(
+ OUT_SCOPE + 'url=' + encodeURIComponent(SCOPE1 + '#ref2') + '#ref',
+ SCOPE1 + '#ref2',
+ [[SCOPE1 + '#ref2'], [], []]);
+ });
+ }, 'Normal redirect to same-origin scope with different hash fragments.');
+promise_test(function(t) {
+ return setup_environment(t).then(function() {
+ return test_redirect(
OUT_SCOPE + 'url=' + encodeURIComponent(OTHER_ORIGIN_SCOPE),
OTHER_ORIGIN_SCOPE,
[[], [], [OTHER_ORIGIN_SCOPE]]);
@@ -182,6 +198,27 @@ promise_test(function(t) {
promise_test(function(t) {
return setup_environment(t).then(function() {
return test_redirect(
+ SCOPE1 + 'url=' + encodeURIComponent(SCOPE1) + '#ref',
+ SCOPE1 + '#ref',
+ [[SCOPE1 + 'url=' + encodeURIComponent(SCOPE1) + '#ref',
+ SCOPE1 + '#ref'],
+ [], []]);
+ });
+ }, 'SW-fallbacked redirect to same-origin same-scope with a hash fragment.');
+promise_test(function(t) {
+ return setup_environment(t).then(function() {
+ return test_redirect(
+ SCOPE1 + 'url=' + encodeURIComponent(SCOPE1 + '#ref2') + '#ref',
+ SCOPE1 + '#ref2',
+ [[SCOPE1 + 'url=' + encodeURIComponent(SCOPE1 + '#ref2') + '#ref',
+ SCOPE1 + '#ref2'],
+ [], []]);
+ });
+ }, 'SW-fallbacked redirect to same-origin same-scope with different hash ' +
+ 'fragments.');
+promise_test(function(t) {
+ return setup_environment(t).then(function() {
+ return test_redirect(
SCOPE1 + 'url=' + encodeURIComponent(SCOPE2),
SCOPE2,
[[SCOPE1 + 'url=' + encodeURIComponent(SCOPE2)], [SCOPE2], []]);
@@ -221,6 +258,27 @@ promise_test(function(t) {
promise_test(function(t) {
return setup_environment(t).then(function() {
return test_redirect(
+ SCOPE1 + 'sw=gen&url=' + encodeURIComponent(OUT_SCOPE) + '#ref',
+ OUT_SCOPE + '#ref',
+ [[SCOPE1 + 'sw=gen&url=' + encodeURIComponent(OUT_SCOPE) + '#ref'],
+ [], []]);
+ });
+ }, 'SW-generated redirect to same-origin out-scope with a hash fragment.');
+promise_test(function(t) {
+ return setup_environment(t).then(function() {
+ return test_redirect(
+ SCOPE1 + 'sw=gen&url=' + encodeURIComponent(OUT_SCOPE + '#ref2') +
+ '#ref',
+ OUT_SCOPE + '#ref2',
+ [[SCOPE1 + 'sw=gen&url=' + encodeURIComponent(OUT_SCOPE + '#ref2') +
+ '#ref'],
+ [], []]);
+ });
+ }, 'SW-generated redirect to same-origin out-scope with different hash' +
+ 'fragments.');
+promise_test(function(t) {
+ return setup_environment(t).then(function() {
+ return test_redirect(
SCOPE1 + 'sw=gen&url=' + encodeURIComponent(SCOPE1),
SCOPE1,
[[SCOPE1 + 'sw=gen&url=' + encodeURIComponent(SCOPE1), SCOPE1],
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/postmessage.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/postmessage.https.html
index 3a6487ea17a..5c43b954aac 100644
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/postmessage.https.html
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/postmessage.https.html
@@ -13,7 +13,11 @@ promise_test(t => {
return service_worker_unregister_and_register(t, script, scope)
.then(r => {
- t.add_cleanup(() => r.unregister());
+ // TODO: return the Promise created by `r.unregister`once
+ // `testharness.js` has been updated to honor thenables returned by
+ // cleanup functions.
+ // See https://github.com/w3c/web-platform-tests/pull/8748
+ t.add_cleanup(() => { r.unregister(); });
registration = r;
worker = registration.installing;
@@ -62,7 +66,11 @@ promise_test(t => {
return service_worker_unregister_and_register(t, script, scope)
.then(r => {
- t.add_cleanup(() => r.unregister());
+ // TODO: return the Promise created by `r.unregister`once
+ // `testharness.js` has been updated to honor thenables returned by
+ // cleanup functions.
+ // See https://github.com/w3c/web-platform-tests/pull/8748
+ t.add_cleanup(() => { r.unregister(); });
var ab = text_encoder.encode(message);
assert_equals(ab.byteLength, message.length);
@@ -102,7 +110,11 @@ promise_test(t => {
return service_worker_unregister_and_register(t, script, scope)
.then(r => {
- t.add_cleanup(() => r.unregister());
+ // TODO: return the Promise created by `r.unregister`once
+ // `testharness.js` has been updated to honor thenables returned by
+ // cleanup functions.
+ // See https://github.com/w3c/web-platform-tests/pull/8748
+ t.add_cleanup(() => { r.unregister(); });
var channel = new MessageChannel;
port = channel.port1;
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/register-foreign-fetch-errors.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/register-foreign-fetch-errors.https.html
deleted file mode 100644
index 8eae074dae8..00000000000
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/register-foreign-fetch-errors.https.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!DOCTYPE html>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/test-helpers.sub.js"></script>
-<script>
-service_worker_test('resources/register-foreign-fetch-errors-worker.js',
- 'foreign fetch registration');
-</script>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/register-link-header.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/register-link-header.https.html
deleted file mode 100644
index dd71c9b892e..00000000000
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/register-link-header.https.html
+++ /dev/null
@@ -1,73 +0,0 @@
-<!DOCTYPE html>
-<title>Service Worker: Registration using Link header</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/test-helpers.sub.js"></script>
-<body>
-<script>
-function get_newest_worker(registration) {
- if (registration.installing)
- return registration.installing;
- if (registration.waiting)
- return registration.waiting;
- if (registration.active)
- return registration.active;
-}
-
-promise_test(function(t) {
- var scope = normalizeURL('resources/blank.html?fetch');
- var header = '<empty-worker.js>; rel=serviceworker; scope="' + scope + '"';
- var resource = 'resources/link-header.py?Link=' +
- encodeURIComponent(header);
- return with_iframe(scope)
- .then(frame =>
- Promise.all([frame.contentWindow.navigator.serviceWorker.ready,
- fetch(resource)]))
- .then(([registration, response]) => {
- assert_equals(registration.scope, scope);
- assert_equals(get_newest_worker(registration).scriptURL,
- normalizeURL('resources/empty-worker.js'));
- return registration.unregister();
- });
- }, 'fetch can trigger service worker installation');
-
-promise_test(function(t) {
- var scope = normalizeURL('resources/blank.html?iframe');
- var header = '<empty-worker.js>; rel=serviceworker; scope="' + scope + '"';
- var resource = 'resources/link-header.py?Link=' +
- encodeURIComponent(header);
- return with_iframe(scope)
- .then(frame =>
- Promise.all([frame.contentWindow.navigator.serviceWorker.ready,
- with_iframe(resource)]))
- .then(([registration, frame]) => {
- assert_equals(registration.scope, scope);
- assert_equals(get_newest_worker(registration).scriptURL,
- normalizeURL('resources/empty-worker.js'));
- return registration.unregister();
- });
- }, 'An iframe can trigger service worker installation');
-
-promise_test(function(t) {
- var scope = normalizeURL('resources/blank.html?css');
- var header = '<empty-worker.js>; rel=serviceworker; scope="' + scope + '"';
- var resource = 'resources/link-header.py?Link=' +
- encodeURIComponent(header);
- return with_iframe(scope)
- .then(frame => {
- var link = document.createElement('link');
- link.setAttribute('rel', 'stylesheet');
- link.setAttribute('type', 'text/css');
- link.setAttribute('href', resource);
- document.getElementsByTagName('head')[0].appendChild(link);
- return frame.contentWindow.navigator.serviceWorker.ready;
- })
- .then(registration => {
- assert_equals(registration.scope, scope);
- assert_equals(get_newest_worker(registration).scriptURL,
- normalizeURL('resources/empty-worker.js'));
- return registration.unregister();
- });
- }, 'A stylesheet can trigger service worker installation');
-
-</script>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/registration-updateviacache.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/registration-updateviacache.https.html
index 0df401efcc6..b1fd902994f 100644
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/registration-updateviacache.https.html
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/registration-updateviacache.https.html
@@ -32,130 +32,54 @@
});
}
- function registerViaApi(scriptUrl, opts) {
- return navigator.serviceWorker.register(scriptUrl, opts);
- }
-
- function registerViaLinkElement(scriptUrl, opts) {
- return new Promise((resolve, reject) => {
- const link = document.createElement('link');
-
- if (link.relList.supports('serviceworker') == false) throw Error("link rel=serviceworker not supported");
-
- link.rel = 'serviceworker';
- link.href = scriptUrl;
- link.scope = opts.scope;
-
- if (opts.updateViaCache) {
- link.updateViaCache = opts.updateViaCache;
- }
-
- link.onload = async () => {
- const fullScope = new URL(opts.scope, window.location).href;
-
- const regs = await navigator.serviceWorker.getRegistrations();
- const reg = regs.find(r => r.scope == fullScope && (r.installing || r.waiting || r.active));
-
- if (reg) {
- document.head.removeChild(link);
- resolve(reg);
- }
- else {
- reject(Error('Service worker not registered'));
- }
- };
-
- document.head.appendChild(link);
- });
- }
-
- async function registerViaLinkHeader(scriptUrl, opts) {
- const link = document.createElement('link');
-
- const fullScope = new URL(opts.scope, window.location).href;
- scriptUrl = new URL(scriptUrl, location).href;
-
- // Assume that if the link element doesn't support serviceworker, the header doesn't either.
- if (link.relList.supports('serviceworker') == false) throw Error("link rel=serviceworker not supported");
-
- let linkHeader = `<${scriptUrl}>; rel=serviceworker; scope="${fullScope}"`;
-
- if (opts.updateViaCache) {
- linkHeader += `; updateviacache="${opts.updateViaCache}"`;
- }
-
- const linkHeaderSenderURL = new URL('resources/link-header.py', location);
- linkHeaderSenderURL.searchParams.set('Link', linkHeader);
-
- await fetch(linkHeaderSenderURL);
- const frame = await with_iframe(fullScope);
- await frame.contentWindow.navigator.serviceWorker.ready;
-
- const regs = await navigator.serviceWorker.getRegistrations();
- const reg = regs.find(r => r.scope == fullScope && (r.installing || r.waiting || r.active));
-
- if (!reg) throw Error('Service worker not registered');
-
- frame.parentNode.removeChild(frame);
- return reg;
- }
-
- const registrationMethods = [
- [registerViaApi, 'via-api'],
- [registerViaLinkElement, 'via-link-element'],
- [registerViaLinkHeader, 'via-link-header']
- ];
-
// Test creating registrations & triggering an update.
- for (const [registrationMethod, registrationMethodName] of registrationMethods) {
- for (const updateViaCache of UPDATE_VIA_CACHE_VALUES) {
- const testName = `register-${registrationMethodName}-updateViaCache-${updateViaCache}`;
+ for (const updateViaCache of UPDATE_VIA_CACHE_VALUES) {
+ const testName = `register-with-updateViaCache-${updateViaCache}`;
- promise_test(async t => {
- await cleanup();
+ promise_test(async t => {
+ await cleanup();
- const opts = {scope: SCOPE};
+ const opts = {scope: SCOPE};
- if (updateViaCache) opts.updateViaCache = updateViaCache;
+ if (updateViaCache) opts.updateViaCache = updateViaCache;
- const reg = await registrationMethod(
- `${SCRIPT_URL}?test=${testName}`,
- opts
- );
+ const reg = await navigator.serviceWorker.register(
+ `${SCRIPT_URL}?test=${testName}`,
+ opts
+ );
- assert_equals(reg.updateViaCache, updateViaCache || 'imports', "reg.updateViaCache");
+ assert_equals(reg.updateViaCache, updateViaCache || 'imports', "reg.updateViaCache");
- const sw = reg.installing || reg.waiting || reg.active;
- await wait_for_state(t, sw, 'activated');
- const values = await getScriptTimes(sw, testName);
- await reg.update();
+ const sw = reg.installing || reg.waiting || reg.active;
+ await wait_for_state(t, sw, 'activated');
+ const values = await getScriptTimes(sw, testName);
+ await reg.update();
- if (updateViaCache == 'all') {
- assert_equals(reg.installing, null, "No new service worker");
+ if (updateViaCache == 'all') {
+ assert_equals(reg.installing, null, "No new service worker");
+ }
+ else {
+ const newWorker = reg.installing;
+ assert_true(!!newWorker, "New worker installing");
+ const newValues = await getScriptTimes(newWorker, testName);
+
+ if (!updateViaCache || updateViaCache == 'imports') {
+ assert_not_equals(values.mainTime, newValues.mainTime, "Main script should have updated");
+ assert_equals(values.importTime, newValues.importTime, "Imported script should be the same");
+ }
+ else if (updateViaCache == 'none') {
+ assert_not_equals(values.mainTime, newValues.mainTime, "Main script should have updated");
+ assert_not_equals(values.importTime, newValues.importTime, "Imported script should have updated");
}
else {
- const newWorker = reg.installing;
- assert_true(!!newWorker, "New worker installing");
- const newValues = await getScriptTimes(newWorker, testName);
-
- if (!updateViaCache || updateViaCache == 'imports') {
- assert_not_equals(values.mainTime, newValues.mainTime, "Main script should have updated");
- assert_equals(values.importTime, newValues.importTime, "Imported script should be the same");
- }
- else if (updateViaCache == 'none') {
- assert_not_equals(values.mainTime, newValues.mainTime, "Main script should have updated");
- assert_not_equals(values.importTime, newValues.importTime, "Imported script should have updated");
- }
- else {
- // We should have handled all of the possible values for updateViaCache.
- // If this runs, something's gone very wrong.
- throw Error(`Unexpected updateViaCache value: ${updateViaCache}`);
- }
+ // We should have handled all of the possible values for updateViaCache.
+ // If this runs, something's gone very wrong.
+ throw Error(`Unexpected updateViaCache value: ${updateViaCache}`);
}
+ }
- await cleanup();
- }, testName);
- }
+ await cleanup();
+ }, testName);
}
// Test changing the updateViaCache value of an existing registration.
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resource-timing.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resource-timing.https.html
index c38bfc9efa5..da898e2bf6d 100644
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/resource-timing.https.html
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resource-timing.https.html
@@ -8,13 +8,25 @@ function resourceUrl(path) {
return get_host_info()['HTTPS_ORIGIN'] + base_path() + path;
}
-function verify(performance, resource, description) {
- var entry = performance.getEntriesByName(resourceUrl(resource))[0];
+function crossOriginUrl(path) {
+ return get_host_info()['HTTPS_REMOTE_ORIGIN'] + base_path() + path;
+}
+
+function verify(performance, resource, mode, description) {
+ var url = mode === 'cross-origin' ? crossOriginUrl(resource)
+ : resourceUrl(resource);
+ var entryList = performance.getEntries();
+ var entry = performance.getEntriesByName(url)[0];
assert_greater_than(entry.workerStart, 0, description);
assert_greater_than_equal(entry.workerStart, entry.startTime, description);
assert_less_than_equal(entry.workerStart, entry.fetchStart, description);
- assert_greater_than_equal(entry.responseStart, entry.fetchStart, description);
- assert_greater_than_equal(entry.responseEnd, entry.responseStart, description);
+ if (mode === 'cross-origin') {
+ assert_equals(entry.responseStart, 0, description);
+ assert_greater_than_equal(entry.responseEnd, entry.fetchStart, description);
+ } else {
+ assert_greater_than_equal(entry.responseStart, entry.fetchStart, description);
+ assert_greater_than_equal(entry.responseEnd, entry.responseStart, description);
+ }
assert_greater_than(entry.responseEnd, entry.fetchStart, description);
assert_greater_than(entry.duration, 0, description);
if (resource.indexOf('redirect.py') != -1) {
@@ -27,7 +39,7 @@ function verify(performance, resource, description) {
async_test(function(t) {
var worker_url = 'resources/resource-timing-worker.js';
- var scope = 'resources/resource-timing-iframe.html';
+ var scope = 'resources/resource-timing-iframe.sub.html';
var registration;
service_worker_unregister_and_register(t, worker_url, scope)
@@ -40,10 +52,20 @@ async_test(function(t) {
})
.then(function(frame) {
var performance = frame.contentWindow.performance;
- verify(performance, 'resources/dummy.js', 'Generated response');
- verify(performance, 'resources/empty.js', 'Network fallback');
+ verify(performance, 'resources/dummy.js', 'same-origin',
+ 'Generated response');
+ verify(performance, 'resources/empty.js', 'same-origin',
+ 'Network fallback');
verify(performance, 'resources/redirect.py?Redirect=empty.js',
- 'Redirect');
+ 'same-origin', 'Redirect');
+ verify(performance, 'resources/missing.jpg', 'same-origin',
+ 'Network fallback image');
+
+ // Test that worker start is available on cross-origin no-cors
+ // subresources.
+ verify(performance, 'resources/missing.jpg', 'cross-origin',
+ 'Network fallback cross-origin image');
+
frame.remove();
return registration.unregister();
})
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/about-blank-replacement-frame.py b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/about-blank-replacement-frame.py
new file mode 100644
index 00000000000..643142dbea1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/about-blank-replacement-frame.py
@@ -0,0 +1,31 @@
+def main(request, response):
+ if 'nested' in request.GET:
+ return (
+ [('Content-Type', 'text/html')],
+ 'failed: nested frame was not intercepted by the service worker'
+ )
+
+ return ([('Content-Type', 'text/html')], """
+<!doctype html>
+<html>
+<body>
+<script>
+function nestedLoaded() {
+ parent.postMessage({ type: 'NESTED_LOADED' }, '*');
+}
+</script>
+<iframe src="?nested=true" id="nested" onload="nestedLoaded()"></iframe>
+<script>
+// Helper routine to make it slightly easier for our parent to find
+// the nested frame.
+function nested() {
+ return document.getElementById('nested').contentWindow;
+}
+
+// NOTE: Make sure not to touch the iframe directly here. We want to
+// test the case where the initial about:blank document is not
+// directly accessed before load.
+</script>
+</body>
+</html>
+""")
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/about-blank-replacement-ping-frame.py b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/about-blank-replacement-ping-frame.py
new file mode 100644
index 00000000000..58fb4403f9c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/about-blank-replacement-ping-frame.py
@@ -0,0 +1,48 @@
+def main(request, response):
+ if 'nested' in request.GET:
+ return (
+ [('Content-Type', 'text/html')],
+ 'failed: nested frame was not intercepted by the service worker'
+ )
+
+ return ([('Content-Type', 'text/html')], """
+<!doctype html>
+<html>
+<body>
+<script>
+function nestedLoaded() {
+ parent.postMessage({ type: 'NESTED_LOADED' }, '*');
+}
+</script>
+<iframe src="?nested=true&amp;ping=true" id="nested" onload="nestedLoaded()"></iframe>
+<script>
+// Helper routine to make it slightly easier for our parent to find
+// the nested frame.
+function nested() {
+ return document.getElementById('nested').contentWindow;
+}
+
+// This modifies the nested iframe immediately and does not wait for it to
+// load. This effectively modifies the global for the initial about:blank
+// document. Any modifications made here should be preserved after the
+// frame loads because the global should be re-used.
+let win = nested();
+if (win.location.href !== 'about:blank') {
+ parent.postMessage({
+ type: 'NESTED_LOADED',
+ result: 'failed: nested iframe does not have an initial about:blank URL'
+ }, '*');
+} else {
+ win.navigator.serviceWorker.addEventListener('message', evt => {
+ if (evt.data.type === 'PING') {
+ evt.source.postMessage({
+ type: 'PONG',
+ location: win.location.toString()
+ });
+ }
+ });
+}
+</script>
+</body>
+</html>
+""")
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/about-blank-replacement-popup-frame.py b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/about-blank-replacement-popup-frame.py
new file mode 100644
index 00000000000..f0b8cd578e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/about-blank-replacement-popup-frame.py
@@ -0,0 +1,32 @@
+def main(request, response):
+ if 'nested' in request.GET:
+ return (
+ [('Content-Type', 'text/html')],
+ 'failed: nested frame was not intercepted by the service worker'
+ )
+
+ return ([('Content-Type', 'text/html')], """
+<!doctype html>
+<html>
+<body>
+<script>
+function nestedLoaded() {
+ parent.postMessage({ type: 'NESTED_LOADED' }, '*');
+}
+
+let popup = window.open('?nested=true');
+popup.onload = nestedLoaded;
+
+addEventListener('unload', evt => {
+ popup.close();
+}, { once: true });
+
+// Helper routine to make it slightly easier for our parent to find
+// the nested popup window.
+function nested() {
+ return popup;
+}
+</script>
+</body>
+</html>
+""")
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/about-blank-replacement-uncontrolled-nested-frame.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/about-blank-replacement-uncontrolled-nested-frame.html
new file mode 100644
index 00000000000..89509159a41
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/about-blank-replacement-uncontrolled-nested-frame.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<html>
+<body>
+<script>
+function nestedLoaded() {
+ parent.postMessage({ type: 'NESTED_LOADED' }, '*');
+}
+</script>
+<iframe src="empty.html?nested=true" id="nested" onload="nestedLoaded()"></iframe>
+<script>
+// Helper routine to make it slightly easier for our parent to find
+// the nested frame.
+function nested() {
+ return document.getElementById('nested').contentWindow;
+}
+
+// NOTE: Make sure not to touch the iframe directly here. We want to
+// test the case where the initial about:blank document is not
+// directly accessed before load.
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/about-blank-replacement-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/about-blank-replacement-worker.js
new file mode 100644
index 00000000000..f43598e41c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/about-blank-replacement-worker.js
@@ -0,0 +1,95 @@
+// Helper routine to find a client that matches a particular URL. Note, we
+// require that Client to be controlled to avoid false matches with other
+// about:blank windows the browser might have. The initial about:blank should
+// inherit the controller from its parent.
+async function getClientByURL(url) {
+ let list = await clients.matchAll();
+ return list.find(client => client.url === url);
+}
+
+// Helper routine to perform a ping-pong with the given target client. We
+// expect the Client to respond with its location URL.
+async function pingPong(target) {
+ function waitForPong() {
+ return new Promise(resolve => {
+ self.addEventListener('message', function onMessage(evt) {
+ if (evt.data.type === 'PONG') {
+ resolve(evt.data.location);
+ }
+ });
+ });
+ }
+
+ target.postMessage({ type: 'PING' })
+ return await waitForPong(target);
+}
+
+addEventListener('fetch', async evt => {
+ let url = new URL(evt.request.url);
+ if (!url.searchParams.get('nested')) {
+ return;
+ }
+
+ evt.respondWith(async function() {
+ // Find the initial about:blank document.
+ const client = await getClientByURL('about:blank');
+ if (!client) {
+ return new Response('failure: could not find about:blank client');
+ }
+
+ // If the nested frame is configured to support a ping-pong, then
+ // ping it now to verify its message listener exists. We also
+ // verify the Client's idea of its own location URL while we are doing
+ // this.
+ if (url.searchParams.get('ping')) {
+ const loc = await pingPong(client);
+ if (loc !== 'about:blank') {
+ return new Response(`failure: got location {$loc}, expected about:blank`);
+ }
+ }
+
+ // Finally, allow the nested frame to complete loading. We place the
+ // Client ID we found for the initial about:blank in the body.
+ return new Response(client.id);
+ }());
+});
+
+addEventListener('message', evt => {
+ if (evt.data.type !== 'GET_CLIENT_ID') {
+ return;
+ }
+
+ evt.waitUntil(async function() {
+ let url = new URL(evt.data.url);
+
+ // Find the given Client by its URL.
+ let client = await getClientByURL(evt.data.url);
+ if (!client) {
+ evt.source.postMessage({
+ type: 'GET_CLIENT_ID',
+ result: `failure: could not find ${evt.data.url} client`
+ });
+ return;
+ }
+
+ // If the Client supports a ping-pong, then do it now to verify
+ // the message listener exists and its location matches the
+ // Client object.
+ if (url.searchParams.get('ping')) {
+ let loc = await pingPong(client);
+ if (loc !== evt.data.url) {
+ evt.source.postMessage({
+ type: 'GET_CLIENT_ID',
+ result: `failure: got location ${loc}, expected ${evt.data.url}`
+ });
+ return;
+ }
+ }
+
+ // Finally, send the client ID back.
+ evt.source.postMessage({
+ type: 'GET_CLIENT_ID',
+ result: client.id
+ });
+ }());
+});
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/clients-get-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/clients-get-worker.js
index 77c99e83521..79a1ce7b757 100644
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/clients-get-worker.js
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/clients-get-worker.js
@@ -4,9 +4,9 @@
// the `event` object. In the case of the `onmessage` handler, it provides the
// Client instance attributes of the requested clients.
self.onfetch = function(e) {
- if (e.request.mode === 'navigate' && e.clientId !== null) {
+ if (e.request.mode === 'navigate' && e.clientId !== "") {
e.respondWith(Response.error(
- '`clientId` incorrectly set to non-null value for request with mode `navigate`'
+ '`clientId` incorrectly set to non-empty string for request with mode `navigate`'
));
return;
}
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-cors-exposed-header-names-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-cors-exposed-header-names-worker.js
new file mode 100644
index 00000000000..145952a22cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-cors-exposed-header-names-worker.js
@@ -0,0 +1,3 @@
+self.addEventListener('fetch', (e) => {
+ e.respondWith(fetch(e.request));
+ });
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-respond-with-custom-response-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-respond-with-custom-response-worker.js
new file mode 100644
index 00000000000..ff24aed1282
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-respond-with-custom-response-worker.js
@@ -0,0 +1,45 @@
+'use strict';
+
+addEventListener('fetch', event => {
+ const url = new URL(event.request.url);
+ const type = url.searchParams.get('type');
+
+ if (!type) return;
+
+ if (type === 'string') {
+ event.respondWith(new Response('PASS'));
+ }
+ else if (type === 'blob') {
+ event.respondWith(
+ new Response(new Blob(['PASS']))
+ );
+ }
+ else if (type === 'buffer-view') {
+ const encoder = new TextEncoder();
+ event.respondWith(
+ new Response(encoder.encode('PASS'))
+ );
+ }
+ else if (type === 'buffer') {
+ const encoder = new TextEncoder();
+ event.respondWith(
+ new Response(encoder.encode('PASS').buffer)
+ );
+ }
+ else if (type === 'form-data') {
+ const body = new FormData();
+ body.set('result', 'PASS');
+ event.respondWith(
+ new Response(body)
+ );
+ }
+ else if (type === 'search-params') {
+ const body = new URLSearchParams();
+ body.set('result', 'PASS');
+ event.respondWith(
+ new Response(body, {
+ headers: { 'Content-Type': 'text/plain' }
+ })
+ );
+ }
+});
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-respond-with-readable-stream-iframe.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-respond-with-readable-stream-iframe.html
deleted file mode 100644
index 1904d75657d..00000000000
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-respond-with-readable-stream-iframe.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<script>
-'use strict';
-
-fetch('body-stream').then(resp => {
- return resp.text();
- }).then(text => parent.done(text))
- .catch(e => parent.done('FAIL: ' + e));
-</script>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-respond-with-readable-stream-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-respond-with-readable-stream-worker.js
index ddaba55fa7b..aaabdc391a9 100644
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-respond-with-readable-stream-worker.js
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-respond-with-readable-stream-worker.js
@@ -1,13 +1,37 @@
'use strict';
+importScripts("/resources/testharness.js");
self.addEventListener('fetch', event => {
- if (!event.request.url.match(/body-stream$/))
- return;
+ const url = new URL(event.request.url);
+ if (!url.searchParams.has('stream')) return;
- const stream = new ReadableStream({start: controller => {
- const encoder = new TextEncoder();
+ if (url.searchParams.has('use-fetch-stream')) {
+ event.respondWith(async function() {
+ const response = await fetch('pass.txt');
+ return new Response(response.body);
+ }());
+ return;
+ }
+
+ const delayEnqueue = url.searchParams.has('delay');
+
+ const stream = new ReadableStream({
+ start(controller) {
+ const encoder = new TextEncoder();
+
+ const populate = () => {
controller.enqueue(encoder.encode('PASS'));
controller.close();
- }});
- event.respondWith(new Response(stream));
+ }
+
+ if (delayEnqueue) {
+ step_timeout(populate, 16);
+ }
+ else {
+ populate();
+ }
+ }
});
+
+ event.respondWith(new Response(stream));
+});
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-test-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-test-worker.js
index 3d8eb0b212c..65025d93409 100644
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-test-worker.js
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/fetch-event-test-worker.js
@@ -29,7 +29,7 @@ function handleReferrerFull(event) {
function handleClientId(event) {
var body;
- if (event.clientId !== null) {
+ if (event.clientId !== "") {
body = 'Client ID Found: ' + event.clientId;
} else {
body = 'Client ID Not Found';
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-cors-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-cors-worker.js
deleted file mode 100644
index b19d0749c2f..00000000000
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-cors-worker.js
+++ /dev/null
@@ -1,30 +0,0 @@
-importScripts('/common/get-host-info.sub.js');
-var host_info = get_host_info();
-
-self.addEventListener('install', function(event) {
- event.registerForeignFetch({scopes: [registration.scope], origins: ['*']});
- });
-
-self.addEventListener('foreignfetch', function(event) {
- var response = JSON.parse(decodeURIComponent(location.search.substring(1)));
- var url = new URL(event.request.url);
- var params = JSON.parse(decodeURIComponent(url.search.substring(1)));
- var url_to_fetch = 'fetch-access-control.py?';
- if (params.cross_origin) {
- url_to_fetch =
- host_info.HTTPS_ORIGIN + new URL('./', location).pathname + url_to_fetch;
- }
- if (params.with_aceheaders)
- url_to_fetch += 'ACEHeaders=X-ServiceWorker-ServerHeader&';
- if (params.with_acaorigin)
- url_to_fetch += 'ACAOrigin=*';
- fetch_params = {};
- if (params.cross_origin && !params.with_acaorigin)
- fetch_params.mode = 'no-cors';
- event.respondWith(fetch(url_to_fetch, fetch_params)
- .then(r => {
- response.response = r;
- return response;
- }));
- return;
- });
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-event-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-event-worker.js
deleted file mode 100644
index 63f996e0895..00000000000
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-event-worker.js
+++ /dev/null
@@ -1,31 +0,0 @@
-self.addEventListener('install', function(event) {
- test(function() {
- assert_throws(new TypeError(), function() {
- new ForeignFetchEvent('type');
- });
- }, 'ForeignFetchEvent constructor with no init dict');
-
- test(function() {
- assert_throws(new TypeError(), function() {
- new ForeignFetchEvent('type', {});
- });
- }, 'ForeignFetchEvent constructor with empty init dict');
-
- test(function() {
- assert_throws(new TypeError(), function() {
- new ForeignFetchEvent('type', { request: null });
- });
- }, 'ForeignFetchEvent constructor with null request');
-
- test(function() {
- var request = new Request('https://www.example.com/');
- var event = new ForeignFetchEvent('type', { request: request, origin: 'origin' });
- assert_equals(event.type, 'type');
- assert_equals(event.request, request);
- assert_equals(event.origin, 'origin');
- }, 'ForeignFetchEvent constructor with all init dict members');
- });
-
-// Import testharness after install handler to make sure our install handler
-// runs first. Otherwise only one test will run.
-importScripts('/resources/testharness.js');
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-helper-iframe.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-helper-iframe.html
deleted file mode 100644
index 722843a09fa..00000000000
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-helper-iframe.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<script src="foreign-fetch-helper-script.js"></script>
-<script>
-self.onmessage = e => {
- if (e.data.worker == 'dedicated') {
- let worker = new Worker('foreign-fetch-helper-script.js');
- worker.postMessage(e.data, e.ports);
- } else if (e.data.worker == 'shared') {
- let worker = new SharedWorker('foreign-fetch-helper-script.js');
- worker.port.postMessage(e.data, e.ports);
- } else {
- handle_message(e);
- }
- };
-if (self.opener) self.opener.postMessage('ready', '*');
-</script>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-helper-script.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-helper-script.js
deleted file mode 100644
index 5ecaa9e3616..00000000000
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-helper-script.js
+++ /dev/null
@@ -1,11 +0,0 @@
-function handle_message(e) {
- fetch(e.data.url)
- .then(response => response.text())
- .then(text => e.ports[0].postMessage('Success: ' + text))
- .catch(error => e.ports[0].postMessage('Error: ' + error));
-}
-
-self.onmessage = handle_message;
-self.onconnect = e => {
- e.ports[0].onmessage = handle_message;
-};
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-helper-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-helper-worker.js
deleted file mode 100644
index ce596044bd1..00000000000
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-helper-worker.js
+++ /dev/null
@@ -1,8 +0,0 @@
-importScripts('/common/get-host-info.sub.js');
-const host_info = get_host_info();
-
-self.onfetch = e => {
- const remote_url = host_info.HTTPS_REMOTE_ORIGIN +
- new URL('./', location).pathname + 'simple.txt?basic_sw';
- e.respondWith(fetch(remote_url));
-};
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-helpers.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-helpers.js
deleted file mode 100644
index e1831ed173c..00000000000
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-helpers.js
+++ /dev/null
@@ -1,44 +0,0 @@
-// Common helper functions for foreign fetch tests.
-
-// Installs a service worker on a different origin. Both |worker| and |scope|
-// are resolved relative to the /service-workers/service-worker/resources/
-// directory on a remote origin.
-function install_cross_origin_worker(
- t, worker, scope, origin = get_host_info().HTTPS_REMOTE_ORIGIN) {
- return with_iframe(origin + new URL('resources/install-worker-helper.html', location).pathname)
- .then(frame => new Promise((resolve, reject) => {
- frame.contentWindow.postMessage({worker: worker,
- options: {scope: scope}},
- '*');
- window.addEventListener('message', reply => {
- if (reply.source != frame.contentWindow) return;
- if (reply.data == 'success') resolve();
- else reject(reply.data);
- });
- }));
-}
-
-// Performs a fetch from a different origin. By default this performs a fetch
-// from a window on that origin, but if |worker_type| is 'dedicated' or 'shared'
-// the fetch is made from a worker on that origin instead.
-// This uses a window rather than an iframe because an iframe might get blocked
-// by mixed content checks.
-function fetch_from_different_origin(origin, url, worker_type) {
- const win = open(origin + new URL('resources/foreign-fetch-helper-iframe.html', location).pathname);
- return new Promise(resolve => {
- self.addEventListener('message', e => {
- if (e.source != win) return;
- resolve();
- });
- })
- .then(() => new Promise((resolve) => {
- const channel = new MessageChannel();
- win.postMessage({url: url,
- worker: worker_type},
- '*', [channel.port1]);
- channel.port2.onmessage = reply => {
- win.close();
- resolve(reply.data);
- };
- }));
-}
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-worker.js
deleted file mode 100644
index 55a740753fc..00000000000
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/foreign-fetch-worker.js
+++ /dev/null
@@ -1,78 +0,0 @@
-self.addEventListener('install', function(event) {
- var params = JSON.parse(decodeURIComponent(location.search.substring(1)));
- if (!('scopes' in params)) {
- if ('relscopes' in params) {
- params.scopes = params.relscopes.map(s => registration.scope + s);
- } else {
- params.scopes = [registration.scope];
- }
- }
- if (!('origins' in params))
- params.origins = ['*'];
- event.registerForeignFetch(params);
- });
-
-function handle_basic(event) {
- event.respondWith({response: new Response('Foreign Fetch'), origin: event.origin});
-}
-
-function handle_null(event) {
- event.respondWith({response: null });
-}
-
-function handle_onmessage(event) {
- event.respondWith({origin: event.origin, response:
- new Response('<script>window.onmessage = e => e.ports[0].postMessage("failed");</script>',
- {headers: {'Content-Type': 'text/html'}})});
-}
-
-function handle_fallback(event) {
- // Do nothing.
-}
-
-function handle_fetch(event) {
- event.respondWith(
- fetch(event.request).then(response => ({response, origin: event.origin})));
-}
-
-function handle_meta(event) {
- var data = {
- origin: event.origin,
- referrer: event.request.referrer
- };
- event.respondWith({response: new Response(JSON.stringify(data)),
- origin: event.origin});
-}
-
-function handle_script(event) {
- event.respondWith({origin: event.origin, response:
- new Response('self.DidLoad("Foreign Fetch");')});
-}
-
-self.addEventListener('foreignfetch', function(event) {
- var url = event.request.url;
- var handlers = [
- { pattern: '?basic', fn: handle_basic },
- { pattern: '?null', fn: handle_null },
- { pattern: '?fallback', fn: handle_fallback },
- { pattern: '?fetch', fn: handle_fetch },
- { pattern: '?onmessage', fn: handle_onmessage },
- { pattern: '?meta', fn: handle_meta },
- { pattern: '?script', fn: handle_script }
- ];
-
- var handler = null;
- for (var i = 0; i < handlers.length; ++i) {
- if (url.indexOf(handlers[i].pattern) != -1) {
- handler = handlers[i];
- break;
- }
- }
-
- if (handler) {
- handler.fn(event);
- } else {
- event.respondWith({origin: event.origin,
- response: new Response('unexpected request')});
- }
- });
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/iframe-register-link-element.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/iframe-register-link-element.html
deleted file mode 100644
index db5bf230e89..00000000000
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/iframe-register-link-element.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<script>
-'use strict';
-var link = document.createElement('link');
-link.setAttribute('rel', 'serviceworker');
-link.setAttribute('href', 'empty-worker.js');
-function report(result) {
- top.postMessage({id: location.search, result: result}, '*');
-};
-link.onload = function() {
- report('loaded');
-};
-link.onerror = function() {
- report('error');
-};
-document.getElementsByTagName('head')[0].appendChild(link);
-</script>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/install-worker-helper.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/install-worker-helper.html
deleted file mode 100644
index fcb8f6d83c7..00000000000
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/install-worker-helper.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<script src="test-helpers.sub.js"></script>
-<script>
-window.addEventListener('message', event => {
- navigator.serviceWorker.getRegistration(event.data.options.scope)
- .then(r => {
- if (r) return r.unregister();
- })
- .then(() => navigator.serviceWorker.register(event.data.worker,
- event.data.options))
- .then(r => new Promise(resolve => {
- window.addEventListener('unload', () => r.unregister());
- var worker = r.installing;
- worker.addEventListener('statechange', () => {
- if (worker.state === 'activated') resolve();
- });
- }))
- .then(() => event.source.postMessage('success', '*'))
- .catch((e) => event.source.postMessage('failure:' + e, '*'));
- });
-</script>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/interfaces-idls.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/interfaces-idls.js
index 814a5df4617..9f5c5ed9675 100644
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/interfaces-idls.js
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/interfaces-idls.js
@@ -23,7 +23,6 @@ interface ServiceWorkerGlobalScope : WorkerGlobalScope {
attribute EventHandler oninstall;
attribute EventHandler onactivate;
attribute EventHandler onfetch;
- attribute EventHandler onforeignfetch;
// event
attribute EventHandler onmessage; // event.source of the message events is Client object
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/interfaces-worker.sub.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/interfaces-worker.sub.js
index 89cf5033178..7bdf1016215 100644
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/interfaces-worker.sub.js
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/interfaces-worker.sub.js
@@ -55,10 +55,7 @@ test(function() {
false, 'Default FetchEvent.bubbles should be false');
assert_equals(
new FetchEvent('FetchEvent', {request: req}).clientId,
- null, 'Default FetchEvent.clientId should be null');
- assert_equals(
- new FetchEvent('FetchEvent', {request: req}).isReload,
- false, 'Default FetchEvent.isReload should be false');
+ '', 'Default FetchEvent.clientId should be the empty string');
assert_equals(
new FetchEvent('FetchEvent', {request: req, cancelable: false}).cancelable,
false, 'FetchEvent.cancelable should be false');
@@ -66,12 +63,14 @@ test(function() {
new FetchEvent('FetchEvent', {request: req, clientId : 'test-client-id'}).clientId, 'test-client-id',
'FetchEvent.clientId with option {clientId : "test-client-id"} should be "test-client-id"');
assert_equals(
- new FetchEvent('FetchEvent', {request: req, isReload : true}).isReload, true,
- 'FetchEvent.isReload with option {isReload : true} should be true');
- assert_equals(
- new FetchEvent('FetchEvent', {request : req, isReload : true}).request.url,
+ new FetchEvent('FetchEvent', {request : req}).request.url,
'http://{{host}}/',
'FetchEvent.request.url should return the value it was initialized to');
+ assert_equals(
+ new FetchEvent('FetchEvent', {request : req}).isReload,
+ undefined,
+ 'FetchEvent.isReload should not exist');
+
}, 'Event constructors');
test(() => {
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/link-header.py b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/link-header.py
deleted file mode 100644
index 1ea37c31218..00000000000
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/link-header.py
+++ /dev/null
@@ -1,4 +0,0 @@
-def main(request, response):
- if 'Link' in request.GET:
- return [('Link', request.GET['Link'])], ""
- return [], ""
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/pass.txt b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/pass.txt
new file mode 100644
index 00000000000..7ef22e9a431
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/pass.txt
@@ -0,0 +1 @@
+PASS
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/register-foreign-fetch-errors-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/register-foreign-fetch-errors-worker.js
deleted file mode 100644
index d1facc89ca8..00000000000
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/register-foreign-fetch-errors-worker.js
+++ /dev/null
@@ -1,134 +0,0 @@
-self.addEventListener('install', function(event) {
- var scope = registration.scope;
- var scope_url = new URL(scope);
-
- test(function() {
- assert_throws(new TypeError(), function() {
- event.registerForeignFetch({});
- });
- }, 'Invalid options');
-
- test(function() {
- assert_throws(new TypeError(), function() {
- event.registerForeignFetch({scopes: scope, origins: ['*']});
- });
- }, 'Scopes not an array');
-
- test(function() {
- assert_throws(new TypeError(), function() {
- event.registerForeignFetch({scopes: [{}], origins: ['*']});
- });
- }, 'Scopes not a string in array');
-
- test(function() {
- assert_throws(new TypeError(), function() {
- event.registerForeignFetch({scopes: ['/foo'], origins: ['*']});
- });
- }, 'Relative url not under scope');
-
- test(function() {
- var url = new URL(scope_url);
- url.host = 'example.com';
- assert_throws(new TypeError(), function() {
- event.registerForeignFetch({scopes: [url.href], origins: ['*']});
- });
- }, 'Absolute url not under scope');
-
- test(function() {
- assert_throws(new TypeError(), function() {
- event.registerForeignFetch({scopes: [], origins: ['*']});
- });
- }, 'Empty scope array');
-
- async_test(function(t) {
- self.setTimeout(t.step_func(function() {
- assert_throws('InvalidStateError', function() {
- event.registerForeignFetch({scopes: [scope], origins: ['*']});
- });
- t.done();
- }), 1);
- }, 'Call after event returned');
-
- test(function() {
- event.registerForeignFetch({scopes: [scope], origins: ['*']});
- }, 'Valid scopes with wildcard origin string');
-
- test(function() {
- event.registerForeignFetch({scopes: [scope, scope + '/foo'], origins: ['*']});
- }, 'Absolute urls');
-
- test(function() {
- // Figure out scope relative to location of this script:
- var local_dir = location.pathname;
- local_dir = local_dir.substr(0, local_dir.lastIndexOf('/'));
- assert_true(scope_url.pathname.startsWith(local_dir));
- var relative_scope = scope_url.pathname.substr(local_dir.length + 1);
-
- event.registerForeignFetch({scopes: [
- scope_url.pathname,
- relative_scope,
- './' + relative_scope,
- relative_scope + '/foo'], origins: ['*']});
- }, 'Relative urls');
-
- test(function() {
- assert_throws(new TypeError(), function() {
- event.registerForeignFetch({scopes: [scope]});
- });
- }, 'No origins specified');
-
- test(function() {
- assert_throws(new TypeError(), function() {
- event.registerForeignFetch({scopes: [scope], origins: {}});
- });
- }, 'Origins not a string or array');
-
- test(function() {
- assert_throws(new TypeError(), function() {
- event.registerForeignFetch({scopes: [scope], origins: [{}]});
- });
- }, 'Origins contains something not a string');
-
- test(function() {
- assert_throws(new TypeError(), function() {
- event.registerForeignFetch({scopes: [scope], origins: ['/foo']});
- });
- }, 'Origin not an absolute URL');
-
- test(function() {
- event.registerForeignFetch({scopes: [scope], origins: ['*']});
- }, 'Wildcard origin string in array');
-
- test(function() {
- assert_throws(new TypeError(), function() {
- event.registerForeignFetch({scopes: [scope], origins: 'https://example.com/'});
- });
- }, 'Origin string');
-
- test(function() {
- event.registerForeignFetch({scopes: [scope], origins: ['https://example.com/']});
- }, 'Origin string in array');
-
- test(function() {
- event.registerForeignFetch({
- scopes: [scope], origins: ['https://example.com/', 'https://chromium.org']});
- }, 'Array with multiple origins');
-
- test(function() {
- assert_throws(new TypeError(), function() {
- event.registerForeignFetch({scopes: [scope],
- origins: ['*', 'https://example.com/']});
- });
- }, 'Origins includes wildcard and other strings');
-
- test(function() {
- assert_throws(new TypeError(), function() {
- event.registerForeignFetch({scopes: [scope],
- origins: ['https://example.com/', '*']});
- });
- }, 'Origins includes other strings and wildcard');
- });
-
-// Import testharness after install handler to make sure our install handler
-// runs first. Otherwise only one test will run.
-importScripts('/resources/testharness.js');
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/resource-timing-iframe.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/resource-timing-iframe.html
deleted file mode 100644
index 2af6793696b..00000000000
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/resource-timing-iframe.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<!DOCTYPE html>
-<script src="empty.js"></script>
-<script src="dummy.js"></script>
-<script src="redirect.py?Redirect=empty.js"></script>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/resource-timing-iframe.sub.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/resource-timing-iframe.sub.html
new file mode 100644
index 00000000000..c9308ea515e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/resource-timing-iframe.sub.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<script src="empty.js"></script>
+<script src="dummy.js"></script>
+<script src="redirect.py?Redirect=empty.js"></script>
+<img src="missing.jpg">
+<img src="https://{{domains[www1]}}:{{ports[https][0]}}/service-workers/service-worker/resources/missing.jpg">
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/sandboxed-iframe-fetch-event-iframe.html b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/sandboxed-iframe-fetch-event-iframe.html
new file mode 100644
index 00000000000..155dbddb6d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/sandboxed-iframe-fetch-event-iframe.html
@@ -0,0 +1,56 @@
+<script>
+function with_iframe(url) {
+ return new Promise(function(resolve) {
+ var frame = document.createElement('iframe');
+ frame.src = url;
+ frame.onload = function() { resolve(frame); };
+ document.body.appendChild(frame);
+ });
+}
+
+function with_sandboxed_iframe(url, sandbox) {
+ return new Promise(function(resolve) {
+ var frame = document.createElement('iframe');
+ frame.sandbox = sandbox;
+ frame.src = url;
+ frame.onload = function() { resolve(frame); };
+ document.body.appendChild(frame);
+ });
+}
+
+function fetch_in_worker() {
+ return new Promise((resolve) => {
+ var blob = new Blob([
+ "fetch('" + location.href + "_workerfetch', {mode: 'no-cors'})" +
+ " .then(() => { self.postMessage('OK'); });"]);
+ var url = URL.createObjectURL(blob);
+ var worker = new Worker(url);
+ worker.onmessage = resolve;
+ });
+}
+
+window.onmessage = function (e) {
+ var id = e.data['id'];
+ fetch(location.href + "_fetch", {mode: 'no-cors'})
+ .then(function() {
+ return fetch_in_worker();
+ })
+ .then(function() {
+ return with_iframe(location.href + "_iframe");
+ })
+ .then(function() {
+ return with_sandboxed_iframe(location.href + "_script",
+ "allow-scripts");
+ })
+ .then(function() {
+ return with_sandboxed_iframe(location.href + "_script-origin",
+ "allow-scripts allow-same-origin");
+ })
+ .then(function() {
+ window.top.postMessage({id: id, result: 'done'}, '*');
+ })
+ .catch(function(e) {
+ window.top.postMessage({id: id, result: 'error: ' + e.toString()}, '*');
+ });
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/sandboxed-iframe-fetch-event-worker.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/sandboxed-iframe-fetch-event-worker.js
new file mode 100644
index 00000000000..ffa0abac34f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/sandboxed-iframe-fetch-event-worker.js
@@ -0,0 +1,19 @@
+var requests = [];
+
+self.addEventListener('message', function(event) {
+ event.waitUntil(self.clients.matchAll()
+ .then(function(clients) {
+ var client_urls = [];
+ for(var client of clients){
+ client_urls.push(client.url);
+ }
+ client_urls = client_urls.sort();
+ event.data.port.postMessage(
+ {clients: client_urls, requests: requests});
+ }));
+ });
+
+self.addEventListener('fetch', function(event) {
+ requests.push(event.request.url);
+ event.respondWith(fetch(event.request));
+ });
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/test-helpers.sub.js b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/test-helpers.sub.js
index 1df4363ce2a..38ec4ae9674 100644
--- a/tests/wpt/web-platform-tests/service-workers/service-worker/resources/test-helpers.sub.js
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/resources/test-helpers.sub.js
@@ -201,20 +201,12 @@ function test_websocket(test, frame, url) {
});
}
-function login(test) {
- return test_login(test, 'http://{{domains[www1]}}:{{ports[http][0]}}',
- 'username1', 'password1', 'cookie1')
- .then(function() {
- return test_login(test, 'http://{{host}}:{{ports[http][0]}}',
- 'username2', 'password2', 'cookie2');
- });
-}
-
function login_https(test) {
- return test_login(test, 'https://{{domains[www1]}}:{{ports[https][0]}}',
+ var host_info = get_host_info();
+ return test_login(test, host_info.HTTPS_REMOTE_ORIGIN,
'username1s', 'password1s', 'cookie1')
.then(function() {
- return test_login(test, 'https://{{host}}:{{ports[https][0]}}',
+ return test_login(test, host_info.HTTPS_ORIGIN,
'username2s', 'password2s', 'cookie2');
});
}
@@ -255,3 +247,13 @@ function register_using_link(script, options) {
})
.then(() => navigator.serviceWorker.getRegistration(scope));
}
+
+function with_sandboxed_iframe(url, sandbox) {
+ return new Promise(function(resolve) {
+ var frame = document.createElement('iframe');
+ frame.sandbox = sandbox;
+ frame.src = url;
+ frame.onload = function() { resolve(frame); };
+ document.body.appendChild(frame);
+ });
+}
diff --git a/tests/wpt/web-platform-tests/service-workers/service-worker/sandboxed-iframe-fetch-event.https.html b/tests/wpt/web-platform-tests/service-workers/service-worker/sandboxed-iframe-fetch-event.https.html
new file mode 100644
index 00000000000..8b361bd25df
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/service-worker/sandboxed-iframe-fetch-event.https.html
@@ -0,0 +1,216 @@
+<!DOCTYPE html>
+<title>ServiceWorker FetchEvent for sandboxed iframe.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/test-helpers.sub.js"></script>
+<body>
+<script>
+var lastCallbackId = 0;
+var callbacks = {};
+function postMessageAndWaitResult(frame) {
+ return new Promise(function(resolve) {
+ var id = ++lastCallbackId;
+ callbacks[id] = resolve;
+ frame.contentWindow.postMessage({id:id}, '*');
+ });
+}
+
+window.onmessage = function (e) {
+ message = e.data;
+ var id = message['id'];
+ var calback = callbacks[id];
+ delete callbacks[id];
+ calback(message['result']);
+};
+
+promise_test(function(t) {
+ var SCOPE = 'resources/sandboxed-iframe-fetch-event-iframe.html';
+ var SCRIPT = 'resources/sandboxed-iframe-fetch-event-worker.js';
+ var frames = [];
+ var worker;
+ return service_worker_unregister_and_register(t, SCRIPT, SCOPE)
+ .then(function(registration) {
+ worker = registration.installing;
+ return wait_for_state(t, registration.installing, 'activated');
+ })
+ .then(function() {
+ return with_iframe(SCOPE + '?iframe');
+ })
+ .then(function(frame) {
+ frames.push(frame);
+ return postMessageAndWaitResult(frame);
+ })
+ .then(function(result) {
+ assert_equals(result, 'done');
+ return with_sandboxed_iframe(SCOPE + '?script', 'allow-scripts');
+ })
+ .then(function(frame) {
+ frames.push(frame);
+ return postMessageAndWaitResult(frame);
+ })
+ .then(function(result) {
+ assert_equals(result, 'done');
+ return with_sandboxed_iframe(SCOPE + '?script-origin',
+ 'allow-scripts allow-same-origin');
+ })
+ .then(function(frame) {
+ frames.push(frame);
+ return postMessageAndWaitResult(frame);
+ })
+ .then(function(result) {
+ assert_equals(result, 'done');
+ return new Promise(function(resolve) {
+ var channel = new MessageChannel();
+ channel.port1.onmessage = function(msg) {
+ resolve(msg);
+ };
+ worker.postMessage({port: channel.port2}, [channel.port2]);
+ });
+ })
+ .then(function(msg) {
+ for (var frame of frames) {
+ frame.remove();
+ }
+ var expected_base_url = new URL(SCOPE, location.href).href;
+ var request_set = {};
+ for (var request of msg.data.requests) {
+ request_set[request] = true;
+ }
+ assert_true(
+ expected_base_url + '?iframe' in request_set,
+ 'The request for normal iframe should be handled by SW.');
+ assert_true(
+ expected_base_url + '?iframe_fetch' in request_set,
+ 'The fetch request from normal iframe should be handled by SW.');
+ assert_true(
+ expected_base_url + '?iframe_workerfetch' in request_set,
+ 'The fetch request from worker in normal iframe should be ' +
+ 'handled by SW.');
+ assert_true(
+ expected_base_url + '?iframe_iframe' in request_set,
+ 'The request for normal iframe inside normal iframe should be ' +
+ 'handled by SW.');
+ assert_false(
+ expected_base_url + '?iframe_script' in request_set,
+ 'The request for sandboxed iframe with allow-scripts flag ' +
+ 'inside normal iframe should not be handled by SW.');
+ assert_true(
+ expected_base_url + '?iframe_script-origin' in request_set,
+ 'The request for sandboxed iframe with allow-scripts and ' +
+ 'allow-same-origin flag inside normal iframe should be handled ' +
+ 'by SW.');
+ assert_false(
+ expected_base_url + '?script' in request_set,
+ 'The request for sandboxed iframe with allow-scripts flag ' +
+ 'should not be handled by SW.');
+ assert_false(
+ expected_base_url + '?script_fetch' in request_set,
+ 'The fetch request from sandboxed iframe with allow-scripts ' +
+ 'flag should not be handled by SW.');
+ assert_false(
+ expected_base_url + '?script_workerfetch' in request_set,
+ 'The fetch request from worker from sandboxed iframe with ' +
+ 'allow-scripts flag should not be handled by SW.');
+ assert_false(
+ expected_base_url + '?script_iframe' in request_set,
+ 'The request for normal iframe inside sandboxed iframe with ' +
+ 'allow-scripts flag should not be handled by SW.');
+ assert_false(
+ expected_base_url + '?script_script' in request_set,
+ 'The request for sandboxed iframe with allow-scripts flag ' +
+ 'inside sandboxed iframe with allow-scripts flag should not be ' +
+ 'handled by SW.');
+ assert_false(
+ expected_base_url + '?script_script-origin' in request_set,
+ 'The request for sandboxed iframe with allow-scripts and ' +
+ 'allow-same-origin flag inside sandboxed iframe with ' +
+ 'allow-scripts flag should not be handled by SW.');
+ assert_true(
+ expected_base_url + '?script-origin' in request_set,
+ 'The request for sandboxed iframe with allow-scripts and ' +
+ 'allow-same-origin flag should be handled by SW.');
+ assert_true(
+ expected_base_url + '?script-origin_fetch' in request_set,
+ 'The fetch request from sandboxed iframe with allow-scripts ' +
+ 'and allow-same-origin flag should be handled by SW.');
+ assert_true(
+ expected_base_url + '?script-origin_workerfetch' in request_set,
+ 'The fetch request from worker in sandboxed iframe with ' +
+ 'allow-scripts and allow-same-origin flag should be handled ' +
+ 'by SW.');
+ assert_true(
+ expected_base_url + '?script-origin_iframe' in request_set,
+ 'The request for normal iframe inside sandboxed iframe with ' +
+ 'allow-scripts and allow-same-origin flag should be handled by' +
+ 'SW.');
+ assert_false(
+ expected_base_url + '?script-origin_script' in request_set,
+ 'The request for sandboxed iframe with allow-scripts flag ' +
+ 'inside sandboxed iframe with allow-scripts and ' +
+ 'allow-same-origin flag should be handled by SW.');
+ assert_true(
+ expected_base_url + '?script-origin_script-origin' in request_set,
+ 'The request for sandboxed iframe with allow-scripts and' +
+ 'allow-same-origin flag inside sandboxed iframe with ' +
+ 'allow-scripts and allow-same-origin flag should be handled by' +
+ 'SW.');
+
+ var client_set = {};
+ for (var client of msg.data.clients) {
+ client_set[client] = true;
+ }
+ assert_true(
+ expected_base_url + '?iframe' in client_set,
+ 'The normal iframe should be controlled by SW.');
+ assert_true(
+ expected_base_url + '?iframe_iframe' in client_set,
+ 'The normal iframe inside normal iframe should be controlled ' +
+ 'by SW.');
+ assert_false(
+ expected_base_url + '?iframe_script' in client_set,
+ 'The sandboxed iframe with allow-scripts flag inside normal ' +
+ 'iframe should not be controlled by SW.');
+ assert_true(
+ expected_base_url + '?iframe_script-origin' in client_set,
+ 'The sandboxed iframe with allow-scripts and allow-same-origin' +
+ 'flag inside normal iframe should be controlled by SW.');
+ assert_false(
+ expected_base_url + '?script' in client_set,
+ 'The sandboxed iframe with allow-scripts flag should not be ' +
+ 'controlled by SW.');
+ assert_false(
+ expected_base_url + '?script_iframe' in client_set,
+ 'The normal iframe inside sandboxed iframe with allow-scripts' +
+ 'flag should not be controlled by SW.');
+ assert_false(
+ expected_base_url + '?script_script' in client_set,
+ 'The sandboxed iframe with allow-scripts flag inside sandboxed ' +
+ 'iframe with allow-scripts flag should not be controlled by SW.');
+ assert_false(
+ expected_base_url + '?script_script-origin' in client_set,
+ 'The sandboxed iframe with allow-scripts and allow-same-origin ' +
+ 'flag inside sandboxed iframe with allow-scripts flag should ' +
+ 'not be controlled by SW.');
+ assert_true(
+ expected_base_url + '?script-origin' in client_set,
+ 'The sandboxed iframe with allow-scripts and allow-same-origin ' +
+ 'flag should be controlled by SW.');
+ assert_true(
+ expected_base_url + '?script-origin_iframe' in client_set,
+ 'The normal iframe inside sandboxed iframe with allow-scripts ' +
+ 'and allow-same-origin flag should be controlled by SW.');
+ assert_false(
+ expected_base_url + '?script-origin_script' in client_set,
+ 'The sandboxed iframe with allow-scripts flag inside sandboxed ' +
+ 'iframe with allow-scripts and allow-same-origin flag should ' +
+ 'be controlled by SW.');
+ assert_true(
+ expected_base_url + '?script-origin_script-origin' in client_set,
+ 'The sandboxed iframe with allow-scripts and allow-same-origin ' +
+ 'flag inside sandboxed iframe with allow-scripts and ' +
+ 'allow-same-origin flag should be controlled by SW.');
+ return service_worker_unregister_and_done(t, SCOPE);
+ });
+ }, 'ServiceWorker FetchEvent for sandboxed iframe.');
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/event-composed-path-after-dom-mutation.html b/tests/wpt/web-platform-tests/shadow-dom/event-composed-path-after-dom-mutation.html
new file mode 100644
index 00000000000..fd129e036af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/event-composed-path-after-dom-mutation.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<title>Shadow DOM: Event.composedPath() should return the same result even if DOM is mutated</title>
+<meta name="author" title="Hayato Ito" href="mailto:hayato@google.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/shadow-dom.js"></script>
+
+<div id="test1">
+ <div id="host">
+ <template id="sr" data-mode="closed">
+ <div id="target"></div>
+ </template>
+ </div>
+</div>
+
+<script>
+async_test((t) => {
+ const n = createTestTree(document.querySelector('#test1'));
+ n.host.addEventListener('my-event', t.step_func((e) => {
+ const path_before = e.composedPath();
+ // Move the target out of a closed shadow tree
+ n.host.append(n.target);
+ const path_after = e.composedPath();
+ assert_array_equals(path_before, path_after);
+ t.done();
+ }));
+ const event = new Event('my-event', { bubbles: true, composed: true });
+ n.target.dispatchEvent(event);
+}, 'Event.composedPath() should return the same result even if DOM is mutated (1/2)');
+</script>
+
+<div id="test2">
+ <div id="host1">
+ <template id="sr1" data-mode="closed">
+ <div id="host2">
+ <template id="sr2" data-mode="open">
+ <div id="target"></div>
+ </template>
+ </div>
+ </template>
+ </div>
+</div>
+
+<script>
+async_test((t) => {
+ const n = createTestTree(document.querySelector('#test2'));
+ n.host1.addEventListener('my-event', t.step_func((e) => {
+ const path_before = e.composedPath();
+ // Move nodes out of a closed shadow tree
+ n.host1.append(n.host2);
+ n.host1.append(n.target);
+ const path_after = e.composedPath();
+ assert_array_equals(path_before, path_after);
+ t.done();
+ }));
+ const event = new Event('my-event', { bubbles: true, composed: true });
+ n.target.dispatchEvent(event);
+}, 'Event.composedPath() should return the same result even if DOM is mutated (2/2)');
+</script>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/event-inside-shadow-tree.html b/tests/wpt/web-platform-tests/shadow-dom/event-inside-shadow-tree.html
index cacd966b3b9..a7405a59560 100644
--- a/tests/wpt/web-platform-tests/shadow-dom/event-inside-shadow-tree.html
+++ b/tests/wpt/web-platform-tests/shadow-dom/event-inside-shadow-tree.html
@@ -44,7 +44,7 @@ function testEventInDetachedShadowTree(mode) {
log = dispatchEventWithLog(shadow.target, new Event('foo', {composed: true, bubbles: true}));
- assert_array_equals(log.length, 4, 'EventPath must contain [target, parent, shadow root, shadow host]');
+ assert_equals(log.length, 4, 'EventPath must contain [target, parent, shadow root, shadow host]');
assert_array_equals(log[0], [shadow.target, shadow.target], 'EventPath[0] must be the target');
assert_array_equals(log[1], [shadow.parent, shadow.target], 'EventPath[1] must be the parent of the target');
assert_array_equals(log[2], [shadow.root, shadow.target], 'EventPath[2] must be the shadow root');
@@ -63,7 +63,7 @@ function testEventInShadowTreeInsideDocument(mode) {
log = dispatchEventWithLog(shadow.target, new Event('foo', {composed: true, bubbles: true}));
- assert_array_equals(log.length, 7, 'EventPath must contain [target, parent, shadow root, shadow host, body, html, document]');
+ assert_equals(log.length, 7, 'EventPath must contain [target, parent, shadow root, shadow host, body, html, document]');
assert_array_equals(log[0], [shadow.target, shadow.target], 'EventPath[0] must be the target');
assert_array_equals(log[1], [shadow.parent, shadow.target], 'EventPath[1] must be the parent of the target');
assert_array_equals(log[2], [shadow.root, shadow.target], 'EventPath[2] must be the shadow root');
@@ -101,7 +101,7 @@ function testEventInDetachedNestedShadowTree(innerMode, outerMode) {
log = dispatchEventWithLog(shadow.target, new Event('bar', {composed: true, bubbles: true}));
- assert_array_equals(log.length, 6, 'EventPath must contain [target, inner root, inner host, parent, outer root, outer host]');
+ assert_equals(log.length, 6, 'EventPath must contain [target, inner root, inner host, parent, outer root, outer host]');
assert_array_equals(log[0], [shadow.target, shadow.target], 'EventPath[0] must be the target');
assert_array_equals(log[1], [shadow.innerRoot, shadow.target], 'EventPath[1] must be the inner shadow root');
assert_array_equals(log[2], [shadow.innerHost, shadow.innerHost], 'EventPath[2] must be the inner shadow host');
@@ -124,7 +124,7 @@ function testEventInNestedShadowTreeInsideDocument(innerMode, outerMode) {
log = dispatchEventWithLog(shadow.target, new Event('bar', {composed: true, bubbles: true}));
- assert_array_equals(log.length, 6, 'EventPath must contain [target, inner root, inner host, parent, outer root, outer host]');
+ assert_equals(log.length, 9, 'EventPath must contain [target, inner root, inner host, parent, outer root, outer host]');
assert_array_equals(log[0], [shadow.target, shadow.target], 'EventPath[0] must be the target');
assert_array_equals(log[1], [shadow.innerRoot, shadow.target], 'EventPath[1] must be the inner shadow root');
assert_array_equals(log[2], [shadow.innerHost, shadow.innerHost], 'EventPath[2] must be the inner shadow host');
diff --git a/tests/wpt/web-platform-tests/shadow-dom/slots-fallback.html b/tests/wpt/web-platform-tests/shadow-dom/slots-fallback.html
index a8d60e88182..e705e18f4a9 100644
--- a/tests/wpt/web-platform-tests/shadow-dom/slots-fallback.html
+++ b/tests/wpt/web-platform-tests/shadow-dom/slots-fallback.html
@@ -25,6 +25,13 @@ test(() => {
assert_array_equals(n.s1.assignedNodes(), []);
assert_array_equals(n.s1.assignedNodes({ flatten: true }), [n.f1]);
}, 'Slots fallback: Basic.');
+
+test(() => {
+ let n = createTestTree(test1);
+
+ assert_array_equals(n.s1.assignedElements(), []);
+ assert_array_equals(n.s1.assignedElements({ flatten: true }), [n.f1]);
+}, 'Slots fallback: Basic, elements only.');
</script>
<div id="test2">
@@ -52,6 +59,16 @@ test(() => {
assert_array_equals(n.s1.assignedNodes({ flatten: true }), [n.f1]);
assert_array_equals(n.s2.assignedNodes({ flatten: true }), [n.f1]);
}, 'Slots fallback: Slots in Slots.');
+
+test(() => {
+ let n = createTestTree(test2);
+
+ assert_array_equals(n.s1.assignedElements(), []);
+ assert_array_equals(n.s2.assignedElements(), []);
+
+ assert_array_equals(n.s1.assignedElements({ flatten: true }), [n.f1]);
+ assert_array_equals(n.s2.assignedElements({ flatten: true }), [n.f1]);
+}, 'Slots fallback: Slots in Slots, elements only.');
</script>
<div id="test3">
@@ -109,7 +126,7 @@ test(() => {
assert_array_equals(n.s1.assignedNodes({ flatten: true }), [n.c1]);
assert_array_equals(n.s2.assignedNodes({ flatten: true }), [n.c1]);
-}, 'Slots fallback: Slots in Slots: Assinged nodes should be used as fallback contents of another slot');
+}, 'Slots fallback: Slots in Slots: Assigned nodes should be used as fallback contents of another slot');
</script>
<div id="test5">
@@ -154,6 +171,20 @@ test(() => {
test(() => {
let n = createTestTree(test5);
+
+ assert_array_equals(n.s1.assignedElements(), [n.c1]);
+ assert_array_equals(n.s2.assignedElements(), []);
+ assert_array_equals(n.s3.assignedElements(), [n.s2]);
+ assert_array_equals(n.s4.assignedElements(), []);
+
+ assert_array_equals(n.s1.assignedElements({ flatten: true }), [n.c1]);
+ assert_array_equals(n.s2.assignedElements({ flatten: true }), [n.c1, n.f2]);
+ assert_array_equals(n.s3.assignedElements({ flatten: true }), [n.c1, n.f2]);
+ assert_array_equals(n.s4.assignedElements({ flatten: true }), [n.c1, n.f2, n.f4]);
+}, 'Slots fallback: Complex case, elements only.');
+
+test(() => {
+ let n = createTestTree(test5);
removeWhiteSpaceOnlyTextNodes(n.test5);
let d1 = document.createElement('div');
diff --git a/tests/wpt/web-platform-tests/shadow-dom/slots.html b/tests/wpt/web-platform-tests/shadow-dom/slots.html
index 550d7d454aa..948d389298f 100644
--- a/tests/wpt/web-platform-tests/shadow-dom/slots.html
+++ b/tests/wpt/web-platform-tests/shadow-dom/slots.html
@@ -22,6 +22,12 @@ test(() => {
assert_equals(n.c1.assignedSlot, n.s1);
assert_array_equals(n.s1.assignedNodes(), [n.c1]);
}, 'Slots: Basic.');
+
+test(() => {
+ let n = createTestTree(test_basic);
+
+ assert_array_equals(n.s1.assignedElements(), [n.c1]);
+}, 'Slots: Basic, elements only.');
</script>
<div id="test_basic_closed">
@@ -41,6 +47,12 @@ test(() => {
assert_equals(n.c1.assignedSlot, null);
assert_array_equals(n.s1.assignedNodes(), [n.c1]);
}, 'Slots: Slots in closed.');
+
+test(() => {
+ let n = createTestTree(test_basic_closed);
+
+ assert_array_equals(n.s1.assignedElements(), [n.c1]);
+}, 'Slots: Slots in closed, elements only.');
</script>
<div id="test_slot_not_in_shadow">
@@ -54,6 +66,12 @@ test(() => {
assert_array_equals(n.s1.assignedNodes(), []);
}, 'Slots: Slots not in a shadow tree.');
+
+test(() => {
+ let n = createTestTree(test_slot_not_in_shadow);
+
+ assert_array_equals(n.s1.assignedElements(), []);
+}, 'Slots: Slots not in a shadow tree, elements only.');
</script>
<div id="test_slot_not_in_shadow_2">
@@ -86,7 +104,7 @@ test(() => {
assert_array_equals(n.s1.assignedNodes({ flatten: true }), []);
assert_array_equals(n.s2.assignedNodes({ flatten: true }), []);
assert_array_equals(n.s3.assignedNodes({ flatten: true }), []);
-}, 'Slots: Distributed nooes for Slots not in a shadow tree.');
+}, 'Slots: Distributed nodes for Slots not in a shadow tree.');
</script>
<div id="test_slot_name_matching">
diff --git a/tests/wpt/web-platform-tests/storage/estimate-parallel.https.html b/tests/wpt/web-platform-tests/storage/estimate-parallel.https.html
new file mode 100644
index 00000000000..571b08cd5e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/storage/estimate-parallel.https.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>StorageManager: multiple estimate() calls in parallel</title>
+<meta name="help" href="https://storage.spec.whatwg.org/#dom-storagemanager-estimate">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+promise_test(async t => {
+ let r1, r2;
+ await Promise.all([
+ navigator.storage.estimate().then(r => { r1 = r; }),
+ navigator.storage.estimate().then(r => { r2 = r; })
+ ]);
+ assert_true(('usage' in r1) && ('quota' in r1),
+ 'first response should have expected fields');
+ assert_true(('usage' in r2) && ('quota' in r2),
+ 'second response should have expected fields');
+}, 'Multiple estimate() calls in parallel should complete');
+</script>
diff --git a/tests/wpt/web-platform-tests/storage/interfaces.idl b/tests/wpt/web-platform-tests/storage/interfaces.idl
index 4967404225e..c45690352f9 100644
--- a/tests/wpt/web-platform-tests/storage/interfaces.idl
+++ b/tests/wpt/web-platform-tests/storage/interfaces.idl
@@ -1,11 +1,9 @@
-[SecureContext,
- NoInterfaceObject,
- Exposed=(Window,Worker)]
-interface NavigatorStorage {
+[SecureContext]
+interface mixin NavigatorStorage {
readonly attribute StorageManager storage;
};
-Navigator implements NavigatorStorage;
-WorkerNavigator implements NavigatorStorage;
+Navigator includes NavigatorStorage;
+WorkerNavigator includes NavigatorStorage;
[SecureContext,
Exposed=(Window,Worker)]
diff --git a/tests/wpt/web-platform-tests/streams/readable-byte-streams/general.js b/tests/wpt/web-platform-tests/streams/readable-byte-streams/general.js
index 1ec9fbca298..edbe1c83f15 100644
--- a/tests/wpt/web-platform-tests/streams/readable-byte-streams/general.js
+++ b/tests/wpt/web-platform-tests/streams/readable-byte-streams/general.js
@@ -520,27 +520,12 @@ promise_test(() => {
return promise;
}, 'ReadableStream with byte source: Push source that doesn\'t understand pull signal');
-promise_test(t => {
- const stream = new ReadableStream({
- pull: 'foo',
- type: 'bytes'
- });
-
- const reader = stream.getReader();
-
- return promise_rejects(t, new TypeError(), reader.read(), 'read() must fail');
-}, 'ReadableStream with byte source: read(), but pull() function is not callable');
-
-promise_test(t => {
- const stream = new ReadableStream({
+test(() => {
+ assert_throws(new TypeError(), () => new ReadableStream({
pull: 'foo',
type: 'bytes'
- });
-
- const reader = stream.getReader({ mode: 'byob' });
-
- return promise_rejects(t, new TypeError(), reader.read(new Uint8Array(1)), 'read() must fail');
-}, 'ReadableStream with byte source: read(view), but pull() function is not callable');
+ }), 'constructor should throw');
+}, 'ReadableStream with byte source: pull() function is not callable');
promise_test(() => {
const stream = new ReadableStream({
@@ -1943,4 +1928,30 @@ test(() => {
assert_throws(new TypeError(), () => new ReadableStreamBYOBReader(stream), 'constructor must throw');
}, 'ReadableStreamBYOBReader constructor requires a ReadableStream with type "bytes"');
+test(() => {
+ assert_throws(new RangeError(), () => new ReadableStream({ type: 'bytes' }, {
+ size() {
+ return 1;
+ }
+ }), 'constructor should throw for size function');
+
+ assert_throws(new RangeError(), () => new ReadableStream({ type: 'bytes' }, { size: null }),
+ 'constructor should throw for size defined');
+
+ assert_throws(new RangeError(),
+ () => new ReadableStream({ type: 'bytes' }, new CountQueuingStrategy({ highWaterMark: 1 })),
+ 'constructor should throw when strategy is CountQueuingStrategy');
+
+ assert_throws(new RangeError(),
+ () => new ReadableStream({ type: 'bytes' }, new ByteLengthQueuingStrategy({ highWaterMark: 512 })),
+ 'constructor should throw when strategy is ByteLengthQueuingStrategy');
+
+ class HasSizeMethod {
+ size() {}
+ }
+
+ assert_throws(new RangeError(), () => new ReadableStream({ type: 'bytes' }, new HasSizeMethod()),
+ 'constructor should throw when size on the prototype chain');
+}, 'ReadableStream constructor should not accept a strategy with a size defined if type is "bytes"');
+
done();
diff --git a/tests/wpt/web-platform-tests/streams/readable-byte-streams/properties.js b/tests/wpt/web-platform-tests/streams/readable-byte-streams/properties.js
index 21549bc667b..02d029431ae 100644
--- a/tests/wpt/web-platform-tests/streams/readable-byte-streams/properties.js
+++ b/tests/wpt/web-platform-tests/streams/readable-byte-streams/properties.js
@@ -138,7 +138,7 @@ test(() => {
}
assert_equals(controller.close.length, 0, 'cancel has no parameters');
- assert_equals(controller.constructor.length, 3, 'constructor has 3 parameters');
+ assert_equals(controller.constructor.length, 0, 'constructor has no parameters');
assert_equals(controller.enqueue.length, 1, 'enqueue has 1 parameter');
assert_equals(controller.error.length, 1, 'releaseLock has 1 parameter');
diff --git a/tests/wpt/web-platform-tests/streams/readable-streams/bad-underlying-sources.js b/tests/wpt/web-platform-tests/streams/readable-streams/bad-underlying-sources.js
index 2f2dec4d41f..9fd958de7c4 100644
--- a/tests/wpt/web-platform-tests/streams/readable-streams/bad-underlying-sources.js
+++ b/tests/wpt/web-platform-tests/streams/readable-streams/bad-underlying-sources.js
@@ -35,16 +35,14 @@ test(() => {
}, 'Underlying source start: throwing method');
-promise_test(t => {
+test(() => {
const theError = new Error('a unique string');
- const rs = new ReadableStream({
+ assert_throws(theError, () => new ReadableStream({
get pull() {
throw theError;
}
- });
-
- return promise_rejects(t, theError, rs.getReader().closed);
+ }), 'constructor should throw');
}, 'Underlying source: throwing pull getter (initial pull)');
@@ -82,13 +80,15 @@ promise_test(t => {
return Promise.all([
reader.read().then(r => {
- assert_object_equals(r, { value: 'a', done: false }, 'the chunk read should be correct');
+ assert_object_equals(r, { value: 'a', done: false }, 'the first chunk read should be correct');
}),
- promise_rejects(t, theError, reader.closed)
+ reader.read().then(r => {
+ assert_object_equals(r, { value: 'a', done: false }, 'the second chunk read should be correct');
+ assert_equals(counter, 1, 'counter should be 1');
+ })
]);
-}, 'Underlying source pull: throwing getter (second pull)');
-
+}, 'Underlying source pull: throwing getter (second pull does not result in a second get)');
promise_test(t => {
@@ -117,16 +117,14 @@ promise_test(t => {
}, 'Underlying source pull: throwing method (second pull)');
-promise_test(t => {
+test(() => {
const theError = new Error('a unique string');
- const rs = new ReadableStream({
+ assert_throws(theError, () => new ReadableStream({
get cancel() {
throw theError;
}
- });
-
- return promise_rejects(t, theError, rs.cancel());
+ }), 'constructor should throw');
}, 'Underlying source cancel: throwing getter');
diff --git a/tests/wpt/web-platform-tests/streams/readable-streams/general.js b/tests/wpt/web-platform-tests/streams/readable-streams/general.js
index 5150c365d47..05382d47f7e 100644
--- a/tests/wpt/web-platform-tests/streams/readable-streams/general.js
+++ b/tests/wpt/web-platform-tests/streams/readable-streams/general.js
@@ -86,15 +86,15 @@ test(() => {
test(() => {
- new ReadableStream({ cancel: '2' });
+ assert_throws(new TypeError(), () => new ReadableStream({ cancel: '2' }), 'constructor should throw');
-}, 'ReadableStream constructor can get initial garbage as cancel argument');
+}, 'ReadableStream constructor will not tolerate initial garbage as cancel argument');
test(() => {
- new ReadableStream({ pull: { } });
+ assert_throws(new TypeError(), () => new ReadableStream({ pull: { } }), 'constructor should throw');
-}, 'ReadableStream constructor can get initial garbage as pull argument');
+}, 'ReadableStream constructor will not tolerate initial garbage as pull argument');
test(() => {
@@ -129,7 +129,7 @@ test(() => {
assert_true(desiredSizePropDesc.configurable, 'desiredSize should be configurable');
assert_equals(controller.close.length, 0, 'close should have no parameters');
- assert_equals(controller.constructor.length, 4, 'constructor should have 4 parameter');
+ assert_equals(controller.constructor.length, 0, 'constructor should have no parameters');
assert_equals(controller.enqueue.length, 1, 'enqueue should have 1 parameter');
assert_equals(controller.error.length, 1, 'error should have 1 parameter');
diff --git a/tests/wpt/web-platform-tests/streams/readable-streams/tee.js b/tests/wpt/web-platform-tests/streams/readable-streams/tee.js
index d5d357fb91a..df76877eff4 100644
--- a/tests/wpt/web-platform-tests/streams/readable-streams/tee.js
+++ b/tests/wpt/web-platform-tests/streams/readable-streams/tee.js
@@ -207,6 +207,20 @@ promise_test(t => {
}, 'ReadableStream teeing: failing to cancel the original stream should cause cancel() to reject on branches');
+test(t => {
+
+ let controller;
+ const stream = new ReadableStream({ start(c) { controller = c; } });
+ const [branch1, branch2] = stream.tee();
+
+ const promise = controller.error("error");
+
+ branch1.cancel().catch(_=>_);
+ branch2.cancel().catch(_=>_);
+
+ return promise;
+}, 'ReadableStream teeing: erroring a teed stream should properly handle canceled branches');
+
promise_test(() => {
let controller;
diff --git a/tests/wpt/web-platform-tests/streams/transform-streams/properties.dedicatedworker.html b/tests/wpt/web-platform-tests/streams/transform-streams/properties.dedicatedworker.html
new file mode 100644
index 00000000000..50d63ed0edb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/streams/transform-streams/properties.dedicatedworker.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>properties.js dedicated worker wrapper file</title>
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<script>
+'use strict';
+fetch_tests_from_worker(new Worker('properties.js'));
+</script>
diff --git a/tests/wpt/web-platform-tests/streams/transform-streams/properties.html b/tests/wpt/web-platform-tests/streams/transform-streams/properties.html
new file mode 100644
index 00000000000..ad410a53c82
--- /dev/null
+++ b/tests/wpt/web-platform-tests/streams/transform-streams/properties.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>properties.js browser context wrapper file</title>
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+
+
+<script src="properties.js"></script>
diff --git a/tests/wpt/web-platform-tests/streams/transform-streams/properties.js b/tests/wpt/web-platform-tests/streams/transform-streams/properties.js
new file mode 100644
index 00000000000..7aefa9f0c3b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/streams/transform-streams/properties.js
@@ -0,0 +1,194 @@
+'use strict';
+
+if (self.importScripts) {
+ self.importScripts('/resources/testharness.js');
+}
+
+// The purpose of this file is to test for objects, attributes and arguments that should not exist.
+// The test cases are generated from data tables to reduce duplication.
+
+// Courtesy of André Bargull. Source is https://esdiscuss.org/topic/isconstructor#content-11.
+function IsConstructor(o) {
+ try {
+ new new Proxy(o, { construct: () => ({}) })();
+ return true;
+ } catch (e) {
+ return false;
+ }
+}
+
+test(() => {
+ assert_equals(self['TransformStreamDefaultController'], undefined,
+ `TransformStreamDefaultController should not be defined`);
+}, `TransformStreamDefaultController should not be exported on the global object`);
+
+// Now get hold of the symbol so we can test its properties.
+self.TransformStreamDefaultController = (() => {
+ let controller;
+ new TransformStream({
+ start(c) {
+ controller = c;
+ }
+ });
+ return controller.constructor;
+})();
+
+const expected = {
+ TransformStream: {
+ constructor: {
+ type: 'constructor',
+ length: 0
+ },
+ readable: {
+ type: 'getter'
+ },
+ writable: {
+ type: 'getter'
+ }
+ },
+ TransformStreamDefaultController: {
+ constructor: {
+ type: 'constructor',
+ length: 0
+ },
+ desiredSize: {
+ type: 'getter'
+ },
+ enqueue: {
+ type: 'method',
+ length: 1
+ },
+ error: {
+ type: 'method',
+ length: 1
+ },
+ terminate: {
+ type: 'method',
+ length: 0
+ }
+ }
+};
+
+for (const c in expected) {
+ const properties = expected[c];
+ const prototype = self[c].prototype;
+ for (const name in properties) {
+ const fullName = `${c}.prototype.${name}`;
+ const descriptor = Object.getOwnPropertyDescriptor(prototype, name);
+ test(() => {
+ const { configurable, enumerable } = descriptor;
+ assert_true(configurable, `${name} should be configurable`);
+ assert_false(enumerable, `${name} should not be enumerable`);
+ }, `${fullName} should have standard properties`);
+ const type = properties[name].type;
+ switch (type) {
+ case 'getter':
+ test(() => {
+ const { writable, get, set } = descriptor;
+ assert_equals(writable, undefined, `${name} should not be a data descriptor`);
+ assert_equals(typeof get, 'function', `${name} should have a getter`);
+ assert_equals(set, undefined, `${name} should not have a setter`);
+ }, `${fullName} should be a getter`);
+ break;
+
+ case 'constructor':
+ case 'method':
+ test(() => {
+ assert_true(descriptor.writable, `${name} should be writable`);
+ assert_equals(typeof prototype[name], 'function', `${name} should be a function`);
+ assert_equals(prototype[name].length, properties[name].length,
+ `${name} should take ${properties[name].length} arguments`);
+ if (type === 'constructor') {
+ assert_true(IsConstructor(prototype[name]), `${name} should be a constructor`);
+ assert_equals(prototype[name].name, c, `${name}.name should be '${c}'`);
+ } else {
+ assert_false(IsConstructor(prototype[name]), `${name} should not be a constructor`);
+ assert_equals(prototype[name].name, name, `${name}.name should be '${name}`);
+ }
+ }, `${fullName} should be a ${type}`);
+ break;
+ }
+ }
+ test(() => {
+ const expectedPropertyNames = Object.keys(properties).sort();
+ const actualPropertyNames = Object.getOwnPropertyNames(prototype).sort();
+ assert_array_equals(actualPropertyNames, expectedPropertyNames,
+ `${c} properties should match expected properties`);
+ }, `${c}.prototype should have exactly the expected properties`);
+}
+
+const transformerMethods = {
+ start: {
+ length: 1,
+ trigger: () => Promise.resolve()
+ },
+ transform: {
+ length: 2,
+ trigger: ts => ts.writable.getWriter().write()
+ },
+ flush: {
+ length: 1,
+ trigger: ts => ts.writable.getWriter().close()
+ }
+};
+
+for (const method in transformerMethods) {
+ const { length, trigger } = transformerMethods[method];
+
+ // Some semantic tests of how transformer methods are called can be found in general.js, as well as in the test files
+ // specific to each method.
+ promise_test(() => {
+ let argCount;
+ const ts = new TransformStream({
+ [method](...args) {
+ argCount = args.length;
+ }
+ }, undefined, { highWaterMark: Infinity });
+ return Promise.resolve(trigger(ts)).then(() => {
+ assert_equals(argCount, length, `${method} should be called with ${length} arguments`);
+ });
+ }, `transformer method ${method} should be called with the right number of arguments`);
+
+ promise_test(() => {
+ let methodWasCalled = false;
+ function Transformer() {}
+ Transformer.prototype = {
+ [method]() {
+ methodWasCalled = true;
+ }
+ };
+ const ts = new TransformStream(new Transformer(), undefined, { highWaterMark: Infinity });
+ return Promise.resolve(trigger(ts)).then(() => {
+ assert_true(methodWasCalled, `${method} should be called`);
+ });
+ }, `transformer method ${method} should be called even when it's located on the prototype chain`);
+
+ promise_test(t => {
+ const unreachedTraps = ['getPrototypeOf', 'setPrototypeOf', 'isExtensible', 'preventExtensions',
+ 'getOwnPropertyDescriptor', 'defineProperty', 'has', 'set', 'deleteProperty', 'ownKeys',
+ 'apply', 'construct'];
+ const touchedProperties = [];
+ const handler = {
+ get: t.step_func((target, property) => {
+ touchedProperties.push(property);
+ if (property === 'readableType' || property === 'writableType') {
+ return undefined;
+ }
+ return () => Promise.resolve();
+ })
+ };
+ for (const trap of unreachedTraps) {
+ handler[trap] = t.unreached_func(`${trap} should not be trapped`);
+ }
+ const transformer = new Proxy({}, handler);
+ const ts = new TransformStream(transformer, undefined, { highWaterMark: Infinity });
+ assert_array_equals(touchedProperties, ['readableType', 'writableType', 'transform', 'flush', 'start'],
+ 'expected properties should be got');
+ return trigger(ts).then(() => {
+ assert_array_equals(touchedProperties, ['readableType', 'writableType', 'transform', 'flush', 'start'],
+ 'no properties should be accessed on method call');
+ });
+ }, `unexpected properties should not be accessed when calling transformer method ${method}`);
+}
+
+done();
diff --git a/tests/wpt/web-platform-tests/streams/transform-streams/properties.serviceworker.https.html b/tests/wpt/web-platform-tests/streams/transform-streams/properties.serviceworker.https.html
new file mode 100644
index 00000000000..ba5c5135f2f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/streams/transform-streams/properties.serviceworker.https.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>properties.js service worker wrapper file</title>
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
+
+<script>
+'use strict';
+service_worker_test('properties.js', 'Service worker test setup');
+</script>
diff --git a/tests/wpt/web-platform-tests/streams/transform-streams/properties.sharedworker.html b/tests/wpt/web-platform-tests/streams/transform-streams/properties.sharedworker.html
new file mode 100644
index 00000000000..42fb3e5ebc0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/streams/transform-streams/properties.sharedworker.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>properties.js shared worker wrapper file</title>
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<script>
+'use strict';
+fetch_tests_from_worker(new SharedWorker('properties.js'));
+</script>
diff --git a/tests/wpt/web-platform-tests/streams/transform-streams/strategies.js b/tests/wpt/web-platform-tests/streams/transform-streams/strategies.js
index 60481a9c623..1775b7fa170 100644
--- a/tests/wpt/web-platform-tests/streams/transform-streams/strategies.js
+++ b/tests/wpt/web-platform-tests/streams/transform-streams/strategies.js
@@ -67,7 +67,6 @@ test(() => {
const ts = new TransformStream();
const writer = ts.writable.getWriter();
assert_equals(writer.desiredSize, 1, 'default writable HWM is 1');
- // There should be no size function, but a size function that always returns 1 is indistinguishable.
writer.write(undefined);
assert_equals(writer.desiredSize, 0, 'default chunk size is 1');
}, 'default writable strategy should be equivalent to { highWaterMark: 1 }');
@@ -89,4 +88,68 @@ promise_test(t => {
return ts.readable.getReader().read().then(() => writePromise);
}, 'default readable strategy should be equivalent to { highWaterMark: 0 }');
+test(() => {
+ assert_throws(new RangeError(), () => new TransformStream(undefined, { highWaterMark: -1 }),
+ 'should throw RangeError for negative writableHighWaterMark');
+ assert_throws(new RangeError(), () => new TransformStream(undefined, undefined, { highWaterMark: -1 }),
+ 'should throw RangeError for negative readableHighWaterMark');
+ assert_throws(new RangeError(), () => new TransformStream(undefined, { highWaterMark: NaN }),
+ 'should throw RangeError for NaN writableHighWaterMark');
+ assert_throws(new RangeError(), () => new TransformStream(undefined, undefined, { highWaterMark: NaN }),
+ 'should throw RangeError for NaN readableHighWaterMark');
+}, 'a RangeError should be thrown for an invalid highWaterMark');
+
+const objectThatConvertsTo42 = {
+ toString() {
+ return '42';
+ }
+};
+
+test(() => {
+ const ts = new TransformStream(undefined, { highWaterMark: objectThatConvertsTo42 });
+ const writer = ts.writable.getWriter();
+ assert_equals(writer.desiredSize, 42, 'writable HWM is 42');
+}, 'writableStrategy highWaterMark should be converted to a number');
+
+test(() => {
+ const ts = new TransformStream({
+ start(controller) {
+ assert_equals(controller.desiredSize, 42, 'desiredSize should be 42');
+ }
+ }, undefined, { highWaterMark: objectThatConvertsTo42 });
+}, 'readableStrategy highWaterMark should be converted to a number');
+
+promise_test(t => {
+ const ts = new TransformStream(undefined, undefined, {
+ size() { return NaN; },
+ highWaterMark: 1
+ });
+ const writer = ts.writable.getWriter();
+ return promise_rejects(t, new RangeError(), writer.write(), 'write should reject');
+}, 'a bad readableStrategy size function should cause writer.write() to reject on an identity transform');
+
+promise_test(t => {
+ const ts = new TransformStream({
+ transform(chunk, controller) {
+ // This assert has the important side-effect of catching the error, so transform() does not throw.
+ assert_throws(new RangeError(), () => controller.enqueue(chunk), 'enqueue should throw');
+ }
+ }, undefined, {
+ size() {
+ return -1;
+ },
+ highWaterMark: 1
+ });
+
+ const writer = ts.writable.getWriter();
+ return writer.write().then(() => {
+ return Promise.all([
+ promise_rejects(t, new RangeError(), writer.ready, 'ready should reject'),
+ promise_rejects(t, new RangeError(), writer.closed, 'closed should reject'),
+ promise_rejects(t, new RangeError(), ts.readable.getReader().closed, 'readable closed should reject')
+ ]);
+ });
+}, 'a bad readableStrategy size function should error the stream on enqueue even when transformer.transform() ' +
+ 'catches the exception');
+
done();
diff --git a/tests/wpt/web-platform-tests/streams/writable-streams/bad-strategies.js b/tests/wpt/web-platform-tests/streams/writable-streams/bad-strategies.js
index eb14cf22e12..1dba393811b 100644
--- a/tests/wpt/web-platform-tests/streams/writable-streams/bad-strategies.js
+++ b/tests/wpt/web-platform-tests/streams/writable-streams/bad-strategies.js
@@ -90,4 +90,11 @@ promise_test(() => {
}));
}, 'Writable stream: invalid strategy.size return value');
+test(() => {
+ assert_throws(new TypeError(), () => new WritableStream(undefined, {
+ size: 'not a function',
+ highWaterMark: NaN
+ }), 'WritableStream constructor should throw a TypeError');
+}, 'Writable stream: invalid size beats invalid highWaterMark');
+
done();
diff --git a/tests/wpt/web-platform-tests/streams/writable-streams/bad-underlying-sinks.js b/tests/wpt/web-platform-tests/streams/writable-streams/bad-underlying-sinks.js
index c519aad71cf..6cc1b0cc441 100644
--- a/tests/wpt/web-platform-tests/streams/writable-streams/bad-underlying-sinks.js
+++ b/tests/wpt/web-platform-tests/streams/writable-streams/bad-underlying-sinks.js
@@ -74,29 +74,20 @@ promise_test(t => {
}, 'close: returning a rejected promise should cause writer close() and ready to reject');
-promise_test(t => {
- const ws = new WritableStream({
+test(() => {
+ assert_throws(error1, () => new WritableStream({
get close() {
throw error1;
}
- });
+ }), 'constructor should throw');
+}, 'close: throwing getter should cause constructor to throw');
- const writer = ws.getWriter();
-
- return promise_rejects(t, error1, writer.close(), 'close should reject with the thrown error');
-}, 'close: throwing getter should cause writer close() to reject');
-
-promise_test(t => {
- const ws = new WritableStream({
+test(() => {
+ assert_throws(error1, () => new WritableStream({
get write() {
throw error1;
}
- });
-
- const writer = ws.getWriter();
-
- return promise_rejects(t, error1, writer.write('a'), 'write should reject with the thrown error')
- .then(() => promise_rejects(t, error1, writer.closed, 'closed should reject with the thrown error'));
+ }), 'constructor should throw');
}, 'write: throwing getter should cause write() and closed to reject');
promise_test(t => {
@@ -173,29 +164,18 @@ promise_test(t => {
}, 'write: returning a rejected promise (second write) should cause writer write() and ready to reject');
-promise_test(t => {
- const ws = new WritableStream({
+test(() => {
+ assert_throws(new TypeError(), () => new WritableStream({
abort: { apply() {} }
- });
-
- return promise_rejects(t, new TypeError(), ws.abort(error1), 'abort should reject with TypeError').then(() => {
- const writer = ws.getWriter();
- return promise_rejects(t, new TypeError(), writer.closed, 'closed should reject with a TypeError');
- });
+ }), 'constructor should throw');
}, 'abort: non-function abort method with .apply');
-promise_test(t => {
- const abortReason = new Error('different string');
- const ws = new WritableStream({
+test(() => {
+ assert_throws(error1, () => new WritableStream({
get abort() {
throw error1;
}
- });
-
- const writer = ws.getWriter();
-
- return promise_rejects(t, error1, writer.abort(abortReason), 'abort should reject with the thrown error')
- .then(() => promise_rejects(t, new TypeError(), writer.closed, 'closed should reject with a TypeError'));
+ }), 'constructor should throw');
}, 'abort: throwing getter should cause abort() and closed to reject');
promise_test(t => {
diff --git a/tests/wpt/web-platform-tests/streams/writable-streams/properties.js b/tests/wpt/web-platform-tests/streams/writable-streams/properties.js
index 99bd09a071a..7f420a79b6f 100644
--- a/tests/wpt/web-platform-tests/streams/writable-streams/properties.js
+++ b/tests/wpt/web-platform-tests/streams/writable-streams/properties.js
@@ -56,7 +56,7 @@ const expected = {
WritableStreamDefaultController: {
constructor: {
type: 'constructor',
- length: 4
+ length: 0
},
error: {
type: 'method',
@@ -147,7 +147,7 @@ for (const c in expected) {
const sinkMethods = {
start: {
length: 1,
- trigger: () => {}
+ trigger: () => Promise.resolve()
},
write: {
length: 2,
@@ -194,28 +194,32 @@ for (const method in sinkMethods) {
});
}, `sink method ${method} should be called even when it's located on the prototype chain`);
- if (method !== 'start') {
- promise_test(t => {
- const unreachedTraps = ['getPrototypeOf', 'setPrototypeOf', 'isExtensible', 'preventExtensions',
- 'getOwnPropertyDescriptor', 'defineProperty', 'has', 'set', 'deleteProperty', 'ownKeys',
- 'apply', 'construct'];
- const handler = {
- get: t.step_func((target, property) => {
- if (property === 'type') {
- return undefined;
- }
- assert_in_array(property, ['start', method], `only start() and ${method}() should be called`);
- return () => Promise.resolve();
- })
- };
- for (const trap of unreachedTraps) {
- handler[trap] = t.unreached_func(`${trap} should not be trapped`);
- }
- const sink = new Proxy({}, handler);
- const ws = new WritableStream(sink);
- return trigger(ws.getWriter());
- }, `unexpected properties should not be accessed when calling sink method ${method}`);
- }
+ promise_test(t => {
+ const unreachedTraps = ['getPrototypeOf', 'setPrototypeOf', 'isExtensible', 'preventExtensions',
+ 'getOwnPropertyDescriptor', 'defineProperty', 'has', 'set', 'deleteProperty', 'ownKeys',
+ 'apply', 'construct'];
+ const touchedProperties = [];
+ const handler = {
+ get: t.step_func((target, property) => {
+ touchedProperties.push(property);
+ if (property === 'type') {
+ return undefined;
+ }
+ return () => Promise.resolve();
+ })
+ };
+ for (const trap of unreachedTraps) {
+ handler[trap] = t.unreached_func(`${trap} should not be trapped`);
+ }
+ const sink = new Proxy({}, handler);
+ const ws = new WritableStream(sink);
+ assert_array_equals(touchedProperties, ['type', 'write', 'close', 'abort', 'start'],
+ 'expected properties should be got');
+ return trigger(ws.getWriter()).then(() => {
+ assert_array_equals(touchedProperties, ['type', 'write', 'close', 'abort', 'start'],
+ 'no properties should be accessed on method call');
+ });
+ }, `unexpected properties should not be accessed when calling sink method ${method}`);
}
done();
diff --git a/tests/wpt/web-platform-tests/svg/extensibility/foreignObject/properties.svg b/tests/wpt/web-platform-tests/svg/extensibility/foreignObject/properties.svg
new file mode 100644
index 00000000000..a89e1e59597
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/extensibility/foreignObject/properties.svg
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:h="http://www.w3.org/1999/xhtml">
+ <metadata>
+ <h:link rel="help" href="https://svgwg.org/svg2-draft/single-page.html#embedded-ForeignObjectElement"/>
+ <h:link rel="help" href="https://svgwg.org/svg2-draft/single-page.html#styling-PresentationAttributes"/>
+ <h:meta name="assert" content="x y width height are presentation attributes of foreignObject"/>
+ </metadata>
+ <style>
+ .c {
+ x: 10px;
+ y: 20px;
+ width: 30px;
+ height: 40px;
+ }
+ </style>
+ <foreignObject id="first"></foreignObject>
+ <foreignObject id="second" class="c"></foreignObject>
+ <foreignObject id="third" x="50" y="60" width="70" height="80"></foreignObject>
+ <foreignObject id="fourth" x="50" y="60" width="70" height="80" class="c"></foreignObject>
+ <h:script src="/resources/testharness.js"/>
+ <h:script src="/resources/testharnessreport.js"/>
+ <script><![CDATA[
+ test(function() {
+ var first = document.getElementById('first');
+ var second = document.getElementById('second');
+ var third = document.getElementById('third');
+ var fourth = document.getElementById('fourth');
+
+ assert_equals(getComputedStyle(first).x, "0px");
+ assert_equals(getComputedStyle(first).y, "0px");
+ assert_equals(getComputedStyle(first).width, "auto");
+ assert_equals(getComputedStyle(first).height, "auto");
+
+ assert_equals(getComputedStyle(second).x, "10px");
+ assert_equals(getComputedStyle(second).y, "20px");
+ assert_equals(getComputedStyle(second).width, "30px");
+ assert_equals(getComputedStyle(second).height, "40px");
+
+ assert_equals(getComputedStyle(third).x, "50px");
+ assert_equals(getComputedStyle(third).y, "60px");
+ assert_equals(getComputedStyle(third).width, "70px");
+ assert_equals(getComputedStyle(third).height, "80px");
+
+ assert_equals(getComputedStyle(fourth).x, "10px");
+ assert_equals(getComputedStyle(fourth).y, "20px");
+ assert_equals(getComputedStyle(fourth).width, "30px");
+ assert_equals(getComputedStyle(fourth).height, "40px");
+ });
+ ]]></script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/svg/foreignobject/position-svg-root-in-foreign-object-ref.html b/tests/wpt/web-platform-tests/svg/foreignobject/position-svg-root-in-foreign-object-ref.html
new file mode 100644
index 00000000000..668eb9b8c7e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/foreignobject/position-svg-root-in-foreign-object-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>SVG Reftest Reference</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<p>You should see the word PASS and no red below.</p>
+PASS
diff --git a/tests/wpt/web-platform-tests/svg/foreignobject/position-svg-root-in-foreign-object.html b/tests/wpt/web-platform-tests/svg/foreignobject/position-svg-root-in-foreign-object.html
new file mode 100644
index 00000000000..5bf38226627
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/foreignobject/position-svg-root-in-foreign-object.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>SVG: svg root child of foreignObject should be positionable</title>
+<link rel="author" title="Rune Lillesveen" href="mailto:futhark@chromium.org">
+<link rel="help" href="https://svgwg.org/svg2-draft/embedded.html#ForeignObjectElement">
+<link rel="match" href="position-svg-root-in-foreign-object-ref.html">
+<p>You should see the word PASS and no red below.</p>
+<svg>
+ <foreignObject>
+ PASS
+ <svg style="position:absolute; left: -1000px; width:100px; height: 100px; background: red"></svg>
+ </foreignObject>
+</svg>
diff --git a/tests/wpt/web-platform-tests/svg/import/animate-elem-33-t-manual.svg b/tests/wpt/web-platform-tests/svg/import/animate-elem-33-t-manual.svg
index 4b50ae3d564..292201d5c32 100644
--- a/tests/wpt/web-platform-tests/svg/import/animate-elem-33-t-manual.svg
+++ b/tests/wpt/web-platform-tests/svg/import/animate-elem-33-t-manual.svg
@@ -86,7 +86,7 @@
</circle>
</g>
<!-- THIRD TEST-->
- <!-- The lenght of the lines in the polyline (motionpath) are 100,50 and 100.
+ <!-- The length of the lines in the polyline (motionpath) are 100,50 and 100.
The animated circle starts at the midpoint of one of the "legs" and also pass
this point at time 1.4 since
1.4 = 4*(0.25) + (4*(0.75-0.25))*(1/5).
diff --git a/tests/wpt/web-platform-tests/svg/interfaces.html b/tests/wpt/web-platform-tests/svg/interfaces.html
index b1711852d07..698e6e7d414 100644
--- a/tests/wpt/web-platform-tests/svg/interfaces.html
+++ b/tests/wpt/web-platform-tests/svg/interfaces.html
@@ -13,7 +13,7 @@ interface Document : Node {};
interface ProcessingInstruction : Node {};
interface Element : Node {};
interface HTMLElement : Element {};
-[PrimaryGlobal] interface Window {};
+[Global=Window, Exposed=Window] interface Window {};
// Just need to know that DOMStringMap exists; its details are tested elsewhere.
interface DOMStringMap { };
diff --git a/tests/wpt/web-platform-tests/svg/path/bearing/absolute-ref.svg b/tests/wpt/web-platform-tests/svg/path/bearing/absolute-ref.svg
new file mode 100644
index 00000000000..85b20271a11
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/path/bearing/absolute-ref.svg
@@ -0,0 +1,9 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">
+ <style>
+ path {
+ stroke-width: 3;
+ stroke: blue;
+ }
+ </style>
+ <path d="M 20 150 v -120 h 140 v 120 z" />
+</svg>
diff --git a/tests/wpt/web-platform-tests/svg/path/bearing/absolute.svg b/tests/wpt/web-platform-tests/svg/path/bearing/absolute.svg
new file mode 100644
index 00000000000..0efc295f317
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/path/bearing/absolute.svg
@@ -0,0 +1,16 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">
+ <metadata>
+ <link xmlns="http://www.w3.org/1999/xhtml" rel="help" href="https://www.w3.org/TR/svg-paths/#PathDataBearingCommands"/>
+ <link xmlns="http://www.w3.org/1999/xhtml" rel="help" href="https://www.w3.org/TR/SVG2/paths.html#PathDataBearingCommands"/>
+ <link xmlns="http://www.w3.org/1999/xhtml" rel="help" href="https://svgwg.org/svg2-draft/changes.html#paths"/>
+ <link xmlns="http://www.w3.org/1999/xhtml" rel="match" href="absolute-ref.svg"/>
+ <meta xmlns="http://www.w3.org/1999/xhtml" name="assert" content="path element with B commands renders correctly."/>
+ </metadata>
+ <style>
+ path {
+ stroke-width: 3;
+ stroke: blue;
+ }
+ </style>
+ <path d="M 20 150 B -90 h 120 B 0 h 140 B 90 h 120 z" />
+</svg>
diff --git a/tests/wpt/web-platform-tests/svg/path/bearing/relative-ref.svg b/tests/wpt/web-platform-tests/svg/path/bearing/relative-ref.svg
new file mode 100644
index 00000000000..85b20271a11
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/path/bearing/relative-ref.svg
@@ -0,0 +1,9 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">
+ <style>
+ path {
+ stroke-width: 3;
+ stroke: blue;
+ }
+ </style>
+ <path d="M 20 150 v -120 h 140 v 120 z" />
+</svg>
diff --git a/tests/wpt/web-platform-tests/svg/path/bearing/relative.svg b/tests/wpt/web-platform-tests/svg/path/bearing/relative.svg
new file mode 100644
index 00000000000..75b87ff8acc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/path/bearing/relative.svg
@@ -0,0 +1,16 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">
+ <metadata>
+ <link xmlns="http://www.w3.org/1999/xhtml" rel="help" href="https://www.w3.org/TR/svg-paths/#PathDataBearingCommands"/>
+ <link xmlns="http://www.w3.org/1999/xhtml" rel="help" href="https://www.w3.org/TR/SVG2/paths.html#PathDataBearingCommands"/>
+ <link xmlns="http://www.w3.org/1999/xhtml" rel="help" href="https://svgwg.org/svg2-draft/changes.html#paths"/>
+ <link xmlns="http://www.w3.org/1999/xhtml" rel="match" href="absolute-ref.svg"/>
+ <meta xmlns="http://www.w3.org/1999/xhtml" name="assert" content="path element with b commands renders correctly."/>
+ </metadata>
+ <style>
+ path {
+ stroke-width: 3;
+ stroke: blue;
+ }
+ </style>
+ <path d="M 20 150 b -90 h 120 b 90 h 140 b 90 h 120 z" />
+</svg>
diff --git a/tests/wpt/web-platform-tests/svg/path/bearing/zero-ref.svg b/tests/wpt/web-platform-tests/svg/path/bearing/zero-ref.svg
new file mode 100644
index 00000000000..3558de3153e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/path/bearing/zero-ref.svg
@@ -0,0 +1,9 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
+ <style>
+ path {
+ stroke-width: 3;
+ stroke: blue;
+ }
+ </style>
+ <path d="M 25 50 h 10 m 10 0 h 10 m 10 0 h 10" />
+</svg>
diff --git a/tests/wpt/web-platform-tests/svg/path/bearing/zero.svg b/tests/wpt/web-platform-tests/svg/path/bearing/zero.svg
new file mode 100644
index 00000000000..80256429b6f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/path/bearing/zero.svg
@@ -0,0 +1,16 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
+ <metadata>
+ <link xmlns="http://www.w3.org/1999/xhtml" rel="help" href="https://www.w3.org/TR/svg-paths/#PathDataBearingCommands"/>
+ <link xmlns="http://www.w3.org/1999/xhtml" rel="help" href="https://www.w3.org/TR/SVG2/paths.html#PathDataBearingCommands"/>
+ <link xmlns="http://www.w3.org/1999/xhtml" rel="help" href="https://svgwg.org/svg2-draft/changes.html#paths"/>
+ <link xmlns="http://www.w3.org/1999/xhtml" rel="match" href="zero-ref.svg"/>
+ <meta xmlns="http://www.w3.org/1999/xhtml" name="assert" content="path element with bearing 0 renders correctly."/>
+ </metadata>
+ <style>
+ path {
+ stroke-width: 3;
+ stroke: blue;
+ }
+ </style>
+ <path d="M 25 50 h 10 B 0 m 10 0 h 10 b 0 m 10 0 h 10" />
+</svg>
diff --git a/tests/wpt/web-platform-tests/svg/path/property/d-interpolation-discrete.svg b/tests/wpt/web-platform-tests/svg/path/property/d-interpolation-discrete.svg
new file mode 100644
index 00000000000..aa9087395fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/path/property/d-interpolation-discrete.svg
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:h="http://www.w3.org/1999/xhtml">
+ <metadata>
+ <h:link rel="help" href="https://svgwg.org/svg2-draft/paths.html#TheDProperty"/>
+ <h:meta name="assert" content="d falls back to step interpolation when no interpolation is possible."/>
+ </metadata>
+
+ <g id="container"/>
+
+ <h:script src="/resources/testharness.js"/>
+ <h:script src="/resources/testharnessreport.js"/>
+ <h:script src="resources/interpolation-test-common.js"/>
+ <script><![CDATA[
+ 'use strict';
+
+ // Distinct number of path segments
+ test_no_interpolation({
+ property: 'd',
+ from: "path('M 0 0 H 1 H 2')",
+ to: "path('M 0 0 H 3')"
+ });
+
+ test_no_interpolation({
+ property: 'd',
+ from: "path('M 1 2 L 3 4 Z')",
+ to: "none"
+ });
+
+ // Distinct segment types
+ test_no_interpolation({
+ property: 'd',
+ from: "path('M 10 0 H 11')",
+ to: "path('M 20 0 V 2')"
+ });
+
+ test_no_interpolation({
+ property: 'd',
+ from: "path('M 1 2 L 4 6 Z')",
+ to: "path('M 1 2 H 4 V 6')"
+ });
+ ]]></script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/svg/path/property/d-interpolation-relative-absolute.svg b/tests/wpt/web-platform-tests/svg/path/property/d-interpolation-relative-absolute.svg
new file mode 100644
index 00000000000..65d2f3b2eb6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/path/property/d-interpolation-relative-absolute.svg
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:h="http://www.w3.org/1999/xhtml">
+ <metadata>
+ <h:link rel="help" href="https://svgwg.org/svg2-draft/paths.html#TheDProperty"/>
+ <h:meta name="assert" content="d can interpolate between absolute and relative paths."/>
+ </metadata>
+
+ <g id="container"/>
+
+ <h:script src="/resources/testharness.js"/>
+ <h:script src="/resources/testharnessreport.js"/>
+ <h:script src="resources/interpolation-test-common.js"/>
+ <script><![CDATA[
+ 'use strict';
+
+ // Mix relative and non-relative
+ test_interpolation({
+ property: 'd',
+ from: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')",
+ to: "path('M 0 0 L 100 100 m 0 100 l 100 0 z l 300 100 z')"
+ }, [
+ {at: -1, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 0 -100 Z')"},
+ {at: 0, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"},
+ {at: 0.125, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 225 125 Z')"},
+ {at: 0.875, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 375 275 Z')"},
+ {at: 1, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 400 300 Z')"},
+ {at: 2, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 600 500 Z')"},
+ ]);
+
+ test_interpolation({
+ property: 'd',
+ from: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')",
+ to: "path('M 0 0 L 100 100 m 0 100 l 100 0 z l 100 -100 z')"
+ }, [
+ {at: -1, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"},
+ {at: 0, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"},
+ {at: 0.125, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"},
+ {at: 0.875, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"},
+ {at: 1, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"},
+ {at: 2, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"},
+ ]);
+
+ test_interpolation({
+ property: 'd',
+ from: "path('m 10 20 l 40 50 z l 40 60 z m 60 70 l 90 60 z t 70 130')",
+ to: "path('M 210 220 L 170 190 Z L 90 120 Z M 110 130 L 200 230 Z T 220 220')"
+ }, [
+ {at: -1, expect: "path('M -190 -180 L -70 -50 Z L 10 40 Z M 30 50 L 120 70 Z T 60 220')"},
+ {at: 0, expect: "path('M 10 20 L 50 70 Z L 50 80 Z M 70 90 L 160 150 Z T 140 220')"},
+ {at: 0.125, expect: "path('M 35 45 L 65 85 Z L 55 85 Z M 75 95 L 165 160 Z T 150 220')"},
+ {at: 0.875, expect: "path('M 185 195 L 155 175 Z L 85 115 Z M 105 125 L 195 220 Z T 210 220')"},
+ {at: 1, expect: "path('M 210 220 L 170 190 Z L 90 120 Z M 110 130 L 200 230 Z T 220 220')"},
+ {at: 2, expect: "path('M 410 420 L 290 310 Z L 130 160 Z M 150 170 L 240 310 Z T 300 220')"}
+ ]);
+
+ test_interpolation({
+ property: 'd',
+ from: "path('m 10 20 c 40 50 30 60 80 70 c 120 130 170 140 110 160')",
+ to: "path('M 130 100 C 130 150 120 160 210 170 C 290 300 340 310 320 330')"
+ }, [
+ {at: -1, expect: "path('M -110 -60 C -30 -10 -40 0 -30 10 C 130 140 180 150 80 170')"},
+ {at: 0, expect: "path('M 10 20 C 50 70 40 80 90 90 C 210 220 260 230 200 250')"},
+ {at: 0.125, expect: "path('M 25 30 C 60 80 50 90 105 100 C 220 230 270 240 215 260')"},
+ {at: 0.875, expect: "path('M 115 90 C 120 140 110 150 195 160 C 280 290 330 300 305 320')"},
+ {at: 1, expect: "path('M 130 100 C 130 150 120 160 210 170 C 290 300 340 310 320 330')"},
+ {at: 2, expect: "path('M 250 180 C 210 230 200 240 330 250 C 370 380 420 390 440 410')"}
+ ]);
+
+ test_interpolation({
+ property: 'd',
+ from: "path('m 10 20 q 30 60 40 50 q 110 80 90 80')",
+ to: "path('M 130 100 Q 120 160 130 150 Q 200 150 180 190')"
+ }, [
+ {at: -1, expect: "path('M -110 -60 Q -40 0 -30 -10 Q 120 150 100 110')"},
+ {at: 0, expect: "path('M 10 20 Q 40 80 50 70 Q 160 150 140 150')"},
+ {at: 0.125, expect: "path('M 25 30 Q 50 90 60 80 Q 165 150 145 155')"},
+ {at: 0.875, expect: "path('M 115 90 Q 110 150 120 140 Q 195 150 175 185')"},
+ {at: 1, expect: "path('M 130 100 Q 120 160 130 150 Q 200 150 180 190')"},
+ {at: 2, expect: "path('M 250 180 Q 200 240 210 230 Q 240 150 220 230')"}
+ ]);
+
+ test_interpolation({
+ property: 'd',
+ from: "path('m 10 20 s 30 60 40 50 s 110 60 90 70')",
+ to: "path('M 130 140 S 120 160 130 150 S 200 170 140 180')"
+ }, [
+ {at: -1, expect: "path('M -110 -100 S -40 0 -30 -10 S 120 90 140 100')"},
+ {at: 0, expect: "path('M 10 20 S 40 80 50 70 S 160 130 140 140')"},
+ {at: 0.125, expect: "path('M 25 35 S 50 90 60 80 S 165 135 140 145')"},
+ {at: 0.875, expect: "path('M 115 125 S 110 150 120 140 S 195 165 140 175')"},
+ {at: 1, expect: "path('M 130 140 S 120 160 130 150 S 200 170 140 180')"},
+ {at: 2, expect: "path('M 250 260 S 200 240 210 230 S 240 210 140 220')"}
+ ]);
+
+ test_interpolation({
+ property: 'd',
+ from: "path('m 10 20 h 30 v 60 h 10 v -10 l 110 60 Z')",
+ to: "path('M 130 140 H 120 V 160 H 130 V 150 L 200 170 Z')"
+ }, [
+ {at: -1, expect: "path('M -110 -100 H -40 V 0 H -30 V -10 L 120 90 Z')"},
+ {at: 0, expect: "path('M 10 20 H 40 V 80 H 50 V 70 L 160 130 Z')"},
+ {at: 0.125, expect: "path('M 25 35 H 50 V 90 H 60 V 80 L 165 135 Z')"},
+ {at: 0.875, expect: "path('M 115 125 H 110 V 150 H 120 V 140 L 195 165 Z')"},
+ {at: 1, expect: "path('M 130 140 H 120 V 160 H 130 V 150 L 200 170 Z')"},
+ {at: 2, expect: "path('M 250 260 H 200 V 240 H 210 V 230 L 240 210 Z')"}
+ ]);
+
+ test_interpolation({
+ property: 'd',
+ from: "path('m 10 20 a 10 20 30 1 0 40 50 a 110 120 30 1 1 140 50')",
+ to: "path('M 18 12 A 50 100 70 0 1 90 110 A 150 160 70 0 1 70 80')"
+ }, [
+ {at: -1, expect: "path('M 2 28 A -30 -60 -10 1 0 10 30 A 70 80 -10 1 1 310 160')"},
+ {at: 0, expect: "path('M 10 20 A 10 20 30 1 0 50 70 A 110 120 30 1 1 190 120')"},
+ {at: 0.125, expect: "path('M 11 19 A 15 30 35 1 0 55 75 A 115 125 35 1 1 175 115')"},
+ {at: 0.875, expect: "path('M 17 13 A 45 90 65 0 1 85 105 A 145 155 65 0 1 85 85')"},
+ {at: 1, expect: "path('M 18 12 A 50 100 70 0 1 90 110 A 150 160 70 0 1 70 80')"},
+ {at: 2, expect: "path('M 26 4 A 90 180 110 0 1 130 150 A 190 200 110 0 1 -50 40')"}
+ ]);
+ ]]></script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/svg/path/property/d-interpolation-single.svg b/tests/wpt/web-platform-tests/svg/path/property/d-interpolation-single.svg
new file mode 100644
index 00000000000..25c523168a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/path/property/d-interpolation-single.svg
@@ -0,0 +1,245 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:h="http://www.w3.org/1999/xhtml">
+ <metadata>
+ <h:link rel="help" href="https://svgwg.org/svg2-draft/paths.html#TheDProperty"/>
+ <h:meta name="assert" content="Each path command interpolates."/>
+ </metadata>
+
+ <g id="container"/>
+
+ <h:script src="/resources/testharness.js"/>
+ <h:script src="/resources/testharnessreport.js"/>
+ <h:script src="resources/interpolation-test-common.js"/>
+ <script><![CDATA[
+ 'use strict';
+
+ // Exercise each segment type
+ test_interpolation({
+ property: 'd',
+ from: "path('M 20 70')",
+ to: "path('M 100 30')"
+ }, [
+ {at: -1, expect: "path('M -60 110')"},
+ {at: 0, expect: "path('M 20 70')"},
+ {at: 0.125, expect: "path('M 30 65')"},
+ {at: 0.875, expect: "path('M 90 35')"},
+ {at: 1, expect: "path('M 100 30')"},
+ {at: 2, expect: "path('M 180 -10')"}
+ ]);
+
+ test_interpolation({
+ property: 'd',
+ from: "path('m 20 70')",
+ to: "path('m 100 30')"
+ }, [
+ {at: -1, expect: "path('M -60 110')"},
+ {at: 0, expect: "path('M 20 70')"},
+ {at: 0.125, expect: "path('M 30 65')"},
+ {at: 0.875, expect: "path('M 90 35')"},
+ {at: 1, expect: "path('M 100 30')"},
+ {at: 2, expect: "path('M 180 -10')"}
+ ]);
+
+ test_interpolation({
+ property: 'd',
+ from: "path('m 100 200 L 120 270')",
+ to: "path('m 100 200 L 200 230')"
+ }, [
+ {at: -1, expect: "path('M 100 200 L 40 310')"},
+ {at: 0, expect: "path('M 100 200 L 120 270')"},
+ {at: 0.125, expect: "path('M 100 200 L 130 265')"},
+ {at: 0.875, expect: "path('M 100 200 L 190 235')"},
+ {at: 1, expect: "path('M 100 200 L 200 230')"},
+ {at: 2, expect: "path('M 100 200 L 280 190')"}
+ ]);
+
+ test_interpolation({
+ property: 'd',
+ from: "path('m 100 200 l 20 70')",
+ to: "path('m 100 200 l 100 30')"
+ }, [
+ {at: -1, expect: "path('M 100 200 L 40 310')"},
+ {at: 0, expect: "path('M 100 200 L 120 270')"},
+ {at: 0.125, expect: "path('M 100 200 L 130 265')"},
+ {at: 0.875, expect: "path('M 100 200 L 190 235')"},
+ {at: 1, expect: "path('M 100 200 L 200 230')"},
+ {at: 2, expect: "path('M 100 200 L 280 190')"}
+ ]);
+
+ test_interpolation({
+ property: 'd',
+ from: "path('M 20 10 C 32 42 52 62 120 2200')",
+ to: "path('M 20 10 C 40 50 60 70 200 3000')",
+ }, [
+ {at: -1, expect: "path('M 20 10 C 24 34 44 54 40 1400')"},
+ {at: 0, expect: "path('M 20 10 C 32 42 52 62 120 2200')"},
+ {at: 0.125, expect: "path('M 20 10 C 33 43 53 63 130 2300')"},
+ {at: 0.875, expect: "path('M 20 10 C 39 49 59 69 190 2900')"},
+ {at: 1, expect: "path('M 20 10 C 40 50 60 70 200 3000')"},
+ {at: 2, expect: "path('M 20 10 C 48 58 68 78 280 3800')"}
+ ]);
+ test_interpolation({
+ property: 'd',
+ from: "path('m 20 10 c 12 32 32 52 100 2190')",
+ to: "path('m 20 10 c 20 40 40 60 180 2990')"
+ }, [
+ {at: -1, expect: "path('M 20 10 C 24 34 44 54 40 1400')"},
+ {at: 0, expect: "path('M 20 10 C 32 42 52 62 120 2200')"},
+ {at: 0.125, expect: "path('M 20 10 C 33 43 53 63 130 2300')"},
+ {at: 0.875, expect: "path('M 20 10 C 39 49 59 69 190 2900')"},
+ {at: 1, expect: "path('M 20 10 C 40 50 60 70 200 3000')"},
+ {at: 2, expect: "path('M 20 10 C 48 58 68 78 280 3800')"}
+ ]);
+
+ test_interpolation({
+ property: 'd',
+ from: "path('M 20 10 Q 32 42 120 2200')",
+ to: "path('M 20 10 Q 40 50 200 3000')"
+ }, [
+ {at: -1, expect: "path('M 20 10 Q 24 34 40 1400')"},
+ {at: 0, expect: "path('M 20 10 Q 32 42 120 2200')"},
+ {at: 0.125, expect: "path('M 20 10 Q 33 43 130 2300')"},
+ {at: 0.875, expect: "path('M 20 10 Q 39 49 190 2900')"},
+ {at: 1, expect: "path('M 20 10 Q 40 50 200 3000')"},
+ {at: 2, expect: "path('M 20 10 Q 48 58 280 3800')"}
+ ]);
+ test_interpolation({
+ property: 'd',
+ from: "path('m 20 10 q 12 32 100 2190')",
+ to: "path('m 20 10 q 20 40 180 2990')"
+ }, [
+ {at: -1, expect: "path('M 20 10 Q 24 34 40 1400')"},
+ {at: 0, expect: "path('M 20 10 Q 32 42 120 2200')"},
+ {at: 0.125, expect: "path('M 20 10 Q 33 43 130 2300')"},
+ {at: 0.875, expect: "path('M 20 10 Q 39 49 190 2900')"},
+ {at: 1, expect: "path('M 20 10 Q 40 50 200 3000')"},
+ {at: 2, expect: "path('M 20 10 Q 48 58 280 3800')"}
+ ]);
+
+ test_interpolation({
+ property: 'd',
+ from: "path('M 100 400 A 10 20 30 1 0 140 450')",
+ to: "path('M 300 200 A 50 60 70 0 1 380 290')"
+ }, [
+ {at: -1, expect: "path('M -100 600 A -30 -20 -10 1 0 -100 610')"},
+ {at: 0, expect: "path('M 100 400 A 10 20 30 1 0 140 450')"},
+ {at: 0.125, expect: "path('M 125 375 A 15 25 35 1 0 170 430')"},
+ {at: 0.875, expect: "path('M 275 225 A 45 55 65 0 1 350 310')"},
+ {at: 1, expect: "path('M 300 200 A 50 60 70 0 1 380 290')"},
+ {at: 2, expect: "path('M 500 0 A 90 100 110 0 1 620 130')"}
+ ]);
+ test_interpolation({
+ property: 'd',
+ from: "path('m 100 400 a 10 20 30 1 0 40 50')",
+ to: "path('m 300 200 a 50 60 70 0 1 80 90')"
+ }, [
+ {at: -1, expect: "path('M -100 600 A -30 -20 -10 1 0 -100 610')"},
+ {at: 0, expect: "path('M 100 400 A 10 20 30 1 0 140 450')"},
+ {at: 0.125, expect: "path('M 125 375 A 15 25 35 1 0 170 430')"},
+ {at: 0.875, expect: "path('M 275 225 A 45 55 65 0 1 350 310')"},
+ {at: 1, expect: "path('M 300 200 A 50 60 70 0 1 380 290')"},
+ {at: 2, expect: "path('M 500 0 A 90 100 110 0 1 620 130')"}
+ ]);
+
+ test_interpolation({
+ property: 'd',
+ from: "path('M 50 60 H 70')",
+ to: "path('M 10 140 H 270')"
+ }, [
+ {at: -1, expect: "path('M 90 -20 H -130')"},
+ {at: 0, expect: "path('M 50 60 H 70')"},
+ {at: 0.125, expect: "path('M 45 70 H 95')"},
+ {at: 0.875, expect: "path('M 15 130 H 245')"},
+ {at: 1, expect: "path('M 10 140 H 270')"},
+ {at: 2, expect: "path('M -30 220 H 470')"}
+ ]);
+ test_interpolation({
+ property: 'd',
+ from: "path('m 50 60 h 20')",
+ to: "path('m 10 140 h 260')"
+ }, [
+ {at: -1, expect: "path('M 90 -20 H -130')"},
+ {at: 0, expect: "path('M 50 60 H 70')"},
+ {at: 0.125, expect: "path('M 45 70 H 95')"},
+ {at: 0.875, expect: "path('M 15 130 H 245')"},
+ {at: 1, expect: "path('M 10 140 H 270')"},
+ {at: 2, expect: "path('M -30 220 H 470')"}
+ ]);
+
+ test_interpolation({
+ property: 'd',
+ from: "path('M 50 60 V 70')",
+ to: "path('M 10 140 V 270')"
+ }, [
+ {at: -1, expect: "path('M 90 -20 V -130')"},
+ {at: 0, expect: "path('M 50 60 V 70')"},
+ {at: 0.125, expect: "path('M 45 70 V 95')"},
+ {at: 0.875, expect: "path('M 15 130 V 245')"},
+ {at: 1, expect: "path('M 10 140 V 270')"},
+ {at: 2, expect: "path('M -30 220 V 470')"}
+ ]);
+ test_interpolation({
+ property: 'd',
+ from: "path('m 50 60 v 10')",
+ to: "path('m 10 140 v 130')"
+ }, [
+ {at: -1, expect: "path('M 90 -20 V -130')"},
+ {at: 0, expect: "path('M 50 60 V 70')"},
+ {at: 0.125, expect: "path('M 45 70 V 95')"},
+ {at: 0.875, expect: "path('M 15 130 V 245')"},
+ {at: 1, expect: "path('M 10 140 V 270')"},
+ {at: 2, expect: "path('M -30 220 V 470')"}
+ ]);
+
+ test_interpolation({
+ property: 'd',
+ from: "path('M 12 34 S 45 67 89 123')",
+ to: "path('M 20 26 S 61 51 113 99')"
+ }, [
+ {at: -1, expect: "path('M 4 42 S 29 83 65 147')"},
+ {at: 0, expect: "path('M 12 34 S 45 67 89 123')"},
+ {at: 0.125, expect: "path('M 13 33 S 47 65 92 120')"},
+ {at: 0.875, expect: "path('M 19 27 S 59 53 110 102')"},
+ {at: 1, expect: "path('M 20 26 S 61 51 113 99')"},
+ {at: 2, expect: "path('M 28 18 S 77 35 137 75')"},
+ ]);
+ test_interpolation({
+ property: 'd',
+ from: "path('m 12 34 s 33 33 77 89')",
+ to: "path('m 20 26 s 41 25 93 73')"
+ }, [
+ {at: -1, expect: "path('M 4 42 S 29 83 65 147')"},
+ {at: 0, expect: "path('M 12 34 S 45 67 89 123')"},
+ {at: 0.125, expect: "path('M 13 33 S 47 65 92 120')"},
+ {at: 0.875, expect: "path('M 19 27 S 59 53 110 102')"},
+ {at: 1, expect: "path('M 20 26 S 61 51 113 99')"},
+ {at: 2, expect: "path('M 28 18 S 77 35 137 75')"},
+ ]);
+
+ test_interpolation({
+ property: 'd',
+ from: "path('M 12 34 T 45 67')",
+ to: "path('M 20 26 T 61 51')"
+ }, [
+ {at: -1, expect: "path('M 4 42 T 29 83')"},
+ {at: 0, expect: "path('M 12 34 T 45 67')"},
+ {at: 0.125, expect: "path('M 13 33 T 47 65')"},
+ {at: 0.875, expect: "path('M 19 27 T 59 53')"},
+ {at: 1, expect: "path('M 20 26 T 61 51')"},
+ {at: 2, expect: "path('M 28 18 T 77 35')"},
+ ]);
+ test_interpolation({
+ property: 'd',
+ from: "path('m 12 34 t 33 33')",
+ to: "path('m 20 26 t 41 25')"
+ }, [
+ {at: -1, expect: "path('M 4 42 T 29 83')"},
+ {at: 0, expect: "path('M 12 34 T 45 67')"},
+ {at: 0.125, expect: "path('M 13 33 T 47 65')"},
+ {at: 0.875, expect: "path('M 19 27 T 59 53')"},
+ {at: 1, expect: "path('M 20 26 T 61 51')"},
+ {at: 2, expect: "path('M 28 18 T 77 35')"},
+ ]);
+ ]]></script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/svg/path/property/getComputedStyle.svg b/tests/wpt/web-platform-tests/svg/path/property/getComputedStyle.svg
new file mode 100644
index 00000000000..af30862781a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/path/property/getComputedStyle.svg
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:h="http://www.w3.org/1999/xhtml">
+ <metadata>
+ <h:link rel="help" href="https://svgwg.org/svg2-draft/paths.html#TheDProperty"/>
+ <h:meta name="assert" content="d is a property"/>
+ </metadata>
+ <style>
+ .p3 {
+ d: path('M 10 3 H 30');
+ }
+ .g5 {
+ d: path('M 10 5 H 50');
+ }
+ .p6 {
+ d: inherit;
+ }
+ </style>
+ <g id="g0">
+ <path id="p1"></path>
+ <path id="p2" d="M 10 2 H 20"></path>
+ <path id="p3" class="p3"></path>
+ <path id="p4" style="d: path('M 10 4 H 40')"></path>
+ </g>
+ <g id="g5" class="g5">
+ <path id="p6" class="p6"></path>
+ <path id="p7"></path>
+ </g>
+ <h:script src="/resources/testharness.js"/>
+ <h:script src="/resources/testharnessreport.js"/>
+ <script><![CDATA[
+ test(function() {
+ var g0 = document.getElementById('g0');
+ var p1 = document.getElementById('p1');
+ var p2 = document.getElementById('p2');
+ var p3 = document.getElementById('p3');
+ var p4 = document.getElementById('p4');
+ var g5 = document.getElementById('g5');
+ var p6 = document.getElementById('p6');
+ var p7 = document.getElementById('p7');
+
+ assert_equals(getComputedStyle(g0).d, "none");
+ assert_equals(getComputedStyle(p1).d, "none");
+ assert_equals(getComputedStyle(p2).d, "path('M 10 2 H 20')");
+ assert_equals(getComputedStyle(p3).d, "path('M 10 3 H 30')");
+ assert_equals(getComputedStyle(p4).d, "path('M 10 4 H 40')");
+ assert_equals(getComputedStyle(g5).d, "path('M 10 5 H 50')");
+ assert_equals(getComputedStyle(p6).d, "path('M 10 5 H 50')");
+ assert_equals(getComputedStyle(p7).d, "none");
+ });
+ ]]></script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/svg/path/property/priority-ref.svg b/tests/wpt/web-platform-tests/svg/path/property/priority-ref.svg
new file mode 100644
index 00000000000..cbc7c385f6d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/path/property/priority-ref.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
+ <style>
+ path {
+ stroke-width: 3;
+ stroke: blue;
+ }
+ </style>
+ <path d="M 20 10 h 70" />
+ <path d="M 20 80 h 70" />
+</svg>
diff --git a/tests/wpt/web-platform-tests/svg/path/property/priority.svg b/tests/wpt/web-platform-tests/svg/path/property/priority.svg
new file mode 100644
index 00000000000..ef187c19136
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/path/property/priority.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:h="http://www.w3.org/1999/xhtml" width="100" height="100">
+ <metadata>
+ <h:link rel="help" href="https://svgwg.org/svg2-draft/paths.html#TheDProperty"/>
+ <h:link rel="match" href="priority-ref.svg"/>
+ <h:meta name="assert" content="Property overrides attribute."/>
+ </metadata>
+ <style>
+ path {
+ stroke-width: 3;
+ stroke: blue;
+ }
+ #top {
+ d: path('M 20 10 h 70');
+ }
+ </style>
+ <path id="top" d="M 10 20 h 70" />
+ <path d="M 10 90 h 70" style="d: path('M 20 80 h 70')" />
+</svg>
diff --git a/tests/wpt/web-platform-tests/svg/path/property/resources/interpolation-test-common.js b/tests/wpt/web-platform-tests/svg/path/property/resources/interpolation-test-common.js
new file mode 100644
index 00000000000..b7f8cd308d7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/path/property/resources/interpolation-test-common.js
@@ -0,0 +1,71 @@
+'use strict';
+function test_interpolation(settings, expectations) {
+
+ test(function(){
+ assert_true(CSS.supports(settings.property, settings.from), 'Value "' + settings.from + '" is supported by ' + settings.property);
+ assert_true(CSS.supports(settings.property, settings.to), 'Value "' + settings.to + '" is supported by ' + settings.property);
+ }, '"' + settings.from + '" and "' + settings.to + '" are valid ' + settings.property + ' values');
+
+ const container = document.getElementById('container');
+ for (let i = 0; i < expectations.length; ++i) {
+ const progress = expectations[i].at;
+ const expectation = expectations[i].expect;
+ const animationId = 'anim' + i;
+ const targetId = 'target' + i;
+ const referenceId = 'reference' + i;
+
+ test(function(){
+ assert_true(CSS.supports(settings.property, expectation), 'Value "' + expectation + '" is supported by ' + settings.property);
+
+ const target = document.createElementNS('http://www.w3.org/2000/svg', 'g');
+ target.id = targetId;
+ container.appendChild(target);
+
+ const reference = document.createElementNS('http://www.w3.org/2000/svg', 'g');
+ reference.id = referenceId;
+ container.appendChild(reference);
+
+ assert_equals(getComputedStyle(target)[settings.property], getComputedStyle(reference)[settings.property]);
+
+ // Create an animation of length 2s that starts at -1s so the current time of 0s is
+ // exactly halfway through the animation. A cubic bezier timing function is used that
+ // evaluates to |progress| at the current time (halfway through the animation).
+
+ // Cubic bezier evaluates to |progress| at 50%.
+ const y = (8 * progress - 1) / 6;
+ const timing_function = 'cubic-bezier(0, ' + y + ', 1, ' + y + ')';
+
+ const stylesheet = document.createElementNS('http://www.w3.org/2000/svg', 'style');
+ stylesheet.textContent =
+ '#' + targetId + ' {\n' +
+ ' animation: 2s ' + timing_function + ' -1s paused ' + animationId + ';\n' +
+ '}\n' +
+ '@keyframes ' + animationId + ' {\n' +
+ ' 0% { ' + settings.property + ': ' + settings.from + '; }\n' +
+ ' 100% { ' + settings.property + ': ' + settings.to + '; }\n' +
+ '}\n' +
+ '#' + referenceId + ' {\n' +
+ ' ' + settings.property + ': ' + expectation + ';\n' +
+ '}\n';
+ container.appendChild(stylesheet);
+
+ assert_equals(getComputedStyle(target)[settings.property], getComputedStyle(reference)[settings.property]);
+ assert_equals(getComputedStyle(target)[settings.property], expectation);
+
+ container.removeChild(target);
+ container.removeChild(reference);
+ container.removeChild(stylesheet);
+ }, 'Animation between "' + settings.from + '" and "' + settings.to + '" at progress ' + progress);
+ }
+}
+
+function test_no_interpolation(settings) {
+ const expectFrom = [-1, 0, 0.125].map(function (progress) {
+ return {at: progress, expect: settings.from};
+ });
+ const expectTo = [0.875, 1, 2].map(function (progress) {
+ return {at: progress, expect: settings.to};
+ });
+
+ test_interpolation(settings, expectFrom.concat(expectTo));
+}
diff --git a/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGClipPathElement.html b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGClipPathElement.html
new file mode 100644
index 00000000000..1200fd450a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGClipPathElement.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Use of SVGAnimatedEnumeration within SVGClipPathElement</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ // This test checks the use of SVGAnimatedEnumeration within SVGClipPathElement.
+
+ var clipPathElement = document.createElementNS("http://www.w3.org/2000/svg", "clipPath");
+ clipPathElement.setAttribute("clipPathUnits", "userSpaceOnUse");
+
+ // Check initial 'clipPathUnits' value.
+ assert_true(clipPathElement.clipPathUnits instanceof SVGAnimatedEnumeration);
+ assert_equals(typeof(clipPathElement.clipPathUnits.baseVal), "number");
+ assert_equals(clipPathElement.clipPathUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+
+ // Switch to 'objectBoundingBox'.
+ clipPathElement.clipPathUnits.baseVal = SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
+ assert_equals(clipPathElement.clipPathUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(clipPathElement.getAttribute('clipPathUnits'), "objectBoundingBox");
+
+ // Try setting invalid values.
+ assert_throws(new TypeError(), function() { clipPathElement.clipPathUnits.baseVal = 3; });
+ assert_equals(clipPathElement.clipPathUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(clipPathElement.getAttribute('clipPathUnits'), "objectBoundingBox");
+
+ assert_throws(new TypeError(), function() { clipPathElement.clipPathUnits.baseVal = -1; });
+ assert_equals(clipPathElement.clipPathUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(clipPathElement.getAttribute('clipPathUnits'), "objectBoundingBox");
+
+ assert_throws(new TypeError(), function() { clipPathElement.clipPathUnits.baseVal = 0; });
+ assert_equals(clipPathElement.clipPathUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(clipPathElement.getAttribute('clipPathUnits'), "objectBoundingBox");
+
+ // Switch to 'userSpaceOnUse'.
+ clipPathElement.clipPathUnits.baseVal = SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE;
+ assert_equals(clipPathElement.clipPathUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+ assert_equals(clipPathElement.getAttribute('clipPathUnits'), "userSpaceOnUse");
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGComponentTransferFunctionElement.html b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGComponentTransferFunctionElement.html
new file mode 100644
index 00000000000..7d8a4be26ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGComponentTransferFunctionElement.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML>
+<title>Use of SVGAnimatedEnumeration within SVGComponentTransferFunctionElement</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ // This test checks the use of SVGAnimatedEnumeration within SVGComponentTransferFunctionElement.
+
+ var feFuncRElement = document.createElementNS("http://www.w3.org/2000/svg", "feFuncR");
+ feFuncRElement.setAttribute("type", "identity");
+
+ // Check initial 'type' value.
+ assert_true(feFuncRElement.type instanceof SVGAnimatedEnumeration);
+ assert_equals(typeof(feFuncRElement.type.baseVal), "number");
+ assert_equals(feFuncRElement.type.baseVal, SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY);
+
+ // Switch to 'table'.
+ feFuncRElement.type.baseVal = SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_TABLE;
+ assert_equals(feFuncRElement.type.baseVal, SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_TABLE);
+ assert_equals(feFuncRElement.getAttribute('type'), "table");
+
+ // Switch to 'discrete'.
+ feFuncRElement.type.baseVal = SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE;
+ assert_equals(feFuncRElement.type.baseVal, SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE);
+ assert_equals(feFuncRElement.getAttribute('type'), "discrete");
+
+ // Switch to 'linear'.
+ feFuncRElement.type.baseVal = SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_LINEAR;
+ assert_equals(feFuncRElement.type.baseVal, SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_LINEAR);
+ assert_equals(feFuncRElement.getAttribute('type'), "linear");
+
+ // Switch to 'gamma'.
+ feFuncRElement.type.baseVal = SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_GAMMA;
+ assert_equals(feFuncRElement.type.baseVal, SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_GAMMA);
+ assert_equals(feFuncRElement.getAttribute('type'), "gamma");
+
+ // Try setting invalid values.
+ assert_throws(new TypeError(), function() { feFuncRElement.type.baseVal = 6; });
+ assert_equals(feFuncRElement.type.baseVal, SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_GAMMA);
+ assert_equals(feFuncRElement.getAttribute('type'), "gamma");
+
+ assert_throws(new TypeError(), function() { feFuncRElement.type.baseVal = -1; });
+ assert_equals(feFuncRElement.type.baseVal, SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_GAMMA);
+ assert_equals(feFuncRElement.getAttribute('type'), "gamma");
+
+ assert_throws(new TypeError(), function() { feFuncRElement.type.baseVal = 0; });
+ assert_equals(feFuncRElement.type.baseVal, SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_GAMMA);
+ assert_equals(feFuncRElement.getAttribute('type'), "gamma");
+
+ // Switch to 'identity'.
+ feFuncRElement.type.baseVal = SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY;
+ assert_equals(feFuncRElement.type.baseVal, SVGComponentTransferFunctionElement.SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY);
+ assert_equals(feFuncRElement.getAttribute('type'), "identity");
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFEBlendElement.html b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFEBlendElement.html
new file mode 100644
index 00000000000..b399264a8d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFEBlendElement.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML>
+<title>Use of SVGAnimatedEnumeration within SVGFEBlendElement</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ // This test checks the use of SVGAnimatedEnumeration within SVGFEBlendElement.
+
+ var feBlendElement = document.createElementNS("http://www.w3.org/2000/svg", "feBlend");
+ feBlendElement.setAttribute("mode", "normal");
+
+ // Check initial 'mode' value.
+ assert_true(feBlendElement.mode instanceof SVGAnimatedEnumeration);
+ assert_equals(typeof(feBlendElement.mode.baseVal), "number");
+ assert_equals(feBlendElement.mode.baseVal, SVGFEBlendElement.SVG_FEBLEND_MODE_NORMAL);
+
+ // Switch to 'multiply'.
+ feBlendElement.mode.baseVal = SVGFEBlendElement.SVG_FEBLEND_MODE_MULTIPLY;
+ assert_equals(feBlendElement.mode.baseVal, SVGFEBlendElement.SVG_FEBLEND_MODE_MULTIPLY);
+ assert_equals(feBlendElement.getAttribute('mode'), "multiply");
+
+ // Switch to 'screen'.
+ feBlendElement.mode.baseVal = SVGFEBlendElement.SVG_FEBLEND_MODE_SCREEN;
+ assert_equals(feBlendElement.mode.baseVal, SVGFEBlendElement.SVG_FEBLEND_MODE_SCREEN);
+ assert_equals(feBlendElement.getAttribute('mode'), "screen");
+
+ // Switch to 'darken';
+ feBlendElement.mode.baseVal = SVGFEBlendElement.SVG_FEBLEND_MODE_DARKEN;
+ assert_equals(feBlendElement.mode.baseVal, SVGFEBlendElement.SVG_FEBLEND_MODE_DARKEN);
+ assert_equals(feBlendElement.getAttribute('mode'), "darken");
+
+ // Switch to 'lighten'
+ feBlendElement.mode.baseVal = SVGFEBlendElement.SVG_FEBLEND_MODE_LIGHTEN;
+ assert_equals(feBlendElement.mode.baseVal, SVGFEBlendElement.SVG_FEBLEND_MODE_LIGHTEN);
+ assert_equals(feBlendElement.getAttribute('mode'), "lighten");
+
+ // Try setting invalid values.
+ assert_throws(new TypeError(), function() { feBlendElement.mode.baseVal = 6; });
+ assert_equals(feBlendElement.mode.baseVal, SVGFEBlendElement.SVG_FEBLEND_MODE_LIGHTEN);
+ assert_equals(feBlendElement.getAttribute('mode'), "lighten");
+
+ assert_throws(new TypeError(), function() { feBlendElement.mode.baseVal = -1; });
+ assert_equals(feBlendElement.mode.baseVal, SVGFEBlendElement.SVG_FEBLEND_MODE_LIGHTEN);
+ assert_equals(feBlendElement.getAttribute('mode'), "lighten");
+
+ assert_throws(new TypeError(), function() { feBlendElement.mode.baseVal = 0; });
+ assert_equals(feBlendElement.mode.baseVal, SVGFEBlendElement.SVG_FEBLEND_MODE_LIGHTEN);
+ assert_equals(feBlendElement.getAttribute('mode'), "lighten");
+
+ // Switch to 'normal'.
+ feBlendElement.mode.baseVal = SVGFEBlendElement.SVG_FEBLEND_MODE_NORMAL;
+ assert_equals(feBlendElement.mode.baseVal, SVGFEBlendElement.SVG_FEBLEND_MODE_NORMAL);
+ assert_equals(feBlendElement.getAttribute('mode'), "normal");
+
+ // baseVal access when mode is set to a value not in SVGFEBlendElement.SVG_FEBLEND_MODE_*. .
+ feBlendElement.setAttribute("mode", "color-dodge");
+ assert_equals(feBlendElement.mode.baseVal, SVGFEBlendElement.SVG_FEBLEND_MODE_UNKNOWN);
+ assert_throws(new TypeError(), function() { feBlendElement.mode.baseVal = 13; });
+ assert_equals(feBlendElement.getAttribute('mode'), "color-dodge");
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFEColorMatrixElement.html b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFEColorMatrixElement.html
new file mode 100644
index 00000000000..c86e6594a29
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFEColorMatrixElement.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML>
+<title>Use of SVGAnimatedEnumeration within SVGFEColorMatrixElement</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ // This test checks the use of SVGAnimatedEnumeration within SVGFEColorMatrixElement.
+
+ var feColorMatrixElement = document.createElementNS("http://www.w3.org/2000/svg", "feColorMatrix");
+ feColorMatrixElement.setAttribute("type", "matrix");
+
+ // Check initial 'type' value.
+ assert_true(feColorMatrixElement.type instanceof SVGAnimatedEnumeration);
+ assert_equals(typeof(feColorMatrixElement.type.baseVal), "number");
+ assert_equals(feColorMatrixElement.type.baseVal, SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_MATRIX);
+
+ // Switch to 'saturate'.
+ feColorMatrixElement.type.baseVal = SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_SATURATE;
+ assert_equals(feColorMatrixElement.type.baseVal, SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_SATURATE);
+ assert_equals(feColorMatrixElement.getAttribute('type'), "saturate");
+
+ // Switch to 'hueRotate'.
+ feColorMatrixElement.type.baseVal = SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_HUEROTATE;
+ assert_equals(feColorMatrixElement.type.baseVal, SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_HUEROTATE);
+ assert_equals(feColorMatrixElement.getAttribute('type'), "hueRotate");
+
+ // Switch to 'luminanceToAlpha'.
+ feColorMatrixElement.type.baseVal = SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_LUMINANCETOALPHA;
+ assert_equals(feColorMatrixElement.type.baseVal, SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_LUMINANCETOALPHA);
+ assert_equals(feColorMatrixElement.getAttribute('type'), "luminanceToAlpha");
+
+ // Try setting invalid values.
+ assert_throws(new TypeError(), function() { feColorMatrixElement.type.baseVal = 5; });
+ assert_equals(feColorMatrixElement.type.baseVal, SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_LUMINANCETOALPHA);
+ assert_equals(feColorMatrixElement.getAttribute('type'), "luminanceToAlpha");
+
+ assert_throws(new TypeError(), function() { feColorMatrixElement.type.baseVal = -1; });
+ assert_equals(feColorMatrixElement.type.baseVal, SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_LUMINANCETOALPHA);
+ assert_equals(feColorMatrixElement.getAttribute('type'), "luminanceToAlpha");
+
+ assert_throws(new TypeError(), function() { feColorMatrixElement.type.baseVal = 0; });
+ assert_equals(feColorMatrixElement.type.baseVal, SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_LUMINANCETOALPHA);
+ assert_equals(feColorMatrixElement.getAttribute('type'), "luminanceToAlpha");
+
+ // Switch to 'matrix'.
+ feColorMatrixElement.type.baseVal = SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_MATRIX;
+ assert_equals(feColorMatrixElement.type.baseVal, SVGFEColorMatrixElement.SVG_FECOLORMATRIX_TYPE_MATRIX);
+ assert_equals(feColorMatrixElement.getAttribute('type'), "matrix");
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFECompositeElement.html b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFECompositeElement.html
new file mode 100644
index 00000000000..19714ea73f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFECompositeElement.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML>
+<title>Use of SVGAnimatedEnumeration within SVGFECompositeElement</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ // This test checks the use of SVGAnimatedEnumeration within SVGFECompositeElement.
+
+ var feCompositeElement = document.createElementNS("http://www.w3.org/2000/svg", "feComposite");
+ feCompositeElement.setAttribute("operator", "over");
+
+ // Check initial 'operator' value.
+ assert_true(feCompositeElement.operator instanceof SVGAnimatedEnumeration);
+ assert_equals(typeof(feCompositeElement.operator.baseVal), "number");
+ assert_equals(feCompositeElement.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_OVER);
+
+ // Switch to 'in'.
+ feCompositeElement.operator.baseVal = SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_IN;
+ assert_equals(feCompositeElement.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_IN);
+ assert_equals(feCompositeElement.getAttribute('operator'), "in");
+
+ // Switch to 'out'.
+ feCompositeElement.operator.baseVal = SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_OUT;
+ assert_equals(feCompositeElement.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_OUT);
+ assert_equals(feCompositeElement.getAttribute('operator'), "out");
+
+ // Switch to 'atop'.
+ feCompositeElement.operator.baseVal = SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_ATOP;
+ assert_equals(feCompositeElement.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_ATOP);
+ assert_equals(feCompositeElement.getAttribute('operator'), "atop");
+
+ // Switch to 'xor'
+ feCompositeElement.operator.baseVal = SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_XOR;
+ assert_equals(feCompositeElement.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_XOR);
+ assert_equals(feCompositeElement.getAttribute('operator'), "xor");
+
+ // Switch to 'arithmetic'.
+ feCompositeElement.operator.baseVal = SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_ARITHMETIC;
+ assert_equals(feCompositeElement.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_ARITHMETIC);
+ assert_equals(feCompositeElement.getAttribute('operator'), "arithmetic");
+
+ // Try setting invalid values.
+ assert_throws(new TypeError(), function() { feCompositeElement.operator.baseVal = 7; });
+ assert_equals(feCompositeElement.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_ARITHMETIC);
+ assert_equals(feCompositeElement.getAttribute('operator'), "arithmetic");
+
+ assert_throws(new TypeError(), function() { feCompositeElement.operator.baseVal = -1; });
+ assert_equals(feCompositeElement.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_ARITHMETIC);
+ assert_equals(feCompositeElement.getAttribute('operator'), "arithmetic");
+
+ assert_throws(new TypeError(), function() { feCompositeElement.operator.baseVal = 0; });
+ assert_equals(feCompositeElement.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_ARITHMETIC);
+ assert_equals(feCompositeElement.getAttribute('operator'), "arithmetic");
+
+ // Switch to 'over'.
+ feCompositeElement.operator.baseVal = SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_OVER;
+ assert_equals(feCompositeElement.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_OVER);
+ assert_equals(feCompositeElement.getAttribute('operator'), "over");
+
+ // Switch to 'lighter'.
+ assert_equals(SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_LIGHTER, undefined);
+ feCompositeElement.setAttribute("operator", "lighter");
+ assert_equals(feCompositeElement.operator.baseVal, SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_UNKNOWN);
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFEConvolveMatrixElement.html b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFEConvolveMatrixElement.html
new file mode 100644
index 00000000000..cab47f1bdae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFEConvolveMatrixElement.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<title>Use of SVGAnimatedEnumeration within SVGFEConvolveMatrixElement</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ // This test checks the use of SVGAnimatedEnumeration within SVGFEConvolveMatrixElement.
+
+ var feConvolveMatrixElement = document.createElementNS("http://www.w3.org/2000/svg", "feConvolveMatrix");
+ feConvolveMatrixElement.setAttribute("edgeMode", "duplicate");
+
+ // Check initial 'edgeMode' value.
+ assert_true(feConvolveMatrixElement.edgeMode instanceof SVGAnimatedEnumeration);
+ assert_equals(typeof(feConvolveMatrixElement.edgeMode.baseVal), "number");
+ assert_equals(feConvolveMatrixElement.edgeMode.baseVal, SVGFEConvolveMatrixElement.SVG_EDGEMODE_DUPLICATE);
+
+ // Switch to 'wrap'.
+ feConvolveMatrixElement.edgeMode.baseVal = SVGFEConvolveMatrixElement.SVG_EDGEMODE_WRAP;
+ assert_equals(feConvolveMatrixElement.edgeMode.baseVal, SVGFEConvolveMatrixElement.SVG_EDGEMODE_WRAP);
+ assert_equals(feConvolveMatrixElement.getAttribute('edgeMode'), "wrap");
+
+ // Switch to 'none'.
+ feConvolveMatrixElement.edgeMode.baseVal = SVGFEConvolveMatrixElement.SVG_EDGEMODE_NONE;
+ assert_equals(feConvolveMatrixElement.edgeMode.baseVal, SVGFEConvolveMatrixElement.SVG_EDGEMODE_NONE);
+ assert_equals(feConvolveMatrixElement.getAttribute('edgeMode'), "none");
+
+ // Try setting invalid values.
+ assert_throws(new TypeError(), function() { feConvolveMatrixElement.edgeMode.baseVal = 4; });
+ assert_equals(feConvolveMatrixElement.edgeMode.baseVal, SVGFEConvolveMatrixElement.SVG_EDGEMODE_NONE);
+ assert_equals(feConvolveMatrixElement.getAttribute('edgeMode'), "none");
+
+ assert_throws(new TypeError(), function() { feConvolveMatrixElement.edgeMode.baseVal = -1; });
+ assert_equals(feConvolveMatrixElement.edgeMode.baseVal, SVGFEConvolveMatrixElement.SVG_EDGEMODE_NONE);
+ assert_equals(feConvolveMatrixElement.getAttribute('edgeMode'), "none");
+
+ assert_throws(new TypeError(), function() { feConvolveMatrixElement.edgeMode.baseVal = 0; });
+ assert_equals(feConvolveMatrixElement.edgeMode.baseVal, SVGFEConvolveMatrixElement.SVG_EDGEMODE_NONE);
+ assert_equals(feConvolveMatrixElement.getAttribute('edgeMode'), "none");
+
+ // Switch to 'duplicate'.
+ feConvolveMatrixElement.edgeMode.baseVal = SVGFEConvolveMatrixElement.SVG_EDGEMODE_DUPLICATE;
+ assert_equals(feConvolveMatrixElement.edgeMode.baseVal, SVGFEConvolveMatrixElement.SVG_EDGEMODE_DUPLICATE);
+ assert_equals(feConvolveMatrixElement.getAttribute('edgeMode'), "duplicate");
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFEDisplacementMapElement.html b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFEDisplacementMapElement.html
new file mode 100644
index 00000000000..11fe32d527c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFEDisplacementMapElement.html
@@ -0,0 +1,91 @@
+<!DOCTYPE HTML>
+<title>Use of SVGAnimatedEnumeration within SVGFEDisplacementMapElement</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ // This test checks the use of SVGAnimatedEnumeration within SVGFEDisplacementMapElement.
+
+ var feDisplacementMapElement = document.createElementNS("http://www.w3.org/2000/svg", "feDisplacementMap");
+ feDisplacementMapElement.setAttribute("xChannelSelector", "R");
+ feDisplacementMapElement.setAttribute("yChannelSelector", "R");
+
+ // xChannelSelector
+ // Check initial 'xChannelSelector' value.
+ assert_true(feDisplacementMapElement.xChannelSelector instanceof SVGAnimatedEnumeration);
+ assert_equals(typeof(feDisplacementMapElement.xChannelSelector.baseVal), "number");
+ assert_equals(feDisplacementMapElement.xChannelSelector.baseVal, SVGFEDisplacementMapElement.SVG_CHANNEL_R);
+
+ // Switch to 'G'.
+ feDisplacementMapElement.xChannelSelector.baseVal = SVGFEDisplacementMapElement.SVG_CHANNEL_G;
+ assert_equals(feDisplacementMapElement.xChannelSelector.baseVal, SVGFEDisplacementMapElement.SVG_CHANNEL_G);
+ assert_equals(feDisplacementMapElement.getAttribute('xChannelSelector'), "G");
+
+ // Switch to 'B'.
+ feDisplacementMapElement.xChannelSelector.baseVal = SVGFEDisplacementMapElement.SVG_CHANNEL_B;
+ assert_equals(feDisplacementMapElement.xChannelSelector.baseVal, SVGFEDisplacementMapElement.SVG_CHANNEL_B);
+ assert_equals(feDisplacementMapElement.getAttribute('xChannelSelector'), "B");
+
+ // Switch to 'A'.
+ feDisplacementMapElement.xChannelSelector.baseVal = SVGFEDisplacementMapElement.SVG_CHANNEL_A;
+ assert_equals(feDisplacementMapElement.xChannelSelector.baseVal, SVGFEDisplacementMapElement.SVG_CHANNEL_A);
+ assert_equals(feDisplacementMapElement.getAttribute('xChannelSelector'), "A");
+
+ // Try setting invalid values.
+ assert_throws(new TypeError(), function() { feDisplacementMapElement.xChannelSelector.baseVal = 5; });
+ assert_equals(feDisplacementMapElement.xChannelSelector.baseVal, SVGFEDisplacementMapElement.SVG_CHANNEL_A);
+ assert_equals(feDisplacementMapElement.getAttribute('xChannelSelector'), "A");
+
+ assert_throws(new TypeError(), function() { feDisplacementMapElement.xChannelSelector.baseVal = -1; });
+ assert_equals(feDisplacementMapElement.xChannelSelector.baseVal, SVGFEDisplacementMapElement.SVG_CHANNEL_A);
+ assert_equals(feDisplacementMapElement.getAttribute('xChannelSelector'), "A");
+
+ assert_throws(new TypeError(), function() { feDisplacementMapElement.xChannelSelector.baseVal = 0; });
+ assert_equals(feDisplacementMapElement.xChannelSelector.baseVal, SVGFEDisplacementMapElement.SVG_CHANNEL_A);
+ assert_equals(feDisplacementMapElement.getAttribute('xChannelSelector'), "A");
+
+ // Switch to 'R'.
+ feDisplacementMapElement.xChannelSelector.baseVal = SVGFEDisplacementMapElement.SVG_CHANNEL_R;
+ assert_equals(feDisplacementMapElement.xChannelSelector.baseVal, SVGFEDisplacementMapElement.SVG_CHANNEL_R);
+ assert_equals(feDisplacementMapElement.getAttribute('xChannelSelector'), "R");
+
+ // yChannelSelector
+ // Check initial 'yChannelSelector' value.
+ assert_true(feDisplacementMapElement.yChannelSelector instanceof SVGAnimatedEnumeration);
+ assert_equals(typeof(feDisplacementMapElement.yChannelSelector.baseVal), "number");
+ assert_equals(feDisplacementMapElement.yChannelSelector.baseVal, SVGFEDisplacementMapElement.SVG_CHANNEL_R);
+
+ // Switch to 'G'.
+ feDisplacementMapElement.yChannelSelector.baseVal = SVGFEDisplacementMapElement.SVG_CHANNEL_G;
+ assert_equals(feDisplacementMapElement.yChannelSelector.baseVal, SVGFEDisplacementMapElement.SVG_CHANNEL_G);
+ assert_equals(feDisplacementMapElement.getAttribute('yChannelSelector'), "G");
+
+ // Switch to 'B'.
+ feDisplacementMapElement.yChannelSelector.baseVal = SVGFEDisplacementMapElement.SVG_CHANNEL_B;
+ assert_equals(feDisplacementMapElement.yChannelSelector.baseVal, SVGFEDisplacementMapElement.SVG_CHANNEL_B);
+ assert_equals(feDisplacementMapElement.getAttribute('yChannelSelector'), "B");
+
+ // Switch to 'A'.
+ feDisplacementMapElement.yChannelSelector.baseVal = SVGFEDisplacementMapElement.SVG_CHANNEL_A;
+ assert_equals(feDisplacementMapElement.yChannelSelector.baseVal, SVGFEDisplacementMapElement.SVG_CHANNEL_A);
+ assert_equals(feDisplacementMapElement.getAttribute('yChannelSelector'), "A");
+
+ // Try setting invalid values.
+ assert_throws(new TypeError(), function() { feDisplacementMapElement.yChannelSelector.baseVal = 5; });
+ assert_equals(feDisplacementMapElement.yChannelSelector.baseVal, SVGFEDisplacementMapElement.SVG_CHANNEL_A);
+ assert_equals(feDisplacementMapElement.getAttribute('yChannelSelector'), "A");
+
+ assert_throws(new TypeError(), function() { feDisplacementMapElement.yChannelSelector.baseVal = -1; });
+ assert_equals(feDisplacementMapElement.yChannelSelector.baseVal, SVGFEDisplacementMapElement.SVG_CHANNEL_A);
+ assert_equals(feDisplacementMapElement.getAttribute('yChannelSelector'), "A");
+
+ assert_throws(new TypeError(), function() { feDisplacementMapElement.yChannelSelector.baseVal = 0; });
+ assert_equals(feDisplacementMapElement.yChannelSelector.baseVal, SVGFEDisplacementMapElement.SVG_CHANNEL_A);
+ assert_equals(feDisplacementMapElement.getAttribute('yChannelSelector'), "A");
+
+ // Switch to 'R'.
+ feDisplacementMapElement.yChannelSelector.baseVal = SVGFEDisplacementMapElement.SVG_CHANNEL_R;
+ assert_equals(feDisplacementMapElement.yChannelSelector.baseVal, SVGFEDisplacementMapElement.SVG_CHANNEL_R);
+ assert_equals(feDisplacementMapElement.getAttribute('yChannelSelector'), "R");
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFEMorphologyElement.html b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFEMorphologyElement.html
new file mode 100644
index 00000000000..250bc6ce811
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFEMorphologyElement.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Use of SVGAnimatedEnumeration within SVGFEMorphologyElement</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ // This test checks the use of SVGAnimatedEnumeration within SVGFEMorphologyElement.
+
+ var feMorphologyElement = document.createElementNS("http://www.w3.org/2000/svg", "feMorphology");
+ feMorphologyElement.setAttribute("operator", "erode");
+
+ // Check initial 'operator' value.
+ assert_true(feMorphologyElement.operator instanceof SVGAnimatedEnumeration);
+ assert_equals(typeof(feMorphologyElement.operator.baseVal), "number");
+ assert_equals(feMorphologyElement.operator.baseVal, SVGFEMorphologyElement.SVG_MORPHOLOGY_OPERATOR_ERODE);
+
+ // Switch to 'dilate'.
+ feMorphologyElement.operator.baseVal = SVGFEMorphologyElement.SVG_MORPHOLOGY_OPERATOR_DILATE;
+ assert_equals(feMorphologyElement.operator.baseVal, SVGFEMorphologyElement.SVG_MORPHOLOGY_OPERATOR_DILATE);
+ assert_equals(feMorphologyElement.getAttribute('operator'), "dilate");
+
+ // Try setting invalid values.
+ assert_throws(new TypeError(), function() { feMorphologyElement.operator.baseVal = 4; });
+ assert_equals(feMorphologyElement.operator.baseVal, SVGFEMorphologyElement.SVG_MORPHOLOGY_OPERATOR_DILATE);
+ assert_equals(feMorphologyElement.getAttribute('operator'), "dilate");
+
+ assert_throws(new TypeError(), function() { feMorphologyElement.operator.baseVal = -1; });
+ assert_equals(feMorphologyElement.operator.baseVal, SVGFEMorphologyElement.SVG_MORPHOLOGY_OPERATOR_DILATE);
+ assert_equals(feMorphologyElement.getAttribute('operator'), "dilate");
+
+ assert_throws(new TypeError(), function() { feMorphologyElement.operator.baseVal = 0; });
+ assert_equals(feMorphologyElement.operator.baseVal, SVGFEMorphologyElement.SVG_MORPHOLOGY_OPERATOR_DILATE);
+ assert_equals(feMorphologyElement.getAttribute('operator'), "dilate");
+
+ // Switch to 'erode'.
+ feMorphologyElement.operator.baseVal = SVGFEMorphologyElement.SVG_MORPHOLOGY_OPERATOR_ERODE;
+ assert_equals(feMorphologyElement.operator.baseVal, SVGFEMorphologyElement.SVG_MORPHOLOGY_OPERATOR_ERODE);
+ assert_equals(feMorphologyElement.getAttribute('operator'), "erode");
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFETurbulenceElement.html b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFETurbulenceElement.html
new file mode 100644
index 00000000000..06e23346bf6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFETurbulenceElement.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML>
+<title>Use of SVGAnimatedEnumeration within SVGFETurbulenceElement</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ // This test checks the use of SVGAnimatedEnumeration within SVGFETurbulenceElement.
+
+ var feTurbulenceElement = document.createElementNS("http://www.w3.org/2000/svg", "feTurbulence");
+ feTurbulenceElement.setAttribute("type", "fractalNoise");
+ feTurbulenceElement.setAttribute("stitchTiles", "stitch");
+
+ // type
+ // Check initial 'type' value.
+ assert_true(feTurbulenceElement.type instanceof SVGAnimatedEnumeration);
+ assert_equals(typeof(feTurbulenceElement.type.baseVal), "number");
+ assert_equals(feTurbulenceElement.type.baseVal, SVGFETurbulenceElement.SVG_TURBULENCE_TYPE_FRACTALNOISE);
+
+ // Switch to 'turbulence'.
+ feTurbulenceElement.type.baseVal = SVGFETurbulenceElement.SVG_TURBULENCE_TYPE_TURBULENCE;
+ assert_equals(feTurbulenceElement.type.baseVal, SVGFETurbulenceElement.SVG_TURBULENCE_TYPE_TURBULENCE);
+ assert_equals(feTurbulenceElement.getAttribute('type'), "turbulence");
+
+ // Try setting invalid values.
+ assert_throws(new TypeError(), function() { feTurbulenceElement.type.baseVal = 3; });
+ assert_equals(feTurbulenceElement.type.baseVal, SVGFETurbulenceElement.SVG_TURBULENCE_TYPE_TURBULENCE);
+ assert_equals(feTurbulenceElement.getAttribute('type'), "turbulence");
+
+ assert_throws(new TypeError(), function() { feTurbulenceElement.type.baseVal = -1; });
+ assert_equals(feTurbulenceElement.type.baseVal, SVGFETurbulenceElement.SVG_TURBULENCE_TYPE_TURBULENCE);
+ assert_equals(feTurbulenceElement.getAttribute('type'), "turbulence");
+
+ assert_throws(new TypeError(), function() { feTurbulenceElement.type.baseVal = 0; });
+ assert_equals(feTurbulenceElement.type.baseVal, SVGFETurbulenceElement.SVG_TURBULENCE_TYPE_TURBULENCE);
+ assert_equals(feTurbulenceElement.getAttribute('type'), "turbulence");
+
+ // Switch to 'fractalNoise'.
+ feTurbulenceElement.type.baseVal = SVGFETurbulenceElement.SVG_TURBULENCE_TYPE_FRACTALNOISE;
+ assert_equals(feTurbulenceElement.type.baseVal, SVGFETurbulenceElement.SVG_TURBULENCE_TYPE_FRACTALNOISE);
+ assert_equals(feTurbulenceElement.getAttribute('type'), "fractalNoise");
+
+ // stitchTiles
+ // Check initial 'stitchTiles' value.
+ assert_true(feTurbulenceElement.stitchTiles instanceof SVGAnimatedEnumeration);
+ assert_equals(typeof(feTurbulenceElement.stitchTiles.baseVal), "number");
+ assert_equals(feTurbulenceElement.stitchTiles.baseVal, SVGFETurbulenceElement.SVG_STITCHTYPE_STITCH);
+
+ // Switch to 'noStitch'.
+ feTurbulenceElement.stitchTiles.baseVal = SVGFETurbulenceElement.SVG_STITCHTYPE_NOSTITCH;
+ assert_equals(feTurbulenceElement.stitchTiles.baseVal, SVGFETurbulenceElement.SVG_STITCHTYPE_NOSTITCH);
+ assert_equals(feTurbulenceElement.getAttribute('stitchTiles'), "noStitch");
+
+ // Try setting invalid values.
+ assert_throws(new TypeError(), function() { feTurbulenceElement.stitchTiles.baseVal = 3; });
+ assert_equals(feTurbulenceElement.stitchTiles.baseVal, SVGFETurbulenceElement.SVG_STITCHTYPE_NOSTITCH);
+ assert_equals(feTurbulenceElement.getAttribute('stitchTiles'), "noStitch");
+
+ assert_throws(new TypeError(), function() { feTurbulenceElement.stitchTiles.baseVal = -1; });
+ assert_equals(feTurbulenceElement.stitchTiles.baseVal, SVGFETurbulenceElement.SVG_STITCHTYPE_NOSTITCH);
+ assert_equals(feTurbulenceElement.getAttribute('stitchTiles'), "noStitch");
+
+ assert_throws(new TypeError(), function() { feTurbulenceElement.stitchTiles.baseVal = 0; });
+ assert_equals(feTurbulenceElement.stitchTiles.baseVal, SVGFETurbulenceElement.SVG_STITCHTYPE_NOSTITCH);
+ assert_equals(feTurbulenceElement.getAttribute('stitchTiles'), "noStitch");
+
+ // Switch to 'stitch'.
+ feTurbulenceElement.stitchTiles.baseVal = SVGFETurbulenceElement.SVG_STITCHTYPE_STITCH;
+ assert_equals(feTurbulenceElement.stitchTiles.baseVal, SVGFETurbulenceElement.SVG_STITCHTYPE_STITCH);
+ assert_equals(feTurbulenceElement.getAttribute('stitchTiles'), "stitch");
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFilterElement.html b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFilterElement.html
new file mode 100644
index 00000000000..b8a82db15ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGFilterElement.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML>
+<title>Use of SVGAnimatedEnumeration within SVGFilterElement</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ // This test checks the use of SVGAnimatedEnumeration within SVGFilterElement.
+
+ var filterElement = document.createElementNS("http://www.w3.org/2000/svg", "filter");
+ filterElement.setAttribute("filterUnits", "userSpaceOnUse");
+ filterElement.setAttribute("primitiveUnits", "userSpaceOnUse");
+
+ // filterUnits
+ // Check initial 'filterUnits' value.
+ assert_true(filterElement.filterUnits instanceof SVGAnimatedEnumeration);
+ assert_equals(typeof(filterElement.filterUnits.baseVal), "number");
+ assert_equals(filterElement.filterUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+
+ // Switch to 'objectBoundingBox'.
+ filterElement.filterUnits.baseVal = SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
+ assert_equals(filterElement.filterUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(filterElement.getAttribute('filterUnits'), "objectBoundingBox");
+
+ // Try setting invalid values.
+ assert_throws(new TypeError(), function() { filterElement.filterUnits.baseVal = 3; });
+ assert_equals(filterElement.filterUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(filterElement.getAttribute('filterUnits'), "objectBoundingBox");
+
+ assert_throws(new TypeError(), function() { filterElement.filterUnits.baseVal = -1; });
+ assert_equals(filterElement.filterUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(filterElement.getAttribute('filterUnits'), "objectBoundingBox");
+
+ assert_throws(new TypeError(), function() { filterElement.filterUnits.baseVal = 0; });
+ assert_equals(filterElement.filterUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(filterElement.getAttribute('filterUnits'), "objectBoundingBox");
+
+ // Switch to 'userSpaceOnUse'.
+ filterElement.filterUnits.baseVal = SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE;
+ assert_equals(filterElement.filterUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+ assert_equals(filterElement.getAttribute('filterUnits'), "userSpaceOnUse");
+
+ // primitiveUnits
+ // Check initial 'primitiveUnits' value.
+ assert_true(filterElement.primitiveUnits instanceof SVGAnimatedEnumeration);
+ assert_equals(typeof(filterElement.primitiveUnits.baseVal), "number");
+ assert_equals(filterElement.primitiveUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+
+ // Switch to 'objectBoundingBox'.
+ filterElement.primitiveUnits.baseVal = SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
+ assert_equals(filterElement.primitiveUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(filterElement.getAttribute('primitiveUnits'), "objectBoundingBox");
+
+ // Try setting invalid values.
+ assert_throws(new TypeError(), function() { filterElement.primitiveUnits.baseVal = 3; });
+ assert_equals(filterElement.primitiveUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(filterElement.getAttribute('primitiveUnits'), "objectBoundingBox");
+
+ assert_throws(new TypeError(), function() { filterElement.primitiveUnits.baseVal = -1; });
+ assert_equals(filterElement.primitiveUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(filterElement.getAttribute('primitiveUnits'), "objectBoundingBox");
+
+ assert_throws(new TypeError(), function() { filterElement.primitiveUnits.baseVal = 0; });
+ assert_equals(filterElement.primitiveUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(filterElement.getAttribute('primitiveUnits'), "objectBoundingBox");
+
+ // Switch to 'userSpaceOnUse'.
+ filterElement.primitiveUnits.baseVal = SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE;
+ assert_equals(filterElement.primitiveUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+ assert_equals(filterElement.getAttribute('primitiveUnits'), "userSpaceOnUse");
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGGradientElement.html b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGGradientElement.html
new file mode 100644
index 00000000000..fcb3d717b2f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGGradientElement.html
@@ -0,0 +1,76 @@
+<!DOCTYPE HTML>
+<title>Use of SVGAnimatedEnumeration within SVGGradientElement</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ // This test checks the use of SVGAnimatedEnumeration within SVGGradientElement.
+
+ var gradientElement = document.createElementNS("http://www.w3.org/2000/svg", "linearGradient");
+ gradientElement.setAttribute("gradientUnits", "userSpaceOnUse");
+ gradientElement.setAttribute("spreadMethod", "pad");
+
+ // gradientUnits
+ // Check initial 'gradientUnits' value.
+ assert_true(gradientElement.gradientUnits instanceof SVGAnimatedEnumeration);
+ assert_equals(typeof(gradientElement.gradientUnits.baseVal), "number");
+ assert_equals(gradientElement.gradientUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+
+ // Switch to 'objectBoundingBox'.
+ gradientElement.gradientUnits.baseVal = SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
+ assert_equals(gradientElement.gradientUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(gradientElement.getAttribute('gradientUnits'), "objectBoundingBox");
+
+ // Try setting invalid values.
+ assert_throws(new TypeError(), function() { gradientElement.gradientUnits.baseVal = 3; });
+ assert_equals(gradientElement.gradientUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(gradientElement.getAttribute('gradientUnits'), "objectBoundingBox");
+
+ assert_throws(new TypeError(), function() { gradientElement.gradientUnits.baseVal = -1; });
+ assert_equals(gradientElement.gradientUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(gradientElement.getAttribute('gradientUnits'), "objectBoundingBox");
+
+ assert_throws(new TypeError(), function() { gradientElement.gradientUnits.baseVal = 0; });
+ assert_equals(gradientElement.gradientUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(gradientElement.getAttribute('gradientUnits'), "objectBoundingBox");
+
+ // Switch to 'userSpaceOnUse'.
+ gradientElement.gradientUnits.baseVal = SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE;
+ assert_equals(gradientElement.gradientUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+ assert_equals(gradientElement.getAttribute('gradientUnits'), "userSpaceOnUse");
+
+ // spreadMethod
+ // Check initial 'spreadMethod' value.
+ assert_true(gradientElement.spreadMethod instanceof SVGAnimatedEnumeration);
+ assert_equals(typeof(gradientElement.spreadMethod.baseVal), "number");
+ assert_equals(gradientElement.spreadMethod.baseVal, SVGGradientElement.SVG_SPREADMETHOD_PAD);
+
+ // Switch to 'reflect' value.
+ gradientElement.spreadMethod.baseVal = SVGGradientElement.SVG_SPREADMETHOD_REFLECT;
+ assert_equals(gradientElement.spreadMethod.baseVal, SVGGradientElement.SVG_SPREADMETHOD_REFLECT);
+ assert_equals(gradientElement.getAttribute('spreadMethod'), "reflect");
+
+ // Switch to 'repeat' value.
+ gradientElement.spreadMethod.baseVal = SVGGradientElement.SVG_SPREADMETHOD_REPEAT;
+ assert_equals(gradientElement.spreadMethod.baseVal, SVGGradientElement.SVG_SPREADMETHOD_REPEAT);
+ assert_equals(gradientElement.getAttribute('spreadMethod'), "repeat");
+
+ // Try setting invalid values.
+ assert_throws(new TypeError(), function() { gradientElement.spreadMethod.baseVal = 4; });
+ assert_equals(gradientElement.spreadMethod.baseVal, SVGGradientElement.SVG_SPREADMETHOD_REPEAT);
+ assert_equals(gradientElement.getAttribute('spreadMethod'), "repeat");
+
+ assert_throws(new TypeError(), function() { gradientElement.spreadMethod.baseVal = -1; });
+ assert_equals(gradientElement.spreadMethod.baseVal, SVGGradientElement.SVG_SPREADMETHOD_REPEAT);
+ assert_equals(gradientElement.getAttribute('spreadMethod'), "repeat");
+
+ assert_throws(new TypeError(), function() { gradientElement.spreadMethod.baseVal = 0; });
+ assert_equals(gradientElement.spreadMethod.baseVal, SVGGradientElement.SVG_SPREADMETHOD_REPEAT);
+ assert_equals(gradientElement.getAttribute('spreadMethod'), "repeat");
+
+ // Switch to 'pad'.
+ gradientElement.spreadMethod.baseVal = SVGGradientElement.SVG_SPREADMETHOD_PAD;
+ assert_equals(gradientElement.spreadMethod.baseVal, SVGGradientElement.SVG_SPREADMETHOD_PAD);
+ assert_equals(gradientElement.getAttribute('spreadMethod'), "pad");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGMarkerElement.html b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGMarkerElement.html
new file mode 100644
index 00000000000..7ff298a9d06
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGMarkerElement.html
@@ -0,0 +1,113 @@
+<!DOCTYPE HTML>
+<title>Use of SVGAnimatedEnumeration within SVGMarkerElement</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ // This test checks the use of SVGAnimatedEnumeration within SVGMarkerElement.
+
+ var markerElement = document.createElementNS("http://www.w3.org/2000/svg", "marker");
+ markerElement.setAttribute("markerUnits", "userSpaceOnUse");
+ markerElement.setAttribute("orient", "auto");
+
+ var svgElement = document.createElementNS("http://www.w3.org/2000/svg", "svg");
+
+ // markerUnits
+ // Check initial 'markerUnits' value.
+ assert_true(markerElement.markerUnits instanceof SVGAnimatedEnumeration);
+ assert_equals(typeof(markerElement.markerUnits.baseVal), "number");
+ assert_equals(markerElement.markerUnits.baseVal, SVGMarkerElement.SVG_MARKERUNITS_USERSPACEONUSE);
+
+ // Switch to 'strokeWidth'.
+ markerElement.markerUnits.baseVal = SVGMarkerElement.SVG_MARKERUNITS_STROKEWIDTH;
+ assert_equals(markerElement.markerUnits.baseVal, SVGMarkerElement.SVG_MARKERUNITS_STROKEWIDTH);
+ assert_equals(markerElement.getAttribute('markerUnits'), "strokeWidth");
+
+ // Try setting invalid values.
+ assert_throws(new TypeError(), function() { markerElement.markerUnits.baseVal = 3; });
+ assert_equals(markerElement.markerUnits.baseVal, SVGMarkerElement.SVG_MARKERUNITS_STROKEWIDTH);
+ assert_equals(markerElement.getAttribute('markerUnits'), "strokeWidth");
+
+ assert_throws(new TypeError(), function() { markerElement.markerUnits.baseVal = -1; });
+ assert_equals(markerElement.markerUnits.baseVal, SVGMarkerElement.SVG_MARKERUNITS_STROKEWIDTH);
+ assert_equals(markerElement.getAttribute('markerUnits'), "strokeWidth");
+
+ assert_throws(new TypeError(), function() { markerElement.markerUnits.baseVal = 0; });
+ assert_equals(markerElement.markerUnits.baseVal, SVGMarkerElement.SVG_MARKERUNITS_STROKEWIDTH);
+ assert_equals(markerElement.getAttribute('markerUnits'), "strokeWidth");
+
+ // Switch to 'userSpaceOnUse'
+ markerElement.markerUnits.baseVal = SVGMarkerElement.SVG_MARKERUNITS_USERSPACEONUSE;
+ assert_equals(markerElement.markerUnits.baseVal, SVGMarkerElement.SVG_MARKERUNITS_USERSPACEONUSE);
+ assert_equals(markerElement.getAttribute('markerUnits'), "userSpaceOnUse");
+
+ // orientType
+ // Check initial 'orient' value.
+ assert_true(markerElement.orientType instanceof SVGAnimatedEnumeration);
+ assert_equals(typeof(markerElement.orientType.baseVal), "number");
+ assert_equals(markerElement.orientAngle.baseVal.value, 0);
+ assert_equals(markerElement.orientAngle.baseVal.unitType, SVGAngle.SVG_ANGLETYPE_UNSPECIFIED);
+ assert_equals(markerElement.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_AUTO);
+
+ // Switch to 'Pi/2 rad' value - via setOrientToAngle().
+ anglePiHalfRad = svgElement.createSVGAngle();
+ anglePiHalfRad.newValueSpecifiedUnits(SVGAngle.SVG_ANGLETYPE_RAD, (Math.PI / 2).toFixed(2));
+ markerElement.setOrientToAngle(anglePiHalfRad);
+ assert_equals(markerElement.orientAngle.baseVal.value.toFixed(1), "90.0");
+ assert_equals(markerElement.orientAngle.baseVal.unitType, SVGAngle.SVG_ANGLETYPE_RAD);
+ assert_equals(markerElement.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(markerElement.getAttribute('orient'), (Math.PI / 2).toFixed(2) + "rad");
+
+ // Switch to 'auto' value - via setOrientToAuto().
+ markerElement.setOrientToAuto();
+ assert_equals(markerElement.orientAngle.baseVal.value, 0);
+ assert_equals(markerElement.orientAngle.baseVal.unitType, SVGAngle.SVG_ANGLETYPE_UNSPECIFIED);
+ assert_equals(markerElement.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_AUTO);
+ assert_equals(markerElement.getAttribute('orient'), "auto");
+
+ // Switch to '20deg' value - via setOrientToAngle().
+ angle20deg = svgElement.createSVGAngle();
+ angle20deg.newValueSpecifiedUnits(SVGAngle.SVG_ANGLETYPE_DEG, 20);
+ markerElement.setOrientToAngle(angle20deg);
+ assert_equals(markerElement.orientAngle.baseVal.value, 20);
+ assert_equals(markerElement.orientAngle.baseVal.unitType, SVGAngle.SVG_ANGLETYPE_DEG);
+ assert_equals(markerElement.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(markerElement.getAttribute('orient'), "20deg");
+
+ // Switch to '10deg' value.
+ markerElement.orientAngle.baseVal.value = 10;
+ assert_equals(markerElement.orientAngle.baseVal.value, 10);
+ assert_equals(markerElement.orientAngle.baseVal.unitType, SVGAngle.SVG_ANGLETYPE_DEG);
+ assert_equals(markerElement.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(markerElement.getAttribute('orient'), "10deg");
+
+ // Switch to 'auto' value - by modifying orientType.
+ markerElement.orientType.baseVal = SVGMarkerElement.SVG_MARKER_ORIENT_AUTO;
+ assert_equals(markerElement.orientAngle.baseVal.value, 0);
+ assert_equals(markerElement.orientAngle.baseVal.unitType, SVGAngle.SVG_ANGLETYPE_UNSPECIFIED);
+ assert_equals(markerElement.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_AUTO);
+ assert_equals(markerElement.getAttribute('orient'), "auto");
+
+ markerElement.setAttribute('orient', '10deg');
+
+ // Try setting invalid values.
+ assert_throws(new TypeError(), function() { markerElement.orientType.baseVal = 3; });
+ assert_equals(markerElement.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(markerElement.getAttribute('orient'), "10deg");
+
+ assert_throws(new TypeError(), function() { markerElement.orientType.baseVal = -1; });
+ assert_equals(markerElement.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(markerElement.getAttribute('orient'), "10deg");
+
+ assert_throws(new TypeError(), function() { markerElement.orientType.baseVal = 0; });
+ assert_equals(markerElement.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+ assert_equals(markerElement.getAttribute('orient'), "10deg");
+
+ // Switch back to 'auto' value.
+ markerElement.orientType.baseVal = SVGMarkerElement.SVG_MARKER_ORIENT_AUTO;
+ assert_equals(markerElement.orientAngle.baseVal.value, 0);
+ assert_equals(markerElement.orientAngle.baseVal.unitType, SVGAngle.SVG_ANGLETYPE_UNSPECIFIED);
+ assert_equals(markerElement.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_AUTO);
+ assert_equals(markerElement.getAttribute('orient'), "auto");
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGMaskElement.html b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGMaskElement.html
new file mode 100644
index 00000000000..e2a75568885
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGMaskElement.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML>
+<title>Use of SVGAnimatedEnumeration within SVGMaskElement</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ // This test checks the use of SVGAnimatedEnumeration within SVGMaskElement.
+
+ var maskElement = document.createElementNS("http://www.w3.org/2000/svg", "mask");
+ maskElement.setAttribute("maskUnits", "userSpaceOnUse");
+ maskElement.setAttribute("maskContentUnits", "userSpaceOnUse");
+
+ // maskUnits
+ // Check initial 'maskUnits' value.
+ assert_true(maskElement.maskUnits instanceof SVGAnimatedEnumeration);
+ assert_equals(typeof(maskElement.maskUnits.baseVal), "number");
+ assert_equals(maskElement.maskUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+
+ // Switch to 'objectBoundingBox'.
+ maskElement.maskUnits.baseVal = SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
+ assert_equals(maskElement.maskUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(maskElement.getAttribute('maskUnits'), "objectBoundingBox");
+
+ // Try setting invalid values.
+ assert_throws(new TypeError(), function() { maskElement.maskUnits.baseVal = 3; });
+ assert_equals(maskElement.maskUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(maskElement.getAttribute('maskUnits'), "objectBoundingBox");
+
+ assert_throws(new TypeError(), function() { maskElement.maskUnits.baseVal = -1; });
+ assert_equals(maskElement.maskUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(maskElement.getAttribute('maskUnits'), "objectBoundingBox");
+
+ assert_throws(new TypeError(), function() { maskElement.maskUnits.baseVal = 0; });
+ assert_equals(maskElement.maskUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(maskElement.getAttribute('maskUnits'), "objectBoundingBox");
+
+ // Switch to 'userSpaceOnUse'.
+ maskElement.maskUnits.baseVal = SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE;
+ assert_equals(maskElement.maskUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+ assert_equals(maskElement.getAttribute('maskUnits'), "userSpaceOnUse");
+
+ // maskContentUnits
+ // Check initial 'maskContentUnits' value.
+ assert_true(maskElement.maskContentUnits instanceof SVGAnimatedEnumeration);
+ assert_equals(typeof(maskElement.maskContentUnits.baseVal), "number");
+ assert_equals(maskElement.maskContentUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+
+ // Switch to 'objectBoundingBox'.
+ maskElement.maskContentUnits.baseVal = SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
+ assert_equals(maskElement.maskContentUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(maskElement.getAttribute('maskContentUnits'), "objectBoundingBox");
+
+ // Try setting invalid values.
+ assert_throws(new TypeError(), function() { maskElement.maskContentUnits.baseVal = 3; });
+ assert_equals(maskElement.maskContentUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(maskElement.getAttribute('maskContentUnits'), "objectBoundingBox");
+
+ assert_throws(new TypeError(), function() { maskElement.maskContentUnits.baseVal = -1; });
+ assert_equals(maskElement.maskContentUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(maskElement.getAttribute('maskContentUnits'), "objectBoundingBox");
+
+ assert_throws(new TypeError(), function() { maskElement.maskContentUnits.baseVal = 0; });
+ assert_equals(maskElement.maskContentUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(maskElement.getAttribute('maskContentUnits'), "objectBoundingBox");
+
+ // Switch to 'userSpaceOnUse'.
+ maskElement.maskContentUnits.baseVal = SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE;
+ assert_equals(maskElement.maskContentUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+ assert_equals(maskElement.getAttribute('maskContentUnits'), "userSpaceOnUse");
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGPatternElement.html b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGPatternElement.html
new file mode 100644
index 00000000000..069336506f2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGPatternElement.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML>
+<title>Use of SVGAnimatedEnumeration within SVGPatternElement</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ // This test checks the use of SVGAnimatedEnumeration within SVGPatternElement.
+
+ var patternElement = document.createElementNS("http://www.w3.org/2000/svg", "pattern");
+ patternElement.setAttribute("patternUnits", "userSpaceOnUse");
+ patternElement.setAttribute("patternContentUnits", "userSpaceOnUse");
+
+ // patternUnits
+ // Check initial 'patternUnits' value.
+ assert_true(patternElement.patternUnits instanceof SVGAnimatedEnumeration);
+ assert_equals(typeof(patternElement.patternUnits.baseVal), "number");
+ assert_equals(patternElement.patternUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+
+ // Switch to 'objectBoundingBox'.
+ patternElement.patternUnits.baseVal = SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
+ assert_equals(patternElement.patternUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(patternElement.getAttribute('patternUnits'), "objectBoundingBox");
+
+ // Try setting invalid values.
+ assert_throws(new TypeError(), function() { patternElement.patternUnits.baseVal = 3; });
+ assert_equals(patternElement.patternUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(patternElement.getAttribute('patternUnits'), "objectBoundingBox");
+
+ assert_throws(new TypeError(), function() { patternElement.patternUnits.baseVal = -1; });
+ assert_equals(patternElement.patternUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(patternElement.getAttribute('patternUnits'), "objectBoundingBox");
+
+ assert_throws(new TypeError(), function() { patternElement.patternUnits.baseVal = 0; });
+ assert_equals(patternElement.patternUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(patternElement.getAttribute('patternUnits'), "objectBoundingBox");
+
+ // Switch to 'userSpaceOnUse'.
+ patternElement.patternUnits.baseVal = SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE;
+ assert_equals(patternElement.patternUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+ assert_equals(patternElement.getAttribute('patternUnits'), "userSpaceOnUse");
+
+ // patternContentUnits
+ // Check initial 'patternContentUnits' value.
+ assert_true(patternElement.patternContentUnits instanceof SVGAnimatedEnumeration);
+ assert_equals(typeof(patternElement.patternContentUnits.baseVal), "number");
+ assert_equals(patternElement.patternContentUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+
+ // Switch to 'objectBoundingBox'.
+ patternElement.patternContentUnits.baseVal = SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
+ assert_equals(patternElement.patternContentUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(patternElement.getAttribute('patternContentUnits'), "objectBoundingBox");
+
+ // Try setting invalid values.
+ assert_throws(new TypeError(), function() { patternElement.patternContentUnits.baseVal = 3; });
+ assert_equals(patternElement.patternContentUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(patternElement.getAttribute('patternContentUnits'), "objectBoundingBox");
+
+ assert_throws(new TypeError(), function() { patternElement.patternContentUnits.baseVal = -1; });
+ assert_equals(patternElement.patternContentUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(patternElement.getAttribute('patternContentUnits'), "objectBoundingBox");
+
+ assert_throws(new TypeError(), function() { patternElement.patternContentUnits.baseVal = 0; });
+ assert_equals(patternElement.patternContentUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(patternElement.getAttribute('patternContentUnits'), "objectBoundingBox");
+
+ // Switch to 'userSpaceOnUse'.
+ patternElement.patternContentUnits.baseVal = SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE;
+ assert_equals(patternElement.patternContentUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+ assert_equals(patternElement.getAttribute('patternContentUnits'), "userSpaceOnUse");
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGTextContentElement.html b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGTextContentElement.html
new file mode 100644
index 00000000000..60e15bda01b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGTextContentElement.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<title>Use of SVGAnimatedEnumeration within SVGTextContentElement</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ // This test checks the use of SVGAnimatedEnumeration within SVGTextContentElement.
+
+ var textContentElement = document.createElementNS("http://www.w3.org/2000/svg", "text");
+ textContentElement.setAttribute("lengthAdjust", "spacing");
+
+ // Check initial 'lengthAdjust' value.
+ assert_true(textContentElement.lengthAdjust instanceof SVGAnimatedEnumeration);
+ assert_equals(typeof(textContentElement.lengthAdjust.baseVal), "number");
+ assert_equals(textContentElement.lengthAdjust.baseVal, SVGTextContentElement.LENGTHADJUST_SPACING);
+
+ // Switch to 'spacingAndGlyphs'.
+ textContentElement.lengthAdjust.baseVal = SVGTextContentElement.LENGTHADJUST_SPACINGANDGLYPHS;
+ assert_equals(textContentElement.lengthAdjust.baseVal, SVGTextContentElement.LENGTHADJUST_SPACINGANDGLYPHS);
+ assert_equals(textContentElement.getAttribute('lengthAdjust'), "spacingAndGlyphs");
+
+ // Try setting invalid values.
+ assert_throws(new TypeError(), function() { textContentElement.lengthAdjust.baseVal = 3; });
+ assert_equals(textContentElement.lengthAdjust.baseVal, SVGTextContentElement.LENGTHADJUST_SPACINGANDGLYPHS);
+ assert_equals(textContentElement.getAttribute('lengthAdjust'), "spacingAndGlyphs");
+
+ assert_throws(new TypeError(), function() { textContentElement.lengthAdjust.baseVal = -1; });
+ assert_equals(textContentElement.lengthAdjust.baseVal, SVGTextContentElement.LENGTHADJUST_SPACINGANDGLYPHS);
+ assert_equals(textContentElement.getAttribute('lengthAdjust'), "spacingAndGlyphs");
+
+ assert_throws(new TypeError(), function() { textContentElement.lengthAdjust.baseVal = 0; });
+ assert_equals(textContentElement.lengthAdjust.baseVal, SVGTextContentElement.LENGTHADJUST_SPACINGANDGLYPHS);
+ assert_equals(textContentElement.getAttribute('lengthAdjust'), "spacingAndGlyphs");
+
+ // Switch to 'spacing'.
+ textContentElement.lengthAdjust.baseVal = SVGTextContentElement.LENGTHADJUST_SPACING;
+ assert_equals(textContentElement.lengthAdjust.baseVal, SVGTextContentElement.LENGTHADJUST_SPACING);
+ assert_equals(textContentElement.getAttribute('lengthAdjust'), "spacing");
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGTextPathElement.html b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGTextPathElement.html
new file mode 100644
index 00000000000..46c136f777f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration-SVGTextPathElement.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML>
+<title>Use of SVGAnimatedEnumeration within SVGTextPathElement</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ // This test checks the use of SVGAnimatedEnumeration within SVGTextPathElement.
+
+ var textPathElement = document.createElementNS("http://www.w3.org/2000/svg", "textPath");
+ textPathElement.setAttribute("method", "align");
+ textPathElement.setAttribute("spacing", "auto");
+
+ // method
+ // Check initial 'method' value.
+ assert_true(textPathElement.method instanceof SVGAnimatedEnumeration);
+ assert_equals(typeof(textPathElement.method.baseVal), "number");
+ assert_equals(textPathElement.method.baseVal, SVGTextPathElement.TEXTPATH_METHODTYPE_ALIGN);
+
+ // Switch to 'stretch'.
+ textPathElement.method.baseVal = SVGTextPathElement.TEXTPATH_METHODTYPE_STRETCH;
+ assert_equals(textPathElement.method.baseVal, SVGTextPathElement.TEXTPATH_METHODTYPE_STRETCH);
+ assert_equals(textPathElement.getAttribute('method'), "stretch");
+
+ // Try setting invalid values.
+ assert_throws(new TypeError(), function() { textPathElement.method.baseVal = 3; });
+ assert_equals(textPathElement.method.baseVal, SVGTextPathElement.TEXTPATH_METHODTYPE_STRETCH);
+ assert_equals(textPathElement.getAttribute('method'), "stretch");
+
+ assert_throws(new TypeError(), function() { textPathElement.method.baseVal = -1; });
+ assert_equals(textPathElement.method.baseVal, SVGTextPathElement.TEXTPATH_METHODTYPE_STRETCH);
+ assert_equals(textPathElement.getAttribute('method'), "stretch");
+
+ assert_throws(new TypeError(), function() { textPathElement.method.baseVal = 0; });
+ assert_equals(textPathElement.method.baseVal, SVGTextPathElement.TEXTPATH_METHODTYPE_STRETCH);
+ assert_equals(textPathElement.getAttribute('method'), "stretch");
+
+ // Switch to 'align'.
+ textPathElement.method.baseVal = SVGTextPathElement.TEXTPATH_METHODTYPE_ALIGN;
+ assert_equals(textPathElement.method.baseVal, SVGTextPathElement.TEXTPATH_METHODTYPE_ALIGN);
+ assert_equals(textPathElement.getAttribute('method'), "align");
+
+ // spacing
+ // Check initial 'spacing' value.
+ assert_true(textPathElement.spacing instanceof SVGAnimatedEnumeration);
+ assert_equals(typeof(textPathElement.spacing.baseVal), "number");
+ assert_equals(textPathElement.spacing.baseVal, SVGTextPathElement.TEXTPATH_SPACINGTYPE_AUTO);
+
+ // Switch to 'exact'.
+ textPathElement.spacing.baseVal = SVGTextPathElement.TEXTPATH_SPACINGTYPE_EXACT;
+ assert_equals(textPathElement.spacing.baseVal, SVGTextPathElement.TEXTPATH_SPACINGTYPE_EXACT);
+ assert_equals(textPathElement.getAttribute('spacing'), "exact");
+
+ // Try setting invalid values.
+ assert_throws(new TypeError(), function() { textPathElement.spacing.baseVal = 3; });
+ assert_equals(textPathElement.spacing.baseVal, SVGTextPathElement.TEXTPATH_SPACINGTYPE_EXACT);
+ assert_equals(textPathElement.getAttribute('spacing'), "exact");
+
+ assert_throws(new TypeError(), function() { textPathElement.spacing.baseVal = -1; });
+ assert_equals(textPathElement.spacing.baseVal, SVGTextPathElement.TEXTPATH_SPACINGTYPE_EXACT);
+ assert_equals(textPathElement.getAttribute('spacing'), "exact");
+
+ assert_throws(new TypeError(), function() { textPathElement.spacing.baseVal = 0; });
+ assert_equals(textPathElement.spacing.baseVal, SVGTextPathElement.TEXTPATH_SPACINGTYPE_EXACT);
+ assert_equals(textPathElement.getAttribute('spacing'), "exact");
+
+ // Switch to 'auto'.
+ textPathElement.spacing.baseVal = SVGTextPathElement.TEXTPATH_SPACINGTYPE_AUTO;
+ assert_equals(textPathElement.spacing.baseVal, SVGTextPathElement.TEXTPATH_SPACINGTYPE_AUTO);
+ assert_equals(textPathElement.getAttribute('spacing'), "auto");
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration.html b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration.html
new file mode 100644
index 00000000000..bac69203311
--- /dev/null
+++ b/tests/wpt/web-platform-tests/svg/types/scripted/SVGAnimatedEnumeration.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<title>SVGAnimatedEnumeration interface - utilizing the clipPathUnits property of SVGClipPathElement</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ // This test checks the SVGAnimatedEnumeration API - utilizing the clipPathUnits property of SVGClipPathElement.
+
+ var clipPathElement = document.createElementNS("http://www.w3.org/2000/svg", "clipPath");
+
+ // Check initial clipPathUnits value.
+ assert_true(clipPathElement.clipPathUnits instanceof SVGAnimatedEnumeration);
+ assert_equals(typeof(clipPathElement.clipPathUnits.baseVal), "number");
+ assert_equals(clipPathElement.clipPathUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+
+ // Check that enumerations are static, caching value in a local variable and modifying it, should have no effect.
+ var enumRef = clipPathElement.clipPathUnits.baseVal;
+ enumRef = SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
+ assert_equals(enumRef, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_equals(clipPathElement.clipPathUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+
+ // Check assigning various valid and invalid values.
+ assert_throws(new TypeError(), function() { clipPathElement.clipPathUnits.baseVal = 3; });
+ assert_equals(clipPathElement.clipPathUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+ assert_throws(new TypeError(), function() { clipPathElement.clipPathUnits.baseVal = -1; });
+ assert_equals(clipPathElement.clipPathUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+
+ // ECMA-262, 9.7, "ToUint16"
+ clipPathElement.clipPathUnits.baseVal = '1';
+ assert_equals(clipPathElement.clipPathUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+
+ // ECMA-262, 9.7, "ToUint16"
+ assert_throws(new TypeError(), function() { clipPathElement.clipPathUnits.baseVal = 'aString'; });
+ assert_equals(clipPathElement.clipPathUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+
+ clipPathElement.clipPathUnits.baseVal = 2;
+ assert_equals(clipPathElement.clipPathUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+ assert_throws(new TypeError(), function() { clipPathElement.clipPathUnits.baseVal = clipPathElement; });
+ assert_equals(clipPathElement.clipPathUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/ci/ci_wpt.sh b/tests/wpt/web-platform-tests/tools/ci/ci_wpt.sh
index 2b634137605..2e572b2a65b 100644
--- a/tests/wpt/web-platform-tests/tools/ci/ci_wpt.sh
+++ b/tests/wpt/web-platform-tests/tools/ci/ci_wpt.sh
@@ -10,7 +10,7 @@ source tools/ci/lib.sh
main() {
git fetch --unshallow https://github.com/w3c/web-platform-tests.git +refs/heads/*:refs/remotes/origin/*
hosts_fixup
- install_chrome unstable
+ install_chrome dev
pip install -U tox codecov
cd tools/wpt
tox
diff --git a/tests/wpt/web-platform-tests/tools/ci/lib.sh b/tests/wpt/web-platform-tests/tools/ci/lib.sh
index e80499a7d0a..db49ec6b449 100644
--- a/tests/wpt/web-platform-tests/tools/ci/lib.sh
+++ b/tests/wpt/web-platform-tests/tools/ci/lib.sh
@@ -23,6 +23,10 @@ hosts_fixup() {
install_chrome() {
channel=$1
+ # The package name for Google Chrome Dev uses "unstable", not "dev".
+ if [[ $channel == "dev" ]]; then
+ channel="unstable"
+ fi
deb_archive=google-chrome-${channel}_current_amd64.deb
wget https://dl.google.com/linux/direct/$deb_archive
diff --git a/tests/wpt/web-platform-tests/tools/lint/lint.py b/tests/wpt/web-platform-tests/tools/lint/lint.py
index 271b9f1441b..3228524353b 100644
--- a/tests/wpt/web-platform-tests/tools/lint/lint.py
+++ b/tests/wpt/web-platform-tests/tools/lint/lint.py
@@ -56,7 +56,7 @@ For example, to make the lint tool ignore all '%s'
errors in the %s file,
you could add the following line to the lint.whitelist file.
-%s:%s"""
+%s: %s"""
def all_filesystem_paths(repo_root):
path_filter = PathFilter(repo_root, extras=[".git/*"])
@@ -108,13 +108,13 @@ def _all_files_equal(paths):
return True
-def check_path_length(repo_root, path, css_mode):
+def check_path_length(repo_root, path):
if len(path) + 1 > 150:
return [("PATH LENGTH", "/%s longer than maximum path length (%d > 150)" % (path, len(path) + 1), path, None)]
return []
-def check_worker_collision(repo_root, path, css_mode):
+def check_worker_collision(repo_root, path):
endings = [(".any.html", ".any.js"),
(".any.worker.html", ".any.js"),
(".worker.html", ".worker.js")]
@@ -127,7 +127,7 @@ def check_worker_collision(repo_root, path, css_mode):
return []
-def check_ahem_copy(repo_root, path, css_mode):
+def check_ahem_copy(repo_root, path):
lpath = path.lower()
if "ahem" in lpath and lpath.endswith(".ttf"):
return [("AHEM COPY", "Don't add extra copies of Ahem, use /fonts/Ahem.ttf", path, None)]
@@ -139,7 +139,7 @@ w3c_tr_re = re.compile(r"https?\:\/\/www\.w3c?\.org\/TR\/([^/?#]+)")
w3c_dev_re = re.compile(r"https?\:\/\/dev\.w3c?\.org\/[^/?#]+\/([^/?#]+)")
-def check_css_globally_unique(repo_root, paths, css_mode):
+def check_css_globally_unique(repo_root, paths):
"""
Checks that CSS filenames are sufficiently unique
@@ -154,7 +154,6 @@ def check_css_globally_unique(repo_root, paths, css_mode):
:param repo_root: the repository root
:param paths: list of all paths
- :param css_mode: whether we're in CSS testsuite mode
:returns: a list of errors found in ``paths``
"""
@@ -166,11 +165,9 @@ def check_css_globally_unique(repo_root, paths, css_mode):
if os.name == "nt":
path = path.replace("\\", "/")
- if not css_mode:
- if not path.startswith("css/"):
- continue
+ if not path.startswith("css/"):
+ continue
- # we're within css or in css_mode after all that
source_file = SourceFile(repo_root, path, "/")
if source_file.name_is_non_test:
# If we're name_is_non_test for a reason apart from support, ignore it.
@@ -332,6 +329,11 @@ class W3CTestOrgRegexp(Regexp):
error = "W3C-TEST.ORG"
description = "External w3c-test.org domain used"
+class WebPlatformTestRegexp(Regexp):
+ pattern = b"web\-platform\.test"
+ error = "WEB-PLATFORM.TEST"
+ description = "Internal web-platform.test domain used"
+
class Webidl2Regexp(Regexp):
pattern = b"webidl2\.js"
error = "WEBIDL2.JS"
@@ -374,6 +376,7 @@ regexps = [item() for item in
CRRegexp,
SetTimeoutRegexp,
W3CTestOrgRegexp,
+ WebPlatformTestRegexp,
Webidl2Regexp,
ConsoleRegexp,
GenerateTestsRegexp,
@@ -381,7 +384,7 @@ regexps = [item() for item in
LayoutTestsRegexp,
SpecialPowersRegexp]]
-def check_regexp_line(repo_root, path, f, css_mode):
+def check_regexp_line(repo_root, path, f):
errors = []
applicable_regexps = [regexp for regexp in regexps if regexp.applies(path)]
@@ -393,12 +396,12 @@ def check_regexp_line(repo_root, path, f, css_mode):
return errors
-def check_parsed(repo_root, path, f, css_mode):
+def check_parsed(repo_root, path, f):
source_file = SourceFile(repo_root, path, "/", contents=f.read())
errors = []
- if css_mode or path.startswith("css/"):
+ if path.startswith("css/"):
if (source_file.type == "support" and
not source_file.name_is_non_test and
not source_file.name_is_reference):
@@ -562,7 +565,7 @@ class OpenModeCheck(ASTCheck):
ast_checkers = [item() for item in [OpenModeCheck]]
-def check_python_ast(repo_root, path, f, css_mode):
+def check_python_ast(repo_root, path, f):
if not path.endswith(".py"):
return []
@@ -582,7 +585,7 @@ broken_js_metadata = re.compile(b"//\s*META:")
broken_python_metadata = re.compile(b"#\s*META:")
-def check_script_metadata(repo_root, path, f, css_mode):
+def check_script_metadata(repo_root, path, f):
if path.endswith((".worker.js", ".any.js")):
meta_re = js_meta_re
broken_metadata = broken_js_metadata
@@ -621,52 +624,49 @@ def check_script_metadata(repo_root, path, f, css_mode):
return errors
-def check_path(repo_root, path, css_mode):
+def check_path(repo_root, path):
"""
Runs lints that check the file path.
:param repo_root: the repository root
:param path: the path of the file within the repository
- :param css_mode: whether we're in CSS testsuite mode
:returns: a list of errors found in ``path``
"""
errors = []
for path_fn in path_lints:
- errors.extend(path_fn(repo_root, path, css_mode))
+ errors.extend(path_fn(repo_root, path))
return errors
-def check_all_paths(repo_root, paths, css_mode):
+def check_all_paths(repo_root, paths):
"""
Runs lints that check all paths globally.
:param repo_root: the repository root
:param paths: a list of all the paths within the repository
- :param css_mode: whether we're in CSS testsuite mode
:returns: a list of errors found in ``f``
"""
errors = []
for paths_fn in all_paths_lints:
- errors.extend(paths_fn(repo_root, paths, css_mode))
+ errors.extend(paths_fn(repo_root, paths))
return errors
-def check_file_contents(repo_root, path, f, css_mode):
+def check_file_contents(repo_root, path, f):
"""
Runs lints that check the file contents.
:param repo_root: the repository root
:param path: the path of the file within the repository
:param f: a file-like object with the file contents
- :param css_mode: whether we're in CSS testsuite mode
:returns: a list of errors found in ``f``
"""
errors = []
for file_fn in file_lints:
- errors.extend(file_fn(repo_root, path, f, css_mode))
+ errors.extend(file_fn(repo_root, path, f))
f.seek(0)
return errors
@@ -773,10 +773,10 @@ def main(**kwargs):
paths = lint_paths(kwargs, repo_root)
- return lint(repo_root, paths, output_format, kwargs.get("css_mode", False))
+ return lint(repo_root, paths, output_format)
-def lint(repo_root, paths, output_format, css_mode):
+def lint(repo_root, paths, output_format):
error_count = defaultdict(int)
last = None
@@ -817,15 +817,15 @@ def lint(repo_root, paths, output_format, css_mode):
paths.remove(path)
continue
- errors = check_path(repo_root, path, css_mode)
+ errors = check_path(repo_root, path)
last = process_errors(errors) or last
if not os.path.isdir(abs_path):
with open(abs_path, 'rb') as f:
- errors = check_file_contents(repo_root, path, f, css_mode)
+ errors = check_file_contents(repo_root, path, f)
last = process_errors(errors) or last
- errors = check_all_paths(repo_root, paths, css_mode)
+ errors = check_all_paths(repo_root, paths)
last = process_errors(errors) or last
if output_format in ("normal", "markdown"):
diff --git a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/a-ref.html b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/a-ref.html
index d00491fd7e5..d00491fd7e5 100644
--- a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/a-ref.html
+++ b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/a-ref.html
diff --git a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/a.html b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/a.html
index 73c5d0bc373..73c5d0bc373 100644
--- a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/a.html
+++ b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/a.html
diff --git a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/match/a-ref.html b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/match/a-ref.html
index d00491fd7e5..d00491fd7e5 100644
--- a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/match/a-ref.html
+++ b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/match/a-ref.html
diff --git a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/match/a.html b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/match/a.html
index 73c5d0bc373..73c5d0bc373 100644
--- a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/match/a.html
+++ b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/match/a.html
diff --git a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/match/support/a.html b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/match/support/a.html
index d00491fd7e5..d00491fd7e5 100644
--- a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/match/support/a.html
+++ b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/match/support/a.html
diff --git a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/match/support/tools/a.html b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/match/support/tools/a.html
index 0cfbf08886f..0cfbf08886f 100644
--- a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/match/support/tools/a.html
+++ b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/match/support/tools/a.html
diff --git a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/match/tools/a.html b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/match/tools/a.html
index d00491fd7e5..d00491fd7e5 100644
--- a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/match/tools/a.html
+++ b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/match/tools/a.html
diff --git a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/not-match/a-ref.html b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/not-match/a-ref.html
index 0cfbf08886f..0cfbf08886f 100644
--- a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/not-match/a-ref.html
+++ b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/not-match/a-ref.html
diff --git a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/not-match/a.html b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/not-match/a.html
index 4b0ce383a25..4b0ce383a25 100644
--- a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/not-match/a.html
+++ b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/not-match/a.html
diff --git a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/not-match/support/a.html b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/not-match/support/a.html
index 0cfbf08886f..0cfbf08886f 100644
--- a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/not-match/support/a.html
+++ b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/not-match/support/a.html
diff --git a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/not-match/tools/a.html b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/not-match/tools/a.html
index 0cfbf08886f..0cfbf08886f 100644
--- a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/not-match/tools/a.html
+++ b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/not-match/tools/a.html
diff --git a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/selectors/a.html b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/selectors/a.html
index 0d63c6bfedd..0d63c6bfedd 100644
--- a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/selectors/a.html
+++ b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/selectors/a.html
diff --git a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/support/a.html b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/support/a.html
index d00491fd7e5..d00491fd7e5 100644
--- a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/support/a.html
+++ b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/support/a.html
diff --git a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/support/tools/a.html b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/support/tools/a.html
index 0cfbf08886f..0cfbf08886f 100644
--- a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/support/tools/a.html
+++ b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/support/tools/a.html
diff --git a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/tools/a.html b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/tools/a.html
index d00491fd7e5..d00491fd7e5 100644
--- a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css-unique/tools/a.html
+++ b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/css-unique/tools/a.html
diff --git a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/work-in-progress/foo/support/a.html b/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/work-in-progress/foo/support/a.html
deleted file mode 100644
index d00491fd7e5..00000000000
--- a/tests/wpt/web-platform-tests/tools/lint/tests/dummy/css/work-in-progress/foo/support/a.html
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/wpt/web-platform-tests/tools/lint/tests/test_file_lints.py b/tests/wpt/web-platform-tests/tools/lint/tests/test_file_lints.py
index 1406de2e980..f4fb221b7a5 100644
--- a/tests/wpt/web-platform-tests/tools/lint/tests/test_file_lints.py
+++ b/tests/wpt/web-platform-tests/tools/lint/tests/test_file_lints.py
@@ -26,7 +26,7 @@ INTERESTING_FILE_NAMES = {
def check_with_files(input_bytes):
return {
- filename: (check_file_contents("", filename, six.BytesIO(input_bytes), False), kind)
+ filename: (check_file_contents("", filename, six.BytesIO(input_bytes)), kind)
for (filename, kind) in
(
(os.path.join("html", filename), kind)
@@ -100,6 +100,19 @@ def test_w3c_test_org():
expected.append(("PARSE-FAILED", "Unable to parse file", filename, None))
assert errors == expected
+def test_web_platform_test():
+ error_map = check_with_files(b"import('http://web-platform.test/')")
+
+ for (filename, (errors, kind)) in error_map.items():
+ check_errors(errors)
+
+ expected = [("WEB-PLATFORM.TEST", "Internal web-platform.test domain used", filename, 1)]
+ if kind == "python":
+ expected.append(("PARSE-FAILED", "Unable to parse file", filename, 1))
+ elif kind == "web-strict":
+ expected.append(("PARSE-FAILED", "Unable to parse file", filename, None))
+ assert errors == expected
+
def test_webidl2_js():
error_map = check_with_files(b"<script src=/resources/webidl2.js>")
@@ -440,7 +453,7 @@ def fifth():
def test_open_mode():
for method in ["open", "file"]:
code = open_mode_code.format(method).encode("utf-8")
- errors = check_file_contents("", "test.py", six.BytesIO(code), False)
+ errors = check_file_contents("", "test.py", six.BytesIO(code))
check_errors(errors)
message = ("File opened without providing an explicit mode (note: " +
@@ -453,15 +466,13 @@ def test_open_mode():
@pytest.mark.parametrize(
- "filename,css_mode,expect_error",
+ "filename,expect_error",
[
- ("foo/bar.html", False, False),
- ("foo/bar.html", True, True),
- ("css/bar.html", False, True),
- ("css/bar.html", True, True),
+ ("foo/bar.html", False),
+ ("css/bar.html", True),
])
-def test_css_support_file(filename, css_mode, expect_error):
- errors = check_file_contents("", filename, six.BytesIO(b""), css_mode)
+def test_css_support_file(filename, expect_error):
+ errors = check_file_contents("", filename, six.BytesIO(b""))
check_errors(errors)
if expect_error:
@@ -475,24 +486,6 @@ def test_css_support_file(filename, css_mode, expect_error):
assert errors == []
-def test_css_missing_file_css_mode():
- code = b"""\
-<html xmlns="http://www.w3.org/1999/xhtml">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-</html>
-"""
- errors = check_file_contents("", "foo/bar.html", six.BytesIO(code), True)
- check_errors(errors)
-
- assert errors == [
- ('MISSING-LINK',
- 'Testcase file must have a link to a spec',
- "foo/bar.html",
- None),
- ]
-
-
def test_css_missing_file_in_css():
code = b"""\
<html xmlns="http://www.w3.org/1999/xhtml">
@@ -500,7 +493,7 @@ def test_css_missing_file_in_css():
<script src="/resources/testharnessreport.js"></script>
</html>
"""
- errors = check_file_contents("", "css/foo/bar.html", six.BytesIO(code), False)
+ errors = check_file_contents("", "css/foo/bar.html", six.BytesIO(code))
check_errors(errors)
assert errors == [
@@ -512,7 +505,7 @@ def test_css_missing_file_in_css():
def test_css_missing_file_manual():
- errors = check_file_contents("", "css/foo/bar-manual.html", six.BytesIO(b""), False)
+ errors = check_file_contents("", "css/foo/bar-manual.html", six.BytesIO(b""))
check_errors(errors)
assert errors == [
@@ -544,7 +537,7 @@ def test_css_missing_file_manual():
(b"""// META: timeout=bar\n""", (1, "UNKNOWN-TIMEOUT-METADATA")),
])
def test_script_metadata(filename, input, error):
- errors = check_file_contents("", filename, six.BytesIO(input), False)
+ errors = check_file_contents("", filename, six.BytesIO(input))
check_errors(errors)
if error is not None:
@@ -583,7 +576,7 @@ def test_script_metadata(filename, input, error):
])
def test_python_metadata(input, error):
filename = "test.py"
- errors = check_file_contents("", filename, six.BytesIO(input), False)
+ errors = check_file_contents("", filename, six.BytesIO(input))
check_errors(errors)
if error is not None:
diff --git a/tests/wpt/web-platform-tests/tools/lint/tests/test_lint.py b/tests/wpt/web-platform-tests/tools/lint/tests/test_lint.py
index 82f432482c9..e3e530f172e 100644
--- a/tests/wpt/web-platform-tests/tools/lint/tests/test_lint.py
+++ b/tests/wpt/web-platform-tests/tools/lint/tests/test_lint.py
@@ -108,7 +108,7 @@ CR AT EOL, INDENT TABS: html/test2.js: 42
def test_lint_no_files(caplog):
- rv = lint(_dummy_repo, [], "normal", False)
+ rv = lint(_dummy_repo, [], "normal")
assert rv == 0
assert caplog.text == ""
@@ -116,7 +116,7 @@ def test_lint_no_files(caplog):
def test_lint_ignored_file(caplog):
with _mock_lint("check_path") as mocked_check_path:
with _mock_lint("check_file_contents") as mocked_check_file_contents:
- rv = lint(_dummy_repo, ["broken_ignored.html"], "normal", False)
+ rv = lint(_dummy_repo, ["broken_ignored.html"], "normal")
assert rv == 0
assert not mocked_check_path.called
assert not mocked_check_file_contents.called
@@ -128,7 +128,7 @@ def test_lint_not_existing_file(caplog):
with _mock_lint("check_file_contents") as mocked_check_file_contents:
# really long path-linted filename
name = "a" * 256 + ".html"
- rv = lint(_dummy_repo, [name], "normal", False)
+ rv = lint(_dummy_repo, [name], "normal")
assert rv == 0
assert not mocked_check_path.called
assert not mocked_check_file_contents.called
@@ -138,7 +138,7 @@ def test_lint_not_existing_file(caplog):
def test_lint_passing(caplog):
with _mock_lint("check_path") as mocked_check_path:
with _mock_lint("check_file_contents") as mocked_check_file_contents:
- rv = lint(_dummy_repo, ["okay.html"], "normal", False)
+ rv = lint(_dummy_repo, ["okay.html"], "normal")
assert rv == 0
assert mocked_check_path.call_count == 1
assert mocked_check_file_contents.call_count == 1
@@ -148,7 +148,7 @@ def test_lint_passing(caplog):
def test_lint_failing(caplog):
with _mock_lint("check_path") as mocked_check_path:
with _mock_lint("check_file_contents") as mocked_check_file_contents:
- rv = lint(_dummy_repo, ["broken.html"], "normal", False)
+ rv = lint(_dummy_repo, ["broken.html"], "normal")
assert rv == 1
assert mocked_check_path.call_count == 1
assert mocked_check_file_contents.call_count == 1
@@ -159,7 +159,7 @@ def test_lint_failing(caplog):
def test_ref_existent_relative(caplog):
with _mock_lint("check_path") as mocked_check_path:
with _mock_lint("check_file_contents") as mocked_check_file_contents:
- rv = lint(_dummy_repo, ["ref/existent_relative.html"], "normal", False)
+ rv = lint(_dummy_repo, ["ref/existent_relative.html"], "normal")
assert rv == 0
assert mocked_check_path.call_count == 1
assert mocked_check_file_contents.call_count == 1
@@ -169,7 +169,7 @@ def test_ref_existent_relative(caplog):
def test_ref_existent_root_relative(caplog):
with _mock_lint("check_path") as mocked_check_path:
with _mock_lint("check_file_contents") as mocked_check_file_contents:
- rv = lint(_dummy_repo, ["ref/existent_root_relative.html"], "normal", False)
+ rv = lint(_dummy_repo, ["ref/existent_root_relative.html"], "normal")
assert rv == 0
assert mocked_check_path.call_count == 1
assert mocked_check_file_contents.call_count == 1
@@ -179,7 +179,7 @@ def test_ref_existent_root_relative(caplog):
def test_ref_non_existent_relative(caplog):
with _mock_lint("check_path") as mocked_check_path:
with _mock_lint("check_file_contents") as mocked_check_file_contents:
- rv = lint(_dummy_repo, ["ref/non_existent_relative.html"], "normal", False)
+ rv = lint(_dummy_repo, ["ref/non_existent_relative.html"], "normal")
assert rv == 1
assert mocked_check_path.call_count == 1
assert mocked_check_file_contents.call_count == 1
@@ -191,7 +191,7 @@ def test_ref_non_existent_relative(caplog):
def test_ref_non_existent_root_relative(caplog):
with _mock_lint("check_path") as mocked_check_path:
with _mock_lint("check_file_contents") as mocked_check_file_contents:
- rv = lint(_dummy_repo, ["ref/non_existent_root_relative.html"], "normal", False)
+ rv = lint(_dummy_repo, ["ref/non_existent_root_relative.html"], "normal")
assert rv == 1
assert mocked_check_path.call_count == 1
assert mocked_check_file_contents.call_count == 1
@@ -204,7 +204,7 @@ def test_ref_non_existent_root_relative(caplog):
def test_ref_absolute_url(caplog):
with _mock_lint("check_path") as mocked_check_path:
with _mock_lint("check_file_contents") as mocked_check_file_contents:
- rv = lint(_dummy_repo, ["ref/absolute.html"], "normal", False)
+ rv = lint(_dummy_repo, ["ref/absolute.html"], "normal")
assert rv == 1
assert mocked_check_path.call_count == 1
assert mocked_check_file_contents.call_count == 1
@@ -216,7 +216,7 @@ def test_ref_absolute_url(caplog):
def test_ref_same_file_empty(caplog):
with _mock_lint("check_path") as mocked_check_path:
with _mock_lint("check_file_contents") as mocked_check_file_contents:
- rv = lint(_dummy_repo, ["ref/same_file_empty.html"], "normal", False)
+ rv = lint(_dummy_repo, ["ref/same_file_empty.html"], "normal")
assert rv == 1
assert mocked_check_path.call_count == 1
assert mocked_check_file_contents.call_count == 1
@@ -227,7 +227,7 @@ def test_ref_same_file_empty(caplog):
def test_ref_same_file_path(caplog):
with _mock_lint("check_path") as mocked_check_path:
with _mock_lint("check_file_contents") as mocked_check_file_contents:
- rv = lint(_dummy_repo, ["ref/same_file_path.html"], "normal", False)
+ rv = lint(_dummy_repo, ["ref/same_file_path.html"], "normal")
assert rv == 1
assert mocked_check_path.call_count == 1
assert mocked_check_file_contents.call_count == 1
@@ -238,7 +238,7 @@ def test_ref_same_file_path(caplog):
def test_lint_passing_and_failing(caplog):
with _mock_lint("check_path") as mocked_check_path:
with _mock_lint("check_file_contents") as mocked_check_file_contents:
- rv = lint(_dummy_repo, ["broken.html", "okay.html"], "normal", False)
+ rv = lint(_dummy_repo, ["broken.html", "okay.html"], "normal")
assert rv == 1
assert mocked_check_path.call_count == 2
assert mocked_check_file_contents.call_count == 2
@@ -250,7 +250,7 @@ def test_lint_passing_and_failing(caplog):
def test_check_css_globally_unique_identical_test(caplog):
with _mock_lint("check_path") as mocked_check_path:
with _mock_lint("check_file_contents") as mocked_check_file_contents:
- rv = lint(_dummy_repo, ["css-unique/match/a.html", "css-unique/a.html"], "normal", True)
+ rv = lint(_dummy_repo, ["css/css-unique/match/a.html", "css/css-unique/a.html"], "normal")
assert rv == 0
assert mocked_check_path.call_count == 2
assert mocked_check_file_contents.call_count == 2
@@ -260,7 +260,7 @@ def test_check_css_globally_unique_identical_test(caplog):
def test_check_css_globally_unique_different_test(caplog):
with _mock_lint("check_path") as mocked_check_path:
with _mock_lint("check_file_contents") as mocked_check_file_contents:
- rv = lint(_dummy_repo, ["css-unique/not-match/a.html", "css-unique/a.html"], "normal", True)
+ rv = lint(_dummy_repo, ["css/css-unique/not-match/a.html", "css/css-unique/a.html"], "normal")
assert rv == 2
assert mocked_check_path.call_count == 2
assert mocked_check_file_contents.call_count == 2
@@ -270,7 +270,7 @@ def test_check_css_globally_unique_different_test(caplog):
def test_check_css_globally_unique_different_spec_test(caplog):
with _mock_lint("check_path") as mocked_check_path:
with _mock_lint("check_file_contents") as mocked_check_file_contents:
- rv = lint(_dummy_repo, ["css-unique/selectors/a.html", "css-unique/a.html"], "normal", True)
+ rv = lint(_dummy_repo, ["css/css-unique/selectors/a.html", "css/css-unique/a.html"], "normal")
assert rv == 0
assert mocked_check_path.call_count == 2
assert mocked_check_file_contents.call_count == 2
@@ -280,7 +280,7 @@ def test_check_css_globally_unique_different_spec_test(caplog):
def test_check_css_globally_unique_support_ignored(caplog):
with _mock_lint("check_path") as mocked_check_path:
with _mock_lint("check_file_contents") as mocked_check_file_contents:
- rv = lint(_dummy_repo, ["css-unique/support/a.html", "css-unique/support/tools/a.html"], "normal", True)
+ rv = lint(_dummy_repo, ["css/css-unique/support/a.html", "css/css-unique/support/tools/a.html"], "normal")
assert rv == 0
assert mocked_check_path.call_count == 2
assert mocked_check_file_contents.call_count == 2
@@ -290,7 +290,7 @@ def test_check_css_globally_unique_support_ignored(caplog):
def test_check_css_globally_unique_support_identical(caplog):
with _mock_lint("check_path") as mocked_check_path:
with _mock_lint("check_file_contents") as mocked_check_file_contents:
- rv = lint(_dummy_repo, ["css-unique/support/a.html", "css-unique/match/support/a.html"], "normal", True)
+ rv = lint(_dummy_repo, ["css/css-unique/support/a.html", "css/css-unique/match/support/a.html"], "normal")
assert rv == 0
assert mocked_check_path.call_count == 2
assert mocked_check_file_contents.call_count == 2
@@ -300,7 +300,7 @@ def test_check_css_globally_unique_support_identical(caplog):
def test_check_css_globally_unique_support_different(caplog):
with _mock_lint("check_path") as mocked_check_path:
with _mock_lint("check_file_contents") as mocked_check_file_contents:
- rv = lint(_dummy_repo, ["css-unique/not-match/support/a.html", "css-unique/support/a.html"], "normal", True)
+ rv = lint(_dummy_repo, ["css/css-unique/not-match/support/a.html", "css/css-unique/support/a.html"], "normal")
assert rv == 2
assert mocked_check_path.call_count == 2
assert mocked_check_file_contents.call_count == 2
@@ -310,7 +310,7 @@ def test_check_css_globally_unique_support_different(caplog):
def test_check_css_globally_unique_test_support(caplog):
with _mock_lint("check_path") as mocked_check_path:
with _mock_lint("check_file_contents") as mocked_check_file_contents:
- rv = lint(_dummy_repo, ["css-unique/support/a.html", "css-unique/a.html"], "normal", True)
+ rv = lint(_dummy_repo, ["css/css-unique/support/a.html", "css/css-unique/a.html"], "normal")
assert rv == 0
assert mocked_check_path.call_count == 2
assert mocked_check_file_contents.call_count == 2
@@ -320,7 +320,7 @@ def test_check_css_globally_unique_test_support(caplog):
def test_check_css_globally_unique_ref_identical(caplog):
with _mock_lint("check_path") as mocked_check_path:
with _mock_lint("check_file_contents") as mocked_check_file_contents:
- rv = lint(_dummy_repo, ["css-unique/a-ref.html", "css-unique/match/a-ref.html"], "normal", True)
+ rv = lint(_dummy_repo, ["css/css-unique/a-ref.html", "css/css-unique/match/a-ref.html"], "normal")
assert rv == 0
assert mocked_check_path.call_count == 2
assert mocked_check_file_contents.call_count == 2
@@ -330,7 +330,7 @@ def test_check_css_globally_unique_ref_identical(caplog):
def test_check_css_globally_unique_ref_different(caplog):
with _mock_lint("check_path") as mocked_check_path:
with _mock_lint("check_file_contents") as mocked_check_file_contents:
- rv = lint(_dummy_repo, ["css-unique/not-match/a-ref.html", "css-unique/a-ref.html"], "normal", True)
+ rv = lint(_dummy_repo, ["css/css-unique/not-match/a-ref.html", "css/css-unique/a-ref.html"], "normal")
assert rv == 2
assert mocked_check_path.call_count == 2
assert mocked_check_file_contents.call_count == 2
@@ -340,7 +340,7 @@ def test_check_css_globally_unique_ref_different(caplog):
def test_check_css_globally_unique_test_ref(caplog):
with _mock_lint("check_path") as mocked_check_path:
with _mock_lint("check_file_contents") as mocked_check_file_contents:
- rv = lint(_dummy_repo, ["css-unique/a-ref.html", "css-unique/a.html"], "normal", True)
+ rv = lint(_dummy_repo, ["css/css-unique/a-ref.html", "css/css-unique/a.html"], "normal")
assert rv == 0
assert mocked_check_path.call_count == 2
assert mocked_check_file_contents.call_count == 2
@@ -350,7 +350,7 @@ def test_check_css_globally_unique_test_ref(caplog):
def test_check_css_globally_unique_ignored(caplog):
with _mock_lint("check_path") as mocked_check_path:
with _mock_lint("check_file_contents") as mocked_check_file_contents:
- rv = lint(_dummy_repo, ["css-unique/tools/a.html", "css-unique/not-match/tools/a.html"], "normal", True)
+ rv = lint(_dummy_repo, ["css/css-unique/tools/a.html", "css/css-unique/not-match/tools/a.html"], "normal")
assert rv == 0
assert mocked_check_path.call_count == 2
assert mocked_check_file_contents.call_count == 2
@@ -360,10 +360,10 @@ def test_check_css_globally_unique_ignored(caplog):
def test_check_css_globally_unique_ignored_dir(caplog):
with _mock_lint("check_path") as mocked_check_path:
with _mock_lint("check_file_contents") as mocked_check_file_contents:
- rv = lint(_dummy_repo, ["css-unique/support/a.html", "css/work-in-progress/foo/support/a.html"], "normal", True)
+ rv = lint(_dummy_repo, ["css/css-unique/support/a.html"], "normal")
assert rv == 0
- assert mocked_check_path.call_count == 2
- assert mocked_check_file_contents.call_count == 2
+ assert mocked_check_path.call_count == 1
+ assert mocked_check_file_contents.call_count == 1
assert caplog.text == ""
@@ -390,7 +390,7 @@ def test_main_with_args():
sys.argv = ['./lint', 'a', 'b', 'c']
with _mock_lint('lint', return_value=True) as m:
lint_mod.main(**vars(create_parser().parse_args()))
- m.assert_called_once_with(repo_root, ['a', 'b', 'c'], "normal", False)
+ m.assert_called_once_with(repo_root, ['a', 'b', 'c'], "normal")
finally:
sys.argv = orig_argv
@@ -402,7 +402,7 @@ def test_main_no_args():
with _mock_lint('lint', return_value=True) as m:
with _mock_lint('changed_files', return_value=['foo', 'bar']) as m2:
lint_mod.main(**vars(create_parser().parse_args()))
- m.assert_called_once_with(repo_root, ['foo', 'bar'], "normal", False)
+ m.assert_called_once_with(repo_root, ['foo', 'bar'], "normal")
finally:
sys.argv = orig_argv
@@ -414,6 +414,6 @@ def test_main_all():
with _mock_lint('lint', return_value=True) as m:
with _mock_lint('all_filesystem_paths', return_value=['foo', 'bar']) as m2:
lint_mod.main(**vars(create_parser().parse_args()))
- m.assert_called_once_with(repo_root, ['foo', 'bar'], "normal", False)
+ m.assert_called_once_with(repo_root, ['foo', 'bar'], "normal")
finally:
sys.argv = orig_argv
diff --git a/tests/wpt/web-platform-tests/tools/lint/tests/test_path_lints.py b/tests/wpt/web-platform-tests/tools/lint/tests/test_path_lints.py
index 7af47062b66..b5818289eac 100644
--- a/tests/wpt/web-platform-tests/tools/lint/tests/test_path_lints.py
+++ b/tests/wpt/web-platform-tests/tools/lint/tests/test_path_lints.py
@@ -11,7 +11,7 @@ def test_allowed_path_length():
for idx in range(5):
filename = basename + idx * "a"
- errors = check_path("/foo/", filename, False)
+ errors = check_path("/foo/", filename)
check_errors(errors)
assert errors == []
@@ -23,7 +23,7 @@ def test_forbidden_path_length():
filename = basename + idx * "a"
message = "/%s longer than maximum path length (%s > 150)" % (filename, 146 + idx)
- errors = check_path("/foo/", filename, False)
+ errors = check_path("/foo/", filename)
check_errors(errors)
assert errors == [("PATH LENGTH", message, filename, None)]
@@ -36,6 +36,6 @@ def test_forbidden_path_endings(path_ending, generated):
message = ("path ends with %s which collides with generated tests from %s files" %
(path_ending, generated))
- errors = check_path("/foo/", path, False)
+ errors = check_path("/foo/", path)
check_errors(errors)
assert errors == [("WORKER COLLISION", message, path, None)]
diff --git a/tests/wpt/web-platform-tests/tools/localpaths.py b/tests/wpt/web-platform-tests/tools/localpaths.py
index 9d59cf815c6..c522efd4326 100644
--- a/tests/wpt/web-platform-tests/tools/localpaths.py
+++ b/tests/wpt/web-platform-tests/tools/localpaths.py
@@ -9,7 +9,10 @@ sys.path.insert(0, os.path.join(here, "six"))
sys.path.insert(0, os.path.join(here, "html5lib"))
sys.path.insert(0, os.path.join(here, "wptserve"))
sys.path.insert(0, os.path.join(here, "pywebsocket", "src"))
-sys.path.insert(0, os.path.join(here, "py"))
-sys.path.insert(0, os.path.join(here, "pytest"))
+sys.path.insert(0, os.path.join(here, "third_party", "attrs", "src"))
+sys.path.insert(0, os.path.join(here, "third_party", "funcsigs"))
+sys.path.insert(0, os.path.join(here, "third_party", "pluggy"))
+sys.path.insert(0, os.path.join(here, "third_party", "py"))
+sys.path.insert(0, os.path.join(here, "third_party", "pytest"))
sys.path.insert(0, os.path.join(here, "webdriver"))
sys.path.insert(0, os.path.join(here, "wptrunner"))
diff --git a/tests/wpt/web-platform-tests/tools/manifest/download.py b/tests/wpt/web-platform-tests/tools/manifest/download.py
index 42998a2a2db..611ada0ecd3 100644
--- a/tests/wpt/web-platform-tests/tools/manifest/download.py
+++ b/tests/wpt/web-platform-tests/tools/manifest/download.py
@@ -1,14 +1,17 @@
+from __future__ import absolute_import
+
import argparse
import gzip
import json
import io
-import log
import os
from datetime import datetime, timedelta
-import urllib2
+from six.moves.urllib.request import urlopen
+
+from .vcs import Git
-from vcs import Git
+from . import log
here = os.path.dirname(__file__)
@@ -37,7 +40,7 @@ def git_commits(repo_root):
def github_url(commits):
try:
- resp = urllib2.urlopen("https://api.github.com/repos/w3c/web-platform-tests/releases")
+ resp = urlopen("https://api.github.com/repos/w3c/web-platform-tests/releases")
except Exception:
return None
@@ -76,7 +79,7 @@ def download_manifest(manifest_path, commits_func, url_func, force=False):
logger.info("Downloading manifest from %s" % url)
try:
- resp = urllib2.urlopen(url)
+ resp = urlopen(url)
except Exception:
logger.warning("Downloading pregenerated manifest failed")
return False
diff --git a/tests/wpt/web-platform-tests/tools/manifest/sourcefile.py b/tests/wpt/web-platform-tests/tools/manifest/sourcefile.py
index 1d0637bdee1..093fc2bd470 100644
--- a/tests/wpt/web-platform-tests/tools/manifest/sourcefile.py
+++ b/tests/wpt/web-platform-tests/tools/manifest/sourcefile.py
@@ -54,8 +54,7 @@ class SourceFile(object):
"xhtml":lambda x:ElementTree.parse(x, XMLParser.XMLParser()),
"svg":lambda x:ElementTree.parse(x, XMLParser.XMLParser())}
- root_dir_non_test = set(["common",
- "work-in-progress"])
+ root_dir_non_test = set(["common"])
dir_non_test = set(["resources",
"support",
@@ -63,8 +62,7 @@ class SourceFile(object):
dir_path_non_test = {("css21", "archive"),
("css", "CSS2", "archive"),
- ("css", "common"),
- ("css", "work-in-progress")}
+ ("css", "common")}
def __init__(self, tests_root, rel_path, url_base, contents=None):
"""Object representing a file in a source tree.
diff --git a/tests/wpt/web-platform-tests/tools/manifest/tests/test_sourcefile.py b/tests/wpt/web-platform-tests/tools/manifest/tests/test_sourcefile.py
index 9c3866715dc..57863bf73c4 100644
--- a/tests/wpt/web-platform-tests/tools/manifest/tests/test_sourcefile.py
+++ b/tests/wpt/web-platform-tests/tools/manifest/tests/test_sourcefile.py
@@ -27,7 +27,6 @@ def items(s):
"common/test.html",
"support/test.html",
"css21/archive/test.html",
- "work-in-progress/test.html",
"conformance-checkers/test.html",
"conformance-checkers/README.md",
"conformance-checkers/html/Makefile",
@@ -38,7 +37,6 @@ def items(s):
"foo/test-support.html",
"css/common/test.html",
"css/CSS2/archive/test.html",
- "css/work-in-progress/test.html",
])
def test_name_is_non_test(rel_path):
s = create(rel_path)
@@ -54,7 +52,6 @@ def test_name_is_non_test(rel_path):
"foo/conformance-checkers/test.html",
"foo/_certs/test.html",
"foo/css21/archive/test.html",
- "foo/work-in-progress/test.html",
"foo/CSS2/archive/test.html",
"css/css21/archive/test.html",
])
diff --git a/tests/wpt/web-platform-tests/tools/py/.hgtags b/tests/wpt/web-platform-tests/tools/py/.hgtags
deleted file mode 100644
index d45ebb5a237..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/.hgtags
+++ /dev/null
@@ -1,67 +0,0 @@
-52c6d9e78777a5a34e813123997dfc614a1a4767 1.0.0b3
-1c7aaa8c61f3b0945921a9acc7beb184201aed4b 1.0.0b4
-1c7aaa8c61f3b0945921a9acc7beb184201aed4b 1.0.0b4
-0000000000000000000000000000000000000000 1.0.0b4
-0000000000000000000000000000000000000000 1.0.0b4
-8cd6eb91eba313b012d6e568f37d844dc0751f2e 1.0.0b4
-8cd6eb91eba313b012d6e568f37d844dc0751f2e 1.0.0b4
-0000000000000000000000000000000000000000 1.0.0b4
-2cc0507f117ffe721dff7ee026648cfce00ec92f 1.0.0b6
-86f1e1b6e49bf5882a809f11edd1dbb08162cdad 1.0.0b8
-86f1e1b6e49bf5882a809f11edd1dbb08162cdad 1.0.0b8
-c63f35c266cbb26dad6b87b5e115d65685adf448 1.0.0b8
-c63f35c266cbb26dad6b87b5e115d65685adf448 1.0.0b8
-0eaa0fdf2ba0163cf534dc2eff4ba2e5fc66c261 1.0.0b8
-e2a60653cb490aeed81bbbd83c070b99401c211c 1.0.0b9
-5ea0cdf7854c3d4278d36eda94a2b68483a0e211 1.0.0
-5ea0cdf7854c3d4278d36eda94a2b68483a0e211 1.0.0
-7acde360d94b6a2690ce3d03ff39301da84c0a2b 1.0.0
-6bd221981ac99103002c1cb94fede400d23a96a1 1.0.1
-4816e8b80602a3fd3a0a120333ad85fbe7d8bab4 1.0.2
-60c44bdbf093285dc69d5462d4dbb4acad325ca6 1.1.0
-319187fcda66714c5eb1353492babeec3d3c826f 1.1.1
-4fc5212f7626a56b9eb6437b5c673f56dd7eb942 1.2.0
-c143a8c8840a1c68570890c8ac6165bbf92fd3c6 1.2.1
-eafd3c256e8732dfb0a4d49d051b5b4339858926 1.3.0
-d5eacf390af74553227122b85e20345d47b2f9e6 1.3.1
-d5eacf390af74553227122b85e20345d47b2f9e6 1.3.1
-8b8e7c25a13cf863f01b2dd955978285ae9daf6a 1.3.1
-3bff44b188a7ec1af328d977b9d39b6757bb38df 1.3.2
-c59d3fa8681a5b5966b8375b16fccd64a3a8dbeb 1.3.3
-79ef6377705184c55633d456832eea318fedcf61 1.3.4
-79ef6377705184c55633d456832eea318fedcf61 1.3.4
-90fffd35373e9f125af233f78b19416f0938d841 1.3.4
-5346ab41b059c95a48cbe1e8a7bae96ce6e0da27 1.4.0
-1f3125cba7976538952be268f107c1d0c36c5ce8 1.4.1
-04ab22db4ff737cf31e91d75a0f5d7077f324167 1.4.2
-9950bf9d684a984d511795013421c89c5cf88bef 1.4.3
-d9951e3bdbc765e73835ae13012f6a074d13d8bf 1.4.4
-b827dd156a36753e32c7f3f15ce82d6fe9e356c8 1.4.6
-f15726f9e5a67cc6221c499affa4840e9d591763 1.4.7
-abfabd07a1d328f13c730e8a50d80d2e470afd3b 1.4.9
-7f37ee0aff9be4b839d6759cfee336f60e8393a4 1.4.10
-fe4593263efa10ea7ba014db6e3379e0b82368a2 1.4.11
-f07af25a26786e4825b5170e17ad693245cb3426 1.4.12
-d3730d84ba7eda92fd3469a3f63fd6d8cb22c975 1.4.13
-12c1ae8e7c5345721e9ec9f8e27b1e36c07f74dc 1.4.14
-12c1ae8e7c5345721e9ec9f8e27b1e36c07f74dc 1.4.14
-0000000000000000000000000000000000000000 1.4.14
-0000000000000000000000000000000000000000 1.4.14
-1497e2efd0f8c73a0e3d529debf0c489e4cd6cab 1.4.14
-e065014c1ce8ad110a381e9baaaa5d647ba7ac6b 1.4.15
-e9e5b38f53dc35b35aa1f9ee9a9be9bbd2d2c3b1 1.4.16
-c603503945f52b78522d96a423605cbc953236d3 1.4.17
-c59201105a29801cc858eb9160b7a19791b91a35 1.4.18
-284cc172e294d48edc840012e1451c32c3963d92 1.4.19
-a3e0626aa0c5aecf271367dc77e476ab216ea3c8 1.4.20
-5e48016c4a3af8e7358a1267d33d021e71765bed 1.4.21
-01ae2cfcc61c4fcb3aa5031349adb5b467c31018 1.4.23
-5ffd982f4dff60b588f309cd9bdc61036547282a 1.4.24
-dc9ffbcaf1f7d72e96be3f68c11deebb7e7193c5 1.4.25
-6de1a44bf75de7af4fcae947c235e9072bbdbb9a 1.4.26
-7d650ba2657890a2253c8c4a83f170febebd90fa 1.4.27
-7d650ba2657890a2253c8c4a83f170febebd90fa 1.4.27
-1810003dec63dd1b506a23849861fffa5bc3ba13 1.4.27
-ba08706f08ddea1b77a426f00dfe2bdc244345e8 1.4.28
-4e8054ada63f3327bcf759ae7cd36c7c8652bc9b 1.4.29
-366ab346610c6de8aaa7617e24011794b40236c6 1.4.30
diff --git a/tests/wpt/web-platform-tests/tools/py/CHANGELOG b/tests/wpt/web-platform-tests/tools/py/CHANGELOG
deleted file mode 100644
index 712fc4c5389..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/CHANGELOG
+++ /dev/null
@@ -1,1089 +0,0 @@
-1.4.31
-==================================================
-
-- fix local().copy(dest, mode=True) to also work
- with unicode.
-
-- pass better error message with svn EEXIST paths
-
-1.4.30
-==================================================
-
-- fix issue68 an assert with a multiline list comprehension
- was not reported correctly. Thanks Henrik Heibuerger.
-
-
-1.4.29
-==================================================
-
-- fix issue55: revert a change to the statement finding algorithm
- which is used by pytest for generating tracebacks.
- Thanks Daniel Hahler for initial analysis.
-
-- fix pytest issue254 for when traceback rendering can't
- find valid source code. Thanks Ionel Cristian Maries.
-
-
-1.4.28
-==================================================
-
-- fix issue64 -- dirpath regression when "abs=True" is passed.
- Thanks Gilles Dartiguelongue.
-
-1.4.27
-==================================================
-
-- fix issue59: point to new repo site
-
-- allow a new ensuresyspath="append" mode for py.path.local.pyimport()
- so that a neccessary import path is appended instead of prepended to
- sys.path
-
-- strike undocumented, untested argument to py.path.local.pypkgpath
-
-- speed up py.path.local.dirpath by a factor of 10
-
-1.4.26
-==================================================
-
-- avoid calling normpath twice in py.path.local
-
-- py.builtin._reraise properly reraises under Python3 now.
-
-- fix issue53 - remove module index, thanks jenisys.
-
-- allow posix path separators when "fnmatch" is called.
- Thanks Christian Long for the complete PR.
-
-1.4.25
-==================================================
-
-- fix issue52: vaguely fix py25 compat of py.path.local (it's not
- officially supported), also fix docs
-
-- fix pytest issue 589: when checking if we have a recursion error
- check for the specific "maximum recursion depth" text of the exception.
-
-1.4.24
-==================================================
-
-- Fix retrieving source when an else: line has an other statement on
- the same line.
-
-- add localpath read_text/write_text/read_bytes/write_bytes methods
- as shortcuts and clearer bytes/text interfaces for read/write.
- Adapted from a PR from Paul Moore.
-
-
-1.4.23
-==================================================
-
-- use newer apipkg version which makes attribute access on
- alias modules resolve to None rather than an ImportError.
- This helps with code that uses inspect.getframeinfo()
- on py34 which causes a complete walk on sys.modules
- thus triggering the alias module to resolve and blowing
- up with ImportError. The negative side is that something
- like "py.test.X" will now result in None instead of "importerror: pytest"
- if pytest is not installed. But you shouldn't import "py.test"
- anyway anymore.
-
-- adapt one svn test to only check for any exception instead
- of specific ones because different svn versions cause different
- errors and we don't care.
-
-
-1.4.22
-==================================================
-
-- refactor class-level registry on ForkedFunc child start/finish
- event to become instance based (i.e. passed into the constructor)
-
-1.4.21
-==================================================
-
-- ForkedFunc now has class-level register_on_start/on_exit()
- methods to allow adding information in the boxed process.
- Thanks Marc Schlaich.
-
-- ForkedFunc in the child opens in "auto-flush" mode for
- stdout/stderr so that when a subprocess dies you can see
- its output even if it didn't flush itself.
-
-- refactor traceback generation in light of pytest issue 364
- (shortening tracebacks). you can now set a new traceback style
- on a per-entry basis such that a caller can force entries to be
- isplayed as short or long entries.
-
-- win32: py.path.local.sysfind(name) will preferrably return files with
- extensions so that if "X" and "X.bat" or "X.exe" is on the PATH,
- one of the latter two will be returned.
-
-1.4.20
-==================================================
-
-- ignore unicode decode errors in xmlescape. Thanks Anatoly Bubenkoff.
-
-- on python2 modify traceback.format_exception_only to match python3
- behaviour, namely trying to print unicode for Exception instances
-
-- use a safer way for serializing exception reports (helps to fix
- pytest issue413)
-
-Changes between 1.4.18 and 1.4.19
-==================================================
-
-- merge in apipkg fixes
-
-- some micro-optimizations in py/_code/code.py for speeding
- up pytest runs. Thanks Alex Gaynor for initiative.
-
-- check PY_COLORS=1 or PY_COLORS=0 to force coloring/not-coloring
- for py.io.TerminalWriter() independently from capabilities
- of the output file. Thanks Marc Abramowitz for the PR.
-
-- some fixes to unicode handling in assertion handling.
- Thanks for the PR to Floris Bruynooghe. (This helps
- to fix pytest issue 319).
-
-- depend on setuptools presence, remove distribute_setup
-
-Changes between 1.4.17 and 1.4.18
-==================================================
-
-- introduce path.ensure_dir() as a synonym for ensure(..., dir=1)
-
-- some unicode/python3 related fixes wrt to path manipulations
- (if you start passing unicode particular in py2 you might
- still get problems, though)
-
-Changes between 1.4.16 and 1.4.17
-==================================================
-
-- make py.io.TerminalWriter() prefer colorama if it is available
- and avoid empty lines when separator-lines are printed by
- being defensive and reducing the working terminalwidth by 1
-
-- introduce optional "expanduser" argument to py.path.local
- to that local("~", expanduser=True) gives the home
- directory of "user".
-
-Changes between 1.4.15 and 1.4.16
-==================================================
-
-- fix issue35 - define __gt__ ordering between a local path
- and strings
-
-- fix issue36 - make chdir() work even if os.getcwd() fails.
-
-- add path.exists/isdir/isfile/islink shortcuts
-
-- introduce local path.as_cwd() context manager.
-
-- introduce p.write(ensure=1) and p.open(ensure=1)
- where ensure triggers creation of neccessary parent
- dirs.
-
-
-Changes between 1.4.14 and 1.4.15
-==================================================
-
-- majorly speed up some common calling patterns with
- LocalPath.listdir()/join/check/stat functions considerably.
-
-- fix an edge case with fnmatch where a glob style pattern appeared
- in an absolute path.
-
-Changes between 1.4.13 and 1.4.14
-==================================================
-
-- fix dupfile to work with files that don't
- carry a mode. Thanks Jason R. Coombs.
-
-Changes between 1.4.12 and 1.4.13
-==================================================
-
-- fix getting statementrange/compiling a file ending
- in a comment line without newline (on python2.5)
-- for local paths you can pass "mode=True" to a copy()
- in order to copy permission bits (underlying mechanism
- is using shutil.copymode)
-- add paths arguments to py.path.local.sysfind to restrict
- search to the diretories in the path.
-- add isdir/isfile/islink to path.stat() objects allowing to perform
- multiple checks without calling out multiple times
-- drop py.path.local.__new__ in favour of a simpler __init__
-- iniconfig: allow "name:value" settings in config files, no space after
- "name" required
-- fix issue 27 - NameError in unlikely untested case of saferepr
-
-
-Changes between 1.4.11 and 1.4.12
-==================================================
-
-- fix python2.4 support - for pre-AST interpreters re-introduce
- old way to find statements in exceptions (closes pytest issue 209)
-- add tox.ini to distribution
-- fix issue23 - print *,** args information in tracebacks,
- thanks Manuel Jacob
-
-
-Changes between 1.4.10 and 1.4.11
-==================================================
-
-- use _ast to determine statement ranges when printing tracebacks -
- avoiding multi-second delays on some large test modules
-- fix an internal test to not use class-denoted pytest_funcarg__
-- fix a doc link to bug tracker
-- try to make terminal.write() printing more robust against
- unicodeencode/decode problems, amend according test
-- introduce py.builtin.text and py.builtin.bytes
- to point to respective str/unicode (py2) and bytes/str (py3) types
-- fix error handling on win32/py33 for ENODIR
-
-Changes between 1.4.9 and 1.4.10
-==================================================
-
-- terminalwriter: default to encode to UTF8 if no encoding is defined
- on the output stream
-- issue22: improve heuristic for finding the statementrange in exceptions
-
-Changes between 1.4.8 and 1.4.9
-==================================================
-
-- fix bug of path.visit() which would not recognize glob-style patterns
- for the "rec" recursion argument
-- changed iniconfig parsing to better conform, now the chars ";"
- and "#" only mark a comment at the stripped start of a line
-- include recent apipkg-1.2
-- change internal terminalwriter.line/reline logic to more nicely
- support file spinners
-
-Changes between 1.4.7 and 1.4.8
-==================================================
-
-- fix issue 13 - correct handling of the tag name object in xmlgen
-- fix issue 14 - support raw attribute values in xmlgen
-- fix windows terminalwriter printing/re-line problem
-- update distribute_setup.py to 0.6.27
-
-Changes between 1.4.6 and 1.4.7
-==================================================
-
-- fix issue11 - own test failure with python3.3 / Thanks Benjamin Peterson
-- help fix pytest issue 102
-
-Changes between 1.4.5 and 1.4.6
-==================================================
-
-- help to fix pytest issue99: unify output of
- ExceptionInfo.getrepr(style="native") with ...(style="long")
-- fix issue7: source.getstatementrange() now raises proper error
- if no valid statement can be found
-- fix issue8: fix code and tests of svnurl/svnwc to work on subversion 1.7 -
- note that path.status(updates=1) will not properly work svn-17's status
- --xml output is broken.
-- make source.getstatementrange() more resilent about non-python code frames
- (as seen from jnja2)
-- make trackeback recursion detection more resilent
- about the eval magic of a decorator library
-- iniconfig: add support for ; as comment starter
-- properly handle lists in xmlgen on python3
-- normalize py.code.getfslineno(obj) to always return a (string, int) tuple
- defaulting to ("", -1) respectively if no source code can be found for obj.
-
-Changes between 1.4.4 and 1.4.5
-==================================================
-
-- improve some unicode handling in terminalwriter and capturing
- (used by pytest)
-
-Changes between 1.4.3 and 1.4.4
-==================================================
-
-- a few fixes and assertion related refinements for pytest-2.1
-- guard py.code.Code and getfslineno against bogus input
- and make py.code.Code objects for object instance
- by looking up their __call__ function.
-- make exception presentation robust against invalid current cwd
-
-Changes between 1.4.2 and 1.4.3
-==================================================
-
-- fix terminal coloring issue for skipped tests (thanks Amaury)
-- fix issue4 - large calls to ansi_print (thanks Amaury)
-
-Changes between 1.4.1 and 1.4.2
-==================================================
-
-- fix (pytest) issue23 - tmpdir argument now works on Python3.2 and WindowsXP
- (which apparently starts to offer os.symlink now)
-
-- better error message for syntax errors from compiled code
-
-- small fix to better deal with (un-)colored terminal output on windows
-
-Changes between 1.4.0 and 1.4.1
-==================================================
-
-- fix issue1 - py.error.* classes to be pickleable
-
-- fix issue2 - on windows32 use PATHEXT as the list of potential
- extensions to find find binaries with py.path.local.sysfind(commandname)
-
-- fix (pytest-) issue10 and refine assertion reinterpretation
- to avoid breaking if the __nonzero__ of an object fails
-
-- fix (pytest-) issue17 where python3 does not like "import *"
- leading to misrepresentation of import-errors in test modules
-
-- fix py.error.* attribute pypy access issue
-
-- allow path.samefile(arg) to succeed when arg is a relative filename
-
-- fix (pytest-) issue20 path.samefile(relpath) works as expected now
-
-- fix (pytest-) issue8 len(long_list) now shows the lenght of the list
-
-Changes between 1.3.4 and 1.4.0
-==================================================
-
-- py.test was moved to a separate "pytest" package. What remains is
- a stub hook which will proxy ``import py.test`` to ``pytest``.
-- all command line tools ("py.cleanup/lookup/countloc/..." moved
- to "pycmd" package)
-- removed the old and deprecated "py.magic" namespace
-- use apipkg-1.1 and make py.apipkg.initpkg|ApiModule available
-- add py.iniconfig module for brain-dead easy ini-config file parsing
-- introduce py.builtin.any()
-- path objects have a .dirname attribute now (equivalent to
- os.path.dirname(path))
-- path.visit() accepts breadthfirst (bf) and sort options
-- remove deprecated py.compat namespace
-
-Changes between 1.3.3 and 1.3.4
-==================================================
-
-- fix issue111: improve install documentation for windows
-- fix issue119: fix custom collectability of __init__.py as a module
-- fix issue116: --doctestmodules work with __init__.py files as well
-- fix issue115: unify internal exception passthrough/catching/GeneratorExit
-- fix issue118: new --tb=native for presenting cpython-standard exceptions
-
-Changes between 1.3.2 and 1.3.3
-==================================================
-
-- fix issue113: assertion representation problem with triple-quoted strings
- (and possibly other cases)
-- make conftest loading detect that a conftest file with the same
- content was already loaded, avoids surprises in nested directory structures
- which can be produced e.g. by Hudson. It probably removes the need to use
- --confcutdir in most cases.
-- fix terminal coloring for win32
- (thanks Michael Foord for reporting)
-- fix weirdness: make terminal width detection work on stdout instead of stdin
- (thanks Armin Ronacher for reporting)
-- remove trailing whitespace in all py/text distribution files
-
-Changes between 1.3.1 and 1.3.2
-==================================================
-
-New features
-++++++++++++++++++
-
-- fix issue103: introduce py.test.raises as context manager, examples::
-
- with py.test.raises(ZeroDivisionError):
- x = 0
- 1 / x
-
- with py.test.raises(RuntimeError) as excinfo:
- call_something()
-
- # you may do extra checks on excinfo.value|type|traceback here
-
- (thanks Ronny Pfannschmidt)
-
-- Funcarg factories can now dynamically apply a marker to a
- test invocation. This is for example useful if a factory
- provides parameters to a test which are expected-to-fail::
-
- def pytest_funcarg__arg(request):
- request.applymarker(py.test.mark.xfail(reason="flaky config"))
- ...
-
- def test_function(arg):
- ...
-
-- improved error reporting on collection and import errors. This makes
- use of a more general mechanism, namely that for custom test item/collect
- nodes ``node.repr_failure(excinfo)`` is now uniformly called so that you can
- override it to return a string error representation of your choice
- which is going to be reported as a (red) string.
-
-- introduce '--junitprefix=STR' option to prepend a prefix
- to all reports in the junitxml file.
-
-Bug fixes / Maintenance
-++++++++++++++++++++++++++
-
-- make tests and the ``pytest_recwarn`` plugin in particular fully compatible
- to Python2.7 (if you use the ``recwarn`` funcarg warnings will be enabled so that
- you can properly check for their existence in a cross-python manner).
-- refine --pdb: ignore xfailed tests, unify its TB-reporting and
- don't display failures again at the end.
-- fix assertion interpretation with the ** operator (thanks Benjamin Peterson)
-- fix issue105 assignment on the same line as a failing assertion (thanks Benjamin Peterson)
-- fix issue104 proper escaping for test names in junitxml plugin (thanks anonymous)
-- fix issue57 -f|--looponfail to work with xpassing tests (thanks Ronny)
-- fix issue92 collectonly reporter and --pastebin (thanks Benjamin Peterson)
-- fix py.code.compile(source) to generate unique filenames
-- fix assertion re-interp problems on PyPy, by defering code
- compilation to the (overridable) Frame.eval class. (thanks Amaury Forgeot)
-- fix py.path.local.pyimport() to work with directories
-- streamline py.path.local.mkdtemp implementation and usage
-- don't print empty lines when showing junitxml-filename
-- add optional boolean ignore_errors parameter to py.path.local.remove
-- fix terminal writing on win32/python2.4
-- py.process.cmdexec() now tries harder to return properly encoded unicode objects
- on all python versions
-- install plain py.test/py.which scripts also for Jython, this helps to
- get canonical script paths in virtualenv situations
-- make path.bestrelpath(path) return ".", note that when calling
- X.bestrelpath the assumption is that X is a directory.
-- make initial conftest discovery ignore "--" prefixed arguments
-- fix resultlog plugin when used in an multicpu/multihost xdist situation
- (thanks Jakub Gustak)
-- perform distributed testing related reporting in the xdist-plugin
- rather than having dist-related code in the generic py.test
- distribution
-- fix homedir detection on Windows
-- ship distribute_setup.py version 0.6.13
-
-Changes between 1.3.0 and 1.3.1
-==================================================
-
-New features
-++++++++++++++++++
-
-- issue91: introduce new py.test.xfail(reason) helper
- to imperatively mark a test as expected to fail. Can
- be used from within setup and test functions. This is
- useful especially for parametrized tests when certain
- configurations are expected-to-fail. In this case the
- declarative approach with the @py.test.mark.xfail cannot
- be used as it would mark all configurations as xfail.
-
-- issue102: introduce new --maxfail=NUM option to stop
- test runs after NUM failures. This is a generalization
- of the '-x' or '--exitfirst' option which is now equivalent
- to '--maxfail=1'. Both '-x' and '--maxfail' will
- now also print a line near the end indicating the Interruption.
-
-- issue89: allow py.test.mark decorators to be used on classes
- (class decorators were introduced with python2.6) and
- also allow to have multiple markers applied at class/module level
- by specifying a list.
-
-- improve and refine letter reporting in the progress bar:
- . pass
- f failed test
- s skipped tests (reminder: use for dependency/platform mismatch only)
- x xfailed test (test that was expected to fail)
- X xpassed test (test that was expected to fail but passed)
-
- You can use any combination of 'fsxX' with the '-r' extended
- reporting option. The xfail/xpass results will show up as
- skipped tests in the junitxml output - which also fixes
- issue99.
-
-- make py.test.cmdline.main() return the exitstatus instead of raising
- SystemExit and also allow it to be called multiple times. This of
- course requires that your application and tests are properly teared
- down and don't have global state.
-
-Fixes / Maintenance
-++++++++++++++++++++++
-
-- improved traceback presentation:
- - improved and unified reporting for "--tb=short" option
- - Errors during test module imports are much shorter, (using --tb=short style)
- - raises shows shorter more relevant tracebacks
- - --fulltrace now more systematically makes traces longer / inhibits cutting
-
-- improve support for raises and other dynamically compiled code by
- manipulating python's linecache.cache instead of the previous
- rather hacky way of creating custom code objects. This makes
- it seemlessly work on Jython and PyPy where it previously didn't.
-
-- fix issue96: make capturing more resilient against Control-C
- interruptions (involved somewhat substantial refactoring
- to the underlying capturing functionality to avoid race
- conditions).
-
-- fix chaining of conditional skipif/xfail decorators - so it works now
- as expected to use multiple @py.test.mark.skipif(condition) decorators,
- including specific reporting which of the conditions lead to skipping.
-
-- fix issue95: late-import zlib so that it's not required
- for general py.test startup.
-
-- fix issue94: make reporting more robust against bogus source code
- (and internally be more careful when presenting unexpected byte sequences)
-
-
-Changes between 1.2.1 and 1.3.0
-==================================================
-
-- deprecate --report option in favour of a new shorter and easier to
- remember -r option: it takes a string argument consisting of any
- combination of 'xfsX' characters. They relate to the single chars
- you see during the dotted progress printing and will print an extra line
- per test at the end of the test run. This extra line indicates the exact
- position or test ID that you directly paste to the py.test cmdline in order
- to re-run a particular test.
-
-- allow external plugins to register new hooks via the new
- pytest_addhooks(pluginmanager) hook. The new release of
- the pytest-xdist plugin for distributed and looponfailing
- testing requires this feature.
-
-- add a new pytest_ignore_collect(path, config) hook to allow projects and
- plugins to define exclusion behaviour for their directory structure -
- for example you may define in a conftest.py this method::
-
- def pytest_ignore_collect(path):
- return path.check(link=1)
-
- to prevent even a collection try of any tests in symlinked dirs.
-
-- new pytest_pycollect_makemodule(path, parent) hook for
- allowing customization of the Module collection object for a
- matching test module.
-
-- extend and refine xfail mechanism:
- ``@py.test.mark.xfail(run=False)`` do not run the decorated test
- ``@py.test.mark.xfail(reason="...")`` prints the reason string in xfail summaries
- specifiying ``--runxfail`` on command line virtually ignores xfail markers
-
-- expose (previously internal) commonly useful methods:
- py.io.get_terminal_with() -> return terminal width
- py.io.ansi_print(...) -> print colored/bold text on linux/win32
- py.io.saferepr(obj) -> return limited representation string
-
-- expose test outcome related exceptions as py.test.skip.Exception,
- py.test.raises.Exception etc., useful mostly for plugins
- doing special outcome interpretation/tweaking
-
-- (issue85) fix junitxml plugin to handle tests with non-ascii output
-
-- fix/refine python3 compatibility (thanks Benjamin Peterson)
-
-- fixes for making the jython/win32 combination work, note however:
- jython2.5.1/win32 does not provide a command line launcher, see
- http://bugs.jython.org/issue1491 . See pylib install documentation
- for how to work around.
-
-- fixes for handling of unicode exception values and unprintable objects
-
-- (issue87) fix unboundlocal error in assertionold code
-
-- (issue86) improve documentation for looponfailing
-
-- refine IO capturing: stdin-redirect pseudo-file now has a NOP close() method
-
-- ship distribute_setup.py version 0.6.10
-
-- added links to the new capturelog and coverage plugins
-
-
-Changes between 1.2.1 and 1.2.0
-=====================================
-
-- refined usage and options for "py.cleanup"::
-
- py.cleanup # remove "*.pyc" and "*$py.class" (jython) files
- py.cleanup -e .swp -e .cache # also remove files with these extensions
- py.cleanup -s # remove "build" and "dist" directory next to setup.py files
- py.cleanup -d # also remove empty directories
- py.cleanup -a # synonym for "-s -d -e 'pip-log.txt'"
- py.cleanup -n # dry run, only show what would be removed
-
-- add a new option "py.test --funcargs" which shows available funcargs
- and their help strings (docstrings on their respective factory function)
- for a given test path
-
-- display a short and concise traceback if a funcarg lookup fails
-
-- early-load "conftest.py" files in non-dot first-level sub directories.
- allows to conveniently keep and access test-related options in a ``test``
- subdir and still add command line options.
-
-- fix issue67: new super-short traceback-printing option: "--tb=line" will print a single line for each failing (python) test indicating its filename, lineno and the failure value
-
-- fix issue78: always call python-level teardown functions even if the
- according setup failed. This includes refinements for calling setup_module/class functions
- which will now only be called once instead of the previous behaviour where they'd be called
- multiple times if they raise an exception (including a Skipped exception). Any exception
- will be re-corded and associated with all tests in the according module/class scope.
-
-- fix issue63: assume <40 columns to be a bogus terminal width, default to 80
-
-- fix pdb debugging to be in the correct frame on raises-related errors
-
-- update apipkg.py to fix an issue where recursive imports might
- unnecessarily break importing
-
-- fix plugin links
-
-Changes between 1.2 and 1.1.1
-=====================================
-
-- moved dist/looponfailing from py.test core into a new
- separately released pytest-xdist plugin.
-
-- new junitxml plugin: --junitxml=path will generate a junit style xml file
- which is processable e.g. by the Hudson CI system.
-
-- new option: --genscript=path will generate a standalone py.test script
- which will not need any libraries installed. thanks to Ralf Schmitt.
-
-- new option: --ignore will prevent specified path from collection.
- Can be specified multiple times.
-
-- new option: --confcutdir=dir will make py.test only consider conftest
- files that are relative to the specified dir.
-
-- new funcarg: "pytestconfig" is the pytest config object for access
- to command line args and can now be easily used in a test.
-
-- install 'py.test' and `py.which` with a ``-$VERSION`` suffix to
- disambiguate between Python3, python2.X, Jython and PyPy installed versions.
-
-- new "pytestconfig" funcarg allows access to test config object
-
-- new "pytest_report_header" hook can return additional lines
- to be displayed at the header of a test run.
-
-- (experimental) allow "py.test path::name1::name2::..." for pointing
- to a test within a test collection directly. This might eventually
- evolve as a full substitute to "-k" specifications.
-
-- streamlined plugin loading: order is now as documented in
- customize.html: setuptools, ENV, commandline, conftest.
- also setuptools entry point names are turned to canonical namees ("pytest_*")
-
-- automatically skip tests that need 'capfd' but have no os.dup
-
-- allow pytest_generate_tests to be defined in classes as well
-
-- deprecate usage of 'disabled' attribute in favour of pytestmark
-- deprecate definition of Directory, Module, Class and Function nodes
- in conftest.py files. Use pytest collect hooks instead.
-
-- collection/item node specific runtest/collect hooks are only called exactly
- on matching conftest.py files, i.e. ones which are exactly below
- the filesystem path of an item
-
-- change: the first pytest_collect_directory hook to return something
- will now prevent further hooks to be called.
-
-- change: figleaf plugin now requires --figleaf to run. Also
- change its long command line options to be a bit shorter (see py.test -h).
-
-- change: pytest doctest plugin is now enabled by default and has a
- new option --doctest-glob to set a pattern for file matches.
-
-- change: remove internal py._* helper vars, only keep py._pydir
-
-- robustify capturing to survive if custom pytest_runtest_setup
- code failed and prevented the capturing setup code from running.
-
-- make py.test.* helpers provided by default plugins visible early -
- works transparently both for pydoc and for interactive sessions
- which will regularly see e.g. py.test.mark and py.test.importorskip.
-
-- simplify internal plugin manager machinery
-- simplify internal collection tree by introducing a RootCollector node
-
-- fix assert reinterpreation that sees a call containing "keyword=..."
-
-- fix issue66: invoke pytest_sessionstart and pytest_sessionfinish
- hooks on slaves during dist-testing, report module/session teardown
- hooks correctly.
-
-- fix issue65: properly handle dist-testing if no
- execnet/py lib installed remotely.
-
-- skip some install-tests if no execnet is available
-
-- fix docs, fix internal bin/ script generation
-
-
-Changes between 1.1.1 and 1.1.0
-=====================================
-
-- introduce automatic plugin registration via 'pytest11'
- entrypoints via setuptools' pkg_resources.iter_entry_points
-
-- fix py.test dist-testing to work with execnet >= 1.0.0b4
-
-- re-introduce py.test.cmdline.main() for better backward compatibility
-
-- svn paths: fix a bug with path.check(versioned=True) for svn paths,
- allow '%' in svn paths, make svnwc.update() default to interactive mode
- like in 1.0.x and add svnwc.update(interactive=False) to inhibit interaction.
-
-- refine distributed tarball to contain test and no pyc files
-
-- try harder to have deprecation warnings for py.compat.* accesses
- report a correct location
-
-Changes between 1.1.0 and 1.0.2
-=====================================
-
-* adjust and improve docs
-
-* remove py.rest tool and internal namespace - it was
- never really advertised and can still be used with
- the old release if needed. If there is interest
- it could be revived into its own tool i guess.
-
-* fix issue48 and issue59: raise an Error if the module
- from an imported test file does not seem to come from
- the filepath - avoids "same-name" confusion that has
- been reported repeatedly
-
-* merged Ronny's nose-compatibility hacks: now
- nose-style setup_module() and setup() functions are
- supported
-
-* introduce generalized py.test.mark function marking
-
-* reshuffle / refine command line grouping
-
-* deprecate parser.addgroup in favour of getgroup which creates option group
-
-* add --report command line option that allows to control showing of skipped/xfailed sections
-
-* generalized skipping: a new way to mark python functions with skipif or xfail
- at function, class and modules level based on platform or sys-module attributes.
-
-* extend py.test.mark decorator to allow for positional args
-
-* introduce and test "py.cleanup -d" to remove empty directories
-
-* fix issue #59 - robustify unittest test collection
-
-* make bpython/help interaction work by adding an __all__ attribute
- to ApiModule, cleanup initpkg
-
-* use MIT license for pylib, add some contributors
-
-* remove py.execnet code and substitute all usages with 'execnet' proper
-
-* fix issue50 - cached_setup now caches more to expectations
- for test functions with multiple arguments.
-
-* merge Jarko's fixes, issue #45 and #46
-
-* add the ability to specify a path for py.lookup to search in
-
-* fix a funcarg cached_setup bug probably only occuring
- in distributed testing and "module" scope with teardown.
-
-* many fixes and changes for making the code base python3 compatible,
- many thanks to Benjamin Peterson for helping with this.
-
-* consolidate builtins implementation to be compatible with >=2.3,
- add helpers to ease keeping 2 and 3k compatible code
-
-* deprecate py.compat.doctest|subprocess|textwrap|optparse
-
-* deprecate py.magic.autopath, remove py/magic directory
-
-* move pytest assertion handling to py/code and a pytest_assertion
- plugin, add "--no-assert" option, deprecate py.magic namespaces
- in favour of (less) py.code ones.
-
-* consolidate and cleanup py/code classes and files
-
-* cleanup py/misc, move tests to bin-for-dist
-
-* introduce delattr/delitem/delenv methods to py.test's monkeypatch funcarg
-
-* consolidate py.log implementation, remove old approach.
-
-* introduce py.io.TextIO and py.io.BytesIO for distinguishing between
- text/unicode and byte-streams (uses underlying standard lib io.*
- if available)
-
-* make py.unittest_convert helper script available which converts "unittest.py"
- style files into the simpler assert/direct-test-classes py.test/nosetests
- style. The script was written by Laura Creighton.
-
-* simplified internal localpath implementation
-
-Changes between 1.0.1 and 1.0.2
-=====================================
-
-* fixing packaging issues, triggered by fedora redhat packaging,
- also added doc, examples and contrib dirs to the tarball.
-
-* added a documentation link to the new django plugin.
-
-Changes between 1.0.0 and 1.0.1
-=====================================
-
-* added a 'pytest_nose' plugin which handles nose.SkipTest,
- nose-style function/method/generator setup/teardown and
- tries to report functions correctly.
-
-* capturing of unicode writes or encoded strings to sys.stdout/err
- work better, also terminalwriting was adapted and somewhat
- unified between windows and linux.
-
-* improved documentation layout and content a lot
-
-* added a "--help-config" option to show conftest.py / ENV-var names for
- all longopt cmdline options, and some special conftest.py variables.
- renamed 'conf_capture' conftest setting to 'option_capture' accordingly.
-
-* fix issue #27: better reporting on non-collectable items given on commandline
- (e.g. pyc files)
-
-* fix issue #33: added --version flag (thanks Benjamin Peterson)
-
-* fix issue #32: adding support for "incomplete" paths to wcpath.status()
-
-* "Test" prefixed classes are *not* collected by default anymore if they
- have an __init__ method
-
-* monkeypatch setenv() now accepts a "prepend" parameter
-
-* improved reporting of collection error tracebacks
-
-* simplified multicall mechanism and plugin architecture,
- renamed some internal methods and argnames
-
-Changes between 1.0.0b9 and 1.0.0
-=====================================
-
-* more terse reporting try to show filesystem path relatively to current dir
-* improve xfail output a bit
-
-Changes between 1.0.0b8 and 1.0.0b9
-=====================================
-
-* cleanly handle and report final teardown of test setup
-
-* fix svn-1.6 compat issue with py.path.svnwc().versioned()
- (thanks Wouter Vanden Hove)
-
-* setup/teardown or collection problems now show as ERRORs
- or with big "E"'s in the progress lines. they are reported
- and counted separately.
-
-* dist-testing: properly handle test items that get locally
- collected but cannot be collected on the remote side - often
- due to platform/dependency reasons
-
-* simplified py.test.mark API - see keyword plugin documentation
-
-* integrate better with logging: capturing now by default captures
- test functions and their immediate setup/teardown in a single stream
-
-* capsys and capfd funcargs now have a readouterr() and a close() method
- (underlyingly py.io.StdCapture/FD objects are used which grew a
- readouterr() method as well to return snapshots of captured out/err)
-
-* make assert-reinterpretation work better with comparisons not
- returning bools (reported with numpy from thanks maciej fijalkowski)
-
-* reworked per-test output capturing into the pytest_iocapture.py plugin
- and thus removed capturing code from config object
-
-* item.repr_failure(excinfo) instead of item.repr_failure(excinfo, outerr)
-
-
-Changes between 1.0.0b7 and 1.0.0b8
-=====================================
-
-* pytest_unittest-plugin is now enabled by default
-
-* introduced pytest_keyboardinterrupt hook and
- refined pytest_sessionfinish hooked, added tests.
-
-* workaround a buggy logging module interaction ("closing already closed
- files"). Thanks to Sridhar Ratnakumar for triggering.
-
-* if plugins use "py.test.importorskip" for importing
- a dependency only a warning will be issued instead
- of exiting the testing process.
-
-* many improvements to docs:
- - refined funcargs doc , use the term "factory" instead of "provider"
- - added a new talk/tutorial doc page
- - better download page
- - better plugin docstrings
- - added new plugins page and automatic doc generation script
-
-* fixed teardown problem related to partially failing funcarg setups
- (thanks MrTopf for reporting), "pytest_runtest_teardown" is now
- always invoked even if the "pytest_runtest_setup" failed.
-
-* tweaked doctest output for docstrings in py modules,
- thanks Radomir.
-
-Changes between 1.0.0b3 and 1.0.0b7
-=============================================
-
-* renamed py.test.xfail back to py.test.mark.xfail to avoid
- two ways to decorate for xfail
-
-* re-added py.test.mark decorator for setting keywords on functions
- (it was actually documented so removing it was not nice)
-
-* remove scope-argument from request.addfinalizer() because
- request.cached_setup has the scope arg. TOOWTDI.
-
-* perform setup finalization before reporting failures
-
-* apply modified patches from Andreas Kloeckner to allow
- test functions to have no func_code (#22) and to make
- "-k" and function keywords work (#20)
-
-* apply patch from Daniel Peolzleithner (issue #23)
-
-* resolve issue #18, multiprocessing.Manager() and
- redirection clash
-
-* make __name__ == "__channelexec__" for remote_exec code
-
-Changes between 1.0.0b1 and 1.0.0b3
-=============================================
-
-* plugin classes are removed: one now defines
- hooks directly in conftest.py or global pytest_*.py
- files.
-
-* added new pytest_namespace(config) hook that allows
- to inject helpers directly to the py.test.* namespace.
-
-* documented and refined many hooks
-
-* added new style of generative tests via
- pytest_generate_tests hook that integrates
- well with function arguments.
-
-
-Changes between 0.9.2 and 1.0.0b1
-=============================================
-
-* introduced new "funcarg" setup method,
- see doc/test/funcarg.txt
-
-* introduced plugin architecuture and many
- new py.test plugins, see
- doc/test/plugins.txt
-
-* teardown_method is now guaranteed to get
- called after a test method has run.
-
-* new method: py.test.importorskip(mod,minversion)
- will either import or call py.test.skip()
-
-* completely revised internal py.test architecture
-
-* new py.process.ForkedFunc object allowing to
- fork execution of a function to a sub process
- and getting a result back.
-
-XXX lots of things missing here XXX
-
-Changes between 0.9.1 and 0.9.2
-===============================
-
-* refined installation and metadata, created new setup.py,
- now based on setuptools/ez_setup (thanks to Ralf Schmitt
- for his support).
-
-* improved the way of making py.* scripts available in
- windows environments, they are now added to the
- Scripts directory as ".cmd" files.
-
-* py.path.svnwc.status() now is more complete and
- uses xml output from the 'svn' command if available
- (Guido Wesdorp)
-
-* fix for py.path.svn* to work with svn 1.5
- (Chris Lamb)
-
-* fix path.relto(otherpath) method on windows to
- use normcase for checking if a path is relative.
-
-* py.test's traceback is better parseable from editors
- (follows the filenames:LINENO: MSG convention)
- (thanks to Osmo Salomaa)
-
-* fix to javascript-generation, "py.test --runbrowser"
- should work more reliably now
-
-* removed previously accidentally added
- py.test.broken and py.test.notimplemented helpers.
-
-* there now is a py.__version__ attribute
-
-Changes between 0.9.0 and 0.9.1
-===============================
-
-This is a fairly complete list of changes between 0.9 and 0.9.1, which can
-serve as a reference for developers.
-
-* allowing + signs in py.path.svn urls [39106]
-* fixed support for Failed exceptions without excinfo in py.test [39340]
-* added support for killing processes for Windows (as well as platforms that
- support os.kill) in py.misc.killproc [39655]
-* added setup/teardown for generative tests to py.test [40702]
-* added detection of FAILED TO LOAD MODULE to py.test [40703, 40738, 40739]
-* fixed problem with calling .remove() on wcpaths of non-versioned files in
- py.path [44248]
-* fixed some import and inheritance issues in py.test [41480, 44648, 44655]
-* fail to run greenlet tests when pypy is available, but without stackless
- [45294]
-* small fixes in rsession tests [45295]
-* fixed issue with 2.5 type representations in py.test [45483, 45484]
-* made that internal reporting issues displaying is done atomically in py.test
- [45518]
-* made that non-existing files are igored by the py.lookup script [45519]
-* improved exception name creation in py.test [45535]
-* made that less threads are used in execnet [merge in 45539]
-* removed lock required for atomical reporting issue displaying in py.test
- [45545]
-* removed globals from execnet [45541, 45547]
-* refactored cleanup mechanics, made that setDaemon is set to 1 to make atexit
- get called in 2.5 (py.execnet) [45548]
-* fixed bug in joining threads in py.execnet's servemain [45549]
-* refactored py.test.rsession tests to not rely on exact output format anymore
- [45646]
-* using repr() on test outcome [45647]
-* added 'Reason' classes for py.test.skip() [45648, 45649]
-* killed some unnecessary sanity check in py.test.collect [45655]
-* avoid using os.tmpfile() in py.io.fdcapture because on Windows it's only
- usable by Administrators [45901]
-* added support for locking and non-recursive commits to py.path.svnwc [45994]
-* locking files in py.execnet to prevent CPython from segfaulting [46010]
-* added export() method to py.path.svnurl
-* fixed -d -x in py.test [47277]
-* fixed argument concatenation problem in py.path.svnwc [49423]
-* restore py.test behaviour that it exits with code 1 when there are failures
- [49974]
-* don't fail on html files that don't have an accompanying .txt file [50606]
-* fixed 'utestconvert.py < input' [50645]
-* small fix for code indentation in py.code.source [50755]
-* fix _docgen.py documentation building [51285]
-* improved checks for source representation of code blocks in py.test [51292]
-* added support for passing authentication to py.path.svn* objects [52000,
- 52001]
-* removed sorted() call for py.apigen tests in favour of [].sort() to support
- Python 2.3 [52481]
diff --git a/tests/wpt/web-platform-tests/tools/py/MANIFEST.in b/tests/wpt/web-platform-tests/tools/py/MANIFEST.in
deleted file mode 100644
index 31fb010b487..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/MANIFEST.in
+++ /dev/null
@@ -1,9 +0,0 @@
-include CHANGELOG
-include AUTHORS
-include README.txt
-include setup.py
-include LICENSE
-include conftest.py
-include tox.ini
-graft doc
-graft testing
diff --git a/tests/wpt/web-platform-tests/tools/py/README.txt b/tests/wpt/web-platform-tests/tools/py/README.txt
deleted file mode 100644
index e327e937373..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/README.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-.. image:: https://drone.io/bitbucket.org/pytest-dev/py/status.png
- :target: https://drone.io/bitbucket.org/pytest-dev/py/latest
-.. image:: https://pypip.in/v/py/badge.png
- :target: https://pypi.python.org/pypi/py
-
-The py lib is a Python development support library featuring
-the following tools and modules:
-
-* py.path: uniform local and svn path objects
-* py.apipkg: explicit API control and lazy-importing
-* py.iniconfig: easy parsing of .ini files
-* py.code: dynamic code generation and introspection
-
-NOTE: prior to the 1.4 release this distribution used to
-contain py.test which is now its own package, see http://pytest.org
-
-For questions and more information please visit http://pylib.readthedocs.org
-
-Bugs and issues: http://bitbucket.org/pytest-dev/py/issues/
-
-Authors: Holger Krekel and others, 2004-2015
diff --git a/tests/wpt/web-platform-tests/tools/py/conftest.py b/tests/wpt/web-platform-tests/tools/py/conftest.py
deleted file mode 100644
index 11c2d442504..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/conftest.py
+++ /dev/null
@@ -1,71 +0,0 @@
-import py
-import sys
-
-pytest_plugins = 'doctest pytester'.split()
-
-collect_ignore = ['build', 'doc/_build']
-
-
-import os, py
-pid = os.getpid()
-
-def pytest_addoption(parser):
- group = parser.getgroup("pylib", "py lib testing options")
- group.addoption('--runslowtests',
- action="store_true", dest="runslowtests", default=False,
- help=("run slow tests"))
-
-def pytest_funcarg__sshhost(request):
- val = request.config.getvalue("sshhost")
- if val:
- return val
- py.test.skip("need --sshhost option")
-def pytest_generate_tests(metafunc):
- multi = getattr(metafunc.function, 'multi', None)
- if multi is not None:
- assert len(multi.kwargs) == 1
- for name, l in multi.kwargs.items():
- for val in l:
- metafunc.addcall(funcargs={name: val})
- elif 'anypython' in metafunc.funcargnames:
- for name in ('python2.4', 'python2.5', 'python2.6',
- 'python2.7', 'python3.1', 'pypy-c', 'jython'):
- metafunc.addcall(id=name, param=name)
-
-# XXX copied from execnet's conftest.py - needs to be merged
-winpymap = {
- 'python2.7': r'C:\Python27\python.exe',
- 'python2.6': r'C:\Python26\python.exe',
- 'python2.5': r'C:\Python25\python.exe',
- 'python2.4': r'C:\Python24\python.exe',
- 'python3.1': r'C:\Python31\python.exe',
-}
-
-def getexecutable(name, cache={}):
- try:
- return cache[name]
- except KeyError:
- executable = py.path.local.sysfind(name)
- if executable:
- if name == "jython":
- import subprocess
- popen = subprocess.Popen([str(executable), "--version"],
- universal_newlines=True, stderr=subprocess.PIPE)
- out, err = popen.communicate()
- if not err or "2.5" not in err:
- executable = None
- cache[name] = executable
- return executable
-
-def pytest_funcarg__anypython(request):
- name = request.param
- executable = getexecutable(name)
- if executable is None:
- if sys.platform == "win32":
- executable = winpymap.get(name, None)
- if executable:
- executable = py.path.local(executable)
- if executable.check():
- return executable
- py.test.skip("no %s found" % (name,))
- return executable
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/index.txt b/tests/wpt/web-platform-tests/tools/py/doc/index.txt
deleted file mode 100644
index 7eb5c63905e..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/doc/index.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-.. py documentation master file, created by
- sphinx-quickstart on Thu Oct 21 08:30:10 2010.
- You can adapt this file completely to your liking, but it should at least
- contain the root `toctree` directive.
-
-Welcome to py's documentation!
-=================================
-
-see :ref:`CHANGELOG <changelog>` for latest changes.
-
-.. note::
-
- Since version 1.4, the testing tool "py.test" is part of its own `pytest distribution`_.
-
-.. _`pytest distribution`: http://pytest.org
-
-Contents:
-
-.. toctree::
-
- install
- path
- code
- io
- log
- xml
- misc
-
- :maxdepth: 2
-
-.. toctree::
- :hidden:
-
- announce/release-2.0.0
- changelog
- announce/*
-
-Indices and tables
-==================
-
-* :ref:`genindex`
-* :ref:`search`
-
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/install.txt b/tests/wpt/web-platform-tests/tools/py/doc/install.txt
deleted file mode 100644
index d0e981def45..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/doc/install.txt
+++ /dev/null
@@ -1,88 +0,0 @@
-
-.. _`py`:
-.. _`index page`: http://pypi.python.org/pypi/py/
-
-installation info in a nutshell
-===================================================
-
-**PyPI name**: py_
-
-**Pythons**: CPython 2.6, 2.7, 3.3, 3.4, PyPy-2.3
-
-**Operating systems**: Linux, Windows, OSX, Unix
-
-**Requirements**: setuptools_ or Distribute_
-
-**Installers**: ``easy_install`` and ``pip``
-
-**hg repository**: https://bitbucket.org/hpk42/py
-
-easy install or pip ``py``
------------------------------
-
-Both `Distribute`_ and setuptools_ provide the ``easy_install``
-installation tool with which you can type into a command line window::
-
- easy_install -U py
-
-to install the latest release of the py lib. The ``-U`` switch
-will trigger an upgrade if you already have an older version installed.
-
-.. note::
-
- As of version 1.4 py does not contain py.test anymore - you
- need to install the new `pytest`_ distribution.
-
-.. _pytest: http://pytest.org
-
-Working from version control or a tarball
------------------------------------------------
-
-To follow development or start experiments, checkout the
-complete code and documentation source with mercurial_::
-
- hg clone https://bitbucket.org/hpk42/py
-
-Development takes place on the 'trunk' branch.
-
-You can also go to the python package index and
-download and unpack a TAR file::
-
- http://pypi.python.org/pypi/py/
-
-activating a checkout with setuptools
---------------------------------------------
-
-With a working `Distribute`_ or setuptools_ installation you can type::
-
- python setup.py develop
-
-in order to work inline with the tools and the lib of your checkout.
-
-.. _`no-setuptools`:
-
-.. _`directly use a checkout`:
-
-.. _`setuptools`: http://pypi.python.org/pypi/setuptools
-
-
-Mailing list and issue tracker
---------------------------------------
-
-- `py-dev developers list`_ and `commit mailing list`_.
-
-- #pylib on irc.freenode.net IRC channel for random questions.
-
-- `bitbucket issue tracker`_ use this bitbucket issue tracker to report
- bugs or request features.
-
-.. _`bitbucket issue tracker`: http://bitbucket.org/hpk42/py/issues/
-
-.. _codespeak: http://codespeak.net/
-.. _`py-dev`:
-.. _`development mailing list`:
-.. _`py-dev developers list`: http://codespeak.net/mailman/listinfo/py-dev
-.. _`py-svn`:
-.. _`commit mailing list`: http://codespeak.net/mailman/listinfo/py-svn
-
-.. include:: links.inc
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/misc.txt b/tests/wpt/web-platform-tests/tools/py/doc/misc.txt
deleted file mode 100644
index 8c3c0b3f7a3..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/doc/misc.txt
+++ /dev/null
@@ -1,93 +0,0 @@
-====================================
-Miscellaneous features of the py lib
-====================================
-
-Mapping the standard python library into py
-===========================================
-
-The ``py.std`` object allows lazy access to
-standard library modules. For example, to get to the print-exception
-functionality of the standard library you can write::
-
- py.std.traceback.print_exc()
-
-without having to do anything else than the usual ``import py``
-at the beginning. You can access any other top-level standard
-library module this way. This means that you will only trigger
-imports of modules that are actually needed. Note that no attempt
-is made to import submodules.
-
-Support for interaction with system utilities/binaries
-======================================================
-
-Currently, the py lib offers two ways to interact with
-system executables. ``py.process.cmdexec()`` invokes
-the shell in order to execute a string. The other
-one, ``py.path.local``'s 'sysexec()' method lets you
-directly execute a binary.
-
-Both approaches will raise an exception in case of a return-
-code other than 0 and otherwise return the stdout-output
-of the child process.
-
-The shell based approach
-------------------------
-
-You can execute a command via your system shell
-by doing something like::
-
- out = py.process.cmdexec('ls -v')
-
-However, the ``cmdexec`` approach has a few shortcomings:
-
-- it relies on the underlying system shell
-- it neccessitates shell-escaping for expressing arguments
-- it does not easily allow to "fix" the binary you want to run.
-- it only allows to execute executables from the local
- filesystem
-
-.. _sysexec:
-
-local paths have ``sysexec``
-----------------------------
-
-In order to synchronously execute an executable file you
-can use ``sysexec``::
-
- binsvn.sysexec('ls', 'http://codespeak.net/svn')
-
-where ``binsvn`` is a path that points to the ``svn`` commandline
-binary. Note that this function does not offer any shell-escaping
-so you have to pass in already separated arguments.
-
-finding an executable local path
---------------------------------
-
-Finding an executable is quite different on multiple platforms.
-Currently, the ``PATH`` environment variable based search on
-unix platforms is supported::
-
- py.path.local.sysfind('svn')
-
-which returns the first path whose ``basename`` matches ``svn``.
-In principle, `sysfind` deploys platform specific algorithms
-to perform the search. On Windows, for example, it may look
-at the registry (XXX).
-
-To make the story complete, we allow to pass in a second ``checker``
-argument that is called for each found executable. For example, if
-you have multiple binaries available you may want to select the
-right version::
-
- def mysvn(p):
- """ check that the given svn binary has version 1.1. """
- line = p.execute('--version'').readlines()[0]
- if line.find('version 1.1'):
- return p
- binsvn = py.path.local.sysfind('svn', checker=mysvn)
-
-
-Cross-Python Version compatibility helpers
-=============================================
-
-The ``py.builtin`` namespace provides a number of helpers that help to write python code compatible across Python interpreters, mainly Python2 and Python3. Type ``help(py.builtin)`` on a Python prompt for a the selection of builtins.
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/path.txt b/tests/wpt/web-platform-tests/tools/py/doc/path.txt
deleted file mode 100644
index 837c1d19272..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/doc/path.txt
+++ /dev/null
@@ -1,260 +0,0 @@
-=======
-py.path
-=======
-
-The 'py' lib provides a uniform high-level api to deal with filesystems
-and filesystem-like interfaces: ``py.path``. It aims to offer a central
-object to fs-like object trees (reading from and writing to files, adding
-files/directories, examining the types and structure, etc.), and out-of-the-box
-provides a number of implementations of this API.
-
-py.path.local - local file system path
-===============================================
-
-.. _`local`:
-
-basic interactive example
--------------------------------------
-
-The first and most obvious of the implementations is a wrapper around a local
-filesystem. It's just a bit nicer in usage than the regular Python APIs, and
-of course all the functionality is bundled together rather than spread over a
-number of modules.
-
-Example usage, here we use the ``py.test.ensuretemp()`` function to create
-a ``py.path.local`` object for us (which wraps a directory):
-
-.. sourcecode:: pycon
-
- >>> import py
- >>> temppath = py.test.ensuretemp('py.path_documentation')
- >>> foopath = temppath.join('foo') # get child 'foo' (lazily)
- >>> foopath.check() # check if child 'foo' exists
- False
- >>> foopath.write('bar') # write some data to it
- >>> foopath.check()
- True
- >>> foopath.read()
- 'bar'
- >>> foofile = foopath.open() # return a 'real' file object
- >>> foofile.read(1)
- 'b'
-
-reference documentation
----------------------------------
-
-.. autoclass:: py._path.local.LocalPath
- :members:
- :inherited-members:
-
-``py.path.svnurl`` and ``py.path.svnwc``
-==================================================
-
-Two other ``py.path`` implementations that the py lib provides wrap the
-popular `Subversion`_ revision control system: the first (called 'svnurl')
-by interfacing with a remote server, the second by wrapping a local checkout.
-Both allow you to access relatively advanced features such as metadata and
-versioning, and both in a way more user-friendly manner than existing other
-solutions.
-
-Some example usage of ``py.path.svnurl``:
-
-.. sourcecode:: pycon
-
- .. >>> import py
- .. >>> if not py.test.config.option.urlcheck: raise ValueError('skipchunk')
- >>> url = py.path.svnurl('http://codespeak.net/svn/py')
- >>> info = url.info()
- >>> info.kind
- 'dir'
- >>> firstentry = url.log()[-1]
- >>> import time
- >>> time.strftime('%Y-%m-%d', time.gmtime(firstentry.date))
- '2004-10-02'
-
-Example usage of ``py.path.svnwc``:
-
-.. sourcecode:: pycon
-
- .. >>> if not py.test.config.option.urlcheck: raise ValueError('skipchunk')
- >>> temp = py.test.ensuretemp('py.path_documentation')
- >>> wc = py.path.svnwc(temp.join('svnwc'))
- >>> wc.checkout('http://codespeak.net/svn/py/dist/py/path/local')
- >>> wc.join('local.py').check()
- True
-
-.. _`Subversion`: http://subversion.tigris.org/
-
-svn path related API reference
------------------------------------------
-
-.. autoclass:: py._path.svnwc.SvnWCCommandPath
- :members:
- :inherited-members:
-
-.. autoclass:: py._path.svnurl.SvnCommandPath
- :members:
- :inherited-members:
-
-.. autoclass:: py._path.svnwc.SvnAuth
- :members:
- :inherited-members:
-
-Common vs. specific API, Examples
-========================================
-
-All Path objects support a common set of operations, suitable
-for many use cases and allowing to transparently switch the
-path object within an application (e.g. from "local" to "svnwc").
-The common set includes functions such as `path.read()` to read all data
-from a file, `path.write()` to write data, `path.listdir()` to get a list
-of directory entries, `path.check()` to check if a node exists
-and is of a particular type, `path.join()` to get
-to a (grand)child, `path.visit()` to recursively walk through a node's
-children, etc. Only things that are not common on 'normal' filesystems (yet),
-such as handling metadata (e.g. the Subversion "properties") require
-using specific APIs.
-
-A quick 'cookbook' of small examples that will be useful 'in real life',
-which also presents parts of the 'common' API, and shows some non-common
-methods:
-
-Searching `.txt` files
---------------------------------
-
-Search for a particular string inside all files with a .txt extension in a
-specific directory.
-
-.. sourcecode:: pycon
-
- >>> dirpath = temppath.ensure('testdir', dir=True)
- >>> dirpath.join('textfile1.txt').write('foo bar baz')
- >>> dirpath.join('textfile2.txt').write('frob bar spam eggs')
- >>> subdir = dirpath.ensure('subdir', dir=True)
- >>> subdir.join('textfile1.txt').write('foo baz')
- >>> subdir.join('textfile2.txt').write('spam eggs spam foo bar spam')
- >>> results = []
- >>> for fpath in dirpath.visit('*.txt'):
- ... if 'bar' in fpath.read():
- ... results.append(fpath.basename)
- >>> results.sort()
- >>> results
- ['textfile1.txt', 'textfile2.txt', 'textfile2.txt']
-
-Working with Paths
-----------------------------
-
-This example shows the ``py.path`` features to deal with
-filesystem paths Note that the filesystem is never touched,
-all operations are performed on a string level (so the paths
-don't have to exist, either):
-
-.. sourcecode:: pycon
-
- >>> p1 = py.path.local('/foo/bar')
- >>> p2 = p1.join('baz/qux')
- >>> p2 == py.path.local('/foo/bar/baz/qux')
- True
- >>> sep = py.path.local.sep
- >>> p2.relto(p1).replace(sep, '/') # os-specific path sep in the string
- 'baz/qux'
- >>> p2.bestrelpath(p1).replace(sep, '/')
- '../..'
- >>> p2.join(p2.bestrelpath(p1)) == p1
- True
- >>> p3 = p1 / 'baz/qux' # the / operator allows joining, too
- >>> p2 == p3
- True
- >>> p4 = p1 + ".py"
- >>> p4.basename == "bar.py"
- True
- >>> p4.ext == ".py"
- True
- >>> p4.purebasename == "bar"
- True
-
-This should be possible on every implementation of ``py.path``, so
-regardless of whether the implementation wraps a UNIX filesystem, a Windows
-one, or a database or object tree, these functions should be available (each
-with their own notion of path seperators and dealing with conversions, etc.).
-
-Checking path types
--------------------------------
-
-Now we will show a bit about the powerful 'check()' method on paths, which
-allows you to check whether a file exists, what type it is, etc.:
-
-.. sourcecode:: pycon
-
- >>> file1 = temppath.join('file1')
- >>> file1.check() # does it exist?
- False
- >>> file1 = file1.ensure(file=True) # 'touch' the file
- >>> file1.check()
- True
- >>> file1.check(dir=True) # is it a dir?
- False
- >>> file1.check(file=True) # or a file?
- True
- >>> file1.check(ext='.txt') # check the extension
- False
- >>> textfile = temppath.ensure('text.txt', file=True)
- >>> textfile.check(ext='.txt')
- True
- >>> file1.check(basename='file1') # we can use all the path's properties here
- True
-
-Setting svn-properties
---------------------------------
-
-As an example of 'uncommon' methods, we'll show how to read and write
-properties in an ``py.path.svnwc`` instance:
-
-.. sourcecode:: pycon
-
- .. >>> if not py.test.config.option.urlcheck: raise ValueError('skipchunk')
- >>> wc.propget('foo')
- ''
- >>> wc.propset('foo', 'bar')
- >>> wc.propget('foo')
- 'bar'
- >>> len(wc.status().prop_modified) # our own props
- 1
- >>> msg = wc.revert() # roll back our changes
- >>> len(wc.status().prop_modified)
- 0
-
-SVN authentication
-----------------------------
-
-Some uncommon functionality can also be provided as extensions, such as SVN
-authentication:
-
-.. sourcecode:: pycon
-
- .. >>> if not py.test.config.option.urlcheck: raise ValueError('skipchunk')
- >>> auth = py.path.SvnAuth('anonymous', 'user', cache_auth=False,
- ... interactive=False)
- >>> wc.auth = auth
- >>> wc.update() # this should work
- >>> path = wc.ensure('thisshouldnotexist.txt')
- >>> try:
- ... path.commit('testing')
- ... except py.process.cmdexec.Error, e:
- ... pass
- >>> 'authorization failed' in str(e)
- True
-
-Known problems / limitations
-===================================
-
-* The SVN path objects require the "svn" command line,
- there is currently no support for python bindings.
- Parsing the svn output can lead to problems, particularly
- regarding if you have a non-english "locales" setting.
-
-* While the path objects basically work on windows,
- there is no attention yet on making unicode paths
- work or deal with the famous "8.3" filename issues.
-
-
diff --git a/tests/wpt/web-platform-tests/tools/py/py/__init__.py b/tests/wpt/web-platform-tests/tools/py/py/__init__.py
deleted file mode 100644
index bdb9aa2181f..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/py/__init__.py
+++ /dev/null
@@ -1,150 +0,0 @@
-"""
-py.test and pylib: rapid testing and development utils
-
-this module uses apipkg.py for lazy-loading sub modules
-and classes. The initpkg-dictionary below specifies
-name->value mappings where value can be another namespace
-dictionary or an import path.
-
-(c) Holger Krekel and others, 2004-2014
-"""
-__version__ = '1.4.31'
-
-from py import _apipkg
-
-# so that py.error.* instances are picklable
-import sys
-sys.modules['py.error'] = _apipkg.AliasModule("py.error", "py._error", 'error')
-
-_apipkg.initpkg(__name__, attr={'_apipkg': _apipkg}, exportdefs={
- # access to all standard lib modules
- 'std': '._std:std',
- # access to all posix errno's as classes
- 'error': '._error:error',
-
- '_pydir' : '.__metainfo:pydir',
- 'version': 'py:__version__', # backward compatibility
-
- # pytest-2.0 has a flat namespace, we use alias modules
- # to keep old references compatible
- 'test' : 'pytest',
- 'test.collect' : 'pytest',
- 'test.cmdline' : 'pytest',
-
- # hook into the top-level standard library
- 'process' : {
- '__doc__' : '._process:__doc__',
- 'cmdexec' : '._process.cmdexec:cmdexec',
- 'kill' : '._process.killproc:kill',
- 'ForkedFunc' : '._process.forkedfunc:ForkedFunc',
- },
-
- 'apipkg' : {
- 'initpkg' : '._apipkg:initpkg',
- 'ApiModule' : '._apipkg:ApiModule',
- },
-
- 'iniconfig' : {
- 'IniConfig' : '._iniconfig:IniConfig',
- 'ParseError' : '._iniconfig:ParseError',
- },
-
- 'path' : {
- '__doc__' : '._path:__doc__',
- 'svnwc' : '._path.svnwc:SvnWCCommandPath',
- 'svnurl' : '._path.svnurl:SvnCommandPath',
- 'local' : '._path.local:LocalPath',
- 'SvnAuth' : '._path.svnwc:SvnAuth',
- },
-
- # python inspection/code-generation API
- 'code' : {
- '__doc__' : '._code:__doc__',
- 'compile' : '._code.source:compile_',
- 'Source' : '._code.source:Source',
- 'Code' : '._code.code:Code',
- 'Frame' : '._code.code:Frame',
- 'ExceptionInfo' : '._code.code:ExceptionInfo',
- 'Traceback' : '._code.code:Traceback',
- 'getfslineno' : '._code.source:getfslineno',
- 'getrawcode' : '._code.code:getrawcode',
- 'patch_builtins' : '._code.code:patch_builtins',
- 'unpatch_builtins' : '._code.code:unpatch_builtins',
- '_AssertionError' : '._code.assertion:AssertionError',
- '_reinterpret_old' : '._code.assertion:reinterpret_old',
- '_reinterpret' : '._code.assertion:reinterpret',
- '_reprcompare' : '._code.assertion:_reprcompare',
- '_format_explanation' : '._code.assertion:_format_explanation',
- },
-
- # backports and additions of builtins
- 'builtin' : {
- '__doc__' : '._builtin:__doc__',
- 'enumerate' : '._builtin:enumerate',
- 'reversed' : '._builtin:reversed',
- 'sorted' : '._builtin:sorted',
- 'any' : '._builtin:any',
- 'all' : '._builtin:all',
- 'set' : '._builtin:set',
- 'frozenset' : '._builtin:frozenset',
- 'BaseException' : '._builtin:BaseException',
- 'GeneratorExit' : '._builtin:GeneratorExit',
- '_sysex' : '._builtin:_sysex',
- 'print_' : '._builtin:print_',
- '_reraise' : '._builtin:_reraise',
- '_tryimport' : '._builtin:_tryimport',
- 'exec_' : '._builtin:exec_',
- '_basestring' : '._builtin:_basestring',
- '_totext' : '._builtin:_totext',
- '_isbytes' : '._builtin:_isbytes',
- '_istext' : '._builtin:_istext',
- '_getimself' : '._builtin:_getimself',
- '_getfuncdict' : '._builtin:_getfuncdict',
- '_getcode' : '._builtin:_getcode',
- 'builtins' : '._builtin:builtins',
- 'execfile' : '._builtin:execfile',
- 'callable' : '._builtin:callable',
- 'bytes' : '._builtin:bytes',
- 'text' : '._builtin:text',
- },
-
- # input-output helping
- 'io' : {
- '__doc__' : '._io:__doc__',
- 'dupfile' : '._io.capture:dupfile',
- 'TextIO' : '._io.capture:TextIO',
- 'BytesIO' : '._io.capture:BytesIO',
- 'FDCapture' : '._io.capture:FDCapture',
- 'StdCapture' : '._io.capture:StdCapture',
- 'StdCaptureFD' : '._io.capture:StdCaptureFD',
- 'TerminalWriter' : '._io.terminalwriter:TerminalWriter',
- 'ansi_print' : '._io.terminalwriter:ansi_print',
- 'get_terminal_width' : '._io.terminalwriter:get_terminal_width',
- 'saferepr' : '._io.saferepr:saferepr',
- },
-
- # small and mean xml/html generation
- 'xml' : {
- '__doc__' : '._xmlgen:__doc__',
- 'html' : '._xmlgen:html',
- 'Tag' : '._xmlgen:Tag',
- 'raw' : '._xmlgen:raw',
- 'Namespace' : '._xmlgen:Namespace',
- 'escape' : '._xmlgen:escape',
- },
-
- 'log' : {
- # logging API ('producers' and 'consumers' connected via keywords)
- '__doc__' : '._log:__doc__',
- '_apiwarn' : '._log.warning:_apiwarn',
- 'Producer' : '._log.log:Producer',
- 'setconsumer' : '._log.log:setconsumer',
- '_setstate' : '._log.log:setstate',
- '_getstate' : '._log.log:getstate',
- 'Path' : '._log.log:Path',
- 'STDOUT' : '._log.log:STDOUT',
- 'STDERR' : '._log.log:STDERR',
- 'Syslog' : '._log.log:Syslog',
- },
-
-})
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_apipkg.py b/tests/wpt/web-platform-tests/tools/py/py/_apipkg.py
deleted file mode 100644
index a73b8f6d0bc..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/py/_apipkg.py
+++ /dev/null
@@ -1,181 +0,0 @@
-"""
-apipkg: control the exported namespace of a python package.
-
-see http://pypi.python.org/pypi/apipkg
-
-(c) holger krekel, 2009 - MIT license
-"""
-import os
-import sys
-from types import ModuleType
-
-__version__ = '1.3.dev'
-
-def _py_abspath(path):
- """
- special version of abspath
- that will leave paths from jython jars alone
- """
- if path.startswith('__pyclasspath__'):
-
- return path
- else:
- return os.path.abspath(path)
-
-def initpkg(pkgname, exportdefs, attr=dict()):
- """ initialize given package from the export definitions. """
- oldmod = sys.modules.get(pkgname)
- d = {}
- f = getattr(oldmod, '__file__', None)
- if f:
- f = _py_abspath(f)
- d['__file__'] = f
- if hasattr(oldmod, '__version__'):
- d['__version__'] = oldmod.__version__
- if hasattr(oldmod, '__loader__'):
- d['__loader__'] = oldmod.__loader__
- if hasattr(oldmod, '__path__'):
- d['__path__'] = [_py_abspath(p) for p in oldmod.__path__]
- if '__doc__' not in exportdefs and getattr(oldmod, '__doc__', None):
- d['__doc__'] = oldmod.__doc__
- d.update(attr)
- if hasattr(oldmod, "__dict__"):
- oldmod.__dict__.update(d)
- mod = ApiModule(pkgname, exportdefs, implprefix=pkgname, attr=d)
- sys.modules[pkgname] = mod
-
-def importobj(modpath, attrname):
- module = __import__(modpath, None, None, ['__doc__'])
- if not attrname:
- return module
-
- retval = module
- names = attrname.split(".")
- for x in names:
- retval = getattr(retval, x)
- return retval
-
-class ApiModule(ModuleType):
- def __docget(self):
- try:
- return self.__doc
- except AttributeError:
- if '__doc__' in self.__map__:
- return self.__makeattr('__doc__')
- def __docset(self, value):
- self.__doc = value
- __doc__ = property(__docget, __docset)
-
- def __init__(self, name, importspec, implprefix=None, attr=None):
- self.__name__ = name
- self.__all__ = [x for x in importspec if x != '__onfirstaccess__']
- self.__map__ = {}
- self.__implprefix__ = implprefix or name
- if attr:
- for name, val in attr.items():
- # print "setting", self.__name__, name, val
- setattr(self, name, val)
- for name, importspec in importspec.items():
- if isinstance(importspec, dict):
- subname = '%s.%s' % (self.__name__, name)
- apimod = ApiModule(subname, importspec, implprefix)
- sys.modules[subname] = apimod
- setattr(self, name, apimod)
- else:
- parts = importspec.split(':')
- modpath = parts.pop(0)
- attrname = parts and parts[0] or ""
- if modpath[0] == '.':
- modpath = implprefix + modpath
-
- if not attrname:
- subname = '%s.%s' % (self.__name__, name)
- apimod = AliasModule(subname, modpath)
- sys.modules[subname] = apimod
- if '.' not in name:
- setattr(self, name, apimod)
- else:
- self.__map__[name] = (modpath, attrname)
-
- def __repr__(self):
- l = []
- if hasattr(self, '__version__'):
- l.append("version=" + repr(self.__version__))
- if hasattr(self, '__file__'):
- l.append('from ' + repr(self.__file__))
- if l:
- return '<ApiModule %r %s>' % (self.__name__, " ".join(l))
- return '<ApiModule %r>' % (self.__name__,)
-
- def __makeattr(self, name):
- """lazily compute value for name or raise AttributeError if unknown."""
- # print "makeattr", self.__name__, name
- target = None
- if '__onfirstaccess__' in self.__map__:
- target = self.__map__.pop('__onfirstaccess__')
- importobj(*target)()
- try:
- modpath, attrname = self.__map__[name]
- except KeyError:
- if target is not None and name != '__onfirstaccess__':
- # retry, onfirstaccess might have set attrs
- return getattr(self, name)
- raise AttributeError(name)
- else:
- result = importobj(modpath, attrname)
- setattr(self, name, result)
- try:
- del self.__map__[name]
- except KeyError:
- pass # in a recursive-import situation a double-del can happen
- return result
-
- __getattr__ = __makeattr
-
- def __dict__(self):
- # force all the content of the module to be loaded when __dict__ is read
- dictdescr = ModuleType.__dict__['__dict__']
- dict = dictdescr.__get__(self)
- if dict is not None:
- hasattr(self, 'some')
- for name in self.__all__:
- try:
- self.__makeattr(name)
- except AttributeError:
- pass
- return dict
- __dict__ = property(__dict__)
-
-
-def AliasModule(modname, modpath, attrname=None):
- mod = []
-
- def getmod():
- if not mod:
- x = importobj(modpath, None)
- if attrname is not None:
- x = getattr(x, attrname)
- mod.append(x)
- return mod[0]
-
- class AliasModule(ModuleType):
-
- def __repr__(self):
- x = modpath
- if attrname:
- x += "." + attrname
- return '<AliasModule %r for %r>' % (modname, x)
-
- def __getattribute__(self, name):
- try:
- return getattr(getmod(), name)
- except ImportError:
- return None
-
- def __setattr__(self, name, value):
- setattr(getmod(), name, value)
-
- def __delattr__(self, name):
- delattr(getmod(), name)
-
- return AliasModule(str(modname))
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_code/_assertionnew.py b/tests/wpt/web-platform-tests/tools/py/py/_code/_assertionnew.py
deleted file mode 100644
index afb1b31ff05..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/py/_code/_assertionnew.py
+++ /dev/null
@@ -1,339 +0,0 @@
-"""
-Find intermediate evalutation results in assert statements through builtin AST.
-This should replace _assertionold.py eventually.
-"""
-
-import sys
-import ast
-
-import py
-from py._code.assertion import _format_explanation, BuiltinAssertionError
-
-
-if sys.platform.startswith("java") and sys.version_info < (2, 5, 2):
- # See http://bugs.jython.org/issue1497
- _exprs = ("BoolOp", "BinOp", "UnaryOp", "Lambda", "IfExp", "Dict",
- "ListComp", "GeneratorExp", "Yield", "Compare", "Call",
- "Repr", "Num", "Str", "Attribute", "Subscript", "Name",
- "List", "Tuple")
- _stmts = ("FunctionDef", "ClassDef", "Return", "Delete", "Assign",
- "AugAssign", "Print", "For", "While", "If", "With", "Raise",
- "TryExcept", "TryFinally", "Assert", "Import", "ImportFrom",
- "Exec", "Global", "Expr", "Pass", "Break", "Continue")
- _expr_nodes = set(getattr(ast, name) for name in _exprs)
- _stmt_nodes = set(getattr(ast, name) for name in _stmts)
- def _is_ast_expr(node):
- return node.__class__ in _expr_nodes
- def _is_ast_stmt(node):
- return node.__class__ in _stmt_nodes
-else:
- def _is_ast_expr(node):
- return isinstance(node, ast.expr)
- def _is_ast_stmt(node):
- return isinstance(node, ast.stmt)
-
-
-class Failure(Exception):
- """Error found while interpreting AST."""
-
- def __init__(self, explanation=""):
- self.cause = sys.exc_info()
- self.explanation = explanation
-
-
-def interpret(source, frame, should_fail=False):
- mod = ast.parse(source)
- visitor = DebugInterpreter(frame)
- try:
- visitor.visit(mod)
- except Failure:
- failure = sys.exc_info()[1]
- return getfailure(failure)
- if should_fail:
- return ("(assertion failed, but when it was re-run for "
- "printing intermediate values, it did not fail. Suggestions: "
- "compute assert expression before the assert or use --no-assert)")
-
-def run(offending_line, frame=None):
- if frame is None:
- frame = py.code.Frame(sys._getframe(1))
- return interpret(offending_line, frame)
-
-def getfailure(failure):
- explanation = _format_explanation(failure.explanation)
- value = failure.cause[1]
- if str(value):
- lines = explanation.splitlines()
- if not lines:
- lines.append("")
- lines[0] += " << %s" % (value,)
- explanation = "\n".join(lines)
- text = "%s: %s" % (failure.cause[0].__name__, explanation)
- if text.startswith("AssertionError: assert "):
- text = text[16:]
- return text
-
-
-operator_map = {
- ast.BitOr : "|",
- ast.BitXor : "^",
- ast.BitAnd : "&",
- ast.LShift : "<<",
- ast.RShift : ">>",
- ast.Add : "+",
- ast.Sub : "-",
- ast.Mult : "*",
- ast.Div : "/",
- ast.FloorDiv : "//",
- ast.Mod : "%",
- ast.Eq : "==",
- ast.NotEq : "!=",
- ast.Lt : "<",
- ast.LtE : "<=",
- ast.Gt : ">",
- ast.GtE : ">=",
- ast.Pow : "**",
- ast.Is : "is",
- ast.IsNot : "is not",
- ast.In : "in",
- ast.NotIn : "not in"
-}
-
-unary_map = {
- ast.Not : "not %s",
- ast.Invert : "~%s",
- ast.USub : "-%s",
- ast.UAdd : "+%s"
-}
-
-
-class DebugInterpreter(ast.NodeVisitor):
- """Interpret AST nodes to gleam useful debugging information. """
-
- def __init__(self, frame):
- self.frame = frame
-
- def generic_visit(self, node):
- # Fallback when we don't have a special implementation.
- if _is_ast_expr(node):
- mod = ast.Expression(node)
- co = self._compile(mod)
- try:
- result = self.frame.eval(co)
- except Exception:
- raise Failure()
- explanation = self.frame.repr(result)
- return explanation, result
- elif _is_ast_stmt(node):
- mod = ast.Module([node])
- co = self._compile(mod, "exec")
- try:
- self.frame.exec_(co)
- except Exception:
- raise Failure()
- return None, None
- else:
- raise AssertionError("can't handle %s" %(node,))
-
- def _compile(self, source, mode="eval"):
- return compile(source, "<assertion interpretation>", mode)
-
- def visit_Expr(self, expr):
- return self.visit(expr.value)
-
- def visit_Module(self, mod):
- for stmt in mod.body:
- self.visit(stmt)
-
- def visit_Name(self, name):
- explanation, result = self.generic_visit(name)
- # See if the name is local.
- source = "%r in locals() is not globals()" % (name.id,)
- co = self._compile(source)
- try:
- local = self.frame.eval(co)
- except Exception:
- # have to assume it isn't
- local = False
- if not local:
- return name.id, result
- return explanation, result
-
- def visit_Compare(self, comp):
- left = comp.left
- left_explanation, left_result = self.visit(left)
- for op, next_op in zip(comp.ops, comp.comparators):
- next_explanation, next_result = self.visit(next_op)
- op_symbol = operator_map[op.__class__]
- explanation = "%s %s %s" % (left_explanation, op_symbol,
- next_explanation)
- source = "__exprinfo_left %s __exprinfo_right" % (op_symbol,)
- co = self._compile(source)
- try:
- result = self.frame.eval(co, __exprinfo_left=left_result,
- __exprinfo_right=next_result)
- except Exception:
- raise Failure(explanation)
- try:
- if not result:
- break
- except KeyboardInterrupt:
- raise
- except:
- break
- left_explanation, left_result = next_explanation, next_result
-
- rcomp = py.code._reprcompare
- if rcomp:
- res = rcomp(op_symbol, left_result, next_result)
- if res:
- explanation = res
- return explanation, result
-
- def visit_BoolOp(self, boolop):
- is_or = isinstance(boolop.op, ast.Or)
- explanations = []
- for operand in boolop.values:
- explanation, result = self.visit(operand)
- explanations.append(explanation)
- if result == is_or:
- break
- name = is_or and " or " or " and "
- explanation = "(" + name.join(explanations) + ")"
- return explanation, result
-
- def visit_UnaryOp(self, unary):
- pattern = unary_map[unary.op.__class__]
- operand_explanation, operand_result = self.visit(unary.operand)
- explanation = pattern % (operand_explanation,)
- co = self._compile(pattern % ("__exprinfo_expr",))
- try:
- result = self.frame.eval(co, __exprinfo_expr=operand_result)
- except Exception:
- raise Failure(explanation)
- return explanation, result
-
- def visit_BinOp(self, binop):
- left_explanation, left_result = self.visit(binop.left)
- right_explanation, right_result = self.visit(binop.right)
- symbol = operator_map[binop.op.__class__]
- explanation = "(%s %s %s)" % (left_explanation, symbol,
- right_explanation)
- source = "__exprinfo_left %s __exprinfo_right" % (symbol,)
- co = self._compile(source)
- try:
- result = self.frame.eval(co, __exprinfo_left=left_result,
- __exprinfo_right=right_result)
- except Exception:
- raise Failure(explanation)
- return explanation, result
-
- def visit_Call(self, call):
- func_explanation, func = self.visit(call.func)
- arg_explanations = []
- ns = {"__exprinfo_func" : func}
- arguments = []
- for arg in call.args:
- arg_explanation, arg_result = self.visit(arg)
- arg_name = "__exprinfo_%s" % (len(ns),)
- ns[arg_name] = arg_result
- arguments.append(arg_name)
- arg_explanations.append(arg_explanation)
- for keyword in call.keywords:
- arg_explanation, arg_result = self.visit(keyword.value)
- arg_name = "__exprinfo_%s" % (len(ns),)
- ns[arg_name] = arg_result
- keyword_source = "%s=%%s" % (keyword.arg)
- arguments.append(keyword_source % (arg_name,))
- arg_explanations.append(keyword_source % (arg_explanation,))
- if call.starargs:
- arg_explanation, arg_result = self.visit(call.starargs)
- arg_name = "__exprinfo_star"
- ns[arg_name] = arg_result
- arguments.append("*%s" % (arg_name,))
- arg_explanations.append("*%s" % (arg_explanation,))
- if call.kwargs:
- arg_explanation, arg_result = self.visit(call.kwargs)
- arg_name = "__exprinfo_kwds"
- ns[arg_name] = arg_result
- arguments.append("**%s" % (arg_name,))
- arg_explanations.append("**%s" % (arg_explanation,))
- args_explained = ", ".join(arg_explanations)
- explanation = "%s(%s)" % (func_explanation, args_explained)
- args = ", ".join(arguments)
- source = "__exprinfo_func(%s)" % (args,)
- co = self._compile(source)
- try:
- result = self.frame.eval(co, **ns)
- except Exception:
- raise Failure(explanation)
- pattern = "%s\n{%s = %s\n}"
- rep = self.frame.repr(result)
- explanation = pattern % (rep, rep, explanation)
- return explanation, result
-
- def _is_builtin_name(self, name):
- pattern = "%r not in globals() and %r not in locals()"
- source = pattern % (name.id, name.id)
- co = self._compile(source)
- try:
- return self.frame.eval(co)
- except Exception:
- return False
-
- def visit_Attribute(self, attr):
- if not isinstance(attr.ctx, ast.Load):
- return self.generic_visit(attr)
- source_explanation, source_result = self.visit(attr.value)
- explanation = "%s.%s" % (source_explanation, attr.attr)
- source = "__exprinfo_expr.%s" % (attr.attr,)
- co = self._compile(source)
- try:
- result = self.frame.eval(co, __exprinfo_expr=source_result)
- except Exception:
- raise Failure(explanation)
- explanation = "%s\n{%s = %s.%s\n}" % (self.frame.repr(result),
- self.frame.repr(result),
- source_explanation, attr.attr)
- # Check if the attr is from an instance.
- source = "%r in getattr(__exprinfo_expr, '__dict__', {})"
- source = source % (attr.attr,)
- co = self._compile(source)
- try:
- from_instance = self.frame.eval(co, __exprinfo_expr=source_result)
- except Exception:
- from_instance = True
- if from_instance:
- rep = self.frame.repr(result)
- pattern = "%s\n{%s = %s\n}"
- explanation = pattern % (rep, rep, explanation)
- return explanation, result
-
- def visit_Assert(self, assrt):
- test_explanation, test_result = self.visit(assrt.test)
- if test_explanation.startswith("False\n{False =") and \
- test_explanation.endswith("\n"):
- test_explanation = test_explanation[15:-2]
- explanation = "assert %s" % (test_explanation,)
- if not test_result:
- try:
- raise BuiltinAssertionError
- except Exception:
- raise Failure(explanation)
- return explanation, test_result
-
- def visit_Assign(self, assign):
- value_explanation, value_result = self.visit(assign.value)
- explanation = "... = %s" % (value_explanation,)
- name = ast.Name("__exprinfo_expr", ast.Load(),
- lineno=assign.value.lineno,
- col_offset=assign.value.col_offset)
- new_assign = ast.Assign(assign.targets, name, lineno=assign.lineno,
- col_offset=assign.col_offset)
- mod = ast.Module([new_assign])
- co = self._compile(mod, "exec")
- try:
- self.frame.exec_(co, __exprinfo_expr=value_result)
- except Exception:
- raise Failure(explanation)
- return explanation, value_result
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_code/_assertionold.py b/tests/wpt/web-platform-tests/tools/py/py/_code/_assertionold.py
deleted file mode 100644
index 4e81fb3ef6e..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/py/_code/_assertionold.py
+++ /dev/null
@@ -1,555 +0,0 @@
-import py
-import sys, inspect
-from compiler import parse, ast, pycodegen
-from py._code.assertion import BuiltinAssertionError, _format_explanation
-
-passthroughex = py.builtin._sysex
-
-class Failure:
- def __init__(self, node):
- self.exc, self.value, self.tb = sys.exc_info()
- self.node = node
-
-class View(object):
- """View base class.
-
- If C is a subclass of View, then C(x) creates a proxy object around
- the object x. The actual class of the proxy is not C in general,
- but a *subclass* of C determined by the rules below. To avoid confusion
- we call view class the class of the proxy (a subclass of C, so of View)
- and object class the class of x.
-
- Attributes and methods not found in the proxy are automatically read on x.
- Other operations like setting attributes are performed on the proxy, as
- determined by its view class. The object x is available from the proxy
- as its __obj__ attribute.
-
- The view class selection is determined by the __view__ tuples and the
- optional __viewkey__ method. By default, the selected view class is the
- most specific subclass of C whose __view__ mentions the class of x.
- If no such subclass is found, the search proceeds with the parent
- object classes. For example, C(True) will first look for a subclass
- of C with __view__ = (..., bool, ...) and only if it doesn't find any
- look for one with __view__ = (..., int, ...), and then ..., object,...
- If everything fails the class C itself is considered to be the default.
-
- Alternatively, the view class selection can be driven by another aspect
- of the object x, instead of the class of x, by overriding __viewkey__.
- See last example at the end of this module.
- """
-
- _viewcache = {}
- __view__ = ()
-
- def __new__(rootclass, obj, *args, **kwds):
- self = object.__new__(rootclass)
- self.__obj__ = obj
- self.__rootclass__ = rootclass
- key = self.__viewkey__()
- try:
- self.__class__ = self._viewcache[key]
- except KeyError:
- self.__class__ = self._selectsubclass(key)
- return self
-
- def __getattr__(self, attr):
- # attributes not found in the normal hierarchy rooted on View
- # are looked up in the object's real class
- return getattr(self.__obj__, attr)
-
- def __viewkey__(self):
- return self.__obj__.__class__
-
- def __matchkey__(self, key, subclasses):
- if inspect.isclass(key):
- keys = inspect.getmro(key)
- else:
- keys = [key]
- for key in keys:
- result = [C for C in subclasses if key in C.__view__]
- if result:
- return result
- return []
-
- def _selectsubclass(self, key):
- subclasses = list(enumsubclasses(self.__rootclass__))
- for C in subclasses:
- if not isinstance(C.__view__, tuple):
- C.__view__ = (C.__view__,)
- choices = self.__matchkey__(key, subclasses)
- if not choices:
- return self.__rootclass__
- elif len(choices) == 1:
- return choices[0]
- else:
- # combine the multiple choices
- return type('?', tuple(choices), {})
-
- def __repr__(self):
- return '%s(%r)' % (self.__rootclass__.__name__, self.__obj__)
-
-
-def enumsubclasses(cls):
- for subcls in cls.__subclasses__():
- for subsubclass in enumsubclasses(subcls):
- yield subsubclass
- yield cls
-
-
-class Interpretable(View):
- """A parse tree node with a few extra methods."""
- explanation = None
-
- def is_builtin(self, frame):
- return False
-
- def eval(self, frame):
- # fall-back for unknown expression nodes
- try:
- expr = ast.Expression(self.__obj__)
- expr.filename = '<eval>'
- self.__obj__.filename = '<eval>'
- co = pycodegen.ExpressionCodeGenerator(expr).getCode()
- result = frame.eval(co)
- except passthroughex:
- raise
- except:
- raise Failure(self)
- self.result = result
- self.explanation = self.explanation or frame.repr(self.result)
-
- def run(self, frame):
- # fall-back for unknown statement nodes
- try:
- expr = ast.Module(None, ast.Stmt([self.__obj__]))
- expr.filename = '<run>'
- co = pycodegen.ModuleCodeGenerator(expr).getCode()
- frame.exec_(co)
- except passthroughex:
- raise
- except:
- raise Failure(self)
-
- def nice_explanation(self):
- return _format_explanation(self.explanation)
-
-
-class Name(Interpretable):
- __view__ = ast.Name
-
- def is_local(self, frame):
- source = '%r in locals() is not globals()' % self.name
- try:
- return frame.is_true(frame.eval(source))
- except passthroughex:
- raise
- except:
- return False
-
- def is_global(self, frame):
- source = '%r in globals()' % self.name
- try:
- return frame.is_true(frame.eval(source))
- except passthroughex:
- raise
- except:
- return False
-
- def is_builtin(self, frame):
- source = '%r not in locals() and %r not in globals()' % (
- self.name, self.name)
- try:
- return frame.is_true(frame.eval(source))
- except passthroughex:
- raise
- except:
- return False
-
- def eval(self, frame):
- super(Name, self).eval(frame)
- if not self.is_local(frame):
- self.explanation = self.name
-
-class Compare(Interpretable):
- __view__ = ast.Compare
-
- def eval(self, frame):
- expr = Interpretable(self.expr)
- expr.eval(frame)
- for operation, expr2 in self.ops:
- if hasattr(self, 'result'):
- # shortcutting in chained expressions
- if not frame.is_true(self.result):
- break
- expr2 = Interpretable(expr2)
- expr2.eval(frame)
- self.explanation = "%s %s %s" % (
- expr.explanation, operation, expr2.explanation)
- source = "__exprinfo_left %s __exprinfo_right" % operation
- try:
- self.result = frame.eval(source,
- __exprinfo_left=expr.result,
- __exprinfo_right=expr2.result)
- except passthroughex:
- raise
- except:
- raise Failure(self)
- expr = expr2
-
-class And(Interpretable):
- __view__ = ast.And
-
- def eval(self, frame):
- explanations = []
- for expr in self.nodes:
- expr = Interpretable(expr)
- expr.eval(frame)
- explanations.append(expr.explanation)
- self.result = expr.result
- if not frame.is_true(expr.result):
- break
- self.explanation = '(' + ' and '.join(explanations) + ')'
-
-class Or(Interpretable):
- __view__ = ast.Or
-
- def eval(self, frame):
- explanations = []
- for expr in self.nodes:
- expr = Interpretable(expr)
- expr.eval(frame)
- explanations.append(expr.explanation)
- self.result = expr.result
- if frame.is_true(expr.result):
- break
- self.explanation = '(' + ' or '.join(explanations) + ')'
-
-
-# == Unary operations ==
-keepalive = []
-for astclass, astpattern in {
- ast.Not : 'not __exprinfo_expr',
- ast.Invert : '(~__exprinfo_expr)',
- }.items():
-
- class UnaryArith(Interpretable):
- __view__ = astclass
-
- def eval(self, frame, astpattern=astpattern):
- expr = Interpretable(self.expr)
- expr.eval(frame)
- self.explanation = astpattern.replace('__exprinfo_expr',
- expr.explanation)
- try:
- self.result = frame.eval(astpattern,
- __exprinfo_expr=expr.result)
- except passthroughex:
- raise
- except:
- raise Failure(self)
-
- keepalive.append(UnaryArith)
-
-# == Binary operations ==
-for astclass, astpattern in {
- ast.Add : '(__exprinfo_left + __exprinfo_right)',
- ast.Sub : '(__exprinfo_left - __exprinfo_right)',
- ast.Mul : '(__exprinfo_left * __exprinfo_right)',
- ast.Div : '(__exprinfo_left / __exprinfo_right)',
- ast.Mod : '(__exprinfo_left % __exprinfo_right)',
- ast.Power : '(__exprinfo_left ** __exprinfo_right)',
- }.items():
-
- class BinaryArith(Interpretable):
- __view__ = astclass
-
- def eval(self, frame, astpattern=astpattern):
- left = Interpretable(self.left)
- left.eval(frame)
- right = Interpretable(self.right)
- right.eval(frame)
- self.explanation = (astpattern
- .replace('__exprinfo_left', left .explanation)
- .replace('__exprinfo_right', right.explanation))
- try:
- self.result = frame.eval(astpattern,
- __exprinfo_left=left.result,
- __exprinfo_right=right.result)
- except passthroughex:
- raise
- except:
- raise Failure(self)
-
- keepalive.append(BinaryArith)
-
-
-class CallFunc(Interpretable):
- __view__ = ast.CallFunc
-
- def is_bool(self, frame):
- source = 'isinstance(__exprinfo_value, bool)'
- try:
- return frame.is_true(frame.eval(source,
- __exprinfo_value=self.result))
- except passthroughex:
- raise
- except:
- return False
-
- def eval(self, frame):
- node = Interpretable(self.node)
- node.eval(frame)
- explanations = []
- vars = {'__exprinfo_fn': node.result}
- source = '__exprinfo_fn('
- for a in self.args:
- if isinstance(a, ast.Keyword):
- keyword = a.name
- a = a.expr
- else:
- keyword = None
- a = Interpretable(a)
- a.eval(frame)
- argname = '__exprinfo_%d' % len(vars)
- vars[argname] = a.result
- if keyword is None:
- source += argname + ','
- explanations.append(a.explanation)
- else:
- source += '%s=%s,' % (keyword, argname)
- explanations.append('%s=%s' % (keyword, a.explanation))
- if self.star_args:
- star_args = Interpretable(self.star_args)
- star_args.eval(frame)
- argname = '__exprinfo_star'
- vars[argname] = star_args.result
- source += '*' + argname + ','
- explanations.append('*' + star_args.explanation)
- if self.dstar_args:
- dstar_args = Interpretable(self.dstar_args)
- dstar_args.eval(frame)
- argname = '__exprinfo_kwds'
- vars[argname] = dstar_args.result
- source += '**' + argname + ','
- explanations.append('**' + dstar_args.explanation)
- self.explanation = "%s(%s)" % (
- node.explanation, ', '.join(explanations))
- if source.endswith(','):
- source = source[:-1]
- source += ')'
- try:
- self.result = frame.eval(source, **vars)
- except passthroughex:
- raise
- except:
- raise Failure(self)
- if not node.is_builtin(frame) or not self.is_bool(frame):
- r = frame.repr(self.result)
- self.explanation = '%s\n{%s = %s\n}' % (r, r, self.explanation)
-
-class Getattr(Interpretable):
- __view__ = ast.Getattr
-
- def eval(self, frame):
- expr = Interpretable(self.expr)
- expr.eval(frame)
- source = '__exprinfo_expr.%s' % self.attrname
- try:
- self.result = frame.eval(source, __exprinfo_expr=expr.result)
- except passthroughex:
- raise
- except:
- raise Failure(self)
- self.explanation = '%s.%s' % (expr.explanation, self.attrname)
- # if the attribute comes from the instance, its value is interesting
- source = ('hasattr(__exprinfo_expr, "__dict__") and '
- '%r in __exprinfo_expr.__dict__' % self.attrname)
- try:
- from_instance = frame.is_true(
- frame.eval(source, __exprinfo_expr=expr.result))
- except passthroughex:
- raise
- except:
- from_instance = True
- if from_instance:
- r = frame.repr(self.result)
- self.explanation = '%s\n{%s = %s\n}' % (r, r, self.explanation)
-
-# == Re-interpretation of full statements ==
-
-class Assert(Interpretable):
- __view__ = ast.Assert
-
- def run(self, frame):
- test = Interpretable(self.test)
- test.eval(frame)
- # simplify 'assert False where False = ...'
- if (test.explanation.startswith('False\n{False = ') and
- test.explanation.endswith('\n}')):
- test.explanation = test.explanation[15:-2]
- # print the result as 'assert <explanation>'
- self.result = test.result
- self.explanation = 'assert ' + test.explanation
- if not frame.is_true(test.result):
- try:
- raise BuiltinAssertionError
- except passthroughex:
- raise
- except:
- raise Failure(self)
-
-class Assign(Interpretable):
- __view__ = ast.Assign
-
- def run(self, frame):
- expr = Interpretable(self.expr)
- expr.eval(frame)
- self.result = expr.result
- self.explanation = '... = ' + expr.explanation
- # fall-back-run the rest of the assignment
- ass = ast.Assign(self.nodes, ast.Name('__exprinfo_expr'))
- mod = ast.Module(None, ast.Stmt([ass]))
- mod.filename = '<run>'
- co = pycodegen.ModuleCodeGenerator(mod).getCode()
- try:
- frame.exec_(co, __exprinfo_expr=expr.result)
- except passthroughex:
- raise
- except:
- raise Failure(self)
-
-class Discard(Interpretable):
- __view__ = ast.Discard
-
- def run(self, frame):
- expr = Interpretable(self.expr)
- expr.eval(frame)
- self.result = expr.result
- self.explanation = expr.explanation
-
-class Stmt(Interpretable):
- __view__ = ast.Stmt
-
- def run(self, frame):
- for stmt in self.nodes:
- stmt = Interpretable(stmt)
- stmt.run(frame)
-
-
-def report_failure(e):
- explanation = e.node.nice_explanation()
- if explanation:
- explanation = ", in: " + explanation
- else:
- explanation = ""
- sys.stdout.write("%s: %s%s\n" % (e.exc.__name__, e.value, explanation))
-
-def check(s, frame=None):
- if frame is None:
- frame = sys._getframe(1)
- frame = py.code.Frame(frame)
- expr = parse(s, 'eval')
- assert isinstance(expr, ast.Expression)
- node = Interpretable(expr.node)
- try:
- node.eval(frame)
- except passthroughex:
- raise
- except Failure:
- e = sys.exc_info()[1]
- report_failure(e)
- else:
- if not frame.is_true(node.result):
- sys.stderr.write("assertion failed: %s\n" % node.nice_explanation())
-
-
-###########################################################
-# API / Entry points
-# #########################################################
-
-def interpret(source, frame, should_fail=False):
- module = Interpretable(parse(source, 'exec').node)
- #print "got module", module
- if isinstance(frame, py.std.types.FrameType):
- frame = py.code.Frame(frame)
- try:
- module.run(frame)
- except Failure:
- e = sys.exc_info()[1]
- return getfailure(e)
- except passthroughex:
- raise
- except:
- import traceback
- traceback.print_exc()
- if should_fail:
- return ("(assertion failed, but when it was re-run for "
- "printing intermediate values, it did not fail. Suggestions: "
- "compute assert expression before the assert or use --nomagic)")
- else:
- return None
-
-def getmsg(excinfo):
- if isinstance(excinfo, tuple):
- excinfo = py.code.ExceptionInfo(excinfo)
- #frame, line = gettbline(tb)
- #frame = py.code.Frame(frame)
- #return interpret(line, frame)
-
- tb = excinfo.traceback[-1]
- source = str(tb.statement).strip()
- x = interpret(source, tb.frame, should_fail=True)
- if not isinstance(x, str):
- raise TypeError("interpret returned non-string %r" % (x,))
- return x
-
-def getfailure(e):
- explanation = e.node.nice_explanation()
- if str(e.value):
- lines = explanation.split('\n')
- lines[0] += " << %s" % (e.value,)
- explanation = '\n'.join(lines)
- text = "%s: %s" % (e.exc.__name__, explanation)
- if text.startswith('AssertionError: assert '):
- text = text[16:]
- return text
-
-def run(s, frame=None):
- if frame is None:
- frame = sys._getframe(1)
- frame = py.code.Frame(frame)
- module = Interpretable(parse(s, 'exec').node)
- try:
- module.run(frame)
- except Failure:
- e = sys.exc_info()[1]
- report_failure(e)
-
-
-if __name__ == '__main__':
- # example:
- def f():
- return 5
- def g():
- return 3
- def h(x):
- return 'never'
- check("f() * g() == 5")
- check("not f()")
- check("not (f() and g() or 0)")
- check("f() == g()")
- i = 4
- check("i == f()")
- check("len(f()) == 0")
- check("isinstance(2+3+4, float)")
-
- run("x = i")
- check("x == 5")
-
- run("assert not f(), 'oops'")
- run("a, b, c = 1, 2")
- run("a, b, c = f()")
-
- check("max([f(),g()]) == 4")
- check("'hello'[g()] == 'h'")
- run("'guk%d' % h(f())")
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_code/assertion.py b/tests/wpt/web-platform-tests/tools/py/py/_code/assertion.py
deleted file mode 100644
index 4ce80c75b1c..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/py/_code/assertion.py
+++ /dev/null
@@ -1,94 +0,0 @@
-import sys
-import py
-
-BuiltinAssertionError = py.builtin.builtins.AssertionError
-
-_reprcompare = None # if set, will be called by assert reinterp for comparison ops
-
-def _format_explanation(explanation):
- """This formats an explanation
-
- Normally all embedded newlines are escaped, however there are
- three exceptions: \n{, \n} and \n~. The first two are intended
- cover nested explanations, see function and attribute explanations
- for examples (.visit_Call(), visit_Attribute()). The last one is
- for when one explanation needs to span multiple lines, e.g. when
- displaying diffs.
- """
- raw_lines = (explanation or '').split('\n')
- # escape newlines not followed by {, } and ~
- lines = [raw_lines[0]]
- for l in raw_lines[1:]:
- if l.startswith('{') or l.startswith('}') or l.startswith('~'):
- lines.append(l)
- else:
- lines[-1] += '\\n' + l
-
- result = lines[:1]
- stack = [0]
- stackcnt = [0]
- for line in lines[1:]:
- if line.startswith('{'):
- if stackcnt[-1]:
- s = 'and '
- else:
- s = 'where '
- stack.append(len(result))
- stackcnt[-1] += 1
- stackcnt.append(0)
- result.append(' +' + ' '*(len(stack)-1) + s + line[1:])
- elif line.startswith('}'):
- assert line.startswith('}')
- stack.pop()
- stackcnt.pop()
- result[stack[-1]] += line[1:]
- else:
- assert line.startswith('~')
- result.append(' '*len(stack) + line[1:])
- assert len(stack) == 1
- return '\n'.join(result)
-
-
-class AssertionError(BuiltinAssertionError):
- def __init__(self, *args):
- BuiltinAssertionError.__init__(self, *args)
- if args:
- try:
- self.msg = str(args[0])
- except py.builtin._sysex:
- raise
- except:
- self.msg = "<[broken __repr__] %s at %0xd>" %(
- args[0].__class__, id(args[0]))
- else:
- f = py.code.Frame(sys._getframe(1))
- try:
- source = f.code.fullsource
- if source is not None:
- try:
- source = source.getstatement(f.lineno, assertion=True)
- except IndexError:
- source = None
- else:
- source = str(source.deindent()).strip()
- except py.error.ENOENT:
- source = None
- # this can also occur during reinterpretation, when the
- # co_filename is set to "<run>".
- if source:
- self.msg = reinterpret(source, f, should_fail=True)
- else:
- self.msg = "<could not determine information>"
- if not self.args:
- self.args = (self.msg,)
-
-if sys.version_info > (3, 0):
- AssertionError.__module__ = "builtins"
- reinterpret_old = "old reinterpretation not available for py3"
-else:
- from py._code._assertionold import interpret as reinterpret_old
-if sys.version_info >= (2, 6) or (sys.platform.startswith("java")):
- from py._code._assertionnew import interpret as reinterpret
-else:
- reinterpret = reinterpret_old
-
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_code/code.py b/tests/wpt/web-platform-tests/tools/py/py/_code/code.py
deleted file mode 100644
index f14c562a296..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/py/_code/code.py
+++ /dev/null
@@ -1,787 +0,0 @@
-import py
-import sys
-from inspect import CO_VARARGS, CO_VARKEYWORDS
-
-builtin_repr = repr
-
-reprlib = py.builtin._tryimport('repr', 'reprlib')
-
-if sys.version_info[0] >= 3:
- from traceback import format_exception_only
-else:
- from py._code._py2traceback import format_exception_only
-
-class Code(object):
- """ wrapper around Python code objects """
- def __init__(self, rawcode):
- if not hasattr(rawcode, "co_filename"):
- rawcode = py.code.getrawcode(rawcode)
- try:
- self.filename = rawcode.co_filename
- self.firstlineno = rawcode.co_firstlineno - 1
- self.name = rawcode.co_name
- except AttributeError:
- raise TypeError("not a code object: %r" %(rawcode,))
- self.raw = rawcode
-
- def __eq__(self, other):
- return self.raw == other.raw
-
- def __ne__(self, other):
- return not self == other
-
- @property
- def path(self):
- """ return a path object pointing to source code (note that it
- might not point to an actually existing file). """
- p = py.path.local(self.raw.co_filename)
- # maybe don't try this checking
- if not p.check():
- # XXX maybe try harder like the weird logic
- # in the standard lib [linecache.updatecache] does?
- p = self.raw.co_filename
- return p
-
- @property
- def fullsource(self):
- """ return a py.code.Source object for the full source file of the code
- """
- from py._code import source
- full, _ = source.findsource(self.raw)
- return full
-
- def source(self):
- """ return a py.code.Source object for the code object's source only
- """
- # return source only for that part of code
- return py.code.Source(self.raw)
-
- def getargs(self, var=False):
- """ return a tuple with the argument names for the code object
-
- if 'var' is set True also return the names of the variable and
- keyword arguments when present
- """
- # handfull shortcut for getting args
- raw = self.raw
- argcount = raw.co_argcount
- if var:
- argcount += raw.co_flags & CO_VARARGS
- argcount += raw.co_flags & CO_VARKEYWORDS
- return raw.co_varnames[:argcount]
-
-class Frame(object):
- """Wrapper around a Python frame holding f_locals and f_globals
- in which expressions can be evaluated."""
-
- def __init__(self, frame):
- self.lineno = frame.f_lineno - 1
- self.f_globals = frame.f_globals
- self.f_locals = frame.f_locals
- self.raw = frame
- self.code = py.code.Code(frame.f_code)
-
- @property
- def statement(self):
- """ statement this frame is at """
- if self.code.fullsource is None:
- return py.code.Source("")
- return self.code.fullsource.getstatement(self.lineno)
-
- def eval(self, code, **vars):
- """ evaluate 'code' in the frame
-
- 'vars' are optional additional local variables
-
- returns the result of the evaluation
- """
- f_locals = self.f_locals.copy()
- f_locals.update(vars)
- return eval(code, self.f_globals, f_locals)
-
- def exec_(self, code, **vars):
- """ exec 'code' in the frame
-
- 'vars' are optiona; additional local variables
- """
- f_locals = self.f_locals.copy()
- f_locals.update(vars)
- py.builtin.exec_(code, self.f_globals, f_locals )
-
- def repr(self, object):
- """ return a 'safe' (non-recursive, one-line) string repr for 'object'
- """
- return py.io.saferepr(object)
-
- def is_true(self, object):
- return object
-
- def getargs(self, var=False):
- """ return a list of tuples (name, value) for all arguments
-
- if 'var' is set True also include the variable and keyword
- arguments when present
- """
- retval = []
- for arg in self.code.getargs(var):
- try:
- retval.append((arg, self.f_locals[arg]))
- except KeyError:
- pass # this can occur when using Psyco
- return retval
-
-class TracebackEntry(object):
- """ a single entry in a traceback """
-
- _repr_style = None
- exprinfo = None
-
- def __init__(self, rawentry):
- self._rawentry = rawentry
- self.lineno = rawentry.tb_lineno - 1
-
- def set_repr_style(self, mode):
- assert mode in ("short", "long")
- self._repr_style = mode
-
- @property
- def frame(self):
- return py.code.Frame(self._rawentry.tb_frame)
-
- @property
- def relline(self):
- return self.lineno - self.frame.code.firstlineno
-
- def __repr__(self):
- return "<TracebackEntry %s:%d>" %(self.frame.code.path, self.lineno+1)
-
- @property
- def statement(self):
- """ py.code.Source object for the current statement """
- source = self.frame.code.fullsource
- return source.getstatement(self.lineno)
-
- @property
- def path(self):
- """ path to the source code """
- return self.frame.code.path
-
- def getlocals(self):
- return self.frame.f_locals
- locals = property(getlocals, None, None, "locals of underlaying frame")
-
- def reinterpret(self):
- """Reinterpret the failing statement and returns a detailed information
- about what operations are performed."""
- if self.exprinfo is None:
- source = str(self.statement).strip()
- x = py.code._reinterpret(source, self.frame, should_fail=True)
- if not isinstance(x, str):
- raise TypeError("interpret returned non-string %r" % (x,))
- self.exprinfo = x
- return self.exprinfo
-
- def getfirstlinesource(self):
- # on Jython this firstlineno can be -1 apparently
- return max(self.frame.code.firstlineno, 0)
-
- def getsource(self, astcache=None):
- """ return failing source code. """
- # we use the passed in astcache to not reparse asttrees
- # within exception info printing
- from py._code.source import getstatementrange_ast
- source = self.frame.code.fullsource
- if source is None:
- return None
- key = astnode = None
- if astcache is not None:
- key = self.frame.code.path
- if key is not None:
- astnode = astcache.get(key, None)
- start = self.getfirstlinesource()
- try:
- astnode, _, end = getstatementrange_ast(self.lineno, source,
- astnode=astnode)
- except SyntaxError:
- end = self.lineno + 1
- else:
- if key is not None:
- astcache[key] = astnode
- return source[start:end]
-
- source = property(getsource)
-
- def ishidden(self):
- """ return True if the current frame has a var __tracebackhide__
- resolving to True
-
- mostly for internal use
- """
- try:
- return self.frame.f_locals['__tracebackhide__']
- except KeyError:
- try:
- return self.frame.f_globals['__tracebackhide__']
- except KeyError:
- return False
-
- def __str__(self):
- try:
- fn = str(self.path)
- except py.error.Error:
- fn = '???'
- name = self.frame.code.name
- try:
- line = str(self.statement).lstrip()
- except KeyboardInterrupt:
- raise
- except:
- line = "???"
- return " File %r:%d in %s\n %s\n" %(fn, self.lineno+1, name, line)
-
- def name(self):
- return self.frame.code.raw.co_name
- name = property(name, None, None, "co_name of underlaying code")
-
-class Traceback(list):
- """ Traceback objects encapsulate and offer higher level
- access to Traceback entries.
- """
- Entry = TracebackEntry
- def __init__(self, tb):
- """ initialize from given python traceback object. """
- if hasattr(tb, 'tb_next'):
- def f(cur):
- while cur is not None:
- yield self.Entry(cur)
- cur = cur.tb_next
- list.__init__(self, f(tb))
- else:
- list.__init__(self, tb)
-
- def cut(self, path=None, lineno=None, firstlineno=None, excludepath=None):
- """ return a Traceback instance wrapping part of this Traceback
-
- by provding any combination of path, lineno and firstlineno, the
- first frame to start the to-be-returned traceback is determined
-
- this allows cutting the first part of a Traceback instance e.g.
- for formatting reasons (removing some uninteresting bits that deal
- with handling of the exception/traceback)
- """
- for x in self:
- code = x.frame.code
- codepath = code.path
- if ((path is None or codepath == path) and
- (excludepath is None or not hasattr(codepath, 'relto') or
- not codepath.relto(excludepath)) and
- (lineno is None or x.lineno == lineno) and
- (firstlineno is None or x.frame.code.firstlineno == firstlineno)):
- return Traceback(x._rawentry)
- return self
-
- def __getitem__(self, key):
- val = super(Traceback, self).__getitem__(key)
- if isinstance(key, type(slice(0))):
- val = self.__class__(val)
- return val
-
- def filter(self, fn=lambda x: not x.ishidden()):
- """ return a Traceback instance with certain items removed
-
- fn is a function that gets a single argument, a TracebackItem
- instance, and should return True when the item should be added
- to the Traceback, False when not
-
- by default this removes all the TracebackItems which are hidden
- (see ishidden() above)
- """
- return Traceback(filter(fn, self))
-
- def getcrashentry(self):
- """ return last non-hidden traceback entry that lead
- to the exception of a traceback.
- """
- for i in range(-1, -len(self)-1, -1):
- entry = self[i]
- if not entry.ishidden():
- return entry
- return self[-1]
-
- def recursionindex(self):
- """ return the index of the frame/TracebackItem where recursion
- originates if appropriate, None if no recursion occurred
- """
- cache = {}
- for i, entry in enumerate(self):
- # id for the code.raw is needed to work around
- # the strange metaprogramming in the decorator lib from pypi
- # which generates code objects that have hash/value equality
- #XXX needs a test
- key = entry.frame.code.path, id(entry.frame.code.raw), entry.lineno
- #print "checking for recursion at", key
- l = cache.setdefault(key, [])
- if l:
- f = entry.frame
- loc = f.f_locals
- for otherloc in l:
- if f.is_true(f.eval(co_equal,
- __recursioncache_locals_1=loc,
- __recursioncache_locals_2=otherloc)):
- return i
- l.append(entry.frame.f_locals)
- return None
-
-co_equal = compile('__recursioncache_locals_1 == __recursioncache_locals_2',
- '?', 'eval')
-
-class ExceptionInfo(object):
- """ wraps sys.exc_info() objects and offers
- help for navigating the traceback.
- """
- _striptext = ''
- def __init__(self, tup=None, exprinfo=None):
- if tup is None:
- tup = sys.exc_info()
- if exprinfo is None and isinstance(tup[1], AssertionError):
- exprinfo = getattr(tup[1], 'msg', None)
- if exprinfo is None:
- exprinfo = str(tup[1])
- if exprinfo and exprinfo.startswith('assert '):
- self._striptext = 'AssertionError: '
- self._excinfo = tup
- #: the exception class
- self.type = tup[0]
- #: the exception instance
- self.value = tup[1]
- #: the exception raw traceback
- self.tb = tup[2]
- #: the exception type name
- self.typename = self.type.__name__
- #: the exception traceback (py.code.Traceback instance)
- self.traceback = py.code.Traceback(self.tb)
-
- def __repr__(self):
- return "<ExceptionInfo %s tblen=%d>" % (self.typename, len(self.traceback))
-
- def exconly(self, tryshort=False):
- """ return the exception as a string
-
- when 'tryshort' resolves to True, and the exception is a
- py.code._AssertionError, only the actual exception part of
- the exception representation is returned (so 'AssertionError: ' is
- removed from the beginning)
- """
- lines = format_exception_only(self.type, self.value)
- text = ''.join(lines)
- text = text.rstrip()
- if tryshort:
- if text.startswith(self._striptext):
- text = text[len(self._striptext):]
- return text
-
- def errisinstance(self, exc):
- """ return True if the exception is an instance of exc """
- return isinstance(self.value, exc)
-
- def _getreprcrash(self):
- exconly = self.exconly(tryshort=True)
- entry = self.traceback.getcrashentry()
- path, lineno = entry.frame.code.raw.co_filename, entry.lineno
- return ReprFileLocation(path, lineno+1, exconly)
-
- def getrepr(self, showlocals=False, style="long",
- abspath=False, tbfilter=True, funcargs=False):
- """ return str()able representation of this exception info.
- showlocals: show locals per traceback entry
- style: long|short|no|native traceback style
- tbfilter: hide entries (where __tracebackhide__ is true)
-
- in case of style==native, tbfilter and showlocals is ignored.
- """
- if style == 'native':
- return ReprExceptionInfo(ReprTracebackNative(
- py.std.traceback.format_exception(
- self.type,
- self.value,
- self.traceback[0]._rawentry,
- )), self._getreprcrash())
-
- fmt = FormattedExcinfo(showlocals=showlocals, style=style,
- abspath=abspath, tbfilter=tbfilter, funcargs=funcargs)
- return fmt.repr_excinfo(self)
-
- def __str__(self):
- entry = self.traceback[-1]
- loc = ReprFileLocation(entry.path, entry.lineno + 1, self.exconly())
- return str(loc)
-
- def __unicode__(self):
- entry = self.traceback[-1]
- loc = ReprFileLocation(entry.path, entry.lineno + 1, self.exconly())
- return unicode(loc)
-
-
-class FormattedExcinfo(object):
- """ presenting information about failing Functions and Generators. """
- # for traceback entries
- flow_marker = ">"
- fail_marker = "E"
-
- def __init__(self, showlocals=False, style="long", abspath=True, tbfilter=True, funcargs=False):
- self.showlocals = showlocals
- self.style = style
- self.tbfilter = tbfilter
- self.funcargs = funcargs
- self.abspath = abspath
- self.astcache = {}
-
- def _getindent(self, source):
- # figure out indent for given source
- try:
- s = str(source.getstatement(len(source)-1))
- except KeyboardInterrupt:
- raise
- except:
- try:
- s = str(source[-1])
- except KeyboardInterrupt:
- raise
- except:
- return 0
- return 4 + (len(s) - len(s.lstrip()))
-
- def _getentrysource(self, entry):
- source = entry.getsource(self.astcache)
- if source is not None:
- source = source.deindent()
- return source
-
- def _saferepr(self, obj):
- return py.io.saferepr(obj)
-
- def repr_args(self, entry):
- if self.funcargs:
- args = []
- for argname, argvalue in entry.frame.getargs(var=True):
- args.append((argname, self._saferepr(argvalue)))
- return ReprFuncArgs(args)
-
- def get_source(self, source, line_index=-1, excinfo=None, short=False):
- """ return formatted and marked up source lines. """
- lines = []
- if source is None or line_index >= len(source.lines):
- source = py.code.Source("???")
- line_index = 0
- if line_index < 0:
- line_index += len(source)
- space_prefix = " "
- if short:
- lines.append(space_prefix + source.lines[line_index].strip())
- else:
- for line in source.lines[:line_index]:
- lines.append(space_prefix + line)
- lines.append(self.flow_marker + " " + source.lines[line_index])
- for line in source.lines[line_index+1:]:
- lines.append(space_prefix + line)
- if excinfo is not None:
- indent = 4 if short else self._getindent(source)
- lines.extend(self.get_exconly(excinfo, indent=indent, markall=True))
- return lines
-
- def get_exconly(self, excinfo, indent=4, markall=False):
- lines = []
- indent = " " * indent
- # get the real exception information out
- exlines = excinfo.exconly(tryshort=True).split('\n')
- failindent = self.fail_marker + indent[1:]
- for line in exlines:
- lines.append(failindent + line)
- if not markall:
- failindent = indent
- return lines
-
- def repr_locals(self, locals):
- if self.showlocals:
- lines = []
- keys = [loc for loc in locals if loc[0] != "@"]
- keys.sort()
- for name in keys:
- value = locals[name]
- if name == '__builtins__':
- lines.append("__builtins__ = <builtins>")
- else:
- # This formatting could all be handled by the
- # _repr() function, which is only reprlib.Repr in
- # disguise, so is very configurable.
- str_repr = self._saferepr(value)
- #if len(str_repr) < 70 or not isinstance(value,
- # (list, tuple, dict)):
- lines.append("%-10s = %s" %(name, str_repr))
- #else:
- # self._line("%-10s =\\" % (name,))
- # # XXX
- # py.std.pprint.pprint(value, stream=self.excinfowriter)
- return ReprLocals(lines)
-
- def repr_traceback_entry(self, entry, excinfo=None):
- source = self._getentrysource(entry)
- if source is None:
- source = py.code.Source("???")
- line_index = 0
- else:
- # entry.getfirstlinesource() can be -1, should be 0 on jython
- line_index = entry.lineno - max(entry.getfirstlinesource(), 0)
-
- lines = []
- style = entry._repr_style
- if style is None:
- style = self.style
- if style in ("short", "long"):
- short = style == "short"
- reprargs = self.repr_args(entry) if not short else None
- s = self.get_source(source, line_index, excinfo, short=short)
- lines.extend(s)
- if short:
- message = "in %s" %(entry.name)
- else:
- message = excinfo and excinfo.typename or ""
- path = self._makepath(entry.path)
- filelocrepr = ReprFileLocation(path, entry.lineno+1, message)
- localsrepr = None
- if not short:
- localsrepr = self.repr_locals(entry.locals)
- return ReprEntry(lines, reprargs, localsrepr, filelocrepr, style)
- if excinfo:
- lines.extend(self.get_exconly(excinfo, indent=4))
- return ReprEntry(lines, None, None, None, style)
-
- def _makepath(self, path):
- if not self.abspath:
- try:
- np = py.path.local().bestrelpath(path)
- except OSError:
- return path
- if len(np) < len(str(path)):
- path = np
- return path
-
- def repr_traceback(self, excinfo):
- traceback = excinfo.traceback
- if self.tbfilter:
- traceback = traceback.filter()
- recursionindex = None
- if excinfo.errisinstance(RuntimeError):
- if "maximum recursion depth exceeded" in str(excinfo.value):
- recursionindex = traceback.recursionindex()
- last = traceback[-1]
- entries = []
- extraline = None
- for index, entry in enumerate(traceback):
- einfo = (last == entry) and excinfo or None
- reprentry = self.repr_traceback_entry(entry, einfo)
- entries.append(reprentry)
- if index == recursionindex:
- extraline = "!!! Recursion detected (same locals & position)"
- break
- return ReprTraceback(entries, extraline, style=self.style)
-
- def repr_excinfo(self, excinfo):
- reprtraceback = self.repr_traceback(excinfo)
- reprcrash = excinfo._getreprcrash()
- return ReprExceptionInfo(reprtraceback, reprcrash)
-
-class TerminalRepr:
- def __str__(self):
- s = self.__unicode__()
- if sys.version_info[0] < 3:
- s = s.encode('utf-8')
- return s
-
- def __unicode__(self):
- # FYI this is called from pytest-xdist's serialization of exception
- # information.
- io = py.io.TextIO()
- tw = py.io.TerminalWriter(file=io)
- self.toterminal(tw)
- return io.getvalue().strip()
-
- def __repr__(self):
- return "<%s instance at %0x>" %(self.__class__, id(self))
-
-
-class ReprExceptionInfo(TerminalRepr):
- def __init__(self, reprtraceback, reprcrash):
- self.reprtraceback = reprtraceback
- self.reprcrash = reprcrash
- self.sections = []
-
- def addsection(self, name, content, sep="-"):
- self.sections.append((name, content, sep))
-
- def toterminal(self, tw):
- self.reprtraceback.toterminal(tw)
- for name, content, sep in self.sections:
- tw.sep(sep, name)
- tw.line(content)
-
-class ReprTraceback(TerminalRepr):
- entrysep = "_ "
-
- def __init__(self, reprentries, extraline, style):
- self.reprentries = reprentries
- self.extraline = extraline
- self.style = style
-
- def toterminal(self, tw):
- # the entries might have different styles
- last_style = None
- for i, entry in enumerate(self.reprentries):
- if entry.style == "long":
- tw.line("")
- entry.toterminal(tw)
- if i < len(self.reprentries) - 1:
- next_entry = self.reprentries[i+1]
- if entry.style == "long" or \
- entry.style == "short" and next_entry.style == "long":
- tw.sep(self.entrysep)
-
- if self.extraline:
- tw.line(self.extraline)
-
-class ReprTracebackNative(ReprTraceback):
- def __init__(self, tblines):
- self.style = "native"
- self.reprentries = [ReprEntryNative(tblines)]
- self.extraline = None
-
-class ReprEntryNative(TerminalRepr):
- style = "native"
-
- def __init__(self, tblines):
- self.lines = tblines
-
- def toterminal(self, tw):
- tw.write("".join(self.lines))
-
-class ReprEntry(TerminalRepr):
- localssep = "_ "
-
- def __init__(self, lines, reprfuncargs, reprlocals, filelocrepr, style):
- self.lines = lines
- self.reprfuncargs = reprfuncargs
- self.reprlocals = reprlocals
- self.reprfileloc = filelocrepr
- self.style = style
-
- def toterminal(self, tw):
- if self.style == "short":
- self.reprfileloc.toterminal(tw)
- for line in self.lines:
- red = line.startswith("E ")
- tw.line(line, bold=True, red=red)
- #tw.line("")
- return
- if self.reprfuncargs:
- self.reprfuncargs.toterminal(tw)
- for line in self.lines:
- red = line.startswith("E ")
- tw.line(line, bold=True, red=red)
- if self.reprlocals:
- #tw.sep(self.localssep, "Locals")
- tw.line("")
- self.reprlocals.toterminal(tw)
- if self.reprfileloc:
- if self.lines:
- tw.line("")
- self.reprfileloc.toterminal(tw)
-
- def __str__(self):
- return "%s\n%s\n%s" % ("\n".join(self.lines),
- self.reprlocals,
- self.reprfileloc)
-
-class ReprFileLocation(TerminalRepr):
- def __init__(self, path, lineno, message):
- self.path = str(path)
- self.lineno = lineno
- self.message = message
-
- def toterminal(self, tw):
- # filename and lineno output for each entry,
- # using an output format that most editors unterstand
- msg = self.message
- i = msg.find("\n")
- if i != -1:
- msg = msg[:i]
- tw.line("%s:%s: %s" %(self.path, self.lineno, msg))
-
-class ReprLocals(TerminalRepr):
- def __init__(self, lines):
- self.lines = lines
-
- def toterminal(self, tw):
- for line in self.lines:
- tw.line(line)
-
-class ReprFuncArgs(TerminalRepr):
- def __init__(self, args):
- self.args = args
-
- def toterminal(self, tw):
- if self.args:
- linesofar = ""
- for name, value in self.args:
- ns = "%s = %s" %(name, value)
- if len(ns) + len(linesofar) + 2 > tw.fullwidth:
- if linesofar:
- tw.line(linesofar)
- linesofar = ns
- else:
- if linesofar:
- linesofar += ", " + ns
- else:
- linesofar = ns
- if linesofar:
- tw.line(linesofar)
- tw.line("")
-
-
-
-oldbuiltins = {}
-
-def patch_builtins(assertion=True, compile=True):
- """ put compile and AssertionError builtins to Python's builtins. """
- if assertion:
- from py._code import assertion
- l = oldbuiltins.setdefault('AssertionError', [])
- l.append(py.builtin.builtins.AssertionError)
- py.builtin.builtins.AssertionError = assertion.AssertionError
- if compile:
- l = oldbuiltins.setdefault('compile', [])
- l.append(py.builtin.builtins.compile)
- py.builtin.builtins.compile = py.code.compile
-
-def unpatch_builtins(assertion=True, compile=True):
- """ remove compile and AssertionError builtins from Python builtins. """
- if assertion:
- py.builtin.builtins.AssertionError = oldbuiltins['AssertionError'].pop()
- if compile:
- py.builtin.builtins.compile = oldbuiltins['compile'].pop()
-
-def getrawcode(obj, trycall=True):
- """ return code object for given function. """
- try:
- return obj.__code__
- except AttributeError:
- obj = getattr(obj, 'im_func', obj)
- obj = getattr(obj, 'func_code', obj)
- obj = getattr(obj, 'f_code', obj)
- obj = getattr(obj, '__code__', obj)
- if trycall and not hasattr(obj, 'co_firstlineno'):
- if hasattr(obj, '__call__') and not py.std.inspect.isclass(obj):
- x = getrawcode(obj.__call__, trycall=False)
- if hasattr(x, 'co_firstlineno'):
- return x
- return obj
-
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_code/source.py b/tests/wpt/web-platform-tests/tools/py/py/_code/source.py
deleted file mode 100644
index 3a648e63579..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/py/_code/source.py
+++ /dev/null
@@ -1,419 +0,0 @@
-from __future__ import generators
-
-from bisect import bisect_right
-import sys
-import inspect, tokenize
-import py
-from types import ModuleType
-cpy_compile = compile
-
-try:
- import _ast
- from _ast import PyCF_ONLY_AST as _AST_FLAG
-except ImportError:
- _AST_FLAG = 0
- _ast = None
-
-
-class Source(object):
- """ a immutable object holding a source code fragment,
- possibly deindenting it.
- """
- _compilecounter = 0
- def __init__(self, *parts, **kwargs):
- self.lines = lines = []
- de = kwargs.get('deindent', True)
- rstrip = kwargs.get('rstrip', True)
- for part in parts:
- if not part:
- partlines = []
- if isinstance(part, Source):
- partlines = part.lines
- elif isinstance(part, (tuple, list)):
- partlines = [x.rstrip("\n") for x in part]
- elif isinstance(part, py.builtin._basestring):
- partlines = part.split('\n')
- if rstrip:
- while partlines:
- if partlines[-1].strip():
- break
- partlines.pop()
- else:
- partlines = getsource(part, deindent=de).lines
- if de:
- partlines = deindent(partlines)
- lines.extend(partlines)
-
- def __eq__(self, other):
- try:
- return self.lines == other.lines
- except AttributeError:
- if isinstance(other, str):
- return str(self) == other
- return False
-
- def __getitem__(self, key):
- if isinstance(key, int):
- return self.lines[key]
- else:
- if key.step not in (None, 1):
- raise IndexError("cannot slice a Source with a step")
- return self.__getslice__(key.start, key.stop)
-
- def __len__(self):
- return len(self.lines)
-
- def __getslice__(self, start, end):
- newsource = Source()
- newsource.lines = self.lines[start:end]
- return newsource
-
- def strip(self):
- """ return new source object with trailing
- and leading blank lines removed.
- """
- start, end = 0, len(self)
- while start < end and not self.lines[start].strip():
- start += 1
- while end > start and not self.lines[end-1].strip():
- end -= 1
- source = Source()
- source.lines[:] = self.lines[start:end]
- return source
-
- def putaround(self, before='', after='', indent=' ' * 4):
- """ return a copy of the source object with
- 'before' and 'after' wrapped around it.
- """
- before = Source(before)
- after = Source(after)
- newsource = Source()
- lines = [ (indent + line) for line in self.lines]
- newsource.lines = before.lines + lines + after.lines
- return newsource
-
- def indent(self, indent=' ' * 4):
- """ return a copy of the source object with
- all lines indented by the given indent-string.
- """
- newsource = Source()
- newsource.lines = [(indent+line) for line in self.lines]
- return newsource
-
- def getstatement(self, lineno, assertion=False):
- """ return Source statement which contains the
- given linenumber (counted from 0).
- """
- start, end = self.getstatementrange(lineno, assertion)
- return self[start:end]
-
- def getstatementrange(self, lineno, assertion=False):
- """ return (start, end) tuple which spans the minimal
- statement region which containing the given lineno.
- """
- if not (0 <= lineno < len(self)):
- raise IndexError("lineno out of range")
- ast, start, end = getstatementrange_ast(lineno, self)
- return start, end
-
- def deindent(self, offset=None):
- """ return a new source object deindented by offset.
- If offset is None then guess an indentation offset from
- the first non-blank line. Subsequent lines which have a
- lower indentation offset will be copied verbatim as
- they are assumed to be part of multilines.
- """
- # XXX maybe use the tokenizer to properly handle multiline
- # strings etc.pp?
- newsource = Source()
- newsource.lines[:] = deindent(self.lines, offset)
- return newsource
-
- def isparseable(self, deindent=True):
- """ return True if source is parseable, heuristically
- deindenting it by default.
- """
- try:
- import parser
- except ImportError:
- syntax_checker = lambda x: compile(x, 'asd', 'exec')
- else:
- syntax_checker = parser.suite
-
- if deindent:
- source = str(self.deindent())
- else:
- source = str(self)
- try:
- #compile(source+'\n', "x", "exec")
- syntax_checker(source+'\n')
- except KeyboardInterrupt:
- raise
- except Exception:
- return False
- else:
- return True
-
- def __str__(self):
- return "\n".join(self.lines)
-
- def compile(self, filename=None, mode='exec',
- flag=generators.compiler_flag,
- dont_inherit=0, _genframe=None):
- """ return compiled code object. if filename is None
- invent an artificial filename which displays
- the source/line position of the caller frame.
- """
- if not filename or py.path.local(filename).check(file=0):
- if _genframe is None:
- _genframe = sys._getframe(1) # the caller
- fn,lineno = _genframe.f_code.co_filename, _genframe.f_lineno
- base = "<%d-codegen " % self._compilecounter
- self.__class__._compilecounter += 1
- if not filename:
- filename = base + '%s:%d>' % (fn, lineno)
- else:
- filename = base + '%r %s:%d>' % (filename, fn, lineno)
- source = "\n".join(self.lines) + '\n'
- try:
- co = cpy_compile(source, filename, mode, flag)
- except SyntaxError:
- ex = sys.exc_info()[1]
- # re-represent syntax errors from parsing python strings
- msglines = self.lines[:ex.lineno]
- if ex.offset:
- msglines.append(" "*ex.offset + '^')
- msglines.append("(code was compiled probably from here: %s)" % filename)
- newex = SyntaxError('\n'.join(msglines))
- newex.offset = ex.offset
- newex.lineno = ex.lineno
- newex.text = ex.text
- raise newex
- else:
- if flag & _AST_FLAG:
- return co
- lines = [(x + "\n") for x in self.lines]
- if sys.version_info[0] >= 3:
- # XXX py3's inspect.getsourcefile() checks for a module
- # and a pep302 __loader__ ... we don't have a module
- # at code compile-time so we need to fake it here
- m = ModuleType("_pycodecompile_pseudo_module")
- py.std.inspect.modulesbyfile[filename] = None
- py.std.sys.modules[None] = m
- m.__loader__ = 1
- py.std.linecache.cache[filename] = (1, None, lines, filename)
- return co
-
-#
-# public API shortcut functions
-#
-
-def compile_(source, filename=None, mode='exec', flags=
- generators.compiler_flag, dont_inherit=0):
- """ compile the given source to a raw code object,
- and maintain an internal cache which allows later
- retrieval of the source code for the code object
- and any recursively created code objects.
- """
- if _ast is not None and isinstance(source, _ast.AST):
- # XXX should Source support having AST?
- return cpy_compile(source, filename, mode, flags, dont_inherit)
- _genframe = sys._getframe(1) # the caller
- s = Source(source)
- co = s.compile(filename, mode, flags, _genframe=_genframe)
- return co
-
-
-def getfslineno(obj):
- """ Return source location (path, lineno) for the given object.
- If the source cannot be determined return ("", -1)
- """
- try:
- code = py.code.Code(obj)
- except TypeError:
- try:
- fn = (py.std.inspect.getsourcefile(obj) or
- py.std.inspect.getfile(obj))
- except TypeError:
- return "", -1
-
- fspath = fn and py.path.local(fn) or None
- lineno = -1
- if fspath:
- try:
- _, lineno = findsource(obj)
- except IOError:
- pass
- else:
- fspath = code.path
- lineno = code.firstlineno
- assert isinstance(lineno, int)
- return fspath, lineno
-
-#
-# helper functions
-#
-
-def findsource(obj):
- try:
- sourcelines, lineno = py.std.inspect.findsource(obj)
- except py.builtin._sysex:
- raise
- except:
- return None, -1
- source = Source()
- source.lines = [line.rstrip() for line in sourcelines]
- return source, lineno
-
-def getsource(obj, **kwargs):
- obj = py.code.getrawcode(obj)
- try:
- strsrc = inspect.getsource(obj)
- except IndentationError:
- strsrc = "\"Buggy python version consider upgrading, cannot get source\""
- assert isinstance(strsrc, str)
- return Source(strsrc, **kwargs)
-
-def deindent(lines, offset=None):
- if offset is None:
- for line in lines:
- line = line.expandtabs()
- s = line.lstrip()
- if s:
- offset = len(line)-len(s)
- break
- else:
- offset = 0
- if offset == 0:
- return list(lines)
- newlines = []
- def readline_generator(lines):
- for line in lines:
- yield line + '\n'
- while True:
- yield ''
-
- it = readline_generator(lines)
-
- try:
- for _, _, (sline, _), (eline, _), _ in tokenize.generate_tokens(lambda: next(it)):
- if sline > len(lines):
- break # End of input reached
- if sline > len(newlines):
- line = lines[sline - 1].expandtabs()
- if line.lstrip() and line[:offset].isspace():
- line = line[offset:] # Deindent
- newlines.append(line)
-
- for i in range(sline, eline):
- # Don't deindent continuing lines of
- # multiline tokens (i.e. multiline strings)
- newlines.append(lines[i])
- except (IndentationError, tokenize.TokenError):
- pass
- # Add any lines we didn't see. E.g. if an exception was raised.
- newlines.extend(lines[len(newlines):])
- return newlines
-
-
-def get_statement_startend2(lineno, node):
- import ast
- # flatten all statements and except handlers into one lineno-list
- # AST's line numbers start indexing at 1
- l = []
- for x in ast.walk(node):
- if isinstance(x, _ast.stmt) or isinstance(x, _ast.ExceptHandler):
- l.append(x.lineno - 1)
- for name in "finalbody", "orelse":
- val = getattr(x, name, None)
- if val:
- # treat the finally/orelse part as its own statement
- l.append(val[0].lineno - 1 - 1)
- l.sort()
- insert_index = bisect_right(l, lineno)
- start = l[insert_index - 1]
- if insert_index >= len(l):
- end = None
- else:
- end = l[insert_index]
- return start, end
-
-
-def getstatementrange_ast(lineno, source, assertion=False, astnode=None):
- if astnode is None:
- content = str(source)
- if sys.version_info < (2,7):
- content += "\n"
- try:
- astnode = compile(content, "source", "exec", 1024) # 1024 for AST
- except ValueError:
- start, end = getstatementrange_old(lineno, source, assertion)
- return None, start, end
- start, end = get_statement_startend2(lineno, astnode)
- # we need to correct the end:
- # - ast-parsing strips comments
- # - there might be empty lines
- # - we might have lesser indented code blocks at the end
- if end is None:
- end = len(source.lines)
-
- if end > start + 1:
- # make sure we don't span differently indented code blocks
- # by using the BlockFinder helper used which inspect.getsource() uses itself
- block_finder = inspect.BlockFinder()
- # if we start with an indented line, put blockfinder to "started" mode
- block_finder.started = source.lines[start][0].isspace()
- it = ((x + "\n") for x in source.lines[start:end])
- try:
- for tok in tokenize.generate_tokens(lambda: next(it)):
- block_finder.tokeneater(*tok)
- except (inspect.EndOfBlock, IndentationError):
- end = block_finder.last + start
- except Exception:
- pass
-
- # the end might still point to a comment or empty line, correct it
- while end:
- line = source.lines[end - 1].lstrip()
- if line.startswith("#") or not line:
- end -= 1
- else:
- break
- return astnode, start, end
-
-
-def getstatementrange_old(lineno, source, assertion=False):
- """ return (start, end) tuple which spans the minimal
- statement region which containing the given lineno.
- raise an IndexError if no such statementrange can be found.
- """
- # XXX this logic is only used on python2.4 and below
- # 1. find the start of the statement
- from codeop import compile_command
- for start in range(lineno, -1, -1):
- if assertion:
- line = source.lines[start]
- # the following lines are not fully tested, change with care
- if 'super' in line and 'self' in line and '__init__' in line:
- raise IndexError("likely a subclass")
- if "assert" not in line and "raise" not in line:
- continue
- trylines = source.lines[start:lineno+1]
- # quick hack to prepare parsing an indented line with
- # compile_command() (which errors on "return" outside defs)
- trylines.insert(0, 'def xxx():')
- trysource = '\n '.join(trylines)
- # ^ space here
- try:
- compile_command(trysource)
- except (SyntaxError, OverflowError, ValueError):
- continue
-
- # 2. find the end of the statement
- for end in range(lineno+1, len(source)+1):
- trysource = source[start:end]
- if trysource.isparseable():
- return start, end
- raise SyntaxError("no valid source range around line %d " % (lineno,))
-
-
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_error.py b/tests/wpt/web-platform-tests/tools/py/py/_error.py
deleted file mode 100644
index 550fb521a04..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/py/_error.py
+++ /dev/null
@@ -1,88 +0,0 @@
-"""
-create errno-specific classes for IO or os calls.
-
-"""
-import sys, os, errno
-
-class Error(EnvironmentError):
- def __repr__(self):
- return "%s.%s %r: %s " %(self.__class__.__module__,
- self.__class__.__name__,
- self.__class__.__doc__,
- " ".join(map(str, self.args)),
- #repr(self.args)
- )
-
- def __str__(self):
- s = "[%s]: %s" %(self.__class__.__doc__,
- " ".join(map(str, self.args)),
- )
- return s
-
-_winerrnomap = {
- 2: errno.ENOENT,
- 3: errno.ENOENT,
- 17: errno.EEXIST,
- 13: errno.EBUSY, # empty cd drive, but ENOMEDIUM seems unavailiable
- 22: errno.ENOTDIR,
- 20: errno.ENOTDIR,
- 267: errno.ENOTDIR,
- 5: errno.EACCES, # anything better?
-}
-
-class ErrorMaker(object):
- """ lazily provides Exception classes for each possible POSIX errno
- (as defined per the 'errno' module). All such instances
- subclass EnvironmentError.
- """
- Error = Error
- _errno2class = {}
-
- def __getattr__(self, name):
- if name[0] == "_":
- raise AttributeError(name)
- eno = getattr(errno, name)
- cls = self._geterrnoclass(eno)
- setattr(self, name, cls)
- return cls
-
- def _geterrnoclass(self, eno):
- try:
- return self._errno2class[eno]
- except KeyError:
- clsname = errno.errorcode.get(eno, "UnknownErrno%d" %(eno,))
- errorcls = type(Error)(clsname, (Error,),
- {'__module__':'py.error',
- '__doc__': os.strerror(eno)})
- self._errno2class[eno] = errorcls
- return errorcls
-
- def checked_call(self, func, *args, **kwargs):
- """ call a function and raise an errno-exception if applicable. """
- __tracebackhide__ = True
- try:
- return func(*args, **kwargs)
- except self.Error:
- raise
- except (OSError, EnvironmentError):
- cls, value, tb = sys.exc_info()
- if not hasattr(value, 'errno'):
- raise
- __tracebackhide__ = False
- errno = value.errno
- try:
- if not isinstance(value, WindowsError):
- raise NameError
- except NameError:
- # we are not on Windows, or we got a proper OSError
- cls = self._geterrnoclass(errno)
- else:
- try:
- cls = self._geterrnoclass(_winerrnomap[errno])
- except KeyError:
- raise value
- raise cls("%s%r" % (func.__name__, args))
- __tracebackhide__ = True
-
-
-error = ErrorMaker()
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_iniconfig.py b/tests/wpt/web-platform-tests/tools/py/py/_iniconfig.py
deleted file mode 100644
index 92b50bd853a..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/py/_iniconfig.py
+++ /dev/null
@@ -1,162 +0,0 @@
-""" brain-dead simple parser for ini-style files.
-(C) Ronny Pfannschmidt, Holger Krekel -- MIT licensed
-"""
-__version__ = "0.2.dev2"
-
-__all__ = ['IniConfig', 'ParseError']
-
-COMMENTCHARS = "#;"
-
-class ParseError(Exception):
- def __init__(self, path, lineno, msg):
- Exception.__init__(self, path, lineno, msg)
- self.path = path
- self.lineno = lineno
- self.msg = msg
-
- def __str__(self):
- return "%s:%s: %s" %(self.path, self.lineno+1, self.msg)
-
-class SectionWrapper(object):
- def __init__(self, config, name):
- self.config = config
- self.name = name
-
- def lineof(self, name):
- return self.config.lineof(self.name, name)
-
- def get(self, key, default=None, convert=str):
- return self.config.get(self.name, key, convert=convert, default=default)
-
- def __getitem__(self, key):
- return self.config.sections[self.name][key]
-
- def __iter__(self):
- section = self.config.sections.get(self.name, [])
- def lineof(key):
- return self.config.lineof(self.name, key)
- for name in sorted(section, key=lineof):
- yield name
-
- def items(self):
- for name in self:
- yield name, self[name]
-
-
-class IniConfig(object):
- def __init__(self, path, data=None):
- self.path = str(path) # convenience
- if data is None:
- f = open(self.path)
- try:
- tokens = self._parse(iter(f))
- finally:
- f.close()
- else:
- tokens = self._parse(data.splitlines(True))
-
- self._sources = {}
- self.sections = {}
-
- for lineno, section, name, value in tokens:
- if section is None:
- self._raise(lineno, 'no section header defined')
- self._sources[section, name] = lineno
- if name is None:
- if section in self.sections:
- self._raise(lineno, 'duplicate section %r'%(section, ))
- self.sections[section] = {}
- else:
- if name in self.sections[section]:
- self._raise(lineno, 'duplicate name %r'%(name, ))
- self.sections[section][name] = value
-
- def _raise(self, lineno, msg):
- raise ParseError(self.path, lineno, msg)
-
- def _parse(self, line_iter):
- result = []
- section = None
- for lineno, line in enumerate(line_iter):
- name, data = self._parseline(line, lineno)
- # new value
- if name is not None and data is not None:
- result.append((lineno, section, name, data))
- # new section
- elif name is not None and data is None:
- if not name:
- self._raise(lineno, 'empty section name')
- section = name
- result.append((lineno, section, None, None))
- # continuation
- elif name is None and data is not None:
- if not result:
- self._raise(lineno, 'unexpected value continuation')
- last = result.pop()
- last_name, last_data = last[-2:]
- if last_name is None:
- self._raise(lineno, 'unexpected value continuation')
-
- if last_data:
- data = '%s\n%s' % (last_data, data)
- result.append(last[:-1] + (data,))
- return result
-
- def _parseline(self, line, lineno):
- # blank lines
- if iscommentline(line):
- line = ""
- else:
- line = line.rstrip()
- if not line:
- return None, None
- # section
- if line[0] == '[':
- realline = line
- for c in COMMENTCHARS:
- line = line.split(c)[0].rstrip()
- if line[-1] == "]":
- return line[1:-1], None
- return None, realline.strip()
- # value
- elif not line[0].isspace():
- try:
- name, value = line.split('=', 1)
- if ":" in name:
- raise ValueError()
- except ValueError:
- try:
- name, value = line.split(":", 1)
- except ValueError:
- self._raise(lineno, 'unexpected line: %r' % line)
- return name.strip(), value.strip()
- # continuation
- else:
- return None, line.strip()
-
- def lineof(self, section, name=None):
- lineno = self._sources.get((section, name))
- if lineno is not None:
- return lineno + 1
-
- def get(self, section, name, default=None, convert=str):
- try:
- return convert(self.sections[section][name])
- except KeyError:
- return default
-
- def __getitem__(self, name):
- if name not in self.sections:
- raise KeyError(name)
- return SectionWrapper(self, name)
-
- def __iter__(self):
- for name in sorted(self.sections, key=self.lineof):
- yield SectionWrapper(self, name)
-
- def __contains__(self, arg):
- return arg in self.sections
-
-def iscommentline(line):
- c = line.lstrip()[:1]
- return c in COMMENTCHARS
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_io/terminalwriter.py b/tests/wpt/web-platform-tests/tools/py/py/_io/terminalwriter.py
deleted file mode 100644
index cef1ff58097..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/py/_io/terminalwriter.py
+++ /dev/null
@@ -1,348 +0,0 @@
-"""
-
-Helper functions for writing to terminals and files.
-
-"""
-
-
-import sys, os
-import py
-py3k = sys.version_info[0] >= 3
-from py.builtin import text, bytes
-
-win32_and_ctypes = False
-colorama = None
-if sys.platform == "win32":
- try:
- import colorama
- except ImportError:
- try:
- import ctypes
- win32_and_ctypes = True
- except ImportError:
- pass
-
-
-def _getdimensions():
- import termios,fcntl,struct
- call = fcntl.ioctl(1,termios.TIOCGWINSZ,"\000"*8)
- height,width = struct.unpack( "hhhh", call ) [:2]
- return height, width
-
-
-def get_terminal_width():
- height = width = 0
- try:
- height, width = _getdimensions()
- except py.builtin._sysex:
- raise
- except:
- # pass to fallback below
- pass
-
- if width == 0:
- # FALLBACK:
- # * some exception happened
- # * or this is emacs terminal which reports (0,0)
- width = int(os.environ.get('COLUMNS', 80))
-
- # XXX the windows getdimensions may be bogus, let's sanify a bit
- if width < 40:
- width = 80
- return width
-
-terminal_width = get_terminal_width()
-
-# XXX unify with _escaped func below
-def ansi_print(text, esc, file=None, newline=True, flush=False):
- if file is None:
- file = sys.stderr
- text = text.rstrip()
- if esc and not isinstance(esc, tuple):
- esc = (esc,)
- if esc and sys.platform != "win32" and file.isatty():
- text = (''.join(['\x1b[%sm' % cod for cod in esc]) +
- text +
- '\x1b[0m') # ANSI color code "reset"
- if newline:
- text += '\n'
-
- if esc and win32_and_ctypes and file.isatty():
- if 1 in esc:
- bold = True
- esc = tuple([x for x in esc if x != 1])
- else:
- bold = False
- esctable = {() : FOREGROUND_WHITE, # normal
- (31,): FOREGROUND_RED, # red
- (32,): FOREGROUND_GREEN, # green
- (33,): FOREGROUND_GREEN|FOREGROUND_RED, # yellow
- (34,): FOREGROUND_BLUE, # blue
- (35,): FOREGROUND_BLUE|FOREGROUND_RED, # purple
- (36,): FOREGROUND_BLUE|FOREGROUND_GREEN, # cyan
- (37,): FOREGROUND_WHITE, # white
- (39,): FOREGROUND_WHITE, # reset
- }
- attr = esctable.get(esc, FOREGROUND_WHITE)
- if bold:
- attr |= FOREGROUND_INTENSITY
- STD_OUTPUT_HANDLE = -11
- STD_ERROR_HANDLE = -12
- if file is sys.stderr:
- handle = GetStdHandle(STD_ERROR_HANDLE)
- else:
- handle = GetStdHandle(STD_OUTPUT_HANDLE)
- oldcolors = GetConsoleInfo(handle).wAttributes
- attr |= (oldcolors & 0x0f0)
- SetConsoleTextAttribute(handle, attr)
- while len(text) > 32768:
- file.write(text[:32768])
- text = text[32768:]
- if text:
- file.write(text)
- SetConsoleTextAttribute(handle, oldcolors)
- else:
- file.write(text)
-
- if flush:
- file.flush()
-
-def should_do_markup(file):
- if os.environ.get('PY_COLORS') == '1':
- return True
- if os.environ.get('PY_COLORS') == '0':
- return False
- return hasattr(file, 'isatty') and file.isatty() \
- and os.environ.get('TERM') != 'dumb' \
- and not (sys.platform.startswith('java') and os._name == 'nt')
-
-class TerminalWriter(object):
- _esctable = dict(black=30, red=31, green=32, yellow=33,
- blue=34, purple=35, cyan=36, white=37,
- Black=40, Red=41, Green=42, Yellow=43,
- Blue=44, Purple=45, Cyan=46, White=47,
- bold=1, light=2, blink=5, invert=7)
-
- # XXX deprecate stringio argument
- def __init__(self, file=None, stringio=False, encoding=None):
- if file is None:
- if stringio:
- self.stringio = file = py.io.TextIO()
- else:
- file = py.std.sys.stdout
- elif py.builtin.callable(file) and not (
- hasattr(file, "write") and hasattr(file, "flush")):
- file = WriteFile(file, encoding=encoding)
- if hasattr(file, "isatty") and file.isatty() and colorama:
- file = colorama.AnsiToWin32(file).stream
- self.encoding = encoding or getattr(file, 'encoding', "utf-8")
- self._file = file
- self.fullwidth = get_terminal_width()
- self.hasmarkup = should_do_markup(file)
- self._lastlen = 0
-
- def _escaped(self, text, esc):
- if esc and self.hasmarkup:
- text = (''.join(['\x1b[%sm' % cod for cod in esc]) +
- text +'\x1b[0m')
- return text
-
- def markup(self, text, **kw):
- esc = []
- for name in kw:
- if name not in self._esctable:
- raise ValueError("unknown markup: %r" %(name,))
- if kw[name]:
- esc.append(self._esctable[name])
- return self._escaped(text, tuple(esc))
-
- def sep(self, sepchar, title=None, fullwidth=None, **kw):
- if fullwidth is None:
- fullwidth = self.fullwidth
- # the goal is to have the line be as long as possible
- # under the condition that len(line) <= fullwidth
- if sys.platform == "win32":
- # if we print in the last column on windows we are on a
- # new line but there is no way to verify/neutralize this
- # (we may not know the exact line width)
- # so let's be defensive to avoid empty lines in the output
- fullwidth -= 1
- if title is not None:
- # we want 2 + 2*len(fill) + len(title) <= fullwidth
- # i.e. 2 + 2*len(sepchar)*N + len(title) <= fullwidth
- # 2*len(sepchar)*N <= fullwidth - len(title) - 2
- # N <= (fullwidth - len(title) - 2) // (2*len(sepchar))
- N = (fullwidth - len(title) - 2) // (2*len(sepchar))
- fill = sepchar * N
- line = "%s %s %s" % (fill, title, fill)
- else:
- # we want len(sepchar)*N <= fullwidth
- # i.e. N <= fullwidth // len(sepchar)
- line = sepchar * (fullwidth // len(sepchar))
- # in some situations there is room for an extra sepchar at the right,
- # in particular if we consider that with a sepchar like "_ " the
- # trailing space is not important at the end of the line
- if len(line) + len(sepchar.rstrip()) <= fullwidth:
- line += sepchar.rstrip()
-
- self.line(line, **kw)
-
- def write(self, msg, **kw):
- if msg:
- if not isinstance(msg, (bytes, text)):
- msg = text(msg)
- if self.hasmarkup and kw:
- markupmsg = self.markup(msg, **kw)
- else:
- markupmsg = msg
- write_out(self._file, markupmsg)
-
- def line(self, s='', **kw):
- self.write(s, **kw)
- self._checkfill(s)
- self.write('\n')
-
- def reline(self, line, **kw):
- if not self.hasmarkup:
- raise ValueError("cannot use rewrite-line without terminal")
- self.write(line, **kw)
- self._checkfill(line)
- self.write('\r')
- self._lastlen = len(line)
-
- def _checkfill(self, line):
- diff2last = self._lastlen - len(line)
- if diff2last > 0:
- self.write(" " * diff2last)
-
-class Win32ConsoleWriter(TerminalWriter):
- def write(self, msg, **kw):
- if msg:
- if not isinstance(msg, (bytes, text)):
- msg = text(msg)
- oldcolors = None
- if self.hasmarkup and kw:
- handle = GetStdHandle(STD_OUTPUT_HANDLE)
- oldcolors = GetConsoleInfo(handle).wAttributes
- default_bg = oldcolors & 0x00F0
- attr = default_bg
- if kw.pop('bold', False):
- attr |= FOREGROUND_INTENSITY
-
- if kw.pop('red', False):
- attr |= FOREGROUND_RED
- elif kw.pop('blue', False):
- attr |= FOREGROUND_BLUE
- elif kw.pop('green', False):
- attr |= FOREGROUND_GREEN
- elif kw.pop('yellow', False):
- attr |= FOREGROUND_GREEN|FOREGROUND_RED
- else:
- attr |= oldcolors & 0x0007
-
- SetConsoleTextAttribute(handle, attr)
- write_out(self._file, msg)
- if oldcolors:
- SetConsoleTextAttribute(handle, oldcolors)
-
-class WriteFile(object):
- def __init__(self, writemethod, encoding=None):
- self.encoding = encoding
- self._writemethod = writemethod
-
- def write(self, data):
- if self.encoding:
- data = data.encode(self.encoding, "replace")
- self._writemethod(data)
-
- def flush(self):
- return
-
-
-if win32_and_ctypes:
- TerminalWriter = Win32ConsoleWriter
- import ctypes
- from ctypes import wintypes
-
- # ctypes access to the Windows console
- STD_OUTPUT_HANDLE = -11
- STD_ERROR_HANDLE = -12
- FOREGROUND_BLACK = 0x0000 # black text
- FOREGROUND_BLUE = 0x0001 # text color contains blue.
- FOREGROUND_GREEN = 0x0002 # text color contains green.
- FOREGROUND_RED = 0x0004 # text color contains red.
- FOREGROUND_WHITE = 0x0007
- FOREGROUND_INTENSITY = 0x0008 # text color is intensified.
- BACKGROUND_BLACK = 0x0000 # background color black
- BACKGROUND_BLUE = 0x0010 # background color contains blue.
- BACKGROUND_GREEN = 0x0020 # background color contains green.
- BACKGROUND_RED = 0x0040 # background color contains red.
- BACKGROUND_WHITE = 0x0070
- BACKGROUND_INTENSITY = 0x0080 # background color is intensified.
-
- SHORT = ctypes.c_short
- class COORD(ctypes.Structure):
- _fields_ = [('X', SHORT),
- ('Y', SHORT)]
- class SMALL_RECT(ctypes.Structure):
- _fields_ = [('Left', SHORT),
- ('Top', SHORT),
- ('Right', SHORT),
- ('Bottom', SHORT)]
- class CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
- _fields_ = [('dwSize', COORD),
- ('dwCursorPosition', COORD),
- ('wAttributes', wintypes.WORD),
- ('srWindow', SMALL_RECT),
- ('dwMaximumWindowSize', COORD)]
-
- _GetStdHandle = ctypes.windll.kernel32.GetStdHandle
- _GetStdHandle.argtypes = [wintypes.DWORD]
- _GetStdHandle.restype = wintypes.HANDLE
- def GetStdHandle(kind):
- return _GetStdHandle(kind)
-
- SetConsoleTextAttribute = ctypes.windll.kernel32.SetConsoleTextAttribute
- SetConsoleTextAttribute.argtypes = [wintypes.HANDLE, wintypes.WORD]
- SetConsoleTextAttribute.restype = wintypes.BOOL
-
- _GetConsoleScreenBufferInfo = \
- ctypes.windll.kernel32.GetConsoleScreenBufferInfo
- _GetConsoleScreenBufferInfo.argtypes = [wintypes.HANDLE,
- ctypes.POINTER(CONSOLE_SCREEN_BUFFER_INFO)]
- _GetConsoleScreenBufferInfo.restype = wintypes.BOOL
- def GetConsoleInfo(handle):
- info = CONSOLE_SCREEN_BUFFER_INFO()
- _GetConsoleScreenBufferInfo(handle, ctypes.byref(info))
- return info
-
- def _getdimensions():
- handle = GetStdHandle(STD_OUTPUT_HANDLE)
- info = GetConsoleInfo(handle)
- # Substract one from the width, otherwise the cursor wraps
- # and the ending \n causes an empty line to display.
- return info.dwSize.Y, info.dwSize.X - 1
-
-def write_out(fil, msg):
- # XXX sometimes "msg" is of type bytes, sometimes text which
- # complicates the situation. Should we try to enforce unicode?
- try:
- # on py27 and above writing out to sys.stdout with an encoding
- # should usually work for unicode messages (if the encoding is
- # capable of it)
- fil.write(msg)
- except UnicodeEncodeError:
- # on py26 it might not work because stdout expects bytes
- if fil.encoding:
- try:
- fil.write(msg.encode(fil.encoding))
- except UnicodeEncodeError:
- # it might still fail if the encoding is not capable
- pass
- else:
- fil.flush()
- return
- # fallback: escape all unicode characters
- msg = msg.encode("unicode-escape").decode("ascii")
- fil.write(msg)
- fil.flush()
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_log/log.py b/tests/wpt/web-platform-tests/tools/py/py/_log/log.py
deleted file mode 100644
index ce47e8c754a..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/py/_log/log.py
+++ /dev/null
@@ -1,186 +0,0 @@
-"""
-basic logging functionality based on a producer/consumer scheme.
-
-XXX implement this API: (maybe put it into slogger.py?)
-
- log = Logger(
- info=py.log.STDOUT,
- debug=py.log.STDOUT,
- command=None)
- log.info("hello", "world")
- log.command("hello", "world")
-
- log = Logger(info=Logger(something=...),
- debug=py.log.STDOUT,
- command=None)
-"""
-import py, sys
-
-class Message(object):
- def __init__(self, keywords, args):
- self.keywords = keywords
- self.args = args
-
- def content(self):
- return " ".join(map(str, self.args))
-
- def prefix(self):
- return "[%s] " % (":".join(self.keywords))
-
- def __str__(self):
- return self.prefix() + self.content()
-
-
-class Producer(object):
- """ (deprecated) Log producer API which sends messages to be logged
- to a 'consumer' object, which then prints them to stdout,
- stderr, files, etc. Used extensively by PyPy-1.1.
- """
-
- Message = Message # to allow later customization
- keywords2consumer = {}
-
- def __init__(self, keywords, keywordmapper=None, **kw):
- if hasattr(keywords, 'split'):
- keywords = tuple(keywords.split())
- self._keywords = keywords
- if keywordmapper is None:
- keywordmapper = default_keywordmapper
- self._keywordmapper = keywordmapper
-
- def __repr__(self):
- return "<py.log.Producer %s>" % ":".join(self._keywords)
-
- def __getattr__(self, name):
- if '_' in name:
- raise AttributeError(name)
- producer = self.__class__(self._keywords + (name,))
- setattr(self, name, producer)
- return producer
-
- def __call__(self, *args):
- """ write a message to the appropriate consumer(s) """
- func = self._keywordmapper.getconsumer(self._keywords)
- if func is not None:
- func(self.Message(self._keywords, args))
-
-class KeywordMapper:
- def __init__(self):
- self.keywords2consumer = {}
-
- def getstate(self):
- return self.keywords2consumer.copy()
- def setstate(self, state):
- self.keywords2consumer.clear()
- self.keywords2consumer.update(state)
-
- def getconsumer(self, keywords):
- """ return a consumer matching the given keywords.
-
- tries to find the most suitable consumer by walking, starting from
- the back, the list of keywords, the first consumer matching a
- keyword is returned (falling back to py.log.default)
- """
- for i in range(len(keywords), 0, -1):
- try:
- return self.keywords2consumer[keywords[:i]]
- except KeyError:
- continue
- return self.keywords2consumer.get('default', default_consumer)
-
- def setconsumer(self, keywords, consumer):
- """ set a consumer for a set of keywords. """
- # normalize to tuples
- if isinstance(keywords, str):
- keywords = tuple(filter(None, keywords.split()))
- elif hasattr(keywords, '_keywords'):
- keywords = keywords._keywords
- elif not isinstance(keywords, tuple):
- raise TypeError("key %r is not a string or tuple" % (keywords,))
- if consumer is not None and not py.builtin.callable(consumer):
- if not hasattr(consumer, 'write'):
- raise TypeError(
- "%r should be None, callable or file-like" % (consumer,))
- consumer = File(consumer)
- self.keywords2consumer[keywords] = consumer
-
-def default_consumer(msg):
- """ the default consumer, prints the message to stdout (using 'print') """
- sys.stderr.write(str(msg)+"\n")
-
-default_keywordmapper = KeywordMapper()
-
-def setconsumer(keywords, consumer):
- default_keywordmapper.setconsumer(keywords, consumer)
-
-def setstate(state):
- default_keywordmapper.setstate(state)
-def getstate():
- return default_keywordmapper.getstate()
-
-#
-# Consumers
-#
-
-class File(object):
- """ log consumer wrapping a file(-like) object """
- def __init__(self, f):
- assert hasattr(f, 'write')
- #assert isinstance(f, file) or not hasattr(f, 'open')
- self._file = f
-
- def __call__(self, msg):
- """ write a message to the log """
- self._file.write(str(msg) + "\n")
- if hasattr(self._file, 'flush'):
- self._file.flush()
-
-class Path(object):
- """ log consumer that opens and writes to a Path """
- def __init__(self, filename, append=False,
- delayed_create=False, buffering=False):
- self._append = append
- self._filename = str(filename)
- self._buffering = buffering
- if not delayed_create:
- self._openfile()
-
- def _openfile(self):
- mode = self._append and 'a' or 'w'
- f = open(self._filename, mode)
- self._file = f
-
- def __call__(self, msg):
- """ write a message to the log """
- if not hasattr(self, "_file"):
- self._openfile()
- self._file.write(str(msg) + "\n")
- if not self._buffering:
- self._file.flush()
-
-def STDOUT(msg):
- """ consumer that writes to sys.stdout """
- sys.stdout.write(str(msg)+"\n")
-
-def STDERR(msg):
- """ consumer that writes to sys.stderr """
- sys.stderr.write(str(msg)+"\n")
-
-class Syslog:
- """ consumer that writes to the syslog daemon """
-
- def __init__(self, priority = None):
- if priority is None:
- priority = self.LOG_INFO
- self.priority = priority
-
- def __call__(self, msg):
- """ write a message to the log """
- py.std.syslog.syslog(self.priority, str(msg))
-
-for _prio in "EMERG ALERT CRIT ERR WARNING NOTICE INFO DEBUG".split():
- _prio = "LOG_" + _prio
- try:
- setattr(Syslog, _prio, getattr(py.std.syslog, _prio))
- except AttributeError:
- pass
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_log/warning.py b/tests/wpt/web-platform-tests/tools/py/py/_log/warning.py
deleted file mode 100644
index 722e31e910d..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/py/_log/warning.py
+++ /dev/null
@@ -1,76 +0,0 @@
-import py, sys
-
-class DeprecationWarning(DeprecationWarning):
- def __init__(self, msg, path, lineno):
- self.msg = msg
- self.path = path
- self.lineno = lineno
- def __repr__(self):
- return "%s:%d: %s" %(self.path, self.lineno+1, self.msg)
- def __str__(self):
- return self.msg
-
-def _apiwarn(startversion, msg, stacklevel=2, function=None):
- # below is mostly COPIED from python2.4/warnings.py's def warn()
- # Get context information
- if isinstance(stacklevel, str):
- frame = sys._getframe(1)
- level = 1
- found = frame.f_code.co_filename.find(stacklevel) != -1
- while frame:
- co = frame.f_code
- if co.co_filename.find(stacklevel) == -1:
- if found:
- stacklevel = level
- break
- else:
- found = True
- level += 1
- frame = frame.f_back
- else:
- stacklevel = 1
- msg = "%s (since version %s)" %(msg, startversion)
- warn(msg, stacklevel=stacklevel+1, function=function)
-
-def warn(msg, stacklevel=1, function=None):
- if function is not None:
- filename = py.std.inspect.getfile(function)
- lineno = py.code.getrawcode(function).co_firstlineno
- else:
- try:
- caller = sys._getframe(stacklevel)
- except ValueError:
- globals = sys.__dict__
- lineno = 1
- else:
- globals = caller.f_globals
- lineno = caller.f_lineno
- if '__name__' in globals:
- module = globals['__name__']
- else:
- module = "<string>"
- filename = globals.get('__file__')
- if filename:
- fnl = filename.lower()
- if fnl.endswith(".pyc") or fnl.endswith(".pyo"):
- filename = filename[:-1]
- elif fnl.endswith("$py.class"):
- filename = filename.replace('$py.class', '.py')
- else:
- if module == "__main__":
- try:
- filename = sys.argv[0]
- except AttributeError:
- # embedded interpreters don't have sys.argv, see bug #839151
- filename = '__main__'
- if not filename:
- filename = module
- path = py.path.local(filename)
- warning = DeprecationWarning(msg, path, lineno)
- py.std.warnings.warn_explicit(warning, category=Warning,
- filename=str(warning.path),
- lineno=warning.lineno,
- registry=py.std.warnings.__dict__.setdefault(
- "__warningsregistry__", {})
- )
-
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_path/common.py b/tests/wpt/web-platform-tests/tools/py/py/_path/common.py
deleted file mode 100644
index d407434cb2a..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/py/_path/common.py
+++ /dev/null
@@ -1,403 +0,0 @@
-"""
-"""
-import os, sys, posixpath
-import py
-
-# Moved from local.py.
-iswin32 = sys.platform == "win32" or (getattr(os, '_name', False) == 'nt')
-
-class Checkers:
- _depend_on_existence = 'exists', 'link', 'dir', 'file'
-
- def __init__(self, path):
- self.path = path
-
- def dir(self):
- raise NotImplementedError
-
- def file(self):
- raise NotImplementedError
-
- def dotfile(self):
- return self.path.basename.startswith('.')
-
- def ext(self, arg):
- if not arg.startswith('.'):
- arg = '.' + arg
- return self.path.ext == arg
-
- def exists(self):
- raise NotImplementedError
-
- def basename(self, arg):
- return self.path.basename == arg
-
- def basestarts(self, arg):
- return self.path.basename.startswith(arg)
-
- def relto(self, arg):
- return self.path.relto(arg)
-
- def fnmatch(self, arg):
- return self.path.fnmatch(arg)
-
- def endswith(self, arg):
- return str(self.path).endswith(arg)
-
- def _evaluate(self, kw):
- for name, value in kw.items():
- invert = False
- meth = None
- try:
- meth = getattr(self, name)
- except AttributeError:
- if name[:3] == 'not':
- invert = True
- try:
- meth = getattr(self, name[3:])
- except AttributeError:
- pass
- if meth is None:
- raise TypeError(
- "no %r checker available for %r" % (name, self.path))
- try:
- if py.code.getrawcode(meth).co_argcount > 1:
- if (not meth(value)) ^ invert:
- return False
- else:
- if bool(value) ^ bool(meth()) ^ invert:
- return False
- except (py.error.ENOENT, py.error.ENOTDIR, py.error.EBUSY):
- # EBUSY feels not entirely correct,
- # but its kind of necessary since ENOMEDIUM
- # is not accessible in python
- for name in self._depend_on_existence:
- if name in kw:
- if kw.get(name):
- return False
- name = 'not' + name
- if name in kw:
- if not kw.get(name):
- return False
- return True
-
-class NeverRaised(Exception):
- pass
-
-class PathBase(object):
- """ shared implementation for filesystem path objects."""
- Checkers = Checkers
-
- def __div__(self, other):
- return self.join(str(other))
- __truediv__ = __div__ # py3k
-
- def basename(self):
- """ basename part of path. """
- return self._getbyspec('basename')[0]
- basename = property(basename, None, None, basename.__doc__)
-
- def dirname(self):
- """ dirname part of path. """
- return self._getbyspec('dirname')[0]
- dirname = property(dirname, None, None, dirname.__doc__)
-
- def purebasename(self):
- """ pure base name of the path."""
- return self._getbyspec('purebasename')[0]
- purebasename = property(purebasename, None, None, purebasename.__doc__)
-
- def ext(self):
- """ extension of the path (including the '.')."""
- return self._getbyspec('ext')[0]
- ext = property(ext, None, None, ext.__doc__)
-
- def dirpath(self, *args, **kwargs):
- """ return the directory path joined with any given path arguments. """
- return self.new(basename='').join(*args, **kwargs)
-
- def read_binary(self):
- """ read and return a bytestring from reading the path. """
- with self.open('rb') as f:
- return f.read()
-
- def read_text(self, encoding):
- """ read and return a Unicode string from reading the path. """
- with self.open("r", encoding=encoding) as f:
- return f.read()
-
-
- def read(self, mode='r'):
- """ read and return a bytestring from reading the path. """
- with self.open(mode) as f:
- return f.read()
-
- def readlines(self, cr=1):
- """ read and return a list of lines from the path. if cr is False, the
-newline will be removed from the end of each line. """
- if not cr:
- content = self.read('rU')
- return content.split('\n')
- else:
- f = self.open('rU')
- try:
- return f.readlines()
- finally:
- f.close()
-
- def load(self):
- """ (deprecated) return object unpickled from self.read() """
- f = self.open('rb')
- try:
- return py.error.checked_call(py.std.pickle.load, f)
- finally:
- f.close()
-
- def move(self, target):
- """ move this path to target. """
- if target.relto(self):
- raise py.error.EINVAL(target,
- "cannot move path into a subdirectory of itself")
- try:
- self.rename(target)
- except py.error.EXDEV: # invalid cross-device link
- self.copy(target)
- self.remove()
-
- def __repr__(self):
- """ return a string representation of this path. """
- return repr(str(self))
-
- def check(self, **kw):
- """ check a path for existence and properties.
-
- Without arguments, return True if the path exists, otherwise False.
-
- valid checkers::
-
- file=1 # is a file
- file=0 # is not a file (may not even exist)
- dir=1 # is a dir
- link=1 # is a link
- exists=1 # exists
-
- You can specify multiple checker definitions, for example::
-
- path.check(file=1, link=1) # a link pointing to a file
- """
- if not kw:
- kw = {'exists' : 1}
- return self.Checkers(self)._evaluate(kw)
-
- def fnmatch(self, pattern):
- """return true if the basename/fullname matches the glob-'pattern'.
-
- valid pattern characters::
-
- * matches everything
- ? matches any single character
- [seq] matches any character in seq
- [!seq] matches any char not in seq
-
- If the pattern contains a path-separator then the full path
- is used for pattern matching and a '*' is prepended to the
- pattern.
-
- if the pattern doesn't contain a path-separator the pattern
- is only matched against the basename.
- """
- return FNMatcher(pattern)(self)
-
- def relto(self, relpath):
- """ return a string which is the relative part of the path
- to the given 'relpath'.
- """
- if not isinstance(relpath, (str, PathBase)):
- raise TypeError("%r: not a string or path object" %(relpath,))
- strrelpath = str(relpath)
- if strrelpath and strrelpath[-1] != self.sep:
- strrelpath += self.sep
- #assert strrelpath[-1] == self.sep
- #assert strrelpath[-2] != self.sep
- strself = self.strpath
- if sys.platform == "win32" or getattr(os, '_name', None) == 'nt':
- if os.path.normcase(strself).startswith(
- os.path.normcase(strrelpath)):
- return strself[len(strrelpath):]
- elif strself.startswith(strrelpath):
- return strself[len(strrelpath):]
- return ""
-
- def ensure_dir(self, *args):
- """ ensure the path joined with args is a directory. """
- return self.ensure(*args, **{"dir": True})
-
- def bestrelpath(self, dest):
- """ return a string which is a relative path from self
- (assumed to be a directory) to dest such that
- self.join(bestrelpath) == dest and if not such
- path can be determined return dest.
- """
- try:
- if self == dest:
- return os.curdir
- base = self.common(dest)
- if not base: # can be the case on windows
- return str(dest)
- self2base = self.relto(base)
- reldest = dest.relto(base)
- if self2base:
- n = self2base.count(self.sep) + 1
- else:
- n = 0
- l = [os.pardir] * n
- if reldest:
- l.append(reldest)
- target = dest.sep.join(l)
- return target
- except AttributeError:
- return str(dest)
-
- def exists(self):
- return self.check()
-
- def isdir(self):
- return self.check(dir=1)
-
- def isfile(self):
- return self.check(file=1)
-
- def parts(self, reverse=False):
- """ return a root-first list of all ancestor directories
- plus the path itself.
- """
- current = self
- l = [self]
- while 1:
- last = current
- current = current.dirpath()
- if last == current:
- break
- l.append(current)
- if not reverse:
- l.reverse()
- return l
-
- def common(self, other):
- """ return the common part shared with the other path
- or None if there is no common part.
- """
- last = None
- for x, y in zip(self.parts(), other.parts()):
- if x != y:
- return last
- last = x
- return last
-
- def __add__(self, other):
- """ return new path object with 'other' added to the basename"""
- return self.new(basename=self.basename+str(other))
-
- def __cmp__(self, other):
- """ return sort value (-1, 0, +1). """
- try:
- return cmp(self.strpath, other.strpath)
- except AttributeError:
- return cmp(str(self), str(other)) # self.path, other.path)
-
- def __lt__(self, other):
- try:
- return self.strpath < other.strpath
- except AttributeError:
- return str(self) < str(other)
-
- def visit(self, fil=None, rec=None, ignore=NeverRaised, bf=False, sort=False):
- """ yields all paths below the current one
-
- fil is a filter (glob pattern or callable), if not matching the
- path will not be yielded, defaulting to None (everything is
- returned)
-
- rec is a filter (glob pattern or callable) that controls whether
- a node is descended, defaulting to None
-
- ignore is an Exception class that is ignoredwhen calling dirlist()
- on any of the paths (by default, all exceptions are reported)
-
- bf if True will cause a breadthfirst search instead of the
- default depthfirst. Default: False
-
- sort if True will sort entries within each directory level.
- """
- for x in Visitor(fil, rec, ignore, bf, sort).gen(self):
- yield x
-
- def _sortlist(self, res, sort):
- if sort:
- if hasattr(sort, '__call__'):
- res.sort(sort)
- else:
- res.sort()
-
- def samefile(self, other):
- """ return True if other refers to the same stat object as self. """
- return self.strpath == str(other)
-
-class Visitor:
- def __init__(self, fil, rec, ignore, bf, sort):
- if isinstance(fil, str):
- fil = FNMatcher(fil)
- if isinstance(rec, str):
- self.rec = FNMatcher(rec)
- elif not hasattr(rec, '__call__') and rec:
- self.rec = lambda path: True
- else:
- self.rec = rec
- self.fil = fil
- self.ignore = ignore
- self.breadthfirst = bf
- self.optsort = sort and sorted or (lambda x: x)
-
- def gen(self, path):
- try:
- entries = path.listdir()
- except self.ignore:
- return
- rec = self.rec
- dirs = self.optsort([p for p in entries
- if p.check(dir=1) and (rec is None or rec(p))])
- if not self.breadthfirst:
- for subdir in dirs:
- for p in self.gen(subdir):
- yield p
- for p in self.optsort(entries):
- if self.fil is None or self.fil(p):
- yield p
- if self.breadthfirst:
- for subdir in dirs:
- for p in self.gen(subdir):
- yield p
-
-class FNMatcher:
- def __init__(self, pattern):
- self.pattern = pattern
-
- def __call__(self, path):
- pattern = self.pattern
-
- if (pattern.find(path.sep) == -1 and
- iswin32 and
- pattern.find(posixpath.sep) != -1):
- # Running on Windows, the pattern has no Windows path separators,
- # and the pattern has one or more Posix path separators. Replace
- # the Posix path separators with the Windows path separator.
- pattern = pattern.replace(posixpath.sep, path.sep)
-
- if pattern.find(path.sep) == -1:
- name = path.basename
- else:
- name = str(path) # path.strpath # XXX svn?
- if not os.path.isabs(pattern):
- pattern = '*' + path.sep + pattern
- return py.std.fnmatch.fnmatch(name, pattern)
-
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_path/local.py b/tests/wpt/web-platform-tests/tools/py/py/_path/local.py
deleted file mode 100644
index d569404ec21..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/py/_path/local.py
+++ /dev/null
@@ -1,911 +0,0 @@
-"""
-local path implementation.
-"""
-from __future__ import with_statement
-
-from contextlib import contextmanager
-import sys, os, re, atexit, io
-import py
-from py._path import common
-from py._path.common import iswin32
-from stat import S_ISLNK, S_ISDIR, S_ISREG
-
-from os.path import abspath, normpath, isabs, exists, isdir, isfile, islink, dirname
-
-if sys.version_info > (3,0):
- def map_as_list(func, iter):
- return list(map(func, iter))
-else:
- map_as_list = map
-
-class Stat(object):
- def __getattr__(self, name):
- return getattr(self._osstatresult, "st_" + name)
-
- def __init__(self, path, osstatresult):
- self.path = path
- self._osstatresult = osstatresult
-
- @property
- def owner(self):
- if iswin32:
- raise NotImplementedError("XXX win32")
- import pwd
- entry = py.error.checked_call(pwd.getpwuid, self.uid)
- return entry[0]
-
- @property
- def group(self):
- """ return group name of file. """
- if iswin32:
- raise NotImplementedError("XXX win32")
- import grp
- entry = py.error.checked_call(grp.getgrgid, self.gid)
- return entry[0]
-
- def isdir(self):
- return S_ISDIR(self._osstatresult.st_mode)
-
- def isfile(self):
- return S_ISREG(self._osstatresult.st_mode)
-
- def islink(self):
- st = self.path.lstat()
- return S_ISLNK(self._osstatresult.st_mode)
-
-class PosixPath(common.PathBase):
- def chown(self, user, group, rec=0):
- """ change ownership to the given user and group.
- user and group may be specified by a number or
- by a name. if rec is True change ownership
- recursively.
- """
- uid = getuserid(user)
- gid = getgroupid(group)
- if rec:
- for x in self.visit(rec=lambda x: x.check(link=0)):
- if x.check(link=0):
- py.error.checked_call(os.chown, str(x), uid, gid)
- py.error.checked_call(os.chown, str(self), uid, gid)
-
- def readlink(self):
- """ return value of a symbolic link. """
- return py.error.checked_call(os.readlink, self.strpath)
-
- def mklinkto(self, oldname):
- """ posix style hard link to another name. """
- py.error.checked_call(os.link, str(oldname), str(self))
-
- def mksymlinkto(self, value, absolute=1):
- """ create a symbolic link with the given value (pointing to another name). """
- if absolute:
- py.error.checked_call(os.symlink, str(value), self.strpath)
- else:
- base = self.common(value)
- # with posix local paths '/' is always a common base
- relsource = self.__class__(value).relto(base)
- reldest = self.relto(base)
- n = reldest.count(self.sep)
- target = self.sep.join(('..', )*n + (relsource, ))
- py.error.checked_call(os.symlink, target, self.strpath)
-
-def getuserid(user):
- import pwd
- if not isinstance(user, int):
- user = pwd.getpwnam(user)[2]
- return user
-
-def getgroupid(group):
- import grp
- if not isinstance(group, int):
- group = grp.getgrnam(group)[2]
- return group
-
-FSBase = not iswin32 and PosixPath or common.PathBase
-
-class LocalPath(FSBase):
- """ object oriented interface to os.path and other local filesystem
- related information.
- """
- class ImportMismatchError(ImportError):
- """ raised on pyimport() if there is a mismatch of __file__'s"""
-
- sep = os.sep
- class Checkers(common.Checkers):
- def _stat(self):
- try:
- return self._statcache
- except AttributeError:
- try:
- self._statcache = self.path.stat()
- except py.error.ELOOP:
- self._statcache = self.path.lstat()
- return self._statcache
-
- def dir(self):
- return S_ISDIR(self._stat().mode)
-
- def file(self):
- return S_ISREG(self._stat().mode)
-
- def exists(self):
- return self._stat()
-
- def link(self):
- st = self.path.lstat()
- return S_ISLNK(st.mode)
-
- def __init__(self, path=None, expanduser=False):
- """ Initialize and return a local Path instance.
-
- Path can be relative to the current directory.
- If path is None it defaults to the current working directory.
- If expanduser is True, tilde-expansion is performed.
- Note that Path instances always carry an absolute path.
- Note also that passing in a local path object will simply return
- the exact same path object. Use new() to get a new copy.
- """
- if path is None:
- self.strpath = py.error.checked_call(os.getcwd)
- elif isinstance(path, common.PathBase):
- self.strpath = path.strpath
- elif isinstance(path, py.builtin._basestring):
- if expanduser:
- path = os.path.expanduser(path)
- self.strpath = abspath(path)
- else:
- raise ValueError("can only pass None, Path instances "
- "or non-empty strings to LocalPath")
-
- def __hash__(self):
- return hash(self.strpath)
-
- def __eq__(self, other):
- s1 = self.strpath
- s2 = getattr(other, "strpath", other)
- if iswin32:
- s1 = s1.lower()
- try:
- s2 = s2.lower()
- except AttributeError:
- return False
- return s1 == s2
-
- def __ne__(self, other):
- return not (self == other)
-
- def __lt__(self, other):
- return self.strpath < getattr(other, "strpath", other)
-
- def __gt__(self, other):
- return self.strpath > getattr(other, "strpath", other)
-
- def samefile(self, other):
- """ return True if 'other' references the same file as 'self'.
- """
- other = getattr(other, "strpath", other)
- if not isabs(other):
- other = abspath(other)
- if self == other:
- return True
- if iswin32:
- return False # there is no samefile
- return py.error.checked_call(
- os.path.samefile, self.strpath, other)
-
- def remove(self, rec=1, ignore_errors=False):
- """ remove a file or directory (or a directory tree if rec=1).
- if ignore_errors is True, errors while removing directories will
- be ignored.
- """
- if self.check(dir=1, link=0):
- if rec:
- # force remove of readonly files on windows
- if iswin32:
- self.chmod(448, rec=1) # octcal 0700
- py.error.checked_call(py.std.shutil.rmtree, self.strpath,
- ignore_errors=ignore_errors)
- else:
- py.error.checked_call(os.rmdir, self.strpath)
- else:
- if iswin32:
- self.chmod(448) # octcal 0700
- py.error.checked_call(os.remove, self.strpath)
-
- def computehash(self, hashtype="md5", chunksize=524288):
- """ return hexdigest of hashvalue for this file. """
- try:
- try:
- import hashlib as mod
- except ImportError:
- if hashtype == "sha1":
- hashtype = "sha"
- mod = __import__(hashtype)
- hash = getattr(mod, hashtype)()
- except (AttributeError, ImportError):
- raise ValueError("Don't know how to compute %r hash" %(hashtype,))
- f = self.open('rb')
- try:
- while 1:
- buf = f.read(chunksize)
- if not buf:
- return hash.hexdigest()
- hash.update(buf)
- finally:
- f.close()
-
- def new(self, **kw):
- """ create a modified version of this path.
- the following keyword arguments modify various path parts::
-
- a:/some/path/to/a/file.ext
- xx drive
- xxxxxxxxxxxxxxxxx dirname
- xxxxxxxx basename
- xxxx purebasename
- xxx ext
- """
- obj = object.__new__(self.__class__)
- if not kw:
- obj.strpath = self.strpath
- return obj
- drive, dirname, basename, purebasename,ext = self._getbyspec(
- "drive,dirname,basename,purebasename,ext")
- if 'basename' in kw:
- if 'purebasename' in kw or 'ext' in kw:
- raise ValueError("invalid specification %r" % kw)
- else:
- pb = kw.setdefault('purebasename', purebasename)
- try:
- ext = kw['ext']
- except KeyError:
- pass
- else:
- if ext and not ext.startswith('.'):
- ext = '.' + ext
- kw['basename'] = pb + ext
-
- if ('dirname' in kw and not kw['dirname']):
- kw['dirname'] = drive
- else:
- kw.setdefault('dirname', dirname)
- kw.setdefault('sep', self.sep)
- obj.strpath = normpath(
- "%(dirname)s%(sep)s%(basename)s" % kw)
- return obj
-
- def _getbyspec(self, spec):
- """ see new for what 'spec' can be. """
- res = []
- parts = self.strpath.split(self.sep)
-
- args = filter(None, spec.split(',') )
- append = res.append
- for name in args:
- if name == 'drive':
- append(parts[0])
- elif name == 'dirname':
- append(self.sep.join(parts[:-1]))
- else:
- basename = parts[-1]
- if name == 'basename':
- append(basename)
- else:
- i = basename.rfind('.')
- if i == -1:
- purebasename, ext = basename, ''
- else:
- purebasename, ext = basename[:i], basename[i:]
- if name == 'purebasename':
- append(purebasename)
- elif name == 'ext':
- append(ext)
- else:
- raise ValueError("invalid part specification %r" % name)
- return res
-
- def dirpath(self, *args, **kwargs):
- """ return the directory path joined with any given path arguments. """
- if not kwargs:
- path = object.__new__(self.__class__)
- path.strpath = dirname(self.strpath)
- if args:
- path = path.join(*args)
- return path
- return super(LocalPath, self).dirpath(*args, **kwargs)
-
- def join(self, *args, **kwargs):
- """ return a new path by appending all 'args' as path
- components. if abs=1 is used restart from root if any
- of the args is an absolute path.
- """
- sep = self.sep
- strargs = [getattr(arg, "strpath", arg) for arg in args]
- strpath = self.strpath
- if kwargs.get('abs'):
- newargs = []
- for arg in reversed(strargs):
- if isabs(arg):
- strpath = arg
- strargs = newargs
- break
- newargs.insert(0, arg)
- for arg in strargs:
- arg = arg.strip(sep)
- if iswin32:
- # allow unix style paths even on windows.
- arg = arg.strip('/')
- arg = arg.replace('/', sep)
- strpath = strpath + sep + arg
- obj = object.__new__(self.__class__)
- obj.strpath = normpath(strpath)
- return obj
-
- def open(self, mode='r', ensure=False, encoding=None):
- """ return an opened file with the given mode.
-
- If ensure is True, create parent directories if needed.
- """
- if ensure:
- self.dirpath().ensure(dir=1)
- if encoding:
- return py.error.checked_call(io.open, self.strpath, mode, encoding=encoding)
- return py.error.checked_call(open, self.strpath, mode)
-
- def _fastjoin(self, name):
- child = object.__new__(self.__class__)
- child.strpath = self.strpath + self.sep + name
- return child
-
- def islink(self):
- return islink(self.strpath)
-
- def check(self, **kw):
- if not kw:
- return exists(self.strpath)
- if len(kw) == 1:
- if "dir" in kw:
- return not kw["dir"] ^ isdir(self.strpath)
- if "file" in kw:
- return not kw["file"] ^ isfile(self.strpath)
- return super(LocalPath, self).check(**kw)
-
- _patternchars = set("*?[" + os.path.sep)
- def listdir(self, fil=None, sort=None):
- """ list directory contents, possibly filter by the given fil func
- and possibly sorted.
- """
- if fil is None and sort is None:
- names = py.error.checked_call(os.listdir, self.strpath)
- return map_as_list(self._fastjoin, names)
- if isinstance(fil, py.builtin._basestring):
- if not self._patternchars.intersection(fil):
- child = self._fastjoin(fil)
- if exists(child.strpath):
- return [child]
- return []
- fil = common.FNMatcher(fil)
- names = py.error.checked_call(os.listdir, self.strpath)
- res = []
- for name in names:
- child = self._fastjoin(name)
- if fil is None or fil(child):
- res.append(child)
- self._sortlist(res, sort)
- return res
-
- def size(self):
- """ return size of the underlying file object """
- return self.stat().size
-
- def mtime(self):
- """ return last modification time of the path. """
- return self.stat().mtime
-
- def copy(self, target, mode=False):
- """ copy path to target."""
- if self.check(file=1):
- if target.check(dir=1):
- target = target.join(self.basename)
- assert self!=target
- copychunked(self, target)
- if mode:
- copymode(self.strpath, target.strpath)
- else:
- def rec(p):
- return p.check(link=0)
- for x in self.visit(rec=rec):
- relpath = x.relto(self)
- newx = target.join(relpath)
- newx.dirpath().ensure(dir=1)
- if x.check(link=1):
- newx.mksymlinkto(x.readlink())
- continue
- elif x.check(file=1):
- copychunked(x, newx)
- elif x.check(dir=1):
- newx.ensure(dir=1)
- if mode:
- copymode(x.strpath, newx.strpath)
-
- def rename(self, target):
- """ rename this path to target. """
- target = getattr(target, "strpath", target)
- return py.error.checked_call(os.rename, self.strpath, target)
-
- def dump(self, obj, bin=1):
- """ pickle object into path location"""
- f = self.open('wb')
- try:
- py.error.checked_call(py.std.pickle.dump, obj, f, bin)
- finally:
- f.close()
-
- def mkdir(self, *args):
- """ create & return the directory joined with args. """
- p = self.join(*args)
- py.error.checked_call(os.mkdir, getattr(p, "strpath", p))
- return p
-
- def write_binary(self, data, ensure=False):
- """ write binary data into path. If ensure is True create
- missing parent directories.
- """
- if ensure:
- self.dirpath().ensure(dir=1)
- with self.open('wb') as f:
- f.write(data)
-
- def write_text(self, data, encoding, ensure=False):
- """ write text data into path using the specified encoding.
- If ensure is True create missing parent directories.
- """
- if ensure:
- self.dirpath().ensure(dir=1)
- with self.open('w', encoding=encoding) as f:
- f.write(data)
-
- def write(self, data, mode='w', ensure=False):
- """ write data into path. If ensure is True create
- missing parent directories.
- """
- if ensure:
- self.dirpath().ensure(dir=1)
- if 'b' in mode:
- if not py.builtin._isbytes(data):
- raise ValueError("can only process bytes")
- else:
- if not py.builtin._istext(data):
- if not py.builtin._isbytes(data):
- data = str(data)
- else:
- data = py.builtin._totext(data, sys.getdefaultencoding())
- f = self.open(mode)
- try:
- f.write(data)
- finally:
- f.close()
-
- def _ensuredirs(self):
- parent = self.dirpath()
- if parent == self:
- return self
- if parent.check(dir=0):
- parent._ensuredirs()
- if self.check(dir=0):
- try:
- self.mkdir()
- except py.error.EEXIST:
- # race condition: file/dir created by another thread/process.
- # complain if it is not a dir
- if self.check(dir=0):
- raise
- return self
-
- def ensure(self, *args, **kwargs):
- """ ensure that an args-joined path exists (by default as
- a file). if you specify a keyword argument 'dir=True'
- then the path is forced to be a directory path.
- """
- p = self.join(*args)
- if kwargs.get('dir', 0):
- return p._ensuredirs()
- else:
- p.dirpath()._ensuredirs()
- if not p.check(file=1):
- p.open('w').close()
- return p
-
- def stat(self, raising=True):
- """ Return an os.stat() tuple. """
- if raising == True:
- return Stat(self, py.error.checked_call(os.stat, self.strpath))
- try:
- return Stat(self, os.stat(self.strpath))
- except KeyboardInterrupt:
- raise
- except Exception:
- return None
-
- def lstat(self):
- """ Return an os.lstat() tuple. """
- return Stat(self, py.error.checked_call(os.lstat, self.strpath))
-
- def setmtime(self, mtime=None):
- """ set modification time for the given path. if 'mtime' is None
- (the default) then the file's mtime is set to current time.
-
- Note that the resolution for 'mtime' is platform dependent.
- """
- if mtime is None:
- return py.error.checked_call(os.utime, self.strpath, mtime)
- try:
- return py.error.checked_call(os.utime, self.strpath, (-1, mtime))
- except py.error.EINVAL:
- return py.error.checked_call(os.utime, self.strpath, (self.atime(), mtime))
-
- def chdir(self):
- """ change directory to self and return old current directory """
- try:
- old = self.__class__()
- except py.error.ENOENT:
- old = None
- py.error.checked_call(os.chdir, self.strpath)
- return old
-
-
- @contextmanager
- def as_cwd(self):
- """ return context manager which changes to current dir during the
- managed "with" context. On __enter__ it returns the old dir.
- """
- old = self.chdir()
- try:
- yield old
- finally:
- old.chdir()
-
- def realpath(self):
- """ return a new path which contains no symbolic links."""
- return self.__class__(os.path.realpath(self.strpath))
-
- def atime(self):
- """ return last access time of the path. """
- return self.stat().atime
-
- def __repr__(self):
- return 'local(%r)' % self.strpath
-
- def __str__(self):
- """ return string representation of the Path. """
- return self.strpath
-
- def chmod(self, mode, rec=0):
- """ change permissions to the given mode. If mode is an
- integer it directly encodes the os-specific modes.
- if rec is True perform recursively.
- """
- if not isinstance(mode, int):
- raise TypeError("mode %r must be an integer" % (mode,))
- if rec:
- for x in self.visit(rec=rec):
- py.error.checked_call(os.chmod, str(x), mode)
- py.error.checked_call(os.chmod, self.strpath, mode)
-
- def pypkgpath(self):
- """ return the Python package path by looking for the last
- directory upwards which still contains an __init__.py.
- Return None if a pkgpath can not be determined.
- """
- pkgpath = None
- for parent in self.parts(reverse=True):
- if parent.isdir():
- if not parent.join('__init__.py').exists():
- break
- if not isimportable(parent.basename):
- break
- pkgpath = parent
- return pkgpath
-
- def _ensuresyspath(self, ensuremode, path):
- if ensuremode:
- s = str(path)
- if ensuremode == "append":
- if s not in sys.path:
- sys.path.append(s)
- else:
- if s != sys.path[0]:
- sys.path.insert(0, s)
-
- def pyimport(self, modname=None, ensuresyspath=True):
- """ return path as an imported python module.
-
- If modname is None, look for the containing package
- and construct an according module name.
- The module will be put/looked up in sys.modules.
- if ensuresyspath is True then the root dir for importing
- the file (taking __init__.py files into account) will
- be prepended to sys.path if it isn't there already.
- If ensuresyspath=="append" the root dir will be appended
- if it isn't already contained in sys.path.
- if ensuresyspath is False no modification of syspath happens.
- """
- if not self.check():
- raise py.error.ENOENT(self)
-
- pkgpath = None
- if modname is None:
- pkgpath = self.pypkgpath()
- if pkgpath is not None:
- pkgroot = pkgpath.dirpath()
- names = self.new(ext="").relto(pkgroot).split(self.sep)
- if names[-1] == "__init__":
- names.pop()
- modname = ".".join(names)
- else:
- pkgroot = self.dirpath()
- modname = self.purebasename
-
- self._ensuresyspath(ensuresyspath, pkgroot)
- __import__(modname)
- mod = sys.modules[modname]
- if self.basename == "__init__.py":
- return mod # we don't check anything as we might
- # we in a namespace package ... too icky to check
- modfile = mod.__file__
- if modfile[-4:] in ('.pyc', '.pyo'):
- modfile = modfile[:-1]
- elif modfile.endswith('$py.class'):
- modfile = modfile[:-9] + '.py'
- if modfile.endswith(os.path.sep + "__init__.py"):
- if self.basename != "__init__.py":
- modfile = modfile[:-12]
- try:
- issame = self.samefile(modfile)
- except py.error.ENOENT:
- issame = False
- if not issame:
- raise self.ImportMismatchError(modname, modfile, self)
- return mod
- else:
- try:
- return sys.modules[modname]
- except KeyError:
- # we have a custom modname, do a pseudo-import
- mod = py.std.types.ModuleType(modname)
- mod.__file__ = str(self)
- sys.modules[modname] = mod
- try:
- py.builtin.execfile(str(self), mod.__dict__)
- except:
- del sys.modules[modname]
- raise
- return mod
-
- def sysexec(self, *argv, **popen_opts):
- """ return stdout text from executing a system child process,
- where the 'self' path points to executable.
- The process is directly invoked and not through a system shell.
- """
- from subprocess import Popen, PIPE
- argv = map_as_list(str, argv)
- popen_opts['stdout'] = popen_opts['stderr'] = PIPE
- proc = Popen([str(self)] + argv, **popen_opts)
- stdout, stderr = proc.communicate()
- ret = proc.wait()
- if py.builtin._isbytes(stdout):
- stdout = py.builtin._totext(stdout, sys.getdefaultencoding())
- if ret != 0:
- if py.builtin._isbytes(stderr):
- stderr = py.builtin._totext(stderr, sys.getdefaultencoding())
- raise py.process.cmdexec.Error(ret, ret, str(self),
- stdout, stderr,)
- return stdout
-
- def sysfind(cls, name, checker=None, paths=None):
- """ return a path object found by looking at the systems
- underlying PATH specification. If the checker is not None
- it will be invoked to filter matching paths. If a binary
- cannot be found, None is returned
- Note: This is probably not working on plain win32 systems
- but may work on cygwin.
- """
- if isabs(name):
- p = py.path.local(name)
- if p.check(file=1):
- return p
- else:
- if paths is None:
- if iswin32:
- paths = py.std.os.environ['Path'].split(';')
- if '' not in paths and '.' not in paths:
- paths.append('.')
- try:
- systemroot = os.environ['SYSTEMROOT']
- except KeyError:
- pass
- else:
- paths = [re.sub('%SystemRoot%', systemroot, path)
- for path in paths]
- else:
- paths = py.std.os.environ['PATH'].split(':')
- tryadd = []
- if iswin32:
- tryadd += os.environ['PATHEXT'].split(os.pathsep)
- tryadd.append("")
-
- for x in paths:
- for addext in tryadd:
- p = py.path.local(x).join(name, abs=True) + addext
- try:
- if p.check(file=1):
- if checker:
- if not checker(p):
- continue
- return p
- except py.error.EACCES:
- pass
- return None
- sysfind = classmethod(sysfind)
-
- def _gethomedir(cls):
- try:
- x = os.environ['HOME']
- except KeyError:
- try:
- x = os.environ["HOMEDRIVE"] + os.environ['HOMEPATH']
- except KeyError:
- return None
- return cls(x)
- _gethomedir = classmethod(_gethomedir)
-
- #"""
- #special class constructors for local filesystem paths
- #"""
- def get_temproot(cls):
- """ return the system's temporary directory
- (where tempfiles are usually created in)
- """
- return py.path.local(py.std.tempfile.gettempdir())
- get_temproot = classmethod(get_temproot)
-
- def mkdtemp(cls, rootdir=None):
- """ return a Path object pointing to a fresh new temporary directory
- (which we created ourself).
- """
- import tempfile
- if rootdir is None:
- rootdir = cls.get_temproot()
- return cls(py.error.checked_call(tempfile.mkdtemp, dir=str(rootdir)))
- mkdtemp = classmethod(mkdtemp)
-
- def make_numbered_dir(cls, prefix='session-', rootdir=None, keep=3,
- lock_timeout = 172800): # two days
- """ return unique directory with a number greater than the current
- maximum one. The number is assumed to start directly after prefix.
- if keep is true directories with a number less than (maxnum-keep)
- will be removed.
- """
- if rootdir is None:
- rootdir = cls.get_temproot()
-
- def parse_num(path):
- """ parse the number out of a path (if it matches the prefix) """
- bn = path.basename
- if bn.startswith(prefix):
- try:
- return int(bn[len(prefix):])
- except ValueError:
- pass
-
- # compute the maximum number currently in use with the
- # prefix
- lastmax = None
- while True:
- maxnum = -1
- for path in rootdir.listdir():
- num = parse_num(path)
- if num is not None:
- maxnum = max(maxnum, num)
-
- # make the new directory
- try:
- udir = rootdir.mkdir(prefix + str(maxnum+1))
- except py.error.EEXIST:
- # race condition: another thread/process created the dir
- # in the meantime. Try counting again
- if lastmax == maxnum:
- raise
- lastmax = maxnum
- continue
- break
-
- # put a .lock file in the new directory that will be removed at
- # process exit
- if lock_timeout:
- lockfile = udir.join('.lock')
- mypid = os.getpid()
- if hasattr(lockfile, 'mksymlinkto'):
- lockfile.mksymlinkto(str(mypid))
- else:
- lockfile.write(str(mypid))
- def try_remove_lockfile():
- # in a fork() situation, only the last process should
- # remove the .lock, otherwise the other processes run the
- # risk of seeing their temporary dir disappear. For now
- # we remove the .lock in the parent only (i.e. we assume
- # that the children finish before the parent).
- if os.getpid() != mypid:
- return
- try:
- lockfile.remove()
- except py.error.Error:
- pass
- atexit.register(try_remove_lockfile)
-
- # prune old directories
- if keep:
- for path in rootdir.listdir():
- num = parse_num(path)
- if num is not None and num <= (maxnum - keep):
- lf = path.join('.lock')
- try:
- t1 = lf.lstat().mtime
- t2 = lockfile.lstat().mtime
- if not lock_timeout or abs(t2-t1) < lock_timeout:
- continue # skip directories still locked
- except py.error.Error:
- pass # assume that it means that there is no 'lf'
- try:
- path.remove(rec=1)
- except KeyboardInterrupt:
- raise
- except: # this might be py.error.Error, WindowsError ...
- pass
-
- # make link...
- try:
- username = os.environ['USER'] #linux, et al
- except KeyError:
- try:
- username = os.environ['USERNAME'] #windows
- except KeyError:
- username = 'current'
-
- src = str(udir)
- dest = src[:src.rfind('-')] + '-' + username
- try:
- os.unlink(dest)
- except OSError:
- pass
- try:
- os.symlink(src, dest)
- except (OSError, AttributeError, NotImplementedError):
- pass
-
- return udir
- make_numbered_dir = classmethod(make_numbered_dir)
-
-def copymode(src, dest):
- py.std.shutil.copymode(src, dest)
-
-def copychunked(src, dest):
- chunksize = 524288 # half a meg of bytes
- fsrc = src.open('rb')
- try:
- fdest = dest.open('wb')
- try:
- while 1:
- buf = fsrc.read(chunksize)
- if not buf:
- break
- fdest.write(buf)
- finally:
- fdest.close()
- finally:
- fsrc.close()
-
-def isimportable(name):
- if name and (name[0].isalpha() or name[0] == '_'):
- name = name.replace("_", '')
- return not name or name.isalnum()
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_path/svnurl.py b/tests/wpt/web-platform-tests/tools/py/py/_path/svnurl.py
deleted file mode 100644
index 78d71317ac0..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/py/_path/svnurl.py
+++ /dev/null
@@ -1,380 +0,0 @@
-"""
-module defining a subversion path object based on the external
-command 'svn'. This modules aims to work with svn 1.3 and higher
-but might also interact well with earlier versions.
-"""
-
-import os, sys, time, re
-import py
-from py import path, process
-from py._path import common
-from py._path import svnwc as svncommon
-from py._path.cacheutil import BuildcostAccessCache, AgingCache
-
-DEBUG=False
-
-class SvnCommandPath(svncommon.SvnPathBase):
- """ path implementation that offers access to (possibly remote) subversion
- repositories. """
-
- _lsrevcache = BuildcostAccessCache(maxentries=128)
- _lsnorevcache = AgingCache(maxentries=1000, maxseconds=60.0)
-
- def __new__(cls, path, rev=None, auth=None):
- self = object.__new__(cls)
- if isinstance(path, cls):
- rev = path.rev
- auth = path.auth
- path = path.strpath
- svncommon.checkbadchars(path)
- path = path.rstrip('/')
- self.strpath = path
- self.rev = rev
- self.auth = auth
- return self
-
- def __repr__(self):
- if self.rev == -1:
- return 'svnurl(%r)' % self.strpath
- else:
- return 'svnurl(%r, %r)' % (self.strpath, self.rev)
-
- def _svnwithrev(self, cmd, *args):
- """ execute an svn command, append our own url and revision """
- if self.rev is None:
- return self._svnwrite(cmd, *args)
- else:
- args = ['-r', self.rev] + list(args)
- return self._svnwrite(cmd, *args)
-
- def _svnwrite(self, cmd, *args):
- """ execute an svn command, append our own url """
- l = ['svn %s' % cmd]
- args = ['"%s"' % self._escape(item) for item in args]
- l.extend(args)
- l.append('"%s"' % self._encodedurl())
- # fixing the locale because we can't otherwise parse
- string = " ".join(l)
- if DEBUG:
- print("execing %s" % string)
- out = self._svncmdexecauth(string)
- return out
-
- def _svncmdexecauth(self, cmd):
- """ execute an svn command 'as is' """
- cmd = svncommon.fixlocale() + cmd
- if self.auth is not None:
- cmd += ' ' + self.auth.makecmdoptions()
- return self._cmdexec(cmd)
-
- def _cmdexec(self, cmd):
- try:
- out = process.cmdexec(cmd)
- except py.process.cmdexec.Error:
- e = sys.exc_info()[1]
- if (e.err.find('File Exists') != -1 or
- e.err.find('File already exists') != -1):
- raise py.error.EEXIST(self)
- raise
- return out
-
- def _svnpopenauth(self, cmd):
- """ execute an svn command, return a pipe for reading stdin """
- cmd = svncommon.fixlocale() + cmd
- if self.auth is not None:
- cmd += ' ' + self.auth.makecmdoptions()
- return self._popen(cmd)
-
- def _popen(self, cmd):
- return os.popen(cmd)
-
- def _encodedurl(self):
- return self._escape(self.strpath)
-
- def _norev_delentry(self, path):
- auth = self.auth and self.auth.makecmdoptions() or None
- self._lsnorevcache.delentry((str(path), auth))
-
- def open(self, mode='r'):
- """ return an opened file with the given mode. """
- if mode not in ("r", "rU",):
- raise ValueError("mode %r not supported" % (mode,))
- assert self.check(file=1) # svn cat returns an empty file otherwise
- if self.rev is None:
- return self._svnpopenauth('svn cat "%s"' % (
- self._escape(self.strpath), ))
- else:
- return self._svnpopenauth('svn cat -r %s "%s"' % (
- self.rev, self._escape(self.strpath)))
-
- def dirpath(self, *args, **kwargs):
- """ return the directory path of the current path joined
- with any given path arguments.
- """
- l = self.strpath.split(self.sep)
- if len(l) < 4:
- raise py.error.EINVAL(self, "base is not valid")
- elif len(l) == 4:
- return self.join(*args, **kwargs)
- else:
- return self.new(basename='').join(*args, **kwargs)
-
- # modifying methods (cache must be invalidated)
- def mkdir(self, *args, **kwargs):
- """ create & return the directory joined with args.
- pass a 'msg' keyword argument to set the commit message.
- """
- commit_msg = kwargs.get('msg', "mkdir by py lib invocation")
- createpath = self.join(*args)
- createpath._svnwrite('mkdir', '-m', commit_msg)
- self._norev_delentry(createpath.dirpath())
- return createpath
-
- def copy(self, target, msg='copied by py lib invocation'):
- """ copy path to target with checkin message msg."""
- if getattr(target, 'rev', None) is not None:
- raise py.error.EINVAL(target, "revisions are immutable")
- self._svncmdexecauth('svn copy -m "%s" "%s" "%s"' %(msg,
- self._escape(self), self._escape(target)))
- self._norev_delentry(target.dirpath())
-
- def rename(self, target, msg="renamed by py lib invocation"):
- """ rename this path to target with checkin message msg. """
- if getattr(self, 'rev', None) is not None:
- raise py.error.EINVAL(self, "revisions are immutable")
- self._svncmdexecauth('svn move -m "%s" --force "%s" "%s"' %(
- msg, self._escape(self), self._escape(target)))
- self._norev_delentry(self.dirpath())
- self._norev_delentry(self)
-
- def remove(self, rec=1, msg='removed by py lib invocation'):
- """ remove a file or directory (or a directory tree if rec=1) with
-checkin message msg."""
- if self.rev is not None:
- raise py.error.EINVAL(self, "revisions are immutable")
- self._svncmdexecauth('svn rm -m "%s" "%s"' %(msg, self._escape(self)))
- self._norev_delentry(self.dirpath())
-
- def export(self, topath):
- """ export to a local path
-
- topath should not exist prior to calling this, returns a
- py.path.local instance
- """
- topath = py.path.local(topath)
- args = ['"%s"' % (self._escape(self),),
- '"%s"' % (self._escape(topath),)]
- if self.rev is not None:
- args = ['-r', str(self.rev)] + args
- self._svncmdexecauth('svn export %s' % (' '.join(args),))
- return topath
-
- def ensure(self, *args, **kwargs):
- """ ensure that an args-joined path exists (by default as
- a file). If you specify a keyword argument 'dir=True'
- then the path is forced to be a directory path.
- """
- if getattr(self, 'rev', None) is not None:
- raise py.error.EINVAL(self, "revisions are immutable")
- target = self.join(*args)
- dir = kwargs.get('dir', 0)
- for x in target.parts(reverse=True):
- if x.check():
- break
- else:
- raise py.error.ENOENT(target, "has not any valid base!")
- if x == target:
- if not x.check(dir=dir):
- raise dir and py.error.ENOTDIR(x) or py.error.EISDIR(x)
- return x
- tocreate = target.relto(x)
- basename = tocreate.split(self.sep, 1)[0]
- tempdir = py.path.local.mkdtemp()
- try:
- tempdir.ensure(tocreate, dir=dir)
- cmd = 'svn import -m "%s" "%s" "%s"' % (
- "ensure %s" % self._escape(tocreate),
- self._escape(tempdir.join(basename)),
- x.join(basename)._encodedurl())
- self._svncmdexecauth(cmd)
- self._norev_delentry(x)
- finally:
- tempdir.remove()
- return target
-
- # end of modifying methods
- def _propget(self, name):
- res = self._svnwithrev('propget', name)
- return res[:-1] # strip trailing newline
-
- def _proplist(self):
- res = self._svnwithrev('proplist')
- lines = res.split('\n')
- lines = [x.strip() for x in lines[1:]]
- return svncommon.PropListDict(self, lines)
-
- def info(self):
- """ return an Info structure with svn-provided information. """
- parent = self.dirpath()
- nameinfo_seq = parent._listdir_nameinfo()
- bn = self.basename
- for name, info in nameinfo_seq:
- if name == bn:
- return info
- raise py.error.ENOENT(self)
-
-
- def _listdir_nameinfo(self):
- """ return sequence of name-info directory entries of self """
- def builder():
- try:
- res = self._svnwithrev('ls', '-v')
- except process.cmdexec.Error:
- e = sys.exc_info()[1]
- if e.err.find('non-existent in that revision') != -1:
- raise py.error.ENOENT(self, e.err)
- elif e.err.find("E200009:") != -1:
- raise py.error.ENOENT(self, e.err)
- elif e.err.find('File not found') != -1:
- raise py.error.ENOENT(self, e.err)
- elif e.err.find('not part of a repository')!=-1:
- raise py.error.ENOENT(self, e.err)
- elif e.err.find('Unable to open')!=-1:
- raise py.error.ENOENT(self, e.err)
- elif e.err.lower().find('method not allowed')!=-1:
- raise py.error.EACCES(self, e.err)
- raise py.error.Error(e.err)
- lines = res.split('\n')
- nameinfo_seq = []
- for lsline in lines:
- if lsline:
- info = InfoSvnCommand(lsline)
- if info._name != '.': # svn 1.5 produces '.' dirs,
- nameinfo_seq.append((info._name, info))
- nameinfo_seq.sort()
- return nameinfo_seq
- auth = self.auth and self.auth.makecmdoptions() or None
- if self.rev is not None:
- return self._lsrevcache.getorbuild((self.strpath, self.rev, auth),
- builder)
- else:
- return self._lsnorevcache.getorbuild((self.strpath, auth),
- builder)
-
- def listdir(self, fil=None, sort=None):
- """ list directory contents, possibly filter by the given fil func
- and possibly sorted.
- """
- if isinstance(fil, str):
- fil = common.FNMatcher(fil)
- nameinfo_seq = self._listdir_nameinfo()
- if len(nameinfo_seq) == 1:
- name, info = nameinfo_seq[0]
- if name == self.basename and info.kind == 'file':
- #if not self.check(dir=1):
- raise py.error.ENOTDIR(self)
- paths = [self.join(name) for (name, info) in nameinfo_seq]
- if fil:
- paths = [x for x in paths if fil(x)]
- self._sortlist(paths, sort)
- return paths
-
-
- def log(self, rev_start=None, rev_end=1, verbose=False):
- """ return a list of LogEntry instances for this path.
-rev_start is the starting revision (defaulting to the first one).
-rev_end is the last revision (defaulting to HEAD).
-if verbose is True, then the LogEntry instances also know which files changed.
-"""
- assert self.check() #make it simpler for the pipe
- rev_start = rev_start is None and "HEAD" or rev_start
- rev_end = rev_end is None and "HEAD" or rev_end
-
- if rev_start == "HEAD" and rev_end == 1:
- rev_opt = ""
- else:
- rev_opt = "-r %s:%s" % (rev_start, rev_end)
- verbose_opt = verbose and "-v" or ""
- xmlpipe = self._svnpopenauth('svn log --xml %s %s "%s"' %
- (rev_opt, verbose_opt, self.strpath))
- from xml.dom import minidom
- tree = minidom.parse(xmlpipe)
- result = []
- for logentry in filter(None, tree.firstChild.childNodes):
- if logentry.nodeType == logentry.ELEMENT_NODE:
- result.append(svncommon.LogEntry(logentry))
- return result
-
-#01234567890123456789012345678901234567890123467
-# 2256 hpk 165 Nov 24 17:55 __init__.py
-# XXX spotted by Guido, SVN 1.3.0 has different aligning, breaks the code!!!
-# 1312 johnny 1627 May 05 14:32 test_decorators.py
-#
-class InfoSvnCommand:
- # the '0?' part in the middle is an indication of whether the resource is
- # locked, see 'svn help ls'
- lspattern = re.compile(
- r'^ *(?P<rev>\d+) +(?P<author>.+?) +(0? *(?P<size>\d+))? '
- '*(?P<date>\w+ +\d{2} +[\d:]+) +(?P<file>.*)$')
- def __init__(self, line):
- # this is a typical line from 'svn ls http://...'
- #_ 1127 jum 0 Jul 13 15:28 branch/
- match = self.lspattern.match(line)
- data = match.groupdict()
- self._name = data['file']
- if self._name[-1] == '/':
- self._name = self._name[:-1]
- self.kind = 'dir'
- else:
- self.kind = 'file'
- #self.has_props = l.pop(0) == 'P'
- self.created_rev = int(data['rev'])
- self.last_author = data['author']
- self.size = data['size'] and int(data['size']) or 0
- self.mtime = parse_time_with_missing_year(data['date'])
- self.time = self.mtime * 1000000
-
- def __eq__(self, other):
- return self.__dict__ == other.__dict__
-
-
-#____________________________________________________
-#
-# helper functions
-#____________________________________________________
-def parse_time_with_missing_year(timestr):
- """ analyze the time part from a single line of "svn ls -v"
- the svn output doesn't show the year makes the 'timestr'
- ambigous.
- """
- import calendar
- t_now = time.gmtime()
-
- tparts = timestr.split()
- month = time.strptime(tparts.pop(0), '%b')[1]
- day = time.strptime(tparts.pop(0), '%d')[2]
- last = tparts.pop(0) # year or hour:minute
- try:
- if ":" in last:
- raise ValueError()
- year = time.strptime(last, '%Y')[0]
- hour = minute = 0
- except ValueError:
- hour, minute = time.strptime(last, '%H:%M')[3:5]
- year = t_now[0]
-
- t_result = (year, month, day, hour, minute, 0,0,0,0)
- if t_result > t_now:
- year -= 1
- t_result = (year, month, day, hour, minute, 0,0,0,0)
- return calendar.timegm(t_result)
-
-class PathEntry:
- def __init__(self, ppart):
- self.strpath = ppart.firstChild.nodeValue.encode('UTF-8')
- self.action = ppart.getAttribute('action').encode('UTF-8')
- if self.action == 'A':
- self.copyfrom_path = ppart.getAttribute('copyfrom-path').encode('UTF-8')
- if self.copyfrom_path:
- self.copyfrom_rev = int(ppart.getAttribute('copyfrom-rev'))
-
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_path/svnwc.py b/tests/wpt/web-platform-tests/tools/py/py/_path/svnwc.py
deleted file mode 100644
index 00d3b4bbaf3..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/py/_path/svnwc.py
+++ /dev/null
@@ -1,1240 +0,0 @@
-"""
-svn-Command based Implementation of a Subversion WorkingCopy Path.
-
- SvnWCCommandPath is the main class.
-
-"""
-
-import os, sys, time, re, calendar
-import py
-import subprocess
-from py._path import common
-
-#-----------------------------------------------------------
-# Caching latest repository revision and repo-paths
-# (getting them is slow with the current implementations)
-#
-# XXX make mt-safe
-#-----------------------------------------------------------
-
-class cache:
- proplist = {}
- info = {}
- entries = {}
- prop = {}
-
-class RepoEntry:
- def __init__(self, url, rev, timestamp):
- self.url = url
- self.rev = rev
- self.timestamp = timestamp
-
- def __str__(self):
- return "repo: %s;%s %s" %(self.url, self.rev, self.timestamp)
-
-class RepoCache:
- """ The Repocache manages discovered repository paths
- and their revisions. If inside a timeout the cache
- will even return the revision of the root.
- """
- timeout = 20 # seconds after which we forget that we know the last revision
-
- def __init__(self):
- self.repos = []
-
- def clear(self):
- self.repos = []
-
- def put(self, url, rev, timestamp=None):
- if rev is None:
- return
- if timestamp is None:
- timestamp = time.time()
-
- for entry in self.repos:
- if url == entry.url:
- entry.timestamp = timestamp
- entry.rev = rev
- #print "set repo", entry
- break
- else:
- entry = RepoEntry(url, rev, timestamp)
- self.repos.append(entry)
- #print "appended repo", entry
-
- def get(self, url):
- now = time.time()
- for entry in self.repos:
- if url.startswith(entry.url):
- if now < entry.timestamp + self.timeout:
- #print "returning immediate Etrny", entry
- return entry.url, entry.rev
- return entry.url, -1
- return url, -1
-
-repositories = RepoCache()
-
-
-# svn support code
-
-ALLOWED_CHARS = "_ -/\\=$.~+%" #add characters as necessary when tested
-if sys.platform == "win32":
- ALLOWED_CHARS += ":"
-ALLOWED_CHARS_HOST = ALLOWED_CHARS + '@:'
-
-def _getsvnversion(ver=[]):
- try:
- return ver[0]
- except IndexError:
- v = py.process.cmdexec("svn -q --version")
- v.strip()
- v = '.'.join(v.split('.')[:2])
- ver.append(v)
- return v
-
-def _escape_helper(text):
- text = str(text)
- if py.std.sys.platform != 'win32':
- text = str(text).replace('$', '\\$')
- return text
-
-def _check_for_bad_chars(text, allowed_chars=ALLOWED_CHARS):
- for c in str(text):
- if c.isalnum():
- continue
- if c in allowed_chars:
- continue
- return True
- return False
-
-def checkbadchars(url):
- # (hpk) not quite sure about the exact purpose, guido w.?
- proto, uri = url.split("://", 1)
- if proto != "file":
- host, uripath = uri.split('/', 1)
- # only check for bad chars in the non-protocol parts
- if (_check_for_bad_chars(host, ALLOWED_CHARS_HOST) \
- or _check_for_bad_chars(uripath, ALLOWED_CHARS)):
- raise ValueError("bad char in %r" % (url, ))
-
-
-#_______________________________________________________________
-
-class SvnPathBase(common.PathBase):
- """ Base implementation for SvnPath implementations. """
- sep = '/'
-
- def _geturl(self):
- return self.strpath
- url = property(_geturl, None, None, "url of this svn-path.")
-
- def __str__(self):
- """ return a string representation (including rev-number) """
- return self.strpath
-
- def __hash__(self):
- return hash(self.strpath)
-
- def new(self, **kw):
- """ create a modified version of this path. A 'rev' argument
- indicates a new revision.
- the following keyword arguments modify various path parts::
-
- http://host.com/repo/path/file.ext
- |-----------------------| dirname
- |------| basename
- |--| purebasename
- |--| ext
- """
- obj = object.__new__(self.__class__)
- obj.rev = kw.get('rev', self.rev)
- obj.auth = kw.get('auth', self.auth)
- dirname, basename, purebasename, ext = self._getbyspec(
- "dirname,basename,purebasename,ext")
- if 'basename' in kw:
- if 'purebasename' in kw or 'ext' in kw:
- raise ValueError("invalid specification %r" % kw)
- else:
- pb = kw.setdefault('purebasename', purebasename)
- ext = kw.setdefault('ext', ext)
- if ext and not ext.startswith('.'):
- ext = '.' + ext
- kw['basename'] = pb + ext
-
- kw.setdefault('dirname', dirname)
- kw.setdefault('sep', self.sep)
- if kw['basename']:
- obj.strpath = "%(dirname)s%(sep)s%(basename)s" % kw
- else:
- obj.strpath = "%(dirname)s" % kw
- return obj
-
- def _getbyspec(self, spec):
- """ get specified parts of the path. 'arg' is a string
- with comma separated path parts. The parts are returned
- in exactly the order of the specification.
-
- you may specify the following parts:
-
- http://host.com/repo/path/file.ext
- |-----------------------| dirname
- |------| basename
- |--| purebasename
- |--| ext
- """
- res = []
- parts = self.strpath.split(self.sep)
- for name in spec.split(','):
- name = name.strip()
- if name == 'dirname':
- res.append(self.sep.join(parts[:-1]))
- elif name == 'basename':
- res.append(parts[-1])
- else:
- basename = parts[-1]
- i = basename.rfind('.')
- if i == -1:
- purebasename, ext = basename, ''
- else:
- purebasename, ext = basename[:i], basename[i:]
- if name == 'purebasename':
- res.append(purebasename)
- elif name == 'ext':
- res.append(ext)
- else:
- raise NameError("Don't know part %r" % name)
- return res
-
- def __eq__(self, other):
- """ return true if path and rev attributes each match """
- return (str(self) == str(other) and
- (self.rev == other.rev or self.rev == other.rev))
-
- def __ne__(self, other):
- return not self == other
-
- def join(self, *args):
- """ return a new Path (with the same revision) which is composed
- of the self Path followed by 'args' path components.
- """
- if not args:
- return self
-
- args = tuple([arg.strip(self.sep) for arg in args])
- parts = (self.strpath, ) + args
- newpath = self.__class__(self.sep.join(parts), self.rev, self.auth)
- return newpath
-
- def propget(self, name):
- """ return the content of the given property. """
- value = self._propget(name)
- return value
-
- def proplist(self):
- """ list all property names. """
- content = self._proplist()
- return content
-
- def size(self):
- """ Return the size of the file content of the Path. """
- return self.info().size
-
- def mtime(self):
- """ Return the last modification time of the file. """
- return self.info().mtime
-
- # shared help methods
-
- def _escape(self, cmd):
- return _escape_helper(cmd)
-
-
- #def _childmaxrev(self):
- # """ return maximum revision number of childs (or self.rev if no childs) """
- # rev = self.rev
- # for name, info in self._listdir_nameinfo():
- # rev = max(rev, info.created_rev)
- # return rev
-
- #def _getlatestrevision(self):
- # """ return latest repo-revision for this path. """
- # url = self.strpath
- # path = self.__class__(url, None)
- #
- # # we need a long walk to find the root-repo and revision
- # while 1:
- # try:
- # rev = max(rev, path._childmaxrev())
- # previous = path
- # path = path.dirpath()
- # except (IOError, process.cmdexec.Error):
- # break
- # if rev is None:
- # raise IOError, "could not determine newest repo revision for %s" % self
- # return rev
-
- class Checkers(common.Checkers):
- def dir(self):
- try:
- return self.path.info().kind == 'dir'
- except py.error.Error:
- return self._listdirworks()
-
- def _listdirworks(self):
- try:
- self.path.listdir()
- except py.error.ENOENT:
- return False
- else:
- return True
-
- def file(self):
- try:
- return self.path.info().kind == 'file'
- except py.error.ENOENT:
- return False
-
- def exists(self):
- try:
- return self.path.info()
- except py.error.ENOENT:
- return self._listdirworks()
-
-def parse_apr_time(timestr):
- i = timestr.rfind('.')
- if i == -1:
- raise ValueError("could not parse %s" % timestr)
- timestr = timestr[:i]
- parsedtime = time.strptime(timestr, "%Y-%m-%dT%H:%M:%S")
- return time.mktime(parsedtime)
-
-class PropListDict(dict):
- """ a Dictionary which fetches values (InfoSvnCommand instances) lazily"""
- def __init__(self, path, keynames):
- dict.__init__(self, [(x, None) for x in keynames])
- self.path = path
-
- def __getitem__(self, key):
- value = dict.__getitem__(self, key)
- if value is None:
- value = self.path.propget(key)
- dict.__setitem__(self, key, value)
- return value
-
-def fixlocale():
- if sys.platform != 'win32':
- return 'LC_ALL=C '
- return ''
-
-# some nasty chunk of code to solve path and url conversion and quoting issues
-ILLEGAL_CHARS = '* | \ / : < > ? \t \n \x0b \x0c \r'.split(' ')
-if os.sep in ILLEGAL_CHARS:
- ILLEGAL_CHARS.remove(os.sep)
-ISWINDOWS = sys.platform == 'win32'
-_reg_allow_disk = re.compile(r'^([a-z]\:\\)?[^:]+$', re.I)
-def _check_path(path):
- illegal = ILLEGAL_CHARS[:]
- sp = path.strpath
- if ISWINDOWS:
- illegal.remove(':')
- if not _reg_allow_disk.match(sp):
- raise ValueError('path may not contain a colon (:)')
- for char in sp:
- if char not in string.printable or char in illegal:
- raise ValueError('illegal character %r in path' % (char,))
-
-def path_to_fspath(path, addat=True):
- _check_path(path)
- sp = path.strpath
- if addat and path.rev != -1:
- sp = '%s@%s' % (sp, path.rev)
- elif addat:
- sp = '%s@HEAD' % (sp,)
- return sp
-
-def url_from_path(path):
- fspath = path_to_fspath(path, False)
- quote = py.std.urllib.quote
- if ISWINDOWS:
- match = _reg_allow_disk.match(fspath)
- fspath = fspath.replace('\\', '/')
- if match.group(1):
- fspath = '/%s%s' % (match.group(1).replace('\\', '/'),
- quote(fspath[len(match.group(1)):]))
- else:
- fspath = quote(fspath)
- else:
- fspath = quote(fspath)
- if path.rev != -1:
- fspath = '%s@%s' % (fspath, path.rev)
- else:
- fspath = '%s@HEAD' % (fspath,)
- return 'file://%s' % (fspath,)
-
-class SvnAuth(object):
- """ container for auth information for Subversion """
- def __init__(self, username, password, cache_auth=True, interactive=True):
- self.username = username
- self.password = password
- self.cache_auth = cache_auth
- self.interactive = interactive
-
- def makecmdoptions(self):
- uname = self.username.replace('"', '\\"')
- passwd = self.password.replace('"', '\\"')
- ret = []
- if uname:
- ret.append('--username="%s"' % (uname,))
- if passwd:
- ret.append('--password="%s"' % (passwd,))
- if not self.cache_auth:
- ret.append('--no-auth-cache')
- if not self.interactive:
- ret.append('--non-interactive')
- return ' '.join(ret)
-
- def __str__(self):
- return "<SvnAuth username=%s ...>" %(self.username,)
-
-rex_blame = re.compile(r'\s*(\d+)\s*(\S+) (.*)')
-
-class SvnWCCommandPath(common.PathBase):
- """ path implementation offering access/modification to svn working copies.
- It has methods similar to the functions in os.path and similar to the
- commands of the svn client.
- """
- sep = os.sep
-
- def __new__(cls, wcpath=None, auth=None):
- self = object.__new__(cls)
- if isinstance(wcpath, cls):
- if wcpath.__class__ == cls:
- return wcpath
- wcpath = wcpath.localpath
- if _check_for_bad_chars(str(wcpath),
- ALLOWED_CHARS):
- raise ValueError("bad char in wcpath %s" % (wcpath, ))
- self.localpath = py.path.local(wcpath)
- self.auth = auth
- return self
-
- strpath = property(lambda x: str(x.localpath), None, None, "string path")
- rev = property(lambda x: x.info(usecache=0).rev, None, None, "revision")
-
- def __eq__(self, other):
- return self.localpath == getattr(other, 'localpath', None)
-
- def _geturl(self):
- if getattr(self, '_url', None) is None:
- info = self.info()
- self._url = info.url #SvnPath(info.url, info.rev)
- assert isinstance(self._url, py.builtin._basestring)
- return self._url
-
- url = property(_geturl, None, None, "url of this WC item")
-
- def _escape(self, cmd):
- return _escape_helper(cmd)
-
- def dump(self, obj):
- """ pickle object into path location"""
- return self.localpath.dump(obj)
-
- def svnurl(self):
- """ return current SvnPath for this WC-item. """
- info = self.info()
- return py.path.svnurl(info.url)
-
- def __repr__(self):
- return "svnwc(%r)" % (self.strpath) # , self._url)
-
- def __str__(self):
- return str(self.localpath)
-
- def _makeauthoptions(self):
- if self.auth is None:
- return ''
- return self.auth.makecmdoptions()
-
- def _authsvn(self, cmd, args=None):
- args = args and list(args) or []
- args.append(self._makeauthoptions())
- return self._svn(cmd, *args)
-
- def _svn(self, cmd, *args):
- l = ['svn %s' % cmd]
- args = [self._escape(item) for item in args]
- l.extend(args)
- l.append('"%s"' % self._escape(self.strpath))
- # try fixing the locale because we can't otherwise parse
- string = fixlocale() + " ".join(l)
- try:
- try:
- key = 'LC_MESSAGES'
- hold = os.environ.get(key)
- os.environ[key] = 'C'
- out = py.process.cmdexec(string)
- finally:
- if hold:
- os.environ[key] = hold
- else:
- del os.environ[key]
- except py.process.cmdexec.Error:
- e = sys.exc_info()[1]
- strerr = e.err.lower()
- if strerr.find('not found') != -1:
- raise py.error.ENOENT(self)
- elif strerr.find("E200009:") != -1:
- raise py.error.ENOENT(self)
- if (strerr.find('file exists') != -1 or
- strerr.find('file already exists') != -1 or
- strerr.find('w150002:') != -1 or
- strerr.find("can't create directory") != -1):
- raise py.error.EEXIST(strerr) #self)
- raise
- return out
-
- def switch(self, url):
- """ switch to given URL. """
- self._authsvn('switch', [url])
-
- def checkout(self, url=None, rev=None):
- """ checkout from url to local wcpath. """
- args = []
- if url is None:
- url = self.url
- if rev is None or rev == -1:
- if (py.std.sys.platform != 'win32' and
- _getsvnversion() == '1.3'):
- url += "@HEAD"
- else:
- if _getsvnversion() == '1.3':
- url += "@%d" % rev
- else:
- args.append('-r' + str(rev))
- args.append(url)
- self._authsvn('co', args)
-
- def update(self, rev='HEAD', interactive=True):
- """ update working copy item to given revision. (None -> HEAD). """
- opts = ['-r', rev]
- if not interactive:
- opts.append("--non-interactive")
- self._authsvn('up', opts)
-
- def write(self, content, mode='w'):
- """ write content into local filesystem wc. """
- self.localpath.write(content, mode)
-
- def dirpath(self, *args):
- """ return the directory Path of the current Path. """
- return self.__class__(self.localpath.dirpath(*args), auth=self.auth)
-
- def _ensuredirs(self):
- parent = self.dirpath()
- if parent.check(dir=0):
- parent._ensuredirs()
- if self.check(dir=0):
- self.mkdir()
- return self
-
- def ensure(self, *args, **kwargs):
- """ ensure that an args-joined path exists (by default as
- a file). if you specify a keyword argument 'directory=True'
- then the path is forced to be a directory path.
- """
- p = self.join(*args)
- if p.check():
- if p.check(versioned=False):
- p.add()
- return p
- if kwargs.get('dir', 0):
- return p._ensuredirs()
- parent = p.dirpath()
- parent._ensuredirs()
- p.write("")
- p.add()
- return p
-
- def mkdir(self, *args):
- """ create & return the directory joined with args. """
- if args:
- return self.join(*args).mkdir()
- else:
- self._svn('mkdir')
- return self
-
- def add(self):
- """ add ourself to svn """
- self._svn('add')
-
- def remove(self, rec=1, force=1):
- """ remove a file or a directory tree. 'rec'ursive is
- ignored and considered always true (because of
- underlying svn semantics.
- """
- assert rec, "svn cannot remove non-recursively"
- if not self.check(versioned=True):
- # not added to svn (anymore?), just remove
- py.path.local(self).remove()
- return
- flags = []
- if force:
- flags.append('--force')
- self._svn('remove', *flags)
-
- def copy(self, target):
- """ copy path to target."""
- py.process.cmdexec("svn copy %s %s" %(str(self), str(target)))
-
- def rename(self, target):
- """ rename this path to target. """
- py.process.cmdexec("svn move --force %s %s" %(str(self), str(target)))
-
- def lock(self):
- """ set a lock (exclusive) on the resource """
- out = self._authsvn('lock').strip()
- if not out:
- # warning or error, raise exception
- raise ValueError("unknown error in svn lock command")
-
- def unlock(self):
- """ unset a previously set lock """
- out = self._authsvn('unlock').strip()
- if out.startswith('svn:'):
- # warning or error, raise exception
- raise Exception(out[4:])
-
- def cleanup(self):
- """ remove any locks from the resource """
- # XXX should be fixed properly!!!
- try:
- self.unlock()
- except:
- pass
-
- def status(self, updates=0, rec=0, externals=0):
- """ return (collective) Status object for this file. """
- # http://svnbook.red-bean.com/book.html#svn-ch-3-sect-4.3.1
- # 2201 2192 jum test
- # XXX
- if externals:
- raise ValueError("XXX cannot perform status() "
- "on external items yet")
- else:
- #1.2 supports: externals = '--ignore-externals'
- externals = ''
- if rec:
- rec= ''
- else:
- rec = '--non-recursive'
-
- # XXX does not work on all subversion versions
- #if not externals:
- # externals = '--ignore-externals'
-
- if updates:
- updates = '-u'
- else:
- updates = ''
-
- try:
- cmd = 'status -v --xml --no-ignore %s %s %s' % (
- updates, rec, externals)
- out = self._authsvn(cmd)
- except py.process.cmdexec.Error:
- cmd = 'status -v --no-ignore %s %s %s' % (
- updates, rec, externals)
- out = self._authsvn(cmd)
- rootstatus = WCStatus(self).fromstring(out, self)
- else:
- rootstatus = XMLWCStatus(self).fromstring(out, self)
- return rootstatus
-
- def diff(self, rev=None):
- """ return a diff of the current path against revision rev (defaulting
- to the last one).
- """
- args = []
- if rev is not None:
- args.append("-r %d" % rev)
- out = self._authsvn('diff', args)
- return out
-
- def blame(self):
- """ return a list of tuples of three elements:
- (revision, commiter, line)
- """
- out = self._svn('blame')
- result = []
- blamelines = out.splitlines()
- reallines = py.path.svnurl(self.url).readlines()
- for i, (blameline, line) in enumerate(
- zip(blamelines, reallines)):
- m = rex_blame.match(blameline)
- if not m:
- raise ValueError("output line %r of svn blame does not match "
- "expected format" % (line, ))
- rev, name, _ = m.groups()
- result.append((int(rev), name, line))
- return result
-
- _rex_commit = re.compile(r'.*Committed revision (\d+)\.$', re.DOTALL)
- def commit(self, msg='', rec=1):
- """ commit with support for non-recursive commits """
- # XXX i guess escaping should be done better here?!?
- cmd = 'commit -m "%s" --force-log' % (msg.replace('"', '\\"'),)
- if not rec:
- cmd += ' -N'
- out = self._authsvn(cmd)
- try:
- del cache.info[self]
- except KeyError:
- pass
- if out:
- m = self._rex_commit.match(out)
- return int(m.group(1))
-
- def propset(self, name, value, *args):
- """ set property name to value on this path. """
- d = py.path.local.mkdtemp()
- try:
- p = d.join('value')
- p.write(value)
- self._svn('propset', name, '--file', str(p), *args)
- finally:
- d.remove()
-
- def propget(self, name):
- """ get property name on this path. """
- res = self._svn('propget', name)
- return res[:-1] # strip trailing newline
-
- def propdel(self, name):
- """ delete property name on this path. """
- res = self._svn('propdel', name)
- return res[:-1] # strip trailing newline
-
- def proplist(self, rec=0):
- """ return a mapping of property names to property values.
-If rec is True, then return a dictionary mapping sub-paths to such mappings.
-"""
- if rec:
- res = self._svn('proplist -R')
- return make_recursive_propdict(self, res)
- else:
- res = self._svn('proplist')
- lines = res.split('\n')
- lines = [x.strip() for x in lines[1:]]
- return PropListDict(self, lines)
-
- def revert(self, rec=0):
- """ revert the local changes of this path. if rec is True, do so
-recursively. """
- if rec:
- result = self._svn('revert -R')
- else:
- result = self._svn('revert')
- return result
-
- def new(self, **kw):
- """ create a modified version of this path. A 'rev' argument
- indicates a new revision.
- the following keyword arguments modify various path parts:
-
- http://host.com/repo/path/file.ext
- |-----------------------| dirname
- |------| basename
- |--| purebasename
- |--| ext
- """
- if kw:
- localpath = self.localpath.new(**kw)
- else:
- localpath = self.localpath
- return self.__class__(localpath, auth=self.auth)
-
- def join(self, *args, **kwargs):
- """ return a new Path (with the same revision) which is composed
- of the self Path followed by 'args' path components.
- """
- if not args:
- return self
- localpath = self.localpath.join(*args, **kwargs)
- return self.__class__(localpath, auth=self.auth)
-
- def info(self, usecache=1):
- """ return an Info structure with svn-provided information. """
- info = usecache and cache.info.get(self)
- if not info:
- try:
- output = self._svn('info')
- except py.process.cmdexec.Error:
- e = sys.exc_info()[1]
- if e.err.find('Path is not a working copy directory') != -1:
- raise py.error.ENOENT(self, e.err)
- elif e.err.find("is not under version control") != -1:
- raise py.error.ENOENT(self, e.err)
- raise
- # XXX SVN 1.3 has output on stderr instead of stdout (while it does
- # return 0!), so a bit nasty, but we assume no output is output
- # to stderr...
- if (output.strip() == '' or
- output.lower().find('not a versioned resource') != -1):
- raise py.error.ENOENT(self, output)
- info = InfoSvnWCCommand(output)
-
- # Can't reliably compare on Windows without access to win32api
- if py.std.sys.platform != 'win32':
- if info.path != self.localpath:
- raise py.error.ENOENT(self, "not a versioned resource:" +
- " %s != %s" % (info.path, self.localpath))
- cache.info[self] = info
- return info
-
- def listdir(self, fil=None, sort=None):
- """ return a sequence of Paths.
-
- listdir will return either a tuple or a list of paths
- depending on implementation choices.
- """
- if isinstance(fil, str):
- fil = common.FNMatcher(fil)
- # XXX unify argument naming with LocalPath.listdir
- def notsvn(path):
- return path.basename != '.svn'
-
- paths = []
- for localpath in self.localpath.listdir(notsvn):
- p = self.__class__(localpath, auth=self.auth)
- if notsvn(p) and (not fil or fil(p)):
- paths.append(p)
- self._sortlist(paths, sort)
- return paths
-
- def open(self, mode='r'):
- """ return an opened file with the given mode. """
- return open(self.strpath, mode)
-
- def _getbyspec(self, spec):
- return self.localpath._getbyspec(spec)
-
- class Checkers(py.path.local.Checkers):
- def __init__(self, path):
- self.svnwcpath = path
- self.path = path.localpath
- def versioned(self):
- try:
- s = self.svnwcpath.info()
- except (py.error.ENOENT, py.error.EEXIST):
- return False
- except py.process.cmdexec.Error:
- e = sys.exc_info()[1]
- if e.err.find('is not a working copy')!=-1:
- return False
- if e.err.lower().find('not a versioned resource') != -1:
- return False
- raise
- else:
- return True
-
- def log(self, rev_start=None, rev_end=1, verbose=False):
- """ return a list of LogEntry instances for this path.
-rev_start is the starting revision (defaulting to the first one).
-rev_end is the last revision (defaulting to HEAD).
-if verbose is True, then the LogEntry instances also know which files changed.
-"""
- assert self.check() # make it simpler for the pipe
- rev_start = rev_start is None and "HEAD" or rev_start
- rev_end = rev_end is None and "HEAD" or rev_end
- if rev_start == "HEAD" and rev_end == 1:
- rev_opt = ""
- else:
- rev_opt = "-r %s:%s" % (rev_start, rev_end)
- verbose_opt = verbose and "-v" or ""
- locale_env = fixlocale()
- # some blather on stderr
- auth_opt = self._makeauthoptions()
- #stdin, stdout, stderr = os.popen3(locale_env +
- # 'svn log --xml %s %s %s "%s"' % (
- # rev_opt, verbose_opt, auth_opt,
- # self.strpath))
- cmd = locale_env + 'svn log --xml %s %s %s "%s"' % (
- rev_opt, verbose_opt, auth_opt, self.strpath)
-
- popen = subprocess.Popen(cmd,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- shell=True,
- )
- stdout, stderr = popen.communicate()
- stdout = py.builtin._totext(stdout, sys.getdefaultencoding())
- minidom,ExpatError = importxml()
- try:
- tree = minidom.parseString(stdout)
- except ExpatError:
- raise ValueError('no such revision')
- result = []
- for logentry in filter(None, tree.firstChild.childNodes):
- if logentry.nodeType == logentry.ELEMENT_NODE:
- result.append(LogEntry(logentry))
- return result
-
- def size(self):
- """ Return the size of the file content of the Path. """
- return self.info().size
-
- def mtime(self):
- """ Return the last modification time of the file. """
- return self.info().mtime
-
- def __hash__(self):
- return hash((self.strpath, self.__class__, self.auth))
-
-
-class WCStatus:
- attrnames = ('modified','added', 'conflict', 'unchanged', 'external',
- 'deleted', 'prop_modified', 'unknown', 'update_available',
- 'incomplete', 'kindmismatch', 'ignored', 'locked', 'replaced'
- )
-
- def __init__(self, wcpath, rev=None, modrev=None, author=None):
- self.wcpath = wcpath
- self.rev = rev
- self.modrev = modrev
- self.author = author
-
- for name in self.attrnames:
- setattr(self, name, [])
-
- def allpath(self, sort=True, **kw):
- d = {}
- for name in self.attrnames:
- if name not in kw or kw[name]:
- for path in getattr(self, name):
- d[path] = 1
- l = d.keys()
- if sort:
- l.sort()
- return l
-
- # XXX a bit scary to assume there's always 2 spaces between username and
- # path, however with win32 allowing spaces in user names there doesn't
- # seem to be a more solid approach :(
- _rex_status = re.compile(r'\s+(\d+|-)\s+(\S+)\s+(.+?)\s{2,}(.*)')
-
- def fromstring(data, rootwcpath, rev=None, modrev=None, author=None):
- """ return a new WCStatus object from data 's'
- """
- rootstatus = WCStatus(rootwcpath, rev, modrev, author)
- update_rev = None
- for line in data.split('\n'):
- if not line.strip():
- continue
- #print "processing %r" % line
- flags, rest = line[:8], line[8:]
- # first column
- c0,c1,c2,c3,c4,c5,x6,c7 = flags
- #if '*' in line:
- # print "flags", repr(flags), "rest", repr(rest)
-
- if c0 in '?XI':
- fn = line.split(None, 1)[1]
- if c0 == '?':
- wcpath = rootwcpath.join(fn, abs=1)
- rootstatus.unknown.append(wcpath)
- elif c0 == 'X':
- wcpath = rootwcpath.__class__(
- rootwcpath.localpath.join(fn, abs=1),
- auth=rootwcpath.auth)
- rootstatus.external.append(wcpath)
- elif c0 == 'I':
- wcpath = rootwcpath.join(fn, abs=1)
- rootstatus.ignored.append(wcpath)
-
- continue
-
- #elif c0 in '~!' or c4 == 'S':
- # raise NotImplementedError("received flag %r" % c0)
-
- m = WCStatus._rex_status.match(rest)
- if not m:
- if c7 == '*':
- fn = rest.strip()
- wcpath = rootwcpath.join(fn, abs=1)
- rootstatus.update_available.append(wcpath)
- continue
- if line.lower().find('against revision:')!=-1:
- update_rev = int(rest.split(':')[1].strip())
- continue
- if line.lower().find('status on external') > -1:
- # XXX not sure what to do here... perhaps we want to
- # store some state instead of just continuing, as right
- # now it makes the top-level external get added twice
- # (once as external, once as 'normal' unchanged item)
- # because of the way SVN presents external items
- continue
- # keep trying
- raise ValueError("could not parse line %r" % line)
- else:
- rev, modrev, author, fn = m.groups()
- wcpath = rootwcpath.join(fn, abs=1)
- #assert wcpath.check()
- if c0 == 'M':
- assert wcpath.check(file=1), "didn't expect a directory with changed content here"
- rootstatus.modified.append(wcpath)
- elif c0 == 'A' or c3 == '+' :
- rootstatus.added.append(wcpath)
- elif c0 == 'D':
- rootstatus.deleted.append(wcpath)
- elif c0 == 'C':
- rootstatus.conflict.append(wcpath)
- elif c0 == '~':
- rootstatus.kindmismatch.append(wcpath)
- elif c0 == '!':
- rootstatus.incomplete.append(wcpath)
- elif c0 == 'R':
- rootstatus.replaced.append(wcpath)
- elif not c0.strip():
- rootstatus.unchanged.append(wcpath)
- else:
- raise NotImplementedError("received flag %r" % c0)
-
- if c1 == 'M':
- rootstatus.prop_modified.append(wcpath)
- # XXX do we cover all client versions here?
- if c2 == 'L' or c5 == 'K':
- rootstatus.locked.append(wcpath)
- if c7 == '*':
- rootstatus.update_available.append(wcpath)
-
- if wcpath == rootwcpath:
- rootstatus.rev = rev
- rootstatus.modrev = modrev
- rootstatus.author = author
- if update_rev:
- rootstatus.update_rev = update_rev
- continue
- return rootstatus
- fromstring = staticmethod(fromstring)
-
-class XMLWCStatus(WCStatus):
- def fromstring(data, rootwcpath, rev=None, modrev=None, author=None):
- """ parse 'data' (XML string as outputted by svn st) into a status obj
- """
- # XXX for externals, the path is shown twice: once
- # with external information, and once with full info as if
- # the item was a normal non-external... the current way of
- # dealing with this issue is by ignoring it - this does make
- # externals appear as external items as well as 'normal',
- # unchanged ones in the status object so this is far from ideal
- rootstatus = WCStatus(rootwcpath, rev, modrev, author)
- update_rev = None
- minidom, ExpatError = importxml()
- try:
- doc = minidom.parseString(data)
- except ExpatError:
- e = sys.exc_info()[1]
- raise ValueError(str(e))
- urevels = doc.getElementsByTagName('against')
- if urevels:
- rootstatus.update_rev = urevels[-1].getAttribute('revision')
- for entryel in doc.getElementsByTagName('entry'):
- path = entryel.getAttribute('path')
- statusel = entryel.getElementsByTagName('wc-status')[0]
- itemstatus = statusel.getAttribute('item')
-
- if itemstatus == 'unversioned':
- wcpath = rootwcpath.join(path, abs=1)
- rootstatus.unknown.append(wcpath)
- continue
- elif itemstatus == 'external':
- wcpath = rootwcpath.__class__(
- rootwcpath.localpath.join(path, abs=1),
- auth=rootwcpath.auth)
- rootstatus.external.append(wcpath)
- continue
- elif itemstatus == 'ignored':
- wcpath = rootwcpath.join(path, abs=1)
- rootstatus.ignored.append(wcpath)
- continue
- elif itemstatus == 'incomplete':
- wcpath = rootwcpath.join(path, abs=1)
- rootstatus.incomplete.append(wcpath)
- continue
-
- rev = statusel.getAttribute('revision')
- if itemstatus == 'added' or itemstatus == 'none':
- rev = '0'
- modrev = '?'
- author = '?'
- date = ''
- elif itemstatus == "replaced":
- pass
- else:
- #print entryel.toxml()
- commitel = entryel.getElementsByTagName('commit')[0]
- if commitel:
- modrev = commitel.getAttribute('revision')
- author = ''
- author_els = commitel.getElementsByTagName('author')
- if author_els:
- for c in author_els[0].childNodes:
- author += c.nodeValue
- date = ''
- for c in commitel.getElementsByTagName('date')[0]\
- .childNodes:
- date += c.nodeValue
-
- wcpath = rootwcpath.join(path, abs=1)
-
- assert itemstatus != 'modified' or wcpath.check(file=1), (
- 'did\'t expect a directory with changed content here')
-
- itemattrname = {
- 'normal': 'unchanged',
- 'unversioned': 'unknown',
- 'conflicted': 'conflict',
- 'none': 'added',
- }.get(itemstatus, itemstatus)
-
- attr = getattr(rootstatus, itemattrname)
- attr.append(wcpath)
-
- propsstatus = statusel.getAttribute('props')
- if propsstatus not in ('none', 'normal'):
- rootstatus.prop_modified.append(wcpath)
-
- if wcpath == rootwcpath:
- rootstatus.rev = rev
- rootstatus.modrev = modrev
- rootstatus.author = author
- rootstatus.date = date
-
- # handle repos-status element (remote info)
- rstatusels = entryel.getElementsByTagName('repos-status')
- if rstatusels:
- rstatusel = rstatusels[0]
- ritemstatus = rstatusel.getAttribute('item')
- if ritemstatus in ('added', 'modified'):
- rootstatus.update_available.append(wcpath)
-
- lockels = entryel.getElementsByTagName('lock')
- if len(lockels):
- rootstatus.locked.append(wcpath)
-
- return rootstatus
- fromstring = staticmethod(fromstring)
-
-class InfoSvnWCCommand:
- def __init__(self, output):
- # Path: test
- # URL: http://codespeak.net/svn/std.path/trunk/dist/std.path/test
- # Repository UUID: fd0d7bf2-dfb6-0310-8d31-b7ecfe96aada
- # Revision: 2151
- # Node Kind: directory
- # Schedule: normal
- # Last Changed Author: hpk
- # Last Changed Rev: 2100
- # Last Changed Date: 2003-10-27 20:43:14 +0100 (Mon, 27 Oct 2003)
- # Properties Last Updated: 2003-11-03 14:47:48 +0100 (Mon, 03 Nov 2003)
-
- d = {}
- for line in output.split('\n'):
- if not line.strip():
- continue
- key, value = line.split(':', 1)
- key = key.lower().replace(' ', '')
- value = value.strip()
- d[key] = value
- try:
- self.url = d['url']
- except KeyError:
- raise ValueError("Not a versioned resource")
- #raise ValueError, "Not a versioned resource %r" % path
- self.kind = d['nodekind'] == 'directory' and 'dir' or d['nodekind']
- try:
- self.rev = int(d['revision'])
- except KeyError:
- self.rev = None
-
- self.path = py.path.local(d['path'])
- self.size = self.path.size()
- if 'lastchangedrev' in d:
- self.created_rev = int(d['lastchangedrev'])
- if 'lastchangedauthor' in d:
- self.last_author = d['lastchangedauthor']
- if 'lastchangeddate' in d:
- self.mtime = parse_wcinfotime(d['lastchangeddate'])
- self.time = self.mtime * 1000000
-
- def __eq__(self, other):
- return self.__dict__ == other.__dict__
-
-def parse_wcinfotime(timestr):
- """ Returns seconds since epoch, UTC. """
- # example: 2003-10-27 20:43:14 +0100 (Mon, 27 Oct 2003)
- m = re.match(r'(\d+-\d+-\d+ \d+:\d+:\d+) ([+-]\d+) .*', timestr)
- if not m:
- raise ValueError("timestring %r does not match" % timestr)
- timestr, timezone = m.groups()
- # do not handle timezone specially, return value should be UTC
- parsedtime = time.strptime(timestr, "%Y-%m-%d %H:%M:%S")
- return calendar.timegm(parsedtime)
-
-def make_recursive_propdict(wcroot,
- output,
- rex = re.compile("Properties on '(.*)':")):
- """ Return a dictionary of path->PropListDict mappings. """
- lines = [x for x in output.split('\n') if x]
- pdict = {}
- while lines:
- line = lines.pop(0)
- m = rex.match(line)
- if not m:
- raise ValueError("could not parse propget-line: %r" % line)
- path = m.groups()[0]
- wcpath = wcroot.join(path, abs=1)
- propnames = []
- while lines and lines[0].startswith(' '):
- propname = lines.pop(0).strip()
- propnames.append(propname)
- assert propnames, "must have found properties!"
- pdict[wcpath] = PropListDict(wcpath, propnames)
- return pdict
-
-
-def importxml(cache=[]):
- if cache:
- return cache
- from xml.dom import minidom
- from xml.parsers.expat import ExpatError
- cache.extend([minidom, ExpatError])
- return cache
-
-class LogEntry:
- def __init__(self, logentry):
- self.rev = int(logentry.getAttribute('revision'))
- for lpart in filter(None, logentry.childNodes):
- if lpart.nodeType == lpart.ELEMENT_NODE:
- if lpart.nodeName == 'author':
- self.author = lpart.firstChild.nodeValue
- elif lpart.nodeName == 'msg':
- if lpart.firstChild:
- self.msg = lpart.firstChild.nodeValue
- else:
- self.msg = ''
- elif lpart.nodeName == 'date':
- #2003-07-29T20:05:11.598637Z
- timestr = lpart.firstChild.nodeValue
- self.date = parse_apr_time(timestr)
- elif lpart.nodeName == 'paths':
- self.strpaths = []
- for ppart in filter(None, lpart.childNodes):
- if ppart.nodeType == ppart.ELEMENT_NODE:
- self.strpaths.append(PathEntry(ppart))
- def __repr__(self):
- return '<Logentry rev=%d author=%s date=%s>' % (
- self.rev, self.author, self.date)
-
-
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_std.py b/tests/wpt/web-platform-tests/tools/py/py/_std.py
deleted file mode 100644
index 97a9853323b..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/py/_std.py
+++ /dev/null
@@ -1,18 +0,0 @@
-import sys
-
-class Std(object):
- """ makes top-level python modules available as an attribute,
- importing them on first access.
- """
-
- def __init__(self):
- self.__dict__ = sys.modules
-
- def __getattr__(self, name):
- try:
- m = __import__(name)
- except ImportError:
- raise AttributeError("py.std: could not import %s" % name)
- return m
-
-std = Std()
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_xmlgen.py b/tests/wpt/web-platform-tests/tools/py/py/_xmlgen.py
deleted file mode 100644
index 2ffcaa14b8e..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/py/_xmlgen.py
+++ /dev/null
@@ -1,253 +0,0 @@
-"""
-module for generating and serializing xml and html structures
-by using simple python objects.
-
-(c) holger krekel, holger at merlinux eu. 2009
-"""
-import sys, re
-
-if sys.version_info >= (3,0):
- def u(s):
- return s
- def unicode(x, errors=None):
- if hasattr(x, '__unicode__'):
- return x.__unicode__()
- return str(x)
-else:
- def u(s):
- return unicode(s)
- unicode = unicode
-
-
-class NamespaceMetaclass(type):
- def __getattr__(self, name):
- if name[:1] == '_':
- raise AttributeError(name)
- if self == Namespace:
- raise ValueError("Namespace class is abstract")
- tagspec = self.__tagspec__
- if tagspec is not None and name not in tagspec:
- raise AttributeError(name)
- classattr = {}
- if self.__stickyname__:
- classattr['xmlname'] = name
- cls = type(name, (self.__tagclass__,), classattr)
- setattr(self, name, cls)
- return cls
-
-class Tag(list):
- class Attr(object):
- def __init__(self, **kwargs):
- self.__dict__.update(kwargs)
-
- def __init__(self, *args, **kwargs):
- super(Tag, self).__init__(args)
- self.attr = self.Attr(**kwargs)
-
- def __unicode__(self):
- return self.unicode(indent=0)
- __str__ = __unicode__
-
- def unicode(self, indent=2):
- l = []
- SimpleUnicodeVisitor(l.append, indent).visit(self)
- return u("").join(l)
-
- def __repr__(self):
- name = self.__class__.__name__
- return "<%r tag object %d>" % (name, id(self))
-
-Namespace = NamespaceMetaclass('Namespace', (object, ), {
- '__tagspec__': None,
- '__tagclass__': Tag,
- '__stickyname__': False,
-})
-
-class HtmlTag(Tag):
- def unicode(self, indent=2):
- l = []
- HtmlVisitor(l.append, indent, shortempty=False).visit(self)
- return u("").join(l)
-
-# exported plain html namespace
-class html(Namespace):
- __tagclass__ = HtmlTag
- __stickyname__ = True
- __tagspec__ = dict([(x,1) for x in (
- 'a,abbr,acronym,address,applet,area,b,bdo,big,blink,'
- 'blockquote,body,br,button,caption,center,cite,code,col,'
- 'colgroup,comment,dd,del,dfn,dir,div,dl,dt,em,embed,'
- 'fieldset,font,form,frameset,h1,h2,h3,h4,h5,h6,head,html,'
- 'i,iframe,img,input,ins,kbd,label,legend,li,link,listing,'
- 'map,marquee,menu,meta,multicol,nobr,noembed,noframes,'
- 'noscript,object,ol,optgroup,option,p,pre,q,s,script,'
- 'select,small,span,strike,strong,style,sub,sup,table,'
- 'tbody,td,textarea,tfoot,th,thead,title,tr,tt,u,ul,xmp,'
- 'base,basefont,frame,hr,isindex,param,samp,var'
- ).split(',') if x])
-
- class Style(object):
- def __init__(self, **kw):
- for x, y in kw.items():
- x = x.replace('_', '-')
- setattr(self, x, y)
-
-
-class raw(object):
- """just a box that can contain a unicode string that will be
- included directly in the output"""
- def __init__(self, uniobj):
- self.uniobj = uniobj
-
-class SimpleUnicodeVisitor(object):
- """ recursive visitor to write unicode. """
- def __init__(self, write, indent=0, curindent=0, shortempty=True):
- self.write = write
- self.cache = {}
- self.visited = {} # for detection of recursion
- self.indent = indent
- self.curindent = curindent
- self.parents = []
- self.shortempty = shortempty # short empty tags or not
-
- def visit(self, node):
- """ dispatcher on node's class/bases name. """
- cls = node.__class__
- try:
- visitmethod = self.cache[cls]
- except KeyError:
- for subclass in cls.__mro__:
- visitmethod = getattr(self, subclass.__name__, None)
- if visitmethod is not None:
- break
- else:
- visitmethod = self.__object
- self.cache[cls] = visitmethod
- visitmethod(node)
-
- # the default fallback handler is marked private
- # to avoid clashes with the tag name object
- def __object(self, obj):
- #self.write(obj)
- self.write(escape(unicode(obj)))
-
- def raw(self, obj):
- self.write(obj.uniobj)
-
- def list(self, obj):
- assert id(obj) not in self.visited
- self.visited[id(obj)] = 1
- for elem in obj:
- self.visit(elem)
-
- def Tag(self, tag):
- assert id(tag) not in self.visited
- try:
- tag.parent = self.parents[-1]
- except IndexError:
- tag.parent = None
- self.visited[id(tag)] = 1
- tagname = getattr(tag, 'xmlname', tag.__class__.__name__)
- if self.curindent and not self._isinline(tagname):
- self.write("\n" + u(' ') * self.curindent)
- if tag:
- self.curindent += self.indent
- self.write(u('<%s%s>') % (tagname, self.attributes(tag)))
- self.parents.append(tag)
- for x in tag:
- self.visit(x)
- self.parents.pop()
- self.write(u('</%s>') % tagname)
- self.curindent -= self.indent
- else:
- nameattr = tagname+self.attributes(tag)
- if self._issingleton(tagname):
- self.write(u('<%s/>') % (nameattr,))
- else:
- self.write(u('<%s></%s>') % (nameattr, tagname))
-
- def attributes(self, tag):
- # serialize attributes
- attrlist = dir(tag.attr)
- attrlist.sort()
- l = []
- for name in attrlist:
- res = self.repr_attribute(tag.attr, name)
- if res is not None:
- l.append(res)
- l.extend(self.getstyle(tag))
- return u("").join(l)
-
- def repr_attribute(self, attrs, name):
- if name[:2] != '__':
- value = getattr(attrs, name)
- if name.endswith('_'):
- name = name[:-1]
- if isinstance(value, raw):
- insert = value.uniobj
- else:
- insert = escape(unicode(value))
- return ' %s="%s"' % (name, insert)
-
- def getstyle(self, tag):
- """ return attribute list suitable for styling. """
- try:
- styledict = tag.style.__dict__
- except AttributeError:
- return []
- else:
- stylelist = [x+': ' + y for x,y in styledict.items()]
- return [u(' style="%s"') % u('; ').join(stylelist)]
-
- def _issingleton(self, tagname):
- """can (and will) be overridden in subclasses"""
- return self.shortempty
-
- def _isinline(self, tagname):
- """can (and will) be overridden in subclasses"""
- return False
-
-class HtmlVisitor(SimpleUnicodeVisitor):
-
- single = dict([(x, 1) for x in
- ('br,img,area,param,col,hr,meta,link,base,'
- 'input,frame').split(',')])
- inline = dict([(x, 1) for x in
- ('a abbr acronym b basefont bdo big br cite code dfn em font '
- 'i img input kbd label q s samp select small span strike '
- 'strong sub sup textarea tt u var'.split(' '))])
-
- def repr_attribute(self, attrs, name):
- if name == 'class_':
- value = getattr(attrs, name)
- if value is None:
- return
- return super(HtmlVisitor, self).repr_attribute(attrs, name)
-
- def _issingleton(self, tagname):
- return tagname in self.single
-
- def _isinline(self, tagname):
- return tagname in self.inline
-
-
-class _escape:
- def __init__(self):
- self.escape = {
- u('"') : u('&quot;'), u('<') : u('&lt;'), u('>') : u('&gt;'),
- u('&') : u('&amp;'), u("'") : u('&apos;'),
- }
- self.charef_rex = re.compile(u("|").join(self.escape.keys()))
-
- def _replacer(self, match):
- return self.escape[match.group(0)]
-
- def __call__(self, ustring):
- """ xml-escape the given unicode string. """
- try:
- ustring = unicode(ustring)
- except UnicodeDecodeError:
- ustring = unicode(ustring, 'utf-8', errors='replace')
- return self.charef_rex.sub(self._replacer, ustring)
-
-escape = _escape()
diff --git a/tests/wpt/web-platform-tests/tools/py/setup.cfg b/tests/wpt/web-platform-tests/tools/py/setup.cfg
deleted file mode 100644
index 272e488f363..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/setup.cfg
+++ /dev/null
@@ -1,5 +0,0 @@
-[wheel]
-universal = 1
-
-[devpi:upload]
-formats=sdist.tgz,bdist_wheel
diff --git a/tests/wpt/web-platform-tests/tools/py/setup.py b/tests/wpt/web-platform-tests/tools/py/setup.py
deleted file mode 100644
index 06f0885cd71..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/setup.py
+++ /dev/null
@@ -1,38 +0,0 @@
-import os, sys
-
-from setuptools import setup
-
-def main():
- setup(
- name='py',
- description='library with cross-python path, ini-parsing, io, code, log facilities',
- long_description = open('README.txt').read(),
- version='1.4.31',
- url='http://pylib.readthedocs.org/',
- license='MIT license',
- platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],
- author='holger krekel, Ronny Pfannschmidt, Benjamin Peterson and others',
- author_email='pytest-dev@python.org',
- classifiers=['Development Status :: 6 - Mature',
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: MIT License',
- 'Operating System :: POSIX',
- 'Operating System :: Microsoft :: Windows',
- 'Operating System :: MacOS :: MacOS X',
- 'Topic :: Software Development :: Testing',
- 'Topic :: Software Development :: Libraries',
- 'Topic :: Utilities',
- 'Programming Language :: Python',
- 'Programming Language :: Python :: 3'],
- packages=['py',
- 'py._code',
- 'py._io',
- 'py._log',
- 'py._path',
- 'py._process',
- ],
- zip_safe=False,
- )
-
-if __name__ == '__main__':
- main()
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/code/test_assertion.py b/tests/wpt/web-platform-tests/tools/py/testing/code/test_assertion.py
deleted file mode 100644
index e2154d0fc7a..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/testing/code/test_assertion.py
+++ /dev/null
@@ -1,308 +0,0 @@
-import pytest, py
-
-def exvalue():
- return py.std.sys.exc_info()[1]
-
-def f():
- return 2
-
-def test_assert():
- try:
- assert f() == 3
- except AssertionError:
- e = exvalue()
- s = str(e)
- assert s.startswith('assert 2 == 3\n')
-
-
-def test_assert_within_finally():
- excinfo = py.test.raises(ZeroDivisionError, """
- try:
- 1/0
- finally:
- i = 42
- """)
- s = excinfo.exconly()
- assert py.std.re.search("division.+by zero", s) is not None
-
- #def g():
- # A.f()
- #excinfo = getexcinfo(TypeError, g)
- #msg = getmsg(excinfo)
- #assert msg.find("must be called with A") != -1
-
-
-def test_assert_multiline_1():
- try:
- assert (f() ==
- 3)
- except AssertionError:
- e = exvalue()
- s = str(e)
- assert s.startswith('assert 2 == 3\n')
-
-def test_assert_multiline_2():
- try:
- assert (f() == (4,
- 3)[-1])
- except AssertionError:
- e = exvalue()
- s = str(e)
- assert s.startswith('assert 2 ==')
-
-def test_in():
- try:
- assert "hi" in [1, 2]
- except AssertionError:
- e = exvalue()
- s = str(e)
- assert s.startswith("assert 'hi' in")
-
-def test_is():
- try:
- assert 1 is 2
- except AssertionError:
- e = exvalue()
- s = str(e)
- assert s.startswith("assert 1 is 2")
-
-
-@py.test.mark.skipif("sys.version_info < (2,6)")
-def test_attrib():
- class Foo(object):
- b = 1
- i = Foo()
- try:
- assert i.b == 2
- except AssertionError:
- e = exvalue()
- s = str(e)
- assert s.startswith("assert 1 == 2")
-
-@py.test.mark.skipif("sys.version_info < (2,6)")
-def test_attrib_inst():
- class Foo(object):
- b = 1
- try:
- assert Foo().b == 2
- except AssertionError:
- e = exvalue()
- s = str(e)
- assert s.startswith("assert 1 == 2")
-
-def test_len():
- l = list(range(42))
- try:
- assert len(l) == 100
- except AssertionError:
- e = exvalue()
- s = str(e)
- assert s.startswith("assert 42 == 100")
- assert "where 42 = len([" in s
-
-
-def test_assert_keyword_arg():
- def f(x=3):
- return False
- try:
- assert f(x=5)
- except AssertionError:
- e = exvalue()
- assert "x=5" in e.msg
-
-# These tests should both fail, but should fail nicely...
-class WeirdRepr:
- def __repr__(self):
- return '<WeirdRepr\nsecond line>'
-
-def bug_test_assert_repr():
- v = WeirdRepr()
- try:
- assert v == 1
- except AssertionError:
- e = exvalue()
- assert e.msg.find('WeirdRepr') != -1
- assert e.msg.find('second line') != -1
- assert 0
-
-def test_assert_non_string():
- try:
- assert 0, ['list']
- except AssertionError:
- e = exvalue()
- assert e.msg.find("list") != -1
-
-def test_assert_implicit_multiline():
- try:
- x = [1,2,3]
- assert x != [1,
- 2, 3]
- except AssertionError:
- e = exvalue()
- assert e.msg.find('assert [1, 2, 3] !=') != -1
-
-
-def test_assert_with_brokenrepr_arg():
- class BrokenRepr:
- def __repr__(self): 0 / 0
- e = AssertionError(BrokenRepr())
- if e.msg.find("broken __repr__") == -1:
- py.test.fail("broken __repr__ not handle correctly")
-
-def test_multiple_statements_per_line():
- try:
- a = 1; assert a == 2
- except AssertionError:
- e = exvalue()
- assert "assert 1 == 2" in e.msg
-
-def test_power():
- try:
- assert 2**3 == 7
- except AssertionError:
- e = exvalue()
- assert "assert (2 ** 3) == 7" in e.msg
-
-
-class TestView:
-
- def setup_class(cls):
- cls.View = py.test.importorskip("py._code._assertionold").View
-
- def test_class_dispatch(self):
- ### Use a custom class hierarchy with existing instances
-
- class Picklable(self.View):
- pass
-
- class Simple(Picklable):
- __view__ = object
- def pickle(self):
- return repr(self.__obj__)
-
- class Seq(Picklable):
- __view__ = list, tuple, dict
- def pickle(self):
- return ';'.join(
- [Picklable(item).pickle() for item in self.__obj__])
-
- class Dict(Seq):
- __view__ = dict
- def pickle(self):
- return Seq.pickle(self) + '!' + Seq(self.values()).pickle()
-
- assert Picklable(123).pickle() == '123'
- assert Picklable([1,[2,3],4]).pickle() == '1;2;3;4'
- assert Picklable({1:2}).pickle() == '1!2'
-
- def test_viewtype_class_hierarchy(self):
- # Use a custom class hierarchy based on attributes of existing instances
- class Operation:
- "Existing class that I don't want to change."
- def __init__(self, opname, *args):
- self.opname = opname
- self.args = args
-
- existing = [Operation('+', 4, 5),
- Operation('getitem', '', 'join'),
- Operation('setattr', 'x', 'y', 3),
- Operation('-', 12, 1)]
-
- class PyOp(self.View):
- def __viewkey__(self):
- return self.opname
- def generate(self):
- return '%s(%s)' % (self.opname, ', '.join(map(repr, self.args)))
-
- class PyBinaryOp(PyOp):
- __view__ = ('+', '-', '*', '/')
- def generate(self):
- return '%s %s %s' % (self.args[0], self.opname, self.args[1])
-
- codelines = [PyOp(op).generate() for op in existing]
- assert codelines == ["4 + 5", "getitem('', 'join')",
- "setattr('x', 'y', 3)", "12 - 1"]
-
-def test_underscore_api():
- py.code._AssertionError
- py.code._reinterpret_old # used by pypy
- py.code._reinterpret
-
-@py.test.mark.skipif("sys.version_info < (2,6)")
-def test_assert_customizable_reprcompare(monkeypatch):
- util = pytest.importorskip("_pytest.assertion.util")
- monkeypatch.setattr(util, '_reprcompare', lambda *args: 'hello')
- try:
- assert 3 == 4
- except AssertionError:
- e = exvalue()
- s = str(e)
- assert "hello" in s
-
-def test_assert_long_source_1():
- try:
- assert len == [
- (None, ['somet text', 'more text']),
- ]
- except AssertionError:
- e = exvalue()
- s = str(e)
- assert 're-run' not in s
- assert 'somet text' in s
-
-def test_assert_long_source_2():
- try:
- assert(len == [
- (None, ['somet text', 'more text']),
- ])
- except AssertionError:
- e = exvalue()
- s = str(e)
- assert 're-run' not in s
- assert 'somet text' in s
-
-def test_assert_raise_alias(testdir):
- testdir.makepyfile("""
- import sys
- EX = AssertionError
- def test_hello():
- raise EX("hello"
- "multi"
- "line")
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*def test_hello*",
- "*raise EX*",
- "*1 failed*",
- ])
-
-
-@pytest.mark.skipif("sys.version_info < (2,5)")
-def test_assert_raise_subclass():
- class SomeEx(AssertionError):
- def __init__(self, *args):
- super(SomeEx, self).__init__()
- try:
- raise SomeEx("hello")
- except AssertionError:
- s = str(exvalue())
- assert 're-run' not in s
- assert 'could not determine' in s
-
-def test_assert_raises_in_nonzero_of_object_pytest_issue10():
- class A(object):
- def __nonzero__(self):
- raise ValueError(42)
- def __lt__(self, other):
- return A()
- def __repr__(self):
- return "<MY42 object>"
- def myany(x):
- return True
- try:
- assert not(myany(A() < 0))
- except AssertionError:
- e = exvalue()
- s = str(e)
- assert "<MY42 object> < 0" in s
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/code/test_excinfo.py b/tests/wpt/web-platform-tests/tools/py/testing/code/test_excinfo.py
deleted file mode 100644
index 65742c6f62e..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/testing/code/test_excinfo.py
+++ /dev/null
@@ -1,909 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import py
-from py._code.code import FormattedExcinfo, ReprExceptionInfo
-queue = py.builtin._tryimport('queue', 'Queue')
-
-failsonjython = py.test.mark.xfail("sys.platform.startswith('java')")
-from test_source import astonly
-
-try:
- import importlib
-except ImportError:
- invalidate_import_caches = None
-else:
- invalidate_import_caches = getattr(importlib, "invalidate_caches", None)
-
-import pytest
-pytest_version_info = tuple(map(int, pytest.__version__.split(".")[:3]))
-
-class TWMock:
- def __init__(self):
- self.lines = []
- def sep(self, sep, line=None):
- self.lines.append((sep, line))
- def line(self, line, **kw):
- self.lines.append(line)
- def markup(self, text, **kw):
- return text
-
- fullwidth = 80
-
-def test_excinfo_simple():
- try:
- raise ValueError
- except ValueError:
- info = py.code.ExceptionInfo()
- assert info.type == ValueError
-
-def test_excinfo_getstatement():
- def g():
- raise ValueError
- def f():
- g()
- try:
- f()
- except ValueError:
- excinfo = py.code.ExceptionInfo()
- linenumbers = [py.code.getrawcode(f).co_firstlineno-1+3,
- py.code.getrawcode(f).co_firstlineno-1+1,
- py.code.getrawcode(g).co_firstlineno-1+1,]
- l = list(excinfo.traceback)
- foundlinenumbers = [x.lineno for x in l]
- assert foundlinenumbers == linenumbers
- #for x in info:
- # print "%s:%d %s" %(x.path.relto(root), x.lineno, x.statement)
- #xxx
-
-# testchain for getentries test below
-def f():
- #
- raise ValueError
- #
-def g():
- #
- __tracebackhide__ = True
- f()
- #
-def h():
- #
- g()
- #
-
-class TestTraceback_f_g_h:
- def setup_method(self, method):
- try:
- h()
- except ValueError:
- self.excinfo = py.code.ExceptionInfo()
-
- def test_traceback_entries(self):
- tb = self.excinfo.traceback
- entries = list(tb)
- assert len(tb) == 4 # maybe fragile test
- assert len(entries) == 4 # maybe fragile test
- names = ['f', 'g', 'h']
- for entry in entries:
- try:
- names.remove(entry.frame.code.name)
- except ValueError:
- pass
- assert not names
-
- def test_traceback_entry_getsource(self):
- tb = self.excinfo.traceback
- s = str(tb[-1].getsource() )
- assert s.startswith("def f():")
- assert s.endswith("raise ValueError")
-
- @astonly
- @failsonjython
- def test_traceback_entry_getsource_in_construct(self):
- source = py.code.Source("""\
- def xyz():
- try:
- raise ValueError
- except somenoname:
- pass
- xyz()
- """)
- try:
- exec (source.compile())
- except NameError:
- tb = py.code.ExceptionInfo().traceback
- print (tb[-1].getsource())
- s = str(tb[-1].getsource())
- assert s.startswith("def xyz():\n try:")
- assert s.strip().endswith("except somenoname:")
-
- def test_traceback_cut(self):
- co = py.code.Code(f)
- path, firstlineno = co.path, co.firstlineno
- traceback = self.excinfo.traceback
- newtraceback = traceback.cut(path=path, firstlineno=firstlineno)
- assert len(newtraceback) == 1
- newtraceback = traceback.cut(path=path, lineno=firstlineno+2)
- assert len(newtraceback) == 1
-
- def test_traceback_cut_excludepath(self, testdir):
- p = testdir.makepyfile("def f(): raise ValueError")
- excinfo = py.test.raises(ValueError, "p.pyimport().f()")
- basedir = py.path.local(py.test.__file__).dirpath()
- newtraceback = excinfo.traceback.cut(excludepath=basedir)
- for x in newtraceback:
- if hasattr(x, 'path'):
- assert not py.path.local(x.path).relto(basedir)
- assert newtraceback[-1].frame.code.path == p
-
- def test_traceback_filter(self):
- traceback = self.excinfo.traceback
- ntraceback = traceback.filter()
- assert len(ntraceback) == len(traceback) - 1
-
- def test_traceback_recursion_index(self):
- def f(n):
- if n < 10:
- n += 1
- f(n)
- excinfo = py.test.raises(RuntimeError, f, 8)
- traceback = excinfo.traceback
- recindex = traceback.recursionindex()
- assert recindex == 3
-
- def test_traceback_only_specific_recursion_errors(self, monkeypatch):
- def f(n):
- if n == 0:
- raise RuntimeError("hello")
- f(n-1)
-
- excinfo = pytest.raises(RuntimeError, f, 100)
- monkeypatch.delattr(excinfo.traceback.__class__, "recursionindex")
- repr = excinfo.getrepr()
- assert "RuntimeError: hello" in str(repr.reprcrash)
-
- def test_traceback_no_recursion_index(self):
- def do_stuff():
- raise RuntimeError
- def reraise_me():
- import sys
- exc, val, tb = sys.exc_info()
- py.builtin._reraise(exc, val, tb)
- def f(n):
- try:
- do_stuff()
- except:
- reraise_me()
- excinfo = py.test.raises(RuntimeError, f, 8)
- traceback = excinfo.traceback
- recindex = traceback.recursionindex()
- assert recindex is None
-
- def test_traceback_messy_recursion(self):
- #XXX: simplified locally testable version
- decorator = py.test.importorskip('decorator').decorator
-
- def log(f, *k, **kw):
- print('%s %s' % (k, kw))
- f(*k, **kw)
- log = decorator(log)
-
- def fail():
- raise ValueError('')
-
- fail = log(log(fail))
-
- excinfo = py.test.raises(ValueError, fail)
- assert excinfo.traceback.recursionindex() is None
-
-
-
- def test_traceback_getcrashentry(self):
- def i():
- __tracebackhide__ = True
- raise ValueError
- def h():
- i()
- def g():
- __tracebackhide__ = True
- h()
- def f():
- g()
-
- excinfo = py.test.raises(ValueError, f)
- tb = excinfo.traceback
- entry = tb.getcrashentry()
- co = py.code.Code(h)
- assert entry.frame.code.path == co.path
- assert entry.lineno == co.firstlineno + 1
- assert entry.frame.code.name == 'h'
-
- def test_traceback_getcrashentry_empty(self):
- def g():
- __tracebackhide__ = True
- raise ValueError
- def f():
- __tracebackhide__ = True
- g()
-
- excinfo = py.test.raises(ValueError, f)
- tb = excinfo.traceback
- entry = tb.getcrashentry()
- co = py.code.Code(g)
- assert entry.frame.code.path == co.path
- assert entry.lineno == co.firstlineno + 2
- assert entry.frame.code.name == 'g'
-
-def hello(x):
- x + 5
-
-def test_tbentry_reinterpret():
- try:
- hello("hello")
- except TypeError:
- excinfo = py.code.ExceptionInfo()
- tbentry = excinfo.traceback[-1]
- msg = tbentry.reinterpret()
- assert msg.startswith("TypeError: ('hello' + 5)")
-
-def test_excinfo_exconly():
- excinfo = py.test.raises(ValueError, h)
- assert excinfo.exconly().startswith('ValueError')
- excinfo = py.test.raises(ValueError,
- "raise ValueError('hello\\nworld')")
- msg = excinfo.exconly(tryshort=True)
- assert msg.startswith('ValueError')
- assert msg.endswith("world")
-
-def test_excinfo_repr():
- excinfo = py.test.raises(ValueError, h)
- s = repr(excinfo)
- assert s == "<ExceptionInfo ValueError tblen=4>"
-
-def test_excinfo_str():
- excinfo = py.test.raises(ValueError, h)
- s = str(excinfo)
- assert s.startswith(__file__[:-9]) # pyc file and $py.class
- assert s.endswith("ValueError")
- assert len(s.split(":")) >= 3 # on windows it's 4
-
-def test_excinfo_errisinstance():
- excinfo = py.test.raises(ValueError, h)
- assert excinfo.errisinstance(ValueError)
-
-def test_excinfo_no_sourcecode():
- try:
- exec ("raise ValueError()")
- except ValueError:
- excinfo = py.code.ExceptionInfo()
- s = str(excinfo.traceback[-1])
- if py.std.sys.version_info < (2,5):
- assert s == " File '<string>':1 in ?\n ???\n"
- else:
- assert s == " File '<string>':1 in <module>\n ???\n"
-
-def test_excinfo_no_python_sourcecode(tmpdir):
- #XXX: simplified locally testable version
- tmpdir.join('test.txt').write("{{ h()}}:")
-
- jinja2 = py.test.importorskip('jinja2')
- loader = jinja2.FileSystemLoader(str(tmpdir))
- env = jinja2.Environment(loader=loader)
- template = env.get_template('test.txt')
- excinfo = py.test.raises(ValueError,
- template.render, h=h)
- for item in excinfo.traceback:
- print(item) #XXX: for some reason jinja.Template.render is printed in full
- item.source # shouldnt fail
- if item.path.basename == 'test.txt':
- assert str(item.source) == '{{ h()}}:'
-
-
-def test_entrysource_Queue_example():
- try:
- queue.Queue().get(timeout=0.001)
- except queue.Empty:
- excinfo = py.code.ExceptionInfo()
- entry = excinfo.traceback[-1]
- source = entry.getsource()
- assert source is not None
- s = str(source).strip()
- assert s.startswith("def get")
-
-def test_codepath_Queue_example():
- try:
- queue.Queue().get(timeout=0.001)
- except queue.Empty:
- excinfo = py.code.ExceptionInfo()
- entry = excinfo.traceback[-1]
- path = entry.path
- assert isinstance(path, py.path.local)
- assert path.basename.lower() == "queue.py"
- assert path.check()
-
-class TestFormattedExcinfo:
- def pytest_funcarg__importasmod(self, request):
- def importasmod(source):
- source = py.code.Source(source)
- tmpdir = request.getfuncargvalue("tmpdir")
- modpath = tmpdir.join("mod.py")
- tmpdir.ensure("__init__.py")
- modpath.write(source)
- if invalidate_import_caches is not None:
- invalidate_import_caches()
- return modpath.pyimport()
- return importasmod
-
- def excinfo_from_exec(self, source):
- source = py.code.Source(source).strip()
- try:
- exec (source.compile())
- except KeyboardInterrupt:
- raise
- except:
- return py.code.ExceptionInfo()
- assert 0, "did not raise"
-
- def test_repr_source(self):
- pr = FormattedExcinfo()
- source = py.code.Source("""
- def f(x):
- pass
- """).strip()
- pr.flow_marker = "|"
- lines = pr.get_source(source, 0)
- assert len(lines) == 2
- assert lines[0] == "| def f(x):"
- assert lines[1] == " pass"
-
- def test_repr_source_excinfo(self):
- """ check if indentation is right """
- pr = FormattedExcinfo()
- excinfo = self.excinfo_from_exec("""
- def f():
- assert 0
- f()
- """)
- pr = FormattedExcinfo()
- source = pr._getentrysource(excinfo.traceback[-1])
- lines = pr.get_source(source, 1, excinfo)
- assert lines == [
- ' def f():',
- '> assert 0',
- 'E assert 0'
- ]
-
-
- def test_repr_source_not_existing(self):
- pr = FormattedExcinfo()
- co = compile("raise ValueError()", "", "exec")
- try:
- exec (co)
- except ValueError:
- excinfo = py.code.ExceptionInfo()
- repr = pr.repr_excinfo(excinfo)
- assert repr.reprtraceback.reprentries[1].lines[0] == "> ???"
-
- def test_repr_many_line_source_not_existing(self):
- pr = FormattedExcinfo()
- co = compile("""
-a = 1
-raise ValueError()
-""", "", "exec")
- try:
- exec (co)
- except ValueError:
- excinfo = py.code.ExceptionInfo()
- repr = pr.repr_excinfo(excinfo)
- assert repr.reprtraceback.reprentries[1].lines[0] == "> ???"
-
- def test_repr_source_failing_fullsource(self):
- pr = FormattedExcinfo()
-
- class FakeCode(object):
- class raw:
- co_filename = '?'
- path = '?'
- firstlineno = 5
-
- def fullsource(self):
- return None
- fullsource = property(fullsource)
-
- class FakeFrame(object):
- code = FakeCode()
- f_locals = {}
- f_globals = {}
-
- class FakeTracebackEntry(py.code.Traceback.Entry):
- def __init__(self, tb):
- self.lineno = 5+3
-
- @property
- def frame(self):
- return FakeFrame()
-
- class Traceback(py.code.Traceback):
- Entry = FakeTracebackEntry
-
- class FakeExcinfo(py.code.ExceptionInfo):
- typename = "Foo"
- def __init__(self):
- pass
-
- def exconly(self, tryshort):
- return "EXC"
- def errisinstance(self, cls):
- return False
-
- excinfo = FakeExcinfo()
- class FakeRawTB(object):
- tb_next = None
- tb = FakeRawTB()
- excinfo.traceback = Traceback(tb)
-
- fail = IOError()
- repr = pr.repr_excinfo(excinfo)
- assert repr.reprtraceback.reprentries[0].lines[0] == "> ???"
-
- fail = py.error.ENOENT
- repr = pr.repr_excinfo(excinfo)
- assert repr.reprtraceback.reprentries[0].lines[0] == "> ???"
-
-
- def test_repr_local(self):
- p = FormattedExcinfo(showlocals=True)
- loc = {'y': 5, 'z': 7, 'x': 3, '@x': 2, '__builtins__': {}}
- reprlocals = p.repr_locals(loc)
- assert reprlocals.lines
- assert reprlocals.lines[0] == '__builtins__ = <builtins>'
- assert reprlocals.lines[1] == 'x = 3'
- assert reprlocals.lines[2] == 'y = 5'
- assert reprlocals.lines[3] == 'z = 7'
-
- def test_repr_tracebackentry_lines(self, importasmod):
- mod = importasmod("""
- def func1():
- raise ValueError("hello\\nworld")
- """)
- excinfo = py.test.raises(ValueError, mod.func1)
- excinfo.traceback = excinfo.traceback.filter()
- p = FormattedExcinfo()
- reprtb = p.repr_traceback_entry(excinfo.traceback[-1])
-
- # test as intermittent entry
- lines = reprtb.lines
- assert lines[0] == ' def func1():'
- assert lines[1] == '> raise ValueError("hello\\nworld")'
-
- # test as last entry
- p = FormattedExcinfo(showlocals=True)
- repr_entry = p.repr_traceback_entry(excinfo.traceback[-1], excinfo)
- lines = repr_entry.lines
- assert lines[0] == ' def func1():'
- assert lines[1] == '> raise ValueError("hello\\nworld")'
- assert lines[2] == 'E ValueError: hello'
- assert lines[3] == 'E world'
- assert not lines[4:]
-
- loc = repr_entry.reprlocals is not None
- loc = repr_entry.reprfileloc
- assert loc.path == mod.__file__
- assert loc.lineno == 3
- #assert loc.message == "ValueError: hello"
-
- def test_repr_tracebackentry_lines(self, importasmod):
- mod = importasmod("""
- def func1(m, x, y, z):
- raise ValueError("hello\\nworld")
- """)
- excinfo = py.test.raises(ValueError, mod.func1, "m"*90, 5, 13, "z"*120)
- excinfo.traceback = excinfo.traceback.filter()
- entry = excinfo.traceback[-1]
- p = FormattedExcinfo(funcargs=True)
- reprfuncargs = p.repr_args(entry)
- assert reprfuncargs.args[0] == ('m', repr("m"*90))
- assert reprfuncargs.args[1] == ('x', '5')
- assert reprfuncargs.args[2] == ('y', '13')
- assert reprfuncargs.args[3] == ('z', repr("z" * 120))
-
- p = FormattedExcinfo(funcargs=True)
- repr_entry = p.repr_traceback_entry(entry)
- assert repr_entry.reprfuncargs.args == reprfuncargs.args
- tw = TWMock()
- repr_entry.toterminal(tw)
- assert tw.lines[0] == "m = " + repr('m' * 90)
- assert tw.lines[1] == "x = 5, y = 13"
- assert tw.lines[2] == "z = " + repr('z' * 120)
-
- def test_repr_tracebackentry_lines_var_kw_args(self, importasmod):
- mod = importasmod("""
- def func1(x, *y, **z):
- raise ValueError("hello\\nworld")
- """)
- excinfo = py.test.raises(ValueError, mod.func1, 'a', 'b', c='d')
- excinfo.traceback = excinfo.traceback.filter()
- entry = excinfo.traceback[-1]
- p = FormattedExcinfo(funcargs=True)
- reprfuncargs = p.repr_args(entry)
- assert reprfuncargs.args[0] == ('x', repr('a'))
- assert reprfuncargs.args[1] == ('y', repr(('b',)))
- assert reprfuncargs.args[2] == ('z', repr({'c': 'd'}))
-
- p = FormattedExcinfo(funcargs=True)
- repr_entry = p.repr_traceback_entry(entry)
- assert repr_entry.reprfuncargs.args == reprfuncargs.args
- tw = TWMock()
- repr_entry.toterminal(tw)
- assert tw.lines[0] == "x = 'a', y = ('b',), z = {'c': 'd'}"
-
- def test_repr_tracebackentry_short(self, importasmod):
- mod = importasmod("""
- def func1():
- raise ValueError("hello")
- def entry():
- func1()
- """)
- excinfo = py.test.raises(ValueError, mod.entry)
- p = FormattedExcinfo(style="short")
- reprtb = p.repr_traceback_entry(excinfo.traceback[-2])
- lines = reprtb.lines
- basename = py.path.local(mod.__file__).basename
- assert lines[0] == ' func1()'
- assert basename in str(reprtb.reprfileloc.path)
- assert reprtb.reprfileloc.lineno == 5
-
- # test last entry
- p = FormattedExcinfo(style="short")
- reprtb = p.repr_traceback_entry(excinfo.traceback[-1], excinfo)
- lines = reprtb.lines
- assert lines[0] == ' raise ValueError("hello")'
- assert lines[1] == 'E ValueError: hello'
- assert basename in str(reprtb.reprfileloc.path)
- assert reprtb.reprfileloc.lineno == 3
-
- def test_repr_tracebackentry_no(self, importasmod):
- mod = importasmod("""
- def func1():
- raise ValueError("hello")
- def entry():
- func1()
- """)
- excinfo = py.test.raises(ValueError, mod.entry)
- p = FormattedExcinfo(style="no")
- p.repr_traceback_entry(excinfo.traceback[-2])
-
- p = FormattedExcinfo(style="no")
- reprentry = p.repr_traceback_entry(excinfo.traceback[-1], excinfo)
- lines = reprentry.lines
- assert lines[0] == 'E ValueError: hello'
- assert not lines[1:]
-
- def test_repr_traceback_tbfilter(self, importasmod):
- mod = importasmod("""
- def f(x):
- raise ValueError(x)
- def entry():
- f(0)
- """)
- excinfo = py.test.raises(ValueError, mod.entry)
- p = FormattedExcinfo(tbfilter=True)
- reprtb = p.repr_traceback(excinfo)
- assert len(reprtb.reprentries) == 2
- p = FormattedExcinfo(tbfilter=False)
- reprtb = p.repr_traceback(excinfo)
- assert len(reprtb.reprentries) == 3
-
- def test_traceback_short_no_source(self, importasmod, monkeypatch):
- mod = importasmod("""
- def func1():
- raise ValueError("hello")
- def entry():
- func1()
- """)
- excinfo = py.test.raises(ValueError, mod.entry)
- from py._code.code import Code
- monkeypatch.setattr(Code, 'path', 'bogus')
- excinfo.traceback[0].frame.code.path = "bogus"
- p = FormattedExcinfo(style="short")
- reprtb = p.repr_traceback_entry(excinfo.traceback[-2])
- lines = reprtb.lines
- last_p = FormattedExcinfo(style="short")
- last_reprtb = last_p.repr_traceback_entry(excinfo.traceback[-1], excinfo)
- last_lines = last_reprtb.lines
- monkeypatch.undo()
- basename = py.path.local(mod.__file__).basename
- assert lines[0] == ' func1()'
-
- assert last_lines[0] == ' raise ValueError("hello")'
- assert last_lines[1] == 'E ValueError: hello'
-
- def test_repr_traceback_and_excinfo(self, importasmod):
- mod = importasmod("""
- def f(x):
- raise ValueError(x)
- def entry():
- f(0)
- """)
- excinfo = py.test.raises(ValueError, mod.entry)
-
- for style in ("long", "short"):
- p = FormattedExcinfo(style=style)
- reprtb = p.repr_traceback(excinfo)
- assert len(reprtb.reprentries) == 2
- assert reprtb.style == style
- assert not reprtb.extraline
- repr = p.repr_excinfo(excinfo)
- assert repr.reprtraceback
- assert len(repr.reprtraceback.reprentries) == len(reprtb.reprentries)
- assert repr.reprcrash.path.endswith("mod.py")
- assert repr.reprcrash.message == "ValueError: 0"
-
- def test_repr_traceback_with_invalid_cwd(self, importasmod, monkeypatch):
- mod = importasmod("""
- def f(x):
- raise ValueError(x)
- def entry():
- f(0)
- """)
- excinfo = py.test.raises(ValueError, mod.entry)
-
- p = FormattedExcinfo()
- def raiseos():
- raise OSError(2)
- monkeypatch.setattr(py.std.os, 'getcwd', raiseos)
- assert p._makepath(__file__) == __file__
- reprtb = p.repr_traceback(excinfo)
-
- def test_repr_excinfo_addouterr(self, importasmod):
- mod = importasmod("""
- def entry():
- raise ValueError()
- """)
- excinfo = py.test.raises(ValueError, mod.entry)
- repr = excinfo.getrepr()
- repr.addsection("title", "content")
- twmock = TWMock()
- repr.toterminal(twmock)
- assert twmock.lines[-1] == "content"
- assert twmock.lines[-2] == ("-", "title")
-
- def test_repr_excinfo_reprcrash(self, importasmod):
- mod = importasmod("""
- def entry():
- raise ValueError()
- """)
- excinfo = py.test.raises(ValueError, mod.entry)
- repr = excinfo.getrepr()
- assert repr.reprcrash.path.endswith("mod.py")
- assert repr.reprcrash.lineno == 3
- assert repr.reprcrash.message == "ValueError"
- assert str(repr.reprcrash).endswith("mod.py:3: ValueError")
-
- def test_repr_traceback_recursion(self, importasmod):
- mod = importasmod("""
- def rec2(x):
- return rec1(x+1)
- def rec1(x):
- return rec2(x-1)
- def entry():
- rec1(42)
- """)
- excinfo = py.test.raises(RuntimeError, mod.entry)
-
- for style in ("short", "long", "no"):
- p = FormattedExcinfo(style="short")
- reprtb = p.repr_traceback(excinfo)
- assert reprtb.extraline == "!!! Recursion detected (same locals & position)"
- assert str(reprtb)
-
- def test_tb_entry_AssertionError(self, importasmod):
- # probably this test is a bit redundant
- # as py/magic/testing/test_assertion.py
- # already tests correctness of
- # assertion-reinterpretation logic
- mod = importasmod("""
- def somefunc():
- x = 1
- assert x == 2
- """)
- excinfo = py.test.raises(AssertionError, mod.somefunc)
-
- p = FormattedExcinfo()
- reprentry = p.repr_traceback_entry(excinfo.traceback[-1], excinfo)
- lines = reprentry.lines
- assert lines[-1] == "E assert 1 == 2"
-
- def test_reprexcinfo_getrepr(self, importasmod):
- mod = importasmod("""
- def f(x):
- raise ValueError(x)
- def entry():
- f(0)
- """)
- excinfo = py.test.raises(ValueError, mod.entry)
-
- for style in ("short", "long", "no"):
- for showlocals in (True, False):
- repr = excinfo.getrepr(style=style, showlocals=showlocals)
- assert isinstance(repr, ReprExceptionInfo)
- assert repr.reprtraceback.style == style
-
- def test_reprexcinfo_unicode(self):
- from py._code.code import TerminalRepr
- class MyRepr(TerminalRepr):
- def toterminal(self, tw):
- tw.line(py.builtin._totext("я", "utf-8"))
- x = py.builtin._totext(MyRepr())
- assert x == py.builtin._totext("я", "utf-8")
-
- def test_toterminal_long(self, importasmod):
- mod = importasmod("""
- def g(x):
- raise ValueError(x)
- def f():
- g(3)
- """)
- excinfo = py.test.raises(ValueError, mod.f)
- excinfo.traceback = excinfo.traceback.filter()
- repr = excinfo.getrepr()
- tw = TWMock()
- repr.toterminal(tw)
- assert tw.lines[0] == ""
- tw.lines.pop(0)
- assert tw.lines[0] == " def f():"
- assert tw.lines[1] == "> g(3)"
- assert tw.lines[2] == ""
- assert tw.lines[3].endswith("mod.py:5: ")
- assert tw.lines[4] == ("_ ", None)
- assert tw.lines[5] == ""
- assert tw.lines[6] == " def g(x):"
- assert tw.lines[7] == "> raise ValueError(x)"
- assert tw.lines[8] == "E ValueError: 3"
- assert tw.lines[9] == ""
- assert tw.lines[10].endswith("mod.py:3: ValueError")
-
- def test_toterminal_long_missing_source(self, importasmod, tmpdir):
- mod = importasmod("""
- def g(x):
- raise ValueError(x)
- def f():
- g(3)
- """)
- excinfo = py.test.raises(ValueError, mod.f)
- tmpdir.join('mod.py').remove()
- excinfo.traceback = excinfo.traceback.filter()
- repr = excinfo.getrepr()
- tw = TWMock()
- repr.toterminal(tw)
- assert tw.lines[0] == ""
- tw.lines.pop(0)
- assert tw.lines[0] == "> ???"
- assert tw.lines[1] == ""
- assert tw.lines[2].endswith("mod.py:5: ")
- assert tw.lines[3] == ("_ ", None)
- assert tw.lines[4] == ""
- assert tw.lines[5] == "> ???"
- assert tw.lines[6] == "E ValueError: 3"
- assert tw.lines[7] == ""
- assert tw.lines[8].endswith("mod.py:3: ValueError")
-
- def test_toterminal_long_incomplete_source(self, importasmod, tmpdir):
- mod = importasmod("""
- def g(x):
- raise ValueError(x)
- def f():
- g(3)
- """)
- excinfo = py.test.raises(ValueError, mod.f)
- tmpdir.join('mod.py').write('asdf')
- excinfo.traceback = excinfo.traceback.filter()
- repr = excinfo.getrepr()
- tw = TWMock()
- repr.toterminal(tw)
- assert tw.lines[0] == ""
- tw.lines.pop(0)
- assert tw.lines[0] == "> ???"
- assert tw.lines[1] == ""
- assert tw.lines[2].endswith("mod.py:5: ")
- assert tw.lines[3] == ("_ ", None)
- assert tw.lines[4] == ""
- assert tw.lines[5] == "> ???"
- assert tw.lines[6] == "E ValueError: 3"
- assert tw.lines[7] == ""
- assert tw.lines[8].endswith("mod.py:3: ValueError")
-
- def test_toterminal_long_filenames(self, importasmod):
- mod = importasmod("""
- def f():
- raise ValueError()
- """)
- excinfo = py.test.raises(ValueError, mod.f)
- tw = TWMock()
- path = py.path.local(mod.__file__)
- old = path.dirpath().chdir()
- try:
- repr = excinfo.getrepr(abspath=False)
- repr.toterminal(tw)
- line = tw.lines[-1]
- x = py.path.local().bestrelpath(path)
- if len(x) < len(str(path)):
- assert line == "mod.py:3: ValueError"
-
- repr = excinfo.getrepr(abspath=True)
- repr.toterminal(tw)
- line = tw.lines[-1]
- assert line == "%s:3: ValueError" %(path,)
- finally:
- old.chdir()
-
- @py.test.mark.multi(reproptions=[
- {'style': style, 'showlocals': showlocals,
- 'funcargs': funcargs, 'tbfilter': tbfilter
- } for style in ("long", "short", "no")
- for showlocals in (True, False)
- for tbfilter in (True, False)
- for funcargs in (True, False)])
- def test_format_excinfo(self, importasmod, reproptions):
- mod = importasmod("""
- def g(x):
- raise ValueError(x)
- def f():
- g(3)
- """)
- excinfo = py.test.raises(ValueError, mod.f)
- tw = py.io.TerminalWriter(stringio=True)
- repr = excinfo.getrepr(**reproptions)
- repr.toterminal(tw)
- assert tw.stringio.getvalue()
-
-
- def test_native_style(self):
- excinfo = self.excinfo_from_exec("""
- assert 0
- """)
- repr = excinfo.getrepr(style='native')
- assert "assert 0" in str(repr.reprcrash)
- s = str(repr)
- assert s.startswith('Traceback (most recent call last):\n File')
- assert s.endswith('\nAssertionError: assert 0')
- assert 'exec (source.compile())' in s
- # python 2.4 fails to get the source line for the assert
- if py.std.sys.version_info >= (2, 5):
- assert s.count('assert 0') == 2
-
- def test_traceback_repr_style(self, importasmod):
- mod = importasmod("""
- def f():
- g()
- def g():
- h()
- def h():
- i()
- def i():
- raise ValueError()
- """)
- excinfo = py.test.raises(ValueError, mod.f)
- excinfo.traceback = excinfo.traceback.filter()
- excinfo.traceback[1].set_repr_style("short")
- excinfo.traceback[2].set_repr_style("short")
- r = excinfo.getrepr(style="long")
- tw = TWMock()
- r.toterminal(tw)
- for line in tw.lines: print (line)
- assert tw.lines[0] == ""
- assert tw.lines[1] == " def f():"
- assert tw.lines[2] == "> g()"
- assert tw.lines[3] == ""
- assert tw.lines[4].endswith("mod.py:3: ")
- assert tw.lines[5] == ("_ ", None)
- assert tw.lines[6].endswith("in g")
- assert tw.lines[7] == " h()"
- assert tw.lines[8].endswith("in h")
- assert tw.lines[9] == " i()"
- assert tw.lines[10] == ("_ ", None)
- assert tw.lines[11] == ""
- assert tw.lines[12] == " def i():"
- assert tw.lines[13] == "> raise ValueError()"
- assert tw.lines[14] == "E ValueError"
- assert tw.lines[15] == ""
- assert tw.lines[16].endswith("mod.py:9: ValueError")
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/code/test_source.py b/tests/wpt/web-platform-tests/tools/py/testing/code/test_source.py
deleted file mode 100644
index 830de2c95de..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/testing/code/test_source.py
+++ /dev/null
@@ -1,651 +0,0 @@
-from py.code import Source
-import py
-import sys
-
-from py._code.source import _ast
-if _ast is not None:
- astonly = py.test.mark.nothing
-else:
- astonly = py.test.mark.xfail("True", reason="only works with AST-compile")
-
-failsonjython = py.test.mark.xfail("sys.platform.startswith('java')")
-
-def test_source_str_function():
- x = Source("3")
- assert str(x) == "3"
-
- x = Source(" 3")
- assert str(x) == "3"
-
- x = Source("""
- 3
- """, rstrip=False)
- assert str(x) == "\n3\n "
-
- x = Source("""
- 3
- """, rstrip=True)
- assert str(x) == "\n3"
-
-def test_unicode():
- try:
- unicode
- except NameError:
- return
- x = Source(unicode("4"))
- assert str(x) == "4"
- co = py.code.compile(unicode('u"\xc3\xa5"', 'utf8'), mode='eval')
- val = eval(co)
- assert isinstance(val, unicode)
-
-def test_source_from_function():
- source = py.code.Source(test_source_str_function)
- assert str(source).startswith('def test_source_str_function():')
-
-def test_source_from_method():
- class TestClass:
- def test_method(self):
- pass
- source = py.code.Source(TestClass().test_method)
- assert source.lines == ["def test_method(self):",
- " pass"]
-
-def test_source_from_lines():
- lines = ["a \n", "b\n", "c"]
- source = py.code.Source(lines)
- assert source.lines == ['a ', 'b', 'c']
-
-def test_source_from_inner_function():
- def f():
- pass
- source = py.code.Source(f, deindent=False)
- assert str(source).startswith(' def f():')
- source = py.code.Source(f)
- assert str(source).startswith('def f():')
-
-def test_source_putaround_simple():
- source = Source("raise ValueError")
- source = source.putaround(
- "try:", """\
- except ValueError:
- x = 42
- else:
- x = 23""")
- assert str(source)=="""\
-try:
- raise ValueError
-except ValueError:
- x = 42
-else:
- x = 23"""
-
-def test_source_putaround():
- source = Source()
- source = source.putaround("""
- if 1:
- x=1
- """)
- assert str(source).strip() == "if 1:\n x=1"
-
-def test_source_strips():
- source = Source("")
- assert source == Source()
- assert str(source) == ''
- assert source.strip() == source
-
-def test_source_strip_multiline():
- source = Source()
- source.lines = ["", " hello", " "]
- source2 = source.strip()
- assert source2.lines == [" hello"]
-
-def test_syntaxerror_rerepresentation():
- ex = py.test.raises(SyntaxError, py.code.compile, 'xyz xyz')
- assert ex.value.lineno == 1
- assert ex.value.offset in (4,7) # XXX pypy/jython versus cpython?
- assert ex.value.text.strip(), 'x x'
-
-def test_isparseable():
- assert Source("hello").isparseable()
- assert Source("if 1:\n pass").isparseable()
- assert Source(" \nif 1:\n pass").isparseable()
- assert not Source("if 1:\n").isparseable()
- assert not Source(" \nif 1:\npass").isparseable()
- assert not Source(chr(0)).isparseable()
-
-class TestAccesses:
- source = Source("""\
- def f(x):
- pass
- def g(x):
- pass
- """)
- def test_getrange(self):
- x = self.source[0:2]
- assert x.isparseable()
- assert len(x.lines) == 2
- assert str(x) == "def f(x):\n pass"
-
- def test_getline(self):
- x = self.source[0]
- assert x == "def f(x):"
-
- def test_len(self):
- assert len(self.source) == 4
-
- def test_iter(self):
- l = [x for x in self.source]
- assert len(l) == 4
-
-class TestSourceParsingAndCompiling:
- source = Source("""\
- def f(x):
- assert (x ==
- 3 +
- 4)
- """).strip()
-
- def test_compile(self):
- co = py.code.compile("x=3")
- d = {}
- exec (co, d)
- assert d['x'] == 3
-
- def test_compile_and_getsource_simple(self):
- co = py.code.compile("x=3")
- exec (co)
- source = py.code.Source(co)
- assert str(source) == "x=3"
-
- def test_compile_and_getsource_through_same_function(self):
- def gensource(source):
- return py.code.compile(source)
- co1 = gensource("""
- def f():
- raise KeyError()
- """)
- co2 = gensource("""
- def f():
- raise ValueError()
- """)
- source1 = py.std.inspect.getsource(co1)
- assert 'KeyError' in source1
- source2 = py.std.inspect.getsource(co2)
- assert 'ValueError' in source2
-
- def test_getstatement(self):
- #print str(self.source)
- ass = str(self.source[1:])
- for i in range(1, 4):
- #print "trying start in line %r" % self.source[i]
- s = self.source.getstatement(i)
- #x = s.deindent()
- assert str(s) == ass
-
- def test_getstatementrange_triple_quoted(self):
- #print str(self.source)
- source = Source("""hello('''
- ''')""")
- s = source.getstatement(0)
- assert s == str(source)
- s = source.getstatement(1)
- assert s == str(source)
-
- @astonly
- def test_getstatementrange_within_constructs(self):
- source = Source("""\
- try:
- try:
- raise ValueError
- except SomeThing:
- pass
- finally:
- 42
- """)
- assert len(source) == 7
- # check all lineno's that could occur in a traceback
- #assert source.getstatementrange(0) == (0, 7)
- #assert source.getstatementrange(1) == (1, 5)
- assert source.getstatementrange(2) == (2, 3)
- assert source.getstatementrange(3) == (3, 4)
- assert source.getstatementrange(4) == (4, 5)
- #assert source.getstatementrange(5) == (0, 7)
- assert source.getstatementrange(6) == (6, 7)
-
- def test_getstatementrange_bug(self):
- source = Source("""\
- try:
- x = (
- y +
- z)
- except:
- pass
- """)
- assert len(source) == 6
- assert source.getstatementrange(2) == (1, 4)
-
- def test_getstatementrange_bug2(self):
- source = Source("""\
- assert (
- 33
- ==
- [
- X(3,
- b=1, c=2
- ),
- ]
- )
- """)
- assert len(source) == 9
- assert source.getstatementrange(5) == (0, 9)
-
- def test_getstatementrange_ast_issue58(self):
- source = Source("""\
-
- def test_some():
- for a in [a for a in
- CAUSE_ERROR]: pass
-
- x = 3
- """)
- assert getstatement(2, source).lines == source.lines[2:3]
- assert getstatement(3, source).lines == source.lines[3:4]
-
- @py.test.mark.skipif("sys.version_info < (2,6)")
- def test_getstatementrange_out_of_bounds_py3(self):
- source = Source("if xxx:\n from .collections import something")
- r = source.getstatementrange(1)
- assert r == (1,2)
-
- def test_getstatementrange_with_syntaxerror_issue7(self):
- source = Source(":")
- py.test.raises(SyntaxError, lambda: source.getstatementrange(0))
-
- @py.test.mark.skipif("sys.version_info < (2,6)")
- def test_compile_to_ast(self):
- import ast
- source = Source("x = 4")
- mod = source.compile(flag=ast.PyCF_ONLY_AST)
- assert isinstance(mod, ast.Module)
- compile(mod, "<filename>", "exec")
-
- def test_compile_and_getsource(self):
- co = self.source.compile()
- py.builtin.exec_(co, globals())
- f(7)
- excinfo = py.test.raises(AssertionError, "f(6)")
- frame = excinfo.traceback[-1].frame
- stmt = frame.code.fullsource.getstatement(frame.lineno)
- #print "block", str(block)
- assert str(stmt).strip().startswith('assert')
-
- def test_compilefuncs_and_path_sanity(self):
- def check(comp, name):
- co = comp(self.source, name)
- if not name:
- expected = "codegen %s:%d>" %(mypath, mylineno+2+1)
- else:
- expected = "codegen %r %s:%d>" % (name, mypath, mylineno+2+1)
- fn = co.co_filename
- assert fn.endswith(expected)
-
- mycode = py.code.Code(self.test_compilefuncs_and_path_sanity)
- mylineno = mycode.firstlineno
- mypath = mycode.path
-
- for comp in py.code.compile, py.code.Source.compile:
- for name in '', None, 'my':
- yield check, comp, name
-
- def test_offsetless_synerr(self):
- py.test.raises(SyntaxError, py.code.compile, "lambda a,a: 0", mode='eval')
-
-def test_getstartingblock_singleline():
- class A:
- def __init__(self, *args):
- frame = sys._getframe(1)
- self.source = py.code.Frame(frame).statement
-
- x = A('x', 'y')
-
- l = [i for i in x.source.lines if i.strip()]
- assert len(l) == 1
-
-def test_getstartingblock_multiline():
- class A:
- def __init__(self, *args):
- frame = sys._getframe(1)
- self.source = py.code.Frame(frame).statement
-
- x = A('x',
- 'y' \
- ,
- 'z')
-
- l = [i for i in x.source.lines if i.strip()]
- assert len(l) == 4
-
-def test_getline_finally():
- def c(): pass
- excinfo = py.test.raises(TypeError, """
- teardown = None
- try:
- c(1)
- finally:
- if teardown:
- teardown()
- """)
- source = excinfo.traceback[-1].statement
- assert str(source).strip() == 'c(1)'
-
-def test_getfuncsource_dynamic():
- source = """
- def f():
- raise ValueError
-
- def g(): pass
- """
- co = py.code.compile(source)
- py.builtin.exec_(co, globals())
- assert str(py.code.Source(f)).strip() == 'def f():\n raise ValueError'
- assert str(py.code.Source(g)).strip() == 'def g(): pass'
-
-
-def test_getfuncsource_with_multine_string():
- def f():
- c = '''while True:
- pass
-'''
- assert str(py.code.Source(f)).strip() == "def f():\n c = '''while True:\n pass\n'''"
-
-
-def test_deindent():
- from py._code.source import deindent as deindent
- assert deindent(['\tfoo', '\tbar', ]) == ['foo', 'bar']
-
- def f():
- c = '''while True:
- pass
-'''
- import inspect
- lines = deindent(inspect.getsource(f).splitlines())
- assert lines == ["def f():", " c = '''while True:", " pass", "'''"]
-
- source = """
- def f():
- def g():
- pass
- """
- lines = deindent(source.splitlines())
- assert lines == ['', 'def f():', ' def g():', ' pass', ' ']
-
-@py.test.mark.xfail("sys.version_info[:3] < (2,7,0) or "
- "((3,0) <= sys.version_info[:2] < (3,2))")
-def test_source_of_class_at_eof_without_newline(tmpdir):
- # this test fails because the implicit inspect.getsource(A) below
- # does not return the "x = 1" last line.
- source = py.code.Source('''
- class A(object):
- def method(self):
- x = 1
- ''')
- path = tmpdir.join("a.py")
- path.write(source)
- s2 = py.code.Source(tmpdir.join("a.py").pyimport().A)
- assert str(source).strip() == str(s2).strip()
-
-if True:
- def x():
- pass
-
-def test_getsource_fallback():
- from py._code.source import getsource
- expected = """def x():
- pass"""
- src = getsource(x)
- assert src == expected
-
-def test_idem_compile_and_getsource():
- from py._code.source import getsource
- expected = "def x(): pass"
- co = py.code.compile(expected)
- src = getsource(co)
- assert src == expected
-
-def test_findsource_fallback():
- from py._code.source import findsource
- src, lineno = findsource(x)
- assert 'test_findsource_simple' in str(src)
- assert src[lineno] == ' def x():'
-
-def test_findsource():
- from py._code.source import findsource
- co = py.code.compile("""if 1:
- def x():
- pass
-""")
-
- src, lineno = findsource(co)
- assert 'if 1:' in str(src)
-
- d = {}
- eval(co, d)
- src, lineno = findsource(d['x'])
- assert 'if 1:' in str(src)
- assert src[lineno] == " def x():"
-
-
-def test_getfslineno():
- from py.code import getfslineno
-
- def f(x):
- pass
-
- fspath, lineno = getfslineno(f)
-
- assert fspath.basename == "test_source.py"
- assert lineno == py.code.getrawcode(f).co_firstlineno-1 # see findsource
-
- class A(object):
- pass
-
- fspath, lineno = getfslineno(A)
-
- _, A_lineno = py.std.inspect.findsource(A)
- assert fspath.basename == "test_source.py"
- assert lineno == A_lineno
-
- assert getfslineno(3) == ("", -1)
- class B:
- pass
- B.__name__ = "B2"
- assert getfslineno(B)[1] == -1
-
-def test_code_of_object_instance_with_call():
- class A:
- pass
- py.test.raises(TypeError, lambda: py.code.Source(A()))
- class WithCall:
- def __call__(self):
- pass
-
- code = py.code.Code(WithCall())
- assert 'pass' in str(code.source())
-
- class Hello(object):
- def __call__(self):
- pass
- py.test.raises(TypeError, lambda: py.code.Code(Hello))
-
-
-def getstatement(lineno, source):
- from py._code.source import getstatementrange_ast
- source = py.code.Source(source, deindent=False)
- ast, start, end = getstatementrange_ast(lineno, source)
- return source[start:end]
-
-def test_oneline():
- source = getstatement(0, "raise ValueError")
- assert str(source) == "raise ValueError"
-
-def test_comment_and_no_newline_at_end():
- from py._code.source import getstatementrange_ast
- source = Source(['def test_basic_complex():',
- ' assert 1 == 2',
- '# vim: filetype=pyopencl:fdm=marker'])
- ast, start, end = getstatementrange_ast(1, source)
- assert end == 2
-
-def test_oneline_and_comment():
- source = getstatement(0, "raise ValueError\n#hello")
- assert str(source) == "raise ValueError"
-
-def test_comments():
- source = '''def test():
- "comment 1"
- x = 1
- # comment 2
- # comment 3
-
- assert False
-
-"""
-comment 4
-"""
-'''
- for line in range(2,6):
- assert str(getstatement(line, source)) == ' x = 1'
- for line in range(6,10):
- assert str(getstatement(line, source)) == ' assert False'
- assert str(getstatement(10, source)) == '"""'
-
-def test_comment_in_statement():
- source = '''test(foo=1,
- # comment 1
- bar=2)
-'''
- for line in range(1,3):
- assert str(getstatement(line, source)) == \
- 'test(foo=1,\n # comment 1\n bar=2)'
-
-def test_single_line_else():
- source = getstatement(1, "if False: 2\nelse: 3")
- assert str(source) == "else: 3"
-
-def test_single_line_finally():
- source = getstatement(1, "try: 1\nfinally: 3")
- assert str(source) == "finally: 3"
-
-def test_issue55():
- source = ('def round_trip(dinp):\n assert 1 == dinp\n'
- 'def test_rt():\n round_trip("""\n""")\n')
- s = getstatement(3, source)
- assert str(s) == ' round_trip("""\n""")'
-
-
-def XXXtest_multiline():
- source = getstatement(0, """\
-raise ValueError(
- 23
-)
-x = 3
-""")
- assert str(source) == "raise ValueError(\n 23\n)"
-
-class TestTry:
- pytestmark = astonly
- source = """\
-try:
- raise ValueError
-except Something:
- raise IndexError(1)
-else:
- raise KeyError()
-"""
-
- def test_body(self):
- source = getstatement(1, self.source)
- assert str(source) == " raise ValueError"
-
- def test_except_line(self):
- source = getstatement(2, self.source)
- assert str(source) == "except Something:"
-
- def test_except_body(self):
- source = getstatement(3, self.source)
- assert str(source) == " raise IndexError(1)"
-
- def test_else(self):
- source = getstatement(5, self.source)
- assert str(source) == " raise KeyError()"
-
-class TestTryFinally:
- source = """\
-try:
- raise ValueError
-finally:
- raise IndexError(1)
-"""
-
- def test_body(self):
- source = getstatement(1, self.source)
- assert str(source) == " raise ValueError"
-
- def test_finally(self):
- source = getstatement(3, self.source)
- assert str(source) == " raise IndexError(1)"
-
-
-
-class TestIf:
- pytestmark = astonly
- source = """\
-if 1:
- y = 3
-elif False:
- y = 5
-else:
- y = 7
-"""
-
- def test_body(self):
- source = getstatement(1, self.source)
- assert str(source) == " y = 3"
-
- def test_elif_clause(self):
- source = getstatement(2, self.source)
- assert str(source) == "elif False:"
-
- def test_elif(self):
- source = getstatement(3, self.source)
- assert str(source) == " y = 5"
-
- def test_else(self):
- source = getstatement(5, self.source)
- assert str(source) == " y = 7"
-
-def test_semicolon():
- s = """\
-hello ; pytest.skip()
-"""
- source = getstatement(0, s)
- assert str(source) == s.strip()
-
-def test_def_online():
- s = """\
-def func(): raise ValueError(42)
-
-def something():
- pass
-"""
- source = getstatement(0, s)
- assert str(source) == "def func(): raise ValueError(42)"
-
-def XXX_test_expression_multiline():
- source = """\
-something
-'''
-'''"""
- result = getstatement(1, source)
- assert str(result) == "'''\n'''"
-
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/io_/test_capture.py b/tests/wpt/web-platform-tests/tools/py/testing/io_/test_capture.py
deleted file mode 100644
index 5745e12a1a1..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/testing/io_/test_capture.py
+++ /dev/null
@@ -1,501 +0,0 @@
-from __future__ import with_statement
-
-import os, sys
-import py
-
-needsdup = py.test.mark.skipif("not hasattr(os, 'dup')")
-
-from py.builtin import print_
-
-if sys.version_info >= (3,0):
- def tobytes(obj):
- if isinstance(obj, str):
- obj = obj.encode('UTF-8')
- assert isinstance(obj, bytes)
- return obj
- def totext(obj):
- if isinstance(obj, bytes):
- obj = str(obj, 'UTF-8')
- assert isinstance(obj, str)
- return obj
-else:
- def tobytes(obj):
- if isinstance(obj, unicode):
- obj = obj.encode('UTF-8')
- assert isinstance(obj, str)
- return obj
- def totext(obj):
- if isinstance(obj, str):
- obj = unicode(obj, 'UTF-8')
- assert isinstance(obj, unicode)
- return obj
-
-def oswritebytes(fd, obj):
- os.write(fd, tobytes(obj))
-
-class TestTextIO:
- def test_text(self):
- f = py.io.TextIO()
- f.write("hello")
- s = f.getvalue()
- assert s == "hello"
- f.close()
-
- def test_unicode_and_str_mixture(self):
- f = py.io.TextIO()
- if sys.version_info >= (3,0):
- f.write("\u00f6")
- py.test.raises(TypeError, "f.write(bytes('hello', 'UTF-8'))")
- else:
- f.write(unicode("\u00f6", 'UTF-8'))
- f.write("hello") # bytes
- s = f.getvalue()
- f.close()
- assert isinstance(s, unicode)
-
-def test_bytes_io():
- f = py.io.BytesIO()
- f.write(tobytes("hello"))
- py.test.raises(TypeError, "f.write(totext('hello'))")
- s = f.getvalue()
- assert s == tobytes("hello")
-
-def test_dontreadfrominput():
- from py._io.capture import DontReadFromInput
- f = DontReadFromInput()
- assert not f.isatty()
- py.test.raises(IOError, f.read)
- py.test.raises(IOError, f.readlines)
- py.test.raises(IOError, iter, f)
- py.test.raises(ValueError, f.fileno)
- f.close() # just for completeness
-
-def pytest_funcarg__tmpfile(request):
- testdir = request.getfuncargvalue("testdir")
- f = testdir.makepyfile("").open('wb+')
- request.addfinalizer(f.close)
- return f
-
-@needsdup
-def test_dupfile(tmpfile):
- flist = []
- for i in range(5):
- nf = py.io.dupfile(tmpfile, encoding="utf-8")
- assert nf != tmpfile
- assert nf.fileno() != tmpfile.fileno()
- assert nf not in flist
- print_(i, end="", file=nf)
- flist.append(nf)
- for i in range(5):
- f = flist[i]
- f.close()
- tmpfile.seek(0)
- s = tmpfile.read()
- assert "01234" in repr(s)
- tmpfile.close()
-
-def test_dupfile_no_mode():
- """
- dupfile should trap an AttributeError and return f if no mode is supplied.
- """
- class SomeFileWrapper(object):
- "An object with a fileno method but no mode attribute"
- def fileno(self):
- return 1
- tmpfile = SomeFileWrapper()
- assert py.io.dupfile(tmpfile) is tmpfile
- with py.test.raises(AttributeError):
- py.io.dupfile(tmpfile, raising=True)
-
-def lsof_check(func):
- pid = os.getpid()
- try:
- out = py.process.cmdexec("lsof -p %d" % pid)
- except py.process.cmdexec.Error:
- py.test.skip("could not run 'lsof'")
- func()
- out2 = py.process.cmdexec("lsof -p %d" % pid)
- len1 = len([x for x in out.split("\n") if "REG" in x])
- len2 = len([x for x in out2.split("\n") if "REG" in x])
- assert len2 < len1 + 3, out2
-
-class TestFDCapture:
- pytestmark = needsdup
-
- def test_not_now(self, tmpfile):
- fd = tmpfile.fileno()
- cap = py.io.FDCapture(fd, now=False)
- data = tobytes("hello")
- os.write(fd, data)
- f = cap.done()
- s = f.read()
- assert not s
- cap = py.io.FDCapture(fd, now=False)
- cap.start()
- os.write(fd, data)
- f = cap.done()
- s = f.read()
- assert s == "hello"
-
- def test_simple(self, tmpfile):
- fd = tmpfile.fileno()
- cap = py.io.FDCapture(fd)
- data = tobytes("hello")
- os.write(fd, data)
- f = cap.done()
- s = f.read()
- assert s == "hello"
- f.close()
-
- def test_simple_many(self, tmpfile):
- for i in range(10):
- self.test_simple(tmpfile)
-
- def test_simple_many_check_open_files(self, tmpfile):
- lsof_check(lambda: self.test_simple_many(tmpfile))
-
- def test_simple_fail_second_start(self, tmpfile):
- fd = tmpfile.fileno()
- cap = py.io.FDCapture(fd)
- f = cap.done()
- py.test.raises(ValueError, cap.start)
- f.close()
-
- def test_stderr(self):
- cap = py.io.FDCapture(2, patchsys=True)
- print_("hello", file=sys.stderr)
- f = cap.done()
- s = f.read()
- assert s == "hello\n"
-
- def test_stdin(self, tmpfile):
- tmpfile.write(tobytes("3"))
- tmpfile.seek(0)
- cap = py.io.FDCapture(0, tmpfile=tmpfile)
- # check with os.read() directly instead of raw_input(), because
- # sys.stdin itself may be redirected (as py.test now does by default)
- x = os.read(0, 100).strip()
- f = cap.done()
- assert x == tobytes("3")
-
- def test_writeorg(self, tmpfile):
- data1, data2 = tobytes("foo"), tobytes("bar")
- try:
- cap = py.io.FDCapture(tmpfile.fileno())
- tmpfile.write(data1)
- cap.writeorg(data2)
- finally:
- tmpfile.close()
- f = cap.done()
- scap = f.read()
- assert scap == totext(data1)
- stmp = open(tmpfile.name, 'rb').read()
- assert stmp == data2
-
-
-class TestStdCapture:
- def getcapture(self, **kw):
- return py.io.StdCapture(**kw)
-
- def test_capturing_done_simple(self):
- cap = self.getcapture()
- sys.stdout.write("hello")
- sys.stderr.write("world")
- outfile, errfile = cap.done()
- s = outfile.read()
- assert s == "hello"
- s = errfile.read()
- assert s == "world"
-
- def test_capturing_reset_simple(self):
- cap = self.getcapture()
- print("hello world")
- sys.stderr.write("hello error\n")
- out, err = cap.reset()
- assert out == "hello world\n"
- assert err == "hello error\n"
-
- def test_capturing_readouterr(self):
- cap = self.getcapture()
- try:
- print ("hello world")
- sys.stderr.write("hello error\n")
- out, err = cap.readouterr()
- assert out == "hello world\n"
- assert err == "hello error\n"
- sys.stderr.write("error2")
- finally:
- out, err = cap.reset()
- assert err == "error2"
-
- def test_capturing_readouterr_unicode(self):
- cap = self.getcapture()
- print ("hx\xc4\x85\xc4\x87")
- out, err = cap.readouterr()
- assert out == py.builtin._totext("hx\xc4\x85\xc4\x87\n", "utf8")
-
- @py.test.mark.skipif('sys.version_info >= (3,)',
- reason='text output different for bytes on python3')
- def test_capturing_readouterr_decode_error_handling(self):
- cap = self.getcapture()
- # triggered a internal error in pytest
- print('\xa6')
- out, err = cap.readouterr()
- assert out == py.builtin._totext('\ufffd\n', 'unicode-escape')
-
- def test_capturing_mixed(self):
- cap = self.getcapture(mixed=True)
- sys.stdout.write("hello ")
- sys.stderr.write("world")
- sys.stdout.write(".")
- out, err = cap.reset()
- assert out.strip() == "hello world."
- assert not err
-
- def test_reset_twice_error(self):
- cap = self.getcapture()
- print ("hello")
- out, err = cap.reset()
- py.test.raises(ValueError, cap.reset)
- assert out == "hello\n"
- assert not err
-
- def test_capturing_modify_sysouterr_in_between(self):
- oldout = sys.stdout
- olderr = sys.stderr
- cap = self.getcapture()
- sys.stdout.write("hello")
- sys.stderr.write("world")
- sys.stdout = py.io.TextIO()
- sys.stderr = py.io.TextIO()
- print ("not seen")
- sys.stderr.write("not seen\n")
- out, err = cap.reset()
- assert out == "hello"
- assert err == "world"
- assert sys.stdout == oldout
- assert sys.stderr == olderr
-
- def test_capturing_error_recursive(self):
- cap1 = self.getcapture()
- print ("cap1")
- cap2 = self.getcapture()
- print ("cap2")
- out2, err2 = cap2.reset()
- out1, err1 = cap1.reset()
- assert out1 == "cap1\n"
- assert out2 == "cap2\n"
-
- def test_just_out_capture(self):
- cap = self.getcapture(out=True, err=False)
- sys.stdout.write("hello")
- sys.stderr.write("world")
- out, err = cap.reset()
- assert out == "hello"
- assert not err
-
- def test_just_err_capture(self):
- cap = self.getcapture(out=False, err=True)
- sys.stdout.write("hello")
- sys.stderr.write("world")
- out, err = cap.reset()
- assert err == "world"
- assert not out
-
- def test_stdin_restored(self):
- old = sys.stdin
- cap = self.getcapture(in_=True)
- newstdin = sys.stdin
- out, err = cap.reset()
- assert newstdin != sys.stdin
- assert sys.stdin is old
-
- def test_stdin_nulled_by_default(self):
- print ("XXX this test may well hang instead of crashing")
- print ("XXX which indicates an error in the underlying capturing")
- print ("XXX mechanisms")
- cap = self.getcapture()
- py.test.raises(IOError, "sys.stdin.read()")
- out, err = cap.reset()
-
- def test_suspend_resume(self):
- cap = self.getcapture(out=True, err=False, in_=False)
- try:
- print ("hello")
- sys.stderr.write("error\n")
- out, err = cap.suspend()
- assert out == "hello\n"
- assert not err
- print ("in between")
- sys.stderr.write("in between\n")
- cap.resume()
- print ("after")
- sys.stderr.write("error_after\n")
- finally:
- out, err = cap.reset()
- assert out == "after\n"
- assert not err
-
-class TestStdCaptureNotNow(TestStdCapture):
- def getcapture(self, **kw):
- kw['now'] = False
- cap = py.io.StdCapture(**kw)
- cap.startall()
- return cap
-
-class TestStdCaptureFD(TestStdCapture):
- pytestmark = needsdup
-
- def getcapture(self, **kw):
- return py.io.StdCaptureFD(**kw)
-
- def test_intermingling(self):
- cap = self.getcapture()
- oswritebytes(1, "1")
- sys.stdout.write(str(2))
- sys.stdout.flush()
- oswritebytes(1, "3")
- oswritebytes(2, "a")
- sys.stderr.write("b")
- sys.stderr.flush()
- oswritebytes(2, "c")
- out, err = cap.reset()
- assert out == "123"
- assert err == "abc"
-
- def test_callcapture(self):
- def func(x, y):
- print (x)
- py.std.sys.stderr.write(str(y))
- return 42
-
- res, out, err = py.io.StdCaptureFD.call(func, 3, y=4)
- assert res == 42
- assert out.startswith("3")
- assert err.startswith("4")
-
- def test_many(self, capfd):
- def f():
- for i in range(10):
- cap = py.io.StdCaptureFD()
- cap.reset()
- lsof_check(f)
-
-class TestStdCaptureFDNotNow(TestStdCaptureFD):
- pytestmark = needsdup
-
- def getcapture(self, **kw):
- kw['now'] = False
- cap = py.io.StdCaptureFD(**kw)
- cap.startall()
- return cap
-
-@needsdup
-def test_stdcapture_fd_tmpfile(tmpfile):
- capfd = py.io.StdCaptureFD(out=tmpfile)
- os.write(1, "hello".encode("ascii"))
- os.write(2, "world".encode("ascii"))
- outf, errf = capfd.done()
- assert outf == tmpfile
-
-class TestStdCaptureFDinvalidFD:
- pytestmark = needsdup
- def test_stdcapture_fd_invalid_fd(self, testdir):
- testdir.makepyfile("""
- import py, os
- def test_stdout():
- os.close(1)
- cap = py.io.StdCaptureFD(out=True, err=False, in_=False)
- cap.done()
- def test_stderr():
- os.close(2)
- cap = py.io.StdCaptureFD(out=False, err=True, in_=False)
- cap.done()
- def test_stdin():
- os.close(0)
- cap = py.io.StdCaptureFD(out=False, err=False, in_=True)
- cap.done()
- """)
- result = testdir.runpytest("--capture=fd")
- assert result.ret == 0
- assert result.parseoutcomes()['passed'] == 3
-
-def test_capture_not_started_but_reset():
- capsys = py.io.StdCapture(now=False)
- capsys.done()
- capsys.done()
- capsys.reset()
-
-@needsdup
-def test_capture_no_sys():
- capsys = py.io.StdCapture()
- try:
- cap = py.io.StdCaptureFD(patchsys=False)
- sys.stdout.write("hello")
- sys.stderr.write("world")
- oswritebytes(1, "1")
- oswritebytes(2, "2")
- out, err = cap.reset()
- assert out == "1"
- assert err == "2"
- finally:
- capsys.reset()
-
-@needsdup
-def test_callcapture_nofd():
- def func(x, y):
- oswritebytes(1, "hello")
- oswritebytes(2, "hello")
- print (x)
- sys.stderr.write(str(y))
- return 42
-
- capfd = py.io.StdCaptureFD(patchsys=False)
- try:
- res, out, err = py.io.StdCapture.call(func, 3, y=4)
- finally:
- capfd.reset()
- assert res == 42
- assert out.startswith("3")
- assert err.startswith("4")
-
-@needsdup
-@py.test.mark.multi(use=[True, False])
-def test_fdcapture_tmpfile_remains_the_same(tmpfile, use):
- if not use:
- tmpfile = True
- cap = py.io.StdCaptureFD(out=False, err=tmpfile, now=False)
- cap.startall()
- capfile = cap.err.tmpfile
- cap.suspend()
- cap.resume()
- capfile2 = cap.err.tmpfile
- assert capfile2 == capfile
-
-@py.test.mark.multi(method=['StdCapture', 'StdCaptureFD'])
-def test_capturing_and_logging_fundamentals(testdir, method):
- if method == "StdCaptureFD" and not hasattr(os, 'dup'):
- py.test.skip("need os.dup")
- # here we check a fundamental feature
- p = testdir.makepyfile("""
- import sys, os
- import py, logging
- cap = py.io.%s(out=False, in_=False)
-
- logging.warn("hello1")
- outerr = cap.suspend()
- print ("suspend, captured %%s" %%(outerr,))
- logging.warn("hello2")
-
- cap.resume()
- logging.warn("hello3")
-
- outerr = cap.suspend()
- print ("suspend2, captured %%s" %% (outerr,))
- """ % (method,))
- result = testdir.runpython(p)
- result.stdout.fnmatch_lines([
- "suspend, captured*hello1*",
- "suspend2, captured*hello2*WARNING:root:hello3*",
- ])
- assert "atexit" not in result.stderr.str()
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/io_/test_saferepr.py b/tests/wpt/web-platform-tests/tools/py/testing/io_/test_saferepr.py
deleted file mode 100644
index 1ed9c4faf62..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/testing/io_/test_saferepr.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from __future__ import generators
-import py
-import sys
-
-saferepr = py.io.saferepr
-
-class TestSafeRepr:
- def test_simple_repr(self):
- assert saferepr(1) == '1'
- assert saferepr(None) == 'None'
-
- def test_maxsize(self):
- s = saferepr('x'*50, maxsize=25)
- assert len(s) == 25
- expected = repr('x'*10 + '...' + 'x'*10)
- assert s == expected
-
- def test_maxsize_error_on_instance(self):
- class A:
- def __repr__(self):
- raise ValueError('...')
-
- s = saferepr(('*'*50, A()), maxsize=25)
- assert len(s) == 25
- assert s[0] == '(' and s[-1] == ')'
-
- def test_exceptions(self):
- class BrokenRepr:
- def __init__(self, ex):
- self.ex = ex
- foo = 0
- def __repr__(self):
- raise self.ex
- class BrokenReprException(Exception):
- __str__ = None
- __repr__ = None
- assert 'Exception' in saferepr(BrokenRepr(Exception("broken")))
- s = saferepr(BrokenReprException("really broken"))
- assert 'TypeError' in s
- if py.std.sys.version_info < (2,6):
- assert 'unknown' in saferepr(BrokenRepr("string"))
- else:
- assert 'TypeError' in saferepr(BrokenRepr("string"))
-
- s2 = saferepr(BrokenRepr(BrokenReprException('omg even worse')))
- assert 'NameError' not in s2
- assert 'unknown' in s2
-
- def test_big_repr(self):
- from py._io.saferepr import SafeRepr
- assert len(saferepr(range(1000))) <= \
- len('[' + SafeRepr().maxlist * "1000" + ']')
-
- def test_repr_on_newstyle(self):
- class Function(object):
- def __repr__(self):
- return "<%s>" %(self.name)
- try:
- s = saferepr(Function())
- except Exception:
- py.test.fail("saferepr failed for newstyle class")
-
- def test_unicode(self):
- val = py.builtin._totext('£€', 'utf-8')
- reprval = py.builtin._totext("'£€'", 'utf-8')
- assert saferepr(val) == reprval
-
-def test_unicode_handling():
- value = py.builtin._totext('\xc4\x85\xc4\x87\n', 'utf-8').encode('utf8')
- def f():
- raise Exception(value)
- excinfo = py.test.raises(Exception, f)
- s = str(excinfo)
- if sys.version_info[0] < 3:
- u = unicode(excinfo)
-
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/io_/test_terminalwriter.py b/tests/wpt/web-platform-tests/tools/py/testing/io_/test_terminalwriter.py
deleted file mode 100644
index 0a15541bd23..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/testing/io_/test_terminalwriter.py
+++ /dev/null
@@ -1,271 +0,0 @@
-
-import py
-import os, sys
-from py._io import terminalwriter
-import codecs
-import pytest
-
-def test_get_terminal_width():
- x = py.io.get_terminal_width
- assert x == terminalwriter.get_terminal_width
-
-def test_getdimensions(monkeypatch):
- fcntl = py.test.importorskip("fcntl")
- import struct
- l = []
- monkeypatch.setattr(fcntl, 'ioctl', lambda *args: l.append(args))
- try:
- terminalwriter._getdimensions()
- except (TypeError, struct.error):
- pass
- assert len(l) == 1
- assert l[0][0] == 1
-
-def test_terminal_width_COLUMNS(monkeypatch):
- """ Dummy test for get_terminal_width
- """
- fcntl = py.test.importorskip("fcntl")
- monkeypatch.setattr(fcntl, 'ioctl', lambda *args: int('x'))
- monkeypatch.setenv('COLUMNS', '42')
- assert terminalwriter.get_terminal_width() == 42
- monkeypatch.delenv('COLUMNS', raising=False)
-
-def test_terminalwriter_defaultwidth_80(monkeypatch):
- monkeypatch.setattr(terminalwriter, '_getdimensions', lambda: 0/0)
- monkeypatch.delenv('COLUMNS', raising=False)
- tw = py.io.TerminalWriter()
- assert tw.fullwidth == 80
-
-def test_terminalwriter_getdimensions_bogus(monkeypatch):
- monkeypatch.setattr(terminalwriter, '_getdimensions', lambda: (10,10))
- monkeypatch.delenv('COLUMNS', raising=False)
- tw = py.io.TerminalWriter()
- assert tw.fullwidth == 80
-
-def test_terminalwriter_getdimensions_emacs(monkeypatch):
- # emacs terminal returns (0,0) but set COLUMNS properly
- monkeypatch.setattr(terminalwriter, '_getdimensions', lambda: (0,0))
- monkeypatch.setenv('COLUMNS', '42')
- tw = py.io.TerminalWriter()
- assert tw.fullwidth == 42
-
-def test_terminalwriter_computes_width(monkeypatch):
- monkeypatch.setattr(terminalwriter, 'get_terminal_width', lambda: 42)
- tw = py.io.TerminalWriter()
- assert tw.fullwidth == 42
-
-def test_terminalwriter_default_instantiation():
- tw = py.io.TerminalWriter(stringio=True)
- assert hasattr(tw, 'stringio')
-
-def test_terminalwriter_dumb_term_no_markup(monkeypatch):
- monkeypatch.setattr(os, 'environ', {'TERM': 'dumb', 'PATH': ''})
- class MyFile:
- closed = False
- def isatty(self):
- return True
- monkeypatch.setattr(sys, 'stdout', MyFile())
- try:
- assert sys.stdout.isatty()
- tw = py.io.TerminalWriter()
- assert not tw.hasmarkup
- finally:
- monkeypatch.undo()
-
-def test_terminalwriter_file_unicode(tmpdir):
- f = py.std.codecs.open(str(tmpdir.join("xyz")), "wb", "utf8")
- tw = py.io.TerminalWriter(file=f)
- assert tw.encoding == "utf8"
-
-def test_unicode_encoding():
- msg = py.builtin._totext('b\u00f6y', 'utf8')
- for encoding in 'utf8', 'latin1':
- l = []
- tw = py.io.TerminalWriter(l.append, encoding=encoding)
- tw.line(msg)
- assert l[0].strip() == msg.encode(encoding)
-
-@pytest.mark.parametrize("encoding", ["ascii"])
-def test_unicode_on_file_with_ascii_encoding(tmpdir, monkeypatch, encoding):
- msg = py.builtin._totext('hell\xf6', "latin1")
- #pytest.raises(UnicodeEncodeError, lambda: bytes(msg))
- f = py.std.codecs.open(str(tmpdir.join("x")), "w", encoding)
- tw = py.io.TerminalWriter(f)
- tw.line(msg)
- f.close()
- s = tmpdir.join("x").open("rb").read().strip()
- assert encoding == "ascii"
- assert s == msg.encode("unicode-escape")
-
-
-win32 = int(sys.platform == "win32")
-class TestTerminalWriter:
- def pytest_generate_tests(self, metafunc):
- if "tw" in metafunc.funcargnames:
- metafunc.addcall(id="path", param="path")
- metafunc.addcall(id="stringio", param="stringio")
- metafunc.addcall(id="callable", param="callable")
- def pytest_funcarg__tw(self, request):
- if request.param == "path":
- tmpdir = request.getfuncargvalue("tmpdir")
- p = tmpdir.join("tmpfile")
- f = codecs.open(str(p), 'w+', encoding='utf8')
- tw = py.io.TerminalWriter(f)
- def getlines():
- tw._file.flush()
- return codecs.open(str(p), 'r',
- encoding='utf8').readlines()
- elif request.param == "stringio":
- tw = py.io.TerminalWriter(stringio=True)
- def getlines():
- tw.stringio.seek(0)
- return tw.stringio.readlines()
- elif request.param == "callable":
- writes = []
- tw = py.io.TerminalWriter(writes.append)
- def getlines():
- io = py.io.TextIO()
- io.write("".join(writes))
- io.seek(0)
- return io.readlines()
- tw.getlines = getlines
- tw.getvalue = lambda: "".join(getlines())
- return tw
-
- def test_line(self, tw):
- tw.line("hello")
- l = tw.getlines()
- assert len(l) == 1
- assert l[0] == "hello\n"
-
- def test_line_unicode(self, tw):
- for encoding in 'utf8', 'latin1':
- tw._encoding = encoding
- msg = py.builtin._totext('b\u00f6y', 'utf8')
- tw.line(msg)
- l = tw.getlines()
- assert l[0] == msg + "\n"
-
- def test_sep_no_title(self, tw):
- tw.sep("-", fullwidth=60)
- l = tw.getlines()
- assert len(l) == 1
- assert l[0] == "-" * (60-win32) + "\n"
-
- def test_sep_with_title(self, tw):
- tw.sep("-", "hello", fullwidth=60)
- l = tw.getlines()
- assert len(l) == 1
- assert l[0] == "-" * 26 + " hello " + "-" * (27-win32) + "\n"
-
- @py.test.mark.skipif("sys.platform == 'win32'")
- def test__escaped(self, tw):
- text2 = tw._escaped("hello", (31))
- assert text2.find("hello") != -1
-
- @py.test.mark.skipif("sys.platform == 'win32'")
- def test_markup(self, tw):
- for bold in (True, False):
- for color in ("red", "green"):
- text2 = tw.markup("hello", **{color: True, 'bold': bold})
- assert text2.find("hello") != -1
- py.test.raises(ValueError, "tw.markup('x', wronkw=3)")
- py.test.raises(ValueError, "tw.markup('x', wronkw=0)")
-
- def test_line_write_markup(self, tw):
- tw.hasmarkup = True
- tw.line("x", bold=True)
- tw.write("x\n", red=True)
- l = tw.getlines()
- if sys.platform != "win32":
- assert len(l[0]) >= 2, l
- assert len(l[1]) >= 2, l
-
- def test_attr_fullwidth(self, tw):
- tw.sep("-", "hello", fullwidth=70)
- tw.fullwidth = 70
- tw.sep("-", "hello")
- l = tw.getlines()
- assert len(l[0]) == len(l[1])
-
- def test_reline(self, tw):
- tw.line("hello")
- tw.hasmarkup = False
- pytest.raises(ValueError, lambda: tw.reline("x"))
- tw.hasmarkup = True
- tw.reline("0 1 2")
- tw.getlines()
- l = tw.getvalue().split("\n")
- assert len(l) == 2
- tw.reline("0 1 3")
- l = tw.getvalue().split("\n")
- assert len(l) == 2
- assert l[1].endswith("0 1 3\r")
- tw.line("so")
- l = tw.getvalue().split("\n")
- assert len(l) == 3
- assert l[-1] == ""
- assert l[1] == ("0 1 2\r0 1 3\rso ")
- assert l[0] == "hello"
-
-
-def test_terminal_with_callable_write_and_flush():
- l = set()
- class fil:
- flush = lambda self: l.add("1")
- write = lambda self, x: l.add("1")
- __call__ = lambda self, x: l.add("2")
-
- tw = py.io.TerminalWriter(fil())
- tw.line("hello")
- assert l == set(["1"])
- del fil.flush
- l.clear()
- tw = py.io.TerminalWriter(fil())
- tw.line("hello")
- assert l == set(["2"])
-
-
-@pytest.mark.skipif(sys.platform == "win32", reason="win32 has no native ansi")
-def test_attr_hasmarkup():
- tw = py.io.TerminalWriter(stringio=True)
- assert not tw.hasmarkup
- tw.hasmarkup = True
- tw.line("hello", bold=True)
- s = tw.stringio.getvalue()
- assert len(s) > len("hello\n")
- assert '\x1b[1m' in s
- assert '\x1b[0m' in s
-
-@pytest.mark.skipif(sys.platform == "win32", reason="win32 has no native ansi")
-def test_ansi_print():
- # we have no easy way to construct a file that
- # represents a terminal
- f = py.io.TextIO()
- f.isatty = lambda: True
- py.io.ansi_print("hello", 0x32, file=f)
- text2 = f.getvalue()
- assert text2.find("hello") != -1
- assert len(text2) >= len("hello\n")
- assert '\x1b[50m' in text2
- assert '\x1b[0m' in text2
-
-def test_should_do_markup_PY_COLORS_eq_1(monkeypatch):
- monkeypatch.setitem(os.environ, 'PY_COLORS', '1')
- tw = py.io.TerminalWriter(stringio=True)
- assert tw.hasmarkup
- tw.line("hello", bold=True)
- s = tw.stringio.getvalue()
- assert len(s) > len("hello\n")
- assert '\x1b[1m' in s
- assert '\x1b[0m' in s
-
-def test_should_do_markup_PY_COLORS_eq_0(monkeypatch):
- monkeypatch.setitem(os.environ, 'PY_COLORS', '0')
- f = py.io.TextIO()
- f.isatty = lambda: True
- tw = py.io.TerminalWriter(file=f)
- assert not tw.hasmarkup
- tw.line("hello", bold=True)
- s = f.getvalue()
- assert s == "hello\n"
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/log/test_log.py b/tests/wpt/web-platform-tests/tools/py/testing/log/test_log.py
deleted file mode 100644
index b41bc3a5821..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/testing/log/test_log.py
+++ /dev/null
@@ -1,190 +0,0 @@
-import py
-import sys
-
-from py._log.log import default_keywordmapper
-
-callcapture = py.io.StdCapture.call
-
-def setup_module(mod):
- mod._oldstate = default_keywordmapper.getstate()
-
-def teardown_module(mod):
- default_keywordmapper.setstate(mod._oldstate)
-
-class TestLogProducer:
- def setup_method(self, meth):
- default_keywordmapper.setstate(_oldstate)
-
- def test_getstate_setstate(self):
- state = py.log._getstate()
- py.log.setconsumer("hello", [].append)
- state2 = py.log._getstate()
- assert state2 != state
- py.log._setstate(state)
- state3 = py.log._getstate()
- assert state3 == state
-
- def test_producer_repr(self):
- d = py.log.Producer("default")
- assert repr(d).find('default') != -1
-
- def test_produce_one_keyword(self):
- l = []
- py.log.setconsumer('s1', l.append)
- py.log.Producer('s1')("hello world")
- assert len(l) == 1
- msg = l[0]
- assert msg.content().startswith('hello world')
- assert msg.prefix() == '[s1] '
- assert str(msg) == "[s1] hello world"
-
- def test_producer_class(self):
- p = py.log.Producer('x1')
- l = []
- py.log.setconsumer(p._keywords, l.append)
- p("hello")
- assert len(l) == 1
- assert len(l[0].keywords) == 1
- assert 'x1' == l[0].keywords[0]
-
- def test_producer_caching(self):
- p = py.log.Producer('x1')
- x2 = p.x2
- assert x2 is p.x2
-
-class TestLogConsumer:
- def setup_method(self, meth):
- default_keywordmapper.setstate(_oldstate)
- def test_log_none(self):
- log = py.log.Producer("XXX")
- l = []
- py.log.setconsumer('XXX', l.append)
- log("1")
- assert l
- l[:] = []
- py.log.setconsumer('XXX', None)
- log("2")
- assert not l
-
- def test_log_default_stderr(self):
- res, out, err = callcapture(py.log.Producer("default"), "hello")
- assert err.strip() == "[default] hello"
-
- def test_simple_consumer_match(self):
- l = []
- py.log.setconsumer("x1", l.append)
- p = py.log.Producer("x1 x2")
- p("hello")
- assert l
- assert l[0].content() == "hello"
-
- def test_simple_consumer_match_2(self):
- l = []
- p = py.log.Producer("x1 x2")
- py.log.setconsumer(p._keywords, l.append)
- p("42")
- assert l
- assert l[0].content() == "42"
-
- def test_no_auto_producer(self):
- p = py.log.Producer('x')
- py.test.raises(AttributeError, "p._x")
- py.test.raises(AttributeError, "p.x_y")
-
- def test_setconsumer_with_producer(self):
- l = []
- p = py.log.Producer("hello")
- py.log.setconsumer(p, l.append)
- p("world")
- assert str(l[0]) == "[hello] world"
-
- def test_multi_consumer(self):
- l = []
- py.log.setconsumer("x1", l.append)
- py.log.setconsumer("x1 x2", None)
- p = py.log.Producer("x1 x2")
- p("hello")
- assert not l
- py.log.Producer("x1")("hello")
- assert l
- assert l[0].content() == "hello"
-
- def test_log_stderr(self):
- py.log.setconsumer("xyz", py.log.STDOUT)
- res, out, err = callcapture(py.log.Producer("xyz"), "hello")
- assert not err
- assert out.strip() == '[xyz] hello'
-
- def test_log_file(self, tmpdir):
- customlog = tmpdir.join('log.out')
- py.log.setconsumer("default", open(str(customlog), 'w', 1))
- py.log.Producer("default")("hello world #1")
- assert customlog.readlines() == ['[default] hello world #1\n']
-
- py.log.setconsumer("default", py.log.Path(customlog, buffering=False))
- py.log.Producer("default")("hello world #2")
- res = customlog.readlines()
- assert res == ['[default] hello world #2\n'] # no append by default!
-
- def test_log_file_append_mode(self, tmpdir):
- logfilefn = tmpdir.join('log_append.out')
-
- # The append mode is on by default, so we don't need to specify it for File
- py.log.setconsumer("default", py.log.Path(logfilefn, append=True,
- buffering=0))
- assert logfilefn.check()
- py.log.Producer("default")("hello world #1")
- lines = logfilefn.readlines()
- assert lines == ['[default] hello world #1\n']
- py.log.setconsumer("default", py.log.Path(logfilefn, append=True,
- buffering=0))
- py.log.Producer("default")("hello world #1")
- lines = logfilefn.readlines()
- assert lines == ['[default] hello world #1\n',
- '[default] hello world #1\n']
-
- def test_log_file_delayed_create(self, tmpdir):
- logfilefn = tmpdir.join('log_create.out')
-
- py.log.setconsumer("default", py.log.Path(logfilefn,
- delayed_create=True, buffering=0))
- assert not logfilefn.check()
- py.log.Producer("default")("hello world #1")
- lines = logfilefn.readlines()
- assert lines == ['[default] hello world #1\n']
-
- def test_keyword_based_log_files(self, tmpdir):
- logfiles = []
- keywords = 'k1 k2 k3'.split()
- for key in keywords:
- path = tmpdir.join(key)
- py.log.setconsumer(key, py.log.Path(path, buffering=0))
-
- py.log.Producer('k1')('1')
- py.log.Producer('k2')('2')
- py.log.Producer('k3')('3')
-
- for key in keywords:
- path = tmpdir.join(key)
- assert path.read().strip() == '[%s] %s' % (key, key[-1])
-
- # disabled for now; the syslog log file can usually be read only by root
- # I manually inspected /var/log/messages and the entries were there
- def no_test_log_syslog(self):
- py.log.setconsumer("default", py.log.Syslog())
- py.log.default("hello world #1")
-
- # disabled for now until I figure out how to read entries in the
- # Event Logs on Windows
- # I manually inspected the Application Log and the entries were there
- def no_test_log_winevent(self):
- py.log.setconsumer("default", py.log.WinEvent())
- py.log.default("hello world #1")
-
- # disabled for now until I figure out how to properly pass the parameters
- def no_test_log_email(self):
- py.log.setconsumer("default", py.log.Email(mailhost="gheorghiu.net",
- fromaddr="grig",
- toaddrs="grig",
- subject = "py.log email"))
- py.log.default("hello world #1")
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/log/test_warning.py b/tests/wpt/web-platform-tests/tools/py/testing/log/test_warning.py
deleted file mode 100644
index 8c89cf8adbb..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/testing/log/test_warning.py
+++ /dev/null
@@ -1,76 +0,0 @@
-import pytest
-import py
-
-mypath = py.path.local(__file__).new(ext=".py")
-
-@pytest.mark.xfail
-def test_forwarding_to_warnings_module():
- pytest.deprecated_call(py.log._apiwarn, "1.3", "..")
-
-def test_apiwarn_functional(recwarn):
- capture = py.io.StdCapture()
- py.log._apiwarn("x.y.z", "something", stacklevel=1)
- out, err = capture.reset()
- py.builtin.print_("out", out)
- py.builtin.print_("err", err)
- assert err.find("x.y.z") != -1
- lno = py.code.getrawcode(test_apiwarn_functional).co_firstlineno + 2
- exp = "%s:%s" % (mypath, lno)
- assert err.find(exp) != -1
-
-def test_stacklevel(recwarn):
- def f():
- py.log._apiwarn("x", "some", stacklevel=2)
- # 3
- # 4
- capture = py.io.StdCapture()
- f()
- out, err = capture.reset()
- lno = py.code.getrawcode(test_stacklevel).co_firstlineno + 6
- warning = str(err)
- assert warning.find(":%s" % lno) != -1
-
-def test_stacklevel_initpkg_with_resolve(testdir, recwarn):
- testdir.makepyfile(modabc="""
- import py
- def f():
- py.log._apiwarn("x", "some", stacklevel="apipkg123")
- """)
- testdir.makepyfile(apipkg123="""
- def __getattr__():
- import modabc
- modabc.f()
- """)
- p = testdir.makepyfile("""
- import apipkg123
- apipkg123.__getattr__()
- """)
- capture = py.io.StdCapture()
- p.pyimport()
- out, err = capture.reset()
- warning = str(err)
- loc = 'test_stacklevel_initpkg_with_resolve.py:2'
- assert warning.find(loc) != -1
-
-def test_stacklevel_initpkg_no_resolve(recwarn):
- def f():
- py.log._apiwarn("x", "some", stacklevel="apipkg")
- capture = py.io.StdCapture()
- f()
- out, err = capture.reset()
- lno = py.code.getrawcode(test_stacklevel_initpkg_no_resolve).co_firstlineno + 2
- warning = str(err)
- assert warning.find(":%s" % lno) != -1
-
-
-def test_function(recwarn):
- capture = py.io.StdCapture()
- py.log._apiwarn("x.y.z", "something", function=test_function)
- out, err = capture.reset()
- py.builtin.print_("out", out)
- py.builtin.print_("err", err)
- assert err.find("x.y.z") != -1
- lno = py.code.getrawcode(test_function).co_firstlineno
- exp = "%s:%s" % (mypath, lno)
- assert err.find(exp) != -1
-
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/path/common.py b/tests/wpt/web-platform-tests/tools/py/testing/path/common.py
deleted file mode 100644
index 4834fba12d0..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/testing/path/common.py
+++ /dev/null
@@ -1,470 +0,0 @@
-import py
-import sys
-
-class CommonFSTests(object):
- def test_constructor_equality(self, path1):
- p = path1.__class__(path1)
- assert p == path1
-
- def test_eq_nonstring(self, path1):
- p1 = path1.join('sampledir')
- p2 = path1.join('sampledir')
- assert p1 == p2
-
- def test_new_identical(self, path1):
- assert path1 == path1.new()
-
- def test_join(self, path1):
- p = path1.join('sampledir')
- strp = str(p)
- assert strp.endswith('sampledir')
- assert strp.startswith(str(path1))
-
- def test_join_normalized(self, path1):
- newpath = path1.join(path1.sep+'sampledir')
- strp = str(newpath)
- assert strp.endswith('sampledir')
- assert strp.startswith(str(path1))
- newpath = path1.join((path1.sep*2) + 'sampledir')
- strp = str(newpath)
- assert strp.endswith('sampledir')
- assert strp.startswith(str(path1))
-
- def test_join_noargs(self, path1):
- newpath = path1.join()
- assert path1 == newpath
-
- def test_add_something(self, path1):
- p = path1.join('sample')
- p = p + 'dir'
- assert p.check()
- assert p.exists()
- assert p.isdir()
- assert not p.isfile()
-
- def test_parts(self, path1):
- newpath = path1.join('sampledir', 'otherfile')
- par = newpath.parts()[-3:]
- assert par == [path1, path1.join('sampledir'), newpath]
-
- revpar = newpath.parts(reverse=True)[:3]
- assert revpar == [newpath, path1.join('sampledir'), path1]
-
- def test_common(self, path1):
- other = path1.join('sampledir')
- x = other.common(path1)
- assert x == path1
-
- #def test_parents_nonexisting_file(self, path1):
- # newpath = path1 / 'dirnoexist' / 'nonexisting file'
- # par = list(newpath.parents())
- # assert par[:2] == [path1 / 'dirnoexist', path1]
-
- def test_basename_checks(self, path1):
- newpath = path1.join('sampledir')
- assert newpath.check(basename='sampledir')
- assert newpath.check(notbasename='xyz')
- assert newpath.basename == 'sampledir'
-
- def test_basename(self, path1):
- newpath = path1.join('sampledir')
- assert newpath.check(basename='sampledir')
- assert newpath.basename, 'sampledir'
-
- def test_dirname(self, path1):
- newpath = path1.join('sampledir')
- assert newpath.dirname == str(path1)
-
- def test_dirpath(self, path1):
- newpath = path1.join('sampledir')
- assert newpath.dirpath() == path1
-
- def test_dirpath_with_args(self, path1):
- newpath = path1.join('sampledir')
- assert newpath.dirpath('x') == path1.join('x')
-
- def test_newbasename(self, path1):
- newpath = path1.join('samplefile')
- newbase = newpath.new(basename="samplefile2")
- assert newbase.basename == "samplefile2"
- assert newbase.dirpath() == newpath.dirpath()
-
- def test_not_exists(self, path1):
- assert not path1.join('does_not_exist').check()
- assert path1.join('does_not_exist').check(exists=0)
-
- def test_exists(self, path1):
- assert path1.join("samplefile").check()
- assert path1.join("samplefile").check(exists=1)
- assert path1.join("samplefile").exists()
- assert path1.join("samplefile").isfile()
- assert not path1.join("samplefile").isdir()
-
- def test_dir(self, path1):
- #print repr(path1.join("sampledir"))
- assert path1.join("sampledir").check(dir=1)
- assert path1.join('samplefile').check(notdir=1)
- assert not path1.join("samplefile").check(dir=1)
- assert path1.join("samplefile").exists()
- assert not path1.join("samplefile").isdir()
- assert path1.join("samplefile").isfile()
-
- def test_fnmatch_file(self, path1):
- assert path1.join("samplefile").check(fnmatch='s*e')
- assert path1.join("samplefile").fnmatch('s*e')
- assert not path1.join("samplefile").fnmatch('s*x')
- assert not path1.join("samplefile").check(fnmatch='s*x')
-
- #def test_fnmatch_dir(self, path1):
-
- # pattern = path1.sep.join(['s*file'])
- # sfile = path1.join("samplefile")
- # assert sfile.check(fnmatch=pattern)
-
- def test_relto(self, path1):
- l=path1.join("sampledir", "otherfile")
- assert l.relto(path1) == l.sep.join(["sampledir", "otherfile"])
- assert l.check(relto=path1)
- assert path1.check(notrelto=l)
- assert not path1.check(relto=l)
-
- def test_bestrelpath(self, path1):
- curdir = path1
- sep = curdir.sep
- s = curdir.bestrelpath(curdir)
- assert s == "."
- s = curdir.bestrelpath(curdir.join("hello", "world"))
- assert s == "hello" + sep + "world"
-
- s = curdir.bestrelpath(curdir.dirpath().join("sister"))
- assert s == ".." + sep + "sister"
- assert curdir.bestrelpath(curdir.dirpath()) == ".."
-
- assert curdir.bestrelpath("hello") == "hello"
-
- def test_relto_not_relative(self, path1):
- l1=path1.join("bcde")
- l2=path1.join("b")
- assert not l1.relto(l2)
- assert not l2.relto(l1)
-
- @py.test.mark.xfail("sys.platform.startswith('java')")
- def test_listdir(self, path1):
- l = path1.listdir()
- assert path1.join('sampledir') in l
- assert path1.join('samplefile') in l
- py.test.raises(py.error.ENOTDIR,
- "path1.join('samplefile').listdir()")
-
- def test_listdir_fnmatchstring(self, path1):
- l = path1.listdir('s*dir')
- assert len(l)
- assert l[0], path1.join('sampledir')
-
- def test_listdir_filter(self, path1):
- l = path1.listdir(lambda x: x.check(dir=1))
- assert path1.join('sampledir') in l
- assert not path1.join('samplefile') in l
-
- def test_listdir_sorted(self, path1):
- l = path1.listdir(lambda x: x.check(basestarts="sample"), sort=True)
- assert path1.join('sampledir') == l[0]
- assert path1.join('samplefile') == l[1]
- assert path1.join('samplepickle') == l[2]
-
- def test_visit_nofilter(self, path1):
- l = []
- for i in path1.visit():
- l.append(i.relto(path1))
- assert "sampledir" in l
- assert path1.sep.join(["sampledir", "otherfile"]) in l
-
- def test_visit_norecurse(self, path1):
- l = []
- for i in path1.visit(None, lambda x: x.basename != "sampledir"):
- l.append(i.relto(path1))
- assert "sampledir" in l
- assert not path1.sep.join(["sampledir", "otherfile"]) in l
-
- def test_visit_filterfunc_is_string(self, path1):
- l = []
- for i in path1.visit('*dir'):
- l.append(i.relto(path1))
- assert len(l), 2
- assert "sampledir" in l
- assert "otherdir" in l
-
- @py.test.mark.xfail("sys.platform.startswith('java')")
- def test_visit_ignore(self, path1):
- p = path1.join('nonexisting')
- assert list(p.visit(ignore=py.error.ENOENT)) == []
-
- def test_visit_endswith(self, path1):
- l = []
- for i in path1.visit(lambda x: x.check(endswith="file")):
- l.append(i.relto(path1))
- assert path1.sep.join(["sampledir", "otherfile"]) in l
- assert "samplefile" in l
-
- def test_endswith(self, path1):
- assert path1.check(notendswith='.py')
- x = path1.join('samplefile')
- assert x.check(endswith='file')
-
- def test_cmp(self, path1):
- path1 = path1.join('samplefile')
- path2 = path1.join('samplefile2')
- assert (path1 < path2) == ('samplefile' < 'samplefile2')
- assert not (path1 < path1)
-
- def test_simple_read(self, path1):
- x = path1.join('samplefile').read('r')
- assert x == 'samplefile\n'
-
- def test_join_div_operator(self, path1):
- newpath = path1 / '/sampledir' / '/test//'
- newpath2 = path1.join('sampledir', 'test')
- assert newpath == newpath2
-
- def test_ext(self, path1):
- newpath = path1.join('sampledir.ext')
- assert newpath.ext == '.ext'
- newpath = path1.join('sampledir')
- assert not newpath.ext
-
- def test_purebasename(self, path1):
- newpath = path1.join('samplefile.py')
- assert newpath.purebasename == 'samplefile'
-
- def test_multiple_parts(self, path1):
- newpath = path1.join('samplefile.py')
- dirname, purebasename, basename, ext = newpath._getbyspec(
- 'dirname,purebasename,basename,ext')
- assert str(path1).endswith(dirname) # be careful with win32 'drive'
- assert purebasename == 'samplefile'
- assert basename == 'samplefile.py'
- assert ext == '.py'
-
- def test_dotted_name_ext(self, path1):
- newpath = path1.join('a.b.c')
- ext = newpath.ext
- assert ext == '.c'
- assert newpath.ext == '.c'
-
- def test_newext(self, path1):
- newpath = path1.join('samplefile.py')
- newext = newpath.new(ext='.txt')
- assert newext.basename == "samplefile.txt"
- assert newext.purebasename == "samplefile"
-
- def test_readlines(self, path1):
- fn = path1.join('samplefile')
- contents = fn.readlines()
- assert contents == ['samplefile\n']
-
- def test_readlines_nocr(self, path1):
- fn = path1.join('samplefile')
- contents = fn.readlines(cr=0)
- assert contents == ['samplefile', '']
-
- def test_file(self, path1):
- assert path1.join('samplefile').check(file=1)
-
- def test_not_file(self, path1):
- assert not path1.join("sampledir").check(file=1)
- assert path1.join("sampledir").check(file=0)
-
- def test_non_existent(self, path1):
- assert path1.join("sampledir.nothere").check(dir=0)
- assert path1.join("sampledir.nothere").check(file=0)
- assert path1.join("sampledir.nothere").check(notfile=1)
- assert path1.join("sampledir.nothere").check(notdir=1)
- assert path1.join("sampledir.nothere").check(notexists=1)
- assert not path1.join("sampledir.nothere").check(notfile=0)
-
- # pattern = path1.sep.join(['s*file'])
- # sfile = path1.join("samplefile")
- # assert sfile.check(fnmatch=pattern)
-
- def test_size(self, path1):
- url = path1.join("samplefile")
- assert url.size() > len("samplefile")
-
- def test_mtime(self, path1):
- url = path1.join("samplefile")
- assert url.mtime() > 0
-
- def test_relto_wrong_type(self, path1):
- py.test.raises(TypeError, "path1.relto(42)")
-
- def test_load(self, path1):
- p = path1.join('samplepickle')
- obj = p.load()
- assert type(obj) is dict
- assert obj.get('answer',None) == 42
-
- def test_visit_filesonly(self, path1):
- l = []
- for i in path1.visit(lambda x: x.check(file=1)):
- l.append(i.relto(path1))
- assert not "sampledir" in l
- assert path1.sep.join(["sampledir", "otherfile"]) in l
-
- def test_visit_nodotfiles(self, path1):
- l = []
- for i in path1.visit(lambda x: x.check(dotfile=0)):
- l.append(i.relto(path1))
- assert "sampledir" in l
- assert path1.sep.join(["sampledir", "otherfile"]) in l
- assert not ".dotfile" in l
-
- def test_visit_breadthfirst(self, path1):
- l = []
- for i in path1.visit(bf=True):
- l.append(i.relto(path1))
- for i, p in enumerate(l):
- if path1.sep in p:
- for j in range(i, len(l)):
- assert path1.sep in l[j]
- break
- else:
- py.test.fail("huh")
-
- def test_visit_sort(self, path1):
- l = []
- for i in path1.visit(bf=True, sort=True):
- l.append(i.relto(path1))
- for i, p in enumerate(l):
- if path1.sep in p:
- break
- assert l[:i] == sorted(l[:i])
- assert l[i:] == sorted(l[i:])
-
- def test_endswith(self, path1):
- def chk(p):
- return p.check(endswith="pickle")
- assert not chk(path1)
- assert not chk(path1.join('samplefile'))
- assert chk(path1.join('somepickle'))
-
- def test_copy_file(self, path1):
- otherdir = path1.join('otherdir')
- initpy = otherdir.join('__init__.py')
- copied = otherdir.join('copied')
- initpy.copy(copied)
- try:
- assert copied.check()
- s1 = initpy.read()
- s2 = copied.read()
- assert s1 == s2
- finally:
- if copied.check():
- copied.remove()
-
- def test_copy_dir(self, path1):
- otherdir = path1.join('otherdir')
- copied = path1.join('newdir')
- try:
- otherdir.copy(copied)
- assert copied.check(dir=1)
- assert copied.join('__init__.py').check(file=1)
- s1 = otherdir.join('__init__.py').read()
- s2 = copied.join('__init__.py').read()
- assert s1 == s2
- finally:
- if copied.check(dir=1):
- copied.remove(rec=1)
-
- def test_remove_file(self, path1):
- d = path1.ensure('todeleted')
- assert d.check()
- d.remove()
- assert not d.check()
-
- def test_remove_dir_recursive_by_default(self, path1):
- d = path1.ensure('to', 'be', 'deleted')
- assert d.check()
- p = path1.join('to')
- p.remove()
- assert not p.check()
-
- def test_ensure_dir(self, path1):
- b = path1.ensure_dir("001", "002")
- assert b.basename == "002"
- assert b.isdir()
-
- def test_mkdir_and_remove(self, path1):
- tmpdir = path1
- py.test.raises(py.error.EEXIST, tmpdir.mkdir, 'sampledir')
- new = tmpdir.join('mktest1')
- new.mkdir()
- assert new.check(dir=1)
- new.remove()
-
- new = tmpdir.mkdir('mktest')
- assert new.check(dir=1)
- new.remove()
- assert tmpdir.join('mktest') == new
-
- def test_move_file(self, path1):
- p = path1.join('samplefile')
- newp = p.dirpath('moved_samplefile')
- p.move(newp)
- try:
- assert newp.check(file=1)
- assert not p.check()
- finally:
- dp = newp.dirpath()
- if hasattr(dp, 'revert'):
- dp.revert()
- else:
- newp.move(p)
- assert p.check()
-
- def test_move_dir(self, path1):
- source = path1.join('sampledir')
- dest = path1.join('moveddir')
- source.move(dest)
- assert dest.check(dir=1)
- assert dest.join('otherfile').check(file=1)
- assert not source.join('sampledir').check()
-
-def setuptestfs(path):
- if path.join('samplefile').check():
- return
- #print "setting up test fs for", repr(path)
- samplefile = path.ensure('samplefile')
- samplefile.write('samplefile\n')
-
- execfile = path.ensure('execfile')
- execfile.write('x=42')
-
- execfilepy = path.ensure('execfile.py')
- execfilepy.write('x=42')
-
- d = {1:2, 'hello': 'world', 'answer': 42}
- path.ensure('samplepickle').dump(d)
-
- sampledir = path.ensure('sampledir', dir=1)
- sampledir.ensure('otherfile')
-
- otherdir = path.ensure('otherdir', dir=1)
- otherdir.ensure('__init__.py')
-
- module_a = otherdir.ensure('a.py')
- if sys.version_info >= (2,6):
- module_a.write('from .b import stuff as result\n')
- else:
- module_a.write('from b import stuff as result\n')
- module_b = otherdir.ensure('b.py')
- module_b.write('stuff="got it"\n')
- module_c = otherdir.ensure('c.py')
- module_c.write('''import py;
-import otherdir.a
-value = otherdir.a.result
-''')
- module_d = otherdir.ensure('d.py')
- module_d.write('''import py;
-from otherdir import a
-value2 = a.result
-''')
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/path/conftest.py b/tests/wpt/web-platform-tests/tools/py/testing/path/conftest.py
deleted file mode 100644
index a9711b2ce30..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/testing/path/conftest.py
+++ /dev/null
@@ -1,80 +0,0 @@
-import py
-import sys
-from py._path import svnwc as svncommon
-
-svnbin = py.path.local.sysfind('svn')
-repodump = py.path.local(__file__).dirpath('repotest.dump')
-from py.builtin import print_
-
-def pytest_funcarg__repowc1(request):
- if svnbin is None:
- py.test.skip("svn binary not found")
-
- tmpdir = request.getfuncargvalue("tmpdir")
- repo, repourl, wc = request.cached_setup(
- setup=lambda: getrepowc(tmpdir, "path1repo", "path1wc"),
- scope="module",
- )
- for x in ('test_remove', 'test_move', 'test_status_deleted'):
- if request.function.__name__.startswith(x):
- #print >>sys.stderr, ("saving repo", repo, "for", request.function)
- _savedrepowc = save_repowc(repo, wc)
- request.addfinalizer(lambda: restore_repowc(_savedrepowc))
- return repo, repourl, wc
-
-def pytest_funcarg__repowc2(request):
- tmpdir = request.getfuncargvalue("tmpdir")
- name = request.function.__name__
- repo, url, wc = getrepowc(tmpdir, "%s-repo-2" % name, "%s-wc-2" % name)
- return repo, url, wc
-
-def getsvnbin():
- if svnbin is None:
- py.test.skip("svn binary not found")
- return svnbin
-
-# make a wc directory out of a given root url
-# cache previously obtained wcs!
-#
-def getrepowc(tmpdir, reponame='basetestrepo', wcname='wc'):
- repo = tmpdir.mkdir(reponame)
- wcdir = tmpdir.mkdir(wcname)
- repo.ensure(dir=1)
- py.process.cmdexec('svnadmin create "%s"' %
- svncommon._escape_helper(repo))
- py.process.cmdexec('svnadmin load -q "%s" <"%s"' %
- (svncommon._escape_helper(repo), repodump))
- print_("created svn repository", repo)
- wcdir.ensure(dir=1)
- wc = py.path.svnwc(wcdir)
- if py.std.sys.platform == 'win32':
- repourl = "file://" + '/' + str(repo).replace('\\', '/')
- else:
- repourl = "file://%s" % repo
- wc.checkout(repourl)
- print_("checked out new repo into", wc)
- return (repo, repourl, wc)
-
-
-def save_repowc(repo, wc):
- assert not str(repo).startswith("file://"), repo
- assert repo.check()
- savedrepo = repo.dirpath(repo.basename+".1")
- savedwc = wc.dirpath(wc.basename+".1")
- repo.copy(savedrepo)
- wc.localpath.copy(savedwc.localpath)
- return savedrepo, savedwc
-
-def restore_repowc(obj):
- savedrepo, savedwc = obj
- #print >>sys.stderr, ("restoring", savedrepo)
- repo = savedrepo.new(basename=savedrepo.basename[:-2])
- assert repo.check()
- wc = savedwc.new(basename=savedwc.basename[:-2])
- assert wc.check()
- wc.localpath.remove()
- repo.remove()
- savedrepo.move(repo)
- savedwc.localpath.move(wc.localpath)
- py.path.svnurl._lsnorevcache.clear()
- py.path.svnurl._lsrevcache.clear()
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/path/test_cacheutil.py b/tests/wpt/web-platform-tests/tools/py/testing/path/test_cacheutil.py
deleted file mode 100644
index 0b5cd31332f..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/testing/path/test_cacheutil.py
+++ /dev/null
@@ -1,84 +0,0 @@
-import py
-from py._path import cacheutil
-
-class BasicCacheAPITest:
- cache = None
- def test_getorbuild(self):
- val = self.cache.getorbuild(-42, lambda: 42)
- assert val == 42
- val = self.cache.getorbuild(-42, lambda: 23)
- assert val == 42
-
- def test_cache_get_key_error(self):
- py.test.raises(KeyError, "self.cache._getentry(-23)")
-
- def test_delentry_non_raising(self):
- val = self.cache.getorbuild(100, lambda: 100)
- self.cache.delentry(100)
- py.test.raises(KeyError, "self.cache._getentry(100)")
-
- def test_delentry_raising(self):
- val = self.cache.getorbuild(100, lambda: 100)
- self.cache.delentry(100)
- py.test.raises(KeyError, "self.cache.delentry(100, raising=True)")
-
- def test_clear(self):
- self.cache.clear()
-
-class TestBuildcostAccess(BasicCacheAPITest):
- cache = cacheutil.BuildcostAccessCache(maxentries=128)
-
- def test_cache_works_somewhat_simple(self, monkeypatch):
- cache = cacheutil.BuildcostAccessCache()
- # the default gettime
- # BuildcostAccessCache.build can
- # result into time()-time() == 0 which makes the below
- # test fail randomly. Let's rather use incrementing
- # numbers instead.
- l = [0]
- def counter():
- l[0] = l[0] + 1
- return l[0]
- monkeypatch.setattr(cacheutil, 'gettime', counter)
- for x in range(cache.maxentries):
- y = cache.getorbuild(x, lambda: x)
- assert x == y
- for x in range(cache.maxentries):
- assert cache.getorbuild(x, None) == x
- halfentries = int(cache.maxentries / 2)
- for x in range(halfentries):
- assert cache.getorbuild(x, None) == x
- assert cache.getorbuild(x, None) == x
- # evict one entry
- val = cache.getorbuild(-1, lambda: 42)
- assert val == 42
- # check that recently used ones are still there
- # and are not build again
- for x in range(halfentries):
- assert cache.getorbuild(x, None) == x
- assert cache.getorbuild(-1, None) == 42
-
-
-class TestAging(BasicCacheAPITest):
- maxsecs = 0.10
- cache = cacheutil.AgingCache(maxentries=128, maxseconds=maxsecs)
-
- def test_cache_eviction(self):
- self.cache.getorbuild(17, lambda: 17)
- endtime = py.std.time.time() + self.maxsecs * 10
- while py.std.time.time() < endtime:
- try:
- self.cache._getentry(17)
- except KeyError:
- break
- py.std.time.sleep(self.maxsecs*0.3)
- else:
- py.test.fail("waiting for cache eviction failed")
-
-def test_prune_lowestweight():
- maxsecs = 0.05
- cache = cacheutil.AgingCache(maxentries=10, maxseconds=maxsecs)
- for x in range(cache.maxentries):
- cache.getorbuild(x, lambda: x)
- py.std.time.sleep(maxsecs*1.1)
- cache.getorbuild(cache.maxentries+1, lambda: 42)
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/path/test_local.py b/tests/wpt/web-platform-tests/tools/py/testing/path/test_local.py
deleted file mode 100644
index bcf131fd2b7..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/testing/path/test_local.py
+++ /dev/null
@@ -1,860 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from __future__ import with_statement
-import py
-import pytest
-import os, sys
-from py.path import local
-import common
-
-failsonjython = py.test.mark.xfail("sys.platform.startswith('java')")
-failsonjywin32 = py.test.mark.xfail("sys.platform.startswith('java') "
- "and getattr(os, '_name', None) == 'nt'")
-win32only = py.test.mark.skipif(
- "not (sys.platform == 'win32' or getattr(os, '_name', None) == 'nt')")
-skiponwin32 = py.test.mark.skipif(
- "sys.platform == 'win32' or getattr(os, '_name', None) == 'nt'")
-
-
-def pytest_funcarg__path1(request):
- def setup():
- path1 = request.getfuncargvalue("tmpdir")
- common.setuptestfs(path1)
- return path1
- def teardown(path1):
- # post check
- assert path1.join("samplefile").check()
- return request.cached_setup(setup, teardown, scope="session")
-
-class TestLocalPath(common.CommonFSTests):
- def test_join_normpath(self, tmpdir):
- assert tmpdir.join(".") == tmpdir
- p = tmpdir.join("../%s" % tmpdir.basename)
- assert p == tmpdir
- p = tmpdir.join("..//%s/" % tmpdir.basename)
- assert p == tmpdir
-
- @skiponwin32
- def test_dirpath_abs_no_abs(self, tmpdir):
- p = tmpdir.join('foo')
- assert p.dirpath('/bar') == tmpdir.join('bar')
- assert tmpdir.dirpath('/bar', abs=True) == py.path.local('/bar')
-
- def test_gethash(self, tmpdir):
- md5 = py.builtin._tryimport('md5', 'hashlib').md5
- lib = py.builtin._tryimport('sha', 'hashlib')
- sha = getattr(lib, 'sha1', getattr(lib, 'sha', None))
- fn = tmpdir.join("testhashfile")
- data = 'hello'.encode('ascii')
- fn.write(data, mode="wb")
- assert fn.computehash("md5") == md5(data).hexdigest()
- assert fn.computehash("sha1") == sha(data).hexdigest()
- py.test.raises(ValueError, fn.computehash, "asdasd")
-
- def test_remove_removes_readonly_file(self, tmpdir):
- readonly_file = tmpdir.join('readonly').ensure()
- readonly_file.chmod(0)
- readonly_file.remove()
- assert not readonly_file.check(exists=1)
-
- def test_remove_removes_readonly_dir(self, tmpdir):
- readonly_dir = tmpdir.join('readonlydir').ensure(dir=1)
- readonly_dir.chmod(int("500", 8))
- readonly_dir.remove()
- assert not readonly_dir.check(exists=1)
-
- def test_remove_removes_dir_and_readonly_file(self, tmpdir):
- readonly_dir = tmpdir.join('readonlydir').ensure(dir=1)
- readonly_file = readonly_dir.join('readonlyfile').ensure()
- readonly_file.chmod(0)
- readonly_dir.remove()
- assert not readonly_dir.check(exists=1)
-
- def test_remove_routes_ignore_errors(self, tmpdir, monkeypatch):
- l = []
- monkeypatch.setattr(py.std.shutil, 'rmtree',
- lambda *args, **kwargs: l.append(kwargs))
- tmpdir.remove()
- assert not l[0]['ignore_errors']
- for val in (True, False):
- l[:] = []
- tmpdir.remove(ignore_errors=val)
- assert l[0]['ignore_errors'] == val
-
- def test_initialize_curdir(self):
- assert str(local()) == py.std.os.getcwd()
-
- @skiponwin32
- def test_chdir_gone(self, path1):
- p = path1.ensure("dir_to_be_removed", dir=1)
- p.chdir()
- p.remove()
- pytest.raises(py.error.ENOENT, py.path.local)
- assert path1.chdir() is None
- assert os.getcwd() == str(path1)
-
- def test_as_cwd(self, path1):
- dir = path1.ensure("subdir", dir=1)
- old = py.path.local()
- with dir.as_cwd() as x:
- assert x == old
- assert py.path.local() == dir
- assert os.getcwd() == str(old)
-
- def test_as_cwd_exception(self, path1):
- old = py.path.local()
- dir = path1.ensure("subdir", dir=1)
- with pytest.raises(ValueError):
- with dir.as_cwd():
- raise ValueError()
- assert old == py.path.local()
-
- def test_initialize_reldir(self, path1):
- with path1.as_cwd():
- p = local('samplefile')
- assert p.check()
-
- @pytest.mark.xfail("sys.version_info < (2,6) and sys.platform == 'win32'")
- def test_tilde_expansion(self, monkeypatch, tmpdir):
- monkeypatch.setenv("HOME", str(tmpdir))
- p = py.path.local("~", expanduser=True)
- assert p == os.path.expanduser("~")
-
- def test_eq_with_strings(self, path1):
- path1 = path1.join('sampledir')
- path2 = str(path1)
- assert path1 == path2
- assert path2 == path1
- path3 = path1.join('samplefile')
- assert path3 != path2
- assert path2 != path3
-
- def test_eq_with_none(self, path1):
- assert path1 != None
-
- def test_gt_with_strings(self, path1):
- path2 = path1.join('sampledir')
- path3 = str(path1.join("ttt"))
- assert path3 > path2
- assert path2 < path3
- assert path2 < "ttt"
- assert "ttt" > path2
- path4 = path1.join("aaa")
- l = [path2, path4,path3]
- assert sorted(l) == [path4, path2, path3]
-
- def test_open_and_ensure(self, path1):
- p = path1.join("sub1", "sub2", "file")
- with p.open("w", ensure=1) as f:
- f.write("hello")
- assert p.read() == "hello"
-
- def test_write_and_ensure(self, path1):
- p = path1.join("sub1", "sub2", "file")
- p.write("hello", ensure=1)
- assert p.read() == "hello"
-
- @py.test.mark.multi(bin=(False, True))
- def test_dump(self, tmpdir, bin):
- path = tmpdir.join("dumpfile%s" % int(bin))
- try:
- d = {'answer' : 42}
- path.dump(d, bin=bin)
- f = path.open('rb+')
- dnew = py.std.pickle.load(f)
- assert d == dnew
- finally:
- f.close()
-
- @failsonjywin32
- def test_setmtime(self):
- import tempfile
- import time
- try:
- fd, name = tempfile.mkstemp()
- py.std.os.close(fd)
- except AttributeError:
- name = tempfile.mktemp()
- open(name, 'w').close()
- try:
- mtime = int(time.time())-100
- path = local(name)
- assert path.mtime() != mtime
- path.setmtime(mtime)
- assert path.mtime() == mtime
- path.setmtime()
- assert path.mtime() != mtime
- finally:
- py.std.os.remove(name)
-
- def test_normpath(self, path1):
- new1 = path1.join("/otherdir")
- new2 = path1.join("otherdir")
- assert str(new1) == str(new2)
-
- def test_mkdtemp_creation(self):
- d = local.mkdtemp()
- try:
- assert d.check(dir=1)
- finally:
- d.remove(rec=1)
-
- def test_tmproot(self):
- d = local.mkdtemp()
- tmproot = local.get_temproot()
- try:
- assert d.check(dir=1)
- assert d.dirpath() == tmproot
- finally:
- d.remove(rec=1)
-
- def test_chdir(self, tmpdir):
- old = local()
- try:
- res = tmpdir.chdir()
- assert str(res) == str(old)
- assert py.std.os.getcwd() == str(tmpdir)
- finally:
- old.chdir()
-
- def test_ensure_filepath_withdir(self, tmpdir):
- newfile = tmpdir.join('test1','test')
- newfile.ensure()
- assert newfile.check(file=1)
- newfile.write("42")
- newfile.ensure()
- s = newfile.read()
- assert s == "42"
-
- def test_ensure_filepath_withoutdir(self, tmpdir):
- newfile = tmpdir.join('test1file')
- t = newfile.ensure()
- assert t == newfile
- assert newfile.check(file=1)
-
- def test_ensure_dirpath(self, tmpdir):
- newfile = tmpdir.join('test1','testfile')
- t = newfile.ensure(dir=1)
- assert t == newfile
- assert newfile.check(dir=1)
-
- def test_init_from_path(self, tmpdir):
- l = local()
- l2 = local(l)
- assert l2 == l
-
- wc = py.path.svnwc('.')
- l3 = local(wc)
- assert l3 is not wc
- assert l3.strpath == wc.strpath
- assert not hasattr(l3, 'commit')
-
- @py.test.mark.xfail(run=False, reason="unreliable est for long filenames")
- def test_long_filenames(self, tmpdir):
- if sys.platform == "win32":
- py.test.skip("win32: work around needed for path length limit")
- # see http://codespeak.net/pipermail/py-dev/2008q2/000922.html
-
- # testing paths > 260 chars (which is Windows' limitation, but
- # depending on how the paths are used), but > 4096 (which is the
- # Linux' limitation) - the behaviour of paths with names > 4096 chars
- # is undetermined
- newfilename = '/test' * 60
- l = tmpdir.join(newfilename)
- l.ensure(file=True)
- l.write('foo')
- l2 = tmpdir.join(newfilename)
- assert l2.read() == 'foo'
-
- def test_visit_depth_first(self, tmpdir):
- p1 = tmpdir.ensure("a","1")
- p2 = tmpdir.ensure("b","2")
- p3 = tmpdir.ensure("breadth")
- l = list(tmpdir.visit(lambda x: x.check(file=1)))
- assert len(l) == 3
- # check that breadth comes last
- assert l[2] == p3
-
- def test_visit_rec_fnmatch(self, tmpdir):
- p1 = tmpdir.ensure("a","123")
- p2 = tmpdir.ensure(".b","345")
- l = list(tmpdir.visit("???", rec="[!.]*"))
- assert len(l) == 1
- # check that breadth comes last
- assert l[0] == p1
-
- def test_fnmatch_file_abspath(self, tmpdir):
- b = tmpdir.join("a", "b")
- assert b.fnmatch(os.sep.join("ab"))
- pattern = os.sep.join([str(tmpdir), "*", "b"])
- assert b.fnmatch(pattern)
-
- def test_sysfind(self):
- name = sys.platform == "win32" and "cmd" or "test"
- x = py.path.local.sysfind(name)
- assert x.check(file=1)
- assert py.path.local.sysfind('jaksdkasldqwe') is None
- assert py.path.local.sysfind(name, paths=[]) is None
- x2 = py.path.local.sysfind(name, paths=[x.dirpath()])
- assert x2 == x
-
-
-class TestExecutionOnWindows:
- pytestmark = win32only
-
- def test_sysfind_bat_exe_before(self, tmpdir, monkeypatch):
- monkeypatch.setenv("PATH", str(tmpdir), prepend=os.pathsep)
- tmpdir.ensure("hello")
- h = tmpdir.ensure("hello.bat")
- x = py.path.local.sysfind("hello")
- assert x == h
-
-
-class TestExecution:
- pytestmark = skiponwin32
-
- def test_sysfind_no_permisson_ignored(self, monkeypatch, tmpdir):
- noperm = tmpdir.ensure('noperm', dir=True)
- monkeypatch.setenv("PATH", noperm, prepend=":")
- noperm.chmod(0)
- assert py.path.local.sysfind('jaksdkasldqwe') is None
-
- def test_sysfind_absolute(self):
- x = py.path.local.sysfind('test')
- assert x.check(file=1)
- y = py.path.local.sysfind(str(x))
- assert y.check(file=1)
- assert y == x
-
- def test_sysfind_multiple(self, tmpdir, monkeypatch):
- monkeypatch.setenv('PATH',
- "%s:%s" % (tmpdir.ensure('a'),
- tmpdir.join('b')),
- prepend=":")
- tmpdir.ensure('b', 'a')
- checker = lambda x: x.dirpath().basename == 'b'
- x = py.path.local.sysfind('a', checker=checker)
- assert x.basename == 'a'
- assert x.dirpath().basename == 'b'
- checker = lambda x: None
- assert py.path.local.sysfind('a', checker=checker) is None
-
- def test_sysexec(self):
- x = py.path.local.sysfind('ls')
- out = x.sysexec('-a')
- for x in py.path.local().listdir():
- assert out.find(x.basename) != -1
-
- def test_sysexec_failing(self):
- x = py.path.local.sysfind('false')
- py.test.raises(py.process.cmdexec.Error, """
- x.sysexec('aksjdkasjd')
- """)
-
- def test_make_numbered_dir(self, tmpdir):
- tmpdir.ensure('base.not_an_int', dir=1)
- for i in range(10):
- numdir = local.make_numbered_dir(prefix='base.', rootdir=tmpdir,
- keep=2, lock_timeout=0)
- assert numdir.check()
- assert numdir.basename == 'base.%d' %i
- if i>=1:
- assert numdir.new(ext=str(i-1)).check()
- if i>=2:
- assert numdir.new(ext=str(i-2)).check()
- if i>=3:
- assert not numdir.new(ext=str(i-3)).check()
-
- def test_make_numbered_dir_NotImplemented_Error(self, tmpdir, monkeypatch):
- def notimpl(x, y):
- raise NotImplementedError(42)
- monkeypatch.setattr(py.std.os, 'symlink', notimpl)
- x = tmpdir.make_numbered_dir(rootdir=tmpdir, lock_timeout=0)
- assert x.relto(tmpdir)
- assert x.check()
-
- def test_locked_make_numbered_dir(self, tmpdir):
- for i in range(10):
- numdir = local.make_numbered_dir(prefix='base2.', rootdir=tmpdir,
- keep=2)
- assert numdir.check()
- assert numdir.basename == 'base2.%d' %i
- for j in range(i):
- assert numdir.new(ext=str(j)).check()
-
- def test_error_preservation(self, path1):
- py.test.raises (EnvironmentError, path1.join('qwoeqiwe').mtime)
- py.test.raises (EnvironmentError, path1.join('qwoeqiwe').read)
-
- #def test_parentdirmatch(self):
- # local.parentdirmatch('std', startmodule=__name__)
- #
-
-
-class TestImport:
- def test_pyimport(self, path1):
- obj = path1.join('execfile.py').pyimport()
- assert obj.x == 42
- assert obj.__name__ == 'execfile'
-
- def test_pyimport_renamed_dir_creates_mismatch(self, tmpdir):
- p = tmpdir.ensure("a", "test_x123.py")
- p.pyimport()
- tmpdir.join("a").move(tmpdir.join("b"))
- pytest.raises(tmpdir.ImportMismatchError,
- lambda: tmpdir.join("b", "test_x123.py").pyimport())
-
- def test_pyimport_messy_name(self, tmpdir):
- # http://bitbucket.org/hpk42/py-trunk/issue/129
- path = tmpdir.ensure('foo__init__.py')
- obj = path.pyimport()
-
- def test_pyimport_dir(self, tmpdir):
- p = tmpdir.join("hello_123")
- p_init = p.ensure("__init__.py")
- m = p.pyimport()
- assert m.__name__ == "hello_123"
- m = p_init.pyimport()
- assert m.__name__ == "hello_123"
-
- def test_pyimport_execfile_different_name(self, path1):
- obj = path1.join('execfile.py').pyimport(modname="0x.y.z")
- assert obj.x == 42
- assert obj.__name__ == '0x.y.z'
-
- def test_pyimport_a(self, path1):
- otherdir = path1.join('otherdir')
- mod = otherdir.join('a.py').pyimport()
- assert mod.result == "got it"
- assert mod.__name__ == 'otherdir.a'
-
- def test_pyimport_b(self, path1):
- otherdir = path1.join('otherdir')
- mod = otherdir.join('b.py').pyimport()
- assert mod.stuff == "got it"
- assert mod.__name__ == 'otherdir.b'
-
- def test_pyimport_c(self, path1):
- otherdir = path1.join('otherdir')
- mod = otherdir.join('c.py').pyimport()
- assert mod.value == "got it"
-
- def test_pyimport_d(self, path1):
- otherdir = path1.join('otherdir')
- mod = otherdir.join('d.py').pyimport()
- assert mod.value2 == "got it"
-
- def test_pyimport_and_import(self, tmpdir):
- tmpdir.ensure('xxxpackage', '__init__.py')
- mod1path = tmpdir.ensure('xxxpackage', 'module1.py')
- mod1 = mod1path.pyimport()
- assert mod1.__name__ == 'xxxpackage.module1'
- from xxxpackage import module1
- assert module1 is mod1
-
- def test_pyimport_check_filepath_consistency(self, monkeypatch, tmpdir):
- name = 'pointsback123'
- ModuleType = type(py.std.os)
- p = tmpdir.ensure(name + '.py')
- for ending in ('.pyc', '$py.class', '.pyo'):
- mod = ModuleType(name)
- pseudopath = tmpdir.ensure(name+ending)
- mod.__file__ = str(pseudopath)
- monkeypatch.setitem(sys.modules, name, mod)
- newmod = p.pyimport()
- assert mod == newmod
- monkeypatch.undo()
- mod = ModuleType(name)
- pseudopath = tmpdir.ensure(name+"123.py")
- mod.__file__ = str(pseudopath)
- monkeypatch.setitem(sys.modules, name, mod)
- excinfo = py.test.raises(pseudopath.ImportMismatchError,
- "p.pyimport()")
- modname, modfile, orig = excinfo.value.args
- assert modname == name
- assert modfile == pseudopath
- assert orig == p
- assert issubclass(pseudopath.ImportMismatchError, ImportError)
-
- def test_issue131_pyimport_on__init__(self, tmpdir):
- # __init__.py files may be namespace packages, and thus the
- # __file__ of an imported module may not be ourselves
- # see issue
- p1 = tmpdir.ensure("proja", "__init__.py")
- p2 = tmpdir.ensure("sub", "proja", "__init__.py")
- m1 = p1.pyimport()
- m2 = p2.pyimport()
- assert m1 == m2
-
- def test_ensuresyspath_append(self, tmpdir):
- root1 = tmpdir.mkdir("root1")
- file1 = root1.ensure("x123.py")
- assert str(root1) not in sys.path
- file1.pyimport(ensuresyspath="append")
- assert str(root1) == sys.path[-1]
- assert str(root1) not in sys.path[:-1]
-
-
-def test_pypkgdir(tmpdir):
- pkg = tmpdir.ensure('pkg1', dir=1)
- pkg.ensure("__init__.py")
- pkg.ensure("subdir/__init__.py")
- assert pkg.pypkgpath() == pkg
- assert pkg.join('subdir', '__init__.py').pypkgpath() == pkg
-
-def test_pypkgdir_unimportable(tmpdir):
- pkg = tmpdir.ensure('pkg1-1', dir=1) # unimportable
- pkg.ensure("__init__.py")
- subdir = pkg.ensure("subdir/__init__.py").dirpath()
- assert subdir.pypkgpath() == subdir
- assert subdir.ensure("xyz.py").pypkgpath() == subdir
- assert not pkg.pypkgpath()
-
-def test_isimportable():
- from py._path.local import isimportable
- assert not isimportable("")
- assert isimportable("x")
- assert isimportable("x1")
- assert isimportable("x_1")
- assert isimportable("_")
- assert isimportable("_1")
- assert not isimportable("x-1")
- assert not isimportable("x:1")
-
-def test_homedir_from_HOME(monkeypatch):
- path = os.getcwd()
- monkeypatch.setenv("HOME", path)
- assert py.path.local._gethomedir() == py.path.local(path)
-
-def test_homedir_not_exists(monkeypatch):
- monkeypatch.delenv("HOME", raising=False)
- monkeypatch.delenv("HOMEDRIVE", raising=False)
- homedir = py.path.local._gethomedir()
- assert homedir is None
-
-def test_samefile(tmpdir):
- assert tmpdir.samefile(tmpdir)
- p = tmpdir.ensure("hello")
- assert p.samefile(p)
- with p.dirpath().as_cwd():
- assert p.samefile(p.basename)
- if sys.platform == "win32":
- p1 = p.__class__(str(p).lower())
- p2 = p.__class__(str(p).upper())
- assert p1.samefile(p2)
-
-def test_listdir_single_arg(tmpdir):
- tmpdir.ensure("hello")
- assert tmpdir.listdir("hello")[0].basename == "hello"
-
-def test_mkdtemp_rootdir(tmpdir):
- dtmp = local.mkdtemp(rootdir=tmpdir)
- assert tmpdir.listdir() == [dtmp]
-
-class TestWINLocalPath:
- pytestmark = win32only
-
- def test_owner_group_not_implemented(self, path1):
- py.test.raises(NotImplementedError, "path1.stat().owner")
- py.test.raises(NotImplementedError, "path1.stat().group")
-
- def test_chmod_simple_int(self, path1):
- py.builtin.print_("path1 is", path1)
- mode = path1.stat().mode
- # Ensure that we actually change the mode to something different.
- path1.chmod(mode == 0 and 1 or 0)
- try:
- print(path1.stat().mode)
- print(mode)
- assert path1.stat().mode != mode
- finally:
- path1.chmod(mode)
- assert path1.stat().mode == mode
-
- def test_path_comparison_lowercase_mixed(self, path1):
- t1 = path1.join("a_path")
- t2 = path1.join("A_path")
- assert t1 == t1
- assert t1 == t2
-
- def test_relto_with_mixed_case(self, path1):
- t1 = path1.join("a_path", "fiLe")
- t2 = path1.join("A_path")
- assert t1.relto(t2) == "fiLe"
-
- def test_allow_unix_style_paths(self, path1):
- t1 = path1.join('a_path')
- assert t1 == str(path1) + '\\a_path'
- t1 = path1.join('a_path/')
- assert t1 == str(path1) + '\\a_path'
- t1 = path1.join('dir/a_path')
- assert t1 == str(path1) + '\\dir\\a_path'
-
- def test_sysfind_in_currentdir(self, path1):
- cmd = py.path.local.sysfind('cmd')
- root = cmd.new(dirname='', basename='') # c:\ in most installations
- with root.as_cwd():
- x = py.path.local.sysfind(cmd.relto(root))
- assert x.check(file=1)
-
- def test_fnmatch_file_abspath_posix_pattern_on_win32(self, tmpdir):
- # path-matching patterns might contain a posix path separator '/'
- # Test that we can match that pattern on windows.
- import posixpath
- b = tmpdir.join("a", "b")
- assert b.fnmatch(posixpath.sep.join("ab"))
- pattern = posixpath.sep.join([str(tmpdir), "*", "b"])
- assert b.fnmatch(pattern)
-
-class TestPOSIXLocalPath:
- pytestmark = skiponwin32
-
- def test_hardlink(self, tmpdir):
- linkpath = tmpdir.join('test')
- filepath = tmpdir.join('file')
- filepath.write("Hello")
- nlink = filepath.stat().nlink
- linkpath.mklinkto(filepath)
- assert filepath.stat().nlink == nlink + 1
-
- def test_symlink_are_identical(self, tmpdir):
- filepath = tmpdir.join('file')
- filepath.write("Hello")
- linkpath = tmpdir.join('test')
- linkpath.mksymlinkto(filepath)
- assert linkpath.readlink() == str(filepath)
-
- def test_symlink_isfile(self, tmpdir):
- linkpath = tmpdir.join('test')
- filepath = tmpdir.join('file')
- filepath.write("")
- linkpath.mksymlinkto(filepath)
- assert linkpath.check(file=1)
- assert not linkpath.check(link=0, file=1)
- assert linkpath.islink()
-
- def test_symlink_relative(self, tmpdir):
- linkpath = tmpdir.join('test')
- filepath = tmpdir.join('file')
- filepath.write("Hello")
- linkpath.mksymlinkto(filepath, absolute=False)
- assert linkpath.readlink() == "file"
- assert filepath.read() == linkpath.read()
-
- def test_symlink_not_existing(self, tmpdir):
- linkpath = tmpdir.join('testnotexisting')
- assert not linkpath.check(link=1)
- assert linkpath.check(link=0)
-
- def test_relto_with_root(self, path1, tmpdir):
- y = path1.join('x').relto(py.path.local('/'))
- assert y[0] == str(path1)[1]
-
- def test_visit_recursive_symlink(self, tmpdir):
- linkpath = tmpdir.join('test')
- linkpath.mksymlinkto(tmpdir)
- visitor = tmpdir.visit(None, lambda x: x.check(link=0))
- assert list(visitor) == [linkpath]
-
- def test_symlink_isdir(self, tmpdir):
- linkpath = tmpdir.join('test')
- linkpath.mksymlinkto(tmpdir)
- assert linkpath.check(dir=1)
- assert not linkpath.check(link=0, dir=1)
-
- def test_symlink_remove(self, tmpdir):
- linkpath = tmpdir.join('test')
- linkpath.mksymlinkto(linkpath) # point to itself
- assert linkpath.check(link=1)
- linkpath.remove()
- assert not linkpath.check()
-
- def test_realpath_file(self, tmpdir):
- linkpath = tmpdir.join('test')
- filepath = tmpdir.join('file')
- filepath.write("")
- linkpath.mksymlinkto(filepath)
- realpath = linkpath.realpath()
- assert realpath.basename == 'file'
-
- def test_owner(self, path1, tmpdir):
- from pwd import getpwuid
- from grp import getgrgid
- stat = path1.stat()
- assert stat.path == path1
-
- uid = stat.uid
- gid = stat.gid
- owner = getpwuid(uid)[0]
- group = getgrgid(gid)[0]
-
- assert uid == stat.uid
- assert owner == stat.owner
- assert gid == stat.gid
- assert group == stat.group
-
- def test_stat_helpers(self, tmpdir, monkeypatch):
- path1 = tmpdir.ensure("file")
- stat1 = path1.stat()
- stat2 = tmpdir.stat()
- assert stat1.isfile()
- assert stat2.isdir()
- assert not stat1.islink()
- assert not stat2.islink()
-
- def test_stat_non_raising(self, tmpdir):
- path1 = tmpdir.join("file")
- pytest.raises(py.error.ENOENT, lambda: path1.stat())
- res = path1.stat(raising=False)
- assert res is None
-
- def test_atime(self, tmpdir):
- import time
- path = tmpdir.ensure('samplefile')
- now = time.time()
- atime1 = path.atime()
- # we could wait here but timer resolution is very
- # system dependent
- path.read()
- time.sleep(0.01)
- atime2 = path.atime()
- time.sleep(0.01)
- duration = time.time() - now
- assert (atime2-atime1) <= duration
-
- def test_commondir(self, path1):
- # XXX This is here in local until we find a way to implement this
- # using the subversion command line api.
- p1 = path1.join('something')
- p2 = path1.join('otherthing')
- assert p1.common(p2) == path1
- assert p2.common(p1) == path1
-
- def test_commondir_nocommon(self, path1):
- # XXX This is here in local until we find a way to implement this
- # using the subversion command line api.
- p1 = path1.join('something')
- p2 = py.path.local(path1.sep+'blabla')
- assert p1.common(p2) == '/'
-
- def test_join_to_root(self, path1):
- root = path1.parts()[0]
- assert len(str(root)) == 1
- assert str(root.join('a')) == '//a' # posix allows two slashes
-
- def test_join_root_to_root_with_no_abs(self, path1):
- nroot = path1.join('/')
- assert str(path1) == str(nroot)
- assert path1 == nroot
-
- def test_chmod_simple_int(self, path1):
- mode = path1.stat().mode
- path1.chmod(int(mode/2))
- try:
- assert path1.stat().mode != mode
- finally:
- path1.chmod(mode)
- assert path1.stat().mode == mode
-
- def test_chmod_rec_int(self, path1):
- # XXX fragile test
- recfilter = lambda x: x.check(dotfile=0, link=0)
- oldmodes = {}
- for x in path1.visit(rec=recfilter):
- oldmodes[x] = x.stat().mode
- path1.chmod(int("772", 8), rec=recfilter)
- try:
- for x in path1.visit(rec=recfilter):
- assert x.stat().mode & int("777", 8) == int("772", 8)
- finally:
- for x,y in oldmodes.items():
- x.chmod(y)
-
- def test_copy_archiving(self, tmpdir):
- unicode_fn = u"something-\342\200\223.txt"
- f = tmpdir.ensure("a", unicode_fn)
- a = f.dirpath()
- oldmode = f.stat().mode
- newmode = oldmode ^ 1
- f.chmod(newmode)
- b = tmpdir.join("b")
- a.copy(b, mode=True)
- assert b.join(f.basename).stat().mode == newmode
-
- @failsonjython
- def test_chown_identity(self, path1):
- owner = path1.stat().owner
- group = path1.stat().group
- path1.chown(owner, group)
-
- @failsonjython
- def test_chown_dangling_link(self, path1):
- owner = path1.stat().owner
- group = path1.stat().group
- x = path1.join('hello')
- x.mksymlinkto('qlwkejqwlek')
- try:
- path1.chown(owner, group, rec=1)
- finally:
- x.remove(rec=0)
-
- @failsonjython
- def test_chown_identity_rec_mayfail(self, path1):
- owner = path1.stat().owner
- group = path1.stat().group
- path1.chown(owner, group)
-
-
-class TestUnicodePy2Py3:
- def test_join_ensure(self, tmpdir, monkeypatch):
- if sys.version_info >= (3,0) and "LANG" not in os.environ:
- pytest.skip("cannot run test without locale")
- x = py.path.local(tmpdir.strpath)
- part = "hällo"
- y = x.ensure(part)
- assert x.join(part) == y
-
- def test_listdir(self, tmpdir):
- if sys.version_info >= (3,0) and "LANG" not in os.environ:
- pytest.skip("cannot run test without locale")
- x = py.path.local(tmpdir.strpath)
- part = "hällo"
- y = x.ensure(part)
- assert x.listdir(part)[0] == y
-
- @pytest.mark.xfail(reason="changing read/write might break existing usages")
- def test_read_write(self, tmpdir):
- x = tmpdir.join("hello")
- part = py.builtin._totext("hällo", "utf8")
- x.write(part)
- assert x.read() == part
- x.write(part.encode(sys.getdefaultencoding()))
- assert x.read() == part.encode(sys.getdefaultencoding())
-
-class TestBinaryAndTextMethods:
- def test_read_binwrite(self, tmpdir):
- x = tmpdir.join("hello")
- part = py.builtin._totext("hällo", "utf8")
- part_utf8 = part.encode("utf8")
- x.write_binary(part_utf8)
- assert x.read_binary() == part_utf8
- s = x.read_text(encoding="utf8")
- assert s == part
- assert py.builtin._istext(s)
-
- def test_read_textwrite(self, tmpdir):
- x = tmpdir.join("hello")
- part = py.builtin._totext("hällo", "utf8")
- part_utf8 = part.encode("utf8")
- x.write_text(part, encoding="utf8")
- assert x.read_binary() == part_utf8
- assert x.read_text(encoding="utf8") == part
-
- def test_default_encoding(self, tmpdir):
- x = tmpdir.join("hello")
- # Can't use UTF8 as the default encoding (ASCII) doesn't support it
- part = py.builtin._totext("hello", "ascii")
- x.write_text(part, "ascii")
- s = x.read_text("ascii")
- assert s == part
- assert type(s) == type(part)
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/path/test_svnauth.py b/tests/wpt/web-platform-tests/tools/py/testing/path/test_svnauth.py
deleted file mode 100644
index b3f36656168..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/testing/path/test_svnauth.py
+++ /dev/null
@@ -1,454 +0,0 @@
-import py
-import svntestbase
-from py.path import SvnAuth
-import time
-import sys
-
-svnbin = py.path.local.sysfind('svn')
-
-def make_repo_auth(repo, userdata):
- """ write config to repo
-
- user information in userdata is used for auth
- userdata has user names as keys, and a tuple (password, readwrite) as
- values, where 'readwrite' is either 'r' or 'rw'
- """
- confdir = py.path.local(repo).join('conf')
- confdir.join('svnserve.conf').write('''\
-[general]
-anon-access = none
-password-db = passwd
-authz-db = authz
-realm = TestRepo
-''')
- authzdata = '[/]\n'
- passwddata = '[users]\n'
- for user in userdata:
- authzdata += '%s = %s\n' % (user, userdata[user][1])
- passwddata += '%s = %s\n' % (user, userdata[user][0])
- confdir.join('authz').write(authzdata)
- confdir.join('passwd').write(passwddata)
-
-def serve_bg(repopath):
- pidfile = py.path.local(repopath).join('pid')
- port = 10000
- e = None
- while port < 10010:
- cmd = 'svnserve -d -T --listen-port=%d --pid-file=%s -r %s' % (
- port, pidfile, repopath)
- print(cmd)
- try:
- py.process.cmdexec(cmd)
- except py.process.cmdexec.Error:
- e = sys.exc_info()[1]
- else:
- # XXX we assume here that the pid file gets written somewhere, I
- # guess this should be relatively safe... (I hope, at least?)
- counter = pid = 0
- while counter < 10:
- counter += 1
- try:
- pid = pidfile.read()
- except py.error.ENOENT:
- pass
- if pid:
- break
- time.sleep(0.2)
- return port, int(pid)
- port += 1
- raise IOError('could not start svnserve: %s' % (e,))
-
-class TestSvnAuth(object):
- def test_basic(self):
- auth = SvnAuth('foo', 'bar')
- assert auth.username == 'foo'
- assert auth.password == 'bar'
- assert str(auth)
-
- def test_makecmdoptions_uname_pw_makestr(self):
- auth = SvnAuth('foo', 'bar')
- assert auth.makecmdoptions() == '--username="foo" --password="bar"'
-
- def test_makecmdoptions_quote_escape(self):
- auth = SvnAuth('fo"o', '"ba\'r"')
- assert auth.makecmdoptions() == '--username="fo\\"o" --password="\\"ba\'r\\""'
-
- def test_makecmdoptions_no_cache_auth(self):
- auth = SvnAuth('foo', 'bar', cache_auth=False)
- assert auth.makecmdoptions() == ('--username="foo" --password="bar" '
- '--no-auth-cache')
-
- def test_makecmdoptions_no_interactive(self):
- auth = SvnAuth('foo', 'bar', interactive=False)
- assert auth.makecmdoptions() == ('--username="foo" --password="bar" '
- '--non-interactive')
-
- def test_makecmdoptions_no_interactive_no_cache_auth(self):
- auth = SvnAuth('foo', 'bar', cache_auth=False,
- interactive=False)
- assert auth.makecmdoptions() == ('--username="foo" --password="bar" '
- '--no-auth-cache --non-interactive')
-
-class svnwc_no_svn(py.path.svnwc):
- def __new__(cls, *args, **kwargs):
- self = super(svnwc_no_svn, cls).__new__(cls, *args, **kwargs)
- self.commands = []
- return self
-
- def _svn(self, *args):
- self.commands.append(args)
-
-class TestSvnWCAuth(object):
- def setup_method(self, meth):
- if not svnbin:
- py.test.skip("svn binary required")
- self.auth = SvnAuth('user', 'pass', cache_auth=False)
-
- def test_checkout(self):
- wc = svnwc_no_svn('foo', auth=self.auth)
- wc.checkout('url')
- assert wc.commands[0][-1] == ('--username="user" --password="pass" '
- '--no-auth-cache')
-
- def test_commit(self):
- wc = svnwc_no_svn('foo', auth=self.auth)
- wc.commit('msg')
- assert wc.commands[0][-1] == ('--username="user" --password="pass" '
- '--no-auth-cache')
-
- def test_checkout_no_cache_auth(self):
- wc = svnwc_no_svn('foo', auth=self.auth)
- wc.checkout('url')
- assert wc.commands[0][-1] == ('--username="user" --password="pass" '
- '--no-auth-cache')
-
- def test_checkout_auth_from_constructor(self):
- wc = svnwc_no_svn('foo', auth=self.auth)
- wc.checkout('url')
- assert wc.commands[0][-1] == ('--username="user" --password="pass" '
- '--no-auth-cache')
-
-class svnurl_no_svn(py.path.svnurl):
- cmdexec_output = 'test'
- popen_output = 'test'
- def __new__(cls, *args, **kwargs):
- self = super(svnurl_no_svn, cls).__new__(cls, *args, **kwargs)
- self.commands = []
- return self
-
- def _cmdexec(self, cmd):
- self.commands.append(cmd)
- return self.cmdexec_output
-
- def _popen(self, cmd):
- self.commands.append(cmd)
- return self.popen_output
-
-class TestSvnURLAuth(object):
- def setup_method(self, meth):
- self.auth = SvnAuth('foo', 'bar')
-
- def test_init(self):
- u = svnurl_no_svn('http://foo.bar/svn')
- assert u.auth is None
-
- u = svnurl_no_svn('http://foo.bar/svn', auth=self.auth)
- assert u.auth is self.auth
-
- def test_new(self):
- u = svnurl_no_svn('http://foo.bar/svn/foo', auth=self.auth)
- new = u.new(basename='bar')
- assert new.auth is self.auth
- assert new.url == 'http://foo.bar/svn/bar'
-
- def test_join(self):
- u = svnurl_no_svn('http://foo.bar/svn', auth=self.auth)
- new = u.join('foo')
- assert new.auth is self.auth
- assert new.url == 'http://foo.bar/svn/foo'
-
- def test_listdir(self):
- u = svnurl_no_svn('http://foo.bar/svn', auth=self.auth)
- u.cmdexec_output = '''\
- 1717 johnny 1529 Nov 04 14:32 LICENSE.txt
- 1716 johnny 5352 Nov 04 14:28 README.txt
-'''
- paths = u.listdir()
- assert paths[0].auth is self.auth
- assert paths[1].auth is self.auth
- assert paths[0].basename == 'LICENSE.txt'
-
- def test_info(self):
- u = svnurl_no_svn('http://foo.bar/svn/LICENSE.txt', auth=self.auth)
- def dirpath(self):
- return self
- u.cmdexec_output = '''\
- 1717 johnny 1529 Nov 04 14:32 LICENSE.txt
- 1716 johnny 5352 Nov 04 14:28 README.txt
-'''
- org_dp = u.__class__.dirpath
- u.__class__.dirpath = dirpath
- try:
- info = u.info()
- finally:
- u.dirpath = org_dp
- assert info.size == 1529
-
- def test_open(self):
- u = svnurl_no_svn('http://foo.bar/svn', auth=self.auth)
- foo = u.join('foo')
- foo.check = lambda *args, **kwargs: True
- ret = foo.open()
- assert ret == 'test'
- assert '--username="foo" --password="bar"' in foo.commands[0]
-
- def test_dirpath(self):
- u = svnurl_no_svn('http://foo.bar/svn/foo', auth=self.auth)
- parent = u.dirpath()
- assert parent.auth is self.auth
-
- def test_mkdir(self):
- u = svnurl_no_svn('http://foo.bar/svn/qweqwe', auth=self.auth)
- assert not u.commands
- u.mkdir(msg='created dir foo')
- assert u.commands
- assert '--username="foo" --password="bar"' in u.commands[0]
-
- def test_copy(self):
- u = svnurl_no_svn('http://foo.bar/svn', auth=self.auth)
- u2 = svnurl_no_svn('http://foo.bar/svn2')
- u.copy(u2, 'copied dir')
- assert '--username="foo" --password="bar"' in u.commands[0]
-
- def test_rename(self):
- u = svnurl_no_svn('http://foo.bar/svn/foo', auth=self.auth)
- u.rename('http://foo.bar/svn/bar', 'moved foo to bar')
- assert '--username="foo" --password="bar"' in u.commands[0]
-
- def test_remove(self):
- u = svnurl_no_svn('http://foo.bar/svn/foo', auth=self.auth)
- u.remove(msg='removing foo')
- assert '--username="foo" --password="bar"' in u.commands[0]
-
- def test_export(self):
- u = svnurl_no_svn('http://foo.bar/svn', auth=self.auth)
- target = py.path.local('/foo')
- u.export(target)
- assert '--username="foo" --password="bar"' in u.commands[0]
-
- def test_log(self):
- u = svnurl_no_svn('http://foo.bar/svn/foo', auth=self.auth)
- u.popen_output = py.io.TextIO(py.builtin._totext('''\
-<?xml version="1.0"?>
-<log>
-<logentry revision="51381">
-<author>guido</author>
-<date>2008-02-11T12:12:18.476481Z</date>
-<msg>Creating branch to work on auth support for py.path.svn*.
-</msg>
-</logentry>
-</log>
-''', 'ascii'))
- u.check = lambda *args, **kwargs: True
- ret = u.log(10, 20, verbose=True)
- assert '--username="foo" --password="bar"' in u.commands[0]
- assert len(ret) == 1
- assert int(ret[0].rev) == 51381
- assert ret[0].author == 'guido'
-
- def test_propget(self):
- u = svnurl_no_svn('http://foo.bar/svn', auth=self.auth)
- u.propget('foo')
- assert '--username="foo" --password="bar"' in u.commands[0]
-
-def pytest_funcarg__setup(request):
- return Setup(request)
-
-class Setup:
- def __init__(self, request):
- if not svnbin:
- py.test.skip("svn binary required")
- if not request.config.option.runslowtests:
- py.test.skip('use --runslowtests to run these tests')
-
- tmpdir = request.getfuncargvalue("tmpdir")
- repodir = tmpdir.join("repo")
- py.process.cmdexec('svnadmin create %s' % repodir)
- if sys.platform == 'win32':
- repodir = '/' + str(repodir).replace('\\', '/')
- self.repo = py.path.svnurl("file://%s" % repodir)
- if py.std.sys.platform == 'win32':
- # remove trailing slash...
- repodir = repodir[1:]
- self.repopath = py.path.local(repodir)
- self.temppath = tmpdir.mkdir("temppath")
- self.auth = SvnAuth('johnny', 'foo', cache_auth=False,
- interactive=False)
- make_repo_auth(self.repopath, {'johnny': ('foo', 'rw')})
- self.port, self.pid = serve_bg(self.repopath.dirpath())
- # XXX caching is too global
- py.path.svnurl._lsnorevcache._dict.clear()
- request.addfinalizer(lambda: py.process.kill(self.pid))
-
-class TestSvnWCAuthFunctional:
- def test_checkout_constructor_arg(self, setup):
- wc = py.path.svnwc(setup.temppath, auth=setup.auth)
- wc.checkout(
- 'svn://localhost:%s/%s' % (setup.port, setup.repopath.basename))
- assert wc.join('.svn').check()
-
- def test_checkout_function_arg(self, setup):
- wc = py.path.svnwc(setup.temppath, auth=setup.auth)
- wc.checkout(
- 'svn://localhost:%s/%s' % (setup.port, setup.repopath.basename))
- assert wc.join('.svn').check()
-
- def test_checkout_failing_non_interactive(self, setup):
- auth = SvnAuth('johnny', 'bar', cache_auth=False,
- interactive=False)
- wc = py.path.svnwc(setup.temppath, auth)
- py.test.raises(Exception,
- ("wc.checkout('svn://localhost:%(port)s/%(repopath)s')" %
- setup.__dict__))
-
- def test_log(self, setup):
- wc = py.path.svnwc(setup.temppath, setup.auth)
- wc.checkout(
- 'svn://localhost:%s/%s' % (setup.port, setup.repopath.basename))
- foo = wc.ensure('foo.txt')
- wc.commit('added foo.txt')
- log = foo.log()
- assert len(log) == 1
- assert log[0].msg == 'added foo.txt'
-
- def test_switch(self, setup):
- wc = py.path.svnwc(setup.temppath, auth=setup.auth)
- svnurl = 'svn://localhost:%s/%s' % (setup.port, setup.repopath.basename)
- wc.checkout(svnurl)
- wc.ensure('foo', dir=True).ensure('foo.txt').write('foo')
- wc.commit('added foo dir with foo.txt file')
- wc.ensure('bar', dir=True)
- wc.commit('added bar dir')
- bar = wc.join('bar')
- bar.switch(svnurl + '/foo')
- assert bar.join('foo.txt')
-
- def test_update(self, setup):
- wc1 = py.path.svnwc(setup.temppath.ensure('wc1', dir=True),
- auth=setup.auth)
- wc2 = py.path.svnwc(setup.temppath.ensure('wc2', dir=True),
- auth=setup.auth)
- wc1.checkout(
- 'svn://localhost:%s/%s' % (setup.port, setup.repopath.basename))
- wc2.checkout(
- 'svn://localhost:%s/%s' % (setup.port, setup.repopath.basename))
- wc1.ensure('foo', dir=True)
- wc1.commit('added foo dir')
- wc2.update()
- assert wc2.join('foo').check()
-
- auth = SvnAuth('unknown', 'unknown', interactive=False)
- wc2.auth = auth
- py.test.raises(Exception, 'wc2.update()')
-
- def test_lock_unlock_status(self, setup):
- port = setup.port
- wc = py.path.svnwc(setup.temppath, auth=setup.auth)
- wc.checkout(
- 'svn://localhost:%s/%s' % (port, setup.repopath.basename,))
- wc.ensure('foo', file=True)
- wc.commit('added foo file')
- foo = wc.join('foo')
- foo.lock()
- status = foo.status()
- assert status.locked
- foo.unlock()
- status = foo.status()
- assert not status.locked
-
- auth = SvnAuth('unknown', 'unknown', interactive=False)
- foo.auth = auth
- py.test.raises(Exception, 'foo.lock()')
- py.test.raises(Exception, 'foo.unlock()')
-
- def test_diff(self, setup):
- port = setup.port
- wc = py.path.svnwc(setup.temppath, auth=setup.auth)
- wc.checkout(
- 'svn://localhost:%s/%s' % (port, setup.repopath.basename,))
- wc.ensure('foo', file=True)
- wc.commit('added foo file')
- wc.update()
- rev = int(wc.status().rev)
- foo = wc.join('foo')
- foo.write('bar')
- diff = foo.diff()
- assert '\n+bar\n' in diff
- foo.commit('added some content')
- diff = foo.diff()
- assert not diff
- diff = foo.diff(rev=rev)
- assert '\n+bar\n' in diff
-
- auth = SvnAuth('unknown', 'unknown', interactive=False)
- foo.auth = auth
- py.test.raises(Exception, 'foo.diff(rev=rev)')
-
-class TestSvnURLAuthFunctional:
- def test_listdir(self, setup):
- port = setup.port
- u = py.path.svnurl(
- 'svn://localhost:%s/%s' % (port, setup.repopath.basename),
- auth=setup.auth)
- u.ensure('foo')
- paths = u.listdir()
- assert len(paths) == 1
- assert paths[0].auth is setup.auth
-
- auth = SvnAuth('foo', 'bar', interactive=False)
- u = py.path.svnurl(
- 'svn://localhost:%s/%s' % (port, setup.repopath.basename),
- auth=auth)
- py.test.raises(Exception, 'u.listdir()')
-
- def test_copy(self, setup):
- port = setup.port
- u = py.path.svnurl(
- 'svn://localhost:%s/%s' % (port, setup.repopath.basename),
- auth=setup.auth)
- foo = u.mkdir('foo')
- assert foo.check()
- bar = u.join('bar')
- foo.copy(bar)
- assert bar.check()
- assert bar.auth is setup.auth
-
- auth = SvnAuth('foo', 'bar', interactive=False)
- u = py.path.svnurl(
- 'svn://localhost:%s/%s' % (port, setup.repopath.basename),
- auth=auth)
- foo = u.join('foo')
- bar = u.join('bar')
- py.test.raises(Exception, 'foo.copy(bar)')
-
- def test_write_read(self, setup):
- port = setup.port
- u = py.path.svnurl(
- 'svn://localhost:%s/%s' % (port, setup.repopath.basename),
- auth=setup.auth)
- foo = u.ensure('foo')
- fp = foo.open()
- try:
- data = fp.read()
- finally:
- fp.close()
- assert data == ''
-
- auth = SvnAuth('foo', 'bar', interactive=False)
- u = py.path.svnurl(
- 'svn://localhost:%s/%s' % (port, setup.repopath.basename),
- auth=auth)
- foo = u.join('foo')
- py.test.raises(Exception, 'foo.open()')
-
- # XXX rinse, repeat... :|
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/path/test_svnwc.py b/tests/wpt/web-platform-tests/tools/py/testing/path/test_svnwc.py
deleted file mode 100644
index 9e6b524acab..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/testing/path/test_svnwc.py
+++ /dev/null
@@ -1,549 +0,0 @@
-import py
-import os, sys
-import pytest
-from py._path.svnwc import InfoSvnWCCommand, XMLWCStatus, parse_wcinfotime
-from py._path import svnwc as svncommon
-from svntestbase import CommonSvnTests
-
-def test_make_repo(path1, tmpdir):
- repo = tmpdir.join("repo")
- py.process.cmdexec('svnadmin create %s' % repo)
- if sys.platform == 'win32':
- repo = '/' + str(repo).replace('\\', '/')
- repo = py.path.svnurl("file://%s" % repo)
- wc = py.path.svnwc(tmpdir.join("wc"))
- wc.checkout(repo)
- assert wc.rev == 0
- assert len(wc.listdir()) == 0
- p = wc.join("a_file")
- p.write("test file")
- p.add()
- rev = wc.commit("some test")
- assert p.info().rev == 1
- assert rev == 1
- rev = wc.commit()
- assert rev is None
-
-def pytest_funcarg__path1(request):
- repo, repourl, wc = request.getfuncargvalue("repowc1")
- return wc
-
-class TestWCSvnCommandPath(CommonSvnTests):
- def test_status_attributes_simple(self, path1):
- def assert_nochange(p):
- s = p.status()
- assert not s.modified
- assert not s.prop_modified
- assert not s.added
- assert not s.deleted
- assert not s.replaced
-
- dpath = path1.join('sampledir')
- assert_nochange(path1.join('sampledir'))
- assert_nochange(path1.join('samplefile'))
-
- def test_status_added(self, path1):
- nf = path1.join('newfile')
- nf.write('hello')
- nf.add()
- try:
- s = nf.status()
- assert s.added
- assert not s.modified
- assert not s.prop_modified
- assert not s.replaced
- finally:
- nf.revert()
-
- def test_status_change(self, path1):
- nf = path1.join('samplefile')
- try:
- nf.write(nf.read() + 'change')
- s = nf.status()
- assert not s.added
- assert s.modified
- assert not s.prop_modified
- assert not s.replaced
- finally:
- nf.revert()
-
- def test_status_added_ondirectory(self, path1):
- sampledir = path1.join('sampledir')
- try:
- t2 = sampledir.mkdir('t2')
- t1 = t2.join('t1')
- t1.write('test')
- t1.add()
- s = sampledir.status(rec=1)
- # Comparing just the file names, because paths are unpredictable
- # on Windows. (long vs. 8.3 paths)
- assert t1.basename in [item.basename for item in s.added]
- assert t2.basename in [item.basename for item in s.added]
- finally:
- t2.revert(rec=1)
- t2.localpath.remove(rec=1)
-
- def test_status_unknown(self, path1):
- t1 = path1.join('un1')
- try:
- t1.write('test')
- s = path1.status()
- # Comparing just the file names, because paths are unpredictable
- # on Windows. (long vs. 8.3 paths)
- assert t1.basename in [item.basename for item in s.unknown]
- finally:
- t1.localpath.remove()
-
- def test_status_unchanged(self, path1):
- r = path1
- s = path1.status(rec=1)
- # Comparing just the file names, because paths are unpredictable
- # on Windows. (long vs. 8.3 paths)
- assert r.join('samplefile').basename in [item.basename
- for item in s.unchanged]
- assert r.join('sampledir').basename in [item.basename
- for item in s.unchanged]
- assert r.join('sampledir/otherfile').basename in [item.basename
- for item in s.unchanged]
-
- @pytest.mark.xfail(reason="svn-1.7 has buggy 'status --xml' output")
- def test_status_update(self, path1):
- r = path1
- try:
- r.update(rev=1)
- s = r.status(updates=1, rec=1)
- # Comparing just the file names, because paths are unpredictable
- # on Windows. (long vs. 8.3 paths)
- py.std.pprint.pprint(s.allpath())
- assert r.join('anotherfile').basename in [item.basename for
- item in s.update_available]
- #assert len(s.update_available) == 1
- finally:
- r.update()
-
- def test_status_replaced(self, path1):
- p = path1.join("samplefile")
- p.remove()
- p.ensure(dir=0)
- try:
- s = path1.status()
- assert p.basename in [item.basename for item in s.replaced]
- finally:
- path1.revert(rec=1)
-
- def test_status_ignored(self, path1):
- try:
- d = path1.join('sampledir')
- p = py.path.local(d).join('ignoredfile')
- p.ensure(file=True)
- s = d.status()
- assert [x.basename for x in s.unknown] == ['ignoredfile']
- assert [x.basename for x in s.ignored] == []
- d.propset('svn:ignore', 'ignoredfile')
- s = d.status()
- assert [x.basename for x in s.unknown] == []
- assert [x.basename for x in s.ignored] == ['ignoredfile']
- finally:
- path1.revert(rec=1)
-
- def test_status_conflict(self, path1, tmpdir):
- wc = path1
- wccopy = py.path.svnwc(tmpdir.join("conflict_copy"))
- wccopy.checkout(wc.url)
- p = wc.ensure('conflictsamplefile', file=1)
- p.write('foo')
- wc.commit('added conflictsamplefile')
- wccopy.update()
- assert wccopy.join('conflictsamplefile').check()
- p.write('bar')
- wc.commit('wrote some data')
- wccopy.join('conflictsamplefile').write('baz')
- wccopy.update(interactive=False)
- s = wccopy.status()
- assert [x.basename for x in s.conflict] == ['conflictsamplefile']
-
- def test_status_external(self, path1, repowc2):
- otherrepo, otherrepourl, otherwc = repowc2
- d = path1.ensure('sampledir', dir=1)
- try:
- d.update()
- d.propset('svn:externals', 'otherwc %s' % (otherwc.url,))
- d.update()
- s = d.status()
- assert [x.basename for x in s.external] == ['otherwc']
- assert 'otherwc' not in [x.basename for x in s.unchanged]
- s = d.status(rec=1)
- assert [x.basename for x in s.external] == ['otherwc']
- assert 'otherwc' in [x.basename for x in s.unchanged]
- finally:
- path1.revert(rec=1)
-
- def test_status_deleted(self, path1):
- d = path1.ensure('sampledir', dir=1)
- d.remove()
- d.ensure(dir=1)
- path1.commit()
- d.ensure('deletefile', dir=0)
- d.commit()
- s = d.status()
- assert 'deletefile' in [x.basename for x in s.unchanged]
- assert not s.deleted
- p = d.join('deletefile')
- p.remove()
- s = d.status()
- assert 'deletefile' not in s.unchanged
- assert [x.basename for x in s.deleted] == ['deletefile']
-
- def test_status_noauthor(self, path1):
- # testing for XML without author - this used to raise an exception
- xml = '''\
- <entry path="/tmp/pytest-23/wc">
- <wc-status item="normal" props="none" revision="0">
- <commit revision="0">
- <date>2008-08-19T16:50:53.400198Z</date>
- </commit>
- </wc-status>
- </entry>
- '''
- XMLWCStatus.fromstring(xml, path1)
-
- def test_status_wrong_xml(self, path1):
- # testing for XML without author - this used to raise an exception
- xml = '<entry path="/home/jean/zope/venv/projectdb/parts/development-products/DataGridField">\n<wc-status item="incomplete" props="none" revision="784">\n</wc-status>\n</entry>'
- st = XMLWCStatus.fromstring(xml, path1)
- assert len(st.incomplete) == 1
-
- def test_diff(self, path1):
- p = path1 / 'anotherfile'
- out = p.diff(rev=2)
- assert out.find('hello') != -1
-
- def test_blame(self, path1):
- p = path1.join('samplepickle')
- lines = p.blame()
- assert sum([l[0] for l in lines]) == len(lines)
- for l1, l2 in zip(p.readlines(), [l[2] for l in lines]):
- assert l1 == l2
- assert [l[1] for l in lines] == ['hpk'] * len(lines)
- p = path1.join('samplefile')
- lines = p.blame()
- assert sum([l[0] for l in lines]) == len(lines)
- for l1, l2 in zip(p.readlines(), [l[2] for l in lines]):
- assert l1 == l2
- assert [l[1] for l in lines] == ['hpk'] * len(lines)
-
- def test_join_abs(self, path1):
- s = str(path1.localpath)
- n = path1.join(s, abs=1)
- assert path1 == n
-
- def test_join_abs2(self, path1):
- assert path1.join('samplefile', abs=1) == path1.join('samplefile')
-
- def test_str_gives_localpath(self, path1):
- assert str(path1) == str(path1.localpath)
-
- def test_versioned(self, path1):
- assert path1.check(versioned=1)
- # TODO: Why does my copy of svn think .svn is versioned?
- #assert path1.join('.svn').check(versioned=0)
- assert path1.join('samplefile').check(versioned=1)
- assert not path1.join('notexisting').check(versioned=1)
- notexisting = path1.join('hello').localpath
- try:
- notexisting.write("")
- assert path1.join('hello').check(versioned=0)
- finally:
- notexisting.remove()
-
- def test_listdir_versioned(self, path1):
- assert path1.check(versioned=1)
- p = path1.localpath.ensure("not_a_versioned_file")
- l = [x.localpath
- for x in path1.listdir(lambda x: x.check(versioned=True))]
- assert p not in l
-
- def test_nonversioned_remove(self, path1):
- assert path1.check(versioned=1)
- somefile = path1.join('nonversioned/somefile')
- nonwc = py.path.local(somefile)
- nonwc.ensure()
- assert somefile.check()
- assert not somefile.check(versioned=True)
- somefile.remove() # this used to fail because it tried to 'svn rm'
-
- def test_properties(self, path1):
- try:
- path1.propset('gaga', 'this')
- assert path1.propget('gaga') == 'this'
- # Comparing just the file names, because paths are unpredictable
- # on Windows. (long vs. 8.3 paths)
- assert path1.basename in [item.basename for item in
- path1.status().prop_modified]
- assert 'gaga' in path1.proplist()
- assert path1.proplist()['gaga'] == 'this'
-
- finally:
- path1.propdel('gaga')
-
- def test_proplist_recursive(self, path1):
- s = path1.join('samplefile')
- s.propset('gugu', 'that')
- try:
- p = path1.proplist(rec=1)
- # Comparing just the file names, because paths are unpredictable
- # on Windows. (long vs. 8.3 paths)
- assert (path1 / 'samplefile').basename in [item.basename
- for item in p]
- finally:
- s.propdel('gugu')
-
- def test_long_properties(self, path1):
- value = """
- vadm:posix : root root 0100755
- Properties on 'chroot/dns/var/bind/db.net.xots':
- """
- try:
- path1.propset('gaga', value)
- backvalue = path1.propget('gaga')
- assert backvalue == value
- #assert len(backvalue.split('\n')) == 1
- finally:
- path1.propdel('gaga')
-
-
- def test_ensure(self, path1):
- newpath = path1.ensure('a', 'b', 'c')
- try:
- assert newpath.check(exists=1, versioned=1)
- newpath.write("hello")
- newpath.ensure()
- assert newpath.read() == "hello"
- finally:
- path1.join('a').remove(force=1)
-
- def test_not_versioned(self, path1):
- p = path1.localpath.mkdir('whatever')
- f = path1.localpath.ensure('testcreatedfile')
- try:
- assert path1.join('whatever').check(versioned=0)
- assert path1.join('testcreatedfile').check(versioned=0)
- assert not path1.join('testcreatedfile').check(versioned=1)
- finally:
- p.remove(rec=1)
- f.remove()
-
- def test_lock_unlock(self, path1):
- root = path1
- somefile = root.join('somefile')
- somefile.ensure(file=True)
- # not yet added to repo
- py.test.raises(Exception, 'somefile.lock()')
- somefile.write('foo')
- somefile.commit('test')
- assert somefile.check(versioned=True)
- somefile.lock()
- try:
- locked = root.status().locked
- assert len(locked) == 1
- assert locked[0].basename == somefile.basename
- assert locked[0].dirpath().basename == somefile.dirpath().basename
- #assert somefile.locked()
- py.test.raises(Exception, 'somefile.lock()')
- finally:
- somefile.unlock()
- #assert not somefile.locked()
- locked = root.status().locked
- assert locked == []
- py.test.raises(Exception, 'somefile,unlock()')
- somefile.remove()
-
- def test_commit_nonrecursive(self, path1):
- somedir = path1.join('sampledir')
- somedir.mkdir("subsubdir")
- somedir.propset('foo', 'bar')
- status = somedir.status()
- assert len(status.prop_modified) == 1
- assert len(status.added) == 1
-
- somedir.commit('non-recursive commit', rec=0)
- status = somedir.status()
- assert len(status.prop_modified) == 0
- assert len(status.added) == 1
-
- somedir.commit('recursive commit')
- status = somedir.status()
- assert len(status.prop_modified) == 0
- assert len(status.added) == 0
-
- def test_commit_return_value(self, path1):
- testfile = path1.join('test.txt').ensure(file=True)
- testfile.write('test')
- rev = path1.commit('testing')
- assert type(rev) == int
-
- anotherfile = path1.join('another.txt').ensure(file=True)
- anotherfile.write('test')
- rev2 = path1.commit('testing more')
- assert type(rev2) == int
- assert rev2 == rev + 1
-
- #def test_log(self, path1):
- # l = path1.log()
- # assert len(l) == 3 # might need to be upped if more tests are added
-
-class XTestWCSvnCommandPathSpecial:
-
- rooturl = 'http://codespeak.net/svn/py.path/trunk/dist/py.path/test/data'
- #def test_update_none_rev(self, path1):
- # path = tmpdir.join('checkouttest')
- # wcpath = newpath(xsvnwc=str(path), url=path1url)
- # try:
- # wcpath.checkout(rev=2100)
- # wcpath.update()
- # assert wcpath.info().rev > 2100
- # finally:
- # wcpath.localpath.remove(rec=1)
-
-def test_parse_wcinfotime():
- assert (parse_wcinfotime('2006-05-30 20:45:26 +0200 (Tue, 30 May 2006)') ==
- 1149021926)
- assert (parse_wcinfotime('2003-10-27 20:43:14 +0100 (Mon, 27 Oct 2003)') ==
- 1067287394)
-
-class TestInfoSvnWCCommand:
-
- def test_svn_1_2(self, path1):
- output = """
- Path: test_svnwc.py
- Name: test_svnwc.py
- URL: http://codespeak.net/svn/py/dist/py/path/svn/wccommand.py
- Repository UUID: fd0d7bf2-dfb6-0310-8d31-b7ecfe96aada
- Revision: 28137
- Node Kind: file
- Schedule: normal
- Last Changed Author: jan
- Last Changed Rev: 27939
- Last Changed Date: 2006-05-30 20:45:26 +0200 (Tue, 30 May 2006)
- Text Last Updated: 2006-06-01 00:42:53 +0200 (Thu, 01 Jun 2006)
- Properties Last Updated: 2006-05-23 11:54:59 +0200 (Tue, 23 May 2006)
- Checksum: 357e44880e5d80157cc5fbc3ce9822e3
- """
- path = py.path.local(__file__).dirpath().chdir()
- try:
- info = InfoSvnWCCommand(output)
- finally:
- path.chdir()
- assert info.last_author == 'jan'
- assert info.kind == 'file'
- assert info.mtime == 1149021926.0
- assert info.url == 'http://codespeak.net/svn/py/dist/py/path/svn/wccommand.py'
- assert info.time == 1149021926000000.0
- assert info.rev == 28137
-
-
- def test_svn_1_3(self, path1):
- output = """
- Path: test_svnwc.py
- Name: test_svnwc.py
- URL: http://codespeak.net/svn/py/dist/py/path/svn/wccommand.py
- Repository Root: http://codespeak.net/svn
- Repository UUID: fd0d7bf2-dfb6-0310-8d31-b7ecfe96aada
- Revision: 28124
- Node Kind: file
- Schedule: normal
- Last Changed Author: jan
- Last Changed Rev: 27939
- Last Changed Date: 2006-05-30 20:45:26 +0200 (Tue, 30 May 2006)
- Text Last Updated: 2006-06-02 23:46:11 +0200 (Fri, 02 Jun 2006)
- Properties Last Updated: 2006-06-02 23:45:28 +0200 (Fri, 02 Jun 2006)
- Checksum: 357e44880e5d80157cc5fbc3ce9822e3
- """
- path = py.path.local(__file__).dirpath().chdir()
- try:
- info = InfoSvnWCCommand(output)
- finally:
- path.chdir()
- assert info.last_author == 'jan'
- assert info.kind == 'file'
- assert info.mtime == 1149021926.0
- assert info.url == 'http://codespeak.net/svn/py/dist/py/path/svn/wccommand.py'
- assert info.rev == 28124
- assert info.time == 1149021926000000.0
-
-
-def test_characters_at():
- py.test.raises(ValueError, "py.path.svnwc('/tmp/@@@:')")
-
-def test_characters_tilde():
- py.path.svnwc('/tmp/test~')
-
-
-class TestRepo:
- def test_trailing_slash_is_stripped(self, path1):
- # XXX we need to test more normalizing properties
- url = path1.join("/")
- assert path1 == url
-
- #def test_different_revs_compare_unequal(self, path1):
- # newpath = path1.new(rev=1199)
- # assert newpath != path1
-
- def test_exists_svn_root(self, path1):
- assert path1.check()
-
- #def test_not_exists_rev(self, path1):
- # url = path1.__class__(path1url, rev=500)
- # assert url.check(exists=0)
-
- #def test_nonexisting_listdir_rev(self, path1):
- # url = path1.__class__(path1url, rev=500)
- # raises(py.error.ENOENT, url.listdir)
-
- #def test_newrev(self, path1):
- # url = path1.new(rev=None)
- # assert url.rev == None
- # assert url.strpath == path1.strpath
- # url = path1.new(rev=10)
- # assert url.rev == 10
-
- #def test_info_rev(self, path1):
- # url = path1.__class__(path1url, rev=1155)
- # url = url.join("samplefile")
- # res = url.info()
- # assert res.size > len("samplefile") and res.created_rev == 1155
-
- # the following tests are easier if we have a path class
- def test_repocache_simple(self, path1):
- repocache = svncommon.RepoCache()
- repocache.put(path1.strpath, 42)
- url, rev = repocache.get(path1.join('test').strpath)
- assert rev == 42
- assert url == path1.strpath
-
- def test_repocache_notimeout(self, path1):
- repocache = svncommon.RepoCache()
- repocache.timeout = 0
- repocache.put(path1.strpath, path1.rev)
- url, rev = repocache.get(path1.strpath)
- assert rev == -1
- assert url == path1.strpath
-
- def test_repocache_outdated(self, path1):
- repocache = svncommon.RepoCache()
- repocache.put(path1.strpath, 42, timestamp=0)
- url, rev = repocache.get(path1.join('test').strpath)
- assert rev == -1
- assert url == path1.strpath
-
- def _test_getreporev(self):
- """ this test runs so slow it's usually disabled """
- old = svncommon.repositories.repos
- try:
- _repocache.clear()
- root = path1.new(rev=-1)
- url, rev = cache.repocache.get(root.strpath)
- assert rev>=0
- assert url == svnrepourl
- finally:
- repositories.repos = old
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/process/test_cmdexec.py b/tests/wpt/web-platform-tests/tools/py/testing/process/test_cmdexec.py
deleted file mode 100644
index b539e0af381..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/testing/process/test_cmdexec.py
+++ /dev/null
@@ -1,39 +0,0 @@
-import py
-from py.process import cmdexec
-
-def exvalue():
- return py.std.sys.exc_info()[1]
-
-class Test_exec_cmd:
- def test_simple(self):
- out = cmdexec('echo hallo')
- assert out.strip() == 'hallo'
- assert py.builtin._istext(out)
-
- def test_simple_newline(self):
- import sys
- out = cmdexec(r"""%s -c "print ('hello')" """ % sys.executable)
- assert out == 'hello\n'
- assert py.builtin._istext(out)
-
- def test_simple_error(self):
- py.test.raises (cmdexec.Error, cmdexec, 'exit 1')
-
- def test_simple_error_exact_status(self):
- try:
- cmdexec('exit 1')
- except cmdexec.Error:
- e = exvalue()
- assert e.status == 1
- assert py.builtin._istext(e.out)
- assert py.builtin._istext(e.err)
-
- def test_err(self):
- try:
- cmdexec('echoqweqwe123 hallo')
- raise AssertionError("command succeeded but shouldn't")
- except cmdexec.Error:
- e = exvalue()
- assert hasattr(e, 'err')
- assert hasattr(e, 'out')
- assert e.err or e.out
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/process/test_forkedfunc.py b/tests/wpt/web-platform-tests/tools/py/testing/process/test_forkedfunc.py
deleted file mode 100644
index d4f9f985e0f..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/testing/process/test_forkedfunc.py
+++ /dev/null
@@ -1,177 +0,0 @@
-import pytest
-import py, sys, os
-
-pytestmark = py.test.mark.skipif("not hasattr(os, 'fork')")
-
-
-def test_waitfinish_removes_tempdir():
- ff = py.process.ForkedFunc(boxf1)
- assert ff.tempdir.check()
- ff.waitfinish()
- assert not ff.tempdir.check()
-
-def test_tempdir_gets_gc_collected(monkeypatch):
- monkeypatch.setattr(os, 'fork', lambda: os.getpid())
- ff = py.process.ForkedFunc(boxf1)
- assert ff.tempdir.check()
- ff.__del__()
- assert not ff.tempdir.check()
-
-def test_basic_forkedfunc():
- result = py.process.ForkedFunc(boxf1).waitfinish()
- assert result.out == "some out\n"
- assert result.err == "some err\n"
- assert result.exitstatus == 0
- assert result.signal == 0
- assert result.retval == 1
-
-def test_exitstatus():
- def func():
- os._exit(4)
- result = py.process.ForkedFunc(func).waitfinish()
- assert result.exitstatus == 4
- assert result.signal == 0
- assert not result.out
- assert not result.err
-
-def test_execption_in_func():
- def fun():
- raise ValueError(42)
- ff = py.process.ForkedFunc(fun)
- result = ff.waitfinish()
- assert result.exitstatus == ff.EXITSTATUS_EXCEPTION
- assert result.err.find("ValueError: 42") != -1
- assert result.signal == 0
- assert not result.retval
-
-def test_forkedfunc_on_fds():
- result = py.process.ForkedFunc(boxf2).waitfinish()
- assert result.out == "someout"
- assert result.err == "someerr"
- assert result.exitstatus == 0
- assert result.signal == 0
- assert result.retval == 2
-
-def test_forkedfunc_on_fds_output():
- result = py.process.ForkedFunc(boxf3).waitfinish()
- assert result.signal == 11
- assert result.out == "s"
-
-
-def test_forkedfunc_on_stdout():
- def boxf3():
- import sys
- sys.stdout.write("hello\n")
- os.kill(os.getpid(), 11)
- result = py.process.ForkedFunc(boxf3).waitfinish()
- assert result.signal == 11
- assert result.out == "hello\n"
-
-def test_forkedfunc_signal():
- result = py.process.ForkedFunc(boxseg).waitfinish()
- assert result.retval is None
- if sys.version_info < (2,4):
- py.test.skip("signal detection does not work with python prior 2.4")
- assert result.signal == 11
-
-def test_forkedfunc_huge_data():
- result = py.process.ForkedFunc(boxhuge).waitfinish()
- assert result.out
- assert result.exitstatus == 0
- assert result.signal == 0
- assert result.retval == 3
-
-def test_box_seq():
- # we run many boxes with huge data, just one after another
- for i in range(50):
- result = py.process.ForkedFunc(boxhuge).waitfinish()
- assert result.out
- assert result.exitstatus == 0
- assert result.signal == 0
- assert result.retval == 3
-
-def test_box_in_a_box():
- def boxfun():
- result = py.process.ForkedFunc(boxf2).waitfinish()
- print (result.out)
- sys.stderr.write(result.err + "\n")
- return result.retval
-
- result = py.process.ForkedFunc(boxfun).waitfinish()
- assert result.out == "someout\n"
- assert result.err == "someerr\n"
- assert result.exitstatus == 0
- assert result.signal == 0
- assert result.retval == 2
-
-def test_kill_func_forked():
- class A:
- pass
- info = A()
- import time
-
- def box_fun():
- time.sleep(10) # we don't want to last forever here
-
- ff = py.process.ForkedFunc(box_fun)
- os.kill(ff.pid, 15)
- result = ff.waitfinish()
- if py.std.sys.version_info < (2,4):
- py.test.skip("signal detection does not work with python prior 2.4")
- assert result.signal == 15
-
-
-def test_hooks(monkeypatch):
- def _boxed():
- return 1
-
- def _on_start():
- sys.stdout.write("some out\n")
- sys.stdout.flush()
-
- def _on_exit():
- sys.stderr.write("some err\n")
- sys.stderr.flush()
-
- result = py.process.ForkedFunc(_boxed, child_on_start=_on_start,
- child_on_exit=_on_exit).waitfinish()
- assert result.out == "some out\n"
- assert result.err == "some err\n"
- assert result.exitstatus == 0
- assert result.signal == 0
- assert result.retval == 1
-
-
-# ======================================================================
-# examples
-# ======================================================================
-#
-
-def boxf1():
- sys.stdout.write("some out\n")
- sys.stderr.write("some err\n")
- return 1
-
-def boxf2():
- os.write(1, "someout".encode('ascii'))
- os.write(2, "someerr".encode('ascii'))
- return 2
-
-def boxf3():
- os.write(1, "s".encode('ascii'))
- os.kill(os.getpid(), 11)
-
-def boxseg():
- os.kill(os.getpid(), 11)
-
-def boxhuge():
- s = " ".encode('ascii')
- os.write(1, s * 10000)
- os.write(2, s * 10000)
- os.write(1, s * 10000)
-
- os.write(1, s * 10000)
- os.write(2, s * 10000)
- os.write(2, s * 10000)
- os.write(1, s * 10000)
- return 3
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/process/test_killproc.py b/tests/wpt/web-platform-tests/tools/py/testing/process/test_killproc.py
deleted file mode 100644
index 57088e1db8c..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/testing/process/test_killproc.py
+++ /dev/null
@@ -1,16 +0,0 @@
-
-import py, sys
-
-@py.test.mark.skipif("sys.platform.startswith('java')")
-def test_kill(tmpdir):
- subprocess = py.test.importorskip("subprocess")
- t = tmpdir.join("t.py")
- t.write("import time ; time.sleep(100)")
- proc = py.std.subprocess.Popen([sys.executable, str(t)])
- assert proc.poll() is None # no return value yet
- py.process.kill(proc.pid)
- ret = proc.wait()
- if sys.platform == "win32" and ret == 0:
- py.test.skip("XXX on win32, subprocess.Popen().wait() on a killed "
- "process does not yield return value != 0")
- assert ret != 0
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/root/test_error.py b/tests/wpt/web-platform-tests/tools/py/testing/root/test_error.py
deleted file mode 100644
index a34e0068d92..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/testing/root/test_error.py
+++ /dev/null
@@ -1,37 +0,0 @@
-
-import py
-
-import errno
-
-def test_error_classes():
- for name in errno.errorcode.values():
- x = getattr(py.error, name)
- assert issubclass(x, py.error.Error)
- assert issubclass(x, EnvironmentError)
-
-def test_picklability_issue1():
- e1 = py.error.ENOENT()
- s = py.std.pickle.dumps(e1)
- e2 = py.std.pickle.loads(s)
- assert isinstance(e2, py.error.ENOENT)
-
-def test_unknown_error():
- num = 3999
- cls = py.error._geterrnoclass(num)
- assert cls.__name__ == 'UnknownErrno%d' % (num,)
- assert issubclass(cls, py.error.Error)
- assert issubclass(cls, EnvironmentError)
- cls2 = py.error._geterrnoclass(num)
- assert cls is cls2
-
-def test_error_conversion_ENOTDIR(testdir):
- p = testdir.makepyfile("")
- excinfo = py.test.raises(py.error.Error, py.error.checked_call, p.listdir)
- assert isinstance(excinfo.value, EnvironmentError)
- assert isinstance(excinfo.value, py.error.Error)
- assert "ENOTDIR" in repr(excinfo.value)
-
-
-def test_checked_call_supports_kwargs(tmpdir):
- import tempfile
- py.error.checked_call(tempfile.mkdtemp, dir=str(tmpdir))
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/root/test_py_imports.py b/tests/wpt/web-platform-tests/tools/py/testing/root/test_py_imports.py
deleted file mode 100644
index 5f5954e9943..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/testing/root/test_py_imports.py
+++ /dev/null
@@ -1,68 +0,0 @@
-import py
-import types
-import sys
-
-def checksubpackage(name):
- obj = getattr(py, name)
- if hasattr(obj, '__map__'): # isinstance(obj, Module):
- keys = dir(obj)
- assert len(keys) > 0
- print (obj.__map__)
- for name in list(obj.__map__):
- assert hasattr(obj, name), (obj, name)
-
-def test_dir():
- for name in dir(py):
- if not name.startswith('_'):
- yield checksubpackage, name
-
-def test_virtual_module_identity():
- from py import path as path1
- from py import path as path2
- assert path1 is path2
- from py.path import local as local1
- from py.path import local as local2
- assert local1 is local2
-
-def test_importall():
- base = py._pydir
- nodirs = [
- ]
- if sys.version_info >= (3,0):
- nodirs.append(base.join('_code', '_assertionold.py'))
- else:
- nodirs.append(base.join('_code', '_assertionnew.py'))
-
- def recurse(p):
- return p.check(dotfile=0) and p.basename != "attic"
-
- for p in base.visit('*.py', recurse):
- if p.basename == '__init__.py':
- continue
- relpath = p.new(ext='').relto(base)
- if base.sep in relpath: # not py/*.py itself
- for x in nodirs:
- if p == x or p.relto(x):
- break
- else:
- relpath = relpath.replace(base.sep, '.')
- modpath = 'py.%s' % relpath
- try:
- check_import(modpath)
- except py.test.skip.Exception:
- pass
-
-def check_import(modpath):
- py.builtin.print_("checking import", modpath)
- assert __import__(modpath)
-
-def test_all_resolves():
- seen = py.builtin.set([py])
- lastlength = None
- while len(seen) != lastlength:
- lastlength = len(seen)
- for item in py.builtin.frozenset(seen):
- for value in item.__dict__.values():
- if isinstance(value, type(py.test)):
- seen.add(value)
-
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/root/test_xmlgen.py b/tests/wpt/web-platform-tests/tools/py/testing/root/test_xmlgen.py
deleted file mode 100644
index 704d1492cb3..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/testing/root/test_xmlgen.py
+++ /dev/null
@@ -1,145 +0,0 @@
-
-import py
-from py._xmlgen import unicode, html, raw
-
-class ns(py.xml.Namespace):
- pass
-
-def test_escape():
- uvalue = py.builtin._totext('\xc4\x85\xc4\x87\n\xe2\x82\xac\n', 'utf-8')
- class A:
- def __unicode__(self):
- return uvalue
- def __str__(self):
- x = self.__unicode__()
- if py.std.sys.version_info[0] < 3:
- return x.encode('utf-8')
- return x
- y = py.xml.escape(uvalue)
- assert y == uvalue
- x = py.xml.escape(A())
- assert x == uvalue
- if py.std.sys.version_info[0] < 3:
- assert isinstance(x, unicode)
- assert isinstance(y, unicode)
- y = py.xml.escape(uvalue.encode('utf-8'))
- assert y == uvalue
-
-
-def test_tag_with_text():
- x = ns.hello("world")
- u = unicode(x)
- assert u == "<hello>world</hello>"
-
-def test_class_identity():
- assert ns.hello is ns.hello
-
-def test_tag_with_text_and_attributes():
- x = ns.some(name="hello", value="world")
- assert x.attr.name == 'hello'
- assert x.attr.value == 'world'
- u = unicode(x)
- assert u == '<some name="hello" value="world"/>'
-
-def test_tag_with_subclassed_attr_simple():
- class my(ns.hello):
- class Attr(ns.hello.Attr):
- hello="world"
- x = my()
- assert x.attr.hello == 'world'
- assert unicode(x) == '<my hello="world"/>'
-
-def test_tag_with_raw_attr():
- x = html.object(data=raw('&'))
- assert unicode(x) == '<object data="&"></object>'
-
-def test_tag_nested():
- x = ns.hello(ns.world())
- unicode(x) # triggers parentifying
- assert x[0].parent is x
- u = unicode(x)
- assert u == '<hello><world/></hello>'
-
-def test_list_nested():
- x = ns.hello([ns.world()]) #pass in a list here
- u = unicode(x)
- assert u == '<hello><world/></hello>'
-
-def test_tag_xmlname():
- class my(ns.hello):
- xmlname = 'world'
- u = unicode(my())
- assert u == '<world/>'
-
-def test_tag_with_text_entity():
- x = ns.hello('world & rest')
- u = unicode(x)
- assert u == "<hello>world &amp; rest</hello>"
-
-def test_tag_with_text_and_attributes_entity():
- x = ns.some(name="hello & world")
- assert x.attr.name == "hello & world"
- u = unicode(x)
- assert u == '<some name="hello &amp; world"/>'
-
-def test_raw():
- x = ns.some(py.xml.raw("<p>literal</p>"))
- u = unicode(x)
- assert u == "<some><p>literal</p></some>"
-
-
-def test_html_name_stickyness():
- class my(html.p):
- pass
- x = my("hello")
- assert unicode(x) == '<p>hello</p>'
-
-def test_stylenames():
- class my:
- class body(html.body):
- style = html.Style(font_size = "12pt")
- u = unicode(my.body())
- assert u == '<body style="font-size: 12pt"></body>'
-
-def test_class_None():
- t = html.body(class_=None)
- u = unicode(t)
- assert u == '<body></body>'
-
-def test_alternating_style():
- alternating = (
- html.Style(background="white"),
- html.Style(background="grey"),
- )
- class my(html):
- class li(html.li):
- def style(self):
- i = self.parent.index(self)
- return alternating[i%2]
- style = property(style)
-
- x = my.ul(
- my.li("hello"),
- my.li("world"),
- my.li("42"))
- u = unicode(x)
- assert u == ('<ul><li style="background: white">hello</li>'
- '<li style="background: grey">world</li>'
- '<li style="background: white">42</li>'
- '</ul>')
-
-def test_singleton():
- h = html.head(html.link(href="foo"))
- assert unicode(h) == '<head><link href="foo"/></head>'
-
- h = html.head(html.script(src="foo"))
- assert unicode(h) == '<head><script src="foo"></script></head>'
-
-def test_inline():
- h = html.div(html.span('foo'), html.span('bar'))
- assert (h.unicode(indent=2) ==
- '<div><span>foo</span><span>bar</span></div>')
-
-def test_object_tags():
- o = html.object(html.object())
- assert o.unicode(indent=0) == '<object><object></object></object>'
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/test_iniconfig.py b/tests/wpt/web-platform-tests/tools/py/testing/test_iniconfig.py
deleted file mode 100644
index 9a7f72c11b3..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/testing/test_iniconfig.py
+++ /dev/null
@@ -1,299 +0,0 @@
-import py
-import pytest
-from py._iniconfig import IniConfig, ParseError, __all__ as ALL
-from py._iniconfig import iscommentline
-from textwrap import dedent
-
-def pytest_generate_tests(metafunc):
- if 'input' in metafunc.funcargnames:
- for name, (input, expected) in check_tokens.items():
- metafunc.addcall(id=name, funcargs={
- 'input': input,
- 'expected': expected,
- })
- elif hasattr(metafunc.function, 'multi'):
- kwargs = metafunc.function.multi.kwargs
- names, values = zip(*kwargs.items())
- values = cartesian_product(*values)
- for p in values:
- metafunc.addcall(funcargs=dict(zip(names, p)))
-
-def cartesian_product(L,*lists):
- # copied from http://bit.ly/cyIXjn
- if not lists:
- for x in L:
- yield (x,)
- else:
- for x in L:
- for y in cartesian_product(lists[0],*lists[1:]):
- yield (x,)+y
-
-check_tokens = {
- 'section': (
- '[section]',
- [(0, 'section', None, None)]
- ),
- 'value': (
- 'value = 1',
- [(0, None, 'value', '1')]
- ),
- 'value in section': (
- '[section]\nvalue=1',
- [(0, 'section', None, None), (1, 'section', 'value', '1')]
- ),
- 'value with continuation': (
- 'names =\n Alice\n Bob',
- [(0, None, 'names', 'Alice\nBob')]
- ),
- 'value with aligned continuation': (
- 'names = Alice\n'
- ' Bob',
- [(0, None, 'names', 'Alice\nBob')]
- ),
- 'blank line':(
- '[section]\n\nvalue=1',
- [(0, 'section', None, None), (2, 'section', 'value', '1')]
- ),
- 'comment': (
- '# comment',
- []
- ),
- 'comment on value': (
- 'value = 1',
- [(0, None, 'value', '1')]
- ),
-
- 'comment on section': (
- '[section] #comment',
- [(0, 'section', None, None)]
- ),
- 'comment2': (
- '; comment',
- []
- ),
-
- 'comment2 on section': (
- '[section] ;comment',
- [(0, 'section', None, None)]
- ),
- 'pseudo section syntax in value': (
- 'name = value []',
- [(0, None, 'name', 'value []')]
- ),
- 'assignment in value': (
- 'value = x = 3',
- [(0, None, 'value', 'x = 3')]
- ),
- 'use of colon for name-values': (
- 'name: y',
- [(0, None, 'name', 'y')]
- ),
- 'use of colon without space': (
- 'value:y=5',
- [(0, None, 'value', 'y=5')]
- ),
- 'equality gets precedence': (
- 'value=xyz:5',
- [(0, None, 'value', 'xyz:5')]
- ),
-
-}
-
-def parse(input):
- # only for testing purposes - _parse() does not use state except path
- ini = object.__new__(IniConfig)
- ini.path = "sample"
- return ini._parse(input.splitlines(True))
-
-def parse_a_error(input):
- return py.test.raises(ParseError, parse, input)
-
-def test_tokenize(input, expected):
- parsed = parse(input)
- assert parsed == expected
-
-def test_parse_empty():
- parsed = parse("")
- assert not parsed
- ini = IniConfig("sample", "")
- assert not ini.sections
-
-def test_ParseError():
- e = ParseError("filename", 0, "hello")
- assert str(e) == "filename:1: hello"
-
-def test_continuation_needs_perceeding_token():
- excinfo = parse_a_error(' Foo')
- assert excinfo.value.lineno == 0
-
-def test_continuation_cant_be_after_section():
- excinfo = parse_a_error('[section]\n Foo')
- assert excinfo.value.lineno == 1
-
-def test_section_cant_be_empty():
- excinfo = parse_a_error('[]')
-
-@py.test.mark.multi(line=[
- '!!',
- ])
-def test_error_on_weird_lines(line):
- parse_a_error(line)
-
-def test_iniconfig_from_file(tmpdir):
- path = tmpdir/'test.txt'
- path.write('[metadata]\nname=1')
-
- config = IniConfig(path=path)
- assert list(config.sections) == ['metadata']
- config = IniConfig(path, "[diff]")
- assert list(config.sections) == ['diff']
- py.test.raises(TypeError, "IniConfig(data=path.read())")
-
-def test_iniconfig_section_first(tmpdir):
- excinfo = py.test.raises(ParseError, """
- IniConfig("x", data='name=1')
- """)
- assert excinfo.value.msg == "no section header defined"
-
-def test_iniconig_section_duplicate_fails():
- excinfo = py.test.raises(ParseError, r"""
- IniConfig("x", data='[section]\n[section]')
- """)
- assert 'duplicate section' in str(excinfo.value)
-
-def test_iniconfig_duplicate_key_fails():
- excinfo = py.test.raises(ParseError, r"""
- IniConfig("x", data='[section]\nname = Alice\nname = bob')
- """)
-
- assert 'duplicate name' in str(excinfo.value)
-
-def test_iniconfig_lineof():
- config = IniConfig("x.ini", data=
- '[section]\n'
- 'value = 1\n'
- '[section2]\n'
- '# comment\n'
- 'value =2'
- )
-
- assert config.lineof('missing') is None
- assert config.lineof('section') == 1
- assert config.lineof('section2') == 3
- assert config.lineof('section', 'value') == 2
- assert config.lineof('section2','value') == 5
-
- assert config['section'].lineof('value') == 2
- assert config['section2'].lineof('value') == 5
-
-def test_iniconfig_get_convert():
- config= IniConfig("x", data='[section]\nint = 1\nfloat = 1.1')
- assert config.get('section', 'int') == '1'
- assert config.get('section', 'int', convert=int) == 1
-
-def test_iniconfig_get_missing():
- config= IniConfig("x", data='[section]\nint = 1\nfloat = 1.1')
- assert config.get('section', 'missing', default=1) == 1
- assert config.get('section', 'missing') is None
-
-def test_section_get():
- config = IniConfig("x", data='[section]\nvalue=1')
- section = config['section']
- assert section.get('value', convert=int) == 1
- assert section.get('value', 1) == "1"
- assert section.get('missing', 2) == 2
-
-def test_missing_section():
- config = IniConfig("x", data='[section]\nvalue=1')
- py.test.raises(KeyError,'config["other"]')
-
-def test_section_getitem():
- config = IniConfig("x", data='[section]\nvalue=1')
- assert config['section']['value'] == '1'
- assert config['section']['value'] == '1'
-
-def test_section_iter():
- config = IniConfig("x", data='[section]\nvalue=1')
- names = list(config['section'])
- assert names == ['value']
- items = list(config['section'].items())
- assert items==[('value', '1')]
-
-def test_config_iter():
- config = IniConfig("x.ini", data=dedent('''
- [section1]
- value=1
- [section2]
- value=2
- '''))
- l = list(config)
- assert len(l) == 2
- assert l[0].name == 'section1'
- assert l[0]['value'] == '1'
- assert l[1].name == 'section2'
- assert l[1]['value'] == '2'
-
-def test_config_contains():
- config = IniConfig("x.ini", data=dedent('''
- [section1]
- value=1
- [section2]
- value=2
- '''))
- assert 'xyz' not in config
- assert 'section1' in config
- assert 'section2' in config
-
-def test_iter_file_order():
- config = IniConfig("x.ini", data="""
-[section2] #cpython dict ordered before section
-value = 1
-value2 = 2 # dict ordered before value
-[section]
-a = 1
-b = 2
-""")
- l = list(config)
- secnames = [x.name for x in l]
- assert secnames == ['section2', 'section']
- assert list(config['section2']) == ['value', 'value2']
- assert list(config['section']) == ['a', 'b']
-
-def test_example_pypirc():
- config = IniConfig("pypirc", data=dedent('''
- [distutils]
- index-servers =
- pypi
- other
-
- [pypi]
- repository: <repository-url>
- username: <username>
- password: <password>
-
- [other]
- repository: http://example.com/pypi
- username: <username>
- password: <password>
- '''))
- distutils, pypi, other = list(config)
- assert distutils["index-servers"] == "pypi\nother"
- assert pypi['repository'] == '<repository-url>'
- assert pypi['username'] == '<username>'
- assert pypi['password'] == '<password>'
- assert ['repository', 'username', 'password'] == list(other)
-
-
-def test_api_import():
- assert ALL == ['IniConfig', 'ParseError']
-
-@pytest.mark.parametrize("line", [
- "#qwe",
- " #qwe",
- ";qwe",
- " ;qwe",
-])
-def test_iscommentline_true(line):
- assert iscommentline(line)
-
-
diff --git a/tests/wpt/web-platform-tests/tools/py/tox.ini b/tests/wpt/web-platform-tests/tools/py/tox.ini
deleted file mode 100644
index 8c0c79d6960..00000000000
--- a/tests/wpt/web-platform-tests/tools/py/tox.ini
+++ /dev/null
@@ -1,39 +0,0 @@
-[tox]
-envlist=py26,py27,py33,py34,external
-# py27-xdist causes problems with svn, py25 requires virtualenv==1.9.1
-#indexserver=
-# default=http://pypi.testrun.org
-
-[testenv]
-changedir=testing
-commands=py.test --confcutdir=.. -rfsxX --junitxml={envlogdir}/junit-{envname}.xml []
-deps=pytest
-
-[testenv:py27-xdist]
-basepython=python2.7
-deps=
- pytest
- pytest-xdist
-commands=
- py.test -n3 -rfsxX --confcutdir=.. --runslowtests \
- --junitxml={envlogdir}/junit-{envname}.xml []
-
-[testenv:jython]
-changedir=testing
-commands=
- {envpython} -m pytest --confcutdir=.. -rfsxX --junitxml={envlogdir}/junit-{envname}0.xml {posargs:io_ code}
-
-[testenv:py25]
-setenv = PIP_INSECURE=1
-
-[testenv:external]
-deps=
- pytest
- jinja2
- decorator
-commands=
- py.test --confcutdir=.. -rfsxX --junitxml={envlogdir}/junit-{envname}.xml {posargs:code}
-
-[pytest]
-rsyncdirs = conftest.py py doc testing
-addopts = -rxXf
diff --git a/tests/wpt/web-platform-tests/tools/pytest.ini b/tests/wpt/web-platform-tests/tools/pytest.ini
index e1ad451c8b3..ecef9b7173d 100644
--- a/tests/wpt/web-platform-tests/tools/pytest.ini
+++ b/tests/wpt/web-platform-tests/tools/pytest.ini
@@ -1,2 +1,2 @@
[pytest]
-norecursedirs = .* {arch} *.egg html5lib py pytest pywebsocket six wpt wptrunner
+norecursedirs = .* {arch} *.egg html5lib third_party pywebsocket six wpt wptrunner
diff --git a/tests/wpt/web-platform-tests/tools/pytest/.coveragerc b/tests/wpt/web-platform-tests/tools/pytest/.coveragerc
deleted file mode 100644
index 27db64e09c1..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/.coveragerc
+++ /dev/null
@@ -1,7 +0,0 @@
-[run]
-omit =
- # standlonetemplate is read dynamically and tested by test_genscript
- *standalonetemplate.py
- # oldinterpret could be removed, as it is no longer used in py26+
- *oldinterpret.py
- vendored_packages
diff --git a/tests/wpt/web-platform-tests/tools/pytest/.github/ISSUE_TEMPLATE.md b/tests/wpt/web-platform-tests/tools/pytest/.github/ISSUE_TEMPLATE.md
deleted file mode 100644
index bc62e8a3f7d..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/.github/ISSUE_TEMPLATE.md
+++ /dev/null
@@ -1,8 +0,0 @@
-Thanks for submitting an issue!
-
-Here's a quick checklist in what to include:
-
-- [ ] Include a detailed description of the bug or suggestion
-- [ ] `pip list` of the virtual environment you are using
-- [ ] py.test and operating system versions
-- [ ] Minimal example if possible
diff --git a/tests/wpt/web-platform-tests/tools/pytest/.github/PULL_REQUEST_TEMPLATE.md b/tests/wpt/web-platform-tests/tools/pytest/.github/PULL_REQUEST_TEMPLATE.md
deleted file mode 100644
index d09edce43d3..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/.github/PULL_REQUEST_TEMPLATE.md
+++ /dev/null
@@ -1,8 +0,0 @@
-Thanks for submitting a PR, your contribution is really appreciated!
-
-Here's a quick checklist that should be present in PRs:
-
-- [ ] Target: for bug or doc fixes, target `master`; for new features, target `features`
-- [ ] Make sure to include one or more tests for your change
-- [ ] Add yourself to `AUTHORS`
-- [ ] Add a new entry to the `CHANGELOG` (choose any open position to avoid merge conflicts with other PRs)
diff --git a/tests/wpt/web-platform-tests/tools/pytest/.gitignore b/tests/wpt/web-platform-tests/tools/pytest/.gitignore
deleted file mode 100644
index e4355b859cc..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/.gitignore
+++ /dev/null
@@ -1,34 +0,0 @@
-# Automatically generated by `hgimportsvn`
-.svn
-.hgsvn
-
-# Ignore local virtualenvs
-lib/
-bin/
-include/
-.Python/
-
-# These lines are suggested according to the svn:ignore property
-# Feel free to enable them by uncommenting them
-*.pyc
-*.pyo
-*.swp
-*.class
-*.orig
-*~
-
-.eggs/
-
-doc/*/_build
-build/
-dist/
-*.egg-info
-issue/
-env/
-.env/
-3rdparty/
-.tox
-.cache
-.coverage
-.ropeproject
-.idea
diff --git a/tests/wpt/web-platform-tests/tools/pytest/.travis.yml b/tests/wpt/web-platform-tests/tools/pytest/.travis.yml
deleted file mode 100644
index 3a8f36e95f8..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/.travis.yml
+++ /dev/null
@@ -1,40 +0,0 @@
-sudo: false
-language: python
-python:
- - '3.5'
-# command to install dependencies
-install: "pip install -U tox"
-# # command to run tests
-env:
- matrix:
- # coveralls is not listed in tox's envlist, but should run in travis
- - TESTENV=coveralls
- # note: please use "tox --listenvs" to populate the build matrix below
- - TESTENV=linting
- - TESTENV=py26
- - TESTENV=py27
- - TESTENV=py33
- - TESTENV=py34
- - TESTENV=py35
- - TESTENV=pypy
- - TESTENV=py27-pexpect
- - TESTENV=py27-xdist
- - TESTENV=py27-trial
- - TESTENV=py35-pexpect
- - TESTENV=py35-xdist
- - TESTENV=py35-trial
- - TESTENV=py27-nobyte
- - TESTENV=doctesting
- - TESTENV=py27-cxfreeze
-
-script: tox --recreate -e $TESTENV
-
-notifications:
- irc:
- channels:
- - "chat.freenode.net#pytest"
- on_success: change
- on_failure: change
- skip_join: true
- email:
- - pytest-commit@python.org
diff --git a/tests/wpt/web-platform-tests/tools/pytest/AUTHORS b/tests/wpt/web-platform-tests/tools/pytest/AUTHORS
deleted file mode 100644
index dfc0a542ec5..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/AUTHORS
+++ /dev/null
@@ -1,87 +0,0 @@
-Holger Krekel, holger at merlinux eu
-merlinux GmbH, Germany, office at merlinux eu
-
-Contributors include::
-
-Abhijeet Kasurde
-Anatoly Bubenkoff
-Andreas Zeidler
-Andy Freeland
-Anthon van der Neut
-Armin Rigo
-Aron Curzon
-Aviv Palivoda
-Benjamin Peterson
-Bob Ippolito
-Brian Dorsey
-Brian Okken
-Brianna Laugher
-Bruno Oliveira
-Carl Friedrich Bolz
-Charles Cloud
-Chris Lamb
-Christian Theunert
-Christian Tismer
-Christopher Gilling
-Daniel Grana
-Daniel Hahler
-Daniel Nuri
-Dave Hunt
-David Mohr
-David Vierra
-Edison Gustavo Muenz
-Eduardo Schettino
-Endre Galaczi
-Elizaveta Shashkova
-Eric Hunsberger
-Eric Siegerman
-Erik M. Bray
-Florian Bruhin
-Floris Bruynooghe
-Gabriel Reis
-Georgy Dyuldin
-Graham Horler
-Grig Gheorghiu
-Guido Wesdorp
-Harald Armin Massa
-Ian Bicking
-Jaap Broekhuizen
-Jan Balster
-Janne Vanhala
-Jason R. Coombs
-Joshua Bronson
-Jurko Gospodnetić
-Katarzyna Jachim
-Kevin Cox
-Lee Kamentsky
-Lukas Bednar
-Maciek Fijalkowski
-Maho
-Marc Schlaich
-Mark Abramowitz
-Markus Unterwaditzer
-Martijn Faassen
-Matt Bachmann
-Michael Aquilina
-Michael Birtwell
-Michael Droettboom
-Nicolas Delaby
-Pieter Mulder
-Piotr Banaszkiewicz
-Punyashloka Biswal
-Ralf Schmitt
-Raphael Pierzina
-Ronny Pfannschmidt
-Ross Lawley
-Ryan Wooden
-Samuele Pedroni
-Tom Viner
-Trevor Bekolay
-Wouter van Ackooy
-David Díaz-Barquero
-Eric Hunsberger
-Simon Gomizelj
-Russel Winder
-Ben Webb
-Alexei Kozlenok
-Cal Leeming
diff --git a/tests/wpt/web-platform-tests/tools/pytest/CHANGELOG.rst b/tests/wpt/web-platform-tests/tools/pytest/CHANGELOG.rst
deleted file mode 100644
index f18f646f008..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/CHANGELOG.rst
+++ /dev/null
@@ -1,2586 +0,0 @@
-2.9.1
-=====
-
-**Bug Fixes**
-
-* Improve error message when a plugin fails to load.
- Thanks `@nicoddemus`_ for the PR.
-
-* Fix (`#1178 <https://github.com/pytest-dev/pytest/issues/1178>`_):
- ``pytest.fail`` with non-ascii characters raises an internal pytest error.
- Thanks `@nicoddemus`_ for the PR.
-
-* Fix (`#469`_): junit parses report.nodeid incorrectly, when params IDs
- contain ``::``. Thanks `@tomviner`_ for the PR (`#1431`_).
-
-* Fix (`#578 <https://github.com/pytest-dev/pytest/issues/578>`_): SyntaxErrors
- containing non-ascii lines at the point of failure generated an internal
- py.test error.
- Thanks `@asottile`_ for the report and `@nicoddemus`_ for the PR.
-
-* Fix (`#1437`_): When passing in a bytestring regex pattern to parameterize
- attempt to decode it as utf-8 ignoring errors.
-
-* Fix (`#649`_): parametrized test nodes cannot be specified to run on the command line.
-
-
-.. _#1437: https://github.com/pytest-dev/pytest/issues/1437
-.. _#469: https://github.com/pytest-dev/pytest/issues/469
-.. _#1431: https://github.com/pytest-dev/pytest/pull/1431
-.. _#649: https://github.com/pytest-dev/pytest/issues/649
-
-.. _@asottile: https://github.com/asottile
-
-
-2.9.0
-=====
-
-**New Features**
-
-* New ``pytest.mark.skip`` mark, which unconditionally skips marked tests.
- Thanks `@MichaelAquilina`_ for the complete PR (`#1040`_).
-
-* ``--doctest-glob`` may now be passed multiple times in the command-line.
- Thanks `@jab`_ and `@nicoddemus`_ for the PR.
-
-* New ``-rp`` and ``-rP`` reporting options give the summary and full output
- of passing tests, respectively. Thanks to `@codewarrior0`_ for the PR.
-
-* ``pytest.mark.xfail`` now has a ``strict`` option, which makes ``XPASS``
- tests to fail the test suite (defaulting to ``False``). There's also a
- ``xfail_strict`` ini option that can be used to configure it project-wise.
- Thanks `@rabbbit`_ for the request and `@nicoddemus`_ for the PR (`#1355`_).
-
-* ``Parser.addini`` now supports options of type ``bool``.
- Thanks `@nicoddemus`_ for the PR.
-
-* New ``ALLOW_BYTES`` doctest option. This strips ``b`` prefixes from byte strings
- in doctest output (similar to ``ALLOW_UNICODE``).
- Thanks `@jaraco`_ for the request and `@nicoddemus`_ for the PR (`#1287`_).
-
-* Give a hint on ``KeyboardInterrupt`` to use the ``--fulltrace`` option to show the errors.
- Fixes `#1366`_.
- Thanks to `@hpk42`_ for the report and `@RonnyPfannschmidt`_ for the PR.
-
-* Catch ``IndexError`` exceptions when getting exception source location.
- Fixes a pytest internal error for dynamically generated code (fixtures and tests)
- where source lines are fake by intention.
-
-**Changes**
-
-* **Important**: `py.code <http://pylib.readthedocs.org/en/latest/code.html>`_ has been
- merged into the ``pytest`` repository as ``pytest._code``. This decision
- was made because ``py.code`` had very few uses outside ``pytest`` and the
- fact that it was in a different repository made it difficult to fix bugs on
- its code in a timely manner. The team hopes with this to be able to better
- refactor out and improve that code.
- This change shouldn't affect users, but it is useful to let users aware
- if they encounter any strange behavior.
-
- Keep in mind that the code for ``pytest._code`` is **private** and
- **experimental**, so you definitely should not import it explicitly!
-
- Please note that the original ``py.code`` is still available in
- `pylib <http://pylib.readthedocs.org>`_.
-
-* ``pytest_enter_pdb`` now optionally receives the pytest config object.
- Thanks `@nicoddemus`_ for the PR.
-
-* Removed code and documentation for Python 2.5 or lower versions,
- including removal of the obsolete ``_pytest.assertion.oldinterpret`` module.
- Thanks `@nicoddemus`_ for the PR (`#1226`_).
-
-* Comparisons now always show up in full when ``CI`` or ``BUILD_NUMBER`` is
- found in the environment, even when ``-vv`` isn't used.
- Thanks `@The-Compiler`_ for the PR.
-
-* ``--lf`` and ``--ff`` now support long names: ``--last-failed`` and
- ``--failed-first`` respectively.
- Thanks `@MichaelAquilina`_ for the PR.
-
-* Added expected exceptions to ``pytest.raises`` fail message.
-
-* Collection only displays progress ("collecting X items") when in a terminal.
- This avoids cluttering the output when using ``--color=yes`` to obtain
- colors in CI integrations systems (`#1397`_).
-
-**Bug Fixes**
-
-* The ``-s`` and ``-c`` options should now work under ``xdist``;
- ``Config.fromdictargs`` now represents its input much more faithfully.
- Thanks to `@bukzor`_ for the complete PR (`#680`_).
-
-* Fix (`#1290`_): support Python 3.5's ``@`` operator in assertion rewriting.
- Thanks `@Shinkenjoe`_ for report with test case and `@tomviner`_ for the PR.
-
-* Fix formatting utf-8 explanation messages (`#1379`_).
- Thanks `@biern`_ for the PR.
-
-* Fix `traceback style docs`_ to describe all of the available options
- (auto/long/short/line/native/no), with `auto` being the default since v2.6.
- Thanks `@hackebrot`_ for the PR.
-
-* Fix (`#1422`_): junit record_xml_property doesn't allow multiple records
- with same name.
-
-.. _`traceback style docs`: https://pytest.org/latest/usage.html#modifying-python-traceback-printing
-
-.. _#1422: https://github.com/pytest-dev/pytest/issues/1422
-.. _#1379: https://github.com/pytest-dev/pytest/issues/1379
-.. _#1366: https://github.com/pytest-dev/pytest/issues/1366
-.. _#1040: https://github.com/pytest-dev/pytest/pull/1040
-.. _#680: https://github.com/pytest-dev/pytest/issues/680
-.. _#1287: https://github.com/pytest-dev/pytest/pull/1287
-.. _#1226: https://github.com/pytest-dev/pytest/pull/1226
-.. _#1290: https://github.com/pytest-dev/pytest/pull/1290
-.. _#1355: https://github.com/pytest-dev/pytest/pull/1355
-.. _#1397: https://github.com/pytest-dev/pytest/issues/1397
-.. _@biern: https://github.com/biern
-.. _@MichaelAquilina: https://github.com/MichaelAquilina
-.. _@bukzor: https://github.com/bukzor
-.. _@hpk42: https://github.com/hpk42
-.. _@nicoddemus: https://github.com/nicoddemus
-.. _@jab: https://github.com/jab
-.. _@codewarrior0: https://github.com/codewarrior0
-.. _@jaraco: https://github.com/jaraco
-.. _@The-Compiler: https://github.com/The-Compiler
-.. _@Shinkenjoe: https://github.com/Shinkenjoe
-.. _@tomviner: https://github.com/tomviner
-.. _@RonnyPfannschmidt: https://github.com/RonnyPfannschmidt
-.. _@rabbbit: https://github.com/rabbbit
-.. _@hackebrot: https://github.com/hackebrot
-
-2.8.7
-=====
-
-- fix #1338: use predictable object resolution for monkeypatch
-
-2.8.6
-=====
-
-- fix #1259: allow for double nodeids in junitxml,
- this was a regression failing plugins combinations
- like pytest-pep8 + pytest-flakes
-
-- Workaround for exception that occurs in pyreadline when using
- ``--pdb`` with standard I/O capture enabled.
- Thanks Erik M. Bray for the PR.
-
-- fix #900: Better error message in case the target of a ``monkeypatch`` call
- raises an ``ImportError``.
-
-- fix #1292: monkeypatch calls (setattr, setenv, etc.) are now O(1).
- Thanks David R. MacIver for the report and Bruno Oliveira for the PR.
-
-- fix #1223: captured stdout and stderr are now properly displayed before
- entering pdb when ``--pdb`` is used instead of being thrown away.
- Thanks Cal Leeming for the PR.
-
-- fix #1305: pytest warnings emitted during ``pytest_terminal_summary`` are now
- properly displayed.
- Thanks Ionel Maries Cristian for the report and Bruno Oliveira for the PR.
-
-- fix #628: fixed internal UnicodeDecodeError when doctests contain unicode.
- Thanks Jason R. Coombs for the report and Bruno Oliveira for the PR.
-
-- fix #1334: Add captured stdout to jUnit XML report on setup error.
- Thanks Georgy Dyuldin for the PR.
-
-
-2.8.5
-=====
-
-- fix #1243: fixed issue where class attributes injected during collection could break pytest.
- PR by Alexei Kozlenok, thanks Ronny Pfannschmidt and Bruno Oliveira for the review and help.
-
-- fix #1074: precompute junitxml chunks instead of storing the whole tree in objects
- Thanks Bruno Oliveira for the report and Ronny Pfannschmidt for the PR
-
-- fix #1238: fix ``pytest.deprecated_call()`` receiving multiple arguments
- (Regression introduced in 2.8.4). Thanks Alex Gaynor for the report and
- Bruno Oliveira for the PR.
-
-
-2.8.4
-=====
-
-- fix #1190: ``deprecated_call()`` now works when the deprecated
- function has been already called by another test in the same
- module. Thanks Mikhail Chernykh for the report and Bruno Oliveira for the
- PR.
-
-- fix #1198: ``--pastebin`` option now works on Python 3. Thanks
- Mehdy Khoshnoody for the PR.
-
-- fix #1219: ``--pastebin`` now works correctly when captured output contains
- non-ascii characters. Thanks Bruno Oliveira for the PR.
-
-- fix #1204: another error when collecting with a nasty __getattr__().
- Thanks Florian Bruhin for the PR.
-
-- fix the summary printed when no tests did run.
- Thanks Florian Bruhin for the PR.
-- fix #1185 - ensure MANIFEST.in exactly matches what should go to a sdist
-
-- a number of documentation modernizations wrt good practices.
- Thanks Bruno Oliveira for the PR.
-
-2.8.3
-=====
-
-- fix #1169: add __name__ attribute to testcases in TestCaseFunction to
- support the @unittest.skip decorator on functions and methods.
- Thanks Lee Kamentsky for the PR.
-
-- fix #1035: collecting tests if test module level obj has __getattr__().
- Thanks Suor for the report and Bruno Oliveira / Tom Viner for the PR.
-
-- fix #331: don't collect tests if their failure cannot be reported correctly
- e.g. they are a callable instance of a class.
-
-- fix #1133: fixed internal error when filtering tracebacks where one entry
- belongs to a file which is no longer available.
- Thanks Bruno Oliveira for the PR.
-
-- enhancement made to highlight in red the name of the failing tests so
- they stand out in the output.
- Thanks Gabriel Reis for the PR.
-
-- add more talks to the documentation
-- extend documentation on the --ignore cli option
-- use pytest-runner for setuptools integration
-- minor fixes for interaction with OS X El Capitan
- system integrity protection (thanks Florian)
-
-
-2.8.2
-=====
-
-- fix #1085: proper handling of encoding errors when passing encoded byte
- strings to pytest.parametrize in Python 2.
- Thanks Themanwithoutaplan for the report and Bruno Oliveira for the PR.
-
-- fix #1087: handling SystemError when passing empty byte strings to
- pytest.parametrize in Python 3.
- Thanks Paul Kehrer for the report and Bruno Oliveira for the PR.
-
-- fix #995: fixed internal error when filtering tracebacks where one entry
- was generated by an exec() statement.
- Thanks Daniel Hahler, Ashley C Straw, Philippe Gauthier and Pavel Savchenko
- for contributing and Bruno Oliveira for the PR.
-
-- fix #1100 and #1057: errors when using autouse fixtures and doctest modules.
- Thanks Sergey B Kirpichev and Vital Kudzelka for contributing and Bruno
- Oliveira for the PR.
-
-2.8.1
-=====
-
-- fix #1034: Add missing nodeid on pytest_logwarning call in
- addhook. Thanks Simon Gomizelj for the PR.
-
-- 'deprecated_call' is now only satisfied with a DeprecationWarning or
- PendingDeprecationWarning. Before 2.8.0, it accepted any warning, and 2.8.0
- made it accept only DeprecationWarning (but not PendingDeprecationWarning).
- Thanks Alex Gaynor for the issue and Eric Hunsberger for the PR.
-
-- fix issue #1073: avoid calling __getattr__ on potential plugin objects.
- This fixes an incompatibility with pytest-django. Thanks Andreas Pelme,
- Bruno Oliveira and Ronny Pfannschmidt for contributing and Holger Krekel
- for the fix.
-
-- Fix issue #704: handle versionconflict during plugin loading more
- gracefully. Thanks Bruno Oliveira for the PR.
-
-- Fix issue #1064: ""--junitxml" regression when used with the
- "pytest-xdist" plugin, with test reports being assigned to the wrong tests.
- Thanks Daniel Grunwald for the report and Bruno Oliveira for the PR.
-
-- (experimental) adapt more SEMVER style versioning and change meaning of
- master branch in git repo: "master" branch now keeps the bugfixes, changes
- aimed for micro releases. "features" branch will only be be released
- with minor or major pytest releases.
-
-- Fix issue #766 by removing documentation references to distutils.
- Thanks Russel Winder.
-
-- Fix issue #1030: now byte-strings are escaped to produce item node ids
- to make them always serializable.
- Thanks Andy Freeland for the report and Bruno Oliveira for the PR.
-
-- Python 2: if unicode parametrized values are convertible to ascii, their
- ascii representation is used for the node id.
-
-- Fix issue #411: Add __eq__ method to assertion comparison example.
- Thanks Ben Webb.
-- Fix issue #653: deprecated_call can be used as context manager.
-
-- fix issue 877: properly handle assertion explanations with non-ascii repr
- Thanks Mathieu Agopian for the report and Ronny Pfannschmidt for the PR.
-
-- fix issue 1029: transform errors when writing cache values into pytest-warnings
-
-2.8.0
-=====
-
-- new ``--lf`` and ``-ff`` options to run only the last failing tests or
- "failing tests first" from the last run. This functionality is provided
- through porting the formerly external pytest-cache plugin into pytest core.
- BACKWARD INCOMPAT: if you used pytest-cache's functionality to persist
- data between test runs be aware that we don't serialize sets anymore.
- Thanks Ronny Pfannschmidt for most of the merging work.
-
-- "-r" option now accepts "a" to include all possible reports, similar
- to passing "fEsxXw" explicitly (isse960).
- Thanks Abhijeet Kasurde for the PR.
-
-- avoid python3.5 deprecation warnings by introducing version
- specific inspection helpers, thanks Michael Droettboom.
-
-- fix issue562: @nose.tools.istest now fully respected.
-
-- fix issue934: when string comparison fails and a diff is too large to display
- without passing -vv, still show a few lines of the diff.
- Thanks Florian Bruhin for the report and Bruno Oliveira for the PR.
-
-- fix issue736: Fix a bug where fixture params would be discarded when combined
- with parametrization markers.
- Thanks to Markus Unterwaditzer for the PR.
-
-- fix issue710: introduce ALLOW_UNICODE doctest option: when enabled, the
- ``u`` prefix is stripped from unicode strings in expected doctest output. This
- allows doctests which use unicode to run in Python 2 and 3 unchanged.
- Thanks Jason R. Coombs for the report and Bruno Oliveira for the PR.
-
-- parametrize now also generates meaningful test IDs for enum, regex and class
- objects (as opposed to class instances).
- Thanks to Florian Bruhin for the PR.
-
-- Add 'warns' to assert that warnings are thrown (like 'raises').
- Thanks to Eric Hunsberger for the PR.
-
-- Fix issue683: Do not apply an already applied mark. Thanks ojake for the PR.
-
-- Deal with capturing failures better so fewer exceptions get lost to
- /dev/null. Thanks David Szotten for the PR.
-
-- fix issue730: deprecate and warn about the --genscript option.
- Thanks Ronny Pfannschmidt for the report and Christian Pommranz for the PR.
-
-- fix issue751: multiple parametrize with ids bug if it parametrizes class with
- two or more test methods. Thanks Sergey Chipiga for reporting and Jan
- Bednarik for PR.
-
-- fix issue82: avoid loading conftest files from setup.cfg/pytest.ini/tox.ini
- files and upwards by default (--confcutdir can still be set to override this).
- Thanks Bruno Oliveira for the PR.
-
-- fix issue768: docstrings found in python modules were not setting up session
- fixtures. Thanks Jason R. Coombs for reporting and Bruno Oliveira for the PR.
-
-- added ``tmpdir_factory``, a session-scoped fixture that can be used to create
- directories under the base temporary directory. Previously this object was
- installed as a ``_tmpdirhandler`` attribute of the ``config`` object, but now it
- is part of the official API and using ``config._tmpdirhandler`` is
- deprecated.
- Thanks Bruno Oliveira for the PR.
-
-- fix issue808: pytest's internal assertion rewrite hook now implements the
- optional PEP302 get_data API so tests can access data files next to them.
- Thanks xmo-odoo for request and example and Bruno Oliveira for
- the PR.
-
-- rootdir and inifile are now displayed during usage errors to help
- users diagnose problems such as unexpected ini files which add
- unknown options being picked up by pytest. Thanks to Pavel Savchenko for
- bringing the problem to attention in #821 and Bruno Oliveira for the PR.
-
-- Summary bar now is colored yellow for warning
- situations such as: all tests either were skipped or xpass/xfailed,
- or no tests were run at all (this is a partial fix for issue500).
-
-- fix issue812: pytest now exits with status code 5 in situations where no
- tests were run at all, such as the directory given in the command line does
- not contain any tests or as result of a command line option filters
- all out all tests (-k for example).
- Thanks Eric Siegerman (issue812) and Bruno Oliveira for the PR.
-
-- Summary bar now is colored yellow for warning
- situations such as: all tests either were skipped or xpass/xfailed,
- or no tests were run at all (related to issue500).
- Thanks Eric Siegerman.
-
-- New ``testpaths`` ini option: list of directories to search for tests
- when executing pytest from the root directory. This can be used
- to speed up test collection when a project has well specified directories
- for tests, being usually more practical than configuring norecursedirs for
- all directories that do not contain tests.
- Thanks to Adrian for idea (#694) and Bruno Oliveira for the PR.
-
-- fix issue713: JUnit XML reports for doctest failures.
- Thanks Punyashloka Biswal.
-
-- fix issue970: internal pytest warnings now appear as "pytest-warnings" in
- the terminal instead of "warnings", so it is clear for users that those
- warnings are from pytest and not from the builtin "warnings" module.
- Thanks Bruno Oliveira.
-
-- Include setup and teardown in junitxml test durations.
- Thanks Janne Vanhala.
-
-- fix issue735: assertion failures on debug versions of Python 3.4+
-
-- new option ``--import-mode`` to allow to change test module importing
- behaviour to append to sys.path instead of prepending. This better allows
- to run test modules against installated versions of a package even if the
- package under test has the same import root. In this example::
-
- testing/__init__.py
- testing/test_pkg_under_test.py
- pkg_under_test/
-
- the tests will run against the installed version
- of pkg_under_test when ``--import-mode=append`` is used whereas
- by default they would always pick up the local version. Thanks Holger Krekel.
-
-- pytester: add method ``TmpTestdir.delete_loaded_modules()``, and call it
- from ``inline_run()`` to allow temporary modules to be reloaded.
- Thanks Eduardo Schettino.
-
-- internally refactor pluginmanager API and code so that there
- is a clear distinction between a pytest-agnostic rather simple
- pluginmanager and the PytestPluginManager which adds a lot of
- behaviour, among it handling of the local conftest files.
- In terms of documented methods this is a backward compatible
- change but it might still break 3rd party plugins which relied on
- details like especially the pluginmanager.add_shutdown() API.
- Thanks Holger Krekel.
-
-- pluginmanagement: introduce ``pytest.hookimpl`` and
- ``pytest.hookspec`` decorators for setting impl/spec
- specific parameters. This substitutes the previous
- now deprecated use of ``pytest.mark`` which is meant to
- contain markers for test functions only.
-
-- write/refine docs for "writing plugins" which now have their
- own page and are separate from the "using/installing plugins`` page.
-
-- fix issue732: properly unregister plugins from any hook calling
- sites allowing to have temporary plugins during test execution.
-
-- deprecate and warn about ``__multicall__`` argument in hook
- implementations. Use the ``hookwrapper`` mechanism instead already
- introduced with pytest-2.7.
-
-- speed up pytest's own test suite considerably by using inprocess
- tests by default (testrun can be modified with --runpytest=subprocess
- to create subprocesses in many places instead). The main
- APIs to run pytest in a test is "runpytest()" or "runpytest_subprocess"
- and "runpytest_inprocess" if you need a particular way of running
- the test. In all cases you get back a RunResult but the inprocess
- one will also have a "reprec" attribute with the recorded events/reports.
-
-- fix monkeypatch.setattr("x.y", raising=False) to actually not raise
- if "y" is not a pre-existing attribute. Thanks Florian Bruhin.
-
-- fix issue741: make running output from testdir.run copy/pasteable
- Thanks Bruno Oliveira.
-
-- add a new ``--noconftest`` argument which ignores all ``conftest.py`` files.
-
-- add ``file`` and ``line`` attributes to JUnit-XML output.
-
-- fix issue890: changed extension of all documentation files from ``txt`` to
- ``rst``. Thanks to Abhijeet for the PR.
-
-- fix issue714: add ability to apply indirect=True parameter on particular argnames.
- Thanks Elizaveta239.
-
-- fix issue890: changed extension of all documentation files from ``txt`` to
- ``rst``. Thanks to Abhijeet for the PR.
-
-- fix issue957: "# doctest: SKIP" option will now register doctests as SKIPPED
- rather than PASSED.
- Thanks Thomas Grainger for the report and Bruno Oliveira for the PR.
-
-- issue951: add new record_xml_property fixture, that supports logging
- additional information on xml output. Thanks David Diaz for the PR.
-
-- issue949: paths after normal options (for example ``-s``, ``-v``, etc) are now
- properly used to discover ``rootdir`` and ``ini`` files.
- Thanks Peter Lauri for the report and Bruno Oliveira for the PR.
-
-2.7.3 (compared to 2.7.2)
-=============================
-
-- Allow 'dev', 'rc', or other non-integer version strings in ``importorskip``.
- Thanks to Eric Hunsberger for the PR.
-
-- fix issue856: consider --color parameter in all outputs (for example
- --fixtures). Thanks Barney Gale for the report and Bruno Oliveira for the PR.
-
-- fix issue855: passing str objects as ``plugins`` argument to pytest.main
- is now interpreted as a module name to be imported and registered as a
- plugin, instead of silently having no effect.
- Thanks xmo-odoo for the report and Bruno Oliveira for the PR.
-
-- fix issue744: fix for ast.Call changes in Python 3.5+. Thanks
- Guido van Rossum, Matthias Bussonnier, Stefan Zimmermann and
- Thomas Kluyver.
-
-- fix issue842: applying markers in classes no longer propagate this markers
- to superclasses which also have markers.
- Thanks xmo-odoo for the report and Bruno Oliveira for the PR.
-
-- preserve warning functions after call to pytest.deprecated_call. Thanks
- Pieter Mulder for PR.
-
-- fix issue854: autouse yield_fixtures defined as class members of
- unittest.TestCase subclasses now work as expected.
- Thannks xmo-odoo for the report and Bruno Oliveira for the PR.
-
-- fix issue833: --fixtures now shows all fixtures of collected test files, instead of just the
- fixtures declared on the first one.
- Thanks Florian Bruhin for reporting and Bruno Oliveira for the PR.
-
-- fix issue863: skipped tests now report the correct reason when a skip/xfail
- condition is met when using multiple markers.
- Thanks Raphael Pierzina for reporting and Bruno Oliveira for the PR.
-
-- optimized tmpdir fixture initialization, which should make test sessions
- faster (specially when using pytest-xdist). The only visible effect
- is that now pytest uses a subdirectory in the $TEMP directory for all
- directories created by this fixture (defaults to $TEMP/pytest-$USER).
- Thanks Bruno Oliveira for the PR.
-
-2.7.2 (compared to 2.7.1)
-=============================
-
-- fix issue767: pytest.raises value attribute does not contain the exception
- instance on Python 2.6. Thanks Eric Siegerman for providing the test
- case and Bruno Oliveira for PR.
-
-- Automatically create directory for junitxml and results log.
- Thanks Aron Curzon.
-
-- fix issue713: JUnit XML reports for doctest failures.
- Thanks Punyashloka Biswal.
-
-- fix issue735: assertion failures on debug versions of Python 3.4+
- Thanks Benjamin Peterson.
-
-- fix issue114: skipif marker reports to internal skipping plugin;
- Thanks Floris Bruynooghe for reporting and Bruno Oliveira for the PR.
-
-- fix issue748: unittest.SkipTest reports to internal pytest unittest plugin.
- Thanks Thomas De Schampheleire for reporting and Bruno Oliveira for the PR.
-
-- fix issue718: failed to create representation of sets containing unsortable
- elements in python 2. Thanks Edison Gustavo Muenz.
-
-- fix issue756, fix issue752 (and similar issues): depend on py-1.4.29
- which has a refined algorithm for traceback generation.
-
-
-2.7.1 (compared to 2.7.0)
-=============================
-
-- fix issue731: do not get confused by the braces which may be present
- and unbalanced in an object's repr while collapsing False
- explanations. Thanks Carl Meyer for the report and test case.
-
-- fix issue553: properly handling inspect.getsourcelines failures in
- FixtureLookupError which would lead to to an internal error,
- obfuscating the original problem. Thanks talljosh for initial
- diagnose/patch and Bruno Oliveira for final patch.
-
-- fix issue660: properly report scope-mismatch-access errors
- independently from ordering of fixture arguments. Also
- avoid the pytest internal traceback which does not provide
- information to the user. Thanks Holger Krekel.
-
-- streamlined and documented release process. Also all versions
- (in setup.py and documentation generation) are now read
- from _pytest/__init__.py. Thanks Holger Krekel.
-
-- fixed docs to remove the notion that yield-fixtures are experimental.
- They are here to stay :) Thanks Bruno Oliveira.
-
-- Support building wheels by using environment markers for the
- requirements. Thanks Ionel Maries Cristian.
-
-- fixed regression to 2.6.4 which surfaced e.g. in lost stdout capture printing
- when tests raised SystemExit. Thanks Holger Krekel.
-
-- reintroduced _pytest fixture of the pytester plugin which is used
- at least by pytest-xdist.
-
-2.7.0 (compared to 2.6.4)
-=============================
-
-- fix issue435: make reload() work when assert rewriting is active.
- Thanks Daniel Hahler.
-
-- fix issue616: conftest.py files and their contained fixutres are now
- properly considered for visibility, independently from the exact
- current working directory and test arguments that are used.
- Many thanks to Eric Siegerman and his PR235 which contains
- systematic tests for conftest visibility and now passes.
- This change also introduces the concept of a ``rootdir`` which
- is printed as a new pytest header and documented in the pytest
- customize web page.
-
-- change reporting of "diverted" tests, i.e. tests that are collected
- in one file but actually come from another (e.g. when tests in a test class
- come from a base class in a different file). We now show the nodeid
- and indicate via a postfix the other file.
-
-- add ability to set command line options by environment variable PYTEST_ADDOPTS.
-
-- added documentation on the new pytest-dev teams on bitbucket and
- github. See https://pytest.org/latest/contributing.html .
- Thanks to Anatoly for pushing and initial work on this.
-
-- fix issue650: new option ``--docttest-ignore-import-errors`` which
- will turn import errors in doctests into skips. Thanks Charles Cloud
- for the complete PR.
-
-- fix issue655: work around different ways that cause python2/3
- to leak sys.exc_info into fixtures/tests causing failures in 3rd party code
-
-- fix issue615: assertion re-writing did not correctly escape % signs
- when formatting boolean operations, which tripped over mixing
- booleans with modulo operators. Thanks to Tom Viner for the report,
- triaging and fix.
-
-- implement issue351: add ability to specify parametrize ids as a callable
- to generate custom test ids. Thanks Brianna Laugher for the idea and
- implementation.
-
-- introduce and document new hookwrapper mechanism useful for plugins
- which want to wrap the execution of certain hooks for their purposes.
- This supersedes the undocumented ``__multicall__`` protocol which
- pytest itself and some external plugins use. Note that pytest-2.8
- is scheduled to drop supporting the old ``__multicall__``
- and only support the hookwrapper protocol.
-
-- majorly speed up invocation of plugin hooks
-
-- use hookwrapper mechanism in builtin pytest plugins.
-
-- add a doctest ini option for doctest flags, thanks Holger Peters.
-
-- add note to docs that if you want to mark a parameter and the
- parameter is a callable, you also need to pass in a reason to disambiguate
- it from the "decorator" case. Thanks Tom Viner.
-
-- "python_classes" and "python_functions" options now support glob-patterns
- for test discovery, as discussed in issue600. Thanks Ldiary Translations.
-
-- allow to override parametrized fixtures with non-parametrized ones and vice versa (bubenkoff).
-
-- fix issue463: raise specific error for 'parameterize' misspelling (pfctdayelise).
-
-- On failure, the ``sys.last_value``, ``sys.last_type`` and
- ``sys.last_traceback`` are set, so that a user can inspect the error
- via postmortem debugging (almarklein).
-
-2.6.4
-=====
-
-- Improve assertion failure reporting on iterables, by using ndiff and
- pprint.
-
-- removed outdated japanese docs from source tree.
-
-- docs for "pytest_addhooks" hook. Thanks Bruno Oliveira.
-
-- updated plugin index docs. Thanks Bruno Oliveira.
-
-- fix issue557: with "-k" we only allow the old style "-" for negation
- at the beginning of strings and even that is deprecated. Use "not" instead.
- This should allow to pick parametrized tests where "-" appeared in the parameter.
-
-- fix issue604: Escape % character in the assertion message.
-
-- fix issue620: add explanation in the --genscript target about what
- the binary blob means. Thanks Dinu Gherman.
-
-- fix issue614: fixed pastebin support.
-
-
-- fix issue620: add explanation in the --genscript target about what
- the binary blob means. Thanks Dinu Gherman.
-
-- fix issue614: fixed pastebin support.
-
-2.6.3
-=====
-
-- fix issue575: xunit-xml was reporting collection errors as failures
- instead of errors, thanks Oleg Sinyavskiy.
-
-- fix issue582: fix setuptools example, thanks Laszlo Papp and Ronny
- Pfannschmidt.
-
-- Fix infinite recursion bug when pickling capture.EncodedFile, thanks
- Uwe Schmitt.
-
-- fix issue589: fix bad interaction with numpy and others when showing
- exceptions. Check for precise "maximum recursion depth exceed" exception
- instead of presuming any RuntimeError is that one (implemented in py
- dep). Thanks Charles Cloud for analysing the issue.
-
-- fix conftest related fixture visibility issue: when running with a
- CWD outside a test package pytest would get fixture discovery wrong.
- Thanks to Wolfgang Schnerring for figuring out a reproducable example.
-
-- Introduce pytest_enter_pdb hook (needed e.g. by pytest_timeout to cancel the
- timeout when interactively entering pdb). Thanks Wolfgang Schnerring.
-
-- check xfail/skip also with non-python function test items. Thanks
- Floris Bruynooghe.
-
-2.6.2
-=====
-
-- Added function pytest.freeze_includes(), which makes it easy to embed
- pytest into executables using tools like cx_freeze.
- See docs for examples and rationale. Thanks Bruno Oliveira.
-
-- Improve assertion rewriting cache invalidation precision.
-
-- fixed issue561: adapt autouse fixture example for python3.
-
-- fixed issue453: assertion rewriting issue with __repr__ containing
- "\n{", "\n}" and "\n~".
-
-- fix issue560: correctly display code if an "else:" or "finally:" is
- followed by statements on the same line.
-
-- Fix example in monkeypatch documentation, thanks t-8ch.
-
-- fix issue572: correct tmpdir doc example for python3.
-
-- Do not mark as universal wheel because Python 2.6 is different from
- other builds due to the extra argparse dependency. Fixes issue566.
- Thanks sontek.
-
-- Implement issue549: user-provided assertion messages now no longer
- replace the py.test introspection message but are shown in addition
- to them.
-
-2.6.1
-=====
-
-- No longer show line numbers in the --verbose output, the output is now
- purely the nodeid. The line number is still shown in failure reports.
- Thanks Floris Bruynooghe.
-
-- fix issue437 where assertion rewriting could cause pytest-xdist slaves
- to collect different tests. Thanks Bruno Oliveira.
-
-- fix issue555: add "errors" attribute to capture-streams to satisfy
- some distutils and possibly other code accessing sys.stdout.errors.
-
-- fix issue547 capsys/capfd also work when output capturing ("-s") is disabled.
-
-- address issue170: allow pytest.mark.xfail(...) to specify expected exceptions via
- an optional "raises=EXC" argument where EXC can be a single exception
- or a tuple of exception classes. Thanks David Mohr for the complete
- PR.
-
-- fix integration of pytest with unittest.mock.patch decorator when
- it uses the "new" argument. Thanks Nicolas Delaby for test and PR.
-
-- fix issue with detecting conftest files if the arguments contain
- "::" node id specifications (copy pasted from "-v" output)
-
-- fix issue544 by only removing "@NUM" at the end of "::" separated parts
- and if the part has an ".py" extension
-
-- don't use py.std import helper, rather import things directly.
- Thanks Bruno Oliveira.
-
-2.6
-===
-
-- Cache exceptions from fixtures according to their scope (issue 467).
-
-- fix issue537: Avoid importing old assertion reinterpretation code by default.
-
-- fix issue364: shorten and enhance tracebacks representation by default.
- The new "--tb=auto" option (default) will only display long tracebacks
- for the first and last entry. You can get the old behaviour of printing
- all entries as long entries with "--tb=long". Also short entries by
- default are now printed very similarly to "--tb=native" ones.
-
-- fix issue514: teach assertion reinterpretation about private class attributes
-
-- change -v output to include full node IDs of tests. Users can copy
- a node ID from a test run, including line number, and use it as a
- positional argument in order to run only a single test.
-
-- fix issue 475: fail early and comprehensible if calling
- pytest.raises with wrong exception type.
-
-- fix issue516: tell in getting-started about current dependencies.
-
-- cleanup setup.py a bit and specify supported versions. Thanks Jurko
- Gospodnetic for the PR.
-
-- change XPASS colour to yellow rather then red when tests are run
- with -v.
-
-- fix issue473: work around mock putting an unbound method into a class
- dict when double-patching.
-
-- fix issue498: if a fixture finalizer fails, make sure that
- the fixture is still invalidated.
-
-- fix issue453: the result of the pytest_assertrepr_compare hook now gets
- it's newlines escaped so that format_exception does not blow up.
-
-- internal new warning system: pytest will now produce warnings when
- it detects oddities in your test collection or execution.
- Warnings are ultimately sent to a new pytest_logwarning hook which is
- currently only implemented by the terminal plugin which displays
- warnings in the summary line and shows more details when -rw (report on
- warnings) is specified.
-
-- change skips into warnings for test classes with an __init__ and
- callables in test modules which look like a test but are not functions.
-
-- fix issue436: improved finding of initial conftest files from command
- line arguments by using the result of parse_known_args rather than
- the previous flaky heuristics. Thanks Marc Abramowitz for tests
- and initial fixing approaches in this area.
-
-- fix issue #479: properly handle nose/unittest(2) SkipTest exceptions
- during collection/loading of test modules. Thanks to Marc Schlaich
- for the complete PR.
-
-- fix issue490: include pytest_load_initial_conftests in documentation
- and improve docstring.
-
-- fix issue472: clarify that ``pytest.config.getvalue()`` cannot work
- if it's triggered ahead of command line parsing.
-
-- merge PR123: improved integration with mock.patch decorator on tests.
-
-- fix issue412: messing with stdout/stderr FD-level streams is now
- captured without crashes.
-
-- fix issue483: trial/py33 works now properly. Thanks Daniel Grana for PR.
-
-- improve example for pytest integration with "python setup.py test"
- which now has a generic "-a" or "--pytest-args" option where you
- can pass additional options as a quoted string. Thanks Trevor Bekolay.
-
-- simplified internal capturing mechanism and made it more robust
- against tests or setups changing FD1/FD2, also better integrated
- now with pytest.pdb() in single tests.
-
-- improvements to pytest's own test-suite leakage detection, courtesy of PRs
- from Marc Abramowitz
-
-- fix issue492: avoid leak in test_writeorg. Thanks Marc Abramowitz.
-
-- fix issue493: don't run tests in doc directory with ``python setup.py test``
- (use tox -e doctesting for that)
-
-- fix issue486: better reporting and handling of early conftest loading failures
-
-- some cleanup and simplification of internal conftest handling.
-
-- work a bit harder to break reference cycles when catching exceptions.
- Thanks Jurko Gospodnetic.
-
-- fix issue443: fix skip examples to use proper comparison. Thanks Alex
- Groenholm.
-
-- support nose-style ``__test__`` attribute on modules, classes and
- functions, including unittest-style Classes. If set to False, the
- test will not be collected.
-
-- fix issue512: show "<notset>" for arguments which might not be set
- in monkeypatch plugin. Improves output in documentation.
-
-
-2.5.2
-=====
-
-- fix issue409 -- better interoperate with cx_freeze by not
- trying to import from collections.abc which causes problems
- for py27/cx_freeze. Thanks Wolfgang L. for reporting and tracking it down.
-
-- fixed docs and code to use "pytest" instead of "py.test" almost everywhere.
- Thanks Jurko Gospodnetic for the complete PR.
-
-- fix issue425: mention at end of "py.test -h" that --markers
- and --fixtures work according to specified test path (or current dir)
-
-- fix issue413: exceptions with unicode attributes are now printed
- correctly also on python2 and with pytest-xdist runs. (the fix
- requires py-1.4.20)
-
-- copy, cleanup and integrate py.io capture
- from pylib 1.4.20.dev2 (rev 13d9af95547e)
-
-- address issue416: clarify docs as to conftest.py loading semantics
-
-- fix issue429: comparing byte strings with non-ascii chars in assert
- expressions now work better. Thanks Floris Bruynooghe.
-
-- make capfd/capsys.capture private, its unused and shouldnt be exposed
-
-
-2.5.1
-=====
-
-- merge new documentation styling PR from Tobias Bieniek.
-
-- fix issue403: allow parametrize of multiple same-name functions within
- a collection node. Thanks Andreas Kloeckner and Alex Gaynor for reporting
- and analysis.
-
-- Allow parameterized fixtures to specify the ID of the parameters by
- adding an ids argument to pytest.fixture() and pytest.yield_fixture().
- Thanks Floris Bruynooghe.
-
-- fix issue404 by always using the binary xml escape in the junitxml
- plugin. Thanks Ronny Pfannschmidt.
-
-- fix issue407: fix addoption docstring to point to argparse instead of
- optparse. Thanks Daniel D. Wright.
-
-
-
-2.5.0
-=====
-
-- dropped python2.5 from automated release testing of pytest itself
- which means it's probably going to break soon (but still works
- with this release we believe).
-
-- simplified and fixed implementation for calling finalizers when
- parametrized fixtures or function arguments are involved. finalization
- is now performed lazily at setup time instead of in the "teardown phase".
- While this might sound odd at first, it helps to ensure that we are
- correctly handling setup/teardown even in complex code. User-level code
- should not be affected unless it's implementing the pytest_runtest_teardown
- hook and expecting certain fixture instances are torn down within (very
- unlikely and would have been unreliable anyway).
-
-- PR90: add --color=yes|no|auto option to force terminal coloring
- mode ("auto" is default). Thanks Marc Abramowitz.
-
-- fix issue319 - correctly show unicode in assertion errors. Many
- thanks to Floris Bruynooghe for the complete PR. Also means
- we depend on py>=1.4.19 now.
-
-- fix issue396 - correctly sort and finalize class-scoped parametrized
- tests independently from number of methods on the class.
-
-- refix issue323 in a better way -- parametrization should now never
- cause Runtime Recursion errors because the underlying algorithm
- for re-ordering tests per-scope/per-fixture is not recursive
- anymore (it was tail-call recursive before which could lead
- to problems for more than >966 non-function scoped parameters).
-
-- fix issue290 - there is preliminary support now for parametrizing
- with repeated same values (sometimes useful to to test if calling
- a second time works as with the first time).
-
-- close issue240 - document precisely how pytest module importing
- works, discuss the two common test directory layouts, and how it
- interacts with PEP420-namespace packages.
-
-- fix issue246 fix finalizer order to be LIFO on independent fixtures
- depending on a parametrized higher-than-function scoped fixture.
- (was quite some effort so please bear with the complexity of this sentence :)
- Thanks Ralph Schmitt for the precise failure example.
-
-- fix issue244 by implementing special index for parameters to only use
- indices for paramentrized test ids
-
-- fix issue287 by running all finalizers but saving the exception
- from the first failing finalizer and re-raising it so teardown will
- still have failed. We reraise the first failing exception because
- it might be the cause for other finalizers to fail.
-
-- fix ordering when mock.patch or other standard decorator-wrappings
- are used with test methods. This fixues issue346 and should
- help with random "xdist" collection failures. Thanks to
- Ronny Pfannschmidt and Donald Stufft for helping to isolate it.
-
-- fix issue357 - special case "-k" expressions to allow for
- filtering with simple strings that are not valid python expressions.
- Examples: "-k 1.3" matches all tests parametrized with 1.3.
- "-k None" filters all tests that have "None" in their name
- and conversely "-k 'not None'".
- Previously these examples would raise syntax errors.
-
-- fix issue384 by removing the trial support code
- since the unittest compat enhancements allow
- trial to handle it on its own
-
-- don't hide an ImportError when importing a plugin produces one.
- fixes issue375.
-
-- fix issue275 - allow usefixtures and autouse fixtures
- for running doctest text files.
-
-- fix issue380 by making --resultlog only rely on longrepr instead
- of the "reprcrash" attribute which only exists sometimes.
-
-- address issue122: allow @pytest.fixture(params=iterator) by exploding
- into a list early on.
-
-- fix pexpect-3.0 compatibility for pytest's own tests.
- (fixes issue386)
-
-- allow nested parametrize-value markers, thanks James Lan for the PR.
-
-- fix unicode handling with new monkeypatch.setattr(import_path, value)
- API. Thanks Rob Dennis. Fixes issue371.
-
-- fix unicode handling with junitxml, fixes issue368.
-
-- In assertion rewriting mode on Python 2, fix the detection of coding
- cookies. See issue #330.
-
-- make "--runxfail" turn imperative pytest.xfail calls into no ops
- (it already did neutralize pytest.mark.xfail markers)
-
-- refine pytest / pkg_resources interactions: The AssertionRewritingHook
- PEP302 compliant loader now registers itself with setuptools/pkg_resources
- properly so that the pkg_resources.resource_stream method works properly.
- Fixes issue366. Thanks for the investigations and full PR to Jason R. Coombs.
-
-- pytestconfig fixture is now session-scoped as it is the same object during the
- whole test run. Fixes issue370.
-
-- avoid one surprising case of marker malfunction/confusion::
-
- @pytest.mark.some(lambda arg: ...)
- def test_function():
-
- would not work correctly because pytest assumes @pytest.mark.some
- gets a function to be decorated already. We now at least detect if this
- arg is an lambda and thus the example will work. Thanks Alex Gaynor
- for bringing it up.
-
-- xfail a test on pypy that checks wrong encoding/ascii (pypy does
- not error out). fixes issue385.
-
-- internally make varnames() deal with classes's __init__,
- although it's not needed by pytest itself atm. Also
- fix caching. Fixes issue376.
-
-- fix issue221 - handle importing of namespace-package with no
- __init__.py properly.
-
-- refactor internal FixtureRequest handling to avoid monkeypatching.
- One of the positive user-facing effects is that the "request" object
- can now be used in closures.
-
-- fixed version comparison in pytest.importskip(modname, minverstring)
-
-- fix issue377 by clarifying in the nose-compat docs that pytest
- does not duplicate the unittest-API into the "plain" namespace.
-
-- fix verbose reporting for @mock'd test functions
-
-2.4.2
-=====
-
-- on Windows require colorama and a newer py lib so that py.io.TerminalWriter()
- now uses colorama instead of its own ctypes hacks. (fixes issue365)
- thanks Paul Moore for bringing it up.
-
-- fix "-k" matching of tests where "repr" and "attr" and other names would
- cause wrong matches because of an internal implementation quirk
- (don't ask) which is now properly implemented. fixes issue345.
-
-- avoid tmpdir fixture to create too long filenames especially
- when parametrization is used (issue354)
-
-- fix pytest-pep8 and pytest-flakes / pytest interactions
- (collection names in mark plugin was assuming an item always
- has a function which is not true for those plugins etc.)
- Thanks Andi Zeidler.
-
-- introduce node.get_marker/node.add_marker API for plugins
- like pytest-pep8 and pytest-flakes to avoid the messy
- details of the node.keywords pseudo-dicts. Adapted
- docs.
-
-- remove attempt to "dup" stdout at startup as it's icky.
- the normal capturing should catch enough possibilities
- of tests messing up standard FDs.
-
-- add pluginmanager.do_configure(config) as a link to
- config.do_configure() for plugin-compatibility
-
-2.4.1
-=====
-
-- When using parser.addoption() unicode arguments to the
- "type" keyword should also be converted to the respective types.
- thanks Floris Bruynooghe, @dnozay. (fixes issue360 and issue362)
-
-- fix dotted filename completion when using argcomplete
- thanks Anthon van der Neuth. (fixes issue361)
-
-- fix regression when a 1-tuple ("arg",) is used for specifying
- parametrization (the values of the parametrization were passed
- nested in a tuple). Thanks Donald Stufft.
-
-- merge doc typo fixes, thanks Andy Dirnberger
-
-2.4
-===
-
-known incompatibilities:
-
-- if calling --genscript from python2.7 or above, you only get a
- standalone script which works on python2.7 or above. Use Python2.6
- to also get a python2.5 compatible version.
-
-- all xunit-style teardown methods (nose-style, pytest-style,
- unittest-style) will not be called if the corresponding setup method failed,
- see issue322 below.
-
-- the pytest_plugin_unregister hook wasn't ever properly called
- and there is no known implementation of the hook - so it got removed.
-
-- pytest.fixture-decorated functions cannot be generators (i.e. use
- yield) anymore. This change might be reversed in 2.4.1 if it causes
- unforeseen real-life issues. However, you can always write and return
- an inner function/generator and change the fixture consumer to iterate
- over the returned generator. This change was done in lieu of the new
- ``pytest.yield_fixture`` decorator, see below.
-
-new features:
-
-- experimentally introduce a new ``pytest.yield_fixture`` decorator
- which accepts exactly the same parameters as pytest.fixture but
- mandates a ``yield`` statement instead of a ``return statement`` from
- fixture functions. This allows direct integration with "with-style"
- context managers in fixture functions and generally avoids registering
- of finalization callbacks in favour of treating the "after-yield" as
- teardown code. Thanks Andreas Pelme, Vladimir Keleshev, Floris
- Bruynooghe, Ronny Pfannschmidt and many others for discussions.
-
-- allow boolean expression directly with skipif/xfail
- if a "reason" is also specified. Rework skipping documentation
- to recommend "condition as booleans" because it prevents surprises
- when importing markers between modules. Specifying conditions
- as strings will remain fully supported.
-
-- reporting: color the last line red or green depending if
- failures/errors occurred or everything passed. thanks Christian
- Theunert.
-
-- make "import pdb ; pdb.set_trace()" work natively wrt capturing (no
- "-s" needed anymore), making ``pytest.set_trace()`` a mere shortcut.
-
-- fix issue181: --pdb now also works on collect errors (and
- on internal errors) . This was implemented by a slight internal
- refactoring and the introduction of a new hook
- ``pytest_exception_interact`` hook (see next item).
-
-- fix issue341: introduce new experimental hook for IDEs/terminals to
- intercept debugging: ``pytest_exception_interact(node, call, report)``.
-
-- new monkeypatch.setattr() variant to provide a shorter
- invocation for patching out classes/functions from modules:
-
- monkeypatch.setattr("requests.get", myfunc)
-
- will replace the "get" function of the "requests" module with ``myfunc``.
-
-- fix issue322: tearDownClass is not run if setUpClass failed. Thanks
- Mathieu Agopian for the initial fix. Also make all of pytest/nose
- finalizer mimick the same generic behaviour: if a setupX exists and
- fails, don't run teardownX. This internally introduces a new method
- "node.addfinalizer()" helper which can only be called during the setup
- phase of a node.
-
-- simplify pytest.mark.parametrize() signature: allow to pass a
- CSV-separated string to specify argnames. For example:
- ``pytest.mark.parametrize("input,expected", [(1,2), (2,3)])``
- works as well as the previous:
- ``pytest.mark.parametrize(("input", "expected"), ...)``.
-
-- add support for setUpModule/tearDownModule detection, thanks Brian Okken.
-
-- integrate tab-completion on options through use of "argcomplete".
- Thanks Anthon van der Neut for the PR.
-
-- change option names to be hyphen-separated long options but keep the
- old spelling backward compatible. py.test -h will only show the
- hyphenated version, for example "--collect-only" but "--collectonly"
- will remain valid as well (for backward-compat reasons). Many thanks to
- Anthon van der Neut for the implementation and to Hynek Schlawack for
- pushing us.
-
-- fix issue 308 - allow to mark/xfail/skip individual parameter sets
- when parametrizing. Thanks Brianna Laugher.
-
-- call new experimental pytest_load_initial_conftests hook to allow
- 3rd party plugins to do something before a conftest is loaded.
-
-Bug fixes:
-
-- fix issue358 - capturing options are now parsed more properly
- by using a new parser.parse_known_args method.
-
-- pytest now uses argparse instead of optparse (thanks Anthon) which
- means that "argparse" is added as a dependency if installing into python2.6
- environments or below.
-
-- fix issue333: fix a case of bad unittest/pytest hook interaction.
-
-- PR27: correctly handle nose.SkipTest during collection. Thanks
- Antonio Cuni, Ronny Pfannschmidt.
-
-- fix issue355: junitxml puts name="pytest" attribute to testsuite tag.
-
-- fix issue336: autouse fixture in plugins should work again.
-
-- fix issue279: improve object comparisons on assertion failure
- for standard datatypes and recognise collections.abc. Thanks to
- Brianna Laugher and Mathieu Agopian.
-
-- fix issue317: assertion rewriter support for the is_package method
-
-- fix issue335: document py.code.ExceptionInfo() object returned
- from pytest.raises(), thanks Mathieu Agopian.
-
-- remove implicit distribute_setup support from setup.py.
-
-- fix issue305: ignore any problems when writing pyc files.
-
-- SO-17664702: call fixture finalizers even if the fixture function
- partially failed (finalizers would not always be called before)
-
-- fix issue320 - fix class scope for fixtures when mixed with
- module-level functions. Thanks Anatloy Bubenkoff.
-
-- you can specify "-q" or "-qq" to get different levels of "quieter"
- reporting (thanks Katarzyna Jachim)
-
-- fix issue300 - Fix order of conftest loading when starting py.test
- in a subdirectory.
-
-- fix issue323 - sorting of many module-scoped arg parametrizations
-
-- make sessionfinish hooks execute with the same cwd-context as at
- session start (helps fix plugin behaviour which write output files
- with relative path such as pytest-cov)
-
-- fix issue316 - properly reference collection hooks in docs
-
-- fix issue 306 - cleanup of -k/-m options to only match markers/test
- names/keywords respectively. Thanks Wouter van Ackooy.
-
-- improved doctest counting for doctests in python modules --
- files without any doctest items will not show up anymore
- and doctest examples are counted as separate test items.
- thanks Danilo Bellini.
-
-- fix issue245 by depending on the released py-1.4.14
- which fixes py.io.dupfile to work with files with no
- mode. Thanks Jason R. Coombs.
-
-- fix junitxml generation when test output contains control characters,
- addressing issue267, thanks Jaap Broekhuizen
-
-- fix issue338: honor --tb style for setup/teardown errors as well. Thanks Maho.
-
-- fix issue307 - use yaml.safe_load in example, thanks Mark Eichin.
-
-- better parametrize error messages, thanks Brianna Laugher
-
-- pytest_terminal_summary(terminalreporter) hooks can now use
- ".section(title)" and ".line(msg)" methods to print extra
- information at the end of a test run.
-
-2.3.5
-=====
-
-- fix issue169: respect --tb=style with setup/teardown errors as well.
-
-- never consider a fixture function for test function collection
-
-- allow re-running of test items / helps to fix pytest-reruntests plugin
- and also help to keep less fixture/resource references alive
-
-- put captured stdout/stderr into junitxml output even for passing tests
- (thanks Adam Goucher)
-
-- Issue 265 - integrate nose setup/teardown with setupstate
- so it doesnt try to teardown if it did not setup
-
-- issue 271 - dont write junitxml on slave nodes
-
-- Issue 274 - dont try to show full doctest example
- when doctest does not know the example location
-
-- issue 280 - disable assertion rewriting on buggy CPython 2.6.0
-
-- inject "getfixture()" helper to retrieve fixtures from doctests,
- thanks Andreas Zeidler
-
-- issue 259 - when assertion rewriting, be consistent with the default
- source encoding of ASCII on Python 2
-
-- issue 251 - report a skip instead of ignoring classes with init
-
-- issue250 unicode/str mixes in parametrization names and values now works
-
-- issue257, assertion-triggered compilation of source ending in a
- comment line doesn't blow up in python2.5 (fixed through py>=1.4.13.dev6)
-
-- fix --genscript option to generate standalone scripts that also
- work with python3.3 (importer ordering)
-
-- issue171 - in assertion rewriting, show the repr of some
- global variables
-
-- fix option help for "-k"
-
-- move long description of distribution into README.rst
-
-- improve docstring for metafunc.parametrize()
-
-- fix bug where using capsys with pytest.set_trace() in a test
- function would break when looking at capsys.readouterr()
-
-- allow to specify prefixes starting with "_" when
- customizing python_functions test discovery. (thanks Graham Horler)
-
-- improve PYTEST_DEBUG tracing output by puting
- extra data on a new lines with additional indent
-
-- ensure OutcomeExceptions like skip/fail have initialized exception attributes
-
-- issue 260 - don't use nose special setup on plain unittest cases
-
-- fix issue134 - print the collect errors that prevent running specified test items
-
-- fix issue266 - accept unicode in MarkEvaluator expressions
-
-2.3.4
-=====
-
-- yielded test functions will now have autouse-fixtures active but
- cannot accept fixtures as funcargs - it's anyway recommended to
- rather use the post-2.0 parametrize features instead of yield, see:
- http://pytest.org/latest/example/parametrize.html
-- fix autouse-issue where autouse-fixtures would not be discovered
- if defined in a a/conftest.py file and tests in a/tests/test_some.py
-- fix issue226 - LIFO ordering for fixture teardowns
-- fix issue224 - invocations with >256 char arguments now work
-- fix issue91 - add/discuss package/directory level setups in example
-- allow to dynamically define markers via
- item.keywords[...]=assignment integrating with "-m" option
-- make "-k" accept an expressions the same as with "-m" so that one
- can write: -k "name1 or name2" etc. This is a slight incompatibility
- if you used special syntax like "TestClass.test_method" which you now
- need to write as -k "TestClass and test_method" to match a certain
- method in a certain test class.
-
-2.3.3
-=====
-
-- fix issue214 - parse modules that contain special objects like e. g.
- flask's request object which blows up on getattr access if no request
- is active. thanks Thomas Waldmann.
-
-- fix issue213 - allow to parametrize with values like numpy arrays that
- do not support an __eq__ operator
-
-- fix issue215 - split test_python.org into multiple files
-
-- fix issue148 - @unittest.skip on classes is now recognized and avoids
- calling setUpClass/tearDownClass, thanks Pavel Repin
-
-- fix issue209 - reintroduce python2.4 support by depending on newer
- pylib which re-introduced statement-finding for pre-AST interpreters
-
-- nose support: only call setup if its a callable, thanks Andrew
- Taumoefolau
-
-- fix issue219 - add py2.4-3.3 classifiers to TROVE list
-
-- in tracebacks *,** arg values are now shown next to normal arguments
- (thanks Manuel Jacob)
-
-- fix issue217 - support mock.patch with pytest's fixtures - note that
- you need either mock-1.0.1 or the python3.3 builtin unittest.mock.
-
-- fix issue127 - improve documentation for pytest_addoption() and
- add a ``config.getoption(name)`` helper function for consistency.
-
-2.3.2
-=====
-
-- fix issue208 and fix issue29 use new py version to avoid long pauses
- when printing tracebacks in long modules
-
-- fix issue205 - conftests in subdirs customizing
- pytest_pycollect_makemodule and pytest_pycollect_makeitem
- now work properly
-
-- fix teardown-ordering for parametrized setups
-
-- fix issue127 - better documentation for pytest_addoption
- and related objects.
-
-- fix unittest behaviour: TestCase.runtest only called if there are
- test methods defined
-
-- improve trial support: don't collect its empty
- unittest.TestCase.runTest() method
-
-- "python setup.py test" now works with pytest itself
-
-- fix/improve internal/packaging related bits:
-
- - exception message check of test_nose.py now passes on python33 as well
-
- - issue206 - fix test_assertrewrite.py to work when a global
- PYTHONDONTWRITEBYTECODE=1 is present
-
- - add tox.ini to pytest distribution so that ignore-dirs and others config
- bits are properly distributed for maintainers who run pytest-own tests
-
-2.3.1
-=====
-
-- fix issue202 - fix regression: using "self" from fixture functions now
- works as expected (it's the same "self" instance that a test method
- which uses the fixture sees)
-
-- skip pexpect using tests (test_pdb.py mostly) on freebsd* systems
- due to pexpect not supporting it properly (hanging)
-
-- link to web pages from --markers output which provides help for
- pytest.mark.* usage.
-
-2.3.0
-=====
-
-- fix issue202 - better automatic names for parametrized test functions
-- fix issue139 - introduce @pytest.fixture which allows direct scoping
- and parametrization of funcarg factories.
-- fix issue198 - conftest fixtures were not found on windows32 in some
- circumstances with nested directory structures due to path manipulation issues
-- fix issue193 skip test functions with were parametrized with empty
- parameter sets
-- fix python3.3 compat, mostly reporting bits that previously depended
- on dict ordering
-- introduce re-ordering of tests by resource and parametrization setup
- which takes precedence to the usual file-ordering
-- fix issue185 monkeypatching time.time does not cause pytest to fail
-- fix issue172 duplicate call of pytest.fixture decoratored setup_module
- functions
-- fix junitxml=path construction so that if tests change the
- current working directory and the path is a relative path
- it is constructed correctly from the original current working dir.
-- fix "python setup.py test" example to cause a proper "errno" return
-- fix issue165 - fix broken doc links and mention stackoverflow for FAQ
-- catch unicode-issues when writing failure representations
- to terminal to prevent the whole session from crashing
-- fix xfail/skip confusion: a skip-mark or an imperative pytest.skip
- will now take precedence before xfail-markers because we
- can't determine xfail/xpass status in case of a skip. see also:
- http://stackoverflow.com/questions/11105828/in-py-test-when-i-explicitly-skip-a-test-that-is-marked-as-xfail-how-can-i-get
-
-- always report installed 3rd party plugins in the header of a test run
-
-- fix issue160: a failing setup of an xfail-marked tests should
- be reported as xfail (not xpass)
-
-- fix issue128: show captured output when capsys/capfd are used
-
-- fix issue179: propperly show the dependency chain of factories
-
-- pluginmanager.register(...) now raises ValueError if the
- plugin has been already registered or the name is taken
-
-- fix issue159: improve http://pytest.org/latest/faq.html
- especially with respect to the "magic" history, also mention
- pytest-django, trial and unittest integration.
-
-- make request.keywords and node.keywords writable. All descendant
- collection nodes will see keyword values. Keywords are dictionaries
- containing markers and other info.
-
-- fix issue 178: xml binary escapes are now wrapped in py.xml.raw
-
-- fix issue 176: correctly catch the builtin AssertionError
- even when we replaced AssertionError with a subclass on the
- python level
-
-- factory discovery no longer fails with magic global callables
- that provide no sane __code__ object (mock.call for example)
-
-- fix issue 182: testdir.inprocess_run now considers passed plugins
-
-- fix issue 188: ensure sys.exc_info is clear on python2
- before calling into a test
-
-- fix issue 191: add unittest TestCase runTest method support
-- fix issue 156: monkeypatch correctly handles class level descriptors
-
-- reporting refinements:
-
- - pytest_report_header now receives a "startdir" so that
- you can use startdir.bestrelpath(yourpath) to show
- nice relative path
-
- - allow plugins to implement both pytest_report_header and
- pytest_sessionstart (sessionstart is invoked first).
-
- - don't show deselected reason line if there is none
-
- - py.test -vv will show all of assert comparisations instead of truncating
-
-2.2.4
-=====
-
-- fix error message for rewritten assertions involving the % operator
-- fix issue 126: correctly match all invalid xml characters for junitxml
- binary escape
-- fix issue with unittest: now @unittest.expectedFailure markers should
- be processed correctly (you can also use @pytest.mark markers)
-- document integration with the extended distribute/setuptools test commands
-- fix issue 140: propperly get the real functions
- of bound classmethods for setup/teardown_class
-- fix issue #141: switch from the deceased paste.pocoo.org to bpaste.net
-- fix issue #143: call unconfigure/sessionfinish always when
- configure/sessionstart where called
-- fix issue #144: better mangle test ids to junitxml classnames
-- upgrade distribute_setup.py to 0.6.27
-
-2.2.3
-=====
-
-- fix uploaded package to only include neccesary files
-
-2.2.2
-=====
-
-- fix issue101: wrong args to unittest.TestCase test function now
- produce better output
-- fix issue102: report more useful errors and hints for when a
- test directory was renamed and some pyc/__pycache__ remain
-- fix issue106: allow parametrize to be applied multiple times
- e.g. from module, class and at function level.
-- fix issue107: actually perform session scope finalization
-- don't check in parametrize if indirect parameters are funcarg names
-- add chdir method to monkeypatch funcarg
-- fix crash resulting from calling monkeypatch undo a second time
-- fix issue115: make --collectonly robust against early failure
- (missing files/directories)
-- "-qq --collectonly" now shows only files and the number of tests in them
-- "-q --collectonly" now shows test ids
-- allow adding of attributes to test reports such that it also works
- with distributed testing (no upgrade of pytest-xdist needed)
-
-2.2.1
-=====
-
-- fix issue99 (in pytest and py) internallerrors with resultlog now
- produce better output - fixed by normalizing pytest_internalerror
- input arguments.
-- fix issue97 / traceback issues (in pytest and py) improve traceback output
- in conjunction with jinja2 and cython which hack tracebacks
-- fix issue93 (in pytest and pytest-xdist) avoid "delayed teardowns":
- the final test in a test node will now run its teardown directly
- instead of waiting for the end of the session. Thanks Dave Hunt for
- the good reporting and feedback. The pytest_runtest_protocol as well
- as the pytest_runtest_teardown hooks now have "nextitem" available
- which will be None indicating the end of the test run.
-- fix collection crash due to unknown-source collected items, thanks
- to Ralf Schmitt (fixed by depending on a more recent pylib)
-
-2.2.0
-=====
-
-- fix issue90: introduce eager tearing down of test items so that
- teardown function are called earlier.
-- add an all-powerful metafunc.parametrize function which allows to
- parametrize test function arguments in multiple steps and therefore
- from indepdenent plugins and palces.
-- add a @pytest.mark.parametrize helper which allows to easily
- call a test function with different argument values
-- Add examples to the "parametrize" example page, including a quick port
- of Test scenarios and the new parametrize function and decorator.
-- introduce registration for "pytest.mark.*" helpers via ini-files
- or through plugin hooks. Also introduce a "--strict" option which
- will treat unregistered markers as errors
- allowing to avoid typos and maintain a well described set of markers
- for your test suite. See exaples at http://pytest.org/latest/mark.html
- and its links.
-- issue50: introduce "-m marker" option to select tests based on markers
- (this is a stricter and more predictable version of '-k' in that "-m"
- only matches complete markers and has more obvious rules for and/or
- semantics.
-- new feature to help optimizing the speed of your tests:
- --durations=N option for displaying N slowest test calls
- and setup/teardown methods.
-- fix issue87: --pastebin now works with python3
-- fix issue89: --pdb with unexpected exceptions in doctest work more sensibly
-- fix and cleanup pytest's own test suite to not leak FDs
-- fix issue83: link to generated funcarg list
-- fix issue74: pyarg module names are now checked against imp.find_module false positives
-- fix compatibility with twisted/trial-11.1.0 use cases
-- simplify Node.listchain
-- simplify junitxml output code by relying on py.xml
-- add support for skip properties on unittest classes and functions
-
-2.1.3
-=====
-
-- fix issue79: assertion rewriting failed on some comparisons in boolops
-- correctly handle zero length arguments (a la pytest '')
-- fix issue67 / junitxml now contains correct test durations, thanks ronny
-- fix issue75 / skipping test failure on jython
-- fix issue77 / Allow assertrepr_compare hook to apply to a subset of tests
-
-2.1.2
-=====
-
-- fix assertion rewriting on files with windows newlines on some Python versions
-- refine test discovery by package/module name (--pyargs), thanks Florian Mayer
-- fix issue69 / assertion rewriting fixed on some boolean operations
-- fix issue68 / packages now work with assertion rewriting
-- fix issue66: use different assertion rewriting caches when the -O option is passed
-- don't try assertion rewriting on Jython, use reinterp
-
-2.1.1
-=====
-
-- fix issue64 / pytest.set_trace now works within pytest_generate_tests hooks
-- fix issue60 / fix error conditions involving the creation of __pycache__
-- fix issue63 / assertion rewriting on inserts involving strings containing '%'
-- fix assertion rewriting on calls with a ** arg
-- don't cache rewritten modules if bytecode generation is disabled
-- fix assertion rewriting in read-only directories
-- fix issue59: provide system-out/err tags for junitxml output
-- fix issue61: assertion rewriting on boolean operations with 3 or more operands
-- you can now build a man page with "cd doc ; make man"
-
-2.1.0
-=====
-
-- fix issue53 call nosestyle setup functions with correct ordering
-- fix issue58 and issue59: new assertion code fixes
-- merge Benjamin's assertionrewrite branch: now assertions
- for test modules on python 2.6 and above are done by rewriting
- the AST and saving the pyc file before the test module is imported.
- see doc/assert.txt for more info.
-- fix issue43: improve doctests with better traceback reporting on
- unexpected exceptions
-- fix issue47: timing output in junitxml for test cases is now correct
-- fix issue48: typo in MarkInfo repr leading to exception
-- fix issue49: avoid confusing error when initizaliation partially fails
-- fix issue44: env/username expansion for junitxml file path
-- show releaselevel information in test runs for pypy
-- reworked doc pages for better navigation and PDF generation
-- report KeyboardInterrupt even if interrupted during session startup
-- fix issue 35 - provide PDF doc version and download link from index page
-
-2.0.3
-=====
-
-- fix issue38: nicer tracebacks on calls to hooks, particularly early
- configure/sessionstart ones
-
-- fix missing skip reason/meta information in junitxml files, reported
- via http://lists.idyll.org/pipermail/testing-in-python/2011-March/003928.html
-
-- fix issue34: avoid collection failure with "test" prefixed classes
- deriving from object.
-
-- don't require zlib (and other libs) for genscript plugin without
- --genscript actually being used.
-
-- speed up skips (by not doing a full traceback represenation
- internally)
-
-- fix issue37: avoid invalid characters in junitxml's output
-
-2.0.2
-=====
-
-- tackle issue32 - speed up test runs of very quick test functions
- by reducing the relative overhead
-
-- fix issue30 - extended xfail/skipif handling and improved reporting.
- If you have a syntax error in your skip/xfail
- expressions you now get nice error reports.
-
- Also you can now access module globals from xfail/skipif
- expressions so that this for example works now::
-
- import pytest
- import mymodule
- @pytest.mark.skipif("mymodule.__version__[0] == "1")
- def test_function():
- pass
-
- This will not run the test function if the module's version string
- does not start with a "1". Note that specifying a string instead
- of a boolean expressions allows py.test to report meaningful information
- when summarizing a test run as to what conditions lead to skipping
- (or xfail-ing) tests.
-
-- fix issue28 - setup_method and pytest_generate_tests work together
- The setup_method fixture method now gets called also for
- test function invocations generated from the pytest_generate_tests
- hook.
-
-- fix issue27 - collectonly and keyword-selection (-k) now work together
- Also, if you do "py.test --collectonly -q" you now get a flat list
- of test ids that you can use to paste to the py.test commandline
- in order to execute a particular test.
-
-- fix issue25 avoid reported problems with --pdb and python3.2/encodings output
-
-- fix issue23 - tmpdir argument now works on Python3.2 and WindowsXP
- Starting with Python3.2 os.symlink may be supported. By requiring
- a newer py lib version the py.path.local() implementation acknowledges
- this.
-
-- fixed typos in the docs (thanks Victor Garcia, Brianna Laugher) and particular
- thanks to Laura Creighton who also revieved parts of the documentation.
-
-- fix slighly wrong output of verbose progress reporting for classes
- (thanks Amaury)
-
-- more precise (avoiding of) deprecation warnings for node.Class|Function accesses
-
-- avoid std unittest assertion helper code in tracebacks (thanks Ronny)
-
-2.0.1
-=====
-
-- refine and unify initial capturing so that it works nicely
- even if the logging module is used on an early-loaded conftest.py
- file or plugin.
-- allow to omit "()" in test ids to allow for uniform test ids
- as produced by Alfredo's nice pytest.vim plugin.
-- fix issue12 - show plugin versions with "--version" and
- "--traceconfig" and also document how to add extra information
- to reporting test header
-- fix issue17 (import-* reporting issue on python3) by
- requiring py>1.4.0 (1.4.1 is going to include it)
-- fix issue10 (numpy arrays truth checking) by refining
- assertion interpretation in py lib
-- fix issue15: make nose compatibility tests compatible
- with python3 (now that nose-1.0 supports python3)
-- remove somewhat surprising "same-conftest" detection because
- it ignores conftest.py when they appear in several subdirs.
-- improve assertions ("not in"), thanks Floris Bruynooghe
-- improve behaviour/warnings when running on top of "python -OO"
- (assertions and docstrings are turned off, leading to potential
- false positives)
-- introduce a pytest_cmdline_processargs(args) hook
- to allow dynamic computation of command line arguments.
- This fixes a regression because py.test prior to 2.0
- allowed to set command line options from conftest.py
- files which so far pytest-2.0 only allowed from ini-files now.
-- fix issue7: assert failures in doctest modules.
- unexpected failures in doctests will not generally
- show nicer, i.e. within the doctest failing context.
-- fix issue9: setup/teardown functions for an xfail-marked
- test will report as xfail if they fail but report as normally
- passing (not xpassing) if they succeed. This only is true
- for "direct" setup/teardown invocations because teardown_class/
- teardown_module cannot closely relate to a single test.
-- fix issue14: no logging errors at process exit
-- refinements to "collecting" output on non-ttys
-- refine internal plugin registration and --traceconfig output
-- introduce a mechanism to prevent/unregister plugins from the
- command line, see http://pytest.org/plugins.html#cmdunregister
-- activate resultlog plugin by default
-- fix regression wrt yielded tests which due to the
- collection-before-running semantics were not
- setup as with pytest 1.3.4. Note, however, that
- the recommended and much cleaner way to do test
- parametraization remains the "pytest_generate_tests"
- mechanism, see the docs.
-
-2.0.0
-=====
-
-- pytest-2.0 is now its own package and depends on pylib-2.0
-- new ability: python -m pytest / python -m pytest.main ability
-- new python invcation: pytest.main(args, plugins) to load
- some custom plugins early.
-- try harder to run unittest test suites in a more compatible manner
- by deferring setup/teardown semantics to the unittest package.
- also work harder to run twisted/trial and Django tests which
- should now basically work by default.
-- introduce a new way to set config options via ini-style files,
- by default setup.cfg and tox.ini files are searched. The old
- ways (certain environment variables, dynamic conftest.py reading
- is removed).
-- add a new "-q" option which decreases verbosity and prints a more
- nose/unittest-style "dot" output.
-- fix issue135 - marks now work with unittest test cases as well
-- fix issue126 - introduce py.test.set_trace() to trace execution via
- PDB during the running of tests even if capturing is ongoing.
-- fix issue123 - new "python -m py.test" invocation for py.test
- (requires Python 2.5 or above)
-- fix issue124 - make reporting more resilient against tests opening
- files on filedescriptor 1 (stdout).
-- fix issue109 - sibling conftest.py files will not be loaded.
- (and Directory collectors cannot be customized anymore from a Directory's
- conftest.py - this needs to happen at least one level up).
-- introduce (customizable) assertion failure representations and enhance
- output on assertion failures for comparisons and other cases (Floris Bruynooghe)
-- nose-plugin: pass through type-signature failures in setup/teardown
- functions instead of not calling them (Ed Singleton)
-- remove py.test.collect.Directory (follows from a major refactoring
- and simplification of the collection process)
-- majorly reduce py.test core code, shift function/python testing to own plugin
-- fix issue88 (finding custom test nodes from command line arg)
-- refine 'tmpdir' creation, will now create basenames better associated
- with test names (thanks Ronny)
-- "xpass" (unexpected pass) tests don't cause exitcode!=0
-- fix issue131 / issue60 - importing doctests in __init__ files used as namespace packages
-- fix issue93 stdout/stderr is captured while importing conftest.py
-- fix bug: unittest collected functions now also can have "pytestmark"
- applied at class/module level
-- add ability to use "class" level for cached_setup helper
-- fix strangeness: mark.* objects are now immutable, create new instances
-
-1.3.4
-=====
-
-- fix issue111: improve install documentation for windows
-- fix issue119: fix custom collectability of __init__.py as a module
-- fix issue116: --doctestmodules work with __init__.py files as well
-- fix issue115: unify internal exception passthrough/catching/GeneratorExit
-- fix issue118: new --tb=native for presenting cpython-standard exceptions
-
-1.3.3
-=====
-
-- fix issue113: assertion representation problem with triple-quoted strings
- (and possibly other cases)
-- make conftest loading detect that a conftest file with the same
- content was already loaded, avoids surprises in nested directory structures
- which can be produced e.g. by Hudson. It probably removes the need to use
- --confcutdir in most cases.
-- fix terminal coloring for win32
- (thanks Michael Foord for reporting)
-- fix weirdness: make terminal width detection work on stdout instead of stdin
- (thanks Armin Ronacher for reporting)
-- remove trailing whitespace in all py/text distribution files
-
-1.3.2
-=====
-
-**New features**
-
-- fix issue103: introduce py.test.raises as context manager, examples::
-
- with py.test.raises(ZeroDivisionError):
- x = 0
- 1 / x
-
- with py.test.raises(RuntimeError) as excinfo:
- call_something()
-
- # you may do extra checks on excinfo.value|type|traceback here
-
- (thanks Ronny Pfannschmidt)
-
-- Funcarg factories can now dynamically apply a marker to a
- test invocation. This is for example useful if a factory
- provides parameters to a test which are expected-to-fail::
-
- def pytest_funcarg__arg(request):
- request.applymarker(py.test.mark.xfail(reason="flaky config"))
- ...
-
- def test_function(arg):
- ...
-
-- improved error reporting on collection and import errors. This makes
- use of a more general mechanism, namely that for custom test item/collect
- nodes ``node.repr_failure(excinfo)`` is now uniformly called so that you can
- override it to return a string error representation of your choice
- which is going to be reported as a (red) string.
-
-- introduce '--junitprefix=STR' option to prepend a prefix
- to all reports in the junitxml file.
-
-**Bug fixes**
-
-- make tests and the ``pytest_recwarn`` plugin in particular fully compatible
- to Python2.7 (if you use the ``recwarn`` funcarg warnings will be enabled so that
- you can properly check for their existence in a cross-python manner).
-- refine --pdb: ignore xfailed tests, unify its TB-reporting and
- don't display failures again at the end.
-- fix assertion interpretation with the ** operator (thanks Benjamin Peterson)
-- fix issue105 assignment on the same line as a failing assertion (thanks Benjamin Peterson)
-- fix issue104 proper escaping for test names in junitxml plugin (thanks anonymous)
-- fix issue57 -f|--looponfail to work with xpassing tests (thanks Ronny)
-- fix issue92 collectonly reporter and --pastebin (thanks Benjamin Peterson)
-- fix py.code.compile(source) to generate unique filenames
-- fix assertion re-interp problems on PyPy, by defering code
- compilation to the (overridable) Frame.eval class. (thanks Amaury Forgeot)
-- fix py.path.local.pyimport() to work with directories
-- streamline py.path.local.mkdtemp implementation and usage
-- don't print empty lines when showing junitxml-filename
-- add optional boolean ignore_errors parameter to py.path.local.remove
-- fix terminal writing on win32/python2.4
-- py.process.cmdexec() now tries harder to return properly encoded unicode objects
- on all python versions
-- install plain py.test/py.which scripts also for Jython, this helps to
- get canonical script paths in virtualenv situations
-- make path.bestrelpath(path) return ".", note that when calling
- X.bestrelpath the assumption is that X is a directory.
-- make initial conftest discovery ignore "--" prefixed arguments
-- fix resultlog plugin when used in an multicpu/multihost xdist situation
- (thanks Jakub Gustak)
-- perform distributed testing related reporting in the xdist-plugin
- rather than having dist-related code in the generic py.test
- distribution
-- fix homedir detection on Windows
-- ship distribute_setup.py version 0.6.13
-
-1.3.1
-=====
-
-**New features**
-
-- issue91: introduce new py.test.xfail(reason) helper
- to imperatively mark a test as expected to fail. Can
- be used from within setup and test functions. This is
- useful especially for parametrized tests when certain
- configurations are expected-to-fail. In this case the
- declarative approach with the @py.test.mark.xfail cannot
- be used as it would mark all configurations as xfail.
-
-- issue102: introduce new --maxfail=NUM option to stop
- test runs after NUM failures. This is a generalization
- of the '-x' or '--exitfirst' option which is now equivalent
- to '--maxfail=1'. Both '-x' and '--maxfail' will
- now also print a line near the end indicating the Interruption.
-
-- issue89: allow py.test.mark decorators to be used on classes
- (class decorators were introduced with python2.6) and
- also allow to have multiple markers applied at class/module level
- by specifying a list.
-
-- improve and refine letter reporting in the progress bar:
- . pass
- f failed test
- s skipped tests (reminder: use for dependency/platform mismatch only)
- x xfailed test (test that was expected to fail)
- X xpassed test (test that was expected to fail but passed)
-
- You can use any combination of 'fsxX' with the '-r' extended
- reporting option. The xfail/xpass results will show up as
- skipped tests in the junitxml output - which also fixes
- issue99.
-
-- make py.test.cmdline.main() return the exitstatus instead of raising
- SystemExit and also allow it to be called multiple times. This of
- course requires that your application and tests are properly teared
- down and don't have global state.
-
-**Bug Fixes**
-
-- improved traceback presentation:
- - improved and unified reporting for "--tb=short" option
- - Errors during test module imports are much shorter, (using --tb=short style)
- - raises shows shorter more relevant tracebacks
- - --fulltrace now more systematically makes traces longer / inhibits cutting
-
-- improve support for raises and other dynamically compiled code by
- manipulating python's linecache.cache instead of the previous
- rather hacky way of creating custom code objects. This makes
- it seemlessly work on Jython and PyPy where it previously didn't.
-
-- fix issue96: make capturing more resilient against Control-C
- interruptions (involved somewhat substantial refactoring
- to the underlying capturing functionality to avoid race
- conditions).
-
-- fix chaining of conditional skipif/xfail decorators - so it works now
- as expected to use multiple @py.test.mark.skipif(condition) decorators,
- including specific reporting which of the conditions lead to skipping.
-
-- fix issue95: late-import zlib so that it's not required
- for general py.test startup.
-
-- fix issue94: make reporting more robust against bogus source code
- (and internally be more careful when presenting unexpected byte sequences)
-
-
-1.3.0
-=====
-
-- deprecate --report option in favour of a new shorter and easier to
- remember -r option: it takes a string argument consisting of any
- combination of 'xfsX' characters. They relate to the single chars
- you see during the dotted progress printing and will print an extra line
- per test at the end of the test run. This extra line indicates the exact
- position or test ID that you directly paste to the py.test cmdline in order
- to re-run a particular test.
-
-- allow external plugins to register new hooks via the new
- pytest_addhooks(pluginmanager) hook. The new release of
- the pytest-xdist plugin for distributed and looponfailing
- testing requires this feature.
-
-- add a new pytest_ignore_collect(path, config) hook to allow projects and
- plugins to define exclusion behaviour for their directory structure -
- for example you may define in a conftest.py this method::
-
- def pytest_ignore_collect(path):
- return path.check(link=1)
-
- to prevent even a collection try of any tests in symlinked dirs.
-
-- new pytest_pycollect_makemodule(path, parent) hook for
- allowing customization of the Module collection object for a
- matching test module.
-
-- extend and refine xfail mechanism:
- ``@py.test.mark.xfail(run=False)`` do not run the decorated test
- ``@py.test.mark.xfail(reason="...")`` prints the reason string in xfail summaries
- specifiying ``--runxfail`` on command line virtually ignores xfail markers
-
-- expose (previously internal) commonly useful methods:
- py.io.get_terminal_with() -> return terminal width
- py.io.ansi_print(...) -> print colored/bold text on linux/win32
- py.io.saferepr(obj) -> return limited representation string
-
-- expose test outcome related exceptions as py.test.skip.Exception,
- py.test.raises.Exception etc., useful mostly for plugins
- doing special outcome interpretation/tweaking
-
-- (issue85) fix junitxml plugin to handle tests with non-ascii output
-
-- fix/refine python3 compatibility (thanks Benjamin Peterson)
-
-- fixes for making the jython/win32 combination work, note however:
- jython2.5.1/win32 does not provide a command line launcher, see
- http://bugs.jython.org/issue1491 . See pylib install documentation
- for how to work around.
-
-- fixes for handling of unicode exception values and unprintable objects
-
-- (issue87) fix unboundlocal error in assertionold code
-
-- (issue86) improve documentation for looponfailing
-
-- refine IO capturing: stdin-redirect pseudo-file now has a NOP close() method
-
-- ship distribute_setup.py version 0.6.10
-
-- added links to the new capturelog and coverage plugins
-
-
-1.2.0
-=====
-
-- refined usage and options for "py.cleanup"::
-
- py.cleanup # remove "*.pyc" and "*$py.class" (jython) files
- py.cleanup -e .swp -e .cache # also remove files with these extensions
- py.cleanup -s # remove "build" and "dist" directory next to setup.py files
- py.cleanup -d # also remove empty directories
- py.cleanup -a # synonym for "-s -d -e 'pip-log.txt'"
- py.cleanup -n # dry run, only show what would be removed
-
-- add a new option "py.test --funcargs" which shows available funcargs
- and their help strings (docstrings on their respective factory function)
- for a given test path
-
-- display a short and concise traceback if a funcarg lookup fails
-
-- early-load "conftest.py" files in non-dot first-level sub directories.
- allows to conveniently keep and access test-related options in a ``test``
- subdir and still add command line options.
-
-- fix issue67: new super-short traceback-printing option: "--tb=line" will print a single line for each failing (python) test indicating its filename, lineno and the failure value
-
-- fix issue78: always call python-level teardown functions even if the
- according setup failed. This includes refinements for calling setup_module/class functions
- which will now only be called once instead of the previous behaviour where they'd be called
- multiple times if they raise an exception (including a Skipped exception). Any exception
- will be re-corded and associated with all tests in the according module/class scope.
-
-- fix issue63: assume <40 columns to be a bogus terminal width, default to 80
-
-- fix pdb debugging to be in the correct frame on raises-related errors
-
-- update apipkg.py to fix an issue where recursive imports might
- unnecessarily break importing
-
-- fix plugin links
-
-1.1.1
-=====
-
-- moved dist/looponfailing from py.test core into a new
- separately released pytest-xdist plugin.
-
-- new junitxml plugin: --junitxml=path will generate a junit style xml file
- which is processable e.g. by the Hudson CI system.
-
-- new option: --genscript=path will generate a standalone py.test script
- which will not need any libraries installed. thanks to Ralf Schmitt.
-
-- new option: --ignore will prevent specified path from collection.
- Can be specified multiple times.
-
-- new option: --confcutdir=dir will make py.test only consider conftest
- files that are relative to the specified dir.
-
-- new funcarg: "pytestconfig" is the pytest config object for access
- to command line args and can now be easily used in a test.
-
-- install ``py.test`` and ``py.which`` with a ``-$VERSION`` suffix to
- disambiguate between Python3, python2.X, Jython and PyPy installed versions.
-
-- new "pytestconfig" funcarg allows access to test config object
-
-- new "pytest_report_header" hook can return additional lines
- to be displayed at the header of a test run.
-
-- (experimental) allow "py.test path::name1::name2::..." for pointing
- to a test within a test collection directly. This might eventually
- evolve as a full substitute to "-k" specifications.
-
-- streamlined plugin loading: order is now as documented in
- customize.html: setuptools, ENV, commandline, conftest.
- also setuptools entry point names are turned to canonical namees ("pytest_*")
-
-- automatically skip tests that need 'capfd' but have no os.dup
-
-- allow pytest_generate_tests to be defined in classes as well
-
-- deprecate usage of 'disabled' attribute in favour of pytestmark
-- deprecate definition of Directory, Module, Class and Function nodes
- in conftest.py files. Use pytest collect hooks instead.
-
-- collection/item node specific runtest/collect hooks are only called exactly
- on matching conftest.py files, i.e. ones which are exactly below
- the filesystem path of an item
-
-- change: the first pytest_collect_directory hook to return something
- will now prevent further hooks to be called.
-
-- change: figleaf plugin now requires --figleaf to run. Also
- change its long command line options to be a bit shorter (see py.test -h).
-
-- change: pytest doctest plugin is now enabled by default and has a
- new option --doctest-glob to set a pattern for file matches.
-
-- change: remove internal py._* helper vars, only keep py._pydir
-
-- robustify capturing to survive if custom pytest_runtest_setup
- code failed and prevented the capturing setup code from running.
-
-- make py.test.* helpers provided by default plugins visible early -
- works transparently both for pydoc and for interactive sessions
- which will regularly see e.g. py.test.mark and py.test.importorskip.
-
-- simplify internal plugin manager machinery
-- simplify internal collection tree by introducing a RootCollector node
-
-- fix assert reinterpreation that sees a call containing "keyword=..."
-
-- fix issue66: invoke pytest_sessionstart and pytest_sessionfinish
- hooks on slaves during dist-testing, report module/session teardown
- hooks correctly.
-
-- fix issue65: properly handle dist-testing if no
- execnet/py lib installed remotely.
-
-- skip some install-tests if no execnet is available
-
-- fix docs, fix internal bin/ script generation
-
-
-1.1.0
-=====
-
-- introduce automatic plugin registration via 'pytest11'
- entrypoints via setuptools' pkg_resources.iter_entry_points
-
-- fix py.test dist-testing to work with execnet >= 1.0.0b4
-
-- re-introduce py.test.cmdline.main() for better backward compatibility
-
-- svn paths: fix a bug with path.check(versioned=True) for svn paths,
- allow '%' in svn paths, make svnwc.update() default to interactive mode
- like in 1.0.x and add svnwc.update(interactive=False) to inhibit interaction.
-
-- refine distributed tarball to contain test and no pyc files
-
-- try harder to have deprecation warnings for py.compat.* accesses
- report a correct location
-
-1.0.3
-=====
-
-* adjust and improve docs
-
-* remove py.rest tool and internal namespace - it was
- never really advertised and can still be used with
- the old release if needed. If there is interest
- it could be revived into its own tool i guess.
-
-* fix issue48 and issue59: raise an Error if the module
- from an imported test file does not seem to come from
- the filepath - avoids "same-name" confusion that has
- been reported repeatedly
-
-* merged Ronny's nose-compatibility hacks: now
- nose-style setup_module() and setup() functions are
- supported
-
-* introduce generalized py.test.mark function marking
-
-* reshuffle / refine command line grouping
-
-* deprecate parser.addgroup in favour of getgroup which creates option group
-
-* add --report command line option that allows to control showing of skipped/xfailed sections
-
-* generalized skipping: a new way to mark python functions with skipif or xfail
- at function, class and modules level based on platform or sys-module attributes.
-
-* extend py.test.mark decorator to allow for positional args
-
-* introduce and test "py.cleanup -d" to remove empty directories
-
-* fix issue #59 - robustify unittest test collection
-
-* make bpython/help interaction work by adding an __all__ attribute
- to ApiModule, cleanup initpkg
-
-* use MIT license for pylib, add some contributors
-
-* remove py.execnet code and substitute all usages with 'execnet' proper
-
-* fix issue50 - cached_setup now caches more to expectations
- for test functions with multiple arguments.
-
-* merge Jarko's fixes, issue #45 and #46
-
-* add the ability to specify a path for py.lookup to search in
-
-* fix a funcarg cached_setup bug probably only occuring
- in distributed testing and "module" scope with teardown.
-
-* many fixes and changes for making the code base python3 compatible,
- many thanks to Benjamin Peterson for helping with this.
-
-* consolidate builtins implementation to be compatible with >=2.3,
- add helpers to ease keeping 2 and 3k compatible code
-
-* deprecate py.compat.doctest|subprocess|textwrap|optparse
-
-* deprecate py.magic.autopath, remove py/magic directory
-
-* move pytest assertion handling to py/code and a pytest_assertion
- plugin, add "--no-assert" option, deprecate py.magic namespaces
- in favour of (less) py.code ones.
-
-* consolidate and cleanup py/code classes and files
-
-* cleanup py/misc, move tests to bin-for-dist
-
-* introduce delattr/delitem/delenv methods to py.test's monkeypatch funcarg
-
-* consolidate py.log implementation, remove old approach.
-
-* introduce py.io.TextIO and py.io.BytesIO for distinguishing between
- text/unicode and byte-streams (uses underlying standard lib io.*
- if available)
-
-* make py.unittest_convert helper script available which converts "unittest.py"
- style files into the simpler assert/direct-test-classes py.test/nosetests
- style. The script was written by Laura Creighton.
-
-* simplified internal localpath implementation
-
-1.0.2
-=====
-
-* fixing packaging issues, triggered by fedora redhat packaging,
- also added doc, examples and contrib dirs to the tarball.
-
-* added a documentation link to the new django plugin.
-
-1.0.1
-=====
-
-* added a 'pytest_nose' plugin which handles nose.SkipTest,
- nose-style function/method/generator setup/teardown and
- tries to report functions correctly.
-
-* capturing of unicode writes or encoded strings to sys.stdout/err
- work better, also terminalwriting was adapted and somewhat
- unified between windows and linux.
-
-* improved documentation layout and content a lot
-
-* added a "--help-config" option to show conftest.py / ENV-var names for
- all longopt cmdline options, and some special conftest.py variables.
- renamed 'conf_capture' conftest setting to 'option_capture' accordingly.
-
-* fix issue #27: better reporting on non-collectable items given on commandline
- (e.g. pyc files)
-
-* fix issue #33: added --version flag (thanks Benjamin Peterson)
-
-* fix issue #32: adding support for "incomplete" paths to wcpath.status()
-
-* "Test" prefixed classes are *not* collected by default anymore if they
- have an __init__ method
-
-* monkeypatch setenv() now accepts a "prepend" parameter
-
-* improved reporting of collection error tracebacks
-
-* simplified multicall mechanism and plugin architecture,
- renamed some internal methods and argnames
-
-1.0.0
-=====
-
-* more terse reporting try to show filesystem path relatively to current dir
-* improve xfail output a bit
-
-1.0.0b9
-=======
-
-* cleanly handle and report final teardown of test setup
-
-* fix svn-1.6 compat issue with py.path.svnwc().versioned()
- (thanks Wouter Vanden Hove)
-
-* setup/teardown or collection problems now show as ERRORs
- or with big "E"'s in the progress lines. they are reported
- and counted separately.
-
-* dist-testing: properly handle test items that get locally
- collected but cannot be collected on the remote side - often
- due to platform/dependency reasons
-
-* simplified py.test.mark API - see keyword plugin documentation
-
-* integrate better with logging: capturing now by default captures
- test functions and their immediate setup/teardown in a single stream
-
-* capsys and capfd funcargs now have a readouterr() and a close() method
- (underlyingly py.io.StdCapture/FD objects are used which grew a
- readouterr() method as well to return snapshots of captured out/err)
-
-* make assert-reinterpretation work better with comparisons not
- returning bools (reported with numpy from thanks maciej fijalkowski)
-
-* reworked per-test output capturing into the pytest_iocapture.py plugin
- and thus removed capturing code from config object
-
-* item.repr_failure(excinfo) instead of item.repr_failure(excinfo, outerr)
-
-
-1.0.0b8
-=======
-
-* pytest_unittest-plugin is now enabled by default
-
-* introduced pytest_keyboardinterrupt hook and
- refined pytest_sessionfinish hooked, added tests.
-
-* workaround a buggy logging module interaction ("closing already closed
- files"). Thanks to Sridhar Ratnakumar for triggering.
-
-* if plugins use "py.test.importorskip" for importing
- a dependency only a warning will be issued instead
- of exiting the testing process.
-
-* many improvements to docs:
- - refined funcargs doc , use the term "factory" instead of "provider"
- - added a new talk/tutorial doc page
- - better download page
- - better plugin docstrings
- - added new plugins page and automatic doc generation script
-
-* fixed teardown problem related to partially failing funcarg setups
- (thanks MrTopf for reporting), "pytest_runtest_teardown" is now
- always invoked even if the "pytest_runtest_setup" failed.
-
-* tweaked doctest output for docstrings in py modules,
- thanks Radomir.
-
-1.0.0b7
-=======
-
-* renamed py.test.xfail back to py.test.mark.xfail to avoid
- two ways to decorate for xfail
-
-* re-added py.test.mark decorator for setting keywords on functions
- (it was actually documented so removing it was not nice)
-
-* remove scope-argument from request.addfinalizer() because
- request.cached_setup has the scope arg. TOOWTDI.
-
-* perform setup finalization before reporting failures
-
-* apply modified patches from Andreas Kloeckner to allow
- test functions to have no func_code (#22) and to make
- "-k" and function keywords work (#20)
-
-* apply patch from Daniel Peolzleithner (issue #23)
-
-* resolve issue #18, multiprocessing.Manager() and
- redirection clash
-
-* make __name__ == "__channelexec__" for remote_exec code
-
-1.0.0b3
-=======
-
-* plugin classes are removed: one now defines
- hooks directly in conftest.py or global pytest_*.py
- files.
-
-* added new pytest_namespace(config) hook that allows
- to inject helpers directly to the py.test.* namespace.
-
-* documented and refined many hooks
-
-* added new style of generative tests via
- pytest_generate_tests hook that integrates
- well with function arguments.
-
-
-1.0.0b1
-=======
-
-* introduced new "funcarg" setup method,
- see doc/test/funcarg.txt
-
-* introduced plugin architecture and many
- new py.test plugins, see
- doc/test/plugins.txt
-
-* teardown_method is now guaranteed to get
- called after a test method has run.
-
-* new method: py.test.importorskip(mod,minversion)
- will either import or call py.test.skip()
-
-* completely revised internal py.test architecture
-
-* new py.process.ForkedFunc object allowing to
- fork execution of a function to a sub process
- and getting a result back.
-
-XXX lots of things missing here XXX
-
-0.9.2
-=====
-
-* refined installation and metadata, created new setup.py,
- now based on setuptools/ez_setup (thanks to Ralf Schmitt
- for his support).
-
-* improved the way of making py.* scripts available in
- windows environments, they are now added to the
- Scripts directory as ".cmd" files.
-
-* py.path.svnwc.status() now is more complete and
- uses xml output from the 'svn' command if available
- (Guido Wesdorp)
-
-* fix for py.path.svn* to work with svn 1.5
- (Chris Lamb)
-
-* fix path.relto(otherpath) method on windows to
- use normcase for checking if a path is relative.
-
-* py.test's traceback is better parseable from editors
- (follows the filenames:LINENO: MSG convention)
- (thanks to Osmo Salomaa)
-
-* fix to javascript-generation, "py.test --runbrowser"
- should work more reliably now
-
-* removed previously accidentally added
- py.test.broken and py.test.notimplemented helpers.
-
-* there now is a py.__version__ attribute
-
-0.9.1
-=====
-
-This is a fairly complete list of v0.9.1, which can
-serve as a reference for developers.
-
-* allowing + signs in py.path.svn urls [39106]
-* fixed support for Failed exceptions without excinfo in py.test [39340]
-* added support for killing processes for Windows (as well as platforms that
- support os.kill) in py.misc.killproc [39655]
-* added setup/teardown for generative tests to py.test [40702]
-* added detection of FAILED TO LOAD MODULE to py.test [40703, 40738, 40739]
-* fixed problem with calling .remove() on wcpaths of non-versioned files in
- py.path [44248]
-* fixed some import and inheritance issues in py.test [41480, 44648, 44655]
-* fail to run greenlet tests when pypy is available, but without stackless
- [45294]
-* small fixes in rsession tests [45295]
-* fixed issue with 2.5 type representations in py.test [45483, 45484]
-* made that internal reporting issues displaying is done atomically in py.test
- [45518]
-* made that non-existing files are igored by the py.lookup script [45519]
-* improved exception name creation in py.test [45535]
-* made that less threads are used in execnet [merge in 45539]
-* removed lock required for atomical reporting issue displaying in py.test
- [45545]
-* removed globals from execnet [45541, 45547]
-* refactored cleanup mechanics, made that setDaemon is set to 1 to make atexit
- get called in 2.5 (py.execnet) [45548]
-* fixed bug in joining threads in py.execnet's servemain [45549]
-* refactored py.test.rsession tests to not rely on exact output format anymore
- [45646]
-* using repr() on test outcome [45647]
-* added 'Reason' classes for py.test.skip() [45648, 45649]
-* killed some unnecessary sanity check in py.test.collect [45655]
-* avoid using os.tmpfile() in py.io.fdcapture because on Windows it's only
- usable by Administrators [45901]
-* added support for locking and non-recursive commits to py.path.svnwc [45994]
-* locking files in py.execnet to prevent CPython from segfaulting [46010]
-* added export() method to py.path.svnurl
-* fixed -d -x in py.test [47277]
-* fixed argument concatenation problem in py.path.svnwc [49423]
-* restore py.test behaviour that it exits with code 1 when there are failures
- [49974]
-* don't fail on html files that don't have an accompanying .txt file [50606]
-* fixed 'utestconvert.py < input' [50645]
-* small fix for code indentation in py.code.source [50755]
-* fix _docgen.py documentation building [51285]
-* improved checks for source representation of code blocks in py.test [51292]
-* added support for passing authentication to py.path.svn* objects [52000,
- 52001]
-* removed sorted() call for py.apigen tests in favour of [].sort() to support
- Python 2.3 [52481]
diff --git a/tests/wpt/web-platform-tests/tools/pytest/CONTRIBUTING.rst b/tests/wpt/web-platform-tests/tools/pytest/CONTRIBUTING.rst
deleted file mode 100644
index 75ee3ec32d3..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/CONTRIBUTING.rst
+++ /dev/null
@@ -1,253 +0,0 @@
-============================
-Contribution getting started
-============================
-
-Contributions are highly welcomed and appreciated. Every little help counts,
-so do not hesitate!
-
-.. contents:: Contribution links
- :depth: 2
-
-
-.. _submitfeedback:
-
-Feature requests and feedback
------------------------------
-
-Do you like pytest? Share some love on Twitter or in your blog posts!
-
-We'd also like to hear about your propositions and suggestions. Feel free to
-`submit them as issues <https://github.com/pytest-dev/pytest/issues>`_ and:
-
-* Explain in detail how they should work.
-* Keep the scope as narrow as possible. This will make it easier to implement.
-
-
-.. _reportbugs:
-
-Report bugs
------------
-
-Report bugs for pytest in the `issue tracker <https://github.com/pytest-dev/pytest/issues>`_.
-
-If you are reporting a bug, please include:
-
-* Your operating system name and version.
-* Any details about your local setup that might be helpful in troubleshooting,
- specifically Python interpreter version,
- installed libraries and pytest version.
-* Detailed steps to reproduce the bug.
-
-If you can write a demonstration test that currently fails but should pass (xfail),
-that is a very useful commit to make as well, even if you can't find how
-to fix the bug yet.
-
-
-.. _fixbugs:
-
-Fix bugs
---------
-
-Look through the GitHub issues for bugs. Here is sample filter you can use:
-https://github.com/pytest-dev/pytest/labels/bug
-
-:ref:`Talk <contact>` to developers to find out how you can fix specific bugs.
-
-Don't forget to check the issue trackers of your favourite plugins, too!
-
-.. _writeplugins:
-
-Implement features
-------------------
-
-Look through the GitHub issues for enhancements. Here is sample filter you
-can use:
-https://github.com/pytest-dev/pytest/labels/enhancement
-
-:ref:`Talk <contact>` to developers to find out how you can implement specific
-features.
-
-Write documentation
--------------------
-
-pytest could always use more documentation. What exactly is needed?
-
-* More complementary documentation. Have you perhaps found something unclear?
-* Documentation translations. We currently have only English.
-* Docstrings. There can never be too many of them.
-* Blog posts, articles and such -- they're all very appreciated.
-
-You can also edit documentation files directly in the Github web interface
-without needing to make a fork and local copy. This can be convenient for
-small fixes.
-
-
-.. _submitplugin:
-
-Submitting Plugins to pytest-dev
---------------------------------
-
-Pytest development of the core, some plugins and support code happens
-in repositories living under the ``pytest-dev`` organisations:
-
-- `pytest-dev on GitHub <https://github.com/pytest-dev>`_
-
-- `pytest-dev on Bitbucket <https://bitbucket.org/pytest-dev>`_
-
-All pytest-dev Contributors team members have write access to all contained
-repositories. pytest core and plugins are generally developed
-using `pull requests`_ to respective repositories.
-
-The objectives of the ``pytest-dev`` organisation are:
-
-* Having a central location for popular pytest plugins
-* Sharing some of the maintenance responsibility (in case a maintainer no longer whishes to maintain a plugin)
-
-You can submit your plugin by subscribing to the `pytest-dev mail list
-<https://mail.python.org/mailman/listinfo/pytest-dev>`_ and writing a
-mail pointing to your existing pytest plugin repository which must have
-the following:
-
-- PyPI presence with a ``setup.py`` that contains a license, ``pytest-``
- prefixed name, version number, authors, short and long description.
-
-- a ``tox.ini`` for running tests using `tox <http://tox.testrun.org>`_.
-
-- a ``README.txt`` describing how to use the plugin and on which
- platforms it runs.
-
-- a ``LICENSE.txt`` file or equivalent containing the licensing
- information, with matching info in ``setup.py``.
-
-- an issue tracker for bug reports and enhancement requests.
-
-If no contributor strongly objects and two agree, the repository can then be
-transferred to the ``pytest-dev`` organisation.
-
-Here's a rundown of how a repository transfer usually proceeds
-(using a repository named ``joedoe/pytest-xyz`` as example):
-
-* One of the ``pytest-dev`` administrators creates:
-
- - ``pytest-xyz-admin`` team, with full administration rights to
- ``pytest-dev/pytest-xyz``.
- - ``pytest-xyz-developers`` team, with write access to
- ``pytest-dev/pytest-xyz``.
-
-* ``joedoe`` is invited to the ``pytest-xyz-admin`` team;
-
-* After accepting the invitation, ``joedoe`` transfers the repository from its
- original location to ``pytest-dev/pytest-xyz`` (A nice feature is that GitHub handles URL redirection from
- the old to the new location automatically).
-
-* ``joedoe`` is free to add any other collaborators to the
- ``pytest-xyz-admin`` or ``pytest-xyz-developers`` team as desired.
-
-The ``pytest-dev/Contributors`` team has write access to all projects, and
-every project administrator is in it. We recommend that each plugin has at least three
-people who have the right to release to PyPI.
-
-Repository owners can be assured that no ``pytest-dev`` administrator will ever make
-releases of your repository or take ownership in any way, except in rare cases
-where someone becomes unresponsive after months of contact attempts.
-As stated, the objective is to share maintenance and avoid "plugin-abandon".
-
-
-.. _`pull requests`:
-.. _pull-requests:
-
-Preparing Pull Requests on GitHub
----------------------------------
-
-There's an excellent tutorial on how Pull Requests work in the
-`GitHub Help Center <https://help.github.com/articles/using-pull-requests/>`_
-
-
-.. note::
- What is a "pull request"? It informs project's core developers about the
- changes you want to review and merge. Pull requests are stored on
- `GitHub servers <https://github.com/pytest-dev/pytest/pulls>`_.
- Once you send pull request, we can discuss it's potential modifications and
- even add more commits to it later on.
-
-There's an excellent tutorial on how Pull Requests work in the
-`GitHub Help Center <https://help.github.com/articles/using-pull-requests/>`_,
-but here is a simple overview:
-
-#. Fork the
- `pytest GitHub repository <https://github.com/pytest-dev/pytest>`__. It's
- fine to use ``pytest`` as your fork repository name because it will live
- under your user.
-
-#. Clone your fork locally using `git <https://git-scm.com/>`_ and create a branch::
-
- $ git clone git@github.com:YOUR_GITHUB_USERNAME/pytest.git
- $ cd pytest
- # now, to fix a bug create your own branch off "master":
-
- $ git checkout -b your-bugfix-branch-name master
-
- # or to instead add a feature create your own branch off "features":
-
- $ git checkout -b your-feature-branch-name features
-
- Given we have "major.minor.micro" version numbers, bugfixes will usually
- be released in micro releases whereas features will be released in
- minor releases and incompatible changes in major releases.
-
- If you need some help with Git, follow this quick start
- guide: https://git.wiki.kernel.org/index.php/QuickStart
-
-#. Install tox
-
- Tox is used to run all the tests and will automatically setup virtualenvs
- to run the tests in.
- (will implicitly use http://www.virtualenv.org/en/latest/)::
-
- $ pip install tox
-
-#. Run all the tests
-
- You need to have Python 2.7 and 3.5 available in your system. Now
- running tests is as simple as issuing this command::
-
- $ python runtox.py -e linting,py27,py35
-
- This command will run tests via the "tox" tool against Python 2.7 and 3.5
- and also perform "lint" coding-style checks. ``runtox.py`` is
- a thin wrapper around ``tox`` which installs from a development package
- index where newer (not yet released to pypi) versions of dependencies
- (especially ``py``) might be present.
-
-#. You can now edit your local working copy.
-
- You can now make the changes you want and run the tests again as necessary.
-
- To run tests on py27 and pass options to pytest (e.g. enter pdb on failure)
- to pytest you can do::
-
- $ python runtox.py -e py27 -- --pdb
-
- or to only run tests in a particular test module on py35::
-
- $ python runtox.py -e py35 -- testing/test_config.py
-
-#. Commit and push once your tests pass and you are happy with your change(s)::
-
- $ git commit -a -m "<commit message>"
- $ git push -u
-
- Make sure you add a CHANGELOG message, and add yourself to AUTHORS. If you
- are unsure about either of these steps, submit your pull request and we'll
- help you fix it up.
-
-#. Finally, submit a pull request through the GitHub website using this data::
-
- head-fork: YOUR_GITHUB_USERNAME/pytest
- compare: your-branch-name
-
- base-fork: pytest-dev/pytest
- base: master # if it's a bugfix
- base: feature # if it's a feature
-
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/HOWTORELEASE.rst b/tests/wpt/web-platform-tests/tools/pytest/HOWTORELEASE.rst
deleted file mode 100644
index 3ebfa28b1ed..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/HOWTORELEASE.rst
+++ /dev/null
@@ -1,92 +0,0 @@
-How to release pytest
---------------------------------------------
-
-Note: this assumes you have already registered on pypi.
-
-0. create the branch release-VERSION
- use features as base for minor/major releases
- and master as base for bugfix releases
-
-1. Bump version numbers in _pytest/__init__.py (setup.py reads it)
-
-2. Check and finalize CHANGELOG
-
-3. Write doc/en/announce/release-VERSION.txt and include
- it in doc/en/announce/index.txt::
-
- git log 2.8.2..HEAD --format='%aN' | sort -u # lists the names of authors involved
-
-4. Use devpi for uploading a release tarball to a staging area::
-
- devpi use https://devpi.net/USER/dev
- devpi upload --formats sdist,bdist_wheel
-
-5. Run from multiple machines::
-
- devpi use https://devpi.net/USER/dev
- devpi test pytest==VERSION
-
-6. Check that tests pass for relevant combinations with::
-
- devpi list pytest
-
- or look at failures with "devpi list -f pytest".
-
-7. Regenerate the docs examples using tox, and check for regressions::
-
- tox -e regen
- git diff
-
-
-8. Build the docs, you need a virtualenv with py and sphinx
- installed::
-
- cd doc/en
- make html
-
- Commit any changes before tagging the release.
-
-9. Tag the release::
-
- git tag VERSION
- git push
-
-10. Upload the docs using doc/en/Makefile::
-
- cd doc/en
- make install # or "installall" if you have LaTeX installed for PDF
-
- This requires ssh-login permission on pytest.org because it uses
- rsync.
- Note that the ``install`` target of ``doc/en/Makefile`` defines where the
- rsync goes to, typically to the "latest" section of pytest.org.
-
- If you are making a minor release (e.g. 5.4), you also need to manually
- create a symlink for "latest"::
-
- ssh pytest-dev@pytest.org
- ln -s 5.4 latest
-
- Browse to pytest.org to verify.
-
-11. Publish to pypi::
-
- devpi push pytest-VERSION pypi:NAME
-
- where NAME is the name of pypi.python.org as configured in your ``~/.pypirc``
- file `for devpi <http://doc.devpi.net/latest/quickstart-releaseprocess.html?highlight=pypirc#devpi-push-releasing-to-an-external-index>`_.
-
-
-12. Send release announcement to mailing lists:
-
- - pytest-dev
- - testing-in-python
- - python-announce-list@python.org
-
-
-13. **after the release** Bump the version number in ``_pytest/__init__.py``,
- to the next Minor release version (i.e. if you released ``pytest-2.8.0``,
- set it to ``pytest-2.9.0.dev1``).
-
-14. merge the actual release into the master branch and do a pull request against it
-15. merge from master to features
diff --git a/tests/wpt/web-platform-tests/tools/pytest/ISSUES.txt b/tests/wpt/web-platform-tests/tools/pytest/ISSUES.txt
deleted file mode 100644
index 081d727e86a..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/ISSUES.txt
+++ /dev/null
@@ -1,365 +0,0 @@
-
-
-recorder = monkeypatch.function(".......")
--------------------------------------------------------------
-tags: nice feature
-
-Like monkeypatch.replace but sets a mock-like call recorder:
-
- recorder = monkeypatch.function("os.path.abspath")
- recorder.set_return("/hello")
- os.path.abspath("hello")
- call, = recorder.calls
- assert call.args.path == "hello"
- assert call.returned == "/hello"
- ...
-
-Unlike mock, "args.path" acts on the parsed auto-spec'ed ``os.path.abspath``
-so it's independent from if the client side called "os.path.abspath(path=...)"
-or "os.path.abspath('positional')".
-
-
-refine parametrize API
--------------------------------------------------------------
-tags: critical feature
-
-extend metafunc.parametrize to directly support indirection, example:
-
- def setupdb(request, config):
- # setup "resource" based on test request and the values passed
- # in to parametrize. setupfunc is called for each such value.
- # you may use request.addfinalizer() or request.cached_setup ...
- return dynamic_setup_database(val)
-
- @pytest.mark.parametrize("db", ["pg", "mysql"], setupfunc=setupdb)
- def test_heavy_functional_test(db):
- ...
-
-There would be no need to write or explain funcarg factories and
-their special __ syntax.
-
-The examples and improvements should also show how to put the parametrize
-decorator to a class, to a module or even to a directory. For the directory
-part a conftest.py content like this::
-
- pytestmark = [
- @pytest.mark.parametrize_setup("db", ...),
- ]
-
-probably makes sense in order to keep the declarative nature. This mirrors
-the marker-mechanism with respect to a test module but puts it to a directory
-scale.
-
-When doing larger scoped parametrization it probably becomes necessary
-to allow parametrization to be ignored if the according parameter is not
-used (currently any parametrized argument that is not present in a function will cause a ValueError). Example:
-
- @pytest.mark.parametrize("db", ..., mustmatch=False)
-
-means to not raise an error but simply ignore the parametrization
-if the signature of a decorated function does not match. XXX is it
-not sufficient to always allow non-matches?
-
-
-allow parametrized attributes on classes
---------------------------------------------------
-
-tags: wish 2.4
-
-example:
-
- @pytest.mark.parametrize_attr("db", setupfunc, [1,2,3], scope="class")
- @pytest.mark.parametrize_attr("tmp", setupfunc, scope="...")
- class TestMe:
- def test_hello(self):
- access self.db ...
-
-this would run the test_hello() function three times with three
-different values for self.db. This could also work with unittest/nose
-style tests, i.e. it leverages existing test suites without needing
-to rewrite them. Together with the previously mentioned setup_test()
-maybe the setupfunc could be omitted?
-
-optimizations
----------------------------------------------------------------
-tags: 2.4 core
-
-- look at ihook optimization such that all lookups for
- hooks relating to the same fspath are cached.
-
-fix start/finish partial finailization problem
----------------------------------------------------------------
-tags: bug core
-
-if a configure/runtest_setup/sessionstart/... hook invocation partially
-fails the sessionfinishes is not called. Each hook implementation
-should better be repsonsible for registering a cleanup/finalizer
-appropriately to avoid this issue. Moreover/Alternatively, we could
-record which implementations of a hook succeeded and only call their
-teardown.
-
-
-relax requirement to have tests/testing contain an __init__
-----------------------------------------------------------------
-tags: feature
-bb: http://bitbucket.org/hpk42/py-trunk/issue/64
-
-A local test run of a "tests" directory may work
-but a remote one fail because the tests directory
-does not contain an "__init__.py". Either give
-an error or make it work without the __init__.py
-i.e. port the nose-logic of unloading a test module.
-
-customize test function collection
--------------------------------------------------------
-tags: feature
-
-- introduce pytest.mark.nocollect for not considering a function for
- test collection at all. maybe also introduce a pytest.mark.test to
- explicitly mark a function to become a tested one. Lookup JUnit ways
- of tagging tests.
-
-introduce pytest.mark.importorskip
--------------------------------------------------------
-tags: feature
-
-in addition to the imperative pytest.importorskip also introduce
-a pytest.mark.importorskip so that the test count is more correct.
-
-
-introduce pytest.mark.platform
--------------------------------------------------------
-tags: feature
-
-Introduce nice-to-spell platform-skipping, examples:
-
- @pytest.mark.platform("python3")
- @pytest.mark.platform("not python3")
- @pytest.mark.platform("win32 and not python3")
- @pytest.mark.platform("darwin")
- @pytest.mark.platform("not (jython and win32)")
- @pytest.mark.platform("not (jython and win32)", xfail=True)
-
-etc. Idea is to allow Python expressions which can operate
-on common spellings for operating systems and python
-interpreter versions.
-
-pytest.mark.xfail signature change
--------------------------------------------------------
-tags: feature
-
-change to pytest.mark.xfail(reason, (optional)condition)
-to better implement the word meaning. It also signals
-better that we always have some kind of an implementation
-reason that can be formualated.
-Compatibility? how to introduce a new name/keep compat?
-
-allow to non-intrusively apply skipfs/xfail/marks
----------------------------------------------------
-tags: feature
-
-use case: mark a module or directory structures
-to be skipped on certain platforms (i.e. no import
-attempt will be made).
-
-consider introducing a hook/mechanism that allows to apply marks
-from conftests or plugins. (See extended parametrization)
-
-
-explicit referencing of conftest.py files
------------------------------------------
-tags: feature
-
-allow to name conftest.py files (in sub directories) that should
-be imported early, as to include command line options.
-
-improve central pytest ini file
--------------------------------
-tags: feature
-
-introduce more declarative configuration options:
-- (to-be-collected test directories)
-- required plugins
-- test func/class/file matching patterns
-- skip/xfail (non-intrusive)
-- pytest.ini and tox.ini and setup.cfg configuration in the same file
-
-new documentation
-----------------------------------
-tags: feature
-
-- logo pytest
-- examples for unittest or functional testing
-- resource management for functional testing
-- patterns: page object
-
-have imported module mismatch honour relative paths
---------------------------------------------------------
-tags: bug
-
-With 1.1.1 pytest fails at least on windows if an import
-is relative and compared against an absolute conftest.py
-path. Normalize.
-
-consider globals: pytest.ensuretemp and config
---------------------------------------------------------------
-tags: experimental-wish
-
-consider deprecating pytest.ensuretemp and pytest.config
-to further reduce pytest globality. Also consider
-having pytest.config and ensuretemp coming from
-a plugin rather than being there from the start.
-
-
-consider pytest_addsyspath hook
------------------------------------------
-tags: wish
-
-pytest could call a new pytest_addsyspath() in order to systematically
-allow manipulation of sys.path and to inhibit it via --no-addsyspath
-in order to more easily run against installed packages.
-
-Alternatively it could also be done via the config object
-and pytest_configure.
-
-
-
-deprecate global pytest.config usage
-----------------------------------------------------------------
-tags: feature
-
-pytest.ensuretemp and pytest.config are probably the last
-objects containing global state. Often using them is not
-necessary. This is about trying to get rid of them, i.e.
-deprecating them and checking with PyPy's usages as well
-as others.
-
-remove deprecated bits in collect.py
--------------------------------------------------------------------
-tags: feature
-
-In an effort to further simplify code, review and remove deprecated bits
-in collect.py. Probably good:
-- inline consider_file/dir methods, no need to have them
- subclass-overridable because of hooks
-
-implement fslayout decorator
----------------------------------
-tags: feature
-
-Improve the way how tests can work with pre-made examples,
-keeping the layout close to the test function:
-
-@pytest.mark.fslayout("""
- conftest.py:
- # empty
- tests/
- test_%(NAME)s: # becomes test_run1.py
- def test_function(self):
- pass
-""")
-def test_run(pytester, fslayout):
- p = fslayout.findone("test_*.py")
- result = pytester.runpytest(p)
- assert result.ret == 0
- assert result.passed == 1
-
-Another idea is to allow to define a full scenario including the run
-in one content string::
-
- runscenario("""
- test_{TESTNAME}.py:
- import pytest
- @pytest.mark.xfail
- def test_that_fails():
- assert 0
-
- @pytest.mark.skipif("True")
- def test_hello():
- pass
-
- conftest.py:
- import pytest
- def pytest_runsetup_setup(item):
- pytest.skip("abc")
-
- runpytest -rsxX
- *SKIP*{TESTNAME}*
- *1 skipped*
- """)
-
-This could be run with at least three different ways to invoke pytest:
-through the shell, through "python -m pytest" and inlined. As inlined
-would be the fastest it could be run first (or "--fast" mode).
-
-
-Create isolate plugin
----------------------
-tags: feature
-
-The idea is that you can e.g. import modules in a test and afterwards
-sys.modules, sys.meta_path etc would be reverted. It can go further
-then just importing however, e.g. current working directory, file
-descriptors, ...
-
-This would probably be done by marking::
-
- @pytest.mark.isolate(importing=True, cwd=True, fds=False)
- def test_foo():
- ...
-
-With the possibility of doing this globally in an ini-file.
-
-
-fnmatch for test names
-----------------------
-tags: feature-wish
-
-various testsuites use suffixes instead of prefixes for test classes
-also it lends itself to bdd style test names::
-
- class UserBehaviour:
- def anonymous_should_not_have_inbox(user):
- ...
- def registred_should_have_inbox(user):
- ..
-
-using the following in pytest.ini::
-
- [pytest]
- python_classes = Test *Behaviour *Test
- python_functions = test *_should_*
-
-
-mechanism for running named parts of tests with different reporting behaviour
-------------------------------------------------------------------------------
-tags: feature-wish-incomplete
-
-a few use-cases come to mind:
-
-* fail assertions and record that without stopping a complete test
-
- * this is in particular hepfull if a small bit of a test is known to fail/xfail::
-
- def test_fun():
- with pytest.section('fdcheck, marks=pytest.mark.xfail_if(...)):
- breaks_on_windows()
-
-* divide functional/acceptance tests into sections
-* provide a different mechanism for generators, maybe something like::
-
- def pytest_runtest_call(item)
- if not generator:
- ...
- prepare_check = GeneratorCheckprepare()
-
- gen = item.obj(**fixtures)
- for check in gen
- id, call = prepare_check(check)
- # bubble should only prevent exception propagation after a failure
- # the whole test should still fail
- # there might be need for a lower level api and taking custom markers into account
- with pytest.section(id, bubble=False):
- call()
-
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/LICENSE b/tests/wpt/web-platform-tests/tools/pytest/LICENSE
deleted file mode 100644
index 9e27bd78419..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2004-2016 Holger Krekel and others
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/tests/wpt/web-platform-tests/tools/pytest/MANIFEST.in b/tests/wpt/web-platform-tests/tools/pytest/MANIFEST.in
deleted file mode 100644
index 266a9184dc3..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/MANIFEST.in
+++ /dev/null
@@ -1,34 +0,0 @@
-include CHANGELOG.rst
-include LICENSE
-include AUTHORS
-
-include README.rst
-include CONTRIBUTING.rst
-
-include tox.ini
-include setup.py
-
-include .coveragerc
-
-include plugin-test.sh
-include requirements-docs.txt
-include runtox.py
-
-recursive-include bench *.py
-recursive-include extra *.py
-
-graft testing
-graft doc
-
-exclude _pytest/impl
-
-graft _pytest/vendored_packages
-
-recursive-exclude * *.pyc *.pyo
-
-exclude appveyor/install.ps1
-exclude appveyor.yml
-exclude appveyor
-
-exclude ISSUES.txt
-exclude HOWTORELEASE.rst
diff --git a/tests/wpt/web-platform-tests/tools/pytest/README.rst b/tests/wpt/web-platform-tests/tools/pytest/README.rst
deleted file mode 100644
index 68fc92211d8..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/README.rst
+++ /dev/null
@@ -1,102 +0,0 @@
-.. image:: http://pytest.org/latest/_static/pytest1.png
- :target: http://pytest.org
- :align: center
- :alt: pytest
-
-------
-
-.. image:: https://img.shields.io/pypi/v/pytest.svg
- :target: https://pypi.python.org/pypi/pytest
-.. image:: https://img.shields.io/pypi/pyversions/pytest.svg
- :target: https://pypi.python.org/pypi/pytest
-.. image:: https://img.shields.io/coveralls/pytest-dev/pytest/master.svg
- :target: https://coveralls.io/r/pytest-dev/pytest
-.. image:: https://travis-ci.org/pytest-dev/pytest.svg?branch=master
- :target: https://travis-ci.org/pytest-dev/pytest
-.. image:: https://ci.appveyor.com/api/projects/status/mrgbjaua7t33pg6b?svg=true
- :target: https://ci.appveyor.com/project/pytestbot/pytest
-
-The ``pytest`` framework makes it easy to write small tests, yet
-scales to support complex functional testing for applications and libraries.
-
-An example of a simple test:
-
-.. code-block:: python
-
- # content of test_sample.py
- def func(x):
- return x + 1
-
- def test_answer():
- assert func(3) == 5
-
-
-To execute it::
-
- $ py.test
- ======= test session starts ========
- platform linux -- Python 3.4.3, pytest-2.8.5, py-1.4.31, pluggy-0.3.1
- collected 1 items
-
- test_sample.py F
-
- ======= FAILURES ========
- _______ test_answer ________
-
- def test_answer():
- > assert func(3) == 5
- E assert 4 == 5
- E + where 4 = func(3)
-
- test_sample.py:5: AssertionError
- ======= 1 failed in 0.12 seconds ========
-
-Due to ``py.test``'s detailed assertion introspection, only plain ``assert`` statements are used. See `getting-started <http://pytest.org/latest/getting-started.html#our-first-test-run>`_ for more examples.
-
-
-Features
---------
-
-- Detailed info on failing `assert statements <http://pytest.org/latest/assert.html>`_ (no need to remember ``self.assert*`` names);
-
-- `Auto-discovery
- <http://pytest.org/latest/goodpractices.html#python-test-discovery>`_
- of test modules and functions;
-
-- `Modular fixtures <http://pytest.org/latest/fixture.html>`_ for
- managing small or parametrized long-lived test resources;
-
-- Can run `unittest <http://pytest.org/latest/unittest.html>`_ (or trial),
- `nose <http://pytest.org/latest/nose.html>`_ test suites out of the box;
-
-- Python2.6+, Python3.2+, PyPy-2.3, Jython-2.5 (untested);
-
-- Rich plugin architecture, with over 150+ `external plugins <http://pytest.org/latest/plugins.html#installing-external-plugins-searching>`_ and thriving community;
-
-
-Documentation
--------------
-
-For full documentation, including installation, tutorials and PDF documents, please see http://pytest.org.
-
-
-Bugs/Requests
--------------
-
-Please use the `GitHub issue tracker <https://github.com/pytest-dev/pytest/issues>`_ to submit bugs or request features.
-
-
-Changelog
----------
-
-Consult the `Changelog <http://pytest.org/latest/changelog.html>`_ page for fixes and enhancements of each version.
-
-
-License
--------
-
-Copyright Holger Krekel and others, 2004-2016.
-
-Distributed under the terms of the `MIT`_ license, pytest is free and open source software.
-
-.. _`MIT`: https://github.com/pytest-dev/pytest/blob/master/LICENSE
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/__init__.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/__init__.py
deleted file mode 100644
index 723fb9e855a..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-#
-__version__ = '2.9.1'
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/_argcomplete.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/_argcomplete.py
deleted file mode 100644
index 955855a9648..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/_argcomplete.py
+++ /dev/null
@@ -1,101 +0,0 @@
-
-"""allow bash-completion for argparse with argcomplete if installed
-needs argcomplete>=0.5.6 for python 3.2/3.3 (older versions fail
-to find the magic string, so _ARGCOMPLETE env. var is never set, and
-this does not need special code.
-
-argcomplete does not support python 2.5 (although the changes for that
-are minor).
-
-Function try_argcomplete(parser) should be called directly before
-the call to ArgumentParser.parse_args().
-
-The filescompleter is what you normally would use on the positional
-arguments specification, in order to get "dirname/" after "dirn<TAB>"
-instead of the default "dirname ":
-
- optparser.add_argument(Config._file_or_dir, nargs='*'
- ).completer=filescompleter
-
-Other, application specific, completers should go in the file
-doing the add_argument calls as they need to be specified as .completer
-attributes as well. (If argcomplete is not installed, the function the
-attribute points to will not be used).
-
-SPEEDUP
-=======
-The generic argcomplete script for bash-completion
-(/etc/bash_completion.d/python-argcomplete.sh )
-uses a python program to determine startup script generated by pip.
-You can speed up completion somewhat by changing this script to include
- # PYTHON_ARGCOMPLETE_OK
-so the the python-argcomplete-check-easy-install-script does not
-need to be called to find the entry point of the code and see if that is
-marked with PYTHON_ARGCOMPLETE_OK
-
-INSTALL/DEBUGGING
-=================
-To include this support in another application that has setup.py generated
-scripts:
-- add the line:
- # PYTHON_ARGCOMPLETE_OK
- near the top of the main python entry point
-- include in the file calling parse_args():
- from _argcomplete import try_argcomplete, filescompleter
- , call try_argcomplete just before parse_args(), and optionally add
- filescompleter to the positional arguments' add_argument()
-If things do not work right away:
-- switch on argcomplete debugging with (also helpful when doing custom
- completers):
- export _ARC_DEBUG=1
-- run:
- python-argcomplete-check-easy-install-script $(which appname)
- echo $?
- will echo 0 if the magic line has been found, 1 if not
-- sometimes it helps to find early on errors using:
- _ARGCOMPLETE=1 _ARC_DEBUG=1 appname
- which should throw a KeyError: 'COMPLINE' (which is properly set by the
- global argcomplete script).
-"""
-
-import sys
-import os
-from glob import glob
-
-class FastFilesCompleter:
- 'Fast file completer class'
- def __init__(self, directories=True):
- self.directories = directories
-
- def __call__(self, prefix, **kwargs):
- """only called on non option completions"""
- if os.path.sep in prefix[1:]: #
- prefix_dir = len(os.path.dirname(prefix) + os.path.sep)
- else:
- prefix_dir = 0
- completion = []
- globbed = []
- if '*' not in prefix and '?' not in prefix:
- if prefix[-1] == os.path.sep: # we are on unix, otherwise no bash
- globbed.extend(glob(prefix + '.*'))
- prefix += '*'
- globbed.extend(glob(prefix))
- for x in sorted(globbed):
- if os.path.isdir(x):
- x += '/'
- # append stripping the prefix (like bash, not like compgen)
- completion.append(x[prefix_dir:])
- return completion
-
-if os.environ.get('_ARGCOMPLETE'):
- try:
- import argcomplete.completers
- except ImportError:
- sys.exit(-1)
- filescompleter = FastFilesCompleter()
-
- def try_argcomplete(parser):
- argcomplete.autocomplete(parser)
-else:
- def try_argcomplete(parser): pass
- filescompleter = None
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/_code/__init__.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/_code/__init__.py
deleted file mode 100644
index c046b9716ca..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/_code/__init__.py
+++ /dev/null
@@ -1,12 +0,0 @@
-""" python inspection/code generation API """
-from .code import Code # noqa
-from .code import ExceptionInfo # noqa
-from .code import Frame # noqa
-from .code import Traceback # noqa
-from .code import getrawcode # noqa
-from .code import patch_builtins # noqa
-from .code import unpatch_builtins # noqa
-from .source import Source # noqa
-from .source import compile_ as compile # noqa
-from .source import getfslineno # noqa
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/_code/_py2traceback.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/_code/_py2traceback.py
deleted file mode 100644
index a830d9899ae..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/_code/_py2traceback.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# copied from python-2.7.3's traceback.py
-# CHANGES:
-# - some_str is replaced, trying to create unicode strings
-#
-import types
-
-def format_exception_only(etype, value):
- """Format the exception part of a traceback.
-
- The arguments are the exception type and value such as given by
- sys.last_type and sys.last_value. The return value is a list of
- strings, each ending in a newline.
-
- Normally, the list contains a single string; however, for
- SyntaxError exceptions, it contains several lines that (when
- printed) display detailed information about where the syntax
- error occurred.
-
- The message indicating which exception occurred is always the last
- string in the list.
-
- """
-
- # An instance should not have a meaningful value parameter, but
- # sometimes does, particularly for string exceptions, such as
- # >>> raise string1, string2 # deprecated
- #
- # Clear these out first because issubtype(string1, SyntaxError)
- # would throw another exception and mask the original problem.
- if (isinstance(etype, BaseException) or
- isinstance(etype, types.InstanceType) or
- etype is None or type(etype) is str):
- return [_format_final_exc_line(etype, value)]
-
- stype = etype.__name__
-
- if not issubclass(etype, SyntaxError):
- return [_format_final_exc_line(stype, value)]
-
- # It was a syntax error; show exactly where the problem was found.
- lines = []
- try:
- msg, (filename, lineno, offset, badline) = value.args
- except Exception:
- pass
- else:
- filename = filename or "<string>"
- lines.append(' File "%s", line %d\n' % (filename, lineno))
- if badline is not None:
- if isinstance(badline, bytes): # python 2 only
- badline = badline.decode('utf-8', 'replace')
- lines.append(u' %s\n' % badline.strip())
- if offset is not None:
- caretspace = badline.rstrip('\n')[:offset].lstrip()
- # non-space whitespace (likes tabs) must be kept for alignment
- caretspace = ((c.isspace() and c or ' ') for c in caretspace)
- # only three spaces to account for offset1 == pos 0
- lines.append(' %s^\n' % ''.join(caretspace))
- value = msg
-
- lines.append(_format_final_exc_line(stype, value))
- return lines
-
-def _format_final_exc_line(etype, value):
- """Return a list of a single line -- normal case for format_exception_only"""
- valuestr = _some_str(value)
- if value is None or not valuestr:
- line = "%s\n" % etype
- else:
- line = "%s: %s\n" % (etype, valuestr)
- return line
-
-def _some_str(value):
- try:
- return unicode(value)
- except Exception:
- try:
- return str(value)
- except Exception:
- pass
- return '<unprintable %s object>' % type(value).__name__
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/_code/code.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/_code/code.py
deleted file mode 100644
index bc68aac5548..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/_code/code.py
+++ /dev/null
@@ -1,795 +0,0 @@
-import sys
-from inspect import CO_VARARGS, CO_VARKEYWORDS
-
-import py
-
-builtin_repr = repr
-
-reprlib = py.builtin._tryimport('repr', 'reprlib')
-
-if sys.version_info[0] >= 3:
- from traceback import format_exception_only
-else:
- from ._py2traceback import format_exception_only
-
-class Code(object):
- """ wrapper around Python code objects """
- def __init__(self, rawcode):
- if not hasattr(rawcode, "co_filename"):
- rawcode = getrawcode(rawcode)
- try:
- self.filename = rawcode.co_filename
- self.firstlineno = rawcode.co_firstlineno - 1
- self.name = rawcode.co_name
- except AttributeError:
- raise TypeError("not a code object: %r" %(rawcode,))
- self.raw = rawcode
-
- def __eq__(self, other):
- return self.raw == other.raw
-
- def __ne__(self, other):
- return not self == other
-
- @property
- def path(self):
- """ return a path object pointing to source code (note that it
- might not point to an actually existing file). """
- p = py.path.local(self.raw.co_filename)
- # maybe don't try this checking
- if not p.check():
- # XXX maybe try harder like the weird logic
- # in the standard lib [linecache.updatecache] does?
- p = self.raw.co_filename
- return p
-
- @property
- def fullsource(self):
- """ return a _pytest._code.Source object for the full source file of the code
- """
- from _pytest._code import source
- full, _ = source.findsource(self.raw)
- return full
-
- def source(self):
- """ return a _pytest._code.Source object for the code object's source only
- """
- # return source only for that part of code
- import _pytest._code
- return _pytest._code.Source(self.raw)
-
- def getargs(self, var=False):
- """ return a tuple with the argument names for the code object
-
- if 'var' is set True also return the names of the variable and
- keyword arguments when present
- """
- # handfull shortcut for getting args
- raw = self.raw
- argcount = raw.co_argcount
- if var:
- argcount += raw.co_flags & CO_VARARGS
- argcount += raw.co_flags & CO_VARKEYWORDS
- return raw.co_varnames[:argcount]
-
-class Frame(object):
- """Wrapper around a Python frame holding f_locals and f_globals
- in which expressions can be evaluated."""
-
- def __init__(self, frame):
- self.lineno = frame.f_lineno - 1
- self.f_globals = frame.f_globals
- self.f_locals = frame.f_locals
- self.raw = frame
- self.code = Code(frame.f_code)
-
- @property
- def statement(self):
- """ statement this frame is at """
- import _pytest._code
- if self.code.fullsource is None:
- return _pytest._code.Source("")
- return self.code.fullsource.getstatement(self.lineno)
-
- def eval(self, code, **vars):
- """ evaluate 'code' in the frame
-
- 'vars' are optional additional local variables
-
- returns the result of the evaluation
- """
- f_locals = self.f_locals.copy()
- f_locals.update(vars)
- return eval(code, self.f_globals, f_locals)
-
- def exec_(self, code, **vars):
- """ exec 'code' in the frame
-
- 'vars' are optiona; additional local variables
- """
- f_locals = self.f_locals.copy()
- f_locals.update(vars)
- py.builtin.exec_(code, self.f_globals, f_locals )
-
- def repr(self, object):
- """ return a 'safe' (non-recursive, one-line) string repr for 'object'
- """
- return py.io.saferepr(object)
-
- def is_true(self, object):
- return object
-
- def getargs(self, var=False):
- """ return a list of tuples (name, value) for all arguments
-
- if 'var' is set True also include the variable and keyword
- arguments when present
- """
- retval = []
- for arg in self.code.getargs(var):
- try:
- retval.append((arg, self.f_locals[arg]))
- except KeyError:
- pass # this can occur when using Psyco
- return retval
-
-class TracebackEntry(object):
- """ a single entry in a traceback """
-
- _repr_style = None
- exprinfo = None
-
- def __init__(self, rawentry):
- self._rawentry = rawentry
- self.lineno = rawentry.tb_lineno - 1
-
- def set_repr_style(self, mode):
- assert mode in ("short", "long")
- self._repr_style = mode
-
- @property
- def frame(self):
- import _pytest._code
- return _pytest._code.Frame(self._rawentry.tb_frame)
-
- @property
- def relline(self):
- return self.lineno - self.frame.code.firstlineno
-
- def __repr__(self):
- return "<TracebackEntry %s:%d>" %(self.frame.code.path, self.lineno+1)
-
- @property
- def statement(self):
- """ _pytest._code.Source object for the current statement """
- source = self.frame.code.fullsource
- return source.getstatement(self.lineno)
-
- @property
- def path(self):
- """ path to the source code """
- return self.frame.code.path
-
- def getlocals(self):
- return self.frame.f_locals
- locals = property(getlocals, None, None, "locals of underlaying frame")
-
- def reinterpret(self):
- """Reinterpret the failing statement and returns a detailed information
- about what operations are performed."""
- from _pytest.assertion.reinterpret import reinterpret
- if self.exprinfo is None:
- source = py.builtin._totext(self.statement).strip()
- x = reinterpret(source, self.frame, should_fail=True)
- if not py.builtin._istext(x):
- raise TypeError("interpret returned non-string %r" % (x,))
- self.exprinfo = x
- return self.exprinfo
-
- def getfirstlinesource(self):
- # on Jython this firstlineno can be -1 apparently
- return max(self.frame.code.firstlineno, 0)
-
- def getsource(self, astcache=None):
- """ return failing source code. """
- # we use the passed in astcache to not reparse asttrees
- # within exception info printing
- from _pytest._code.source import getstatementrange_ast
- source = self.frame.code.fullsource
- if source is None:
- return None
- key = astnode = None
- if astcache is not None:
- key = self.frame.code.path
- if key is not None:
- astnode = astcache.get(key, None)
- start = self.getfirstlinesource()
- try:
- astnode, _, end = getstatementrange_ast(self.lineno, source,
- astnode=astnode)
- except SyntaxError:
- end = self.lineno + 1
- else:
- if key is not None:
- astcache[key] = astnode
- return source[start:end]
-
- source = property(getsource)
-
- def ishidden(self):
- """ return True if the current frame has a var __tracebackhide__
- resolving to True
-
- mostly for internal use
- """
- try:
- return self.frame.f_locals['__tracebackhide__']
- except KeyError:
- try:
- return self.frame.f_globals['__tracebackhide__']
- except KeyError:
- return False
-
- def __str__(self):
- try:
- fn = str(self.path)
- except py.error.Error:
- fn = '???'
- name = self.frame.code.name
- try:
- line = str(self.statement).lstrip()
- except KeyboardInterrupt:
- raise
- except:
- line = "???"
- return " File %r:%d in %s\n %s\n" %(fn, self.lineno+1, name, line)
-
- def name(self):
- return self.frame.code.raw.co_name
- name = property(name, None, None, "co_name of underlaying code")
-
-class Traceback(list):
- """ Traceback objects encapsulate and offer higher level
- access to Traceback entries.
- """
- Entry = TracebackEntry
- def __init__(self, tb):
- """ initialize from given python traceback object. """
- if hasattr(tb, 'tb_next'):
- def f(cur):
- while cur is not None:
- yield self.Entry(cur)
- cur = cur.tb_next
- list.__init__(self, f(tb))
- else:
- list.__init__(self, tb)
-
- def cut(self, path=None, lineno=None, firstlineno=None, excludepath=None):
- """ return a Traceback instance wrapping part of this Traceback
-
- by provding any combination of path, lineno and firstlineno, the
- first frame to start the to-be-returned traceback is determined
-
- this allows cutting the first part of a Traceback instance e.g.
- for formatting reasons (removing some uninteresting bits that deal
- with handling of the exception/traceback)
- """
- for x in self:
- code = x.frame.code
- codepath = code.path
- if ((path is None or codepath == path) and
- (excludepath is None or not hasattr(codepath, 'relto') or
- not codepath.relto(excludepath)) and
- (lineno is None or x.lineno == lineno) and
- (firstlineno is None or x.frame.code.firstlineno == firstlineno)):
- return Traceback(x._rawentry)
- return self
-
- def __getitem__(self, key):
- val = super(Traceback, self).__getitem__(key)
- if isinstance(key, type(slice(0))):
- val = self.__class__(val)
- return val
-
- def filter(self, fn=lambda x: not x.ishidden()):
- """ return a Traceback instance with certain items removed
-
- fn is a function that gets a single argument, a TracebackItem
- instance, and should return True when the item should be added
- to the Traceback, False when not
-
- by default this removes all the TracebackItems which are hidden
- (see ishidden() above)
- """
- return Traceback(filter(fn, self))
-
- def getcrashentry(self):
- """ return last non-hidden traceback entry that lead
- to the exception of a traceback.
- """
- for i in range(-1, -len(self)-1, -1):
- entry = self[i]
- if not entry.ishidden():
- return entry
- return self[-1]
-
- def recursionindex(self):
- """ return the index of the frame/TracebackItem where recursion
- originates if appropriate, None if no recursion occurred
- """
- cache = {}
- for i, entry in enumerate(self):
- # id for the code.raw is needed to work around
- # the strange metaprogramming in the decorator lib from pypi
- # which generates code objects that have hash/value equality
- #XXX needs a test
- key = entry.frame.code.path, id(entry.frame.code.raw), entry.lineno
- #print "checking for recursion at", key
- l = cache.setdefault(key, [])
- if l:
- f = entry.frame
- loc = f.f_locals
- for otherloc in l:
- if f.is_true(f.eval(co_equal,
- __recursioncache_locals_1=loc,
- __recursioncache_locals_2=otherloc)):
- return i
- l.append(entry.frame.f_locals)
- return None
-
-co_equal = compile('__recursioncache_locals_1 == __recursioncache_locals_2',
- '?', 'eval')
-
-class ExceptionInfo(object):
- """ wraps sys.exc_info() objects and offers
- help for navigating the traceback.
- """
- _striptext = ''
- def __init__(self, tup=None, exprinfo=None):
- import _pytest._code
- if tup is None:
- tup = sys.exc_info()
- if exprinfo is None and isinstance(tup[1], AssertionError):
- exprinfo = getattr(tup[1], 'msg', None)
- if exprinfo is None:
- exprinfo = str(tup[1])
- if exprinfo and exprinfo.startswith('assert '):
- self._striptext = 'AssertionError: '
- self._excinfo = tup
- #: the exception class
- self.type = tup[0]
- #: the exception instance
- self.value = tup[1]
- #: the exception raw traceback
- self.tb = tup[2]
- #: the exception type name
- self.typename = self.type.__name__
- #: the exception traceback (_pytest._code.Traceback instance)
- self.traceback = _pytest._code.Traceback(self.tb)
-
- def __repr__(self):
- return "<ExceptionInfo %s tblen=%d>" % (self.typename, len(self.traceback))
-
- def exconly(self, tryshort=False):
- """ return the exception as a string
-
- when 'tryshort' resolves to True, and the exception is a
- _pytest._code._AssertionError, only the actual exception part of
- the exception representation is returned (so 'AssertionError: ' is
- removed from the beginning)
- """
- lines = format_exception_only(self.type, self.value)
- text = ''.join(lines)
- text = text.rstrip()
- if tryshort:
- if text.startswith(self._striptext):
- text = text[len(self._striptext):]
- return text
-
- def errisinstance(self, exc):
- """ return True if the exception is an instance of exc """
- return isinstance(self.value, exc)
-
- def _getreprcrash(self):
- exconly = self.exconly(tryshort=True)
- entry = self.traceback.getcrashentry()
- path, lineno = entry.frame.code.raw.co_filename, entry.lineno
- return ReprFileLocation(path, lineno+1, exconly)
-
- def getrepr(self, showlocals=False, style="long",
- abspath=False, tbfilter=True, funcargs=False):
- """ return str()able representation of this exception info.
- showlocals: show locals per traceback entry
- style: long|short|no|native traceback style
- tbfilter: hide entries (where __tracebackhide__ is true)
-
- in case of style==native, tbfilter and showlocals is ignored.
- """
- if style == 'native':
- return ReprExceptionInfo(ReprTracebackNative(
- py.std.traceback.format_exception(
- self.type,
- self.value,
- self.traceback[0]._rawentry,
- )), self._getreprcrash())
-
- fmt = FormattedExcinfo(showlocals=showlocals, style=style,
- abspath=abspath, tbfilter=tbfilter, funcargs=funcargs)
- return fmt.repr_excinfo(self)
-
- def __str__(self):
- entry = self.traceback[-1]
- loc = ReprFileLocation(entry.path, entry.lineno + 1, self.exconly())
- return str(loc)
-
- def __unicode__(self):
- entry = self.traceback[-1]
- loc = ReprFileLocation(entry.path, entry.lineno + 1, self.exconly())
- return unicode(loc)
-
-
-class FormattedExcinfo(object):
- """ presenting information about failing Functions and Generators. """
- # for traceback entries
- flow_marker = ">"
- fail_marker = "E"
-
- def __init__(self, showlocals=False, style="long", abspath=True, tbfilter=True, funcargs=False):
- self.showlocals = showlocals
- self.style = style
- self.tbfilter = tbfilter
- self.funcargs = funcargs
- self.abspath = abspath
- self.astcache = {}
-
- def _getindent(self, source):
- # figure out indent for given source
- try:
- s = str(source.getstatement(len(source)-1))
- except KeyboardInterrupt:
- raise
- except:
- try:
- s = str(source[-1])
- except KeyboardInterrupt:
- raise
- except:
- return 0
- return 4 + (len(s) - len(s.lstrip()))
-
- def _getentrysource(self, entry):
- source = entry.getsource(self.astcache)
- if source is not None:
- source = source.deindent()
- return source
-
- def _saferepr(self, obj):
- return py.io.saferepr(obj)
-
- def repr_args(self, entry):
- if self.funcargs:
- args = []
- for argname, argvalue in entry.frame.getargs(var=True):
- args.append((argname, self._saferepr(argvalue)))
- return ReprFuncArgs(args)
-
- def get_source(self, source, line_index=-1, excinfo=None, short=False):
- """ return formatted and marked up source lines. """
- import _pytest._code
- lines = []
- if source is None or line_index >= len(source.lines):
- source = _pytest._code.Source("???")
- line_index = 0
- if line_index < 0:
- line_index += len(source)
- space_prefix = " "
- if short:
- lines.append(space_prefix + source.lines[line_index].strip())
- else:
- for line in source.lines[:line_index]:
- lines.append(space_prefix + line)
- lines.append(self.flow_marker + " " + source.lines[line_index])
- for line in source.lines[line_index+1:]:
- lines.append(space_prefix + line)
- if excinfo is not None:
- indent = 4 if short else self._getindent(source)
- lines.extend(self.get_exconly(excinfo, indent=indent, markall=True))
- return lines
-
- def get_exconly(self, excinfo, indent=4, markall=False):
- lines = []
- indent = " " * indent
- # get the real exception information out
- exlines = excinfo.exconly(tryshort=True).split('\n')
- failindent = self.fail_marker + indent[1:]
- for line in exlines:
- lines.append(failindent + line)
- if not markall:
- failindent = indent
- return lines
-
- def repr_locals(self, locals):
- if self.showlocals:
- lines = []
- keys = [loc for loc in locals if loc[0] != "@"]
- keys.sort()
- for name in keys:
- value = locals[name]
- if name == '__builtins__':
- lines.append("__builtins__ = <builtins>")
- else:
- # This formatting could all be handled by the
- # _repr() function, which is only reprlib.Repr in
- # disguise, so is very configurable.
- str_repr = self._saferepr(value)
- #if len(str_repr) < 70 or not isinstance(value,
- # (list, tuple, dict)):
- lines.append("%-10s = %s" %(name, str_repr))
- #else:
- # self._line("%-10s =\\" % (name,))
- # # XXX
- # py.std.pprint.pprint(value, stream=self.excinfowriter)
- return ReprLocals(lines)
-
- def repr_traceback_entry(self, entry, excinfo=None):
- import _pytest._code
- source = self._getentrysource(entry)
- if source is None:
- source = _pytest._code.Source("???")
- line_index = 0
- else:
- # entry.getfirstlinesource() can be -1, should be 0 on jython
- line_index = entry.lineno - max(entry.getfirstlinesource(), 0)
-
- lines = []
- style = entry._repr_style
- if style is None:
- style = self.style
- if style in ("short", "long"):
- short = style == "short"
- reprargs = self.repr_args(entry) if not short else None
- s = self.get_source(source, line_index, excinfo, short=short)
- lines.extend(s)
- if short:
- message = "in %s" %(entry.name)
- else:
- message = excinfo and excinfo.typename or ""
- path = self._makepath(entry.path)
- filelocrepr = ReprFileLocation(path, entry.lineno+1, message)
- localsrepr = None
- if not short:
- localsrepr = self.repr_locals(entry.locals)
- return ReprEntry(lines, reprargs, localsrepr, filelocrepr, style)
- if excinfo:
- lines.extend(self.get_exconly(excinfo, indent=4))
- return ReprEntry(lines, None, None, None, style)
-
- def _makepath(self, path):
- if not self.abspath:
- try:
- np = py.path.local().bestrelpath(path)
- except OSError:
- return path
- if len(np) < len(str(path)):
- path = np
- return path
-
- def repr_traceback(self, excinfo):
- traceback = excinfo.traceback
- if self.tbfilter:
- traceback = traceback.filter()
- recursionindex = None
- if excinfo.errisinstance(RuntimeError):
- if "maximum recursion depth exceeded" in str(excinfo.value):
- recursionindex = traceback.recursionindex()
- last = traceback[-1]
- entries = []
- extraline = None
- for index, entry in enumerate(traceback):
- einfo = (last == entry) and excinfo or None
- reprentry = self.repr_traceback_entry(entry, einfo)
- entries.append(reprentry)
- if index == recursionindex:
- extraline = "!!! Recursion detected (same locals & position)"
- break
- return ReprTraceback(entries, extraline, style=self.style)
-
- def repr_excinfo(self, excinfo):
- reprtraceback = self.repr_traceback(excinfo)
- reprcrash = excinfo._getreprcrash()
- return ReprExceptionInfo(reprtraceback, reprcrash)
-
-class TerminalRepr:
- def __str__(self):
- s = self.__unicode__()
- if sys.version_info[0] < 3:
- s = s.encode('utf-8')
- return s
-
- def __unicode__(self):
- # FYI this is called from pytest-xdist's serialization of exception
- # information.
- io = py.io.TextIO()
- tw = py.io.TerminalWriter(file=io)
- self.toterminal(tw)
- return io.getvalue().strip()
-
- def __repr__(self):
- return "<%s instance at %0x>" %(self.__class__, id(self))
-
-
-class ReprExceptionInfo(TerminalRepr):
- def __init__(self, reprtraceback, reprcrash):
- self.reprtraceback = reprtraceback
- self.reprcrash = reprcrash
- self.sections = []
-
- def addsection(self, name, content, sep="-"):
- self.sections.append((name, content, sep))
-
- def toterminal(self, tw):
- self.reprtraceback.toterminal(tw)
- for name, content, sep in self.sections:
- tw.sep(sep, name)
- tw.line(content)
-
-class ReprTraceback(TerminalRepr):
- entrysep = "_ "
-
- def __init__(self, reprentries, extraline, style):
- self.reprentries = reprentries
- self.extraline = extraline
- self.style = style
-
- def toterminal(self, tw):
- # the entries might have different styles
- for i, entry in enumerate(self.reprentries):
- if entry.style == "long":
- tw.line("")
- entry.toterminal(tw)
- if i < len(self.reprentries) - 1:
- next_entry = self.reprentries[i+1]
- if entry.style == "long" or \
- entry.style == "short" and next_entry.style == "long":
- tw.sep(self.entrysep)
-
- if self.extraline:
- tw.line(self.extraline)
-
-class ReprTracebackNative(ReprTraceback):
- def __init__(self, tblines):
- self.style = "native"
- self.reprentries = [ReprEntryNative(tblines)]
- self.extraline = None
-
-class ReprEntryNative(TerminalRepr):
- style = "native"
-
- def __init__(self, tblines):
- self.lines = tblines
-
- def toterminal(self, tw):
- tw.write("".join(self.lines))
-
-class ReprEntry(TerminalRepr):
- localssep = "_ "
-
- def __init__(self, lines, reprfuncargs, reprlocals, filelocrepr, style):
- self.lines = lines
- self.reprfuncargs = reprfuncargs
- self.reprlocals = reprlocals
- self.reprfileloc = filelocrepr
- self.style = style
-
- def toterminal(self, tw):
- if self.style == "short":
- self.reprfileloc.toterminal(tw)
- for line in self.lines:
- red = line.startswith("E ")
- tw.line(line, bold=True, red=red)
- #tw.line("")
- return
- if self.reprfuncargs:
- self.reprfuncargs.toterminal(tw)
- for line in self.lines:
- red = line.startswith("E ")
- tw.line(line, bold=True, red=red)
- if self.reprlocals:
- #tw.sep(self.localssep, "Locals")
- tw.line("")
- self.reprlocals.toterminal(tw)
- if self.reprfileloc:
- if self.lines:
- tw.line("")
- self.reprfileloc.toterminal(tw)
-
- def __str__(self):
- return "%s\n%s\n%s" % ("\n".join(self.lines),
- self.reprlocals,
- self.reprfileloc)
-
-class ReprFileLocation(TerminalRepr):
- def __init__(self, path, lineno, message):
- self.path = str(path)
- self.lineno = lineno
- self.message = message
-
- def toterminal(self, tw):
- # filename and lineno output for each entry,
- # using an output format that most editors unterstand
- msg = self.message
- i = msg.find("\n")
- if i != -1:
- msg = msg[:i]
- tw.line("%s:%s: %s" %(self.path, self.lineno, msg))
-
-class ReprLocals(TerminalRepr):
- def __init__(self, lines):
- self.lines = lines
-
- def toterminal(self, tw):
- for line in self.lines:
- tw.line(line)
-
-class ReprFuncArgs(TerminalRepr):
- def __init__(self, args):
- self.args = args
-
- def toterminal(self, tw):
- if self.args:
- linesofar = ""
- for name, value in self.args:
- ns = "%s = %s" %(name, value)
- if len(ns) + len(linesofar) + 2 > tw.fullwidth:
- if linesofar:
- tw.line(linesofar)
- linesofar = ns
- else:
- if linesofar:
- linesofar += ", " + ns
- else:
- linesofar = ns
- if linesofar:
- tw.line(linesofar)
- tw.line("")
-
-
-
-oldbuiltins = {}
-
-def patch_builtins(assertion=True, compile=True):
- """ put compile and AssertionError builtins to Python's builtins. """
- if assertion:
- from _pytest.assertion import reinterpret
- l = oldbuiltins.setdefault('AssertionError', [])
- l.append(py.builtin.builtins.AssertionError)
- py.builtin.builtins.AssertionError = reinterpret.AssertionError
- if compile:
- import _pytest._code
- l = oldbuiltins.setdefault('compile', [])
- l.append(py.builtin.builtins.compile)
- py.builtin.builtins.compile = _pytest._code.compile
-
-def unpatch_builtins(assertion=True, compile=True):
- """ remove compile and AssertionError builtins from Python builtins. """
- if assertion:
- py.builtin.builtins.AssertionError = oldbuiltins['AssertionError'].pop()
- if compile:
- py.builtin.builtins.compile = oldbuiltins['compile'].pop()
-
-def getrawcode(obj, trycall=True):
- """ return code object for given function. """
- try:
- return obj.__code__
- except AttributeError:
- obj = getattr(obj, 'im_func', obj)
- obj = getattr(obj, 'func_code', obj)
- obj = getattr(obj, 'f_code', obj)
- obj = getattr(obj, '__code__', obj)
- if trycall and not hasattr(obj, 'co_firstlineno'):
- if hasattr(obj, '__call__') and not py.std.inspect.isclass(obj):
- x = getrawcode(obj.__call__, trycall=False)
- if hasattr(x, 'co_firstlineno'):
- return x
- return obj
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/_code/source.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/_code/source.py
deleted file mode 100644
index a1521f8a212..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/_code/source.py
+++ /dev/null
@@ -1,421 +0,0 @@
-from __future__ import generators
-
-from bisect import bisect_right
-import sys
-import inspect, tokenize
-import py
-from types import ModuleType
-cpy_compile = compile
-
-try:
- import _ast
- from _ast import PyCF_ONLY_AST as _AST_FLAG
-except ImportError:
- _AST_FLAG = 0
- _ast = None
-
-
-class Source(object):
- """ a immutable object holding a source code fragment,
- possibly deindenting it.
- """
- _compilecounter = 0
- def __init__(self, *parts, **kwargs):
- self.lines = lines = []
- de = kwargs.get('deindent', True)
- rstrip = kwargs.get('rstrip', True)
- for part in parts:
- if not part:
- partlines = []
- if isinstance(part, Source):
- partlines = part.lines
- elif isinstance(part, (tuple, list)):
- partlines = [x.rstrip("\n") for x in part]
- elif isinstance(part, py.builtin._basestring):
- partlines = part.split('\n')
- if rstrip:
- while partlines:
- if partlines[-1].strip():
- break
- partlines.pop()
- else:
- partlines = getsource(part, deindent=de).lines
- if de:
- partlines = deindent(partlines)
- lines.extend(partlines)
-
- def __eq__(self, other):
- try:
- return self.lines == other.lines
- except AttributeError:
- if isinstance(other, str):
- return str(self) == other
- return False
-
- def __getitem__(self, key):
- if isinstance(key, int):
- return self.lines[key]
- else:
- if key.step not in (None, 1):
- raise IndexError("cannot slice a Source with a step")
- return self.__getslice__(key.start, key.stop)
-
- def __len__(self):
- return len(self.lines)
-
- def __getslice__(self, start, end):
- newsource = Source()
- newsource.lines = self.lines[start:end]
- return newsource
-
- def strip(self):
- """ return new source object with trailing
- and leading blank lines removed.
- """
- start, end = 0, len(self)
- while start < end and not self.lines[start].strip():
- start += 1
- while end > start and not self.lines[end-1].strip():
- end -= 1
- source = Source()
- source.lines[:] = self.lines[start:end]
- return source
-
- def putaround(self, before='', after='', indent=' ' * 4):
- """ return a copy of the source object with
- 'before' and 'after' wrapped around it.
- """
- before = Source(before)
- after = Source(after)
- newsource = Source()
- lines = [ (indent + line) for line in self.lines]
- newsource.lines = before.lines + lines + after.lines
- return newsource
-
- def indent(self, indent=' ' * 4):
- """ return a copy of the source object with
- all lines indented by the given indent-string.
- """
- newsource = Source()
- newsource.lines = [(indent+line) for line in self.lines]
- return newsource
-
- def getstatement(self, lineno, assertion=False):
- """ return Source statement which contains the
- given linenumber (counted from 0).
- """
- start, end = self.getstatementrange(lineno, assertion)
- return self[start:end]
-
- def getstatementrange(self, lineno, assertion=False):
- """ return (start, end) tuple which spans the minimal
- statement region which containing the given lineno.
- """
- if not (0 <= lineno < len(self)):
- raise IndexError("lineno out of range")
- ast, start, end = getstatementrange_ast(lineno, self)
- return start, end
-
- def deindent(self, offset=None):
- """ return a new source object deindented by offset.
- If offset is None then guess an indentation offset from
- the first non-blank line. Subsequent lines which have a
- lower indentation offset will be copied verbatim as
- they are assumed to be part of multilines.
- """
- # XXX maybe use the tokenizer to properly handle multiline
- # strings etc.pp?
- newsource = Source()
- newsource.lines[:] = deindent(self.lines, offset)
- return newsource
-
- def isparseable(self, deindent=True):
- """ return True if source is parseable, heuristically
- deindenting it by default.
- """
- try:
- import parser
- except ImportError:
- syntax_checker = lambda x: compile(x, 'asd', 'exec')
- else:
- syntax_checker = parser.suite
-
- if deindent:
- source = str(self.deindent())
- else:
- source = str(self)
- try:
- #compile(source+'\n', "x", "exec")
- syntax_checker(source+'\n')
- except KeyboardInterrupt:
- raise
- except Exception:
- return False
- else:
- return True
-
- def __str__(self):
- return "\n".join(self.lines)
-
- def compile(self, filename=None, mode='exec',
- flag=generators.compiler_flag,
- dont_inherit=0, _genframe=None):
- """ return compiled code object. if filename is None
- invent an artificial filename which displays
- the source/line position of the caller frame.
- """
- if not filename or py.path.local(filename).check(file=0):
- if _genframe is None:
- _genframe = sys._getframe(1) # the caller
- fn,lineno = _genframe.f_code.co_filename, _genframe.f_lineno
- base = "<%d-codegen " % self._compilecounter
- self.__class__._compilecounter += 1
- if not filename:
- filename = base + '%s:%d>' % (fn, lineno)
- else:
- filename = base + '%r %s:%d>' % (filename, fn, lineno)
- source = "\n".join(self.lines) + '\n'
- try:
- co = cpy_compile(source, filename, mode, flag)
- except SyntaxError:
- ex = sys.exc_info()[1]
- # re-represent syntax errors from parsing python strings
- msglines = self.lines[:ex.lineno]
- if ex.offset:
- msglines.append(" "*ex.offset + '^')
- msglines.append("(code was compiled probably from here: %s)" % filename)
- newex = SyntaxError('\n'.join(msglines))
- newex.offset = ex.offset
- newex.lineno = ex.lineno
- newex.text = ex.text
- raise newex
- else:
- if flag & _AST_FLAG:
- return co
- lines = [(x + "\n") for x in self.lines]
- if sys.version_info[0] >= 3:
- # XXX py3's inspect.getsourcefile() checks for a module
- # and a pep302 __loader__ ... we don't have a module
- # at code compile-time so we need to fake it here
- m = ModuleType("_pycodecompile_pseudo_module")
- py.std.inspect.modulesbyfile[filename] = None
- py.std.sys.modules[None] = m
- m.__loader__ = 1
- py.std.linecache.cache[filename] = (1, None, lines, filename)
- return co
-
-#
-# public API shortcut functions
-#
-
-def compile_(source, filename=None, mode='exec', flags=
- generators.compiler_flag, dont_inherit=0):
- """ compile the given source to a raw code object,
- and maintain an internal cache which allows later
- retrieval of the source code for the code object
- and any recursively created code objects.
- """
- if _ast is not None and isinstance(source, _ast.AST):
- # XXX should Source support having AST?
- return cpy_compile(source, filename, mode, flags, dont_inherit)
- _genframe = sys._getframe(1) # the caller
- s = Source(source)
- co = s.compile(filename, mode, flags, _genframe=_genframe)
- return co
-
-
-def getfslineno(obj):
- """ Return source location (path, lineno) for the given object.
- If the source cannot be determined return ("", -1)
- """
- import _pytest._code
- try:
- code = _pytest._code.Code(obj)
- except TypeError:
- try:
- fn = (py.std.inspect.getsourcefile(obj) or
- py.std.inspect.getfile(obj))
- except TypeError:
- return "", -1
-
- fspath = fn and py.path.local(fn) or None
- lineno = -1
- if fspath:
- try:
- _, lineno = findsource(obj)
- except IOError:
- pass
- else:
- fspath = code.path
- lineno = code.firstlineno
- assert isinstance(lineno, int)
- return fspath, lineno
-
-#
-# helper functions
-#
-
-def findsource(obj):
- try:
- sourcelines, lineno = py.std.inspect.findsource(obj)
- except py.builtin._sysex:
- raise
- except:
- return None, -1
- source = Source()
- source.lines = [line.rstrip() for line in sourcelines]
- return source, lineno
-
-def getsource(obj, **kwargs):
- import _pytest._code
- obj = _pytest._code.getrawcode(obj)
- try:
- strsrc = inspect.getsource(obj)
- except IndentationError:
- strsrc = "\"Buggy python version consider upgrading, cannot get source\""
- assert isinstance(strsrc, str)
- return Source(strsrc, **kwargs)
-
-def deindent(lines, offset=None):
- if offset is None:
- for line in lines:
- line = line.expandtabs()
- s = line.lstrip()
- if s:
- offset = len(line)-len(s)
- break
- else:
- offset = 0
- if offset == 0:
- return list(lines)
- newlines = []
- def readline_generator(lines):
- for line in lines:
- yield line + '\n'
- while True:
- yield ''
-
- it = readline_generator(lines)
-
- try:
- for _, _, (sline, _), (eline, _), _ in tokenize.generate_tokens(lambda: next(it)):
- if sline > len(lines):
- break # End of input reached
- if sline > len(newlines):
- line = lines[sline - 1].expandtabs()
- if line.lstrip() and line[:offset].isspace():
- line = line[offset:] # Deindent
- newlines.append(line)
-
- for i in range(sline, eline):
- # Don't deindent continuing lines of
- # multiline tokens (i.e. multiline strings)
- newlines.append(lines[i])
- except (IndentationError, tokenize.TokenError):
- pass
- # Add any lines we didn't see. E.g. if an exception was raised.
- newlines.extend(lines[len(newlines):])
- return newlines
-
-
-def get_statement_startend2(lineno, node):
- import ast
- # flatten all statements and except handlers into one lineno-list
- # AST's line numbers start indexing at 1
- l = []
- for x in ast.walk(node):
- if isinstance(x, _ast.stmt) or isinstance(x, _ast.ExceptHandler):
- l.append(x.lineno - 1)
- for name in "finalbody", "orelse":
- val = getattr(x, name, None)
- if val:
- # treat the finally/orelse part as its own statement
- l.append(val[0].lineno - 1 - 1)
- l.sort()
- insert_index = bisect_right(l, lineno)
- start = l[insert_index - 1]
- if insert_index >= len(l):
- end = None
- else:
- end = l[insert_index]
- return start, end
-
-
-def getstatementrange_ast(lineno, source, assertion=False, astnode=None):
- if astnode is None:
- content = str(source)
- if sys.version_info < (2,7):
- content += "\n"
- try:
- astnode = compile(content, "source", "exec", 1024) # 1024 for AST
- except ValueError:
- start, end = getstatementrange_old(lineno, source, assertion)
- return None, start, end
- start, end = get_statement_startend2(lineno, astnode)
- # we need to correct the end:
- # - ast-parsing strips comments
- # - there might be empty lines
- # - we might have lesser indented code blocks at the end
- if end is None:
- end = len(source.lines)
-
- if end > start + 1:
- # make sure we don't span differently indented code blocks
- # by using the BlockFinder helper used which inspect.getsource() uses itself
- block_finder = inspect.BlockFinder()
- # if we start with an indented line, put blockfinder to "started" mode
- block_finder.started = source.lines[start][0].isspace()
- it = ((x + "\n") for x in source.lines[start:end])
- try:
- for tok in tokenize.generate_tokens(lambda: next(it)):
- block_finder.tokeneater(*tok)
- except (inspect.EndOfBlock, IndentationError):
- end = block_finder.last + start
- except Exception:
- pass
-
- # the end might still point to a comment or empty line, correct it
- while end:
- line = source.lines[end - 1].lstrip()
- if line.startswith("#") or not line:
- end -= 1
- else:
- break
- return astnode, start, end
-
-
-def getstatementrange_old(lineno, source, assertion=False):
- """ return (start, end) tuple which spans the minimal
- statement region which containing the given lineno.
- raise an IndexError if no such statementrange can be found.
- """
- # XXX this logic is only used on python2.4 and below
- # 1. find the start of the statement
- from codeop import compile_command
- for start in range(lineno, -1, -1):
- if assertion:
- line = source.lines[start]
- # the following lines are not fully tested, change with care
- if 'super' in line and 'self' in line and '__init__' in line:
- raise IndexError("likely a subclass")
- if "assert" not in line and "raise" not in line:
- continue
- trylines = source.lines[start:lineno+1]
- # quick hack to prepare parsing an indented line with
- # compile_command() (which errors on "return" outside defs)
- trylines.insert(0, 'def xxx():')
- trysource = '\n '.join(trylines)
- # ^ space here
- try:
- compile_command(trysource)
- except (SyntaxError, OverflowError, ValueError):
- continue
-
- # 2. find the end of the statement
- for end in range(lineno+1, len(source)+1):
- trysource = source[start:end]
- if trysource.isparseable():
- return start, end
- raise SyntaxError("no valid source range around line %d " % (lineno,))
-
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/_pluggy.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/_pluggy.py
deleted file mode 100644
index 87d32cf8dd1..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/_pluggy.py
+++ /dev/null
@@ -1,11 +0,0 @@
-"""
-imports symbols from vendored "pluggy" if available, otherwise
-falls back to importing "pluggy" from the default namespace.
-"""
-
-try:
- from _pytest.vendored_packages.pluggy import * # noqa
- from _pytest.vendored_packages.pluggy import __version__ # noqa
-except ImportError:
- from pluggy import * # noqa
- from pluggy import __version__ # noqa
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/assertion/__init__.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/assertion/__init__.py
deleted file mode 100644
index 6921deb2a60..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/assertion/__init__.py
+++ /dev/null
@@ -1,176 +0,0 @@
-"""
-support for presenting detailed information in failing assertions.
-"""
-import py
-import os
-import sys
-from _pytest.monkeypatch import monkeypatch
-from _pytest.assertion import util
-
-
-def pytest_addoption(parser):
- group = parser.getgroup("debugconfig")
- group.addoption('--assert',
- action="store",
- dest="assertmode",
- choices=("rewrite", "reinterp", "plain",),
- default="rewrite",
- metavar="MODE",
- help="""control assertion debugging tools. 'plain'
- performs no assertion debugging. 'reinterp'
- reinterprets assert statements after they failed
- to provide assertion expression information.
- 'rewrite' (the default) rewrites assert
- statements in test modules on import to
- provide assert expression information. """)
- group.addoption('--no-assert',
- action="store_true",
- default=False,
- dest="noassert",
- help="DEPRECATED equivalent to --assert=plain")
- group.addoption('--nomagic', '--no-magic',
- action="store_true",
- default=False,
- help="DEPRECATED equivalent to --assert=plain")
-
-
-class AssertionState:
- """State for the assertion plugin."""
-
- def __init__(self, config, mode):
- self.mode = mode
- self.trace = config.trace.root.get("assertion")
-
-
-def pytest_configure(config):
- mode = config.getvalue("assertmode")
- if config.getvalue("noassert") or config.getvalue("nomagic"):
- mode = "plain"
- if mode == "rewrite":
- try:
- import ast # noqa
- except ImportError:
- mode = "reinterp"
- else:
- # Both Jython and CPython 2.6.0 have AST bugs that make the
- # assertion rewriting hook malfunction.
- if (sys.platform.startswith('java') or
- sys.version_info[:3] == (2, 6, 0)):
- mode = "reinterp"
- if mode != "plain":
- _load_modules(mode)
- m = monkeypatch()
- config._cleanup.append(m.undo)
- m.setattr(py.builtin.builtins, 'AssertionError',
- reinterpret.AssertionError) # noqa
- hook = None
- if mode == "rewrite":
- hook = rewrite.AssertionRewritingHook() # noqa
- sys.meta_path.insert(0, hook)
- warn_about_missing_assertion(mode)
- config._assertstate = AssertionState(config, mode)
- config._assertstate.hook = hook
- config._assertstate.trace("configured with mode set to %r" % (mode,))
- def undo():
- hook = config._assertstate.hook
- if hook is not None and hook in sys.meta_path:
- sys.meta_path.remove(hook)
- config.add_cleanup(undo)
-
-
-def pytest_collection(session):
- # this hook is only called when test modules are collected
- # so for example not in the master process of pytest-xdist
- # (which does not collect test modules)
- hook = session.config._assertstate.hook
- if hook is not None:
- hook.set_session(session)
-
-
-def _running_on_ci():
- """Check if we're currently running on a CI system."""
- env_vars = ['CI', 'BUILD_NUMBER']
- return any(var in os.environ for var in env_vars)
-
-
-def pytest_runtest_setup(item):
- """Setup the pytest_assertrepr_compare hook
-
- The newinterpret and rewrite modules will use util._reprcompare if
- it exists to use custom reporting via the
- pytest_assertrepr_compare hook. This sets up this custom
- comparison for the test.
- """
- def callbinrepr(op, left, right):
- """Call the pytest_assertrepr_compare hook and prepare the result
-
- This uses the first result from the hook and then ensures the
- following:
- * Overly verbose explanations are dropped unless -vv was used or
- running on a CI.
- * Embedded newlines are escaped to help util.format_explanation()
- later.
- * If the rewrite mode is used embedded %-characters are replaced
- to protect later % formatting.
-
- The result can be formatted by util.format_explanation() for
- pretty printing.
- """
- hook_result = item.ihook.pytest_assertrepr_compare(
- config=item.config, op=op, left=left, right=right)
- for new_expl in hook_result:
- if new_expl:
- if (sum(len(p) for p in new_expl[1:]) > 80*8 and
- item.config.option.verbose < 2 and
- not _running_on_ci()):
- show_max = 10
- truncated_lines = len(new_expl) - show_max
- new_expl[show_max:] = [py.builtin._totext(
- 'Detailed information truncated (%d more lines)'
- ', use "-vv" to show' % truncated_lines)]
- new_expl = [line.replace("\n", "\\n") for line in new_expl]
- res = py.builtin._totext("\n~").join(new_expl)
- if item.config.getvalue("assertmode") == "rewrite":
- res = res.replace("%", "%%")
- return res
- util._reprcompare = callbinrepr
-
-
-def pytest_runtest_teardown(item):
- util._reprcompare = None
-
-
-def pytest_sessionfinish(session):
- hook = session.config._assertstate.hook
- if hook is not None:
- hook.session = None
-
-
-def _load_modules(mode):
- """Lazily import assertion related code."""
- global rewrite, reinterpret
- from _pytest.assertion import reinterpret # noqa
- if mode == "rewrite":
- from _pytest.assertion import rewrite # noqa
-
-
-def warn_about_missing_assertion(mode):
- try:
- assert False
- except AssertionError:
- pass
- else:
- if mode == "rewrite":
- specifically = ("assertions which are not in test modules "
- "will be ignored")
- else:
- specifically = "failing tests may report as passing"
-
- sys.stderr.write("WARNING: " + specifically +
- " because assert statements are not executed "
- "by the underlying Python interpreter "
- "(are you using python -O?)\n")
-
-
-# Expose this plugin's implementation for the pytest_assertrepr_compare hook
-pytest_assertrepr_compare = util.assertrepr_compare
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/assertion/reinterpret.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/assertion/reinterpret.py
deleted file mode 100644
index f4262c3aced..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/assertion/reinterpret.py
+++ /dev/null
@@ -1,407 +0,0 @@
-"""
-Find intermediate evalutation results in assert statements through builtin AST.
-"""
-import ast
-import sys
-
-import _pytest._code
-import py
-from _pytest.assertion import util
-u = py.builtin._totext
-
-
-class AssertionError(util.BuiltinAssertionError):
- def __init__(self, *args):
- util.BuiltinAssertionError.__init__(self, *args)
- if args:
- # on Python2.6 we get len(args)==2 for: assert 0, (x,y)
- # on Python2.7 and above we always get len(args) == 1
- # with args[0] being the (x,y) tuple.
- if len(args) > 1:
- toprint = args
- else:
- toprint = args[0]
- try:
- self.msg = u(toprint)
- except Exception:
- self.msg = u(
- "<[broken __repr__] %s at %0xd>"
- % (toprint.__class__, id(toprint)))
- else:
- f = _pytest._code.Frame(sys._getframe(1))
- try:
- source = f.code.fullsource
- if source is not None:
- try:
- source = source.getstatement(f.lineno, assertion=True)
- except IndexError:
- source = None
- else:
- source = str(source.deindent()).strip()
- except py.error.ENOENT:
- source = None
- # this can also occur during reinterpretation, when the
- # co_filename is set to "<run>".
- if source:
- self.msg = reinterpret(source, f, should_fail=True)
- else:
- self.msg = "<could not determine information>"
- if not self.args:
- self.args = (self.msg,)
-
-if sys.version_info > (3, 0):
- AssertionError.__module__ = "builtins"
-
-if sys.platform.startswith("java"):
- # See http://bugs.jython.org/issue1497
- _exprs = ("BoolOp", "BinOp", "UnaryOp", "Lambda", "IfExp", "Dict",
- "ListComp", "GeneratorExp", "Yield", "Compare", "Call",
- "Repr", "Num", "Str", "Attribute", "Subscript", "Name",
- "List", "Tuple")
- _stmts = ("FunctionDef", "ClassDef", "Return", "Delete", "Assign",
- "AugAssign", "Print", "For", "While", "If", "With", "Raise",
- "TryExcept", "TryFinally", "Assert", "Import", "ImportFrom",
- "Exec", "Global", "Expr", "Pass", "Break", "Continue")
- _expr_nodes = set(getattr(ast, name) for name in _exprs)
- _stmt_nodes = set(getattr(ast, name) for name in _stmts)
- def _is_ast_expr(node):
- return node.__class__ in _expr_nodes
- def _is_ast_stmt(node):
- return node.__class__ in _stmt_nodes
-else:
- def _is_ast_expr(node):
- return isinstance(node, ast.expr)
- def _is_ast_stmt(node):
- return isinstance(node, ast.stmt)
-
-try:
- _Starred = ast.Starred
-except AttributeError:
- # Python 2. Define a dummy class so isinstance() will always be False.
- class _Starred(object): pass
-
-
-class Failure(Exception):
- """Error found while interpreting AST."""
-
- def __init__(self, explanation=""):
- self.cause = sys.exc_info()
- self.explanation = explanation
-
-
-def reinterpret(source, frame, should_fail=False):
- mod = ast.parse(source)
- visitor = DebugInterpreter(frame)
- try:
- visitor.visit(mod)
- except Failure:
- failure = sys.exc_info()[1]
- return getfailure(failure)
- if should_fail:
- return ("(assertion failed, but when it was re-run for "
- "printing intermediate values, it did not fail. Suggestions: "
- "compute assert expression before the assert or use --assert=plain)")
-
-def run(offending_line, frame=None):
- if frame is None:
- frame = _pytest._code.Frame(sys._getframe(1))
- return reinterpret(offending_line, frame)
-
-def getfailure(e):
- explanation = util.format_explanation(e.explanation)
- value = e.cause[1]
- if str(value):
- lines = explanation.split('\n')
- lines[0] += " << %s" % (value,)
- explanation = '\n'.join(lines)
- text = "%s: %s" % (e.cause[0].__name__, explanation)
- if text.startswith('AssertionError: assert '):
- text = text[16:]
- return text
-
-operator_map = {
- ast.BitOr : "|",
- ast.BitXor : "^",
- ast.BitAnd : "&",
- ast.LShift : "<<",
- ast.RShift : ">>",
- ast.Add : "+",
- ast.Sub : "-",
- ast.Mult : "*",
- ast.Div : "/",
- ast.FloorDiv : "//",
- ast.Mod : "%",
- ast.Eq : "==",
- ast.NotEq : "!=",
- ast.Lt : "<",
- ast.LtE : "<=",
- ast.Gt : ">",
- ast.GtE : ">=",
- ast.Pow : "**",
- ast.Is : "is",
- ast.IsNot : "is not",
- ast.In : "in",
- ast.NotIn : "not in"
-}
-
-unary_map = {
- ast.Not : "not %s",
- ast.Invert : "~%s",
- ast.USub : "-%s",
- ast.UAdd : "+%s"
-}
-
-
-class DebugInterpreter(ast.NodeVisitor):
- """Interpret AST nodes to gleam useful debugging information. """
-
- def __init__(self, frame):
- self.frame = frame
-
- def generic_visit(self, node):
- # Fallback when we don't have a special implementation.
- if _is_ast_expr(node):
- mod = ast.Expression(node)
- co = self._compile(mod)
- try:
- result = self.frame.eval(co)
- except Exception:
- raise Failure()
- explanation = self.frame.repr(result)
- return explanation, result
- elif _is_ast_stmt(node):
- mod = ast.Module([node])
- co = self._compile(mod, "exec")
- try:
- self.frame.exec_(co)
- except Exception:
- raise Failure()
- return None, None
- else:
- raise AssertionError("can't handle %s" %(node,))
-
- def _compile(self, source, mode="eval"):
- return compile(source, "<assertion interpretation>", mode)
-
- def visit_Expr(self, expr):
- return self.visit(expr.value)
-
- def visit_Module(self, mod):
- for stmt in mod.body:
- self.visit(stmt)
-
- def visit_Name(self, name):
- explanation, result = self.generic_visit(name)
- # See if the name is local.
- source = "%r in locals() is not globals()" % (name.id,)
- co = self._compile(source)
- try:
- local = self.frame.eval(co)
- except Exception:
- # have to assume it isn't
- local = None
- if local is None or not self.frame.is_true(local):
- return name.id, result
- return explanation, result
-
- def visit_Compare(self, comp):
- left = comp.left
- left_explanation, left_result = self.visit(left)
- for op, next_op in zip(comp.ops, comp.comparators):
- next_explanation, next_result = self.visit(next_op)
- op_symbol = operator_map[op.__class__]
- explanation = "%s %s %s" % (left_explanation, op_symbol,
- next_explanation)
- source = "__exprinfo_left %s __exprinfo_right" % (op_symbol,)
- co = self._compile(source)
- try:
- result = self.frame.eval(co, __exprinfo_left=left_result,
- __exprinfo_right=next_result)
- except Exception:
- raise Failure(explanation)
- try:
- if not self.frame.is_true(result):
- break
- except KeyboardInterrupt:
- raise
- except:
- break
- left_explanation, left_result = next_explanation, next_result
-
- if util._reprcompare is not None:
- res = util._reprcompare(op_symbol, left_result, next_result)
- if res:
- explanation = res
- return explanation, result
-
- def visit_BoolOp(self, boolop):
- is_or = isinstance(boolop.op, ast.Or)
- explanations = []
- for operand in boolop.values:
- explanation, result = self.visit(operand)
- explanations.append(explanation)
- if result == is_or:
- break
- name = is_or and " or " or " and "
- explanation = "(" + name.join(explanations) + ")"
- return explanation, result
-
- def visit_UnaryOp(self, unary):
- pattern = unary_map[unary.op.__class__]
- operand_explanation, operand_result = self.visit(unary.operand)
- explanation = pattern % (operand_explanation,)
- co = self._compile(pattern % ("__exprinfo_expr",))
- try:
- result = self.frame.eval(co, __exprinfo_expr=operand_result)
- except Exception:
- raise Failure(explanation)
- return explanation, result
-
- def visit_BinOp(self, binop):
- left_explanation, left_result = self.visit(binop.left)
- right_explanation, right_result = self.visit(binop.right)
- symbol = operator_map[binop.op.__class__]
- explanation = "(%s %s %s)" % (left_explanation, symbol,
- right_explanation)
- source = "__exprinfo_left %s __exprinfo_right" % (symbol,)
- co = self._compile(source)
- try:
- result = self.frame.eval(co, __exprinfo_left=left_result,
- __exprinfo_right=right_result)
- except Exception:
- raise Failure(explanation)
- return explanation, result
-
- def visit_Call(self, call):
- func_explanation, func = self.visit(call.func)
- arg_explanations = []
- ns = {"__exprinfo_func" : func}
- arguments = []
- for arg in call.args:
- arg_explanation, arg_result = self.visit(arg)
- if isinstance(arg, _Starred):
- arg_name = "__exprinfo_star"
- ns[arg_name] = arg_result
- arguments.append("*%s" % (arg_name,))
- arg_explanations.append("*%s" % (arg_explanation,))
- else:
- arg_name = "__exprinfo_%s" % (len(ns),)
- ns[arg_name] = arg_result
- arguments.append(arg_name)
- arg_explanations.append(arg_explanation)
- for keyword in call.keywords:
- arg_explanation, arg_result = self.visit(keyword.value)
- if keyword.arg:
- arg_name = "__exprinfo_%s" % (len(ns),)
- keyword_source = "%s=%%s" % (keyword.arg)
- arguments.append(keyword_source % (arg_name,))
- arg_explanations.append(keyword_source % (arg_explanation,))
- else:
- arg_name = "__exprinfo_kwds"
- arguments.append("**%s" % (arg_name,))
- arg_explanations.append("**%s" % (arg_explanation,))
-
- ns[arg_name] = arg_result
-
- if getattr(call, 'starargs', None):
- arg_explanation, arg_result = self.visit(call.starargs)
- arg_name = "__exprinfo_star"
- ns[arg_name] = arg_result
- arguments.append("*%s" % (arg_name,))
- arg_explanations.append("*%s" % (arg_explanation,))
-
- if getattr(call, 'kwargs', None):
- arg_explanation, arg_result = self.visit(call.kwargs)
- arg_name = "__exprinfo_kwds"
- ns[arg_name] = arg_result
- arguments.append("**%s" % (arg_name,))
- arg_explanations.append("**%s" % (arg_explanation,))
- args_explained = ", ".join(arg_explanations)
- explanation = "%s(%s)" % (func_explanation, args_explained)
- args = ", ".join(arguments)
- source = "__exprinfo_func(%s)" % (args,)
- co = self._compile(source)
- try:
- result = self.frame.eval(co, **ns)
- except Exception:
- raise Failure(explanation)
- pattern = "%s\n{%s = %s\n}"
- rep = self.frame.repr(result)
- explanation = pattern % (rep, rep, explanation)
- return explanation, result
-
- def _is_builtin_name(self, name):
- pattern = "%r not in globals() and %r not in locals()"
- source = pattern % (name.id, name.id)
- co = self._compile(source)
- try:
- return self.frame.eval(co)
- except Exception:
- return False
-
- def visit_Attribute(self, attr):
- if not isinstance(attr.ctx, ast.Load):
- return self.generic_visit(attr)
- source_explanation, source_result = self.visit(attr.value)
- explanation = "%s.%s" % (source_explanation, attr.attr)
- source = "__exprinfo_expr.%s" % (attr.attr,)
- co = self._compile(source)
- try:
- try:
- result = self.frame.eval(co, __exprinfo_expr=source_result)
- except AttributeError:
- # Maybe the attribute name needs to be mangled?
- if not attr.attr.startswith("__") or attr.attr.endswith("__"):
- raise
- source = "getattr(__exprinfo_expr.__class__, '__name__', '')"
- co = self._compile(source)
- class_name = self.frame.eval(co, __exprinfo_expr=source_result)
- mangled_attr = "_" + class_name + attr.attr
- source = "__exprinfo_expr.%s" % (mangled_attr,)
- co = self._compile(source)
- result = self.frame.eval(co, __exprinfo_expr=source_result)
- except Exception:
- raise Failure(explanation)
- explanation = "%s\n{%s = %s.%s\n}" % (self.frame.repr(result),
- self.frame.repr(result),
- source_explanation, attr.attr)
- # Check if the attr is from an instance.
- source = "%r in getattr(__exprinfo_expr, '__dict__', {})"
- source = source % (attr.attr,)
- co = self._compile(source)
- try:
- from_instance = self.frame.eval(co, __exprinfo_expr=source_result)
- except Exception:
- from_instance = None
- if from_instance is None or self.frame.is_true(from_instance):
- rep = self.frame.repr(result)
- pattern = "%s\n{%s = %s\n}"
- explanation = pattern % (rep, rep, explanation)
- return explanation, result
-
- def visit_Assert(self, assrt):
- test_explanation, test_result = self.visit(assrt.test)
- explanation = "assert %s" % (test_explanation,)
- if not self.frame.is_true(test_result):
- try:
- raise util.BuiltinAssertionError
- except Exception:
- raise Failure(explanation)
- return explanation, test_result
-
- def visit_Assign(self, assign):
- value_explanation, value_result = self.visit(assign.value)
- explanation = "... = %s" % (value_explanation,)
- name = ast.Name("__exprinfo_expr", ast.Load(),
- lineno=assign.value.lineno,
- col_offset=assign.value.col_offset)
- new_assign = ast.Assign(assign.targets, name, lineno=assign.lineno,
- col_offset=assign.col_offset)
- mod = ast.Module([new_assign])
- co = self._compile(mod, "exec")
- try:
- self.frame.exec_(co, __exprinfo_expr=value_result)
- except Exception:
- raise Failure(explanation)
- return explanation, value_result
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/assertion/rewrite.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/assertion/rewrite.py
deleted file mode 100644
index 14b8e49db2b..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/assertion/rewrite.py
+++ /dev/null
@@ -1,885 +0,0 @@
-"""Rewrite assertion AST to produce nice error messages"""
-
-import ast
-import errno
-import itertools
-import imp
-import marshal
-import os
-import re
-import struct
-import sys
-import types
-
-import py
-from _pytest.assertion import util
-
-
-# pytest caches rewritten pycs in __pycache__.
-if hasattr(imp, "get_tag"):
- PYTEST_TAG = imp.get_tag() + "-PYTEST"
-else:
- if hasattr(sys, "pypy_version_info"):
- impl = "pypy"
- elif sys.platform == "java":
- impl = "jython"
- else:
- impl = "cpython"
- ver = sys.version_info
- PYTEST_TAG = "%s-%s%s-PYTEST" % (impl, ver[0], ver[1])
- del ver, impl
-
-PYC_EXT = ".py" + (__debug__ and "c" or "o")
-PYC_TAIL = "." + PYTEST_TAG + PYC_EXT
-
-REWRITE_NEWLINES = sys.version_info[:2] != (2, 7) and sys.version_info < (3, 2)
-ASCII_IS_DEFAULT_ENCODING = sys.version_info[0] < 3
-
-if sys.version_info >= (3,5):
- ast_Call = ast.Call
-else:
- ast_Call = lambda a,b,c: ast.Call(a, b, c, None, None)
-
-
-class AssertionRewritingHook(object):
- """PEP302 Import hook which rewrites asserts."""
-
- def __init__(self):
- self.session = None
- self.modules = {}
- self._register_with_pkg_resources()
-
- def set_session(self, session):
- self.fnpats = session.config.getini("python_files")
- self.session = session
-
- def find_module(self, name, path=None):
- if self.session is None:
- return None
- sess = self.session
- state = sess.config._assertstate
- state.trace("find_module called for: %s" % name)
- names = name.rsplit(".", 1)
- lastname = names[-1]
- pth = None
- if path is not None:
- # Starting with Python 3.3, path is a _NamespacePath(), which
- # causes problems if not converted to list.
- path = list(path)
- if len(path) == 1:
- pth = path[0]
- if pth is None:
- try:
- fd, fn, desc = imp.find_module(lastname, path)
- except ImportError:
- return None
- if fd is not None:
- fd.close()
- tp = desc[2]
- if tp == imp.PY_COMPILED:
- if hasattr(imp, "source_from_cache"):
- fn = imp.source_from_cache(fn)
- else:
- fn = fn[:-1]
- elif tp != imp.PY_SOURCE:
- # Don't know what this is.
- return None
- else:
- fn = os.path.join(pth, name.rpartition(".")[2] + ".py")
- fn_pypath = py.path.local(fn)
- # Is this a test file?
- if not sess.isinitpath(fn):
- # We have to be very careful here because imports in this code can
- # trigger a cycle.
- self.session = None
- try:
- for pat in self.fnpats:
- if fn_pypath.fnmatch(pat):
- state.trace("matched test file %r" % (fn,))
- break
- else:
- return None
- finally:
- self.session = sess
- else:
- state.trace("matched test file (was specified on cmdline): %r" %
- (fn,))
- # The requested module looks like a test file, so rewrite it. This is
- # the most magical part of the process: load the source, rewrite the
- # asserts, and load the rewritten source. We also cache the rewritten
- # module code in a special pyc. We must be aware of the possibility of
- # concurrent pytest processes rewriting and loading pycs. To avoid
- # tricky race conditions, we maintain the following invariant: The
- # cached pyc is always a complete, valid pyc. Operations on it must be
- # atomic. POSIX's atomic rename comes in handy.
- write = not sys.dont_write_bytecode
- cache_dir = os.path.join(fn_pypath.dirname, "__pycache__")
- if write:
- try:
- os.mkdir(cache_dir)
- except OSError:
- e = sys.exc_info()[1].errno
- if e == errno.EEXIST:
- # Either the __pycache__ directory already exists (the
- # common case) or it's blocked by a non-dir node. In the
- # latter case, we'll ignore it in _write_pyc.
- pass
- elif e in [errno.ENOENT, errno.ENOTDIR]:
- # One of the path components was not a directory, likely
- # because we're in a zip file.
- write = False
- elif e in [errno.EACCES, errno.EROFS, errno.EPERM]:
- state.trace("read only directory: %r" % fn_pypath.dirname)
- write = False
- else:
- raise
- cache_name = fn_pypath.basename[:-3] + PYC_TAIL
- pyc = os.path.join(cache_dir, cache_name)
- # Notice that even if we're in a read-only directory, I'm going
- # to check for a cached pyc. This may not be optimal...
- co = _read_pyc(fn_pypath, pyc, state.trace)
- if co is None:
- state.trace("rewriting %r" % (fn,))
- source_stat, co = _rewrite_test(state, fn_pypath)
- if co is None:
- # Probably a SyntaxError in the test.
- return None
- if write:
- _make_rewritten_pyc(state, source_stat, pyc, co)
- else:
- state.trace("found cached rewritten pyc for %r" % (fn,))
- self.modules[name] = co, pyc
- return self
-
- def load_module(self, name):
- # If there is an existing module object named 'fullname' in
- # sys.modules, the loader must use that existing module. (Otherwise,
- # the reload() builtin will not work correctly.)
- if name in sys.modules:
- return sys.modules[name]
-
- co, pyc = self.modules.pop(name)
- # I wish I could just call imp.load_compiled here, but __file__ has to
- # be set properly. In Python 3.2+, this all would be handled correctly
- # by load_compiled.
- mod = sys.modules[name] = imp.new_module(name)
- try:
- mod.__file__ = co.co_filename
- # Normally, this attribute is 3.2+.
- mod.__cached__ = pyc
- mod.__loader__ = self
- py.builtin.exec_(co, mod.__dict__)
- except:
- del sys.modules[name]
- raise
- return sys.modules[name]
-
-
-
- def is_package(self, name):
- try:
- fd, fn, desc = imp.find_module(name)
- except ImportError:
- return False
- if fd is not None:
- fd.close()
- tp = desc[2]
- return tp == imp.PKG_DIRECTORY
-
- @classmethod
- def _register_with_pkg_resources(cls):
- """
- Ensure package resources can be loaded from this loader. May be called
- multiple times, as the operation is idempotent.
- """
- try:
- import pkg_resources
- # access an attribute in case a deferred importer is present
- pkg_resources.__name__
- except ImportError:
- return
-
- # Since pytest tests are always located in the file system, the
- # DefaultProvider is appropriate.
- pkg_resources.register_loader_type(cls, pkg_resources.DefaultProvider)
-
- def get_data(self, pathname):
- """Optional PEP302 get_data API.
- """
- with open(pathname, 'rb') as f:
- return f.read()
-
-
-def _write_pyc(state, co, source_stat, pyc):
- # Technically, we don't have to have the same pyc format as
- # (C)Python, since these "pycs" should never be seen by builtin
- # import. However, there's little reason deviate, and I hope
- # sometime to be able to use imp.load_compiled to load them. (See
- # the comment in load_module above.)
- try:
- fp = open(pyc, "wb")
- except IOError:
- err = sys.exc_info()[1].errno
- state.trace("error writing pyc file at %s: errno=%s" %(pyc, err))
- # we ignore any failure to write the cache file
- # there are many reasons, permission-denied, __pycache__ being a
- # file etc.
- return False
- try:
- fp.write(imp.get_magic())
- mtime = int(source_stat.mtime)
- size = source_stat.size & 0xFFFFFFFF
- fp.write(struct.pack("<ll", mtime, size))
- marshal.dump(co, fp)
- finally:
- fp.close()
- return True
-
-RN = "\r\n".encode("utf-8")
-N = "\n".encode("utf-8")
-
-cookie_re = re.compile(r"^[ \t\f]*#.*coding[:=][ \t]*[-\w.]+")
-BOM_UTF8 = '\xef\xbb\xbf'
-
-def _rewrite_test(state, fn):
- """Try to read and rewrite *fn* and return the code object."""
- try:
- stat = fn.stat()
- source = fn.read("rb")
- except EnvironmentError:
- return None, None
- if ASCII_IS_DEFAULT_ENCODING:
- # ASCII is the default encoding in Python 2. Without a coding
- # declaration, Python 2 will complain about any bytes in the file
- # outside the ASCII range. Sadly, this behavior does not extend to
- # compile() or ast.parse(), which prefer to interpret the bytes as
- # latin-1. (At least they properly handle explicit coding cookies.) To
- # preserve this error behavior, we could force ast.parse() to use ASCII
- # as the encoding by inserting a coding cookie. Unfortunately, that
- # messes up line numbers. Thus, we have to check ourselves if anything
- # is outside the ASCII range in the case no encoding is explicitly
- # declared. For more context, see issue #269. Yay for Python 3 which
- # gets this right.
- end1 = source.find("\n")
- end2 = source.find("\n", end1 + 1)
- if (not source.startswith(BOM_UTF8) and
- cookie_re.match(source[0:end1]) is None and
- cookie_re.match(source[end1 + 1:end2]) is None):
- if hasattr(state, "_indecode"):
- # encodings imported us again, so don't rewrite.
- return None, None
- state._indecode = True
- try:
- try:
- source.decode("ascii")
- except UnicodeDecodeError:
- # Let it fail in real import.
- return None, None
- finally:
- del state._indecode
- # On Python versions which are not 2.7 and less than or equal to 3.1, the
- # parser expects *nix newlines.
- if REWRITE_NEWLINES:
- source = source.replace(RN, N) + N
- try:
- tree = ast.parse(source)
- except SyntaxError:
- # Let this pop up again in the real import.
- state.trace("failed to parse: %r" % (fn,))
- return None, None
- rewrite_asserts(tree)
- try:
- co = compile(tree, fn.strpath, "exec")
- except SyntaxError:
- # It's possible that this error is from some bug in the
- # assertion rewriting, but I don't know of a fast way to tell.
- state.trace("failed to compile: %r" % (fn,))
- return None, None
- return stat, co
-
-def _make_rewritten_pyc(state, source_stat, pyc, co):
- """Try to dump rewritten code to *pyc*."""
- if sys.platform.startswith("win"):
- # Windows grants exclusive access to open files and doesn't have atomic
- # rename, so just write into the final file.
- _write_pyc(state, co, source_stat, pyc)
- else:
- # When not on windows, assume rename is atomic. Dump the code object
- # into a file specific to this process and atomically replace it.
- proc_pyc = pyc + "." + str(os.getpid())
- if _write_pyc(state, co, source_stat, proc_pyc):
- os.rename(proc_pyc, pyc)
-
-def _read_pyc(source, pyc, trace=lambda x: None):
- """Possibly read a pytest pyc containing rewritten code.
-
- Return rewritten code if successful or None if not.
- """
- try:
- fp = open(pyc, "rb")
- except IOError:
- return None
- with fp:
- try:
- mtime = int(source.mtime())
- size = source.size()
- data = fp.read(12)
- except EnvironmentError as e:
- trace('_read_pyc(%s): EnvironmentError %s' % (source, e))
- return None
- # Check for invalid or out of date pyc file.
- if (len(data) != 12 or data[:4] != imp.get_magic() or
- struct.unpack("<ll", data[4:]) != (mtime, size)):
- trace('_read_pyc(%s): invalid or out of date pyc' % source)
- return None
- try:
- co = marshal.load(fp)
- except Exception as e:
- trace('_read_pyc(%s): marshal.load error %s' % (source, e))
- return None
- if not isinstance(co, types.CodeType):
- trace('_read_pyc(%s): not a code object' % source)
- return None
- return co
-
-
-def rewrite_asserts(mod):
- """Rewrite the assert statements in mod."""
- AssertionRewriter().run(mod)
-
-
-def _saferepr(obj):
- """Get a safe repr of an object for assertion error messages.
-
- The assertion formatting (util.format_explanation()) requires
- newlines to be escaped since they are a special character for it.
- Normally assertion.util.format_explanation() does this but for a
- custom repr it is possible to contain one of the special escape
- sequences, especially '\n{' and '\n}' are likely to be present in
- JSON reprs.
-
- """
- repr = py.io.saferepr(obj)
- if py.builtin._istext(repr):
- t = py.builtin.text
- else:
- t = py.builtin.bytes
- return repr.replace(t("\n"), t("\\n"))
-
-
-from _pytest.assertion.util import format_explanation as _format_explanation # noqa
-
-def _format_assertmsg(obj):
- """Format the custom assertion message given.
-
- For strings this simply replaces newlines with '\n~' so that
- util.format_explanation() will preserve them instead of escaping
- newlines. For other objects py.io.saferepr() is used first.
-
- """
- # reprlib appears to have a bug which means that if a string
- # contains a newline it gets escaped, however if an object has a
- # .__repr__() which contains newlines it does not get escaped.
- # However in either case we want to preserve the newline.
- if py.builtin._istext(obj) or py.builtin._isbytes(obj):
- s = obj
- is_repr = False
- else:
- s = py.io.saferepr(obj)
- is_repr = True
- if py.builtin._istext(s):
- t = py.builtin.text
- else:
- t = py.builtin.bytes
- s = s.replace(t("\n"), t("\n~")).replace(t("%"), t("%%"))
- if is_repr:
- s = s.replace(t("\\n"), t("\n~"))
- return s
-
-def _should_repr_global_name(obj):
- return not hasattr(obj, "__name__") and not py.builtin.callable(obj)
-
-def _format_boolop(explanations, is_or):
- explanation = "(" + (is_or and " or " or " and ").join(explanations) + ")"
- if py.builtin._istext(explanation):
- t = py.builtin.text
- else:
- t = py.builtin.bytes
- return explanation.replace(t('%'), t('%%'))
-
-def _call_reprcompare(ops, results, expls, each_obj):
- for i, res, expl in zip(range(len(ops)), results, expls):
- try:
- done = not res
- except Exception:
- done = True
- if done:
- break
- if util._reprcompare is not None:
- custom = util._reprcompare(ops[i], each_obj[i], each_obj[i + 1])
- if custom is not None:
- return custom
- return expl
-
-
-unary_map = {
- ast.Not: "not %s",
- ast.Invert: "~%s",
- ast.USub: "-%s",
- ast.UAdd: "+%s"
-}
-
-binop_map = {
- ast.BitOr: "|",
- ast.BitXor: "^",
- ast.BitAnd: "&",
- ast.LShift: "<<",
- ast.RShift: ">>",
- ast.Add: "+",
- ast.Sub: "-",
- ast.Mult: "*",
- ast.Div: "/",
- ast.FloorDiv: "//",
- ast.Mod: "%%", # escaped for string formatting
- ast.Eq: "==",
- ast.NotEq: "!=",
- ast.Lt: "<",
- ast.LtE: "<=",
- ast.Gt: ">",
- ast.GtE: ">=",
- ast.Pow: "**",
- ast.Is: "is",
- ast.IsNot: "is not",
- ast.In: "in",
- ast.NotIn: "not in"
-}
-# Python 3.5+ compatibility
-try:
- binop_map[ast.MatMult] = "@"
-except AttributeError:
- pass
-
-# Python 3.4+ compatibility
-if hasattr(ast, "NameConstant"):
- _NameConstant = ast.NameConstant
-else:
- def _NameConstant(c):
- return ast.Name(str(c), ast.Load())
-
-
-def set_location(node, lineno, col_offset):
- """Set node location information recursively."""
- def _fix(node, lineno, col_offset):
- if "lineno" in node._attributes:
- node.lineno = lineno
- if "col_offset" in node._attributes:
- node.col_offset = col_offset
- for child in ast.iter_child_nodes(node):
- _fix(child, lineno, col_offset)
- _fix(node, lineno, col_offset)
- return node
-
-
-class AssertionRewriter(ast.NodeVisitor):
- """Assertion rewriting implementation.
-
- The main entrypoint is to call .run() with an ast.Module instance,
- this will then find all the assert statements and re-write them to
- provide intermediate values and a detailed assertion error. See
- http://pybites.blogspot.be/2011/07/behind-scenes-of-pytests-new-assertion.html
- for an overview of how this works.
-
- The entry point here is .run() which will iterate over all the
- statements in an ast.Module and for each ast.Assert statement it
- finds call .visit() with it. Then .visit_Assert() takes over and
- is responsible for creating new ast statements to replace the
- original assert statement: it re-writes the test of an assertion
- to provide intermediate values and replace it with an if statement
- which raises an assertion error with a detailed explanation in
- case the expression is false.
-
- For this .visit_Assert() uses the visitor pattern to visit all the
- AST nodes of the ast.Assert.test field, each visit call returning
- an AST node and the corresponding explanation string. During this
- state is kept in several instance attributes:
-
- :statements: All the AST statements which will replace the assert
- statement.
-
- :variables: This is populated by .variable() with each variable
- used by the statements so that they can all be set to None at
- the end of the statements.
-
- :variable_counter: Counter to create new unique variables needed
- by statements. Variables are created using .variable() and
- have the form of "@py_assert0".
-
- :on_failure: The AST statements which will be executed if the
- assertion test fails. This is the code which will construct
- the failure message and raises the AssertionError.
-
- :explanation_specifiers: A dict filled by .explanation_param()
- with %-formatting placeholders and their corresponding
- expressions to use in the building of an assertion message.
- This is used by .pop_format_context() to build a message.
-
- :stack: A stack of the explanation_specifiers dicts maintained by
- .push_format_context() and .pop_format_context() which allows
- to build another %-formatted string while already building one.
-
- This state is reset on every new assert statement visited and used
- by the other visitors.
-
- """
-
- def run(self, mod):
- """Find all assert statements in *mod* and rewrite them."""
- if not mod.body:
- # Nothing to do.
- return
- # Insert some special imports at the top of the module but after any
- # docstrings and __future__ imports.
- aliases = [ast.alias(py.builtin.builtins.__name__, "@py_builtins"),
- ast.alias("_pytest.assertion.rewrite", "@pytest_ar")]
- expect_docstring = True
- pos = 0
- lineno = 0
- for item in mod.body:
- if (expect_docstring and isinstance(item, ast.Expr) and
- isinstance(item.value, ast.Str)):
- doc = item.value.s
- if "PYTEST_DONT_REWRITE" in doc:
- # The module has disabled assertion rewriting.
- return
- lineno += len(doc) - 1
- expect_docstring = False
- elif (not isinstance(item, ast.ImportFrom) or item.level > 0 or
- item.module != "__future__"):
- lineno = item.lineno
- break
- pos += 1
- imports = [ast.Import([alias], lineno=lineno, col_offset=0)
- for alias in aliases]
- mod.body[pos:pos] = imports
- # Collect asserts.
- nodes = [mod]
- while nodes:
- node = nodes.pop()
- for name, field in ast.iter_fields(node):
- if isinstance(field, list):
- new = []
- for i, child in enumerate(field):
- if isinstance(child, ast.Assert):
- # Transform assert.
- new.extend(self.visit(child))
- else:
- new.append(child)
- if isinstance(child, ast.AST):
- nodes.append(child)
- setattr(node, name, new)
- elif (isinstance(field, ast.AST) and
- # Don't recurse into expressions as they can't contain
- # asserts.
- not isinstance(field, ast.expr)):
- nodes.append(field)
-
- def variable(self):
- """Get a new variable."""
- # Use a character invalid in python identifiers to avoid clashing.
- name = "@py_assert" + str(next(self.variable_counter))
- self.variables.append(name)
- return name
-
- def assign(self, expr):
- """Give *expr* a name."""
- name = self.variable()
- self.statements.append(ast.Assign([ast.Name(name, ast.Store())], expr))
- return ast.Name(name, ast.Load())
-
- def display(self, expr):
- """Call py.io.saferepr on the expression."""
- return self.helper("saferepr", expr)
-
- def helper(self, name, *args):
- """Call a helper in this module."""
- py_name = ast.Name("@pytest_ar", ast.Load())
- attr = ast.Attribute(py_name, "_" + name, ast.Load())
- return ast_Call(attr, list(args), [])
-
- def builtin(self, name):
- """Return the builtin called *name*."""
- builtin_name = ast.Name("@py_builtins", ast.Load())
- return ast.Attribute(builtin_name, name, ast.Load())
-
- def explanation_param(self, expr):
- """Return a new named %-formatting placeholder for expr.
-
- This creates a %-formatting placeholder for expr in the
- current formatting context, e.g. ``%(py0)s``. The placeholder
- and expr are placed in the current format context so that it
- can be used on the next call to .pop_format_context().
-
- """
- specifier = "py" + str(next(self.variable_counter))
- self.explanation_specifiers[specifier] = expr
- return "%(" + specifier + ")s"
-
- def push_format_context(self):
- """Create a new formatting context.
-
- The format context is used for when an explanation wants to
- have a variable value formatted in the assertion message. In
- this case the value required can be added using
- .explanation_param(). Finally .pop_format_context() is used
- to format a string of %-formatted values as added by
- .explanation_param().
-
- """
- self.explanation_specifiers = {}
- self.stack.append(self.explanation_specifiers)
-
- def pop_format_context(self, expl_expr):
- """Format the %-formatted string with current format context.
-
- The expl_expr should be an ast.Str instance constructed from
- the %-placeholders created by .explanation_param(). This will
- add the required code to format said string to .on_failure and
- return the ast.Name instance of the formatted string.
-
- """
- current = self.stack.pop()
- if self.stack:
- self.explanation_specifiers = self.stack[-1]
- keys = [ast.Str(key) for key in current.keys()]
- format_dict = ast.Dict(keys, list(current.values()))
- form = ast.BinOp(expl_expr, ast.Mod(), format_dict)
- name = "@py_format" + str(next(self.variable_counter))
- self.on_failure.append(ast.Assign([ast.Name(name, ast.Store())], form))
- return ast.Name(name, ast.Load())
-
- def generic_visit(self, node):
- """Handle expressions we don't have custom code for."""
- assert isinstance(node, ast.expr)
- res = self.assign(node)
- return res, self.explanation_param(self.display(res))
-
- def visit_Assert(self, assert_):
- """Return the AST statements to replace the ast.Assert instance.
-
- This re-writes the test of an assertion to provide
- intermediate values and replace it with an if statement which
- raises an assertion error with a detailed explanation in case
- the expression is false.
-
- """
- self.statements = []
- self.variables = []
- self.variable_counter = itertools.count()
- self.stack = []
- self.on_failure = []
- self.push_format_context()
- # Rewrite assert into a bunch of statements.
- top_condition, explanation = self.visit(assert_.test)
- # Create failure message.
- body = self.on_failure
- negation = ast.UnaryOp(ast.Not(), top_condition)
- self.statements.append(ast.If(negation, body, []))
- if assert_.msg:
- assertmsg = self.helper('format_assertmsg', assert_.msg)
- explanation = "\n>assert " + explanation
- else:
- assertmsg = ast.Str("")
- explanation = "assert " + explanation
- template = ast.BinOp(assertmsg, ast.Add(), ast.Str(explanation))
- msg = self.pop_format_context(template)
- fmt = self.helper("format_explanation", msg)
- err_name = ast.Name("AssertionError", ast.Load())
- exc = ast_Call(err_name, [fmt], [])
- if sys.version_info[0] >= 3:
- raise_ = ast.Raise(exc, None)
- else:
- raise_ = ast.Raise(exc, None, None)
- body.append(raise_)
- # Clear temporary variables by setting them to None.
- if self.variables:
- variables = [ast.Name(name, ast.Store())
- for name in self.variables]
- clear = ast.Assign(variables, _NameConstant(None))
- self.statements.append(clear)
- # Fix line numbers.
- for stmt in self.statements:
- set_location(stmt, assert_.lineno, assert_.col_offset)
- return self.statements
-
- def visit_Name(self, name):
- # Display the repr of the name if it's a local variable or
- # _should_repr_global_name() thinks it's acceptable.
- locs = ast_Call(self.builtin("locals"), [], [])
- inlocs = ast.Compare(ast.Str(name.id), [ast.In()], [locs])
- dorepr = self.helper("should_repr_global_name", name)
- test = ast.BoolOp(ast.Or(), [inlocs, dorepr])
- expr = ast.IfExp(test, self.display(name), ast.Str(name.id))
- return name, self.explanation_param(expr)
-
- def visit_BoolOp(self, boolop):
- res_var = self.variable()
- expl_list = self.assign(ast.List([], ast.Load()))
- app = ast.Attribute(expl_list, "append", ast.Load())
- is_or = int(isinstance(boolop.op, ast.Or))
- body = save = self.statements
- fail_save = self.on_failure
- levels = len(boolop.values) - 1
- self.push_format_context()
- # Process each operand, short-circuting if needed.
- for i, v in enumerate(boolop.values):
- if i:
- fail_inner = []
- # cond is set in a prior loop iteration below
- self.on_failure.append(ast.If(cond, fail_inner, [])) # noqa
- self.on_failure = fail_inner
- self.push_format_context()
- res, expl = self.visit(v)
- body.append(ast.Assign([ast.Name(res_var, ast.Store())], res))
- expl_format = self.pop_format_context(ast.Str(expl))
- call = ast_Call(app, [expl_format], [])
- self.on_failure.append(ast.Expr(call))
- if i < levels:
- cond = res
- if is_or:
- cond = ast.UnaryOp(ast.Not(), cond)
- inner = []
- self.statements.append(ast.If(cond, inner, []))
- self.statements = body = inner
- self.statements = save
- self.on_failure = fail_save
- expl_template = self.helper("format_boolop", expl_list, ast.Num(is_or))
- expl = self.pop_format_context(expl_template)
- return ast.Name(res_var, ast.Load()), self.explanation_param(expl)
-
- def visit_UnaryOp(self, unary):
- pattern = unary_map[unary.op.__class__]
- operand_res, operand_expl = self.visit(unary.operand)
- res = self.assign(ast.UnaryOp(unary.op, operand_res))
- return res, pattern % (operand_expl,)
-
- def visit_BinOp(self, binop):
- symbol = binop_map[binop.op.__class__]
- left_expr, left_expl = self.visit(binop.left)
- right_expr, right_expl = self.visit(binop.right)
- explanation = "(%s %s %s)" % (left_expl, symbol, right_expl)
- res = self.assign(ast.BinOp(left_expr, binop.op, right_expr))
- return res, explanation
-
- def visit_Call_35(self, call):
- """
- visit `ast.Call` nodes on Python3.5 and after
- """
- new_func, func_expl = self.visit(call.func)
- arg_expls = []
- new_args = []
- new_kwargs = []
- for arg in call.args:
- res, expl = self.visit(arg)
- arg_expls.append(expl)
- new_args.append(res)
- for keyword in call.keywords:
- res, expl = self.visit(keyword.value)
- new_kwargs.append(ast.keyword(keyword.arg, res))
- if keyword.arg:
- arg_expls.append(keyword.arg + "=" + expl)
- else: ## **args have `arg` keywords with an .arg of None
- arg_expls.append("**" + expl)
-
- expl = "%s(%s)" % (func_expl, ', '.join(arg_expls))
- new_call = ast.Call(new_func, new_args, new_kwargs)
- res = self.assign(new_call)
- res_expl = self.explanation_param(self.display(res))
- outer_expl = "%s\n{%s = %s\n}" % (res_expl, res_expl, expl)
- return res, outer_expl
-
- def visit_Starred(self, starred):
- # From Python 3.5, a Starred node can appear in a function call
- res, expl = self.visit(starred.value)
- return starred, '*' + expl
-
- def visit_Call_legacy(self, call):
- """
- visit `ast.Call nodes on 3.4 and below`
- """
- new_func, func_expl = self.visit(call.func)
- arg_expls = []
- new_args = []
- new_kwargs = []
- new_star = new_kwarg = None
- for arg in call.args:
- res, expl = self.visit(arg)
- new_args.append(res)
- arg_expls.append(expl)
- for keyword in call.keywords:
- res, expl = self.visit(keyword.value)
- new_kwargs.append(ast.keyword(keyword.arg, res))
- arg_expls.append(keyword.arg + "=" + expl)
- if call.starargs:
- new_star, expl = self.visit(call.starargs)
- arg_expls.append("*" + expl)
- if call.kwargs:
- new_kwarg, expl = self.visit(call.kwargs)
- arg_expls.append("**" + expl)
- expl = "%s(%s)" % (func_expl, ', '.join(arg_expls))
- new_call = ast.Call(new_func, new_args, new_kwargs,
- new_star, new_kwarg)
- res = self.assign(new_call)
- res_expl = self.explanation_param(self.display(res))
- outer_expl = "%s\n{%s = %s\n}" % (res_expl, res_expl, expl)
- return res, outer_expl
-
- # ast.Call signature changed on 3.5,
- # conditionally change which methods is named
- # visit_Call depending on Python version
- if sys.version_info >= (3, 5):
- visit_Call = visit_Call_35
- else:
- visit_Call = visit_Call_legacy
-
-
- def visit_Attribute(self, attr):
- if not isinstance(attr.ctx, ast.Load):
- return self.generic_visit(attr)
- value, value_expl = self.visit(attr.value)
- res = self.assign(ast.Attribute(value, attr.attr, ast.Load()))
- res_expl = self.explanation_param(self.display(res))
- pat = "%s\n{%s = %s.%s\n}"
- expl = pat % (res_expl, res_expl, value_expl, attr.attr)
- return res, expl
-
- def visit_Compare(self, comp):
- self.push_format_context()
- left_res, left_expl = self.visit(comp.left)
- res_variables = [self.variable() for i in range(len(comp.ops))]
- load_names = [ast.Name(v, ast.Load()) for v in res_variables]
- store_names = [ast.Name(v, ast.Store()) for v in res_variables]
- it = zip(range(len(comp.ops)), comp.ops, comp.comparators)
- expls = []
- syms = []
- results = [left_res]
- for i, op, next_operand in it:
- next_res, next_expl = self.visit(next_operand)
- results.append(next_res)
- sym = binop_map[op.__class__]
- syms.append(ast.Str(sym))
- expl = "%s %s %s" % (left_expl, sym, next_expl)
- expls.append(ast.Str(expl))
- res_expr = ast.Compare(left_res, [op], [next_res])
- self.statements.append(ast.Assign([store_names[i]], res_expr))
- left_res, left_expl = next_res, next_expl
- # Use pytest.assertion.util._reprcompare if that's available.
- expl_call = self.helper("call_reprcompare",
- ast.Tuple(syms, ast.Load()),
- ast.Tuple(load_names, ast.Load()),
- ast.Tuple(expls, ast.Load()),
- ast.Tuple(results, ast.Load()))
- if len(comp.ops) > 1:
- res = ast.BoolOp(ast.And(), load_names)
- else:
- res = load_names[0]
- return res, self.explanation_param(self.pop_format_context(expl_call))
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/assertion/util.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/assertion/util.py
deleted file mode 100644
index f2f23efea27..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/assertion/util.py
+++ /dev/null
@@ -1,332 +0,0 @@
-"""Utilities for assertion debugging"""
-import pprint
-
-import _pytest._code
-import py
-try:
- from collections import Sequence
-except ImportError:
- Sequence = list
-
-BuiltinAssertionError = py.builtin.builtins.AssertionError
-u = py.builtin._totext
-
-# The _reprcompare attribute on the util module is used by the new assertion
-# interpretation code and assertion rewriter to detect this plugin was
-# loaded and in turn call the hooks defined here as part of the
-# DebugInterpreter.
-_reprcompare = None
-
-
-# the re-encoding is needed for python2 repr
-# with non-ascii characters (see issue 877 and 1379)
-def ecu(s):
- try:
- return u(s, 'utf-8', 'replace')
- except TypeError:
- return s
-
-
-def format_explanation(explanation):
- """This formats an explanation
-
- Normally all embedded newlines are escaped, however there are
- three exceptions: \n{, \n} and \n~. The first two are intended
- cover nested explanations, see function and attribute explanations
- for examples (.visit_Call(), visit_Attribute()). The last one is
- for when one explanation needs to span multiple lines, e.g. when
- displaying diffs.
- """
- explanation = ecu(explanation)
- explanation = _collapse_false(explanation)
- lines = _split_explanation(explanation)
- result = _format_lines(lines)
- return u('\n').join(result)
-
-
-def _collapse_false(explanation):
- """Collapse expansions of False
-
- So this strips out any "assert False\n{where False = ...\n}"
- blocks.
- """
- where = 0
- while True:
- start = where = explanation.find("False\n{False = ", where)
- if where == -1:
- break
- level = 0
- prev_c = explanation[start]
- for i, c in enumerate(explanation[start:]):
- if prev_c + c == "\n{":
- level += 1
- elif prev_c + c == "\n}":
- level -= 1
- if not level:
- break
- prev_c = c
- else:
- raise AssertionError("unbalanced braces: %r" % (explanation,))
- end = start + i
- where = end
- if explanation[end - 1] == '\n':
- explanation = (explanation[:start] + explanation[start+15:end-1] +
- explanation[end+1:])
- where -= 17
- return explanation
-
-
-def _split_explanation(explanation):
- """Return a list of individual lines in the explanation
-
- This will return a list of lines split on '\n{', '\n}' and '\n~'.
- Any other newlines will be escaped and appear in the line as the
- literal '\n' characters.
- """
- raw_lines = (explanation or u('')).split('\n')
- lines = [raw_lines[0]]
- for l in raw_lines[1:]:
- if l and l[0] in ['{', '}', '~', '>']:
- lines.append(l)
- else:
- lines[-1] += '\\n' + l
- return lines
-
-
-def _format_lines(lines):
- """Format the individual lines
-
- This will replace the '{', '}' and '~' characters of our mini
- formatting language with the proper 'where ...', 'and ...' and ' +
- ...' text, taking care of indentation along the way.
-
- Return a list of formatted lines.
- """
- result = lines[:1]
- stack = [0]
- stackcnt = [0]
- for line in lines[1:]:
- if line.startswith('{'):
- if stackcnt[-1]:
- s = u('and ')
- else:
- s = u('where ')
- stack.append(len(result))
- stackcnt[-1] += 1
- stackcnt.append(0)
- result.append(u(' +') + u(' ')*(len(stack)-1) + s + line[1:])
- elif line.startswith('}'):
- stack.pop()
- stackcnt.pop()
- result[stack[-1]] += line[1:]
- else:
- assert line[0] in ['~', '>']
- stack[-1] += 1
- indent = len(stack) if line.startswith('~') else len(stack) - 1
- result.append(u(' ')*indent + line[1:])
- assert len(stack) == 1
- return result
-
-
-# Provide basestring in python3
-try:
- basestring = basestring
-except NameError:
- basestring = str
-
-
-def assertrepr_compare(config, op, left, right):
- """Return specialised explanations for some operators/operands"""
- width = 80 - 15 - len(op) - 2 # 15 chars indentation, 1 space around op
- left_repr = py.io.saferepr(left, maxsize=int(width/2))
- right_repr = py.io.saferepr(right, maxsize=width-len(left_repr))
-
- summary = u('%s %s %s') % (ecu(left_repr), op, ecu(right_repr))
-
- issequence = lambda x: (isinstance(x, (list, tuple, Sequence)) and
- not isinstance(x, basestring))
- istext = lambda x: isinstance(x, basestring)
- isdict = lambda x: isinstance(x, dict)
- isset = lambda x: isinstance(x, (set, frozenset))
-
- def isiterable(obj):
- try:
- iter(obj)
- return not istext(obj)
- except TypeError:
- return False
-
- verbose = config.getoption('verbose')
- explanation = None
- try:
- if op == '==':
- if istext(left) and istext(right):
- explanation = _diff_text(left, right, verbose)
- else:
- if issequence(left) and issequence(right):
- explanation = _compare_eq_sequence(left, right, verbose)
- elif isset(left) and isset(right):
- explanation = _compare_eq_set(left, right, verbose)
- elif isdict(left) and isdict(right):
- explanation = _compare_eq_dict(left, right, verbose)
- if isiterable(left) and isiterable(right):
- expl = _compare_eq_iterable(left, right, verbose)
- if explanation is not None:
- explanation.extend(expl)
- else:
- explanation = expl
- elif op == 'not in':
- if istext(left) and istext(right):
- explanation = _notin_text(left, right, verbose)
- except Exception:
- explanation = [
- u('(pytest_assertion plugin: representation of details failed. '
- 'Probably an object has a faulty __repr__.)'),
- u(_pytest._code.ExceptionInfo())]
-
- if not explanation:
- return None
-
- return [summary] + explanation
-
-
-def _diff_text(left, right, verbose=False):
- """Return the explanation for the diff between text or bytes
-
- Unless --verbose is used this will skip leading and trailing
- characters which are identical to keep the diff minimal.
-
- If the input are bytes they will be safely converted to text.
- """
- from difflib import ndiff
- explanation = []
- if isinstance(left, py.builtin.bytes):
- left = u(repr(left)[1:-1]).replace(r'\n', '\n')
- if isinstance(right, py.builtin.bytes):
- right = u(repr(right)[1:-1]).replace(r'\n', '\n')
- if not verbose:
- i = 0 # just in case left or right has zero length
- for i in range(min(len(left), len(right))):
- if left[i] != right[i]:
- break
- if i > 42:
- i -= 10 # Provide some context
- explanation = [u('Skipping %s identical leading '
- 'characters in diff, use -v to show') % i]
- left = left[i:]
- right = right[i:]
- if len(left) == len(right):
- for i in range(len(left)):
- if left[-i] != right[-i]:
- break
- if i > 42:
- i -= 10 # Provide some context
- explanation += [u('Skipping %s identical trailing '
- 'characters in diff, use -v to show') % i]
- left = left[:-i]
- right = right[:-i]
- explanation += [line.strip('\n')
- for line in ndiff(left.splitlines(),
- right.splitlines())]
- return explanation
-
-
-def _compare_eq_iterable(left, right, verbose=False):
- if not verbose:
- return [u('Use -v to get the full diff')]
- # dynamic import to speedup pytest
- import difflib
-
- try:
- left_formatting = pprint.pformat(left).splitlines()
- right_formatting = pprint.pformat(right).splitlines()
- explanation = [u('Full diff:')]
- except Exception:
- # hack: PrettyPrinter.pformat() in python 2 fails when formatting items that can't be sorted(), ie, calling
- # sorted() on a list would raise. See issue #718.
- # As a workaround, the full diff is generated by using the repr() string of each item of each container.
- left_formatting = sorted(repr(x) for x in left)
- right_formatting = sorted(repr(x) for x in right)
- explanation = [u('Full diff (fallback to calling repr on each item):')]
- explanation.extend(line.strip() for line in difflib.ndiff(left_formatting, right_formatting))
- return explanation
-
-
-def _compare_eq_sequence(left, right, verbose=False):
- explanation = []
- for i in range(min(len(left), len(right))):
- if left[i] != right[i]:
- explanation += [u('At index %s diff: %r != %r')
- % (i, left[i], right[i])]
- break
- if len(left) > len(right):
- explanation += [u('Left contains more items, first extra item: %s')
- % py.io.saferepr(left[len(right)],)]
- elif len(left) < len(right):
- explanation += [
- u('Right contains more items, first extra item: %s') %
- py.io.saferepr(right[len(left)],)]
- return explanation
-
-
-def _compare_eq_set(left, right, verbose=False):
- explanation = []
- diff_left = left - right
- diff_right = right - left
- if diff_left:
- explanation.append(u('Extra items in the left set:'))
- for item in diff_left:
- explanation.append(py.io.saferepr(item))
- if diff_right:
- explanation.append(u('Extra items in the right set:'))
- for item in diff_right:
- explanation.append(py.io.saferepr(item))
- return explanation
-
-
-def _compare_eq_dict(left, right, verbose=False):
- explanation = []
- common = set(left).intersection(set(right))
- same = dict((k, left[k]) for k in common if left[k] == right[k])
- if same and not verbose:
- explanation += [u('Omitting %s identical items, use -v to show') %
- len(same)]
- elif same:
- explanation += [u('Common items:')]
- explanation += pprint.pformat(same).splitlines()
- diff = set(k for k in common if left[k] != right[k])
- if diff:
- explanation += [u('Differing items:')]
- for k in diff:
- explanation += [py.io.saferepr({k: left[k]}) + ' != ' +
- py.io.saferepr({k: right[k]})]
- extra_left = set(left) - set(right)
- if extra_left:
- explanation.append(u('Left contains more items:'))
- explanation.extend(pprint.pformat(
- dict((k, left[k]) for k in extra_left)).splitlines())
- extra_right = set(right) - set(left)
- if extra_right:
- explanation.append(u('Right contains more items:'))
- explanation.extend(pprint.pformat(
- dict((k, right[k]) for k in extra_right)).splitlines())
- return explanation
-
-
-def _notin_text(term, text, verbose=False):
- index = text.find(term)
- head = text[:index]
- tail = text[index+len(term):]
- correct_text = head + tail
- diff = _diff_text(correct_text, text, verbose)
- newdiff = [u('%s is contained here:') % py.io.saferepr(term, maxsize=42)]
- for line in diff:
- if line.startswith(u('Skipping')):
- continue
- if line.startswith(u('- ')):
- continue
- if line.startswith(u('+ ')):
- newdiff.append(u(' ') + line[2:])
- else:
- newdiff.append(line)
- return newdiff
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/cacheprovider.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/cacheprovider.py
deleted file mode 100755
index 0657001f2d4..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/cacheprovider.py
+++ /dev/null
@@ -1,245 +0,0 @@
-"""
-merged implementation of the cache provider
-
-the name cache was not choosen to ensure pluggy automatically
-ignores the external pytest-cache
-"""
-
-import py
-import pytest
-import json
-from os.path import sep as _sep, altsep as _altsep
-
-
-class Cache(object):
- def __init__(self, config):
- self.config = config
- self._cachedir = config.rootdir.join(".cache")
- self.trace = config.trace.root.get("cache")
- if config.getvalue("cacheclear"):
- self.trace("clearing cachedir")
- if self._cachedir.check():
- self._cachedir.remove()
- self._cachedir.mkdir()
-
- def makedir(self, name):
- """ return a directory path object with the given name. If the
- directory does not yet exist, it will be created. You can use it
- to manage files likes e. g. store/retrieve database
- dumps across test sessions.
-
- :param name: must be a string not containing a ``/`` separator.
- Make sure the name contains your plugin or application
- identifiers to prevent clashes with other cache users.
- """
- if _sep in name or _altsep is not None and _altsep in name:
- raise ValueError("name is not allowed to contain path separators")
- return self._cachedir.ensure_dir("d", name)
-
- def _getvaluepath(self, key):
- return self._cachedir.join('v', *key.split('/'))
-
- def get(self, key, default):
- """ return cached value for the given key. If no value
- was yet cached or the value cannot be read, the specified
- default is returned.
-
- :param key: must be a ``/`` separated value. Usually the first
- name is the name of your plugin or your application.
- :param default: must be provided in case of a cache-miss or
- invalid cache values.
-
- """
- path = self._getvaluepath(key)
- if path.check():
- try:
- with path.open("r") as f:
- return json.load(f)
- except ValueError:
- self.trace("cache-invalid at %s" % (path,))
- return default
-
- def set(self, key, value):
- """ save value for the given key.
-
- :param key: must be a ``/`` separated value. Usually the first
- name is the name of your plugin or your application.
- :param value: must be of any combination of basic
- python types, including nested types
- like e. g. lists of dictionaries.
- """
- path = self._getvaluepath(key)
- try:
- path.dirpath().ensure_dir()
- except (py.error.EEXIST, py.error.EACCES):
- self.config.warn(
- code='I9', message='could not create cache path %s' % (path,)
- )
- return
- try:
- f = path.open('w')
- except py.error.ENOTDIR:
- self.config.warn(
- code='I9', message='cache could not write path %s' % (path,))
- else:
- with f:
- self.trace("cache-write %s: %r" % (key, value,))
- json.dump(value, f, indent=2, sort_keys=True)
-
-
-class LFPlugin:
- """ Plugin which implements the --lf (run last-failing) option """
- def __init__(self, config):
- self.config = config
- active_keys = 'lf', 'failedfirst'
- self.active = any(config.getvalue(key) for key in active_keys)
- if self.active:
- self.lastfailed = config.cache.get("cache/lastfailed", {})
- else:
- self.lastfailed = {}
-
- def pytest_report_header(self):
- if self.active:
- if not self.lastfailed:
- mode = "run all (no recorded failures)"
- else:
- mode = "rerun last %d failures%s" % (
- len(self.lastfailed),
- " first" if self.config.getvalue("failedfirst") else "")
- return "run-last-failure: %s" % mode
-
- def pytest_runtest_logreport(self, report):
- if report.failed and "xfail" not in report.keywords:
- self.lastfailed[report.nodeid] = True
- elif not report.failed:
- if report.when == "call":
- self.lastfailed.pop(report.nodeid, None)
-
- def pytest_collectreport(self, report):
- passed = report.outcome in ('passed', 'skipped')
- if passed:
- if report.nodeid in self.lastfailed:
- self.lastfailed.pop(report.nodeid)
- self.lastfailed.update(
- (item.nodeid, True)
- for item in report.result)
- else:
- self.lastfailed[report.nodeid] = True
-
- def pytest_collection_modifyitems(self, session, config, items):
- if self.active and self.lastfailed:
- previously_failed = []
- previously_passed = []
- for item in items:
- if item.nodeid in self.lastfailed:
- previously_failed.append(item)
- else:
- previously_passed.append(item)
- if not previously_failed and previously_passed:
- # running a subset of all tests with recorded failures outside
- # of the set of tests currently executing
- pass
- elif self.config.getvalue("failedfirst"):
- items[:] = previously_failed + previously_passed
- else:
- items[:] = previously_failed
- config.hook.pytest_deselected(items=previously_passed)
-
- def pytest_sessionfinish(self, session):
- config = self.config
- if config.getvalue("cacheshow") or hasattr(config, "slaveinput"):
- return
- prev_failed = config.cache.get("cache/lastfailed", None) is not None
- if (session.testscollected and prev_failed) or self.lastfailed:
- config.cache.set("cache/lastfailed", self.lastfailed)
-
-
-def pytest_addoption(parser):
- group = parser.getgroup("general")
- group.addoption(
- '--lf', '--last-failed', action='store_true', dest="lf",
- help="rerun only the tests that failed "
- "at the last run (or all if none failed)")
- group.addoption(
- '--ff', '--failed-first', action='store_true', dest="failedfirst",
- help="run all tests but run the last failures first. "
- "This may re-order tests and thus lead to "
- "repeated fixture setup/teardown")
- group.addoption(
- '--cache-show', action='store_true', dest="cacheshow",
- help="show cache contents, don't perform collection or tests")
- group.addoption(
- '--cache-clear', action='store_true', dest="cacheclear",
- help="remove all cache contents at start of test run.")
-
-
-def pytest_cmdline_main(config):
- if config.option.cacheshow:
- from _pytest.main import wrap_session
- return wrap_session(config, cacheshow)
-
-
-
-@pytest.hookimpl(tryfirst=True)
-def pytest_configure(config):
- config.cache = Cache(config)
- config.pluginmanager.register(LFPlugin(config), "lfplugin")
-
-
-@pytest.fixture
-def cache(request):
- """
- Return a cache object that can persist state between testing sessions.
-
- cache.get(key, default)
- cache.set(key, value)
-
- Keys must be a ``/`` separated value, where the first part is usually the
- name of your plugin or application to avoid clashes with other cache users.
-
- Values can be any object handled by the json stdlib module.
- """
- return request.config.cache
-
-
-def pytest_report_header(config):
- if config.option.verbose:
- relpath = py.path.local().bestrelpath(config.cache._cachedir)
- return "cachedir: %s" % relpath
-
-
-def cacheshow(config, session):
- from pprint import pprint
- tw = py.io.TerminalWriter()
- tw.line("cachedir: " + str(config.cache._cachedir))
- if not config.cache._cachedir.check():
- tw.line("cache is empty")
- return 0
- dummy = object()
- basedir = config.cache._cachedir
- vdir = basedir.join("v")
- tw.sep("-", "cache values")
- for valpath in vdir.visit(lambda x: x.isfile()):
- key = valpath.relto(vdir).replace(valpath.sep, "/")
- val = config.cache.get(key, dummy)
- if val is dummy:
- tw.line("%s contains unreadable content, "
- "will be ignored" % key)
- else:
- tw.line("%s contains:" % key)
- stream = py.io.TextIO()
- pprint(val, stream=stream)
- for line in stream.getvalue().splitlines():
- tw.line(" " + line)
-
- ddir = basedir.join("d")
- if ddir.isdir() and ddir.listdir():
- tw.sep("-", "cache directories")
- for p in basedir.join("d").visit():
- #if p.check(dir=1):
- # print("%s/" % p.relto(basedir))
- if p.isfile():
- key = p.relto(basedir)
- tw.line("%s is a file of length %d" % (
- key, p.size()))
- return 0
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/capture.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/capture.py
deleted file mode 100644
index 3895a714aa0..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/capture.py
+++ /dev/null
@@ -1,472 +0,0 @@
-"""
-per-test stdout/stderr capturing mechanism.
-
-"""
-from __future__ import with_statement
-
-import sys
-import os
-from tempfile import TemporaryFile
-
-import py
-import pytest
-
-from py.io import TextIO
-unicode = py.builtin.text
-
-patchsysdict = {0: 'stdin', 1: 'stdout', 2: 'stderr'}
-
-
-def pytest_addoption(parser):
- group = parser.getgroup("general")
- group._addoption(
- '--capture', action="store",
- default="fd" if hasattr(os, "dup") else "sys",
- metavar="method", choices=['fd', 'sys', 'no'],
- help="per-test capturing method: one of fd|sys|no.")
- group._addoption(
- '-s', action="store_const", const="no", dest="capture",
- help="shortcut for --capture=no.")
-
-
-@pytest.hookimpl(hookwrapper=True)
-def pytest_load_initial_conftests(early_config, parser, args):
- _readline_workaround()
- ns = early_config.known_args_namespace
- pluginmanager = early_config.pluginmanager
- capman = CaptureManager(ns.capture)
- pluginmanager.register(capman, "capturemanager")
-
- # make sure that capturemanager is properly reset at final shutdown
- early_config.add_cleanup(capman.reset_capturings)
-
- # make sure logging does not raise exceptions at the end
- def silence_logging_at_shutdown():
- if "logging" in sys.modules:
- sys.modules["logging"].raiseExceptions = False
- early_config.add_cleanup(silence_logging_at_shutdown)
-
- # finally trigger conftest loading but while capturing (issue93)
- capman.init_capturings()
- outcome = yield
- out, err = capman.suspendcapture()
- if outcome.excinfo is not None:
- sys.stdout.write(out)
- sys.stderr.write(err)
-
-
-class CaptureManager:
- def __init__(self, method):
- self._method = method
-
- def _getcapture(self, method):
- if method == "fd":
- return MultiCapture(out=True, err=True, Capture=FDCapture)
- elif method == "sys":
- return MultiCapture(out=True, err=True, Capture=SysCapture)
- elif method == "no":
- return MultiCapture(out=False, err=False, in_=False)
- else:
- raise ValueError("unknown capturing method: %r" % method)
-
- def init_capturings(self):
- assert not hasattr(self, "_capturing")
- self._capturing = self._getcapture(self._method)
- self._capturing.start_capturing()
-
- def reset_capturings(self):
- cap = self.__dict__.pop("_capturing", None)
- if cap is not None:
- cap.pop_outerr_to_orig()
- cap.stop_capturing()
-
- def resumecapture(self):
- self._capturing.resume_capturing()
-
- def suspendcapture(self, in_=False):
- self.deactivate_funcargs()
- cap = getattr(self, "_capturing", None)
- if cap is not None:
- try:
- outerr = cap.readouterr()
- finally:
- cap.suspend_capturing(in_=in_)
- return outerr
-
- def activate_funcargs(self, pyfuncitem):
- capfuncarg = pyfuncitem.__dict__.pop("_capfuncarg", None)
- if capfuncarg is not None:
- capfuncarg._start()
- self._capfuncarg = capfuncarg
-
- def deactivate_funcargs(self):
- capfuncarg = self.__dict__.pop("_capfuncarg", None)
- if capfuncarg is not None:
- capfuncarg.close()
-
- @pytest.hookimpl(hookwrapper=True)
- def pytest_make_collect_report(self, collector):
- if isinstance(collector, pytest.File):
- self.resumecapture()
- outcome = yield
- out, err = self.suspendcapture()
- rep = outcome.get_result()
- if out:
- rep.sections.append(("Captured stdout", out))
- if err:
- rep.sections.append(("Captured stderr", err))
- else:
- yield
-
- @pytest.hookimpl(hookwrapper=True)
- def pytest_runtest_setup(self, item):
- self.resumecapture()
- yield
- self.suspendcapture_item(item, "setup")
-
- @pytest.hookimpl(hookwrapper=True)
- def pytest_runtest_call(self, item):
- self.resumecapture()
- self.activate_funcargs(item)
- yield
- #self.deactivate_funcargs() called from suspendcapture()
- self.suspendcapture_item(item, "call")
-
- @pytest.hookimpl(hookwrapper=True)
- def pytest_runtest_teardown(self, item):
- self.resumecapture()
- yield
- self.suspendcapture_item(item, "teardown")
-
- @pytest.hookimpl(tryfirst=True)
- def pytest_keyboard_interrupt(self, excinfo):
- self.reset_capturings()
-
- @pytest.hookimpl(tryfirst=True)
- def pytest_internalerror(self, excinfo):
- self.reset_capturings()
-
- def suspendcapture_item(self, item, when):
- out, err = self.suspendcapture()
- item.add_report_section(when, "stdout", out)
- item.add_report_section(when, "stderr", err)
-
-error_capsysfderror = "cannot use capsys and capfd at the same time"
-
-
-@pytest.fixture
-def capsys(request):
- """enables capturing of writes to sys.stdout/sys.stderr and makes
- captured output available via ``capsys.readouterr()`` method calls
- which return a ``(out, err)`` tuple.
- """
- if "capfd" in request._funcargs:
- raise request.raiseerror(error_capsysfderror)
- request.node._capfuncarg = c = CaptureFixture(SysCapture)
- return c
-
-@pytest.fixture
-def capfd(request):
- """enables capturing of writes to file descriptors 1 and 2 and makes
- captured output available via ``capfd.readouterr()`` method calls
- which return a ``(out, err)`` tuple.
- """
- if "capsys" in request._funcargs:
- request.raiseerror(error_capsysfderror)
- if not hasattr(os, 'dup'):
- pytest.skip("capfd funcarg needs os.dup")
- request.node._capfuncarg = c = CaptureFixture(FDCapture)
- return c
-
-
-class CaptureFixture:
- def __init__(self, captureclass):
- self.captureclass = captureclass
-
- def _start(self):
- self._capture = MultiCapture(out=True, err=True, in_=False,
- Capture=self.captureclass)
- self._capture.start_capturing()
-
- def close(self):
- cap = self.__dict__.pop("_capture", None)
- if cap is not None:
- self._outerr = cap.pop_outerr_to_orig()
- cap.stop_capturing()
-
- def readouterr(self):
- try:
- return self._capture.readouterr()
- except AttributeError:
- return self._outerr
-
-
-def safe_text_dupfile(f, mode, default_encoding="UTF8"):
- """ return a open text file object that's a duplicate of f on the
- FD-level if possible.
- """
- encoding = getattr(f, "encoding", None)
- try:
- fd = f.fileno()
- except Exception:
- if "b" not in getattr(f, "mode", "") and hasattr(f, "encoding"):
- # we seem to have a text stream, let's just use it
- return f
- else:
- newfd = os.dup(fd)
- if "b" not in mode:
- mode += "b"
- f = os.fdopen(newfd, mode, 0) # no buffering
- return EncodedFile(f, encoding or default_encoding)
-
-
-class EncodedFile(object):
- errors = "strict" # possibly needed by py3 code (issue555)
- def __init__(self, buffer, encoding):
- self.buffer = buffer
- self.encoding = encoding
-
- def write(self, obj):
- if isinstance(obj, unicode):
- obj = obj.encode(self.encoding, "replace")
- self.buffer.write(obj)
-
- def writelines(self, linelist):
- data = ''.join(linelist)
- self.write(data)
-
- def __getattr__(self, name):
- return getattr(object.__getattribute__(self, "buffer"), name)
-
-
-class MultiCapture(object):
- out = err = in_ = None
-
- def __init__(self, out=True, err=True, in_=True, Capture=None):
- if in_:
- self.in_ = Capture(0)
- if out:
- self.out = Capture(1)
- if err:
- self.err = Capture(2)
-
- def start_capturing(self):
- if self.in_:
- self.in_.start()
- if self.out:
- self.out.start()
- if self.err:
- self.err.start()
-
- def pop_outerr_to_orig(self):
- """ pop current snapshot out/err capture and flush to orig streams. """
- out, err = self.readouterr()
- if out:
- self.out.writeorg(out)
- if err:
- self.err.writeorg(err)
- return out, err
-
- def suspend_capturing(self, in_=False):
- if self.out:
- self.out.suspend()
- if self.err:
- self.err.suspend()
- if in_ and self.in_:
- self.in_.suspend()
- self._in_suspended = True
-
- def resume_capturing(self):
- if self.out:
- self.out.resume()
- if self.err:
- self.err.resume()
- if hasattr(self, "_in_suspended"):
- self.in_.resume()
- del self._in_suspended
-
- def stop_capturing(self):
- """ stop capturing and reset capturing streams """
- if hasattr(self, '_reset'):
- raise ValueError("was already stopped")
- self._reset = True
- if self.out:
- self.out.done()
- if self.err:
- self.err.done()
- if self.in_:
- self.in_.done()
-
- def readouterr(self):
- """ return snapshot unicode value of stdout/stderr capturings. """
- return (self.out.snap() if self.out is not None else "",
- self.err.snap() if self.err is not None else "")
-
-class NoCapture:
- __init__ = start = done = suspend = resume = lambda *args: None
-
-class FDCapture:
- """ Capture IO to/from a given os-level filedescriptor. """
-
- def __init__(self, targetfd, tmpfile=None):
- self.targetfd = targetfd
- try:
- self.targetfd_save = os.dup(self.targetfd)
- except OSError:
- self.start = lambda: None
- self.done = lambda: None
- else:
- if targetfd == 0:
- assert not tmpfile, "cannot set tmpfile with stdin"
- tmpfile = open(os.devnull, "r")
- self.syscapture = SysCapture(targetfd)
- else:
- if tmpfile is None:
- f = TemporaryFile()
- with f:
- tmpfile = safe_text_dupfile(f, mode="wb+")
- if targetfd in patchsysdict:
- self.syscapture = SysCapture(targetfd, tmpfile)
- else:
- self.syscapture = NoCapture()
- self.tmpfile = tmpfile
- self.tmpfile_fd = tmpfile.fileno()
-
- def __repr__(self):
- return "<FDCapture %s oldfd=%s>" % (self.targetfd, self.targetfd_save)
-
- def start(self):
- """ Start capturing on targetfd using memorized tmpfile. """
- try:
- os.fstat(self.targetfd_save)
- except (AttributeError, OSError):
- raise ValueError("saved filedescriptor not valid anymore")
- os.dup2(self.tmpfile_fd, self.targetfd)
- self.syscapture.start()
-
- def snap(self):
- f = self.tmpfile
- f.seek(0)
- res = f.read()
- if res:
- enc = getattr(f, "encoding", None)
- if enc and isinstance(res, bytes):
- res = py.builtin._totext(res, enc, "replace")
- f.truncate(0)
- f.seek(0)
- return res
- return ''
-
- def done(self):
- """ stop capturing, restore streams, return original capture file,
- seeked to position zero. """
- targetfd_save = self.__dict__.pop("targetfd_save")
- os.dup2(targetfd_save, self.targetfd)
- os.close(targetfd_save)
- self.syscapture.done()
- self.tmpfile.close()
-
- def suspend(self):
- self.syscapture.suspend()
- os.dup2(self.targetfd_save, self.targetfd)
-
- def resume(self):
- self.syscapture.resume()
- os.dup2(self.tmpfile_fd, self.targetfd)
-
- def writeorg(self, data):
- """ write to original file descriptor. """
- if py.builtin._istext(data):
- data = data.encode("utf8") # XXX use encoding of original stream
- os.write(self.targetfd_save, data)
-
-
-class SysCapture:
- def __init__(self, fd, tmpfile=None):
- name = patchsysdict[fd]
- self._old = getattr(sys, name)
- self.name = name
- if tmpfile is None:
- if name == "stdin":
- tmpfile = DontReadFromInput()
- else:
- tmpfile = TextIO()
- self.tmpfile = tmpfile
-
- def start(self):
- setattr(sys, self.name, self.tmpfile)
-
- def snap(self):
- f = self.tmpfile
- res = f.getvalue()
- f.truncate(0)
- f.seek(0)
- return res
-
- def done(self):
- setattr(sys, self.name, self._old)
- del self._old
- self.tmpfile.close()
-
- def suspend(self):
- setattr(sys, self.name, self._old)
-
- def resume(self):
- setattr(sys, self.name, self.tmpfile)
-
- def writeorg(self, data):
- self._old.write(data)
- self._old.flush()
-
-
-class DontReadFromInput:
- """Temporary stub class. Ideally when stdin is accessed, the
- capturing should be turned off, with possibly all data captured
- so far sent to the screen. This should be configurable, though,
- because in automated test runs it is better to crash than
- hang indefinitely.
- """
-
- encoding = None
-
- def read(self, *args):
- raise IOError("reading from stdin while output is captured")
- readline = read
- readlines = read
- __iter__ = read
-
- def fileno(self):
- raise ValueError("redirected Stdin is pseudofile, has no fileno()")
-
- def isatty(self):
- return False
-
- def close(self):
- pass
-
-
-def _readline_workaround():
- """
- Ensure readline is imported so that it attaches to the correct stdio
- handles on Windows.
-
- Pdb uses readline support where available--when not running from the Python
- prompt, the readline module is not imported until running the pdb REPL. If
- running py.test with the --pdb option this means the readline module is not
- imported until after I/O capture has been started.
-
- This is a problem for pyreadline, which is often used to implement readline
- support on Windows, as it does not attach to the correct handles for stdout
- and/or stdin if they have been redirected by the FDCapture mechanism. This
- workaround ensures that readline is imported before I/O capture is setup so
- that it can attach to the actual stdin/out for the console.
-
- See https://github.com/pytest-dev/pytest/pull/1281
- """
-
- if not sys.platform.startswith('win32'):
- return
- try:
- import readline # noqa
- except ImportError:
- pass
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/config.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/config.py
deleted file mode 100644
index fb7b1774f68..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/config.py
+++ /dev/null
@@ -1,1192 +0,0 @@
-""" command line options, ini-file and conftest.py processing. """
-import argparse
-import shlex
-import traceback
-import types
-import warnings
-
-import py
-# DON't import pytest here because it causes import cycle troubles
-import sys, os
-import _pytest._code
-import _pytest.hookspec # the extension point definitions
-from _pytest._pluggy import PluginManager, HookimplMarker, HookspecMarker
-
-hookimpl = HookimplMarker("pytest")
-hookspec = HookspecMarker("pytest")
-
-# pytest startup
-#
-
-
-class ConftestImportFailure(Exception):
- def __init__(self, path, excinfo):
- Exception.__init__(self, path, excinfo)
- self.path = path
- self.excinfo = excinfo
-
-
-def main(args=None, plugins=None):
- """ return exit code, after performing an in-process test run.
-
- :arg args: list of command line arguments.
-
- :arg plugins: list of plugin objects to be auto-registered during
- initialization.
- """
- try:
- try:
- config = _prepareconfig(args, plugins)
- except ConftestImportFailure as e:
- tw = py.io.TerminalWriter(sys.stderr)
- for line in traceback.format_exception(*e.excinfo):
- tw.line(line.rstrip(), red=True)
- tw.line("ERROR: could not load %s\n" % (e.path), red=True)
- return 4
- else:
- try:
- config.pluginmanager.check_pending()
- return config.hook.pytest_cmdline_main(config=config)
- finally:
- config._ensure_unconfigure()
- except UsageError as e:
- for msg in e.args:
- sys.stderr.write("ERROR: %s\n" %(msg,))
- return 4
-
-class cmdline: # compatibility namespace
- main = staticmethod(main)
-
-class UsageError(Exception):
- """ error in pytest usage or invocation"""
-
-_preinit = []
-
-default_plugins = (
- "mark main terminal runner python pdb unittest capture skipping "
- "tmpdir monkeypatch recwarn pastebin helpconfig nose assertion genscript "
- "junitxml resultlog doctest cacheprovider").split()
-
-builtin_plugins = set(default_plugins)
-builtin_plugins.add("pytester")
-
-
-def _preloadplugins():
- assert not _preinit
- _preinit.append(get_config())
-
-def get_config():
- if _preinit:
- return _preinit.pop(0)
- # subsequent calls to main will create a fresh instance
- pluginmanager = PytestPluginManager()
- config = Config(pluginmanager)
- for spec in default_plugins:
- pluginmanager.import_plugin(spec)
- return config
-
-def get_plugin_manager():
- """
- Obtain a new instance of the
- :py:class:`_pytest.config.PytestPluginManager`, with default plugins
- already loaded.
-
- This function can be used by integration with other tools, like hooking
- into pytest to run tests into an IDE.
- """
- return get_config().pluginmanager
-
-def _prepareconfig(args=None, plugins=None):
- if args is None:
- args = sys.argv[1:]
- elif isinstance(args, py.path.local):
- args = [str(args)]
- elif not isinstance(args, (tuple, list)):
- if not isinstance(args, str):
- raise ValueError("not a string or argument list: %r" % (args,))
- args = shlex.split(args)
- config = get_config()
- pluginmanager = config.pluginmanager
- try:
- if plugins:
- for plugin in plugins:
- if isinstance(plugin, py.builtin._basestring):
- pluginmanager.consider_pluginarg(plugin)
- else:
- pluginmanager.register(plugin)
- return pluginmanager.hook.pytest_cmdline_parse(
- pluginmanager=pluginmanager, args=args)
- except BaseException:
- config._ensure_unconfigure()
- raise
-
-
-class PytestPluginManager(PluginManager):
- """
- Overwrites :py:class:`pluggy.PluginManager` to add pytest-specific
- functionality:
-
- * loading plugins from the command line, ``PYTEST_PLUGIN`` env variable and
- ``pytest_plugins`` global variables found in plugins being loaded;
- * ``conftest.py`` loading during start-up;
- """
- def __init__(self):
- super(PytestPluginManager, self).__init__("pytest", implprefix="pytest_")
- self._conftest_plugins = set()
-
- # state related to local conftest plugins
- self._path2confmods = {}
- self._conftestpath2mod = {}
- self._confcutdir = None
- self._noconftest = False
-
- self.add_hookspecs(_pytest.hookspec)
- self.register(self)
- if os.environ.get('PYTEST_DEBUG'):
- err = sys.stderr
- encoding = getattr(err, 'encoding', 'utf8')
- try:
- err = py.io.dupfile(err, encoding=encoding)
- except Exception:
- pass
- self.trace.root.setwriter(err.write)
- self.enable_tracing()
-
- def addhooks(self, module_or_class):
- """
- .. deprecated:: 2.8
-
- Use :py:meth:`pluggy.PluginManager.add_hookspecs` instead.
- """
- warning = dict(code="I2",
- fslocation=_pytest._code.getfslineno(sys._getframe(1)),
- nodeid=None,
- message="use pluginmanager.add_hookspecs instead of "
- "deprecated addhooks() method.")
- self._warn(warning)
- return self.add_hookspecs(module_or_class)
-
- def parse_hookimpl_opts(self, plugin, name):
- # pytest hooks are always prefixed with pytest_
- # so we avoid accessing possibly non-readable attributes
- # (see issue #1073)
- if not name.startswith("pytest_"):
- return
- # ignore some historic special names which can not be hooks anyway
- if name == "pytest_plugins" or name.startswith("pytest_funcarg__"):
- return
-
- method = getattr(plugin, name)
- opts = super(PytestPluginManager, self).parse_hookimpl_opts(plugin, name)
- if opts is not None:
- for name in ("tryfirst", "trylast", "optionalhook", "hookwrapper"):
- opts.setdefault(name, hasattr(method, name))
- return opts
-
- def parse_hookspec_opts(self, module_or_class, name):
- opts = super(PytestPluginManager, self).parse_hookspec_opts(
- module_or_class, name)
- if opts is None:
- method = getattr(module_or_class, name)
- if name.startswith("pytest_"):
- opts = {"firstresult": hasattr(method, "firstresult"),
- "historic": hasattr(method, "historic")}
- return opts
-
- def _verify_hook(self, hook, hookmethod):
- super(PytestPluginManager, self)._verify_hook(hook, hookmethod)
- if "__multicall__" in hookmethod.argnames:
- fslineno = _pytest._code.getfslineno(hookmethod.function)
- warning = dict(code="I1",
- fslocation=fslineno,
- nodeid=None,
- message="%r hook uses deprecated __multicall__ "
- "argument" % (hook.name))
- self._warn(warning)
-
- def register(self, plugin, name=None):
- ret = super(PytestPluginManager, self).register(plugin, name)
- if ret:
- self.hook.pytest_plugin_registered.call_historic(
- kwargs=dict(plugin=plugin, manager=self))
- return ret
-
- def getplugin(self, name):
- # support deprecated naming because plugins (xdist e.g.) use it
- return self.get_plugin(name)
-
- def hasplugin(self, name):
- """Return True if the plugin with the given name is registered."""
- return bool(self.get_plugin(name))
-
- def pytest_configure(self, config):
- # XXX now that the pluginmanager exposes hookimpl(tryfirst...)
- # we should remove tryfirst/trylast as markers
- config.addinivalue_line("markers",
- "tryfirst: mark a hook implementation function such that the "
- "plugin machinery will try to call it first/as early as possible.")
- config.addinivalue_line("markers",
- "trylast: mark a hook implementation function such that the "
- "plugin machinery will try to call it last/as late as possible.")
-
- def _warn(self, message):
- kwargs = message if isinstance(message, dict) else {
- 'code': 'I1',
- 'message': message,
- 'fslocation': None,
- 'nodeid': None,
- }
- self.hook.pytest_logwarning.call_historic(kwargs=kwargs)
-
- #
- # internal API for local conftest plugin handling
- #
- def _set_initial_conftests(self, namespace):
- """ load initial conftest files given a preparsed "namespace".
- As conftest files may add their own command line options
- which have arguments ('--my-opt somepath') we might get some
- false positives. All builtin and 3rd party plugins will have
- been loaded, however, so common options will not confuse our logic
- here.
- """
- current = py.path.local()
- self._confcutdir = current.join(namespace.confcutdir, abs=True) \
- if namespace.confcutdir else None
- self._noconftest = namespace.noconftest
- testpaths = namespace.file_or_dir
- foundanchor = False
- for path in testpaths:
- path = str(path)
- # remove node-id syntax
- i = path.find("::")
- if i != -1:
- path = path[:i]
- anchor = current.join(path, abs=1)
- if exists(anchor): # we found some file object
- self._try_load_conftest(anchor)
- foundanchor = True
- if not foundanchor:
- self._try_load_conftest(current)
-
- def _try_load_conftest(self, anchor):
- self._getconftestmodules(anchor)
- # let's also consider test* subdirs
- if anchor.check(dir=1):
- for x in anchor.listdir("test*"):
- if x.check(dir=1):
- self._getconftestmodules(x)
-
- def _getconftestmodules(self, path):
- if self._noconftest:
- return []
- try:
- return self._path2confmods[path]
- except KeyError:
- if path.isfile():
- clist = self._getconftestmodules(path.dirpath())
- else:
- # XXX these days we may rather want to use config.rootdir
- # and allow users to opt into looking into the rootdir parent
- # directories instead of requiring to specify confcutdir
- clist = []
- for parent in path.parts():
- if self._confcutdir and self._confcutdir.relto(parent):
- continue
- conftestpath = parent.join("conftest.py")
- if conftestpath.isfile():
- mod = self._importconftest(conftestpath)
- clist.append(mod)
-
- self._path2confmods[path] = clist
- return clist
-
- def _rget_with_confmod(self, name, path):
- modules = self._getconftestmodules(path)
- for mod in reversed(modules):
- try:
- return mod, getattr(mod, name)
- except AttributeError:
- continue
- raise KeyError(name)
-
- def _importconftest(self, conftestpath):
- try:
- return self._conftestpath2mod[conftestpath]
- except KeyError:
- pkgpath = conftestpath.pypkgpath()
- if pkgpath is None:
- _ensure_removed_sysmodule(conftestpath.purebasename)
- try:
- mod = conftestpath.pyimport()
- except Exception:
- raise ConftestImportFailure(conftestpath, sys.exc_info())
-
- self._conftest_plugins.add(mod)
- self._conftestpath2mod[conftestpath] = mod
- dirpath = conftestpath.dirpath()
- if dirpath in self._path2confmods:
- for path, mods in self._path2confmods.items():
- if path and path.relto(dirpath) or path == dirpath:
- assert mod not in mods
- mods.append(mod)
- self.trace("loaded conftestmodule %r" %(mod))
- self.consider_conftest(mod)
- return mod
-
- #
- # API for bootstrapping plugin loading
- #
- #
-
- def consider_preparse(self, args):
- for opt1,opt2 in zip(args, args[1:]):
- if opt1 == "-p":
- self.consider_pluginarg(opt2)
-
- def consider_pluginarg(self, arg):
- if arg.startswith("no:"):
- name = arg[3:]
- self.set_blocked(name)
- if not name.startswith("pytest_"):
- self.set_blocked("pytest_" + name)
- else:
- self.import_plugin(arg)
-
- def consider_conftest(self, conftestmodule):
- if self.register(conftestmodule, name=conftestmodule.__file__):
- self.consider_module(conftestmodule)
-
- def consider_env(self):
- self._import_plugin_specs(os.environ.get("PYTEST_PLUGINS"))
-
- def consider_module(self, mod):
- self._import_plugin_specs(getattr(mod, "pytest_plugins", None))
-
- def _import_plugin_specs(self, spec):
- if spec:
- if isinstance(spec, str):
- spec = spec.split(",")
- for import_spec in spec:
- self.import_plugin(import_spec)
-
- def import_plugin(self, modname):
- # most often modname refers to builtin modules, e.g. "pytester",
- # "terminal" or "capture". Those plugins are registered under their
- # basename for historic purposes but must be imported with the
- # _pytest prefix.
- assert isinstance(modname, str)
- if self.get_plugin(modname) is not None:
- return
- if modname in builtin_plugins:
- importspec = "_pytest." + modname
- else:
- importspec = modname
- try:
- __import__(importspec)
- except ImportError as e:
- new_exc = ImportError('Error importing plugin "%s": %s' % (modname, e))
- # copy over name and path attributes
- for attr in ('name', 'path'):
- if hasattr(e, attr):
- setattr(new_exc, attr, getattr(e, attr))
- raise new_exc
- except Exception as e:
- import pytest
- if not hasattr(pytest, 'skip') or not isinstance(e, pytest.skip.Exception):
- raise
- self._warn("skipped plugin %r: %s" %((modname, e.msg)))
- else:
- mod = sys.modules[importspec]
- self.register(mod, modname)
- self.consider_module(mod)
-
-
-class Parser:
- """ Parser for command line arguments and ini-file values.
-
- :ivar extra_info: dict of generic param -> value to display in case
- there's an error processing the command line arguments.
- """
-
- def __init__(self, usage=None, processopt=None):
- self._anonymous = OptionGroup("custom options", parser=self)
- self._groups = []
- self._processopt = processopt
- self._usage = usage
- self._inidict = {}
- self._ininames = []
- self.extra_info = {}
-
- def processoption(self, option):
- if self._processopt:
- if option.dest:
- self._processopt(option)
-
- def getgroup(self, name, description="", after=None):
- """ get (or create) a named option Group.
-
- :name: name of the option group.
- :description: long description for --help output.
- :after: name of other group, used for ordering --help output.
-
- The returned group object has an ``addoption`` method with the same
- signature as :py:func:`parser.addoption
- <_pytest.config.Parser.addoption>` but will be shown in the
- respective group in the output of ``pytest. --help``.
- """
- for group in self._groups:
- if group.name == name:
- return group
- group = OptionGroup(name, description, parser=self)
- i = 0
- for i, grp in enumerate(self._groups):
- if grp.name == after:
- break
- self._groups.insert(i+1, group)
- return group
-
- def addoption(self, *opts, **attrs):
- """ register a command line option.
-
- :opts: option names, can be short or long options.
- :attrs: same attributes which the ``add_option()`` function of the
- `argparse library
- <http://docs.python.org/2/library/argparse.html>`_
- accepts.
-
- After command line parsing options are available on the pytest config
- object via ``config.option.NAME`` where ``NAME`` is usually set
- by passing a ``dest`` attribute, for example
- ``addoption("--long", dest="NAME", ...)``.
- """
- self._anonymous.addoption(*opts, **attrs)
-
- def parse(self, args, namespace=None):
- from _pytest._argcomplete import try_argcomplete
- self.optparser = self._getparser()
- try_argcomplete(self.optparser)
- return self.optparser.parse_args([str(x) for x in args], namespace=namespace)
-
- def _getparser(self):
- from _pytest._argcomplete import filescompleter
- optparser = MyOptionParser(self, self.extra_info)
- groups = self._groups + [self._anonymous]
- for group in groups:
- if group.options:
- desc = group.description or group.name
- arggroup = optparser.add_argument_group(desc)
- for option in group.options:
- n = option.names()
- a = option.attrs()
- arggroup.add_argument(*n, **a)
- # bash like autocompletion for dirs (appending '/')
- optparser.add_argument(FILE_OR_DIR, nargs='*').completer=filescompleter
- return optparser
-
- def parse_setoption(self, args, option, namespace=None):
- parsedoption = self.parse(args, namespace=namespace)
- for name, value in parsedoption.__dict__.items():
- setattr(option, name, value)
- return getattr(parsedoption, FILE_OR_DIR)
-
- def parse_known_args(self, args, namespace=None):
- """parses and returns a namespace object with known arguments at this
- point.
- """
- return self.parse_known_and_unknown_args(args, namespace=namespace)[0]
-
- def parse_known_and_unknown_args(self, args, namespace=None):
- """parses and returns a namespace object with known arguments, and
- the remaining arguments unknown at this point.
- """
- optparser = self._getparser()
- args = [str(x) for x in args]
- return optparser.parse_known_args(args, namespace=namespace)
-
- def addini(self, name, help, type=None, default=None):
- """ register an ini-file option.
-
- :name: name of the ini-variable
- :type: type of the variable, can be ``pathlist``, ``args``, ``linelist``
- or ``bool``.
- :default: default value if no ini-file option exists but is queried.
-
- The value of ini-variables can be retrieved via a call to
- :py:func:`config.getini(name) <_pytest.config.Config.getini>`.
- """
- assert type in (None, "pathlist", "args", "linelist", "bool")
- self._inidict[name] = (help, type, default)
- self._ininames.append(name)
-
-
-class ArgumentError(Exception):
- """
- Raised if an Argument instance is created with invalid or
- inconsistent arguments.
- """
-
- def __init__(self, msg, option):
- self.msg = msg
- self.option_id = str(option)
-
- def __str__(self):
- if self.option_id:
- return "option %s: %s" % (self.option_id, self.msg)
- else:
- return self.msg
-
-
-class Argument:
- """class that mimics the necessary behaviour of optparse.Option """
- _typ_map = {
- 'int': int,
- 'string': str,
- }
- # enable after some grace period for plugin writers
- TYPE_WARN = False
-
- def __init__(self, *names, **attrs):
- """store parms in private vars for use in add_argument"""
- self._attrs = attrs
- self._short_opts = []
- self._long_opts = []
- self.dest = attrs.get('dest')
- if self.TYPE_WARN:
- try:
- help = attrs['help']
- if '%default' in help:
- warnings.warn(
- 'pytest now uses argparse. "%default" should be'
- ' changed to "%(default)s" ',
- FutureWarning,
- stacklevel=3)
- except KeyError:
- pass
- try:
- typ = attrs['type']
- except KeyError:
- pass
- else:
- # this might raise a keyerror as well, don't want to catch that
- if isinstance(typ, py.builtin._basestring):
- if typ == 'choice':
- if self.TYPE_WARN:
- warnings.warn(
- 'type argument to addoption() is a string %r.'
- ' For parsearg this is optional and when supplied '
- ' should be a type.'
- ' (options: %s)' % (typ, names),
- FutureWarning,
- stacklevel=3)
- # argparse expects a type here take it from
- # the type of the first element
- attrs['type'] = type(attrs['choices'][0])
- else:
- if self.TYPE_WARN:
- warnings.warn(
- 'type argument to addoption() is a string %r.'
- ' For parsearg this should be a type.'
- ' (options: %s)' % (typ, names),
- FutureWarning,
- stacklevel=3)
- attrs['type'] = Argument._typ_map[typ]
- # used in test_parseopt -> test_parse_defaultgetter
- self.type = attrs['type']
- else:
- self.type = typ
- try:
- # attribute existence is tested in Config._processopt
- self.default = attrs['default']
- except KeyError:
- pass
- self._set_opt_strings(names)
- if not self.dest:
- if self._long_opts:
- self.dest = self._long_opts[0][2:].replace('-', '_')
- else:
- try:
- self.dest = self._short_opts[0][1:]
- except IndexError:
- raise ArgumentError(
- 'need a long or short option', self)
-
- def names(self):
- return self._short_opts + self._long_opts
-
- def attrs(self):
- # update any attributes set by processopt
- attrs = 'default dest help'.split()
- if self.dest:
- attrs.append(self.dest)
- for attr in attrs:
- try:
- self._attrs[attr] = getattr(self, attr)
- except AttributeError:
- pass
- if self._attrs.get('help'):
- a = self._attrs['help']
- a = a.replace('%default', '%(default)s')
- #a = a.replace('%prog', '%(prog)s')
- self._attrs['help'] = a
- return self._attrs
-
- def _set_opt_strings(self, opts):
- """directly from optparse
-
- might not be necessary as this is passed to argparse later on"""
- for opt in opts:
- if len(opt) < 2:
- raise ArgumentError(
- "invalid option string %r: "
- "must be at least two characters long" % opt, self)
- elif len(opt) == 2:
- if not (opt[0] == "-" and opt[1] != "-"):
- raise ArgumentError(
- "invalid short option string %r: "
- "must be of the form -x, (x any non-dash char)" % opt,
- self)
- self._short_opts.append(opt)
- else:
- if not (opt[0:2] == "--" and opt[2] != "-"):
- raise ArgumentError(
- "invalid long option string %r: "
- "must start with --, followed by non-dash" % opt,
- self)
- self._long_opts.append(opt)
-
- def __repr__(self):
- retval = 'Argument('
- if self._short_opts:
- retval += '_short_opts: ' + repr(self._short_opts) + ', '
- if self._long_opts:
- retval += '_long_opts: ' + repr(self._long_opts) + ', '
- retval += 'dest: ' + repr(self.dest) + ', '
- if hasattr(self, 'type'):
- retval += 'type: ' + repr(self.type) + ', '
- if hasattr(self, 'default'):
- retval += 'default: ' + repr(self.default) + ', '
- if retval[-2:] == ', ': # always long enough to test ("Argument(" )
- retval = retval[:-2]
- retval += ')'
- return retval
-
-
-class OptionGroup:
- def __init__(self, name, description="", parser=None):
- self.name = name
- self.description = description
- self.options = []
- self.parser = parser
-
- def addoption(self, *optnames, **attrs):
- """ add an option to this group.
-
- if a shortened version of a long option is specified it will
- be suppressed in the help. addoption('--twowords', '--two-words')
- results in help showing '--two-words' only, but --twowords gets
- accepted **and** the automatic destination is in args.twowords
- """
- option = Argument(*optnames, **attrs)
- self._addoption_instance(option, shortupper=False)
-
- def _addoption(self, *optnames, **attrs):
- option = Argument(*optnames, **attrs)
- self._addoption_instance(option, shortupper=True)
-
- def _addoption_instance(self, option, shortupper=False):
- if not shortupper:
- for opt in option._short_opts:
- if opt[0] == '-' and opt[1].islower():
- raise ValueError("lowercase shortoptions reserved")
- if self.parser:
- self.parser.processoption(option)
- self.options.append(option)
-
-
-class MyOptionParser(argparse.ArgumentParser):
- def __init__(self, parser, extra_info=None):
- if not extra_info:
- extra_info = {}
- self._parser = parser
- argparse.ArgumentParser.__init__(self, usage=parser._usage,
- add_help=False, formatter_class=DropShorterLongHelpFormatter)
- # extra_info is a dict of (param -> value) to display if there's
- # an usage error to provide more contextual information to the user
- self.extra_info = extra_info
-
- def parse_args(self, args=None, namespace=None):
- """allow splitting of positional arguments"""
- args, argv = self.parse_known_args(args, namespace)
- if argv:
- for arg in argv:
- if arg and arg[0] == '-':
- lines = ['unrecognized arguments: %s' % (' '.join(argv))]
- for k, v in sorted(self.extra_info.items()):
- lines.append(' %s: %s' % (k, v))
- self.error('\n'.join(lines))
- getattr(args, FILE_OR_DIR).extend(argv)
- return args
-
-
-class DropShorterLongHelpFormatter(argparse.HelpFormatter):
- """shorten help for long options that differ only in extra hyphens
-
- - collapse **long** options that are the same except for extra hyphens
- - special action attribute map_long_option allows surpressing additional
- long options
- - shortcut if there are only two options and one of them is a short one
- - cache result on action object as this is called at least 2 times
- """
- def _format_action_invocation(self, action):
- orgstr = argparse.HelpFormatter._format_action_invocation(self, action)
- if orgstr and orgstr[0] != '-': # only optional arguments
- return orgstr
- res = getattr(action, '_formatted_action_invocation', None)
- if res:
- return res
- options = orgstr.split(', ')
- if len(options) == 2 and (len(options[0]) == 2 or len(options[1]) == 2):
- # a shortcut for '-h, --help' or '--abc', '-a'
- action._formatted_action_invocation = orgstr
- return orgstr
- return_list = []
- option_map = getattr(action, 'map_long_option', {})
- if option_map is None:
- option_map = {}
- short_long = {}
- for option in options:
- if len(option) == 2 or option[2] == ' ':
- continue
- if not option.startswith('--'):
- raise ArgumentError('long optional argument without "--": [%s]'
- % (option), self)
- xxoption = option[2:]
- if xxoption.split()[0] not in option_map:
- shortened = xxoption.replace('-', '')
- if shortened not in short_long or \
- len(short_long[shortened]) < len(xxoption):
- short_long[shortened] = xxoption
- # now short_long has been filled out to the longest with dashes
- # **and** we keep the right option ordering from add_argument
- for option in options: #
- if len(option) == 2 or option[2] == ' ':
- return_list.append(option)
- if option[2:] == short_long.get(option.replace('-', '')):
- return_list.append(option.replace(' ', '='))
- action._formatted_action_invocation = ', '.join(return_list)
- return action._formatted_action_invocation
-
-
-
-def _ensure_removed_sysmodule(modname):
- try:
- del sys.modules[modname]
- except KeyError:
- pass
-
-class CmdOptions(object):
- """ holds cmdline options as attributes."""
- def __init__(self, values=()):
- self.__dict__.update(values)
- def __repr__(self):
- return "<CmdOptions %r>" %(self.__dict__,)
- def copy(self):
- return CmdOptions(self.__dict__)
-
-class Notset:
- def __repr__(self):
- return "<NOTSET>"
-
-notset = Notset()
-FILE_OR_DIR = 'file_or_dir'
-
-class Config(object):
- """ access to configuration values, pluginmanager and plugin hooks. """
-
- def __init__(self, pluginmanager):
- #: access to command line option as attributes.
- #: (deprecated), use :py:func:`getoption() <_pytest.config.Config.getoption>` instead
- self.option = CmdOptions()
- _a = FILE_OR_DIR
- self._parser = Parser(
- usage="%%(prog)s [options] [%s] [%s] [...]" % (_a, _a),
- processopt=self._processopt,
- )
- #: a pluginmanager instance
- self.pluginmanager = pluginmanager
- self.trace = self.pluginmanager.trace.root.get("config")
- self.hook = self.pluginmanager.hook
- self._inicache = {}
- self._opt2dest = {}
- self._cleanup = []
- self._warn = self.pluginmanager._warn
- self.pluginmanager.register(self, "pytestconfig")
- self._configured = False
- def do_setns(dic):
- import pytest
- setns(pytest, dic)
- self.hook.pytest_namespace.call_historic(do_setns, {})
- self.hook.pytest_addoption.call_historic(kwargs=dict(parser=self._parser))
-
- def add_cleanup(self, func):
- """ Add a function to be called when the config object gets out of
- use (usually coninciding with pytest_unconfigure)."""
- self._cleanup.append(func)
-
- def _do_configure(self):
- assert not self._configured
- self._configured = True
- self.hook.pytest_configure.call_historic(kwargs=dict(config=self))
-
- def _ensure_unconfigure(self):
- if self._configured:
- self._configured = False
- self.hook.pytest_unconfigure(config=self)
- self.hook.pytest_configure._call_history = []
- while self._cleanup:
- fin = self._cleanup.pop()
- fin()
-
- def warn(self, code, message, fslocation=None):
- """ generate a warning for this test session. """
- self.hook.pytest_logwarning.call_historic(kwargs=dict(
- code=code, message=message,
- fslocation=fslocation, nodeid=None))
-
- def get_terminal_writer(self):
- return self.pluginmanager.get_plugin("terminalreporter")._tw
-
- def pytest_cmdline_parse(self, pluginmanager, args):
- # REF1 assert self == pluginmanager.config, (self, pluginmanager.config)
- self.parse(args)
- return self
-
- def notify_exception(self, excinfo, option=None):
- if option and option.fulltrace:
- style = "long"
- else:
- style = "native"
- excrepr = excinfo.getrepr(funcargs=True,
- showlocals=getattr(option, 'showlocals', False),
- style=style,
- )
- res = self.hook.pytest_internalerror(excrepr=excrepr,
- excinfo=excinfo)
- if not py.builtin.any(res):
- for line in str(excrepr).split("\n"):
- sys.stderr.write("INTERNALERROR> %s\n" %line)
- sys.stderr.flush()
-
- def cwd_relative_nodeid(self, nodeid):
- # nodeid's are relative to the rootpath, compute relative to cwd
- if self.invocation_dir != self.rootdir:
- fullpath = self.rootdir.join(nodeid)
- nodeid = self.invocation_dir.bestrelpath(fullpath)
- return nodeid
-
- @classmethod
- def fromdictargs(cls, option_dict, args):
- """ constructor useable for subprocesses. """
- config = get_config()
- config.option.__dict__.update(option_dict)
- config.parse(args, addopts=False)
- for x in config.option.plugins:
- config.pluginmanager.consider_pluginarg(x)
- return config
-
- def _processopt(self, opt):
- for name in opt._short_opts + opt._long_opts:
- self._opt2dest[name] = opt.dest
-
- if hasattr(opt, 'default') and opt.dest:
- if not hasattr(self.option, opt.dest):
- setattr(self.option, opt.dest, opt.default)
-
- @hookimpl(trylast=True)
- def pytest_load_initial_conftests(self, early_config):
- self.pluginmanager._set_initial_conftests(early_config.known_args_namespace)
-
- def _initini(self, args):
- ns, unknown_args = self._parser.parse_known_and_unknown_args(args, namespace=self.option.copy())
- r = determine_setup(ns.inifilename, ns.file_or_dir + unknown_args)
- self.rootdir, self.inifile, self.inicfg = r
- self._parser.extra_info['rootdir'] = self.rootdir
- self._parser.extra_info['inifile'] = self.inifile
- self.invocation_dir = py.path.local()
- self._parser.addini('addopts', 'extra command line options', 'args')
- self._parser.addini('minversion', 'minimally required pytest version')
-
- def _preparse(self, args, addopts=True):
- self._initini(args)
- if addopts:
- args[:] = shlex.split(os.environ.get('PYTEST_ADDOPTS', '')) + args
- args[:] = self.getini("addopts") + args
- self._checkversion()
- self.pluginmanager.consider_preparse(args)
- try:
- self.pluginmanager.load_setuptools_entrypoints("pytest11")
- except ImportError as e:
- self.warn("I2", "could not load setuptools entry import: %s" % (e,))
- self.pluginmanager.consider_env()
- self.known_args_namespace = ns = self._parser.parse_known_args(args, namespace=self.option.copy())
- if self.known_args_namespace.confcutdir is None and self.inifile:
- confcutdir = py.path.local(self.inifile).dirname
- self.known_args_namespace.confcutdir = confcutdir
- try:
- self.hook.pytest_load_initial_conftests(early_config=self,
- args=args, parser=self._parser)
- except ConftestImportFailure:
- e = sys.exc_info()[1]
- if ns.help or ns.version:
- # we don't want to prevent --help/--version to work
- # so just let is pass and print a warning at the end
- self._warn("could not load initial conftests (%s)\n" % e.path)
- else:
- raise
-
- def _checkversion(self):
- import pytest
- minver = self.inicfg.get('minversion', None)
- if minver:
- ver = minver.split(".")
- myver = pytest.__version__.split(".")
- if myver < ver:
- raise pytest.UsageError(
- "%s:%d: requires pytest-%s, actual pytest-%s'" %(
- self.inicfg.config.path, self.inicfg.lineof('minversion'),
- minver, pytest.__version__))
-
- def parse(self, args, addopts=True):
- # parse given cmdline arguments into this config object.
- assert not hasattr(self, 'args'), (
- "can only parse cmdline args at most once per Config object")
- self._origargs = args
- self.hook.pytest_addhooks.call_historic(
- kwargs=dict(pluginmanager=self.pluginmanager))
- self._preparse(args, addopts=addopts)
- # XXX deprecated hook:
- self.hook.pytest_cmdline_preparse(config=self, args=args)
- args = self._parser.parse_setoption(args, self.option, namespace=self.option)
- if not args:
- cwd = os.getcwd()
- if cwd == self.rootdir:
- args = self.getini('testpaths')
- if not args:
- args = [cwd]
- self.args = args
-
- def addinivalue_line(self, name, line):
- """ add a line to an ini-file option. The option must have been
- declared but might not yet be set in which case the line becomes the
- the first line in its value. """
- x = self.getini(name)
- assert isinstance(x, list)
- x.append(line) # modifies the cached list inline
-
- def getini(self, name):
- """ return configuration value from an :ref:`ini file <inifiles>`. If the
- specified name hasn't been registered through a prior
- :py:func:`parser.addini <pytest.config.Parser.addini>`
- call (usually from a plugin), a ValueError is raised. """
- try:
- return self._inicache[name]
- except KeyError:
- self._inicache[name] = val = self._getini(name)
- return val
-
- def _getini(self, name):
- try:
- description, type, default = self._parser._inidict[name]
- except KeyError:
- raise ValueError("unknown configuration value: %r" %(name,))
- try:
- value = self.inicfg[name]
- except KeyError:
- if default is not None:
- return default
- if type is None:
- return ''
- return []
- if type == "pathlist":
- dp = py.path.local(self.inicfg.config.path).dirpath()
- l = []
- for relpath in shlex.split(value):
- l.append(dp.join(relpath, abs=True))
- return l
- elif type == "args":
- return shlex.split(value)
- elif type == "linelist":
- return [t for t in map(lambda x: x.strip(), value.split("\n")) if t]
- elif type == "bool":
- return bool(_strtobool(value.strip()))
- else:
- assert type is None
- return value
-
- def _getconftest_pathlist(self, name, path):
- try:
- mod, relroots = self.pluginmanager._rget_with_confmod(name, path)
- except KeyError:
- return None
- modpath = py.path.local(mod.__file__).dirpath()
- l = []
- for relroot in relroots:
- if not isinstance(relroot, py.path.local):
- relroot = relroot.replace("/", py.path.local.sep)
- relroot = modpath.join(relroot, abs=True)
- l.append(relroot)
- return l
-
- def getoption(self, name, default=notset, skip=False):
- """ return command line option value.
-
- :arg name: name of the option. You may also specify
- the literal ``--OPT`` option instead of the "dest" option name.
- :arg default: default value if no option of that name exists.
- :arg skip: if True raise pytest.skip if option does not exists
- or has a None value.
- """
- name = self._opt2dest.get(name, name)
- try:
- val = getattr(self.option, name)
- if val is None and skip:
- raise AttributeError(name)
- return val
- except AttributeError:
- if default is not notset:
- return default
- if skip:
- import pytest
- pytest.skip("no %r option found" %(name,))
- raise ValueError("no option named %r" % (name,))
-
- def getvalue(self, name, path=None):
- """ (deprecated, use getoption()) """
- return self.getoption(name)
-
- def getvalueorskip(self, name, path=None):
- """ (deprecated, use getoption(skip=True)) """
- return self.getoption(name, skip=True)
-
-def exists(path, ignore=EnvironmentError):
- try:
- return path.check()
- except ignore:
- return False
-
-def getcfg(args, inibasenames):
- args = [x for x in args if not str(x).startswith("-")]
- if not args:
- args = [py.path.local()]
- for arg in args:
- arg = py.path.local(arg)
- for base in arg.parts(reverse=True):
- for inibasename in inibasenames:
- p = base.join(inibasename)
- if exists(p):
- iniconfig = py.iniconfig.IniConfig(p)
- if 'pytest' in iniconfig.sections:
- return base, p, iniconfig['pytest']
- elif inibasename == "pytest.ini":
- # allowed to be empty
- return base, p, {}
- return None, None, None
-
-
-def get_common_ancestor(args):
- # args are what we get after early command line parsing (usually
- # strings, but can be py.path.local objects as well)
- common_ancestor = None
- for arg in args:
- if str(arg)[0] == "-":
- continue
- p = py.path.local(arg)
- if common_ancestor is None:
- common_ancestor = p
- else:
- if p.relto(common_ancestor) or p == common_ancestor:
- continue
- elif common_ancestor.relto(p):
- common_ancestor = p
- else:
- shared = p.common(common_ancestor)
- if shared is not None:
- common_ancestor = shared
- if common_ancestor is None:
- common_ancestor = py.path.local()
- elif not common_ancestor.isdir():
- common_ancestor = common_ancestor.dirpath()
- return common_ancestor
-
-
-def determine_setup(inifile, args):
- if inifile:
- iniconfig = py.iniconfig.IniConfig(inifile)
- try:
- inicfg = iniconfig["pytest"]
- except KeyError:
- inicfg = None
- rootdir = get_common_ancestor(args)
- else:
- ancestor = get_common_ancestor(args)
- rootdir, inifile, inicfg = getcfg(
- [ancestor], ["pytest.ini", "tox.ini", "setup.cfg"])
- if rootdir is None:
- for rootdir in ancestor.parts(reverse=True):
- if rootdir.join("setup.py").exists():
- break
- else:
- rootdir = ancestor
- return rootdir, inifile, inicfg or {}
-
-
-def setns(obj, dic):
- import pytest
- for name, value in dic.items():
- if isinstance(value, dict):
- mod = getattr(obj, name, None)
- if mod is None:
- modname = "pytest.%s" % name
- mod = types.ModuleType(modname)
- sys.modules[modname] = mod
- mod.__all__ = []
- setattr(obj, name, mod)
- obj.__all__.append(name)
- setns(mod, value)
- else:
- setattr(obj, name, value)
- obj.__all__.append(name)
- #if obj != pytest:
- # pytest.__all__.append(name)
- setattr(pytest, name, value)
-
-
-def create_terminal_writer(config, *args, **kwargs):
- """Create a TerminalWriter instance configured according to the options
- in the config object. Every code which requires a TerminalWriter object
- and has access to a config object should use this function.
- """
- tw = py.io.TerminalWriter(*args, **kwargs)
- if config.option.color == 'yes':
- tw.hasmarkup = True
- if config.option.color == 'no':
- tw.hasmarkup = False
- return tw
-
-
-def _strtobool(val):
- """Convert a string representation of truth to true (1) or false (0).
-
- True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
- are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if
- 'val' is anything else.
-
- .. note:: copied from distutils.util
- """
- val = val.lower()
- if val in ('y', 'yes', 't', 'true', 'on', '1'):
- return 1
- elif val in ('n', 'no', 'f', 'false', 'off', '0'):
- return 0
- else:
- raise ValueError("invalid truth value %r" % (val,))
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/doctest.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/doctest.py
deleted file mode 100644
index a57f7a4949e..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/doctest.py
+++ /dev/null
@@ -1,290 +0,0 @@
-""" discover and run doctests in modules and test files."""
-from __future__ import absolute_import
-
-import traceback
-
-import pytest
-from _pytest._code.code import TerminalRepr, ReprFileLocation, ExceptionInfo
-from _pytest.python import FixtureRequest
-
-
-
-def pytest_addoption(parser):
- parser.addini('doctest_optionflags', 'option flags for doctests',
- type="args", default=["ELLIPSIS"])
- group = parser.getgroup("collect")
- group.addoption("--doctest-modules",
- action="store_true", default=False,
- help="run doctests in all .py modules",
- dest="doctestmodules")
- group.addoption("--doctest-glob",
- action="append", default=[], metavar="pat",
- help="doctests file matching pattern, default: test*.txt",
- dest="doctestglob")
- group.addoption("--doctest-ignore-import-errors",
- action="store_true", default=False,
- help="ignore doctest ImportErrors",
- dest="doctest_ignore_import_errors")
-
-
-def pytest_collect_file(path, parent):
- config = parent.config
- if path.ext == ".py":
- if config.option.doctestmodules:
- return DoctestModule(path, parent)
- elif _is_doctest(config, path, parent):
- return DoctestTextfile(path, parent)
-
-
-def _is_doctest(config, path, parent):
- if path.ext in ('.txt', '.rst') and parent.session.isinitpath(path):
- return True
- globs = config.getoption("doctestglob") or ['test*.txt']
- for glob in globs:
- if path.check(fnmatch=glob):
- return True
- return False
-
-
-class ReprFailDoctest(TerminalRepr):
-
- def __init__(self, reprlocation, lines):
- self.reprlocation = reprlocation
- self.lines = lines
-
- def toterminal(self, tw):
- for line in self.lines:
- tw.line(line)
- self.reprlocation.toterminal(tw)
-
-
-class DoctestItem(pytest.Item):
-
- def __init__(self, name, parent, runner=None, dtest=None):
- super(DoctestItem, self).__init__(name, parent)
- self.runner = runner
- self.dtest = dtest
- self.obj = None
- self.fixture_request = None
-
- def setup(self):
- if self.dtest is not None:
- self.fixture_request = _setup_fixtures(self)
- globs = dict(getfixture=self.fixture_request.getfuncargvalue)
- self.dtest.globs.update(globs)
-
- def runtest(self):
- _check_all_skipped(self.dtest)
- self.runner.run(self.dtest)
-
- def repr_failure(self, excinfo):
- import doctest
- if excinfo.errisinstance((doctest.DocTestFailure,
- doctest.UnexpectedException)):
- doctestfailure = excinfo.value
- example = doctestfailure.example
- test = doctestfailure.test
- filename = test.filename
- if test.lineno is None:
- lineno = None
- else:
- lineno = test.lineno + example.lineno + 1
- message = excinfo.type.__name__
- reprlocation = ReprFileLocation(filename, lineno, message)
- checker = _get_checker()
- REPORT_UDIFF = doctest.REPORT_UDIFF
- if lineno is not None:
- lines = doctestfailure.test.docstring.splitlines(False)
- # add line numbers to the left of the error message
- lines = ["%03d %s" % (i + test.lineno + 1, x)
- for (i, x) in enumerate(lines)]
- # trim docstring error lines to 10
- lines = lines[example.lineno - 9:example.lineno + 1]
- else:
- lines = ['EXAMPLE LOCATION UNKNOWN, not showing all tests of that example']
- indent = '>>>'
- for line in example.source.splitlines():
- lines.append('??? %s %s' % (indent, line))
- indent = '...'
- if excinfo.errisinstance(doctest.DocTestFailure):
- lines += checker.output_difference(example,
- doctestfailure.got, REPORT_UDIFF).split("\n")
- else:
- inner_excinfo = ExceptionInfo(excinfo.value.exc_info)
- lines += ["UNEXPECTED EXCEPTION: %s" %
- repr(inner_excinfo.value)]
- lines += traceback.format_exception(*excinfo.value.exc_info)
- return ReprFailDoctest(reprlocation, lines)
- else:
- return super(DoctestItem, self).repr_failure(excinfo)
-
- def reportinfo(self):
- return self.fspath, None, "[doctest] %s" % self.name
-
-
-def _get_flag_lookup():
- import doctest
- return dict(DONT_ACCEPT_TRUE_FOR_1=doctest.DONT_ACCEPT_TRUE_FOR_1,
- DONT_ACCEPT_BLANKLINE=doctest.DONT_ACCEPT_BLANKLINE,
- NORMALIZE_WHITESPACE=doctest.NORMALIZE_WHITESPACE,
- ELLIPSIS=doctest.ELLIPSIS,
- IGNORE_EXCEPTION_DETAIL=doctest.IGNORE_EXCEPTION_DETAIL,
- COMPARISON_FLAGS=doctest.COMPARISON_FLAGS,
- ALLOW_UNICODE=_get_allow_unicode_flag(),
- ALLOW_BYTES=_get_allow_bytes_flag(),
- )
-
-
-def get_optionflags(parent):
- optionflags_str = parent.config.getini("doctest_optionflags")
- flag_lookup_table = _get_flag_lookup()
- flag_acc = 0
- for flag in optionflags_str:
- flag_acc |= flag_lookup_table[flag]
- return flag_acc
-
-
-class DoctestTextfile(DoctestItem, pytest.Module):
-
- def runtest(self):
- import doctest
- fixture_request = _setup_fixtures(self)
-
- # inspired by doctest.testfile; ideally we would use it directly,
- # but it doesn't support passing a custom checker
- text = self.fspath.read()
- filename = str(self.fspath)
- name = self.fspath.basename
- globs = dict(getfixture=fixture_request.getfuncargvalue)
- if '__name__' not in globs:
- globs['__name__'] = '__main__'
-
- optionflags = get_optionflags(self)
- runner = doctest.DebugRunner(verbose=0, optionflags=optionflags,
- checker=_get_checker())
-
- parser = doctest.DocTestParser()
- test = parser.get_doctest(text, globs, name, filename, 0)
- _check_all_skipped(test)
- runner.run(test)
-
-
-def _check_all_skipped(test):
- """raises pytest.skip() if all examples in the given DocTest have the SKIP
- option set.
- """
- import doctest
- all_skipped = all(x.options.get(doctest.SKIP, False) for x in test.examples)
- if all_skipped:
- pytest.skip('all tests skipped by +SKIP option')
-
-
-class DoctestModule(pytest.Module):
- def collect(self):
- import doctest
- if self.fspath.basename == "conftest.py":
- module = self.config.pluginmanager._importconftest(self.fspath)
- else:
- try:
- module = self.fspath.pyimport()
- except ImportError:
- if self.config.getvalue('doctest_ignore_import_errors'):
- pytest.skip('unable to import module %r' % self.fspath)
- else:
- raise
- # uses internal doctest module parsing mechanism
- finder = doctest.DocTestFinder()
- optionflags = get_optionflags(self)
- runner = doctest.DebugRunner(verbose=0, optionflags=optionflags,
- checker=_get_checker())
- for test in finder.find(module, module.__name__):
- if test.examples: # skip empty doctests
- yield DoctestItem(test.name, self, runner, test)
-
-
-def _setup_fixtures(doctest_item):
- """
- Used by DoctestTextfile and DoctestItem to setup fixture information.
- """
- def func():
- pass
-
- doctest_item.funcargs = {}
- fm = doctest_item.session._fixturemanager
- doctest_item._fixtureinfo = fm.getfixtureinfo(node=doctest_item, func=func,
- cls=None, funcargs=False)
- fixture_request = FixtureRequest(doctest_item)
- fixture_request._fillfixtures()
- return fixture_request
-
-
-def _get_checker():
- """
- Returns a doctest.OutputChecker subclass that takes in account the
- ALLOW_UNICODE option to ignore u'' prefixes in strings and ALLOW_BYTES
- to strip b'' prefixes.
- Useful when the same doctest should run in Python 2 and Python 3.
-
- An inner class is used to avoid importing "doctest" at the module
- level.
- """
- if hasattr(_get_checker, 'LiteralsOutputChecker'):
- return _get_checker.LiteralsOutputChecker()
-
- import doctest
- import re
-
- class LiteralsOutputChecker(doctest.OutputChecker):
- """
- Copied from doctest_nose_plugin.py from the nltk project:
- https://github.com/nltk/nltk
-
- Further extended to also support byte literals.
- """
-
- _unicode_literal_re = re.compile(r"(\W|^)[uU]([rR]?[\'\"])", re.UNICODE)
- _bytes_literal_re = re.compile(r"(\W|^)[bB]([rR]?[\'\"])", re.UNICODE)
-
- def check_output(self, want, got, optionflags):
- res = doctest.OutputChecker.check_output(self, want, got,
- optionflags)
- if res:
- return True
-
- allow_unicode = optionflags & _get_allow_unicode_flag()
- allow_bytes = optionflags & _get_allow_bytes_flag()
- if not allow_unicode and not allow_bytes:
- return False
-
- else: # pragma: no cover
- def remove_prefixes(regex, txt):
- return re.sub(regex, r'\1\2', txt)
-
- if allow_unicode:
- want = remove_prefixes(self._unicode_literal_re, want)
- got = remove_prefixes(self._unicode_literal_re, got)
- if allow_bytes:
- want = remove_prefixes(self._bytes_literal_re, want)
- got = remove_prefixes(self._bytes_literal_re, got)
- res = doctest.OutputChecker.check_output(self, want, got,
- optionflags)
- return res
-
- _get_checker.LiteralsOutputChecker = LiteralsOutputChecker
- return _get_checker.LiteralsOutputChecker()
-
-
-def _get_allow_unicode_flag():
- """
- Registers and returns the ALLOW_UNICODE flag.
- """
- import doctest
- return doctest.register_optionflag('ALLOW_UNICODE')
-
-
-def _get_allow_bytes_flag():
- """
- Registers and returns the ALLOW_BYTES flag.
- """
- import doctest
- return doctest.register_optionflag('ALLOW_BYTES')
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/genscript.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/genscript.py
deleted file mode 100755
index d2962d8fc82..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/genscript.py
+++ /dev/null
@@ -1,132 +0,0 @@
-""" (deprecated) generate a single-file self-contained version of pytest """
-import os
-import sys
-import pkgutil
-
-import py
-import _pytest
-
-
-
-def find_toplevel(name):
- for syspath in sys.path:
- base = py.path.local(syspath)
- lib = base/name
- if lib.check(dir=1):
- return lib
- mod = base.join("%s.py" % name)
- if mod.check(file=1):
- return mod
- raise LookupError(name)
-
-def pkgname(toplevel, rootpath, path):
- parts = path.parts()[len(rootpath.parts()):]
- return '.'.join([toplevel] + [x.purebasename for x in parts])
-
-def pkg_to_mapping(name):
- toplevel = find_toplevel(name)
- name2src = {}
- if toplevel.check(file=1): # module
- name2src[toplevel.purebasename] = toplevel.read()
- else: # package
- for pyfile in toplevel.visit('*.py'):
- pkg = pkgname(name, toplevel, pyfile)
- name2src[pkg] = pyfile.read()
- # with wheels py source code might be not be installed
- # and the resulting genscript is useless, just bail out.
- assert name2src, "no source code found for %r at %r" %(name, toplevel)
- return name2src
-
-def compress_mapping(mapping):
- import base64, pickle, zlib
- data = pickle.dumps(mapping, 2)
- data = zlib.compress(data, 9)
- data = base64.encodestring(data)
- data = data.decode('ascii')
- return data
-
-
-def compress_packages(names):
- mapping = {}
- for name in names:
- mapping.update(pkg_to_mapping(name))
- return compress_mapping(mapping)
-
-def generate_script(entry, packages):
- data = compress_packages(packages)
- tmpl = py.path.local(__file__).dirpath().join('standalonetemplate.py')
- exe = tmpl.read()
- exe = exe.replace('@SOURCES@', data)
- exe = exe.replace('@ENTRY@', entry)
- return exe
-
-
-def pytest_addoption(parser):
- group = parser.getgroup("debugconfig")
- group.addoption("--genscript", action="store", default=None,
- dest="genscript", metavar="path",
- help="create standalone pytest script at given target path.")
-
-def pytest_cmdline_main(config):
- import _pytest.config
- genscript = config.getvalue("genscript")
- if genscript:
- tw = _pytest.config.create_terminal_writer(config)
- tw.line("WARNING: usage of genscript is deprecated.",
- red=True)
- deps = ['py', '_pytest', 'pytest'] # pluggy is vendored
- if sys.version_info < (2,7):
- deps.append("argparse")
- tw.line("generated script will run on python2.6-python3.3++")
- else:
- tw.line("WARNING: generated script will not run on python2.6 "
- "due to 'argparse' dependency. Use python2.6 "
- "to generate a python2.6 compatible script", red=True)
- script = generate_script(
- 'import pytest; raise SystemExit(pytest.cmdline.main())',
- deps,
- )
- genscript = py.path.local(genscript)
- genscript.write(script)
- tw.line("generated pytest standalone script: %s" % genscript,
- bold=True)
- return 0
-
-
-def pytest_namespace():
- return {'freeze_includes': freeze_includes}
-
-
-def freeze_includes():
- """
- Returns a list of module names used by py.test that should be
- included by cx_freeze.
- """
- result = list(_iter_all_modules(py))
- result += list(_iter_all_modules(_pytest))
- return result
-
-
-def _iter_all_modules(package, prefix=''):
- """
- Iterates over the names of all modules that can be found in the given
- package, recursively.
-
- Example:
- _iter_all_modules(_pytest) ->
- ['_pytest.assertion.newinterpret',
- '_pytest.capture',
- '_pytest.core',
- ...
- ]
- """
- if type(package) is not str:
- path, prefix = package.__path__[0], package.__name__ + '.'
- else:
- path = package
- for _, name, is_package in pkgutil.iter_modules([path]):
- if is_package:
- for m in _iter_all_modules(os.path.join(path, name), prefix=name + '.'):
- yield prefix + m
- else:
- yield prefix + name
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/helpconfig.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/helpconfig.py
deleted file mode 100644
index 1df0c56ac7b..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/helpconfig.py
+++ /dev/null
@@ -1,139 +0,0 @@
-""" version info, help messages, tracing configuration. """
-import py
-import pytest
-import os, sys
-
-def pytest_addoption(parser):
- group = parser.getgroup('debugconfig')
- group.addoption('--version', action="store_true",
- help="display pytest lib version and import information.")
- group._addoption("-h", "--help", action="store_true", dest="help",
- help="show help message and configuration info")
- group._addoption('-p', action="append", dest="plugins", default = [],
- metavar="name",
- help="early-load given plugin (multi-allowed). "
- "To avoid loading of plugins, use the `no:` prefix, e.g. "
- "`no:doctest`.")
- group.addoption('--traceconfig', '--trace-config',
- action="store_true", default=False,
- help="trace considerations of conftest.py files."),
- group.addoption('--debug',
- action="store_true", dest="debug", default=False,
- help="store internal tracing debug information in 'pytestdebug.log'.")
-
-
-@pytest.hookimpl(hookwrapper=True)
-def pytest_cmdline_parse():
- outcome = yield
- config = outcome.get_result()
- if config.option.debug:
- path = os.path.abspath("pytestdebug.log")
- debugfile = open(path, 'w')
- debugfile.write("versions pytest-%s, py-%s, "
- "python-%s\ncwd=%s\nargs=%s\n\n" %(
- pytest.__version__, py.__version__,
- ".".join(map(str, sys.version_info)),
- os.getcwd(), config._origargs))
- config.trace.root.setwriter(debugfile.write)
- undo_tracing = config.pluginmanager.enable_tracing()
- sys.stderr.write("writing pytestdebug information to %s\n" % path)
- def unset_tracing():
- debugfile.close()
- sys.stderr.write("wrote pytestdebug information to %s\n" %
- debugfile.name)
- config.trace.root.setwriter(None)
- undo_tracing()
- config.add_cleanup(unset_tracing)
-
-def pytest_cmdline_main(config):
- if config.option.version:
- p = py.path.local(pytest.__file__)
- sys.stderr.write("This is pytest version %s, imported from %s\n" %
- (pytest.__version__, p))
- plugininfo = getpluginversioninfo(config)
- if plugininfo:
- for line in plugininfo:
- sys.stderr.write(line + "\n")
- return 0
- elif config.option.help:
- config._do_configure()
- showhelp(config)
- config._ensure_unconfigure()
- return 0
-
-def showhelp(config):
- reporter = config.pluginmanager.get_plugin('terminalreporter')
- tw = reporter._tw
- tw.write(config._parser.optparser.format_help())
- tw.line()
- tw.line()
- #tw.sep( "=", "config file settings")
- tw.line("[pytest] ini-options in the next "
- "pytest.ini|tox.ini|setup.cfg file:")
- tw.line()
-
- for name in config._parser._ininames:
- help, type, default = config._parser._inidict[name]
- if type is None:
- type = "string"
- spec = "%s (%s)" % (name, type)
- line = " %-24s %s" %(spec, help)
- tw.line(line[:tw.fullwidth])
-
- tw.line()
- tw.line("environment variables:")
- vars = [
- ("PYTEST_ADDOPTS", "extra command line options"),
- ("PYTEST_PLUGINS", "comma-separated plugins to load during startup"),
- ("PYTEST_DEBUG", "set to enable debug tracing of pytest's internals")
- ]
- for name, help in vars:
- tw.line(" %-24s %s" % (name, help))
- tw.line()
- tw.line()
-
- tw.line("to see available markers type: py.test --markers")
- tw.line("to see available fixtures type: py.test --fixtures")
- tw.line("(shown according to specified file_or_dir or current dir "
- "if not specified)")
-
- for warningreport in reporter.stats.get('warnings', []):
- tw.line("warning : " + warningreport.message, red=True)
- return
-
-
-conftest_options = [
- ('pytest_plugins', 'list of plugin names to load'),
-]
-
-def getpluginversioninfo(config):
- lines = []
- plugininfo = config.pluginmanager.list_plugin_distinfo()
- if plugininfo:
- lines.append("setuptools registered plugins:")
- for plugin, dist in plugininfo:
- loc = getattr(plugin, '__file__', repr(plugin))
- content = "%s-%s at %s" % (dist.project_name, dist.version, loc)
- lines.append(" " + content)
- return lines
-
-def pytest_report_header(config):
- lines = []
- if config.option.debug or config.option.traceconfig:
- lines.append("using: pytest-%s pylib-%s" %
- (pytest.__version__,py.__version__))
-
- verinfo = getpluginversioninfo(config)
- if verinfo:
- lines.extend(verinfo)
-
- if config.option.traceconfig:
- lines.append("active plugins:")
- items = config.pluginmanager.list_name_plugin()
- for name, plugin in items:
- if hasattr(plugin, '__file__'):
- r = plugin.__file__
- else:
- r = repr(plugin)
- lines.append(" %-20s: %s" %(name, r))
- return lines
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/hookspec.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/hookspec.py
deleted file mode 100644
index 60e9b47d262..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/hookspec.py
+++ /dev/null
@@ -1,295 +0,0 @@
-""" hook specifications for pytest plugins, invoked from main.py and builtin plugins. """
-
-from _pytest._pluggy import HookspecMarker
-
-hookspec = HookspecMarker("pytest")
-
-# -------------------------------------------------------------------------
-# Initialization hooks called for every plugin
-# -------------------------------------------------------------------------
-
-@hookspec(historic=True)
-def pytest_addhooks(pluginmanager):
- """called at plugin registration time to allow adding new hooks via a call to
- pluginmanager.add_hookspecs(module_or_class, prefix)."""
-
-
-@hookspec(historic=True)
-def pytest_namespace():
- """return dict of name->object to be made globally available in
- the pytest namespace. This hook is called at plugin registration
- time.
- """
-
-@hookspec(historic=True)
-def pytest_plugin_registered(plugin, manager):
- """ a new pytest plugin got registered. """
-
-
-@hookspec(historic=True)
-def pytest_addoption(parser):
- """register argparse-style options and ini-style config values,
- called once at the beginning of a test run.
-
- .. note::
-
- This function should be implemented only in plugins or ``conftest.py``
- files situated at the tests root directory due to how py.test
- :ref:`discovers plugins during startup <pluginorder>`.
-
- :arg parser: To add command line options, call
- :py:func:`parser.addoption(...) <_pytest.config.Parser.addoption>`.
- To add ini-file values call :py:func:`parser.addini(...)
- <_pytest.config.Parser.addini>`.
-
- Options can later be accessed through the
- :py:class:`config <_pytest.config.Config>` object, respectively:
-
- - :py:func:`config.getoption(name) <_pytest.config.Config.getoption>` to
- retrieve the value of a command line option.
-
- - :py:func:`config.getini(name) <_pytest.config.Config.getini>` to retrieve
- a value read from an ini-style file.
-
- The config object is passed around on many internal objects via the ``.config``
- attribute or can be retrieved as the ``pytestconfig`` fixture or accessed
- via (deprecated) ``pytest.config``.
- """
-
-@hookspec(historic=True)
-def pytest_configure(config):
- """ called after command line options have been parsed
- and all plugins and initial conftest files been loaded.
- This hook is called for every plugin.
- """
-
-# -------------------------------------------------------------------------
-# Bootstrapping hooks called for plugins registered early enough:
-# internal and 3rd party plugins as well as directly
-# discoverable conftest.py local plugins.
-# -------------------------------------------------------------------------
-
-@hookspec(firstresult=True)
-def pytest_cmdline_parse(pluginmanager, args):
- """return initialized config object, parsing the specified args. """
-
-def pytest_cmdline_preparse(config, args):
- """(deprecated) modify command line arguments before option parsing. """
-
-@hookspec(firstresult=True)
-def pytest_cmdline_main(config):
- """ called for performing the main command line action. The default
- implementation will invoke the configure hooks and runtest_mainloop. """
-
-def pytest_load_initial_conftests(early_config, parser, args):
- """ implements the loading of initial conftest files ahead
- of command line option parsing. """
-
-
-# -------------------------------------------------------------------------
-# collection hooks
-# -------------------------------------------------------------------------
-
-@hookspec(firstresult=True)
-def pytest_collection(session):
- """ perform the collection protocol for the given session. """
-
-def pytest_collection_modifyitems(session, config, items):
- """ called after collection has been performed, may filter or re-order
- the items in-place."""
-
-def pytest_collection_finish(session):
- """ called after collection has been performed and modified. """
-
-@hookspec(firstresult=True)
-def pytest_ignore_collect(path, config):
- """ return True to prevent considering this path for collection.
- This hook is consulted for all files and directories prior to calling
- more specific hooks.
- """
-
-@hookspec(firstresult=True)
-def pytest_collect_directory(path, parent):
- """ called before traversing a directory for collection files. """
-
-def pytest_collect_file(path, parent):
- """ return collection Node or None for the given path. Any new node
- needs to have the specified ``parent`` as a parent."""
-
-# logging hooks for collection
-def pytest_collectstart(collector):
- """ collector starts collecting. """
-
-def pytest_itemcollected(item):
- """ we just collected a test item. """
-
-def pytest_collectreport(report):
- """ collector finished collecting. """
-
-def pytest_deselected(items):
- """ called for test items deselected by keyword. """
-
-@hookspec(firstresult=True)
-def pytest_make_collect_report(collector):
- """ perform ``collector.collect()`` and return a CollectReport. """
-
-# -------------------------------------------------------------------------
-# Python test function related hooks
-# -------------------------------------------------------------------------
-
-@hookspec(firstresult=True)
-def pytest_pycollect_makemodule(path, parent):
- """ return a Module collector or None for the given path.
- This hook will be called for each matching test module path.
- The pytest_collect_file hook needs to be used if you want to
- create test modules for files that do not match as a test module.
- """
-
-@hookspec(firstresult=True)
-def pytest_pycollect_makeitem(collector, name, obj):
- """ return custom item/collector for a python object in a module, or None. """
-
-@hookspec(firstresult=True)
-def pytest_pyfunc_call(pyfuncitem):
- """ call underlying test function. """
-
-def pytest_generate_tests(metafunc):
- """ generate (multiple) parametrized calls to a test function."""
-
-# -------------------------------------------------------------------------
-# generic runtest related hooks
-# -------------------------------------------------------------------------
-
-@hookspec(firstresult=True)
-def pytest_runtestloop(session):
- """ called for performing the main runtest loop
- (after collection finished). """
-
-def pytest_itemstart(item, node):
- """ (deprecated, use pytest_runtest_logstart). """
-
-@hookspec(firstresult=True)
-def pytest_runtest_protocol(item, nextitem):
- """ implements the runtest_setup/call/teardown protocol for
- the given test item, including capturing exceptions and calling
- reporting hooks.
-
- :arg item: test item for which the runtest protocol is performed.
-
- :arg nextitem: the scheduled-to-be-next test item (or None if this
- is the end my friend). This argument is passed on to
- :py:func:`pytest_runtest_teardown`.
-
- :return boolean: True if no further hook implementations should be invoked.
- """
-
-def pytest_runtest_logstart(nodeid, location):
- """ signal the start of running a single test item. """
-
-def pytest_runtest_setup(item):
- """ called before ``pytest_runtest_call(item)``. """
-
-def pytest_runtest_call(item):
- """ called to execute the test ``item``. """
-
-def pytest_runtest_teardown(item, nextitem):
- """ called after ``pytest_runtest_call``.
-
- :arg nextitem: the scheduled-to-be-next test item (None if no further
- test item is scheduled). This argument can be used to
- perform exact teardowns, i.e. calling just enough finalizers
- so that nextitem only needs to call setup-functions.
- """
-
-@hookspec(firstresult=True)
-def pytest_runtest_makereport(item, call):
- """ return a :py:class:`_pytest.runner.TestReport` object
- for the given :py:class:`pytest.Item` and
- :py:class:`_pytest.runner.CallInfo`.
- """
-
-def pytest_runtest_logreport(report):
- """ process a test setup/call/teardown report relating to
- the respective phase of executing a test. """
-
-# -------------------------------------------------------------------------
-# test session related hooks
-# -------------------------------------------------------------------------
-
-def pytest_sessionstart(session):
- """ before session.main() is called. """
-
-def pytest_sessionfinish(session, exitstatus):
- """ whole test run finishes. """
-
-def pytest_unconfigure(config):
- """ called before test process is exited. """
-
-
-# -------------------------------------------------------------------------
-# hooks for customising the assert methods
-# -------------------------------------------------------------------------
-
-def pytest_assertrepr_compare(config, op, left, right):
- """return explanation for comparisons in failing assert expressions.
-
- Return None for no custom explanation, otherwise return a list
- of strings. The strings will be joined by newlines but any newlines
- *in* a string will be escaped. Note that all but the first line will
- be indented sligthly, the intention is for the first line to be a summary.
- """
-
-# -------------------------------------------------------------------------
-# hooks for influencing reporting (invoked from _pytest_terminal)
-# -------------------------------------------------------------------------
-
-def pytest_report_header(config, startdir):
- """ return a string to be displayed as header info for terminal reporting."""
-
-@hookspec(firstresult=True)
-def pytest_report_teststatus(report):
- """ return result-category, shortletter and verbose word for reporting."""
-
-def pytest_terminal_summary(terminalreporter):
- """ add additional section in terminal summary reporting. """
-
-
-@hookspec(historic=True)
-def pytest_logwarning(message, code, nodeid, fslocation):
- """ process a warning specified by a message, a code string,
- a nodeid and fslocation (both of which may be None
- if the warning is not tied to a partilar node/location)."""
-
-# -------------------------------------------------------------------------
-# doctest hooks
-# -------------------------------------------------------------------------
-
-@hookspec(firstresult=True)
-def pytest_doctest_prepare_content(content):
- """ return processed content for a given doctest"""
-
-# -------------------------------------------------------------------------
-# error handling and internal debugging hooks
-# -------------------------------------------------------------------------
-
-def pytest_internalerror(excrepr, excinfo):
- """ called for internal errors. """
-
-def pytest_keyboard_interrupt(excinfo):
- """ called for keyboard interrupt. """
-
-def pytest_exception_interact(node, call, report):
- """called when an exception was raised which can potentially be
- interactively handled.
-
- This hook is only called if an exception was raised
- that is not an internal exception like ``skip.Exception``.
- """
-
-def pytest_enter_pdb(config):
- """ called upon pdb.set_trace(), can be used by plugins to take special
- action just before the python debugger enters in interactive mode.
-
- :arg config: pytest config object
- :type config: _pytest.config.Config
- """
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/impl b/tests/wpt/web-platform-tests/tools/pytest/_pytest/impl
deleted file mode 100644
index 889e37e5abc..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/impl
+++ /dev/null
@@ -1,254 +0,0 @@
-Sorting per-resource
------------------------------
-
-for any given set of items:
-
-- collect items per session-scoped parametrized funcarg
-- re-order until items no parametrizations are mixed
-
- examples:
-
- test()
- test1(s1)
- test1(s2)
- test2()
- test3(s1)
- test3(s2)
-
- gets sorted to:
-
- test()
- test2()
- test1(s1)
- test3(s1)
- test1(s2)
- test3(s2)
-
-
-the new @setup functions
---------------------------------------
-
-Consider a given @setup-marked function::
-
- @pytest.mark.setup(maxscope=SCOPE)
- def mysetup(request, arg1, arg2, ...)
- ...
- request.addfinalizer(fin)
- ...
-
-then FUNCARGSET denotes the set of (arg1, arg2, ...) funcargs and
-all of its dependent funcargs. The mysetup function will execute
-for any matching test item once per scope.
-
-The scope is determined as the minimum scope of all scopes of the args
-in FUNCARGSET and the given "maxscope".
-
-If mysetup has been called and no finalizers have been called it is
-called "active".
-
-Furthermore the following rules apply:
-
-- if an arg value in FUNCARGSET is about to be torn down, the
- mysetup-registered finalizers will execute as well.
-
-- There will never be two active mysetup invocations.
-
-Example 1, session scope::
-
- @pytest.mark.funcarg(scope="session", params=[1,2])
- def db(request):
- request.addfinalizer(db_finalize)
-
- @pytest.mark.setup
- def mysetup(request, db):
- request.addfinalizer(mysetup_finalize)
- ...
-
-And a given test module:
-
- def test_something():
- ...
- def test_otherthing():
- pass
-
-Here is what happens::
-
- db(request) executes with request.param == 1
- mysetup(request, db) executes
- test_something() executes
- test_otherthing() executes
- mysetup_finalize() executes
- db_finalize() executes
- db(request) executes with request.param == 2
- mysetup(request, db) executes
- test_something() executes
- test_otherthing() executes
- mysetup_finalize() executes
- db_finalize() executes
-
-Example 2, session/function scope::
-
- @pytest.mark.funcarg(scope="session", params=[1,2])
- def db(request):
- request.addfinalizer(db_finalize)
-
- @pytest.mark.setup(scope="function")
- def mysetup(request, db):
- ...
- request.addfinalizer(mysetup_finalize)
- ...
-
-And a given test module:
-
- def test_something():
- ...
- def test_otherthing():
- pass
-
-Here is what happens::
-
- db(request) executes with request.param == 1
- mysetup(request, db) executes
- test_something() executes
- mysetup_finalize() executes
- mysetup(request, db) executes
- test_otherthing() executes
- mysetup_finalize() executes
- db_finalize() executes
- db(request) executes with request.param == 2
- mysetup(request, db) executes
- test_something() executes
- mysetup_finalize() executes
- mysetup(request, db) executes
- test_otherthing() executes
- mysetup_finalize() executes
- db_finalize() executes
-
-
-Example 3 - funcargs session-mix
-----------------------------------------
-
-Similar with funcargs, an example::
-
- @pytest.mark.funcarg(scope="session", params=[1,2])
- def db(request):
- request.addfinalizer(db_finalize)
-
- @pytest.mark.funcarg(scope="function")
- def table(request, db):
- ...
- request.addfinalizer(table_finalize)
- ...
-
-And a given test module:
-
- def test_something(table):
- ...
- def test_otherthing(table):
- pass
- def test_thirdthing():
- pass
-
-Here is what happens::
-
- db(request) executes with param == 1
- table(request, db)
- test_something(table)
- table_finalize()
- table(request, db)
- test_otherthing(table)
- table_finalize()
- db_finalize
- db(request) executes with param == 2
- table(request, db)
- test_something(table)
- table_finalize()
- table(request, db)
- test_otherthing(table)
- table_finalize()
- db_finalize
- test_thirdthing()
-
-Data structures
---------------------
-
-pytest internally maintains a dict of active funcargs with cache, param,
-finalizer, (scopeitem?) information:
-
- active_funcargs = dict()
-
-if a parametrized "db" is activated:
-
- active_funcargs["db"] = FuncargInfo(dbvalue, paramindex,
- FuncargFinalize(...), scopeitem)
-
-if a test is torn down and the next test requires a differently
-parametrized "db":
-
- for argname in item.callspec.params:
- if argname in active_funcargs:
- funcarginfo = active_funcargs[argname]
- if funcarginfo.param != item.callspec.params[argname]:
- funcarginfo.callfinalizer()
- del node2funcarg[funcarginfo.scopeitem]
- del active_funcargs[argname]
- nodes_to_be_torn_down = ...
- for node in nodes_to_be_torn_down:
- if node in node2funcarg:
- argname = node2funcarg[node]
- active_funcargs[argname].callfinalizer()
- del node2funcarg[node]
- del active_funcargs[argname]
-
-if a test is setup requiring a "db" funcarg:
-
- if "db" in active_funcargs:
- return active_funcargs["db"][0]
- funcarginfo = setup_funcarg()
- active_funcargs["db"] = funcarginfo
- node2funcarg[funcarginfo.scopeitem] = "db"
-
-Implementation plan for resources
-------------------------------------------
-
-1. Revert FuncargRequest to the old form, unmerge item/request
- (done)
-2. make funcarg factories be discovered at collection time
-3. Introduce funcarg marker
-4. Introduce funcarg scope parameter
-5. Introduce funcarg parametrize parameter
-6. make setup functions be discovered at collection time
-7. (Introduce a pytest_fixture_protocol/setup_funcargs hook)
-
-methods and data structures
---------------------------------
-
-A FuncarcManager holds all information about funcarg definitions
-including parametrization and scope definitions. It implements
-a pytest_generate_tests hook which performs parametrization as appropriate.
-
-as a simple example, let's consider a tree where a test function requires
-a "abc" funcarg and its factory defines it as parametrized and scoped
-for Modules. When collections hits the function item, it creates
-the metafunc object, and calls funcargdb.pytest_generate_tests(metafunc)
-which looks up available funcarg factories and their scope and parametrization.
-This information is equivalent to what can be provided today directly
-at the function site and it should thus be relatively straight forward
-to implement the additional way of defining parametrization/scoping.
-
-conftest loading:
- each funcarg-factory will populate the session.funcargmanager
-
-When a test item is collected, it grows a dictionary
-(funcargname2factorycalllist). A factory lookup is performed
-for each required funcarg. The resulting factory call is stored
-with the item. If a function is parametrized multiple items are
-created with respective factory calls. Else if a factory is parametrized
-multiple items and calls to the factory function are created as well.
-
-At setup time, an item populates a funcargs mapping, mapping names
-to values. If a value is funcarg factories are queried for a given item
-test functions and setup functions are put in a class
-which looks up required funcarg factories.
-
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/junitxml.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/junitxml.py
deleted file mode 100644
index 660d718a6a8..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/junitxml.py
+++ /dev/null
@@ -1,387 +0,0 @@
-"""
- report test results in JUnit-XML format,
- for use with Jenkins and build integration servers.
-
-
-Based on initial code from Ross Lawley.
-"""
-# Output conforms to https://github.com/jenkinsci/xunit-plugin/blob/master/
-# src/main/resources/org/jenkinsci/plugins/xunit/types/model/xsd/junit-10.xsd
-
-import py
-import os
-import re
-import sys
-import time
-import pytest
-
-# Python 2.X and 3.X compatibility
-if sys.version_info[0] < 3:
- from codecs import open
-else:
- unichr = chr
- unicode = str
- long = int
-
-
-class Junit(py.xml.Namespace):
- pass
-
-# We need to get the subset of the invalid unicode ranges according to
-# XML 1.0 which are valid in this python build. Hence we calculate
-# this dynamically instead of hardcoding it. The spec range of valid
-# chars is: Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD]
-# | [#x10000-#x10FFFF]
-_legal_chars = (0x09, 0x0A, 0x0d)
-_legal_ranges = (
- (0x20, 0x7E), (0x80, 0xD7FF), (0xE000, 0xFFFD), (0x10000, 0x10FFFF),
-)
-_legal_xml_re = [
- unicode("%s-%s") % (unichr(low), unichr(high))
- for (low, high) in _legal_ranges if low < sys.maxunicode
-]
-_legal_xml_re = [unichr(x) for x in _legal_chars] + _legal_xml_re
-illegal_xml_re = re.compile(unicode('[^%s]') % unicode('').join(_legal_xml_re))
-del _legal_chars
-del _legal_ranges
-del _legal_xml_re
-
-_py_ext_re = re.compile(r"\.py$")
-
-
-def bin_xml_escape(arg):
- def repl(matchobj):
- i = ord(matchobj.group())
- if i <= 0xFF:
- return unicode('#x%02X') % i
- else:
- return unicode('#x%04X') % i
-
- return py.xml.raw(illegal_xml_re.sub(repl, py.xml.escape(arg)))
-
-
-class _NodeReporter(object):
- def __init__(self, nodeid, xml):
-
- self.id = nodeid
- self.xml = xml
- self.add_stats = self.xml.add_stats
- self.duration = 0
- self.properties = []
- self.nodes = []
- self.testcase = None
- self.attrs = {}
-
- def append(self, node):
- self.xml.add_stats(type(node).__name__)
- self.nodes.append(node)
-
- def add_property(self, name, value):
- self.properties.append((str(name), bin_xml_escape(value)))
-
- def make_properties_node(self):
- """Return a Junit node containing custom properties, if any.
- """
- if self.properties:
- return Junit.properties([
- Junit.property(name=name, value=value)
- for name, value in self.properties
- ])
- return ''
-
- def record_testreport(self, testreport):
- assert not self.testcase
- names = mangle_test_address(testreport.nodeid)
- classnames = names[:-1]
- if self.xml.prefix:
- classnames.insert(0, self.xml.prefix)
- attrs = {
- "classname": ".".join(classnames),
- "name": bin_xml_escape(names[-1]),
- "file": testreport.location[0],
- }
- if testreport.location[1] is not None:
- attrs["line"] = testreport.location[1]
- self.attrs = attrs
-
- def to_xml(self):
- testcase = Junit.testcase(time=self.duration, **self.attrs)
- testcase.append(self.make_properties_node())
- for node in self.nodes:
- testcase.append(node)
- return testcase
-
- def _add_simple(self, kind, message, data=None):
- data = bin_xml_escape(data)
- node = kind(data, message=message)
- self.append(node)
-
- def _write_captured_output(self, report):
- for capname in ('out', 'err'):
- allcontent = ""
- for name, content in report.get_sections("Captured std%s" %
- capname):
- allcontent += content
- if allcontent:
- tag = getattr(Junit, 'system-' + capname)
- self.append(tag(bin_xml_escape(allcontent)))
-
- def append_pass(self, report):
- self.add_stats('passed')
- self._write_captured_output(report)
-
- def append_failure(self, report):
- # msg = str(report.longrepr.reprtraceback.extraline)
- if hasattr(report, "wasxfail"):
- self._add_simple(
- Junit.skipped,
- "xfail-marked test passes unexpectedly")
- else:
- if hasattr(report.longrepr, "reprcrash"):
- message = report.longrepr.reprcrash.message
- elif isinstance(report.longrepr, (unicode, str)):
- message = report.longrepr
- else:
- message = str(report.longrepr)
- message = bin_xml_escape(message)
- fail = Junit.failure(message=message)
- fail.append(bin_xml_escape(report.longrepr))
- self.append(fail)
- self._write_captured_output(report)
-
- def append_collect_error(self, report):
- # msg = str(report.longrepr.reprtraceback.extraline)
- self.append(Junit.error(bin_xml_escape(report.longrepr),
- message="collection failure"))
-
- def append_collect_skipped(self, report):
- self._add_simple(
- Junit.skipped, "collection skipped", report.longrepr)
-
- def append_error(self, report):
- self._add_simple(
- Junit.error, "test setup failure", report.longrepr)
- self._write_captured_output(report)
-
- def append_skipped(self, report):
- if hasattr(report, "wasxfail"):
- self._add_simple(
- Junit.skipped, "expected test failure", report.wasxfail
- )
- else:
- filename, lineno, skipreason = report.longrepr
- if skipreason.startswith("Skipped: "):
- skipreason = bin_xml_escape(skipreason[9:])
- self.append(
- Junit.skipped("%s:%s: %s" % (filename, lineno, skipreason),
- type="pytest.skip",
- message=skipreason))
- self._write_captured_output(report)
-
- def finalize(self):
- data = self.to_xml().unicode(indent=0)
- self.__dict__.clear()
- self.to_xml = lambda: py.xml.raw(data)
-
-
-@pytest.fixture
-def record_xml_property(request):
- """Fixture that adds extra xml properties to the tag for the calling test.
- The fixture is callable with (name, value), with value being automatically
- xml-encoded.
- """
- request.node.warn(
- code='C3',
- message='record_xml_property is an experimental feature',
- )
- xml = getattr(request.config, "_xml", None)
- if xml is not None:
- node_reporter = xml.node_reporter(request.node.nodeid)
- return node_reporter.add_property
- else:
- def add_property_noop(name, value):
- pass
-
- return add_property_noop
-
-
-def pytest_addoption(parser):
- group = parser.getgroup("terminal reporting")
- group.addoption(
- '--junitxml', '--junit-xml',
- action="store",
- dest="xmlpath",
- metavar="path",
- default=None,
- help="create junit-xml style report file at given path.")
- group.addoption(
- '--junitprefix', '--junit-prefix',
- action="store",
- metavar="str",
- default=None,
- help="prepend prefix to classnames in junit-xml output")
-
-
-def pytest_configure(config):
- xmlpath = config.option.xmlpath
- # prevent opening xmllog on slave nodes (xdist)
- if xmlpath and not hasattr(config, 'slaveinput'):
- config._xml = LogXML(xmlpath, config.option.junitprefix)
- config.pluginmanager.register(config._xml)
-
-
-def pytest_unconfigure(config):
- xml = getattr(config, '_xml', None)
- if xml:
- del config._xml
- config.pluginmanager.unregister(xml)
-
-
-def mangle_test_address(address):
- path, possible_open_bracket, params = address.partition('[')
- names = path.split("::")
- try:
- names.remove('()')
- except ValueError:
- pass
- # convert file path to dotted path
- names[0] = names[0].replace("/", '.')
- names[0] = _py_ext_re.sub("", names[0])
- # put any params back
- names[-1] += possible_open_bracket + params
- return names
-
-
-class LogXML(object):
- def __init__(self, logfile, prefix):
- logfile = os.path.expanduser(os.path.expandvars(logfile))
- self.logfile = os.path.normpath(os.path.abspath(logfile))
- self.prefix = prefix
- self.stats = dict.fromkeys([
- 'error',
- 'passed',
- 'failure',
- 'skipped',
- ], 0)
- self.node_reporters = {} # nodeid -> _NodeReporter
- self.node_reporters_ordered = []
-
- def finalize(self, report):
- nodeid = getattr(report, 'nodeid', report)
- # local hack to handle xdist report order
- slavenode = getattr(report, 'node', None)
- reporter = self.node_reporters.pop((nodeid, slavenode))
- if reporter is not None:
- reporter.finalize()
-
- def node_reporter(self, report):
- nodeid = getattr(report, 'nodeid', report)
- # local hack to handle xdist report order
- slavenode = getattr(report, 'node', None)
-
- key = nodeid, slavenode
-
- if key in self.node_reporters:
- # TODO: breasks for --dist=each
- return self.node_reporters[key]
- reporter = _NodeReporter(nodeid, self)
- self.node_reporters[key] = reporter
- self.node_reporters_ordered.append(reporter)
- return reporter
-
- def add_stats(self, key):
- if key in self.stats:
- self.stats[key] += 1
-
- def _opentestcase(self, report):
- reporter = self.node_reporter(report)
- reporter.record_testreport(report)
- return reporter
-
- def pytest_runtest_logreport(self, report):
- """handle a setup/call/teardown report, generating the appropriate
- xml tags as necessary.
-
- note: due to plugins like xdist, this hook may be called in interlaced
- order with reports from other nodes. for example:
-
- usual call order:
- -> setup node1
- -> call node1
- -> teardown node1
- -> setup node2
- -> call node2
- -> teardown node2
-
- possible call order in xdist:
- -> setup node1
- -> call node1
- -> setup node2
- -> call node2
- -> teardown node2
- -> teardown node1
- """
- if report.passed:
- if report.when == "call": # ignore setup/teardown
- reporter = self._opentestcase(report)
- reporter.append_pass(report)
- elif report.failed:
- reporter = self._opentestcase(report)
- if report.when == "call":
- reporter.append_failure(report)
- else:
- reporter.append_error(report)
- elif report.skipped:
- reporter = self._opentestcase(report)
- reporter.append_skipped(report)
- self.update_testcase_duration(report)
- if report.when == "teardown":
- self.finalize(report)
-
- def update_testcase_duration(self, report):
- """accumulates total duration for nodeid from given report and updates
- the Junit.testcase with the new total if already created.
- """
- reporter = self.node_reporter(report)
- reporter.duration += getattr(report, 'duration', 0.0)
-
- def pytest_collectreport(self, report):
- if not report.passed:
- reporter = self._opentestcase(report)
- if report.failed:
- reporter.append_collect_error(report)
- else:
- reporter.append_collect_skipped(report)
-
- def pytest_internalerror(self, excrepr):
- reporter = self.node_reporter('internal')
- reporter.attrs.update(classname="pytest", name='internal')
- reporter._add_simple(Junit.error, 'internal error', excrepr)
-
- def pytest_sessionstart(self):
- self.suite_start_time = time.time()
-
- def pytest_sessionfinish(self):
- dirname = os.path.dirname(os.path.abspath(self.logfile))
- if not os.path.isdir(dirname):
- os.makedirs(dirname)
- logfile = open(self.logfile, 'w', encoding='utf-8')
- suite_stop_time = time.time()
- suite_time_delta = suite_stop_time - self.suite_start_time
-
- numtests = self.stats['passed'] + self.stats['failure']
-
- logfile.write('<?xml version="1.0" encoding="utf-8"?>')
- logfile.write(Junit.testsuite(
- [x.to_xml() for x in self.node_reporters_ordered],
- name="pytest",
- errors=self.stats['error'],
- failures=self.stats['failure'],
- skips=self.stats['skipped'],
- tests=numtests,
- time="%.3f" % suite_time_delta, ).unicode(indent=0))
- logfile.close()
-
- def pytest_terminal_summary(self, terminalreporter):
- terminalreporter.write_sep("-",
- "generated xml file: %s" % (self.logfile))
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/main.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/main.py
deleted file mode 100644
index 8654d7af627..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/main.py
+++ /dev/null
@@ -1,744 +0,0 @@
-""" core implementation of testing process: init, session, runtest loop. """
-import imp
-import os
-import re
-import sys
-
-import _pytest
-import _pytest._code
-import py
-import pytest
-try:
- from collections import MutableMapping as MappingMixin
-except ImportError:
- from UserDict import DictMixin as MappingMixin
-
-from _pytest.runner import collect_one_node
-
-tracebackcutdir = py.path.local(_pytest.__file__).dirpath()
-
-# exitcodes for the command line
-EXIT_OK = 0
-EXIT_TESTSFAILED = 1
-EXIT_INTERRUPTED = 2
-EXIT_INTERNALERROR = 3
-EXIT_USAGEERROR = 4
-EXIT_NOTESTSCOLLECTED = 5
-
-name_re = re.compile("^[a-zA-Z_]\w*$")
-
-def pytest_addoption(parser):
- parser.addini("norecursedirs", "directory patterns to avoid for recursion",
- type="args", default=['.*', 'CVS', '_darcs', '{arch}', '*.egg'])
- parser.addini("testpaths", "directories to search for tests when no files or directories are given in the command line.",
- type="args", default=[])
- #parser.addini("dirpatterns",
- # "patterns specifying possible locations of test files",
- # type="linelist", default=["**/test_*.txt",
- # "**/test_*.py", "**/*_test.py"]
- #)
- group = parser.getgroup("general", "running and selection options")
- group._addoption('-x', '--exitfirst', action="store_true", default=False,
- dest="exitfirst",
- help="exit instantly on first error or failed test."),
- group._addoption('--maxfail', metavar="num",
- action="store", type=int, dest="maxfail", default=0,
- help="exit after first num failures or errors.")
- group._addoption('--strict', action="store_true",
- help="run pytest in strict mode, warnings become errors.")
- group._addoption("-c", metavar="file", type=str, dest="inifilename",
- help="load configuration from `file` instead of trying to locate one of the implicit configuration files.")
-
- group = parser.getgroup("collect", "collection")
- group.addoption('--collectonly', '--collect-only', action="store_true",
- help="only collect tests, don't execute them."),
- group.addoption('--pyargs', action="store_true",
- help="try to interpret all arguments as python packages.")
- group.addoption("--ignore", action="append", metavar="path",
- help="ignore path during collection (multi-allowed).")
- # when changing this to --conf-cut-dir, config.py Conftest.setinitial
- # needs upgrading as well
- group.addoption('--confcutdir', dest="confcutdir", default=None,
- metavar="dir",
- help="only load conftest.py's relative to specified dir.")
- group.addoption('--noconftest', action="store_true",
- dest="noconftest", default=False,
- help="Don't load any conftest.py files.")
-
- group = parser.getgroup("debugconfig",
- "test session debugging and configuration")
- group.addoption('--basetemp', dest="basetemp", default=None, metavar="dir",
- help="base temporary directory for this test run.")
-
-
-def pytest_namespace():
- collect = dict(Item=Item, Collector=Collector, File=File, Session=Session)
- return dict(collect=collect)
-
-def pytest_configure(config):
- pytest.config = config # compatibiltiy
- if config.option.exitfirst:
- config.option.maxfail = 1
-
-def wrap_session(config, doit):
- """Skeleton command line program"""
- session = Session(config)
- session.exitstatus = EXIT_OK
- initstate = 0
- try:
- try:
- config._do_configure()
- initstate = 1
- config.hook.pytest_sessionstart(session=session)
- initstate = 2
- session.exitstatus = doit(config, session) or 0
- except pytest.UsageError:
- raise
- except KeyboardInterrupt:
- excinfo = _pytest._code.ExceptionInfo()
- config.hook.pytest_keyboard_interrupt(excinfo=excinfo)
- session.exitstatus = EXIT_INTERRUPTED
- except:
- excinfo = _pytest._code.ExceptionInfo()
- config.notify_exception(excinfo, config.option)
- session.exitstatus = EXIT_INTERNALERROR
- if excinfo.errisinstance(SystemExit):
- sys.stderr.write("mainloop: caught Spurious SystemExit!\n")
-
- finally:
- excinfo = None # Explicitly break reference cycle.
- session.startdir.chdir()
- if initstate >= 2:
- config.hook.pytest_sessionfinish(
- session=session,
- exitstatus=session.exitstatus)
- config._ensure_unconfigure()
- return session.exitstatus
-
-def pytest_cmdline_main(config):
- return wrap_session(config, _main)
-
-def _main(config, session):
- """ default command line protocol for initialization, session,
- running tests and reporting. """
- config.hook.pytest_collection(session=session)
- config.hook.pytest_runtestloop(session=session)
-
- if session.testsfailed:
- return EXIT_TESTSFAILED
- elif session.testscollected == 0:
- return EXIT_NOTESTSCOLLECTED
-
-def pytest_collection(session):
- return session.perform_collect()
-
-def pytest_runtestloop(session):
- if session.config.option.collectonly:
- return True
-
- def getnextitem(i):
- # this is a function to avoid python2
- # keeping sys.exc_info set when calling into a test
- # python2 keeps sys.exc_info till the frame is left
- try:
- return session.items[i+1]
- except IndexError:
- return None
-
- for i, item in enumerate(session.items):
- nextitem = getnextitem(i)
- item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem)
- if session.shouldstop:
- raise session.Interrupted(session.shouldstop)
- return True
-
-def pytest_ignore_collect(path, config):
- p = path.dirpath()
- ignore_paths = config._getconftest_pathlist("collect_ignore", path=p)
- ignore_paths = ignore_paths or []
- excludeopt = config.getoption("ignore")
- if excludeopt:
- ignore_paths.extend([py.path.local(x) for x in excludeopt])
- return path in ignore_paths
-
-class FSHookProxy:
- def __init__(self, fspath, pm, remove_mods):
- self.fspath = fspath
- self.pm = pm
- self.remove_mods = remove_mods
-
- def __getattr__(self, name):
- x = self.pm.subset_hook_caller(name, remove_plugins=self.remove_mods)
- self.__dict__[name] = x
- return x
-
-def compatproperty(name):
- def fget(self):
- # deprecated - use pytest.name
- return getattr(pytest, name)
-
- return property(fget)
-
-class NodeKeywords(MappingMixin):
- def __init__(self, node):
- self.node = node
- self.parent = node.parent
- self._markers = {node.name: True}
-
- def __getitem__(self, key):
- try:
- return self._markers[key]
- except KeyError:
- if self.parent is None:
- raise
- return self.parent.keywords[key]
-
- def __setitem__(self, key, value):
- self._markers[key] = value
-
- def __delitem__(self, key):
- raise ValueError("cannot delete key in keywords dict")
-
- def __iter__(self):
- seen = set(self._markers)
- if self.parent is not None:
- seen.update(self.parent.keywords)
- return iter(seen)
-
- def __len__(self):
- return len(self.__iter__())
-
- def keys(self):
- return list(self)
-
- def __repr__(self):
- return "<NodeKeywords for node %s>" % (self.node, )
-
-
-class Node(object):
- """ base class for Collector and Item the test collection tree.
- Collector subclasses have children, Items are terminal nodes."""
-
- def __init__(self, name, parent=None, config=None, session=None):
- #: a unique name within the scope of the parent node
- self.name = name
-
- #: the parent collector node.
- self.parent = parent
-
- #: the pytest config object
- self.config = config or parent.config
-
- #: the session this node is part of
- self.session = session or parent.session
-
- #: filesystem path where this node was collected from (can be None)
- self.fspath = getattr(parent, 'fspath', None)
-
- #: keywords/markers collected from all scopes
- self.keywords = NodeKeywords(self)
-
- #: allow adding of extra keywords to use for matching
- self.extra_keyword_matches = set()
-
- # used for storing artificial fixturedefs for direct parametrization
- self._name2pseudofixturedef = {}
-
- @property
- def ihook(self):
- """ fspath sensitive hook proxy used to call pytest hooks"""
- return self.session.gethookproxy(self.fspath)
-
- Module = compatproperty("Module")
- Class = compatproperty("Class")
- Instance = compatproperty("Instance")
- Function = compatproperty("Function")
- File = compatproperty("File")
- Item = compatproperty("Item")
-
- def _getcustomclass(self, name):
- cls = getattr(self, name)
- if cls != getattr(pytest, name):
- py.log._apiwarn("2.0", "use of node.%s is deprecated, "
- "use pytest_pycollect_makeitem(...) to create custom "
- "collection nodes" % name)
- return cls
-
- def __repr__(self):
- return "<%s %r>" %(self.__class__.__name__,
- getattr(self, 'name', None))
-
- def warn(self, code, message):
- """ generate a warning with the given code and message for this
- item. """
- assert isinstance(code, str)
- fslocation = getattr(self, "location", None)
- if fslocation is None:
- fslocation = getattr(self, "fspath", None)
- else:
- fslocation = "%s:%s" % fslocation[:2]
-
- self.ihook.pytest_logwarning.call_historic(kwargs=dict(
- code=code, message=message,
- nodeid=self.nodeid, fslocation=fslocation))
-
- # methods for ordering nodes
- @property
- def nodeid(self):
- """ a ::-separated string denoting its collection tree address. """
- try:
- return self._nodeid
- except AttributeError:
- self._nodeid = x = self._makeid()
- return x
-
- def _makeid(self):
- return self.parent.nodeid + "::" + self.name
-
- def __hash__(self):
- return hash(self.nodeid)
-
- def setup(self):
- pass
-
- def teardown(self):
- pass
-
- def _memoizedcall(self, attrname, function):
- exattrname = "_ex_" + attrname
- failure = getattr(self, exattrname, None)
- if failure is not None:
- py.builtin._reraise(failure[0], failure[1], failure[2])
- if hasattr(self, attrname):
- return getattr(self, attrname)
- try:
- res = function()
- except py.builtin._sysex:
- raise
- except:
- failure = sys.exc_info()
- setattr(self, exattrname, failure)
- raise
- setattr(self, attrname, res)
- return res
-
- def listchain(self):
- """ return list of all parent collectors up to self,
- starting from root of collection tree. """
- chain = []
- item = self
- while item is not None:
- chain.append(item)
- item = item.parent
- chain.reverse()
- return chain
-
- def add_marker(self, marker):
- """ dynamically add a marker object to the node.
-
- ``marker`` can be a string or pytest.mark.* instance.
- """
- from _pytest.mark import MarkDecorator
- if isinstance(marker, py.builtin._basestring):
- marker = MarkDecorator(marker)
- elif not isinstance(marker, MarkDecorator):
- raise ValueError("is not a string or pytest.mark.* Marker")
- self.keywords[marker.name] = marker
-
- def get_marker(self, name):
- """ get a marker object from this node or None if
- the node doesn't have a marker with that name. """
- val = self.keywords.get(name, None)
- if val is not None:
- from _pytest.mark import MarkInfo, MarkDecorator
- if isinstance(val, (MarkDecorator, MarkInfo)):
- return val
-
- def listextrakeywords(self):
- """ Return a set of all extra keywords in self and any parents."""
- extra_keywords = set()
- item = self
- for item in self.listchain():
- extra_keywords.update(item.extra_keyword_matches)
- return extra_keywords
-
- def listnames(self):
- return [x.name for x in self.listchain()]
-
- def addfinalizer(self, fin):
- """ register a function to be called when this node is finalized.
-
- This method can only be called when this node is active
- in a setup chain, for example during self.setup().
- """
- self.session._setupstate.addfinalizer(fin, self)
-
- def getparent(self, cls):
- """ get the next parent node (including ourself)
- which is an instance of the given class"""
- current = self
- while current and not isinstance(current, cls):
- current = current.parent
- return current
-
- def _prunetraceback(self, excinfo):
- pass
-
- def _repr_failure_py(self, excinfo, style=None):
- fm = self.session._fixturemanager
- if excinfo.errisinstance(fm.FixtureLookupError):
- return excinfo.value.formatrepr()
- tbfilter = True
- if self.config.option.fulltrace:
- style="long"
- else:
- self._prunetraceback(excinfo)
- tbfilter = False # prunetraceback already does it
- if style == "auto":
- style = "long"
- # XXX should excinfo.getrepr record all data and toterminal() process it?
- if style is None:
- if self.config.option.tbstyle == "short":
- style = "short"
- else:
- style = "long"
-
- return excinfo.getrepr(funcargs=True,
- showlocals=self.config.option.showlocals,
- style=style, tbfilter=tbfilter)
-
- repr_failure = _repr_failure_py
-
-class Collector(Node):
- """ Collector instances create children through collect()
- and thus iteratively build a tree.
- """
-
- class CollectError(Exception):
- """ an error during collection, contains a custom message. """
-
- def collect(self):
- """ returns a list of children (items and collectors)
- for this collection node.
- """
- raise NotImplementedError("abstract")
-
- def repr_failure(self, excinfo):
- """ represent a collection failure. """
- if excinfo.errisinstance(self.CollectError):
- exc = excinfo.value
- return str(exc.args[0])
- return self._repr_failure_py(excinfo, style="short")
-
- def _memocollect(self):
- """ internal helper method to cache results of calling collect(). """
- return self._memoizedcall('_collected', lambda: list(self.collect()))
-
- def _prunetraceback(self, excinfo):
- if hasattr(self, 'fspath'):
- traceback = excinfo.traceback
- ntraceback = traceback.cut(path=self.fspath)
- if ntraceback == traceback:
- ntraceback = ntraceback.cut(excludepath=tracebackcutdir)
- excinfo.traceback = ntraceback.filter()
-
-class FSCollector(Collector):
- def __init__(self, fspath, parent=None, config=None, session=None):
- fspath = py.path.local(fspath) # xxx only for test_resultlog.py?
- name = fspath.basename
- if parent is not None:
- rel = fspath.relto(parent.fspath)
- if rel:
- name = rel
- name = name.replace(os.sep, "/")
- super(FSCollector, self).__init__(name, parent, config, session)
- self.fspath = fspath
-
- def _makeid(self):
- relpath = self.fspath.relto(self.config.rootdir)
- if os.sep != "/":
- relpath = relpath.replace(os.sep, "/")
- return relpath
-
-class File(FSCollector):
- """ base class for collecting tests from a file. """
-
-class Item(Node):
- """ a basic test invocation item. Note that for a single function
- there might be multiple test invocation items.
- """
- nextitem = None
-
- def __init__(self, name, parent=None, config=None, session=None):
- super(Item, self).__init__(name, parent, config, session)
- self._report_sections = []
-
- def add_report_section(self, when, key, content):
- if content:
- self._report_sections.append((when, key, content))
-
- def reportinfo(self):
- return self.fspath, None, ""
-
- @property
- def location(self):
- try:
- return self._location
- except AttributeError:
- location = self.reportinfo()
- # bestrelpath is a quite slow function
- cache = self.config.__dict__.setdefault("_bestrelpathcache", {})
- try:
- fspath = cache[location[0]]
- except KeyError:
- fspath = self.session.fspath.bestrelpath(location[0])
- cache[location[0]] = fspath
- location = (fspath, location[1], str(location[2]))
- self._location = location
- return location
-
-class NoMatch(Exception):
- """ raised if matching cannot locate a matching names. """
-
-class Interrupted(KeyboardInterrupt):
- """ signals an interrupted test run. """
- __module__ = 'builtins' # for py3
-
-class Session(FSCollector):
- Interrupted = Interrupted
-
- def __init__(self, config):
- FSCollector.__init__(self, config.rootdir, parent=None,
- config=config, session=self)
- self._fs2hookproxy = {}
- self.testsfailed = 0
- self.testscollected = 0
- self.shouldstop = False
- self.trace = config.trace.root.get("collection")
- self._norecursepatterns = config.getini("norecursedirs")
- self.startdir = py.path.local()
- self.config.pluginmanager.register(self, name="session")
-
- def _makeid(self):
- return ""
-
- @pytest.hookimpl(tryfirst=True)
- def pytest_collectstart(self):
- if self.shouldstop:
- raise self.Interrupted(self.shouldstop)
-
- @pytest.hookimpl(tryfirst=True)
- def pytest_runtest_logreport(self, report):
- if report.failed and not hasattr(report, 'wasxfail'):
- self.testsfailed += 1
- maxfail = self.config.getvalue("maxfail")
- if maxfail and self.testsfailed >= maxfail:
- self.shouldstop = "stopping after %d failures" % (
- self.testsfailed)
- pytest_collectreport = pytest_runtest_logreport
-
- def isinitpath(self, path):
- return path in self._initialpaths
-
- def gethookproxy(self, fspath):
- try:
- return self._fs2hookproxy[fspath]
- except KeyError:
- # check if we have the common case of running
- # hooks with all conftest.py filesall conftest.py
- pm = self.config.pluginmanager
- my_conftestmodules = pm._getconftestmodules(fspath)
- remove_mods = pm._conftest_plugins.difference(my_conftestmodules)
- if remove_mods:
- # one or more conftests are not in use at this fspath
- proxy = FSHookProxy(fspath, pm, remove_mods)
- else:
- # all plugis are active for this fspath
- proxy = self.config.hook
-
- self._fs2hookproxy[fspath] = proxy
- return proxy
-
- def perform_collect(self, args=None, genitems=True):
- hook = self.config.hook
- try:
- items = self._perform_collect(args, genitems)
- hook.pytest_collection_modifyitems(session=self,
- config=self.config, items=items)
- finally:
- hook.pytest_collection_finish(session=self)
- self.testscollected = len(items)
- return items
-
- def _perform_collect(self, args, genitems):
- if args is None:
- args = self.config.args
- self.trace("perform_collect", self, args)
- self.trace.root.indent += 1
- self._notfound = []
- self._initialpaths = set()
- self._initialparts = []
- self.items = items = []
- for arg in args:
- parts = self._parsearg(arg)
- self._initialparts.append(parts)
- self._initialpaths.add(parts[0])
- rep = collect_one_node(self)
- self.ihook.pytest_collectreport(report=rep)
- self.trace.root.indent -= 1
- if self._notfound:
- errors = []
- for arg, exc in self._notfound:
- line = "(no name %r in any of %r)" % (arg, exc.args[0])
- errors.append("not found: %s\n%s" % (arg, line))
- #XXX: test this
- raise pytest.UsageError(*errors)
- if not genitems:
- return rep.result
- else:
- if rep.passed:
- for node in rep.result:
- self.items.extend(self.genitems(node))
- return items
-
- def collect(self):
- for parts in self._initialparts:
- arg = "::".join(map(str, parts))
- self.trace("processing argument", arg)
- self.trace.root.indent += 1
- try:
- for x in self._collect(arg):
- yield x
- except NoMatch:
- # we are inside a make_report hook so
- # we cannot directly pass through the exception
- self._notfound.append((arg, sys.exc_info()[1]))
-
- self.trace.root.indent -= 1
-
- def _collect(self, arg):
- names = self._parsearg(arg)
- path = names.pop(0)
- if path.check(dir=1):
- assert not names, "invalid arg %r" %(arg,)
- for path in path.visit(fil=lambda x: x.check(file=1),
- rec=self._recurse, bf=True, sort=True):
- for x in self._collectfile(path):
- yield x
- else:
- assert path.check(file=1)
- for x in self.matchnodes(self._collectfile(path), names):
- yield x
-
- def _collectfile(self, path):
- ihook = self.gethookproxy(path)
- if not self.isinitpath(path):
- if ihook.pytest_ignore_collect(path=path, config=self.config):
- return ()
- return ihook.pytest_collect_file(path=path, parent=self)
-
- def _recurse(self, path):
- ihook = self.gethookproxy(path.dirpath())
- if ihook.pytest_ignore_collect(path=path, config=self.config):
- return
- for pat in self._norecursepatterns:
- if path.check(fnmatch=pat):
- return False
- ihook = self.gethookproxy(path)
- ihook.pytest_collect_directory(path=path, parent=self)
- return True
-
- def _tryconvertpyarg(self, x):
- mod = None
- path = [os.path.abspath('.')] + sys.path
- for name in x.split('.'):
- # ignore anything that's not a proper name here
- # else something like --pyargs will mess up '.'
- # since imp.find_module will actually sometimes work for it
- # but it's supposed to be considered a filesystem path
- # not a package
- if name_re.match(name) is None:
- return x
- try:
- fd, mod, type_ = imp.find_module(name, path)
- except ImportError:
- return x
- else:
- if fd is not None:
- fd.close()
-
- if type_[2] != imp.PKG_DIRECTORY:
- path = [os.path.dirname(mod)]
- else:
- path = [mod]
- return mod
-
- def _parsearg(self, arg):
- """ return (fspath, names) tuple after checking the file exists. """
- arg = str(arg)
- if self.config.option.pyargs:
- arg = self._tryconvertpyarg(arg)
- parts = str(arg).split("::")
- relpath = parts[0].replace("/", os.sep)
- path = self.config.invocation_dir.join(relpath, abs=True)
- if not path.check():
- if self.config.option.pyargs:
- msg = "file or package not found: "
- else:
- msg = "file not found: "
- raise pytest.UsageError(msg + arg)
- parts[0] = path
- return parts
-
- def matchnodes(self, matching, names):
- self.trace("matchnodes", matching, names)
- self.trace.root.indent += 1
- nodes = self._matchnodes(matching, names)
- num = len(nodes)
- self.trace("matchnodes finished -> ", num, "nodes")
- self.trace.root.indent -= 1
- if num == 0:
- raise NoMatch(matching, names[:1])
- return nodes
-
- def _matchnodes(self, matching, names):
- if not matching or not names:
- return matching
- name = names[0]
- assert name
- nextnames = names[1:]
- resultnodes = []
- for node in matching:
- if isinstance(node, pytest.Item):
- if not names:
- resultnodes.append(node)
- continue
- assert isinstance(node, pytest.Collector)
- rep = collect_one_node(node)
- if rep.passed:
- has_matched = False
- for x in rep.result:
- # TODO: remove parametrized workaround once collection structure contains parametrization
- if x.name == name or x.name.split("[")[0] == name:
- resultnodes.extend(self.matchnodes([x], nextnames))
- has_matched = True
- # XXX accept IDs that don't have "()" for class instances
- if not has_matched and len(rep.result) == 1 and x.name == "()":
- nextnames.insert(0, name)
- resultnodes.extend(self.matchnodes([x], nextnames))
- node.ihook.pytest_collectreport(report=rep)
- return resultnodes
-
- def genitems(self, node):
- self.trace("genitems", node)
- if isinstance(node, pytest.Item):
- node.ihook.pytest_itemcollected(item=node)
- yield node
- else:
- assert isinstance(node, pytest.Collector)
- rep = collect_one_node(node)
- if rep.passed:
- for subnode in rep.result:
- for x in self.genitems(subnode):
- yield x
- node.ihook.pytest_collectreport(report=rep)
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/mark.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/mark.py
deleted file mode 100644
index 1a763540240..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/mark.py
+++ /dev/null
@@ -1,311 +0,0 @@
-""" generic mechanism for marking and selecting python functions. """
-import inspect
-
-
-class MarkerError(Exception):
-
- """Error in use of a pytest marker/attribute."""
-
-
-def pytest_namespace():
- return {'mark': MarkGenerator()}
-
-
-def pytest_addoption(parser):
- group = parser.getgroup("general")
- group._addoption(
- '-k',
- action="store", dest="keyword", default='', metavar="EXPRESSION",
- help="only run tests which match the given substring expression. "
- "An expression is a python evaluatable expression "
- "where all names are substring-matched against test names "
- "and their parent classes. Example: -k 'test_method or test "
- "other' matches all test functions and classes whose name "
- "contains 'test_method' or 'test_other'. "
- "Additionally keywords are matched to classes and functions "
- "containing extra names in their 'extra_keyword_matches' set, "
- "as well as functions which have names assigned directly to them."
- )
-
- group._addoption(
- "-m",
- action="store", dest="markexpr", default="", metavar="MARKEXPR",
- help="only run tests matching given mark expression. "
- "example: -m 'mark1 and not mark2'."
- )
-
- group.addoption(
- "--markers", action="store_true",
- help="show markers (builtin, plugin and per-project ones)."
- )
-
- parser.addini("markers", "markers for test functions", 'linelist')
-
-
-def pytest_cmdline_main(config):
- import _pytest.config
- if config.option.markers:
- config._do_configure()
- tw = _pytest.config.create_terminal_writer(config)
- for line in config.getini("markers"):
- name, rest = line.split(":", 1)
- tw.write("@pytest.mark.%s:" % name, bold=True)
- tw.line(rest)
- tw.line()
- config._ensure_unconfigure()
- return 0
-pytest_cmdline_main.tryfirst = True
-
-
-def pytest_collection_modifyitems(items, config):
- keywordexpr = config.option.keyword
- matchexpr = config.option.markexpr
- if not keywordexpr and not matchexpr:
- return
- # pytest used to allow "-" for negating
- # but today we just allow "-" at the beginning, use "not" instead
- # we probably remove "-" alltogether soon
- if keywordexpr.startswith("-"):
- keywordexpr = "not " + keywordexpr[1:]
- selectuntil = False
- if keywordexpr[-1:] == ":":
- selectuntil = True
- keywordexpr = keywordexpr[:-1]
-
- remaining = []
- deselected = []
- for colitem in items:
- if keywordexpr and not matchkeyword(colitem, keywordexpr):
- deselected.append(colitem)
- else:
- if selectuntil:
- keywordexpr = None
- if matchexpr:
- if not matchmark(colitem, matchexpr):
- deselected.append(colitem)
- continue
- remaining.append(colitem)
-
- if deselected:
- config.hook.pytest_deselected(items=deselected)
- items[:] = remaining
-
-
-class MarkMapping:
- """Provides a local mapping for markers where item access
- resolves to True if the marker is present. """
- def __init__(self, keywords):
- mymarks = set()
- for key, value in keywords.items():
- if isinstance(value, MarkInfo) or isinstance(value, MarkDecorator):
- mymarks.add(key)
- self._mymarks = mymarks
-
- def __getitem__(self, name):
- return name in self._mymarks
-
-
-class KeywordMapping:
- """Provides a local mapping for keywords.
- Given a list of names, map any substring of one of these names to True.
- """
- def __init__(self, names):
- self._names = names
-
- def __getitem__(self, subname):
- for name in self._names:
- if subname in name:
- return True
- return False
-
-
-def matchmark(colitem, markexpr):
- """Tries to match on any marker names, attached to the given colitem."""
- return eval(markexpr, {}, MarkMapping(colitem.keywords))
-
-
-def matchkeyword(colitem, keywordexpr):
- """Tries to match given keyword expression to given collector item.
-
- Will match on the name of colitem, including the names of its parents.
- Only matches names of items which are either a :class:`Class` or a
- :class:`Function`.
- Additionally, matches on names in the 'extra_keyword_matches' set of
- any item, as well as names directly assigned to test functions.
- """
- mapped_names = set()
-
- # Add the names of the current item and any parent items
- import pytest
- for item in colitem.listchain():
- if not isinstance(item, pytest.Instance):
- mapped_names.add(item.name)
-
- # Add the names added as extra keywords to current or parent items
- for name in colitem.listextrakeywords():
- mapped_names.add(name)
-
- # Add the names attached to the current function through direct assignment
- if hasattr(colitem, 'function'):
- for name in colitem.function.__dict__:
- mapped_names.add(name)
-
- mapping = KeywordMapping(mapped_names)
- if " " not in keywordexpr:
- # special case to allow for simple "-k pass" and "-k 1.3"
- return mapping[keywordexpr]
- elif keywordexpr.startswith("not ") and " " not in keywordexpr[4:]:
- return not mapping[keywordexpr[4:]]
- return eval(keywordexpr, {}, mapping)
-
-
-def pytest_configure(config):
- import pytest
- if config.option.strict:
- pytest.mark._config = config
-
-
-class MarkGenerator:
- """ Factory for :class:`MarkDecorator` objects - exposed as
- a ``pytest.mark`` singleton instance. Example::
-
- import pytest
- @pytest.mark.slowtest
- def test_function():
- pass
-
- will set a 'slowtest' :class:`MarkInfo` object
- on the ``test_function`` object. """
-
- def __getattr__(self, name):
- if name[0] == "_":
- raise AttributeError("Marker name must NOT start with underscore")
- if hasattr(self, '_config'):
- self._check(name)
- return MarkDecorator(name)
-
- def _check(self, name):
- try:
- if name in self._markers:
- return
- except AttributeError:
- pass
- self._markers = l = set()
- for line in self._config.getini("markers"):
- beginning = line.split(":", 1)
- x = beginning[0].split("(", 1)[0]
- l.add(x)
- if name not in self._markers:
- raise AttributeError("%r not a registered marker" % (name,))
-
-def istestfunc(func):
- return hasattr(func, "__call__") and \
- getattr(func, "__name__", "<lambda>") != "<lambda>"
-
-class MarkDecorator:
- """ A decorator for test functions and test classes. When applied
- it will create :class:`MarkInfo` objects which may be
- :ref:`retrieved by hooks as item keywords <excontrolskip>`.
- MarkDecorator instances are often created like this::
-
- mark1 = pytest.mark.NAME # simple MarkDecorator
- mark2 = pytest.mark.NAME(name1=value) # parametrized MarkDecorator
-
- and can then be applied as decorators to test functions::
-
- @mark2
- def test_function():
- pass
-
- When a MarkDecorator instance is called it does the following:
- 1. If called with a single class as its only positional argument and no
- additional keyword arguments, it attaches itself to the class so it
- gets applied automatically to all test cases found in that class.
- 2. If called with a single function as its only positional argument and
- no additional keyword arguments, it attaches a MarkInfo object to the
- function, containing all the arguments already stored internally in
- the MarkDecorator.
- 3. When called in any other case, it performs a 'fake construction' call,
- i.e. it returns a new MarkDecorator instance with the original
- MarkDecorator's content updated with the arguments passed to this
- call.
-
- Note: The rules above prevent MarkDecorator objects from storing only a
- single function or class reference as their positional argument with no
- additional keyword or positional arguments.
-
- """
- def __init__(self, name, args=None, kwargs=None):
- self.name = name
- self.args = args or ()
- self.kwargs = kwargs or {}
-
- @property
- def markname(self):
- return self.name # for backward-compat (2.4.1 had this attr)
-
- def __repr__(self):
- d = self.__dict__.copy()
- name = d.pop('name')
- return "<MarkDecorator %r %r>" % (name, d)
-
- def __call__(self, *args, **kwargs):
- """ if passed a single callable argument: decorate it with mark info.
- otherwise add *args/**kwargs in-place to mark information. """
- if args and not kwargs:
- func = args[0]
- is_class = inspect.isclass(func)
- if len(args) == 1 and (istestfunc(func) or is_class):
- if is_class:
- if hasattr(func, 'pytestmark'):
- mark_list = func.pytestmark
- if not isinstance(mark_list, list):
- mark_list = [mark_list]
- # always work on a copy to avoid updating pytestmark
- # from a superclass by accident
- mark_list = mark_list + [self]
- func.pytestmark = mark_list
- else:
- func.pytestmark = [self]
- else:
- holder = getattr(func, self.name, None)
- if holder is None:
- holder = MarkInfo(
- self.name, self.args, self.kwargs
- )
- setattr(func, self.name, holder)
- else:
- holder.add(self.args, self.kwargs)
- return func
- kw = self.kwargs.copy()
- kw.update(kwargs)
- args = self.args + args
- return self.__class__(self.name, args=args, kwargs=kw)
-
-
-class MarkInfo:
- """ Marking object created by :class:`MarkDecorator` instances. """
- def __init__(self, name, args, kwargs):
- #: name of attribute
- self.name = name
- #: positional argument list, empty if none specified
- self.args = args
- #: keyword argument dictionary, empty if nothing specified
- self.kwargs = kwargs.copy()
- self._arglist = [(args, kwargs.copy())]
-
- def __repr__(self):
- return "<MarkInfo %r args=%r kwargs=%r>" % (
- self.name, self.args, self.kwargs
- )
-
- def add(self, args, kwargs):
- """ add a MarkInfo with the given args and kwargs. """
- self._arglist.append((args, kwargs))
- self.args += args
- self.kwargs.update(kwargs)
-
- def __iter__(self):
- """ yield MarkInfo objects each relating to a marking-call. """
- for args, kwargs in self._arglist:
- yield MarkInfo(self.name, args, kwargs)
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/monkeypatch.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/monkeypatch.py
deleted file mode 100644
index d4c169d37a9..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/monkeypatch.py
+++ /dev/null
@@ -1,254 +0,0 @@
-""" monkeypatching and mocking functionality. """
-
-import os, sys
-import re
-
-from py.builtin import _basestring
-
-RE_IMPORT_ERROR_NAME = re.compile("^No module named (.*)$")
-
-
-def pytest_funcarg__monkeypatch(request):
- """The returned ``monkeypatch`` funcarg provides these
- helper methods to modify objects, dictionaries or os.environ::
-
- monkeypatch.setattr(obj, name, value, raising=True)
- monkeypatch.delattr(obj, name, raising=True)
- monkeypatch.setitem(mapping, name, value)
- monkeypatch.delitem(obj, name, raising=True)
- monkeypatch.setenv(name, value, prepend=False)
- monkeypatch.delenv(name, value, raising=True)
- monkeypatch.syspath_prepend(path)
- monkeypatch.chdir(path)
-
- All modifications will be undone after the requesting
- test function has finished. The ``raising``
- parameter determines if a KeyError or AttributeError
- will be raised if the set/deletion operation has no target.
- """
- mpatch = monkeypatch()
- request.addfinalizer(mpatch.undo)
- return mpatch
-
-
-def resolve(name):
- # simplified from zope.dottedname
- parts = name.split('.')
-
- used = parts.pop(0)
- found = __import__(used)
- for part in parts:
- used += '.' + part
- try:
- found = getattr(found, part)
- except AttributeError:
- pass
- else:
- continue
- # we use explicit un-nesting of the handling block in order
- # to avoid nested exceptions on python 3
- try:
- __import__(used)
- except ImportError as ex:
- # str is used for py2 vs py3
- expected = str(ex).split()[-1]
- if expected == used:
- raise
- else:
- raise ImportError(
- 'import error in %s: %s' % (used, ex)
- )
- found = annotated_getattr(found, part, used)
- return found
-
-
-def annotated_getattr(obj, name, ann):
- try:
- obj = getattr(obj, name)
- except AttributeError:
- raise AttributeError(
- '%r object at %s has no attribute %r' % (
- type(obj).__name__, ann, name
- )
- )
- return obj
-
-
-def derive_importpath(import_path, raising):
- if not isinstance(import_path, _basestring) or "." not in import_path:
- raise TypeError("must be absolute import path string, not %r" %
- (import_path,))
- module, attr = import_path.rsplit('.', 1)
- target = resolve(module)
- if raising:
- annotated_getattr(target, attr, ann=module)
- return attr, target
-
-
-class Notset:
- def __repr__(self):
- return "<notset>"
-
-
-notset = Notset()
-
-
-class monkeypatch:
- """ Object keeping a record of setattr/item/env/syspath changes. """
-
- def __init__(self):
- self._setattr = []
- self._setitem = []
- self._cwd = None
- self._savesyspath = None
-
- def setattr(self, target, name, value=notset, raising=True):
- """ Set attribute value on target, memorizing the old value.
- By default raise AttributeError if the attribute did not exist.
-
- For convenience you can specify a string as ``target`` which
- will be interpreted as a dotted import path, with the last part
- being the attribute name. Example:
- ``monkeypatch.setattr("os.getcwd", lambda x: "/")``
- would set the ``getcwd`` function of the ``os`` module.
-
- The ``raising`` value determines if the setattr should fail
- if the attribute is not already present (defaults to True
- which means it will raise).
- """
- __tracebackhide__ = True
- import inspect
-
- if value is notset:
- if not isinstance(target, _basestring):
- raise TypeError("use setattr(target, name, value) or "
- "setattr(target, value) with target being a dotted "
- "import string")
- value = name
- name, target = derive_importpath(target, raising)
-
- oldval = getattr(target, name, notset)
- if raising and oldval is notset:
- raise AttributeError("%r has no attribute %r" % (target, name))
-
- # avoid class descriptors like staticmethod/classmethod
- if inspect.isclass(target):
- oldval = target.__dict__.get(name, notset)
- self._setattr.append((target, name, oldval))
- setattr(target, name, value)
-
- def delattr(self, target, name=notset, raising=True):
- """ Delete attribute ``name`` from ``target``, by default raise
- AttributeError it the attribute did not previously exist.
-
- If no ``name`` is specified and ``target`` is a string
- it will be interpreted as a dotted import path with the
- last part being the attribute name.
-
- If ``raising`` is set to False, no exception will be raised if the
- attribute is missing.
- """
- __tracebackhide__ = True
- if name is notset:
- if not isinstance(target, _basestring):
- raise TypeError("use delattr(target, name) or "
- "delattr(target) with target being a dotted "
- "import string")
- name, target = derive_importpath(target, raising)
-
- if not hasattr(target, name):
- if raising:
- raise AttributeError(name)
- else:
- self._setattr.append((target, name, getattr(target, name, notset)))
- delattr(target, name)
-
- def setitem(self, dic, name, value):
- """ Set dictionary entry ``name`` to value. """
- self._setitem.append((dic, name, dic.get(name, notset)))
- dic[name] = value
-
- def delitem(self, dic, name, raising=True):
- """ Delete ``name`` from dict. Raise KeyError if it doesn't exist.
-
- If ``raising`` is set to False, no exception will be raised if the
- key is missing.
- """
- if name not in dic:
- if raising:
- raise KeyError(name)
- else:
- self._setitem.append((dic, name, dic.get(name, notset)))
- del dic[name]
-
- def setenv(self, name, value, prepend=None):
- """ Set environment variable ``name`` to ``value``. If ``prepend``
- is a character, read the current environment variable value
- and prepend the ``value`` adjoined with the ``prepend`` character."""
- value = str(value)
- if prepend and name in os.environ:
- value = value + prepend + os.environ[name]
- self.setitem(os.environ, name, value)
-
- def delenv(self, name, raising=True):
- """ Delete ``name`` from the environment. Raise KeyError it does not
- exist.
-
- If ``raising`` is set to False, no exception will be raised if the
- environment variable is missing.
- """
- self.delitem(os.environ, name, raising=raising)
-
- def syspath_prepend(self, path):
- """ Prepend ``path`` to ``sys.path`` list of import locations. """
- if self._savesyspath is None:
- self._savesyspath = sys.path[:]
- sys.path.insert(0, str(path))
-
- def chdir(self, path):
- """ Change the current working directory to the specified path.
- Path can be a string or a py.path.local object.
- """
- if self._cwd is None:
- self._cwd = os.getcwd()
- if hasattr(path, "chdir"):
- path.chdir()
- else:
- os.chdir(path)
-
- def undo(self):
- """ Undo previous changes. This call consumes the
- undo stack. Calling it a second time has no effect unless
- you do more monkeypatching after the undo call.
-
- There is generally no need to call `undo()`, since it is
- called automatically during tear-down.
-
- Note that the same `monkeypatch` fixture is used across a
- single test function invocation. If `monkeypatch` is used both by
- the test function itself and one of the test fixtures,
- calling `undo()` will undo all of the changes made in
- both functions.
- """
- for obj, name, value in reversed(self._setattr):
- if value is not notset:
- setattr(obj, name, value)
- else:
- delattr(obj, name)
- self._setattr[:] = []
- for dictionary, name, value in reversed(self._setitem):
- if value is notset:
- try:
- del dictionary[name]
- except KeyError:
- pass # was already deleted, so we have the desired state
- else:
- dictionary[name] = value
- self._setitem[:] = []
- if self._savesyspath is not None:
- sys.path[:] = self._savesyspath
- self._savesyspath = None
-
- if self._cwd is not None:
- os.chdir(self._cwd)
- self._cwd = None
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/nose.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/nose.py
deleted file mode 100644
index 03874686860..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/nose.py
+++ /dev/null
@@ -1,71 +0,0 @@
-""" run test suites written for nose. """
-
-import sys
-
-import py
-import pytest
-from _pytest import unittest
-
-
-def get_skip_exceptions():
- skip_classes = set()
- for module_name in ('unittest', 'unittest2', 'nose'):
- mod = sys.modules.get(module_name)
- if hasattr(mod, 'SkipTest'):
- skip_classes.add(mod.SkipTest)
- return tuple(skip_classes)
-
-
-def pytest_runtest_makereport(item, call):
- if call.excinfo and call.excinfo.errisinstance(get_skip_exceptions()):
- # let's substitute the excinfo with a pytest.skip one
- call2 = call.__class__(lambda:
- pytest.skip(str(call.excinfo.value)), call.when)
- call.excinfo = call2.excinfo
-
-
-@pytest.hookimpl(trylast=True)
-def pytest_runtest_setup(item):
- if is_potential_nosetest(item):
- if isinstance(item.parent, pytest.Generator):
- gen = item.parent
- if not hasattr(gen, '_nosegensetup'):
- call_optional(gen.obj, 'setup')
- if isinstance(gen.parent, pytest.Instance):
- call_optional(gen.parent.obj, 'setup')
- gen._nosegensetup = True
- if not call_optional(item.obj, 'setup'):
- # call module level setup if there is no object level one
- call_optional(item.parent.obj, 'setup')
- #XXX this implies we only call teardown when setup worked
- item.session._setupstate.addfinalizer((lambda: teardown_nose(item)), item)
-
-def teardown_nose(item):
- if is_potential_nosetest(item):
- if not call_optional(item.obj, 'teardown'):
- call_optional(item.parent.obj, 'teardown')
- #if hasattr(item.parent, '_nosegensetup'):
- # #call_optional(item._nosegensetup, 'teardown')
- # del item.parent._nosegensetup
-
-
-def pytest_make_collect_report(collector):
- if isinstance(collector, pytest.Generator):
- call_optional(collector.obj, 'setup')
-
-
-def is_potential_nosetest(item):
- # extra check needed since we do not do nose style setup/teardown
- # on direct unittest style classes
- return isinstance(item, pytest.Function) and \
- not isinstance(item, unittest.TestCaseFunction)
-
-
-def call_optional(obj, name):
- method = getattr(obj, name, None)
- isfixture = hasattr(method, "_pytestfixturefunction")
- if method is not None and not isfixture and py.builtin.callable(method):
- # If there's any problems allow the exception to raise rather than
- # silently ignoring them
- method()
- return True
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/pastebin.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/pastebin.py
deleted file mode 100644
index 4ec62d02280..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/pastebin.py
+++ /dev/null
@@ -1,92 +0,0 @@
-""" submit failure or test session information to a pastebin service. """
-import pytest
-import sys
-import tempfile
-
-
-def pytest_addoption(parser):
- group = parser.getgroup("terminal reporting")
- group._addoption('--pastebin', metavar="mode",
- action='store', dest="pastebin", default=None,
- choices=['failed', 'all'],
- help="send failed|all info to bpaste.net pastebin service.")
-
-@pytest.hookimpl(trylast=True)
-def pytest_configure(config):
- import py
- if config.option.pastebin == "all":
- tr = config.pluginmanager.getplugin('terminalreporter')
- # if no terminal reporter plugin is present, nothing we can do here;
- # this can happen when this function executes in a slave node
- # when using pytest-xdist, for example
- if tr is not None:
- # pastebin file will be utf-8 encoded binary file
- config._pastebinfile = tempfile.TemporaryFile('w+b')
- oldwrite = tr._tw.write
- def tee_write(s, **kwargs):
- oldwrite(s, **kwargs)
- if py.builtin._istext(s):
- s = s.encode('utf-8')
- config._pastebinfile.write(s)
- tr._tw.write = tee_write
-
-def pytest_unconfigure(config):
- if hasattr(config, '_pastebinfile'):
- # get terminal contents and delete file
- config._pastebinfile.seek(0)
- sessionlog = config._pastebinfile.read()
- config._pastebinfile.close()
- del config._pastebinfile
- # undo our patching in the terminal reporter
- tr = config.pluginmanager.getplugin('terminalreporter')
- del tr._tw.__dict__['write']
- # write summary
- tr.write_sep("=", "Sending information to Paste Service")
- pastebinurl = create_new_paste(sessionlog)
- tr.write_line("pastebin session-log: %s\n" % pastebinurl)
-
-def create_new_paste(contents):
- """
- Creates a new paste using bpaste.net service.
-
- :contents: paste contents as utf-8 encoded bytes
- :returns: url to the pasted contents
- """
- import re
- if sys.version_info < (3, 0):
- from urllib import urlopen, urlencode
- else:
- from urllib.request import urlopen
- from urllib.parse import urlencode
-
- params = {
- 'code': contents,
- 'lexer': 'python3' if sys.version_info[0] == 3 else 'python',
- 'expiry': '1week',
- }
- url = 'https://bpaste.net'
- response = urlopen(url, data=urlencode(params).encode('ascii')).read()
- m = re.search(r'href="/raw/(\w+)"', response.decode('utf-8'))
- if m:
- return '%s/show/%s' % (url, m.group(1))
- else:
- return 'bad response: ' + response
-
-def pytest_terminal_summary(terminalreporter):
- import _pytest.config
- if terminalreporter.config.option.pastebin != "failed":
- return
- tr = terminalreporter
- if 'failed' in tr.stats:
- terminalreporter.write_sep("=", "Sending information to Paste Service")
- for rep in terminalreporter.stats.get('failed'):
- try:
- msg = rep.longrepr.reprtraceback.reprentries[-1].reprfileloc
- except AttributeError:
- msg = tr._getfailureheadline(rep)
- tw = _pytest.config.create_terminal_writer(terminalreporter.config, stringio=True)
- rep.toterminal(tw)
- s = tw.stringio.getvalue()
- assert len(s)
- pastebinurl = create_new_paste(s)
- tr.write_line("%s --> %s" %(msg, pastebinurl))
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/pdb.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/pdb.py
deleted file mode 100644
index 84c920d172c..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/pdb.py
+++ /dev/null
@@ -1,109 +0,0 @@
-""" interactive debugging with PDB, the Python Debugger. """
-from __future__ import absolute_import
-import pdb
-import sys
-
-import pytest
-
-
-def pytest_addoption(parser):
- group = parser.getgroup("general")
- group._addoption('--pdb',
- action="store_true", dest="usepdb", default=False,
- help="start the interactive Python debugger on errors.")
-
-def pytest_namespace():
- return {'set_trace': pytestPDB().set_trace}
-
-def pytest_configure(config):
- if config.getvalue("usepdb"):
- config.pluginmanager.register(PdbInvoke(), 'pdbinvoke')
-
- old = (pdb.set_trace, pytestPDB._pluginmanager)
- def fin():
- pdb.set_trace, pytestPDB._pluginmanager = old
- pytestPDB._config = None
- pdb.set_trace = pytest.set_trace
- pytestPDB._pluginmanager = config.pluginmanager
- pytestPDB._config = config
- config._cleanup.append(fin)
-
-class pytestPDB:
- """ Pseudo PDB that defers to the real pdb. """
- _pluginmanager = None
- _config = None
-
- def set_trace(self):
- """ invoke PDB set_trace debugging, dropping any IO capturing. """
- import _pytest.config
- frame = sys._getframe().f_back
- if self._pluginmanager is not None:
- capman = self._pluginmanager.getplugin("capturemanager")
- if capman:
- capman.suspendcapture(in_=True)
- tw = _pytest.config.create_terminal_writer(self._config)
- tw.line()
- tw.sep(">", "PDB set_trace (IO-capturing turned off)")
- self._pluginmanager.hook.pytest_enter_pdb(config=self._config)
- pdb.Pdb().set_trace(frame)
-
-
-class PdbInvoke:
- def pytest_exception_interact(self, node, call, report):
- capman = node.config.pluginmanager.getplugin("capturemanager")
- if capman:
- out, err = capman.suspendcapture(in_=True)
- sys.stdout.write(out)
- sys.stdout.write(err)
- _enter_pdb(node, call.excinfo, report)
-
- def pytest_internalerror(self, excrepr, excinfo):
- for line in str(excrepr).split("\n"):
- sys.stderr.write("INTERNALERROR> %s\n" %line)
- sys.stderr.flush()
- tb = _postmortem_traceback(excinfo)
- post_mortem(tb)
-
-
-def _enter_pdb(node, excinfo, rep):
- # XXX we re-use the TerminalReporter's terminalwriter
- # because this seems to avoid some encoding related troubles
- # for not completely clear reasons.
- tw = node.config.pluginmanager.getplugin("terminalreporter")._tw
- tw.line()
- tw.sep(">", "traceback")
- rep.toterminal(tw)
- tw.sep(">", "entering PDB")
- tb = _postmortem_traceback(excinfo)
- post_mortem(tb)
- rep._pdbshown = True
- return rep
-
-
-def _postmortem_traceback(excinfo):
- # A doctest.UnexpectedException is not useful for post_mortem.
- # Use the underlying exception instead:
- from doctest import UnexpectedException
- if isinstance(excinfo.value, UnexpectedException):
- return excinfo.value.exc_info[2]
- else:
- return excinfo._excinfo[2]
-
-
-def _find_last_non_hidden_frame(stack):
- i = max(0, len(stack) - 1)
- while i and stack[i][0].f_locals.get("__tracebackhide__", False):
- i -= 1
- return i
-
-
-def post_mortem(t):
- class Pdb(pdb.Pdb):
- def get_stack(self, f, t):
- stack, i = pdb.Pdb.get_stack(self, f, t)
- if f is None:
- i = _find_last_non_hidden_frame(stack)
- return stack, i
- p = Pdb()
- p.reset()
- p.interaction(None, t)
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/pytester.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/pytester.py
deleted file mode 100644
index faed7f581c9..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/pytester.py
+++ /dev/null
@@ -1,1110 +0,0 @@
-""" (disabled by default) support for testing pytest and pytest plugins. """
-import codecs
-import gc
-import os
-import platform
-import re
-import subprocess
-import sys
-import time
-import traceback
-from fnmatch import fnmatch
-
-from py.builtin import print_
-
-from _pytest._code import Source
-import py
-import pytest
-from _pytest.main import Session, EXIT_OK
-
-
-def pytest_addoption(parser):
- # group = parser.getgroup("pytester", "pytester (self-tests) options")
- parser.addoption('--lsof',
- action="store_true", dest="lsof", default=False,
- help=("run FD checks if lsof is available"))
-
- parser.addoption('--runpytest', default="inprocess", dest="runpytest",
- choices=("inprocess", "subprocess", ),
- help=("run pytest sub runs in tests using an 'inprocess' "
- "or 'subprocess' (python -m main) method"))
-
-
-def pytest_configure(config):
- # This might be called multiple times. Only take the first.
- global _pytest_fullpath
- try:
- _pytest_fullpath
- except NameError:
- _pytest_fullpath = os.path.abspath(pytest.__file__.rstrip("oc"))
- _pytest_fullpath = _pytest_fullpath.replace("$py.class", ".py")
-
- if config.getvalue("lsof"):
- checker = LsofFdLeakChecker()
- if checker.matching_platform():
- config.pluginmanager.register(checker)
-
-
-class LsofFdLeakChecker(object):
- def get_open_files(self):
- out = self._exec_lsof()
- open_files = self._parse_lsof_output(out)
- return open_files
-
- def _exec_lsof(self):
- pid = os.getpid()
- return py.process.cmdexec("lsof -Ffn0 -p %d" % pid)
-
- def _parse_lsof_output(self, out):
- def isopen(line):
- return line.startswith('f') and ("deleted" not in line and
- 'mem' not in line and "txt" not in line and 'cwd' not in line)
-
- open_files = []
-
- for line in out.split("\n"):
- if isopen(line):
- fields = line.split('\0')
- fd = fields[0][1:]
- filename = fields[1][1:]
- if filename.startswith('/'):
- open_files.append((fd, filename))
-
- return open_files
-
- def matching_platform(self):
- try:
- py.process.cmdexec("lsof -v")
- except (py.process.cmdexec.Error, UnicodeDecodeError):
- # cmdexec may raise UnicodeDecodeError on Windows systems
- # with locale other than english:
- # https://bitbucket.org/pytest-dev/py/issues/66
- return False
- else:
- return True
-
- @pytest.hookimpl(hookwrapper=True, tryfirst=True)
- def pytest_runtest_item(self, item):
- lines1 = self.get_open_files()
- yield
- if hasattr(sys, "pypy_version_info"):
- gc.collect()
- lines2 = self.get_open_files()
-
- new_fds = set([t[0] for t in lines2]) - set([t[0] for t in lines1])
- leaked_files = [t for t in lines2 if t[0] in new_fds]
- if leaked_files:
- error = []
- error.append("***** %s FD leakage detected" % len(leaked_files))
- error.extend([str(f) for f in leaked_files])
- error.append("*** Before:")
- error.extend([str(f) for f in lines1])
- error.append("*** After:")
- error.extend([str(f) for f in lines2])
- error.append(error[0])
- error.append("*** function %s:%s: %s " % item.location)
- pytest.fail("\n".join(error), pytrace=False)
-
-
-# XXX copied from execnet's conftest.py - needs to be merged
-winpymap = {
- 'python2.7': r'C:\Python27\python.exe',
- 'python2.6': r'C:\Python26\python.exe',
- 'python3.1': r'C:\Python31\python.exe',
- 'python3.2': r'C:\Python32\python.exe',
- 'python3.3': r'C:\Python33\python.exe',
- 'python3.4': r'C:\Python34\python.exe',
- 'python3.5': r'C:\Python35\python.exe',
-}
-
-def getexecutable(name, cache={}):
- try:
- return cache[name]
- except KeyError:
- executable = py.path.local.sysfind(name)
- if executable:
- if name == "jython":
- import subprocess
- popen = subprocess.Popen([str(executable), "--version"],
- universal_newlines=True, stderr=subprocess.PIPE)
- out, err = popen.communicate()
- if not err or "2.5" not in err:
- executable = None
- if "2.5.2" in err:
- executable = None # http://bugs.jython.org/issue1790
- cache[name] = executable
- return executable
-
-@pytest.fixture(params=['python2.6', 'python2.7', 'python3.3', "python3.4",
- 'pypy', 'pypy3'])
-def anypython(request):
- name = request.param
- executable = getexecutable(name)
- if executable is None:
- if sys.platform == "win32":
- executable = winpymap.get(name, None)
- if executable:
- executable = py.path.local(executable)
- if executable.check():
- return executable
- pytest.skip("no suitable %s found" % (name,))
- return executable
-
-# used at least by pytest-xdist plugin
-@pytest.fixture
-def _pytest(request):
- """ Return a helper which offers a gethookrecorder(hook)
- method which returns a HookRecorder instance which helps
- to make assertions about called hooks.
- """
- return PytestArg(request)
-
-class PytestArg:
- def __init__(self, request):
- self.request = request
-
- def gethookrecorder(self, hook):
- hookrecorder = HookRecorder(hook._pm)
- self.request.addfinalizer(hookrecorder.finish_recording)
- return hookrecorder
-
-
-def get_public_names(l):
- """Only return names from iterator l without a leading underscore."""
- return [x for x in l if x[0] != "_"]
-
-
-class ParsedCall:
- def __init__(self, name, kwargs):
- self.__dict__.update(kwargs)
- self._name = name
-
- def __repr__(self):
- d = self.__dict__.copy()
- del d['_name']
- return "<ParsedCall %r(**%r)>" %(self._name, d)
-
-
-class HookRecorder:
- """Record all hooks called in a plugin manager.
-
- This wraps all the hook calls in the plugin manager, recording
- each call before propagating the normal calls.
-
- """
-
- def __init__(self, pluginmanager):
- self._pluginmanager = pluginmanager
- self.calls = []
-
- def before(hook_name, hook_impls, kwargs):
- self.calls.append(ParsedCall(hook_name, kwargs))
-
- def after(outcome, hook_name, hook_impls, kwargs):
- pass
-
- self._undo_wrapping = pluginmanager.add_hookcall_monitoring(before, after)
-
- def finish_recording(self):
- self._undo_wrapping()
-
- def getcalls(self, names):
- if isinstance(names, str):
- names = names.split()
- return [call for call in self.calls if call._name in names]
-
- def assert_contains(self, entries):
- __tracebackhide__ = True
- i = 0
- entries = list(entries)
- backlocals = sys._getframe(1).f_locals
- while entries:
- name, check = entries.pop(0)
- for ind, call in enumerate(self.calls[i:]):
- if call._name == name:
- print_("NAMEMATCH", name, call)
- if eval(check, backlocals, call.__dict__):
- print_("CHECKERMATCH", repr(check), "->", call)
- else:
- print_("NOCHECKERMATCH", repr(check), "-", call)
- continue
- i += ind + 1
- break
- print_("NONAMEMATCH", name, "with", call)
- else:
- pytest.fail("could not find %r check %r" % (name, check))
-
- def popcall(self, name):
- __tracebackhide__ = True
- for i, call in enumerate(self.calls):
- if call._name == name:
- del self.calls[i]
- return call
- lines = ["could not find call %r, in:" % (name,)]
- lines.extend([" %s" % str(x) for x in self.calls])
- pytest.fail("\n".join(lines))
-
- def getcall(self, name):
- l = self.getcalls(name)
- assert len(l) == 1, (name, l)
- return l[0]
-
- # functionality for test reports
-
- def getreports(self,
- names="pytest_runtest_logreport pytest_collectreport"):
- return [x.report for x in self.getcalls(names)]
-
- def matchreport(self, inamepart="",
- names="pytest_runtest_logreport pytest_collectreport", when=None):
- """ return a testreport whose dotted import path matches """
- l = []
- for rep in self.getreports(names=names):
- try:
- if not when and rep.when != "call" and rep.passed:
- # setup/teardown passing reports - let's ignore those
- continue
- except AttributeError:
- pass
- if when and getattr(rep, 'when', None) != when:
- continue
- if not inamepart or inamepart in rep.nodeid.split("::"):
- l.append(rep)
- if not l:
- raise ValueError("could not find test report matching %r: "
- "no test reports at all!" % (inamepart,))
- if len(l) > 1:
- raise ValueError(
- "found 2 or more testreports matching %r: %s" %(inamepart, l))
- return l[0]
-
- def getfailures(self,
- names='pytest_runtest_logreport pytest_collectreport'):
- return [rep for rep in self.getreports(names) if rep.failed]
-
- def getfailedcollections(self):
- return self.getfailures('pytest_collectreport')
-
- def listoutcomes(self):
- passed = []
- skipped = []
- failed = []
- for rep in self.getreports(
- "pytest_collectreport pytest_runtest_logreport"):
- if rep.passed:
- if getattr(rep, "when", None) == "call":
- passed.append(rep)
- elif rep.skipped:
- skipped.append(rep)
- elif rep.failed:
- failed.append(rep)
- return passed, skipped, failed
-
- def countoutcomes(self):
- return [len(x) for x in self.listoutcomes()]
-
- def assertoutcome(self, passed=0, skipped=0, failed=0):
- realpassed, realskipped, realfailed = self.listoutcomes()
- assert passed == len(realpassed)
- assert skipped == len(realskipped)
- assert failed == len(realfailed)
-
- def clear(self):
- self.calls[:] = []
-
-
-@pytest.fixture
-def linecomp(request):
- return LineComp()
-
-
-def pytest_funcarg__LineMatcher(request):
- return LineMatcher
-
-
-@pytest.fixture
-def testdir(request, tmpdir_factory):
- return Testdir(request, tmpdir_factory)
-
-
-rex_outcome = re.compile("(\d+) ([\w-]+)")
-class RunResult:
- """The result of running a command.
-
- Attributes:
-
- :ret: The return value.
- :outlines: List of lines captured from stdout.
- :errlines: List of lines captures from stderr.
- :stdout: :py:class:`LineMatcher` of stdout, use ``stdout.str()`` to
- reconstruct stdout or the commonly used
- ``stdout.fnmatch_lines()`` method.
- :stderrr: :py:class:`LineMatcher` of stderr.
- :duration: Duration in seconds.
-
- """
- def __init__(self, ret, outlines, errlines, duration):
- self.ret = ret
- self.outlines = outlines
- self.errlines = errlines
- self.stdout = LineMatcher(outlines)
- self.stderr = LineMatcher(errlines)
- self.duration = duration
-
- def parseoutcomes(self):
- """ Return a dictionary of outcomestring->num from parsing
- the terminal output that the test process produced."""
- for line in reversed(self.outlines):
- if 'seconds' in line:
- outcomes = rex_outcome.findall(line)
- if outcomes:
- d = {}
- for num, cat in outcomes:
- d[cat] = int(num)
- return d
-
- def assert_outcomes(self, passed=0, skipped=0, failed=0):
- """ assert that the specified outcomes appear with the respective
- numbers (0 means it didn't occur) in the text output from a test run."""
- d = self.parseoutcomes()
- assert passed == d.get("passed", 0)
- assert skipped == d.get("skipped", 0)
- assert failed == d.get("failed", 0)
-
-
-
-class Testdir:
- """Temporary test directory with tools to test/run py.test itself.
-
- This is based on the ``tmpdir`` fixture but provides a number of
- methods which aid with testing py.test itself. Unless
- :py:meth:`chdir` is used all methods will use :py:attr:`tmpdir` as
- current working directory.
-
- Attributes:
-
- :tmpdir: The :py:class:`py.path.local` instance of the temporary
- directory.
-
- :plugins: A list of plugins to use with :py:meth:`parseconfig` and
- :py:meth:`runpytest`. Initially this is an empty list but
- plugins can be added to the list. The type of items to add to
- the list depend on the method which uses them so refer to them
- for details.
-
- """
-
- def __init__(self, request, tmpdir_factory):
- self.request = request
- # XXX remove duplication with tmpdir plugin
- basetmp = tmpdir_factory.ensuretemp("testdir")
- name = request.function.__name__
- for i in range(100):
- try:
- tmpdir = basetmp.mkdir(name + str(i))
- except py.error.EEXIST:
- continue
- break
- self.tmpdir = tmpdir
- self.plugins = []
- self._savesyspath = (list(sys.path), list(sys.meta_path))
- self._savemodulekeys = set(sys.modules)
- self.chdir() # always chdir
- self.request.addfinalizer(self.finalize)
- method = self.request.config.getoption("--runpytest")
- if method == "inprocess":
- self._runpytest_method = self.runpytest_inprocess
- elif method == "subprocess":
- self._runpytest_method = self.runpytest_subprocess
-
- def __repr__(self):
- return "<Testdir %r>" % (self.tmpdir,)
-
- def finalize(self):
- """Clean up global state artifacts.
-
- Some methods modify the global interpreter state and this
- tries to clean this up. It does not remove the temporary
- directory however so it can be looked at after the test run
- has finished.
-
- """
- sys.path[:], sys.meta_path[:] = self._savesyspath
- if hasattr(self, '_olddir'):
- self._olddir.chdir()
- self.delete_loaded_modules()
-
- def delete_loaded_modules(self):
- """Delete modules that have been loaded during a test.
-
- This allows the interpreter to catch module changes in case
- the module is re-imported.
- """
- for name in set(sys.modules).difference(self._savemodulekeys):
- # it seems zope.interfaces is keeping some state
- # (used by twisted related tests)
- if name != "zope.interface":
- del sys.modules[name]
-
- def make_hook_recorder(self, pluginmanager):
- """Create a new :py:class:`HookRecorder` for a PluginManager."""
- assert not hasattr(pluginmanager, "reprec")
- pluginmanager.reprec = reprec = HookRecorder(pluginmanager)
- self.request.addfinalizer(reprec.finish_recording)
- return reprec
-
- def chdir(self):
- """Cd into the temporary directory.
-
- This is done automatically upon instantiation.
-
- """
- old = self.tmpdir.chdir()
- if not hasattr(self, '_olddir'):
- self._olddir = old
-
- def _makefile(self, ext, args, kwargs):
- items = list(kwargs.items())
- if args:
- source = py.builtin._totext("\n").join(
- map(py.builtin._totext, args)) + py.builtin._totext("\n")
- basename = self.request.function.__name__
- items.insert(0, (basename, source))
- ret = None
- for name, value in items:
- p = self.tmpdir.join(name).new(ext=ext)
- source = Source(value)
- def my_totext(s, encoding="utf-8"):
- if py.builtin._isbytes(s):
- s = py.builtin._totext(s, encoding=encoding)
- return s
- source_unicode = "\n".join([my_totext(line) for line in source.lines])
- source = py.builtin._totext(source_unicode)
- content = source.strip().encode("utf-8") # + "\n"
- #content = content.rstrip() + "\n"
- p.write(content, "wb")
- if ret is None:
- ret = p
- return ret
-
- def makefile(self, ext, *args, **kwargs):
- """Create a new file in the testdir.
-
- ext: The extension the file should use, including the dot.
- E.g. ".py".
-
- args: All args will be treated as strings and joined using
- newlines. The result will be written as contents to the
- file. The name of the file will be based on the test
- function requesting this fixture.
- E.g. "testdir.makefile('.txt', 'line1', 'line2')"
-
- kwargs: Each keyword is the name of a file, while the value of
- it will be written as contents of the file.
- E.g. "testdir.makefile('.ini', pytest='[pytest]\naddopts=-rs\n')"
-
- """
- return self._makefile(ext, args, kwargs)
-
- def makeconftest(self, source):
- """Write a contest.py file with 'source' as contents."""
- return self.makepyfile(conftest=source)
-
- def makeini(self, source):
- """Write a tox.ini file with 'source' as contents."""
- return self.makefile('.ini', tox=source)
-
- def getinicfg(self, source):
- """Return the pytest section from the tox.ini config file."""
- p = self.makeini(source)
- return py.iniconfig.IniConfig(p)['pytest']
-
- def makepyfile(self, *args, **kwargs):
- """Shortcut for .makefile() with a .py extension."""
- return self._makefile('.py', args, kwargs)
-
- def maketxtfile(self, *args, **kwargs):
- """Shortcut for .makefile() with a .txt extension."""
- return self._makefile('.txt', args, kwargs)
-
- def syspathinsert(self, path=None):
- """Prepend a directory to sys.path, defaults to :py:attr:`tmpdir`.
-
- This is undone automatically after the test.
- """
- if path is None:
- path = self.tmpdir
- sys.path.insert(0, str(path))
- # a call to syspathinsert() usually means that the caller
- # wants to import some dynamically created files.
- # with python3 we thus invalidate import caches.
- self._possibly_invalidate_import_caches()
-
- def _possibly_invalidate_import_caches(self):
- # invalidate caches if we can (py33 and above)
- try:
- import importlib
- except ImportError:
- pass
- else:
- if hasattr(importlib, "invalidate_caches"):
- importlib.invalidate_caches()
-
- def mkdir(self, name):
- """Create a new (sub)directory."""
- return self.tmpdir.mkdir(name)
-
- def mkpydir(self, name):
- """Create a new python package.
-
- This creates a (sub)direcotry with an empty ``__init__.py``
- file so that is recognised as a python package.
-
- """
- p = self.mkdir(name)
- p.ensure("__init__.py")
- return p
-
- Session = Session
- def getnode(self, config, arg):
- """Return the collection node of a file.
-
- :param config: :py:class:`_pytest.config.Config` instance, see
- :py:meth:`parseconfig` and :py:meth:`parseconfigure` to
- create the configuration.
-
- :param arg: A :py:class:`py.path.local` instance of the file.
-
- """
- session = Session(config)
- assert '::' not in str(arg)
- p = py.path.local(arg)
- config.hook.pytest_sessionstart(session=session)
- res = session.perform_collect([str(p)], genitems=False)[0]
- config.hook.pytest_sessionfinish(session=session, exitstatus=EXIT_OK)
- return res
-
- def getpathnode(self, path):
- """Return the collection node of a file.
-
- This is like :py:meth:`getnode` but uses
- :py:meth:`parseconfigure` to create the (configured) py.test
- Config instance.
-
- :param path: A :py:class:`py.path.local` instance of the file.
-
- """
- config = self.parseconfigure(path)
- session = Session(config)
- x = session.fspath.bestrelpath(path)
- config.hook.pytest_sessionstart(session=session)
- res = session.perform_collect([x], genitems=False)[0]
- config.hook.pytest_sessionfinish(session=session, exitstatus=EXIT_OK)
- return res
-
- def genitems(self, colitems):
- """Generate all test items from a collection node.
-
- This recurses into the collection node and returns a list of
- all the test items contained within.
-
- """
- session = colitems[0].session
- result = []
- for colitem in colitems:
- result.extend(session.genitems(colitem))
- return result
-
- def runitem(self, source):
- """Run the "test_func" Item.
-
- The calling test instance (the class which contains the test
- method) must provide a ``.getrunner()`` method which should
- return a runner which can run the test protocol for a single
- item, like e.g. :py:func:`_pytest.runner.runtestprotocol`.
-
- """
- # used from runner functional tests
- item = self.getitem(source)
- # the test class where we are called from wants to provide the runner
- testclassinstance = self.request.instance
- runner = testclassinstance.getrunner()
- return runner(item)
-
- def inline_runsource(self, source, *cmdlineargs):
- """Run a test module in process using ``pytest.main()``.
-
- This run writes "source" into a temporary file and runs
- ``pytest.main()`` on it, returning a :py:class:`HookRecorder`
- instance for the result.
-
- :param source: The source code of the test module.
-
- :param cmdlineargs: Any extra command line arguments to use.
-
- :return: :py:class:`HookRecorder` instance of the result.
-
- """
- p = self.makepyfile(source)
- l = list(cmdlineargs) + [p]
- return self.inline_run(*l)
-
- def inline_genitems(self, *args):
- """Run ``pytest.main(['--collectonly'])`` in-process.
-
- Retuns a tuple of the collected items and a
- :py:class:`HookRecorder` instance.
-
- This runs the :py:func:`pytest.main` function to run all of
- py.test inside the test process itself like
- :py:meth:`inline_run`. However the return value is a tuple of
- the collection items and a :py:class:`HookRecorder` instance.
-
- """
- rec = self.inline_run("--collect-only", *args)
- items = [x.item for x in rec.getcalls("pytest_itemcollected")]
- return items, rec
-
- def inline_run(self, *args, **kwargs):
- """Run ``pytest.main()`` in-process, returning a HookRecorder.
-
- This runs the :py:func:`pytest.main` function to run all of
- py.test inside the test process itself. This means it can
- return a :py:class:`HookRecorder` instance which gives more
- detailed results from then run then can be done by matching
- stdout/stderr from :py:meth:`runpytest`.
-
- :param args: Any command line arguments to pass to
- :py:func:`pytest.main`.
-
- :param plugin: (keyword-only) Extra plugin instances the
- ``pytest.main()`` instance should use.
-
- :return: A :py:class:`HookRecorder` instance.
-
- """
- rec = []
- class Collect:
- def pytest_configure(x, config):
- rec.append(self.make_hook_recorder(config.pluginmanager))
-
- plugins = kwargs.get("plugins") or []
- plugins.append(Collect())
- ret = pytest.main(list(args), plugins=plugins)
- self.delete_loaded_modules()
- if len(rec) == 1:
- reprec = rec.pop()
- else:
- class reprec:
- pass
- reprec.ret = ret
-
- # typically we reraise keyboard interrupts from the child run
- # because it's our user requesting interruption of the testing
- if ret == 2 and not kwargs.get("no_reraise_ctrlc"):
- calls = reprec.getcalls("pytest_keyboard_interrupt")
- if calls and calls[-1].excinfo.type == KeyboardInterrupt:
- raise KeyboardInterrupt()
- return reprec
-
- def runpytest_inprocess(self, *args, **kwargs):
- """ Return result of running pytest in-process, providing a similar
- interface to what self.runpytest() provides. """
- if kwargs.get("syspathinsert"):
- self.syspathinsert()
- now = time.time()
- capture = py.io.StdCapture()
- try:
- try:
- reprec = self.inline_run(*args, **kwargs)
- except SystemExit as e:
- class reprec:
- ret = e.args[0]
- except Exception:
- traceback.print_exc()
- class reprec:
- ret = 3
- finally:
- out, err = capture.reset()
- sys.stdout.write(out)
- sys.stderr.write(err)
-
- res = RunResult(reprec.ret,
- out.split("\n"), err.split("\n"),
- time.time()-now)
- res.reprec = reprec
- return res
-
- def runpytest(self, *args, **kwargs):
- """ Run pytest inline or in a subprocess, depending on the command line
- option "--runpytest" and return a :py:class:`RunResult`.
-
- """
- args = self._ensure_basetemp(args)
- return self._runpytest_method(*args, **kwargs)
-
- def _ensure_basetemp(self, args):
- args = [str(x) for x in args]
- for x in args:
- if str(x).startswith('--basetemp'):
- #print ("basedtemp exists: %s" %(args,))
- break
- else:
- args.append("--basetemp=%s" % self.tmpdir.dirpath('basetemp'))
- #print ("added basetemp: %s" %(args,))
- return args
-
- def parseconfig(self, *args):
- """Return a new py.test Config instance from given commandline args.
-
- This invokes the py.test bootstrapping code in _pytest.config
- to create a new :py:class:`_pytest.core.PluginManager` and
- call the pytest_cmdline_parse hook to create new
- :py:class:`_pytest.config.Config` instance.
-
- If :py:attr:`plugins` has been populated they should be plugin
- modules which will be registered with the PluginManager.
-
- """
- args = self._ensure_basetemp(args)
-
- import _pytest.config
- config = _pytest.config._prepareconfig(args, self.plugins)
- # we don't know what the test will do with this half-setup config
- # object and thus we make sure it gets unconfigured properly in any
- # case (otherwise capturing could still be active, for example)
- self.request.addfinalizer(config._ensure_unconfigure)
- return config
-
- def parseconfigure(self, *args):
- """Return a new py.test configured Config instance.
-
- This returns a new :py:class:`_pytest.config.Config` instance
- like :py:meth:`parseconfig`, but also calls the
- pytest_configure hook.
-
- """
- config = self.parseconfig(*args)
- config._do_configure()
- self.request.addfinalizer(config._ensure_unconfigure)
- return config
-
- def getitem(self, source, funcname="test_func"):
- """Return the test item for a test function.
-
- This writes the source to a python file and runs py.test's
- collection on the resulting module, returning the test item
- for the requested function name.
-
- :param source: The module source.
-
- :param funcname: The name of the test function for which the
- Item must be returned.
-
- """
- items = self.getitems(source)
- for item in items:
- if item.name == funcname:
- return item
- assert 0, "%r item not found in module:\n%s\nitems: %s" %(
- funcname, source, items)
-
- def getitems(self, source):
- """Return all test items collected from the module.
-
- This writes the source to a python file and runs py.test's
- collection on the resulting module, returning all test items
- contained within.
-
- """
- modcol = self.getmodulecol(source)
- return self.genitems([modcol])
-
- def getmodulecol(self, source, configargs=(), withinit=False):
- """Return the module collection node for ``source``.
-
- This writes ``source`` to a file using :py:meth:`makepyfile`
- and then runs the py.test collection on it, returning the
- collection node for the test module.
-
- :param source: The source code of the module to collect.
-
- :param configargs: Any extra arguments to pass to
- :py:meth:`parseconfigure`.
-
- :param withinit: Whether to also write a ``__init__.py`` file
- to the temporarly directory to ensure it is a package.
-
- """
- kw = {self.request.function.__name__: Source(source).strip()}
- path = self.makepyfile(**kw)
- if withinit:
- self.makepyfile(__init__ = "#")
- self.config = config = self.parseconfigure(path, *configargs)
- node = self.getnode(config, path)
- return node
-
- def collect_by_name(self, modcol, name):
- """Return the collection node for name from the module collection.
-
- This will search a module collection node for a collection
- node matching the given name.
-
- :param modcol: A module collection node, see
- :py:meth:`getmodulecol`.
-
- :param name: The name of the node to return.
-
- """
- for colitem in modcol._memocollect():
- if colitem.name == name:
- return colitem
-
- def popen(self, cmdargs, stdout, stderr, **kw):
- """Invoke subprocess.Popen.
-
- This calls subprocess.Popen making sure the current working
- directory is the PYTHONPATH.
-
- You probably want to use :py:meth:`run` instead.
-
- """
- env = os.environ.copy()
- env['PYTHONPATH'] = os.pathsep.join(filter(None, [
- str(os.getcwd()), env.get('PYTHONPATH', '')]))
- kw['env'] = env
- return subprocess.Popen(cmdargs,
- stdout=stdout, stderr=stderr, **kw)
-
- def run(self, *cmdargs):
- """Run a command with arguments.
-
- Run a process using subprocess.Popen saving the stdout and
- stderr.
-
- Returns a :py:class:`RunResult`.
-
- """
- return self._run(*cmdargs)
-
- def _run(self, *cmdargs):
- cmdargs = [str(x) for x in cmdargs]
- p1 = self.tmpdir.join("stdout")
- p2 = self.tmpdir.join("stderr")
- print_("running:", ' '.join(cmdargs))
- print_(" in:", str(py.path.local()))
- f1 = codecs.open(str(p1), "w", encoding="utf8")
- f2 = codecs.open(str(p2), "w", encoding="utf8")
- try:
- now = time.time()
- popen = self.popen(cmdargs, stdout=f1, stderr=f2,
- close_fds=(sys.platform != "win32"))
- ret = popen.wait()
- finally:
- f1.close()
- f2.close()
- f1 = codecs.open(str(p1), "r", encoding="utf8")
- f2 = codecs.open(str(p2), "r", encoding="utf8")
- try:
- out = f1.read().splitlines()
- err = f2.read().splitlines()
- finally:
- f1.close()
- f2.close()
- self._dump_lines(out, sys.stdout)
- self._dump_lines(err, sys.stderr)
- return RunResult(ret, out, err, time.time()-now)
-
- def _dump_lines(self, lines, fp):
- try:
- for line in lines:
- py.builtin.print_(line, file=fp)
- except UnicodeEncodeError:
- print("couldn't print to %s because of encoding" % (fp,))
-
- def _getpytestargs(self):
- # we cannot use "(sys.executable,script)"
- # because on windows the script is e.g. a py.test.exe
- return (sys.executable, _pytest_fullpath,) # noqa
-
- def runpython(self, script):
- """Run a python script using sys.executable as interpreter.
-
- Returns a :py:class:`RunResult`.
- """
- return self.run(sys.executable, script)
-
- def runpython_c(self, command):
- """Run python -c "command", return a :py:class:`RunResult`."""
- return self.run(sys.executable, "-c", command)
-
- def runpytest_subprocess(self, *args, **kwargs):
- """Run py.test as a subprocess with given arguments.
-
- Any plugins added to the :py:attr:`plugins` list will added
- using the ``-p`` command line option. Addtionally
- ``--basetemp`` is used put any temporary files and directories
- in a numbered directory prefixed with "runpytest-" so they do
- not conflict with the normal numberd pytest location for
- temporary files and directories.
-
- Returns a :py:class:`RunResult`.
-
- """
- p = py.path.local.make_numbered_dir(prefix="runpytest-",
- keep=None, rootdir=self.tmpdir)
- args = ('--basetemp=%s' % p, ) + args
- #for x in args:
- # if '--confcutdir' in str(x):
- # break
- #else:
- # pass
- # args = ('--confcutdir=.',) + args
- plugins = [x for x in self.plugins if isinstance(x, str)]
- if plugins:
- args = ('-p', plugins[0]) + args
- args = self._getpytestargs() + args
- return self.run(*args)
-
- def spawn_pytest(self, string, expect_timeout=10.0):
- """Run py.test using pexpect.
-
- This makes sure to use the right py.test and sets up the
- temporary directory locations.
-
- The pexpect child is returned.
-
- """
- basetemp = self.tmpdir.mkdir("pexpect")
- invoke = " ".join(map(str, self._getpytestargs()))
- cmd = "%s --basetemp=%s %s" % (invoke, basetemp, string)
- return self.spawn(cmd, expect_timeout=expect_timeout)
-
- def spawn(self, cmd, expect_timeout=10.0):
- """Run a command using pexpect.
-
- The pexpect child is returned.
- """
- pexpect = pytest.importorskip("pexpect", "3.0")
- if hasattr(sys, 'pypy_version_info') and '64' in platform.machine():
- pytest.skip("pypy-64 bit not supported")
- if sys.platform == "darwin":
- pytest.xfail("pexpect does not work reliably on darwin?!")
- if sys.platform.startswith("freebsd"):
- pytest.xfail("pexpect does not work reliably on freebsd")
- logfile = self.tmpdir.join("spawn.out").open("wb")
- child = pexpect.spawn(cmd, logfile=logfile)
- self.request.addfinalizer(logfile.close)
- child.timeout = expect_timeout
- return child
-
-def getdecoded(out):
- try:
- return out.decode("utf-8")
- except UnicodeDecodeError:
- return "INTERNAL not-utf8-decodeable, truncated string:\n%s" % (
- py.io.saferepr(out),)
-
-
-class LineComp:
- def __init__(self):
- self.stringio = py.io.TextIO()
-
- def assert_contains_lines(self, lines2):
- """ assert that lines2 are contained (linearly) in lines1.
- return a list of extralines found.
- """
- __tracebackhide__ = True
- val = self.stringio.getvalue()
- self.stringio.truncate(0)
- self.stringio.seek(0)
- lines1 = val.split("\n")
- return LineMatcher(lines1).fnmatch_lines(lines2)
-
-
-class LineMatcher:
- """Flexible matching of text.
-
- This is a convenience class to test large texts like the output of
- commands.
-
- The constructor takes a list of lines without their trailing
- newlines, i.e. ``text.splitlines()``.
-
- """
-
- def __init__(self, lines):
- self.lines = lines
-
- def str(self):
- """Return the entire original text."""
- return "\n".join(self.lines)
-
- def _getlines(self, lines2):
- if isinstance(lines2, str):
- lines2 = Source(lines2)
- if isinstance(lines2, Source):
- lines2 = lines2.strip().lines
- return lines2
-
- def fnmatch_lines_random(self, lines2):
- """Check lines exist in the output.
-
- The argument is a list of lines which have to occur in the
- output, in any order. Each line can contain glob whildcards.
-
- """
- lines2 = self._getlines(lines2)
- for line in lines2:
- for x in self.lines:
- if line == x or fnmatch(x, line):
- print_("matched: ", repr(line))
- break
- else:
- raise ValueError("line %r not found in output" % line)
-
- def get_lines_after(self, fnline):
- """Return all lines following the given line in the text.
-
- The given line can contain glob wildcards.
- """
- for i, line in enumerate(self.lines):
- if fnline == line or fnmatch(line, fnline):
- return self.lines[i+1:]
- raise ValueError("line %r not found in output" % fnline)
-
- def fnmatch_lines(self, lines2):
- """Search the text for matching lines.
-
- The argument is a list of lines which have to match and can
- use glob wildcards. If they do not match an pytest.fail() is
- called. The matches and non-matches are also printed on
- stdout.
-
- """
- def show(arg1, arg2):
- py.builtin.print_(arg1, arg2, file=sys.stderr)
- lines2 = self._getlines(lines2)
- lines1 = self.lines[:]
- nextline = None
- extralines = []
- __tracebackhide__ = True
- for line in lines2:
- nomatchprinted = False
- while lines1:
- nextline = lines1.pop(0)
- if line == nextline:
- show("exact match:", repr(line))
- break
- elif fnmatch(nextline, line):
- show("fnmatch:", repr(line))
- show(" with:", repr(nextline))
- break
- else:
- if not nomatchprinted:
- show("nomatch:", repr(line))
- nomatchprinted = True
- show(" and:", repr(nextline))
- extralines.append(nextline)
- else:
- pytest.fail("remains unmatched: %r, see stderr" % (line,))
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/python.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/python.py
deleted file mode 100644
index 3580eae074f..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/python.py
+++ /dev/null
@@ -1,2302 +0,0 @@
-""" Python test discovery, setup and run of test functions. """
-import fnmatch
-import functools
-import inspect
-import re
-import types
-import sys
-
-import py
-import pytest
-from _pytest._code.code import TerminalRepr
-from _pytest.mark import MarkDecorator, MarkerError
-
-try:
- import enum
-except ImportError: # pragma: no cover
- # Only available in Python 3.4+ or as a backport
- enum = None
-
-import _pytest
-import _pytest._pluggy as pluggy
-
-cutdir2 = py.path.local(_pytest.__file__).dirpath()
-cutdir1 = py.path.local(pluggy.__file__.rstrip("oc"))
-
-
-NoneType = type(None)
-NOTSET = object()
-isfunction = inspect.isfunction
-isclass = inspect.isclass
-callable = py.builtin.callable
-# used to work around a python2 exception info leak
-exc_clear = getattr(sys, 'exc_clear', lambda: None)
-# The type of re.compile objects is not exposed in Python.
-REGEX_TYPE = type(re.compile(''))
-
-_PY3 = sys.version_info > (3, 0)
-_PY2 = not _PY3
-
-
-if hasattr(inspect, 'signature'):
- def _format_args(func):
- return str(inspect.signature(func))
-else:
- def _format_args(func):
- return inspect.formatargspec(*inspect.getargspec(func))
-
-if sys.version_info[:2] == (2, 6):
- def isclass(object):
- """ Return true if the object is a class. Overrides inspect.isclass for
- python 2.6 because it will return True for objects which always return
- something on __getattr__ calls (see #1035).
- Backport of https://hg.python.org/cpython/rev/35bf8f7a8edc
- """
- return isinstance(object, (type, types.ClassType))
-
-def _has_positional_arg(func):
- return func.__code__.co_argcount
-
-
-def filter_traceback(entry):
- # entry.path might sometimes return a str object when the entry
- # points to dynamically generated code
- # see https://bitbucket.org/pytest-dev/py/issues/71
- raw_filename = entry.frame.code.raw.co_filename
- is_generated = '<' in raw_filename and '>' in raw_filename
- if is_generated:
- return False
- # entry.path might point to an inexisting file, in which case it will
- # alsso return a str object. see #1133
- p = py.path.local(entry.path)
- return p != cutdir1 and not p.relto(cutdir2)
-
-
-def get_real_func(obj):
- """ gets the real function object of the (possibly) wrapped object by
- functools.wraps or functools.partial.
- """
- while hasattr(obj, "__wrapped__"):
- obj = obj.__wrapped__
- if isinstance(obj, functools.partial):
- obj = obj.func
- return obj
-
-def getfslineno(obj):
- # xxx let decorators etc specify a sane ordering
- obj = get_real_func(obj)
- if hasattr(obj, 'place_as'):
- obj = obj.place_as
- fslineno = _pytest._code.getfslineno(obj)
- assert isinstance(fslineno[1], int), obj
- return fslineno
-
-def getimfunc(func):
- try:
- return func.__func__
- except AttributeError:
- try:
- return func.im_func
- except AttributeError:
- return func
-
-def safe_getattr(object, name, default):
- """ Like getattr but return default upon any Exception.
-
- Attribute access can potentially fail for 'evil' Python objects.
- See issue214
- """
- try:
- return getattr(object, name, default)
- except Exception:
- return default
-
-
-class FixtureFunctionMarker:
- def __init__(self, scope, params,
- autouse=False, yieldctx=False, ids=None):
- self.scope = scope
- self.params = params
- self.autouse = autouse
- self.yieldctx = yieldctx
- self.ids = ids
-
- def __call__(self, function):
- if isclass(function):
- raise ValueError(
- "class fixtures not supported (may be in the future)")
- function._pytestfixturefunction = self
- return function
-
-
-def fixture(scope="function", params=None, autouse=False, ids=None):
- """ (return a) decorator to mark a fixture factory function.
-
- This decorator can be used (with or or without parameters) to define
- a fixture function. The name of the fixture function can later be
- referenced to cause its invocation ahead of running tests: test
- modules or classes can use the pytest.mark.usefixtures(fixturename)
- marker. Test functions can directly use fixture names as input
- arguments in which case the fixture instance returned from the fixture
- function will be injected.
-
- :arg scope: the scope for which this fixture is shared, one of
- "function" (default), "class", "module", "session".
-
- :arg params: an optional list of parameters which will cause multiple
- invocations of the fixture function and all of the tests
- using it.
-
- :arg autouse: if True, the fixture func is activated for all tests that
- can see it. If False (the default) then an explicit
- reference is needed to activate the fixture.
-
- :arg ids: list of string ids each corresponding to the params
- so that they are part of the test id. If no ids are provided
- they will be generated automatically from the params.
-
- """
- if callable(scope) and params is None and autouse == False:
- # direct decoration
- return FixtureFunctionMarker(
- "function", params, autouse)(scope)
- if params is not None and not isinstance(params, (list, tuple)):
- params = list(params)
- return FixtureFunctionMarker(scope, params, autouse, ids=ids)
-
-def yield_fixture(scope="function", params=None, autouse=False, ids=None):
- """ (return a) decorator to mark a yield-fixture factory function
- (EXPERIMENTAL).
-
- This takes the same arguments as :py:func:`pytest.fixture` but
- expects a fixture function to use a ``yield`` instead of a ``return``
- statement to provide a fixture. See
- http://pytest.org/en/latest/yieldfixture.html for more info.
- """
- if callable(scope) and params is None and autouse == False:
- # direct decoration
- return FixtureFunctionMarker(
- "function", params, autouse, yieldctx=True)(scope)
- else:
- return FixtureFunctionMarker(scope, params, autouse,
- yieldctx=True, ids=ids)
-
-defaultfuncargprefixmarker = fixture()
-
-def pyobj_property(name):
- def get(self):
- node = self.getparent(getattr(pytest, name))
- if node is not None:
- return node.obj
- doc = "python %s object this node was collected from (can be None)." % (
- name.lower(),)
- return property(get, None, None, doc)
-
-
-def pytest_addoption(parser):
- group = parser.getgroup("general")
- group.addoption('--fixtures', '--funcargs',
- action="store_true", dest="showfixtures", default=False,
- help="show available fixtures, sorted by plugin appearance")
- parser.addini("usefixtures", type="args", default=[],
- help="list of default fixtures to be used with this project")
- parser.addini("python_files", type="args",
- default=['test_*.py', '*_test.py'],
- help="glob-style file patterns for Python test module discovery")
- parser.addini("python_classes", type="args", default=["Test",],
- help="prefixes or glob names for Python test class discovery")
- parser.addini("python_functions", type="args", default=["test",],
- help="prefixes or glob names for Python test function and "
- "method discovery")
-
- group.addoption("--import-mode", default="prepend",
- choices=["prepend", "append"], dest="importmode",
- help="prepend/append to sys.path when importing test modules, "
- "default is to prepend.")
-
-
-def pytest_cmdline_main(config):
- if config.option.showfixtures:
- showfixtures(config)
- return 0
-
-
-def pytest_generate_tests(metafunc):
- # those alternative spellings are common - raise a specific error to alert
- # the user
- alt_spellings = ['parameterize', 'parametrise', 'parameterise']
- for attr in alt_spellings:
- if hasattr(metafunc.function, attr):
- msg = "{0} has '{1}', spelling should be 'parametrize'"
- raise MarkerError(msg.format(metafunc.function.__name__, attr))
- try:
- markers = metafunc.function.parametrize
- except AttributeError:
- return
- for marker in markers:
- metafunc.parametrize(*marker.args, **marker.kwargs)
-
-def pytest_configure(config):
- config.addinivalue_line("markers",
- "parametrize(argnames, argvalues): call a test function multiple "
- "times passing in different arguments in turn. argvalues generally "
- "needs to be a list of values if argnames specifies only one name "
- "or a list of tuples of values if argnames specifies multiple names. "
- "Example: @parametrize('arg1', [1,2]) would lead to two calls of the "
- "decorated test function, one with arg1=1 and another with arg1=2."
- "see http://pytest.org/latest/parametrize.html for more info and "
- "examples."
- )
- config.addinivalue_line("markers",
- "usefixtures(fixturename1, fixturename2, ...): mark tests as needing "
- "all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures "
- )
-
-def pytest_sessionstart(session):
- session._fixturemanager = FixtureManager(session)
-
-@pytest.hookimpl(trylast=True)
-def pytest_namespace():
- raises.Exception = pytest.fail.Exception
- return {
- 'fixture': fixture,
- 'yield_fixture': yield_fixture,
- 'raises' : raises,
- 'collect': {
- 'Module': Module, 'Class': Class, 'Instance': Instance,
- 'Function': Function, 'Generator': Generator,
- '_fillfuncargs': fillfixtures}
- }
-
-@fixture(scope="session")
-def pytestconfig(request):
- """ the pytest config object with access to command line opts."""
- return request.config
-
-
-@pytest.hookimpl(trylast=True)
-def pytest_pyfunc_call(pyfuncitem):
- testfunction = pyfuncitem.obj
- if pyfuncitem._isyieldedfunction():
- testfunction(*pyfuncitem._args)
- else:
- funcargs = pyfuncitem.funcargs
- testargs = {}
- for arg in pyfuncitem._fixtureinfo.argnames:
- testargs[arg] = funcargs[arg]
- testfunction(**testargs)
- return True
-
-def pytest_collect_file(path, parent):
- ext = path.ext
- if ext == ".py":
- if not parent.session.isinitpath(path):
- for pat in parent.config.getini('python_files'):
- if path.fnmatch(pat):
- break
- else:
- return
- ihook = parent.session.gethookproxy(path)
- return ihook.pytest_pycollect_makemodule(path=path, parent=parent)
-
-def pytest_pycollect_makemodule(path, parent):
- return Module(path, parent)
-
-@pytest.hookimpl(hookwrapper=True)
-def pytest_pycollect_makeitem(collector, name, obj):
- outcome = yield
- res = outcome.get_result()
- if res is not None:
- raise StopIteration
- # nothing was collected elsewhere, let's do it here
- if isclass(obj):
- if collector.istestclass(obj, name):
- Class = collector._getcustomclass("Class")
- outcome.force_result(Class(name, parent=collector))
- elif collector.istestfunction(obj, name):
- # mock seems to store unbound methods (issue473), normalize it
- obj = getattr(obj, "__func__", obj)
- # We need to try and unwrap the function if it's a functools.partial
- # or a funtools.wrapped.
- # We musn't if it's been wrapped with mock.patch (python 2 only)
- if not (isfunction(obj) or isfunction(get_real_func(obj))):
- collector.warn(code="C2", message=
- "cannot collect %r because it is not a function."
- % name, )
- elif getattr(obj, "__test__", True):
- if is_generator(obj):
- res = Generator(name, parent=collector)
- else:
- res = list(collector._genfunctions(name, obj))
- outcome.force_result(res)
-
-def is_generator(func):
- try:
- return _pytest._code.getrawcode(func).co_flags & 32 # generator function
- except AttributeError: # builtin functions have no bytecode
- # assume them to not be generators
- return False
-
-class PyobjContext(object):
- module = pyobj_property("Module")
- cls = pyobj_property("Class")
- instance = pyobj_property("Instance")
-
-class PyobjMixin(PyobjContext):
- def obj():
- def fget(self):
- try:
- return self._obj
- except AttributeError:
- self._obj = obj = self._getobj()
- return obj
- def fset(self, value):
- self._obj = value
- return property(fget, fset, None, "underlying python object")
- obj = obj()
-
- def _getobj(self):
- return getattr(self.parent.obj, self.name)
-
- def getmodpath(self, stopatmodule=True, includemodule=False):
- """ return python path relative to the containing module. """
- chain = self.listchain()
- chain.reverse()
- parts = []
- for node in chain:
- if isinstance(node, Instance):
- continue
- name = node.name
- if isinstance(node, Module):
- assert name.endswith(".py")
- name = name[:-3]
- if stopatmodule:
- if includemodule:
- parts.append(name)
- break
- parts.append(name)
- parts.reverse()
- s = ".".join(parts)
- return s.replace(".[", "[")
-
- def _getfslineno(self):
- return getfslineno(self.obj)
-
- def reportinfo(self):
- # XXX caching?
- obj = self.obj
- compat_co_firstlineno = getattr(obj, 'compat_co_firstlineno', None)
- if isinstance(compat_co_firstlineno, int):
- # nose compatibility
- fspath = sys.modules[obj.__module__].__file__
- if fspath.endswith(".pyc"):
- fspath = fspath[:-1]
- lineno = compat_co_firstlineno
- else:
- fspath, lineno = getfslineno(obj)
- modpath = self.getmodpath()
- assert isinstance(lineno, int)
- return fspath, lineno, modpath
-
-class PyCollector(PyobjMixin, pytest.Collector):
-
- def funcnamefilter(self, name):
- return self._matches_prefix_or_glob_option('python_functions', name)
-
- def isnosetest(self, obj):
- """ Look for the __test__ attribute, which is applied by the
- @nose.tools.istest decorator
- """
- # We explicitly check for "is True" here to not mistakenly treat
- # classes with a custom __getattr__ returning something truthy (like a
- # function) as test classes.
- return safe_getattr(obj, '__test__', False) is True
-
- def classnamefilter(self, name):
- return self._matches_prefix_or_glob_option('python_classes', name)
-
- def istestfunction(self, obj, name):
- return (
- (self.funcnamefilter(name) or self.isnosetest(obj)) and
- safe_getattr(obj, "__call__", False) and getfixturemarker(obj) is None
- )
-
- def istestclass(self, obj, name):
- return self.classnamefilter(name) or self.isnosetest(obj)
-
- def _matches_prefix_or_glob_option(self, option_name, name):
- """
- checks if the given name matches the prefix or glob-pattern defined
- in ini configuration.
- """
- for option in self.config.getini(option_name):
- if name.startswith(option):
- return True
- # check that name looks like a glob-string before calling fnmatch
- # because this is called for every name in each collected module,
- # and fnmatch is somewhat expensive to call
- elif ('*' in option or '?' in option or '[' in option) and \
- fnmatch.fnmatch(name, option):
- return True
- return False
-
- def collect(self):
- if not getattr(self.obj, "__test__", True):
- return []
-
- # NB. we avoid random getattrs and peek in the __dict__ instead
- # (XXX originally introduced from a PyPy need, still true?)
- dicts = [getattr(self.obj, '__dict__', {})]
- for basecls in inspect.getmro(self.obj.__class__):
- dicts.append(basecls.__dict__)
- seen = {}
- l = []
- for dic in dicts:
- for name, obj in list(dic.items()):
- if name in seen:
- continue
- seen[name] = True
- res = self.makeitem(name, obj)
- if res is None:
- continue
- if not isinstance(res, list):
- res = [res]
- l.extend(res)
- l.sort(key=lambda item: item.reportinfo()[:2])
- return l
-
- def makeitem(self, name, obj):
- #assert self.ihook.fspath == self.fspath, self
- return self.ihook.pytest_pycollect_makeitem(
- collector=self, name=name, obj=obj)
-
- def _genfunctions(self, name, funcobj):
- module = self.getparent(Module).obj
- clscol = self.getparent(Class)
- cls = clscol and clscol.obj or None
- transfer_markers(funcobj, cls, module)
- fm = self.session._fixturemanager
- fixtureinfo = fm.getfixtureinfo(self, funcobj, cls)
- metafunc = Metafunc(funcobj, fixtureinfo, self.config,
- cls=cls, module=module)
- methods = []
- if hasattr(module, "pytest_generate_tests"):
- methods.append(module.pytest_generate_tests)
- if hasattr(cls, "pytest_generate_tests"):
- methods.append(cls().pytest_generate_tests)
- if methods:
- self.ihook.pytest_generate_tests.call_extra(methods,
- dict(metafunc=metafunc))
- else:
- self.ihook.pytest_generate_tests(metafunc=metafunc)
-
- Function = self._getcustomclass("Function")
- if not metafunc._calls:
- yield Function(name, parent=self, fixtureinfo=fixtureinfo)
- else:
- # add funcargs() as fixturedefs to fixtureinfo.arg2fixturedefs
- add_funcarg_pseudo_fixture_def(self, metafunc, fm)
-
- for callspec in metafunc._calls:
- subname = "%s[%s]" %(name, callspec.id)
- yield Function(name=subname, parent=self,
- callspec=callspec, callobj=funcobj,
- fixtureinfo=fixtureinfo,
- keywords={callspec.id:True})
-
-def add_funcarg_pseudo_fixture_def(collector, metafunc, fixturemanager):
- # this function will transform all collected calls to a functions
- # if they use direct funcargs (i.e. direct parametrization)
- # because we want later test execution to be able to rely on
- # an existing FixtureDef structure for all arguments.
- # XXX we can probably avoid this algorithm if we modify CallSpec2
- # to directly care for creating the fixturedefs within its methods.
- if not metafunc._calls[0].funcargs:
- return # this function call does not have direct parametrization
- # collect funcargs of all callspecs into a list of values
- arg2params = {}
- arg2scope = {}
- for callspec in metafunc._calls:
- for argname, argvalue in callspec.funcargs.items():
- assert argname not in callspec.params
- callspec.params[argname] = argvalue
- arg2params_list = arg2params.setdefault(argname, [])
- callspec.indices[argname] = len(arg2params_list)
- arg2params_list.append(argvalue)
- if argname not in arg2scope:
- scopenum = callspec._arg2scopenum.get(argname,
- scopenum_function)
- arg2scope[argname] = scopes[scopenum]
- callspec.funcargs.clear()
-
- # register artificial FixtureDef's so that later at test execution
- # time we can rely on a proper FixtureDef to exist for fixture setup.
- arg2fixturedefs = metafunc._arg2fixturedefs
- for argname, valuelist in arg2params.items():
- # if we have a scope that is higher than function we need
- # to make sure we only ever create an according fixturedef on
- # a per-scope basis. We thus store and cache the fixturedef on the
- # node related to the scope.
- scope = arg2scope[argname]
- node = None
- if scope != "function":
- node = get_scope_node(collector, scope)
- if node is None:
- assert scope == "class" and isinstance(collector, Module)
- # use module-level collector for class-scope (for now)
- node = collector
- if node and argname in node._name2pseudofixturedef:
- arg2fixturedefs[argname] = [node._name2pseudofixturedef[argname]]
- else:
- fixturedef = FixtureDef(fixturemanager, '', argname,
- get_direct_param_fixture_func,
- arg2scope[argname],
- valuelist, False, False)
- arg2fixturedefs[argname] = [fixturedef]
- if node is not None:
- node._name2pseudofixturedef[argname] = fixturedef
-
-
-def get_direct_param_fixture_func(request):
- return request.param
-
-class FuncFixtureInfo:
- def __init__(self, argnames, names_closure, name2fixturedefs):
- self.argnames = argnames
- self.names_closure = names_closure
- self.name2fixturedefs = name2fixturedefs
-
-
-def _marked(func, mark):
- """ Returns True if :func: is already marked with :mark:, False otherwise.
- This can happen if marker is applied to class and the test file is
- invoked more than once.
- """
- try:
- func_mark = getattr(func, mark.name)
- except AttributeError:
- return False
- return mark.args == func_mark.args and mark.kwargs == func_mark.kwargs
-
-
-def transfer_markers(funcobj, cls, mod):
- # XXX this should rather be code in the mark plugin or the mark
- # plugin should merge with the python plugin.
- for holder in (cls, mod):
- try:
- pytestmark = holder.pytestmark
- except AttributeError:
- continue
- if isinstance(pytestmark, list):
- for mark in pytestmark:
- if not _marked(funcobj, mark):
- mark(funcobj)
- else:
- if not _marked(funcobj, pytestmark):
- pytestmark(funcobj)
-
-class Module(pytest.File, PyCollector):
- """ Collector for test classes and functions. """
- def _getobj(self):
- return self._memoizedcall('_obj', self._importtestmodule)
-
- def collect(self):
- self.session._fixturemanager.parsefactories(self)
- return super(Module, self).collect()
-
- def _importtestmodule(self):
- # we assume we are only called once per module
- importmode = self.config.getoption("--import-mode")
- try:
- mod = self.fspath.pyimport(ensuresyspath=importmode)
- except SyntaxError:
- raise self.CollectError(
- _pytest._code.ExceptionInfo().getrepr(style="short"))
- except self.fspath.ImportMismatchError:
- e = sys.exc_info()[1]
- raise self.CollectError(
- "import file mismatch:\n"
- "imported module %r has this __file__ attribute:\n"
- " %s\n"
- "which is not the same as the test file we want to collect:\n"
- " %s\n"
- "HINT: remove __pycache__ / .pyc files and/or use a "
- "unique basename for your test file modules"
- % e.args
- )
- #print "imported test module", mod
- self.config.pluginmanager.consider_module(mod)
- return mod
-
- def setup(self):
- setup_module = xunitsetup(self.obj, "setUpModule")
- if setup_module is None:
- setup_module = xunitsetup(self.obj, "setup_module")
- if setup_module is not None:
- #XXX: nose compat hack, move to nose plugin
- # if it takes a positional arg, its probably a pytest style one
- # so we pass the current module object
- if _has_positional_arg(setup_module):
- setup_module(self.obj)
- else:
- setup_module()
- fin = getattr(self.obj, 'tearDownModule', None)
- if fin is None:
- fin = getattr(self.obj, 'teardown_module', None)
- if fin is not None:
- #XXX: nose compat hack, move to nose plugin
- # if it takes a positional arg, it's probably a pytest style one
- # so we pass the current module object
- if _has_positional_arg(fin):
- finalizer = lambda: fin(self.obj)
- else:
- finalizer = fin
- self.addfinalizer(finalizer)
-
-
-class Class(PyCollector):
- """ Collector for test methods. """
- def collect(self):
- if hasinit(self.obj):
- self.warn("C1", "cannot collect test class %r because it has a "
- "__init__ constructor" % self.obj.__name__)
- return []
- return [self._getcustomclass("Instance")(name="()", parent=self)]
-
- def setup(self):
- setup_class = xunitsetup(self.obj, 'setup_class')
- if setup_class is not None:
- setup_class = getattr(setup_class, 'im_func', setup_class)
- setup_class = getattr(setup_class, '__func__', setup_class)
- setup_class(self.obj)
-
- fin_class = getattr(self.obj, 'teardown_class', None)
- if fin_class is not None:
- fin_class = getattr(fin_class, 'im_func', fin_class)
- fin_class = getattr(fin_class, '__func__', fin_class)
- self.addfinalizer(lambda: fin_class(self.obj))
-
-class Instance(PyCollector):
- def _getobj(self):
- obj = self.parent.obj()
- return obj
-
- def collect(self):
- self.session._fixturemanager.parsefactories(self)
- return super(Instance, self).collect()
-
- def newinstance(self):
- self.obj = self._getobj()
- return self.obj
-
-class FunctionMixin(PyobjMixin):
- """ mixin for the code common to Function and Generator.
- """
-
- def setup(self):
- """ perform setup for this test function. """
- if hasattr(self, '_preservedparent'):
- obj = self._preservedparent
- elif isinstance(self.parent, Instance):
- obj = self.parent.newinstance()
- self.obj = self._getobj()
- else:
- obj = self.parent.obj
- if inspect.ismethod(self.obj):
- setup_name = 'setup_method'
- teardown_name = 'teardown_method'
- else:
- setup_name = 'setup_function'
- teardown_name = 'teardown_function'
- setup_func_or_method = xunitsetup(obj, setup_name)
- if setup_func_or_method is not None:
- setup_func_or_method(self.obj)
- fin = getattr(obj, teardown_name, None)
- if fin is not None:
- self.addfinalizer(lambda: fin(self.obj))
-
- def _prunetraceback(self, excinfo):
- if hasattr(self, '_obj') and not self.config.option.fulltrace:
- code = _pytest._code.Code(get_real_func(self.obj))
- path, firstlineno = code.path, code.firstlineno
- traceback = excinfo.traceback
- ntraceback = traceback.cut(path=path, firstlineno=firstlineno)
- if ntraceback == traceback:
- ntraceback = ntraceback.cut(path=path)
- if ntraceback == traceback:
- #ntraceback = ntraceback.cut(excludepath=cutdir2)
- ntraceback = ntraceback.filter(filter_traceback)
- if not ntraceback:
- ntraceback = traceback
-
- excinfo.traceback = ntraceback.filter()
- # issue364: mark all but first and last frames to
- # only show a single-line message for each frame
- if self.config.option.tbstyle == "auto":
- if len(excinfo.traceback) > 2:
- for entry in excinfo.traceback[1:-1]:
- entry.set_repr_style('short')
-
- def _repr_failure_py(self, excinfo, style="long"):
- if excinfo.errisinstance(pytest.fail.Exception):
- if not excinfo.value.pytrace:
- return py._builtin._totext(excinfo.value)
- return super(FunctionMixin, self)._repr_failure_py(excinfo,
- style=style)
-
- def repr_failure(self, excinfo, outerr=None):
- assert outerr is None, "XXX outerr usage is deprecated"
- style = self.config.option.tbstyle
- if style == "auto":
- style = "long"
- return self._repr_failure_py(excinfo, style=style)
-
-
-class Generator(FunctionMixin, PyCollector):
- def collect(self):
- # test generators are seen as collectors but they also
- # invoke setup/teardown on popular request
- # (induced by the common "test_*" naming shared with normal tests)
- self.session._setupstate.prepare(self)
- # see FunctionMixin.setup and test_setupstate_is_preserved_134
- self._preservedparent = self.parent.obj
- l = []
- seen = {}
- for i, x in enumerate(self.obj()):
- name, call, args = self.getcallargs(x)
- if not callable(call):
- raise TypeError("%r yielded non callable test %r" %(self.obj, call,))
- if name is None:
- name = "[%d]" % i
- else:
- name = "['%s']" % name
- if name in seen:
- raise ValueError("%r generated tests with non-unique name %r" %(self, name))
- seen[name] = True
- l.append(self.Function(name, self, args=args, callobj=call))
- return l
-
- def getcallargs(self, obj):
- if not isinstance(obj, (tuple, list)):
- obj = (obj,)
- # explict naming
- if isinstance(obj[0], py.builtin._basestring):
- name = obj[0]
- obj = obj[1:]
- else:
- name = None
- call, args = obj[0], obj[1:]
- return name, call, args
-
-
-def hasinit(obj):
- init = getattr(obj, '__init__', None)
- if init:
- if init != object.__init__:
- return True
-
-
-
-def fillfixtures(function):
- """ fill missing funcargs for a test function. """
- try:
- request = function._request
- except AttributeError:
- # XXX this special code path is only expected to execute
- # with the oejskit plugin. It uses classes with funcargs
- # and we thus have to work a bit to allow this.
- fm = function.session._fixturemanager
- fi = fm.getfixtureinfo(function.parent, function.obj, None)
- function._fixtureinfo = fi
- request = function._request = FixtureRequest(function)
- request._fillfixtures()
- # prune out funcargs for jstests
- newfuncargs = {}
- for name in fi.argnames:
- newfuncargs[name] = function.funcargs[name]
- function.funcargs = newfuncargs
- else:
- request._fillfixtures()
-
-
-_notexists = object()
-
-class CallSpec2(object):
- def __init__(self, metafunc):
- self.metafunc = metafunc
- self.funcargs = {}
- self._idlist = []
- self.params = {}
- self._globalid = _notexists
- self._globalid_args = set()
- self._globalparam = _notexists
- self._arg2scopenum = {} # used for sorting parametrized resources
- self.keywords = {}
- self.indices = {}
-
- def copy(self, metafunc):
- cs = CallSpec2(self.metafunc)
- cs.funcargs.update(self.funcargs)
- cs.params.update(self.params)
- cs.keywords.update(self.keywords)
- cs.indices.update(self.indices)
- cs._arg2scopenum.update(self._arg2scopenum)
- cs._idlist = list(self._idlist)
- cs._globalid = self._globalid
- cs._globalid_args = self._globalid_args
- cs._globalparam = self._globalparam
- return cs
-
- def _checkargnotcontained(self, arg):
- if arg in self.params or arg in self.funcargs:
- raise ValueError("duplicate %r" %(arg,))
-
- def getparam(self, name):
- try:
- return self.params[name]
- except KeyError:
- if self._globalparam is _notexists:
- raise ValueError(name)
- return self._globalparam
-
- @property
- def id(self):
- return "-".join(map(str, filter(None, self._idlist)))
-
- def setmulti(self, valtypes, argnames, valset, id, keywords, scopenum,
- param_index):
- for arg,val in zip(argnames, valset):
- self._checkargnotcontained(arg)
- valtype_for_arg = valtypes[arg]
- getattr(self, valtype_for_arg)[arg] = val
- self.indices[arg] = param_index
- self._arg2scopenum[arg] = scopenum
- if val is _notexists:
- self._emptyparamspecified = True
- self._idlist.append(id)
- self.keywords.update(keywords)
-
- def setall(self, funcargs, id, param):
- for x in funcargs:
- self._checkargnotcontained(x)
- self.funcargs.update(funcargs)
- if id is not _notexists:
- self._idlist.append(id)
- if param is not _notexists:
- assert self._globalparam is _notexists
- self._globalparam = param
- for arg in funcargs:
- self._arg2scopenum[arg] = scopenum_function
-
-
-class FuncargnamesCompatAttr:
- """ helper class so that Metafunc, Function and FixtureRequest
- don't need to each define the "funcargnames" compatibility attribute.
- """
- @property
- def funcargnames(self):
- """ alias attribute for ``fixturenames`` for pre-2.3 compatibility"""
- return self.fixturenames
-
-class Metafunc(FuncargnamesCompatAttr):
- """
- Metafunc objects are passed to the ``pytest_generate_tests`` hook.
- They help to inspect a test function and to generate tests according to
- test configuration or values specified in the class or module where a
- test function is defined.
-
- :ivar fixturenames: set of fixture names required by the test function
-
- :ivar function: underlying python test function
-
- :ivar cls: class object where the test function is defined in or ``None``.
-
- :ivar module: the module object where the test function is defined in.
-
- :ivar config: access to the :class:`_pytest.config.Config` object for the
- test session.
-
- :ivar funcargnames:
- .. deprecated:: 2.3
- Use ``fixturenames`` instead.
- """
- def __init__(self, function, fixtureinfo, config, cls=None, module=None):
- self.config = config
- self.module = module
- self.function = function
- self.fixturenames = fixtureinfo.names_closure
- self._arg2fixturedefs = fixtureinfo.name2fixturedefs
- self.cls = cls
- self._calls = []
- self._ids = py.builtin.set()
-
- def parametrize(self, argnames, argvalues, indirect=False, ids=None,
- scope=None):
- """ Add new invocations to the underlying test function using the list
- of argvalues for the given argnames. Parametrization is performed
- during the collection phase. If you need to setup expensive resources
- see about setting indirect to do it rather at test setup time.
-
- :arg argnames: a comma-separated string denoting one or more argument
- names, or a list/tuple of argument strings.
-
- :arg argvalues: The list of argvalues determines how often a
- test is invoked with different argument values. If only one
- argname was specified argvalues is a list of values. If N
- argnames were specified, argvalues must be a list of N-tuples,
- where each tuple-element specifies a value for its respective
- argname.
-
- :arg indirect: The list of argnames or boolean. A list of arguments'
- names (subset of argnames). If True the list contains all names from
- the argnames. Each argvalue corresponding to an argname in this list will
- be passed as request.param to its respective argname fixture
- function so that it can perform more expensive setups during the
- setup phase of a test rather than at collection time.
-
- :arg ids: list of string ids, or a callable.
- If strings, each is corresponding to the argvalues so that they are
- part of the test id.
- If callable, it should take one argument (a single argvalue) and return
- a string or return None. If None, the automatically generated id for that
- argument will be used.
- If no ids are provided they will be generated automatically from
- the argvalues.
-
- :arg scope: if specified it denotes the scope of the parameters.
- The scope is used for grouping tests by parameter instances.
- It will also override any fixture-function defined scope, allowing
- to set a dynamic scope using test context or configuration.
- """
-
- # individual parametrized argument sets can be wrapped in a series
- # of markers in which case we unwrap the values and apply the mark
- # at Function init
- newkeywords = {}
- unwrapped_argvalues = []
- for i, argval in enumerate(argvalues):
- while isinstance(argval, MarkDecorator):
- newmark = MarkDecorator(argval.markname,
- argval.args[:-1], argval.kwargs)
- newmarks = newkeywords.setdefault(i, {})
- newmarks[newmark.markname] = newmark
- argval = argval.args[-1]
- unwrapped_argvalues.append(argval)
- argvalues = unwrapped_argvalues
-
- if not isinstance(argnames, (tuple, list)):
- argnames = [x.strip() for x in argnames.split(",") if x.strip()]
- if len(argnames) == 1:
- argvalues = [(val,) for val in argvalues]
- if not argvalues:
- argvalues = [(_notexists,) * len(argnames)]
-
- if scope is None:
- scope = "function"
- scopenum = scopes.index(scope)
- valtypes = {}
- for arg in argnames:
- if arg not in self.fixturenames:
- raise ValueError("%r uses no fixture %r" %(self.function, arg))
-
- if indirect is True:
- valtypes = dict.fromkeys(argnames, "params")
- elif indirect is False:
- valtypes = dict.fromkeys(argnames, "funcargs")
- elif isinstance(indirect, (tuple, list)):
- valtypes = dict.fromkeys(argnames, "funcargs")
- for arg in indirect:
- if arg not in argnames:
- raise ValueError("indirect given to %r: fixture %r doesn't exist" %(
- self.function, arg))
- valtypes[arg] = "params"
- idfn = None
- if callable(ids):
- idfn = ids
- ids = None
- if ids and len(ids) != len(argvalues):
- raise ValueError('%d tests specified with %d ids' %(
- len(argvalues), len(ids)))
- if not ids:
- ids = idmaker(argnames, argvalues, idfn)
- newcalls = []
- for callspec in self._calls or [CallSpec2(self)]:
- for param_index, valset in enumerate(argvalues):
- assert len(valset) == len(argnames)
- newcallspec = callspec.copy(self)
- newcallspec.setmulti(valtypes, argnames, valset, ids[param_index],
- newkeywords.get(param_index, {}), scopenum,
- param_index)
- newcalls.append(newcallspec)
- self._calls = newcalls
-
- def addcall(self, funcargs=None, id=_notexists, param=_notexists):
- """ (deprecated, use parametrize) Add a new call to the underlying
- test function during the collection phase of a test run. Note that
- request.addcall() is called during the test collection phase prior and
- independently to actual test execution. You should only use addcall()
- if you need to specify multiple arguments of a test function.
-
- :arg funcargs: argument keyword dictionary used when invoking
- the test function.
-
- :arg id: used for reporting and identification purposes. If you
- don't supply an `id` an automatic unique id will be generated.
-
- :arg param: a parameter which will be exposed to a later fixture function
- invocation through the ``request.param`` attribute.
- """
- assert funcargs is None or isinstance(funcargs, dict)
- if funcargs is not None:
- for name in funcargs:
- if name not in self.fixturenames:
- pytest.fail("funcarg %r not used in this function." % name)
- else:
- funcargs = {}
- if id is None:
- raise ValueError("id=None not allowed")
- if id is _notexists:
- id = len(self._calls)
- id = str(id)
- if id in self._ids:
- raise ValueError("duplicate id %r" % id)
- self._ids.add(id)
-
- cs = CallSpec2(self)
- cs.setall(funcargs, id, param)
- self._calls.append(cs)
-
-
-if _PY3:
- import codecs
-
- def _escape_bytes(val):
- """
- If val is pure ascii, returns it as a str(), otherwise escapes
- into a sequence of escaped bytes:
- b'\xc3\xb4\xc5\xd6' -> u'\\xc3\\xb4\\xc5\\xd6'
-
- note:
- the obvious "v.decode('unicode-escape')" will return
- valid utf-8 unicode if it finds them in the string, but we
- want to return escaped bytes for any byte, even if they match
- a utf-8 string.
- """
- if val:
- # source: http://goo.gl/bGsnwC
- encoded_bytes, _ = codecs.escape_encode(val)
- return encoded_bytes.decode('ascii')
- else:
- # empty bytes crashes codecs.escape_encode (#1087)
- return ''
-else:
- def _escape_bytes(val):
- """
- In py2 bytes and str are the same type, so return it unchanged if it
- is a full ascii string, otherwise escape it into its binary form.
- """
- try:
- return val.decode('ascii')
- except UnicodeDecodeError:
- return val.encode('string-escape')
-
-
-def _idval(val, argname, idx, idfn):
- if idfn:
- try:
- s = idfn(val)
- if s:
- return s
- except Exception:
- pass
-
- if isinstance(val, bytes):
- return _escape_bytes(val)
- elif isinstance(val, (float, int, str, bool, NoneType)):
- return str(val)
- elif isinstance(val, REGEX_TYPE):
- return _escape_bytes(val.pattern) if isinstance(val.pattern, bytes) else val.pattern
- elif enum is not None and isinstance(val, enum.Enum):
- return str(val)
- elif isclass(val) and hasattr(val, '__name__'):
- return val.__name__
- elif _PY2 and isinstance(val, unicode):
- # special case for python 2: if a unicode string is
- # convertible to ascii, return it as an str() object instead
- try:
- return str(val)
- except UnicodeError:
- # fallthrough
- pass
- return str(argname)+str(idx)
-
-def _idvalset(idx, valset, argnames, idfn):
- this_id = [_idval(val, argname, idx, idfn)
- for val, argname in zip(valset, argnames)]
- return "-".join(this_id)
-
-def idmaker(argnames, argvalues, idfn=None):
- ids = [_idvalset(valindex, valset, argnames, idfn)
- for valindex, valset in enumerate(argvalues)]
- if len(set(ids)) < len(ids):
- # user may have provided a bad idfn which means the ids are not unique
- ids = [str(i) + testid for i, testid in enumerate(ids)]
- return ids
-
-def showfixtures(config):
- from _pytest.main import wrap_session
- return wrap_session(config, _showfixtures_main)
-
-def _showfixtures_main(config, session):
- import _pytest.config
- session.perform_collect()
- curdir = py.path.local()
- tw = _pytest.config.create_terminal_writer(config)
- verbose = config.getvalue("verbose")
-
- fm = session._fixturemanager
-
- available = []
- for argname, fixturedefs in fm._arg2fixturedefs.items():
- assert fixturedefs is not None
- if not fixturedefs:
- continue
- fixturedef = fixturedefs[-1]
- loc = getlocation(fixturedef.func, curdir)
- available.append((len(fixturedef.baseid),
- fixturedef.func.__module__,
- curdir.bestrelpath(loc),
- fixturedef.argname, fixturedef))
-
- available.sort()
- currentmodule = None
- for baseid, module, bestrel, argname, fixturedef in available:
- if currentmodule != module:
- if not module.startswith("_pytest."):
- tw.line()
- tw.sep("-", "fixtures defined from %s" %(module,))
- currentmodule = module
- if verbose <= 0 and argname[0] == "_":
- continue
- if verbose > 0:
- funcargspec = "%s -- %s" %(argname, bestrel,)
- else:
- funcargspec = argname
- tw.line(funcargspec, green=True)
- loc = getlocation(fixturedef.func, curdir)
- doc = fixturedef.func.__doc__ or ""
- if doc:
- for line in doc.strip().split("\n"):
- tw.line(" " + line.strip())
- else:
- tw.line(" %s: no docstring available" %(loc,),
- red=True)
-
-def getlocation(function, curdir):
- import inspect
- fn = py.path.local(inspect.getfile(function))
- lineno = py.builtin._getcode(function).co_firstlineno
- if fn.relto(curdir):
- fn = fn.relto(curdir)
- return "%s:%d" %(fn, lineno+1)
-
-# builtin pytest.raises helper
-
-def raises(expected_exception, *args, **kwargs):
- """ assert that a code block/function call raises ``expected_exception``
- and raise a failure exception otherwise.
-
- This helper produces a ``ExceptionInfo()`` object (see below).
-
- If using Python 2.5 or above, you may use this function as a
- context manager::
-
- >>> with raises(ZeroDivisionError):
- ... 1/0
-
- .. note::
-
- When using ``pytest.raises`` as a context manager, it's worthwhile to
- note that normal context manager rules apply and that the exception
- raised *must* be the final line in the scope of the context manager.
- Lines of code after that, within the scope of the context manager will
- not be executed. For example::
-
- >>> with raises(OSError) as exc_info:
- assert 1 == 1 # this will execute as expected
- raise OSError(errno.EEXISTS, 'directory exists')
- assert exc_info.value.errno == errno.EEXISTS # this will not execute
-
- Instead, the following approach must be taken (note the difference in
- scope)::
-
- >>> with raises(OSError) as exc_info:
- assert 1 == 1 # this will execute as expected
- raise OSError(errno.EEXISTS, 'directory exists')
-
- assert exc_info.value.errno == errno.EEXISTS # this will now execute
-
- Or you can specify a callable by passing a to-be-called lambda::
-
- >>> raises(ZeroDivisionError, lambda: 1/0)
- <ExceptionInfo ...>
-
- or you can specify an arbitrary callable with arguments::
-
- >>> def f(x): return 1/x
- ...
- >>> raises(ZeroDivisionError, f, 0)
- <ExceptionInfo ...>
- >>> raises(ZeroDivisionError, f, x=0)
- <ExceptionInfo ...>
-
- A third possibility is to use a string to be executed::
-
- >>> raises(ZeroDivisionError, "f(0)")
- <ExceptionInfo ...>
-
- .. autoclass:: _pytest._code.ExceptionInfo
- :members:
-
- .. note::
- Similar to caught exception objects in Python, explicitly clearing
- local references to returned ``ExceptionInfo`` objects can
- help the Python interpreter speed up its garbage collection.
-
- Clearing those references breaks a reference cycle
- (``ExceptionInfo`` --> caught exception --> frame stack raising
- the exception --> current frame stack --> local variables -->
- ``ExceptionInfo``) which makes Python keep all objects referenced
- from that cycle (including all local variables in the current
- frame) alive until the next cyclic garbage collection run. See the
- official Python ``try`` statement documentation for more detailed
- information.
-
- """
- __tracebackhide__ = True
- if expected_exception is AssertionError:
- # we want to catch a AssertionError
- # replace our subclass with the builtin one
- # see https://github.com/pytest-dev/pytest/issues/176
- from _pytest.assertion.util import BuiltinAssertionError \
- as expected_exception
- msg = ("exceptions must be old-style classes or"
- " derived from BaseException, not %s")
- if isinstance(expected_exception, tuple):
- for exc in expected_exception:
- if not isclass(exc):
- raise TypeError(msg % type(exc))
- elif not isclass(expected_exception):
- raise TypeError(msg % type(expected_exception))
-
- if not args:
- return RaisesContext(expected_exception)
- elif isinstance(args[0], str):
- code, = args
- assert isinstance(code, str)
- frame = sys._getframe(1)
- loc = frame.f_locals.copy()
- loc.update(kwargs)
- #print "raises frame scope: %r" % frame.f_locals
- try:
- code = _pytest._code.Source(code).compile()
- py.builtin.exec_(code, frame.f_globals, loc)
- # XXX didn'T mean f_globals == f_locals something special?
- # this is destroyed here ...
- except expected_exception:
- return _pytest._code.ExceptionInfo()
- else:
- func = args[0]
- try:
- func(*args[1:], **kwargs)
- except expected_exception:
- return _pytest._code.ExceptionInfo()
- pytest.fail("DID NOT RAISE {0}".format(expected_exception))
-
-class RaisesContext(object):
- def __init__(self, expected_exception):
- self.expected_exception = expected_exception
- self.excinfo = None
-
- def __enter__(self):
- self.excinfo = object.__new__(_pytest._code.ExceptionInfo)
- return self.excinfo
-
- def __exit__(self, *tp):
- __tracebackhide__ = True
- if tp[0] is None:
- pytest.fail("DID NOT RAISE")
- if sys.version_info < (2, 7):
- # py26: on __exit__() exc_value often does not contain the
- # exception value.
- # http://bugs.python.org/issue7853
- if not isinstance(tp[1], BaseException):
- exc_type, value, traceback = tp
- tp = exc_type, exc_type(value), traceback
- self.excinfo.__init__(tp)
- return issubclass(self.excinfo.type, self.expected_exception)
-
-#
-# the basic pytest Function item
-#
-
-class Function(FunctionMixin, pytest.Item, FuncargnamesCompatAttr):
- """ a Function Item is responsible for setting up and executing a
- Python test function.
- """
- _genid = None
- def __init__(self, name, parent, args=None, config=None,
- callspec=None, callobj=NOTSET, keywords=None, session=None,
- fixtureinfo=None):
- super(Function, self).__init__(name, parent, config=config,
- session=session)
- self._args = args
- if callobj is not NOTSET:
- self.obj = callobj
-
- self.keywords.update(self.obj.__dict__)
- if callspec:
- self.callspec = callspec
- self.keywords.update(callspec.keywords)
- if keywords:
- self.keywords.update(keywords)
-
- if fixtureinfo is None:
- fixtureinfo = self.session._fixturemanager.getfixtureinfo(
- self.parent, self.obj, self.cls,
- funcargs=not self._isyieldedfunction())
- self._fixtureinfo = fixtureinfo
- self.fixturenames = fixtureinfo.names_closure
- self._initrequest()
-
- def _initrequest(self):
- self.funcargs = {}
- if self._isyieldedfunction():
- assert not hasattr(self, "callspec"), (
- "yielded functions (deprecated) cannot have funcargs")
- else:
- if hasattr(self, "callspec"):
- callspec = self.callspec
- assert not callspec.funcargs
- self._genid = callspec.id
- if hasattr(callspec, "param"):
- self.param = callspec.param
- self._request = FixtureRequest(self)
-
- @property
- def function(self):
- "underlying python 'function' object"
- return getattr(self.obj, 'im_func', self.obj)
-
- def _getobj(self):
- name = self.name
- i = name.find("[") # parametrization
- if i != -1:
- name = name[:i]
- return getattr(self.parent.obj, name)
-
- @property
- def _pyfuncitem(self):
- "(compatonly) for code expecting pytest-2.2 style request objects"
- return self
-
- def _isyieldedfunction(self):
- return getattr(self, "_args", None) is not None
-
- def runtest(self):
- """ execute the underlying test function. """
- self.ihook.pytest_pyfunc_call(pyfuncitem=self)
-
- def setup(self):
- # check if parametrization happend with an empty list
- try:
- self.callspec._emptyparamspecified
- except AttributeError:
- pass
- else:
- fs, lineno = self._getfslineno()
- pytest.skip("got empty parameter set, function %s at %s:%d" %(
- self.function.__name__, fs, lineno))
- super(Function, self).setup()
- fillfixtures(self)
-
-
-scope2props = dict(session=())
-scope2props["module"] = ("fspath", "module")
-scope2props["class"] = scope2props["module"] + ("cls",)
-scope2props["instance"] = scope2props["class"] + ("instance", )
-scope2props["function"] = scope2props["instance"] + ("function", "keywords")
-
-def scopeproperty(name=None, doc=None):
- def decoratescope(func):
- scopename = name or func.__name__
- def provide(self):
- if func.__name__ in scope2props[self.scope]:
- return func(self)
- raise AttributeError("%s not available in %s-scoped context" % (
- scopename, self.scope))
- return property(provide, None, None, func.__doc__)
- return decoratescope
-
-
-class FixtureRequest(FuncargnamesCompatAttr):
- """ A request for a fixture from a test or fixture function.
-
- A request object gives access to the requesting test context
- and has an optional ``param`` attribute in case
- the fixture is parametrized indirectly.
- """
-
- def __init__(self, pyfuncitem):
- self._pyfuncitem = pyfuncitem
- #: fixture for which this request is being performed
- self.fixturename = None
- #: Scope string, one of "function", "cls", "module", "session"
- self.scope = "function"
- self._funcargs = {}
- self._fixturedefs = {}
- fixtureinfo = pyfuncitem._fixtureinfo
- self._arg2fixturedefs = fixtureinfo.name2fixturedefs.copy()
- self._arg2index = {}
- self.fixturenames = fixtureinfo.names_closure
- self._fixturemanager = pyfuncitem.session._fixturemanager
-
- @property
- def node(self):
- """ underlying collection node (depends on current request scope)"""
- return self._getscopeitem(self.scope)
-
-
- def _getnextfixturedef(self, argname):
- fixturedefs = self._arg2fixturedefs.get(argname, None)
- if fixturedefs is None:
- # we arrive here because of a a dynamic call to
- # getfuncargvalue(argname) usage which was naturally
- # not known at parsing/collection time
- fixturedefs = self._fixturemanager.getfixturedefs(
- argname, self._pyfuncitem.parent.nodeid)
- self._arg2fixturedefs[argname] = fixturedefs
- # fixturedefs list is immutable so we maintain a decreasing index
- index = self._arg2index.get(argname, 0) - 1
- if fixturedefs is None or (-index > len(fixturedefs)):
- raise FixtureLookupError(argname, self)
- self._arg2index[argname] = index
- return fixturedefs[index]
-
- @property
- def config(self):
- """ the pytest config object associated with this request. """
- return self._pyfuncitem.config
-
-
- @scopeproperty()
- def function(self):
- """ test function object if the request has a per-function scope. """
- return self._pyfuncitem.obj
-
- @scopeproperty("class")
- def cls(self):
- """ class (can be None) where the test function was collected. """
- clscol = self._pyfuncitem.getparent(pytest.Class)
- if clscol:
- return clscol.obj
-
- @property
- def instance(self):
- """ instance (can be None) on which test function was collected. """
- # unittest support hack, see _pytest.unittest.TestCaseFunction
- try:
- return self._pyfuncitem._testcase
- except AttributeError:
- function = getattr(self, "function", None)
- if function is not None:
- return py.builtin._getimself(function)
-
- @scopeproperty()
- def module(self):
- """ python module object where the test function was collected. """
- return self._pyfuncitem.getparent(pytest.Module).obj
-
- @scopeproperty()
- def fspath(self):
- """ the file system path of the test module which collected this test. """
- return self._pyfuncitem.fspath
-
- @property
- def keywords(self):
- """ keywords/markers dictionary for the underlying node. """
- return self.node.keywords
-
- @property
- def session(self):
- """ pytest session object. """
- return self._pyfuncitem.session
-
- def addfinalizer(self, finalizer):
- """ add finalizer/teardown function to be called after the
- last test within the requesting test context finished
- execution. """
- # XXX usually this method is shadowed by fixturedef specific ones
- self._addfinalizer(finalizer, scope=self.scope)
-
- def _addfinalizer(self, finalizer, scope):
- colitem = self._getscopeitem(scope)
- self._pyfuncitem.session._setupstate.addfinalizer(
- finalizer=finalizer, colitem=colitem)
-
- def applymarker(self, marker):
- """ Apply a marker to a single test function invocation.
- This method is useful if you don't want to have a keyword/marker
- on all function invocations.
-
- :arg marker: a :py:class:`_pytest.mark.MarkDecorator` object
- created by a call to ``pytest.mark.NAME(...)``.
- """
- try:
- self.node.keywords[marker.markname] = marker
- except AttributeError:
- raise ValueError(marker)
-
- def raiseerror(self, msg):
- """ raise a FixtureLookupError with the given message. """
- raise self._fixturemanager.FixtureLookupError(None, self, msg)
-
- def _fillfixtures(self):
- item = self._pyfuncitem
- fixturenames = getattr(item, "fixturenames", self.fixturenames)
- for argname in fixturenames:
- if argname not in item.funcargs:
- item.funcargs[argname] = self.getfuncargvalue(argname)
-
- def cached_setup(self, setup, teardown=None, scope="module", extrakey=None):
- """ (deprecated) Return a testing resource managed by ``setup`` &
- ``teardown`` calls. ``scope`` and ``extrakey`` determine when the
- ``teardown`` function will be called so that subsequent calls to
- ``setup`` would recreate the resource. With pytest-2.3 you often
- do not need ``cached_setup()`` as you can directly declare a scope
- on a fixture function and register a finalizer through
- ``request.addfinalizer()``.
-
- :arg teardown: function receiving a previously setup resource.
- :arg setup: a no-argument function creating a resource.
- :arg scope: a string value out of ``function``, ``class``, ``module``
- or ``session`` indicating the caching lifecycle of the resource.
- :arg extrakey: added to internal caching key of (funcargname, scope).
- """
- if not hasattr(self.config, '_setupcache'):
- self.config._setupcache = {} # XXX weakref?
- cachekey = (self.fixturename, self._getscopeitem(scope), extrakey)
- cache = self.config._setupcache
- try:
- val = cache[cachekey]
- except KeyError:
- self._check_scope(self.fixturename, self.scope, scope)
- val = setup()
- cache[cachekey] = val
- if teardown is not None:
- def finalizer():
- del cache[cachekey]
- teardown(val)
- self._addfinalizer(finalizer, scope=scope)
- return val
-
- def getfuncargvalue(self, argname):
- """ Dynamically retrieve a named fixture function argument.
-
- As of pytest-2.3, it is easier and usually better to access other
- fixture values by stating it as an input argument in the fixture
- function. If you only can decide about using another fixture at test
- setup time, you may use this function to retrieve it inside a fixture
- function body.
- """
- return self._get_active_fixturedef(argname).cached_result[0]
-
- def _get_active_fixturedef(self, argname):
- try:
- return self._fixturedefs[argname]
- except KeyError:
- try:
- fixturedef = self._getnextfixturedef(argname)
- except FixtureLookupError:
- if argname == "request":
- class PseudoFixtureDef:
- cached_result = (self, [0], None)
- scope = "function"
- return PseudoFixtureDef
- raise
- # remove indent to prevent the python3 exception
- # from leaking into the call
- result = self._getfuncargvalue(fixturedef)
- self._funcargs[argname] = result
- self._fixturedefs[argname] = fixturedef
- return fixturedef
-
- def _get_fixturestack(self):
- current = self
- l = []
- while 1:
- fixturedef = getattr(current, "_fixturedef", None)
- if fixturedef is None:
- l.reverse()
- return l
- l.append(fixturedef)
- current = current._parent_request
-
- def _getfuncargvalue(self, fixturedef):
- # prepare a subrequest object before calling fixture function
- # (latter managed by fixturedef)
- argname = fixturedef.argname
- funcitem = self._pyfuncitem
- scope = fixturedef.scope
- try:
- param = funcitem.callspec.getparam(argname)
- except (AttributeError, ValueError):
- param = NOTSET
- param_index = 0
- else:
- # indices might not be set if old-style metafunc.addcall() was used
- param_index = funcitem.callspec.indices.get(argname, 0)
- # if a parametrize invocation set a scope it will override
- # the static scope defined with the fixture function
- paramscopenum = funcitem.callspec._arg2scopenum.get(argname)
- if paramscopenum is not None:
- scope = scopes[paramscopenum]
-
- subrequest = SubRequest(self, scope, param, param_index, fixturedef)
-
- # check if a higher-level scoped fixture accesses a lower level one
- subrequest._check_scope(argname, self.scope, scope)
-
- # clear sys.exc_info before invoking the fixture (python bug?)
- # if its not explicitly cleared it will leak into the call
- exc_clear()
- try:
- # call the fixture function
- val = fixturedef.execute(request=subrequest)
- finally:
- # if fixture function failed it might have registered finalizers
- self.session._setupstate.addfinalizer(fixturedef.finish,
- subrequest.node)
- return val
-
- def _check_scope(self, argname, invoking_scope, requested_scope):
- if argname == "request":
- return
- if scopemismatch(invoking_scope, requested_scope):
- # try to report something helpful
- lines = self._factorytraceback()
- pytest.fail("ScopeMismatch: You tried to access the %r scoped "
- "fixture %r with a %r scoped request object, "
- "involved factories\n%s" %(
- (requested_scope, argname, invoking_scope, "\n".join(lines))),
- pytrace=False)
-
- def _factorytraceback(self):
- lines = []
- for fixturedef in self._get_fixturestack():
- factory = fixturedef.func
- fs, lineno = getfslineno(factory)
- p = self._pyfuncitem.session.fspath.bestrelpath(fs)
- args = _format_args(factory)
- lines.append("%s:%d: def %s%s" %(
- p, lineno, factory.__name__, args))
- return lines
-
- def _getscopeitem(self, scope):
- if scope == "function":
- # this might also be a non-function Item despite its attribute name
- return self._pyfuncitem
- node = get_scope_node(self._pyfuncitem, scope)
- if node is None and scope == "class":
- # fallback to function item itself
- node = self._pyfuncitem
- assert node
- return node
-
- def __repr__(self):
- return "<FixtureRequest for %r>" %(self.node)
-
-
-class SubRequest(FixtureRequest):
- """ a sub request for handling getting a fixture from a
- test function/fixture. """
- def __init__(self, request, scope, param, param_index, fixturedef):
- self._parent_request = request
- self.fixturename = fixturedef.argname
- if param is not NOTSET:
- self.param = param
- self.param_index = param_index
- self.scope = scope
- self._fixturedef = fixturedef
- self.addfinalizer = fixturedef.addfinalizer
- self._pyfuncitem = request._pyfuncitem
- self._funcargs = request._funcargs
- self._fixturedefs = request._fixturedefs
- self._arg2fixturedefs = request._arg2fixturedefs
- self._arg2index = request._arg2index
- self.fixturenames = request.fixturenames
- self._fixturemanager = request._fixturemanager
-
- def __repr__(self):
- return "<SubRequest %r for %r>" % (self.fixturename, self._pyfuncitem)
-
-
-class ScopeMismatchError(Exception):
- """ A fixture function tries to use a different fixture function which
- which has a lower scope (e.g. a Session one calls a function one)
- """
-
-scopes = "session module class function".split()
-scopenum_function = scopes.index("function")
-def scopemismatch(currentscope, newscope):
- return scopes.index(newscope) > scopes.index(currentscope)
-
-
-class FixtureLookupError(LookupError):
- """ could not return a requested Fixture (missing or invalid). """
- def __init__(self, argname, request, msg=None):
- self.argname = argname
- self.request = request
- self.fixturestack = request._get_fixturestack()
- self.msg = msg
-
- def formatrepr(self):
- tblines = []
- addline = tblines.append
- stack = [self.request._pyfuncitem.obj]
- stack.extend(map(lambda x: x.func, self.fixturestack))
- msg = self.msg
- if msg is not None:
- # the last fixture raise an error, let's present
- # it at the requesting side
- stack = stack[:-1]
- for function in stack:
- fspath, lineno = getfslineno(function)
- try:
- lines, _ = inspect.getsourcelines(get_real_func(function))
- except (IOError, IndexError):
- error_msg = "file %s, line %s: source code not available"
- addline(error_msg % (fspath, lineno+1))
- else:
- addline("file %s, line %s" % (fspath, lineno+1))
- for i, line in enumerate(lines):
- line = line.rstrip()
- addline(" " + line)
- if line.lstrip().startswith('def'):
- break
-
- if msg is None:
- fm = self.request._fixturemanager
- available = []
- for name, fixturedef in fm._arg2fixturedefs.items():
- parentid = self.request._pyfuncitem.parent.nodeid
- faclist = list(fm._matchfactories(fixturedef, parentid))
- if faclist:
- available.append(name)
- msg = "fixture %r not found" % (self.argname,)
- msg += "\n available fixtures: %s" %(", ".join(available),)
- msg += "\n use 'py.test --fixtures [testpath]' for help on them."
-
- return FixtureLookupErrorRepr(fspath, lineno, tblines, msg, self.argname)
-
-class FixtureLookupErrorRepr(TerminalRepr):
- def __init__(self, filename, firstlineno, tblines, errorstring, argname):
- self.tblines = tblines
- self.errorstring = errorstring
- self.filename = filename
- self.firstlineno = firstlineno
- self.argname = argname
-
- def toterminal(self, tw):
- #tw.line("FixtureLookupError: %s" %(self.argname), red=True)
- for tbline in self.tblines:
- tw.line(tbline.rstrip())
- for line in self.errorstring.split("\n"):
- tw.line(" " + line.strip(), red=True)
- tw.line()
- tw.line("%s:%d" % (self.filename, self.firstlineno+1))
-
-class FixtureManager:
- """
- pytest fixtures definitions and information is stored and managed
- from this class.
-
- During collection fm.parsefactories() is called multiple times to parse
- fixture function definitions into FixtureDef objects and internal
- data structures.
-
- During collection of test functions, metafunc-mechanics instantiate
- a FuncFixtureInfo object which is cached per node/func-name.
- This FuncFixtureInfo object is later retrieved by Function nodes
- which themselves offer a fixturenames attribute.
-
- The FuncFixtureInfo object holds information about fixtures and FixtureDefs
- relevant for a particular function. An initial list of fixtures is
- assembled like this:
-
- - ini-defined usefixtures
- - autouse-marked fixtures along the collection chain up from the function
- - usefixtures markers at module/class/function level
- - test function funcargs
-
- Subsequently the funcfixtureinfo.fixturenames attribute is computed
- as the closure of the fixtures needed to setup the initial fixtures,
- i. e. fixtures needed by fixture functions themselves are appended
- to the fixturenames list.
-
- Upon the test-setup phases all fixturenames are instantiated, retrieved
- by a lookup of their FuncFixtureInfo.
- """
-
- _argprefix = "pytest_funcarg__"
- FixtureLookupError = FixtureLookupError
- FixtureLookupErrorRepr = FixtureLookupErrorRepr
-
- def __init__(self, session):
- self.session = session
- self.config = session.config
- self._arg2fixturedefs = {}
- self._holderobjseen = set()
- self._arg2finish = {}
- self._nodeid_and_autousenames = [("", self.config.getini("usefixtures"))]
- session.config.pluginmanager.register(self, "funcmanage")
-
-
- def getfixtureinfo(self, node, func, cls, funcargs=True):
- if funcargs and not hasattr(node, "nofuncargs"):
- if cls is not None:
- startindex = 1
- else:
- startindex = None
- argnames = getfuncargnames(func, startindex)
- else:
- argnames = ()
- usefixtures = getattr(func, "usefixtures", None)
- initialnames = argnames
- if usefixtures is not None:
- initialnames = usefixtures.args + initialnames
- fm = node.session._fixturemanager
- names_closure, arg2fixturedefs = fm.getfixtureclosure(initialnames,
- node)
- return FuncFixtureInfo(argnames, names_closure, arg2fixturedefs)
-
- def pytest_plugin_registered(self, plugin):
- nodeid = None
- try:
- p = py.path.local(plugin.__file__)
- except AttributeError:
- pass
- else:
- # construct the base nodeid which is later used to check
- # what fixtures are visible for particular tests (as denoted
- # by their test id)
- if p.basename.startswith("conftest.py"):
- nodeid = p.dirpath().relto(self.config.rootdir)
- if p.sep != "/":
- nodeid = nodeid.replace(p.sep, "/")
- self.parsefactories(plugin, nodeid)
-
- def _getautousenames(self, nodeid):
- """ return a tuple of fixture names to be used. """
- autousenames = []
- for baseid, basenames in self._nodeid_and_autousenames:
- if nodeid.startswith(baseid):
- if baseid:
- i = len(baseid)
- nextchar = nodeid[i:i+1]
- if nextchar and nextchar not in ":/":
- continue
- autousenames.extend(basenames)
- # make sure autousenames are sorted by scope, scopenum 0 is session
- autousenames.sort(
- key=lambda x: self._arg2fixturedefs[x][-1].scopenum)
- return autousenames
-
- def getfixtureclosure(self, fixturenames, parentnode):
- # collect the closure of all fixtures , starting with the given
- # fixturenames as the initial set. As we have to visit all
- # factory definitions anyway, we also return a arg2fixturedefs
- # mapping so that the caller can reuse it and does not have
- # to re-discover fixturedefs again for each fixturename
- # (discovering matching fixtures for a given name/node is expensive)
-
- parentid = parentnode.nodeid
- fixturenames_closure = self._getautousenames(parentid)
- def merge(otherlist):
- for arg in otherlist:
- if arg not in fixturenames_closure:
- fixturenames_closure.append(arg)
- merge(fixturenames)
- arg2fixturedefs = {}
- lastlen = -1
- while lastlen != len(fixturenames_closure):
- lastlen = len(fixturenames_closure)
- for argname in fixturenames_closure:
- if argname in arg2fixturedefs:
- continue
- fixturedefs = self.getfixturedefs(argname, parentid)
- if fixturedefs:
- arg2fixturedefs[argname] = fixturedefs
- merge(fixturedefs[-1].argnames)
- return fixturenames_closure, arg2fixturedefs
-
- def pytest_generate_tests(self, metafunc):
- for argname in metafunc.fixturenames:
- faclist = metafunc._arg2fixturedefs.get(argname)
- if faclist:
- fixturedef = faclist[-1]
- if fixturedef.params is not None:
- func_params = getattr(getattr(metafunc.function, 'parametrize', None), 'args', [[None]])
- # skip directly parametrized arguments
- argnames = func_params[0]
- if not isinstance(argnames, (tuple, list)):
- argnames = [x.strip() for x in argnames.split(",") if x.strip()]
- if argname not in func_params and argname not in argnames:
- metafunc.parametrize(argname, fixturedef.params,
- indirect=True, scope=fixturedef.scope,
- ids=fixturedef.ids)
- else:
- continue # will raise FixtureLookupError at setup time
-
- def pytest_collection_modifyitems(self, items):
- # separate parametrized setups
- items[:] = reorder_items(items)
-
- def parsefactories(self, node_or_obj, nodeid=NOTSET, unittest=False):
- if nodeid is not NOTSET:
- holderobj = node_or_obj
- else:
- holderobj = node_or_obj.obj
- nodeid = node_or_obj.nodeid
- if holderobj in self._holderobjseen:
- return
- self._holderobjseen.add(holderobj)
- autousenames = []
- for name in dir(holderobj):
- obj = getattr(holderobj, name, None)
- # fixture functions have a pytest_funcarg__ prefix (pre-2.3 style)
- # or are "@pytest.fixture" marked
- marker = getfixturemarker(obj)
- if marker is None:
- if not name.startswith(self._argprefix):
- continue
- if not callable(obj):
- continue
- marker = defaultfuncargprefixmarker
- name = name[len(self._argprefix):]
- elif not isinstance(marker, FixtureFunctionMarker):
- # magic globals with __getattr__ might have got us a wrong
- # fixture attribute
- continue
- else:
- assert not name.startswith(self._argprefix)
- fixturedef = FixtureDef(self, nodeid, name, obj,
- marker.scope, marker.params,
- yieldctx=marker.yieldctx,
- unittest=unittest, ids=marker.ids)
- faclist = self._arg2fixturedefs.setdefault(name, [])
- if fixturedef.has_location:
- faclist.append(fixturedef)
- else:
- # fixturedefs with no location are at the front
- # so this inserts the current fixturedef after the
- # existing fixturedefs from external plugins but
- # before the fixturedefs provided in conftests.
- i = len([f for f in faclist if not f.has_location])
- faclist.insert(i, fixturedef)
- if marker.autouse:
- autousenames.append(name)
- if autousenames:
- self._nodeid_and_autousenames.append((nodeid or '', autousenames))
-
- def getfixturedefs(self, argname, nodeid):
- try:
- fixturedefs = self._arg2fixturedefs[argname]
- except KeyError:
- return None
- else:
- return tuple(self._matchfactories(fixturedefs, nodeid))
-
- def _matchfactories(self, fixturedefs, nodeid):
- for fixturedef in fixturedefs:
- if nodeid.startswith(fixturedef.baseid):
- yield fixturedef
-
-
-def fail_fixturefunc(fixturefunc, msg):
- fs, lineno = getfslineno(fixturefunc)
- location = "%s:%s" % (fs, lineno+1)
- source = _pytest._code.Source(fixturefunc)
- pytest.fail(msg + ":\n\n" + str(source.indent()) + "\n" + location,
- pytrace=False)
-
-def call_fixture_func(fixturefunc, request, kwargs, yieldctx):
- if yieldctx:
- if not is_generator(fixturefunc):
- fail_fixturefunc(fixturefunc,
- msg="yield_fixture requires yield statement in function")
- iter = fixturefunc(**kwargs)
- next = getattr(iter, "__next__", None)
- if next is None:
- next = getattr(iter, "next")
- res = next()
- def teardown():
- try:
- next()
- except StopIteration:
- pass
- else:
- fail_fixturefunc(fixturefunc,
- "yield_fixture function has more than one 'yield'")
- request.addfinalizer(teardown)
- else:
- if is_generator(fixturefunc):
- fail_fixturefunc(fixturefunc,
- msg="pytest.fixture functions cannot use ``yield``. "
- "Instead write and return an inner function/generator "
- "and let the consumer call and iterate over it.")
- res = fixturefunc(**kwargs)
- return res
-
-class FixtureDef:
- """ A container for a factory definition. """
- def __init__(self, fixturemanager, baseid, argname, func, scope, params,
- yieldctx, unittest=False, ids=None):
- self._fixturemanager = fixturemanager
- self.baseid = baseid or ''
- self.has_location = baseid is not None
- self.func = func
- self.argname = argname
- self.scope = scope
- self.scopenum = scopes.index(scope or "function")
- self.params = params
- startindex = unittest and 1 or None
- self.argnames = getfuncargnames(func, startindex=startindex)
- self.yieldctx = yieldctx
- self.unittest = unittest
- self.ids = ids
- self._finalizer = []
-
- def addfinalizer(self, finalizer):
- self._finalizer.append(finalizer)
-
- def finish(self):
- try:
- while self._finalizer:
- func = self._finalizer.pop()
- func()
- finally:
- # even if finalization fails, we invalidate
- # the cached fixture value
- if hasattr(self, "cached_result"):
- del self.cached_result
-
- def execute(self, request):
- # get required arguments and register our own finish()
- # with their finalization
- kwargs = {}
- for argname in self.argnames:
- fixturedef = request._get_active_fixturedef(argname)
- result, arg_cache_key, exc = fixturedef.cached_result
- request._check_scope(argname, request.scope, fixturedef.scope)
- kwargs[argname] = result
- if argname != "request":
- fixturedef.addfinalizer(self.finish)
-
- my_cache_key = request.param_index
- cached_result = getattr(self, "cached_result", None)
- if cached_result is not None:
- result, cache_key, err = cached_result
- if my_cache_key == cache_key:
- if err is not None:
- py.builtin._reraise(*err)
- else:
- return result
- # we have a previous but differently parametrized fixture instance
- # so we need to tear it down before creating a new one
- self.finish()
- assert not hasattr(self, "cached_result")
-
- fixturefunc = self.func
-
- if self.unittest:
- if request.instance is not None:
- # bind the unbound method to the TestCase instance
- fixturefunc = self.func.__get__(request.instance)
- else:
- # the fixture function needs to be bound to the actual
- # request.instance so that code working with "self" behaves
- # as expected.
- if request.instance is not None:
- fixturefunc = getimfunc(self.func)
- if fixturefunc != self.func:
- fixturefunc = fixturefunc.__get__(request.instance)
-
- try:
- result = call_fixture_func(fixturefunc, request, kwargs,
- self.yieldctx)
- except Exception:
- self.cached_result = (None, my_cache_key, sys.exc_info())
- raise
- self.cached_result = (result, my_cache_key, None)
- return result
-
- def __repr__(self):
- return ("<FixtureDef name=%r scope=%r baseid=%r >" %
- (self.argname, self.scope, self.baseid))
-
-def num_mock_patch_args(function):
- """ return number of arguments used up by mock arguments (if any) """
- patchings = getattr(function, "patchings", None)
- if not patchings:
- return 0
- mock = sys.modules.get("mock", sys.modules.get("unittest.mock", None))
- if mock is not None:
- return len([p for p in patchings
- if not p.attribute_name and p.new is mock.DEFAULT])
- return len(patchings)
-
-
-def getfuncargnames(function, startindex=None):
- # XXX merge with main.py's varnames
- #assert not isclass(function)
- realfunction = function
- while hasattr(realfunction, "__wrapped__"):
- realfunction = realfunction.__wrapped__
- if startindex is None:
- startindex = inspect.ismethod(function) and 1 or 0
- if realfunction != function:
- startindex += num_mock_patch_args(function)
- function = realfunction
- if isinstance(function, functools.partial):
- argnames = inspect.getargs(_pytest._code.getrawcode(function.func))[0]
- partial = function
- argnames = argnames[len(partial.args):]
- if partial.keywords:
- for kw in partial.keywords:
- argnames.remove(kw)
- else:
- argnames = inspect.getargs(_pytest._code.getrawcode(function))[0]
- defaults = getattr(function, 'func_defaults',
- getattr(function, '__defaults__', None)) or ()
- numdefaults = len(defaults)
- if numdefaults:
- return tuple(argnames[startindex:-numdefaults])
- return tuple(argnames[startindex:])
-
-# algorithm for sorting on a per-parametrized resource setup basis
-# it is called for scopenum==0 (session) first and performs sorting
-# down to the lower scopes such as to minimize number of "high scope"
-# setups and teardowns
-
-def reorder_items(items):
- argkeys_cache = {}
- for scopenum in range(0, scopenum_function):
- argkeys_cache[scopenum] = d = {}
- for item in items:
- keys = set(get_parametrized_fixture_keys(item, scopenum))
- if keys:
- d[item] = keys
- return reorder_items_atscope(items, set(), argkeys_cache, 0)
-
-def reorder_items_atscope(items, ignore, argkeys_cache, scopenum):
- if scopenum >= scopenum_function or len(items) < 3:
- return items
- items_done = []
- while 1:
- items_before, items_same, items_other, newignore = \
- slice_items(items, ignore, argkeys_cache[scopenum])
- items_before = reorder_items_atscope(
- items_before, ignore, argkeys_cache,scopenum+1)
- if items_same is None:
- # nothing to reorder in this scope
- assert items_other is None
- return items_done + items_before
- items_done.extend(items_before)
- items = items_same + items_other
- ignore = newignore
-
-
-def slice_items(items, ignore, scoped_argkeys_cache):
- # we pick the first item which uses a fixture instance in the
- # requested scope and which we haven't seen yet. We slice the input
- # items list into a list of items_nomatch, items_same and
- # items_other
- if scoped_argkeys_cache: # do we need to do work at all?
- it = iter(items)
- # first find a slicing key
- for i, item in enumerate(it):
- argkeys = scoped_argkeys_cache.get(item)
- if argkeys is not None:
- argkeys = argkeys.difference(ignore)
- if argkeys: # found a slicing key
- slicing_argkey = argkeys.pop()
- items_before = items[:i]
- items_same = [item]
- items_other = []
- # now slice the remainder of the list
- for item in it:
- argkeys = scoped_argkeys_cache.get(item)
- if argkeys and slicing_argkey in argkeys and \
- slicing_argkey not in ignore:
- items_same.append(item)
- else:
- items_other.append(item)
- newignore = ignore.copy()
- newignore.add(slicing_argkey)
- return (items_before, items_same, items_other, newignore)
- return items, None, None, None
-
-def get_parametrized_fixture_keys(item, scopenum):
- """ return list of keys for all parametrized arguments which match
- the specified scope. """
- assert scopenum < scopenum_function # function
- try:
- cs = item.callspec
- except AttributeError:
- pass
- else:
- # cs.indictes.items() is random order of argnames but
- # then again different functions (items) can change order of
- # arguments so it doesn't matter much probably
- for argname, param_index in cs.indices.items():
- if cs._arg2scopenum[argname] != scopenum:
- continue
- if scopenum == 0: # session
- key = (argname, param_index)
- elif scopenum == 1: # module
- key = (argname, param_index, item.fspath)
- elif scopenum == 2: # class
- key = (argname, param_index, item.fspath, item.cls)
- yield key
-
-
-def xunitsetup(obj, name):
- meth = getattr(obj, name, None)
- if getfixturemarker(meth) is None:
- return meth
-
-def getfixturemarker(obj):
- """ return fixturemarker or None if it doesn't exist or raised
- exceptions."""
- try:
- return getattr(obj, "_pytestfixturefunction", None)
- except KeyboardInterrupt:
- raise
- except Exception:
- # some objects raise errors like request (from flask import request)
- # we don't expect them to be fixture functions
- return None
-
-scopename2class = {
- 'class': Class,
- 'module': Module,
- 'function': pytest.Item,
-}
-def get_scope_node(node, scope):
- cls = scopename2class.get(scope)
- if cls is None:
- if scope == "session":
- return node.session
- raise ValueError("unknown scope")
- return node.getparent(cls)
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/recwarn.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/recwarn.py
deleted file mode 100644
index a89474c036a..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/recwarn.py
+++ /dev/null
@@ -1,221 +0,0 @@
-""" recording warnings during test function execution. """
-
-import inspect
-
-import _pytest._code
-import py
-import sys
-import warnings
-import pytest
-
-
-@pytest.yield_fixture
-def recwarn(request):
- """Return a WarningsRecorder instance that provides these methods:
-
- * ``pop(category=None)``: return last warning matching the category.
- * ``clear()``: clear list of warnings
-
- See http://docs.python.org/library/warnings.html for information
- on warning categories.
- """
- wrec = WarningsRecorder()
- with wrec:
- warnings.simplefilter('default')
- yield wrec
-
-
-def pytest_namespace():
- return {'deprecated_call': deprecated_call,
- 'warns': warns}
-
-
-def deprecated_call(func=None, *args, **kwargs):
- """ assert that calling ``func(*args, **kwargs)`` triggers a
- ``DeprecationWarning`` or ``PendingDeprecationWarning``.
-
- This function can be used as a context manager::
-
- >>> with deprecated_call():
- ... myobject.deprecated_method()
-
- Note: we cannot use WarningsRecorder here because it is still subject
- to the mechanism that prevents warnings of the same type from being
- triggered twice for the same module. See #1190.
- """
- if not func:
- return WarningsChecker(expected_warning=DeprecationWarning)
-
- categories = []
-
- def warn_explicit(message, category, *args, **kwargs):
- categories.append(category)
- old_warn_explicit(message, category, *args, **kwargs)
-
- def warn(message, category=None, *args, **kwargs):
- if isinstance(message, Warning):
- categories.append(message.__class__)
- else:
- categories.append(category)
- old_warn(message, category, *args, **kwargs)
-
- old_warn = warnings.warn
- old_warn_explicit = warnings.warn_explicit
- warnings.warn_explicit = warn_explicit
- warnings.warn = warn
- try:
- ret = func(*args, **kwargs)
- finally:
- warnings.warn_explicit = old_warn_explicit
- warnings.warn = old_warn
- deprecation_categories = (DeprecationWarning, PendingDeprecationWarning)
- if not any(issubclass(c, deprecation_categories) for c in categories):
- __tracebackhide__ = True
- raise AssertionError("%r did not produce DeprecationWarning" % (func,))
- return ret
-
-
-def warns(expected_warning, *args, **kwargs):
- """Assert that code raises a particular class of warning.
-
- Specifically, the input @expected_warning can be a warning class or
- tuple of warning classes, and the code must return that warning
- (if a single class) or one of those warnings (if a tuple).
-
- This helper produces a list of ``warnings.WarningMessage`` objects,
- one for each warning raised.
-
- This function can be used as a context manager, or any of the other ways
- ``pytest.raises`` can be used::
-
- >>> with warns(RuntimeWarning):
- ... warnings.warn("my warning", RuntimeWarning)
- """
- wcheck = WarningsChecker(expected_warning)
- if not args:
- return wcheck
- elif isinstance(args[0], str):
- code, = args
- assert isinstance(code, str)
- frame = sys._getframe(1)
- loc = frame.f_locals.copy()
- loc.update(kwargs)
-
- with wcheck:
- code = _pytest._code.Source(code).compile()
- py.builtin.exec_(code, frame.f_globals, loc)
- else:
- func = args[0]
- with wcheck:
- return func(*args[1:], **kwargs)
-
-
-class RecordedWarning(object):
- def __init__(self, message, category, filename, lineno, file, line):
- self.message = message
- self.category = category
- self.filename = filename
- self.lineno = lineno
- self.file = file
- self.line = line
-
-
-class WarningsRecorder(object):
- """A context manager to record raised warnings.
-
- Adapted from `warnings.catch_warnings`.
- """
-
- def __init__(self, module=None):
- self._module = sys.modules['warnings'] if module is None else module
- self._entered = False
- self._list = []
-
- @property
- def list(self):
- """The list of recorded warnings."""
- return self._list
-
- def __getitem__(self, i):
- """Get a recorded warning by index."""
- return self._list[i]
-
- def __iter__(self):
- """Iterate through the recorded warnings."""
- return iter(self._list)
-
- def __len__(self):
- """The number of recorded warnings."""
- return len(self._list)
-
- def pop(self, cls=Warning):
- """Pop the first recorded warning, raise exception if not exists."""
- for i, w in enumerate(self._list):
- if issubclass(w.category, cls):
- return self._list.pop(i)
- __tracebackhide__ = True
- raise AssertionError("%r not found in warning list" % cls)
-
- def clear(self):
- """Clear the list of recorded warnings."""
- self._list[:] = []
-
- def __enter__(self):
- if self._entered:
- __tracebackhide__ = True
- raise RuntimeError("Cannot enter %r twice" % self)
- self._entered = True
- self._filters = self._module.filters
- self._module.filters = self._filters[:]
- self._showwarning = self._module.showwarning
-
- def showwarning(message, category, filename, lineno,
- file=None, line=None):
- self._list.append(RecordedWarning(
- message, category, filename, lineno, file, line))
-
- # still perform old showwarning functionality
- self._showwarning(
- message, category, filename, lineno, file=file, line=line)
-
- self._module.showwarning = showwarning
-
- # allow the same warning to be raised more than once
-
- self._module.simplefilter('always')
- return self
-
- def __exit__(self, *exc_info):
- if not self._entered:
- __tracebackhide__ = True
- raise RuntimeError("Cannot exit %r without entering first" % self)
- self._module.filters = self._filters
- self._module.showwarning = self._showwarning
-
-
-class WarningsChecker(WarningsRecorder):
- def __init__(self, expected_warning=None, module=None):
- super(WarningsChecker, self).__init__(module=module)
-
- msg = ("exceptions must be old-style classes or "
- "derived from Warning, not %s")
- if isinstance(expected_warning, tuple):
- for exc in expected_warning:
- if not inspect.isclass(exc):
- raise TypeError(msg % type(exc))
- elif inspect.isclass(expected_warning):
- expected_warning = (expected_warning,)
- elif expected_warning is not None:
- raise TypeError(msg % type(expected_warning))
-
- self.expected_warning = expected_warning
-
- def __exit__(self, *exc_info):
- super(WarningsChecker, self).__exit__(*exc_info)
-
- # only check if we're not currently handling an exception
- if all(a is None for a in exc_info):
- if self.expected_warning is not None:
- if not any(r.category in self.expected_warning for r in self):
- __tracebackhide__ = True
- pytest.fail("DID NOT WARN")
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/resultlog.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/resultlog.py
deleted file mode 100644
index 3670f0214c9..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/resultlog.py
+++ /dev/null
@@ -1,104 +0,0 @@
-""" log machine-parseable test session result information in a plain
-text file.
-"""
-
-import py
-import os
-
-def pytest_addoption(parser):
- group = parser.getgroup("terminal reporting", "resultlog plugin options")
- group.addoption('--resultlog', '--result-log', action="store",
- metavar="path", default=None,
- help="path for machine-readable result log.")
-
-def pytest_configure(config):
- resultlog = config.option.resultlog
- # prevent opening resultlog on slave nodes (xdist)
- if resultlog and not hasattr(config, 'slaveinput'):
- dirname = os.path.dirname(os.path.abspath(resultlog))
- if not os.path.isdir(dirname):
- os.makedirs(dirname)
- logfile = open(resultlog, 'w', 1) # line buffered
- config._resultlog = ResultLog(config, logfile)
- config.pluginmanager.register(config._resultlog)
-
-def pytest_unconfigure(config):
- resultlog = getattr(config, '_resultlog', None)
- if resultlog:
- resultlog.logfile.close()
- del config._resultlog
- config.pluginmanager.unregister(resultlog)
-
-def generic_path(item):
- chain = item.listchain()
- gpath = [chain[0].name]
- fspath = chain[0].fspath
- fspart = False
- for node in chain[1:]:
- newfspath = node.fspath
- if newfspath == fspath:
- if fspart:
- gpath.append(':')
- fspart = False
- else:
- gpath.append('.')
- else:
- gpath.append('/')
- fspart = True
- name = node.name
- if name[0] in '([':
- gpath.pop()
- gpath.append(name)
- fspath = newfspath
- return ''.join(gpath)
-
-class ResultLog(object):
- def __init__(self, config, logfile):
- self.config = config
- self.logfile = logfile # preferably line buffered
-
- def write_log_entry(self, testpath, lettercode, longrepr):
- py.builtin.print_("%s %s" % (lettercode, testpath), file=self.logfile)
- for line in longrepr.splitlines():
- py.builtin.print_(" %s" % line, file=self.logfile)
-
- def log_outcome(self, report, lettercode, longrepr):
- testpath = getattr(report, 'nodeid', None)
- if testpath is None:
- testpath = report.fspath
- self.write_log_entry(testpath, lettercode, longrepr)
-
- def pytest_runtest_logreport(self, report):
- if report.when != "call" and report.passed:
- return
- res = self.config.hook.pytest_report_teststatus(report=report)
- code = res[1]
- if code == 'x':
- longrepr = str(report.longrepr)
- elif code == 'X':
- longrepr = ''
- elif report.passed:
- longrepr = ""
- elif report.failed:
- longrepr = str(report.longrepr)
- elif report.skipped:
- longrepr = str(report.longrepr[2])
- self.log_outcome(report, code, longrepr)
-
- def pytest_collectreport(self, report):
- if not report.passed:
- if report.failed:
- code = "F"
- longrepr = str(report.longrepr)
- else:
- assert report.skipped
- code = "S"
- longrepr = "%s:%d: %s" % report.longrepr
- self.log_outcome(report, code, longrepr)
-
- def pytest_internalerror(self, excrepr):
- reprcrash = getattr(excrepr, 'reprcrash', None)
- path = getattr(reprcrash, "path", None)
- if path is None:
- path = "cwd:%s" % py.path.local()
- self.write_log_entry(path, '!', str(excrepr))
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/runner.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/runner.py
deleted file mode 100644
index cde94c8c89e..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/runner.py
+++ /dev/null
@@ -1,515 +0,0 @@
-""" basic collect and runtest protocol implementations """
-import bdb
-import sys
-from time import time
-
-import py
-import pytest
-from _pytest._code.code import TerminalRepr, ExceptionInfo
-
-
-def pytest_namespace():
- return {
- 'fail' : fail,
- 'skip' : skip,
- 'importorskip' : importorskip,
- 'exit' : exit,
- }
-
-#
-# pytest plugin hooks
-
-def pytest_addoption(parser):
- group = parser.getgroup("terminal reporting", "reporting", after="general")
- group.addoption('--durations',
- action="store", type=int, default=None, metavar="N",
- help="show N slowest setup/test durations (N=0 for all)."),
-
-def pytest_terminal_summary(terminalreporter):
- durations = terminalreporter.config.option.durations
- if durations is None:
- return
- tr = terminalreporter
- dlist = []
- for replist in tr.stats.values():
- for rep in replist:
- if hasattr(rep, 'duration'):
- dlist.append(rep)
- if not dlist:
- return
- dlist.sort(key=lambda x: x.duration)
- dlist.reverse()
- if not durations:
- tr.write_sep("=", "slowest test durations")
- else:
- tr.write_sep("=", "slowest %s test durations" % durations)
- dlist = dlist[:durations]
-
- for rep in dlist:
- nodeid = rep.nodeid.replace("::()::", "::")
- tr.write_line("%02.2fs %-8s %s" %
- (rep.duration, rep.when, nodeid))
-
-def pytest_sessionstart(session):
- session._setupstate = SetupState()
-def pytest_sessionfinish(session):
- session._setupstate.teardown_all()
-
-class NodeInfo:
- def __init__(self, location):
- self.location = location
-
-def pytest_runtest_protocol(item, nextitem):
- item.ihook.pytest_runtest_logstart(
- nodeid=item.nodeid, location=item.location,
- )
- runtestprotocol(item, nextitem=nextitem)
- return True
-
-def runtestprotocol(item, log=True, nextitem=None):
- hasrequest = hasattr(item, "_request")
- if hasrequest and not item._request:
- item._initrequest()
- rep = call_and_report(item, "setup", log)
- reports = [rep]
- if rep.passed:
- reports.append(call_and_report(item, "call", log))
- reports.append(call_and_report(item, "teardown", log,
- nextitem=nextitem))
- # after all teardown hooks have been called
- # want funcargs and request info to go away
- if hasrequest:
- item._request = False
- item.funcargs = None
- return reports
-
-def pytest_runtest_setup(item):
- item.session._setupstate.prepare(item)
-
-def pytest_runtest_call(item):
- try:
- item.runtest()
- except Exception:
- # Store trace info to allow postmortem debugging
- type, value, tb = sys.exc_info()
- tb = tb.tb_next # Skip *this* frame
- sys.last_type = type
- sys.last_value = value
- sys.last_traceback = tb
- del tb # Get rid of it in this namespace
- raise
-
-def pytest_runtest_teardown(item, nextitem):
- item.session._setupstate.teardown_exact(item, nextitem)
-
-def pytest_report_teststatus(report):
- if report.when in ("setup", "teardown"):
- if report.failed:
- # category, shortletter, verbose-word
- return "error", "E", "ERROR"
- elif report.skipped:
- return "skipped", "s", "SKIPPED"
- else:
- return "", "", ""
-
-
-#
-# Implementation
-
-def call_and_report(item, when, log=True, **kwds):
- call = call_runtest_hook(item, when, **kwds)
- hook = item.ihook
- report = hook.pytest_runtest_makereport(item=item, call=call)
- if log:
- hook.pytest_runtest_logreport(report=report)
- if check_interactive_exception(call, report):
- hook.pytest_exception_interact(node=item, call=call, report=report)
- return report
-
-def check_interactive_exception(call, report):
- return call.excinfo and not (
- hasattr(report, "wasxfail") or
- call.excinfo.errisinstance(skip.Exception) or
- call.excinfo.errisinstance(bdb.BdbQuit))
-
-def call_runtest_hook(item, when, **kwds):
- hookname = "pytest_runtest_" + when
- ihook = getattr(item.ihook, hookname)
- return CallInfo(lambda: ihook(item=item, **kwds), when=when)
-
-class CallInfo:
- """ Result/Exception info a function invocation. """
- #: None or ExceptionInfo object.
- excinfo = None
- def __init__(self, func, when):
- #: context of invocation: one of "setup", "call",
- #: "teardown", "memocollect"
- self.when = when
- self.start = time()
- try:
- self.result = func()
- except KeyboardInterrupt:
- self.stop = time()
- raise
- except:
- self.excinfo = ExceptionInfo()
- self.stop = time()
-
- def __repr__(self):
- if self.excinfo:
- status = "exception: %s" % str(self.excinfo.value)
- else:
- status = "result: %r" % (self.result,)
- return "<CallInfo when=%r %s>" % (self.when, status)
-
-def getslaveinfoline(node):
- try:
- return node._slaveinfocache
- except AttributeError:
- d = node.slaveinfo
- ver = "%s.%s.%s" % d['version_info'][:3]
- node._slaveinfocache = s = "[%s] %s -- Python %s %s" % (
- d['id'], d['sysplatform'], ver, d['executable'])
- return s
-
-class BaseReport(object):
-
- def __init__(self, **kw):
- self.__dict__.update(kw)
-
- def toterminal(self, out):
- if hasattr(self, 'node'):
- out.line(getslaveinfoline(self.node))
-
- longrepr = self.longrepr
- if longrepr is None:
- return
-
- if hasattr(longrepr, 'toterminal'):
- longrepr.toterminal(out)
- else:
- try:
- out.line(longrepr)
- except UnicodeEncodeError:
- out.line("<unprintable longrepr>")
-
- def get_sections(self, prefix):
- for name, content in self.sections:
- if name.startswith(prefix):
- yield prefix, content
-
- passed = property(lambda x: x.outcome == "passed")
- failed = property(lambda x: x.outcome == "failed")
- skipped = property(lambda x: x.outcome == "skipped")
-
- @property
- def fspath(self):
- return self.nodeid.split("::")[0]
-
-def pytest_runtest_makereport(item, call):
- when = call.when
- duration = call.stop-call.start
- keywords = dict([(x,1) for x in item.keywords])
- excinfo = call.excinfo
- sections = []
- if not call.excinfo:
- outcome = "passed"
- longrepr = None
- else:
- if not isinstance(excinfo, ExceptionInfo):
- outcome = "failed"
- longrepr = excinfo
- elif excinfo.errisinstance(pytest.skip.Exception):
- outcome = "skipped"
- r = excinfo._getreprcrash()
- longrepr = (str(r.path), r.lineno, r.message)
- else:
- outcome = "failed"
- if call.when == "call":
- longrepr = item.repr_failure(excinfo)
- else: # exception in setup or teardown
- longrepr = item._repr_failure_py(excinfo,
- style=item.config.option.tbstyle)
- for rwhen, key, content in item._report_sections:
- sections.append(("Captured %s %s" %(key, rwhen), content))
- return TestReport(item.nodeid, item.location,
- keywords, outcome, longrepr, when,
- sections, duration)
-
-class TestReport(BaseReport):
- """ Basic test report object (also used for setup and teardown calls if
- they fail).
- """
- def __init__(self, nodeid, location, keywords, outcome,
- longrepr, when, sections=(), duration=0, **extra):
- #: normalized collection node id
- self.nodeid = nodeid
-
- #: a (filesystempath, lineno, domaininfo) tuple indicating the
- #: actual location of a test item - it might be different from the
- #: collected one e.g. if a method is inherited from a different module.
- self.location = location
-
- #: a name -> value dictionary containing all keywords and
- #: markers associated with a test invocation.
- self.keywords = keywords
-
- #: test outcome, always one of "passed", "failed", "skipped".
- self.outcome = outcome
-
- #: None or a failure representation.
- self.longrepr = longrepr
-
- #: one of 'setup', 'call', 'teardown' to indicate runtest phase.
- self.when = when
-
- #: list of (secname, data) extra information which needs to
- #: marshallable
- self.sections = list(sections)
-
- #: time it took to run just the test
- self.duration = duration
-
- self.__dict__.update(extra)
-
- def __repr__(self):
- return "<TestReport %r when=%r outcome=%r>" % (
- self.nodeid, self.when, self.outcome)
-
-class TeardownErrorReport(BaseReport):
- outcome = "failed"
- when = "teardown"
- def __init__(self, longrepr, **extra):
- self.longrepr = longrepr
- self.sections = []
- self.__dict__.update(extra)
-
-def pytest_make_collect_report(collector):
- call = CallInfo(collector._memocollect, "memocollect")
- longrepr = None
- if not call.excinfo:
- outcome = "passed"
- else:
- from _pytest import nose
- skip_exceptions = (Skipped,) + nose.get_skip_exceptions()
- if call.excinfo.errisinstance(skip_exceptions):
- outcome = "skipped"
- r = collector._repr_failure_py(call.excinfo, "line").reprcrash
- longrepr = (str(r.path), r.lineno, r.message)
- else:
- outcome = "failed"
- errorinfo = collector.repr_failure(call.excinfo)
- if not hasattr(errorinfo, "toterminal"):
- errorinfo = CollectErrorRepr(errorinfo)
- longrepr = errorinfo
- rep = CollectReport(collector.nodeid, outcome, longrepr,
- getattr(call, 'result', None))
- rep.call = call # see collect_one_node
- return rep
-
-
-class CollectReport(BaseReport):
- def __init__(self, nodeid, outcome, longrepr, result,
- sections=(), **extra):
- self.nodeid = nodeid
- self.outcome = outcome
- self.longrepr = longrepr
- self.result = result or []
- self.sections = list(sections)
- self.__dict__.update(extra)
-
- @property
- def location(self):
- return (self.fspath, None, self.fspath)
-
- def __repr__(self):
- return "<CollectReport %r lenresult=%s outcome=%r>" % (
- self.nodeid, len(self.result), self.outcome)
-
-class CollectErrorRepr(TerminalRepr):
- def __init__(self, msg):
- self.longrepr = msg
- def toterminal(self, out):
- out.line(self.longrepr, red=True)
-
-class SetupState(object):
- """ shared state for setting up/tearing down test items or collectors. """
- def __init__(self):
- self.stack = []
- self._finalizers = {}
-
- def addfinalizer(self, finalizer, colitem):
- """ attach a finalizer to the given colitem.
- if colitem is None, this will add a finalizer that
- is called at the end of teardown_all().
- """
- assert colitem and not isinstance(colitem, tuple)
- assert py.builtin.callable(finalizer)
- #assert colitem in self.stack # some unit tests don't setup stack :/
- self._finalizers.setdefault(colitem, []).append(finalizer)
-
- def _pop_and_teardown(self):
- colitem = self.stack.pop()
- self._teardown_with_finalization(colitem)
-
- def _callfinalizers(self, colitem):
- finalizers = self._finalizers.pop(colitem, None)
- exc = None
- while finalizers:
- fin = finalizers.pop()
- try:
- fin()
- except Exception:
- # XXX Only first exception will be seen by user,
- # ideally all should be reported.
- if exc is None:
- exc = sys.exc_info()
- if exc:
- py.builtin._reraise(*exc)
-
- def _teardown_with_finalization(self, colitem):
- self._callfinalizers(colitem)
- if hasattr(colitem, "teardown"):
- colitem.teardown()
- for colitem in self._finalizers:
- assert colitem is None or colitem in self.stack \
- or isinstance(colitem, tuple)
-
- def teardown_all(self):
- while self.stack:
- self._pop_and_teardown()
- for key in list(self._finalizers):
- self._teardown_with_finalization(key)
- assert not self._finalizers
-
- def teardown_exact(self, item, nextitem):
- needed_collectors = nextitem and nextitem.listchain() or []
- self._teardown_towards(needed_collectors)
-
- def _teardown_towards(self, needed_collectors):
- while self.stack:
- if self.stack == needed_collectors[:len(self.stack)]:
- break
- self._pop_and_teardown()
-
- def prepare(self, colitem):
- """ setup objects along the collector chain to the test-method
- and teardown previously setup objects."""
- needed_collectors = colitem.listchain()
- self._teardown_towards(needed_collectors)
-
- # check if the last collection node has raised an error
- for col in self.stack:
- if hasattr(col, '_prepare_exc'):
- py.builtin._reraise(*col._prepare_exc)
- for col in needed_collectors[len(self.stack):]:
- self.stack.append(col)
- try:
- col.setup()
- except Exception:
- col._prepare_exc = sys.exc_info()
- raise
-
-def collect_one_node(collector):
- ihook = collector.ihook
- ihook.pytest_collectstart(collector=collector)
- rep = ihook.pytest_make_collect_report(collector=collector)
- call = rep.__dict__.pop("call", None)
- if call and check_interactive_exception(call, rep):
- ihook.pytest_exception_interact(node=collector, call=call, report=rep)
- return rep
-
-
-# =============================================================
-# Test OutcomeExceptions and helpers for creating them.
-
-
-class OutcomeException(Exception):
- """ OutcomeException and its subclass instances indicate and
- contain info about test and collection outcomes.
- """
- def __init__(self, msg=None, pytrace=True):
- Exception.__init__(self, msg)
- self.msg = msg
- self.pytrace = pytrace
-
- def __repr__(self):
- if self.msg:
- val = self.msg
- if isinstance(val, bytes):
- val = py._builtin._totext(val, errors='replace')
- return val
- return "<%s instance>" %(self.__class__.__name__,)
- __str__ = __repr__
-
-class Skipped(OutcomeException):
- # XXX hackish: on 3k we fake to live in the builtins
- # in order to have Skipped exception printing shorter/nicer
- __module__ = 'builtins'
-
-class Failed(OutcomeException):
- """ raised from an explicit call to pytest.fail() """
- __module__ = 'builtins'
-
-class Exit(KeyboardInterrupt):
- """ raised for immediate program exits (no tracebacks/summaries)"""
- def __init__(self, msg="unknown reason"):
- self.msg = msg
- KeyboardInterrupt.__init__(self, msg)
-
-# exposed helper methods
-
-def exit(msg):
- """ exit testing process as if KeyboardInterrupt was triggered. """
- __tracebackhide__ = True
- raise Exit(msg)
-
-exit.Exception = Exit
-
-def skip(msg=""):
- """ skip an executing test with the given message. Note: it's usually
- better to use the pytest.mark.skipif marker to declare a test to be
- skipped under certain conditions like mismatching platforms or
- dependencies. See the pytest_skipping plugin for details.
- """
- __tracebackhide__ = True
- raise Skipped(msg=msg)
-skip.Exception = Skipped
-
-def fail(msg="", pytrace=True):
- """ explicitly fail an currently-executing test with the given Message.
-
- :arg pytrace: if false the msg represents the full failure information
- and no python traceback will be reported.
- """
- __tracebackhide__ = True
- raise Failed(msg=msg, pytrace=pytrace)
-fail.Exception = Failed
-
-
-def importorskip(modname, minversion=None):
- """ return imported module if it has at least "minversion" as its
- __version__ attribute. If no minversion is specified the a skip
- is only triggered if the module can not be imported.
- """
- __tracebackhide__ = True
- compile(modname, '', 'eval') # to catch syntaxerrors
- try:
- __import__(modname)
- except ImportError:
- skip("could not import %r" %(modname,))
- mod = sys.modules[modname]
- if minversion is None:
- return mod
- verattr = getattr(mod, '__version__', None)
- if minversion is not None:
- try:
- from pkg_resources import parse_version as pv
- except ImportError:
- skip("we have a required version for %r but can not import "
- "no pkg_resources to parse version strings." %(modname,))
- if verattr is None or pv(verattr) < pv(minversion):
- skip("module %r has __version__ %r, required is: %r" %(
- modname, verattr, minversion))
- return mod
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/skipping.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/skipping.py
deleted file mode 100644
index 69157f485a0..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/skipping.py
+++ /dev/null
@@ -1,354 +0,0 @@
-""" support for skip/xfail functions and markers. """
-import os
-import sys
-import traceback
-
-import py
-import pytest
-from _pytest.mark import MarkInfo, MarkDecorator
-
-
-def pytest_addoption(parser):
- group = parser.getgroup("general")
- group.addoption('--runxfail',
- action="store_true", dest="runxfail", default=False,
- help="run tests even if they are marked xfail")
-
- parser.addini("xfail_strict", "default for the strict parameter of xfail "
- "markers when not given explicitly (default: "
- "False)",
- default=False,
- type="bool")
-
-
-def pytest_configure(config):
- if config.option.runxfail:
- old = pytest.xfail
- config._cleanup.append(lambda: setattr(pytest, "xfail", old))
- def nop(*args, **kwargs):
- pass
- nop.Exception = XFailed
- setattr(pytest, "xfail", nop)
-
- config.addinivalue_line("markers",
- "skipif(condition): skip the given test function if eval(condition) "
- "results in a True value. Evaluation happens within the "
- "module global context. Example: skipif('sys.platform == \"win32\"') "
- "skips the test if we are on the win32 platform. see "
- "http://pytest.org/latest/skipping.html"
- )
- config.addinivalue_line("markers",
- "xfail(condition, reason=None, run=True, raises=None): mark the the test function "
- "as an expected failure if eval(condition) has a True value. "
- "Optionally specify a reason for better reporting and run=False if "
- "you don't even want to execute the test function. If only specific "
- "exception(s) are expected, you can list them in raises, and if the test fails "
- "in other ways, it will be reported as a true failure. "
- "See http://pytest.org/latest/skipping.html"
- )
-
-
-def pytest_namespace():
- return dict(xfail=xfail)
-
-
-class XFailed(pytest.fail.Exception):
- """ raised from an explicit call to pytest.xfail() """
-
-
-def xfail(reason=""):
- """ xfail an executing test or setup functions with the given reason."""
- __tracebackhide__ = True
- raise XFailed(reason)
-xfail.Exception = XFailed
-
-
-class MarkEvaluator:
- def __init__(self, item, name):
- self.item = item
- self.name = name
-
- @property
- def holder(self):
- return self.item.keywords.get(self.name)
-
- def __bool__(self):
- return bool(self.holder)
- __nonzero__ = __bool__
-
- def wasvalid(self):
- return not hasattr(self, 'exc')
-
- def invalidraise(self, exc):
- raises = self.get('raises')
- if not raises:
- return
- return not isinstance(exc, raises)
-
- def istrue(self):
- try:
- return self._istrue()
- except Exception:
- self.exc = sys.exc_info()
- if isinstance(self.exc[1], SyntaxError):
- msg = [" " * (self.exc[1].offset + 4) + "^",]
- msg.append("SyntaxError: invalid syntax")
- else:
- msg = traceback.format_exception_only(*self.exc[:2])
- pytest.fail("Error evaluating %r expression\n"
- " %s\n"
- "%s"
- %(self.name, self.expr, "\n".join(msg)),
- pytrace=False)
-
- def _getglobals(self):
- d = {'os': os, 'sys': sys, 'config': self.item.config}
- func = self.item.obj
- try:
- d.update(func.__globals__)
- except AttributeError:
- d.update(func.func_globals)
- return d
-
- def _istrue(self):
- if hasattr(self, 'result'):
- return self.result
- if self.holder:
- d = self._getglobals()
- if self.holder.args:
- self.result = False
- # "holder" might be a MarkInfo or a MarkDecorator; only
- # MarkInfo keeps track of all parameters it received in an
- # _arglist attribute
- if hasattr(self.holder, '_arglist'):
- arglist = self.holder._arglist
- else:
- arglist = [(self.holder.args, self.holder.kwargs)]
- for args, kwargs in arglist:
- for expr in args:
- self.expr = expr
- if isinstance(expr, py.builtin._basestring):
- result = cached_eval(self.item.config, expr, d)
- else:
- if "reason" not in kwargs:
- # XXX better be checked at collection time
- msg = "you need to specify reason=STRING " \
- "when using booleans as conditions."
- pytest.fail(msg)
- result = bool(expr)
- if result:
- self.result = True
- self.reason = kwargs.get('reason', None)
- self.expr = expr
- return self.result
- else:
- self.result = True
- return getattr(self, 'result', False)
-
- def get(self, attr, default=None):
- return self.holder.kwargs.get(attr, default)
-
- def getexplanation(self):
- expl = getattr(self, 'reason', None) or self.get('reason', None)
- if not expl:
- if not hasattr(self, 'expr'):
- return ""
- else:
- return "condition: " + str(self.expr)
- return expl
-
-
-@pytest.hookimpl(tryfirst=True)
-def pytest_runtest_setup(item):
- # Check if skip or skipif are specified as pytest marks
-
- skipif_info = item.keywords.get('skipif')
- if isinstance(skipif_info, (MarkInfo, MarkDecorator)):
- eval_skipif = MarkEvaluator(item, 'skipif')
- if eval_skipif.istrue():
- item._evalskip = eval_skipif
- pytest.skip(eval_skipif.getexplanation())
-
- skip_info = item.keywords.get('skip')
- if isinstance(skip_info, (MarkInfo, MarkDecorator)):
- item._evalskip = True
- if 'reason' in skip_info.kwargs:
- pytest.skip(skip_info.kwargs['reason'])
- elif skip_info.args:
- pytest.skip(skip_info.args[0])
- else:
- pytest.skip("unconditional skip")
-
- item._evalxfail = MarkEvaluator(item, 'xfail')
- check_xfail_no_run(item)
-
-
-@pytest.mark.hookwrapper
-def pytest_pyfunc_call(pyfuncitem):
- check_xfail_no_run(pyfuncitem)
- outcome = yield
- passed = outcome.excinfo is None
- if passed:
- check_strict_xfail(pyfuncitem)
-
-
-def check_xfail_no_run(item):
- """check xfail(run=False)"""
- if not item.config.option.runxfail:
- evalxfail = item._evalxfail
- if evalxfail.istrue():
- if not evalxfail.get('run', True):
- pytest.xfail("[NOTRUN] " + evalxfail.getexplanation())
-
-
-def check_strict_xfail(pyfuncitem):
- """check xfail(strict=True) for the given PASSING test"""
- evalxfail = pyfuncitem._evalxfail
- if evalxfail.istrue():
- strict_default = pyfuncitem.config.getini('xfail_strict')
- is_strict_xfail = evalxfail.get('strict', strict_default)
- if is_strict_xfail:
- del pyfuncitem._evalxfail
- explanation = evalxfail.getexplanation()
- pytest.fail('[XPASS(strict)] ' + explanation, pytrace=False)
-
-
-@pytest.hookimpl(hookwrapper=True)
-def pytest_runtest_makereport(item, call):
- outcome = yield
- rep = outcome.get_result()
- evalxfail = getattr(item, '_evalxfail', None)
- evalskip = getattr(item, '_evalskip', None)
- # unitttest special case, see setting of _unexpectedsuccess
- if hasattr(item, '_unexpectedsuccess') and rep.when == "call":
- # we need to translate into how pytest encodes xpass
- rep.wasxfail = "reason: " + repr(item._unexpectedsuccess)
- rep.outcome = "failed"
- elif item.config.option.runxfail:
- pass # don't interefere
- elif call.excinfo and call.excinfo.errisinstance(pytest.xfail.Exception):
- rep.wasxfail = "reason: " + call.excinfo.value.msg
- rep.outcome = "skipped"
- elif evalxfail and not rep.skipped and evalxfail.wasvalid() and \
- evalxfail.istrue():
- if call.excinfo:
- if evalxfail.invalidraise(call.excinfo.value):
- rep.outcome = "failed"
- else:
- rep.outcome = "skipped"
- rep.wasxfail = evalxfail.getexplanation()
- elif call.when == "call":
- rep.outcome = "failed" # xpass outcome
- rep.wasxfail = evalxfail.getexplanation()
- elif evalskip is not None and rep.skipped and type(rep.longrepr) is tuple:
- # skipped by mark.skipif; change the location of the failure
- # to point to the item definition, otherwise it will display
- # the location of where the skip exception was raised within pytest
- filename, line, reason = rep.longrepr
- filename, line = item.location[:2]
- rep.longrepr = filename, line, reason
-
-# called by terminalreporter progress reporting
-def pytest_report_teststatus(report):
- if hasattr(report, "wasxfail"):
- if report.skipped:
- return "xfailed", "x", "xfail"
- elif report.failed:
- return "xpassed", "X", ("XPASS", {'yellow': True})
-
-# called by the terminalreporter instance/plugin
-def pytest_terminal_summary(terminalreporter):
- tr = terminalreporter
- if not tr.reportchars:
- #for name in "xfailed skipped failed xpassed":
- # if not tr.stats.get(name, 0):
- # tr.write_line("HINT: use '-r' option to see extra "
- # "summary info about tests")
- # break
- return
-
- lines = []
- for char in tr.reportchars:
- if char == "x":
- show_xfailed(terminalreporter, lines)
- elif char == "X":
- show_xpassed(terminalreporter, lines)
- elif char in "fF":
- show_simple(terminalreporter, lines, 'failed', "FAIL %s")
- elif char in "sS":
- show_skipped(terminalreporter, lines)
- elif char == "E":
- show_simple(terminalreporter, lines, 'error', "ERROR %s")
- elif char == 'p':
- show_simple(terminalreporter, lines, 'passed', "PASSED %s")
-
- if lines:
- tr._tw.sep("=", "short test summary info")
- for line in lines:
- tr._tw.line(line)
-
-def show_simple(terminalreporter, lines, stat, format):
- failed = terminalreporter.stats.get(stat)
- if failed:
- for rep in failed:
- pos = terminalreporter.config.cwd_relative_nodeid(rep.nodeid)
- lines.append(format %(pos,))
-
-def show_xfailed(terminalreporter, lines):
- xfailed = terminalreporter.stats.get("xfailed")
- if xfailed:
- for rep in xfailed:
- pos = terminalreporter.config.cwd_relative_nodeid(rep.nodeid)
- reason = rep.wasxfail
- lines.append("XFAIL %s" % (pos,))
- if reason:
- lines.append(" " + str(reason))
-
-def show_xpassed(terminalreporter, lines):
- xpassed = terminalreporter.stats.get("xpassed")
- if xpassed:
- for rep in xpassed:
- pos = terminalreporter.config.cwd_relative_nodeid(rep.nodeid)
- reason = rep.wasxfail
- lines.append("XPASS %s %s" %(pos, reason))
-
-def cached_eval(config, expr, d):
- if not hasattr(config, '_evalcache'):
- config._evalcache = {}
- try:
- return config._evalcache[expr]
- except KeyError:
- import _pytest._code
- exprcode = _pytest._code.compile(expr, mode="eval")
- config._evalcache[expr] = x = eval(exprcode, d)
- return x
-
-
-def folded_skips(skipped):
- d = {}
- for event in skipped:
- key = event.longrepr
- assert len(key) == 3, (event, key)
- d.setdefault(key, []).append(event)
- l = []
- for key, events in d.items():
- l.append((len(events),) + key)
- return l
-
-def show_skipped(terminalreporter, lines):
- tr = terminalreporter
- skipped = tr.stats.get('skipped', [])
- if skipped:
- #if not tr.hasopt('skipped'):
- # tr.write_line(
- # "%d skipped tests, specify -rs for more info" %
- # len(skipped))
- # return
- fskips = folded_skips(skipped)
- if fskips:
- #tr.write_sep("_", "skipped test summary")
- for num, fspath, lineno, reason in fskips:
- if reason.startswith("Skipped: "):
- reason = reason[9:]
- lines.append("SKIP [%d] %s:%d: %s" %
- (num, fspath, lineno, reason))
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/standalonetemplate.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/standalonetemplate.py
deleted file mode 100755
index 484d5d1b25f..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/standalonetemplate.py
+++ /dev/null
@@ -1,89 +0,0 @@
-#! /usr/bin/env python
-
-# Hi There!
-# You may be wondering what this giant blob of binary data here is, you might
-# even be worried that we're up to something nefarious (good for you for being
-# paranoid!). This is a base64 encoding of a zip file, this zip file contains
-# a fully functional basic pytest script.
-#
-# Pytest is a thing that tests packages, pytest itself is a package that some-
-# one might want to install, especially if they're looking to run tests inside
-# some package they want to install. Pytest has a lot of code to collect and
-# execute tests, and other such sort of "tribal knowledge" that has been en-
-# coded in its code base. Because of this we basically include a basic copy
-# of pytest inside this blob. We do this because it let's you as a maintainer
-# or application developer who wants people who don't deal with python much to
-# easily run tests without installing the complete pytest package.
-#
-# If you're wondering how this is created: you can create it yourself if you
-# have a complete pytest installation by using this command on the command-
-# line: ``py.test --genscript=runtests.py``.
-
-sources = """
-@SOURCES@"""
-
-import sys
-import base64
-import zlib
-
-class DictImporter(object):
- def __init__(self, sources):
- self.sources = sources
-
- def find_module(self, fullname, path=None):
- if fullname == "argparse" and sys.version_info >= (2,7):
- # we were generated with <python2.7 (which pulls in argparse)
- # but we are running now on a stdlib which has it, so use that.
- return None
- if fullname in self.sources:
- return self
- if fullname + '.__init__' in self.sources:
- return self
- return None
-
- def load_module(self, fullname):
- # print "load_module:", fullname
- from types import ModuleType
- try:
- s = self.sources[fullname]
- is_pkg = False
- except KeyError:
- s = self.sources[fullname + '.__init__']
- is_pkg = True
-
- co = compile(s, fullname, 'exec')
- module = sys.modules.setdefault(fullname, ModuleType(fullname))
- module.__file__ = "%s/%s" % (__file__, fullname)
- module.__loader__ = self
- if is_pkg:
- module.__path__ = [fullname]
-
- do_exec(co, module.__dict__) # noqa
- return sys.modules[fullname]
-
- def get_source(self, name):
- res = self.sources.get(name)
- if res is None:
- res = self.sources.get(name + '.__init__')
- return res
-
-if __name__ == "__main__":
- try:
- import pkg_resources # noqa
- except ImportError:
- sys.stderr.write("ERROR: setuptools not installed\n")
- sys.exit(2)
- if sys.version_info >= (3, 0):
- exec("def do_exec(co, loc): exec(co, loc)\n")
- import pickle
- sources = sources.encode("ascii") # ensure bytes
- sources = pickle.loads(zlib.decompress(base64.decodebytes(sources)))
- else:
- import cPickle as pickle
- exec("def do_exec(co, loc): exec co in loc\n")
- sources = pickle.loads(zlib.decompress(base64.decodestring(sources)))
-
- importer = DictImporter(sources)
- sys.meta_path.insert(0, importer)
- entry = "@ENTRY@"
- do_exec(entry, locals()) # noqa
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/terminal.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/terminal.py
deleted file mode 100644
index 825f553ef2c..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/terminal.py
+++ /dev/null
@@ -1,593 +0,0 @@
-""" terminal reporting of the full testing process.
-
-This is a good source for looking at the various reporting hooks.
-"""
-from _pytest.main import EXIT_OK, EXIT_TESTSFAILED, EXIT_INTERRUPTED, \
- EXIT_USAGEERROR, EXIT_NOTESTSCOLLECTED
-import pytest
-import py
-import sys
-import time
-import platform
-
-import _pytest._pluggy as pluggy
-
-
-def pytest_addoption(parser):
- group = parser.getgroup("terminal reporting", "reporting", after="general")
- group._addoption('-v', '--verbose', action="count",
- dest="verbose", default=0, help="increase verbosity."),
- group._addoption('-q', '--quiet', action="count",
- dest="quiet", default=0, help="decrease verbosity."),
- group._addoption('-r',
- action="store", dest="reportchars", default=None, metavar="chars",
- help="show extra test summary info as specified by chars (f)ailed, "
- "(E)error, (s)skipped, (x)failed, (X)passed (w)pytest-warnings "
- "(p)passed, (P)passed with output, (a)all except pP.")
- group._addoption('-l', '--showlocals',
- action="store_true", dest="showlocals", default=False,
- help="show locals in tracebacks (disabled by default).")
- group._addoption('--report',
- action="store", dest="report", default=None, metavar="opts",
- help="(deprecated, use -r)")
- group._addoption('--tb', metavar="style",
- action="store", dest="tbstyle", default='auto',
- choices=['auto', 'long', 'short', 'no', 'line', 'native'],
- help="traceback print mode (auto/long/short/line/native/no).")
- group._addoption('--fulltrace', '--full-trace',
- action="store_true", default=False,
- help="don't cut any tracebacks (default is to cut).")
- group._addoption('--color', metavar="color",
- action="store", dest="color", default='auto',
- choices=['yes', 'no', 'auto'],
- help="color terminal output (yes/no/auto).")
-
-def pytest_configure(config):
- config.option.verbose -= config.option.quiet
- reporter = TerminalReporter(config, sys.stdout)
- config.pluginmanager.register(reporter, 'terminalreporter')
- if config.option.debug or config.option.traceconfig:
- def mywriter(tags, args):
- msg = " ".join(map(str, args))
- reporter.write_line("[traceconfig] " + msg)
- config.trace.root.setprocessor("pytest:config", mywriter)
-
-def getreportopt(config):
- reportopts = ""
- optvalue = config.option.report
- if optvalue:
- py.builtin.print_("DEPRECATED: use -r instead of --report option.",
- file=sys.stderr)
- if optvalue:
- for setting in optvalue.split(","):
- setting = setting.strip()
- if setting == "skipped":
- reportopts += "s"
- elif setting == "xfailed":
- reportopts += "x"
- reportchars = config.option.reportchars
- if reportchars:
- for char in reportchars:
- if char not in reportopts and char != 'a':
- reportopts += char
- elif char == 'a':
- reportopts = 'fEsxXw'
- return reportopts
-
-def pytest_report_teststatus(report):
- if report.passed:
- letter = "."
- elif report.skipped:
- letter = "s"
- elif report.failed:
- letter = "F"
- if report.when != "call":
- letter = "f"
- return report.outcome, letter, report.outcome.upper()
-
-class WarningReport:
- def __init__(self, code, message, nodeid=None, fslocation=None):
- self.code = code
- self.message = message
- self.nodeid = nodeid
- self.fslocation = fslocation
-
-
-class TerminalReporter:
- def __init__(self, config, file=None):
- import _pytest.config
- self.config = config
- self.verbosity = self.config.option.verbose
- self.showheader = self.verbosity >= 0
- self.showfspath = self.verbosity >= 0
- self.showlongtestinfo = self.verbosity > 0
- self._numcollected = 0
-
- self.stats = {}
- self.startdir = py.path.local()
- if file is None:
- file = sys.stdout
- self._tw = self.writer = _pytest.config.create_terminal_writer(config,
- file)
- self.currentfspath = None
- self.reportchars = getreportopt(config)
- self.hasmarkup = self._tw.hasmarkup
- self.isatty = file.isatty()
-
- def hasopt(self, char):
- char = {'xfailed': 'x', 'skipped': 's'}.get(char, char)
- return char in self.reportchars
-
- def write_fspath_result(self, nodeid, res):
- fspath = self.config.rootdir.join(nodeid.split("::")[0])
- if fspath != self.currentfspath:
- self.currentfspath = fspath
- fspath = self.startdir.bestrelpath(fspath)
- self._tw.line()
- self._tw.write(fspath + " ")
- self._tw.write(res)
-
- def write_ensure_prefix(self, prefix, extra="", **kwargs):
- if self.currentfspath != prefix:
- self._tw.line()
- self.currentfspath = prefix
- self._tw.write(prefix)
- if extra:
- self._tw.write(extra, **kwargs)
- self.currentfspath = -2
-
- def ensure_newline(self):
- if self.currentfspath:
- self._tw.line()
- self.currentfspath = None
-
- def write(self, content, **markup):
- self._tw.write(content, **markup)
-
- def write_line(self, line, **markup):
- if not py.builtin._istext(line):
- line = py.builtin.text(line, errors="replace")
- self.ensure_newline()
- self._tw.line(line, **markup)
-
- def rewrite(self, line, **markup):
- line = str(line)
- self._tw.write("\r" + line, **markup)
-
- def write_sep(self, sep, title=None, **markup):
- self.ensure_newline()
- self._tw.sep(sep, title, **markup)
-
- def section(self, title, sep="=", **kw):
- self._tw.sep(sep, title, **kw)
-
- def line(self, msg, **kw):
- self._tw.line(msg, **kw)
-
- def pytest_internalerror(self, excrepr):
- for line in py.builtin.text(excrepr).split("\n"):
- self.write_line("INTERNALERROR> " + line)
- return 1
-
- def pytest_logwarning(self, code, fslocation, message, nodeid):
- warnings = self.stats.setdefault("warnings", [])
- if isinstance(fslocation, tuple):
- fslocation = "%s:%d" % fslocation
- warning = WarningReport(code=code, fslocation=fslocation,
- message=message, nodeid=nodeid)
- warnings.append(warning)
-
- def pytest_plugin_registered(self, plugin):
- if self.config.option.traceconfig:
- msg = "PLUGIN registered: %s" % (plugin,)
- # XXX this event may happen during setup/teardown time
- # which unfortunately captures our output here
- # which garbles our output if we use self.write_line
- self.write_line(msg)
-
- def pytest_deselected(self, items):
- self.stats.setdefault('deselected', []).extend(items)
-
- def pytest_runtest_logstart(self, nodeid, location):
- # ensure that the path is printed before the
- # 1st test of a module starts running
- if self.showlongtestinfo:
- line = self._locationline(nodeid, *location)
- self.write_ensure_prefix(line, "")
- elif self.showfspath:
- fsid = nodeid.split("::")[0]
- self.write_fspath_result(fsid, "")
-
- def pytest_runtest_logreport(self, report):
- rep = report
- res = self.config.hook.pytest_report_teststatus(report=rep)
- cat, letter, word = res
- self.stats.setdefault(cat, []).append(rep)
- self._tests_ran = True
- if not letter and not word:
- # probably passed setup/teardown
- return
- if self.verbosity <= 0:
- if not hasattr(rep, 'node') and self.showfspath:
- self.write_fspath_result(rep.nodeid, letter)
- else:
- self._tw.write(letter)
- else:
- if isinstance(word, tuple):
- word, markup = word
- else:
- if rep.passed:
- markup = {'green':True}
- elif rep.failed:
- markup = {'red':True}
- elif rep.skipped:
- markup = {'yellow':True}
- line = self._locationline(rep.nodeid, *rep.location)
- if not hasattr(rep, 'node'):
- self.write_ensure_prefix(line, word, **markup)
- #self._tw.write(word, **markup)
- else:
- self.ensure_newline()
- if hasattr(rep, 'node'):
- self._tw.write("[%s] " % rep.node.gateway.id)
- self._tw.write(word, **markup)
- self._tw.write(" " + line)
- self.currentfspath = -2
-
- def pytest_collection(self):
- if not self.isatty and self.config.option.verbose >= 1:
- self.write("collecting ... ", bold=True)
-
- def pytest_collectreport(self, report):
- if report.failed:
- self.stats.setdefault("error", []).append(report)
- elif report.skipped:
- self.stats.setdefault("skipped", []).append(report)
- items = [x for x in report.result if isinstance(x, pytest.Item)]
- self._numcollected += len(items)
- if self.isatty:
- #self.write_fspath_result(report.nodeid, 'E')
- self.report_collect()
-
- def report_collect(self, final=False):
- if self.config.option.verbose < 0:
- return
-
- errors = len(self.stats.get('error', []))
- skipped = len(self.stats.get('skipped', []))
- if final:
- line = "collected "
- else:
- line = "collecting "
- line += str(self._numcollected) + " items"
- if errors:
- line += " / %d errors" % errors
- if skipped:
- line += " / %d skipped" % skipped
- if self.isatty:
- if final:
- line += " \n"
- self.rewrite(line, bold=True)
- else:
- self.write_line(line)
-
- def pytest_collection_modifyitems(self):
- self.report_collect(True)
-
- @pytest.hookimpl(trylast=True)
- def pytest_sessionstart(self, session):
- self._sessionstarttime = time.time()
- if not self.showheader:
- return
- self.write_sep("=", "test session starts", bold=True)
- verinfo = platform.python_version()
- msg = "platform %s -- Python %s" % (sys.platform, verinfo)
- if hasattr(sys, 'pypy_version_info'):
- verinfo = ".".join(map(str, sys.pypy_version_info[:3]))
- msg += "[pypy-%s-%s]" % (verinfo, sys.pypy_version_info[3])
- msg += ", pytest-%s, py-%s, pluggy-%s" % (
- pytest.__version__, py.__version__, pluggy.__version__)
- if self.verbosity > 0 or self.config.option.debug or \
- getattr(self.config.option, 'pastebin', None):
- msg += " -- " + str(sys.executable)
- self.write_line(msg)
- lines = self.config.hook.pytest_report_header(
- config=self.config, startdir=self.startdir)
- lines.reverse()
- for line in flatten(lines):
- self.write_line(line)
-
- def pytest_report_header(self, config):
- inifile = ""
- if config.inifile:
- inifile = config.rootdir.bestrelpath(config.inifile)
- lines = ["rootdir: %s, inifile: %s" %(config.rootdir, inifile)]
-
- plugininfo = config.pluginmanager.list_plugin_distinfo()
- if plugininfo:
-
- lines.append(
- "plugins: %s" % ", ".join(_plugin_nameversions(plugininfo)))
- return lines
-
- def pytest_collection_finish(self, session):
- if self.config.option.collectonly:
- self._printcollecteditems(session.items)
- if self.stats.get('failed'):
- self._tw.sep("!", "collection failures")
- for rep in self.stats.get('failed'):
- rep.toterminal(self._tw)
- return 1
- return 0
- if not self.showheader:
- return
- #for i, testarg in enumerate(self.config.args):
- # self.write_line("test path %d: %s" %(i+1, testarg))
-
- def _printcollecteditems(self, items):
- # to print out items and their parent collectors
- # we take care to leave out Instances aka ()
- # because later versions are going to get rid of them anyway
- if self.config.option.verbose < 0:
- if self.config.option.verbose < -1:
- counts = {}
- for item in items:
- name = item.nodeid.split('::', 1)[0]
- counts[name] = counts.get(name, 0) + 1
- for name, count in sorted(counts.items()):
- self._tw.line("%s: %d" % (name, count))
- else:
- for item in items:
- nodeid = item.nodeid
- nodeid = nodeid.replace("::()::", "::")
- self._tw.line(nodeid)
- return
- stack = []
- indent = ""
- for item in items:
- needed_collectors = item.listchain()[1:] # strip root node
- while stack:
- if stack == needed_collectors[:len(stack)]:
- break
- stack.pop()
- for col in needed_collectors[len(stack):]:
- stack.append(col)
- #if col.name == "()":
- # continue
- indent = (len(stack) - 1) * " "
- self._tw.line("%s%s" % (indent, col))
-
- @pytest.hookimpl(hookwrapper=True)
- def pytest_sessionfinish(self, exitstatus):
- outcome = yield
- outcome.get_result()
- self._tw.line("")
- summary_exit_codes = (
- EXIT_OK, EXIT_TESTSFAILED, EXIT_INTERRUPTED, EXIT_USAGEERROR,
- EXIT_NOTESTSCOLLECTED)
- if exitstatus in summary_exit_codes:
- self.config.hook.pytest_terminal_summary(terminalreporter=self)
- self.summary_errors()
- self.summary_failures()
- self.summary_warnings()
- self.summary_passes()
- if exitstatus == EXIT_INTERRUPTED:
- self._report_keyboardinterrupt()
- del self._keyboardinterrupt_memo
- self.summary_deselected()
- self.summary_stats()
-
- def pytest_keyboard_interrupt(self, excinfo):
- self._keyboardinterrupt_memo = excinfo.getrepr(funcargs=True)
-
- def pytest_unconfigure(self):
- if hasattr(self, '_keyboardinterrupt_memo'):
- self._report_keyboardinterrupt()
-
- def _report_keyboardinterrupt(self):
- excrepr = self._keyboardinterrupt_memo
- msg = excrepr.reprcrash.message
- self.write_sep("!", msg)
- if "KeyboardInterrupt" in msg:
- if self.config.option.fulltrace:
- excrepr.toterminal(self._tw)
- else:
- self._tw.line("to show a full traceback on KeyboardInterrupt use --fulltrace", yellow=True)
- excrepr.reprcrash.toterminal(self._tw)
-
- def _locationline(self, nodeid, fspath, lineno, domain):
- def mkrel(nodeid):
- line = self.config.cwd_relative_nodeid(nodeid)
- if domain and line.endswith(domain):
- line = line[:-len(domain)]
- l = domain.split("[")
- l[0] = l[0].replace('.', '::') # don't replace '.' in params
- line += "[".join(l)
- return line
- # collect_fspath comes from testid which has a "/"-normalized path
-
- if fspath:
- res = mkrel(nodeid).replace("::()", "") # parens-normalization
- if nodeid.split("::")[0] != fspath.replace("\\", "/"):
- res += " <- " + self.startdir.bestrelpath(fspath)
- else:
- res = "[location]"
- return res + " "
-
- def _getfailureheadline(self, rep):
- if hasattr(rep, 'location'):
- fspath, lineno, domain = rep.location
- return domain
- else:
- return "test session" # XXX?
-
- def _getcrashline(self, rep):
- try:
- return str(rep.longrepr.reprcrash)
- except AttributeError:
- try:
- return str(rep.longrepr)[:50]
- except AttributeError:
- return ""
-
- #
- # summaries for sessionfinish
- #
- def getreports(self, name):
- l = []
- for x in self.stats.get(name, []):
- if not hasattr(x, '_pdbshown'):
- l.append(x)
- return l
-
- def summary_warnings(self):
- if self.hasopt("w"):
- warnings = self.stats.get("warnings")
- if not warnings:
- return
- self.write_sep("=", "pytest-warning summary")
- for w in warnings:
- self._tw.line("W%s %s %s" % (w.code,
- w.fslocation, w.message))
-
- def summary_passes(self):
- if self.config.option.tbstyle != "no":
- if self.hasopt("P"):
- reports = self.getreports('passed')
- if not reports:
- return
- self.write_sep("=", "PASSES")
- for rep in reports:
- msg = self._getfailureheadline(rep)
- self.write_sep("_", msg)
- self._outrep_summary(rep)
-
- def summary_failures(self):
- if self.config.option.tbstyle != "no":
- reports = self.getreports('failed')
- if not reports:
- return
- self.write_sep("=", "FAILURES")
- for rep in reports:
- if self.config.option.tbstyle == "line":
- line = self._getcrashline(rep)
- self.write_line(line)
- else:
- msg = self._getfailureheadline(rep)
- markup = {'red': True, 'bold': True}
- self.write_sep("_", msg, **markup)
- self._outrep_summary(rep)
-
- def summary_errors(self):
- if self.config.option.tbstyle != "no":
- reports = self.getreports('error')
- if not reports:
- return
- self.write_sep("=", "ERRORS")
- for rep in self.stats['error']:
- msg = self._getfailureheadline(rep)
- if not hasattr(rep, 'when'):
- # collect
- msg = "ERROR collecting " + msg
- elif rep.when == "setup":
- msg = "ERROR at setup of " + msg
- elif rep.when == "teardown":
- msg = "ERROR at teardown of " + msg
- self.write_sep("_", msg)
- self._outrep_summary(rep)
-
- def _outrep_summary(self, rep):
- rep.toterminal(self._tw)
- for secname, content in rep.sections:
- self._tw.sep("-", secname)
- if content[-1:] == "\n":
- content = content[:-1]
- self._tw.line(content)
-
- def summary_stats(self):
- session_duration = time.time() - self._sessionstarttime
- (line, color) = build_summary_stats_line(self.stats)
- msg = "%s in %.2f seconds" % (line, session_duration)
- markup = {color: True, 'bold': True}
-
- if self.verbosity >= 0:
- self.write_sep("=", msg, **markup)
- if self.verbosity == -1:
- self.write_line(msg, **markup)
-
- def summary_deselected(self):
- if 'deselected' in self.stats:
- l = []
- k = self.config.option.keyword
- if k:
- l.append("-k%s" % k)
- m = self.config.option.markexpr
- if m:
- l.append("-m %r" % m)
- if l:
- self.write_sep("=", "%d tests deselected by %r" % (
- len(self.stats['deselected']), " ".join(l)), bold=True)
-
-def repr_pythonversion(v=None):
- if v is None:
- v = sys.version_info
- try:
- return "%s.%s.%s-%s-%s" % v
- except (TypeError, ValueError):
- return str(v)
-
-def flatten(l):
- for x in l:
- if isinstance(x, (list, tuple)):
- for y in flatten(x):
- yield y
- else:
- yield x
-
-def build_summary_stats_line(stats):
- keys = ("failed passed skipped deselected "
- "xfailed xpassed warnings error").split()
- key_translation = {'warnings': 'pytest-warnings'}
- unknown_key_seen = False
- for key in stats.keys():
- if key not in keys:
- if key: # setup/teardown reports have an empty key, ignore them
- keys.append(key)
- unknown_key_seen = True
- parts = []
- for key in keys:
- val = stats.get(key, None)
- if val:
- key_name = key_translation.get(key, key)
- parts.append("%d %s" % (len(val), key_name))
-
- if parts:
- line = ", ".join(parts)
- else:
- line = "no tests ran"
-
- if 'failed' in stats or 'error' in stats:
- color = 'red'
- elif 'warnings' in stats or unknown_key_seen:
- color = 'yellow'
- elif 'passed' in stats:
- color = 'green'
- else:
- color = 'yellow'
-
- return (line, color)
-
-
-def _plugin_nameversions(plugininfo):
- l = []
- for plugin, dist in plugininfo:
- # gets us name and version!
- name = '{dist.project_name}-{dist.version}'.format(dist=dist)
- # questionable convenience, but it keeps things short
- if name.startswith("pytest-"):
- name = name[7:]
- # we decided to print python package names
- # they can have more than one plugin
- if name not in l:
- l.append(name)
- return l
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/tmpdir.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/tmpdir.py
deleted file mode 100644
index ebc48dbe5b2..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/tmpdir.py
+++ /dev/null
@@ -1,123 +0,0 @@
-""" support for providing temporary directories to test functions. """
-import re
-
-import pytest
-import py
-from _pytest.monkeypatch import monkeypatch
-
-
-class TempdirFactory:
- """Factory for temporary directories under the common base temp directory.
-
- The base directory can be configured using the ``--basetemp`` option.
- """
-
- def __init__(self, config):
- self.config = config
- self.trace = config.trace.get("tmpdir")
-
- def ensuretemp(self, string, dir=1):
- """ (deprecated) return temporary directory path with
- the given string as the trailing part. It is usually
- better to use the 'tmpdir' function argument which
- provides an empty unique-per-test-invocation directory
- and is guaranteed to be empty.
- """
- #py.log._apiwarn(">1.1", "use tmpdir function argument")
- return self.getbasetemp().ensure(string, dir=dir)
-
- def mktemp(self, basename, numbered=True):
- """Create a subdirectory of the base temporary directory and return it.
- If ``numbered``, ensure the directory is unique by adding a number
- prefix greater than any existing one.
- """
- basetemp = self.getbasetemp()
- if not numbered:
- p = basetemp.mkdir(basename)
- else:
- p = py.path.local.make_numbered_dir(prefix=basename,
- keep=0, rootdir=basetemp, lock_timeout=None)
- self.trace("mktemp", p)
- return p
-
- def getbasetemp(self):
- """ return base temporary directory. """
- try:
- return self._basetemp
- except AttributeError:
- basetemp = self.config.option.basetemp
- if basetemp:
- basetemp = py.path.local(basetemp)
- if basetemp.check():
- basetemp.remove()
- basetemp.mkdir()
- else:
- temproot = py.path.local.get_temproot()
- user = get_user()
- if user:
- # use a sub-directory in the temproot to speed-up
- # make_numbered_dir() call
- rootdir = temproot.join('pytest-of-%s' % user)
- else:
- rootdir = temproot
- rootdir.ensure(dir=1)
- basetemp = py.path.local.make_numbered_dir(prefix='pytest-',
- rootdir=rootdir)
- self._basetemp = t = basetemp.realpath()
- self.trace("new basetemp", t)
- return t
-
- def finish(self):
- self.trace("finish")
-
-
-def get_user():
- """Return the current user name, or None if getuser() does not work
- in the current environment (see #1010).
- """
- import getpass
- try:
- return getpass.getuser()
- except (ImportError, KeyError):
- return None
-
-# backward compatibility
-TempdirHandler = TempdirFactory
-
-
-def pytest_configure(config):
- """Create a TempdirFactory and attach it to the config object.
-
- This is to comply with existing plugins which expect the handler to be
- available at pytest_configure time, but ideally should be moved entirely
- to the tmpdir_factory session fixture.
- """
- mp = monkeypatch()
- t = TempdirFactory(config)
- config._cleanup.extend([mp.undo, t.finish])
- mp.setattr(config, '_tmpdirhandler', t, raising=False)
- mp.setattr(pytest, 'ensuretemp', t.ensuretemp, raising=False)
-
-
-@pytest.fixture(scope='session')
-def tmpdir_factory(request):
- """Return a TempdirFactory instance for the test session.
- """
- return request.config._tmpdirhandler
-
-
-@pytest.fixture
-def tmpdir(request, tmpdir_factory):
- """return a temporary directory path object
- which is unique to each test function invocation,
- created as a sub directory of the base temporary
- directory. The returned object is a `py.path.local`_
- path object.
- """
- name = request.node.name
- name = re.sub("[\W]", "_", name)
- MAXVAL = 30
- if len(name) > MAXVAL:
- name = name[:MAXVAL]
- x = tmpdir_factory.mktemp(name, numbered=True)
- return x
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/unittest.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/unittest.py
deleted file mode 100644
index 8120e94fbf4..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/unittest.py
+++ /dev/null
@@ -1,205 +0,0 @@
-""" discovery and running of std-library "unittest" style tests. """
-from __future__ import absolute_import
-
-import sys
-import traceback
-
-import pytest
-# for transfering markers
-import _pytest._code
-from _pytest.python import transfer_markers
-from _pytest.skipping import MarkEvaluator
-
-
-def pytest_pycollect_makeitem(collector, name, obj):
- # has unittest been imported and is obj a subclass of its TestCase?
- try:
- if not issubclass(obj, sys.modules["unittest"].TestCase):
- return
- except Exception:
- return
- # yes, so let's collect it
- return UnitTestCase(name, parent=collector)
-
-
-class UnitTestCase(pytest.Class):
- # marker for fixturemanger.getfixtureinfo()
- # to declare that our children do not support funcargs
- nofuncargs = True
-
- def setup(self):
- cls = self.obj
- if getattr(cls, '__unittest_skip__', False):
- return # skipped
- setup = getattr(cls, 'setUpClass', None)
- if setup is not None:
- setup()
- teardown = getattr(cls, 'tearDownClass', None)
- if teardown is not None:
- self.addfinalizer(teardown)
- super(UnitTestCase, self).setup()
-
- def collect(self):
- from unittest import TestLoader
- cls = self.obj
- if not getattr(cls, "__test__", True):
- return
- self.session._fixturemanager.parsefactories(self, unittest=True)
- loader = TestLoader()
- module = self.getparent(pytest.Module).obj
- foundsomething = False
- for name in loader.getTestCaseNames(self.obj):
- x = getattr(self.obj, name)
- funcobj = getattr(x, 'im_func', x)
- transfer_markers(funcobj, cls, module)
- yield TestCaseFunction(name, parent=self)
- foundsomething = True
-
- if not foundsomething:
- runtest = getattr(self.obj, 'runTest', None)
- if runtest is not None:
- ut = sys.modules.get("twisted.trial.unittest", None)
- if ut is None or runtest != ut.TestCase.runTest:
- yield TestCaseFunction('runTest', parent=self)
-
-
-
-class TestCaseFunction(pytest.Function):
- _excinfo = None
-
- def setup(self):
- self._testcase = self.parent.obj(self.name)
- self._fix_unittest_skip_decorator()
- self._obj = getattr(self._testcase, self.name)
- if hasattr(self._testcase, 'setup_method'):
- self._testcase.setup_method(self._obj)
- if hasattr(self, "_request"):
- self._request._fillfixtures()
-
- def _fix_unittest_skip_decorator(self):
- """
- The @unittest.skip decorator calls functools.wraps(self._testcase)
- The call to functools.wraps() fails unless self._testcase
- has a __name__ attribute. This is usually automatically supplied
- if the test is a function or method, but we need to add manually
- here.
-
- See issue #1169
- """
- if sys.version_info[0] == 2:
- setattr(self._testcase, "__name__", self.name)
-
- def teardown(self):
- if hasattr(self._testcase, 'teardown_method'):
- self._testcase.teardown_method(self._obj)
-
- def startTest(self, testcase):
- pass
-
- def _addexcinfo(self, rawexcinfo):
- # unwrap potential exception info (see twisted trial support below)
- rawexcinfo = getattr(rawexcinfo, '_rawexcinfo', rawexcinfo)
- try:
- excinfo = _pytest._code.ExceptionInfo(rawexcinfo)
- except TypeError:
- try:
- try:
- l = traceback.format_exception(*rawexcinfo)
- l.insert(0, "NOTE: Incompatible Exception Representation, "
- "displaying natively:\n\n")
- pytest.fail("".join(l), pytrace=False)
- except (pytest.fail.Exception, KeyboardInterrupt):
- raise
- except:
- pytest.fail("ERROR: Unknown Incompatible Exception "
- "representation:\n%r" %(rawexcinfo,), pytrace=False)
- except KeyboardInterrupt:
- raise
- except pytest.fail.Exception:
- excinfo = _pytest._code.ExceptionInfo()
- self.__dict__.setdefault('_excinfo', []).append(excinfo)
-
- def addError(self, testcase, rawexcinfo):
- self._addexcinfo(rawexcinfo)
- def addFailure(self, testcase, rawexcinfo):
- self._addexcinfo(rawexcinfo)
-
- def addSkip(self, testcase, reason):
- try:
- pytest.skip(reason)
- except pytest.skip.Exception:
- self._evalskip = MarkEvaluator(self, 'SkipTest')
- self._evalskip.result = True
- self._addexcinfo(sys.exc_info())
-
- def addExpectedFailure(self, testcase, rawexcinfo, reason=""):
- try:
- pytest.xfail(str(reason))
- except pytest.xfail.Exception:
- self._addexcinfo(sys.exc_info())
-
- def addUnexpectedSuccess(self, testcase, reason=""):
- self._unexpectedsuccess = reason
-
- def addSuccess(self, testcase):
- pass
-
- def stopTest(self, testcase):
- pass
-
- def runtest(self):
- self._testcase(result=self)
-
- def _prunetraceback(self, excinfo):
- pytest.Function._prunetraceback(self, excinfo)
- traceback = excinfo.traceback.filter(
- lambda x:not x.frame.f_globals.get('__unittest'))
- if traceback:
- excinfo.traceback = traceback
-
-@pytest.hookimpl(tryfirst=True)
-def pytest_runtest_makereport(item, call):
- if isinstance(item, TestCaseFunction):
- if item._excinfo:
- call.excinfo = item._excinfo.pop(0)
- try:
- del call.result
- except AttributeError:
- pass
-
-# twisted trial support
-
-@pytest.hookimpl(hookwrapper=True)
-def pytest_runtest_protocol(item):
- if isinstance(item, TestCaseFunction) and \
- 'twisted.trial.unittest' in sys.modules:
- ut = sys.modules['twisted.python.failure']
- Failure__init__ = ut.Failure.__init__
- check_testcase_implements_trial_reporter()
- def excstore(self, exc_value=None, exc_type=None, exc_tb=None,
- captureVars=None):
- if exc_value is None:
- self._rawexcinfo = sys.exc_info()
- else:
- if exc_type is None:
- exc_type = type(exc_value)
- self._rawexcinfo = (exc_type, exc_value, exc_tb)
- try:
- Failure__init__(self, exc_value, exc_type, exc_tb,
- captureVars=captureVars)
- except TypeError:
- Failure__init__(self, exc_value, exc_type, exc_tb)
- ut.Failure.__init__ = excstore
- yield
- ut.Failure.__init__ = Failure__init__
- else:
- yield
-
-
-def check_testcase_implements_trial_reporter(done=[]):
- if done:
- return
- from zope.interface import classImplements
- from twisted.trial.itrial import IReporter
- classImplements(TestCaseFunction, IReporter)
- done.append(1)
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/README.md b/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/README.md
deleted file mode 100644
index eab7c714fb0..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/README.md
+++ /dev/null
@@ -1,13 +0,0 @@
-This directory vendors the `pluggy` module.
-
-For a more detailed discussion for the reasons to vendoring this
-package, please see [this issue](https://github.com/pytest-dev/pytest/issues/944).
-
-To update the current version, execute:
-
-```
-$ pip install -U pluggy==<version> --no-compile --target=_pytest/vendored_packages
-```
-
-And commit the modified files. The `pluggy-<version>.dist-info` directory
-created by `pip` should be ignored.
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/DESCRIPTION.rst b/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/DESCRIPTION.rst
deleted file mode 100644
index aa3bbf81297..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/DESCRIPTION.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-Plugin registration and hook calling for Python
-===============================================
-
-This is the plugin manager as used by pytest but stripped
-of pytest specific details.
-
-During the 0.x series this plugin does not have much documentation
-except extensive docstrings in the pluggy.py module.
-
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/METADATA b/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/METADATA
deleted file mode 100644
index ec81f0a6be0..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/METADATA
+++ /dev/null
@@ -1,39 +0,0 @@
-Metadata-Version: 2.0
-Name: pluggy
-Version: 0.3.1
-Summary: plugin and hook calling mechanisms for python
-Home-page: UNKNOWN
-Author: Holger Krekel
-Author-email: holger at merlinux.eu
-License: MIT license
-Platform: unix
-Platform: linux
-Platform: osx
-Platform: win32
-Classifier: Development Status :: 4 - Beta
-Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: MIT License
-Classifier: Operating System :: POSIX
-Classifier: Operating System :: Microsoft :: Windows
-Classifier: Operating System :: MacOS :: MacOS X
-Classifier: Topic :: Software Development :: Testing
-Classifier: Topic :: Software Development :: Libraries
-Classifier: Topic :: Utilities
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.6
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.3
-Classifier: Programming Language :: Python :: 3.4
-Classifier: Programming Language :: Python :: 3.5
-
-Plugin registration and hook calling for Python
-===============================================
-
-This is the plugin manager as used by pytest but stripped
-of pytest specific details.
-
-During the 0.x series this plugin does not have much documentation
-except extensive docstrings in the pluggy.py module.
-
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/RECORD b/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/RECORD
deleted file mode 100644
index 9626673c43c..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/RECORD
+++ /dev/null
@@ -1,8 +0,0 @@
-pluggy.py,sha256=v_RfWzyW6DPU1cJu_EFoL_OHq3t13qloVdR6UaMCXQA,29862
-pluggy-0.3.1.dist-info/top_level.txt,sha256=xKSCRhai-v9MckvMuWqNz16c1tbsmOggoMSwTgcpYHE,7
-pluggy-0.3.1.dist-info/pbr.json,sha256=xX3s6__wOcAyF-AZJX1sdZyW6PUXT-FkfBlM69EEUCg,47
-pluggy-0.3.1.dist-info/RECORD,,
-pluggy-0.3.1.dist-info/metadata.json,sha256=nLKltOT78dMV-00uXD6Aeemp4xNsz2q59j6ORSDeLjw,1027
-pluggy-0.3.1.dist-info/METADATA,sha256=1b85Ho2u4iK30M099k7axMzcDDhLcIMb-A82JUJZnSo,1334
-pluggy-0.3.1.dist-info/WHEEL,sha256=AvR0WeTpDaxT645bl5FQxUK6NPsTls2ttpcGJg3j1Xg,110
-pluggy-0.3.1.dist-info/DESCRIPTION.rst,sha256=P5Akh1EdIBR6CeqtV2P8ZwpGSpZiTKPw0NyS7jEiD-g,306
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/metadata.json b/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/metadata.json
deleted file mode 100644
index 426a3a7ade1..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/metadata.json
+++ /dev/null
@@ -1 +0,0 @@
-{"license": "MIT license", "name": "pluggy", "metadata_version": "2.0", "generator": "bdist_wheel (0.24.0)", "summary": "plugin and hook calling mechanisms for python", "platform": "unix", "version": "0.3.1", "extensions": {"python.details": {"document_names": {"description": "DESCRIPTION.rst"}, "contacts": [{"role": "author", "email": "holger at merlinux.eu", "name": "Holger Krekel"}]}}, "classifiers": ["Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: POSIX", "Operating System :: Microsoft :: Windows", "Operating System :: MacOS :: MacOS X", "Topic :: Software Development :: Testing", "Topic :: Software Development :: Libraries", "Topic :: Utilities", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5"]} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/pbr.json b/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/pbr.json
deleted file mode 100644
index d6b79864019..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/pbr.json
+++ /dev/null
@@ -1 +0,0 @@
-{"is_release": false, "git_version": "7d4c9cd"} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/top_level.txt b/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/top_level.txt
deleted file mode 100644
index 11bdb5c1f5f..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/top_level.txt
+++ /dev/null
@@ -1 +0,0 @@
-pluggy
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy.py b/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy.py
deleted file mode 100644
index 2f848b23d35..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy.py
+++ /dev/null
@@ -1,777 +0,0 @@
-"""
-PluginManager, basic initialization and tracing.
-
-pluggy is the cristallized core of plugin management as used
-by some 150 plugins for pytest.
-
-Pluggy uses semantic versioning. Breaking changes are only foreseen for
-Major releases (incremented X in "X.Y.Z"). If you want to use pluggy in
-your project you should thus use a dependency restriction like
-"pluggy>=0.1.0,<1.0" to avoid surprises.
-
-pluggy is concerned with hook specification, hook implementations and hook
-calling. For any given hook specification a hook call invokes up to N implementations.
-A hook implementation can influence its position and type of execution:
-if attributed "tryfirst" or "trylast" it will be tried to execute
-first or last. However, if attributed "hookwrapper" an implementation
-can wrap all calls to non-hookwrapper implementations. A hookwrapper
-can thus execute some code ahead and after the execution of other hooks.
-
-Hook specification is done by way of a regular python function where
-both the function name and the names of all its arguments are significant.
-Each hook implementation function is verified against the original specification
-function, including the names of all its arguments. To allow for hook specifications
-to evolve over the livetime of a project, hook implementations can
-accept less arguments. One can thus add new arguments and semantics to
-a hook specification by adding another argument typically without breaking
-existing hook implementations.
-
-The chosen approach is meant to let a hook designer think carefuly about
-which objects are needed by an extension writer. By contrast, subclass-based
-extension mechanisms often expose a lot more state and behaviour than needed,
-thus restricting future developments.
-
-Pluggy currently consists of functionality for:
-
-- a way to register new hook specifications. Without a hook
- specification no hook calling can be performed.
-
-- a registry of plugins which contain hook implementation functions. It
- is possible to register plugins for which a hook specification is not yet
- known and validate all hooks when the system is in a more referentially
- consistent state. Setting an "optionalhook" attribution to a hook
- implementation will avoid PluginValidationError's if a specification
- is missing. This allows to have optional integration between plugins.
-
-- a "hook" relay object from which you can launch 1:N calls to
- registered hook implementation functions
-
-- a mechanism for ordering hook implementation functions
-
-- mechanisms for two different type of 1:N calls: "firstresult" for when
- the call should stop when the first implementation returns a non-None result.
- And the other (default) way of guaranteeing that all hook implementations
- will be called and their non-None result collected.
-
-- mechanisms for "historic" extension points such that all newly
- registered functions will receive all hook calls that happened
- before their registration.
-
-- a mechanism for discovering plugin objects which are based on
- setuptools based entry points.
-
-- a simple tracing mechanism, including tracing of plugin calls and
- their arguments.
-
-"""
-import sys
-import inspect
-
-__version__ = '0.3.1'
-__all__ = ["PluginManager", "PluginValidationError",
- "HookspecMarker", "HookimplMarker"]
-
-_py3 = sys.version_info > (3, 0)
-
-
-class HookspecMarker:
- """ Decorator helper class for marking functions as hook specifications.
-
- You can instantiate it with a project_name to get a decorator.
- Calling PluginManager.add_hookspecs later will discover all marked functions
- if the PluginManager uses the same project_name.
- """
-
- def __init__(self, project_name):
- self.project_name = project_name
-
- def __call__(self, function=None, firstresult=False, historic=False):
- """ if passed a function, directly sets attributes on the function
- which will make it discoverable to add_hookspecs(). If passed no
- function, returns a decorator which can be applied to a function
- later using the attributes supplied.
-
- If firstresult is True the 1:N hook call (N being the number of registered
- hook implementation functions) will stop at I<=N when the I'th function
- returns a non-None result.
-
- If historic is True calls to a hook will be memorized and replayed
- on later registered plugins.
-
- """
- def setattr_hookspec_opts(func):
- if historic and firstresult:
- raise ValueError("cannot have a historic firstresult hook")
- setattr(func, self.project_name + "_spec",
- dict(firstresult=firstresult, historic=historic))
- return func
-
- if function is not None:
- return setattr_hookspec_opts(function)
- else:
- return setattr_hookspec_opts
-
-
-class HookimplMarker:
- """ Decorator helper class for marking functions as hook implementations.
-
- You can instantiate with a project_name to get a decorator.
- Calling PluginManager.register later will discover all marked functions
- if the PluginManager uses the same project_name.
- """
- def __init__(self, project_name):
- self.project_name = project_name
-
- def __call__(self, function=None, hookwrapper=False, optionalhook=False,
- tryfirst=False, trylast=False):
-
- """ if passed a function, directly sets attributes on the function
- which will make it discoverable to register(). If passed no function,
- returns a decorator which can be applied to a function later using
- the attributes supplied.
-
- If optionalhook is True a missing matching hook specification will not result
- in an error (by default it is an error if no matching spec is found).
-
- If tryfirst is True this hook implementation will run as early as possible
- in the chain of N hook implementations for a specfication.
-
- If trylast is True this hook implementation will run as late as possible
- in the chain of N hook implementations.
-
- If hookwrapper is True the hook implementations needs to execute exactly
- one "yield". The code before the yield is run early before any non-hookwrapper
- function is run. The code after the yield is run after all non-hookwrapper
- function have run. The yield receives an ``_CallOutcome`` object representing
- the exception or result outcome of the inner calls (including other hookwrapper
- calls).
-
- """
- def setattr_hookimpl_opts(func):
- setattr(func, self.project_name + "_impl",
- dict(hookwrapper=hookwrapper, optionalhook=optionalhook,
- tryfirst=tryfirst, trylast=trylast))
- return func
-
- if function is None:
- return setattr_hookimpl_opts
- else:
- return setattr_hookimpl_opts(function)
-
-
-def normalize_hookimpl_opts(opts):
- opts.setdefault("tryfirst", False)
- opts.setdefault("trylast", False)
- opts.setdefault("hookwrapper", False)
- opts.setdefault("optionalhook", False)
-
-
-class _TagTracer:
- def __init__(self):
- self._tag2proc = {}
- self.writer = None
- self.indent = 0
-
- def get(self, name):
- return _TagTracerSub(self, (name,))
-
- def format_message(self, tags, args):
- if isinstance(args[-1], dict):
- extra = args[-1]
- args = args[:-1]
- else:
- extra = {}
-
- content = " ".join(map(str, args))
- indent = " " * self.indent
-
- lines = [
- "%s%s [%s]\n" % (indent, content, ":".join(tags))
- ]
-
- for name, value in extra.items():
- lines.append("%s %s: %s\n" % (indent, name, value))
- return lines
-
- def processmessage(self, tags, args):
- if self.writer is not None and args:
- lines = self.format_message(tags, args)
- self.writer(''.join(lines))
- try:
- self._tag2proc[tags](tags, args)
- except KeyError:
- pass
-
- def setwriter(self, writer):
- self.writer = writer
-
- def setprocessor(self, tags, processor):
- if isinstance(tags, str):
- tags = tuple(tags.split(":"))
- else:
- assert isinstance(tags, tuple)
- self._tag2proc[tags] = processor
-
-
-class _TagTracerSub:
- def __init__(self, root, tags):
- self.root = root
- self.tags = tags
-
- def __call__(self, *args):
- self.root.processmessage(self.tags, args)
-
- def setmyprocessor(self, processor):
- self.root.setprocessor(self.tags, processor)
-
- def get(self, name):
- return self.__class__(self.root, self.tags + (name,))
-
-
-def _raise_wrapfail(wrap_controller, msg):
- co = wrap_controller.gi_code
- raise RuntimeError("wrap_controller at %r %s:%d %s" %
- (co.co_name, co.co_filename, co.co_firstlineno, msg))
-
-
-def _wrapped_call(wrap_controller, func):
- """ Wrap calling to a function with a generator which needs to yield
- exactly once. The yield point will trigger calling the wrapped function
- and return its _CallOutcome to the yield point. The generator then needs
- to finish (raise StopIteration) in order for the wrapped call to complete.
- """
- try:
- next(wrap_controller) # first yield
- except StopIteration:
- _raise_wrapfail(wrap_controller, "did not yield")
- call_outcome = _CallOutcome(func)
- try:
- wrap_controller.send(call_outcome)
- _raise_wrapfail(wrap_controller, "has second yield")
- except StopIteration:
- pass
- return call_outcome.get_result()
-
-
-class _CallOutcome:
- """ Outcome of a function call, either an exception or a proper result.
- Calling the ``get_result`` method will return the result or reraise
- the exception raised when the function was called. """
- excinfo = None
-
- def __init__(self, func):
- try:
- self.result = func()
- except BaseException:
- self.excinfo = sys.exc_info()
-
- def force_result(self, result):
- self.result = result
- self.excinfo = None
-
- def get_result(self):
- if self.excinfo is None:
- return self.result
- else:
- ex = self.excinfo
- if _py3:
- raise ex[1].with_traceback(ex[2])
- _reraise(*ex) # noqa
-
-if not _py3:
- exec("""
-def _reraise(cls, val, tb):
- raise cls, val, tb
-""")
-
-
-class _TracedHookExecution:
- def __init__(self, pluginmanager, before, after):
- self.pluginmanager = pluginmanager
- self.before = before
- self.after = after
- self.oldcall = pluginmanager._inner_hookexec
- assert not isinstance(self.oldcall, _TracedHookExecution)
- self.pluginmanager._inner_hookexec = self
-
- def __call__(self, hook, hook_impls, kwargs):
- self.before(hook.name, hook_impls, kwargs)
- outcome = _CallOutcome(lambda: self.oldcall(hook, hook_impls, kwargs))
- self.after(outcome, hook.name, hook_impls, kwargs)
- return outcome.get_result()
-
- def undo(self):
- self.pluginmanager._inner_hookexec = self.oldcall
-
-
-class PluginManager(object):
- """ Core Pluginmanager class which manages registration
- of plugin objects and 1:N hook calling.
-
- You can register new hooks by calling ``addhooks(module_or_class)``.
- You can register plugin objects (which contain hooks) by calling
- ``register(plugin)``. The Pluginmanager is initialized with a
- prefix that is searched for in the names of the dict of registered
- plugin objects. An optional excludefunc allows to blacklist names which
- are not considered as hooks despite a matching prefix.
-
- For debugging purposes you can call ``enable_tracing()``
- which will subsequently send debug information to the trace helper.
- """
-
- def __init__(self, project_name, implprefix=None):
- """ if implprefix is given implementation functions
- will be recognized if their name matches the implprefix. """
- self.project_name = project_name
- self._name2plugin = {}
- self._plugin2hookcallers = {}
- self._plugin_distinfo = []
- self.trace = _TagTracer().get("pluginmanage")
- self.hook = _HookRelay(self.trace.root.get("hook"))
- self._implprefix = implprefix
- self._inner_hookexec = lambda hook, methods, kwargs: \
- _MultiCall(methods, kwargs, hook.spec_opts).execute()
-
- def _hookexec(self, hook, methods, kwargs):
- # called from all hookcaller instances.
- # enable_tracing will set its own wrapping function at self._inner_hookexec
- return self._inner_hookexec(hook, methods, kwargs)
-
- def register(self, plugin, name=None):
- """ Register a plugin and return its canonical name or None if the name
- is blocked from registering. Raise a ValueError if the plugin is already
- registered. """
- plugin_name = name or self.get_canonical_name(plugin)
-
- if plugin_name in self._name2plugin or plugin in self._plugin2hookcallers:
- if self._name2plugin.get(plugin_name, -1) is None:
- return # blocked plugin, return None to indicate no registration
- raise ValueError("Plugin already registered: %s=%s\n%s" %
- (plugin_name, plugin, self._name2plugin))
-
- # XXX if an error happens we should make sure no state has been
- # changed at point of return
- self._name2plugin[plugin_name] = plugin
-
- # register matching hook implementations of the plugin
- self._plugin2hookcallers[plugin] = hookcallers = []
- for name in dir(plugin):
- hookimpl_opts = self.parse_hookimpl_opts(plugin, name)
- if hookimpl_opts is not None:
- normalize_hookimpl_opts(hookimpl_opts)
- method = getattr(plugin, name)
- hookimpl = HookImpl(plugin, plugin_name, method, hookimpl_opts)
- hook = getattr(self.hook, name, None)
- if hook is None:
- hook = _HookCaller(name, self._hookexec)
- setattr(self.hook, name, hook)
- elif hook.has_spec():
- self._verify_hook(hook, hookimpl)
- hook._maybe_apply_history(hookimpl)
- hook._add_hookimpl(hookimpl)
- hookcallers.append(hook)
- return plugin_name
-
- def parse_hookimpl_opts(self, plugin, name):
- method = getattr(plugin, name)
- res = getattr(method, self.project_name + "_impl", None)
- if res is not None and not isinstance(res, dict):
- # false positive
- res = None
- elif res is None and self._implprefix and name.startswith(self._implprefix):
- res = {}
- return res
-
- def unregister(self, plugin=None, name=None):
- """ unregister a plugin object and all its contained hook implementations
- from internal data structures. """
- if name is None:
- assert plugin is not None, "one of name or plugin needs to be specified"
- name = self.get_name(plugin)
-
- if plugin is None:
- plugin = self.get_plugin(name)
-
- # if self._name2plugin[name] == None registration was blocked: ignore
- if self._name2plugin.get(name):
- del self._name2plugin[name]
-
- for hookcaller in self._plugin2hookcallers.pop(plugin, []):
- hookcaller._remove_plugin(plugin)
-
- return plugin
-
- def set_blocked(self, name):
- """ block registrations of the given name, unregister if already registered. """
- self.unregister(name=name)
- self._name2plugin[name] = None
-
- def is_blocked(self, name):
- """ return True if the name blogs registering plugins of that name. """
- return name in self._name2plugin and self._name2plugin[name] is None
-
- def add_hookspecs(self, module_or_class):
- """ add new hook specifications defined in the given module_or_class.
- Functions are recognized if they have been decorated accordingly. """
- names = []
- for name in dir(module_or_class):
- spec_opts = self.parse_hookspec_opts(module_or_class, name)
- if spec_opts is not None:
- hc = getattr(self.hook, name, None)
- if hc is None:
- hc = _HookCaller(name, self._hookexec, module_or_class, spec_opts)
- setattr(self.hook, name, hc)
- else:
- # plugins registered this hook without knowing the spec
- hc.set_specification(module_or_class, spec_opts)
- for hookfunction in (hc._wrappers + hc._nonwrappers):
- self._verify_hook(hc, hookfunction)
- names.append(name)
-
- if not names:
- raise ValueError("did not find any %r hooks in %r" %
- (self.project_name, module_or_class))
-
- def parse_hookspec_opts(self, module_or_class, name):
- method = getattr(module_or_class, name)
- return getattr(method, self.project_name + "_spec", None)
-
- def get_plugins(self):
- """ return the set of registered plugins. """
- return set(self._plugin2hookcallers)
-
- def is_registered(self, plugin):
- """ Return True if the plugin is already registered. """
- return plugin in self._plugin2hookcallers
-
- def get_canonical_name(self, plugin):
- """ Return canonical name for a plugin object. Note that a plugin
- may be registered under a different name which was specified
- by the caller of register(plugin, name). To obtain the name
- of an registered plugin use ``get_name(plugin)`` instead."""
- return getattr(plugin, "__name__", None) or str(id(plugin))
-
- def get_plugin(self, name):
- """ Return a plugin or None for the given name. """
- return self._name2plugin.get(name)
-
- def get_name(self, plugin):
- """ Return name for registered plugin or None if not registered. """
- for name, val in self._name2plugin.items():
- if plugin == val:
- return name
-
- def _verify_hook(self, hook, hookimpl):
- if hook.is_historic() and hookimpl.hookwrapper:
- raise PluginValidationError(
- "Plugin %r\nhook %r\nhistoric incompatible to hookwrapper" %
- (hookimpl.plugin_name, hook.name))
-
- for arg in hookimpl.argnames:
- if arg not in hook.argnames:
- raise PluginValidationError(
- "Plugin %r\nhook %r\nargument %r not available\n"
- "plugin definition: %s\n"
- "available hookargs: %s" %
- (hookimpl.plugin_name, hook.name, arg,
- _formatdef(hookimpl.function), ", ".join(hook.argnames)))
-
- def check_pending(self):
- """ Verify that all hooks which have not been verified against
- a hook specification are optional, otherwise raise PluginValidationError"""
- for name in self.hook.__dict__:
- if name[0] != "_":
- hook = getattr(self.hook, name)
- if not hook.has_spec():
- for hookimpl in (hook._wrappers + hook._nonwrappers):
- if not hookimpl.optionalhook:
- raise PluginValidationError(
- "unknown hook %r in plugin %r" %
- (name, hookimpl.plugin))
-
- def load_setuptools_entrypoints(self, entrypoint_name):
- """ Load modules from querying the specified setuptools entrypoint name.
- Return the number of loaded plugins. """
- from pkg_resources import iter_entry_points, DistributionNotFound
- for ep in iter_entry_points(entrypoint_name):
- # is the plugin registered or blocked?
- if self.get_plugin(ep.name) or self.is_blocked(ep.name):
- continue
- try:
- plugin = ep.load()
- except DistributionNotFound:
- continue
- self.register(plugin, name=ep.name)
- self._plugin_distinfo.append((plugin, ep.dist))
- return len(self._plugin_distinfo)
-
- def list_plugin_distinfo(self):
- """ return list of distinfo/plugin tuples for all setuptools registered
- plugins. """
- return list(self._plugin_distinfo)
-
- def list_name_plugin(self):
- """ return list of name/plugin pairs. """
- return list(self._name2plugin.items())
-
- def get_hookcallers(self, plugin):
- """ get all hook callers for the specified plugin. """
- return self._plugin2hookcallers.get(plugin)
-
- def add_hookcall_monitoring(self, before, after):
- """ add before/after tracing functions for all hooks
- and return an undo function which, when called,
- will remove the added tracers.
-
- ``before(hook_name, hook_impls, kwargs)`` will be called ahead
- of all hook calls and receive a hookcaller instance, a list
- of HookImpl instances and the keyword arguments for the hook call.
-
- ``after(outcome, hook_name, hook_impls, kwargs)`` receives the
- same arguments as ``before`` but also a :py:class:`_CallOutcome`` object
- which represents the result of the overall hook call.
- """
- return _TracedHookExecution(self, before, after).undo
-
- def enable_tracing(self):
- """ enable tracing of hook calls and return an undo function. """
- hooktrace = self.hook._trace
-
- def before(hook_name, methods, kwargs):
- hooktrace.root.indent += 1
- hooktrace(hook_name, kwargs)
-
- def after(outcome, hook_name, methods, kwargs):
- if outcome.excinfo is None:
- hooktrace("finish", hook_name, "-->", outcome.result)
- hooktrace.root.indent -= 1
-
- return self.add_hookcall_monitoring(before, after)
-
- def subset_hook_caller(self, name, remove_plugins):
- """ Return a new _HookCaller instance for the named method
- which manages calls to all registered plugins except the
- ones from remove_plugins. """
- orig = getattr(self.hook, name)
- plugins_to_remove = [plug for plug in remove_plugins if hasattr(plug, name)]
- if plugins_to_remove:
- hc = _HookCaller(orig.name, orig._hookexec, orig._specmodule_or_class,
- orig.spec_opts)
- for hookimpl in (orig._wrappers + orig._nonwrappers):
- plugin = hookimpl.plugin
- if plugin not in plugins_to_remove:
- hc._add_hookimpl(hookimpl)
- # we also keep track of this hook caller so it
- # gets properly removed on plugin unregistration
- self._plugin2hookcallers.setdefault(plugin, []).append(hc)
- return hc
- return orig
-
-
-class _MultiCall:
- """ execute a call into multiple python functions/methods. """
-
- # XXX note that the __multicall__ argument is supported only
- # for pytest compatibility reasons. It was never officially
- # supported there and is explicitly deprecated since 2.8
- # so we can remove it soon, allowing to avoid the below recursion
- # in execute() and simplify/speed up the execute loop.
-
- def __init__(self, hook_impls, kwargs, specopts={}):
- self.hook_impls = hook_impls
- self.kwargs = kwargs
- self.kwargs["__multicall__"] = self
- self.specopts = specopts
-
- def execute(self):
- all_kwargs = self.kwargs
- self.results = results = []
- firstresult = self.specopts.get("firstresult")
-
- while self.hook_impls:
- hook_impl = self.hook_impls.pop()
- args = [all_kwargs[argname] for argname in hook_impl.argnames]
- if hook_impl.hookwrapper:
- return _wrapped_call(hook_impl.function(*args), self.execute)
- res = hook_impl.function(*args)
- if res is not None:
- if firstresult:
- return res
- results.append(res)
-
- if not firstresult:
- return results
-
- def __repr__(self):
- status = "%d meths" % (len(self.hook_impls),)
- if hasattr(self, "results"):
- status = ("%d results, " % len(self.results)) + status
- return "<_MultiCall %s, kwargs=%r>" % (status, self.kwargs)
-
-
-def varnames(func, startindex=None):
- """ return argument name tuple for a function, method, class or callable.
-
- In case of a class, its "__init__" method is considered.
- For methods the "self" parameter is not included unless you are passing
- an unbound method with Python3 (which has no supports for unbound methods)
- """
- cache = getattr(func, "__dict__", {})
- try:
- return cache["_varnames"]
- except KeyError:
- pass
- if inspect.isclass(func):
- try:
- func = func.__init__
- except AttributeError:
- return ()
- startindex = 1
- else:
- if not inspect.isfunction(func) and not inspect.ismethod(func):
- func = getattr(func, '__call__', func)
- if startindex is None:
- startindex = int(inspect.ismethod(func))
-
- try:
- rawcode = func.__code__
- except AttributeError:
- return ()
- try:
- x = rawcode.co_varnames[startindex:rawcode.co_argcount]
- except AttributeError:
- x = ()
- else:
- defaults = func.__defaults__
- if defaults:
- x = x[:-len(defaults)]
- try:
- cache["_varnames"] = x
- except TypeError:
- pass
- return x
-
-
-class _HookRelay:
- """ hook holder object for performing 1:N hook calls where N is the number
- of registered plugins.
-
- """
-
- def __init__(self, trace):
- self._trace = trace
-
-
-class _HookCaller(object):
- def __init__(self, name, hook_execute, specmodule_or_class=None, spec_opts=None):
- self.name = name
- self._wrappers = []
- self._nonwrappers = []
- self._hookexec = hook_execute
- if specmodule_or_class is not None:
- assert spec_opts is not None
- self.set_specification(specmodule_or_class, spec_opts)
-
- def has_spec(self):
- return hasattr(self, "_specmodule_or_class")
-
- def set_specification(self, specmodule_or_class, spec_opts):
- assert not self.has_spec()
- self._specmodule_or_class = specmodule_or_class
- specfunc = getattr(specmodule_or_class, self.name)
- argnames = varnames(specfunc, startindex=inspect.isclass(specmodule_or_class))
- assert "self" not in argnames # sanity check
- self.argnames = ["__multicall__"] + list(argnames)
- self.spec_opts = spec_opts
- if spec_opts.get("historic"):
- self._call_history = []
-
- def is_historic(self):
- return hasattr(self, "_call_history")
-
- def _remove_plugin(self, plugin):
- def remove(wrappers):
- for i, method in enumerate(wrappers):
- if method.plugin == plugin:
- del wrappers[i]
- return True
- if remove(self._wrappers) is None:
- if remove(self._nonwrappers) is None:
- raise ValueError("plugin %r not found" % (plugin,))
-
- def _add_hookimpl(self, hookimpl):
- if hookimpl.hookwrapper:
- methods = self._wrappers
- else:
- methods = self._nonwrappers
-
- if hookimpl.trylast:
- methods.insert(0, hookimpl)
- elif hookimpl.tryfirst:
- methods.append(hookimpl)
- else:
- # find last non-tryfirst method
- i = len(methods) - 1
- while i >= 0 and methods[i].tryfirst:
- i -= 1
- methods.insert(i + 1, hookimpl)
-
- def __repr__(self):
- return "<_HookCaller %r>" % (self.name,)
-
- def __call__(self, **kwargs):
- assert not self.is_historic()
- return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs)
-
- def call_historic(self, proc=None, kwargs=None):
- self._call_history.append((kwargs or {}, proc))
- # historizing hooks don't return results
- self._hookexec(self, self._nonwrappers + self._wrappers, kwargs)
-
- def call_extra(self, methods, kwargs):
- """ Call the hook with some additional temporarily participating
- methods using the specified kwargs as call parameters. """
- old = list(self._nonwrappers), list(self._wrappers)
- for method in methods:
- opts = dict(hookwrapper=False, trylast=False, tryfirst=False)
- hookimpl = HookImpl(None, "<temp>", method, opts)
- self._add_hookimpl(hookimpl)
- try:
- return self(**kwargs)
- finally:
- self._nonwrappers, self._wrappers = old
-
- def _maybe_apply_history(self, method):
- if self.is_historic():
- for kwargs, proc in self._call_history:
- res = self._hookexec(self, [method], kwargs)
- if res and proc is not None:
- proc(res[0])
-
-
-class HookImpl:
- def __init__(self, plugin, plugin_name, function, hook_impl_opts):
- self.function = function
- self.argnames = varnames(self.function)
- self.plugin = plugin
- self.opts = hook_impl_opts
- self.plugin_name = plugin_name
- self.__dict__.update(hook_impl_opts)
-
-
-class PluginValidationError(Exception):
- """ plugin failed validation. """
-
-
-if hasattr(inspect, 'signature'):
- def _formatdef(func):
- return "%s%s" % (
- func.__name__,
- str(inspect.signature(func))
- )
-else:
- def _formatdef(func):
- return "%s%s" % (
- func.__name__,
- inspect.formatargspec(*inspect.getargspec(func))
- )
diff --git a/tests/wpt/web-platform-tests/tools/pytest/appveyor.yml b/tests/wpt/web-platform-tests/tools/pytest/appveyor.yml
deleted file mode 100644
index 4b73645f735..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/appveyor.yml
+++ /dev/null
@@ -1,28 +0,0 @@
-environment:
- COVERALLS_REPO_TOKEN:
- secure: 2NJ5Ct55cHJ9WEg3xbSqCuv0rdgzzb6pnzOIG5OkMbTndw3wOBrXntWFoQrXiMFi
- # this is pytest's token in coveralls.io, encrypted
- # using pytestbot account as detailed here:
- # https://www.appveyor.com/docs/build-configuration#secure-variables
-
-install:
- - echo Installed Pythons
- - dir c:\Python*
-
- # install pypy using choco (redirect to a file and write to console in case
- # choco install returns non-zero, because choco install python.pypy is too
- # noisy)
- - choco install python.pypy > pypy-inst.log 2>&1 || (type pypy-inst.log & exit /b 1)
- - set PATH=C:\tools\pypy\pypy;%PATH% # so tox can find pypy
- - echo PyPy installed
- - pypy --version
-
- - C:\Python35\python -m pip install tox
-
-build: false # Not a C# project, build stuff at the test step instead.
-
-test_script:
- - C:\Python35\python -m tox
- # coveralls is not in tox's envlist, plus for PRs the secure variable
- # is not defined so we have to check for it
- - if defined COVERALLS_REPO_TOKEN C:\Python35\python -m tox -e coveralls
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/Makefile b/tests/wpt/web-platform-tests/tools/pytest/doc/en/Makefile
deleted file mode 100644
index 8621f779c70..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/Makefile
+++ /dev/null
@@ -1,164 +0,0 @@
-# Makefile for Sphinx documentation
-#
-
-# You can set these variables from the command line.
-SPHINXOPTS =
-SPHINXBUILD = sphinx-build
-PAPER =
-BUILDDIR = _build
-
-# Internal variables.
-PAPEROPT_a4 = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
-ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
-
-REGENDOC_ARGS := \
- --normalize "/={8,} (.*) ={8,}/======= \1 ========/" \
- --normalize "/_{8,} (.*) _{8,}/_______ \1 ________/" \
- --normalize "/in \d+.\d+ seconds/in 0.12 seconds/" \
- --normalize "@/tmp/pytest-of-.*/pytest-\d+@PYTEST_TMPDIR@" \
-
-
-
-.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
-
-
-help:
- @echo "Please use \`make <target>' where <target> is one of"
- @echo " html to make standalone HTML files"
- @echo " latexpdf to make LaTeX files and run them through pdflatex"
- @echo " showtarget to show the pytest.org target directory"
- @echo " install to install docs to pytest.org/SITETARGET"
- @echo " install-ldf to install the doc pdf to pytest.org/SITETARGET"
- @echo " regen to regenerate pytest examples using the installed pytest"
- @echo " linkcheck to check all external links for integrity"
-
-clean:
- -rm -rf $(BUILDDIR)/*
-
-SITETARGET=$(shell ./_getdoctarget.py)
-
-showtarget:
- @echo $(SITETARGET)
-
-install: html
- # for access talk to someone with login rights to
- # pytest-dev@pytest.org to add your ssh key
- rsync -avz _build/html/ pytest-dev@pytest.org:pytest.org/$(SITETARGET)
-
-installpdf: latexpdf
- @scp $(BUILDDIR)/latex/pytest.pdf pytest-dev@pytest.org:pytest.org/$(SITETARGET)
-
-installall: clean install installpdf
- @echo "done"
-
-regen:
- PYTHONDONTWRITEBYTECODE=1 COLUMNS=76 regendoc --update *.rst */*.rst ${REGENDOC_ARGS}
-
-html:
- $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
- @echo
- @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
-
-dirhtml:
- $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
- @echo
- @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
-
-singlehtml:
- $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
- @echo
- @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
-
-pickle:
- $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
- @echo
- @echo "Build finished; now you can process the pickle files."
-
-json:
- $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
- @echo
- @echo "Build finished; now you can process the JSON files."
-
-htmlhelp:
- $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
- @echo
- @echo "Build finished; now you can run HTML Help Workshop with the" \
- ".hhp project file in $(BUILDDIR)/htmlhelp."
-
-qthelp:
- $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
- @echo
- @echo "Build finished; now you can run "qcollectiongenerator" with the" \
- ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
- @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pytest.qhcp"
- @echo "To view the help file:"
- @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pytest.qhc"
-
-devhelp:
- $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
- @echo
- @echo "Build finished."
- @echo "To view the help file:"
- @echo "# mkdir -p $$HOME/.local/share/devhelp/pytest"
- @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pytest"
- @echo "# devhelp"
-
-epub:
- $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
- @echo
- @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
-
-latex:
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
- @echo
- @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
- @echo "Run \`make' in that directory to run these through (pdf)latex" \
- "(use \`make latexpdf' here to do that automatically)."
-
-latexpdf:
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
- @echo "Running LaTeX files through pdflatex..."
- make -C $(BUILDDIR)/latex all-pdf
- @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
-
-text:
- $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
- @echo
- @echo "Build finished. The text files are in $(BUILDDIR)/text."
-
-man:
- $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
- @echo
- @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
-
-changes:
- $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
- @echo
- @echo "The overview file is in $(BUILDDIR)/changes."
-
-linkcheck:
- $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
- @echo
- @echo "Link check complete; look for any errors in the above output " \
- "or in $(BUILDDIR)/linkcheck/output.txt."
-
-doctest:
- $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
- @echo "Testing of doctests in the sources finished, look at the " \
- "results in $(BUILDDIR)/doctest/output.txt."
-
-texinfo:
- mkdir -p $(BUILDDIR)/texinfo
- $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
- @echo
- @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
- @echo "Run \`make' in that directory to run these through makeinfo" \
- "(use \`make info' here to do that automatically)."
-
-info:
- mkdir -p $(BUILDDIR)/texinfo
- $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
- @echo "Running Texinfo files through makeinfo..."
- make -C $(BUILDDIR)/texinfo info
- @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/_getdoctarget.py b/tests/wpt/web-platform-tests/tools/pytest/doc/en/_getdoctarget.py
deleted file mode 100755
index 20e487bb738..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/_getdoctarget.py
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env python
-
-import py
-
-def get_version_string():
- fn = py.path.local(__file__).join("..", "..", "..",
- "_pytest", "__init__.py")
- for line in fn.readlines():
- if "version" in line and not line.strip().startswith('#'):
- return eval(line.split("=")[-1])
-
-def get_minor_version_string():
- return ".".join(get_version_string().split(".")[:2])
-
-if __name__ == "__main__":
- print (get_minor_version_string())
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/_templates/globaltoc.html b/tests/wpt/web-platform-tests/tools/pytest/doc/en/_templates/globaltoc.html
deleted file mode 100644
index af427198a62..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/_templates/globaltoc.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<h3><a href="{{ pathto(master_doc) }}">{{ _('Table Of Contents') }}</a></h3>
-
-<ul>
- <li><a href="{{ pathto('index') }}">Home</a></li>
- <li><a href="{{ pathto('contents') }}">Contents</a></li>
- <li><a href="{{ pathto('getting-started') }}">Install</a></li>
- <li><a href="{{ pathto('example/index') }}">Examples</a></li>
- <li><a href="{{ pathto('customize') }}">Customize</a></li>
- <li><a href="{{ pathto('contact') }}">Contact</a></li>
- <li><a href="{{ pathto('talks') }}">Talks/Posts</a></li>
- <li><a href="{{ pathto('changelog') }}">Changelog</a></li>
- <li><a href="{{ pathto('license') }}">License</a></li>
-</ul>
-
-{%- if display_toc %}
- <hr>
- {{ toc }}
-{%- endif %}
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/_templates/layout.html b/tests/wpt/web-platform-tests/tools/pytest/doc/en/_templates/layout.html
deleted file mode 100644
index 0ce480be300..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/_templates/layout.html
+++ /dev/null
@@ -1,34 +0,0 @@
-{% extends "!layout.html" %}
-{% block header %}
-<div align="center" xmlns="http://www.w3.org/1999/html" style="background-color: lightgreen; padding: .5em">
- <h4>
- Want to help improve pytest? Please
- <a href="https://www.indiegogo.com/projects/python-testing-sprint-mid-2016#/">
- contribute to
- </a>
- or
- <a href="announce/sprint2016.html">
- join
- </a>
- our upcoming sprint in June 2016!
-
- </h4>
-</div>
- {{super()}}
-{% endblock %}
-{% block footer %}
-{{ super() }}
-<script type="text/javascript">
-
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-7597274-13']);
- _gaq.push(['_trackPageview']);
-
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-
-</script>
-{% endblock %}
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/_templates/links.html b/tests/wpt/web-platform-tests/tools/pytest/doc/en/_templates/links.html
deleted file mode 100644
index 200258e165f..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/_templates/links.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<h3>Useful Links</h3>
-<ul>
- <li>
- <a href="https://www.indiegogo.com/projects/python-testing-sprint-mid-2016#/">
- <b>Sprint funding campaign</b>
- </a>
- </li>
- <li><a href="{{ pathto('index') }}">The pytest Website</a></li>
- <li><a href="{{ pathto('contributing') }}">Contribution Guide</a></li>
- <li><a href="https://pypi.python.org/pypi/pytest">pytest @ PyPI</a></li>
- <li><a href="https://github.com/pytest-dev/pytest/">pytest @ GitHub</a></li>
- <li><a href="http://plugincompat.herokuapp.com/">3rd party plugins</a></li>
- <li><a href="https://github.com/pytest-dev/pytest/issues">Issue Tracker</a></li>
- <li><a href="http://pytest.org/latest/pytest.pdf">PDF Documentation</a>
-</ul>
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/adopt.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/adopt.rst
deleted file mode 100644
index aead96e7f3d..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/adopt.rst
+++ /dev/null
@@ -1,78 +0,0 @@
-
-April 2015 is "adopt pytest month"
-=============================================
-
-Are you an enthusiastic pytest user, the local testing guru in your workplace? Or are you considering using pytest for your open source project, but not sure how to get started? Then you may be interested in "adopt pytest month"!
-
-We will pair experienced pytest users with open source projects, for a month's effort of getting new development teams started with pytest.
-
-In 2015 we are trying this for the first time. In February and March 2015 we will gather volunteers on both sides, in April we will do the work, and in May we will evaluate how it went. This effort is being coordinated by Brianna Laugher. If you have any questions or comments, you can raise them on the `@pytestdotorg twitter account <https://twitter.com/pytestdotorg>`_ the `issue tracker`_ or the `pytest-dev mailing list`_.
-
-
-.. _`issue tracker`: https://github.com/pytest-dev/pytest/issues/676
-.. _`pytest-dev mailing list`: https://mail.python.org/mailman/listinfo/pytest-dev
-
-
-The ideal pytest helper
------------------------------------------
-
- - will be able to commit 2-4 hours a week to working with their particular project (this might involve joining their mailing list, installing the software and exploring any existing tests, offering advice, writing some example tests)
- - feels confident in using pytest (e.g. has explored command line options, knows how to write parametrized tests, has an idea about conftest contents)
- - does not need to be an expert in every aspect!
-
-`Pytest helpers, sign up here`_! (preferably in February, hard deadline 22 March)
-
-
-.. _`Pytest helpers, sign up here`: http://goo.gl/forms/nxqAhqWt1P
-
-
-The ideal partner project
------------------------------------------
-
- - is open source, and predominantly written in Python
- - has an automated/documented install process for developers
- - has more than one core developer
- - has at least one official release (e.g. is available on pypi)
- - has the support of the core development team, in trying out pytest adoption
- - has no tests... or 100% test coverage... or somewhere in between!
-
-`Partner projects, sign up here`_! (by 22 March)
-
-
-.. _`Partner projects, sign up here`: http://goo.gl/forms/ZGyqlHiwk3
-
-
-What does it mean to "adopt pytest"?
------------------------------------------
-
-There can be many different definitions of "success". Pytest can run many `nose and unittest`_ tests by default, so using pytest as your testrunner may be possible from day 1. Job done, right?
-
-Progressive success might look like:
-
- - tests can be run (by pytest) without errors (there may be failures)
- - tests can be run (by pytest) without failures
- - test runner is integrated into CI server
- - existing tests are rewritten to take advantage of pytest features - this can happen in several iterations, for example:
- - changing to native assert_ statements (pycmd_ has a script to help with that, ``pyconvert_unittest.py``)
- - changing `setUp/tearDown methods`_ to fixtures_
- - adding markers_
- - other changes to reduce boilerplate
- - assess needs for future tests to be written, e.g. new fixtures, distributed_ testing tweaks
-
-"Success" should also include that the development team feels comfortable with their knowledge of how to use pytest. In fact this is probably more important than anything else. So spending a lot of time on communication, giving examples, etc will probably be important - both in running the tests, and in writing them.
-
-It may be after the month is up, the partner project decides that pytest is not right for it. That's okay - hopefully the pytest team will also learn something about its weaknesses or deficiencies.
-
-.. _`nose and unittest`: faq.html#how-does-pytest-relate-to-nose-and-unittest
-.. _assert: asserts.html
-.. _pycmd: https://bitbucket.org/hpk42/pycmd/overview
-.. _`setUp/tearDown methods`: xunit_setup.html
-.. _fixtures: fixture.html
-.. _markers: markers.html
-.. _distributed: xdist.html
-
-
-Other ways to help
------------------------------------------
-
-Promote! Do your favourite open source Python projects use pytest? If not, why not tell them about this page?
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/index.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/index.rst
deleted file mode 100644
index 877afff7777..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/index.rst
+++ /dev/null
@@ -1,48 +0,0 @@
-
-Release announcements
-===========================================
-
-.. toctree::
- :maxdepth: 2
-
-
- sprint2016
- release-2.9.0
- release-2.8.7
- release-2.8.6
- release-2.8.5
- release-2.8.4
- release-2.8.3
- release-2.8.2
- release-2.7.2
- release-2.7.1
- release-2.7.0
- release-2.6.3
- release-2.6.2
- release-2.6.1
- release-2.6.0
- release-2.5.2
- release-2.5.1
- release-2.5.0
- release-2.4.2
- release-2.4.1
- release-2.4.0
- release-2.3.5
- release-2.3.4
- release-2.3.3
- release-2.3.2
- release-2.3.1
- release-2.3.0
- release-2.2.4
- release-2.2.2
- release-2.2.1
- release-2.2.0
- release-2.1.3
- release-2.1.2
- release-2.1.1
- release-2.1.0
- release-2.0.3
- release-2.0.2
- release-2.0.1
- release-2.0.0
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.0.2.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.0.2.rst
deleted file mode 100644
index 733a9f7bdd8..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.0.2.rst
+++ /dev/null
@@ -1,73 +0,0 @@
-py.test 2.0.2: bug fixes, improved xfail/skip expressions, speed ups
-===========================================================================
-
-Welcome to pytest-2.0.2, a maintenance and bug fix release of pytest,
-a mature testing tool for Python, supporting CPython 2.4-3.2, Jython
-and latest PyPy interpreters. See the extensive docs with tested examples here:
-
- http://pytest.org/
-
-If you want to install or upgrade pytest, just type one of::
-
- pip install -U pytest # or
- easy_install -U pytest
-
-Many thanks to all issue reporters and people asking questions
-or complaining, particularly Jurko for his insistence,
-Laura, Victor and Brianna for helping with improving
-and Ronny for his general advise.
-
-best,
-holger krekel
-
-Changes between 2.0.1 and 2.0.2
-----------------------------------------------
-
-- tackle issue32 - speed up test runs of very quick test functions
- by reducing the relative overhead
-
-- fix issue30 - extended xfail/skipif handling and improved reporting.
- If you have a syntax error in your skip/xfail
- expressions you now get nice error reports.
-
- Also you can now access module globals from xfail/skipif
- expressions so that this for example works now::
-
- import pytest
- import mymodule
- @pytest.mark.skipif("mymodule.__version__[0] == "1")
- def test_function():
- pass
-
- This will not run the test function if the module's version string
- does not start with a "1". Note that specifying a string instead
- of a boolean expressions allows py.test to report meaningful information
- when summarizing a test run as to what conditions lead to skipping
- (or xfail-ing) tests.
-
-- fix issue28 - setup_method and pytest_generate_tests work together
- The setup_method fixture method now gets called also for
- test function invocations generated from the pytest_generate_tests
- hook.
-
-- fix issue27 - collectonly and keyword-selection (-k) now work together
- Also, if you do "py.test --collectonly -q" you now get a flat list
- of test ids that you can use to paste to the py.test commandline
- in order to execute a particular test.
-
-- fix issue25 avoid reported problems with --pdb and python3.2/encodings output
-
-- fix issue23 - tmpdir argument now works on Python3.2 and WindowsXP
- Starting with Python3.2 os.symlink may be supported. By requiring
- a newer py lib version the py.path.local() implementation acknowledges
- this.
-
-- fixed typos in the docs (thanks Victor Garcia, Brianna Laugher) and particular
- thanks to Laura Creighton who also revieved parts of the documentation.
-
-- fix slighly wrong output of verbose progress reporting for classes
- (thanks Amaury)
-
-- more precise (avoiding of) deprecation warnings for node.Class|Function accesses
-
-- avoid std unittest assertion helper code in tracebacks (thanks Ronny)
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.0.3.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.0.3.rst
deleted file mode 100644
index ed746e8519b..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.0.3.rst
+++ /dev/null
@@ -1,40 +0,0 @@
-py.test 2.0.3: bug fixes and speed ups
-===========================================================================
-
-Welcome to pytest-2.0.3, a maintenance and bug fix release of pytest,
-a mature testing tool for Python, supporting CPython 2.4-3.2, Jython
-and latest PyPy interpreters. See the extensive docs with tested examples here:
-
- http://pytest.org/
-
-If you want to install or upgrade pytest, just type one of::
-
- pip install -U pytest # or
- easy_install -U pytest
-
-There also is a bugfix release 1.6 of pytest-xdist, the plugin
-that enables seemless distributed and "looponfail" testing for Python.
-
-best,
-holger krekel
-
-Changes between 2.0.2 and 2.0.3
-----------------------------------------------
-
-- fix issue38: nicer tracebacks on calls to hooks, particularly early
- configure/sessionstart ones
-
-- fix missing skip reason/meta information in junitxml files, reported
- via http://lists.idyll.org/pipermail/testing-in-python/2011-March/003928.html
-
-- fix issue34: avoid collection failure with "test" prefixed classes
- deriving from object.
-
-- don't require zlib (and other libs) for genscript plugin without
- --genscript actually being used.
-
-- speed up skips (by not doing a full traceback represenation
- internally)
-
-- fix issue37: avoid invalid characters in junitxml's output
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.2.1.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.2.1.rst
deleted file mode 100644
index f9764634c72..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.2.1.rst
+++ /dev/null
@@ -1,41 +0,0 @@
-pytest-2.2.1: bug fixes, perfect teardowns
-===========================================================================
-
-
-pytest-2.2.1 is a minor backward-compatible release of the the py.test
-testing tool. It contains bug fixes and little improvements, including
-documentation fixes. If you are using the distributed testing
-pluginmake sure to upgrade it to pytest-xdist-1.8.
-
-For general information see here:
-
- http://pytest.org/
-
-To install or upgrade pytest:
-
- pip install -U pytest # or
- easy_install -U pytest
-
-Special thanks for helping on this release to Ronny Pfannschmidt, Jurko
-Gospodnetic and Ralf Schmitt.
-
-best,
-holger krekel
-
-
-Changes between 2.2.0 and 2.2.1
-----------------------------------------
-
-- fix issue99 (in pytest and py) internallerrors with resultlog now
- produce better output - fixed by normalizing pytest_internalerror
- input arguments.
-- fix issue97 / traceback issues (in pytest and py) improve traceback output
- in conjunction with jinja2 and cython which hack tracebacks
-- fix issue93 (in pytest and pytest-xdist) avoid "delayed teardowns":
- the final test in a test node will now run its teardown directly
- instead of waiting for the end of the session. Thanks Dave Hunt for
- the good reporting and feedback. The pytest_runtest_protocol as well
- as the pytest_runtest_teardown hooks now have "nextitem" available
- which will be None indicating the end of the test run.
-- fix collection crash due to unknown-source collected items, thanks
- to Ralf Schmitt (fixed by depending on a more recent pylib)
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.2.4.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.2.4.rst
deleted file mode 100644
index 8720bdb28a7..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.2.4.rst
+++ /dev/null
@@ -1,39 +0,0 @@
-pytest-2.2.4: bug fixes, better junitxml/unittest/python3 compat
-===========================================================================
-
-pytest-2.2.4 is a minor backward-compatible release of the versatile
-py.test testing tool. It contains bug fixes and a few refinements
-to junitxml reporting, better unittest- and python3 compatibility.
-
-For general information see here:
-
- http://pytest.org/
-
-To install or upgrade pytest:
-
- pip install -U pytest # or
- easy_install -U pytest
-
-Special thanks for helping on this release to Ronny Pfannschmidt
-and Benjamin Peterson and the contributors of issues.
-
-best,
-holger krekel
-
-Changes between 2.2.3 and 2.2.4
------------------------------------
-
-- fix error message for rewritten assertions involving the % operator
-- fix issue 126: correctly match all invalid xml characters for junitxml
- binary escape
-- fix issue with unittest: now @unittest.expectedFailure markers should
- be processed correctly (you can also use @pytest.mark markers)
-- document integration with the extended distribute/setuptools test commands
-- fix issue 140: propperly get the real functions
- of bound classmethods for setup/teardown_class
-- fix issue #141: switch from the deceased paste.pocoo.org to bpaste.net
-- fix issue #143: call unconfigure/sessionfinish always when
- configure/sessionstart where called
-- fix issue #144: better mangle test ids to junitxml classnames
-- upgrade distribute_setup.py to 0.6.27
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.3.0.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.3.0.rst
deleted file mode 100644
index 54fe3961fd8..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.3.0.rst
+++ /dev/null
@@ -1,134 +0,0 @@
-pytest-2.3: improved fixtures / better unittest integration
-=============================================================================
-
-pytest-2.3 comes with many major improvements for fixture/funcarg management
-and parametrized testing in Python. It is now easier, more efficient and
-more predicatable to re-run the same tests with different fixture
-instances. Also, you can directly declare the caching "scope" of
-fixtures so that dependent tests throughout your whole test suite can
-re-use database or other expensive fixture objects with ease. Lastly,
-it's possible for fixture functions (formerly known as funcarg
-factories) to use other fixtures, allowing for a completely modular and
-re-useable fixture design.
-
-For detailed info and tutorial-style examples, see:
-
- http://pytest.org/latest/fixture.html
-
-Moreover, there is now support for using pytest fixtures/funcargs with
-unittest-style suites, see here for examples:
-
- http://pytest.org/latest/unittest.html
-
-Besides, more unittest-test suites are now expected to "simply work"
-with pytest.
-
-All changes are backward compatible and you should be able to continue
-to run your test suites and 3rd party plugins that worked with
-pytest-2.2.4.
-
-If you are interested in the precise reasoning (including examples) of the
-pytest-2.3 fixture evolution, please consult
-http://pytest.org/latest/funcarg_compare.html
-
-For general info on installation and getting started:
-
- http://pytest.org/latest/getting-started.html
-
-Docs and PDF access as usual at:
-
- http://pytest.org
-
-and more details for those already in the knowing of pytest can be found
-in the CHANGELOG below.
-
-Particular thanks for this release go to Floris Bruynooghe, Alex Okrushko
-Carl Meyer, Ronny Pfannschmidt, Benjamin Peterson and Alex Gaynor for helping
-to get the new features right and well integrated. Ronny and Floris
-also helped to fix a number of bugs and yet more people helped by
-providing bug reports.
-
-have fun,
-holger krekel
-
-
-Changes between 2.2.4 and 2.3.0
------------------------------------
-
-- fix issue202 - better automatic names for parametrized test functions
-- fix issue139 - introduce @pytest.fixture which allows direct scoping
- and parametrization of funcarg factories. Introduce new @pytest.setup
- marker to allow the writing of setup functions which accept funcargs.
-- fix issue198 - conftest fixtures were not found on windows32 in some
- circumstances with nested directory structures due to path manipulation issues
-- fix issue193 skip test functions with were parametrized with empty
- parameter sets
-- fix python3.3 compat, mostly reporting bits that previously depended
- on dict ordering
-- introduce re-ordering of tests by resource and parametrization setup
- which takes precedence to the usual file-ordering
-- fix issue185 monkeypatching time.time does not cause pytest to fail
-- fix issue172 duplicate call of pytest.setup-decoratored setup_module
- functions
-- fix junitxml=path construction so that if tests change the
- current working directory and the path is a relative path
- it is constructed correctly from the original current working dir.
-- fix "python setup.py test" example to cause a proper "errno" return
-- fix issue165 - fix broken doc links and mention stackoverflow for FAQ
-- catch unicode-issues when writing failure representations
- to terminal to prevent the whole session from crashing
-- fix xfail/skip confusion: a skip-mark or an imperative pytest.skip
- will now take precedence before xfail-markers because we
- can't determine xfail/xpass status in case of a skip. see also:
- http://stackoverflow.com/questions/11105828/in-py-test-when-i-explicitly-skip-a-test-that-is-marked-as-xfail-how-can-i-get
-
-- always report installed 3rd party plugins in the header of a test run
-
-- fix issue160: a failing setup of an xfail-marked tests should
- be reported as xfail (not xpass)
-
-- fix issue128: show captured output when capsys/capfd are used
-
-- fix issue179: propperly show the dependency chain of factories
-
-- pluginmanager.register(...) now raises ValueError if the
- plugin has been already registered or the name is taken
-
-- fix issue159: improve http://pytest.org/latest/faq.html
- especially with respect to the "magic" history, also mention
- pytest-django, trial and unittest integration.
-
-- make request.keywords and node.keywords writable. All descendant
- collection nodes will see keyword values. Keywords are dictionaries
- containing markers and other info.
-
-- fix issue 178: xml binary escapes are now wrapped in py.xml.raw
-
-- fix issue 176: correctly catch the builtin AssertionError
- even when we replaced AssertionError with a subclass on the
- python level
-
-- factory discovery no longer fails with magic global callables
- that provide no sane __code__ object (mock.call for example)
-
-- fix issue 182: testdir.inprocess_run now considers passed plugins
-
-- fix issue 188: ensure sys.exc_info is clear on python2
- before calling into a test
-
-- fix issue 191: add unittest TestCase runTest method support
-- fix issue 156: monkeypatch correctly handles class level descriptors
-
-- reporting refinements:
-
- - pytest_report_header now receives a "startdir" so that
- you can use startdir.bestrelpath(yourpath) to show
- nice relative path
-
- - allow plugins to implement both pytest_report_header and
- pytest_sessionstart (sessionstart is invoked first).
-
- - don't show deselected reason line if there is none
-
- - py.test -vv will show all of assert comparisations instead of truncating
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.3.2.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.3.2.rst
deleted file mode 100644
index 948b374d43b..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.3.2.rst
+++ /dev/null
@@ -1,57 +0,0 @@
-pytest-2.3.2: some fixes and more traceback-printing speed
-===========================================================================
-
-pytest-2.3.2 is a another stabilization release:
-
-- issue 205: fixes a regression with conftest detection
-- issue 208/29: fixes traceback-printing speed in some bad cases
-- fix teardown-ordering for parametrized setups
-- fix unittest and trial compat behaviour with respect to runTest() methods
-- issue 206 and others: some improvements to packaging
-- fix issue127 and others: improve some docs
-
-See
-
- http://pytest.org/
-
-for general information. To install or upgrade pytest:
-
- pip install -U pytest # or
- easy_install -U pytest
-
-best,
-holger krekel
-
-
-Changes between 2.3.1 and 2.3.2
------------------------------------
-
-- fix issue208 and fix issue29 use new py version to avoid long pauses
- when printing tracebacks in long modules
-
-- fix issue205 - conftests in subdirs customizing
- pytest_pycollect_makemodule and pytest_pycollect_makeitem
- now work properly
-
-- fix teardown-ordering for parametrized setups
-
-- fix issue127 - better documentation for pytest_addoption
- and related objects.
-
-- fix unittest behaviour: TestCase.runtest only called if there are
- test methods defined
-
-- improve trial support: don't collect its empty
- unittest.TestCase.runTest() method
-
-- "python setup.py test" now works with pytest itself
-
-- fix/improve internal/packaging related bits:
-
- - exception message check of test_nose.py now passes on python33 as well
-
- - issue206 - fix test_assertrewrite.py to work when a global
- PYTHONDONTWRITEBYTECODE=1 is present
-
- - add tox.ini to pytest distribution so that ignore-dirs and others config
- bits are properly distributed for maintainers who run pytest-own tests
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.3.3.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.3.3.rst
deleted file mode 100644
index 1d7c7027bed..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.3.3.rst
+++ /dev/null
@@ -1,62 +0,0 @@
-pytest-2.3.3: integration fixes, py24 suport, ``*/**`` shown in traceback
-===========================================================================
-
-pytest-2.3.3 is a another stabilization release of the py.test tool
-which offers uebersimple assertions, scalable fixture mechanisms
-and deep customization for testing with Python. Particularly,
-this release provides:
-
-- integration fixes and improvements related to flask, numpy, nose,
- unittest, mock
-
-- makes pytest work on py24 again (yes, people sometimes still need to use it)
-
-- show ``*,**`` args in pytest tracebacks
-
-Thanks to Manuel Jacob, Thomas Waldmann, Ronny Pfannschmidt, Pavel Repin
-and Andreas Taumoefolau for providing patches and all for the issues.
-
-See
-
- http://pytest.org/
-
-for general information. To install or upgrade pytest:
-
- pip install -U pytest # or
- easy_install -U pytest
-
-best,
-holger krekel
-
-Changes between 2.3.2 and 2.3.3
------------------------------------
-
-- fix issue214 - parse modules that contain special objects like e. g.
- flask's request object which blows up on getattr access if no request
- is active. thanks Thomas Waldmann.
-
-- fix issue213 - allow to parametrize with values like numpy arrays that
- do not support an __eq__ operator
-
-- fix issue215 - split test_python.org into multiple files
-
-- fix issue148 - @unittest.skip on classes is now recognized and avoids
- calling setUpClass/tearDownClass, thanks Pavel Repin
-
-- fix issue209 - reintroduce python2.4 support by depending on newer
- pylib which re-introduced statement-finding for pre-AST interpreters
-
-- nose support: only call setup if its a callable, thanks Andrew
- Taumoefolau
-
-- fix issue219 - add py2.4-3.3 classifiers to TROVE list
-
-- in tracebacks *,** arg values are now shown next to normal arguments
- (thanks Manuel Jacob)
-
-- fix issue217 - support mock.patch with pytest's fixtures - note that
- you need either mock-1.0.1 or the python3.3 builtin unittest.mock.
-
-- fix issue127 - improve documentation for pytest_addoption() and
- add a ``config.getoption(name)`` helper function for consistency.
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.3.5.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.3.5.rst
deleted file mode 100644
index c4e91e0e614..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.3.5.rst
+++ /dev/null
@@ -1,97 +0,0 @@
-pytest-2.3.5: bug fixes and little improvements
-===========================================================================
-
-pytest-2.3.5 is a maintenance release with many bug fixes and little
-improvements. See the changelog below for details. No backward
-compatibility issues are foreseen and all plugins which worked with the
-prior version are expected to work unmodified. Speaking of which, a
-few interesting new plugins saw the light last month:
-
-- pytest-instafail: show failure information while tests are running
-- pytest-qt: testing of GUI applications written with QT/Pyside
-- pytest-xprocess: managing external processes across test runs
-- pytest-random: randomize test ordering
-
-And several others like pytest-django saw maintenance releases.
-For a more complete list, check out
-https://pypi.python.org/pypi?%3Aaction=search&term=pytest&submit=search.
-
-For general information see:
-
- http://pytest.org/
-
-To install or upgrade pytest:
-
- pip install -U pytest # or
- easy_install -U pytest
-
-Particular thanks to Floris, Ronny, Benjamin and the many bug reporters
-and fix providers.
-
-may the fixtures be with you,
-holger krekel
-
-
-Changes between 2.3.4 and 2.3.5
------------------------------------
-
-- never consider a fixture function for test function collection
-
-- allow re-running of test items / helps to fix pytest-reruntests plugin
- and also help to keep less fixture/resource references alive
-
-- put captured stdout/stderr into junitxml output even for passing tests
- (thanks Adam Goucher)
-
-- Issue 265 - integrate nose setup/teardown with setupstate
- so it doesnt try to teardown if it did not setup
-
-- issue 271 - dont write junitxml on slave nodes
-
-- Issue 274 - dont try to show full doctest example
- when doctest does not know the example location
-
-- issue 280 - disable assertion rewriting on buggy CPython 2.6.0
-
-- inject "getfixture()" helper to retrieve fixtures from doctests,
- thanks Andreas Zeidler
-
-- issue 259 - when assertion rewriting, be consistent with the default
- source encoding of ASCII on Python 2
-
-- issue 251 - report a skip instead of ignoring classes with init
-
-- issue250 unicode/str mixes in parametrization names and values now works
-
-- issue257, assertion-triggered compilation of source ending in a
- comment line doesn't blow up in python2.5 (fixed through py>=1.4.13.dev6)
-
-- fix --genscript option to generate standalone scripts that also
- work with python3.3 (importer ordering)
-
-- issue171 - in assertion rewriting, show the repr of some
- global variables
-
-- fix option help for "-k"
-
-- move long description of distribution into README.rst
-
-- improve docstring for metafunc.parametrize()
-
-- fix bug where using capsys with pytest.set_trace() in a test
- function would break when looking at capsys.readouterr()
-
-- allow to specify prefixes starting with "_" when
- customizing python_functions test discovery. (thanks Graham Horler)
-
-- improve PYTEST_DEBUG tracing output by puting
- extra data on a new lines with additional indent
-
-- ensure OutcomeExceptions like skip/fail have initialized exception attributes
-
-- issue 260 - don't use nose special setup on plain unittest cases
-
-- fix issue134 - print the collect errors that prevent running specified test items
-
-- fix issue266 - accept unicode in MarkEvaluator expressions
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.4.0.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.4.0.rst
deleted file mode 100644
index 88130c481f1..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.4.0.rst
+++ /dev/null
@@ -1,225 +0,0 @@
-pytest-2.4.0: new fixture features/hooks and bug fixes
-===========================================================================
-
-The just released pytest-2.4.0 brings many improvements and numerous
-bug fixes while remaining plugin- and test-suite compatible apart
-from a few supposedly very minor incompatibilities. See below for
-a full list of details. A few feature highlights:
-
-- new yield-style fixtures `pytest.yield_fixture
- <http://pytest.org/latest/yieldfixture.html>`_, allowing to use
- existing with-style context managers in fixture functions.
-
-- improved pdb support: ``import pdb ; pdb.set_trace()`` now works
- without requiring prior disabling of stdout/stderr capturing.
- Also the ``--pdb`` options works now on collection and internal errors
- and we introduced a new experimental hook for IDEs/plugins to
- intercept debugging: ``pytest_exception_interact(node, call, report)``.
-
-- shorter monkeypatch variant to allow specifying an import path as
- a target, for example: ``monkeypatch.setattr("requests.get", myfunc)``
-
-- better unittest/nose compatibility: all teardown methods are now only
- called if the corresponding setup method succeeded.
-
-- integrate tab-completion on command line options if you
- have `argcomplete <http://pypi.python.org/pypi/argcomplete>`_
- configured.
-
-- allow boolean expression directly with skipif/xfail
- if a "reason" is also specified.
-
-- a new hook ``pytest_load_initial_conftests`` allows plugins like
- `pytest-django <http://pypi.python.org/pypi/pytest-django>`_ to
- influence the environment before conftest files import ``django``.
-
-- reporting: color the last line red or green depending if
- failures/errors occurred or everything passed.
-
-The documentation has been updated to accomodate the changes,
-see `http://pytest.org <http://pytest.org>`_
-
-To install or upgrade pytest::
-
- pip install -U pytest # or
- easy_install -U pytest
-
-
-**Many thanks to all who helped, including Floris Bruynooghe,
-Brianna Laugher, Andreas Pelme, Anthon van der Neut, Anatoly Bubenkoff,
-Vladimir Keleshev, Mathieu Agopian, Ronny Pfannschmidt, Christian
-Theunert and many others.**
-
-may passing tests be with you,
-
-holger krekel
-
-Changes between 2.3.5 and 2.4
------------------------------------
-
-known incompatibilities:
-
-- if calling --genscript from python2.7 or above, you only get a
- standalone script which works on python2.7 or above. Use Python2.6
- to also get a python2.5 compatible version.
-
-- all xunit-style teardown methods (nose-style, pytest-style,
- unittest-style) will not be called if the corresponding setup method failed,
- see issue322 below.
-
-- the pytest_plugin_unregister hook wasn't ever properly called
- and there is no known implementation of the hook - so it got removed.
-
-- pytest.fixture-decorated functions cannot be generators (i.e. use
- yield) anymore. This change might be reversed in 2.4.1 if it causes
- unforeseen real-life issues. However, you can always write and return
- an inner function/generator and change the fixture consumer to iterate
- over the returned generator. This change was done in lieu of the new
- ``pytest.yield_fixture`` decorator, see below.
-
-new features:
-
-- experimentally introduce a new ``pytest.yield_fixture`` decorator
- which accepts exactly the same parameters as pytest.fixture but
- mandates a ``yield`` statement instead of a ``return statement`` from
- fixture functions. This allows direct integration with "with-style"
- context managers in fixture functions and generally avoids registering
- of finalization callbacks in favour of treating the "after-yield" as
- teardown code. Thanks Andreas Pelme, Vladimir Keleshev, Floris
- Bruynooghe, Ronny Pfannschmidt and many others for discussions.
-
-- allow boolean expression directly with skipif/xfail
- if a "reason" is also specified. Rework skipping documentation
- to recommend "condition as booleans" because it prevents surprises
- when importing markers between modules. Specifying conditions
- as strings will remain fully supported.
-
-- reporting: color the last line red or green depending if
- failures/errors occurred or everything passed. thanks Christian
- Theunert.
-
-- make "import pdb ; pdb.set_trace()" work natively wrt capturing (no
- "-s" needed anymore), making ``pytest.set_trace()`` a mere shortcut.
-
-- fix issue181: --pdb now also works on collect errors (and
- on internal errors) . This was implemented by a slight internal
- refactoring and the introduction of a new hook
- ``pytest_exception_interact`` hook (see next item).
-
-- fix issue341: introduce new experimental hook for IDEs/terminals to
- intercept debugging: ``pytest_exception_interact(node, call, report)``.
-
-- new monkeypatch.setattr() variant to provide a shorter
- invocation for patching out classes/functions from modules:
-
- monkeypatch.setattr("requests.get", myfunc)
-
- will replace the "get" function of the "requests" module with ``myfunc``.
-
-- fix issue322: tearDownClass is not run if setUpClass failed. Thanks
- Mathieu Agopian for the initial fix. Also make all of pytest/nose
- finalizer mimick the same generic behaviour: if a setupX exists and
- fails, don't run teardownX. This internally introduces a new method
- "node.addfinalizer()" helper which can only be called during the setup
- phase of a node.
-
-- simplify pytest.mark.parametrize() signature: allow to pass a
- CSV-separated string to specify argnames. For example:
- ``pytest.mark.parametrize("input,expected", [(1,2), (2,3)])``
- works as well as the previous:
- ``pytest.mark.parametrize(("input", "expected"), ...)``.
-
-- add support for setUpModule/tearDownModule detection, thanks Brian Okken.
-
-- integrate tab-completion on options through use of "argcomplete".
- Thanks Anthon van der Neut for the PR.
-
-- change option names to be hyphen-separated long options but keep the
- old spelling backward compatible. py.test -h will only show the
- hyphenated version, for example "--collect-only" but "--collectonly"
- will remain valid as well (for backward-compat reasons). Many thanks to
- Anthon van der Neut for the implementation and to Hynek Schlawack for
- pushing us.
-
-- fix issue 308 - allow to mark/xfail/skip individual parameter sets
- when parametrizing. Thanks Brianna Laugher.
-
-- call new experimental pytest_load_initial_conftests hook to allow
- 3rd party plugins to do something before a conftest is loaded.
-
-Bug fixes:
-
-- fix issue358 - capturing options are now parsed more properly
- by using a new parser.parse_known_args method.
-
-- pytest now uses argparse instead of optparse (thanks Anthon) which
- means that "argparse" is added as a dependency if installing into python2.6
- environments or below.
-
-- fix issue333: fix a case of bad unittest/pytest hook interaction.
-
-- PR27: correctly handle nose.SkipTest during collection. Thanks
- Antonio Cuni, Ronny Pfannschmidt.
-
-- fix issue355: junitxml puts name="pytest" attribute to testsuite tag.
-
-- fix issue336: autouse fixture in plugins should work again.
-
-- fix issue279: improve object comparisons on assertion failure
- for standard datatypes and recognise collections.abc. Thanks to
- Brianna Laugher and Mathieu Agopian.
-
-- fix issue317: assertion rewriter support for the is_package method
-
-- fix issue335: document py.code.ExceptionInfo() object returned
- from pytest.raises(), thanks Mathieu Agopian.
-
-- remove implicit distribute_setup support from setup.py.
-
-- fix issue305: ignore any problems when writing pyc files.
-
-- SO-17664702: call fixture finalizers even if the fixture function
- partially failed (finalizers would not always be called before)
-
-- fix issue320 - fix class scope for fixtures when mixed with
- module-level functions. Thanks Anatloy Bubenkoff.
-
-- you can specify "-q" or "-qq" to get different levels of "quieter"
- reporting (thanks Katarzyna Jachim)
-
-- fix issue300 - Fix order of conftest loading when starting py.test
- in a subdirectory.
-
-- fix issue323 - sorting of many module-scoped arg parametrizations
-
-- make sessionfinish hooks execute with the same cwd-context as at
- session start (helps fix plugin behaviour which write output files
- with relative path such as pytest-cov)
-
-- fix issue316 - properly reference collection hooks in docs
-
-- fix issue 306 - cleanup of -k/-m options to only match markers/test
- names/keywords respectively. Thanks Wouter van Ackooy.
-
-- improved doctest counting for doctests in python modules --
- files without any doctest items will not show up anymore
- and doctest examples are counted as separate test items.
- thanks Danilo Bellini.
-
-- fix issue245 by depending on the released py-1.4.14
- which fixes py.io.dupfile to work with files with no
- mode. Thanks Jason R. Coombs.
-
-- fix junitxml generation when test output contains control characters,
- addressing issue267, thanks Jaap Broekhuizen
-
-- fix issue338: honor --tb style for setup/teardown errors as well. Thanks Maho.
-
-- fix issue307 - use yaml.safe_load in example, thanks Mark Eichin.
-
-- better parametrize error messages, thanks Brianna Laugher
-
-- pytest_terminal_summary(terminalreporter) hooks can now use
- ".section(title)" and ".line(msg)" methods to print extra
- information at the end of a test run.
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.5.0.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.5.0.rst
deleted file mode 100644
index b8f28d6fd5e..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.5.0.rst
+++ /dev/null
@@ -1,175 +0,0 @@
-pytest-2.5.0: now down to ZERO reported bugs!
-===========================================================================
-
-pytest-2.5.0 is a big fixing release, the result of two community bug
-fixing days plus numerous additional works from many people and
-reporters. The release should be fully compatible to 2.4.2, existing
-plugins and test suites. We aim at maintaining this level of ZERO reported
-bugs because it's no fun if your testing tool has bugs, is it? Under a
-condition, though: when submitting a bug report please provide
-clear information about the circumstances and a simple example which
-reproduces the problem.
-
-The issue tracker is of course not empty now. We have many remaining
-"enhacement" issues which we'll hopefully can tackle in 2014 with your
-help.
-
-For those who use older Python versions, please note that pytest is not
-automatically tested on python2.5 due to virtualenv, setuptools and tox
-not supporting it anymore. Manual verification shows that it mostly
-works fine but it's not going to be part of the automated release
-process and thus likely to break in the future.
-
-As usual, current docs are at
-
- http://pytest.org
-
-and you can upgrade from pypi via::
-
- pip install -U pytest
-
-Particular thanks for helping with this release go to Anatoly Bubenkoff,
-Floris Bruynooghe, Marc Abramowitz, Ralph Schmitt, Ronny Pfannschmidt,
-Donald Stufft, James Lan, Rob Dennis, Jason R. Coombs, Mathieu Agopian,
-Virgil Dupras, Bruno Oliveira, Alex Gaynor and others.
-
-have fun,
-holger krekel
-
-
-2.5.0
------------------------------------
-
-- dropped python2.5 from automated release testing of pytest itself
- which means it's probably going to break soon (but still works
- with this release we believe).
-
-- simplified and fixed implementation for calling finalizers when
- parametrized fixtures or function arguments are involved. finalization
- is now performed lazily at setup time instead of in the "teardown phase".
- While this might sound odd at first, it helps to ensure that we are
- correctly handling setup/teardown even in complex code. User-level code
- should not be affected unless it's implementing the pytest_runtest_teardown
- hook and expecting certain fixture instances are torn down within (very
- unlikely and would have been unreliable anyway).
-
-- PR90: add --color=yes|no|auto option to force terminal coloring
- mode ("auto" is default). Thanks Marc Abramowitz.
-
-- fix issue319 - correctly show unicode in assertion errors. Many
- thanks to Floris Bruynooghe for the complete PR. Also means
- we depend on py>=1.4.19 now.
-
-- fix issue396 - correctly sort and finalize class-scoped parametrized
- tests independently from number of methods on the class.
-
-- refix issue323 in a better way -- parametrization should now never
- cause Runtime Recursion errors because the underlying algorithm
- for re-ordering tests per-scope/per-fixture is not recursive
- anymore (it was tail-call recursive before which could lead
- to problems for more than >966 non-function scoped parameters).
-
-- fix issue290 - there is preliminary support now for parametrizing
- with repeated same values (sometimes useful to to test if calling
- a second time works as with the first time).
-
-- close issue240 - document precisely how pytest module importing
- works, discuss the two common test directory layouts, and how it
- interacts with PEP420-namespace packages.
-
-- fix issue246 fix finalizer order to be LIFO on independent fixtures
- depending on a parametrized higher-than-function scoped fixture.
- (was quite some effort so please bear with the complexity of this sentence :)
- Thanks Ralph Schmitt for the precise failure example.
-
-- fix issue244 by implementing special index for parameters to only use
- indices for paramentrized test ids
-
-- fix issue287 by running all finalizers but saving the exception
- from the first failing finalizer and re-raising it so teardown will
- still have failed. We reraise the first failing exception because
- it might be the cause for other finalizers to fail.
-
-- fix ordering when mock.patch or other standard decorator-wrappings
- are used with test methods. This fixues issue346 and should
- help with random "xdist" collection failures. Thanks to
- Ronny Pfannschmidt and Donald Stufft for helping to isolate it.
-
-- fix issue357 - special case "-k" expressions to allow for
- filtering with simple strings that are not valid python expressions.
- Examples: "-k 1.3" matches all tests parametrized with 1.3.
- "-k None" filters all tests that have "None" in their name
- and conversely "-k 'not None'".
- Previously these examples would raise syntax errors.
-
-- fix issue384 by removing the trial support code
- since the unittest compat enhancements allow
- trial to handle it on its own
-
-- don't hide an ImportError when importing a plugin produces one.
- fixes issue375.
-
-- fix issue275 - allow usefixtures and autouse fixtures
- for running doctest text files.
-
-- fix issue380 by making --resultlog only rely on longrepr instead
- of the "reprcrash" attribute which only exists sometimes.
-
-- address issue122: allow @pytest.fixture(params=iterator) by exploding
- into a list early on.
-
-- fix pexpect-3.0 compatibility for pytest's own tests.
- (fixes issue386)
-
-- allow nested parametrize-value markers, thanks James Lan for the PR.
-
-- fix unicode handling with new monkeypatch.setattr(import_path, value)
- API. Thanks Rob Dennis. Fixes issue371.
-
-- fix unicode handling with junitxml, fixes issue368.
-
-- In assertion rewriting mode on Python 2, fix the detection of coding
- cookies. See issue #330.
-
-- make "--runxfail" turn imperative pytest.xfail calls into no ops
- (it already did neutralize pytest.mark.xfail markers)
-
-- refine pytest / pkg_resources interactions: The AssertionRewritingHook
- PEP302 compliant loader now registers itself with setuptools/pkg_resources
- properly so that the pkg_resources.resource_stream method works properly.
- Fixes issue366. Thanks for the investigations and full PR to Jason R. Coombs.
-
-- pytestconfig fixture is now session-scoped as it is the same object during the
- whole test run. Fixes issue370.
-
-- avoid one surprising case of marker malfunction/confusion::
-
- @pytest.mark.some(lambda arg: ...)
- def test_function():
-
- would not work correctly because pytest assumes @pytest.mark.some
- gets a function to be decorated already. We now at least detect if this
- arg is an lambda and thus the example will work. Thanks Alex Gaynor
- for bringing it up.
-
-- xfail a test on pypy that checks wrong encoding/ascii (pypy does
- not error out). fixes issue385.
-
-- internally make varnames() deal with classes's __init__,
- although it's not needed by pytest itself atm. Also
- fix caching. Fixes issue376.
-
-- fix issue221 - handle importing of namespace-package with no
- __init__.py properly.
-
-- refactor internal FixtureRequest handling to avoid monkeypatching.
- One of the positive user-facing effects is that the "request" object
- can now be used in closures.
-
-- fixed version comparison in pytest.importskip(modname, minverstring)
-
-- fix issue377 by clarifying in the nose-compat docs that pytest
- does not duplicate the unittest-API into the "plain" namespace.
-
-- fix verbose reporting for @mock'd test functions
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.5.2.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.5.2.rst
deleted file mode 100644
index 9308ffdd626..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.5.2.rst
+++ /dev/null
@@ -1,64 +0,0 @@
-pytest-2.5.2: fixes
-===========================================================================
-
-pytest is a mature Python testing tool with more than a 1000 tests
-against itself, passing on many different interpreters and platforms.
-
-The 2.5.2 release fixes a few bugs with two maybe-bugs remaining and
-actively being worked on (and waiting for the bug reporter's input).
-We also have a new contribution guide thanks to Piotr Banaszkiewicz
-and others.
-
-See docs at:
-
- http://pytest.org
-
-As usual, you can upgrade from pypi via::
-
- pip install -U pytest
-
-Thanks to the following people who contributed to this release:
-
- Anatoly Bubenkov
- Ronny Pfannschmidt
- Floris Bruynooghe
- Bruno Oliveira
- Andreas Pelme
- Jurko Gospodnetić
- Piotr Banaszkiewicz
- Simon Liedtke
- lakka
- Lukasz Balcerzak
- Philippe Muller
- Daniel Hahler
-
-have fun,
-holger krekel
-
-2.5.2
------------------------------------
-
-- fix issue409 -- better interoperate with cx_freeze by not
- trying to import from collections.abc which causes problems
- for py27/cx_freeze. Thanks Wolfgang L. for reporting and tracking it down.
-
-- fixed docs and code to use "pytest" instead of "py.test" almost everywhere.
- Thanks Jurko Gospodnetic for the complete PR.
-
-- fix issue425: mention at end of "py.test -h" that --markers
- and --fixtures work according to specified test path (or current dir)
-
-- fix issue413: exceptions with unicode attributes are now printed
- correctly also on python2 and with pytest-xdist runs. (the fix
- requires py-1.4.20)
-
-- copy, cleanup and integrate py.io capture
- from pylib 1.4.20.dev2 (rev 13d9af95547e)
-
-- address issue416: clarify docs as to conftest.py loading semantics
-
-- fix issue429: comparing byte strings with non-ascii chars in assert
- expressions now work better. Thanks Floris Bruynooghe.
-
-- make capfd/capsys.capture private, its unused and shouldnt be exposed
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.6.3.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.6.3.rst
deleted file mode 100644
index 13fae31b8a1..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.6.3.rst
+++ /dev/null
@@ -1,52 +0,0 @@
-pytest-2.6.3: fixes and little improvements
-===========================================================================
-
-pytest is a mature Python testing tool with more than a 1100 tests
-against itself, passing on many different interpreters and platforms.
-This release is drop-in compatible to 2.5.2 and 2.6.X.
-See below for the changes and see docs at:
-
- http://pytest.org
-
-As usual, you can upgrade from pypi via::
-
- pip install -U pytest
-
-Thanks to all who contributed, among them:
-
- Floris Bruynooghe
- Oleg Sinyavskiy
- Uwe Schmitt
- Charles Cloud
- Wolfgang Schnerring
-
-have fun,
-holger krekel
-
-Changes 2.6.3
-======================
-
-- fix issue575: xunit-xml was reporting collection errors as failures
- instead of errors, thanks Oleg Sinyavskiy.
-
-- fix issue582: fix setuptools example, thanks Laszlo Papp and Ronny
- Pfannschmidt.
-
-- Fix infinite recursion bug when pickling capture.EncodedFile, thanks
- Uwe Schmitt.
-
-- fix issue589: fix bad interaction with numpy and others when showing
- exceptions. Check for precise "maximum recursion depth exceed" exception
- instead of presuming any RuntimeError is that one (implemented in py
- dep). Thanks Charles Cloud for analysing the issue.
-
-- fix conftest related fixture visibility issue: when running with a
- CWD outside a test package pytest would get fixture discovery wrong.
- Thanks to Wolfgang Schnerring for figuring out a reproducable example.
-
-- Introduce pytest_enter_pdb hook (needed e.g. by pytest_timeout to cancel the
- timeout when interactively entering pdb). Thanks Wolfgang Schnerring.
-
-- check xfail/skip also with non-python function test items. Thanks
- Floris Bruynooghe.
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.7.0.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.7.0.rst
deleted file mode 100644
index 07ae44ca1ac..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.7.0.rst
+++ /dev/null
@@ -1,101 +0,0 @@
-pytest-2.7.0: fixes, features, speed improvements
-===========================================================================
-
-pytest is a mature Python testing tool with more than a 1100 tests
-against itself, passing on many different interpreters and platforms.
-This release is supposed to be drop-in compatible to 2.6.X.
-
-See below for the changes and see docs at:
-
- http://pytest.org
-
-As usual, you can upgrade from pypi via::
-
- pip install -U pytest
-
-Thanks to all who contributed, among them:
-
- Anatoly Bubenkoff
- Floris Bruynooghe
- Brianna Laugher
- Eric Siegerman
- Daniel Hahler
- Charles Cloud
- Tom Viner
- Holger Peters
- Ldiary Translations
- almarklein
-
-have fun,
-holger krekel
-
-2.7.0 (compared to 2.6.4)
------------------------------
-
-- fix issue435: make reload() work when assert rewriting is active.
- Thanks Daniel Hahler.
-
-- fix issue616: conftest.py files and their contained fixutres are now
- properly considered for visibility, independently from the exact
- current working directory and test arguments that are used.
- Many thanks to Eric Siegerman and his PR235 which contains
- systematic tests for conftest visibility and now passes.
- This change also introduces the concept of a ``rootdir`` which
- is printed as a new pytest header and documented in the pytest
- customize web page.
-
-- change reporting of "diverted" tests, i.e. tests that are collected
- in one file but actually come from another (e.g. when tests in a test class
- come from a base class in a different file). We now show the nodeid
- and indicate via a postfix the other file.
-
-- add ability to set command line options by environment variable PYTEST_ADDOPTS.
-
-- added documentation on the new pytest-dev teams on bitbucket and
- github. See https://pytest.org/latest/contributing.html .
- Thanks to Anatoly for pushing and initial work on this.
-
-- fix issue650: new option ``--docttest-ignore-import-errors`` which
- will turn import errors in doctests into skips. Thanks Charles Cloud
- for the complete PR.
-
-- fix issue655: work around different ways that cause python2/3
- to leak sys.exc_info into fixtures/tests causing failures in 3rd party code
-
-- fix issue615: assertion re-writing did not correctly escape % signs
- when formatting boolean operations, which tripped over mixing
- booleans with modulo operators. Thanks to Tom Viner for the report,
- triaging and fix.
-
-- implement issue351: add ability to specify parametrize ids as a callable
- to generate custom test ids. Thanks Brianna Laugher for the idea and
- implementation.
-
-- introduce and document new hookwrapper mechanism useful for plugins
- which want to wrap the execution of certain hooks for their purposes.
- This supersedes the undocumented ``__multicall__`` protocol which
- pytest itself and some external plugins use. Note that pytest-2.8
- is scheduled to drop supporting the old ``__multicall__``
- and only support the hookwrapper protocol.
-
-- majorly speed up invocation of plugin hooks
-
-- use hookwrapper mechanism in builtin pytest plugins.
-
-- add a doctest ini option for doctest flags, thanks Holger Peters.
-
-- add note to docs that if you want to mark a parameter and the
- parameter is a callable, you also need to pass in a reason to disambiguate
- it from the "decorator" case. Thanks Tom Viner.
-
-- "python_classes" and "python_functions" options now support glob-patterns
- for test discovery, as discussed in issue600. Thanks Ldiary Translations.
-
-- allow to override parametrized fixtures with non-parametrized ones and vice versa (bubenkoff).
-
-- fix issue463: raise specific error for 'parameterize' misspelling (pfctdayelise).
-
-- On failure, the ``sys.last_value``, ``sys.last_type`` and
- ``sys.last_traceback`` are set, so that a user can inspect the error
- via postmortem debugging (almarklein).
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.7.1.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.7.1.rst
deleted file mode 100644
index cd37cad0cb8..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.7.1.rst
+++ /dev/null
@@ -1,58 +0,0 @@
-pytest-2.7.1: bug fixes
-=======================
-
-pytest is a mature Python testing tool with more than a 1100 tests
-against itself, passing on many different interpreters and platforms.
-This release is supposed to be drop-in compatible to 2.7.0.
-
-See below for the changes and see docs at:
-
- http://pytest.org
-
-As usual, you can upgrade from pypi via::
-
- pip install -U pytest
-
-Thanks to all who contributed to this release, among them:
-
- Bruno Oliveira
- Holger Krekel
- Ionel Maries Cristian
- Floris Bruynooghe
-
-Happy testing,
-The py.test Development Team
-
-
-2.7.1 (compared to 2.7.0)
--------------------------
-
-- fix issue731: do not get confused by the braces which may be present
- and unbalanced in an object's repr while collapsing False
- explanations. Thanks Carl Meyer for the report and test case.
-
-- fix issue553: properly handling inspect.getsourcelines failures in
- FixtureLookupError which would lead to to an internal error,
- obfuscating the original problem. Thanks talljosh for initial
- diagnose/patch and Bruno Oliveira for final patch.
-
-- fix issue660: properly report scope-mismatch-access errors
- independently from ordering of fixture arguments. Also
- avoid the pytest internal traceback which does not provide
- information to the user. Thanks Holger Krekel.
-
-- streamlined and documented release process. Also all versions
- (in setup.py and documentation generation) are now read
- from _pytest/__init__.py. Thanks Holger Krekel.
-
-- fixed docs to remove the notion that yield-fixtures are experimental.
- They are here to stay :) Thanks Bruno Oliveira.
-
-- Support building wheels by using environment markers for the
- requirements. Thanks Ionel Maries Cristian.
-
-- fixed regression to 2.6.4 which surfaced e.g. in lost stdout capture printing
- when tests raised SystemExit. Thanks Holger Krekel.
-
-- reintroduced _pytest fixture of the pytester plugin which is used
- at least by pytest-xdist.
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.9.0.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.9.0.rst
deleted file mode 100644
index 99c1c631f17..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.9.0.rst
+++ /dev/null
@@ -1,159 +0,0 @@
-pytest-2.9.0
-============
-
-pytest is a mature Python testing tool with more than a 1100 tests
-against itself, passing on many different interpreters and platforms.
-
-See below for the changes and see docs at:
-
- http://pytest.org
-
-As usual, you can upgrade from pypi via::
-
- pip install -U pytest
-
-Thanks to all who contributed to this release, among them:
-
- Anatoly Bubenkov
- Bruno Oliveira
- Buck Golemon
- David Vierra
- Florian Bruhin
- Galaczi Endre
- Georgy Dyuldin
- Lukas Bednar
- Luke Murphy
- Marcin Biernat
- Matt Williams
- Michael Aquilina
- Raphael Pierzina
- Ronny Pfannschmidt
- Ryan Wooden
- Tiemo Kieft
- TomV
- holger krekel
- jab
-
-
-Happy testing,
-The py.test Development Team
-
-
-2.9.0 (compared to 2.8.7)
--------------------------
-
-**New Features**
-
-* New ``pytest.mark.skip`` mark, which unconditionally skips marked tests.
- Thanks `@MichaelAquilina`_ for the complete PR (`#1040`_).
-
-* ``--doctest-glob`` may now be passed multiple times in the command-line.
- Thanks `@jab`_ and `@nicoddemus`_ for the PR.
-
-* New ``-rp`` and ``-rP`` reporting options give the summary and full output
- of passing tests, respectively. Thanks to `@codewarrior0`_ for the PR.
-
-* ``pytest.mark.xfail`` now has a ``strict`` option which makes ``XPASS``
- tests to fail the test suite, defaulting to ``False``. There's also a
- ``xfail_strict`` ini option that can be used to configure it project-wise.
- Thanks `@rabbbit`_ for the request and `@nicoddemus`_ for the PR (`#1355`_).
-
-* ``Parser.addini`` now supports options of type ``bool``. Thanks
- `@nicoddemus`_ for the PR.
-
-* New ``ALLOW_BYTES`` doctest option strips ``b`` prefixes from byte strings
- in doctest output (similar to ``ALLOW_UNICODE``).
- Thanks `@jaraco`_ for the request and `@nicoddemus`_ for the PR (`#1287`_).
-
-* give a hint on KeyboardInterrupt to use the --fulltrace option to show the errors,
- this fixes `#1366`_.
- Thanks to `@hpk42`_ for the report and `@RonnyPfannschmidt`_ for the PR.
-
-* catch IndexError exceptions when getting exception source location. This fixes
- pytest internal error for dynamically generated code (fixtures and tests)
- where source lines are fake by intention
-
-**Changes**
-
-* **Important**: `py.code <http://pylib.readthedocs.org/en/latest/code.html>`_ has been
- merged into the ``pytest`` repository as ``pytest._code``. This decision
- was made because ``py.code`` had very few uses outside ``pytest`` and the
- fact that it was in a different repository made it difficult to fix bugs on
- its code in a timely manner. The team hopes with this to be able to better
- refactor out and improve that code.
- This change shouldn't affect users, but it is useful to let users aware
- if they encounter any strange behavior.
-
- Keep in mind that the code for ``pytest._code`` is **private** and
- **experimental**, so you definitely should not import it explicitly!
-
- Please note that the original ``py.code`` is still available in
- `pylib <http://pylib.readthedocs.org>`_.
-
-* ``pytest_enter_pdb`` now optionally receives the pytest config object.
- Thanks `@nicoddemus`_ for the PR.
-
-* Removed code and documentation for Python 2.5 or lower versions,
- including removal of the obsolete ``_pytest.assertion.oldinterpret`` module.
- Thanks `@nicoddemus`_ for the PR (`#1226`_).
-
-* Comparisons now always show up in full when ``CI`` or ``BUILD_NUMBER`` is
- found in the environment, even when -vv isn't used.
- Thanks `@The-Compiler`_ for the PR.
-
-* ``--lf`` and ``--ff`` now support long names: ``--last-failed`` and
- ``--failed-first`` respectively.
- Thanks `@MichaelAquilina`_ for the PR.
-
-* Added expected exceptions to pytest.raises fail message
-
-* Collection only displays progress ("collecting X items") when in a terminal.
- This avoids cluttering the output when using ``--color=yes`` to obtain
- colors in CI integrations systems (`#1397`_).
-
-**Bug Fixes**
-
-* The ``-s`` and ``-c`` options should now work under ``xdist``;
- ``Config.fromdictargs`` now represents its input much more faithfully.
- Thanks to `@bukzor`_ for the complete PR (`#680`_).
-
-* Fix (`#1290`_): support Python 3.5's ``@`` operator in assertion rewriting.
- Thanks `@Shinkenjoe`_ for report with test case and `@tomviner`_ for the PR.
-
-* Fix formatting utf-8 explanation messages (`#1379`_).
- Thanks `@biern`_ for the PR.
-
-* Fix `traceback style docs`_ to describe all of the available options
- (auto/long/short/line/native/no), with `auto` being the default since v2.6.
- Thanks `@hackebrot`_ for the PR.
-
-* Fix (`#1422`_): junit record_xml_property doesn't allow multiple records
- with same name.
-
-
-.. _`traceback style docs`: https://pytest.org/latest/usage.html#modifying-python-traceback-printing
-
-.. _#1422: https://github.com/pytest-dev/pytest/issues/1422
-.. _#1379: https://github.com/pytest-dev/pytest/issues/1379
-.. _#1366: https://github.com/pytest-dev/pytest/issues/1366
-.. _#1040: https://github.com/pytest-dev/pytest/pull/1040
-.. _#680: https://github.com/pytest-dev/pytest/issues/680
-.. _#1287: https://github.com/pytest-dev/pytest/pull/1287
-.. _#1226: https://github.com/pytest-dev/pytest/pull/1226
-.. _#1290: https://github.com/pytest-dev/pytest/pull/1290
-.. _#1355: https://github.com/pytest-dev/pytest/pull/1355
-.. _#1397: https://github.com/pytest-dev/pytest/issues/1397
-.. _@biern: https://github.com/biern
-.. _@MichaelAquilina: https://github.com/MichaelAquilina
-.. _@bukzor: https://github.com/bukzor
-.. _@hpk42: https://github.com/hpk42
-.. _@nicoddemus: https://github.com/nicoddemus
-.. _@jab: https://github.com/jab
-.. _@codewarrior0: https://github.com/codewarrior0
-.. _@jaraco: https://github.com/jaraco
-.. _@The-Compiler: https://github.com/The-Compiler
-.. _@Shinkenjoe: https://github.com/Shinkenjoe
-.. _@tomviner: https://github.com/tomviner
-.. _@RonnyPfannschmidt: https://github.com/RonnyPfannschmidt
-.. _@rabbbit: https://github.com/rabbbit
-.. _@hackebrot: https://github.com/hackebrot \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.9.1.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.9.1.rst
deleted file mode 100644
index 05a44843042..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.9.1.rst
+++ /dev/null
@@ -1,65 +0,0 @@
-pytest-2.9.1
-============
-
-pytest is a mature Python testing tool with more than a 1100 tests
-against itself, passing on many different interpreters and platforms.
-
-See below for the changes and see docs at:
-
- http://pytest.org
-
-As usual, you can upgrade from pypi via::
-
- pip install -U pytest
-
-Thanks to all who contributed to this release, among them:
-
- Bruno Oliveira
- Daniel Hahler
- Dmitry Malinovsky
- Florian Bruhin
- Floris Bruynooghe
- Matt Bachmann
- Ronny Pfannschmidt
- TomV
- Vladimir Bolshakov
- Zearin
- palaviv
-
-
-Happy testing,
-The py.test Development Team
-
-
-2.9.1 (compared to 2.9.0)
--------------------------
-
-**Bug Fixes**
-
-* Improve error message when a plugin fails to load.
- Thanks `@nicoddemus`_ for the PR.
-
-* Fix (`#1178 <https://github.com/pytest-dev/pytest/issues/1178>`_):
- ``pytest.fail`` with non-ascii characters raises an internal pytest error.
- Thanks `@nicoddemus`_ for the PR.
-
-* Fix (`#469`_): junit parses report.nodeid incorrectly, when params IDs
- contain ``::``. Thanks `@tomviner`_ for the PR (`#1431`_).
-
-* Fix (`#578 <https://github.com/pytest-dev/pytest/issues/578>`_): SyntaxErrors
- containing non-ascii lines at the point of failure generated an internal
- py.test error.
- Thanks `@asottile`_ for the report and `@nicoddemus`_ for the PR.
-
-* Fix (`#1437`_): When passing in a bytestring regex pattern to parameterize
- attempt to decode it as utf-8 ignoring errors.
-
-* Fix (`#649`_): parametrized test nodes cannot be specified to run on the command line.
-
-
-.. _#1437: https://github.com/pytest-dev/pytest/issues/1437
-.. _#469: https://github.com/pytest-dev/pytest/issues/469
-.. _#1431: https://github.com/pytest-dev/pytest/pull/1431
-.. _#649: https://github.com/pytest-dev/pytest/issues/649
-
-.. _@asottile: https://github.com/asottile
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/sprint2016.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/sprint2016.rst
deleted file mode 100644
index e59ccdda772..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/sprint2016.rst
+++ /dev/null
@@ -1,105 +0,0 @@
-python testing sprint June 20th-26th 2016
-======================================================
-
-.. image:: ../img/freiburg2.jpg
- :width: 400
-
-The pytest core group is heading towards the biggest sprint
-in its history, to take place in the black forest town Freiburg
-in Germany. As of February 2016 we have started a `funding
-campaign on Indiegogo to cover expenses
-<http://igg.me/at/pytest-sprint/x/4034848>`_ The page also mentions
-some preliminary topics:
-
-- improving pytest-xdist test scheduling to take into account
- fixture setups and explicit user hints.
-
-- provide info on fixture dependencies during --collect-only
-
-- tying pytest-xdist to tox so that you can do "py.test -e py34"
- to run tests in a particular tox-managed virtualenv. Also
- look into making pytest-xdist use tox environments on
- remote ssh-sides so that remote dependency management becomes
- easier.
-
-- refactoring the fixture system so more people understand it :)
-
-- integrating PyUnit setup methods as autouse fixtures.
- possibly adding ways to influence ordering of same-scoped
- fixtures (so you can make a choice of which fixtures come
- before others)
-
-- fixing bugs and issues from the tracker, really an endless source :)
-
-
-Participants
---------------
-
-Here are preliminary participants who said they are likely to come,
-given some expenses funding::
-
- Anatoly Bubenkoff, Netherlands
- Andreas Pelme, Personalkollen, Sweden
- Anthony Wang, Splunk, US
- Brianna Laugher, Australia
- Bruno Oliveira, Brazil
- Danielle Jenkins, Splunk, US
- Dave Hunt, UK
- Florian Bruhin, Switzerland
- Floris Bruynooghe, Cobe.io, UK
- Holger Krekel, merlinux, Germany
- Oliver Bestwalter, Avira, Germany
- Omar Kohl, Germany
- Raphael Pierzina, FanDuel, UK
- Tom Viner, UK
-
- <your name here?>
-
-Other contributors and experienced newcomers are invited to join as well
-but please send a mail to the pytest-dev mailing list if you intend to
-do so somewhat soon, also how much funding you need if so. And if you
-are working for a company and using pytest heavily you are welcome to
-join and we encourage your company to provide some funding for the
-sprint. They may see it, and rightfully so, as a very cheap and deep
-training which brings you together with the experts in the field :)
-
-
-Sprint organisation, schedule
--------------------------------
-
-tentative schedule:
-
-- 19/20th arrival in Freiburg
-- 20th social get together, initial hacking
-- 21/22th full sprint days
-- 23rd break day, hiking
-- 24/25th full sprint days
-- 26th departure
-
-We might adjust according to weather to make sure that if
-we do some hiking or excursion we'll have good weather.
-Freiburg is one of the sunniest places in Germany so
-it shouldn't be too much of a constraint.
-
-
-Accomodation
-----------------
-
-We'll see to arrange for renting a flat with multiple
-beds/rooms. Hotels are usually below 100 per night.
-The earlier we book the better.
-
-Money / funding
----------------
-
-The Indiegogo campaign asks for 11000 USD which should cover
-the costs for flights and accomodation, renting a sprint place
-and maybe a bit of food as well.
-
-If your organisation wants to support the sprint but prefers
-to give money according to an invoice, get in contact with
-holger at http://merlinux.eu who can invoice your organisation
-properly.
-
-If we have excess money we'll use for further sprint/travel
-funding for pytest/tox contributors.
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/assert.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/assert.rst
deleted file mode 100644
index e7f14e8bd1a..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/assert.rst
+++ /dev/null
@@ -1,289 +0,0 @@
-
-The writing and reporting of assertions in tests
-==================================================
-
-.. _`assertfeedback`:
-.. _`assert with the assert statement`:
-.. _`assert`:
-
-
-Asserting with the ``assert`` statement
----------------------------------------------------------
-
-``pytest`` allows you to use the standard python ``assert`` for verifying
-expectations and values in Python tests. For example, you can write the
-following::
-
- # content of test_assert1.py
- def f():
- return 3
-
- def test_function():
- assert f() == 4
-
-to assert that your function returns a certain value. If this assertion fails
-you will see the return value of the function call::
-
- $ py.test test_assert1.py
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 1 items
-
- test_assert1.py F
-
- ======= FAILURES ========
- _______ test_function ________
-
- def test_function():
- > assert f() == 4
- E assert 3 == 4
- E + where 3 = f()
-
- test_assert1.py:5: AssertionError
- ======= 1 failed in 0.12 seconds ========
-
-``pytest`` has support for showing the values of the most common subexpressions
-including calls, attributes, comparisons, and binary and unary
-operators. (See :ref:`tbreportdemo`). This allows you to use the
-idiomatic python constructs without boilerplate code while not losing
-introspection information.
-
-However, if you specify a message with the assertion like this::
-
- assert a % 2 == 0, "value was odd, should be even"
-
-then no assertion introspection takes places at all and the message
-will be simply shown in the traceback.
-
-See :ref:`assert-details` for more information on assertion introspection.
-
-.. _`assertraises`:
-
-Assertions about expected exceptions
-------------------------------------------
-
-In order to write assertions about raised exceptions, you can use
-``pytest.raises`` as a context manager like this::
-
- import pytest
-
- def test_zero_division():
- with pytest.raises(ZeroDivisionError):
- 1 / 0
-
-and if you need to have access to the actual exception info you may use::
-
- def test_recursion_depth():
- with pytest.raises(RuntimeError) as excinfo:
- def f():
- f()
- f()
- assert 'maximum recursion' in str(excinfo.value)
-
-``excinfo`` is a ``ExceptionInfo`` instance, which is a wrapper around
-the actual exception raised. The main attributes of interest are
-``.type``, ``.value`` and ``.traceback``.
-
-If you want to write test code that works on Python 2.4 as well,
-you may also use two other ways to test for an expected exception::
-
- pytest.raises(ExpectedException, func, *args, **kwargs)
- pytest.raises(ExpectedException, "func(*args, **kwargs)")
-
-both of which execute the specified function with args and kwargs and
-asserts that the given ``ExpectedException`` is raised. The reporter will
-provide you with helpful output in case of failures such as *no
-exception* or *wrong exception*.
-
-Note that it is also possible to specify a "raises" argument to
-``pytest.mark.xfail``, which checks that the test is failing in a more
-specific way than just having any exception raised::
-
- @pytest.mark.xfail(raises=IndexError)
- def test_f():
- f()
-
-Using ``pytest.raises`` is likely to be better for cases where you are testing
-exceptions your own code is deliberately raising, whereas using
-``@pytest.mark.xfail`` with a check function is probably better for something
-like documenting unfixed bugs (where the test describes what "should" happen)
-or bugs in dependencies.
-
-
-.. _`assertwarns`:
-
-Assertions about expected warnings
------------------------------------------
-
-.. versionadded:: 2.8
-
-You can check that code raises a particular warning using
-:ref:`pytest.warns <warns>`.
-
-
-.. _newreport:
-
-Making use of context-sensitive comparisons
--------------------------------------------------
-
-.. versionadded:: 2.0
-
-``pytest`` has rich support for providing context-sensitive information
-when it encounters comparisons. For example::
-
- # content of test_assert2.py
-
- def test_set_comparison():
- set1 = set("1308")
- set2 = set("8035")
- assert set1 == set2
-
-if you run this module::
-
- $ py.test test_assert2.py
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 1 items
-
- test_assert2.py F
-
- ======= FAILURES ========
- _______ test_set_comparison ________
-
- def test_set_comparison():
- set1 = set("1308")
- set2 = set("8035")
- > assert set1 == set2
- E assert set(['0', '1', '3', '8']) == set(['0', '3', '5', '8'])
- E Extra items in the left set:
- E '1'
- E Extra items in the right set:
- E '5'
- E Use -v to get the full diff
-
- test_assert2.py:5: AssertionError
- ======= 1 failed in 0.12 seconds ========
-
-Special comparisons are done for a number of cases:
-
-* comparing long strings: a context diff is shown
-* comparing long sequences: first failing indices
-* comparing dicts: different entries
-
-See the :ref:`reporting demo <tbreportdemo>` for many more examples.
-
-Defining your own assertion comparison
-----------------------------------------------
-
-It is possible to add your own detailed explanations by implementing
-the ``pytest_assertrepr_compare`` hook.
-
-.. autofunction:: _pytest.hookspec.pytest_assertrepr_compare
-
-As an example consider adding the following hook in a conftest.py which
-provides an alternative explanation for ``Foo`` objects::
-
- # content of conftest.py
- from test_foocompare import Foo
- def pytest_assertrepr_compare(op, left, right):
- if isinstance(left, Foo) and isinstance(right, Foo) and op == "==":
- return ['Comparing Foo instances:',
- ' vals: %s != %s' % (left.val, right.val)]
-
-now, given this test module::
-
- # content of test_foocompare.py
- class Foo:
- def __init__(self, val):
- self.val = val
-
- def __eq__(self, other):
- return self.val == other.val
-
- def test_compare():
- f1 = Foo(1)
- f2 = Foo(2)
- assert f1 == f2
-
-you can run the test module and get the custom output defined in
-the conftest file::
-
- $ py.test -q test_foocompare.py
- F
- ======= FAILURES ========
- _______ test_compare ________
-
- def test_compare():
- f1 = Foo(1)
- f2 = Foo(2)
- > assert f1 == f2
- E assert Comparing Foo instances:
- E vals: 1 != 2
-
- test_foocompare.py:11: AssertionError
- 1 failed in 0.12 seconds
-
-.. _assert-details:
-.. _`assert introspection`:
-
-Advanced assertion introspection
-----------------------------------
-
-.. versionadded:: 2.1
-
-
-Reporting details about a failing assertion is achieved either by rewriting
-assert statements before they are run or re-evaluating the assert expression and
-recording the intermediate values. Which technique is used depends on the
-location of the assert, ``pytest`` configuration, and Python version being used
-to run ``pytest``.
-
-By default, ``pytest`` rewrites assert statements in test modules.
-Rewritten assert statements put introspection information into the assertion failure message.
-``pytest`` only rewrites test modules directly discovered by its test collection process, so
-asserts in supporting modules which are not themselves test modules will not be
-rewritten.
-
-.. note::
-
- ``pytest`` rewrites test modules on import. It does this by using an import
- hook to write a new pyc files. Most of the time this works transparently.
- However, if you are messing with import yourself, the import hook may
- interfere. If this is the case, simply use ``--assert=reinterp`` or
- ``--assert=plain``. Additionally, rewriting will fail silently if it cannot
- write new pycs, i.e. in a read-only filesystem or a zipfile.
-
-If an assert statement has not been rewritten or the Python version is less than
-2.6, ``pytest`` falls back on assert reinterpretation. In assert
-reinterpretation, ``pytest`` walks the frame of the function containing the
-assert statement to discover sub-expression results of the failing assert
-statement. You can force ``pytest`` to always use assertion reinterpretation by
-passing the ``--assert=reinterp`` option.
-
-Assert reinterpretation has a caveat not present with assert rewriting: If
-evaluating the assert expression has side effects you may get a warning that the
-intermediate values could not be determined safely. A common example of this
-issue is an assertion which reads from a file::
-
- assert f.read() != '...'
-
-If this assertion fails then the re-evaluation will probably succeed!
-This is because ``f.read()`` will return an empty string when it is
-called the second time during the re-evaluation. However, it is
-easy to rewrite the assertion and avoid any trouble::
-
- content = f.read()
- assert content != '...'
-
-All assert introspection can be turned off by passing ``--assert=plain``.
-
-For further information, Benjamin Peterson wrote up `Behind the scenes of pytest's new assertion rewriting <http://pybites.blogspot.com/2011/07/behind-scenes-of-pytests-new-assertion.html>`_.
-
-.. versionadded:: 2.1
- Add assert rewriting as an alternate introspection technique.
-
-.. versionchanged:: 2.1
- Introduce the ``--assert`` option. Deprecate ``--no-assert`` and
- ``--nomagic``.
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/bash-completion.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/bash-completion.rst
deleted file mode 100644
index b2a52fa637b..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/bash-completion.rst
+++ /dev/null
@@ -1,28 +0,0 @@
-
-.. _bash_completion:
-
-Setting up bash completion
-==========================
-
-When using bash as your shell, ``pytest`` can use argcomplete
-(https://argcomplete.readthedocs.org/) for auto-completion.
-For this ``argcomplete`` needs to be installed **and** enabled.
-
-Install argcomplete using::
-
- sudo pip install 'argcomplete>=0.5.7'
-
-For global activation of all argcomplete enabled python applications run::
-
- sudo activate-global-python-argcomplete
-
-For permanent (but not global) ``pytest`` activation, use::
-
- register-python-argcomplete py.test >> ~/.bashrc
-
-For one-time activation of argcomplete for ``pytest`` only, use::
-
- eval "$(register-python-argcomplete py.test)"
-
-
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/builtin.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/builtin.rst
deleted file mode 100644
index b18c3f8280a..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/builtin.rst
+++ /dev/null
@@ -1,134 +0,0 @@
-
-.. _`pytest helpers`:
-
-Pytest API and builtin fixtures
-================================================
-
-This is a list of ``pytest.*`` API functions and fixtures.
-
-For information on plugin hooks and objects, see :ref:`plugins`.
-
-For information on the ``pytest.mark`` mechanism, see :ref:`mark`.
-
-For the below objects, you can also interactively ask for help, e.g. by
-typing on the Python interactive prompt something like::
-
- import pytest
- help(pytest)
-
-.. currentmodule:: pytest
-
-Invoking pytest interactively
----------------------------------------------------
-
-.. autofunction:: main
-
-More examples at :ref:`pytest.main-usage`
-
-
-Helpers for assertions about Exceptions/Warnings
---------------------------------------------------------
-
-.. autofunction:: raises
-
-Examples at :ref:`assertraises`.
-
-.. autofunction:: deprecated_call
-
-Raising a specific test outcome
---------------------------------------
-
-You can use the following functions in your test, fixture or setup
-functions to force a certain test outcome. Note that most often
-you can rather use declarative marks, see :ref:`skipping`.
-
-.. autofunction:: _pytest.runner.fail
-.. autofunction:: _pytest.runner.skip
-.. autofunction:: _pytest.runner.importorskip
-.. autofunction:: _pytest.skipping.xfail
-.. autofunction:: _pytest.runner.exit
-
-fixtures and requests
------------------------------------------------------
-
-To mark a fixture function:
-
-.. autofunction:: _pytest.python.fixture
-
-Tutorial at :ref:`fixtures`.
-
-The ``request`` object that can be used from fixture functions.
-
-.. autoclass:: _pytest.python.FixtureRequest()
- :members:
-
-
-.. _builtinfixtures:
-.. _builtinfuncargs:
-
-Builtin fixtures/function arguments
------------------------------------------
-
-You can ask for available builtin or project-custom
-:ref:`fixtures <fixtures>` by typing::
-
- $ py.test -q --fixtures
- cache
- Return a cache object that can persist state between testing sessions.
-
- cache.get(key, default)
- cache.set(key, value)
-
- Keys must be a ``/`` separated value, where the first part is usually the
- name of your plugin or application to avoid clashes with other cache users.
-
- Values can be any object handled by the json stdlib module.
- capsys
- enables capturing of writes to sys.stdout/sys.stderr and makes
- captured output available via ``capsys.readouterr()`` method calls
- which return a ``(out, err)`` tuple.
- capfd
- enables capturing of writes to file descriptors 1 and 2 and makes
- captured output available via ``capfd.readouterr()`` method calls
- which return a ``(out, err)`` tuple.
- record_xml_property
- Fixture that adds extra xml properties to the tag for the calling test.
- The fixture is callable with (name, value), with value being automatically
- xml-encoded.
- monkeypatch
- The returned ``monkeypatch`` funcarg provides these
- helper methods to modify objects, dictionaries or os.environ::
-
- monkeypatch.setattr(obj, name, value, raising=True)
- monkeypatch.delattr(obj, name, raising=True)
- monkeypatch.setitem(mapping, name, value)
- monkeypatch.delitem(obj, name, raising=True)
- monkeypatch.setenv(name, value, prepend=False)
- monkeypatch.delenv(name, value, raising=True)
- monkeypatch.syspath_prepend(path)
- monkeypatch.chdir(path)
-
- All modifications will be undone after the requesting
- test function has finished. The ``raising``
- parameter determines if a KeyError or AttributeError
- will be raised if the set/deletion operation has no target.
- pytestconfig
- the pytest config object with access to command line opts.
- recwarn
- Return a WarningsRecorder instance that provides these methods:
-
- * ``pop(category=None)``: return last warning matching the category.
- * ``clear()``: clear list of warnings
-
- See http://docs.python.org/library/warnings.html for information
- on warning categories.
- tmpdir_factory
- Return a TempdirFactory instance for the test session.
- tmpdir
- return a temporary directory path object
- which is unique to each test function invocation,
- created as a sub directory of the base temporary
- directory. The returned object is a `py.path.local`_
- path object.
-
- no tests ran in 0.12 seconds
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/cache.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/cache.rst
deleted file mode 100644
index 52abb52a0df..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/cache.rst
+++ /dev/null
@@ -1,278 +0,0 @@
-Cache: working with cross-testrun state
-=======================================
-
-.. versionadded:: 2.8
-
-.. warning::
-
- The functionality of this core plugin was previously distributed
- as a third party plugin named ``pytest-cache``. The core plugin
- is compatible regarding command line options and API usage except that you
- can only store/receive data between test runs that is json-serializable.
-
-
-Usage
----------
-
-The plugin provides two command line options to rerun failures from the
-last ``py.test`` invocation:
-
-* ``--lf``, ``--last-failed`` - to only re-run the failures.
-* ``--ff``, ``--failed-first`` - to run the failures first and then the rest of
- the tests.
-
-For cleanup (usually not needed), a ``--cache-clear`` option allows to remove
-all cross-session cache contents ahead of a test run.
-
-Other plugins may access the `config.cache`_ object to set/get
-**json encodable** values between ``py.test`` invocations.
-
-.. note::
-
- This plugin is enabled by default, but can be disabled if needed: see
- :ref:`cmdunregister` (the internal name for this plugin is
- ``cacheprovider``).
-
-
-Rerunning only failures or failures first
------------------------------------------------
-
-First, let's create 50 test invocation of which only 2 fail::
-
- # content of test_50.py
- import pytest
-
- @pytest.mark.parametrize("i", range(50))
- def test_num(i):
- if i in (17, 25):
- pytest.fail("bad luck")
-
-If you run this for the first time you will see two failures::
-
- $ py.test -q
- .................F.......F........................
- ======= FAILURES ========
- _______ test_num[17] ________
-
- i = 17
-
- @pytest.mark.parametrize("i", range(50))
- def test_num(i):
- if i in (17, 25):
- > pytest.fail("bad luck")
- E Failed: bad luck
-
- test_50.py:6: Failed
- _______ test_num[25] ________
-
- i = 25
-
- @pytest.mark.parametrize("i", range(50))
- def test_num(i):
- if i in (17, 25):
- > pytest.fail("bad luck")
- E Failed: bad luck
-
- test_50.py:6: Failed
- 2 failed, 48 passed in 0.12 seconds
-
-If you then run it with ``--lf``::
-
- $ py.test --lf
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- run-last-failure: rerun last 2 failures
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 50 items
-
- test_50.py FF
-
- ======= FAILURES ========
- _______ test_num[17] ________
-
- i = 17
-
- @pytest.mark.parametrize("i", range(50))
- def test_num(i):
- if i in (17, 25):
- > pytest.fail("bad luck")
- E Failed: bad luck
-
- test_50.py:6: Failed
- _______ test_num[25] ________
-
- i = 25
-
- @pytest.mark.parametrize("i", range(50))
- def test_num(i):
- if i in (17, 25):
- > pytest.fail("bad luck")
- E Failed: bad luck
-
- test_50.py:6: Failed
- ======= 2 failed, 48 deselected in 0.12 seconds ========
-
-You have run only the two failing test from the last run, while 48 tests have
-not been run ("deselected").
-
-Now, if you run with the ``--ff`` option, all tests will be run but the first
-previous failures will be executed first (as can be seen from the series
-of ``FF`` and dots)::
-
- $ py.test --ff
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- run-last-failure: rerun last 2 failures first
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 50 items
-
- test_50.py FF................................................
-
- ======= FAILURES ========
- _______ test_num[17] ________
-
- i = 17
-
- @pytest.mark.parametrize("i", range(50))
- def test_num(i):
- if i in (17, 25):
- > pytest.fail("bad luck")
- E Failed: bad luck
-
- test_50.py:6: Failed
- _______ test_num[25] ________
-
- i = 25
-
- @pytest.mark.parametrize("i", range(50))
- def test_num(i):
- if i in (17, 25):
- > pytest.fail("bad luck")
- E Failed: bad luck
-
- test_50.py:6: Failed
- ======= 2 failed, 48 passed in 0.12 seconds ========
-
-.. _`config.cache`:
-
-The new config.cache object
---------------------------------
-
-.. regendoc:wipe
-
-Plugins or conftest.py support code can get a cached value using the
-pytest ``config`` object. Here is a basic example plugin which
-implements a :ref:`fixture` which re-uses previously created state
-across py.test invocations::
-
- # content of test_caching.py
- import pytest
- import time
-
- @pytest.fixture
- def mydata(request):
- val = request.config.cache.get("example/value", None)
- if val is None:
- time.sleep(9*0.6) # expensive computation :)
- val = 42
- request.config.cache.set("example/value", val)
- return val
-
- def test_function(mydata):
- assert mydata == 23
-
-If you run this command once, it will take a while because
-of the sleep::
-
- $ py.test -q
- F
- ======= FAILURES ========
- _______ test_function ________
-
- mydata = 42
-
- def test_function(mydata):
- > assert mydata == 23
- E assert 42 == 23
-
- test_caching.py:14: AssertionError
- 1 failed in 0.12 seconds
-
-If you run it a second time the value will be retrieved from
-the cache and this will be quick::
-
- $ py.test -q
- F
- ======= FAILURES ========
- _______ test_function ________
-
- mydata = 42
-
- def test_function(mydata):
- > assert mydata == 23
- E assert 42 == 23
-
- test_caching.py:14: AssertionError
- 1 failed in 0.12 seconds
-
-See the `cache-api`_ for more details.
-
-
-Inspecting Cache content
--------------------------------
-
-You can always peek at the content of the cache using the
-``--cache-clear`` command line option::
-
- $ py.test --cache-clear
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 1 items
-
- test_caching.py F
-
- ======= FAILURES ========
- _______ test_function ________
-
- mydata = 42
-
- def test_function(mydata):
- > assert mydata == 23
- E assert 42 == 23
-
- test_caching.py:14: AssertionError
- ======= 1 failed in 0.12 seconds ========
-
-Clearing Cache content
--------------------------------
-
-You can instruct pytest to clear all cache files and values
-by adding the ``--cache-clear`` option like this::
-
- py.test --cache-clear
-
-This is recommended for invocations from Continous Integration
-servers where isolation and correctness is more important
-than speed.
-
-
-.. _`cache-api`:
-
-config.cache API
-------------------
-
-The ``config.cache`` object allows other plugins,
-including ``conftest.py`` files,
-to safely and flexibly store and retrieve values across
-test runs because the ``config`` object is available
-in many places.
-
-Under the hood, the cache plugin uses the simple
-dumps/loads API of the json stdlib module
-
-.. currentmodule:: _pytest.cacheprovider
-
-.. automethod:: Cache.get
-.. automethod:: Cache.set
-.. automethod:: Cache.makedir
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/capture.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/capture.rst
deleted file mode 100644
index 8892f5be756..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/capture.rst
+++ /dev/null
@@ -1,118 +0,0 @@
-
-.. _`captures`:
-
-Capturing of the stdout/stderr output
-=========================================================
-
-Default stdout/stderr/stdin capturing behaviour
----------------------------------------------------------
-
-During test execution any output sent to ``stdout`` and ``stderr`` is
-captured. If a test or a setup method fails its according captured
-output will usually be shown along with the failure traceback.
-
-In addition, ``stdin`` is set to a "null" object which will
-fail on attempts to read from it because it is rarely desired
-to wait for interactive input when running automated tests.
-
-By default capturing is done by intercepting writes to low level
-file descriptors. This allows to capture output from simple
-print statements as well as output from a subprocess started by
-a test.
-
-Setting capturing methods or disabling capturing
--------------------------------------------------
-
-There are two ways in which ``pytest`` can perform capturing:
-
-* file descriptor (FD) level capturing (default): All writes going to the
- operating system file descriptors 1 and 2 will be captured.
-
-* ``sys`` level capturing: Only writes to Python files ``sys.stdout``
- and ``sys.stderr`` will be captured. No capturing of writes to
- filedescriptors is performed.
-
-.. _`disable capturing`:
-
-You can influence output capturing mechanisms from the command line::
-
- py.test -s # disable all capturing
- py.test --capture=sys # replace sys.stdout/stderr with in-mem files
- py.test --capture=fd # also point filedescriptors 1 and 2 to temp file
-
-.. _printdebugging:
-
-Using print statements for debugging
----------------------------------------------------
-
-One primary benefit of the default capturing of stdout/stderr output
-is that you can use print statements for debugging::
-
- # content of test_module.py
-
- def setup_function(function):
- print ("setting up %s" % function)
-
- def test_func1():
- assert True
-
- def test_func2():
- assert False
-
-and running this module will show you precisely the output
-of the failing function and hide the other one::
-
- $ py.test
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 2 items
-
- test_module.py .F
-
- ======= FAILURES ========
- _______ test_func2 ________
-
- def test_func2():
- > assert False
- E assert False
-
- test_module.py:9: AssertionError
- -------------------------- Captured stdout setup ---------------------------
- setting up <function test_func2 at 0xdeadbeef>
- ======= 1 failed, 1 passed in 0.12 seconds ========
-
-Accessing captured output from a test function
----------------------------------------------------
-
-The ``capsys`` and ``capfd`` fixtures allow to access stdout/stderr
-output created during test execution. Here is an example test function
-that performs some output related checks:
-
-.. code-block:: python
-
- def test_myoutput(capsys): # or use "capfd" for fd-level
- print ("hello")
- sys.stderr.write("world\n")
- out, err = capsys.readouterr()
- assert out == "hello\n"
- assert err == "world\n"
- print "next"
- out, err = capsys.readouterr()
- assert out == "next\n"
-
-The ``readouterr()`` call snapshots the output so far -
-and capturing will be continued. After the test
-function finishes the original streams will
-be restored. Using ``capsys`` this way frees your
-test from having to care about setting/resetting
-output streams and also interacts well with pytest's
-own per-test capturing.
-
-If you want to capture on filedescriptor level you can use
-the ``capfd`` function argument which offers the exact
-same interface but allows to also capture output from
-libraries or subprocesses that directly write to operating
-system level output streams (FD1 and FD2).
-
-.. include:: links.inc
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/conf.py b/tests/wpt/web-platform-tests/tools/pytest/doc/en/conf.py
deleted file mode 100644
index aca0442c5d6..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/conf.py
+++ /dev/null
@@ -1,326 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# pytest documentation build configuration file, created by
-# sphinx-quickstart on Fri Oct 8 17:54:28 2010.
-#
-# This file is execfile()d with the current directory set to its containing dir.
-#
-# Note that not all possible configuration values are present in this
-# autogenerated file.
-#
-# All configuration values have a default; values that are commented out
-# serve to show the default.
-
-# The version info for the project you're documenting, acts as replacement for
-# |version| and |release|, also used in various other places throughout the
-# built documents.
-#
-# The full version, including alpha/beta/rc tags.
-# The short X.Y version.
-
-import os, sys
-sys.path.insert(0, os.path.dirname(__file__))
-import _getdoctarget
-
-version = _getdoctarget.get_minor_version_string()
-release = _getdoctarget.get_version_string()
-
-# If extensions (or modules to document with autodoc) are in another directory,
-# add these directories to sys.path here. If the directory is relative to the
-# documentation root, use os.path.abspath to make it absolute, like shown here.
-#sys.path.insert(0, os.path.abspath('.'))
-
-autodoc_member_order = "bysource"
-todo_include_todos = 1
-
-# -- General configuration -----------------------------------------------------
-
-# If your documentation needs a minimal Sphinx version, state it here.
-#needs_sphinx = '1.0'
-
-# Add any Sphinx extension module names here, as strings. They can be extensions
-# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.autosummary',
- 'sphinx.ext.intersphinx', 'sphinx.ext.viewcode']
-
-# Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
-
-# The suffix of source filenames.
-source_suffix = '.rst'
-
-# The encoding of source files.
-#source_encoding = 'utf-8-sig'
-
-# The master toctree document.
-master_doc = 'contents'
-
-# General information about the project.
-project = u'pytest'
-copyright = u'2015, holger krekel and pytest-dev team'
-
-
-
-# The language for content autogenerated by Sphinx. Refer to documentation
-# for a list of supported languages.
-#language = None
-
-# There are two options for replacing |today|: either, you set today to some
-# non-false value, then it is used:
-#today = ''
-# Else, today_fmt is used as the format for a strftime call.
-#today_fmt = '%B %d, %Y'
-
-# List of patterns, relative to source directory, that match files and
-# directories to ignore when looking for source files.
-exclude_patterns = ['links.inc', '_build', 'naming20.rst', 'test/*',
- "old_*",
- '*attic*',
- '*/attic*',
- 'funcargs.rst',
- 'setup.rst',
- 'example/remoteinterp.rst',
- ]
-
-
-# The reST default role (used for this markup: `text`) to use for all documents.
-#default_role = None
-
-# If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
-
-# If true, the current module name will be prepended to all description
-# unit titles (such as .. function::).
-add_module_names = False
-
-# If true, sectionauthor and moduleauthor directives will be shown in the
-# output. They are ignored by default.
-#show_authors = False
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
-
-
-
-# A list of ignored prefixes for module index sorting.
-#modindex_common_prefix = []
-
-
-# -- Options for HTML output ---------------------------------------------------
-
-sys.path.append(os.path.abspath('_themes'))
-html_theme_path = ['_themes']
-
-# The theme to use for HTML and HTML Help pages. See the documentation for
-# a list of builtin themes.
-html_theme = 'flask'
-
-# Theme options are theme-specific and customize the look and feel of a theme
-# further. For a list of options available for each theme, see the
-# documentation.
-html_theme_options = {
- 'index_logo': None
-}
-
-# Add any paths that contain custom themes here, relative to this directory.
-#html_theme_path = []
-
-# The name for this set of Sphinx documents. If None, it defaults to
-# "<project> v<release> documentation".
-html_title = None
-
-# A shorter title for the navigation bar. Default is the same as html_title.
-html_short_title = "pytest-%s" % release
-
-# The name of an image file (relative to this directory) to place at the top
-# of the sidebar.
-html_logo = "img/pytest1.png"
-
-# The name of an image file (within the static path) to use as favicon of the
-# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
-# pixels large.
-html_favicon = "img/pytest1favi.ico"
-
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
-
-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-# using the given strftime format.
-#html_last_updated_fmt = '%b %d, %Y'
-
-# If true, SmartyPants will be used to convert quotes and dashes to
-# typographically correct entities.
-#html_use_smartypants = True
-
-# Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
-#html_sidebars = {'index': 'indexsidebar.html'}
-
-html_sidebars = {
- 'index': [
- 'sidebarintro.html',
- 'globaltoc.html',
- 'links.html',
- 'sourcelink.html',
- 'searchbox.html'
- ],
- '**': [
- 'globaltoc.html',
- 'relations.html',
- 'links.html',
- 'sourcelink.html',
- 'searchbox.html'
- ]
-}
-
-# Additional templates that should be rendered to pages, maps page names to
-# template names.
-#html_additional_pages = {}
-#html_additional_pages = {'index': 'index.html'}
-
-
-# If false, no module index is generated.
-html_domain_indices = True
-
-# If false, no index is generated.
-html_use_index = False
-
-# If true, the index is split into individual pages for each letter.
-#html_split_index = False
-
-# If true, links to the reST sources are added to the pages.
-html_show_sourcelink = False
-
-# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#html_show_sphinx = True
-
-# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#html_show_copyright = True
-
-# If true, an OpenSearch description file will be output, and all pages will
-# contain a <link> tag referring to it. The value of this option must be the
-# base URL from which the finished HTML is served.
-#html_use_opensearch = ''
-
-# This is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = None
-
-# Output file base name for HTML help builder.
-htmlhelp_basename = 'pytestdoc'
-
-
-# -- Options for LaTeX output --------------------------------------------------
-
-# The paper size ('letter' or 'a4').
-#latex_paper_size = 'letter'
-
-# The font size ('10pt', '11pt' or '12pt').
-#latex_font_size = '10pt'
-
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title, author, documentclass [howto/manual]).
-latex_documents = [
- ('contents', 'pytest.tex', u'pytest Documentation',
- u'holger krekel, trainer and consultant, http://merlinux.eu', 'manual'),
-]
-
-# The name of an image file (relative to this directory) to place at the top of
-# the title page.
-latex_logo = 'img/pytest1.png'
-
-# For "manual" documents, if this is true, then toplevel headings are parts,
-# not chapters.
-#latex_use_parts = False
-
-# If true, show page references after internal links.
-#latex_show_pagerefs = False
-
-# If true, show URL addresses after external links.
-#latex_show_urls = False
-
-# Additional stuff for the LaTeX preamble.
-#latex_preamble = ''
-
-# Documents to append as an appendix to all manuals.
-#latex_appendices = []
-
-# If false, no module index is generated.
-latex_domain_indices = False
-
-# -- Options for manual page output --------------------------------------------
-
-# One entry per manual page. List of tuples
-# (source start file, name, description, authors, manual section).
-man_pages = [
- ('usage', 'pytest', u'pytest usage',
- [u'holger krekel at merlinux eu'], 1)
-]
-
-
-# -- Options for Epub output ---------------------------------------------------
-
-# Bibliographic Dublin Core info.
-epub_title = u'pytest'
-epub_author = u'holger krekel at merlinux eu'
-epub_publisher = u'holger krekel at merlinux eu'
-epub_copyright = u'2013, holger krekel et alii'
-
-# The language of the text. It defaults to the language option
-# or en if the language is not set.
-#epub_language = ''
-
-# The scheme of the identifier. Typical schemes are ISBN or URL.
-#epub_scheme = ''
-
-# The unique identifier of the text. This can be a ISBN number
-# or the project homepage.
-#epub_identifier = ''
-
-# A unique identification for the text.
-#epub_uid = ''
-
-# HTML files that should be inserted before the pages created by sphinx.
-# The format is a list of tuples containing the path and title.
-#epub_pre_files = []
-
-# HTML files shat should be inserted after the pages created by sphinx.
-# The format is a list of tuples containing the path and title.
-#epub_post_files = []
-
-# A list of files that should not be packed into the epub file.
-#epub_exclude_files = []
-
-# The depth of the table of contents in toc.ncx.
-#epub_tocdepth = 3
-
-# Allow duplicate toc entries.
-#epub_tocdup = True
-
-
-# -- Options for texinfo output ------------------------------------------------
-
-texinfo_documents = [
- (master_doc, 'pytest', 'pytest Documentation',
- ('Holger Krekel@*Benjamin Peterson@*Ronny Pfannschmidt@*'
- 'Floris Bruynooghe@*others'),
- 'pytest',
- 'simple powerful testing with Pytho',
- 'Programming',
- 1),
-]
-
-
-# Example configuration for intersphinx: refer to the Python standard library.
-intersphinx_mapping = {'python': ('http://docs.python.org/', None),
-# 'lib': ("http://docs.python.org/2.7library/", None),
- }
-
-
-def setup(app):
- #from sphinx.ext.autodoc import cut_lines
- #app.connect('autodoc-process-docstring', cut_lines(4, what=['module']))
- app.add_description_unit('confval', 'confval',
- objname='configuration value',
- indextemplate='pair: %s; configuration value')
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/contact.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/contact.rst
deleted file mode 100644
index d4a1a03dee3..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/contact.rst
+++ /dev/null
@@ -1,51 +0,0 @@
-
-.. _`contact channels`:
-.. _`contact`:
-
-Contact channels
-===================================
-
-- `pytest issue tracker`_ to report bugs or suggest features (for version
- 2.0 and above).
-
-- `pytest on stackoverflow.com <http://stackoverflow.com/search?q=pytest>`_
- to post questions with the tag ``pytest``. New Questions will usually
- be seen by pytest users or developers and answered quickly.
-
-- `Testing In Python`_: a mailing list for Python testing tools and discussion.
-
-- `pytest-dev at python.org (mailing list)`_ pytest specific announcements and discussions.
-
-- `pytest-commit at python.org (mailing list)`_: for commits and new issues
-
-- :doc:`contribution guide <contributing>` for help on submitting pull
- requests to bitbucket (including using git via gitifyhg).
-
-- #pylib on irc.freenode.net IRC channel for random questions.
-
-- private mail to Holger.Krekel at gmail com if you want to communicate sensitive issues
-
-
-- `merlinux.eu`_ offers pytest and tox-related professional teaching and
- consulting.
-
-.. _`pytest issue tracker`: https://github.com/pytest-dev/pytest/issues
-.. _`old issue tracker`: http://bitbucket.org/hpk42/py-trunk/issues/
-
-.. _`merlinux.eu`: http://merlinux.eu
-
-.. _`get an account`:
-
-.. _tetamap: http://tetamap.wordpress.com
-
-.. _`@pylibcommit`: http://twitter.com/pylibcommit
-
-
-.. _`Testing in Python`: http://lists.idyll.org/listinfo/testing-in-python
-.. _FOAF: http://en.wikipedia.org/wiki/FOAF
-.. _`py-dev`:
-.. _`development mailing list`:
-.. _`pytest-dev at python.org (mailing list)`: http://mail.python.org/mailman/listinfo/pytest-dev
-.. _`py-svn`:
-.. _`pytest-commit at python.org (mailing list)`: http://mail.python.org/mailman/listinfo/pytest-commit
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/contents.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/contents.rst
deleted file mode 100644
index 48c3471b5e2..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/contents.rst
+++ /dev/null
@@ -1,39 +0,0 @@
-.. _toc:
-
-Full pytest documentation
-===========================
-
-`Download latest version as PDF <pytest.pdf>`_
-
-.. `Download latest version as EPUB <http://media.readthedocs.org/epub/pytest/latest/pytest.epub>`_
-
-.. toctree::
- :maxdepth: 2
-
- overview
- apiref
- example/index
- monkeypatch
- tmpdir
- capture
- recwarn
- cache
- plugins
-
- contributing
- talks
-
-.. only:: html
-
- .. toctree::
-
- funcarg_compare
- announce/index
-
-.. only:: html
-
- .. toctree::
- :hidden:
-
- changelog
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/customize.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/customize.rst
deleted file mode 100644
index 34e319c246a..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/customize.rst
+++ /dev/null
@@ -1,228 +0,0 @@
-Basic test configuration
-===================================
-
-Command line options and configuration file settings
------------------------------------------------------------------
-
-You can get help on command line options and values in INI-style
-configurations files by using the general help option::
-
- py.test -h # prints options _and_ config file settings
-
-This will display command line and configuration file settings
-which were registered by installed plugins.
-
-.. _rootdir:
-.. _inifiles:
-
-initialization: determining rootdir and inifile
------------------------------------------------
-
-.. versionadded:: 2.7
-
-pytest determines a "rootdir" for each test run which depends on
-the command line arguments (specified test files, paths) and on
-the existence of inifiles. The determined rootdir and ini-file are
-printed as part of the pytest header. The rootdir is used for constructing
-"nodeids" during collection and may also be used by plugins to store
-project/testrun-specific information.
-
-Here is the algorithm which finds the rootdir from ``args``:
-
-- determine the common ancestor directory for the specified ``args``.
-
-- look for ``pytest.ini``, ``tox.ini`` and ``setup.cfg`` files in the
- ancestor directory and upwards. If one is matched, it becomes the
- ini-file and its directory becomes the rootdir. An existing
- ``pytest.ini`` file will always be considered a match whereas
- ``tox.ini`` and ``setup.cfg`` will only match if they contain
- a ``[pytest]`` section.
-
-- if no ini-file was found, look for ``setup.py`` upwards from
- the common ancestor directory to determine the ``rootdir``.
-
-- if no ini-file and no ``setup.py`` was found, use the already
- determined common ancestor as root directory. This allows to
- work with pytest in structures that are not part of a package
- and don't have any particular ini-file configuration.
-
-Note that options from multiple ini-files candidates are never merged,
-the first one wins (``pytest.ini`` always wins even if it does not
-contain a ``[pytest]`` section).
-
-The ``config`` object will subsequently carry these attributes:
-
-- ``config.rootdir``: the determined root directory, guaranteed to exist.
-
-- ``config.inifile``: the determined ini-file, may be ``None``.
-
-The rootdir is used a reference directory for constructing test
-addresses ("nodeids") and can be used also by plugins for storing
-per-testrun information.
-
-Example::
-
- py.test path/to/testdir path/other/
-
-will determine the common ancestor as ``path`` and then
-check for ini-files as follows::
-
- # first look for pytest.ini files
- path/pytest.ini
- path/setup.cfg # must also contain [pytest] section to match
- path/tox.ini # must also contain [pytest] section to match
- pytest.ini
- ... # all the way down to the root
-
- # now look for setup.py
- path/setup.py
- setup.py
- ... # all the way down to the root
-
-
-.. _`how to change command line options defaults`:
-.. _`adding default options`:
-
-How to change command line options defaults
-------------------------------------------------
-
-It can be tedious to type the same series of command line options
-every time you use ``pytest``. For example, if you always want to see
-detailed info on skipped and xfailed tests, as well as have terser "dot"
-progress output, you can write it into a configuration file:
-
-.. code-block:: ini
-
- # content of pytest.ini
- # (or tox.ini or setup.cfg)
- [pytest]
- addopts = -rsxX -q
-
-Alternatively, you can set a PYTEST_ADDOPTS environment variable to add command
-line options while the environment is in use::
-
- export PYTEST_ADDOPTS="-rsxX -q"
-
-From now on, running ``pytest`` will add the specified options.
-
-
-
-Builtin configuration file options
-----------------------------------------------
-
-.. confval:: minversion
-
- Specifies a minimal pytest version required for running tests.
-
- minversion = 2.1 # will fail if we run with pytest-2.0
-
-.. confval:: addopts
-
- Add the specified ``OPTS`` to the set of command line arguments as if they
- had been specified by the user. Example: if you have this ini file content:
-
- .. code-block:: ini
-
- [pytest]
- addopts = --maxfail=2 -rf # exit after 2 failures, report fail info
-
- issuing ``py.test test_hello.py`` actually means::
-
- py.test --maxfail=2 -rf test_hello.py
-
- Default is to add no options.
-
-.. confval:: norecursedirs
-
- Set the directory basename patterns to avoid when recursing
- for test discovery. The individual (fnmatch-style) patterns are
- applied to the basename of a directory to decide if to recurse into it.
- Pattern matching characters::
-
- * matches everything
- ? matches any single character
- [seq] matches any character in seq
- [!seq] matches any char not in seq
-
- Default patterns are ``'.*', 'CVS', '_darcs', '{arch}', '*.egg'``.
- Setting a ``norecursedirs`` replaces the default. Here is an example of
- how to avoid certain directories:
-
- .. code-block:: ini
-
- # content of setup.cfg
- [pytest]
- norecursedirs = .svn _build tmp*
-
- This would tell ``pytest`` to not look into typical subversion or
- sphinx-build directories or into any ``tmp`` prefixed directory.
-
-.. confval:: testpaths
-
- .. versionadded:: 2.8
-
- Sets list of directories that should be searched for tests when
- no specific directories, files or test ids are given in the command line when
- executing pytest from the :ref:`rootdir <rootdir>` directory.
- Useful when all project tests are in a known location to speed up
- test collection and to avoid picking up undesired tests by accident.
-
- .. code-block:: ini
-
- # content of pytest.ini
- [pytest]
- testpaths = testing doc
-
- This tells pytest to only look for tests in ``testing`` and ``doc``
- directories when executing from the root directory.
-
-.. confval:: python_files
-
- One or more Glob-style file patterns determining which python files
- are considered as test modules.
-
-.. confval:: python_classes
-
- One or more name prefixes or glob-style patterns determining which classes
- are considered for test collection. Here is an example of how to collect
- tests from classes that end in ``Suite``:
-
- .. code-block:: ini
-
- # content of pytest.ini
- [pytest]
- python_classes = *Suite
-
- Note that ``unittest.TestCase`` derived classes are always collected
- regardless of this option, as ``unittest``'s own collection framework is used
- to collect those tests.
-
-.. confval:: python_functions
-
- One or more name prefixes or glob-patterns determining which test functions
- and methods are considered tests. Here is an example of how
- to collect test functions and methods that end in ``_test``:
-
- .. code-block:: ini
-
- # content of pytest.ini
- [pytest]
- python_functions = *_test
-
- Note that this has no effect on methods that live on a ``unittest
- .TestCase`` derived class, as ``unittest``'s own collection framework is used
- to collect those tests.
-
- See :ref:`change naming conventions` for more detailed examples.
-
-.. confval:: doctest_optionflags
-
- One or more doctest flag names from the standard ``doctest`` module.
- :doc:`See how py.test handles doctests <doctest>`.
-
-.. confval:: confcutdir
-
- Sets a directory where search upwards for ``conftest.py`` files stops.
- By default, pytest will stop searching for ``conftest.py`` files upwards
- from ``pytest.ini``/``tox.ini``/``setup.cfg`` of the project if any,
- or up to the file-system root.
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/doctest.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/doctest.rst
deleted file mode 100644
index db764141ecb..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/doctest.rst
+++ /dev/null
@@ -1,105 +0,0 @@
-
-Doctest integration for modules and test files
-=========================================================
-
-By default all files matching the ``test*.txt`` pattern will
-be run through the python standard ``doctest`` module. You
-can change the pattern by issuing::
-
- py.test --doctest-glob='*.rst'
-
-on the command line. Since version ``2.9``, ``--doctest-glob``
-can be given multiple times in the command-line.
-
-You can also trigger running of doctests
-from docstrings in all python modules (including regular
-python test modules)::
-
- py.test --doctest-modules
-
-You can make these changes permanent in your project by
-putting them into a pytest.ini file like this:
-
-.. code-block:: ini
-
- # content of pytest.ini
- [pytest]
- addopts = --doctest-modules
-
-If you then have a text file like this::
-
- # content of example.rst
-
- hello this is a doctest
- >>> x = 3
- >>> x
- 3
-
-and another like this::
-
- # content of mymodule.py
- def something():
- """ a doctest in a docstring
- >>> something()
- 42
- """
- return 42
-
-then you can just invoke ``py.test`` without command line options::
-
- $ py.test
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
- collected 1 items
-
- mymodule.py .
-
- ======= 1 passed in 0.12 seconds ========
-
-It is possible to use fixtures using the ``getfixture`` helper::
-
- # content of example.rst
- >>> tmp = getfixture('tmpdir')
- >>> ...
- >>>
-
-Also, :ref:`usefixtures` and :ref:`autouse` fixtures are supported
-when executing text doctest files.
-
-The standard ``doctest`` module provides some setting flags to configure the
-strictness of doctest tests. In py.test You can enable those flags those flags
-using the configuration file. To make pytest ignore trailing whitespaces and
-ignore lengthy exception stack traces you can just write:
-
-.. code-block:: ini
-
- [pytest]
- doctest_optionflags= NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL
-
-py.test also introduces new options to allow doctests to run in Python 2 and
-Python 3 unchanged:
-
-* ``ALLOW_UNICODE``: when enabled, the ``u`` prefix is stripped from unicode
- strings in expected doctest output.
-
-* ``ALLOW_BYTES``: when enabled, the ``b`` prefix is stripped from byte strings
- in expected doctest output.
-
-As with any other option flag, these flags can be enabled in ``pytest.ini`` using
-the ``doctest_optionflags`` ini option:
-
-.. code-block:: ini
-
- [pytest]
- doctest_optionflags = ALLOW_UNICODE ALLOW_BYTES
-
-
-Alternatively, it can be enabled by an inline comment in the doc test
-itself::
-
- # content of example.rst
- >>> get_unicode_greeting() # doctest: +ALLOW_UNICODE
- 'Hello'
-
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/assertion/failure_demo.py b/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/assertion/failure_demo.py
deleted file mode 100644
index a4ff758b18c..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/assertion/failure_demo.py
+++ /dev/null
@@ -1,238 +0,0 @@
-from pytest import raises
-import _pytest._code
-import py
-
-def otherfunc(a,b):
- assert a==b
-
-def somefunc(x,y):
- otherfunc(x,y)
-
-def otherfunc_multi(a,b):
- assert (a ==
- b)
-
-def test_generative(param1, param2):
- assert param1 * 2 < param2
-
-def pytest_generate_tests(metafunc):
- if 'param1' in metafunc.fixturenames:
- metafunc.addcall(funcargs=dict(param1=3, param2=6))
-
-class TestFailing(object):
- def test_simple(self):
- def f():
- return 42
- def g():
- return 43
-
- assert f() == g()
-
- def test_simple_multiline(self):
- otherfunc_multi(
- 42,
- 6*9)
-
- def test_not(self):
- def f():
- return 42
- assert not f()
-
-class TestSpecialisedExplanations(object):
- def test_eq_text(self):
- assert 'spam' == 'eggs'
-
- def test_eq_similar_text(self):
- assert 'foo 1 bar' == 'foo 2 bar'
-
- def test_eq_multiline_text(self):
- assert 'foo\nspam\nbar' == 'foo\neggs\nbar'
-
- def test_eq_long_text(self):
- a = '1'*100 + 'a' + '2'*100
- b = '1'*100 + 'b' + '2'*100
- assert a == b
-
- def test_eq_long_text_multiline(self):
- a = '1\n'*100 + 'a' + '2\n'*100
- b = '1\n'*100 + 'b' + '2\n'*100
- assert a == b
-
- def test_eq_list(self):
- assert [0, 1, 2] == [0, 1, 3]
-
- def test_eq_list_long(self):
- a = [0]*100 + [1] + [3]*100
- b = [0]*100 + [2] + [3]*100
- assert a == b
-
- def test_eq_dict(self):
- assert {'a': 0, 'b': 1, 'c': 0} == {'a': 0, 'b': 2, 'd': 0}
-
- def test_eq_set(self):
- assert set([0, 10, 11, 12]) == set([0, 20, 21])
-
- def test_eq_longer_list(self):
- assert [1,2] == [1,2,3]
-
- def test_in_list(self):
- assert 1 in [0, 2, 3, 4, 5]
-
- def test_not_in_text_multiline(self):
- text = 'some multiline\ntext\nwhich\nincludes foo\nand a\ntail'
- assert 'foo' not in text
-
- def test_not_in_text_single(self):
- text = 'single foo line'
- assert 'foo' not in text
-
- def test_not_in_text_single_long(self):
- text = 'head ' * 50 + 'foo ' + 'tail ' * 20
- assert 'foo' not in text
-
- def test_not_in_text_single_long_term(self):
- text = 'head ' * 50 + 'f'*70 + 'tail ' * 20
- assert 'f'*70 not in text
-
-
-def test_attribute():
- class Foo(object):
- b = 1
- i = Foo()
- assert i.b == 2
-
-
-def test_attribute_instance():
- class Foo(object):
- b = 1
- assert Foo().b == 2
-
-
-def test_attribute_failure():
- class Foo(object):
- def _get_b(self):
- raise Exception('Failed to get attrib')
- b = property(_get_b)
- i = Foo()
- assert i.b == 2
-
-
-def test_attribute_multiple():
- class Foo(object):
- b = 1
- class Bar(object):
- b = 2
- assert Foo().b == Bar().b
-
-
-def globf(x):
- return x+1
-
-class TestRaises:
- def test_raises(self):
- s = 'qwe'
- raises(TypeError, "int(s)")
-
- def test_raises_doesnt(self):
- raises(IOError, "int('3')")
-
- def test_raise(self):
- raise ValueError("demo error")
-
- def test_tupleerror(self):
- a,b = [1]
-
- def test_reinterpret_fails_with_print_for_the_fun_of_it(self):
- l = [1,2,3]
- print ("l is %r" % l)
- a,b = l.pop()
-
- def test_some_error(self):
- if namenotexi:
- pass
-
- def func1(self):
- assert 41 == 42
-
-
-# thanks to Matthew Scott for this test
-def test_dynamic_compile_shows_nicely():
- src = 'def foo():\n assert 1 == 0\n'
- name = 'abc-123'
- module = py.std.imp.new_module(name)
- code = _pytest._code.compile(src, name, 'exec')
- py.builtin.exec_(code, module.__dict__)
- py.std.sys.modules[name] = module
- module.foo()
-
-
-
-class TestMoreErrors:
- def test_complex_error(self):
- def f():
- return 44
- def g():
- return 43
- somefunc(f(), g())
-
- def test_z1_unpack_error(self):
- l = []
- a,b = l
-
- def test_z2_type_error(self):
- l = 3
- a,b = l
-
- def test_startswith(self):
- s = "123"
- g = "456"
- assert s.startswith(g)
-
- def test_startswith_nested(self):
- def f():
- return "123"
- def g():
- return "456"
- assert f().startswith(g())
-
- def test_global_func(self):
- assert isinstance(globf(42), float)
-
- def test_instance(self):
- self.x = 6*7
- assert self.x != 42
-
- def test_compare(self):
- assert globf(10) < 5
-
- def test_try_finally(self):
- x = 1
- try:
- assert x == 0
- finally:
- x = 0
-
-
-class TestCustomAssertMsg:
-
- def test_single_line(self):
- class A:
- a = 1
- b = 2
- assert A.a == b, "A.a appears not to be b"
-
- def test_multiline(self):
- class A:
- a = 1
- b = 2
- assert A.a == b, "A.a appears not to be b\n" \
- "or does not appear to be b\none of those"
-
- def test_custom_repr(self):
- class JSON:
- a = 1
- def __repr__(self):
- return "This is JSON\n{\n 'foo': 'bar'\n}"
- a = JSON()
- b = 2
- assert a.a == b, a
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/assertion/test_setup_flow_example.py b/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/assertion/test_setup_flow_example.py
deleted file mode 100644
index 512330cb4c7..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/assertion/test_setup_flow_example.py
+++ /dev/null
@@ -1,42 +0,0 @@
-def setup_module(module):
- module.TestStateFullThing.classcount = 0
-
-class TestStateFullThing:
- def setup_class(cls):
- cls.classcount += 1
-
- def teardown_class(cls):
- cls.classcount -= 1
-
- def setup_method(self, method):
- self.id = eval(method.__name__[5:])
-
- def test_42(self):
- assert self.classcount == 1
- assert self.id == 42
-
- def test_23(self):
- assert self.classcount == 1
- assert self.id == 23
-
-def teardown_module(module):
- assert module.TestStateFullThing.classcount == 0
-
-""" For this example the control flow happens as follows::
- import test_setup_flow_example
- setup_module(test_setup_flow_example)
- setup_class(TestStateFullThing)
- instance = TestStateFullThing()
- setup_method(instance, instance.test_42)
- instance.test_42()
- setup_method(instance, instance.test_23)
- instance.test_23()
- teardown_class(TestStateFullThing)
- teardown_module(test_setup_flow_example)
-
-Note that ``setup_class(TestStateFullThing)`` is called and not
-``TestStateFullThing.setup_class()`` which would require you
-to insert ``setup_class = classmethod(setup_class)`` to make
-your setup function callable.
-"""
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/attic.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/attic.rst
deleted file mode 100644
index 1bc32b2837d..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/attic.rst
+++ /dev/null
@@ -1,79 +0,0 @@
-
-.. _`accept example`:
-
-example: specifying and selecting acceptance tests
---------------------------------------------------------------
-
-.. sourcecode:: python
-
- # ./conftest.py
- def pytest_option(parser):
- group = parser.getgroup("myproject")
- group.addoption("-A", dest="acceptance", action="store_true",
- help="run (slow) acceptance tests")
-
- def pytest_funcarg__accept(request):
- return AcceptFixture(request)
-
- class AcceptFixture:
- def __init__(self, request):
- if not request.config.option.acceptance:
- pytest.skip("specify -A to run acceptance tests")
- self.tmpdir = request.config.mktemp(request.function.__name__, numbered=True)
-
- def run(self, cmd):
- """ called by test code to execute an acceptance test. """
- self.tmpdir.chdir()
- return py.process.cmdexec(cmd)
-
-
-and the actual test function example:
-
-.. sourcecode:: python
-
- def test_some_acceptance_aspect(accept):
- accept.tmpdir.mkdir("somesub")
- result = accept.run("ls -la")
- assert "somesub" in result
-
-If you run this test without specifying a command line option
-the test will get skipped with an appropriate message. Otherwise
-you can start to add convenience and test support methods
-to your AcceptFixture and drive running of tools or
-applications and provide ways to do assertions about
-the output.
-
-.. _`decorate a funcarg`:
-
-example: decorating a funcarg in a test module
---------------------------------------------------------------
-
-For larger scale setups it's sometimes useful to decorate
-a funcarg just for a particular test module. We can
-extend the `accept example`_ by putting this in our test module:
-
-.. sourcecode:: python
-
- def pytest_funcarg__accept(request):
- # call the next factory (living in our conftest.py)
- arg = request.getfuncargvalue("accept")
- # create a special layout in our tempdir
- arg.tmpdir.mkdir("special")
- return arg
-
- class TestSpecialAcceptance:
- def test_sometest(self, accept):
- assert accept.tmpdir.join("special").check()
-
-Our module level factory will be invoked first and it can
-ask its request object to call the next factory and then
-decorate its result. This mechanism allows us to stay
-ignorant of how/where the function argument is provided -
-in our example from a `conftest plugin`_.
-
-sidenote: the temporary directory used here are instances of
-the `py.path.local`_ class which provides many of the os.path
-methods in a convenient way.
-
-.. _`py.path.local`: ../path.html#local
-.. _`conftest plugin`: customize.html#conftestplugin
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/costlysetup/conftest.py b/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/costlysetup/conftest.py
deleted file mode 100644
index d689c11b207..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/costlysetup/conftest.py
+++ /dev/null
@@ -1,18 +0,0 @@
-
-import pytest
-
-@pytest.fixture("session")
-def setup(request):
- setup = CostlySetup()
- request.addfinalizer(setup.finalize)
- return setup
-
-class CostlySetup:
- def __init__(self):
- import time
- print ("performing costly setup")
- time.sleep(5)
- self.timecostly = 1
-
- def finalize(self):
- del self.timecostly
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/index.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/index.rst
deleted file mode 100644
index 363de5ab714..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/index.rst
+++ /dev/null
@@ -1,34 +0,0 @@
-
-.. _examples:
-
-Usages and Examples
-===========================================
-
-Here is a (growing) list of examples. :ref:`Contact <contact>` us if you
-need more examples or have questions. Also take a look at the
-:ref:`comprehensive documentation <toc>` which contains many example
-snippets as well. Also, `pytest on stackoverflow.com
-<http://stackoverflow.com/search?q=pytest>`_ often comes with example
-answers.
-
-For basic examples, see
-
-- :doc:`../getting-started` for basic introductory examples
-- :ref:`assert` for basic assertion examples
-- :ref:`fixtures` for basic fixture/setup examples
-- :ref:`parametrize` for basic test function parametrization
-- :doc:`../unittest` for basic unittest integration
-- :doc:`../nose` for basic nosetests integration
-
-The following examples aim at various use cases you might encounter.
-
-.. toctree::
- :maxdepth: 2
-
- reportingdemo
- simple
- parametrize
- markers
- special
- pythoncollection
- nonpython
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/layout1/setup.cfg b/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/layout1/setup.cfg
deleted file mode 100644
index 02d3750ee40..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/layout1/setup.cfg
+++ /dev/null
@@ -1,4 +0,0 @@
-[pytest]
-testfilepatterns =
- ${topdir}/tests/unit/test_${basename}
- ${topdir}/tests/functional/*.py
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/markers.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/markers.rst
deleted file mode 100644
index 6bdc603479c..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/markers.rst
+++ /dev/null
@@ -1,592 +0,0 @@
-
-.. _`mark examples`:
-
-Working with custom markers
-=================================================
-
-Here are some example using the :ref:`mark` mechanism.
-
-Marking test functions and selecting them for a run
-----------------------------------------------------
-
-You can "mark" a test function with custom metadata like this::
-
- # content of test_server.py
-
- import pytest
- @pytest.mark.webtest
- def test_send_http():
- pass # perform some webtest test for your app
- def test_something_quick():
- pass
- def test_another():
- pass
- class TestClass:
- def test_method(self):
- pass
-
-.. versionadded:: 2.2
-
-You can then restrict a test run to only run tests marked with ``webtest``::
-
- $ py.test -v -m webtest
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.4
- cachedir: .cache
- rootdir: $REGENDOC_TMPDIR, inifile:
- collecting ... collected 4 items
-
- test_server.py::test_send_http PASSED
-
- ======= 3 tests deselected by "-m 'webtest'" ========
- ======= 1 passed, 3 deselected in 0.12 seconds ========
-
-Or the inverse, running all tests except the webtest ones::
-
- $ py.test -v -m "not webtest"
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.4
- cachedir: .cache
- rootdir: $REGENDOC_TMPDIR, inifile:
- collecting ... collected 4 items
-
- test_server.py::test_something_quick PASSED
- test_server.py::test_another PASSED
- test_server.py::TestClass::test_method PASSED
-
- ======= 1 tests deselected by "-m 'not webtest'" ========
- ======= 3 passed, 1 deselected in 0.12 seconds ========
-
-Selecting tests based on their node ID
---------------------------------------
-
-You can provide one or more :ref:`node IDs <node-id>` as positional
-arguments to select only specified tests. This makes it easy to select
-tests based on their module, class, method, or function name::
-
- $ py.test -v test_server.py::TestClass::test_method
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.4
- cachedir: .cache
- rootdir: $REGENDOC_TMPDIR, inifile:
- collecting ... collected 5 items
-
- test_server.py::TestClass::test_method PASSED
-
- ======= 1 passed in 0.12 seconds ========
-
-You can also select on the class::
-
- $ py.test -v test_server.py::TestClass
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.4
- cachedir: .cache
- rootdir: $REGENDOC_TMPDIR, inifile:
- collecting ... collected 4 items
-
- test_server.py::TestClass::test_method PASSED
-
- ======= 1 passed in 0.12 seconds ========
-
-Or select multiple nodes::
-
- $ py.test -v test_server.py::TestClass test_server.py::test_send_http
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.4
- cachedir: .cache
- rootdir: $REGENDOC_TMPDIR, inifile:
- collecting ... collected 8 items
-
- test_server.py::TestClass::test_method PASSED
- test_server.py::test_send_http PASSED
-
- ======= 2 passed in 0.12 seconds ========
-
-.. _node-id:
-
-.. note::
-
- Node IDs are of the form ``module.py::class::method`` or
- ``module.py::function``. Node IDs control which tests are
- collected, so ``module.py::class`` will select all test methods
- on the class. Nodes are also created for each parameter of a
- parametrized fixture or test, so selecting a parametrized test
- must include the parameter value, e.g.
- ``module.py::function[param]``.
-
- Node IDs for failing tests are displayed in the test summary info
- when running py.test with the ``-rf`` option. You can also
- construct Node IDs from the output of ``py.test --collectonly``.
-
-Using ``-k expr`` to select tests based on their name
--------------------------------------------------------
-
-.. versionadded: 2.0/2.3.4
-
-You can use the ``-k`` command line option to specify an expression
-which implements a substring match on the test names instead of the
-exact match on markers that ``-m`` provides. This makes it easy to
-select tests based on their names::
-
- $ py.test -v -k http # running with the above defined example module
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.4
- cachedir: .cache
- rootdir: $REGENDOC_TMPDIR, inifile:
- collecting ... collected 4 items
-
- test_server.py::test_send_http PASSED
-
- ======= 3 tests deselected by '-khttp' ========
- ======= 1 passed, 3 deselected in 0.12 seconds ========
-
-And you can also run all tests except the ones that match the keyword::
-
- $ py.test -k "not send_http" -v
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.4
- cachedir: .cache
- rootdir: $REGENDOC_TMPDIR, inifile:
- collecting ... collected 4 items
-
- test_server.py::test_something_quick PASSED
- test_server.py::test_another PASSED
- test_server.py::TestClass::test_method PASSED
-
- ======= 1 tests deselected by '-knot send_http' ========
- ======= 3 passed, 1 deselected in 0.12 seconds ========
-
-Or to select "http" and "quick" tests::
-
- $ py.test -k "http or quick" -v
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.4
- cachedir: .cache
- rootdir: $REGENDOC_TMPDIR, inifile:
- collecting ... collected 4 items
-
- test_server.py::test_send_http PASSED
- test_server.py::test_something_quick PASSED
-
- ======= 2 tests deselected by '-khttp or quick' ========
- ======= 2 passed, 2 deselected in 0.12 seconds ========
-
-.. note::
-
- If you are using expressions such as "X and Y" then both X and Y
- need to be simple non-keyword names. For example, "pass" or "from"
- will result in SyntaxErrors because "-k" evaluates the expression.
-
- However, if the "-k" argument is a simple string, no such restrictions
- apply. Also "-k 'not STRING'" has no restrictions. You can also
- specify numbers like "-k 1.3" to match tests which are parametrized
- with the float "1.3".
-
-Registering markers
--------------------------------------
-
-.. versionadded:: 2.2
-
-.. ini-syntax for custom markers:
-
-Registering markers for your test suite is simple::
-
- # content of pytest.ini
- [pytest]
- markers =
- webtest: mark a test as a webtest.
-
-You can ask which markers exist for your test suite - the list includes our just defined ``webtest`` markers::
-
- $ py.test --markers
- @pytest.mark.webtest: mark a test as a webtest.
-
- @pytest.mark.skipif(condition): skip the given test function if eval(condition) results in a True value. Evaluation happens within the module global context. Example: skipif('sys.platform == "win32"') skips the test if we are on the win32 platform. see http://pytest.org/latest/skipping.html
-
- @pytest.mark.xfail(condition, reason=None, run=True, raises=None): mark the the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html
-
- @pytest.mark.parametrize(argnames, argvalues): call a test function multiple times passing in different arguments in turn. argvalues generally needs to be a list of values if argnames specifies only one name or a list of tuples of values if argnames specifies multiple names. Example: @parametrize('arg1', [1,2]) would lead to two calls of the decorated test function, one with arg1=1 and another with arg1=2.see http://pytest.org/latest/parametrize.html for more info and examples.
-
- @pytest.mark.usefixtures(fixturename1, fixturename2, ...): mark tests as needing all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures
-
- @pytest.mark.tryfirst: mark a hook implementation function such that the plugin machinery will try to call it first/as early as possible.
-
- @pytest.mark.trylast: mark a hook implementation function such that the plugin machinery will try to call it last/as late as possible.
-
-
-For an example on how to add and work with markers from a plugin, see
-:ref:`adding a custom marker from a plugin`.
-
-.. note::
-
- It is recommended to explicitly register markers so that:
-
- * there is one place in your test suite defining your markers
-
- * asking for existing markers via ``py.test --markers`` gives good output
-
- * typos in function markers are treated as an error if you use
- the ``--strict`` option. Future versions of ``pytest`` are probably
- going to start treating non-registered markers as errors at some point.
-
-.. _`scoped-marking`:
-
-Marking whole classes or modules
-----------------------------------------------------
-
-You may use ``pytest.mark`` decorators with classes to apply markers to all of
-its test methods::
-
- # content of test_mark_classlevel.py
- import pytest
- @pytest.mark.webtest
- class TestClass:
- def test_startup(self):
- pass
- def test_startup_and_more(self):
- pass
-
-This is equivalent to directly applying the decorator to the
-two test functions.
-
-To remain backward-compatible with Python 2.4 you can also set a
-``pytestmark`` attribute on a TestClass like this::
-
- import pytest
-
- class TestClass:
- pytestmark = pytest.mark.webtest
-
-or if you need to use multiple markers you can use a list::
-
- import pytest
-
- class TestClass:
- pytestmark = [pytest.mark.webtest, pytest.mark.slowtest]
-
-You can also set a module level marker::
-
- import pytest
- pytestmark = pytest.mark.webtest
-
-in which case it will be applied to all functions and
-methods defined in the module.
-
-.. _`marking individual tests when using parametrize`:
-
-Marking individual tests when using parametrize
------------------------------------------------
-
-When using parametrize, applying a mark will make it apply
-to each individual test. However it is also possible to
-apply a marker to an individual test instance::
-
- import pytest
-
- @pytest.mark.foo
- @pytest.mark.parametrize(("n", "expected"), [
- (1, 2),
- pytest.mark.bar((1, 3)),
- (2, 3),
- ])
- def test_increment(n, expected):
- assert n + 1 == expected
-
-In this example the mark "foo" will apply to each of the three
-tests, whereas the "bar" mark is only applied to the second test.
-Skip and xfail marks can also be applied in this way, see :ref:`skip/xfail with parametrize`.
-
-.. note::
-
- If the data you are parametrizing happen to be single callables, you need to be careful
- when marking these items. `pytest.mark.xfail(my_func)` won't work because it's also the
- signature of a function being decorated. To resolve this ambiguity, you need to pass a
- reason argument:
- `pytest.mark.xfail(func_bar, reason="Issue#7")`.
-
-
-.. _`adding a custom marker from a plugin`:
-
-Custom marker and command line option to control test runs
-----------------------------------------------------------
-
-.. regendoc:wipe
-
-Plugins can provide custom markers and implement specific behaviour
-based on it. This is a self-contained example which adds a command
-line option and a parametrized test function marker to run tests
-specifies via named environments::
-
- # content of conftest.py
-
- import pytest
- def pytest_addoption(parser):
- parser.addoption("-E", action="store", metavar="NAME",
- help="only run tests matching the environment NAME.")
-
- def pytest_configure(config):
- # register an additional marker
- config.addinivalue_line("markers",
- "env(name): mark test to run only on named environment")
-
- def pytest_runtest_setup(item):
- envmarker = item.get_marker("env")
- if envmarker is not None:
- envname = envmarker.args[0]
- if envname != item.config.getoption("-E"):
- pytest.skip("test requires env %r" % envname)
-
-A test file using this local plugin::
-
- # content of test_someenv.py
-
- import pytest
- @pytest.mark.env("stage1")
- def test_basic_db_operation():
- pass
-
-and an example invocations specifying a different environment than what
-the test needs::
-
- $ py.test -E stage2
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 1 items
-
- test_someenv.py s
-
- ======= 1 skipped in 0.12 seconds ========
-
-and here is one that specifies exactly the environment needed::
-
- $ py.test -E stage1
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 1 items
-
- test_someenv.py .
-
- ======= 1 passed in 0.12 seconds ========
-
-The ``--markers`` option always gives you a list of available markers::
-
- $ py.test --markers
- @pytest.mark.env(name): mark test to run only on named environment
-
- @pytest.mark.skipif(condition): skip the given test function if eval(condition) results in a True value. Evaluation happens within the module global context. Example: skipif('sys.platform == "win32"') skips the test if we are on the win32 platform. see http://pytest.org/latest/skipping.html
-
- @pytest.mark.xfail(condition, reason=None, run=True, raises=None): mark the the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html
-
- @pytest.mark.parametrize(argnames, argvalues): call a test function multiple times passing in different arguments in turn. argvalues generally needs to be a list of values if argnames specifies only one name or a list of tuples of values if argnames specifies multiple names. Example: @parametrize('arg1', [1,2]) would lead to two calls of the decorated test function, one with arg1=1 and another with arg1=2.see http://pytest.org/latest/parametrize.html for more info and examples.
-
- @pytest.mark.usefixtures(fixturename1, fixturename2, ...): mark tests as needing all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures
-
- @pytest.mark.tryfirst: mark a hook implementation function such that the plugin machinery will try to call it first/as early as possible.
-
- @pytest.mark.trylast: mark a hook implementation function such that the plugin machinery will try to call it last/as late as possible.
-
-
-Reading markers which were set from multiple places
-----------------------------------------------------
-
-.. versionadded: 2.2.2
-
-.. regendoc:wipe
-
-If you are heavily using markers in your test suite you may encounter the case where a marker is applied several times to a test function. From plugin
-code you can read over all such settings. Example::
-
- # content of test_mark_three_times.py
- import pytest
- pytestmark = pytest.mark.glob("module", x=1)
-
- @pytest.mark.glob("class", x=2)
- class TestClass:
- @pytest.mark.glob("function", x=3)
- def test_something(self):
- pass
-
-Here we have the marker "glob" applied three times to the same
-test function. From a conftest file we can read it like this::
-
- # content of conftest.py
- import sys
-
- def pytest_runtest_setup(item):
- g = item.get_marker("glob")
- if g is not None:
- for info in g:
- print ("glob args=%s kwargs=%s" %(info.args, info.kwargs))
- sys.stdout.flush()
-
-Let's run this without capturing output and see what we get::
-
- $ py.test -q -s
- glob args=('function',) kwargs={'x': 3}
- glob args=('class',) kwargs={'x': 2}
- glob args=('module',) kwargs={'x': 1}
- .
- 1 passed in 0.12 seconds
-
-marking platform specific tests with pytest
---------------------------------------------------------------
-
-.. regendoc:wipe
-
-Consider you have a test suite which marks tests for particular platforms,
-namely ``pytest.mark.darwin``, ``pytest.mark.win32`` etc. and you
-also have tests that run on all platforms and have no specific
-marker. If you now want to have a way to only run the tests
-for your particular platform, you could use the following plugin::
-
- # content of conftest.py
- #
- import sys
- import pytest
-
- ALL = set("darwin linux2 win32".split())
-
- def pytest_runtest_setup(item):
- if isinstance(item, item.Function):
- plat = sys.platform
- if not item.get_marker(plat):
- if ALL.intersection(item.keywords):
- pytest.skip("cannot run on platform %s" %(plat))
-
-then tests will be skipped if they were specified for a different platform.
-Let's do a little test file to show how this looks like::
-
- # content of test_plat.py
-
- import pytest
-
- @pytest.mark.darwin
- def test_if_apple_is_evil():
- pass
-
- @pytest.mark.linux2
- def test_if_linux_works():
- pass
-
- @pytest.mark.win32
- def test_if_win32_crashes():
- pass
-
- def test_runs_everywhere():
- pass
-
-then you will see two test skipped and two executed tests as expected::
-
- $ py.test -rs # this option reports skip reasons
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 4 items
-
- test_plat.py sss.
- ======= short test summary info ========
- SKIP [3] $REGENDOC_TMPDIR/conftest.py:12: cannot run on platform linux
-
- ======= 1 passed, 3 skipped in 0.12 seconds ========
-
-Note that if you specify a platform via the marker-command line option like this::
-
- $ py.test -m linux2
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 4 items
-
- test_plat.py s
-
- ======= 3 tests deselected by "-m 'linux2'" ========
- ======= 1 skipped, 3 deselected in 0.12 seconds ========
-
-then the unmarked-tests will not be run. It is thus a way to restrict the run to the specific tests.
-
-Automatically adding markers based on test names
---------------------------------------------------------
-
-.. regendoc:wipe
-
-If you a test suite where test function names indicate a certain
-type of test, you can implement a hook that automatically defines
-markers so that you can use the ``-m`` option with it. Let's look
-at this test module::
-
- # content of test_module.py
-
- def test_interface_simple():
- assert 0
-
- def test_interface_complex():
- assert 0
-
- def test_event_simple():
- assert 0
-
- def test_something_else():
- assert 0
-
-We want to dynamically define two markers and can do it in a
-``conftest.py`` plugin::
-
- # content of conftest.py
-
- import pytest
- def pytest_collection_modifyitems(items):
- for item in items:
- if "interface" in item.nodeid:
- item.add_marker(pytest.mark.interface)
- elif "event" in item.nodeid:
- item.add_marker(pytest.mark.event)
-
-We can now use the ``-m option`` to select one set::
-
- $ py.test -m interface --tb=short
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 4 items
-
- test_module.py FF
-
- ======= FAILURES ========
- _______ test_interface_simple ________
- test_module.py:3: in test_interface_simple
- assert 0
- E assert 0
- _______ test_interface_complex ________
- test_module.py:6: in test_interface_complex
- assert 0
- E assert 0
- ======= 2 tests deselected by "-m 'interface'" ========
- ======= 2 failed, 2 deselected in 0.12 seconds ========
-
-or to select both "event" and "interface" tests::
-
- $ py.test -m "interface or event" --tb=short
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 4 items
-
- test_module.py FFF
-
- ======= FAILURES ========
- _______ test_interface_simple ________
- test_module.py:3: in test_interface_simple
- assert 0
- E assert 0
- _______ test_interface_complex ________
- test_module.py:6: in test_interface_complex
- assert 0
- E assert 0
- _______ test_event_simple ________
- test_module.py:9: in test_event_simple
- assert 0
- E assert 0
- ======= 1 tests deselected by "-m 'interface or event'" ========
- ======= 3 failed, 1 deselected in 0.12 seconds ========
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/multipython.py b/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/multipython.py
deleted file mode 100644
index 66a368a1267..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/multipython.py
+++ /dev/null
@@ -1,52 +0,0 @@
-"""
-module containing a parametrized tests testing cross-python
-serialization via the pickle module.
-"""
-import py
-import pytest
-import _pytest._code
-
-pythonlist = ['python2.6', 'python2.7', 'python3.3']
-@pytest.fixture(params=pythonlist)
-def python1(request, tmpdir):
- picklefile = tmpdir.join("data.pickle")
- return Python(request.param, picklefile)
-
-@pytest.fixture(params=pythonlist)
-def python2(request, python1):
- return Python(request.param, python1.picklefile)
-
-class Python:
- def __init__(self, version, picklefile):
- self.pythonpath = py.path.local.sysfind(version)
- if not self.pythonpath:
- pytest.skip("%r not found" %(version,))
- self.picklefile = picklefile
- def dumps(self, obj):
- dumpfile = self.picklefile.dirpath("dump.py")
- dumpfile.write(_pytest._code.Source("""
- import pickle
- f = open(%r, 'wb')
- s = pickle.dump(%r, f, protocol=2)
- f.close()
- """ % (str(self.picklefile), obj)))
- py.process.cmdexec("%s %s" %(self.pythonpath, dumpfile))
-
- def load_and_is_true(self, expression):
- loadfile = self.picklefile.dirpath("load.py")
- loadfile.write(_pytest._code.Source("""
- import pickle
- f = open(%r, 'rb')
- obj = pickle.load(f)
- f.close()
- res = eval(%r)
- if not res:
- raise SystemExit(1)
- """ % (str(self.picklefile), expression)))
- print (loadfile)
- py.process.cmdexec("%s %s" %(self.pythonpath, loadfile))
-
-@pytest.mark.parametrize("obj", [42, {}, {1:3},])
-def test_basic_objects(python1, python2, obj):
- python1.dumps(obj)
- python2.load_and_is_true("obj == %s" % obj)
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/nonpython.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/nonpython.rst
deleted file mode 100644
index 6437e398457..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/nonpython.rst
+++ /dev/null
@@ -1,91 +0,0 @@
-
-.. _`non-python tests`:
-
-Working with non-python tests
-====================================================
-
-.. _`yaml plugin`:
-
-A basic example for specifying tests in Yaml files
---------------------------------------------------------------
-
-.. _`pytest-yamlwsgi`: http://bitbucket.org/aafshar/pytest-yamlwsgi/src/tip/pytest_yamlwsgi.py
-.. _`PyYAML`: http://pypi.python.org/pypi/PyYAML/
-
-Here is an example ``conftest.py`` (extracted from Ali Afshnars special purpose `pytest-yamlwsgi`_ plugin). This ``conftest.py`` will collect ``test*.yml`` files and will execute the yaml-formatted content as custom tests:
-
-.. include:: nonpython/conftest.py
- :literal:
-
-You can create a simple example file:
-
-.. include:: nonpython/test_simple.yml
- :literal:
-
-and if you installed `PyYAML`_ or a compatible YAML-parser you can
-now execute the test specification::
-
- nonpython $ py.test test_simple.yml
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR/nonpython, inifile:
- collected 2 items
-
- test_simple.yml F.
-
- ======= FAILURES ========
- _______ usecase: hello ________
- usecase execution failed
- spec failed: 'some': 'other'
- no further details known at this point.
- ======= 1 failed, 1 passed in 0.12 seconds ========
-
-.. regendoc:wipe
-
-You get one dot for the passing ``sub1: sub1`` check and one failure.
-Obviously in the above ``conftest.py`` you'll want to implement a more
-interesting interpretation of the yaml-values. You can easily write
-your own domain specific testing language this way.
-
-.. note::
-
- ``repr_failure(excinfo)`` is called for representing test failures.
- If you create custom collection nodes you can return an error
- representation string of your choice. It
- will be reported as a (red) string.
-
-``reportinfo()`` is used for representing the test location and is also
-consulted when reporting in ``verbose`` mode::
-
- nonpython $ py.test -v
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.4
- cachedir: .cache
- rootdir: $REGENDOC_TMPDIR/nonpython, inifile:
- collecting ... collected 2 items
-
- test_simple.yml::hello FAILED
- test_simple.yml::ok PASSED
-
- ======= FAILURES ========
- _______ usecase: hello ________
- usecase execution failed
- spec failed: 'some': 'other'
- no further details known at this point.
- ======= 1 failed, 1 passed in 0.12 seconds ========
-
-.. regendoc:wipe
-
-While developing your custom test collection and execution it's also
-interesting to just look at the collection tree::
-
- nonpython $ py.test --collect-only
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR/nonpython, inifile:
- collected 2 items
- <YamlFile 'test_simple.yml'>
- <YamlItem 'hello'>
- <YamlItem 'ok'>
-
- ======= no tests ran in 0.12 seconds ========
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/nonpython/conftest.py b/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/nonpython/conftest.py
deleted file mode 100644
index 2406e8f10bb..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/nonpython/conftest.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# content of conftest.py
-
-import pytest
-
-def pytest_collect_file(parent, path):
- if path.ext == ".yml" and path.basename.startswith("test"):
- return YamlFile(path, parent)
-
-class YamlFile(pytest.File):
- def collect(self):
- import yaml # we need a yaml parser, e.g. PyYAML
- raw = yaml.safe_load(self.fspath.open())
- for name, spec in raw.items():
- yield YamlItem(name, self, spec)
-
-class YamlItem(pytest.Item):
- def __init__(self, name, parent, spec):
- super(YamlItem, self).__init__(name, parent)
- self.spec = spec
-
- def runtest(self):
- for name, value in self.spec.items():
- # some custom test execution (dumb example follows)
- if name != value:
- raise YamlException(self, name, value)
-
- def repr_failure(self, excinfo):
- """ called when self.runtest() raises an exception. """
- if isinstance(excinfo.value, YamlException):
- return "\n".join([
- "usecase execution failed",
- " spec failed: %r: %r" % excinfo.value.args[1:3],
- " no further details known at this point."
- ])
-
- def reportinfo(self):
- return self.fspath, 0, "usecase: %s" % self.name
-
-class YamlException(Exception):
- """ custom exception for error reporting. """
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/parametrize.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/parametrize.rst
deleted file mode 100644
index 5d637ffcbf9..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/parametrize.rst
+++ /dev/null
@@ -1,475 +0,0 @@
-
-.. _paramexamples:
-
-Parametrizing tests
-=================================================
-
-.. currentmodule:: _pytest.python
-
-``pytest`` allows to easily parametrize test functions.
-For basic docs, see :ref:`parametrize-basics`.
-
-In the following we provide some examples using
-the builtin mechanisms.
-
-Generating parameters combinations, depending on command line
-----------------------------------------------------------------------------
-
-.. regendoc:wipe
-
-Let's say we want to execute a test with different computation
-parameters and the parameter range shall be determined by a command
-line argument. Let's first write a simple (do-nothing) computation test::
-
- # content of test_compute.py
-
- def test_compute(param1):
- assert param1 < 4
-
-Now we add a test configuration like this::
-
- # content of conftest.py
-
- def pytest_addoption(parser):
- parser.addoption("--all", action="store_true",
- help="run all combinations")
-
- def pytest_generate_tests(metafunc):
- if 'param1' in metafunc.fixturenames:
- if metafunc.config.option.all:
- end = 5
- else:
- end = 2
- metafunc.parametrize("param1", range(end))
-
-This means that we only run 2 tests if we do not pass ``--all``::
-
- $ py.test -q test_compute.py
- ..
- 2 passed in 0.12 seconds
-
-We run only two computations, so we see two dots.
-let's run the full monty::
-
- $ py.test -q --all
- ....F
- ======= FAILURES ========
- _______ test_compute[4] ________
-
- param1 = 4
-
- def test_compute(param1):
- > assert param1 < 4
- E assert 4 < 4
-
- test_compute.py:3: AssertionError
- 1 failed, 4 passed in 0.12 seconds
-
-As expected when running the full range of ``param1`` values
-we'll get an error on the last one.
-
-
-Different options for test IDs
-------------------------------------
-
-pytest will build a string that is the test ID for each set of values in a
-parametrized test. These IDs can be used with ``-k`` to select specific cases
-to run, and they will also identify the specific case when one is failing.
-Running pytest with ``--collect-only`` will show the generated IDs.
-
-Numbers, strings, booleans and None will have their usual string representation
-used in the test ID. For other objects, pytest will make a string based on
-the argument name::
-
- # content of test_time.py
-
- import pytest
-
- from datetime import datetime, timedelta
-
- testdata = [
- (datetime(2001, 12, 12), datetime(2001, 12, 11), timedelta(1)),
- (datetime(2001, 12, 11), datetime(2001, 12, 12), timedelta(-1)),
- ]
-
-
- @pytest.mark.parametrize("a,b,expected", testdata)
- def test_timedistance_v0(a, b, expected):
- diff = a - b
- assert diff == expected
-
-
- @pytest.mark.parametrize("a,b,expected", testdata, ids=["forward", "backward"])
- def test_timedistance_v1(a, b, expected):
- diff = a - b
- assert diff == expected
-
-
- def idfn(val):
- if isinstance(val, (datetime,)):
- # note this wouldn't show any hours/minutes/seconds
- return val.strftime('%Y%m%d')
-
-
- @pytest.mark.parametrize("a,b,expected", testdata, ids=idfn)
- def test_timedistance_v2(a, b, expected):
- diff = a - b
- assert diff == expected
-
-
-In ``test_timedistance_v0``, we let pytest generate the test IDs.
-
-In ``test_timedistance_v1``, we specified ``ids`` as a list of strings which were
-used as the test IDs. These are succinct, but can be a pain to maintain.
-
-In ``test_timedistance_v2``, we specified ``ids`` as a function that can generate a
-string representation to make part of the test ID. So our ``datetime`` values use the
-label generated by ``idfn``, but because we didn't generate a label for ``timedelta``
-objects, they are still using the default pytest representation::
-
-
- $ py.test test_time.py --collect-only
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 6 items
- <Module 'test_time.py'>
- <Function 'test_timedistance_v0[a0-b0-expected0]'>
- <Function 'test_timedistance_v0[a1-b1-expected1]'>
- <Function 'test_timedistance_v1[forward]'>
- <Function 'test_timedistance_v1[backward]'>
- <Function 'test_timedistance_v2[20011212-20011211-expected0]'>
- <Function 'test_timedistance_v2[20011211-20011212-expected1]'>
-
- ======= no tests ran in 0.12 seconds ========
-
-A quick port of "testscenarios"
-------------------------------------
-
-.. _`test scenarios`: http://pypi.python.org/pypi/testscenarios/
-
-Here is a quick port to run tests configured with `test scenarios`_,
-an add-on from Robert Collins for the standard unittest framework. We
-only have to work a bit to construct the correct arguments for pytest's
-:py:func:`Metafunc.parametrize`::
-
- # content of test_scenarios.py
-
- def pytest_generate_tests(metafunc):
- idlist = []
- argvalues = []
- for scenario in metafunc.cls.scenarios:
- idlist.append(scenario[0])
- items = scenario[1].items()
- argnames = [x[0] for x in items]
- argvalues.append(([x[1] for x in items]))
- metafunc.parametrize(argnames, argvalues, ids=idlist, scope="class")
-
- scenario1 = ('basic', {'attribute': 'value'})
- scenario2 = ('advanced', {'attribute': 'value2'})
-
- class TestSampleWithScenarios:
- scenarios = [scenario1, scenario2]
-
- def test_demo1(self, attribute):
- assert isinstance(attribute, str)
-
- def test_demo2(self, attribute):
- assert isinstance(attribute, str)
-
-this is a fully self-contained example which you can run with::
-
- $ py.test test_scenarios.py
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 4 items
-
- test_scenarios.py ....
-
- ======= 4 passed in 0.12 seconds ========
-
-If you just collect tests you'll also nicely see 'advanced' and 'basic' as variants for the test function::
-
-
- $ py.test --collect-only test_scenarios.py
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 4 items
- <Module 'test_scenarios.py'>
- <Class 'TestSampleWithScenarios'>
- <Instance '()'>
- <Function 'test_demo1[basic]'>
- <Function 'test_demo2[basic]'>
- <Function 'test_demo1[advanced]'>
- <Function 'test_demo2[advanced]'>
-
- ======= no tests ran in 0.12 seconds ========
-
-Note that we told ``metafunc.parametrize()`` that your scenario values
-should be considered class-scoped. With pytest-2.3 this leads to a
-resource-based ordering.
-
-Deferring the setup of parametrized resources
----------------------------------------------------
-
-.. regendoc:wipe
-
-The parametrization of test functions happens at collection
-time. It is a good idea to setup expensive resources like DB
-connections or subprocess only when the actual test is run.
-Here is a simple example how you can achieve that, first
-the actual test requiring a ``db`` object::
-
- # content of test_backends.py
-
- import pytest
- def test_db_initialized(db):
- # a dummy test
- if db.__class__.__name__ == "DB2":
- pytest.fail("deliberately failing for demo purposes")
-
-We can now add a test configuration that generates two invocations of
-the ``test_db_initialized`` function and also implements a factory that
-creates a database object for the actual test invocations::
-
- # content of conftest.py
- import pytest
-
- def pytest_generate_tests(metafunc):
- if 'db' in metafunc.fixturenames:
- metafunc.parametrize("db", ['d1', 'd2'], indirect=True)
-
- class DB1:
- "one database object"
- class DB2:
- "alternative database object"
-
- @pytest.fixture
- def db(request):
- if request.param == "d1":
- return DB1()
- elif request.param == "d2":
- return DB2()
- else:
- raise ValueError("invalid internal test config")
-
-Let's first see how it looks like at collection time::
-
- $ py.test test_backends.py --collect-only
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 2 items
- <Module 'test_backends.py'>
- <Function 'test_db_initialized[d1]'>
- <Function 'test_db_initialized[d2]'>
-
- ======= no tests ran in 0.12 seconds ========
-
-And then when we run the test::
-
- $ py.test -q test_backends.py
- .F
- ======= FAILURES ========
- _______ test_db_initialized[d2] ________
-
- db = <conftest.DB2 object at 0xdeadbeef>
-
- def test_db_initialized(db):
- # a dummy test
- if db.__class__.__name__ == "DB2":
- > pytest.fail("deliberately failing for demo purposes")
- E Failed: deliberately failing for demo purposes
-
- test_backends.py:6: Failed
- 1 failed, 1 passed in 0.12 seconds
-
-The first invocation with ``db == "DB1"`` passed while the second with ``db == "DB2"`` failed. Our ``db`` fixture function has instantiated each of the DB values during the setup phase while the ``pytest_generate_tests`` generated two according calls to the ``test_db_initialized`` during the collection phase.
-
-.. regendoc:wipe
-
-Apply indirect on particular arguments
----------------------------------------------------
-
-Very often parametrization uses more than one argument name. There is opportunity to apply ``indirect``
-parameter on particular arguments. It can be done by passing list or tuple of
-arguments' names to ``indirect``. In the example below there is a function ``test_indirect`` which uses
-two fixtures: ``x`` and ``y``. Here we give to indirect the list, which contains the name of the
-fixture ``x``. The indirect parameter will be applied to this argument only, and the value ``a``
-will be passed to respective fixture function::
-
- # content of test_indirect_list.py
-
- import pytest
- @pytest.fixture(scope='function')
- def x(request):
- return request.param * 3
-
- @pytest.fixture(scope='function')
- def y(request):
- return request.param * 2
-
- @pytest.mark.parametrize('x, y', [('a', 'b')], indirect=['x'])
- def test_indirect(x,y):
- assert x == 'aaa'
- assert y == 'b'
-
-The result of this test will be successful::
-
- $ py.test test_indirect_list.py --collect-only
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 1 items
- <Module 'test_indirect_list.py'>
- <Function 'test_indirect[a-b]'>
-
- ======= no tests ran in 0.12 seconds ========
-
-.. regendoc:wipe
-
-Parametrizing test methods through per-class configuration
---------------------------------------------------------------
-
-.. _`unittest parametrizer`: https://github.com/testing-cabal/unittest-ext/blob/master/params.py
-
-
-Here is an example ``pytest_generate_function`` function implementing a
-parametrization scheme similar to Michael Foord's `unittest
-parametrizer`_ but in a lot less code::
-
- # content of ./test_parametrize.py
- import pytest
-
- def pytest_generate_tests(metafunc):
- # called once per each test function
- funcarglist = metafunc.cls.params[metafunc.function.__name__]
- argnames = list(funcarglist[0])
- metafunc.parametrize(argnames, [[funcargs[name] for name in argnames]
- for funcargs in funcarglist])
-
- class TestClass:
- # a map specifying multiple argument sets for a test method
- params = {
- 'test_equals': [dict(a=1, b=2), dict(a=3, b=3), ],
- 'test_zerodivision': [dict(a=1, b=0), ],
- }
-
- def test_equals(self, a, b):
- assert a == b
-
- def test_zerodivision(self, a, b):
- pytest.raises(ZeroDivisionError, "a/b")
-
-Our test generator looks up a class-level definition which specifies which
-argument sets to use for each test function. Let's run it::
-
- $ py.test -q
- F..
- ======= FAILURES ========
- _______ TestClass.test_equals[1-2] ________
-
- self = <test_parametrize.TestClass object at 0xdeadbeef>, a = 1, b = 2
-
- def test_equals(self, a, b):
- > assert a == b
- E assert 1 == 2
-
- test_parametrize.py:18: AssertionError
- 1 failed, 2 passed in 0.12 seconds
-
-Indirect parametrization with multiple fixtures
---------------------------------------------------------------
-
-Here is a stripped down real-life example of using parametrized
-testing for testing serialization of objects between different python
-interpreters. We define a ``test_basic_objects`` function which
-is to be run with different sets of arguments for its three arguments:
-
-* ``python1``: first python interpreter, run to pickle-dump an object to a file
-* ``python2``: second interpreter, run to pickle-load an object from a file
-* ``obj``: object to be dumped/loaded
-
-.. literalinclude:: multipython.py
-
-Running it results in some skips if we don't have all the python interpreters installed and otherwise runs all combinations (5 interpreters times 5 interpreters times 3 objects to serialize/deserialize)::
-
- . $ py.test -rs -q multipython.py
- ssssssssssss...ssssssssssss
- ======= short test summary info ========
- SKIP [12] $REGENDOC_TMPDIR/CWD/multipython.py:23: 'python3.3' not found
- SKIP [12] $REGENDOC_TMPDIR/CWD/multipython.py:23: 'python2.6' not found
- 3 passed, 24 skipped in 0.12 seconds
-
-Indirect parametrization of optional implementations/imports
---------------------------------------------------------------------
-
-If you want to compare the outcomes of several implementations of a given
-API, you can write test functions that receive the already imported implementations
-and get skipped in case the implementation is not importable/available. Let's
-say we have a "base" implementation and the other (possibly optimized ones)
-need to provide similar results::
-
- # content of conftest.py
-
- import pytest
-
- @pytest.fixture(scope="session")
- def basemod(request):
- return pytest.importorskip("base")
-
- @pytest.fixture(scope="session", params=["opt1", "opt2"])
- def optmod(request):
- return pytest.importorskip(request.param)
-
-And then a base implementation of a simple function::
-
- # content of base.py
- def func1():
- return 1
-
-And an optimized version::
-
- # content of opt1.py
- def func1():
- return 1.0001
-
-And finally a little test module::
-
- # content of test_module.py
-
- def test_func1(basemod, optmod):
- assert round(basemod.func1(), 3) == round(optmod.func1(), 3)
-
-
-If you run this with reporting for skips enabled::
-
- $ py.test -rs test_module.py
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 2 items
-
- test_module.py .s
- ======= short test summary info ========
- SKIP [1] $REGENDOC_TMPDIR/conftest.py:10: could not import 'opt2'
-
- ======= 1 passed, 1 skipped in 0.12 seconds ========
-
-You'll see that we don't have a ``opt2`` module and thus the second test run
-of our ``test_func1`` was skipped. A few notes:
-
-- the fixture functions in the ``conftest.py`` file are "session-scoped" because we
- don't need to import more than once
-
-- if you have multiple test functions and a skipped import, you will see
- the ``[1]`` count increasing in the report
-
-- you can put :ref:`@pytest.mark.parametrize <@pytest.mark.parametrize>` style
- parametrization on the test functions to parametrize input/output
- values as well.
-
-
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/pythoncollection.py b/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/pythoncollection.py
deleted file mode 100644
index 05858eb854b..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/pythoncollection.py
+++ /dev/null
@@ -1,11 +0,0 @@
-
-# run this with $ py.test --collect-only test_collectonly.py
-#
-def test_function():
- pass
-
-class TestClass:
- def test_method(self):
- pass
- def test_anothermethod(self):
- pass
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/pythoncollection.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/pythoncollection.rst
deleted file mode 100644
index 5faf4c6c8ad..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/pythoncollection.rst
+++ /dev/null
@@ -1,192 +0,0 @@
-Changing standard (Python) test discovery
-===============================================
-
-Ignore paths during test collection
------------------------------------
-
-You can easily ignore certain test directories and modules during collection
-by passing the ``--ignore=path`` option on the cli. ``pytest`` allows multiple
-``--ignore`` options. Example::
-
- tests/
- ├── example
- │   ├── test_example_01.py
- │   ├── test_example_02.py
- │   └── test_example_03.py
- ├── foobar
- │   ├── test_foobar_01.py
- │   ├── test_foobar_02.py
- │   └── test_foobar_03.py
- └── hello
- └── world
- ├── test_world_01.py
- ├── test_world_02.py
- └── test_world_03.py
-
-Now if you invoke ``pytest`` with ``--ignore=tests/foobar/test_foobar_03.py --ignore=tests/hello/``,
-you will see that ``pytest`` only collects test-modules, which do not match the patterns specified::
-
- ========= test session starts ==========
- platform darwin -- Python 2.7.10, pytest-2.8.2, py-1.4.30, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 5 items
-
- tests/example/test_example_01.py .
- tests/example/test_example_02.py .
- tests/example/test_example_03.py .
- tests/foobar/test_foobar_01.py .
- tests/foobar/test_foobar_02.py .
-
- ======= 5 passed in 0.02 seconds =======
-
-
-Changing directory recursion
------------------------------------------------------
-
-You can set the :confval:`norecursedirs` option in an ini-file, for example your ``setup.cfg`` in the project root directory::
-
- # content of setup.cfg
- [pytest]
- norecursedirs = .svn _build tmp*
-
-This would tell ``pytest`` to not recurse into typical subversion or sphinx-build directories or into any ``tmp`` prefixed directory.
-
-.. _`change naming conventions`:
-
-Changing naming conventions
------------------------------------------------------
-
-You can configure different naming conventions by setting
-the :confval:`python_files`, :confval:`python_classes` and
-:confval:`python_functions` configuration options. Example::
-
- # content of setup.cfg
- # can also be defined in in tox.ini or pytest.ini file
- [pytest]
- python_files=check_*.py
- python_classes=Check
- python_functions=*_check
-
-This would make ``pytest`` look for tests in files that match the ``check_*
-.py`` glob-pattern, ``Check`` prefixes in classes, and functions and methods
-that match ``*_check``. For example, if we have::
-
- # content of check_myapp.py
- class CheckMyApp:
- def simple_check(self):
- pass
- def complex_check(self):
- pass
-
-then the test collection looks like this::
-
- $ py.test --collect-only
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile: setup.cfg
- collected 2 items
- <Module 'check_myapp.py'>
- <Class 'CheckMyApp'>
- <Instance '()'>
- <Function 'simple_check'>
- <Function 'complex_check'>
-
- ======= no tests ran in 0.12 seconds ========
-
-.. note::
-
- the ``python_functions`` and ``python_classes`` options has no effect
- for ``unittest.TestCase`` test discovery because pytest delegates
- detection of test case methods to unittest code.
-
-Interpreting cmdline arguments as Python packages
------------------------------------------------------
-
-You can use the ``--pyargs`` option to make ``pytest`` try
-interpreting arguments as python package names, deriving
-their file system path and then running the test. For
-example if you have unittest2 installed you can type::
-
- py.test --pyargs unittest2.test.test_skipping -q
-
-which would run the respective test module. Like with
-other options, through an ini-file and the :confval:`addopts` option you
-can make this change more permanently::
-
- # content of pytest.ini
- [pytest]
- addopts = --pyargs
-
-Now a simple invocation of ``py.test NAME`` will check
-if NAME exists as an importable package/module and otherwise
-treat it as a filesystem path.
-
-Finding out what is collected
------------------------------------------------
-
-You can always peek at the collection tree without running tests like this::
-
- . $ py.test --collect-only pythoncollection.py
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
- collected 3 items
- <Module 'CWD/pythoncollection.py'>
- <Function 'test_function'>
- <Class 'TestClass'>
- <Instance '()'>
- <Function 'test_method'>
- <Function 'test_anothermethod'>
-
- ======= no tests ran in 0.12 seconds ========
-
-customizing test collection to find all .py files
----------------------------------------------------------
-
-.. regendoc:wipe
-
-You can easily instruct ``pytest`` to discover tests from every python file::
-
-
- # content of pytest.ini
- [pytest]
- python_files = *.py
-
-However, many projects will have a ``setup.py`` which they don't want to be imported. Moreover, there may files only importable by a specific python version.
-For such cases you can dynamically define files to be ignored by listing
-them in a ``conftest.py`` file::
-
- # content of conftest.py
- import sys
-
- collect_ignore = ["setup.py"]
- if sys.version_info[0] > 2:
- collect_ignore.append("pkg/module_py2.py")
-
-And then if you have a module file like this::
-
- # content of pkg/module_py2.py
- def test_only_on_python2():
- try:
- assert 0
- except Exception, e:
- pass
-
-and a setup.py dummy file like this::
-
- # content of setup.py
- 0/0 # will raise exception if imported
-
-then a pytest run on python2 will find the one test when run with a python2
-interpreters and will leave out the setup.py file::
-
- $ py.test --collect-only
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
- collected 0 items
-
- ======= no tests ran in 0.12 seconds ========
-
-If you run with a Python3 interpreter the moduled added through the conftest.py file will not be considered for test collection.
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/reportingdemo.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/reportingdemo.rst
deleted file mode 100644
index 28624aa07b8..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/reportingdemo.rst
+++ /dev/null
@@ -1,598 +0,0 @@
-
-.. _`tbreportdemo`:
-
-Demo of Python failure reports with pytest
-==================================================
-
-Here is a nice run of several tens of failures
-and how ``pytest`` presents things (unfortunately
-not showing the nice colors here in the HTML that you
-get on the terminal - we are working on that):
-
-.. code-block:: python
-
- assertion $ py.test failure_demo.py
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR/assertion, inifile:
- collected 42 items
-
- failure_demo.py FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
-
- ======= FAILURES ========
- _______ test_generative[0] ________
-
- param1 = 3, param2 = 6
-
- def test_generative(param1, param2):
- > assert param1 * 2 < param2
- E assert (3 * 2) < 6
-
- failure_demo.py:16: AssertionError
- _______ TestFailing.test_simple ________
-
- self = <failure_demo.TestFailing object at 0xdeadbeef>
-
- def test_simple(self):
- def f():
- return 42
- def g():
- return 43
-
- > assert f() == g()
- E assert 42 == 43
- E + where 42 = <function TestFailing.test_simple.<locals>.f at 0xdeadbeef>()
- E + and 43 = <function TestFailing.test_simple.<locals>.g at 0xdeadbeef>()
-
- failure_demo.py:29: AssertionError
- _______ TestFailing.test_simple_multiline ________
-
- self = <failure_demo.TestFailing object at 0xdeadbeef>
-
- def test_simple_multiline(self):
- otherfunc_multi(
- 42,
- > 6*9)
-
- failure_demo.py:34:
- _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
-
- a = 42, b = 54
-
- def otherfunc_multi(a,b):
- > assert (a ==
- b)
- E assert 42 == 54
-
- failure_demo.py:12: AssertionError
- _______ TestFailing.test_not ________
-
- self = <failure_demo.TestFailing object at 0xdeadbeef>
-
- def test_not(self):
- def f():
- return 42
- > assert not f()
- E assert not 42
- E + where 42 = <function TestFailing.test_not.<locals>.f at 0xdeadbeef>()
-
- failure_demo.py:39: AssertionError
- _______ TestSpecialisedExplanations.test_eq_text ________
-
- self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
-
- def test_eq_text(self):
- > assert 'spam' == 'eggs'
- E assert 'spam' == 'eggs'
- E - spam
- E + eggs
-
- failure_demo.py:43: AssertionError
- _______ TestSpecialisedExplanations.test_eq_similar_text ________
-
- self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
-
- def test_eq_similar_text(self):
- > assert 'foo 1 bar' == 'foo 2 bar'
- E assert 'foo 1 bar' == 'foo 2 bar'
- E - foo 1 bar
- E ? ^
- E + foo 2 bar
- E ? ^
-
- failure_demo.py:46: AssertionError
- _______ TestSpecialisedExplanations.test_eq_multiline_text ________
-
- self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
-
- def test_eq_multiline_text(self):
- > assert 'foo\nspam\nbar' == 'foo\neggs\nbar'
- E assert 'foo\nspam\nbar' == 'foo\neggs\nbar'
- E foo
- E - spam
- E + eggs
- E bar
-
- failure_demo.py:49: AssertionError
- _______ TestSpecialisedExplanations.test_eq_long_text ________
-
- self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
-
- def test_eq_long_text(self):
- a = '1'*100 + 'a' + '2'*100
- b = '1'*100 + 'b' + '2'*100
- > assert a == b
- E assert '111111111111...2222222222222' == '1111111111111...2222222222222'
- E Skipping 90 identical leading characters in diff, use -v to show
- E Skipping 91 identical trailing characters in diff, use -v to show
- E - 1111111111a222222222
- E ? ^
- E + 1111111111b222222222
- E ? ^
-
- failure_demo.py:54: AssertionError
- _______ TestSpecialisedExplanations.test_eq_long_text_multiline ________
-
- self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
-
- def test_eq_long_text_multiline(self):
- a = '1\n'*100 + 'a' + '2\n'*100
- b = '1\n'*100 + 'b' + '2\n'*100
- > assert a == b
- E assert '1\n1\n1\n1\n...n2\n2\n2\n2\n' == '1\n1\n1\n1\n1...n2\n2\n2\n2\n'
- E Skipping 190 identical leading characters in diff, use -v to show
- E Skipping 191 identical trailing characters in diff, use -v to show
- E 1
- E 1
- E 1
- E 1
- E 1
- E - a2
- E + b2
- E 2
- E 2
- E 2
- E 2
-
- failure_demo.py:59: AssertionError
- _______ TestSpecialisedExplanations.test_eq_list ________
-
- self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
-
- def test_eq_list(self):
- > assert [0, 1, 2] == [0, 1, 3]
- E assert [0, 1, 2] == [0, 1, 3]
- E At index 2 diff: 2 != 3
- E Use -v to get the full diff
-
- failure_demo.py:62: AssertionError
- _______ TestSpecialisedExplanations.test_eq_list_long ________
-
- self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
-
- def test_eq_list_long(self):
- a = [0]*100 + [1] + [3]*100
- b = [0]*100 + [2] + [3]*100
- > assert a == b
- E assert [0, 0, 0, 0, 0, 0, ...] == [0, 0, 0, 0, 0, 0, ...]
- E At index 100 diff: 1 != 2
- E Use -v to get the full diff
-
- failure_demo.py:67: AssertionError
- _______ TestSpecialisedExplanations.test_eq_dict ________
-
- self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
-
- def test_eq_dict(self):
- > assert {'a': 0, 'b': 1, 'c': 0} == {'a': 0, 'b': 2, 'd': 0}
- E assert {'a': 0, 'b': 1, 'c': 0} == {'a': 0, 'b': 2, 'd': 0}
- E Omitting 1 identical items, use -v to show
- E Differing items:
- E {'b': 1} != {'b': 2}
- E Left contains more items:
- E {'c': 0}
- E Right contains more items:
- E {'d': 0}
- E Use -v to get the full diff
-
- failure_demo.py:70: AssertionError
- _______ TestSpecialisedExplanations.test_eq_set ________
-
- self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
-
- def test_eq_set(self):
- > assert set([0, 10, 11, 12]) == set([0, 20, 21])
- E assert set([0, 10, 11, 12]) == set([0, 20, 21])
- E Extra items in the left set:
- E 10
- E 11
- E 12
- E Extra items in the right set:
- E 20
- E 21
- E Use -v to get the full diff
-
- failure_demo.py:73: AssertionError
- _______ TestSpecialisedExplanations.test_eq_longer_list ________
-
- self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
-
- def test_eq_longer_list(self):
- > assert [1,2] == [1,2,3]
- E assert [1, 2] == [1, 2, 3]
- E Right contains more items, first extra item: 3
- E Use -v to get the full diff
-
- failure_demo.py:76: AssertionError
- _______ TestSpecialisedExplanations.test_in_list ________
-
- self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
-
- def test_in_list(self):
- > assert 1 in [0, 2, 3, 4, 5]
- E assert 1 in [0, 2, 3, 4, 5]
-
- failure_demo.py:79: AssertionError
- _______ TestSpecialisedExplanations.test_not_in_text_multiline ________
-
- self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
-
- def test_not_in_text_multiline(self):
- text = 'some multiline\ntext\nwhich\nincludes foo\nand a\ntail'
- > assert 'foo' not in text
- E assert 'foo' not in 'some multiline\ntext\nw...ncludes foo\nand a\ntail'
- E 'foo' is contained here:
- E some multiline
- E text
- E which
- E includes foo
- E ? +++
- E and a
- E tail
-
- failure_demo.py:83: AssertionError
- _______ TestSpecialisedExplanations.test_not_in_text_single ________
-
- self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
-
- def test_not_in_text_single(self):
- text = 'single foo line'
- > assert 'foo' not in text
- E assert 'foo' not in 'single foo line'
- E 'foo' is contained here:
- E single foo line
- E ? +++
-
- failure_demo.py:87: AssertionError
- _______ TestSpecialisedExplanations.test_not_in_text_single_long ________
-
- self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
-
- def test_not_in_text_single_long(self):
- text = 'head ' * 50 + 'foo ' + 'tail ' * 20
- > assert 'foo' not in text
- E assert 'foo' not in 'head head head head hea...ail tail tail tail tail '
- E 'foo' is contained here:
- E head head foo tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail
- E ? +++
-
- failure_demo.py:91: AssertionError
- ______ TestSpecialisedExplanations.test_not_in_text_single_long_term _______
-
- self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
-
- def test_not_in_text_single_long_term(self):
- text = 'head ' * 50 + 'f'*70 + 'tail ' * 20
- > assert 'f'*70 not in text
- E assert 'fffffffffff...ffffffffffff' not in 'head head he...l tail tail '
- E 'ffffffffffffffffff...fffffffffffffffffff' is contained here:
- E head head fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffftail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail
- E ? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- failure_demo.py:95: AssertionError
- _______ test_attribute ________
-
- def test_attribute():
- class Foo(object):
- b = 1
- i = Foo()
- > assert i.b == 2
- E assert 1 == 2
- E + where 1 = <failure_demo.test_attribute.<locals>.Foo object at 0xdeadbeef>.b
-
- failure_demo.py:102: AssertionError
- _______ test_attribute_instance ________
-
- def test_attribute_instance():
- class Foo(object):
- b = 1
- > assert Foo().b == 2
- E assert 1 == 2
- E + where 1 = <failure_demo.test_attribute_instance.<locals>.Foo object at 0xdeadbeef>.b
- E + where <failure_demo.test_attribute_instance.<locals>.Foo object at 0xdeadbeef> = <class 'failure_demo.test_attribute_instance.<locals>.Foo'>()
-
- failure_demo.py:108: AssertionError
- _______ test_attribute_failure ________
-
- def test_attribute_failure():
- class Foo(object):
- def _get_b(self):
- raise Exception('Failed to get attrib')
- b = property(_get_b)
- i = Foo()
- > assert i.b == 2
-
- failure_demo.py:117:
- _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
-
- self = <failure_demo.test_attribute_failure.<locals>.Foo object at 0xdeadbeef>
-
- def _get_b(self):
- > raise Exception('Failed to get attrib')
- E Exception: Failed to get attrib
-
- failure_demo.py:114: Exception
- _______ test_attribute_multiple ________
-
- def test_attribute_multiple():
- class Foo(object):
- b = 1
- class Bar(object):
- b = 2
- > assert Foo().b == Bar().b
- E assert 1 == 2
- E + where 1 = <failure_demo.test_attribute_multiple.<locals>.Foo object at 0xdeadbeef>.b
- E + where <failure_demo.test_attribute_multiple.<locals>.Foo object at 0xdeadbeef> = <class 'failure_demo.test_attribute_multiple.<locals>.Foo'>()
- E + and 2 = <failure_demo.test_attribute_multiple.<locals>.Bar object at 0xdeadbeef>.b
- E + where <failure_demo.test_attribute_multiple.<locals>.Bar object at 0xdeadbeef> = <class 'failure_demo.test_attribute_multiple.<locals>.Bar'>()
-
- failure_demo.py:125: AssertionError
- _______ TestRaises.test_raises ________
-
- self = <failure_demo.TestRaises object at 0xdeadbeef>
-
- def test_raises(self):
- s = 'qwe'
- > raises(TypeError, "int(s)")
-
- failure_demo.py:134:
- _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
-
- > int(s)
- E ValueError: invalid literal for int() with base 10: 'qwe'
-
- <0-codegen $PYTHON_PREFIX/lib/python3.4/site-packages/_pytest/python.py:1302>:1: ValueError
- _______ TestRaises.test_raises_doesnt ________
-
- self = <failure_demo.TestRaises object at 0xdeadbeef>
-
- def test_raises_doesnt(self):
- > raises(IOError, "int('3')")
- E Failed: DID NOT RAISE <class 'OSError'>
-
- failure_demo.py:137: Failed
- _______ TestRaises.test_raise ________
-
- self = <failure_demo.TestRaises object at 0xdeadbeef>
-
- def test_raise(self):
- > raise ValueError("demo error")
- E ValueError: demo error
-
- failure_demo.py:140: ValueError
- _______ TestRaises.test_tupleerror ________
-
- self = <failure_demo.TestRaises object at 0xdeadbeef>
-
- def test_tupleerror(self):
- > a,b = [1]
- E ValueError: need more than 1 value to unpack
-
- failure_demo.py:143: ValueError
- ______ TestRaises.test_reinterpret_fails_with_print_for_the_fun_of_it ______
-
- self = <failure_demo.TestRaises object at 0xdeadbeef>
-
- def test_reinterpret_fails_with_print_for_the_fun_of_it(self):
- l = [1,2,3]
- print ("l is %r" % l)
- > a,b = l.pop()
- E TypeError: 'int' object is not iterable
-
- failure_demo.py:148: TypeError
- --------------------------- Captured stdout call ---------------------------
- l is [1, 2, 3]
- _______ TestRaises.test_some_error ________
-
- self = <failure_demo.TestRaises object at 0xdeadbeef>
-
- def test_some_error(self):
- > if namenotexi:
- E NameError: name 'namenotexi' is not defined
-
- failure_demo.py:151: NameError
- _______ test_dynamic_compile_shows_nicely ________
-
- def test_dynamic_compile_shows_nicely():
- src = 'def foo():\n assert 1 == 0\n'
- name = 'abc-123'
- module = py.std.imp.new_module(name)
- code = _pytest._code.compile(src, name, 'exec')
- py.builtin.exec_(code, module.__dict__)
- py.std.sys.modules[name] = module
- > module.foo()
-
- failure_demo.py:166:
- _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
-
- def foo():
- > assert 1 == 0
- E assert 1 == 0
-
- <2-codegen 'abc-123' $REGENDOC_TMPDIR/assertion/failure_demo.py:163>:2: AssertionError
- _______ TestMoreErrors.test_complex_error ________
-
- self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
-
- def test_complex_error(self):
- def f():
- return 44
- def g():
- return 43
- > somefunc(f(), g())
-
- failure_demo.py:176:
- _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
- failure_demo.py:9: in somefunc
- otherfunc(x,y)
- _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
-
- a = 44, b = 43
-
- def otherfunc(a,b):
- > assert a==b
- E assert 44 == 43
-
- failure_demo.py:6: AssertionError
- _______ TestMoreErrors.test_z1_unpack_error ________
-
- self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
-
- def test_z1_unpack_error(self):
- l = []
- > a,b = l
- E ValueError: need more than 0 values to unpack
-
- failure_demo.py:180: ValueError
- _______ TestMoreErrors.test_z2_type_error ________
-
- self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
-
- def test_z2_type_error(self):
- l = 3
- > a,b = l
- E TypeError: 'int' object is not iterable
-
- failure_demo.py:184: TypeError
- _______ TestMoreErrors.test_startswith ________
-
- self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
-
- def test_startswith(self):
- s = "123"
- g = "456"
- > assert s.startswith(g)
- E assert <built-in method startswith of str object at 0xdeadbeef>('456')
- E + where <built-in method startswith of str object at 0xdeadbeef> = '123'.startswith
-
- failure_demo.py:189: AssertionError
- _______ TestMoreErrors.test_startswith_nested ________
-
- self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
-
- def test_startswith_nested(self):
- def f():
- return "123"
- def g():
- return "456"
- > assert f().startswith(g())
- E assert <built-in method startswith of str object at 0xdeadbeef>('456')
- E + where <built-in method startswith of str object at 0xdeadbeef> = '123'.startswith
- E + where '123' = <function TestMoreErrors.test_startswith_nested.<locals>.f at 0xdeadbeef>()
- E + and '456' = <function TestMoreErrors.test_startswith_nested.<locals>.g at 0xdeadbeef>()
-
- failure_demo.py:196: AssertionError
- _______ TestMoreErrors.test_global_func ________
-
- self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
-
- def test_global_func(self):
- > assert isinstance(globf(42), float)
- E assert isinstance(43, float)
- E + where 43 = globf(42)
-
- failure_demo.py:199: AssertionError
- _______ TestMoreErrors.test_instance ________
-
- self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
-
- def test_instance(self):
- self.x = 6*7
- > assert self.x != 42
- E assert 42 != 42
- E + where 42 = <failure_demo.TestMoreErrors object at 0xdeadbeef>.x
-
- failure_demo.py:203: AssertionError
- _______ TestMoreErrors.test_compare ________
-
- self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
-
- def test_compare(self):
- > assert globf(10) < 5
- E assert 11 < 5
- E + where 11 = globf(10)
-
- failure_demo.py:206: AssertionError
- _______ TestMoreErrors.test_try_finally ________
-
- self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
-
- def test_try_finally(self):
- x = 1
- try:
- > assert x == 0
- E assert 1 == 0
-
- failure_demo.py:211: AssertionError
- _______ TestCustomAssertMsg.test_single_line ________
-
- self = <failure_demo.TestCustomAssertMsg object at 0xdeadbeef>
-
- def test_single_line(self):
- class A:
- a = 1
- b = 2
- > assert A.a == b, "A.a appears not to be b"
- E AssertionError: A.a appears not to be b
- E assert 1 == 2
- E + where 1 = <class 'failure_demo.TestCustomAssertMsg.test_single_line.<locals>.A'>.a
-
- failure_demo.py:222: AssertionError
- _______ TestCustomAssertMsg.test_multiline ________
-
- self = <failure_demo.TestCustomAssertMsg object at 0xdeadbeef>
-
- def test_multiline(self):
- class A:
- a = 1
- b = 2
- > assert A.a == b, "A.a appears not to be b\n" \
- "or does not appear to be b\none of those"
- E AssertionError: A.a appears not to be b
- E or does not appear to be b
- E one of those
- E assert 1 == 2
- E + where 1 = <class 'failure_demo.TestCustomAssertMsg.test_multiline.<locals>.A'>.a
-
- failure_demo.py:228: AssertionError
- _______ TestCustomAssertMsg.test_custom_repr ________
-
- self = <failure_demo.TestCustomAssertMsg object at 0xdeadbeef>
-
- def test_custom_repr(self):
- class JSON:
- a = 1
- def __repr__(self):
- return "This is JSON\n{\n 'foo': 'bar'\n}"
- a = JSON()
- b = 2
- > assert a.a == b, a
- E AssertionError: This is JSON
- E {
- E 'foo': 'bar'
- E }
- E assert 1 == 2
- E + where 1 = This is JSON\n{\n 'foo': 'bar'\n}.a
-
- failure_demo.py:238: AssertionError
- ======= 42 failed in 0.12 seconds ========
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/simple.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/simple.rst
deleted file mode 100644
index be12d2afe41..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/simple.rst
+++ /dev/null
@@ -1,751 +0,0 @@
-
-.. highlightlang:: python
-
-Basic patterns and examples
-==========================================================
-
-Pass different values to a test function, depending on command line options
-----------------------------------------------------------------------------
-
-.. regendoc:wipe
-
-Suppose we want to write a test that depends on a command line option.
-Here is a basic pattern to achieve this::
-
- # content of test_sample.py
- def test_answer(cmdopt):
- if cmdopt == "type1":
- print ("first")
- elif cmdopt == "type2":
- print ("second")
- assert 0 # to see what was printed
-
-
-For this to work we need to add a command line option and
-provide the ``cmdopt`` through a :ref:`fixture function <fixture function>`::
-
- # content of conftest.py
- import pytest
-
- def pytest_addoption(parser):
- parser.addoption("--cmdopt", action="store", default="type1",
- help="my option: type1 or type2")
-
- @pytest.fixture
- def cmdopt(request):
- return request.config.getoption("--cmdopt")
-
-Let's run this without supplying our new option::
-
- $ py.test -q test_sample.py
- F
- ======= FAILURES ========
- _______ test_answer ________
-
- cmdopt = 'type1'
-
- def test_answer(cmdopt):
- if cmdopt == "type1":
- print ("first")
- elif cmdopt == "type2":
- print ("second")
- > assert 0 # to see what was printed
- E assert 0
-
- test_sample.py:6: AssertionError
- --------------------------- Captured stdout call ---------------------------
- first
- 1 failed in 0.12 seconds
-
-And now with supplying a command line option::
-
- $ py.test -q --cmdopt=type2
- F
- ======= FAILURES ========
- _______ test_answer ________
-
- cmdopt = 'type2'
-
- def test_answer(cmdopt):
- if cmdopt == "type1":
- print ("first")
- elif cmdopt == "type2":
- print ("second")
- > assert 0 # to see what was printed
- E assert 0
-
- test_sample.py:6: AssertionError
- --------------------------- Captured stdout call ---------------------------
- second
- 1 failed in 0.12 seconds
-
-You can see that the command line option arrived in our test. This
-completes the basic pattern. However, one often rather wants to process
-command line options outside of the test and rather pass in different or
-more complex objects.
-
-Dynamically adding command line options
---------------------------------------------------------------
-
-.. regendoc:wipe
-
-Through :confval:`addopts` you can statically add command line
-options for your project. You can also dynamically modify
-the command line arguments before they get processed::
-
- # content of conftest.py
- import sys
- def pytest_cmdline_preparse(args):
- if 'xdist' in sys.modules: # pytest-xdist plugin
- import multiprocessing
- num = max(multiprocessing.cpu_count() / 2, 1)
- args[:] = ["-n", str(num)] + args
-
-If you have the :ref:`xdist plugin <xdist>` installed
-you will now always perform test runs using a number
-of subprocesses close to your CPU. Running in an empty
-directory with the above conftest.py::
-
- $ py.test
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 0 items
-
- ======= no tests ran in 0.12 seconds ========
-
-.. _`excontrolskip`:
-
-Control skipping of tests according to command line option
---------------------------------------------------------------
-
-.. regendoc:wipe
-
-Here is a ``conftest.py`` file adding a ``--runslow`` command
-line option to control skipping of ``slow`` marked tests::
-
- # content of conftest.py
-
- import pytest
- def pytest_addoption(parser):
- parser.addoption("--runslow", action="store_true",
- help="run slow tests")
-
-We can now write a test module like this::
-
- # content of test_module.py
-
- import pytest
-
-
- slow = pytest.mark.skipif(
- not pytest.config.getoption("--runslow"),
- reason="need --runslow option to run"
- )
-
-
- def test_func_fast():
- pass
-
-
- @slow
- def test_func_slow():
- pass
-
-and when running it will see a skipped "slow" test::
-
- $ py.test -rs # "-rs" means report details on the little 's'
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 2 items
-
- test_module.py .s
- ======= short test summary info ========
- SKIP [1] test_module.py:14: need --runslow option to run
-
- ======= 1 passed, 1 skipped in 0.12 seconds ========
-
-Or run it including the ``slow`` marked test::
-
- $ py.test --runslow
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 2 items
-
- test_module.py ..
-
- ======= 2 passed in 0.12 seconds ========
-
-Writing well integrated assertion helpers
---------------------------------------------------
-
-.. regendoc:wipe
-
-If you have a test helper function called from a test you can
-use the ``pytest.fail`` marker to fail a test with a certain message.
-The test support function will not show up in the traceback if you
-set the ``__tracebackhide__`` option somewhere in the helper function.
-Example::
-
- # content of test_checkconfig.py
- import pytest
- def checkconfig(x):
- __tracebackhide__ = True
- if not hasattr(x, "config"):
- pytest.fail("not configured: %s" %(x,))
-
- def test_something():
- checkconfig(42)
-
-The ``__tracebackhide__`` setting influences ``pytest`` showing
-of tracebacks: the ``checkconfig`` function will not be shown
-unless the ``--fulltrace`` command line option is specified.
-Let's run our little function::
-
- $ py.test -q test_checkconfig.py
- F
- ======= FAILURES ========
- _______ test_something ________
-
- def test_something():
- > checkconfig(42)
- E Failed: not configured: 42
-
- test_checkconfig.py:8: Failed
- 1 failed in 0.12 seconds
-
-Detect if running from within a pytest run
---------------------------------------------------------------
-
-.. regendoc:wipe
-
-Usually it is a bad idea to make application code
-behave differently if called from a test. But if you
-absolutely must find out if your application code is
-running from a test you can do something like this::
-
- # content of conftest.py
-
- def pytest_configure(config):
- import sys
- sys._called_from_test = True
-
- def pytest_unconfigure(config):
- del sys._called_from_test
-
-and then check for the ``sys._called_from_test`` flag::
-
- if hasattr(sys, '_called_from_test'):
- # called from within a test run
- else:
- # called "normally"
-
-accordingly in your application. It's also a good idea
-to use your own application module rather than ``sys``
-for handling flag.
-
-Adding info to test report header
---------------------------------------------------------------
-
-.. regendoc:wipe
-
-It's easy to present extra information in a ``pytest`` run::
-
- # content of conftest.py
-
- def pytest_report_header(config):
- return "project deps: mylib-1.1"
-
-which will add the string to the test header accordingly::
-
- $ py.test
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- project deps: mylib-1.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 0 items
-
- ======= no tests ran in 0.12 seconds ========
-
-.. regendoc:wipe
-
-You can also return a list of strings which will be considered as several
-lines of information. You can of course also make the amount of reporting
-information on e.g. the value of ``config.option.verbose`` so that
-you present more information appropriately::
-
- # content of conftest.py
-
- def pytest_report_header(config):
- if config.option.verbose > 0:
- return ["info1: did you know that ...", "did you?"]
-
-which will add info only when run with "--v"::
-
- $ py.test -v
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.4
- cachedir: .cache
- info1: did you know that ...
- did you?
- rootdir: $REGENDOC_TMPDIR, inifile:
- collecting ... collected 0 items
-
- ======= no tests ran in 0.12 seconds ========
-
-and nothing when run plainly::
-
- $ py.test
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 0 items
-
- ======= no tests ran in 0.12 seconds ========
-
-profiling test duration
---------------------------
-
-.. regendoc:wipe
-
-.. versionadded: 2.2
-
-If you have a slow running large test suite you might want to find
-out which tests are the slowest. Let's make an artificial test suite::
-
- # content of test_some_are_slow.py
-
- import time
-
- def test_funcfast():
- pass
-
- def test_funcslow1():
- time.sleep(0.1)
-
- def test_funcslow2():
- time.sleep(0.2)
-
-Now we can profile which test functions execute the slowest::
-
- $ py.test --durations=3
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 3 items
-
- test_some_are_slow.py ...
-
- ======= slowest 3 test durations ========
- 0.20s call test_some_are_slow.py::test_funcslow2
- 0.10s call test_some_are_slow.py::test_funcslow1
- 0.00s setup test_some_are_slow.py::test_funcfast
- ======= 3 passed in 0.12 seconds ========
-
-incremental testing - test steps
----------------------------------------------------
-
-.. regendoc:wipe
-
-Sometimes you may have a testing situation which consists of a series
-of test steps. If one step fails it makes no sense to execute further
-steps as they are all expected to fail anyway and their tracebacks
-add no insight. Here is a simple ``conftest.py`` file which introduces
-an ``incremental`` marker which is to be used on classes::
-
- # content of conftest.py
-
- import pytest
-
- def pytest_runtest_makereport(item, call):
- if "incremental" in item.keywords:
- if call.excinfo is not None:
- parent = item.parent
- parent._previousfailed = item
-
- def pytest_runtest_setup(item):
- if "incremental" in item.keywords:
- previousfailed = getattr(item.parent, "_previousfailed", None)
- if previousfailed is not None:
- pytest.xfail("previous test failed (%s)" %previousfailed.name)
-
-These two hook implementations work together to abort incremental-marked
-tests in a class. Here is a test module example::
-
- # content of test_step.py
-
- import pytest
-
- @pytest.mark.incremental
- class TestUserHandling:
- def test_login(self):
- pass
- def test_modification(self):
- assert 0
- def test_deletion(self):
- pass
-
- def test_normal():
- pass
-
-If we run this::
-
- $ py.test -rx
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 4 items
-
- test_step.py .Fx.
- ======= short test summary info ========
- XFAIL test_step.py::TestUserHandling::()::test_deletion
- reason: previous test failed (test_modification)
-
- ======= FAILURES ========
- _______ TestUserHandling.test_modification ________
-
- self = <test_step.TestUserHandling object at 0xdeadbeef>
-
- def test_modification(self):
- > assert 0
- E assert 0
-
- test_step.py:9: AssertionError
- ======= 1 failed, 2 passed, 1 xfailed in 0.12 seconds ========
-
-We'll see that ``test_deletion`` was not executed because ``test_modification``
-failed. It is reported as an "expected failure".
-
-
-Package/Directory-level fixtures (setups)
--------------------------------------------------------
-
-If you have nested test directories, you can have per-directory fixture scopes
-by placing fixture functions in a ``conftest.py`` file in that directory
-You can use all types of fixtures including :ref:`autouse fixtures
-<autouse fixtures>` which are the equivalent of xUnit's setup/teardown
-concept. It's however recommended to have explicit fixture references in your
-tests or test classes rather than relying on implicitly executing
-setup/teardown functions, especially if they are far away from the actual tests.
-
-Here is a an example for making a ``db`` fixture available in a directory::
-
- # content of a/conftest.py
- import pytest
-
- class DB:
- pass
-
- @pytest.fixture(scope="session")
- def db():
- return DB()
-
-and then a test module in that directory::
-
- # content of a/test_db.py
- def test_a1(db):
- assert 0, db # to show value
-
-another test module::
-
- # content of a/test_db2.py
- def test_a2(db):
- assert 0, db # to show value
-
-and then a module in a sister directory which will not see
-the ``db`` fixture::
-
- # content of b/test_error.py
- def test_root(db): # no db here, will error out
- pass
-
-We can run this::
-
- $ py.test
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 7 items
-
- test_step.py .Fx.
- a/test_db.py F
- a/test_db2.py F
- b/test_error.py E
-
- ======= ERRORS ========
- _______ ERROR at setup of test_root ________
- file $REGENDOC_TMPDIR/b/test_error.py, line 1
- def test_root(db): # no db here, will error out
- fixture 'db' not found
- available fixtures: record_xml_property, recwarn, cache, capsys, pytestconfig, tmpdir_factory, capfd, monkeypatch, tmpdir
- use 'py.test --fixtures [testpath]' for help on them.
-
- $REGENDOC_TMPDIR/b/test_error.py:1
- ======= FAILURES ========
- _______ TestUserHandling.test_modification ________
-
- self = <test_step.TestUserHandling object at 0xdeadbeef>
-
- def test_modification(self):
- > assert 0
- E assert 0
-
- test_step.py:9: AssertionError
- _______ test_a1 ________
-
- db = <conftest.DB object at 0xdeadbeef>
-
- def test_a1(db):
- > assert 0, db # to show value
- E AssertionError: <conftest.DB object at 0xdeadbeef>
- E assert 0
-
- a/test_db.py:2: AssertionError
- _______ test_a2 ________
-
- db = <conftest.DB object at 0xdeadbeef>
-
- def test_a2(db):
- > assert 0, db # to show value
- E AssertionError: <conftest.DB object at 0xdeadbeef>
- E assert 0
-
- a/test_db2.py:2: AssertionError
- ======= 3 failed, 2 passed, 1 xfailed, 1 error in 0.12 seconds ========
-
-The two test modules in the ``a`` directory see the same ``db`` fixture instance
-while the one test in the sister-directory ``b`` doesn't see it. We could of course
-also define a ``db`` fixture in that sister directory's ``conftest.py`` file.
-Note that each fixture is only instantiated if there is a test actually needing
-it (unless you use "autouse" fixture which are always executed ahead of the first test
-executing).
-
-
-post-process test reports / failures
----------------------------------------
-
-If you want to postprocess test reports and need access to the executing
-environment you can implement a hook that gets called when the test
-"report" object is about to be created. Here we write out all failing
-test calls and also access a fixture (if it was used by the test) in
-case you want to query/look at it during your post processing. In our
-case we just write some informations out to a ``failures`` file::
-
- # content of conftest.py
-
- import pytest
- import os.path
-
- @pytest.hookimpl(tryfirst=True, hookwrapper=True)
- def pytest_runtest_makereport(item, call):
- # execute all other hooks to obtain the report object
- outcome = yield
- rep = outcome.get_result()
-
- # we only look at actual failing test calls, not setup/teardown
- if rep.when == "call" and rep.failed:
- mode = "a" if os.path.exists("failures") else "w"
- with open("failures", mode) as f:
- # let's also access a fixture for the fun of it
- if "tmpdir" in item.fixturenames:
- extra = " (%s)" % item.funcargs["tmpdir"]
- else:
- extra = ""
-
- f.write(rep.nodeid + extra + "\n")
-
-
-if you then have failing tests::
-
- # content of test_module.py
- def test_fail1(tmpdir):
- assert 0
- def test_fail2():
- assert 0
-
-and run them::
-
- $ py.test test_module.py
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 2 items
-
- test_module.py FF
-
- ======= FAILURES ========
- _______ test_fail1 ________
-
- tmpdir = local('PYTEST_TMPDIR/test_fail10')
-
- def test_fail1(tmpdir):
- > assert 0
- E assert 0
-
- test_module.py:2: AssertionError
- _______ test_fail2 ________
-
- def test_fail2():
- > assert 0
- E assert 0
-
- test_module.py:4: AssertionError
- ======= 2 failed in 0.12 seconds ========
-
-you will have a "failures" file which contains the failing test ids::
-
- $ cat failures
- test_module.py::test_fail1 (PYTEST_TMPDIR/test_fail10)
- test_module.py::test_fail2
-
-Making test result information available in fixtures
------------------------------------------------------------
-
-.. regendoc:wipe
-
-If you want to make test result reports available in fixture finalizers
-here is a little example implemented via a local plugin::
-
- # content of conftest.py
-
- import pytest
-
- @pytest.hookimpl(tryfirst=True, hookwrapper=True)
- def pytest_runtest_makereport(item, call):
- # execute all other hooks to obtain the report object
- outcome = yield
- rep = outcome.get_result()
-
- # set an report attribute for each phase of a call, which can
- # be "setup", "call", "teardown"
-
- setattr(item, "rep_" + rep.when, rep)
-
-
- @pytest.fixture
- def something(request):
- def fin():
- # request.node is an "item" because we use the default
- # "function" scope
- if request.node.rep_setup.failed:
- print ("setting up a test failed!", request.node.nodeid)
- elif request.node.rep_setup.passed:
- if request.node.rep_call.failed:
- print ("executing test failed", request.node.nodeid)
- request.addfinalizer(fin)
-
-
-if you then have failing tests::
-
- # content of test_module.py
-
- import pytest
-
- @pytest.fixture
- def other():
- assert 0
-
- def test_setup_fails(something, other):
- pass
-
- def test_call_fails(something):
- assert 0
-
- def test_fail2():
- assert 0
-
-and run it::
-
- $ py.test -s test_module.py
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 3 items
-
- test_module.py Esetting up a test failed! test_module.py::test_setup_fails
- Fexecuting test failed test_module.py::test_call_fails
- F
-
- ======= ERRORS ========
- _______ ERROR at setup of test_setup_fails ________
-
- @pytest.fixture
- def other():
- > assert 0
- E assert 0
-
- test_module.py:6: AssertionError
- ======= FAILURES ========
- _______ test_call_fails ________
-
- something = None
-
- def test_call_fails(something):
- > assert 0
- E assert 0
-
- test_module.py:12: AssertionError
- _______ test_fail2 ________
-
- def test_fail2():
- > assert 0
- E assert 0
-
- test_module.py:15: AssertionError
- ======= 2 failed, 1 error in 0.12 seconds ========
-
-You'll see that the fixture finalizers could use the precise reporting
-information.
-
-Integrating pytest runner and cx_freeze
------------------------------------------------------------
-
-If you freeze your application using a tool like
-`cx_freeze <http://cx-freeze.readthedocs.org>`_ in order to distribute it
-to your end-users, it is a good idea to also package your test runner and run
-your tests using the frozen application.
-
-This way packaging errors such as dependencies not being
-included into the executable can be detected early while also allowing you to
-send test files to users so they can run them in their machines, which can be
-invaluable to obtain more information about a hard to reproduce bug.
-
-Unfortunately ``cx_freeze`` can't discover them
-automatically because of ``pytest``'s use of dynamic module loading, so you
-must declare them explicitly by using ``pytest.freeze_includes()``::
-
- # contents of setup.py
- from cx_Freeze import setup, Executable
- import pytest
-
- setup(
- name="app_main",
- executables=[Executable("app_main.py")],
- options={"build_exe":
- {
- 'includes': pytest.freeze_includes()}
- },
- # ... other options
- )
-
-If you don't want to ship a different executable just in order to run your tests,
-you can make your program check for a certain flag and pass control
-over to ``pytest`` instead. For example::
-
- # contents of app_main.py
- import sys
-
- if len(sys.argv) > 1 and sys.argv[1] == '--pytest':
- import pytest
- sys.exit(pytest.main(sys.argv[2:]))
- else:
- # normal application execution: at this point argv can be parsed
- # by your argument-parsing library of choice as usual
- ...
-
-This makes it convenient to execute your tests from within your frozen
-application, using standard ``py.test`` command-line options::
-
- ./app_main --pytest --verbose --tb=long --junitxml=results.xml test-suite/
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/special.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/special.rst
deleted file mode 100644
index 58e66d44e34..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/special.rst
+++ /dev/null
@@ -1,72 +0,0 @@
-A session-fixture which can look at all collected tests
-----------------------------------------------------------------
-
-A session-scoped fixture effectively has access to all
-collected test items. Here is an example of a fixture
-function which walks all collected tests and looks
-if their test class defines a ``callme`` method and
-calls it::
-
- # content of conftest.py
-
- import pytest
-
- @pytest.fixture(scope="session", autouse=True)
- def callattr_ahead_of_alltests(request):
- print ("callattr_ahead_of_alltests called")
- seen = set([None])
- session = request.node
- for item in session.items:
- cls = item.getparent(pytest.Class)
- if cls not in seen:
- if hasattr(cls.obj, "callme"):
- cls.obj.callme()
- seen.add(cls)
-
-test classes may now define a ``callme`` method which
-will be called ahead of running any tests::
-
- # content of test_module.py
-
- class TestHello:
- @classmethod
- def callme(cls):
- print ("callme called!")
-
- def test_method1(self):
- print ("test_method1 called")
-
- def test_method2(self):
- print ("test_method1 called")
-
- class TestOther:
- @classmethod
- def callme(cls):
- print ("callme other called")
- def test_other(self):
- print ("test other")
-
- # works with unittest as well ...
- import unittest
-
- class SomeTest(unittest.TestCase):
- @classmethod
- def callme(self):
- print ("SomeTest callme called")
-
- def test_unit1(self):
- print ("test_unit1 method called")
-
-If you run this without output capturing::
-
- $ py.test -q -s test_module.py
- callattr_ahead_of_alltests called
- callme called!
- callme other called
- SomeTest callme called
- test_method1 called
- .test_method1 called
- .test other
- .test_unit1 method called
- .
- 4 passed in 0.12 seconds
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/faq.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/faq.rst
deleted file mode 100644
index fd7ca35e943..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/faq.rst
+++ /dev/null
@@ -1,165 +0,0 @@
-Some Issues and Questions
-==================================
-
-.. note::
-
- This FAQ is here only mostly for historic reasons. Checkout
- `pytest Q&A at Stackoverflow <http://stackoverflow.com/search?q=pytest>`_
- for many questions and answers related to pytest and/or use
- :ref:`contact channels` to get help.
-
-On naming, nosetests, licensing and magic
-------------------------------------------------
-
-How does pytest relate to nose and unittest?
-+++++++++++++++++++++++++++++++++++++++++++++++++
-
-``pytest`` and nose_ share basic philosophy when it comes
-to running and writing Python tests. In fact, you can run many tests
-written for nose with ``pytest``. nose_ was originally created
-as a clone of ``pytest`` when ``pytest`` was in the ``0.8`` release
-cycle. Note that starting with pytest-2.0 support for running unittest
-test suites is majorly improved.
-
-how does pytest relate to twisted's trial?
-++++++++++++++++++++++++++++++++++++++++++++++
-
-Since some time ``pytest`` has builtin support for supporting tests
-written using trial. It does not itself start a reactor, however,
-and does not handle Deferreds returned from a test in pytest style.
-If you are using trial's unittest.TestCase chances are that you can
-just run your tests even if you return Deferreds. In addition,
-there also is a dedicated `pytest-twisted
-<http://pypi.python.org/pypi/pytest-twisted>`_ plugin which allows you to
-return deferreds from pytest-style tests, allowing the use of
-:ref:`fixtures` and other features.
-
-how does pytest work with Django?
-++++++++++++++++++++++++++++++++++++++++++++++
-
-In 2012, some work is going into the `pytest-django plugin <http://pypi.python.org/pypi/pytest-django>`_. It substitutes the usage of Django's
-``manage.py test`` and allows the use of all pytest features_ most of which
-are not available from Django directly.
-
-.. _features: features.html
-
-
-What's this "magic" with pytest? (historic notes)
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-Around 2007 (version ``0.8``) some people thought that ``pytest``
-was using too much "magic". It had been part of the `pylib`_ which
-contains a lot of unrelated python library code. Around 2010 there
-was a major cleanup refactoring, which removed unused or deprecated code
-and resulted in the new ``pytest`` PyPI package which strictly contains
-only test-related code. This release also brought a complete pluginification
-such that the core is around 300 lines of code and everything else is
-implemented in plugins. Thus ``pytest`` today is a small, universally runnable
-and customizable testing framework for Python. Note, however, that
-``pytest`` uses metaprogramming techniques and reading its source is
-thus likely not something for Python beginners.
-
-A second "magic" issue was the assert statement debugging feature.
-Nowadays, ``pytest`` explicitly rewrites assert statements in test modules
-in order to provide more useful :ref:`assert feedback <assertfeedback>`.
-This completely avoids previous issues of confusing assertion-reporting.
-It also means, that you can use Python's ``-O`` optimization without losing
-assertions in test modules.
-
-``pytest`` contains a second, mostly obsolete, assert debugging technique
-invoked via ``--assert=reinterpret``: When an ``assert`` statement fails, ``pytest`` re-interprets
-the expression part to show intermediate values. This technique suffers
-from a caveat that the rewriting does not: If your expression has side
-effects (better to avoid them anyway!) the intermediate values may not
-be the same, confusing the reinterpreter and obfuscating the initial
-error (this is also explained at the command line if it happens).
-
-You can also turn off all assertion interaction using the
-``--assert=plain`` option.
-
-.. _`py namespaces`: index.html
-.. _`py/__init__.py`: http://bitbucket.org/hpk42/py-trunk/src/trunk/py/__init__.py
-
-
-Why a ``py.test`` instead of a ``pytest`` command?
-++++++++++++++++++++++++++++++++++++++++++++++++++
-
-Some of the reasons are historic, others are practical. ``pytest``
-used to be part of the ``py`` package which provided several developer
-utilities, all starting with ``py.<TAB>``, thus providing nice
-TAB-completion. If
-you install ``pip install pycmd`` you get these tools from a separate
-package. These days the command line tool could be called ``pytest``
-but since many people have gotten used to the old name and there
-is another tool named "pytest" we just decided to stick with
-``py.test`` for now.
-
-pytest fixtures, parametrized tests
--------------------------------------------------------
-
-.. _funcargs: funcargs.html
-
-Is using pytest fixtures versus xUnit setup a style question?
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-For simple applications and for people experienced with nose_ or
-unittest-style test setup using `xUnit style setup`_ probably
-feels natural. For larger test suites, parametrized testing
-or setup of complex test resources using fixtures_ may feel more natural.
-Moreover, fixtures are ideal for writing advanced test support
-code (like e.g. the monkeypatch_, the tmpdir_ or capture_ fixtures)
-because the support code can register setup/teardown functions
-in a managed class/module/function scope.
-
-.. _monkeypatch: monkeypatch.html
-.. _tmpdir: tmpdir.html
-.. _capture: capture.html
-.. _fixtures: fixture.html
-
-.. _`why pytest_pyfuncarg__ methods?`:
-
-.. _`Convention over Configuration`: http://en.wikipedia.org/wiki/Convention_over_Configuration
-
-Can I yield multiple values from a fixture function?
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-There are two conceptual reasons why yielding from a factory function
-is not possible:
-
-* If multiple factories yielded values there would
- be no natural place to determine the combination
- policy - in real-world examples some combinations
- often should not run.
-
-* Calling factories for obtaining test function arguments
- is part of setting up and running a test. At that
- point it is not possible to add new test calls to
- the test collection anymore.
-
-However, with pytest-2.3 you can use the :ref:`@pytest.fixture` decorator
-and specify ``params`` so that all tests depending on the factory-created
-resource will run multiple times with different parameters.
-
-You can also use the ``pytest_generate_tests`` hook to
-implement the `parametrization scheme of your choice`_. See also
-:ref:`paramexamples` for more examples.
-
-.. _`parametrization scheme of your choice`: http://tetamap.wordpress.com/2009/05/13/parametrizing-python-tests-generalized/
-
-pytest interaction with other packages
----------------------------------------------------
-
-Issues with pytest, multiprocess and setuptools?
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-On Windows the multiprocess package will instantiate sub processes
-by pickling and thus implicitly re-import a lot of local modules.
-Unfortunately, setuptools-0.6.11 does not ``if __name__=='__main__'``
-protect its generated command line script. This leads to infinite
-recursion when running a test that instantiates Processes.
-
-As of mid-2013, there shouldn't be a problem anymore when you
-use the standard setuptools (note that distribute has been merged
-back into setuptools which is now shipped directly with virtualenv).
-
-.. include:: links.inc
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/feedback.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/feedback.rst
deleted file mode 100644
index 9c63b7640e0..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/feedback.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-
-What users say:
-
- `py.test is pretty much the best thing ever`_ (Alex Gaynor)
-
-
-.. _`py.test is pretty much the best thing ever`_ (Alex Gaynor)
- http://twitter.com/#!/alex_gaynor/status/22389410366
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/fixture.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/fixture.rst
deleted file mode 100644
index f48607ae2dd..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/fixture.rst
+++ /dev/null
@@ -1,987 +0,0 @@
-.. _fixture:
-.. _fixtures:
-.. _`fixture functions`:
-
-pytest fixtures: explicit, modular, scalable
-========================================================
-
-.. currentmodule:: _pytest.python
-
-.. versionadded:: 2.0/2.3/2.4
-
-.. _`xUnit`: http://en.wikipedia.org/wiki/XUnit
-.. _`purpose of test fixtures`: http://en.wikipedia.org/wiki/Test_fixture#Software
-.. _`Dependency injection`: http://en.wikipedia.org/wiki/Dependency_injection#Definition
-
-The `purpose of test fixtures`_ is to provide a fixed baseline
-upon which tests can reliably and repeatedly execute. pytest fixtures
-offer dramatic improvements over the classic xUnit style of setup/teardown
-functions:
-
-* fixtures have explicit names and are activated by declaring their use
- from test functions, modules, classes or whole projects.
-
-* fixtures are implemented in a modular manner, as each fixture name
- triggers a *fixture function* which can itself use other fixtures.
-
-* fixture management scales from simple unit to complex
- functional testing, allowing to parametrize fixtures and tests according
- to configuration and component options, or to re-use fixtures
- across class, module or whole test session scopes.
-
-In addition, pytest continues to support :ref:`xunitsetup`. You can mix
-both styles, moving incrementally from classic to new style, as you
-prefer. You can also start out from existing :ref:`unittest.TestCase
-style <unittest.TestCase>` or :ref:`nose based <nosestyle>` projects.
-
-.. note::
-
- pytest-2.4 introduced an additional experimental
- :ref:`yield fixture mechanism <yieldfixture>` for easier context manager
- integration and more linear writing of teardown code.
-
-.. _`funcargs`:
-.. _`funcarg mechanism`:
-.. _`fixture function`:
-.. _`@pytest.fixture`:
-.. _`pytest.fixture`:
-
-Fixtures as Function arguments
------------------------------------------
-
-Test functions can receive fixture objects by naming them as an input
-argument. For each argument name, a fixture function with that name provides
-the fixture object. Fixture functions are registered by marking them with
-:py:func:`@pytest.fixture <_pytest.python.fixture>`. Let's look at a simple
-self-contained test module containing a fixture and a test function
-using it::
-
- # content of ./test_smtpsimple.py
- import pytest
-
- @pytest.fixture
- def smtp():
- import smtplib
- return smtplib.SMTP("smtp.gmail.com")
-
- def test_ehlo(smtp):
- response, msg = smtp.ehlo()
- assert response == 250
- assert 0 # for demo purposes
-
-Here, the ``test_ehlo`` needs the ``smtp`` fixture value. pytest
-will discover and call the :py:func:`@pytest.fixture <_pytest.python.fixture>`
-marked ``smtp`` fixture function. Running the test looks like this::
-
- $ py.test test_smtpsimple.py
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 1 items
-
- test_smtpsimple.py F
-
- ======= FAILURES ========
- _______ test_ehlo ________
-
- smtp = <smtplib.SMTP object at 0xdeadbeef>
-
- def test_ehlo(smtp):
- response, msg = smtp.ehlo()
- assert response == 250
- > assert 0 # for demo purposes
- E assert 0
-
- test_smtpsimple.py:11: AssertionError
- ======= 1 failed in 0.12 seconds ========
-
-In the failure traceback we see that the test function was called with a
-``smtp`` argument, the ``smtplib.SMTP()`` instance created by the fixture
-function. The test function fails on our deliberate ``assert 0``. Here is
-the exact protocol used by ``pytest`` to call the test function this way:
-
-1. pytest :ref:`finds <test discovery>` the ``test_ehlo`` because
- of the ``test_`` prefix. The test function needs a function argument
- named ``smtp``. A matching fixture function is discovered by
- looking for a fixture-marked function named ``smtp``.
-
-2. ``smtp()`` is called to create an instance.
-
-3. ``test_ehlo(<SMTP instance>)`` is called and fails in the last
- line of the test function.
-
-Note that if you misspell a function argument or want
-to use one that isn't available, you'll see an error
-with a list of available function arguments.
-
-.. Note::
-
- You can always issue::
-
- py.test --fixtures test_simplefactory.py
-
- to see available fixtures.
-
- In versions prior to 2.3 there was no ``@pytest.fixture`` marker
- and you had to use a magic ``pytest_funcarg__NAME`` prefix
- for the fixture factory. This remains and will remain supported
- but is not anymore advertised as the primary means of declaring fixture
- functions.
-
-"Funcargs" a prime example of dependency injection
----------------------------------------------------
-
-When injecting fixtures to test functions, pytest-2.0 introduced the
-term "funcargs" or "funcarg mechanism" which continues to be present
-also in docs today. It now refers to the specific case of injecting
-fixture values as arguments to test functions. With pytest-2.3 there are
-more possibilities to use fixtures but "funcargs" remain as the main way
-as they allow to directly state the dependencies of a test function.
-
-As the following examples show in more detail, funcargs allow test
-functions to easily receive and work against specific pre-initialized
-application objects without having to care about import/setup/cleanup
-details. It's a prime example of `dependency injection`_ where fixture
-functions take the role of the *injector* and test functions are the
-*consumers* of fixture objects.
-
-.. _smtpshared:
-
-Sharing a fixture across tests in a module (or class/session)
------------------------------------------------------------------
-
-.. regendoc:wipe
-
-Fixtures requiring network access depend on connectivity and are
-usually time-expensive to create. Extending the previous example, we
-can add a ``scope='module'`` parameter to the
-:py:func:`@pytest.fixture <_pytest.python.fixture>` invocation
-to cause the decorated ``smtp`` fixture function to only be invoked once
-per test module. Multiple test functions in a test module will thus
-each receive the same ``smtp`` fixture instance. The next example puts
-the fixture function into a separate ``conftest.py`` file so
-that tests from multiple test modules in the directory can
-access the fixture function::
-
- # content of conftest.py
- import pytest
- import smtplib
-
- @pytest.fixture(scope="module")
- def smtp():
- return smtplib.SMTP("smtp.gmail.com")
-
-The name of the fixture again is ``smtp`` and you can access its result by
-listing the name ``smtp`` as an input parameter in any test or fixture
-function (in or below the directory where ``conftest.py`` is located)::
-
- # content of test_module.py
-
- def test_ehlo(smtp):
- response, msg = smtp.ehlo()
- assert response == 250
- assert b"smtp.gmail.com" in msg
- assert 0 # for demo purposes
-
- def test_noop(smtp):
- response, msg = smtp.noop()
- assert response == 250
- assert 0 # for demo purposes
-
-We deliberately insert failing ``assert 0`` statements in order to
-inspect what is going on and can now run the tests::
-
- $ py.test test_module.py
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 2 items
-
- test_module.py FF
-
- ======= FAILURES ========
- _______ test_ehlo ________
-
- smtp = <smtplib.SMTP object at 0xdeadbeef>
-
- def test_ehlo(smtp):
- response, msg = smtp.ehlo()
- assert response == 250
- assert b"smtp.gmail.com" in msg
- > assert 0 # for demo purposes
- E assert 0
-
- test_module.py:6: AssertionError
- _______ test_noop ________
-
- smtp = <smtplib.SMTP object at 0xdeadbeef>
-
- def test_noop(smtp):
- response, msg = smtp.noop()
- assert response == 250
- > assert 0 # for demo purposes
- E assert 0
-
- test_module.py:11: AssertionError
- ======= 2 failed in 0.12 seconds ========
-
-You see the two ``assert 0`` failing and more importantly you can also see
-that the same (module-scoped) ``smtp`` object was passed into the two
-test functions because pytest shows the incoming argument values in the
-traceback. As a result, the two test functions using ``smtp`` run as
-quick as a single one because they reuse the same instance.
-
-If you decide that you rather want to have a session-scoped ``smtp``
-instance, you can simply declare it:
-
-.. code-block:: python
-
- @pytest.fixture(scope="session")
- def smtp(...):
- # the returned fixture value will be shared for
- # all tests needing it
-
-.. _`finalization`:
-
-Fixture finalization / executing teardown code
--------------------------------------------------------------
-
-pytest supports execution of fixture specific finalization code
-when the fixture goes out of scope. By accepting a ``request`` object
-into your fixture function you can call its ``request.addfinalizer`` one
-or multiple times::
-
- # content of conftest.py
-
- import smtplib
- import pytest
-
- @pytest.fixture(scope="module")
- def smtp(request):
- smtp = smtplib.SMTP("smtp.gmail.com")
- def fin():
- print ("teardown smtp")
- smtp.close()
- request.addfinalizer(fin)
- return smtp # provide the fixture value
-
-The ``fin`` function will execute when the last test using
-the fixture in the module has finished execution.
-
-Let's execute it::
-
- $ py.test -s -q --tb=no
- FFteardown smtp
-
- 2 failed in 0.12 seconds
-
-We see that the ``smtp`` instance is finalized after the two
-tests finished execution. Note that if we decorated our fixture
-function with ``scope='function'`` then fixture setup and cleanup would
-occur around each single test. In either case the test
-module itself does not need to change or know about these details
-of fixture setup.
-
-
-.. _`request-context`:
-
-Fixtures can introspect the requesting test context
--------------------------------------------------------------
-
-Fixture function can accept the :py:class:`request <FixtureRequest>` object
-to introspect the "requesting" test function, class or module context.
-Further extending the previous ``smtp`` fixture example, let's
-read an optional server URL from the test module which uses our fixture::
-
- # content of conftest.py
- import pytest
- import smtplib
-
- @pytest.fixture(scope="module")
- def smtp(request):
- server = getattr(request.module, "smtpserver", "smtp.gmail.com")
- smtp = smtplib.SMTP(server)
-
- def fin():
- print ("finalizing %s (%s)" % (smtp, server))
- smtp.close()
- request.addfinalizer(fin)
- return smtp
-
-We use the ``request.module`` attribute to optionally obtain an
-``smtpserver`` attribute from the test module. If we just execute
-again, nothing much has changed::
-
- $ py.test -s -q --tb=no
- FFfinalizing <smtplib.SMTP object at 0xdeadbeef> (smtp.gmail.com)
-
- 2 failed in 0.12 seconds
-
-Let's quickly create another test module that actually sets the
-server URL in its module namespace::
-
- # content of test_anothersmtp.py
-
- smtpserver = "mail.python.org" # will be read by smtp fixture
-
- def test_showhelo(smtp):
- assert 0, smtp.helo()
-
-Running it::
-
- $ py.test -qq --tb=short test_anothersmtp.py
- F
- ======= FAILURES ========
- _______ test_showhelo ________
- test_anothersmtp.py:5: in test_showhelo
- assert 0, smtp.helo()
- E AssertionError: (250, b'mail.python.org')
- E assert 0
-
-voila! The ``smtp`` fixture function picked up our mail server name
-from the module namespace.
-
-.. _`fixture-parametrize`:
-
-Parametrizing a fixture
------------------------------------------------------------------
-
-Fixture functions can be parametrized in which case they will be called
-multiple times, each time executing the set of dependent tests, i. e. the
-tests that depend on this fixture. Test functions do usually not need
-to be aware of their re-running. Fixture parametrization helps to
-write exhaustive functional tests for components which themselves can be
-configured in multiple ways.
-
-Extending the previous example, we can flag the fixture to create two
-``smtp`` fixture instances which will cause all tests using the fixture
-to run twice. The fixture function gets access to each parameter
-through the special :py:class:`request <FixtureRequest>` object::
-
- # content of conftest.py
- import pytest
- import smtplib
-
- @pytest.fixture(scope="module",
- params=["smtp.gmail.com", "mail.python.org"])
- def smtp(request):
- smtp = smtplib.SMTP(request.param)
- def fin():
- print ("finalizing %s" % smtp)
- smtp.close()
- request.addfinalizer(fin)
- return smtp
-
-The main change is the declaration of ``params`` with
-:py:func:`@pytest.fixture <_pytest.python.fixture>`, a list of values
-for each of which the fixture function will execute and can access
-a value via ``request.param``. No test function code needs to change.
-So let's just do another run::
-
- $ py.test -q test_module.py
- FFFF
- ======= FAILURES ========
- _______ test_ehlo[smtp.gmail.com] ________
-
- smtp = <smtplib.SMTP object at 0xdeadbeef>
-
- def test_ehlo(smtp):
- response, msg = smtp.ehlo()
- assert response == 250
- assert b"smtp.gmail.com" in msg
- > assert 0 # for demo purposes
- E assert 0
-
- test_module.py:6: AssertionError
- _______ test_noop[smtp.gmail.com] ________
-
- smtp = <smtplib.SMTP object at 0xdeadbeef>
-
- def test_noop(smtp):
- response, msg = smtp.noop()
- assert response == 250
- > assert 0 # for demo purposes
- E assert 0
-
- test_module.py:11: AssertionError
- _______ test_ehlo[mail.python.org] ________
-
- smtp = <smtplib.SMTP object at 0xdeadbeef>
-
- def test_ehlo(smtp):
- response, msg = smtp.ehlo()
- assert response == 250
- > assert b"smtp.gmail.com" in msg
- E assert b'smtp.gmail.com' in b'mail.python.org\nSIZE 51200000\nETRN\nSTARTTLS\nENHANCEDSTATUSCODES\n8BITMIME\nDSN\nSMTPUTF8'
-
- test_module.py:5: AssertionError
- -------------------------- Captured stdout setup ---------------------------
- finalizing <smtplib.SMTP object at 0xdeadbeef>
- _______ test_noop[mail.python.org] ________
-
- smtp = <smtplib.SMTP object at 0xdeadbeef>
-
- def test_noop(smtp):
- response, msg = smtp.noop()
- assert response == 250
- > assert 0 # for demo purposes
- E assert 0
-
- test_module.py:11: AssertionError
- 4 failed in 0.12 seconds
-
-We see that our two test functions each ran twice, against the different
-``smtp`` instances. Note also, that with the ``mail.python.org``
-connection the second test fails in ``test_ehlo`` because a
-different server string is expected than what arrived.
-
-pytest will build a string that is the test ID for each fixture value
-in a parametrized fixture, e.g. ``test_ehlo[smtp.gmail.com]`` and
-``test_ehlo[mail.python.org]`` in the above examples. These IDs can
-be used with ``-k`` to select specific cases to run, and they will
-also identify the specific case when one is failing. Running pytest
-with ``--collect-only`` will show the generated IDs.
-
-Numbers, strings, booleans and None will have their usual string
-representation used in the test ID. For other objects, pytest will
-make a string based on the argument name. It is possible to customise
-the string used in a test ID for a certain fixture value by using the
-``ids`` keyword argument::
-
- # content of test_ids.py
- import pytest
-
- @pytest.fixture(params=[0, 1], ids=["spam", "ham"])
- def a(request):
- return request.param
-
- def test_a(a):
- pass
-
- def idfn(fixture_value):
- if fixture_value == 0:
- return "eggs"
- else:
- return None
-
- @pytest.fixture(params=[0, 1], ids=idfn)
- def b(request):
- return request.param
-
- def test_b(b):
- pass
-
-The above shows how ``ids`` can be either a list of strings to use or
-a function which will be called with the fixture value and then
-has to return a string to use. In the latter case if the function
-return ``None`` then pytest's auto-generated ID will be used.
-
-Running the above tests results in the following test IDs being used::
-
- $ py.test --collect-only
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 10 items
- <Module 'test_anothersmtp.py'>
- <Function 'test_showhelo[smtp.gmail.com]'>
- <Function 'test_showhelo[mail.python.org]'>
- <Module 'test_ids.py'>
- <Function 'test_a[spam]'>
- <Function 'test_a[ham]'>
- <Function 'test_b[eggs]'>
- <Function 'test_b[1]'>
- <Module 'test_module.py'>
- <Function 'test_ehlo[smtp.gmail.com]'>
- <Function 'test_noop[smtp.gmail.com]'>
- <Function 'test_ehlo[mail.python.org]'>
- <Function 'test_noop[mail.python.org]'>
-
- ======= no tests ran in 0.12 seconds ========
-
-.. _`interdependent fixtures`:
-
-Modularity: using fixtures from a fixture function
-----------------------------------------------------------
-
-You can not only use fixtures in test functions but fixture functions
-can use other fixtures themselves. This contributes to a modular design
-of your fixtures and allows re-use of framework-specific fixtures across
-many projects. As a simple example, we can extend the previous example
-and instantiate an object ``app`` where we stick the already defined
-``smtp`` resource into it::
-
- # content of test_appsetup.py
-
- import pytest
-
- class App:
- def __init__(self, smtp):
- self.smtp = smtp
-
- @pytest.fixture(scope="module")
- def app(smtp):
- return App(smtp)
-
- def test_smtp_exists(app):
- assert app.smtp
-
-Here we declare an ``app`` fixture which receives the previously defined
-``smtp`` fixture and instantiates an ``App`` object with it. Let's run it::
-
- $ py.test -v test_appsetup.py
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.4
- cachedir: .cache
- rootdir: $REGENDOC_TMPDIR, inifile:
- collecting ... collected 2 items
-
- test_appsetup.py::test_smtp_exists[smtp.gmail.com] PASSED
- test_appsetup.py::test_smtp_exists[mail.python.org] PASSED
-
- ======= 2 passed in 0.12 seconds ========
-
-Due to the parametrization of ``smtp`` the test will run twice with two
-different ``App`` instances and respective smtp servers. There is no
-need for the ``app`` fixture to be aware of the ``smtp`` parametrization
-as pytest will fully analyse the fixture dependency graph.
-
-Note, that the ``app`` fixture has a scope of ``module`` and uses a
-module-scoped ``smtp`` fixture. The example would still work if ``smtp``
-was cached on a ``session`` scope: it is fine for fixtures to use
-"broader" scoped fixtures but not the other way round:
-A session-scoped fixture could not use a module-scoped one in a
-meaningful way.
-
-
-.. _`automatic per-resource grouping`:
-
-Automatic grouping of tests by fixture instances
-----------------------------------------------------------
-
-.. regendoc: wipe
-
-pytest minimizes the number of active fixtures during test runs.
-If you have a parametrized fixture, then all the tests using it will
-first execute with one instance and then finalizers are called
-before the next fixture instance is created. Among other things,
-this eases testing of applications which create and use global state.
-
-The following example uses two parametrized funcargs, one of which is
-scoped on a per-module basis, and all the functions perform ``print`` calls
-to show the setup/teardown flow::
-
- # content of test_module.py
- import pytest
-
- @pytest.fixture(scope="module", params=["mod1", "mod2"])
- def modarg(request):
- param = request.param
- print ("create", param)
- def fin():
- print ("fin %s" % param)
- return param
-
- @pytest.fixture(scope="function", params=[1,2])
- def otherarg(request):
- return request.param
-
- def test_0(otherarg):
- print (" test0", otherarg)
- def test_1(modarg):
- print (" test1", modarg)
- def test_2(otherarg, modarg):
- print (" test2", otherarg, modarg)
-
-Let's run the tests in verbose mode and with looking at the print-output::
-
- $ py.test -v -s test_module.py
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.4
- cachedir: .cache
- rootdir: $REGENDOC_TMPDIR, inifile:
- collecting ... collected 8 items
-
- test_module.py::test_0[1] test0 1
- PASSED
- test_module.py::test_0[2] test0 2
- PASSED
- test_module.py::test_1[mod1] create mod1
- test1 mod1
- PASSED
- test_module.py::test_2[1-mod1] test2 1 mod1
- PASSED
- test_module.py::test_2[2-mod1] test2 2 mod1
- PASSED
- test_module.py::test_1[mod2] create mod2
- test1 mod2
- PASSED
- test_module.py::test_2[1-mod2] test2 1 mod2
- PASSED
- test_module.py::test_2[2-mod2] test2 2 mod2
- PASSED
-
- ======= 8 passed in 0.12 seconds ========
-
-You can see that the parametrized module-scoped ``modarg`` resource caused
-an ordering of test execution that lead to the fewest possible "active" resources. The finalizer for the ``mod1`` parametrized resource was executed
-before the ``mod2`` resource was setup.
-
-
-.. _`usefixtures`:
-
-Using fixtures from classes, modules or projects
-----------------------------------------------------------------------
-
-.. regendoc:wipe
-
-Sometimes test functions do not directly need access to a fixture object.
-For example, tests may require to operate with an empty directory as the
-current working directory but otherwise do not care for the concrete
-directory. Here is how you can can use the standard `tempfile
-<http://docs.python.org/library/tempfile.html>`_ and pytest fixtures to
-achieve it. We separate the creation of the fixture into a conftest.py
-file::
-
- # content of conftest.py
-
- import pytest
- import tempfile
- import os
-
- @pytest.fixture()
- def cleandir():
- newpath = tempfile.mkdtemp()
- os.chdir(newpath)
-
-and declare its use in a test module via a ``usefixtures`` marker::
-
- # content of test_setenv.py
- import os
- import pytest
-
- @pytest.mark.usefixtures("cleandir")
- class TestDirectoryInit:
- def test_cwd_starts_empty(self):
- assert os.listdir(os.getcwd()) == []
- with open("myfile", "w") as f:
- f.write("hello")
-
- def test_cwd_again_starts_empty(self):
- assert os.listdir(os.getcwd()) == []
-
-Due to the ``usefixtures`` marker, the ``cleandir`` fixture
-will be required for the execution of each test method, just as if
-you specified a "cleandir" function argument to each of them. Let's run it
-to verify our fixture is activated and the tests pass::
-
- $ py.test -q
- ..
- 2 passed in 0.12 seconds
-
-You can specify multiple fixtures like this:
-
-.. code-block:: python
-
- @pytest.mark.usefixtures("cleandir", "anotherfixture")
-
-and you may specify fixture usage at the test module level, using
-a generic feature of the mark mechanism:
-
-.. code-block:: python
-
- pytestmark = pytest.mark.usefixtures("cleandir")
-
-Note that the assigned variable *must* be called ``pytestmark``, assigning e.g.
-``foomark`` will not activate the fixtures.
-
-Lastly you can put fixtures required by all tests in your project
-into an ini-file:
-
-.. code-block:: ini
-
- # content of pytest.ini
- [pytest]
- usefixtures = cleandir
-
-
-.. _`autouse`:
-.. _`autouse fixtures`:
-
-Autouse fixtures (xUnit setup on steroids)
-----------------------------------------------------------------------
-
-.. regendoc:wipe
-
-Occasionally, you may want to have fixtures get invoked automatically
-without a `usefixtures`_ or `funcargs`_ reference. As a practical
-example, suppose we have a database fixture which has a
-begin/rollback/commit architecture and we want to automatically surround
-each test method by a transaction and a rollback. Here is a dummy
-self-contained implementation of this idea::
-
- # content of test_db_transact.py
-
- import pytest
-
- class DB:
- def __init__(self):
- self.intransaction = []
- def begin(self, name):
- self.intransaction.append(name)
- def rollback(self):
- self.intransaction.pop()
-
- @pytest.fixture(scope="module")
- def db():
- return DB()
-
- class TestClass:
- @pytest.fixture(autouse=True)
- def transact(self, request, db):
- db.begin(request.function.__name__)
- request.addfinalizer(db.rollback)
-
- def test_method1(self, db):
- assert db.intransaction == ["test_method1"]
-
- def test_method2(self, db):
- assert db.intransaction == ["test_method2"]
-
-The class-level ``transact`` fixture is marked with *autouse=true*
-which implies that all test methods in the class will use this fixture
-without a need to state it in the test function signature or with a
-class-level ``usefixtures`` decorator.
-
-If we run it, we get two passing tests::
-
- $ py.test -q
- ..
- 2 passed in 0.12 seconds
-
-Here is how autouse fixtures work in other scopes:
-
-- if an autouse fixture is defined in a test module, all its test
- functions automatically use it.
-
-- if an autouse fixture is defined in a conftest.py file then all tests in
- all test modules below its directory will invoke the fixture.
-
-- lastly, and **please use that with care**: if you define an autouse
- fixture in a plugin, it will be invoked for all tests in all projects
- where the plugin is installed. This can be useful if a fixture only
- anyway works in the presence of certain settings e. g. in the ini-file. Such
- a global fixture should always quickly determine if it should do
- any work and avoid otherwise expensive imports or computation.
-
-Note that the above ``transact`` fixture may very well be a fixture that
-you want to make available in your project without having it generally
-active. The canonical way to do that is to put the transact definition
-into a conftest.py file **without** using ``autouse``::
-
- # content of conftest.py
- @pytest.fixture()
- def transact(self, request, db):
- db.begin()
- request.addfinalizer(db.rollback)
-
-and then e.g. have a TestClass using it by declaring the need::
-
- @pytest.mark.usefixtures("transact")
- class TestClass:
- def test_method1(self):
- ...
-
-All test methods in this TestClass will use the transaction fixture while
-other test classes or functions in the module will not use it unless
-they also add a ``transact`` reference.
-
-Shifting (visibility of) fixture functions
-----------------------------------------------------
-
-If during implementing your tests you realize that you
-want to use a fixture function from multiple test files you can move it
-to a :ref:`conftest.py <conftest.py>` file or even separately installable
-:ref:`plugins <plugins>` without changing test code. The discovery of
-fixtures functions starts at test classes, then test modules, then
-``conftest.py`` files and finally builtin and third party plugins.
-
-Overriding fixtures on various levels
--------------------------------------
-
-In relatively large test suite, you most likely need to ``override`` a ``global`` or ``root`` fixture with a ``locally``
-defined one, keeping the test code readable and maintainable.
-
-Override a fixture on a folder (conftest) level
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Given the tests file structure is:
-
-::
-
- tests/
- __init__.py
-
- conftest.py
- # content of tests/conftest.py
- import pytest
-
- @pytest.fixture
- def username():
- return 'username'
-
- test_something.py
- # content of tests/test_something.py
- def test_username(username):
- assert username == 'username'
-
- subfolder/
- __init__.py
-
- conftest.py
- # content of tests/subfolder/conftest.py
- import pytest
-
- @pytest.fixture
- def username(username):
- return 'overridden-' + username
-
- test_something.py
- # content of tests/subfolder/test_something.py
- def test_username(username):
- assert username == 'overridden-username'
-
-As you can see, a fixture with the same name can be overridden for certain test folder level.
-Note that the ``base`` or ``super`` fixture can be accessed from the ``overriding``
-fixture easily - used in the example above.
-
-Override a fixture on a test module level
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Given the tests file structure is:
-
-::
-
- tests/
- __init__.py
-
- conftest.py
- # content of tests/conftest.py
- @pytest.fixture
- def username():
- return 'username'
-
- test_something.py
- # content of tests/test_something.py
- import pytest
-
- @pytest.fixture
- def username(username):
- return 'overridden-' + username
-
- def test_username(username):
- assert username == 'overridden-username'
-
- test_something_else.py
- # content of tests/test_something_else.py
- import pytest
-
- @pytest.fixture
- def username(username):
- return 'overridden-else-' + username
-
- def test_username(username):
- assert username == 'overridden-else-username'
-
-In the example above, a fixture with the same name can be overridden for certain test module.
-
-
-Override a fixture with direct test parametrization
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Given the tests file structure is:
-
-::
-
- tests/
- __init__.py
-
- conftest.py
- # content of tests/conftest.py
- import pytest
-
- @pytest.fixture
- def username():
- return 'username'
-
- @pytest.fixture
- def other_username(username):
- return 'other-' + username
-
- test_something.py
- # content of tests/test_something.py
- import pytest
-
- @pytest.mark.parametrize('username', ['directly-overridden-username'])
- def test_username(username):
- assert username == 'directly-overridden-username'
-
- @pytest.mark.parametrize('username', ['directly-overridden-username-other'])
- def test_username_other(other_username):
- assert username == 'other-directly-overridden-username-other'
-
-In the example above, a fixture value is overridden by the test parameter value. Note that the value of the fixture
-can be overridden this way even if the test doesn't use it directly (doesn't mention it in the function prototype).
-
-
-Override a parametrized fixture with non-parametrized one and vice versa
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Given the tests file structure is:
-
-::
-
- tests/
- __init__.py
-
- conftest.py
- # content of tests/conftest.py
- import pytest
-
- @pytest.fixture(params=['one', 'two', 'three'])
- def parametrized_username(request):
- return request.param
-
- @pytest.fixture
- def non_parametrized_username(request):
- return 'username'
-
- test_something.py
- # content of tests/test_something.py
- import pytest
-
- @pytest.fixture
- def parametrized_username():
- return 'overridden-username'
-
- @pytest.fixture(params=['one', 'two', 'three'])
- def non_parametrized_username(request):
- return request.param
-
- def test_username(parametrized_username):
- assert parametrized_username == 'overridden-username'
-
- def test_parametrized_username(non_parametrized_username):
- assert non_parametrized_username in ['one', 'two', 'three']
-
- test_something_else.py
- # content of tests/test_something_else.py
- def test_username(parametrized_username):
- assert parametrized_username in ['one', 'two', 'three']
-
- def test_username(non_parametrized_username):
- assert non_parametrized_username == 'username'
-
-In the example above, a parametrized fixture is overridden with a non-parametrized version, and
-a non-parametrized fixture is overridden with a parametrized version for certain test module.
-The same applies for the test folder level obviously.
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/funcarg_compare.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/funcarg_compare.rst
deleted file mode 100644
index 832922e1839..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/funcarg_compare.rst
+++ /dev/null
@@ -1,217 +0,0 @@
-
-.. _`funcargcompare`:
-
-pytest-2.3: reasoning for fixture/funcarg evolution
-=============================================================
-
-**Target audience**: Reading this document requires basic knowledge of
-python testing, xUnit setup methods and the (previous) basic pytest
-funcarg mechanism, see http://pytest.org/2.2.4/funcargs.html
-If you are new to pytest, then you can simply ignore this
-section and read the other sections.
-
-.. currentmodule:: _pytest
-
-Shortcomings of the previous ``pytest_funcarg__`` mechanism
---------------------------------------------------------------
-
-The pre pytest-2.3 funcarg mechanism calls a factory each time a
-funcarg for a test function is required. If a factory wants to
-re-use a resource across different scopes, it often used
-the ``request.cached_setup()`` helper to manage caching of
-resources. Here is a basic example how we could implement
-a per-session Database object::
-
- # content of conftest.py
- class Database:
- def __init__(self):
- print ("database instance created")
- def destroy(self):
- print ("database instance destroyed")
-
- def pytest_funcarg__db(request):
- return request.cached_setup(setup=DataBase,
- teardown=lambda db: db.destroy,
- scope="session")
-
-There are several limitations and difficulties with this approach:
-
-1. Scoping funcarg resource creation is not straight forward, instead one must
- understand the intricate cached_setup() method mechanics.
-
-2. parametrizing the "db" resource is not straight forward:
- you need to apply a "parametrize" decorator or implement a
- :py:func:`~hookspec.pytest_generate_tests` hook
- calling :py:func:`~python.Metafunc.parametrize` which
- performs parametrization at the places where the resource
- is used. Moreover, you need to modify the factory to use an
- ``extrakey`` parameter containing ``request.param`` to the
- :py:func:`~python.Request.cached_setup` call.
-
-3. Multiple parametrized session-scoped resources will be active
- at the same time, making it hard for them to affect global state
- of the application under test.
-
-4. there is no way how you can make use of funcarg factories
- in xUnit setup methods.
-
-5. A non-parametrized fixture function cannot use a parametrized
- funcarg resource if it isn't stated in the test function signature.
-
-All of these limitations are addressed with pytest-2.3 and its
-improved :ref:`fixture mechanism <fixture>`.
-
-
-Direct scoping of fixture/funcarg factories
---------------------------------------------------------
-
-Instead of calling cached_setup() with a cache scope, you can use the
-:ref:`@pytest.fixture <pytest.fixture>` decorator and directly state
-the scope::
-
- @pytest.fixture(scope="session")
- def db(request):
- # factory will only be invoked once per session -
- db = DataBase()
- request.addfinalizer(db.destroy) # destroy when session is finished
- return db
-
-This factory implementation does not need to call ``cached_setup()`` anymore
-because it will only be invoked once per session. Moreover, the
-``request.addfinalizer()`` registers a finalizer according to the specified
-resource scope on which the factory function is operating.
-
-
-Direct parametrization of funcarg resource factories
-----------------------------------------------------------
-
-Previously, funcarg factories could not directly cause parametrization.
-You needed to specify a ``@parametrize`` decorator on your test function
-or implement a ``pytest_generate_tests`` hook to perform
-parametrization, i.e. calling a test multiple times with different value
-sets. pytest-2.3 introduces a decorator for use on the factory itself::
-
- @pytest.fixture(params=["mysql", "pg"])
- def db(request):
- ... # use request.param
-
-Here the factory will be invoked twice (with the respective "mysql"
-and "pg" values set as ``request.param`` attributes) and and all of
-the tests requiring "db" will run twice as well. The "mysql" and
-"pg" values will also be used for reporting the test-invocation variants.
-
-This new way of parametrizing funcarg factories should in many cases
-allow to re-use already written factories because effectively
-``request.param`` was already used when test functions/classes were
-parametrized via
-:py:func:`~_pytest.python.Metafunc.parametrize(indirect=True)` calls.
-
-Of course it's perfectly fine to combine parametrization and scoping::
-
- @pytest.fixture(scope="session", params=["mysql", "pg"])
- def db(request):
- if request.param == "mysql":
- db = MySQL()
- elif request.param == "pg":
- db = PG()
- request.addfinalizer(db.destroy) # destroy when session is finished
- return db
-
-This would execute all tests requiring the per-session "db" resource twice,
-receiving the values created by the two respective invocations to the
-factory function.
-
-
-No ``pytest_funcarg__`` prefix when using @fixture decorator
--------------------------------------------------------------------
-
-When using the ``@fixture`` decorator the name of the function
-denotes the name under which the resource can be accessed as a function
-argument::
-
- @pytest.fixture()
- def db(request):
- ...
-
-The name under which the funcarg resource can be requested is ``db``.
-
-You can still use the "old" non-decorator way of specifying funcarg factories
-aka::
-
- def pytest_funcarg__db(request):
- ...
-
-
-But it is then not possible to define scoping and parametrization.
-It is thus recommended to use the factory decorator.
-
-
-solving per-session setup / autouse fixtures
---------------------------------------------------------------
-
-pytest for a long time offered a pytest_configure and a pytest_sessionstart
-hook which are often used to setup global resources. This suffers from
-several problems:
-
-1. in distributed testing the master process would setup test resources
- that are never needed because it only co-ordinates the test run
- activities of the slave processes.
-
-2. if you only perform a collection (with "--collect-only")
- resource-setup will still be executed.
-
-3. If a pytest_sessionstart is contained in some subdirectories
- conftest.py file, it will not be called. This stems from the
- fact that this hook is actually used for reporting, in particular
- the test-header with platform/custom information.
-
-Moreover, it was not easy to define a scoped setup from plugins or
-conftest files other than to implement a ``pytest_runtest_setup()`` hook
-and caring for scoping/caching yourself. And it's virtually impossible
-to do this with parametrization as ``pytest_runtest_setup()`` is called
-during test execution and parametrization happens at collection time.
-
-It follows that pytest_configure/session/runtest_setup are often not
-appropriate for implementing common fixture needs. Therefore,
-pytest-2.3 introduces :ref:`autouse fixtures` which fully
-integrate with the generic :ref:`fixture mechanism <fixture>`
-and obsolete many prior uses of pytest hooks.
-
-funcargs/fixture discovery now happens at collection time
----------------------------------------------------------------------
-
-pytest-2.3 takes care to discover fixture/funcarg factories
-at collection time. This is more efficient especially for large test suites.
-Moreover, a call to "py.test --collect-only" should be able to in the future
-show a lot of setup-information and thus presents a nice method to get an
-overview of fixture management in your project.
-
-.. _`compatibility notes`:
-
-.. _`funcargscompat`:
-
-Conclusion and compatibility notes
----------------------------------------------------------
-
-**funcargs** were originally introduced to pytest-2.0. In pytest-2.3
-the mechanism was extended and refined and is now described as
-fixtures:
-
-* previously funcarg factories were specified with a special
- ``pytest_funcarg__NAME`` prefix instead of using the
- ``@pytest.fixture`` decorator.
-
-* Factories received a ``request`` object which managed caching through
- ``request.cached_setup()`` calls and allowed using other funcargs via
- ``request.getfuncargvalue()`` calls. These intricate APIs made it hard
- to do proper parametrization and implement resource caching. The
- new :py:func:`pytest.fixture` decorator allows to declare the scope
- and let pytest figure things out for you.
-
-* if you used parametrization and funcarg factories which made use of
- ``request.cached_setup()`` it is recommended to invest a few minutes
- and simplify your fixture function code to use the :ref:`@pytest.fixture`
- decorator instead. This will also allow to take advantage of
- the automatic per-resource grouping of tests.
-
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/genapi.py b/tests/wpt/web-platform-tests/tools/pytest/doc/en/genapi.py
deleted file mode 100644
index f8cdda6cfbf..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/genapi.py
+++ /dev/null
@@ -1,41 +0,0 @@
-import textwrap
-import inspect
-
-class Writer:
- def __init__(self, clsname):
- self.clsname = clsname
-
- def __enter__(self):
- self.file = open("%s.api" % self.clsname, "w")
- return self
-
- def __exit__(self, *args):
- self.file.close()
- print "wrote", self.file.name
-
- def line(self, line):
- self.file.write(line+"\n")
-
- def docmethod(self, method):
- doc = " ".join(method.__doc__.split())
- indent = " "
- w = textwrap.TextWrapper(initial_indent=indent,
- subsequent_indent=indent)
-
- spec = inspect.getargspec(method)
- del spec.args[0]
- self.line(".. py:method:: " + method.__name__ +
- inspect.formatargspec(*spec))
- self.line("")
- self.line(w.fill(doc))
- self.line("")
-
-def pytest_funcarg__a(request):
- with Writer("request") as writer:
- writer.docmethod(request.getfuncargvalue)
- writer.docmethod(request.cached_setup)
- writer.docmethod(request.addfinalizer)
- writer.docmethod(request.applymarker)
-
-def test_hello(a):
- pass
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/getting-started.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/getting-started.rst
deleted file mode 100644
index 4a5b75aea0c..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/getting-started.rst
+++ /dev/null
@@ -1,237 +0,0 @@
-Installation and Getting Started
-===================================
-
-**Pythons**: Python 2.6,2.7,3.3,3.4,3.5, Jython, PyPy-2.3
-
-**Platforms**: Unix/Posix and Windows
-
-**PyPI package name**: `pytest <http://pypi.python.org/pypi/pytest>`_
-
-**dependencies**: `py <http://pypi.python.org/pypi/py>`_,
-`colorama (Windows) <http://pypi.python.org/pypi/colorama>`_,
-`argparse (py26) <http://pypi.python.org/pypi/argparse>`_.
-
-**documentation as PDF**: `download latest <http://pytest.org/latest/pytest.pdf>`_
-
-.. _`getstarted`:
-.. _installation:
-
-Installation
-----------------------------------------
-
-Installation options::
-
- pip install -U pytest # or
- easy_install -U pytest
-
-To check your installation has installed the correct version::
-
- $ py.test --version
- This is pytest version 2.9.1, imported from $PYTHON_PREFIX/lib/python3.4/site-packages/pytest.py
-
-If you get an error checkout :ref:`installation issues`.
-
-.. _`simpletest`:
-
-Our first test run
-----------------------------------------------------------
-
-Let's create a first test file with a simple test function::
-
- # content of test_sample.py
- def func(x):
- return x + 1
-
- def test_answer():
- assert func(3) == 5
-
-That's it. You can execute the test function now::
-
- $ py.test
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 1 items
-
- test_sample.py F
-
- ======= FAILURES ========
- _______ test_answer ________
-
- def test_answer():
- > assert func(3) == 5
- E assert 4 == 5
- E + where 4 = func(3)
-
- test_sample.py:5: AssertionError
- ======= 1 failed in 0.12 seconds ========
-
-We got a failure report because our little ``func(3)`` call did not return ``5``.
-
-.. note::
-
- You can simply use the ``assert`` statement for asserting test
- expectations. pytest's :ref:`assert introspection` will intelligently
- report intermediate values of the assert expression freeing
- you from the need to learn the many names of `JUnit legacy methods`_.
-
-.. _`JUnit legacy methods`: http://docs.python.org/library/unittest.html#test-cases
-
-.. _`assert statement`: http://docs.python.org/reference/simple_stmts.html#the-assert-statement
-
-Running multiple tests
-----------------------------------------------------------
-
-``pytest`` will run all files in the current directory and its subdirectories of the form test_*.py or \*_test.py. More generally, it follows :ref:`standard test discovery rules <test discovery>`.
-
-
-Asserting that a certain exception is raised
---------------------------------------------------------------
-
-If you want to assert that some code raises an exception you can
-use the ``raises`` helper::
-
- # content of test_sysexit.py
- import pytest
- def f():
- raise SystemExit(1)
-
- def test_mytest():
- with pytest.raises(SystemExit):
- f()
-
-Running it with, this time in "quiet" reporting mode::
-
- $ py.test -q test_sysexit.py
- .
- 1 passed in 0.12 seconds
-
-Grouping multiple tests in a class
---------------------------------------------------------------
-
-Once you start to have more than a few tests it often makes sense
-to group tests logically, in classes and modules. Let's write a class
-containing two tests::
-
- # content of test_class.py
- class TestClass:
- def test_one(self):
- x = "this"
- assert 'h' in x
-
- def test_two(self):
- x = "hello"
- assert hasattr(x, 'check')
-
-The two tests are found because of the standard :ref:`test discovery`.
-There is no need to subclass anything. We can simply
-run the module by passing its filename::
-
- $ py.test -q test_class.py
- .F
- ======= FAILURES ========
- _______ TestClass.test_two ________
-
- self = <test_class.TestClass object at 0xdeadbeef>
-
- def test_two(self):
- x = "hello"
- > assert hasattr(x, 'check')
- E assert hasattr('hello', 'check')
-
- test_class.py:8: AssertionError
- 1 failed, 1 passed in 0.12 seconds
-
-The first test passed, the second failed. Again we can easily see
-the intermediate values used in the assertion, helping us to
-understand the reason for the failure.
-
-Going functional: requesting a unique temporary directory
---------------------------------------------------------------
-
-For functional tests one often needs to create some files
-and pass them to application objects. pytest provides
-:ref:`builtinfixtures` which allow to request arbitrary
-resources, for example a unique temporary directory::
-
- # content of test_tmpdir.py
- def test_needsfiles(tmpdir):
- print (tmpdir)
- assert 0
-
-We list the name ``tmpdir`` in the test function signature and
-``pytest`` will lookup and call a fixture factory to create the resource
-before performing the test function call. Let's just run it::
-
- $ py.test -q test_tmpdir.py
- F
- ======= FAILURES ========
- _______ test_needsfiles ________
-
- tmpdir = local('PYTEST_TMPDIR/test_needsfiles0')
-
- def test_needsfiles(tmpdir):
- print (tmpdir)
- > assert 0
- E assert 0
-
- test_tmpdir.py:3: AssertionError
- --------------------------- Captured stdout call ---------------------------
- PYTEST_TMPDIR/test_needsfiles0
- 1 failed in 0.12 seconds
-
-Before the test runs, a unique-per-test-invocation temporary directory
-was created. More info at :ref:`tmpdir handling`.
-
-You can find out what kind of builtin :ref:`fixtures` exist by typing::
-
- py.test --fixtures # shows builtin and custom fixtures
-
-Where to go next
--------------------------------------
-
-Here are a few suggestions where to go next:
-
-* :ref:`cmdline` for command line invocation examples
-* :ref:`good practices <goodpractices>` for virtualenv, test layout, genscript support
-* :ref:`fixtures` for providing a functional baseline to your tests
-* :ref:`apiref` for documentation and examples on using ``pytest``
-* :ref:`plugins` managing and writing plugins
-
-.. _`installation issues`:
-
-Known Installation issues
-------------------------------
-
-easy_install or pip not found?
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-.. _`install pip`: http://www.pip-installer.org/en/latest/index.html
-
-`Install pip`_ for a state of the art python package installer.
-
-Install `setuptools`_ to get ``easy_install`` which allows to install
-``.egg`` binary format packages in addition to source-based ones.
-
-py.test not found on Windows despite installation?
-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-.. _`Python for Windows`: http://www.imladris.com/Scripts/PythonForWindows.html
-
-- **Windows**: If "easy_install" or "py.test" are not found
- you need to add the Python script path to your ``PATH``, see here:
- `Python for Windows`_. You may alternatively use an `ActivePython install`_
- which does this for you automatically.
-
-.. _`ActivePython install`: http://www.activestate.com/activepython/downloads
-
-.. _`Jython does not create command line launchers`: http://bugs.jython.org/issue1491
-
-- **Jython2.5.1 on Windows XP**: `Jython does not create command line launchers`_
- so ``py.test`` will not work correctly. You may install py.test on
- CPython and type ``py.test --genscript=mytest`` and then use
- ``jython mytest`` to run your tests with Jython using ``pytest``.
-
- :ref:`examples` for more complex examples
-
-.. include:: links.inc
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/goodpractices.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/goodpractices.rst
deleted file mode 100644
index 2d8050bd9ca..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/goodpractices.rst
+++ /dev/null
@@ -1,278 +0,0 @@
-.. highlightlang:: python
-.. _`goodpractices`:
-
-Good Integration Practices
-=================================================
-
-
-.. _`test discovery`:
-.. _`Python test discovery`:
-
-Conventions for Python test discovery
--------------------------------------------------
-
-``pytest`` implements the following standard test discovery:
-
-* If no arguments are specified then collection starts from :confval:`testpaths`
- (if configured) or the current directory. Alternatively, command line arguments
- can be used in any combination of directories, file names or node ids.
-* recurse into directories, unless they match :confval:`norecursedirs`
-* ``test_*.py`` or ``*_test.py`` files, imported by their `test package name`_.
-* ``Test`` prefixed test classes (without an ``__init__`` method)
-* ``test_`` prefixed test functions or methods are test items
-
-For examples of how to customize your test discovery :doc:`example/pythoncollection`.
-
-Within Python modules, ``pytest`` also discovers tests using the standard
-:ref:`unittest.TestCase <unittest.TestCase>` subclassing technique.
-
-
-Choosing a test layout / import rules
-------------------------------------------
-
-``pytest`` supports two common test layouts:
-
-* putting tests into an extra directory outside your actual application
- code, useful if you have many functional tests or for other reasons
- want to keep tests separate from actual application code (often a good
- idea)::
-
- setup.py # your setuptools Python package metadata
- mypkg/
- __init__.py
- appmodule.py
- tests/
- test_app.py
- ...
-
-
-* inlining test directories into your application package, useful if you
- have direct relation between (unit-)test and application modules and
- want to distribute your tests along with your application::
-
- setup.py # your setuptools Python package metadata
- mypkg/
- __init__.py
- appmodule.py
- ...
- test/
- test_app.py
- ...
-
-Important notes relating to both schemes:
-
-- **make sure that "mypkg" is importable**, for example by typing once::
-
- pip install -e . # install package using setup.py in editable mode
-
-- **avoid "__init__.py" files in your test directories**.
- This way your tests can run easily against an installed version
- of ``mypkg``, independently from the installed package if it contains
- the tests or not.
-
-- With inlined tests you might put ``__init__.py`` into test
- directories and make them installable as part of your application.
- Using the ``py.test --pyargs mypkg`` invocation pytest will
- discover where mypkg is installed and collect tests from there.
- With the "external" test you can still distribute tests but they
- will not be installed or become importable.
-
-Typically you can run tests by pointing to test directories or modules::
-
- py.test tests/test_app.py # for external test dirs
- py.test mypkg/test/test_app.py # for inlined test dirs
- py.test mypkg # run tests in all below test directories
- py.test # run all tests below current dir
- ...
-
-Because of the above ``editable install`` mode you can change your
-source code (both tests and the app) and rerun tests at will.
-Once you are done with your work, you can `use tox`_ to make sure
-that the package is really correct and tests pass in all
-required configurations.
-
-.. note::
-
- You can use Python3 namespace packages (PEP420) for your application
- but pytest will still perform `test package name`_ discovery based on the
- presence of ``__init__.py`` files. If you use one of the
- two recommended file system layouts above but leave away the ``__init__.py``
- files from your directories it should just work on Python3.3 and above. From
- "inlined tests", however, you will need to use absolute imports for
- getting at your application code.
-
-.. _`test package name`:
-
-.. note::
-
- If ``pytest`` finds a "a/b/test_module.py" test file while
- recursing into the filesystem it determines the import name
- as follows:
-
- * determine ``basedir``: this is the first "upward" (towards the root)
- directory not containing an ``__init__.py``. If e.g. both ``a``
- and ``b`` contain an ``__init__.py`` file then the parent directory
- of ``a`` will become the ``basedir``.
-
- * perform ``sys.path.insert(0, basedir)`` to make the test module
- importable under the fully qualified import name.
-
- * ``import a.b.test_module`` where the path is determined
- by converting path separators ``/`` into "." characters. This means
- you must follow the convention of having directory and file
- names map directly to the import names.
-
- The reason for this somewhat evolved importing technique is
- that in larger projects multiple test modules might import
- from each other and thus deriving a canonical import name helps
- to avoid surprises such as a test modules getting imported twice.
-
-
-.. _`virtualenv`: http://pypi.python.org/pypi/virtualenv
-.. _`buildout`: http://www.buildout.org/
-.. _pip: http://pypi.python.org/pypi/pip
-
-.. _`use tox`:
-
-Tox
-------
-
-For development, we recommend to use virtualenv_ environments and pip_
-for installing your application and any dependencies
-as well as the ``pytest`` package itself. This ensures your code and
-dependencies are isolated from the system Python installation.
-
-If you frequently release code and want to make sure that your actual
-package passes all tests you may want to look into `tox`_, the
-virtualenv test automation tool and its `pytest support
-<http://testrun.org/tox/latest/example/pytest.html>`_.
-Tox helps you to setup virtualenv environments with pre-defined
-dependencies and then executing a pre-configured test command with
-options. It will run tests against the installed package and not
-against your source code checkout, helping to detect packaging
-glitches.
-
-Continuous integration services such as Jenkins_ can make use of the
-``--junitxml=PATH`` option to create a JUnitXML file and generate reports.
-
-
-Integrating with setuptools / ``python setup.py test`` / ``pytest-runner``
---------------------------------------------------------------------------
-
-You can integrate test runs into your setuptools based project
-with the `pytest-runner <https://pypi.python.org/pypi/pytest-runner>`_ plugin.
-
-Add this to ``setup.py`` file:
-
-.. code-block:: python
-
- from setuptools import setup
-
- setup(
- #...,
- setup_requires=['pytest-runner', ...],
- tests_require=['pytest', ...],
- #...,
- )
-
-
-And create an alias into ``setup.cfg`` file:
-
-
-.. code-block:: ini
-
- [aliases]
- test=pytest
-
-If you now type::
-
- python setup.py test
-
-this will execute your tests using ``pytest-runner``. As this is a
-standalone version of ``pytest`` no prior installation whatsoever is
-required for calling the test command. You can also pass additional
-arguments to py.test such as your test directory or other
-options using ``--addopts``.
-
-
-Manual Integration
-^^^^^^^^^^^^^^^^^^
-
-If for some reason you don't want/can't use ``pytest-runner``, you can write
-your own setuptools Test command for invoking pytest.
-
-.. code-block:: python
-
- import sys
-
- from setuptools.command.test import test as TestCommand
-
-
- class PyTest(TestCommand):
- user_options = [('pytest-args=', 'a', "Arguments to pass to py.test")]
-
- def initialize_options(self):
- TestCommand.initialize_options(self)
- self.pytest_args = []
-
- def run_tests(self):
- #import here, cause outside the eggs aren't loaded
- import pytest
- errno = pytest.main(self.pytest_args)
- sys.exit(errno)
-
-
- setup(
- #...,
- tests_require=['pytest'],
- cmdclass = {'test': PyTest},
- )
-
-Now if you run::
-
- python setup.py test
-
-this will download ``pytest`` if needed and then run your tests
-as you would expect it to. You can pass a single string of arguments
-using the ``--pytest-args`` or ``-a`` command-line option. For example::
-
- python setup.py test -a "--durations=5"
-
-is equivalent to running ``py.test --durations=5``.
-
-
-.. _standalone:
-.. _`genscript method`:
-
-(deprecated) Create a pytest standalone script
------------------------------------------------
-
-.. deprecated:: 2.8
-
-.. note::
-
- ``genscript`` has been deprecated because:
-
- * It cannot support plugins, rendering its usefulness extremely limited;
- * Tooling has become much better since ``genscript`` was introduced;
- * It is possible to build a zipped ``pytest`` application without the
- shortcomings above.
-
- There's no planned version in which this command will be removed
- at the moment of this writing, but its use is discouraged for new
- applications.
-
-If you are a maintainer or application developer and want people
-who don't deal with python much to easily run tests you may generate
-a standalone ``pytest`` script::
-
- py.test --genscript=runtests.py
-
-This generates a ``runtests.py`` script which is a fully functional basic
-``pytest`` script, running unchanged under Python2 and Python3.
-You can tell people to download the script and then e.g. run it like this::
-
- python runtests.py
-
-
-.. include:: links.inc
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/index.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/index.rst
deleted file mode 100644
index 04b4512da30..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/index.rst
+++ /dev/null
@@ -1,61 +0,0 @@
-
-.. _features:
-
-pytest: helps you write better programs
-=============================================
-
-**a mature full-featured Python testing tool**
-
- - runs on Posix/Windows, Python 2.6-3.5, PyPy and (possibly still) Jython-2.5.1
- - free and open source software, distributed under the terms of the :ref:`MIT license <license>`
- - **well tested** with more than a thousand tests against itself
- - **strict backward compatibility policy** for safe pytest upgrades
- - :ref:`comprehensive online <toc>` and `PDF documentation <pytest.pdf>`_
- - many :ref:`third party plugins <extplugins>` and :ref:`builtin helpers <pytest helpers>`,
- - used in :ref:`many small and large projects and organisations <projects>`
- - comes with many :ref:`tested examples <examples>`
-
-**provides easy no-boilerplate testing**
-
- - makes it :ref:`easy to get started <getstarted>`,
- has many :ref:`usage options <usage>`
- - :ref:`assert with the assert statement`
- - helpful :ref:`traceback and failing assertion reporting <tbreportdemo>`
- - :ref:`print debugging <printdebugging>` and :ref:`the
- capturing of standard output during test execution <captures>`
-
-**scales from simple unit to complex functional testing**
-
- - :ref:`modular parametrizeable fixtures <fixture>` (new in 2.3,
- continuously improved)
- - :ref:`parametrized test functions <parametrized test functions>`
- - :ref:`mark`
- - :ref:`skipping` (improved in 2.4)
- - :ref:`distribute tests to multiple CPUs <xdistcpu>` through :ref:`xdist plugin <xdist>`
- - :ref:`continuously re-run failing tests <looponfailing>`
- - :doc:`cache`
- - flexible :ref:`Python test discovery`
-
-**integrates with other testing methods and tools**:
-
- - multi-paradigm: pytest can run ``nose``, ``unittest`` and
- ``doctest`` style test suites, including running testcases made for
- Django and trial
- - supports :ref:`good integration practices <goodpractices>`
- - supports extended :ref:`xUnit style setup <xunitsetup>`
- - supports domain-specific :ref:`non-python tests`
- - supports generating `test coverage reports
- <https://pypi.python.org/pypi/pytest-cov>`_
- - supports :pep:`8` compliant coding styles in tests
-
-**extensive plugin and customization system**:
-
- - all collection, reporting, running aspects are delegated to hook functions
- - customizations can be per-directory, per-project or per PyPI released plugin
- - it is easy to add command line options or customize existing behaviour
- - :ref:`easy to write your own plugins <writing-plugins>`
-
-
-.. _`easy`: http://bruynooghe.blogspot.com/2009/12/skipping-slow-test-by-default-in-pytest.html
-
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/license.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/license.rst
deleted file mode 100644
index 3fc1dad52fd..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/license.rst
+++ /dev/null
@@ -1,32 +0,0 @@
-.. _license:
-
-License
--------
-
-Distributed under the terms of the `MIT`_ license, pytest is free and open source software.
-
-::
-
- The MIT License (MIT)
-
- Copyright (c) 2004-2016 Holger Krekel and others
-
- Permission is hereby granted, free of charge, to any person obtaining a copy of
- this software and associated documentation files (the "Software"), to deal in
- the Software without restriction, including without limitation the rights to
- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- of the Software, and to permit persons to whom the Software is furnished to do
- so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
-
-.. _`MIT`: https://github.com/pytest-dev/pytest/blob/master/LICENSE
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/links.inc b/tests/wpt/web-platform-tests/tools/pytest/doc/en/links.inc
deleted file mode 100644
index 3d7863751e2..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/links.inc
+++ /dev/null
@@ -1,21 +0,0 @@
-
-.. _`skipping plugin`: plugin/skipping.html
-.. _`funcargs mechanism`: funcargs.html
-.. _`doctest.py`: http://docs.python.org/library/doctest.html
-.. _`xUnit style setup`: xunit_setup.html
-.. _`pytest_nose`: plugin/nose.html
-.. _`reStructured Text`: http://docutils.sourceforge.net
-.. _`Python debugger`: http://docs.python.org/lib/module-pdb.html
-.. _nose: https://nose.readthedocs.org/en/latest/
-.. _pytest: http://pypi.python.org/pypi/pytest
-.. _mercurial: http://mercurial.selenic.com/wiki/
-.. _`setuptools`: http://pypi.python.org/pypi/setuptools
-.. _`easy_install`:
-.. _`distribute docs`:
-.. _`distribute`: http://pypi.python.org/pypi/distribute
-.. _`pip`: http://pypi.python.org/pypi/pip
-.. _`virtualenv`: http://pypi.python.org/pypi/virtualenv
-.. _hudson: http://hudson-ci.org/
-.. _jenkins: http://jenkins-ci.org/
-.. _tox: http://testrun.org/tox
-.. _pylib: http://py.readthedocs.org/en/latest/
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/mark.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/mark.rst
deleted file mode 100644
index ab9546d317c..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/mark.rst
+++ /dev/null
@@ -1,40 +0,0 @@
-
-.. _mark:
-
-Marking test functions with attributes
-=================================================================
-
-.. currentmodule:: _pytest.mark
-
-By using the ``pytest.mark`` helper you can easily set
-metadata on your test functions. There are
-some builtin markers, for example:
-
-* :ref:`skipif <skipif>` - skip a test function if a certain condition is met
-* :ref:`xfail <xfail>` - produce an "expected failure" outcome if a certain
- condition is met
-* :ref:`parametrize <parametrizemark>` to perform multiple calls
- to the same test function.
-
-It's easy to create custom markers or to apply markers
-to whole test classes or modules. See :ref:`mark examples` for examples
-which also serve as documentation.
-
-.. note::
-
- Marks can only be applied to tests, having no effect on
- :ref:`fixtures <fixtures>`.
-
-
-API reference for mark related objects
-------------------------------------------------
-
-.. autoclass:: MarkGenerator
- :members:
-
-.. autoclass:: MarkDecorator
- :members:
-
-.. autoclass:: MarkInfo
- :members:
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/monkeypatch.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/monkeypatch.rst
deleted file mode 100644
index 4155a3a345b..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/monkeypatch.rst
+++ /dev/null
@@ -1,82 +0,0 @@
-
-Monkeypatching/mocking modules and environments
-================================================================
-
-.. currentmodule:: _pytest.monkeypatch
-
-Sometimes tests need to invoke functionality which depends
-on global settings or which invokes code which cannot be easily
-tested such as network access. The ``monkeypatch`` function argument
-helps you to safely set/delete an attribute, dictionary item or
-environment variable or to modify ``sys.path`` for importing.
-See the `monkeypatch blog post`_ for some introduction material
-and a discussion of its motivation.
-
-.. _`monkeypatch blog post`: http://tetamap.wordpress.com/2009/03/03/monkeypatching-in-unit-tests-done-right/
-
-Simple example: monkeypatching functions
----------------------------------------------------
-
-If you want to pretend that ``os.expanduser`` returns a certain
-directory, you can use the :py:meth:`monkeypatch.setattr` method to
-patch this function before calling into a function which uses it::
-
- # content of test_module.py
- import os.path
- def getssh(): # pseudo application code
- return os.path.join(os.path.expanduser("~admin"), '.ssh')
-
- def test_mytest(monkeypatch):
- def mockreturn(path):
- return '/abc'
- monkeypatch.setattr(os.path, 'expanduser', mockreturn)
- x = getssh()
- assert x == '/abc/.ssh'
-
-Here our test function monkeypatches ``os.path.expanduser`` and
-then calls into an function that calls it. After the test function
-finishes the ``os.path.expanduser`` modification will be undone.
-
-example: preventing "requests" from remote operations
-------------------------------------------------------
-
-If you want to prevent the "requests" library from performing http
-requests in all your tests, you can do::
-
- # content of conftest.py
- import pytest
- @pytest.fixture(autouse=True)
- def no_requests(monkeypatch):
- monkeypatch.delattr("requests.sessions.Session.request")
-
-This autouse fixture will be executed for each test function and it
-will delete the method ``request.session.Session.request``
-so that any attempts within tests to create http requests will fail.
-
-example: setting an attribute on some class
-------------------------------------------------------
-
-If you need to patch out ``os.getcwd()`` to return an artificial
-value::
-
- def test_some_interaction(monkeypatch):
- monkeypatch.setattr("os.getcwd", lambda: "/")
-
-which is equivalent to the long form::
-
- def test_some_interaction(monkeypatch):
- import os
- monkeypatch.setattr(os, "getcwd", lambda: "/")
-
-
-
-Method reference of the monkeypatch function argument
------------------------------------------------------
-
-.. autoclass:: monkeypatch
- :members: setattr, replace, delattr, setitem, delitem, setenv, delenv, syspath_prepend, chdir, undo
-
-``monkeypatch.setattr/delattr/delitem/delenv()`` all
-by default raise an Exception if the target does not exist.
-Pass ``raising=False`` if you want to skip this check.
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/nose.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/nose.rst
deleted file mode 100644
index 3b92e04cffd..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/nose.rst
+++ /dev/null
@@ -1,55 +0,0 @@
-Running tests written for nose
-=======================================
-
-.. include:: links.inc
-
-``pytest`` has basic support for running tests written for nose_.
-
-.. _nosestyle:
-
-Usage
--------------
-
-After :ref:`installation` type::
-
- python setup.py develop # make sure tests can import our package
- py.test # instead of 'nosetests'
-
-and you should be able to run your nose style tests and
-make use of pytest's capabilities.
-
-Supported nose Idioms
-----------------------
-
-* setup and teardown at module/class/method level
-* SkipTest exceptions and markers
-* setup/teardown decorators
-* yield-based tests and their setup
-* ``__test__`` attribute on modules/classes/functions
-* general usage of nose utilities
-
-Unsupported idioms / known issues
-----------------------------------
-
-- unittest-style ``setUp, tearDown, setUpClass, tearDownClass``
- are recognized only on ``unittest.TestCase`` classes but not
- on plain classes. ``nose`` supports these methods also on plain
- classes but pytest deliberately does not. As nose and pytest already
- both support ``setup_class, teardown_class, setup_method, teardown_method``
- it doesn't seem useful to duplicate the unittest-API like nose does.
- If you however rather think pytest should support the unittest-spelling on
- plain classes please post `to this issue
- <https://github.com/pytest-dev/pytest/issues/377/>`_.
-
-- nose imports test modules with the same import path (e.g.
- ``tests.test_mod``) but different file system paths
- (e.g. ``tests/test_mode.py`` and ``other/tests/test_mode.py``)
- by extending sys.path/import semantics. pytest does not do that
- but there is discussion in `issue268 <https://github.com/pytest-dev/pytest/issues/268>`_ for adding some support. Note that
- `nose2 choose to avoid this sys.path/import hackery <https://nose2.readthedocs.org/en/latest/differences.html#test-discovery-and-loading>`_.
-
-- nose-style doctests are not collected and executed correctly,
- also doctest fixtures don't work.
-
-- no nose-configuration is recognized
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/overview.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/overview.rst
deleted file mode 100644
index eb261977514..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/overview.rst
+++ /dev/null
@@ -1,13 +0,0 @@
-==================================================
-Getting started basics
-==================================================
-
-.. toctree::
- :maxdepth: 2
-
- getting-started
- usage
- goodpractices
- projects
- faq
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/parametrize.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/parametrize.rst
deleted file mode 100644
index 919ac93d25a..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/parametrize.rst
+++ /dev/null
@@ -1,219 +0,0 @@
-
-.. _`test generators`:
-.. _`parametrizing-tests`:
-.. _`parametrized test functions`:
-.. _`parametrize`:
-
-.. _`parametrize-basics`:
-
-Parametrizing fixtures and test functions
-==========================================================================
-
-pytest supports test parametrization in several well-integrated ways:
-
-- :py:func:`pytest.fixture` allows to define :ref:`parametrization
- at the level of fixture functions <fixture-parametrize>`.
-
-* `@pytest.mark.parametrize`_ allows to define parametrization at the
- function or class level, provides multiple argument/fixture sets
- for a particular test function or class.
-
-* `pytest_generate_tests`_ enables implementing your own custom
- dynamic parametrization scheme or extensions.
-
-.. _parametrizemark:
-.. _`@pytest.mark.parametrize`:
-
-
-``@pytest.mark.parametrize``: parametrizing test functions
----------------------------------------------------------------------
-
-.. regendoc: wipe
-
-.. versionadded:: 2.2
-.. versionchanged:: 2.4
- Several improvements.
-
-The builtin ``pytest.mark.parametrize`` decorator enables
-parametrization of arguments for a test function. Here is a typical example
-of a test function that implements checking that a certain input leads
-to an expected output::
-
- # content of test_expectation.py
- import pytest
- @pytest.mark.parametrize("test_input,expected", [
- ("3+5", 8),
- ("2+4", 6),
- ("6*9", 42),
- ])
- def test_eval(test_input, expected):
- assert eval(test_input) == expected
-
-Here, the ``@parametrize`` decorator defines three different ``(test_input,expected)``
-tuples so that the ``test_eval`` function will run three times using
-them in turn::
-
- $ py.test
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 3 items
-
- test_expectation.py ..F
-
- ======= FAILURES ========
- _______ test_eval[6*9-42] ________
-
- test_input = '6*9', expected = 42
-
- @pytest.mark.parametrize("test_input,expected", [
- ("3+5", 8),
- ("2+4", 6),
- ("6*9", 42),
- ])
- def test_eval(test_input, expected):
- > assert eval(test_input) == expected
- E assert 54 == 42
- E + where 54 = eval('6*9')
-
- test_expectation.py:8: AssertionError
- ======= 1 failed, 2 passed in 0.12 seconds ========
-
-As designed in this example, only one pair of input/output values fails
-the simple test function. And as usual with test function arguments,
-you can see the ``input`` and ``output`` values in the traceback.
-
-Note that you could also use the parametrize marker on a class or a module
-(see :ref:`mark`) which would invoke several functions with the argument sets.
-
-It is also possible to mark individual test instances within parametrize,
-for example with the builtin ``mark.xfail``::
-
- # content of test_expectation.py
- import pytest
- @pytest.mark.parametrize("test_input,expected", [
- ("3+5", 8),
- ("2+4", 6),
- pytest.mark.xfail(("6*9", 42)),
- ])
- def test_eval(test_input, expected):
- assert eval(test_input) == expected
-
-Let's run this::
-
- $ py.test
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 3 items
-
- test_expectation.py ..x
-
- ======= 2 passed, 1 xfailed in 0.12 seconds ========
-
-The one parameter set which caused a failure previously now
-shows up as an "xfailed (expected to fail)" test.
-
-To get all combinations of multiple parametrized arguments you can stack
-``parametrize`` decorators::
-
- import pytest
- @pytest.mark.parametrize("x", [0, 1])
- @pytest.mark.parametrize("y", [2, 3])
- def test_foo(x, y):
- pass
-
-This will run the test with the arguments set to x=0/y=2, x=0/y=3, x=1/y=2 and
-x=1/y=3.
-
-.. note::
-
- In versions prior to 2.4 one needed to specify the argument
- names as a tuple. This remains valid but the simpler ``"name1,name2,..."``
- comma-separated-string syntax is now advertised first because
- it's easier to write and produces less line noise.
-
-.. _`pytest_generate_tests`:
-
-Basic ``pytest_generate_tests`` example
----------------------------------------------
-
-Sometimes you may want to implement your own parametrization scheme
-or implement some dynamism for determining the parameters or scope
-of a fixture. For this, you can use the ``pytest_generate_tests`` hook
-which is called when collecting a test function. Through the passed in
-``metafunc`` object you can inspect the requesting test context and, most
-importantly, you can call ``metafunc.parametrize()`` to cause
-parametrization.
-
-For example, let's say we want to run a test taking string inputs which
-we want to set via a new ``pytest`` command line option. Let's first write
-a simple test accepting a ``stringinput`` fixture function argument::
-
- # content of test_strings.py
-
- def test_valid_string(stringinput):
- assert stringinput.isalpha()
-
-Now we add a ``conftest.py`` file containing the addition of a
-command line option and the parametrization of our test function::
-
- # content of conftest.py
-
- def pytest_addoption(parser):
- parser.addoption("--stringinput", action="append", default=[],
- help="list of stringinputs to pass to test functions")
-
- def pytest_generate_tests(metafunc):
- if 'stringinput' in metafunc.fixturenames:
- metafunc.parametrize("stringinput",
- metafunc.config.option.stringinput)
-
-If we now pass two stringinput values, our test will run twice::
-
- $ py.test -q --stringinput="hello" --stringinput="world" test_strings.py
- ..
- 2 passed in 0.12 seconds
-
-Let's also run with a stringinput that will lead to a failing test::
-
- $ py.test -q --stringinput="!" test_strings.py
- F
- ======= FAILURES ========
- _______ test_valid_string[!] ________
-
- stringinput = '!'
-
- def test_valid_string(stringinput):
- > assert stringinput.isalpha()
- E assert <built-in method isalpha of str object at 0xdeadbeef>()
- E + where <built-in method isalpha of str object at 0xdeadbeef> = '!'.isalpha
-
- test_strings.py:3: AssertionError
- 1 failed in 0.12 seconds
-
-As expected our test function fails.
-
-If you don't specify a stringinput it will be skipped because
-``metafunc.parametrize()`` will be called with an empty parameter
-list::
-
- $ py.test -q -rs test_strings.py
- s
- ======= short test summary info ========
- SKIP [1] $PYTHON_PREFIX/lib/python3.4/site-packages/_pytest/python.py:1419: got empty parameter set, function test_valid_string at $REGENDOC_TMPDIR/test_strings.py:1
- 1 skipped in 0.12 seconds
-
-For further examples, you might want to look at :ref:`more
-parametrization examples <paramexamples>`.
-
-.. _`metafunc object`:
-
-The **metafunc** object
--------------------------------------------
-
-.. currentmodule:: _pytest.python
-.. autoclass:: Metafunc
-
- .. automethod:: Metafunc.parametrize
- .. automethod:: Metafunc.addcall(funcargs=None,id=_notexists,param=_notexists)
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/plugins.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/plugins.rst
deleted file mode 100644
index e9b3f460cc4..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/plugins.rst
+++ /dev/null
@@ -1,159 +0,0 @@
-.. _`external plugins`:
-.. _`extplugins`:
-.. _`using plugins`:
-
-Installing and Using plugins
-============================
-
-This section talks about installing and using third party plugins.
-For writing your own plugins, please refer to :ref:`writing-plugins`.
-
-Installing a third party plugin can be easily done with ``pip``::
-
- pip install pytest-NAME
- pip uninstall pytest-NAME
-
-If a plugin is installed, ``pytest`` automatically finds and integrates it,
-there is no need to activate it.
-
-Here is a little annotated list for some popular plugins:
-
-.. _`django`: https://www.djangoproject.com/
-
-* `pytest-django <http://pypi.python.org/pypi/pytest-django>`_: write tests
- for `django`_ apps, using pytest integration.
-
-* `pytest-twisted <http://pypi.python.org/pypi/pytest-twisted>`_: write tests
- for `twisted <http://twistedmatrix.com>`_ apps, starting a reactor and
- processing deferreds from test functions.
-
-* `pytest-catchlog <http://pypi.python.org/pypi/pytest-catchlog>`_:
- to capture and assert about messages from the logging module
-
-* `pytest-cov <http://pypi.python.org/pypi/pytest-cov>`_:
- coverage reporting, compatible with distributed testing
-
-* `pytest-xdist <http://pypi.python.org/pypi/pytest-xdist>`_:
- to distribute tests to CPUs and remote hosts, to run in boxed
- mode which allows to survive segmentation faults, to run in
- looponfailing mode, automatically re-running failing tests
- on file changes, see also :ref:`xdist`
-
-* `pytest-instafail <http://pypi.python.org/pypi/pytest-instafail>`_:
- to report failures while the test run is happening.
-
-* `pytest-bdd <http://pypi.python.org/pypi/pytest-bdd>`_ and
- `pytest-konira <http://pypi.python.org/pypi/pytest-konira>`_
- to write tests using behaviour-driven testing.
-
-* `pytest-timeout <http://pypi.python.org/pypi/pytest-timeout>`_:
- to timeout tests based on function marks or global definitions.
-
-* `pytest-pep8 <http://pypi.python.org/pypi/pytest-pep8>`_:
- a ``--pep8`` option to enable PEP8 compliance checking.
-
-* `pytest-flakes <https://pypi.python.org/pypi/pytest-flakes>`_:
- check source code with pyflakes.
-
-* `oejskit <http://pypi.python.org/pypi/oejskit>`_:
- a plugin to run javascript unittests in live browsers.
-
-To see a complete list of all plugins with their latest testing
-status against different py.test and Python versions, please visit
-`plugincompat <http://plugincompat.herokuapp.com/>`_.
-
-You may also discover more plugins through a `pytest- pypi.python.org search`_.
-
-.. _`available installable plugins`:
-.. _`pytest- pypi.python.org search`: http://pypi.python.org/pypi?%3Aaction=search&term=pytest-&submit=search
-
-
-Requiring/Loading plugins in a test module or conftest file
------------------------------------------------------------
-
-You can require plugins in a test module or a conftest file like this::
-
- pytest_plugins = "myapp.testsupport.myplugin",
-
-When the test module or conftest plugin is loaded the specified plugins
-will be loaded as well.
-
- pytest_plugins = "myapp.testsupport.myplugin"
-
-which will import the specified module as a ``pytest`` plugin.
-
-.. _`findpluginname`:
-
-Finding out which plugins are active
-------------------------------------
-
-If you want to find out which plugins are active in your
-environment you can type::
-
- py.test --traceconfig
-
-and will get an extended test header which shows activated plugins
-and their names. It will also print local plugins aka
-:ref:`conftest.py <conftest>` files when they are loaded.
-
-.. _`cmdunregister`:
-
-Deactivating / unregistering a plugin by name
----------------------------------------------
-
-You can prevent plugins from loading or unregister them::
-
- py.test -p no:NAME
-
-This means that any subsequent try to activate/load the named
-plugin will not work.
-
-If you want to unconditionally disable a plugin for a project, you can add
-this option to your ``pytest.ini`` file:
-
-.. code-block:: ini
-
- [pytest]
- addopts = -p no:NAME
-
-Alternatively to disable it only in certain environments (for example in a
-CI server), you can set ``PYTEST_ADDOPTS`` environment variable to
-``-p no:name``.
-
-See :ref:`findpluginname` for how to obtain the name of a plugin.
-
-.. _`builtin plugins`:
-
-Pytest default plugin reference
--------------------------------
-
-
-You can find the source code for the following plugins
-in the `pytest repository <https://github.com/pytest-dev/pytest>`_.
-
-.. autosummary::
-
- _pytest.assertion
- _pytest.cacheprovider
- _pytest.capture
- _pytest.config
- _pytest.doctest
- _pytest.genscript
- _pytest.helpconfig
- _pytest.junitxml
- _pytest.mark
- _pytest.monkeypatch
- _pytest.nose
- _pytest.pastebin
- _pytest.pdb
- _pytest.pytester
- _pytest.python
- _pytest.recwarn
- _pytest.resultlog
- _pytest.runner
- _pytest.main
- _pytest.skipping
- _pytest.terminal
- _pytest.tmpdir
- _pytest.unittest
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/projects.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/projects.rst
deleted file mode 100644
index 76d004916ce..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/projects.rst
+++ /dev/null
@@ -1,85 +0,0 @@
-.. _projects:
-
-.. image:: img/gaynor3.png
- :width: 400px
- :align: right
-
-.. image:: img/theuni.png
- :width: 400px
- :align: right
-
-.. image:: img/cramer2.png
- :width: 400px
- :align: right
-
-.. image:: img/keleshev.png
- :width: 400px
- :align: right
-
-
-Project examples
-==========================
-
-Here are some examples of projects using ``pytest`` (please send notes via :ref:`contact`):
-
-* `PyPy <http://pypy.org>`_, Python with a JIT compiler, running over
- `21000 tests <http://buildbot.pypy.org/summary?branch=%3Ctrunk%3E>`_
-* the `MoinMoin <http://moinmo.in>`_ Wiki Engine
-* `sentry <https://getsentry.com/welcome/>`_, realtime app-maintenance and exception tracking
-* `Astropy <http://www.astropy.org/>`_ and `affiliated packages <http://www.astropy.org/affiliated/index.html>`_
-* `tox <http://testrun.org/tox>`_, virtualenv/Hudson integration tool
-* `PIDA <http://pida.co.uk>`_ framework for integrated development
-* `PyPM <http://code.activestate.com/pypm/>`_ ActiveState's package manager
-* `Fom <http://packages.python.org/Fom/>`_ a fluid object mapper for FluidDB
-* `applib <https://github.com/ActiveState/applib>`_ cross-platform utilities
-* `six <http://pypi.python.org/pypi/six/>`_ Python 2 and 3 compatibility utilities
-* `pediapress <http://code.pediapress.com/wiki/wiki>`_ MediaWiki articles
-* `mwlib <http://pypi.python.org/pypi/mwlib>`_ mediawiki parser and utility library
-* `The Translate Toolkit <http://translate.sourceforge.net/wiki/toolkit/index>`_ for localization and conversion
-* `execnet <http://codespeak.net/execnet>`_ rapid multi-Python deployment
-* `pylib <http://py.rtfd.org>`_ cross-platform path, IO, dynamic code library
-* `Pacha <http://pacha.cafepais.com/>`_ configuration management in five minutes
-* `bbfreeze <http://pypi.python.org/pypi/bbfreeze>`_ create standalone executables from Python scripts
-* `pdb++ <http://bitbucket.org/antocuni/pdb>`_ a fancier version of PDB
-* `py-s3fuse <http://code.google.com/p/py-s3fuse/>`_ Amazon S3 FUSE based filesystem
-* `waskr <http://code.google.com/p/waskr/>`_ WSGI Stats Middleware
-* `guachi <http://code.google.com/p/guachi/>`_ global persistent configs for Python modules
-* `Circuits <http://pypi.python.org/pypi/circuits>`_ lightweight Event Driven Framework
-* `pygtk-helpers <http://bitbucket.org/aafshar/pygtkhelpers-main/>`_ easy interaction with PyGTK
-* `QuantumCore <http://quantumcore.org/>`_ statusmessage and repoze openid plugin
-* `pydataportability <http://pydataportability.net/>`_ libraries for managing the open web
-* `XIST <http://www.livinglogic.de/Python/xist/>`_ extensible HTML/XML generator
-* `tiddlyweb <http://pypi.python.org/pypi/tiddlyweb>`_ optionally headless, extensible RESTful datastore
-* `fancycompleter <http://bitbucket.org/antocuni/fancycompleter/src>`_ for colorful tab-completion
-* `Paludis <http://paludis.exherbo.org/>`_ tools for Gentoo Paludis package manager
-* `Gerald <http://halfcooked.com/code/gerald/>`_ schema comparison tool
-* `abjad <http://code.google.com/p/abjad/>`_ Python API for Formalized Score control
-* `bu <http://packages.python.org/bu/>`_ a microscopic build system
-* `katcp <https://bitbucket.org/hodgestar/katcp>`_ Telescope communication protocol over Twisted
-* `kss plugin timer <http://pypi.python.org/pypi/kss.plugin.timer>`_
-* `pyudev <http://pyudev.readthedocs.org/en/latest/tests/plugins.html>`_ a pure Python binding to the Linux library libudev
-* `pytest-localserver <https://bitbucket.org/basti/pytest-localserver/>`_ a plugin for pytest that provides a httpserver and smtpserver
-* `pytest-monkeyplus <http://pypi.python.org/pypi/pytest-monkeyplus/>`_ a plugin that extends monkeypatch
-
-These projects help integrate ``pytest`` into other Python frameworks:
-
-* `pytest-django <http://pypi.python.org/pypi/pytest-django/>`_ for Django
-* `zope.pytest <http://packages.python.org/zope.pytest/>`_ for Zope and Grok
-* `pytest_gae <http://pypi.python.org/pypi/pytest_gae/0.2.1>`_ for Google App Engine
-* There is `some work <https://github.com/Kotti/Kotti/blob/master/kotti/testing.py>`_ underway for Kotti, a CMS built in Pyramid/Pylons
-
-
-Some organisations using pytest
------------------------------------
-
-* `Square Kilometre Array, Cape Town <http://ska.ac.za/>`_
-* `Some Mozilla QA people <http://www.theautomatedtester.co.uk/blog/2011/pytest_and_xdist_plugin.html>`_ use pytest to distribute their Selenium tests
-* `Tandberg <http://www.tandberg.com/>`_
-* `Shootq <http://web.shootq.com/>`_
-* `Stups department of Heinrich Heine University Duesseldorf <http://www.stups.uni-duesseldorf.de/projects.php>`_
-* `cellzome <http://www.cellzome.com/>`_
-* `Open End, Gothenborg <http://www.openend.se>`_
-* `Laboratory of Bioinformatics, Warsaw <http://genesilico.pl/>`_
-* `merlinux, Germany <http://merlinux.eu>`_
-* `ESSS, Brazil <http://www.esss.com.br>`_
-* many more ... (please be so kind to send a note via :ref:`contact`)
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/recwarn.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/recwarn.rst
deleted file mode 100644
index 3c42bfaaf94..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/recwarn.rst
+++ /dev/null
@@ -1,130 +0,0 @@
-
-Asserting Warnings
-=====================================================
-
-.. _warns:
-
-Asserting warnings with the warns function
------------------------------------------------
-
-.. versionadded:: 2.8
-
-You can check that code raises a particular warning using ``pytest.warns``,
-which works in a similar manner to :ref:`raises <assertraises>`::
-
- import warnings
- import pytest
-
- def test_warning():
- with pytest.warns(UserWarning):
- warnings.warn("my warning", UserWarning)
-
-The test will fail if the warning in question is not raised.
-
-You can also call ``pytest.warns`` on a function or code string::
-
- pytest.warns(expected_warning, func, *args, **kwargs)
- pytest.warns(expected_warning, "func(*args, **kwargs)")
-
-The function also returns a list of all raised warnings (as
-``warnings.WarningMessage`` objects), which you can query for
-additional information::
-
- with pytest.warns(RuntimeWarning) as record:
- warnings.warn("another warning", RuntimeWarning)
-
- # check that only one warning was raised
- assert len(record) == 1
- # check that the message matches
- assert record[0].message.args[0] == "another warning"
-
-Alternatively, you can examine raised warnings in detail using the
-:ref:`recwarn <recwarn>` fixture (see below).
-
-.. note::
- ``DeprecationWarning`` and ``PendingDeprecationWarning`` are treated
- differently; see :ref:`ensuring_function_triggers`.
-
-.. _recwarn:
-
-Recording warnings
-------------------------
-
-You can record raised warnings either using ``pytest.warns`` or with
-the ``recwarn`` fixture.
-
-To record with ``pytest.warns`` without asserting anything about the warnings,
-pass ``None`` as the expected warning type::
-
- with pytest.warns(None) as record:
- warnings.warn("user", UserWarning)
- warnings.warn("runtime", RuntimeWarning)
-
- assert len(record) == 2
- assert str(record[0].message) == "user"
- assert str(record[1].message) == "runtime"
-
-The ``recwarn`` fixture will record warnings for the whole function::
-
- import warnings
-
- def test_hello(recwarn):
- warnings.warn("hello", UserWarning)
- assert len(recwarn) == 1
- w = recwarn.pop(UserWarning)
- assert issubclass(w.category, UserWarning)
- assert str(w.message) == "hello"
- assert w.filename
- assert w.lineno
-
-Both ``recwarn`` and ``pytest.warns`` return the same interface for recorded
-warnings: a WarningsRecorder instance. To view the recorded warnings, you can
-iterate over this instance, call ``len`` on it to get the number of recorded
-warnings, or index into it to get a particular recorded warning. It also
-provides these methods:
-
-.. autoclass:: _pytest.recwarn.WarningsRecorder()
- :members:
-
-Each recorded warning has the attributes ``message``, ``category``,
-``filename``, ``lineno``, ``file``, and ``line``. The ``category`` is the
-class of the warning. The ``message`` is the warning itself; calling
-``str(message)`` will return the actual message of the warning.
-
-.. note::
- ``DeprecationWarning`` and ``PendingDeprecationWarning`` are treated
- differently; see :ref:`ensuring_function_triggers`.
-
-.. _ensuring_function_triggers:
-
-Ensuring a function triggers a deprecation warning
--------------------------------------------------------
-
-You can also call a global helper for checking
-that a certain function call triggers a ``DeprecationWarning`` or
-``PendingDeprecationWarning``::
-
- import pytest
-
- def test_global():
- pytest.deprecated_call(myfunction, 17)
-
-By default, ``DeprecationWarning`` and ``PendingDeprecationWarning`` will not be
-caught when using ``pytest.warns`` or ``recwarn`` because default Python warnings filters hide
-them. If you wish to record them in your own code, use the
-command ``warnings.simplefilter('always')``::
-
- import warnings
- import pytest
-
- def test_deprecation(recwarn):
- warnings.simplefilter('always')
- warnings.warn("deprecated", DeprecationWarning)
- assert len(recwarn) == 1
- assert recwarn.pop(DeprecationWarning)
-
-You can also use it as a contextmanager::
-
- def test_global():
- with pytest.deprecated_call():
- myobject.deprecated_method()
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/setup.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/setup.rst
deleted file mode 100644
index fe235346544..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/setup.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-
-setup: is now an "autouse fixture"
-========================================================
-
-During development prior to the pytest-2.3 release the name
-``pytest.setup`` was used but before the release it was renamed
-and moved to become part of the general fixture mechanism,
-namely :ref:`autouse fixtures`
-
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/skipping.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/skipping.rst
deleted file mode 100644
index 4282afb77ec..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/skipping.rst
+++ /dev/null
@@ -1,373 +0,0 @@
-.. _`skip and xfail`:
-
-.. _skipping:
-
-Skip and xfail: dealing with tests that can not succeed
-=====================================================================
-
-If you have test functions that cannot be run on certain platforms
-or that you expect to fail you can mark them accordingly or you
-may call helper functions during execution of setup or test functions.
-
-A *skip* means that you expect your test to pass unless the environment
-(e.g. wrong Python interpreter, missing dependency) prevents it to run.
-And *xfail* means that your test can run but you expect it to fail
-because there is an implementation problem.
-
-``pytest`` counts and lists *skip* and *xfail* tests separately. Detailed
-information about skipped/xfailed tests is not shown by default to avoid
-cluttering the output. You can use the ``-r`` option to see details
-corresponding to the "short" letters shown in the test progress::
-
- py.test -rxs # show extra info on skips and xfails
-
-(See :ref:`how to change command line options defaults`)
-
-.. _skipif:
-.. _`condition booleans`:
-
-Marking a test function to be skipped
--------------------------------------------
-
-.. versionadded:: 2.9
-
-The simplest way to skip a test function is to mark it with the ``skip`` decorator
-which may be passed an optional ``reason``:
-
-.. code-block:: python
-
- @pytest.mark.skip(reason="no way of currently testing this")
- def test_the_unknown():
- ...
-
-``skipif``
-~~~~~~~~~~
-
-.. versionadded:: 2.0, 2.4
-
-If you wish to skip something conditionally then you can use ``skipif`` instead.
-Here is an example of marking a test function to be skipped
-when run on a Python3.3 interpreter::
-
- import sys
- @pytest.mark.skipif(sys.version_info < (3,3),
- reason="requires python3.3")
- def test_function():
- ...
-
-During test function setup the condition ("sys.version_info >= (3,3)") is
-checked. If it evaluates to True, the test function will be skipped
-with the specified reason. Note that pytest enforces specifying a reason
-in order to report meaningful "skip reasons" (e.g. when using ``-rs``).
-If the condition is a string, it will be evaluated as python expression.
-
-You can share skipif markers between modules. Consider this test module::
-
- # content of test_mymodule.py
-
- import mymodule
- minversion = pytest.mark.skipif(mymodule.__versioninfo__ < (1,1),
- reason="at least mymodule-1.1 required")
- @minversion
- def test_function():
- ...
-
-You can import it from another test module::
-
- # test_myothermodule.py
- from test_mymodule import minversion
-
- @minversion
- def test_anotherfunction():
- ...
-
-For larger test suites it's usually a good idea to have one file
-where you define the markers which you then consistently apply
-throughout your test suite.
-
-Alternatively, the pre pytest-2.4 way to specify :ref:`condition strings
-<string conditions>` instead of booleans will remain fully supported in future
-versions of pytest. It couldn't be easily used for importing markers
-between test modules so it's no longer advertised as the primary method.
-
-
-Skip all test functions of a class or module
----------------------------------------------
-
-You can use the ``skipif`` decorator (and any other marker) on classes::
-
- @pytest.mark.skipif(sys.platform == 'win32',
- reason="does not run on windows")
- class TestPosixCalls:
-
- def test_function(self):
- "will not be setup or run under 'win32' platform"
-
-If the condition is true, this marker will produce a skip result for
-each of the test methods.
-
-If you want to skip all test functions of a module, you must use
-the ``pytestmark`` name on the global level:
-
-.. code-block:: python
-
- # test_module.py
- pytestmark = pytest.mark.skipif(...)
-
-If multiple "skipif" decorators are applied to a test function, it
-will be skipped if any of the skip conditions is true.
-
-.. _`whole class- or module level`: mark.html#scoped-marking
-
-.. _xfail:
-
-Mark a test function as expected to fail
--------------------------------------------------------
-
-You can use the ``xfail`` marker to indicate that you
-expect a test to fail::
-
- @pytest.mark.xfail
- def test_function():
- ...
-
-This test will be run but no traceback will be reported
-when it fails. Instead terminal reporting will list it in the
-"expected to fail" (``XFAIL``) or "unexpectedly passing" (``XPASS``) sections.
-
-``strict`` parameter
-~~~~~~~~~~~~~~~~~~~~
-
-.. versionadded:: 2.9
-
-Both ``XFAIL`` and ``XPASS`` don't fail the test suite, unless the ``strict`` keyword-only
-parameter is passed as ``True``:
-
-.. code-block:: python
-
- @pytest.mark.xfail(strict=True)
- def test_function():
- ...
-
-
-This will make ``XPASS`` ("unexpectedly passing") results from this test to fail the test suite.
-
-You can change the default value of the ``strict`` parameter using the
-``xfail_strict`` ini option:
-
-.. code-block:: ini
-
- [pytest]
- xfail_strict=true
-
-
-``reason`` parameter
-~~~~~~~~~~~~~~~~~~~~
-
-As with skipif_ you can also mark your expectation of a failure
-on a particular platform::
-
- @pytest.mark.xfail(sys.version_info >= (3,3),
- reason="python3.3 api changes")
- def test_function():
- ...
-
-
-``raises`` parameter
-~~~~~~~~~~~~~~~~~~~~
-
-If you want to be more specific as to why the test is failing, you can specify
-a single exception, or a list of exceptions, in the ``raises`` argument.
-
-.. code-block:: python
-
- @pytest.mark.xfail(raises=RuntimeError)
- def test_function():
- ...
-
-Then the test will be reported as a regular failure if it fails with an
-exception not mentioned in ``raises``.
-
-``run`` parameter
-~~~~~~~~~~~~~~~~~
-
-If a test should be marked as xfail and reported as such but should not be
-even executed, use the ``run`` parameter as ``False``:
-
-.. code-block:: python
-
- @pytest.mark.xfail(run=False)
- def test_function():
- ...
-
-This is specially useful for marking crashing tests for later inspection.
-
-
-Ignoring xfail marks
-~~~~~~~~~~~~~~~~~~~~
-
-By specifying on the commandline::
-
- pytest --runxfail
-
-you can force the running and reporting of an ``xfail`` marked test
-as if it weren't marked at all.
-
-Examples
-~~~~~~~~
-
-Here is a simple test file with the several usages:
-
-.. literalinclude:: example/xfail_demo.py
-
-Running it with the report-on-xfail option gives this output::
-
- example $ py.test -rx xfail_demo.py
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR/example, inifile:
- collected 7 items
-
- xfail_demo.py xxxxxxx
- ======= short test summary info ========
- XFAIL xfail_demo.py::test_hello
- XFAIL xfail_demo.py::test_hello2
- reason: [NOTRUN]
- XFAIL xfail_demo.py::test_hello3
- condition: hasattr(os, 'sep')
- XFAIL xfail_demo.py::test_hello4
- bug 110
- XFAIL xfail_demo.py::test_hello5
- condition: pytest.__version__[0] != "17"
- XFAIL xfail_demo.py::test_hello6
- reason: reason
- XFAIL xfail_demo.py::test_hello7
-
- ======= 7 xfailed in 0.12 seconds ========
-
-xfail signature summary
-~~~~~~~~~~~~~~~~~~~~~~~
-
-Here's the signature of the ``xfail`` marker, using Python 3 keyword-only
-arguments syntax:
-
-.. code-block:: python
-
- def xfail(condition=None, *, reason=None, raises=None, run=True, strict=False):
-
-
-
-.. _`skip/xfail with parametrize`:
-
-Skip/xfail with parametrize
----------------------------
-
-It is possible to apply markers like skip and xfail to individual
-test instances when using parametrize::
-
- import pytest
-
- @pytest.mark.parametrize(("n", "expected"), [
- (1, 2),
- pytest.mark.xfail((1, 0)),
- pytest.mark.xfail(reason="some bug")((1, 3)),
- (2, 3),
- (3, 4),
- (4, 5),
- pytest.mark.skipif("sys.version_info >= (3,0)")((10, 11)),
- ])
- def test_increment(n, expected):
- assert n + 1 == expected
-
-
-Imperative xfail from within a test or setup function
-------------------------------------------------------
-
-If you cannot declare xfail- of skipif conditions at import
-time you can also imperatively produce an according outcome
-imperatively, in test or setup code::
-
- def test_function():
- if not valid_config():
- pytest.xfail("failing configuration (but should work)")
- # or
- pytest.skip("unsupported configuration")
-
-
-Skipping on a missing import dependency
---------------------------------------------------
-
-You can use the following import helper at module level
-or within a test or test setup function::
-
- docutils = pytest.importorskip("docutils")
-
-If ``docutils`` cannot be imported here, this will lead to a
-skip outcome of the test. You can also skip based on the
-version number of a library::
-
- docutils = pytest.importorskip("docutils", minversion="0.3")
-
-The version will be read from the specified
-module's ``__version__`` attribute.
-
-
-.. _string conditions:
-
-specifying conditions as strings versus booleans
-----------------------------------------------------------
-
-Prior to pytest-2.4 the only way to specify skipif/xfail conditions was
-to use strings::
-
- import sys
- @pytest.mark.skipif("sys.version_info >= (3,3)")
- def test_function():
- ...
-
-During test function setup the skipif condition is evaluated by calling
-``eval('sys.version_info >= (3,0)', namespace)``. The namespace contains
-all the module globals, and ``os`` and ``sys`` as a minimum.
-
-Since pytest-2.4 `condition booleans`_ are considered preferable
-because markers can then be freely imported between test modules.
-With strings you need to import not only the marker but all variables
-everything used by the marker, which violates encapsulation.
-
-The reason for specifying the condition as a string was that ``pytest`` can
-report a summary of skip conditions based purely on the condition string.
-With conditions as booleans you are required to specify a ``reason`` string.
-
-Note that string conditions will remain fully supported and you are free
-to use them if you have no need for cross-importing markers.
-
-The evaluation of a condition string in ``pytest.mark.skipif(conditionstring)``
-or ``pytest.mark.xfail(conditionstring)`` takes place in a namespace
-dictionary which is constructed as follows:
-
-* the namespace is initialized by putting the ``sys`` and ``os`` modules
- and the pytest ``config`` object into it.
-
-* updated with the module globals of the test function for which the
- expression is applied.
-
-The pytest ``config`` object allows you to skip based on a test
-configuration value which you might have added::
-
- @pytest.mark.skipif("not config.getvalue('db')")
- def test_function(...):
- ...
-
-The equivalent with "boolean conditions" is::
-
- @pytest.mark.skipif(not pytest.config.getvalue("db"),
- reason="--db was not specified")
- def test_function(...):
- pass
-
-.. note::
-
- You cannot use ``pytest.config.getvalue()`` in code
- imported before py.test's argument parsing takes place. For example,
- ``conftest.py`` files are imported before command line parsing and thus
- ``config.getvalue()`` will not execute correctly.
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/status.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/status.rst
deleted file mode 100644
index 3c7bf70eaa4..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/status.rst
+++ /dev/null
@@ -1,5 +0,0 @@
-pytest development status
-================================
-
-https://travis-ci.org/pytest-dev/pytest
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/talks.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/talks.rst
deleted file mode 100644
index 7a5221845ce..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/talks.rst
+++ /dev/null
@@ -1,116 +0,0 @@
-
-Talks and Tutorials
-==========================
-
-.. sidebar:: Next Open Trainings
-
- `professional testing with pytest and tox <http://www.python-academy.com/courses/specialtopics/python_course_testing.html>`_, 27-29th June 2016, Freiburg, Germany
-
-.. _`funcargs`: funcargs.html
-
-Talks and blog postings
----------------------------------------------
-
-.. _`tutorial1 repository`: http://bitbucket.org/pytest-dev/pytest-tutorial1/
-.. _`pycon 2010 tutorial PDF`: http://bitbucket.org/pytest-dev/pytest-tutorial1/raw/tip/pytest-basic.pdf
-
-- `pytest - Rapid Simple Testing, Florian Bruhin, Swiss Python Summit 2016
- <https://www.youtube.com/watch?v=rCBHkQ_LVIs>`_.
-
-- `Improve your testing with Pytest and Mock, Gabe Hollombe, PyCon SG 2015
- <https://www.youtube.com/watch?v=RcN26hznmk4>`_.
-
-- `Introduction to pytest, Andreas Pelme, EuroPython 2014
- <https://www.youtube.com/watch?v=LdVJj65ikRY>`_.
-
-- `Advanced Uses of py.test Fixtures, Floris Bruynooghe, EuroPython
- 2014 <https://www.youtube.com/watch?v=IBC_dxr-4ps>`_.
-
-- `Why i use py.test and maybe you should too, Andy Todd, Pycon AU 2013
- <https://www.youtube.com/watch?v=P-AhpukDIik>`_
-
-- `3-part blog series about pytest from @pydanny alias Daniel Greenfeld (January
- 2014) <http://pydanny.com/pytest-no-boilerplate-testing.html>`_
-
-- `pytest: helps you write better Django apps, Andreas Pelme, DjangoCon
- Europe 2014 <https://www.youtube.com/watch?v=aaArYVh6XSM>`_.
-
-- :ref:`fixtures`
-
-- `Testing Django Applications with pytest, Andreas Pelme, EuroPython
- 2013 <https://www.youtube.com/watch?v=aUf8Fkb7TaY>`_.
-
-- `Testes pythonics com py.test, Vinicius Belchior Assef Neto, Plone
- Conf 2013, Brazil <https://www.youtube.com/watch?v=QUKoq2K7bis>`_.
-
-- `Introduction to py.test fixtures, FOSDEM 2013, Floris Bruynooghe
- <https://www.youtube.com/watch?v=bJhRW4eZMco>`_.
-
-- `pytest feature and release highlights, Holger Krekel (GERMAN, October 2013)
- <http://pyvideo.org/video/2429/pytest-feature-and-new-release-highlights>`_
-
-- `pytest introduction from Brian Okken (January 2013)
- <http://pythontesting.net/framework/pytest-introduction/>`_
-
-- `monkey patching done right`_ (blog post, consult `monkeypatch
- plugin`_ for up-to-date API)
-
-Test parametrization:
-
-- `generating parametrized tests with funcargs`_ (uses deprecated ``addcall()`` API.
-- `test generators and cached setup`_
-- `parametrizing tests, generalized`_ (blog post)
-- `putting test-hooks into local or global plugins`_ (blog post)
-
-Assertion introspection:
-
-- `(07/2011) Behind the scenes of pytest's new assertion rewriting
- <http://pybites.blogspot.com/2011/07/behind-scenes-of-pytests-new-assertion.html>`_
-
-Distributed testing:
-
-- `simultaneously test your code on all platforms`_ (blog entry)
-
-Plugin specific examples:
-
-- `skipping slow tests by default in pytest`_ (blog entry)
-
-- `many examples in the docs for plugins`_
-
-.. _`skipping slow tests by default in pytest`: http://bruynooghe.blogspot.com/2009/12/skipping-slow-test-by-default-in-pytest.html
-.. _`many examples in the docs for plugins`: plugin/index.html
-.. _`monkeypatch plugin`: plugin/monkeypatch.html
-.. _`application setup in test functions with funcargs`: funcargs.html#appsetup
-.. _`simultaneously test your code on all platforms`: http://tetamap.wordpress.com/2009/03/23/new-simultanously-test-your-code-on-all-platforms/
-.. _`monkey patching done right`: http://tetamap.wordpress.com/2009/03/03/monkeypatching-in-unit-tests-done-right/
-.. _`putting test-hooks into local or global plugins`: http://tetamap.wordpress.com/2009/05/14/putting-test-hooks-into-local-and-global-plugins/
-.. _`parametrizing tests, generalized`: http://tetamap.wordpress.com/2009/05/13/parametrizing-python-tests-generalized/
-.. _`generating parametrized tests with funcargs`: funcargs.html#test-generators
-.. _`test generators and cached setup`: http://bruynooghe.blogspot.com/2010/06/pytest-test-generators-and-cached-setup.html
-
-Older conference talks and tutorials
-----------------------------------------
-
-- `pycon australia 2012 pytest talk from Brianna Laugher
- <http://2012.pycon-au.org/schedule/52/view_talk?day=sunday>`_ (`video <http://www.youtube.com/watch?v=DTNejE9EraI>`_, `slides <http://www.slideshare.net/pfctdayelise/funcargs-other-fun-with-pytest>`_, `code <https://gist.github.com/3386951>`_)
-- `pycon 2012 US talk video from Holger Krekel <http://www.youtube.com/watch?v=9LVqBQcFmyw>`_
-- `pycon 2010 tutorial PDF`_ and `tutorial1 repository`_
-
-- `ep2009-rapidtesting.pdf`_ tutorial slides (July 2009):
-
- - testing terminology
- - basic pytest usage, file system layout
- - test function arguments (funcargs_) and test fixtures
- - existing plugins
- - distributed testing
-
-- `ep2009-pytest.pdf`_ 60 minute pytest talk, highlighting unique features and a roadmap (July 2009)
-
-- `pycon2009-pytest-introduction.zip`_ slides and files, extended version of pytest basic introduction, discusses more options, also introduces old-style xUnit setup, looponfailing and other features.
-
-- `pycon2009-pytest-advanced.pdf`_ contain a slightly older version of funcargs and distributed testing, compared to the EuroPython 2009 slides.
-
-.. _`ep2009-rapidtesting.pdf`: http://codespeak.net/download/py/ep2009-rapidtesting.pdf
-.. _`ep2009-pytest.pdf`: http://codespeak.net/download/py/ep2009-pytest.pdf
-.. _`pycon2009-pytest-introduction.zip`: http://codespeak.net/download/py/pycon2009-pytest-introduction.zip
-.. _`pycon2009-pytest-advanced.pdf`: http://codespeak.net/download/py/pycon2009-pytest-advanced.pdf
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/attic.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/attic.rst
deleted file mode 100644
index 6408c722584..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/attic.rst
+++ /dev/null
@@ -1,117 +0,0 @@
-===============================================
-ATTIC documentation
-===============================================
-
-XXX REVIEW and remove the below XXX
-
-Customizing the testing process
-===============================
-
-writing conftest.py files
------------------------------------
-
-You may put conftest.py files containing project-specific
-configuration in your project's root directory, it's usually
-best to put it just into the same directory level as your
-topmost ``__init__.py``. In fact, ``pytest`` performs
-an "upwards" search starting from the directory that you specify
-to be tested and will lookup configuration values right-to-left.
-You may have options that reside e.g. in your home directory
-but note that project specific settings will be considered
-first. There is a flag that helps you debugging your
-conftest.py configurations::
-
- py.test --traceconfig
-
-
-customizing the collecting and running process
------------------------------------------------
-
-To introduce different test items you can create
-one or more ``conftest.py`` files in your project.
-When the collection process traverses directories
-and modules the default collectors will produce
-custom Collectors and Items if they are found
-in a local ``conftest.py`` file.
-
-
-Customizing the collection process in a module
-----------------------------------------------
-
-If you have a module where you want to take responsibility for
-collecting your own test Items and possibly even for executing
-a test then you can provide `generative tests`_ that yield
-callables and possibly arguments as a tuple. This is especially
-useful for calling application test machinery with different
-parameter sets but counting each of the calls as a separate
-tests.
-
-.. _`generative tests`: features.html#generative-tests
-
-The other extension possibility is about
-specifying a custom test ``Item`` class which
-is responsible for setting up and executing an underlying
-test. Or you can extend the collection process for a whole
-directory tree by putting Items in a ``conftest.py`` configuration file.
-The collection process dynamically consults the *chain of conftest.py*
-modules to determine collectors and items at ``Directory``, ``Module``,
-``Class``, ``Function`` or ``Generator`` level respectively.
-
-Customizing execution of Items and Functions
-----------------------------------------------------
-
-- ``pytest.Function`` test items control execution
- of a test function through its ``function.runtest()`` method.
- This method is responsible for performing setup and teardown
- ("Test Fixtures") for a test Function.
-
-- ``Function.execute(target, *args)`` methods are invoked by
- the default ``Function.run()`` to actually execute a python
- function with the given (usually empty set of) arguments.
-
-.. _`py-dev mailing list`: http://codespeak.net/mailman/listinfo/py-dev
-
-
-.. _`test generators`: funcargs.html#test-generators
-
-.. _`generative tests`:
-
-generative tests: yielding parametrized tests
-====================================================
-
-Deprecated since 1.0 in favour of `test generators`_.
-
-*Generative tests* are test methods that are *generator functions* which
-``yield`` callables and their arguments. This is useful for running a
-test function multiple times against different parameters. Example::
-
- def test_generative():
- for x in (42,17,49):
- yield check, x
-
- def check(arg):
- assert arg % 7 == 0 # second generated tests fails!
-
-Note that ``test_generative()`` will cause three tests
-to get run, notably ``check(42)``, ``check(17)`` and ``check(49)``
-of which the middle one will obviously fail.
-
-To make it easier to distinguish the generated tests it is possible to specify an explicit name for them, like for example::
-
- def test_generative():
- for x in (42,17,49):
- yield "case %d" % x, check, x
-
-
-disabling a test class
-----------------------
-
-If you want to disable a complete test class you
-can set the class-level attribute ``disabled``.
-For example, in order to avoid running some tests on Win32::
-
- class TestPosixOnly:
- disabled = sys.platform == 'win32'
-
- def test_xxx(self):
- ...
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/mission.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/mission.rst
deleted file mode 100644
index cda8d9a7208..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/mission.rst
+++ /dev/null
@@ -1,13 +0,0 @@
-
-Mission
-====================================
-
-``pytest`` strives to make testing a fun and no-boilerplate effort.
-
-The tool is distributed as a `pytest` package. Its project independent
-``py.test`` command line tool helps you to:
-
-* rapidly collect and run tests
-* run unit- or doctests, functional or integration tests
-* distribute tests to multiple environments
-* use local or global plugins for custom test types and setup
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/cov.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/cov.rst
deleted file mode 100644
index 355093f2586..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/cov.rst
+++ /dev/null
@@ -1,230 +0,0 @@
-
-produce code coverage reports using the 'coverage' package, including support for distributed testing.
-======================================================================================================
-
-
-.. contents::
- :local:
-
-This plugin produces coverage reports. It supports centralised testing and distributed testing in
-both load and each modes. It also supports coverage of subprocesses.
-
-All features offered by the coverage package should be available, either through pytest-cov or
-through coverage's config file.
-
-
-Installation
-------------
-
-The `pytest-cov`_ package may be installed with pip or easy_install::
-
- pip install pytest-cov
- easy_install pytest-cov
-
-.. _`pytest-cov`: http://pypi.python.org/pypi/pytest-cov/
-
-
-Uninstallation
---------------
-
-Uninstalling packages is supported by pip::
-
- pip uninstall pytest-cov
-
-However easy_install does not provide an uninstall facility.
-
-.. IMPORTANT::
-
- Ensure that you manually delete the init_covmain.pth file in your
- site-packages directory.
-
- This file starts coverage collection of subprocesses if appropriate during
- site initialization at python startup.
-
-
-Usage
------
-
-Centralised Testing
-~~~~~~~~~~~~~~~~~~~
-
-Centralised testing will report on the combined coverage of the main process and all of it's
-subprocesses.
-
-Running centralised testing::
-
- py.test --cov myproj tests/
-
-Shows a terminal report::
-
- -------------------- coverage: platform linux2, python 2.6.4-final-0 ---------------------
- Name Stmts Miss Cover
- ----------------------------------------
- myproj/__init__ 2 0 100%
- myproj/myproj 257 13 94%
- myproj/feature4286 94 7 92%
- ----------------------------------------
- TOTAL 353 20 94%
-
-
-Distributed Testing: Load
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Distributed testing with dist mode set to load will report on the combined coverage of all slaves.
-The slaves may be spread out over any number of hosts and each slave may be located anywhere on the
-file system. Each slave will have it's subprocesses measured.
-
-Running distributed testing with dist mode set to load::
-
- py.test --cov myproj -n 2 tests/
-
-Shows a terminal report::
-
- -------------------- coverage: platform linux2, python 2.6.4-final-0 ---------------------
- Name Stmts Miss Cover
- ----------------------------------------
- myproj/__init__ 2 0 100%
- myproj/myproj 257 13 94%
- myproj/feature4286 94 7 92%
- ----------------------------------------
- TOTAL 353 20 94%
-
-
-Again but spread over different hosts and different directories::
-
- py.test --cov myproj --dist load
- --tx ssh=memedough@host1//chdir=testenv1
- --tx ssh=memedough@host2//chdir=/tmp/testenv2//python=/tmp/env1/bin/python
- --rsyncdir myproj --rsyncdir tests --rsync examples
- tests/
-
-Shows a terminal report::
-
- -------------------- coverage: platform linux2, python 2.6.4-final-0 ---------------------
- Name Stmts Miss Cover
- ----------------------------------------
- myproj/__init__ 2 0 100%
- myproj/myproj 257 13 94%
- myproj/feature4286 94 7 92%
- ----------------------------------------
- TOTAL 353 20 94%
-
-
-Distributed Testing: Each
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Distributed testing with dist mode set to each will report on the combined coverage of all slaves.
-Since each slave is running all tests this allows generating a combined coverage report for multiple
-environments.
-
-Running distributed testing with dist mode set to each::
-
- py.test --cov myproj --dist each
- --tx popen//chdir=/tmp/testenv3//python=/usr/local/python27/bin/python
- --tx ssh=memedough@host2//chdir=/tmp/testenv4//python=/tmp/env2/bin/python
- --rsyncdir myproj --rsyncdir tests --rsync examples
- tests/
-
-Shows a terminal report::
-
- ---------------------------------------- coverage ----------------------------------------
- platform linux2, python 2.6.5-final-0
- platform linux2, python 2.7.0-final-0
- Name Stmts Miss Cover
- ----------------------------------------
- myproj/__init__ 2 0 100%
- myproj/myproj 257 13 94%
- myproj/feature4286 94 7 92%
- ----------------------------------------
- TOTAL 353 20 94%
-
-
-Reporting
----------
-
-It is possible to generate any combination of the reports for a single test run.
-
-The available reports are terminal (with or without missing line numbers shown), HTML, XML and
-annotated source code.
-
-The terminal report without line numbers (default)::
-
- py.test --cov-report term --cov myproj tests/
-
- -------------------- coverage: platform linux2, python 2.6.4-final-0 ---------------------
- Name Stmts Miss Cover
- ----------------------------------------
- myproj/__init__ 2 0 100%
- myproj/myproj 257 13 94%
- myproj/feature4286 94 7 92%
- ----------------------------------------
- TOTAL 353 20 94%
-
-
-The terminal report with line numbers::
-
- py.test --cov-report term-missing --cov myproj tests/
-
- -------------------- coverage: platform linux2, python 2.6.4-final-0 ---------------------
- Name Stmts Miss Cover Missing
- --------------------------------------------------
- myproj/__init__ 2 0 100%
- myproj/myproj 257 13 94% 24-26, 99, 149, 233-236, 297-298, 369-370
- myproj/feature4286 94 7 92% 183-188, 197
- --------------------------------------------------
- TOTAL 353 20 94%
-
-
-The remaining three reports output to files without showing anything on the terminal (useful for
-when the output is going to a continuous integration server)::
-
- py.test --cov-report html --cov-report xml --cov-report annotate --cov myproj tests/
-
-
-Coverage Data File
-------------------
-
-The data file is erased at the beginning of testing to ensure clean data for each test run.
-
-The data file is left at the end of testing so that it is possible to use normal coverage tools to
-examine it.
-
-
-Limitations
------------
-
-For distributed testing the slaves must have the pytest-cov package installed. This is needed since
-the plugin must be registered through setuptools / distribute for pytest to start the plugin on the
-slave.
-
-For subprocess measurement environment variables must make it from the main process to the
-subprocess. The python used by the subprocess must have pytest-cov installed. The subprocess must
-do normal site initialization so that the environment variables can be detected and coverage
-started.
-
-
-Acknowledgments
-----------------
-
-Holger Krekel for pytest with its distributed testing support.
-
-Ned Batchelder for coverage and its ability to combine the coverage results of parallel runs.
-
-Whilst this plugin has been built fresh from the ground up to support distributed testing it has
-been influenced by the work done on pytest-coverage (Ross Lawley, James Mills, Holger Krekel) and
-nose-cover (Jason Pellerin) which are other coverage plugins for pytest and nose respectively.
-
-No doubt others have contributed to these tools as well.
-
-command line options
---------------------
-
-
-``--cov=path``
- measure coverage for filesystem path (multi-allowed)
-``--cov-report=type``
- type of report to generate: term, term-missing, annotate, html, xml (multi-allowed)
-``--cov-config=path``
- config file for coverage, default: .coveragerc
-
-.. include:: links.txt
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/coverage.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/coverage.rst
deleted file mode 100644
index 965b4a4ee07..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/coverage.rst
+++ /dev/null
@@ -1,51 +0,0 @@
-
-Write and report coverage data with the 'coverage' package.
-===========================================================
-
-
-.. contents::
- :local:
-
-Note: Original code by Ross Lawley.
-
-Install
---------------
-
-Use pip to (un)install::
-
- pip install pytest-coverage
- pip uninstall pytest-coverage
-
-or alternatively use easy_install to install::
-
- easy_install pytest-coverage
-
-
-Usage
--------------
-
-To get full test coverage reports for a particular package type::
-
- py.test --cover-report=report
-
-command line options
---------------------
-
-
-``--cover=COVERPACKAGES``
- (multi allowed) only include info from specified package.
-``--cover-report=REPORT_TYPE``
- html: Directory for html output.
- report: Output a text report.
- annotate: Annotate your source code for which lines were executed and which were not.
- xml: Output an xml report compatible with the cobertura plugin for hudson.
-``--cover-directory=DIRECTORY``
- Directory for the reports (html / annotate results) defaults to ./coverage
-``--cover-xml-file=XML_FILE``
- File for the xml report defaults to ./coverage.xml
-``--cover-show-missing``
- Show missing files
-``--cover-ignore-errors=IGNORE_ERRORS``
- Ignore errors of finding source files for code.
-
-.. include:: links.txt
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/figleaf.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/figleaf.rst
deleted file mode 100644
index 86e0da65b6b..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/figleaf.rst
+++ /dev/null
@@ -1,44 +0,0 @@
-
-report test coverage using the 'figleaf' package.
-=================================================
-
-
-.. contents::
- :local:
-
-Install
----------------
-
-To install the plugin issue::
-
- easy_install pytest-figleaf # or
- pip install pytest-figleaf
-
-and if you are using pip you can also uninstall::
-
- pip uninstall pytest-figleaf
-
-
-Usage
----------------
-
-After installation you can simply type::
-
- py.test --figleaf [...]
-
-to enable figleaf coverage in your test run. A default ".figleaf" data file
-and "html" directory will be created. You can use command line options
-to control where data and html files are created.
-
-command line options
---------------------
-
-
-``--figleaf``
- trace python coverage with figleaf and write HTML for files below the current working dir
-``--fig-data=dir``
- set tracing file, default: ".figleaf".
-``--fig-html=dir``
- set html reporting dir, default "html".
-
-.. include:: links.txt
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/genscript.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/genscript.rst
deleted file mode 100644
index ee80f233fa0..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/genscript.rst
+++ /dev/null
@@ -1,28 +0,0 @@
-
-(deprecated) generate standalone test script to be distributed along with an application.
-============================================================================
-
-
-.. contents::
- :local:
-
-
-
-command line options
---------------------
-
-
-``--genscript=path``
- create standalone ``pytest`` script at given target path.
-
-Start improving this plugin in 30 seconds
-=========================================
-
-
-1. Download `pytest_genscript.py`_ plugin source code
-2. put it somewhere as ``pytest_genscript.py`` into your import path
-3. a subsequent ``pytest`` run will use your local version
-
-Checkout customize_, other plugins_ or `get in contact`_.
-
-.. include:: links.txt
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/helpconfig.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/helpconfig.rst
deleted file mode 100644
index 9b5b8cddd9d..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/helpconfig.rst
+++ /dev/null
@@ -1,38 +0,0 @@
-
-provide version info, conftest/environment config names.
-========================================================
-
-
-.. contents::
- :local:
-
-
-
-command line options
---------------------
-
-
-``--version``
- display py lib version and import information.
-``-p name``
- early-load given plugin (multi-allowed).
-``--traceconfig``
- trace considerations of conftest.py files.
-``--nomagic``
- don't reinterpret asserts, no traceback cutting.
-``--debug``
- generate and show internal debugging information.
-``--help-config``
- show available conftest.py and ENV-variable names.
-
-Start improving this plugin in 30 seconds
-=========================================
-
-
-1. Download `pytest_helpconfig.py`_ plugin source code
-2. put it somewhere as ``pytest_helpconfig.py`` into your import path
-3. a subsequent ``pytest`` run will use your local version
-
-Checkout customize_, other plugins_ or `get in contact`_.
-
-.. include:: links.txt
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/links.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/links.rst
deleted file mode 100644
index aa965e73049..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/links.rst
+++ /dev/null
@@ -1,47 +0,0 @@
-.. _`helpconfig`: helpconfig.html
-.. _`pytest_recwarn.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_recwarn.py
-.. _`unittest`: unittest.html
-.. _`pytest_monkeypatch.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_monkeypatch.py
-.. _`pytest_genscript.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_genscript.py
-.. _`pastebin`: pastebin.html
-.. _`skipping`: skipping.html
-.. _`genscript`: genscript.html
-.. _`plugins`: index.html
-.. _`mark`: mark.html
-.. _`tmpdir`: tmpdir.html
-.. _`pytest_doctest.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_doctest.py
-.. _`capture`: capture.html
-.. _`pytest_nose.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_nose.py
-.. _`pytest_restdoc.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_restdoc.py
-.. _`restdoc`: restdoc.html
-.. _`xdist`: xdist.html
-.. _`pytest_pastebin.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_pastebin.py
-.. _`pytest_tmpdir.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_tmpdir.py
-.. _`terminal`: terminal.html
-.. _`pytest_hooklog.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_hooklog.py
-.. _`capturelog`: capturelog.html
-.. _`junitxml`: junitxml.html
-.. _`pytest_skipping.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_skipping.py
-.. _`checkout the pytest development version`: ../../install.html#checkout
-.. _`pytest_helpconfig.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_helpconfig.py
-.. _`oejskit`: oejskit.html
-.. _`doctest`: doctest.html
-.. _`pytest_mark.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_mark.py
-.. _`get in contact`: ../../contact.html
-.. _`pytest_capture.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_capture.py
-.. _`figleaf`: figleaf.html
-.. _`customize`: ../customize.html
-.. _`hooklog`: hooklog.html
-.. _`pytest_terminal.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_terminal.py
-.. _`recwarn`: recwarn.html
-.. _`pytest_pdb.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_pdb.py
-.. _`monkeypatch`: monkeypatch.html
-.. _`coverage`: coverage.html
-.. _`resultlog`: resultlog.html
-.. _`cov`: cov.html
-.. _`pytest_junitxml.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_junitxml.py
-.. _`django`: django.html
-.. _`pytest_unittest.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_unittest.py
-.. _`nose`: nose.html
-.. _`pytest_resultlog.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_resultlog.py
-.. _`pdb`: pdb.html
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/nose.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/nose.rst
deleted file mode 100644
index f3aa7d705f5..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/nose.rst
+++ /dev/null
@@ -1,56 +0,0 @@
-
-nose-compatibility plugin: allow to run nose test suites natively.
-==================================================================
-
-
-.. contents::
- :local:
-
-This is an experimental plugin for allowing to run tests written
-in 'nosetests' style with ``pytest``.
-
-Usage
--------------
-
-type::
-
- py.test # instead of 'nosetests'
-
-and you should be able to run nose style tests and at the same
-time can make full use of pytest's capabilities.
-
-Supported nose Idioms
-----------------------
-
-* setup and teardown at module/class/method level
-* SkipTest exceptions and markers
-* setup/teardown decorators
-* yield-based tests and their setup
-* general usage of nose utilities
-
-Unsupported idioms / issues
-----------------------------------
-
-- nose-style doctests are not collected and executed correctly,
- also fixtures don't work.
-
-- no nose-configuration is recognized
-
-If you find other issues or have suggestions please run::
-
- py.test --pastebin=all
-
-and send the resulting URL to a ``pytest`` contact channel,
-at best to the mailing list.
-
-Start improving this plugin in 30 seconds
-=========================================
-
-
-1. Download `pytest_nose.py`_ plugin source code
-2. put it somewhere as ``pytest_nose.py`` into your import path
-3. a subsequent ``pytest`` run will use your local version
-
-Checkout customize_, other plugins_ or `get in contact`_.
-
-.. include:: links.txt
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/terminal.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/terminal.rst
deleted file mode 100644
index 214c24dfccd..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/terminal.rst
+++ /dev/null
@@ -1,40 +0,0 @@
-
-Implements terminal reporting of the full testing process.
-==========================================================
-
-
-.. contents::
- :local:
-
-This is a good source for looking at the various reporting hooks.
-
-command line options
---------------------
-
-
-``-v, --verbose``
- increase verbosity.
-``-r chars``
- show extra test summary info as specified by chars (f)ailed, (s)skipped, (x)failed, (X)passed.
-``-l, --showlocals``
- show locals in tracebacks (disabled by default).
-``--report=opts``
- (deprecated, use -r)
-``--tb=style``
- traceback print mode (long/short/line/no).
-``--fulltrace``
- don't cut any tracebacks (default is to cut).
-``--fixtures``
- show available function arguments, sorted by plugin
-
-Start improving this plugin in 30 seconds
-=========================================
-
-
-1. Download `pytest_terminal.py`_ plugin source code
-2. put it somewhere as ``pytest_terminal.py`` into your import path
-3. a subsequent ``pytest`` run will use your local version
-
-Checkout customize_, other plugins_ or `get in contact`_.
-
-.. include:: links.txt
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/xdist.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/xdist.rst
deleted file mode 100644
index 7ab6cdc8b83..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/xdist.rst
+++ /dev/null
@@ -1,172 +0,0 @@
-
-loop on failing tests, distribute test runs to CPUs and hosts.
-==============================================================
-
-
-.. contents::
- :local:
-
-The `pytest-xdist`_ plugin extends ``pytest`` with some unique
-test execution modes:
-
-* Looponfail: run your tests repeatedly in a subprocess. After each run
- ``pytest`` waits until a file in your project changes and then re-runs the
- previously failing tests. This is repeated until all tests pass after which
- again a full run is performed.
-
-* Load-balancing: if you have multiple CPUs or hosts you can use
- those for a combined test run. This allows to speed up
- development or to use special resources of remote machines.
-
-* Multi-Platform coverage: you can specify different Python interpreters
- or different platforms and run tests in parallel on all of them.
-
-Before running tests remotely, ``pytest`` efficiently synchronizes your
-program source code to the remote place. All test results
-are reported back and displayed to your local test session.
-You may specify different Python versions and interpreters.
-
-.. _`pytest-xdist`: http://pypi.python.org/pypi/pytest-xdist
-
-Usage examples
----------------------
-
-Speed up test runs by sending tests to multiple CPUs
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-To send tests to multiple CPUs, type::
-
- py.test -n NUM
-
-Especially for longer running tests or tests requiring
-a lot of IO this can lead to considerable speed ups.
-
-
-Running tests in a Python subprocess
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-To instantiate a python2.4 sub process and send tests to it, you may type::
-
- py.test -d --tx popen//python=python2.4
-
-This will start a subprocess which is run with the "python2.4"
-Python interpreter, found in your system binary lookup path.
-
-If you prefix the --tx option value like this::
-
- --tx 3*popen//python=python2.4
-
-then three subprocesses would be created and tests
-will be load-balanced across these three processes.
-
-
-Sending tests to remote SSH accounts
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-Suppose you have a package ``mypkg`` which contains some
-tests that you can successfully run locally. And you
-have a ssh-reachable machine ``myhost``. Then
-you can ad-hoc distribute your tests by typing::
-
- py.test -d --tx ssh=myhostpopen --rsyncdir mypkg mypkg
-
-This will synchronize your ``mypkg`` package directory
-to an remote ssh account and then locally collect tests
-and send them to remote places for execution.
-
-You can specify multiple ``--rsyncdir`` directories
-to be sent to the remote side.
-
-**NOTE:** For ``pytest`` to collect and send tests correctly
-you not only need to make sure all code and tests
-directories are rsynced, but that any test (sub) directory
-also has an ``__init__.py`` file because internally
-``pytest`` references tests using their fully qualified python
-module path. **You will otherwise get strange errors**
-during setup of the remote side.
-
-Sending tests to remote Socket Servers
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-Download the single-module `socketserver.py`_ Python program
-and run it like this::
-
- python socketserver.py
-
-It will tell you that it starts listening on the default
-port. You can now on your home machine specify this
-new socket host with something like this::
-
- py.test -d --tx socket=192.168.1.102:8888 --rsyncdir mypkg mypkg
-
-
-.. _`atonce`:
-
-Running tests on many platforms at once
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-The basic command to run tests on multiple platforms is::
-
- py.test --dist=each --tx=spec1 --tx=spec2
-
-If you specify a windows host, an OSX host and a Linux
-environment this command will send each tests to all
-platforms - and report back failures from all platforms
-at once. The specifications strings use the `xspec syntax`_.
-
-.. _`xspec syntax`: http://codespeak.net/execnet/trunk/basics.html#xspec
-
-.. _`socketserver.py`: http://codespeak.net/svn/py/dist/py/execnet/script/socketserver.py
-
-.. _`execnet`: http://codespeak.net/execnet
-
-Specifying test exec environments in a conftest.py
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-Instead of specifying command line options, you can
-put options values in a ``conftest.py`` file like this::
-
- option_tx = ['ssh=myhost//python=python2.7', 'popen//python=python2.7']
- option_dist = True
-
-Any commandline ``--tx`` specifications will add to the list of
-available execution environments.
-
-Specifying "rsync" dirs in a conftest.py
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-In your ``mypkg/conftest.py`` you may specify directories to synchronise
-or to exclude::
-
- rsyncdirs = ['.', '../plugins']
- rsyncignore = ['_cache']
-
-These directory specifications are relative to the directory
-where the ``conftest.py`` is found.
-
-command line options
---------------------
-
-
-``-f, --looponfail``
- run tests in subprocess, wait for modified files and re-run failing test set until all pass.
-``-n numprocesses``
- shortcut for '--dist=load --tx=NUM*popen'
-``--boxed``
- box each test run in a separate process (unix)
-``--dist=distmode``
- set mode for distributing tests to exec environments.
-
- each: send each test to each available environment.
-
- load: send each test to one available environment so it is run only once.
-
- (default) no: run tests inprocess, don't distribute.
-``--tx=xspec``
- add a test execution environment. some examples: --tx popen//python=python2.7 --tx socket=192.168.1.102:8888 --tx ssh=user@codespeak.net//chdir=testcache
-``-d``
- load-balance tests. shortcut for '--dist=load'
-``--rsyncdir=dir1``
- add directory for rsyncing to remote tx nodes.
-
-.. include:: links.txt
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/tmpdir.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/tmpdir.rst
deleted file mode 100644
index f8935b8cef8..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/tmpdir.rst
+++ /dev/null
@@ -1,111 +0,0 @@
-
-.. _`tmpdir handling`:
-.. _tmpdir:
-
-Temporary directories and files
-================================================
-
-The 'tmpdir' fixture
---------------------
-
-You can use the ``tmpdir`` fixture which will
-provide a temporary directory unique to the test invocation,
-created in the `base temporary directory`_.
-
-``tmpdir`` is a `py.path.local`_ object which offers ``os.path`` methods
-and more. Here is an example test usage::
-
- # content of test_tmpdir.py
- import os
- def test_create_file(tmpdir):
- p = tmpdir.mkdir("sub").join("hello.txt")
- p.write("content")
- assert p.read() == "content"
- assert len(tmpdir.listdir()) == 1
- assert 0
-
-Running this would result in a passed test except for the last
-``assert 0`` line which we use to look at values::
-
- $ py.test test_tmpdir.py
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 1 items
-
- test_tmpdir.py F
-
- ======= FAILURES ========
- _______ test_create_file ________
-
- tmpdir = local('PYTEST_TMPDIR/test_create_file0')
-
- def test_create_file(tmpdir):
- p = tmpdir.mkdir("sub").join("hello.txt")
- p.write("content")
- assert p.read() == "content"
- assert len(tmpdir.listdir()) == 1
- > assert 0
- E assert 0
-
- test_tmpdir.py:7: AssertionError
- ======= 1 failed in 0.12 seconds ========
-
-The 'tmpdir_factory' fixture
-----------------------------
-
-.. versionadded:: 2.8
-
-The ``tmpdir_factory`` is a session-scoped fixture which can be used
-to create arbitrary temporary directories from any other fixture or test.
-
-For example, suppose your test suite needs a large image on disk, which is
-generated procedurally. Instead of computing the same image for each test
-that uses it into its own ``tmpdir``, you can generate it once per-session
-to save time:
-
-.. code-block:: python
-
- # contents of conftest.py
- import pytest
-
- @pytest.fixture(scope='session')
- def image_file(tmpdir_factory):
- img = compute_expensive_image()
- fn = tmpdir_factory.mktemp('data').join('img.png')
- img.save(str(fn))
- return fn
-
- # contents of test_image.py
- def test_histogram(image_file):
- img = load_image(image_file)
- # compute and test histogram
-
-``tmpdir_factory`` instances have the following methods:
-
-.. currentmodule:: _pytest.tmpdir
-
-.. automethod:: TempdirFactory.mktemp
-.. automethod:: TempdirFactory.getbasetemp
-
-.. _`base temporary directory`:
-
-The default base temporary directory
------------------------------------------------
-
-Temporary directories are by default created as sub-directories of
-the system temporary directory. The base name will be ``pytest-NUM`` where
-``NUM`` will be incremented with each test run. Moreover, entries older
-than 3 temporary directories will be removed.
-
-You can override the default temporary directory setting like this::
-
- py.test --basetemp=mydir
-
-When distributing tests on the local machine, ``pytest`` takes care to
-configure a basetemp directory for the sub processes such that all temporary
-data lands below a single per-test run basetemp directory.
-
-.. _`py.path.local`: http://py.rtfd.org/en/latest/path.html
-
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/unittest.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/unittest.rst
deleted file mode 100644
index ce99bd11867..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/unittest.rst
+++ /dev/null
@@ -1,190 +0,0 @@
-
-.. _`unittest.TestCase`:
-
-Support for unittest.TestCase / Integration of fixtures
-=====================================================================
-
-.. _`unittest.py style`: http://docs.python.org/library/unittest.html
-
-``pytest`` has support for running Python `unittest.py style`_ tests.
-It's meant for leveraging existing unittest-style projects
-to use pytest features. Concretely, pytest will automatically
-collect ``unittest.TestCase`` subclasses and their ``test`` methods in
-test files. It will invoke typical setup/teardown methods and
-generally try to make test suites written to run on unittest, to also
-run using ``pytest``. We assume here that you are familiar with writing
-``unittest.TestCase`` style tests and rather focus on
-integration aspects.
-
-Usage
--------------------------------------------------------------------
-
-After :ref:`installation` type::
-
- py.test
-
-and you should be able to run your unittest-style tests if they
-are contained in ``test_*`` modules. If that works for you then
-you can make use of most :ref:`pytest features <features>`, for example
-``--pdb`` debugging in failures, using :ref:`plain assert-statements <assert>`,
-:ref:`more informative tracebacks <tbreportdemo>`, stdout-capturing or
-distributing tests to multiple CPUs via the ``-nNUM`` option if you
-installed the ``pytest-xdist`` plugin. Please refer to
-the general ``pytest`` documentation for many more examples.
-
-Mixing pytest fixtures into unittest.TestCase style tests
------------------------------------------------------------
-
-Running your unittest with ``pytest`` allows you to use its
-:ref:`fixture mechanism <fixture>` with ``unittest.TestCase`` style
-tests. Assuming you have at least skimmed the pytest fixture features,
-let's jump-start into an example that integrates a pytest ``db_class``
-fixture, setting up a class-cached database object, and then reference
-it from a unittest-style test::
-
- # content of conftest.py
-
- # we define a fixture function below and it will be "used" by
- # referencing its name from tests
-
- import pytest
-
- @pytest.fixture(scope="class")
- def db_class(request):
- class DummyDB:
- pass
- # set a class attribute on the invoking test context
- request.cls.db = DummyDB()
-
-This defines a fixture function ``db_class`` which - if used - is
-called once for each test class and which sets the class-level
-``db`` attribute to a ``DummyDB`` instance. The fixture function
-achieves this by receiving a special ``request`` object which gives
-access to :ref:`the requesting test context <request-context>` such
-as the ``cls`` attribute, denoting the class from which the fixture
-is used. This architecture de-couples fixture writing from actual test
-code and allows re-use of the fixture by a minimal reference, the fixture
-name. So let's write an actual ``unittest.TestCase`` class using our
-fixture definition::
-
- # content of test_unittest_db.py
-
- import unittest
- import pytest
-
- @pytest.mark.usefixtures("db_class")
- class MyTest(unittest.TestCase):
- def test_method1(self):
- assert hasattr(self, "db")
- assert 0, self.db # fail for demo purposes
-
- def test_method2(self):
- assert 0, self.db # fail for demo purposes
-
-The ``@pytest.mark.usefixtures("db_class")`` class-decorator makes sure that
-the pytest fixture function ``db_class`` is called once per class.
-Due to the deliberately failing assert statements, we can take a look at
-the ``self.db`` values in the traceback::
-
- $ py.test test_unittest_db.py
- ======= test session starts ========
- platform linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
- rootdir: $REGENDOC_TMPDIR, inifile:
- collected 2 items
-
- test_unittest_db.py FF
-
- ======= FAILURES ========
- _______ MyTest.test_method1 ________
-
- self = <test_unittest_db.MyTest testMethod=test_method1>
-
- def test_method1(self):
- assert hasattr(self, "db")
- > assert 0, self.db # fail for demo purposes
- E AssertionError: <conftest.db_class.<locals>.DummyDB object at 0xdeadbeef>
- E assert 0
-
- test_unittest_db.py:9: AssertionError
- _______ MyTest.test_method2 ________
-
- self = <test_unittest_db.MyTest testMethod=test_method2>
-
- def test_method2(self):
- > assert 0, self.db # fail for demo purposes
- E AssertionError: <conftest.db_class.<locals>.DummyDB object at 0xdeadbeef>
- E assert 0
-
- test_unittest_db.py:12: AssertionError
- ======= 2 failed in 0.12 seconds ========
-
-This default pytest traceback shows that the two test methods
-share the same ``self.db`` instance which was our intention
-when writing the class-scoped fixture function above.
-
-
-autouse fixtures and accessing other fixtures
--------------------------------------------------------------------
-
-Although it's usually better to explicitly declare use of fixtures you need
-for a given test, you may sometimes want to have fixtures that are
-automatically used in a given context. After all, the traditional
-style of unittest-setup mandates the use of this implicit fixture writing
-and chances are, you are used to it or like it.
-
-You can flag fixture functions with ``@pytest.fixture(autouse=True)``
-and define the fixture function in the context where you want it used.
-Let's look at an ``initdir`` fixture which makes all test methods of a
-``TestCase`` class execute in a temporary directory with a
-pre-initialized ``samplefile.ini``. Our ``initdir`` fixture itself uses
-the pytest builtin :ref:`tmpdir <tmpdir>` fixture to delegate the
-creation of a per-test temporary directory::
-
- # content of test_unittest_cleandir.py
- import pytest
- import unittest
-
- class MyTest(unittest.TestCase):
- @pytest.fixture(autouse=True)
- def initdir(self, tmpdir):
- tmpdir.chdir() # change to pytest-provided temporary directory
- tmpdir.join("samplefile.ini").write("# testdata")
-
- def test_method(self):
- s = open("samplefile.ini").read()
- assert "testdata" in s
-
-Due to the ``autouse`` flag the ``initdir`` fixture function will be
-used for all methods of the class where it is defined. This is a
-shortcut for using a ``@pytest.mark.usefixtures("initdir")`` marker
-on the class like in the previous example.
-
-Running this test module ...::
-
- $ py.test -q test_unittest_cleandir.py
- .
- 1 passed in 0.12 seconds
-
-... gives us one passed test because the ``initdir`` fixture function
-was executed ahead of the ``test_method``.
-
-.. note::
-
- While pytest supports receiving fixtures via :ref:`test function arguments <funcargs>` for non-unittest test methods, ``unittest.TestCase`` methods cannot directly receive fixture
- function arguments as implementing that is likely to inflict
- on the ability to run general unittest.TestCase test suites.
- Maybe optional support would be possible, though. If unittest finally
- grows a plugin system that should help as well. In the meanwhile, the
- above ``usefixtures`` and ``autouse`` examples should help to mix in
- pytest fixtures into unittest suites. And of course you can also start
- to selectively leave away the ``unittest.TestCase`` subclassing, use
- plain asserts and get the unlimited pytest feature set.
-
-
-Converting from unittest to pytest
----------------------------------------
-
-If you want to convert your unittest testcases to pytest, there are
-some helpers like `unittest2pytest
-<https://pypi.python.org/pypi/unittest2pytest/>`__, which uses lib2to3
-and introspection for the transformation.
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/usage.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/usage.rst
deleted file mode 100644
index 4b92fd1e150..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/usage.rst
+++ /dev/null
@@ -1,275 +0,0 @@
-
-.. _usage:
-
-Usage and Invocations
-==========================================
-
-
-.. _cmdline:
-
-Calling pytest through ``python -m pytest``
------------------------------------------------------
-
-.. versionadded:: 2.0
-
-You can invoke testing through the Python interpreter from the command line::
-
- python -m pytest [...]
-
-This is equivalent to invoking the command line script ``py.test [...]``
-directly.
-
-Getting help on version, option names, environment variables
---------------------------------------------------------------
-
-::
-
- py.test --version # shows where pytest was imported from
- py.test --fixtures # show available builtin function arguments
- py.test -h | --help # show help on command line and config file options
-
-
-Stopping after the first (or N) failures
----------------------------------------------------
-
-To stop the testing process after the first (N) failures::
-
- py.test -x # stop after first failure
- py.test --maxfail=2 # stop after two failures
-
-Specifying tests / selecting tests
----------------------------------------------------
-
-Several test run options::
-
- py.test test_mod.py # run tests in module
- py.test somepath # run all tests below somepath
- py.test -k stringexpr # only run tests with names that match the
- # "string expression", e.g. "MyClass and not method"
- # will select TestMyClass.test_something
- # but not TestMyClass.test_method_simple
- py.test test_mod.py::test_func # only run tests that match the "node ID",
- # e.g "test_mod.py::test_func" will select
- # only test_func in test_mod.py
- py.test test_mod.py::TestClass::test_method # run a single method in
- # a single class
-
-Import 'pkg' and use its filesystem location to find and run tests::
-
- py.test --pyargs pkg # run all tests found below directory of pypkg
-
-Modifying Python traceback printing
-----------------------------------------------
-
-Examples for modifying traceback printing::
-
- py.test --showlocals # show local variables in tracebacks
- py.test -l # show local variables (shortcut)
-
- py.test --tb=auto # (default) 'long' tracebacks for the first and last
- # entry, but 'short' style for the other entries
- py.test --tb=long # exhaustive, informative traceback formatting
- py.test --tb=short # shorter traceback format
- py.test --tb=line # only one line per failure
- py.test --tb=native # Python standard library formatting
- py.test --tb=no # no traceback at all
-
-Dropping to PDB_ (Python Debugger) on failures
------------------------------------------------
-
-.. _PDB: http://docs.python.org/library/pdb.html
-
-Python comes with a builtin Python debugger called PDB_. ``pytest``
-allows one to drop into the PDB_ prompt via a command line option::
-
- py.test --pdb
-
-This will invoke the Python debugger on every failure. Often you might
-only want to do this for the first failing test to understand a certain
-failure situation::
-
- py.test -x --pdb # drop to PDB on first failure, then end test session
- py.test --pdb --maxfail=3 # drop to PDB for first three failures
-
-Note that on any failure the exception information is stored on
-``sys.last_value``, ``sys.last_type`` and ``sys.last_traceback``. In
-interactive use, this allows one to drop into postmortem debugging with
-any debug tool. One can also manually access the exception information,
-for example::
-
- >>> import sys
- >>> sys.last_traceback.tb_lineno
- 42
- >>> sys.last_value
- AssertionError('assert result == "ok"',)
-
-Setting a breakpoint / aka ``set_trace()``
-----------------------------------------------------
-
-If you want to set a breakpoint and enter the ``pdb.set_trace()`` you
-can use a helper::
-
- import pytest
- def test_function():
- ...
- pytest.set_trace() # invoke PDB debugger and tracing
-
-.. versionadded: 2.0.0
-
-Prior to pytest version 2.0.0 you could only enter PDB_ tracing if you disabled
-capturing on the command line via ``py.test -s``. In later versions, pytest
-automatically disables its output capture when you enter PDB_ tracing:
-
-* Output capture in other tests is not affected.
-* Any prior test output that has already been captured and will be processed as
- such.
-* Any later output produced within the same test will not be captured and will
- instead get sent directly to ``sys.stdout``. Note that this holds true even
- for test output occurring after you exit the interactive PDB_ tracing session
- and continue with the regular test run.
-
-.. versionadded: 2.4.0
-
-Since pytest version 2.4.0 you can also use the native Python
-``import pdb;pdb.set_trace()`` call to enter PDB_ tracing without having to use
-the ``pytest.set_trace()`` wrapper or explicitly disable pytest's output
-capturing via ``py.test -s``.
-
-.. _durations:
-
-Profiling test execution duration
--------------------------------------
-
-.. versionadded: 2.2
-
-To get a list of the slowest 10 test durations::
-
- py.test --durations=10
-
-
-Creating JUnitXML format files
-----------------------------------------------------
-
-To create result files which can be read by Hudson_ or other Continuous
-integration servers, use this invocation::
-
- py.test --junitxml=path
-
-to create an XML file at ``path``.
-
-record_xml_property
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-.. versionadded:: 2.8
-
-If you want to log additional information for a test, you can use the
-``record_xml_property`` fixture:
-
-.. code-block:: python
-
- def test_function(record_xml_property):
- record_xml_property("example_key", 1)
- assert 0
-
-This will add an extra property ``example_key="1"`` to the generated
-``testcase`` tag:
-
-.. code-block:: xml
-
- <testcase classname="test_function" file="test_function.py" line="0" name="test_function" time="0.0009">
- <properties>
- <property name="example_key" value="1" />
- </properties>
- </testcase>
-
-.. warning::
-
- This is an experimental feature, and its interface might be replaced
- by something more powerful and general in future versions. The
- functionality per-se will be kept, however.
-
- Currently it does not work when used with the ``pytest-xdist`` plugin.
-
- Also please note that using this feature will break any schema verification.
- This might be a problem when used with some CI servers.
-
-Creating resultlog format files
-----------------------------------------------------
-
-To create plain-text machine-readable result files you can issue::
-
- py.test --resultlog=path
-
-and look at the content at the ``path`` location. Such files are used e.g.
-by the `PyPy-test`_ web page to show test results over several revisions.
-
-.. _`PyPy-test`: http://buildbot.pypy.org/summary
-
-
-Sending test report to online pastebin service
------------------------------------------------------
-
-**Creating a URL for each test failure**::
-
- py.test --pastebin=failed
-
-This will submit test run information to a remote Paste service and
-provide a URL for each failure. You may select tests as usual or add
-for example ``-x`` if you only want to send one particular failure.
-
-**Creating a URL for a whole test session log**::
-
- py.test --pastebin=all
-
-Currently only pasting to the http://bpaste.net service is implemented.
-
-Disabling plugins
------------------
-
-To disable loading specific plugins at invocation time, use the ``-p`` option
-together with the prefix ``no:``.
-
-Example: to disable loading the plugin ``doctest``, which is responsible for
-executing doctest tests from text files, invoke py.test like this::
-
- py.test -p no:doctest
-
-.. _`pytest.main-usage`:
-
-Calling pytest from Python code
-----------------------------------------------------
-
-.. versionadded:: 2.0
-
-You can invoke ``pytest`` from Python code directly::
-
- pytest.main()
-
-this acts as if you would call "py.test" from the command line.
-It will not raise ``SystemExit`` but return the exitcode instead.
-You can pass in options and arguments::
-
- pytest.main(['-x', 'mytestdir'])
-
-or pass in a string::
-
- pytest.main("-x mytestdir")
-
-You can specify additional plugins to ``pytest.main``::
-
- # content of myinvoke.py
- import pytest
- class MyPlugin:
- def pytest_sessionfinish(self):
- print("*** test run reporting finishing")
-
- pytest.main("-qq", plugins=[MyPlugin()])
-
-Running it will show that ``MyPlugin`` was added and its
-hook was invoked::
-
- $ python myinvoke.py
- *** test run reporting finishing
-
-
-.. include:: links.inc
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/writing_plugins.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/writing_plugins.rst
deleted file mode 100644
index cc346aaa85c..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/writing_plugins.rst
+++ /dev/null
@@ -1,575 +0,0 @@
-.. _plugins:
-.. _`writing-plugins`:
-
-Writing plugins
-===============
-
-It is easy to implement `local conftest plugins`_ for your own project
-or `pip-installable plugins`_ that can be used throughout many projects,
-including third party projects. Please refer to :ref:`using plugins` if you
-only want to use but not write plugins.
-
-A plugin contains one or multiple hook functions. :ref:`Writing hooks <writinghooks>`
-explains the basics and details of how you can write a hook function yourself.
-``pytest`` implements all aspects of configuration, collection, running and
-reporting by calling `well specified hooks`_ of the following plugins:
-
-* :ref:`builtin plugins`: loaded from pytest's internal ``_pytest`` directory.
-
-* :ref:`external plugins <extplugins>`: modules discovered through
- `setuptools entry points`_
-
-* `conftest.py plugins`_: modules auto-discovered in test directories
-
-In principle, each hook call is a ``1:N`` Python function call where ``N`` is the
-number of registered implementation functions for a given specification.
-All specifications and implementations following the ``pytest_`` prefix
-naming convention, making them easy to distinguish and find.
-
-.. _`pluginorder`:
-
-Plugin discovery order at tool startup
---------------------------------------
-
-``pytest`` loads plugin modules at tool startup in the following way:
-
-* by loading all builtin plugins
-
-* by loading all plugins registered through `setuptools entry points`_.
-
-* by pre-scanning the command line for the ``-p name`` option
- and loading the specified plugin before actual command line parsing.
-
-* by loading all :file:`conftest.py` files as inferred by the command line
- invocation:
-
- - if no test paths are specified use current dir as a test path
- - if exists, load ``conftest.py`` and ``test*/conftest.py`` relative
- to the directory part of the first test path.
-
- Note that pytest does not find ``conftest.py`` files in deeper nested
- sub directories at tool startup. It is usually a good idea to keep
- your conftest.py file in the top level test or project root directory.
-
-* by recursively loading all plugins specified by the
- ``pytest_plugins`` variable in ``conftest.py`` files
-
-
-.. _`pytest/plugin`: http://bitbucket.org/pytest-dev/pytest/src/tip/pytest/plugin/
-.. _`conftest.py plugins`:
-.. _`conftest.py`:
-.. _`localplugin`:
-.. _`conftest`:
-.. _`local conftest plugins`:
-
-conftest.py: local per-directory plugins
-----------------------------------------
-
-Local ``conftest.py`` plugins contain directory-specific hook
-implementations. Hook Session and test running activities will
-invoke all hooks defined in ``conftest.py`` files closer to the
-root of the filesystem. Example of implementing the
-``pytest_runtest_setup`` hook so that is called for tests in the ``a``
-sub directory but not for other directories::
-
- a/conftest.py:
- def pytest_runtest_setup(item):
- # called for running each test in 'a' directory
- print ("setting up", item)
-
- a/test_sub.py:
- def test_sub():
- pass
-
- test_flat.py:
- def test_flat():
- pass
-
-Here is how you might run it::
-
- py.test test_flat.py # will not show "setting up"
- py.test a/test_sub.py # will show "setting up"
-
-.. Note::
- If you have ``conftest.py`` files which do not reside in a
- python package directory (i.e. one containing an ``__init__.py``) then
- "import conftest" can be ambiguous because there might be other
- ``conftest.py`` files as well on your PYTHONPATH or ``sys.path``.
- It is thus good practice for projects to either put ``conftest.py``
- under a package scope or to never import anything from a
- conftest.py file.
-
-
-Writing your own plugin
------------------------
-
-.. _`setuptools`: http://pypi.python.org/pypi/setuptools
-
-If you want to write a plugin, there are many real-life examples
-you can copy from:
-
-* a custom collection example plugin: :ref:`yaml plugin`
-* around 20 :ref:`builtin plugins` which provide pytest's own functionality
-* many `external plugins <http://plugincompat.herokuapp.com>`_ providing additional features
-
-All of these plugins implement the documented `well specified hooks`_
-to extend and add functionality.
-
-.. note::
- Make sure to check out the excellent
- `cookiecutter-pytest-plugin <https://github.com/pytest-dev/cookiecutter-pytest-plugin>`_
- project, which is a `cookiecutter template <https://github.com/audreyr/cookiecutter>`_
- for authoring plugins.
-
- The template provides an excellent starting point with a working plugin,
- tests running with tox, comprehensive README and
- entry-pointy already pre-configured.
-
-Also consider :ref:`contributing your plugin to pytest-dev<submitplugin>`
-once it has some happy users other than yourself.
-
-
-.. _`setuptools entry points`:
-.. _`pip-installable plugins`:
-
-Making your plugin installable by others
-----------------------------------------
-
-If you want to make your plugin externally available, you
-may define a so-called entry point for your distribution so
-that ``pytest`` finds your plugin module. Entry points are
-a feature that is provided by `setuptools`_. pytest looks up
-the ``pytest11`` entrypoint to discover its
-plugins and you can thus make your plugin available by defining
-it in your setuptools-invocation:
-
-.. sourcecode:: python
-
- # sample ./setup.py file
- from setuptools import setup
-
- setup(
- name="myproject",
- packages = ['myproject']
-
- # the following makes a plugin available to pytest
- entry_points = {
- 'pytest11': [
- 'name_of_plugin = myproject.pluginmodule',
- ]
- },
- )
-
-If a package is installed this way, ``pytest`` will load
-``myproject.pluginmodule`` as a plugin which can define
-`well specified hooks`_.
-
-
-
-
-Requiring/Loading plugins in a test module or conftest file
------------------------------------------------------------
-
-You can require plugins in a test module or a conftest file like this::
-
- pytest_plugins = "name1", "name2",
-
-When the test module or conftest plugin is loaded the specified plugins
-will be loaded as well. You can also use dotted path like this::
-
- pytest_plugins = "myapp.testsupport.myplugin"
-
-which will import the specified module as a ``pytest`` plugin.
-
-
-Accessing another plugin by name
---------------------------------
-
-If a plugin wants to collaborate with code from
-another plugin it can obtain a reference through
-the plugin manager like this:
-
-.. sourcecode:: python
-
- plugin = config.pluginmanager.getplugin("name_of_plugin")
-
-If you want to look at the names of existing plugins, use
-the ``--traceconfig`` option.
-
-Testing plugins
----------------
-
-pytest comes with some facilities that you can enable for testing your
-plugin. Given that you have an installed plugin you can enable the
-:py:class:`testdir <_pytest.pytester.Testdir>` fixture via specifying a
-command line option to include the pytester plugin (``-p pytester``) or
-by putting ``pytest_plugins = "pytester"`` into your test or
-``conftest.py`` file. You then will have a ``testdir`` fixture which you
-can use like this::
-
- # content of test_myplugin.py
-
- pytest_plugins = "pytester" # to get testdir fixture
-
- def test_myplugin(testdir):
- testdir.makepyfile("""
- def test_example():
- pass
- """)
- result = testdir.runpytest("--verbose")
- result.fnmatch_lines("""
- test_example*
- """)
-
-Note that by default ``testdir.runpytest()`` will perform a pytest
-in-process. You can pass the command line option ``--runpytest=subprocess``
-to have it happen in a subprocess.
-
-Also see the :py:class:`RunResult <_pytest.pytester.RunResult>` for more
-methods of the result object that you get from a call to ``runpytest``.
-
-.. _`writinghooks`:
-
-Writing hook functions
-======================
-
-
-.. _validation:
-
-hook function validation and execution
---------------------------------------
-
-pytest calls hook functions from registered plugins for any
-given hook specification. Let's look at a typical hook function
-for the ``pytest_collection_modifyitems(session, config,
-items)`` hook which pytest calls after collection of all test items is
-completed.
-
-When we implement a ``pytest_collection_modifyitems`` function in our plugin
-pytest will during registration verify that you use argument
-names which match the specification and bail out if not.
-
-Let's look at a possible implementation:
-
-.. code-block:: python
-
- def pytest_collection_modifyitems(config, items):
- # called after collection is completed
- # you can modify the ``items`` list
-
-Here, ``pytest`` will pass in ``config`` (the pytest config object)
-and ``items`` (the list of collected test items) but will not pass
-in the ``session`` argument because we didn't list it in the function
-signature. This dynamic "pruning" of arguments allows ``pytest`` to
-be "future-compatible": we can introduce new hook named parameters without
-breaking the signatures of existing hook implementations. It is one of
-the reasons for the general long-lived compatibility of pytest plugins.
-
-Note that hook functions other than ``pytest_runtest_*`` are not
-allowed to raise exceptions. Doing so will break the pytest run.
-
-
-
-firstresult: stop at first non-None result
--------------------------------------------
-
-Most calls to ``pytest`` hooks result in a **list of results** which contains
-all non-None results of the called hook functions.
-
-Some hook specifications use the ``firstresult=True`` option so that the hook
-call only executes until the first of N registered functions returns a
-non-None result which is then taken as result of the overall hook call.
-The remaining hook functions will not be called in this case.
-
-
-hookwrapper: executing around other hooks
--------------------------------------------------
-
-.. currentmodule:: _pytest.core
-
-.. versionadded:: 2.7 (experimental)
-
-pytest plugins can implement hook wrappers which wrap the execution
-of other hook implementations. A hook wrapper is a generator function
-which yields exactly once. When pytest invokes hooks it first executes
-hook wrappers and passes the same arguments as to the regular hooks.
-
-At the yield point of the hook wrapper pytest will execute the next hook
-implementations and return their result to the yield point in the form of
-a :py:class:`CallOutcome` instance which encapsulates a result or
-exception info. The yield point itself will thus typically not raise
-exceptions (unless there are bugs).
-
-Here is an example definition of a hook wrapper::
-
- import pytest
-
- @pytest.hookimpl(hookwrapper=True)
- def pytest_pyfunc_call(pyfuncitem):
- # do whatever you want before the next hook executes
-
- outcome = yield
- # outcome.excinfo may be None or a (cls, val, tb) tuple
-
- res = outcome.get_result() # will raise if outcome was exception
- # postprocess result
-
-Note that hook wrappers don't return results themselves, they merely
-perform tracing or other side effects around the actual hook implementations.
-If the result of the underlying hook is a mutable object, they may modify
-that result but it's probably better to avoid it.
-
-
-Hook function ordering / call example
--------------------------------------
-
-For any given hook specification there may be more than one
-implementation and we thus generally view ``hook`` execution as a
-``1:N`` function call where ``N`` is the number of registered functions.
-There are ways to influence if a hook implementation comes before or
-after others, i.e. the position in the ``N``-sized list of functions:
-
-.. code-block:: python
-
- # Plugin 1
- @pytest.hookimpl(tryfirst=True)
- def pytest_collection_modifyitems(items):
- # will execute as early as possible
-
- # Plugin 2
- @pytest.hookimpl(trylast=True)
- def pytest_collection_modifyitems(items):
- # will execute as late as possible
-
- # Plugin 3
- @pytest.hookimpl(hookwrapper=True)
- def pytest_collection_modifyitems(items):
- # will execute even before the tryfirst one above!
- outcome = yield
- # will execute after all non-hookwrappers executed
-
-Here is the order of execution:
-
-1. Plugin3's pytest_collection_modifyitems called until the yield point
- because it is a hook wrapper.
-
-2. Plugin1's pytest_collection_modifyitems is called because it is marked
- with ``tryfirst=True``.
-
-3. Plugin2's pytest_collection_modifyitems is called because it is marked
- with ``trylast=True`` (but even without this mark it would come after
- Plugin1).
-
-4. Plugin3's pytest_collection_modifyitems then executing the code after the yield
- point. The yield receives a :py:class:`CallOutcome` instance which encapsulates
- the result from calling the non-wrappers. Wrappers shall not modify the result.
-
-It's possible to use ``tryfirst`` and ``trylast`` also in conjunction with
-``hookwrapper=True`` in which case it will influence the ordering of hookwrappers
-among each other.
-
-
-Declaring new hooks
-------------------------
-
-.. currentmodule:: _pytest.hookspec
-
-Plugins and ``conftest.py`` files may declare new hooks that can then be
-implemented by other plugins in order to alter behaviour or interact with
-the new plugin:
-
-.. autofunction:: pytest_addhooks
-
-Hooks are usually declared as do-nothing functions that contain only
-documentation describing when the hook will be called and what return values
-are expected.
-
-For an example, see `newhooks.py`_ from :ref:`xdist`.
-
-.. _`newhooks.py`: https://github.com/pytest-dev/pytest-xdist/blob/974bd566c599dc6a9ea291838c6f226197208b46/xdist/newhooks.py
-
-
-Optionally using hooks from 3rd party plugins
----------------------------------------------
-
-Using new hooks from plugins as explained above might be a little tricky
-because of the standard :ref:`validation mechanism <validation>`:
-if you depend on a plugin that is not installed, validation will fail and
-the error message will not make much sense to your users.
-
-One approach is to defer the hook implementation to a new plugin instead of
-declaring the hook functions directly in your plugin module, for example::
-
- # contents of myplugin.py
-
- class DeferPlugin(object):
- """Simple plugin to defer pytest-xdist hook functions."""
-
- def pytest_testnodedown(self, node, error):
- """standard xdist hook function.
- """
-
- def pytest_configure(config):
- if config.pluginmanager.hasplugin('xdist'):
- config.pluginmanager.register(DeferPlugin())
-
-This has the added benefit of allowing you to conditionally install hooks
-depending on which plugins are installed.
-
-.. _`well specified hooks`:
-
-.. currentmodule:: _pytest.hookspec
-
-pytest hook reference
-=====================
-
-
-Initialization, command line and configuration hooks
-----------------------------------------------------
-
-.. autofunction:: pytest_load_initial_conftests
-.. autofunction:: pytest_cmdline_preparse
-.. autofunction:: pytest_cmdline_parse
-.. autofunction:: pytest_namespace
-.. autofunction:: pytest_addoption
-.. autofunction:: pytest_cmdline_main
-.. autofunction:: pytest_configure
-.. autofunction:: pytest_unconfigure
-
-Generic "runtest" hooks
------------------------
-
-All runtest related hooks receive a :py:class:`pytest.Item` object.
-
-.. autofunction:: pytest_runtest_protocol
-.. autofunction:: pytest_runtest_setup
-.. autofunction:: pytest_runtest_call
-.. autofunction:: pytest_runtest_teardown
-.. autofunction:: pytest_runtest_makereport
-
-For deeper understanding you may look at the default implementation of
-these hooks in :py:mod:`_pytest.runner` and maybe also
-in :py:mod:`_pytest.pdb` which interacts with :py:mod:`_pytest.capture`
-and its input/output capturing in order to immediately drop
-into interactive debugging when a test failure occurs.
-
-The :py:mod:`_pytest.terminal` reported specifically uses
-the reporting hook to print information about a test run.
-
-Collection hooks
-----------------
-
-``pytest`` calls the following hooks for collecting files and directories:
-
-.. autofunction:: pytest_ignore_collect
-.. autofunction:: pytest_collect_directory
-.. autofunction:: pytest_collect_file
-
-For influencing the collection of objects in Python modules
-you can use the following hook:
-
-.. autofunction:: pytest_pycollect_makeitem
-.. autofunction:: pytest_generate_tests
-
-After collection is complete, you can modify the order of
-items, delete or otherwise amend the test items:
-
-.. autofunction:: pytest_collection_modifyitems
-
-Reporting hooks
----------------
-
-Session related reporting hooks:
-
-.. autofunction:: pytest_collectstart
-.. autofunction:: pytest_itemcollected
-.. autofunction:: pytest_collectreport
-.. autofunction:: pytest_deselected
-.. autofunction:: pytest_report_header
-.. autofunction:: pytest_report_teststatus
-.. autofunction:: pytest_terminal_summary
-
-And here is the central hook for reporting about
-test execution:
-
-.. autofunction:: pytest_runtest_logreport
-
-You can also use this hook to customize assertion representation for some
-types:
-
-.. autofunction:: pytest_assertrepr_compare
-
-
-Debugging/Interaction hooks
----------------------------
-
-There are few hooks which can be used for special
-reporting or interaction with exceptions:
-
-.. autofunction:: pytest_internalerror
-.. autofunction:: pytest_keyboard_interrupt
-.. autofunction:: pytest_exception_interact
-.. autofunction:: pytest_enter_pdb
-
-
-Reference of objects involved in hooks
-======================================
-
-.. autoclass:: _pytest.config.Config()
- :members:
-
-.. autoclass:: _pytest.config.Parser()
- :members:
-
-.. autoclass:: _pytest.main.Node()
- :members:
-
-.. autoclass:: _pytest.main.Collector()
- :members:
- :show-inheritance:
-
-.. autoclass:: _pytest.main.Item()
- :members:
- :show-inheritance:
-
-.. autoclass:: _pytest.python.Module()
- :members:
- :show-inheritance:
-
-.. autoclass:: _pytest.python.Class()
- :members:
- :show-inheritance:
-
-.. autoclass:: _pytest.python.Function()
- :members:
- :show-inheritance:
-
-.. autoclass:: _pytest.runner.CallInfo()
- :members:
-
-.. autoclass:: _pytest.runner.TestReport()
- :members:
-
-.. autoclass:: _pytest.vendored_packages.pluggy._CallOutcome()
- :members:
-
-.. autofunction:: _pytest.config.get_plugin_manager()
-
-.. autoclass:: _pytest.config.PytestPluginManager()
- :members:
- :undoc-members:
- :show-inheritance:
-
-.. autoclass:: pluggy.PluginManager()
- :members:
-
-.. currentmodule:: _pytest.pytester
-
-.. autoclass:: Testdir()
- :members: runpytest,runpytest_subprocess,runpytest_inprocess,makeconftest,makepyfile
-
-.. autoclass:: RunResult()
- :members:
-
-.. autoclass:: LineMatcher()
- :members:
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/xdist.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/xdist.rst
deleted file mode 100644
index ee1bd603283..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/xdist.rst
+++ /dev/null
@@ -1,197 +0,0 @@
-
-.. _`xdist`:
-
-xdist: pytest distributed testing plugin
-===============================================================
-
-The `pytest-xdist`_ plugin extends ``pytest`` with some unique
-test execution modes:
-
-* Looponfail: run your tests repeatedly in a subprocess. After each
- run, ``pytest`` waits until a file in your project changes and then
- re-runs the previously failing tests. This is repeated until all
- tests pass. At this point a full run is again performed.
-
-* multiprocess Load-balancing: if you have multiple CPUs or hosts you can use
- them for a combined test run. This allows to speed up
- development or to use special resources of remote machines.
-
-* Multi-Platform coverage: you can specify different Python interpreters
- or different platforms and run tests in parallel on all of them.
-
-Before running tests remotely, ``pytest`` efficiently "rsyncs" your
-program source code to the remote place. All test results
-are reported back and displayed to your local terminal.
-You may specify different Python versions and interpreters.
-
-
-Installation of xdist plugin
-------------------------------
-
-Install the plugin with::
-
- easy_install pytest-xdist
-
- # or
-
- pip install pytest-xdist
-
-or use the package in develop/in-place mode with
-a checkout of the `pytest-xdist repository`_ ::
-
- python setup.py develop
-
-
-Usage examples
----------------------
-
-.. _`xdistcpu`:
-
-Speed up test runs by sending tests to multiple CPUs
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-To send tests to multiple CPUs, type::
-
- py.test -n NUM
-
-Especially for longer running tests or tests requiring
-a lot of I/O this can lead to considerable speed ups.
-
-
-Running tests in a Python subprocess
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-To instantiate a Python-2.7 subprocess and send tests to it, you may type::
-
- py.test -d --tx popen//python=python2.7
-
-This will start a subprocess which is run with the "python2.7"
-Python interpreter, found in your system binary lookup path.
-
-If you prefix the --tx option value like this::
-
- py.test -d --tx 3*popen//python=python2.7
-
-then three subprocesses would be created and the tests
-will be distributed to three subprocesses and run simultanously.
-
-.. _looponfailing:
-
-
-Running tests in looponfailing mode
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-For refactoring a project with a medium or large test suite
-you can use the looponfailing mode. Simply add the ``--f`` option::
-
- py.test -f
-
-and ``pytest`` will run your tests. Assuming you have failures it will then
-wait for file changes and re-run the failing test set. File changes are detected by looking at ``looponfailingroots`` root directories and all of their contents (recursively). If the default for this value does not work for you you
-can change it in your project by setting a configuration option::
-
- # content of a pytest.ini, setup.cfg or tox.ini file
- [pytest]
- looponfailroots = mypkg testdir
-
-This would lead to only looking for file changes in the respective directories, specified relatively to the ini-file's directory.
-
-Sending tests to remote SSH accounts
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-Suppose you have a package ``mypkg`` which contains some
-tests that you can successfully run locally. And you also
-have a ssh-reachable machine ``myhost``. Then
-you can ad-hoc distribute your tests by typing::
-
- py.test -d --tx ssh=myhostpopen --rsyncdir mypkg mypkg
-
-This will synchronize your ``mypkg`` package directory
-with a remote ssh account and then collect and run your
-tests at the remote side.
-
-You can specify multiple ``--rsyncdir`` directories
-to be sent to the remote side.
-
-.. XXX CHECK
-
- **NOTE:** For ``pytest`` to collect and send tests correctly
- you not only need to make sure all code and tests
- directories are rsynced, but that any test (sub) directory
- also has an ``__init__.py`` file because internally
- ``pytest`` references tests as a fully qualified python
- module path. **You will otherwise get strange errors**
- during setup of the remote side.
-
-Sending tests to remote Socket Servers
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-Download the single-module `socketserver.py`_ Python program
-and run it like this::
-
- python socketserver.py
-
-It will tell you that it starts listening on the default
-port. You can now on your home machine specify this
-new socket host with something like this::
-
- py.test -d --tx socket=192.168.1.102:8888 --rsyncdir mypkg mypkg
-
-
-.. _`atonce`:
-
-Running tests on many platforms at once
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-The basic command to run tests on multiple platforms is::
-
- py.test --dist=each --tx=spec1 --tx=spec2
-
-If you specify a windows host, an OSX host and a Linux
-environment this command will send each tests to all
-platforms - and report back failures from all platforms
-at once. The specifications strings use the `xspec syntax`_.
-
-.. _`xspec syntax`: http://codespeak.net/execnet/basics.html#xspec
-
-.. _`socketserver.py`: http://bitbucket.org/hpk42/execnet/raw/2af991418160/execnet/script/socketserver.py
-
-.. _`execnet`: http://codespeak.net/execnet
-
-Specifying test exec environments in an ini file
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-pytest (since version 2.0) supports ini-style configuration.
-For example, you could make running with three subprocesses your default::
-
- [pytest]
- addopts = -n3
-
-You can also add default environments like this::
-
- [pytest]
- addopts = --tx ssh=myhost//python=python2.7 --tx ssh=myhost//python=python2.6
-
-and then just type::
-
- py.test --dist=each
-
-to run tests in each of the environments.
-
-Specifying "rsync" dirs in an ini-file
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-In a ``tox.ini`` or ``setup.cfg`` file in your root project directory
-you may specify directories to include or to exclude in synchronisation::
-
- [pytest]
- rsyncdirs = . mypkg helperpkg
- rsyncignore = .hg
-
-These directory specifications are relative to the directory
-where the configuration file was found.
-
-.. _`pytest-xdist`: http://pypi.python.org/pypi/pytest-xdist
-.. _`pytest-xdist repository`: http://bitbucket.org/pytest-dev/pytest-xdist
-.. _`pytest`: http://pytest.org
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/xunit_setup.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/xunit_setup.rst
deleted file mode 100644
index 7a80f129966..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/xunit_setup.rst
+++ /dev/null
@@ -1,90 +0,0 @@
-
-.. _`classic xunit`:
-.. _xunitsetup:
-
-classic xunit-style setup
-========================================
-
-This section describes a classic and popular way how you can implement
-fixtures (setup and teardown test state) on a per-module/class/function basis.
-pytest started supporting these methods around 2005 and subsequently
-nose and the standard library introduced them (under slightly different
-names). While these setup/teardown methods are and will remain fully
-supported you may also use pytest's more powerful :ref:`fixture mechanism
-<fixture>` which leverages the concept of dependency injection, allowing
-for a more modular and more scalable approach for managing test state,
-especially for larger projects and for functional testing. You can
-mix both fixture mechanisms in the same file but unittest-based
-test methods cannot receive fixture arguments.
-
-.. note::
-
- As of pytest-2.4, teardownX functions are not called if
- setupX existed and failed/was skipped. This harmonizes
- behaviour across all major python testing tools.
-
-Module level setup/teardown
---------------------------------------
-
-If you have multiple test functions and test classes in a single
-module you can optionally implement the following fixture methods
-which will usually be called once for all the functions::
-
- def setup_module(module):
- """ setup any state specific to the execution of the given module."""
-
- def teardown_module(module):
- """ teardown any state that was previously setup with a setup_module
- method.
- """
-
-Class level setup/teardown
-----------------------------------
-
-Similarly, the following methods are called at class level before
-and after all test methods of the class are called::
-
- @classmethod
- def setup_class(cls):
- """ setup any state specific to the execution of the given class (which
- usually contains tests).
- """
-
- @classmethod
- def teardown_class(cls):
- """ teardown any state that was previously setup with a call to
- setup_class.
- """
-
-Method and function level setup/teardown
------------------------------------------------
-
-Similarly, the following methods are called around each method invocation::
-
- def setup_method(self, method):
- """ setup any state tied to the execution of the given method in a
- class. setup_method is invoked for every test method of a class.
- """
-
- def teardown_method(self, method):
- """ teardown any state that was previously setup with a setup_method
- call.
- """
-
-If you would rather define test functions directly at module level
-you can also use the following functions to implement fixtures::
-
- def setup_function(function):
- """ setup any state tied to the execution of the given function.
- Invoked for every test function in the module.
- """
-
- def teardown_function(function):
- """ teardown any state that was previously setup with a setup_function
- call.
- """
-
-Note that it is possible for setup/teardown pairs to be invoked multiple times
-per testing process.
-
-.. _`unittest.py module`: http://docs.python.org/library/unittest.html
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/yieldfixture.rst b/tests/wpt/web-platform-tests/tools/pytest/doc/en/yieldfixture.rst
deleted file mode 100644
index ee88a27df59..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/yieldfixture.rst
+++ /dev/null
@@ -1,100 +0,0 @@
-.. _yieldfixture:
-
-Fixture functions using "yield" / context manager integration
----------------------------------------------------------------
-
-.. versionadded:: 2.4
-
-.. regendoc:wipe
-
-pytest-2.4 allows fixture functions to seamlessly use a ``yield`` instead
-of a ``return`` statement to provide a fixture value while otherwise
-fully supporting all other fixture features.
-
-Let's look at a simple standalone-example using the ``yield`` syntax::
-
- # content of test_yield.py
-
- import pytest
-
- @pytest.yield_fixture
- def passwd():
- print ("\nsetup before yield")
- f = open("/etc/passwd")
- yield f.readlines()
- print ("teardown after yield")
- f.close()
-
- def test_has_lines(passwd):
- print ("test called")
- assert passwd
-
-In contrast to :ref:`finalization through registering callbacks
-<finalization>`, our fixture function used a ``yield``
-statement to provide the lines of the ``/etc/passwd`` file.
-The code after the ``yield`` statement serves as the teardown code,
-avoiding the indirection of registering a teardown callback function.
-
-Let's run it with output capturing disabled::
-
- $ py.test -q -s test_yield.py
-
- setup before yield
- test called
- .teardown after yield
-
- 1 passed in 0.12 seconds
-
-We can also seamlessly use the new syntax with ``with`` statements.
-Let's simplify the above ``passwd`` fixture::
-
- # content of test_yield2.py
-
- import pytest
-
- @pytest.yield_fixture
- def passwd():
- with open("/etc/passwd") as f:
- yield f.readlines()
-
- def test_has_lines(passwd):
- assert len(passwd) >= 1
-
-The file ``f`` will be closed after the test finished execution
-because the Python ``file`` object supports finalization when
-the ``with`` statement ends.
-
-Note that the yield fixture form supports all other fixture
-features such as ``scope``, ``params``, etc., thus changing existing
-fixture functions to use ``yield`` is straightforward.
-
-.. note::
-
- While the ``yield`` syntax is similar to what
- :py:func:`contextlib.contextmanager` decorated functions
- provide, with pytest fixture functions the part after the
- "yield" will always be invoked, independently from the
- exception status of the test function which uses the fixture.
- This behaviour makes sense if you consider that many different
- test functions might use a module or session scoped fixture.
-
-
-Discussion and future considerations / feedback
-++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-There are some topics that are worth mentioning:
-
-- usually ``yield`` is used for producing multiple values.
- But fixture functions can only yield exactly one value.
- Yielding a second fixture value will get you an error.
- It's possible we can evolve pytest to allow for producing
- multiple values as an alternative to current parametrization.
- For now, you can just use the normal
- :ref:`fixture parametrization <fixture-parametrize>`
- mechanisms together with ``yield``-style fixtures.
-
-- lastly ``yield`` introduces more than one way to write
- fixture functions, so what's the obvious way to a newcomer?
-
-If you want to feedback or participate in discussion of the above
-topics, please join our :ref:`contact channels`, you are most welcome.
diff --git a/tests/wpt/web-platform-tests/tools/pytest/extra/get_issues.py b/tests/wpt/web-platform-tests/tools/pytest/extra/get_issues.py
deleted file mode 100644
index 6437ba4c34e..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/extra/get_issues.py
+++ /dev/null
@@ -1,74 +0,0 @@
-import json
-import py
-import textwrap
-
-issues_url = "http://bitbucket.org/api/1.0/repositories/pytest-dev/pytest/issues"
-
-import requests
-
-def get_issues():
- chunksize = 50
- start = 0
- issues = []
- while 1:
- post_data = {"accountname": "pytest-dev",
- "repo_slug": "pytest",
- "start": start,
- "limit": chunksize}
- print ("getting from", start)
- r = requests.get(issues_url, params=post_data)
- data = r.json()
- issues.extend(data["issues"])
- if start + chunksize >= data["count"]:
- return issues
- start += chunksize
-
-kind2num = "bug enhancement task proposal".split()
-
-status2num = "new open resolved duplicate invalid wontfix".split()
-
-def main(args):
- cachefile = py.path.local(args.cache)
- if not cachefile.exists() or args.refresh:
- issues = get_issues()
- cachefile.write(json.dumps(issues))
- else:
- issues = json.loads(cachefile.read())
-
- open_issues = [x for x in issues
- if x["status"] in ("new", "open")]
-
- def kind_and_id(x):
- kind = x["metadata"]["kind"]
- return kind2num.index(kind), len(issues)-int(x["local_id"])
- open_issues.sort(key=kind_and_id)
- report(open_issues)
-
-def report(issues):
- for issue in issues:
- metadata = issue["metadata"]
- priority = issue["priority"]
- title = issue["title"]
- content = issue["content"]
- kind = metadata["kind"]
- status = issue["status"]
- id = issue["local_id"]
- link = "https://bitbucket.org/pytest-dev/pytest/issue/%s/" % id
- print("----")
- print(status, kind, link)
- print(title)
- #print()
- #lines = content.split("\n")
- #print ("\n".join(lines[:3]))
- #if len(lines) > 3 or len(content) > 240:
- # print ("...")
-
-if __name__ == "__main__":
- import argparse
- parser = argparse.ArgumentParser("process bitbucket issues")
- parser.add_argument("--refresh", action="store_true",
- help="invalidate cache, refresh issues")
- parser.add_argument("--cache", action="store", default="issues.json",
- help="cache file")
- args = parser.parse_args()
- main(args)
diff --git a/tests/wpt/web-platform-tests/tools/pytest/plugin-test.sh b/tests/wpt/web-platform-tests/tools/pytest/plugin-test.sh
deleted file mode 100644
index 9c61b50536e..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/plugin-test.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-
-# this assumes plugins are installed as sister directories
-
-set -e
-cd ../pytest-pep8
-py.test
-cd ../pytest-instafail
-py.test
-cd ../pytest-cache
-py.test
-cd ../pytest-xprocess
-py.test
-#cd ../pytest-cov
-#py.test
-cd ../pytest-capturelog
-py.test
-cd ../pytest-xdist
-py.test
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/pytest.py b/tests/wpt/web-platform-tests/tools/pytest/pytest.py
deleted file mode 100644
index e376e417e8a..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/pytest.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# PYTHON_ARGCOMPLETE_OK
-"""
-pytest: unit and functional testing with Python.
-"""
-__all__ = [
- 'main',
- 'UsageError',
- 'cmdline',
- 'hookspec',
- 'hookimpl',
- '__version__',
-]
-
-if __name__ == '__main__': # if run as a script or by 'python -m pytest'
- # we trigger the below "else" condition by the following import
- import pytest
- raise SystemExit(pytest.main())
-
-# else we are imported
-
-from _pytest.config import (
- main, UsageError, _preloadplugins, cmdline,
- hookspec, hookimpl
-)
-from _pytest import __version__
-
-_preloadplugins() # to populate pytest.* namespace so help(pytest) works
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/requirements-docs.txt b/tests/wpt/web-platform-tests/tools/pytest/requirements-docs.txt
deleted file mode 100644
index be3a232e57b..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/requirements-docs.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-sphinx==1.2.3
-regendoc
-pyyaml
diff --git a/tests/wpt/web-platform-tests/tools/pytest/runtox.py b/tests/wpt/web-platform-tests/tools/pytest/runtox.py
deleted file mode 100644
index 8c13c53e1c4..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/runtox.py
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env python
-
-if __name__ == "__main__":
- import subprocess
- import sys
- subprocess.call([sys.executable, "-m", "tox",
- "-i", "ALL=https://devpi.net/hpk/dev/",
- "--develop"] + sys.argv[1:])
diff --git a/tests/wpt/web-platform-tests/tools/pytest/setup.cfg b/tests/wpt/web-platform-tests/tools/pytest/setup.cfg
deleted file mode 100644
index 1ab4fd059b2..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/setup.cfg
+++ /dev/null
@@ -1,13 +0,0 @@
-[build_sphinx]
-source-dir = doc/en/
-build-dir = doc/build
-all_files = 1
-
-[upload_sphinx]
-upload-dir = doc/en/build/html
-
-[bdist_wheel]
-universal = 1
-
-[devpi:upload]
-formats = sdist.tgz,bdist_wheel
diff --git a/tests/wpt/web-platform-tests/tools/pytest/setup.py b/tests/wpt/web-platform-tests/tools/pytest/setup.py
deleted file mode 100644
index 6660f21604d..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/setup.py
+++ /dev/null
@@ -1,122 +0,0 @@
-import os, sys
-import setuptools
-import pkg_resources
-from setuptools import setup, Command
-
-classifiers = ['Development Status :: 6 - Mature',
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: MIT License',
- 'Operating System :: POSIX',
- 'Operating System :: Microsoft :: Windows',
- 'Operating System :: MacOS :: MacOS X',
- 'Topic :: Software Development :: Testing',
- 'Topic :: Software Development :: Libraries',
- 'Topic :: Utilities'] + [
- ('Programming Language :: Python :: %s' % x) for x in
- '2 2.6 2.7 3 3.2 3.3 3.4 3.5'.split()]
-
-with open('README.rst') as fd:
- long_description = fd.read()
-
-def get_version():
- p = os.path.join(os.path.dirname(
- os.path.abspath(__file__)), "_pytest", "__init__.py")
- with open(p) as f:
- for line in f.readlines():
- if "__version__" in line:
- return line.strip().split("=")[-1].strip(" '")
- raise ValueError("could not read version")
-
-
-def has_environment_marker_support():
- """
- Tests that setuptools has support for PEP-426 environment marker support.
-
- The first known release to support it is 0.7 (and the earliest on PyPI seems to be 0.7.2
- so we're using that), see: http://pythonhosted.org/setuptools/history.html#id142
-
- References:
-
- * https://wheel.readthedocs.org/en/latest/index.html#defining-conditional-dependencies
- * https://www.python.org/dev/peps/pep-0426/#environment-markers
- """
- try:
- return pkg_resources.parse_version(setuptools.__version__) >= pkg_resources.parse_version('0.7.2')
- except Exception as exc:
- sys.stderr.write("Could not test setuptool's version: %s\n" % exc)
- return False
-
-
-def main():
- install_requires = ['py>=1.4.29'] # pluggy is vendored in _pytest.vendored_packages
- extras_require = {}
- if has_environment_marker_support():
- extras_require[':python_version=="2.6" or python_version=="3.0" or python_version=="3.1"'] = ['argparse']
- extras_require[':sys_platform=="win32"'] = ['colorama']
- else:
- if sys.version_info < (2, 7) or (3,) <= sys.version_info < (3, 2):
- install_requires.append('argparse')
- if sys.platform == 'win32':
- install_requires.append('colorama')
-
- setup(
- name='pytest',
- description='pytest: simple powerful testing with Python',
- long_description=long_description,
- version=get_version(),
- url='http://pytest.org',
- license='MIT license',
- platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],
- author='Holger Krekel, Bruno Oliveira, Ronny Pfannschmidt, Floris Bruynooghe, Brianna Laugher, Florian Bruhin and others',
- author_email='holger at merlinux.eu',
- entry_points=make_entry_points(),
- classifiers=classifiers,
- cmdclass={'test': PyTest},
- # the following should be enabled for release
- install_requires=install_requires,
- extras_require=extras_require,
- packages=['_pytest', '_pytest.assertion', '_pytest._code', '_pytest.vendored_packages'],
- py_modules=['pytest'],
- zip_safe=False,
- )
-
-
-def cmdline_entrypoints(versioninfo, platform, basename):
- target = 'pytest:main'
- if platform.startswith('java'):
- points = {'py.test-jython': target}
- else:
- if basename.startswith('pypy'):
- points = {'py.test-%s' % basename: target}
- else: # cpython
- points = {'py.test-%s.%s' % versioninfo[:2] : target}
- points['py.test'] = target
- return points
-
-
-def make_entry_points():
- basename = os.path.basename(sys.executable)
- points = cmdline_entrypoints(sys.version_info, sys.platform, basename)
- keys = list(points.keys())
- keys.sort()
- l = ['%s = %s' % (x, points[x]) for x in keys]
- return {'console_scripts': l}
-
-
-class PyTest(Command):
- user_options = []
- def initialize_options(self):
- pass
- def finalize_options(self):
- pass
- def run(self):
- import subprocess
- PPATH = [x for x in os.environ.get('PYTHONPATH', '').split(':') if x]
- PPATH.insert(0, os.getcwd())
- os.environ['PYTHONPATH'] = ':'.join(PPATH)
- errno = subprocess.call([sys.executable, 'pytest.py', '--ignore=doc'])
- raise SystemExit(errno)
-
-
-if __name__ == '__main__':
- main()
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/acceptance_test.py b/tests/wpt/web-platform-tests/tools/pytest/testing/acceptance_test.py
deleted file mode 100644
index 9bc3a191a53..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/acceptance_test.py
+++ /dev/null
@@ -1,695 +0,0 @@
-import sys
-
-import _pytest._code
-import py
-import pytest
-from _pytest.main import EXIT_NOTESTSCOLLECTED, EXIT_USAGEERROR
-
-
-class TestGeneralUsage:
- def test_config_error(self, testdir):
- testdir.makeconftest("""
- def pytest_configure(config):
- import pytest
- raise pytest.UsageError("hello")
- """)
- result = testdir.runpytest(testdir.tmpdir)
- assert result.ret != 0
- result.stderr.fnmatch_lines([
- '*ERROR: hello'
- ])
-
- def test_root_conftest_syntax_error(self, testdir):
- testdir.makepyfile(conftest="raise SyntaxError\n")
- result = testdir.runpytest()
- result.stderr.fnmatch_lines(["*raise SyntaxError*"])
- assert result.ret != 0
-
- def test_early_hook_error_issue38_1(self, testdir):
- testdir.makeconftest("""
- def pytest_sessionstart():
- 0 / 0
- """)
- result = testdir.runpytest(testdir.tmpdir)
- assert result.ret != 0
- # tracestyle is native by default for hook failures
- result.stdout.fnmatch_lines([
- '*INTERNALERROR*File*conftest.py*line 2*',
- '*0 / 0*',
- ])
- result = testdir.runpytest(testdir.tmpdir, "--fulltrace")
- assert result.ret != 0
- # tracestyle is native by default for hook failures
- result.stdout.fnmatch_lines([
- '*INTERNALERROR*def pytest_sessionstart():*',
- '*INTERNALERROR*0 / 0*',
- ])
-
- def test_early_hook_configure_error_issue38(self, testdir):
- testdir.makeconftest("""
- def pytest_configure():
- 0 / 0
- """)
- result = testdir.runpytest(testdir.tmpdir)
- assert result.ret != 0
- # here we get it on stderr
- result.stderr.fnmatch_lines([
- '*INTERNALERROR*File*conftest.py*line 2*',
- '*0 / 0*',
- ])
-
- def test_file_not_found(self, testdir):
- result = testdir.runpytest("asd")
- assert result.ret != 0
- result.stderr.fnmatch_lines(["ERROR: file not found*asd"])
-
- def test_file_not_found_unconfigure_issue143(self, testdir):
- testdir.makeconftest("""
- def pytest_configure():
- print("---configure")
- def pytest_unconfigure():
- print("---unconfigure")
- """)
- result = testdir.runpytest("-s", "asd")
- assert result.ret == 4 # EXIT_USAGEERROR
- result.stderr.fnmatch_lines(["ERROR: file not found*asd"])
- result.stdout.fnmatch_lines([
- "*---configure",
- "*---unconfigure",
- ])
-
-
- def test_config_preparse_plugin_option(self, testdir):
- testdir.makepyfile(pytest_xyz="""
- def pytest_addoption(parser):
- parser.addoption("--xyz", dest="xyz", action="store")
- """)
- testdir.makepyfile(test_one="""
- def test_option(pytestconfig):
- assert pytestconfig.option.xyz == "123"
- """)
- result = testdir.runpytest("-p", "pytest_xyz", "--xyz=123", syspathinsert=True)
- assert result.ret == 0
- result.stdout.fnmatch_lines([
- '*1 passed*',
- ])
-
- def test_assertion_magic(self, testdir):
- p = testdir.makepyfile("""
- def test_this():
- x = 0
- assert x
- """)
- result = testdir.runpytest(p)
- result.stdout.fnmatch_lines([
- "> assert x",
- "E assert 0",
- ])
- assert result.ret == 1
-
- def test_nested_import_error(self, testdir):
- p = testdir.makepyfile("""
- import import_fails
- def test_this():
- assert import_fails.a == 1
- """)
- testdir.makepyfile(import_fails="import does_not_work")
- result = testdir.runpytest(p)
- result.stdout.fnmatch_lines([
- #XXX on jython this fails: "> import import_fails",
- "E ImportError: No module named *does_not_work*",
- ])
- assert result.ret == 1
-
- def test_not_collectable_arguments(self, testdir):
- p1 = testdir.makepyfile("")
- p2 = testdir.makefile(".pyc", "123")
- result = testdir.runpytest(p1, p2)
- assert result.ret
- result.stderr.fnmatch_lines([
- "*ERROR: not found:*%s" %(p2.basename,)
- ])
-
- def test_issue486_better_reporting_on_conftest_load_failure(self, testdir):
- testdir.makepyfile("")
- testdir.makeconftest("import qwerty")
- result = testdir.runpytest("--help")
- result.stdout.fnmatch_lines("""
- *--version*
- *warning*conftest.py*
- """)
- result = testdir.runpytest()
- result.stderr.fnmatch_lines("""
- *ERROR*could not load*conftest.py*
- """)
-
-
- def test_early_skip(self, testdir):
- testdir.mkdir("xyz")
- testdir.makeconftest("""
- import pytest
- def pytest_collect_directory():
- pytest.skip("early")
- """)
- result = testdir.runpytest()
- assert result.ret == EXIT_NOTESTSCOLLECTED
- result.stdout.fnmatch_lines([
- "*1 skip*"
- ])
-
- def test_issue88_initial_file_multinodes(self, testdir):
- testdir.makeconftest("""
- import pytest
- class MyFile(pytest.File):
- def collect(self):
- return [MyItem("hello", parent=self)]
- def pytest_collect_file(path, parent):
- return MyFile(path, parent)
- class MyItem(pytest.Item):
- pass
- """)
- p = testdir.makepyfile("def test_hello(): pass")
- result = testdir.runpytest(p, "--collect-only")
- result.stdout.fnmatch_lines([
- "*MyFile*test_issue88*",
- "*Module*test_issue88*",
- ])
-
- def test_issue93_initialnode_importing_capturing(self, testdir):
- testdir.makeconftest("""
- import sys
- print ("should not be seen")
- sys.stderr.write("stder42\\n")
- """)
- result = testdir.runpytest()
- assert result.ret == EXIT_NOTESTSCOLLECTED
- assert "should not be seen" not in result.stdout.str()
- assert "stderr42" not in result.stderr.str()
-
- def test_conftest_printing_shows_if_error(self, testdir):
- testdir.makeconftest("""
- print ("should be seen")
- assert 0
- """)
- result = testdir.runpytest()
- assert result.ret != 0
- assert "should be seen" in result.stdout.str()
-
- @pytest.mark.skipif(not hasattr(py.path.local, 'mksymlinkto'),
- reason="symlink not available on this platform")
- def test_chdir(self, testdir):
- testdir.tmpdir.join("py").mksymlinkto(py._pydir)
- p = testdir.tmpdir.join("main.py")
- p.write(_pytest._code.Source("""
- import sys, os
- sys.path.insert(0, '')
- import py
- print (py.__file__)
- print (py.__path__)
- os.chdir(os.path.dirname(os.getcwd()))
- print (py.log)
- """))
- result = testdir.runpython(p)
- assert not result.ret
-
- def test_issue109_sibling_conftests_not_loaded(self, testdir):
- sub1 = testdir.tmpdir.mkdir("sub1")
- sub2 = testdir.tmpdir.mkdir("sub2")
- sub1.join("conftest.py").write("assert 0")
- result = testdir.runpytest(sub2)
- assert result.ret == EXIT_NOTESTSCOLLECTED
- sub2.ensure("__init__.py")
- p = sub2.ensure("test_hello.py")
- result = testdir.runpytest(p)
- assert result.ret == EXIT_NOTESTSCOLLECTED
- result = testdir.runpytest(sub1)
- assert result.ret == EXIT_USAGEERROR
-
- def test_directory_skipped(self, testdir):
- testdir.makeconftest("""
- import pytest
- def pytest_ignore_collect():
- pytest.skip("intentional")
- """)
- testdir.makepyfile("def test_hello(): pass")
- result = testdir.runpytest()
- assert result.ret == EXIT_NOTESTSCOLLECTED
- result.stdout.fnmatch_lines([
- "*1 skipped*"
- ])
-
- def test_multiple_items_per_collector_byid(self, testdir):
- c = testdir.makeconftest("""
- import pytest
- class MyItem(pytest.Item):
- def runtest(self):
- pass
- class MyCollector(pytest.File):
- def collect(self):
- return [MyItem(name="xyz", parent=self)]
- def pytest_collect_file(path, parent):
- if path.basename.startswith("conftest"):
- return MyCollector(path, parent)
- """)
- result = testdir.runpytest(c.basename+"::"+"xyz")
- assert result.ret == 0
- result.stdout.fnmatch_lines([
- "*1 pass*",
- ])
-
- def test_skip_on_generated_funcarg_id(self, testdir):
- testdir.makeconftest("""
- import pytest
- def pytest_generate_tests(metafunc):
- metafunc.addcall({'x': 3}, id='hello-123')
- def pytest_runtest_setup(item):
- print (item.keywords)
- if 'hello-123' in item.keywords:
- pytest.skip("hello")
- assert 0
- """)
- p = testdir.makepyfile("""def test_func(x): pass""")
- res = testdir.runpytest(p)
- assert res.ret == 0
- res.stdout.fnmatch_lines(["*1 skipped*"])
-
- def test_direct_addressing_selects(self, testdir):
- p = testdir.makepyfile("""
- def pytest_generate_tests(metafunc):
- metafunc.addcall({'i': 1}, id="1")
- metafunc.addcall({'i': 2}, id="2")
- def test_func(i):
- pass
- """)
- res = testdir.runpytest(p.basename + "::" + "test_func[1]")
- assert res.ret == 0
- res.stdout.fnmatch_lines(["*1 passed*"])
-
- def test_direct_addressing_notfound(self, testdir):
- p = testdir.makepyfile("""
- def test_func():
- pass
- """)
- res = testdir.runpytest(p.basename + "::" + "test_notfound")
- assert res.ret
- res.stderr.fnmatch_lines(["*ERROR*not found*"])
-
- def test_docstring_on_hookspec(self):
- from _pytest import hookspec
- for name, value in vars(hookspec).items():
- if name.startswith("pytest_"):
- assert value.__doc__, "no docstring for %s" % name
-
- def test_initialization_error_issue49(self, testdir):
- testdir.makeconftest("""
- def pytest_configure():
- x
- """)
- result = testdir.runpytest()
- assert result.ret == 3 # internal error
- result.stderr.fnmatch_lines([
- "INTERNAL*pytest_configure*",
- "INTERNAL*x*",
- ])
- assert 'sessionstarttime' not in result.stderr.str()
-
- @pytest.mark.parametrize('lookfor', ['test_fun.py', 'test_fun.py::test_a'])
- def test_issue134_report_syntaxerror_when_collecting_member(self, testdir, lookfor):
- testdir.makepyfile(test_fun="""
- def test_a():
- pass
- def""")
- result = testdir.runpytest(lookfor)
- result.stdout.fnmatch_lines(['*SyntaxError*'])
- if '::' in lookfor:
- result.stderr.fnmatch_lines([
- '*ERROR*',
- ])
- assert result.ret == 4 # usage error only if item not found
-
- def test_report_all_failed_collections_initargs(self, testdir):
- testdir.makepyfile(test_a="def", test_b="def")
- result = testdir.runpytest("test_a.py::a", "test_b.py::b")
- result.stderr.fnmatch_lines([
- "*ERROR*test_a.py::a*",
- "*ERROR*test_b.py::b*",
- ])
-
- def test_namespace_import_doesnt_confuse_import_hook(self, testdir):
- # Ref #383. Python 3.3's namespace package messed with our import hooks
- # Importing a module that didn't exist, even if the ImportError was
- # gracefully handled, would make our test crash.
- testdir.mkdir('not_a_package')
- p = testdir.makepyfile("""
- try:
- from not_a_package import doesnt_exist
- except ImportError:
- # We handle the import error gracefully here
- pass
-
- def test_whatever():
- pass
- """)
- res = testdir.runpytest(p.basename)
- assert res.ret == 0
-
- def test_unknown_option(self, testdir):
- result = testdir.runpytest("--qwlkej")
- result.stderr.fnmatch_lines("""
- *unrecognized*
- """)
-
- def test_getsourcelines_error_issue553(self, testdir, monkeypatch):
- monkeypatch.setattr("inspect.getsourcelines", None)
- p = testdir.makepyfile("""
- def raise_error(obj):
- raise IOError('source code not available')
-
- import inspect
- inspect.getsourcelines = raise_error
-
- def test_foo(invalid_fixture):
- pass
- """)
- res = testdir.runpytest(p)
- res.stdout.fnmatch_lines([
- "*source code not available*",
- "*fixture 'invalid_fixture' not found",
- ])
-
- def test_plugins_given_as_strings(self, tmpdir, monkeypatch):
- """test that str values passed to main() as `plugins` arg
- are interpreted as module names to be imported and registered.
- #855.
- """
- with pytest.raises(ImportError) as excinfo:
- pytest.main([str(tmpdir)], plugins=['invalid.module'])
- assert 'invalid' in str(excinfo.value)
-
- p = tmpdir.join('test_test_plugins_given_as_strings.py')
- p.write('def test_foo(): pass')
- mod = py.std.types.ModuleType("myplugin")
- monkeypatch.setitem(sys.modules, 'myplugin', mod)
- assert pytest.main(args=[str(tmpdir)], plugins=['myplugin']) == 0
-
- def test_parameterized_with_bytes_regex(self, testdir):
- p = testdir.makepyfile("""
- import re
- import pytest
- @pytest.mark.parametrize('r', [re.compile(b'foo')])
- def test_stuff(r):
- pass
- """
- )
- res = testdir.runpytest(p)
- res.stdout.fnmatch_lines([
- '*1 passed*'
- ])
-
-
-class TestInvocationVariants:
- def test_earlyinit(self, testdir):
- p = testdir.makepyfile("""
- import pytest
- assert hasattr(pytest, 'mark')
- """)
- result = testdir.runpython(p)
- assert result.ret == 0
-
- @pytest.mark.xfail("sys.platform.startswith('java')")
- def test_pydoc(self, testdir):
- for name in ('py.test', 'pytest'):
- result = testdir.runpython_c("import %s;help(%s)" % (name, name))
- assert result.ret == 0
- s = result.stdout.str()
- assert 'MarkGenerator' in s
-
- def test_import_star_py_dot_test(self, testdir):
- p = testdir.makepyfile("""
- from py.test import *
- #collect
- #cmdline
- #Item
- #assert collect.Item is Item
- #assert collect.Collector is Collector
- main
- skip
- xfail
- """)
- result = testdir.runpython(p)
- assert result.ret == 0
-
- def test_import_star_pytest(self, testdir):
- p = testdir.makepyfile("""
- from pytest import *
- #Item
- #File
- main
- skip
- xfail
- """)
- result = testdir.runpython(p)
- assert result.ret == 0
-
- def test_double_pytestcmdline(self, testdir):
- p = testdir.makepyfile(run="""
- import pytest
- pytest.main()
- pytest.main()
- """)
- testdir.makepyfile("""
- def test_hello():
- pass
- """)
- result = testdir.runpython(p)
- result.stdout.fnmatch_lines([
- "*1 passed*",
- "*1 passed*",
- ])
-
- def test_python_minus_m_invocation_ok(self, testdir):
- p1 = testdir.makepyfile("def test_hello(): pass")
- res = testdir.run(py.std.sys.executable, "-m", "pytest", str(p1))
- assert res.ret == 0
-
- def test_python_minus_m_invocation_fail(self, testdir):
- p1 = testdir.makepyfile("def test_fail(): 0/0")
- res = testdir.run(py.std.sys.executable, "-m", "pytest", str(p1))
- assert res.ret == 1
-
- def test_python_pytest_package(self, testdir):
- p1 = testdir.makepyfile("def test_pass(): pass")
- res = testdir.run(py.std.sys.executable, "-m", "pytest", str(p1))
- assert res.ret == 0
- res.stdout.fnmatch_lines(["*1 passed*"])
-
- def test_equivalence_pytest_pytest(self):
- assert pytest.main == py.test.cmdline.main
-
- def test_invoke_with_string(self, capsys):
- retcode = pytest.main("-h")
- assert not retcode
- out, err = capsys.readouterr()
- assert "--help" in out
- pytest.raises(ValueError, lambda: pytest.main(0))
-
- def test_invoke_with_path(self, tmpdir, capsys):
- retcode = pytest.main(tmpdir)
- assert retcode == EXIT_NOTESTSCOLLECTED
- out, err = capsys.readouterr()
-
- def test_invoke_plugin_api(self, testdir, capsys):
- class MyPlugin:
- def pytest_addoption(self, parser):
- parser.addoption("--myopt")
-
- pytest.main(["-h"], plugins=[MyPlugin()])
- out, err = capsys.readouterr()
- assert "--myopt" in out
-
- def test_pyargs_importerror(self, testdir, monkeypatch):
- monkeypatch.delenv('PYTHONDONTWRITEBYTECODE', False)
- path = testdir.mkpydir("tpkg")
- path.join("test_hello.py").write('raise ImportError')
-
- result = testdir.runpytest("--pyargs", "tpkg.test_hello")
- assert result.ret != 0
- # FIXME: It would be more natural to match NOT
- # "ERROR*file*or*package*not*found*".
- result.stdout.fnmatch_lines([
- "*collected 0 items*"
- ])
-
- def test_cmdline_python_package(self, testdir, monkeypatch):
- monkeypatch.delenv('PYTHONDONTWRITEBYTECODE', False)
- path = testdir.mkpydir("tpkg")
- path.join("test_hello.py").write("def test_hello(): pass")
- path.join("test_world.py").write("def test_world(): pass")
- result = testdir.runpytest("--pyargs", "tpkg")
- assert result.ret == 0
- result.stdout.fnmatch_lines([
- "*2 passed*"
- ])
- result = testdir.runpytest("--pyargs", "tpkg.test_hello")
- assert result.ret == 0
- result.stdout.fnmatch_lines([
- "*1 passed*"
- ])
-
- def join_pythonpath(what):
- cur = py.std.os.environ.get('PYTHONPATH')
- if cur:
- return str(what) + ':' + cur
- return what
- empty_package = testdir.mkpydir("empty_package")
- monkeypatch.setenv('PYTHONPATH', join_pythonpath(empty_package))
- result = testdir.runpytest("--pyargs", ".")
- assert result.ret == 0
- result.stdout.fnmatch_lines([
- "*2 passed*"
- ])
-
- monkeypatch.setenv('PYTHONPATH', join_pythonpath(testdir))
- path.join('test_hello.py').remove()
- result = testdir.runpytest("--pyargs", "tpkg.test_hello")
- assert result.ret != 0
- result.stderr.fnmatch_lines([
- "*not*found*test_hello*",
- ])
-
- def test_cmdline_python_package_not_exists(self, testdir):
- result = testdir.runpytest("--pyargs", "tpkgwhatv")
- assert result.ret
- result.stderr.fnmatch_lines([
- "ERROR*file*or*package*not*found*",
- ])
-
- @pytest.mark.xfail(reason="decide: feature or bug")
- def test_noclass_discovery_if_not_testcase(self, testdir):
- testpath = testdir.makepyfile("""
- import unittest
- class TestHello(object):
- def test_hello(self):
- assert self.attr
-
- class RealTest(unittest.TestCase, TestHello):
- attr = 42
- """)
- reprec = testdir.inline_run(testpath)
- reprec.assertoutcome(passed=1)
-
- def test_doctest_id(self, testdir):
- testdir.makefile('.txt', """
- >>> x=3
- >>> x
- 4
- """)
- result = testdir.runpytest("-rf")
- lines = result.stdout.str().splitlines()
- for line in lines:
- if line.startswith("FAIL "):
- testid = line[5:].strip()
- break
- result = testdir.runpytest(testid, '-rf')
- result.stdout.fnmatch_lines([
- line,
- "*1 failed*",
- ])
-
- def test_core_backward_compatibility(self):
- """Test backward compatibility for get_plugin_manager function. See #787."""
- import _pytest.config
- assert type(_pytest.config.get_plugin_manager()) is _pytest.config.PytestPluginManager
-
-
- def test_has_plugin(self, request):
- """Test hasplugin function of the plugin manager (#932)."""
- assert request.config.pluginmanager.hasplugin('python')
-
-
-class TestDurations:
- source = """
- import time
- frag = 0.002
- def test_something():
- pass
- def test_2():
- time.sleep(frag*5)
- def test_1():
- time.sleep(frag)
- def test_3():
- time.sleep(frag*10)
- """
-
- def test_calls(self, testdir):
- testdir.makepyfile(self.source)
- result = testdir.runpytest("--durations=10")
- assert result.ret == 0
- result.stdout.fnmatch_lines_random([
- "*durations*",
- "*call*test_3*",
- "*call*test_2*",
- "*call*test_1*",
- ])
-
- def test_calls_show_2(self, testdir):
- testdir.makepyfile(self.source)
- result = testdir.runpytest("--durations=2")
- assert result.ret == 0
- lines = result.stdout.get_lines_after("*slowest*durations*")
- assert "4 passed" in lines[2]
-
- def test_calls_showall(self, testdir):
- testdir.makepyfile(self.source)
- result = testdir.runpytest("--durations=0")
- assert result.ret == 0
- for x in "123":
- for y in 'call',: #'setup', 'call', 'teardown':
- for line in result.stdout.lines:
- if ("test_%s" % x) in line and y in line:
- break
- else:
- raise AssertionError("not found %s %s" % (x,y))
-
- def test_with_deselected(self, testdir):
- testdir.makepyfile(self.source)
- result = testdir.runpytest("--durations=2", "-k test_1")
- assert result.ret == 0
- result.stdout.fnmatch_lines([
- "*durations*",
- "*call*test_1*",
- ])
-
- def test_with_failing_collection(self, testdir):
- testdir.makepyfile(self.source)
- testdir.makepyfile(test_collecterror="""xyz""")
- result = testdir.runpytest("--durations=2", "-k test_1")
- assert result.ret != 0
- result.stdout.fnmatch_lines([
- "*durations*",
- "*call*test_1*",
- ])
-
-
-class TestDurationWithFixture:
- source = """
- import time
- frag = 0.001
- def setup_function(func):
- time.sleep(frag * 3)
- def test_1():
- time.sleep(frag*2)
- def test_2():
- time.sleep(frag)
- """
- def test_setup_function(self, testdir):
- testdir.makepyfile(self.source)
- result = testdir.runpytest("--durations=10")
- assert result.ret == 0
-
- result.stdout.fnmatch_lines_random("""
- *durations*
- * setup *test_1*
- * call *test_1*
- """)
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/code/test_code.py b/tests/wpt/web-platform-tests/tools/pytest/testing/code/test_code.py
deleted file mode 100644
index 0db4ad2ab4c..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/code/test_code.py
+++ /dev/null
@@ -1,174 +0,0 @@
-import sys
-
-import _pytest._code
-import py
-import pytest
-
-
-def test_ne():
- code1 = _pytest._code.Code(compile('foo = "bar"', '', 'exec'))
- assert code1 == code1
- code2 = _pytest._code.Code(compile('foo = "baz"', '', 'exec'))
- assert code2 != code1
-
-def test_code_gives_back_name_for_not_existing_file():
- name = 'abc-123'
- co_code = compile("pass\n", name, 'exec')
- assert co_code.co_filename == name
- code = _pytest._code.Code(co_code)
- assert str(code.path) == name
- assert code.fullsource is None
-
-def test_code_with_class():
- class A:
- pass
- pytest.raises(TypeError, "_pytest._code.Code(A)")
-
-if True:
- def x():
- pass
-
-def test_code_fullsource():
- code = _pytest._code.Code(x)
- full = code.fullsource
- assert 'test_code_fullsource()' in str(full)
-
-def test_code_source():
- code = _pytest._code.Code(x)
- src = code.source()
- expected = """def x():
- pass"""
- assert str(src) == expected
-
-def test_frame_getsourcelineno_myself():
- def func():
- return sys._getframe(0)
- f = func()
- f = _pytest._code.Frame(f)
- source, lineno = f.code.fullsource, f.lineno
- assert source[lineno].startswith(" return sys._getframe(0)")
-
-def test_getstatement_empty_fullsource():
- def func():
- return sys._getframe(0)
- f = func()
- f = _pytest._code.Frame(f)
- prop = f.code.__class__.fullsource
- try:
- f.code.__class__.fullsource = None
- assert f.statement == _pytest._code.Source("")
- finally:
- f.code.__class__.fullsource = prop
-
-def test_code_from_func():
- co = _pytest._code.Code(test_frame_getsourcelineno_myself)
- assert co.firstlineno
- assert co.path
-
-
-
-def test_builtin_patch_unpatch(monkeypatch):
- cpy_builtin = py.builtin.builtins
- comp = cpy_builtin.compile
- def mycompile(*args, **kwargs):
- return comp(*args, **kwargs)
- class Sub(AssertionError):
- pass
- monkeypatch.setattr(cpy_builtin, 'AssertionError', Sub)
- monkeypatch.setattr(cpy_builtin, 'compile', mycompile)
- _pytest._code.patch_builtins()
- assert cpy_builtin.AssertionError != Sub
- assert cpy_builtin.compile != mycompile
- _pytest._code.unpatch_builtins()
- assert cpy_builtin.AssertionError is Sub
- assert cpy_builtin.compile == mycompile
-
-
-def test_unicode_handling():
- value = py.builtin._totext('\xc4\x85\xc4\x87\n', 'utf-8').encode('utf8')
- def f():
- raise Exception(value)
- excinfo = pytest.raises(Exception, f)
- str(excinfo)
- if sys.version_info[0] < 3:
- unicode(excinfo)
-
-
-@pytest.mark.skipif(sys.version_info[0] >= 3, reason='python 2 only issue')
-def test_unicode_handling_syntax_error():
- value = py.builtin._totext('\xc4\x85\xc4\x87\n', 'utf-8').encode('utf8')
- def f():
- raise SyntaxError('invalid syntax', (None, 1, 3, value))
- excinfo = pytest.raises(Exception, f)
- str(excinfo)
- if sys.version_info[0] < 3:
- unicode(excinfo)
-
-def test_code_getargs():
- def f1(x):
- pass
- c1 = _pytest._code.Code(f1)
- assert c1.getargs(var=True) == ('x',)
-
- def f2(x, *y):
- pass
- c2 = _pytest._code.Code(f2)
- assert c2.getargs(var=True) == ('x', 'y')
-
- def f3(x, **z):
- pass
- c3 = _pytest._code.Code(f3)
- assert c3.getargs(var=True) == ('x', 'z')
-
- def f4(x, *y, **z):
- pass
- c4 = _pytest._code.Code(f4)
- assert c4.getargs(var=True) == ('x', 'y', 'z')
-
-
-def test_frame_getargs():
- def f1(x):
- return sys._getframe(0)
- fr1 = _pytest._code.Frame(f1('a'))
- assert fr1.getargs(var=True) == [('x', 'a')]
-
- def f2(x, *y):
- return sys._getframe(0)
- fr2 = _pytest._code.Frame(f2('a', 'b', 'c'))
- assert fr2.getargs(var=True) == [('x', 'a'), ('y', ('b', 'c'))]
-
- def f3(x, **z):
- return sys._getframe(0)
- fr3 = _pytest._code.Frame(f3('a', b='c'))
- assert fr3.getargs(var=True) == [('x', 'a'), ('z', {'b': 'c'})]
-
- def f4(x, *y, **z):
- return sys._getframe(0)
- fr4 = _pytest._code.Frame(f4('a', 'b', c='d'))
- assert fr4.getargs(var=True) == [('x', 'a'), ('y', ('b',)),
- ('z', {'c': 'd'})]
-
-
-class TestExceptionInfo:
-
- def test_bad_getsource(self):
- try:
- if False: pass
- else: assert False
- except AssertionError:
- exci = _pytest._code.ExceptionInfo()
- assert exci.getrepr()
-
-
-class TestTracebackEntry:
-
- def test_getsource(self):
- try:
- if False: pass
- else: assert False
- except AssertionError:
- exci = _pytest._code.ExceptionInfo()
- entry = exci.traceback[0]
- source = entry.getsource()
- assert len(source) == 4
- assert 'else: assert False' in source[3]
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/code/test_excinfo.py b/tests/wpt/web-platform-tests/tools/pytest/testing/code/test_excinfo.py
deleted file mode 100644
index 2defa31035b..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/code/test_excinfo.py
+++ /dev/null
@@ -1,911 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import _pytest
-import py
-import pytest
-from _pytest._code.code import FormattedExcinfo, ReprExceptionInfo
-
-queue = py.builtin._tryimport('queue', 'Queue')
-
-failsonjython = pytest.mark.xfail("sys.platform.startswith('java')")
-from test_source import astonly
-
-try:
- import importlib
-except ImportError:
- invalidate_import_caches = None
-else:
- invalidate_import_caches = getattr(importlib, "invalidate_caches", None)
-
-import pytest
-pytest_version_info = tuple(map(int, pytest.__version__.split(".")[:3]))
-
-class TWMock:
- def __init__(self):
- self.lines = []
- def sep(self, sep, line=None):
- self.lines.append((sep, line))
- def line(self, line, **kw):
- self.lines.append(line)
- def markup(self, text, **kw):
- return text
-
- fullwidth = 80
-
-def test_excinfo_simple():
- try:
- raise ValueError
- except ValueError:
- info = _pytest._code.ExceptionInfo()
- assert info.type == ValueError
-
-def test_excinfo_getstatement():
- def g():
- raise ValueError
- def f():
- g()
- try:
- f()
- except ValueError:
- excinfo = _pytest._code.ExceptionInfo()
- linenumbers = [_pytest._code.getrawcode(f).co_firstlineno - 1 + 3,
- _pytest._code.getrawcode(f).co_firstlineno - 1 + 1,
- _pytest._code.getrawcode(g).co_firstlineno - 1 + 1, ]
- l = list(excinfo.traceback)
- foundlinenumbers = [x.lineno for x in l]
- assert foundlinenumbers == linenumbers
- #for x in info:
- # print "%s:%d %s" %(x.path.relto(root), x.lineno, x.statement)
- #xxx
-
-# testchain for getentries test below
-def f():
- #
- raise ValueError
- #
-def g():
- #
- __tracebackhide__ = True
- f()
- #
-def h():
- #
- g()
- #
-
-class TestTraceback_f_g_h:
- def setup_method(self, method):
- try:
- h()
- except ValueError:
- self.excinfo = _pytest._code.ExceptionInfo()
-
- def test_traceback_entries(self):
- tb = self.excinfo.traceback
- entries = list(tb)
- assert len(tb) == 4 # maybe fragile test
- assert len(entries) == 4 # maybe fragile test
- names = ['f', 'g', 'h']
- for entry in entries:
- try:
- names.remove(entry.frame.code.name)
- except ValueError:
- pass
- assert not names
-
- def test_traceback_entry_getsource(self):
- tb = self.excinfo.traceback
- s = str(tb[-1].getsource() )
- assert s.startswith("def f():")
- assert s.endswith("raise ValueError")
-
- @astonly
- @failsonjython
- def test_traceback_entry_getsource_in_construct(self):
- source = _pytest._code.Source("""\
- def xyz():
- try:
- raise ValueError
- except somenoname:
- pass
- xyz()
- """)
- try:
- exec (source.compile())
- except NameError:
- tb = _pytest._code.ExceptionInfo().traceback
- print (tb[-1].getsource())
- s = str(tb[-1].getsource())
- assert s.startswith("def xyz():\n try:")
- assert s.strip().endswith("except somenoname:")
-
- def test_traceback_cut(self):
- co = _pytest._code.Code(f)
- path, firstlineno = co.path, co.firstlineno
- traceback = self.excinfo.traceback
- newtraceback = traceback.cut(path=path, firstlineno=firstlineno)
- assert len(newtraceback) == 1
- newtraceback = traceback.cut(path=path, lineno=firstlineno+2)
- assert len(newtraceback) == 1
-
- def test_traceback_cut_excludepath(self, testdir):
- p = testdir.makepyfile("def f(): raise ValueError")
- excinfo = pytest.raises(ValueError, "p.pyimport().f()")
- basedir = py.path.local(pytest.__file__).dirpath()
- newtraceback = excinfo.traceback.cut(excludepath=basedir)
- for x in newtraceback:
- if hasattr(x, 'path'):
- assert not py.path.local(x.path).relto(basedir)
- assert newtraceback[-1].frame.code.path == p
-
- def test_traceback_filter(self):
- traceback = self.excinfo.traceback
- ntraceback = traceback.filter()
- assert len(ntraceback) == len(traceback) - 1
-
- def test_traceback_recursion_index(self):
- def f(n):
- if n < 10:
- n += 1
- f(n)
- excinfo = pytest.raises(RuntimeError, f, 8)
- traceback = excinfo.traceback
- recindex = traceback.recursionindex()
- assert recindex == 3
-
- def test_traceback_only_specific_recursion_errors(self, monkeypatch):
- def f(n):
- if n == 0:
- raise RuntimeError("hello")
- f(n-1)
-
- excinfo = pytest.raises(RuntimeError, f, 100)
- monkeypatch.delattr(excinfo.traceback.__class__, "recursionindex")
- repr = excinfo.getrepr()
- assert "RuntimeError: hello" in str(repr.reprcrash)
-
- def test_traceback_no_recursion_index(self):
- def do_stuff():
- raise RuntimeError
- def reraise_me():
- import sys
- exc, val, tb = sys.exc_info()
- py.builtin._reraise(exc, val, tb)
- def f(n):
- try:
- do_stuff()
- except:
- reraise_me()
- excinfo = pytest.raises(RuntimeError, f, 8)
- traceback = excinfo.traceback
- recindex = traceback.recursionindex()
- assert recindex is None
-
- def test_traceback_messy_recursion(self):
- #XXX: simplified locally testable version
- decorator = pytest.importorskip('decorator').decorator
-
- def log(f, *k, **kw):
- print('%s %s' % (k, kw))
- f(*k, **kw)
- log = decorator(log)
-
- def fail():
- raise ValueError('')
-
- fail = log(log(fail))
-
- excinfo = pytest.raises(ValueError, fail)
- assert excinfo.traceback.recursionindex() is None
-
-
-
- def test_traceback_getcrashentry(self):
- def i():
- __tracebackhide__ = True
- raise ValueError
- def h():
- i()
- def g():
- __tracebackhide__ = True
- h()
- def f():
- g()
-
- excinfo = pytest.raises(ValueError, f)
- tb = excinfo.traceback
- entry = tb.getcrashentry()
- co = _pytest._code.Code(h)
- assert entry.frame.code.path == co.path
- assert entry.lineno == co.firstlineno + 1
- assert entry.frame.code.name == 'h'
-
- def test_traceback_getcrashentry_empty(self):
- def g():
- __tracebackhide__ = True
- raise ValueError
- def f():
- __tracebackhide__ = True
- g()
-
- excinfo = pytest.raises(ValueError, f)
- tb = excinfo.traceback
- entry = tb.getcrashentry()
- co = _pytest._code.Code(g)
- assert entry.frame.code.path == co.path
- assert entry.lineno == co.firstlineno + 2
- assert entry.frame.code.name == 'g'
-
-def hello(x):
- x + 5
-
-def test_tbentry_reinterpret():
- try:
- hello("hello")
- except TypeError:
- excinfo = _pytest._code.ExceptionInfo()
- tbentry = excinfo.traceback[-1]
- msg = tbentry.reinterpret()
- assert msg.startswith("TypeError: ('hello' + 5)")
-
-def test_excinfo_exconly():
- excinfo = pytest.raises(ValueError, h)
- assert excinfo.exconly().startswith('ValueError')
- excinfo = pytest.raises(ValueError,
- "raise ValueError('hello\\nworld')")
- msg = excinfo.exconly(tryshort=True)
- assert msg.startswith('ValueError')
- assert msg.endswith("world")
-
-def test_excinfo_repr():
- excinfo = pytest.raises(ValueError, h)
- s = repr(excinfo)
- assert s == "<ExceptionInfo ValueError tblen=4>"
-
-def test_excinfo_str():
- excinfo = pytest.raises(ValueError, h)
- s = str(excinfo)
- assert s.startswith(__file__[:-9]) # pyc file and $py.class
- assert s.endswith("ValueError")
- assert len(s.split(":")) >= 3 # on windows it's 4
-
-def test_excinfo_errisinstance():
- excinfo = pytest.raises(ValueError, h)
- assert excinfo.errisinstance(ValueError)
-
-def test_excinfo_no_sourcecode():
- try:
- exec ("raise ValueError()")
- except ValueError:
- excinfo = _pytest._code.ExceptionInfo()
- s = str(excinfo.traceback[-1])
- if py.std.sys.version_info < (2,5):
- assert s == " File '<string>':1 in ?\n ???\n"
- else:
- assert s == " File '<string>':1 in <module>\n ???\n"
-
-def test_excinfo_no_python_sourcecode(tmpdir):
- #XXX: simplified locally testable version
- tmpdir.join('test.txt').write("{{ h()}}:")
-
- jinja2 = pytest.importorskip('jinja2')
- loader = jinja2.FileSystemLoader(str(tmpdir))
- env = jinja2.Environment(loader=loader)
- template = env.get_template('test.txt')
- excinfo = pytest.raises(ValueError,
- template.render, h=h)
- for item in excinfo.traceback:
- print(item) #XXX: for some reason jinja.Template.render is printed in full
- item.source # shouldnt fail
- if item.path.basename == 'test.txt':
- assert str(item.source) == '{{ h()}}:'
-
-
-def test_entrysource_Queue_example():
- try:
- queue.Queue().get(timeout=0.001)
- except queue.Empty:
- excinfo = _pytest._code.ExceptionInfo()
- entry = excinfo.traceback[-1]
- source = entry.getsource()
- assert source is not None
- s = str(source).strip()
- assert s.startswith("def get")
-
-def test_codepath_Queue_example():
- try:
- queue.Queue().get(timeout=0.001)
- except queue.Empty:
- excinfo = _pytest._code.ExceptionInfo()
- entry = excinfo.traceback[-1]
- path = entry.path
- assert isinstance(path, py.path.local)
- assert path.basename.lower() == "queue.py"
- assert path.check()
-
-class TestFormattedExcinfo:
- def pytest_funcarg__importasmod(self, request):
- def importasmod(source):
- source = _pytest._code.Source(source)
- tmpdir = request.getfuncargvalue("tmpdir")
- modpath = tmpdir.join("mod.py")
- tmpdir.ensure("__init__.py")
- modpath.write(source)
- if invalidate_import_caches is not None:
- invalidate_import_caches()
- return modpath.pyimport()
- return importasmod
-
- def excinfo_from_exec(self, source):
- source = _pytest._code.Source(source).strip()
- try:
- exec (source.compile())
- except KeyboardInterrupt:
- raise
- except:
- return _pytest._code.ExceptionInfo()
- assert 0, "did not raise"
-
- def test_repr_source(self):
- pr = FormattedExcinfo()
- source = _pytest._code.Source("""
- def f(x):
- pass
- """).strip()
- pr.flow_marker = "|"
- lines = pr.get_source(source, 0)
- assert len(lines) == 2
- assert lines[0] == "| def f(x):"
- assert lines[1] == " pass"
-
- def test_repr_source_excinfo(self):
- """ check if indentation is right """
- pr = FormattedExcinfo()
- excinfo = self.excinfo_from_exec("""
- def f():
- assert 0
- f()
- """)
- pr = FormattedExcinfo()
- source = pr._getentrysource(excinfo.traceback[-1])
- lines = pr.get_source(source, 1, excinfo)
- assert lines == [
- ' def f():',
- '> assert 0',
- 'E assert 0'
- ]
-
-
- def test_repr_source_not_existing(self):
- pr = FormattedExcinfo()
- co = compile("raise ValueError()", "", "exec")
- try:
- exec (co)
- except ValueError:
- excinfo = _pytest._code.ExceptionInfo()
- repr = pr.repr_excinfo(excinfo)
- assert repr.reprtraceback.reprentries[1].lines[0] == "> ???"
-
- def test_repr_many_line_source_not_existing(self):
- pr = FormattedExcinfo()
- co = compile("""
-a = 1
-raise ValueError()
-""", "", "exec")
- try:
- exec (co)
- except ValueError:
- excinfo = _pytest._code.ExceptionInfo()
- repr = pr.repr_excinfo(excinfo)
- assert repr.reprtraceback.reprentries[1].lines[0] == "> ???"
-
- def test_repr_source_failing_fullsource(self):
- pr = FormattedExcinfo()
-
- class FakeCode(object):
- class raw:
- co_filename = '?'
- path = '?'
- firstlineno = 5
-
- def fullsource(self):
- return None
- fullsource = property(fullsource)
-
- class FakeFrame(object):
- code = FakeCode()
- f_locals = {}
- f_globals = {}
-
- class FakeTracebackEntry(_pytest._code.Traceback.Entry):
- def __init__(self, tb):
- self.lineno = 5+3
-
- @property
- def frame(self):
- return FakeFrame()
-
- class Traceback(_pytest._code.Traceback):
- Entry = FakeTracebackEntry
-
- class FakeExcinfo(_pytest._code.ExceptionInfo):
- typename = "Foo"
- def __init__(self):
- pass
-
- def exconly(self, tryshort):
- return "EXC"
- def errisinstance(self, cls):
- return False
-
- excinfo = FakeExcinfo()
- class FakeRawTB(object):
- tb_next = None
- tb = FakeRawTB()
- excinfo.traceback = Traceback(tb)
-
- fail = IOError() # noqa
- repr = pr.repr_excinfo(excinfo)
- assert repr.reprtraceback.reprentries[0].lines[0] == "> ???"
-
- fail = py.error.ENOENT # noqa
- repr = pr.repr_excinfo(excinfo)
- assert repr.reprtraceback.reprentries[0].lines[0] == "> ???"
-
-
- def test_repr_local(self):
- p = FormattedExcinfo(showlocals=True)
- loc = {'y': 5, 'z': 7, 'x': 3, '@x': 2, '__builtins__': {}}
- reprlocals = p.repr_locals(loc)
- assert reprlocals.lines
- assert reprlocals.lines[0] == '__builtins__ = <builtins>'
- assert reprlocals.lines[1] == 'x = 3'
- assert reprlocals.lines[2] == 'y = 5'
- assert reprlocals.lines[3] == 'z = 7'
-
- def test_repr_tracebackentry_lines(self, importasmod):
- mod = importasmod("""
- def func1():
- raise ValueError("hello\\nworld")
- """)
- excinfo = pytest.raises(ValueError, mod.func1)
- excinfo.traceback = excinfo.traceback.filter()
- p = FormattedExcinfo()
- reprtb = p.repr_traceback_entry(excinfo.traceback[-1])
-
- # test as intermittent entry
- lines = reprtb.lines
- assert lines[0] == ' def func1():'
- assert lines[1] == '> raise ValueError("hello\\nworld")'
-
- # test as last entry
- p = FormattedExcinfo(showlocals=True)
- repr_entry = p.repr_traceback_entry(excinfo.traceback[-1], excinfo)
- lines = repr_entry.lines
- assert lines[0] == ' def func1():'
- assert lines[1] == '> raise ValueError("hello\\nworld")'
- assert lines[2] == 'E ValueError: hello'
- assert lines[3] == 'E world'
- assert not lines[4:]
-
- loc = repr_entry.reprlocals is not None
- loc = repr_entry.reprfileloc
- assert loc.path == mod.__file__
- assert loc.lineno == 3
- #assert loc.message == "ValueError: hello"
-
- def test_repr_tracebackentry_lines2(self, importasmod):
- mod = importasmod("""
- def func1(m, x, y, z):
- raise ValueError("hello\\nworld")
- """)
- excinfo = pytest.raises(ValueError, mod.func1, "m"*90, 5, 13, "z"*120)
- excinfo.traceback = excinfo.traceback.filter()
- entry = excinfo.traceback[-1]
- p = FormattedExcinfo(funcargs=True)
- reprfuncargs = p.repr_args(entry)
- assert reprfuncargs.args[0] == ('m', repr("m"*90))
- assert reprfuncargs.args[1] == ('x', '5')
- assert reprfuncargs.args[2] == ('y', '13')
- assert reprfuncargs.args[3] == ('z', repr("z" * 120))
-
- p = FormattedExcinfo(funcargs=True)
- repr_entry = p.repr_traceback_entry(entry)
- assert repr_entry.reprfuncargs.args == reprfuncargs.args
- tw = TWMock()
- repr_entry.toterminal(tw)
- assert tw.lines[0] == "m = " + repr('m' * 90)
- assert tw.lines[1] == "x = 5, y = 13"
- assert tw.lines[2] == "z = " + repr('z' * 120)
-
- def test_repr_tracebackentry_lines_var_kw_args(self, importasmod):
- mod = importasmod("""
- def func1(x, *y, **z):
- raise ValueError("hello\\nworld")
- """)
- excinfo = pytest.raises(ValueError, mod.func1, 'a', 'b', c='d')
- excinfo.traceback = excinfo.traceback.filter()
- entry = excinfo.traceback[-1]
- p = FormattedExcinfo(funcargs=True)
- reprfuncargs = p.repr_args(entry)
- assert reprfuncargs.args[0] == ('x', repr('a'))
- assert reprfuncargs.args[1] == ('y', repr(('b',)))
- assert reprfuncargs.args[2] == ('z', repr({'c': 'd'}))
-
- p = FormattedExcinfo(funcargs=True)
- repr_entry = p.repr_traceback_entry(entry)
- assert repr_entry.reprfuncargs.args == reprfuncargs.args
- tw = TWMock()
- repr_entry.toterminal(tw)
- assert tw.lines[0] == "x = 'a', y = ('b',), z = {'c': 'd'}"
-
- def test_repr_tracebackentry_short(self, importasmod):
- mod = importasmod("""
- def func1():
- raise ValueError("hello")
- def entry():
- func1()
- """)
- excinfo = pytest.raises(ValueError, mod.entry)
- p = FormattedExcinfo(style="short")
- reprtb = p.repr_traceback_entry(excinfo.traceback[-2])
- lines = reprtb.lines
- basename = py.path.local(mod.__file__).basename
- assert lines[0] == ' func1()'
- assert basename in str(reprtb.reprfileloc.path)
- assert reprtb.reprfileloc.lineno == 5
-
- # test last entry
- p = FormattedExcinfo(style="short")
- reprtb = p.repr_traceback_entry(excinfo.traceback[-1], excinfo)
- lines = reprtb.lines
- assert lines[0] == ' raise ValueError("hello")'
- assert lines[1] == 'E ValueError: hello'
- assert basename in str(reprtb.reprfileloc.path)
- assert reprtb.reprfileloc.lineno == 3
-
- def test_repr_tracebackentry_no(self, importasmod):
- mod = importasmod("""
- def func1():
- raise ValueError("hello")
- def entry():
- func1()
- """)
- excinfo = pytest.raises(ValueError, mod.entry)
- p = FormattedExcinfo(style="no")
- p.repr_traceback_entry(excinfo.traceback[-2])
-
- p = FormattedExcinfo(style="no")
- reprentry = p.repr_traceback_entry(excinfo.traceback[-1], excinfo)
- lines = reprentry.lines
- assert lines[0] == 'E ValueError: hello'
- assert not lines[1:]
-
- def test_repr_traceback_tbfilter(self, importasmod):
- mod = importasmod("""
- def f(x):
- raise ValueError(x)
- def entry():
- f(0)
- """)
- excinfo = pytest.raises(ValueError, mod.entry)
- p = FormattedExcinfo(tbfilter=True)
- reprtb = p.repr_traceback(excinfo)
- assert len(reprtb.reprentries) == 2
- p = FormattedExcinfo(tbfilter=False)
- reprtb = p.repr_traceback(excinfo)
- assert len(reprtb.reprentries) == 3
-
- def test_traceback_short_no_source(self, importasmod, monkeypatch):
- mod = importasmod("""
- def func1():
- raise ValueError("hello")
- def entry():
- func1()
- """)
- excinfo = pytest.raises(ValueError, mod.entry)
- from _pytest._code.code import Code
- monkeypatch.setattr(Code, 'path', 'bogus')
- excinfo.traceback[0].frame.code.path = "bogus"
- p = FormattedExcinfo(style="short")
- reprtb = p.repr_traceback_entry(excinfo.traceback[-2])
- lines = reprtb.lines
- last_p = FormattedExcinfo(style="short")
- last_reprtb = last_p.repr_traceback_entry(excinfo.traceback[-1], excinfo)
- last_lines = last_reprtb.lines
- monkeypatch.undo()
- assert lines[0] == ' func1()'
-
- assert last_lines[0] == ' raise ValueError("hello")'
- assert last_lines[1] == 'E ValueError: hello'
-
- def test_repr_traceback_and_excinfo(self, importasmod):
- mod = importasmod("""
- def f(x):
- raise ValueError(x)
- def entry():
- f(0)
- """)
- excinfo = pytest.raises(ValueError, mod.entry)
-
- for style in ("long", "short"):
- p = FormattedExcinfo(style=style)
- reprtb = p.repr_traceback(excinfo)
- assert len(reprtb.reprentries) == 2
- assert reprtb.style == style
- assert not reprtb.extraline
- repr = p.repr_excinfo(excinfo)
- assert repr.reprtraceback
- assert len(repr.reprtraceback.reprentries) == len(reprtb.reprentries)
- assert repr.reprcrash.path.endswith("mod.py")
- assert repr.reprcrash.message == "ValueError: 0"
-
- def test_repr_traceback_with_invalid_cwd(self, importasmod, monkeypatch):
- mod = importasmod("""
- def f(x):
- raise ValueError(x)
- def entry():
- f(0)
- """)
- excinfo = pytest.raises(ValueError, mod.entry)
-
- p = FormattedExcinfo()
- def raiseos():
- raise OSError(2)
- monkeypatch.setattr(py.std.os, 'getcwd', raiseos)
- assert p._makepath(__file__) == __file__
- p.repr_traceback(excinfo)
-
- def test_repr_excinfo_addouterr(self, importasmod):
- mod = importasmod("""
- def entry():
- raise ValueError()
- """)
- excinfo = pytest.raises(ValueError, mod.entry)
- repr = excinfo.getrepr()
- repr.addsection("title", "content")
- twmock = TWMock()
- repr.toterminal(twmock)
- assert twmock.lines[-1] == "content"
- assert twmock.lines[-2] == ("-", "title")
-
- def test_repr_excinfo_reprcrash(self, importasmod):
- mod = importasmod("""
- def entry():
- raise ValueError()
- """)
- excinfo = pytest.raises(ValueError, mod.entry)
- repr = excinfo.getrepr()
- assert repr.reprcrash.path.endswith("mod.py")
- assert repr.reprcrash.lineno == 3
- assert repr.reprcrash.message == "ValueError"
- assert str(repr.reprcrash).endswith("mod.py:3: ValueError")
-
- def test_repr_traceback_recursion(self, importasmod):
- mod = importasmod("""
- def rec2(x):
- return rec1(x+1)
- def rec1(x):
- return rec2(x-1)
- def entry():
- rec1(42)
- """)
- excinfo = pytest.raises(RuntimeError, mod.entry)
-
- for style in ("short", "long", "no"):
- p = FormattedExcinfo(style="short")
- reprtb = p.repr_traceback(excinfo)
- assert reprtb.extraline == "!!! Recursion detected (same locals & position)"
- assert str(reprtb)
-
- def test_tb_entry_AssertionError(self, importasmod):
- # probably this test is a bit redundant
- # as py/magic/testing/test_assertion.py
- # already tests correctness of
- # assertion-reinterpretation logic
- mod = importasmod("""
- def somefunc():
- x = 1
- assert x == 2
- """)
- excinfo = pytest.raises(AssertionError, mod.somefunc)
-
- p = FormattedExcinfo()
- reprentry = p.repr_traceback_entry(excinfo.traceback[-1], excinfo)
- lines = reprentry.lines
- assert lines[-1] == "E assert 1 == 2"
-
- def test_reprexcinfo_getrepr(self, importasmod):
- mod = importasmod("""
- def f(x):
- raise ValueError(x)
- def entry():
- f(0)
- """)
- excinfo = pytest.raises(ValueError, mod.entry)
-
- for style in ("short", "long", "no"):
- for showlocals in (True, False):
- repr = excinfo.getrepr(style=style, showlocals=showlocals)
- assert isinstance(repr, ReprExceptionInfo)
- assert repr.reprtraceback.style == style
-
- def test_reprexcinfo_unicode(self):
- from _pytest._code.code import TerminalRepr
- class MyRepr(TerminalRepr):
- def toterminal(self, tw):
- tw.line(py.builtin._totext("я", "utf-8"))
- x = py.builtin._totext(MyRepr())
- assert x == py.builtin._totext("я", "utf-8")
-
- def test_toterminal_long(self, importasmod):
- mod = importasmod("""
- def g(x):
- raise ValueError(x)
- def f():
- g(3)
- """)
- excinfo = pytest.raises(ValueError, mod.f)
- excinfo.traceback = excinfo.traceback.filter()
- repr = excinfo.getrepr()
- tw = TWMock()
- repr.toterminal(tw)
- assert tw.lines[0] == ""
- tw.lines.pop(0)
- assert tw.lines[0] == " def f():"
- assert tw.lines[1] == "> g(3)"
- assert tw.lines[2] == ""
- assert tw.lines[3].endswith("mod.py:5: ")
- assert tw.lines[4] == ("_ ", None)
- assert tw.lines[5] == ""
- assert tw.lines[6] == " def g(x):"
- assert tw.lines[7] == "> raise ValueError(x)"
- assert tw.lines[8] == "E ValueError: 3"
- assert tw.lines[9] == ""
- assert tw.lines[10].endswith("mod.py:3: ValueError")
-
- def test_toterminal_long_missing_source(self, importasmod, tmpdir):
- mod = importasmod("""
- def g(x):
- raise ValueError(x)
- def f():
- g(3)
- """)
- excinfo = pytest.raises(ValueError, mod.f)
- tmpdir.join('mod.py').remove()
- excinfo.traceback = excinfo.traceback.filter()
- repr = excinfo.getrepr()
- tw = TWMock()
- repr.toterminal(tw)
- assert tw.lines[0] == ""
- tw.lines.pop(0)
- assert tw.lines[0] == "> ???"
- assert tw.lines[1] == ""
- assert tw.lines[2].endswith("mod.py:5: ")
- assert tw.lines[3] == ("_ ", None)
- assert tw.lines[4] == ""
- assert tw.lines[5] == "> ???"
- assert tw.lines[6] == "E ValueError: 3"
- assert tw.lines[7] == ""
- assert tw.lines[8].endswith("mod.py:3: ValueError")
-
- def test_toterminal_long_incomplete_source(self, importasmod, tmpdir):
- mod = importasmod("""
- def g(x):
- raise ValueError(x)
- def f():
- g(3)
- """)
- excinfo = pytest.raises(ValueError, mod.f)
- tmpdir.join('mod.py').write('asdf')
- excinfo.traceback = excinfo.traceback.filter()
- repr = excinfo.getrepr()
- tw = TWMock()
- repr.toterminal(tw)
- assert tw.lines[0] == ""
- tw.lines.pop(0)
- assert tw.lines[0] == "> ???"
- assert tw.lines[1] == ""
- assert tw.lines[2].endswith("mod.py:5: ")
- assert tw.lines[3] == ("_ ", None)
- assert tw.lines[4] == ""
- assert tw.lines[5] == "> ???"
- assert tw.lines[6] == "E ValueError: 3"
- assert tw.lines[7] == ""
- assert tw.lines[8].endswith("mod.py:3: ValueError")
-
- def test_toterminal_long_filenames(self, importasmod):
- mod = importasmod("""
- def f():
- raise ValueError()
- """)
- excinfo = pytest.raises(ValueError, mod.f)
- tw = TWMock()
- path = py.path.local(mod.__file__)
- old = path.dirpath().chdir()
- try:
- repr = excinfo.getrepr(abspath=False)
- repr.toterminal(tw)
- line = tw.lines[-1]
- x = py.path.local().bestrelpath(path)
- if len(x) < len(str(path)):
- assert line == "mod.py:3: ValueError"
-
- repr = excinfo.getrepr(abspath=True)
- repr.toterminal(tw)
- line = tw.lines[-1]
- assert line == "%s:3: ValueError" %(path,)
- finally:
- old.chdir()
-
- @pytest.mark.parametrize('reproptions', [
- {'style': style, 'showlocals': showlocals,
- 'funcargs': funcargs, 'tbfilter': tbfilter
- } for style in ("long", "short", "no")
- for showlocals in (True, False)
- for tbfilter in (True, False)
- for funcargs in (True, False)])
- def test_format_excinfo(self, importasmod, reproptions):
- mod = importasmod("""
- def g(x):
- raise ValueError(x)
- def f():
- g(3)
- """)
- excinfo = pytest.raises(ValueError, mod.f)
- tw = py.io.TerminalWriter(stringio=True)
- repr = excinfo.getrepr(**reproptions)
- repr.toterminal(tw)
- assert tw.stringio.getvalue()
-
-
- def test_native_style(self):
- excinfo = self.excinfo_from_exec("""
- assert 0
- """)
- repr = excinfo.getrepr(style='native')
- assert "assert 0" in str(repr.reprcrash)
- s = str(repr)
- assert s.startswith('Traceback (most recent call last):\n File')
- assert s.endswith('\nAssertionError: assert 0')
- assert 'exec (source.compile())' in s
- # python 2.4 fails to get the source line for the assert
- if py.std.sys.version_info >= (2, 5):
- assert s.count('assert 0') == 2
-
- def test_traceback_repr_style(self, importasmod):
- mod = importasmod("""
- def f():
- g()
- def g():
- h()
- def h():
- i()
- def i():
- raise ValueError()
- """)
- excinfo = pytest.raises(ValueError, mod.f)
- excinfo.traceback = excinfo.traceback.filter()
- excinfo.traceback[1].set_repr_style("short")
- excinfo.traceback[2].set_repr_style("short")
- r = excinfo.getrepr(style="long")
- tw = TWMock()
- r.toterminal(tw)
- for line in tw.lines: print (line)
- assert tw.lines[0] == ""
- assert tw.lines[1] == " def f():"
- assert tw.lines[2] == "> g()"
- assert tw.lines[3] == ""
- assert tw.lines[4].endswith("mod.py:3: ")
- assert tw.lines[5] == ("_ ", None)
- assert tw.lines[6].endswith("in g")
- assert tw.lines[7] == " h()"
- assert tw.lines[8].endswith("in h")
- assert tw.lines[9] == " i()"
- assert tw.lines[10] == ("_ ", None)
- assert tw.lines[11] == ""
- assert tw.lines[12] == " def i():"
- assert tw.lines[13] == "> raise ValueError()"
- assert tw.lines[14] == "E ValueError"
- assert tw.lines[15] == ""
- assert tw.lines[16].endswith("mod.py:9: ValueError")
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/code/test_source.py b/tests/wpt/web-platform-tests/tools/pytest/testing/code/test_source.py
deleted file mode 100644
index 007ad1433aa..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/code/test_source.py
+++ /dev/null
@@ -1,659 +0,0 @@
-# flake8: noqa
-# disable flake check on this file because some constructs are strange
-# or redundant on purpose and can't be disable on a line-by-line basis
-import sys
-
-import _pytest._code
-import py
-import pytest
-from _pytest._code import Source
-from _pytest._code.source import _ast
-
-if _ast is not None:
- astonly = pytest.mark.nothing
-else:
- astonly = pytest.mark.xfail("True", reason="only works with AST-compile")
-
-failsonjython = pytest.mark.xfail("sys.platform.startswith('java')")
-
-def test_source_str_function():
- x = Source("3")
- assert str(x) == "3"
-
- x = Source(" 3")
- assert str(x) == "3"
-
- x = Source("""
- 3
- """, rstrip=False)
- assert str(x) == "\n3\n "
-
- x = Source("""
- 3
- """, rstrip=True)
- assert str(x) == "\n3"
-
-def test_unicode():
- try:
- unicode
- except NameError:
- return
- x = Source(unicode("4"))
- assert str(x) == "4"
- co = _pytest._code.compile(unicode('u"\xc3\xa5"', 'utf8'), mode='eval')
- val = eval(co)
- assert isinstance(val, unicode)
-
-def test_source_from_function():
- source = _pytest._code.Source(test_source_str_function)
- assert str(source).startswith('def test_source_str_function():')
-
-def test_source_from_method():
- class TestClass:
- def test_method(self):
- pass
- source = _pytest._code.Source(TestClass().test_method)
- assert source.lines == ["def test_method(self):",
- " pass"]
-
-def test_source_from_lines():
- lines = ["a \n", "b\n", "c"]
- source = _pytest._code.Source(lines)
- assert source.lines == ['a ', 'b', 'c']
-
-def test_source_from_inner_function():
- def f():
- pass
- source = _pytest._code.Source(f, deindent=False)
- assert str(source).startswith(' def f():')
- source = _pytest._code.Source(f)
- assert str(source).startswith('def f():')
-
-def test_source_putaround_simple():
- source = Source("raise ValueError")
- source = source.putaround(
- "try:", """\
- except ValueError:
- x = 42
- else:
- x = 23""")
- assert str(source)=="""\
-try:
- raise ValueError
-except ValueError:
- x = 42
-else:
- x = 23"""
-
-def test_source_putaround():
- source = Source()
- source = source.putaround("""
- if 1:
- x=1
- """)
- assert str(source).strip() == "if 1:\n x=1"
-
-def test_source_strips():
- source = Source("")
- assert source == Source()
- assert str(source) == ''
- assert source.strip() == source
-
-def test_source_strip_multiline():
- source = Source()
- source.lines = ["", " hello", " "]
- source2 = source.strip()
- assert source2.lines == [" hello"]
-
-def test_syntaxerror_rerepresentation():
- ex = pytest.raises(SyntaxError, _pytest._code.compile, 'xyz xyz')
- assert ex.value.lineno == 1
- assert ex.value.offset in (4,7) # XXX pypy/jython versus cpython?
- assert ex.value.text.strip(), 'x x'
-
-def test_isparseable():
- assert Source("hello").isparseable()
- assert Source("if 1:\n pass").isparseable()
- assert Source(" \nif 1:\n pass").isparseable()
- assert not Source("if 1:\n").isparseable()
- assert not Source(" \nif 1:\npass").isparseable()
- assert not Source(chr(0)).isparseable()
-
-class TestAccesses:
- source = Source("""\
- def f(x):
- pass
- def g(x):
- pass
- """)
- def test_getrange(self):
- x = self.source[0:2]
- assert x.isparseable()
- assert len(x.lines) == 2
- assert str(x) == "def f(x):\n pass"
-
- def test_getline(self):
- x = self.source[0]
- assert x == "def f(x):"
-
- def test_len(self):
- assert len(self.source) == 4
-
- def test_iter(self):
- l = [x for x in self.source]
- assert len(l) == 4
-
-class TestSourceParsingAndCompiling:
- source = Source("""\
- def f(x):
- assert (x ==
- 3 +
- 4)
- """).strip()
-
- def test_compile(self):
- co = _pytest._code.compile("x=3")
- d = {}
- exec (co, d)
- assert d['x'] == 3
-
- def test_compile_and_getsource_simple(self):
- co = _pytest._code.compile("x=3")
- exec (co)
- source = _pytest._code.Source(co)
- assert str(source) == "x=3"
-
- def test_compile_and_getsource_through_same_function(self):
- def gensource(source):
- return _pytest._code.compile(source)
- co1 = gensource("""
- def f():
- raise KeyError()
- """)
- co2 = gensource("""
- def f():
- raise ValueError()
- """)
- source1 = py.std.inspect.getsource(co1)
- assert 'KeyError' in source1
- source2 = py.std.inspect.getsource(co2)
- assert 'ValueError' in source2
-
- def test_getstatement(self):
- #print str(self.source)
- ass = str(self.source[1:])
- for i in range(1, 4):
- #print "trying start in line %r" % self.source[i]
- s = self.source.getstatement(i)
- #x = s.deindent()
- assert str(s) == ass
-
- def test_getstatementrange_triple_quoted(self):
- #print str(self.source)
- source = Source("""hello('''
- ''')""")
- s = source.getstatement(0)
- assert s == str(source)
- s = source.getstatement(1)
- assert s == str(source)
-
- @astonly
- def test_getstatementrange_within_constructs(self):
- source = Source("""\
- try:
- try:
- raise ValueError
- except SomeThing:
- pass
- finally:
- 42
- """)
- assert len(source) == 7
- # check all lineno's that could occur in a traceback
- #assert source.getstatementrange(0) == (0, 7)
- #assert source.getstatementrange(1) == (1, 5)
- assert source.getstatementrange(2) == (2, 3)
- assert source.getstatementrange(3) == (3, 4)
- assert source.getstatementrange(4) == (4, 5)
- #assert source.getstatementrange(5) == (0, 7)
- assert source.getstatementrange(6) == (6, 7)
-
- def test_getstatementrange_bug(self):
- source = Source("""\
- try:
- x = (
- y +
- z)
- except:
- pass
- """)
- assert len(source) == 6
- assert source.getstatementrange(2) == (1, 4)
-
- def test_getstatementrange_bug2(self):
- source = Source("""\
- assert (
- 33
- ==
- [
- X(3,
- b=1, c=2
- ),
- ]
- )
- """)
- assert len(source) == 9
- assert source.getstatementrange(5) == (0, 9)
-
- def test_getstatementrange_ast_issue58(self):
- source = Source("""\
-
- def test_some():
- for a in [a for a in
- CAUSE_ERROR]: pass
-
- x = 3
- """)
- assert getstatement(2, source).lines == source.lines[2:3]
- assert getstatement(3, source).lines == source.lines[3:4]
-
- @pytest.mark.skipif("sys.version_info < (2,6)")
- def test_getstatementrange_out_of_bounds_py3(self):
- source = Source("if xxx:\n from .collections import something")
- r = source.getstatementrange(1)
- assert r == (1,2)
-
- def test_getstatementrange_with_syntaxerror_issue7(self):
- source = Source(":")
- pytest.raises(SyntaxError, lambda: source.getstatementrange(0))
-
- @pytest.mark.skipif("sys.version_info < (2,6)")
- def test_compile_to_ast(self):
- import ast
- source = Source("x = 4")
- mod = source.compile(flag=ast.PyCF_ONLY_AST)
- assert isinstance(mod, ast.Module)
- compile(mod, "<filename>", "exec")
-
- def test_compile_and_getsource(self):
- co = self.source.compile()
- py.builtin.exec_(co, globals())
- f(7)
- excinfo = pytest.raises(AssertionError, "f(6)")
- frame = excinfo.traceback[-1].frame
- stmt = frame.code.fullsource.getstatement(frame.lineno)
- #print "block", str(block)
- assert str(stmt).strip().startswith('assert')
-
- def test_compilefuncs_and_path_sanity(self):
- def check(comp, name):
- co = comp(self.source, name)
- if not name:
- expected = "codegen %s:%d>" %(mypath, mylineno+2+1)
- else:
- expected = "codegen %r %s:%d>" % (name, mypath, mylineno+2+1)
- fn = co.co_filename
- assert fn.endswith(expected)
-
- mycode = _pytest._code.Code(self.test_compilefuncs_and_path_sanity)
- mylineno = mycode.firstlineno
- mypath = mycode.path
-
- for comp in _pytest._code.compile, _pytest._code.Source.compile:
- for name in '', None, 'my':
- yield check, comp, name
-
- def test_offsetless_synerr(self):
- pytest.raises(SyntaxError, _pytest._code.compile, "lambda a,a: 0", mode='eval')
-
-def test_getstartingblock_singleline():
- class A:
- def __init__(self, *args):
- frame = sys._getframe(1)
- self.source = _pytest._code.Frame(frame).statement
-
- x = A('x', 'y')
-
- l = [i for i in x.source.lines if i.strip()]
- assert len(l) == 1
-
-def test_getstartingblock_multiline():
- class A:
- def __init__(self, *args):
- frame = sys._getframe(1)
- self.source = _pytest._code.Frame(frame).statement
-
- x = A('x',
- 'y' \
- ,
- 'z')
-
- l = [i for i in x.source.lines if i.strip()]
- assert len(l) == 4
-
-def test_getline_finally():
- def c(): pass
- excinfo = pytest.raises(TypeError, """
- teardown = None
- try:
- c(1)
- finally:
- if teardown:
- teardown()
- """)
- source = excinfo.traceback[-1].statement
- assert str(source).strip() == 'c(1)'
-
-def test_getfuncsource_dynamic():
- source = """
- def f():
- raise ValueError
-
- def g(): pass
- """
- co = _pytest._code.compile(source)
- py.builtin.exec_(co, globals())
- assert str(_pytest._code.Source(f)).strip() == 'def f():\n raise ValueError'
- assert str(_pytest._code.Source(g)).strip() == 'def g(): pass'
-
-
-def test_getfuncsource_with_multine_string():
- def f():
- c = '''while True:
- pass
-'''
- assert str(_pytest._code.Source(f)).strip() == "def f():\n c = '''while True:\n pass\n'''"
-
-
-def test_deindent():
- from _pytest._code.source import deindent as deindent
- assert deindent(['\tfoo', '\tbar', ]) == ['foo', 'bar']
-
- def f():
- c = '''while True:
- pass
-'''
- import inspect
- lines = deindent(inspect.getsource(f).splitlines())
- assert lines == ["def f():", " c = '''while True:", " pass", "'''"]
-
- source = """
- def f():
- def g():
- pass
- """
- lines = deindent(source.splitlines())
- assert lines == ['', 'def f():', ' def g():', ' pass', ' ']
-
-@pytest.mark.xfail("sys.version_info[:3] < (2,7,0) or "
- "((3,0) <= sys.version_info[:2] < (3,2))")
-def test_source_of_class_at_eof_without_newline(tmpdir):
- # this test fails because the implicit inspect.getsource(A) below
- # does not return the "x = 1" last line.
- source = _pytest._code.Source('''
- class A(object):
- def method(self):
- x = 1
- ''')
- path = tmpdir.join("a.py")
- path.write(source)
- s2 = _pytest._code.Source(tmpdir.join("a.py").pyimport().A)
- assert str(source).strip() == str(s2).strip()
-
-if True:
- def x():
- pass
-
-def test_getsource_fallback():
- from _pytest._code.source import getsource
- expected = """def x():
- pass"""
- src = getsource(x)
- assert src == expected
-
-def test_idem_compile_and_getsource():
- from _pytest._code.source import getsource
- expected = "def x(): pass"
- co = _pytest._code.compile(expected)
- src = getsource(co)
- assert src == expected
-
-def test_findsource_fallback():
- from _pytest._code.source import findsource
- src, lineno = findsource(x)
- assert 'test_findsource_simple' in str(src)
- assert src[lineno] == ' def x():'
-
-def test_findsource():
- from _pytest._code.source import findsource
- co = _pytest._code.compile("""if 1:
- def x():
- pass
-""")
-
- src, lineno = findsource(co)
- assert 'if 1:' in str(src)
-
- d = {}
- eval(co, d)
- src, lineno = findsource(d['x'])
- assert 'if 1:' in str(src)
- assert src[lineno] == " def x():"
-
-
-def test_getfslineno():
- from _pytest._code import getfslineno
-
- def f(x):
- pass
-
- fspath, lineno = getfslineno(f)
-
- assert fspath.basename == "test_source.py"
- assert lineno == _pytest._code.getrawcode(f).co_firstlineno - 1 # see findsource
-
- class A(object):
- pass
-
- fspath, lineno = getfslineno(A)
-
- _, A_lineno = py.std.inspect.findsource(A)
- assert fspath.basename == "test_source.py"
- assert lineno == A_lineno
-
- assert getfslineno(3) == ("", -1)
- class B:
- pass
- B.__name__ = "B2"
- assert getfslineno(B)[1] == -1
-
-def test_code_of_object_instance_with_call():
- class A:
- pass
- pytest.raises(TypeError, lambda: _pytest._code.Source(A()))
- class WithCall:
- def __call__(self):
- pass
-
- code = _pytest._code.Code(WithCall())
- assert 'pass' in str(code.source())
-
- class Hello(object):
- def __call__(self):
- pass
- pytest.raises(TypeError, lambda: _pytest._code.Code(Hello))
-
-
-def getstatement(lineno, source):
- from _pytest._code.source import getstatementrange_ast
- source = _pytest._code.Source(source, deindent=False)
- ast, start, end = getstatementrange_ast(lineno, source)
- return source[start:end]
-
-def test_oneline():
- source = getstatement(0, "raise ValueError")
- assert str(source) == "raise ValueError"
-
-def test_comment_and_no_newline_at_end():
- from _pytest._code.source import getstatementrange_ast
- source = Source(['def test_basic_complex():',
- ' assert 1 == 2',
- '# vim: filetype=pyopencl:fdm=marker'])
- ast, start, end = getstatementrange_ast(1, source)
- assert end == 2
-
-def test_oneline_and_comment():
- source = getstatement(0, "raise ValueError\n#hello")
- assert str(source) == "raise ValueError"
-
-@pytest.mark.xfail(hasattr(sys, "pypy_version_info"),
- reason='does not work on pypy')
-def test_comments():
- source = '''def test():
- "comment 1"
- x = 1
- # comment 2
- # comment 3
-
- assert False
-
-"""
-comment 4
-"""
-'''
- for line in range(2,6):
- assert str(getstatement(line, source)) == ' x = 1'
- for line in range(6,10):
- assert str(getstatement(line, source)) == ' assert False'
- assert str(getstatement(10, source)) == '"""'
-
-def test_comment_in_statement():
- source = '''test(foo=1,
- # comment 1
- bar=2)
-'''
- for line in range(1,3):
- assert str(getstatement(line, source)) == \
- 'test(foo=1,\n # comment 1\n bar=2)'
-
-def test_single_line_else():
- source = getstatement(1, "if False: 2\nelse: 3")
- assert str(source) == "else: 3"
-
-def test_single_line_finally():
- source = getstatement(1, "try: 1\nfinally: 3")
- assert str(source) == "finally: 3"
-
-def test_issue55():
- source = ('def round_trip(dinp):\n assert 1 == dinp\n'
- 'def test_rt():\n round_trip("""\n""")\n')
- s = getstatement(3, source)
- assert str(s) == ' round_trip("""\n""")'
-
-
-def XXXtest_multiline():
- source = getstatement(0, """\
-raise ValueError(
- 23
-)
-x = 3
-""")
- assert str(source) == "raise ValueError(\n 23\n)"
-
-class TestTry:
- pytestmark = astonly
- source = """\
-try:
- raise ValueError
-except Something:
- raise IndexError(1)
-else:
- raise KeyError()
-"""
-
- def test_body(self):
- source = getstatement(1, self.source)
- assert str(source) == " raise ValueError"
-
- def test_except_line(self):
- source = getstatement(2, self.source)
- assert str(source) == "except Something:"
-
- def test_except_body(self):
- source = getstatement(3, self.source)
- assert str(source) == " raise IndexError(1)"
-
- def test_else(self):
- source = getstatement(5, self.source)
- assert str(source) == " raise KeyError()"
-
-class TestTryFinally:
- source = """\
-try:
- raise ValueError
-finally:
- raise IndexError(1)
-"""
-
- def test_body(self):
- source = getstatement(1, self.source)
- assert str(source) == " raise ValueError"
-
- def test_finally(self):
- source = getstatement(3, self.source)
- assert str(source) == " raise IndexError(1)"
-
-
-
-class TestIf:
- pytestmark = astonly
- source = """\
-if 1:
- y = 3
-elif False:
- y = 5
-else:
- y = 7
-"""
-
- def test_body(self):
- source = getstatement(1, self.source)
- assert str(source) == " y = 3"
-
- def test_elif_clause(self):
- source = getstatement(2, self.source)
- assert str(source) == "elif False:"
-
- def test_elif(self):
- source = getstatement(3, self.source)
- assert str(source) == " y = 5"
-
- def test_else(self):
- source = getstatement(5, self.source)
- assert str(source) == " y = 7"
-
-def test_semicolon():
- s = """\
-hello ; pytest.skip()
-"""
- source = getstatement(0, s)
- assert str(source) == s.strip()
-
-def test_def_online():
- s = """\
-def func(): raise ValueError(42)
-
-def something():
- pass
-"""
- source = getstatement(0, s)
- assert str(source) == "def func(): raise ValueError(42)"
-
-def XXX_test_expression_multiline():
- source = """\
-something
-'''
-'''"""
- result = getstatement(1, source)
- assert str(result) == "'''\n'''"
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/cx_freeze/install_cx_freeze.py b/tests/wpt/web-platform-tests/tools/pytest/testing/cx_freeze/install_cx_freeze.py
deleted file mode 100644
index 83dce87aa56..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/cx_freeze/install_cx_freeze.py
+++ /dev/null
@@ -1,64 +0,0 @@
-"""
-Installs cx_freeze from source, but first patching
-setup.py as described here:
-
-http://stackoverflow.com/questions/25107697/compiling-cx-freeze-under-ubuntu
-"""
-import glob
-import tarfile
-import os
-import sys
-import platform
-import py
-
-if __name__ == '__main__':
- if 'ubuntu' not in platform.version().lower():
-
- print('Not Ubuntu, installing using pip. (platform.version() is %r)' %
- platform.version())
- res = os.system('pip install cx_freeze')
- if res != 0:
- sys.exit(res)
- sys.exit(0)
-
- rootdir = py.path.local.make_numbered_dir(prefix='cx_freeze')
-
- res = os.system('pip install --download %s --no-use-wheel '
- 'cx_freeze' % rootdir)
- if res != 0:
- sys.exit(res)
-
- packages = glob.glob('%s/*.tar.gz' % rootdir)
- assert len(packages) == 1
- tar_filename = packages[0]
-
- tar_file = tarfile.open(tar_filename)
- try:
- tar_file.extractall(path=str(rootdir))
- finally:
- tar_file.close()
-
- basename = os.path.basename(tar_filename).replace('.tar.gz', '')
- setup_py_filename = '%s/%s/setup.py' % (rootdir, basename)
- with open(setup_py_filename) as f:
- lines = f.readlines()
-
- line_to_patch = 'if not vars.get("Py_ENABLE_SHARED", 0):'
- for index, line in enumerate(lines):
- if line_to_patch in line:
- indent = line[:line.index(line_to_patch)]
- lines[index] = indent + 'if True:\n'
- print('Patched line %d' % (index + 1))
- break
- else:
- sys.exit('Could not find line in setup.py to patch!')
-
- with open(setup_py_filename, 'w') as f:
- f.writelines(lines)
-
- os.chdir('%s/%s' % (rootdir, basename))
- res = os.system('python setup.py install')
- if res != 0:
- sys.exit(res)
-
- sys.exit(0)
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/cx_freeze/runtests_script.py b/tests/wpt/web-platform-tests/tools/pytest/testing/cx_freeze/runtests_script.py
deleted file mode 100644
index f2b032d7655..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/cx_freeze/runtests_script.py
+++ /dev/null
@@ -1,9 +0,0 @@
-"""
-This is the script that is actually frozen into an executable: simply executes
-py.test main().
-"""
-
-if __name__ == '__main__':
- import sys
- import pytest
- sys.exit(pytest.main()) \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/cx_freeze/runtests_setup.py b/tests/wpt/web-platform-tests/tools/pytest/testing/cx_freeze/runtests_setup.py
deleted file mode 100644
index a2874a655eb..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/cx_freeze/runtests_setup.py
+++ /dev/null
@@ -1,15 +0,0 @@
-"""
-Sample setup.py script that generates an executable with pytest runner embedded.
-"""
-if __name__ == '__main__':
- from cx_Freeze import setup, Executable
- import pytest
-
- setup(
- name="runtests",
- version="0.1",
- description="exemple of how embedding py.test into an executable using cx_freeze",
- executables=[Executable("runtests_script.py")],
- options={"build_exe": {'includes': pytest.freeze_includes()}},
- )
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/cx_freeze/tests/test_trivial.py b/tests/wpt/web-platform-tests/tools/pytest/testing/cx_freeze/tests/test_trivial.py
deleted file mode 100644
index d8a572baaed..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/cx_freeze/tests/test_trivial.py
+++ /dev/null
@@ -1,6 +0,0 @@
-
-def test_upper():
- assert 'foo'.upper() == 'FOO'
-
-def test_lower():
- assert 'FOO'.lower() == 'foo' \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/cx_freeze/tox_run.py b/tests/wpt/web-platform-tests/tools/pytest/testing/cx_freeze/tox_run.py
deleted file mode 100644
index e8df2684bb1..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/cx_freeze/tox_run.py
+++ /dev/null
@@ -1,15 +0,0 @@
-"""
-Called by tox.ini: uses the generated executable to run the tests in ./tests/
-directory.
-
-.. note:: somehow calling "build/runtests_script" directly from tox doesn't
- seem to work (at least on Windows).
-"""
-if __name__ == '__main__':
- import os
- import sys
-
- executable = os.path.join(os.getcwd(), 'build', 'runtests_script')
- if sys.platform.startswith('win'):
- executable += '.exe'
- sys.exit(os.system('%s tests' % executable)) \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/python/collect.py b/tests/wpt/web-platform-tests/tools/pytest/testing/python/collect.py
deleted file mode 100644
index 22433da7716..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/python/collect.py
+++ /dev/null
@@ -1,1200 +0,0 @@
-# -*- coding: utf-8 -*-
-import sys
-from textwrap import dedent
-
-import _pytest._code
-import py
-import pytest
-from _pytest.main import EXIT_NOTESTSCOLLECTED
-
-
-class TestModule:
- def test_failing_import(self, testdir):
- modcol = testdir.getmodulecol("import alksdjalskdjalkjals")
- pytest.raises(ImportError, modcol.collect)
- pytest.raises(ImportError, modcol.collect)
-
- def test_import_duplicate(self, testdir):
- a = testdir.mkdir("a")
- b = testdir.mkdir("b")
- p = a.ensure("test_whatever.py")
- p.pyimport()
- del py.std.sys.modules['test_whatever']
- b.ensure("test_whatever.py")
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*import*mismatch*",
- "*imported*test_whatever*",
- "*%s*" % a.join("test_whatever.py"),
- "*not the same*",
- "*%s*" % b.join("test_whatever.py"),
- "*HINT*",
- ])
-
- def test_import_prepend_append(self, testdir, monkeypatch):
- syspath = list(sys.path)
- monkeypatch.setattr(sys, "path", syspath)
- root1 = testdir.mkdir("root1")
- root2 = testdir.mkdir("root2")
- root1.ensure("x456.py")
- root2.ensure("x456.py")
- p = root2.join("test_x456.py")
- monkeypatch.syspath_prepend(str(root1))
- p.write(dedent("""\
- import x456
- def test():
- assert x456.__file__.startswith(%r)
- """ % str(root2)))
- with root2.as_cwd():
- reprec = testdir.inline_run("--import-mode=append")
- reprec.assertoutcome(passed=0, failed=1)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
- def test_syntax_error_in_module(self, testdir):
- modcol = testdir.getmodulecol("this is a syntax error")
- pytest.raises(modcol.CollectError, modcol.collect)
- pytest.raises(modcol.CollectError, modcol.collect)
-
- def test_module_considers_pluginmanager_at_import(self, testdir):
- modcol = testdir.getmodulecol("pytest_plugins='xasdlkj',")
- pytest.raises(ImportError, lambda: modcol.obj)
-
-class TestClass:
- def test_class_with_init_warning(self, testdir):
- testdir.makepyfile("""
- class TestClass1:
- def __init__(self):
- pass
- """)
- result = testdir.runpytest("-rw")
- result.stdout.fnmatch_lines_random("""
- WC1*test_class_with_init_warning.py*__init__*
- """)
-
- def test_class_subclassobject(self, testdir):
- testdir.getmodulecol("""
- class test(object):
- pass
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*collected 0*",
- ])
-
- def test_setup_teardown_class_as_classmethod(self, testdir):
- testdir.makepyfile(test_mod1="""
- class TestClassMethod:
- @classmethod
- def setup_class(cls):
- pass
- def test_1(self):
- pass
- @classmethod
- def teardown_class(cls):
- pass
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*1 passed*",
- ])
-
- def test_issue1035_obj_has_getattr(self, testdir):
- modcol = testdir.getmodulecol("""
- class Chameleon(object):
- def __getattr__(self, name):
- return True
- chameleon = Chameleon()
- """)
- colitems = modcol.collect()
- assert len(colitems) == 0
-
-
-class TestGenerator:
- def test_generative_functions(self, testdir):
- modcol = testdir.getmodulecol("""
- def func1(arg, arg2):
- assert arg == arg2
-
- def test_gen():
- yield func1, 17, 3*5
- yield func1, 42, 6*7
- """)
- colitems = modcol.collect()
- assert len(colitems) == 1
- gencol = colitems[0]
- assert isinstance(gencol, pytest.Generator)
- gencolitems = gencol.collect()
- assert len(gencolitems) == 2
- assert isinstance(gencolitems[0], pytest.Function)
- assert isinstance(gencolitems[1], pytest.Function)
- assert gencolitems[0].name == '[0]'
- assert gencolitems[0].obj.__name__ == 'func1'
-
- def test_generative_methods(self, testdir):
- modcol = testdir.getmodulecol("""
- def func1(arg, arg2):
- assert arg == arg2
- class TestGenMethods:
- def test_gen(self):
- yield func1, 17, 3*5
- yield func1, 42, 6*7
- """)
- gencol = modcol.collect()[0].collect()[0].collect()[0]
- assert isinstance(gencol, pytest.Generator)
- gencolitems = gencol.collect()
- assert len(gencolitems) == 2
- assert isinstance(gencolitems[0], pytest.Function)
- assert isinstance(gencolitems[1], pytest.Function)
- assert gencolitems[0].name == '[0]'
- assert gencolitems[0].obj.__name__ == 'func1'
-
- def test_generative_functions_with_explicit_names(self, testdir):
- modcol = testdir.getmodulecol("""
- def func1(arg, arg2):
- assert arg == arg2
-
- def test_gen():
- yield "seventeen", func1, 17, 3*5
- yield "fortytwo", func1, 42, 6*7
- """)
- colitems = modcol.collect()
- assert len(colitems) == 1
- gencol = colitems[0]
- assert isinstance(gencol, pytest.Generator)
- gencolitems = gencol.collect()
- assert len(gencolitems) == 2
- assert isinstance(gencolitems[0], pytest.Function)
- assert isinstance(gencolitems[1], pytest.Function)
- assert gencolitems[0].name == "['seventeen']"
- assert gencolitems[0].obj.__name__ == 'func1'
- assert gencolitems[1].name == "['fortytwo']"
- assert gencolitems[1].obj.__name__ == 'func1'
-
- def test_generative_functions_unique_explicit_names(self, testdir):
- # generative
- modcol = testdir.getmodulecol("""
- def func(): pass
- def test_gen():
- yield "name", func
- yield "name", func
- """)
- colitems = modcol.collect()
- assert len(colitems) == 1
- gencol = colitems[0]
- assert isinstance(gencol, pytest.Generator)
- pytest.raises(ValueError, "gencol.collect()")
-
- def test_generative_methods_with_explicit_names(self, testdir):
- modcol = testdir.getmodulecol("""
- def func1(arg, arg2):
- assert arg == arg2
- class TestGenMethods:
- def test_gen(self):
- yield "m1", func1, 17, 3*5
- yield "m2", func1, 42, 6*7
- """)
- gencol = modcol.collect()[0].collect()[0].collect()[0]
- assert isinstance(gencol, pytest.Generator)
- gencolitems = gencol.collect()
- assert len(gencolitems) == 2
- assert isinstance(gencolitems[0], pytest.Function)
- assert isinstance(gencolitems[1], pytest.Function)
- assert gencolitems[0].name == "['m1']"
- assert gencolitems[0].obj.__name__ == 'func1'
- assert gencolitems[1].name == "['m2']"
- assert gencolitems[1].obj.__name__ == 'func1'
-
- def test_order_of_execution_generator_same_codeline(self, testdir, tmpdir):
- o = testdir.makepyfile("""
- def test_generative_order_of_execution():
- import py, pytest
- test_list = []
- expected_list = list(range(6))
-
- def list_append(item):
- test_list.append(item)
-
- def assert_order_of_execution():
- py.builtin.print_('expected order', expected_list)
- py.builtin.print_('but got ', test_list)
- assert test_list == expected_list
-
- for i in expected_list:
- yield list_append, i
- yield assert_order_of_execution
- """)
- reprec = testdir.inline_run(o)
- passed, skipped, failed = reprec.countoutcomes()
- assert passed == 7
- assert not skipped and not failed
-
- def test_order_of_execution_generator_different_codeline(self, testdir):
- o = testdir.makepyfile("""
- def test_generative_tests_different_codeline():
- import py, pytest
- test_list = []
- expected_list = list(range(3))
-
- def list_append_2():
- test_list.append(2)
-
- def list_append_1():
- test_list.append(1)
-
- def list_append_0():
- test_list.append(0)
-
- def assert_order_of_execution():
- py.builtin.print_('expected order', expected_list)
- py.builtin.print_('but got ', test_list)
- assert test_list == expected_list
-
- yield list_append_0
- yield list_append_1
- yield list_append_2
- yield assert_order_of_execution
- """)
- reprec = testdir.inline_run(o)
- passed, skipped, failed = reprec.countoutcomes()
- assert passed == 4
- assert not skipped and not failed
-
- def test_setupstate_is_preserved_134(self, testdir):
- # yield-based tests are messy wrt to setupstate because
- # during collection they already invoke setup functions
- # and then again when they are run. For now, we want to make sure
- # that the old 1.3.4 behaviour is preserved such that all
- # yielded functions all share the same "self" instance that
- # has been used during collection.
- o = testdir.makepyfile("""
- setuplist = []
- class TestClass:
- def setup_method(self, func):
- #print "setup_method", self, func
- setuplist.append(self)
- self.init = 42
-
- def teardown_method(self, func):
- self.init = None
-
- def test_func1(self):
- pass
-
- def test_func2(self):
- yield self.func2
- yield self.func2
-
- def func2(self):
- assert self.init
-
- def test_setuplist():
- # once for test_func2 during collection
- # once for test_func1 during test run
- # once for test_func2 during test run
- #print setuplist
- assert len(setuplist) == 3, len(setuplist)
- assert setuplist[0] == setuplist[2], setuplist
- assert setuplist[1] != setuplist[2], setuplist
- """)
- reprec = testdir.inline_run(o, '-v')
- passed, skipped, failed = reprec.countoutcomes()
- assert passed == 4
- assert not skipped and not failed
-
-
-class TestFunction:
- def test_getmodulecollector(self, testdir):
- item = testdir.getitem("def test_func(): pass")
- modcol = item.getparent(pytest.Module)
- assert isinstance(modcol, pytest.Module)
- assert hasattr(modcol.obj, 'test_func')
-
- def test_function_as_object_instance_ignored(self, testdir):
- testdir.makepyfile("""
- class A:
- def __call__(self, tmpdir):
- 0/0
-
- test_a = A()
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome()
-
- def test_function_equality(self, testdir, tmpdir):
- from _pytest.python import FixtureManager
- config = testdir.parseconfigure()
- session = testdir.Session(config)
- session._fixturemanager = FixtureManager(session)
- def func1():
- pass
- def func2():
- pass
- f1 = pytest.Function(name="name", parent=session, config=config,
- args=(1,), callobj=func1)
- assert f1 == f1
- f2 = pytest.Function(name="name",config=config,
- callobj=func2, parent=session)
- assert f1 != f2
-
- def test_issue197_parametrize_emptyset(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.mark.parametrize('arg', [])
- def test_function(arg):
- pass
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(skipped=1)
-
- def test_single_tuple_unwraps_values(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.mark.parametrize(('arg',), [(1,)])
- def test_function(arg):
- assert arg == 1
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
- def test_issue213_parametrize_value_no_equal(self, testdir):
- testdir.makepyfile("""
- import pytest
- class A:
- def __eq__(self, other):
- raise ValueError("not possible")
- @pytest.mark.parametrize('arg', [A()])
- def test_function(arg):
- assert arg.__class__.__name__ == "A"
- """)
- reprec = testdir.inline_run("--fulltrace")
- reprec.assertoutcome(passed=1)
-
- def test_parametrize_with_non_hashable_values(self, testdir):
- """Test parametrization with non-hashable values."""
- testdir.makepyfile("""
- archival_mapping = {
- '1.0': {'tag': '1.0'},
- '1.2.2a1': {'tag': 'release-1.2.2a1'},
- }
-
- import pytest
- @pytest.mark.parametrize('key value'.split(),
- archival_mapping.items())
- def test_archival_to_version(key, value):
- assert key in archival_mapping
- assert value == archival_mapping[key]
- """)
- rec = testdir.inline_run()
- rec.assertoutcome(passed=2)
-
-
- def test_parametrize_with_non_hashable_values_indirect(self, testdir):
- """Test parametrization with non-hashable values with indirect parametrization."""
- testdir.makepyfile("""
- archival_mapping = {
- '1.0': {'tag': '1.0'},
- '1.2.2a1': {'tag': 'release-1.2.2a1'},
- }
-
- import pytest
-
- @pytest.fixture
- def key(request):
- return request.param
-
- @pytest.fixture
- def value(request):
- return request.param
-
- @pytest.mark.parametrize('key value'.split(),
- archival_mapping.items(), indirect=True)
- def test_archival_to_version(key, value):
- assert key in archival_mapping
- assert value == archival_mapping[key]
- """)
- rec = testdir.inline_run()
- rec.assertoutcome(passed=2)
-
-
- def test_parametrize_overrides_fixture(self, testdir):
- """Test parametrization when parameter overrides existing fixture with same name."""
- testdir.makepyfile("""
- import pytest
-
- @pytest.fixture
- def value():
- return 'value'
-
- @pytest.mark.parametrize('value',
- ['overridden'])
- def test_overridden_via_param(value):
- assert value == 'overridden'
-
- @pytest.mark.parametrize('somevalue', ['overridden'])
- def test_not_overridden(value, somevalue):
- assert value == 'value'
- assert somevalue == 'overridden'
-
- @pytest.mark.parametrize('other,value', [('foo', 'overridden')])
- def test_overridden_via_multiparam(other, value):
- assert other == 'foo'
- assert value == 'overridden'
- """)
- rec = testdir.inline_run()
- rec.assertoutcome(passed=3)
-
-
- def test_parametrize_overrides_parametrized_fixture(self, testdir):
- """Test parametrization when parameter overrides existing parametrized fixture with same name."""
- testdir.makepyfile("""
- import pytest
-
- @pytest.fixture(params=[1, 2])
- def value(request):
- return request.param
-
- @pytest.mark.parametrize('value',
- ['overridden'])
- def test_overridden_via_param(value):
- assert value == 'overridden'
- """)
- rec = testdir.inline_run()
- rec.assertoutcome(passed=1)
-
- def test_parametrize_with_mark(selfself, testdir):
- items = testdir.getitems("""
- import pytest
- @pytest.mark.foo
- @pytest.mark.parametrize('arg', [
- 1,
- pytest.mark.bar(pytest.mark.baz(2))
- ])
- def test_function(arg):
- pass
- """)
- keywords = [item.keywords for item in items]
- assert 'foo' in keywords[0] and 'bar' not in keywords[0] and 'baz' not in keywords[0]
- assert 'foo' in keywords[1] and 'bar' in keywords[1] and 'baz' in keywords[1]
-
- def test_function_equality_with_callspec(self, testdir, tmpdir):
- items = testdir.getitems("""
- import pytest
- @pytest.mark.parametrize('arg', [1,2])
- def test_function(arg):
- pass
- """)
- assert items[0] != items[1]
- assert not (items[0] == items[1])
-
- def test_pyfunc_call(self, testdir):
- item = testdir.getitem("def test_func(): raise ValueError")
- config = item.config
- class MyPlugin1:
- def pytest_pyfunc_call(self, pyfuncitem):
- raise ValueError
- class MyPlugin2:
- def pytest_pyfunc_call(self, pyfuncitem):
- return True
- config.pluginmanager.register(MyPlugin1())
- config.pluginmanager.register(MyPlugin2())
- config.hook.pytest_runtest_setup(item=item)
- config.hook.pytest_pyfunc_call(pyfuncitem=item)
-
- def test_multiple_parametrize(self, testdir):
- modcol = testdir.getmodulecol("""
- import pytest
- @pytest.mark.parametrize('x', [0, 1])
- @pytest.mark.parametrize('y', [2, 3])
- def test1(x, y):
- pass
- """)
- colitems = modcol.collect()
- assert colitems[0].name == 'test1[2-0]'
- assert colitems[1].name == 'test1[2-1]'
- assert colitems[2].name == 'test1[3-0]'
- assert colitems[3].name == 'test1[3-1]'
-
- def test_issue751_multiple_parametrize_with_ids(self, testdir):
- modcol = testdir.getmodulecol("""
- import pytest
- @pytest.mark.parametrize('x', [0], ids=['c'])
- @pytest.mark.parametrize('y', [0, 1], ids=['a', 'b'])
- class Test(object):
- def test1(self, x, y):
- pass
- def test2(self, x, y):
- pass
- """)
- colitems = modcol.collect()[0].collect()[0].collect()
- assert colitems[0].name == 'test1[a-c]'
- assert colitems[1].name == 'test1[b-c]'
- assert colitems[2].name == 'test2[a-c]'
- assert colitems[3].name == 'test2[b-c]'
-
- def test_parametrize_skipif(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- m = pytest.mark.skipif('True')
-
- @pytest.mark.parametrize('x', [0, 1, m(2)])
- def test_skip_if(x):
- assert x < 2
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines('* 2 passed, 1 skipped in *')
-
- def test_parametrize_skip(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- m = pytest.mark.skip('')
-
- @pytest.mark.parametrize('x', [0, 1, m(2)])
- def test_skip(x):
- assert x < 2
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines('* 2 passed, 1 skipped in *')
-
- def test_parametrize_skipif_no_skip(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- m = pytest.mark.skipif('False')
-
- @pytest.mark.parametrize('x', [0, 1, m(2)])
- def test_skipif_no_skip(x):
- assert x < 2
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines('* 1 failed, 2 passed in *')
-
- def test_parametrize_xfail(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- m = pytest.mark.xfail('True')
-
- @pytest.mark.parametrize('x', [0, 1, m(2)])
- def test_xfail(x):
- assert x < 2
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines('* 2 passed, 1 xfailed in *')
-
- def test_parametrize_passed(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- m = pytest.mark.xfail('True')
-
- @pytest.mark.parametrize('x', [0, 1, m(2)])
- def test_xfail(x):
- pass
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines('* 2 passed, 1 xpassed in *')
-
- def test_parametrize_xfail_passed(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- m = pytest.mark.xfail('False')
-
- @pytest.mark.parametrize('x', [0, 1, m(2)])
- def test_passed(x):
- pass
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines('* 3 passed in *')
-
-
-class TestSorting:
- def test_check_equality(self, testdir):
- modcol = testdir.getmodulecol("""
- def test_pass(): pass
- def test_fail(): assert 0
- """)
- fn1 = testdir.collect_by_name(modcol, "test_pass")
- assert isinstance(fn1, pytest.Function)
- fn2 = testdir.collect_by_name(modcol, "test_pass")
- assert isinstance(fn2, pytest.Function)
-
- assert fn1 == fn2
- assert fn1 != modcol
- if py.std.sys.version_info < (3, 0):
- assert cmp(fn1, fn2) == 0
- assert hash(fn1) == hash(fn2)
-
- fn3 = testdir.collect_by_name(modcol, "test_fail")
- assert isinstance(fn3, pytest.Function)
- assert not (fn1 == fn3)
- assert fn1 != fn3
-
- for fn in fn1,fn2,fn3:
- assert fn != 3
- assert fn != modcol
- assert fn != [1,2,3]
- assert [1,2,3] != fn
- assert modcol != fn
-
- def test_allow_sane_sorting_for_decorators(self, testdir):
- modcol = testdir.getmodulecol("""
- def dec(f):
- g = lambda: f(2)
- g.place_as = f
- return g
-
-
- def test_b(y):
- pass
- test_b = dec(test_b)
-
- def test_a(y):
- pass
- test_a = dec(test_a)
- """)
- colitems = modcol.collect()
- assert len(colitems) == 2
- assert [item.name for item in colitems] == ['test_b', 'test_a']
-
-
-class TestConftestCustomization:
- def test_pytest_pycollect_module(self, testdir):
- testdir.makeconftest("""
- import pytest
- class MyModule(pytest.Module):
- pass
- def pytest_pycollect_makemodule(path, parent):
- if path.basename == "test_xyz.py":
- return MyModule(path, parent)
- """)
- testdir.makepyfile("def test_some(): pass")
- testdir.makepyfile(test_xyz="def test_func(): pass")
- result = testdir.runpytest("--collect-only")
- result.stdout.fnmatch_lines([
- "*<Module*test_pytest*",
- "*<MyModule*xyz*",
- ])
-
- def test_customized_pymakemodule_issue205_subdir(self, testdir):
- b = testdir.mkdir("a").mkdir("b")
- b.join("conftest.py").write(_pytest._code.Source("""
- def pytest_pycollect_makemodule(__multicall__):
- mod = __multicall__.execute()
- mod.obj.hello = "world"
- return mod
- """))
- b.join("test_module.py").write(_pytest._code.Source("""
- def test_hello():
- assert hello == "world"
- """))
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
- def test_customized_pymakeitem(self, testdir):
- b = testdir.mkdir("a").mkdir("b")
- b.join("conftest.py").write(_pytest._code.Source("""
- import pytest
- @pytest.hookimpl(hookwrapper=True)
- def pytest_pycollect_makeitem():
- outcome = yield
- if outcome.excinfo is None:
- result = outcome.result
- if result:
- for func in result:
- func._some123 = "world"
- """))
- b.join("test_module.py").write(_pytest._code.Source("""
- import pytest
-
- @pytest.fixture()
- def obj(request):
- return request.node._some123
- def test_hello(obj):
- assert obj == "world"
- """))
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
- def test_pytest_pycollect_makeitem(self, testdir):
- testdir.makeconftest("""
- import pytest
- class MyFunction(pytest.Function):
- pass
- def pytest_pycollect_makeitem(collector, name, obj):
- if name == "some":
- return MyFunction(name, collector)
- """)
- testdir.makepyfile("def some(): pass")
- result = testdir.runpytest("--collect-only")
- result.stdout.fnmatch_lines([
- "*MyFunction*some*",
- ])
-
- def test_makeitem_non_underscore(self, testdir, monkeypatch):
- modcol = testdir.getmodulecol("def _hello(): pass")
- l = []
- monkeypatch.setattr(pytest.Module, 'makeitem',
- lambda self, name, obj: l.append(name))
- l = modcol.collect()
- assert '_hello' not in l
-
-def test_setup_only_available_in_subdir(testdir):
- sub1 = testdir.mkpydir("sub1")
- sub2 = testdir.mkpydir("sub2")
- sub1.join("conftest.py").write(_pytest._code.Source("""
- import pytest
- def pytest_runtest_setup(item):
- assert item.fspath.purebasename == "test_in_sub1"
- def pytest_runtest_call(item):
- assert item.fspath.purebasename == "test_in_sub1"
- def pytest_runtest_teardown(item):
- assert item.fspath.purebasename == "test_in_sub1"
- """))
- sub2.join("conftest.py").write(_pytest._code.Source("""
- import pytest
- def pytest_runtest_setup(item):
- assert item.fspath.purebasename == "test_in_sub2"
- def pytest_runtest_call(item):
- assert item.fspath.purebasename == "test_in_sub2"
- def pytest_runtest_teardown(item):
- assert item.fspath.purebasename == "test_in_sub2"
- """))
- sub1.join("test_in_sub1.py").write("def test_1(): pass")
- sub2.join("test_in_sub2.py").write("def test_2(): pass")
- result = testdir.runpytest("-v", "-s")
- result.assert_outcomes(passed=2)
-
-def test_modulecol_roundtrip(testdir):
- modcol = testdir.getmodulecol("pass", withinit=True)
- trail = modcol.nodeid
- newcol = modcol.session.perform_collect([trail], genitems=0)[0]
- assert modcol.name == newcol.name
-
-
-class TestTracebackCutting:
- def test_skip_simple(self):
- excinfo = pytest.raises(pytest.skip.Exception, 'pytest.skip("xxx")')
- assert excinfo.traceback[-1].frame.code.name == "skip"
- assert excinfo.traceback[-1].ishidden()
-
- def test_traceback_argsetup(self, testdir):
- testdir.makeconftest("""
- def pytest_funcarg__hello(request):
- raise ValueError("xyz")
- """)
- p = testdir.makepyfile("def test(hello): pass")
- result = testdir.runpytest(p)
- assert result.ret != 0
- out = result.stdout.str()
- assert out.find("xyz") != -1
- assert out.find("conftest.py:2: ValueError") != -1
- numentries = out.count("_ _ _") # separator for traceback entries
- assert numentries == 0
-
- result = testdir.runpytest("--fulltrace", p)
- out = result.stdout.str()
- assert out.find("conftest.py:2: ValueError") != -1
- numentries = out.count("_ _ _ _") # separator for traceback entries
- assert numentries > 3
-
- def test_traceback_error_during_import(self, testdir):
- testdir.makepyfile("""
- x = 1
- x = 2
- x = 17
- asd
- """)
- result = testdir.runpytest()
- assert result.ret != 0
- out = result.stdout.str()
- assert "x = 1" not in out
- assert "x = 2" not in out
- result.stdout.fnmatch_lines([
- " *asd*",
- "E*NameError*",
- ])
- result = testdir.runpytest("--fulltrace")
- out = result.stdout.str()
- assert "x = 1" in out
- assert "x = 2" in out
- result.stdout.fnmatch_lines([
- ">*asd*",
- "E*NameError*",
- ])
-
- def test_traceback_filter_error_during_fixture_collection(self, testdir):
- """integration test for issue #995.
- """
- testdir.makepyfile("""
- import pytest
-
- def fail_me(func):
- ns = {}
- exec('def w(): raise ValueError("fail me")', ns)
- return ns['w']
-
- @pytest.fixture(scope='class')
- @fail_me
- def fail_fixture():
- pass
-
- def test_failing_fixture(fail_fixture):
- pass
- """)
- result = testdir.runpytest()
- assert result.ret != 0
- out = result.stdout.str()
- assert "INTERNALERROR>" not in out
- result.stdout.fnmatch_lines([
- "*ValueError: fail me*",
- "* 1 error in *",
- ])
-
- def test_filter_traceback_generated_code(self):
- """test that filter_traceback() works with the fact that
- py.code.Code.path attribute might return an str object.
- In this case, one of the entries on the traceback was produced by
- dynamically generated code.
- See: https://bitbucket.org/pytest-dev/py/issues/71
- This fixes #995.
- """
- from _pytest.python import filter_traceback
- try:
- ns = {}
- exec('def foo(): raise ValueError', ns)
- ns['foo']()
- except ValueError:
- _, _, tb = sys.exc_info()
-
- tb = _pytest._code.Traceback(tb)
- assert isinstance(tb[-1].path, str)
- assert not filter_traceback(tb[-1])
-
- def test_filter_traceback_path_no_longer_valid(self, testdir):
- """test that filter_traceback() works with the fact that
- py.code.Code.path attribute might return an str object.
- In this case, one of the files in the traceback no longer exists.
- This fixes #1133.
- """
- from _pytest.python import filter_traceback
- testdir.syspathinsert()
- testdir.makepyfile(filter_traceback_entry_as_str='''
- def foo():
- raise ValueError
- ''')
- try:
- import filter_traceback_entry_as_str
- filter_traceback_entry_as_str.foo()
- except ValueError:
- _, _, tb = sys.exc_info()
-
- testdir.tmpdir.join('filter_traceback_entry_as_str.py').remove()
- tb = _pytest._code.Traceback(tb)
- assert isinstance(tb[-1].path, str)
- assert filter_traceback(tb[-1])
-
-
-class TestReportInfo:
- def test_itemreport_reportinfo(self, testdir, linecomp):
- testdir.makeconftest("""
- import pytest
- class MyFunction(pytest.Function):
- def reportinfo(self):
- return "ABCDE", 42, "custom"
- def pytest_pycollect_makeitem(collector, name, obj):
- if name == "test_func":
- return MyFunction(name, parent=collector)
- """)
- item = testdir.getitem("def test_func(): pass")
- item.config.pluginmanager.getplugin("runner")
- assert item.location == ("ABCDE", 42, "custom")
-
- def test_func_reportinfo(self, testdir):
- item = testdir.getitem("def test_func(): pass")
- fspath, lineno, modpath = item.reportinfo()
- assert fspath == item.fspath
- assert lineno == 0
- assert modpath == "test_func"
-
- def test_class_reportinfo(self, testdir):
- modcol = testdir.getmodulecol("""
- # lineno 0
- class TestClass:
- def test_hello(self): pass
- """)
- classcol = testdir.collect_by_name(modcol, "TestClass")
- fspath, lineno, msg = classcol.reportinfo()
- assert fspath == modcol.fspath
- assert lineno == 1
- assert msg == "TestClass"
-
- def test_generator_reportinfo(self, testdir):
- modcol = testdir.getmodulecol("""
- # lineno 0
- def test_gen():
- def check(x):
- assert x
- yield check, 3
- """)
- gencol = testdir.collect_by_name(modcol, "test_gen")
- fspath, lineno, modpath = gencol.reportinfo()
- assert fspath == modcol.fspath
- assert lineno == 1
- assert modpath == "test_gen"
-
- genitem = gencol.collect()[0]
- fspath, lineno, modpath = genitem.reportinfo()
- assert fspath == modcol.fspath
- assert lineno == 2
- assert modpath == "test_gen[0]"
- """
- def test_func():
- pass
- def test_genfunc():
- def check(x):
- pass
- yield check, 3
- class TestClass:
- def test_method(self):
- pass
- """
-
- def test_reportinfo_with_nasty_getattr(self, testdir):
- # https://github.com/pytest-dev/pytest/issues/1204
- modcol = testdir.getmodulecol("""
- # lineno 0
- class TestClass:
- def __getattr__(self, name):
- return "this is not an int"
-
- def test_foo(self):
- pass
- """)
- classcol = testdir.collect_by_name(modcol, "TestClass")
- instance = classcol.collect()[0]
- fspath, lineno, msg = instance.reportinfo()
-
-
-def test_customized_python_discovery(testdir):
- testdir.makeini("""
- [pytest]
- python_files=check_*.py
- python_classes=Check
- python_functions=check
- """)
- p = testdir.makepyfile("""
- def check_simple():
- pass
- class CheckMyApp:
- def check_meth(self):
- pass
- """)
- p2 = p.new(basename=p.basename.replace("test", "check"))
- p.move(p2)
- result = testdir.runpytest("--collect-only", "-s")
- result.stdout.fnmatch_lines([
- "*check_customized*",
- "*check_simple*",
- "*CheckMyApp*",
- "*check_meth*",
- ])
-
- result = testdir.runpytest()
- assert result.ret == 0
- result.stdout.fnmatch_lines([
- "*2 passed*",
- ])
-
-
-def test_customized_python_discovery_functions(testdir):
- testdir.makeini("""
- [pytest]
- python_functions=_test
- """)
- testdir.makepyfile("""
- def _test_underscore():
- pass
- """)
- result = testdir.runpytest("--collect-only", "-s")
- result.stdout.fnmatch_lines([
- "*_test_underscore*",
- ])
-
- result = testdir.runpytest()
- assert result.ret == 0
- result.stdout.fnmatch_lines([
- "*1 passed*",
- ])
-
-
-def test_collector_attributes(testdir):
- testdir.makeconftest("""
- import pytest
- def pytest_pycollect_makeitem(collector):
- assert collector.Function == pytest.Function
- assert collector.Class == pytest.Class
- assert collector.Instance == pytest.Instance
- assert collector.Module == pytest.Module
- """)
- testdir.makepyfile("""
- def test_hello():
- pass
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*1 passed*",
- ])
-
-def test_customize_through_attributes(testdir):
- testdir.makeconftest("""
- import pytest
- class MyFunction(pytest.Function):
- pass
- class MyInstance(pytest.Instance):
- Function = MyFunction
- class MyClass(pytest.Class):
- Instance = MyInstance
-
- def pytest_pycollect_makeitem(collector, name, obj):
- if name.startswith("MyTestClass"):
- return MyClass(name, parent=collector)
- """)
- testdir.makepyfile("""
- class MyTestClass:
- def test_hello(self):
- pass
- """)
- result = testdir.runpytest("--collect-only")
- result.stdout.fnmatch_lines([
- "*MyClass*",
- "*MyInstance*",
- "*MyFunction*test_hello*",
- ])
-
-
-def test_unorderable_types(testdir):
- testdir.makepyfile("""
- class TestJoinEmpty:
- pass
-
- def make_test():
- class Test:
- pass
- Test.__name__ = "TestFoo"
- return Test
- TestFoo = make_test()
- """)
- result = testdir.runpytest()
- assert "TypeError" not in result.stdout.str()
- assert result.ret == EXIT_NOTESTSCOLLECTED
-
-
-def test_collect_functools_partial(testdir):
- """
- Test that collection of functools.partial object works, and arguments
- to the wrapped functions are dealt correctly (see #811).
- """
- testdir.makepyfile("""
- import functools
- import pytest
-
- @pytest.fixture
- def fix1():
- return 'fix1'
-
- @pytest.fixture
- def fix2():
- return 'fix2'
-
- def check1(i, fix1):
- assert i == 2
- assert fix1 == 'fix1'
-
- def check2(fix1, i):
- assert i == 2
- assert fix1 == 'fix1'
-
- def check3(fix1, i, fix2):
- assert i == 2
- assert fix1 == 'fix1'
- assert fix2 == 'fix2'
-
- test_ok_1 = functools.partial(check1, i=2)
- test_ok_2 = functools.partial(check1, i=2, fix1='fix1')
- test_ok_3 = functools.partial(check1, 2)
- test_ok_4 = functools.partial(check2, i=2)
- test_ok_5 = functools.partial(check3, i=2)
- test_ok_6 = functools.partial(check3, i=2, fix1='fix1')
-
- test_fail_1 = functools.partial(check2, 2)
- test_fail_2 = functools.partial(check3, 2)
- """)
- result = testdir.inline_run()
- result.assertoutcome(passed=6, failed=2)
-
-
-def test_dont_collect_non_function_callable(testdir):
- """Test for issue https://github.com/pytest-dev/pytest/issues/331
-
- In this case an INTERNALERROR occurred trying to report the failure of
- a test like this one because py test failed to get the source lines.
- """
- testdir.makepyfile("""
- class Oh(object):
- def __call__(self):
- pass
-
- test_a = Oh()
-
- def test_real():
- pass
- """)
- result = testdir.runpytest('-rw')
- result.stdout.fnmatch_lines([
- '*collected 1 item*',
- 'WC2 *',
- '*1 passed, 1 pytest-warnings in *',
- ])
-
-
-def test_class_injection_does_not_break_collection(testdir):
- """Tests whether injection during collection time will terminate testing.
-
- In this case the error should not occur if the TestClass itself
- is modified during collection time, and the original method list
- is still used for collection.
- """
- testdir.makeconftest("""
- from test_inject import TestClass
- def pytest_generate_tests(metafunc):
- TestClass.changed_var = {}
- """)
- testdir.makepyfile(test_inject='''
- class TestClass(object):
- def test_injection(self):
- """Test being parametrized."""
- pass
- ''')
- result = testdir.runpytest()
- assert "RuntimeError: dictionary changed size during iteration" not in result.stdout.str()
- result.stdout.fnmatch_lines(['*1 passed*'])
-
-
-def test_syntax_error_with_non_ascii_chars(testdir):
- """Fix decoding issue while formatting SyntaxErrors during collection (#578)
- """
- testdir.makepyfile(u"""
- # -*- coding: UTF-8 -*-
-
- ☃
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- '*ERROR collecting*',
- '*SyntaxError*',
- '*1 error in*',
- ])
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/python/fixture.py b/tests/wpt/web-platform-tests/tools/pytest/testing/python/fixture.py
deleted file mode 100644
index 506d8426e3c..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/python/fixture.py
+++ /dev/null
@@ -1,2693 +0,0 @@
-from textwrap import dedent
-
-import _pytest._code
-import pytest
-import sys
-from _pytest import python as funcargs
-from _pytest.pytester import get_public_names
-from _pytest.python import FixtureLookupError
-
-
-def test_getfuncargnames():
- def f(): pass
- assert not funcargs.getfuncargnames(f)
- def g(arg): pass
- assert funcargs.getfuncargnames(g) == ('arg',)
- def h(arg1, arg2="hello"): pass
- assert funcargs.getfuncargnames(h) == ('arg1',)
- def h(arg1, arg2, arg3="hello"): pass
- assert funcargs.getfuncargnames(h) == ('arg1', 'arg2')
- class A:
- def f(self, arg1, arg2="hello"):
- pass
- assert funcargs.getfuncargnames(A().f) == ('arg1',)
- if sys.version_info < (3,0):
- assert funcargs.getfuncargnames(A.f) == ('arg1',)
-
-class TestFillFixtures:
- def test_fillfuncargs_exposed(self):
- # used by oejskit, kept for compatibility
- assert pytest._fillfuncargs == funcargs.fillfixtures
-
- def test_funcarg_lookupfails(self, testdir):
- testdir.makepyfile("""
- def pytest_funcarg__xyzsomething(request):
- return 42
-
- def test_func(some):
- pass
- """)
- result = testdir.runpytest() # "--collect-only")
- assert result.ret != 0
- result.stdout.fnmatch_lines([
- "*def test_func(some)*",
- "*fixture*some*not found*",
- "*xyzsomething*",
- ])
-
- def test_funcarg_basic(self, testdir):
- item = testdir.getitem("""
- def pytest_funcarg__some(request):
- return request.function.__name__
- def pytest_funcarg__other(request):
- return 42
- def test_func(some, other):
- pass
- """)
- funcargs.fillfixtures(item)
- del item.funcargs["request"]
- assert len(get_public_names(item.funcargs)) == 2
- assert item.funcargs['some'] == "test_func"
- assert item.funcargs['other'] == 42
-
- def test_funcarg_lookup_modulelevel(self, testdir):
- testdir.makepyfile("""
- def pytest_funcarg__something(request):
- return request.function.__name__
-
- class TestClass:
- def test_method(self, something):
- assert something == "test_method"
- def test_func(something):
- assert something == "test_func"
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=2)
-
- def test_funcarg_lookup_classlevel(self, testdir):
- p = testdir.makepyfile("""
- class TestClass:
- def pytest_funcarg__something(self, request):
- return request.instance
- def test_method(self, something):
- assert something is self
- """)
- result = testdir.runpytest(p)
- result.stdout.fnmatch_lines([
- "*1 passed*"
- ])
-
- def test_conftest_funcargs_only_available_in_subdir(self, testdir):
- sub1 = testdir.mkpydir("sub1")
- sub2 = testdir.mkpydir("sub2")
- sub1.join("conftest.py").write(_pytest._code.Source("""
- import pytest
- def pytest_funcarg__arg1(request):
- pytest.raises(Exception, "request.getfuncargvalue('arg2')")
- """))
- sub2.join("conftest.py").write(_pytest._code.Source("""
- import pytest
- def pytest_funcarg__arg2(request):
- pytest.raises(Exception, "request.getfuncargvalue('arg1')")
- """))
-
- sub1.join("test_in_sub1.py").write("def test_1(arg1): pass")
- sub2.join("test_in_sub2.py").write("def test_2(arg2): pass")
- result = testdir.runpytest("-v")
- result.assert_outcomes(passed=2)
-
- def test_extend_fixture_module_class(self, testdir):
- testfile = testdir.makepyfile("""
- import pytest
-
- @pytest.fixture
- def spam():
- return 'spam'
-
- class TestSpam:
-
- @pytest.fixture
- def spam(self, spam):
- return spam * 2
-
- def test_spam(self, spam):
- assert spam == 'spamspam'
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines(["*1 passed*"])
- result = testdir.runpytest(testfile)
- result.stdout.fnmatch_lines(["*1 passed*"])
-
- def test_extend_fixture_conftest_module(self, testdir):
- testdir.makeconftest("""
- import pytest
-
- @pytest.fixture
- def spam():
- return 'spam'
- """)
- testfile = testdir.makepyfile("""
- import pytest
-
- @pytest.fixture
- def spam(spam):
- return spam * 2
-
- def test_spam(spam):
- assert spam == 'spamspam'
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines(["*1 passed*"])
- result = testdir.runpytest(testfile)
- result.stdout.fnmatch_lines(["*1 passed*"])
-
- def test_extend_fixture_conftest_conftest(self, testdir):
- testdir.makeconftest("""
- import pytest
-
- @pytest.fixture
- def spam():
- return 'spam'
- """)
- pkg = testdir.mkpydir("pkg")
- pkg.join("conftest.py").write(_pytest._code.Source("""
- import pytest
-
- @pytest.fixture
- def spam(spam):
- return spam * 2
- """))
- testfile = pkg.join("test_spam.py")
- testfile.write(_pytest._code.Source("""
- def test_spam(spam):
- assert spam == "spamspam"
- """))
- result = testdir.runpytest()
- result.stdout.fnmatch_lines(["*1 passed*"])
- result = testdir.runpytest(testfile)
- result.stdout.fnmatch_lines(["*1 passed*"])
-
- def test_extend_fixture_conftest_plugin(self, testdir):
- testdir.makepyfile(testplugin="""
- import pytest
-
- @pytest.fixture
- def foo():
- return 7
- """)
- testdir.syspathinsert()
- testdir.makeconftest("""
- import pytest
-
- pytest_plugins = 'testplugin'
-
- @pytest.fixture
- def foo(foo):
- return foo + 7
- """)
- testdir.makepyfile("""
- def test_foo(foo):
- assert foo == 14
- """)
- result = testdir.runpytest('-s')
- assert result.ret == 0
-
- def test_extend_fixture_plugin_plugin(self, testdir):
- # Two plugins should extend each order in loading order
- testdir.makepyfile(testplugin0="""
- import pytest
-
- @pytest.fixture
- def foo():
- return 7
- """)
- testdir.makepyfile(testplugin1="""
- import pytest
-
- @pytest.fixture
- def foo(foo):
- return foo + 7
- """)
- testdir.syspathinsert()
- testdir.makepyfile("""
- pytest_plugins = ['testplugin0', 'testplugin1']
-
- def test_foo(foo):
- assert foo == 14
- """)
- result = testdir.runpytest()
- assert result.ret == 0
-
- def test_override_parametrized_fixture_conftest_module(self, testdir):
- """Test override of the parametrized fixture with non-parametrized one on the test module level."""
- testdir.makeconftest("""
- import pytest
-
- @pytest.fixture(params=[1, 2, 3])
- def spam(request):
- return request.param
- """)
- testfile = testdir.makepyfile("""
- import pytest
-
- @pytest.fixture
- def spam():
- return 'spam'
-
- def test_spam(spam):
- assert spam == 'spam'
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines(["*1 passed*"])
- result = testdir.runpytest(testfile)
- result.stdout.fnmatch_lines(["*1 passed*"])
-
- def test_override_parametrized_fixture_conftest_conftest(self, testdir):
- """Test override of the parametrized fixture with non-parametrized one on the conftest level."""
- testdir.makeconftest("""
- import pytest
-
- @pytest.fixture(params=[1, 2, 3])
- def spam(request):
- return request.param
- """)
- subdir = testdir.mkpydir('subdir')
- subdir.join("conftest.py").write(_pytest._code.Source("""
- import pytest
-
- @pytest.fixture
- def spam():
- return 'spam'
- """))
- testfile = subdir.join("test_spam.py")
- testfile.write(_pytest._code.Source("""
- def test_spam(spam):
- assert spam == "spam"
- """))
- result = testdir.runpytest()
- result.stdout.fnmatch_lines(["*1 passed*"])
- result = testdir.runpytest(testfile)
- result.stdout.fnmatch_lines(["*1 passed*"])
-
- def test_override_non_parametrized_fixture_conftest_module(self, testdir):
- """Test override of the non-parametrized fixture with parametrized one on the test module level."""
- testdir.makeconftest("""
- import pytest
-
- @pytest.fixture
- def spam():
- return 'spam'
- """)
- testfile = testdir.makepyfile("""
- import pytest
-
- @pytest.fixture(params=[1, 2, 3])
- def spam(request):
- return request.param
-
- params = {'spam': 1}
-
- def test_spam(spam):
- assert spam == params['spam']
- params['spam'] += 1
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines(["*3 passed*"])
- result = testdir.runpytest(testfile)
- result.stdout.fnmatch_lines(["*3 passed*"])
-
- def test_override_non_parametrized_fixture_conftest_conftest(self, testdir):
- """Test override of the non-parametrized fixture with parametrized one on the conftest level."""
- testdir.makeconftest("""
- import pytest
-
- @pytest.fixture
- def spam():
- return 'spam'
- """)
- subdir = testdir.mkpydir('subdir')
- subdir.join("conftest.py").write(_pytest._code.Source("""
- import pytest
-
- @pytest.fixture(params=[1, 2, 3])
- def spam(request):
- return request.param
- """))
- testfile = subdir.join("test_spam.py")
- testfile.write(_pytest._code.Source("""
- params = {'spam': 1}
-
- def test_spam(spam):
- assert spam == params['spam']
- params['spam'] += 1
- """))
- result = testdir.runpytest()
- result.stdout.fnmatch_lines(["*3 passed*"])
- result = testdir.runpytest(testfile)
- result.stdout.fnmatch_lines(["*3 passed*"])
-
- def test_autouse_fixture_plugin(self, testdir):
- # A fixture from a plugin has no baseid set, which screwed up
- # the autouse fixture handling.
- testdir.makepyfile(testplugin="""
- import pytest
-
- @pytest.fixture(autouse=True)
- def foo(request):
- request.function.foo = 7
- """)
- testdir.syspathinsert()
- testdir.makepyfile("""
- pytest_plugins = 'testplugin'
-
- def test_foo(request):
- assert request.function.foo == 7
- """)
- result = testdir.runpytest()
- assert result.ret == 0
-
- def test_funcarg_lookup_error(self, testdir):
- testdir.makepyfile("""
- def test_lookup_error(unknown):
- pass
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*ERROR*test_lookup_error*",
- "*def test_lookup_error(unknown):*",
- "*fixture*unknown*not found*",
- "*available fixtures*",
- "*1 error*",
- ])
- assert "INTERNAL" not in result.stdout.str()
-
- def test_fixture_excinfo_leak(self, testdir):
- # on python2 sys.excinfo would leak into fixture executions
- testdir.makepyfile("""
- import sys
- import traceback
- import pytest
-
- @pytest.fixture
- def leak():
- if sys.exc_info()[0]: # python3 bug :)
- traceback.print_exc()
- #fails
- assert sys.exc_info() == (None, None, None)
-
- def test_leak(leak):
- if sys.exc_info()[0]: # python3 bug :)
- traceback.print_exc()
- assert sys.exc_info() == (None, None, None)
- """)
- result = testdir.runpytest()
- assert result.ret == 0
-
-
-class TestRequestBasic:
- def test_request_attributes(self, testdir):
- item = testdir.getitem("""
- def pytest_funcarg__something(request): pass
- def test_func(something): pass
- """)
- req = funcargs.FixtureRequest(item)
- assert req.function == item.obj
- assert req.keywords == item.keywords
- assert hasattr(req.module, 'test_func')
- assert req.cls is None
- assert req.function.__name__ == "test_func"
- assert req.config == item.config
- assert repr(req).find(req.function.__name__) != -1
-
- def test_request_attributes_method(self, testdir):
- item, = testdir.getitems("""
- class TestB:
- def pytest_funcarg__something(self, request):
- return 1
- def test_func(self, something):
- pass
- """)
- req = item._request
- assert req.cls.__name__ == "TestB"
- assert req.instance.__class__ == req.cls
-
- def XXXtest_request_contains_funcarg_arg2fixturedefs(self, testdir):
- modcol = testdir.getmodulecol("""
- def pytest_funcarg__something(request):
- pass
- class TestClass:
- def test_method(self, something):
- pass
- """)
- item1, = testdir.genitems([modcol])
- assert item1.name == "test_method"
- arg2fixturedefs = funcargs.FixtureRequest(item1)._arg2fixturedefs
- assert len(arg2fixturedefs) == 1
- assert arg2fixturedefs[0].__name__ == "pytest_funcarg__something"
-
- def test_getfuncargvalue_recursive(self, testdir):
- testdir.makeconftest("""
- def pytest_funcarg__something(request):
- return 1
- """)
- testdir.makepyfile("""
- def pytest_funcarg__something(request):
- return request.getfuncargvalue("something") + 1
- def test_func(something):
- assert something == 2
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
- def test_getfuncargvalue(self, testdir):
- item = testdir.getitem("""
- l = [2]
- def pytest_funcarg__something(request): return 1
- def pytest_funcarg__other(request):
- return l.pop()
- def test_func(something): pass
- """)
- req = item._request
- pytest.raises(FixtureLookupError, req.getfuncargvalue, "notexists")
- val = req.getfuncargvalue("something")
- assert val == 1
- val = req.getfuncargvalue("something")
- assert val == 1
- val2 = req.getfuncargvalue("other")
- assert val2 == 2
- val2 = req.getfuncargvalue("other") # see about caching
- assert val2 == 2
- pytest._fillfuncargs(item)
- assert item.funcargs["something"] == 1
- assert len(get_public_names(item.funcargs)) == 2
- assert "request" in item.funcargs
- #assert item.funcargs == {'something': 1, "other": 2}
-
- def test_request_addfinalizer(self, testdir):
- item = testdir.getitem("""
- teardownlist = []
- def pytest_funcarg__something(request):
- request.addfinalizer(lambda: teardownlist.append(1))
- def test_func(something): pass
- """)
- item.session._setupstate.prepare(item)
- pytest._fillfuncargs(item)
- # successively check finalization calls
- teardownlist = item.getparent(pytest.Module).obj.teardownlist
- ss = item.session._setupstate
- assert not teardownlist
- ss.teardown_exact(item, None)
- print(ss.stack)
- assert teardownlist == [1]
-
- def test_request_addfinalizer_failing_setup(self, testdir):
- testdir.makepyfile("""
- import pytest
- l = [1]
- @pytest.fixture
- def myfix(request):
- request.addfinalizer(l.pop)
- assert 0
- def test_fix(myfix):
- pass
- def test_finalizer_ran():
- assert not l
- """)
- reprec = testdir.inline_run("-s")
- reprec.assertoutcome(failed=1, passed=1)
-
- def test_request_addfinalizer_failing_setup_module(self, testdir):
- testdir.makepyfile("""
- import pytest
- l = [1, 2]
- @pytest.fixture(scope="module")
- def myfix(request):
- request.addfinalizer(l.pop)
- request.addfinalizer(l.pop)
- assert 0
- def test_fix(myfix):
- pass
- """)
- reprec = testdir.inline_run("-s")
- mod = reprec.getcalls("pytest_runtest_setup")[0].item.module
- assert not mod.l
-
-
- def test_request_addfinalizer_partial_setup_failure(self, testdir):
- p = testdir.makepyfile("""
- l = []
- def pytest_funcarg__something(request):
- request.addfinalizer(lambda: l.append(None))
- def test_func(something, missingarg):
- pass
- def test_second():
- assert len(l) == 1
- """)
- result = testdir.runpytest(p)
- result.stdout.fnmatch_lines([
- "*1 error*" # XXX the whole module collection fails
- ])
-
- def test_request_getmodulepath(self, testdir):
- modcol = testdir.getmodulecol("def test_somefunc(): pass")
- item, = testdir.genitems([modcol])
- req = funcargs.FixtureRequest(item)
- assert req.fspath == modcol.fspath
-
- def test_request_fixturenames(self, testdir):
- testdir.makepyfile("""
- import pytest
- from _pytest.pytester import get_public_names
- @pytest.fixture()
- def arg1():
- pass
- @pytest.fixture()
- def farg(arg1):
- pass
- @pytest.fixture(autouse=True)
- def sarg(tmpdir):
- pass
- def test_function(request, farg):
- assert set(get_public_names(request.fixturenames)) == \
- set(["tmpdir", "sarg", "arg1", "request", "farg",
- "tmpdir_factory"])
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
- def test_funcargnames_compatattr(self, testdir):
- testdir.makepyfile("""
- def pytest_generate_tests(metafunc):
- assert metafunc.funcargnames == metafunc.fixturenames
- def pytest_funcarg__fn(request):
- assert request._pyfuncitem.funcargnames == \
- request._pyfuncitem.fixturenames
- return request.funcargnames, request.fixturenames
-
- def test_hello(fn):
- assert fn[0] == fn[1]
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
- def test_setupdecorator_and_xunit(self, testdir):
- testdir.makepyfile("""
- import pytest
- l = []
- @pytest.fixture(scope='module', autouse=True)
- def setup_module():
- l.append("module")
- @pytest.fixture(autouse=True)
- def setup_function():
- l.append("function")
-
- def test_func():
- pass
-
- class TestClass:
- @pytest.fixture(scope="class", autouse=True)
- def setup_class(self):
- l.append("class")
- @pytest.fixture(autouse=True)
- def setup_method(self):
- l.append("method")
- def test_method(self):
- pass
- def test_all():
- assert l == ["module", "function", "class",
- "function", "method", "function"]
- """)
- reprec = testdir.inline_run("-v")
- reprec.assertoutcome(passed=3)
-
- def test_fixtures_sub_subdir_normalize_sep(self, testdir):
- # this tests that normalization of nodeids takes place
- b = testdir.mkdir("tests").mkdir("unit")
- b.join("conftest.py").write(_pytest._code.Source("""
- def pytest_funcarg__arg1():
- pass
- """))
- p = b.join("test_module.py")
- p.write("def test_func(arg1): pass")
- result = testdir.runpytest(p, "--fixtures")
- assert result.ret == 0
- result.stdout.fnmatch_lines("""
- *fixtures defined*conftest*
- *arg1*
- """)
-
- def test_show_fixtures_color_yes(self, testdir):
- testdir.makepyfile("def test_this(): assert 1")
- result = testdir.runpytest('--color=yes', '--fixtures')
- assert '\x1b[32mtmpdir' in result.stdout.str()
-
- def test_newstyle_with_request(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.fixture()
- def arg(request):
- pass
- def test_1(arg):
- pass
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
- def test_setupcontext_no_param(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.fixture(params=[1,2])
- def arg(request):
- return request.param
-
- @pytest.fixture(autouse=True)
- def mysetup(request, arg):
- assert not hasattr(request, "param")
- def test_1(arg):
- assert arg in (1,2)
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=2)
-
-class TestRequestMarking:
- def test_applymarker(self, testdir):
- item1,item2 = testdir.getitems("""
- def pytest_funcarg__something(request):
- pass
- class TestClass:
- def test_func1(self, something):
- pass
- def test_func2(self, something):
- pass
- """)
- req1 = funcargs.FixtureRequest(item1)
- assert 'xfail' not in item1.keywords
- req1.applymarker(pytest.mark.xfail)
- assert 'xfail' in item1.keywords
- assert 'skipif' not in item1.keywords
- req1.applymarker(pytest.mark.skipif)
- assert 'skipif' in item1.keywords
- pytest.raises(ValueError, "req1.applymarker(42)")
-
- def test_accesskeywords(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.fixture()
- def keywords(request):
- return request.keywords
- @pytest.mark.XYZ
- def test_function(keywords):
- assert keywords["XYZ"]
- assert "abc" not in keywords
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
- def test_accessmarker_dynamic(self, testdir):
- testdir.makeconftest("""
- import pytest
- @pytest.fixture()
- def keywords(request):
- return request.keywords
-
- @pytest.fixture(scope="class", autouse=True)
- def marking(request):
- request.applymarker(pytest.mark.XYZ("hello"))
- """)
- testdir.makepyfile("""
- import pytest
- def test_fun1(keywords):
- assert keywords["XYZ"] is not None
- assert "abc" not in keywords
- def test_fun2(keywords):
- assert keywords["XYZ"] is not None
- assert "abc" not in keywords
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=2)
-
-class TestRequestCachedSetup:
- def test_request_cachedsetup_defaultmodule(self, testdir):
- reprec = testdir.inline_runsource("""
- mysetup = ["hello",].pop
-
- def pytest_funcarg__something(request):
- return request.cached_setup(mysetup, scope="module")
-
- def test_func1(something):
- assert something == "hello"
- class TestClass:
- def test_func1a(self, something):
- assert something == "hello"
- """)
- reprec.assertoutcome(passed=2)
-
- def test_request_cachedsetup_class(self, testdir):
- reprec = testdir.inline_runsource("""
- mysetup = ["hello", "hello2", "hello3"].pop
-
- def pytest_funcarg__something(request):
- return request.cached_setup(mysetup, scope="class")
- def test_func1(something):
- assert something == "hello3"
- def test_func2(something):
- assert something == "hello2"
- class TestClass:
- def test_func1a(self, something):
- assert something == "hello"
- def test_func2b(self, something):
- assert something == "hello"
- """)
- reprec.assertoutcome(passed=4)
-
- def test_request_cachedsetup_extrakey(self, testdir):
- item1 = testdir.getitem("def test_func(): pass")
- req1 = funcargs.FixtureRequest(item1)
- l = ["hello", "world"]
- def setup():
- return l.pop()
- ret1 = req1.cached_setup(setup, extrakey=1)
- ret2 = req1.cached_setup(setup, extrakey=2)
- assert ret2 == "hello"
- assert ret1 == "world"
- ret1b = req1.cached_setup(setup, extrakey=1)
- ret2b = req1.cached_setup(setup, extrakey=2)
- assert ret1 == ret1b
- assert ret2 == ret2b
-
- def test_request_cachedsetup_cache_deletion(self, testdir):
- item1 = testdir.getitem("def test_func(): pass")
- req1 = funcargs.FixtureRequest(item1)
- l = []
- def setup():
- l.append("setup")
- def teardown(val):
- l.append("teardown")
- req1.cached_setup(setup, teardown, scope="function")
- assert l == ['setup']
- # artificial call of finalizer
- setupstate = req1._pyfuncitem.session._setupstate
- setupstate._callfinalizers(item1)
- assert l == ["setup", "teardown"]
- req1.cached_setup(setup, teardown, scope="function")
- assert l == ["setup", "teardown", "setup"]
- setupstate._callfinalizers(item1)
- assert l == ["setup", "teardown", "setup", "teardown"]
-
- def test_request_cached_setup_two_args(self, testdir):
- testdir.makepyfile("""
- def pytest_funcarg__arg1(request):
- return request.cached_setup(lambda: 42)
- def pytest_funcarg__arg2(request):
- return request.cached_setup(lambda: 17)
- def test_two_different_setups(arg1, arg2):
- assert arg1 != arg2
- """)
- result = testdir.runpytest("-v")
- result.stdout.fnmatch_lines([
- "*1 passed*"
- ])
-
- def test_request_cached_setup_getfuncargvalue(self, testdir):
- testdir.makepyfile("""
- def pytest_funcarg__arg1(request):
- arg1 = request.getfuncargvalue("arg2")
- return request.cached_setup(lambda: arg1 + 1)
- def pytest_funcarg__arg2(request):
- return request.cached_setup(lambda: 10)
- def test_two_funcarg(arg1):
- assert arg1 == 11
- """)
- result = testdir.runpytest("-v")
- result.stdout.fnmatch_lines([
- "*1 passed*"
- ])
-
- def test_request_cached_setup_functional(self, testdir):
- testdir.makepyfile(test_0="""
- l = []
- def pytest_funcarg__something(request):
- val = request.cached_setup(fsetup, fteardown)
- return val
- def fsetup(mycache=[1]):
- l.append(mycache.pop())
- return l
- def fteardown(something):
- l.remove(something[0])
- l.append(2)
- def test_list_once(something):
- assert something == [1]
- def test_list_twice(something):
- assert something == [1]
- """)
- testdir.makepyfile(test_1="""
- import test_0 # should have run already
- def test_check_test0_has_teardown_correct():
- assert test_0.l == [2]
- """)
- result = testdir.runpytest("-v")
- result.stdout.fnmatch_lines([
- "*3 passed*"
- ])
-
- def test_issue117_sessionscopeteardown(self, testdir):
- testdir.makepyfile("""
- def pytest_funcarg__app(request):
- app = request.cached_setup(
- scope='session',
- setup=lambda: 0,
- teardown=lambda x: 3/x)
- return app
- def test_func(app):
- pass
- """)
- result = testdir.runpytest()
- assert result.ret != 0
- result.stdout.fnmatch_lines([
- "*3/x*",
- "*ZeroDivisionError*",
- ])
-
-class TestFixtureUsages:
- def test_noargfixturedec(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.fixture
- def arg1():
- return 1
-
- def test_func(arg1):
- assert arg1 == 1
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
- def test_receives_funcargs(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.fixture()
- def arg1():
- return 1
-
- @pytest.fixture()
- def arg2(arg1):
- return arg1 + 1
-
- def test_add(arg2):
- assert arg2 == 2
- def test_all(arg1, arg2):
- assert arg1 == 1
- assert arg2 == 2
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=2)
-
- def test_receives_funcargs_scope_mismatch(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.fixture(scope="function")
- def arg1():
- return 1
-
- @pytest.fixture(scope="module")
- def arg2(arg1):
- return arg1 + 1
-
- def test_add(arg2):
- assert arg2 == 2
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*ScopeMismatch*involved factories*",
- "* def arg2*",
- "* def arg1*",
- "*1 error*"
- ])
-
- def test_receives_funcargs_scope_mismatch_issue660(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.fixture(scope="function")
- def arg1():
- return 1
-
- @pytest.fixture(scope="module")
- def arg2(arg1):
- return arg1 + 1
-
- def test_add(arg1, arg2):
- assert arg2 == 2
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*ScopeMismatch*involved factories*",
- "* def arg2*",
- "*1 error*"
- ])
-
- def test_funcarg_parametrized_and_used_twice(self, testdir):
- testdir.makepyfile("""
- import pytest
- l = []
- @pytest.fixture(params=[1,2])
- def arg1(request):
- l.append(1)
- return request.param
-
- @pytest.fixture()
- def arg2(arg1):
- return arg1 + 1
-
- def test_add(arg1, arg2):
- assert arg2 == arg1 + 1
- assert len(l) == arg1
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*2 passed*"
- ])
-
- def test_factory_uses_unknown_funcarg_as_dependency_error(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- @pytest.fixture()
- def fail(missing):
- return
-
- @pytest.fixture()
- def call_fail(fail):
- return
-
- def test_missing(call_fail):
- pass
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines("""
- *pytest.fixture()*
- *def call_fail(fail)*
- *pytest.fixture()*
- *def fail*
- *fixture*'missing'*not found*
- """)
-
- def test_factory_setup_as_classes_fails(self, testdir):
- testdir.makepyfile("""
- import pytest
- class arg1:
- def __init__(self, request):
- self.x = 1
- arg1 = pytest.fixture()(arg1)
-
- """)
- reprec = testdir.inline_run()
- l = reprec.getfailedcollections()
- assert len(l) == 1
-
- def test_request_can_be_overridden(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.fixture()
- def request(request):
- request.a = 1
- return request
- def test_request(request):
- assert request.a == 1
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
- def test_usefixtures_marker(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- l = []
-
- @pytest.fixture(scope="class")
- def myfix(request):
- request.cls.hello = "world"
- l.append(1)
-
- class TestClass:
- def test_one(self):
- assert self.hello == "world"
- assert len(l) == 1
- def test_two(self):
- assert self.hello == "world"
- assert len(l) == 1
- pytest.mark.usefixtures("myfix")(TestClass)
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=2)
-
- def test_usefixtures_ini(self, testdir):
- testdir.makeini("""
- [pytest]
- usefixtures = myfix
- """)
- testdir.makeconftest("""
- import pytest
-
- @pytest.fixture(scope="class")
- def myfix(request):
- request.cls.hello = "world"
-
- """)
- testdir.makepyfile("""
- class TestClass:
- def test_one(self):
- assert self.hello == "world"
- def test_two(self):
- assert self.hello == "world"
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=2)
-
- def test_usefixtures_seen_in_showmarkers(self, testdir):
- result = testdir.runpytest("--markers")
- result.stdout.fnmatch_lines("""
- *usefixtures(fixturename1*mark tests*fixtures*
- """)
-
- def test_request_instance_issue203(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- class TestClass:
- @pytest.fixture
- def setup1(self, request):
- assert self == request.instance
- self.arg1 = 1
- def test_hello(self, setup1):
- assert self.arg1 == 1
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
- def test_fixture_parametrized_with_iterator(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- l = []
- def f():
- yield 1
- yield 2
- dec = pytest.fixture(scope="module", params=f())
-
- @dec
- def arg(request):
- return request.param
- @dec
- def arg2(request):
- return request.param
-
- def test_1(arg):
- l.append(arg)
- def test_2(arg2):
- l.append(arg2*10)
- """)
- reprec = testdir.inline_run("-v")
- reprec.assertoutcome(passed=4)
- l = reprec.getcalls("pytest_runtest_call")[0].item.module.l
- assert l == [1,2, 10,20]
-
-
-class TestFixtureManagerParseFactories:
- def pytest_funcarg__testdir(self, request):
- testdir = request.getfuncargvalue("testdir")
- testdir.makeconftest("""
- def pytest_funcarg__hello(request):
- return "conftest"
-
- def pytest_funcarg__fm(request):
- return request._fixturemanager
-
- def pytest_funcarg__item(request):
- return request._pyfuncitem
- """)
- return testdir
-
- def test_parsefactories_evil_objects_issue214(self, testdir):
- testdir.makepyfile("""
- class A:
- def __call__(self):
- pass
- def __getattr__(self, name):
- raise RuntimeError()
- a = A()
- def test_hello():
- pass
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1, failed=0)
-
- def test_parsefactories_conftest(self, testdir):
- testdir.makepyfile("""
- def test_hello(item, fm):
- for name in ("fm", "hello", "item"):
- faclist = fm.getfixturedefs(name, item.nodeid)
- assert len(faclist) == 1
- fac = faclist[0]
- assert fac.func.__name__ == "pytest_funcarg__" + name
- """)
- reprec = testdir.inline_run("-s")
- reprec.assertoutcome(passed=1)
-
- def test_parsefactories_conftest_and_module_and_class(self, testdir):
- testdir.makepyfile("""
- def pytest_funcarg__hello(request):
- return "module"
- class TestClass:
- def pytest_funcarg__hello(self, request):
- return "class"
- def test_hello(self, item, fm):
- faclist = fm.getfixturedefs("hello", item.nodeid)
- print (faclist)
- assert len(faclist) == 3
- assert faclist[0].func(item._request) == "conftest"
- assert faclist[1].func(item._request) == "module"
- assert faclist[2].func(item._request) == "class"
- """)
- reprec = testdir.inline_run("-s")
- reprec.assertoutcome(passed=1)
-
- def test_parsefactories_relative_node_ids(self, testdir):
- # example mostly taken from:
- # https://mail.python.org/pipermail/pytest-dev/2014-September/002617.html
- runner = testdir.mkdir("runner")
- package = testdir.mkdir("package")
- package.join("conftest.py").write(dedent("""\
- import pytest
- @pytest.fixture
- def one():
- return 1
- """))
- package.join("test_x.py").write(dedent("""\
- def test_x(one):
- assert one == 1
- """))
- sub = package.mkdir("sub")
- sub.join("__init__.py").ensure()
- sub.join("conftest.py").write(dedent("""\
- import pytest
- @pytest.fixture
- def one():
- return 2
- """))
- sub.join("test_y.py").write(dedent("""\
- def test_x(one):
- assert one == 2
- """))
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=2)
- with runner.as_cwd():
- reprec = testdir.inline_run("..")
- reprec.assertoutcome(passed=2)
-
-
-class TestAutouseDiscovery:
- def pytest_funcarg__testdir(self, testdir):
- testdir.makeconftest("""
- import pytest
- @pytest.fixture(autouse=True)
- def perfunction(request, tmpdir):
- pass
-
- @pytest.fixture()
- def arg1(tmpdir):
- pass
- @pytest.fixture(autouse=True)
- def perfunction2(arg1):
- pass
-
- def pytest_funcarg__fm(request):
- return request._fixturemanager
-
- def pytest_funcarg__item(request):
- return request._pyfuncitem
- """)
- return testdir
-
- def test_parsefactories_conftest(self, testdir):
- testdir.makepyfile("""
- from _pytest.pytester import get_public_names
- def test_check_setup(item, fm):
- autousenames = fm._getautousenames(item.nodeid)
- assert len(get_public_names(autousenames)) == 2
- assert "perfunction2" in autousenames
- assert "perfunction" in autousenames
- """)
- reprec = testdir.inline_run("-s")
- reprec.assertoutcome(passed=1)
-
- def test_two_classes_separated_autouse(self, testdir):
- testdir.makepyfile("""
- import pytest
- class TestA:
- l = []
- @pytest.fixture(autouse=True)
- def setup1(self):
- self.l.append(1)
- def test_setup1(self):
- assert self.l == [1]
- class TestB:
- l = []
- @pytest.fixture(autouse=True)
- def setup2(self):
- self.l.append(1)
- def test_setup2(self):
- assert self.l == [1]
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=2)
-
- def test_setup_at_classlevel(self, testdir):
- testdir.makepyfile("""
- import pytest
- class TestClass:
- @pytest.fixture(autouse=True)
- def permethod(self, request):
- request.instance.funcname = request.function.__name__
- def test_method1(self):
- assert self.funcname == "test_method1"
- def test_method2(self):
- assert self.funcname == "test_method2"
- """)
- reprec = testdir.inline_run("-s")
- reprec.assertoutcome(passed=2)
-
- @pytest.mark.xfail(reason="'enabled' feature not implemented")
- def test_setup_enabled_functionnode(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- def enabled(parentnode, markers):
- return "needsdb" in markers
-
- @pytest.fixture(params=[1,2])
- def db(request):
- return request.param
-
- @pytest.fixture(enabled=enabled, autouse=True)
- def createdb(db):
- pass
-
- def test_func1(request):
- assert "db" not in request.fixturenames
-
- @pytest.mark.needsdb
- def test_func2(request):
- assert "db" in request.fixturenames
- """)
- reprec = testdir.inline_run("-s")
- reprec.assertoutcome(passed=2)
-
- def test_callables_nocode(self, testdir):
- """
- a imported mock.call would break setup/factory discovery
- due to it being callable and __code__ not being a code object
- """
- testdir.makepyfile("""
- class _call(tuple):
- def __call__(self, *k, **kw):
- pass
- def __getattr__(self, k):
- return self
-
- call = _call()
- """)
- reprec = testdir.inline_run("-s")
- reprec.assertoutcome(failed=0, passed=0)
-
- def test_autouse_in_conftests(self, testdir):
- a = testdir.mkdir("a")
- b = testdir.mkdir("a1")
- conftest = testdir.makeconftest("""
- import pytest
- @pytest.fixture(autouse=True)
- def hello():
- xxx
- """)
- conftest.move(a.join(conftest.basename))
- a.join("test_something.py").write("def test_func(): pass")
- b.join("test_otherthing.py").write("def test_func(): pass")
- result = testdir.runpytest()
- result.stdout.fnmatch_lines("""
- *1 passed*1 error*
- """)
-
- def test_autouse_in_module_and_two_classes(self, testdir):
- testdir.makepyfile("""
- import pytest
- l = []
- @pytest.fixture(autouse=True)
- def append1():
- l.append("module")
- def test_x():
- assert l == ["module"]
-
- class TestA:
- @pytest.fixture(autouse=True)
- def append2(self):
- l.append("A")
- def test_hello(self):
- assert l == ["module", "module", "A"], l
- class TestA2:
- def test_world(self):
- assert l == ["module", "module", "A", "module"], l
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=3)
-
-
-class TestAutouseManagement:
- def test_autouse_conftest_mid_directory(self, testdir):
- pkgdir = testdir.mkpydir("xyz123")
- pkgdir.join("conftest.py").write(_pytest._code.Source("""
- import pytest
- @pytest.fixture(autouse=True)
- def app():
- import sys
- sys._myapp = "hello"
- """))
- t = pkgdir.ensure("tests", "test_app.py")
- t.write(_pytest._code.Source("""
- import sys
- def test_app():
- assert sys._myapp == "hello"
- """))
- reprec = testdir.inline_run("-s")
- reprec.assertoutcome(passed=1)
-
- def test_autouse_honored_for_yield(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.fixture(autouse=True)
- def tst():
- global x
- x = 3
- def test_gen():
- def f(hello):
- assert x == abs(hello)
- yield f, 3
- yield f, -3
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=2)
-
-
-
- def test_funcarg_and_setup(self, testdir):
- testdir.makepyfile("""
- import pytest
- l = []
- @pytest.fixture(scope="module")
- def arg():
- l.append(1)
- return 0
- @pytest.fixture(scope="module", autouse=True)
- def something(arg):
- l.append(2)
-
- def test_hello(arg):
- assert len(l) == 2
- assert l == [1,2]
- assert arg == 0
-
- def test_hello2(arg):
- assert len(l) == 2
- assert l == [1,2]
- assert arg == 0
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=2)
-
- def test_uses_parametrized_resource(self, testdir):
- testdir.makepyfile("""
- import pytest
- l = []
- @pytest.fixture(params=[1,2])
- def arg(request):
- return request.param
-
- @pytest.fixture(autouse=True)
- def something(arg):
- l.append(arg)
-
- def test_hello():
- if len(l) == 1:
- assert l == [1]
- elif len(l) == 2:
- assert l == [1, 2]
- else:
- 0/0
-
- """)
- reprec = testdir.inline_run("-s")
- reprec.assertoutcome(passed=2)
-
- def test_session_parametrized_function(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- l = []
-
- @pytest.fixture(scope="session", params=[1,2])
- def arg(request):
- return request.param
-
- @pytest.fixture(scope="function", autouse=True)
- def append(request, arg):
- if request.function.__name__ == "test_some":
- l.append(arg)
-
- def test_some():
- pass
-
- def test_result(arg):
- assert len(l) == arg
- assert l[:arg] == [1,2][:arg]
- """)
- reprec = testdir.inline_run("-v", "-s")
- reprec.assertoutcome(passed=4)
-
- def test_class_function_parametrization_finalization(self, testdir):
- p = testdir.makeconftest("""
- import pytest
- import pprint
-
- l = []
-
- @pytest.fixture(scope="function", params=[1,2])
- def farg(request):
- return request.param
-
- @pytest.fixture(scope="class", params=list("ab"))
- def carg(request):
- return request.param
-
- @pytest.fixture(scope="function", autouse=True)
- def append(request, farg, carg):
- def fin():
- l.append("fin_%s%s" % (carg, farg))
- request.addfinalizer(fin)
- """)
- testdir.makepyfile("""
- import pytest
-
- class TestClass:
- def test_1(self):
- pass
- class TestClass2:
- def test_2(self):
- pass
- """)
- reprec = testdir.inline_run("-v","-s")
- reprec.assertoutcome(passed=8)
- config = reprec.getcalls("pytest_unconfigure")[0].config
- l = config.pluginmanager._getconftestmodules(p)[0].l
- assert l == ["fin_a1", "fin_a2", "fin_b1", "fin_b2"] * 2
-
- def test_scope_ordering(self, testdir):
- testdir.makepyfile("""
- import pytest
- l = []
- @pytest.fixture(scope="function", autouse=True)
- def fappend2():
- l.append(2)
- @pytest.fixture(scope="class", autouse=True)
- def classappend3():
- l.append(3)
- @pytest.fixture(scope="module", autouse=True)
- def mappend():
- l.append(1)
-
- class TestHallo:
- def test_method(self):
- assert l == [1,3,2]
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
- def test_parametrization_setup_teardown_ordering(self, testdir):
- testdir.makepyfile("""
- import pytest
- l = []
- def pytest_generate_tests(metafunc):
- if metafunc.cls is not None:
- metafunc.parametrize("item", [1,2], scope="class")
- class TestClass:
- @pytest.fixture(scope="class", autouse=True)
- def addteardown(self, item, request):
- l.append("setup-%d" % item)
- request.addfinalizer(lambda: l.append("teardown-%d" % item))
- def test_step1(self, item):
- l.append("step1-%d" % item)
- def test_step2(self, item):
- l.append("step2-%d" % item)
-
- def test_finish():
- print (l)
- assert l == ["setup-1", "step1-1", "step2-1", "teardown-1",
- "setup-2", "step1-2", "step2-2", "teardown-2",]
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=5)
-
- def test_ordering_autouse_before_explicit(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- l = []
- @pytest.fixture(autouse=True)
- def fix1():
- l.append(1)
- @pytest.fixture()
- def arg1():
- l.append(2)
- def test_hello(arg1):
- assert l == [1,2]
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
- @pytest.mark.issue226
- @pytest.mark.parametrize("param1", ["", "params=[1]"], ids=["p00","p01"])
- @pytest.mark.parametrize("param2", ["", "params=[1]"], ids=["p10","p11"])
- def test_ordering_dependencies_torndown_first(self, testdir, param1, param2):
- testdir.makepyfile("""
- import pytest
- l = []
- @pytest.fixture(%(param1)s)
- def arg1(request):
- request.addfinalizer(lambda: l.append("fin1"))
- l.append("new1")
- @pytest.fixture(%(param2)s)
- def arg2(request, arg1):
- request.addfinalizer(lambda: l.append("fin2"))
- l.append("new2")
-
- def test_arg(arg2):
- pass
- def test_check():
- assert l == ["new1", "new2", "fin2", "fin1"]
- """ % locals())
- reprec = testdir.inline_run("-s")
- reprec.assertoutcome(passed=2)
-
-
-class TestFixtureMarker:
- def test_parametrize(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.fixture(params=["a", "b", "c"])
- def arg(request):
- return request.param
- l = []
- def test_param(arg):
- l.append(arg)
- def test_result():
- assert l == list("abc")
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=4)
-
- def test_multiple_parametrization_issue_736(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- @pytest.fixture(params=[1,2,3])
- def foo(request):
- return request.param
-
- @pytest.mark.parametrize('foobar', [4,5,6])
- def test_issue(foo, foobar):
- assert foo in [1,2,3]
- assert foobar in [4,5,6]
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=9)
-
- @pytest.mark.parametrize('param_args', ["'fixt, val'", "'fixt,val'", "['fixt', 'val']", "('fixt', 'val')"])
- def test_override_parametrized_fixture_issue_979(self, testdir, param_args):
- """Make sure a parametrized argument can override a parametrized fixture.
-
- This was a regression introduced in the fix for #736.
- """
- testdir.makepyfile("""
- import pytest
-
- @pytest.fixture(params=[1, 2])
- def fixt(request):
- return request.param
-
- @pytest.mark.parametrize(%s, [(3, 'x'), (4, 'x')])
- def test_foo(fixt, val):
- pass
- """ % param_args)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=2)
-
- def test_scope_session(self, testdir):
- testdir.makepyfile("""
- import pytest
- l = []
- @pytest.fixture(scope="module")
- def arg():
- l.append(1)
- return 1
-
- def test_1(arg):
- assert arg == 1
- def test_2(arg):
- assert arg == 1
- assert len(l) == 1
- class TestClass:
- def test3(self, arg):
- assert arg == 1
- assert len(l) == 1
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=3)
-
- def test_scope_session_exc(self, testdir):
- testdir.makepyfile("""
- import pytest
- l = []
- @pytest.fixture(scope="session")
- def fix():
- l.append(1)
- pytest.skip('skipping')
-
- def test_1(fix):
- pass
- def test_2(fix):
- pass
- def test_last():
- assert l == [1]
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(skipped=2, passed=1)
-
- def test_scope_session_exc_two_fix(self, testdir):
- testdir.makepyfile("""
- import pytest
- l = []
- m = []
- @pytest.fixture(scope="session")
- def a():
- l.append(1)
- pytest.skip('skipping')
- @pytest.fixture(scope="session")
- def b(a):
- m.append(1)
-
- def test_1(b):
- pass
- def test_2(b):
- pass
- def test_last():
- assert l == [1]
- assert m == []
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(skipped=2, passed=1)
-
- def test_scope_exc(self, testdir):
- testdir.makepyfile(
- test_foo="""
- def test_foo(fix):
- pass
- """,
- test_bar="""
- def test_bar(fix):
- pass
- """,
- conftest="""
- import pytest
- reqs = []
- @pytest.fixture(scope="session")
- def fix(request):
- reqs.append(1)
- pytest.skip()
- @pytest.fixture
- def req_list():
- return reqs
- """,
- test_real="""
- def test_last(req_list):
- assert req_list == [1]
- """
- )
- reprec = testdir.inline_run()
- reprec.assertoutcome(skipped=2, passed=1)
-
- def test_scope_module_uses_session(self, testdir):
- testdir.makepyfile("""
- import pytest
- l = []
- @pytest.fixture(scope="module")
- def arg():
- l.append(1)
- return 1
-
- def test_1(arg):
- assert arg == 1
- def test_2(arg):
- assert arg == 1
- assert len(l) == 1
- class TestClass:
- def test3(self, arg):
- assert arg == 1
- assert len(l) == 1
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=3)
-
- def test_scope_module_and_finalizer(self, testdir):
- testdir.makeconftest("""
- import pytest
- finalized = []
- created = []
- @pytest.fixture(scope="module")
- def arg(request):
- created.append(1)
- assert request.scope == "module"
- request.addfinalizer(lambda: finalized.append(1))
- def pytest_funcarg__created(request):
- return len(created)
- def pytest_funcarg__finalized(request):
- return len(finalized)
- """)
- testdir.makepyfile(
- test_mod1="""
- def test_1(arg, created, finalized):
- assert created == 1
- assert finalized == 0
- def test_2(arg, created, finalized):
- assert created == 1
- assert finalized == 0""",
- test_mod2="""
- def test_3(arg, created, finalized):
- assert created == 2
- assert finalized == 1""",
- test_mode3="""
- def test_4(arg, created, finalized):
- assert created == 3
- assert finalized == 2
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=4)
-
- @pytest.mark.parametrize("method", [
- 'request.getfuncargvalue("arg")',
- 'request.cached_setup(lambda: None, scope="function")',
- ], ids=["getfuncargvalue", "cached_setup"])
- def test_scope_mismatch_various(self, testdir, method):
- testdir.makeconftest("""
- import pytest
- finalized = []
- created = []
- @pytest.fixture(scope="function")
- def arg(request):
- pass
- """)
- testdir.makepyfile(
- test_mod1="""
- import pytest
- @pytest.fixture(scope="session")
- def arg(request):
- %s
- def test_1(arg):
- pass
- """ % method)
- result = testdir.runpytest()
- assert result.ret != 0
- result.stdout.fnmatch_lines([
- "*ScopeMismatch*You tried*function*session*request*",
- ])
-
- def test_register_only_with_mark(self, testdir):
- testdir.makeconftest("""
- import pytest
- @pytest.fixture()
- def arg():
- return 1
- """)
- testdir.makepyfile(
- test_mod1="""
- import pytest
- @pytest.fixture()
- def arg(arg):
- return arg + 1
- def test_1(arg):
- assert arg == 2
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
- def test_parametrize_and_scope(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.fixture(scope="module", params=["a", "b", "c"])
- def arg(request):
- return request.param
- l = []
- def test_param(arg):
- l.append(arg)
- """)
- reprec = testdir.inline_run("-v")
- reprec.assertoutcome(passed=3)
- l = reprec.getcalls("pytest_runtest_call")[0].item.module.l
- assert len(l) == 3
- assert "a" in l
- assert "b" in l
- assert "c" in l
-
- def test_scope_mismatch(self, testdir):
- testdir.makeconftest("""
- import pytest
- @pytest.fixture(scope="function")
- def arg(request):
- pass
- """)
- testdir.makepyfile("""
- import pytest
- @pytest.fixture(scope="session")
- def arg(arg):
- pass
- def test_mismatch(arg):
- pass
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*ScopeMismatch*",
- "*1 error*",
- ])
-
- def test_parametrize_separated_order(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- @pytest.fixture(scope="module", params=[1, 2])
- def arg(request):
- return request.param
-
- l = []
- def test_1(arg):
- l.append(arg)
- def test_2(arg):
- l.append(arg)
- """)
- reprec = testdir.inline_run("-v")
- reprec.assertoutcome(passed=4)
- l = reprec.getcalls("pytest_runtest_call")[0].item.module.l
- assert l == [1,1,2,2]
-
- def test_module_parametrized_ordering(self, testdir):
- testdir.makeconftest("""
- import pytest
-
- @pytest.fixture(scope="session", params="s1 s2".split())
- def sarg():
- pass
- @pytest.fixture(scope="module", params="m1 m2".split())
- def marg():
- pass
- """)
- testdir.makepyfile(test_mod1="""
- def test_func(sarg):
- pass
- def test_func1(marg):
- pass
- """, test_mod2="""
- def test_func2(sarg):
- pass
- def test_func3(sarg, marg):
- pass
- def test_func3b(sarg, marg):
- pass
- def test_func4(marg):
- pass
- """)
- result = testdir.runpytest("-v")
- result.stdout.fnmatch_lines("""
- test_mod1.py::test_func[s1] PASSED
- test_mod2.py::test_func2[s1] PASSED
- test_mod2.py::test_func3[s1-m1] PASSED
- test_mod2.py::test_func3b[s1-m1] PASSED
- test_mod2.py::test_func3[s1-m2] PASSED
- test_mod2.py::test_func3b[s1-m2] PASSED
- test_mod1.py::test_func[s2] PASSED
- test_mod2.py::test_func2[s2] PASSED
- test_mod2.py::test_func3[s2-m1] PASSED
- test_mod2.py::test_func3b[s2-m1] PASSED
- test_mod2.py::test_func4[m1] PASSED
- test_mod2.py::test_func3[s2-m2] PASSED
- test_mod2.py::test_func3b[s2-m2] PASSED
- test_mod2.py::test_func4[m2] PASSED
- test_mod1.py::test_func1[m1] PASSED
- test_mod1.py::test_func1[m2] PASSED
- """)
-
- def test_class_ordering(self, testdir):
- testdir.makeconftest("""
- import pytest
-
- l = []
-
- @pytest.fixture(scope="function", params=[1,2])
- def farg(request):
- return request.param
-
- @pytest.fixture(scope="class", params=list("ab"))
- def carg(request):
- return request.param
-
- @pytest.fixture(scope="function", autouse=True)
- def append(request, farg, carg):
- def fin():
- l.append("fin_%s%s" % (carg, farg))
- request.addfinalizer(fin)
- """)
- testdir.makepyfile("""
- import pytest
-
- class TestClass2:
- def test_1(self):
- pass
- def test_2(self):
- pass
- class TestClass:
- def test_3(self):
- pass
- """)
- result = testdir.runpytest("-vs")
- result.stdout.fnmatch_lines("""
- test_class_ordering.py::TestClass2::test_1[1-a] PASSED
- test_class_ordering.py::TestClass2::test_1[2-a] PASSED
- test_class_ordering.py::TestClass2::test_2[1-a] PASSED
- test_class_ordering.py::TestClass2::test_2[2-a] PASSED
- test_class_ordering.py::TestClass2::test_1[1-b] PASSED
- test_class_ordering.py::TestClass2::test_1[2-b] PASSED
- test_class_ordering.py::TestClass2::test_2[1-b] PASSED
- test_class_ordering.py::TestClass2::test_2[2-b] PASSED
- test_class_ordering.py::TestClass::test_3[1-a] PASSED
- test_class_ordering.py::TestClass::test_3[2-a] PASSED
- test_class_ordering.py::TestClass::test_3[1-b] PASSED
- test_class_ordering.py::TestClass::test_3[2-b] PASSED
- """)
-
- def test_parametrize_separated_order_higher_scope_first(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- @pytest.fixture(scope="function", params=[1, 2])
- def arg(request):
- param = request.param
- request.addfinalizer(lambda: l.append("fin:%s" % param))
- l.append("create:%s" % param)
- return request.param
-
- @pytest.fixture(scope="module", params=["mod1", "mod2"])
- def modarg(request):
- param = request.param
- request.addfinalizer(lambda: l.append("fin:%s" % param))
- l.append("create:%s" % param)
- return request.param
-
- l = []
- def test_1(arg):
- l.append("test1")
- def test_2(modarg):
- l.append("test2")
- def test_3(arg, modarg):
- l.append("test3")
- def test_4(modarg, arg):
- l.append("test4")
- """)
- reprec = testdir.inline_run("-v")
- reprec.assertoutcome(passed=12)
- l = reprec.getcalls("pytest_runtest_call")[0].item.module.l
- expected = [
- 'create:1', 'test1', 'fin:1', 'create:2', 'test1',
- 'fin:2', 'create:mod1', 'test2', 'create:1', 'test3',
- 'fin:1', 'create:2', 'test3', 'fin:2', 'create:1',
- 'test4', 'fin:1', 'create:2', 'test4', 'fin:2',
- 'fin:mod1', 'create:mod2', 'test2', 'create:1', 'test3',
- 'fin:1', 'create:2', 'test3', 'fin:2', 'create:1',
- 'test4', 'fin:1', 'create:2', 'test4', 'fin:2',
- 'fin:mod2']
- import pprint
- pprint.pprint(list(zip(l, expected)))
- assert l == expected
-
- def test_parametrized_fixture_teardown_order(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.fixture(params=[1,2], scope="class")
- def param1(request):
- return request.param
-
- l = []
-
- class TestClass:
- @classmethod
- @pytest.fixture(scope="class", autouse=True)
- def setup1(self, request, param1):
- l.append(1)
- request.addfinalizer(self.teardown1)
- @classmethod
- def teardown1(self):
- assert l.pop() == 1
- @pytest.fixture(scope="class", autouse=True)
- def setup2(self, request, param1):
- l.append(2)
- request.addfinalizer(self.teardown2)
- @classmethod
- def teardown2(self):
- assert l.pop() == 2
- def test(self):
- pass
-
- def test_finish():
- assert not l
- """)
- result = testdir.runpytest("-v")
- result.stdout.fnmatch_lines("""
- *3 passed*
- """)
- assert "error" not in result.stdout.str()
-
- def test_fixture_finalizer(self, testdir):
- testdir.makeconftest("""
- import pytest
- import sys
-
- @pytest.fixture
- def browser(request):
-
- def finalize():
- sys.stdout.write('Finalized')
- request.addfinalizer(finalize)
- return {}
- """)
- b = testdir.mkdir("subdir")
- b.join("test_overriden_fixture_finalizer.py").write(dedent("""
- import pytest
- @pytest.fixture
- def browser(browser):
- browser['visited'] = True
- return browser
-
- def test_browser(browser):
- assert browser['visited'] is True
- """))
- reprec = testdir.runpytest("-s")
- for test in ['test_browser']:
- reprec.stdout.fnmatch_lines('*Finalized*')
-
- def test_class_scope_with_normal_tests(self, testdir):
- testpath = testdir.makepyfile("""
- import pytest
-
- class Box:
- value = 0
-
- @pytest.fixture(scope='class')
- def a(request):
- Box.value += 1
- return Box.value
-
- def test_a(a):
- assert a == 1
-
- class Test1:
- def test_b(self, a):
- assert a == 2
-
- class Test2:
- def test_c(self, a):
- assert a == 3""")
- reprec = testdir.inline_run(testpath)
- for test in ['test_a', 'test_b', 'test_c']:
- assert reprec.matchreport(test).passed
-
- def test_request_is_clean(self, testdir):
- testdir.makepyfile("""
- import pytest
- l = []
- @pytest.fixture(params=[1, 2])
- def fix(request):
- request.addfinalizer(lambda: l.append(request.param))
- def test_fix(fix):
- pass
- """)
- reprec = testdir.inline_run("-s")
- l = reprec.getcalls("pytest_runtest_call")[0].item.module.l
- assert l == [1,2]
-
- def test_parametrize_separated_lifecycle(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- l = []
- @pytest.fixture(scope="module", params=[1, 2])
- def arg(request):
- x = request.param
- request.addfinalizer(lambda: l.append("fin%s" % x))
- return request.param
- def test_1(arg):
- l.append(arg)
- def test_2(arg):
- l.append(arg)
- """)
- reprec = testdir.inline_run("-vs")
- reprec.assertoutcome(passed=4)
- l = reprec.getcalls("pytest_runtest_call")[0].item.module.l
- import pprint
- pprint.pprint(l)
- #assert len(l) == 6
- assert l[0] == l[1] == 1
- assert l[2] == "fin1"
- assert l[3] == l[4] == 2
- assert l[5] == "fin2"
-
- def test_parametrize_function_scoped_finalizers_called(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- @pytest.fixture(scope="function", params=[1, 2])
- def arg(request):
- x = request.param
- request.addfinalizer(lambda: l.append("fin%s" % x))
- return request.param
-
- l = []
- def test_1(arg):
- l.append(arg)
- def test_2(arg):
- l.append(arg)
- def test_3():
- assert len(l) == 8
- assert l == [1, "fin1", 2, "fin2", 1, "fin1", 2, "fin2"]
- """)
- reprec = testdir.inline_run("-v")
- reprec.assertoutcome(passed=5)
-
-
- @pytest.mark.issue246
- @pytest.mark.parametrize("scope", ["session", "function", "module"])
- def test_finalizer_order_on_parametrization(self, scope, testdir):
- testdir.makepyfile("""
- import pytest
- l = []
-
- @pytest.fixture(scope=%(scope)r, params=["1"])
- def fix1(request):
- return request.param
-
- @pytest.fixture(scope=%(scope)r)
- def fix2(request, base):
- def cleanup_fix2():
- assert not l, "base should not have been finalized"
- request.addfinalizer(cleanup_fix2)
-
- @pytest.fixture(scope=%(scope)r)
- def base(request, fix1):
- def cleanup_base():
- l.append("fin_base")
- print ("finalizing base")
- request.addfinalizer(cleanup_base)
-
- def test_begin():
- pass
- def test_baz(base, fix2):
- pass
- def test_other():
- pass
- """ % {"scope": scope})
- reprec = testdir.inline_run("-lvs")
- reprec.assertoutcome(passed=3)
-
- @pytest.mark.issue396
- def test_class_scope_parametrization_ordering(self, testdir):
- testdir.makepyfile("""
- import pytest
- l = []
- @pytest.fixture(params=["John", "Doe"], scope="class")
- def human(request):
- request.addfinalizer(lambda: l.append("fin %s" % request.param))
- return request.param
-
- class TestGreetings:
- def test_hello(self, human):
- l.append("test_hello")
-
- class TestMetrics:
- def test_name(self, human):
- l.append("test_name")
-
- def test_population(self, human):
- l.append("test_population")
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=6)
- l = reprec.getcalls("pytest_runtest_call")[0].item.module.l
- assert l == ["test_hello", "fin John", "test_hello", "fin Doe",
- "test_name", "test_population", "fin John",
- "test_name", "test_population", "fin Doe"]
-
- def test_parametrize_setup_function(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- @pytest.fixture(scope="module", params=[1, 2])
- def arg(request):
- return request.param
-
- @pytest.fixture(scope="module", autouse=True)
- def mysetup(request, arg):
- request.addfinalizer(lambda: l.append("fin%s" % arg))
- l.append("setup%s" % arg)
-
- l = []
- def test_1(arg):
- l.append(arg)
- def test_2(arg):
- l.append(arg)
- def test_3():
- import pprint
- pprint.pprint(l)
- if arg == 1:
- assert l == ["setup1", 1, 1, ]
- elif arg == 2:
- assert l == ["setup1", 1, 1, "fin1",
- "setup2", 2, 2, ]
-
- """)
- reprec = testdir.inline_run("-v")
- reprec.assertoutcome(passed=6)
-
- def test_fixture_marked_function_not_collected_as_test(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.fixture
- def test_app():
- return 1
-
- def test_something(test_app):
- assert test_app == 1
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
- def test_params_and_ids(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- @pytest.fixture(params=[object(), object()],
- ids=['alpha', 'beta'])
- def fix(request):
- return request.param
-
- def test_foo(fix):
- assert 1
- """)
- res = testdir.runpytest('-v')
- res.stdout.fnmatch_lines([
- '*test_foo*alpha*',
- '*test_foo*beta*'])
-
- def test_params_and_ids_yieldfixture(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- @pytest.yield_fixture(params=[object(), object()],
- ids=['alpha', 'beta'])
- def fix(request):
- yield request.param
-
- def test_foo(fix):
- assert 1
- """)
- res = testdir.runpytest('-v')
- res.stdout.fnmatch_lines([
- '*test_foo*alpha*',
- '*test_foo*beta*'])
-
-
-class TestRequestScopeAccess:
- pytestmark = pytest.mark.parametrize(("scope", "ok", "error"),[
- ["session", "", "fspath class function module"],
- ["module", "module fspath", "cls function"],
- ["class", "module fspath cls", "function"],
- ["function", "module fspath cls function", ""]
- ])
-
- def test_setup(self, testdir, scope, ok, error):
- testdir.makepyfile("""
- import pytest
- @pytest.fixture(scope=%r, autouse=True)
- def myscoped(request):
- for x in %r:
- assert hasattr(request, x)
- for x in %r:
- pytest.raises(AttributeError, lambda:
- getattr(request, x))
- assert request.session
- assert request.config
- def test_func():
- pass
- """ %(scope, ok.split(), error.split()))
- reprec = testdir.inline_run("-l")
- reprec.assertoutcome(passed=1)
-
- def test_funcarg(self, testdir, scope, ok, error):
- testdir.makepyfile("""
- import pytest
- @pytest.fixture(scope=%r)
- def arg(request):
- for x in %r:
- assert hasattr(request, x)
- for x in %r:
- pytest.raises(AttributeError, lambda:
- getattr(request, x))
- assert request.session
- assert request.config
- def test_func(arg):
- pass
- """ %(scope, ok.split(), error.split()))
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
-class TestErrors:
- def test_subfactory_missing_funcarg(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.fixture()
- def gen(qwe123):
- return 1
- def test_something(gen):
- pass
- """)
- result = testdir.runpytest()
- assert result.ret != 0
- result.stdout.fnmatch_lines([
- "*def gen(qwe123):*",
- "*fixture*qwe123*not found*",
- "*1 error*",
- ])
-
- def test_issue498_fixture_finalizer_failing(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.fixture
- def fix1(request):
- def f():
- raise KeyError
- request.addfinalizer(f)
- return object()
-
- l = []
- def test_1(fix1):
- l.append(fix1)
- def test_2(fix1):
- l.append(fix1)
- def test_3():
- assert l[0] != l[1]
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines("""
- *ERROR*teardown*test_1*
- *KeyError*
- *ERROR*teardown*test_2*
- *KeyError*
- *3 pass*2 error*
- """)
-
-
-
- def test_setupfunc_missing_funcarg(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.fixture(autouse=True)
- def gen(qwe123):
- return 1
- def test_something():
- pass
- """)
- result = testdir.runpytest()
- assert result.ret != 0
- result.stdout.fnmatch_lines([
- "*def gen(qwe123):*",
- "*fixture*qwe123*not found*",
- "*1 error*",
- ])
-
-class TestShowFixtures:
- def test_funcarg_compat(self, testdir):
- config = testdir.parseconfigure("--funcargs")
- assert config.option.showfixtures
-
- def test_show_fixtures(self, testdir):
- result = testdir.runpytest("--fixtures")
- result.stdout.fnmatch_lines([
- "*tmpdir*",
- "*temporary directory*",
- ]
- )
-
- def test_show_fixtures_verbose(self, testdir):
- result = testdir.runpytest("--fixtures", "-v")
- result.stdout.fnmatch_lines([
- "*tmpdir*--*tmpdir.py*",
- "*temporary directory*",
- ]
- )
-
- def test_show_fixtures_testmodule(self, testdir):
- p = testdir.makepyfile('''
- import pytest
- @pytest.fixture
- def _arg0():
- """ hidden """
- @pytest.fixture
- def arg1():
- """ hello world """
- ''')
- result = testdir.runpytest("--fixtures", p)
- result.stdout.fnmatch_lines("""
- *tmpdir
- *fixtures defined from*
- *arg1*
- *hello world*
- """)
- assert "arg0" not in result.stdout.str()
-
- @pytest.mark.parametrize("testmod", [True, False])
- def test_show_fixtures_conftest(self, testdir, testmod):
- testdir.makeconftest('''
- import pytest
- @pytest.fixture
- def arg1():
- """ hello world """
- ''')
- if testmod:
- testdir.makepyfile("""
- def test_hello():
- pass
- """)
- result = testdir.runpytest("--fixtures")
- result.stdout.fnmatch_lines("""
- *tmpdir*
- *fixtures defined from*conftest*
- *arg1*
- *hello world*
- """)
-
- def test_show_fixtures_trimmed_doc(self, testdir):
- p = testdir.makepyfile('''
- import pytest
- @pytest.fixture
- def arg1():
- """
- line1
- line2
-
- """
- @pytest.fixture
- def arg2():
- """
- line1
- line2
-
- """
- ''')
- result = testdir.runpytest("--fixtures", p)
- result.stdout.fnmatch_lines("""
- * fixtures defined from test_show_fixtures_trimmed_doc *
- arg2
- line1
- line2
- arg1
- line1
- line2
-
- """)
-
-
- def test_show_fixtures_different_files(self, testdir):
- """
- #833: --fixtures only shows fixtures from first file
- """
- testdir.makepyfile(test_a='''
- import pytest
-
- @pytest.fixture
- def fix_a():
- """Fixture A"""
- pass
-
- def test_a(fix_a):
- pass
- ''')
- testdir.makepyfile(test_b='''
- import pytest
-
- @pytest.fixture
- def fix_b():
- """Fixture B"""
- pass
-
- def test_b(fix_b):
- pass
- ''')
- result = testdir.runpytest("--fixtures")
- result.stdout.fnmatch_lines("""
- * fixtures defined from test_a *
- fix_a
- Fixture A
-
- * fixtures defined from test_b *
- fix_b
- Fixture B
- """)
-
-
-class TestContextManagerFixtureFuncs:
- def test_simple(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.yield_fixture
- def arg1():
- print ("setup")
- yield 1
- print ("teardown")
- def test_1(arg1):
- print ("test1 %s" % arg1)
- def test_2(arg1):
- print ("test2 %s" % arg1)
- assert 0
- """)
- result = testdir.runpytest("-s")
- result.stdout.fnmatch_lines("""
- *setup*
- *test1 1*
- *teardown*
- *setup*
- *test2 1*
- *teardown*
- """)
-
- def test_scoped(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.yield_fixture(scope="module")
- def arg1():
- print ("setup")
- yield 1
- print ("teardown")
- def test_1(arg1):
- print ("test1 %s" % arg1)
- def test_2(arg1):
- print ("test2 %s" % arg1)
- """)
- result = testdir.runpytest("-s")
- result.stdout.fnmatch_lines("""
- *setup*
- *test1 1*
- *test2 1*
- *teardown*
- """)
-
- def test_setup_exception(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.yield_fixture(scope="module")
- def arg1():
- pytest.fail("setup")
- yield 1
- def test_1(arg1):
- pass
- """)
- result = testdir.runpytest("-s")
- result.stdout.fnmatch_lines("""
- *pytest.fail*setup*
- *1 error*
- """)
-
- def test_teardown_exception(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.yield_fixture(scope="module")
- def arg1():
- yield 1
- pytest.fail("teardown")
- def test_1(arg1):
- pass
- """)
- result = testdir.runpytest("-s")
- result.stdout.fnmatch_lines("""
- *pytest.fail*teardown*
- *1 passed*1 error*
- """)
-
- def test_yields_more_than_one(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.yield_fixture(scope="module")
- def arg1():
- yield 1
- yield 2
- def test_1(arg1):
- pass
- """)
- result = testdir.runpytest("-s")
- result.stdout.fnmatch_lines("""
- *fixture function*
- *test_yields*:2*
- """)
-
-
- def test_no_yield(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.yield_fixture(scope="module")
- def arg1():
- return 1
- def test_1(arg1):
- pass
- """)
- result = testdir.runpytest("-s")
- result.stdout.fnmatch_lines("""
- *yield_fixture*requires*yield*
- *yield_fixture*
- *def arg1*
- """)
-
- def test_yield_not_allowed_in_non_yield(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.fixture(scope="module")
- def arg1():
- yield 1
- def test_1(arg1):
- pass
- """)
- result = testdir.runpytest("-s")
- result.stdout.fnmatch_lines("""
- *fixture*cannot use*yield*
- *def arg1*
- """)
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/python/integration.py b/tests/wpt/web-platform-tests/tools/pytest/testing/python/integration.py
deleted file mode 100644
index dea86f942fd..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/python/integration.py
+++ /dev/null
@@ -1,369 +0,0 @@
-import pytest
-from _pytest import python
-from _pytest import runner
-
-
-class TestOEJSKITSpecials:
- def test_funcarg_non_pycollectobj(self, testdir): # rough jstests usage
- testdir.makeconftest("""
- import pytest
- def pytest_pycollect_makeitem(collector, name, obj):
- if name == "MyClass":
- return MyCollector(name, parent=collector)
- class MyCollector(pytest.Collector):
- def reportinfo(self):
- return self.fspath, 3, "xyz"
- """)
- modcol = testdir.getmodulecol("""
- def pytest_funcarg__arg1(request):
- return 42
- class MyClass:
- pass
- """)
- # this hook finds funcarg factories
- rep = runner.collect_one_node(collector=modcol)
- clscol = rep.result[0]
- clscol.obj = lambda arg1: None
- clscol.funcargs = {}
- pytest._fillfuncargs(clscol)
- assert clscol.funcargs['arg1'] == 42
-
- def test_autouse_fixture(self, testdir): # rough jstests usage
- testdir.makeconftest("""
- import pytest
- def pytest_pycollect_makeitem(collector, name, obj):
- if name == "MyClass":
- return MyCollector(name, parent=collector)
- class MyCollector(pytest.Collector):
- def reportinfo(self):
- return self.fspath, 3, "xyz"
- """)
- modcol = testdir.getmodulecol("""
- import pytest
- @pytest.fixture(autouse=True)
- def hello():
- pass
- def pytest_funcarg__arg1(request):
- return 42
- class MyClass:
- pass
- """)
- # this hook finds funcarg factories
- rep = runner.collect_one_node(modcol)
- clscol = rep.result[0]
- clscol.obj = lambda: None
- clscol.funcargs = {}
- pytest._fillfuncargs(clscol)
- assert not clscol.funcargs
-
-
-def test_wrapped_getfslineno():
- def func():
- pass
- def wrap(f):
- func.__wrapped__ = f
- func.patchings = ["qwe"]
- return func
- @wrap
- def wrapped_func(x, y, z):
- pass
- fs, lineno = python.getfslineno(wrapped_func)
- fs2, lineno2 = python.getfslineno(wrap)
- assert lineno > lineno2, "getfslineno does not unwrap correctly"
-
-class TestMockDecoration:
- def test_wrapped_getfuncargnames(self):
- from _pytest.python import getfuncargnames
- def wrap(f):
- def func():
- pass
- func.__wrapped__ = f
- return func
- @wrap
- def f(x):
- pass
- l = getfuncargnames(f)
- assert l == ("x",)
-
- def test_wrapped_getfuncargnames_patching(self):
- from _pytest.python import getfuncargnames
- def wrap(f):
- def func():
- pass
- func.__wrapped__ = f
- func.patchings = ["qwe"]
- return func
- @wrap
- def f(x, y, z):
- pass
- l = getfuncargnames(f)
- assert l == ("y", "z")
-
- def test_unittest_mock(self, testdir):
- pytest.importorskip("unittest.mock")
- testdir.makepyfile("""
- import unittest.mock
- class T(unittest.TestCase):
- @unittest.mock.patch("os.path.abspath")
- def test_hello(self, abspath):
- import os
- os.path.abspath("hello")
- abspath.assert_any_call("hello")
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
- def test_unittest_mock_and_fixture(self, testdir):
- pytest.importorskip("unittest.mock")
- testdir.makepyfile("""
- import os.path
- import unittest.mock
- import pytest
-
- @pytest.fixture
- def inject_me():
- pass
-
- @unittest.mock.patch.object(os.path, "abspath",
- new=unittest.mock.MagicMock)
- def test_hello(inject_me):
- import os
- os.path.abspath("hello")
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
- def test_mock(self, testdir):
- pytest.importorskip("mock", "1.0.1")
- testdir.makepyfile("""
- import os
- import unittest
- import mock
-
- class T(unittest.TestCase):
- @mock.patch("os.path.abspath")
- def test_hello(self, abspath):
- os.path.abspath("hello")
- abspath.assert_any_call("hello")
- def mock_basename(path):
- return "mock_basename"
- @mock.patch("os.path.abspath")
- @mock.patch("os.path.normpath")
- @mock.patch("os.path.basename", new=mock_basename)
- def test_someting(normpath, abspath, tmpdir):
- abspath.return_value = "this"
- os.path.normpath(os.path.abspath("hello"))
- normpath.assert_any_call("this")
- assert os.path.basename("123") == "mock_basename"
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=2)
- calls = reprec.getcalls("pytest_runtest_logreport")
- funcnames = [call.report.location[2] for call in calls
- if call.report.when == "call"]
- assert funcnames == ["T.test_hello", "test_someting"]
-
- def test_mock_sorting(self, testdir):
- pytest.importorskip("mock", "1.0.1")
- testdir.makepyfile("""
- import os
- import mock
-
- @mock.patch("os.path.abspath")
- def test_one(abspath):
- pass
- @mock.patch("os.path.abspath")
- def test_two(abspath):
- pass
- @mock.patch("os.path.abspath")
- def test_three(abspath):
- pass
- """)
- reprec = testdir.inline_run()
- calls = reprec.getreports("pytest_runtest_logreport")
- calls = [x for x in calls if x.when == "call"]
- names = [x.nodeid.split("::")[-1] for x in calls]
- assert names == ["test_one", "test_two", "test_three"]
-
- def test_mock_double_patch_issue473(self, testdir):
- pytest.importorskip("mock", "1.0.1")
- testdir.makepyfile("""
- from mock import patch
- from pytest import mark
-
- @patch('os.getcwd')
- @patch('os.path')
- @mark.slow
- class TestSimple:
- def test_simple_thing(self, mock_path, mock_getcwd):
- pass
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
-
-class TestReRunTests:
- def test_rerun(self, testdir):
- testdir.makeconftest("""
- from _pytest.runner import runtestprotocol
- def pytest_runtest_protocol(item, nextitem):
- runtestprotocol(item, log=False, nextitem=nextitem)
- runtestprotocol(item, log=True, nextitem=nextitem)
- """)
- testdir.makepyfile("""
- import pytest
- count = 0
- req = None
- @pytest.fixture
- def fix(request):
- global count, req
- assert request != req
- req = request
- print ("fix count %s" % count)
- count += 1
- def test_fix(fix):
- pass
- """)
- result = testdir.runpytest("-s")
- result.stdout.fnmatch_lines("""
- *fix count 0*
- *fix count 1*
- """)
- result.stdout.fnmatch_lines("""
- *2 passed*
- """)
-
-def test_pytestconfig_is_session_scoped():
- from _pytest.python import pytestconfig
- assert pytestconfig._pytestfixturefunction.scope == "session"
-
-
-class TestNoselikeTestAttribute:
- def test_module_with_global_test(self, testdir):
- testdir.makepyfile("""
- __test__ = False
- def test_hello():
- pass
- """)
- reprec = testdir.inline_run()
- assert not reprec.getfailedcollections()
- calls = reprec.getreports("pytest_runtest_logreport")
- assert not calls
-
- def test_class_and_method(self, testdir):
- testdir.makepyfile("""
- __test__ = True
- def test_func():
- pass
- test_func.__test__ = False
-
- class TestSome:
- __test__ = False
- def test_method(self):
- pass
- """)
- reprec = testdir.inline_run()
- assert not reprec.getfailedcollections()
- calls = reprec.getreports("pytest_runtest_logreport")
- assert not calls
-
- def test_unittest_class(self, testdir):
- testdir.makepyfile("""
- import unittest
- class TC(unittest.TestCase):
- def test_1(self):
- pass
- class TC2(unittest.TestCase):
- __test__ = False
- def test_2(self):
- pass
- """)
- reprec = testdir.inline_run()
- assert not reprec.getfailedcollections()
- call = reprec.getcalls("pytest_collection_modifyitems")[0]
- assert len(call.items) == 1
- assert call.items[0].cls.__name__ == "TC"
-
- def test_class_with_nasty_getattr(self, testdir):
- """Make sure we handle classes with a custom nasty __getattr__ right.
-
- With a custom __getattr__ which e.g. returns a function (like with a
- RPC wrapper), we shouldn't assume this meant "__test__ = True".
- """
- # https://github.com/pytest-dev/pytest/issues/1204
- testdir.makepyfile("""
- class MetaModel(type):
-
- def __getattr__(cls, key):
- return lambda: None
-
-
- BaseModel = MetaModel('Model', (), {})
-
-
- class Model(BaseModel):
-
- __metaclass__ = MetaModel
-
- def test_blah(self):
- pass
- """)
- reprec = testdir.inline_run()
- assert not reprec.getfailedcollections()
- call = reprec.getcalls("pytest_collection_modifyitems")[0]
- assert not call.items
-
-
-@pytest.mark.issue351
-class TestParameterize:
-
- def test_idfn_marker(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- def idfn(param):
- if param == 0:
- return 'spam'
- elif param == 1:
- return 'ham'
- else:
- return None
-
- @pytest.mark.parametrize('a,b', [(0, 2), (1, 2)], ids=idfn)
- def test_params(a, b):
- pass
- """)
- res = testdir.runpytest('--collect-only')
- res.stdout.fnmatch_lines([
- "*spam-2*",
- "*ham-2*",
- ])
-
- def test_idfn_fixture(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- def idfn(param):
- if param == 0:
- return 'spam'
- elif param == 1:
- return 'ham'
- else:
- return None
-
- @pytest.fixture(params=[0, 1], ids=idfn)
- def a(request):
- return request.param
-
- @pytest.fixture(params=[1, 2], ids=idfn)
- def b(request):
- return request.param
-
- def test_params(a, b):
- pass
- """)
- res = testdir.runpytest('--collect-only')
- res.stdout.fnmatch_lines([
- "*spam-2*",
- "*ham-2*",
- ])
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/python/metafunc.py b/tests/wpt/web-platform-tests/tools/pytest/testing/python/metafunc.py
deleted file mode 100644
index faa687f4056..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/python/metafunc.py
+++ /dev/null
@@ -1,1094 +0,0 @@
-# -*- coding: utf-8 -*-
-import re
-
-import _pytest._code
-import py
-import pytest
-from _pytest import python as funcargs
-
-class TestMetafunc:
- def Metafunc(self, func):
- # the unit tests of this class check if things work correctly
- # on the funcarg level, so we don't need a full blown
- # initiliazation
- class FixtureInfo:
- name2fixturedefs = None
- def __init__(self, names):
- self.names_closure = names
- names = funcargs.getfuncargnames(func)
- fixtureinfo = FixtureInfo(names)
- return funcargs.Metafunc(func, fixtureinfo, None)
-
- def test_no_funcargs(self, testdir):
- def function(): pass
- metafunc = self.Metafunc(function)
- assert not metafunc.fixturenames
- repr(metafunc._calls)
-
- def test_function_basic(self):
- def func(arg1, arg2="qwe"): pass
- metafunc = self.Metafunc(func)
- assert len(metafunc.fixturenames) == 1
- assert 'arg1' in metafunc.fixturenames
- assert metafunc.function is func
- assert metafunc.cls is None
-
- def test_addcall_no_args(self):
- def func(arg1): pass
- metafunc = self.Metafunc(func)
- metafunc.addcall()
- assert len(metafunc._calls) == 1
- call = metafunc._calls[0]
- assert call.id == "0"
- assert not hasattr(call, 'param')
-
- def test_addcall_id(self):
- def func(arg1): pass
- metafunc = self.Metafunc(func)
- pytest.raises(ValueError, "metafunc.addcall(id=None)")
-
- metafunc.addcall(id=1)
- pytest.raises(ValueError, "metafunc.addcall(id=1)")
- pytest.raises(ValueError, "metafunc.addcall(id='1')")
- metafunc.addcall(id=2)
- assert len(metafunc._calls) == 2
- assert metafunc._calls[0].id == "1"
- assert metafunc._calls[1].id == "2"
-
- def test_addcall_param(self):
- def func(arg1): pass
- metafunc = self.Metafunc(func)
- class obj: pass
- metafunc.addcall(param=obj)
- metafunc.addcall(param=obj)
- metafunc.addcall(param=1)
- assert len(metafunc._calls) == 3
- assert metafunc._calls[0].getparam("arg1") == obj
- assert metafunc._calls[1].getparam("arg1") == obj
- assert metafunc._calls[2].getparam("arg1") == 1
-
- def test_addcall_funcargs(self):
- def func(x): pass
- metafunc = self.Metafunc(func)
- class obj: pass
- metafunc.addcall(funcargs={"x": 2})
- metafunc.addcall(funcargs={"x": 3})
- pytest.raises(pytest.fail.Exception, "metafunc.addcall({'xyz': 0})")
- assert len(metafunc._calls) == 2
- assert metafunc._calls[0].funcargs == {'x': 2}
- assert metafunc._calls[1].funcargs == {'x': 3}
- assert not hasattr(metafunc._calls[1], 'param')
-
- def test_parametrize_error(self):
- def func(x, y): pass
- metafunc = self.Metafunc(func)
- metafunc.parametrize("x", [1,2])
- pytest.raises(ValueError, lambda: metafunc.parametrize("x", [5,6]))
- pytest.raises(ValueError, lambda: metafunc.parametrize("x", [5,6]))
- metafunc.parametrize("y", [1,2])
- pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5,6]))
- pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5,6]))
-
- def test_parametrize_and_id(self):
- def func(x, y): pass
- metafunc = self.Metafunc(func)
-
- metafunc.parametrize("x", [1,2], ids=['basic', 'advanced'])
- metafunc.parametrize("y", ["abc", "def"])
- ids = [x.id for x in metafunc._calls]
- assert ids == ["basic-abc", "basic-def", "advanced-abc", "advanced-def"]
-
- def test_parametrize_with_wrong_number_of_ids(self, testdir):
- def func(x, y): pass
- metafunc = self.Metafunc(func)
-
- pytest.raises(ValueError, lambda:
- metafunc.parametrize("x", [1,2], ids=['basic']))
-
- pytest.raises(ValueError, lambda:
- metafunc.parametrize(("x","y"), [("abc", "def"),
- ("ghi", "jkl")], ids=["one"]))
-
- def test_parametrize_with_userobjects(self):
- def func(x, y): pass
- metafunc = self.Metafunc(func)
- class A:
- pass
- metafunc.parametrize("x", [A(), A()])
- metafunc.parametrize("y", list("ab"))
- assert metafunc._calls[0].id == "x0-a"
- assert metafunc._calls[1].id == "x0-b"
- assert metafunc._calls[2].id == "x1-a"
- assert metafunc._calls[3].id == "x1-b"
-
- @pytest.mark.skipif('sys.version_info[0] >= 3')
- def test_unicode_idval_python2(self):
- """unittest for the expected behavior to obtain ids for parametrized
- unicode values in Python 2: if convertible to ascii, they should appear
- as ascii values, otherwise fallback to hide the value behind the name
- of the parametrized variable name. #1086
- """
- from _pytest.python import _idval
- values = [
- (u'', ''),
- (u'ascii', 'ascii'),
- (u'ação', 'a6'),
- (u'josé@blah.com', 'a6'),
- (u'δοκ.ιμή@παράδειγμα.δοκιμή', 'a6'),
- ]
- for val, expected in values:
- assert _idval(val, 'a', 6, None) == expected
-
- def test_bytes_idval(self):
- """unittest for the expected behavior to obtain ids for parametrized
- bytes values:
- - python2: non-ascii strings are considered bytes and formatted using
- "binary escape", where any byte < 127 is escaped into its hex form.
- - python3: bytes objects are always escaped using "binary escape".
- """
- from _pytest.python import _idval
- values = [
- (b'', ''),
- (b'\xc3\xb4\xff\xe4', '\\xc3\\xb4\\xff\\xe4'),
- (b'ascii', 'ascii'),
- (u'αρά'.encode('utf-8'), '\\xce\\xb1\\xcf\\x81\\xce\\xac'),
- ]
- for val, expected in values:
- assert _idval(val, 'a', 6, None) == expected
-
- @pytest.mark.issue250
- def test_idmaker_autoname(self):
- from _pytest.python import idmaker
- result = idmaker(("a", "b"), [("string", 1.0),
- ("st-ring", 2.0)])
- assert result == ["string-1.0", "st-ring-2.0"]
-
- result = idmaker(("a", "b"), [(object(), 1.0),
- (object(), object())])
- assert result == ["a0-1.0", "a1-b1"]
- # unicode mixing, issue250
- result = idmaker((py.builtin._totext("a"), "b"), [({}, b'\xc3\xb4')])
- assert result == ['a0-\\xc3\\xb4']
-
- def test_idmaker_with_bytes_regex(self):
- from _pytest.python import idmaker
- result = idmaker(("a"), [(re.compile(b'foo'), 1.0)])
- assert result == ["foo"]
-
- def test_idmaker_native_strings(self):
- from _pytest.python import idmaker
- totext = py.builtin._totext
- result = idmaker(("a", "b"), [(1.0, -1.1),
- (2, -202),
- ("three", "three hundred"),
- (True, False),
- (None, None),
- (re.compile('foo'), re.compile('bar')),
- (str, int),
- (list("six"), [66, 66]),
- (set([7]), set("seven")),
- (tuple("eight"), (8, -8, 8)),
- (b'\xc3\xb4', b"name"),
- (b'\xc3\xb4', totext("other")),
- ])
- assert result == ["1.0--1.1",
- "2--202",
- "three-three hundred",
- "True-False",
- "None-None",
- "foo-bar",
- "str-int",
- "a7-b7",
- "a8-b8",
- "a9-b9",
- "\\xc3\\xb4-name",
- "\\xc3\\xb4-other",
- ]
-
- def test_idmaker_enum(self):
- from _pytest.python import idmaker
- enum = pytest.importorskip("enum")
- e = enum.Enum("Foo", "one, two")
- result = idmaker(("a", "b"), [(e.one, e.two)])
- assert result == ["Foo.one-Foo.two"]
-
- @pytest.mark.issue351
- def test_idmaker_idfn(self):
- from _pytest.python import idmaker
- def ids(val):
- if isinstance(val, Exception):
- return repr(val)
-
- result = idmaker(("a", "b"), [(10.0, IndexError()),
- (20, KeyError()),
- ("three", [1, 2, 3]),
- ], idfn=ids)
- assert result == ["10.0-IndexError()",
- "20-KeyError()",
- "three-b2",
- ]
-
- @pytest.mark.issue351
- def test_idmaker_idfn_unique_names(self):
- from _pytest.python import idmaker
- def ids(val):
- return 'a'
-
- result = idmaker(("a", "b"), [(10.0, IndexError()),
- (20, KeyError()),
- ("three", [1, 2, 3]),
- ], idfn=ids)
- assert result == ["0a-a",
- "1a-a",
- "2a-a",
- ]
-
- @pytest.mark.issue351
- def test_idmaker_idfn_exception(self):
- from _pytest.python import idmaker
- def ids(val):
- raise Exception("bad code")
-
- result = idmaker(("a", "b"), [(10.0, IndexError()),
- (20, KeyError()),
- ("three", [1, 2, 3]),
- ], idfn=ids)
- assert result == ["10.0-b0",
- "20-b1",
- "three-b2",
- ]
-
- def test_addcall_and_parametrize(self):
- def func(x, y): pass
- metafunc = self.Metafunc(func)
- metafunc.addcall({'x': 1})
- metafunc.parametrize('y', [2,3])
- assert len(metafunc._calls) == 2
- assert metafunc._calls[0].funcargs == {'x': 1, 'y': 2}
- assert metafunc._calls[1].funcargs == {'x': 1, 'y': 3}
- assert metafunc._calls[0].id == "0-2"
- assert metafunc._calls[1].id == "0-3"
-
- @pytest.mark.issue714
- def test_parametrize_indirect(self):
- def func(x, y): pass
- metafunc = self.Metafunc(func)
- metafunc.parametrize('x', [1], indirect=True)
- metafunc.parametrize('y', [2,3], indirect=True)
- assert len(metafunc._calls) == 2
- assert metafunc._calls[0].funcargs == {}
- assert metafunc._calls[1].funcargs == {}
- assert metafunc._calls[0].params == dict(x=1,y=2)
- assert metafunc._calls[1].params == dict(x=1,y=3)
-
- @pytest.mark.issue714
- def test_parametrize_indirect_list(self):
- def func(x, y): pass
- metafunc = self.Metafunc(func)
- metafunc.parametrize('x, y', [('a', 'b')], indirect=['x'])
- assert metafunc._calls[0].funcargs == dict(y='b')
- assert metafunc._calls[0].params == dict(x='a')
-
- @pytest.mark.issue714
- def test_parametrize_indirect_list_all(self):
- def func(x, y): pass
- metafunc = self.Metafunc(func)
- metafunc.parametrize('x, y', [('a', 'b')], indirect=['x', 'y'])
- assert metafunc._calls[0].funcargs == {}
- assert metafunc._calls[0].params == dict(x='a', y='b')
-
- @pytest.mark.issue714
- def test_parametrize_indirect_list_empty(self):
- def func(x, y): pass
- metafunc = self.Metafunc(func)
- metafunc.parametrize('x, y', [('a', 'b')], indirect=[])
- assert metafunc._calls[0].funcargs == dict(x='a', y='b')
- assert metafunc._calls[0].params == {}
-
- @pytest.mark.issue714
- def test_parametrize_indirect_list_functional(self, testdir):
- """
- Test parametrization with 'indirect' parameter applied on
- particular arguments. As y is is direct, its value should
- be used directly rather than being passed to the fixture
- y.
-
- :param testdir: the instance of Testdir class, a temporary
- test directory.
- """
- testdir.makepyfile("""
- import pytest
- @pytest.fixture(scope='function')
- def x(request):
- return request.param * 3
- @pytest.fixture(scope='function')
- def y(request):
- return request.param * 2
- @pytest.mark.parametrize('x, y', [('a', 'b')], indirect=['x'])
- def test_simple(x,y):
- assert len(x) == 3
- assert len(y) == 1
- """)
- result = testdir.runpytest("-v")
- result.stdout.fnmatch_lines([
- "*test_simple*a-b*",
- "*1 passed*",
- ])
-
- @pytest.mark.issue714
- def test_parametrize_indirect_list_error(self, testdir):
- def func(x, y): pass
- metafunc = self.Metafunc(func)
- with pytest.raises(ValueError):
- metafunc.parametrize('x, y', [('a', 'b')], indirect=['x', 'z'])
-
- @pytest.mark.issue714
- def test_parametrize_uses_no_fixture_error_indirect_false(self, testdir):
- """The 'uses no fixture' error tells the user at collection time
- that the parametrize data they've set up doesn't correspond to the
- fixtures in their test function, rather than silently ignoring this
- and letting the test potentially pass.
- """
- testdir.makepyfile("""
- import pytest
-
- @pytest.mark.parametrize('x, y', [('a', 'b')], indirect=False)
- def test_simple(x):
- assert len(x) == 3
- """)
- result = testdir.runpytest("--collect-only")
- result.stdout.fnmatch_lines([
- "*uses no fixture 'y'*",
- ])
-
- @pytest.mark.issue714
- def test_parametrize_uses_no_fixture_error_indirect_true(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.fixture(scope='function')
- def x(request):
- return request.param * 3
- @pytest.fixture(scope='function')
- def y(request):
- return request.param * 2
-
- @pytest.mark.parametrize('x, y', [('a', 'b')], indirect=True)
- def test_simple(x):
- assert len(x) == 3
- """)
- result = testdir.runpytest("--collect-only")
- result.stdout.fnmatch_lines([
- "*uses no fixture 'y'*",
- ])
-
- @pytest.mark.issue714
- def test_parametrize_indirect_uses_no_fixture_error_indirect_list(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.fixture(scope='function')
- def x(request):
- return request.param * 3
-
- @pytest.mark.parametrize('x, y', [('a', 'b')], indirect=['x'])
- def test_simple(x):
- assert len(x) == 3
- """)
- result = testdir.runpytest("--collect-only")
- result.stdout.fnmatch_lines([
- "*uses no fixture 'y'*",
- ])
-
- def test_addcalls_and_parametrize_indirect(self):
- def func(x, y): pass
- metafunc = self.Metafunc(func)
- metafunc.addcall(param="123")
- metafunc.parametrize('x', [1], indirect=True)
- metafunc.parametrize('y', [2,3], indirect=True)
- assert len(metafunc._calls) == 2
- assert metafunc._calls[0].funcargs == {}
- assert metafunc._calls[1].funcargs == {}
- assert metafunc._calls[0].params == dict(x=1,y=2)
- assert metafunc._calls[1].params == dict(x=1,y=3)
-
- def test_parametrize_functional(self, testdir):
- testdir.makepyfile("""
- def pytest_generate_tests(metafunc):
- metafunc.parametrize('x', [1,2], indirect=True)
- metafunc.parametrize('y', [2])
- def pytest_funcarg__x(request):
- return request.param * 10
- #def pytest_funcarg__y(request):
- # return request.param
-
- def test_simple(x,y):
- assert x in (10,20)
- assert y == 2
- """)
- result = testdir.runpytest("-v")
- result.stdout.fnmatch_lines([
- "*test_simple*1-2*",
- "*test_simple*2-2*",
- "*2 passed*",
- ])
-
- def test_parametrize_onearg(self):
- metafunc = self.Metafunc(lambda x: None)
- metafunc.parametrize("x", [1,2])
- assert len(metafunc._calls) == 2
- assert metafunc._calls[0].funcargs == dict(x=1)
- assert metafunc._calls[0].id == "1"
- assert metafunc._calls[1].funcargs == dict(x=2)
- assert metafunc._calls[1].id == "2"
-
- def test_parametrize_onearg_indirect(self):
- metafunc = self.Metafunc(lambda x: None)
- metafunc.parametrize("x", [1,2], indirect=True)
- assert metafunc._calls[0].params == dict(x=1)
- assert metafunc._calls[0].id == "1"
- assert metafunc._calls[1].params == dict(x=2)
- assert metafunc._calls[1].id == "2"
-
- def test_parametrize_twoargs(self):
- metafunc = self.Metafunc(lambda x,y: None)
- metafunc.parametrize(("x", "y"), [(1,2), (3,4)])
- assert len(metafunc._calls) == 2
- assert metafunc._calls[0].funcargs == dict(x=1, y=2)
- assert metafunc._calls[0].id == "1-2"
- assert metafunc._calls[1].funcargs == dict(x=3, y=4)
- assert metafunc._calls[1].id == "3-4"
-
- def test_parametrize_multiple_times(self, testdir):
- testdir.makepyfile("""
- import pytest
- pytestmark = pytest.mark.parametrize("x", [1,2])
- def test_func(x):
- assert 0, x
- class TestClass:
- pytestmark = pytest.mark.parametrize("y", [3,4])
- def test_meth(self, x, y):
- assert 0, x
- """)
- result = testdir.runpytest()
- assert result.ret == 1
- result.assert_outcomes(failed=6)
-
- def test_parametrize_CSV(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.mark.parametrize("x, y,", [(1,2), (2,3)])
- def test_func(x, y):
- assert x+1 == y
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=2)
-
- def test_parametrize_class_scenarios(self, testdir):
- testdir.makepyfile("""
- # same as doc/en/example/parametrize scenario example
- def pytest_generate_tests(metafunc):
- idlist = []
- argvalues = []
- for scenario in metafunc.cls.scenarios:
- idlist.append(scenario[0])
- items = scenario[1].items()
- argnames = [x[0] for x in items]
- argvalues.append(([x[1] for x in items]))
- metafunc.parametrize(argnames, argvalues, ids=idlist, scope="class")
-
- class Test(object):
- scenarios = [['1', {'arg': {1: 2}, "arg2": "value2"}],
- ['2', {'arg':'value2', "arg2": "value2"}]]
-
- def test_1(self, arg, arg2):
- pass
-
- def test_2(self, arg2, arg):
- pass
-
- def test_3(self, arg, arg2):
- pass
- """)
- result = testdir.runpytest("-v")
- assert result.ret == 0
- result.stdout.fnmatch_lines("""
- *test_1*1*
- *test_2*1*
- *test_3*1*
- *test_1*2*
- *test_2*2*
- *test_3*2*
- *6 passed*
- """)
-
- def test_format_args(self):
- def function1(): pass
- assert funcargs._format_args(function1) == '()'
-
- def function2(arg1): pass
- assert funcargs._format_args(function2) == "(arg1)"
-
- def function3(arg1, arg2="qwe"): pass
- assert funcargs._format_args(function3) == "(arg1, arg2='qwe')"
-
- def function4(arg1, *args, **kwargs): pass
- assert funcargs._format_args(function4) == "(arg1, *args, **kwargs)"
-
-
-class TestMetafuncFunctional:
- def test_attributes(self, testdir):
- p = testdir.makepyfile("""
- # assumes that generate/provide runs in the same process
- import py, pytest
- def pytest_generate_tests(metafunc):
- metafunc.addcall(param=metafunc)
-
- def pytest_funcarg__metafunc(request):
- assert request._pyfuncitem._genid == "0"
- return request.param
-
- def test_function(metafunc, pytestconfig):
- assert metafunc.config == pytestconfig
- assert metafunc.module.__name__ == __name__
- assert metafunc.function == test_function
- assert metafunc.cls is None
-
- class TestClass:
- def test_method(self, metafunc, pytestconfig):
- assert metafunc.config == pytestconfig
- assert metafunc.module.__name__ == __name__
- if py.std.sys.version_info > (3, 0):
- unbound = TestClass.test_method
- else:
- unbound = TestClass.test_method.im_func
- # XXX actually have an unbound test function here?
- assert metafunc.function == unbound
- assert metafunc.cls == TestClass
- """)
- result = testdir.runpytest(p, "-v")
- result.assert_outcomes(passed=2)
-
- def test_addcall_with_two_funcargs_generators(self, testdir):
- testdir.makeconftest("""
- def pytest_generate_tests(metafunc):
- assert "arg1" in metafunc.fixturenames
- metafunc.addcall(funcargs=dict(arg1=1, arg2=2))
- """)
- p = testdir.makepyfile("""
- def pytest_generate_tests(metafunc):
- metafunc.addcall(funcargs=dict(arg1=1, arg2=1))
-
- class TestClass:
- def test_myfunc(self, arg1, arg2):
- assert arg1 == arg2
- """)
- result = testdir.runpytest("-v", p)
- result.stdout.fnmatch_lines([
- "*test_myfunc*0*PASS*",
- "*test_myfunc*1*FAIL*",
- "*1 failed, 1 passed*"
- ])
-
- def test_two_functions(self, testdir):
- p = testdir.makepyfile("""
- def pytest_generate_tests(metafunc):
- metafunc.addcall(param=10)
- metafunc.addcall(param=20)
-
- def pytest_funcarg__arg1(request):
- return request.param
-
- def test_func1(arg1):
- assert arg1 == 10
- def test_func2(arg1):
- assert arg1 in (10, 20)
- """)
- result = testdir.runpytest("-v", p)
- result.stdout.fnmatch_lines([
- "*test_func1*0*PASS*",
- "*test_func1*1*FAIL*",
- "*test_func2*PASS*",
- "*1 failed, 3 passed*"
- ])
-
- def test_noself_in_method(self, testdir):
- p = testdir.makepyfile("""
- def pytest_generate_tests(metafunc):
- assert 'xyz' not in metafunc.fixturenames
-
- class TestHello:
- def test_hello(xyz):
- pass
- """)
- result = testdir.runpytest(p)
- result.assert_outcomes(passed=1)
-
-
- def test_generate_plugin_and_module(self, testdir):
- testdir.makeconftest("""
- def pytest_generate_tests(metafunc):
- assert "arg1" in metafunc.fixturenames
- metafunc.addcall(id="world", param=(2,100))
- """)
- p = testdir.makepyfile("""
- def pytest_generate_tests(metafunc):
- metafunc.addcall(param=(1,1), id="hello")
-
- def pytest_funcarg__arg1(request):
- return request.param[0]
- def pytest_funcarg__arg2(request):
- return request.param[1]
-
- class TestClass:
- def test_myfunc(self, arg1, arg2):
- assert arg1 == arg2
- """)
- result = testdir.runpytest("-v", p)
- result.stdout.fnmatch_lines([
- "*test_myfunc*hello*PASS*",
- "*test_myfunc*world*FAIL*",
- "*1 failed, 1 passed*"
- ])
-
- def test_generate_tests_in_class(self, testdir):
- p = testdir.makepyfile("""
- class TestClass:
- def pytest_generate_tests(self, metafunc):
- metafunc.addcall(funcargs={'hello': 'world'}, id="hello")
-
- def test_myfunc(self, hello):
- assert hello == "world"
- """)
- result = testdir.runpytest("-v", p)
- result.stdout.fnmatch_lines([
- "*test_myfunc*hello*PASS*",
- "*1 passed*"
- ])
-
- def test_two_functions_not_same_instance(self, testdir):
- p = testdir.makepyfile("""
- def pytest_generate_tests(metafunc):
- metafunc.addcall({'arg1': 10})
- metafunc.addcall({'arg1': 20})
-
- class TestClass:
- def test_func(self, arg1):
- assert not hasattr(self, 'x')
- self.x = 1
- """)
- result = testdir.runpytest("-v", p)
- result.stdout.fnmatch_lines([
- "*test_func*0*PASS*",
- "*test_func*1*PASS*",
- "*2 pass*",
- ])
-
- def test_issue28_setup_method_in_generate_tests(self, testdir):
- p = testdir.makepyfile("""
- def pytest_generate_tests(metafunc):
- metafunc.addcall({'arg1': 1})
-
- class TestClass:
- def test_method(self, arg1):
- assert arg1 == self.val
- def setup_method(self, func):
- self.val = 1
- """)
- result = testdir.runpytest(p)
- result.assert_outcomes(passed=1)
-
- def test_parametrize_functional2(self, testdir):
- testdir.makepyfile("""
- def pytest_generate_tests(metafunc):
- metafunc.parametrize("arg1", [1,2])
- metafunc.parametrize("arg2", [4,5])
- def test_hello(arg1, arg2):
- assert 0, (arg1, arg2)
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*(1, 4)*",
- "*(1, 5)*",
- "*(2, 4)*",
- "*(2, 5)*",
- "*4 failed*",
- ])
-
- def test_parametrize_and_inner_getfuncargvalue(self, testdir):
- p = testdir.makepyfile("""
- def pytest_generate_tests(metafunc):
- metafunc.parametrize("arg1", [1], indirect=True)
- metafunc.parametrize("arg2", [10], indirect=True)
-
- def pytest_funcarg__arg1(request):
- x = request.getfuncargvalue("arg2")
- return x + request.param
-
- def pytest_funcarg__arg2(request):
- return request.param
-
- def test_func1(arg1, arg2):
- assert arg1 == 11
- """)
- result = testdir.runpytest("-v", p)
- result.stdout.fnmatch_lines([
- "*test_func1*1*PASS*",
- "*1 passed*"
- ])
-
- def test_parametrize_on_setup_arg(self, testdir):
- p = testdir.makepyfile("""
- def pytest_generate_tests(metafunc):
- assert "arg1" in metafunc.fixturenames
- metafunc.parametrize("arg1", [1], indirect=True)
-
- def pytest_funcarg__arg1(request):
- return request.param
-
- def pytest_funcarg__arg2(request, arg1):
- return 10 * arg1
-
- def test_func(arg2):
- assert arg2 == 10
- """)
- result = testdir.runpytest("-v", p)
- result.stdout.fnmatch_lines([
- "*test_func*1*PASS*",
- "*1 passed*"
- ])
-
- def test_parametrize_with_ids(self, testdir):
- testdir.makepyfile("""
- import pytest
- def pytest_generate_tests(metafunc):
- metafunc.parametrize(("a", "b"), [(1,1), (1,2)],
- ids=["basic", "advanced"])
-
- def test_function(a, b):
- assert a == b
- """)
- result = testdir.runpytest("-v")
- assert result.ret == 1
- result.stdout.fnmatch_lines_random([
- "*test_function*basic*PASSED",
- "*test_function*advanced*FAILED",
- ])
-
- def test_parametrize_without_ids(self, testdir):
- testdir.makepyfile("""
- import pytest
- def pytest_generate_tests(metafunc):
- metafunc.parametrize(("a", "b"),
- [(1,object()), (1.3,object())])
-
- def test_function(a, b):
- assert 1
- """)
- result = testdir.runpytest("-v")
- result.stdout.fnmatch_lines("""
- *test_function*1-b0*
- *test_function*1.3-b1*
- """)
-
- @pytest.mark.parametrize(("scope", "length"),
- [("module", 2), ("function", 4)])
- def test_parametrize_scope_overrides(self, testdir, scope, length):
- testdir.makepyfile("""
- import pytest
- l = []
- def pytest_generate_tests(metafunc):
- if "arg" in metafunc.funcargnames:
- metafunc.parametrize("arg", [1,2], indirect=True,
- scope=%r)
- def pytest_funcarg__arg(request):
- l.append(request.param)
- return request.param
- def test_hello(arg):
- assert arg in (1,2)
- def test_world(arg):
- assert arg in (1,2)
- def test_checklength():
- assert len(l) == %d
- """ % (scope, length))
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=5)
-
- def test_parametrize_issue323(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- @pytest.fixture(scope='module', params=range(966))
- def foo(request):
- return request.param
-
- def test_it(foo):
- pass
- def test_it2(foo):
- pass
- """)
- reprec = testdir.inline_run("--collect-only")
- assert not reprec.getcalls("pytest_internalerror")
-
- def test_usefixtures_seen_in_generate_tests(self, testdir):
- testdir.makepyfile("""
- import pytest
- def pytest_generate_tests(metafunc):
- assert "abc" in metafunc.fixturenames
- metafunc.parametrize("abc", [1])
-
- @pytest.mark.usefixtures("abc")
- def test_function():
- pass
- """)
- reprec = testdir.runpytest()
- reprec.assert_outcomes(passed=1)
-
- def test_generate_tests_only_done_in_subdir(self, testdir):
- sub1 = testdir.mkpydir("sub1")
- sub2 = testdir.mkpydir("sub2")
- sub1.join("conftest.py").write(_pytest._code.Source("""
- def pytest_generate_tests(metafunc):
- assert metafunc.function.__name__ == "test_1"
- """))
- sub2.join("conftest.py").write(_pytest._code.Source("""
- def pytest_generate_tests(metafunc):
- assert metafunc.function.__name__ == "test_2"
- """))
- sub1.join("test_in_sub1.py").write("def test_1(): pass")
- sub2.join("test_in_sub2.py").write("def test_2(): pass")
- result = testdir.runpytest("-v", "-s", sub1, sub2, sub1)
- result.assert_outcomes(passed=3)
-
- def test_generate_same_function_names_issue403(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- def make_tests():
- @pytest.mark.parametrize("x", range(2))
- def test_foo(x):
- pass
- return test_foo
-
- test_x = make_tests()
- test_y = make_tests()
- """)
- reprec = testdir.runpytest()
- reprec.assert_outcomes(passed=4)
-
- @pytest.mark.issue463
- @pytest.mark.parametrize('attr', ['parametrise', 'parameterize',
- 'parameterise'])
- def test_parametrize_misspelling(self, testdir, attr):
- testdir.makepyfile("""
- import pytest
-
- @pytest.mark.{0}("x", range(2))
- def test_foo(x):
- pass
- """.format(attr))
- reprec = testdir.inline_run('--collectonly')
- failures = reprec.getfailures()
- assert len(failures) == 1
- expectederror = "MarkerError: test_foo has '{0}', spelling should be 'parametrize'".format(attr)
- assert expectederror in failures[0].longrepr.reprcrash.message
-
-
-class TestMarkersWithParametrization:
- pytestmark = pytest.mark.issue308
- def test_simple_mark(self, testdir):
- s = """
- import pytest
-
- @pytest.mark.foo
- @pytest.mark.parametrize(("n", "expected"), [
- (1, 2),
- pytest.mark.bar((1, 3)),
- (2, 3),
- ])
- def test_increment(n, expected):
- assert n + 1 == expected
- """
- items = testdir.getitems(s)
- assert len(items) == 3
- for item in items:
- assert 'foo' in item.keywords
- assert 'bar' not in items[0].keywords
- assert 'bar' in items[1].keywords
- assert 'bar' not in items[2].keywords
-
- def test_select_based_on_mark(self, testdir):
- s = """
- import pytest
-
- @pytest.mark.parametrize(("n", "expected"), [
- (1, 2),
- pytest.mark.foo((2, 3)),
- (3, 4),
- ])
- def test_increment(n, expected):
- assert n + 1 == expected
- """
- testdir.makepyfile(s)
- rec = testdir.inline_run("-m", 'foo')
- passed, skipped, fail = rec.listoutcomes()
- assert len(passed) == 1
- assert len(skipped) == 0
- assert len(fail) == 0
-
- @pytest.mark.xfail(reason="is this important to support??")
- def test_nested_marks(self, testdir):
- s = """
- import pytest
- mastermark = pytest.mark.foo(pytest.mark.bar)
-
- @pytest.mark.parametrize(("n", "expected"), [
- (1, 2),
- mastermark((1, 3)),
- (2, 3),
- ])
- def test_increment(n, expected):
- assert n + 1 == expected
- """
- items = testdir.getitems(s)
- assert len(items) == 3
- for mark in ['foo', 'bar']:
- assert mark not in items[0].keywords
- assert mark in items[1].keywords
- assert mark not in items[2].keywords
-
- def test_simple_xfail(self, testdir):
- s = """
- import pytest
-
- @pytest.mark.parametrize(("n", "expected"), [
- (1, 2),
- pytest.mark.xfail((1, 3)),
- (2, 3),
- ])
- def test_increment(n, expected):
- assert n + 1 == expected
- """
- testdir.makepyfile(s)
- reprec = testdir.inline_run()
- # xfail is skip??
- reprec.assertoutcome(passed=2, skipped=1)
-
- def test_simple_xfail_single_argname(self, testdir):
- s = """
- import pytest
-
- @pytest.mark.parametrize("n", [
- 2,
- pytest.mark.xfail(3),
- 4,
- ])
- def test_isEven(n):
- assert n % 2 == 0
- """
- testdir.makepyfile(s)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=2, skipped=1)
-
- def test_xfail_with_arg(self, testdir):
- s = """
- import pytest
-
- @pytest.mark.parametrize(("n", "expected"), [
- (1, 2),
- pytest.mark.xfail("True")((1, 3)),
- (2, 3),
- ])
- def test_increment(n, expected):
- assert n + 1 == expected
- """
- testdir.makepyfile(s)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=2, skipped=1)
-
- def test_xfail_with_kwarg(self, testdir):
- s = """
- import pytest
-
- @pytest.mark.parametrize(("n", "expected"), [
- (1, 2),
- pytest.mark.xfail(reason="some bug")((1, 3)),
- (2, 3),
- ])
- def test_increment(n, expected):
- assert n + 1 == expected
- """
- testdir.makepyfile(s)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=2, skipped=1)
-
- def test_xfail_with_arg_and_kwarg(self, testdir):
- s = """
- import pytest
-
- @pytest.mark.parametrize(("n", "expected"), [
- (1, 2),
- pytest.mark.xfail("True", reason="some bug")((1, 3)),
- (2, 3),
- ])
- def test_increment(n, expected):
- assert n + 1 == expected
- """
- testdir.makepyfile(s)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=2, skipped=1)
-
- def test_xfail_passing_is_xpass(self, testdir):
- s = """
- import pytest
-
- @pytest.mark.parametrize(("n", "expected"), [
- (1, 2),
- pytest.mark.xfail("sys.version > 0", reason="some bug")((2, 3)),
- (3, 4),
- ])
- def test_increment(n, expected):
- assert n + 1 == expected
- """
- testdir.makepyfile(s)
- reprec = testdir.inline_run()
- # xpass is fail, obviously :)
- reprec.assertoutcome(passed=2, failed=1)
-
- def test_parametrize_called_in_generate_tests(self, testdir):
- s = """
- import pytest
-
-
- def pytest_generate_tests(metafunc):
- passingTestData = [(1, 2),
- (2, 3)]
- failingTestData = [(1, 3),
- (2, 2)]
-
- testData = passingTestData + [pytest.mark.xfail(d)
- for d in failingTestData]
- metafunc.parametrize(("n", "expected"), testData)
-
-
- def test_increment(n, expected):
- assert n + 1 == expected
- """
- testdir.makepyfile(s)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=2, skipped=2)
-
-
- @pytest.mark.issue290
- def test_parametrize_ID_generation_string_int_works(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- @pytest.fixture
- def myfixture():
- return 'example'
- @pytest.mark.parametrize(
- 'limit', (0, '0'))
- def test_limit(limit, myfixture):
- return
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=2)
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/python/raises.py b/tests/wpt/web-platform-tests/tools/pytest/testing/python/raises.py
deleted file mode 100644
index 0ea7f9bee3e..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/python/raises.py
+++ /dev/null
@@ -1,78 +0,0 @@
-import pytest
-
-class TestRaises:
- def test_raises(self):
- source = "int('qwe')"
- excinfo = pytest.raises(ValueError, source)
- code = excinfo.traceback[-1].frame.code
- s = str(code.fullsource)
- assert s == source
-
- def test_raises_exec(self):
- pytest.raises(ValueError, "a,x = []")
-
- def test_raises_syntax_error(self):
- pytest.raises(SyntaxError, "qwe qwe qwe")
-
- def test_raises_function(self):
- pytest.raises(ValueError, int, 'hello')
-
- def test_raises_callable_no_exception(self):
- class A:
- def __call__(self):
- pass
- try:
- pytest.raises(ValueError, A())
- except pytest.raises.Exception:
- pass
-
- def test_raises_flip_builtin_AssertionError(self):
- # we replace AssertionError on python level
- # however c code might still raise the builtin one
- from _pytest.assertion.util import BuiltinAssertionError # noqa
- pytest.raises(AssertionError,"""
- raise BuiltinAssertionError
- """)
-
- def test_raises_as_contextmanager(self, testdir):
- testdir.makepyfile("""
- from __future__ import with_statement
- import py, pytest
- import _pytest._code
-
- def test_simple():
- with pytest.raises(ZeroDivisionError) as excinfo:
- assert isinstance(excinfo, _pytest._code.ExceptionInfo)
- 1/0
- print (excinfo)
- assert excinfo.type == ZeroDivisionError
- assert isinstance(excinfo.value, ZeroDivisionError)
-
- def test_noraise():
- with pytest.raises(pytest.raises.Exception):
- with pytest.raises(ValueError):
- int()
-
- def test_raise_wrong_exception_passes_by():
- with pytest.raises(ZeroDivisionError):
- with pytest.raises(ValueError):
- 1/0
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- '*3 passed*',
- ])
-
- def test_noclass(self):
- with pytest.raises(TypeError):
- pytest.raises('wrong', lambda: None)
-
- def test_tuple(self):
- with pytest.raises((KeyError, ValueError)):
- raise KeyError('oops')
-
- def test_no_raise_message(self):
- try:
- pytest.raises(ValueError, int, '0')
- except pytest.raises.Exception as e:
- assert e.msg == "DID NOT RAISE {0}".format(repr(ValueError))
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_argcomplete.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_argcomplete.py
deleted file mode 100644
index ace7d8ceb43..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_argcomplete.py
+++ /dev/null
@@ -1,90 +0,0 @@
-from __future__ import with_statement
-import py, pytest
-
-# test for _argcomplete but not specific for any application
-
-def equal_with_bash(prefix, ffc, fc, out=None):
- res = ffc(prefix)
- res_bash = set(fc(prefix))
- retval = set(res) == res_bash
- if out:
- out.write('equal_with_bash %s %s\n' % (retval, res))
- if not retval:
- out.write(' python - bash: %s\n' % (set(res) - res_bash))
- out.write(' bash - python: %s\n' % (res_bash - set(res)))
- return retval
-
-# copied from argcomplete.completers as import from there
-# also pulls in argcomplete.__init__ which opens filedescriptor 9
-# this gives an IOError at the end of testrun
-def _wrapcall(*args, **kargs):
- try:
- if py.std.sys.version_info > (2,7):
- return py.std.subprocess.check_output(*args,**kargs).decode().splitlines()
- if 'stdout' in kargs:
- raise ValueError('stdout argument not allowed, it will be overridden.')
- process = py.std.subprocess.Popen(
- stdout=py.std.subprocess.PIPE, *args, **kargs)
- output, unused_err = process.communicate()
- retcode = process.poll()
- if retcode:
- cmd = kargs.get("args")
- if cmd is None:
- cmd = args[0]
- raise py.std.subprocess.CalledProcessError(retcode, cmd)
- return output.decode().splitlines()
- except py.std.subprocess.CalledProcessError:
- return []
-
-class FilesCompleter(object):
- 'File completer class, optionally takes a list of allowed extensions'
- def __init__(self,allowednames=(),directories=True):
- # Fix if someone passes in a string instead of a list
- if type(allowednames) is str:
- allowednames = [allowednames]
-
- self.allowednames = [x.lstrip('*').lstrip('.') for x in allowednames]
- self.directories = directories
-
- def __call__(self, prefix, **kwargs):
- completion = []
- if self.allowednames:
- if self.directories:
- files = _wrapcall(['bash','-c',
- "compgen -A directory -- '{p}'".format(p=prefix)])
- completion += [ f + '/' for f in files]
- for x in self.allowednames:
- completion += _wrapcall(['bash', '-c',
- "compgen -A file -X '!*.{0}' -- '{p}'".format(x,p=prefix)])
- else:
- completion += _wrapcall(['bash', '-c',
- "compgen -A file -- '{p}'".format(p=prefix)])
-
- anticomp = _wrapcall(['bash', '-c',
- "compgen -A directory -- '{p}'".format(p=prefix)])
-
- completion = list( set(completion) - set(anticomp))
-
- if self.directories:
- completion += [f + '/' for f in anticomp]
- return completion
-
-class TestArgComplete:
- @pytest.mark.skipif("sys.platform in ('win32', 'darwin')")
- def test_compare_with_compgen(self):
- from _pytest._argcomplete import FastFilesCompleter
- ffc = FastFilesCompleter()
- fc = FilesCompleter()
- for x in '/ /d /data qqq'.split():
- assert equal_with_bash(x, ffc, fc, out=py.std.sys.stdout)
-
- @pytest.mark.skipif("sys.platform in ('win32', 'darwin')")
- def test_remove_dir_prefix(self):
- """this is not compatible with compgen but it is with bash itself:
- ls /usr/<TAB>
- """
- from _pytest._argcomplete import FastFilesCompleter
- ffc = FastFilesCompleter()
- fc = FilesCompleter()
- for x in '/usr/'.split():
- assert not equal_with_bash(x, ffc, fc, out=py.std.sys.stdout)
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_assertinterpret.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_assertinterpret.py
deleted file mode 100644
index 67a352ce7f5..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_assertinterpret.py
+++ /dev/null
@@ -1,274 +0,0 @@
-"PYTEST_DONT_REWRITE"
-import py
-import pytest
-from _pytest.assertion import util
-
-
-def exvalue():
- return py.std.sys.exc_info()[1]
-
-def f():
- return 2
-
-def test_not_being_rewritten():
- assert "@py_builtins" not in globals()
-
-def test_assert():
- try:
- assert f() == 3
- except AssertionError:
- e = exvalue()
- s = str(e)
- assert s.startswith('assert 2 == 3\n')
-
-def test_assert_with_explicit_message():
- try:
- assert f() == 3, "hello"
- except AssertionError:
- e = exvalue()
- assert e.msg == 'hello'
-
-def test_assert_within_finally():
- excinfo = pytest.raises(ZeroDivisionError, """
- try:
- 1/0
- finally:
- i = 42
- """)
- s = excinfo.exconly()
- assert py.std.re.search("division.+by zero", s) is not None
-
- #def g():
- # A.f()
- #excinfo = getexcinfo(TypeError, g)
- #msg = getmsg(excinfo)
- #assert msg.find("must be called with A") != -1
-
-
-def test_assert_multiline_1():
- try:
- assert (f() ==
- 3)
- except AssertionError:
- e = exvalue()
- s = str(e)
- assert s.startswith('assert 2 == 3\n')
-
-def test_assert_multiline_2():
- try:
- assert (f() == (4,
- 3)[-1])
- except AssertionError:
- e = exvalue()
- s = str(e)
- assert s.startswith('assert 2 ==')
-
-def test_in():
- try:
- assert "hi" in [1, 2]
- except AssertionError:
- e = exvalue()
- s = str(e)
- assert s.startswith("assert 'hi' in")
-
-def test_is():
- try:
- assert 1 is 2
- except AssertionError:
- e = exvalue()
- s = str(e)
- assert s.startswith("assert 1 is 2")
-
-
-def test_attrib():
- class Foo(object):
- b = 1
- i = Foo()
- try:
- assert i.b == 2
- except AssertionError:
- e = exvalue()
- s = str(e)
- assert s.startswith("assert 1 == 2")
-
-def test_attrib_inst():
- class Foo(object):
- b = 1
- try:
- assert Foo().b == 2
- except AssertionError:
- e = exvalue()
- s = str(e)
- assert s.startswith("assert 1 == 2")
-
-def test_len():
- l = list(range(42))
- try:
- assert len(l) == 100
- except AssertionError:
- e = exvalue()
- s = str(e)
- assert s.startswith("assert 42 == 100")
- assert "where 42 = len([" in s
-
-def test_assert_non_string_message():
- class A:
- def __str__(self):
- return "hello"
- try:
- assert 0 == 1, A()
- except AssertionError:
- e = exvalue()
- assert e.msg == "hello"
-
-def test_assert_keyword_arg():
- def f(x=3):
- return False
- try:
- assert f(x=5)
- except AssertionError:
- e = exvalue()
- assert "x=5" in e.msg
-
-def test_private_class_variable():
- class X:
- def __init__(self):
- self.__v = 41
- def m(self):
- assert self.__v == 42
- try:
- X().m()
- except AssertionError:
- e = exvalue()
- assert "== 42" in e.msg
-
-# These tests should both fail, but should fail nicely...
-class WeirdRepr:
- def __repr__(self):
- return '<WeirdRepr\nsecond line>'
-
-def bug_test_assert_repr():
- v = WeirdRepr()
- try:
- assert v == 1
- except AssertionError:
- e = exvalue()
- assert e.msg.find('WeirdRepr') != -1
- assert e.msg.find('second line') != -1
- assert 0
-
-def test_assert_non_string():
- try:
- assert 0, ['list']
- except AssertionError:
- e = exvalue()
- assert e.msg.find("list") != -1
-
-def test_assert_implicit_multiline():
- try:
- x = [1,2,3]
- assert x != [1,
- 2, 3]
- except AssertionError:
- e = exvalue()
- assert e.msg.find('assert [1, 2, 3] !=') != -1
-
-
-def test_assert_with_brokenrepr_arg():
- class BrokenRepr:
- def __repr__(self): 0 / 0
- e = AssertionError(BrokenRepr())
- if e.msg.find("broken __repr__") == -1:
- pytest.fail("broken __repr__ not handle correctly")
-
-def test_multiple_statements_per_line():
- try:
- a = 1; assert a == 2
- except AssertionError:
- e = exvalue()
- assert "assert 1 == 2" in e.msg
-
-def test_power():
- try:
- assert 2**3 == 7
- except AssertionError:
- e = exvalue()
- assert "assert (2 ** 3) == 7" in e.msg
-
-
-def test_assert_customizable_reprcompare(monkeypatch):
- monkeypatch.setattr(util, '_reprcompare', lambda *args: 'hello')
- try:
- assert 3 == 4
- except AssertionError:
- e = exvalue()
- s = str(e)
- assert "hello" in s
-
-def test_assert_long_source_1():
- try:
- assert len == [
- (None, ['somet text', 'more text']),
- ]
- except AssertionError:
- e = exvalue()
- s = str(e)
- assert 're-run' not in s
- assert 'somet text' in s
-
-def test_assert_long_source_2():
- try:
- assert(len == [
- (None, ['somet text', 'more text']),
- ])
- except AssertionError:
- e = exvalue()
- s = str(e)
- assert 're-run' not in s
- assert 'somet text' in s
-
-def test_assert_raise_alias(testdir):
- testdir.makepyfile("""
- "PYTEST_DONT_REWRITE"
- import sys
- EX = AssertionError
- def test_hello():
- raise EX("hello"
- "multi"
- "line")
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*def test_hello*",
- "*raise EX*",
- "*1 failed*",
- ])
-
-
-def test_assert_raise_subclass():
- class SomeEx(AssertionError):
- def __init__(self, *args):
- super(SomeEx, self).__init__()
- try:
- raise SomeEx("hello")
- except AssertionError:
- s = str(exvalue())
- assert 're-run' not in s
- assert 'could not determine' in s
-
-def test_assert_raises_in_nonzero_of_object_pytest_issue10():
- class A(object):
- def __nonzero__(self):
- raise ValueError(42)
- def __lt__(self, other):
- return A()
- def __repr__(self):
- return "<MY42 object>"
- def myany(x):
- return True
- try:
- assert not(myany(A() < 0))
- except AssertionError:
- e = exvalue()
- s = str(e)
- assert "<MY42 object> < 0" in s
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_assertion.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_assertion.py
deleted file mode 100644
index 347278e1904..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_assertion.py
+++ /dev/null
@@ -1,628 +0,0 @@
-# -*- coding: utf-8 -*-
-import sys
-import textwrap
-
-import _pytest.assertion as plugin
-import _pytest._code
-import py
-import pytest
-from _pytest.assertion import reinterpret
-from _pytest.assertion import util
-
-PY3 = sys.version_info >= (3, 0)
-
-
-@pytest.fixture
-def mock_config():
- class Config(object):
- verbose = False
- def getoption(self, name):
- if name == 'verbose':
- return self.verbose
- raise KeyError('Not mocked out: %s' % name)
- return Config()
-
-
-def interpret(expr):
- return reinterpret.reinterpret(expr, _pytest._code.Frame(sys._getframe(1)))
-
-class TestBinReprIntegration:
-
- def test_pytest_assertrepr_compare_called(self, testdir):
- testdir.makeconftest("""
- l = []
- def pytest_assertrepr_compare(op, left, right):
- l.append((op, left, right))
- def pytest_funcarg__l(request):
- return l
- """)
- testdir.makepyfile("""
- def test_hello():
- assert 0 == 1
- def test_check(l):
- assert l == [("==", 0, 1)]
- """)
- result = testdir.runpytest("-v")
- result.stdout.fnmatch_lines([
- "*test_hello*FAIL*",
- "*test_check*PASS*",
- ])
-
-def callequal(left, right, verbose=False):
- config = mock_config()
- config.verbose = verbose
- return plugin.pytest_assertrepr_compare(config, '==', left, right)
-
-
-class TestAssert_reprcompare:
- def test_different_types(self):
- assert callequal([0, 1], 'foo') is None
-
- def test_summary(self):
- summary = callequal([0, 1], [0, 2])[0]
- assert len(summary) < 65
-
- def test_text_diff(self):
- diff = callequal('spam', 'eggs')[1:]
- assert '- spam' in diff
- assert '+ eggs' in diff
-
- def test_text_skipping(self):
- lines = callequal('a'*50 + 'spam', 'a'*50 + 'eggs')
- assert 'Skipping' in lines[1]
- for line in lines:
- assert 'a'*50 not in line
-
- def test_text_skipping_verbose(self):
- lines = callequal('a'*50 + 'spam', 'a'*50 + 'eggs', verbose=True)
- assert '- ' + 'a'*50 + 'spam' in lines
- assert '+ ' + 'a'*50 + 'eggs' in lines
-
- def test_multiline_text_diff(self):
- left = 'foo\nspam\nbar'
- right = 'foo\neggs\nbar'
- diff = callequal(left, right)
- assert '- spam' in diff
- assert '+ eggs' in diff
-
- def test_list(self):
- expl = callequal([0, 1], [0, 2])
- assert len(expl) > 1
-
- @pytest.mark.parametrize(
- ['left', 'right', 'expected'], [
- ([0, 1], [0, 2], """
- Full diff:
- - [0, 1]
- ? ^
- + [0, 2]
- ? ^
- """),
- ({0: 1}, {0: 2}, """
- Full diff:
- - {0: 1}
- ? ^
- + {0: 2}
- ? ^
- """),
- (set([0, 1]), set([0, 2]), """
- Full diff:
- - set([0, 1])
- ? ^
- + set([0, 2])
- ? ^
- """ if not PY3 else """
- Full diff:
- - {0, 1}
- ? ^
- + {0, 2}
- ? ^
- """)
- ]
- )
- def test_iterable_full_diff(self, left, right, expected):
- """Test the full diff assertion failure explanation.
-
- When verbose is False, then just a -v notice to get the diff is rendered,
- when verbose is True, then ndiff of the pprint is returned.
- """
- expl = callequal(left, right, verbose=False)
- assert expl[-1] == 'Use -v to get the full diff'
- expl = '\n'.join(callequal(left, right, verbose=True))
- assert expl.endswith(textwrap.dedent(expected).strip())
-
- def test_list_different_lenghts(self):
- expl = callequal([0, 1], [0, 1, 2])
- assert len(expl) > 1
- expl = callequal([0, 1, 2], [0, 1])
- assert len(expl) > 1
-
- def test_dict(self):
- expl = callequal({'a': 0}, {'a': 1})
- assert len(expl) > 1
-
- def test_dict_omitting(self):
- lines = callequal({'a': 0, 'b': 1}, {'a': 1, 'b': 1})
- assert lines[1].startswith('Omitting 1 identical item')
- assert 'Common items' not in lines
- for line in lines[1:]:
- assert 'b' not in line
-
- def test_dict_omitting_verbose(self):
- lines = callequal({'a': 0, 'b': 1}, {'a': 1, 'b': 1}, verbose=True)
- assert lines[1].startswith('Common items:')
- assert 'Omitting' not in lines[1]
- assert lines[2] == "{'b': 1}"
-
- def test_set(self):
- expl = callequal(set([0, 1]), set([0, 2]))
- assert len(expl) > 1
-
- def test_frozenzet(self):
- expl = callequal(frozenset([0, 1]), set([0, 2]))
- assert len(expl) > 1
-
- def test_Sequence(self):
- col = py.builtin._tryimport(
- "collections.abc",
- "collections",
- "sys")
- if not hasattr(col, "MutableSequence"):
- pytest.skip("cannot import MutableSequence")
- MutableSequence = col.MutableSequence
-
- class TestSequence(MutableSequence): # works with a Sequence subclass
- def __init__(self, iterable):
- self.elements = list(iterable)
-
- def __getitem__(self, item):
- return self.elements[item]
-
- def __len__(self):
- return len(self.elements)
-
- def __setitem__(self, item, value):
- pass
-
- def __delitem__(self, item):
- pass
-
- def insert(self, item, index):
- pass
-
- expl = callequal(TestSequence([0, 1]), list([0, 2]))
- assert len(expl) > 1
-
- def test_list_tuples(self):
- expl = callequal([], [(1,2)])
- assert len(expl) > 1
- expl = callequal([(1,2)], [])
- assert len(expl) > 1
-
- def test_list_bad_repr(self):
- class A:
- def __repr__(self):
- raise ValueError(42)
- expl = callequal([], [A()])
- assert 'ValueError' in "".join(expl)
- expl = callequal({}, {'1': A()})
- assert 'faulty' in "".join(expl)
-
- def test_one_repr_empty(self):
- """
- the faulty empty string repr did trigger
- a unbound local error in _diff_text
- """
- class A(str):
- def __repr__(self):
- return ''
- expl = callequal(A(), '')
- assert not expl
-
- def test_repr_no_exc(self):
- expl = ' '.join(callequal('foo', 'bar'))
- assert 'raised in repr()' not in expl
-
- def test_unicode(self):
- left = py.builtin._totext('£€', 'utf-8')
- right = py.builtin._totext('£', 'utf-8')
- expl = callequal(left, right)
- assert expl[0] == py.builtin._totext("'£€' == '£'", 'utf-8')
- assert expl[1] == py.builtin._totext('- £€', 'utf-8')
- assert expl[2] == py.builtin._totext('+ £', 'utf-8')
-
- def test_nonascii_text(self):
- """
- :issue: 877
- non ascii python2 str caused a UnicodeDecodeError
- """
- class A(str):
- def __repr__(self):
- return '\xff'
- expl = callequal(A(), '1')
- assert expl
-
- def test_format_nonascii_explanation(self):
- assert util.format_explanation('λ')
-
- def test_mojibake(self):
- # issue 429
- left = 'e'
- right = '\xc3\xa9'
- if not isinstance(left, py.builtin.bytes):
- left = py.builtin.bytes(left, 'utf-8')
- right = py.builtin.bytes(right, 'utf-8')
- expl = callequal(left, right)
- for line in expl:
- assert isinstance(line, py.builtin.text)
- msg = py.builtin._totext('\n').join(expl)
- assert msg
-
-
-class TestFormatExplanation:
-
- def test_special_chars_full(self, testdir):
- # Issue 453, for the bug this would raise IndexError
- testdir.makepyfile("""
- def test_foo():
- assert '\\n}' == ''
- """)
- result = testdir.runpytest()
- assert result.ret == 1
- result.stdout.fnmatch_lines([
- "*AssertionError*",
- ])
-
- def test_fmt_simple(self):
- expl = 'assert foo'
- assert util.format_explanation(expl) == 'assert foo'
-
- def test_fmt_where(self):
- expl = '\n'.join(['assert 1',
- '{1 = foo',
- '} == 2'])
- res = '\n'.join(['assert 1 == 2',
- ' + where 1 = foo'])
- assert util.format_explanation(expl) == res
-
- def test_fmt_and(self):
- expl = '\n'.join(['assert 1',
- '{1 = foo',
- '} == 2',
- '{2 = bar',
- '}'])
- res = '\n'.join(['assert 1 == 2',
- ' + where 1 = foo',
- ' + and 2 = bar'])
- assert util.format_explanation(expl) == res
-
- def test_fmt_where_nested(self):
- expl = '\n'.join(['assert 1',
- '{1 = foo',
- '{foo = bar',
- '}',
- '} == 2'])
- res = '\n'.join(['assert 1 == 2',
- ' + where 1 = foo',
- ' + where foo = bar'])
- assert util.format_explanation(expl) == res
-
- def test_fmt_newline(self):
- expl = '\n'.join(['assert "foo" == "bar"',
- '~- foo',
- '~+ bar'])
- res = '\n'.join(['assert "foo" == "bar"',
- ' - foo',
- ' + bar'])
- assert util.format_explanation(expl) == res
-
- def test_fmt_newline_escaped(self):
- expl = '\n'.join(['assert foo == bar',
- 'baz'])
- res = 'assert foo == bar\\nbaz'
- assert util.format_explanation(expl) == res
-
- def test_fmt_newline_before_where(self):
- expl = '\n'.join(['the assertion message here',
- '>assert 1',
- '{1 = foo',
- '} == 2',
- '{2 = bar',
- '}'])
- res = '\n'.join(['the assertion message here',
- 'assert 1 == 2',
- ' + where 1 = foo',
- ' + and 2 = bar'])
- assert util.format_explanation(expl) == res
-
- def test_fmt_multi_newline_before_where(self):
- expl = '\n'.join(['the assertion',
- '~message here',
- '>assert 1',
- '{1 = foo',
- '} == 2',
- '{2 = bar',
- '}'])
- res = '\n'.join(['the assertion',
- ' message here',
- 'assert 1 == 2',
- ' + where 1 = foo',
- ' + and 2 = bar'])
- assert util.format_explanation(expl) == res
-
-
-def test_python25_compile_issue257(testdir):
- testdir.makepyfile("""
- def test_rewritten():
- assert 1 == 2
- # some comment
- """)
- result = testdir.runpytest()
- assert result.ret == 1
- result.stdout.fnmatch_lines("""
- *E*assert 1 == 2*
- *1 failed*
- """)
-
-def test_rewritten(testdir):
- testdir.makepyfile("""
- def test_rewritten():
- assert "@py_builtins" in globals()
- """)
- assert testdir.runpytest().ret == 0
-
-def test_reprcompare_notin(mock_config):
- detail = plugin.pytest_assertrepr_compare(
- mock_config, 'not in', 'foo', 'aaafoobbb')[1:]
- assert detail == ["'foo' is contained here:", ' aaafoobbb', '? +++']
-
-def test_pytest_assertrepr_compare_integration(testdir):
- testdir.makepyfile("""
- def test_hello():
- x = set(range(100))
- y = x.copy()
- y.remove(50)
- assert x == y
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*def test_hello():*",
- "*assert x == y*",
- "*E*Extra items*left*",
- "*E*50*",
- ])
-
-def test_sequence_comparison_uses_repr(testdir):
- testdir.makepyfile("""
- def test_hello():
- x = set("hello x")
- y = set("hello y")
- assert x == y
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*def test_hello():*",
- "*assert x == y*",
- "*E*Extra items*left*",
- "*E*'x'*",
- "*E*Extra items*right*",
- "*E*'y'*",
- ])
-
-
-def test_assert_compare_truncate_longmessage(monkeypatch, testdir):
- testdir.makepyfile(r"""
- def test_long():
- a = list(range(200))
- b = a[::2]
- a = '\n'.join(map(str, a))
- b = '\n'.join(map(str, b))
- assert a == b
- """)
- monkeypatch.delenv('CI', raising=False)
-
- result = testdir.runpytest()
- # without -vv, truncate the message showing a few diff lines only
- result.stdout.fnmatch_lines([
- "*- 1",
- "*- 3",
- "*- 5",
- "*- 7",
- "*truncated (191 more lines)*use*-vv*",
- ])
-
-
- result = testdir.runpytest('-vv')
- result.stdout.fnmatch_lines([
- "*- 197",
- ])
-
- monkeypatch.setenv('CI', '1')
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*- 197",
- ])
-
-
-def test_assertrepr_loaded_per_dir(testdir):
- testdir.makepyfile(test_base=['def test_base(): assert 1 == 2'])
- a = testdir.mkdir('a')
- a_test = a.join('test_a.py')
- a_test.write('def test_a(): assert 1 == 2')
- a_conftest = a.join('conftest.py')
- a_conftest.write('def pytest_assertrepr_compare(): return ["summary a"]')
- b = testdir.mkdir('b')
- b_test = b.join('test_b.py')
- b_test.write('def test_b(): assert 1 == 2')
- b_conftest = b.join('conftest.py')
- b_conftest.write('def pytest_assertrepr_compare(): return ["summary b"]')
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- '*def test_base():*',
- '*E*assert 1 == 2*',
- '*def test_a():*',
- '*E*assert summary a*',
- '*def test_b():*',
- '*E*assert summary b*'])
-
-
-def test_assertion_options(testdir):
- testdir.makepyfile("""
- def test_hello():
- x = 3
- assert x == 4
- """)
- result = testdir.runpytest()
- assert "3 == 4" in result.stdout.str()
- off_options = (("--no-assert",),
- ("--nomagic",),
- ("--no-assert", "--nomagic"),
- ("--assert=plain",),
- ("--assert=plain", "--no-assert"),
- ("--assert=plain", "--nomagic"),
- ("--assert=plain", "--no-assert", "--nomagic"))
- for opt in off_options:
- result = testdir.runpytest_subprocess(*opt)
- assert "3 == 4" not in result.stdout.str()
-
-def test_old_assert_mode(testdir):
- testdir.makepyfile("""
- def test_in_old_mode():
- assert "@py_builtins" not in globals()
- """)
- result = testdir.runpytest_subprocess("--assert=reinterp")
- assert result.ret == 0
-
-def test_triple_quoted_string_issue113(testdir):
- testdir.makepyfile("""
- def test_hello():
- assert "" == '''
- '''""")
- result = testdir.runpytest("--fulltrace")
- result.stdout.fnmatch_lines([
- "*1 failed*",
- ])
- assert 'SyntaxError' not in result.stdout.str()
-
-def test_traceback_failure(testdir):
- p1 = testdir.makepyfile("""
- def g():
- return 2
- def f(x):
- assert x == g()
- def test_onefails():
- f(3)
- """)
- result = testdir.runpytest(p1, "--tb=long")
- result.stdout.fnmatch_lines([
- "*test_traceback_failure.py F",
- "====* FAILURES *====",
- "____*____",
- "",
- " def test_onefails():",
- "> f(3)",
- "",
- "*test_*.py:6: ",
- "_ _ _ *",
- #"",
- " def f(x):",
- "> assert x == g()",
- "E assert 3 == 2",
- "E + where 2 = g()",
- "",
- "*test_traceback_failure.py:4: AssertionError"
- ])
-
- result = testdir.runpytest(p1) # "auto"
- result.stdout.fnmatch_lines([
- "*test_traceback_failure.py F",
- "====* FAILURES *====",
- "____*____",
- "",
- " def test_onefails():",
- "> f(3)",
- "",
- "*test_*.py:6: ",
- "",
- " def f(x):",
- "> assert x == g()",
- "E assert 3 == 2",
- "E + where 2 = g()",
- "",
- "*test_traceback_failure.py:4: AssertionError"
- ])
-
-@pytest.mark.skipif("'__pypy__' in sys.builtin_module_names or sys.platform.startswith('java')" )
-def test_warn_missing(testdir):
- testdir.makepyfile("")
- result = testdir.run(sys.executable, "-OO", "-m", "pytest", "-h")
- result.stderr.fnmatch_lines([
- "*WARNING*assert statements are not executed*",
- ])
- result = testdir.run(sys.executable, "-OO", "-m", "pytest", "--no-assert")
- result.stderr.fnmatch_lines([
- "*WARNING*assert statements are not executed*",
- ])
-
-def test_recursion_source_decode(testdir):
- testdir.makepyfile("""
- def test_something():
- pass
- """)
- testdir.makeini("""
- [pytest]
- python_files = *.py
- """)
- result = testdir.runpytest("--collect-only")
- result.stdout.fnmatch_lines("""
- <Module*>
- """)
-
-def test_AssertionError_message(testdir):
- testdir.makepyfile("""
- def test_hello():
- x,y = 1,2
- assert 0, (x,y)
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines("""
- *def test_hello*
- *assert 0, (x,y)*
- *AssertionError: (1, 2)*
- """)
-
-@pytest.mark.skipif(PY3, reason='This bug does not exist on PY3')
-def test_set_with_unsortable_elements():
- # issue #718
- class UnsortableKey(object):
- def __init__(self, name):
- self.name = name
-
- def __lt__(self, other):
- raise RuntimeError()
-
- def __repr__(self):
- return 'repr({0})'.format(self.name)
-
- def __eq__(self, other):
- return self.name == other.name
-
- def __hash__(self):
- return hash(self.name)
-
- left_set = set(UnsortableKey(str(i)) for i in range(1, 3))
- right_set = set(UnsortableKey(str(i)) for i in range(2, 4))
- expl = callequal(left_set, right_set, verbose=True)
- # skip first line because it contains the "construction" of the set, which does not have a guaranteed order
- expl = expl[1:]
- dedent = textwrap.dedent("""
- Extra items in the left set:
- repr(1)
- Extra items in the right set:
- repr(3)
- Full diff (fallback to calling repr on each item):
- - repr(1)
- repr(2)
- + repr(3)
- """).strip()
- assert '\n'.join(expl) == dedent
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_assertrewrite.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_assertrewrite.py
deleted file mode 100644
index f43c424ca94..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_assertrewrite.py
+++ /dev/null
@@ -1,716 +0,0 @@
-import os
-import stat
-import sys
-import zipfile
-import py
-import pytest
-
-ast = pytest.importorskip("ast")
-if sys.platform.startswith("java"):
- # XXX should be xfail
- pytest.skip("assert rewrite does currently not work on jython")
-
-import _pytest._code
-from _pytest.assertion import util
-from _pytest.assertion.rewrite import rewrite_asserts, PYTEST_TAG
-from _pytest.main import EXIT_NOTESTSCOLLECTED
-
-
-def setup_module(mod):
- mod._old_reprcompare = util._reprcompare
- _pytest._code._reprcompare = None
-
-def teardown_module(mod):
- util._reprcompare = mod._old_reprcompare
- del mod._old_reprcompare
-
-
-def rewrite(src):
- tree = ast.parse(src)
- rewrite_asserts(tree)
- return tree
-
-def getmsg(f, extra_ns=None, must_pass=False):
- """Rewrite the assertions in f, run it, and get the failure message."""
- src = '\n'.join(_pytest._code.Code(f).source().lines)
- mod = rewrite(src)
- code = compile(mod, "<test>", "exec")
- ns = {}
- if extra_ns is not None:
- ns.update(extra_ns)
- py.builtin.exec_(code, ns)
- func = ns[f.__name__]
- try:
- func()
- except AssertionError:
- if must_pass:
- pytest.fail("shouldn't have raised")
- s = str(sys.exc_info()[1])
- if not s.startswith("assert"):
- return "AssertionError: " + s
- return s
- else:
- if not must_pass:
- pytest.fail("function didn't raise at all")
-
-
-class TestAssertionRewrite:
-
- def test_place_initial_imports(self):
- s = """'Doc string'\nother = stuff"""
- m = rewrite(s)
- assert isinstance(m.body[0], ast.Expr)
- assert isinstance(m.body[0].value, ast.Str)
- for imp in m.body[1:3]:
- assert isinstance(imp, ast.Import)
- assert imp.lineno == 2
- assert imp.col_offset == 0
- assert isinstance(m.body[3], ast.Assign)
- s = """from __future__ import with_statement\nother_stuff"""
- m = rewrite(s)
- assert isinstance(m.body[0], ast.ImportFrom)
- for imp in m.body[1:3]:
- assert isinstance(imp, ast.Import)
- assert imp.lineno == 2
- assert imp.col_offset == 0
- assert isinstance(m.body[3], ast.Expr)
- s = """'doc string'\nfrom __future__ import with_statement\nother"""
- m = rewrite(s)
- assert isinstance(m.body[0], ast.Expr)
- assert isinstance(m.body[0].value, ast.Str)
- assert isinstance(m.body[1], ast.ImportFrom)
- for imp in m.body[2:4]:
- assert isinstance(imp, ast.Import)
- assert imp.lineno == 3
- assert imp.col_offset == 0
- assert isinstance(m.body[4], ast.Expr)
- s = """from . import relative\nother_stuff"""
- m = rewrite(s)
- for imp in m.body[0:2]:
- assert isinstance(imp, ast.Import)
- assert imp.lineno == 1
- assert imp.col_offset == 0
- assert isinstance(m.body[3], ast.Expr)
-
- def test_dont_rewrite(self):
- s = """'PYTEST_DONT_REWRITE'\nassert 14"""
- m = rewrite(s)
- assert len(m.body) == 2
- assert isinstance(m.body[0].value, ast.Str)
- assert isinstance(m.body[1], ast.Assert)
- assert m.body[1].msg is None
-
- def test_name(self):
- def f():
- assert False
- assert getmsg(f) == "assert False"
- def f():
- f = False
- assert f
- assert getmsg(f) == "assert False"
- def f():
- assert a_global # noqa
- assert getmsg(f, {"a_global" : False}) == "assert False"
- def f():
- assert sys == 42
- assert getmsg(f, {"sys" : sys}) == "assert sys == 42"
- def f():
- assert cls == 42 # noqa
- class X(object):
- pass
- assert getmsg(f, {"cls" : X}) == "assert cls == 42"
-
- def test_assert_already_has_message(self):
- def f():
- assert False, "something bad!"
- assert getmsg(f) == "AssertionError: something bad!\nassert False"
-
- def test_assertion_message(self, testdir):
- testdir.makepyfile("""
- def test_foo():
- assert 1 == 2, "The failure message"
- """)
- result = testdir.runpytest()
- assert result.ret == 1
- result.stdout.fnmatch_lines([
- "*AssertionError*The failure message*",
- "*assert 1 == 2*",
- ])
-
- def test_assertion_message_multiline(self, testdir):
- testdir.makepyfile("""
- def test_foo():
- assert 1 == 2, "A multiline\\nfailure message"
- """)
- result = testdir.runpytest()
- assert result.ret == 1
- result.stdout.fnmatch_lines([
- "*AssertionError*A multiline*",
- "*failure message*",
- "*assert 1 == 2*",
- ])
-
- def test_assertion_message_tuple(self, testdir):
- testdir.makepyfile("""
- def test_foo():
- assert 1 == 2, (1, 2)
- """)
- result = testdir.runpytest()
- assert result.ret == 1
- result.stdout.fnmatch_lines([
- "*AssertionError*%s*" % repr((1, 2)),
- "*assert 1 == 2*",
- ])
-
- def test_assertion_message_expr(self, testdir):
- testdir.makepyfile("""
- def test_foo():
- assert 1 == 2, 1 + 2
- """)
- result = testdir.runpytest()
- assert result.ret == 1
- result.stdout.fnmatch_lines([
- "*AssertionError*3*",
- "*assert 1 == 2*",
- ])
-
- def test_assertion_message_escape(self, testdir):
- testdir.makepyfile("""
- def test_foo():
- assert 1 == 2, 'To be escaped: %'
- """)
- result = testdir.runpytest()
- assert result.ret == 1
- result.stdout.fnmatch_lines([
- "*AssertionError: To be escaped: %",
- "*assert 1 == 2",
- ])
-
- def test_boolop(self):
- def f():
- f = g = False
- assert f and g
- assert getmsg(f) == "assert (False)"
- def f():
- f = True
- g = False
- assert f and g
- assert getmsg(f) == "assert (True and False)"
- def f():
- f = False
- g = True
- assert f and g
- assert getmsg(f) == "assert (False)"
- def f():
- f = g = False
- assert f or g
- assert getmsg(f) == "assert (False or False)"
- def f():
- f = g = False
- assert not f and not g
- getmsg(f, must_pass=True)
- def x():
- return False
- def f():
- assert x() and x()
- assert getmsg(f, {"x" : x}) == "assert (x())"
- def f():
- assert False or x()
- assert getmsg(f, {"x" : x}) == "assert (False or x())"
- def f():
- assert 1 in {} and 2 in {}
- assert getmsg(f) == "assert (1 in {})"
- def f():
- x = 1
- y = 2
- assert x in {1 : None} and y in {}
- assert getmsg(f) == "assert (1 in {1: None} and 2 in {})"
- def f():
- f = True
- g = False
- assert f or g
- getmsg(f, must_pass=True)
- def f():
- f = g = h = lambda: True
- assert f() and g() and h()
- getmsg(f, must_pass=True)
-
- def test_short_circut_evaluation(self):
- def f():
- assert True or explode # noqa
- getmsg(f, must_pass=True)
- def f():
- x = 1
- assert x == 1 or x == 2
- getmsg(f, must_pass=True)
-
- def test_unary_op(self):
- def f():
- x = True
- assert not x
- assert getmsg(f) == "assert not True"
- def f():
- x = 0
- assert ~x + 1
- assert getmsg(f) == "assert (~0 + 1)"
- def f():
- x = 3
- assert -x + x
- assert getmsg(f) == "assert (-3 + 3)"
- def f():
- x = 0
- assert +x + x
- assert getmsg(f) == "assert (+0 + 0)"
-
- def test_binary_op(self):
- def f():
- x = 1
- y = -1
- assert x + y
- assert getmsg(f) == "assert (1 + -1)"
- def f():
- assert not 5 % 4
- assert getmsg(f) == "assert not (5 % 4)"
-
- def test_boolop_percent(self):
- def f():
- assert 3 % 2 and False
- assert getmsg(f) == "assert ((3 % 2) and False)"
- def f():
- assert False or 4 % 2
- assert getmsg(f) == "assert (False or (4 % 2))"
-
- @pytest.mark.skipif("sys.version_info < (3,5)")
- def test_at_operator_issue1290(self, testdir):
- testdir.makepyfile("""
- class Matrix:
- def __init__(self, num):
- self.num = num
- def __matmul__(self, other):
- return self.num * other.num
-
- def test_multmat_operator():
- assert Matrix(2) @ Matrix(3) == 6""")
- testdir.runpytest().assert_outcomes(passed=1)
-
- def test_call(self):
- def g(a=42, *args, **kwargs):
- return False
- ns = {"g" : g}
- def f():
- assert g()
- assert getmsg(f, ns) == """assert g()"""
- def f():
- assert g(1)
- assert getmsg(f, ns) == """assert g(1)"""
- def f():
- assert g(1, 2)
- assert getmsg(f, ns) == """assert g(1, 2)"""
- def f():
- assert g(1, g=42)
- assert getmsg(f, ns) == """assert g(1, g=42)"""
- def f():
- assert g(1, 3, g=23)
- assert getmsg(f, ns) == """assert g(1, 3, g=23)"""
- def f():
- seq = [1, 2, 3]
- assert g(*seq)
- assert getmsg(f, ns) == """assert g(*[1, 2, 3])"""
- def f():
- x = "a"
- assert g(**{x : 2})
- assert getmsg(f, ns) == """assert g(**{'a': 2})"""
-
- def test_attribute(self):
- class X(object):
- g = 3
- ns = {"x" : X}
- def f():
- assert not x.g # noqa
- assert getmsg(f, ns) == """assert not 3
- + where 3 = x.g"""
- def f():
- x.a = False # noqa
- assert x.a # noqa
- assert getmsg(f, ns) == """assert x.a"""
-
- def test_comparisons(self):
- def f():
- a, b = range(2)
- assert b < a
- assert getmsg(f) == """assert 1 < 0"""
- def f():
- a, b, c = range(3)
- assert a > b > c
- assert getmsg(f) == """assert 0 > 1"""
- def f():
- a, b, c = range(3)
- assert a < b > c
- assert getmsg(f) == """assert 1 > 2"""
- def f():
- a, b, c = range(3)
- assert a < b <= c
- getmsg(f, must_pass=True)
- def f():
- a, b, c = range(3)
- assert a < b
- assert b < c
- getmsg(f, must_pass=True)
-
- def test_len(self):
- def f():
- l = list(range(10))
- assert len(l) == 11
- assert getmsg(f).startswith("""assert 10 == 11
- + where 10 = len([""")
-
- def test_custom_reprcompare(self, monkeypatch):
- def my_reprcompare(op, left, right):
- return "42"
- monkeypatch.setattr(util, "_reprcompare", my_reprcompare)
- def f():
- assert 42 < 3
- assert getmsg(f) == "assert 42"
- def my_reprcompare(op, left, right):
- return "%s %s %s" % (left, op, right)
- monkeypatch.setattr(util, "_reprcompare", my_reprcompare)
- def f():
- assert 1 < 3 < 5 <= 4 < 7
- assert getmsg(f) == "assert 5 <= 4"
-
- def test_assert_raising_nonzero_in_comparison(self):
- def f():
- class A(object):
- def __nonzero__(self):
- raise ValueError(42)
- def __lt__(self, other):
- return A()
- def __repr__(self):
- return "<MY42 object>"
- def myany(x):
- return False
- assert myany(A() < 0)
- assert "<MY42 object> < 0" in getmsg(f)
-
- def test_formatchar(self):
- def f():
- assert "%test" == "test"
- assert getmsg(f).startswith("assert '%test' == 'test'")
-
- def test_custom_repr(self):
- def f():
- class Foo(object):
- a = 1
-
- def __repr__(self):
- return "\n{ \n~ \n}"
- f = Foo()
- assert 0 == f.a
- assert r"where 1 = \n{ \n~ \n}.a" in util._format_lines([getmsg(f)])[0]
-
-
-class TestRewriteOnImport:
-
- def test_pycache_is_a_file(self, testdir):
- testdir.tmpdir.join("__pycache__").write("Hello")
- testdir.makepyfile("""
- def test_rewritten():
- assert "@py_builtins" in globals()""")
- assert testdir.runpytest().ret == 0
-
- def test_pycache_is_readonly(self, testdir):
- cache = testdir.tmpdir.mkdir("__pycache__")
- old_mode = cache.stat().mode
- cache.chmod(old_mode ^ stat.S_IWRITE)
- testdir.makepyfile("""
- def test_rewritten():
- assert "@py_builtins" in globals()""")
- try:
- assert testdir.runpytest().ret == 0
- finally:
- cache.chmod(old_mode)
-
- def test_zipfile(self, testdir):
- z = testdir.tmpdir.join("myzip.zip")
- z_fn = str(z)
- f = zipfile.ZipFile(z_fn, "w")
- try:
- f.writestr("test_gum/__init__.py", "")
- f.writestr("test_gum/test_lizard.py", "")
- finally:
- f.close()
- z.chmod(256)
- testdir.makepyfile("""
- import sys
- sys.path.append(%r)
- import test_gum.test_lizard""" % (z_fn,))
- assert testdir.runpytest().ret == EXIT_NOTESTSCOLLECTED
-
- def test_readonly(self, testdir):
- sub = testdir.mkdir("testing")
- sub.join("test_readonly.py").write(
- py.builtin._totext("""
-def test_rewritten():
- assert "@py_builtins" in globals()
- """).encode("utf-8"), "wb")
- old_mode = sub.stat().mode
- sub.chmod(320)
- try:
- assert testdir.runpytest().ret == 0
- finally:
- sub.chmod(old_mode)
-
- def test_dont_write_bytecode(self, testdir, monkeypatch):
- testdir.makepyfile("""
- import os
- def test_no_bytecode():
- assert "__pycache__" in __cached__
- assert not os.path.exists(__cached__)
- assert not os.path.exists(os.path.dirname(__cached__))""")
- monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", "1")
- assert testdir.runpytest_subprocess().ret == 0
-
- @pytest.mark.skipif('"__pypy__" in sys.modules')
- def test_pyc_vs_pyo(self, testdir, monkeypatch):
- testdir.makepyfile("""
- import pytest
- def test_optimized():
- "hello"
- assert test_optimized.__doc__ is None"""
- )
- p = py.path.local.make_numbered_dir(prefix="runpytest-", keep=None,
- rootdir=testdir.tmpdir)
- tmp = "--basetemp=%s" % p
- monkeypatch.setenv("PYTHONOPTIMIZE", "2")
- monkeypatch.delenv("PYTHONDONTWRITEBYTECODE", raising=False)
- assert testdir.runpytest_subprocess(tmp).ret == 0
- tagged = "test_pyc_vs_pyo." + PYTEST_TAG
- assert tagged + ".pyo" in os.listdir("__pycache__")
- monkeypatch.undo()
- monkeypatch.delenv("PYTHONDONTWRITEBYTECODE", raising=False)
- assert testdir.runpytest_subprocess(tmp).ret == 1
- assert tagged + ".pyc" in os.listdir("__pycache__")
-
- def test_package(self, testdir):
- pkg = testdir.tmpdir.join("pkg")
- pkg.mkdir()
- pkg.join("__init__.py").ensure()
- pkg.join("test_blah.py").write("""
-def test_rewritten():
- assert "@py_builtins" in globals()""")
- assert testdir.runpytest().ret == 0
-
- def test_translate_newlines(self, testdir):
- content = "def test_rewritten():\r\n assert '@py_builtins' in globals()"
- b = content.encode("utf-8")
- testdir.tmpdir.join("test_newlines.py").write(b, "wb")
- assert testdir.runpytest().ret == 0
-
- @pytest.mark.skipif(sys.version_info < (3,3),
- reason='packages without __init__.py not supported on python 2')
- def test_package_without__init__py(self, testdir):
- pkg = testdir.mkdir('a_package_without_init_py')
- pkg.join('module.py').ensure()
- testdir.makepyfile("import a_package_without_init_py.module")
- assert testdir.runpytest().ret == EXIT_NOTESTSCOLLECTED
-
-class TestAssertionRewriteHookDetails(object):
- def test_loader_is_package_false_for_module(self, testdir):
- testdir.makepyfile(test_fun="""
- def test_loader():
- assert not __loader__.is_package(__name__)
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "* 1 passed*",
- ])
-
- def test_loader_is_package_true_for_package(self, testdir):
- testdir.makepyfile(test_fun="""
- def test_loader():
- assert not __loader__.is_package(__name__)
-
- def test_fun():
- assert __loader__.is_package('fun')
-
- def test_missing():
- assert not __loader__.is_package('pytest_not_there')
- """)
- testdir.mkpydir('fun')
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- '* 3 passed*',
- ])
-
- @pytest.mark.skipif("sys.version_info[0] >= 3")
- @pytest.mark.xfail("hasattr(sys, 'pypy_translation_info')")
- def test_assume_ascii(self, testdir):
- content = "u'\xe2\x99\xa5\x01\xfe'"
- testdir.tmpdir.join("test_encoding.py").write(content, "wb")
- res = testdir.runpytest()
- assert res.ret != 0
- assert "SyntaxError: Non-ASCII character" in res.stdout.str()
-
- @pytest.mark.skipif("sys.version_info[0] >= 3")
- def test_detect_coding_cookie(self, testdir):
- testdir.makepyfile(test_cookie="""
- # -*- coding: utf-8 -*-
- u"St\xc3\xa4d"
- def test_rewritten():
- assert "@py_builtins" in globals()""")
- assert testdir.runpytest().ret == 0
-
- @pytest.mark.skipif("sys.version_info[0] >= 3")
- def test_detect_coding_cookie_second_line(self, testdir):
- testdir.makepyfile(test_cookie="""
- # -*- coding: utf-8 -*-
- u"St\xc3\xa4d"
- def test_rewritten():
- assert "@py_builtins" in globals()""")
- assert testdir.runpytest().ret == 0
-
- @pytest.mark.skipif("sys.version_info[0] >= 3")
- def test_detect_coding_cookie_crlf(self, testdir):
- testdir.makepyfile(test_cookie="""
- # -*- coding: utf-8 -*-
- u"St\xc3\xa4d"
- def test_rewritten():
- assert "@py_builtins" in globals()""")
- assert testdir.runpytest().ret == 0
-
- def test_sys_meta_path_munged(self, testdir):
- testdir.makepyfile("""
- def test_meta_path():
- import sys; sys.meta_path = []""")
- assert testdir.runpytest().ret == 0
-
- def test_write_pyc(self, testdir, tmpdir, monkeypatch):
- from _pytest.assertion.rewrite import _write_pyc
- from _pytest.assertion import AssertionState
- try:
- import __builtin__ as b
- except ImportError:
- import builtins as b
- config = testdir.parseconfig([])
- state = AssertionState(config, "rewrite")
- source_path = tmpdir.ensure("source.py")
- pycpath = tmpdir.join("pyc").strpath
- assert _write_pyc(state, [1], source_path.stat(), pycpath)
- def open(*args):
- e = IOError()
- e.errno = 10
- raise e
- monkeypatch.setattr(b, "open", open)
- assert not _write_pyc(state, [1], source_path.stat(), pycpath)
-
- def test_resources_provider_for_loader(self, testdir):
- """
- Attempts to load resources from a package should succeed normally,
- even when the AssertionRewriteHook is used to load the modules.
-
- See #366 for details.
- """
- pytest.importorskip("pkg_resources")
-
- testdir.mkpydir('testpkg')
- contents = {
- 'testpkg/test_pkg': """
- import pkg_resources
-
- import pytest
- from _pytest.assertion.rewrite import AssertionRewritingHook
-
- def test_load_resource():
- assert isinstance(__loader__, AssertionRewritingHook)
- res = pkg_resources.resource_string(__name__, 'resource.txt')
- res = res.decode('ascii')
- assert res == 'Load me please.'
- """,
- }
- testdir.makepyfile(**contents)
- testdir.maketxtfile(**{'testpkg/resource': "Load me please."})
-
- result = testdir.runpytest_subprocess()
- result.assert_outcomes(passed=1)
-
- def test_read_pyc(self, tmpdir):
- """
- Ensure that the `_read_pyc` can properly deal with corrupted pyc files.
- In those circumstances it should just give up instead of generating
- an exception that is propagated to the caller.
- """
- import py_compile
- from _pytest.assertion.rewrite import _read_pyc
-
- source = tmpdir.join('source.py')
- pyc = source + 'c'
-
- source.write('def test(): pass')
- py_compile.compile(str(source), str(pyc))
-
- contents = pyc.read(mode='rb')
- strip_bytes = 20 # header is around 8 bytes, strip a little more
- assert len(contents) > strip_bytes
- pyc.write(contents[:strip_bytes], mode='wb')
-
- assert _read_pyc(source, str(pyc)) is None # no error
-
- def test_reload_is_same(self, testdir):
- # A file that will be picked up during collecting.
- testdir.tmpdir.join("file.py").ensure()
- testdir.tmpdir.join("pytest.ini").write(py.std.textwrap.dedent("""
- [pytest]
- python_files = *.py
- """))
-
- testdir.makepyfile(test_fun="""
- import sys
- try:
- from imp import reload
- except ImportError:
- pass
-
- def test_loader():
- import file
- assert sys.modules["file"] is reload(file)
- """)
- result = testdir.runpytest('-s')
- result.stdout.fnmatch_lines([
- "* 1 passed*",
- ])
-
- def test_get_data_support(self, testdir):
- """Implement optional PEP302 api (#808).
- """
- path = testdir.mkpydir("foo")
- path.join("test_foo.py").write(_pytest._code.Source("""
- class Test:
- def test_foo(self):
- import pkgutil
- data = pkgutil.get_data('foo.test_foo', 'data.txt')
- assert data == b'Hey'
- """))
- path.join('data.txt').write('Hey')
- result = testdir.runpytest()
- result.stdout.fnmatch_lines('*1 passed*')
-
-
-def test_issue731(testdir):
- testdir.makepyfile("""
- class LongReprWithBraces(object):
- def __repr__(self):
- return 'LongReprWithBraces({' + ('a' * 80) + '}' + ('a' * 120) + ')'
-
- def some_method(self):
- return False
-
- def test_long_repr():
- obj = LongReprWithBraces()
- assert obj.some_method()
- """)
- result = testdir.runpytest()
- assert 'unbalanced braces' not in result.stdout.str()
-
-
-def test_collapse_false_unbalanced_braces():
- util._collapse_false('some text{ False\n{False = some more text\n}')
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_cache.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_cache.py
deleted file mode 100755
index 98053f86947..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_cache.py
+++ /dev/null
@@ -1,386 +0,0 @@
-import sys
-
-import _pytest
-import pytest
-import os
-import shutil
-
-pytest_plugins = "pytester",
-
-class TestNewAPI:
- def test_config_cache_makedir(self, testdir):
- testdir.makeini("[pytest]")
- config = testdir.parseconfigure()
- with pytest.raises(ValueError):
- config.cache.makedir("key/name")
-
- p = config.cache.makedir("name")
- assert p.check()
-
- def test_config_cache_dataerror(self, testdir):
- testdir.makeini("[pytest]")
- config = testdir.parseconfigure()
- cache = config.cache
- pytest.raises(TypeError, lambda: cache.set("key/name", cache))
- config.cache.set("key/name", 0)
- config.cache._getvaluepath("key/name").write("123invalid")
- val = config.cache.get("key/name", -2)
- assert val == -2
-
- def test_cache_writefail_cachfile_silent(self, testdir):
- testdir.makeini("[pytest]")
- testdir.tmpdir.join('.cache').write('gone wrong')
- config = testdir.parseconfigure()
- cache = config.cache
- cache.set('test/broken', [])
-
- @pytest.mark.skipif(sys.platform.startswith('win'), reason='no chmod on windows')
- def test_cache_writefail_permissions(self, testdir):
- testdir.makeini("[pytest]")
- testdir.tmpdir.ensure_dir('.cache').chmod(0)
- config = testdir.parseconfigure()
- cache = config.cache
- cache.set('test/broken', [])
-
- @pytest.mark.skipif(sys.platform.startswith('win'), reason='no chmod on windows')
- def test_cache_failure_warns(self, testdir):
- testdir.tmpdir.ensure_dir('.cache').chmod(0)
- testdir.makepyfile("""
- def test_error():
- raise Exception
-
- """)
- result = testdir.runpytest('-rw')
- assert result.ret == 1
- result.stdout.fnmatch_lines([
- "*could not create cache path*",
- "*1 pytest-warnings*",
- ])
-
- def test_config_cache(self, testdir):
- testdir.makeconftest("""
- def pytest_configure(config):
- # see that we get cache information early on
- assert hasattr(config, "cache")
- """)
- testdir.makepyfile("""
- def test_session(pytestconfig):
- assert hasattr(pytestconfig, "cache")
- """)
- result = testdir.runpytest()
- assert result.ret == 0
- result.stdout.fnmatch_lines(["*1 passed*"])
-
- def test_cachefuncarg(self, testdir):
- testdir.makepyfile("""
- import pytest
- def test_cachefuncarg(cache):
- val = cache.get("some/thing", None)
- assert val is None
- cache.set("some/thing", [1])
- pytest.raises(TypeError, lambda: cache.get("some/thing"))
- val = cache.get("some/thing", [])
- assert val == [1]
- """)
- result = testdir.runpytest()
- assert result.ret == 0
- result.stdout.fnmatch_lines(["*1 passed*"])
-
-
-
-def test_cache_reportheader(testdir):
- testdir.makepyfile("""
- def test_hello():
- pass
- """)
- result = testdir.runpytest("-v")
- result.stdout.fnmatch_lines([
- "cachedir: .cache"
- ])
-
-
-def test_cache_show(testdir):
- result = testdir.runpytest("--cache-show")
- assert result.ret == 0
- result.stdout.fnmatch_lines([
- "*cache is empty*"
- ])
- testdir.makeconftest("""
- def pytest_configure(config):
- config.cache.set("my/name", [1,2,3])
- config.cache.set("other/some", {1:2})
- dp = config.cache.makedir("mydb")
- dp.ensure("hello")
- dp.ensure("world")
- """)
- result = testdir.runpytest()
- assert result.ret == 5 # no tests executed
- result = testdir.runpytest("--cache-show")
- result.stdout.fnmatch_lines_random([
- "*cachedir:*",
- "-*cache values*-",
- "*my/name contains:",
- " [1, 2, 3]",
- "*other/some contains*",
- " {*1*: 2}",
- "-*cache directories*-",
- "*mydb/hello*length 0*",
- "*mydb/world*length 0*",
- ])
-
-
-class TestLastFailed:
-
- def test_lastfailed_usecase(self, testdir, monkeypatch):
- monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1)
- p = testdir.makepyfile("""
- def test_1():
- assert 0
- def test_2():
- assert 0
- def test_3():
- assert 1
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*2 failed*",
- ])
- p.write(_pytest._code.Source("""
- def test_1():
- assert 1
-
- def test_2():
- assert 1
-
- def test_3():
- assert 0
- """))
- result = testdir.runpytest("--lf")
- result.stdout.fnmatch_lines([
- "*2 passed*1 desel*",
- ])
- result = testdir.runpytest("--lf")
- result.stdout.fnmatch_lines([
- "*1 failed*2 passed*",
- ])
- result = testdir.runpytest("--lf", "--cache-clear")
- result.stdout.fnmatch_lines([
- "*1 failed*2 passed*",
- ])
-
- # Run this again to make sure clear-cache is robust
- if os.path.isdir('.cache'):
- shutil.rmtree('.cache')
- result = testdir.runpytest("--lf", "--cache-clear")
- result.stdout.fnmatch_lines([
- "*1 failed*2 passed*",
- ])
-
- def test_failedfirst_order(self, testdir):
- testdir.tmpdir.join('test_a.py').write(_pytest._code.Source("""
- def test_always_passes():
- assert 1
- """))
- testdir.tmpdir.join('test_b.py').write(_pytest._code.Source("""
- def test_always_fails():
- assert 0
- """))
- result = testdir.runpytest()
- # Test order will be collection order; alphabetical
- result.stdout.fnmatch_lines([
- "test_a.py*",
- "test_b.py*",
- ])
- result = testdir.runpytest("--lf", "--ff")
- # Test order will be failing tests firs
- result.stdout.fnmatch_lines([
- "test_b.py*",
- "test_a.py*",
- ])
-
- def test_lastfailed_difference_invocations(self, testdir, monkeypatch):
- monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1)
- testdir.makepyfile(test_a="""
- def test_a1():
- assert 0
- def test_a2():
- assert 1
- """, test_b="""
- def test_b1():
- assert 0
- """)
- p = testdir.tmpdir.join("test_a.py")
- p2 = testdir.tmpdir.join("test_b.py")
-
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*2 failed*",
- ])
- result = testdir.runpytest("--lf", p2)
- result.stdout.fnmatch_lines([
- "*1 failed*",
- ])
- p2.write(_pytest._code.Source("""
- def test_b1():
- assert 1
- """))
- result = testdir.runpytest("--lf", p2)
- result.stdout.fnmatch_lines([
- "*1 passed*",
- ])
- result = testdir.runpytest("--lf", p)
- result.stdout.fnmatch_lines([
- "*1 failed*1 desel*",
- ])
-
- def test_lastfailed_usecase_splice(self, testdir, monkeypatch):
- monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1)
- testdir.makepyfile("""
- def test_1():
- assert 0
- """)
- p2 = testdir.tmpdir.join("test_something.py")
- p2.write(_pytest._code.Source("""
- def test_2():
- assert 0
- """))
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*2 failed*",
- ])
- result = testdir.runpytest("--lf", p2)
- result.stdout.fnmatch_lines([
- "*1 failed*",
- ])
- result = testdir.runpytest("--lf")
- result.stdout.fnmatch_lines([
- "*2 failed*",
- ])
-
- def test_lastfailed_xpass(self, testdir):
- testdir.inline_runsource("""
- import pytest
- @pytest.mark.xfail
- def test_hello():
- assert 1
- """)
- config = testdir.parseconfigure()
- lastfailed = config.cache.get("cache/lastfailed", -1)
- assert lastfailed == -1
-
- def test_non_serializable_parametrize(self, testdir):
- """Test that failed parametrized tests with unmarshable parameters
- don't break pytest-cache.
- """
- testdir.makepyfile(r"""
- import pytest
-
- @pytest.mark.parametrize('val', [
- b'\xac\x10\x02G',
- ])
- def test_fail(val):
- assert False
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines('*1 failed in*')
-
- def test_lastfailed_collectfailure(self, testdir, monkeypatch):
-
- testdir.makepyfile(test_maybe="""
- import py
- env = py.std.os.environ
- if '1' == env['FAILIMPORT']:
- raise ImportError('fail')
- def test_hello():
- assert '0' == env['FAILTEST']
- """)
-
- def rlf(fail_import, fail_run):
- monkeypatch.setenv('FAILIMPORT', fail_import)
- monkeypatch.setenv('FAILTEST', fail_run)
-
- testdir.runpytest('-q')
- config = testdir.parseconfigure()
- lastfailed = config.cache.get("cache/lastfailed", -1)
- return lastfailed
-
- lastfailed = rlf(fail_import=0, fail_run=0)
- assert lastfailed == -1
-
- lastfailed = rlf(fail_import=1, fail_run=0)
- assert list(lastfailed) == ['test_maybe.py']
-
- lastfailed = rlf(fail_import=0, fail_run=1)
- assert list(lastfailed) == ['test_maybe.py::test_hello']
-
-
- def test_lastfailed_failure_subset(self, testdir, monkeypatch):
-
- testdir.makepyfile(test_maybe="""
- import py
- env = py.std.os.environ
- if '1' == env['FAILIMPORT']:
- raise ImportError('fail')
- def test_hello():
- assert '0' == env['FAILTEST']
- """)
-
- testdir.makepyfile(test_maybe2="""
- import py
- env = py.std.os.environ
- if '1' == env['FAILIMPORT']:
- raise ImportError('fail')
- def test_hello():
- assert '0' == env['FAILTEST']
-
- def test_pass():
- pass
- """)
-
- def rlf(fail_import, fail_run, args=()):
- monkeypatch.setenv('FAILIMPORT', fail_import)
- monkeypatch.setenv('FAILTEST', fail_run)
-
- result = testdir.runpytest('-q', '--lf', *args)
- config = testdir.parseconfigure()
- lastfailed = config.cache.get("cache/lastfailed", -1)
- return result, lastfailed
-
- result, lastfailed = rlf(fail_import=0, fail_run=0)
- assert lastfailed == -1
- result.stdout.fnmatch_lines([
- '*3 passed*',
- ])
-
- result, lastfailed = rlf(fail_import=1, fail_run=0)
- assert sorted(list(lastfailed)) == ['test_maybe.py', 'test_maybe2.py']
-
-
- result, lastfailed = rlf(fail_import=0, fail_run=0,
- args=('test_maybe2.py',))
- assert list(lastfailed) == ['test_maybe.py']
-
-
- # edge case of test selection - even if we remember failures
- # from other tests we still need to run all tests if no test
- # matches the failures
- result, lastfailed = rlf(fail_import=0, fail_run=0,
- args=('test_maybe2.py',))
- assert list(lastfailed) == ['test_maybe.py']
- result.stdout.fnmatch_lines([
- '*2 passed*',
- ])
-
- def test_lastfailed_creates_cache_when_needed(self, testdir):
- # Issue #1342
- testdir.makepyfile(test_empty='')
- testdir.runpytest('-q', '--lf')
- assert not os.path.exists('.cache')
-
- testdir.makepyfile(test_successful='def test_success():\n assert True')
- testdir.runpytest('-q', '--lf')
- assert not os.path.exists('.cache')
-
- testdir.makepyfile(test_errored='def test_error():\n assert False')
- testdir.runpytest('-q', '--lf')
- assert os.path.exists('.cache')
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_capture.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_capture.py
deleted file mode 100644
index 73660692b8e..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_capture.py
+++ /dev/null
@@ -1,1068 +0,0 @@
-# note: py.io capture tests where copied from
-# pylib 1.4.20.dev2 (rev 13d9af95547e)
-from __future__ import with_statement
-import pickle
-import os
-import sys
-
-import _pytest._code
-import py
-import pytest
-import contextlib
-
-from _pytest import capture
-from _pytest.capture import CaptureManager
-from _pytest.main import EXIT_NOTESTSCOLLECTED
-from py.builtin import print_
-
-needsosdup = pytest.mark.xfail("not hasattr(os, 'dup')")
-
-if sys.version_info >= (3, 0):
- def tobytes(obj):
- if isinstance(obj, str):
- obj = obj.encode('UTF-8')
- assert isinstance(obj, bytes)
- return obj
-
- def totext(obj):
- if isinstance(obj, bytes):
- obj = str(obj, 'UTF-8')
- assert isinstance(obj, str)
- return obj
-else:
- def tobytes(obj):
- if isinstance(obj, unicode):
- obj = obj.encode('UTF-8')
- assert isinstance(obj, str)
- return obj
-
- def totext(obj):
- if isinstance(obj, str):
- obj = unicode(obj, 'UTF-8')
- assert isinstance(obj, unicode)
- return obj
-
-
-def oswritebytes(fd, obj):
- os.write(fd, tobytes(obj))
-
-
-
-def StdCaptureFD(out=True, err=True, in_=True):
- return capture.MultiCapture(out, err, in_, Capture=capture.FDCapture)
-
-def StdCapture(out=True, err=True, in_=True):
- return capture.MultiCapture(out, err, in_, Capture=capture.SysCapture)
-
-
-class TestCaptureManager:
- def test_getmethod_default_no_fd(self, monkeypatch):
- from _pytest.capture import pytest_addoption
- from _pytest.config import Parser
- parser = Parser()
- pytest_addoption(parser)
- default = parser._groups[0].options[0].default
- assert default == "fd" if hasattr(os, "dup") else "sys"
- parser = Parser()
- monkeypatch.delattr(os, 'dup', raising=False)
- pytest_addoption(parser)
- assert parser._groups[0].options[0].default == "sys"
-
- @needsosdup
- @pytest.mark.parametrize("method",
- ['no', 'sys', pytest.mark.skipif('not hasattr(os, "dup")', 'fd')])
- def test_capturing_basic_api(self, method):
- capouter = StdCaptureFD()
- old = sys.stdout, sys.stderr, sys.stdin
- try:
- capman = CaptureManager(method)
- capman.init_capturings()
- outerr = capman.suspendcapture()
- assert outerr == ("", "")
- outerr = capman.suspendcapture()
- assert outerr == ("", "")
- print ("hello")
- out, err = capman.suspendcapture()
- if method == "no":
- assert old == (sys.stdout, sys.stderr, sys.stdin)
- else:
- assert not out
- capman.resumecapture()
- print ("hello")
- out, err = capman.suspendcapture()
- if method != "no":
- assert out == "hello\n"
- capman.reset_capturings()
- finally:
- capouter.stop_capturing()
-
- @needsosdup
- def test_init_capturing(self):
- capouter = StdCaptureFD()
- try:
- capman = CaptureManager("fd")
- capman.init_capturings()
- pytest.raises(AssertionError, "capman.init_capturings()")
- capman.reset_capturings()
- finally:
- capouter.stop_capturing()
-
-
-@pytest.mark.parametrize("method", ['fd', 'sys'])
-def test_capturing_unicode(testdir, method):
- if hasattr(sys, "pypy_version_info") and sys.pypy_version_info < (2,2):
- pytest.xfail("does not work on pypy < 2.2")
- if sys.version_info >= (3, 0):
- obj = "'b\u00f6y'"
- else:
- obj = "u'\u00f6y'"
- testdir.makepyfile("""
- # coding=utf8
- # taken from issue 227 from nosetests
- def test_unicode():
- import sys
- print (sys.stdout)
- print (%s)
- """ % obj)
- result = testdir.runpytest("--capture=%s" % method)
- result.stdout.fnmatch_lines([
- "*1 passed*"
- ])
-
-
-@pytest.mark.parametrize("method", ['fd', 'sys'])
-def test_capturing_bytes_in_utf8_encoding(testdir, method):
- testdir.makepyfile("""
- def test_unicode():
- print ('b\\u00f6y')
- """)
- result = testdir.runpytest("--capture=%s" % method)
- result.stdout.fnmatch_lines([
- "*1 passed*"
- ])
-
-
-def test_collect_capturing(testdir):
- p = testdir.makepyfile("""
- print ("collect %s failure" % 13)
- import xyz42123
- """)
- result = testdir.runpytest(p)
- result.stdout.fnmatch_lines([
- "*Captured stdout*",
- "*collect 13 failure*",
- ])
-
-
-class TestPerTestCapturing:
- def test_capture_and_fixtures(self, testdir):
- p = testdir.makepyfile("""
- def setup_module(mod):
- print ("setup module")
- def setup_function(function):
- print ("setup " + function.__name__)
- def test_func1():
- print ("in func1")
- assert 0
- def test_func2():
- print ("in func2")
- assert 0
- """)
- result = testdir.runpytest(p)
- result.stdout.fnmatch_lines([
- "setup module*",
- "setup test_func1*",
- "in func1*",
- "setup test_func2*",
- "in func2*",
- ])
-
- @pytest.mark.xfail(reason="unimplemented feature")
- def test_capture_scope_cache(self, testdir):
- p = testdir.makepyfile("""
- import sys
- def setup_module(func):
- print ("module-setup")
- def setup_function(func):
- print ("function-setup")
- def test_func():
- print ("in function")
- assert 0
- def teardown_function(func):
- print ("in teardown")
- """)
- result = testdir.runpytest(p)
- result.stdout.fnmatch_lines([
- "*test_func():*",
- "*Captured stdout during setup*",
- "module-setup*",
- "function-setup*",
- "*Captured stdout*",
- "in teardown*",
- ])
-
- def test_no_carry_over(self, testdir):
- p = testdir.makepyfile("""
- def test_func1():
- print ("in func1")
- def test_func2():
- print ("in func2")
- assert 0
- """)
- result = testdir.runpytest(p)
- s = result.stdout.str()
- assert "in func1" not in s
- assert "in func2" in s
-
- def test_teardown_capturing(self, testdir):
- p = testdir.makepyfile("""
- def setup_function(function):
- print ("setup func1")
- def teardown_function(function):
- print ("teardown func1")
- assert 0
- def test_func1():
- print ("in func1")
- pass
- """)
- result = testdir.runpytest(p)
- result.stdout.fnmatch_lines([
- '*teardown_function*',
- '*Captured stdout*',
- "setup func1*",
- "in func1*",
- "teardown func1*",
- #"*1 fixture failure*"
- ])
-
- def test_teardown_capturing_final(self, testdir):
- p = testdir.makepyfile("""
- def teardown_module(mod):
- print ("teardown module")
- assert 0
- def test_func():
- pass
- """)
- result = testdir.runpytest(p)
- result.stdout.fnmatch_lines([
- "*def teardown_module(mod):*",
- "*Captured stdout*",
- "*teardown module*",
- "*1 error*",
- ])
-
- def test_capturing_outerr(self, testdir):
- p1 = testdir.makepyfile("""
- import sys
- def test_capturing():
- print (42)
- sys.stderr.write(str(23))
- def test_capturing_error():
- print (1)
- sys.stderr.write(str(2))
- raise ValueError
- """)
- result = testdir.runpytest(p1)
- result.stdout.fnmatch_lines([
- "*test_capturing_outerr.py .F",
- "====* FAILURES *====",
- "____*____",
- "*test_capturing_outerr.py:8: ValueError",
- "*--- Captured stdout *call*",
- "1",
- "*--- Captured stderr *call*",
- "2",
- ])
-
-
-class TestLoggingInteraction:
- def test_logging_stream_ownership(self, testdir):
- p = testdir.makepyfile("""
- def test_logging():
- import logging
- import pytest
- stream = capture.TextIO()
- logging.basicConfig(stream=stream)
- stream.close() # to free memory/release resources
- """)
- result = testdir.runpytest_subprocess(p)
- result.stderr.str().find("atexit") == -1
-
- def test_logging_and_immediate_setupteardown(self, testdir):
- p = testdir.makepyfile("""
- import logging
- def setup_function(function):
- logging.warn("hello1")
-
- def test_logging():
- logging.warn("hello2")
- assert 0
-
- def teardown_function(function):
- logging.warn("hello3")
- assert 0
- """)
- for optargs in (('--capture=sys',), ('--capture=fd',)):
- print (optargs)
- result = testdir.runpytest_subprocess(p, *optargs)
- s = result.stdout.str()
- result.stdout.fnmatch_lines([
- "*WARN*hello3", # errors show first!
- "*WARN*hello1",
- "*WARN*hello2",
- ])
- # verify proper termination
- assert "closed" not in s
-
- def test_logging_and_crossscope_fixtures(self, testdir):
- p = testdir.makepyfile("""
- import logging
- def setup_module(function):
- logging.warn("hello1")
-
- def test_logging():
- logging.warn("hello2")
- assert 0
-
- def teardown_module(function):
- logging.warn("hello3")
- assert 0
- """)
- for optargs in (('--capture=sys',), ('--capture=fd',)):
- print (optargs)
- result = testdir.runpytest_subprocess(p, *optargs)
- s = result.stdout.str()
- result.stdout.fnmatch_lines([
- "*WARN*hello3", # errors come first
- "*WARN*hello1",
- "*WARN*hello2",
- ])
- # verify proper termination
- assert "closed" not in s
-
- def test_logging_initialized_in_test(self, testdir):
- p = testdir.makepyfile("""
- import sys
- def test_something():
- # pytest does not import logging
- assert 'logging' not in sys.modules
- import logging
- logging.basicConfig()
- logging.warn("hello432")
- assert 0
- """)
- result = testdir.runpytest_subprocess(
- p, "--traceconfig",
- "-p", "no:capturelog")
- assert result.ret != 0
- result.stdout.fnmatch_lines([
- "*hello432*",
- ])
- assert 'operation on closed file' not in result.stderr.str()
-
- def test_conftestlogging_is_shown(self, testdir):
- testdir.makeconftest("""
- import logging
- logging.basicConfig()
- logging.warn("hello435")
- """)
- # make sure that logging is still captured in tests
- result = testdir.runpytest_subprocess("-s", "-p", "no:capturelog")
- assert result.ret == EXIT_NOTESTSCOLLECTED
- result.stderr.fnmatch_lines([
- "WARNING*hello435*",
- ])
- assert 'operation on closed file' not in result.stderr.str()
-
- def test_conftestlogging_and_test_logging(self, testdir):
- testdir.makeconftest("""
- import logging
- logging.basicConfig()
- """)
- # make sure that logging is still captured in tests
- p = testdir.makepyfile("""
- def test_hello():
- import logging
- logging.warn("hello433")
- assert 0
- """)
- result = testdir.runpytest_subprocess(p, "-p", "no:capturelog")
- assert result.ret != 0
- result.stdout.fnmatch_lines([
- "WARNING*hello433*",
- ])
- assert 'something' not in result.stderr.str()
- assert 'operation on closed file' not in result.stderr.str()
-
-
-class TestCaptureFixture:
- @pytest.mark.parametrize("opt", [[], ["-s"]])
- def test_std_functional(self, testdir, opt):
- reprec = testdir.inline_runsource("""
- def test_hello(capsys):
- print (42)
- out, err = capsys.readouterr()
- assert out.startswith("42")
- """, *opt)
- reprec.assertoutcome(passed=1)
-
- def test_capsyscapfd(self, testdir):
- p = testdir.makepyfile("""
- def test_one(capsys, capfd):
- pass
- def test_two(capfd, capsys):
- pass
- """)
- result = testdir.runpytest(p)
- result.stdout.fnmatch_lines([
- "*ERROR*setup*test_one*",
- "*capsys*capfd*same*time*",
- "*ERROR*setup*test_two*",
- "*capsys*capfd*same*time*",
- "*2 error*"])
-
- @pytest.mark.parametrize("method", ["sys", "fd"])
- def test_capture_is_represented_on_failure_issue128(self, testdir, method):
- p = testdir.makepyfile("""
- def test_hello(cap%s):
- print ("xxx42xxx")
- assert 0
- """ % method)
- result = testdir.runpytest(p)
- result.stdout.fnmatch_lines([
- "xxx42xxx",
- ])
-
- @needsosdup
- def test_stdfd_functional(self, testdir):
- reprec = testdir.inline_runsource("""
- def test_hello(capfd):
- import os
- os.write(1, "42".encode('ascii'))
- out, err = capfd.readouterr()
- assert out.startswith("42")
- capfd.close()
- """)
- reprec.assertoutcome(passed=1)
-
- def test_partial_setup_failure(self, testdir):
- p = testdir.makepyfile("""
- def test_hello(capsys, missingarg):
- pass
- """)
- result = testdir.runpytest(p)
- result.stdout.fnmatch_lines([
- "*test_partial_setup_failure*",
- "*1 error*",
- ])
-
- @needsosdup
- def test_keyboardinterrupt_disables_capturing(self, testdir):
- p = testdir.makepyfile("""
- def test_hello(capfd):
- import os
- os.write(1, str(42).encode('ascii'))
- raise KeyboardInterrupt()
- """)
- result = testdir.runpytest_subprocess(p)
- result.stdout.fnmatch_lines([
- "*KeyboardInterrupt*"
- ])
- assert result.ret == 2
-
- @pytest.mark.issue14
- def test_capture_and_logging(self, testdir):
- p = testdir.makepyfile("""
- import logging
- def test_log(capsys):
- logging.error('x')
- """)
- result = testdir.runpytest_subprocess(p)
- assert 'closed' not in result.stderr.str()
-
-
-def test_setup_failure_does_not_kill_capturing(testdir):
- sub1 = testdir.mkpydir("sub1")
- sub1.join("conftest.py").write(_pytest._code.Source("""
- def pytest_runtest_setup(item):
- raise ValueError(42)
- """))
- sub1.join("test_mod.py").write("def test_func1(): pass")
- result = testdir.runpytest(testdir.tmpdir, '--traceconfig')
- result.stdout.fnmatch_lines([
- "*ValueError(42)*",
- "*1 error*"
- ])
-
-
-def test_fdfuncarg_skips_on_no_osdup(testdir):
- testdir.makepyfile("""
- import os
- if hasattr(os, 'dup'):
- del os.dup
- def test_hello(capfd):
- pass
- """)
- result = testdir.runpytest_subprocess("--capture=no")
- result.stdout.fnmatch_lines([
- "*1 skipped*"
- ])
-
-
-def test_capture_conftest_runtest_setup(testdir):
- testdir.makeconftest("""
- def pytest_runtest_setup():
- print ("hello19")
- """)
- testdir.makepyfile("def test_func(): pass")
- result = testdir.runpytest()
- assert result.ret == 0
- assert 'hello19' not in result.stdout.str()
-
-
-def test_capture_badoutput_issue412(testdir):
- testdir.makepyfile("""
- import os
-
- def test_func():
- omg = bytearray([1,129,1])
- os.write(1, omg)
- assert 0
- """)
- result = testdir.runpytest('--cap=fd')
- result.stdout.fnmatch_lines('''
- *def test_func*
- *assert 0*
- *Captured*
- *1 failed*
- ''')
-
-
-def test_capture_early_option_parsing(testdir):
- testdir.makeconftest("""
- def pytest_runtest_setup():
- print ("hello19")
- """)
- testdir.makepyfile("def test_func(): pass")
- result = testdir.runpytest("-vs")
- assert result.ret == 0
- assert 'hello19' in result.stdout.str()
-
-
-def test_capture_binary_output(testdir):
- testdir.makepyfile(r"""
- import pytest
-
- def test_a():
- import sys
- import subprocess
- subprocess.call([sys.executable, __file__])
-
- def test_foo():
- import os;os.write(1, b'\xc3')
-
- if __name__ == '__main__':
- test_foo()
- """)
- result = testdir.runpytest('--assert=plain')
- result.assert_outcomes(passed=2)
-
-
-def test_error_during_readouterr(testdir):
- """Make sure we suspend capturing if errors occurr during readouterr"""
- testdir.makepyfile(pytest_xyz="""
- from _pytest.capture import FDCapture
- def bad_snap(self):
- raise Exception('boom')
- assert FDCapture.snap
- FDCapture.snap = bad_snap
- """)
- result = testdir.runpytest_subprocess(
- "-p", "pytest_xyz", "--version", syspathinsert=True
- )
- result.stderr.fnmatch_lines([
- "*in bad_snap",
- " raise Exception('boom')",
- "Exception: boom",
- ])
-
-
-class TestTextIO:
- def test_text(self):
- f = capture.TextIO()
- f.write("hello")
- s = f.getvalue()
- assert s == "hello"
- f.close()
-
- def test_unicode_and_str_mixture(self):
- f = capture.TextIO()
- if sys.version_info >= (3, 0):
- f.write("\u00f6")
- pytest.raises(TypeError, "f.write(bytes('hello', 'UTF-8'))")
- else:
- f.write(unicode("\u00f6", 'UTF-8'))
- f.write("hello") # bytes
- s = f.getvalue()
- f.close()
- assert isinstance(s, unicode)
-
-
-def test_bytes_io():
- f = py.io.BytesIO()
- f.write(tobytes("hello"))
- pytest.raises(TypeError, "f.write(totext('hello'))")
- s = f.getvalue()
- assert s == tobytes("hello")
-
-
-def test_dontreadfrominput():
- from _pytest.capture import DontReadFromInput
- f = DontReadFromInput()
- assert not f.isatty()
- pytest.raises(IOError, f.read)
- pytest.raises(IOError, f.readlines)
- pytest.raises(IOError, iter, f)
- pytest.raises(ValueError, f.fileno)
- f.close() # just for completeness
-
-
-@pytest.yield_fixture
-def tmpfile(testdir):
- f = testdir.makepyfile("").open('wb+')
- yield f
- if not f.closed:
- f.close()
-
-@needsosdup
-def test_dupfile(tmpfile):
- flist = []
- for i in range(5):
- nf = capture.safe_text_dupfile(tmpfile, "wb")
- assert nf != tmpfile
- assert nf.fileno() != tmpfile.fileno()
- assert nf not in flist
- print_(i, end="", file=nf)
- flist.append(nf)
- for i in range(5):
- f = flist[i]
- f.close()
- tmpfile.seek(0)
- s = tmpfile.read()
- assert "01234" in repr(s)
- tmpfile.close()
-
-def test_dupfile_on_bytesio():
- io = py.io.BytesIO()
- f = capture.safe_text_dupfile(io, "wb")
- f.write("hello")
- assert io.getvalue() == b"hello"
-
-def test_dupfile_on_textio():
- io = py.io.TextIO()
- f = capture.safe_text_dupfile(io, "wb")
- f.write("hello")
- assert io.getvalue() == "hello"
-
-
-@contextlib.contextmanager
-def lsof_check():
- pid = os.getpid()
- try:
- out = py.process.cmdexec("lsof -p %d" % pid)
- except (py.process.cmdexec.Error, UnicodeDecodeError):
- # about UnicodeDecodeError, see note on pytester
- pytest.skip("could not run 'lsof'")
- yield
- out2 = py.process.cmdexec("lsof -p %d" % pid)
- len1 = len([x for x in out.split("\n") if "REG" in x])
- len2 = len([x for x in out2.split("\n") if "REG" in x])
- assert len2 < len1 + 3, out2
-
-
-class TestFDCapture:
- pytestmark = needsosdup
-
- def test_simple(self, tmpfile):
- fd = tmpfile.fileno()
- cap = capture.FDCapture(fd)
- data = tobytes("hello")
- os.write(fd, data)
- s = cap.snap()
- cap.done()
- assert not s
- cap = capture.FDCapture(fd)
- cap.start()
- os.write(fd, data)
- s = cap.snap()
- cap.done()
- assert s == "hello"
-
- def test_simple_many(self, tmpfile):
- for i in range(10):
- self.test_simple(tmpfile)
-
- def test_simple_many_check_open_files(self, testdir):
- with lsof_check():
- with testdir.makepyfile("").open('wb+') as tmpfile:
- self.test_simple_many(tmpfile)
-
- def test_simple_fail_second_start(self, tmpfile):
- fd = tmpfile.fileno()
- cap = capture.FDCapture(fd)
- cap.done()
- pytest.raises(ValueError, cap.start)
-
- def test_stderr(self):
- cap = capture.FDCapture(2)
- cap.start()
- print_("hello", file=sys.stderr)
- s = cap.snap()
- cap.done()
- assert s == "hello\n"
-
- def test_stdin(self, tmpfile):
- cap = capture.FDCapture(0)
- cap.start()
- x = os.read(0, 100).strip()
- cap.done()
- assert x == tobytes('')
-
- def test_writeorg(self, tmpfile):
- data1, data2 = tobytes("foo"), tobytes("bar")
- cap = capture.FDCapture(tmpfile.fileno())
- cap.start()
- tmpfile.write(data1)
- tmpfile.flush()
- cap.writeorg(data2)
- scap = cap.snap()
- cap.done()
- assert scap == totext(data1)
- with open(tmpfile.name, 'rb') as stmp_file:
- stmp = stmp_file.read()
- assert stmp == data2
-
- def test_simple_resume_suspend(self, tmpfile):
- with saved_fd(1):
- cap = capture.FDCapture(1)
- cap.start()
- data = tobytes("hello")
- os.write(1, data)
- sys.stdout.write("whatever")
- s = cap.snap()
- assert s == "hellowhatever"
- cap.suspend()
- os.write(1, tobytes("world"))
- sys.stdout.write("qlwkej")
- assert not cap.snap()
- cap.resume()
- os.write(1, tobytes("but now"))
- sys.stdout.write(" yes\n")
- s = cap.snap()
- assert s == "but now yes\n"
- cap.suspend()
- cap.done()
- pytest.raises(AttributeError, cap.suspend)
-
-
-@contextlib.contextmanager
-def saved_fd(fd):
- new_fd = os.dup(fd)
- try:
- yield
- finally:
- os.dup2(new_fd, fd)
- os.close(new_fd)
-
-
-class TestStdCapture:
- captureclass = staticmethod(StdCapture)
-
- @contextlib.contextmanager
- def getcapture(self, **kw):
- cap = self.__class__.captureclass(**kw)
- cap.start_capturing()
- try:
- yield cap
- finally:
- cap.stop_capturing()
-
- def test_capturing_done_simple(self):
- with self.getcapture() as cap:
- sys.stdout.write("hello")
- sys.stderr.write("world")
- out, err = cap.readouterr()
- assert out == "hello"
- assert err == "world"
-
- def test_capturing_reset_simple(self):
- with self.getcapture() as cap:
- print("hello world")
- sys.stderr.write("hello error\n")
- out, err = cap.readouterr()
- assert out == "hello world\n"
- assert err == "hello error\n"
-
- def test_capturing_readouterr(self):
- with self.getcapture() as cap:
- print ("hello world")
- sys.stderr.write("hello error\n")
- out, err = cap.readouterr()
- assert out == "hello world\n"
- assert err == "hello error\n"
- sys.stderr.write("error2")
- out, err = cap.readouterr()
- assert err == "error2"
-
- def test_capturing_readouterr_unicode(self):
- with self.getcapture() as cap:
- print ("hx\xc4\x85\xc4\x87")
- out, err = cap.readouterr()
- assert out == py.builtin._totext("hx\xc4\x85\xc4\x87\n", "utf8")
-
- @pytest.mark.skipif('sys.version_info >= (3,)',
- reason='text output different for bytes on python3')
- def test_capturing_readouterr_decode_error_handling(self):
- with self.getcapture() as cap:
- # triggered a internal error in pytest
- print('\xa6')
- out, err = cap.readouterr()
- assert out == py.builtin._totext('\ufffd\n', 'unicode-escape')
-
- def test_reset_twice_error(self):
- with self.getcapture() as cap:
- print ("hello")
- out, err = cap.readouterr()
- pytest.raises(ValueError, cap.stop_capturing)
- assert out == "hello\n"
- assert not err
-
- def test_capturing_modify_sysouterr_in_between(self):
- oldout = sys.stdout
- olderr = sys.stderr
- with self.getcapture() as cap:
- sys.stdout.write("hello")
- sys.stderr.write("world")
- sys.stdout = capture.TextIO()
- sys.stderr = capture.TextIO()
- print ("not seen")
- sys.stderr.write("not seen\n")
- out, err = cap.readouterr()
- assert out == "hello"
- assert err == "world"
- assert sys.stdout == oldout
- assert sys.stderr == olderr
-
- def test_capturing_error_recursive(self):
- with self.getcapture() as cap1:
- print ("cap1")
- with self.getcapture() as cap2:
- print ("cap2")
- out2, err2 = cap2.readouterr()
- out1, err1 = cap1.readouterr()
- assert out1 == "cap1\n"
- assert out2 == "cap2\n"
-
- def test_just_out_capture(self):
- with self.getcapture(out=True, err=False) as cap:
- sys.stdout.write("hello")
- sys.stderr.write("world")
- out, err = cap.readouterr()
- assert out == "hello"
- assert not err
-
- def test_just_err_capture(self):
- with self.getcapture(out=False, err=True) as cap:
- sys.stdout.write("hello")
- sys.stderr.write("world")
- out, err = cap.readouterr()
- assert err == "world"
- assert not out
-
- def test_stdin_restored(self):
- old = sys.stdin
- with self.getcapture(in_=True):
- newstdin = sys.stdin
- assert newstdin != sys.stdin
- assert sys.stdin is old
-
- def test_stdin_nulled_by_default(self):
- print ("XXX this test may well hang instead of crashing")
- print ("XXX which indicates an error in the underlying capturing")
- print ("XXX mechanisms")
- with self.getcapture():
- pytest.raises(IOError, "sys.stdin.read()")
-
-
-class TestStdCaptureFD(TestStdCapture):
- pytestmark = needsosdup
- captureclass = staticmethod(StdCaptureFD)
-
- def test_simple_only_fd(self, testdir):
- testdir.makepyfile("""
- import os
- def test_x():
- os.write(1, "hello\\n".encode("ascii"))
- assert 0
- """)
- result = testdir.runpytest_subprocess()
- result.stdout.fnmatch_lines("""
- *test_x*
- *assert 0*
- *Captured stdout*
- """)
-
- def test_intermingling(self):
- with self.getcapture() as cap:
- oswritebytes(1, "1")
- sys.stdout.write(str(2))
- sys.stdout.flush()
- oswritebytes(1, "3")
- oswritebytes(2, "a")
- sys.stderr.write("b")
- sys.stderr.flush()
- oswritebytes(2, "c")
- out, err = cap.readouterr()
- assert out == "123"
- assert err == "abc"
-
- def test_many(self, capfd):
- with lsof_check():
- for i in range(10):
- cap = StdCaptureFD()
- cap.stop_capturing()
-
-
-class TestStdCaptureFDinvalidFD:
- pytestmark = needsosdup
-
- def test_stdcapture_fd_invalid_fd(self, testdir):
- testdir.makepyfile("""
- import os
- from _pytest import capture
- def StdCaptureFD(out=True, err=True, in_=True):
- return capture.MultiCapture(out, err, in_,
- Capture=capture.FDCapture)
- def test_stdout():
- os.close(1)
- cap = StdCaptureFD(out=True, err=False, in_=False)
- cap.stop_capturing()
- def test_stderr():
- os.close(2)
- cap = StdCaptureFD(out=False, err=True, in_=False)
- cap.stop_capturing()
- def test_stdin():
- os.close(0)
- cap = StdCaptureFD(out=False, err=False, in_=True)
- cap.stop_capturing()
- """)
- result = testdir.runpytest_subprocess("--capture=fd")
- assert result.ret == 0
- assert result.parseoutcomes()['passed'] == 3
-
-
-def test_capture_not_started_but_reset():
- capsys = StdCapture()
- capsys.stop_capturing()
-
-
-@needsosdup
-@pytest.mark.parametrize('use', [True, False])
-def test_fdcapture_tmpfile_remains_the_same(tmpfile, use):
- if not use:
- tmpfile = True
- cap = StdCaptureFD(out=False, err=tmpfile)
- try:
- cap.start_capturing()
- capfile = cap.err.tmpfile
- cap.readouterr()
- finally:
- cap.stop_capturing()
- capfile2 = cap.err.tmpfile
- assert capfile2 == capfile
-
-@needsosdup
-def test_close_and_capture_again(testdir):
- testdir.makepyfile("""
- import os
- def test_close():
- os.close(1)
- def test_capture_again():
- os.write(1, b"hello\\n")
- assert 0
- """)
- result = testdir.runpytest_subprocess()
- result.stdout.fnmatch_lines("""
- *test_capture_again*
- *assert 0*
- *stdout*
- *hello*
- """)
-
-
-
-@pytest.mark.parametrize('method', ['SysCapture', 'FDCapture'])
-def test_capturing_and_logging_fundamentals(testdir, method):
- if method == "StdCaptureFD" and not hasattr(os, 'dup'):
- pytest.skip("need os.dup")
- # here we check a fundamental feature
- p = testdir.makepyfile("""
- import sys, os
- import py, logging
- from _pytest import capture
- cap = capture.MultiCapture(out=False, in_=False,
- Capture=capture.%s)
- cap.start_capturing()
-
- logging.warn("hello1")
- outerr = cap.readouterr()
- print ("suspend, captured %%s" %%(outerr,))
- logging.warn("hello2")
-
- cap.pop_outerr_to_orig()
- logging.warn("hello3")
-
- outerr = cap.readouterr()
- print ("suspend2, captured %%s" %% (outerr,))
- """ % (method,))
- result = testdir.runpython(p)
- result.stdout.fnmatch_lines("""
- suspend, captured*hello1*
- suspend2, captured*WARNING:root:hello3*
- """)
- result.stderr.fnmatch_lines("""
- WARNING:root:hello2
- """)
- assert "atexit" not in result.stderr.str()
-
-
-def test_error_attribute_issue555(testdir):
- testdir.makepyfile("""
- import sys
- def test_capattr():
- assert sys.stdout.errors == "strict"
- assert sys.stderr.errors == "strict"
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
-
-def test_dontreadfrominput_has_encoding(testdir):
- testdir.makepyfile("""
- import sys
- def test_capattr():
- # should not raise AttributeError
- assert sys.stdout.encoding
- assert sys.stderr.encoding
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
-
-def test_pickling_and_unpickling_enocded_file():
- # See https://bitbucket.org/pytest-dev/pytest/pull-request/194
- # pickle.loads() raises infinite recursion if
- # EncodedFile.__getattr__ is not implemented properly
- ef = capture.EncodedFile(None, None)
- ef_as_str = pickle.dumps(ef)
- pickle.loads(ef_as_str)
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_collection.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_collection.py
deleted file mode 100644
index 749c5b7ce45..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_collection.py
+++ /dev/null
@@ -1,641 +0,0 @@
-import pytest, py
-
-from _pytest.main import Session, EXIT_NOTESTSCOLLECTED
-
-class TestCollector:
- def test_collect_versus_item(self):
- from pytest import Collector, Item
- assert not issubclass(Collector, Item)
- assert not issubclass(Item, Collector)
-
- def test_compat_attributes(self, testdir, recwarn):
- modcol = testdir.getmodulecol("""
- def test_pass(): pass
- def test_fail(): assert 0
- """)
- recwarn.clear()
- assert modcol.Module == pytest.Module
- assert modcol.Class == pytest.Class
- assert modcol.Item == pytest.Item
- assert modcol.File == pytest.File
- assert modcol.Function == pytest.Function
-
- def test_check_equality(self, testdir):
- modcol = testdir.getmodulecol("""
- def test_pass(): pass
- def test_fail(): assert 0
- """)
- fn1 = testdir.collect_by_name(modcol, "test_pass")
- assert isinstance(fn1, pytest.Function)
- fn2 = testdir.collect_by_name(modcol, "test_pass")
- assert isinstance(fn2, pytest.Function)
-
- assert fn1 == fn2
- assert fn1 != modcol
- if py.std.sys.version_info < (3, 0):
- assert cmp(fn1, fn2) == 0
- assert hash(fn1) == hash(fn2)
-
- fn3 = testdir.collect_by_name(modcol, "test_fail")
- assert isinstance(fn3, pytest.Function)
- assert not (fn1 == fn3)
- assert fn1 != fn3
-
- for fn in fn1,fn2,fn3:
- assert fn != 3
- assert fn != modcol
- assert fn != [1,2,3]
- assert [1,2,3] != fn
- assert modcol != fn
-
- def test_getparent(self, testdir):
- modcol = testdir.getmodulecol("""
- class TestClass:
- def test_foo():
- pass
- """)
- cls = testdir.collect_by_name(modcol, "TestClass")
- fn = testdir.collect_by_name(
- testdir.collect_by_name(cls, "()"), "test_foo")
-
- parent = fn.getparent(pytest.Module)
- assert parent is modcol
-
- parent = fn.getparent(pytest.Function)
- assert parent is fn
-
- parent = fn.getparent(pytest.Class)
- assert parent is cls
-
-
- def test_getcustomfile_roundtrip(self, testdir):
- hello = testdir.makefile(".xxx", hello="world")
- testdir.makepyfile(conftest="""
- import pytest
- class CustomFile(pytest.File):
- pass
- def pytest_collect_file(path, parent):
- if path.ext == ".xxx":
- return CustomFile(path, parent=parent)
- """)
- node = testdir.getpathnode(hello)
- assert isinstance(node, pytest.File)
- assert node.name == "hello.xxx"
- nodes = node.session.perform_collect([node.nodeid], genitems=False)
- assert len(nodes) == 1
- assert isinstance(nodes[0], pytest.File)
-
-class TestCollectFS:
- def test_ignored_certain_directories(self, testdir):
- tmpdir = testdir.tmpdir
- tmpdir.ensure("_darcs", 'test_notfound.py')
- tmpdir.ensure("CVS", 'test_notfound.py')
- tmpdir.ensure("{arch}", 'test_notfound.py')
- tmpdir.ensure(".whatever", 'test_notfound.py')
- tmpdir.ensure(".bzr", 'test_notfound.py')
- tmpdir.ensure("normal", 'test_found.py')
- for x in tmpdir.visit("test_*.py"):
- x.write("def test_hello(): pass")
-
- result = testdir.runpytest("--collect-only")
- s = result.stdout.str()
- assert "test_notfound" not in s
- assert "test_found" in s
-
- def test_custom_norecursedirs(self, testdir):
- testdir.makeini("""
- [pytest]
- norecursedirs = mydir xyz*
- """)
- tmpdir = testdir.tmpdir
- tmpdir.ensure("mydir", "test_hello.py").write("def test_1(): pass")
- tmpdir.ensure("xyz123", "test_2.py").write("def test_2(): 0/0")
- tmpdir.ensure("xy", "test_ok.py").write("def test_3(): pass")
- rec = testdir.inline_run()
- rec.assertoutcome(passed=1)
- rec = testdir.inline_run("xyz123/test_2.py")
- rec.assertoutcome(failed=1)
-
- def test_testpaths_ini(self, testdir, monkeypatch):
- testdir.makeini("""
- [pytest]
- testpaths = gui uts
- """)
- tmpdir = testdir.tmpdir
- tmpdir.ensure("env", "test_1.py").write("def test_env(): pass")
- tmpdir.ensure("gui", "test_2.py").write("def test_gui(): pass")
- tmpdir.ensure("uts", "test_3.py").write("def test_uts(): pass")
-
- # executing from rootdir only tests from `testpaths` directories
- # are collected
- items, reprec = testdir.inline_genitems('-v')
- assert [x.name for x in items] == ['test_gui', 'test_uts']
-
- # check that explicitly passing directories in the command-line
- # collects the tests
- for dirname in ('env', 'gui', 'uts'):
- items, reprec = testdir.inline_genitems(tmpdir.join(dirname))
- assert [x.name for x in items] == ['test_%s' % dirname]
-
- # changing cwd to each subdirectory and running pytest without
- # arguments collects the tests in that directory normally
- for dirname in ('env', 'gui', 'uts'):
- monkeypatch.chdir(testdir.tmpdir.join(dirname))
- items, reprec = testdir.inline_genitems()
- assert [x.name for x in items] == ['test_%s' % dirname]
-
-
-class TestCollectPluginHookRelay:
- def test_pytest_collect_file(self, testdir):
- wascalled = []
- class Plugin:
- def pytest_collect_file(self, path, parent):
- wascalled.append(path)
- testdir.makefile(".abc", "xyz")
- pytest.main([testdir.tmpdir], plugins=[Plugin()])
- assert len(wascalled) == 1
- assert wascalled[0].ext == '.abc'
-
- def test_pytest_collect_directory(self, testdir):
- wascalled = []
- class Plugin:
- def pytest_collect_directory(self, path, parent):
- wascalled.append(path.basename)
- testdir.mkdir("hello")
- testdir.mkdir("world")
- pytest.main(testdir.tmpdir, plugins=[Plugin()])
- assert "hello" in wascalled
- assert "world" in wascalled
-
-class TestPrunetraceback:
- def test_collection_error(self, testdir):
- p = testdir.makepyfile("""
- import not_exists
- """)
- result = testdir.runpytest(p)
- assert "__import__" not in result.stdout.str(), "too long traceback"
- result.stdout.fnmatch_lines([
- "*ERROR collecting*",
- "*mport*not_exists*"
- ])
-
- def test_custom_repr_failure(self, testdir):
- p = testdir.makepyfile("""
- import not_exists
- """)
- testdir.makeconftest("""
- import pytest
- def pytest_collect_file(path, parent):
- return MyFile(path, parent)
- class MyError(Exception):
- pass
- class MyFile(pytest.File):
- def collect(self):
- raise MyError()
- def repr_failure(self, excinfo):
- if excinfo.errisinstance(MyError):
- return "hello world"
- return pytest.File.repr_failure(self, excinfo)
- """)
-
- result = testdir.runpytest(p)
- result.stdout.fnmatch_lines([
- "*ERROR collecting*",
- "*hello world*",
- ])
-
- @pytest.mark.xfail(reason="other mechanism for adding to reporting needed")
- def test_collect_report_postprocessing(self, testdir):
- p = testdir.makepyfile("""
- import not_exists
- """)
- testdir.makeconftest("""
- import pytest
- def pytest_make_collect_report(__multicall__):
- rep = __multicall__.execute()
- rep.headerlines += ["header1"]
- return rep
- """)
- result = testdir.runpytest(p)
- result.stdout.fnmatch_lines([
- "*ERROR collecting*",
- "*header1*",
- ])
-
-
-class TestCustomConftests:
- def test_ignore_collect_path(self, testdir):
- testdir.makeconftest("""
- def pytest_ignore_collect(path, config):
- return path.basename.startswith("x") or \
- path.basename == "test_one.py"
- """)
- sub = testdir.mkdir("xy123")
- sub.ensure("test_hello.py").write("syntax error")
- sub.join("conftest.py").write("syntax error")
- testdir.makepyfile("def test_hello(): pass")
- testdir.makepyfile(test_one="syntax error")
- result = testdir.runpytest("--fulltrace")
- assert result.ret == 0
- result.stdout.fnmatch_lines(["*1 passed*"])
-
- def test_ignore_collect_not_called_on_argument(self, testdir):
- testdir.makeconftest("""
- def pytest_ignore_collect(path, config):
- return True
- """)
- p = testdir.makepyfile("def test_hello(): pass")
- result = testdir.runpytest(p)
- assert result.ret == 0
- result.stdout.fnmatch_lines("*1 passed*")
- result = testdir.runpytest()
- assert result.ret == EXIT_NOTESTSCOLLECTED
- result.stdout.fnmatch_lines("*collected 0 items*")
-
- def test_collectignore_exclude_on_option(self, testdir):
- testdir.makeconftest("""
- collect_ignore = ['hello', 'test_world.py']
- def pytest_addoption(parser):
- parser.addoption("--XX", action="store_true", default=False)
- def pytest_configure(config):
- if config.getvalue("XX"):
- collect_ignore[:] = []
- """)
- testdir.mkdir("hello")
- testdir.makepyfile(test_world="def test_hello(): pass")
- result = testdir.runpytest()
- assert result.ret == EXIT_NOTESTSCOLLECTED
- assert "passed" not in result.stdout.str()
- result = testdir.runpytest("--XX")
- assert result.ret == 0
- assert "passed" in result.stdout.str()
-
- def test_pytest_fs_collect_hooks_are_seen(self, testdir):
- testdir.makeconftest("""
- import pytest
- class MyModule(pytest.Module):
- pass
- def pytest_collect_file(path, parent):
- if path.ext == ".py":
- return MyModule(path, parent)
- """)
- testdir.mkdir("sub")
- testdir.makepyfile("def test_x(): pass")
- result = testdir.runpytest("--collect-only")
- result.stdout.fnmatch_lines([
- "*MyModule*",
- "*test_x*"
- ])
-
- def test_pytest_collect_file_from_sister_dir(self, testdir):
- sub1 = testdir.mkpydir("sub1")
- sub2 = testdir.mkpydir("sub2")
- conf1 = testdir.makeconftest("""
- import pytest
- class MyModule1(pytest.Module):
- pass
- def pytest_collect_file(path, parent):
- if path.ext == ".py":
- return MyModule1(path, parent)
- """)
- conf1.move(sub1.join(conf1.basename))
- conf2 = testdir.makeconftest("""
- import pytest
- class MyModule2(pytest.Module):
- pass
- def pytest_collect_file(path, parent):
- if path.ext == ".py":
- return MyModule2(path, parent)
- """)
- conf2.move(sub2.join(conf2.basename))
- p = testdir.makepyfile("def test_x(): pass")
- p.copy(sub1.join(p.basename))
- p.copy(sub2.join(p.basename))
- result = testdir.runpytest("--collect-only")
- result.stdout.fnmatch_lines([
- "*MyModule1*",
- "*MyModule2*",
- "*test_x*"
- ])
-
-class TestSession:
- def test_parsearg(self, testdir):
- p = testdir.makepyfile("def test_func(): pass")
- subdir = testdir.mkdir("sub")
- subdir.ensure("__init__.py")
- target = subdir.join(p.basename)
- p.move(target)
- subdir.chdir()
- config = testdir.parseconfig(p.basename)
- rcol = Session(config=config)
- assert rcol.fspath == subdir
- parts = rcol._parsearg(p.basename)
-
- assert parts[0] == target
- assert len(parts) == 1
- parts = rcol._parsearg(p.basename + "::test_func")
- assert parts[0] == target
- assert parts[1] == "test_func"
- assert len(parts) == 2
-
- def test_collect_topdir(self, testdir):
- p = testdir.makepyfile("def test_func(): pass")
- id = "::".join([p.basename, "test_func"])
- # XXX migrate to collectonly? (see below)
- config = testdir.parseconfig(id)
- topdir = testdir.tmpdir
- rcol = Session(config)
- assert topdir == rcol.fspath
- #rootid = rcol.nodeid
- #root2 = rcol.perform_collect([rcol.nodeid], genitems=False)[0]
- #assert root2 == rcol, rootid
- colitems = rcol.perform_collect([rcol.nodeid], genitems=False)
- assert len(colitems) == 1
- assert colitems[0].fspath == p
-
-
- def test_collect_protocol_single_function(self, testdir):
- p = testdir.makepyfile("def test_func(): pass")
- id = "::".join([p.basename, "test_func"])
- items, hookrec = testdir.inline_genitems(id)
- item, = items
- assert item.name == "test_func"
- newid = item.nodeid
- assert newid == id
- py.std.pprint.pprint(hookrec.calls)
- topdir = testdir.tmpdir # noqa
- hookrec.assert_contains([
- ("pytest_collectstart", "collector.fspath == topdir"),
- ("pytest_make_collect_report", "collector.fspath == topdir"),
- ("pytest_collectstart", "collector.fspath == p"),
- ("pytest_make_collect_report", "collector.fspath == p"),
- ("pytest_pycollect_makeitem", "name == 'test_func'"),
- ("pytest_collectreport", "report.nodeid.startswith(p.basename)"),
- ("pytest_collectreport", "report.nodeid == ''")
- ])
-
- def test_collect_protocol_method(self, testdir):
- p = testdir.makepyfile("""
- class TestClass:
- def test_method(self):
- pass
- """)
- normid = p.basename + "::TestClass::()::test_method"
- for id in [p.basename,
- p.basename + "::TestClass",
- p.basename + "::TestClass::()",
- normid,
- ]:
- items, hookrec = testdir.inline_genitems(id)
- assert len(items) == 1
- assert items[0].name == "test_method"
- newid = items[0].nodeid
- assert newid == normid
-
- def test_collect_custom_nodes_multi_id(self, testdir):
- p = testdir.makepyfile("def test_func(): pass")
- testdir.makeconftest("""
- import pytest
- class SpecialItem(pytest.Item):
- def runtest(self):
- return # ok
- class SpecialFile(pytest.File):
- def collect(self):
- return [SpecialItem(name="check", parent=self)]
- def pytest_collect_file(path, parent):
- if path.basename == %r:
- return SpecialFile(fspath=path, parent=parent)
- """ % p.basename)
- id = p.basename
-
- items, hookrec = testdir.inline_genitems(id)
- py.std.pprint.pprint(hookrec.calls)
- assert len(items) == 2
- hookrec.assert_contains([
- ("pytest_collectstart",
- "collector.fspath == collector.session.fspath"),
- ("pytest_collectstart",
- "collector.__class__.__name__ == 'SpecialFile'"),
- ("pytest_collectstart",
- "collector.__class__.__name__ == 'Module'"),
- ("pytest_pycollect_makeitem", "name == 'test_func'"),
- ("pytest_collectreport", "report.nodeid.startswith(p.basename)"),
- #("pytest_collectreport",
- # "report.fspath == %r" % str(rcol.fspath)),
- ])
-
- def test_collect_subdir_event_ordering(self, testdir):
- p = testdir.makepyfile("def test_func(): pass")
- aaa = testdir.mkpydir("aaa")
- test_aaa = aaa.join("test_aaa.py")
- p.move(test_aaa)
-
- items, hookrec = testdir.inline_genitems()
- assert len(items) == 1
- py.std.pprint.pprint(hookrec.calls)
- hookrec.assert_contains([
- ("pytest_collectstart", "collector.fspath == test_aaa"),
- ("pytest_pycollect_makeitem", "name == 'test_func'"),
- ("pytest_collectreport",
- "report.nodeid.startswith('aaa/test_aaa.py')"),
- ])
-
- def test_collect_two_commandline_args(self, testdir):
- p = testdir.makepyfile("def test_func(): pass")
- aaa = testdir.mkpydir("aaa")
- bbb = testdir.mkpydir("bbb")
- test_aaa = aaa.join("test_aaa.py")
- p.copy(test_aaa)
- test_bbb = bbb.join("test_bbb.py")
- p.move(test_bbb)
-
- id = "."
-
- items, hookrec = testdir.inline_genitems(id)
- assert len(items) == 2
- py.std.pprint.pprint(hookrec.calls)
- hookrec.assert_contains([
- ("pytest_collectstart", "collector.fspath == test_aaa"),
- ("pytest_pycollect_makeitem", "name == 'test_func'"),
- ("pytest_collectreport", "report.nodeid == 'aaa/test_aaa.py'"),
- ("pytest_collectstart", "collector.fspath == test_bbb"),
- ("pytest_pycollect_makeitem", "name == 'test_func'"),
- ("pytest_collectreport", "report.nodeid == 'bbb/test_bbb.py'"),
- ])
-
- def test_serialization_byid(self, testdir):
- testdir.makepyfile("def test_func(): pass")
- items, hookrec = testdir.inline_genitems()
- assert len(items) == 1
- item, = items
- items2, hookrec = testdir.inline_genitems(item.nodeid)
- item2, = items2
- assert item2.name == item.name
- assert item2.fspath == item.fspath
-
- def test_find_byid_without_instance_parents(self, testdir):
- p = testdir.makepyfile("""
- class TestClass:
- def test_method(self):
- pass
- """)
- arg = p.basename + ("::TestClass::test_method")
- items, hookrec = testdir.inline_genitems(arg)
- assert len(items) == 1
- item, = items
- assert item.nodeid.endswith("TestClass::()::test_method")
-
-class Test_getinitialnodes:
- def test_global_file(self, testdir, tmpdir):
- x = tmpdir.ensure("x.py")
- config = testdir.parseconfigure(x)
- col = testdir.getnode(config, x)
- assert isinstance(col, pytest.Module)
- assert col.name == 'x.py'
- assert col.parent.name == testdir.tmpdir.basename
- assert col.parent.parent is None
- for col in col.listchain():
- assert col.config is config
-
- def test_pkgfile(self, testdir):
- tmpdir = testdir.tmpdir
- subdir = tmpdir.join("subdir")
- x = subdir.ensure("x.py")
- subdir.ensure("__init__.py")
- config = testdir.parseconfigure(x)
- col = testdir.getnode(config, x)
- assert isinstance(col, pytest.Module)
- assert col.name == 'x.py'
- assert col.parent.parent is None
- for col in col.listchain():
- assert col.config is config
-
-class Test_genitems:
- def test_check_collect_hashes(self, testdir):
- p = testdir.makepyfile("""
- def test_1():
- pass
-
- def test_2():
- pass
- """)
- p.copy(p.dirpath(p.purebasename + "2" + ".py"))
- items, reprec = testdir.inline_genitems(p.dirpath())
- assert len(items) == 4
- for numi, i in enumerate(items):
- for numj, j in enumerate(items):
- if numj != numi:
- assert hash(i) != hash(j)
- assert i != j
-
- def test_example_items1(self, testdir):
- p = testdir.makepyfile('''
- def testone():
- pass
-
- class TestX:
- def testmethod_one(self):
- pass
-
- class TestY(TestX):
- pass
- ''')
- items, reprec = testdir.inline_genitems(p)
- assert len(items) == 3
- assert items[0].name == 'testone'
- assert items[1].name == 'testmethod_one'
- assert items[2].name == 'testmethod_one'
-
- # let's also test getmodpath here
- assert items[0].getmodpath() == "testone"
- assert items[1].getmodpath() == "TestX.testmethod_one"
- assert items[2].getmodpath() == "TestY.testmethod_one"
-
- s = items[0].getmodpath(stopatmodule=False)
- assert s.endswith("test_example_items1.testone")
- print(s)
-
- def test_class_and_functions_discovery_using_glob(self, testdir):
- """
- tests that python_classes and python_functions config options work
- as prefixes and glob-like patterns (issue #600).
- """
- testdir.makeini("""
- [pytest]
- python_classes = *Suite Test
- python_functions = *_test test
- """)
- p = testdir.makepyfile('''
- class MyTestSuite:
- def x_test(self):
- pass
-
- class TestCase:
- def test_y(self):
- pass
- ''')
- items, reprec = testdir.inline_genitems(p)
- ids = [x.getmodpath() for x in items]
- assert ids == ['MyTestSuite.x_test', 'TestCase.test_y']
-
-
-def test_matchnodes_two_collections_same_file(testdir):
- testdir.makeconftest("""
- import pytest
- def pytest_configure(config):
- config.pluginmanager.register(Plugin2())
-
- class Plugin2:
- def pytest_collect_file(self, path, parent):
- if path.ext == ".abc":
- return MyFile2(path, parent)
-
- def pytest_collect_file(path, parent):
- if path.ext == ".abc":
- return MyFile1(path, parent)
-
- class MyFile1(pytest.Item, pytest.File):
- def runtest(self):
- pass
- class MyFile2(pytest.File):
- def collect(self):
- return [Item2("hello", parent=self)]
-
- class Item2(pytest.Item):
- def runtest(self):
- pass
- """)
- p = testdir.makefile(".abc", "")
- result = testdir.runpytest()
- assert result.ret == 0
- result.stdout.fnmatch_lines([
- "*2 passed*",
- ])
- res = testdir.runpytest("%s::hello" % p.basename)
- res.stdout.fnmatch_lines([
- "*1 passed*",
- ])
-
-
-class TestNodekeywords:
- def test_no_under(self, testdir):
- modcol = testdir.getmodulecol("""
- def test_pass(): pass
- def test_fail(): assert 0
- """)
- l = list(modcol.keywords)
- assert modcol.name in l
- for x in l:
- assert not x.startswith("_")
- assert modcol.name in repr(modcol.keywords)
-
- def test_issue345(self, testdir):
- testdir.makepyfile("""
- def test_should_not_be_selected():
- assert False, 'I should not have been selected to run'
-
- def test___repr__():
- pass
- """)
- reprec = testdir.inline_run("-k repr")
- reprec.assertoutcome(passed=1, failed=0)
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_config.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_config.py
deleted file mode 100644
index 92c9bdb8b08..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_config.py
+++ /dev/null
@@ -1,570 +0,0 @@
-import py, pytest
-
-import _pytest._code
-from _pytest.config import getcfg, get_common_ancestor, determine_setup
-from _pytest.main import EXIT_NOTESTSCOLLECTED
-
-class TestParseIni:
- def test_getcfg_and_config(self, testdir, tmpdir):
- sub = tmpdir.mkdir("sub")
- sub.chdir()
- tmpdir.join("setup.cfg").write(_pytest._code.Source("""
- [pytest]
- name = value
- """))
- rootdir, inifile, cfg = getcfg([sub], ["setup.cfg"])
- assert cfg['name'] == "value"
- config = testdir.parseconfigure(sub)
- assert config.inicfg['name'] == 'value'
-
- def test_getcfg_empty_path(self, tmpdir):
- getcfg([''], ['setup.cfg']) #happens on py.test ""
-
- def test_append_parse_args(self, testdir, tmpdir, monkeypatch):
- monkeypatch.setenv('PYTEST_ADDOPTS', '--color no -rs --tb="short"')
- tmpdir.join("setup.cfg").write(_pytest._code.Source("""
- [pytest]
- addopts = --verbose
- """))
- config = testdir.parseconfig(tmpdir)
- assert config.option.color == 'no'
- assert config.option.reportchars == 's'
- assert config.option.tbstyle == 'short'
- assert config.option.verbose
- #config = testdir.Config()
- #args = [tmpdir,]
- #config._preparse(args, addopts=False)
- #assert len(args) == 1
-
- def test_tox_ini_wrong_version(self, testdir):
- testdir.makefile('.ini', tox="""
- [pytest]
- minversion=9.0
- """)
- result = testdir.runpytest()
- assert result.ret != 0
- result.stderr.fnmatch_lines([
- "*tox.ini:2*requires*9.0*actual*"
- ])
-
- @pytest.mark.parametrize("name", "setup.cfg tox.ini pytest.ini".split())
- def test_ini_names(self, testdir, name):
- testdir.tmpdir.join(name).write(py.std.textwrap.dedent("""
- [pytest]
- minversion = 1.0
- """))
- config = testdir.parseconfig()
- assert config.getini("minversion") == "1.0"
-
- def test_toxini_before_lower_pytestini(self, testdir):
- sub = testdir.tmpdir.mkdir("sub")
- sub.join("tox.ini").write(py.std.textwrap.dedent("""
- [pytest]
- minversion = 2.0
- """))
- testdir.tmpdir.join("pytest.ini").write(py.std.textwrap.dedent("""
- [pytest]
- minversion = 1.5
- """))
- config = testdir.parseconfigure(sub)
- assert config.getini("minversion") == "2.0"
-
- @pytest.mark.xfail(reason="probably not needed")
- def test_confcutdir(self, testdir):
- sub = testdir.mkdir("sub")
- sub.chdir()
- testdir.makeini("""
- [pytest]
- addopts = --qwe
- """)
- result = testdir.inline_run("--confcutdir=.")
- assert result.ret == 0
-
-class TestConfigCmdlineParsing:
- def test_parsing_again_fails(self, testdir):
- config = testdir.parseconfig()
- pytest.raises(AssertionError, lambda: config.parse([]))
-
- def test_explicitly_specified_config_file_is_loaded(self, testdir):
- testdir.makeconftest("""
- def pytest_addoption(parser):
- parser.addini("custom", "")
- """)
- testdir.makeini("""
- [pytest]
- custom = 0
- """)
- testdir.makefile(".cfg", custom = """
- [pytest]
- custom = 1
- """)
- config = testdir.parseconfig("-c", "custom.cfg")
- assert config.getini("custom") == "1"
-
-class TestConfigAPI:
- def test_config_trace(self, testdir):
- config = testdir.parseconfig()
- l = []
- config.trace.root.setwriter(l.append)
- config.trace("hello")
- assert len(l) == 1
- assert l[0] == "hello [config]\n"
-
- def test_config_getoption(self, testdir):
- testdir.makeconftest("""
- def pytest_addoption(parser):
- parser.addoption("--hello", "-X", dest="hello")
- """)
- config = testdir.parseconfig("--hello=this")
- for x in ("hello", "--hello", "-X"):
- assert config.getoption(x) == "this"
- pytest.raises(ValueError, "config.getoption('qweqwe')")
-
- @pytest.mark.skipif('sys.version_info[:2] not in [(2, 6), (2, 7)]')
- def test_config_getoption_unicode(self, testdir):
- testdir.makeconftest("""
- from __future__ import unicode_literals
-
- def pytest_addoption(parser):
- parser.addoption('--hello', type='string')
- """)
- config = testdir.parseconfig('--hello=this')
- assert config.getoption('hello') == 'this'
-
- def test_config_getvalueorskip(self, testdir):
- config = testdir.parseconfig()
- pytest.raises(pytest.skip.Exception,
- "config.getvalueorskip('hello')")
- verbose = config.getvalueorskip("verbose")
- assert verbose == config.option.verbose
-
- def test_config_getvalueorskip_None(self, testdir):
- testdir.makeconftest("""
- def pytest_addoption(parser):
- parser.addoption("--hello")
- """)
- config = testdir.parseconfig()
- with pytest.raises(pytest.skip.Exception):
- config.getvalueorskip('hello')
-
- def test_getoption(self, testdir):
- config = testdir.parseconfig()
- with pytest.raises(ValueError):
- config.getvalue('x')
- assert config.getoption("x", 1) == 1
-
- def test_getconftest_pathlist(self, testdir, tmpdir):
- somepath = tmpdir.join("x", "y", "z")
- p = tmpdir.join("conftest.py")
- p.write("pathlist = ['.', %r]" % str(somepath))
- config = testdir.parseconfigure(p)
- assert config._getconftest_pathlist('notexist', path=tmpdir) is None
- pl = config._getconftest_pathlist('pathlist', path=tmpdir)
- print(pl)
- assert len(pl) == 2
- assert pl[0] == tmpdir
- assert pl[1] == somepath
-
- def test_addini(self, testdir):
- testdir.makeconftest("""
- def pytest_addoption(parser):
- parser.addini("myname", "my new ini value")
- """)
- testdir.makeini("""
- [pytest]
- myname=hello
- """)
- config = testdir.parseconfig()
- val = config.getini("myname")
- assert val == "hello"
- pytest.raises(ValueError, config.getini, 'other')
-
- def test_addini_pathlist(self, testdir):
- testdir.makeconftest("""
- def pytest_addoption(parser):
- parser.addini("paths", "my new ini value", type="pathlist")
- parser.addini("abc", "abc value")
- """)
- p = testdir.makeini("""
- [pytest]
- paths=hello world/sub.py
- """)
- config = testdir.parseconfig()
- l = config.getini("paths")
- assert len(l) == 2
- assert l[0] == p.dirpath('hello')
- assert l[1] == p.dirpath('world/sub.py')
- pytest.raises(ValueError, config.getini, 'other')
-
- def test_addini_args(self, testdir):
- testdir.makeconftest("""
- def pytest_addoption(parser):
- parser.addini("args", "new args", type="args")
- parser.addini("a2", "", "args", default="1 2 3".split())
- """)
- testdir.makeini("""
- [pytest]
- args=123 "123 hello" "this"
- """)
- config = testdir.parseconfig()
- l = config.getini("args")
- assert len(l) == 3
- assert l == ["123", "123 hello", "this"]
- l = config.getini("a2")
- assert l == list("123")
-
- def test_addini_linelist(self, testdir):
- testdir.makeconftest("""
- def pytest_addoption(parser):
- parser.addini("xy", "", type="linelist")
- parser.addini("a2", "", "linelist")
- """)
- testdir.makeini("""
- [pytest]
- xy= 123 345
- second line
- """)
- config = testdir.parseconfig()
- l = config.getini("xy")
- assert len(l) == 2
- assert l == ["123 345", "second line"]
- l = config.getini("a2")
- assert l == []
-
- @pytest.mark.parametrize('str_val, bool_val',
- [('True', True), ('no', False), ('no-ini', True)])
- def test_addini_bool(self, testdir, str_val, bool_val):
- testdir.makeconftest("""
- def pytest_addoption(parser):
- parser.addini("strip", "", type="bool", default=True)
- """)
- if str_val != 'no-ini':
- testdir.makeini("""
- [pytest]
- strip=%s
- """ % str_val)
- config = testdir.parseconfig()
- assert config.getini("strip") is bool_val
-
- def test_addinivalue_line_existing(self, testdir):
- testdir.makeconftest("""
- def pytest_addoption(parser):
- parser.addini("xy", "", type="linelist")
- """)
- testdir.makeini("""
- [pytest]
- xy= 123
- """)
- config = testdir.parseconfig()
- l = config.getini("xy")
- assert len(l) == 1
- assert l == ["123"]
- config.addinivalue_line("xy", "456")
- l = config.getini("xy")
- assert len(l) == 2
- assert l == ["123", "456"]
-
- def test_addinivalue_line_new(self, testdir):
- testdir.makeconftest("""
- def pytest_addoption(parser):
- parser.addini("xy", "", type="linelist")
- """)
- config = testdir.parseconfig()
- assert not config.getini("xy")
- config.addinivalue_line("xy", "456")
- l = config.getini("xy")
- assert len(l) == 1
- assert l == ["456"]
- config.addinivalue_line("xy", "123")
- l = config.getini("xy")
- assert len(l) == 2
- assert l == ["456", "123"]
-
-
-class TestConfigFromdictargs:
- def test_basic_behavior(self):
- from _pytest.config import Config
- option_dict = {
- 'verbose': 444,
- 'foo': 'bar',
- 'capture': 'no',
- }
- args = ['a', 'b']
-
- config = Config.fromdictargs(option_dict, args)
- with pytest.raises(AssertionError):
- config.parse(['should refuse to parse again'])
- assert config.option.verbose == 444
- assert config.option.foo == 'bar'
- assert config.option.capture == 'no'
- assert config.args == args
-
- def test_origargs(self):
- """Show that fromdictargs can handle args in their "orig" format"""
- from _pytest.config import Config
- option_dict = {}
- args = ['-vvvv', '-s', 'a', 'b']
-
- config = Config.fromdictargs(option_dict, args)
- assert config.args == ['a', 'b']
- assert config._origargs == args
- assert config.option.verbose == 4
- assert config.option.capture == 'no'
-
- def test_inifilename(self, tmpdir):
- tmpdir.join("foo/bar.ini").ensure().write(_pytest._code.Source("""
- [pytest]
- name = value
- """))
-
- from _pytest.config import Config
- inifile = '../../foo/bar.ini'
- option_dict = {
- 'inifilename': inifile,
- 'capture': 'no',
- }
-
- cwd = tmpdir.join('a/b')
- cwd.join('pytest.ini').ensure().write(_pytest._code.Source("""
- [pytest]
- name = wrong-value
- should_not_be_set = true
- """))
- with cwd.ensure(dir=True).as_cwd():
- config = Config.fromdictargs(option_dict, ())
-
- assert config.args == [str(cwd)]
- assert config.option.inifilename == inifile
- assert config.option.capture == 'no'
-
- # this indicates this is the file used for getting configuration values
- assert config.inifile == inifile
- assert config.inicfg.get('name') == 'value'
- assert config.inicfg.get('should_not_be_set') is None
-
-
-def test_options_on_small_file_do_not_blow_up(testdir):
- def runfiletest(opts):
- reprec = testdir.inline_run(*opts)
- passed, skipped, failed = reprec.countoutcomes()
- assert failed == 2
- assert skipped == passed == 0
- path = testdir.makepyfile("""
- def test_f1(): assert 0
- def test_f2(): assert 0
- """)
-
- for opts in ([], ['-l'], ['-s'], ['--tb=no'], ['--tb=short'],
- ['--tb=long'], ['--fulltrace'], ['--nomagic'],
- ['--traceconfig'], ['-v'], ['-v', '-v']):
- runfiletest(opts + [path])
-
-def test_preparse_ordering_with_setuptools(testdir, monkeypatch):
- pkg_resources = pytest.importorskip("pkg_resources")
- def my_iter(name):
- assert name == "pytest11"
- class EntryPoint:
- name = "mytestplugin"
- class dist:
- pass
- def load(self):
- class PseudoPlugin:
- x = 42
- return PseudoPlugin()
- return iter([EntryPoint()])
- monkeypatch.setattr(pkg_resources, 'iter_entry_points', my_iter)
- testdir.makeconftest("""
- pytest_plugins = "mytestplugin",
- """)
- monkeypatch.setenv("PYTEST_PLUGINS", "mytestplugin")
- config = testdir.parseconfig()
- plugin = config.pluginmanager.getplugin("mytestplugin")
- assert plugin.x == 42
-
-def test_plugin_preparse_prevents_setuptools_loading(testdir, monkeypatch):
- pkg_resources = pytest.importorskip("pkg_resources")
- def my_iter(name):
- assert name == "pytest11"
- class EntryPoint:
- name = "mytestplugin"
- def load(self):
- assert 0, "should not arrive here"
- return iter([EntryPoint()])
- monkeypatch.setattr(pkg_resources, 'iter_entry_points', my_iter)
- config = testdir.parseconfig("-p", "no:mytestplugin")
- plugin = config.pluginmanager.getplugin("mytestplugin")
- assert plugin is None
-
-def test_cmdline_processargs_simple(testdir):
- testdir.makeconftest("""
- def pytest_cmdline_preparse(args):
- args.append("-h")
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*pytest*",
- "*-h*",
- ])
-
-def test_invalid_options_show_extra_information(testdir):
- """display extra information when pytest exits due to unrecognized
- options in the command-line"""
- testdir.makeini("""
- [pytest]
- addopts = --invalid-option
- """)
- result = testdir.runpytest()
- result.stderr.fnmatch_lines([
- "*error: unrecognized arguments: --invalid-option*",
- "* inifile: %s*" % testdir.tmpdir.join('tox.ini'),
- "* rootdir: %s*" % testdir.tmpdir,
- ])
-
-
-@pytest.mark.parametrize('args', [
- ['dir1', 'dir2', '-v'],
- ['dir1', '-v', 'dir2'],
- ['dir2', '-v', 'dir1'],
- ['-v', 'dir2', 'dir1'],
-])
-def test_consider_args_after_options_for_rootdir_and_inifile(testdir, args):
- """
- Consider all arguments in the command-line for rootdir and inifile
- discovery, even if they happen to occur after an option. #949
- """
- # replace "dir1" and "dir2" from "args" into their real directory
- root = testdir.tmpdir.mkdir('myroot')
- d1 = root.mkdir('dir1')
- d2 = root.mkdir('dir2')
- for i, arg in enumerate(args):
- if arg == 'dir1':
- args[i] = d1
- elif arg == 'dir2':
- args[i] = d2
- result = testdir.runpytest(*args)
- result.stdout.fnmatch_lines(['*rootdir: *myroot, inifile: '])
-
-
-@pytest.mark.skipif("sys.platform == 'win32'")
-def test_toolongargs_issue224(testdir):
- result = testdir.runpytest("-m", "hello" * 500)
- assert result.ret == EXIT_NOTESTSCOLLECTED
-
-def test_notify_exception(testdir, capfd):
- config = testdir.parseconfig()
- excinfo = pytest.raises(ValueError, "raise ValueError(1)")
- config.notify_exception(excinfo)
- out, err = capfd.readouterr()
- assert "ValueError" in err
- class A:
- def pytest_internalerror(self, excrepr):
- return True
- config.pluginmanager.register(A())
- config.notify_exception(excinfo)
- out, err = capfd.readouterr()
- assert not err
-
-
-def test_load_initial_conftest_last_ordering(testdir):
- from _pytest.config import get_config
- pm = get_config().pluginmanager
- class My:
- def pytest_load_initial_conftests(self):
- pass
- m = My()
- pm.register(m)
- hc = pm.hook.pytest_load_initial_conftests
- l = hc._nonwrappers + hc._wrappers
- assert l[-1].function.__module__ == "_pytest.capture"
- assert l[-2].function == m.pytest_load_initial_conftests
- assert l[-3].function.__module__ == "_pytest.config"
-
-class TestWarning:
- def test_warn_config(self, testdir):
- testdir.makeconftest("""
- l = []
- def pytest_configure(config):
- config.warn("C1", "hello")
- def pytest_logwarning(code, message):
- if message == "hello" and code == "C1":
- l.append(1)
- """)
- testdir.makepyfile("""
- def test_proper(pytestconfig):
- import conftest
- assert conftest.l == [1]
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
- def test_warn_on_test_item_from_request(self, testdir):
- testdir.makepyfile("""
- import pytest
-
- @pytest.fixture
- def fix(request):
- request.node.warn("T1", "hello")
- def test_hello(fix):
- pass
- """)
- result = testdir.runpytest()
- assert result.parseoutcomes()["pytest-warnings"] > 0
- assert "hello" not in result.stdout.str()
-
- result = testdir.runpytest("-rw")
- result.stdout.fnmatch_lines("""
- ===*pytest-warning summary*===
- *WT1*test_warn_on_test_item*:5*hello*
- """)
-
-class TestRootdir:
- def test_simple_noini(self, tmpdir):
- assert get_common_ancestor([tmpdir]) == tmpdir
- assert get_common_ancestor([tmpdir.mkdir("a"), tmpdir]) == tmpdir
- assert get_common_ancestor([tmpdir, tmpdir.join("a")]) == tmpdir
- with tmpdir.as_cwd():
- assert get_common_ancestor([]) == tmpdir
-
- @pytest.mark.parametrize("name", "setup.cfg tox.ini pytest.ini".split())
- def test_with_ini(self, tmpdir, name):
- inifile = tmpdir.join(name)
- inifile.write("[pytest]\n")
-
- a = tmpdir.mkdir("a")
- b = a.mkdir("b")
- for args in ([tmpdir], [a], [b]):
- rootdir, inifile, inicfg = determine_setup(None, args)
- assert rootdir == tmpdir
- assert inifile == inifile
- rootdir, inifile, inicfg = determine_setup(None, [b,a])
- assert rootdir == tmpdir
- assert inifile == inifile
-
- @pytest.mark.parametrize("name", "setup.cfg tox.ini".split())
- def test_pytestini_overides_empty_other(self, tmpdir, name):
- inifile = tmpdir.ensure("pytest.ini")
- a = tmpdir.mkdir("a")
- a.ensure(name)
- rootdir, inifile, inicfg = determine_setup(None, [a])
- assert rootdir == tmpdir
- assert inifile == inifile
-
- def test_setuppy_fallback(self, tmpdir):
- a = tmpdir.mkdir("a")
- a.ensure("setup.cfg")
- tmpdir.ensure("setup.py")
- rootdir, inifile, inicfg = determine_setup(None, [a])
- assert rootdir == tmpdir
- assert inifile is None
- assert inicfg == {}
-
- def test_nothing(self, tmpdir):
- rootdir, inifile, inicfg = determine_setup(None, [tmpdir])
- assert rootdir == tmpdir
- assert inifile is None
- assert inicfg == {}
-
- def test_with_specific_inifile(self, tmpdir):
- inifile = tmpdir.ensure("pytest.ini")
- rootdir, inifile, inicfg = determine_setup(inifile, [tmpdir])
- assert rootdir == tmpdir
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_conftest.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_conftest.py
deleted file mode 100644
index 6f5e77f6d49..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_conftest.py
+++ /dev/null
@@ -1,409 +0,0 @@
-from textwrap import dedent
-
-import _pytest._code
-import py
-import pytest
-from _pytest.config import PytestPluginManager
-from _pytest.main import EXIT_NOTESTSCOLLECTED, EXIT_USAGEERROR
-
-
-@pytest.fixture(scope="module", params=["global", "inpackage"])
-def basedir(request, tmpdir_factory):
- from _pytest.tmpdir import tmpdir
- tmpdir = tmpdir(request, tmpdir_factory)
- tmpdir.ensure("adir/conftest.py").write("a=1 ; Directory = 3")
- tmpdir.ensure("adir/b/conftest.py").write("b=2 ; a = 1.5")
- if request.param == "inpackage":
- tmpdir.ensure("adir/__init__.py")
- tmpdir.ensure("adir/b/__init__.py")
- return tmpdir
-
-def ConftestWithSetinitial(path):
- conftest = PytestPluginManager()
- conftest_setinitial(conftest, [path])
- return conftest
-
-def conftest_setinitial(conftest, args, confcutdir=None):
- class Namespace:
- def __init__(self):
- self.file_or_dir = args
- self.confcutdir = str(confcutdir)
- self.noconftest = False
- conftest._set_initial_conftests(Namespace())
-
-class TestConftestValueAccessGlobal:
- def test_basic_init(self, basedir):
- conftest = PytestPluginManager()
- p = basedir.join("adir")
- assert conftest._rget_with_confmod("a", p)[1] == 1
-
- def test_immediate_initialiation_and_incremental_are_the_same(self, basedir):
- conftest = PytestPluginManager()
- len(conftest._path2confmods)
- conftest._getconftestmodules(basedir)
- snap1 = len(conftest._path2confmods)
- #assert len(conftest._path2confmods) == snap1 + 1
- conftest._getconftestmodules(basedir.join('adir'))
- assert len(conftest._path2confmods) == snap1 + 1
- conftest._getconftestmodules(basedir.join('b'))
- assert len(conftest._path2confmods) == snap1 + 2
-
- def test_value_access_not_existing(self, basedir):
- conftest = ConftestWithSetinitial(basedir)
- with pytest.raises(KeyError):
- conftest._rget_with_confmod('a', basedir)
-
- def test_value_access_by_path(self, basedir):
- conftest = ConftestWithSetinitial(basedir)
- adir = basedir.join("adir")
- assert conftest._rget_with_confmod("a", adir)[1] == 1
- assert conftest._rget_with_confmod("a", adir.join("b"))[1] == 1.5
-
- def test_value_access_with_confmod(self, basedir):
- startdir = basedir.join("adir", "b")
- startdir.ensure("xx", dir=True)
- conftest = ConftestWithSetinitial(startdir)
- mod, value = conftest._rget_with_confmod("a", startdir)
- assert value == 1.5
- path = py.path.local(mod.__file__)
- assert path.dirpath() == basedir.join("adir", "b")
- assert path.purebasename.startswith("conftest")
-
-def test_conftest_in_nonpkg_with_init(tmpdir):
- tmpdir.ensure("adir-1.0/conftest.py").write("a=1 ; Directory = 3")
- tmpdir.ensure("adir-1.0/b/conftest.py").write("b=2 ; a = 1.5")
- tmpdir.ensure("adir-1.0/b/__init__.py")
- tmpdir.ensure("adir-1.0/__init__.py")
- ConftestWithSetinitial(tmpdir.join("adir-1.0", "b"))
-
-def test_doubledash_considered(testdir):
- conf = testdir.mkdir("--option")
- conf.join("conftest.py").ensure()
- conftest = PytestPluginManager()
- conftest_setinitial(conftest, [conf.basename, conf.basename])
- l = conftest._getconftestmodules(conf)
- assert len(l) == 1
-
-def test_issue151_load_all_conftests(testdir):
- names = "code proj src".split()
- for name in names:
- p = testdir.mkdir(name)
- p.ensure("conftest.py")
-
- conftest = PytestPluginManager()
- conftest_setinitial(conftest, names)
- d = list(conftest._conftestpath2mod.values())
- assert len(d) == len(names)
-
-def test_conftest_global_import(testdir):
- testdir.makeconftest("x=3")
- p = testdir.makepyfile("""
- import py, pytest
- from _pytest.config import PytestPluginManager
- conf = PytestPluginManager()
- mod = conf._importconftest(py.path.local("conftest.py"))
- assert mod.x == 3
- import conftest
- assert conftest is mod, (conftest, mod)
- subconf = py.path.local().ensure("sub", "conftest.py")
- subconf.write("y=4")
- mod2 = conf._importconftest(subconf)
- assert mod != mod2
- assert mod2.y == 4
- import conftest
- assert conftest is mod2, (conftest, mod)
- """)
- res = testdir.runpython(p)
- assert res.ret == 0
-
-def test_conftestcutdir(testdir):
- conf = testdir.makeconftest("")
- p = testdir.mkdir("x")
- conftest = PytestPluginManager()
- conftest_setinitial(conftest, [testdir.tmpdir], confcutdir=p)
- l = conftest._getconftestmodules(p)
- assert len(l) == 0
- l = conftest._getconftestmodules(conf.dirpath())
- assert len(l) == 0
- assert conf not in conftest._conftestpath2mod
- # but we can still import a conftest directly
- conftest._importconftest(conf)
- l = conftest._getconftestmodules(conf.dirpath())
- assert l[0].__file__.startswith(str(conf))
- # and all sub paths get updated properly
- l = conftest._getconftestmodules(p)
- assert len(l) == 1
- assert l[0].__file__.startswith(str(conf))
-
-def test_conftestcutdir_inplace_considered(testdir):
- conf = testdir.makeconftest("")
- conftest = PytestPluginManager()
- conftest_setinitial(conftest, [conf.dirpath()], confcutdir=conf.dirpath())
- l = conftest._getconftestmodules(conf.dirpath())
- assert len(l) == 1
- assert l[0].__file__.startswith(str(conf))
-
-@pytest.mark.parametrize("name", 'test tests whatever .dotdir'.split())
-def test_setinitial_conftest_subdirs(testdir, name):
- sub = testdir.mkdir(name)
- subconftest = sub.ensure("conftest.py")
- conftest = PytestPluginManager()
- conftest_setinitial(conftest, [sub.dirpath()], confcutdir=testdir.tmpdir)
- if name not in ('whatever', '.dotdir'):
- assert subconftest in conftest._conftestpath2mod
- assert len(conftest._conftestpath2mod) == 1
- else:
- assert subconftest not in conftest._conftestpath2mod
- assert len(conftest._conftestpath2mod) == 0
-
-def test_conftest_confcutdir(testdir):
- testdir.makeconftest("assert 0")
- x = testdir.mkdir("x")
- x.join("conftest.py").write(_pytest._code.Source("""
- def pytest_addoption(parser):
- parser.addoption("--xyz", action="store_true")
- """))
- result = testdir.runpytest("-h", "--confcutdir=%s" % x, x)
- result.stdout.fnmatch_lines(["*--xyz*"])
- assert 'warning: could not load initial' not in result.stdout.str()
-
-def test_no_conftest(testdir):
- testdir.makeconftest("assert 0")
- result = testdir.runpytest("--noconftest")
- assert result.ret == EXIT_NOTESTSCOLLECTED
-
- result = testdir.runpytest()
- assert result.ret == EXIT_USAGEERROR
-
-def test_conftest_existing_resultlog(testdir):
- x = testdir.mkdir("tests")
- x.join("conftest.py").write(_pytest._code.Source("""
- def pytest_addoption(parser):
- parser.addoption("--xyz", action="store_true")
- """))
- testdir.makefile(ext=".log", result="") # Writes result.log
- result = testdir.runpytest("-h", "--resultlog", "result.log")
- result.stdout.fnmatch_lines(["*--xyz*"])
-
-def test_conftest_existing_junitxml(testdir):
- x = testdir.mkdir("tests")
- x.join("conftest.py").write(_pytest._code.Source("""
- def pytest_addoption(parser):
- parser.addoption("--xyz", action="store_true")
- """))
- testdir.makefile(ext=".xml", junit="") # Writes junit.xml
- result = testdir.runpytest("-h", "--junitxml", "junit.xml")
- result.stdout.fnmatch_lines(["*--xyz*"])
-
-def test_conftest_import_order(testdir, monkeypatch):
- ct1 = testdir.makeconftest("")
- sub = testdir.mkdir("sub")
- ct2 = sub.join("conftest.py")
- ct2.write("")
- def impct(p):
- return p
- conftest = PytestPluginManager()
- monkeypatch.setattr(conftest, '_importconftest', impct)
- assert conftest._getconftestmodules(sub) == [ct1, ct2]
-
-
-def test_fixture_dependency(testdir, monkeypatch):
- ct1 = testdir.makeconftest("")
- ct1 = testdir.makepyfile("__init__.py")
- ct1.write("")
- sub = testdir.mkdir("sub")
- sub.join("__init__.py").write("")
- sub.join("conftest.py").write(py.std.textwrap.dedent("""
- import pytest
-
- @pytest.fixture
- def not_needed():
- assert False, "Should not be called!"
-
- @pytest.fixture
- def foo():
- assert False, "Should not be called!"
-
- @pytest.fixture
- def bar(foo):
- return 'bar'
- """))
- subsub = sub.mkdir("subsub")
- subsub.join("__init__.py").write("")
- subsub.join("test_bar.py").write(py.std.textwrap.dedent("""
- import pytest
-
- @pytest.fixture
- def bar():
- return 'sub bar'
-
- def test_event_fixture(bar):
- assert bar == 'sub bar'
- """))
- result = testdir.runpytest("sub")
- result.stdout.fnmatch_lines(["*1 passed*"])
-
-
-def test_conftest_found_with_double_dash(testdir):
- sub = testdir.mkdir("sub")
- sub.join("conftest.py").write(py.std.textwrap.dedent("""
- def pytest_addoption(parser):
- parser.addoption("--hello-world", action="store_true")
- """))
- p = sub.join("test_hello.py")
- p.write(py.std.textwrap.dedent("""
- import pytest
- def test_hello(found):
- assert found == 1
- """))
- result = testdir.runpytest(str(p) + "::test_hello", "-h")
- result.stdout.fnmatch_lines("""
- *--hello-world*
- """)
-
-
-class TestConftestVisibility:
- def _setup_tree(self, testdir): # for issue616
- # example mostly taken from:
- # https://mail.python.org/pipermail/pytest-dev/2014-September/002617.html
- runner = testdir.mkdir("empty")
- package = testdir.mkdir("package")
-
- package.join("conftest.py").write(dedent("""\
- import pytest
- @pytest.fixture
- def fxtr():
- return "from-package"
- """))
- package.join("test_pkgroot.py").write(dedent("""\
- def test_pkgroot(fxtr):
- assert fxtr == "from-package"
- """))
-
- swc = package.mkdir("swc")
- swc.join("__init__.py").ensure()
- swc.join("conftest.py").write(dedent("""\
- import pytest
- @pytest.fixture
- def fxtr():
- return "from-swc"
- """))
- swc.join("test_with_conftest.py").write(dedent("""\
- def test_with_conftest(fxtr):
- assert fxtr == "from-swc"
-
- """))
-
- snc = package.mkdir("snc")
- snc.join("__init__.py").ensure()
- snc.join("test_no_conftest.py").write(dedent("""\
- def test_no_conftest(fxtr):
- assert fxtr == "from-package" # No local conftest.py, so should
- # use value from parent dir's
-
- """))
- print ("created directory structure:")
- for x in testdir.tmpdir.visit():
- print (" " + x.relto(testdir.tmpdir))
-
- return {
- "runner": runner,
- "package": package,
- "swc": swc,
- "snc": snc}
-
- # N.B.: "swc" stands for "subdir with conftest.py"
- # "snc" stands for "subdir no [i.e. without] conftest.py"
- @pytest.mark.parametrize("chdir,testarg,expect_ntests_passed", [
- # Effective target: package/..
- ("runner", "..", 3),
- ("package", "..", 3),
- ("swc", "../..", 3),
- ("snc", "../..", 3),
-
- # Effective target: package
- ("runner", "../package", 3),
- ("package", ".", 3),
- ("swc", "..", 3),
- ("snc", "..", 3),
-
- # Effective target: package/swc
- ("runner", "../package/swc", 1),
- ("package", "./swc", 1),
- ("swc", ".", 1),
- ("snc", "../swc", 1),
-
- # Effective target: package/snc
- ("runner", "../package/snc", 1),
- ("package", "./snc", 1),
- ("swc", "../snc", 1),
- ("snc", ".", 1),
- ])
- @pytest.mark.issue616
- def test_parsefactories_relative_node_ids(
- self, testdir, chdir,testarg, expect_ntests_passed):
- dirs = self._setup_tree(testdir)
- print("pytest run in cwd: %s" %(
- dirs[chdir].relto(testdir.tmpdir)))
- print("pytestarg : %s" %(testarg))
- print("expected pass : %s" %(expect_ntests_passed))
- with dirs[chdir].as_cwd():
- reprec = testdir.inline_run(testarg, "-q", "--traceconfig")
- reprec.assertoutcome(passed=expect_ntests_passed)
-
-
-@pytest.mark.parametrize('confcutdir,passed,error', [
- ('.', 2, 0),
- ('src', 1, 1),
- (None, 1, 1),
-])
-def test_search_conftest_up_to_inifile(testdir, confcutdir, passed, error):
- """Test that conftest files are detected only up to a ini file, unless
- an explicit --confcutdir option is given.
- """
- root = testdir.tmpdir
- src = root.join('src').ensure(dir=1)
- src.join('pytest.ini').write('[pytest]')
- src.join('conftest.py').write(_pytest._code.Source("""
- import pytest
- @pytest.fixture
- def fix1(): pass
- """))
- src.join('test_foo.py').write(_pytest._code.Source("""
- def test_1(fix1):
- pass
- def test_2(out_of_reach):
- pass
- """))
- root.join('conftest.py').write(_pytest._code.Source("""
- import pytest
- @pytest.fixture
- def out_of_reach(): pass
- """))
-
- args = [str(src)]
- if confcutdir:
- args = ['--confcutdir=%s' % root.join(confcutdir)]
- result = testdir.runpytest(*args)
- match = ''
- if passed:
- match += '*%d passed*' % passed
- if error:
- match += '*%d error*' % error
- result.stdout.fnmatch_lines(match)
-
-
-def test_issue1073_conftest_special_objects(testdir):
- testdir.makeconftest("""
- class DontTouchMe:
- def __getattr__(self, x):
- raise Exception('cant touch me')
-
- x = DontTouchMe()
- """)
- testdir.makepyfile("""
- def test_some():
- pass
- """)
- res = testdir.runpytest()
- assert res.ret == 0
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_doctest.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_doctest.py
deleted file mode 100644
index a4821ee4c9e..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_doctest.py
+++ /dev/null
@@ -1,715 +0,0 @@
-# encoding: utf-8
-import sys
-import _pytest._code
-from _pytest.doctest import DoctestItem, DoctestModule, DoctestTextfile
-import pytest
-
-class TestDoctests:
-
- def test_collect_testtextfile(self, testdir):
- w = testdir.maketxtfile(whatever="")
- checkfile = testdir.maketxtfile(test_something="""
- alskdjalsdk
- >>> i = 5
- >>> i-1
- 4
- """)
- for x in (testdir.tmpdir, checkfile):
- #print "checking that %s returns custom items" % (x,)
- items, reprec = testdir.inline_genitems(x)
- assert len(items) == 1
- assert isinstance(items[0], DoctestTextfile)
- items, reprec = testdir.inline_genitems(w)
- assert len(items) == 1
-
- def test_collect_module_empty(self, testdir):
- path = testdir.makepyfile(whatever="#")
- for p in (path, testdir.tmpdir):
- items, reprec = testdir.inline_genitems(p,
- '--doctest-modules')
- assert len(items) == 0
-
- def test_collect_module_single_modulelevel_doctest(self, testdir):
- path = testdir.makepyfile(whatever='""">>> pass"""')
- for p in (path, testdir.tmpdir):
- items, reprec = testdir.inline_genitems(p,
- '--doctest-modules')
- assert len(items) == 1
- assert isinstance(items[0], DoctestItem)
- assert isinstance(items[0].parent, DoctestModule)
-
- def test_collect_module_two_doctest_one_modulelevel(self, testdir):
- path = testdir.makepyfile(whatever="""
- '>>> x = None'
- def my_func():
- ">>> magic = 42 "
- """)
- for p in (path, testdir.tmpdir):
- items, reprec = testdir.inline_genitems(p,
- '--doctest-modules')
- assert len(items) == 2
- assert isinstance(items[0], DoctestItem)
- assert isinstance(items[1], DoctestItem)
- assert isinstance(items[0].parent, DoctestModule)
- assert items[0].parent is items[1].parent
-
- def test_collect_module_two_doctest_no_modulelevel(self, testdir):
- path = testdir.makepyfile(whatever="""
- '# Empty'
- def my_func():
- ">>> magic = 42 "
- def unuseful():
- '''
- # This is a function
- # >>> # it doesn't have any doctest
- '''
- def another():
- '''
- # This is another function
- >>> import os # this one does have a doctest
- '''
- """)
- for p in (path, testdir.tmpdir):
- items, reprec = testdir.inline_genitems(p,
- '--doctest-modules')
- assert len(items) == 2
- assert isinstance(items[0], DoctestItem)
- assert isinstance(items[1], DoctestItem)
- assert isinstance(items[0].parent, DoctestModule)
- assert items[0].parent is items[1].parent
-
- def test_simple_doctestfile(self, testdir):
- p = testdir.maketxtfile(test_doc="""
- >>> x = 1
- >>> x == 1
- False
- """)
- reprec = testdir.inline_run(p, )
- reprec.assertoutcome(failed=1)
-
- def test_new_pattern(self, testdir):
- p = testdir.maketxtfile(xdoc="""
- >>> x = 1
- >>> x == 1
- False
- """)
- reprec = testdir.inline_run(p, "--doctest-glob=x*.txt")
- reprec.assertoutcome(failed=1)
-
- def test_multiple_patterns(self, testdir):
- """Test support for multiple --doctest-glob arguments (#1255).
- """
- testdir.maketxtfile(xdoc="""
- >>> 1
- 1
- """)
- testdir.makefile('.foo', test="""
- >>> 1
- 1
- """)
- testdir.maketxtfile(test_normal="""
- >>> 1
- 1
- """)
- expected = set(['xdoc.txt', 'test.foo', 'test_normal.txt'])
- assert set(x.basename for x in testdir.tmpdir.listdir()) == expected
- args = ["--doctest-glob=xdoc*.txt", "--doctest-glob=*.foo"]
- result = testdir.runpytest(*args)
- result.stdout.fnmatch_lines([
- '*test.foo *',
- '*xdoc.txt *',
- '*2 passed*',
- ])
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- '*test_normal.txt *',
- '*1 passed*',
- ])
-
- def test_doctest_unexpected_exception(self, testdir):
- testdir.maketxtfile("""
- >>> i = 0
- >>> 0 / i
- 2
- """)
- result = testdir.runpytest("--doctest-modules")
- result.stdout.fnmatch_lines([
- "*unexpected_exception*",
- "*>>> i = 0*",
- "*>>> 0 / i*",
- "*UNEXPECTED*ZeroDivision*",
- ])
-
- def test_docstring_context_around_error(self, testdir):
- """Test that we show some context before the actual line of a failing
- doctest.
- """
- testdir.makepyfile('''
- def foo():
- """
- text-line-1
- text-line-2
- text-line-3
- text-line-4
- text-line-5
- text-line-6
- text-line-7
- text-line-8
- text-line-9
- text-line-10
- text-line-11
- >>> 1 + 1
- 3
-
- text-line-after
- """
- ''')
- result = testdir.runpytest('--doctest-modules')
- result.stdout.fnmatch_lines([
- '*docstring_context_around_error*',
- '005*text-line-3',
- '006*text-line-4',
- '013*text-line-11',
- '014*>>> 1 + 1',
- 'Expected:',
- ' 3',
- 'Got:',
- ' 2',
- ])
- # lines below should be trimmed out
- assert 'text-line-2' not in result.stdout.str()
- assert 'text-line-after' not in result.stdout.str()
-
- def test_doctest_linedata_missing(self, testdir):
- testdir.tmpdir.join('hello.py').write(_pytest._code.Source("""
- class Fun(object):
- @property
- def test(self):
- '''
- >>> a = 1
- >>> 1/0
- '''
- """))
- result = testdir.runpytest("--doctest-modules")
- result.stdout.fnmatch_lines([
- "*hello*",
- "*EXAMPLE LOCATION UNKNOWN, not showing all tests of that example*",
- "*1/0*",
- "*UNEXPECTED*ZeroDivision*",
- "*1 failed*",
- ])
-
-
- def test_doctest_unex_importerror(self, testdir):
- testdir.tmpdir.join("hello.py").write(_pytest._code.Source("""
- import asdalsdkjaslkdjasd
- """))
- testdir.maketxtfile("""
- >>> import hello
- >>>
- """)
- result = testdir.runpytest("--doctest-modules")
- result.stdout.fnmatch_lines([
- "*>>> import hello",
- "*UNEXPECTED*ImportError*",
- "*import asdals*",
- ])
-
- def test_doctestmodule(self, testdir):
- p = testdir.makepyfile("""
- '''
- >>> x = 1
- >>> x == 1
- False
-
- '''
- """)
- reprec = testdir.inline_run(p, "--doctest-modules")
- reprec.assertoutcome(failed=1)
-
- def test_doctestmodule_external_and_issue116(self, testdir):
- p = testdir.mkpydir("hello")
- p.join("__init__.py").write(_pytest._code.Source("""
- def somefunc():
- '''
- >>> i = 0
- >>> i + 1
- 2
- '''
- """))
- result = testdir.runpytest(p, "--doctest-modules")
- result.stdout.fnmatch_lines([
- '004 *>>> i = 0',
- '005 *>>> i + 1',
- '*Expected:',
- "* 2",
- "*Got:",
- "* 1",
- "*:5: DocTestFailure"
- ])
-
-
- def test_txtfile_failing(self, testdir):
- p = testdir.maketxtfile("""
- >>> i = 0
- >>> i + 1
- 2
- """)
- result = testdir.runpytest(p, "-s")
- result.stdout.fnmatch_lines([
- '001 >>> i = 0',
- '002 >>> i + 1',
- 'Expected:',
- " 2",
- "Got:",
- " 1",
- "*test_txtfile_failing.txt:2: DocTestFailure"
- ])
-
- def test_txtfile_with_fixtures(self, testdir):
- p = testdir.maketxtfile("""
- >>> dir = getfixture('tmpdir')
- >>> type(dir).__name__
- 'LocalPath'
- """)
- reprec = testdir.inline_run(p, )
- reprec.assertoutcome(passed=1)
-
- def test_txtfile_with_usefixtures_in_ini(self, testdir):
- testdir.makeini("""
- [pytest]
- usefixtures = myfixture
- """)
- testdir.makeconftest("""
- import pytest
- @pytest.fixture
- def myfixture(monkeypatch):
- monkeypatch.setenv("HELLO", "WORLD")
- """)
-
- p = testdir.maketxtfile("""
- >>> import os
- >>> os.environ["HELLO"]
- 'WORLD'
- """)
- reprec = testdir.inline_run(p, )
- reprec.assertoutcome(passed=1)
-
- def test_doctestmodule_with_fixtures(self, testdir):
- p = testdir.makepyfile("""
- '''
- >>> dir = getfixture('tmpdir')
- >>> type(dir).__name__
- 'LocalPath'
- '''
- """)
- reprec = testdir.inline_run(p, "--doctest-modules")
- reprec.assertoutcome(passed=1)
-
- def test_doctestmodule_three_tests(self, testdir):
- p = testdir.makepyfile("""
- '''
- >>> dir = getfixture('tmpdir')
- >>> type(dir).__name__
- 'LocalPath'
- '''
- def my_func():
- '''
- >>> magic = 42
- >>> magic - 42
- 0
- '''
- def unuseful():
- pass
- def another():
- '''
- >>> import os
- >>> os is os
- True
- '''
- """)
- reprec = testdir.inline_run(p, "--doctest-modules")
- reprec.assertoutcome(passed=3)
-
- def test_doctestmodule_two_tests_one_fail(self, testdir):
- p = testdir.makepyfile("""
- class MyClass:
- def bad_meth(self):
- '''
- >>> magic = 42
- >>> magic
- 0
- '''
- def nice_meth(self):
- '''
- >>> magic = 42
- >>> magic - 42
- 0
- '''
- """)
- reprec = testdir.inline_run(p, "--doctest-modules")
- reprec.assertoutcome(failed=1, passed=1)
-
- def test_ignored_whitespace(self, testdir):
- testdir.makeini("""
- [pytest]
- doctest_optionflags = ELLIPSIS NORMALIZE_WHITESPACE
- """)
- p = testdir.makepyfile("""
- class MyClass:
- '''
- >>> a = "foo "
- >>> print(a)
- foo
- '''
- pass
- """)
- reprec = testdir.inline_run(p, "--doctest-modules")
- reprec.assertoutcome(passed=1)
-
- def test_non_ignored_whitespace(self, testdir):
- testdir.makeini("""
- [pytest]
- doctest_optionflags = ELLIPSIS
- """)
- p = testdir.makepyfile("""
- class MyClass:
- '''
- >>> a = "foo "
- >>> print(a)
- foo
- '''
- pass
- """)
- reprec = testdir.inline_run(p, "--doctest-modules")
- reprec.assertoutcome(failed=1, passed=0)
-
- def test_ignored_whitespace_glob(self, testdir):
- testdir.makeini("""
- [pytest]
- doctest_optionflags = ELLIPSIS NORMALIZE_WHITESPACE
- """)
- p = testdir.maketxtfile(xdoc="""
- >>> a = "foo "
- >>> print(a)
- foo
- """)
- reprec = testdir.inline_run(p, "--doctest-glob=x*.txt")
- reprec.assertoutcome(passed=1)
-
- def test_non_ignored_whitespace_glob(self, testdir):
- testdir.makeini("""
- [pytest]
- doctest_optionflags = ELLIPSIS
- """)
- p = testdir.maketxtfile(xdoc="""
- >>> a = "foo "
- >>> print(a)
- foo
- """)
- reprec = testdir.inline_run(p, "--doctest-glob=x*.txt")
- reprec.assertoutcome(failed=1, passed=0)
-
- def test_contains_unicode(self, testdir):
- """Fix internal error with docstrings containing non-ascii characters.
- """
- testdir.makepyfile(u'''
- # encoding: utf-8
- def foo():
- """
- >>> name = 'с' # not letter 'c' but instead Cyrillic 's'.
- 'anything'
- """
- ''')
- result = testdir.runpytest('--doctest-modules')
- result.stdout.fnmatch_lines([
- 'Got nothing',
- '* 1 failed in*',
- ])
-
- def test_ignore_import_errors_on_doctest(self, testdir):
- p = testdir.makepyfile("""
- import asdf
-
- def add_one(x):
- '''
- >>> add_one(1)
- 2
- '''
- return x + 1
- """)
-
- reprec = testdir.inline_run(p, "--doctest-modules",
- "--doctest-ignore-import-errors")
- reprec.assertoutcome(skipped=1, failed=1, passed=0)
-
- def test_junit_report_for_doctest(self, testdir):
- """
- #713: Fix --junit-xml option when used with --doctest-modules.
- """
- p = testdir.makepyfile("""
- def foo():
- '''
- >>> 1 + 1
- 3
- '''
- pass
- """)
- reprec = testdir.inline_run(p, "--doctest-modules",
- "--junit-xml=junit.xml")
- reprec.assertoutcome(failed=1)
-
-
-class TestLiterals:
-
- @pytest.mark.parametrize('config_mode', ['ini', 'comment'])
- def test_allow_unicode(self, testdir, config_mode):
- """Test that doctests which output unicode work in all python versions
- tested by pytest when the ALLOW_UNICODE option is used (either in
- the ini file or by an inline comment).
- """
- if config_mode == 'ini':
- testdir.makeini('''
- [pytest]
- doctest_optionflags = ALLOW_UNICODE
- ''')
- comment = ''
- else:
- comment = '#doctest: +ALLOW_UNICODE'
-
- testdir.maketxtfile(test_doc="""
- >>> b'12'.decode('ascii') {comment}
- '12'
- """.format(comment=comment))
- testdir.makepyfile(foo="""
- def foo():
- '''
- >>> b'12'.decode('ascii') {comment}
- '12'
- '''
- """.format(comment=comment))
- reprec = testdir.inline_run("--doctest-modules")
- reprec.assertoutcome(passed=2)
-
- @pytest.mark.parametrize('config_mode', ['ini', 'comment'])
- def test_allow_bytes(self, testdir, config_mode):
- """Test that doctests which output bytes work in all python versions
- tested by pytest when the ALLOW_BYTES option is used (either in
- the ini file or by an inline comment)(#1287).
- """
- if config_mode == 'ini':
- testdir.makeini('''
- [pytest]
- doctest_optionflags = ALLOW_BYTES
- ''')
- comment = ''
- else:
- comment = '#doctest: +ALLOW_BYTES'
-
- testdir.maketxtfile(test_doc="""
- >>> b'foo' {comment}
- 'foo'
- """.format(comment=comment))
- testdir.makepyfile(foo="""
- def foo():
- '''
- >>> b'foo' {comment}
- 'foo'
- '''
- """.format(comment=comment))
- reprec = testdir.inline_run("--doctest-modules")
- reprec.assertoutcome(passed=2)
-
- def test_unicode_string(self, testdir):
- """Test that doctests which output unicode fail in Python 2 when
- the ALLOW_UNICODE option is not used. The same test should pass
- in Python 3.
- """
- testdir.maketxtfile(test_doc="""
- >>> b'12'.decode('ascii')
- '12'
- """)
- reprec = testdir.inline_run()
- passed = int(sys.version_info[0] >= 3)
- reprec.assertoutcome(passed=passed, failed=int(not passed))
-
- def test_bytes_literal(self, testdir):
- """Test that doctests which output bytes fail in Python 3 when
- the ALLOW_BYTES option is not used. The same test should pass
- in Python 2 (#1287).
- """
- testdir.maketxtfile(test_doc="""
- >>> b'foo'
- 'foo'
- """)
- reprec = testdir.inline_run()
- passed = int(sys.version_info[0] == 2)
- reprec.assertoutcome(passed=passed, failed=int(not passed))
-
-
-class TestDoctestSkips:
- """
- If all examples in a doctest are skipped due to the SKIP option, then
- the tests should be SKIPPED rather than PASSED. (#957)
- """
-
- @pytest.fixture(params=['text', 'module'])
- def makedoctest(self, testdir, request):
- def makeit(doctest):
- mode = request.param
- if mode == 'text':
- testdir.maketxtfile(doctest)
- else:
- assert mode == 'module'
- testdir.makepyfile('"""\n%s"""' % doctest)
-
- return makeit
-
- def test_one_skipped(self, testdir, makedoctest):
- makedoctest("""
- >>> 1 + 1 # doctest: +SKIP
- 2
- >>> 2 + 2
- 4
- """)
- reprec = testdir.inline_run("--doctest-modules")
- reprec.assertoutcome(passed=1)
-
- def test_one_skipped_failed(self, testdir, makedoctest):
- makedoctest("""
- >>> 1 + 1 # doctest: +SKIP
- 2
- >>> 2 + 2
- 200
- """)
- reprec = testdir.inline_run("--doctest-modules")
- reprec.assertoutcome(failed=1)
-
- def test_all_skipped(self, testdir, makedoctest):
- makedoctest("""
- >>> 1 + 1 # doctest: +SKIP
- 2
- >>> 2 + 2 # doctest: +SKIP
- 200
- """)
- reprec = testdir.inline_run("--doctest-modules")
- reprec.assertoutcome(skipped=1)
-
-
-class TestDoctestAutoUseFixtures:
-
- SCOPES = ['module', 'session', 'class', 'function']
-
- def test_doctest_module_session_fixture(self, testdir):
- """Test that session fixtures are initialized for doctest modules (#768)
- """
- # session fixture which changes some global data, which will
- # be accessed by doctests in a module
- testdir.makeconftest("""
- import pytest
- import sys
-
- @pytest.yield_fixture(autouse=True, scope='session')
- def myfixture():
- assert not hasattr(sys, 'pytest_session_data')
- sys.pytest_session_data = 1
- yield
- del sys.pytest_session_data
- """)
- testdir.makepyfile(foo="""
- import sys
-
- def foo():
- '''
- >>> assert sys.pytest_session_data == 1
- '''
-
- def bar():
- '''
- >>> assert sys.pytest_session_data == 1
- '''
- """)
- result = testdir.runpytest("--doctest-modules")
- result.stdout.fnmatch_lines('*2 passed*')
-
- @pytest.mark.parametrize('scope', SCOPES)
- @pytest.mark.parametrize('enable_doctest', [True, False])
- def test_fixture_scopes(self, testdir, scope, enable_doctest):
- """Test that auto-use fixtures work properly with doctest modules.
- See #1057 and #1100.
- """
- testdir.makeconftest('''
- import pytest
-
- @pytest.fixture(autouse=True, scope="{scope}")
- def auto(request):
- return 99
- '''.format(scope=scope))
- testdir.makepyfile(test_1='''
- def test_foo():
- """
- >>> getfixture('auto') + 1
- 100
- """
- def test_bar():
- assert 1
- ''')
- params = ('--doctest-modules',) if enable_doctest else ()
- passes = 3 if enable_doctest else 2
- result = testdir.runpytest(*params)
- result.stdout.fnmatch_lines(['*=== %d passed in *' % passes])
-
- @pytest.mark.parametrize('scope', SCOPES)
- @pytest.mark.parametrize('autouse', [True, False])
- @pytest.mark.parametrize('use_fixture_in_doctest', [True, False])
- def test_fixture_module_doctest_scopes(self, testdir, scope, autouse,
- use_fixture_in_doctest):
- """Test that auto-use fixtures work properly with doctest files.
- See #1057 and #1100.
- """
- testdir.makeconftest('''
- import pytest
-
- @pytest.fixture(autouse={autouse}, scope="{scope}")
- def auto(request):
- return 99
- '''.format(scope=scope, autouse=autouse))
- if use_fixture_in_doctest:
- testdir.maketxtfile(test_doc="""
- >>> getfixture('auto')
- 99
- """)
- else:
- testdir.maketxtfile(test_doc="""
- >>> 1 + 1
- 2
- """)
- result = testdir.runpytest('--doctest-modules')
- assert 'FAILURES' not in str(result.stdout.str())
- result.stdout.fnmatch_lines(['*=== 1 passed in *'])
-
- @pytest.mark.parametrize('scope', SCOPES)
- def test_auto_use_request_attributes(self, testdir, scope):
- """Check that all attributes of a request in an autouse fixture
- behave as expected when requested for a doctest item.
- """
- testdir.makeconftest('''
- import pytest
-
- @pytest.fixture(autouse=True, scope="{scope}")
- def auto(request):
- if "{scope}" == 'module':
- assert request.module is None
- if "{scope}" == 'class':
- assert request.cls is None
- if "{scope}" == 'function':
- assert request.function is None
- return 99
- '''.format(scope=scope))
- testdir.maketxtfile(test_doc="""
- >>> 1 + 1
- 2
- """)
- result = testdir.runpytest('--doctest-modules')
- assert 'FAILURES' not in str(result.stdout.str())
- result.stdout.fnmatch_lines(['*=== 1 passed in *'])
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_genscript.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_genscript.py
deleted file mode 100644
index 1260a5a6b26..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_genscript.py
+++ /dev/null
@@ -1,51 +0,0 @@
-import pytest
-import sys
-
-
-@pytest.fixture(scope="module")
-def standalone(request):
- return Standalone(request)
-
-class Standalone:
- def __init__(self, request):
- self.testdir = request.getfuncargvalue("testdir")
- script = "mypytest"
- result = self.testdir.runpytest("--genscript=%s" % script)
- assert result.ret == 0
- self.script = self.testdir.tmpdir.join(script)
- assert self.script.check()
-
- def run(self, anypython, testdir, *args):
- return testdir._run(anypython, self.script, *args)
-
-def test_gen(testdir, anypython, standalone):
- if sys.version_info >= (2,7):
- result = testdir._run(anypython, "-c",
- "import sys;print (sys.version_info >=(2,7))")
- assert result.ret == 0
- if result.stdout.str() == "False":
- pytest.skip("genscript called from python2.7 cannot work "
- "earlier python versions")
- result = standalone.run(anypython, testdir, '--version')
- if result.ret == 2:
- result.stderr.fnmatch_lines(["*ERROR: setuptools not installed*"])
- elif result.ret == 0:
- result.stderr.fnmatch_lines([
- "*imported from*mypytest*"
- ])
- p = testdir.makepyfile("def test_func(): assert 0")
- result = standalone.run(anypython, testdir, p)
- assert result.ret != 0
- else:
- pytest.fail("Unexpected return code")
-
-
-def test_freeze_includes():
- """
- Smoke test for freeze_includes(), to ensure that it works across all
- supported python versions.
- """
- includes = pytest.freeze_includes()
- assert len(includes) > 1
- assert '_pytest.genscript' in includes
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_helpconfig.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_helpconfig.py
deleted file mode 100644
index 9f8d87b7cb5..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_helpconfig.py
+++ /dev/null
@@ -1,69 +0,0 @@
-from _pytest.main import EXIT_NOTESTSCOLLECTED
-import pytest
-
-def test_version(testdir, pytestconfig):
- result = testdir.runpytest("--version")
- assert result.ret == 0
- #p = py.path.local(py.__file__).dirpath()
- result.stderr.fnmatch_lines([
- '*pytest*%s*imported from*' % (pytest.__version__, )
- ])
- if pytestconfig.pluginmanager.list_plugin_distinfo():
- result.stderr.fnmatch_lines([
- "*setuptools registered plugins:",
- "*at*",
- ])
-
-def test_help(testdir):
- result = testdir.runpytest("--help")
- assert result.ret == 0
- result.stdout.fnmatch_lines("""
- *-v*verbose*
- *setup.cfg*
- *minversion*
- *to see*markers*py.test --markers*
- *to see*fixtures*py.test --fixtures*
- """)
-
-def test_hookvalidation_unknown(testdir):
- testdir.makeconftest("""
- def pytest_hello(xyz):
- pass
- """)
- result = testdir.runpytest()
- assert result.ret != 0
- result.stderr.fnmatch_lines([
- '*unknown hook*pytest_hello*'
- ])
-
-def test_hookvalidation_optional(testdir):
- testdir.makeconftest("""
- import pytest
- @pytest.hookimpl(optionalhook=True)
- def pytest_hello(xyz):
- pass
- """)
- result = testdir.runpytest()
- assert result.ret == EXIT_NOTESTSCOLLECTED
-
-def test_traceconfig(testdir):
- result = testdir.runpytest("--traceconfig")
- result.stdout.fnmatch_lines([
- "*using*pytest*py*",
- "*active plugins*",
- ])
-
-def test_debug(testdir, monkeypatch):
- result = testdir.runpytest_subprocess("--debug")
- assert result.ret == EXIT_NOTESTSCOLLECTED
- p = testdir.tmpdir.join("pytestdebug.log")
- assert "pytest_sessionstart" in p.read()
-
-def test_PYTEST_DEBUG(testdir, monkeypatch):
- monkeypatch.setenv("PYTEST_DEBUG", "1")
- result = testdir.runpytest_subprocess()
- assert result.ret == EXIT_NOTESTSCOLLECTED
- result.stderr.fnmatch_lines([
- "*pytest_plugin_registered*",
- "*manager*PluginManager*"
- ])
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_junitxml.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_junitxml.py
deleted file mode 100644
index 5960f882535..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_junitxml.py
+++ /dev/null
@@ -1,816 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from xml.dom import minidom
-from _pytest.main import EXIT_NOTESTSCOLLECTED
-import py
-import sys
-import os
-from _pytest.junitxml import LogXML
-import pytest
-
-
-def runandparse(testdir, *args):
- resultpath = testdir.tmpdir.join("junit.xml")
- result = testdir.runpytest("--junitxml=%s" % resultpath, *args)
- xmldoc = minidom.parse(str(resultpath))
- return result, DomNode(xmldoc)
-
-
-def assert_attr(node, **kwargs):
- __tracebackhide__ = True
-
- def nodeval(node, name):
- anode = node.getAttributeNode(name)
- if anode is not None:
- return anode.value
-
- expected = dict((name, str(value)) for name, value in kwargs.items())
- on_node = dict((name, nodeval(node, name)) for name in expected)
- assert on_node == expected
-
-
-class DomNode(object):
- def __init__(self, dom):
- self.__node = dom
-
- def __repr__(self):
- return self.__node.toxml()
-
- def find_first_by_tag(self, tag):
- return self.find_nth_by_tag(tag, 0)
-
- def _by_tag(self, tag):
- return self.__node.getElementsByTagName(tag)
-
- def find_nth_by_tag(self, tag, n):
- items = self._by_tag(tag)
- try:
- nth = items[n]
- except IndexError:
- pass
- else:
- return type(self)(nth)
-
- def find_by_tag(self, tag):
- t = type(self)
- return [t(x) for x in self.__node.getElementsByTagName(tag)]
-
- def __getitem__(self, key):
- node = self.__node.getAttributeNode(key)
- if node is not None:
- return node.value
-
- def assert_attr(self, **kwargs):
- __tracebackhide__ = True
- return assert_attr(self.__node, **kwargs)
-
- def toxml(self):
- return self.__node.toxml()
-
- @property
- def text(self):
- return self.__node.childNodes[0].wholeText
-
- @property
- def tag(self):
- return self.__node.tagName
-
- @property
- def next_siebling(self):
- return type(self)(self.__node.nextSibling)
-
-
-class TestPython:
- def test_summing_simple(self, testdir):
- testdir.makepyfile("""
- import pytest
- def test_pass():
- pass
- def test_fail():
- assert 0
- def test_skip():
- pytest.skip("")
- @pytest.mark.xfail
- def test_xfail():
- assert 0
- @pytest.mark.xfail
- def test_xpass():
- assert 1
- """)
- result, dom = runandparse(testdir)
- assert result.ret
- node = dom.find_first_by_tag("testsuite")
- node.assert_attr(name="pytest", errors=0, failures=1, skips=3, tests=2)
-
- def test_timing_function(self, testdir):
- testdir.makepyfile("""
- import time, pytest
- def setup_module():
- time.sleep(0.01)
- def teardown_module():
- time.sleep(0.01)
- def test_sleep():
- time.sleep(0.01)
- """)
- result, dom = runandparse(testdir)
- node = dom.find_first_by_tag("testsuite")
- tnode = node.find_first_by_tag("testcase")
- val = tnode["time"]
- assert round(float(val), 2) >= 0.03
-
- def test_setup_error(self, testdir):
- testdir.makepyfile("""
- def pytest_funcarg__arg(request):
- raise ValueError()
- def test_function(arg):
- pass
- """)
- result, dom = runandparse(testdir)
- assert result.ret
- node = dom.find_first_by_tag("testsuite")
- node.assert_attr(errors=1, tests=0)
- tnode = node.find_first_by_tag("testcase")
- tnode.assert_attr(
- file="test_setup_error.py",
- line="2",
- classname="test_setup_error",
- name="test_function")
- fnode = tnode.find_first_by_tag("error")
- fnode.assert_attr(message="test setup failure")
- assert "ValueError" in fnode.toxml()
-
- def test_skip_contains_name_reason(self, testdir):
- testdir.makepyfile("""
- import pytest
- def test_skip():
- pytest.skip("hello23")
- """)
- result, dom = runandparse(testdir)
- assert result.ret == 0
- node = dom.find_first_by_tag("testsuite")
- node.assert_attr(skips=1)
- tnode = node.find_first_by_tag("testcase")
- tnode.assert_attr(
- file="test_skip_contains_name_reason.py",
- line="1",
- classname="test_skip_contains_name_reason",
- name="test_skip")
- snode = tnode.find_first_by_tag("skipped")
- snode.assert_attr(type="pytest.skip", message="hello23", )
-
- def test_classname_instance(self, testdir):
- testdir.makepyfile("""
- class TestClass:
- def test_method(self):
- assert 0
- """)
- result, dom = runandparse(testdir)
- assert result.ret
- node = dom.find_first_by_tag("testsuite")
- node.assert_attr(failures=1)
- tnode = node.find_first_by_tag("testcase")
- tnode.assert_attr(
- file="test_classname_instance.py",
- line="1",
- classname="test_classname_instance.TestClass",
- name="test_method")
-
- def test_classname_nested_dir(self, testdir):
- p = testdir.tmpdir.ensure("sub", "test_hello.py")
- p.write("def test_func(): 0/0")
- result, dom = runandparse(testdir)
- assert result.ret
- node = dom.find_first_by_tag("testsuite")
- node.assert_attr(failures=1)
- tnode = node.find_first_by_tag("testcase")
- tnode.assert_attr(
- file=os.path.join("sub", "test_hello.py"),
- line="0",
- classname="sub.test_hello",
- name="test_func")
-
- def test_internal_error(self, testdir):
- testdir.makeconftest("def pytest_runtest_protocol(): 0 / 0")
- testdir.makepyfile("def test_function(): pass")
- result, dom = runandparse(testdir)
- assert result.ret
- node = dom.find_first_by_tag("testsuite")
- node.assert_attr(errors=1, tests=0)
- tnode = node.find_first_by_tag("testcase")
- tnode.assert_attr(classname="pytest", name="internal")
- fnode = tnode.find_first_by_tag("error")
- fnode.assert_attr(message="internal error")
- assert "Division" in fnode.toxml()
-
- def test_failure_function(self, testdir):
- testdir.makepyfile("""
- import sys
- def test_fail():
- print ("hello-stdout")
- sys.stderr.write("hello-stderr\\n")
- raise ValueError(42)
- """)
-
- result, dom = runandparse(testdir)
- assert result.ret
- node = dom.find_first_by_tag("testsuite")
- node.assert_attr(failures=1, tests=1)
- tnode = node.find_first_by_tag("testcase")
- tnode.assert_attr(
- file="test_failure_function.py",
- line="1",
- classname="test_failure_function",
- name="test_fail")
- fnode = tnode.find_first_by_tag("failure")
- fnode.assert_attr(message="ValueError: 42")
- assert "ValueError" in fnode.toxml()
- systemout = fnode.next_siebling
- assert systemout.tag == "system-out"
- assert "hello-stdout" in systemout.toxml()
- systemerr = systemout.next_siebling
- assert systemerr.tag == "system-err"
- assert "hello-stderr" in systemerr.toxml()
-
- def test_failure_verbose_message(self, testdir):
- testdir.makepyfile("""
- import sys
- def test_fail():
- assert 0, "An error"
- """)
-
- result, dom = runandparse(testdir)
- node = dom.find_first_by_tag("testsuite")
- tnode = node.find_first_by_tag("testcase")
- fnode = tnode.find_first_by_tag("failure")
- fnode.assert_attr(message="AssertionError: An error assert 0")
-
- def test_failure_escape(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.mark.parametrize('arg1', "<&'", ids="<&'")
- def test_func(arg1):
- print(arg1)
- assert 0
- """)
- result, dom = runandparse(testdir)
- assert result.ret
- node = dom.find_first_by_tag("testsuite")
- node.assert_attr(failures=3, tests=3)
-
- for index, char in enumerate("<&'"):
-
- tnode = node.find_nth_by_tag("testcase", index)
- tnode.assert_attr(
- file="test_failure_escape.py",
- line="1",
- classname="test_failure_escape",
- name="test_func[%s]" % char)
- sysout = tnode.find_first_by_tag('system-out')
- text = sysout.text
- assert text == '%s\n' % char
-
- def test_junit_prefixing(self, testdir):
- testdir.makepyfile("""
- def test_func():
- assert 0
- class TestHello:
- def test_hello(self):
- pass
- """)
- result, dom = runandparse(testdir, "--junitprefix=xyz")
- assert result.ret
- node = dom.find_first_by_tag("testsuite")
- node.assert_attr(failures=1, tests=2)
- tnode = node.find_first_by_tag("testcase")
- tnode.assert_attr(
- file="test_junit_prefixing.py",
- line="0",
- classname="xyz.test_junit_prefixing",
- name="test_func")
- tnode = node.find_nth_by_tag("testcase", 1)
- tnode.assert_attr(
- file="test_junit_prefixing.py",
- line="3",
- classname="xyz.test_junit_prefixing."
- "TestHello",
- name="test_hello")
-
- def test_xfailure_function(self, testdir):
- testdir.makepyfile("""
- import pytest
- def test_xfail():
- pytest.xfail("42")
- """)
- result, dom = runandparse(testdir)
- assert not result.ret
- node = dom.find_first_by_tag("testsuite")
- node.assert_attr(skips=1, tests=0)
- tnode = node.find_first_by_tag("testcase")
- tnode.assert_attr(
- file="test_xfailure_function.py",
- line="1",
- classname="test_xfailure_function",
- name="test_xfail")
- fnode = tnode.find_first_by_tag("skipped")
- fnode.assert_attr(message="expected test failure")
- # assert "ValueError" in fnode.toxml()
-
- def test_xfailure_xpass(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.mark.xfail
- def test_xpass():
- pass
- """)
- result, dom = runandparse(testdir)
- # assert result.ret
- node = dom.find_first_by_tag("testsuite")
- node.assert_attr(skips=1, tests=0)
- tnode = node.find_first_by_tag("testcase")
- tnode.assert_attr(
- file="test_xfailure_xpass.py",
- line="1",
- classname="test_xfailure_xpass",
- name="test_xpass")
- fnode = tnode.find_first_by_tag("skipped")
- fnode.assert_attr(message="xfail-marked test passes unexpectedly")
- # assert "ValueError" in fnode.toxml()
-
- def test_collect_error(self, testdir):
- testdir.makepyfile("syntax error")
- result, dom = runandparse(testdir)
- assert result.ret
- node = dom.find_first_by_tag("testsuite")
- node.assert_attr(errors=1, tests=0)
- tnode = node.find_first_by_tag("testcase")
- tnode.assert_attr(
- file="test_collect_error.py",
- name="test_collect_error")
- assert tnode["line"] is None
- fnode = tnode.find_first_by_tag("error")
- fnode.assert_attr(message="collection failure")
- assert "SyntaxError" in fnode.toxml()
-
- def test_collect_skipped(self, testdir):
- testdir.makepyfile("import pytest; pytest.skip('xyz')")
- result, dom = runandparse(testdir)
- assert result.ret == EXIT_NOTESTSCOLLECTED
- node = dom.find_first_by_tag("testsuite")
- node.assert_attr(skips=1, tests=0)
- tnode = node.find_first_by_tag("testcase")
- tnode.assert_attr(
- file="test_collect_skipped.py",
- name="test_collect_skipped")
-
- # py.test doesn't give us a line here.
- assert tnode["line"] is None
-
- fnode = tnode.find_first_by_tag("skipped")
- fnode.assert_attr(message="collection skipped")
-
- def test_unicode(self, testdir):
- value = 'hx\xc4\x85\xc4\x87\n'
- testdir.makepyfile("""
- # coding: latin1
- def test_hello():
- print (%r)
- assert 0
- """ % value)
- result, dom = runandparse(testdir)
- assert result.ret == 1
- tnode = dom.find_first_by_tag("testcase")
- fnode = tnode.find_first_by_tag("failure")
- if not sys.platform.startswith("java"):
- assert "hx" in fnode.toxml()
-
- def test_assertion_binchars(self, testdir):
- """this test did fail when the escaping wasnt strict"""
- testdir.makepyfile("""
-
- M1 = '\x01\x02\x03\x04'
- M2 = '\x01\x02\x03\x05'
-
- def test_str_compare():
- assert M1 == M2
- """)
- result, dom = runandparse(testdir)
- print(dom.toxml())
-
- def test_pass_captures_stdout(self, testdir):
- testdir.makepyfile("""
- def test_pass():
- print('hello-stdout')
- """)
- result, dom = runandparse(testdir)
- node = dom.find_first_by_tag("testsuite")
- pnode = node.find_first_by_tag("testcase")
- systemout = pnode.find_first_by_tag("system-out")
- assert "hello-stdout" in systemout.toxml()
-
- def test_pass_captures_stderr(self, testdir):
- testdir.makepyfile("""
- import sys
- def test_pass():
- sys.stderr.write('hello-stderr')
- """)
- result, dom = runandparse(testdir)
- node = dom.find_first_by_tag("testsuite")
- pnode = node.find_first_by_tag("testcase")
- systemout = pnode.find_first_by_tag("system-err")
- assert "hello-stderr" in systemout.toxml()
-
- def test_setup_error_captures_stdout(self, testdir):
- testdir.makepyfile("""
- def pytest_funcarg__arg(request):
- print('hello-stdout')
- raise ValueError()
- def test_function(arg):
- pass
- """)
- result, dom = runandparse(testdir)
- node = dom.find_first_by_tag("testsuite")
- pnode = node.find_first_by_tag("testcase")
- systemout = pnode.find_first_by_tag("system-out")
- assert "hello-stdout" in systemout.toxml()
-
- def test_setup_error_captures_stderr(self, testdir):
- testdir.makepyfile("""
- import sys
- def pytest_funcarg__arg(request):
- sys.stderr.write('hello-stderr')
- raise ValueError()
- def test_function(arg):
- pass
- """)
- result, dom = runandparse(testdir)
- node = dom.find_first_by_tag("testsuite")
- pnode = node.find_first_by_tag("testcase")
- systemout = pnode.find_first_by_tag("system-err")
- assert "hello-stderr" in systemout.toxml()
-
-
-def test_mangle_test_address():
- from _pytest.junitxml import mangle_test_address
- address = '::'.join(
- ["a/my.py.thing.py", "Class", "()", "method", "[a-1-::]"])
- newnames = mangle_test_address(address)
- assert newnames == ["a.my.py.thing", "Class", "method", "[a-1-::]"]
-
-
-def test_dont_configure_on_slaves(tmpdir):
- gotten = []
-
- class FakeConfig:
- def __init__(self):
- self.pluginmanager = self
- self.option = self
-
- junitprefix = None
- # XXX: shouldnt need tmpdir ?
- xmlpath = str(tmpdir.join('junix.xml'))
- register = gotten.append
-
- fake_config = FakeConfig()
- from _pytest import junitxml
- junitxml.pytest_configure(fake_config)
- assert len(gotten) == 1
- FakeConfig.slaveinput = None
- junitxml.pytest_configure(fake_config)
- assert len(gotten) == 1
-
-
-class TestNonPython:
- def test_summing_simple(self, testdir):
- testdir.makeconftest("""
- import pytest
- def pytest_collect_file(path, parent):
- if path.ext == ".xyz":
- return MyItem(path, parent)
- class MyItem(pytest.Item):
- def __init__(self, path, parent):
- super(MyItem, self).__init__(path.basename, parent)
- self.fspath = path
- def runtest(self):
- raise ValueError(42)
- def repr_failure(self, excinfo):
- return "custom item runtest failed"
- """)
- testdir.tmpdir.join("myfile.xyz").write("hello")
- result, dom = runandparse(testdir)
- assert result.ret
- node = dom.find_first_by_tag("testsuite")
- node.assert_attr(errors=0, failures=1, skips=0, tests=1)
- tnode = node.find_first_by_tag("testcase")
- tnode.assert_attr(name="myfile.xyz")
- fnode = tnode.find_first_by_tag("failure")
- fnode.assert_attr(message="custom item runtest failed")
- assert "custom item runtest failed" in fnode.toxml()
-
-
-def test_nullbyte(testdir):
- # A null byte can not occur in XML (see section 2.2 of the spec)
- testdir.makepyfile("""
- import sys
- def test_print_nullbyte():
- sys.stdout.write('Here the null -->' + chr(0) + '<--')
- sys.stdout.write('In repr form -->' + repr(chr(0)) + '<--')
- assert False
- """)
- xmlf = testdir.tmpdir.join('junit.xml')
- testdir.runpytest('--junitxml=%s' % xmlf)
- text = xmlf.read()
- assert '\x00' not in text
- assert '#x00' in text
-
-
-def test_nullbyte_replace(testdir):
- # Check if the null byte gets replaced
- testdir.makepyfile("""
- import sys
- def test_print_nullbyte():
- sys.stdout.write('Here the null -->' + chr(0) + '<--')
- sys.stdout.write('In repr form -->' + repr(chr(0)) + '<--')
- assert False
- """)
- xmlf = testdir.tmpdir.join('junit.xml')
- testdir.runpytest('--junitxml=%s' % xmlf)
- text = xmlf.read()
- assert '#x0' in text
-
-
-def test_invalid_xml_escape():
- # Test some more invalid xml chars, the full range should be
- # tested really but let's just thest the edges of the ranges
- # intead.
- # XXX This only tests low unicode character points for now as
- # there are some issues with the testing infrastructure for
- # the higher ones.
- # XXX Testing 0xD (\r) is tricky as it overwrites the just written
- # line in the output, so we skip it too.
- global unichr
- try:
- unichr(65)
- except NameError:
- unichr = chr
- invalid = (0x00, 0x1, 0xB, 0xC, 0xE, 0x19, 27, # issue #126
- 0xD800, 0xDFFF, 0xFFFE, 0x0FFFF) # , 0x110000)
- valid = (0x9, 0xA, 0x20, )
- # 0xD, 0xD7FF, 0xE000, 0xFFFD, 0x10000, 0x10FFFF)
-
- from _pytest.junitxml import bin_xml_escape
-
- for i in invalid:
- got = bin_xml_escape(unichr(i)).uniobj
- if i <= 0xFF:
- expected = '#x%02X' % i
- else:
- expected = '#x%04X' % i
- assert got == expected
- for i in valid:
- assert chr(i) == bin_xml_escape(unichr(i)).uniobj
-
-
-def test_logxml_path_expansion(tmpdir, monkeypatch):
- home_tilde = py.path.local(os.path.expanduser('~')).join('test.xml')
-
- xml_tilde = LogXML('~%stest.xml' % tmpdir.sep, None)
- assert xml_tilde.logfile == home_tilde
-
- # this is here for when $HOME is not set correct
- monkeypatch.setenv("HOME", tmpdir)
- home_var = os.path.normpath(os.path.expandvars('$HOME/test.xml'))
-
- xml_var = LogXML('$HOME%stest.xml' % tmpdir.sep, None)
- assert xml_var.logfile == home_var
-
-
-def test_logxml_changingdir(testdir):
- testdir.makepyfile("""
- def test_func():
- import os
- os.chdir("a")
- """)
- testdir.tmpdir.mkdir("a")
- result = testdir.runpytest("--junitxml=a/x.xml")
- assert result.ret == 0
- assert testdir.tmpdir.join("a/x.xml").check()
-
-
-def test_logxml_makedir(testdir):
- """--junitxml should automatically create directories for the xml file"""
- testdir.makepyfile("""
- def test_pass():
- pass
- """)
- result = testdir.runpytest("--junitxml=path/to/results.xml")
- assert result.ret == 0
- assert testdir.tmpdir.join("path/to/results.xml").check()
-
-
-def test_escaped_parametrized_names_xml(testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.mark.parametrize('char', ["\\x00"])
- def test_func(char):
- assert char
- """)
- result, dom = runandparse(testdir)
- assert result.ret == 0
- node = dom.find_first_by_tag("testcase")
- node.assert_attr(name="test_func[#x00]")
-
-
-def test_double_colon_split_function_issue469(testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.mark.parametrize('param', ["double::colon"])
- def test_func(param):
- pass
- """)
- result, dom = runandparse(testdir)
- assert result.ret == 0
- node = dom.find_first_by_tag("testcase")
- node.assert_attr(classname="test_double_colon_split_function_issue469")
- node.assert_attr(name='test_func[double::colon]')
-
-
-def test_double_colon_split_method_issue469(testdir):
- testdir.makepyfile("""
- import pytest
- class TestClass:
- @pytest.mark.parametrize('param', ["double::colon"])
- def test_func(self, param):
- pass
- """)
- result, dom = runandparse(testdir)
- assert result.ret == 0
- node = dom.find_first_by_tag("testcase")
- node.assert_attr(
- classname="test_double_colon_split_method_issue469.TestClass")
- node.assert_attr(name='test_func[double::colon]')
-
-
-def test_unicode_issue368(testdir):
- path = testdir.tmpdir.join("test.xml")
- log = LogXML(str(path), None)
- ustr = py.builtin._totext("ВНИ!", "utf-8")
- from _pytest.runner import BaseReport
-
- class Report(BaseReport):
- longrepr = ustr
- sections = []
- nodeid = "something"
- location = 'tests/filename.py', 42, 'TestClass.method'
-
- test_report = Report()
-
- # hopefully this is not too brittle ...
- log.pytest_sessionstart()
- node_reporter = log._opentestcase(test_report)
- node_reporter.append_failure(test_report)
- node_reporter.append_collect_error(test_report)
- node_reporter.append_collect_skipped(test_report)
- node_reporter.append_error(test_report)
- test_report.longrepr = "filename", 1, ustr
- node_reporter.append_skipped(test_report)
- test_report.longrepr = "filename", 1, "Skipped: 卡嘣嘣"
- node_reporter.append_skipped(test_report)
- test_report.wasxfail = ustr
- node_reporter.append_skipped(test_report)
- log.pytest_sessionfinish()
-
-
-def test_record_property(testdir):
- testdir.makepyfile("""
- import pytest
-
- @pytest.fixture
- def other(record_xml_property):
- record_xml_property("bar", 1)
- def test_record(record_xml_property, other):
- record_xml_property("foo", "<1");
- """)
- result, dom = runandparse(testdir, '-rw')
- node = dom.find_first_by_tag("testsuite")
- tnode = node.find_first_by_tag("testcase")
- psnode = tnode.find_first_by_tag('properties')
- pnodes = psnode.find_by_tag('property')
- pnodes[0].assert_attr(name="bar", value="1")
- pnodes[1].assert_attr(name="foo", value="<1")
- result.stdout.fnmatch_lines('*C3*test_record_property.py*experimental*')
-
-
-def test_record_property_same_name(testdir):
- testdir.makepyfile("""
- def test_record_with_same_name(record_xml_property):
- record_xml_property("foo", "bar")
- record_xml_property("foo", "baz")
- """)
- result, dom = runandparse(testdir, '-rw')
- node = dom.find_first_by_tag("testsuite")
- tnode = node.find_first_by_tag("testcase")
- psnode = tnode.find_first_by_tag('properties')
- pnodes = psnode.find_by_tag('property')
- pnodes[0].assert_attr(name="foo", value="bar")
- pnodes[1].assert_attr(name="foo", value="baz")
-
-
-def test_random_report_log_xdist(testdir):
- """xdist calls pytest_runtest_logreport as they are executed by the slaves,
- with nodes from several nodes overlapping, so junitxml must cope with that
- to produce correct reports. #1064
- """
- pytest.importorskip('xdist')
- testdir.makepyfile("""
- import pytest, time
- @pytest.mark.parametrize('i', list(range(30)))
- def test_x(i):
- assert i != 22
- """)
- _, dom = runandparse(testdir, '-n2')
- suite_node = dom.find_first_by_tag("testsuite")
- failed = []
- for case_node in suite_node.find_by_tag("testcase"):
- if case_node.find_first_by_tag('failure'):
- failed.append(case_node['name'])
-
- assert failed == ['test_x[22]']
-
-
-def test_runs_twice(testdir):
- f = testdir.makepyfile('''
- def test_pass():
- pass
- ''')
-
- result, dom = runandparse(testdir, f, f)
- assert 'INTERNALERROR' not in result.stdout.str()
- first, second = [x['classname'] for x in dom.find_by_tag("testcase")]
- assert first == second
-
-
-@pytest.mark.xfail(reason='hangs', run=False)
-def test_runs_twice_xdist(testdir):
- pytest.importorskip('xdist')
- f = testdir.makepyfile('''
- def test_pass():
- pass
- ''')
-
- result, dom = runandparse(
- testdir, f,
- '--dist', 'each', '--tx', '2*popen',)
- assert 'INTERNALERROR' not in result.stdout.str()
- first, second = [x['classname'] for x in dom.find_by_tag("testcase")]
- assert first == second
-
-
-def test_fancy_items_regression(testdir):
- # issue 1259
- testdir.makeconftest("""
- import pytest
- class FunItem(pytest.Item):
- def runtest(self):
- pass
- class NoFunItem(pytest.Item):
- def runtest(self):
- pass
-
- class FunCollector(pytest.File):
- def collect(self):
- return [
- FunItem('a', self),
- NoFunItem('a', self),
- NoFunItem('b', self),
- ]
-
- def pytest_collect_file(path, parent):
- if path.check(ext='.py'):
- return FunCollector(path, parent)
- """)
-
- testdir.makepyfile('''
- def test_pass():
- pass
- ''')
-
- result, dom = runandparse(testdir)
-
- assert 'INTERNALERROR' not in result.stdout.str()
-
- items = sorted(
- '%(classname)s %(name)s %(file)s' % x
-
- for x in dom.find_by_tag("testcase"))
- import pprint
- pprint.pprint(items)
- assert items == [
- u'conftest a conftest.py',
- u'conftest a conftest.py',
- u'conftest b conftest.py',
- u'test_fancy_items_regression a test_fancy_items_regression.py',
- u'test_fancy_items_regression a test_fancy_items_regression.py',
- u'test_fancy_items_regression b test_fancy_items_regression.py',
- u'test_fancy_items_regression test_pass'
- u' test_fancy_items_regression.py',
- ]
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_mark.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_mark.py
deleted file mode 100644
index aa1be6f7c66..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_mark.py
+++ /dev/null
@@ -1,672 +0,0 @@
-import os
-
-import py, pytest
-from _pytest.mark import MarkGenerator as Mark
-
-class TestMark:
- def test_markinfo_repr(self):
- from _pytest.mark import MarkInfo
- m = MarkInfo("hello", (1,2), {})
- repr(m)
-
- def test_pytest_exists_in_namespace_all(self):
- assert 'mark' in py.test.__all__
- assert 'mark' in pytest.__all__
-
- def test_pytest_mark_notcallable(self):
- mark = Mark()
- pytest.raises((AttributeError, TypeError), mark)
-
- def test_pytest_mark_name_starts_with_underscore(self):
- mark = Mark()
- pytest.raises(AttributeError, getattr, mark, '_some_name')
-
- def test_pytest_mark_bare(self):
- mark = Mark()
- def f():
- pass
- mark.hello(f)
- assert f.hello
-
- def test_pytest_mark_keywords(self):
- mark = Mark()
- def f():
- pass
- mark.world(x=3, y=4)(f)
- assert f.world
- assert f.world.kwargs['x'] == 3
- assert f.world.kwargs['y'] == 4
-
- def test_apply_multiple_and_merge(self):
- mark = Mark()
- def f():
- pass
- mark.world
- mark.world(x=3)(f)
- assert f.world.kwargs['x'] == 3
- mark.world(y=4)(f)
- assert f.world.kwargs['x'] == 3
- assert f.world.kwargs['y'] == 4
- mark.world(y=1)(f)
- assert f.world.kwargs['y'] == 1
- assert len(f.world.args) == 0
-
- def test_pytest_mark_positional(self):
- mark = Mark()
- def f():
- pass
- mark.world("hello")(f)
- assert f.world.args[0] == "hello"
- mark.world("world")(f)
-
- def test_pytest_mark_positional_func_and_keyword(self):
- mark = Mark()
- def f():
- raise Exception
- m = mark.world(f, omega="hello")
- def g():
- pass
- assert m(g) == g
- assert g.world.args[0] is f
- assert g.world.kwargs["omega"] == "hello"
-
- def test_pytest_mark_reuse(self):
- mark = Mark()
- def f():
- pass
- w = mark.some
- w("hello", reason="123")(f)
- assert f.some.args[0] == "hello"
- assert f.some.kwargs['reason'] == "123"
- def g():
- pass
- w("world", reason2="456")(g)
- assert g.some.args[0] == "world"
- assert 'reason' not in g.some.kwargs
- assert g.some.kwargs['reason2'] == "456"
-
-
-def test_marked_class_run_twice(testdir, request):
- """Test fails file is run twice that contains marked class.
- See issue#683.
- """
- py_file = testdir.makepyfile("""
- import pytest
- @pytest.mark.parametrize('abc', [1, 2, 3])
- class Test1(object):
- def test_1(self, abc):
- assert abc in [1, 2, 3]
- """)
- file_name = os.path.basename(py_file.strpath)
- rec = testdir.inline_run(file_name, file_name)
- rec.assertoutcome(passed=6)
-
-
-def test_ini_markers(testdir):
- testdir.makeini("""
- [pytest]
- markers =
- a1: this is a webtest marker
- a2: this is a smoke marker
- """)
- testdir.makepyfile("""
- def test_markers(pytestconfig):
- markers = pytestconfig.getini("markers")
- print (markers)
- assert len(markers) >= 2
- assert markers[0].startswith("a1:")
- assert markers[1].startswith("a2:")
- """)
- rec = testdir.inline_run()
- rec.assertoutcome(passed=1)
-
-def test_markers_option(testdir):
- testdir.makeini("""
- [pytest]
- markers =
- a1: this is a webtest marker
- a1some: another marker
- """)
- result = testdir.runpytest("--markers", )
- result.stdout.fnmatch_lines([
- "*a1*this is a webtest*",
- "*a1some*another marker",
- ])
-
-def test_markers_option_with_plugin_in_current_dir(testdir):
- testdir.makeconftest('pytest_plugins = "flip_flop"')
- testdir.makepyfile(flip_flop="""\
- def pytest_configure(config):
- config.addinivalue_line("markers", "flip:flop")
-
- def pytest_generate_tests(metafunc):
- try:
- mark = metafunc.function.flipper
- except AttributeError:
- return
- metafunc.parametrize("x", (10, 20))""")
- testdir.makepyfile("""\
- import pytest
- @pytest.mark.flipper
- def test_example(x):
- assert x""")
-
- result = testdir.runpytest("--markers")
- result.stdout.fnmatch_lines(["*flip*flop*"])
-
-
-def test_mark_on_pseudo_function(testdir):
- testdir.makepyfile("""
- import pytest
-
- @pytest.mark.r(lambda x: 0/0)
- def test_hello():
- pass
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
-def test_strict_prohibits_unregistered_markers(testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.mark.unregisteredmark
- def test_hello():
- pass
- """)
- result = testdir.runpytest("--strict")
- assert result.ret != 0
- result.stdout.fnmatch_lines([
- "*unregisteredmark*not*registered*",
- ])
-
-@pytest.mark.parametrize("spec", [
- ("xyz", ("test_one",)),
- ("xyz and xyz2", ()),
- ("xyz2", ("test_two",)),
- ("xyz or xyz2", ("test_one", "test_two"),)
-])
-def test_mark_option(spec, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.mark.xyz
- def test_one():
- pass
- @pytest.mark.xyz2
- def test_two():
- pass
- """)
- opt, passed_result = spec
- rec = testdir.inline_run("-m", opt)
- passed, skipped, fail = rec.listoutcomes()
- passed = [x.nodeid.split("::")[-1] for x in passed]
- assert len(passed) == len(passed_result)
- assert list(passed) == list(passed_result)
-
-@pytest.mark.parametrize("spec", [
- ("interface", ("test_interface",)),
- ("not interface", ("test_nointer",)),
-])
-def test_mark_option_custom(spec, testdir):
- testdir.makeconftest("""
- import pytest
- def pytest_collection_modifyitems(items):
- for item in items:
- if "interface" in item.nodeid:
- item.keywords["interface"] = pytest.mark.interface
- """)
- testdir.makepyfile("""
- def test_interface():
- pass
- def test_nointer():
- pass
- """)
- opt, passed_result = spec
- rec = testdir.inline_run("-m", opt)
- passed, skipped, fail = rec.listoutcomes()
- passed = [x.nodeid.split("::")[-1] for x in passed]
- assert len(passed) == len(passed_result)
- assert list(passed) == list(passed_result)
-
-@pytest.mark.parametrize("spec", [
- ("interface", ("test_interface",)),
- ("not interface", ("test_nointer", "test_pass")),
- ("pass", ("test_pass",)),
- ("not pass", ("test_interface", "test_nointer")),
-])
-def test_keyword_option_custom(spec, testdir):
- testdir.makepyfile("""
- def test_interface():
- pass
- def test_nointer():
- pass
- def test_pass():
- pass
- """)
- opt, passed_result = spec
- rec = testdir.inline_run("-k", opt)
- passed, skipped, fail = rec.listoutcomes()
- passed = [x.nodeid.split("::")[-1] for x in passed]
- assert len(passed) == len(passed_result)
- assert list(passed) == list(passed_result)
-
-
-@pytest.mark.parametrize("spec", [
- ("None", ("test_func[None]",)),
- ("1.3", ("test_func[1.3]",)),
- ("2-3", ("test_func[2-3]",))
-])
-def test_keyword_option_parametrize(spec, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.mark.parametrize("arg", [None, 1.3, "2-3"])
- def test_func(arg):
- pass
- """)
- opt, passed_result = spec
- rec = testdir.inline_run("-k", opt)
- passed, skipped, fail = rec.listoutcomes()
- passed = [x.nodeid.split("::")[-1] for x in passed]
- assert len(passed) == len(passed_result)
- assert list(passed) == list(passed_result)
-
-
-def test_parametrized_collected_from_command_line(testdir):
- """Parametrized test not collected if test named specified
- in command line issue#649.
- """
- py_file = testdir.makepyfile("""
- import pytest
- @pytest.mark.parametrize("arg", [None, 1.3, "2-3"])
- def test_func(arg):
- pass
- """)
- file_name = os.path.basename(py_file.strpath)
- rec = testdir.inline_run(file_name + "::" + "test_func")
- rec.assertoutcome(passed=3)
-
-
-class TestFunctional:
-
- def test_mark_per_function(self, testdir):
- p = testdir.makepyfile("""
- import pytest
- @pytest.mark.hello
- def test_hello():
- assert hasattr(test_hello, 'hello')
- """)
- result = testdir.runpytest(p)
- result.stdout.fnmatch_lines(["*1 passed*"])
-
- def test_mark_per_module(self, testdir):
- item = testdir.getitem("""
- import pytest
- pytestmark = pytest.mark.hello
- def test_func():
- pass
- """)
- keywords = item.keywords
- assert 'hello' in keywords
-
- def test_marklist_per_class(self, testdir):
- item = testdir.getitem("""
- import pytest
- class TestClass:
- pytestmark = [pytest.mark.hello, pytest.mark.world]
- def test_func(self):
- assert TestClass.test_func.hello
- assert TestClass.test_func.world
- """)
- keywords = item.keywords
- assert 'hello' in keywords
-
- def test_marklist_per_module(self, testdir):
- item = testdir.getitem("""
- import pytest
- pytestmark = [pytest.mark.hello, pytest.mark.world]
- class TestClass:
- def test_func(self):
- assert TestClass.test_func.hello
- assert TestClass.test_func.world
- """)
- keywords = item.keywords
- assert 'hello' in keywords
- assert 'world' in keywords
-
- def test_mark_per_class_decorator(self, testdir):
- item = testdir.getitem("""
- import pytest
- @pytest.mark.hello
- class TestClass:
- def test_func(self):
- assert TestClass.test_func.hello
- """)
- keywords = item.keywords
- assert 'hello' in keywords
-
- def test_mark_per_class_decorator_plus_existing_dec(self, testdir):
- item = testdir.getitem("""
- import pytest
- @pytest.mark.hello
- class TestClass:
- pytestmark = pytest.mark.world
- def test_func(self):
- assert TestClass.test_func.hello
- assert TestClass.test_func.world
- """)
- keywords = item.keywords
- assert 'hello' in keywords
- assert 'world' in keywords
-
- def test_merging_markers(self, testdir):
- p = testdir.makepyfile("""
- import pytest
- pytestmark = pytest.mark.hello("pos1", x=1, y=2)
- class TestClass:
- # classlevel overrides module level
- pytestmark = pytest.mark.hello(x=3)
- @pytest.mark.hello("pos0", z=4)
- def test_func(self):
- pass
- """)
- items, rec = testdir.inline_genitems(p)
- item, = items
- keywords = item.keywords
- marker = keywords['hello']
- assert marker.args == ("pos0", "pos1")
- assert marker.kwargs == {'x': 1, 'y': 2, 'z': 4}
-
- # test the new __iter__ interface
- l = list(marker)
- assert len(l) == 3
- assert l[0].args == ("pos0",)
- assert l[1].args == ()
- assert l[2].args == ("pos1", )
-
- @pytest.mark.xfail(reason='unfixed')
- def test_merging_markers_deep(self, testdir):
- # issue 199 - propagate markers into nested classes
- p = testdir.makepyfile("""
- import pytest
- class TestA:
- pytestmark = pytest.mark.a
- def test_b(self):
- assert True
- class TestC:
- # this one didnt get marked
- def test_d(self):
- assert True
- """)
- items, rec = testdir.inline_genitems(p)
- for item in items:
- print (item, item.keywords)
- assert 'a' in item.keywords
-
- def test_mark_decorator_subclass_does_not_propagate_to_base(self, testdir):
- p = testdir.makepyfile("""
- import pytest
-
- @pytest.mark.a
- class Base: pass
-
- @pytest.mark.b
- class Test1(Base):
- def test_foo(self): pass
-
- class Test2(Base):
- def test_bar(self): pass
- """)
- items, rec = testdir.inline_genitems(p)
- self.assert_markers(items, test_foo=('a', 'b'), test_bar=('a',))
-
- def test_mark_decorator_baseclasses_merged(self, testdir):
- p = testdir.makepyfile("""
- import pytest
-
- @pytest.mark.a
- class Base: pass
-
- @pytest.mark.b
- class Base2(Base): pass
-
- @pytest.mark.c
- class Test1(Base2):
- def test_foo(self): pass
-
- class Test2(Base2):
- @pytest.mark.d
- def test_bar(self): pass
- """)
- items, rec = testdir.inline_genitems(p)
- self.assert_markers(items, test_foo=('a', 'b', 'c'),
- test_bar=('a', 'b', 'd'))
-
- def test_mark_with_wrong_marker(self, testdir):
- reprec = testdir.inline_runsource("""
- import pytest
- class pytestmark:
- pass
- def test_func():
- pass
- """)
- l = reprec.getfailedcollections()
- assert len(l) == 1
- assert "TypeError" in str(l[0].longrepr)
-
- def test_mark_dynamically_in_funcarg(self, testdir):
- testdir.makeconftest("""
- import pytest
- def pytest_funcarg__arg(request):
- request.applymarker(pytest.mark.hello)
- def pytest_terminal_summary(terminalreporter):
- l = terminalreporter.stats['passed']
- terminalreporter.writer.line("keyword: %s" % l[0].keywords)
- """)
- testdir.makepyfile("""
- def test_func(arg):
- pass
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "keyword: *hello*"
- ])
-
- def test_merging_markers_two_functions(self, testdir):
- p = testdir.makepyfile("""
- import pytest
- @pytest.mark.hello("pos1", z=4)
- @pytest.mark.hello("pos0", z=3)
- def test_func():
- pass
- """)
- items, rec = testdir.inline_genitems(p)
- item, = items
- keywords = item.keywords
- marker = keywords['hello']
- l = list(marker)
- assert len(l) == 2
- assert l[0].args == ("pos0",)
- assert l[1].args == ("pos1",)
-
- def test_no_marker_match_on_unmarked_names(self, testdir):
- p = testdir.makepyfile("""
- import pytest
- @pytest.mark.shouldmatch
- def test_marked():
- assert 1
-
- def test_unmarked():
- assert 1
- """)
- reprec = testdir.inline_run("-m", "test_unmarked", p)
- passed, skipped, failed = reprec.listoutcomes()
- assert len(passed) + len(skipped) + len(failed) == 0
- dlist = reprec.getcalls("pytest_deselected")
- deselected_tests = dlist[0].items
- assert len(deselected_tests) == 2
-
- def test_keywords_at_node_level(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.fixture(scope="session", autouse=True)
- def some(request):
- request.keywords["hello"] = 42
- assert "world" not in request.keywords
-
- @pytest.fixture(scope="function", autouse=True)
- def funcsetup(request):
- assert "world" in request.keywords
- assert "hello" in request.keywords
-
- @pytest.mark.world
- def test_function():
- pass
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
- def test_keyword_added_for_session(self, testdir):
- testdir.makeconftest("""
- import pytest
- def pytest_collection_modifyitems(session):
- session.add_marker("mark1")
- session.add_marker(pytest.mark.mark2)
- session.add_marker(pytest.mark.mark3)
- pytest.raises(ValueError, lambda:
- session.add_marker(10))
- """)
- testdir.makepyfile("""
- def test_some(request):
- assert "mark1" in request.keywords
- assert "mark2" in request.keywords
- assert "mark3" in request.keywords
- assert 10 not in request.keywords
- marker = request.node.get_marker("mark1")
- assert marker.name == "mark1"
- assert marker.args == ()
- assert marker.kwargs == {}
- """)
- reprec = testdir.inline_run("-m", "mark1")
- reprec.assertoutcome(passed=1)
-
- def assert_markers(self, items, **expected):
- """assert that given items have expected marker names applied to them.
- expected should be a dict of (item name -> seq of expected marker names)
-
- .. note:: this could be moved to ``testdir`` if proven to be useful
- to other modules.
- """
- from _pytest.mark import MarkInfo
- items = dict((x.name, x) for x in items)
- for name, expected_markers in expected.items():
- markers = items[name].keywords._markers
- marker_names = set([name for (name, v) in markers.items()
- if isinstance(v, MarkInfo)])
- assert marker_names == set(expected_markers)
-
-
-class TestKeywordSelection:
- def test_select_simple(self, testdir):
- file_test = testdir.makepyfile("""
- def test_one():
- assert 0
- class TestClass(object):
- def test_method_one(self):
- assert 42 == 43
- """)
- def check(keyword, name):
- reprec = testdir.inline_run("-s", "-k", keyword, file_test)
- passed, skipped, failed = reprec.listoutcomes()
- assert len(failed) == 1
- assert failed[0].nodeid.split("::")[-1] == name
- assert len(reprec.getcalls('pytest_deselected')) == 1
-
- for keyword in ['test_one', 'est_on']:
- check(keyword, 'test_one')
- check('TestClass and test', 'test_method_one')
-
- @pytest.mark.parametrize("keyword", [
- 'xxx', 'xxx and test_2', 'TestClass', 'xxx and not test_1',
- 'TestClass and test_2', 'xxx and TestClass and test_2'])
- def test_select_extra_keywords(self, testdir, keyword):
- p = testdir.makepyfile(test_select="""
- def test_1():
- pass
- class TestClass:
- def test_2(self):
- pass
- """)
- testdir.makepyfile(conftest="""
- import pytest
- @pytest.hookimpl(hookwrapper=True)
- def pytest_pycollect_makeitem(name):
- outcome = yield
- if name == "TestClass":
- item = outcome.get_result()
- item.extra_keyword_matches.add("xxx")
- """)
- reprec = testdir.inline_run(p.dirpath(), '-s', '-k', keyword)
- py.builtin.print_("keyword", repr(keyword))
- passed, skipped, failed = reprec.listoutcomes()
- assert len(passed) == 1
- assert passed[0].nodeid.endswith("test_2")
- dlist = reprec.getcalls("pytest_deselected")
- assert len(dlist) == 1
- assert dlist[0].items[0].name == 'test_1'
-
- def test_select_starton(self, testdir):
- threepass = testdir.makepyfile(test_threepass="""
- def test_one(): assert 1
- def test_two(): assert 1
- def test_three(): assert 1
- """)
- reprec = testdir.inline_run("-k", "test_two:", threepass)
- passed, skipped, failed = reprec.listoutcomes()
- assert len(passed) == 2
- assert not failed
- dlist = reprec.getcalls("pytest_deselected")
- assert len(dlist) == 1
- item = dlist[0].items[0]
- assert item.name == "test_one"
-
- def test_keyword_extra(self, testdir):
- p = testdir.makepyfile("""
- def test_one():
- assert 0
- test_one.mykeyword = True
- """)
- reprec = testdir.inline_run("-k", "mykeyword", p)
- passed, skipped, failed = reprec.countoutcomes()
- assert failed == 1
-
- @pytest.mark.xfail
- def test_keyword_extra_dash(self, testdir):
- p = testdir.makepyfile("""
- def test_one():
- assert 0
- test_one.mykeyword = True
- """)
- # with argparse the argument to an option cannot
- # start with '-'
- reprec = testdir.inline_run("-k", "-mykeyword", p)
- passed, skipped, failed = reprec.countoutcomes()
- assert passed + skipped + failed == 0
-
- def test_no_magic_values(self, testdir):
- """Make sure the tests do not match on magic values,
- no double underscored values, like '__dict__',
- and no instance values, like '()'.
- """
- p = testdir.makepyfile("""
- def test_one(): assert 1
- """)
- def assert_test_is_not_selected(keyword):
- reprec = testdir.inline_run("-k", keyword, p)
- passed, skipped, failed = reprec.countoutcomes()
- dlist = reprec.getcalls("pytest_deselected")
- assert passed + skipped + failed == 0
- deselected_tests = dlist[0].items
- assert len(deselected_tests) == 1
-
- assert_test_is_not_selected("__")
- assert_test_is_not_selected("()")
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_monkeypatch.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_monkeypatch.py
deleted file mode 100644
index 048c942c867..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_monkeypatch.py
+++ /dev/null
@@ -1,330 +0,0 @@
-import os
-import sys
-import textwrap
-
-import pytest
-from _pytest.monkeypatch import monkeypatch as MonkeyPatch
-
-
-def pytest_funcarg__mp(request):
- cwd = os.getcwd()
- sys_path = list(sys.path)
-
- def cleanup():
- sys.path[:] = sys_path
- os.chdir(cwd)
-
- request.addfinalizer(cleanup)
- return MonkeyPatch()
-
-
-def test_setattr():
- class A:
- x = 1
-
- monkeypatch = MonkeyPatch()
- pytest.raises(AttributeError, "monkeypatch.setattr(A, 'notexists', 2)")
- monkeypatch.setattr(A, 'y', 2, raising=False)
- assert A.y == 2
- monkeypatch.undo()
- assert not hasattr(A, 'y')
-
- monkeypatch = MonkeyPatch()
- monkeypatch.setattr(A, 'x', 2)
- assert A.x == 2
- monkeypatch.setattr(A, 'x', 3)
- assert A.x == 3
- monkeypatch.undo()
- assert A.x == 1
-
- A.x = 5
- monkeypatch.undo() # double-undo makes no modification
- assert A.x == 5
-
-
-class TestSetattrWithImportPath:
- def test_string_expression(self, monkeypatch):
- monkeypatch.setattr("os.path.abspath", lambda x: "hello2")
- assert os.path.abspath("123") == "hello2"
-
- def test_string_expression_class(self, monkeypatch):
- monkeypatch.setattr("_pytest.config.Config", 42)
- import _pytest
- assert _pytest.config.Config == 42
-
- def test_unicode_string(self, monkeypatch):
- monkeypatch.setattr("_pytest.config.Config", 42)
- import _pytest
- assert _pytest.config.Config == 42
- monkeypatch.delattr("_pytest.config.Config")
-
- def test_wrong_target(self, monkeypatch):
- pytest.raises(TypeError, lambda: monkeypatch.setattr(None, None))
-
- def test_unknown_import(self, monkeypatch):
- pytest.raises(ImportError,
- lambda: monkeypatch.setattr("unkn123.classx", None))
-
- def test_unknown_attr(self, monkeypatch):
- pytest.raises(AttributeError,
- lambda: monkeypatch.setattr("os.path.qweqwe", None))
-
- def test_unknown_attr_non_raising(self, monkeypatch):
- # https://github.com/pytest-dev/pytest/issues/746
- monkeypatch.setattr('os.path.qweqwe', 42, raising=False)
- assert os.path.qweqwe == 42
-
- def test_delattr(self, monkeypatch):
- monkeypatch.delattr("os.path.abspath")
- assert not hasattr(os.path, "abspath")
- monkeypatch.undo()
- assert os.path.abspath
-
-
-def test_delattr():
- class A:
- x = 1
-
- monkeypatch = MonkeyPatch()
- monkeypatch.delattr(A, 'x')
- assert not hasattr(A, 'x')
- monkeypatch.undo()
- assert A.x == 1
-
- monkeypatch = MonkeyPatch()
- monkeypatch.delattr(A, 'x')
- pytest.raises(AttributeError, "monkeypatch.delattr(A, 'y')")
- monkeypatch.delattr(A, 'y', raising=False)
- monkeypatch.setattr(A, 'x', 5, raising=False)
- assert A.x == 5
- monkeypatch.undo()
- assert A.x == 1
-
-
-def test_setitem():
- d = {'x': 1}
- monkeypatch = MonkeyPatch()
- monkeypatch.setitem(d, 'x', 2)
- monkeypatch.setitem(d, 'y', 1700)
- monkeypatch.setitem(d, 'y', 1700)
- assert d['x'] == 2
- assert d['y'] == 1700
- monkeypatch.setitem(d, 'x', 3)
- assert d['x'] == 3
- monkeypatch.undo()
- assert d['x'] == 1
- assert 'y' not in d
- d['x'] = 5
- monkeypatch.undo()
- assert d['x'] == 5
-
-
-def test_setitem_deleted_meanwhile():
- d = {}
- monkeypatch = MonkeyPatch()
- monkeypatch.setitem(d, 'x', 2)
- del d['x']
- monkeypatch.undo()
- assert not d
-
-
-@pytest.mark.parametrize("before", [True, False])
-def test_setenv_deleted_meanwhile(before):
- key = "qwpeoip123"
- if before:
- os.environ[key] = "world"
- monkeypatch = MonkeyPatch()
- monkeypatch.setenv(key, 'hello')
- del os.environ[key]
- monkeypatch.undo()
- if before:
- assert os.environ[key] == "world"
- del os.environ[key]
- else:
- assert key not in os.environ
-
-
-def test_delitem():
- d = {'x': 1}
- monkeypatch = MonkeyPatch()
- monkeypatch.delitem(d, 'x')
- assert 'x' not in d
- monkeypatch.delitem(d, 'y', raising=False)
- pytest.raises(KeyError, "monkeypatch.delitem(d, 'y')")
- assert not d
- monkeypatch.setitem(d, 'y', 1700)
- assert d['y'] == 1700
- d['hello'] = 'world'
- monkeypatch.setitem(d, 'x', 1500)
- assert d['x'] == 1500
- monkeypatch.undo()
- assert d == {'hello': 'world', 'x': 1}
-
-
-def test_setenv():
- monkeypatch = MonkeyPatch()
- monkeypatch.setenv('XYZ123', 2)
- import os
- assert os.environ['XYZ123'] == "2"
- monkeypatch.undo()
- assert 'XYZ123' not in os.environ
-
-
-def test_delenv():
- name = 'xyz1234'
- assert name not in os.environ
- monkeypatch = MonkeyPatch()
- pytest.raises(KeyError, "monkeypatch.delenv(%r, raising=True)" % name)
- monkeypatch.delenv(name, raising=False)
- monkeypatch.undo()
- os.environ[name] = "1"
- try:
- monkeypatch = MonkeyPatch()
- monkeypatch.delenv(name)
- assert name not in os.environ
- monkeypatch.setenv(name, "3")
- assert os.environ[name] == "3"
- monkeypatch.undo()
- assert os.environ[name] == "1"
- finally:
- if name in os.environ:
- del os.environ[name]
-
-
-def test_setenv_prepend():
- import os
- monkeypatch = MonkeyPatch()
- monkeypatch.setenv('XYZ123', 2, prepend="-")
- assert os.environ['XYZ123'] == "2"
- monkeypatch.setenv('XYZ123', 3, prepend="-")
- assert os.environ['XYZ123'] == "3-2"
- monkeypatch.undo()
- assert 'XYZ123' not in os.environ
-
-
-def test_monkeypatch_plugin(testdir):
- reprec = testdir.inline_runsource("""
- def test_method(monkeypatch):
- assert monkeypatch.__class__.__name__ == "monkeypatch"
- """)
- res = reprec.countoutcomes()
- assert tuple(res) == (1, 0, 0), res
-
-
-def test_syspath_prepend(mp):
- old = list(sys.path)
- mp.syspath_prepend('world')
- mp.syspath_prepend('hello')
- assert sys.path[0] == "hello"
- assert sys.path[1] == "world"
- mp.undo()
- assert sys.path == old
- mp.undo()
- assert sys.path == old
-
-
-def test_syspath_prepend_double_undo(mp):
- mp.syspath_prepend('hello world')
- mp.undo()
- sys.path.append('more hello world')
- mp.undo()
- assert sys.path[-1] == 'more hello world'
-
-
-def test_chdir_with_path_local(mp, tmpdir):
- mp.chdir(tmpdir)
- assert os.getcwd() == tmpdir.strpath
-
-
-def test_chdir_with_str(mp, tmpdir):
- mp.chdir(tmpdir.strpath)
- assert os.getcwd() == tmpdir.strpath
-
-
-def test_chdir_undo(mp, tmpdir):
- cwd = os.getcwd()
- mp.chdir(tmpdir)
- mp.undo()
- assert os.getcwd() == cwd
-
-
-def test_chdir_double_undo(mp, tmpdir):
- mp.chdir(tmpdir.strpath)
- mp.undo()
- tmpdir.chdir()
- mp.undo()
- assert os.getcwd() == tmpdir.strpath
-
-
-def test_issue185_time_breaks(testdir):
- testdir.makepyfile("""
- import time
- def test_m(monkeypatch):
- def f():
- raise Exception
- monkeypatch.setattr(time, "time", f)
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines("""
- *1 passed*
- """)
-
-
-def test_importerror(testdir):
- p = testdir.mkpydir("package")
- p.join("a.py").write(textwrap.dedent("""\
- import doesnotexist
-
- x = 1
- """))
- testdir.tmpdir.join("test_importerror.py").write(textwrap.dedent("""\
- def test_importerror(monkeypatch):
- monkeypatch.setattr('package.a.x', 2)
- """))
- result = testdir.runpytest()
- result.stdout.fnmatch_lines("""
- *import error in package.a: No module named {0}doesnotexist{0}*
- """.format("'" if sys.version_info > (3, 0) else ""))
-
-
-class SampleNew(object):
- @staticmethod
- def hello():
- return True
-
-
-class SampleNewInherit(SampleNew):
- pass
-
-
-class SampleOld:
- # oldstyle on python2
- @staticmethod
- def hello():
- return True
-
-
-class SampleOldInherit(SampleOld):
- pass
-
-
-@pytest.mark.parametrize('Sample', [
- SampleNew, SampleNewInherit,
- SampleOld, SampleOldInherit,
-], ids=['new', 'new-inherit', 'old', 'old-inherit'])
-def test_issue156_undo_staticmethod(Sample):
- monkeypatch = MonkeyPatch()
-
- monkeypatch.setattr(Sample, 'hello', None)
- assert Sample.hello is None
-
- monkeypatch.undo()
- assert Sample.hello()
-
-def test_issue1338_name_resolving():
- pytest.importorskip('requests')
- monkeypatch = MonkeyPatch()
- try:
- monkeypatch.delattr('requests.sessions.Session.request')
- finally:
- monkeypatch.undo() \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_nose.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_nose.py
deleted file mode 100644
index a5162381e47..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_nose.py
+++ /dev/null
@@ -1,394 +0,0 @@
-import pytest
-
-def setup_module(mod):
- mod.nose = pytest.importorskip("nose")
-
-def test_nose_setup(testdir):
- p = testdir.makepyfile("""
- l = []
- from nose.tools import with_setup
-
- @with_setup(lambda: l.append(1), lambda: l.append(2))
- def test_hello():
- assert l == [1]
-
- def test_world():
- assert l == [1,2]
-
- test_hello.setup = lambda: l.append(1)
- test_hello.teardown = lambda: l.append(2)
- """)
- result = testdir.runpytest(p, '-p', 'nose')
- result.assert_outcomes(passed=2)
-
-
-def test_setup_func_with_setup_decorator():
- from _pytest.nose import call_optional
- l = []
- class A:
- @pytest.fixture(autouse=True)
- def f(self):
- l.append(1)
- call_optional(A(), "f")
- assert not l
-
-
-def test_setup_func_not_callable():
- from _pytest.nose import call_optional
- class A:
- f = 1
- call_optional(A(), "f")
-
-def test_nose_setup_func(testdir):
- p = testdir.makepyfile("""
- from nose.tools import with_setup
-
- l = []
-
- def my_setup():
- a = 1
- l.append(a)
-
- def my_teardown():
- b = 2
- l.append(b)
-
- @with_setup(my_setup, my_teardown)
- def test_hello():
- print (l)
- assert l == [1]
-
- def test_world():
- print (l)
- assert l == [1,2]
-
- """)
- result = testdir.runpytest(p, '-p', 'nose')
- result.assert_outcomes(passed=2)
-
-
-def test_nose_setup_func_failure(testdir):
- p = testdir.makepyfile("""
- from nose.tools import with_setup
-
- l = []
- my_setup = lambda x: 1
- my_teardown = lambda x: 2
-
- @with_setup(my_setup, my_teardown)
- def test_hello():
- print (l)
- assert l == [1]
-
- def test_world():
- print (l)
- assert l == [1,2]
-
- """)
- result = testdir.runpytest(p, '-p', 'nose')
- result.stdout.fnmatch_lines([
- "*TypeError: <lambda>()*"
- ])
-
-
-def test_nose_setup_func_failure_2(testdir):
- testdir.makepyfile("""
- l = []
-
- my_setup = 1
- my_teardown = 2
-
- def test_hello():
- assert l == []
-
- test_hello.setup = my_setup
- test_hello.teardown = my_teardown
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
-def test_nose_setup_partial(testdir):
- pytest.importorskip("functools")
- p = testdir.makepyfile("""
- from functools import partial
-
- l = []
-
- def my_setup(x):
- a = x
- l.append(a)
-
- def my_teardown(x):
- b = x
- l.append(b)
-
- my_setup_partial = partial(my_setup, 1)
- my_teardown_partial = partial(my_teardown, 2)
-
- def test_hello():
- print (l)
- assert l == [1]
-
- def test_world():
- print (l)
- assert l == [1,2]
-
- test_hello.setup = my_setup_partial
- test_hello.teardown = my_teardown_partial
- """)
- result = testdir.runpytest(p, '-p', 'nose')
- result.stdout.fnmatch_lines([
- "*2 passed*"
- ])
-
-
-def test_nose_test_generator_fixtures(testdir):
- p = testdir.makepyfile("""
- # taken from nose-0.11.1 unit_tests/test_generator_fixtures.py
- from nose.tools import eq_
- called = []
-
- def outer_setup():
- called.append('outer_setup')
-
- def outer_teardown():
- called.append('outer_teardown')
-
- def inner_setup():
- called.append('inner_setup')
-
- def inner_teardown():
- called.append('inner_teardown')
-
- def test_gen():
- called[:] = []
- for i in range(0, 5):
- yield check, i
-
- def check(i):
- expect = ['outer_setup']
- for x in range(0, i):
- expect.append('inner_setup')
- expect.append('inner_teardown')
- expect.append('inner_setup')
- eq_(called, expect)
-
-
- test_gen.setup = outer_setup
- test_gen.teardown = outer_teardown
- check.setup = inner_setup
- check.teardown = inner_teardown
-
- class TestClass(object):
- def setup(self):
- print ("setup called in %s" % self)
- self.called = ['setup']
-
- def teardown(self):
- print ("teardown called in %s" % self)
- eq_(self.called, ['setup'])
- self.called.append('teardown')
-
- def test(self):
- print ("test called in %s" % self)
- for i in range(0, 5):
- yield self.check, i
-
- def check(self, i):
- print ("check called in %s" % self)
- expect = ['setup']
- #for x in range(0, i):
- # expect.append('setup')
- # expect.append('teardown')
- #expect.append('setup')
- eq_(self.called, expect)
- """)
- result = testdir.runpytest(p, '-p', 'nose')
- result.stdout.fnmatch_lines([
- "*10 passed*"
- ])
-
-
-def test_module_level_setup(testdir):
- testdir.makepyfile("""
- from nose.tools import with_setup
- items = {}
-
- def setup():
- items[1]=1
-
- def teardown():
- del items[1]
-
- def setup2():
- items[2] = 2
-
- def teardown2():
- del items[2]
-
- def test_setup_module_setup():
- assert items[1] == 1
-
- @with_setup(setup2, teardown2)
- def test_local_setup():
- assert items[2] == 2
- assert 1 not in items
- """)
- result = testdir.runpytest('-p', 'nose')
- result.stdout.fnmatch_lines([
- "*2 passed*",
- ])
-
-
-def test_nose_style_setup_teardown(testdir):
- testdir.makepyfile("""
- l = []
-
- def setup_module():
- l.append(1)
-
- def teardown_module():
- del l[0]
-
- def test_hello():
- assert l == [1]
-
- def test_world():
- assert l == [1]
- """)
- result = testdir.runpytest('-p', 'nose')
- result.stdout.fnmatch_lines([
- "*2 passed*",
- ])
-
-def test_nose_setup_ordering(testdir):
- testdir.makepyfile("""
- def setup_module(mod):
- mod.visited = True
-
- class TestClass:
- def setup(self):
- assert visited
- def test_first(self):
- pass
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*1 passed*",
- ])
-
-
-def test_apiwrapper_problem_issue260(testdir):
- # this would end up trying a call a optional teardown on the class
- # for plain unittests we dont want nose behaviour
- testdir.makepyfile("""
- import unittest
- class TestCase(unittest.TestCase):
- def setup(self):
- #should not be called in unittest testcases
- assert 0, 'setup'
- def teardown(self):
- #should not be called in unittest testcases
- assert 0, 'teardown'
- def setUp(self):
- print('setup')
- def tearDown(self):
- print('teardown')
- def test_fun(self):
- pass
- """)
- result = testdir.runpytest()
- result.assert_outcomes(passed=1)
-
-def test_setup_teardown_linking_issue265(testdir):
- # we accidentally didnt integrate nose setupstate with normal setupstate
- # this test ensures that won't happen again
- testdir.makepyfile('''
- import pytest
-
- class TestGeneric(object):
- def test_nothing(self):
- """Tests the API of the implementation (for generic and specialized)."""
-
- @pytest.mark.skipif("True", reason=
- "Skip tests to check if teardown is skipped as well.")
- class TestSkipTeardown(TestGeneric):
-
- def setup(self):
- """Sets up my specialized implementation for $COOL_PLATFORM."""
- raise Exception("should not call setup for skipped tests")
-
- def teardown(self):
- """Undoes the setup."""
- raise Exception("should not call teardown for skipped tests")
- ''')
- reprec = testdir.runpytest()
- reprec.assert_outcomes(passed=1, skipped=1)
-
-
-def test_SkipTest_during_collection(testdir):
- p = testdir.makepyfile("""
- import nose
- raise nose.SkipTest("during collection")
- def test_failing():
- assert False
- """)
- result = testdir.runpytest(p)
- result.assert_outcomes(skipped=1)
-
-
-def test_SkipTest_in_test(testdir):
- testdir.makepyfile("""
- import nose
-
- def test_skipping():
- raise nose.SkipTest("in test")
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(skipped=1)
-
-def test_istest_function_decorator(testdir):
- p = testdir.makepyfile("""
- import nose.tools
- @nose.tools.istest
- def not_test_prefix():
- pass
- """)
- result = testdir.runpytest(p)
- result.assert_outcomes(passed=1)
-
-def test_nottest_function_decorator(testdir):
- testdir.makepyfile("""
- import nose.tools
- @nose.tools.nottest
- def test_prefix():
- pass
- """)
- reprec = testdir.inline_run()
- assert not reprec.getfailedcollections()
- calls = reprec.getreports("pytest_runtest_logreport")
- assert not calls
-
-def test_istest_class_decorator(testdir):
- p = testdir.makepyfile("""
- import nose.tools
- @nose.tools.istest
- class NotTestPrefix:
- def test_method(self):
- pass
- """)
- result = testdir.runpytest(p)
- result.assert_outcomes(passed=1)
-
-def test_nottest_class_decorator(testdir):
- testdir.makepyfile("""
- import nose.tools
- @nose.tools.nottest
- class TestPrefix:
- def test_method(self):
- pass
- """)
- reprec = testdir.inline_run()
- assert not reprec.getfailedcollections()
- calls = reprec.getreports("pytest_runtest_logreport")
- assert not calls
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_parseopt.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_parseopt.py
deleted file mode 100644
index e45ee285409..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_parseopt.py
+++ /dev/null
@@ -1,287 +0,0 @@
-from __future__ import with_statement
-import sys
-import os
-import py, pytest
-from _pytest import config as parseopt
-
-@pytest.fixture
-def parser():
- return parseopt.Parser()
-
-class TestParser:
- def test_no_help_by_default(self, capsys):
- parser = parseopt.Parser(usage="xyz")
- pytest.raises(SystemExit, lambda: parser.parse(["-h"]))
- out, err = capsys.readouterr()
- assert err.find("error: unrecognized arguments") != -1
-
- def test_argument(self):
- with pytest.raises(parseopt.ArgumentError):
- # need a short or long option
- argument = parseopt.Argument()
- argument = parseopt.Argument('-t')
- assert argument._short_opts == ['-t']
- assert argument._long_opts == []
- assert argument.dest == 't'
- argument = parseopt.Argument('-t', '--test')
- assert argument._short_opts == ['-t']
- assert argument._long_opts == ['--test']
- assert argument.dest == 'test'
- argument = parseopt.Argument('-t', '--test', dest='abc')
- assert argument.dest == 'abc'
-
- def test_argument_type(self):
- argument = parseopt.Argument('-t', dest='abc', type='int')
- assert argument.type is int
- argument = parseopt.Argument('-t', dest='abc', type='string')
- assert argument.type is str
- argument = parseopt.Argument('-t', dest='abc', type=float)
- assert argument.type is float
- with pytest.raises(KeyError):
- argument = parseopt.Argument('-t', dest='abc', type='choice')
- argument = parseopt.Argument('-t', dest='abc', type='choice',
- choices=['red', 'blue'])
- assert argument.type is str
-
- def test_argument_processopt(self):
- argument = parseopt.Argument('-t', type=int)
- argument.default = 42
- argument.dest = 'abc'
- res = argument.attrs()
- assert res['default'] == 42
- assert res['dest'] == 'abc'
-
- def test_group_add_and_get(self, parser):
- group = parser.getgroup("hello", description="desc")
- assert group.name == "hello"
- assert group.description == "desc"
-
- def test_getgroup_simple(self, parser):
- group = parser.getgroup("hello", description="desc")
- assert group.name == "hello"
- assert group.description == "desc"
- group2 = parser.getgroup("hello")
- assert group2 is group
-
- def test_group_ordering(self, parser):
- parser.getgroup("1")
- parser.getgroup("2")
- parser.getgroup("3", after="1")
- groups = parser._groups
- groups_names = [x.name for x in groups]
- assert groups_names == list("132")
-
- def test_group_addoption(self):
- group = parseopt.OptionGroup("hello")
- group.addoption("--option1", action="store_true")
- assert len(group.options) == 1
- assert isinstance(group.options[0], parseopt.Argument)
-
- def test_group_shortopt_lowercase(self, parser):
- group = parser.getgroup("hello")
- pytest.raises(ValueError, """
- group.addoption("-x", action="store_true")
- """)
- assert len(group.options) == 0
- group._addoption("-x", action="store_true")
- assert len(group.options) == 1
-
- def test_parser_addoption(self, parser):
- group = parser.getgroup("custom options")
- assert len(group.options) == 0
- group.addoption("--option1", action="store_true")
- assert len(group.options) == 1
-
- def test_parse(self, parser):
- parser.addoption("--hello", dest="hello", action="store")
- args = parser.parse(['--hello', 'world'])
- assert args.hello == "world"
- assert not getattr(args, parseopt.FILE_OR_DIR)
-
- def test_parse2(self, parser):
- args = parser.parse([py.path.local()])
- assert getattr(args, parseopt.FILE_OR_DIR)[0] == py.path.local()
-
- def test_parse_known_args(self, parser):
- parser.parse_known_args([py.path.local()])
- parser.addoption("--hello", action="store_true")
- ns = parser.parse_known_args(["x", "--y", "--hello", "this"])
- assert ns.hello
- assert ns.file_or_dir == ['x']
-
- def test_parse_known_and_unknown_args(self, parser):
- parser.addoption("--hello", action="store_true")
- ns, unknown = parser.parse_known_and_unknown_args(["x", "--y",
- "--hello", "this"])
- assert ns.hello
- assert ns.file_or_dir == ['x']
- assert unknown == ['--y', 'this']
-
- def test_parse_will_set_default(self, parser):
- parser.addoption("--hello", dest="hello", default="x", action="store")
- option = parser.parse([])
- assert option.hello == "x"
- del option.hello
- parser.parse_setoption([], option)
- assert option.hello == "x"
-
- def test_parse_setoption(self, parser):
- parser.addoption("--hello", dest="hello", action="store")
- parser.addoption("--world", dest="world", default=42)
- class A: pass
- option = A()
- args = parser.parse_setoption(['--hello', 'world'], option)
- assert option.hello == "world"
- assert option.world == 42
- assert not args
-
- def test_parse_special_destination(self, parser):
- parser.addoption("--ultimate-answer", type=int)
- args = parser.parse(['--ultimate-answer', '42'])
- assert args.ultimate_answer == 42
-
- def test_parse_split_positional_arguments(self, parser):
- parser.addoption("-R", action='store_true')
- parser.addoption("-S", action='store_false')
- args = parser.parse(['-R', '4', '2', '-S'])
- assert getattr(args, parseopt.FILE_OR_DIR) == ['4', '2']
- args = parser.parse(['-R', '-S', '4', '2', '-R'])
- assert getattr(args, parseopt.FILE_OR_DIR) == ['4', '2']
- assert args.R == True
- assert args.S == False
- args = parser.parse(['-R', '4', '-S', '2'])
- assert getattr(args, parseopt.FILE_OR_DIR) == ['4', '2']
- assert args.R == True
- assert args.S == False
-
- def test_parse_defaultgetter(self):
- def defaultget(option):
- if not hasattr(option, 'type'):
- return
- if option.type is int:
- option.default = 42
- elif option.type is str:
- option.default = "world"
- parser = parseopt.Parser(processopt=defaultget)
- parser.addoption("--this", dest="this", type="int", action="store")
- parser.addoption("--hello", dest="hello", type="string", action="store")
- parser.addoption("--no", dest="no", action="store_true")
- option = parser.parse([])
- assert option.hello == "world"
- assert option.this == 42
- assert option.no is False
-
- def test_drop_short_helper(self):
- parser = py.std.argparse.ArgumentParser(formatter_class=parseopt.DropShorterLongHelpFormatter)
- parser.add_argument('-t', '--twoword', '--duo', '--two-word', '--two',
- help='foo').map_long_option = {'two': 'two-word'}
- # throws error on --deux only!
- parser.add_argument('-d', '--deuxmots', '--deux-mots',
- action='store_true', help='foo').map_long_option = {'deux': 'deux-mots'}
- parser.add_argument('-s', action='store_true', help='single short')
- parser.add_argument('--abc', '-a',
- action='store_true', help='bar')
- parser.add_argument('--klm', '-k', '--kl-m',
- action='store_true', help='bar')
- parser.add_argument('-P', '--pq-r', '-p', '--pqr',
- action='store_true', help='bar')
- parser.add_argument('--zwei-wort', '--zweiwort', '--zweiwort',
- action='store_true', help='bar')
- parser.add_argument('-x', '--exit-on-first', '--exitfirst',
- action='store_true', help='spam').map_long_option = {'exitfirst': 'exit-on-first'}
- parser.add_argument('files_and_dirs', nargs='*')
- args = parser.parse_args(['-k', '--duo', 'hallo', '--exitfirst'])
- assert args.twoword == 'hallo'
- assert args.klm is True
- assert args.zwei_wort is False
- assert args.exit_on_first is True
- assert args.s is False
- args = parser.parse_args(['--deux-mots'])
- with pytest.raises(AttributeError):
- assert args.deux_mots is True
- assert args.deuxmots is True
- args = parser.parse_args(['file', 'dir'])
- assert '|'.join(args.files_and_dirs) == 'file|dir'
-
- def test_drop_short_0(self, parser):
- parser.addoption('--funcarg', '--func-arg', action='store_true')
- parser.addoption('--abc-def', '--abc-def', action='store_true')
- parser.addoption('--klm-hij', action='store_true')
- args = parser.parse(['--funcarg', '--k'])
- assert args.funcarg is True
- assert args.abc_def is False
- assert args.klm_hij is True
-
- def test_drop_short_2(self, parser):
- parser.addoption('--func-arg', '--doit', action='store_true')
- args = parser.parse(['--doit'])
- assert args.func_arg is True
-
- def test_drop_short_3(self, parser):
- parser.addoption('--func-arg', '--funcarg', '--doit', action='store_true')
- args = parser.parse(['abcd'])
- assert args.func_arg is False
- assert args.file_or_dir == ['abcd']
-
- def test_drop_short_help0(self, parser, capsys):
- parser.addoption('--func-args', '--doit', help = 'foo',
- action='store_true')
- parser.parse([])
- help = parser.optparser.format_help()
- assert '--func-args, --doit foo' in help
-
- # testing would be more helpful with all help generated
- def test_drop_short_help1(self, parser, capsys):
- group = parser.getgroup("general")
- group.addoption('--doit', '--func-args', action='store_true', help='foo')
- group._addoption("-h", "--help", action="store_true", dest="help",
- help="show help message and configuration info")
- parser.parse(['-h'])
- help = parser.optparser.format_help()
- assert '-doit, --func-args foo' in help
-
-
-def test_argcomplete(testdir, monkeypatch):
- if not py.path.local.sysfind('bash'):
- pytest.skip("bash not available")
- script = str(testdir.tmpdir.join("test_argcomplete"))
- pytest_bin = sys.argv[0]
- if "py.test" not in os.path.basename(pytest_bin):
- pytest.skip("need to be run with py.test executable, not %s" %(pytest_bin,))
-
- with open(str(script), 'w') as fp:
- # redirect output from argcomplete to stdin and stderr is not trivial
- # http://stackoverflow.com/q/12589419/1307905
- # so we use bash
- fp.write('COMP_WORDBREAKS="$COMP_WORDBREAKS" %s 8>&1 9>&2' % pytest_bin)
- # alternative would be exteneded Testdir.{run(),_run(),popen()} to be able
- # to handle a keyword argument env that replaces os.environ in popen or
- # extends the copy, advantage: could not forget to restore
- monkeypatch.setenv('_ARGCOMPLETE', "1")
- monkeypatch.setenv('_ARGCOMPLETE_IFS',"\x0b")
- monkeypatch.setenv('COMP_WORDBREAKS', ' \\t\\n"\\\'><=;|&(:')
-
- arg = '--fu'
- monkeypatch.setenv('COMP_LINE', "py.test " + arg)
- monkeypatch.setenv('COMP_POINT', str(len("py.test " + arg)))
- result = testdir.run('bash', str(script), arg)
- if result.ret == 255:
- # argcomplete not found
- pytest.skip("argcomplete not available")
- elif not result.stdout.str():
- pytest.skip("bash provided no output, argcomplete not available?")
- else:
- if py.std.sys.version_info < (2,7):
- result.stdout.lines = result.stdout.lines[0].split('\x0b')
- result.stdout.fnmatch_lines(["--funcargs", "--fulltrace"])
- else:
- result.stdout.fnmatch_lines(["--funcargs", "--fulltrace"])
- if py.std.sys.version_info < (2,7):
- return
- os.mkdir('test_argcomplete.d')
- arg = 'test_argc'
- monkeypatch.setenv('COMP_LINE', "py.test " + arg)
- monkeypatch.setenv('COMP_POINT', str(len('py.test ' + arg)))
- result = testdir.run('bash', str(script), arg)
- result.stdout.fnmatch_lines(["test_argcomplete", "test_argcomplete.d/"])
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_pastebin.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_pastebin.py
deleted file mode 100644
index 03570a5c70b..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_pastebin.py
+++ /dev/null
@@ -1,115 +0,0 @@
-# encoding: utf-8
-import sys
-import pytest
-
-class TestPasteCapture:
-
- @pytest.fixture
- def pastebinlist(self, monkeypatch, request):
- pastebinlist = []
- plugin = request.config.pluginmanager.getplugin('pastebin')
- monkeypatch.setattr(plugin, 'create_new_paste', pastebinlist.append)
- return pastebinlist
-
- def test_failed(self, testdir, pastebinlist):
- testpath = testdir.makepyfile("""
- import pytest
- def test_pass():
- pass
- def test_fail():
- assert 0
- def test_skip():
- pytest.skip("")
- """)
- reprec = testdir.inline_run(testpath, "--paste=failed")
- assert len(pastebinlist) == 1
- s = pastebinlist[0]
- assert s.find("def test_fail") != -1
- assert reprec.countoutcomes() == [1,1,1]
-
- def test_all(self, testdir, pastebinlist):
- from _pytest.pytester import LineMatcher
- testpath = testdir.makepyfile("""
- import pytest
- def test_pass():
- pass
- def test_fail():
- assert 0
- def test_skip():
- pytest.skip("")
- """)
- reprec = testdir.inline_run(testpath, "--pastebin=all", '-v')
- assert reprec.countoutcomes() == [1,1,1]
- assert len(pastebinlist) == 1
- contents = pastebinlist[0].decode('utf-8')
- matcher = LineMatcher(contents.splitlines())
- matcher.fnmatch_lines([
- '*test_pass PASSED*',
- '*test_fail FAILED*',
- '*test_skip SKIPPED*',
- '*== 1 failed, 1 passed, 1 skipped in *'
- ])
-
- def test_non_ascii_paste_text(self, testdir):
- """Make sure that text which contains non-ascii characters is pasted
- correctly. See #1219.
- """
- testdir.makepyfile(test_unicode="""
- # encoding: utf-8
- def test():
- assert '☺' == 1
- """)
- result = testdir.runpytest('--pastebin=all')
- if sys.version_info[0] == 3:
- expected_msg = "*assert '☺' == 1*"
- else:
- expected_msg = "*assert '\\xe2\\x98\\xba' == 1*"
- result.stdout.fnmatch_lines([
- expected_msg,
- "*== 1 failed in *",
- '*Sending information to Paste Service*',
- ])
-
-
-class TestPaste:
-
- @pytest.fixture
- def pastebin(self, request):
- return request.config.pluginmanager.getplugin('pastebin')
-
- @pytest.fixture
- def mocked_urlopen(self, monkeypatch):
- """
- monkeypatch the actual urlopen calls done by the internal plugin
- function that connects to bpaste service.
- """
- calls = []
- def mocked(url, data):
- calls.append((url, data))
- class DummyFile:
- def read(self):
- # part of html of a normal response
- return b'View <a href="/raw/3c0c6750bd">raw</a>.'
- return DummyFile()
-
- if sys.version_info < (3, 0):
- import urllib
- monkeypatch.setattr(urllib, 'urlopen', mocked)
- else:
- import urllib.request
- monkeypatch.setattr(urllib.request, 'urlopen', mocked)
- return calls
-
- def test_create_new_paste(self, pastebin, mocked_urlopen):
- result = pastebin.create_new_paste(b'full-paste-contents')
- assert result == 'https://bpaste.net/show/3c0c6750bd'
- assert len(mocked_urlopen) == 1
- url, data = mocked_urlopen[0]
- assert type(data) is bytes
- lexer = 'python3' if sys.version_info[0] == 3 else 'python'
- assert url == 'https://bpaste.net'
- assert 'lexer=%s' % lexer in data.decode()
- assert 'code=full-paste-contents' in data.decode()
- assert 'expiry=1week' in data.decode()
-
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_pdb.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_pdb.py
deleted file mode 100644
index eeddcf0ae80..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_pdb.py
+++ /dev/null
@@ -1,313 +0,0 @@
-import sys
-
-import _pytest._code
-
-
-def runpdb_and_get_report(testdir, source):
- p = testdir.makepyfile(source)
- result = testdir.runpytest_inprocess("--pdb", p)
- reports = result.reprec.getreports("pytest_runtest_logreport")
- assert len(reports) == 3, reports # setup/call/teardown
- return reports[1]
-
-
-class TestPDB:
- def pytest_funcarg__pdblist(self, request):
- monkeypatch = request.getfuncargvalue("monkeypatch")
- pdblist = []
- def mypdb(*args):
- pdblist.append(args)
- plugin = request.config.pluginmanager.getplugin('pdb')
- monkeypatch.setattr(plugin, 'post_mortem', mypdb)
- return pdblist
-
- def test_pdb_on_fail(self, testdir, pdblist):
- rep = runpdb_and_get_report(testdir, """
- def test_func():
- assert 0
- """)
- assert rep.failed
- assert len(pdblist) == 1
- tb = _pytest._code.Traceback(pdblist[0][0])
- assert tb[-1].name == "test_func"
-
- def test_pdb_on_xfail(self, testdir, pdblist):
- rep = runpdb_and_get_report(testdir, """
- import pytest
- @pytest.mark.xfail
- def test_func():
- assert 0
- """)
- assert "xfail" in rep.keywords
- assert not pdblist
-
- def test_pdb_on_skip(self, testdir, pdblist):
- rep = runpdb_and_get_report(testdir, """
- import pytest
- def test_func():
- pytest.skip("hello")
- """)
- assert rep.skipped
- assert len(pdblist) == 0
-
- def test_pdb_on_BdbQuit(self, testdir, pdblist):
- rep = runpdb_and_get_report(testdir, """
- import bdb
- def test_func():
- raise bdb.BdbQuit
- """)
- assert rep.failed
- assert len(pdblist) == 0
-
- def test_pdb_interaction(self, testdir):
- p1 = testdir.makepyfile("""
- def test_1():
- i = 0
- assert i == 1
- """)
- child = testdir.spawn_pytest("--pdb %s" % p1)
- child.expect(".*def test_1")
- child.expect(".*i = 0")
- child.expect("(Pdb)")
- child.sendeof()
- rest = child.read().decode("utf8")
- assert "1 failed" in rest
- assert "def test_1" not in rest
- if child.isalive():
- child.wait()
-
- def test_pdb_interaction_capture(self, testdir):
- p1 = testdir.makepyfile("""
- def test_1():
- print("getrekt")
- assert False
- """)
- child = testdir.spawn_pytest("--pdb %s" % p1)
- child.expect("getrekt")
- child.expect("(Pdb)")
- child.sendeof()
- rest = child.read().decode("utf8")
- assert "1 failed" in rest
- assert "getrekt" not in rest
- if child.isalive():
- child.wait()
-
- def test_pdb_interaction_exception(self, testdir):
- p1 = testdir.makepyfile("""
- import pytest
- def globalfunc():
- pass
- def test_1():
- pytest.raises(ValueError, globalfunc)
- """)
- child = testdir.spawn_pytest("--pdb %s" % p1)
- child.expect(".*def test_1")
- child.expect(".*pytest.raises.*globalfunc")
- child.expect("(Pdb)")
- child.sendline("globalfunc")
- child.expect(".*function")
- child.sendeof()
- child.expect("1 failed")
- if child.isalive():
- child.wait()
-
- def test_pdb_interaction_on_collection_issue181(self, testdir):
- p1 = testdir.makepyfile("""
- import pytest
- xxx
- """)
- child = testdir.spawn_pytest("--pdb %s" % p1)
- #child.expect(".*import pytest.*")
- child.expect("(Pdb)")
- child.sendeof()
- child.expect("1 error")
- if child.isalive():
- child.wait()
-
- def test_pdb_interaction_on_internal_error(self, testdir):
- testdir.makeconftest("""
- def pytest_runtest_protocol():
- 0/0
- """)
- p1 = testdir.makepyfile("def test_func(): pass")
- child = testdir.spawn_pytest("--pdb %s" % p1)
- #child.expect(".*import pytest.*")
- child.expect("(Pdb)")
- child.sendeof()
- if child.isalive():
- child.wait()
-
- def test_pdb_interaction_capturing_simple(self, testdir):
- p1 = testdir.makepyfile("""
- import pytest
- def test_1():
- i = 0
- print ("hello17")
- pytest.set_trace()
- x = 3
- """)
- child = testdir.spawn_pytest(str(p1))
- child.expect("test_1")
- child.expect("x = 3")
- child.expect("(Pdb)")
- child.sendeof()
- rest = child.read().decode("utf-8")
- assert "1 failed" in rest
- assert "def test_1" in rest
- assert "hello17" in rest # out is captured
- if child.isalive():
- child.wait()
-
- def test_pdb_set_trace_interception(self, testdir):
- p1 = testdir.makepyfile("""
- import pdb
- def test_1():
- pdb.set_trace()
- """)
- child = testdir.spawn_pytest(str(p1))
- child.expect("test_1")
- child.expect("(Pdb)")
- child.sendeof()
- rest = child.read().decode("utf8")
- assert "1 failed" in rest
- assert "reading from stdin while output" not in rest
- if child.isalive():
- child.wait()
-
- def test_pdb_and_capsys(self, testdir):
- p1 = testdir.makepyfile("""
- import pytest
- def test_1(capsys):
- print ("hello1")
- pytest.set_trace()
- """)
- child = testdir.spawn_pytest(str(p1))
- child.expect("test_1")
- child.send("capsys.readouterr()\n")
- child.expect("hello1")
- child.sendeof()
- child.read()
- if child.isalive():
- child.wait()
-
- def test_set_trace_capturing_afterwards(self, testdir):
- p1 = testdir.makepyfile("""
- import pdb
- def test_1():
- pdb.set_trace()
- def test_2():
- print ("hello")
- assert 0
- """)
- child = testdir.spawn_pytest(str(p1))
- child.expect("test_1")
- child.send("c\n")
- child.expect("test_2")
- child.expect("Captured")
- child.expect("hello")
- child.sendeof()
- child.read()
- if child.isalive():
- child.wait()
-
- def test_pdb_interaction_doctest(self, testdir):
- p1 = testdir.makepyfile("""
- import pytest
- def function_1():
- '''
- >>> i = 0
- >>> assert i == 1
- '''
- """)
- child = testdir.spawn_pytest("--doctest-modules --pdb %s" % p1)
- child.expect("(Pdb)")
- child.sendline('i')
- child.expect("0")
- child.expect("(Pdb)")
- child.sendeof()
- rest = child.read().decode("utf8")
- assert "1 failed" in rest
- if child.isalive():
- child.wait()
-
- def test_pdb_interaction_capturing_twice(self, testdir):
- p1 = testdir.makepyfile("""
- import pytest
- def test_1():
- i = 0
- print ("hello17")
- pytest.set_trace()
- x = 3
- print ("hello18")
- pytest.set_trace()
- x = 4
- """)
- child = testdir.spawn_pytest(str(p1))
- child.expect("test_1")
- child.expect("x = 3")
- child.expect("(Pdb)")
- child.sendline('c')
- child.expect("x = 4")
- child.sendeof()
- rest = child.read().decode("utf8")
- assert "1 failed" in rest
- assert "def test_1" in rest
- assert "hello17" in rest # out is captured
- assert "hello18" in rest # out is captured
- if child.isalive():
- child.wait()
-
- def test_pdb_used_outside_test(self, testdir):
- p1 = testdir.makepyfile("""
- import pytest
- pytest.set_trace()
- x = 5
- """)
- child = testdir.spawn("%s %s" %(sys.executable, p1))
- child.expect("x = 5")
- child.sendeof()
- child.wait()
-
- def test_pdb_used_in_generate_tests(self, testdir):
- p1 = testdir.makepyfile("""
- import pytest
- def pytest_generate_tests(metafunc):
- pytest.set_trace()
- x = 5
- def test_foo(a):
- pass
- """)
- child = testdir.spawn_pytest(str(p1))
- child.expect("x = 5")
- child.sendeof()
- child.wait()
-
- def test_pdb_collection_failure_is_shown(self, testdir):
- p1 = testdir.makepyfile("""xxx """)
- result = testdir.runpytest_subprocess("--pdb", p1)
- result.stdout.fnmatch_lines([
- "*NameError*xxx*",
- "*1 error*",
- ])
-
- def test_enter_pdb_hook_is_called(self, testdir):
- testdir.makeconftest("""
- def pytest_enter_pdb(config):
- assert config.testing_verification == 'configured'
- print 'enter_pdb_hook'
-
- def pytest_configure(config):
- config.testing_verification = 'configured'
- """)
- p1 = testdir.makepyfile("""
- import pytest
-
- def test_foo():
- pytest.set_trace()
- """)
- child = testdir.spawn_pytest(str(p1))
- child.expect("enter_pdb_hook")
- child.send('c\n')
- child.sendeof()
- if child.isalive():
- child.wait()
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_pluginmanager.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_pluginmanager.py
deleted file mode 100644
index 36847638d48..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_pluginmanager.py
+++ /dev/null
@@ -1,340 +0,0 @@
-import pytest
-import py
-import os
-
-from _pytest.config import get_config, PytestPluginManager
-from _pytest.main import EXIT_NOTESTSCOLLECTED
-
-@pytest.fixture
-def pytestpm():
- return PytestPluginManager()
-
-class TestPytestPluginInteractions:
- def test_addhooks_conftestplugin(self, testdir):
- testdir.makepyfile(newhooks="""
- def pytest_myhook(xyz):
- "new hook"
- """)
- conf = testdir.makeconftest("""
- import sys ; sys.path.insert(0, '.')
- import newhooks
- def pytest_addhooks(pluginmanager):
- pluginmanager.addhooks(newhooks)
- def pytest_myhook(xyz):
- return xyz + 1
- """)
- config = get_config()
- pm = config.pluginmanager
- pm.hook.pytest_addhooks.call_historic(
- kwargs=dict(pluginmanager=config.pluginmanager))
- config.pluginmanager._importconftest(conf)
- #print(config.pluginmanager.get_plugins())
- res = config.hook.pytest_myhook(xyz=10)
- assert res == [11]
-
- def test_addhooks_nohooks(self, testdir):
- testdir.makeconftest("""
- import sys
- def pytest_addhooks(pluginmanager):
- pluginmanager.addhooks(sys)
- """)
- res = testdir.runpytest()
- assert res.ret != 0
- res.stderr.fnmatch_lines([
- "*did not find*sys*"
- ])
-
- def test_namespace_early_from_import(self, testdir):
- p = testdir.makepyfile("""
- from pytest import Item
- from pytest import Item as Item2
- assert Item is Item2
- """)
- result = testdir.runpython(p)
- assert result.ret == 0
-
- def test_do_ext_namespace(self, testdir):
- testdir.makeconftest("""
- def pytest_namespace():
- return {'hello': 'world'}
- """)
- p = testdir.makepyfile("""
- from pytest import hello
- import pytest
- def test_hello():
- assert hello == "world"
- assert 'hello' in pytest.__all__
- """)
- reprec = testdir.inline_run(p)
- reprec.assertoutcome(passed=1)
-
- def test_do_option_postinitialize(self, testdir):
- config = testdir.parseconfigure()
- assert not hasattr(config.option, 'test123')
- p = testdir.makepyfile("""
- def pytest_addoption(parser):
- parser.addoption('--test123', action="store_true",
- default=True)
- """)
- config.pluginmanager._importconftest(p)
- assert config.option.test123
-
- def test_configure(self, testdir):
- config = testdir.parseconfig()
- l = []
- class A:
- def pytest_configure(self, config):
- l.append(self)
-
- config.pluginmanager.register(A())
- assert len(l) == 0
- config._do_configure()
- assert len(l) == 1
- config.pluginmanager.register(A()) # leads to a configured() plugin
- assert len(l) == 2
- assert l[0] != l[1]
-
- config._ensure_unconfigure()
- config.pluginmanager.register(A())
- assert len(l) == 2
-
- def test_hook_tracing(self):
- pytestpm = get_config().pluginmanager # fully initialized with plugins
- saveindent = []
- class api1:
- def pytest_plugin_registered(self):
- saveindent.append(pytestpm.trace.root.indent)
- class api2:
- def pytest_plugin_registered(self):
- saveindent.append(pytestpm.trace.root.indent)
- raise ValueError()
- l = []
- pytestpm.trace.root.setwriter(l.append)
- undo = pytestpm.enable_tracing()
- try:
- indent = pytestpm.trace.root.indent
- p = api1()
- pytestpm.register(p)
- assert pytestpm.trace.root.indent == indent
- assert len(l) >= 2
- assert 'pytest_plugin_registered' in l[0]
- assert 'finish' in l[1]
-
- l[:] = []
- with pytest.raises(ValueError):
- pytestpm.register(api2())
- assert pytestpm.trace.root.indent == indent
- assert saveindent[0] > indent
- finally:
- undo()
-
- def test_warn_on_deprecated_multicall(self, pytestpm):
- warnings = []
-
- class get_warnings:
- def pytest_logwarning(self, message):
- warnings.append(message)
-
- class Plugin:
- def pytest_configure(self, __multicall__):
- pass
-
- pytestpm.register(get_warnings())
- before = list(warnings)
- pytestpm.register(Plugin())
- assert len(warnings) == len(before) + 1
- assert "deprecated" in warnings[-1]
-
- def test_warn_on_deprecated_addhooks(self, pytestpm):
- warnings = []
-
- class get_warnings:
- def pytest_logwarning(self, code, fslocation, message, nodeid):
- warnings.append(message)
-
- class Plugin:
- def pytest_testhook():
- pass
-
- pytestpm.register(get_warnings())
- before = list(warnings)
- pytestpm.addhooks(Plugin())
- assert len(warnings) == len(before) + 1
- assert "deprecated" in warnings[-1]
-
-
-def test_namespace_has_default_and_env_plugins(testdir):
- p = testdir.makepyfile("""
- import pytest
- pytest.mark
- """)
- result = testdir.runpython(p)
- assert result.ret == 0
-
-def test_default_markers(testdir):
- result = testdir.runpytest("--markers")
- result.stdout.fnmatch_lines([
- "*tryfirst*first*",
- "*trylast*last*",
- ])
-
-
-def test_importplugin_issue375(testdir, pytestpm):
- """Don't hide import errors when importing plugins and provide
- an easy to debug message.
- """
- testdir.syspathinsert(testdir.tmpdir)
- testdir.makepyfile(qwe="import aaaa")
- with pytest.raises(ImportError) as excinfo:
- pytestpm.import_plugin("qwe")
- expected = '.*Error importing plugin "qwe": No module named \'?aaaa\'?'
- assert py.std.re.match(expected, str(excinfo.value))
-
-
-class TestPytestPluginManager:
- def test_register_imported_modules(self):
- pm = PytestPluginManager()
- mod = py.std.types.ModuleType("x.y.pytest_hello")
- pm.register(mod)
- assert pm.is_registered(mod)
- l = pm.get_plugins()
- assert mod in l
- pytest.raises(ValueError, "pm.register(mod)")
- pytest.raises(ValueError, lambda: pm.register(mod))
- #assert not pm.is_registered(mod2)
- assert pm.get_plugins() == l
-
- def test_canonical_import(self, monkeypatch):
- mod = py.std.types.ModuleType("pytest_xyz")
- monkeypatch.setitem(py.std.sys.modules, 'pytest_xyz', mod)
- pm = PytestPluginManager()
- pm.import_plugin('pytest_xyz')
- assert pm.get_plugin('pytest_xyz') == mod
- assert pm.is_registered(mod)
-
- def test_consider_module(self, testdir, pytestpm):
- testdir.syspathinsert()
- testdir.makepyfile(pytest_p1="#")
- testdir.makepyfile(pytest_p2="#")
- mod = py.std.types.ModuleType("temp")
- mod.pytest_plugins = ["pytest_p1", "pytest_p2"]
- pytestpm.consider_module(mod)
- assert pytestpm.get_plugin("pytest_p1").__name__ == "pytest_p1"
- assert pytestpm.get_plugin("pytest_p2").__name__ == "pytest_p2"
-
- def test_consider_module_import_module(self, testdir):
- pytestpm = get_config().pluginmanager
- mod = py.std.types.ModuleType("x")
- mod.pytest_plugins = "pytest_a"
- aplugin = testdir.makepyfile(pytest_a="#")
- reprec = testdir.make_hook_recorder(pytestpm)
- #syspath.prepend(aplugin.dirpath())
- py.std.sys.path.insert(0, str(aplugin.dirpath()))
- pytestpm.consider_module(mod)
- call = reprec.getcall(pytestpm.hook.pytest_plugin_registered.name)
- assert call.plugin.__name__ == "pytest_a"
-
- # check that it is not registered twice
- pytestpm.consider_module(mod)
- l = reprec.getcalls("pytest_plugin_registered")
- assert len(l) == 1
-
- def test_consider_env_fails_to_import(self, monkeypatch, pytestpm):
- monkeypatch.setenv('PYTEST_PLUGINS', 'nonexisting', prepend=",")
- with pytest.raises(ImportError):
- pytestpm.consider_env()
-
- def test_plugin_skip(self, testdir, monkeypatch):
- p = testdir.makepyfile(skipping1="""
- import pytest
- pytest.skip("hello")
- """)
- p.copy(p.dirpath("skipping2.py"))
- monkeypatch.setenv("PYTEST_PLUGINS", "skipping2")
- result = testdir.runpytest("-rw", "-p", "skipping1", syspathinsert=True)
- assert result.ret == EXIT_NOTESTSCOLLECTED
- result.stdout.fnmatch_lines([
- "WI1*skipped plugin*skipping1*hello*",
- "WI1*skipped plugin*skipping2*hello*",
- ])
-
- def test_consider_env_plugin_instantiation(self, testdir, monkeypatch, pytestpm):
- testdir.syspathinsert()
- testdir.makepyfile(xy123="#")
- monkeypatch.setitem(os.environ, 'PYTEST_PLUGINS', 'xy123')
- l1 = len(pytestpm.get_plugins())
- pytestpm.consider_env()
- l2 = len(pytestpm.get_plugins())
- assert l2 == l1 + 1
- assert pytestpm.get_plugin('xy123')
- pytestpm.consider_env()
- l3 = len(pytestpm.get_plugins())
- assert l2 == l3
-
- def test_pluginmanager_ENV_startup(self, testdir, monkeypatch):
- testdir.makepyfile(pytest_x500="#")
- p = testdir.makepyfile("""
- import pytest
- def test_hello(pytestconfig):
- plugin = pytestconfig.pluginmanager.get_plugin('pytest_x500')
- assert plugin is not None
- """)
- monkeypatch.setenv('PYTEST_PLUGINS', 'pytest_x500', prepend=",")
- result = testdir.runpytest(p, syspathinsert=True)
- assert result.ret == 0
- result.stdout.fnmatch_lines(["*1 passed*"])
-
- def test_import_plugin_importname(self, testdir, pytestpm):
- pytest.raises(ImportError, 'pytestpm.import_plugin("qweqwex.y")')
- pytest.raises(ImportError, 'pytestpm.import_plugin("pytest_qweqwx.y")')
-
- testdir.syspathinsert()
- pluginname = "pytest_hello"
- testdir.makepyfile(**{pluginname: ""})
- pytestpm.import_plugin("pytest_hello")
- len1 = len(pytestpm.get_plugins())
- pytestpm.import_plugin("pytest_hello")
- len2 = len(pytestpm.get_plugins())
- assert len1 == len2
- plugin1 = pytestpm.get_plugin("pytest_hello")
- assert plugin1.__name__.endswith('pytest_hello')
- plugin2 = pytestpm.get_plugin("pytest_hello")
- assert plugin2 is plugin1
-
- def test_import_plugin_dotted_name(self, testdir, pytestpm):
- pytest.raises(ImportError, 'pytestpm.import_plugin("qweqwex.y")')
- pytest.raises(ImportError, 'pytestpm.import_plugin("pytest_qweqwex.y")')
-
- testdir.syspathinsert()
- testdir.mkpydir("pkg").join("plug.py").write("x=3")
- pluginname = "pkg.plug"
- pytestpm.import_plugin(pluginname)
- mod = pytestpm.get_plugin("pkg.plug")
- assert mod.x == 3
-
- def test_consider_conftest_deps(self, testdir, pytestpm):
- mod = testdir.makepyfile("pytest_plugins='xyz'").pyimport()
- with pytest.raises(ImportError):
- pytestpm.consider_conftest(mod)
-
-
-class TestPytestPluginManagerBootstrapming:
- def test_preparse_args(self, pytestpm):
- pytest.raises(ImportError, lambda:
- pytestpm.consider_preparse(["xyz", "-p", "hello123"]))
-
- def test_plugin_prevent_register(self, pytestpm):
- pytestpm.consider_preparse(["xyz", "-p", "no:abc"])
- l1 = pytestpm.get_plugins()
- pytestpm.register(42, name="abc")
- l2 = pytestpm.get_plugins()
- assert len(l2) == len(l1)
- assert 42 not in l2
-
- def test_plugin_prevent_register_unregistered_alredy_registered(self, pytestpm):
- pytestpm.register(42, name="abc")
- l1 = pytestpm.get_plugins()
- assert 42 in l1
- pytestpm.consider_preparse(["xyz", "-p", "no:abc"])
- l2 = pytestpm.get_plugins()
- assert 42 not in l2
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_pytester.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_pytester.py
deleted file mode 100644
index 65660afdfe3..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_pytester.py
+++ /dev/null
@@ -1,122 +0,0 @@
-import pytest
-import os
-from _pytest.pytester import HookRecorder
-from _pytest.config import PytestPluginManager
-from _pytest.main import EXIT_OK, EXIT_TESTSFAILED
-
-
-def test_make_hook_recorder(testdir):
- item = testdir.getitem("def test_func(): pass")
- recorder = testdir.make_hook_recorder(item.config.pluginmanager)
- assert not recorder.getfailures()
-
- pytest.xfail("internal reportrecorder tests need refactoring")
- class rep:
- excinfo = None
- passed = False
- failed = True
- skipped = False
- when = "call"
-
- recorder.hook.pytest_runtest_logreport(report=rep)
- failures = recorder.getfailures()
- assert failures == [rep]
- failures = recorder.getfailures()
- assert failures == [rep]
-
- class rep:
- excinfo = None
- passed = False
- failed = False
- skipped = True
- when = "call"
- rep.passed = False
- rep.skipped = True
- recorder.hook.pytest_runtest_logreport(report=rep)
-
- modcol = testdir.getmodulecol("")
- rep = modcol.config.hook.pytest_make_collect_report(collector=modcol)
- rep.passed = False
- rep.failed = True
- rep.skipped = False
- recorder.hook.pytest_collectreport(report=rep)
-
- passed, skipped, failed = recorder.listoutcomes()
- assert not passed and skipped and failed
-
- numpassed, numskipped, numfailed = recorder.countoutcomes()
- assert numpassed == 0
- assert numskipped == 1
- assert numfailed == 1
- assert len(recorder.getfailedcollections()) == 1
-
- recorder.unregister()
- recorder.clear()
- recorder.hook.pytest_runtest_logreport(report=rep)
- pytest.raises(ValueError, "recorder.getfailures()")
-
-
-def test_parseconfig(testdir):
- config1 = testdir.parseconfig()
- config2 = testdir.parseconfig()
- assert config2 != config1
- assert config1 != pytest.config
-
-def test_testdir_runs_with_plugin(testdir):
- testdir.makepyfile("""
- pytest_plugins = "pytester"
- def test_hello(testdir):
- assert 1
- """)
- result = testdir.runpytest()
- result.assert_outcomes(passed=1)
-
-
-def make_holder():
- class apiclass:
- def pytest_xyz(self, arg):
- "x"
- def pytest_xyz_noarg(self):
- "x"
-
- apimod = type(os)('api')
- def pytest_xyz(arg):
- "x"
- def pytest_xyz_noarg():
- "x"
- apimod.pytest_xyz = pytest_xyz
- apimod.pytest_xyz_noarg = pytest_xyz_noarg
- return apiclass, apimod
-
-
-@pytest.mark.parametrize("holder", make_holder())
-def test_hookrecorder_basic(holder):
- pm = PytestPluginManager()
- pm.addhooks(holder)
- rec = HookRecorder(pm)
- pm.hook.pytest_xyz(arg=123)
- call = rec.popcall("pytest_xyz")
- assert call.arg == 123
- assert call._name == "pytest_xyz"
- pytest.raises(pytest.fail.Exception, "rec.popcall('abc')")
- pm.hook.pytest_xyz_noarg()
- call = rec.popcall("pytest_xyz_noarg")
- assert call._name == "pytest_xyz_noarg"
-
-
-def test_makepyfile_unicode(testdir):
- global unichr
- try:
- unichr(65)
- except NameError:
- unichr = chr
- testdir.makepyfile(unichr(0xfffd))
-
-def test_inline_run_clean_modules(testdir):
- test_mod = testdir.makepyfile("def test_foo(): assert True")
- result = testdir.inline_run(str(test_mod))
- assert result.ret == EXIT_OK
- # rewrite module, now test should fail if module was re-imported
- test_mod.write("def test_foo(): assert False")
- result2 = testdir.inline_run(str(test_mod))
- assert result2.ret == EXIT_TESTSFAILED
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_recwarn.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_recwarn.py
deleted file mode 100644
index 87e5846c2b0..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_recwarn.py
+++ /dev/null
@@ -1,227 +0,0 @@
-import warnings
-import py
-import pytest
-from _pytest.recwarn import WarningsRecorder
-
-
-def test_recwarn_functional(testdir):
- reprec = testdir.inline_runsource("""
- import warnings
- oldwarn = warnings.showwarning
- def test_method(recwarn):
- assert warnings.showwarning != oldwarn
- warnings.warn("hello")
- warn = recwarn.pop()
- assert isinstance(warn.message, UserWarning)
- def test_finalized():
- assert warnings.showwarning == oldwarn
- """)
- res = reprec.countoutcomes()
- assert tuple(res) == (2, 0, 0), res
-
-
-class TestWarningsRecorderChecker(object):
- def test_recording(self, recwarn):
- showwarning = py.std.warnings.showwarning
- rec = WarningsRecorder()
- with rec:
- assert py.std.warnings.showwarning != showwarning
- assert not rec.list
- py.std.warnings.warn_explicit("hello", UserWarning, "xyz", 13)
- assert len(rec.list) == 1
- py.std.warnings.warn(DeprecationWarning("hello"))
- assert len(rec.list) == 2
- warn = rec.pop()
- assert str(warn.message) == "hello"
- l = rec.list
- rec.clear()
- assert len(rec.list) == 0
- assert l is rec.list
- pytest.raises(AssertionError, "rec.pop()")
-
- assert showwarning == py.std.warnings.showwarning
-
- def test_typechecking(self):
- from _pytest.recwarn import WarningsChecker
- with pytest.raises(TypeError):
- WarningsChecker(5)
- with pytest.raises(TypeError):
- WarningsChecker(('hi', RuntimeWarning))
- with pytest.raises(TypeError):
- WarningsChecker([DeprecationWarning, RuntimeWarning])
-
- def test_invalid_enter_exit(self):
- # wrap this test in WarningsRecorder to ensure warning state gets reset
- with WarningsRecorder():
- with pytest.raises(RuntimeError):
- rec = WarningsRecorder()
- rec.__exit__(None, None, None) # can't exit before entering
-
- with pytest.raises(RuntimeError):
- rec = WarningsRecorder()
- with rec:
- with rec:
- pass # can't enter twice
-
-
-class TestDeprecatedCall(object):
- """test pytest.deprecated_call()"""
-
- def dep(self, i, j=None):
- if i == 0:
- py.std.warnings.warn("is deprecated", DeprecationWarning,
- stacklevel=1)
- return 42
-
- def dep_explicit(self, i):
- if i == 0:
- py.std.warnings.warn_explicit("dep_explicit", category=DeprecationWarning,
- filename="hello", lineno=3)
-
- def test_deprecated_call_raises(self):
- with pytest.raises(AssertionError) as excinfo:
- pytest.deprecated_call(self.dep, 3, 5)
- assert str(excinfo).find("did not produce") != -1
-
- def test_deprecated_call(self):
- pytest.deprecated_call(self.dep, 0, 5)
-
- def test_deprecated_call_ret(self):
- ret = pytest.deprecated_call(self.dep, 0)
- assert ret == 42
-
- def test_deprecated_call_preserves(self):
- onceregistry = py.std.warnings.onceregistry.copy()
- filters = py.std.warnings.filters[:]
- warn = py.std.warnings.warn
- warn_explicit = py.std.warnings.warn_explicit
- self.test_deprecated_call_raises()
- self.test_deprecated_call()
- assert onceregistry == py.std.warnings.onceregistry
- assert filters == py.std.warnings.filters
- assert warn is py.std.warnings.warn
- assert warn_explicit is py.std.warnings.warn_explicit
-
- def test_deprecated_explicit_call_raises(self):
- with pytest.raises(AssertionError):
- pytest.deprecated_call(self.dep_explicit, 3)
-
- def test_deprecated_explicit_call(self):
- pytest.deprecated_call(self.dep_explicit, 0)
- pytest.deprecated_call(self.dep_explicit, 0)
-
- def test_deprecated_call_as_context_manager_no_warning(self):
- with pytest.raises(pytest.fail.Exception) as ex:
- with pytest.deprecated_call():
- self.dep(1)
- assert str(ex.value) == "DID NOT WARN"
-
- def test_deprecated_call_as_context_manager(self):
- with pytest.deprecated_call():
- self.dep(0)
-
- def test_deprecated_call_pending(self):
- def f():
- py.std.warnings.warn(PendingDeprecationWarning("hi"))
- pytest.deprecated_call(f)
-
- def test_deprecated_call_specificity(self):
- other_warnings = [Warning, UserWarning, SyntaxWarning, RuntimeWarning,
- FutureWarning, ImportWarning, UnicodeWarning]
- for warning in other_warnings:
- def f():
- py.std.warnings.warn(warning("hi"))
- with pytest.raises(AssertionError):
- pytest.deprecated_call(f)
-
- def test_deprecated_function_already_called(self, testdir):
- """deprecated_call should be able to catch a call to a deprecated
- function even if that function has already been called in the same
- module. See #1190.
- """
- testdir.makepyfile("""
- import warnings
- import pytest
-
- def deprecated_function():
- warnings.warn("deprecated", DeprecationWarning)
-
- def test_one():
- deprecated_function()
-
- def test_two():
- pytest.deprecated_call(deprecated_function)
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines('*=== 2 passed in *===')
-
-
-class TestWarns(object):
- def test_strings(self):
- # different messages, b/c Python suppresses multiple identical warnings
- source1 = "warnings.warn('w1', RuntimeWarning)"
- source2 = "warnings.warn('w2', RuntimeWarning)"
- source3 = "warnings.warn('w3', RuntimeWarning)"
- pytest.warns(RuntimeWarning, source1)
- pytest.raises(pytest.fail.Exception,
- lambda: pytest.warns(UserWarning, source2))
- pytest.warns(RuntimeWarning, source3)
-
- def test_function(self):
- pytest.warns(SyntaxWarning,
- lambda msg: warnings.warn(msg, SyntaxWarning), "syntax")
-
- def test_warning_tuple(self):
- pytest.warns((RuntimeWarning, SyntaxWarning),
- lambda: warnings.warn('w1', RuntimeWarning))
- pytest.warns((RuntimeWarning, SyntaxWarning),
- lambda: warnings.warn('w2', SyntaxWarning))
- pytest.raises(pytest.fail.Exception,
- lambda: pytest.warns(
- (RuntimeWarning, SyntaxWarning),
- lambda: warnings.warn('w3', UserWarning)))
-
- def test_as_contextmanager(self):
- with pytest.warns(RuntimeWarning):
- warnings.warn("runtime", RuntimeWarning)
-
- with pytest.raises(pytest.fail.Exception):
- with pytest.warns(RuntimeWarning):
- warnings.warn("user", UserWarning)
-
- with pytest.raises(pytest.fail.Exception):
- with pytest.warns(UserWarning):
- warnings.warn("runtime", RuntimeWarning)
-
- with pytest.warns(UserWarning):
- warnings.warn("user", UserWarning)
-
- def test_record(self):
- with pytest.warns(UserWarning) as record:
- warnings.warn("user", UserWarning)
-
- assert len(record) == 1
- assert str(record[0].message) == "user"
-
- def test_record_only(self):
- with pytest.warns(None) as record:
- warnings.warn("user", UserWarning)
- warnings.warn("runtime", RuntimeWarning)
-
- assert len(record) == 2
- assert str(record[0].message) == "user"
- assert str(record[1].message) == "runtime"
-
- def test_double_test(self, testdir):
- """If a test is run again, the warning should still be raised"""
- testdir.makepyfile('''
- import pytest
- import warnings
-
- @pytest.mark.parametrize('run', [1, 2])
- def test(run):
- with pytest.warns(RuntimeWarning):
- warnings.warn("runtime", RuntimeWarning)
- ''')
- result = testdir.runpytest()
- result.stdout.fnmatch_lines(['*2 passed in*'])
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_resultlog.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_resultlog.py
deleted file mode 100644
index 74d13f64330..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_resultlog.py
+++ /dev/null
@@ -1,236 +0,0 @@
-import os
-
-import _pytest._code
-import py
-import pytest
-from _pytest.main import Node, Item, FSCollector
-from _pytest.resultlog import generic_path, ResultLog, \
- pytest_configure, pytest_unconfigure
-
-
-def test_generic_path(testdir):
- from _pytest.main import Session
- config = testdir.parseconfig()
- session = Session(config)
- p1 = Node('a', config=config, session=session)
- #assert p1.fspath is None
- p2 = Node('B', parent=p1)
- p3 = Node('()', parent = p2)
- item = Item('c', parent = p3)
-
- res = generic_path(item)
- assert res == 'a.B().c'
-
- p0 = FSCollector('proj/test', config=config, session=session)
- p1 = FSCollector('proj/test/a', parent=p0)
- p2 = Node('B', parent=p1)
- p3 = Node('()', parent = p2)
- p4 = Node('c', parent=p3)
- item = Item('[1]', parent = p4)
-
- res = generic_path(item)
- assert res == 'test/a:B().c[1]'
-
-def test_write_log_entry():
- reslog = ResultLog(None, None)
- reslog.logfile = py.io.TextIO()
- reslog.write_log_entry('name', '.', '')
- entry = reslog.logfile.getvalue()
- assert entry[-1] == '\n'
- entry_lines = entry.splitlines()
- assert len(entry_lines) == 1
- assert entry_lines[0] == '. name'
-
- reslog.logfile = py.io.TextIO()
- reslog.write_log_entry('name', 's', 'Skipped')
- entry = reslog.logfile.getvalue()
- assert entry[-1] == '\n'
- entry_lines = entry.splitlines()
- assert len(entry_lines) == 2
- assert entry_lines[0] == 's name'
- assert entry_lines[1] == ' Skipped'
-
- reslog.logfile = py.io.TextIO()
- reslog.write_log_entry('name', 's', 'Skipped\n')
- entry = reslog.logfile.getvalue()
- assert entry[-1] == '\n'
- entry_lines = entry.splitlines()
- assert len(entry_lines) == 2
- assert entry_lines[0] == 's name'
- assert entry_lines[1] == ' Skipped'
-
- reslog.logfile = py.io.TextIO()
- longrepr = ' tb1\n tb 2\nE tb3\nSome Error'
- reslog.write_log_entry('name', 'F', longrepr)
- entry = reslog.logfile.getvalue()
- assert entry[-1] == '\n'
- entry_lines = entry.splitlines()
- assert len(entry_lines) == 5
- assert entry_lines[0] == 'F name'
- assert entry_lines[1:] == [' '+line for line in longrepr.splitlines()]
-
-
-class TestWithFunctionIntegration:
- # XXX (hpk) i think that the resultlog plugin should
- # provide a Parser object so that one can remain
- # ignorant regarding formatting details.
- def getresultlog(self, testdir, arg):
- resultlog = testdir.tmpdir.join("resultlog")
- testdir.plugins.append("resultlog")
- args = ["--resultlog=%s" % resultlog] + [arg]
- testdir.runpytest(*args)
- return [x for x in resultlog.readlines(cr=0) if x]
-
- def test_collection_report(self, testdir):
- ok = testdir.makepyfile(test_collection_ok="")
- skip = testdir.makepyfile(test_collection_skip=
- "import pytest ; pytest.skip('hello')")
- fail = testdir.makepyfile(test_collection_fail="XXX")
- lines = self.getresultlog(testdir, ok)
- assert not lines
-
- lines = self.getresultlog(testdir, skip)
- assert len(lines) == 2
- assert lines[0].startswith("S ")
- assert lines[0].endswith("test_collection_skip.py")
- assert lines[1].startswith(" ")
- assert lines[1].endswith("test_collection_skip.py:1: Skipped: hello")
-
- lines = self.getresultlog(testdir, fail)
- assert lines
- assert lines[0].startswith("F ")
- assert lines[0].endswith("test_collection_fail.py"), lines[0]
- for x in lines[1:]:
- assert x.startswith(" ")
- assert "XXX" in "".join(lines[1:])
-
- def test_log_test_outcomes(self, testdir):
- mod = testdir.makepyfile(test_mod="""
- import pytest
- def test_pass(): pass
- def test_skip(): pytest.skip("hello")
- def test_fail(): raise ValueError("FAIL")
-
- @pytest.mark.xfail
- def test_xfail(): raise ValueError("XFAIL")
- @pytest.mark.xfail
- def test_xpass(): pass
-
- """)
- lines = self.getresultlog(testdir, mod)
- assert len(lines) >= 3
- assert lines[0].startswith(". ")
- assert lines[0].endswith("test_pass")
- assert lines[1].startswith("s "), lines[1]
- assert lines[1].endswith("test_skip")
- assert lines[2].find("hello") != -1
-
- assert lines[3].startswith("F ")
- assert lines[3].endswith("test_fail")
- tb = "".join(lines[4:8])
- assert tb.find('raise ValueError("FAIL")') != -1
-
- assert lines[8].startswith('x ')
- tb = "".join(lines[8:14])
- assert tb.find('raise ValueError("XFAIL")') != -1
-
- assert lines[14].startswith('X ')
- assert len(lines) == 15
-
- @pytest.mark.parametrize("style", ("native", "long", "short"))
- def test_internal_exception(self, style):
- # they are produced for example by a teardown failing
- # at the end of the run or a failing hook invocation
- try:
- raise ValueError
- except ValueError:
- excinfo = _pytest._code.ExceptionInfo()
- reslog = ResultLog(None, py.io.TextIO())
- reslog.pytest_internalerror(excinfo.getrepr(style=style))
- entry = reslog.logfile.getvalue()
- entry_lines = entry.splitlines()
-
- assert entry_lines[0].startswith('! ')
- if style != "native":
- assert os.path.basename(__file__)[:-9] in entry_lines[0] #.pyc/class
- assert entry_lines[-1][0] == ' '
- assert 'ValueError' in entry
-
-
-def test_generic(testdir, LineMatcher):
- testdir.plugins.append("resultlog")
- testdir.makepyfile("""
- import pytest
- def test_pass():
- pass
- def test_fail():
- assert 0
- def test_skip():
- pytest.skip("")
- @pytest.mark.xfail
- def test_xfail():
- assert 0
- @pytest.mark.xfail(run=False)
- def test_xfail_norun():
- assert 0
- """)
- testdir.runpytest("--resultlog=result.log")
- lines = testdir.tmpdir.join("result.log").readlines(cr=0)
- LineMatcher(lines).fnmatch_lines([
- ". *:test_pass",
- "F *:test_fail",
- "s *:test_skip",
- "x *:test_xfail",
- "x *:test_xfail_norun",
- ])
-
-def test_makedir_for_resultlog(testdir, LineMatcher):
- """--resultlog should automatically create directories for the log file"""
- testdir.plugins.append("resultlog")
- testdir.makepyfile("""
- import pytest
- def test_pass():
- pass
- """)
- testdir.runpytest("--resultlog=path/to/result.log")
- lines = testdir.tmpdir.join("path/to/result.log").readlines(cr=0)
- LineMatcher(lines).fnmatch_lines([
- ". *:test_pass",
- ])
-
-
-def test_no_resultlog_on_slaves(testdir):
- config = testdir.parseconfig("-p", "resultlog", "--resultlog=resultlog")
-
- assert not hasattr(config, '_resultlog')
- pytest_configure(config)
- assert hasattr(config, '_resultlog')
- pytest_unconfigure(config)
- assert not hasattr(config, '_resultlog')
-
- config.slaveinput = {}
- pytest_configure(config)
- assert not hasattr(config, '_resultlog')
- pytest_unconfigure(config)
- assert not hasattr(config, '_resultlog')
-
-
-def test_failure_issue380(testdir):
- testdir.makeconftest("""
- import pytest
- class MyCollector(pytest.File):
- def collect(self):
- raise ValueError()
- def repr_failure(self, excinfo):
- return "somestring"
- def pytest_collect_file(path, parent):
- return MyCollector(parent=parent, fspath=path)
- """)
- testdir.makepyfile("""
- def test_func():
- pass
- """)
- result = testdir.runpytest("--resultlog=log")
- assert result.ret == 1
-
-
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_runner.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_runner.py
deleted file mode 100644
index 4421c5d0d29..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_runner.py
+++ /dev/null
@@ -1,634 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import with_statement
-
-import _pytest._code
-import os
-import py
-import pytest
-import sys
-from _pytest import runner, main
-
-class TestSetupState:
- def test_setup(self, testdir):
- ss = runner.SetupState()
- item = testdir.getitem("def test_func(): pass")
- l = [1]
- ss.prepare(item)
- ss.addfinalizer(l.pop, colitem=item)
- assert l
- ss._pop_and_teardown()
- assert not l
-
- def test_teardown_exact_stack_empty(self, testdir):
- item = testdir.getitem("def test_func(): pass")
- ss = runner.SetupState()
- ss.teardown_exact(item, None)
- ss.teardown_exact(item, None)
- ss.teardown_exact(item, None)
-
- def test_setup_fails_and_failure_is_cached(self, testdir):
- item = testdir.getitem("""
- def setup_module(mod):
- raise ValueError(42)
- def test_func(): pass
- """) # noqa
- ss = runner.SetupState()
- pytest.raises(ValueError, lambda: ss.prepare(item))
- pytest.raises(ValueError, lambda: ss.prepare(item))
-
- def test_teardown_multiple_one_fails(self, testdir):
- r = []
- def fin1(): r.append('fin1')
- def fin2(): raise Exception('oops')
- def fin3(): r.append('fin3')
- item = testdir.getitem("def test_func(): pass")
- ss = runner.SetupState()
- ss.addfinalizer(fin1, item)
- ss.addfinalizer(fin2, item)
- ss.addfinalizer(fin3, item)
- with pytest.raises(Exception) as err:
- ss._callfinalizers(item)
- assert err.value.args == ('oops',)
- assert r == ['fin3', 'fin1']
-
- def test_teardown_multiple_fail(self, testdir):
- # Ensure the first exception is the one which is re-raised.
- # Ideally both would be reported however.
- def fin1(): raise Exception('oops1')
- def fin2(): raise Exception('oops2')
- item = testdir.getitem("def test_func(): pass")
- ss = runner.SetupState()
- ss.addfinalizer(fin1, item)
- ss.addfinalizer(fin2, item)
- with pytest.raises(Exception) as err:
- ss._callfinalizers(item)
- assert err.value.args == ('oops2',)
-
-
-class BaseFunctionalTests:
- def test_passfunction(self, testdir):
- reports = testdir.runitem("""
- def test_func():
- pass
- """)
- rep = reports[1]
- assert rep.passed
- assert not rep.failed
- assert rep.outcome == "passed"
- assert not rep.longrepr
-
- def test_failfunction(self, testdir):
- reports = testdir.runitem("""
- def test_func():
- assert 0
- """)
- rep = reports[1]
- assert not rep.passed
- assert not rep.skipped
- assert rep.failed
- assert rep.when == "call"
- assert rep.outcome == "failed"
- #assert isinstance(rep.longrepr, ReprExceptionInfo)
-
- def test_skipfunction(self, testdir):
- reports = testdir.runitem("""
- import pytest
- def test_func():
- pytest.skip("hello")
- """)
- rep = reports[1]
- assert not rep.failed
- assert not rep.passed
- assert rep.skipped
- assert rep.outcome == "skipped"
- #assert rep.skipped.when == "call"
- #assert rep.skipped.when == "call"
- #assert rep.skipped == "%sreason == "hello"
- #assert rep.skipped.location.lineno == 3
- #assert rep.skipped.location.path
- #assert not rep.skipped.failurerepr
-
- def test_skip_in_setup_function(self, testdir):
- reports = testdir.runitem("""
- import pytest
- def setup_function(func):
- pytest.skip("hello")
- def test_func():
- pass
- """)
- print(reports)
- rep = reports[0]
- assert not rep.failed
- assert not rep.passed
- assert rep.skipped
- #assert rep.skipped.reason == "hello"
- #assert rep.skipped.location.lineno == 3
- #assert rep.skipped.location.lineno == 3
- assert len(reports) == 2
- assert reports[1].passed # teardown
-
- def test_failure_in_setup_function(self, testdir):
- reports = testdir.runitem("""
- import pytest
- def setup_function(func):
- raise ValueError(42)
- def test_func():
- pass
- """)
- rep = reports[0]
- assert not rep.skipped
- assert not rep.passed
- assert rep.failed
- assert rep.when == "setup"
- assert len(reports) == 2
-
- def test_failure_in_teardown_function(self, testdir):
- reports = testdir.runitem("""
- import pytest
- def teardown_function(func):
- raise ValueError(42)
- def test_func():
- pass
- """)
- print(reports)
- assert len(reports) == 3
- rep = reports[2]
- assert not rep.skipped
- assert not rep.passed
- assert rep.failed
- assert rep.when == "teardown"
- #assert rep.longrepr.reprcrash.lineno == 3
- #assert rep.longrepr.reprtraceback.reprentries
-
- def test_custom_failure_repr(self, testdir):
- testdir.makepyfile(conftest="""
- import pytest
- class Function(pytest.Function):
- def repr_failure(self, excinfo):
- return "hello"
- """)
- reports = testdir.runitem("""
- import pytest
- def test_func():
- assert 0
- """)
- rep = reports[1]
- assert not rep.skipped
- assert not rep.passed
- assert rep.failed
- #assert rep.outcome.when == "call"
- #assert rep.failed.where.lineno == 3
- #assert rep.failed.where.path.basename == "test_func.py"
- #assert rep.failed.failurerepr == "hello"
-
- def test_teardown_final_returncode(self, testdir):
- rec = testdir.inline_runsource("""
- def test_func():
- pass
- def teardown_function(func):
- raise ValueError(42)
- """)
- assert rec.ret == 1
-
- def test_exact_teardown_issue90(self, testdir):
- rec = testdir.inline_runsource("""
- import pytest
-
- class TestClass:
- def test_method(self):
- pass
- def teardown_class(cls):
- raise Exception()
-
- def test_func():
- import sys
- # on python2 exc_info is keept till a function exits
- # so we would end up calling test functions while
- # sys.exc_info would return the indexerror
- # from guessing the lastitem
- excinfo = sys.exc_info()
- import traceback
- assert excinfo[0] is None, \
- traceback.format_exception(*excinfo)
- def teardown_function(func):
- raise ValueError(42)
- """)
- reps = rec.getreports("pytest_runtest_logreport")
- print (reps)
- for i in range(2):
- assert reps[i].nodeid.endswith("test_method")
- assert reps[i].passed
- assert reps[2].when == "teardown"
- assert reps[2].failed
- assert len(reps) == 6
- for i in range(3,5):
- assert reps[i].nodeid.endswith("test_func")
- assert reps[i].passed
- assert reps[5].when == "teardown"
- assert reps[5].nodeid.endswith("test_func")
- assert reps[5].failed
-
- def test_failure_in_setup_function_ignores_custom_repr(self, testdir):
- testdir.makepyfile(conftest="""
- import pytest
- class Function(pytest.Function):
- def repr_failure(self, excinfo):
- assert 0
- """)
- reports = testdir.runitem("""
- def setup_function(func):
- raise ValueError(42)
- def test_func():
- pass
- """)
- assert len(reports) == 2
- rep = reports[0]
- print(rep)
- assert not rep.skipped
- assert not rep.passed
- assert rep.failed
- #assert rep.outcome.when == "setup"
- #assert rep.outcome.where.lineno == 3
- #assert rep.outcome.where.path.basename == "test_func.py"
- #assert instanace(rep.failed.failurerepr, PythonFailureRepr)
-
- def test_systemexit_does_not_bail_out(self, testdir):
- try:
- reports = testdir.runitem("""
- def test_func():
- raise SystemExit(42)
- """)
- except SystemExit:
- pytest.fail("runner did not catch SystemExit")
- rep = reports[1]
- assert rep.failed
- assert rep.when == "call"
-
- def test_exit_propagates(self, testdir):
- try:
- testdir.runitem("""
- import pytest
- def test_func():
- raise pytest.exit.Exception()
- """)
- except pytest.exit.Exception:
- pass
- else:
- pytest.fail("did not raise")
-
-class TestExecutionNonForked(BaseFunctionalTests):
- def getrunner(self):
- def f(item):
- return runner.runtestprotocol(item, log=False)
- return f
-
- def test_keyboardinterrupt_propagates(self, testdir):
- try:
- testdir.runitem("""
- def test_func():
- raise KeyboardInterrupt("fake")
- """)
- except KeyboardInterrupt:
- pass
- else:
- pytest.fail("did not raise")
-
-class TestExecutionForked(BaseFunctionalTests):
- pytestmark = pytest.mark.skipif("not hasattr(os, 'fork')")
-
- def getrunner(self):
- # XXX re-arrange this test to live in pytest-xdist
- boxed = pytest.importorskip("xdist.boxed")
- return boxed.forked_run_report
-
- def test_suicide(self, testdir):
- reports = testdir.runitem("""
- def test_func():
- import os
- os.kill(os.getpid(), 15)
- """)
- rep = reports[0]
- assert rep.failed
- assert rep.when == "???"
-
-class TestSessionReports:
- def test_collect_result(self, testdir):
- col = testdir.getmodulecol("""
- def test_func1():
- pass
- class TestClass:
- pass
- """)
- rep = runner.collect_one_node(col)
- assert not rep.failed
- assert not rep.skipped
- assert rep.passed
- locinfo = rep.location
- assert locinfo[0] == col.fspath.basename
- assert not locinfo[1]
- assert locinfo[2] == col.fspath.basename
- res = rep.result
- assert len(res) == 2
- assert res[0].name == "test_func1"
- assert res[1].name == "TestClass"
-
- def test_skip_at_module_scope(self, testdir):
- col = testdir.getmodulecol("""
- import pytest
- pytest.skip("hello")
- def test_func():
- pass
- """)
- rep = main.collect_one_node(col)
- assert not rep.failed
- assert not rep.passed
- assert rep.skipped
-
-
-reporttypes = [
- runner.BaseReport,
- runner.TestReport,
- runner.TeardownErrorReport,
- runner.CollectReport,
-]
-
-@pytest.mark.parametrize('reporttype', reporttypes, ids=[x.__name__ for x in reporttypes])
-def test_report_extra_parameters(reporttype):
- if hasattr(py.std.inspect, 'signature'):
- args = list(py.std.inspect.signature(reporttype.__init__).parameters.keys())[1:]
- else:
- args = py.std.inspect.getargspec(reporttype.__init__)[0][1:]
- basekw = dict.fromkeys(args, [])
- report = reporttype(newthing=1, **basekw)
- assert report.newthing == 1
-
-def test_callinfo():
- ci = runner.CallInfo(lambda: 0, '123')
- assert ci.when == "123"
- assert ci.result == 0
- assert "result" in repr(ci)
- ci = runner.CallInfo(lambda: 0/0, '123')
- assert ci.when == "123"
- assert not hasattr(ci, 'result')
- assert ci.excinfo
- assert "exc" in repr(ci)
-
-# design question: do we want general hooks in python files?
-# then something like the following functional tests makes sense
-@pytest.mark.xfail
-def test_runtest_in_module_ordering(testdir):
- p1 = testdir.makepyfile("""
- def pytest_runtest_setup(item): # runs after class-level!
- item.function.mylist.append("module")
- class TestClass:
- def pytest_runtest_setup(self, item):
- assert not hasattr(item.function, 'mylist')
- item.function.mylist = ['class']
- def pytest_funcarg__mylist(self, request):
- return request.function.mylist
- def pytest_runtest_call(self, item, __multicall__):
- try:
- __multicall__.execute()
- except ValueError:
- pass
- def test_hello1(self, mylist):
- assert mylist == ['class', 'module'], mylist
- raise ValueError()
- def test_hello2(self, mylist):
- assert mylist == ['class', 'module'], mylist
- def pytest_runtest_teardown(item):
- del item.function.mylist
- """)
- result = testdir.runpytest(p1)
- result.stdout.fnmatch_lines([
- "*2 passed*"
- ])
-
-
-def test_outcomeexception_exceptionattributes():
- outcome = runner.OutcomeException('test')
- assert outcome.args[0] == outcome.msg
-
-def test_pytest_exit():
- try:
- pytest.exit("hello")
- except pytest.exit.Exception:
- excinfo = _pytest._code.ExceptionInfo()
- assert excinfo.errisinstance(KeyboardInterrupt)
-
-def test_pytest_fail():
- try:
- pytest.fail("hello")
- except pytest.fail.Exception:
- excinfo = _pytest._code.ExceptionInfo()
- s = excinfo.exconly(tryshort=True)
- assert s.startswith("Failed")
-
-def test_pytest_fail_notrace(testdir):
- testdir.makepyfile("""
- import pytest
- def test_hello():
- pytest.fail("hello", pytrace=False)
- def teardown_function(function):
- pytest.fail("world", pytrace=False)
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "world",
- "hello",
- ])
- assert 'def teardown_function' not in result.stdout.str()
-
-
-@pytest.mark.parametrize('str_prefix', ['u', ''])
-def test_pytest_fail_notrace_non_ascii(testdir, str_prefix):
- """Fix pytest.fail with pytrace=False with non-ascii characters (#1178).
-
- This tests with native and unicode strings containing non-ascii chars.
- """
- testdir.makepyfile(u"""
- # coding: utf-8
- import pytest
-
- def test_hello():
- pytest.fail(%s'oh oh: ☺', pytrace=False)
- """ % str_prefix)
- result = testdir.runpytest()
- if sys.version_info[0] >= 3:
- result.stdout.fnmatch_lines(['*test_hello*', "oh oh: ☺"])
- else:
- result.stdout.fnmatch_lines(['*test_hello*', "oh oh: *"])
- assert 'def test_hello' not in result.stdout.str()
-
-
-def test_pytest_no_tests_collected_exit_status(testdir):
- result = testdir.runpytest()
- result.stdout.fnmatch_lines('*collected 0 items*')
- assert result.ret == main.EXIT_NOTESTSCOLLECTED
-
- testdir.makepyfile(test_foo="""
- def test_foo():
- assert 1
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines('*collected 1 items*')
- result.stdout.fnmatch_lines('*1 passed*')
- assert result.ret == main.EXIT_OK
-
- result = testdir.runpytest('-k nonmatch')
- result.stdout.fnmatch_lines('*collected 1 items*')
- result.stdout.fnmatch_lines('*1 deselected*')
- assert result.ret == main.EXIT_NOTESTSCOLLECTED
-
-
-def test_exception_printing_skip():
- try:
- pytest.skip("hello")
- except pytest.skip.Exception:
- excinfo = _pytest._code.ExceptionInfo()
- s = excinfo.exconly(tryshort=True)
- assert s.startswith("Skipped")
-
-def test_importorskip(monkeypatch):
- importorskip = pytest.importorskip
- def f():
- importorskip("asdlkj")
- try:
- sys = importorskip("sys") # noqa
- assert sys == py.std.sys
- #path = pytest.importorskip("os.path")
- #assert path == py.std.os.path
- excinfo = pytest.raises(pytest.skip.Exception, f)
- path = py.path.local(excinfo.getrepr().reprcrash.path)
- # check that importorskip reports the actual call
- # in this test the test_runner.py file
- assert path.purebasename == "test_runner"
- pytest.raises(SyntaxError, "pytest.importorskip('x y z')")
- pytest.raises(SyntaxError, "pytest.importorskip('x=y')")
- mod = py.std.types.ModuleType("hello123")
- mod.__version__ = "1.3"
- monkeypatch.setitem(sys.modules, "hello123", mod)
- pytest.raises(pytest.skip.Exception, """
- pytest.importorskip("hello123", minversion="1.3.1")
- """)
- mod2 = pytest.importorskip("hello123", minversion="1.3")
- assert mod2 == mod
- except pytest.skip.Exception:
- print(_pytest._code.ExceptionInfo())
- pytest.fail("spurious skip")
-
-def test_importorskip_imports_last_module_part():
- ospath = pytest.importorskip("os.path")
- assert os.path == ospath
-
-def test_importorskip_dev_module(monkeypatch):
- try:
- mod = py.std.types.ModuleType("mockmodule")
- mod.__version__ = '0.13.0.dev-43290'
- monkeypatch.setitem(sys.modules, 'mockmodule', mod)
- mod2 = pytest.importorskip('mockmodule', minversion='0.12.0')
- assert mod2 == mod
- pytest.raises(pytest.skip.Exception, """
- pytest.importorskip('mockmodule1', minversion='0.14.0')""")
- except pytest.skip.Exception:
- print(_pytest._code.ExceptionInfo())
- pytest.fail("spurious skip")
-
-
-def test_pytest_cmdline_main(testdir):
- p = testdir.makepyfile("""
- import pytest
- def test_hello():
- assert 1
- if __name__ == '__main__':
- pytest.cmdline.main([__file__])
- """)
- import subprocess
- popen = subprocess.Popen([sys.executable, str(p)], stdout=subprocess.PIPE)
- popen.communicate()
- ret = popen.wait()
- assert ret == 0
-
-
-def test_unicode_in_longrepr(testdir):
- testdir.makeconftest("""
- import py
- def pytest_runtest_makereport(__multicall__):
- rep = __multicall__.execute()
- if rep.when == "call":
- rep.longrepr = py.builtin._totext("\\xc3\\xa4", "utf8")
- return rep
- """)
- testdir.makepyfile("""
- def test_out():
- assert 0
- """)
- result = testdir.runpytest()
- assert result.ret == 1
- assert "UnicodeEncodeError" not in result.stderr.str()
-
-
-def test_failure_in_setup(testdir):
- testdir.makepyfile("""
- def setup_module():
- 0/0
- def test_func():
- pass
- """)
- result = testdir.runpytest("--tb=line")
- assert "def setup_module" not in result.stdout.str()
-
-
-def test_makereport_getsource(testdir):
- testdir.makepyfile("""
- def test_foo():
- if False: pass
- else: assert False
- """)
- result = testdir.runpytest()
- assert 'INTERNALERROR' not in result.stdout.str()
- result.stdout.fnmatch_lines(['*else: assert False*'])
-
-
-def test_makereport_getsource_dynamic_code(testdir, monkeypatch):
- """Test that exception in dynamically generated code doesn't break getting the source line."""
- import inspect
- original_findsource = inspect.findsource
- def findsource(obj, *args, **kwargs):
- # Can be triggered by dynamically created functions
- if obj.__name__ == 'foo':
- raise IndexError()
- return original_findsource(obj, *args, **kwargs)
- monkeypatch.setattr(inspect, 'findsource', findsource)
-
- testdir.makepyfile("""
- import pytest
-
- @pytest.fixture
- def foo(missing):
- pass
-
- def test_fix(foo):
- assert False
- """)
- result = testdir.runpytest('-vv')
- assert 'INTERNALERROR' not in result.stdout.str()
- result.stdout.fnmatch_lines(["*test_fix*", "*fixture*'missing'*not found*"])
-
-
-def test_store_except_info_on_eror():
- """ Test that upon test failure, the exception info is stored on
- sys.last_traceback and friends.
- """
- # Simulate item that raises a specific exception
- class ItemThatRaises:
- def runtest(self):
- raise IndexError('TEST')
- try:
- runner.pytest_runtest_call(ItemThatRaises())
- except IndexError:
- pass
- # Check that exception info is stored on sys
- assert sys.last_type is IndexError
- assert sys.last_value.args[0] == 'TEST'
- assert sys.last_traceback
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_runner_xunit.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_runner_xunit.py
deleted file mode 100644
index f32a1311ba8..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_runner_xunit.py
+++ /dev/null
@@ -1,252 +0,0 @@
-#
-# test correct setup/teardowns at
-# module, class, and instance level
-
-def test_module_and_function_setup(testdir):
- reprec = testdir.inline_runsource("""
- modlevel = []
- def setup_module(module):
- assert not modlevel
- module.modlevel.append(42)
-
- def teardown_module(module):
- modlevel.pop()
-
- def setup_function(function):
- function.answer = 17
-
- def teardown_function(function):
- del function.answer
-
- def test_modlevel():
- assert modlevel[0] == 42
- assert test_modlevel.answer == 17
-
- class TestFromClass:
- def test_module(self):
- assert modlevel[0] == 42
- assert not hasattr(test_modlevel, 'answer')
- """)
- rep = reprec.matchreport("test_modlevel")
- assert rep.passed
- rep = reprec.matchreport("test_module")
- assert rep.passed
-
-def test_module_setup_failure_no_teardown(testdir):
- reprec = testdir.inline_runsource("""
- l = []
- def setup_module(module):
- l.append(1)
- 0/0
-
- def test_nothing():
- pass
-
- def teardown_module(module):
- l.append(2)
- """)
- reprec.assertoutcome(failed=1)
- calls = reprec.getcalls("pytest_runtest_setup")
- assert calls[0].item.module.l == [1]
-
-def test_setup_function_failure_no_teardown(testdir):
- reprec = testdir.inline_runsource("""
- modlevel = []
- def setup_function(function):
- modlevel.append(1)
- 0/0
-
- def teardown_function(module):
- modlevel.append(2)
-
- def test_func():
- pass
- """)
- calls = reprec.getcalls("pytest_runtest_setup")
- assert calls[0].item.module.modlevel == [1]
-
-def test_class_setup(testdir):
- reprec = testdir.inline_runsource("""
- class TestSimpleClassSetup:
- clslevel = []
- def setup_class(cls):
- cls.clslevel.append(23)
-
- def teardown_class(cls):
- cls.clslevel.pop()
-
- def test_classlevel(self):
- assert self.clslevel[0] == 23
-
- class TestInheritedClassSetupStillWorks(TestSimpleClassSetup):
- def test_classlevel_anothertime(self):
- assert self.clslevel == [23]
-
- def test_cleanup():
- assert not TestSimpleClassSetup.clslevel
- assert not TestInheritedClassSetupStillWorks.clslevel
- """)
- reprec.assertoutcome(passed=1+2+1)
-
-def test_class_setup_failure_no_teardown(testdir):
- reprec = testdir.inline_runsource("""
- class TestSimpleClassSetup:
- clslevel = []
- def setup_class(cls):
- 0/0
-
- def teardown_class(cls):
- cls.clslevel.append(1)
-
- def test_classlevel(self):
- pass
-
- def test_cleanup():
- assert not TestSimpleClassSetup.clslevel
- """)
- reprec.assertoutcome(failed=1, passed=1)
-
-def test_method_setup(testdir):
- reprec = testdir.inline_runsource("""
- class TestSetupMethod:
- def setup_method(self, meth):
- self.methsetup = meth
- def teardown_method(self, meth):
- del self.methsetup
-
- def test_some(self):
- assert self.methsetup == self.test_some
-
- def test_other(self):
- assert self.methsetup == self.test_other
- """)
- reprec.assertoutcome(passed=2)
-
-def test_method_setup_failure_no_teardown(testdir):
- reprec = testdir.inline_runsource("""
- class TestMethodSetup:
- clslevel = []
- def setup_method(self, method):
- self.clslevel.append(1)
- 0/0
-
- def teardown_method(self, method):
- self.clslevel.append(2)
-
- def test_method(self):
- pass
-
- def test_cleanup():
- assert TestMethodSetup.clslevel == [1]
- """)
- reprec.assertoutcome(failed=1, passed=1)
-
-def test_method_generator_setup(testdir):
- reprec = testdir.inline_runsource("""
- class TestSetupTeardownOnInstance:
- def setup_class(cls):
- cls.classsetup = True
-
- def setup_method(self, method):
- self.methsetup = method
-
- def test_generate(self):
- assert self.classsetup
- assert self.methsetup == self.test_generate
- yield self.generated, 5
- yield self.generated, 2
-
- def generated(self, value):
- assert self.classsetup
- assert self.methsetup == self.test_generate
- assert value == 5
- """)
- reprec.assertoutcome(passed=1, failed=1)
-
-def test_func_generator_setup(testdir):
- reprec = testdir.inline_runsource("""
- import sys
-
- def setup_module(mod):
- print ("setup_module")
- mod.x = []
-
- def setup_function(fun):
- print ("setup_function")
- x.append(1)
-
- def teardown_function(fun):
- print ("teardown_function")
- x.pop()
-
- def test_one():
- assert x == [1]
- def check():
- print ("check")
- sys.stderr.write("e\\n")
- assert x == [1]
- yield check
- assert x == [1]
- """)
- rep = reprec.matchreport("test_one", names="pytest_runtest_logreport")
- assert rep.passed
-
-def test_method_setup_uses_fresh_instances(testdir):
- reprec = testdir.inline_runsource("""
- class TestSelfState1:
- memory = []
- def test_hello(self):
- self.memory.append(self)
-
- def test_afterhello(self):
- assert self != self.memory[0]
- """)
- reprec.assertoutcome(passed=2, failed=0)
-
-def test_setup_that_skips_calledagain(testdir):
- p = testdir.makepyfile("""
- import pytest
- def setup_module(mod):
- pytest.skip("x")
- def test_function1():
- pass
- def test_function2():
- pass
- """)
- reprec = testdir.inline_run(p)
- reprec.assertoutcome(skipped=2)
-
-def test_setup_fails_again_on_all_tests(testdir):
- p = testdir.makepyfile("""
- import pytest
- def setup_module(mod):
- raise ValueError(42)
- def test_function1():
- pass
- def test_function2():
- pass
- """)
- reprec = testdir.inline_run(p)
- reprec.assertoutcome(failed=2)
-
-def test_setup_funcarg_setup_when_outer_scope_fails(testdir):
- p = testdir.makepyfile("""
- import pytest
- def setup_module(mod):
- raise ValueError(42)
- def pytest_funcarg__hello(request):
- raise ValueError("xyz43")
- def test_function1(hello):
- pass
- def test_function2(hello):
- pass
- """)
- result = testdir.runpytest(p)
- result.stdout.fnmatch_lines([
- "*function1*",
- "*ValueError*42*",
- "*function2*",
- "*ValueError*42*",
- "*2 error*"
- ])
- assert "xyz43" not in result.stdout.str()
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_session.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_session.py
deleted file mode 100644
index 76f804b4f99..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_session.py
+++ /dev/null
@@ -1,244 +0,0 @@
-import pytest
-
-from _pytest.main import EXIT_NOTESTSCOLLECTED
-
-class SessionTests:
- def test_basic_testitem_events(self, testdir):
- tfile = testdir.makepyfile("""
- def test_one():
- pass
- def test_one_one():
- assert 0
- def test_other():
- raise ValueError(23)
- class TestClass:
- def test_two(self, someargs):
- pass
- """)
- reprec = testdir.inline_run(tfile)
- passed, skipped, failed = reprec.listoutcomes()
- assert len(skipped) == 0
- assert len(passed) == 1
- assert len(failed) == 3
- end = lambda x: x.nodeid.split("::")[-1]
- assert end(failed[0]) == "test_one_one"
- assert end(failed[1]) == "test_other"
- itemstarted = reprec.getcalls("pytest_itemcollected")
- assert len(itemstarted) == 4
- # XXX check for failing funcarg setup
- #colreports = reprec.getcalls("pytest_collectreport")
- #assert len(colreports) == 4
- #assert colreports[1].report.failed
-
- def test_nested_import_error(self, testdir):
- tfile = testdir.makepyfile("""
- import import_fails
- def test_this():
- assert import_fails.a == 1
- """, import_fails="""
- import does_not_work
- a = 1
- """)
- reprec = testdir.inline_run(tfile)
- l = reprec.getfailedcollections()
- assert len(l) == 1
- out = l[0].longrepr.reprcrash.message
- assert out.find('does_not_work') != -1
-
- def test_raises_output(self, testdir):
- reprec = testdir.inline_runsource("""
- import pytest
- def test_raises_doesnt():
- pytest.raises(ValueError, int, "3")
- """)
- passed, skipped, failed = reprec.listoutcomes()
- assert len(failed) == 1
- out = failed[0].longrepr.reprcrash.message
- if not out.find("DID NOT RAISE") != -1:
- print(out)
- pytest.fail("incorrect raises() output")
-
- def test_generator_yields_None(self, testdir):
- reprec = testdir.inline_runsource("""
- def test_1():
- yield None
- """)
- failures = reprec.getfailedcollections()
- out = failures[0].longrepr.reprcrash.message
- i = out.find('TypeError')
- assert i != -1
-
- def test_syntax_error_module(self, testdir):
- reprec = testdir.inline_runsource("this is really not python")
- l = reprec.getfailedcollections()
- assert len(l) == 1
- out = str(l[0].longrepr)
- assert out.find(str('not python')) != -1
-
- def test_exit_first_problem(self, testdir):
- reprec = testdir.inline_runsource("""
- def test_one(): assert 0
- def test_two(): assert 0
- """, '--exitfirst')
- passed, skipped, failed = reprec.countoutcomes()
- assert failed == 1
- assert passed == skipped == 0
-
- def test_maxfail(self, testdir):
- reprec = testdir.inline_runsource("""
- def test_one(): assert 0
- def test_two(): assert 0
- def test_three(): assert 0
- """, '--maxfail=2')
- passed, skipped, failed = reprec.countoutcomes()
- assert failed == 2
- assert passed == skipped == 0
-
- def test_broken_repr(self, testdir):
- p = testdir.makepyfile("""
- import pytest
- class BrokenRepr1:
- foo=0
- def __repr__(self):
- raise Exception("Ha Ha fooled you, I'm a broken repr().")
-
- class TestBrokenClass:
- def test_explicit_bad_repr(self):
- t = BrokenRepr1()
- pytest.raises(Exception, 'repr(t)')
-
- def test_implicit_bad_repr1(self):
- t = BrokenRepr1()
- assert t.foo == 1
-
- """)
- reprec = testdir.inline_run(p)
- passed, skipped, failed = reprec.listoutcomes()
- assert len(failed) == 1
- out = failed[0].longrepr.reprcrash.message
- assert out.find("""[Exception("Ha Ha fooled you, I'm a broken repr().") raised in repr()]""") != -1 #'
-
- def test_skip_file_by_conftest(self, testdir):
- testdir.makepyfile(conftest="""
- import pytest
- def pytest_collect_file():
- pytest.skip("intentional")
- """, test_file="""
- def test_one(): pass
- """)
- try:
- reprec = testdir.inline_run(testdir.tmpdir)
- except pytest.skip.Exception:
- pytest.fail("wrong skipped caught")
- reports = reprec.getreports("pytest_collectreport")
- assert len(reports) == 1
- assert reports[0].skipped
-
-class TestNewSession(SessionTests):
-
- def test_order_of_execution(self, testdir):
- reprec = testdir.inline_runsource("""
- l = []
- def test_1():
- l.append(1)
- def test_2():
- l.append(2)
- def test_3():
- assert l == [1,2]
- class Testmygroup:
- reslist = l
- def test_1(self):
- self.reslist.append(1)
- def test_2(self):
- self.reslist.append(2)
- def test_3(self):
- self.reslist.append(3)
- def test_4(self):
- assert self.reslist == [1,2,1,2,3]
- """)
- passed, skipped, failed = reprec.countoutcomes()
- assert failed == skipped == 0
- assert passed == 7
- # also test listnames() here ...
-
- def test_collect_only_with_various_situations(self, testdir):
- p = testdir.makepyfile(
- test_one="""
- def test_one():
- raise ValueError()
-
- class TestX:
- def test_method_one(self):
- pass
-
- class TestY(TestX):
- pass
- """,
- test_two="""
- import pytest
- pytest.skip('xxx')
- """,
- test_three="xxxdsadsadsadsa",
- __init__=""
- )
- reprec = testdir.inline_run('--collect-only', p.dirpath())
-
- itemstarted = reprec.getcalls("pytest_itemcollected")
- assert len(itemstarted) == 3
- assert not reprec.getreports("pytest_runtest_logreport")
- started = reprec.getcalls("pytest_collectstart")
- finished = reprec.getreports("pytest_collectreport")
- assert len(started) == len(finished)
- assert len(started) == 8 # XXX extra TopCollector
- colfail = [x for x in finished if x.failed]
- colskipped = [x for x in finished if x.skipped]
- assert len(colfail) == 1
- assert len(colskipped) == 1
-
- def test_minus_x_import_error(self, testdir):
- testdir.makepyfile(__init__="")
- testdir.makepyfile(test_one="xxxx", test_two="yyyy")
- reprec = testdir.inline_run("-x", testdir.tmpdir)
- finished = reprec.getreports("pytest_collectreport")
- colfail = [x for x in finished if x.failed]
- assert len(colfail) == 1
-
-
-def test_plugin_specify(testdir):
- pytest.raises(ImportError, """
- testdir.parseconfig("-p", "nqweotexistent")
- """)
- #pytest.raises(ImportError,
- # "config.do_configure(config)"
- #)
-
-def test_plugin_already_exists(testdir):
- config = testdir.parseconfig("-p", "terminal")
- assert config.option.plugins == ['terminal']
- config._do_configure()
- config._ensure_unconfigure()
-
-def test_exclude(testdir):
- hellodir = testdir.mkdir("hello")
- hellodir.join("test_hello.py").write("x y syntaxerror")
- hello2dir = testdir.mkdir("hello2")
- hello2dir.join("test_hello2.py").write("x y syntaxerror")
- testdir.makepyfile(test_ok="def test_pass(): pass")
- result = testdir.runpytest("--ignore=hello", "--ignore=hello2")
- assert result.ret == 0
- result.stdout.fnmatch_lines(["*1 passed*"])
-
-def test_sessionfinish_with_start(testdir):
- testdir.makeconftest("""
- import os
- l = []
- def pytest_sessionstart():
- l.append(os.getcwd())
- os.chdir("..")
-
- def pytest_sessionfinish():
- assert l[0] == os.getcwd()
-
- """)
- res = testdir.runpytest("--collect-only")
- assert res.ret == EXIT_NOTESTSCOLLECTED
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_skipping.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_skipping.py
deleted file mode 100644
index 3464974e0c2..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_skipping.py
+++ /dev/null
@@ -1,917 +0,0 @@
-import pytest
-import sys
-
-from _pytest.skipping import MarkEvaluator, folded_skips, pytest_runtest_setup
-from _pytest.runner import runtestprotocol
-
-
-class TestEvaluator:
- def test_no_marker(self, testdir):
- item = testdir.getitem("def test_func(): pass")
- evalskipif = MarkEvaluator(item, 'skipif')
- assert not evalskipif
- assert not evalskipif.istrue()
-
- def test_marked_no_args(self, testdir):
- item = testdir.getitem("""
- import pytest
- @pytest.mark.xyz
- def test_func():
- pass
- """)
- ev = MarkEvaluator(item, 'xyz')
- assert ev
- assert ev.istrue()
- expl = ev.getexplanation()
- assert expl == ""
- assert not ev.get("run", False)
-
- def test_marked_one_arg(self, testdir):
- item = testdir.getitem("""
- import pytest
- @pytest.mark.xyz("hasattr(os, 'sep')")
- def test_func():
- pass
- """)
- ev = MarkEvaluator(item, 'xyz')
- assert ev
- assert ev.istrue()
- expl = ev.getexplanation()
- assert expl == "condition: hasattr(os, 'sep')"
-
- @pytest.mark.skipif('sys.version_info[0] >= 3')
- def test_marked_one_arg_unicode(self, testdir):
- item = testdir.getitem("""
- import pytest
- @pytest.mark.xyz(u"hasattr(os, 'sep')")
- def test_func():
- pass
- """)
- ev = MarkEvaluator(item, 'xyz')
- assert ev
- assert ev.istrue()
- expl = ev.getexplanation()
- assert expl == "condition: hasattr(os, 'sep')"
-
- def test_marked_one_arg_with_reason(self, testdir):
- item = testdir.getitem("""
- import pytest
- @pytest.mark.xyz("hasattr(os, 'sep')", attr=2, reason="hello world")
- def test_func():
- pass
- """)
- ev = MarkEvaluator(item, 'xyz')
- assert ev
- assert ev.istrue()
- expl = ev.getexplanation()
- assert expl == "hello world"
- assert ev.get("attr") == 2
-
- def test_marked_one_arg_twice(self, testdir):
- lines = [
- '''@pytest.mark.skipif("not hasattr(os, 'murks')")''',
- '''@pytest.mark.skipif("hasattr(os, 'murks')")'''
- ]
- for i in range(0, 2):
- item = testdir.getitem("""
- import pytest
- %s
- %s
- def test_func():
- pass
- """ % (lines[i], lines[(i+1) %2]))
- ev = MarkEvaluator(item, 'skipif')
- assert ev
- assert ev.istrue()
- expl = ev.getexplanation()
- assert expl == "condition: not hasattr(os, 'murks')"
-
- def test_marked_one_arg_twice2(self, testdir):
- item = testdir.getitem("""
- import pytest
- @pytest.mark.skipif("hasattr(os, 'murks')")
- @pytest.mark.skipif("not hasattr(os, 'murks')")
- def test_func():
- pass
- """)
- ev = MarkEvaluator(item, 'skipif')
- assert ev
- assert ev.istrue()
- expl = ev.getexplanation()
- assert expl == "condition: not hasattr(os, 'murks')"
-
- def test_marked_skip_with_not_string(self, testdir):
- item = testdir.getitem("""
- import pytest
- @pytest.mark.skipif(False)
- def test_func():
- pass
- """)
- ev = MarkEvaluator(item, 'skipif')
- exc = pytest.raises(pytest.fail.Exception, ev.istrue)
- assert """Failed: you need to specify reason=STRING when using booleans as conditions.""" in exc.value.msg
-
- def test_skipif_class(self, testdir):
- item, = testdir.getitems("""
- import pytest
- class TestClass:
- pytestmark = pytest.mark.skipif("config._hackxyz")
- def test_func(self):
- pass
- """)
- item.config._hackxyz = 3
- ev = MarkEvaluator(item, 'skipif')
- assert ev.istrue()
- expl = ev.getexplanation()
- assert expl == "condition: config._hackxyz"
-
-
-class TestXFail:
-
- @pytest.mark.parametrize('strict', [True, False])
- def test_xfail_simple(self, testdir, strict):
- item = testdir.getitem("""
- import pytest
- @pytest.mark.xfail(strict=%s)
- def test_func():
- assert 0
- """ % strict)
- reports = runtestprotocol(item, log=False)
- assert len(reports) == 3
- callreport = reports[1]
- assert callreport.skipped
- assert callreport.wasxfail == ""
-
- def test_xfail_xpassed(self, testdir):
- item = testdir.getitem("""
- import pytest
- @pytest.mark.xfail
- def test_func():
- assert 1
- """)
- reports = runtestprotocol(item, log=False)
- assert len(reports) == 3
- callreport = reports[1]
- assert callreport.failed
- assert callreport.wasxfail == ""
-
- def test_xfail_run_anyway(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.mark.xfail
- def test_func():
- assert 0
- def test_func2():
- pytest.xfail("hello")
- """)
- result = testdir.runpytest("--runxfail")
- result.stdout.fnmatch_lines([
- "*def test_func():*",
- "*assert 0*",
- "*1 failed*1 pass*",
- ])
-
- def test_xfail_evalfalse_but_fails(self, testdir):
- item = testdir.getitem("""
- import pytest
- @pytest.mark.xfail('False')
- def test_func():
- assert 0
- """)
- reports = runtestprotocol(item, log=False)
- callreport = reports[1]
- assert callreport.failed
- assert not hasattr(callreport, "wasxfail")
- assert 'xfail' in callreport.keywords
-
- def test_xfail_not_report_default(self, testdir):
- p = testdir.makepyfile(test_one="""
- import pytest
- @pytest.mark.xfail
- def test_this():
- assert 0
- """)
- testdir.runpytest(p, '-v')
- #result.stdout.fnmatch_lines([
- # "*HINT*use*-r*"
- #])
-
- def test_xfail_not_run_xfail_reporting(self, testdir):
- p = testdir.makepyfile(test_one="""
- import pytest
- @pytest.mark.xfail(run=False, reason="noway")
- def test_this():
- assert 0
- @pytest.mark.xfail("True", run=False)
- def test_this_true():
- assert 0
- @pytest.mark.xfail("False", run=False, reason="huh")
- def test_this_false():
- assert 1
- """)
- result = testdir.runpytest(p, '--report=xfailed', )
- result.stdout.fnmatch_lines([
- "*test_one*test_this*",
- "*NOTRUN*noway",
- "*test_one*test_this_true*",
- "*NOTRUN*condition:*True*",
- "*1 passed*",
- ])
-
- def test_xfail_not_run_no_setup_run(self, testdir):
- p = testdir.makepyfile(test_one="""
- import pytest
- @pytest.mark.xfail(run=False, reason="hello")
- def test_this():
- assert 0
- def setup_module(mod):
- raise ValueError(42)
- """)
- result = testdir.runpytest(p, '--report=xfailed', )
- result.stdout.fnmatch_lines([
- "*test_one*test_this*",
- "*NOTRUN*hello",
- "*1 xfailed*",
- ])
-
- def test_xfail_xpass(self, testdir):
- p = testdir.makepyfile(test_one="""
- import pytest
- @pytest.mark.xfail
- def test_that():
- assert 1
- """)
- result = testdir.runpytest(p, '-rX')
- result.stdout.fnmatch_lines([
- "*XPASS*test_that*",
- "*1 xpassed*"
- ])
- assert result.ret == 0
-
- def test_xfail_imperative(self, testdir):
- p = testdir.makepyfile("""
- import pytest
- def test_this():
- pytest.xfail("hello")
- """)
- result = testdir.runpytest(p)
- result.stdout.fnmatch_lines([
- "*1 xfailed*",
- ])
- result = testdir.runpytest(p, "-rx")
- result.stdout.fnmatch_lines([
- "*XFAIL*test_this*",
- "*reason:*hello*",
- ])
- result = testdir.runpytest(p, "--runxfail")
- result.stdout.fnmatch_lines("*1 pass*")
-
- def test_xfail_imperative_in_setup_function(self, testdir):
- p = testdir.makepyfile("""
- import pytest
- def setup_function(function):
- pytest.xfail("hello")
-
- def test_this():
- assert 0
- """)
- result = testdir.runpytest(p)
- result.stdout.fnmatch_lines([
- "*1 xfailed*",
- ])
- result = testdir.runpytest(p, "-rx")
- result.stdout.fnmatch_lines([
- "*XFAIL*test_this*",
- "*reason:*hello*",
- ])
- result = testdir.runpytest(p, "--runxfail")
- result.stdout.fnmatch_lines("""
- *def test_this*
- *1 fail*
- """)
-
- def xtest_dynamic_xfail_set_during_setup(self, testdir):
- p = testdir.makepyfile("""
- import pytest
- def setup_function(function):
- pytest.mark.xfail(function)
- def test_this():
- assert 0
- def test_that():
- assert 1
- """)
- result = testdir.runpytest(p, '-rxX')
- result.stdout.fnmatch_lines([
- "*XFAIL*test_this*",
- "*XPASS*test_that*",
- ])
-
- def test_dynamic_xfail_no_run(self, testdir):
- p = testdir.makepyfile("""
- import pytest
- def pytest_funcarg__arg(request):
- request.applymarker(pytest.mark.xfail(run=False))
- def test_this(arg):
- assert 0
- """)
- result = testdir.runpytest(p, '-rxX')
- result.stdout.fnmatch_lines([
- "*XFAIL*test_this*",
- "*NOTRUN*",
- ])
-
- def test_dynamic_xfail_set_during_funcarg_setup(self, testdir):
- p = testdir.makepyfile("""
- import pytest
- def pytest_funcarg__arg(request):
- request.applymarker(pytest.mark.xfail)
- def test_this2(arg):
- assert 0
- """)
- result = testdir.runpytest(p)
- result.stdout.fnmatch_lines([
- "*1 xfailed*",
- ])
-
-
- @pytest.mark.parametrize('expected, actual, matchline',
- [('TypeError', 'TypeError', "*1 xfailed*"),
- ('(AttributeError, TypeError)', 'TypeError', "*1 xfailed*"),
- ('TypeError', 'IndexError', "*1 failed*"),
- ('(AttributeError, TypeError)', 'IndexError', "*1 failed*"),
- ])
- def test_xfail_raises(self, expected, actual, matchline, testdir):
- p = testdir.makepyfile("""
- import pytest
- @pytest.mark.xfail(raises=%s)
- def test_raises():
- raise %s()
- """ % (expected, actual))
- result = testdir.runpytest(p)
- result.stdout.fnmatch_lines([
- matchline,
- ])
-
- def test_strict_sanity(self, testdir):
- """sanity check for xfail(strict=True): a failing test should behave
- exactly like a normal xfail.
- """
- p = testdir.makepyfile("""
- import pytest
- @pytest.mark.xfail(reason='unsupported feature', strict=True)
- def test_foo():
- assert 0
- """)
- result = testdir.runpytest(p, '-rxX')
- result.stdout.fnmatch_lines([
- '*XFAIL*',
- '*unsupported feature*',
- ])
- assert result.ret == 0
-
- @pytest.mark.parametrize('strict', [True, False])
- def test_strict_xfail(self, testdir, strict):
- p = testdir.makepyfile("""
- import pytest
-
- @pytest.mark.xfail(reason='unsupported feature', strict=%s)
- def test_foo():
- with open('foo_executed', 'w'): pass # make sure test executes
- """ % strict)
- result = testdir.runpytest(p, '-rxX')
- if strict:
- result.stdout.fnmatch_lines([
- '*test_foo*',
- '*XPASS(strict)*unsupported feature*',
- ])
- else:
- result.stdout.fnmatch_lines([
- '*test_strict_xfail*',
- 'XPASS test_strict_xfail.py::test_foo unsupported feature',
- ])
- assert result.ret == (1 if strict else 0)
- assert testdir.tmpdir.join('foo_executed').isfile()
-
- @pytest.mark.parametrize('strict', [True, False])
- def test_strict_xfail_condition(self, testdir, strict):
- p = testdir.makepyfile("""
- import pytest
-
- @pytest.mark.xfail(False, reason='unsupported feature', strict=%s)
- def test_foo():
- pass
- """ % strict)
- result = testdir.runpytest(p, '-rxX')
- result.stdout.fnmatch_lines('*1 passed*')
- assert result.ret == 0
-
- @pytest.mark.parametrize('strict_val', ['true', 'false'])
- def test_strict_xfail_default_from_file(self, testdir, strict_val):
- testdir.makeini('''
- [pytest]
- xfail_strict = %s
- ''' % strict_val)
- p = testdir.makepyfile("""
- import pytest
- @pytest.mark.xfail(reason='unsupported feature')
- def test_foo():
- pass
- """)
- result = testdir.runpytest(p, '-rxX')
- strict = strict_val == 'true'
- result.stdout.fnmatch_lines('*1 failed*' if strict else '*1 xpassed*')
- assert result.ret == (1 if strict else 0)
-
-
-class TestXFailwithSetupTeardown:
- def test_failing_setup_issue9(self, testdir):
- testdir.makepyfile("""
- import pytest
- def setup_function(func):
- assert 0
-
- @pytest.mark.xfail
- def test_func():
- pass
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*1 xfail*",
- ])
-
- def test_failing_teardown_issue9(self, testdir):
- testdir.makepyfile("""
- import pytest
- def teardown_function(func):
- assert 0
-
- @pytest.mark.xfail
- def test_func():
- pass
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*1 xfail*",
- ])
-
-
-class TestSkip:
- def test_skip_class(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.mark.skip
- class TestSomething(object):
- def test_foo(self):
- pass
- def test_bar(self):
- pass
-
- def test_baz():
- pass
- """)
- rec = testdir.inline_run()
- rec.assertoutcome(skipped=2, passed=1)
-
- def test_skips_on_false_string(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.mark.skip('False')
- def test_foo():
- pass
- """)
- rec = testdir.inline_run()
- rec.assertoutcome(skipped=1)
-
- def test_arg_as_reason(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.mark.skip('testing stuff')
- def test_bar():
- pass
- """)
- result = testdir.runpytest('-rs')
- result.stdout.fnmatch_lines([
- "*testing stuff*",
- "*1 skipped*",
- ])
-
- def test_skip_no_reason(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.mark.skip
- def test_foo():
- pass
- """)
- result = testdir.runpytest('-rs')
- result.stdout.fnmatch_lines([
- "*unconditional skip*",
- "*1 skipped*",
- ])
-
- def test_skip_with_reason(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.mark.skip(reason="for lolz")
- def test_bar():
- pass
- """)
- result = testdir.runpytest('-rs')
- result.stdout.fnmatch_lines([
- "*for lolz*",
- "*1 skipped*",
- ])
-
- def test_only_skips_marked_test(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.mark.skip
- def test_foo():
- pass
- @pytest.mark.skip(reason="nothing in particular")
- def test_bar():
- pass
- def test_baz():
- assert True
- """)
- result = testdir.runpytest('-rs')
- result.stdout.fnmatch_lines([
- "*nothing in particular*",
- "*1 passed*2 skipped*",
- ])
-
-class TestSkipif:
- def test_skipif_conditional(self, testdir):
- item = testdir.getitem("""
- import pytest
- @pytest.mark.skipif("hasattr(os, 'sep')")
- def test_func():
- pass
- """) # noqa
- x = pytest.raises(pytest.skip.Exception, lambda:
- pytest_runtest_setup(item))
- assert x.value.msg == "condition: hasattr(os, 'sep')"
-
- @pytest.mark.parametrize('params', [
- '"hasattr(sys, \'platform\')"',
- 'True, reason="invalid platform"',
- ])
- def test_skipif_reporting(self, testdir, params):
- p = testdir.makepyfile(test_foo="""
- import pytest
- @pytest.mark.skipif(%(params)s)
- def test_that():
- assert 0
- """ % dict(params=params))
- result = testdir.runpytest(p, '-s', '-rs')
- result.stdout.fnmatch_lines([
- "*SKIP*1*test_foo.py*platform*",
- "*1 skipped*"
- ])
- assert result.ret == 0
-
- @pytest.mark.parametrize('marker, msg1, msg2', [
- ('skipif', 'SKIP', 'skipped'),
- ('xfail', 'XPASS', 'xpassed'),
- ])
- def test_skipif_reporting_multiple(self, testdir, marker, msg1, msg2):
- testdir.makepyfile(test_foo="""
- import pytest
- @pytest.mark.{marker}(False, reason='first_condition')
- @pytest.mark.{marker}(True, reason='second_condition')
- def test_foobar():
- assert 1
- """.format(marker=marker))
- result = testdir.runpytest('-s', '-rsxX')
- result.stdout.fnmatch_lines([
- "*{msg1}*test_foo.py*second_condition*".format(msg1=msg1),
- "*1 {msg2}*".format(msg2=msg2),
- ])
- assert result.ret == 0
-
-
-def test_skip_not_report_default(testdir):
- p = testdir.makepyfile(test_one="""
- import pytest
- def test_this():
- pytest.skip("hello")
- """)
- result = testdir.runpytest(p, '-v')
- result.stdout.fnmatch_lines([
- #"*HINT*use*-r*",
- "*1 skipped*",
- ])
-
-
-def test_skipif_class(testdir):
- p = testdir.makepyfile("""
- import pytest
-
- class TestClass:
- pytestmark = pytest.mark.skipif("True")
- def test_that(self):
- assert 0
- def test_though(self):
- assert 0
- """)
- result = testdir.runpytest(p)
- result.stdout.fnmatch_lines([
- "*2 skipped*"
- ])
-
-
-def test_skip_reasons_folding():
- path = 'xyz'
- lineno = 3
- message = "justso"
- longrepr = (path, lineno, message)
-
- class X:
- pass
- ev1 = X()
- ev1.when = "execute"
- ev1.skipped = True
- ev1.longrepr = longrepr
-
- ev2 = X()
- ev2.longrepr = longrepr
- ev2.skipped = True
-
- l = folded_skips([ev1, ev2])
- assert len(l) == 1
- num, fspath, lineno, reason = l[0]
- assert num == 2
- assert fspath == path
- assert lineno == lineno
- assert reason == message
-
-def test_skipped_reasons_functional(testdir):
- testdir.makepyfile(
- test_one="""
- from conftest import doskip
- def setup_function(func):
- doskip()
- def test_func():
- pass
- class TestClass:
- def test_method(self):
- doskip()
- """,
- test_two = """
- from conftest import doskip
- doskip()
- """,
- conftest = """
- import pytest
- def doskip():
- pytest.skip('test')
- """
- )
- result = testdir.runpytest('--report=skipped')
- result.stdout.fnmatch_lines([
- "*SKIP*3*conftest.py:3: test",
- ])
- assert result.ret == 0
-
-def test_reportchars(testdir):
- testdir.makepyfile("""
- import pytest
- def test_1():
- assert 0
- @pytest.mark.xfail
- def test_2():
- assert 0
- @pytest.mark.xfail
- def test_3():
- pass
- def test_4():
- pytest.skip("four")
- """)
- result = testdir.runpytest("-rfxXs")
- result.stdout.fnmatch_lines([
- "FAIL*test_1*",
- "XFAIL*test_2*",
- "XPASS*test_3*",
- "SKIP*four*",
- ])
-
-def test_reportchars_error(testdir):
- testdir.makepyfile(
- conftest="""
- def pytest_runtest_teardown():
- assert 0
- """,
- test_simple="""
- def test_foo():
- pass
- """)
- result = testdir.runpytest('-rE')
- result.stdout.fnmatch_lines([
- 'ERROR*test_foo*',
- ])
-
-def test_reportchars_all(testdir):
- testdir.makepyfile("""
- import pytest
- def test_1():
- assert 0
- @pytest.mark.xfail
- def test_2():
- assert 0
- @pytest.mark.xfail
- def test_3():
- pass
- def test_4():
- pytest.skip("four")
- """)
- result = testdir.runpytest("-ra")
- result.stdout.fnmatch_lines([
- "FAIL*test_1*",
- "SKIP*four*",
- "XFAIL*test_2*",
- "XPASS*test_3*",
- ])
-
-def test_reportchars_all_error(testdir):
- testdir.makepyfile(
- conftest="""
- def pytest_runtest_teardown():
- assert 0
- """,
- test_simple="""
- def test_foo():
- pass
- """)
- result = testdir.runpytest('-ra')
- result.stdout.fnmatch_lines([
- 'ERROR*test_foo*',
- ])
-
-@pytest.mark.xfail("hasattr(sys, 'pypy_version_info')")
-def test_errors_in_xfail_skip_expressions(testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.mark.skipif("asd")
- def test_nameerror():
- pass
- @pytest.mark.xfail("syntax error")
- def test_syntax():
- pass
-
- def test_func():
- pass
- """)
- result = testdir.runpytest()
- markline = " ^"
- if sys.platform.startswith("java"):
- # XXX report this to java
- markline = "*" + markline[8:]
- result.stdout.fnmatch_lines([
- "*ERROR*test_nameerror*",
- "*evaluating*skipif*expression*",
- "*asd*",
- "*ERROR*test_syntax*",
- "*evaluating*xfail*expression*",
- " syntax error",
- markline,
- "SyntaxError: invalid syntax",
- "*1 pass*2 error*",
- ])
-
-def test_xfail_skipif_with_globals(testdir):
- testdir.makepyfile("""
- import pytest
- x = 3
- @pytest.mark.skipif("x == 3")
- def test_skip1():
- pass
- @pytest.mark.xfail("x == 3")
- def test_boolean():
- assert 0
- """)
- result = testdir.runpytest("-rsx")
- result.stdout.fnmatch_lines([
- "*SKIP*x == 3*",
- "*XFAIL*test_boolean*",
- "*x == 3*",
- ])
-
-def test_direct_gives_error(testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.mark.skipif(True)
- def test_skip1():
- pass
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*1 error*",
- ])
-
-
-def test_default_markers(testdir):
- result = testdir.runpytest("--markers")
- result.stdout.fnmatch_lines([
- "*skipif(*condition)*skip*",
- "*xfail(*condition, reason=None, run=True, raises=None)*expected failure*",
- ])
-
-def test_xfail_test_setup_exception(testdir):
- testdir.makeconftest("""
- def pytest_runtest_setup():
- 0 / 0
- """)
- p = testdir.makepyfile("""
- import pytest
- @pytest.mark.xfail
- def test_func():
- assert 0
- """)
- result = testdir.runpytest(p)
- assert result.ret == 0
- assert 'xfailed' in result.stdout.str()
- assert 'xpassed' not in result.stdout.str()
-
-def test_imperativeskip_on_xfail_test(testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.mark.xfail
- def test_that_fails():
- assert 0
-
- @pytest.mark.skipif("True")
- def test_hello():
- pass
- """)
- testdir.makeconftest("""
- import pytest
- def pytest_runtest_setup(item):
- pytest.skip("abc")
- """)
- result = testdir.runpytest("-rsxX")
- result.stdout.fnmatch_lines_random("""
- *SKIP*abc*
- *SKIP*condition: True*
- *2 skipped*
- """)
-
-class TestBooleanCondition:
- def test_skipif(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.mark.skipif(True, reason="True123")
- def test_func1():
- pass
- @pytest.mark.skipif(False, reason="True123")
- def test_func2():
- pass
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines("""
- *1 passed*1 skipped*
- """)
-
- def test_skipif_noreason(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.mark.skipif(True)
- def test_func():
- pass
- """)
- result = testdir.runpytest("-rs")
- result.stdout.fnmatch_lines("""
- *1 error*
- """)
-
- def test_xfail(self, testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.mark.xfail(True, reason="True123")
- def test_func():
- assert 0
- """)
- result = testdir.runpytest("-rxs")
- result.stdout.fnmatch_lines("""
- *XFAIL*
- *True123*
- *1 xfail*
- """)
-
-
-def test_xfail_item(testdir):
- # Ensure pytest.xfail works with non-Python Item
- testdir.makeconftest("""
- import pytest
-
- class MyItem(pytest.Item):
- nodeid = 'foo'
- def runtest(self):
- pytest.xfail("Expected Failure")
-
- def pytest_collect_file(path, parent):
- return MyItem("foo", parent)
- """)
- result = testdir.inline_run()
- passed, skipped, failed = result.listoutcomes()
- assert not failed
- xfailed = [r for r in skipped if hasattr(r, 'wasxfail')]
- assert xfailed
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_terminal.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_terminal.py
deleted file mode 100644
index b43d6b37923..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_terminal.py
+++ /dev/null
@@ -1,880 +0,0 @@
-"""
-terminal reporting of the full testing process.
-"""
-import collections
-import sys
-
-import _pytest._pluggy as pluggy
-import _pytest._code
-import py
-import pytest
-from _pytest import runner
-from _pytest.main import EXIT_NOTESTSCOLLECTED
-from _pytest.terminal import TerminalReporter, repr_pythonversion, getreportopt
-from _pytest.terminal import build_summary_stats_line, _plugin_nameversions
-
-
-def basic_run_report(item):
- runner.call_and_report(item, "setup", log=False)
- return runner.call_and_report(item, "call", log=False)
-
-DistInfo = collections.namedtuple('DistInfo', ['project_name', 'version'])
-
-
-class Option:
- def __init__(self, verbose=False, fulltrace=False):
- self.verbose = verbose
- self.fulltrace = fulltrace
-
- @property
- def args(self):
- l = []
- if self.verbose:
- l.append('-v')
- if self.fulltrace:
- l.append('--fulltrace')
- return l
-
-def pytest_generate_tests(metafunc):
- if "option" in metafunc.fixturenames:
- metafunc.addcall(id="default",
- funcargs={'option': Option(verbose=False)})
- metafunc.addcall(id="verbose",
- funcargs={'option': Option(verbose=True)})
- metafunc.addcall(id="quiet",
- funcargs={'option': Option(verbose= -1)})
- metafunc.addcall(id="fulltrace",
- funcargs={'option': Option(fulltrace=True)})
-
-
-@pytest.mark.parametrize('input,expected', [
- ([DistInfo(project_name='test', version=1)], ['test-1']),
- ([DistInfo(project_name='pytest-test', version=1)], ['test-1']),
- ([
- DistInfo(project_name='test', version=1),
- DistInfo(project_name='test', version=1)
- ], ['test-1']),
-], ids=['normal', 'prefix-strip', 'deduplicate'])
-def test_plugin_nameversion(input, expected):
- pluginlist = [(None, x) for x in input]
- result = _plugin_nameversions(pluginlist)
- assert result == expected
-
-
-class TestTerminal:
- def test_pass_skip_fail(self, testdir, option):
- testdir.makepyfile("""
- import pytest
- def test_ok():
- pass
- def test_skip():
- pytest.skip("xx")
- def test_func():
- assert 0
- """)
- result = testdir.runpytest(*option.args)
- if option.verbose:
- result.stdout.fnmatch_lines([
- "*test_pass_skip_fail.py::test_ok PASS*",
- "*test_pass_skip_fail.py::test_skip SKIP*",
- "*test_pass_skip_fail.py::test_func FAIL*",
- ])
- else:
- result.stdout.fnmatch_lines([
- "*test_pass_skip_fail.py .sF"
- ])
- result.stdout.fnmatch_lines([
- " def test_func():",
- "> assert 0",
- "E assert 0",
- ])
-
- def test_internalerror(self, testdir, linecomp):
- modcol = testdir.getmodulecol("def test_one(): pass")
- rep = TerminalReporter(modcol.config, file=linecomp.stringio)
- excinfo = pytest.raises(ValueError, "raise ValueError('hello')")
- rep.pytest_internalerror(excinfo.getrepr())
- linecomp.assert_contains_lines([
- "INTERNALERROR> *ValueError*hello*"
- ])
-
- def test_writeline(self, testdir, linecomp):
- modcol = testdir.getmodulecol("def test_one(): pass")
- rep = TerminalReporter(modcol.config, file=linecomp.stringio)
- rep.write_fspath_result(modcol.nodeid, ".")
- rep.write_line("hello world")
- lines = linecomp.stringio.getvalue().split('\n')
- assert not lines[0]
- assert lines[1].endswith(modcol.name + " .")
- assert lines[2] == "hello world"
-
- def test_show_runtest_logstart(self, testdir, linecomp):
- item = testdir.getitem("def test_func(): pass")
- tr = TerminalReporter(item.config, file=linecomp.stringio)
- item.config.pluginmanager.register(tr)
- location = item.reportinfo()
- tr.config.hook.pytest_runtest_logstart(nodeid=item.nodeid,
- location=location, fspath=str(item.fspath))
- linecomp.assert_contains_lines([
- "*test_show_runtest_logstart.py*"
- ])
-
- def test_runtest_location_shown_before_test_starts(self, testdir):
- testdir.makepyfile("""
- def test_1():
- import time
- time.sleep(20)
- """)
- child = testdir.spawn_pytest("")
- child.expect(".*test_runtest_location.*py")
- child.sendeof()
- child.kill(15)
-
- def test_itemreport_subclasses_show_subclassed_file(self, testdir):
- testdir.makepyfile(test_p1="""
- class BaseTests:
- def test_p1(self):
- pass
- class TestClass(BaseTests):
- pass
- """)
- p2 = testdir.makepyfile(test_p2="""
- from test_p1 import BaseTests
- class TestMore(BaseTests):
- pass
- """)
- result = testdir.runpytest(p2)
- result.stdout.fnmatch_lines([
- "*test_p2.py .",
- "*1 passed*",
- ])
- result = testdir.runpytest("-v", p2)
- result.stdout.fnmatch_lines([
- "*test_p2.py::TestMore::test_p1* <- *test_p1.py*PASSED",
- ])
-
- def test_itemreport_directclasses_not_shown_as_subclasses(self, testdir):
- a = testdir.mkpydir("a123")
- a.join("test_hello123.py").write(_pytest._code.Source("""
- class TestClass:
- def test_method(self):
- pass
- """))
- result = testdir.runpytest("-v")
- assert result.ret == 0
- result.stdout.fnmatch_lines([
- "*a123/test_hello123.py*PASS*",
- ])
- assert " <- " not in result.stdout.str()
-
- def test_keyboard_interrupt(self, testdir, option):
- testdir.makepyfile("""
- def test_foobar():
- assert 0
- def test_spamegg():
- import py; pytest.skip('skip me please!')
- def test_interrupt_me():
- raise KeyboardInterrupt # simulating the user
- """)
-
- result = testdir.runpytest(*option.args, no_reraise_ctrlc=True)
- result.stdout.fnmatch_lines([
- " def test_foobar():",
- "> assert 0",
- "E assert 0",
- "*_keyboard_interrupt.py:6: KeyboardInterrupt*",
- ])
- if option.fulltrace:
- result.stdout.fnmatch_lines([
- "*raise KeyboardInterrupt # simulating the user*",
- ])
- else:
- result.stdout.fnmatch_lines([
- "to show a full traceback on KeyboardInterrupt use --fulltrace"
- ])
- result.stdout.fnmatch_lines(['*KeyboardInterrupt*'])
-
- def test_keyboard_in_sessionstart(self, testdir):
- testdir.makeconftest("""
- def pytest_sessionstart():
- raise KeyboardInterrupt
- """)
- testdir.makepyfile("""
- def test_foobar():
- pass
- """)
-
- result = testdir.runpytest(no_reraise_ctrlc=True)
- assert result.ret == 2
- result.stdout.fnmatch_lines(['*KeyboardInterrupt*'])
-
-
-class TestCollectonly:
- def test_collectonly_basic(self, testdir):
- testdir.makepyfile("""
- def test_func():
- pass
- """)
- result = testdir.runpytest("--collect-only",)
- result.stdout.fnmatch_lines([
- "<Module 'test_collectonly_basic.py'>",
- " <Function 'test_func'>",
- ])
-
- def test_collectonly_skipped_module(self, testdir):
- testdir.makepyfile("""
- import pytest
- pytest.skip("hello")
- """)
- result = testdir.runpytest("--collect-only", "-rs")
- result.stdout.fnmatch_lines([
- "SKIP*hello*",
- "*1 skip*",
- ])
-
- def test_collectonly_failed_module(self, testdir):
- testdir.makepyfile("""raise ValueError(0)""")
- result = testdir.runpytest("--collect-only")
- result.stdout.fnmatch_lines([
- "*raise ValueError*",
- "*1 error*",
- ])
-
- def test_collectonly_fatal(self, testdir):
- testdir.makeconftest("""
- def pytest_collectstart(collector):
- assert 0, "urgs"
- """)
- result = testdir.runpytest("--collect-only")
- result.stdout.fnmatch_lines([
- "*INTERNAL*args*"
- ])
- assert result.ret == 3
-
- def test_collectonly_simple(self, testdir):
- p = testdir.makepyfile("""
- def test_func1():
- pass
- class TestClass:
- def test_method(self):
- pass
- """)
- result = testdir.runpytest("--collect-only", p)
- #assert stderr.startswith("inserting into sys.path")
- assert result.ret == 0
- result.stdout.fnmatch_lines([
- "*<Module '*.py'>",
- "* <Function 'test_func1'*>",
- "* <Class 'TestClass'>",
- #"* <Instance '()'>",
- "* <Function 'test_method'*>",
- ])
-
- def test_collectonly_error(self, testdir):
- p = testdir.makepyfile("import Errlkjqweqwe")
- result = testdir.runpytest("--collect-only", p)
- assert result.ret == 1
- result.stdout.fnmatch_lines(_pytest._code.Source("""
- *ERROR*
- *import Errlk*
- *ImportError*
- *1 error*
- """).strip())
-
- def test_collectonly_missing_path(self, testdir):
- """this checks issue 115,
- failure in parseargs will cause session
- not to have the items attribute
- """
- result = testdir.runpytest("--collect-only", "uhm_missing_path")
- assert result.ret == 4
- result.stderr.fnmatch_lines([
- '*ERROR: file not found*',
- ])
-
- def test_collectonly_quiet(self, testdir):
- testdir.makepyfile("def test_foo(): pass")
- result = testdir.runpytest("--collect-only", "-q")
- result.stdout.fnmatch_lines([
- '*test_foo*',
- ])
-
- def test_collectonly_more_quiet(self, testdir):
- testdir.makepyfile(test_fun="def test_foo(): pass")
- result = testdir.runpytest("--collect-only", "-qq")
- result.stdout.fnmatch_lines([
- '*test_fun.py: 1*',
- ])
-
-
-def test_repr_python_version(monkeypatch):
- try:
- monkeypatch.setattr(sys, 'version_info', (2, 5, 1, 'final', 0))
- assert repr_pythonversion() == "2.5.1-final-0"
- py.std.sys.version_info = x = (2, 3)
- assert repr_pythonversion() == str(x)
- finally:
- monkeypatch.undo() # do this early as pytest can get confused
-
-class TestFixtureReporting:
- def test_setup_fixture_error(self, testdir):
- testdir.makepyfile("""
- def setup_function(function):
- print ("setup func")
- assert 0
- def test_nada():
- pass
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*ERROR at setup of test_nada*",
- "*setup_function(function):*",
- "*setup func*",
- "*assert 0*",
- "*1 error*",
- ])
- assert result.ret != 0
-
- def test_teardown_fixture_error(self, testdir):
- testdir.makepyfile("""
- def test_nada():
- pass
- def teardown_function(function):
- print ("teardown func")
- assert 0
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*ERROR at teardown*",
- "*teardown_function(function):*",
- "*assert 0*",
- "*Captured stdout*",
- "*teardown func*",
- "*1 passed*1 error*",
- ])
-
- def test_teardown_fixture_error_and_test_failure(self, testdir):
- testdir.makepyfile("""
- def test_fail():
- assert 0, "failingfunc"
-
- def teardown_function(function):
- print ("teardown func")
- assert False
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*ERROR at teardown of test_fail*",
- "*teardown_function(function):*",
- "*assert False*",
- "*Captured stdout*",
- "*teardown func*",
-
- "*test_fail*",
- "*def test_fail():",
- "*failingfunc*",
- "*1 failed*1 error*",
- ])
-
-class TestTerminalFunctional:
- def test_deselected(self, testdir):
- testpath = testdir.makepyfile("""
- def test_one():
- pass
- def test_two():
- pass
- def test_three():
- pass
- """
- )
- result = testdir.runpytest("-k", "test_two:", testpath)
- result.stdout.fnmatch_lines([
- "*test_deselected.py ..",
- "=* 1 test*deselected by*test_two:*=",
- ])
- assert result.ret == 0
-
- def test_no_skip_summary_if_failure(self, testdir):
- testdir.makepyfile("""
- import pytest
- def test_ok():
- pass
- def test_fail():
- assert 0
- def test_skip():
- pytest.skip("dontshow")
- """)
- result = testdir.runpytest()
- assert result.stdout.str().find("skip test summary") == -1
- assert result.ret == 1
-
- def test_passes(self, testdir):
- p1 = testdir.makepyfile("""
- def test_passes():
- pass
- class TestClass:
- def test_method(self):
- pass
- """)
- old = p1.dirpath().chdir()
- try:
- result = testdir.runpytest()
- finally:
- old.chdir()
- result.stdout.fnmatch_lines([
- "test_passes.py ..",
- "* 2 pass*",
- ])
- assert result.ret == 0
-
- def test_header_trailer_info(self, testdir):
- testdir.makepyfile("""
- def test_passes():
- pass
- """)
- result = testdir.runpytest()
- verinfo = ".".join(map(str, py.std.sys.version_info[:3]))
- result.stdout.fnmatch_lines([
- "*===== test session starts ====*",
- "platform %s -- Python %s*pytest-%s*py-%s*pluggy-%s" % (
- py.std.sys.platform, verinfo,
- pytest.__version__, py.__version__, pluggy.__version__),
- "*test_header_trailer_info.py .",
- "=* 1 passed*in *.[0-9][0-9] seconds *=",
- ])
- if pytest.config.pluginmanager.list_plugin_distinfo():
- result.stdout.fnmatch_lines([
- "plugins: *",
- ])
-
- def test_showlocals(self, testdir):
- p1 = testdir.makepyfile("""
- def test_showlocals():
- x = 3
- y = "x" * 5000
- assert 0
- """)
- result = testdir.runpytest(p1, '-l')
- result.stdout.fnmatch_lines([
- #"_ _ * Locals *",
- "x* = 3",
- "y* = 'xxxxxx*"
- ])
-
- def test_verbose_reporting(self, testdir, pytestconfig):
- p1 = testdir.makepyfile("""
- import pytest
- def test_fail():
- raise ValueError()
- def test_pass():
- pass
- class TestClass:
- def test_skip(self):
- pytest.skip("hello")
- def test_gen():
- def check(x):
- assert x == 1
- yield check, 0
- """)
- result = testdir.runpytest(p1, '-v')
- result.stdout.fnmatch_lines([
- "*test_verbose_reporting.py::test_fail *FAIL*",
- "*test_verbose_reporting.py::test_pass *PASS*",
- "*test_verbose_reporting.py::TestClass::test_skip *SKIP*",
- "*test_verbose_reporting.py::test_gen*0* *FAIL*",
- ])
- assert result.ret == 1
-
- if not pytestconfig.pluginmanager.get_plugin("xdist"):
- pytest.skip("xdist plugin not installed")
-
- result = testdir.runpytest(p1, '-v', '-n 1')
- result.stdout.fnmatch_lines([
- "*FAIL*test_verbose_reporting.py::test_fail*",
- ])
- assert result.ret == 1
-
- def test_quiet_reporting(self, testdir):
- p1 = testdir.makepyfile("def test_pass(): pass")
- result = testdir.runpytest(p1, '-q')
- s = result.stdout.str()
- assert 'test session starts' not in s
- assert p1.basename not in s
- assert "===" not in s
- assert "passed" in s
-
- def test_more_quiet_reporting(self, testdir):
- p1 = testdir.makepyfile("def test_pass(): pass")
- result = testdir.runpytest(p1, '-qq')
- s = result.stdout.str()
- assert 'test session starts' not in s
- assert p1.basename not in s
- assert "===" not in s
- assert "passed" not in s
-
-
-def test_fail_extra_reporting(testdir):
- testdir.makepyfile("def test_this(): assert 0")
- result = testdir.runpytest()
- assert 'short test summary' not in result.stdout.str()
- result = testdir.runpytest('-rf')
- result.stdout.fnmatch_lines([
- "*test summary*",
- "FAIL*test_fail_extra_reporting*",
- ])
-
-def test_fail_reporting_on_pass(testdir):
- testdir.makepyfile("def test_this(): assert 1")
- result = testdir.runpytest('-rf')
- assert 'short test summary' not in result.stdout.str()
-
-def test_pass_extra_reporting(testdir):
- testdir.makepyfile("def test_this(): assert 1")
- result = testdir.runpytest()
- assert 'short test summary' not in result.stdout.str()
- result = testdir.runpytest('-rp')
- result.stdout.fnmatch_lines([
- "*test summary*",
- "PASS*test_pass_extra_reporting*",
- ])
-
-def test_pass_reporting_on_fail(testdir):
- testdir.makepyfile("def test_this(): assert 0")
- result = testdir.runpytest('-rp')
- assert 'short test summary' not in result.stdout.str()
-
-def test_pass_output_reporting(testdir):
- testdir.makepyfile("""
- def test_pass_output():
- print("Four score and seven years ago...")
- """)
- result = testdir.runpytest()
- assert 'Four score and seven years ago...' not in result.stdout.str()
- result = testdir.runpytest('-rP')
- result.stdout.fnmatch_lines([
- "Four score and seven years ago...",
- ])
-
-def test_color_yes(testdir):
- testdir.makepyfile("def test_this(): assert 1")
- result = testdir.runpytest('--color=yes')
- assert 'test session starts' in result.stdout.str()
- assert '\x1b[1m' in result.stdout.str()
-
-
-def test_color_no(testdir):
- testdir.makepyfile("def test_this(): assert 1")
- result = testdir.runpytest('--color=no')
- assert 'test session starts' in result.stdout.str()
- assert '\x1b[1m' not in result.stdout.str()
-
-
-@pytest.mark.parametrize('verbose', [True, False])
-def test_color_yes_collection_on_non_atty(testdir, verbose):
- """skip collect progress report when working on non-terminals.
- #1397
- """
- testdir.makepyfile("""
- import pytest
- @pytest.mark.parametrize('i', range(10))
- def test_this(i):
- assert 1
- """)
- args = ['--color=yes']
- if verbose:
- args.append('-vv')
- result = testdir.runpytest(*args)
- assert 'test session starts' in result.stdout.str()
- assert '\x1b[1m' in result.stdout.str()
- assert 'collecting 10 items' not in result.stdout.str()
- if verbose:
- assert 'collecting ...' in result.stdout.str()
- assert 'collected 10 items' in result.stdout.str()
-
-
-def test_getreportopt():
- class config:
- class option:
- reportchars = ""
- config.option.report = "xfailed"
- assert getreportopt(config) == "x"
-
- config.option.report = "xfailed,skipped"
- assert getreportopt(config) == "xs"
-
- config.option.report = "skipped,xfailed"
- assert getreportopt(config) == "sx"
-
- config.option.report = "skipped"
- config.option.reportchars = "sf"
- assert getreportopt(config) == "sf"
-
- config.option.reportchars = "sfx"
- assert getreportopt(config) == "sfx"
-
-def test_terminalreporter_reportopt_addopts(testdir):
- testdir.makeini("[pytest]\naddopts=-rs")
- testdir.makepyfile("""
- def pytest_funcarg__tr(request):
- tr = request.config.pluginmanager.getplugin("terminalreporter")
- return tr
- def test_opt(tr):
- assert tr.hasopt('skipped')
- assert not tr.hasopt('qwe')
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*1 passed*"
- ])
-
-def test_tbstyle_short(testdir):
- p = testdir.makepyfile("""
- def pytest_funcarg__arg(request):
- return 42
- def test_opt(arg):
- x = 0
- assert x
- """)
- result = testdir.runpytest("--tb=short")
- s = result.stdout.str()
- assert 'arg = 42' not in s
- assert 'x = 0' not in s
- result.stdout.fnmatch_lines([
- "*%s:5*" % p.basename,
- " assert x",
- "E assert*",
- ])
- result = testdir.runpytest()
- s = result.stdout.str()
- assert 'x = 0' in s
- assert 'assert x' in s
-
-def test_traceconfig(testdir, monkeypatch):
- result = testdir.runpytest("--traceconfig")
- result.stdout.fnmatch_lines([
- "*active plugins*"
- ])
- assert result.ret == EXIT_NOTESTSCOLLECTED
-
-
-class TestGenericReporting:
- """ this test class can be subclassed with a different option
- provider to run e.g. distributed tests.
- """
- def test_collect_fail(self, testdir, option):
- testdir.makepyfile("import xyz\n")
- result = testdir.runpytest(*option.args)
- result.stdout.fnmatch_lines([
- "? import xyz",
- "E ImportError: No module named *xyz*",
- "*1 error*",
- ])
-
- def test_maxfailures(self, testdir, option):
- testdir.makepyfile("""
- def test_1():
- assert 0
- def test_2():
- assert 0
- def test_3():
- assert 0
- """)
- result = testdir.runpytest("--maxfail=2", *option.args)
- result.stdout.fnmatch_lines([
- "*def test_1():*",
- "*def test_2():*",
- "*!! Interrupted: stopping after 2 failures*!!*",
- "*2 failed*",
- ])
-
-
- def test_tb_option(self, testdir, option):
- testdir.makepyfile("""
- import pytest
- def g():
- raise IndexError
- def test_func():
- print (6*7)
- g() # --calling--
- """)
- for tbopt in ["long", "short", "no"]:
- print('testing --tb=%s...' % tbopt)
- result = testdir.runpytest('--tb=%s' % tbopt)
- s = result.stdout.str()
- if tbopt == "long":
- assert 'print (6*7)' in s
- else:
- assert 'print (6*7)' not in s
- if tbopt != "no":
- assert '--calling--' in s
- assert 'IndexError' in s
- else:
- assert 'FAILURES' not in s
- assert '--calling--' not in s
- assert 'IndexError' not in s
-
- def test_tb_crashline(self, testdir, option):
- p = testdir.makepyfile("""
- import pytest
- def g():
- raise IndexError
- def test_func1():
- print (6*7)
- g() # --calling--
- def test_func2():
- assert 0, "hello"
- """)
- result = testdir.runpytest("--tb=line")
- bn = p.basename
- result.stdout.fnmatch_lines([
- "*%s:3: IndexError*" % bn,
- "*%s:8: AssertionError: hello*" % bn,
- ])
- s = result.stdout.str()
- assert "def test_func2" not in s
-
- def test_pytest_report_header(self, testdir, option):
- testdir.makeconftest("""
- def pytest_sessionstart(session):
- session.config._somevalue = 42
- def pytest_report_header(config):
- return "hello: %s" % config._somevalue
- """)
- testdir.mkdir("a").join("conftest.py").write("""
-def pytest_report_header(config, startdir):
- return ["line1", str(startdir)]
-""")
- result = testdir.runpytest("a")
- result.stdout.fnmatch_lines([
- "*hello: 42*",
- "line1",
- str(testdir.tmpdir),
- ])
-
-@pytest.mark.xfail("not hasattr(os, 'dup')")
-def test_fdopen_kept_alive_issue124(testdir):
- testdir.makepyfile("""
- import os, sys
- k = []
- def test_open_file_and_keep_alive(capfd):
- stdout = os.fdopen(1, 'w', 1)
- k.append(stdout)
-
- def test_close_kept_alive_file():
- stdout = k.pop()
- stdout.close()
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*2 passed*"
- ])
-
-def test_tbstyle_native_setup_error(testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.fixture
- def setup_error_fixture():
- raise Exception("error in exception")
-
- def test_error_fixture(setup_error_fixture):
- pass
- """)
- result = testdir.runpytest("--tb=native")
- result.stdout.fnmatch_lines([
- '*File *test_tbstyle_native_setup_error.py", line *, in setup_error_fixture*'
- ])
-
-def test_terminal_summary(testdir):
- testdir.makeconftest("""
- def pytest_terminal_summary(terminalreporter):
- w = terminalreporter
- w.section("hello")
- w.line("world")
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines("""
- *==== hello ====*
- world
- """)
-
-
-def test_terminal_summary_warnings_are_displayed(testdir):
- """Test that warnings emitted during pytest_terminal_summary are displayed.
- (#1305).
- """
- testdir.makeconftest("""
- def pytest_terminal_summary(terminalreporter):
- config = terminalreporter.config
- config.warn('C1', 'internal warning')
- """)
- result = testdir.runpytest('-rw')
- result.stdout.fnmatch_lines([
- '*C1*internal warning',
- '*== 1 pytest-warnings in *',
- ])
-
-
-@pytest.mark.parametrize("exp_color, exp_line, stats_arg", [
- # The method under test only cares about the length of each
- # dict value, not the actual contents, so tuples of anything
- # suffice
-
- # Important statuses -- the highest priority of these always wins
- ("red", "1 failed", {"failed": (1,)}),
- ("red", "1 failed, 1 passed", {"failed": (1,), "passed": (1,)}),
-
- ("red", "1 error", {"error": (1,)}),
- ("red", "1 passed, 1 error", {"error": (1,), "passed": (1,)}),
-
- # (a status that's not known to the code)
- ("yellow", "1 weird", {"weird": (1,)}),
- ("yellow", "1 passed, 1 weird", {"weird": (1,), "passed": (1,)}),
-
- ("yellow", "1 pytest-warnings", {"warnings": (1,)}),
- ("yellow", "1 passed, 1 pytest-warnings", {"warnings": (1,),
- "passed": (1,)}),
-
- ("green", "5 passed", {"passed": (1,2,3,4,5)}),
-
-
- # "Boring" statuses. These have no effect on the color of the summary
- # line. Thus, if *every* test has a boring status, the summary line stays
- # at its default color, i.e. yellow, to warn the user that the test run
- # produced no useful information
- ("yellow", "1 skipped", {"skipped": (1,)}),
- ("green", "1 passed, 1 skipped", {"skipped": (1,), "passed": (1,)}),
-
- ("yellow", "1 deselected", {"deselected": (1,)}),
- ("green", "1 passed, 1 deselected", {"deselected": (1,), "passed": (1,)}),
-
- ("yellow", "1 xfailed", {"xfailed": (1,)}),
- ("green", "1 passed, 1 xfailed", {"xfailed": (1,), "passed": (1,)}),
-
- ("yellow", "1 xpassed", {"xpassed": (1,)}),
- ("green", "1 passed, 1 xpassed", {"xpassed": (1,), "passed": (1,)}),
-
- # Likewise if no tests were found at all
- ("yellow", "no tests ran", {}),
-
- # Test the empty-key special case
- ("yellow", "no tests ran", {"": (1,)}),
- ("green", "1 passed", {"": (1,), "passed": (1,)}),
-
-
- # A couple more complex combinations
- ("red", "1 failed, 2 passed, 3 xfailed",
- {"passed": (1,2), "failed": (1,), "xfailed": (1,2,3)}),
-
- ("green", "1 passed, 2 skipped, 3 deselected, 2 xfailed",
- {"passed": (1,),
- "skipped": (1,2),
- "deselected": (1,2,3),
- "xfailed": (1,2)}),
-])
-def test_summary_stats(exp_line, exp_color, stats_arg):
- print("Based on stats: %s" % stats_arg)
- print("Expect summary: \"%s\"; with color \"%s\"" % (exp_line, exp_color))
- (line, color) = build_summary_stats_line(stats_arg)
- print("Actually got: \"%s\"; with color \"%s\"" % (line, color))
- assert line == exp_line
- assert color == exp_color
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_tmpdir.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_tmpdir.py
deleted file mode 100644
index d514e722e1f..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_tmpdir.py
+++ /dev/null
@@ -1,183 +0,0 @@
-import sys
-import py
-import pytest
-
-from _pytest.tmpdir import tmpdir
-
-def test_funcarg(testdir):
- testdir.makepyfile("""
- def pytest_generate_tests(metafunc):
- metafunc.addcall(id='a')
- metafunc.addcall(id='b')
- def test_func(tmpdir): pass
- """)
- from _pytest.tmpdir import TempdirFactory
- reprec = testdir.inline_run()
- calls = reprec.getcalls("pytest_runtest_setup")
- item = calls[0].item
- config = item.config
- tmpdirhandler = TempdirFactory(config)
- item._initrequest()
- p = tmpdir(item._request, tmpdirhandler)
- assert p.check()
- bn = p.basename.strip("0123456789")
- assert bn.endswith("test_func_a_")
- item.name = "qwe/\\abc"
- p = tmpdir(item._request, tmpdirhandler)
- assert p.check()
- bn = p.basename.strip("0123456789")
- assert bn == "qwe__abc"
-
-def test_ensuretemp(recwarn):
- #pytest.deprecated_call(pytest.ensuretemp, 'hello')
- d1 = pytest.ensuretemp('hello')
- d2 = pytest.ensuretemp('hello')
- assert d1 == d2
- assert d1.check(dir=1)
-
-class TestTempdirHandler:
- def test_mktemp(self, testdir):
- from _pytest.tmpdir import TempdirFactory
- config = testdir.parseconfig()
- config.option.basetemp = testdir.mkdir("hello")
- t = TempdirFactory(config)
- tmp = t.mktemp("world")
- assert tmp.relto(t.getbasetemp()) == "world0"
- tmp = t.mktemp("this")
- assert tmp.relto(t.getbasetemp()).startswith("this")
- tmp2 = t.mktemp("this")
- assert tmp2.relto(t.getbasetemp()).startswith("this")
- assert tmp2 != tmp
-
-class TestConfigTmpdir:
- def test_getbasetemp_custom_removes_old(self, testdir):
- mytemp = testdir.tmpdir.join("xyz")
- p = testdir.makepyfile("""
- def test_1(tmpdir):
- pass
- """)
- testdir.runpytest(p, '--basetemp=%s' % mytemp)
- mytemp.check()
- mytemp.ensure("hello")
-
- testdir.runpytest(p, '--basetemp=%s' % mytemp)
- mytemp.check()
- assert not mytemp.join("hello").check()
-
-
-def test_basetemp(testdir):
- mytemp = testdir.tmpdir.mkdir("mytemp")
- p = testdir.makepyfile("""
- import pytest
- def test_1():
- pytest.ensuretemp("hello")
- """)
- result = testdir.runpytest(p, '--basetemp=%s' % mytemp)
- assert result.ret == 0
- assert mytemp.join('hello').check()
-
-@pytest.mark.skipif(not hasattr(py.path.local, 'mksymlinkto'),
- reason="symlink not available on this platform")
-def test_tmpdir_always_is_realpath(testdir):
- # the reason why tmpdir should be a realpath is that
- # when you cd to it and do "os.getcwd()" you will anyway
- # get the realpath. Using the symlinked path can thus
- # easily result in path-inequality
- # XXX if that proves to be a problem, consider using
- # os.environ["PWD"]
- realtemp = testdir.tmpdir.mkdir("myrealtemp")
- linktemp = testdir.tmpdir.join("symlinktemp")
- linktemp.mksymlinkto(realtemp)
- p = testdir.makepyfile("""
- def test_1(tmpdir):
- import os
- assert os.path.realpath(str(tmpdir)) == str(tmpdir)
- """)
- result = testdir.runpytest("-s", p, '--basetemp=%s/bt' % linktemp)
- assert not result.ret
-
-
-def test_tmpdir_too_long_on_parametrization(testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.mark.parametrize("arg", ["1"*1000])
- def test_some(arg, tmpdir):
- tmpdir.ensure("hello")
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
-
-def test_tmpdir_factory(testdir):
- testdir.makepyfile("""
- import pytest
- @pytest.fixture(scope='session')
- def session_dir(tmpdir_factory):
- return tmpdir_factory.mktemp('data', numbered=False)
- def test_some(session_dir):
- session_dir.isdir()
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
-
-def test_tmpdir_fallback_tox_env(testdir, monkeypatch):
- """Test that tmpdir works even if environment variables required by getpass
- module are missing (#1010).
- """
- monkeypatch.delenv('USER', raising=False)
- monkeypatch.delenv('USERNAME', raising=False)
- testdir.makepyfile("""
- import pytest
- def test_some(tmpdir):
- assert tmpdir.isdir()
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
-
-@pytest.fixture
-def break_getuser(monkeypatch):
- monkeypatch.setattr('os.getuid', lambda: -1)
- # taken from python 2.7/3.4
- for envvar in ('LOGNAME', 'USER', 'LNAME', 'USERNAME'):
- monkeypatch.delenv(envvar, raising=False)
-
-
-@pytest.mark.usefixtures("break_getuser")
-@pytest.mark.skipif(sys.platform.startswith('win'), reason='no os.getuid on windows')
-def test_tmpdir_fallback_uid_not_found(testdir):
- """Test that tmpdir works even if the current process's user id does not
- correspond to a valid user.
- """
-
- testdir.makepyfile("""
- import pytest
- def test_some(tmpdir):
- assert tmpdir.isdir()
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
-
-@pytest.mark.usefixtures("break_getuser")
-@pytest.mark.skipif(sys.platform.startswith('win'), reason='no os.getuid on windows')
-def test_get_user_uid_not_found():
- """Test that get_user() function works even if the current process's
- user id does not correspond to a valid user (e.g. running pytest in a
- Docker container with 'docker run -u'.
- """
- from _pytest.tmpdir import get_user
- assert get_user() is None
-
-
-@pytest.mark.skipif(not sys.platform.startswith('win'), reason='win only')
-def test_get_user(monkeypatch):
- """Test that get_user() function works even if environment variables
- required by getpass module are missing from the environment on Windows
- (#1010).
- """
- from _pytest.tmpdir import get_user
- monkeypatch.delenv('USER', raising=False)
- monkeypatch.delenv('USERNAME', raising=False)
- assert get_user() is None
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/test_unittest.py b/tests/wpt/web-platform-tests/tools/pytest/testing/test_unittest.py
deleted file mode 100644
index 144aad79bf4..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/test_unittest.py
+++ /dev/null
@@ -1,737 +0,0 @@
-from _pytest.main import EXIT_NOTESTSCOLLECTED
-import pytest
-
-def test_simple_unittest(testdir):
- testpath = testdir.makepyfile("""
- import unittest
- class MyTestCase(unittest.TestCase):
- def testpassing(self):
- self.assertEquals('foo', 'foo')
- def test_failing(self):
- self.assertEquals('foo', 'bar')
- """)
- reprec = testdir.inline_run(testpath)
- assert reprec.matchreport("testpassing").passed
- assert reprec.matchreport("test_failing").failed
-
-def test_runTest_method(testdir):
- testdir.makepyfile("""
- import unittest
- class MyTestCaseWithRunTest(unittest.TestCase):
- def runTest(self):
- self.assertEquals('foo', 'foo')
- class MyTestCaseWithoutRunTest(unittest.TestCase):
- def runTest(self):
- self.assertEquals('foo', 'foo')
- def test_something(self):
- pass
- """)
- result = testdir.runpytest("-v")
- result.stdout.fnmatch_lines("""
- *MyTestCaseWithRunTest::runTest*
- *MyTestCaseWithoutRunTest::test_something*
- *2 passed*
- """)
-
-def test_isclasscheck_issue53(testdir):
- testpath = testdir.makepyfile("""
- import unittest
- class _E(object):
- def __getattr__(self, tag):
- pass
- E = _E()
- """)
- result = testdir.runpytest(testpath)
- assert result.ret == EXIT_NOTESTSCOLLECTED
-
-def test_setup(testdir):
- testpath = testdir.makepyfile("""
- import unittest
- class MyTestCase(unittest.TestCase):
- def setUp(self):
- self.foo = 1
- def setup_method(self, method):
- self.foo2 = 1
- def test_both(self):
- self.assertEquals(1, self.foo)
- assert self.foo2 == 1
- def teardown_method(self, method):
- assert 0, "42"
-
- """)
- reprec = testdir.inline_run("-s", testpath)
- assert reprec.matchreport("test_both", when="call").passed
- rep = reprec.matchreport("test_both", when="teardown")
- assert rep.failed and '42' in str(rep.longrepr)
-
-def test_setUpModule(testdir):
- testpath = testdir.makepyfile("""
- l = []
-
- def setUpModule():
- l.append(1)
-
- def tearDownModule():
- del l[0]
-
- def test_hello():
- assert l == [1]
-
- def test_world():
- assert l == [1]
- """)
- result = testdir.runpytest(testpath)
- result.stdout.fnmatch_lines([
- "*2 passed*",
- ])
-
-def test_setUpModule_failing_no_teardown(testdir):
- testpath = testdir.makepyfile("""
- l = []
-
- def setUpModule():
- 0/0
-
- def tearDownModule():
- l.append(1)
-
- def test_hello():
- pass
- """)
- reprec = testdir.inline_run(testpath)
- reprec.assertoutcome(passed=0, failed=1)
- call = reprec.getcalls("pytest_runtest_setup")[0]
- assert not call.item.module.l
-
-def test_new_instances(testdir):
- testpath = testdir.makepyfile("""
- import unittest
- class MyTestCase(unittest.TestCase):
- def test_func1(self):
- self.x = 2
- def test_func2(self):
- assert not hasattr(self, 'x')
- """)
- reprec = testdir.inline_run(testpath)
- reprec.assertoutcome(passed=2)
-
-def test_teardown(testdir):
- testpath = testdir.makepyfile("""
- import unittest
- class MyTestCase(unittest.TestCase):
- l = []
- def test_one(self):
- pass
- def tearDown(self):
- self.l.append(None)
- class Second(unittest.TestCase):
- def test_check(self):
- self.assertEquals(MyTestCase.l, [None])
- """)
- reprec = testdir.inline_run(testpath)
- passed, skipped, failed = reprec.countoutcomes()
- assert failed == 0, failed
- assert passed == 2
- assert passed + skipped + failed == 2
-
-@pytest.mark.skipif("sys.version_info < (2,7)")
-def test_unittest_skip_issue148(testdir):
- testpath = testdir.makepyfile("""
- import unittest
-
- @unittest.skip("hello")
- class MyTestCase(unittest.TestCase):
- @classmethod
- def setUpClass(self):
- xxx
- def test_one(self):
- pass
- @classmethod
- def tearDownClass(self):
- xxx
- """)
- reprec = testdir.inline_run(testpath)
- reprec.assertoutcome(skipped=1)
-
-def test_method_and_teardown_failing_reporting(testdir):
- testdir.makepyfile("""
- import unittest, pytest
- class TC(unittest.TestCase):
- def tearDown(self):
- assert 0, "down1"
- def test_method(self):
- assert False, "down2"
- """)
- result = testdir.runpytest("-s")
- assert result.ret == 1
- result.stdout.fnmatch_lines([
- "*tearDown*",
- "*assert 0*",
- "*test_method*",
- "*assert False*",
- "*1 failed*1 error*",
- ])
-
-def test_setup_failure_is_shown(testdir):
- testdir.makepyfile("""
- import unittest
- import pytest
- class TC(unittest.TestCase):
- def setUp(self):
- assert 0, "down1"
- def test_method(self):
- print ("never42")
- xyz
- """)
- result = testdir.runpytest("-s")
- assert result.ret == 1
- result.stdout.fnmatch_lines([
- "*setUp*",
- "*assert 0*down1*",
- "*1 failed*",
- ])
- assert 'never42' not in result.stdout.str()
-
-def test_setup_setUpClass(testdir):
- testpath = testdir.makepyfile("""
- import unittest
- import pytest
- class MyTestCase(unittest.TestCase):
- x = 0
- @classmethod
- def setUpClass(cls):
- cls.x += 1
- def test_func1(self):
- assert self.x == 1
- def test_func2(self):
- assert self.x == 1
- @classmethod
- def tearDownClass(cls):
- cls.x -= 1
- def test_teareddown():
- assert MyTestCase.x == 0
- """)
- reprec = testdir.inline_run(testpath)
- reprec.assertoutcome(passed=3)
-
-def test_setup_class(testdir):
- testpath = testdir.makepyfile("""
- import unittest
- import pytest
- class MyTestCase(unittest.TestCase):
- x = 0
- def setup_class(cls):
- cls.x += 1
- def test_func1(self):
- assert self.x == 1
- def test_func2(self):
- assert self.x == 1
- def teardown_class(cls):
- cls.x -= 1
- def test_teareddown():
- assert MyTestCase.x == 0
- """)
- reprec = testdir.inline_run(testpath)
- reprec.assertoutcome(passed=3)
-
-
-@pytest.mark.parametrize("type", ['Error', 'Failure'])
-def test_testcase_adderrorandfailure_defers(testdir, type):
- testdir.makepyfile("""
- from unittest import TestCase
- import pytest
- class MyTestCase(TestCase):
- def run(self, result):
- excinfo = pytest.raises(ZeroDivisionError, lambda: 0/0)
- try:
- result.add%s(self, excinfo._excinfo)
- except KeyboardInterrupt:
- raise
- except:
- pytest.fail("add%s should not raise")
- def test_hello(self):
- pass
- """ % (type, type))
- result = testdir.runpytest()
- assert 'should not raise' not in result.stdout.str()
-
-@pytest.mark.parametrize("type", ['Error', 'Failure'])
-def test_testcase_custom_exception_info(testdir, type):
- testdir.makepyfile("""
- from unittest import TestCase
- import py, pytest
- import _pytest._code
- class MyTestCase(TestCase):
- def run(self, result):
- excinfo = pytest.raises(ZeroDivisionError, lambda: 0/0)
- # we fake an incompatible exception info
- from _pytest.monkeypatch import monkeypatch
- mp = monkeypatch()
- def t(*args):
- mp.undo()
- raise TypeError()
- mp.setattr(_pytest._code, 'ExceptionInfo', t)
- try:
- excinfo = excinfo._excinfo
- result.add%(type)s(self, excinfo)
- finally:
- mp.undo()
- def test_hello(self):
- pass
- """ % locals())
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "NOTE: Incompatible Exception Representation*",
- "*ZeroDivisionError*",
- "*1 failed*",
- ])
-
-def test_testcase_totally_incompatible_exception_info(testdir):
- item, = testdir.getitems("""
- from unittest import TestCase
- class MyTestCase(TestCase):
- def test_hello(self):
- pass
- """)
- item.addError(None, 42)
- excinfo = item._excinfo.pop(0)
- assert 'ERROR: Unknown Incompatible' in str(excinfo.getrepr())
-
-def test_module_level_pytestmark(testdir):
- testpath = testdir.makepyfile("""
- import unittest
- import pytest
- pytestmark = pytest.mark.xfail
- class MyTestCase(unittest.TestCase):
- def test_func1(self):
- assert 0
- """)
- reprec = testdir.inline_run(testpath, "-s")
- reprec.assertoutcome(skipped=1)
-
-
-def test_trial_testcase_skip_property(testdir):
- pytest.importorskip('twisted.trial.unittest')
- testpath = testdir.makepyfile("""
- from twisted.trial import unittest
- class MyTestCase(unittest.TestCase):
- skip = 'dont run'
- def test_func(self):
- pass
- """)
- reprec = testdir.inline_run(testpath, "-s")
- reprec.assertoutcome(skipped=1)
-
-
-def test_trial_testfunction_skip_property(testdir):
- pytest.importorskip('twisted.trial.unittest')
- testpath = testdir.makepyfile("""
- from twisted.trial import unittest
- class MyTestCase(unittest.TestCase):
- def test_func(self):
- pass
- test_func.skip = 'dont run'
- """)
- reprec = testdir.inline_run(testpath, "-s")
- reprec.assertoutcome(skipped=1)
-
-
-def test_trial_testcase_todo_property(testdir):
- pytest.importorskip('twisted.trial.unittest')
- testpath = testdir.makepyfile("""
- from twisted.trial import unittest
- class MyTestCase(unittest.TestCase):
- todo = 'dont run'
- def test_func(self):
- assert 0
- """)
- reprec = testdir.inline_run(testpath, "-s")
- reprec.assertoutcome(skipped=1)
-
-
-def test_trial_testfunction_todo_property(testdir):
- pytest.importorskip('twisted.trial.unittest')
- testpath = testdir.makepyfile("""
- from twisted.trial import unittest
- class MyTestCase(unittest.TestCase):
- def test_func(self):
- assert 0
- test_func.todo = 'dont run'
- """)
- reprec = testdir.inline_run(testpath, "-s")
- reprec.assertoutcome(skipped=1)
-
-
-class TestTrialUnittest:
- def setup_class(cls):
- cls.ut = pytest.importorskip("twisted.trial.unittest")
-
- def test_trial_testcase_runtest_not_collected(self, testdir):
- testdir.makepyfile("""
- from twisted.trial.unittest import TestCase
-
- class TC(TestCase):
- def test_hello(self):
- pass
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
- testdir.makepyfile("""
- from twisted.trial.unittest import TestCase
-
- class TC(TestCase):
- def runTest(self):
- pass
- """)
- reprec = testdir.inline_run()
- reprec.assertoutcome(passed=1)
-
- def test_trial_exceptions_with_skips(self, testdir):
- testdir.makepyfile("""
- from twisted.trial import unittest
- import pytest
- class TC(unittest.TestCase):
- def test_hello(self):
- pytest.skip("skip_in_method")
- @pytest.mark.skipif("sys.version_info != 1")
- def test_hello2(self):
- pass
- @pytest.mark.xfail(reason="iwanto")
- def test_hello3(self):
- assert 0
- def test_hello4(self):
- pytest.xfail("i2wanto")
- def test_trial_skip(self):
- pass
- test_trial_skip.skip = "trialselfskip"
-
- def test_trial_todo(self):
- assert 0
- test_trial_todo.todo = "mytodo"
-
- def test_trial_todo_success(self):
- pass
- test_trial_todo_success.todo = "mytodo"
-
- class TC2(unittest.TestCase):
- def setup_class(cls):
- pytest.skip("skip_in_setup_class")
- def test_method(self):
- pass
- """)
- result = testdir.runpytest("-rxs")
- assert result.ret == 0
- result.stdout.fnmatch_lines_random([
- "*XFAIL*test_trial_todo*",
- "*trialselfskip*",
- "*skip_in_setup_class*",
- "*iwanto*",
- "*i2wanto*",
- "*sys.version_info*",
- "*skip_in_method*",
- "*4 skipped*3 xfail*1 xpass*",
- ])
-
- def test_trial_error(self, testdir):
- testdir.makepyfile("""
- from twisted.trial.unittest import TestCase
- from twisted.internet.defer import Deferred
- from twisted.internet import reactor
-
- class TC(TestCase):
- def test_one(self):
- crash
-
- def test_two(self):
- def f(_):
- crash
-
- d = Deferred()
- d.addCallback(f)
- reactor.callLater(0.3, d.callback, None)
- return d
-
- def test_three(self):
- def f():
- pass # will never get called
- reactor.callLater(0.3, f)
- # will crash at teardown
-
- def test_four(self):
- def f(_):
- reactor.callLater(0.3, f)
- crash
-
- d = Deferred()
- d.addCallback(f)
- reactor.callLater(0.3, d.callback, None)
- return d
- # will crash both at test time and at teardown
- """)
- result = testdir.runpytest()
- result.stdout.fnmatch_lines([
- "*ERRORS*",
- "*DelayedCalls*",
- "*test_four*",
- "*NameError*crash*",
- "*test_one*",
- "*NameError*crash*",
- "*test_three*",
- "*DelayedCalls*",
- "*test_two*",
- "*crash*",
- ])
-
- def test_trial_pdb(self, testdir):
- p = testdir.makepyfile("""
- from twisted.trial import unittest
- import pytest
- class TC(unittest.TestCase):
- def test_hello(self):
- assert 0, "hellopdb"
- """)
- child = testdir.spawn_pytest(p)
- child.expect("hellopdb")
- child.sendeof()
-
-def test_djangolike_testcase(testdir):
- # contributed from Morten Breekevold
- testdir.makepyfile("""
- from unittest import TestCase, main
-
- class DjangoLikeTestCase(TestCase):
-
- def setUp(self):
- print ("setUp()")
-
- def test_presetup_has_been_run(self):
- print ("test_thing()")
- self.assertTrue(hasattr(self, 'was_presetup'))
-
- def tearDown(self):
- print ("tearDown()")
-
- def __call__(self, result=None):
- try:
- self._pre_setup()
- except (KeyboardInterrupt, SystemExit):
- raise
- except Exception:
- import sys
- result.addError(self, sys.exc_info())
- return
- super(DjangoLikeTestCase, self).__call__(result)
- try:
- self._post_teardown()
- except (KeyboardInterrupt, SystemExit):
- raise
- except Exception:
- import sys
- result.addError(self, sys.exc_info())
- return
-
- def _pre_setup(self):
- print ("_pre_setup()")
- self.was_presetup = True
-
- def _post_teardown(self):
- print ("_post_teardown()")
- """)
- result = testdir.runpytest("-s")
- assert result.ret == 0
- result.stdout.fnmatch_lines([
- "*_pre_setup()*",
- "*setUp()*",
- "*test_thing()*",
- "*tearDown()*",
- "*_post_teardown()*",
- ])
-
-
-def test_unittest_not_shown_in_traceback(testdir):
- testdir.makepyfile("""
- import unittest
- class t(unittest.TestCase):
- def test_hello(self):
- x = 3
- self.assertEquals(x, 4)
- """)
- res = testdir.runpytest()
- assert "failUnlessEqual" not in res.stdout.str()
-
-def test_unorderable_types(testdir):
- testdir.makepyfile("""
- import unittest
- class TestJoinEmpty(unittest.TestCase):
- pass
-
- def make_test():
- class Test(unittest.TestCase):
- pass
- Test.__name__ = "TestFoo"
- return Test
- TestFoo = make_test()
- """)
- result = testdir.runpytest()
- assert "TypeError" not in result.stdout.str()
- assert result.ret == EXIT_NOTESTSCOLLECTED
-
-def test_unittest_typerror_traceback(testdir):
- testdir.makepyfile("""
- import unittest
- class TestJoinEmpty(unittest.TestCase):
- def test_hello(self, arg1):
- pass
- """)
- result = testdir.runpytest()
- assert "TypeError" in result.stdout.str()
- assert result.ret == 1
-
-@pytest.mark.skipif("sys.version_info < (2,7)")
-def test_unittest_unexpected_failure(testdir):
- testdir.makepyfile("""
- import unittest
- class MyTestCase(unittest.TestCase):
- @unittest.expectedFailure
- def test_func1(self):
- assert 0
- @unittest.expectedFailure
- def test_func2(self):
- assert 1
- """)
- result = testdir.runpytest("-rxX")
- result.stdout.fnmatch_lines([
- "*XFAIL*MyTestCase*test_func1*",
- "*XPASS*MyTestCase*test_func2*",
- "*1 xfailed*1 xpass*",
- ])
-
-
-@pytest.mark.parametrize('fix_type, stmt', [
- ('fixture', 'return'),
- ('yield_fixture', 'yield'),
-])
-def test_unittest_setup_interaction(testdir, fix_type, stmt):
- testdir.makepyfile("""
- import unittest
- import pytest
- class MyTestCase(unittest.TestCase):
- @pytest.{fix_type}(scope="class", autouse=True)
- def perclass(self, request):
- request.cls.hello = "world"
- {stmt}
- @pytest.{fix_type}(scope="function", autouse=True)
- def perfunction(self, request):
- request.instance.funcname = request.function.__name__
- {stmt}
-
- def test_method1(self):
- assert self.funcname == "test_method1"
- assert self.hello == "world"
-
- def test_method2(self):
- assert self.funcname == "test_method2"
-
- def test_classattr(self):
- assert self.__class__.hello == "world"
- """.format(fix_type=fix_type, stmt=stmt))
- result = testdir.runpytest()
- result.stdout.fnmatch_lines("*3 passed*")
-
-
-def test_non_unittest_no_setupclass_support(testdir):
- testpath = testdir.makepyfile("""
- class TestFoo:
- x = 0
-
- @classmethod
- def setUpClass(cls):
- cls.x = 1
-
- def test_method1(self):
- assert self.x == 0
-
- @classmethod
- def tearDownClass(cls):
- cls.x = 1
-
- def test_not_teareddown():
- assert TestFoo.x == 0
-
- """)
- reprec = testdir.inline_run(testpath)
- reprec.assertoutcome(passed=2)
-
-
-def test_no_teardown_if_setupclass_failed(testdir):
- testpath = testdir.makepyfile("""
- import unittest
-
- class MyTestCase(unittest.TestCase):
- x = 0
-
- @classmethod
- def setUpClass(cls):
- cls.x = 1
- assert False
-
- def test_func1(self):
- cls.x = 10
-
- @classmethod
- def tearDownClass(cls):
- cls.x = 100
-
- def test_notTornDown():
- assert MyTestCase.x == 1
- """)
- reprec = testdir.inline_run(testpath)
- reprec.assertoutcome(passed=1, failed=1)
-
-
-def test_issue333_result_clearing(testdir):
- testdir.makeconftest("""
- def pytest_runtest_call(__multicall__, item):
- __multicall__.execute()
- assert 0
- """)
- testdir.makepyfile("""
- import unittest
- class TestIt(unittest.TestCase):
- def test_func(self):
- 0/0
- """)
-
- reprec = testdir.inline_run()
- reprec.assertoutcome(failed=1)
-
-@pytest.mark.skipif("sys.version_info < (2,7)")
-def test_unittest_raise_skip_issue748(testdir):
- testdir.makepyfile(test_foo="""
- import unittest
-
- class MyTestCase(unittest.TestCase):
- def test_one(self):
- raise unittest.SkipTest('skipping due to reasons')
- """)
- result = testdir.runpytest("-v", '-rs')
- result.stdout.fnmatch_lines("""
- *SKIP*[1]*test_foo.py*skipping due to reasons*
- *1 skipped*
- """)
-
-@pytest.mark.skipif("sys.version_info < (2,7)")
-def test_unittest_skip_issue1169(testdir):
- testdir.makepyfile(test_foo="""
- import unittest
-
- class MyTestCase(unittest.TestCase):
- @unittest.skip("skipping due to reasons")
- def test_skip(self):
- self.fail()
- """)
- result = testdir.runpytest("-v", '-rs')
- result.stdout.fnmatch_lines("""
- *SKIP*[1]*skipping due to reasons*
- *1 skipped*
- """)
diff --git a/tests/wpt/web-platform-tests/tools/pytest/tox.ini b/tests/wpt/web-platform-tests/tools/pytest/tox.ini
deleted file mode 100644
index 5f65446e42b..00000000000
--- a/tests/wpt/web-platform-tests/tools/pytest/tox.ini
+++ /dev/null
@@ -1,160 +0,0 @@
-[tox]
-minversion=2.0
-distshare={homedir}/.tox/distshare
-envlist=
- linting,py26,py27,py33,py34,py35,pypy,
- {py27,py35}-{pexpect,xdist,trial},
- py27-nobyte,doctesting,py27-cxfreeze
-
-[testenv]
-commands= py.test --lsof -rfsxX {posargs:testing}
-passenv = USER USERNAME
-deps=
- nose
- mock
- requests
-
-[testenv:py26]
-commands= py.test --lsof -rfsxX {posargs:testing}
-deps=
- nose
- mock<1.1 # last supported version for py26
-
-[testenv:py27-subprocess]
-changedir=.
-basepython=python2.7
-deps=pytest-xdist>=1.13
- mock
- nose
-commands=
- py.test -n3 -rfsxX --runpytest=subprocess {posargs:testing}
-
-[testenv:genscript]
-commands= py.test --genscript=pytest1
-
-[testenv:linting]
-basepython = python2.7
-deps = flake8
- restructuredtext_lint
-commands = flake8 pytest.py _pytest testing
- rst-lint CHANGELOG.rst
-
-[testenv:py27-xdist]
-deps=pytest-xdist>=1.13
- mock
- nose
-commands=
- py.test -n1 -rfsxX {posargs:testing}
-
-[testenv:py35-xdist]
-deps={[testenv:py27-xdist]deps}
-commands=
- py.test -n3 -rfsxX {posargs:testing}
-
-[testenv:py27-pexpect]
-changedir=testing
-platform=linux|darwin
-deps=pexpect
-commands=
- py.test -rfsxX test_pdb.py test_terminal.py test_unittest.py
-
-[testenv:py35-pexpect]
-changedir=testing
-platform=linux|darwin
-deps={[testenv:py27-pexpect]deps}
-commands=
- py.test -rfsxX test_pdb.py test_terminal.py test_unittest.py
-
-[testenv:py27-nobyte]
-deps=pytest-xdist>=1.13
-distribute=true
-setenv=
- PYTHONDONTWRITEBYTECODE=1
-commands=
- py.test -n3 -rfsxX {posargs:testing}
-
-[testenv:py27-trial]
-deps=twisted
-commands=
- py.test -rsxf {posargs:testing/test_unittest.py}
-
-[testenv:py35-trial]
-platform=linux|darwin
-deps={[testenv:py27-trial]deps}
-commands=
- py.test -rsxf {posargs:testing/test_unittest.py}
-
-[testenv:doctest]
-commands=py.test --doctest-modules _pytest
-deps=
-
-[testenv:doc]
-basepython=python
-changedir=doc/en
-deps=sphinx
- PyYAML
-
-commands=
- make clean
- make html
-
-[testenv:doctesting]
-basepython = python3.4
-changedir=doc/en
-deps=PyYAML
-commands= py.test -rfsxX {posargs}
-
-[testenv:regen]
-changedir=doc/en
-basepython = python3.4
-deps=sphinx
- PyYAML
- regendoc>=0.6.1
-whitelist_externals=
- rm
- make
-commands=
- rm -rf /tmp/doc-exec*
- make regen
-
-[testenv:jython]
-changedir=testing
-commands=
- {envpython} {envbindir}/py.test-jython -rfsxX {posargs}
-
-[testenv:py27-cxfreeze]
-changedir=testing/cx_freeze
-platform=linux|darwin
-commands=
- {envpython} install_cx_freeze.py
- {envpython} runtests_setup.py build --build-exe build
- {envpython} tox_run.py
-
-
-[testenv:coveralls]
-passenv = TRAVIS TRAVIS_JOB_ID TRAVIS_BRANCH COVERALLS_REPO_TOKEN
-usedevelop=True
-basepython=python3.4
-changedir=.
-deps =
- {[testenv]deps}
- coveralls
-commands=
- coverage run --source=_pytest -m pytest testing
- coverage report -m
- coveralls
-
-[pytest]
-minversion=2.0
-plugins=pytester
-#--pyargs --doctest-modules --ignore=.tox
-addopts= -rxsX -p pytester --ignore=testing/cx_freeze
-rsyncdirs=tox.ini pytest.py _pytest testing
-python_files=test_*.py *_test.py testing/*/*.py
-python_classes=Test Acceptance
-python_functions=test
-norecursedirs = .tox ja .hg cx_freeze_source
-
-
-[flake8]
-ignore =E401,E225,E261,E128,E124,E301,E302,E121,E303,W391,E501,E231,E126,E701,E265,E241,E251,E226,E101,W191,E131,E203,E122,E123,E271,E712,E222,E127,E125,E221,W292,E111,E113,E293,E262,W293,E129,E702,E201,E272,E202,E704,E731,E402
diff --git a/tests/wpt/web-platform-tests/tools/serve/serve.py b/tests/wpt/web-platform-tests/tools/serve/serve.py
index 74b9b7e55b7..c77badc2682 100644
--- a/tests/wpt/web-platform-tests/tools/serve/serve.py
+++ b/tests/wpt/web-platform-tests/tools/serve/serve.py
@@ -383,19 +383,19 @@ class ServerProc(object):
self.daemon = None
self.stop = Event()
- def start(self, init_func, host, port, paths, routes, bind_hostname, external_config,
+ def start(self, init_func, host, port, paths, routes, bind_hostname, config,
ssl_config, **kwargs):
self.proc = Process(target=self.create_daemon,
args=(init_func, host, port, paths, routes, bind_hostname,
- external_config, ssl_config),
+ config, ssl_config),
kwargs=kwargs)
self.proc.daemon = True
self.proc.start()
def create_daemon(self, init_func, host, port, paths, routes, bind_hostname,
- external_config, ssl_config, **kwargs):
+ config, ssl_config, **kwargs):
try:
- self.daemon = init_func(host, port, paths, routes, bind_hostname, external_config,
+ self.daemon = init_func(host, port, paths, routes, bind_hostname, config,
ssl_config, **kwargs)
except socket.error:
print("Socket error on port %s" % port, file=sys.stderr)
@@ -446,7 +446,8 @@ def check_subdomains(host, paths, bind_hostname, ssl_config, aliases):
time.sleep(1)
if not connected:
- logger.critical("Failed to connect to test server on http://%s:%s You may need to edit /etc/hosts or similar" % (host, port))
+ logger.critical("Failed to connect to test server on http://%s:%s. "
+ "You may need to edit /etc/hosts or similar, see README.md." % (host, port))
sys.exit(1)
for subdomain, (punycode, host) in subdomains.iteritems():
@@ -454,7 +455,8 @@ def check_subdomains(host, paths, bind_hostname, ssl_config, aliases):
try:
urllib2.urlopen("http://%s:%d/" % (domain, port))
except Exception as e:
- logger.critical("Failed probing domain %s. You may need to edit /etc/hosts or similar." % domain)
+ logger.critical("Failed probing domain %s. "
+ "You may need to edit /etc/hosts or similar, see README.md." % domain)
sys.exit(1)
wrapper.wait()
@@ -466,7 +468,7 @@ def get_subdomains(host):
for subdomain in subdomains}
-def start_servers(host, ports, paths, routes, bind_hostname, external_config, ssl_config,
+def start_servers(host, ports, paths, routes, bind_hostname, config, ssl_config,
**kwargs):
servers = defaultdict(list)
for scheme, ports in ports.iteritems():
@@ -482,13 +484,13 @@ def start_servers(host, ports, paths, routes, bind_hostname, external_config, ss
server_proc = ServerProc()
server_proc.start(init_func, host, port, paths, routes, bind_hostname,
- external_config, ssl_config, **kwargs)
+ config, ssl_config, **kwargs)
servers[scheme].append((port, server_proc))
return servers
-def start_http_server(host, port, paths, routes, bind_hostname, external_config, ssl_config,
+def start_http_server(host, port, paths, routes, bind_hostname, config, ssl_config,
**kwargs):
return wptserve.WebTestHttpd(host=host,
port=port,
@@ -496,14 +498,14 @@ def start_http_server(host, port, paths, routes, bind_hostname, external_config,
routes=routes,
rewrites=rewrites,
bind_hostname=bind_hostname,
- config=external_config,
+ config=config,
use_ssl=False,
key_file=None,
certificate=None,
latency=kwargs.get("latency"))
-def start_https_server(host, port, paths, routes, bind_hostname, external_config, ssl_config,
+def start_https_server(host, port, paths, routes, bind_hostname, config, ssl_config,
**kwargs):
return wptserve.WebTestHttpd(host=host,
port=port,
@@ -511,7 +513,7 @@ def start_https_server(host, port, paths, routes, bind_hostname, external_config
routes=routes,
rewrites=rewrites,
bind_hostname=bind_hostname,
- config=external_config,
+ config=config,
use_ssl=True,
key_file=ssl_config["key_path"],
certificate=ssl_config["cert_path"],
@@ -584,7 +586,7 @@ class WebSocketDaemon(object):
self.server = None
-def start_ws_server(host, port, paths, routes, bind_hostname, external_config, ssl_config,
+def start_ws_server(host, port, paths, routes, bind_hostname, config, ssl_config,
**kwargs):
return WebSocketDaemon(host,
str(port),
@@ -595,7 +597,7 @@ def start_ws_server(host, port, paths, routes, bind_hostname, external_config, s
ssl_config = None)
-def start_wss_server(host, port, paths, routes, bind_hostname, external_config, ssl_config,
+def start_wss_server(host, port, paths, routes, bind_hostname, config, ssl_config,
**kwargs):
return WebSocketDaemon(host,
str(port),
@@ -637,12 +639,22 @@ def normalise_config(config, ports):
for scheme, ports_used in ports.iteritems():
ports_[scheme] = ports_used
- return {"host": host,
- "domains": domains,
- "ports": ports_}
+ # make a (shallow) copy of the config and update that, so that the
+ # normalized config can be used in place of the original one.
+ config_ = config.copy()
+ config_["host"] = host
+ config_["domains"] = domains
+ config_["ports"] = ports_
+ return config_
-def get_ssl_config(config, external_domains, ssl_environment):
+def get_paths(config):
+ return {"doc_root": config["doc_root"],
+ "ws_doc_root": config["ws_doc_root"]}
+
+
+def get_ssl_config(config, ssl_environment):
+ external_domains = config["domains"].values()
key_path, cert_path = ssl_environment.host_cert_path(external_domains)
return {"key_path": key_path,
"cert_path": cert_path,
@@ -650,24 +662,15 @@ def get_ssl_config(config, external_domains, ssl_environment):
def start(config, ssl_environment, routes, **kwargs):
host = config["host"]
- domains = get_subdomains(host)
ports = get_ports(config, ssl_environment)
+ paths = get_paths(config)
bind_hostname = config["bind_hostname"]
+ ssl_config = get_ssl_config(config, ssl_environment)
- paths = {"doc_root": config["doc_root"],
- "ws_doc_root": config["ws_doc_root"]}
-
- external_config = normalise_config(config, ports)
-
- ssl_config = get_ssl_config(config, external_config["domains"].values(), ssl_environment)
-
- if config["check_subdomains"]:
- check_subdomains(host, paths, bind_hostname, ssl_config, config["aliases"])
-
- servers = start_servers(host, ports, paths, routes, bind_hostname, external_config,
+ servers = start_servers(host, ports, paths, routes, bind_hostname, config,
ssl_config, **kwargs)
- return external_config, servers
+ return servers
def iter_procs(servers):
@@ -778,13 +781,23 @@ def run(**kwargs):
setup_logger(config["log_level"])
- stash_address = None
- if config["bind_hostname"]:
- stash_address = (config["host"], get_port())
+ with get_ssl_environment(config) as ssl_env:
+ ports = get_ports(config, ssl_env)
+ config = normalise_config(config, ports)
+ host = config["host"]
+ bind_hostname = config["bind_hostname"]
+
+ if config["check_subdomains"]:
+ paths = get_paths(config)
+ ssl_config = get_ssl_config(config, ssl_env)
+ check_subdomains(host, paths, bind_hostname, ssl_config, config["aliases"])
+
+ stash_address = None
+ if bind_hostname:
+ stash_address = (host, get_port())
- with stash.StashServer(stash_address, authkey=str(uuid.uuid4())):
- with get_ssl_environment(config) as ssl_env:
- config_, servers = start(config, ssl_env, build_routes(config["aliases"]), **kwargs)
+ with stash.StashServer(stash_address, authkey=str(uuid.uuid4())):
+ servers = start(config, ssl_env, build_routes(config["aliases"]), **kwargs)
try:
while any(item.is_alive() for item in iter_procs(servers)):
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/.gitignore b/tests/wpt/web-platform-tests/tools/third_party/attrs/.gitignore
new file mode 100644
index 00000000000..a4ca3f8cef7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/.gitignore
@@ -0,0 +1,9 @@
+.tox
+.coverage*
+*.pyc
+*.egg-info
+docs/_build/
+htmlcov
+dist
+.cache
+.hypothesis \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/.travis.yml b/tests/wpt/web-platform-tests/tools/third_party/attrs/.travis.yml
new file mode 100644
index 00000000000..4f1cf2f60b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/.travis.yml
@@ -0,0 +1,56 @@
+dist: trusty
+sudo: false
+cache:
+ directories:
+ - $HOME/.cache/pip
+
+language: python
+
+
+matrix:
+ include:
+ - python: "2.7"
+ env: TOXENV=py27
+ - python: "3.4"
+ env: TOXENV=py34
+ - python: "3.5"
+ env: TOXENV=py35
+ - python: "3.6"
+ env: TOXENV=py36
+ - python: "pypy2.7-5.8.0"
+ env: TOXENV=pypy
+ - python: "pypy3.5-5.8.0"
+ env: TOXENV=pypy3
+
+ # Meta
+ - python: "3.6"
+ env: TOXENV=flake8
+ - python: "3.6"
+ env: TOXENV=manifest
+ - python: "3.6"
+ env: TOXENV=docs
+ - python: "3.6"
+ env: TOXENV=readme
+ - python: "3.6"
+ env: TOXENV=changelog
+
+
+install:
+ - pip install tox
+
+
+script:
+ - tox
+
+
+before_install:
+ - pip install codecov
+
+
+after_success:
+ - tox -e coverage-report
+ - codecov
+
+
+notifications:
+ email: false
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/AUTHORS.rst b/tests/wpt/web-platform-tests/tools/third_party/attrs/AUTHORS.rst
new file mode 100644
index 00000000000..73eae2154d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/AUTHORS.rst
@@ -0,0 +1,11 @@
+Credits
+=======
+
+``attrs`` is written and maintained by `Hynek Schlawack <https://hynek.me/>`_.
+
+The development is kindly supported by `Variomedia AG <https://www.variomedia.de/>`_.
+
+A full list of contributors can be found in `GitHub's overview <https://github.com/python-attrs/attrs/graphs/contributors>`_.
+
+It’s the spiritual successor of `characteristic <https://characteristic.readthedocs.io/>`_ and aspires to fix some of it clunkiness and unfortunate decisions.
+Both were inspired by Twisted’s `FancyEqMixin <https://twistedmatrix.com/documents/current/api/twisted.python.util.FancyEqMixin.html>`_ but both are implemented using class decorators because `sub-classing is bad for you <https://www.youtube.com/watch?v=3MNVP9-hglc>`_, m’kay?
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/CHANGELOG.rst b/tests/wpt/web-platform-tests/tools/third_party/attrs/CHANGELOG.rst
new file mode 100644
index 00000000000..55cd4591357
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/CHANGELOG.rst
@@ -0,0 +1,326 @@
+Changelog
+=========
+
+Versions follow `CalVer <http://calver.org>`_ with a strict backwards compatibility policy.
+The third digit is only for regressions.
+
+Changes for the upcoming release can be found in the `"changelog.d" directory <https://github.com/python-attrs/attrs/tree/master/changelog.d>`_ in our repository.
+
+..
+ Do *NOT* add changelog entries here!
+
+ This changelog is managed by towncrier and is compiled at release time.
+
+ See http://www.attrs.org/en/latest/contributing.html#changelog for details.""" # noqa
+
+.. towncrier release notes start
+
+
+17.3.0 (2017-11-08)
+-------------------
+
+Backward-incompatible Changes
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- Attributes are not defined on the class body anymore.
+
+ This means that if you define a class ``C`` with an attribute ``x``, the class will *not* have an attribute ``x`` for introspection anymore.
+ Instead of ``C.x``, use ``attr.fields(C).x`` or look at ``C.__attrs_attrs__``.
+ The old behavior has been deprecated since version 16.1.
+ (`#253 <https://github.com/python-attrs/attrs/issues/253>`_)
+
+
+Changes
+^^^^^^^
+
+- ``super()`` and ``__class__`` now work on Python 3 when ``slots=True``.
+ (`#102 <https://github.com/python-attrs/attrs/issues/102>`_, `#226 <https://github.com/python-attrs/attrs/issues/226>`_, `#269 <https://github.com/python-attrs/attrs/issues/269>`_, `#270 <https://github.com/python-attrs/attrs/issues/270>`_, `#272 <https://github.com/python-attrs/attrs/issues/272>`_)
+- Added ``type`` argument to ``attr.ib()`` and corresponding ``type`` attribute to ``attr.Attribute``.
+
+ This change paves the way for automatic type checking and serialization (though as of this release ``attrs`` does not make use of it).
+ In Python 3.6 or higher, the value of ``attr.Attribute.type`` can alternately be set using variable type annotations
+ (see `PEP 526 <https://www.python.org/dev/peps/pep-0526/>`_). (`#151 <https://github.com/python-attrs/attrs/issues/151>`_, `#214 <https://github.com/python-attrs/attrs/issues/214>`_, `#215 <https://github.com/python-attrs/attrs/issues/215>`_, `#239 <https://github.com/python-attrs/attrs/issues/239>`_)
+- The combination of ``str=True`` and ``slots=True`` now works on Python 2.
+ (`#198 <https://github.com/python-attrs/attrs/issues/198>`_)
+- ``attr.Factory`` is hashable again. (`#204
+ <https://github.com/python-attrs/attrs/issues/204>`_)
+- Subclasses now can overwrite attribute definitions of their superclass.
+
+ That means that you can -- for example -- change the default value for an attribute by redefining it.
+ (`#221 <https://github.com/python-attrs/attrs/issues/221>`_, `#229 <https://github.com/python-attrs/attrs/issues/229>`_)
+- Added new option ``auto_attribs`` to ``@attr.s`` that allows to collect annotated fields without setting them to ``attr.ib()``.
+
+ Setting a field to an ``attr.ib()`` is still possible to supply options like validators.
+ Setting it to any other value is treated like it was passed as ``attr.ib(default=value)`` -- passing an instance of ``attr.Factory`` also works as expected.
+ (`#262 <https://github.com/python-attrs/attrs/issues/262>`_, `#277 <https://github.com/python-attrs/attrs/issues/277>`_)
+- Instances of classes created using ``attr.make_class()`` can now be pickled.
+ (`#282 <https://github.com/python-attrs/attrs/issues/282>`_)
+
+
+----
+
+
+17.2.0 (2017-05-24)
+-------------------
+
+
+Changes:
+^^^^^^^^
+
+- Validators are hashable again.
+ Note that validators may become frozen in the future, pending availability of no-overhead frozen classes.
+ `#192 <https://github.com/python-attrs/attrs/issues/192>`_
+
+
+----
+
+
+17.1.0 (2017-05-16)
+-------------------
+
+To encourage more participation, the project has also been moved into a `dedicated GitHub organization <https://github.com/python-attrs/>`_ and everyone is most welcome to join!
+
+``attrs`` also has a logo now!
+
+.. image:: http://www.attrs.org/en/latest/_static/attrs_logo.png
+ :alt: attrs logo
+
+
+Backward-incompatible Changes:
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- ``attrs`` will set the ``__hash__()`` method to ``None`` by default now.
+ The way hashes were handled before was in conflict with `Python's specification <https://docs.python.org/3/reference/datamodel.html#object.__hash__>`_.
+ This *may* break some software although this breakage is most likely just surfacing of latent bugs.
+ You can always make ``attrs`` create the ``__hash__()`` method using ``@attr.s(hash=True)``.
+ See `#136`_ for the rationale of this change.
+
+ .. warning::
+
+ Please *do not* upgrade blindly and *do* test your software!
+ *Especially* if you use instances as dict keys or put them into sets!
+
+- Correspondingly, ``attr.ib``'s ``hash`` argument is ``None`` by default too and mirrors the ``cmp`` argument as it should.
+
+
+Deprecations:
+^^^^^^^^^^^^^
+
+- ``attr.assoc()`` is now deprecated in favor of ``attr.evolve()`` and will stop working in 2018.
+
+
+Changes:
+^^^^^^^^
+
+- Fix default hashing behavior.
+ Now *hash* mirrors the value of *cmp* and classes are unhashable by default.
+ `#136`_
+ `#142 <https://github.com/python-attrs/attrs/issues/142>`_
+- Added ``attr.evolve()`` that, given an instance of an ``attrs`` class and field changes as keyword arguments, will instantiate a copy of the given instance with the changes applied.
+ ``evolve()`` replaces ``assoc()``, which is now deprecated.
+ ``evolve()`` is significantly faster than ``assoc()``, and requires the class have an initializer that can take the field values as keyword arguments (like ``attrs`` itself can generate).
+ `#116 <https://github.com/python-attrs/attrs/issues/116>`_
+ `#124 <https://github.com/python-attrs/attrs/pull/124>`_
+ `#135 <https://github.com/python-attrs/attrs/pull/135>`_
+- ``FrozenInstanceError`` is now raised when trying to delete an attribute from a frozen class.
+ `#118 <https://github.com/python-attrs/attrs/pull/118>`_
+- Frozen-ness of classes is now inherited.
+ `#128 <https://github.com/python-attrs/attrs/pull/128>`_
+- ``__attrs_post_init__()`` is now run if validation is disabled.
+ `#130 <https://github.com/python-attrs/attrs/pull/130>`_
+- Added ``attr.validators.in_(options)`` that, given the allowed `options`, checks whether the attribute value is in it.
+ This can be used to check constants, enums, mappings, etc.
+ `#181 <https://github.com/python-attrs/attrs/pull/181>`_
+- Added ``attr.validators.and_()`` that composes multiple validators into one.
+ `#161 <https://github.com/python-attrs/attrs/issues/161>`_
+- For convenience, the ``validator`` argument of ``@attr.s`` now can take a ``list`` of validators that are wrapped using ``and_()``.
+ `#138 <https://github.com/python-attrs/attrs/issues/138>`_
+- Accordingly, ``attr.validators.optional()`` now can take a ``list`` of validators too.
+ `#161 <https://github.com/python-attrs/attrs/issues/161>`_
+- Validators can now be defined conveniently inline by using the attribute as a decorator.
+ Check out the `examples <http://www.attrs.org/en/stable/examples.html#validators>`_ to see it in action!
+ `#143 <https://github.com/python-attrs/attrs/issues/143>`_
+- ``attr.Factory()`` now has a ``takes_self`` argument that makes the initializer to pass the partially initialized instance into the factory.
+ In other words you can define attribute defaults based on other attributes.
+ `#165`_
+ `#189 <https://github.com/python-attrs/attrs/issues/189>`_
+- Default factories can now also be defined inline using decorators.
+ They are *always* passed the partially initialized instance.
+ `#165`_
+- Conversion can now be made optional using ``attr.converters.optional()``.
+ `#105 <https://github.com/python-attrs/attrs/issues/105>`_
+ `#173 <https://github.com/python-attrs/attrs/pull/173>`_
+- ``attr.make_class()`` now accepts the keyword argument ``bases`` which allows for subclassing.
+ `#152 <https://github.com/python-attrs/attrs/pull/152>`_
+- Metaclasses are now preserved with ``slots=True``.
+ `#155 <https://github.com/python-attrs/attrs/pull/155>`_
+
+.. _`#136`: https://github.com/python-attrs/attrs/issues/136
+.. _`#165`: https://github.com/python-attrs/attrs/issues/165
+
+
+----
+
+
+16.3.0 (2016-11-24)
+-------------------
+
+Changes:
+^^^^^^^^
+
+- Attributes now can have user-defined metadata which greatly improves ``attrs``'s extensibility.
+ `#96 <https://github.com/python-attrs/attrs/pull/96>`_
+- Allow for a ``__attrs_post_init__()`` method that -- if defined -- will get called at the end of the ``attrs``-generated ``__init__()`` method.
+ `#111 <https://github.com/python-attrs/attrs/pull/111>`_
+- Added ``@attr.s(str=True)`` that will optionally create a ``__str__()`` method that is identical to ``__repr__()``.
+ This is mainly useful with ``Exception``\ s and other classes that rely on a useful ``__str__()`` implementation but overwrite the default one through a poor own one.
+ Default Python class behavior is to use ``__repr__()`` as ``__str__()`` anyways.
+
+ If you tried using ``attrs`` with ``Exception``\ s and were puzzled by the tracebacks: this option is for you.
+- ``__name__`` is not overwritten with ``__qualname__`` for ``attr.s(slots=True)`` classes anymore.
+ `#99 <https://github.com/python-attrs/attrs/issues/99>`_
+
+
+----
+
+
+16.2.0 (2016-09-17)
+-------------------
+
+Changes:
+^^^^^^^^
+
+- Added ``attr.astuple()`` that -- similarly to ``attr.asdict()`` -- returns the instance as a tuple.
+ `#77 <https://github.com/python-attrs/attrs/issues/77>`_
+- Converts now work with frozen classes.
+ `#76 <https://github.com/python-attrs/attrs/issues/76>`_
+- Instantiation of ``attrs`` classes with converters is now significantly faster.
+ `#80 <https://github.com/python-attrs/attrs/pull/80>`_
+- Pickling now works with ``__slots__`` classes.
+ `#81 <https://github.com/python-attrs/attrs/issues/81>`_
+- ``attr.assoc()`` now works with ``__slots__`` classes.
+ `#84 <https://github.com/python-attrs/attrs/issues/84>`_
+- The tuple returned by ``attr.fields()`` now also allows to access the ``Attribute`` instances by name.
+ Yes, we've subclassed ``tuple`` so you don't have to!
+ Therefore ``attr.fields(C).x`` is equivalent to the deprecated ``C.x`` and works with ``__slots__`` classes.
+ `#88 <https://github.com/python-attrs/attrs/issues/88>`_
+
+
+----
+
+
+16.1.0 (2016-08-30)
+-------------------
+
+Backward-incompatible Changes:
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- All instances where function arguments were called ``cl`` have been changed to the more Pythonic ``cls``.
+ Since it was always the first argument, it's doubtful anyone ever called those function with in the keyword form.
+ If so, sorry for any breakage but there's no practical deprecation path to solve this ugly wart.
+
+
+Deprecations:
+^^^^^^^^^^^^^
+
+- Accessing ``Attribute`` instances on class objects is now deprecated and will stop working in 2017.
+ If you need introspection please use the ``__attrs_attrs__`` attribute or the ``attr.fields()`` function that carry them too.
+ In the future, the attributes that are defined on the class body and are usually overwritten in your ``__init__`` method are simply removed after ``@attr.s`` has been applied.
+
+ This will remove the confusing error message if you write your own ``__init__`` and forget to initialize some attribute.
+ Instead you will get a straightforward ``AttributeError``.
+ In other words: decorated classes will work more like plain Python classes which was always ``attrs``'s goal.
+- The serious business aliases ``attr.attributes`` and ``attr.attr`` have been deprecated in favor of ``attr.attrs`` and ``attr.attrib`` which are much more consistent and frankly obvious in hindsight.
+ They will be purged from documentation immediately but there are no plans to actually remove them.
+
+
+Changes:
+^^^^^^^^
+
+- ``attr.asdict()``\ 's ``dict_factory`` arguments is now propagated on recursion.
+ `#45 <https://github.com/python-attrs/attrs/issues/45>`_
+- ``attr.asdict()``, ``attr.has()`` and ``attr.fields()`` are significantly faster.
+ `#48 <https://github.com/python-attrs/attrs/issues/48>`_
+ `#51 <https://github.com/python-attrs/attrs/issues/51>`_
+- Add ``attr.attrs`` and ``attr.attrib`` as a more consistent aliases for ``attr.s`` and ``attr.ib``.
+- Add ``frozen`` option to ``attr.s`` that will make instances best-effort immutable.
+ `#60 <https://github.com/python-attrs/attrs/issues/60>`_
+- ``attr.asdict()`` now takes ``retain_collection_types`` as an argument.
+ If ``True``, it does not convert attributes of type ``tuple`` or ``set`` to ``list``.
+ `#69 <https://github.com/python-attrs/attrs/issues/69>`_
+
+
+----
+
+
+16.0.0 (2016-05-23)
+-------------------
+
+Backward-incompatible Changes:
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- Python 3.3 and 2.6 aren't supported anymore.
+ They may work by chance but any effort to keep them working has ceased.
+
+ The last Python 2.6 release was on October 29, 2013 and isn't supported by the CPython core team anymore.
+ Major Python packages like Django and Twisted dropped Python 2.6 a while ago already.
+
+ Python 3.3 never had a significant user base and wasn't part of any distribution's LTS release.
+
+Changes:
+^^^^^^^^
+
+- ``__slots__`` have arrived!
+ Classes now can automatically be `slots <https://docs.python.org/3/reference/datamodel.html#slots>`_-style (and save your precious memory) just by passing ``slots=True``.
+ `#35 <https://github.com/python-attrs/attrs/issues/35>`_
+- Allow the case of initializing attributes that are set to ``init=False``.
+ This allows for clean initializer parameter lists while being able to initialize attributes to default values.
+ `#32 <https://github.com/python-attrs/attrs/issues/32>`_
+- ``attr.asdict()`` can now produce arbitrary mappings instead of Python ``dict``\ s when provided with a ``dict_factory`` argument.
+ `#40 <https://github.com/python-attrs/attrs/issues/40>`_
+- Multiple performance improvements.
+
+
+----
+
+
+15.2.0 (2015-12-08)
+-------------------
+
+Changes:
+^^^^^^^^
+
+- Added a ``convert`` argument to ``attr.ib``, which allows specifying a function to run on arguments.
+ This allows for simple type conversions, e.g. with ``attr.ib(convert=int)``.
+ `#26 <https://github.com/python-attrs/attrs/issues/26>`_
+- Speed up object creation when attribute validators are used.
+ `#28 <https://github.com/python-attrs/attrs/issues/28>`_
+
+
+----
+
+
+15.1.0 (2015-08-20)
+-------------------
+
+Changes:
+^^^^^^^^
+
+- Added ``attr.validators.optional()`` that wraps other validators allowing attributes to be ``None``.
+ `#16 <https://github.com/python-attrs/attrs/issues/16>`_
+- Multi-level inheritance now works.
+ `#24 <https://github.com/python-attrs/attrs/issues/24>`_
+- ``__repr__()`` now works with non-redecorated subclasses.
+ `#20 <https://github.com/python-attrs/attrs/issues/20>`_
+
+
+----
+
+
+15.0.0 (2015-04-15)
+-------------------
+
+Changes:
+^^^^^^^^
+
+Initial release.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/CODE_OF_CONDUCT.rst b/tests/wpt/web-platform-tests/tools/third_party/attrs/CODE_OF_CONDUCT.rst
new file mode 100644
index 00000000000..4f4b8ee9cd9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/CODE_OF_CONDUCT.rst
@@ -0,0 +1,55 @@
+Contributor Covenant Code of Conduct
+====================================
+
+Our Pledge
+----------
+
+In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
+
+Our Standards
+-------------
+
+Examples of behavior that contributes to creating a positive environment include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a professional setting
+
+Our Responsibilities
+--------------------
+
+Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
+
+Scope
+-----
+
+This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.
+Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
+Representation of a project may be further defined and clarified by project maintainers.
+
+Enforcement
+-----------
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at hs@ox.cx.
+All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances.
+The project team is obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
+
+Attribution
+-----------
+
+This Code of Conduct is adapted from the `Contributor Covenant <http://contributor-covenant.org>`_, version 1.4, available at http://contributor-covenant.org/version/1/4.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/CONTRIBUTING.rst b/tests/wpt/web-platform-tests/tools/third_party/attrs/CONTRIBUTING.rst
new file mode 100644
index 00000000000..9822f8926a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/CONTRIBUTING.rst
@@ -0,0 +1,220 @@
+How To Contribute
+=================
+
+First off, thank you for considering contributing to ``attrs``!
+It's people like *you* who make it is such a great tool for everyone.
+
+This document is mainly to help you to get started by codifying tribal knowledge and expectations and make it more accessible to everyone.
+But don't be afraid to open half-finished PRs and ask questions if something is unclear!
+
+
+Support
+-------
+
+In case you'd like to help out but don't want to deal with GitHub, there's a great opportunity:
+help your fellow developers on `StackOverflow <https://stackoverflow.com/questions/tagged/python-attrs>`_!
+
+The offical tag is ``python-attrs`` and helping out in support frees us up for improving ``attrs`` instead!
+
+
+Workflow
+--------
+
+- No contribution is too small!
+ Please submit as many fixes for typos and grammar bloopers as you can!
+- Try to limit each pull request to *one* change only.
+- *Always* add tests and docs for your code.
+ This is a hard rule; patches with missing tests or documentation can't be merged.
+- Make sure your changes pass our CI_.
+ You won't get any feedback until it's green unless you ask for it.
+- Once you've addressed review feedback, make sure to bump the pull request with a short note, so we know you're done.
+- Don’t break `backward compatibility`_.
+
+
+Code
+----
+
+- Obey `PEP 8`_ and `PEP 257`_.
+ We use the ``"""``\ -on-separate-lines style for docstrings:
+
+ .. code-block:: python
+
+ def func(x):
+ """
+ Do something.
+
+ :param str x: A very important parameter.
+
+ :rtype: str
+ """
+- If you add or change public APIs, tag the docstring using ``.. versionadded:: 16.0.0 WHAT`` or ``.. versionchanged:: 16.2.0 WHAT``.
+- Prefer double quotes (``"``) over single quotes (``'``) unless the string contains double quotes itself.
+
+
+Tests
+-----
+
+- Write your asserts as ``expected == actual`` to line them up nicely:
+
+ .. code-block:: python
+
+ x = f()
+
+ assert 42 == x.some_attribute
+ assert "foo" == x._a_private_attribute
+
+- To run the test suite, all you need is a recent tox_.
+ It will ensure the test suite runs with all dependencies against all Python versions just as it will on Travis CI.
+ If you lack some Python versions, you can can always limit the environments like ``tox -e py27,py35`` (in that case you may want to look into pyenv_, which makes it very easy to install many different Python versions in parallel).
+- Write `good test docstrings`_.
+- To ensure new features work well with the rest of the system, they should be also added to our `Hypothesis`_ testing strategy which you find in ``tests/util.py``.
+
+
+Documentation
+-------------
+
+- Use `semantic newlines`_ in reStructuredText_ files (files ending in ``.rst``):
+
+ .. code-block:: rst
+
+ This is a sentence.
+ This is another sentence.
+
+- If you start a new section, add two blank lines before and one blank line after the header except if two headers follow immediately after each other:
+
+ .. code-block:: rst
+
+ Last line of previous section.
+
+
+ Header of New Top Section
+ -------------------------
+
+ Header of New Section
+ ^^^^^^^^^^^^^^^^^^^^^
+
+ First line of new section.
+- If you add a new feature, demonstrate its awesomeness in the `examples page`_!
+
+
+Changelog
+^^^^^^^^^
+
+If your change is noteworthy, there needs to be a changelog entry, so our users can learn about it!
+
+To avoid merge conflicts, we use the towncrier_ package to manage our changelog.
+``towncrier`` uses independent files for each pull request -- so called *news fragments* -- instead of one monolithic changelog file.
+On release those news fragments are compiled into our ``CHANGELOG.rst``.
+
+You don't need to install ``towncrier`` yourself, you just have to abide to a few simple rules:
+
+- For each pull request, add a new file into ``changelog.d`` with a filename adhering to the ``pr#.(change|deprecation|breaking).rst`` schema:
+ For example ``changelog.d/42.change.rst`` for a non-breaking change, that is proposed in pull request number 42.
+- As with other docs, please use `semantic newlines`_ within news fragments.
+- Wrap symbols like modules, functions, or classes into double backticks so they are rendered in a monospaced font.
+- If you mention functions or other callables, add parantheses at the end of their names: ``attr.func()`` or ``attr.Class.method()``.
+ This makes the changelog a lot more readable.
+- Prefer simple past or constructions with "now".
+ For example:
+
+ + Added ``attr.validators.func()``.
+ + ``attr.func()`` now doesn't crash the Large Hadron Collider anymore.
+- If you want to reference multiple issues, copy the news fragment to another filename.
+ ``towncrier`` will merge all news fragments with identical contents into one entry with multiple links to the respective pull requests.
+
+Example entries:
+
+ .. code-block:: rst
+
+ Added ``attr.validators.func()``.
+ The feature really *is* awesome.
+
+or:
+
+ .. code-block:: rst
+
+ ``attr.func()`` now doesn't crash the Large Hadron Collider anymore.
+ The bug really *was* nasty.
+
+----
+
+``tox -e changelog`` will render the current changelog to the terminal if you have any doubts.
+
+
+Local Development Environment
+-----------------------------
+
+You can (and should) run our test suite using tox_.
+However you’ll probably want a more traditional environment too.
+We highly recommend to develop using the latest Python 3 release because ``attrs`` tries to take advantage of modern features whenever possible.
+
+First create a `virtual environment <https://virtualenv.pypa.io/>`_.
+It’s out of scope for this document to list all the ways to manage virtual environments in Python but if you don’t have already a pet way, take some time to look at tools like `pew <https://github.com/berdario/pew>`_, `virtualfish <http://virtualfish.readthedocs.io/>`_, and `virtualenvwrapper <http://virtualenvwrapper.readthedocs.io/>`_.
+
+Next get an up to date checkout of the ``attrs`` repository:
+
+.. code-block:: bash
+
+ git checkout git@github.com:python-attrs/attrs.git
+
+Change into the newly created directory and **after activating your virtual environment** install an editable version of ``attrs``:
+
+.. code-block:: bash
+
+ cd attrs
+ pip install -e .
+
+If you run the virtual environment’s Python and try to ``import attr`` it should work!
+
+To run the test suite, you'll need our development dependencies which can be installed using
+
+.. code-block:: bash
+
+ pip install -r dev-requirements.txt
+
+At this point
+
+.. code-block:: bash
+
+ python -m pytest
+
+should work and pass!
+
+
+Governance
+----------
+
+``attrs`` is maintained by `team of volunteers`_ that is always open for new members that share our vision of a fast, lean, and magic-free library that empowers programmers to write better code with less effort.
+If you'd like to join, just get a pull request merged and ask to be added in the very same pull request!
+
+**The simple rule is that everyone is welcome to review/merge pull requests of others but nobody is allowed to merge their own code.**
+
+`Hynek Schlawack`_ acts reluctantly as the BDFL_ and has the final say over design decisions.
+
+
+****
+
+Please note that this project is released with a Contributor `Code of Conduct`_.
+By participating in this project you agree to abide by its terms.
+Please report any harm to `Hynek Schlawack`_ in any way you find appropriate.
+
+Thank you for considering contributing to ``attrs``!
+
+
+.. _`Hynek Schlawack`: https://hynek.me/about/
+.. _`PEP 8`: https://www.python.org/dev/peps/pep-0008/
+.. _`PEP 257`: https://www.python.org/dev/peps/pep-0257/
+.. _`good test docstrings`: https://jml.io/pages/test-docstrings.html
+.. _`Code of Conduct`: https://github.com/python-attrs/attrs/blob/master/CODE_OF_CONDUCT.rst
+.. _changelog: https://github.com/python-attrs/attrs/blob/master/CHANGELOG.rst
+.. _`backward compatibility`: http://www.attrs.org/en/latest/backward-compatibility.html
+.. _tox: https://tox.readthedocs.io/
+.. _pyenv: https://github.com/pyenv/pyenv
+.. _reStructuredText: http://www.sphinx-doc.org/en/stable/rest.html
+.. _semantic newlines: http://rhodesmill.org/brandon/2012/one-sentence-per-line/
+.. _examples page: https://github.com/python-attrs/attrs/blob/master/docs/examples.rst
+.. _Hypothesis: https://hypothesis.readthedocs.io/
+.. _CI: https://travis-ci.org/python-attrs/attrs/
+.. _`team of volunteers`: https://github.com/python-attrs
+.. _BDFL: https://en.wikipedia.org/wiki/Benevolent_dictator_for_life
+.. _towncrier: https://pypi.org/project/towncrier
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/LICENSE b/tests/wpt/web-platform-tests/tools/third_party/attrs/LICENSE
new file mode 100644
index 00000000000..7ae3df93097
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Hynek Schlawack
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/MANIFEST.in b/tests/wpt/web-platform-tests/tools/third_party/attrs/MANIFEST.in
new file mode 100644
index 00000000000..03a948ef2c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/MANIFEST.in
@@ -0,0 +1,19 @@
+include LICENSE *.rst *.toml
+
+# Don't package GitHub-specific files.
+exclude *.md .travis.yml
+
+# Tests
+include tox.ini .coveragerc conftest.py dev-requirements.txt docs-requirements.txt
+recursive-include tests *.py
+
+# Documentation
+include docs/Makefile docs/docutils.conf
+recursive-include docs *.png
+recursive-include docs *.svg
+recursive-include docs *.py
+recursive-include docs *.rst
+prune docs/_build
+
+# Changelog news fragments -- is empty on releases.
+prune changelog.d
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/PULL_REQUEST_TEMPLATE.md b/tests/wpt/web-platform-tests/tools/third_party/attrs/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 00000000000..34c468e6ae5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,12 @@
+# Pull Request Check List
+
+This is just a reminder about the most common mistakes. Please make sure that you tick all *appropriate* boxes. But please read our [contribution guide](http://www.attrs.org/en/latest/contributing.html) at least once, it will save you unnecessary review cycles!
+
+- [ ] Added **tests** for changed code.
+- [ ] New features have been added to our [Hypothesis testing strategy](https://github.com/python-attrs/attrs/blob/master/tests/utils.py).
+- [ ] Updated **documentation** for changed code.
+- [ ] Documentation in `.rst` files is written using [semantic newlines](http://rhodesmill.org/brandon/2012/one-sentence-per-line/).
+- [ ] Changed/added classes/methods/functions have appropriate `versionadded`, `versionchanged`, or `deprecated` [directives](http://www.sphinx-doc.org/en/stable/markup/para.html#directive-versionadded).
+- [ ] Changes (and possible deprecations) have news fragments in [`changelog.d`](https://github.com/python-attrs/attrs/blob/master/changelog.d).
+
+If you have *any* questions to *any* of the points above, just **submit and ask**! This checklist is here to *help* you, not to deter you from contributing!
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/README.rst b/tests/wpt/web-platform-tests/tools/third_party/attrs/README.rst
new file mode 100644
index 00000000000..84d6aa76531
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/README.rst
@@ -0,0 +1,129 @@
+.. image:: http://www.attrs.org/en/latest/_static/attrs_logo.png
+ :alt: attrs Logo
+
+======================================
+``attrs``: Classes Without Boilerplate
+======================================
+
+.. image:: https://readthedocs.org/projects/attrs/badge/?version=stable
+ :target: http://www.attrs.org/en/stable/?badge=stable
+ :alt: Documentation Status
+
+.. image:: https://travis-ci.org/python-attrs/attrs.svg?branch=master
+ :target: https://travis-ci.org/python-attrs/attrs
+ :alt: CI Status
+
+.. image:: https://codecov.io/github/python-attrs/attrs/branch/master/graph/badge.svg
+ :target: https://codecov.io/github/python-attrs/attrs
+ :alt: Test Coverage
+
+.. teaser-begin
+
+``attrs`` is the Python package that will bring back the **joy** of **writing classes** by relieving you from the drudgery of implementing object protocols (aka `dunder <https://nedbatchelder.com/blog/200605/dunder.html>`_ methods).
+
+Its main goal is to help you to write **concise** and **correct** software without slowing down your code.
+
+.. -spiel-end-
+
+For that, it gives you a class decorator and a way to declaratively define the attributes on that class:
+
+.. -code-begin-
+
+.. code-block:: pycon
+
+ >>> import attr
+
+ >>> @attr.s
+ ... class SomeClass(object):
+ ... a_number = attr.ib(default=42)
+ ... list_of_numbers = attr.ib(default=attr.Factory(list))
+ ...
+ ... def hard_math(self, another_number):
+ ... return self.a_number + sum(self.list_of_numbers) * another_number
+
+
+ >>> sc = SomeClass(1, [1, 2, 3])
+ >>> sc
+ SomeClass(a_number=1, list_of_numbers=[1, 2, 3])
+
+ >>> sc.hard_math(3)
+ 19
+ >>> sc == SomeClass(1, [1, 2, 3])
+ True
+ >>> sc != SomeClass(2, [3, 2, 1])
+ True
+
+ >>> attr.asdict(sc)
+ {'a_number': 1, 'list_of_numbers': [1, 2, 3]}
+
+ >>> SomeClass()
+ SomeClass(a_number=42, list_of_numbers=[])
+
+ >>> C = attr.make_class("C", ["a", "b"])
+ >>> C("foo", "bar")
+ C(a='foo', b='bar')
+
+
+After *declaring* your attributes ``attrs`` gives you:
+
+- a concise and explicit overview of the class's attributes,
+- a nice human-readable ``__repr__``,
+- a complete set of comparison methods,
+- an initializer,
+- and much more,
+
+*without* writing dull boilerplate code again and again and *without* runtime performance penalties.
+
+This gives you the power to use actual classes with actual types in your code instead of confusing ``tuple``\ s or `confusingly behaving <http://www.attrs.org/en/stable/why.html#namedtuples>`_ ``namedtuple``\ s.
+Which in turn encourages you to write *small classes* that do `one thing well <https://www.destroyallsoftware.com/talks/boundaries>`_.
+Never again violate the `single responsibility principle <https://en.wikipedia.org/wiki/Single_responsibility_principle>`_ just because implementing ``__init__`` et al is a painful drag.
+
+
+.. -testimonials-
+
+Testimonials
+============
+
+**Amber Hawkie Brown**, Twisted Release Manager and Computer Owl:
+
+ Writing a fully-functional class using attrs takes me less time than writing this testimonial.
+
+
+**Glyph Lefkowitz**, creator of `Twisted <https://twistedmatrix.com/>`_, `Automat <https://pypi.python.org/pypi/Automat>`_, and other open source software, in `The One Python Library Everyone Needs <https://glyph.twistedmatrix.com/2016/08/attrs.html>`_:
+
+ I’m looking forward to is being able to program in Python-with-attrs everywhere.
+ It exerts a subtle, but positive, design influence in all the codebases I’ve see it used in.
+
+
+**Kenneth Reitz**, author of `requests <http://www.python-requests.org/>`_, Python Overlord at Heroku, `on paper no less <https://twitter.com/hynek/status/866817877650751488>`_:
+
+ attrs—classes for humans. I like it.
+
+
+**Łukasz Langa**, prolific CPython core developer and Production Engineer at Facebook:
+
+ I'm increasingly digging your attr.ocity. Good job!
+
+
+.. -end-
+
+.. -project-information-
+
+Getting Help
+============
+
+Please use the ``python-attrs`` tag on `StackOverflow <https://stackoverflow.com/questions/tagged/python-attrs>`_ to get help.
+
+Answering questions of your fellow developers is also great way to help the project!
+
+
+Project Information
+===================
+
+``attrs`` is released under the `MIT <https://choosealicense.com/licenses/mit/>`_ license,
+its documentation lives at `Read the Docs <http://www.attrs.org/>`_,
+the code on `GitHub <https://github.com/python-attrs/attrs>`_,
+and the latest release on `PyPI <https://pypi.org/project/attrs/>`_.
+It’s rigorously tested on Python 2.7, 3.4+, and PyPy.
+
+If you'd like to contribute you're most welcome and we've written `a little guide <http://www.attrs.org/en/latest/contributing.html>`_ to get you started!
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/nonpython/__init__.py b/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/.gitignore
index e69de29bb2d..e69de29bb2d 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/nonpython/__init__.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/.gitignore
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/261.change.rst b/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/261.change.rst
new file mode 100644
index 00000000000..6867f66dd23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/261.change.rst
@@ -0,0 +1,4 @@
+Generated ``__hash__`` methods now hash the class type along with the attribute values.
+Until now the hashes of two classes with the same values were identical which was a bug.
+
+The generated method is also *much* faster now.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/284.change.rst b/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/284.change.rst
new file mode 100644
index 00000000000..266599daabe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/284.change.rst
@@ -0,0 +1,2 @@
+``ctypes`` is optional now however if it's missing, a bare ``super()`` will not work in slots classes.
+This should only happen in special environments like Google App Engine.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/285.change.rst b/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/285.change.rst
new file mode 100644
index 00000000000..c3fbb797d4f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/285.change.rst
@@ -0,0 +1,2 @@
+The attribute redefinition feature introduced in 17.3.0 now takes into account if an attribute is redefined via multiple inheritance.
+In that case, the definition that is closer to the base of the class hierarchy wins.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/286.change.rst b/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/286.change.rst
new file mode 100644
index 00000000000..266599daabe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/286.change.rst
@@ -0,0 +1,2 @@
+``ctypes`` is optional now however if it's missing, a bare ``super()`` will not work in slots classes.
+This should only happen in special environments like Google App Engine.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/287.change.rst b/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/287.change.rst
new file mode 100644
index 00000000000..c3fbb797d4f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/287.change.rst
@@ -0,0 +1,2 @@
+The attribute redefinition feature introduced in 17.3.0 now takes into account if an attribute is redefined via multiple inheritance.
+In that case, the definition that is closer to the base of the class hierarchy wins.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/291.change.rst b/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/291.change.rst
new file mode 100644
index 00000000000..0d5438f1dbe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/291.change.rst
@@ -0,0 +1 @@
+Subclasses of ``auto_attribs=True`` can be empty now.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/292.change.rst b/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/292.change.rst
new file mode 100644
index 00000000000..0d5438f1dbe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/292.change.rst
@@ -0,0 +1 @@
+Subclasses of ``auto_attribs=True`` can be empty now.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/295.change.rst b/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/295.change.rst
new file mode 100644
index 00000000000..6867f66dd23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/295.change.rst
@@ -0,0 +1,4 @@
+Generated ``__hash__`` methods now hash the class type along with the attribute values.
+Until now the hashes of two classes with the same values were identical which was a bug.
+
+The generated method is also *much* faster now.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/296.change.rst b/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/296.change.rst
new file mode 100644
index 00000000000..6867f66dd23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/changelog.d/296.change.rst
@@ -0,0 +1,4 @@
+Generated ``__hash__`` methods now hash the class type along with the attribute values.
+Until now the hashes of two classes with the same values were identical which was a bug.
+
+The generated method is also *much* faster now.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/conftest.py b/tests/wpt/web-platform-tests/tools/third_party/attrs/conftest.py
new file mode 100644
index 00000000000..ed4d6525b45
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/conftest.py
@@ -0,0 +1,28 @@
+from __future__ import absolute_import, division, print_function
+
+import sys
+
+import pytest
+
+
+@pytest.fixture(scope="session")
+def C():
+ """
+ Return a simple but fully featured attrs class with an x and a y attribute.
+ """
+ import attr
+
+ @attr.s
+ class C(object):
+ x = attr.ib()
+ y = attr.ib()
+
+ return C
+
+
+collect_ignore = []
+if sys.version_info[:2] < (3, 6):
+ collect_ignore.extend([
+ "tests/test_annotations.py",
+ "tests/test_init_subclass.py",
+ ])
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/dev-requirements.txt b/tests/wpt/web-platform-tests/tools/third_party/attrs/dev-requirements.txt
new file mode 100644
index 00000000000..bbd6b9201e0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/dev-requirements.txt
@@ -0,0 +1,6 @@
+coverage
+hypothesis
+pympler
+pytest
+six
+zope.interface
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/docs-requirements.txt b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs-requirements.txt
new file mode 100644
index 00000000000..c473e1e4324
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs-requirements.txt
@@ -0,0 +1,3 @@
+-e .
+sphinx
+zope.interface
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/Makefile b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/Makefile
new file mode 100644
index 00000000000..3143891daf8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/Makefile
@@ -0,0 +1,177 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = _build
+
+# User-friendly check for sphinx-build
+ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
+$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
+endif
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " singlehtml to make a single large HTML file"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " devhelp to make HTML files and a Devhelp project"
+ @echo " epub to make an epub"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
+ @echo " text to make text files"
+ @echo " man to make manual pages"
+ @echo " texinfo to make Texinfo files"
+ @echo " info to make Texinfo files and run them through makeinfo"
+ @echo " gettext to make PO message catalogs"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " xml to make Docutils-native XML files"
+ @echo " pseudoxml to make pseudoxml-XML files for display purposes"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+ rm -rf $(BUILDDIR)/*
+
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/attrs.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/attrs.qhc"
+
+devhelp:
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+ @echo
+ @echo "Build finished."
+ @echo "To view the help file:"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/attrs"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/attrs"
+ @echo "# devhelp"
+
+epub:
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
+ "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+latexpdfja:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through platex and dvipdfmx..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+ @echo
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+ @echo
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo
+ @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+ @echo "Run \`make' in that directory to run these through makeinfo" \
+ "(use \`make info' here to do that automatically)."
+
+info:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo "Running Texinfo files through makeinfo..."
+ make -C $(BUILDDIR)/texinfo info
+ @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+ $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+ @echo
+ @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
+
+xml:
+ $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
+ @echo
+ @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
+
+pseudoxml:
+ $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
+ @echo
+ @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/_static/attrs_logo.png b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/_static/attrs_logo.png
new file mode 100644
index 00000000000..11b6e6fe3f9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/_static/attrs_logo.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/_static/attrs_logo.svg b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/_static/attrs_logo.svg
new file mode 100644
index 00000000000..1bb3e4b7273
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/_static/attrs_logo.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 142 118" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;"><rect id="ArtBoard1" x="0" y="0" width="141.578" height="117.638" style="fill:none;"/><path d="M32.55,82.516c-0.191,4.027 -0.832,8.503 -1.793,13.238c-1.023,4.793 -2.301,9.269 -3.836,13.234c-3.324,1.215 -7.035,1.922 -10.808,1.922c-3.77,0 -7.161,-0.707 -9.973,-1.922c0,0 -0.387,-3.133 0.637,-7.863c1.023,-4.797 2.687,-7.93 2.687,-7.93c3.324,-1.215 7.098,-1.918 10.871,-1.918c1.856,0 3.645,0.192 5.309,0.512c0.445,-2.688 0.832,-5.309 0.832,-5.309c0,0 -2.496,-0.703 -4.988,-0.703c-4.864,0 -9.465,1.086 -11.45,1.664c0.579,-1.726 1.09,-3.328 1.727,-4.925c3.328,-1.153 7.035,-1.856 10.809,-1.856c3.773,0 7.16,0.703 9.976,1.856Zm-15.348,23.277c2.75,0 5.309,-0.703 5.309,-0.703c0,0 1.34,-4.668 2.109,-7.996c-1.152,-0.317 -3.132,-0.704 -5.371,-0.704c-2.496,0 -5.437,0.704 -5.437,0.704c0,0 -0.703,1.664 -1.215,4.031c-0.512,2.301 -0.445,3.965 -0.445,3.965c0,0 2.554,0.703 5.05,0.703Zm32.676,0c2.813,0 5.629,-0.512 7.867,-1.024c-0.769,1.981 -1.664,3.774 -2.621,5.5c-2.047,0.383 -4.16,0.641 -6.332,0.641c-3.773,0 -7.097,-0.707 -9.914,-1.922c0.129,-3.965 0.77,-8.441 1.793,-13.234l1.918,-9.082l-6.461,0c0.707,-1.789 1.473,-3.453 2.496,-5.051l5.051,0l1.344,-6.332c1.918,-0.703 3.965,-1.215 6.074,-1.535l-1.66,7.867l11.125,0c-0.703,1.789 -1.535,3.516 -2.492,5.051l-9.723,0l-1.918,9.082c-0.703,3.262 -1.469,9.336 -1.469,9.336c0,0 2.493,0.703 4.922,0.703Zm27.496,0c2.817,0 5.629,-0.512 7.867,-1.024c-0.765,1.981 -1.664,3.774 -2.621,5.5c-2.046,0.383 -4.156,0.641 -6.332,0.641c-3.773,0 -7.097,-0.707 -9.91,-1.922c0.125,-3.965 0.766,-8.441 1.789,-13.234l1.918,-9.082l-6.457,0c0.703,-1.789 1.469,-3.453 2.492,-5.051l5.055,0l1.34,-6.332c1.918,-0.703 3.965,-1.215 6.074,-1.535l-1.66,7.867l11.125,0c-0.703,1.789 -1.535,3.516 -2.492,5.051l-9.719,0l-1.922,9.082c-0.703,3.262 -1.469,9.336 -1.469,9.336c0,0 2.493,0.703 4.922,0.703Zm28.137,-25.133c1.984,0 3.84,0.191 5.629,0.578c-0.703,1.727 -1.469,3.324 -2.367,4.86c-1.406,-0.192 -2.813,-0.321 -4.348,-0.321c-2.492,0 -5.242,0.703 -5.242,0.703c0,0 -1.856,6.075 -2.496,9.274l-3.067,14.515l-5.82,0l3.07,-14.515c0.957,-4.735 2.301,-9.211 3.836,-13.238c3.325,-1.153 7.035,-1.856 10.805,-1.856Zm28.715,13.621c0,0 0.445,2.621 -0.574,7.356c-1.024,4.796 -2.559,7.351 -2.559,7.351c-3.328,1.215 -7.035,1.922 -10.809,1.922c-3.773,0 -7.16,-0.707 -9.976,-1.922c0,0 -0.383,-1.726 0.129,-4.988c1.406,0.387 6.457,1.793 10.933,1.793c2.497,0 5.375,-0.703 5.375,-0.703c0,0 0.704,-1.153 1.149,-3.453c0.512,-2.305 0.32,-3.454 0.32,-3.454c0,0 -2.558,-0.703 -5.051,-0.703c-3.902,0 -7.226,-0.64 -10.039,-1.855c0,0 -0.386,-2.879 0.383,-6.524c0.766,-3.707 2.43,-6.585 2.43,-6.585c3.324,-1.153 7.035,-1.856 10.808,-1.856c3.77,0 7.161,0.703 9.973,1.856c0,0.128 0.387,2.046 -0.062,5.179c-1.536,-0.449 -7.165,-1.918 -11,-1.918c-2.493,0 -5.372,0.703 -5.372,0.703c0,0 -0.64,1.024 -0.957,2.621c-0.32,1.598 -0.195,2.622 -0.195,2.622c0,0 2.496,0.64 5.117,0.703c3.774,0 7.164,0.64 9.977,1.855Z" style="fill:#222;fill-rule:nonzero;"/><path d="M79.12,44.539c0,-0.914 -0.066,-1.805 -0.195,-2.68l2.832,-1.687l-0.058,-0.266c-0.434,-2.004 -1.145,-3.902 -2.086,-5.66l-0.137,-0.254l-3.156,0.723c-0.766,-1.235 -1.676,-2.375 -2.703,-3.395l1.285,-3.012l-0.2,-0.175c-1.5,-1.293 -3.168,-2.391 -4.976,-3.246l-0.254,-0.118l-2.137,2.442c-1.386,-0.551 -2.855,-0.934 -4.386,-1.137l-0.727,-3.176l-0.277,-0.015c-0.477,-0.035 -0.965,-0.059 -1.457,-0.059c-1.52,0 -3,0.16 -4.43,0.457l-0.277,0.051l-0.293,3.25c-1.465,0.41 -2.864,0.996 -4.164,1.73l-2.438,-2.132l-0.238,0.156c-1.672,1.09 -3.188,2.402 -4.496,3.894l-0.18,0.207l1.684,2.821c-0.86,1.125 -1.602,2.363 -2.188,3.675l-3.219,-0.289l-0.093,0.266c-0.707,1.863 -1.157,3.852 -1.313,5.918l-0.023,0.266l3.035,1.296c-0.004,0.047 -0.004,0.098 -0.004,0.149c0,1.289 0.137,2.555 0.387,3.766l-2.782,1.656l0.071,0.273c0.55,2.028 1.379,3.926 2.453,5.672l0.14,0.227l3.223,-0.731c0.703,0.973 1.496,1.883 2.371,2.703l-1.277,2.993l0.211,0.179c1.609,1.328 3.41,2.434 5.359,3.258l0.242,0.105l2.176,-2.48c1.059,0.367 2.176,0.641 3.313,0.809l0.726,3.187l0.281,0.02c0.563,0.047 1.149,0.078 1.743,0.078c1.554,0 3.07,-0.168 4.535,-0.481l0.273,-0.058l0.293,-3.254c1.113,-0.317 2.18,-0.738 3.203,-1.242l2.477,2.164l0.234,-0.137c1.813,-1.07 3.449,-2.391 4.875,-3.918l0.196,-0.203l-1.665,-2.789c0.774,-0.938 1.45,-1.965 2.028,-3.047l3.293,0.297l0.105,-0.25c0.821,-1.84 1.391,-3.836 1.672,-5.922l0.035,-0.285l-2.976,-1.27c0.031,-0.429 0.054,-0.871 0.054,-1.32Zm-12.921,0c0,3.156 -2.555,5.711 -5.711,5.715c-3.161,-0.004 -5.711,-2.559 -5.715,-5.715c0.004,-3.152 2.554,-5.703 5.715,-5.715c3.156,0.012 5.711,2.563 5.711,5.715Z" style="fill:#222;fill-rule:nonzero;"/><path d="M103.519,15.5l-0.067,-0.242l-2.253,-0.012c-0.317,-0.934 -0.747,-1.832 -1.258,-2.664l1.351,-1.844l-0.136,-0.191c-0.809,-1.121 -1.778,-2.133 -2.868,-3.004l-0.195,-0.156l-1.84,1.316c-0.832,-0.578 -1.75,-1.059 -2.722,-1.437l0.011,-2.266l-0.23,-0.074c-0.328,-0.098 -0.649,-0.192 -0.992,-0.274c-1.028,-0.242 -2.063,-0.367 -3.086,-0.402l-0.25,-0.004l-0.715,2.16c-1.028,0.047 -2.047,0.215 -3.024,0.496l-1.308,-1.84l-0.238,0.09c-1.317,0.469 -2.559,1.121 -3.692,1.934l-0.195,0.14l0.695,2.18c-0.742,0.617 -1.422,1.313 -2.016,2.09l-2.14,-0.711l-0.137,0.211c-0.773,1.156 -1.402,2.434 -1.844,3.816l-0.066,0.223l1.852,1.363c-0.012,0.02 -0.016,0.043 -0.02,0.059c-0.207,0.867 -0.312,1.726 -0.34,2.578l-2.156,0.684l0.012,0.246c0.054,1.468 0.308,2.902 0.761,4.261l0.075,0.227l2.308,0.012c0.313,0.75 0.692,1.465 1.137,2.148l-1.348,1.828l0.149,0.196c0.886,1.16 1.929,2.207 3.129,3.074l0.191,0.14l1.867,-1.335c0.641,0.402 1.328,0.75 2.047,1.039l-0.016,2.281l0.231,0.074c0.387,0.121 0.777,0.234 1.18,0.332c1.062,0.246 2.121,0.379 3.168,0.402l0.242,0.004l0.718,-2.164c0.782,-0.035 1.547,-0.144 2.297,-0.316l1.336,1.863l0.231,-0.074c1.398,-0.43 2.73,-1.074 3.945,-1.887l0.203,-0.137l-0.679,-2.16c0.648,-0.504 1.257,-1.066 1.804,-1.687l2.184,0.726l0.144,-0.191c0.86,-1.117 1.567,-2.387 2.09,-3.762l0.09,-0.238l-1.816,-1.336c0.086,-0.277 0.16,-0.559 0.23,-0.84c0.141,-0.613 0.238,-1.219 0.293,-1.82l2.191,-0.695l0,-0.239c0,-0.086 0.008,-0.172 0.008,-0.261c-0.004,-1.34 -0.183,-2.661 -0.523,-3.93Zm-10.766,3.941c0,0.301 -0.031,0.602 -0.101,0.903c-0.43,1.8 -2.032,3.015 -3.805,3.015c-0.301,0 -0.598,-0.035 -0.898,-0.109c-1.805,-0.414 -3.012,-2.024 -3.012,-3.797c0,-0.297 0.031,-0.594 0.097,-0.898c0.422,-1.801 2.032,-3.016 3.809,-3.016c0.289,0 0.594,0.031 0.898,0.105c1.793,0.418 3.012,2.032 3.012,3.797Z" style="fill:#222;fill-rule:nonzero;"/></svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/api.rst b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/api.rst
new file mode 100644
index 00000000000..e2acb7400f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/api.rst
@@ -0,0 +1,428 @@
+.. _api:
+
+API Reference
+=============
+
+.. currentmodule:: attr
+
+``attrs`` works by decorating a class using :func:`attr.s` and then optionally defining attributes on the class using :func:`attr.ib`.
+
+.. note::
+
+ When this documentation speaks about "``attrs`` attributes" it means those attributes that are defined using :func:`attr.ib` in the class body.
+
+What follows is the API explanation, if you'd like a more hands-on introduction, have a look at :doc:`examples`.
+
+
+
+Core
+----
+
+.. autofunction:: attr.s(these=None, repr_ns=None, repr=True, cmp=True, hash=None, init=True, slots=False, frozen=False, str=False)
+
+ .. note::
+
+ ``attrs`` also comes with a serious business alias ``attr.attrs``.
+
+ For example:
+
+ .. doctest::
+
+ >>> import attr
+ >>> @attr.s
+ ... class C(object):
+ ... _private = attr.ib()
+ >>> C(private=42)
+ C(_private=42)
+ >>> class D(object):
+ ... def __init__(self, x):
+ ... self.x = x
+ >>> D(1)
+ <D object at ...>
+ >>> D = attr.s(these={"x": attr.ib()}, init=False)(D)
+ >>> D(1)
+ D(x=1)
+
+
+.. autofunction:: attr.ib
+
+ .. note::
+
+ ``attrs`` also comes with a serious business alias ``attr.attrib``.
+
+ The object returned by :func:`attr.ib` also allows for setting the default and the validator using decorators:
+
+ .. doctest::
+
+ >>> @attr.s
+ ... class C(object):
+ ... x = attr.ib()
+ ... y = attr.ib()
+ ... @x.validator
+ ... def name_can_be_anything(self, attribute, value):
+ ... if value < 0:
+ ... raise ValueError("x must be positive")
+ ... @y.default
+ ... def name_does_not_matter(self):
+ ... return self.x + 1
+ >>> C(1)
+ C(x=1, y=2)
+ >>> C(-1)
+ Traceback (most recent call last):
+ ...
+ ValueError: x must be positive
+
+.. autoclass:: attr.Attribute
+
+ Instances of this class are frequently used for introspection purposes like:
+
+ - :func:`fields` returns a tuple of them.
+ - Validators get them passed as the first argument.
+
+ .. warning::
+
+ You should never instantiate this class yourself!
+
+ .. doctest::
+
+ >>> import attr
+ >>> @attr.s
+ ... class C(object):
+ ... x = attr.ib()
+ >>> attr.fields(C).x
+ Attribute(name='x', default=NOTHING, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}), type=None)
+
+
+.. autofunction:: attr.make_class
+
+ This is handy if you want to programmatically create classes.
+
+ For example:
+
+ .. doctest::
+
+ >>> C1 = attr.make_class("C1", ["x", "y"])
+ >>> C1(1, 2)
+ C1(x=1, y=2)
+ >>> C2 = attr.make_class("C2", {"x": attr.ib(default=42),
+ ... "y": attr.ib(default=attr.Factory(list))})
+ >>> C2()
+ C2(x=42, y=[])
+
+
+.. autoclass:: attr.Factory
+
+ For example:
+
+ .. doctest::
+
+ >>> @attr.s
+ ... class C(object):
+ ... x = attr.ib(default=attr.Factory(list))
+ ... y = attr.ib(default=attr.Factory(
+ ... lambda self: set(self.x),
+ ... takes_self=True)
+ ... )
+ >>> C()
+ C(x=[], y=set())
+ >>> C([1, 2, 3])
+ C(x=[1, 2, 3], y={1, 2, 3})
+
+
+.. autoexception:: attr.exceptions.FrozenInstanceError
+.. autoexception:: attr.exceptions.AttrsAttributeNotFoundError
+.. autoexception:: attr.exceptions.NotAnAttrsClassError
+.. autoexception:: attr.exceptions.DefaultAlreadySetError
+.. autoexception:: attr.exceptions.UnannotatedAttributeError
+
+ For example::
+
+ @attr.s(auto_attribs=True)
+ class C:
+ x: int
+ y = attr.ib()
+
+
+Influencing Initialization
+++++++++++++++++++++++++++
+
+Generally speaking, it's best to keep logic out of your ``__init__``.
+The moment you need a finer control over how your class is instantiated, it's usually best to use a classmethod factory or to apply the `builder pattern <https://en.wikipedia.org/wiki/Builder_pattern>`_.
+
+However, sometimes you need to do that one quick thing after your class is initialized.
+And for that ``attrs`` offers the ``__attrs_post_init__`` hook that is automatically detected and run after ``attrs`` is done initializing your instance:
+
+.. doctest::
+
+ >>> @attr.s
+ ... class C(object):
+ ... x = attr.ib()
+ ... y = attr.ib(init=False)
+ ... def __attrs_post_init__(self):
+ ... self.y = self.x + 1
+ >>> C(1)
+ C(x=1, y=2)
+
+Please note that you can't directly set attributes on frozen classes:
+
+.. doctest::
+
+ >>> @attr.s(frozen=True)
+ ... class FrozenBroken(object):
+ ... x = attr.ib()
+ ... y = attr.ib(init=False)
+ ... def __attrs_post_init__(self):
+ ... self.y = self.x + 1
+ >>> FrozenBroken(1)
+ Traceback (most recent call last):
+ ...
+ attr.exceptions.FrozenInstanceError: can't set attribute
+
+If you need to set attributes on a frozen class, you'll have to resort to the :ref:`same trick <how-frozen>` as ``attrs`` and use :meth:`object.__setattr__`:
+
+.. doctest::
+
+ >>> @attr.s(frozen=True)
+ ... class Frozen(object):
+ ... x = attr.ib()
+ ... y = attr.ib(init=False)
+ ... def __attrs_post_init__(self):
+ ... object.__setattr__(self, "y", self.x + 1)
+ >>> Frozen(1)
+ Frozen(x=1, y=2)
+
+
+.. _helpers:
+
+Helpers
+-------
+
+``attrs`` comes with a bunch of helper methods that make working with it easier:
+
+.. autofunction:: attr.fields
+
+ For example:
+
+ .. doctest::
+
+ >>> @attr.s
+ ... class C(object):
+ ... x = attr.ib()
+ ... y = attr.ib()
+ >>> attr.fields(C)
+ (Attribute(name='x', default=NOTHING, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}), type=None), Attribute(name='y', default=NOTHING, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}), type=None))
+ >>> attr.fields(C)[1]
+ Attribute(name='y', default=NOTHING, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}), type=None)
+ >>> attr.fields(C).y is attr.fields(C)[1]
+ True
+
+
+.. autofunction:: attr.has
+
+ For example:
+
+ .. doctest::
+
+ >>> @attr.s
+ ... class C(object):
+ ... pass
+ >>> attr.has(C)
+ True
+ >>> attr.has(object)
+ False
+
+
+.. autofunction:: attr.asdict
+
+ For example:
+
+ .. doctest::
+
+ >>> @attr.s
+ ... class C(object):
+ ... x = attr.ib()
+ ... y = attr.ib()
+ >>> attr.asdict(C(1, C(2, 3)))
+ {'x': 1, 'y': {'x': 2, 'y': 3}}
+
+
+.. autofunction:: attr.astuple
+
+ For example:
+
+ .. doctest::
+
+ >>> @attr.s
+ ... class C(object):
+ ... x = attr.ib()
+ ... y = attr.ib()
+ >>> attr.astuple(C(1,2))
+ (1, 2)
+
+``attrs`` includes some handy helpers for filtering:
+
+.. autofunction:: attr.filters.include
+
+.. autofunction:: attr.filters.exclude
+
+See :ref:`asdict` for examples.
+
+.. autofunction:: attr.evolve
+
+ For example:
+
+ .. doctest::
+
+ >>> @attr.s
+ ... class C(object):
+ ... x = attr.ib()
+ ... y = attr.ib()
+ >>> i1 = C(1, 2)
+ >>> i1
+ C(x=1, y=2)
+ >>> i2 = attr.evolve(i1, y=3)
+ >>> i2
+ C(x=1, y=3)
+ >>> i1 == i2
+ False
+
+ ``evolve`` creates a new instance using ``__init__``.
+ This fact has several implications:
+
+ * private attributes should be specified without the leading underscore, just like in ``__init__``.
+ * attributes with ``init=False`` can't be set with ``evolve``.
+ * the usual ``__init__`` validators will validate the new values.
+
+.. autofunction:: validate
+
+ For example:
+
+ .. doctest::
+
+ >>> @attr.s
+ ... class C(object):
+ ... x = attr.ib(validator=attr.validators.instance_of(int))
+ >>> i = C(1)
+ >>> i.x = "1"
+ >>> attr.validate(i)
+ Traceback (most recent call last):
+ ...
+ TypeError: ("'x' must be <type 'int'> (got '1' that is a <type 'str'>).", Attribute(name='x', default=NOTHING, validator=<instance_of validator for type <type 'int'>>, repr=True, cmp=True, hash=None, init=True, type=None), <type 'int'>, '1')
+
+
+Validators can be globally disabled if you want to run them only in development and tests but not in production because you fear their performance impact:
+
+.. autofunction:: set_run_validators
+
+.. autofunction:: get_run_validators
+
+
+.. _api_validators:
+
+Validators
+----------
+
+``attrs`` comes with some common validators in the ``attrs.validators`` module:
+
+
+.. autofunction:: attr.validators.instance_of
+
+
+ For example:
+
+ .. doctest::
+
+ >>> @attr.s
+ ... class C(object):
+ ... x = attr.ib(validator=attr.validators.instance_of(int))
+ >>> C(42)
+ C(x=42)
+ >>> C("42")
+ Traceback (most recent call last):
+ ...
+ TypeError: ("'x' must be <type 'int'> (got '42' that is a <type 'str'>).", Attribute(name='x', default=NOTHING, validator=<instance_of validator for type <type 'int'>>, type=None), <type 'int'>, '42')
+ >>> C(None)
+ Traceback (most recent call last):
+ ...
+ TypeError: ("'x' must be <type 'int'> (got None that is a <type 'NoneType'>).", Attribute(name='x', default=NOTHING, validator=<instance_of validator for type <type 'int'>>, repr=True, cmp=True, hash=None, init=True, type=None), <type 'int'>, None)
+
+.. autofunction:: attr.validators.in_
+
+ For example:
+
+ .. doctest::
+
+ >>> import enum
+ >>> class State(enum.Enum):
+ ... ON = "on"
+ ... OFF = "off"
+ >>> @attr.s
+ ... class C(object):
+ ... state = attr.ib(validator=attr.validators.in_(State))
+ ... val = attr.ib(validator=attr.validators.in_([1, 2, 3]))
+ >>> C(State.ON, 1)
+ C(state=<State.ON: 'on'>, val=1)
+ >>> C("on", 1)
+ Traceback (most recent call last):
+ ...
+ ValueError: 'state' must be in <enum 'State'> (got 'on')
+ >>> C(State.ON, 4)
+ Traceback (most recent call last):
+ ...
+ ValueError: 'val' must be in [1, 2, 3] (got 4)
+
+.. autofunction:: attr.validators.provides
+
+.. autofunction:: attr.validators.and_
+
+ For convenience, it's also possible to pass a list to :func:`attr.ib`'s validator argument.
+
+ Thus the following two statements are equivalent::
+
+ x = attr.ib(validator=attr.validators.and_(v1, v2, v3))
+ x = attr.ib(validator=[v1, v2, v3])
+
+.. autofunction:: attr.validators.optional
+
+ For example:
+
+ .. doctest::
+
+ >>> @attr.s
+ ... class C(object):
+ ... x = attr.ib(validator=attr.validators.optional(attr.validators.instance_of(int)))
+ >>> C(42)
+ C(x=42)
+ >>> C("42")
+ Traceback (most recent call last):
+ ...
+ TypeError: ("'x' must be <type 'int'> (got '42' that is a <type 'str'>).", Attribute(name='x', default=NOTHING, validator=<instance_of validator for type <type 'int'>>, type=None), <type 'int'>, '42')
+ >>> C(None)
+ C(x=None)
+
+
+Converters
+----------
+
+.. autofunction:: attr.converters.optional
+
+ For example:
+
+ .. doctest::
+
+ >>> @attr.s
+ ... class C(object):
+ ... x = attr.ib(convert=attr.converters.optional(int))
+ >>> C(None)
+ C(x=None)
+ >>> C(42)
+ C(x=42)
+
+
+Deprecated APIs
+---------------
+
+The serious business aliases used to be called ``attr.attributes`` and ``attr.attr``.
+There are no plans to remove them but they shouldn't be used in new code.
+
+.. autofunction:: assoc
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/backward-compatibility.rst b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/backward-compatibility.rst
new file mode 100644
index 00000000000..52559f8d450
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/backward-compatibility.rst
@@ -0,0 +1,19 @@
+Backward Compatibility
+======================
+
+.. currentmodule:: attr
+
+``attrs`` has a very strong backward compatibility policy that is inspired by the policy of the `Twisted framework <https://twistedmatrix.com/trac/wiki/CompatibilityPolicy>`_.
+
+Put simply, you shouldn't ever be afraid to upgrade ``attrs`` if you're only using its public APIs.
+If there will ever be a need to break compatibility, it will be announced in the :doc:`changelog` and raise a ``DeprecationWarning`` for a year (if possible) before it's finally really broken.
+
+
+.. _exemption:
+
+.. warning::
+
+ The structure of the :class:`attr.Attribute` class is exempt from this rule.
+ It *will* change in the future, but since it should be considered read-only, that shouldn't matter.
+
+ However if you intend to build extensions on top of ``attrs`` you have to anticipate that.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/changelog.rst b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/changelog.rst
new file mode 100644
index 00000000000..565b0521d0c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/changelog.rst
@@ -0,0 +1 @@
+.. include:: ../CHANGELOG.rst
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/conf.py b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/conf.py
new file mode 100644
index 00000000000..1cdb07c1f79
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/conf.py
@@ -0,0 +1,155 @@
+# -*- coding: utf-8 -*-
+
+import codecs
+import os
+import re
+
+
+def read(*parts):
+ """
+ Build an absolute path from *parts* and and return the contents of the
+ resulting file. Assume UTF-8 encoding.
+ """
+ here = os.path.abspath(os.path.dirname(__file__))
+ with codecs.open(os.path.join(here, *parts), "rb", "utf-8") as f:
+ return f.read()
+
+
+def find_version(*file_paths):
+ """
+ Build a path from *file_paths* and search for a ``__version__``
+ string inside.
+ """
+ version_file = read(*file_paths)
+ version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]",
+ version_file, re.M)
+ if version_match:
+ return version_match.group(1)
+ raise RuntimeError("Unable to find version string.")
+
+
+# -- General configuration ------------------------------------------------
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+ 'sphinx.ext.autodoc',
+ 'sphinx.ext.doctest',
+ 'sphinx.ext.intersphinx',
+ 'sphinx.ext.todo',
+]
+
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'attrs'
+copyright = u'2015, Hynek Schlawack'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+release = find_version("../src/attr/__init__.py")
+version = release.rsplit(u".", 1)[0]
+# The full version, including alpha/beta/rc tags.
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+add_function_parentheses = True
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# -- Options for HTML output ----------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+
+html_theme = "alabaster"
+html_theme_options = {
+ "font_family": '"Avenir Next", Calibri, "PT Sans", sans-serif',
+ "head_font_family": '"Avenir Next", Calibri, "PT Sans", sans-serif',
+ "font_size": "18px",
+ "page_width": "980px",
+}
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+html_logo = "_static/attrs_logo.svg"
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+# html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If false, no module index is generated.
+html_domain_indices = True
+
+# If false, no index is generated.
+html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+html_show_sourcelink = False
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+# html_use_opensearch = ''
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'attrsdoc'
+
+# -- Options for manual page output ---------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ ('index', 'attrs', u'attrs Documentation',
+ [u'Hynek Schlawack'], 1)
+]
+
+
+# -- Options for Texinfo output -------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ ('index', 'attrs', u'attrs Documentation',
+ u'Hynek Schlawack', 'attrs', 'One line description of project.',
+ 'Miscellaneous'),
+]
+
+intersphinx_mapping = {
+ "https://docs.python.org/3": None,
+}
+
+# Allow non-local URIs so we can have images in CHANGELOG etc.
+suppress_warnings = ['image.nonlocal_uri']
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/contributing.rst b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/contributing.rst
new file mode 100644
index 00000000000..1d519c38151
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/contributing.rst
@@ -0,0 +1,5 @@
+.. _contributing:
+
+.. include:: ../CONTRIBUTING.rst
+
+.. include:: ../CODE_OF_CONDUCT.rst
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/docutils.conf b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/docutils.conf
new file mode 100644
index 00000000000..db8ca82c747
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/docutils.conf
@@ -0,0 +1,3 @@
+[parsers]
+[restructuredtext parser]
+smart_quotes=yes
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/examples.rst b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/examples.rst
new file mode 100644
index 00000000000..4432e8fcb53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/examples.rst
@@ -0,0 +1,705 @@
+.. _examples:
+
+``attrs`` by Example
+====================
+
+
+Basics
+------
+
+The simplest possible usage is:
+
+.. doctest::
+
+ >>> import attr
+ >>> @attr.s
+ ... class Empty(object):
+ ... pass
+ >>> Empty()
+ Empty()
+ >>> Empty() == Empty()
+ True
+ >>> Empty() is Empty()
+ False
+
+So in other words: ``attrs`` is useful even without actual attributes!
+
+But you'll usually want some data on your classes, so let's add some:
+
+.. doctest::
+
+ >>> @attr.s
+ ... class Coordinates(object):
+ ... x = attr.ib()
+ ... y = attr.ib()
+
+By default, all features are added, so you immediately have a fully functional data class with a nice ``repr`` string and comparison methods.
+
+.. doctest::
+
+ >>> c1 = Coordinates(1, 2)
+ >>> c1
+ Coordinates(x=1, y=2)
+ >>> c2 = Coordinates(x=2, y=1)
+ >>> c2
+ Coordinates(x=2, y=1)
+ >>> c1 == c2
+ False
+
+As shown, the generated ``__init__`` method allows for both positional and keyword arguments.
+
+If playful naming turns you off, ``attrs`` comes with serious business aliases:
+
+.. doctest::
+
+ >>> from attr import attrs, attrib
+ >>> @attrs
+ ... class SeriousCoordinates(object):
+ ... x = attrib()
+ ... y = attrib()
+ >>> SeriousCoordinates(1, 2)
+ SeriousCoordinates(x=1, y=2)
+ >>> attr.fields(Coordinates) == attr.fields(SeriousCoordinates)
+ True
+
+For private attributes, ``attrs`` will strip the leading underscores for keyword arguments:
+
+.. doctest::
+
+ >>> @attr.s
+ ... class C(object):
+ ... _x = attr.ib()
+ >>> C(x=1)
+ C(_x=1)
+
+If you want to initialize your private attributes yourself, you can do that too:
+
+.. doctest::
+
+ >>> @attr.s
+ ... class C(object):
+ ... _x = attr.ib(init=False, default=42)
+ >>> C()
+ C(_x=42)
+ >>> C(23)
+ Traceback (most recent call last):
+ ...
+ TypeError: __init__() takes exactly 1 argument (2 given)
+
+An additional way of defining attributes is supported too.
+This is useful in times when you want to enhance classes that are not yours (nice ``__repr__`` for Django models anyone?):
+
+.. doctest::
+
+ >>> class SomethingFromSomeoneElse(object):
+ ... def __init__(self, x):
+ ... self.x = x
+ >>> SomethingFromSomeoneElse = attr.s(
+ ... these={
+ ... "x": attr.ib()
+ ... }, init=False)(SomethingFromSomeoneElse)
+ >>> SomethingFromSomeoneElse(1)
+ SomethingFromSomeoneElse(x=1)
+
+
+`Subclassing is bad for you <https://www.youtube.com/watch?v=3MNVP9-hglc>`_, but ``attrs`` will still do what you'd hope for:
+
+.. doctest::
+
+ >>> @attr.s
+ ... class A(object):
+ ... a = attr.ib()
+ ... def get_a(self):
+ ... return self.a
+ >>> @attr.s
+ ... class B(object):
+ ... b = attr.ib()
+ >>> @attr.s
+ ... class C(B, A):
+ ... c = attr.ib()
+ >>> i = C(1, 2, 3)
+ >>> i
+ C(a=1, b=2, c=3)
+ >>> i == C(1, 2, 3)
+ True
+ >>> i.get_a()
+ 1
+
+The order of the attributes is defined by the `MRO <https://www.python.org/download/releases/2.3/mro/>`_.
+
+In Python 3, classes defined within other classes are `detected <https://www.python.org/dev/peps/pep-3155/>`_ and reflected in the ``__repr__``.
+In Python 2 though, it's impossible.
+Therefore ``@attr.s`` comes with the ``repr_ns`` option to set it manually:
+
+.. doctest::
+
+ >>> @attr.s
+ ... class C(object):
+ ... @attr.s(repr_ns="C")
+ ... class D(object):
+ ... pass
+ >>> C.D()
+ C.D()
+
+``repr_ns`` works on both Python 2 and 3.
+On Python 3 it overrides the implicit detection.
+
+
+.. _asdict:
+
+Converting to Collections Types
+-------------------------------
+
+When you have a class with data, it often is very convenient to transform that class into a :class:`dict` (for example if you want to serialize it to JSON):
+
+.. doctest::
+
+ >>> attr.asdict(Coordinates(x=1, y=2))
+ {'x': 1, 'y': 2}
+
+Some fields cannot or should not be transformed.
+For that, :func:`attr.asdict` offers a callback that decides whether an attribute should be included:
+
+.. doctest::
+
+ >>> @attr.s
+ ... class UserList(object):
+ ... users = attr.ib()
+ >>> @attr.s
+ ... class User(object):
+ ... email = attr.ib()
+ ... password = attr.ib()
+ >>> attr.asdict(UserList([User("jane@doe.invalid", "s33kred"),
+ ... User("joe@doe.invalid", "p4ssw0rd")]),
+ ... filter=lambda attr, value: attr.name != "password")
+ {'users': [{'email': 'jane@doe.invalid'}, {'email': 'joe@doe.invalid'}]}
+
+For the common case where you want to :func:`include <attr.filters.include>` or :func:`exclude <attr.filters.exclude>` certain types or attributes, ``attrs`` ships with a few helpers:
+
+.. doctest::
+
+ >>> @attr.s
+ ... class User(object):
+ ... login = attr.ib()
+ ... password = attr.ib()
+ ... id = attr.ib()
+ >>> attr.asdict(
+ ... User("jane", "s33kred", 42),
+ ... filter=attr.filters.exclude(attr.fields(User).password, int))
+ {'login': 'jane'}
+ >>> @attr.s
+ ... class C(object):
+ ... x = attr.ib()
+ ... y = attr.ib()
+ ... z = attr.ib()
+ >>> attr.asdict(C("foo", "2", 3),
+ ... filter=attr.filters.include(int, attr.fields(C).x))
+ {'x': 'foo', 'z': 3}
+
+Other times, all you want is a tuple and ``attrs`` won't let you down:
+
+.. doctest::
+
+ >>> import sqlite3
+ >>> import attr
+ >>> @attr.s
+ ... class Foo:
+ ... a = attr.ib()
+ ... b = attr.ib()
+ >>> foo = Foo(2, 3)
+ >>> with sqlite3.connect(":memory:") as conn:
+ ... c = conn.cursor()
+ ... c.execute("CREATE TABLE foo (x INTEGER PRIMARY KEY ASC, y)") #doctest: +ELLIPSIS
+ ... c.execute("INSERT INTO foo VALUES (?, ?)", attr.astuple(foo)) #doctest: +ELLIPSIS
+ ... foo2 = Foo(*c.execute("SELECT x, y FROM foo").fetchone())
+ <sqlite3.Cursor object at ...>
+ <sqlite3.Cursor object at ...>
+ >>> foo == foo2
+ True
+
+
+
+
+Defaults
+--------
+
+Sometimes you want to have default values for your initializer.
+And sometimes you even want mutable objects as default values (ever used accidentally ``def f(arg=[])``?).
+``attrs`` has you covered in both cases:
+
+.. doctest::
+
+ >>> import collections
+ >>> @attr.s
+ ... class Connection(object):
+ ... socket = attr.ib()
+ ... @classmethod
+ ... def connect(cls, db_string):
+ ... # ... connect somehow to db_string ...
+ ... return cls(socket=42)
+ >>> @attr.s
+ ... class ConnectionPool(object):
+ ... db_string = attr.ib()
+ ... pool = attr.ib(default=attr.Factory(collections.deque))
+ ... debug = attr.ib(default=False)
+ ... def get_connection(self):
+ ... try:
+ ... return self.pool.pop()
+ ... except IndexError:
+ ... if self.debug:
+ ... print("New connection!")
+ ... return Connection.connect(self.db_string)
+ ... def free_connection(self, conn):
+ ... if self.debug:
+ ... print("Connection returned!")
+ ... self.pool.appendleft(conn)
+ ...
+ >>> cp = ConnectionPool("postgres://localhost")
+ >>> cp
+ ConnectionPool(db_string='postgres://localhost', pool=deque([]), debug=False)
+ >>> conn = cp.get_connection()
+ >>> conn
+ Connection(socket=42)
+ >>> cp.free_connection(conn)
+ >>> cp
+ ConnectionPool(db_string='postgres://localhost', pool=deque([Connection(socket=42)]), debug=False)
+
+More information on why class methods for constructing objects are awesome can be found in this insightful `blog post <http://as.ynchrono.us/2014/12/asynchronous-object-initialization.html>`_.
+
+Default factories can also be set using a decorator.
+The method receives the partially initialized instance which enables you to base a default value on other attributes:
+
+.. doctest::
+
+ >>> @attr.s
+ ... class C(object):
+ ... x = attr.ib(default=1)
+ ... y = attr.ib()
+ ... @y.default
+ ... def name_does_not_matter(self):
+ ... return self.x + 1
+ >>> C()
+ C(x=1, y=2)
+
+
+.. _examples_validators:
+
+Validators
+----------
+
+Although your initializers should do as little as possible (ideally: just initialize your instance according to the arguments!), it can come in handy to do some kind of validation on the arguments.
+
+``attrs`` offers two ways to define validators for each attribute and it's up to you to choose which one suites better your style and project.
+
+
+Decorator
+~~~~~~~~~
+
+The more straightforward way is by using the attribute's ``validator`` method as a decorator.
+The method has to accept three arguments:
+
+#. the *instance* that's being validated (aka ``self``),
+#. the *attribute* that it's validating, and finally
+#. the *value* that is passed for it.
+
+If the value does not pass the validator's standards, it just raises an appropriate exception.
+
+.. doctest::
+
+ >>> @attr.s
+ ... class C(object):
+ ... x = attr.ib()
+ ... @x.validator
+ ... def check(self, attribute, value):
+ ... if value > 42:
+ ... raise ValueError("x must be smaller or equal to 42")
+ >>> C(42)
+ C(x=42)
+ >>> C(43)
+ Traceback (most recent call last):
+ ...
+ ValueError: x must be smaller or equal to 42
+
+
+Callables
+~~~~~~~~~
+
+If you want to re-use your validators, you should have a look at the ``validator`` argument to :func:`attr.ib()`.
+
+It takes either a callable or a list of callables (usually functions) and treats them as validators that receive the same arguments as with the decorator approach.
+
+Since the validators runs *after* the instance is initialized, you can refer to other attributes while validating:
+
+.. doctest::
+
+ >>> def x_smaller_than_y(instance, attribute, value):
+ ... if value >= instance.y:
+ ... raise ValueError("'x' has to be smaller than 'y'!")
+ >>> @attr.s
+ ... class C(object):
+ ... x = attr.ib(validator=[attr.validators.instance_of(int),
+ ... x_smaller_than_y])
+ ... y = attr.ib()
+ >>> C(x=3, y=4)
+ C(x=3, y=4)
+ >>> C(x=4, y=3)
+ Traceback (most recent call last):
+ ...
+ ValueError: 'x' has to be smaller than 'y'!
+
+This example also shows of some syntactic sugar for using the :func:`attr.validators.and_` validator: if you pass a list, all validators have to pass.
+
+``attrs`` won't intercept your changes to those attributes but you can always call :func:`attr.validate` on any instance to verify that it's still valid:
+
+.. doctest::
+
+ >>> i = C(4, 5)
+ >>> i.x = 5 # works, no magic here
+ >>> attr.validate(i)
+ Traceback (most recent call last):
+ ...
+ ValueError: 'x' has to be smaller than 'y'!
+
+``attrs`` ships with a bunch of validators, make sure to :ref:`check them out <api_validators>` before writing your own:
+
+.. doctest::
+
+ >>> @attr.s
+ ... class C(object):
+ ... x = attr.ib(validator=attr.validators.instance_of(int))
+ >>> C(42)
+ C(x=42)
+ >>> C("42")
+ Traceback (most recent call last):
+ ...
+ TypeError: ("'x' must be <type 'int'> (got '42' that is a <type 'str'>).", Attribute(name='x', default=NOTHING, factory=NOTHING, validator=<instance_of validator for type <type 'int'>>, type=None), <type 'int'>, '42')
+
+Of course you can mix and match the two approaches at your convenience:
+
+.. doctest::
+
+ >>> @attr.s
+ ... class C(object):
+ ... x = attr.ib(validator=attr.validators.instance_of(int))
+ ... @x.validator
+ ... def fits_byte(self, attribute, value):
+ ... if not 0 < value < 256:
+ ... raise ValueError("value out of bounds")
+ >>> C(128)
+ C(x=128)
+ >>> C("128")
+ Traceback (most recent call last):
+ ...
+ TypeError: ("'x' must be <class 'int'> (got '128' that is a <class 'str'>).", Attribute(name='x', default=NOTHING, validator=[<instance_of validator for type <class 'int'>>, <function fits_byte at 0x10fd7a0d0>], repr=True, cmp=True, hash=True, init=True, convert=None, metadata=mappingproxy({}), type=None), <class 'int'>, '128')
+ >>> C(256)
+ Traceback (most recent call last):
+ ...
+ ValueError: value out of bounds
+
+And finally you can disable validators globally:
+
+ >>> attr.set_run_validators(False)
+ >>> C("128")
+ C(x='128')
+ >>> attr.set_run_validators(True)
+ >>> C("128")
+ Traceback (most recent call last):
+ ...
+ TypeError: ("'x' must be <class 'int'> (got '128' that is a <class 'str'>).", Attribute(name='x', default=NOTHING, validator=[<instance_of validator for type <class 'int'>>, <function fits_byte at 0x10fd7a0d0>], repr=True, cmp=True, hash=True, init=True, convert=None, metadata=mappingproxy({}), type=None), <class 'int'>, '128')
+
+
+Conversion
+----------
+
+Attributes can have a ``convert`` function specified, which will be called with the attribute's passed-in value to get a new value to use.
+This can be useful for doing type-conversions on values that you don't want to force your callers to do.
+
+.. doctest::
+
+ >>> @attr.s
+ ... class C(object):
+ ... x = attr.ib(convert=int)
+ >>> o = C("1")
+ >>> o.x
+ 1
+
+Converters are run *before* validators, so you can use validators to check the final form of the value.
+
+.. doctest::
+
+ >>> def validate_x(instance, attribute, value):
+ ... if value < 0:
+ ... raise ValueError("x must be be at least 0.")
+ >>> @attr.s
+ ... class C(object):
+ ... x = attr.ib(convert=int, validator=validate_x)
+ >>> o = C("0")
+ >>> o.x
+ 0
+ >>> C("-1")
+ Traceback (most recent call last):
+ ...
+ ValueError: x must be be at least 0.
+
+
+.. _metadata:
+
+Metadata
+--------
+
+All ``attrs`` attributes may include arbitrary metadata in the form of a read-only dictionary.
+
+.. doctest::
+
+ >>> @attr.s
+ ... class C(object):
+ ... x = attr.ib(metadata={'my_metadata': 1})
+ >>> attr.fields(C).x.metadata
+ mappingproxy({'my_metadata': 1})
+ >>> attr.fields(C).x.metadata['my_metadata']
+ 1
+
+Metadata is not used by ``attrs``, and is meant to enable rich functionality in third-party libraries.
+The metadata dictionary follows the normal dictionary rules: keys need to be hashable, and both keys and values are recommended to be immutable.
+
+If you're the author of a third-party library with ``attrs`` integration, please see :ref:`Extending Metadata <extending_metadata>`.
+
+
+Types
+-----
+
+``attrs`` also allows you to associate a type with an attribute using either the *type* argument to :func:`attr.ib` or -- as of Python 3.6 -- using `PEP 526 <https://www.python.org/dev/peps/pep-0526/>`_-annotations:
+
+
+.. doctest::
+
+ >>> @attr.s
+ ... class C:
+ ... x = attr.ib(type=int)
+ ... y: int = attr.ib()
+ >>> attr.fields(C).x.type
+ <class 'int'>
+ >>> attr.fields(C).y.type
+ <class 'int'>
+
+If you don't mind annotating *all* attributes, you can even drop the :func:`attr.ib` and assign default values instead:
+
+.. doctest::
+
+ >>> import typing
+ >>> @attr.s(auto_attribs=True)
+ ... class AutoC:
+ ... cls_var: typing.ClassVar[int] = 5 # this one is ignored
+ ... l: typing.List[int] = attr.Factory(list)
+ ... x: int = 1
+ ... foo: str = attr.ib(
+ ... default="every attrib needs a type if auto_attribs=True"
+ ... )
+ ... bar: typing.Any = None
+ >>> attr.fields(AutoC).l.type
+ typing.List[int]
+ >>> attr.fields(AutoC).x.type
+ <class 'int'>
+ >>> attr.fields(AutoC).foo.type
+ <class 'str'>
+ >>> attr.fields(AutoC).bar.type
+ typing.Any
+ >>> AutoC()
+ AutoC(l=[], x=1, foo='every attrib needs a type if auto_attribs=True', bar=None)
+ >>> AutoC.cls_var
+ 5
+
+
+.. warning::
+
+ ``attrs`` itself doesn't have any features that work on top of type metadata *yet*.
+ However it's useful for writing your own validators or serialization frameworks.
+
+
+.. _slots:
+
+Slots
+-----
+
+By default, instances of classes have a dictionary for attribute storage.
+This wastes space for objects having very few data attributes.
+The space consumption can become significant when creating large numbers of instances.
+
+Normal Python classes can avoid using a separate dictionary for each instance of a class by `defining <https://docs.python.org/3/reference/datamodel.html#slots>`_ ``__slots__``.
+For ``attrs`` classes it's enough to set ``slots=True``:
+
+.. doctest::
+
+ >>> @attr.s(slots=True)
+ ... class Coordinates(object):
+ ... x = attr.ib()
+ ... y = attr.ib()
+
+
+.. note::
+
+ ``attrs`` slot classes can inherit from other classes just like non-slot classes, but some of the benefits of slot classes are lost if you do that.
+ If you must inherit from other classes, try to inherit only from other slot classes.
+
+Slot classes are a little different than ordinary, dictionary-backed classes:
+
+- Assigning to a non-existent attribute of an instance will result in an ``AttributeError`` being raised.
+ Depending on your needs, this might be a good thing since it will let you catch typos early.
+ This is not the case if your class inherits from any non-slot classes.
+
+ .. doctest::
+
+ >>> @attr.s(slots=True)
+ ... class Coordinates(object):
+ ... x = attr.ib()
+ ... y = attr.ib()
+ ...
+ >>> c = Coordinates(x=1, y=2)
+ >>> c.z = 3
+ Traceback (most recent call last):
+ ...
+ AttributeError: 'Coordinates' object has no attribute 'z'
+
+- Since non-slot classes cannot be turned into slot classes after they have been created, ``attr.s(slots=True)`` will *replace* the class it is applied to with a copy.
+ In almost all cases this isn't a problem, but we mention it for the sake of completeness.
+
+ * One notable problem is that certain metaclass features like ``__init_subclass__`` do not work with slot classes.
+
+- Using :mod:`pickle` with slot classes requires pickle protocol 2 or greater.
+ Python 2 uses protocol 0 by default so the protocol needs to be specified.
+ Python 3 uses protocol 3 by default.
+ You can support protocol 0 and 1 by implementing :meth:`__getstate__ <object.__getstate__>` and :meth:`__setstate__ <object.__setstate__>` methods yourself.
+ Those methods are created for frozen slot classes because they won't pickle otherwise.
+ `Think twice <https://www.youtube.com/watch?v=7KnfGDajDQw>`_ before using :mod:`pickle` though.
+
+- As always with slot classes, you must specify a ``__weakref__`` slot if you wish for the class to be weak-referenceable.
+ Here's how it looks using ``attrs``:
+
+ .. doctest::
+
+ >>> import weakref
+ >>> @attr.s(slots=True)
+ ... class C(object):
+ ... __weakref__ = attr.ib(init=False, hash=False, repr=False, cmp=False)
+ ... x = attr.ib()
+ >>> c = C(1)
+ >>> weakref.ref(c)
+ <weakref at 0x...; to 'C' at 0x...>
+
+All in all, setting ``slots=True`` is usually a very good idea.
+
+
+Immutability
+------------
+
+Sometimes you have instances that shouldn't be changed after instantiation.
+Immutability is especially popular in functional programming and is generally a very good thing.
+If you'd like to enforce it, ``attrs`` will try to help:
+
+.. doctest::
+
+ >>> @attr.s(frozen=True)
+ ... class C(object):
+ ... x = attr.ib()
+ >>> i = C(1)
+ >>> i.x = 2
+ Traceback (most recent call last):
+ ...
+ attr.exceptions.FrozenInstanceError: can't set attribute
+ >>> i.x
+ 1
+
+Please note that true immutability is impossible in Python but it will :ref:`get <how-frozen>` you 99% there.
+By themselves, immutable classes are useful for long-lived objects that should never change; like configurations for example.
+
+In order to use them in regular program flow, you'll need a way to easily create new instances with changed attributes.
+In Clojure that function is called `assoc <https://clojuredocs.org/clojure.core/assoc>`_ and ``attrs`` shamelessly imitates it: :func:`attr.evolve`:
+
+.. doctest::
+
+ >>> @attr.s(frozen=True)
+ ... class C(object):
+ ... x = attr.ib()
+ ... y = attr.ib()
+ >>> i1 = C(1, 2)
+ >>> i1
+ C(x=1, y=2)
+ >>> i2 = attr.evolve(i1, y=3)
+ >>> i2
+ C(x=1, y=3)
+ >>> i1 == i2
+ False
+
+
+Other Goodies
+-------------
+
+Sometimes you may want to create a class programmatically.
+``attrs`` won't let you down and gives you :func:`attr.make_class` :
+
+.. doctest::
+
+ >>> @attr.s
+ ... class C1(object):
+ ... x = attr.ib()
+ ... y = attr.ib()
+ >>> C2 = attr.make_class("C2", ["x", "y"])
+ >>> attr.fields(C1) == attr.fields(C2)
+ True
+
+You can still have power over the attributes if you pass a dictionary of name: ``attr.ib`` mappings and can pass arguments to ``@attr.s``:
+
+.. doctest::
+
+ >>> C = attr.make_class("C", {"x": attr.ib(default=42),
+ ... "y": attr.ib(default=attr.Factory(list))},
+ ... repr=False)
+ >>> i = C()
+ >>> i # no repr added!
+ <__main__.C object at ...>
+ >>> i.x
+ 42
+ >>> i.y
+ []
+
+If you need to dynamically make a class with :func:`attr.make_class` and it needs to be a subclass of something else than ``object``, use the ``bases`` argument:
+
+.. doctest::
+
+ >>> class D(object):
+ ... def __eq__(self, other):
+ ... return True # arbitrary example
+ >>> C = attr.make_class("C", {}, bases=(D,), cmp=False)
+ >>> isinstance(C(), D)
+ True
+
+Sometimes, you want to have your class's ``__init__`` method do more than just
+the initialization, validation, etc. that gets done for you automatically when
+using ``@attr.s``.
+To do this, just define a ``__attrs_post_init__`` method in your class.
+It will get called at the end of the generated ``__init__`` method.
+
+.. doctest::
+
+ >>> @attr.s
+ ... class C(object):
+ ... x = attr.ib()
+ ... y = attr.ib()
+ ... z = attr.ib(init=False)
+ ...
+ ... def __attrs_post_init__(self):
+ ... self.z = self.x + self.y
+ >>> obj = C(x=1, y=2)
+ >>> obj
+ C(x=1, y=2, z=3)
+
+Finally, you can exclude single attributes from certain methods:
+
+.. doctest::
+
+ >>> @attr.s
+ ... class C(object):
+ ... user = attr.ib()
+ ... password = attr.ib(repr=False)
+ >>> C("me", "s3kr3t")
+ C(user='me')
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/extending.rst b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/extending.rst
new file mode 100644
index 00000000000..d460ee9b8c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/extending.rst
@@ -0,0 +1,112 @@
+.. _extending:
+
+Extending
+=========
+
+Each ``attrs``-decorated class has a ``__attrs_attrs__`` class attribute.
+It is a tuple of :class:`attr.Attribute` carrying meta-data about each attribute.
+
+So it is fairly simple to build your own decorators on top of ``attrs``:
+
+.. doctest::
+
+ >>> import attr
+ >>> def print_attrs(cls):
+ ... print(cls.__attrs_attrs__)
+ >>> @print_attrs
+ ... @attr.s
+ ... class C(object):
+ ... a = attr.ib()
+ (Attribute(name='a', default=NOTHING, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}), type=None),)
+
+
+.. warning::
+
+ The :func:`attr.s` decorator **must** be applied first because it puts ``__attrs_attrs__`` in place!
+ That means that is has to come *after* your decorator because::
+
+ @a
+ @b
+ def f():
+ pass
+
+ is just `syntactic sugar <https://en.wikipedia.org/wiki/Syntactic_sugar>`_ for::
+
+ def original_f():
+ pass
+
+ f = a(b(original_f))
+
+
+Wrapping the Decorator
+----------------------
+
+A more elegant way can be to wrap ``attrs`` altogether and build a class `DSL <https://en.wikipedia.org/wiki/Domain-specific_language>`_ on top of it.
+
+An example for that is the package `environ_config <https://github.com/hynek/environ_config>`_ that uses ``attrs`` under the hood to define environment-based configurations declaratively without exposing ``attrs`` APIs at all.
+
+
+Types
+-----
+
+``attrs`` offers two ways of attaching type information to attributes:
+
+- `PEP 526 <https://www.python.org/dev/peps/pep-0526/>`_ annotations on Python 3.6 and later,
+- and the *type* argument to :func:`attr.ib`.
+
+This information is available to you:
+
+.. doctest::
+
+ >>> import attr
+ >>> @attr.s
+ ... class C(object):
+ ... x: int = attr.ib()
+ ... y = attr.ib(type=str)
+ >>> attr.fields(C).x.type
+ <class 'int'>
+ >>> attr.fields(C).y.type
+ <class 'str'>
+
+Currently, ``attrs`` doesn't do anything with this information but it's very useful if you'd like to write your own validators or serializers!
+
+
+.. _extending_metadata:
+
+Metadata
+--------
+
+If you're the author of a third-party library with ``attrs`` integration, you may want to take advantage of attribute metadata.
+
+Here are some tips for effective use of metadata:
+
+- Try making your metadata keys and values immutable.
+ This keeps the entire ``Attribute`` instances immutable too.
+
+- To avoid metadata key collisions, consider exposing your metadata keys from your modules.::
+
+ from mylib import MY_METADATA_KEY
+
+ @attr.s
+ class C(object):
+ x = attr.ib(metadata={MY_METADATA_KEY: 1})
+
+ Metadata should be composable, so consider supporting this approach even if you decide implementing your metadata in one of the following ways.
+
+- Expose ``attr.ib`` wrappers for your specific metadata.
+ This is a more graceful approach if your users don't require metadata from other libraries.
+
+ .. doctest::
+
+ >>> MY_TYPE_METADATA = '__my_type_metadata'
+ >>>
+ >>> def typed(cls, default=attr.NOTHING, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata={}):
+ ... metadata = dict() if not metadata else metadata
+ ... metadata[MY_TYPE_METADATA] = cls
+ ... return attr.ib(default, validator, repr, cmp, hash, init, convert, metadata)
+ >>>
+ >>> @attr.s
+ ... class C(object):
+ ... x = typed(int, default=1, init=False)
+ >>> attr.fields(C).x.metadata[MY_TYPE_METADATA]
+ <class 'int'>
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/how-does-it-work.rst b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/how-does-it-work.rst
new file mode 100644
index 00000000000..c20becd1f78
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/how-does-it-work.rst
@@ -0,0 +1,79 @@
+.. _how:
+
+How Does It Work?
+=================
+
+
+Boilerplate
+-----------
+
+``attrs`` certainly isn't the first library that aims to simplify class definition in Python.
+But its **declarative** approach combined with **no runtime overhead** lets it stand out.
+
+Once you apply the ``@attr.s`` decorator to a class, ``attrs`` searches the class object for instances of ``attr.ib``\ s.
+Internally they're a representation of the data passed into ``attr.ib`` along with a counter to preserve the order of the attributes.
+
+In order to ensure that sub-classing works as you'd expect it to work, ``attrs`` also walks the class hierarchy and collects the attributes of all super-classes.
+Please note that ``attrs`` does *not* call ``super()`` *ever*.
+It will write dunder methods to work on *all* of those attributes which also has performance benefits due to fewer function calls.
+
+Once ``attrs`` knows what attributes it has to work on, it writes the requested dunder methods and -- depending on whether you wish to have ``__slots__`` -- creates a new class for you (``slots=True``) or attaches them to the original class (``slots=False``).
+While creating new classes is more elegant, we've run into several edge cases surrounding metaclasses that make it impossible to go this route unconditionally.
+
+To be very clear: if you define a class with a single attribute without a default value, the generated ``__init__`` will look *exactly* how you'd expect:
+
+.. doctest::
+
+ >>> import attr, inspect
+ >>> @attr.s
+ ... class C(object):
+ ... x = attr.ib()
+ >>> print(inspect.getsource(C.__init__))
+ def __init__(self, x):
+ self.x = x
+ <BLANKLINE>
+
+No magic, no meta programming, no expensive introspection at runtime.
+
+****
+
+Everything until this point happens exactly *once* when the class is defined.
+As soon as a class is done, it's done.
+And it's just a regular Python class like any other, except for a single ``__attrs_attrs__`` attribute that can be used for introspection or for writing your own tools and decorators on top of ``attrs`` (like :func:`attr.asdict`).
+
+And once you start instantiating your classes, ``attrs`` is out of your way completely.
+
+This **static** approach was very much a design goal of ``attrs`` and what I strongly believe makes it distinct.
+
+
+.. _how-frozen:
+
+Immutability
+------------
+
+In order to give you immutability, ``attrs`` will attach a ``__setattr__`` method to your class that raises a :exc:`attr.exceptions.FrozenInstanceError` whenever anyone tries to set an attribute.
+
+To circumvent that ourselves in ``__init__``, ``attrs`` uses (an aggressively cached) :meth:`object.__setattr__` to set your attributes.
+This is (still) slower than a plain assignment:
+
+.. code-block:: none
+
+ $ pyperf timeit --rigorous \
+ -s "import attr; C = attr.make_class('C', ['x', 'y', 'z'], slots=True)" \
+ "C(1, 2, 3)"
+ ........................................
+ Median +- std dev: 378 ns +- 12 ns
+
+ $ pyperf timeit --rigorous \
+ -s "import attr; C = attr.make_class('C', ['x', 'y', 'z'], slots=True, frozen=True)" \
+ "C(1, 2, 3)"
+ ........................................
+ Median +- std dev: 676 ns +- 16 ns
+
+So on a standard notebook the difference is about 300 nanoseconds (1 second is 1,000,000,000 nanoseconds).
+It's certainly something you'll feel in a hot loop but shouldn't matter in normal code.
+Pick what's more important to you.
+
+****
+
+Once constructed, frozen instances don't differ in any way from regular ones except that you cannot change its attributes.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/index.rst b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/index.rst
new file mode 100644
index 00000000000..bb24cd773fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/index.rst
@@ -0,0 +1,80 @@
+======================================
+``attrs``: Classes Without Boilerplate
+======================================
+
+Release v\ |release| (:doc:`What's new? <changelog>`).
+
+.. include:: ../README.rst
+ :start-after: teaser-begin
+ :end-before: -spiel-end-
+
+
+Getting Started
+===============
+
+``attrs`` is a Python-only package `hosted on PyPI <https://pypi.org/project/attrs/>`_.
+The recommended installation method is `pip <https://pip.pypa.io/en/stable/>`_-installing into a `virtualenv <https://hynek.me/articles/virtualenv-lives/>`_:
+
+.. code-block:: console
+
+ $ pip install attrs
+
+The next three steps should bring you up and running in no time:
+
+- :doc:`overview` will show you a simple example of ``attrs`` in action and introduce you to its philosophy.
+ Afterwards, you can start writing your own classes, understand what drives ``attrs``'s design, and know what ``@attr.s`` and ``attr.ib()`` stand for.
+- :doc:`examples` will give you a comprehensive tour of ``attrs``'s features.
+ After reading, you will know about our advanced features and how to use them.
+- Finally :doc:`why` gives you a rundown of potential alternatives and why we think ``attrs`` is superior.
+ Yes, we've heard about ``namedtuple``\ s!
+
+
+If you need any help while getting started, feel free to use the ``python-attrs`` tag on `StackOverflow <https://stackoverflow.com/questions/tagged/python-attrs>`_ and someone will surely help you out!
+
+
+Day-to-Day Usage
+================
+
+- Once you're comfortable with the concepts, our :doc:`api` contains all information you need to use ``attrs`` to its fullest.
+- ``attrs`` is built for extension from the ground up.
+ :doc:`extending` will show you the affordances it offers and how to make it a building block of your own projects.
+
+
+.. include:: ../README.rst
+ :start-after: -testimonials-
+ :end-before: -end-
+
+.. include:: ../README.rst
+ :start-after: -project-information-
+
+.. toctree::
+ :maxdepth: 1
+
+ license
+ backward-compatibility
+ contributing
+ changelog
+
+
+----
+
+
+Full Table of Contents
+======================
+
+.. toctree::
+ :maxdepth: 2
+
+ overview
+ why
+ examples
+ api
+ extending
+ how-does-it-work
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`search`
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/license.rst b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/license.rst
new file mode 100644
index 00000000000..cef5f393993
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/license.rst
@@ -0,0 +1,8 @@
+===================
+License and Credits
+===================
+
+``attrs`` is licensed under the `MIT <https://choosealicense.com/licenses/mit/>`_ license.
+The full license text can be also found in the `source code repository <https://github.com/python-attrs/attrs/blob/master/LICENSE>`_.
+
+.. include:: ../AUTHORS.rst
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/overview.rst b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/overview.rst
new file mode 100644
index 00000000000..47b022ff32e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/overview.rst
@@ -0,0 +1,87 @@
+========
+Overview
+========
+
+In order to fulfill its ambitious goal of bringing back the joy to writing classes, it gives you a class decorator and a way to declaratively define the attributes on that class:
+
+.. include:: ../README.rst
+ :start-after: -code-begin-
+ :end-before: -testimonials-
+
+
+.. _philosophy:
+
+Philosophy
+==========
+
+**It's about regular classes.**
+ ``attrs`` is for creating well-behaved classes with a type, attributes, methods, and everything that comes with a class.
+ It can be used for data-only containers like ``namedtuple``\ s or ``types.SimpleNamespace`` but they're just a sub-genre of what ``attrs`` is good for.
+
+**The class belongs to the users.**
+ You define a class and ``attrs`` adds static methods to that class based on the attributes you declare.
+ The end.
+ It doesn't add metaclasses.
+ It doesn't add classes you've never heard of to your inheritance tree.
+ An ``attrs`` class in runtime is indistiguishable from a regular class: because it *is* a regular class with a few boilerplate-y methods attached.
+
+**Be light on API impact.**
+ As convenient as it seems at first, ``attrs`` will *not* tack on any methods to your classes save the dunder ones.
+ Hence all the useful :ref:`tools <helpers>` that come with ``attrs`` live in functions that operate on top of instances.
+ Since they take an ``attrs`` instance as their first argument, you can attach them to your classes with one line of code.
+
+**Performance matters.**
+ ``attrs`` runtime impact is very close to zero because all the work is done when the class is defined.
+ Once you're instantiating it, ``attrs`` is out of the picture completely.
+
+**No surprises.**
+ ``attrs`` creates classes that arguably work the way a Python beginner would reasonably expect them to work.
+ It doesn't try to guess what you mean because explicit is better than implicit.
+ It doesn't try to be clever because software shouldn't be clever.
+
+Check out :doc:`how-does-it-work` if you'd like to know how it achieves all of the above.
+
+
+What ``attrs`` Is Not
+=====================
+
+``attrs`` does *not* invent some kind of magic system that pulls classes out of its hat using meta classes, runtime introspection, and shaky interdependencies.
+
+All ``attrs`` does is:
+
+1. take your declaration,
+2. write dunder methods based on that information,
+3. and attach them to your class.
+
+It does *nothing* dynamic at runtime, hence zero runtime overhead.
+It's still *your* class.
+Do with it as you please.
+
+
+On the ``attr.s`` and ``attr.ib`` Names
+=======================================
+
+The ``attr.s`` decorator and the ``attr.ib`` function aren't any obscure abbreviations.
+They are a *concise* and highly *readable* way to write ``attrs`` and ``attrib`` with an *explicit namespace*.
+
+At first, some people have a negative gut reaction to that; resembling the reactions to Python's significant whitespace.
+And as with that, once one gets used to it, the readability and explicitness of that API prevails and delights.
+
+For those who can't swallow that API at all, ``attrs`` comes with serious business aliases: ``attr.attrs`` and ``attr.attrib``.
+
+Therefore, the following class definition is identical to the previous one:
+
+.. doctest::
+
+ >>> from attr import attrs, attrib, Factory
+ >>> @attrs
+ ... class SomeClass(object):
+ ... a_number = attrib(default=42)
+ ... list_of_numbers = attrib(default=Factory(list))
+ ...
+ ... def hard_math(self, another_number):
+ ... return self.a_number + sum(self.list_of_numbers) * another_number
+ >>> SomeClass(1, [1, 2, 3])
+ SomeClass(a_number=1, list_of_numbers=[1, 2, 3])
+
+Use whichever variant fits your taste better.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/why.rst b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/why.rst
new file mode 100644
index 00000000000..9c64cb93c57
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/docs/why.rst
@@ -0,0 +1,251 @@
+.. _why:
+
+Why not…
+========
+
+
+If you'd like third party's account why ``attrs`` is great, have a look at Glyph's `The One Python Library Everyone Needs <https://glyph.twistedmatrix.com/2016/08/attrs.html>`_!
+
+
+…tuples?
+--------
+
+
+Readability
+^^^^^^^^^^^
+
+What makes more sense while debugging::
+
+ Point(x=1, y=2)
+
+or::
+
+ (1, 2)
+
+?
+
+Let's add even more ambiguity::
+
+ Customer(id=42, reseller=23, first_name="Jane", last_name="John")
+
+or::
+
+ (42, 23, "Jane", "John")
+
+?
+
+Why would you want to write ``customer[2]`` instead of ``customer.first_name``?
+
+Don't get me started when you add nesting.
+If you've never run into mysterious tuples you had no idea what the hell they meant while debugging, you're much smarter than yours truly.
+
+Using proper classes with names and types makes program code much more readable and comprehensible_.
+Especially when trying to grok a new piece of software or returning to old code after several months.
+
+.. _comprehensible: https://arxiv.org/pdf/1304.5257.pdf
+
+
+Extendability
+^^^^^^^^^^^^^
+
+Imagine you have a function that takes or returns a tuple.
+Especially if you use tuple unpacking (eg. ``x, y = get_point()``), adding additional data means that you have to change the invocation of that function *everywhere*.
+
+Adding an attribute to a class concerns only those who actually care about that attribute.
+
+
+…namedtuples?
+-------------
+
+:func:`collections.namedtuple`\ s are tuples with names, not classes. [#history]_
+Since writing classes is tiresome in Python, every now and then someone discovers all the typing they could save and gets really excited.
+However that convenience comes at a price.
+
+The most obvious difference between ``namedtuple``\ s and ``attrs``-based classes is that the latter are type-sensitive:
+
+.. doctest::
+
+ >>> import attr
+ >>> C1 = attr.make_class("C1", ["a"])
+ >>> C2 = attr.make_class("C2", ["a"])
+ >>> i1 = C1(1)
+ >>> i2 = C2(1)
+ >>> i1.a == i2.a
+ True
+ >>> i1 == i2
+ False
+
+…while a ``namedtuple`` is *intentionally* `behaving like a tuple`_ which means the type of a tuple is *ignored*:
+
+.. doctest::
+
+ >>> from collections import namedtuple
+ >>> NT1 = namedtuple("NT1", "a")
+ >>> NT2 = namedtuple("NT2", "b")
+ >>> t1 = NT1(1)
+ >>> t2 = NT2(1)
+ >>> t1 == t2 == (1,)
+ True
+
+Other often surprising behaviors include:
+
+- Since they are a subclass of tuples, ``namedtuple``\ s have a length and are both iterable and indexable.
+ That's not what you'd expect from a class and is likely to shadow subtle typo bugs.
+- Iterability also implies that it's easy to accidentally unpack a ``namedtuple`` which leads to hard-to-find bugs. [#iter]_
+- ``namedtuple``\ s have their methods *on your instances* whether you like it or not. [#pollution]_
+- ``namedtuple``\ s are *always* immutable.
+ Not only does that mean that you can't decide for yourself whether your instances should be immutable or not, it also means that if you want to influence your class' initialization (validation? default values?), you have to implement :meth:`__new__() <object.__new__>` which is a particularly hacky and error-prone requirement for a very common problem. [#immutable]_
+- To attach methods to a ``namedtuple`` you have to subclass it.
+ And if you follow the standard library documentation's recommendation of::
+
+ class Point(namedtuple('Point', ['x', 'y'])):
+ # ...
+
+ you end up with a class that has *two* ``Point``\ s in its :attr:`__mro__ <class.__mro__>`: ``[<class 'point.Point'>, <class 'point.Point'>, <type 'tuple'>, <type 'object'>]``.
+
+ That's not only confusing, it also has very practical consequences:
+ for example if you create documentation that includes class hierarchies like `Sphinx's autodoc <http://www.sphinx-doc.org/en/stable/ext/autodoc.html>`_ with ``show-inheritance``.
+ Again: common problem, hacky solution with confusing fallout.
+
+All these things make ``namedtuple``\ s a particularly poor choice for public APIs because all your objects are irrevocably tainted.
+With ``attrs`` your users won't notice a difference because it creates regular, well-behaved classes.
+
+.. admonition:: Summary
+
+ If you want a *tuple with names*, by all means: go for a ``namedtuple``. [#perf]_
+ But if you want a class with methods, you're doing yourself a disservice by relying on a pile of hacks that requires you to employ even more hacks as your requirements expand.
+
+ Other than that, ``attrs`` also adds nifty features like validators, converters, and (mutable!) default values.
+
+
+.. rubric:: Footnotes
+
+.. [#history] The word is that ``namedtuple``\ s were added to the Python standard library as a way to make tuples in return values more readable.
+ And indeed that is something you see throughout the standard library.
+
+ Looking at what the makers of ``namedtuple``\ s use it for themselves is a good guideline for deciding on your own use cases.
+.. [#pollution] ``attrs`` only adds a single attribute: ``__attrs_attrs__`` for introspection.
+ All helpers are functions in the ``attr`` package.
+ Since they take the instance as first argument, you can easily attach them to your classes under a name of your own choice.
+.. [#iter] :func:`attr.astuple` can be used to get that behavior in ``attrs`` on *explicit demand*.
+.. [#immutable] ``attrs`` offers *optional* immutability through the ``frozen`` keyword.
+.. [#perf] Although ``attrs`` would serve you just as well!
+ Since both employ the same method of writing and compiling Python code for you, the performance penalty is negligible at worst and in some cases ``attrs`` is even faster if you use ``slots=True`` (which is generally a good idea anyway).
+
+.. _behaving like a tuple: https://docs.python.org/3/tutorial/datastructures.html#tuples-and-sequences
+
+
+…dicts?
+-------
+
+Dictionaries are not for fixed fields.
+
+If you have a dict, it maps something to something else.
+You should be able to add and remove values.
+
+
+
+``attrs`` lets you be specific about those expectations; a dictionary does not.
+It gives you a named entity (the class) in your code, which lets you explain in other places whether you take a parameter of that class or return a value of that class.
+
+In other words: if your dict has a fixed and known set of keys, it is an object, not a hash.
+So if you never iterate over the keys of a dict, you should use a proper class.
+
+
+…hand-written classes?
+----------------------
+
+While we're fans of all things artisanal, writing the same nine methods all over again doesn't qualify for me.
+I usually manage to get some typos inside and there's simply more code that can break and thus has to be tested.
+
+To bring it into perspective, the equivalent of
+
+.. doctest::
+
+ >>> @attr.s
+ ... class SmartClass(object):
+ ... a = attr.ib()
+ ... b = attr.ib()
+ >>> SmartClass(1, 2)
+ SmartClass(a=1, b=2)
+
+is
+
+.. doctest::
+
+ >>> class ArtisanalClass(object):
+ ... def __init__(self, a, b):
+ ... self.a = a
+ ... self.b = b
+ ...
+ ... def __repr__(self):
+ ... return "ArtisanalClass(a={}, b={})".format(self.a, self.b)
+ ...
+ ... def __eq__(self, other):
+ ... if other.__class__ is self.__class__:
+ ... return (self.a, self.b) == (other.a, other.b)
+ ... else:
+ ... return NotImplemented
+ ...
+ ... def __ne__(self, other):
+ ... result = self.__eq__(other)
+ ... if result is NotImplemented:
+ ... return NotImplemented
+ ... else:
+ ... return not result
+ ...
+ ... def __lt__(self, other):
+ ... if other.__class__ is self.__class__:
+ ... return (self.a, self.b) < (other.a, other.b)
+ ... else:
+ ... return NotImplemented
+ ...
+ ... def __le__(self, other):
+ ... if other.__class__ is self.__class__:
+ ... return (self.a, self.b) <= (other.a, other.b)
+ ... else:
+ ... return NotImplemented
+ ...
+ ... def __gt__(self, other):
+ ... if other.__class__ is self.__class__:
+ ... return (self.a, self.b) > (other.a, other.b)
+ ... else:
+ ... return NotImplemented
+ ...
+ ... def __ge__(self, other):
+ ... if other.__class__ is self.__class__:
+ ... return (self.a, self.b) >= (other.a, other.b)
+ ... else:
+ ... return NotImplemented
+ ...
+ ... def __hash__(self):
+ ... return hash((self.a, self.b))
+ >>> ArtisanalClass(a=1, b=2)
+ ArtisanalClass(a=1, b=2)
+
+which is quite a mouthful and it doesn't even use any of ``attrs``'s more advanced features like validators or defaults values.
+Also: no tests whatsoever.
+And who will guarantee you, that you don't accidentally flip the ``<`` in your tenth implementation of ``__gt__``?
+
+It also should be noted that ``attrs`` is not an all-or-nothing solution.
+You can freely choose which features you want and disable those that you want more control over:
+
+.. doctest::
+
+ >>> @attr.s(repr=False)
+ ... class SmartClass(object):
+ ... a = attr.ib()
+ ... b = attr.ib()
+ ...
+ ... def __repr__(self):
+ ... return "<SmartClass(a=%d)>" % (self.a,)
+ >>> SmartClass(1, 2)
+ <SmartClass(a=1)>
+
+.. admonition:: Summary
+
+ If you don't care and like typing, we're not gonna stop you.
+
+ However it takes a lot of bias and determined rationalization to claim that ``attrs`` raises the mental burden on a project given how difficult it is to find the important bits in a hand-written class and how annoying it is to ensure you've copy-pasted your code correctly over all your classes.
+
+ In any case, if you ever get sick of the repetitiveness and drowning important code in a sea of boilerplate, ``attrs`` will be waiting for you.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/pyproject.toml b/tests/wpt/web-platform-tests/tools/third_party/attrs/pyproject.toml
new file mode 100644
index 00000000000..0f68a7cb0fc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/pyproject.toml
@@ -0,0 +1,26 @@
+[tool.towncrier]
+ package = "attr"
+ package_dir = "src"
+ filename = "CHANGELOG.rst"
+ issue_format = "`#{issue} <https://github.com/python-attrs/attrs/issues/{issue}>`_"
+ directory = "changelog.d"
+ title_format = "{version} ({project_date})"
+ underlines = ["-", "^"]
+
+ [[tool.towncrier.section]]
+ path = ""
+
+ [[tool.towncrier.type]]
+ directory = "breaking"
+ name = "Backward-incompatible Changes"
+ showcontent = true
+
+ [[tool.towncrier.type]]
+ directory = "deprecation"
+ name = "Deprecations"
+ showcontent = true
+
+ [[tool.towncrier.type]]
+ directory = "change"
+ name = "Changes"
+ showcontent = true
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/setup.cfg b/tests/wpt/web-platform-tests/tools/third_party/attrs/setup.cfg
new file mode 100644
index 00000000000..8ddbbabc3cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/setup.cfg
@@ -0,0 +1,26 @@
+[bdist_wheel]
+universal = 1
+
+
+[metadata]
+# ensure LICENSE is included in wheel metadata
+license_file = LICENSE
+
+
+[tool:pytest]
+minversion = 3.0
+strict = true
+addopts = -ra
+testpaths = tests
+filterwarnings =
+ once::Warning
+
+
+[isort]
+atomic=true
+lines_after_imports=2
+lines_between_types=1
+multi_line_output=5
+not_skip=__init__.py
+
+known_first_party=attr
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/setup.py b/tests/wpt/web-platform-tests/tools/third_party/attrs/setup.py
new file mode 100644
index 00000000000..232d3f5eaaa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/setup.py
@@ -0,0 +1,95 @@
+import codecs
+import os
+import re
+
+from setuptools import find_packages, setup
+
+
+###############################################################################
+
+NAME = "attrs"
+PACKAGES = find_packages(where="src")
+META_PATH = os.path.join("src", "attr", "__init__.py")
+KEYWORDS = ["class", "attribute", "boilerplate"]
+CLASSIFIERS = [
+ "Development Status :: 5 - Production/Stable",
+ "Intended Audience :: Developers",
+ "Natural Language :: English",
+ "License :: OSI Approved :: MIT License",
+ "Operating System :: OS Independent",
+ "Programming Language :: Python",
+ "Programming Language :: Python :: 2",
+ "Programming Language :: Python :: 2.7",
+ "Programming Language :: Python :: 3",
+ "Programming Language :: Python :: 3.4",
+ "Programming Language :: Python :: 3.5",
+ "Programming Language :: Python :: 3.6",
+ "Programming Language :: Python :: Implementation :: CPython",
+ "Programming Language :: Python :: Implementation :: PyPy",
+ "Topic :: Software Development :: Libraries :: Python Modules",
+]
+INSTALL_REQUIRES = []
+
+###############################################################################
+
+HERE = os.path.abspath(os.path.dirname(__file__))
+
+
+def read(*parts):
+ """
+ Build an absolute path from *parts* and and return the contents of the
+ resulting file. Assume UTF-8 encoding.
+ """
+ with codecs.open(os.path.join(HERE, *parts), "rb", "utf-8") as f:
+ return f.read()
+
+
+META_FILE = read(META_PATH)
+
+
+def find_meta(meta):
+ """
+ Extract __*meta*__ from META_FILE.
+ """
+ meta_match = re.search(
+ r"^__{meta}__ = ['\"]([^'\"]*)['\"]".format(meta=meta),
+ META_FILE, re.M
+ )
+ if meta_match:
+ return meta_match.group(1)
+ raise RuntimeError("Unable to find __{meta}__ string.".format(meta=meta))
+
+
+VERSION = find_meta("version")
+URI = find_meta("uri")
+LONG = (
+ read("README.rst") + "\n\n" +
+ "Release Information\n" +
+ "===================\n\n" +
+ re.search("(\d+.\d.\d \(.*?\)\n.*?)\n\n\n----\n\n\n",
+ read("CHANGELOG.rst"), re.S).group(1) +
+ "\n\n`Full changelog " +
+ "<{uri}en/stable/changelog.html>`_.\n\n".format(uri=URI) +
+ read("AUTHORS.rst")
+)
+
+
+if __name__ == "__main__":
+ setup(
+ name=NAME,
+ description=find_meta("description"),
+ license=find_meta("license"),
+ url=URI,
+ version=VERSION,
+ author=find_meta("author"),
+ author_email=find_meta("email"),
+ maintainer=find_meta("author"),
+ maintainer_email=find_meta("email"),
+ keywords=KEYWORDS,
+ long_description=LONG,
+ packages=PACKAGES,
+ package_dir={"": "src"},
+ zip_safe=False,
+ classifiers=CLASSIFIERS,
+ install_requires=INSTALL_REQUIRES,
+ )
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/__init__.py b/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/__init__.py
new file mode 100644
index 00000000000..929b1721ff1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/__init__.py
@@ -0,0 +1,55 @@
+from __future__ import absolute_import, division, print_function
+
+from functools import partial
+
+from . import converters, exceptions, filters, validators
+from ._config import get_run_validators, set_run_validators
+from ._funcs import asdict, assoc, astuple, evolve, has
+from ._make import (
+ NOTHING, Attribute, Factory, attrib, attrs, fields, make_class, validate
+)
+
+
+__version__ = "17.4.0.dev0"
+
+__title__ = "attrs"
+__description__ = "Classes Without Boilerplate"
+__uri__ = "http://www.attrs.org/"
+__doc__ = __description__ + " <" + __uri__ + ">"
+
+__author__ = "Hynek Schlawack"
+__email__ = "hs@ox.cx"
+
+__license__ = "MIT"
+__copyright__ = "Copyright (c) 2015 Hynek Schlawack"
+
+
+s = attributes = attrs
+ib = attr = attrib
+dataclass = partial(attrs, auto_attribs=True) # happy Easter ;)
+
+__all__ = [
+ "Attribute",
+ "Factory",
+ "NOTHING",
+ "asdict",
+ "assoc",
+ "astuple",
+ "attr",
+ "attrib",
+ "attributes",
+ "attrs",
+ "converters",
+ "evolve",
+ "exceptions",
+ "fields",
+ "filters",
+ "get_run_validators",
+ "has",
+ "ib",
+ "make_class",
+ "s",
+ "set_run_validators",
+ "validate",
+ "validators",
+]
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/_compat.py b/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/_compat.py
new file mode 100644
index 00000000000..8a49341b25f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/_compat.py
@@ -0,0 +1,139 @@
+from __future__ import absolute_import, division, print_function
+
+import platform
+import sys
+import types
+import warnings
+
+
+PY2 = sys.version_info[0] == 2
+PYPY = platform.python_implementation() == "PyPy"
+
+
+if PY2:
+ from UserDict import IterableUserDict
+
+ # We 'bundle' isclass instead of using inspect as importing inspect is
+ # fairly expensive (order of 10-15 ms for a modern machine in 2016)
+ def isclass(klass):
+ return isinstance(klass, (type, types.ClassType))
+
+ # TYPE is used in exceptions, repr(int) is different on Python 2 and 3.
+ TYPE = "type"
+
+ def iteritems(d):
+ return d.iteritems()
+
+ # Python 2 is bereft of a read-only dict proxy, so we make one!
+ class ReadOnlyDict(IterableUserDict):
+ """
+ Best-effort read-only dict wrapper.
+ """
+
+ def __setitem__(self, key, val):
+ # We gently pretend we're a Python 3 mappingproxy.
+ raise TypeError("'mappingproxy' object does not support item "
+ "assignment")
+
+ def update(self, _):
+ # We gently pretend we're a Python 3 mappingproxy.
+ raise AttributeError("'mappingproxy' object has no attribute "
+ "'update'")
+
+ def __delitem__(self, _):
+ # We gently pretend we're a Python 3 mappingproxy.
+ raise TypeError("'mappingproxy' object does not support item "
+ "deletion")
+
+ def clear(self):
+ # We gently pretend we're a Python 3 mappingproxy.
+ raise AttributeError("'mappingproxy' object has no attribute "
+ "'clear'")
+
+ def pop(self, key, default=None):
+ # We gently pretend we're a Python 3 mappingproxy.
+ raise AttributeError("'mappingproxy' object has no attribute "
+ "'pop'")
+
+ def popitem(self):
+ # We gently pretend we're a Python 3 mappingproxy.
+ raise AttributeError("'mappingproxy' object has no attribute "
+ "'popitem'")
+
+ def setdefault(self, key, default=None):
+ # We gently pretend we're a Python 3 mappingproxy.
+ raise AttributeError("'mappingproxy' object has no attribute "
+ "'setdefault'")
+
+ def __repr__(self):
+ # Override to be identical to the Python 3 version.
+ return "mappingproxy(" + repr(self.data) + ")"
+
+ def metadata_proxy(d):
+ res = ReadOnlyDict()
+ res.data.update(d) # We blocked update, so we have to do it like this.
+ return res
+
+else:
+ def isclass(klass):
+ return isinstance(klass, type)
+
+ TYPE = "class"
+
+ def iteritems(d):
+ return d.items()
+
+ def metadata_proxy(d):
+ return types.MappingProxyType(dict(d))
+
+
+def import_ctypes(): # pragma: nocover
+ """
+ Moved into a function for testability.
+ """
+ try:
+ import ctypes
+ return ctypes
+ except ImportError:
+ return None
+
+
+if not PY2:
+ def just_warn(*args, **kw):
+ """
+ We only warn on Python 3 because we are not aware of any concrete
+ consequences of not setting the cell on Python 2.
+ """
+ warnings.warn(
+ "Missing ctypes. Some features like bare super() or accessing "
+ "__class__ will not work with slots classes.",
+ RuntimeWarning,
+ stacklevel=2,
+ )
+else:
+ def just_warn(*args, **kw): # pragma: nocover
+ """
+ We only warn on Python 3 because we are not aware of any concrete
+ consequences of not setting the cell on Python 2.
+ """
+
+
+def make_set_closure_cell():
+ """
+ Moved into a function for testability.
+ """
+ if PYPY: # pragma: no cover
+ def set_closure_cell(cell, value):
+ cell.__setstate__((value,))
+ else:
+ ctypes = import_ctypes()
+ if ctypes is not None:
+ set_closure_cell = ctypes.pythonapi.PyCell_Set
+ set_closure_cell.argtypes = (ctypes.py_object, ctypes.py_object)
+ set_closure_cell.restype = ctypes.c_int
+ else:
+ set_closure_cell = just_warn
+ return set_closure_cell
+
+
+set_closure_cell = make_set_closure_cell()
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/_config.py b/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/_config.py
new file mode 100644
index 00000000000..8ec920962d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/_config.py
@@ -0,0 +1,23 @@
+from __future__ import absolute_import, division, print_function
+
+
+__all__ = ["set_run_validators", "get_run_validators"]
+
+_run_validators = True
+
+
+def set_run_validators(run):
+ """
+ Set whether or not validators are run. By default, they are run.
+ """
+ if not isinstance(run, bool):
+ raise TypeError("'run' must be bool.")
+ global _run_validators
+ _run_validators = run
+
+
+def get_run_validators():
+ """
+ Return whether or not validators are run.
+ """
+ return _run_validators
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/_funcs.py b/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/_funcs.py
new file mode 100644
index 00000000000..798043af3f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/_funcs.py
@@ -0,0 +1,212 @@
+from __future__ import absolute_import, division, print_function
+
+import copy
+
+from ._compat import iteritems
+from ._make import NOTHING, _obj_setattr, fields
+from .exceptions import AttrsAttributeNotFoundError
+
+
+def asdict(inst, recurse=True, filter=None, dict_factory=dict,
+ retain_collection_types=False):
+ """
+ Return the ``attrs`` attribute values of *inst* as a dict.
+
+ Optionally recurse into other ``attrs``-decorated classes.
+
+ :param inst: Instance of an ``attrs``-decorated class.
+ :param bool recurse: Recurse into classes that are also
+ ``attrs``-decorated.
+ :param callable filter: A callable whose return code determines whether an
+ attribute or element is included (``True``) or dropped (``False``). Is
+ called with the :class:`attr.Attribute` as the first argument and the
+ value as the second argument.
+ :param callable dict_factory: A callable to produce dictionaries from. For
+ example, to produce ordered dictionaries instead of normal Python
+ dictionaries, pass in ``collections.OrderedDict``.
+ :param bool retain_collection_types: Do not convert to ``list`` when
+ encountering an attribute whose type is ``tuple`` or ``set``. Only
+ meaningful if ``recurse`` is ``True``.
+
+ :rtype: return type of *dict_factory*
+
+ :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``
+ class.
+
+ .. versionadded:: 16.0.0 *dict_factory*
+ .. versionadded:: 16.1.0 *retain_collection_types*
+ """
+ attrs = fields(inst.__class__)
+ rv = dict_factory()
+ for a in attrs:
+ v = getattr(inst, a.name)
+ if filter is not None and not filter(a, v):
+ continue
+ if recurse is True:
+ if has(v.__class__):
+ rv[a.name] = asdict(v, recurse=True, filter=filter,
+ dict_factory=dict_factory)
+ elif isinstance(v, (tuple, list, set)):
+ cf = v.__class__ if retain_collection_types is True else list
+ rv[a.name] = cf([
+ asdict(i, recurse=True, filter=filter,
+ dict_factory=dict_factory)
+ if has(i.__class__) else i
+ for i in v
+ ])
+ elif isinstance(v, dict):
+ df = dict_factory
+ rv[a.name] = df((
+ asdict(kk, dict_factory=df) if has(kk.__class__) else kk,
+ asdict(vv, dict_factory=df) if has(vv.__class__) else vv)
+ for kk, vv in iteritems(v))
+ else:
+ rv[a.name] = v
+ else:
+ rv[a.name] = v
+ return rv
+
+
+def astuple(inst, recurse=True, filter=None, tuple_factory=tuple,
+ retain_collection_types=False):
+ """
+ Return the ``attrs`` attribute values of *inst* as a tuple.
+
+ Optionally recurse into other ``attrs``-decorated classes.
+
+ :param inst: Instance of an ``attrs``-decorated class.
+ :param bool recurse: Recurse into classes that are also
+ ``attrs``-decorated.
+ :param callable filter: A callable whose return code determines whether an
+ attribute or element is included (``True``) or dropped (``False``). Is
+ called with the :class:`attr.Attribute` as the first argument and the
+ value as the second argument.
+ :param callable tuple_factory: A callable to produce tuples from. For
+ example, to produce lists instead of tuples.
+ :param bool retain_collection_types: Do not convert to ``list``
+ or ``dict`` when encountering an attribute which type is
+ ``tuple``, ``dict`` or ``set``. Only meaningful if ``recurse`` is
+ ``True``.
+
+ :rtype: return type of *tuple_factory*
+
+ :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``
+ class.
+
+ .. versionadded:: 16.2.0
+ """
+ attrs = fields(inst.__class__)
+ rv = []
+ retain = retain_collection_types # Very long. :/
+ for a in attrs:
+ v = getattr(inst, a.name)
+ if filter is not None and not filter(a, v):
+ continue
+ if recurse is True:
+ if has(v.__class__):
+ rv.append(astuple(v, recurse=True, filter=filter,
+ tuple_factory=tuple_factory,
+ retain_collection_types=retain))
+ elif isinstance(v, (tuple, list, set)):
+ cf = v.__class__ if retain is True else list
+ rv.append(cf([
+ astuple(j, recurse=True, filter=filter,
+ tuple_factory=tuple_factory,
+ retain_collection_types=retain)
+ if has(j.__class__) else j
+ for j in v
+ ]))
+ elif isinstance(v, dict):
+ df = v.__class__ if retain is True else dict
+ rv.append(df(
+ (
+ astuple(
+ kk,
+ tuple_factory=tuple_factory,
+ retain_collection_types=retain
+ ) if has(kk.__class__) else kk,
+ astuple(
+ vv,
+ tuple_factory=tuple_factory,
+ retain_collection_types=retain
+ ) if has(vv.__class__) else vv
+ )
+ for kk, vv in iteritems(v)))
+ else:
+ rv.append(v)
+ else:
+ rv.append(v)
+ return rv if tuple_factory is list else tuple_factory(rv)
+
+
+def has(cls):
+ """
+ Check whether *cls* is a class with ``attrs`` attributes.
+
+ :param type cls: Class to introspect.
+ :raise TypeError: If *cls* is not a class.
+
+ :rtype: :class:`bool`
+ """
+ return getattr(cls, "__attrs_attrs__", None) is not None
+
+
+def assoc(inst, **changes):
+ """
+ Copy *inst* and apply *changes*.
+
+ :param inst: Instance of a class with ``attrs`` attributes.
+ :param changes: Keyword changes in the new copy.
+
+ :return: A copy of inst with *changes* incorporated.
+
+ :raise attr.exceptions.AttrsAttributeNotFoundError: If *attr_name* couldn't
+ be found on *cls*.
+ :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``
+ class.
+
+ .. deprecated:: 17.1.0
+ Use :func:`evolve` instead.
+ """
+ import warnings
+ warnings.warn("assoc is deprecated and will be removed after 2018/01.",
+ DeprecationWarning, stacklevel=2)
+ new = copy.copy(inst)
+ attrs = fields(inst.__class__)
+ for k, v in iteritems(changes):
+ a = getattr(attrs, k, NOTHING)
+ if a is NOTHING:
+ raise AttrsAttributeNotFoundError(
+ "{k} is not an attrs attribute on {cl}."
+ .format(k=k, cl=new.__class__)
+ )
+ _obj_setattr(new, k, v)
+ return new
+
+
+def evolve(inst, **changes):
+ """
+ Create a new instance, based on *inst* with *changes* applied.
+
+ :param inst: Instance of a class with ``attrs`` attributes.
+ :param changes: Keyword changes in the new copy.
+
+ :return: A copy of inst with *changes* incorporated.
+
+ :raise TypeError: If *attr_name* couldn't be found in the class
+ ``__init__``.
+ :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``
+ class.
+
+ .. versionadded:: 17.1.0
+ """
+ cls = inst.__class__
+ attrs = fields(cls)
+ for a in attrs:
+ if not a.init:
+ continue
+ attr_name = a.name # To deal with private attributes.
+ init_name = attr_name if attr_name[0] != "_" else attr_name[1:]
+ if init_name not in changes:
+ changes[init_name] = getattr(inst, attr_name)
+ return cls(**changes)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/_make.py b/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/_make.py
new file mode 100644
index 00000000000..31c5f94ce38
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/_make.py
@@ -0,0 +1,1395 @@
+from __future__ import absolute_import, division, print_function
+
+import hashlib
+import linecache
+import sys
+
+from operator import itemgetter
+
+from . import _config
+from ._compat import PY2, isclass, iteritems, metadata_proxy, set_closure_cell
+from .exceptions import (
+ DefaultAlreadySetError, FrozenInstanceError, NotAnAttrsClassError,
+ UnannotatedAttributeError
+)
+
+
+# This is used at least twice, so cache it here.
+_obj_setattr = object.__setattr__
+_init_convert_pat = "__attr_convert_{}"
+_init_factory_pat = "__attr_factory_{}"
+_tuple_property_pat = " {attr_name} = property(itemgetter({index}))"
+_empty_metadata_singleton = metadata_proxy({})
+
+
+class _Nothing(object):
+ """
+ Sentinel class to indicate the lack of a value when ``None`` is ambiguous.
+
+ All instances of `_Nothing` are equal.
+ """
+ def __copy__(self):
+ return self
+
+ def __deepcopy__(self, _):
+ return self
+
+ def __eq__(self, other):
+ return other.__class__ == _Nothing
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __repr__(self):
+ return "NOTHING"
+
+ def __hash__(self):
+ return 0xdeadbeef
+
+
+NOTHING = _Nothing()
+"""
+Sentinel to indicate the lack of a value when ``None`` is ambiguous.
+"""
+
+
+def attrib(default=NOTHING, validator=None,
+ repr=True, cmp=True, hash=None, init=True,
+ convert=None, metadata={}, type=None):
+ """
+ Create a new attribute on a class.
+
+ .. warning::
+
+ Does *not* do anything unless the class is also decorated with
+ :func:`attr.s`!
+
+ :param default: A value that is used if an ``attrs``-generated ``__init__``
+ is used and no value is passed while instantiating or the attribute is
+ excluded using ``init=False``.
+
+ If the value is an instance of :class:`Factory`, its callable will be
+ used to construct a new value (useful for mutable data types like lists
+ or dicts).
+
+ If a default is not set (or set manually to ``attr.NOTHING``), a value
+ *must* be supplied when instantiating; otherwise a :exc:`TypeError`
+ will be raised.
+
+ The default can also be set using decorator notation as shown below.
+
+ :type default: Any value.
+
+ :param validator: :func:`callable` that is called by ``attrs``-generated
+ ``__init__`` methods after the instance has been initialized. They
+ receive the initialized instance, the :class:`Attribute`, and the
+ passed value.
+
+ The return value is *not* inspected so the validator has to throw an
+ exception itself.
+
+ If a ``list`` is passed, its items are treated as validators and must
+ all pass.
+
+ Validators can be globally disabled and re-enabled using
+ :func:`get_run_validators`.
+
+ The validator can also be set using decorator notation as shown below.
+
+ :type validator: ``callable`` or a ``list`` of ``callable``\ s.
+
+ :param bool repr: Include this attribute in the generated ``__repr__``
+ method.
+ :param bool cmp: Include this attribute in the generated comparison methods
+ (``__eq__`` et al).
+ :param hash: Include this attribute in the generated ``__hash__``
+ method. If ``None`` (default), mirror *cmp*'s value. This is the
+ correct behavior according the Python spec. Setting this value to
+ anything else than ``None`` is *discouraged*.
+ :type hash: ``bool`` or ``None``
+ :param bool init: Include this attribute in the generated ``__init__``
+ method. It is possible to set this to ``False`` and set a default
+ value. In that case this attributed is unconditionally initialized
+ with the specified default value or factory.
+ :param callable convert: :func:`callable` that is called by
+ ``attrs``-generated ``__init__`` methods to convert attribute's value
+ to the desired format. It is given the passed-in value, and the
+ returned value will be used as the new value of the attribute. The
+ value is converted before being passed to the validator, if any.
+ :param metadata: An arbitrary mapping, to be used by third-party
+ components. See :ref:`extending_metadata`.
+ :param type: The type of the attribute. In Python 3.6 or greater, the
+ preferred method to specify the type is using a variable annotation
+ (see `PEP 526 <https://www.python.org/dev/peps/pep-0526/>`_).
+ This argument is provided for backward compatibility.
+ Regardless of the approach used, the type will be stored on
+ ``Attribute.type``.
+
+ .. versionchanged:: 17.1.0 *validator* can be a ``list`` now.
+ .. versionchanged:: 17.1.0
+ *hash* is ``None`` and therefore mirrors *cmp* by default.
+ .. versionadded:: 17.3.0 *type*
+ """
+ if hash is not None and hash is not True and hash is not False:
+ raise TypeError(
+ "Invalid value for hash. Must be True, False, or None."
+ )
+ return _CountingAttr(
+ default=default,
+ validator=validator,
+ repr=repr,
+ cmp=cmp,
+ hash=hash,
+ init=init,
+ convert=convert,
+ metadata=metadata,
+ type=type,
+ )
+
+
+def _make_attr_tuple_class(cls_name, attr_names):
+ """
+ Create a tuple subclass to hold `Attribute`s for an `attrs` class.
+
+ The subclass is a bare tuple with properties for names.
+
+ class MyClassAttributes(tuple):
+ __slots__ = ()
+ x = property(itemgetter(0))
+ """
+ attr_class_name = "{}Attributes".format(cls_name)
+ attr_class_template = [
+ "class {}(tuple):".format(attr_class_name),
+ " __slots__ = ()",
+ ]
+ if attr_names:
+ for i, attr_name in enumerate(attr_names):
+ attr_class_template.append(_tuple_property_pat.format(
+ index=i,
+ attr_name=attr_name,
+ ))
+ else:
+ attr_class_template.append(" pass")
+ globs = {"itemgetter": itemgetter}
+ eval(compile("\n".join(attr_class_template), "", "exec"), globs)
+ return globs[attr_class_name]
+
+
+# Tuple class for extracted attributes from a class definition.
+# `super_attrs` is a subset of `attrs`.
+_Attributes = _make_attr_tuple_class("_Attributes", [
+ "attrs", # all attributes to build dunder methods for
+ "super_attrs", # attributes that have been inherited from super classes
+])
+
+
+def _is_class_var(annot):
+ """
+ Check whether *annot* is a typing.ClassVar.
+
+ The implementation is gross but importing `typing` is slow and there are
+ discussions to remove it from the stdlib alltogether.
+ """
+ return str(annot).startswith("typing.ClassVar")
+
+
+def _get_annotations(cls):
+ """
+ Get annotations for *cls*.
+ """
+ anns = getattr(cls, "__annotations__", None)
+ if anns is None:
+ return {}
+
+ # Verify that the annotations aren't merely inherited.
+ for super_cls in cls.__mro__[1:]:
+ if anns is getattr(super_cls, "__annotations__", None):
+ return {}
+
+ return anns
+
+
+def _transform_attrs(cls, these, auto_attribs):
+ """
+ Transform all `_CountingAttr`s on a class into `Attribute`s.
+
+ If *these* is passed, use that and don't look for them on the class.
+
+ Return an `_Attributes`.
+ """
+ cd = cls.__dict__
+ anns = _get_annotations(cls)
+
+ if these is not None:
+ ca_list = sorted((
+ (name, ca)
+ for name, ca
+ in iteritems(these)
+ ), key=lambda e: e[1].counter)
+ elif auto_attribs is True:
+ ca_names = {
+ name
+ for name, attr
+ in cd.items()
+ if isinstance(attr, _CountingAttr)
+ }
+ ca_list = []
+ annot_names = set()
+ for attr_name, type in anns.items():
+ if _is_class_var(type):
+ continue
+ annot_names.add(attr_name)
+ a = cd.get(attr_name, NOTHING)
+ if not isinstance(a, _CountingAttr):
+ if a is NOTHING:
+ a = attrib()
+ else:
+ a = attrib(default=a)
+ ca_list.append((attr_name, a))
+
+ unannotated = ca_names - annot_names
+ if len(unannotated) > 0:
+ raise UnannotatedAttributeError(
+ "The following `attr.ib`s lack a type annotation: " +
+ ", ".join(sorted(
+ unannotated,
+ key=lambda n: cd.get(n).counter
+ )) + "."
+ )
+ else:
+ ca_list = sorted((
+ (name, attr)
+ for name, attr
+ in cd.items()
+ if isinstance(attr, _CountingAttr)
+ ), key=lambda e: e[1].counter)
+
+ non_super_attrs = [
+ Attribute.from_counting_attr(
+ name=attr_name,
+ ca=ca,
+ type=anns.get(attr_name),
+ )
+ for attr_name, ca
+ in ca_list
+ ]
+
+ # Walk *down* the MRO for attributes. While doing so, we collect the names
+ # of attributes we've seen in `take_attr_names` and ignore their
+ # redefinitions deeper in the hierarchy.
+ super_attrs = []
+ taken_attr_names = {a.name: a for a in non_super_attrs}
+ for super_cls in cls.__mro__[1:-1]:
+ sub_attrs = getattr(super_cls, "__attrs_attrs__", None)
+ if sub_attrs is not None:
+ # We iterate over sub_attrs backwards so we can reverse the whole
+ # list in the end and get all attributes in the order they have
+ # been defined.
+ for a in reversed(sub_attrs):
+ prev_a = taken_attr_names.get(a.name)
+ if prev_a is None:
+ super_attrs.append(a)
+ taken_attr_names[a.name] = a
+ elif prev_a == a:
+ # This happens thru multiple inheritance. We don't want
+ # to favor attributes that are further down in the tree
+ # so we move them to the back.
+ super_attrs.remove(a)
+ super_attrs.append(a)
+
+ # Now reverse the list, such that the attributes are sorted by *descending*
+ # age. IOW: the oldest attribute definition is at the head of the list.
+ super_attrs.reverse()
+
+ attr_names = [a.name for a in super_attrs + non_super_attrs]
+
+ AttrsClass = _make_attr_tuple_class(cls.__name__, attr_names)
+
+ attrs = AttrsClass(
+ super_attrs + [
+ Attribute.from_counting_attr(
+ name=attr_name,
+ ca=ca,
+ type=anns.get(attr_name)
+ )
+ for attr_name, ca
+ in ca_list
+ ]
+ )
+
+ had_default = False
+ for a in attrs:
+ if had_default is True and a.default is NOTHING and a.init is True:
+ raise ValueError(
+ "No mandatory attributes allowed after an attribute with a "
+ "default value or factory. Attribute in question: {a!r}"
+ .format(a=a)
+ )
+ elif had_default is False and \
+ a.default is not NOTHING and \
+ a.init is not False:
+ had_default = True
+
+ return _Attributes((attrs, super_attrs))
+
+
+def _frozen_setattrs(self, name, value):
+ """
+ Attached to frozen classes as __setattr__.
+ """
+ raise FrozenInstanceError()
+
+
+def _frozen_delattrs(self, name):
+ """
+ Attached to frozen classes as __delattr__.
+ """
+ raise FrozenInstanceError()
+
+
+class _ClassBuilder(object):
+ """
+ Iteratively build *one* class.
+ """
+ __slots__ = (
+ "_cls", "_cls_dict", "_attrs", "_super_names", "_attr_names", "_slots",
+ "_frozen", "_has_post_init",
+ )
+
+ def __init__(self, cls, these, slots, frozen, auto_attribs):
+ attrs, super_attrs = _transform_attrs(cls, these, auto_attribs)
+
+ self._cls = cls
+ self._cls_dict = dict(cls.__dict__) if slots else {}
+ self._attrs = attrs
+ self._super_names = set(a.name for a in super_attrs)
+ self._attr_names = tuple(a.name for a in attrs)
+ self._slots = slots
+ self._frozen = frozen or _has_frozen_superclass(cls)
+ self._has_post_init = bool(getattr(cls, "__attrs_post_init__", False))
+
+ self._cls_dict["__attrs_attrs__"] = self._attrs
+
+ if frozen:
+ self._cls_dict["__setattr__"] = _frozen_setattrs
+ self._cls_dict["__delattr__"] = _frozen_delattrs
+
+ def __repr__(self):
+ return "<_ClassBuilder(cls={cls})>".format(cls=self._cls.__name__)
+
+ def build_class(self):
+ """
+ Finalize class based on the accumulated configuration.
+
+ Builder cannot be used anymore after calling this method.
+ """
+ if self._slots is True:
+ return self._create_slots_class()
+ else:
+ return self._patch_original_class()
+
+ def _patch_original_class(self):
+ """
+ Apply accumulated methods and return the class.
+ """
+ cls = self._cls
+ super_names = self._super_names
+
+ # Clean class of attribute definitions (`attr.ib()`s).
+ for name in self._attr_names:
+ if name not in super_names and \
+ getattr(cls, name, None) is not None:
+ delattr(cls, name)
+
+ # Attach our dunder methods.
+ for name, value in self._cls_dict.items():
+ setattr(cls, name, value)
+
+ return cls
+
+ def _create_slots_class(self):
+ """
+ Build and return a new class with a `__slots__` attribute.
+ """
+ super_names = self._super_names
+ cd = {
+ k: v
+ for k, v in iteritems(self._cls_dict)
+ if k not in tuple(self._attr_names) + ("__dict__",)
+ }
+
+ # We only add the names of attributes that aren't inherited.
+ # Settings __slots__ to inherited attributes wastes memory.
+ cd["__slots__"] = tuple(
+ name
+ for name in self._attr_names
+ if name not in super_names
+ )
+
+ qualname = getattr(self._cls, "__qualname__", None)
+ if qualname is not None:
+ cd["__qualname__"] = qualname
+
+ attr_names = tuple(self._attr_names)
+
+ def slots_getstate(self):
+ """
+ Automatically created by attrs.
+ """
+ return tuple(getattr(self, name) for name in attr_names)
+
+ def slots_setstate(self, state):
+ """
+ Automatically created by attrs.
+ """
+ __bound_setattr = _obj_setattr.__get__(self, Attribute)
+ for name, value in zip(attr_names, state):
+ __bound_setattr(name, value)
+
+ # slots and frozen require __getstate__/__setstate__ to work
+ cd["__getstate__"] = slots_getstate
+ cd["__setstate__"] = slots_setstate
+
+ # Create new class based on old class and our methods.
+ cls = type(self._cls)(
+ self._cls.__name__,
+ self._cls.__bases__,
+ cd,
+ )
+
+ # The following is a fix for
+ # https://github.com/python-attrs/attrs/issues/102. On Python 3,
+ # if a method mentions `__class__` or uses the no-arg super(), the
+ # compiler will bake a reference to the class in the method itself
+ # as `method.__closure__`. Since we replace the class with a
+ # clone, we rewrite these references so it keeps working.
+ for item in cls.__dict__.values():
+ if isinstance(item, (classmethod, staticmethod)):
+ # Class- and staticmethods hide their functions inside.
+ # These might need to be rewritten as well.
+ closure_cells = getattr(item.__func__, "__closure__", None)
+ else:
+ closure_cells = getattr(item, "__closure__", None)
+
+ if not closure_cells: # Catch None or the empty list.
+ continue
+ for cell in closure_cells:
+ if cell.cell_contents is self._cls:
+ set_closure_cell(cell, cls)
+
+ return cls
+
+ def add_repr(self, ns):
+ self._cls_dict["__repr__"] = _make_repr(self._attrs, ns=ns)
+ return self
+
+ def add_str(self):
+ repr_ = self._cls_dict.get("__repr__")
+ if repr_ is None:
+ raise ValueError(
+ "__str__ can only be generated if a __repr__ exists."
+ )
+
+ self._cls_dict["__str__"] = repr_
+ return self
+
+ def make_unhashable(self):
+ self._cls_dict["__hash__"] = None
+ return self
+
+ def add_hash(self):
+ self._cls_dict["__hash__"] = _make_hash(self._attrs)
+ return self
+
+ def add_init(self):
+ self._cls_dict["__init__"] = _make_init(
+ self._attrs,
+ self._has_post_init,
+ self._frozen,
+ )
+ return self
+
+ def add_cmp(self):
+ cd = self._cls_dict
+
+ cd["__eq__"], cd["__ne__"], cd["__lt__"], cd["__le__"], cd["__gt__"], \
+ cd["__ge__"] = _make_cmp(self._attrs)
+
+ return self
+
+
+def attrs(maybe_cls=None, these=None, repr_ns=None,
+ repr=True, cmp=True, hash=None, init=True,
+ slots=False, frozen=False, str=False, auto_attribs=False):
+ r"""
+ A class decorator that adds `dunder
+ <https://wiki.python.org/moin/DunderAlias>`_\ -methods according to the
+ specified attributes using :func:`attr.ib` or the *these* argument.
+
+ :param these: A dictionary of name to :func:`attr.ib` mappings. This is
+ useful to avoid the definition of your attributes within the class body
+ because you can't (e.g. if you want to add ``__repr__`` methods to
+ Django models) or don't want to.
+
+ If *these* is not ``None``, ``attrs`` will *not* search the class body
+ for attributes.
+
+ :type these: :class:`dict` of :class:`str` to :func:`attr.ib`
+
+ :param str repr_ns: When using nested classes, there's no way in Python 2
+ to automatically detect that. Therefore it's possible to set the
+ namespace explicitly for a more meaningful ``repr`` output.
+ :param bool repr: Create a ``__repr__`` method with a human readable
+ representation of ``attrs`` attributes..
+ :param bool str: Create a ``__str__`` method that is identical to
+ ``__repr__``. This is usually not necessary except for
+ :class:`Exception`\ s.
+ :param bool cmp: Create ``__eq__``, ``__ne__``, ``__lt__``, ``__le__``,
+ ``__gt__``, and ``__ge__`` methods that compare the class as if it were
+ a tuple of its ``attrs`` attributes. But the attributes are *only*
+ compared, if the type of both classes is *identical*!
+ :param hash: If ``None`` (default), the ``__hash__`` method is generated
+ according how *cmp* and *frozen* are set.
+
+ 1. If *both* are True, ``attrs`` will generate a ``__hash__`` for you.
+ 2. If *cmp* is True and *frozen* is False, ``__hash__`` will be set to
+ None, marking it unhashable (which it is).
+ 3. If *cmp* is False, ``__hash__`` will be left untouched meaning the
+ ``__hash__`` method of the superclass will be used (if superclass is
+ ``object``, this means it will fall back to id-based hashing.).
+
+ Although not recommended, you can decide for yourself and force
+ ``attrs`` to create one (e.g. if the class is immutable even though you
+ didn't freeze it programmatically) by passing ``True`` or not. Both of
+ these cases are rather special and should be used carefully.
+
+ See the `Python documentation \
+ <https://docs.python.org/3/reference/datamodel.html#object.__hash__>`_
+ and the `GitHub issue that led to the default behavior \
+ <https://github.com/python-attrs/attrs/issues/136>`_ for more details.
+ :type hash: ``bool`` or ``None``
+ :param bool init: Create a ``__init__`` method that initializes the
+ ``attrs`` attributes. Leading underscores are stripped for the
+ argument name. If a ``__attrs_post_init__`` method exists on the
+ class, it will be called after the class is fully initialized.
+ :param bool slots: Create a slots_-style class that's more
+ memory-efficient. See :ref:`slots` for further ramifications.
+ :param bool frozen: Make instances immutable after initialization. If
+ someone attempts to modify a frozen instance,
+ :exc:`attr.exceptions.FrozenInstanceError` is raised.
+
+ Please note:
+
+ 1. This is achieved by installing a custom ``__setattr__`` method
+ on your class so you can't implement an own one.
+
+ 2. True immutability is impossible in Python.
+
+ 3. This *does* have a minor a runtime performance :ref:`impact
+ <how-frozen>` when initializing new instances. In other words:
+ ``__init__`` is slightly slower with ``frozen=True``.
+
+ 4. If a class is frozen, you cannot modify ``self`` in
+ ``__attrs_post_init__`` or a self-written ``__init__``. You can
+ circumvent that limitation by using
+ ``object.__setattr__(self, "attribute_name", value)``.
+
+ .. _slots: https://docs.python.org/3/reference/datamodel.html#slots
+ :param bool auto_attribs: If True, collect `PEP 526`_-annotated attributes
+ (Python 3.6 and later only) from the class body.
+
+ In this case, you **must** annotate every field. If ``attrs``
+ encounters a field that is set to an :func:`attr.ib` but lacks a type
+ annotation, an :exc:`attr.exceptions.UnannotatedAttributeError` is
+ raised. Use ``field_name: typing.Any = attr.ib(...)`` if you don't
+ want to set a type.
+
+ If you assign a value to those attributes (e.g. ``x: int = 42``), that
+ value becomes the default value like if it were passed using
+ ``attr.ib(default=42)``. Passing an instance of :class:`Factory` also
+ works as expected.
+
+ Attributes annotated as :data:`typing.ClassVar` are **ignored**.
+
+ .. _`PEP 526`: https://www.python.org/dev/peps/pep-0526/
+
+ .. versionadded:: 16.0.0 *slots*
+ .. versionadded:: 16.1.0 *frozen*
+ .. versionadded:: 16.3.0 *str*, and support for ``__attrs_post_init__``.
+ .. versionchanged::
+ 17.1.0 *hash* supports ``None`` as value which is also the default
+ now.
+ .. versionadded:: 17.3.0 *auto_attribs*
+ """
+ def wrap(cls):
+ if getattr(cls, "__class__", None) is None:
+ raise TypeError("attrs only works with new-style classes.")
+
+ builder = _ClassBuilder(cls, these, slots, frozen, auto_attribs)
+
+ if repr is True:
+ builder.add_repr(repr_ns)
+ if str is True:
+ builder.add_str()
+ if cmp is True:
+ builder.add_cmp()
+
+ if hash is not True and hash is not False and hash is not None:
+ # Can't use `hash in` because 1 == True for example.
+ raise TypeError(
+ "Invalid value for hash. Must be True, False, or None."
+ )
+ elif hash is False or (hash is None and cmp is False):
+ pass
+ elif hash is True or (hash is None and cmp is True and frozen is True):
+ builder.add_hash()
+ else:
+ builder.make_unhashable()
+
+ if init is True:
+ builder.add_init()
+
+ return builder.build_class()
+
+ # maybe_cls's type depends on the usage of the decorator. It's a class
+ # if it's used as `@attrs` but ``None`` if used as `@attrs()`.
+ if maybe_cls is None:
+ return wrap
+ else:
+ return wrap(maybe_cls)
+
+
+_attrs = attrs
+"""
+Internal alias so we can use it in functions that take an argument called
+*attrs*.
+"""
+
+
+if PY2:
+ def _has_frozen_superclass(cls):
+ """
+ Check whether *cls* has a frozen ancestor by looking at its
+ __setattr__.
+ """
+ return (
+ getattr(
+ cls.__setattr__, "__module__", None
+ ) == _frozen_setattrs.__module__ and
+ cls.__setattr__.__name__ == _frozen_setattrs.__name__
+ )
+else:
+ def _has_frozen_superclass(cls):
+ """
+ Check whether *cls* has a frozen ancestor by looking at its
+ __setattr__.
+ """
+ return cls.__setattr__ == _frozen_setattrs
+
+
+def _attrs_to_tuple(obj, attrs):
+ """
+ Create a tuple of all values of *obj*'s *attrs*.
+ """
+ return tuple(getattr(obj, a.name) for a in attrs)
+
+
+def _make_hash(attrs):
+ attrs = tuple(
+ a
+ for a in attrs
+ if a.hash is True or (a.hash is None and a.cmp is True)
+ )
+
+ # We cache the generated init methods for the same kinds of attributes.
+ sha1 = hashlib.sha1()
+ sha1.update(repr(attrs).encode("utf-8"))
+ unique_filename = "<attrs generated hash %s>" % (sha1.hexdigest(),)
+ type_hash = hash(unique_filename)
+ lines = [
+ "def __hash__(self):",
+ " return hash((",
+ " %d," % (type_hash,),
+ ]
+ for a in attrs:
+ lines.append(" self.%s," % (a.name))
+
+ lines.append(" ))")
+
+ script = "\n".join(lines)
+ globs = {}
+ locs = {}
+ bytecode = compile(script, unique_filename, "exec")
+ eval(bytecode, globs, locs)
+
+ # In order of debuggers like PDB being able to step through the code,
+ # we add a fake linecache entry.
+ linecache.cache[unique_filename] = (
+ len(script),
+ None,
+ script.splitlines(True),
+ unique_filename,
+ )
+
+ return locs["__hash__"]
+
+
+def _add_hash(cls, attrs):
+ """
+ Add a hash method to *cls*.
+ """
+ cls.__hash__ = _make_hash(attrs)
+ return cls
+
+
+def _make_cmp(attrs):
+ attrs = [a for a in attrs if a.cmp]
+
+ def attrs_to_tuple(obj):
+ """
+ Save us some typing.
+ """
+ return _attrs_to_tuple(obj, attrs)
+
+ def eq(self, other):
+ """
+ Automatically created by attrs.
+ """
+ if other.__class__ is self.__class__:
+ return attrs_to_tuple(self) == attrs_to_tuple(other)
+ else:
+ return NotImplemented
+
+ def ne(self, other):
+ """
+ Automatically created by attrs.
+ """
+ result = eq(self, other)
+ if result is NotImplemented:
+ return NotImplemented
+ else:
+ return not result
+
+ def lt(self, other):
+ """
+ Automatically created by attrs.
+ """
+ if isinstance(other, self.__class__):
+ return attrs_to_tuple(self) < attrs_to_tuple(other)
+ else:
+ return NotImplemented
+
+ def le(self, other):
+ """
+ Automatically created by attrs.
+ """
+ if isinstance(other, self.__class__):
+ return attrs_to_tuple(self) <= attrs_to_tuple(other)
+ else:
+ return NotImplemented
+
+ def gt(self, other):
+ """
+ Automatically created by attrs.
+ """
+ if isinstance(other, self.__class__):
+ return attrs_to_tuple(self) > attrs_to_tuple(other)
+ else:
+ return NotImplemented
+
+ def ge(self, other):
+ """
+ Automatically created by attrs.
+ """
+ if isinstance(other, self.__class__):
+ return attrs_to_tuple(self) >= attrs_to_tuple(other)
+ else:
+ return NotImplemented
+
+ return eq, ne, lt, le, gt, ge
+
+
+def _add_cmp(cls, attrs=None):
+ """
+ Add comparison methods to *cls*.
+ """
+ if attrs is None:
+ attrs = cls.__attrs_attrs__
+
+ cls.__eq__, cls.__ne__, cls.__lt__, cls.__le__, cls.__gt__, cls.__ge__ = \
+ _make_cmp(attrs)
+
+ return cls
+
+
+def _make_repr(attrs, ns):
+ """
+ Make a repr method for *attr_names* adding *ns* to the full name.
+ """
+ attr_names = tuple(
+ a.name
+ for a in attrs
+ if a.repr
+ )
+
+ def repr_(self):
+ """
+ Automatically created by attrs.
+ """
+ real_cls = self.__class__
+ if ns is None:
+ qualname = getattr(real_cls, "__qualname__", None)
+ if qualname is not None:
+ class_name = qualname.rsplit(">.", 1)[-1]
+ else:
+ class_name = real_cls.__name__
+ else:
+ class_name = ns + "." + real_cls.__name__
+
+ return "{0}({1})".format(
+ class_name,
+ ", ".join(
+ name + "=" + repr(getattr(self, name))
+ for name in attr_names
+ )
+ )
+ return repr_
+
+
+def _add_repr(cls, ns=None, attrs=None):
+ """
+ Add a repr method to *cls*.
+ """
+ if attrs is None:
+ attrs = cls.__attrs_attrs__
+
+ repr_ = _make_repr(attrs, ns)
+ cls.__repr__ = repr_
+ return cls
+
+
+def _make_init(attrs, post_init, frozen):
+ attrs = [
+ a
+ for a in attrs
+ if a.init or a.default is not NOTHING
+ ]
+
+ # We cache the generated init methods for the same kinds of attributes.
+ sha1 = hashlib.sha1()
+ sha1.update(repr(attrs).encode("utf-8"))
+ unique_filename = "<attrs generated init {0}>".format(
+ sha1.hexdigest()
+ )
+
+ script, globs = _attrs_to_init_script(
+ attrs,
+ frozen,
+ post_init,
+ )
+ locs = {}
+ bytecode = compile(script, unique_filename, "exec")
+ attr_dict = dict((a.name, a) for a in attrs)
+ globs.update({
+ "NOTHING": NOTHING,
+ "attr_dict": attr_dict,
+ })
+ if frozen is True:
+ # Save the lookup overhead in __init__ if we need to circumvent
+ # immutability.
+ globs["_cached_setattr"] = _obj_setattr
+ eval(bytecode, globs, locs)
+
+ # In order of debuggers like PDB being able to step through the code,
+ # we add a fake linecache entry.
+ linecache.cache[unique_filename] = (
+ len(script),
+ None,
+ script.splitlines(True),
+ unique_filename,
+ )
+
+ return locs["__init__"]
+
+
+def _add_init(cls, frozen):
+ """
+ Add a __init__ method to *cls*. If *frozen* is True, make it immutable.
+ """
+ cls.__init__ = _make_init(
+ cls.__attrs_attrs__,
+ getattr(cls, "__attrs_post_init__", False),
+ frozen,
+ )
+ return cls
+
+
+def fields(cls):
+ """
+ Returns the tuple of ``attrs`` attributes for a class.
+
+ The tuple also allows accessing the fields by their names (see below for
+ examples).
+
+ :param type cls: Class to introspect.
+
+ :raise TypeError: If *cls* is not a class.
+ :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs``
+ class.
+
+ :rtype: tuple (with name accessors) of :class:`attr.Attribute`
+
+ .. versionchanged:: 16.2.0 Returned tuple allows accessing the fields
+ by name.
+ """
+ if not isclass(cls):
+ raise TypeError("Passed object must be a class.")
+ attrs = getattr(cls, "__attrs_attrs__", None)
+ if attrs is None:
+ raise NotAnAttrsClassError(
+ "{cls!r} is not an attrs-decorated class.".format(cls=cls)
+ )
+ return attrs
+
+
+def validate(inst):
+ """
+ Validate all attributes on *inst* that have a validator.
+
+ Leaves all exceptions through.
+
+ :param inst: Instance of a class with ``attrs`` attributes.
+ """
+ if _config._run_validators is False:
+ return
+
+ for a in fields(inst.__class__):
+ v = a.validator
+ if v is not None:
+ v(inst, a, getattr(inst, a.name))
+
+
+def _attrs_to_init_script(attrs, frozen, post_init):
+ """
+ Return a script of an initializer for *attrs* and a dict of globals.
+
+ The globals are expected by the generated script.
+
+ If *frozen* is True, we cannot set the attributes directly so we use
+ a cached ``object.__setattr__``.
+ """
+ lines = []
+ if frozen is True:
+ lines.append(
+ # Circumvent the __setattr__ descriptor to save one lookup per
+ # assignment.
+ "_setattr = _cached_setattr.__get__(self, self.__class__)"
+ )
+
+ def fmt_setter(attr_name, value_var):
+ return "_setattr('%(attr_name)s', %(value_var)s)" % {
+ "attr_name": attr_name,
+ "value_var": value_var,
+ }
+
+ def fmt_setter_with_converter(attr_name, value_var):
+ conv_name = _init_convert_pat.format(attr_name)
+ return "_setattr('%(attr_name)s', %(conv)s(%(value_var)s))" % {
+ "attr_name": attr_name,
+ "value_var": value_var,
+ "conv": conv_name,
+ }
+ else:
+ def fmt_setter(attr_name, value):
+ return "self.%(attr_name)s = %(value)s" % {
+ "attr_name": attr_name,
+ "value": value,
+ }
+
+ def fmt_setter_with_converter(attr_name, value_var):
+ conv_name = _init_convert_pat.format(attr_name)
+ return "self.%(attr_name)s = %(conv)s(%(value_var)s)" % {
+ "attr_name": attr_name,
+ "value_var": value_var,
+ "conv": conv_name,
+ }
+
+ args = []
+ attrs_to_validate = []
+
+ # This is a dictionary of names to validator and converter callables.
+ # Injecting this into __init__ globals lets us avoid lookups.
+ names_for_globals = {}
+
+ for a in attrs:
+ if a.validator:
+ attrs_to_validate.append(a)
+ attr_name = a.name
+ arg_name = a.name.lstrip("_")
+ has_factory = isinstance(a.default, Factory)
+ if has_factory and a.default.takes_self:
+ maybe_self = "self"
+ else:
+ maybe_self = ""
+ if a.init is False:
+ if has_factory:
+ init_factory_name = _init_factory_pat.format(a.name)
+ if a.convert is not None:
+ lines.append(fmt_setter_with_converter(
+ attr_name,
+ init_factory_name + "({0})".format(maybe_self)))
+ conv_name = _init_convert_pat.format(a.name)
+ names_for_globals[conv_name] = a.convert
+ else:
+ lines.append(fmt_setter(
+ attr_name,
+ init_factory_name + "({0})".format(maybe_self)
+ ))
+ names_for_globals[init_factory_name] = a.default.factory
+ else:
+ if a.convert is not None:
+ lines.append(fmt_setter_with_converter(
+ attr_name,
+ "attr_dict['{attr_name}'].default"
+ .format(attr_name=attr_name)
+ ))
+ conv_name = _init_convert_pat.format(a.name)
+ names_for_globals[conv_name] = a.convert
+ else:
+ lines.append(fmt_setter(
+ attr_name,
+ "attr_dict['{attr_name}'].default"
+ .format(attr_name=attr_name)
+ ))
+ elif a.default is not NOTHING and not has_factory:
+ args.append(
+ "{arg_name}=attr_dict['{attr_name}'].default".format(
+ arg_name=arg_name,
+ attr_name=attr_name,
+ )
+ )
+ if a.convert is not None:
+ lines.append(fmt_setter_with_converter(attr_name, arg_name))
+ names_for_globals[_init_convert_pat.format(a.name)] = a.convert
+ else:
+ lines.append(fmt_setter(attr_name, arg_name))
+ elif has_factory:
+ args.append("{arg_name}=NOTHING".format(arg_name=arg_name))
+ lines.append("if {arg_name} is not NOTHING:"
+ .format(arg_name=arg_name))
+ init_factory_name = _init_factory_pat.format(a.name)
+ if a.convert is not None:
+ lines.append(" " + fmt_setter_with_converter(attr_name,
+ arg_name))
+ lines.append("else:")
+ lines.append(" " + fmt_setter_with_converter(
+ attr_name,
+ init_factory_name + "({0})".format(maybe_self)
+ ))
+ names_for_globals[_init_convert_pat.format(a.name)] = a.convert
+ else:
+ lines.append(" " + fmt_setter(attr_name, arg_name))
+ lines.append("else:")
+ lines.append(" " + fmt_setter(
+ attr_name,
+ init_factory_name + "({0})".format(maybe_self)
+ ))
+ names_for_globals[init_factory_name] = a.default.factory
+ else:
+ args.append(arg_name)
+ if a.convert is not None:
+ lines.append(fmt_setter_with_converter(attr_name, arg_name))
+ names_for_globals[_init_convert_pat.format(a.name)] = a.convert
+ else:
+ lines.append(fmt_setter(attr_name, arg_name))
+
+ if attrs_to_validate: # we can skip this if there are no validators.
+ names_for_globals["_config"] = _config
+ lines.append("if _config._run_validators is True:")
+ for a in attrs_to_validate:
+ val_name = "__attr_validator_{}".format(a.name)
+ attr_name = "__attr_{}".format(a.name)
+ lines.append(" {}(self, {}, self.{})".format(
+ val_name, attr_name, a.name))
+ names_for_globals[val_name] = a.validator
+ names_for_globals[attr_name] = a
+ if post_init:
+ lines.append("self.__attrs_post_init__()")
+
+ return """\
+def __init__(self, {args}):
+ {lines}
+""".format(
+ args=", ".join(args),
+ lines="\n ".join(lines) if lines else "pass",
+ ), names_for_globals
+
+
+class Attribute(object):
+ """
+ *Read-only* representation of an attribute.
+
+ :attribute name: The name of the attribute.
+
+ Plus *all* arguments of :func:`attr.ib`.
+ """
+ __slots__ = (
+ "name", "default", "validator", "repr", "cmp", "hash", "init",
+ "convert", "metadata", "type"
+ )
+
+ def __init__(self, name, default, validator, repr, cmp, hash, init,
+ convert=None, metadata=None, type=None):
+ # Cache this descriptor here to speed things up later.
+ bound_setattr = _obj_setattr.__get__(self, Attribute)
+
+ bound_setattr("name", name)
+ bound_setattr("default", default)
+ bound_setattr("validator", validator)
+ bound_setattr("repr", repr)
+ bound_setattr("cmp", cmp)
+ bound_setattr("hash", hash)
+ bound_setattr("init", init)
+ bound_setattr("convert", convert)
+ bound_setattr("metadata", (metadata_proxy(metadata) if metadata
+ else _empty_metadata_singleton))
+ bound_setattr("type", type)
+
+ def __setattr__(self, name, value):
+ raise FrozenInstanceError()
+
+ @classmethod
+ def from_counting_attr(cls, name, ca, type=None):
+ # type holds the annotated value. deal with conflicts:
+ if type is None:
+ type = ca.type
+ elif ca.type is not None:
+ raise ValueError(
+ "Type annotation and type argument cannot both be present"
+ )
+ inst_dict = {
+ k: getattr(ca, k)
+ for k
+ in Attribute.__slots__
+ if k not in (
+ "name", "validator", "default", "type"
+ ) # exclude methods
+ }
+ return cls(name=name, validator=ca._validator, default=ca._default,
+ type=type, **inst_dict)
+
+ # Don't use _add_pickle since fields(Attribute) doesn't work
+ def __getstate__(self):
+ """
+ Play nice with pickle.
+ """
+ return tuple(getattr(self, name) if name != "metadata"
+ else dict(self.metadata)
+ for name in self.__slots__)
+
+ def __setstate__(self, state):
+ """
+ Play nice with pickle.
+ """
+ bound_setattr = _obj_setattr.__get__(self, Attribute)
+ for name, value in zip(self.__slots__, state):
+ if name != "metadata":
+ bound_setattr(name, value)
+ else:
+ bound_setattr(name, metadata_proxy(value) if value else
+ _empty_metadata_singleton)
+
+
+_a = [Attribute(name=name, default=NOTHING, validator=None,
+ repr=True, cmp=True, hash=(name != "metadata"), init=True)
+ for name in Attribute.__slots__]
+
+Attribute = _add_hash(
+ _add_cmp(_add_repr(Attribute, attrs=_a), attrs=_a),
+ attrs=[a for a in _a if a.hash]
+)
+
+
+class _CountingAttr(object):
+ """
+ Intermediate representation of attributes that uses a counter to preserve
+ the order in which the attributes have been defined.
+
+ *Internal* data structure of the attrs library. Running into is most
+ likely the result of a bug like a forgotten `@attr.s` decorator.
+ """
+ __slots__ = ("counter", "_default", "repr", "cmp", "hash", "init",
+ "metadata", "_validator", "convert", "type")
+ __attrs_attrs__ = tuple(
+ Attribute(name=name, default=NOTHING, validator=None,
+ repr=True, cmp=True, hash=True, init=True)
+ for name
+ in ("counter", "_default", "repr", "cmp", "hash", "init",)
+ ) + (
+ Attribute(name="metadata", default=None, validator=None,
+ repr=True, cmp=True, hash=False, init=True),
+ )
+ cls_counter = 0
+
+ def __init__(self, default, validator, repr, cmp, hash, init, convert,
+ metadata, type):
+ _CountingAttr.cls_counter += 1
+ self.counter = _CountingAttr.cls_counter
+ self._default = default
+ # If validator is a list/tuple, wrap it using helper validator.
+ if validator and isinstance(validator, (list, tuple)):
+ self._validator = and_(*validator)
+ else:
+ self._validator = validator
+ self.repr = repr
+ self.cmp = cmp
+ self.hash = hash
+ self.init = init
+ self.convert = convert
+ self.metadata = metadata
+ self.type = type
+
+ def validator(self, meth):
+ """
+ Decorator that adds *meth* to the list of validators.
+
+ Returns *meth* unchanged.
+
+ .. versionadded:: 17.1.0
+ """
+ if self._validator is None:
+ self._validator = meth
+ else:
+ self._validator = and_(self._validator, meth)
+ return meth
+
+ def default(self, meth):
+ """
+ Decorator that allows to set the default for an attribute.
+
+ Returns *meth* unchanged.
+
+ :raises DefaultAlreadySetError: If default has been set before.
+
+ .. versionadded:: 17.1.0
+ """
+ if self._default is not NOTHING:
+ raise DefaultAlreadySetError()
+
+ self._default = Factory(meth, takes_self=True)
+
+ return meth
+
+
+_CountingAttr = _add_cmp(_add_repr(_CountingAttr))
+
+
+@attrs(slots=True, init=False, hash=True)
+class Factory(object):
+ """
+ Stores a factory callable.
+
+ If passed as the default value to :func:`attr.ib`, the factory is used to
+ generate a new value.
+
+ :param callable factory: A callable that takes either none or exactly one
+ mandatory positional argument depending on *takes_self*.
+ :param bool takes_self: Pass the partially initialized instance that is
+ being initialized as a positional argument.
+
+ .. versionadded:: 17.1.0 *takes_self*
+ """
+ factory = attrib()
+ takes_self = attrib()
+
+ def __init__(self, factory, takes_self=False):
+ """
+ `Factory` is part of the default machinery so if we want a default
+ value here, we have to implement it ourselves.
+ """
+ self.factory = factory
+ self.takes_self = takes_self
+
+
+def make_class(name, attrs, bases=(object,), **attributes_arguments):
+ """
+ A quick way to create a new class called *name* with *attrs*.
+
+ :param name: The name for the new class.
+ :type name: str
+
+ :param attrs: A list of names or a dictionary of mappings of names to
+ attributes.
+ :type attrs: :class:`list` or :class:`dict`
+
+ :param tuple bases: Classes that the new class will subclass.
+
+ :param attributes_arguments: Passed unmodified to :func:`attr.s`.
+
+ :return: A new class with *attrs*.
+ :rtype: type
+
+ .. versionadded:: 17.1.0 *bases*
+ """
+ if isinstance(attrs, dict):
+ cls_dict = attrs
+ elif isinstance(attrs, (list, tuple)):
+ cls_dict = dict((a, attrib()) for a in attrs)
+ else:
+ raise TypeError("attrs argument must be a dict or a list.")
+
+ post_init = cls_dict.pop("__attrs_post_init__", None)
+ type_ = type(
+ name,
+ bases,
+ {} if post_init is None else {"__attrs_post_init__": post_init}
+ )
+ # For pickling to work, the __module__ variable needs to be set to the
+ # frame where the class is created. Bypass this step in environments where
+ # sys._getframe is not defined (Jython for example) or sys._getframe is not
+ # defined for arguments greater than 0 (IronPython).
+ try:
+ type_.__module__ = sys._getframe(1).f_globals.get(
+ "__name__", "__main__",
+ )
+ except (AttributeError, ValueError):
+ pass
+
+ return _attrs(these=cls_dict, **attributes_arguments)(type_)
+
+
+# These are required by within this module so we define them here and merely
+# import into .validators.
+
+
+@attrs(slots=True, hash=True)
+class _AndValidator(object):
+ """
+ Compose many validators to a single one.
+ """
+ _validators = attrib()
+
+ def __call__(self, inst, attr, value):
+ for v in self._validators:
+ v(inst, attr, value)
+
+
+def and_(*validators):
+ """
+ A validator that composes multiple validators into one.
+
+ When called on a value, it runs all wrapped validators.
+
+ :param validators: Arbitrary number of validators.
+ :type validators: callables
+
+ .. versionadded:: 17.1.0
+ """
+ vals = []
+ for validator in validators:
+ vals.extend(
+ validator._validators if isinstance(validator, _AndValidator)
+ else [validator]
+ )
+
+ return _AndValidator(tuple(vals))
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/converters.py b/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/converters.py
new file mode 100644
index 00000000000..3b3bac92be5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/converters.py
@@ -0,0 +1,24 @@
+"""
+Commonly useful converters.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+
+def optional(converter):
+ """
+ A converter that allows an attribute to be optional. An optional attribute
+ is one which can be set to ``None``.
+
+ :param callable converter: the converter that is used for non-``None``
+ values.
+
+ .. versionadded:: 17.1.0
+ """
+
+ def optional_converter(val):
+ if val is None:
+ return None
+ return converter(val)
+
+ return optional_converter
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/exceptions.py b/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/exceptions.py
new file mode 100644
index 00000000000..f949f3c9c01
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/exceptions.py
@@ -0,0 +1,48 @@
+from __future__ import absolute_import, division, print_function
+
+
+class FrozenInstanceError(AttributeError):
+ """
+ A frozen/immutable instance has been attempted to be modified.
+
+ It mirrors the behavior of ``namedtuples`` by using the same error message
+ and subclassing :exc:`AttributeError`.
+
+ .. versionadded:: 16.1.0
+ """
+ msg = "can't set attribute"
+ args = [msg]
+
+
+class AttrsAttributeNotFoundError(ValueError):
+ """
+ An ``attrs`` function couldn't find an attribute that the user asked for.
+
+ .. versionadded:: 16.2.0
+ """
+
+
+class NotAnAttrsClassError(ValueError):
+ """
+ A non-``attrs`` class has been passed into an ``attrs`` function.
+
+ .. versionadded:: 16.2.0
+ """
+
+
+class DefaultAlreadySetError(RuntimeError):
+ """
+ A default has been set using ``attr.ib()`` and is attempted to be reset
+ using the decorator.
+
+ .. versionadded:: 17.1.0
+ """
+
+
+class UnannotatedAttributeError(RuntimeError):
+ """
+ A class with ``auto_attribs=True`` has an ``attr.ib()`` without a type
+ annotation.
+
+ .. versionadded:: 17.3.0
+ """
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/filters.py b/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/filters.py
new file mode 100644
index 00000000000..d1bad35e363
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/filters.py
@@ -0,0 +1,52 @@
+"""
+Commonly useful filters for :func:`attr.asdict`.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+from ._compat import isclass
+from ._make import Attribute
+
+
+def _split_what(what):
+ """
+ Returns a tuple of `frozenset`s of classes and attributes.
+ """
+ return (
+ frozenset(cls for cls in what if isclass(cls)),
+ frozenset(cls for cls in what if isinstance(cls, Attribute)),
+ )
+
+
+def include(*what):
+ """
+ Whitelist *what*.
+
+ :param what: What to whitelist.
+ :type what: :class:`list` of :class:`type` or :class:`attr.Attribute`\ s
+
+ :rtype: :class:`callable`
+ """
+ cls, attrs = _split_what(what)
+
+ def include_(attribute, value):
+ return value.__class__ in cls or attribute in attrs
+
+ return include_
+
+
+def exclude(*what):
+ """
+ Blacklist *what*.
+
+ :param what: What to blacklist.
+ :type what: :class:`list` of classes or :class:`attr.Attribute`\ s.
+
+ :rtype: :class:`callable`
+ """
+ cls, attrs = _split_what(what)
+
+ def exclude_(attribute, value):
+ return value.__class__ not in cls and attribute not in attrs
+
+ return exclude_
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/validators.py b/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/validators.py
new file mode 100644
index 00000000000..f8892fcdfe4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/src/attr/validators.py
@@ -0,0 +1,166 @@
+"""
+Commonly useful validators.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+from ._make import _AndValidator, and_, attrib, attrs
+
+
+__all__ = [
+ "and_",
+ "in_",
+ "instance_of",
+ "optional",
+ "provides",
+]
+
+
+@attrs(repr=False, slots=True, hash=True)
+class _InstanceOfValidator(object):
+ type = attrib()
+
+ def __call__(self, inst, attr, value):
+ """
+ We use a callable class to be able to change the ``__repr__``.
+ """
+ if not isinstance(value, self.type):
+ raise TypeError(
+ "'{name}' must be {type!r} (got {value!r} that is a "
+ "{actual!r})."
+ .format(name=attr.name, type=self.type,
+ actual=value.__class__, value=value),
+ attr, self.type, value,
+ )
+
+ def __repr__(self):
+ return (
+ "<instance_of validator for type {type!r}>"
+ .format(type=self.type)
+ )
+
+
+def instance_of(type):
+ """
+ A validator that raises a :exc:`TypeError` if the initializer is called
+ with a wrong type for this particular attribute (checks are performed using
+ :func:`isinstance` therefore it's also valid to pass a tuple of types).
+
+ :param type: The type to check for.
+ :type type: type or tuple of types
+
+ :raises TypeError: With a human readable error message, the attribute
+ (of type :class:`attr.Attribute`), the expected type, and the value it
+ got.
+ """
+ return _InstanceOfValidator(type)
+
+
+@attrs(repr=False, slots=True, hash=True)
+class _ProvidesValidator(object):
+ interface = attrib()
+
+ def __call__(self, inst, attr, value):
+ """
+ We use a callable class to be able to change the ``__repr__``.
+ """
+ if not self.interface.providedBy(value):
+ raise TypeError(
+ "'{name}' must provide {interface!r} which {value!r} "
+ "doesn't."
+ .format(name=attr.name, interface=self.interface, value=value),
+ attr, self.interface, value,
+ )
+
+ def __repr__(self):
+ return (
+ "<provides validator for interface {interface!r}>"
+ .format(interface=self.interface)
+ )
+
+
+def provides(interface):
+ """
+ A validator that raises a :exc:`TypeError` if the initializer is called
+ with an object that does not provide the requested *interface* (checks are
+ performed using ``interface.providedBy(value)`` (see `zope.interface
+ <https://zopeinterface.readthedocs.io/en/latest/>`_).
+
+ :param zope.interface.Interface interface: The interface to check for.
+
+ :raises TypeError: With a human readable error message, the attribute
+ (of type :class:`attr.Attribute`), the expected interface, and the
+ value it got.
+ """
+ return _ProvidesValidator(interface)
+
+
+@attrs(repr=False, slots=True, hash=True)
+class _OptionalValidator(object):
+ validator = attrib()
+
+ def __call__(self, inst, attr, value):
+ if value is None:
+ return
+
+ self.validator(inst, attr, value)
+
+ def __repr__(self):
+ return (
+ "<optional validator for {what} or None>"
+ .format(what=repr(self.validator))
+ )
+
+
+def optional(validator):
+ """
+ A validator that makes an attribute optional. An optional attribute is one
+ which can be set to ``None`` in addition to satisfying the requirements of
+ the sub-validator.
+
+ :param validator: A validator (or a list of validators) that is used for
+ non-``None`` values.
+ :type validator: callable or :class:`list` of callables.
+
+ .. versionadded:: 15.1.0
+ .. versionchanged:: 17.1.0 *validator* can be a list of validators.
+ """
+ if isinstance(validator, list):
+ return _OptionalValidator(_AndValidator(validator))
+ return _OptionalValidator(validator)
+
+
+@attrs(repr=False, slots=True, hash=True)
+class _InValidator(object):
+ options = attrib()
+
+ def __call__(self, inst, attr, value):
+ if value not in self.options:
+ raise ValueError(
+ "'{name}' must be in {options!r} (got {value!r})"
+ .format(name=attr.name, options=self.options, value=value)
+ )
+
+ def __repr__(self):
+ return (
+ "<in_ validator with options {options!r}>"
+ .format(options=self.options)
+ )
+
+
+def in_(options):
+ """
+ A validator that raises a :exc:`ValueError` if the initializer is called
+ with a value that does not belong in the options provided. The check is
+ performed using ``value in options``.
+
+ :param options: Allowed options.
+ :type options: list, tuple, :class:`enum.Enum`, ...
+
+ :raises ValueError: With a human readable error message, the attribute (of
+ type :class:`attr.Attribute`), the expected options, and the value it
+ got.
+
+ .. versionadded:: 17.1.0
+ """
+ return _InValidator(options)
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/retrieval/__init__.py b/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/__init__.py
index e69de29bb2d..e69de29bb2d 100644
--- a/tests/wpt/web-platform-tests/webdriver/tests/retrieval/__init__.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/__init__.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_annotations.py b/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_annotations.py
new file mode 100644
index 00000000000..602f21bd5e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_annotations.py
@@ -0,0 +1,156 @@
+"""
+Tests for PEP-526 type annotations.
+
+Python 3.6+ only.
+"""
+
+import types
+import typing
+
+import pytest
+
+import attr
+
+from attr.exceptions import UnannotatedAttributeError
+
+
+class TestAnnotations:
+ """
+ Tests for types derived from variable annotations (PEP-526).
+ """
+
+ def test_basic_annotations(self):
+ """
+ Sets the `Attribute.type` attr from basic type annotations.
+ """
+ @attr.s
+ class C:
+ x: int = attr.ib()
+ y = attr.ib(type=str)
+ z = attr.ib()
+
+ assert int is attr.fields(C).x.type
+ assert str is attr.fields(C).y.type
+ assert None is attr.fields(C).z.type
+
+ def test_catches_basic_type_conflict(self):
+ """
+ Raises ValueError if type is specified both ways.
+ """
+ with pytest.raises(ValueError) as e:
+ @attr.s
+ class C:
+ x: int = attr.ib(type=int)
+
+ assert (
+ "Type annotation and type argument cannot both be present",
+ ) == e.value.args
+
+ def test_typing_annotations(self):
+ """
+ Sets the `Attribute.type` attr from typing annotations.
+ """
+ @attr.s
+ class C:
+ x: typing.List[int] = attr.ib()
+ y = attr.ib(type=typing.Optional[str])
+
+ assert typing.List[int] is attr.fields(C).x.type
+ assert typing.Optional[str] is attr.fields(C).y.type
+
+ def test_only_attrs_annotations_collected(self):
+ """
+ Annotations that aren't set to an attr.ib are ignored.
+ """
+ @attr.s
+ class C:
+ x: typing.List[int] = attr.ib()
+ y: int
+
+ assert 1 == len(attr.fields(C))
+
+ @pytest.mark.parametrize("slots", [True, False])
+ def test_auto_attribs(self, slots):
+ """
+ If *auto_attribs* is True, bare annotations are collected too.
+ Defaults work and class variables are ignored.
+ """
+ @attr.s(auto_attribs=True, slots=slots)
+ class C:
+ cls_var: typing.ClassVar[int] = 23
+ a: int
+ x: typing.List[int] = attr.Factory(list)
+ y: int = 2
+ z: int = attr.ib(default=3)
+ foo: typing.Any = None
+
+ i = C(42)
+ assert "C(a=42, x=[], y=2, z=3, foo=None)" == repr(i)
+
+ attr_names = set(a.name for a in C.__attrs_attrs__)
+ assert "a" in attr_names # just double check that the set works
+ assert "cls_var" not in attr_names
+
+ assert int == attr.fields(C).a.type
+
+ assert attr.Factory(list) == attr.fields(C).x.default
+ assert typing.List[int] == attr.fields(C).x.type
+
+ assert int == attr.fields(C).y.type
+ assert 2 == attr.fields(C).y.default
+
+ assert int == attr.fields(C).z.type
+
+ assert typing.Any == attr.fields(C).foo.type
+
+ # Class body is clean.
+ if slots is False:
+ with pytest.raises(AttributeError):
+ C.y
+
+ assert 2 == i.y
+ else:
+ assert isinstance(C.y, types.MemberDescriptorType)
+
+ i.y = 23
+ assert 23 == i.y
+
+ @pytest.mark.parametrize("slots", [True, False])
+ def test_auto_attribs_unannotated(self, slots):
+ """
+ Unannotated `attr.ib`s raise an error.
+ """
+ with pytest.raises(UnannotatedAttributeError) as e:
+ @attr.s(slots=slots, auto_attribs=True)
+ class C:
+ v = attr.ib()
+ x: int
+ y = attr.ib()
+ z: str
+
+ assert (
+ "The following `attr.ib`s lack a type annotation: v, y.",
+ ) == e.value.args
+
+ @pytest.mark.parametrize("slots", [True, False])
+ def test_auto_attribs_subclassing(self, slots):
+ """
+ Attributes from super classes are inherited, it doesn't matter if the
+ subclass has annotations or not.
+
+ Ref #291
+ """
+ @attr.s(slots=slots, auto_attribs=True)
+ class A:
+ a: int = 1
+
+ @attr.s(slots=slots, auto_attribs=True)
+ class B(A):
+ b: int = 2
+
+ @attr.s(slots=slots, auto_attribs=True)
+ class C(A):
+ pass
+
+ assert "B(a=1, b=2)" == repr(B())
+ assert "C(a=1)" == repr(C())
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_config.py b/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_config.py
new file mode 100644
index 00000000000..287be03a597
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_config.py
@@ -0,0 +1,43 @@
+"""
+Tests for `attr._config`.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+import pytest
+
+from attr import _config
+
+
+class TestConfig(object):
+ def test_default(self):
+ """
+ Run validators by default.
+ """
+ assert True is _config._run_validators
+
+ def test_set_run_validators(self):
+ """
+ Sets `_run_validators`.
+ """
+ _config.set_run_validators(False)
+ assert False is _config._run_validators
+ _config.set_run_validators(True)
+ assert True is _config._run_validators
+
+ def test_get_run_validators(self):
+ """
+ Returns `_run_validators`.
+ """
+ _config._run_validators = False
+ assert _config._run_validators is _config.get_run_validators()
+ _config._run_validators = True
+ assert _config._run_validators is _config.get_run_validators()
+
+ def test_wrong_type(self):
+ """
+ Passing anything else than a boolean raises TypeError.
+ """
+ with pytest.raises(TypeError) as e:
+ _config.set_run_validators("False")
+ assert "'run' must be bool." == e.value.args[0]
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_converters.py b/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_converters.py
new file mode 100644
index 00000000000..daf39d8ace0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_converters.py
@@ -0,0 +1,36 @@
+"""
+Tests for `attr.converters`.
+"""
+
+from __future__ import absolute_import
+
+import pytest
+
+from attr.converters import optional
+
+
+class TestOptional(object):
+ """
+ Tests for `optional`.
+ """
+ def test_success_with_type(self):
+ """
+ Wrapped converter is used as usual if value is not None.
+ """
+ c = optional(int)
+ assert c("42") == 42
+
+ def test_success_with_none(self):
+ """
+ Nothing happens if None.
+ """
+ c = optional(int)
+ assert c(None) is None
+
+ def test_fail(self):
+ """
+ Propagates the underlying conversion error when conversion fails.
+ """
+ c = optional(int)
+ with pytest.raises(ValueError):
+ c("not_an_int")
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_dark_magic.py b/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_dark_magic.py
new file mode 100644
index 00000000000..bc6665cf5fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_dark_magic.py
@@ -0,0 +1,382 @@
+"""
+End-to-end tests.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+import pickle
+
+import pytest
+import six
+
+from hypothesis import given
+from hypothesis.strategies import booleans
+
+import attr
+
+from attr._compat import TYPE
+from attr._make import NOTHING, Attribute
+from attr.exceptions import FrozenInstanceError
+
+
+@attr.s
+class C1(object):
+ x = attr.ib(validator=attr.validators.instance_of(int))
+ y = attr.ib()
+
+
+@attr.s(slots=True)
+class C1Slots(object):
+ x = attr.ib(validator=attr.validators.instance_of(int))
+ y = attr.ib()
+
+
+foo = None
+
+
+@attr.s()
+class C2(object):
+ x = attr.ib(default=foo)
+ y = attr.ib(default=attr.Factory(list))
+
+
+@attr.s(slots=True)
+class C2Slots(object):
+ x = attr.ib(default=foo)
+ y = attr.ib(default=attr.Factory(list))
+
+
+@attr.s
+class Super(object):
+ x = attr.ib()
+
+ def meth(self):
+ return self.x
+
+
+@attr.s(slots=True)
+class SuperSlots(object):
+ x = attr.ib()
+
+ def meth(self):
+ return self.x
+
+
+@attr.s
+class Sub(Super):
+ y = attr.ib()
+
+
+@attr.s(slots=True)
+class SubSlots(SuperSlots):
+ y = attr.ib()
+
+
+@attr.s(frozen=True, slots=True)
+class Frozen(object):
+ x = attr.ib()
+
+
+@attr.s
+class SubFrozen(Frozen):
+ y = attr.ib()
+
+
+@attr.s(frozen=True, slots=False)
+class FrozenNoSlots(object):
+ x = attr.ib()
+
+
+class Meta(type):
+ pass
+
+
+@attr.s
+@six.add_metaclass(Meta)
+class WithMeta(object):
+ pass
+
+
+@attr.s(slots=True)
+@six.add_metaclass(Meta)
+class WithMetaSlots(object):
+ pass
+
+
+FromMakeClass = attr.make_class("FromMakeClass", ["x"])
+
+
+class TestDarkMagic(object):
+ """
+ Integration tests.
+ """
+ @pytest.mark.parametrize("cls", [C2, C2Slots])
+ def test_fields(self, cls):
+ """
+ `attr.fields` works.
+ """
+ assert (
+ Attribute(name="x", default=foo, validator=None,
+ repr=True, cmp=True, hash=None, init=True),
+ Attribute(name="y", default=attr.Factory(list), validator=None,
+ repr=True, cmp=True, hash=None, init=True),
+ ) == attr.fields(cls)
+
+ @pytest.mark.parametrize("cls", [C1, C1Slots])
+ def test_asdict(self, cls):
+ """
+ `attr.asdict` works.
+ """
+ assert {
+ "x": 1,
+ "y": 2,
+ } == attr.asdict(cls(x=1, y=2))
+
+ @pytest.mark.parametrize("cls", [C1, C1Slots])
+ def test_validator(self, cls):
+ """
+ `instance_of` raises `TypeError` on type mismatch.
+ """
+ with pytest.raises(TypeError) as e:
+ cls("1", 2)
+
+ # Using C1 explicitly, since slot classes don't support this.
+ assert (
+ "'x' must be <{type} 'int'> (got '1' that is a <{type} "
+ "'str'>).".format(type=TYPE),
+ attr.fields(C1).x, int, "1",
+ ) == e.value.args
+
+ @given(booleans())
+ def test_renaming(self, slots):
+ """
+ Private members are renamed but only in `__init__`.
+ """
+ @attr.s(slots=slots)
+ class C3(object):
+ _x = attr.ib()
+
+ assert "C3(_x=1)" == repr(C3(x=1))
+
+ @given(booleans(), booleans())
+ def test_programmatic(self, slots, frozen):
+ """
+ `attr.make_class` works.
+ """
+ PC = attr.make_class("PC", ["a", "b"], slots=slots, frozen=frozen)
+ assert (
+ Attribute(name="a", default=NOTHING, validator=None,
+ repr=True, cmp=True, hash=None, init=True),
+ Attribute(name="b", default=NOTHING, validator=None,
+ repr=True, cmp=True, hash=None, init=True),
+ ) == attr.fields(PC)
+
+ @pytest.mark.parametrize("cls", [Sub, SubSlots])
+ def test_subclassing_with_extra_attrs(self, cls):
+ """
+ Sub-classing (where the subclass has extra attrs) does what you'd hope
+ for.
+ """
+ obj = object()
+ i = cls(x=obj, y=2)
+ assert i.x is i.meth() is obj
+ assert i.y == 2
+ if cls is Sub:
+ assert "Sub(x={obj}, y=2)".format(obj=obj) == repr(i)
+ else:
+ assert "SubSlots(x={obj}, y=2)".format(obj=obj) == repr(i)
+
+ @pytest.mark.parametrize("base", [Super, SuperSlots])
+ def test_subclass_without_extra_attrs(self, base):
+ """
+ Sub-classing (where the subclass does not have extra attrs) still
+ behaves the same as a subclass with extra attrs.
+ """
+ class Sub2(base):
+ pass
+
+ obj = object()
+ i = Sub2(x=obj)
+ assert i.x is i.meth() is obj
+ assert "Sub2(x={obj})".format(obj=obj) == repr(i)
+
+ @pytest.mark.parametrize("frozen_class", [
+ Frozen, # has slots=True
+ attr.make_class("FrozenToo", ["x"], slots=False, frozen=True),
+ ])
+ def test_frozen_instance(self, frozen_class):
+ """
+ Frozen instances can't be modified (easily).
+ """
+ frozen = frozen_class(1)
+
+ with pytest.raises(FrozenInstanceError) as e:
+ frozen.x = 2
+
+ with pytest.raises(FrozenInstanceError) as e:
+ del frozen.x
+
+ assert e.value.args[0] == "can't set attribute"
+ assert 1 == frozen.x
+
+ @pytest.mark.parametrize("cls",
+ [C1, C1Slots, C2, C2Slots, Super, SuperSlots,
+ Sub, SubSlots, Frozen, FrozenNoSlots,
+ FromMakeClass])
+ @pytest.mark.parametrize("protocol",
+ range(2, pickle.HIGHEST_PROTOCOL + 1))
+ def test_pickle_attributes(self, cls, protocol):
+ """
+ Pickling/un-pickling of Attribute instances works.
+ """
+ for attribute in attr.fields(cls):
+ assert attribute == pickle.loads(pickle.dumps(attribute, protocol))
+
+ @pytest.mark.parametrize("cls",
+ [C1, C1Slots, C2, C2Slots, Super, SuperSlots,
+ Sub, SubSlots, Frozen, FrozenNoSlots,
+ FromMakeClass])
+ @pytest.mark.parametrize("protocol",
+ range(2, pickle.HIGHEST_PROTOCOL + 1))
+ def test_pickle_object(self, cls, protocol):
+ """
+ Pickle object serialization works on all kinds of attrs classes.
+ """
+ if len(attr.fields(cls)) == 2:
+ obj = cls(123, 456)
+ else:
+ obj = cls(123)
+ assert repr(obj) == repr(pickle.loads(pickle.dumps(obj, protocol)))
+
+ def test_subclassing_frozen_gives_frozen(self):
+ """
+ The frozen-ness of classes is inherited. Subclasses of frozen classes
+ are also frozen and can be instantiated.
+ """
+ i = SubFrozen("foo", "bar")
+
+ assert i.x == "foo"
+ assert i.y == "bar"
+
+ @pytest.mark.parametrize("cls", [WithMeta, WithMetaSlots])
+ def test_metaclass_preserved(self, cls):
+ """
+ Metaclass data is preserved.
+ """
+ assert Meta == type(cls)
+
+ def test_default_decorator(self):
+ """
+ Default decorator sets the default and the respective method gets
+ called.
+ """
+ @attr.s
+ class C(object):
+ x = attr.ib(default=1)
+ y = attr.ib()
+
+ @y.default
+ def compute(self):
+ return self.x + 1
+
+ assert C(1, 2) == C()
+
+ @pytest.mark.parametrize("slots", [True, False])
+ @pytest.mark.parametrize("frozen", [True, False])
+ def test_attrib_overwrite(self, slots, frozen):
+ """
+ Subclasses can overwrite attributes of their superclass.
+ """
+ @attr.s(slots=slots, frozen=frozen)
+ class SubOverwrite(Super):
+ x = attr.ib(default=attr.Factory(list))
+
+ assert SubOverwrite([]) == SubOverwrite()
+
+ def test_dict_patch_class(self):
+ """
+ dict-classes are never replaced.
+ """
+ class C(object):
+ x = attr.ib()
+
+ C_new = attr.s(C)
+
+ assert C_new is C
+
+ def test_hash_by_id(self):
+ """
+ With dict classes, hashing by ID is active for hash=False even on
+ Python 3. This is incorrect behavior but we have to retain it for
+ backward compatibility.
+ """
+ @attr.s(hash=False)
+ class HashByIDBackwardCompat(object):
+ x = attr.ib()
+
+ assert (
+ hash(HashByIDBackwardCompat(1)) != hash(HashByIDBackwardCompat(1))
+ )
+
+ @attr.s(hash=False, cmp=False)
+ class HashByID(object):
+ x = attr.ib()
+
+ assert hash(HashByID(1)) != hash(HashByID(1))
+
+ @attr.s(hash=True)
+ class HashByValues(object):
+ x = attr.ib()
+
+ assert hash(HashByValues(1)) == hash(HashByValues(1))
+
+ def test_handles_different_defaults(self):
+ """
+ Unhashable defaults + subclassing values work.
+ """
+ @attr.s
+ class Unhashable(object):
+ pass
+
+ @attr.s
+ class C(object):
+ x = attr.ib(default=Unhashable())
+
+ @attr.s
+ class D(C):
+ pass
+
+ @pytest.mark.parametrize("slots", [True, False])
+ def test_hash_false_cmp_false(self, slots):
+ """
+ hash=False and cmp=False make a class hashable by ID.
+ """
+ @attr.s(hash=False, cmp=False, slots=slots)
+ class C(object):
+ pass
+
+ assert hash(C()) != hash(C())
+
+ def test_overwrite_super(self):
+ """
+ Super classes can overwrite each other and the attributes are added
+ in the order they are defined.
+ """
+ @attr.s
+ class C(object):
+ c = attr.ib(default=100)
+ x = attr.ib(default=1)
+ b = attr.ib(default=23)
+
+ @attr.s
+ class D(C):
+ a = attr.ib(default=42)
+ x = attr.ib(default=2)
+ d = attr.ib(default=3.14)
+
+ @attr.s
+ class E(D):
+ y = attr.ib(default=3)
+ z = attr.ib(default=4)
+
+ assert "E(c=100, b=23, a=42, x=2, d=3.14, y=3, z=4)" == repr(E())
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_dunders.py b/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_dunders.py
new file mode 100644
index 00000000000..951faba2ffc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_dunders.py
@@ -0,0 +1,502 @@
+"""
+Tests for dunder methods from `attrib._make`.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+import copy
+
+import pytest
+
+from hypothesis import given
+from hypothesis.strategies import booleans
+
+import attr
+
+from attr._make import (
+ NOTHING, Factory, _add_init, _add_repr, _Nothing, fields, make_class
+)
+from attr.validators import instance_of
+
+from .utils import simple_attr, simple_class
+
+
+CmpC = simple_class(cmp=True)
+CmpCSlots = simple_class(cmp=True, slots=True)
+ReprC = simple_class(repr=True)
+ReprCSlots = simple_class(repr=True, slots=True)
+
+# HashC is hashable by explicit definition while HashCSlots is hashable
+# implicitly.
+HashC = simple_class(hash=True)
+HashCSlots = simple_class(hash=None, cmp=True, frozen=True, slots=True)
+
+
+class InitC(object):
+ __attrs_attrs__ = [simple_attr("a"), simple_attr("b")]
+
+
+InitC = _add_init(InitC, False)
+
+
+class TestAddCmp(object):
+ """
+ Tests for `_add_cmp`.
+ """
+ @given(booleans())
+ def test_cmp(self, slots):
+ """
+ If `cmp` is False, ignore that attribute.
+ """
+ C = make_class("C", {
+ "a": attr.ib(cmp=False),
+ "b": attr.ib()
+ }, slots=slots)
+
+ assert C(1, 2) == C(2, 2)
+
+ @pytest.mark.parametrize("cls", [CmpC, CmpCSlots])
+ def test_equal(self, cls):
+ """
+ Equal objects are detected as equal.
+ """
+ assert cls(1, 2) == cls(1, 2)
+ assert not (cls(1, 2) != cls(1, 2))
+
+ @pytest.mark.parametrize("cls", [CmpC, CmpCSlots])
+ def test_unequal_same_class(self, cls):
+ """
+ Unequal objects of correct type are detected as unequal.
+ """
+ assert cls(1, 2) != cls(2, 1)
+ assert not (cls(1, 2) == cls(2, 1))
+
+ @pytest.mark.parametrize("cls", [CmpC, CmpCSlots])
+ def test_unequal_different_class(self, cls):
+ """
+ Unequal objects of different type are detected even if their attributes
+ match.
+ """
+ class NotCmpC(object):
+ a = 1
+ b = 2
+ assert cls(1, 2) != NotCmpC()
+ assert not (cls(1, 2) == NotCmpC())
+
+ @pytest.mark.parametrize("cls", [CmpC, CmpCSlots])
+ def test_lt(self, cls):
+ """
+ __lt__ compares objects as tuples of attribute values.
+ """
+ for a, b in [
+ ((1, 2), (2, 1)),
+ ((1, 2), (1, 3)),
+ (("a", "b"), ("b", "a")),
+ ]:
+ assert cls(*a) < cls(*b)
+
+ @pytest.mark.parametrize("cls", [CmpC, CmpCSlots])
+ def test_lt_unordable(self, cls):
+ """
+ __lt__ returns NotImplemented if classes differ.
+ """
+ assert NotImplemented == (cls(1, 2).__lt__(42))
+
+ @pytest.mark.parametrize("cls", [CmpC, CmpCSlots])
+ def test_le(self, cls):
+ """
+ __le__ compares objects as tuples of attribute values.
+ """
+ for a, b in [
+ ((1, 2), (2, 1)),
+ ((1, 2), (1, 3)),
+ ((1, 1), (1, 1)),
+ (("a", "b"), ("b", "a")),
+ (("a", "b"), ("a", "b")),
+ ]:
+ assert cls(*a) <= cls(*b)
+
+ @pytest.mark.parametrize("cls", [CmpC, CmpCSlots])
+ def test_le_unordable(self, cls):
+ """
+ __le__ returns NotImplemented if classes differ.
+ """
+ assert NotImplemented == (cls(1, 2).__le__(42))
+
+ @pytest.mark.parametrize("cls", [CmpC, CmpCSlots])
+ def test_gt(self, cls):
+ """
+ __gt__ compares objects as tuples of attribute values.
+ """
+ for a, b in [
+ ((2, 1), (1, 2)),
+ ((1, 3), (1, 2)),
+ (("b", "a"), ("a", "b")),
+ ]:
+ assert cls(*a) > cls(*b)
+
+ @pytest.mark.parametrize("cls", [CmpC, CmpCSlots])
+ def test_gt_unordable(self, cls):
+ """
+ __gt__ returns NotImplemented if classes differ.
+ """
+ assert NotImplemented == (cls(1, 2).__gt__(42))
+
+ @pytest.mark.parametrize("cls", [CmpC, CmpCSlots])
+ def test_ge(self, cls):
+ """
+ __ge__ compares objects as tuples of attribute values.
+ """
+ for a, b in [
+ ((2, 1), (1, 2)),
+ ((1, 3), (1, 2)),
+ ((1, 1), (1, 1)),
+ (("b", "a"), ("a", "b")),
+ (("a", "b"), ("a", "b")),
+ ]:
+ assert cls(*a) >= cls(*b)
+
+ @pytest.mark.parametrize("cls", [CmpC, CmpCSlots])
+ def test_ge_unordable(self, cls):
+ """
+ __ge__ returns NotImplemented if classes differ.
+ """
+ assert NotImplemented == (cls(1, 2).__ge__(42))
+
+
+class TestAddRepr(object):
+ """
+ Tests for `_add_repr`.
+ """
+ @pytest.mark.parametrize("slots", [True, False])
+ def test_repr(self, slots):
+ """
+ If `repr` is False, ignore that attribute.
+ """
+ C = make_class("C", {
+ "a": attr.ib(repr=False),
+ "b": attr.ib()
+ }, slots=slots)
+
+ assert "C(b=2)" == repr(C(1, 2))
+
+ @pytest.mark.parametrize("cls", [ReprC, ReprCSlots])
+ def test_repr_works(self, cls):
+ """
+ repr returns a sensible value.
+ """
+ assert "C(a=1, b=2)" == repr(cls(1, 2))
+
+ def test_underscores(self):
+ """
+ repr does not strip underscores.
+ """
+ class C(object):
+ __attrs_attrs__ = [simple_attr("_x")]
+
+ C = _add_repr(C)
+ i = C()
+ i._x = 42
+
+ assert "C(_x=42)" == repr(i)
+
+ @given(add_str=booleans(), slots=booleans())
+ def test_str(self, add_str, slots):
+ """
+ If str is True, it returns the same as repr.
+
+ This only makes sense when subclassing a class with an poor __str__
+ (like Exceptions).
+ """
+ @attr.s(str=add_str, slots=slots)
+ class Error(Exception):
+ x = attr.ib()
+
+ e = Error(42)
+
+ assert (str(e) == repr(e)) is add_str
+
+ def test_str_no_repr(self):
+ """
+ Raises a ValueError if repr=False and str=True.
+ """
+ with pytest.raises(ValueError) as e:
+ simple_class(repr=False, str=True)
+
+ assert (
+ "__str__ can only be generated if a __repr__ exists."
+ ) == e.value.args[0]
+
+
+class TestAddHash(object):
+ """
+ Tests for `_add_hash`.
+ """
+ def test_enforces_type(self):
+ """
+ The `hash` argument to both attrs and attrib must be None, True, or
+ False.
+ """
+ exc_args = ("Invalid value for hash. Must be True, False, or None.",)
+
+ with pytest.raises(TypeError) as e:
+ make_class("C", {}, hash=1),
+
+ assert exc_args == e.value.args
+
+ with pytest.raises(TypeError) as e:
+ make_class("C", {"a": attr.ib(hash=1)}),
+
+ assert exc_args == e.value.args
+
+ @given(booleans())
+ def test_hash_attribute(self, slots):
+ """
+ If `hash` is False on an attribute, ignore that attribute.
+ """
+ C = make_class("C", {"a": attr.ib(hash=False), "b": attr.ib()},
+ slots=slots, hash=True)
+
+ assert hash(C(1, 2)) == hash(C(2, 2))
+
+ @given(booleans())
+ def test_hash_attribute_mirrors_cmp(self, cmp):
+ """
+ If `hash` is None, the hash generation mirrors `cmp`.
+ """
+ C = make_class("C", {"a": attr.ib(cmp=cmp)}, cmp=True, frozen=True)
+
+ if cmp:
+ assert C(1) != C(2)
+ assert hash(C(1)) != hash(C(2))
+ assert hash(C(1)) == hash(C(1))
+ else:
+ assert C(1) == C(2)
+ assert hash(C(1)) == hash(C(2))
+
+ @given(booleans())
+ def test_hash_mirrors_cmp(self, cmp):
+ """
+ If `hash` is None, the hash generation mirrors `cmp`.
+ """
+ C = make_class("C", {"a": attr.ib()}, cmp=cmp, frozen=True)
+
+ i = C(1)
+
+ assert i == i
+ assert hash(i) == hash(i)
+
+ if cmp:
+ assert C(1) == C(1)
+ assert hash(C(1)) == hash(C(1))
+ else:
+ assert C(1) != C(1)
+ assert hash(C(1)) != hash(C(1))
+
+ @pytest.mark.parametrize("cls", [HashC, HashCSlots])
+ def test_hash_works(self, cls):
+ """
+ __hash__ returns different hashes for different values.
+ """
+ assert hash(cls(1, 2)) != hash(cls(1, 1))
+
+ def test_hash_default(self):
+ """
+ Classes are not hashable by default.
+ """
+ C = make_class("C", {})
+
+ with pytest.raises(TypeError) as e:
+ hash(C())
+
+ assert e.value.args[0] in (
+ "'C' objects are unhashable", # PyPy
+ "unhashable type: 'C'", # CPython
+ )
+
+
+class TestAddInit(object):
+ """
+ Tests for `_add_init`.
+ """
+ @given(booleans(), booleans())
+ def test_init(self, slots, frozen):
+ """
+ If `init` is False, ignore that attribute.
+ """
+ C = make_class("C", {"a": attr.ib(init=False), "b": attr.ib()},
+ slots=slots, frozen=frozen)
+ with pytest.raises(TypeError) as e:
+ C(a=1, b=2)
+
+ assert (
+ "__init__() got an unexpected keyword argument 'a'" ==
+ e.value.args[0]
+ )
+
+ @given(booleans(), booleans())
+ def test_no_init_default(self, slots, frozen):
+ """
+ If `init` is False but a Factory is specified, don't allow passing that
+ argument but initialize it anyway.
+ """
+ C = make_class("C", {
+ "_a": attr.ib(init=False, default=42),
+ "_b": attr.ib(init=False, default=Factory(list)),
+ "c": attr.ib()
+ }, slots=slots, frozen=frozen)
+ with pytest.raises(TypeError):
+ C(a=1, c=2)
+ with pytest.raises(TypeError):
+ C(b=1, c=2)
+
+ i = C(23)
+ assert (42, [], 23) == (i._a, i._b, i.c)
+
+ @given(booleans(), booleans())
+ def test_no_init_order(self, slots, frozen):
+ """
+ If an attribute is `init=False`, it's legal to come after a mandatory
+ attribute.
+ """
+ make_class("C", {
+ "a": attr.ib(default=Factory(list)),
+ "b": attr.ib(init=False),
+ }, slots=slots, frozen=frozen)
+
+ def test_sets_attributes(self):
+ """
+ The attributes are initialized using the passed keywords.
+ """
+ obj = InitC(a=1, b=2)
+ assert 1 == obj.a
+ assert 2 == obj.b
+
+ def test_default(self):
+ """
+ If a default value is present, it's used as fallback.
+ """
+ class C(object):
+ __attrs_attrs__ = [
+ simple_attr(name="a", default=2),
+ simple_attr(name="b", default="hallo"),
+ simple_attr(name="c", default=None),
+ ]
+
+ C = _add_init(C, False)
+ i = C()
+ assert 2 == i.a
+ assert "hallo" == i.b
+ assert None is i.c
+
+ def test_factory(self):
+ """
+ If a default factory is present, it's used as fallback.
+ """
+ class D(object):
+ pass
+
+ class C(object):
+ __attrs_attrs__ = [
+ simple_attr(name="a", default=Factory(list)),
+ simple_attr(name="b", default=Factory(D)),
+ ]
+ C = _add_init(C, False)
+ i = C()
+
+ assert [] == i.a
+ assert isinstance(i.b, D)
+
+ def test_validator(self):
+ """
+ If a validator is passed, call it with the preliminary instance, the
+ Attribute, and the argument.
+ """
+ class VException(Exception):
+ pass
+
+ def raiser(*args):
+ raise VException(*args)
+
+ C = make_class("C", {"a": attr.ib("a", validator=raiser)})
+ with pytest.raises(VException) as e:
+ C(42)
+
+ assert (fields(C).a, 42,) == e.value.args[1:]
+ assert isinstance(e.value.args[0], C)
+
+ def test_validator_slots(self):
+ """
+ If a validator is passed, call it with the preliminary instance, the
+ Attribute, and the argument.
+ """
+ class VException(Exception):
+ pass
+
+ def raiser(*args):
+ raise VException(*args)
+
+ C = make_class("C", {"a": attr.ib("a", validator=raiser)}, slots=True)
+ with pytest.raises(VException) as e:
+ C(42)
+
+ assert (fields(C)[0], 42,) == e.value.args[1:]
+ assert isinstance(e.value.args[0], C)
+
+ @given(booleans())
+ def test_validator_others(self, slots):
+ """
+ Does not interfere when setting non-attrs attributes.
+ """
+ C = make_class("C", {
+ "a": attr.ib("a", validator=instance_of(int))
+ }, slots=slots)
+ i = C(1)
+
+ assert 1 == i.a
+
+ if not slots:
+ i.b = "foo"
+ assert "foo" == i.b
+ else:
+ with pytest.raises(AttributeError):
+ i.b = "foo"
+
+ def test_underscores(self):
+ """
+ The argument names in `__init__` are without leading and trailing
+ underscores.
+ """
+ class C(object):
+ __attrs_attrs__ = [simple_attr("_private")]
+
+ C = _add_init(C, False)
+ i = C(private=42)
+ assert 42 == i._private
+
+
+class TestNothing(object):
+ """
+ Tests for `_Nothing`.
+ """
+ def test_copy(self):
+ """
+ __copy__ returns the same object.
+ """
+ n = _Nothing()
+ assert n is copy.copy(n)
+
+ def test_deepcopy(self):
+ """
+ __deepcopy__ returns the same object.
+ """
+ n = _Nothing()
+ assert n is copy.deepcopy(n)
+
+ def test_eq(self):
+ """
+ All instances are equal.
+ """
+ assert _Nothing() == _Nothing() == NOTHING
+ assert not (_Nothing() != _Nothing())
+ assert 1 != _Nothing()
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_filters.py b/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_filters.py
new file mode 100644
index 00000000000..8f7dd694925
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_filters.py
@@ -0,0 +1,94 @@
+"""
+Tests for `attr.filters`.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+import pytest
+
+import attr
+
+from attr import fields
+from attr.filters import _split_what, exclude, include
+
+
+@attr.s
+class C(object):
+ a = attr.ib()
+ b = attr.ib()
+
+
+class TestSplitWhat(object):
+ """
+ Tests for `_split_what`.
+ """
+ def test_splits(self):
+ """
+ Splits correctly.
+ """
+ assert (
+ frozenset((int, str)),
+ frozenset((fields(C).a,)),
+ ) == _split_what((str, fields(C).a, int,))
+
+
+class TestInclude(object):
+ """
+ Tests for `include`.
+ """
+ @pytest.mark.parametrize("incl,value", [
+ ((int,), 42),
+ ((str,), "hello"),
+ ((str, fields(C).a), 42),
+ ((str, fields(C).b), "hello"),
+ ])
+ def test_allow(self, incl, value):
+ """
+ Return True if a class or attribute is whitelisted.
+ """
+ i = include(*incl)
+ assert i(fields(C).a, value) is True
+
+ @pytest.mark.parametrize("incl,value", [
+ ((str,), 42),
+ ((int,), "hello"),
+ ((str, fields(C).b), 42),
+ ((int, fields(C).b), "hello"),
+ ])
+ def test_drop_class(self, incl, value):
+ """
+ Return False on non-whitelisted classes and attributes.
+ """
+ i = include(*incl)
+ assert i(fields(C).a, value) is False
+
+
+class TestExclude(object):
+ """
+ Tests for `exclude`.
+ """
+ @pytest.mark.parametrize("excl,value", [
+ ((str,), 42),
+ ((int,), "hello"),
+ ((str, fields(C).b), 42),
+ ((int, fields(C).b), "hello"),
+ ])
+ def test_allow(self, excl, value):
+ """
+ Return True if class or attribute is not blacklisted.
+ """
+ e = exclude(*excl)
+ assert e(fields(C).a, value) is True
+
+ @pytest.mark.parametrize("excl,value", [
+ ((int,), 42),
+ ((str,), "hello"),
+ ((str, fields(C).a), 42),
+ ((str, fields(C).b), "hello"),
+ ])
+ def test_drop_class(self, excl, value):
+ """
+ Return True on non-blacklisted classes and attributes.
+ """
+ e = exclude(*excl)
+ assert e(fields(C).a, value) is False
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_funcs.py b/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_funcs.py
new file mode 100644
index 00000000000..0167823818e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_funcs.py
@@ -0,0 +1,527 @@
+"""
+Tests for `attr._funcs`.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+from collections import Mapping, OrderedDict, Sequence
+
+import pytest
+
+from hypothesis import strategies as st
+from hypothesis import HealthCheck, assume, given, settings
+
+import attr
+
+from attr import asdict, assoc, astuple, evolve, fields, has
+from attr._compat import TYPE
+from attr.exceptions import AttrsAttributeNotFoundError
+from attr.validators import instance_of
+
+from .utils import nested_classes, simple_classes
+
+
+MAPPING_TYPES = (dict, OrderedDict)
+SEQUENCE_TYPES = (list, tuple)
+
+
+class TestAsDict(object):
+ """
+ Tests for `asdict`.
+ """
+ @given(st.sampled_from(MAPPING_TYPES))
+ def test_shallow(self, C, dict_factory):
+ """
+ Shallow asdict returns correct dict.
+ """
+ assert {
+ "x": 1,
+ "y": 2,
+ } == asdict(C(x=1, y=2), False, dict_factory=dict_factory)
+
+ @given(st.sampled_from(MAPPING_TYPES))
+ def test_recurse(self, C, dict_class):
+ """
+ Deep asdict returns correct dict.
+ """
+ assert {
+ "x": {"x": 1, "y": 2},
+ "y": {"x": 3, "y": 4},
+ } == asdict(C(
+ C(1, 2),
+ C(3, 4),
+ ), dict_factory=dict_class)
+
+ @given(nested_classes, st.sampled_from(MAPPING_TYPES))
+ @settings(suppress_health_check=[HealthCheck.too_slow])
+ def test_recurse_property(self, cls, dict_class):
+ """
+ Property tests for recursive asdict.
+ """
+ obj = cls()
+ obj_dict = asdict(obj, dict_factory=dict_class)
+
+ def assert_proper_dict_class(obj, obj_dict):
+ assert isinstance(obj_dict, dict_class)
+
+ for field in fields(obj.__class__):
+ field_val = getattr(obj, field.name)
+ if has(field_val.__class__):
+ # This field holds a class, recurse the assertions.
+ assert_proper_dict_class(field_val, obj_dict[field.name])
+ elif isinstance(field_val, Sequence):
+ dict_val = obj_dict[field.name]
+ for item, item_dict in zip(field_val, dict_val):
+ if has(item.__class__):
+ assert_proper_dict_class(item, item_dict)
+ elif isinstance(field_val, Mapping):
+ # This field holds a dictionary.
+ assert isinstance(obj_dict[field.name], dict_class)
+
+ for key, val in field_val.items():
+ if has(val.__class__):
+ assert_proper_dict_class(val,
+ obj_dict[field.name][key])
+
+ assert_proper_dict_class(obj, obj_dict)
+
+ @given(st.sampled_from(MAPPING_TYPES))
+ def test_filter(self, C, dict_factory):
+ """
+ Attributes that are supposed to be skipped are skipped.
+ """
+ assert {
+ "x": {"x": 1},
+ } == asdict(C(
+ C(1, 2),
+ C(3, 4),
+ ), filter=lambda a, v: a.name != "y", dict_factory=dict_factory)
+
+ @given(container=st.sampled_from(SEQUENCE_TYPES))
+ def test_lists_tuples(self, container, C):
+ """
+ If recurse is True, also recurse into lists.
+ """
+ assert {
+ "x": 1,
+ "y": [{"x": 2, "y": 3}, {"x": 4, "y": 5}, "a"],
+ } == asdict(C(1, container([C(2, 3), C(4, 5), "a"])))
+
+ @given(container=st.sampled_from(SEQUENCE_TYPES))
+ def test_lists_tuples_retain_type(self, container, C):
+ """
+ If recurse and retain_collection_types are True, also recurse
+ into lists and do not convert them into list.
+ """
+ assert {
+ "x": 1,
+ "y": container([{"x": 2, "y": 3}, {"x": 4, "y": 5}, "a"]),
+ } == asdict(C(1, container([C(2, 3), C(4, 5), "a"])),
+ retain_collection_types=True)
+
+ @given(st.sampled_from(MAPPING_TYPES))
+ def test_dicts(self, C, dict_factory):
+ """
+ If recurse is True, also recurse into dicts.
+ """
+ res = asdict(C(1, {"a": C(4, 5)}), dict_factory=dict_factory)
+ assert {
+ "x": 1,
+ "y": {"a": {"x": 4, "y": 5}},
+ } == res
+ assert isinstance(res, dict_factory)
+
+ @given(simple_classes(private_attrs=False), st.sampled_from(MAPPING_TYPES))
+ def test_roundtrip(self, cls, dict_class):
+ """
+ Test dumping to dicts and back for Hypothesis-generated classes.
+
+ Private attributes don't round-trip (the attribute name is different
+ than the initializer argument).
+ """
+ instance = cls()
+ dict_instance = asdict(instance, dict_factory=dict_class)
+
+ assert isinstance(dict_instance, dict_class)
+
+ roundtrip_instance = cls(**dict_instance)
+
+ assert instance == roundtrip_instance
+
+ @given(simple_classes())
+ def test_asdict_preserve_order(self, cls):
+ """
+ Field order should be preserved when dumping to OrderedDicts.
+ """
+ instance = cls()
+ dict_instance = asdict(instance, dict_factory=OrderedDict)
+
+ assert [a.name for a in fields(cls)] == list(dict_instance.keys())
+
+
+class TestAsTuple(object):
+ """
+ Tests for `astuple`.
+ """
+ @given(st.sampled_from(SEQUENCE_TYPES))
+ def test_shallow(self, C, tuple_factory):
+ """
+ Shallow astuple returns correct dict.
+ """
+ assert (tuple_factory([1, 2]) ==
+ astuple(C(x=1, y=2), False, tuple_factory=tuple_factory))
+
+ @given(st.sampled_from(SEQUENCE_TYPES))
+ def test_recurse(self, C, tuple_factory):
+ """
+ Deep astuple returns correct tuple.
+ """
+ assert (tuple_factory([tuple_factory([1, 2]),
+ tuple_factory([3, 4])])
+ == astuple(C(
+ C(1, 2),
+ C(3, 4),
+ ),
+ tuple_factory=tuple_factory))
+
+ @given(nested_classes, st.sampled_from(SEQUENCE_TYPES))
+ @settings(suppress_health_check=[HealthCheck.too_slow])
+ def test_recurse_property(self, cls, tuple_class):
+ """
+ Property tests for recursive astuple.
+ """
+ obj = cls()
+ obj_tuple = astuple(obj, tuple_factory=tuple_class)
+
+ def assert_proper_tuple_class(obj, obj_tuple):
+ assert isinstance(obj_tuple, tuple_class)
+ for index, field in enumerate(fields(obj.__class__)):
+ field_val = getattr(obj, field.name)
+ if has(field_val.__class__):
+ # This field holds a class, recurse the assertions.
+ assert_proper_tuple_class(field_val, obj_tuple[index])
+
+ assert_proper_tuple_class(obj, obj_tuple)
+
+ @given(nested_classes, st.sampled_from(SEQUENCE_TYPES))
+ @settings(suppress_health_check=[HealthCheck.too_slow])
+ def test_recurse_retain(self, cls, tuple_class):
+ """
+ Property tests for asserting collection types are retained.
+ """
+ obj = cls()
+ obj_tuple = astuple(obj, tuple_factory=tuple_class,
+ retain_collection_types=True)
+
+ def assert_proper_col_class(obj, obj_tuple):
+ # Iterate over all attributes, and if they are lists or mappings
+ # in the original, assert they are the same class in the dumped.
+ for index, field in enumerate(fields(obj.__class__)):
+ field_val = getattr(obj, field.name)
+ if has(field_val.__class__):
+ # This field holds a class, recurse the assertions.
+ assert_proper_col_class(field_val, obj_tuple[index])
+ elif isinstance(field_val, (list, tuple)):
+ # This field holds a sequence of something.
+ expected_type = type(obj_tuple[index])
+ assert type(field_val) is expected_type # noqa: E721
+ for obj_e, obj_tuple_e in zip(field_val, obj_tuple[index]):
+ if has(obj_e.__class__):
+ assert_proper_col_class(obj_e, obj_tuple_e)
+ elif isinstance(field_val, dict):
+ orig = field_val
+ tupled = obj_tuple[index]
+ assert type(orig) is type(tupled) # noqa: E721
+ for obj_e, obj_tuple_e in zip(orig.items(),
+ tupled.items()):
+ if has(obj_e[0].__class__): # Dict key
+ assert_proper_col_class(obj_e[0], obj_tuple_e[0])
+ if has(obj_e[1].__class__): # Dict value
+ assert_proper_col_class(obj_e[1], obj_tuple_e[1])
+
+ assert_proper_col_class(obj, obj_tuple)
+
+ @given(st.sampled_from(SEQUENCE_TYPES))
+ def test_filter(self, C, tuple_factory):
+ """
+ Attributes that are supposed to be skipped are skipped.
+ """
+ assert tuple_factory([tuple_factory([1, ]), ]) == astuple(C(
+ C(1, 2),
+ C(3, 4),
+ ), filter=lambda a, v: a.name != "y", tuple_factory=tuple_factory)
+
+ @given(container=st.sampled_from(SEQUENCE_TYPES))
+ def test_lists_tuples(self, container, C):
+ """
+ If recurse is True, also recurse into lists.
+ """
+ assert ((1, [(2, 3), (4, 5), "a"])
+ == astuple(C(1, container([C(2, 3), C(4, 5), "a"])))
+ )
+
+ @given(st.sampled_from(SEQUENCE_TYPES))
+ def test_dicts(self, C, tuple_factory):
+ """
+ If recurse is True, also recurse into dicts.
+ """
+ res = astuple(C(1, {"a": C(4, 5)}), tuple_factory=tuple_factory)
+ assert tuple_factory([1, {"a": tuple_factory([4, 5])}]) == res
+ assert isinstance(res, tuple_factory)
+
+ @given(container=st.sampled_from(SEQUENCE_TYPES))
+ def test_lists_tuples_retain_type(self, container, C):
+ """
+ If recurse and retain_collection_types are True, also recurse
+ into lists and do not convert them into list.
+ """
+ assert (
+ (1, container([(2, 3), (4, 5), "a"]))
+ == astuple(C(1, container([C(2, 3), C(4, 5), "a"])),
+ retain_collection_types=True))
+
+ @given(container=st.sampled_from(MAPPING_TYPES))
+ def test_dicts_retain_type(self, container, C):
+ """
+ If recurse and retain_collection_types are True, also recurse
+ into lists and do not convert them into list.
+ """
+ assert (
+ (1, container({"a": (4, 5)}))
+ == astuple(C(1, container({"a": C(4, 5)})),
+ retain_collection_types=True))
+
+ @given(simple_classes(), st.sampled_from(SEQUENCE_TYPES))
+ def test_roundtrip(self, cls, tuple_class):
+ """
+ Test dumping to tuple and back for Hypothesis-generated classes.
+ """
+ instance = cls()
+ tuple_instance = astuple(instance, tuple_factory=tuple_class)
+
+ assert isinstance(tuple_instance, tuple_class)
+
+ roundtrip_instance = cls(*tuple_instance)
+
+ assert instance == roundtrip_instance
+
+
+class TestHas(object):
+ """
+ Tests for `has`.
+ """
+ def test_positive(self, C):
+ """
+ Returns `True` on decorated classes.
+ """
+ assert has(C)
+
+ def test_positive_empty(self):
+ """
+ Returns `True` on decorated classes even if there are no attributes.
+ """
+ @attr.s
+ class D(object):
+ pass
+
+ assert has(D)
+
+ def test_negative(self):
+ """
+ Returns `False` on non-decorated classes.
+ """
+ assert not has(object)
+
+
+class TestAssoc(object):
+ """
+ Tests for `assoc`.
+ """
+ @given(slots=st.booleans(), frozen=st.booleans())
+ def test_empty(self, slots, frozen):
+ """
+ Empty classes without changes get copied.
+ """
+ @attr.s(slots=slots, frozen=frozen)
+ class C(object):
+ pass
+
+ i1 = C()
+ with pytest.deprecated_call():
+ i2 = assoc(i1)
+
+ assert i1 is not i2
+ assert i1 == i2
+
+ @given(simple_classes())
+ def test_no_changes(self, C):
+ """
+ No changes means a verbatim copy.
+ """
+ i1 = C()
+ with pytest.deprecated_call():
+ i2 = assoc(i1)
+
+ assert i1 is not i2
+ assert i1 == i2
+
+ @given(simple_classes(), st.data())
+ def test_change(self, C, data):
+ """
+ Changes work.
+ """
+ # Take the first attribute, and change it.
+ assume(fields(C)) # Skip classes with no attributes.
+ field_names = [a.name for a in fields(C)]
+ original = C()
+ chosen_names = data.draw(st.sets(st.sampled_from(field_names)))
+ change_dict = {name: data.draw(st.integers())
+ for name in chosen_names}
+
+ with pytest.deprecated_call():
+ changed = assoc(original, **change_dict)
+
+ for k, v in change_dict.items():
+ assert getattr(changed, k) == v
+
+ @given(simple_classes())
+ def test_unknown(self, C):
+ """
+ Wanting to change an unknown attribute raises an
+ AttrsAttributeNotFoundError.
+ """
+ # No generated class will have a four letter attribute.
+ with pytest.raises(AttrsAttributeNotFoundError) as e, \
+ pytest.deprecated_call():
+ assoc(C(), aaaa=2)
+
+ assert (
+ "aaaa is not an attrs attribute on {cls!r}.".format(cls=C),
+ ) == e.value.args
+
+ def test_frozen(self):
+ """
+ Works on frozen classes.
+ """
+ @attr.s(frozen=True)
+ class C(object):
+ x = attr.ib()
+ y = attr.ib()
+
+ with pytest.deprecated_call():
+ assert C(3, 2) == assoc(C(1, 2), x=3)
+
+ def test_warning(self):
+ """
+ DeprecationWarning points to the correct file.
+ """
+ @attr.s
+ class C(object):
+ x = attr.ib()
+
+ with pytest.warns(DeprecationWarning) as wi:
+ assert C(2) == assoc(C(1), x=2)
+
+ assert __file__ == wi.list[0].filename
+
+
+class TestEvolve(object):
+ """
+ Tests for `evolve`.
+ """
+ @given(slots=st.booleans(), frozen=st.booleans())
+ def test_empty(self, slots, frozen):
+ """
+ Empty classes without changes get copied.
+ """
+ @attr.s(slots=slots, frozen=frozen)
+ class C(object):
+ pass
+
+ i1 = C()
+ i2 = evolve(i1)
+
+ assert i1 is not i2
+ assert i1 == i2
+
+ @given(simple_classes())
+ def test_no_changes(self, C):
+ """
+ No changes means a verbatim copy.
+ """
+ i1 = C()
+ i2 = evolve(i1)
+
+ assert i1 is not i2
+ assert i1 == i2
+
+ @given(simple_classes(), st.data())
+ def test_change(self, C, data):
+ """
+ Changes work.
+ """
+ # Take the first attribute, and change it.
+ assume(fields(C)) # Skip classes with no attributes.
+ field_names = [a.name for a in fields(C)]
+ original = C()
+ chosen_names = data.draw(st.sets(st.sampled_from(field_names)))
+ # We pay special attention to private attributes, they should behave
+ # like in `__init__`.
+ change_dict = {name.replace('_', ''): data.draw(st.integers())
+ for name in chosen_names}
+ changed = evolve(original, **change_dict)
+ for name in chosen_names:
+ assert getattr(changed, name) == change_dict[name.replace('_', '')]
+
+ @given(simple_classes())
+ def test_unknown(self, C):
+ """
+ Wanting to change an unknown attribute raises an
+ AttrsAttributeNotFoundError.
+ """
+ # No generated class will have a four letter attribute.
+ with pytest.raises(TypeError) as e:
+ evolve(C(), aaaa=2)
+ expected = "__init__() got an unexpected keyword argument 'aaaa'"
+ assert (expected,) == e.value.args
+
+ def test_validator_failure(self):
+ """
+ TypeError isn't swallowed when validation fails within evolve.
+ """
+ @attr.s
+ class C(object):
+ a = attr.ib(validator=instance_of(int))
+
+ with pytest.raises(TypeError) as e:
+ evolve(C(a=1), a="some string")
+ m = e.value.args[0]
+
+ assert m.startswith("'a' must be <{type} 'int'>".format(type=TYPE))
+
+ def test_private(self):
+ """
+ evolve() acts as `__init__` with regards to private attributes.
+ """
+ @attr.s
+ class C(object):
+ _a = attr.ib()
+
+ assert evolve(C(1), a=2)._a == 2
+
+ with pytest.raises(TypeError):
+ evolve(C(1), _a=2)
+
+ with pytest.raises(TypeError):
+ evolve(C(1), a=3, _a=2)
+
+ def test_non_init_attrs(self):
+ """
+ evolve() handles `init=False` attributes.
+ """
+ @attr.s
+ class C(object):
+ a = attr.ib()
+ b = attr.ib(init=False, default=0)
+
+ assert evolve(C(1), a=2).a == 2
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_init_subclass.py b/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_init_subclass.py
new file mode 100644
index 00000000000..b66130ede47
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_init_subclass.py
@@ -0,0 +1,44 @@
+"""
+Tests for `__init_subclass__` related tests.
+
+Python 3.6+ only.
+"""
+
+import pytest
+
+import attr
+
+
+@pytest.mark.parametrize("slots", [True, False])
+def test_init_subclass_vanilla(slots):
+ """
+ `super().__init_subclass__` can be used if the subclass is not an attrs
+ class both with dict and slots classes.
+ """
+ @attr.s(slots=slots)
+ class Base:
+ def __init_subclass__(cls, param, **kw):
+ super().__init_subclass__(**kw)
+ cls.param = param
+
+ class Vanilla(Base, param="foo"):
+ pass
+
+ assert "foo" == Vanilla().param
+
+
+def test_init_subclass_attrs():
+ """
+ `__init_subclass__` works with attrs classes as long as slots=False.
+ """
+ @attr.s(slots=False)
+ class Base:
+ def __init_subclass__(cls, param, **kw):
+ super().__init_subclass__(**kw)
+ cls.param = param
+
+ @attr.s
+ class Attrs(Base, param="foo"):
+ pass
+
+ assert "foo" == Attrs().param
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_make.py b/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_make.py
new file mode 100644
index 00000000000..f8c80228ae8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_make.py
@@ -0,0 +1,866 @@
+"""
+Tests for `attr._make`.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+import inspect
+import sys
+
+from operator import attrgetter
+
+import pytest
+
+from hypothesis import given
+from hypothesis.strategies import booleans, integers, lists, sampled_from, text
+
+import attr
+
+from attr import _config
+from attr._compat import PY2
+from attr._make import (
+ Attribute, Factory, _AndValidator, _Attributes, _ClassBuilder,
+ _CountingAttr, _transform_attrs, and_, fields, make_class, validate
+)
+from attr.exceptions import DefaultAlreadySetError, NotAnAttrsClassError
+
+from .utils import (
+ gen_attr_names, list_of_attrs, simple_attr, simple_attrs,
+ simple_attrs_without_metadata, simple_classes
+)
+
+
+attrs_st = simple_attrs.map(lambda c: Attribute.from_counting_attr("name", c))
+
+
+class TestCountingAttr(object):
+ """
+ Tests for `attr`.
+ """
+ def test_returns_Attr(self):
+ """
+ Returns an instance of _CountingAttr.
+ """
+ a = attr.ib()
+
+ assert isinstance(a, _CountingAttr)
+
+ def test_validators_lists_to_wrapped_tuples(self):
+ """
+ If a list is passed as validator, it's just converted to a tuple.
+ """
+ def v1(_, __):
+ pass
+
+ def v2(_, __):
+ pass
+
+ a = attr.ib(validator=[v1, v2])
+
+ assert _AndValidator((v1, v2,)) == a._validator
+
+ def test_validator_decorator_single(self):
+ """
+ If _CountingAttr.validator is used as a decorator and there is no
+ decorator set, the decorated method is used as the validator.
+ """
+ a = attr.ib()
+
+ @a.validator
+ def v():
+ pass
+
+ assert v == a._validator
+
+ @pytest.mark.parametrize("wrap", [
+ lambda v: v,
+ lambda v: [v],
+ lambda v: and_(v)
+
+ ])
+ def test_validator_decorator(self, wrap):
+ """
+ If _CountingAttr.validator is used as a decorator and there is already
+ a decorator set, the decorators are composed using `and_`.
+ """
+ def v(_, __):
+ pass
+
+ a = attr.ib(validator=wrap(v))
+
+ @a.validator
+ def v2(self, _, __):
+ pass
+
+ assert _AndValidator((v, v2,)) == a._validator
+
+ def test_default_decorator_already_set(self):
+ """
+ Raise DefaultAlreadySetError if the decorator is used after a default
+ has been set.
+ """
+ a = attr.ib(default=42)
+
+ with pytest.raises(DefaultAlreadySetError):
+ @a.default
+ def f(self):
+ pass
+
+ def test_default_decorator_sets(self):
+ """
+ Decorator wraps the method in a Factory with pass_self=True and sets
+ the default.
+ """
+ a = attr.ib()
+
+ @a.default
+ def f(self):
+ pass
+
+ assert Factory(f, True) == a._default
+
+
+def make_tc():
+ class TransformC(object):
+ z = attr.ib()
+ y = attr.ib()
+ x = attr.ib()
+ a = 42
+ return TransformC
+
+
+class TestTransformAttrs(object):
+ """
+ Tests for `_transform_attrs`.
+ """
+ def test_no_modifications(self):
+ """
+ Doesn't attach __attrs_attrs__ to the class anymore.
+ """
+ C = make_tc()
+ _transform_attrs(C, None, False)
+
+ assert None is getattr(C, "__attrs_attrs__", None)
+
+ def test_normal(self):
+ """
+ Transforms every `_CountingAttr` and leaves others (a) be.
+ """
+ C = make_tc()
+ attrs, _, = _transform_attrs(C, None, False)
+
+ assert ["z", "y", "x"] == [a.name for a in attrs]
+
+ def test_empty(self):
+ """
+ No attributes works as expected.
+ """
+ @attr.s
+ class C(object):
+ pass
+
+ assert _Attributes(((), [])) == _transform_attrs(C, None, False)
+
+ def test_transforms_to_attribute(self):
+ """
+ All `_CountingAttr`s are transformed into `Attribute`s.
+ """
+ C = make_tc()
+ attrs, super_attrs = _transform_attrs(C, None, False)
+
+ assert [] == super_attrs
+ assert 3 == len(attrs)
+ assert all(isinstance(a, Attribute) for a in attrs)
+
+ def test_conflicting_defaults(self):
+ """
+ Raises `ValueError` if attributes with defaults are followed by
+ mandatory attributes.
+ """
+ class C(object):
+ x = attr.ib(default=None)
+ y = attr.ib()
+
+ with pytest.raises(ValueError) as e:
+ _transform_attrs(C, None, False)
+ assert (
+ "No mandatory attributes allowed after an attribute with a "
+ "default value or factory. Attribute in question: Attribute"
+ "(name='y', default=NOTHING, validator=None, repr=True, "
+ "cmp=True, hash=None, init=True, convert=None, "
+ "metadata=mappingproxy({}), type=None)",
+ ) == e.value.args
+
+ def test_these(self):
+ """
+ If these is passed, use it and ignore body and super classes.
+ """
+ class Base(object):
+ z = attr.ib()
+
+ class C(Base):
+ y = attr.ib()
+
+ attrs, super_attrs = _transform_attrs(C, {"x": attr.ib()}, False)
+
+ assert [] == super_attrs
+ assert (
+ simple_attr("x"),
+ ) == attrs
+
+ def test_multiple_inheritance(self):
+ """
+ Order of attributes doesn't get mixed up by multiple inheritance.
+
+ See #285
+ """
+ @attr.s
+ class A(object):
+ a1 = attr.ib(default="a1")
+ a2 = attr.ib(default="a2")
+
+ @attr.s
+ class B(A):
+ b1 = attr.ib(default="b1")
+ b2 = attr.ib(default="b2")
+
+ @attr.s
+ class C(B, A):
+ c1 = attr.ib(default="c1")
+ c2 = attr.ib(default="c2")
+
+ @attr.s
+ class D(A):
+ d1 = attr.ib(default="d1")
+ d2 = attr.ib(default="d2")
+
+ @attr.s
+ class E(D, C):
+ e1 = attr.ib(default="e1")
+ e2 = attr.ib(default="e2")
+
+ assert (
+ "E(a1='a1', a2='a2', b1='b1', b2='b2', c1='c1', c2='c2', d1='d1', "
+ "d2='d2', e1='e1', e2='e2')"
+ ) == repr(E())
+
+
+class TestAttributes(object):
+ """
+ Tests for the `attrs`/`attr.s` class decorator.
+ """
+ @pytest.mark.skipif(not PY2, reason="No old-style classes in Py3")
+ def test_catches_old_style(self):
+ """
+ Raises TypeError on old-style classes.
+ """
+ with pytest.raises(TypeError) as e:
+ @attr.s
+ class C:
+ pass
+
+ assert ("attrs only works with new-style classes.",) == e.value.args
+
+ def test_sets_attrs(self):
+ """
+ Sets the `__attrs_attrs__` class attribute with a list of `Attribute`s.
+ """
+ @attr.s
+ class C(object):
+ x = attr.ib()
+
+ assert "x" == C.__attrs_attrs__[0].name
+ assert all(isinstance(a, Attribute) for a in C.__attrs_attrs__)
+
+ def test_empty(self):
+ """
+ No attributes, no problems.
+ """
+ @attr.s
+ class C3(object):
+ pass
+
+ assert "C3()" == repr(C3())
+ assert C3() == C3()
+
+ @given(attr=attrs_st, attr_name=sampled_from(Attribute.__slots__))
+ def test_immutable(self, attr, attr_name):
+ """
+ Attribute instances are immutable.
+ """
+ with pytest.raises(AttributeError):
+ setattr(attr, attr_name, 1)
+
+ @pytest.mark.parametrize("method_name", [
+ "__repr__",
+ "__eq__",
+ "__hash__",
+ "__init__",
+ ])
+ def test_adds_all_by_default(self, method_name):
+ """
+ If no further arguments are supplied, all add_XXX functions except
+ add_hash are applied. __hash__ is set to None.
+ """
+ # Set the method name to a sentinel and check whether it has been
+ # overwritten afterwards.
+ sentinel = object()
+
+ class C(object):
+ x = attr.ib()
+
+ setattr(C, method_name, sentinel)
+
+ C = attr.s(C)
+ meth = getattr(C, method_name)
+
+ assert sentinel != meth
+ if method_name == "__hash__":
+ assert meth is None
+
+ @pytest.mark.parametrize("arg_name, method_name", [
+ ("repr", "__repr__"),
+ ("cmp", "__eq__"),
+ ("hash", "__hash__"),
+ ("init", "__init__"),
+ ])
+ def test_respects_add_arguments(self, arg_name, method_name):
+ """
+ If a certain `add_XXX` is `False`, `__XXX__` is not added to the class.
+ """
+ # Set the method name to a sentinel and check whether it has been
+ # overwritten afterwards.
+ sentinel = object()
+
+ am_args = {
+ "repr": True,
+ "cmp": True,
+ "hash": True,
+ "init": True
+ }
+ am_args[arg_name] = False
+
+ class C(object):
+ x = attr.ib()
+
+ setattr(C, method_name, sentinel)
+
+ C = attr.s(**am_args)(C)
+
+ assert sentinel == getattr(C, method_name)
+
+ @pytest.mark.skipif(PY2, reason="__qualname__ is PY3-only.")
+ @given(slots_outer=booleans(), slots_inner=booleans())
+ def test_repr_qualname(self, slots_outer, slots_inner):
+ """
+ On Python 3, the name in repr is the __qualname__.
+ """
+ @attr.s(slots=slots_outer)
+ class C(object):
+ @attr.s(slots=slots_inner)
+ class D(object):
+ pass
+
+ assert "C.D()" == repr(C.D())
+ assert "GC.D()" == repr(GC.D())
+
+ @given(slots_outer=booleans(), slots_inner=booleans())
+ def test_repr_fake_qualname(self, slots_outer, slots_inner):
+ """
+ Setting repr_ns overrides a potentially guessed namespace.
+ """
+ @attr.s(slots=slots_outer)
+ class C(object):
+ @attr.s(repr_ns="C", slots=slots_inner)
+ class D(object):
+ pass
+ assert "C.D()" == repr(C.D())
+
+ @pytest.mark.skipif(PY2, reason="__qualname__ is PY3-only.")
+ @given(slots_outer=booleans(), slots_inner=booleans())
+ def test_name_not_overridden(self, slots_outer, slots_inner):
+ """
+ On Python 3, __name__ is different from __qualname__.
+ """
+ @attr.s(slots=slots_outer)
+ class C(object):
+ @attr.s(slots=slots_inner)
+ class D(object):
+ pass
+
+ assert C.D.__name__ == "D"
+ assert C.D.__qualname__ == C.__qualname__ + ".D"
+
+ @given(with_validation=booleans())
+ def test_post_init(self, with_validation, monkeypatch):
+ """
+ Verify that __attrs_post_init__ gets called if defined.
+ """
+ monkeypatch.setattr(_config, "_run_validators", with_validation)
+
+ @attr.s
+ class C(object):
+ x = attr.ib()
+ y = attr.ib()
+
+ def __attrs_post_init__(self2):
+ self2.z = self2.x + self2.y
+
+ c = C(x=10, y=20)
+
+ assert 30 == getattr(c, 'z', None)
+
+ def test_types(self):
+ """
+ Sets the `Attribute.type` attr from type argument.
+ """
+ @attr.s
+ class C(object):
+ x = attr.ib(type=int)
+ y = attr.ib(type=str)
+ z = attr.ib()
+
+ assert int is fields(C).x.type
+ assert str is fields(C).y.type
+ assert None is fields(C).z.type
+
+ @pytest.mark.parametrize("slots", [True, False])
+ def test_clean_class(self, slots):
+ """
+ Attribute definitions do not appear on the class body after @attr.s.
+ """
+ @attr.s(slots=slots)
+ class C(object):
+ x = attr.ib()
+
+ x = getattr(C, "x", None)
+
+ assert not isinstance(x, _CountingAttr)
+
+
+@attr.s
+class GC(object):
+ @attr.s
+ class D(object):
+ pass
+
+
+class TestMakeClass(object):
+ """
+ Tests for `make_class`.
+ """
+ @pytest.mark.parametrize("ls", [
+ list,
+ tuple
+ ])
+ def test_simple(self, ls):
+ """
+ Passing a list of strings creates attributes with default args.
+ """
+ C1 = make_class("C1", ls(["a", "b"]))
+
+ @attr.s
+ class C2(object):
+ a = attr.ib()
+ b = attr.ib()
+
+ assert C1.__attrs_attrs__ == C2.__attrs_attrs__
+
+ def test_dict(self):
+ """
+ Passing a dict of name: _CountingAttr creates an equivalent class.
+ """
+ C1 = make_class("C1", {
+ "a": attr.ib(default=42),
+ "b": attr.ib(default=None),
+ })
+
+ @attr.s
+ class C2(object):
+ a = attr.ib(default=42)
+ b = attr.ib(default=None)
+
+ assert C1.__attrs_attrs__ == C2.__attrs_attrs__
+
+ def test_attr_args(self):
+ """
+ attributes_arguments are passed to attributes
+ """
+ C = make_class("C", ["x"], repr=False)
+
+ assert repr(C(1)).startswith("<tests.test_make.C object at 0x")
+
+ def test_catches_wrong_attrs_type(self):
+ """
+ Raise `TypeError` if an invalid type for attrs is passed.
+ """
+ with pytest.raises(TypeError) as e:
+ make_class("C", object())
+
+ assert (
+ "attrs argument must be a dict or a list.",
+ ) == e.value.args
+
+ def test_bases(self):
+ """
+ Parameter bases default to (object,) and subclasses correctly
+ """
+ class D(object):
+ pass
+
+ cls = make_class("C", {})
+
+ assert cls.__mro__[-1] == object
+
+ cls = make_class("C", {}, bases=(D,))
+
+ assert D in cls.__mro__
+ assert isinstance(cls(), D)
+
+ @pytest.mark.parametrize("slots", [True, False])
+ def test_clean_class(self, slots):
+ """
+ Attribute definitions do not appear on the class body.
+ """
+ C = make_class("C", ["x"], slots=slots)
+
+ x = getattr(C, "x", None)
+
+ assert not isinstance(x, _CountingAttr)
+
+ def test_missing_sys_getframe(self, monkeypatch):
+ """
+ `make_class()` does not fail when `sys._getframe()` is not available.
+ """
+ monkeypatch.delattr(sys, '_getframe')
+ C = make_class("C", ["x"])
+
+ assert 1 == len(C.__attrs_attrs__)
+
+
+class TestFields(object):
+ """
+ Tests for `fields`.
+ """
+ def test_instance(self, C):
+ """
+ Raises `TypeError` on non-classes.
+ """
+ with pytest.raises(TypeError) as e:
+ fields(C(1, 2))
+
+ assert "Passed object must be a class." == e.value.args[0]
+
+ def test_handler_non_attrs_class(self, C):
+ """
+ Raises `ValueError` if passed a non-``attrs`` instance.
+ """
+ with pytest.raises(NotAnAttrsClassError) as e:
+ fields(object)
+ assert (
+ "{o!r} is not an attrs-decorated class.".format(o=object)
+ ) == e.value.args[0]
+
+ @given(simple_classes())
+ def test_fields(self, C):
+ """
+ Returns a list of `Attribute`a.
+ """
+ assert all(isinstance(a, Attribute) for a in fields(C))
+
+ @given(simple_classes())
+ def test_fields_properties(self, C):
+ """
+ Fields returns a tuple with properties.
+ """
+ for attribute in fields(C):
+ assert getattr(fields(C), attribute.name) is attribute
+
+
+class TestConvert(object):
+ """
+ Tests for attribute conversion.
+ """
+ def test_convert(self):
+ """
+ Return value of convert is used as the attribute's value.
+ """
+ C = make_class("C", {
+ "x": attr.ib(convert=lambda v: v + 1),
+ "y": attr.ib(),
+ })
+ c = C(1, 2)
+
+ assert c.x == 2
+ assert c.y == 2
+
+ @given(integers(), booleans())
+ def test_convert_property(self, val, init):
+ """
+ Property tests for attributes with convert.
+ """
+ C = make_class("C", {
+ "y": attr.ib(),
+ "x": attr.ib(init=init, default=val, convert=lambda v: v + 1),
+ })
+ c = C(2)
+
+ assert c.x == val + 1
+ assert c.y == 2
+
+ @given(integers(), booleans())
+ def test_convert_factory_property(self, val, init):
+ """
+ Property tests for attributes with convert, and a factory default.
+ """
+ C = make_class("C", {
+ "y": attr.ib(),
+ "x": attr.ib(
+ init=init,
+ default=Factory(lambda: val),
+ convert=lambda v: v + 1),
+ })
+ c = C(2)
+
+ assert c.x == val + 1
+ assert c.y == 2
+
+ def test_factory_takes_self(self):
+ """
+ If takes_self on factories is True, self is passed.
+ """
+ C = make_class("C", {
+ "x": attr.ib(
+ default=Factory((lambda self: self), takes_self=True)
+ ),
+ })
+
+ i = C()
+
+ assert i is i.x
+
+ def test_factory_hashable(self):
+ """
+ Factory is hashable.
+ """
+ assert hash(Factory(None, False)) == hash(Factory(None, False))
+
+ def test_convert_before_validate(self):
+ """
+ Validation happens after conversion.
+ """
+ def validator(inst, attr, val):
+ raise RuntimeError("foo")
+ C = make_class(
+ "C", {
+ "x": attr.ib(validator=validator, convert=lambda v: 1 / 0),
+ "y": attr.ib(),
+ })
+ with pytest.raises(ZeroDivisionError):
+ C(1, 2)
+
+ def test_frozen(self):
+ """
+ Converters circumvent immutability.
+ """
+ C = make_class("C", {
+ "x": attr.ib(convert=lambda v: int(v)),
+ }, frozen=True)
+ C("1")
+
+
+class TestValidate(object):
+ """
+ Tests for `validate`.
+ """
+ def test_success(self):
+ """
+ If the validator succeeds, nothing gets raised.
+ """
+ C = make_class("C", {
+ "x": attr.ib(validator=lambda *a: None),
+ "y": attr.ib()
+ })
+ validate(C(1, 2))
+
+ def test_propagates(self):
+ """
+ The exception of the validator is handed through.
+ """
+ def raiser(_, __, value):
+ if value == 42:
+ raise FloatingPointError
+
+ C = make_class("C", {"x": attr.ib(validator=raiser)})
+ i = C(1)
+ i.x = 42
+
+ with pytest.raises(FloatingPointError):
+ validate(i)
+
+ def test_run_validators(self):
+ """
+ Setting `_run_validators` to False prevents validators from running.
+ """
+ _config._run_validators = False
+ obj = object()
+
+ def raiser(_, __, ___):
+ raise Exception(obj)
+
+ C = make_class("C", {"x": attr.ib(validator=raiser)})
+ c = C(1)
+ validate(c)
+ assert 1 == c.x
+ _config._run_validators = True
+
+ with pytest.raises(Exception):
+ validate(c)
+
+ with pytest.raises(Exception) as e:
+ C(1)
+ assert (obj,) == e.value.args
+
+ def test_multiple_validators(self):
+ """
+ If a list is passed as a validator, all of its items are treated as one
+ and must pass.
+ """
+ def v1(_, __, value):
+ if value == 23:
+ raise TypeError("omg")
+
+ def v2(_, __, value):
+ if value == 42:
+ raise ValueError("omg")
+
+ C = make_class("C", {"x": attr.ib(validator=[v1, v2])})
+
+ validate(C(1))
+
+ with pytest.raises(TypeError) as e:
+ C(23)
+
+ assert "omg" == e.value.args[0]
+
+ with pytest.raises(ValueError) as e:
+ C(42)
+
+ assert "omg" == e.value.args[0]
+
+ def test_multiple_empty(self):
+ """
+ Empty list/tuple for validator is the same as None.
+ """
+ C1 = make_class("C", {"x": attr.ib(validator=[])})
+ C2 = make_class("C", {"x": attr.ib(validator=None)})
+
+ assert inspect.getsource(C1.__init__) == inspect.getsource(C2.__init__)
+
+
+# Hypothesis seems to cache values, so the lists of attributes come out
+# unsorted.
+sorted_lists_of_attrs = list_of_attrs.map(
+ lambda l: sorted(l, key=attrgetter("counter")))
+
+
+class TestMetadata(object):
+ """
+ Tests for metadata handling.
+ """
+ @given(sorted_lists_of_attrs)
+ def test_metadata_present(self, list_of_attrs):
+ """
+ Assert dictionaries are copied and present.
+ """
+ C = make_class("C", dict(zip(gen_attr_names(), list_of_attrs)))
+
+ for hyp_attr, class_attr in zip(list_of_attrs, fields(C)):
+ if hyp_attr.metadata is None:
+ # The default is a singleton empty dict.
+ assert class_attr.metadata is not None
+ assert len(class_attr.metadata) == 0
+ else:
+ assert hyp_attr.metadata == class_attr.metadata
+
+ # Once more, just to assert getting items and iteration.
+ for k in class_attr.metadata:
+ assert hyp_attr.metadata[k] == class_attr.metadata[k]
+ assert (hyp_attr.metadata.get(k) ==
+ class_attr.metadata.get(k))
+
+ @given(simple_classes(), text())
+ def test_metadata_immutability(self, C, string):
+ """
+ The metadata dict should be best-effort immutable.
+ """
+ for a in fields(C):
+ with pytest.raises(TypeError):
+ a.metadata[string] = string
+ with pytest.raises(AttributeError):
+ a.metadata.update({string: string})
+ with pytest.raises(AttributeError):
+ a.metadata.clear()
+ with pytest.raises(AttributeError):
+ a.metadata.setdefault(string, string)
+
+ for k in a.metadata:
+ # For some reason, Python 3's MappingProxyType throws an
+ # IndexError for deletes on a large integer key.
+ with pytest.raises((TypeError, IndexError)):
+ del a.metadata[k]
+ with pytest.raises(AttributeError):
+ a.metadata.pop(k)
+ with pytest.raises(AttributeError):
+ a.metadata.popitem()
+
+ @given(lists(simple_attrs_without_metadata, min_size=2, max_size=5))
+ def test_empty_metadata_singleton(self, list_of_attrs):
+ """
+ All empty metadata attributes share the same empty metadata dict.
+ """
+ C = make_class("C", dict(zip(gen_attr_names(), list_of_attrs)))
+ for a in fields(C)[1:]:
+ assert a.metadata is fields(C)[0].metadata
+
+
+class TestClassBuilder(object):
+ """
+ Tests for `_ClassBuilder`.
+ """
+ def test_repr_str(self):
+ """
+ Trying to add a `__str__` without having a `__repr__` raises a
+ ValueError.
+ """
+ with pytest.raises(ValueError) as ei:
+ make_class("C", {}, repr=False, str=True)
+
+ assert (
+ "__str__ can only be generated if a __repr__ exists.",
+ ) == ei.value.args
+
+ def test_repr(self):
+ """
+ repr of builder itself makes sense.
+ """
+ class C(object):
+ pass
+
+ b = _ClassBuilder(C, None, True, True, False)
+
+ assert "<_ClassBuilder(cls=C)>" == repr(b)
+
+ def test_returns_self(self):
+ """
+ All methods return the builder for chaining.
+ """
+ class C(object):
+ x = attr.ib()
+
+ b = _ClassBuilder(C, None, True, True, False)
+
+ cls = b.add_cmp().add_hash().add_init().add_repr("ns").add_str() \
+ .build_class()
+
+ assert "ns.C(x=1)" == repr(cls(1))
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_slots.py b/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_slots.py
new file mode 100644
index 00000000000..516a797b757
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_slots.py
@@ -0,0 +1,423 @@
+"""
+Unit tests for slot-related functionality.
+"""
+
+import pytest
+
+import attr
+
+from attr._compat import PY2, PYPY, just_warn, make_set_closure_cell
+
+
+# Pympler doesn't work on PyPy.
+try:
+ from pympler.asizeof import asizeof
+ has_pympler = True
+except BaseException: # Won't be an import error.
+ has_pympler = False
+
+
+@attr.s
+class C1(object):
+ x = attr.ib(validator=attr.validators.instance_of(int))
+ y = attr.ib()
+
+ def method(self):
+ return self.x
+
+ @classmethod
+ def classmethod(cls):
+ return "clsmethod"
+
+ @staticmethod
+ def staticmethod():
+ return "staticmethod"
+
+ if not PY2:
+ def my_class(self):
+ return __class__ # NOQA: F821
+
+ def my_super(self):
+ """Just to test out the no-arg super."""
+ return super().__repr__()
+
+
+@attr.s(slots=True, hash=True)
+class C1Slots(object):
+ x = attr.ib(validator=attr.validators.instance_of(int))
+ y = attr.ib()
+
+ def method(self):
+ return self.x
+
+ @classmethod
+ def classmethod(cls):
+ return "clsmethod"
+
+ @staticmethod
+ def staticmethod():
+ return "staticmethod"
+
+ if not PY2:
+ def my_class(self):
+ return __class__ # NOQA: F821
+
+ def my_super(self):
+ """Just to test out the no-arg super."""
+ return super().__repr__()
+
+
+def test_slots_being_used():
+ """
+ The class is really using __slots__.
+ """
+ non_slot_instance = C1(x=1, y="test")
+ slot_instance = C1Slots(x=1, y="test")
+
+ assert "__dict__" not in dir(slot_instance)
+ assert "__slots__" in dir(slot_instance)
+
+ assert "__dict__" in dir(non_slot_instance)
+ assert "__slots__" not in dir(non_slot_instance)
+
+ assert set(["x", "y"]) == set(slot_instance.__slots__)
+
+ if has_pympler:
+ assert asizeof(slot_instance) < asizeof(non_slot_instance)
+
+ non_slot_instance.t = "test"
+ with pytest.raises(AttributeError):
+ slot_instance.t = "test"
+
+ assert 1 == non_slot_instance.method()
+ assert 1 == slot_instance.method()
+
+ assert attr.fields(C1Slots) == attr.fields(C1)
+ assert attr.asdict(slot_instance) == attr.asdict(non_slot_instance)
+
+
+def test_basic_attr_funcs():
+ """
+ Comparison, `__eq__`, `__hash__`, `__repr__`, `attrs.asdict` work.
+ """
+ a = C1Slots(x=1, y=2)
+ b = C1Slots(x=1, y=3)
+ a_ = C1Slots(x=1, y=2)
+
+ # Comparison.
+ assert b > a
+
+ assert a_ == a
+
+ # Hashing.
+ hash(b) # Just to assert it doesn't raise.
+
+ # Repr.
+ assert "C1Slots(x=1, y=2)" == repr(a)
+
+ assert {"x": 1, "y": 2} == attr.asdict(a)
+
+
+def test_inheritance_from_nonslots():
+ """
+ Inheritance from a non-slot class works.
+
+ Note that a slots class inheriting from an ordinary class loses most of the
+ benefits of slots classes, but it should still work.
+ """
+ @attr.s(slots=True, hash=True)
+ class C2Slots(C1):
+ z = attr.ib()
+
+ c2 = C2Slots(x=1, y=2, z="test")
+
+ assert 1 == c2.x
+ assert 2 == c2.y
+ assert "test" == c2.z
+
+ c2.t = "test" # This will work, using the base class.
+
+ assert "test" == c2.t
+
+ assert 1 == c2.method()
+ assert "clsmethod" == c2.classmethod()
+ assert "staticmethod" == c2.staticmethod()
+
+ assert set(["z"]) == set(C2Slots.__slots__)
+
+ c3 = C2Slots(x=1, y=3, z="test")
+
+ assert c3 > c2
+
+ c2_ = C2Slots(x=1, y=2, z="test")
+
+ assert c2 == c2_
+
+ assert "C2Slots(x=1, y=2, z='test')" == repr(c2)
+
+ hash(c2) # Just to assert it doesn't raise.
+
+ assert {"x": 1, "y": 2, "z": "test"} == attr.asdict(c2)
+
+
+def test_nonslots_these():
+ """
+ Enhancing a non-slots class using 'these' works.
+
+ This will actually *replace* the class with another one, using slots.
+ """
+ class SimpleOrdinaryClass(object):
+ def __init__(self, x, y, z):
+ self.x = x
+ self.y = y
+ self.z = z
+
+ def method(self):
+ return self.x
+
+ @classmethod
+ def classmethod(cls):
+ return "clsmethod"
+
+ @staticmethod
+ def staticmethod():
+ return "staticmethod"
+
+ C2Slots = attr.s(these={"x": attr.ib(), "y": attr.ib(), "z": attr.ib()},
+ init=False, slots=True, hash=True)(SimpleOrdinaryClass)
+
+ c2 = C2Slots(x=1, y=2, z="test")
+ assert 1 == c2.x
+ assert 2 == c2.y
+ assert "test" == c2.z
+ with pytest.raises(AttributeError):
+ c2.t = "test" # We have slots now.
+
+ assert 1 == c2.method()
+ assert "clsmethod" == c2.classmethod()
+ assert "staticmethod" == c2.staticmethod()
+
+ assert set(["x", "y", "z"]) == set(C2Slots.__slots__)
+
+ c3 = C2Slots(x=1, y=3, z="test")
+ assert c3 > c2
+ c2_ = C2Slots(x=1, y=2, z="test")
+ assert c2 == c2_
+
+ assert "SimpleOrdinaryClass(x=1, y=2, z='test')" == repr(c2)
+
+ hash(c2) # Just to assert it doesn't raise.
+
+ assert {"x": 1, "y": 2, "z": "test"} == attr.asdict(c2)
+
+
+def test_inheritance_from_slots():
+ """
+ Inheriting from an attr slot class works.
+ """
+ @attr.s(slots=True, hash=True)
+ class C2Slots(C1Slots):
+ z = attr.ib()
+
+ @attr.s(slots=True, hash=True)
+ class C2(C1):
+ z = attr.ib()
+
+ c2 = C2Slots(x=1, y=2, z="test")
+ assert 1 == c2.x
+ assert 2 == c2.y
+ assert "test" == c2.z
+
+ assert set(["z"]) == set(C2Slots.__slots__)
+
+ assert 1 == c2.method()
+ assert "clsmethod" == c2.classmethod()
+ assert "staticmethod" == c2.staticmethod()
+
+ with pytest.raises(AttributeError):
+ c2.t = "test"
+
+ non_slot_instance = C2(x=1, y=2, z="test")
+ if has_pympler:
+ assert asizeof(c2) < asizeof(non_slot_instance)
+
+ c3 = C2Slots(x=1, y=3, z="test")
+ assert c3 > c2
+ c2_ = C2Slots(x=1, y=2, z="test")
+ assert c2 == c2_
+
+ assert "C2Slots(x=1, y=2, z='test')" == repr(c2)
+
+ hash(c2) # Just to assert it doesn't raise.
+
+ assert {"x": 1, "y": 2, "z": "test"} == attr.asdict(c2)
+
+
+def test_bare_inheritance_from_slots():
+ """
+ Inheriting from a bare attr slot class works.
+ """
+ @attr.s(init=False, cmp=False, hash=False, repr=False, slots=True)
+ class C1BareSlots(object):
+ x = attr.ib(validator=attr.validators.instance_of(int))
+ y = attr.ib()
+
+ def method(self):
+ return self.x
+
+ @classmethod
+ def classmethod(cls):
+ return "clsmethod"
+
+ @staticmethod
+ def staticmethod():
+ return "staticmethod"
+
+ @attr.s(init=False, cmp=False, hash=False, repr=False)
+ class C1Bare(object):
+ x = attr.ib(validator=attr.validators.instance_of(int))
+ y = attr.ib()
+
+ def method(self):
+ return self.x
+
+ @classmethod
+ def classmethod(cls):
+ return "clsmethod"
+
+ @staticmethod
+ def staticmethod():
+ return "staticmethod"
+
+ @attr.s(slots=True, hash=True)
+ class C2Slots(C1BareSlots):
+ z = attr.ib()
+
+ @attr.s(slots=True, hash=True)
+ class C2(C1Bare):
+ z = attr.ib()
+
+ c2 = C2Slots(x=1, y=2, z="test")
+ assert 1 == c2.x
+ assert 2 == c2.y
+ assert "test" == c2.z
+
+ assert 1 == c2.method()
+ assert "clsmethod" == c2.classmethod()
+ assert "staticmethod" == c2.staticmethod()
+
+ with pytest.raises(AttributeError):
+ c2.t = "test"
+
+ non_slot_instance = C2(x=1, y=2, z="test")
+ if has_pympler:
+ assert asizeof(c2) < asizeof(non_slot_instance)
+
+ c3 = C2Slots(x=1, y=3, z="test")
+ assert c3 > c2
+ c2_ = C2Slots(x=1, y=2, z="test")
+ assert c2 == c2_
+
+ assert "C2Slots(x=1, y=2, z='test')" == repr(c2)
+
+ hash(c2) # Just to assert it doesn't raise.
+
+ assert {"x": 1, "y": 2, "z": "test"} == attr.asdict(c2)
+
+
+@pytest.mark.skipif(PY2, reason="closure cell rewriting is PY3-only.")
+class TestClosureCellRewriting(object):
+ def test_closure_cell_rewriting(self):
+ """
+ Slot classes support proper closure cell rewriting.
+
+ This affects features like `__class__` and the no-arg super().
+ """
+ non_slot_instance = C1(x=1, y="test")
+ slot_instance = C1Slots(x=1, y="test")
+
+ assert non_slot_instance.my_class() is C1
+ assert slot_instance.my_class() is C1Slots
+
+ # Just assert they return something, and not an exception.
+ assert non_slot_instance.my_super()
+ assert slot_instance.my_super()
+
+ def test_inheritance(self):
+ """
+ Slot classes support proper closure cell rewriting when inheriting.
+
+ This affects features like `__class__` and the no-arg super().
+ """
+ @attr.s
+ class C2(C1):
+ def my_subclass(self):
+ return __class__ # NOQA: F821
+
+ @attr.s
+ class C2Slots(C1Slots):
+ def my_subclass(self):
+ return __class__ # NOQA: F821
+
+ non_slot_instance = C2(x=1, y="test")
+ slot_instance = C2Slots(x=1, y="test")
+
+ assert non_slot_instance.my_class() is C1
+ assert slot_instance.my_class() is C1Slots
+
+ # Just assert they return something, and not an exception.
+ assert non_slot_instance.my_super()
+ assert slot_instance.my_super()
+
+ assert non_slot_instance.my_subclass() is C2
+ assert slot_instance.my_subclass() is C2Slots
+
+ @pytest.mark.parametrize("slots", [True, False])
+ def test_cls_static(self, slots):
+ """
+ Slot classes support proper closure cell rewriting for class- and
+ static methods.
+ """
+ # Python can reuse closure cells, so we create new classes just for
+ # this test.
+
+ @attr.s(slots=slots)
+ class C:
+ @classmethod
+ def clsmethod(cls):
+ return __class__ # noqa: F821
+
+ assert C.clsmethod() is C
+
+ @attr.s(slots=slots)
+ class D:
+ @staticmethod
+ def statmethod():
+ return __class__ # noqa: F821
+
+ assert D.statmethod() is D
+
+ @pytest.mark.skipif(
+ PYPY,
+ reason="ctypes are used only on CPython"
+ )
+ def test_missing_ctypes(self, monkeypatch):
+ """
+ Keeps working if ctypes is missing.
+
+ A warning is emitted that points to the actual code.
+ """
+ monkeypatch.setattr(attr._compat, "import_ctypes", lambda: None)
+ func = make_set_closure_cell()
+
+ with pytest.warns(RuntimeWarning) as wr:
+ func()
+
+ w = wr.pop()
+ assert __file__ == w.filename
+ assert (
+ "Missing ctypes. Some features like bare super() or accessing "
+ "__class__ will not work with slots classes.",
+ ) == w.message.args
+
+ assert just_warn is func
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_validators.py b/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_validators.py
new file mode 100644
index 00000000000..9722da27fdb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/test_validators.py
@@ -0,0 +1,266 @@
+"""
+Tests for `attr.validators`.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+import pytest
+import zope.interface
+
+import attr
+
+from attr import validators as validator_module
+from attr import has
+from attr._compat import TYPE
+from attr.validators import and_, in_, instance_of, optional, provides
+
+from .utils import simple_attr
+
+
+class TestInstanceOf(object):
+ """
+ Tests for `instance_of`.
+ """
+ def test_success(self):
+ """
+ Nothing happens if types match.
+ """
+ v = instance_of(int)
+ v(None, simple_attr("test"), 42)
+
+ def test_subclass(self):
+ """
+ Subclasses are accepted too.
+ """
+ v = instance_of(int)
+ # yep, bools are a subclass of int :(
+ v(None, simple_attr("test"), True)
+
+ def test_fail(self):
+ """
+ Raises `TypeError` on wrong types.
+ """
+ v = instance_of(int)
+ a = simple_attr("test")
+ with pytest.raises(TypeError) as e:
+ v(None, a, "42")
+ assert (
+ "'test' must be <{type} 'int'> (got '42' that is a <{type} "
+ "'str'>).".format(type=TYPE),
+ a, int, "42",
+
+ ) == e.value.args
+
+ def test_repr(self):
+ """
+ Returned validator has a useful `__repr__`.
+ """
+ v = instance_of(int)
+ assert (
+ "<instance_of validator for type <{type} 'int'>>"
+ .format(type=TYPE)
+ ) == repr(v)
+
+
+def always_pass(_, __, ___):
+ """
+ Toy validator that always passses.
+ """
+
+
+def always_fail(_, __, ___):
+ """
+ Toy validator that always fails.
+ """
+ 0/0
+
+
+class TestAnd(object):
+ def test_success(self):
+ """
+ Succeeds if all wrapped validators succeed.
+ """
+ v = and_(instance_of(int), always_pass)
+
+ v(None, simple_attr("test"), 42)
+
+ def test_fail(self):
+ """
+ Fails if any wrapped validator fails.
+ """
+ v = and_(instance_of(int), always_fail)
+
+ with pytest.raises(ZeroDivisionError):
+ v(None, simple_attr("test"), 42)
+
+ def test_sugar(self):
+ """
+ `and_(v1, v2, v3)` and `[v1, v2, v3]` are equivalent.
+ """
+ @attr.s
+ class C(object):
+ a1 = attr.ib("a1", validator=and_(
+ instance_of(int),
+ ))
+ a2 = attr.ib("a2", validator=[
+ instance_of(int),
+ ])
+
+ assert C.__attrs_attrs__[0].validator == C.__attrs_attrs__[1].validator
+
+
+class IFoo(zope.interface.Interface):
+ """
+ An interface.
+ """
+ def f():
+ """
+ A function called f.
+ """
+
+
+class TestProvides(object):
+ """
+ Tests for `provides`.
+ """
+ def test_success(self):
+ """
+ Nothing happens if value provides requested interface.
+ """
+ @zope.interface.implementer(IFoo)
+ class C(object):
+ def f(self):
+ pass
+
+ v = provides(IFoo)
+ v(None, simple_attr("x"), C())
+
+ def test_fail(self):
+ """
+ Raises `TypeError` if interfaces isn't provided by value.
+ """
+ value = object()
+ a = simple_attr("x")
+
+ v = provides(IFoo)
+ with pytest.raises(TypeError) as e:
+ v(None, a, value)
+ assert (
+ "'x' must provide {interface!r} which {value!r} doesn't."
+ .format(interface=IFoo, value=value),
+ a, IFoo, value,
+ ) == e.value.args
+
+ def test_repr(self):
+ """
+ Returned validator has a useful `__repr__`.
+ """
+ v = provides(IFoo)
+ assert (
+ "<provides validator for interface {interface!r}>"
+ .format(interface=IFoo)
+ ) == repr(v)
+
+
+@pytest.mark.parametrize("validator", [
+ instance_of(int),
+ [always_pass, instance_of(int)],
+])
+class TestOptional(object):
+ """
+ Tests for `optional`.
+ """
+ def test_success(self, validator):
+ """
+ Nothing happens if validator succeeds.
+ """
+ v = optional(validator)
+ v(None, simple_attr("test"), 42)
+
+ def test_success_with_none(self, validator):
+ """
+ Nothing happens if None.
+ """
+ v = optional(validator)
+ v(None, simple_attr("test"), None)
+
+ def test_fail(self, validator):
+ """
+ Raises `TypeError` on wrong types.
+ """
+ v = optional(validator)
+ a = simple_attr("test")
+ with pytest.raises(TypeError) as e:
+ v(None, a, "42")
+ assert (
+ "'test' must be <{type} 'int'> (got '42' that is a <{type} "
+ "'str'>).".format(type=TYPE),
+ a, int, "42",
+
+ ) == e.value.args
+
+ def test_repr(self, validator):
+ """
+ Returned validator has a useful `__repr__`.
+ """
+ v = optional(validator)
+
+ if isinstance(validator, list):
+ assert (
+ ("<optional validator for _AndValidator(_validators=[{func}, "
+ "<instance_of validator for type <{type} 'int'>>]) or None>")
+ .format(func=repr(always_pass), type=TYPE)
+ ) == repr(v)
+ else:
+ assert (
+ ("<optional validator for <instance_of validator for type "
+ "<{type} 'int'>> or None>")
+ .format(type=TYPE)
+ ) == repr(v)
+
+
+class TestIn_(object):
+ """
+ Tests for `in_`.
+ """
+ def test_success_with_value(self):
+ """
+ If the value is in our options, nothing happens.
+ """
+ v = in_([1, 2, 3])
+ a = simple_attr("test")
+ v(1, a, 3)
+
+ def test_fail(self):
+ """
+ Raise ValueError if the value is outside our options.
+ """
+ v = in_([1, 2, 3])
+ a = simple_attr("test")
+ with pytest.raises(ValueError) as e:
+ v(None, a, None)
+ assert (
+ "'test' must be in [1, 2, 3] (got None)",
+ ) == e.value.args
+
+ def test_repr(self):
+ """
+ Returned validator has a useful `__repr__`.
+ """
+ v = in_([3, 4, 5])
+ assert(
+ ("<in_ validator with options [3, 4, 5]>")
+ ) == repr(v)
+
+
+def test_hashability():
+ """
+ Validator classes are hashable.
+ """
+ for obj_name in dir(validator_module):
+ obj = getattr(validator_module, obj_name)
+ if not has(obj):
+ continue
+ hash_func = getattr(obj, '__hash__', None)
+ assert hash_func is not None
+ assert hash_func is not object.__hash__
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/utils.py b/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/utils.py
new file mode 100644
index 00000000000..36b624981e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/tests/utils.py
@@ -0,0 +1,237 @@
+"""
+Common helper functions for tests.
+"""
+
+from __future__ import absolute_import, division, print_function
+
+import keyword
+import string
+
+from collections import OrderedDict
+
+from hypothesis import strategies as st
+
+import attr
+
+from attr import Attribute
+from attr._make import NOTHING, make_class
+
+
+def simple_class(cmp=False, repr=False, hash=False, str=False, slots=False,
+ frozen=False):
+ """
+ Return a new simple class.
+ """
+ return make_class(
+ "C", ["a", "b"],
+ cmp=cmp, repr=repr, hash=hash, init=True, slots=slots, str=str,
+ frozen=frozen,
+ )
+
+
+def simple_attr(name, default=NOTHING, validator=None, repr=True,
+ cmp=True, hash=None, init=True):
+ """
+ Return an attribute with a name and no other bells and whistles.
+ """
+ return Attribute(
+ name=name, default=default, validator=validator, repr=repr,
+ cmp=cmp, hash=hash, init=init
+ )
+
+
+class TestSimpleClass(object):
+ """
+ Tests for the testing helper function `make_class`.
+ """
+ def test_returns_class(self):
+ """
+ Returns a class object.
+ """
+ assert type is simple_class().__class__
+
+ def returns_distinct_classes(self):
+ """
+ Each call returns a completely new class.
+ """
+ assert simple_class() is not simple_class()
+
+
+def gen_attr_names():
+ """
+ Generate names for attributes, 'a'...'z', then 'aa'...'zz'.
+
+ ~702 different attribute names should be enough in practice.
+
+ Some short strings (such as 'as') are keywords, so we skip them.
+ """
+ lc = string.ascii_lowercase
+ for c in lc:
+ yield c
+ for outer in lc:
+ for inner in lc:
+ res = outer + inner
+ if keyword.iskeyword(res):
+ continue
+ yield outer + inner
+
+
+def maybe_underscore_prefix(source):
+ """
+ A generator to sometimes prepend an underscore.
+ """
+ to_underscore = False
+ for val in source:
+ yield val if not to_underscore else '_' + val
+ to_underscore = not to_underscore
+
+
+def _create_hyp_class(attrs):
+ """
+ A helper function for Hypothesis to generate attrs classes.
+ """
+ return make_class(
+ "HypClass", dict(zip(gen_attr_names(), attrs))
+ )
+
+
+def _create_hyp_nested_strategy(simple_class_strategy):
+ """
+ Create a recursive attrs class.
+
+ Given a strategy for building (simpler) classes, create and return
+ a strategy for building classes that have as an attribute: either just
+ the simpler class, a list of simpler classes, a tuple of simpler classes,
+ an ordered dict or a dict mapping the string "cls" to a simpler class.
+ """
+ # Use a tuple strategy to combine simple attributes and an attr class.
+ def just_class(tup):
+ combined_attrs = list(tup[0])
+ combined_attrs.append(attr.ib(default=attr.Factory(tup[1])))
+ return _create_hyp_class(combined_attrs)
+
+ def list_of_class(tup):
+ default = attr.Factory(lambda: [tup[1]()])
+ combined_attrs = list(tup[0])
+ combined_attrs.append(attr.ib(default=default))
+ return _create_hyp_class(combined_attrs)
+
+ def tuple_of_class(tup):
+ default = attr.Factory(lambda: (tup[1](),))
+ combined_attrs = list(tup[0])
+ combined_attrs.append(attr.ib(default=default))
+ return _create_hyp_class(combined_attrs)
+
+ def dict_of_class(tup):
+ default = attr.Factory(lambda: {"cls": tup[1]()})
+ combined_attrs = list(tup[0])
+ combined_attrs.append(attr.ib(default=default))
+ return _create_hyp_class(combined_attrs)
+
+ def ordereddict_of_class(tup):
+ default = attr.Factory(lambda: OrderedDict([("cls", tup[1]())]))
+ combined_attrs = list(tup[0])
+ combined_attrs.append(attr.ib(default=default))
+ return _create_hyp_class(combined_attrs)
+
+ # A strategy producing tuples of the form ([list of attributes], <given
+ # class strategy>).
+ attrs_and_classes = st.tuples(list_of_attrs, simple_class_strategy)
+
+ return st.one_of(attrs_and_classes.map(just_class),
+ attrs_and_classes.map(list_of_class),
+ attrs_and_classes.map(tuple_of_class),
+ attrs_and_classes.map(dict_of_class),
+ attrs_and_classes.map(ordereddict_of_class))
+
+
+bare_attrs = st.just(attr.ib(default=None))
+int_attrs = st.integers().map(lambda i: attr.ib(default=i))
+str_attrs = st.text().map(lambda s: attr.ib(default=s))
+float_attrs = st.floats().map(lambda f: attr.ib(default=f))
+dict_attrs = (st.dictionaries(keys=st.text(), values=st.integers())
+ .map(lambda d: attr.ib(default=d)))
+
+simple_attrs_without_metadata = (bare_attrs | int_attrs | str_attrs |
+ float_attrs | dict_attrs)
+
+
+@st.composite
+def simple_attrs_with_metadata(draw):
+ """
+ Create a simple attribute with arbitrary metadata.
+ """
+ c_attr = draw(simple_attrs)
+ keys = st.booleans() | st.binary() | st.integers() | st.text()
+ vals = st.booleans() | st.binary() | st.integers() | st.text()
+ metadata = draw(st.dictionaries(keys=keys, values=vals))
+
+ return attr.ib(c_attr._default, c_attr._validator, c_attr.repr,
+ c_attr.cmp, c_attr.hash, c_attr.init, c_attr.convert,
+ metadata)
+
+
+simple_attrs = simple_attrs_without_metadata | simple_attrs_with_metadata()
+
+# Python functions support up to 255 arguments.
+list_of_attrs = st.lists(simple_attrs, average_size=3, max_size=9)
+
+
+@st.composite
+def simple_classes(draw, slots=None, frozen=None, private_attrs=None):
+ """
+ A strategy that generates classes with default non-attr attributes.
+
+ For example, this strategy might generate a class such as:
+
+ @attr.s(slots=True, frozen=True)
+ class HypClass:
+ a = attr.ib(default=1)
+ _b = attr.ib(default=None)
+ c = attr.ib(default='text')
+ _d = attr.ib(default=1.0)
+ c = attr.ib(default={'t': 1})
+
+ By default, all combinations of slots and frozen classes will be generated.
+ If `slots=True` is passed in, only slots classes will be generated, and
+ if `slots=False` is passed in, no slot classes will be generated. The same
+ applies to `frozen`.
+
+ By default, some attributes will be private (i.e. prefixed with an
+ underscore). If `private_attrs=True` is passed in, all attributes will be
+ private, and if `private_attrs=False`, no attributes will be private.
+ """
+ attrs = draw(list_of_attrs)
+ frozen_flag = draw(st.booleans()) if frozen is None else frozen
+ slots_flag = draw(st.booleans()) if slots is None else slots
+
+ if private_attrs is None:
+ attr_names = maybe_underscore_prefix(gen_attr_names())
+ elif private_attrs is True:
+ attr_names = ('_' + n for n in gen_attr_names())
+ elif private_attrs is False:
+ attr_names = gen_attr_names()
+
+ cls_dict = dict(zip(attr_names, attrs))
+ post_init_flag = draw(st.booleans())
+ if post_init_flag:
+ def post_init(self):
+ pass
+ cls_dict["__attrs_post_init__"] = post_init
+
+ return make_class(
+ "HypClass",
+ cls_dict,
+ slots=slots_flag,
+ frozen=frozen_flag,
+ )
+
+
+# st.recursive works by taking a base strategy (in this case, simple_classes)
+# and a special function. This function receives a strategy, and returns
+# another strategy (building on top of the base strategy).
+nested_classes = st.recursive(
+ simple_classes(),
+ _create_hyp_nested_strategy,
+ max_leaves=10
+)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/attrs/tox.ini b/tests/wpt/web-platform-tests/tools/third_party/attrs/tox.ini
new file mode 100644
index 00000000000..e02c3301025
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/attrs/tox.ini
@@ -0,0 +1,83 @@
+[tox]
+envlist = isort,py27,py34,py35,py36,pypy,pypy3,flake8,manifest,docs,readme,changelog,coverage-report
+
+
+[testenv]
+# Prevent random setuptools/pip breakages like
+# https://github.com/pypa/setuptools/issues/1042 from breaking our builds.
+setenv =
+ VIRTUALENV_NO_DOWNLOAD=1
+deps = -rdev-requirements.txt
+commands = python -m pytest {posargs}
+
+
+[testenv:py27]
+deps = -rdev-requirements.txt
+commands = coverage run --parallel -m pytest {posargs}
+
+
+[testenv:py36]
+deps = -rdev-requirements.txt
+commands = coverage run --parallel -m pytest {posargs}
+
+
+# Uses default basepython otherwise reporting doesn't work on Travis where
+# Python 3.6 is only available in 3.6 jobs.
+[testenv:coverage-report]
+deps = coverage
+skip_install = true
+commands =
+ coverage combine
+ coverage report
+
+
+[testenv:flake8]
+basepython = python3.6
+# Needs a full install so isort can determine own/foreign imports.
+deps =
+ -rdev-requirements.txt
+ flake8
+ flake8-isort
+commands = flake8 src tests setup.py conftest.py docs/conf.py
+
+
+[testenv:isort]
+basepython = python3.6
+# Needs a full install so isort can determine own/foreign imports.
+deps =
+ -rdev-requirements.txt
+ isort
+commands =
+ isort --recursive setup.py conftest.py src tests
+
+
+[testenv:docs]
+basepython = python3.6
+setenv =
+ PYTHONHASHSEED = 0
+deps = -rdocs-requirements.txt
+commands =
+ sphinx-build -W -b html -d {envtmpdir}/doctrees docs docs/_build/html
+ sphinx-build -W -b doctest -d {envtmpdir}/doctrees docs docs/_build/html
+ python -m doctest README.rst
+
+
+[testenv:manifest]
+basepython = python3.6
+deps = check-manifest
+skip_install = true
+commands = check-manifest
+
+
+[testenv:readme]
+basepython = python3.6
+deps = readme_renderer
+skip_install = true
+commands = python setup.py check -r -s
+
+
+[testenv:changelog]
+basepython = python3.6
+deps = towncrier
+skip_install = true
+commands = towncrier --draft
diff --git a/tests/wpt/web-platform-tests/tools/third_party/funcsigs/.travis.yml b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/.travis.yml
new file mode 100644
index 00000000000..d2a7ab3051a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/.travis.yml
@@ -0,0 +1,17 @@
+language: python
+python:
+ - 2.6
+ - 2.7
+ - 3.2
+ - 3.3
+ - pypy
+install:
+ - pip install -r requirements/development.txt -r requirements/production.txt
+ - python setup.py install
+script:
+ - coverage run setup.py test
+ - coverage report --show-missing
+after_success:
+ - coveralls
+notifications:
+ email: aaron.iles+travis-ci@gmail.com
diff --git a/tests/wpt/web-platform-tests/tools/third_party/funcsigs/CHANGELOG b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/CHANGELOG
new file mode 100644
index 00000000000..602eec5e7c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/CHANGELOG
@@ -0,0 +1,19 @@
+Changelog
+---------
+
+0.4 (2013-12-20)
+````````````````
+* Fix unbound methods getting their first parameter curried
+* Publish Python wheel packages
+
+0.3 (2013-05-29)
+````````````````
+* Fix annotation formatting of builtin types on Python 2.x
+
+0.2 (2012-01-07)
+````````````````
+* PyPy compatability
+
+0.1 (2012-01-06)
+````````````````
+* Initial release
diff --git a/tests/wpt/web-platform-tests/tools/third_party/funcsigs/LICENSE b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/LICENSE
new file mode 100644
index 00000000000..3e563d6fbd4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/LICENSE
@@ -0,0 +1,13 @@
+Copyright 2013 Aaron Iles
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/funcsigs/MANIFEST.in b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/MANIFEST.in
new file mode 100644
index 00000000000..f0abb42f04a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/MANIFEST.in
@@ -0,0 +1,7 @@
+recursive-include docs *
+recursive-include tests *.py
+include *.py
+include CHANGELOG
+include LICENSE
+include MANIFEST.in
+include README.rst
diff --git a/tests/wpt/web-platform-tests/tools/third_party/funcsigs/Makefile b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/Makefile
new file mode 100644
index 00000000000..e2329231b56
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/Makefile
@@ -0,0 +1,39 @@
+SHELL := /bin/bash
+
+deps:
+ pip install --upgrade \
+ -r requirements/development.txt \
+ -r requirements/production.txt
+
+sdist:
+ python setup.py sdist
+ python setup.py bdist_wheel
+
+register:
+ python setup.py register
+ python setup.py sdist upload
+ python setup.py bdist_wheel upload
+
+site:
+ cd docs; make html
+
+test:
+ coverage run setup.py test
+
+unittest:
+ coverage run -m unittest discover
+
+lint:
+ flake8 --exit-zero funcsigs tests
+
+coverage:
+ coverage report --show-missing
+
+clean:
+ python setup.py clean --all
+ find . -type f -name "*.pyc" -exec rm '{}' +
+ find . -type d -name "__pycache__" -exec rmdir '{}' +
+ rm -rf *.egg-info .coverage
+ cd docs; make clean
+
+docs: site
diff --git a/tests/wpt/web-platform-tests/tools/third_party/funcsigs/README.rst b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/README.rst
new file mode 100644
index 00000000000..f04b7b422cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/README.rst
@@ -0,0 +1,83 @@
+funcsigs
+========
+
+``funcsigs`` is a backport of the `PEP 362`_ function signature features from
+Python 3.3's `inspect`_ module. The backport is compatible with Python 2.6, 2.7
+as well as 3.2 and up.
+
+|pypi_version|
+
+Documentation
+-------------
+
+The reference documentation is standard library documentation for the
+`inspect`_ module in Python3. This documentation has been included in the
+``funcsigs`` package documentation hosted on `Read The Docs`_.
+
+Example
+-------
+
+To obtain a signature object, pass the target function to the
+``funcsigs.signature`` function. ::
+
+ >>> from funcsigs import signature
+ >>> def foo(a, b=None, *args, **kwargs):
+ ... pass
+
+ >>> sig = signature(foo)
+
+For the details of the signature object, refer to the either the package of
+standard library documentation.
+
+Compatability
+-------------
+
+The ``funcsigs`` backport has been tested against:
+
+* CPython 2.6
+* CPython 2.7
+* CPython 3.2
+* PyPy 1.9
+
+Continuous integration testing is provided by `Travis CI`_.
+
+Under Python 2.x there is a compatability issue when a function is assigned to
+the ``__wrapped__`` property of a class after it has been constructed.
+Similiarily there under PyPy directly passing the ``__call__`` method of a
+builtin is also a compatability issues. Otherwise the functionality is
+believed to be uniform between both Python2 and Python3.
+
+Issues
+------
+
+Source code for ``funcsigs`` is hosted on `GitHub`_. Any bug reports or feature
+requests can be made using GitHub's `issues system`_. |build_status| |coverage|
+
+Copyright
+---------
+
+This is a derived work of CPython under the terms of the `PSF License
+Agreement`_. The original CPython inspect module, its unit tests and
+documentation are the copyright of the Python Software Foundation. The derived
+work is distributed under the `Apache License Version 2.0`_.
+
+.. _Apache License Version 2.0: http://opensource.org/licenses/Apache-2.0
+.. _GitHub: https://github.com/aliles/funcsigs
+.. _PSF License Agreement: http://docs.python.org/3/license.html#terms-and-conditions-for-accessing-or-otherwise-using-python
+.. _Travis CI: http://travis-ci.org/
+.. _Read The Docs: http://funcsigs.readthedocs.org/
+.. _PEP 362: http://www.python.org/dev/peps/pep-0362/
+.. _inspect: http://docs.python.org/3/library/inspect.html#introspecting-callables-with-the-signature-object
+.. _issues system: https://github.com/alies/funcsigs/issues
+
+.. |build_status| image:: https://secure.travis-ci.org/aliles/funcsigs.png?branch=master
+ :target: http://travis-ci.org/#!/aliles/funcsigs
+ :alt: Current build status
+
+.. |coverage| image:: https://coveralls.io/repos/aliles/funcsigs/badge.png?branch=master
+ :target: https://coveralls.io/r/aliles/funcsigs?branch=master
+ :alt: Coverage status
+
+.. |pypi_version| image:: https://pypip.in/v/funcsigs/badge.png
+ :target: https://crate.io/packages/funcsigs/
+ :alt: Latest PyPI version
diff --git a/tests/wpt/web-platform-tests/tools/third_party/funcsigs/docs/Makefile b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/docs/Makefile
new file mode 100644
index 00000000000..f7ab3d16b40
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/docs/Makefile
@@ -0,0 +1,153 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = _build
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " singlehtml to make a single large HTML file"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " devhelp to make HTML files and a Devhelp project"
+ @echo " epub to make an epub"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " text to make text files"
+ @echo " man to make manual pages"
+ @echo " texinfo to make Texinfo files"
+ @echo " info to make Texinfo files and run them through makeinfo"
+ @echo " gettext to make PO message catalogs"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+ -rm -rf $(BUILDDIR)
+
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/funcsigs.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/funcsigs.qhc"
+
+devhelp:
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+ @echo
+ @echo "Build finished."
+ @echo "To view the help file:"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/funcsigs"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/funcsigs"
+ @echo "# devhelp"
+
+epub:
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
+ "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+ @echo
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+ @echo
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo
+ @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+ @echo "Run \`make' in that directory to run these through makeinfo" \
+ "(use \`make info' here to do that automatically)."
+
+info:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo "Running Texinfo files through makeinfo..."
+ make -C $(BUILDDIR)/texinfo info
+ @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+ $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+ @echo
+ @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
diff --git a/tests/wpt/web-platform-tests/tools/third_party/funcsigs/docs/_templates/page.html b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/docs/_templates/page.html
new file mode 100644
index 00000000000..5e1e00bcafa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/docs/_templates/page.html
@@ -0,0 +1,9 @@
+{% extends "!page.html" %}
+{% block extrahead %}
+ <a href="https://github.com/aliles/funcsigs">
+ <img style="position: absolute; top: 0; right: 0; border: 0;"
+ src="https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png"
+ alt="Fork me on GitHub">
+ </a>
+ {{ super() }}
+{% endblock %}
diff --git a/tests/wpt/web-platform-tests/tools/third_party/funcsigs/docs/conf.py b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/docs/conf.py
new file mode 100644
index 00000000000..c6e4194cc05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/docs/conf.py
@@ -0,0 +1,251 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# funcsigs documentation build configuration file, created by
+# sphinx-quickstart on Fri Apr 20 20:27:52 2012.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+sys.path.insert(0, os.path.abspath('..'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.viewcode']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = 'funcsigs'
+copyright = '2013, Aaron Iles'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+from funcsigs import __version__
+version = '.'.join(__version__.split('.')[:2])
+# The full version, including alpha/beta/rc tags.
+release = __version__
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+html_theme = 'agogo'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = []
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'funcsigsdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+ ('index', 'funcsigs.tex', 'funcsigs Documentation',
+ 'Aaron Iles', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ ('index', 'funcsigs', 'funcsigs Documentation',
+ ['Aaron Iles'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output ------------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ ('index', 'funcsigs', 'funcsigs Documentation',
+ 'Aaron Iles', 'funcsigs', 'One line description of project.',
+ 'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+
+# Example configuration for intersphinx: refer to the Python standard library.
+intersphinx_mapping = {
+ 'python3': ('http://docs.python.org/py3k', None),
+ 'python': ('http://docs.python.org/', None)
+}
diff --git a/tests/wpt/web-platform-tests/tools/third_party/funcsigs/docs/index.rst b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/docs/index.rst
new file mode 100644
index 00000000000..5d0f42f9368
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/docs/index.rst
@@ -0,0 +1,315 @@
+.. funcsigs documentation master file, created by
+ sphinx-quickstart on Fri Apr 20 20:27:52 2012.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Introducing funcsigs
+====================
+
+The Funcsigs Package
+--------------------
+
+*funcsigs* is a backport of the `PEP 362`_ function signature features from
+Python 3.3's `inspect`_ module. The backport is compatible with Python 2.6, 2.7
+as well as 3.2 and up.
+
+.. _PEP 362: http://www.python.org/dev/peps/pep-0362/
+.. _inspect: http://docs.python.org/3/library/inspect.html#introspecting-callables-with-the-signature-object
+
+Compatability
+`````````````
+
+The *funcsigs* backport has been tested against:
+
+* CPython 2.6
+* CPython 2.7
+* CPython 3.2
+* PyPy 1.9
+
+Continuous integration testing is provided by `Travis CI`_.
+
+Under Python 2.x there is a compatability issue when a function is assigned to
+the ``__wrapped__`` property of a class after it has been constructed.
+Similiarily there under PyPy directly passing the ``__call__`` method of a
+builtin is also a compatability issues. Otherwise the functionality is
+believed to be uniform between both Python2 and Python3.
+
+.. _Travis CI: http://travis-ci.org/
+
+Issues
+``````
+
+Source code for *funcsigs* is hosted on `GitHub`_. Any bug reports or feature
+requests can be made using GitHub's `issues system`_.
+
+.. _GitHub: https://github.com/aliles/funcsigs
+.. _issues system: https://github.com/alies/funcsigs/issues
+
+Introspecting callables with the Signature object
+-------------------------------------------------
+
+.. note::
+
+ This section of documentation is a direct repoduction of the Python
+ standard library documentation for the inspect module.
+
+The Signature object represents the call signature of a callable object and its
+return annotation. To retrieve a Signature object, use the :func:`signature`
+function.
+
+.. function:: signature(callable)
+
+ Return a :class:`Signature` object for the given ``callable``::
+
+ >>> from inspect import signature
+ >>> def foo(a, *, b:int, **kwargs):
+ ... pass
+
+ >>> sig = signature(foo)
+
+ >>> str(sig)
+ '(a, *, b:int, **kwargs)'
+
+ >>> str(sig.parameters['b'])
+ 'b:int'
+
+ >>> sig.parameters['b'].annotation
+ <class 'int'>
+
+ Accepts a wide range of python callables, from plain functions and classes to
+ :func:`functools.partial` objects.
+
+ .. note::
+
+ Some callables may not be introspectable in certain implementations of
+ Python. For example, in CPython, built-in functions defined in C provide
+ no metadata about their arguments.
+
+
+.. class:: Signature
+
+ A Signature object represents the call signature of a function and its return
+ annotation. For each parameter accepted by the function it stores a
+ :class:`Parameter` object in its :attr:`parameters` collection.
+
+ Signature objects are *immutable*. Use :meth:`Signature.replace` to make a
+ modified copy.
+
+ .. attribute:: Signature.empty
+
+ A special class-level marker to specify absence of a return annotation.
+
+ .. attribute:: Signature.parameters
+
+ An ordered mapping of parameters' names to the corresponding
+ :class:`Parameter` objects.
+
+ .. attribute:: Signature.return_annotation
+
+ The "return" annotation for the callable. If the callable has no "return"
+ annotation, this attribute is set to :attr:`Signature.empty`.
+
+ .. method:: Signature.bind(*args, **kwargs)
+
+ Create a mapping from positional and keyword arguments to parameters.
+ Returns :class:`BoundArguments` if ``*args`` and ``**kwargs`` match the
+ signature, or raises a :exc:`TypeError`.
+
+ .. method:: Signature.bind_partial(*args, **kwargs)
+
+ Works the same way as :meth:`Signature.bind`, but allows the omission of
+ some required arguments (mimics :func:`functools.partial` behavior.)
+ Returns :class:`BoundArguments`, or raises a :exc:`TypeError` if the
+ passed arguments do not match the signature.
+
+ .. method:: Signature.replace(*[, parameters][, return_annotation])
+
+ Create a new Signature instance based on the instance replace was invoked
+ on. It is possible to pass different ``parameters`` and/or
+ ``return_annotation`` to override the corresponding properties of the base
+ signature. To remove return_annotation from the copied Signature, pass in
+ :attr:`Signature.empty`.
+
+ ::
+
+ >>> def test(a, b):
+ ... pass
+ >>> sig = signature(test)
+ >>> new_sig = sig.replace(return_annotation="new return anno")
+ >>> str(new_sig)
+ "(a, b) -> 'new return anno'"
+
+
+.. class:: Parameter
+
+ Parameter objects are *immutable*. Instead of modifying a Parameter object,
+ you can use :meth:`Parameter.replace` to create a modified copy.
+
+ .. attribute:: Parameter.empty
+
+ A special class-level marker to specify absence of default values and
+ annotations.
+
+ .. attribute:: Parameter.name
+
+ The name of the parameter as a string. Must be a valid python identifier
+ name (with the exception of ``POSITIONAL_ONLY`` parameters, which can have
+ it set to ``None``).
+
+ .. attribute:: Parameter.default
+
+ The default value for the parameter. If the parameter has no default
+ value, this attribute is set to :attr:`Parameter.empty`.
+
+ .. attribute:: Parameter.annotation
+
+ The annotation for the parameter. If the parameter has no annotation,
+ this attribute is set to :attr:`Parameter.empty`.
+
+ .. attribute:: Parameter.kind
+
+ Describes how argument values are bound to the parameter. Possible values
+ (accessible via :class:`Parameter`, like ``Parameter.KEYWORD_ONLY``):
+
+ +------------------------+----------------------------------------------+
+ | Name | Meaning |
+ +========================+==============================================+
+ | *POSITIONAL_ONLY* | Value must be supplied as a positional |
+ | | argument. |
+ | | |
+ | | Python has no explicit syntax for defining |
+ | | positional-only parameters, but many built-in|
+ | | and extension module functions (especially |
+ | | those that accept only one or two parameters)|
+ | | accept them. |
+ +------------------------+----------------------------------------------+
+ | *POSITIONAL_OR_KEYWORD*| Value may be supplied as either a keyword or |
+ | | positional argument (this is the standard |
+ | | binding behaviour for functions implemented |
+ | | in Python.) |
+ +------------------------+----------------------------------------------+
+ | *VAR_POSITIONAL* | A tuple of positional arguments that aren't |
+ | | bound to any other parameter. This |
+ | | corresponds to a ``*args`` parameter in a |
+ | | Python function definition. |
+ +------------------------+----------------------------------------------+
+ | *KEYWORD_ONLY* | Value must be supplied as a keyword argument.|
+ | | Keyword only parameters are those which |
+ | | appear after a ``*`` or ``*args`` entry in a |
+ | | Python function definition. |
+ +------------------------+----------------------------------------------+
+ | *VAR_KEYWORD* | A dict of keyword arguments that aren't bound|
+ | | to any other parameter. This corresponds to a|
+ | | ``**kwargs`` parameter in a Python function |
+ | | definition. |
+ +------------------------+----------------------------------------------+
+
+ Example: print all keyword-only arguments without default values::
+
+ >>> def foo(a, b, *, c, d=10):
+ ... pass
+
+ >>> sig = signature(foo)
+ >>> for param in sig.parameters.values():
+ ... if (param.kind == param.KEYWORD_ONLY and
+ ... param.default is param.empty):
+ ... print('Parameter:', param)
+ Parameter: c
+
+ .. method:: Parameter.replace(*[, name][, kind][, default][, annotation])
+
+ Create a new Parameter instance based on the instance replaced was invoked
+ on. To override a :class:`Parameter` attribute, pass the corresponding
+ argument. To remove a default value or/and an annotation from a
+ Parameter, pass :attr:`Parameter.empty`.
+
+ ::
+
+ >>> from inspect import Parameter
+ >>> param = Parameter('foo', Parameter.KEYWORD_ONLY, default=42)
+ >>> str(param)
+ 'foo=42'
+
+ >>> str(param.replace()) # Will create a shallow copy of 'param'
+ 'foo=42'
+
+ >>> str(param.replace(default=Parameter.empty, annotation='spam'))
+ "foo:'spam'"
+
+
+.. class:: BoundArguments
+
+ Result of a :meth:`Signature.bind` or :meth:`Signature.bind_partial` call.
+ Holds the mapping of arguments to the function's parameters.
+
+ .. attribute:: BoundArguments.arguments
+
+ An ordered, mutable mapping (:class:`collections.OrderedDict`) of
+ parameters' names to arguments' values. Contains only explicitly bound
+ arguments. Changes in :attr:`arguments` will reflect in :attr:`args` and
+ :attr:`kwargs`.
+
+ Should be used in conjunction with :attr:`Signature.parameters` for any
+ argument processing purposes.
+
+ .. note::
+
+ Arguments for which :meth:`Signature.bind` or
+ :meth:`Signature.bind_partial` relied on a default value are skipped.
+ However, if needed, it is easy to include them.
+
+ ::
+
+ >>> def foo(a, b=10):
+ ... pass
+
+ >>> sig = signature(foo)
+ >>> ba = sig.bind(5)
+
+ >>> ba.args, ba.kwargs
+ ((5,), {})
+
+ >>> for param in sig.parameters.values():
+ ... if param.name not in ba.arguments:
+ ... ba.arguments[param.name] = param.default
+
+ >>> ba.args, ba.kwargs
+ ((5, 10), {})
+
+
+ .. attribute:: BoundArguments.args
+
+ A tuple of positional arguments values. Dynamically computed from the
+ :attr:`arguments` attribute.
+
+ .. attribute:: BoundArguments.kwargs
+
+ A dict of keyword arguments values. Dynamically computed from the
+ :attr:`arguments` attribute.
+
+ The :attr:`args` and :attr:`kwargs` properties can be used to invoke
+ functions::
+
+ def test(a, *, b):
+ ...
+
+ sig = signature(test)
+ ba = sig.bind(10, b=20)
+ test(*ba.args, **ba.kwargs)
+
+
+.. seealso::
+
+ :pep:`362` - Function Signature Object.
+ The detailed specification, implementation details and examples.
+
+Copyright
+---------
+
+*funcsigs* is a derived work of CPython under the terms of the `PSF License
+Agreement`_. The original CPython inspect module, its unit tests and
+documentation are the copyright of the Python Software Foundation. The derived
+work is distributed under the `Apache License Version 2.0`_.
+
+.. _PSF License Agreement: http://docs.python.org/3/license.html#terms-and-conditions-for-accessing-or-otherwise-using-python
+.. _Apache License Version 2.0: http://opensource.org/licenses/Apache-2.0
diff --git a/tests/wpt/web-platform-tests/tools/third_party/funcsigs/funcsigs/__init__.py b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/funcsigs/__init__.py
new file mode 100644
index 00000000000..fd2f47b1d4d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/funcsigs/__init__.py
@@ -0,0 +1,818 @@
+# Copyright 2001-2013 Python Software Foundation; All Rights Reserved
+"""Function signature objects for callables
+
+Back port of Python 3.3's function signature tools from the inspect module,
+modified to be compatible with Python 2.6, 2.7 and 3.2+.
+"""
+from __future__ import absolute_import, division, print_function
+import itertools
+import functools
+import re
+import types
+
+try:
+ from collections import OrderedDict
+except ImportError:
+ from funcsigs.odict import OrderedDict
+
+from funcsigs.version import __version__
+
+__all__ = ['BoundArguments', 'Parameter', 'Signature', 'signature']
+
+
+_WrapperDescriptor = type(type.__call__)
+_MethodWrapper = type(all.__call__)
+
+_NonUserDefinedCallables = (_WrapperDescriptor,
+ _MethodWrapper,
+ types.BuiltinFunctionType)
+
+
+def formatannotation(annotation, base_module=None):
+ if isinstance(annotation, type):
+ if annotation.__module__ in ('builtins', '__builtin__', base_module):
+ return annotation.__name__
+ return annotation.__module__+'.'+annotation.__name__
+ return repr(annotation)
+
+
+def _get_user_defined_method(cls, method_name, *nested):
+ try:
+ if cls is type:
+ return
+ meth = getattr(cls, method_name)
+ for name in nested:
+ meth = getattr(meth, name, meth)
+ except AttributeError:
+ return
+ else:
+ if not isinstance(meth, _NonUserDefinedCallables):
+ # Once '__signature__' will be added to 'C'-level
+ # callables, this check won't be necessary
+ return meth
+
+
+def signature(obj):
+ '''Get a signature object for the passed callable.'''
+
+ if not callable(obj):
+ raise TypeError('{0!r} is not a callable object'.format(obj))
+
+ if isinstance(obj, types.MethodType):
+ sig = signature(obj.__func__)
+ if obj.__self__ is None:
+ # Unbound method: the first parameter becomes positional-only
+ if sig.parameters:
+ first = sig.parameters.values()[0].replace(
+ kind=_POSITIONAL_ONLY)
+ return sig.replace(
+ parameters=(first,) + tuple(sig.parameters.values())[1:])
+ else:
+ return sig
+ else:
+ # In this case we skip the first parameter of the underlying
+ # function (usually `self` or `cls`).
+ return sig.replace(parameters=tuple(sig.parameters.values())[1:])
+
+ try:
+ sig = obj.__signature__
+ except AttributeError:
+ pass
+ else:
+ if sig is not None:
+ return sig
+
+ try:
+ # Was this function wrapped by a decorator?
+ wrapped = obj.__wrapped__
+ except AttributeError:
+ pass
+ else:
+ return signature(wrapped)
+
+ if isinstance(obj, types.FunctionType):
+ return Signature.from_function(obj)
+
+ if isinstance(obj, functools.partial):
+ sig = signature(obj.func)
+
+ new_params = OrderedDict(sig.parameters.items())
+
+ partial_args = obj.args or ()
+ partial_keywords = obj.keywords or {}
+ try:
+ ba = sig.bind_partial(*partial_args, **partial_keywords)
+ except TypeError as ex:
+ msg = 'partial object {0!r} has incorrect arguments'.format(obj)
+ raise ValueError(msg)
+
+ for arg_name, arg_value in ba.arguments.items():
+ param = new_params[arg_name]
+ if arg_name in partial_keywords:
+ # We set a new default value, because the following code
+ # is correct:
+ #
+ # >>> def foo(a): print(a)
+ # >>> print(partial(partial(foo, a=10), a=20)())
+ # 20
+ # >>> print(partial(partial(foo, a=10), a=20)(a=30))
+ # 30
+ #
+ # So, with 'partial' objects, passing a keyword argument is
+ # like setting a new default value for the corresponding
+ # parameter
+ #
+ # We also mark this parameter with '_partial_kwarg'
+ # flag. Later, in '_bind', the 'default' value of this
+ # parameter will be added to 'kwargs', to simulate
+ # the 'functools.partial' real call.
+ new_params[arg_name] = param.replace(default=arg_value,
+ _partial_kwarg=True)
+
+ elif (param.kind not in (_VAR_KEYWORD, _VAR_POSITIONAL) and
+ not param._partial_kwarg):
+ new_params.pop(arg_name)
+
+ return sig.replace(parameters=new_params.values())
+
+ sig = None
+ if isinstance(obj, type):
+ # obj is a class or a metaclass
+
+ # First, let's see if it has an overloaded __call__ defined
+ # in its metaclass
+ call = _get_user_defined_method(type(obj), '__call__')
+ if call is not None:
+ sig = signature(call)
+ else:
+ # Now we check if the 'obj' class has a '__new__' method
+ new = _get_user_defined_method(obj, '__new__')
+ if new is not None:
+ sig = signature(new)
+ else:
+ # Finally, we should have at least __init__ implemented
+ init = _get_user_defined_method(obj, '__init__')
+ if init is not None:
+ sig = signature(init)
+ elif not isinstance(obj, _NonUserDefinedCallables):
+ # An object with __call__
+ # We also check that the 'obj' is not an instance of
+ # _WrapperDescriptor or _MethodWrapper to avoid
+ # infinite recursion (and even potential segfault)
+ call = _get_user_defined_method(type(obj), '__call__', 'im_func')
+ if call is not None:
+ sig = signature(call)
+
+ if sig is not None:
+ # For classes and objects we skip the first parameter of their
+ # __call__, __new__, or __init__ methods
+ return sig.replace(parameters=tuple(sig.parameters.values())[1:])
+
+ if isinstance(obj, types.BuiltinFunctionType):
+ # Raise a nicer error message for builtins
+ msg = 'no signature found for builtin function {0!r}'.format(obj)
+ raise ValueError(msg)
+
+ raise ValueError('callable {0!r} is not supported by signature'.format(obj))
+
+
+class _void(object):
+ '''A private marker - used in Parameter & Signature'''
+
+
+class _empty(object):
+ pass
+
+
+class _ParameterKind(int):
+ def __new__(self, *args, **kwargs):
+ obj = int.__new__(self, *args)
+ obj._name = kwargs['name']
+ return obj
+
+ def __str__(self):
+ return self._name
+
+ def __repr__(self):
+ return '<_ParameterKind: {0!r}>'.format(self._name)
+
+
+_POSITIONAL_ONLY = _ParameterKind(0, name='POSITIONAL_ONLY')
+_POSITIONAL_OR_KEYWORD = _ParameterKind(1, name='POSITIONAL_OR_KEYWORD')
+_VAR_POSITIONAL = _ParameterKind(2, name='VAR_POSITIONAL')
+_KEYWORD_ONLY = _ParameterKind(3, name='KEYWORD_ONLY')
+_VAR_KEYWORD = _ParameterKind(4, name='VAR_KEYWORD')
+
+
+class Parameter(object):
+ '''Represents a parameter in a function signature.
+
+ Has the following public attributes:
+
+ * name : str
+ The name of the parameter as a string.
+ * default : object
+ The default value for the parameter if specified. If the
+ parameter has no default value, this attribute is not set.
+ * annotation
+ The annotation for the parameter if specified. If the
+ parameter has no annotation, this attribute is not set.
+ * kind : str
+ Describes how argument values are bound to the parameter.
+ Possible values: `Parameter.POSITIONAL_ONLY`,
+ `Parameter.POSITIONAL_OR_KEYWORD`, `Parameter.VAR_POSITIONAL`,
+ `Parameter.KEYWORD_ONLY`, `Parameter.VAR_KEYWORD`.
+ '''
+
+ __slots__ = ('_name', '_kind', '_default', '_annotation', '_partial_kwarg')
+
+ POSITIONAL_ONLY = _POSITIONAL_ONLY
+ POSITIONAL_OR_KEYWORD = _POSITIONAL_OR_KEYWORD
+ VAR_POSITIONAL = _VAR_POSITIONAL
+ KEYWORD_ONLY = _KEYWORD_ONLY
+ VAR_KEYWORD = _VAR_KEYWORD
+
+ empty = _empty
+
+ def __init__(self, name, kind, default=_empty, annotation=_empty,
+ _partial_kwarg=False):
+
+ if kind not in (_POSITIONAL_ONLY, _POSITIONAL_OR_KEYWORD,
+ _VAR_POSITIONAL, _KEYWORD_ONLY, _VAR_KEYWORD):
+ raise ValueError("invalid value for 'Parameter.kind' attribute")
+ self._kind = kind
+
+ if default is not _empty:
+ if kind in (_VAR_POSITIONAL, _VAR_KEYWORD):
+ msg = '{0} parameters cannot have default values'.format(kind)
+ raise ValueError(msg)
+ self._default = default
+ self._annotation = annotation
+
+ if name is None:
+ if kind != _POSITIONAL_ONLY:
+ raise ValueError("None is not a valid name for a "
+ "non-positional-only parameter")
+ self._name = name
+ else:
+ name = str(name)
+ if kind != _POSITIONAL_ONLY and not re.match(r'[a-z_]\w*$', name, re.I):
+ msg = '{0!r} is not a valid parameter name'.format(name)
+ raise ValueError(msg)
+ self._name = name
+
+ self._partial_kwarg = _partial_kwarg
+
+ @property
+ def name(self):
+ return self._name
+
+ @property
+ def default(self):
+ return self._default
+
+ @property
+ def annotation(self):
+ return self._annotation
+
+ @property
+ def kind(self):
+ return self._kind
+
+ def replace(self, name=_void, kind=_void, annotation=_void,
+ default=_void, _partial_kwarg=_void):
+ '''Creates a customized copy of the Parameter.'''
+
+ if name is _void:
+ name = self._name
+
+ if kind is _void:
+ kind = self._kind
+
+ if annotation is _void:
+ annotation = self._annotation
+
+ if default is _void:
+ default = self._default
+
+ if _partial_kwarg is _void:
+ _partial_kwarg = self._partial_kwarg
+
+ return type(self)(name, kind, default=default, annotation=annotation,
+ _partial_kwarg=_partial_kwarg)
+
+ def __str__(self):
+ kind = self.kind
+
+ formatted = self._name
+ if kind == _POSITIONAL_ONLY:
+ if formatted is None:
+ formatted = ''
+ formatted = '<{0}>'.format(formatted)
+
+ # Add annotation and default value
+ if self._annotation is not _empty:
+ formatted = '{0}:{1}'.format(formatted,
+ formatannotation(self._annotation))
+
+ if self._default is not _empty:
+ formatted = '{0}={1}'.format(formatted, repr(self._default))
+
+ if kind == _VAR_POSITIONAL:
+ formatted = '*' + formatted
+ elif kind == _VAR_KEYWORD:
+ formatted = '**' + formatted
+
+ return formatted
+
+ def __repr__(self):
+ return '<{0} at {1:#x} {2!r}>'.format(self.__class__.__name__,
+ id(self), self.name)
+
+ def __hash__(self):
+ msg = "unhashable type: '{0}'".format(self.__class__.__name__)
+ raise TypeError(msg)
+
+ def __eq__(self, other):
+ return (issubclass(other.__class__, Parameter) and
+ self._name == other._name and
+ self._kind == other._kind and
+ self._default == other._default and
+ self._annotation == other._annotation)
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+
+class BoundArguments(object):
+ '''Result of `Signature.bind` call. Holds the mapping of arguments
+ to the function's parameters.
+
+ Has the following public attributes:
+
+ * arguments : OrderedDict
+ An ordered mutable mapping of parameters' names to arguments' values.
+ Does not contain arguments' default values.
+ * signature : Signature
+ The Signature object that created this instance.
+ * args : tuple
+ Tuple of positional arguments values.
+ * kwargs : dict
+ Dict of keyword arguments values.
+ '''
+
+ def __init__(self, signature, arguments):
+ self.arguments = arguments
+ self._signature = signature
+
+ @property
+ def signature(self):
+ return self._signature
+
+ @property
+ def args(self):
+ args = []
+ for param_name, param in self._signature.parameters.items():
+ if (param.kind in (_VAR_KEYWORD, _KEYWORD_ONLY) or
+ param._partial_kwarg):
+ # Keyword arguments mapped by 'functools.partial'
+ # (Parameter._partial_kwarg is True) are mapped
+ # in 'BoundArguments.kwargs', along with VAR_KEYWORD &
+ # KEYWORD_ONLY
+ break
+
+ try:
+ arg = self.arguments[param_name]
+ except KeyError:
+ # We're done here. Other arguments
+ # will be mapped in 'BoundArguments.kwargs'
+ break
+ else:
+ if param.kind == _VAR_POSITIONAL:
+ # *args
+ args.extend(arg)
+ else:
+ # plain argument
+ args.append(arg)
+
+ return tuple(args)
+
+ @property
+ def kwargs(self):
+ kwargs = {}
+ kwargs_started = False
+ for param_name, param in self._signature.parameters.items():
+ if not kwargs_started:
+ if (param.kind in (_VAR_KEYWORD, _KEYWORD_ONLY) or
+ param._partial_kwarg):
+ kwargs_started = True
+ else:
+ if param_name not in self.arguments:
+ kwargs_started = True
+ continue
+
+ if not kwargs_started:
+ continue
+
+ try:
+ arg = self.arguments[param_name]
+ except KeyError:
+ pass
+ else:
+ if param.kind == _VAR_KEYWORD:
+ # **kwargs
+ kwargs.update(arg)
+ else:
+ # plain keyword argument
+ kwargs[param_name] = arg
+
+ return kwargs
+
+ def __hash__(self):
+ msg = "unhashable type: '{0}'".format(self.__class__.__name__)
+ raise TypeError(msg)
+
+ def __eq__(self, other):
+ return (issubclass(other.__class__, BoundArguments) and
+ self.signature == other.signature and
+ self.arguments == other.arguments)
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+
+class Signature(object):
+ '''A Signature object represents the overall signature of a function.
+ It stores a Parameter object for each parameter accepted by the
+ function, as well as information specific to the function itself.
+
+ A Signature object has the following public attributes and methods:
+
+ * parameters : OrderedDict
+ An ordered mapping of parameters' names to the corresponding
+ Parameter objects (keyword-only arguments are in the same order
+ as listed in `code.co_varnames`).
+ * return_annotation : object
+ The annotation for the return type of the function if specified.
+ If the function has no annotation for its return type, this
+ attribute is not set.
+ * bind(*args, **kwargs) -> BoundArguments
+ Creates a mapping from positional and keyword arguments to
+ parameters.
+ * bind_partial(*args, **kwargs) -> BoundArguments
+ Creates a partial mapping from positional and keyword arguments
+ to parameters (simulating 'functools.partial' behavior.)
+ '''
+
+ __slots__ = ('_return_annotation', '_parameters')
+
+ _parameter_cls = Parameter
+ _bound_arguments_cls = BoundArguments
+
+ empty = _empty
+
+ def __init__(self, parameters=None, return_annotation=_empty,
+ __validate_parameters__=True):
+ '''Constructs Signature from the given list of Parameter
+ objects and 'return_annotation'. All arguments are optional.
+ '''
+
+ if parameters is None:
+ params = OrderedDict()
+ else:
+ if __validate_parameters__:
+ params = OrderedDict()
+ top_kind = _POSITIONAL_ONLY
+
+ for idx, param in enumerate(parameters):
+ kind = param.kind
+ if kind < top_kind:
+ msg = 'wrong parameter order: {0} before {1}'
+ msg = msg.format(top_kind, param.kind)
+ raise ValueError(msg)
+ else:
+ top_kind = kind
+
+ name = param.name
+ if name is None:
+ name = str(idx)
+ param = param.replace(name=name)
+
+ if name in params:
+ msg = 'duplicate parameter name: {0!r}'.format(name)
+ raise ValueError(msg)
+ params[name] = param
+ else:
+ params = OrderedDict(((param.name, param)
+ for param in parameters))
+
+ self._parameters = params
+ self._return_annotation = return_annotation
+
+ @classmethod
+ def from_function(cls, func):
+ '''Constructs Signature for the given python function'''
+
+ if not isinstance(func, types.FunctionType):
+ raise TypeError('{0!r} is not a Python function'.format(func))
+
+ Parameter = cls._parameter_cls
+
+ # Parameter information.
+ func_code = func.__code__
+ pos_count = func_code.co_argcount
+ arg_names = func_code.co_varnames
+ positional = tuple(arg_names[:pos_count])
+ keyword_only_count = getattr(func_code, 'co_kwonlyargcount', 0)
+ keyword_only = arg_names[pos_count:(pos_count + keyword_only_count)]
+ annotations = getattr(func, '__annotations__', {})
+ defaults = func.__defaults__
+ kwdefaults = getattr(func, '__kwdefaults__', None)
+
+ if defaults:
+ pos_default_count = len(defaults)
+ else:
+ pos_default_count = 0
+
+ parameters = []
+
+ # Non-keyword-only parameters w/o defaults.
+ non_default_count = pos_count - pos_default_count
+ for name in positional[:non_default_count]:
+ annotation = annotations.get(name, _empty)
+ parameters.append(Parameter(name, annotation=annotation,
+ kind=_POSITIONAL_OR_KEYWORD))
+
+ # ... w/ defaults.
+ for offset, name in enumerate(positional[non_default_count:]):
+ annotation = annotations.get(name, _empty)
+ parameters.append(Parameter(name, annotation=annotation,
+ kind=_POSITIONAL_OR_KEYWORD,
+ default=defaults[offset]))
+
+ # *args
+ if func_code.co_flags & 0x04:
+ name = arg_names[pos_count + keyword_only_count]
+ annotation = annotations.get(name, _empty)
+ parameters.append(Parameter(name, annotation=annotation,
+ kind=_VAR_POSITIONAL))
+
+ # Keyword-only parameters.
+ for name in keyword_only:
+ default = _empty
+ if kwdefaults is not None:
+ default = kwdefaults.get(name, _empty)
+
+ annotation = annotations.get(name, _empty)
+ parameters.append(Parameter(name, annotation=annotation,
+ kind=_KEYWORD_ONLY,
+ default=default))
+ # **kwargs
+ if func_code.co_flags & 0x08:
+ index = pos_count + keyword_only_count
+ if func_code.co_flags & 0x04:
+ index += 1
+
+ name = arg_names[index]
+ annotation = annotations.get(name, _empty)
+ parameters.append(Parameter(name, annotation=annotation,
+ kind=_VAR_KEYWORD))
+
+ return cls(parameters,
+ return_annotation=annotations.get('return', _empty),
+ __validate_parameters__=False)
+
+ @property
+ def parameters(self):
+ try:
+ return types.MappingProxyType(self._parameters)
+ except AttributeError:
+ return OrderedDict(self._parameters.items())
+
+ @property
+ def return_annotation(self):
+ return self._return_annotation
+
+ def replace(self, parameters=_void, return_annotation=_void):
+ '''Creates a customized copy of the Signature.
+ Pass 'parameters' and/or 'return_annotation' arguments
+ to override them in the new copy.
+ '''
+
+ if parameters is _void:
+ parameters = self.parameters.values()
+
+ if return_annotation is _void:
+ return_annotation = self._return_annotation
+
+ return type(self)(parameters,
+ return_annotation=return_annotation)
+
+ def __hash__(self):
+ msg = "unhashable type: '{0}'".format(self.__class__.__name__)
+ raise TypeError(msg)
+
+ def __eq__(self, other):
+ if (not issubclass(type(other), Signature) or
+ self.return_annotation != other.return_annotation or
+ len(self.parameters) != len(other.parameters)):
+ return False
+
+ other_positions = dict((param, idx)
+ for idx, param in enumerate(other.parameters.keys()))
+
+ for idx, (param_name, param) in enumerate(self.parameters.items()):
+ if param.kind == _KEYWORD_ONLY:
+ try:
+ other_param = other.parameters[param_name]
+ except KeyError:
+ return False
+ else:
+ if param != other_param:
+ return False
+ else:
+ try:
+ other_idx = other_positions[param_name]
+ except KeyError:
+ return False
+ else:
+ if (idx != other_idx or
+ param != other.parameters[param_name]):
+ return False
+
+ return True
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+ def _bind(self, args, kwargs, partial=False):
+ '''Private method. Don't use directly.'''
+
+ arguments = OrderedDict()
+
+ parameters = iter(self.parameters.values())
+ parameters_ex = ()
+ arg_vals = iter(args)
+
+ if partial:
+ # Support for binding arguments to 'functools.partial' objects.
+ # See 'functools.partial' case in 'signature()' implementation
+ # for details.
+ for param_name, param in self.parameters.items():
+ if (param._partial_kwarg and param_name not in kwargs):
+ # Simulating 'functools.partial' behavior
+ kwargs[param_name] = param.default
+
+ while True:
+ # Let's iterate through the positional arguments and corresponding
+ # parameters
+ try:
+ arg_val = next(arg_vals)
+ except StopIteration:
+ # No more positional arguments
+ try:
+ param = next(parameters)
+ except StopIteration:
+ # No more parameters. That's it. Just need to check that
+ # we have no `kwargs` after this while loop
+ break
+ else:
+ if param.kind == _VAR_POSITIONAL:
+ # That's OK, just empty *args. Let's start parsing
+ # kwargs
+ break
+ elif param.name in kwargs:
+ if param.kind == _POSITIONAL_ONLY:
+ msg = '{arg!r} parameter is positional only, ' \
+ 'but was passed as a keyword'
+ msg = msg.format(arg=param.name)
+ raise TypeError(msg)
+ parameters_ex = (param,)
+ break
+ elif (param.kind == _VAR_KEYWORD or
+ param.default is not _empty):
+ # That's fine too - we have a default value for this
+ # parameter. So, lets start parsing `kwargs`, starting
+ # with the current parameter
+ parameters_ex = (param,)
+ break
+ else:
+ if partial:
+ parameters_ex = (param,)
+ break
+ else:
+ msg = '{arg!r} parameter lacking default value'
+ msg = msg.format(arg=param.name)
+ raise TypeError(msg)
+ else:
+ # We have a positional argument to process
+ try:
+ param = next(parameters)
+ except StopIteration:
+ raise TypeError('too many positional arguments')
+ else:
+ if param.kind in (_VAR_KEYWORD, _KEYWORD_ONLY):
+ # Looks like we have no parameter for this positional
+ # argument
+ raise TypeError('too many positional arguments')
+
+ if param.kind == _VAR_POSITIONAL:
+ # We have an '*args'-like argument, let's fill it with
+ # all positional arguments we have left and move on to
+ # the next phase
+ values = [arg_val]
+ values.extend(arg_vals)
+ arguments[param.name] = tuple(values)
+ break
+
+ if param.name in kwargs:
+ raise TypeError('multiple values for argument '
+ '{arg!r}'.format(arg=param.name))
+
+ arguments[param.name] = arg_val
+
+ # Now, we iterate through the remaining parameters to process
+ # keyword arguments
+ kwargs_param = None
+ for param in itertools.chain(parameters_ex, parameters):
+ if param.kind == _POSITIONAL_ONLY:
+ # This should never happen in case of a properly built
+ # Signature object (but let's have this check here
+ # to ensure correct behaviour just in case)
+ raise TypeError('{arg!r} parameter is positional only, '
+ 'but was passed as a keyword'. \
+ format(arg=param.name))
+
+ if param.kind == _VAR_KEYWORD:
+ # Memorize that we have a '**kwargs'-like parameter
+ kwargs_param = param
+ continue
+
+ param_name = param.name
+ try:
+ arg_val = kwargs.pop(param_name)
+ except KeyError:
+ # We have no value for this parameter. It's fine though,
+ # if it has a default value, or it is an '*args'-like
+ # parameter, left alone by the processing of positional
+ # arguments.
+ if (not partial and param.kind != _VAR_POSITIONAL and
+ param.default is _empty):
+ raise TypeError('{arg!r} parameter lacking default value'. \
+ format(arg=param_name))
+
+ else:
+ arguments[param_name] = arg_val
+
+ if kwargs:
+ if kwargs_param is not None:
+ # Process our '**kwargs'-like parameter
+ arguments[kwargs_param.name] = kwargs
+ else:
+ raise TypeError('too many keyword arguments')
+
+ return self._bound_arguments_cls(self, arguments)
+
+ def bind(self, *args, **kwargs):
+ '''Get a BoundArguments object, that maps the passed `args`
+ and `kwargs` to the function's signature. Raises `TypeError`
+ if the passed arguments can not be bound.
+ '''
+ return self._bind(args, kwargs)
+
+ def bind_partial(self, *args, **kwargs):
+ '''Get a BoundArguments object, that partially maps the
+ passed `args` and `kwargs` to the function's signature.
+ Raises `TypeError` if the passed arguments can not be bound.
+ '''
+ return self._bind(args, kwargs, partial=True)
+
+ def __str__(self):
+ result = []
+ render_kw_only_separator = True
+ for idx, param in enumerate(self.parameters.values()):
+ formatted = str(param)
+
+ kind = param.kind
+ if kind == _VAR_POSITIONAL:
+ # OK, we have an '*args'-like parameter, so we won't need
+ # a '*' to separate keyword-only arguments
+ render_kw_only_separator = False
+ elif kind == _KEYWORD_ONLY and render_kw_only_separator:
+ # We have a keyword-only parameter to render and we haven't
+ # rendered an '*args'-like parameter before, so add a '*'
+ # separator to the parameters list ("foo(arg1, *, arg2)" case)
+ result.append('*')
+ # This condition should be only triggered once, so
+ # reset the flag
+ render_kw_only_separator = False
+
+ result.append(formatted)
+
+ rendered = '({0})'.format(', '.join(result))
+
+ if self.return_annotation is not _empty:
+ anno = formatannotation(self.return_annotation)
+ rendered += ' -> {0}'.format(anno)
+
+ return rendered
diff --git a/tests/wpt/web-platform-tests/tools/third_party/funcsigs/funcsigs/odict.py b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/funcsigs/odict.py
new file mode 100644
index 00000000000..6221e971b37
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/funcsigs/odict.py
@@ -0,0 +1,261 @@
+# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy.
+# Passes Python2.7's test suite and incorporates all the latest updates.
+# Copyright 2009 Raymond Hettinger
+# http://code.activestate.com/recipes/576693/
+"Ordered dictionary"
+
+try:
+ from thread import get_ident as _get_ident
+except ImportError:
+ from dummy_thread import get_ident as _get_ident
+
+try:
+ from _abcoll import KeysView, ValuesView, ItemsView
+except ImportError:
+ pass
+
+
+class OrderedDict(dict):
+ 'Dictionary that remembers insertion order'
+ # An inherited dict maps keys to values.
+ # The inherited dict provides __getitem__, __len__, __contains__, and get.
+ # The remaining methods are order-aware.
+ # Big-O running times for all methods are the same as for regular dictionaries.
+
+ # The internal self.__map dictionary maps keys to links in a doubly linked list.
+ # The circular doubly linked list starts and ends with a sentinel element.
+ # The sentinel element never gets deleted (this simplifies the algorithm).
+ # Each link is stored as a list of length three: [PREV, NEXT, KEY].
+
+ def __init__(self, *args, **kwds):
+ '''Initialize an ordered dictionary. Signature is the same as for
+ regular dictionaries, but keyword arguments are not recommended
+ because their insertion order is arbitrary.
+
+ '''
+ if len(args) > 1:
+ raise TypeError('expected at most 1 arguments, got %d' % len(args))
+ try:
+ self.__root
+ except AttributeError:
+ self.__root = root = [] # sentinel node
+ root[:] = [root, root, None]
+ self.__map = {}
+ self.__update(*args, **kwds)
+
+ def __setitem__(self, key, value, dict_setitem=dict.__setitem__):
+ 'od.__setitem__(i, y) <==> od[i]=y'
+ # Setting a new item creates a new link which goes at the end of the linked
+ # list, and the inherited dictionary is updated with the new key/value pair.
+ if key not in self:
+ root = self.__root
+ last = root[0]
+ last[1] = root[0] = self.__map[key] = [last, root, key]
+ dict_setitem(self, key, value)
+
+ def __delitem__(self, key, dict_delitem=dict.__delitem__):
+ 'od.__delitem__(y) <==> del od[y]'
+ # Deleting an existing item uses self.__map to find the link which is
+ # then removed by updating the links in the predecessor and successor nodes.
+ dict_delitem(self, key)
+ link_prev, link_next, key = self.__map.pop(key)
+ link_prev[1] = link_next
+ link_next[0] = link_prev
+
+ def __iter__(self):
+ 'od.__iter__() <==> iter(od)'
+ root = self.__root
+ curr = root[1]
+ while curr is not root:
+ yield curr[2]
+ curr = curr[1]
+
+ def __reversed__(self):
+ 'od.__reversed__() <==> reversed(od)'
+ root = self.__root
+ curr = root[0]
+ while curr is not root:
+ yield curr[2]
+ curr = curr[0]
+
+ def clear(self):
+ 'od.clear() -> None. Remove all items from od.'
+ try:
+ for node in self.__map.itervalues():
+ del node[:]
+ root = self.__root
+ root[:] = [root, root, None]
+ self.__map.clear()
+ except AttributeError:
+ pass
+ dict.clear(self)
+
+ def popitem(self, last=True):
+ '''od.popitem() -> (k, v), return and remove a (key, value) pair.
+ Pairs are returned in LIFO order if last is true or FIFO order if false.
+
+ '''
+ if not self:
+ raise KeyError('dictionary is empty')
+ root = self.__root
+ if last:
+ link = root[0]
+ link_prev = link[0]
+ link_prev[1] = root
+ root[0] = link_prev
+ else:
+ link = root[1]
+ link_next = link[1]
+ root[1] = link_next
+ link_next[0] = root
+ key = link[2]
+ del self.__map[key]
+ value = dict.pop(self, key)
+ return key, value
+
+ # -- the following methods do not depend on the internal structure --
+
+ def keys(self):
+ 'od.keys() -> list of keys in od'
+ return list(self)
+
+ def values(self):
+ 'od.values() -> list of values in od'
+ return [self[key] for key in self]
+
+ def items(self):
+ 'od.items() -> list of (key, value) pairs in od'
+ return [(key, self[key]) for key in self]
+
+ def iterkeys(self):
+ 'od.iterkeys() -> an iterator over the keys in od'
+ return iter(self)
+
+ def itervalues(self):
+ 'od.itervalues -> an iterator over the values in od'
+ for k in self:
+ yield self[k]
+
+ def iteritems(self):
+ 'od.iteritems -> an iterator over the (key, value) items in od'
+ for k in self:
+ yield (k, self[k])
+
+ def update(*args, **kwds):
+ '''od.update(E, **F) -> None. Update od from dict/iterable E and F.
+
+ If E is a dict instance, does: for k in E: od[k] = E[k]
+ If E has a .keys() method, does: for k in E.keys(): od[k] = E[k]
+ Or if E is an iterable of items, does: for k, v in E: od[k] = v
+ In either case, this is followed by: for k, v in F.items(): od[k] = v
+
+ '''
+ if len(args) > 2:
+ raise TypeError('update() takes at most 2 positional '
+ 'arguments (%d given)' % (len(args),))
+ elif not args:
+ raise TypeError('update() takes at least 1 argument (0 given)')
+ self = args[0]
+ # Make progressively weaker assumptions about "other"
+ other = ()
+ if len(args) == 2:
+ other = args[1]
+ if isinstance(other, dict):
+ for key in other:
+ self[key] = other[key]
+ elif hasattr(other, 'keys'):
+ for key in other.keys():
+ self[key] = other[key]
+ else:
+ for key, value in other:
+ self[key] = value
+ for key, value in kwds.items():
+ self[key] = value
+
+ __update = update # let subclasses override update without breaking __init__
+
+ __marker = object()
+
+ def pop(self, key, default=__marker):
+ '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value.
+ If key is not found, d is returned if given, otherwise KeyError is raised.
+
+ '''
+ if key in self:
+ result = self[key]
+ del self[key]
+ return result
+ if default is self.__marker:
+ raise KeyError(key)
+ return default
+
+ def setdefault(self, key, default=None):
+ 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od'
+ if key in self:
+ return self[key]
+ self[key] = default
+ return default
+
+ def __repr__(self, _repr_running={}):
+ 'od.__repr__() <==> repr(od)'
+ call_key = id(self), _get_ident()
+ if call_key in _repr_running:
+ return '...'
+ _repr_running[call_key] = 1
+ try:
+ if not self:
+ return '%s()' % (self.__class__.__name__,)
+ return '%s(%r)' % (self.__class__.__name__, self.items())
+ finally:
+ del _repr_running[call_key]
+
+ def __reduce__(self):
+ 'Return state information for pickling'
+ items = [[k, self[k]] for k in self]
+ inst_dict = vars(self).copy()
+ for k in vars(OrderedDict()):
+ inst_dict.pop(k, None)
+ if inst_dict:
+ return (self.__class__, (items,), inst_dict)
+ return self.__class__, (items,)
+
+ def copy(self):
+ 'od.copy() -> a shallow copy of od'
+ return self.__class__(self)
+
+ @classmethod
+ def fromkeys(cls, iterable, value=None):
+ '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
+ and values equal to v (which defaults to None).
+
+ '''
+ d = cls()
+ for key in iterable:
+ d[key] = value
+ return d
+
+ def __eq__(self, other):
+ '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive
+ while comparison to a regular mapping is order-insensitive.
+
+ '''
+ if isinstance(other, OrderedDict):
+ return len(self)==len(other) and self.items() == other.items()
+ return dict.__eq__(self, other)
+
+ def __ne__(self, other):
+ return not self == other
+
+ # -- the following methods are only used in Python 2.7 --
+
+ def viewkeys(self):
+ "od.viewkeys() -> a set-like object providing a view on od's keys"
+ return KeysView(self)
+
+ def viewvalues(self):
+ "od.viewvalues() -> an object providing a view on od's values"
+ return ValuesView(self)
+
+ def viewitems(self):
+ "od.viewitems() -> a set-like object providing a view on od's items"
+ return ItemsView(self)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/funcsigs/funcsigs/version.py b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/funcsigs/version.py
new file mode 100644
index 00000000000..896a370cad1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/funcsigs/version.py
@@ -0,0 +1 @@
+__version__ = "0.4"
diff --git a/tests/wpt/web-platform-tests/tools/third_party/funcsigs/requirements/development.txt b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/requirements/development.txt
new file mode 100644
index 00000000000..ecafb0a527d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/requirements/development.txt
@@ -0,0 +1,6 @@
+coverage
+coveralls
+pip
+flake8
+sphinx
+wheel
diff --git a/tests/wpt/web-platform-tests/tools/third_party/funcsigs/requirements/production.txt b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/requirements/production.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/requirements/production.txt
diff --git a/tests/wpt/web-platform-tests/tools/third_party/funcsigs/setup.cfg b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/setup.cfg
new file mode 100644
index 00000000000..5e4090017a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/setup.cfg
@@ -0,0 +1,2 @@
+[wheel]
+universal = 1
diff --git a/tests/wpt/web-platform-tests/tools/third_party/funcsigs/setup.py b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/setup.py
new file mode 100644
index 00000000000..98b09126045
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/setup.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+from setuptools import setup
+import re
+import sys
+
+def load_version(filename='funcsigs/version.py'):
+ "Parse a __version__ number from a source file"
+ with open(filename) as source:
+ text = source.read()
+ match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", text)
+ if not match:
+ msg = "Unable to find version number in {}".format(filename)
+ raise RuntimeError(msg)
+ version = match.group(1)
+ return version
+
+def load_rst(filename='docs/source/guide_content.rst'):
+ "Purge refs directives from restructured text"
+ with open(filename) as source:
+ text = source.read()
+ doc = re.sub(r':\w+:`~?([a-zA-Z._()]+)`', r'*\1*', text)
+ return doc
+
+setup(
+ name="funcsigs",
+ version=load_version(),
+ packages=['funcsigs'],
+ zip_safe=False,
+ author="Aaron Iles",
+ author_email="aaron.iles@gmail.com",
+ url="http://funcsigs.readthedocs.org",
+ description="Python function signatures from PEP362 for Python 2.6, 2.7 and 3.2+",
+ long_description=open('README.rst').read(),
+ # long_description=load_rst(),
+ license="ASL",
+ install_requires = [],
+ classifiers = [
+ 'Development Status :: 4 - Beta',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: Apache Software License',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python',
+ 'Programming Language :: Python :: 2',
+ 'Programming Language :: Python :: 2.6',
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.2',
+ 'Programming Language :: Python :: 3.3',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ 'Topic :: Software Development :: Libraries :: Python Modules'
+ ],
+ tests_require = [] if sys.version_info[0] > 2 else ['unittest2'],
+ test_suite = "tests" if sys.version_info[0] > 2 else 'unittest2.collector'
+)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/funcsigs/tests/__init__.py b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/tests/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/tests/__init__.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/funcsigs/tests/test_formatannotation.py b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/tests/test_formatannotation.py
new file mode 100644
index 00000000000..fd7a8873f85
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/tests/test_formatannotation.py
@@ -0,0 +1,27 @@
+try:
+ # python 2.x
+ import unittest2 as unittest
+except ImportError:
+ # python 3.x
+ import unittest
+
+import funcsigs
+
+
+class TestFormatAnnotation(unittest.TestCase):
+ def test_string (self):
+ self.assertEqual(funcsigs.formatannotation("annotation"),
+ "'annotation'")
+
+ def test_builtin_type (self):
+ self.assertEqual(funcsigs.formatannotation(int),
+ "int")
+
+ def test_user_type (self):
+ class dummy (object): pass
+ self.assertEqual(funcsigs.formatannotation(dummy),
+ "tests.test_formatannotation.dummy")
+
+
+if __name__ == "__main__":
+ unittest.begin()
diff --git a/tests/wpt/web-platform-tests/tools/third_party/funcsigs/tests/test_funcsigs.py b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/tests/test_funcsigs.py
new file mode 100644
index 00000000000..eecc0a8a709
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/tests/test_funcsigs.py
@@ -0,0 +1,93 @@
+try:
+ # python 2.x
+ import unittest2 as unittest
+except ImportError:
+ # python 3.x
+ import unittest
+
+import doctest
+import sys
+
+import funcsigs as inspect
+
+
+class TestFunctionSignatures(unittest.TestCase):
+
+ @staticmethod
+ def signature(func):
+ sig = inspect.signature(func)
+ return (tuple((param.name,
+ (Ellipsis if param.default is param.empty else param.default),
+ (Ellipsis if param.annotation is param.empty
+ else param.annotation),
+ str(param.kind).lower())
+ for param in sig.parameters.values()),
+ (Ellipsis if sig.return_annotation is sig.empty
+ else sig.return_annotation))
+
+ def test_zero_arguments(self):
+ def test():
+ pass
+ self.assertEqual(self.signature(test),
+ ((), Ellipsis))
+
+ def test_single_positional_argument(self):
+ def test(a):
+ pass
+ self.assertEqual(self.signature(test),
+ (((('a', Ellipsis, Ellipsis, "positional_or_keyword")),), Ellipsis))
+
+ def test_single_keyword_argument(self):
+ def test(a=None):
+ pass
+ self.assertEqual(self.signature(test),
+ (((('a', None, Ellipsis, "positional_or_keyword")),), Ellipsis))
+
+ def test_var_args(self):
+ def test(*args):
+ pass
+ self.assertEqual(self.signature(test),
+ (((('args', Ellipsis, Ellipsis, "var_positional")),), Ellipsis))
+
+ def test_keywords_args(self):
+ def test(**kwargs):
+ pass
+ self.assertEqual(self.signature(test),
+ (((('kwargs', Ellipsis, Ellipsis, "var_keyword")),), Ellipsis))
+
+ def test_multiple_arguments(self):
+ def test(a, b=None, *args, **kwargs):
+ pass
+ self.assertEqual(self.signature(test), ((
+ ('a', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('b', None, Ellipsis, "positional_or_keyword"),
+ ('args', Ellipsis, Ellipsis, "var_positional"),
+ ('kwargs', Ellipsis, Ellipsis, "var_keyword"),
+ ), Ellipsis))
+
+ def test_has_version(self):
+ self.assertTrue(inspect.__version__)
+
+ def test_readme(self):
+ doctest.testfile('../README.rst')
+
+ def test_unbound_method(self):
+ if sys.version_info < (3,):
+ self_kind = "positional_only"
+ else:
+ self_kind = "positional_or_keyword"
+ class Test(object):
+ def method(self):
+ pass
+ def method_with_args(self, a):
+ pass
+ self.assertEqual(self.signature(Test.method),
+ (((('self', Ellipsis, Ellipsis, self_kind)),), Ellipsis))
+ self.assertEqual(self.signature(Test.method_with_args), ((
+ ('self', Ellipsis, Ellipsis, self_kind),
+ ('a', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ), Ellipsis))
+
+
+if __name__ == "__main__":
+ unittest.begin()
diff --git a/tests/wpt/web-platform-tests/tools/third_party/funcsigs/tests/test_inspect.py b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/tests/test_inspect.py
new file mode 100644
index 00000000000..323c323eafd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/funcsigs/tests/test_inspect.py
@@ -0,0 +1,1019 @@
+# Copyright 2001-2013 Python Software Foundation; All Rights Reserved
+from __future__ import absolute_import, division, print_function
+import collections
+import sys
+
+try:
+ import unittest2 as unittest
+except ImportError:
+ import unittest
+
+import funcsigs as inspect
+
+
+class TestSignatureObject(unittest.TestCase):
+ @staticmethod
+ def signature(func):
+ sig = inspect.signature(func)
+ return (tuple((param.name,
+ (Ellipsis if param.default is param.empty else param.default),
+ (Ellipsis if param.annotation is param.empty
+ else param.annotation),
+ str(param.kind).lower())
+ for param in sig.parameters.values()),
+ (Ellipsis if sig.return_annotation is sig.empty
+ else sig.return_annotation))
+
+ def __init__(self, *args, **kwargs):
+ unittest.TestCase.__init__(self, *args, **kwargs)
+ if not hasattr(self, 'assertRaisesRegex'):
+ self.assertRaisesRegex = self.assertRaisesRegexp
+
+ if sys.version_info[0] > 2:
+ exec("""
+def test_signature_object(self):
+ S = inspect.Signature
+ P = inspect.Parameter
+
+ self.assertEqual(str(S()), '()')
+
+ def test(po, pk, *args, ko, **kwargs):
+ pass
+ sig = inspect.signature(test)
+ po = sig.parameters['po'].replace(kind=P.POSITIONAL_ONLY)
+ pk = sig.parameters['pk']
+ args = sig.parameters['args']
+ ko = sig.parameters['ko']
+ kwargs = sig.parameters['kwargs']
+
+ S((po, pk, args, ko, kwargs))
+
+ with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
+ S((pk, po, args, ko, kwargs))
+
+ with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
+ S((po, args, pk, ko, kwargs))
+
+ with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
+ S((args, po, pk, ko, kwargs))
+
+ with self.assertRaisesRegex(ValueError, 'wrong parameter order'):
+ S((po, pk, args, kwargs, ko))
+
+ kwargs2 = kwargs.replace(name='args')
+ with self.assertRaisesRegex(ValueError, 'duplicate parameter name'):
+ S((po, pk, args, kwargs2, ko))
+""")
+
+ def test_signature_immutability(self):
+ def test(a):
+ pass
+ sig = inspect.signature(test)
+
+ with self.assertRaises(AttributeError):
+ sig.foo = 'bar'
+
+ # Python2 does not have MappingProxyType class
+ if sys.version_info[:2] < (3, 3):
+ return
+
+ with self.assertRaises(TypeError):
+ sig.parameters['a'] = None
+
+ def test_signature_on_noarg(self):
+ def test():
+ pass
+ self.assertEqual(self.signature(test), ((), Ellipsis))
+
+ if sys.version_info[0] > 2:
+ exec("""
+def test_signature_on_wargs(self):
+ def test(a, b:'foo') -> 123:
+ pass
+ self.assertEqual(self.signature(test),
+ ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('b', Ellipsis, 'foo', "positional_or_keyword")),
+ 123))
+""")
+
+ if sys.version_info[0] > 2:
+ exec("""
+def test_signature_on_wkwonly(self):
+ def test(*, a:float, b:str) -> int:
+ pass
+ self.assertEqual(self.signature(test),
+ ((('a', Ellipsis, float, "keyword_only"),
+ ('b', Ellipsis, str, "keyword_only")),
+ int))
+""")
+
+ if sys.version_info[0] > 2:
+ exec("""
+def test_signature_on_complex_args(self):
+ def test(a, b:'foo'=10, *args:'bar', spam:'baz', ham=123, **kwargs:int):
+ pass
+ self.assertEqual(self.signature(test),
+ ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('b', 10, 'foo', "positional_or_keyword"),
+ ('args', Ellipsis, 'bar', "var_positional"),
+ ('spam', Ellipsis, 'baz', "keyword_only"),
+ ('ham', 123, Ellipsis, "keyword_only"),
+ ('kwargs', Ellipsis, int, "var_keyword")),
+ Ellipsis))
+""")
+
+ def test_signature_on_builtin_function(self):
+ with self.assertRaisesRegex(ValueError, 'not supported by signature'):
+ inspect.signature(type)
+ with self.assertRaisesRegex(ValueError, 'not supported by signature'):
+ # support for 'wrapper_descriptor'
+ inspect.signature(type.__call__)
+ if hasattr(sys, 'pypy_version_info'):
+ raise ValueError('not supported by signature')
+ with self.assertRaisesRegex(ValueError, 'not supported by signature'):
+ # support for 'method-wrapper'
+ inspect.signature(min.__call__)
+ if hasattr(sys, 'pypy_version_info'):
+ raise ValueError('not supported by signature')
+ with self.assertRaisesRegex(ValueError,
+ 'no signature found for builtin function'):
+ # support for 'method-wrapper'
+ inspect.signature(min)
+
+ def test_signature_on_non_function(self):
+ with self.assertRaisesRegex(TypeError, 'is not a callable object'):
+ inspect.signature(42)
+
+ with self.assertRaisesRegex(TypeError, 'is not a Python function'):
+ inspect.Signature.from_function(42)
+
+ if sys.version_info[0] > 2:
+ exec("""
+def test_signature_on_method(self):
+ class Test:
+ def foo(self, arg1, arg2=1) -> int:
+ pass
+
+ meth = Test().foo
+
+ self.assertEqual(self.signature(meth),
+ ((('arg1', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('arg2', 1, Ellipsis, "positional_or_keyword")),
+ int))
+""")
+
+ if sys.version_info[0] > 2:
+ exec("""
+def test_signature_on_classmethod(self):
+ class Test:
+ @classmethod
+ def foo(cls, arg1, *, arg2=1):
+ pass
+
+ meth = Test().foo
+ self.assertEqual(self.signature(meth),
+ ((('arg1', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('arg2', 1, Ellipsis, "keyword_only")),
+ Ellipsis))
+
+ meth = Test.foo
+ self.assertEqual(self.signature(meth),
+ ((('arg1', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('arg2', 1, Ellipsis, "keyword_only")),
+ Ellipsis))
+""")
+
+ if sys.version_info[0] > 2:
+ exec("""
+def test_signature_on_staticmethod(self):
+ class Test:
+ @staticmethod
+ def foo(cls, *, arg):
+ pass
+
+ meth = Test().foo
+ self.assertEqual(self.signature(meth),
+ ((('cls', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('arg', Ellipsis, Ellipsis, "keyword_only")),
+ Ellipsis))
+
+ meth = Test.foo
+ self.assertEqual(self.signature(meth),
+ ((('cls', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('arg', Ellipsis, Ellipsis, "keyword_only")),
+ Ellipsis))
+""")
+
+ if sys.version_info[0] > 2:
+ exec("""
+def test_signature_on_partial(self):
+ from functools import partial
+
+ def test():
+ pass
+
+ self.assertEqual(self.signature(partial(test)), ((), Ellipsis))
+
+ with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
+ inspect.signature(partial(test, 1))
+
+ with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
+ inspect.signature(partial(test, a=1))
+
+ def test(a, b, *, c, d):
+ pass
+
+ self.assertEqual(self.signature(partial(test)),
+ ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('b', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('c', Ellipsis, Ellipsis, "keyword_only"),
+ ('d', Ellipsis, Ellipsis, "keyword_only")),
+ Ellipsis))
+
+ self.assertEqual(self.signature(partial(test, 1)),
+ ((('b', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('c', Ellipsis, Ellipsis, "keyword_only"),
+ ('d', Ellipsis, Ellipsis, "keyword_only")),
+ Ellipsis))
+
+ self.assertEqual(self.signature(partial(test, 1, c=2)),
+ ((('b', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('c', 2, Ellipsis, "keyword_only"),
+ ('d', Ellipsis, Ellipsis, "keyword_only")),
+ Ellipsis))
+
+ self.assertEqual(self.signature(partial(test, b=1, c=2)),
+ ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('b', 1, Ellipsis, "positional_or_keyword"),
+ ('c', 2, Ellipsis, "keyword_only"),
+ ('d', Ellipsis, Ellipsis, "keyword_only")),
+ Ellipsis))
+
+ self.assertEqual(self.signature(partial(test, 0, b=1, c=2)),
+ ((('b', 1, Ellipsis, "positional_or_keyword"),
+ ('c', 2, Ellipsis, "keyword_only"),
+ ('d', Ellipsis, Ellipsis, "keyword_only"),),
+ Ellipsis))
+
+ def test(a, *args, b, **kwargs):
+ pass
+
+ self.assertEqual(self.signature(partial(test, 1)),
+ ((('args', Ellipsis, Ellipsis, "var_positional"),
+ ('b', Ellipsis, Ellipsis, "keyword_only"),
+ ('kwargs', Ellipsis, Ellipsis, "var_keyword")),
+ Ellipsis))
+
+ self.assertEqual(self.signature(partial(test, 1, 2, 3)),
+ ((('args', Ellipsis, Ellipsis, "var_positional"),
+ ('b', Ellipsis, Ellipsis, "keyword_only"),
+ ('kwargs', Ellipsis, Ellipsis, "var_keyword")),
+ Ellipsis))
+
+
+ self.assertEqual(self.signature(partial(test, 1, 2, 3, test=True)),
+ ((('args', Ellipsis, Ellipsis, "var_positional"),
+ ('b', Ellipsis, Ellipsis, "keyword_only"),
+ ('kwargs', Ellipsis, Ellipsis, "var_keyword")),
+ Ellipsis))
+
+ self.assertEqual(self.signature(partial(test, 1, 2, 3, test=1, b=0)),
+ ((('args', Ellipsis, Ellipsis, "var_positional"),
+ ('b', 0, Ellipsis, "keyword_only"),
+ ('kwargs', Ellipsis, Ellipsis, "var_keyword")),
+ Ellipsis))
+
+ self.assertEqual(self.signature(partial(test, b=0)),
+ ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('args', Ellipsis, Ellipsis, "var_positional"),
+ ('b', 0, Ellipsis, "keyword_only"),
+ ('kwargs', Ellipsis, Ellipsis, "var_keyword")),
+ Ellipsis))
+
+ self.assertEqual(self.signature(partial(test, b=0, test=1)),
+ ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('args', Ellipsis, Ellipsis, "var_positional"),
+ ('b', 0, Ellipsis, "keyword_only"),
+ ('kwargs', Ellipsis, Ellipsis, "var_keyword")),
+ Ellipsis))
+
+ def test(a, b, c:int) -> 42:
+ pass
+
+ sig = test.__signature__ = inspect.signature(test)
+
+ self.assertEqual(self.signature(partial(partial(test, 1))),
+ ((('b', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('c', Ellipsis, int, "positional_or_keyword")),
+ 42))
+
+ self.assertEqual(self.signature(partial(partial(test, 1), 2)),
+ ((('c', Ellipsis, int, "positional_or_keyword"),),
+ 42))
+
+ psig = inspect.signature(partial(partial(test, 1), 2))
+
+ def foo(a):
+ return a
+ _foo = partial(partial(foo, a=10), a=20)
+ self.assertEqual(self.signature(_foo),
+ ((('a', 20, Ellipsis, "positional_or_keyword"),),
+ Ellipsis))
+ # check that we don't have any side-effects in signature(),
+ # and the partial object is still functioning
+ self.assertEqual(_foo(), 20)
+
+ def foo(a, b, c):
+ return a, b, c
+ _foo = partial(partial(foo, 1, b=20), b=30)
+ self.assertEqual(self.signature(_foo),
+ ((('b', 30, Ellipsis, "positional_or_keyword"),
+ ('c', Ellipsis, Ellipsis, "positional_or_keyword")),
+ Ellipsis))
+ self.assertEqual(_foo(c=10), (1, 30, 10))
+ _foo = partial(_foo, 2) # now 'b' has two values -
+ # positional and keyword
+ with self.assertRaisesRegex(ValueError, "has incorrect arguments"):
+ inspect.signature(_foo)
+
+ def foo(a, b, c, *, d):
+ return a, b, c, d
+ _foo = partial(partial(foo, d=20, c=20), b=10, d=30)
+ self.assertEqual(self.signature(_foo),
+ ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('b', 10, Ellipsis, "positional_or_keyword"),
+ ('c', 20, Ellipsis, "positional_or_keyword"),
+ ('d', 30, Ellipsis, "keyword_only")),
+ Ellipsis))
+ ba = inspect.signature(_foo).bind(a=200, b=11)
+ self.assertEqual(_foo(*ba.args, **ba.kwargs), (200, 11, 20, 30))
+
+ def foo(a=1, b=2, c=3):
+ return a, b, c
+ _foo = partial(foo, a=10, c=13)
+ ba = inspect.signature(_foo).bind(11)
+ self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 2, 13))
+ ba = inspect.signature(_foo).bind(11, 12)
+ self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
+ ba = inspect.signature(_foo).bind(11, b=12)
+ self.assertEqual(_foo(*ba.args, **ba.kwargs), (11, 12, 13))
+ ba = inspect.signature(_foo).bind(b=12)
+ self.assertEqual(_foo(*ba.args, **ba.kwargs), (10, 12, 13))
+ _foo = partial(_foo, b=10)
+ ba = inspect.signature(_foo).bind(12, 14)
+ self.assertEqual(_foo(*ba.args, **ba.kwargs), (12, 14, 13))
+""")
+
+ if sys.version_info[0] > 2:
+ exec("""
+def test_signature_on_decorated(self):
+ import functools
+
+ def decorator(func):
+ @functools.wraps(func)
+ def wrapper(*args, **kwargs) -> int:
+ return func(*args, **kwargs)
+ return wrapper
+
+ class Foo:
+ @decorator
+ def bar(self, a, b):
+ pass
+
+ self.assertEqual(self.signature(Foo.bar),
+ ((('self', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('a', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('b', Ellipsis, Ellipsis, "positional_or_keyword")),
+ Ellipsis))
+
+ self.assertEqual(self.signature(Foo().bar),
+ ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('b', Ellipsis, Ellipsis, "positional_or_keyword")),
+ Ellipsis))
+
+ # Test that we handle method wrappers correctly
+ def decorator(func):
+ @functools.wraps(func)
+ def wrapper(*args, **kwargs) -> int:
+ return func(42, *args, **kwargs)
+ sig = inspect.signature(func)
+ new_params = tuple(sig.parameters.values())[1:]
+ wrapper.__signature__ = sig.replace(parameters=new_params)
+ return wrapper
+
+ class Foo:
+ @decorator
+ def __call__(self, a, b):
+ pass
+
+ self.assertEqual(self.signature(Foo.__call__),
+ ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('b', Ellipsis, Ellipsis, "positional_or_keyword")),
+ Ellipsis))
+
+ self.assertEqual(self.signature(Foo().__call__),
+ ((('b', Ellipsis, Ellipsis, "positional_or_keyword"),),
+ Ellipsis))
+""")
+
+ if sys.version_info[0] > 2:
+ exec("""
+def test_signature_on_class(self):
+ class C:
+ def __init__(self, a):
+ pass
+
+ self.assertEqual(self.signature(C),
+ ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),),
+ Ellipsis))
+
+ class CM(type):
+ def __call__(cls, a):
+ pass
+ class C(metaclass=CM):
+ def __init__(self, b):
+ pass
+
+ self.assertEqual(self.signature(C),
+ ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),),
+ Ellipsis))
+
+ class CM(type):
+ def __new__(mcls, name, bases, dct, *, foo=1):
+ return super().__new__(mcls, name, bases, dct)
+ class C(metaclass=CM):
+ def __init__(self, b):
+ pass
+
+ self.assertEqual(self.signature(C),
+ ((('b', Ellipsis, Ellipsis, "positional_or_keyword"),),
+ Ellipsis))
+
+ self.assertEqual(self.signature(CM),
+ ((('name', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('bases', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('dct', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('foo', 1, Ellipsis, "keyword_only")),
+ Ellipsis))
+
+ class CMM(type):
+ def __new__(mcls, name, bases, dct, *, foo=1):
+ return super().__new__(mcls, name, bases, dct)
+ def __call__(cls, nm, bs, dt):
+ return type(nm, bs, dt)
+ class CM(type, metaclass=CMM):
+ def __new__(mcls, name, bases, dct, *, bar=2):
+ return super().__new__(mcls, name, bases, dct)
+ class C(metaclass=CM):
+ def __init__(self, b):
+ pass
+
+ self.assertEqual(self.signature(CMM),
+ ((('name', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('bases', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('dct', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('foo', 1, Ellipsis, "keyword_only")),
+ Ellipsis))
+
+ self.assertEqual(self.signature(CM),
+ ((('nm', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('bs', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('dt', Ellipsis, Ellipsis, "positional_or_keyword")),
+ Ellipsis))
+
+ self.assertEqual(self.signature(C),
+ ((('b', Ellipsis, Ellipsis, "positional_or_keyword"),),
+ Ellipsis))
+
+ class CM(type):
+ def __init__(cls, name, bases, dct, *, bar=2):
+ return super().__init__(name, bases, dct)
+ class C(metaclass=CM):
+ def __init__(self, b):
+ pass
+
+ self.assertEqual(self.signature(CM),
+ ((('name', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('bases', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('dct', Ellipsis, Ellipsis, "positional_or_keyword"),
+ ('bar', 2, Ellipsis, "keyword_only")),
+ Ellipsis))
+""")
+
+ def test_signature_on_callable_objects(self):
+ class Foo(object):
+ def __call__(self, a):
+ pass
+
+ self.assertEqual(self.signature(Foo()),
+ ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),),
+ Ellipsis))
+
+ class Spam(object):
+ pass
+ with self.assertRaisesRegex(TypeError, "is not a callable object"):
+ inspect.signature(Spam())
+
+ class Bar(Spam, Foo):
+ pass
+
+ self.assertEqual(self.signature(Bar()),
+ ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),),
+ Ellipsis))
+
+ class ToFail(object):
+ __call__ = type
+ with self.assertRaisesRegex(ValueError, "not supported by signature"):
+ inspect.signature(ToFail())
+
+ if sys.version_info[0] < 3:
+ return
+
+ class Wrapped(object):
+ pass
+ Wrapped.__wrapped__ = lambda a: None
+ self.assertEqual(self.signature(Wrapped),
+ ((('a', Ellipsis, Ellipsis, "positional_or_keyword"),),
+ Ellipsis))
+
+ def test_signature_on_lambdas(self):
+ self.assertEqual(self.signature((lambda a=10: a)),
+ ((('a', 10, Ellipsis, "positional_or_keyword"),),
+ Ellipsis))
+
+ if sys.version_info[0] > 2:
+ exec("""
+def test_signature_equality(self):
+ def foo(a, *, b:int) -> float: pass
+ self.assertNotEqual(inspect.signature(foo), 42)
+
+ def bar(a, *, b:int) -> float: pass
+ self.assertEqual(inspect.signature(foo), inspect.signature(bar))
+
+ def bar(a, *, b:int) -> int: pass
+ self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
+
+ def bar(a, *, b:int): pass
+ self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
+
+ def bar(a, *, b:int=42) -> float: pass
+ self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
+
+ def bar(a, *, c) -> float: pass
+ self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
+
+ def bar(a, b:int) -> float: pass
+ self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
+ def spam(b:int, a) -> float: pass
+ self.assertNotEqual(inspect.signature(spam), inspect.signature(bar))
+
+ def foo(*, a, b, c): pass
+ def bar(*, c, b, a): pass
+ self.assertEqual(inspect.signature(foo), inspect.signature(bar))
+
+ def foo(*, a=1, b, c): pass
+ def bar(*, c, b, a=1): pass
+ self.assertEqual(inspect.signature(foo), inspect.signature(bar))
+
+ def foo(pos, *, a=1, b, c): pass
+ def bar(pos, *, c, b, a=1): pass
+ self.assertEqual(inspect.signature(foo), inspect.signature(bar))
+
+ def foo(pos, *, a, b, c): pass
+ def bar(pos, *, c, b, a=1): pass
+ self.assertNotEqual(inspect.signature(foo), inspect.signature(bar))
+
+ def foo(pos, *args, a=42, b, c, **kwargs:int): pass
+ def bar(pos, *args, c, b, a=42, **kwargs:int): pass
+ self.assertEqual(inspect.signature(foo), inspect.signature(bar))
+""")
+
+ def test_signature_unhashable(self):
+ def foo(a): pass
+ sig = inspect.signature(foo)
+ with self.assertRaisesRegex(TypeError, 'unhashable type'):
+ hash(sig)
+
+
+ if sys.version_info[0] > 2:
+ exec("""
+def test_signature_str(self):
+ def foo(a:int=1, *, b, c=None, **kwargs) -> 42:
+ pass
+ self.assertEqual(str(inspect.signature(foo)),
+ '(a:int=1, *, b, c=None, **kwargs) -> 42')
+
+ def foo(a:int=1, *args, b, c=None, **kwargs) -> 42:
+ pass
+ self.assertEqual(str(inspect.signature(foo)),
+ '(a:int=1, *args, b, c=None, **kwargs) -> 42')
+
+ def foo():
+ pass
+ self.assertEqual(str(inspect.signature(foo)), '()')
+""")
+
+ if sys.version_info[0] > 2:
+ exec("""
+def test_signature_str_positional_only(self):
+ P = inspect.Parameter
+
+ def test(a_po, *, b, **kwargs):
+ return a_po, kwargs
+
+ sig = inspect.signature(test)
+ new_params = list(sig.parameters.values())
+ new_params[0] = new_params[0].replace(kind=P.POSITIONAL_ONLY)
+ test.__signature__ = sig.replace(parameters=new_params)
+
+ self.assertEqual(str(inspect.signature(test)),
+ '(<a_po>, *, b, **kwargs)')
+
+ sig = inspect.signature(test)
+ new_params = list(sig.parameters.values())
+ new_params[0] = new_params[0].replace(name=None)
+ test.__signature__ = sig.replace(parameters=new_params)
+ self.assertEqual(str(inspect.signature(test)),
+ '(<0>, *, b, **kwargs)')
+""")
+
+ if sys.version_info[0] > 2:
+ exec("""
+def test_signature_replace_anno(self):
+ def test() -> 42:
+ pass
+
+ sig = inspect.signature(test)
+ sig = sig.replace(return_annotation=None)
+ self.assertIs(sig.return_annotation, None)
+ sig = sig.replace(return_annotation=sig.empty)
+ self.assertIs(sig.return_annotation, sig.empty)
+ sig = sig.replace(return_annotation=42)
+ self.assertEqual(sig.return_annotation, 42)
+ self.assertEqual(sig, inspect.signature(test))
+""")
+
+
+class TestParameterObject(unittest.TestCase):
+
+ def __init__(self, *args, **kwargs):
+ unittest.TestCase.__init__(self, *args, **kwargs)
+ if not hasattr(self, 'assertRaisesRegex'):
+ self.assertRaisesRegex = self.assertRaisesRegexp
+
+ def test_signature_parameter_kinds(self):
+ P = inspect.Parameter
+ self.assertTrue(P.POSITIONAL_ONLY < P.POSITIONAL_OR_KEYWORD < \
+ P.VAR_POSITIONAL < P.KEYWORD_ONLY < P.VAR_KEYWORD)
+
+ self.assertEqual(str(P.POSITIONAL_ONLY), 'POSITIONAL_ONLY')
+ self.assertTrue('POSITIONAL_ONLY' in repr(P.POSITIONAL_ONLY))
+
+ def test_signature_parameter_object(self):
+ p = inspect.Parameter('foo', default=10,
+ kind=inspect.Parameter.POSITIONAL_ONLY)
+ self.assertEqual(p.name, 'foo')
+ self.assertEqual(p.default, 10)
+ self.assertIs(p.annotation, p.empty)
+ self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY)
+
+ with self.assertRaisesRegex(ValueError, 'invalid value'):
+ inspect.Parameter('foo', default=10, kind='123')
+
+ with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
+ inspect.Parameter('1', kind=inspect.Parameter.VAR_KEYWORD)
+
+ with self.assertRaisesRegex(ValueError,
+ 'non-positional-only parameter'):
+ inspect.Parameter(None, kind=inspect.Parameter.VAR_KEYWORD)
+
+ with self.assertRaisesRegex(ValueError, 'cannot have default values'):
+ inspect.Parameter('a', default=42,
+ kind=inspect.Parameter.VAR_KEYWORD)
+
+ with self.assertRaisesRegex(ValueError, 'cannot have default values'):
+ inspect.Parameter('a', default=42,
+ kind=inspect.Parameter.VAR_POSITIONAL)
+
+ p = inspect.Parameter('a', default=42,
+ kind=inspect.Parameter.POSITIONAL_OR_KEYWORD)
+ with self.assertRaisesRegex(ValueError, 'cannot have default values'):
+ p.replace(kind=inspect.Parameter.VAR_POSITIONAL)
+
+ self.assertTrue(repr(p).startswith('<Parameter'))
+
+ def test_signature_parameter_equality(self):
+ P = inspect.Parameter
+ p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
+
+ self.assertEqual(p, p)
+ self.assertNotEqual(p, 42)
+
+ self.assertEqual(p, P('foo', default=42,
+ kind=inspect.Parameter.KEYWORD_ONLY))
+
+ def test_signature_parameter_unhashable(self):
+ p = inspect.Parameter('foo', default=42,
+ kind=inspect.Parameter.KEYWORD_ONLY)
+
+ with self.assertRaisesRegex(TypeError, 'unhashable type'):
+ hash(p)
+
+ def test_signature_parameter_replace(self):
+ p = inspect.Parameter('foo', default=42,
+ kind=inspect.Parameter.KEYWORD_ONLY)
+
+ self.assertIsNot(p, p.replace())
+ self.assertEqual(p, p.replace())
+
+ p2 = p.replace(annotation=1)
+ self.assertEqual(p2.annotation, 1)
+ p2 = p2.replace(annotation=p2.empty)
+ self.assertEqual(p, p2)
+
+ p2 = p2.replace(name='bar')
+ self.assertEqual(p2.name, 'bar')
+ self.assertNotEqual(p2, p)
+
+ with self.assertRaisesRegex(ValueError, 'not a valid parameter name'):
+ p2 = p2.replace(name=p2.empty)
+
+ p2 = p2.replace(name='foo', default=None)
+ self.assertIs(p2.default, None)
+ self.assertNotEqual(p2, p)
+
+ p2 = p2.replace(name='foo', default=p2.empty)
+ self.assertIs(p2.default, p2.empty)
+
+
+ p2 = p2.replace(default=42, kind=p2.POSITIONAL_OR_KEYWORD)
+ self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD)
+ self.assertNotEqual(p2, p)
+
+ with self.assertRaisesRegex(ValueError, 'invalid value for'):
+ p2 = p2.replace(kind=p2.empty)
+
+ p2 = p2.replace(kind=p2.KEYWORD_ONLY)
+ self.assertEqual(p2, p)
+
+ def test_signature_parameter_positional_only(self):
+ p = inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
+ self.assertEqual(str(p), '<>')
+
+ p = p.replace(name='1')
+ self.assertEqual(str(p), '<1>')
+
+ def test_signature_parameter_immutability(self):
+ p = inspect.Parameter(None, kind=inspect.Parameter.POSITIONAL_ONLY)
+
+ with self.assertRaises(AttributeError):
+ p.foo = 'bar'
+
+ with self.assertRaises(AttributeError):
+ p.kind = 123
+
+
+class TestSignatureBind(unittest.TestCase):
+ @staticmethod
+ def call(func, *args, **kwargs):
+ sig = inspect.signature(func)
+ ba = sig.bind(*args, **kwargs)
+ return func(*ba.args, **ba.kwargs)
+
+ def __init__(self, *args, **kwargs):
+ unittest.TestCase.__init__(self, *args, **kwargs)
+ if not hasattr(self, 'assertRaisesRegex'):
+ self.assertRaisesRegex = self.assertRaisesRegexp
+
+ def test_signature_bind_empty(self):
+ def test():
+ return 42
+
+ self.assertEqual(self.call(test), 42)
+ with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
+ self.call(test, 1)
+ with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
+ self.call(test, 1, spam=10)
+ with self.assertRaisesRegex(TypeError, 'too many keyword arguments'):
+ self.call(test, spam=1)
+
+ def test_signature_bind_var(self):
+ def test(*args, **kwargs):
+ return args, kwargs
+
+ self.assertEqual(self.call(test), ((), {}))
+ self.assertEqual(self.call(test, 1), ((1,), {}))
+ self.assertEqual(self.call(test, 1, 2), ((1, 2), {}))
+ self.assertEqual(self.call(test, foo='bar'), ((), {'foo': 'bar'}))
+ self.assertEqual(self.call(test, 1, foo='bar'), ((1,), {'foo': 'bar'}))
+ self.assertEqual(self.call(test, args=10), ((), {'args': 10}))
+ self.assertEqual(self.call(test, 1, 2, foo='bar'),
+ ((1, 2), {'foo': 'bar'}))
+
+ def test_signature_bind_just_args(self):
+ def test(a, b, c):
+ return a, b, c
+
+ self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
+
+ with self.assertRaisesRegex(TypeError, 'too many positional arguments'):
+ self.call(test, 1, 2, 3, 4)
+
+ with self.assertRaisesRegex(TypeError, "'b' parameter lacking default"):
+ self.call(test, 1)
+
+ with self.assertRaisesRegex(TypeError, "'a' parameter lacking default"):
+ self.call(test)
+
+ def test(a, b, c=10):
+ return a, b, c
+ self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
+ self.assertEqual(self.call(test, 1, 2), (1, 2, 10))
+
+ def test(a=1, b=2, c=3):
+ return a, b, c
+ self.assertEqual(self.call(test, a=10, c=13), (10, 2, 13))
+ self.assertEqual(self.call(test, a=10), (10, 2, 3))
+ self.assertEqual(self.call(test, b=10), (1, 10, 3))
+
+ def test_signature_bind_varargs_order(self):
+ def test(*args):
+ return args
+
+ self.assertEqual(self.call(test), ())
+ self.assertEqual(self.call(test, 1, 2, 3), (1, 2, 3))
+
+ def test_signature_bind_args_and_varargs(self):
+ def test(a, b, c=3, *args):
+ return a, b, c, args
+
+ self.assertEqual(self.call(test, 1, 2, 3, 4, 5), (1, 2, 3, (4, 5)))
+ self.assertEqual(self.call(test, 1, 2), (1, 2, 3, ()))
+ self.assertEqual(self.call(test, b=1, a=2), (2, 1, 3, ()))
+ self.assertEqual(self.call(test, 1, b=2), (1, 2, 3, ()))
+
+ with self.assertRaisesRegex(TypeError,
+ "multiple values for argument 'c'"):
+ self.call(test, 1, 2, 3, c=4)
+
+ def test_signature_bind_just_kwargs(self):
+ def test(**kwargs):
+ return kwargs
+
+ self.assertEqual(self.call(test), {})
+ self.assertEqual(self.call(test, foo='bar', spam='ham'),
+ {'foo': 'bar', 'spam': 'ham'})
+
+ def test_signature_bind_args_and_kwargs(self):
+ def test(a, b, c=3, **kwargs):
+ return a, b, c, kwargs
+
+ self.assertEqual(self.call(test, 1, 2), (1, 2, 3, {}))
+ self.assertEqual(self.call(test, 1, 2, foo='bar', spam='ham'),
+ (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
+ self.assertEqual(self.call(test, b=2, a=1, foo='bar', spam='ham'),
+ (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
+ self.assertEqual(self.call(test, a=1, b=2, foo='bar', spam='ham'),
+ (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
+ self.assertEqual(self.call(test, 1, b=2, foo='bar', spam='ham'),
+ (1, 2, 3, {'foo': 'bar', 'spam': 'ham'}))
+ self.assertEqual(self.call(test, 1, b=2, c=4, foo='bar', spam='ham'),
+ (1, 2, 4, {'foo': 'bar', 'spam': 'ham'}))
+ self.assertEqual(self.call(test, 1, 2, 4, foo='bar'),
+ (1, 2, 4, {'foo': 'bar'}))
+ self.assertEqual(self.call(test, c=5, a=4, b=3),
+ (4, 3, 5, {}))
+
+ if sys.version_info[0] > 2:
+ exec("""
+def test_signature_bind_kwonly(self):
+ def test(*, foo):
+ return foo
+ with self.assertRaisesRegex(TypeError,
+ 'too many positional arguments'):
+ self.call(test, 1)
+ self.assertEqual(self.call(test, foo=1), 1)
+
+ def test(a, *, foo=1, bar):
+ return foo
+ with self.assertRaisesRegex(TypeError,
+ "'bar' parameter lacking default value"):
+ self.call(test, 1)
+
+ def test(foo, *, bar):
+ return foo, bar
+ self.assertEqual(self.call(test, 1, bar=2), (1, 2))
+ self.assertEqual(self.call(test, bar=2, foo=1), (1, 2))
+
+ with self.assertRaisesRegex(TypeError,
+ 'too many keyword arguments'):
+ self.call(test, bar=2, foo=1, spam=10)
+
+ with self.assertRaisesRegex(TypeError,
+ 'too many positional arguments'):
+ self.call(test, 1, 2)
+
+ with self.assertRaisesRegex(TypeError,
+ 'too many positional arguments'):
+ self.call(test, 1, 2, bar=2)
+
+ with self.assertRaisesRegex(TypeError,
+ 'too many keyword arguments'):
+ self.call(test, 1, bar=2, spam='ham')
+
+ with self.assertRaisesRegex(TypeError,
+ "'bar' parameter lacking default value"):
+ self.call(test, 1)
+
+ def test(foo, *, bar, **bin):
+ return foo, bar, bin
+ self.assertEqual(self.call(test, 1, bar=2), (1, 2, {}))
+ self.assertEqual(self.call(test, foo=1, bar=2), (1, 2, {}))
+ self.assertEqual(self.call(test, 1, bar=2, spam='ham'),
+ (1, 2, {'spam': 'ham'}))
+ self.assertEqual(self.call(test, spam='ham', foo=1, bar=2),
+ (1, 2, {'spam': 'ham'}))
+ with self.assertRaisesRegex(TypeError,
+ "'foo' parameter lacking default value"):
+ self.call(test, spam='ham', bar=2)
+ self.assertEqual(self.call(test, 1, bar=2, bin=1, spam=10),
+ (1, 2, {'bin': 1, 'spam': 10}))
+""")
+#
+ if sys.version_info[0] > 2:
+ exec("""
+def test_signature_bind_arguments(self):
+ def test(a, *args, b, z=100, **kwargs):
+ pass
+ sig = inspect.signature(test)
+ ba = sig.bind(10, 20, b=30, c=40, args=50, kwargs=60)
+ # we won't have 'z' argument in the bound arguments object, as we didn't
+ # pass it to the 'bind'
+ self.assertEqual(tuple(ba.arguments.items()),
+ (('a', 10), ('args', (20,)), ('b', 30),
+ ('kwargs', {'c': 40, 'args': 50, 'kwargs': 60})))
+ self.assertEqual(ba.kwargs,
+ {'b': 30, 'c': 40, 'args': 50, 'kwargs': 60})
+ self.assertEqual(ba.args, (10, 20))
+""")
+#
+ if sys.version_info[0] > 2:
+ exec("""
+def test_signature_bind_positional_only(self):
+ P = inspect.Parameter
+
+ def test(a_po, b_po, c_po=3, foo=42, *, bar=50, **kwargs):
+ return a_po, b_po, c_po, foo, bar, kwargs
+
+ sig = inspect.signature(test)
+ new_params = collections.OrderedDict(tuple(sig.parameters.items()))
+ for name in ('a_po', 'b_po', 'c_po'):
+ new_params[name] = new_params[name].replace(kind=P.POSITIONAL_ONLY)
+ new_sig = sig.replace(parameters=new_params.values())
+ test.__signature__ = new_sig
+
+ self.assertEqual(self.call(test, 1, 2, 4, 5, bar=6),
+ (1, 2, 4, 5, 6, {}))
+
+ with self.assertRaisesRegex(TypeError, "parameter is positional only"):
+ self.call(test, 1, 2, c_po=4)
+
+ with self.assertRaisesRegex(TypeError, "parameter is positional only"):
+ self.call(test, a_po=1, b_po=2)
+""")
+
+
+class TestBoundArguments(unittest.TestCase):
+
+ def __init__(self, *args, **kwargs):
+ unittest.TestCase.__init__(self, *args, **kwargs)
+ if not hasattr(self, 'assertRaisesRegex'):
+ self.assertRaisesRegex = self.assertRaisesRegexp
+
+ def test_signature_bound_arguments_unhashable(self):
+ def foo(a): pass
+ ba = inspect.signature(foo).bind(1)
+
+ with self.assertRaisesRegex(TypeError, 'unhashable type'):
+ hash(ba)
+
+ def test_signature_bound_arguments_equality(self):
+ def foo(a): pass
+ ba = inspect.signature(foo).bind(1)
+ self.assertEqual(ba, ba)
+
+ ba2 = inspect.signature(foo).bind(1)
+ self.assertEqual(ba, ba2)
+
+ ba3 = inspect.signature(foo).bind(2)
+ self.assertNotEqual(ba, ba3)
+ ba3.arguments['a'] = 1
+ self.assertEqual(ba, ba3)
+
+ def bar(b): pass
+ ba4 = inspect.signature(bar).bind(1)
+ self.assertNotEqual(ba, ba4)
+
+
+if __name__ == "__main__":
+ unittest.begin()
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pluggy/.gitignore b/tests/wpt/web-platform-tests/tools/third_party/pluggy/.gitignore
new file mode 100644
index 00000000000..e5c7e98041c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pluggy/.gitignore
@@ -0,0 +1,58 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+env/
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+*.egg-info/
+.installed.cfg
+*.egg
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*,cover
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+*.swp
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pluggy/.travis.yml b/tests/wpt/web-platform-tests/tools/third_party/pluggy/.travis.yml
new file mode 100644
index 00000000000..6fd136baf37
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pluggy/.travis.yml
@@ -0,0 +1,48 @@
+sudo: false
+language: python
+
+matrix:
+ include:
+ - python: '3.6'
+ env: TOXENV=check
+ - python: '3.6'
+ env: TOXENV=docs
+ - python: '2.7'
+ env: TOXENV=py27-pytestrelease
+ - python: '3.4'
+ env: TOXENV=py34-pytestrelease
+ - python: '3.5'
+ env: TOXENV=py35-pytestrelease
+ - python: '3.6'
+ env: TOXENV=py36-pytestrelease
+ - python: 'pypy'
+ env: TOXENV=pypy-pytestrelease
+ - python: 'nightly'
+ env: TOXENV=py37-pytestrelease
+ - python: '2.7'
+ env: TOXENV=py27-pytestmaster
+ - python: '2.7'
+ env: TOXENV=py27-pytestfeatures
+ - python: '3.6'
+ env: TOXENV=py36-pytestmaster
+ - python: '3.6'
+ env: TOXENV=py36-pytestfeatures
+ - python: '3.6'
+ env: TOXENV=benchmark
+
+install:
+ - pip install -U setuptools pip
+ - pip install -U tox
+
+script:
+ - tox
+
+notifications:
+ irc:
+ channels:
+ - "chat.freenode.net#pytest"
+ on_success: change
+ on_failure: change
+ skip_join: true
+# email:
+# - pytest-commit@python.org
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pluggy/CHANGELOG.rst b/tests/wpt/web-platform-tests/tools/third_party/pluggy/CHANGELOG.rst
new file mode 100644
index 00000000000..91bf53fdccb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pluggy/CHANGELOG.rst
@@ -0,0 +1,152 @@
+0.6.0
+-----
+- Add CI testing for the features, release, and master
+ branches of ``pytest`` (PR `#79`_).
+- Document public API for ``_Result`` objects passed to wrappers
+ (PR `#85`_).
+- Document and test hook LIFO ordering (PR `#85`_).
+- Turn warnings into errors in test suite (PR `#89`_).
+- Deprecate ``_Result.result`` (PR `#88`_).
+- Convert ``_Multicall`` to a simple function distinguishing it from
+ the legacy version (PR `#90`_).
+- Resolve E741 errors (PR `#96`_).
+- Test and bug fix for unmarked hook collection (PRs `#97`_ and
+ `#102`_).
+- Drop support for EOL Python 2.6 and 3.3 (PR `#103`_).
+- Fix ``inspect`` based arg introspection on py3.6 (PR `#94`_).
+
+.. _#79: https://github.com/pytest-dev/pluggy/pull/79
+.. _#85: https://github.com/pytest-dev/pluggy/pull/85
+.. _#88: https://github.com/pytest-dev/pluggy/pull/88
+.. _#89: https://github.com/pytest-dev/pluggy/pull/89
+.. _#90: https://github.com/pytest-dev/pluggy/pull/90
+.. _#94: https://github.com/pytest-dev/pluggy/pull/94
+.. _#96: https://github.com/pytest-dev/pluggy/pull/96
+.. _#97: https://github.com/pytest-dev/pluggy/pull/97
+.. _#102: https://github.com/pytest-dev/pluggy/pull/102
+.. _#103: https://github.com/pytest-dev/pluggy/pull/103
+
+
+0.5.2
+-----
+- fix bug where ``firstresult`` wrappers were being sent an incorrectly configured
+ ``_Result`` (a list was set instead of a single value). Add tests to check for
+ this as well as ``_Result.force_result()`` behaviour. Thanks to `@tgoodlet`_
+ for the PR `#72`_.
+
+- fix incorrect ``getattr`` of ``DeprecationWarning`` from the ``warnings``
+ module. Thanks to `@nicoddemus`_ for the PR `#77`_.
+
+- hide ``pytest`` tracebacks in certain core routines. Thanks to
+ `@nicoddemus`_ for the PR `#80`_.
+
+.. _#72: https://github.com/pytest-dev/pluggy/pull/72
+.. _#77: https://github.com/pytest-dev/pluggy/pull/77
+.. _#80: https://github.com/pytest-dev/pluggy/pull/80
+
+
+0.5.1
+-----
+- fix a bug and add tests for case where ``firstresult`` hooks return
+ ``None`` results. Thanks to `@RonnyPfannschmidt`_ and `@tgoodlet`_
+ for the issue (`#68`_) and PR (`#69`_) respectively.
+
+.. _#69: https://github.com/pytest-dev/pluggy/pull/69
+.. _#68: https://github.com/pytest-dev/pluggy/issuses/68
+
+
+0.5.0
+-----
+- fix bug where callbacks for historic hooks would not be called for
+ already registered plugins. Thanks `@vodik`_ for the PR
+ and `@hpk42`_ for further fixes.
+
+- fix `#17`_ by considering only actual functions for hooks
+ this removes the ability to register arbitrary callable objects
+ which at first glance is a reasonable simplification,
+ thanks `@RonnyPfannschmidt`_ for report and pr.
+
+- fix `#19`_: allow registering hookspecs from instances. The PR from
+ `@tgoodlet`_ also modernized the varnames implementation.
+
+- resolve `#32`_: split up the test set into multiple modules.
+ Thanks to `@RonnyPfannschmidt`_ for the PR and `@tgoodlet`_ for
+ the initial request.
+
+- resolve `#14`_: add full sphinx docs. Thanks to `@tgoodlet`_ for
+ PR `#39`_.
+
+- add hook call mismatch warnings. Thanks to `@tgoodlet`_ for the
+ PR `#42`_.
+
+- resolve `#44`_: move to new-style classes. Thanks to `@MichalTHEDUDE`_
+ for PR `#46`_.
+
+- add baseline benchmarking/speed tests using ``pytest-benchmark``
+ in PR `#54`_. Thanks to `@tgoodlet`_.
+
+- update the README to showcase the API. Thanks to `@tgoodlet`_ for the
+ issue and PR `#55`_.
+
+- deprecate ``__multicall__`` and add a faster call loop implementation.
+ Thanks to `@tgoodlet`_ for PR `#58`_.
+
+- raise a comprehensible error when a ``hookimpl`` is called with positional
+ args. Thanks to `@RonnyPfannschmidt`_ for the issue and `@tgoodlet`_ for
+ PR `#60`_.
+
+- fix the ``firstresult`` test making it more complete
+ and remove a duplicate of that test. Thanks to `@tgoodlet`_
+ for PR `#62`_.
+
+.. _#62: https://github.com/pytest-dev/pluggy/pull/62
+.. _#60: https://github.com/pytest-dev/pluggy/pull/60
+.. _#58: https://github.com/pytest-dev/pluggy/pull/58
+.. _#55: https://github.com/pytest-dev/pluggy/pull/55
+.. _#54: https://github.com/pytest-dev/pluggy/pull/54
+.. _#46: https://github.com/pytest-dev/pluggy/pull/46
+.. _#44: https://github.com/pytest-dev/pluggy/issues/44
+.. _#42: https://github.com/pytest-dev/pluggy/pull/42
+.. _#39: https://github.com/pytest-dev/pluggy/pull/39
+.. _#32: https://github.com/pytest-dev/pluggy/pull/32
+.. _#19: https://github.com/pytest-dev/pluggy/issues/19
+.. _#17: https://github.com/pytest-dev/pluggy/issues/17
+.. _#14: https://github.com/pytest-dev/pluggy/issues/14
+
+
+0.4.0
+-----
+- add ``has_plugin(name)`` method to pluginmanager. thanks `@nicoddemus`_.
+
+- fix `#11`_: make plugin parsing more resilient against exceptions
+ from ``__getattr__`` functions. Thanks `@nicoddemus`_.
+
+- fix issue `#4`_: specific ``HookCallError`` exception for when a hook call
+ provides not enough arguments.
+
+- better error message when loading setuptools entrypoints fails
+ due to a ``VersionConflict``. Thanks `@blueyed`_.
+
+.. _#11: https://github.com/pytest-dev/pluggy/issues/11
+.. _#4: https://github.com/pytest-dev/pluggy/issues/4
+
+
+0.3.1
+-----
+- avoid using deprecated-in-python3.5 getargspec method. Thanks
+ `@mdboom`_.
+
+
+0.3.0
+-----
+initial release
+
+.. contributors
+.. _@hpk42: https://github.com/hpk42
+.. _@tgoodlet: https://github.com/tgoodlet
+.. _@MichalTHEDUDE: https://github.com/MichalTHEDUDE
+.. _@vodik: https://github.com/vodik
+.. _@RonnyPfannschmidt: https://github.com/RonnyPfannschmidt
+.. _@blueyed: https://github.com/blueyed
+.. _@nicoddemus: https://github.com/nicoddemus
+.. _@mdboom: https://github.com/mdboom
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pluggy/LICENSE b/tests/wpt/web-platform-tests/tools/third_party/pluggy/LICENSE
new file mode 100644
index 00000000000..121017d0866
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pluggy/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 holger krekel (rather uses bitbucket/hpk42)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pluggy/MANIFEST.in b/tests/wpt/web-platform-tests/tools/third_party/pluggy/MANIFEST.in
new file mode 100644
index 00000000000..0cf8f3e0887
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pluggy/MANIFEST.in
@@ -0,0 +1,7 @@
+include CHANGELOG
+include README.rst
+include setup.py
+include tox.ini
+include LICENSE
+graft testing
+recursive-exclude * *.pyc *.pyo
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pluggy/README.rst b/tests/wpt/web-platform-tests/tools/third_party/pluggy/README.rst
new file mode 100644
index 00000000000..3636b6ec642
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pluggy/README.rst
@@ -0,0 +1,80 @@
+pluggy - A minimalist production ready plugin system
+====================================================
+|pypi| |anaconda| |versions| |travis| |appveyor|
+
+
+This is the core framework used by the `pytest`_, `tox`_, and `devpi`_ projects.
+
+Please `read the docs`_ to learn more!
+
+A definitive example
+********************
+.. code-block:: python
+
+ import pluggy
+
+ hookspec = pluggy.HookspecMarker("myproject")
+ hookimpl = pluggy.HookimplMarker("myproject")
+
+
+ class MySpec(object):
+ """A hook specification namespace.
+ """
+ @hookspec
+ def myhook(self, arg1, arg2):
+ """My special little hook that you can customize.
+ """
+
+
+ class Plugin_1(object):
+ """A hook implementation namespace.
+ """
+ @hookimpl
+ def myhook(self, arg1, arg2):
+ print("inside Plugin_1.myhook()")
+ return arg1 + arg2
+
+
+ class Plugin_2(object):
+ """A 2nd hook implementation namespace.
+ """
+ @hookimpl
+ def myhook(self, arg1, arg2):
+ print("inside Plugin_2.myhook()")
+ return arg1 - arg2
+
+
+ # create a manager and add the spec
+ pm = pluggy.PluginManager("myproject")
+ pm.add_hookspecs(MySpec)
+
+ # register plugins
+ pm.register(Plugin_1())
+ pm.register(Plugin_2())
+
+ # call our `myhook` hook
+ results = pm.hook.myhook(arg1=1, arg2=2)
+ print(results)
+
+
+.. badges
+.. |pypi| image:: https://img.shields.io/pypi/v/pluggy.svg
+ :target: https://pypi.python.org/pypi/pluggy
+.. |versions| image:: https://img.shields.io/pypi/pyversions/pluggy.svg
+ :target: https://pypi.python.org/pypi/pluggy
+.. |travis| image:: https://img.shields.io/travis/pytest-dev/pluggy/master.svg
+ :target: https://travis-ci.org/pytest-dev/pluggy
+.. |appveyor| image:: https://img.shields.io/appveyor/ci/pytestbot/pluggy/master.svg
+ :target: https://ci.appveyor.com/project/pytestbot/pluggy
+.. |anaconda| image:: https://anaconda.org/conda-forge/pluggy/badges/version.svg
+ :target: https://anaconda.org/conda-forge/pluggy
+
+.. links
+.. _pytest:
+ http://pytest.org
+.. _tox:
+ https://tox.readthedocs.org
+.. _devpi:
+ http://doc.devpi.net
+.. _read the docs:
+ https://pluggy.readthedocs.io/en/latest/
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pluggy/appveyor.yml b/tests/wpt/web-platform-tests/tools/third_party/pluggy/appveyor.yml
new file mode 100644
index 00000000000..c3903f8bfcc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pluggy/appveyor.yml
@@ -0,0 +1,34 @@
+environment:
+ matrix:
+ # note: please use "tox --listenvs" to populate the build matrix below
+ - TOXENV: "check"
+ - TOXENV: "docs"
+ - TOXENV: "py27-pytestrelease"
+ - TOXENV: "py34-pytestrelease"
+ - TOXENV: "py35-pytestrelease"
+ - TOXENV: "py36-pytestrelease"
+ - TOXENV: "pypy-pytestrelease"
+ - TOXENV: "py27-pytestmaster"
+ - TOXENV: "py27-pytestfeatures"
+ - TOXENV: "py36-pytestmaster"
+ - TOXENV: "py36-pytestfeatures"
+
+install:
+ - echo Installed Pythons
+ - dir c:\Python*
+
+ # install pypy using choco (redirect to a file and write to console in case
+ # choco install returns non-zero, because choco install python.pypy is too
+ # noisy)
+ # pypy is disabled until #1963 gets fixed
+ - choco install python.pypy > pypy-inst.log 2>&1 || (type pypy-inst.log & exit /b 1)
+ - set PATH=C:\tools\pypy\pypy;%PATH% # so tox can find pypy
+ - echo PyPy installed
+ - pypy --version
+
+ - C:\Python35\python -m pip install tox
+
+build: false # Not a C# project, build stuff at the test step instead.
+
+test_script:
+ - C:\Python35\python -m tox
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pluggy/docs/_static/img/plug.png b/tests/wpt/web-platform-tests/tools/third_party/pluggy/docs/_static/img/plug.png
new file mode 100644
index 00000000000..3339f8a608d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pluggy/docs/_static/img/plug.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pluggy/docs/api_reference.rst b/tests/wpt/web-platform-tests/tools/third_party/pluggy/docs/api_reference.rst
new file mode 100644
index 00000000000..aa15135ad3d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pluggy/docs/api_reference.rst
@@ -0,0 +1,14 @@
+Api Reference
+=============
+
+.. automodule:: pluggy
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+
+.. automethod:: pluggy._Result.get_result
+
+.. automethod:: pluggy._Result.force_result
+
+.. automethod:: pluggy._HookCaller.call_extra
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pluggy/docs/conf.py b/tests/wpt/web-platform-tests/tools/third_party/pluggy/docs/conf.py
new file mode 100644
index 00000000000..04065218fda
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pluggy/docs/conf.py
@@ -0,0 +1,71 @@
+# -*- coding: utf-8 -*-
+import pkg_resources
+
+
+extensions = [
+ 'sphinx.ext.autodoc',
+ 'sphinx.ext.doctest',
+ 'sphinx.ext.intersphinx',
+ 'sphinx.ext.coverage',
+ 'sphinx.ext.viewcode',
+]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+
+dist = pkg_resources.get_distribution('pluggy')
+project = dist.project_name
+copyright = u'2016, Holger Krekel'
+author = 'Holger Krekel'
+
+release = dist.version
+# The short X.Y version.
+version = u'.'.join(dist.version.split('.')[:2])
+
+
+language = None
+
+pygments_style = 'sphinx'
+html_logo = '_static/img/plug.png'
+html_theme = 'alabaster'
+html_theme_options = {
+ # 'logo': 'img/plug.png',
+ # 'logo_name': 'true',
+ 'description': 'The `pytest` plugin system',
+ 'github_user': 'pytest-dev',
+ 'github_repo': 'pluggy',
+ 'github_button': 'true',
+ 'github_banner': 'true',
+ 'page_width': '1080px',
+ 'fixed_sidebar': 'false',
+}
+html_static_path = ['_static']
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ (master_doc, 'pluggy', u'pluggy Documentation',
+ [author], 1)
+]
+
+
+# -- Options for Texinfo output -------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ (master_doc, 'pluggy', u'pluggy Documentation',
+ author, 'pluggy', 'One line description of project.',
+ 'Miscellaneous'),
+]
+
+# Example configuration for intersphinx: refer to the Python standard library.
+intersphinx_mapping = {'https://docs.python.org/': None}
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pluggy/docs/examples/firstexample.py b/tests/wpt/web-platform-tests/tools/third_party/pluggy/docs/examples/firstexample.py
new file mode 100644
index 00000000000..3cec7cd2144
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pluggy/docs/examples/firstexample.py
@@ -0,0 +1,44 @@
+import pluggy
+
+hookspec = pluggy.HookspecMarker("myproject")
+hookimpl = pluggy.HookimplMarker("myproject")
+
+
+class MySpec(object):
+ """A hook specification namespace.
+ """
+ @hookspec
+ def myhook(self, arg1, arg2):
+ """My special little hook that you can customize.
+ """
+
+
+class Plugin_1(object):
+ """A hook implementation namespace.
+ """
+ @hookimpl
+ def myhook(self, arg1, arg2):
+ print("inside Plugin_1.myhook()")
+ return arg1 + arg2
+
+
+class Plugin_2(object):
+ """A 2nd hook implementation namespace.
+ """
+ @hookimpl
+ def myhook(self, arg1, arg2):
+ print("inside Plugin_2.myhook()")
+ return arg1 - arg2
+
+
+# create a manager and add the spec
+pm = pluggy.PluginManager("myproject")
+pm.add_hookspecs(MySpec)
+
+# register plugins
+pm.register(Plugin_1())
+pm.register(Plugin_2())
+
+# call our `myhook` hook
+results = pm.hook.myhook(arg1=1, arg2=2)
+print(results)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pluggy/docs/index.rst b/tests/wpt/web-platform-tests/tools/third_party/pluggy/docs/index.rst
new file mode 100644
index 00000000000..db65a1023fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pluggy/docs/index.rst
@@ -0,0 +1,705 @@
+``pluggy``
+==========
+
+The ``pytest`` plugin system
+****************************
+``pluggy`` is the crystallized core of `plugin management and hook
+calling`_ for `pytest`_.
+
+In fact, ``pytest`` is itself composed as a set of ``pluggy`` plugins
+which are invoked in sequence according to a well defined set of protocols.
+Some `200+ plugins`_ use ``pluggy`` to extend and customize ``pytest``'s default behaviour.
+
+In essence, ``pluggy`` enables function `hooking`_ so you can build "pluggable" systems.
+
+How's it work?
+--------------
+A `plugin` is a `namespace`_ which defines hook functions.
+
+``pluggy`` manages *plugins* by relying on:
+
+- a hook *specification* - defines a call signature
+- a set of hook *implementations* - aka `callbacks`_
+- the hook *caller* - a call loop which collects results
+
+where for each registered hook *specification*, a hook *call* will invoke up to ``N``
+registered hook *implementations*.
+
+``pluggy`` accomplishes all this by implementing a `request-response pattern`_ using *function*
+subscriptions and can be thought of and used as a rudimentary busless `publish-subscribe`_
+event system.
+
+``pluggy``'s approach is meant to let a designer think carefuly about which objects are
+explicitly needed by an extension writer. This is in contrast to subclass-based extension
+systems which may expose unecessary state and behaviour or encourage `tight coupling`_
+in overlying frameworks.
+
+
+A first example
+---------------
+
+.. literalinclude:: examples/firstexample.py
+
+Running this directly gets us::
+
+ $ python docs/examples/firstexample.py
+
+ inside Plugin_2.myhook()
+ inside Plugin_1.myhook()
+ [-1, 3]
+
+For more details and advanced usage please read on.
+
+.. _define:
+
+Defining and Collecting Hooks
+*****************************
+A *plugin* is a namespace type (currently one of a ``class`` or module)
+which defines a set of *hook* functions.
+
+As mentioned in :ref:`manage`, all *plugins* which define *hooks*
+are managed by an instance of a :py:class:`pluggy.PluginManager` which
+defines the primary ``pluggy`` API.
+
+In order for a ``PluginManager`` to detect functions in a namespace
+intended to be *hooks*, they must be decorated using special ``pluggy`` *marks*.
+
+.. _marking_hooks:
+
+Marking hooks
+-------------
+The :py:class:`~pluggy.HookspecMarker` and :py:class:`~pluggy.HookimplMarker`
+decorators are used to *mark* functions for detection by a ``PluginManager``:
+
+.. code-block:: python
+
+ from pluggy import HookspecMarker, HookimplMarker
+
+ hookspec = HookspecMarker('project_name')
+ hookimpl = HookimplMarker('project_name')
+
+
+Each decorator type takes a single ``project_name`` string as its
+lone argument the value of which is used to mark hooks for detection by
+by a similarly configured ``PluginManager`` instance.
+
+That is, a *mark* type called with ``project_name`` returns an object which
+can be used to decorate functions which will then be detected by a
+``PluginManager`` which was instantiated with the the same ``project_name``
+value.
+
+Furthermore, each *hookimpl* or *hookspec* decorator can configure the
+underlying call-time behavior of each *hook* object by providing special
+*options* passed as keyword arguments.
+
+
+.. note::
+ The following sections correspond to similar documentation in
+ ``pytest`` for `Writing hook functions`_ and can be used
+ as a supplementary resource.
+
+.. _impls:
+
+Implementations
+---------------
+A hook *implementation* (*hookimpl*) is just a (callback) function
+which has been appropriately marked.
+
+*hookimpls* are loaded from a plugin using the
+:py:meth:`~pluggy.PluginManager.register()` method:
+
+.. code-block:: python
+
+ import sys
+ from pluggy import PluginManager, HookimplMarker
+
+ hookimpl = HookimplMarker('myproject')
+
+ @hookimpl
+ def setup_project(config, args):
+ """This hook is used to process the initial config
+ and possibly input arguments.
+ """
+ if args:
+ config.process_args(args)
+
+ return config
+
+ pm = PluginManager('myproject')
+
+ # load all hookimpls from the local module's namespace
+ plugin_name = pm.register(sys.modules[__name__])
+
+.. _optionalhook:
+
+Optional validation
+^^^^^^^^^^^^^^^^^^^
+Normally each *hookimpl* should be validated a against a corresponding
+hook :ref:`specification <specs>`. If you want to make an exception
+then the *hookimpl* should be marked with the ``"optionalhook"`` option:
+
+.. code-block:: python
+
+ @hookimpl(optionalhook=True)
+ def setup_project(config, args):
+ """This hook is used to process the initial config
+ and possibly input arguments.
+ """
+ if args:
+ config.process_args(args)
+
+ return config
+
+Call time order
+^^^^^^^^^^^^^^^
+By default hooks are :ref:`called <calling>` in LIFO registered order, however,
+a *hookimpl* can influence its call-time invocation position using special
+attributes. If marked with a ``"tryfirst"`` or ``"trylast"`` option it
+will be executed *first* or *last* respectively in the hook call loop:
+
+.. code-block:: python
+
+ import sys
+ from pluggy import PluginManager, HookimplMarker
+
+ hookimpl = HookimplMarker('myproject')
+
+ @hookimpl(trylast=True)
+ def setup_project(config, args):
+ """Default implementation.
+ """
+ if args:
+ config.process_args(args)
+
+ return config
+
+
+ class SomeOtherPlugin(object):
+ """Some other plugin defining the same hook.
+ """
+ @hookimpl(tryfirst=True)
+ def setup_project(config, args):
+ """Report what args were passed before calling
+ downstream hooks.
+ """
+ if args:
+ print("Got args: {}".format(args))
+
+ return config
+
+ pm = PluginManager('myproject')
+
+ # load from the local module's namespace
+ pm.register(sys.modules[__name__])
+ # load a plugin defined on a class
+ pm.register(SomePlugin())
+
+For another example see the `hook function ordering`_ section of the
+``pytest`` docs.
+
+.. note::
+ ``tryfirst`` and ``trylast`` hooks are still invoked in LIFO order within
+ each category.
+
+Wrappers
+^^^^^^^^
+A *hookimpl* can be marked with a ``"hookwrapper"`` option which indicates that
+the function will be called to *wrap* (or surround) all other normal *hookimpl*
+calls. A *hookwrapper* can thus execute some code ahead and after the execution
+of all corresponding non-wrappper *hookimpls*.
+
+Much in the same way as a `@contextlib.contextmanager`_, *hookwrappers* must
+be implemented as generator function with a single ``yield`` in its body:
+
+
+.. code-block:: python
+
+ @hookimpl(hookwrapper=True)
+ def setup_project(config, args):
+ """Wrap calls to ``setup_project()`` implementations which
+ should return json encoded config options.
+ """
+ if config.debug:
+ print("Pre-hook config is {}".format(
+ config.tojson()))
+
+ # get initial default config
+ defaults = config.tojson()
+
+ # all corresponding hookimpls are invoked here
+ outcome = yield
+
+ for item in outcome.get_result():
+ print("JSON config override is {}".format(item))
+
+ if config.debug:
+ print("Post-hook config is {}".format(
+ config.tojson()))
+
+ if config.use_defaults:
+ outcome.force_result(defaults)
+
+The generator is `sent`_ a :py:class:`pluggy._Result` object which can
+be assigned in the ``yield`` expression and used to override or inspect
+the final result(s) returned back to the caller using the
+:py:meth:`~pluggy._Result.force_result` or
+:py:meth:`~pluggy._Result.get_result` methods.
+
+.. note::
+ Hook wrappers can **not** return results (as per generator function
+ semantics); they can only modify them using the ``_Result`` API.
+
+Also see the `hookwrapper`_ section in the ``pytest`` docs.
+
+.. _specs:
+
+Specifications
+--------------
+A hook *specification* (*hookspec*) is a definition used to validate each
+*hookimpl* ensuring that an extension writer has correctly defined their
+callback function *implementation* .
+
+*hookspecs* are defined using similarly marked functions however only the
+function *signature* (its name and names of all its arguments) is analyzed
+and stored. As such, often you will see a *hookspec* defined with only
+a docstring in its body.
+
+*hookspecs* are loaded using the
+:py:meth:`~pluggy.PluginManager.add_hookspecs()` method and normally
+should be added before registering corresponding *hookimpls*:
+
+.. code-block:: python
+
+ import sys
+ from pluggy import PluginManager, HookspecMarker
+
+ hookspec = HookspecMarker('myproject')
+
+ @hookspec
+ def setup_project(config, args):
+ """This hook is used to process the inital config and input
+ arguments.
+ """
+
+ pm = PluginManager('myproject')
+
+ # load from the local module's namespace
+ pm.add_hookspecs(sys.modules[__name__])
+
+
+Registering a *hookimpl* which does not meet the constraints of its
+corresponding *hookspec* will result in an error.
+
+A *hookspec* can also be added **after** some *hookimpls* have been
+registered however this is not normally recommended as it results in
+delayed hook validation.
+
+.. note::
+ The term *hookspec* can sometimes refer to the plugin-namespace
+ which defines ``hookspec`` decorated functions as in the case of
+ ``pytest``'s `hookspec module`_
+
+Enforcing spec validation
+^^^^^^^^^^^^^^^^^^^^^^^^^
+By default there is no strict requirement that each *hookimpl* has
+a corresponding *hookspec*. However, if you'd like you enforce this
+behavior you can run a check with the
+:py:meth:`~pluggy.PluginManager.check_pending()` method. If you'd like
+to enforce requisite *hookspecs* but with certain exceptions for some hooks
+then make sure to mark those hooks as :ref:`optional <optionalhook>`.
+
+Opt-in arguments
+^^^^^^^^^^^^^^^^
+To allow for *hookspecs* to evolve over the lifetime of a project,
+*hookimpls* can accept **less** arguments then defined in the spec.
+This allows for extending hook arguments (and thus semantics) without
+breaking existing *hookimpls*.
+
+In other words this is ok:
+
+.. code-block:: python
+
+ @hookspec
+ def myhook(config, args):
+ pass
+
+ @hookimpl
+ def myhook(args):
+ print(args)
+
+
+whereas this is not:
+
+.. code-block:: python
+
+ @hookspec
+ def myhook(config, args):
+ pass
+
+ @hookimpl
+ def myhook(config, args, extra_arg):
+ print(args)
+
+.. _firstresult:
+
+First result only
+^^^^^^^^^^^^^^^^^
+A *hookspec* can be marked such that when the *hook* is called the call loop
+will only invoke up to the first *hookimpl* which returns a result other
+then ``None``.
+
+.. code-block:: python
+
+ @hookspec(firstresult=True)
+ def myhook(config, args):
+ pass
+
+This can be useful for optimizing a call loop for which you are only
+interested in a single core *hookimpl*. An example is the
+`pytest_cmdline_main`_ central routine of ``pytest``.
+
+Also see the `first result`_ section in the ``pytest`` docs.
+
+.. _historic:
+
+Historic hooks
+^^^^^^^^^^^^^^
+You can mark a *hookspec* as being *historic* meaning that the hook
+can be called with :py:meth:`~pluggy.PluginManager.call_historic()` **before**
+having been registered:
+
+.. code-block:: python
+
+ @hookspec(historic=True)
+ def myhook(config, args):
+ pass
+
+The implication is that late registered *hookimpls* will be called back
+immediately at register time and **can not** return a result to the caller.**
+
+This turns out to be particularly useful when dealing with lazy or
+dynamically loaded plugins.
+
+For more info see :ref:`call_historic`.
+
+
+.. links
+.. _@contextlib.contextmanager:
+ https://docs.python.org/3.6/library/contextlib.html#contextlib.contextmanager
+.. _pytest_cmdline_main:
+ https://github.com/pytest-dev/pytest/blob/master/_pytest/hookspec.py#L80
+.. _hookspec module:
+ https://github.com/pytest-dev/pytest/blob/master/_pytest/hookspec.py
+.. _Writing hook functions:
+ http://doc.pytest.org/en/latest/writing_plugins.html#writing-hook-functions
+.. _hookwrapper:
+ http://doc.pytest.org/en/latest/writing_plugins.html#hookwrapper-executing-around-other-hooks
+.. _hook function ordering:
+ http://doc.pytest.org/en/latest/writing_plugins.html#hook-function-ordering-call-example
+.. _first result:
+ http://doc.pytest.org/en/latest/writing_plugins.html#firstresult-stop-at-first-non-none-result
+.. _sent:
+ https://docs.python.org/3/reference/expressions.html#generator.send
+
+.. _manage:
+
+The Plugin Registry
+*******************
+``pluggy`` manages plugins using instances of the
+:py:class:`pluggy.PluginManager`.
+
+A ``PluginManager`` is instantiated with a single
+``str`` argument, the ``project_name``:
+
+.. code-block:: python
+
+ import pluggy
+ pm = pluggy.PluginManager('my_project_name')
+
+
+The ``project_name`` value is used when a ``PluginManager`` scans for *hook*
+functions :ref:`defined on a plugin <define>`.
+This allows for multiple
+plugin managers from multiple projects to define hooks alongside each other.
+
+
+Registration
+------------
+Each ``PluginManager`` maintains a *plugin* registry where each *plugin*
+contains a set of *hookimpl* definitions. Loading *hookimpl* and *hookspec*
+definitions to populate the registry is described in detail in the section on
+:ref:`define`.
+
+In summary, you pass a plugin namespace object to the
+:py:meth:`~pluggy.PluginManager.register()` and
+:py:meth:`~pluggy.PluginManager.add_hookspec()` methods to collect
+hook *implementations* and *specfications* from *plugin* namespaces respectively.
+
+You can unregister any *plugin*'s hooks using
+:py:meth:`~pluggy.PluginManager.unregister()` and check if a plugin is
+registered by passing its name to the
+:py:meth:`~pluggy.PluginManager.is_registered()` method.
+
+Loading ``setuptools`` entry points
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+You can automatically load plugins registered through `setuptools entry points`_
+with the :py:meth:`~pluggy.PluginManager.load_setuptools_entrypoints()`
+method.
+
+An example use of this is the `pytest entry point`_.
+
+
+Blocking
+--------
+You can block any plugin from being registered using
+:py:meth:`~pluggy.PluginManager.set_blocked()` and check if a given
+*plugin* is blocked by name using :py:meth:`~pluggy.PluginManager.is_blocked()`.
+
+
+Inspection
+----------
+You can use a variety of methods to inspect the both the registry
+and particular plugins in it:
+
+- :py:meth:`~pluggy.PluginManager.list_name_plugin()` -
+ return a list of name-plugin pairs
+- :py:meth:`~pluggy.PluginManager.get_plugins()` - retrieve all plugins
+- :py:meth:`~pluggy.PluginManager.get_canonical_name()`- get a *plugin*'s
+ canonical name (the name it was registered with)
+- :py:meth:`~pluggy.PluginManager.get_plugin()` - retrieve a plugin by its
+ canonical name
+
+
+Parsing mark options
+^^^^^^^^^^^^^^^^^^^^
+You can retrieve the *options* applied to a particular
+*hookspec* or *hookimpl* as per :ref:`marking_hooks` using the
+:py:meth:`~pluggy.PluginManager.parse_hookspec_opts()` and
+:py:meth:`~pluggy.PluginManager.parse_hookimpl_opts()` respectively.
+
+.. links
+.. _setuptools entry points:
+ http://setuptools.readthedocs.io/en/latest/setuptools.html#dynamic-discovery-of-services-and-plugins
+.. _pytest entry point:
+ http://doc.pytest.org/en/latest/writing_plugins.html#setuptools-entry-points
+
+
+.. _calling:
+
+Calling Hooks
+*************
+The core functionality of ``pluggy`` enables an extension provider
+to override function calls made at certain points throughout a program.
+
+A particular *hook* is invoked by calling an instance of
+a :py:class:`pluggy._HookCaller` which in turn *loops* through the
+``1:N`` registered *hookimpls* and calls them in sequence.
+
+Every :py:class:`pluggy.PluginManager` has a ``hook`` attribute
+which is an instance of this :py:class:`pluggy._HookRelay`.
+The ``_HookRelay`` itself contains references (by hook name) to each
+registered *hookimpl*'s ``_HookCaller`` instance.
+
+More practically you call a *hook* like so:
+
+.. code-block:: python
+
+ import sys
+ import pluggy
+ import mypluginspec
+ import myplugin
+ from configuration import config
+
+ pm = pluggy.PluginManager("myproject")
+ pm.add_hookspecs(mypluginspec)
+ pm.register(myplugin)
+
+ # we invoke the _HookCaller and thus all underlying hookimpls
+ result_list = pm.hook.myhook(config=config, args=sys.argv)
+
+Note that you **must** call hooks using keyword `arguments`_ syntax!
+
+Hook implementations are called in LIFO registered order: *the last
+registered plugin's hooks are called first*. As an example, the below
+assertion should not error:
+
+.. code-block:: python
+
+ from pluggy import PluginManager, HookimplMarker
+
+ hookimpl = HookimplMarker('myproject')
+
+ class Plugin1(object):
+ def myhook(self, args):
+ """Default implementation.
+ """
+ return 1
+
+ class Plugin2(object):
+ def myhook(self, args):
+ """Default implementation.
+ """
+ return 2
+
+ class Plugin3(object):
+ def myhook(self, args):
+ """Default implementation.
+ """
+ return 3
+
+ pm = PluginManager('myproject')
+ pm.register(Plugin1())
+ pm.register(Plugin2())
+ pm.register(Plugin3())
+
+ assert pm.hook.myhook(args=()) == [3, 2, 1]
+
+Collecting results
+------------------
+By default calling a hook results in all underlying :ref:`hookimpls
+<impls>` functions to be invoked in sequence via a loop. Any function
+which returns a value other then a ``None`` result will have that result
+appended to a :py:class:`list` which is returned by the call.
+
+The only exception to this behaviour is if the hook has been marked to return
+its :ref:`firstresult` in which case only the first single value (which is not
+``None``) will be returned.
+
+.. _call_historic:
+
+Historic calls
+--------------
+A *historic call* allows for all newly registered functions to receive all hook
+calls that happened before their registration. The implication is that this is
+only useful if you expect that some *hookimpls* may be registered **after** the
+hook is initially invoked.
+
+Historic hooks must be :ref:`specially marked <historic>` and called
+using the :py:meth:`pluggy._HookCaller.call_historic()` method:
+
+.. code-block:: python
+
+ # call with history; no results returned
+ pm.hook.myhook.call_historic(config=config, args=sys.argv)
+
+ # ... more of our program ...
+
+ # late loading of some plugin
+ import mylateplugin
+
+ # historic call back is done here
+ pm.register(mylateplugin)
+
+Note that if you ``call_historic()`` the ``_HookCaller`` (and thus your
+calling code) can not receive results back from the underlying *hookimpl*
+functions.
+
+Calling with extras
+-------------------
+You can call a hook with temporarily participating *implementation* functions
+(that aren't in the registry) using the
+:py:meth:`pluggy._HookCaller.call_extra()` method.
+
+
+Calling with a subset of registered plugins
+-------------------------------------------
+You can make a call using a subset of plugins by asking the
+``PluginManager`` first for a ``_HookCaller`` with those plugins removed
+using the :py:meth:`pluggy.PluginManager.subset_hook_caller()` method.
+
+You then can use that ``_HookCaller`` to make normal, ``call_historic()``,
+or ``call_extra()`` calls as necessary.
+
+
+.. links
+.. _arguments:
+ https://docs.python.org/3/glossary.html#term-argument
+
+
+Built-in tracing
+****************
+``pluggy`` comes with some batteries included hook tracing for your
+debugging needs.
+
+
+Call tracing
+------------
+To enable tracing use the
+:py:meth:`pluggy.PluginManager.enable_tracing()` method which returns an
+undo function to disable the behaviour.
+
+.. code-block:: python
+
+ pm = PluginManager('myproject')
+ # magic line to set a writer function
+ pm.trace.root.setwriter(print)
+ undo = pm.enable_tracing()
+
+
+Call monitoring
+---------------
+Instead of using the built-in tracing mechanism you can also add your
+own ``before`` and ``after`` monitoring functions using
+:py:class:`pluggy.PluginManager.add_hookcall_monitoring()`.
+
+The expected signature and default implementations for these functions is:
+
+.. code-block:: python
+
+ def before(hook_name, methods, kwargs):
+ pass
+
+ def after(outcome, hook_name, methods, kwargs):
+ pass
+
+Public API
+**********
+Please see the :doc:`api_reference`.
+
+Development
+***********
+Great care must taken when hacking on ``pluggy`` since multiple mature
+projects rely on it. Our Github integrated CI process runs the full
+`tox test suite`_ on each commit so be sure your changes can run on
+all required `Python interpreters`_ and ``pytest`` versions.
+
+Release Policy
+**************
+Pluggy uses `Semantic Versioning`_. Breaking changes are only foreseen for
+Major releases (incremented X in "X.Y.Z"). If you want to use ``pluggy``
+in your project you should thus use a dependency restriction like
+``"pluggy>=0.1.0,<1.0"`` to avoid surprises.
+
+
+.. hyperlinks
+.. _pytest:
+ http://pytest.org
+.. _request-response pattern:
+ https://en.wikipedia.org/wiki/Request%E2%80%93response
+.. _publish-subscribe:
+ https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern
+.. _hooking:
+ https://en.wikipedia.org/wiki/Hooking
+.. _plugin management and hook calling:
+ http://doc.pytest.org/en/latest/writing_plugins.html
+.. _namespace:
+ https://docs.python.org/3.6/tutorial/classes.html#python-scopes-and-namespaces
+.. _callbacks:
+ https://en.wikipedia.org/wiki/Callback_(computer_programming)
+.. _tox test suite:
+ https://github.com/pytest-dev/pluggy/blob/master/tox.ini
+.. _Semantic Versioning:
+ http://semver.org/
+.. _tight coupling:
+ https://en.wikipedia.org/wiki/Coupling_%28computer_programming%29#Types_of_coupling
+.. _Python interpreters:
+ https://github.com/pytest-dev/pluggy/blob/master/tox.ini#L2
+.. _200+ plugins:
+ http://plugincompat.herokuapp.com/
+
+
+.. Indices and tables
+.. ==================
+.. * :ref:`genindex`
+.. * :ref:`modindex`
+.. * :ref:`search`
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pluggy/pluggy/__init__.py b/tests/wpt/web-platform-tests/tools/third_party/pluggy/pluggy/__init__.py
new file mode 100644
index 00000000000..ab5175d9566
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pluggy/pluggy/__init__.py
@@ -0,0 +1,684 @@
+import inspect
+import warnings
+from .callers import _multicall, HookCallError, _Result, _legacymulticall
+
+__version__ = '0.5.3.dev'
+
+__all__ = ["PluginManager", "PluginValidationError", "HookCallError",
+ "HookspecMarker", "HookimplMarker"]
+
+
+class PluginValidationError(Exception):
+ """ plugin failed validation. """
+
+
+class HookspecMarker(object):
+ """ Decorator helper class for marking functions as hook specifications.
+
+ You can instantiate it with a project_name to get a decorator.
+ Calling PluginManager.add_hookspecs later will discover all marked functions
+ if the PluginManager uses the same project_name.
+ """
+
+ def __init__(self, project_name):
+ self.project_name = project_name
+
+ def __call__(self, function=None, firstresult=False, historic=False):
+ """ if passed a function, directly sets attributes on the function
+ which will make it discoverable to add_hookspecs(). If passed no
+ function, returns a decorator which can be applied to a function
+ later using the attributes supplied.
+
+ If firstresult is True the 1:N hook call (N being the number of registered
+ hook implementation functions) will stop at I<=N when the I'th function
+ returns a non-None result.
+
+ If historic is True calls to a hook will be memorized and replayed
+ on later registered plugins.
+
+ """
+ def setattr_hookspec_opts(func):
+ if historic and firstresult:
+ raise ValueError("cannot have a historic firstresult hook")
+ setattr(func, self.project_name + "_spec",
+ dict(firstresult=firstresult, historic=historic))
+ return func
+
+ if function is not None:
+ return setattr_hookspec_opts(function)
+ else:
+ return setattr_hookspec_opts
+
+
+class HookimplMarker(object):
+ """ Decorator helper class for marking functions as hook implementations.
+
+ You can instantiate with a project_name to get a decorator.
+ Calling PluginManager.register later will discover all marked functions
+ if the PluginManager uses the same project_name.
+ """
+ def __init__(self, project_name):
+ self.project_name = project_name
+
+ def __call__(self, function=None, hookwrapper=False, optionalhook=False,
+ tryfirst=False, trylast=False):
+
+ """ if passed a function, directly sets attributes on the function
+ which will make it discoverable to register(). If passed no function,
+ returns a decorator which can be applied to a function later using
+ the attributes supplied.
+
+ If optionalhook is True a missing matching hook specification will not result
+ in an error (by default it is an error if no matching spec is found).
+
+ If tryfirst is True this hook implementation will run as early as possible
+ in the chain of N hook implementations for a specfication.
+
+ If trylast is True this hook implementation will run as late as possible
+ in the chain of N hook implementations.
+
+ If hookwrapper is True the hook implementations needs to execute exactly
+ one "yield". The code before the yield is run early before any non-hookwrapper
+ function is run. The code after the yield is run after all non-hookwrapper
+ function have run. The yield receives a ``_Result`` object representing
+ the exception or result outcome of the inner calls (including other hookwrapper
+ calls).
+
+ """
+ def setattr_hookimpl_opts(func):
+ setattr(func, self.project_name + "_impl",
+ dict(hookwrapper=hookwrapper, optionalhook=optionalhook,
+ tryfirst=tryfirst, trylast=trylast))
+ return func
+
+ if function is None:
+ return setattr_hookimpl_opts
+ else:
+ return setattr_hookimpl_opts(function)
+
+
+def normalize_hookimpl_opts(opts):
+ opts.setdefault("tryfirst", False)
+ opts.setdefault("trylast", False)
+ opts.setdefault("hookwrapper", False)
+ opts.setdefault("optionalhook", False)
+
+
+class _TagTracer(object):
+ def __init__(self):
+ self._tag2proc = {}
+ self.writer = None
+ self.indent = 0
+
+ def get(self, name):
+ return _TagTracerSub(self, (name,))
+
+ def format_message(self, tags, args):
+ if isinstance(args[-1], dict):
+ extra = args[-1]
+ args = args[:-1]
+ else:
+ extra = {}
+
+ content = " ".join(map(str, args))
+ indent = " " * self.indent
+
+ lines = [
+ "%s%s [%s]\n" % (indent, content, ":".join(tags))
+ ]
+
+ for name, value in extra.items():
+ lines.append("%s %s: %s\n" % (indent, name, value))
+ return lines
+
+ def processmessage(self, tags, args):
+ if self.writer is not None and args:
+ lines = self.format_message(tags, args)
+ self.writer(''.join(lines))
+ try:
+ self._tag2proc[tags](tags, args)
+ except KeyError:
+ pass
+
+ def setwriter(self, writer):
+ self.writer = writer
+
+ def setprocessor(self, tags, processor):
+ if isinstance(tags, str):
+ tags = tuple(tags.split(":"))
+ else:
+ assert isinstance(tags, tuple)
+ self._tag2proc[tags] = processor
+
+
+class _TagTracerSub(object):
+ def __init__(self, root, tags):
+ self.root = root
+ self.tags = tags
+
+ def __call__(self, *args):
+ self.root.processmessage(self.tags, args)
+
+ def setmyprocessor(self, processor):
+ self.root.setprocessor(self.tags, processor)
+
+ def get(self, name):
+ return self.__class__(self.root, self.tags + (name,))
+
+
+class _TracedHookExecution(object):
+ def __init__(self, pluginmanager, before, after):
+ self.pluginmanager = pluginmanager
+ self.before = before
+ self.after = after
+ self.oldcall = pluginmanager._inner_hookexec
+ assert not isinstance(self.oldcall, _TracedHookExecution)
+ self.pluginmanager._inner_hookexec = self
+
+ def __call__(self, hook, hook_impls, kwargs):
+ self.before(hook.name, hook_impls, kwargs)
+ outcome = _Result.from_call(lambda: self.oldcall(hook, hook_impls, kwargs))
+ self.after(outcome, hook.name, hook_impls, kwargs)
+ return outcome.get_result()
+
+ def undo(self):
+ self.pluginmanager._inner_hookexec = self.oldcall
+
+
+class PluginManager(object):
+ """ Core Pluginmanager class which manages registration
+ of plugin objects and 1:N hook calling.
+
+ You can register new hooks by calling ``add_hookspec(module_or_class)``.
+ You can register plugin objects (which contain hooks) by calling
+ ``register(plugin)``. The Pluginmanager is initialized with a
+ prefix that is searched for in the names of the dict of registered
+ plugin objects. An optional excludefunc allows to blacklist names which
+ are not considered as hooks despite a matching prefix.
+
+ For debugging purposes you can call ``enable_tracing()``
+ which will subsequently send debug information to the trace helper.
+ """
+
+ def __init__(self, project_name, implprefix=None):
+ """ if implprefix is given implementation functions
+ will be recognized if their name matches the implprefix. """
+ self.project_name = project_name
+ self._name2plugin = {}
+ self._plugin2hookcallers = {}
+ self._plugin_distinfo = []
+ self.trace = _TagTracer().get("pluginmanage")
+ self.hook = _HookRelay(self.trace.root.get("hook"))
+ self._implprefix = implprefix
+ self._inner_hookexec = lambda hook, methods, kwargs: \
+ hook.multicall(
+ methods, kwargs,
+ firstresult=hook.spec_opts.get('firstresult'),
+ )
+
+ def _hookexec(self, hook, methods, kwargs):
+ # called from all hookcaller instances.
+ # enable_tracing will set its own wrapping function at self._inner_hookexec
+ return self._inner_hookexec(hook, methods, kwargs)
+
+ def register(self, plugin, name=None):
+ """ Register a plugin and return its canonical name or None if the name
+ is blocked from registering. Raise a ValueError if the plugin is already
+ registered. """
+ plugin_name = name or self.get_canonical_name(plugin)
+
+ if plugin_name in self._name2plugin or plugin in self._plugin2hookcallers:
+ if self._name2plugin.get(plugin_name, -1) is None:
+ return # blocked plugin, return None to indicate no registration
+ raise ValueError("Plugin already registered: %s=%s\n%s" %
+ (plugin_name, plugin, self._name2plugin))
+
+ # XXX if an error happens we should make sure no state has been
+ # changed at point of return
+ self._name2plugin[plugin_name] = plugin
+
+ # register matching hook implementations of the plugin
+ self._plugin2hookcallers[plugin] = hookcallers = []
+ for name in dir(plugin):
+ hookimpl_opts = self.parse_hookimpl_opts(plugin, name)
+ if hookimpl_opts is not None:
+ normalize_hookimpl_opts(hookimpl_opts)
+ method = getattr(plugin, name)
+ hookimpl = HookImpl(plugin, plugin_name, method, hookimpl_opts)
+ hook = getattr(self.hook, name, None)
+ if hook is None:
+ hook = _HookCaller(name, self._hookexec)
+ setattr(self.hook, name, hook)
+ elif hook.has_spec():
+ self._verify_hook(hook, hookimpl)
+ hook._maybe_apply_history(hookimpl)
+ hook._add_hookimpl(hookimpl)
+ hookcallers.append(hook)
+ return plugin_name
+
+ def parse_hookimpl_opts(self, plugin, name):
+ method = getattr(plugin, name)
+ if not inspect.isroutine(method):
+ return
+ try:
+ res = getattr(method, self.project_name + "_impl", None)
+ except Exception:
+ res = {}
+ if res is not None and not isinstance(res, dict):
+ # false positive
+ res = None
+ elif res is None and self._implprefix and name.startswith(self._implprefix):
+ res = {}
+ return res
+
+ def unregister(self, plugin=None, name=None):
+ """ unregister a plugin object and all its contained hook implementations
+ from internal data structures. """
+ if name is None:
+ assert plugin is not None, "one of name or plugin needs to be specified"
+ name = self.get_name(plugin)
+
+ if plugin is None:
+ plugin = self.get_plugin(name)
+
+ # if self._name2plugin[name] == None registration was blocked: ignore
+ if self._name2plugin.get(name):
+ del self._name2plugin[name]
+
+ for hookcaller in self._plugin2hookcallers.pop(plugin, []):
+ hookcaller._remove_plugin(plugin)
+
+ return plugin
+
+ def set_blocked(self, name):
+ """ block registrations of the given name, unregister if already registered. """
+ self.unregister(name=name)
+ self._name2plugin[name] = None
+
+ def is_blocked(self, name):
+ """ return True if the name blogs registering plugins of that name. """
+ return name in self._name2plugin and self._name2plugin[name] is None
+
+ def add_hookspecs(self, module_or_class):
+ """ add new hook specifications defined in the given module_or_class.
+ Functions are recognized if they have been decorated accordingly. """
+ names = []
+ for name in dir(module_or_class):
+ spec_opts = self.parse_hookspec_opts(module_or_class, name)
+ if spec_opts is not None:
+ hc = getattr(self.hook, name, None)
+ if hc is None:
+ hc = _HookCaller(name, self._hookexec, module_or_class, spec_opts)
+ setattr(self.hook, name, hc)
+ else:
+ # plugins registered this hook without knowing the spec
+ hc.set_specification(module_or_class, spec_opts)
+ for hookfunction in (hc._wrappers + hc._nonwrappers):
+ self._verify_hook(hc, hookfunction)
+ names.append(name)
+
+ if not names:
+ raise ValueError("did not find any %r hooks in %r" %
+ (self.project_name, module_or_class))
+
+ def parse_hookspec_opts(self, module_or_class, name):
+ method = getattr(module_or_class, name)
+ return getattr(method, self.project_name + "_spec", None)
+
+ def get_plugins(self):
+ """ return the set of registered plugins. """
+ return set(self._plugin2hookcallers)
+
+ def is_registered(self, plugin):
+ """ Return True if the plugin is already registered. """
+ return plugin in self._plugin2hookcallers
+
+ def get_canonical_name(self, plugin):
+ """ Return canonical name for a plugin object. Note that a plugin
+ may be registered under a different name which was specified
+ by the caller of register(plugin, name). To obtain the name
+ of an registered plugin use ``get_name(plugin)`` instead."""
+ return getattr(plugin, "__name__", None) or str(id(plugin))
+
+ def get_plugin(self, name):
+ """ Return a plugin or None for the given name. """
+ return self._name2plugin.get(name)
+
+ def has_plugin(self, name):
+ """ Return True if a plugin with the given name is registered. """
+ return self.get_plugin(name) is not None
+
+ def get_name(self, plugin):
+ """ Return name for registered plugin or None if not registered. """
+ for name, val in self._name2plugin.items():
+ if plugin == val:
+ return name
+
+ def _verify_hook(self, hook, hookimpl):
+ if hook.is_historic() and hookimpl.hookwrapper:
+ raise PluginValidationError(
+ "Plugin %r\nhook %r\nhistoric incompatible to hookwrapper" %
+ (hookimpl.plugin_name, hook.name))
+
+ # positional arg checking
+ notinspec = set(hookimpl.argnames) - set(hook.argnames)
+ if notinspec:
+ raise PluginValidationError(
+ "Plugin %r for hook %r\nhookimpl definition: %s\n"
+ "Argument(s) %s are declared in the hookimpl but "
+ "can not be found in the hookspec" %
+ (hookimpl.plugin_name, hook.name,
+ _formatdef(hookimpl.function), notinspec)
+ )
+
+ def check_pending(self):
+ """ Verify that all hooks which have not been verified against
+ a hook specification are optional, otherwise raise PluginValidationError"""
+ for name in self.hook.__dict__:
+ if name[0] != "_":
+ hook = getattr(self.hook, name)
+ if not hook.has_spec():
+ for hookimpl in (hook._wrappers + hook._nonwrappers):
+ if not hookimpl.optionalhook:
+ raise PluginValidationError(
+ "unknown hook %r in plugin %r" %
+ (name, hookimpl.plugin))
+
+ def load_setuptools_entrypoints(self, entrypoint_name):
+ """ Load modules from querying the specified setuptools entrypoint name.
+ Return the number of loaded plugins. """
+ from pkg_resources import (iter_entry_points, DistributionNotFound,
+ VersionConflict)
+ for ep in iter_entry_points(entrypoint_name):
+ # is the plugin registered or blocked?
+ if self.get_plugin(ep.name) or self.is_blocked(ep.name):
+ continue
+ try:
+ plugin = ep.load()
+ except DistributionNotFound:
+ continue
+ except VersionConflict as e:
+ raise PluginValidationError(
+ "Plugin %r could not be loaded: %s!" % (ep.name, e))
+ self.register(plugin, name=ep.name)
+ self._plugin_distinfo.append((plugin, ep.dist))
+ return len(self._plugin_distinfo)
+
+ def list_plugin_distinfo(self):
+ """ return list of distinfo/plugin tuples for all setuptools registered
+ plugins. """
+ return list(self._plugin_distinfo)
+
+ def list_name_plugin(self):
+ """ return list of name/plugin pairs. """
+ return list(self._name2plugin.items())
+
+ def get_hookcallers(self, plugin):
+ """ get all hook callers for the specified plugin. """
+ return self._plugin2hookcallers.get(plugin)
+
+ def add_hookcall_monitoring(self, before, after):
+ """ add before/after tracing functions for all hooks
+ and return an undo function which, when called,
+ will remove the added tracers.
+
+ ``before(hook_name, hook_impls, kwargs)`` will be called ahead
+ of all hook calls and receive a hookcaller instance, a list
+ of HookImpl instances and the keyword arguments for the hook call.
+
+ ``after(outcome, hook_name, hook_impls, kwargs)`` receives the
+ same arguments as ``before`` but also a :py:class:`_Result`` object
+ which represents the result of the overall hook call.
+ """
+ return _TracedHookExecution(self, before, after).undo
+
+ def enable_tracing(self):
+ """ enable tracing of hook calls and return an undo function. """
+ hooktrace = self.hook._trace
+
+ def before(hook_name, methods, kwargs):
+ hooktrace.root.indent += 1
+ hooktrace(hook_name, kwargs)
+
+ def after(outcome, hook_name, methods, kwargs):
+ if outcome.excinfo is None:
+ hooktrace("finish", hook_name, "-->", outcome.get_result())
+ hooktrace.root.indent -= 1
+
+ return self.add_hookcall_monitoring(before, after)
+
+ def subset_hook_caller(self, name, remove_plugins):
+ """ Return a new _HookCaller instance for the named method
+ which manages calls to all registered plugins except the
+ ones from remove_plugins. """
+ orig = getattr(self.hook, name)
+ plugins_to_remove = [plug for plug in remove_plugins if hasattr(plug, name)]
+ if plugins_to_remove:
+ hc = _HookCaller(orig.name, orig._hookexec, orig._specmodule_or_class,
+ orig.spec_opts)
+ for hookimpl in (orig._wrappers + orig._nonwrappers):
+ plugin = hookimpl.plugin
+ if plugin not in plugins_to_remove:
+ hc._add_hookimpl(hookimpl)
+ # we also keep track of this hook caller so it
+ # gets properly removed on plugin unregistration
+ self._plugin2hookcallers.setdefault(plugin, []).append(hc)
+ return hc
+ return orig
+
+
+def varnames(func):
+ """Return tuple of positional and keywrord argument names for a function,
+ method, class or callable.
+
+ In case of a class, its ``__init__`` method is considered.
+ For methods the ``self`` parameter is not included.
+ """
+ cache = getattr(func, "__dict__", {})
+ try:
+ return cache["_varnames"]
+ except KeyError:
+ pass
+
+ if inspect.isclass(func):
+ try:
+ func = func.__init__
+ except AttributeError:
+ return (), ()
+ elif not inspect.isroutine(func): # callable object?
+ try:
+ func = getattr(func, '__call__', func)
+ except Exception:
+ return ()
+
+ try: # func MUST be a function or method here or we won't parse any args
+ spec = _getargspec(func)
+ except TypeError:
+ return (), ()
+
+ args, defaults = tuple(spec.args), spec.defaults
+ if defaults:
+ index = -len(defaults)
+ args, defaults = args[:index], tuple(args[index:])
+ else:
+ defaults = ()
+
+ # strip any implicit instance arg
+ if args:
+ if inspect.ismethod(func) or (
+ '.' in getattr(func, '__qualname__', ()) and args[0] == 'self'
+ ):
+ args = args[1:]
+
+ assert "self" not in args # best naming practises check?
+ try:
+ cache["_varnames"] = args, defaults
+ except TypeError:
+ pass
+ return args, defaults
+
+
+class _HookRelay(object):
+ """ hook holder object for performing 1:N hook calls where N is the number
+ of registered plugins.
+
+ """
+
+ def __init__(self, trace):
+ self._trace = trace
+
+
+class _HookCaller(object):
+ def __init__(self, name, hook_execute, specmodule_or_class=None,
+ spec_opts=None):
+ self.name = name
+ self._wrappers = []
+ self._nonwrappers = []
+ self._hookexec = hook_execute
+ self._specmodule_or_class = None
+ self.argnames = None
+ self.kwargnames = None
+ self.multicall = _multicall
+ self.spec_opts = spec_opts or {}
+ if specmodule_or_class is not None:
+ self.set_specification(specmodule_or_class, spec_opts)
+
+ def has_spec(self):
+ return self._specmodule_or_class is not None
+
+ def set_specification(self, specmodule_or_class, spec_opts):
+ assert not self.has_spec()
+ self._specmodule_or_class = specmodule_or_class
+ specfunc = getattr(specmodule_or_class, self.name)
+ # get spec arg signature
+ argnames, self.kwargnames = varnames(specfunc)
+ self.argnames = ["__multicall__"] + list(argnames)
+ self.spec_opts.update(spec_opts)
+ if spec_opts.get("historic"):
+ self._call_history = []
+
+ def is_historic(self):
+ return hasattr(self, "_call_history")
+
+ def _remove_plugin(self, plugin):
+ def remove(wrappers):
+ for i, method in enumerate(wrappers):
+ if method.plugin == plugin:
+ del wrappers[i]
+ return True
+ if remove(self._wrappers) is None:
+ if remove(self._nonwrappers) is None:
+ raise ValueError("plugin %r not found" % (plugin,))
+
+ def _add_hookimpl(self, hookimpl):
+ """A an implementation to the callback chain.
+ """
+ if hookimpl.hookwrapper:
+ methods = self._wrappers
+ else:
+ methods = self._nonwrappers
+
+ if hookimpl.trylast:
+ methods.insert(0, hookimpl)
+ elif hookimpl.tryfirst:
+ methods.append(hookimpl)
+ else:
+ # find last non-tryfirst method
+ i = len(methods) - 1
+ while i >= 0 and methods[i].tryfirst:
+ i -= 1
+ methods.insert(i + 1, hookimpl)
+
+ if '__multicall__' in hookimpl.argnames:
+ warnings.warn(
+ "Support for __multicall__ is now deprecated and will be"
+ "removed in an upcoming release.",
+ DeprecationWarning
+ )
+ self.multicall = _legacymulticall
+
+ def __repr__(self):
+ return "<_HookCaller %r>" % (self.name,)
+
+ def __call__(self, *args, **kwargs):
+ if args:
+ raise TypeError("hook calling supports only keyword arguments")
+ assert not self.is_historic()
+ if self.argnames:
+ notincall = set(self.argnames) - set(['__multicall__']) - set(
+ kwargs.keys())
+ if notincall:
+ warnings.warn(
+ "Argument(s) {} which are declared in the hookspec "
+ "can not be found in this hook call"
+ .format(tuple(notincall)),
+ stacklevel=2,
+ )
+ return self._hookexec(self, self._nonwrappers + self._wrappers, kwargs)
+
+ def call_historic(self, proc=None, kwargs=None):
+ """ call the hook with given ``kwargs`` for all registered plugins and
+ for all plugins which will be registered afterwards.
+
+ If ``proc`` is not None it will be called for for each non-None result
+ obtained from a hook implementation.
+ """
+ self._call_history.append((kwargs or {}, proc))
+ # historizing hooks don't return results
+ res = self._hookexec(self, self._nonwrappers + self._wrappers, kwargs)
+ for x in res or []:
+ proc(x)
+
+ def call_extra(self, methods, kwargs):
+ """ Call the hook with some additional temporarily participating
+ methods using the specified kwargs as call parameters. """
+ old = list(self._nonwrappers), list(self._wrappers)
+ for method in methods:
+ opts = dict(hookwrapper=False, trylast=False, tryfirst=False)
+ hookimpl = HookImpl(None, "<temp>", method, opts)
+ self._add_hookimpl(hookimpl)
+ try:
+ return self(**kwargs)
+ finally:
+ self._nonwrappers, self._wrappers = old
+
+ def _maybe_apply_history(self, method):
+ """Apply call history to a new hookimpl if it is marked as historic.
+ """
+ if self.is_historic():
+ for kwargs, proc in self._call_history:
+ res = self._hookexec(self, [method], kwargs)
+ if res and proc is not None:
+ proc(res[0])
+
+
+class HookImpl(object):
+ def __init__(self, plugin, plugin_name, function, hook_impl_opts):
+ self.function = function
+ self.argnames, self.kwargnames = varnames(self.function)
+ self.plugin = plugin
+ self.opts = hook_impl_opts
+ self.plugin_name = plugin_name
+ self.__dict__.update(hook_impl_opts)
+
+
+if hasattr(inspect, 'getfullargspec'):
+ def _getargspec(func):
+ return inspect.getfullargspec(func)
+else:
+ def _getargspec(func):
+ return inspect.getargspec(func)
+
+
+if hasattr(inspect, 'signature'):
+ def _formatdef(func):
+ return "%s%s" % (
+ func.__name__,
+ str(inspect.signature(func))
+ )
+else:
+ def _formatdef(func):
+ return "%s%s" % (
+ func.__name__,
+ inspect.formatargspec(*inspect.getargspec(func))
+ )
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pluggy/pluggy/callers.py b/tests/wpt/web-platform-tests/tools/third_party/pluggy/pluggy/callers.py
new file mode 100644
index 00000000000..3ff67becffb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pluggy/pluggy/callers.py
@@ -0,0 +1,201 @@
+'''
+Call loop machinery
+'''
+import sys
+import warnings
+
+_py3 = sys.version_info > (3, 0)
+
+
+if not _py3:
+ exec("""
+def _reraise(cls, val, tb):
+ raise cls, val, tb
+""")
+
+
+def _raise_wrapfail(wrap_controller, msg):
+ co = wrap_controller.gi_code
+ raise RuntimeError("wrap_controller at %r %s:%d %s" %
+ (co.co_name, co.co_filename, co.co_firstlineno, msg))
+
+
+class HookCallError(Exception):
+ """ Hook was called wrongly. """
+
+
+class _Result(object):
+ def __init__(self, result, excinfo):
+ self._result = result
+ self._excinfo = excinfo
+
+ @property
+ def excinfo(self):
+ return self._excinfo
+
+ @property
+ def result(self):
+ """Get the result(s) for this hook call (DEPRECATED in favor of ``get_result()``)."""
+ msg = 'Use get_result() which forces correct exception handling'
+ warnings.warn(DeprecationWarning(msg), stacklevel=2)
+ return self._result
+
+ @classmethod
+ def from_call(cls, func):
+ __tracebackhide__ = True
+ result = excinfo = None
+ try:
+ result = func()
+ except BaseException:
+ excinfo = sys.exc_info()
+
+ return cls(result, excinfo)
+
+ def force_result(self, result):
+ """Force the result(s) to ``result``.
+
+ If the hook was marked as a ``firstresult`` a single value should
+ be set otherwise set a (modified) list of results. Any exceptions
+ found during invocation will be deleted.
+ """
+ self._result = result
+ self._excinfo = None
+
+ def get_result(self):
+ """Get the result(s) for this hook call.
+
+ If the hook was marked as a ``firstresult`` only a single value
+ will be returned otherwise a list of results.
+ """
+ __tracebackhide__ = True
+ if self._excinfo is None:
+ return self._result
+ else:
+ ex = self._excinfo
+ if _py3:
+ raise ex[1].with_traceback(ex[2])
+ _reraise(*ex) # noqa
+
+
+def _wrapped_call(wrap_controller, func):
+ """ Wrap calling to a function with a generator which needs to yield
+ exactly once. The yield point will trigger calling the wrapped function
+ and return its ``_Result`` to the yield point. The generator then needs
+ to finish (raise StopIteration) in order for the wrapped call to complete.
+ """
+ try:
+ next(wrap_controller) # first yield
+ except StopIteration:
+ _raise_wrapfail(wrap_controller, "did not yield")
+ call_outcome = _Result.from_call(func)
+ try:
+ wrap_controller.send(call_outcome)
+ _raise_wrapfail(wrap_controller, "has second yield")
+ except StopIteration:
+ pass
+ return call_outcome.get_result()
+
+
+class _LegacyMultiCall(object):
+ """ execute a call into multiple python functions/methods. """
+
+ # XXX note that the __multicall__ argument is supported only
+ # for pytest compatibility reasons. It was never officially
+ # supported there and is explicitely deprecated since 2.8
+ # so we can remove it soon, allowing to avoid the below recursion
+ # in execute() and simplify/speed up the execute loop.
+
+ def __init__(self, hook_impls, kwargs, firstresult=False):
+ self.hook_impls = hook_impls
+ self.caller_kwargs = kwargs # come from _HookCaller.__call__()
+ self.caller_kwargs["__multicall__"] = self
+ self.firstresult = firstresult
+
+ def execute(self):
+ caller_kwargs = self.caller_kwargs
+ self.results = results = []
+ firstresult = self.firstresult
+
+ while self.hook_impls:
+ hook_impl = self.hook_impls.pop()
+ try:
+ args = [caller_kwargs[argname] for argname in hook_impl.argnames]
+ except KeyError:
+ for argname in hook_impl.argnames:
+ if argname not in caller_kwargs:
+ raise HookCallError(
+ "hook call must provide argument %r" % (argname,))
+ if hook_impl.hookwrapper:
+ return _wrapped_call(hook_impl.function(*args), self.execute)
+ res = hook_impl.function(*args)
+ if res is not None:
+ if firstresult:
+ return res
+ results.append(res)
+
+ if not firstresult:
+ return results
+
+ def __repr__(self):
+ status = "%d meths" % (len(self.hook_impls),)
+ if hasattr(self, "results"):
+ status = ("%d results, " % len(self.results)) + status
+ return "<_MultiCall %s, kwargs=%r>" % (status, self.caller_kwargs)
+
+
+def _legacymulticall(hook_impls, caller_kwargs, firstresult=False):
+ return _LegacyMultiCall(
+ hook_impls, caller_kwargs, firstresult=firstresult).execute()
+
+
+def _multicall(hook_impls, caller_kwargs, firstresult=False):
+ """Execute a call into multiple python functions/methods and return the
+ result(s).
+
+ ``caller_kwargs`` comes from _HookCaller.__call__().
+ """
+ __tracebackhide__ = True
+ results = []
+ excinfo = None
+ try: # run impl and wrapper setup functions in a loop
+ teardowns = []
+ try:
+ for hook_impl in reversed(hook_impls):
+ try:
+ args = [caller_kwargs[argname] for argname in hook_impl.argnames]
+ except KeyError:
+ for argname in hook_impl.argnames:
+ if argname not in caller_kwargs:
+ raise HookCallError(
+ "hook call must provide argument %r" % (argname,))
+
+ if hook_impl.hookwrapper:
+ try:
+ gen = hook_impl.function(*args)
+ next(gen) # first yield
+ teardowns.append(gen)
+ except StopIteration:
+ _raise_wrapfail(gen, "did not yield")
+ else:
+ res = hook_impl.function(*args)
+ if res is not None:
+ results.append(res)
+ if firstresult: # halt further impl calls
+ break
+ except BaseException:
+ excinfo = sys.exc_info()
+ finally:
+ if firstresult: # first result hooks return a single value
+ outcome = _Result(results[0] if results else None, excinfo)
+ else:
+ outcome = _Result(results, excinfo)
+
+ # run all wrapper post-yield blocks
+ for gen in reversed(teardowns):
+ try:
+ gen.send(outcome)
+ _raise_wrapfail(gen, "has second yield")
+ except StopIteration:
+ pass
+
+ return outcome.get_result()
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pluggy/setup.cfg b/tests/wpt/web-platform-tests/tools/third_party/pluggy/setup.cfg
new file mode 100644
index 00000000000..7e729cb4f24
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pluggy/setup.cfg
@@ -0,0 +1,8 @@
+[bdist_wheel]
+universal=1
+
+[metadata]
+license_file=LICENSE
+
+[devpi:upload]
+formats=sdist.tgz,bdist_wheel
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pluggy/setup.py b/tests/wpt/web-platform-tests/tools/third_party/pluggy/setup.py
new file mode 100644
index 00000000000..b7c0f697120
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pluggy/setup.py
@@ -0,0 +1,51 @@
+import os
+from setuptools import setup
+
+classifiers = [
+ 'Development Status :: 4 - Beta',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: MIT License',
+ 'Operating System :: POSIX',
+ 'Operating System :: Microsoft :: Windows',
+ 'Operating System :: MacOS :: MacOS X',
+ 'Topic :: Software Development :: Testing',
+ 'Topic :: Software Development :: Libraries',
+ 'Topic :: Utilities',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy'] + [
+ ('Programming Language :: Python :: %s' % x) for x in
+ '2 2.7 3 3.4 3.5 3.6'.split()]
+
+with open('README.rst') as fd:
+ long_description = fd.read()
+
+
+def get_version():
+ p = os.path.join(os.path.dirname(
+ os.path.abspath(__file__)), "pluggy/__init__.py")
+ with open(p) as f:
+ for line in f.readlines():
+ if "__version__" in line:
+ return line.strip().split("=")[-1].strip(" '")
+ raise ValueError("could not read version")
+
+
+def main():
+ setup(
+ name='pluggy',
+ description='plugin and hook calling mechanisms for python',
+ long_description=long_description,
+ version=get_version(),
+ license='MIT license',
+ platforms=['unix', 'linux', 'osx', 'win32'],
+ author='Holger Krekel',
+ author_email='holger@merlinux.eu',
+ url='https://github.com/pytest-dev/pluggy',
+ python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
+ classifiers=classifiers,
+ packages=['pluggy'],
+ )
+
+
+if __name__ == '__main__':
+ main()
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/benchmark.py b/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/benchmark.py
new file mode 100644
index 00000000000..5a913e9d418
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/benchmark.py
@@ -0,0 +1,59 @@
+"""
+Benchmarking and performance tests.
+"""
+import pytest
+from pluggy import (_multicall, _legacymulticall, HookImpl, HookspecMarker,
+ HookimplMarker)
+
+hookspec = HookspecMarker("example")
+hookimpl = HookimplMarker("example")
+
+
+def MC(methods, kwargs, callertype, firstresult=False):
+ hookfuncs = []
+ for method in methods:
+ f = HookImpl(None, "<temp>", method, method.example_impl)
+ hookfuncs.append(f)
+ return callertype(hookfuncs, kwargs, {"firstresult": firstresult})
+
+
+@hookimpl
+def hook(arg1, arg2, arg3):
+ return arg1, arg2, arg3
+
+
+@hookimpl(hookwrapper=True)
+def wrapper(arg1, arg2, arg3):
+ yield
+
+
+@pytest.fixture(
+ params=[10, 100],
+ ids="hooks={}".format,
+)
+def hooks(request):
+ return [hook for i in range(request.param)]
+
+
+@pytest.fixture(
+ params=[10, 100],
+ ids="wrappers={}".format,
+)
+def wrappers(request):
+ return [wrapper for i in range(request.param)]
+
+
+@pytest.fixture(
+ params=[_multicall, _legacymulticall],
+ ids=lambda item: item.__name__
+)
+def callertype(request):
+ return request.param
+
+
+def inner_exec(methods, callertype):
+ return MC(methods, {'arg1': 1, 'arg2': 2, 'arg3': 3}, callertype)
+
+
+def test_hook_and_wrappers_speed(benchmark, hooks, wrappers, callertype):
+ benchmark(inner_exec, hooks + wrappers, callertype)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/conftest.py b/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/conftest.py
new file mode 100644
index 00000000000..3d61a349c88
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/conftest.py
@@ -0,0 +1,30 @@
+import pytest
+
+
+@pytest.fixture(
+ params=[
+ lambda spec: spec,
+ lambda spec: spec()
+ ],
+ ids=[
+ "spec-is-class",
+ "spec-is-instance"
+ ],
+)
+def he_pm(request, pm):
+ from pluggy import HookspecMarker
+ hookspec = HookspecMarker("example")
+
+ class Hooks(object):
+ @hookspec
+ def he_method1(self, arg):
+ return arg + 1
+
+ pm.add_hookspecs(request.param(Hooks))
+ return pm
+
+
+@pytest.fixture
+def pm():
+ from pluggy import PluginManager
+ return PluginManager("example")
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_details.py b/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_details.py
new file mode 100644
index 00000000000..2fad198d958
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_details.py
@@ -0,0 +1,103 @@
+import warnings
+
+import pytest
+
+from pluggy import PluginManager, HookimplMarker, HookspecMarker, _Result
+
+hookspec = HookspecMarker("example")
+hookimpl = HookimplMarker("example")
+
+
+def test_parse_hookimpl_override():
+ class MyPluginManager(PluginManager):
+ def parse_hookimpl_opts(self, module_or_class, name):
+ opts = PluginManager.parse_hookimpl_opts(
+ self, module_or_class, name)
+ if opts is None:
+ if name.startswith("x1"):
+ opts = {}
+ return opts
+
+ class Plugin(object):
+ def x1meth(self):
+ pass
+
+ @hookimpl(hookwrapper=True, tryfirst=True)
+ def x1meth2(self):
+ pass
+
+ class Spec(object):
+ @hookspec
+ def x1meth(self):
+ pass
+
+ @hookspec
+ def x1meth2(self):
+ pass
+
+ pm = MyPluginManager(hookspec.project_name)
+ pm.register(Plugin())
+ pm.add_hookspecs(Spec)
+ assert not pm.hook.x1meth._nonwrappers[0].hookwrapper
+ assert not pm.hook.x1meth._nonwrappers[0].tryfirst
+ assert not pm.hook.x1meth._nonwrappers[0].trylast
+ assert not pm.hook.x1meth._nonwrappers[0].optionalhook
+
+ assert pm.hook.x1meth2._wrappers[0].tryfirst
+ assert pm.hook.x1meth2._wrappers[0].hookwrapper
+
+
+def test_plugin_getattr_raises_errors():
+ """Pluggy must be able to handle plugins which raise weird exceptions
+ when getattr() gets called (#11).
+ """
+ class DontTouchMe(object):
+ def __getattr__(self, x):
+ raise Exception('cant touch me')
+
+ class Module(object):
+ pass
+
+ module = Module()
+ module.x = DontTouchMe()
+
+ pm = PluginManager(hookspec.project_name)
+ # register() would raise an error
+ pm.register(module, 'donttouch')
+ assert pm.get_plugin('donttouch') is module
+
+
+def test_warning_on_call_vs_hookspec_arg_mismatch():
+ """Verify that is a hook is called with less arguments then defined in the
+ spec that a warning is emitted.
+ """
+ class Spec:
+ @hookspec
+ def myhook(self, arg1, arg2):
+ pass
+
+ class Plugin:
+ @hookimpl
+ def myhook(self, arg1):
+ pass
+
+ pm = PluginManager(hookspec.project_name)
+ pm.register(Plugin())
+ pm.add_hookspecs(Spec())
+
+ with warnings.catch_warnings(record=True) as warns:
+ warnings.simplefilter('always')
+
+ # calling should trigger a warning
+ pm.hook.myhook(arg1=1)
+
+ assert len(warns) == 1
+ warning = warns[-1]
+ assert issubclass(warning.category, Warning)
+ assert "Argument(s) ('arg2',)" in str(warning.message)
+
+
+def test_result_deprecated():
+ r = _Result(10, None)
+ with pytest.deprecated_call():
+ assert r.result == 10
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_helpers.py b/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_helpers.py
new file mode 100644
index 00000000000..b1780968446
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_helpers.py
@@ -0,0 +1,68 @@
+from pluggy import _formatdef, varnames
+
+
+def test_varnames():
+ def f(x):
+ i = 3 # noqa
+
+ class A(object):
+ def f(self, y):
+ pass
+
+ class B(object):
+ def __call__(self, z):
+ pass
+
+ assert varnames(f) == (("x",), ())
+ assert varnames(A().f) == (('y',), ())
+ assert varnames(B()) == (('z',), ())
+
+
+def test_varnames_default():
+ def f(x, y=3):
+ pass
+
+ assert varnames(f) == (("x",), ("y",))
+
+
+def test_varnames_class():
+ class C(object):
+ def __init__(self, x):
+ pass
+
+ class D(object):
+ pass
+
+ class E(object):
+ def __init__(self, x):
+ pass
+
+ class F(object):
+ pass
+
+ assert varnames(C) == (("x",), ())
+ assert varnames(D) == ((), ())
+ assert varnames(E) == (("x",), ())
+ assert varnames(F) == ((), ())
+
+
+def test_formatdef():
+ def function1():
+ pass
+
+ assert _formatdef(function1) == 'function1()'
+
+ def function2(arg1):
+ pass
+
+ assert _formatdef(function2) == "function2(arg1)"
+
+ def function3(arg1, arg2="qwe"):
+ pass
+
+ assert _formatdef(function3) == "function3(arg1, arg2='qwe')"
+
+ def function4(arg1, *args, **kwargs):
+ pass
+
+ assert _formatdef(function4) == "function4(arg1, *args, **kwargs)"
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_hookrelay.py b/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_hookrelay.py
new file mode 100644
index 00000000000..5e7821bed8f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_hookrelay.py
@@ -0,0 +1,210 @@
+import pytest
+from pluggy import PluginValidationError, HookimplMarker, HookspecMarker
+
+
+hookspec = HookspecMarker("example")
+hookimpl = HookimplMarker("example")
+
+
+def test_happypath(pm):
+ class Api(object):
+ @hookspec
+ def hello(self, arg):
+ "api hook 1"
+
+ pm.add_hookspecs(Api)
+ hook = pm.hook
+ assert hasattr(hook, 'hello')
+ assert repr(hook.hello).find("hello") != -1
+
+ class Plugin(object):
+ @hookimpl
+ def hello(self, arg):
+ return arg + 1
+
+ plugin = Plugin()
+ pm.register(plugin)
+ out = hook.hello(arg=3)
+ assert out == [4]
+ assert not hasattr(hook, 'world')
+ pm.unregister(plugin)
+ assert hook.hello(arg=3) == []
+
+
+def test_argmismatch(pm):
+ class Api(object):
+ @hookspec
+ def hello(self, arg):
+ "api hook 1"
+
+ pm.add_hookspecs(Api)
+
+ class Plugin(object):
+ @hookimpl
+ def hello(self, argwrong):
+ pass
+
+ with pytest.raises(PluginValidationError) as exc:
+ pm.register(Plugin())
+
+ assert "argwrong" in str(exc.value)
+
+
+def test_only_kwargs(pm):
+ class Api(object):
+ @hookspec
+ def hello(self, arg):
+ "api hook 1"
+
+ pm.add_hookspecs(Api)
+ with pytest.raises(TypeError) as exc:
+ pm.hook.hello(3)
+
+ comprehensible = "hook calling supports only keyword arguments"
+ assert comprehensible in str(exc.value)
+
+
+def test_call_order(pm):
+ class Api(object):
+ @hookspec
+ def hello(self, arg):
+ "api hook 1"
+
+ pm.add_hookspecs(Api)
+
+ class Plugin1(object):
+ @hookimpl
+ def hello(self, arg):
+ return 1
+
+ class Plugin2(object):
+ @hookimpl
+ def hello(self, arg):
+ return 2
+
+ class Plugin3(object):
+ @hookimpl
+ def hello(self, arg):
+ return 3
+
+ class Plugin4(object):
+ @hookimpl(hookwrapper=True)
+ def hello(self, arg):
+ assert arg == 0
+ outcome = yield
+ assert outcome.get_result() == [3, 2, 1]
+
+ pm.register(Plugin1())
+ pm.register(Plugin2())
+ pm.register(Plugin3())
+ pm.register(Plugin4()) # hookwrapper should get same list result
+ res = pm.hook.hello(arg=0)
+ assert res == [3, 2, 1]
+
+
+def test_firstresult_definition(pm):
+ class Api(object):
+ @hookspec(firstresult=True)
+ def hello(self, arg):
+ "api hook 1"
+
+ pm.add_hookspecs(Api)
+
+ class Plugin1(object):
+ @hookimpl
+ def hello(self, arg):
+ return arg + 1
+
+ class Plugin2(object):
+ @hookimpl
+ def hello(self, arg):
+ return arg - 1
+
+ class Plugin3(object):
+ @hookimpl
+ def hello(self, arg):
+ return None
+
+ class Plugin4(object):
+ @hookimpl(hookwrapper=True)
+ def hello(self, arg):
+ assert arg == 3
+ outcome = yield
+ assert outcome.get_result() == 2
+
+ pm.register(Plugin1()) # discarded - not the last registered plugin
+ pm.register(Plugin2()) # used as result
+ pm.register(Plugin3()) # None result is ignored
+ pm.register(Plugin4()) # hookwrapper should get same non-list result
+ res = pm.hook.hello(arg=3)
+ assert res == 2
+
+
+def test_firstresult_force_result(pm):
+ """Verify forcing a result in a wrapper.
+ """
+ class Api(object):
+ @hookspec(firstresult=True)
+ def hello(self, arg):
+ "api hook 1"
+
+ pm.add_hookspecs(Api)
+
+ class Plugin1(object):
+ @hookimpl
+ def hello(self, arg):
+ return arg + 1
+
+ class Plugin2(object):
+ @hookimpl(hookwrapper=True)
+ def hello(self, arg):
+ assert arg == 3
+ outcome = yield
+ assert outcome.get_result() == 4
+ outcome.force_result(0)
+
+ class Plugin3(object):
+ @hookimpl
+ def hello(self, arg):
+ return None
+
+ pm.register(Plugin1())
+ pm.register(Plugin2()) # wrapper
+ pm.register(Plugin3()) # ignored since returns None
+ res = pm.hook.hello(arg=3)
+ assert res == 0 # this result is forced and not a list
+
+
+def test_firstresult_returns_none(pm):
+ """If None results are returned by underlying implementations ensure
+ the multi-call loop returns a None value.
+ """
+ class Api(object):
+ @hookspec(firstresult=True)
+ def hello(self, arg):
+ "api hook 1"
+
+ pm.add_hookspecs(Api)
+
+ class Plugin1(object):
+ @hookimpl
+ def hello(self, arg):
+ return None
+
+ pm.register(Plugin1())
+ res = pm.hook.hello(arg=3)
+ assert res is None
+
+
+def test_firstresult_no_plugin(pm):
+ """If no implementations/plugins have been registered for a firstresult
+ hook the multi-call loop should return a None value.
+ """
+ class Api(object):
+ @hookspec(firstresult=True)
+ def hello(self, arg):
+ "api hook 1"
+
+ pm.add_hookspecs(Api)
+ res = pm.hook.hello(arg=3)
+ assert res is None
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_method_ordering.py b/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_method_ordering.py
new file mode 100644
index 00000000000..9584a0ae5a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_method_ordering.py
@@ -0,0 +1,322 @@
+import pytest
+
+
+import sys
+import types
+
+from pluggy import PluginManager, HookImpl, HookimplMarker, HookspecMarker
+
+hookspec = HookspecMarker("example")
+hookimpl = HookimplMarker("example")
+
+
+@pytest.fixture
+def hc(pm):
+ class Hooks(object):
+ @hookspec
+ def he_method1(self, arg):
+ pass
+ pm.add_hookspecs(Hooks)
+ return pm.hook.he_method1
+
+
+@pytest.fixture
+def addmeth(hc):
+ def addmeth(tryfirst=False, trylast=False, hookwrapper=False):
+ def wrap(func):
+ hookimpl(tryfirst=tryfirst, trylast=trylast,
+ hookwrapper=hookwrapper)(func)
+ hc._add_hookimpl(HookImpl(None, "<temp>", func, func.example_impl))
+ return func
+ return wrap
+ return addmeth
+
+
+def funcs(hookmethods):
+ return [hookmethod.function for hookmethod in hookmethods]
+
+
+def test_adding_nonwrappers(hc, addmeth):
+ @addmeth()
+ def he_method1():
+ pass
+
+ @addmeth()
+ def he_method2():
+ pass
+
+ @addmeth()
+ def he_method3():
+ pass
+ assert funcs(hc._nonwrappers) == [he_method1, he_method2, he_method3]
+
+
+def test_adding_nonwrappers_trylast(hc, addmeth):
+ @addmeth()
+ def he_method1_middle():
+ pass
+
+ @addmeth(trylast=True)
+ def he_method1():
+ pass
+
+ @addmeth()
+ def he_method1_b():
+ pass
+ assert funcs(hc._nonwrappers) == [he_method1, he_method1_middle, he_method1_b]
+
+
+def test_adding_nonwrappers_trylast3(hc, addmeth):
+ @addmeth()
+ def he_method1_a():
+ pass
+
+ @addmeth(trylast=True)
+ def he_method1_b():
+ pass
+
+ @addmeth()
+ def he_method1_c():
+ pass
+
+ @addmeth(trylast=True)
+ def he_method1_d():
+ pass
+ assert funcs(hc._nonwrappers) == \
+ [he_method1_d, he_method1_b, he_method1_a, he_method1_c]
+
+
+def test_adding_nonwrappers_trylast2(hc, addmeth):
+ @addmeth()
+ def he_method1_middle():
+ pass
+
+ @addmeth()
+ def he_method1_b():
+ pass
+
+ @addmeth(trylast=True)
+ def he_method1():
+ pass
+ assert funcs(hc._nonwrappers) == \
+ [he_method1, he_method1_middle, he_method1_b]
+
+
+def test_adding_nonwrappers_tryfirst(hc, addmeth):
+ @addmeth(tryfirst=True)
+ def he_method1():
+ pass
+
+ @addmeth()
+ def he_method1_middle():
+ pass
+
+ @addmeth()
+ def he_method1_b():
+ pass
+ assert funcs(hc._nonwrappers) == [
+ he_method1_middle, he_method1_b, he_method1]
+
+
+def test_adding_wrappers_ordering(hc, addmeth):
+ @addmeth(hookwrapper=True)
+ def he_method1():
+ pass
+
+ @addmeth()
+ def he_method1_middle():
+ pass
+
+ @addmeth(hookwrapper=True)
+ def he_method3():
+ pass
+
+ assert funcs(hc._nonwrappers) == [he_method1_middle]
+ assert funcs(hc._wrappers) == [he_method1, he_method3]
+
+
+def test_adding_wrappers_ordering_tryfirst(hc, addmeth):
+ @addmeth(hookwrapper=True, tryfirst=True)
+ def he_method1():
+ pass
+
+ @addmeth(hookwrapper=True)
+ def he_method2():
+ pass
+
+ assert hc._nonwrappers == []
+ assert funcs(hc._wrappers) == [he_method2, he_method1]
+
+
+def test_hookspec(pm):
+ class HookSpec(object):
+ @hookspec()
+ def he_myhook1(arg1):
+ pass
+
+ @hookspec(firstresult=True)
+ def he_myhook2(arg1):
+ pass
+
+ @hookspec(firstresult=False)
+ def he_myhook3(arg1):
+ pass
+
+ pm.add_hookspecs(HookSpec)
+ assert not pm.hook.he_myhook1.spec_opts["firstresult"]
+ assert pm.hook.he_myhook2.spec_opts["firstresult"]
+ assert not pm.hook.he_myhook3.spec_opts["firstresult"]
+
+
+@pytest.mark.parametrize('name', ["hookwrapper", "optionalhook", "tryfirst", "trylast"])
+@pytest.mark.parametrize('val', [True, False])
+def test_hookimpl(name, val):
+ @hookimpl(**{name: val})
+ def he_myhook1(arg1):
+ pass
+ if val:
+ assert he_myhook1.example_impl.get(name)
+ else:
+ assert not hasattr(he_myhook1, name)
+
+
+def test_load_setuptools_instantiation(monkeypatch, pm):
+ pkg_resources = pytest.importorskip("pkg_resources")
+
+ def my_iter(name):
+ assert name == "hello"
+
+ class EntryPoint(object):
+ name = "myname"
+ dist = None
+
+ def load(self):
+ class PseudoPlugin(object):
+ x = 42
+ return PseudoPlugin()
+
+ return iter([EntryPoint()])
+
+ monkeypatch.setattr(pkg_resources, 'iter_entry_points', my_iter)
+ num = pm.load_setuptools_entrypoints("hello")
+ assert num == 1
+ plugin = pm.get_plugin("myname")
+ assert plugin.x == 42
+ assert pm.list_plugin_distinfo() == [(plugin, None)]
+
+
+def test_load_setuptools_not_installed(monkeypatch, pm):
+ monkeypatch.setitem(
+ sys.modules, 'pkg_resources',
+ types.ModuleType("pkg_resources"))
+
+ with pytest.raises(ImportError):
+ pm.load_setuptools_entrypoints("qwe")
+
+
+def test_add_tracefuncs(he_pm):
+ out = []
+
+ class api1(object):
+ @hookimpl
+ def he_method1(self):
+ out.append("he_method1-api1")
+
+ class api2(object):
+ @hookimpl
+ def he_method1(self):
+ out.append("he_method1-api2")
+
+ he_pm.register(api1())
+ he_pm.register(api2())
+
+ def before(hook_name, hook_impls, kwargs):
+ out.append((hook_name, list(hook_impls), kwargs))
+
+ def after(outcome, hook_name, hook_impls, kwargs):
+ out.append((outcome, hook_name, list(hook_impls), kwargs))
+
+ undo = he_pm.add_hookcall_monitoring(before, after)
+
+ he_pm.hook.he_method1(arg=1)
+ assert len(out) == 4
+ assert out[0][0] == "he_method1"
+ assert len(out[0][1]) == 2
+ assert isinstance(out[0][2], dict)
+ assert out[1] == "he_method1-api2"
+ assert out[2] == "he_method1-api1"
+ assert len(out[3]) == 4
+ assert out[3][1] == out[0][0]
+
+ undo()
+ he_pm.hook.he_method1(arg=1)
+ assert len(out) == 4 + 2
+
+
+def test_hook_tracing(he_pm):
+ saveindent = []
+
+ class api1(object):
+ @hookimpl
+ def he_method1(self):
+ saveindent.append(he_pm.trace.root.indent)
+
+ class api2(object):
+ @hookimpl
+ def he_method1(self):
+ saveindent.append(he_pm.trace.root.indent)
+ raise ValueError()
+
+ he_pm.register(api1())
+ out = []
+ he_pm.trace.root.setwriter(out.append)
+ undo = he_pm.enable_tracing()
+ try:
+ indent = he_pm.trace.root.indent
+ he_pm.hook.he_method1(arg=1)
+ assert indent == he_pm.trace.root.indent
+ assert len(out) == 2
+ assert 'he_method1' in out[0]
+ assert 'finish' in out[1]
+
+ out[:] = []
+ he_pm.register(api2())
+
+ with pytest.raises(ValueError):
+ he_pm.hook.he_method1(arg=1)
+ assert he_pm.trace.root.indent == indent
+ assert saveindent[0] > indent
+ finally:
+ undo()
+
+
+@pytest.mark.parametrize('include_hookspec', [True, False])
+def test_prefix_hookimpl(include_hookspec):
+ pm = PluginManager(hookspec.project_name, "hello_")
+
+ if include_hookspec:
+ class HookSpec(object):
+ @hookspec
+ def hello_myhook(self, arg1):
+ """ add to arg1 """
+
+ pm.add_hookspecs(HookSpec)
+
+ class Plugin(object):
+ def hello_myhook(self, arg1):
+ return arg1 + 1
+
+ pm.register(Plugin())
+ pm.register(Plugin())
+ results = pm.hook.hello_myhook(arg1=17)
+ assert results == [18, 18]
+
+
+def test_prefix_hookimpl_dontmatch_module():
+ pm = PluginManager(hookspec.project_name, "hello_")
+
+ class BadPlugin(object):
+ hello_module = __import__('email')
+
+ pm.register(BadPlugin())
+ pm.check_pending()
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_multicall.py b/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_multicall.py
new file mode 100644
index 00000000000..860a209b669
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_multicall.py
@@ -0,0 +1,194 @@
+import pytest
+
+from pluggy import _multicall, _legacymulticall, HookImpl, HookCallError
+from pluggy.callers import _LegacyMultiCall
+from pluggy import HookspecMarker, HookimplMarker
+
+
+hookspec = HookspecMarker("example")
+hookimpl = HookimplMarker("example")
+
+
+def test_uses_copy_of_methods():
+ out = [lambda: 42]
+ mc = _LegacyMultiCall(out, {})
+ repr(mc)
+ out[:] = []
+ res = mc.execute()
+ return res == 42
+
+
+def MC(methods, kwargs, firstresult=False):
+ caller = _multicall
+ hookfuncs = []
+ for method in methods:
+ f = HookImpl(None, "<temp>", method, method.example_impl)
+ hookfuncs.append(f)
+ if '__multicall__' in f.argnames:
+ caller = _legacymulticall
+ return caller(hookfuncs, kwargs, firstresult=firstresult)
+
+
+def test_call_passing():
+ class P1(object):
+ @hookimpl
+ def m(self, __multicall__, x):
+ assert len(__multicall__.results) == 1
+ assert not __multicall__.hook_impls
+ return 17
+
+ class P2(object):
+ @hookimpl
+ def m(self, __multicall__, x):
+ assert __multicall__.results == []
+ assert __multicall__.hook_impls
+ return 23
+
+ p1 = P1()
+ p2 = P2()
+ reslist = MC([p1.m, p2.m], {"x": 23})
+ assert len(reslist) == 2
+ # ensure reversed order
+ assert reslist == [23, 17]
+
+
+def test_keyword_args():
+ @hookimpl
+ def f(x):
+ return x + 1
+
+ class A(object):
+ @hookimpl
+ def f(self, x, y):
+ return x + y
+
+ reslist = MC([f, A().f], dict(x=23, y=24))
+ assert reslist == [24 + 23, 24]
+
+
+def test_keyword_args_with_defaultargs():
+ @hookimpl
+ def f(x, z=1):
+ return x + z
+ reslist = MC([f], dict(x=23, y=24))
+ assert reslist == [24]
+
+
+def test_tags_call_error():
+ @hookimpl
+ def f(x):
+ return x
+ with pytest.raises(HookCallError):
+ MC([f], {})
+
+
+def test_call_subexecute():
+ @hookimpl
+ def m(__multicall__):
+ subresult = __multicall__.execute()
+ return subresult + 1
+
+ @hookimpl
+ def n():
+ return 1
+
+ res = MC([n, m], {}, firstresult=True)
+ assert res == 2
+
+
+def test_call_none_is_no_result():
+ @hookimpl
+ def m1():
+ return 1
+
+ @hookimpl
+ def m2():
+ return None
+
+ res = MC([m1, m2], {}, firstresult=True)
+ assert res == 1
+ res = MC([m1, m2], {}, {})
+ assert res == [1]
+
+
+def test_hookwrapper():
+ out = []
+
+ @hookimpl(hookwrapper=True)
+ def m1():
+ out.append("m1 init")
+ yield None
+ out.append("m1 finish")
+
+ @hookimpl
+ def m2():
+ out.append("m2")
+ return 2
+
+ res = MC([m2, m1], {})
+ assert res == [2]
+ assert out == ["m1 init", "m2", "m1 finish"]
+ out[:] = []
+ res = MC([m2, m1], {}, firstresult=True)
+ assert res == 2
+ assert out == ["m1 init", "m2", "m1 finish"]
+
+
+def test_hookwrapper_order():
+ out = []
+
+ @hookimpl(hookwrapper=True)
+ def m1():
+ out.append("m1 init")
+ yield 1
+ out.append("m1 finish")
+
+ @hookimpl(hookwrapper=True)
+ def m2():
+ out.append("m2 init")
+ yield 2
+ out.append("m2 finish")
+
+ res = MC([m2, m1], {})
+ assert res == []
+ assert out == ["m1 init", "m2 init", "m2 finish", "m1 finish"]
+
+
+def test_hookwrapper_not_yield():
+ @hookimpl(hookwrapper=True)
+ def m1():
+ pass
+
+ with pytest.raises(TypeError):
+ MC([m1], {})
+
+
+def test_hookwrapper_too_many_yield():
+ @hookimpl(hookwrapper=True)
+ def m1():
+ yield 1
+ yield 2
+
+ with pytest.raises(RuntimeError) as ex:
+ MC([m1], {})
+ assert "m1" in str(ex.value)
+ assert (__file__ + ':') in str(ex.value)
+
+
+@pytest.mark.parametrize("exc", [ValueError, SystemExit])
+def test_hookwrapper_exception(exc):
+ out = []
+
+ @hookimpl(hookwrapper=True)
+ def m1():
+ out.append("m1 init")
+ yield None
+ out.append("m1 finish")
+
+ @hookimpl
+ def m2():
+ raise exc
+
+ with pytest.raises(exc):
+ MC([m2, m1], {})
+ assert out == ["m1 init", "m1 finish"]
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_pluginmanager.py b/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_pluginmanager.py
new file mode 100644
index 00000000000..e2c86cc6442
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_pluginmanager.py
@@ -0,0 +1,374 @@
+import pytest
+import types
+
+from pluggy import (PluginValidationError,
+ HookCallError, HookimplMarker, HookspecMarker)
+
+
+hookspec = HookspecMarker("example")
+hookimpl = HookimplMarker("example")
+
+
+def test_plugin_double_register(pm):
+ pm.register(42, name="abc")
+ with pytest.raises(ValueError):
+ pm.register(42, name="abc")
+ with pytest.raises(ValueError):
+ pm.register(42, name="def")
+
+
+def test_pm(pm):
+ class A(object):
+ pass
+
+ a1, a2 = A(), A()
+ pm.register(a1)
+ assert pm.is_registered(a1)
+ pm.register(a2, "hello")
+ assert pm.is_registered(a2)
+ out = pm.get_plugins()
+ assert a1 in out
+ assert a2 in out
+ assert pm.get_plugin('hello') == a2
+ assert pm.unregister(a1) == a1
+ assert not pm.is_registered(a1)
+
+ out = pm.list_name_plugin()
+ assert len(out) == 1
+ assert out == [("hello", a2)]
+
+
+def test_has_plugin(pm):
+ class A(object):
+ pass
+
+ a1 = A()
+ pm.register(a1, 'hello')
+ assert pm.is_registered(a1)
+ assert pm.has_plugin('hello')
+
+
+def test_register_dynamic_attr(he_pm):
+ class A(object):
+ def __getattr__(self, name):
+ if name[0] != "_":
+ return 42
+ raise AttributeError()
+
+ a = A()
+ he_pm.register(a)
+ assert not he_pm.get_hookcallers(a)
+
+
+def test_pm_name(pm):
+ class A(object):
+ pass
+
+ a1 = A()
+ name = pm.register(a1, name="hello")
+ assert name == "hello"
+ pm.unregister(a1)
+ assert pm.get_plugin(a1) is None
+ assert not pm.is_registered(a1)
+ assert not pm.get_plugins()
+ name2 = pm.register(a1, name="hello")
+ assert name2 == name
+ pm.unregister(name="hello")
+ assert pm.get_plugin(a1) is None
+ assert not pm.is_registered(a1)
+ assert not pm.get_plugins()
+
+
+def test_set_blocked(pm):
+ class A(object):
+ pass
+
+ a1 = A()
+ name = pm.register(a1)
+ assert pm.is_registered(a1)
+ assert not pm.is_blocked(name)
+ pm.set_blocked(name)
+ assert pm.is_blocked(name)
+ assert not pm.is_registered(a1)
+
+ pm.set_blocked("somename")
+ assert pm.is_blocked("somename")
+ assert not pm.register(A(), "somename")
+ pm.unregister(name="somename")
+ assert pm.is_blocked("somename")
+
+
+def test_register_mismatch_method(he_pm):
+ class hello(object):
+ @hookimpl
+ def he_method_notexists(self):
+ pass
+
+ he_pm.register(hello())
+ with pytest.raises(PluginValidationError):
+ he_pm.check_pending()
+
+
+def test_register_mismatch_arg(he_pm):
+ class hello(object):
+ @hookimpl
+ def he_method1(self, qlwkje):
+ pass
+
+ with pytest.raises(PluginValidationError):
+ he_pm.register(hello())
+
+
+def test_register(pm):
+ class MyPlugin(object):
+ pass
+ my = MyPlugin()
+ pm.register(my)
+ assert my in pm.get_plugins()
+ my2 = MyPlugin()
+ pm.register(my2)
+ assert set([my, my2]).issubset(pm.get_plugins())
+
+ assert pm.is_registered(my)
+ assert pm.is_registered(my2)
+ pm.unregister(my)
+ assert not pm.is_registered(my)
+ assert my not in pm.get_plugins()
+
+
+def test_register_unknown_hooks(pm):
+ class Plugin1(object):
+ @hookimpl
+ def he_method1(self, arg):
+ return arg + 1
+
+ pname = pm.register(Plugin1())
+
+ class Hooks(object):
+ @hookspec
+ def he_method1(self, arg):
+ pass
+
+ pm.add_hookspecs(Hooks)
+ # assert not pm._unverified_hooks
+ assert pm.hook.he_method1(arg=1) == [2]
+ assert len(pm.get_hookcallers(pm.get_plugin(pname))) == 1
+
+
+def test_register_historic(pm):
+ class Hooks(object):
+ @hookspec(historic=True)
+ def he_method1(self, arg):
+ pass
+ pm.add_hookspecs(Hooks)
+
+ pm.hook.he_method1.call_historic(kwargs=dict(arg=1))
+ out = []
+
+ class Plugin(object):
+ @hookimpl
+ def he_method1(self, arg):
+ out.append(arg)
+
+ pm.register(Plugin())
+ assert out == [1]
+
+ class Plugin2(object):
+ @hookimpl
+ def he_method1(self, arg):
+ out.append(arg * 10)
+
+ pm.register(Plugin2())
+ assert out == [1, 10]
+ pm.hook.he_method1.call_historic(kwargs=dict(arg=12))
+ assert out == [1, 10, 120, 12]
+
+
+def test_with_result_memorized(pm):
+ class Hooks(object):
+ @hookspec(historic=True)
+ def he_method1(self, arg):
+ pass
+ pm.add_hookspecs(Hooks)
+
+ he_method1 = pm.hook.he_method1
+ he_method1.call_historic(lambda res: out.append(res), dict(arg=1))
+ out = []
+
+ class Plugin(object):
+ @hookimpl
+ def he_method1(self, arg):
+ return arg * 10
+
+ pm.register(Plugin())
+ assert out == [10]
+
+
+def test_with_callbacks_immediately_executed(pm):
+ class Hooks(object):
+ @hookspec(historic=True)
+ def he_method1(self, arg):
+ pass
+ pm.add_hookspecs(Hooks)
+
+ class Plugin1(object):
+ @hookimpl
+ def he_method1(self, arg):
+ return arg * 10
+
+ class Plugin2(object):
+ @hookimpl
+ def he_method1(self, arg):
+ return arg * 20
+
+ class Plugin3(object):
+ @hookimpl
+ def he_method1(self, arg):
+ return arg * 30
+
+ out = []
+ pm.register(Plugin1())
+ pm.register(Plugin2())
+
+ he_method1 = pm.hook.he_method1
+ he_method1.call_historic(lambda res: out.append(res), dict(arg=1))
+ assert out == [20, 10]
+ pm.register(Plugin3())
+ assert out == [20, 10, 30]
+
+
+def test_register_historic_incompat_hookwrapper(pm):
+ class Hooks(object):
+ @hookspec(historic=True)
+ def he_method1(self, arg):
+ pass
+
+ pm.add_hookspecs(Hooks)
+
+ out = []
+
+ class Plugin(object):
+ @hookimpl(hookwrapper=True)
+ def he_method1(self, arg):
+ out.append(arg)
+
+ with pytest.raises(PluginValidationError):
+ pm.register(Plugin())
+
+
+def test_call_extra(pm):
+ class Hooks(object):
+ @hookspec
+ def he_method1(self, arg):
+ pass
+
+ pm.add_hookspecs(Hooks)
+
+ def he_method1(arg):
+ return arg * 10
+
+ out = pm.hook.he_method1.call_extra([he_method1], dict(arg=1))
+ assert out == [10]
+
+
+def test_call_with_too_few_args(pm):
+ class Hooks(object):
+ @hookspec
+ def he_method1(self, arg):
+ pass
+
+ pm.add_hookspecs(Hooks)
+
+ class Plugin1(object):
+ @hookimpl
+ def he_method1(self, arg):
+ 0 / 0
+ pm.register(Plugin1())
+ with pytest.raises(HookCallError):
+ with pytest.warns(UserWarning):
+ pm.hook.he_method1()
+
+
+def test_subset_hook_caller(pm):
+ class Hooks(object):
+ @hookspec
+ def he_method1(self, arg):
+ pass
+
+ pm.add_hookspecs(Hooks)
+
+ out = []
+
+ class Plugin1(object):
+ @hookimpl
+ def he_method1(self, arg):
+ out.append(arg)
+
+ class Plugin2(object):
+ @hookimpl
+ def he_method1(self, arg):
+ out.append(arg * 10)
+
+ class PluginNo(object):
+ pass
+
+ plugin1, plugin2, plugin3 = Plugin1(), Plugin2(), PluginNo()
+ pm.register(plugin1)
+ pm.register(plugin2)
+ pm.register(plugin3)
+ pm.hook.he_method1(arg=1)
+ assert out == [10, 1]
+ out[:] = []
+
+ hc = pm.subset_hook_caller("he_method1", [plugin1])
+ hc(arg=2)
+ assert out == [20]
+ out[:] = []
+
+ hc = pm.subset_hook_caller("he_method1", [plugin2])
+ hc(arg=2)
+ assert out == [2]
+ out[:] = []
+
+ pm.unregister(plugin1)
+ hc(arg=2)
+ assert out == []
+ out[:] = []
+
+ pm.hook.he_method1(arg=1)
+ assert out == [10]
+
+
+def test_multicall_deprecated(pm):
+ class P1(object):
+ @hookimpl
+ def m(self, __multicall__, x):
+ pass
+
+ pytest.deprecated_call(pm.register, P1())
+
+
+def test_add_hookspecs_nohooks(pm):
+ with pytest.raises(ValueError):
+ pm.add_hookspecs(10)
+
+
+def test_reject_prefixed_module(pm):
+ """Verify that a module type attribute that contains the project
+ prefix in its name (in this case `'example_*'` isn't collected
+ when registering a module which imports it.
+ """
+ pm._implprefix = 'example'
+ conftest = types.ModuleType("conftest")
+ src = ("""
+def example_hook():
+ pass
+""")
+ exec(src, conftest.__dict__)
+ conftest.example_blah = types.ModuleType("example_blah")
+ name = pm.register(conftest)
+ assert name == 'conftest'
+ assert getattr(pm.hook, 'example_blah', None) is None
+ assert getattr(pm.hook, 'example_hook', None) # conftest.example_hook should be collected
+ assert pm.parse_hookimpl_opts(conftest, 'example_blah') is None
+ assert pm.parse_hookimpl_opts(conftest, 'example_hook') == {}
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_tracer.py b/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_tracer.py
new file mode 100644
index 00000000000..4a3e16cec43
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pluggy/testing/test_tracer.py
@@ -0,0 +1,89 @@
+
+from pluggy import _TagTracer
+
+
+def test_simple():
+ rootlogger = _TagTracer()
+ log = rootlogger.get("pytest")
+ log("hello")
+ out = []
+ rootlogger.setwriter(out.append)
+ log("world")
+ assert len(out) == 1
+ assert out[0] == "world [pytest]\n"
+ sublog = log.get("collection")
+ sublog("hello")
+ assert out[1] == "hello [pytest:collection]\n"
+
+
+def test_indent():
+ rootlogger = _TagTracer()
+ log = rootlogger.get("1")
+ out = []
+ log.root.setwriter(lambda arg: out.append(arg))
+ log("hello")
+ log.root.indent += 1
+ log("line1")
+ log("line2")
+ log.root.indent += 1
+ log("line3")
+ log("line4")
+ log.root.indent -= 1
+ log("line5")
+ log.root.indent -= 1
+ log("last")
+ assert len(out) == 7
+ names = [x[:x.rfind(' [')] for x in out]
+ assert names == [
+ 'hello', ' line1', ' line2',
+ ' line3', ' line4', ' line5', 'last']
+
+
+def test_readable_output_dictargs():
+ rootlogger = _TagTracer()
+
+ out = rootlogger.format_message(['test'], [1])
+ assert out == ['1 [test]\n']
+
+ out2 = rootlogger.format_message(['test'], ['test', {'a': 1}])
+ assert out2 == [
+ 'test [test]\n',
+ ' a: 1\n'
+ ]
+
+
+def test_setprocessor():
+ rootlogger = _TagTracer()
+ log = rootlogger.get("1")
+ log2 = log.get("2")
+ assert log2.tags == tuple("12")
+ out = []
+ rootlogger.setprocessor(tuple("12"), lambda *args: out.append(args))
+ log("not seen")
+ log2("seen")
+ assert len(out) == 1
+ tags, args = out[0]
+ assert "1" in tags
+ assert "2" in tags
+ assert args == ("seen",)
+ l2 = []
+ rootlogger.setprocessor("1:2", lambda *args: l2.append(args))
+ log2("seen")
+ tags, args = l2[0]
+ assert args == ("seen",)
+
+
+def test_setmyprocessor():
+ rootlogger = _TagTracer()
+ log = rootlogger.get("1")
+ log2 = log.get("2")
+ out = []
+ log2.setmyprocessor(lambda *args: out.append(args))
+ log("not seen")
+ assert not out
+ log2(42)
+ assert len(out) == 1
+ tags, args = out[0]
+ assert "1" in tags
+ assert "2" in tags
+ assert args == (42,)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pluggy/tox.ini b/tests/wpt/web-platform-tests/tools/third_party/pluggy/tox.ini
new file mode 100644
index 00000000000..89d44e352db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pluggy/tox.ini
@@ -0,0 +1,44 @@
+[tox]
+envlist=check,docs,py{27,34,35,36,py}-pytestrelease,py{27,36}-pytest{master,features}
+
+[testenv]
+commands=py.test {posargs:testing/}
+setenv=
+ _PYTEST_SETUP_SKIP_PLUGGY_DEP=1
+deps=
+ pytestrelease: pytest
+ pytestmaster: git+https://github.com/pytest-dev/pytest.git@master
+ pytestfeatures: git+https://github.com/pytest-dev/pytest.git@features
+
+[testenv:benchmark]
+commands=py.test {posargs:testing/benchmark.py}
+deps=
+ pytest
+ pytest-benchmark
+
+[testenv:check]
+deps =
+ flake8
+ restructuredtext_lint
+ pygments
+commands =
+ flake8 pluggy.py setup.py testing
+ rst-lint CHANGELOG.rst README.rst
+
+[testenv:docs]
+deps =
+ sphinx
+ pygments
+commands =
+ sphinx-build -b html {toxinidir}/docs {toxinidir}/build/html-docs
+
+[pytest]
+minversion=2.0
+#--pyargs --doctest-modules --ignore=.tox
+addopts=-rxsX
+norecursedirs=.tox ja .hg .env*
+filterwarnings =
+ error
+
+[flake8]
+max-line-length=99
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/.gitattributes b/tests/wpt/web-platform-tests/tools/third_party/py/.gitattributes
new file mode 100644
index 00000000000..1246879c4da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/.gitattributes
@@ -0,0 +1 @@
+*.dump eol=lf
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/.gitignore b/tests/wpt/web-platform-tests/tools/third_party/py/.gitignore
new file mode 100644
index 00000000000..5bb0d457d49
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/.gitignore
@@ -0,0 +1,12 @@
+
+.cache/
+.tox/
+__pycache__/
+
+*.pyc
+*.pyo
+
+*.egg-info
+.eggs/
+
+dist/*
diff --git a/tests/wpt/web-platform-tests/tools/py/.hgignore b/tests/wpt/web-platform-tests/tools/third_party/py/.hgignore
index 34976da5d15..34976da5d15 100644
--- a/tests/wpt/web-platform-tests/tools/py/.hgignore
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/.hgignore
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/.hgtags b/tests/wpt/web-platform-tests/tools/third_party/py/.hgtags
new file mode 100644
index 00000000000..9d48095bf64
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/.hgtags
@@ -0,0 +1,68 @@
+52c6d9e78777a5a34e813123997dfc614a1a4767 1.0.0b3
+1c7aaa8c61f3b0945921a9acc7beb184201aed4b 1.0.0b4
+1c7aaa8c61f3b0945921a9acc7beb184201aed4b 1.0.0b4
+0000000000000000000000000000000000000000 1.0.0b4
+0000000000000000000000000000000000000000 1.0.0b4
+8cd6eb91eba313b012d6e568f37d844dc0751f2e 1.0.0b4
+8cd6eb91eba313b012d6e568f37d844dc0751f2e 1.0.0b4
+0000000000000000000000000000000000000000 1.0.0b4
+2cc0507f117ffe721dff7ee026648cfce00ec92f 1.0.0b6
+86f1e1b6e49bf5882a809f11edd1dbb08162cdad 1.0.0b8
+86f1e1b6e49bf5882a809f11edd1dbb08162cdad 1.0.0b8
+c63f35c266cbb26dad6b87b5e115d65685adf448 1.0.0b8
+c63f35c266cbb26dad6b87b5e115d65685adf448 1.0.0b8
+0eaa0fdf2ba0163cf534dc2eff4ba2e5fc66c261 1.0.0b8
+e2a60653cb490aeed81bbbd83c070b99401c211c 1.0.0b9
+5ea0cdf7854c3d4278d36eda94a2b68483a0e211 1.0.0
+5ea0cdf7854c3d4278d36eda94a2b68483a0e211 1.0.0
+7acde360d94b6a2690ce3d03ff39301da84c0a2b 1.0.0
+6bd221981ac99103002c1cb94fede400d23a96a1 1.0.1
+4816e8b80602a3fd3a0a120333ad85fbe7d8bab4 1.0.2
+60c44bdbf093285dc69d5462d4dbb4acad325ca6 1.1.0
+319187fcda66714c5eb1353492babeec3d3c826f 1.1.1
+4fc5212f7626a56b9eb6437b5c673f56dd7eb942 1.2.0
+c143a8c8840a1c68570890c8ac6165bbf92fd3c6 1.2.1
+eafd3c256e8732dfb0a4d49d051b5b4339858926 1.3.0
+d5eacf390af74553227122b85e20345d47b2f9e6 1.3.1
+d5eacf390af74553227122b85e20345d47b2f9e6 1.3.1
+8b8e7c25a13cf863f01b2dd955978285ae9daf6a 1.3.1
+3bff44b188a7ec1af328d977b9d39b6757bb38df 1.3.2
+c59d3fa8681a5b5966b8375b16fccd64a3a8dbeb 1.3.3
+79ef6377705184c55633d456832eea318fedcf61 1.3.4
+79ef6377705184c55633d456832eea318fedcf61 1.3.4
+90fffd35373e9f125af233f78b19416f0938d841 1.3.4
+5346ab41b059c95a48cbe1e8a7bae96ce6e0da27 1.4.0
+1f3125cba7976538952be268f107c1d0c36c5ce8 1.4.1
+04ab22db4ff737cf31e91d75a0f5d7077f324167 1.4.2
+9950bf9d684a984d511795013421c89c5cf88bef 1.4.3
+d9951e3bdbc765e73835ae13012f6a074d13d8bf 1.4.4
+b827dd156a36753e32c7f3f15ce82d6fe9e356c8 1.4.6
+f15726f9e5a67cc6221c499affa4840e9d591763 1.4.7
+abfabd07a1d328f13c730e8a50d80d2e470afd3b 1.4.9
+7f37ee0aff9be4b839d6759cfee336f60e8393a4 1.4.10
+fe4593263efa10ea7ba014db6e3379e0b82368a2 1.4.11
+f07af25a26786e4825b5170e17ad693245cb3426 1.4.12
+d3730d84ba7eda92fd3469a3f63fd6d8cb22c975 1.4.13
+12c1ae8e7c5345721e9ec9f8e27b1e36c07f74dc 1.4.14
+12c1ae8e7c5345721e9ec9f8e27b1e36c07f74dc 1.4.14
+0000000000000000000000000000000000000000 1.4.14
+0000000000000000000000000000000000000000 1.4.14
+1497e2efd0f8c73a0e3d529debf0c489e4cd6cab 1.4.14
+e065014c1ce8ad110a381e9baaaa5d647ba7ac6b 1.4.15
+e9e5b38f53dc35b35aa1f9ee9a9be9bbd2d2c3b1 1.4.16
+c603503945f52b78522d96a423605cbc953236d3 1.4.17
+c59201105a29801cc858eb9160b7a19791b91a35 1.4.18
+284cc172e294d48edc840012e1451c32c3963d92 1.4.19
+a3e0626aa0c5aecf271367dc77e476ab216ea3c8 1.4.20
+5e48016c4a3af8e7358a1267d33d021e71765bed 1.4.21
+01ae2cfcc61c4fcb3aa5031349adb5b467c31018 1.4.23
+5ffd982f4dff60b588f309cd9bdc61036547282a 1.4.24
+dc9ffbcaf1f7d72e96be3f68c11deebb7e7193c5 1.4.25
+6de1a44bf75de7af4fcae947c235e9072bbdbb9a 1.4.26
+7d650ba2657890a2253c8c4a83f170febebd90fa 1.4.27
+7d650ba2657890a2253c8c4a83f170febebd90fa 1.4.27
+1810003dec63dd1b506a23849861fffa5bc3ba13 1.4.27
+ba08706f08ddea1b77a426f00dfe2bdc244345e8 1.4.28
+4e8054ada63f3327bcf759ae7cd36c7c8652bc9b 1.4.29
+366ab346610c6de8aaa7617e24011794b40236c6 1.4.30
+657380e439f9b7e04918cb162cb2e46388244b42 1.4.31
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/.travis.yml b/tests/wpt/web-platform-tests/tools/third_party/py/.travis.yml
new file mode 100644
index 00000000000..917c59d14b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/.travis.yml
@@ -0,0 +1,27 @@
+sudo: false
+language: python
+python:
+- '2.7'
+- '3.4'
+- '3.5'
+- '3.6'
+- 'pypy-5.4'
+env:
+- DEPS="pytest~=2.9.0"
+- DEPS="pytest~=3.0.0"
+#- DEPS="pytest~=3.1.0"
+
+matrix:
+
+ include:
+ - python: '2.7'
+ # using a different option due to pytest-addopts pytester issues
+ env: PYTEST_XADDOPTS="-n 3 --runslowtests" DEPS="pytest~=3.0.0 pytest-xdist"
+ allow_failures:
+ - python: 'pypy-5.4'
+install:
+- pip install -U setuptools setuptools_scm
+- pip install $DEPS
+- pip install -U . --force-reinstall
+script:
+- py.test --lsof $PYTEST_XADDOPTS
diff --git a/tests/wpt/web-platform-tests/tools/py/AUTHORS b/tests/wpt/web-platform-tests/tools/third_party/py/AUTHORS
index 8c0cf9b71b1..8c0cf9b71b1 100644
--- a/tests/wpt/web-platform-tests/tools/py/AUTHORS
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/AUTHORS
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/CHANGELOG b/tests/wpt/web-platform-tests/tools/third_party/py/CHANGELOG
new file mode 100644
index 00000000000..7e7b01b0b9e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/CHANGELOG
@@ -0,0 +1,1149 @@
+1.5.2
+=====
+
+- fix #169, #170: error importing py.log on Windows: no module named ``syslog``.
+
+1.5.1
+=====
+
+- fix #167 - prevent pip from installing py in unsupported Python versions.
+
+1.5.0
+=====
+
+NOTE: **this release has been removed from PyPI** due to missing package
+metadata which caused a number of problems to py26 and py33 users.
+This issue was fixed in the 1.5.1 release.
+
+- python 2.6 and 3.3 are no longer supported
+- deprecate py.std and remove all internal uses
+- fix #73 turn py.error into an actual module
+- path join to / no longer produces leading double slashes
+- fix #82 - remove unsupportable aliases
+- fix python37 compatibility of path.sysfind on windows by correctly replacing vars
+- turn iniconfig and apipkg into vendored packages and ease de-vendoring for distributions
+- fix #68 remove invalid py.test.ensuretemp references
+- fix #25 - deprecate path.listdir(sort=callable)
+- add ``TerminalWriter.chars_on_current_line`` read-only property that tracks how many characters
+ have been written to the current line.
+
+1.4.34
+====================================================================
+
+- fix issue119 / pytest issue708 where tmpdir may fail to make numbered directories
+ when the filesystem is case-insensitive.
+
+1.4.33
+====================================================================
+
+- avoid imports in calls to py.path.local().fnmatch(). Thanks Andreas Pelme for
+ the PR.
+
+- fix issue106: Naive unicode encoding when calling fspath() in python2. Thanks Tiago Nobrega for the PR.
+
+- fix issue110: unittest.TestCase.assertWarns fails with py imported.
+
+1.4.32
+====================================================================
+
+- fix issue70: added ability to copy all stat info in py.path.local.copy.
+
+- make TerminalWriter.fullwidth a property. This results in the correct
+ value when the terminal gets resized.
+
+- update supported html tags to include recent additions.
+ Thanks Denis Afonso for the PR.
+
+- Remove internal code in ``Source.compile`` meant to support earlier Python 3 versions that produced the side effect
+ of leaving ``None`` in ``sys.modules`` when called (see pytest-dev/pytest#2103).
+ Thanks Bruno Oliveira for the PR.
+
+1.4.31
+==================================================
+
+- fix local().copy(dest, mode=True) to also work
+ with unicode.
+
+- pass better error message with svn EEXIST paths
+
+1.4.30
+==================================================
+
+- fix issue68 an assert with a multiline list comprehension
+ was not reported correctly. Thanks Henrik Heibuerger.
+
+
+1.4.29
+==================================================
+
+- fix issue55: revert a change to the statement finding algorithm
+ which is used by pytest for generating tracebacks.
+ Thanks Daniel Hahler for initial analysis.
+
+- fix pytest issue254 for when traceback rendering can't
+ find valid source code. Thanks Ionel Cristian Maries.
+
+
+1.4.28
+==================================================
+
+- fix issue64 -- dirpath regression when "abs=True" is passed.
+ Thanks Gilles Dartiguelongue.
+
+1.4.27
+==================================================
+
+- fix issue59: point to new repo site
+
+- allow a new ensuresyspath="append" mode for py.path.local.pyimport()
+ so that a neccessary import path is appended instead of prepended to
+ sys.path
+
+- strike undocumented, untested argument to py.path.local.pypkgpath
+
+- speed up py.path.local.dirpath by a factor of 10
+
+1.4.26
+==================================================
+
+- avoid calling normpath twice in py.path.local
+
+- py.builtin._reraise properly reraises under Python3 now.
+
+- fix issue53 - remove module index, thanks jenisys.
+
+- allow posix path separators when "fnmatch" is called.
+ Thanks Christian Long for the complete PR.
+
+1.4.25
+==================================================
+
+- fix issue52: vaguely fix py25 compat of py.path.local (it's not
+ officially supported), also fix docs
+
+- fix pytest issue 589: when checking if we have a recursion error
+ check for the specific "maximum recursion depth" text of the exception.
+
+1.4.24
+==================================================
+
+- Fix retrieving source when an else: line has an other statement on
+ the same line.
+
+- add localpath read_text/write_text/read_bytes/write_bytes methods
+ as shortcuts and clearer bytes/text interfaces for read/write.
+ Adapted from a PR from Paul Moore.
+
+
+1.4.23
+==================================================
+
+- use newer apipkg version which makes attribute access on
+ alias modules resolve to None rather than an ImportError.
+ This helps with code that uses inspect.getframeinfo()
+ on py34 which causes a complete walk on sys.modules
+ thus triggering the alias module to resolve and blowing
+ up with ImportError. The negative side is that something
+ like "py.test.X" will now result in None instead of "importerror: pytest"
+ if pytest is not installed. But you shouldn't import "py.test"
+ anyway anymore.
+
+- adapt one svn test to only check for any exception instead
+ of specific ones because different svn versions cause different
+ errors and we don't care.
+
+
+1.4.22
+==================================================
+
+- refactor class-level registry on ForkedFunc child start/finish
+ event to become instance based (i.e. passed into the constructor)
+
+1.4.21
+==================================================
+
+- ForkedFunc now has class-level register_on_start/on_exit()
+ methods to allow adding information in the boxed process.
+ Thanks Marc Schlaich.
+
+- ForkedFunc in the child opens in "auto-flush" mode for
+ stdout/stderr so that when a subprocess dies you can see
+ its output even if it didn't flush itself.
+
+- refactor traceback generation in light of pytest issue 364
+ (shortening tracebacks). you can now set a new traceback style
+ on a per-entry basis such that a caller can force entries to be
+ isplayed as short or long entries.
+
+- win32: py.path.local.sysfind(name) will preferrably return files with
+ extensions so that if "X" and "X.bat" or "X.exe" is on the PATH,
+ one of the latter two will be returned.
+
+1.4.20
+==================================================
+
+- ignore unicode decode errors in xmlescape. Thanks Anatoly Bubenkoff.
+
+- on python2 modify traceback.format_exception_only to match python3
+ behaviour, namely trying to print unicode for Exception instances
+
+- use a safer way for serializing exception reports (helps to fix
+ pytest issue413)
+
+Changes between 1.4.18 and 1.4.19
+==================================================
+
+- merge in apipkg fixes
+
+- some micro-optimizations in py/_code/code.py for speeding
+ up pytest runs. Thanks Alex Gaynor for initiative.
+
+- check PY_COLORS=1 or PY_COLORS=0 to force coloring/not-coloring
+ for py.io.TerminalWriter() independently from capabilities
+ of the output file. Thanks Marc Abramowitz for the PR.
+
+- some fixes to unicode handling in assertion handling.
+ Thanks for the PR to Floris Bruynooghe. (This helps
+ to fix pytest issue 319).
+
+- depend on setuptools presence, remove distribute_setup
+
+Changes between 1.4.17 and 1.4.18
+==================================================
+
+- introduce path.ensure_dir() as a synonym for ensure(..., dir=1)
+
+- some unicode/python3 related fixes wrt to path manipulations
+ (if you start passing unicode particular in py2 you might
+ still get problems, though)
+
+Changes between 1.4.16 and 1.4.17
+==================================================
+
+- make py.io.TerminalWriter() prefer colorama if it is available
+ and avoid empty lines when separator-lines are printed by
+ being defensive and reducing the working terminalwidth by 1
+
+- introduce optional "expanduser" argument to py.path.local
+ to that local("~", expanduser=True) gives the home
+ directory of "user".
+
+Changes between 1.4.15 and 1.4.16
+==================================================
+
+- fix issue35 - define __gt__ ordering between a local path
+ and strings
+
+- fix issue36 - make chdir() work even if os.getcwd() fails.
+
+- add path.exists/isdir/isfile/islink shortcuts
+
+- introduce local path.as_cwd() context manager.
+
+- introduce p.write(ensure=1) and p.open(ensure=1)
+ where ensure triggers creation of neccessary parent
+ dirs.
+
+
+Changes between 1.4.14 and 1.4.15
+==================================================
+
+- majorly speed up some common calling patterns with
+ LocalPath.listdir()/join/check/stat functions considerably.
+
+- fix an edge case with fnmatch where a glob style pattern appeared
+ in an absolute path.
+
+Changes between 1.4.13 and 1.4.14
+==================================================
+
+- fix dupfile to work with files that don't
+ carry a mode. Thanks Jason R. Coombs.
+
+Changes between 1.4.12 and 1.4.13
+==================================================
+
+- fix getting statementrange/compiling a file ending
+ in a comment line without newline (on python2.5)
+- for local paths you can pass "mode=True" to a copy()
+ in order to copy permission bits (underlying mechanism
+ is using shutil.copymode)
+- add paths arguments to py.path.local.sysfind to restrict
+ search to the diretories in the path.
+- add isdir/isfile/islink to path.stat() objects allowing to perform
+ multiple checks without calling out multiple times
+- drop py.path.local.__new__ in favour of a simpler __init__
+- iniconfig: allow "name:value" settings in config files, no space after
+ "name" required
+- fix issue 27 - NameError in unlikely untested case of saferepr
+
+
+Changes between 1.4.11 and 1.4.12
+==================================================
+
+- fix python2.4 support - for pre-AST interpreters re-introduce
+ old way to find statements in exceptions (closes pytest issue 209)
+- add tox.ini to distribution
+- fix issue23 - print *,** args information in tracebacks,
+ thanks Manuel Jacob
+
+
+Changes between 1.4.10 and 1.4.11
+==================================================
+
+- use _ast to determine statement ranges when printing tracebacks -
+ avoiding multi-second delays on some large test modules
+- fix an internal test to not use class-denoted pytest_funcarg__
+- fix a doc link to bug tracker
+- try to make terminal.write() printing more robust against
+ unicodeencode/decode problems, amend according test
+- introduce py.builtin.text and py.builtin.bytes
+ to point to respective str/unicode (py2) and bytes/str (py3) types
+- fix error handling on win32/py33 for ENODIR
+
+Changes between 1.4.9 and 1.4.10
+==================================================
+
+- terminalwriter: default to encode to UTF8 if no encoding is defined
+ on the output stream
+- issue22: improve heuristic for finding the statementrange in exceptions
+
+Changes between 1.4.8 and 1.4.9
+==================================================
+
+- fix bug of path.visit() which would not recognize glob-style patterns
+ for the "rec" recursion argument
+- changed iniconfig parsing to better conform, now the chars ";"
+ and "#" only mark a comment at the stripped start of a line
+- include recent apipkg-1.2
+- change internal terminalwriter.line/reline logic to more nicely
+ support file spinners
+
+Changes between 1.4.7 and 1.4.8
+==================================================
+
+- fix issue 13 - correct handling of the tag name object in xmlgen
+- fix issue 14 - support raw attribute values in xmlgen
+- fix windows terminalwriter printing/re-line problem
+- update distribute_setup.py to 0.6.27
+
+Changes between 1.4.6 and 1.4.7
+==================================================
+
+- fix issue11 - own test failure with python3.3 / Thanks Benjamin Peterson
+- help fix pytest issue 102
+
+Changes between 1.4.5 and 1.4.6
+==================================================
+
+- help to fix pytest issue99: unify output of
+ ExceptionInfo.getrepr(style="native") with ...(style="long")
+- fix issue7: source.getstatementrange() now raises proper error
+ if no valid statement can be found
+- fix issue8: fix code and tests of svnurl/svnwc to work on subversion 1.7 -
+ note that path.status(updates=1) will not properly work svn-17's status
+ --xml output is broken.
+- make source.getstatementrange() more resilent about non-python code frames
+ (as seen from jnja2)
+- make trackeback recursion detection more resilent
+ about the eval magic of a decorator library
+- iniconfig: add support for ; as comment starter
+- properly handle lists in xmlgen on python3
+- normalize py.code.getfslineno(obj) to always return a (string, int) tuple
+ defaulting to ("", -1) respectively if no source code can be found for obj.
+
+Changes between 1.4.4 and 1.4.5
+==================================================
+
+- improve some unicode handling in terminalwriter and capturing
+ (used by pytest)
+
+Changes between 1.4.3 and 1.4.4
+==================================================
+
+- a few fixes and assertion related refinements for pytest-2.1
+- guard py.code.Code and getfslineno against bogus input
+ and make py.code.Code objects for object instance
+ by looking up their __call__ function.
+- make exception presentation robust against invalid current cwd
+
+Changes between 1.4.2 and 1.4.3
+==================================================
+
+- fix terminal coloring issue for skipped tests (thanks Amaury)
+- fix issue4 - large calls to ansi_print (thanks Amaury)
+
+Changes between 1.4.1 and 1.4.2
+==================================================
+
+- fix (pytest) issue23 - tmpdir argument now works on Python3.2 and WindowsXP
+ (which apparently starts to offer os.symlink now)
+
+- better error message for syntax errors from compiled code
+
+- small fix to better deal with (un-)colored terminal output on windows
+
+Changes between 1.4.0 and 1.4.1
+==================================================
+
+- fix issue1 - py.error.* classes to be pickleable
+
+- fix issue2 - on windows32 use PATHEXT as the list of potential
+ extensions to find find binaries with py.path.local.sysfind(commandname)
+
+- fix (pytest-) issue10 and refine assertion reinterpretation
+ to avoid breaking if the __nonzero__ of an object fails
+
+- fix (pytest-) issue17 where python3 does not like "import *"
+ leading to misrepresentation of import-errors in test modules
+
+- fix py.error.* attribute pypy access issue
+
+- allow path.samefile(arg) to succeed when arg is a relative filename
+
+- fix (pytest-) issue20 path.samefile(relpath) works as expected now
+
+- fix (pytest-) issue8 len(long_list) now shows the length of the list
+
+Changes between 1.3.4 and 1.4.0
+==================================================
+
+- py.test was moved to a separate "pytest" package. What remains is
+ a stub hook which will proxy ``import py.test`` to ``pytest``.
+- all command line tools ("py.cleanup/lookup/countloc/..." moved
+ to "pycmd" package)
+- removed the old and deprecated "py.magic" namespace
+- use apipkg-1.1 and make py.apipkg.initpkg|ApiModule available
+- add py.iniconfig module for brain-dead easy ini-config file parsing
+- introduce py.builtin.any()
+- path objects have a .dirname attribute now (equivalent to
+ os.path.dirname(path))
+- path.visit() accepts breadthfirst (bf) and sort options
+- remove deprecated py.compat namespace
+
+Changes between 1.3.3 and 1.3.4
+==================================================
+
+- fix issue111: improve install documentation for windows
+- fix issue119: fix custom collectability of __init__.py as a module
+- fix issue116: --doctestmodules work with __init__.py files as well
+- fix issue115: unify internal exception passthrough/catching/GeneratorExit
+- fix issue118: new --tb=native for presenting cpython-standard exceptions
+
+Changes between 1.3.2 and 1.3.3
+==================================================
+
+- fix issue113: assertion representation problem with triple-quoted strings
+ (and possibly other cases)
+- make conftest loading detect that a conftest file with the same
+ content was already loaded, avoids surprises in nested directory structures
+ which can be produced e.g. by Hudson. It probably removes the need to use
+ --confcutdir in most cases.
+- fix terminal coloring for win32
+ (thanks Michael Foord for reporting)
+- fix weirdness: make terminal width detection work on stdout instead of stdin
+ (thanks Armin Ronacher for reporting)
+- remove trailing whitespace in all py/text distribution files
+
+Changes between 1.3.1 and 1.3.2
+==================================================
+
+New features
+++++++++++++++++++
+
+- fix issue103: introduce py.test.raises as context manager, examples::
+
+ with py.test.raises(ZeroDivisionError):
+ x = 0
+ 1 / x
+
+ with py.test.raises(RuntimeError) as excinfo:
+ call_something()
+
+ # you may do extra checks on excinfo.value|type|traceback here
+
+ (thanks Ronny Pfannschmidt)
+
+- Funcarg factories can now dynamically apply a marker to a
+ test invocation. This is for example useful if a factory
+ provides parameters to a test which are expected-to-fail::
+
+ def pytest_funcarg__arg(request):
+ request.applymarker(py.test.mark.xfail(reason="flaky config"))
+ ...
+
+ def test_function(arg):
+ ...
+
+- improved error reporting on collection and import errors. This makes
+ use of a more general mechanism, namely that for custom test item/collect
+ nodes ``node.repr_failure(excinfo)`` is now uniformly called so that you can
+ override it to return a string error representation of your choice
+ which is going to be reported as a (red) string.
+
+- introduce '--junitprefix=STR' option to prepend a prefix
+ to all reports in the junitxml file.
+
+Bug fixes / Maintenance
+++++++++++++++++++++++++++
+
+- make tests and the ``pytest_recwarn`` plugin in particular fully compatible
+ to Python2.7 (if you use the ``recwarn`` funcarg warnings will be enabled so that
+ you can properly check for their existence in a cross-python manner).
+- refine --pdb: ignore xfailed tests, unify its TB-reporting and
+ don't display failures again at the end.
+- fix assertion interpretation with the ** operator (thanks Benjamin Peterson)
+- fix issue105 assignment on the same line as a failing assertion (thanks Benjamin Peterson)
+- fix issue104 proper escaping for test names in junitxml plugin (thanks anonymous)
+- fix issue57 -f|--looponfail to work with xpassing tests (thanks Ronny)
+- fix issue92 collectonly reporter and --pastebin (thanks Benjamin Peterson)
+- fix py.code.compile(source) to generate unique filenames
+- fix assertion re-interp problems on PyPy, by defering code
+ compilation to the (overridable) Frame.eval class. (thanks Amaury Forgeot)
+- fix py.path.local.pyimport() to work with directories
+- streamline py.path.local.mkdtemp implementation and usage
+- don't print empty lines when showing junitxml-filename
+- add optional boolean ignore_errors parameter to py.path.local.remove
+- fix terminal writing on win32/python2.4
+- py.process.cmdexec() now tries harder to return properly encoded unicode objects
+ on all python versions
+- install plain py.test/py.which scripts also for Jython, this helps to
+ get canonical script paths in virtualenv situations
+- make path.bestrelpath(path) return ".", note that when calling
+ X.bestrelpath the assumption is that X is a directory.
+- make initial conftest discovery ignore "--" prefixed arguments
+- fix resultlog plugin when used in an multicpu/multihost xdist situation
+ (thanks Jakub Gustak)
+- perform distributed testing related reporting in the xdist-plugin
+ rather than having dist-related code in the generic py.test
+ distribution
+- fix homedir detection on Windows
+- ship distribute_setup.py version 0.6.13
+
+Changes between 1.3.0 and 1.3.1
+==================================================
+
+New features
+++++++++++++++++++
+
+- issue91: introduce new py.test.xfail(reason) helper
+ to imperatively mark a test as expected to fail. Can
+ be used from within setup and test functions. This is
+ useful especially for parametrized tests when certain
+ configurations are expected-to-fail. In this case the
+ declarative approach with the @py.test.mark.xfail cannot
+ be used as it would mark all configurations as xfail.
+
+- issue102: introduce new --maxfail=NUM option to stop
+ test runs after NUM failures. This is a generalization
+ of the '-x' or '--exitfirst' option which is now equivalent
+ to '--maxfail=1'. Both '-x' and '--maxfail' will
+ now also print a line near the end indicating the Interruption.
+
+- issue89: allow py.test.mark decorators to be used on classes
+ (class decorators were introduced with python2.6) and
+ also allow to have multiple markers applied at class/module level
+ by specifying a list.
+
+- improve and refine letter reporting in the progress bar:
+ . pass
+ f failed test
+ s skipped tests (reminder: use for dependency/platform mismatch only)
+ x xfailed test (test that was expected to fail)
+ X xpassed test (test that was expected to fail but passed)
+
+ You can use any combination of 'fsxX' with the '-r' extended
+ reporting option. The xfail/xpass results will show up as
+ skipped tests in the junitxml output - which also fixes
+ issue99.
+
+- make py.test.cmdline.main() return the exitstatus instead of raising
+ SystemExit and also allow it to be called multiple times. This of
+ course requires that your application and tests are properly teared
+ down and don't have global state.
+
+Fixes / Maintenance
+++++++++++++++++++++++
+
+- improved traceback presentation:
+ - improved and unified reporting for "--tb=short" option
+ - Errors during test module imports are much shorter, (using --tb=short style)
+ - raises shows shorter more relevant tracebacks
+ - --fulltrace now more systematically makes traces longer / inhibits cutting
+
+- improve support for raises and other dynamically compiled code by
+ manipulating python's linecache.cache instead of the previous
+ rather hacky way of creating custom code objects. This makes
+ it seemlessly work on Jython and PyPy where it previously didn't.
+
+- fix issue96: make capturing more resilient against Control-C
+ interruptions (involved somewhat substantial refactoring
+ to the underlying capturing functionality to avoid race
+ conditions).
+
+- fix chaining of conditional skipif/xfail decorators - so it works now
+ as expected to use multiple @py.test.mark.skipif(condition) decorators,
+ including specific reporting which of the conditions lead to skipping.
+
+- fix issue95: late-import zlib so that it's not required
+ for general py.test startup.
+
+- fix issue94: make reporting more robust against bogus source code
+ (and internally be more careful when presenting unexpected byte sequences)
+
+
+Changes between 1.2.1 and 1.3.0
+==================================================
+
+- deprecate --report option in favour of a new shorter and easier to
+ remember -r option: it takes a string argument consisting of any
+ combination of 'xfsX' characters. They relate to the single chars
+ you see during the dotted progress printing and will print an extra line
+ per test at the end of the test run. This extra line indicates the exact
+ position or test ID that you directly paste to the py.test cmdline in order
+ to re-run a particular test.
+
+- allow external plugins to register new hooks via the new
+ pytest_addhooks(pluginmanager) hook. The new release of
+ the pytest-xdist plugin for distributed and looponfailing
+ testing requires this feature.
+
+- add a new pytest_ignore_collect(path, config) hook to allow projects and
+ plugins to define exclusion behaviour for their directory structure -
+ for example you may define in a conftest.py this method::
+
+ def pytest_ignore_collect(path):
+ return path.check(link=1)
+
+ to prevent even a collection try of any tests in symlinked dirs.
+
+- new pytest_pycollect_makemodule(path, parent) hook for
+ allowing customization of the Module collection object for a
+ matching test module.
+
+- extend and refine xfail mechanism:
+ ``@py.test.mark.xfail(run=False)`` do not run the decorated test
+ ``@py.test.mark.xfail(reason="...")`` prints the reason string in xfail summaries
+ specifiying ``--runxfail`` on command line virtually ignores xfail markers
+
+- expose (previously internal) commonly useful methods:
+ py.io.get_terminal_with() -> return terminal width
+ py.io.ansi_print(...) -> print colored/bold text on linux/win32
+ py.io.saferepr(obj) -> return limited representation string
+
+- expose test outcome related exceptions as py.test.skip.Exception,
+ py.test.raises.Exception etc., useful mostly for plugins
+ doing special outcome interpretation/tweaking
+
+- (issue85) fix junitxml plugin to handle tests with non-ascii output
+
+- fix/refine python3 compatibility (thanks Benjamin Peterson)
+
+- fixes for making the jython/win32 combination work, note however:
+ jython2.5.1/win32 does not provide a command line launcher, see
+ http://bugs.jython.org/issue1491 . See pylib install documentation
+ for how to work around.
+
+- fixes for handling of unicode exception values and unprintable objects
+
+- (issue87) fix unboundlocal error in assertionold code
+
+- (issue86) improve documentation for looponfailing
+
+- refine IO capturing: stdin-redirect pseudo-file now has a NOP close() method
+
+- ship distribute_setup.py version 0.6.10
+
+- added links to the new capturelog and coverage plugins
+
+
+Changes between 1.2.1 and 1.2.0
+=====================================
+
+- refined usage and options for "py.cleanup"::
+
+ py.cleanup # remove "*.pyc" and "*$py.class" (jython) files
+ py.cleanup -e .swp -e .cache # also remove files with these extensions
+ py.cleanup -s # remove "build" and "dist" directory next to setup.py files
+ py.cleanup -d # also remove empty directories
+ py.cleanup -a # synonym for "-s -d -e 'pip-log.txt'"
+ py.cleanup -n # dry run, only show what would be removed
+
+- add a new option "py.test --funcargs" which shows available funcargs
+ and their help strings (docstrings on their respective factory function)
+ for a given test path
+
+- display a short and concise traceback if a funcarg lookup fails
+
+- early-load "conftest.py" files in non-dot first-level sub directories.
+ allows to conveniently keep and access test-related options in a ``test``
+ subdir and still add command line options.
+
+- fix issue67: new super-short traceback-printing option: "--tb=line" will print a single line for each failing (python) test indicating its filename, lineno and the failure value
+
+- fix issue78: always call python-level teardown functions even if the
+ according setup failed. This includes refinements for calling setup_module/class functions
+ which will now only be called once instead of the previous behaviour where they'd be called
+ multiple times if they raise an exception (including a Skipped exception). Any exception
+ will be re-corded and associated with all tests in the according module/class scope.
+
+- fix issue63: assume <40 columns to be a bogus terminal width, default to 80
+
+- fix pdb debugging to be in the correct frame on raises-related errors
+
+- update apipkg.py to fix an issue where recursive imports might
+ unnecessarily break importing
+
+- fix plugin links
+
+Changes between 1.2 and 1.1.1
+=====================================
+
+- moved dist/looponfailing from py.test core into a new
+ separately released pytest-xdist plugin.
+
+- new junitxml plugin: --junitxml=path will generate a junit style xml file
+ which is processable e.g. by the Hudson CI system.
+
+- new option: --genscript=path will generate a standalone py.test script
+ which will not need any libraries installed. thanks to Ralf Schmitt.
+
+- new option: --ignore will prevent specified path from collection.
+ Can be specified multiple times.
+
+- new option: --confcutdir=dir will make py.test only consider conftest
+ files that are relative to the specified dir.
+
+- new funcarg: "pytestconfig" is the pytest config object for access
+ to command line args and can now be easily used in a test.
+
+- install 'py.test' and `py.which` with a ``-$VERSION`` suffix to
+ disambiguate between Python3, python2.X, Jython and PyPy installed versions.
+
+- new "pytestconfig" funcarg allows access to test config object
+
+- new "pytest_report_header" hook can return additional lines
+ to be displayed at the header of a test run.
+
+- (experimental) allow "py.test path::name1::name2::..." for pointing
+ to a test within a test collection directly. This might eventually
+ evolve as a full substitute to "-k" specifications.
+
+- streamlined plugin loading: order is now as documented in
+ customize.html: setuptools, ENV, commandline, conftest.
+ also setuptools entry point names are turned to canonical namees ("pytest_*")
+
+- automatically skip tests that need 'capfd' but have no os.dup
+
+- allow pytest_generate_tests to be defined in classes as well
+
+- deprecate usage of 'disabled' attribute in favour of pytestmark
+- deprecate definition of Directory, Module, Class and Function nodes
+ in conftest.py files. Use pytest collect hooks instead.
+
+- collection/item node specific runtest/collect hooks are only called exactly
+ on matching conftest.py files, i.e. ones which are exactly below
+ the filesystem path of an item
+
+- change: the first pytest_collect_directory hook to return something
+ will now prevent further hooks to be called.
+
+- change: figleaf plugin now requires --figleaf to run. Also
+ change its long command line options to be a bit shorter (see py.test -h).
+
+- change: pytest doctest plugin is now enabled by default and has a
+ new option --doctest-glob to set a pattern for file matches.
+
+- change: remove internal py._* helper vars, only keep py._pydir
+
+- robustify capturing to survive if custom pytest_runtest_setup
+ code failed and prevented the capturing setup code from running.
+
+- make py.test.* helpers provided by default plugins visible early -
+ works transparently both for pydoc and for interactive sessions
+ which will regularly see e.g. py.test.mark and py.test.importorskip.
+
+- simplify internal plugin manager machinery
+- simplify internal collection tree by introducing a RootCollector node
+
+- fix assert reinterpreation that sees a call containing "keyword=..."
+
+- fix issue66: invoke pytest_sessionstart and pytest_sessionfinish
+ hooks on slaves during dist-testing, report module/session teardown
+ hooks correctly.
+
+- fix issue65: properly handle dist-testing if no
+ execnet/py lib installed remotely.
+
+- skip some install-tests if no execnet is available
+
+- fix docs, fix internal bin/ script generation
+
+
+Changes between 1.1.1 and 1.1.0
+=====================================
+
+- introduce automatic plugin registration via 'pytest11'
+ entrypoints via setuptools' pkg_resources.iter_entry_points
+
+- fix py.test dist-testing to work with execnet >= 1.0.0b4
+
+- re-introduce py.test.cmdline.main() for better backward compatibility
+
+- svn paths: fix a bug with path.check(versioned=True) for svn paths,
+ allow '%' in svn paths, make svnwc.update() default to interactive mode
+ like in 1.0.x and add svnwc.update(interactive=False) to inhibit interaction.
+
+- refine distributed tarball to contain test and no pyc files
+
+- try harder to have deprecation warnings for py.compat.* accesses
+ report a correct location
+
+Changes between 1.1.0 and 1.0.2
+=====================================
+
+* adjust and improve docs
+
+* remove py.rest tool and internal namespace - it was
+ never really advertised and can still be used with
+ the old release if needed. If there is interest
+ it could be revived into its own tool i guess.
+
+* fix issue48 and issue59: raise an Error if the module
+ from an imported test file does not seem to come from
+ the filepath - avoids "same-name" confusion that has
+ been reported repeatedly
+
+* merged Ronny's nose-compatibility hacks: now
+ nose-style setup_module() and setup() functions are
+ supported
+
+* introduce generalized py.test.mark function marking
+
+* reshuffle / refine command line grouping
+
+* deprecate parser.addgroup in favour of getgroup which creates option group
+
+* add --report command line option that allows to control showing of skipped/xfailed sections
+
+* generalized skipping: a new way to mark python functions with skipif or xfail
+ at function, class and modules level based on platform or sys-module attributes.
+
+* extend py.test.mark decorator to allow for positional args
+
+* introduce and test "py.cleanup -d" to remove empty directories
+
+* fix issue #59 - robustify unittest test collection
+
+* make bpython/help interaction work by adding an __all__ attribute
+ to ApiModule, cleanup initpkg
+
+* use MIT license for pylib, add some contributors
+
+* remove py.execnet code and substitute all usages with 'execnet' proper
+
+* fix issue50 - cached_setup now caches more to expectations
+ for test functions with multiple arguments.
+
+* merge Jarko's fixes, issue #45 and #46
+
+* add the ability to specify a path for py.lookup to search in
+
+* fix a funcarg cached_setup bug probably only occuring
+ in distributed testing and "module" scope with teardown.
+
+* many fixes and changes for making the code base python3 compatible,
+ many thanks to Benjamin Peterson for helping with this.
+
+* consolidate builtins implementation to be compatible with >=2.3,
+ add helpers to ease keeping 2 and 3k compatible code
+
+* deprecate py.compat.doctest|subprocess|textwrap|optparse
+
+* deprecate py.magic.autopath, remove py/magic directory
+
+* move pytest assertion handling to py/code and a pytest_assertion
+ plugin, add "--no-assert" option, deprecate py.magic namespaces
+ in favour of (less) py.code ones.
+
+* consolidate and cleanup py/code classes and files
+
+* cleanup py/misc, move tests to bin-for-dist
+
+* introduce delattr/delitem/delenv methods to py.test's monkeypatch funcarg
+
+* consolidate py.log implementation, remove old approach.
+
+* introduce py.io.TextIO and py.io.BytesIO for distinguishing between
+ text/unicode and byte-streams (uses underlying standard lib io.*
+ if available)
+
+* make py.unittest_convert helper script available which converts "unittest.py"
+ style files into the simpler assert/direct-test-classes py.test/nosetests
+ style. The script was written by Laura Creighton.
+
+* simplified internal localpath implementation
+
+Changes between 1.0.1 and 1.0.2
+=====================================
+
+* fixing packaging issues, triggered by fedora redhat packaging,
+ also added doc, examples and contrib dirs to the tarball.
+
+* added a documentation link to the new django plugin.
+
+Changes between 1.0.0 and 1.0.1
+=====================================
+
+* added a 'pytest_nose' plugin which handles nose.SkipTest,
+ nose-style function/method/generator setup/teardown and
+ tries to report functions correctly.
+
+* capturing of unicode writes or encoded strings to sys.stdout/err
+ work better, also terminalwriting was adapted and somewhat
+ unified between windows and linux.
+
+* improved documentation layout and content a lot
+
+* added a "--help-config" option to show conftest.py / ENV-var names for
+ all longopt cmdline options, and some special conftest.py variables.
+ renamed 'conf_capture' conftest setting to 'option_capture' accordingly.
+
+* fix issue #27: better reporting on non-collectable items given on commandline
+ (e.g. pyc files)
+
+* fix issue #33: added --version flag (thanks Benjamin Peterson)
+
+* fix issue #32: adding support for "incomplete" paths to wcpath.status()
+
+* "Test" prefixed classes are *not* collected by default anymore if they
+ have an __init__ method
+
+* monkeypatch setenv() now accepts a "prepend" parameter
+
+* improved reporting of collection error tracebacks
+
+* simplified multicall mechanism and plugin architecture,
+ renamed some internal methods and argnames
+
+Changes between 1.0.0b9 and 1.0.0
+=====================================
+
+* more terse reporting try to show filesystem path relatively to current dir
+* improve xfail output a bit
+
+Changes between 1.0.0b8 and 1.0.0b9
+=====================================
+
+* cleanly handle and report final teardown of test setup
+
+* fix svn-1.6 compat issue with py.path.svnwc().versioned()
+ (thanks Wouter Vanden Hove)
+
+* setup/teardown or collection problems now show as ERRORs
+ or with big "E"'s in the progress lines. they are reported
+ and counted separately.
+
+* dist-testing: properly handle test items that get locally
+ collected but cannot be collected on the remote side - often
+ due to platform/dependency reasons
+
+* simplified py.test.mark API - see keyword plugin documentation
+
+* integrate better with logging: capturing now by default captures
+ test functions and their immediate setup/teardown in a single stream
+
+* capsys and capfd funcargs now have a readouterr() and a close() method
+ (underlyingly py.io.StdCapture/FD objects are used which grew a
+ readouterr() method as well to return snapshots of captured out/err)
+
+* make assert-reinterpretation work better with comparisons not
+ returning bools (reported with numpy from thanks maciej fijalkowski)
+
+* reworked per-test output capturing into the pytest_iocapture.py plugin
+ and thus removed capturing code from config object
+
+* item.repr_failure(excinfo) instead of item.repr_failure(excinfo, outerr)
+
+
+Changes between 1.0.0b7 and 1.0.0b8
+=====================================
+
+* pytest_unittest-plugin is now enabled by default
+
+* introduced pytest_keyboardinterrupt hook and
+ refined pytest_sessionfinish hooked, added tests.
+
+* workaround a buggy logging module interaction ("closing already closed
+ files"). Thanks to Sridhar Ratnakumar for triggering.
+
+* if plugins use "py.test.importorskip" for importing
+ a dependency only a warning will be issued instead
+ of exiting the testing process.
+
+* many improvements to docs:
+ - refined funcargs doc , use the term "factory" instead of "provider"
+ - added a new talk/tutorial doc page
+ - better download page
+ - better plugin docstrings
+ - added new plugins page and automatic doc generation script
+
+* fixed teardown problem related to partially failing funcarg setups
+ (thanks MrTopf for reporting), "pytest_runtest_teardown" is now
+ always invoked even if the "pytest_runtest_setup" failed.
+
+* tweaked doctest output for docstrings in py modules,
+ thanks Radomir.
+
+Changes between 1.0.0b3 and 1.0.0b7
+=============================================
+
+* renamed py.test.xfail back to py.test.mark.xfail to avoid
+ two ways to decorate for xfail
+
+* re-added py.test.mark decorator for setting keywords on functions
+ (it was actually documented so removing it was not nice)
+
+* remove scope-argument from request.addfinalizer() because
+ request.cached_setup has the scope arg. TOOWTDI.
+
+* perform setup finalization before reporting failures
+
+* apply modified patches from Andreas Kloeckner to allow
+ test functions to have no func_code (#22) and to make
+ "-k" and function keywords work (#20)
+
+* apply patch from Daniel Peolzleithner (issue #23)
+
+* resolve issue #18, multiprocessing.Manager() and
+ redirection clash
+
+* make __name__ == "__channelexec__" for remote_exec code
+
+Changes between 1.0.0b1 and 1.0.0b3
+=============================================
+
+* plugin classes are removed: one now defines
+ hooks directly in conftest.py or global pytest_*.py
+ files.
+
+* added new pytest_namespace(config) hook that allows
+ to inject helpers directly to the py.test.* namespace.
+
+* documented and refined many hooks
+
+* added new style of generative tests via
+ pytest_generate_tests hook that integrates
+ well with function arguments.
+
+
+Changes between 0.9.2 and 1.0.0b1
+=============================================
+
+* introduced new "funcarg" setup method,
+ see doc/test/funcarg.txt
+
+* introduced plugin architecuture and many
+ new py.test plugins, see
+ doc/test/plugins.txt
+
+* teardown_method is now guaranteed to get
+ called after a test method has run.
+
+* new method: py.test.importorskip(mod,minversion)
+ will either import or call py.test.skip()
+
+* completely revised internal py.test architecture
+
+* new py.process.ForkedFunc object allowing to
+ fork execution of a function to a sub process
+ and getting a result back.
+
+XXX lots of things missing here XXX
+
+Changes between 0.9.1 and 0.9.2
+===============================
+
+* refined installation and metadata, created new setup.py,
+ now based on setuptools/ez_setup (thanks to Ralf Schmitt
+ for his support).
+
+* improved the way of making py.* scripts available in
+ windows environments, they are now added to the
+ Scripts directory as ".cmd" files.
+
+* py.path.svnwc.status() now is more complete and
+ uses xml output from the 'svn' command if available
+ (Guido Wesdorp)
+
+* fix for py.path.svn* to work with svn 1.5
+ (Chris Lamb)
+
+* fix path.relto(otherpath) method on windows to
+ use normcase for checking if a path is relative.
+
+* py.test's traceback is better parseable from editors
+ (follows the filenames:LINENO: MSG convention)
+ (thanks to Osmo Salomaa)
+
+* fix to javascript-generation, "py.test --runbrowser"
+ should work more reliably now
+
+* removed previously accidentally added
+ py.test.broken and py.test.notimplemented helpers.
+
+* there now is a py.__version__ attribute
+
+Changes between 0.9.0 and 0.9.1
+===============================
+
+This is a fairly complete list of changes between 0.9 and 0.9.1, which can
+serve as a reference for developers.
+
+* allowing + signs in py.path.svn urls [39106]
+* fixed support for Failed exceptions without excinfo in py.test [39340]
+* added support for killing processes for Windows (as well as platforms that
+ support os.kill) in py.misc.killproc [39655]
+* added setup/teardown for generative tests to py.test [40702]
+* added detection of FAILED TO LOAD MODULE to py.test [40703, 40738, 40739]
+* fixed problem with calling .remove() on wcpaths of non-versioned files in
+ py.path [44248]
+* fixed some import and inheritance issues in py.test [41480, 44648, 44655]
+* fail to run greenlet tests when pypy is available, but without stackless
+ [45294]
+* small fixes in rsession tests [45295]
+* fixed issue with 2.5 type representations in py.test [45483, 45484]
+* made that internal reporting issues displaying is done atomically in py.test
+ [45518]
+* made that non-existing files are igored by the py.lookup script [45519]
+* improved exception name creation in py.test [45535]
+* made that less threads are used in execnet [merge in 45539]
+* removed lock required for atomical reporting issue displaying in py.test
+ [45545]
+* removed globals from execnet [45541, 45547]
+* refactored cleanup mechanics, made that setDaemon is set to 1 to make atexit
+ get called in 2.5 (py.execnet) [45548]
+* fixed bug in joining threads in py.execnet's servemain [45549]
+* refactored py.test.rsession tests to not rely on exact output format anymore
+ [45646]
+* using repr() on test outcome [45647]
+* added 'Reason' classes for py.test.skip() [45648, 45649]
+* killed some unnecessary sanity check in py.test.collect [45655]
+* avoid using os.tmpfile() in py.io.fdcapture because on Windows it's only
+ usable by Administrators [45901]
+* added support for locking and non-recursive commits to py.path.svnwc [45994]
+* locking files in py.execnet to prevent CPython from segfaulting [46010]
+* added export() method to py.path.svnurl
+* fixed -d -x in py.test [47277]
+* fixed argument concatenation problem in py.path.svnwc [49423]
+* restore py.test behaviour that it exits with code 1 when there are failures
+ [49974]
+* don't fail on html files that don't have an accompanying .txt file [50606]
+* fixed 'utestconvert.py < input' [50645]
+* small fix for code indentation in py.code.source [50755]
+* fix _docgen.py documentation building [51285]
+* improved checks for source representation of code blocks in py.test [51292]
+* added support for passing authentication to py.path.svn* objects [52000,
+ 52001]
+* removed sorted() call for py.apigen tests in favour of [].sort() to support
+ Python 2.3 [52481]
diff --git a/tests/wpt/web-platform-tests/tools/py/LICENSE b/tests/wpt/web-platform-tests/tools/third_party/py/LICENSE
index 31ecdfb1dbc..31ecdfb1dbc 100644
--- a/tests/wpt/web-platform-tests/tools/py/LICENSE
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/LICENSE
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/MANIFEST.in b/tests/wpt/web-platform-tests/tools/third_party/py/MANIFEST.in
new file mode 100644
index 00000000000..239ad2283e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/MANIFEST.in
@@ -0,0 +1,10 @@
+include CHANGELOG
+include AUTHORS
+include README.rst
+include setup.py
+include LICENSE
+include conftest.py
+include tox.ini
+graft doc
+graft testing
+global-exclude *.pyc
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/README.rst b/tests/wpt/web-platform-tests/tools/third_party/py/README.rst
new file mode 100644
index 00000000000..7092ae4c460
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/README.rst
@@ -0,0 +1,34 @@
+.. image:: https://img.shields.io/pypi/v/py.svg
+ :target: https://pypi.org/project/py
+
+.. image:: https://anaconda.org/conda-forge/py/badges/version.svg
+ :target: https://anaconda.org/conda-forge/py
+
+.. image:: https://img.shields.io/pypi/pyversions/pytest.svg
+ :target: https://pypi.org/project/py
+
+.. image:: https://img.shields.io/travis/pytest-dev/py.svg
+ :target: https://travis-ci.org/pytest-dev/py
+
+.. image:: https://ci.appveyor.com/api/projects/status/10keglan6uqwj5al/branch/master?svg=true
+ :target: https://ci.appveyor.com/project/pytestbot/py
+
+
+**NOTE**: this library is in **maintenance mode** and should not be used in new code.
+
+The py lib is a Python development support library featuring
+the following tools and modules:
+
+* ``py.path``: uniform local and svn path objects
+* ``py.apipkg``: explicit API control and lazy-importing
+* ``py.iniconfig``: easy parsing of .ini files
+* ``py.code``: dynamic code generation and introspection (deprecated, moved to ``pytest``).
+
+**NOTE**: prior to the 1.4 release this distribution used to
+contain py.test which is now its own package, see http://pytest.org
+
+For questions and more information please visit http://py.readthedocs.org
+
+Bugs and issues: https://github.com/pytest-dev/py
+
+Authors: Holger Krekel and others, 2004-2017
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/appveyor.yml b/tests/wpt/web-platform-tests/tools/third_party/py/appveyor.yml
new file mode 100644
index 00000000000..5fbeca9ab65
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/appveyor.yml
@@ -0,0 +1,26 @@
+environment:
+ matrix:
+ # note: please use "tox --listenvs" to populate the build matrix below
+ - TOXENV: "py27-pytest29"
+ - TOXENV: "py27-pytest30"
+ - TOXENV: "py27-pytest31"
+ - TOXENV: "py34-pytest29"
+ - TOXENV: "py34-pytest30"
+ - TOXENV: "py34-pytest31"
+ - TOXENV: "py35-pytest29"
+ - TOXENV: "py35-pytest30"
+ - TOXENV: "py35-pytest31"
+ - TOXENV: "py36-pytest29"
+ - TOXENV: "py36-pytest30"
+ - TOXENV: "py36-pytest31"
+
+install:
+ - echo Installed Pythons
+ - dir c:\Python*
+
+ - C:\Python36\python -m pip install --upgrade --pre tox
+
+build: false # Not a C# project, build stuff at the test step instead.
+
+test_script:
+ - C:\Python36\python -m tox
diff --git a/tests/wpt/web-platform-tests/tools/py/bench/localpath.py b/tests/wpt/web-platform-tests/tools/third_party/py/bench/localpath.py
index ad4fbd8e2bf..ad4fbd8e2bf 100644
--- a/tests/wpt/web-platform-tests/tools/py/bench/localpath.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/bench/localpath.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/conftest.py b/tests/wpt/web-platform-tests/tools/third_party/py/conftest.py
new file mode 100644
index 00000000000..5bff3fe0224
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/conftest.py
@@ -0,0 +1,60 @@
+import py
+import pytest
+import sys
+
+pytest_plugins = 'doctest', 'pytester'
+
+collect_ignore = ['build', 'doc/_build']
+
+
+def pytest_addoption(parser):
+ group = parser.getgroup("pylib", "py lib testing options")
+ group.addoption('--runslowtests',
+ action="store_true", dest="runslowtests", default=False,
+ help=("run slow tests"))
+
+@pytest.fixture
+def sshhost(request):
+ val = request.config.getvalue("sshhost")
+ if val:
+ return val
+ py.test.skip("need --sshhost option")
+
+
+# XXX copied from execnet's conftest.py - needs to be merged
+winpymap = {
+ 'python2.7': r'C:\Python27\python.exe',
+}
+
+
+def getexecutable(name, cache={}):
+ try:
+ return cache[name]
+ except KeyError:
+ executable = py.path.local.sysfind(name)
+ if executable:
+ if name == "jython":
+ import subprocess
+ popen = subprocess.Popen(
+ [str(executable), "--version"],
+ universal_newlines=True, stderr=subprocess.PIPE)
+ out, err = popen.communicate()
+ if not err or "2.5" not in err:
+ executable = None
+ cache[name] = executable
+ return executable
+
+
+@pytest.fixture(params=('python2.7', 'pypy-c', 'jython'))
+def anypython(request):
+ name = request.param
+ executable = getexecutable(name)
+ if executable is None:
+ if sys.platform == "win32":
+ executable = winpymap.get(name, None)
+ if executable:
+ executable = py.path.local(executable)
+ if executable.check():
+ return executable
+ py.test.skip("no %s found" % (name,))
+ return executable
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/Makefile b/tests/wpt/web-platform-tests/tools/third_party/py/doc/Makefile
index 0a0e89e01fe..0a0e89e01fe 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/Makefile
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/Makefile
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/_templates/layout.html b/tests/wpt/web-platform-tests/tools/third_party/py/doc/_templates/layout.html
index 683863aa460..683863aa460 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/_templates/layout.html
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/_templates/layout.html
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-0.9.0.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-0.9.0.txt
index 07109313543..07109313543 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-0.9.0.txt
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-0.9.0.txt
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-0.9.2.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-0.9.2.txt
index bc2d2ef2908..bc2d2ef2908 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-0.9.2.txt
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-0.9.2.txt
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.0.0.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.0.0.txt
index 7024255a195..7024255a195 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.0.0.txt
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.0.0.txt
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.0.1.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.0.1.txt
index 0c9f8760bdb..0c9f8760bdb 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.0.1.txt
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.0.1.txt
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.0.2.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.0.2.txt
index 23546195353..23546195353 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.0.2.txt
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.0.2.txt
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.1.0.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.1.0.txt
index 0441c3215eb..0441c3215eb 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.1.0.txt
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.1.0.txt
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.1.1.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.1.1.txt
index 83e6a1fd8d9..83e6a1fd8d9 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.1.1.txt
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.1.1.txt
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.2.0.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.2.0.txt
index 4f6a5614476..4f6a5614476 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.2.0.txt
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.2.0.txt
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.2.1.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.2.1.txt
index 5bf8ba22dc6..5bf8ba22dc6 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.2.1.txt
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.2.1.txt
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.0.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.3.0.txt
index cf97db0367a..cf97db0367a 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.0.txt
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.3.0.txt
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.1.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.3.1.txt
index 471de408a10..471de408a10 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.1.txt
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.3.1.txt
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.2.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.3.2.txt
index 599dfbed755..599dfbed755 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.2.txt
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.3.2.txt
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.3.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.3.3.txt
index c62cb859053..c62cb859053 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.3.txt
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.3.3.txt
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.4.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.3.4.txt
index c156c8bdb33..c156c8bdb33 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.3.4.txt
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.3.4.txt
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.4.0.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.4.0.txt
index 6f9a7714d9f..6f9a7714d9f 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.4.0.txt
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.4.0.txt
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.4.1.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.4.1.txt
index a5aa76b1438..a5aa76b1438 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/announce/release-1.4.1.txt
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/release-1.4.1.txt
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/announce/releases.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/releases.txt
index 309c29bac5d..309c29bac5d 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/announce/releases.txt
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/announce/releases.txt
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/changelog.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/changelog.txt
index 237daca3548..237daca3548 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/changelog.txt
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/changelog.txt
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/code.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/code.txt
index bdd8691da03..bdd8691da03 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/code.txt
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/code.txt
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/conf.py b/tests/wpt/web-platform-tests/tools/third_party/py/doc/conf.py
index de4cbf8a46f..de4cbf8a46f 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/conf.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/conf.py
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/download.html b/tests/wpt/web-platform-tests/tools/third_party/py/doc/download.html
index 5f4c466402d..5f4c466402d 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/download.html
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/download.html
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/example/genhtml.py b/tests/wpt/web-platform-tests/tools/third_party/py/doc/example/genhtml.py
index b5c8f525b62..b5c8f525b62 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/example/genhtml.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/example/genhtml.py
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/example/genhtmlcss.py b/tests/wpt/web-platform-tests/tools/third_party/py/doc/example/genhtmlcss.py
index 3e6d0af5454..3e6d0af5454 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/example/genhtmlcss.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/example/genhtmlcss.py
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/example/genxml.py b/tests/wpt/web-platform-tests/tools/third_party/py/doc/example/genxml.py
index 5f754e8897b..5f754e8897b 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/example/genxml.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/example/genxml.py
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/faq.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/faq.txt
index 52cb4b3fbd3..52cb4b3fbd3 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/faq.txt
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/faq.txt
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/img/pylib.png b/tests/wpt/web-platform-tests/tools/third_party/py/doc/img/pylib.png
index 2e10d438866..2e10d438866 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/img/pylib.png
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/img/pylib.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/doc/index.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/index.txt
new file mode 100644
index 00000000000..c700b17e987
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/index.txt
@@ -0,0 +1,39 @@
+.. py documentation master file, created by
+ sphinx-quickstart on Thu Oct 21 08:30:10 2010.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Welcome to py's documentation!
+=================================
+
+see :ref:`CHANGELOG <changelog>` for latest changes.
+
+.. _`pytest distribution`: http://pytest.org
+
+Contents:
+
+.. toctree::
+
+ install
+ path
+ code
+ io
+ log
+ xml
+ misc
+
+ :maxdepth: 2
+
+.. toctree::
+ :hidden:
+
+ announce/release-2.0.0
+ changelog
+ announce/*
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`search`
+
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/doc/install.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/install.txt
new file mode 100644
index 00000000000..fb4056d1fba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/install.txt
@@ -0,0 +1,88 @@
+
+.. _`py`:
+.. _`index page`: http://pypi.python.org/pypi/py/
+
+installation info in a nutshell
+===================================================
+
+**PyPI name**: py_
+
+**Pythons**: CPython 2.7, 3.4, 3.5, 3.6, PyPy-5.4
+
+**Operating systems**: Linux, Windows, OSX, Unix
+
+**Requirements**: setuptools_ or Distribute_
+
+**Installers**: ``easy_install`` and ``pip``
+
+**hg repository**: https://bitbucket.org/hpk42/py
+
+easy install or pip ``py``
+-----------------------------
+
+Both `Distribute`_ and setuptools_ provide the ``easy_install``
+installation tool with which you can type into a command line window::
+
+ easy_install -U py
+
+to install the latest release of the py lib. The ``-U`` switch
+will trigger an upgrade if you already have an older version installed.
+
+.. note::
+
+ As of version 1.4 py does not contain py.test anymore - you
+ need to install the new `pytest`_ distribution.
+
+.. _pytest: http://pytest.org
+
+Working from version control or a tarball
+-----------------------------------------------
+
+To follow development or start experiments, checkout the
+complete code and documentation source with mercurial_::
+
+ hg clone https://bitbucket.org/hpk42/py
+
+Development takes place on the 'trunk' branch.
+
+You can also go to the python package index and
+download and unpack a TAR file::
+
+ http://pypi.python.org/pypi/py/
+
+activating a checkout with setuptools
+--------------------------------------------
+
+With a working `Distribute`_ or setuptools_ installation you can type::
+
+ python setup.py develop
+
+in order to work inline with the tools and the lib of your checkout.
+
+.. _`no-setuptools`:
+
+.. _`directly use a checkout`:
+
+.. _`setuptools`: http://pypi.python.org/pypi/setuptools
+
+
+Mailing list and issue tracker
+--------------------------------------
+
+- `py-dev developers list`_ and `commit mailing list`_.
+
+- #pylib on irc.freenode.net IRC channel for random questions.
+
+- `bitbucket issue tracker`_ use this bitbucket issue tracker to report
+ bugs or request features.
+
+.. _`bitbucket issue tracker`: http://bitbucket.org/hpk42/py/issues/
+
+.. _codespeak: http://codespeak.net/
+.. _`py-dev`:
+.. _`development mailing list`:
+.. _`py-dev developers list`: http://codespeak.net/mailman/listinfo/py-dev
+.. _`py-svn`:
+.. _`commit mailing list`: http://codespeak.net/mailman/listinfo/py-svn
+
+.. include:: links.inc
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/io.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/io.txt
index c11308a6d28..c11308a6d28 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/io.txt
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/io.txt
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/links.inc b/tests/wpt/web-platform-tests/tools/third_party/py/doc/links.inc
index 9bcfe5cf85c..9bcfe5cf85c 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/links.inc
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/links.inc
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/log.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/log.txt
index ca60fcac250..ca60fcac250 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/log.txt
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/log.txt
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/doc/misc.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/misc.txt
new file mode 100644
index 00000000000..4b453482757
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/misc.txt
@@ -0,0 +1,93 @@
+====================================
+Miscellaneous features of the py lib
+====================================
+
+Mapping the standard python library into py
+===========================================
+
+The ``py.std`` object allows lazy access to
+standard library modules. For example, to get to the print-exception
+functionality of the standard library you can write::
+
+ py.std.traceback.print_exc()
+
+without having to do anything else than the usual ``import py``
+at the beginning. You can access any other top-level standard
+library module this way. This means that you will only trigger
+imports of modules that are actually needed. Note that no attempt
+is made to import submodules.
+
+Support for interaction with system utilities/binaries
+======================================================
+
+Currently, the py lib offers two ways to interact with
+system executables. ``py.process.cmdexec()`` invokes
+the shell in order to execute a string. The other
+one, ``py.path.local``'s 'sysexec()' method lets you
+directly execute a binary.
+
+Both approaches will raise an exception in case of a return-
+code other than 0 and otherwise return the stdout-output
+of the child process.
+
+The shell based approach
+------------------------
+
+You can execute a command via your system shell
+by doing something like::
+
+ out = py.process.cmdexec('ls -v')
+
+However, the ``cmdexec`` approach has a few shortcomings:
+
+- it relies on the underlying system shell
+- it neccessitates shell-escaping for expressing arguments
+- it does not easily allow to "fix" the binary you want to run.
+- it only allows to execute executables from the local
+ filesystem
+
+.. _sysexec:
+
+local paths have ``sysexec``
+----------------------------
+
+In order to synchronously execute an executable file you
+can use ``sysexec``::
+
+ binsvn.sysexec('ls', 'http://codespeak.net/svn')
+
+where ``binsvn`` is a path that points to the ``svn`` commandline
+binary. Note that this function does not offer any shell-escaping
+so you have to pass in already separated arguments.
+
+finding an executable local path
+--------------------------------
+
+Finding an executable is quite different on multiple platforms.
+Currently, the ``PATH`` environment variable based search on
+unix platforms is supported::
+
+ py.path.local.sysfind('svn')
+
+which returns the first path whose ``basename`` matches ``svn``.
+In principle, `sysfind` deploys platform specific algorithms
+to perform the search. On Windows, for example, it may look
+at the registry (XXX).
+
+To make the story complete, we allow to pass in a second ``checker``
+argument that is called for each found executable. For example, if
+you have multiple binaries available you may want to select the
+right version::
+
+ def mysvn(p):
+ """ check that the given svn binary has version 1.1. """
+ line = p.execute('--version'').readlines()[0]
+ if line.find('version 1.1'):
+ return p
+ binsvn = py.path.local.sysfind('svn', checker=mysvn)
+
+
+Cross-Python Version compatibility helpers
+=============================================
+
+The ``py.builtin`` namespace provides a number of helpers that help to write python code compatible across Python interpreters, mainly Python2 and Python3. Type ``help(py.builtin)`` on a Python prompt for the selection of builtins.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/doc/path.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/path.txt
new file mode 100644
index 00000000000..c906179099a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/path.txt
@@ -0,0 +1,258 @@
+=======
+py.path
+=======
+
+The 'py' lib provides a uniform high-level api to deal with filesystems
+and filesystem-like interfaces: ``py.path``. It aims to offer a central
+object to fs-like object trees (reading from and writing to files, adding
+files/directories, examining the types and structure, etc.), and out-of-the-box
+provides a number of implementations of this API.
+
+py.path.local - local file system path
+===============================================
+
+.. _`local`:
+
+basic interactive example
+-------------------------------------
+
+The first and most obvious of the implementations is a wrapper around a local
+filesystem. It's just a bit nicer in usage than the regular Python APIs, and
+of course all the functionality is bundled together rather than spread over a
+number of modules.
+
+
+.. sourcecode:: pycon
+
+ >>> import py
+ >>> temppath = py.path.local('py.path_documentation')
+ >>> foopath = temppath.join('foo') # get child 'foo' (lazily)
+ >>> foopath.check() # check if child 'foo' exists
+ False
+ >>> foopath.write('bar') # write some data to it
+ >>> foopath.check()
+ True
+ >>> foopath.read()
+ 'bar'
+ >>> foofile = foopath.open() # return a 'real' file object
+ >>> foofile.read(1)
+ 'b'
+
+reference documentation
+---------------------------------
+
+.. autoclass:: py._path.local.LocalPath
+ :members:
+ :inherited-members:
+
+``py.path.svnurl`` and ``py.path.svnwc``
+==================================================
+
+Two other ``py.path`` implementations that the py lib provides wrap the
+popular `Subversion`_ revision control system: the first (called 'svnurl')
+by interfacing with a remote server, the second by wrapping a local checkout.
+Both allow you to access relatively advanced features such as metadata and
+versioning, and both in a way more user-friendly manner than existing other
+solutions.
+
+Some example usage of ``py.path.svnurl``:
+
+.. sourcecode:: pycon
+
+ .. >>> import py
+ .. >>> if not py.test.config.option.urlcheck: raise ValueError('skipchunk')
+ >>> url = py.path.svnurl('http://codespeak.net/svn/py')
+ >>> info = url.info()
+ >>> info.kind
+ 'dir'
+ >>> firstentry = url.log()[-1]
+ >>> import time
+ >>> time.strftime('%Y-%m-%d', time.gmtime(firstentry.date))
+ '2004-10-02'
+
+Example usage of ``py.path.svnwc``:
+
+.. sourcecode:: pycon
+
+ .. >>> if not py.test.config.option.urlcheck: raise ValueError('skipchunk')
+ >>> temp = py.path.local('py.path_documentation')
+ >>> wc = py.path.svnwc(temp.join('svnwc'))
+ >>> wc.checkout('http://codespeak.net/svn/py/dist/py/path/local')
+ >>> wc.join('local.py').check()
+ True
+
+.. _`Subversion`: http://subversion.tigris.org/
+
+svn path related API reference
+-----------------------------------------
+
+.. autoclass:: py._path.svnwc.SvnWCCommandPath
+ :members:
+ :inherited-members:
+
+.. autoclass:: py._path.svnurl.SvnCommandPath
+ :members:
+ :inherited-members:
+
+.. autoclass:: py._path.svnwc.SvnAuth
+ :members:
+ :inherited-members:
+
+Common vs. specific API, Examples
+========================================
+
+All Path objects support a common set of operations, suitable
+for many use cases and allowing to transparently switch the
+path object within an application (e.g. from "local" to "svnwc").
+The common set includes functions such as `path.read()` to read all data
+from a file, `path.write()` to write data, `path.listdir()` to get a list
+of directory entries, `path.check()` to check if a node exists
+and is of a particular type, `path.join()` to get
+to a (grand)child, `path.visit()` to recursively walk through a node's
+children, etc. Only things that are not common on 'normal' filesystems (yet),
+such as handling metadata (e.g. the Subversion "properties") require
+using specific APIs.
+
+A quick 'cookbook' of small examples that will be useful 'in real life',
+which also presents parts of the 'common' API, and shows some non-common
+methods:
+
+Searching `.txt` files
+--------------------------------
+
+Search for a particular string inside all files with a .txt extension in a
+specific directory.
+
+.. sourcecode:: pycon
+
+ >>> dirpath = temppath.ensure('testdir', dir=True)
+ >>> dirpath.join('textfile1.txt').write('foo bar baz')
+ >>> dirpath.join('textfile2.txt').write('frob bar spam eggs')
+ >>> subdir = dirpath.ensure('subdir', dir=True)
+ >>> subdir.join('textfile1.txt').write('foo baz')
+ >>> subdir.join('textfile2.txt').write('spam eggs spam foo bar spam')
+ >>> results = []
+ >>> for fpath in dirpath.visit('*.txt'):
+ ... if 'bar' in fpath.read():
+ ... results.append(fpath.basename)
+ >>> results.sort()
+ >>> results
+ ['textfile1.txt', 'textfile2.txt', 'textfile2.txt']
+
+Working with Paths
+----------------------------
+
+This example shows the ``py.path`` features to deal with
+filesystem paths Note that the filesystem is never touched,
+all operations are performed on a string level (so the paths
+don't have to exist, either):
+
+.. sourcecode:: pycon
+
+ >>> p1 = py.path.local('/foo/bar')
+ >>> p2 = p1.join('baz/qux')
+ >>> p2 == py.path.local('/foo/bar/baz/qux')
+ True
+ >>> sep = py.path.local.sep
+ >>> p2.relto(p1).replace(sep, '/') # os-specific path sep in the string
+ 'baz/qux'
+ >>> p2.bestrelpath(p1).replace(sep, '/')
+ '../..'
+ >>> p2.join(p2.bestrelpath(p1)) == p1
+ True
+ >>> p3 = p1 / 'baz/qux' # the / operator allows joining, too
+ >>> p2 == p3
+ True
+ >>> p4 = p1 + ".py"
+ >>> p4.basename == "bar.py"
+ True
+ >>> p4.ext == ".py"
+ True
+ >>> p4.purebasename == "bar"
+ True
+
+This should be possible on every implementation of ``py.path``, so
+regardless of whether the implementation wraps a UNIX filesystem, a Windows
+one, or a database or object tree, these functions should be available (each
+with their own notion of path seperators and dealing with conversions, etc.).
+
+Checking path types
+-------------------------------
+
+Now we will show a bit about the powerful 'check()' method on paths, which
+allows you to check whether a file exists, what type it is, etc.:
+
+.. sourcecode:: pycon
+
+ >>> file1 = temppath.join('file1')
+ >>> file1.check() # does it exist?
+ False
+ >>> file1 = file1.ensure(file=True) # 'touch' the file
+ >>> file1.check()
+ True
+ >>> file1.check(dir=True) # is it a dir?
+ False
+ >>> file1.check(file=True) # or a file?
+ True
+ >>> file1.check(ext='.txt') # check the extension
+ False
+ >>> textfile = temppath.ensure('text.txt', file=True)
+ >>> textfile.check(ext='.txt')
+ True
+ >>> file1.check(basename='file1') # we can use all the path's properties here
+ True
+
+Setting svn-properties
+--------------------------------
+
+As an example of 'uncommon' methods, we'll show how to read and write
+properties in an ``py.path.svnwc`` instance:
+
+.. sourcecode:: pycon
+
+ .. >>> if not py.test.config.option.urlcheck: raise ValueError('skipchunk')
+ >>> wc.propget('foo')
+ ''
+ >>> wc.propset('foo', 'bar')
+ >>> wc.propget('foo')
+ 'bar'
+ >>> len(wc.status().prop_modified) # our own props
+ 1
+ >>> msg = wc.revert() # roll back our changes
+ >>> len(wc.status().prop_modified)
+ 0
+
+SVN authentication
+----------------------------
+
+Some uncommon functionality can also be provided as extensions, such as SVN
+authentication:
+
+.. sourcecode:: pycon
+
+ .. >>> if not py.test.config.option.urlcheck: raise ValueError('skipchunk')
+ >>> auth = py.path.SvnAuth('anonymous', 'user', cache_auth=False,
+ ... interactive=False)
+ >>> wc.auth = auth
+ >>> wc.update() # this should work
+ >>> path = wc.ensure('thisshouldnotexist.txt')
+ >>> try:
+ ... path.commit('testing')
+ ... except py.process.cmdexec.Error, e:
+ ... pass
+ >>> 'authorization failed' in str(e)
+ True
+
+Known problems / limitations
+===================================
+
+* The SVN path objects require the "svn" command line,
+ there is currently no support for python bindings.
+ Parsing the svn output can lead to problems, particularly
+ regarding if you have a non-english "locales" setting.
+
+* While the path objects basically work on windows,
+ there is no attention yet on making unicode paths
+ work or deal with the famous "8.3" filename issues.
+
+
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/style.css b/tests/wpt/web-platform-tests/tools/third_party/py/doc/style.css
index 1faf762c715..1faf762c715 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/style.css
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/style.css
diff --git a/tests/wpt/web-platform-tests/tools/py/doc/xml.txt b/tests/wpt/web-platform-tests/tools/third_party/py/doc/xml.txt
index 1022de6e912..1022de6e912 100644
--- a/tests/wpt/web-platform-tests/tools/py/doc/xml.txt
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/doc/xml.txt
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/__init__.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/__init__.py
new file mode 100644
index 00000000000..b5e0c1630c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/__init__.py
@@ -0,0 +1,154 @@
+"""
+pylib: rapid testing and development utils
+
+this module uses apipkg.py for lazy-loading sub modules
+and classes. The initpkg-dictionary below specifies
+name->value mappings where value can be another namespace
+dictionary or an import path.
+
+(c) Holger Krekel and others, 2004-2014
+"""
+__version__ = '1.5.2'
+
+try:
+ from py._vendored_packages import apipkg
+ lib_not_mangled_by_packagers = True
+ vendor_prefix = '._vendored_packages.'
+except ImportError:
+ import apipkg
+ lib_not_mangled_by_packagers = False
+ vendor_prefix = ''
+
+# so that py.error.* instances are picklable
+import sys
+
+apipkg.initpkg(__name__, attr={'_apipkg': apipkg}, exportdefs={
+ # access to all standard lib modules
+ 'std': '._std:std',
+ # access to all posix errno's as classes
+ 'error': '._error:error',
+
+ '_pydir' : '.__metainfo:pydir',
+ 'version': 'py:__version__', # backward compatibility
+
+ # pytest-2.0 has a flat namespace, we use alias modules
+ # to keep old references compatible
+ 'test' : 'pytest',
+
+ # hook into the top-level standard library
+ 'process' : {
+ '__doc__' : '._process:__doc__',
+ 'cmdexec' : '._process.cmdexec:cmdexec',
+ 'kill' : '._process.killproc:kill',
+ 'ForkedFunc' : '._process.forkedfunc:ForkedFunc',
+ },
+
+ 'apipkg' : {
+ 'initpkg' : vendor_prefix + 'apipkg:initpkg',
+ 'ApiModule' : vendor_prefix + 'apipkg:ApiModule',
+ },
+
+ 'iniconfig' : {
+ 'IniConfig' : vendor_prefix + 'iniconfig:IniConfig',
+ 'ParseError' : vendor_prefix + 'iniconfig:ParseError',
+ },
+
+ 'path' : {
+ '__doc__' : '._path:__doc__',
+ 'svnwc' : '._path.svnwc:SvnWCCommandPath',
+ 'svnurl' : '._path.svnurl:SvnCommandPath',
+ 'local' : '._path.local:LocalPath',
+ 'SvnAuth' : '._path.svnwc:SvnAuth',
+ },
+
+ # python inspection/code-generation API
+ 'code' : {
+ '__doc__' : '._code:__doc__',
+ 'compile' : '._code.source:compile_',
+ 'Source' : '._code.source:Source',
+ 'Code' : '._code.code:Code',
+ 'Frame' : '._code.code:Frame',
+ 'ExceptionInfo' : '._code.code:ExceptionInfo',
+ 'Traceback' : '._code.code:Traceback',
+ 'getfslineno' : '._code.source:getfslineno',
+ 'getrawcode' : '._code.code:getrawcode',
+ 'patch_builtins' : '._code.code:patch_builtins',
+ 'unpatch_builtins' : '._code.code:unpatch_builtins',
+ '_AssertionError' : '._code.assertion:AssertionError',
+ '_reinterpret_old' : '._code.assertion:reinterpret_old',
+ '_reinterpret' : '._code.assertion:reinterpret',
+ '_reprcompare' : '._code.assertion:_reprcompare',
+ '_format_explanation' : '._code.assertion:_format_explanation',
+ },
+
+ # backports and additions of builtins
+ 'builtin' : {
+ '__doc__' : '._builtin:__doc__',
+ 'enumerate' : '._builtin:enumerate',
+ 'reversed' : '._builtin:reversed',
+ 'sorted' : '._builtin:sorted',
+ 'any' : '._builtin:any',
+ 'all' : '._builtin:all',
+ 'set' : '._builtin:set',
+ 'frozenset' : '._builtin:frozenset',
+ 'BaseException' : '._builtin:BaseException',
+ 'GeneratorExit' : '._builtin:GeneratorExit',
+ '_sysex' : '._builtin:_sysex',
+ 'print_' : '._builtin:print_',
+ '_reraise' : '._builtin:_reraise',
+ '_tryimport' : '._builtin:_tryimport',
+ 'exec_' : '._builtin:exec_',
+ '_basestring' : '._builtin:_basestring',
+ '_totext' : '._builtin:_totext',
+ '_isbytes' : '._builtin:_isbytes',
+ '_istext' : '._builtin:_istext',
+ '_getimself' : '._builtin:_getimself',
+ '_getfuncdict' : '._builtin:_getfuncdict',
+ '_getcode' : '._builtin:_getcode',
+ 'builtins' : '._builtin:builtins',
+ 'execfile' : '._builtin:execfile',
+ 'callable' : '._builtin:callable',
+ 'bytes' : '._builtin:bytes',
+ 'text' : '._builtin:text',
+ },
+
+ # input-output helping
+ 'io' : {
+ '__doc__' : '._io:__doc__',
+ 'dupfile' : '._io.capture:dupfile',
+ 'TextIO' : '._io.capture:TextIO',
+ 'BytesIO' : '._io.capture:BytesIO',
+ 'FDCapture' : '._io.capture:FDCapture',
+ 'StdCapture' : '._io.capture:StdCapture',
+ 'StdCaptureFD' : '._io.capture:StdCaptureFD',
+ 'TerminalWriter' : '._io.terminalwriter:TerminalWriter',
+ 'ansi_print' : '._io.terminalwriter:ansi_print',
+ 'get_terminal_width' : '._io.terminalwriter:get_terminal_width',
+ 'saferepr' : '._io.saferepr:saferepr',
+ },
+
+ # small and mean xml/html generation
+ 'xml' : {
+ '__doc__' : '._xmlgen:__doc__',
+ 'html' : '._xmlgen:html',
+ 'Tag' : '._xmlgen:Tag',
+ 'raw' : '._xmlgen:raw',
+ 'Namespace' : '._xmlgen:Namespace',
+ 'escape' : '._xmlgen:escape',
+ },
+
+ 'log' : {
+ # logging API ('producers' and 'consumers' connected via keywords)
+ '__doc__' : '._log:__doc__',
+ '_apiwarn' : '._log.warning:_apiwarn',
+ 'Producer' : '._log.log:Producer',
+ 'setconsumer' : '._log.log:setconsumer',
+ '_setstate' : '._log.log:setstate',
+ '_getstate' : '._log.log:getstate',
+ 'Path' : '._log.log:Path',
+ 'STDOUT' : '._log.log:STDOUT',
+ 'STDERR' : '._log.log:STDERR',
+ 'Syslog' : '._log.log:Syslog',
+ },
+
+})
diff --git a/tests/wpt/web-platform-tests/tools/py/py/__metainfo.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/__metainfo.py
index 12581eb7afb..12581eb7afb 100644
--- a/tests/wpt/web-platform-tests/tools/py/py/__metainfo.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/__metainfo.py
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_builtin.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_builtin.py
index 52ee9d79cad..52ee9d79cad 100644
--- a/tests/wpt/web-platform-tests/tools/py/py/_builtin.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_builtin.py
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_code/__init__.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_code/__init__.py
index f15acf85132..f15acf85132 100644
--- a/tests/wpt/web-platform-tests/tools/py/py/_code/__init__.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_code/__init__.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_code/_assertionnew.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_code/_assertionnew.py
new file mode 100644
index 00000000000..d03f29d8708
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_code/_assertionnew.py
@@ -0,0 +1,322 @@
+"""
+Find intermediate evalutation results in assert statements through builtin AST.
+This should replace _assertionold.py eventually.
+"""
+
+import sys
+import ast
+
+import py
+from py._code.assertion import _format_explanation, BuiltinAssertionError
+
+
+def _is_ast_expr(node):
+ return isinstance(node, ast.expr)
+def _is_ast_stmt(node):
+ return isinstance(node, ast.stmt)
+
+
+class Failure(Exception):
+ """Error found while interpreting AST."""
+
+ def __init__(self, explanation=""):
+ self.cause = sys.exc_info()
+ self.explanation = explanation
+
+
+def interpret(source, frame, should_fail=False):
+ mod = ast.parse(source)
+ visitor = DebugInterpreter(frame)
+ try:
+ visitor.visit(mod)
+ except Failure:
+ failure = sys.exc_info()[1]
+ return getfailure(failure)
+ if should_fail:
+ return ("(assertion failed, but when it was re-run for "
+ "printing intermediate values, it did not fail. Suggestions: "
+ "compute assert expression before the assert or use --no-assert)")
+
+def run(offending_line, frame=None):
+ if frame is None:
+ frame = py.code.Frame(sys._getframe(1))
+ return interpret(offending_line, frame)
+
+def getfailure(failure):
+ explanation = _format_explanation(failure.explanation)
+ value = failure.cause[1]
+ if str(value):
+ lines = explanation.splitlines()
+ if not lines:
+ lines.append("")
+ lines[0] += " << %s" % (value,)
+ explanation = "\n".join(lines)
+ text = "%s: %s" % (failure.cause[0].__name__, explanation)
+ if text.startswith("AssertionError: assert "):
+ text = text[16:]
+ return text
+
+
+operator_map = {
+ ast.BitOr : "|",
+ ast.BitXor : "^",
+ ast.BitAnd : "&",
+ ast.LShift : "<<",
+ ast.RShift : ">>",
+ ast.Add : "+",
+ ast.Sub : "-",
+ ast.Mult : "*",
+ ast.Div : "/",
+ ast.FloorDiv : "//",
+ ast.Mod : "%",
+ ast.Eq : "==",
+ ast.NotEq : "!=",
+ ast.Lt : "<",
+ ast.LtE : "<=",
+ ast.Gt : ">",
+ ast.GtE : ">=",
+ ast.Pow : "**",
+ ast.Is : "is",
+ ast.IsNot : "is not",
+ ast.In : "in",
+ ast.NotIn : "not in"
+}
+
+unary_map = {
+ ast.Not : "not %s",
+ ast.Invert : "~%s",
+ ast.USub : "-%s",
+ ast.UAdd : "+%s"
+}
+
+
+class DebugInterpreter(ast.NodeVisitor):
+ """Interpret AST nodes to gleam useful debugging information. """
+
+ def __init__(self, frame):
+ self.frame = frame
+
+ def generic_visit(self, node):
+ # Fallback when we don't have a special implementation.
+ if _is_ast_expr(node):
+ mod = ast.Expression(node)
+ co = self._compile(mod)
+ try:
+ result = self.frame.eval(co)
+ except Exception:
+ raise Failure()
+ explanation = self.frame.repr(result)
+ return explanation, result
+ elif _is_ast_stmt(node):
+ mod = ast.Module([node])
+ co = self._compile(mod, "exec")
+ try:
+ self.frame.exec_(co)
+ except Exception:
+ raise Failure()
+ return None, None
+ else:
+ raise AssertionError("can't handle %s" %(node,))
+
+ def _compile(self, source, mode="eval"):
+ return compile(source, "<assertion interpretation>", mode)
+
+ def visit_Expr(self, expr):
+ return self.visit(expr.value)
+
+ def visit_Module(self, mod):
+ for stmt in mod.body:
+ self.visit(stmt)
+
+ def visit_Name(self, name):
+ explanation, result = self.generic_visit(name)
+ # See if the name is local.
+ source = "%r in locals() is not globals()" % (name.id,)
+ co = self._compile(source)
+ try:
+ local = self.frame.eval(co)
+ except Exception:
+ # have to assume it isn't
+ local = False
+ if not local:
+ return name.id, result
+ return explanation, result
+
+ def visit_Compare(self, comp):
+ left = comp.left
+ left_explanation, left_result = self.visit(left)
+ for op, next_op in zip(comp.ops, comp.comparators):
+ next_explanation, next_result = self.visit(next_op)
+ op_symbol = operator_map[op.__class__]
+ explanation = "%s %s %s" % (left_explanation, op_symbol,
+ next_explanation)
+ source = "__exprinfo_left %s __exprinfo_right" % (op_symbol,)
+ co = self._compile(source)
+ try:
+ result = self.frame.eval(co, __exprinfo_left=left_result,
+ __exprinfo_right=next_result)
+ except Exception:
+ raise Failure(explanation)
+ try:
+ if not result:
+ break
+ except KeyboardInterrupt:
+ raise
+ except:
+ break
+ left_explanation, left_result = next_explanation, next_result
+
+ rcomp = py.code._reprcompare
+ if rcomp:
+ res = rcomp(op_symbol, left_result, next_result)
+ if res:
+ explanation = res
+ return explanation, result
+
+ def visit_BoolOp(self, boolop):
+ is_or = isinstance(boolop.op, ast.Or)
+ explanations = []
+ for operand in boolop.values:
+ explanation, result = self.visit(operand)
+ explanations.append(explanation)
+ if result == is_or:
+ break
+ name = is_or and " or " or " and "
+ explanation = "(" + name.join(explanations) + ")"
+ return explanation, result
+
+ def visit_UnaryOp(self, unary):
+ pattern = unary_map[unary.op.__class__]
+ operand_explanation, operand_result = self.visit(unary.operand)
+ explanation = pattern % (operand_explanation,)
+ co = self._compile(pattern % ("__exprinfo_expr",))
+ try:
+ result = self.frame.eval(co, __exprinfo_expr=operand_result)
+ except Exception:
+ raise Failure(explanation)
+ return explanation, result
+
+ def visit_BinOp(self, binop):
+ left_explanation, left_result = self.visit(binop.left)
+ right_explanation, right_result = self.visit(binop.right)
+ symbol = operator_map[binop.op.__class__]
+ explanation = "(%s %s %s)" % (left_explanation, symbol,
+ right_explanation)
+ source = "__exprinfo_left %s __exprinfo_right" % (symbol,)
+ co = self._compile(source)
+ try:
+ result = self.frame.eval(co, __exprinfo_left=left_result,
+ __exprinfo_right=right_result)
+ except Exception:
+ raise Failure(explanation)
+ return explanation, result
+
+ def visit_Call(self, call):
+ func_explanation, func = self.visit(call.func)
+ arg_explanations = []
+ ns = {"__exprinfo_func" : func}
+ arguments = []
+ for arg in call.args:
+ arg_explanation, arg_result = self.visit(arg)
+ arg_name = "__exprinfo_%s" % (len(ns),)
+ ns[arg_name] = arg_result
+ arguments.append(arg_name)
+ arg_explanations.append(arg_explanation)
+ for keyword in call.keywords:
+ arg_explanation, arg_result = self.visit(keyword.value)
+ arg_name = "__exprinfo_%s" % (len(ns),)
+ ns[arg_name] = arg_result
+ keyword_source = "%s=%%s" % (keyword.arg)
+ arguments.append(keyword_source % (arg_name,))
+ arg_explanations.append(keyword_source % (arg_explanation,))
+ if call.starargs:
+ arg_explanation, arg_result = self.visit(call.starargs)
+ arg_name = "__exprinfo_star"
+ ns[arg_name] = arg_result
+ arguments.append("*%s" % (arg_name,))
+ arg_explanations.append("*%s" % (arg_explanation,))
+ if call.kwargs:
+ arg_explanation, arg_result = self.visit(call.kwargs)
+ arg_name = "__exprinfo_kwds"
+ ns[arg_name] = arg_result
+ arguments.append("**%s" % (arg_name,))
+ arg_explanations.append("**%s" % (arg_explanation,))
+ args_explained = ", ".join(arg_explanations)
+ explanation = "%s(%s)" % (func_explanation, args_explained)
+ args = ", ".join(arguments)
+ source = "__exprinfo_func(%s)" % (args,)
+ co = self._compile(source)
+ try:
+ result = self.frame.eval(co, **ns)
+ except Exception:
+ raise Failure(explanation)
+ pattern = "%s\n{%s = %s\n}"
+ rep = self.frame.repr(result)
+ explanation = pattern % (rep, rep, explanation)
+ return explanation, result
+
+ def _is_builtin_name(self, name):
+ pattern = "%r not in globals() and %r not in locals()"
+ source = pattern % (name.id, name.id)
+ co = self._compile(source)
+ try:
+ return self.frame.eval(co)
+ except Exception:
+ return False
+
+ def visit_Attribute(self, attr):
+ if not isinstance(attr.ctx, ast.Load):
+ return self.generic_visit(attr)
+ source_explanation, source_result = self.visit(attr.value)
+ explanation = "%s.%s" % (source_explanation, attr.attr)
+ source = "__exprinfo_expr.%s" % (attr.attr,)
+ co = self._compile(source)
+ try:
+ result = self.frame.eval(co, __exprinfo_expr=source_result)
+ except Exception:
+ raise Failure(explanation)
+ explanation = "%s\n{%s = %s.%s\n}" % (self.frame.repr(result),
+ self.frame.repr(result),
+ source_explanation, attr.attr)
+ # Check if the attr is from an instance.
+ source = "%r in getattr(__exprinfo_expr, '__dict__', {})"
+ source = source % (attr.attr,)
+ co = self._compile(source)
+ try:
+ from_instance = self.frame.eval(co, __exprinfo_expr=source_result)
+ except Exception:
+ from_instance = True
+ if from_instance:
+ rep = self.frame.repr(result)
+ pattern = "%s\n{%s = %s\n}"
+ explanation = pattern % (rep, rep, explanation)
+ return explanation, result
+
+ def visit_Assert(self, assrt):
+ test_explanation, test_result = self.visit(assrt.test)
+ if test_explanation.startswith("False\n{False =") and \
+ test_explanation.endswith("\n"):
+ test_explanation = test_explanation[15:-2]
+ explanation = "assert %s" % (test_explanation,)
+ if not test_result:
+ try:
+ raise BuiltinAssertionError
+ except Exception:
+ raise Failure(explanation)
+ return explanation, test_result
+
+ def visit_Assign(self, assign):
+ value_explanation, value_result = self.visit(assign.value)
+ explanation = "... = %s" % (value_explanation,)
+ name = ast.Name("__exprinfo_expr", ast.Load(),
+ lineno=assign.value.lineno,
+ col_offset=assign.value.col_offset)
+ new_assign = ast.Assign(assign.targets, name, lineno=assign.lineno,
+ col_offset=assign.col_offset)
+ mod = ast.Module([new_assign])
+ co = self._compile(mod, "exec")
+ try:
+ self.frame.exec_(co, __exprinfo_expr=value_result)
+ except Exception:
+ raise Failure(explanation)
+ return explanation, value_result
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_code/_assertionold.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_code/_assertionold.py
new file mode 100644
index 00000000000..1bb70a875d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_code/_assertionold.py
@@ -0,0 +1,556 @@
+import py
+import sys, inspect
+from compiler import parse, ast, pycodegen
+from py._code.assertion import BuiltinAssertionError, _format_explanation
+import types
+
+passthroughex = py.builtin._sysex
+
+class Failure:
+ def __init__(self, node):
+ self.exc, self.value, self.tb = sys.exc_info()
+ self.node = node
+
+class View(object):
+ """View base class.
+
+ If C is a subclass of View, then C(x) creates a proxy object around
+ the object x. The actual class of the proxy is not C in general,
+ but a *subclass* of C determined by the rules below. To avoid confusion
+ we call view class the class of the proxy (a subclass of C, so of View)
+ and object class the class of x.
+
+ Attributes and methods not found in the proxy are automatically read on x.
+ Other operations like setting attributes are performed on the proxy, as
+ determined by its view class. The object x is available from the proxy
+ as its __obj__ attribute.
+
+ The view class selection is determined by the __view__ tuples and the
+ optional __viewkey__ method. By default, the selected view class is the
+ most specific subclass of C whose __view__ mentions the class of x.
+ If no such subclass is found, the search proceeds with the parent
+ object classes. For example, C(True) will first look for a subclass
+ of C with __view__ = (..., bool, ...) and only if it doesn't find any
+ look for one with __view__ = (..., int, ...), and then ..., object,...
+ If everything fails the class C itself is considered to be the default.
+
+ Alternatively, the view class selection can be driven by another aspect
+ of the object x, instead of the class of x, by overriding __viewkey__.
+ See last example at the end of this module.
+ """
+
+ _viewcache = {}
+ __view__ = ()
+
+ def __new__(rootclass, obj, *args, **kwds):
+ self = object.__new__(rootclass)
+ self.__obj__ = obj
+ self.__rootclass__ = rootclass
+ key = self.__viewkey__()
+ try:
+ self.__class__ = self._viewcache[key]
+ except KeyError:
+ self.__class__ = self._selectsubclass(key)
+ return self
+
+ def __getattr__(self, attr):
+ # attributes not found in the normal hierarchy rooted on View
+ # are looked up in the object's real class
+ return getattr(self.__obj__, attr)
+
+ def __viewkey__(self):
+ return self.__obj__.__class__
+
+ def __matchkey__(self, key, subclasses):
+ if inspect.isclass(key):
+ keys = inspect.getmro(key)
+ else:
+ keys = [key]
+ for key in keys:
+ result = [C for C in subclasses if key in C.__view__]
+ if result:
+ return result
+ return []
+
+ def _selectsubclass(self, key):
+ subclasses = list(enumsubclasses(self.__rootclass__))
+ for C in subclasses:
+ if not isinstance(C.__view__, tuple):
+ C.__view__ = (C.__view__,)
+ choices = self.__matchkey__(key, subclasses)
+ if not choices:
+ return self.__rootclass__
+ elif len(choices) == 1:
+ return choices[0]
+ else:
+ # combine the multiple choices
+ return type('?', tuple(choices), {})
+
+ def __repr__(self):
+ return '%s(%r)' % (self.__rootclass__.__name__, self.__obj__)
+
+
+def enumsubclasses(cls):
+ for subcls in cls.__subclasses__():
+ for subsubclass in enumsubclasses(subcls):
+ yield subsubclass
+ yield cls
+
+
+class Interpretable(View):
+ """A parse tree node with a few extra methods."""
+ explanation = None
+
+ def is_builtin(self, frame):
+ return False
+
+ def eval(self, frame):
+ # fall-back for unknown expression nodes
+ try:
+ expr = ast.Expression(self.__obj__)
+ expr.filename = '<eval>'
+ self.__obj__.filename = '<eval>'
+ co = pycodegen.ExpressionCodeGenerator(expr).getCode()
+ result = frame.eval(co)
+ except passthroughex:
+ raise
+ except:
+ raise Failure(self)
+ self.result = result
+ self.explanation = self.explanation or frame.repr(self.result)
+
+ def run(self, frame):
+ # fall-back for unknown statement nodes
+ try:
+ expr = ast.Module(None, ast.Stmt([self.__obj__]))
+ expr.filename = '<run>'
+ co = pycodegen.ModuleCodeGenerator(expr).getCode()
+ frame.exec_(co)
+ except passthroughex:
+ raise
+ except:
+ raise Failure(self)
+
+ def nice_explanation(self):
+ return _format_explanation(self.explanation)
+
+
+class Name(Interpretable):
+ __view__ = ast.Name
+
+ def is_local(self, frame):
+ source = '%r in locals() is not globals()' % self.name
+ try:
+ return frame.is_true(frame.eval(source))
+ except passthroughex:
+ raise
+ except:
+ return False
+
+ def is_global(self, frame):
+ source = '%r in globals()' % self.name
+ try:
+ return frame.is_true(frame.eval(source))
+ except passthroughex:
+ raise
+ except:
+ return False
+
+ def is_builtin(self, frame):
+ source = '%r not in locals() and %r not in globals()' % (
+ self.name, self.name)
+ try:
+ return frame.is_true(frame.eval(source))
+ except passthroughex:
+ raise
+ except:
+ return False
+
+ def eval(self, frame):
+ super(Name, self).eval(frame)
+ if not self.is_local(frame):
+ self.explanation = self.name
+
+class Compare(Interpretable):
+ __view__ = ast.Compare
+
+ def eval(self, frame):
+ expr = Interpretable(self.expr)
+ expr.eval(frame)
+ for operation, expr2 in self.ops:
+ if hasattr(self, 'result'):
+ # shortcutting in chained expressions
+ if not frame.is_true(self.result):
+ break
+ expr2 = Interpretable(expr2)
+ expr2.eval(frame)
+ self.explanation = "%s %s %s" % (
+ expr.explanation, operation, expr2.explanation)
+ source = "__exprinfo_left %s __exprinfo_right" % operation
+ try:
+ self.result = frame.eval(source,
+ __exprinfo_left=expr.result,
+ __exprinfo_right=expr2.result)
+ except passthroughex:
+ raise
+ except:
+ raise Failure(self)
+ expr = expr2
+
+class And(Interpretable):
+ __view__ = ast.And
+
+ def eval(self, frame):
+ explanations = []
+ for expr in self.nodes:
+ expr = Interpretable(expr)
+ expr.eval(frame)
+ explanations.append(expr.explanation)
+ self.result = expr.result
+ if not frame.is_true(expr.result):
+ break
+ self.explanation = '(' + ' and '.join(explanations) + ')'
+
+class Or(Interpretable):
+ __view__ = ast.Or
+
+ def eval(self, frame):
+ explanations = []
+ for expr in self.nodes:
+ expr = Interpretable(expr)
+ expr.eval(frame)
+ explanations.append(expr.explanation)
+ self.result = expr.result
+ if frame.is_true(expr.result):
+ break
+ self.explanation = '(' + ' or '.join(explanations) + ')'
+
+
+# == Unary operations ==
+keepalive = []
+for astclass, astpattern in {
+ ast.Not : 'not __exprinfo_expr',
+ ast.Invert : '(~__exprinfo_expr)',
+ }.items():
+
+ class UnaryArith(Interpretable):
+ __view__ = astclass
+
+ def eval(self, frame, astpattern=astpattern):
+ expr = Interpretable(self.expr)
+ expr.eval(frame)
+ self.explanation = astpattern.replace('__exprinfo_expr',
+ expr.explanation)
+ try:
+ self.result = frame.eval(astpattern,
+ __exprinfo_expr=expr.result)
+ except passthroughex:
+ raise
+ except:
+ raise Failure(self)
+
+ keepalive.append(UnaryArith)
+
+# == Binary operations ==
+for astclass, astpattern in {
+ ast.Add : '(__exprinfo_left + __exprinfo_right)',
+ ast.Sub : '(__exprinfo_left - __exprinfo_right)',
+ ast.Mul : '(__exprinfo_left * __exprinfo_right)',
+ ast.Div : '(__exprinfo_left / __exprinfo_right)',
+ ast.Mod : '(__exprinfo_left % __exprinfo_right)',
+ ast.Power : '(__exprinfo_left ** __exprinfo_right)',
+ }.items():
+
+ class BinaryArith(Interpretable):
+ __view__ = astclass
+
+ def eval(self, frame, astpattern=astpattern):
+ left = Interpretable(self.left)
+ left.eval(frame)
+ right = Interpretable(self.right)
+ right.eval(frame)
+ self.explanation = (astpattern
+ .replace('__exprinfo_left', left .explanation)
+ .replace('__exprinfo_right', right.explanation))
+ try:
+ self.result = frame.eval(astpattern,
+ __exprinfo_left=left.result,
+ __exprinfo_right=right.result)
+ except passthroughex:
+ raise
+ except:
+ raise Failure(self)
+
+ keepalive.append(BinaryArith)
+
+
+class CallFunc(Interpretable):
+ __view__ = ast.CallFunc
+
+ def is_bool(self, frame):
+ source = 'isinstance(__exprinfo_value, bool)'
+ try:
+ return frame.is_true(frame.eval(source,
+ __exprinfo_value=self.result))
+ except passthroughex:
+ raise
+ except:
+ return False
+
+ def eval(self, frame):
+ node = Interpretable(self.node)
+ node.eval(frame)
+ explanations = []
+ vars = {'__exprinfo_fn': node.result}
+ source = '__exprinfo_fn('
+ for a in self.args:
+ if isinstance(a, ast.Keyword):
+ keyword = a.name
+ a = a.expr
+ else:
+ keyword = None
+ a = Interpretable(a)
+ a.eval(frame)
+ argname = '__exprinfo_%d' % len(vars)
+ vars[argname] = a.result
+ if keyword is None:
+ source += argname + ','
+ explanations.append(a.explanation)
+ else:
+ source += '%s=%s,' % (keyword, argname)
+ explanations.append('%s=%s' % (keyword, a.explanation))
+ if self.star_args:
+ star_args = Interpretable(self.star_args)
+ star_args.eval(frame)
+ argname = '__exprinfo_star'
+ vars[argname] = star_args.result
+ source += '*' + argname + ','
+ explanations.append('*' + star_args.explanation)
+ if self.dstar_args:
+ dstar_args = Interpretable(self.dstar_args)
+ dstar_args.eval(frame)
+ argname = '__exprinfo_kwds'
+ vars[argname] = dstar_args.result
+ source += '**' + argname + ','
+ explanations.append('**' + dstar_args.explanation)
+ self.explanation = "%s(%s)" % (
+ node.explanation, ', '.join(explanations))
+ if source.endswith(','):
+ source = source[:-1]
+ source += ')'
+ try:
+ self.result = frame.eval(source, **vars)
+ except passthroughex:
+ raise
+ except:
+ raise Failure(self)
+ if not node.is_builtin(frame) or not self.is_bool(frame):
+ r = frame.repr(self.result)
+ self.explanation = '%s\n{%s = %s\n}' % (r, r, self.explanation)
+
+class Getattr(Interpretable):
+ __view__ = ast.Getattr
+
+ def eval(self, frame):
+ expr = Interpretable(self.expr)
+ expr.eval(frame)
+ source = '__exprinfo_expr.%s' % self.attrname
+ try:
+ self.result = frame.eval(source, __exprinfo_expr=expr.result)
+ except passthroughex:
+ raise
+ except:
+ raise Failure(self)
+ self.explanation = '%s.%s' % (expr.explanation, self.attrname)
+ # if the attribute comes from the instance, its value is interesting
+ source = ('hasattr(__exprinfo_expr, "__dict__") and '
+ '%r in __exprinfo_expr.__dict__' % self.attrname)
+ try:
+ from_instance = frame.is_true(
+ frame.eval(source, __exprinfo_expr=expr.result))
+ except passthroughex:
+ raise
+ except:
+ from_instance = True
+ if from_instance:
+ r = frame.repr(self.result)
+ self.explanation = '%s\n{%s = %s\n}' % (r, r, self.explanation)
+
+# == Re-interpretation of full statements ==
+
+class Assert(Interpretable):
+ __view__ = ast.Assert
+
+ def run(self, frame):
+ test = Interpretable(self.test)
+ test.eval(frame)
+ # simplify 'assert False where False = ...'
+ if (test.explanation.startswith('False\n{False = ') and
+ test.explanation.endswith('\n}')):
+ test.explanation = test.explanation[15:-2]
+ # print the result as 'assert <explanation>'
+ self.result = test.result
+ self.explanation = 'assert ' + test.explanation
+ if not frame.is_true(test.result):
+ try:
+ raise BuiltinAssertionError
+ except passthroughex:
+ raise
+ except:
+ raise Failure(self)
+
+class Assign(Interpretable):
+ __view__ = ast.Assign
+
+ def run(self, frame):
+ expr = Interpretable(self.expr)
+ expr.eval(frame)
+ self.result = expr.result
+ self.explanation = '... = ' + expr.explanation
+ # fall-back-run the rest of the assignment
+ ass = ast.Assign(self.nodes, ast.Name('__exprinfo_expr'))
+ mod = ast.Module(None, ast.Stmt([ass]))
+ mod.filename = '<run>'
+ co = pycodegen.ModuleCodeGenerator(mod).getCode()
+ try:
+ frame.exec_(co, __exprinfo_expr=expr.result)
+ except passthroughex:
+ raise
+ except:
+ raise Failure(self)
+
+class Discard(Interpretable):
+ __view__ = ast.Discard
+
+ def run(self, frame):
+ expr = Interpretable(self.expr)
+ expr.eval(frame)
+ self.result = expr.result
+ self.explanation = expr.explanation
+
+class Stmt(Interpretable):
+ __view__ = ast.Stmt
+
+ def run(self, frame):
+ for stmt in self.nodes:
+ stmt = Interpretable(stmt)
+ stmt.run(frame)
+
+
+def report_failure(e):
+ explanation = e.node.nice_explanation()
+ if explanation:
+ explanation = ", in: " + explanation
+ else:
+ explanation = ""
+ sys.stdout.write("%s: %s%s\n" % (e.exc.__name__, e.value, explanation))
+
+def check(s, frame=None):
+ if frame is None:
+ frame = sys._getframe(1)
+ frame = py.code.Frame(frame)
+ expr = parse(s, 'eval')
+ assert isinstance(expr, ast.Expression)
+ node = Interpretable(expr.node)
+ try:
+ node.eval(frame)
+ except passthroughex:
+ raise
+ except Failure:
+ e = sys.exc_info()[1]
+ report_failure(e)
+ else:
+ if not frame.is_true(node.result):
+ sys.stderr.write("assertion failed: %s\n" % node.nice_explanation())
+
+
+###########################################################
+# API / Entry points
+# #########################################################
+
+def interpret(source, frame, should_fail=False):
+ module = Interpretable(parse(source, 'exec').node)
+ #print "got module", module
+ if isinstance(frame, types.FrameType):
+ frame = py.code.Frame(frame)
+ try:
+ module.run(frame)
+ except Failure:
+ e = sys.exc_info()[1]
+ return getfailure(e)
+ except passthroughex:
+ raise
+ except:
+ import traceback
+ traceback.print_exc()
+ if should_fail:
+ return ("(assertion failed, but when it was re-run for "
+ "printing intermediate values, it did not fail. Suggestions: "
+ "compute assert expression before the assert or use --nomagic)")
+ else:
+ return None
+
+def getmsg(excinfo):
+ if isinstance(excinfo, tuple):
+ excinfo = py.code.ExceptionInfo(excinfo)
+ #frame, line = gettbline(tb)
+ #frame = py.code.Frame(frame)
+ #return interpret(line, frame)
+
+ tb = excinfo.traceback[-1]
+ source = str(tb.statement).strip()
+ x = interpret(source, tb.frame, should_fail=True)
+ if not isinstance(x, str):
+ raise TypeError("interpret returned non-string %r" % (x,))
+ return x
+
+def getfailure(e):
+ explanation = e.node.nice_explanation()
+ if str(e.value):
+ lines = explanation.split('\n')
+ lines[0] += " << %s" % (e.value,)
+ explanation = '\n'.join(lines)
+ text = "%s: %s" % (e.exc.__name__, explanation)
+ if text.startswith('AssertionError: assert '):
+ text = text[16:]
+ return text
+
+def run(s, frame=None):
+ if frame is None:
+ frame = sys._getframe(1)
+ frame = py.code.Frame(frame)
+ module = Interpretable(parse(s, 'exec').node)
+ try:
+ module.run(frame)
+ except Failure:
+ e = sys.exc_info()[1]
+ report_failure(e)
+
+
+if __name__ == '__main__':
+ # example:
+ def f():
+ return 5
+ def g():
+ return 3
+ def h(x):
+ return 'never'
+ check("f() * g() == 5")
+ check("not f()")
+ check("not (f() and g() or 0)")
+ check("f() == g()")
+ i = 4
+ check("i == f()")
+ check("len(f()) == 0")
+ check("isinstance(2+3+4, float)")
+
+ run("x = i")
+ check("x == 5")
+
+ run("assert not f(), 'oops'")
+ run("a, b, c = 1, 2")
+ run("a, b, c = f()")
+
+ check("max([f(),g()]) == 4")
+ check("'hello'[g()] == 'h'")
+ run("'guk%d' % h(f())")
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_code/_py2traceback.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_code/_py2traceback.py
index d65e27cb730..d65e27cb730 100644
--- a/tests/wpt/web-platform-tests/tools/py/py/_code/_py2traceback.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_code/_py2traceback.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_code/assertion.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_code/assertion.py
new file mode 100644
index 00000000000..ff1643799c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_code/assertion.py
@@ -0,0 +1,90 @@
+import sys
+import py
+
+BuiltinAssertionError = py.builtin.builtins.AssertionError
+
+_reprcompare = None # if set, will be called by assert reinterp for comparison ops
+
+def _format_explanation(explanation):
+ """This formats an explanation
+
+ Normally all embedded newlines are escaped, however there are
+ three exceptions: \n{, \n} and \n~. The first two are intended
+ cover nested explanations, see function and attribute explanations
+ for examples (.visit_Call(), visit_Attribute()). The last one is
+ for when one explanation needs to span multiple lines, e.g. when
+ displaying diffs.
+ """
+ raw_lines = (explanation or '').split('\n')
+ # escape newlines not followed by {, } and ~
+ lines = [raw_lines[0]]
+ for l in raw_lines[1:]:
+ if l.startswith('{') or l.startswith('}') or l.startswith('~'):
+ lines.append(l)
+ else:
+ lines[-1] += '\\n' + l
+
+ result = lines[:1]
+ stack = [0]
+ stackcnt = [0]
+ for line in lines[1:]:
+ if line.startswith('{'):
+ if stackcnt[-1]:
+ s = 'and '
+ else:
+ s = 'where '
+ stack.append(len(result))
+ stackcnt[-1] += 1
+ stackcnt.append(0)
+ result.append(' +' + ' '*(len(stack)-1) + s + line[1:])
+ elif line.startswith('}'):
+ assert line.startswith('}')
+ stack.pop()
+ stackcnt.pop()
+ result[stack[-1]] += line[1:]
+ else:
+ assert line.startswith('~')
+ result.append(' '*len(stack) + line[1:])
+ assert len(stack) == 1
+ return '\n'.join(result)
+
+
+class AssertionError(BuiltinAssertionError):
+ def __init__(self, *args):
+ BuiltinAssertionError.__init__(self, *args)
+ if args:
+ try:
+ self.msg = str(args[0])
+ except py.builtin._sysex:
+ raise
+ except:
+ self.msg = "<[broken __repr__] %s at %0xd>" %(
+ args[0].__class__, id(args[0]))
+ else:
+ f = py.code.Frame(sys._getframe(1))
+ try:
+ source = f.code.fullsource
+ if source is not None:
+ try:
+ source = source.getstatement(f.lineno, assertion=True)
+ except IndexError:
+ source = None
+ else:
+ source = str(source.deindent()).strip()
+ except py.error.ENOENT:
+ source = None
+ # this can also occur during reinterpretation, when the
+ # co_filename is set to "<run>".
+ if source:
+ self.msg = reinterpret(source, f, should_fail=True)
+ else:
+ self.msg = "<could not determine information>"
+ if not self.args:
+ self.args = (self.msg,)
+
+if sys.version_info > (3, 0):
+ AssertionError.__module__ = "builtins"
+ reinterpret_old = "old reinterpretation not available for py3"
+else:
+ from py._code._assertionold import interpret as reinterpret_old
+from py._code._assertionnew import interpret as reinterpret
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_code/code.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_code/code.py
new file mode 100644
index 00000000000..dad796283fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_code/code.py
@@ -0,0 +1,796 @@
+import py
+import sys
+from inspect import CO_VARARGS, CO_VARKEYWORDS, isclass
+
+builtin_repr = repr
+
+reprlib = py.builtin._tryimport('repr', 'reprlib')
+
+if sys.version_info[0] >= 3:
+ from traceback import format_exception_only
+else:
+ from py._code._py2traceback import format_exception_only
+
+import traceback
+
+
+class Code(object):
+ """ wrapper around Python code objects """
+ def __init__(self, rawcode):
+ if not hasattr(rawcode, "co_filename"):
+ rawcode = py.code.getrawcode(rawcode)
+ try:
+ self.filename = rawcode.co_filename
+ self.firstlineno = rawcode.co_firstlineno - 1
+ self.name = rawcode.co_name
+ except AttributeError:
+ raise TypeError("not a code object: %r" % (rawcode,))
+ self.raw = rawcode
+
+ def __eq__(self, other):
+ return self.raw == other.raw
+
+ def __ne__(self, other):
+ return not self == other
+
+ @property
+ def path(self):
+ """ return a path object pointing to source code (note that it
+ might not point to an actually existing file). """
+ p = py.path.local(self.raw.co_filename)
+ # maybe don't try this checking
+ if not p.check():
+ # XXX maybe try harder like the weird logic
+ # in the standard lib [linecache.updatecache] does?
+ p = self.raw.co_filename
+ return p
+
+ @property
+ def fullsource(self):
+ """ return a py.code.Source object for the full source file of the code
+ """
+ from py._code import source
+ full, _ = source.findsource(self.raw)
+ return full
+
+ def source(self):
+ """ return a py.code.Source object for the code object's source only
+ """
+ # return source only for that part of code
+ return py.code.Source(self.raw)
+
+ def getargs(self, var=False):
+ """ return a tuple with the argument names for the code object
+
+ if 'var' is set True also return the names of the variable and
+ keyword arguments when present
+ """
+ # handfull shortcut for getting args
+ raw = self.raw
+ argcount = raw.co_argcount
+ if var:
+ argcount += raw.co_flags & CO_VARARGS
+ argcount += raw.co_flags & CO_VARKEYWORDS
+ return raw.co_varnames[:argcount]
+
+class Frame(object):
+ """Wrapper around a Python frame holding f_locals and f_globals
+ in which expressions can be evaluated."""
+
+ def __init__(self, frame):
+ self.lineno = frame.f_lineno - 1
+ self.f_globals = frame.f_globals
+ self.f_locals = frame.f_locals
+ self.raw = frame
+ self.code = py.code.Code(frame.f_code)
+
+ @property
+ def statement(self):
+ """ statement this frame is at """
+ if self.code.fullsource is None:
+ return py.code.Source("")
+ return self.code.fullsource.getstatement(self.lineno)
+
+ def eval(self, code, **vars):
+ """ evaluate 'code' in the frame
+
+ 'vars' are optional additional local variables
+
+ returns the result of the evaluation
+ """
+ f_locals = self.f_locals.copy()
+ f_locals.update(vars)
+ return eval(code, self.f_globals, f_locals)
+
+ def exec_(self, code, **vars):
+ """ exec 'code' in the frame
+
+ 'vars' are optiona; additional local variables
+ """
+ f_locals = self.f_locals.copy()
+ f_locals.update(vars)
+ py.builtin.exec_(code, self.f_globals, f_locals)
+
+ def repr(self, object):
+ """ return a 'safe' (non-recursive, one-line) string repr for 'object'
+ """
+ return py.io.saferepr(object)
+
+ def is_true(self, object):
+ return object
+
+ def getargs(self, var=False):
+ """ return a list of tuples (name, value) for all arguments
+
+ if 'var' is set True also include the variable and keyword
+ arguments when present
+ """
+ retval = []
+ for arg in self.code.getargs(var):
+ try:
+ retval.append((arg, self.f_locals[arg]))
+ except KeyError:
+ pass # this can occur when using Psyco
+ return retval
+
+
+class TracebackEntry(object):
+ """ a single entry in a traceback """
+
+ _repr_style = None
+ exprinfo = None
+
+ def __init__(self, rawentry):
+ self._rawentry = rawentry
+ self.lineno = rawentry.tb_lineno - 1
+
+ def set_repr_style(self, mode):
+ assert mode in ("short", "long")
+ self._repr_style = mode
+
+ @property
+ def frame(self):
+ return py.code.Frame(self._rawentry.tb_frame)
+
+ @property
+ def relline(self):
+ return self.lineno - self.frame.code.firstlineno
+
+ def __repr__(self):
+ return "<TracebackEntry %s:%d>" % (self.frame.code.path, self.lineno+1)
+
+ @property
+ def statement(self):
+ """ py.code.Source object for the current statement """
+ source = self.frame.code.fullsource
+ return source.getstatement(self.lineno)
+
+ @property
+ def path(self):
+ """ path to the source code """
+ return self.frame.code.path
+
+ def getlocals(self):
+ return self.frame.f_locals
+ locals = property(getlocals, None, None, "locals of underlaying frame")
+
+ def reinterpret(self):
+ """Reinterpret the failing statement and returns a detailed information
+ about what operations are performed."""
+ if self.exprinfo is None:
+ source = str(self.statement).strip()
+ x = py.code._reinterpret(source, self.frame, should_fail=True)
+ if not isinstance(x, str):
+ raise TypeError("interpret returned non-string %r" % (x,))
+ self.exprinfo = x
+ return self.exprinfo
+
+ def getfirstlinesource(self):
+ # on Jython this firstlineno can be -1 apparently
+ return max(self.frame.code.firstlineno, 0)
+
+ def getsource(self, astcache=None):
+ """ return failing source code. """
+ # we use the passed in astcache to not reparse asttrees
+ # within exception info printing
+ from py._code.source import getstatementrange_ast
+ source = self.frame.code.fullsource
+ if source is None:
+ return None
+ key = astnode = None
+ if astcache is not None:
+ key = self.frame.code.path
+ if key is not None:
+ astnode = astcache.get(key, None)
+ start = self.getfirstlinesource()
+ try:
+ astnode, _, end = getstatementrange_ast(self.lineno, source,
+ astnode=astnode)
+ except SyntaxError:
+ end = self.lineno + 1
+ else:
+ if key is not None:
+ astcache[key] = astnode
+ return source[start:end]
+
+ source = property(getsource)
+
+ def ishidden(self):
+ """ return True if the current frame has a var __tracebackhide__
+ resolving to True
+
+ mostly for internal use
+ """
+ try:
+ return self.frame.f_locals['__tracebackhide__']
+ except KeyError:
+ try:
+ return self.frame.f_globals['__tracebackhide__']
+ except KeyError:
+ return False
+
+ def __str__(self):
+ try:
+ fn = str(self.path)
+ except py.error.Error:
+ fn = '???'
+ name = self.frame.code.name
+ try:
+ line = str(self.statement).lstrip()
+ except KeyboardInterrupt:
+ raise
+ except:
+ line = "???"
+ return " File %r:%d in %s\n %s\n" % (fn, self.lineno+1, name, line)
+
+ def name(self):
+ return self.frame.code.raw.co_name
+ name = property(name, None, None, "co_name of underlaying code")
+
+
+class Traceback(list):
+ """ Traceback objects encapsulate and offer higher level
+ access to Traceback entries.
+ """
+ Entry = TracebackEntry
+
+ def __init__(self, tb):
+ """ initialize from given python traceback object. """
+ if hasattr(tb, 'tb_next'):
+ def f(cur):
+ while cur is not None:
+ yield self.Entry(cur)
+ cur = cur.tb_next
+ list.__init__(self, f(tb))
+ else:
+ list.__init__(self, tb)
+
+ def cut(self, path=None, lineno=None, firstlineno=None, excludepath=None):
+ """ return a Traceback instance wrapping part of this Traceback
+
+ by provding any combination of path, lineno and firstlineno, the
+ first frame to start the to-be-returned traceback is determined
+
+ this allows cutting the first part of a Traceback instance e.g.
+ for formatting reasons (removing some uninteresting bits that deal
+ with handling of the exception/traceback)
+ """
+ for x in self:
+ code = x.frame.code
+ codepath = code.path
+ if ((path is None or codepath == path) and
+ (excludepath is None or not hasattr(codepath, 'relto') or
+ not codepath.relto(excludepath)) and
+ (lineno is None or x.lineno == lineno) and
+ (firstlineno is None or x.frame.code.firstlineno == firstlineno)):
+ return Traceback(x._rawentry)
+ return self
+
+ def __getitem__(self, key):
+ val = super(Traceback, self).__getitem__(key)
+ if isinstance(key, type(slice(0))):
+ val = self.__class__(val)
+ return val
+
+ def filter(self, fn=lambda x: not x.ishidden()):
+ """ return a Traceback instance with certain items removed
+
+ fn is a function that gets a single argument, a TracebackItem
+ instance, and should return True when the item should be added
+ to the Traceback, False when not
+
+ by default this removes all the TracebackItems which are hidden
+ (see ishidden() above)
+ """
+ return Traceback(filter(fn, self))
+
+ def getcrashentry(self):
+ """ return last non-hidden traceback entry that lead
+ to the exception of a traceback.
+ """
+ for i in range(-1, -len(self)-1, -1):
+ entry = self[i]
+ if not entry.ishidden():
+ return entry
+ return self[-1]
+
+ def recursionindex(self):
+ """ return the index of the frame/TracebackItem where recursion
+ originates if appropriate, None if no recursion occurred
+ """
+ cache = {}
+ for i, entry in enumerate(self):
+ # id for the code.raw is needed to work around
+ # the strange metaprogramming in the decorator lib from pypi
+ # which generates code objects that have hash/value equality
+ #XXX needs a test
+ key = entry.frame.code.path, id(entry.frame.code.raw), entry.lineno
+ #print "checking for recursion at", key
+ l = cache.setdefault(key, [])
+ if l:
+ f = entry.frame
+ loc = f.f_locals
+ for otherloc in l:
+ if f.is_true(f.eval(co_equal,
+ __recursioncache_locals_1=loc,
+ __recursioncache_locals_2=otherloc)):
+ return i
+ l.append(entry.frame.f_locals)
+ return None
+
+co_equal = compile('__recursioncache_locals_1 == __recursioncache_locals_2',
+ '?', 'eval')
+
+class ExceptionInfo(object):
+ """ wraps sys.exc_info() objects and offers
+ help for navigating the traceback.
+ """
+ _striptext = ''
+ def __init__(self, tup=None, exprinfo=None):
+ if tup is None:
+ tup = sys.exc_info()
+ if exprinfo is None and isinstance(tup[1], AssertionError):
+ exprinfo = getattr(tup[1], 'msg', None)
+ if exprinfo is None:
+ exprinfo = str(tup[1])
+ if exprinfo and exprinfo.startswith('assert '):
+ self._striptext = 'AssertionError: '
+ self._excinfo = tup
+ #: the exception class
+ self.type = tup[0]
+ #: the exception instance
+ self.value = tup[1]
+ #: the exception raw traceback
+ self.tb = tup[2]
+ #: the exception type name
+ self.typename = self.type.__name__
+ #: the exception traceback (py.code.Traceback instance)
+ self.traceback = py.code.Traceback(self.tb)
+
+ def __repr__(self):
+ return "<ExceptionInfo %s tblen=%d>" % (
+ self.typename, len(self.traceback))
+
+ def exconly(self, tryshort=False):
+ """ return the exception as a string
+
+ when 'tryshort' resolves to True, and the exception is a
+ py.code._AssertionError, only the actual exception part of
+ the exception representation is returned (so 'AssertionError: ' is
+ removed from the beginning)
+ """
+ lines = format_exception_only(self.type, self.value)
+ text = ''.join(lines)
+ text = text.rstrip()
+ if tryshort:
+ if text.startswith(self._striptext):
+ text = text[len(self._striptext):]
+ return text
+
+ def errisinstance(self, exc):
+ """ return True if the exception is an instance of exc """
+ return isinstance(self.value, exc)
+
+ def _getreprcrash(self):
+ exconly = self.exconly(tryshort=True)
+ entry = self.traceback.getcrashentry()
+ path, lineno = entry.frame.code.raw.co_filename, entry.lineno
+ return ReprFileLocation(path, lineno+1, exconly)
+
+ def getrepr(self, showlocals=False, style="long",
+ abspath=False, tbfilter=True, funcargs=False):
+ """ return str()able representation of this exception info.
+ showlocals: show locals per traceback entry
+ style: long|short|no|native traceback style
+ tbfilter: hide entries (where __tracebackhide__ is true)
+
+ in case of style==native, tbfilter and showlocals is ignored.
+ """
+ if style == 'native':
+ return ReprExceptionInfo(ReprTracebackNative(
+ traceback.format_exception(
+ self.type,
+ self.value,
+ self.traceback[0]._rawentry,
+ )), self._getreprcrash())
+
+ fmt = FormattedExcinfo(
+ showlocals=showlocals, style=style,
+ abspath=abspath, tbfilter=tbfilter, funcargs=funcargs)
+ return fmt.repr_excinfo(self)
+
+ def __str__(self):
+ entry = self.traceback[-1]
+ loc = ReprFileLocation(entry.path, entry.lineno + 1, self.exconly())
+ return str(loc)
+
+ def __unicode__(self):
+ entry = self.traceback[-1]
+ loc = ReprFileLocation(entry.path, entry.lineno + 1, self.exconly())
+ return loc.__unicode__()
+
+
+class FormattedExcinfo(object):
+ """ presenting information about failing Functions and Generators. """
+ # for traceback entries
+ flow_marker = ">"
+ fail_marker = "E"
+
+ def __init__(self, showlocals=False, style="long",
+ abspath=True, tbfilter=True, funcargs=False):
+ self.showlocals = showlocals
+ self.style = style
+ self.tbfilter = tbfilter
+ self.funcargs = funcargs
+ self.abspath = abspath
+ self.astcache = {}
+
+ def _getindent(self, source):
+ # figure out indent for given source
+ try:
+ s = str(source.getstatement(len(source)-1))
+ except KeyboardInterrupt:
+ raise
+ except:
+ try:
+ s = str(source[-1])
+ except KeyboardInterrupt:
+ raise
+ except:
+ return 0
+ return 4 + (len(s) - len(s.lstrip()))
+
+ def _getentrysource(self, entry):
+ source = entry.getsource(self.astcache)
+ if source is not None:
+ source = source.deindent()
+ return source
+
+ def _saferepr(self, obj):
+ return py.io.saferepr(obj)
+
+ def repr_args(self, entry):
+ if self.funcargs:
+ args = []
+ for argname, argvalue in entry.frame.getargs(var=True):
+ args.append((argname, self._saferepr(argvalue)))
+ return ReprFuncArgs(args)
+
+ def get_source(self, source, line_index=-1, excinfo=None, short=False):
+ """ return formatted and marked up source lines. """
+ lines = []
+ if source is None or line_index >= len(source.lines):
+ source = py.code.Source("???")
+ line_index = 0
+ if line_index < 0:
+ line_index += len(source)
+ space_prefix = " "
+ if short:
+ lines.append(space_prefix + source.lines[line_index].strip())
+ else:
+ for line in source.lines[:line_index]:
+ lines.append(space_prefix + line)
+ lines.append(self.flow_marker + " " + source.lines[line_index])
+ for line in source.lines[line_index+1:]:
+ lines.append(space_prefix + line)
+ if excinfo is not None:
+ indent = 4 if short else self._getindent(source)
+ lines.extend(self.get_exconly(excinfo, indent=indent, markall=True))
+ return lines
+
+ def get_exconly(self, excinfo, indent=4, markall=False):
+ lines = []
+ indent = " " * indent
+ # get the real exception information out
+ exlines = excinfo.exconly(tryshort=True).split('\n')
+ failindent = self.fail_marker + indent[1:]
+ for line in exlines:
+ lines.append(failindent + line)
+ if not markall:
+ failindent = indent
+ return lines
+
+ def repr_locals(self, locals):
+ if self.showlocals:
+ lines = []
+ keys = [loc for loc in locals if loc[0] != "@"]
+ keys.sort()
+ for name in keys:
+ value = locals[name]
+ if name == '__builtins__':
+ lines.append("__builtins__ = <builtins>")
+ else:
+ # This formatting could all be handled by the
+ # _repr() function, which is only reprlib.Repr in
+ # disguise, so is very configurable.
+ str_repr = self._saferepr(value)
+ #if len(str_repr) < 70 or not isinstance(value,
+ # (list, tuple, dict)):
+ lines.append("%-10s = %s" %(name, str_repr))
+ #else:
+ # self._line("%-10s =\\" % (name,))
+ # # XXX
+ # pprint.pprint(value, stream=self.excinfowriter)
+ return ReprLocals(lines)
+
+ def repr_traceback_entry(self, entry, excinfo=None):
+ source = self._getentrysource(entry)
+ if source is None:
+ source = py.code.Source("???")
+ line_index = 0
+ else:
+ # entry.getfirstlinesource() can be -1, should be 0 on jython
+ line_index = entry.lineno - max(entry.getfirstlinesource(), 0)
+
+ lines = []
+ style = entry._repr_style
+ if style is None:
+ style = self.style
+ if style in ("short", "long"):
+ short = style == "short"
+ reprargs = self.repr_args(entry) if not short else None
+ s = self.get_source(source, line_index, excinfo, short=short)
+ lines.extend(s)
+ if short:
+ message = "in %s" %(entry.name)
+ else:
+ message = excinfo and excinfo.typename or ""
+ path = self._makepath(entry.path)
+ filelocrepr = ReprFileLocation(path, entry.lineno+1, message)
+ localsrepr = None
+ if not short:
+ localsrepr = self.repr_locals(entry.locals)
+ return ReprEntry(lines, reprargs, localsrepr, filelocrepr, style)
+ if excinfo:
+ lines.extend(self.get_exconly(excinfo, indent=4))
+ return ReprEntry(lines, None, None, None, style)
+
+ def _makepath(self, path):
+ if not self.abspath:
+ try:
+ np = py.path.local().bestrelpath(path)
+ except OSError:
+ return path
+ if len(np) < len(str(path)):
+ path = np
+ return path
+
+ def repr_traceback(self, excinfo):
+ traceback = excinfo.traceback
+ if self.tbfilter:
+ traceback = traceback.filter()
+ recursionindex = None
+ if excinfo.errisinstance(RuntimeError):
+ if "maximum recursion depth exceeded" in str(excinfo.value):
+ recursionindex = traceback.recursionindex()
+ last = traceback[-1]
+ entries = []
+ extraline = None
+ for index, entry in enumerate(traceback):
+ einfo = (last == entry) and excinfo or None
+ reprentry = self.repr_traceback_entry(entry, einfo)
+ entries.append(reprentry)
+ if index == recursionindex:
+ extraline = "!!! Recursion detected (same locals & position)"
+ break
+ return ReprTraceback(entries, extraline, style=self.style)
+
+ def repr_excinfo(self, excinfo):
+ reprtraceback = self.repr_traceback(excinfo)
+ reprcrash = excinfo._getreprcrash()
+ return ReprExceptionInfo(reprtraceback, reprcrash)
+
+class TerminalRepr:
+ def __str__(self):
+ s = self.__unicode__()
+ if sys.version_info[0] < 3:
+ s = s.encode('utf-8')
+ return s
+
+ def __unicode__(self):
+ # FYI this is called from pytest-xdist's serialization of exception
+ # information.
+ io = py.io.TextIO()
+ tw = py.io.TerminalWriter(file=io)
+ self.toterminal(tw)
+ return io.getvalue().strip()
+
+ def __repr__(self):
+ return "<%s instance at %0x>" %(self.__class__, id(self))
+
+
+class ReprExceptionInfo(TerminalRepr):
+ def __init__(self, reprtraceback, reprcrash):
+ self.reprtraceback = reprtraceback
+ self.reprcrash = reprcrash
+ self.sections = []
+
+ def addsection(self, name, content, sep="-"):
+ self.sections.append((name, content, sep))
+
+ def toterminal(self, tw):
+ self.reprtraceback.toterminal(tw)
+ for name, content, sep in self.sections:
+ tw.sep(sep, name)
+ tw.line(content)
+
+class ReprTraceback(TerminalRepr):
+ entrysep = "_ "
+
+ def __init__(self, reprentries, extraline, style):
+ self.reprentries = reprentries
+ self.extraline = extraline
+ self.style = style
+
+ def toterminal(self, tw):
+ # the entries might have different styles
+ last_style = None
+ for i, entry in enumerate(self.reprentries):
+ if entry.style == "long":
+ tw.line("")
+ entry.toterminal(tw)
+ if i < len(self.reprentries) - 1:
+ next_entry = self.reprentries[i+1]
+ if entry.style == "long" or \
+ entry.style == "short" and next_entry.style == "long":
+ tw.sep(self.entrysep)
+
+ if self.extraline:
+ tw.line(self.extraline)
+
+class ReprTracebackNative(ReprTraceback):
+ def __init__(self, tblines):
+ self.style = "native"
+ self.reprentries = [ReprEntryNative(tblines)]
+ self.extraline = None
+
+class ReprEntryNative(TerminalRepr):
+ style = "native"
+
+ def __init__(self, tblines):
+ self.lines = tblines
+
+ def toterminal(self, tw):
+ tw.write("".join(self.lines))
+
+class ReprEntry(TerminalRepr):
+ localssep = "_ "
+
+ def __init__(self, lines, reprfuncargs, reprlocals, filelocrepr, style):
+ self.lines = lines
+ self.reprfuncargs = reprfuncargs
+ self.reprlocals = reprlocals
+ self.reprfileloc = filelocrepr
+ self.style = style
+
+ def toterminal(self, tw):
+ if self.style == "short":
+ self.reprfileloc.toterminal(tw)
+ for line in self.lines:
+ red = line.startswith("E ")
+ tw.line(line, bold=True, red=red)
+ #tw.line("")
+ return
+ if self.reprfuncargs:
+ self.reprfuncargs.toterminal(tw)
+ for line in self.lines:
+ red = line.startswith("E ")
+ tw.line(line, bold=True, red=red)
+ if self.reprlocals:
+ #tw.sep(self.localssep, "Locals")
+ tw.line("")
+ self.reprlocals.toterminal(tw)
+ if self.reprfileloc:
+ if self.lines:
+ tw.line("")
+ self.reprfileloc.toterminal(tw)
+
+ def __str__(self):
+ return "%s\n%s\n%s" % ("\n".join(self.lines),
+ self.reprlocals,
+ self.reprfileloc)
+
+class ReprFileLocation(TerminalRepr):
+ def __init__(self, path, lineno, message):
+ self.path = str(path)
+ self.lineno = lineno
+ self.message = message
+
+ def toterminal(self, tw):
+ # filename and lineno output for each entry,
+ # using an output format that most editors unterstand
+ msg = self.message
+ i = msg.find("\n")
+ if i != -1:
+ msg = msg[:i]
+ tw.line("%s:%s: %s" %(self.path, self.lineno, msg))
+
+class ReprLocals(TerminalRepr):
+ def __init__(self, lines):
+ self.lines = lines
+
+ def toterminal(self, tw):
+ for line in self.lines:
+ tw.line(line)
+
+class ReprFuncArgs(TerminalRepr):
+ def __init__(self, args):
+ self.args = args
+
+ def toterminal(self, tw):
+ if self.args:
+ linesofar = ""
+ for name, value in self.args:
+ ns = "%s = %s" %(name, value)
+ if len(ns) + len(linesofar) + 2 > tw.fullwidth:
+ if linesofar:
+ tw.line(linesofar)
+ linesofar = ns
+ else:
+ if linesofar:
+ linesofar += ", " + ns
+ else:
+ linesofar = ns
+ if linesofar:
+ tw.line(linesofar)
+ tw.line("")
+
+
+
+oldbuiltins = {}
+
+def patch_builtins(assertion=True, compile=True):
+ """ put compile and AssertionError builtins to Python's builtins. """
+ if assertion:
+ from py._code import assertion
+ l = oldbuiltins.setdefault('AssertionError', [])
+ l.append(py.builtin.builtins.AssertionError)
+ py.builtin.builtins.AssertionError = assertion.AssertionError
+ if compile:
+ l = oldbuiltins.setdefault('compile', [])
+ l.append(py.builtin.builtins.compile)
+ py.builtin.builtins.compile = py.code.compile
+
+def unpatch_builtins(assertion=True, compile=True):
+ """ remove compile and AssertionError builtins from Python builtins. """
+ if assertion:
+ py.builtin.builtins.AssertionError = oldbuiltins['AssertionError'].pop()
+ if compile:
+ py.builtin.builtins.compile = oldbuiltins['compile'].pop()
+
+def getrawcode(obj, trycall=True):
+ """ return code object for given function. """
+ try:
+ return obj.__code__
+ except AttributeError:
+ obj = getattr(obj, 'im_func', obj)
+ obj = getattr(obj, 'func_code', obj)
+ obj = getattr(obj, 'f_code', obj)
+ obj = getattr(obj, '__code__', obj)
+ if trycall and not hasattr(obj, 'co_firstlineno'):
+ if hasattr(obj, '__call__') and not isclass(obj):
+ x = getrawcode(obj.__call__, trycall=False)
+ if hasattr(x, 'co_firstlineno'):
+ return x
+ return obj
+
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_code/source.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_code/source.py
new file mode 100644
index 00000000000..7fc7b23a96c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_code/source.py
@@ -0,0 +1,410 @@
+from __future__ import generators
+
+from bisect import bisect_right
+import sys
+import inspect, tokenize
+import py
+from types import ModuleType
+cpy_compile = compile
+
+try:
+ import _ast
+ from _ast import PyCF_ONLY_AST as _AST_FLAG
+except ImportError:
+ _AST_FLAG = 0
+ _ast = None
+
+
+class Source(object):
+ """ a immutable object holding a source code fragment,
+ possibly deindenting it.
+ """
+ _compilecounter = 0
+ def __init__(self, *parts, **kwargs):
+ self.lines = lines = []
+ de = kwargs.get('deindent', True)
+ rstrip = kwargs.get('rstrip', True)
+ for part in parts:
+ if not part:
+ partlines = []
+ if isinstance(part, Source):
+ partlines = part.lines
+ elif isinstance(part, (tuple, list)):
+ partlines = [x.rstrip("\n") for x in part]
+ elif isinstance(part, py.builtin._basestring):
+ partlines = part.split('\n')
+ if rstrip:
+ while partlines:
+ if partlines[-1].strip():
+ break
+ partlines.pop()
+ else:
+ partlines = getsource(part, deindent=de).lines
+ if de:
+ partlines = deindent(partlines)
+ lines.extend(partlines)
+
+ def __eq__(self, other):
+ try:
+ return self.lines == other.lines
+ except AttributeError:
+ if isinstance(other, str):
+ return str(self) == other
+ return False
+
+ def __getitem__(self, key):
+ if isinstance(key, int):
+ return self.lines[key]
+ else:
+ if key.step not in (None, 1):
+ raise IndexError("cannot slice a Source with a step")
+ return self.__getslice__(key.start, key.stop)
+
+ def __len__(self):
+ return len(self.lines)
+
+ def __getslice__(self, start, end):
+ newsource = Source()
+ newsource.lines = self.lines[start:end]
+ return newsource
+
+ def strip(self):
+ """ return new source object with trailing
+ and leading blank lines removed.
+ """
+ start, end = 0, len(self)
+ while start < end and not self.lines[start].strip():
+ start += 1
+ while end > start and not self.lines[end-1].strip():
+ end -= 1
+ source = Source()
+ source.lines[:] = self.lines[start:end]
+ return source
+
+ def putaround(self, before='', after='', indent=' ' * 4):
+ """ return a copy of the source object with
+ 'before' and 'after' wrapped around it.
+ """
+ before = Source(before)
+ after = Source(after)
+ newsource = Source()
+ lines = [ (indent + line) for line in self.lines]
+ newsource.lines = before.lines + lines + after.lines
+ return newsource
+
+ def indent(self, indent=' ' * 4):
+ """ return a copy of the source object with
+ all lines indented by the given indent-string.
+ """
+ newsource = Source()
+ newsource.lines = [(indent+line) for line in self.lines]
+ return newsource
+
+ def getstatement(self, lineno, assertion=False):
+ """ return Source statement which contains the
+ given linenumber (counted from 0).
+ """
+ start, end = self.getstatementrange(lineno, assertion)
+ return self[start:end]
+
+ def getstatementrange(self, lineno, assertion=False):
+ """ return (start, end) tuple which spans the minimal
+ statement region which containing the given lineno.
+ """
+ if not (0 <= lineno < len(self)):
+ raise IndexError("lineno out of range")
+ ast, start, end = getstatementrange_ast(lineno, self)
+ return start, end
+
+ def deindent(self, offset=None):
+ """ return a new source object deindented by offset.
+ If offset is None then guess an indentation offset from
+ the first non-blank line. Subsequent lines which have a
+ lower indentation offset will be copied verbatim as
+ they are assumed to be part of multilines.
+ """
+ # XXX maybe use the tokenizer to properly handle multiline
+ # strings etc.pp?
+ newsource = Source()
+ newsource.lines[:] = deindent(self.lines, offset)
+ return newsource
+
+ def isparseable(self, deindent=True):
+ """ return True if source is parseable, heuristically
+ deindenting it by default.
+ """
+ try:
+ import parser
+ except ImportError:
+ syntax_checker = lambda x: compile(x, 'asd', 'exec')
+ else:
+ syntax_checker = parser.suite
+
+ if deindent:
+ source = str(self.deindent())
+ else:
+ source = str(self)
+ try:
+ #compile(source+'\n', "x", "exec")
+ syntax_checker(source+'\n')
+ except KeyboardInterrupt:
+ raise
+ except Exception:
+ return False
+ else:
+ return True
+
+ def __str__(self):
+ return "\n".join(self.lines)
+
+ def compile(self, filename=None, mode='exec',
+ flag=generators.compiler_flag,
+ dont_inherit=0, _genframe=None):
+ """ return compiled code object. if filename is None
+ invent an artificial filename which displays
+ the source/line position of the caller frame.
+ """
+ if not filename or py.path.local(filename).check(file=0):
+ if _genframe is None:
+ _genframe = sys._getframe(1) # the caller
+ fn,lineno = _genframe.f_code.co_filename, _genframe.f_lineno
+ base = "<%d-codegen " % self._compilecounter
+ self.__class__._compilecounter += 1
+ if not filename:
+ filename = base + '%s:%d>' % (fn, lineno)
+ else:
+ filename = base + '%r %s:%d>' % (filename, fn, lineno)
+ source = "\n".join(self.lines) + '\n'
+ try:
+ co = cpy_compile(source, filename, mode, flag)
+ except SyntaxError:
+ ex = sys.exc_info()[1]
+ # re-represent syntax errors from parsing python strings
+ msglines = self.lines[:ex.lineno]
+ if ex.offset:
+ msglines.append(" "*ex.offset + '^')
+ msglines.append("(code was compiled probably from here: %s)" % filename)
+ newex = SyntaxError('\n'.join(msglines))
+ newex.offset = ex.offset
+ newex.lineno = ex.lineno
+ newex.text = ex.text
+ raise newex
+ else:
+ if flag & _AST_FLAG:
+ return co
+ lines = [(x + "\n") for x in self.lines]
+ import linecache
+ linecache.cache[filename] = (1, None, lines, filename)
+ return co
+
+#
+# public API shortcut functions
+#
+
+def compile_(source, filename=None, mode='exec', flags=
+ generators.compiler_flag, dont_inherit=0):
+ """ compile the given source to a raw code object,
+ and maintain an internal cache which allows later
+ retrieval of the source code for the code object
+ and any recursively created code objects.
+ """
+ if _ast is not None and isinstance(source, _ast.AST):
+ # XXX should Source support having AST?
+ return cpy_compile(source, filename, mode, flags, dont_inherit)
+ _genframe = sys._getframe(1) # the caller
+ s = Source(source)
+ co = s.compile(filename, mode, flags, _genframe=_genframe)
+ return co
+
+
+def getfslineno(obj):
+ """ Return source location (path, lineno) for the given object.
+ If the source cannot be determined return ("", -1)
+ """
+ try:
+ code = py.code.Code(obj)
+ except TypeError:
+ try:
+ fn = (inspect.getsourcefile(obj) or
+ inspect.getfile(obj))
+ except TypeError:
+ return "", -1
+
+ fspath = fn and py.path.local(fn) or None
+ lineno = -1
+ if fspath:
+ try:
+ _, lineno = findsource(obj)
+ except IOError:
+ pass
+ else:
+ fspath = code.path
+ lineno = code.firstlineno
+ assert isinstance(lineno, int)
+ return fspath, lineno
+
+#
+# helper functions
+#
+
+def findsource(obj):
+ try:
+ sourcelines, lineno = inspect.findsource(obj)
+ except py.builtin._sysex:
+ raise
+ except:
+ return None, -1
+ source = Source()
+ source.lines = [line.rstrip() for line in sourcelines]
+ return source, lineno
+
+def getsource(obj, **kwargs):
+ obj = py.code.getrawcode(obj)
+ try:
+ strsrc = inspect.getsource(obj)
+ except IndentationError:
+ strsrc = "\"Buggy python version consider upgrading, cannot get source\""
+ assert isinstance(strsrc, str)
+ return Source(strsrc, **kwargs)
+
+def deindent(lines, offset=None):
+ if offset is None:
+ for line in lines:
+ line = line.expandtabs()
+ s = line.lstrip()
+ if s:
+ offset = len(line)-len(s)
+ break
+ else:
+ offset = 0
+ if offset == 0:
+ return list(lines)
+ newlines = []
+ def readline_generator(lines):
+ for line in lines:
+ yield line + '\n'
+ while True:
+ yield ''
+
+ it = readline_generator(lines)
+
+ try:
+ for _, _, (sline, _), (eline, _), _ in tokenize.generate_tokens(lambda: next(it)):
+ if sline > len(lines):
+ break # End of input reached
+ if sline > len(newlines):
+ line = lines[sline - 1].expandtabs()
+ if line.lstrip() and line[:offset].isspace():
+ line = line[offset:] # Deindent
+ newlines.append(line)
+
+ for i in range(sline, eline):
+ # Don't deindent continuing lines of
+ # multiline tokens (i.e. multiline strings)
+ newlines.append(lines[i])
+ except (IndentationError, tokenize.TokenError):
+ pass
+ # Add any lines we didn't see. E.g. if an exception was raised.
+ newlines.extend(lines[len(newlines):])
+ return newlines
+
+
+def get_statement_startend2(lineno, node):
+ import ast
+ # flatten all statements and except handlers into one lineno-list
+ # AST's line numbers start indexing at 1
+ l = []
+ for x in ast.walk(node):
+ if isinstance(x, _ast.stmt) or isinstance(x, _ast.ExceptHandler):
+ l.append(x.lineno - 1)
+ for name in "finalbody", "orelse":
+ val = getattr(x, name, None)
+ if val:
+ # treat the finally/orelse part as its own statement
+ l.append(val[0].lineno - 1 - 1)
+ l.sort()
+ insert_index = bisect_right(l, lineno)
+ start = l[insert_index - 1]
+ if insert_index >= len(l):
+ end = None
+ else:
+ end = l[insert_index]
+ return start, end
+
+
+def getstatementrange_ast(lineno, source, assertion=False, astnode=None):
+ if astnode is None:
+ content = str(source)
+ try:
+ astnode = compile(content, "source", "exec", 1024) # 1024 for AST
+ except ValueError:
+ start, end = getstatementrange_old(lineno, source, assertion)
+ return None, start, end
+ start, end = get_statement_startend2(lineno, astnode)
+ # we need to correct the end:
+ # - ast-parsing strips comments
+ # - there might be empty lines
+ # - we might have lesser indented code blocks at the end
+ if end is None:
+ end = len(source.lines)
+
+ if end > start + 1:
+ # make sure we don't span differently indented code blocks
+ # by using the BlockFinder helper used which inspect.getsource() uses itself
+ block_finder = inspect.BlockFinder()
+ # if we start with an indented line, put blockfinder to "started" mode
+ block_finder.started = source.lines[start][0].isspace()
+ it = ((x + "\n") for x in source.lines[start:end])
+ try:
+ for tok in tokenize.generate_tokens(lambda: next(it)):
+ block_finder.tokeneater(*tok)
+ except (inspect.EndOfBlock, IndentationError):
+ end = block_finder.last + start
+ except Exception:
+ pass
+
+ # the end might still point to a comment or empty line, correct it
+ while end:
+ line = source.lines[end - 1].lstrip()
+ if line.startswith("#") or not line:
+ end -= 1
+ else:
+ break
+ return astnode, start, end
+
+
+def getstatementrange_old(lineno, source, assertion=False):
+ """ return (start, end) tuple which spans the minimal
+ statement region which containing the given lineno.
+ raise an IndexError if no such statementrange can be found.
+ """
+ # XXX this logic is only used on python2.4 and below
+ # 1. find the start of the statement
+ from codeop import compile_command
+ for start in range(lineno, -1, -1):
+ if assertion:
+ line = source.lines[start]
+ # the following lines are not fully tested, change with care
+ if 'super' in line and 'self' in line and '__init__' in line:
+ raise IndexError("likely a subclass")
+ if "assert" not in line and "raise" not in line:
+ continue
+ trylines = source.lines[start:lineno+1]
+ # quick hack to prepare parsing an indented line with
+ # compile_command() (which errors on "return" outside defs)
+ trylines.insert(0, 'def xxx():')
+ trysource = '\n '.join(trylines)
+ # ^ space here
+ try:
+ compile_command(trysource)
+ except (SyntaxError, OverflowError, ValueError):
+ continue
+
+ # 2. find the end of the statement
+ for end in range(lineno+1, len(source)+1):
+ trysource = source[start:end]
+ if trysource.isparseable():
+ return start, end
+ raise SyntaxError("no valid source range around line %d " % (lineno,))
+
+
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_error.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_error.py
new file mode 100644
index 00000000000..a6375de9fa2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_error.py
@@ -0,0 +1,91 @@
+"""
+create errno-specific classes for IO or os calls.
+
+"""
+from types import ModuleType
+import sys, os, errno
+
+class Error(EnvironmentError):
+ def __repr__(self):
+ return "%s.%s %r: %s " %(self.__class__.__module__,
+ self.__class__.__name__,
+ self.__class__.__doc__,
+ " ".join(map(str, self.args)),
+ #repr(self.args)
+ )
+
+ def __str__(self):
+ s = "[%s]: %s" %(self.__class__.__doc__,
+ " ".join(map(str, self.args)),
+ )
+ return s
+
+_winerrnomap = {
+ 2: errno.ENOENT,
+ 3: errno.ENOENT,
+ 17: errno.EEXIST,
+ 18: errno.EXDEV,
+ 13: errno.EBUSY, # empty cd drive, but ENOMEDIUM seems unavailiable
+ 22: errno.ENOTDIR,
+ 20: errno.ENOTDIR,
+ 267: errno.ENOTDIR,
+ 5: errno.EACCES, # anything better?
+}
+
+class ErrorMaker(ModuleType):
+ """ lazily provides Exception classes for each possible POSIX errno
+ (as defined per the 'errno' module). All such instances
+ subclass EnvironmentError.
+ """
+ Error = Error
+ _errno2class = {}
+
+ def __getattr__(self, name):
+ if name[0] == "_":
+ raise AttributeError(name)
+ eno = getattr(errno, name)
+ cls = self._geterrnoclass(eno)
+ setattr(self, name, cls)
+ return cls
+
+ def _geterrnoclass(self, eno):
+ try:
+ return self._errno2class[eno]
+ except KeyError:
+ clsname = errno.errorcode.get(eno, "UnknownErrno%d" %(eno,))
+ errorcls = type(Error)(clsname, (Error,),
+ {'__module__':'py.error',
+ '__doc__': os.strerror(eno)})
+ self._errno2class[eno] = errorcls
+ return errorcls
+
+ def checked_call(self, func, *args, **kwargs):
+ """ call a function and raise an errno-exception if applicable. """
+ __tracebackhide__ = True
+ try:
+ return func(*args, **kwargs)
+ except self.Error:
+ raise
+ except (OSError, EnvironmentError):
+ cls, value, tb = sys.exc_info()
+ if not hasattr(value, 'errno'):
+ raise
+ __tracebackhide__ = False
+ errno = value.errno
+ try:
+ if not isinstance(value, WindowsError):
+ raise NameError
+ except NameError:
+ # we are not on Windows, or we got a proper OSError
+ cls = self._geterrnoclass(errno)
+ else:
+ try:
+ cls = self._geterrnoclass(_winerrnomap[errno])
+ except KeyError:
+ raise value
+ raise cls("%s%r" % (func.__name__, args))
+ __tracebackhide__ = True
+
+
+error = ErrorMaker('py.error')
+sys.modules[error.__name__] = error \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_io/__init__.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_io/__init__.py
index 835f01f3ab9..835f01f3ab9 100644
--- a/tests/wpt/web-platform-tests/tools/py/py/_io/__init__.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_io/__init__.py
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_io/capture.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_io/capture.py
index bc157ed978f..bc157ed978f 100644
--- a/tests/wpt/web-platform-tests/tools/py/py/_io/capture.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_io/capture.py
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_io/saferepr.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_io/saferepr.py
index 8518290efdd..8518290efdd 100644
--- a/tests/wpt/web-platform-tests/tools/py/py/_io/saferepr.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_io/saferepr.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_io/terminalwriter.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_io/terminalwriter.py
new file mode 100644
index 00000000000..74d31259dac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_io/terminalwriter.py
@@ -0,0 +1,384 @@
+"""
+
+Helper functions for writing to terminals and files.
+
+"""
+
+
+import sys, os
+import py
+py3k = sys.version_info[0] >= 3
+from py.builtin import text, bytes
+
+win32_and_ctypes = False
+colorama = None
+if sys.platform == "win32":
+ try:
+ import colorama
+ except ImportError:
+ try:
+ import ctypes
+ win32_and_ctypes = True
+ except ImportError:
+ pass
+
+
+def _getdimensions():
+ import termios,fcntl,struct
+ call = fcntl.ioctl(1,termios.TIOCGWINSZ,"\000"*8)
+ height,width = struct.unpack( "hhhh", call ) [:2]
+ return height, width
+
+
+def get_terminal_width():
+ width = 0
+ try:
+ _, width = _getdimensions()
+ except py.builtin._sysex:
+ raise
+ except:
+ # pass to fallback below
+ pass
+
+ if width == 0:
+ # FALLBACK:
+ # * some exception happened
+ # * or this is emacs terminal which reports (0,0)
+ width = int(os.environ.get('COLUMNS', 80))
+
+ # XXX the windows getdimensions may be bogus, let's sanify a bit
+ if width < 40:
+ width = 80
+ return width
+
+terminal_width = get_terminal_width()
+
+# XXX unify with _escaped func below
+def ansi_print(text, esc, file=None, newline=True, flush=False):
+ if file is None:
+ file = sys.stderr
+ text = text.rstrip()
+ if esc and not isinstance(esc, tuple):
+ esc = (esc,)
+ if esc and sys.platform != "win32" and file.isatty():
+ text = (''.join(['\x1b[%sm' % cod for cod in esc]) +
+ text +
+ '\x1b[0m') # ANSI color code "reset"
+ if newline:
+ text += '\n'
+
+ if esc and win32_and_ctypes and file.isatty():
+ if 1 in esc:
+ bold = True
+ esc = tuple([x for x in esc if x != 1])
+ else:
+ bold = False
+ esctable = {() : FOREGROUND_WHITE, # normal
+ (31,): FOREGROUND_RED, # red
+ (32,): FOREGROUND_GREEN, # green
+ (33,): FOREGROUND_GREEN|FOREGROUND_RED, # yellow
+ (34,): FOREGROUND_BLUE, # blue
+ (35,): FOREGROUND_BLUE|FOREGROUND_RED, # purple
+ (36,): FOREGROUND_BLUE|FOREGROUND_GREEN, # cyan
+ (37,): FOREGROUND_WHITE, # white
+ (39,): FOREGROUND_WHITE, # reset
+ }
+ attr = esctable.get(esc, FOREGROUND_WHITE)
+ if bold:
+ attr |= FOREGROUND_INTENSITY
+ STD_OUTPUT_HANDLE = -11
+ STD_ERROR_HANDLE = -12
+ if file is sys.stderr:
+ handle = GetStdHandle(STD_ERROR_HANDLE)
+ else:
+ handle = GetStdHandle(STD_OUTPUT_HANDLE)
+ oldcolors = GetConsoleInfo(handle).wAttributes
+ attr |= (oldcolors & 0x0f0)
+ SetConsoleTextAttribute(handle, attr)
+ while len(text) > 32768:
+ file.write(text[:32768])
+ text = text[32768:]
+ if text:
+ file.write(text)
+ SetConsoleTextAttribute(handle, oldcolors)
+ else:
+ file.write(text)
+
+ if flush:
+ file.flush()
+
+def should_do_markup(file):
+ if os.environ.get('PY_COLORS') == '1':
+ return True
+ if os.environ.get('PY_COLORS') == '0':
+ return False
+ return hasattr(file, 'isatty') and file.isatty() \
+ and os.environ.get('TERM') != 'dumb' \
+ and not (sys.platform.startswith('java') and os._name == 'nt')
+
+class TerminalWriter(object):
+ _esctable = dict(black=30, red=31, green=32, yellow=33,
+ blue=34, purple=35, cyan=36, white=37,
+ Black=40, Red=41, Green=42, Yellow=43,
+ Blue=44, Purple=45, Cyan=46, White=47,
+ bold=1, light=2, blink=5, invert=7)
+
+ # XXX deprecate stringio argument
+ def __init__(self, file=None, stringio=False, encoding=None):
+ if file is None:
+ if stringio:
+ self.stringio = file = py.io.TextIO()
+ else:
+ from sys import stdout as file
+ elif py.builtin.callable(file) and not (
+ hasattr(file, "write") and hasattr(file, "flush")):
+ file = WriteFile(file, encoding=encoding)
+ if hasattr(file, "isatty") and file.isatty() and colorama:
+ file = colorama.AnsiToWin32(file).stream
+ self.encoding = encoding or getattr(file, 'encoding', "utf-8")
+ self._file = file
+ self.hasmarkup = should_do_markup(file)
+ self._lastlen = 0
+ self._chars_on_current_line = 0
+
+ @property
+ def fullwidth(self):
+ if hasattr(self, '_terminal_width'):
+ return self._terminal_width
+ return get_terminal_width()
+
+ @fullwidth.setter
+ def fullwidth(self, value):
+ self._terminal_width = value
+
+ @property
+ def chars_on_current_line(self):
+ """Return the number of characters written so far in the current line.
+
+ Please note that this count does not produce correct results after a reline() call,
+ see #164.
+
+ .. versionadded:: 1.5.0
+
+ :rtype: int
+ """
+ return self._chars_on_current_line
+
+ def _escaped(self, text, esc):
+ if esc and self.hasmarkup:
+ text = (''.join(['\x1b[%sm' % cod for cod in esc]) +
+ text +'\x1b[0m')
+ return text
+
+ def markup(self, text, **kw):
+ esc = []
+ for name in kw:
+ if name not in self._esctable:
+ raise ValueError("unknown markup: %r" %(name,))
+ if kw[name]:
+ esc.append(self._esctable[name])
+ return self._escaped(text, tuple(esc))
+
+ def sep(self, sepchar, title=None, fullwidth=None, **kw):
+ if fullwidth is None:
+ fullwidth = self.fullwidth
+ # the goal is to have the line be as long as possible
+ # under the condition that len(line) <= fullwidth
+ if sys.platform == "win32":
+ # if we print in the last column on windows we are on a
+ # new line but there is no way to verify/neutralize this
+ # (we may not know the exact line width)
+ # so let's be defensive to avoid empty lines in the output
+ fullwidth -= 1
+ if title is not None:
+ # we want 2 + 2*len(fill) + len(title) <= fullwidth
+ # i.e. 2 + 2*len(sepchar)*N + len(title) <= fullwidth
+ # 2*len(sepchar)*N <= fullwidth - len(title) - 2
+ # N <= (fullwidth - len(title) - 2) // (2*len(sepchar))
+ N = (fullwidth - len(title) - 2) // (2*len(sepchar))
+ fill = sepchar * N
+ line = "%s %s %s" % (fill, title, fill)
+ else:
+ # we want len(sepchar)*N <= fullwidth
+ # i.e. N <= fullwidth // len(sepchar)
+ line = sepchar * (fullwidth // len(sepchar))
+ # in some situations there is room for an extra sepchar at the right,
+ # in particular if we consider that with a sepchar like "_ " the
+ # trailing space is not important at the end of the line
+ if len(line) + len(sepchar.rstrip()) <= fullwidth:
+ line += sepchar.rstrip()
+
+ self.line(line, **kw)
+
+ def write(self, msg, **kw):
+ if msg:
+ if not isinstance(msg, (bytes, text)):
+ msg = text(msg)
+
+ self._update_chars_on_current_line(msg)
+
+ if self.hasmarkup and kw:
+ markupmsg = self.markup(msg, **kw)
+ else:
+ markupmsg = msg
+ write_out(self._file, markupmsg)
+
+ def _update_chars_on_current_line(self, text):
+ fields = text.rsplit('\n', 1)
+ if '\n' in text:
+ self._chars_on_current_line = len(fields[-1])
+ else:
+ self._chars_on_current_line += len(fields[-1])
+
+ def line(self, s='', **kw):
+ self.write(s, **kw)
+ self._checkfill(s)
+ self.write('\n')
+
+ def reline(self, line, **kw):
+ if not self.hasmarkup:
+ raise ValueError("cannot use rewrite-line without terminal")
+ self.write(line, **kw)
+ self._checkfill(line)
+ self.write('\r')
+ self._lastlen = len(line)
+
+ def _checkfill(self, line):
+ diff2last = self._lastlen - len(line)
+ if diff2last > 0:
+ self.write(" " * diff2last)
+
+class Win32ConsoleWriter(TerminalWriter):
+ def write(self, msg, **kw):
+ if msg:
+ if not isinstance(msg, (bytes, text)):
+ msg = text(msg)
+
+ self._update_chars_on_current_line(msg)
+
+ oldcolors = None
+ if self.hasmarkup and kw:
+ handle = GetStdHandle(STD_OUTPUT_HANDLE)
+ oldcolors = GetConsoleInfo(handle).wAttributes
+ default_bg = oldcolors & 0x00F0
+ attr = default_bg
+ if kw.pop('bold', False):
+ attr |= FOREGROUND_INTENSITY
+
+ if kw.pop('red', False):
+ attr |= FOREGROUND_RED
+ elif kw.pop('blue', False):
+ attr |= FOREGROUND_BLUE
+ elif kw.pop('green', False):
+ attr |= FOREGROUND_GREEN
+ elif kw.pop('yellow', False):
+ attr |= FOREGROUND_GREEN|FOREGROUND_RED
+ else:
+ attr |= oldcolors & 0x0007
+
+ SetConsoleTextAttribute(handle, attr)
+ write_out(self._file, msg)
+ if oldcolors:
+ SetConsoleTextAttribute(handle, oldcolors)
+
+class WriteFile(object):
+ def __init__(self, writemethod, encoding=None):
+ self.encoding = encoding
+ self._writemethod = writemethod
+
+ def write(self, data):
+ if self.encoding:
+ data = data.encode(self.encoding, "replace")
+ self._writemethod(data)
+
+ def flush(self):
+ return
+
+
+if win32_and_ctypes:
+ TerminalWriter = Win32ConsoleWriter
+ import ctypes
+ from ctypes import wintypes
+
+ # ctypes access to the Windows console
+ STD_OUTPUT_HANDLE = -11
+ STD_ERROR_HANDLE = -12
+ FOREGROUND_BLACK = 0x0000 # black text
+ FOREGROUND_BLUE = 0x0001 # text color contains blue.
+ FOREGROUND_GREEN = 0x0002 # text color contains green.
+ FOREGROUND_RED = 0x0004 # text color contains red.
+ FOREGROUND_WHITE = 0x0007
+ FOREGROUND_INTENSITY = 0x0008 # text color is intensified.
+ BACKGROUND_BLACK = 0x0000 # background color black
+ BACKGROUND_BLUE = 0x0010 # background color contains blue.
+ BACKGROUND_GREEN = 0x0020 # background color contains green.
+ BACKGROUND_RED = 0x0040 # background color contains red.
+ BACKGROUND_WHITE = 0x0070
+ BACKGROUND_INTENSITY = 0x0080 # background color is intensified.
+
+ SHORT = ctypes.c_short
+ class COORD(ctypes.Structure):
+ _fields_ = [('X', SHORT),
+ ('Y', SHORT)]
+ class SMALL_RECT(ctypes.Structure):
+ _fields_ = [('Left', SHORT),
+ ('Top', SHORT),
+ ('Right', SHORT),
+ ('Bottom', SHORT)]
+ class CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
+ _fields_ = [('dwSize', COORD),
+ ('dwCursorPosition', COORD),
+ ('wAttributes', wintypes.WORD),
+ ('srWindow', SMALL_RECT),
+ ('dwMaximumWindowSize', COORD)]
+
+ _GetStdHandle = ctypes.windll.kernel32.GetStdHandle
+ _GetStdHandle.argtypes = [wintypes.DWORD]
+ _GetStdHandle.restype = wintypes.HANDLE
+ def GetStdHandle(kind):
+ return _GetStdHandle(kind)
+
+ SetConsoleTextAttribute = ctypes.windll.kernel32.SetConsoleTextAttribute
+ SetConsoleTextAttribute.argtypes = [wintypes.HANDLE, wintypes.WORD]
+ SetConsoleTextAttribute.restype = wintypes.BOOL
+
+ _GetConsoleScreenBufferInfo = \
+ ctypes.windll.kernel32.GetConsoleScreenBufferInfo
+ _GetConsoleScreenBufferInfo.argtypes = [wintypes.HANDLE,
+ ctypes.POINTER(CONSOLE_SCREEN_BUFFER_INFO)]
+ _GetConsoleScreenBufferInfo.restype = wintypes.BOOL
+ def GetConsoleInfo(handle):
+ info = CONSOLE_SCREEN_BUFFER_INFO()
+ _GetConsoleScreenBufferInfo(handle, ctypes.byref(info))
+ return info
+
+ def _getdimensions():
+ handle = GetStdHandle(STD_OUTPUT_HANDLE)
+ info = GetConsoleInfo(handle)
+ # Substract one from the width, otherwise the cursor wraps
+ # and the ending \n causes an empty line to display.
+ return info.dwSize.Y, info.dwSize.X - 1
+
+def write_out(fil, msg):
+ # XXX sometimes "msg" is of type bytes, sometimes text which
+ # complicates the situation. Should we try to enforce unicode?
+ try:
+ # on py27 and above writing out to sys.stdout with an encoding
+ # should usually work for unicode messages (if the encoding is
+ # capable of it)
+ fil.write(msg)
+ except UnicodeEncodeError:
+ # on py26 it might not work because stdout expects bytes
+ if fil.encoding:
+ try:
+ fil.write(msg.encode(fil.encoding))
+ except UnicodeEncodeError:
+ # it might still fail if the encoding is not capable
+ pass
+ else:
+ fil.flush()
+ return
+ # fallback: escape all unicode characters
+ msg = msg.encode("unicode-escape").decode("ascii")
+ fil.write(msg)
+ fil.flush()
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_log/__init__.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_log/__init__.py
index fad62e960d4..fad62e960d4 100644
--- a/tests/wpt/web-platform-tests/tools/py/py/_log/__init__.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_log/__init__.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_log/log.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_log/log.py
new file mode 100644
index 00000000000..56969bcb58c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_log/log.py
@@ -0,0 +1,206 @@
+"""
+basic logging functionality based on a producer/consumer scheme.
+
+XXX implement this API: (maybe put it into slogger.py?)
+
+ log = Logger(
+ info=py.log.STDOUT,
+ debug=py.log.STDOUT,
+ command=None)
+ log.info("hello", "world")
+ log.command("hello", "world")
+
+ log = Logger(info=Logger(something=...),
+ debug=py.log.STDOUT,
+ command=None)
+"""
+import py
+import sys
+
+
+class Message(object):
+ def __init__(self, keywords, args):
+ self.keywords = keywords
+ self.args = args
+
+ def content(self):
+ return " ".join(map(str, self.args))
+
+ def prefix(self):
+ return "[%s] " % (":".join(self.keywords))
+
+ def __str__(self):
+ return self.prefix() + self.content()
+
+
+class Producer(object):
+ """ (deprecated) Log producer API which sends messages to be logged
+ to a 'consumer' object, which then prints them to stdout,
+ stderr, files, etc. Used extensively by PyPy-1.1.
+ """
+
+ Message = Message # to allow later customization
+ keywords2consumer = {}
+
+ def __init__(self, keywords, keywordmapper=None, **kw):
+ if hasattr(keywords, 'split'):
+ keywords = tuple(keywords.split())
+ self._keywords = keywords
+ if keywordmapper is None:
+ keywordmapper = default_keywordmapper
+ self._keywordmapper = keywordmapper
+
+ def __repr__(self):
+ return "<py.log.Producer %s>" % ":".join(self._keywords)
+
+ def __getattr__(self, name):
+ if '_' in name:
+ raise AttributeError(name)
+ producer = self.__class__(self._keywords + (name,))
+ setattr(self, name, producer)
+ return producer
+
+ def __call__(self, *args):
+ """ write a message to the appropriate consumer(s) """
+ func = self._keywordmapper.getconsumer(self._keywords)
+ if func is not None:
+ func(self.Message(self._keywords, args))
+
+class KeywordMapper:
+ def __init__(self):
+ self.keywords2consumer = {}
+
+ def getstate(self):
+ return self.keywords2consumer.copy()
+
+ def setstate(self, state):
+ self.keywords2consumer.clear()
+ self.keywords2consumer.update(state)
+
+ def getconsumer(self, keywords):
+ """ return a consumer matching the given keywords.
+
+ tries to find the most suitable consumer by walking, starting from
+ the back, the list of keywords, the first consumer matching a
+ keyword is returned (falling back to py.log.default)
+ """
+ for i in range(len(keywords), 0, -1):
+ try:
+ return self.keywords2consumer[keywords[:i]]
+ except KeyError:
+ continue
+ return self.keywords2consumer.get('default', default_consumer)
+
+ def setconsumer(self, keywords, consumer):
+ """ set a consumer for a set of keywords. """
+ # normalize to tuples
+ if isinstance(keywords, str):
+ keywords = tuple(filter(None, keywords.split()))
+ elif hasattr(keywords, '_keywords'):
+ keywords = keywords._keywords
+ elif not isinstance(keywords, tuple):
+ raise TypeError("key %r is not a string or tuple" % (keywords,))
+ if consumer is not None and not py.builtin.callable(consumer):
+ if not hasattr(consumer, 'write'):
+ raise TypeError(
+ "%r should be None, callable or file-like" % (consumer,))
+ consumer = File(consumer)
+ self.keywords2consumer[keywords] = consumer
+
+
+def default_consumer(msg):
+ """ the default consumer, prints the message to stdout (using 'print') """
+ sys.stderr.write(str(msg)+"\n")
+
+default_keywordmapper = KeywordMapper()
+
+
+def setconsumer(keywords, consumer):
+ default_keywordmapper.setconsumer(keywords, consumer)
+
+
+def setstate(state):
+ default_keywordmapper.setstate(state)
+
+
+def getstate():
+ return default_keywordmapper.getstate()
+
+#
+# Consumers
+#
+
+
+class File(object):
+ """ log consumer wrapping a file(-like) object """
+ def __init__(self, f):
+ assert hasattr(f, 'write')
+ # assert isinstance(f, file) or not hasattr(f, 'open')
+ self._file = f
+
+ def __call__(self, msg):
+ """ write a message to the log """
+ self._file.write(str(msg) + "\n")
+ if hasattr(self._file, 'flush'):
+ self._file.flush()
+
+
+class Path(object):
+ """ log consumer that opens and writes to a Path """
+ def __init__(self, filename, append=False,
+ delayed_create=False, buffering=False):
+ self._append = append
+ self._filename = str(filename)
+ self._buffering = buffering
+ if not delayed_create:
+ self._openfile()
+
+ def _openfile(self):
+ mode = self._append and 'a' or 'w'
+ f = open(self._filename, mode)
+ self._file = f
+
+ def __call__(self, msg):
+ """ write a message to the log """
+ if not hasattr(self, "_file"):
+ self._openfile()
+ self._file.write(str(msg) + "\n")
+ if not self._buffering:
+ self._file.flush()
+
+
+def STDOUT(msg):
+ """ consumer that writes to sys.stdout """
+ sys.stdout.write(str(msg)+"\n")
+
+
+def STDERR(msg):
+ """ consumer that writes to sys.stderr """
+ sys.stderr.write(str(msg)+"\n")
+
+
+class Syslog:
+ """ consumer that writes to the syslog daemon """
+
+ def __init__(self, priority=None):
+ if priority is None:
+ priority = self.LOG_INFO
+ self.priority = priority
+
+ def __call__(self, msg):
+ """ write a message to the log """
+ import syslog
+ syslog.syslog(self.priority, str(msg))
+
+
+try:
+ import syslog
+except ImportError:
+ pass
+else:
+ for _prio in "EMERG ALERT CRIT ERR WARNING NOTICE INFO DEBUG".split():
+ _prio = "LOG_" + _prio
+ try:
+ setattr(Syslog, _prio, getattr(syslog, _prio))
+ except AttributeError:
+ pass
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_log/warning.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_log/warning.py
new file mode 100644
index 00000000000..6ef20d98a2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_log/warning.py
@@ -0,0 +1,79 @@
+import py, sys
+
+class DeprecationWarning(DeprecationWarning):
+ def __init__(self, msg, path, lineno):
+ self.msg = msg
+ self.path = path
+ self.lineno = lineno
+ def __repr__(self):
+ return "%s:%d: %s" %(self.path, self.lineno+1, self.msg)
+ def __str__(self):
+ return self.msg
+
+def _apiwarn(startversion, msg, stacklevel=2, function=None):
+ # below is mostly COPIED from python2.4/warnings.py's def warn()
+ # Get context information
+ if isinstance(stacklevel, str):
+ frame = sys._getframe(1)
+ level = 1
+ found = frame.f_code.co_filename.find(stacklevel) != -1
+ while frame:
+ co = frame.f_code
+ if co.co_filename.find(stacklevel) == -1:
+ if found:
+ stacklevel = level
+ break
+ else:
+ found = True
+ level += 1
+ frame = frame.f_back
+ else:
+ stacklevel = 1
+ msg = "%s (since version %s)" %(msg, startversion)
+ warn(msg, stacklevel=stacklevel+1, function=function)
+
+
+def warn(msg, stacklevel=1, function=None):
+ if function is not None:
+ import inspect
+ filename = inspect.getfile(function)
+ lineno = py.code.getrawcode(function).co_firstlineno
+ else:
+ try:
+ caller = sys._getframe(stacklevel)
+ except ValueError:
+ globals = sys.__dict__
+ lineno = 1
+ else:
+ globals = caller.f_globals
+ lineno = caller.f_lineno
+ if '__name__' in globals:
+ module = globals['__name__']
+ else:
+ module = "<string>"
+ filename = globals.get('__file__')
+ if filename:
+ fnl = filename.lower()
+ if fnl.endswith(".pyc") or fnl.endswith(".pyo"):
+ filename = filename[:-1]
+ elif fnl.endswith("$py.class"):
+ filename = filename.replace('$py.class', '.py')
+ else:
+ if module == "__main__":
+ try:
+ filename = sys.argv[0]
+ except AttributeError:
+ # embedded interpreters don't have sys.argv, see bug #839151
+ filename = '__main__'
+ if not filename:
+ filename = module
+ path = py.path.local(filename)
+ warning = DeprecationWarning(msg, path, lineno)
+ import warnings
+ warnings.warn_explicit(warning, category=Warning,
+ filename=str(warning.path),
+ lineno=warning.lineno,
+ registry=warnings.__dict__.setdefault(
+ "__warningsregistry__", {})
+ )
+
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_path/__init__.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_path/__init__.py
index 51f3246f807..51f3246f807 100644
--- a/tests/wpt/web-platform-tests/tools/py/py/_path/__init__.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_path/__init__.py
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_path/cacheutil.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_path/cacheutil.py
index 99225047502..99225047502 100644
--- a/tests/wpt/web-platform-tests/tools/py/py/_path/cacheutil.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_path/cacheutil.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_path/common.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_path/common.py
new file mode 100644
index 00000000000..2d490b56a86
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_path/common.py
@@ -0,0 +1,453 @@
+"""
+"""
+import warnings
+import os
+import sys
+import posixpath
+import fnmatch
+import py
+
+# Moved from local.py.
+iswin32 = sys.platform == "win32" or (getattr(os, '_name', False) == 'nt')
+
+try:
+ from os import fspath
+except ImportError:
+ def fspath(path):
+ """
+ Return the string representation of the path.
+ If str or bytes is passed in, it is returned unchanged.
+ This code comes from PEP 519, modified to support earlier versions of
+ python.
+
+ This is required for python < 3.6.
+ """
+ if isinstance(path, (py.builtin.text, py.builtin.bytes)):
+ return path
+
+ # Work from the object's type to match method resolution of other magic
+ # methods.
+ path_type = type(path)
+ try:
+ return path_type.__fspath__(path)
+ except AttributeError:
+ if hasattr(path_type, '__fspath__'):
+ raise
+ try:
+ import pathlib
+ except ImportError:
+ pass
+ else:
+ if isinstance(path, pathlib.PurePath):
+ return py.builtin.text(path)
+
+ raise TypeError("expected str, bytes or os.PathLike object, not "
+ + path_type.__name__)
+
+class Checkers:
+ _depend_on_existence = 'exists', 'link', 'dir', 'file'
+
+ def __init__(self, path):
+ self.path = path
+
+ def dir(self):
+ raise NotImplementedError
+
+ def file(self):
+ raise NotImplementedError
+
+ def dotfile(self):
+ return self.path.basename.startswith('.')
+
+ def ext(self, arg):
+ if not arg.startswith('.'):
+ arg = '.' + arg
+ return self.path.ext == arg
+
+ def exists(self):
+ raise NotImplementedError
+
+ def basename(self, arg):
+ return self.path.basename == arg
+
+ def basestarts(self, arg):
+ return self.path.basename.startswith(arg)
+
+ def relto(self, arg):
+ return self.path.relto(arg)
+
+ def fnmatch(self, arg):
+ return self.path.fnmatch(arg)
+
+ def endswith(self, arg):
+ return str(self.path).endswith(arg)
+
+ def _evaluate(self, kw):
+ for name, value in kw.items():
+ invert = False
+ meth = None
+ try:
+ meth = getattr(self, name)
+ except AttributeError:
+ if name[:3] == 'not':
+ invert = True
+ try:
+ meth = getattr(self, name[3:])
+ except AttributeError:
+ pass
+ if meth is None:
+ raise TypeError(
+ "no %r checker available for %r" % (name, self.path))
+ try:
+ if py.code.getrawcode(meth).co_argcount > 1:
+ if (not meth(value)) ^ invert:
+ return False
+ else:
+ if bool(value) ^ bool(meth()) ^ invert:
+ return False
+ except (py.error.ENOENT, py.error.ENOTDIR, py.error.EBUSY):
+ # EBUSY feels not entirely correct,
+ # but its kind of necessary since ENOMEDIUM
+ # is not accessible in python
+ for name in self._depend_on_existence:
+ if name in kw:
+ if kw.get(name):
+ return False
+ name = 'not' + name
+ if name in kw:
+ if not kw.get(name):
+ return False
+ return True
+
+class NeverRaised(Exception):
+ pass
+
+class PathBase(object):
+ """ shared implementation for filesystem path objects."""
+ Checkers = Checkers
+
+ def __div__(self, other):
+ return self.join(fspath(other))
+ __truediv__ = __div__ # py3k
+
+ def basename(self):
+ """ basename part of path. """
+ return self._getbyspec('basename')[0]
+ basename = property(basename, None, None, basename.__doc__)
+
+ def dirname(self):
+ """ dirname part of path. """
+ return self._getbyspec('dirname')[0]
+ dirname = property(dirname, None, None, dirname.__doc__)
+
+ def purebasename(self):
+ """ pure base name of the path."""
+ return self._getbyspec('purebasename')[0]
+ purebasename = property(purebasename, None, None, purebasename.__doc__)
+
+ def ext(self):
+ """ extension of the path (including the '.')."""
+ return self._getbyspec('ext')[0]
+ ext = property(ext, None, None, ext.__doc__)
+
+ def dirpath(self, *args, **kwargs):
+ """ return the directory path joined with any given path arguments. """
+ return self.new(basename='').join(*args, **kwargs)
+
+ def read_binary(self):
+ """ read and return a bytestring from reading the path. """
+ with self.open('rb') as f:
+ return f.read()
+
+ def read_text(self, encoding):
+ """ read and return a Unicode string from reading the path. """
+ with self.open("r", encoding=encoding) as f:
+ return f.read()
+
+
+ def read(self, mode='r'):
+ """ read and return a bytestring from reading the path. """
+ with self.open(mode) as f:
+ return f.read()
+
+ def readlines(self, cr=1):
+ """ read and return a list of lines from the path. if cr is False, the
+newline will be removed from the end of each line. """
+ if sys.version_info < (3, ):
+ mode = 'rU'
+ else: # python 3 deprecates mode "U" in favor of "newline" option
+ mode = 'r'
+
+ if not cr:
+ content = self.read(mode)
+ return content.split('\n')
+ else:
+ f = self.open(mode)
+ try:
+ return f.readlines()
+ finally:
+ f.close()
+
+ def load(self):
+ """ (deprecated) return object unpickled from self.read() """
+ f = self.open('rb')
+ try:
+ import pickle
+ return py.error.checked_call(pickle.load, f)
+ finally:
+ f.close()
+
+ def move(self, target):
+ """ move this path to target. """
+ if target.relto(self):
+ raise py.error.EINVAL(
+ target,
+ "cannot move path into a subdirectory of itself")
+ try:
+ self.rename(target)
+ except py.error.EXDEV: # invalid cross-device link
+ self.copy(target)
+ self.remove()
+
+ def __repr__(self):
+ """ return a string representation of this path. """
+ return repr(str(self))
+
+ def check(self, **kw):
+ """ check a path for existence and properties.
+
+ Without arguments, return True if the path exists, otherwise False.
+
+ valid checkers::
+
+ file=1 # is a file
+ file=0 # is not a file (may not even exist)
+ dir=1 # is a dir
+ link=1 # is a link
+ exists=1 # exists
+
+ You can specify multiple checker definitions, for example::
+
+ path.check(file=1, link=1) # a link pointing to a file
+ """
+ if not kw:
+ kw = {'exists': 1}
+ return self.Checkers(self)._evaluate(kw)
+
+ def fnmatch(self, pattern):
+ """return true if the basename/fullname matches the glob-'pattern'.
+
+ valid pattern characters::
+
+ * matches everything
+ ? matches any single character
+ [seq] matches any character in seq
+ [!seq] matches any char not in seq
+
+ If the pattern contains a path-separator then the full path
+ is used for pattern matching and a '*' is prepended to the
+ pattern.
+
+ if the pattern doesn't contain a path-separator the pattern
+ is only matched against the basename.
+ """
+ return FNMatcher(pattern)(self)
+
+ def relto(self, relpath):
+ """ return a string which is the relative part of the path
+ to the given 'relpath'.
+ """
+ if not isinstance(relpath, (str, PathBase)):
+ raise TypeError("%r: not a string or path object" %(relpath,))
+ strrelpath = str(relpath)
+ if strrelpath and strrelpath[-1] != self.sep:
+ strrelpath += self.sep
+ #assert strrelpath[-1] == self.sep
+ #assert strrelpath[-2] != self.sep
+ strself = self.strpath
+ if sys.platform == "win32" or getattr(os, '_name', None) == 'nt':
+ if os.path.normcase(strself).startswith(
+ os.path.normcase(strrelpath)):
+ return strself[len(strrelpath):]
+ elif strself.startswith(strrelpath):
+ return strself[len(strrelpath):]
+ return ""
+
+ def ensure_dir(self, *args):
+ """ ensure the path joined with args is a directory. """
+ return self.ensure(*args, **{"dir": True})
+
+ def bestrelpath(self, dest):
+ """ return a string which is a relative path from self
+ (assumed to be a directory) to dest such that
+ self.join(bestrelpath) == dest and if not such
+ path can be determined return dest.
+ """
+ try:
+ if self == dest:
+ return os.curdir
+ base = self.common(dest)
+ if not base: # can be the case on windows
+ return str(dest)
+ self2base = self.relto(base)
+ reldest = dest.relto(base)
+ if self2base:
+ n = self2base.count(self.sep) + 1
+ else:
+ n = 0
+ l = [os.pardir] * n
+ if reldest:
+ l.append(reldest)
+ target = dest.sep.join(l)
+ return target
+ except AttributeError:
+ return str(dest)
+
+ def exists(self):
+ return self.check()
+
+ def isdir(self):
+ return self.check(dir=1)
+
+ def isfile(self):
+ return self.check(file=1)
+
+ def parts(self, reverse=False):
+ """ return a root-first list of all ancestor directories
+ plus the path itself.
+ """
+ current = self
+ l = [self]
+ while 1:
+ last = current
+ current = current.dirpath()
+ if last == current:
+ break
+ l.append(current)
+ if not reverse:
+ l.reverse()
+ return l
+
+ def common(self, other):
+ """ return the common part shared with the other path
+ or None if there is no common part.
+ """
+ last = None
+ for x, y in zip(self.parts(), other.parts()):
+ if x != y:
+ return last
+ last = x
+ return last
+
+ def __add__(self, other):
+ """ return new path object with 'other' added to the basename"""
+ return self.new(basename=self.basename+str(other))
+
+ def __cmp__(self, other):
+ """ return sort value (-1, 0, +1). """
+ try:
+ return cmp(self.strpath, other.strpath)
+ except AttributeError:
+ return cmp(str(self), str(other)) # self.path, other.path)
+
+ def __lt__(self, other):
+ try:
+ return self.strpath < other.strpath
+ except AttributeError:
+ return str(self) < str(other)
+
+ def visit(self, fil=None, rec=None, ignore=NeverRaised, bf=False, sort=False):
+ """ yields all paths below the current one
+
+ fil is a filter (glob pattern or callable), if not matching the
+ path will not be yielded, defaulting to None (everything is
+ returned)
+
+ rec is a filter (glob pattern or callable) that controls whether
+ a node is descended, defaulting to None
+
+ ignore is an Exception class that is ignoredwhen calling dirlist()
+ on any of the paths (by default, all exceptions are reported)
+
+ bf if True will cause a breadthfirst search instead of the
+ default depthfirst. Default: False
+
+ sort if True will sort entries within each directory level.
+ """
+ for x in Visitor(fil, rec, ignore, bf, sort).gen(self):
+ yield x
+
+ def _sortlist(self, res, sort):
+ if sort:
+ if hasattr(sort, '__call__'):
+ warnings.warn(DeprecationWarning(
+ "listdir(sort=callable) is deprecated and breaks on python3"
+ ), stacklevel=3)
+ res.sort(sort)
+ else:
+ res.sort()
+
+ def samefile(self, other):
+ """ return True if other refers to the same stat object as self. """
+ return self.strpath == str(other)
+
+ def __fspath__(self):
+ return self.strpath
+
+class Visitor:
+ def __init__(self, fil, rec, ignore, bf, sort):
+ if isinstance(fil, py.builtin._basestring):
+ fil = FNMatcher(fil)
+ if isinstance(rec, py.builtin._basestring):
+ self.rec = FNMatcher(rec)
+ elif not hasattr(rec, '__call__') and rec:
+ self.rec = lambda path: True
+ else:
+ self.rec = rec
+ self.fil = fil
+ self.ignore = ignore
+ self.breadthfirst = bf
+ self.optsort = sort and sorted or (lambda x: x)
+
+ def gen(self, path):
+ try:
+ entries = path.listdir()
+ except self.ignore:
+ return
+ rec = self.rec
+ dirs = self.optsort([p for p in entries
+ if p.check(dir=1) and (rec is None or rec(p))])
+ if not self.breadthfirst:
+ for subdir in dirs:
+ for p in self.gen(subdir):
+ yield p
+ for p in self.optsort(entries):
+ if self.fil is None or self.fil(p):
+ yield p
+ if self.breadthfirst:
+ for subdir in dirs:
+ for p in self.gen(subdir):
+ yield p
+
+class FNMatcher:
+ def __init__(self, pattern):
+ self.pattern = pattern
+
+ def __call__(self, path):
+ pattern = self.pattern
+
+ if (pattern.find(path.sep) == -1 and
+ iswin32 and
+ pattern.find(posixpath.sep) != -1):
+ # Running on Windows, the pattern has no Windows path separators,
+ # and the pattern has one or more Posix path separators. Replace
+ # the Posix path separators with the Windows path separator.
+ pattern = pattern.replace(posixpath.sep, path.sep)
+
+ if pattern.find(path.sep) == -1:
+ name = path.basename
+ else:
+ name = str(path) # path.strpath # XXX svn?
+ if not os.path.isabs(pattern):
+ pattern = '*' + path.sep + pattern
+ return fnmatch.fnmatch(name, pattern)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_path/local.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_path/local.py
new file mode 100644
index 00000000000..c550fa2f1ab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_path/local.py
@@ -0,0 +1,992 @@
+"""
+local path implementation.
+"""
+from __future__ import with_statement
+
+from contextlib import contextmanager
+import sys, os, re, atexit, io, uuid
+import py
+from py._path import common
+from py._path.common import iswin32, fspath
+from stat import S_ISLNK, S_ISDIR, S_ISREG
+
+from os.path import abspath, normcase, normpath, isabs, exists, isdir, isfile, islink, dirname
+
+if sys.version_info > (3,0):
+ def map_as_list(func, iter):
+ return list(map(func, iter))
+else:
+ map_as_list = map
+
+class Stat(object):
+ def __getattr__(self, name):
+ return getattr(self._osstatresult, "st_" + name)
+
+ def __init__(self, path, osstatresult):
+ self.path = path
+ self._osstatresult = osstatresult
+
+ @property
+ def owner(self):
+ if iswin32:
+ raise NotImplementedError("XXX win32")
+ import pwd
+ entry = py.error.checked_call(pwd.getpwuid, self.uid)
+ return entry[0]
+
+ @property
+ def group(self):
+ """ return group name of file. """
+ if iswin32:
+ raise NotImplementedError("XXX win32")
+ import grp
+ entry = py.error.checked_call(grp.getgrgid, self.gid)
+ return entry[0]
+
+ def isdir(self):
+ return S_ISDIR(self._osstatresult.st_mode)
+
+ def isfile(self):
+ return S_ISREG(self._osstatresult.st_mode)
+
+ def islink(self):
+ st = self.path.lstat()
+ return S_ISLNK(self._osstatresult.st_mode)
+
+class PosixPath(common.PathBase):
+ def chown(self, user, group, rec=0):
+ """ change ownership to the given user and group.
+ user and group may be specified by a number or
+ by a name. if rec is True change ownership
+ recursively.
+ """
+ uid = getuserid(user)
+ gid = getgroupid(group)
+ if rec:
+ for x in self.visit(rec=lambda x: x.check(link=0)):
+ if x.check(link=0):
+ py.error.checked_call(os.chown, str(x), uid, gid)
+ py.error.checked_call(os.chown, str(self), uid, gid)
+
+ def readlink(self):
+ """ return value of a symbolic link. """
+ return py.error.checked_call(os.readlink, self.strpath)
+
+ def mklinkto(self, oldname):
+ """ posix style hard link to another name. """
+ py.error.checked_call(os.link, str(oldname), str(self))
+
+ def mksymlinkto(self, value, absolute=1):
+ """ create a symbolic link with the given value (pointing to another name). """
+ if absolute:
+ py.error.checked_call(os.symlink, str(value), self.strpath)
+ else:
+ base = self.common(value)
+ # with posix local paths '/' is always a common base
+ relsource = self.__class__(value).relto(base)
+ reldest = self.relto(base)
+ n = reldest.count(self.sep)
+ target = self.sep.join(('..', )*n + (relsource, ))
+ py.error.checked_call(os.symlink, target, self.strpath)
+
+def getuserid(user):
+ import pwd
+ if not isinstance(user, int):
+ user = pwd.getpwnam(user)[2]
+ return user
+
+def getgroupid(group):
+ import grp
+ if not isinstance(group, int):
+ group = grp.getgrnam(group)[2]
+ return group
+
+FSBase = not iswin32 and PosixPath or common.PathBase
+
+class LocalPath(FSBase):
+ """ object oriented interface to os.path and other local filesystem
+ related information.
+ """
+ class ImportMismatchError(ImportError):
+ """ raised on pyimport() if there is a mismatch of __file__'s"""
+
+ sep = os.sep
+ class Checkers(common.Checkers):
+ def _stat(self):
+ try:
+ return self._statcache
+ except AttributeError:
+ try:
+ self._statcache = self.path.stat()
+ except py.error.ELOOP:
+ self._statcache = self.path.lstat()
+ return self._statcache
+
+ def dir(self):
+ return S_ISDIR(self._stat().mode)
+
+ def file(self):
+ return S_ISREG(self._stat().mode)
+
+ def exists(self):
+ return self._stat()
+
+ def link(self):
+ st = self.path.lstat()
+ return S_ISLNK(st.mode)
+
+ def __init__(self, path=None, expanduser=False):
+ """ Initialize and return a local Path instance.
+
+ Path can be relative to the current directory.
+ If path is None it defaults to the current working directory.
+ If expanduser is True, tilde-expansion is performed.
+ Note that Path instances always carry an absolute path.
+ Note also that passing in a local path object will simply return
+ the exact same path object. Use new() to get a new copy.
+ """
+ if path is None:
+ self.strpath = py.error.checked_call(os.getcwd)
+ else:
+ try:
+ path = fspath(path)
+ except TypeError:
+ raise ValueError("can only pass None, Path instances "
+ "or non-empty strings to LocalPath")
+ if expanduser:
+ path = os.path.expanduser(path)
+ self.strpath = abspath(path)
+
+ def __hash__(self):
+ return hash(self.strpath)
+
+ def __eq__(self, other):
+ s1 = fspath(self)
+ try:
+ s2 = fspath(other)
+ except TypeError:
+ return False
+ if iswin32:
+ s1 = s1.lower()
+ try:
+ s2 = s2.lower()
+ except AttributeError:
+ return False
+ return s1 == s2
+
+ def __ne__(self, other):
+ return not (self == other)
+
+ def __lt__(self, other):
+ return fspath(self) < fspath(other)
+
+ def __gt__(self, other):
+ return fspath(self) > fspath(other)
+
+ def samefile(self, other):
+ """ return True if 'other' references the same file as 'self'.
+ """
+ other = fspath(other)
+ if not isabs(other):
+ other = abspath(other)
+ if self == other:
+ return True
+ if iswin32:
+ return False # there is no samefile
+ return py.error.checked_call(
+ os.path.samefile, self.strpath, other)
+
+ def remove(self, rec=1, ignore_errors=False):
+ """ remove a file or directory (or a directory tree if rec=1).
+ if ignore_errors is True, errors while removing directories will
+ be ignored.
+ """
+ if self.check(dir=1, link=0):
+ if rec:
+ # force remove of readonly files on windows
+ if iswin32:
+ self.chmod(0o700, rec=1)
+ import shutil
+ py.error.checked_call(
+ shutil.rmtree, self.strpath,
+ ignore_errors=ignore_errors)
+ else:
+ py.error.checked_call(os.rmdir, self.strpath)
+ else:
+ if iswin32:
+ self.chmod(0o700)
+ py.error.checked_call(os.remove, self.strpath)
+
+ def computehash(self, hashtype="md5", chunksize=524288):
+ """ return hexdigest of hashvalue for this file. """
+ try:
+ try:
+ import hashlib as mod
+ except ImportError:
+ if hashtype == "sha1":
+ hashtype = "sha"
+ mod = __import__(hashtype)
+ hash = getattr(mod, hashtype)()
+ except (AttributeError, ImportError):
+ raise ValueError("Don't know how to compute %r hash" %(hashtype,))
+ f = self.open('rb')
+ try:
+ while 1:
+ buf = f.read(chunksize)
+ if not buf:
+ return hash.hexdigest()
+ hash.update(buf)
+ finally:
+ f.close()
+
+ def new(self, **kw):
+ """ create a modified version of this path.
+ the following keyword arguments modify various path parts::
+
+ a:/some/path/to/a/file.ext
+ xx drive
+ xxxxxxxxxxxxxxxxx dirname
+ xxxxxxxx basename
+ xxxx purebasename
+ xxx ext
+ """
+ obj = object.__new__(self.__class__)
+ if not kw:
+ obj.strpath = self.strpath
+ return obj
+ drive, dirname, basename, purebasename,ext = self._getbyspec(
+ "drive,dirname,basename,purebasename,ext")
+ if 'basename' in kw:
+ if 'purebasename' in kw or 'ext' in kw:
+ raise ValueError("invalid specification %r" % kw)
+ else:
+ pb = kw.setdefault('purebasename', purebasename)
+ try:
+ ext = kw['ext']
+ except KeyError:
+ pass
+ else:
+ if ext and not ext.startswith('.'):
+ ext = '.' + ext
+ kw['basename'] = pb + ext
+
+ if ('dirname' in kw and not kw['dirname']):
+ kw['dirname'] = drive
+ else:
+ kw.setdefault('dirname', dirname)
+ kw.setdefault('sep', self.sep)
+ obj.strpath = normpath(
+ "%(dirname)s%(sep)s%(basename)s" % kw)
+ return obj
+
+ def _getbyspec(self, spec):
+ """ see new for what 'spec' can be. """
+ res = []
+ parts = self.strpath.split(self.sep)
+
+ args = filter(None, spec.split(',') )
+ append = res.append
+ for name in args:
+ if name == 'drive':
+ append(parts[0])
+ elif name == 'dirname':
+ append(self.sep.join(parts[:-1]))
+ else:
+ basename = parts[-1]
+ if name == 'basename':
+ append(basename)
+ else:
+ i = basename.rfind('.')
+ if i == -1:
+ purebasename, ext = basename, ''
+ else:
+ purebasename, ext = basename[:i], basename[i:]
+ if name == 'purebasename':
+ append(purebasename)
+ elif name == 'ext':
+ append(ext)
+ else:
+ raise ValueError("invalid part specification %r" % name)
+ return res
+
+ def dirpath(self, *args, **kwargs):
+ """ return the directory path joined with any given path arguments. """
+ if not kwargs:
+ path = object.__new__(self.__class__)
+ path.strpath = dirname(self.strpath)
+ if args:
+ path = path.join(*args)
+ return path
+ return super(LocalPath, self).dirpath(*args, **kwargs)
+
+ def join(self, *args, **kwargs):
+ """ return a new path by appending all 'args' as path
+ components. if abs=1 is used restart from root if any
+ of the args is an absolute path.
+ """
+ sep = self.sep
+ strargs = [fspath(arg) for arg in args]
+ strpath = self.strpath
+ if kwargs.get('abs'):
+ newargs = []
+ for arg in reversed(strargs):
+ if isabs(arg):
+ strpath = arg
+ strargs = newargs
+ break
+ newargs.insert(0, arg)
+ # special case for when we have e.g. strpath == "/"
+ actual_sep = "" if strpath.endswith(sep) else sep
+ for arg in strargs:
+ arg = arg.strip(sep)
+ if iswin32:
+ # allow unix style paths even on windows.
+ arg = arg.strip('/')
+ arg = arg.replace('/', sep)
+ strpath = strpath + actual_sep + arg
+ actual_sep = sep
+ obj = object.__new__(self.__class__)
+ obj.strpath = normpath(strpath)
+ return obj
+
+ def open(self, mode='r', ensure=False, encoding=None):
+ """ return an opened file with the given mode.
+
+ If ensure is True, create parent directories if needed.
+ """
+ if ensure:
+ self.dirpath().ensure(dir=1)
+ if encoding:
+ return py.error.checked_call(io.open, self.strpath, mode, encoding=encoding)
+ return py.error.checked_call(open, self.strpath, mode)
+
+ def _fastjoin(self, name):
+ child = object.__new__(self.__class__)
+ child.strpath = self.strpath + self.sep + name
+ return child
+
+ def islink(self):
+ return islink(self.strpath)
+
+ def check(self, **kw):
+ if not kw:
+ return exists(self.strpath)
+ if len(kw) == 1:
+ if "dir" in kw:
+ return not kw["dir"] ^ isdir(self.strpath)
+ if "file" in kw:
+ return not kw["file"] ^ isfile(self.strpath)
+ return super(LocalPath, self).check(**kw)
+
+ _patternchars = set("*?[" + os.path.sep)
+ def listdir(self, fil=None, sort=None):
+ """ list directory contents, possibly filter by the given fil func
+ and possibly sorted.
+ """
+ if fil is None and sort is None:
+ names = py.error.checked_call(os.listdir, self.strpath)
+ return map_as_list(self._fastjoin, names)
+ if isinstance(fil, py.builtin._basestring):
+ if not self._patternchars.intersection(fil):
+ child = self._fastjoin(fil)
+ if exists(child.strpath):
+ return [child]
+ return []
+ fil = common.FNMatcher(fil)
+ names = py.error.checked_call(os.listdir, self.strpath)
+ res = []
+ for name in names:
+ child = self._fastjoin(name)
+ if fil is None or fil(child):
+ res.append(child)
+ self._sortlist(res, sort)
+ return res
+
+ def size(self):
+ """ return size of the underlying file object """
+ return self.stat().size
+
+ def mtime(self):
+ """ return last modification time of the path. """
+ return self.stat().mtime
+
+ def copy(self, target, mode=False, stat=False):
+ """ copy path to target.
+
+ If mode is True, will copy copy permission from path to target.
+ If stat is True, copy permission, last modification
+ time, last access time, and flags from path to target.
+ """
+ if self.check(file=1):
+ if target.check(dir=1):
+ target = target.join(self.basename)
+ assert self!=target
+ copychunked(self, target)
+ if mode:
+ copymode(self.strpath, target.strpath)
+ if stat:
+ copystat(self, target)
+ else:
+ def rec(p):
+ return p.check(link=0)
+ for x in self.visit(rec=rec):
+ relpath = x.relto(self)
+ newx = target.join(relpath)
+ newx.dirpath().ensure(dir=1)
+ if x.check(link=1):
+ newx.mksymlinkto(x.readlink())
+ continue
+ elif x.check(file=1):
+ copychunked(x, newx)
+ elif x.check(dir=1):
+ newx.ensure(dir=1)
+ if mode:
+ copymode(x.strpath, newx.strpath)
+ if stat:
+ copystat(x, newx)
+
+ def rename(self, target):
+ """ rename this path to target. """
+ target = fspath(target)
+ return py.error.checked_call(os.rename, self.strpath, target)
+
+ def dump(self, obj, bin=1):
+ """ pickle object into path location"""
+ f = self.open('wb')
+ import pickle
+ try:
+ py.error.checked_call(pickle.dump, obj, f, bin)
+ finally:
+ f.close()
+
+ def mkdir(self, *args):
+ """ create & return the directory joined with args. """
+ p = self.join(*args)
+ py.error.checked_call(os.mkdir, fspath(p))
+ return p
+
+ def write_binary(self, data, ensure=False):
+ """ write binary data into path. If ensure is True create
+ missing parent directories.
+ """
+ if ensure:
+ self.dirpath().ensure(dir=1)
+ with self.open('wb') as f:
+ f.write(data)
+
+ def write_text(self, data, encoding, ensure=False):
+ """ write text data into path using the specified encoding.
+ If ensure is True create missing parent directories.
+ """
+ if ensure:
+ self.dirpath().ensure(dir=1)
+ with self.open('w', encoding=encoding) as f:
+ f.write(data)
+
+ def write(self, data, mode='w', ensure=False):
+ """ write data into path. If ensure is True create
+ missing parent directories.
+ """
+ if ensure:
+ self.dirpath().ensure(dir=1)
+ if 'b' in mode:
+ if not py.builtin._isbytes(data):
+ raise ValueError("can only process bytes")
+ else:
+ if not py.builtin._istext(data):
+ if not py.builtin._isbytes(data):
+ data = str(data)
+ else:
+ data = py.builtin._totext(data, sys.getdefaultencoding())
+ f = self.open(mode)
+ try:
+ f.write(data)
+ finally:
+ f.close()
+
+ def _ensuredirs(self):
+ parent = self.dirpath()
+ if parent == self:
+ return self
+ if parent.check(dir=0):
+ parent._ensuredirs()
+ if self.check(dir=0):
+ try:
+ self.mkdir()
+ except py.error.EEXIST:
+ # race condition: file/dir created by another thread/process.
+ # complain if it is not a dir
+ if self.check(dir=0):
+ raise
+ return self
+
+ def ensure(self, *args, **kwargs):
+ """ ensure that an args-joined path exists (by default as
+ a file). if you specify a keyword argument 'dir=True'
+ then the path is forced to be a directory path.
+ """
+ p = self.join(*args)
+ if kwargs.get('dir', 0):
+ return p._ensuredirs()
+ else:
+ p.dirpath()._ensuredirs()
+ if not p.check(file=1):
+ p.open('w').close()
+ return p
+
+ def stat(self, raising=True):
+ """ Return an os.stat() tuple. """
+ if raising == True:
+ return Stat(self, py.error.checked_call(os.stat, self.strpath))
+ try:
+ return Stat(self, os.stat(self.strpath))
+ except KeyboardInterrupt:
+ raise
+ except Exception:
+ return None
+
+ def lstat(self):
+ """ Return an os.lstat() tuple. """
+ return Stat(self, py.error.checked_call(os.lstat, self.strpath))
+
+ def setmtime(self, mtime=None):
+ """ set modification time for the given path. if 'mtime' is None
+ (the default) then the file's mtime is set to current time.
+
+ Note that the resolution for 'mtime' is platform dependent.
+ """
+ if mtime is None:
+ return py.error.checked_call(os.utime, self.strpath, mtime)
+ try:
+ return py.error.checked_call(os.utime, self.strpath, (-1, mtime))
+ except py.error.EINVAL:
+ return py.error.checked_call(os.utime, self.strpath, (self.atime(), mtime))
+
+ def chdir(self):
+ """ change directory to self and return old current directory """
+ try:
+ old = self.__class__()
+ except py.error.ENOENT:
+ old = None
+ py.error.checked_call(os.chdir, self.strpath)
+ return old
+
+
+ @contextmanager
+ def as_cwd(self):
+ """ return context manager which changes to current dir during the
+ managed "with" context. On __enter__ it returns the old dir.
+ """
+ old = self.chdir()
+ try:
+ yield old
+ finally:
+ old.chdir()
+
+ def realpath(self):
+ """ return a new path which contains no symbolic links."""
+ return self.__class__(os.path.realpath(self.strpath))
+
+ def atime(self):
+ """ return last access time of the path. """
+ return self.stat().atime
+
+ def __repr__(self):
+ return 'local(%r)' % self.strpath
+
+ def __str__(self):
+ """ return string representation of the Path. """
+ return self.strpath
+
+ def chmod(self, mode, rec=0):
+ """ change permissions to the given mode. If mode is an
+ integer it directly encodes the os-specific modes.
+ if rec is True perform recursively.
+ """
+ if not isinstance(mode, int):
+ raise TypeError("mode %r must be an integer" % (mode,))
+ if rec:
+ for x in self.visit(rec=rec):
+ py.error.checked_call(os.chmod, str(x), mode)
+ py.error.checked_call(os.chmod, self.strpath, mode)
+
+ def pypkgpath(self):
+ """ return the Python package path by looking for the last
+ directory upwards which still contains an __init__.py.
+ Return None if a pkgpath can not be determined.
+ """
+ pkgpath = None
+ for parent in self.parts(reverse=True):
+ if parent.isdir():
+ if not parent.join('__init__.py').exists():
+ break
+ if not isimportable(parent.basename):
+ break
+ pkgpath = parent
+ return pkgpath
+
+ def _ensuresyspath(self, ensuremode, path):
+ if ensuremode:
+ s = str(path)
+ if ensuremode == "append":
+ if s not in sys.path:
+ sys.path.append(s)
+ else:
+ if s != sys.path[0]:
+ sys.path.insert(0, s)
+
+ def pyimport(self, modname=None, ensuresyspath=True):
+ """ return path as an imported python module.
+
+ If modname is None, look for the containing package
+ and construct an according module name.
+ The module will be put/looked up in sys.modules.
+ if ensuresyspath is True then the root dir for importing
+ the file (taking __init__.py files into account) will
+ be prepended to sys.path if it isn't there already.
+ If ensuresyspath=="append" the root dir will be appended
+ if it isn't already contained in sys.path.
+ if ensuresyspath is False no modification of syspath happens.
+ """
+ if not self.check():
+ raise py.error.ENOENT(self)
+
+ pkgpath = None
+ if modname is None:
+ pkgpath = self.pypkgpath()
+ if pkgpath is not None:
+ pkgroot = pkgpath.dirpath()
+ names = self.new(ext="").relto(pkgroot).split(self.sep)
+ if names[-1] == "__init__":
+ names.pop()
+ modname = ".".join(names)
+ else:
+ pkgroot = self.dirpath()
+ modname = self.purebasename
+
+ self._ensuresyspath(ensuresyspath, pkgroot)
+ __import__(modname)
+ mod = sys.modules[modname]
+ if self.basename == "__init__.py":
+ return mod # we don't check anything as we might
+ # we in a namespace package ... too icky to check
+ modfile = mod.__file__
+ if modfile[-4:] in ('.pyc', '.pyo'):
+ modfile = modfile[:-1]
+ elif modfile.endswith('$py.class'):
+ modfile = modfile[:-9] + '.py'
+ if modfile.endswith(os.path.sep + "__init__.py"):
+ if self.basename != "__init__.py":
+ modfile = modfile[:-12]
+ try:
+ issame = self.samefile(modfile)
+ except py.error.ENOENT:
+ issame = False
+ if not issame:
+ raise self.ImportMismatchError(modname, modfile, self)
+ return mod
+ else:
+ try:
+ return sys.modules[modname]
+ except KeyError:
+ # we have a custom modname, do a pseudo-import
+ import types
+ mod = types.ModuleType(modname)
+ mod.__file__ = str(self)
+ sys.modules[modname] = mod
+ try:
+ py.builtin.execfile(str(self), mod.__dict__)
+ except:
+ del sys.modules[modname]
+ raise
+ return mod
+
+ def sysexec(self, *argv, **popen_opts):
+ """ return stdout text from executing a system child process,
+ where the 'self' path points to executable.
+ The process is directly invoked and not through a system shell.
+ """
+ from subprocess import Popen, PIPE
+ argv = map_as_list(str, argv)
+ popen_opts['stdout'] = popen_opts['stderr'] = PIPE
+ proc = Popen([str(self)] + argv, **popen_opts)
+ stdout, stderr = proc.communicate()
+ ret = proc.wait()
+ if py.builtin._isbytes(stdout):
+ stdout = py.builtin._totext(stdout, sys.getdefaultencoding())
+ if ret != 0:
+ if py.builtin._isbytes(stderr):
+ stderr = py.builtin._totext(stderr, sys.getdefaultencoding())
+ raise py.process.cmdexec.Error(ret, ret, str(self),
+ stdout, stderr,)
+ return stdout
+
+ def sysfind(cls, name, checker=None, paths=None):
+ """ return a path object found by looking at the systems
+ underlying PATH specification. If the checker is not None
+ it will be invoked to filter matching paths. If a binary
+ cannot be found, None is returned
+ Note: This is probably not working on plain win32 systems
+ but may work on cygwin.
+ """
+ if isabs(name):
+ p = py.path.local(name)
+ if p.check(file=1):
+ return p
+ else:
+ if paths is None:
+ if iswin32:
+ paths = os.environ['Path'].split(';')
+ if '' not in paths and '.' not in paths:
+ paths.append('.')
+ try:
+ systemroot = os.environ['SYSTEMROOT']
+ except KeyError:
+ pass
+ else:
+ paths = [path.replace('%SystemRoot%', systemroot)
+ for path in paths]
+ else:
+ paths = os.environ['PATH'].split(':')
+ tryadd = []
+ if iswin32:
+ tryadd += os.environ['PATHEXT'].split(os.pathsep)
+ tryadd.append("")
+
+ for x in paths:
+ for addext in tryadd:
+ p = py.path.local(x).join(name, abs=True) + addext
+ try:
+ if p.check(file=1):
+ if checker:
+ if not checker(p):
+ continue
+ return p
+ except py.error.EACCES:
+ pass
+ return None
+ sysfind = classmethod(sysfind)
+
+ def _gethomedir(cls):
+ try:
+ x = os.environ['HOME']
+ except KeyError:
+ try:
+ x = os.environ["HOMEDRIVE"] + os.environ['HOMEPATH']
+ except KeyError:
+ return None
+ return cls(x)
+ _gethomedir = classmethod(_gethomedir)
+
+ # """
+ # special class constructors for local filesystem paths
+ # """
+ @classmethod
+ def get_temproot(cls):
+ """ return the system's temporary directory
+ (where tempfiles are usually created in)
+ """
+ import tempfile
+ return py.path.local(tempfile.gettempdir())
+
+ @classmethod
+ def mkdtemp(cls, rootdir=None):
+ """ return a Path object pointing to a fresh new temporary directory
+ (which we created ourself).
+ """
+ import tempfile
+ if rootdir is None:
+ rootdir = cls.get_temproot()
+ return cls(py.error.checked_call(tempfile.mkdtemp, dir=str(rootdir)))
+
+ def make_numbered_dir(cls, prefix='session-', rootdir=None, keep=3,
+ lock_timeout = 172800): # two days
+ """ return unique directory with a number greater than the current
+ maximum one. The number is assumed to start directly after prefix.
+ if keep is true directories with a number less than (maxnum-keep)
+ will be removed. If .lock files are used (lock_timeout non-zero),
+ algorithm is multi-process safe.
+ """
+ if rootdir is None:
+ rootdir = cls.get_temproot()
+
+ nprefix = normcase(prefix)
+ def parse_num(path):
+ """ parse the number out of a path (if it matches the prefix) """
+ nbasename = normcase(path.basename)
+ if nbasename.startswith(nprefix):
+ try:
+ return int(nbasename[len(nprefix):])
+ except ValueError:
+ pass
+
+ def create_lockfile(path):
+ """ exclusively create lockfile. Throws when failed """
+ mypid = os.getpid()
+ lockfile = path.join('.lock')
+ if hasattr(lockfile, 'mksymlinkto'):
+ lockfile.mksymlinkto(str(mypid))
+ else:
+ fd = py.error.checked_call(os.open, str(lockfile), os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o644)
+ with os.fdopen(fd, 'w') as f:
+ f.write(str(mypid))
+ return lockfile
+
+ def atexit_remove_lockfile(lockfile):
+ """ ensure lockfile is removed at process exit """
+ mypid = os.getpid()
+ def try_remove_lockfile():
+ # in a fork() situation, only the last process should
+ # remove the .lock, otherwise the other processes run the
+ # risk of seeing their temporary dir disappear. For now
+ # we remove the .lock in the parent only (i.e. we assume
+ # that the children finish before the parent).
+ if os.getpid() != mypid:
+ return
+ try:
+ lockfile.remove()
+ except py.error.Error:
+ pass
+ atexit.register(try_remove_lockfile)
+
+ # compute the maximum number currently in use with the prefix
+ lastmax = None
+ while True:
+ maxnum = -1
+ for path in rootdir.listdir():
+ num = parse_num(path)
+ if num is not None:
+ maxnum = max(maxnum, num)
+
+ # make the new directory
+ try:
+ udir = rootdir.mkdir(prefix + str(maxnum+1))
+ if lock_timeout:
+ lockfile = create_lockfile(udir)
+ atexit_remove_lockfile(lockfile)
+ except (py.error.EEXIST, py.error.ENOENT, py.error.EBUSY):
+ # race condition (1): another thread/process created the dir
+ # in the meantime - try again
+ # race condition (2): another thread/process spuriously acquired
+ # lock treating empty directory as candidate
+ # for removal - try again
+ # race condition (3): another thread/process tried to create the lock at
+ # the same time (happened in Python 3.3 on Windows)
+ # https://ci.appveyor.com/project/pytestbot/py/build/1.0.21/job/ffi85j4c0lqwsfwa
+ if lastmax == maxnum:
+ raise
+ lastmax = maxnum
+ continue
+ break
+
+ def get_mtime(path):
+ """ read file modification time """
+ try:
+ return path.lstat().mtime
+ except py.error.Error:
+ pass
+
+ garbage_prefix = prefix + 'garbage-'
+
+ def is_garbage(path):
+ """ check if path denotes directory scheduled for removal """
+ bn = path.basename
+ return bn.startswith(garbage_prefix)
+
+ # prune old directories
+ udir_time = get_mtime(udir)
+ if keep and udir_time:
+ for path in rootdir.listdir():
+ num = parse_num(path)
+ if num is not None and num <= (maxnum - keep):
+ try:
+ # try acquiring lock to remove directory as exclusive user
+ if lock_timeout:
+ create_lockfile(path)
+ except (py.error.EEXIST, py.error.ENOENT, py.error.EBUSY):
+ path_time = get_mtime(path)
+ if not path_time:
+ # assume directory doesn't exist now
+ continue
+ if abs(udir_time - path_time) < lock_timeout:
+ # assume directory with lockfile exists
+ # and lock timeout hasn't expired yet
+ continue
+
+ # path dir locked for exclusive use
+ # and scheduled for removal to avoid another thread/process
+ # treating it as a new directory or removal candidate
+ garbage_path = rootdir.join(garbage_prefix + str(uuid.uuid4()))
+ try:
+ path.rename(garbage_path)
+ garbage_path.remove(rec=1)
+ except KeyboardInterrupt:
+ raise
+ except: # this might be py.error.Error, WindowsError ...
+ pass
+ if is_garbage(path):
+ try:
+ path.remove(rec=1)
+ except KeyboardInterrupt:
+ raise
+ except: # this might be py.error.Error, WindowsError ...
+ pass
+
+ # make link...
+ try:
+ username = os.environ['USER'] #linux, et al
+ except KeyError:
+ try:
+ username = os.environ['USERNAME'] #windows
+ except KeyError:
+ username = 'current'
+
+ src = str(udir)
+ dest = src[:src.rfind('-')] + '-' + username
+ try:
+ os.unlink(dest)
+ except OSError:
+ pass
+ try:
+ os.symlink(src, dest)
+ except (OSError, AttributeError, NotImplementedError):
+ pass
+
+ return udir
+ make_numbered_dir = classmethod(make_numbered_dir)
+
+
+def copymode(src, dest):
+ """ copy permission from src to dst. """
+ import shutil
+ shutil.copymode(src, dest)
+
+
+def copystat(src, dest):
+ """ copy permission, last modification time,
+ last access time, and flags from src to dst."""
+ import shutil
+ shutil.copystat(str(src), str(dest))
+
+
+def copychunked(src, dest):
+ chunksize = 524288 # half a meg of bytes
+ fsrc = src.open('rb')
+ try:
+ fdest = dest.open('wb')
+ try:
+ while 1:
+ buf = fsrc.read(chunksize)
+ if not buf:
+ break
+ fdest.write(buf)
+ finally:
+ fdest.close()
+ finally:
+ fsrc.close()
+
+
+def isimportable(name):
+ if name and (name[0].isalpha() or name[0] == '_'):
+ name = name.replace("_", '')
+ return not name or name.isalnum()
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_path/svnurl.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_path/svnurl.py
new file mode 100644
index 00000000000..6589a71d09e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_path/svnurl.py
@@ -0,0 +1,380 @@
+"""
+module defining a subversion path object based on the external
+command 'svn'. This modules aims to work with svn 1.3 and higher
+but might also interact well with earlier versions.
+"""
+
+import os, sys, time, re
+import py
+from py import path, process
+from py._path import common
+from py._path import svnwc as svncommon
+from py._path.cacheutil import BuildcostAccessCache, AgingCache
+
+DEBUG=False
+
+class SvnCommandPath(svncommon.SvnPathBase):
+ """ path implementation that offers access to (possibly remote) subversion
+ repositories. """
+
+ _lsrevcache = BuildcostAccessCache(maxentries=128)
+ _lsnorevcache = AgingCache(maxentries=1000, maxseconds=60.0)
+
+ def __new__(cls, path, rev=None, auth=None):
+ self = object.__new__(cls)
+ if isinstance(path, cls):
+ rev = path.rev
+ auth = path.auth
+ path = path.strpath
+ svncommon.checkbadchars(path)
+ path = path.rstrip('/')
+ self.strpath = path
+ self.rev = rev
+ self.auth = auth
+ return self
+
+ def __repr__(self):
+ if self.rev == -1:
+ return 'svnurl(%r)' % self.strpath
+ else:
+ return 'svnurl(%r, %r)' % (self.strpath, self.rev)
+
+ def _svnwithrev(self, cmd, *args):
+ """ execute an svn command, append our own url and revision """
+ if self.rev is None:
+ return self._svnwrite(cmd, *args)
+ else:
+ args = ['-r', self.rev] + list(args)
+ return self._svnwrite(cmd, *args)
+
+ def _svnwrite(self, cmd, *args):
+ """ execute an svn command, append our own url """
+ l = ['svn %s' % cmd]
+ args = ['"%s"' % self._escape(item) for item in args]
+ l.extend(args)
+ l.append('"%s"' % self._encodedurl())
+ # fixing the locale because we can't otherwise parse
+ string = " ".join(l)
+ if DEBUG:
+ print("execing %s" % string)
+ out = self._svncmdexecauth(string)
+ return out
+
+ def _svncmdexecauth(self, cmd):
+ """ execute an svn command 'as is' """
+ cmd = svncommon.fixlocale() + cmd
+ if self.auth is not None:
+ cmd += ' ' + self.auth.makecmdoptions()
+ return self._cmdexec(cmd)
+
+ def _cmdexec(self, cmd):
+ try:
+ out = process.cmdexec(cmd)
+ except py.process.cmdexec.Error:
+ e = sys.exc_info()[1]
+ if (e.err.find('File Exists') != -1 or
+ e.err.find('File already exists') != -1):
+ raise py.error.EEXIST(self)
+ raise
+ return out
+
+ def _svnpopenauth(self, cmd):
+ """ execute an svn command, return a pipe for reading stdin """
+ cmd = svncommon.fixlocale() + cmd
+ if self.auth is not None:
+ cmd += ' ' + self.auth.makecmdoptions()
+ return self._popen(cmd)
+
+ def _popen(self, cmd):
+ return os.popen(cmd)
+
+ def _encodedurl(self):
+ return self._escape(self.strpath)
+
+ def _norev_delentry(self, path):
+ auth = self.auth and self.auth.makecmdoptions() or None
+ self._lsnorevcache.delentry((str(path), auth))
+
+ def open(self, mode='r'):
+ """ return an opened file with the given mode. """
+ if mode not in ("r", "rU",):
+ raise ValueError("mode %r not supported" % (mode,))
+ assert self.check(file=1) # svn cat returns an empty file otherwise
+ if self.rev is None:
+ return self._svnpopenauth('svn cat "%s"' % (
+ self._escape(self.strpath), ))
+ else:
+ return self._svnpopenauth('svn cat -r %s "%s"' % (
+ self.rev, self._escape(self.strpath)))
+
+ def dirpath(self, *args, **kwargs):
+ """ return the directory path of the current path joined
+ with any given path arguments.
+ """
+ l = self.strpath.split(self.sep)
+ if len(l) < 4:
+ raise py.error.EINVAL(self, "base is not valid")
+ elif len(l) == 4:
+ return self.join(*args, **kwargs)
+ else:
+ return self.new(basename='').join(*args, **kwargs)
+
+ # modifying methods (cache must be invalidated)
+ def mkdir(self, *args, **kwargs):
+ """ create & return the directory joined with args.
+ pass a 'msg' keyword argument to set the commit message.
+ """
+ commit_msg = kwargs.get('msg', "mkdir by py lib invocation")
+ createpath = self.join(*args)
+ createpath._svnwrite('mkdir', '-m', commit_msg)
+ self._norev_delentry(createpath.dirpath())
+ return createpath
+
+ def copy(self, target, msg='copied by py lib invocation'):
+ """ copy path to target with checkin message msg."""
+ if getattr(target, 'rev', None) is not None:
+ raise py.error.EINVAL(target, "revisions are immutable")
+ self._svncmdexecauth('svn copy -m "%s" "%s" "%s"' %(msg,
+ self._escape(self), self._escape(target)))
+ self._norev_delentry(target.dirpath())
+
+ def rename(self, target, msg="renamed by py lib invocation"):
+ """ rename this path to target with checkin message msg. """
+ if getattr(self, 'rev', None) is not None:
+ raise py.error.EINVAL(self, "revisions are immutable")
+ self._svncmdexecauth('svn move -m "%s" --force "%s" "%s"' %(
+ msg, self._escape(self), self._escape(target)))
+ self._norev_delentry(self.dirpath())
+ self._norev_delentry(self)
+
+ def remove(self, rec=1, msg='removed by py lib invocation'):
+ """ remove a file or directory (or a directory tree if rec=1) with
+checkin message msg."""
+ if self.rev is not None:
+ raise py.error.EINVAL(self, "revisions are immutable")
+ self._svncmdexecauth('svn rm -m "%s" "%s"' %(msg, self._escape(self)))
+ self._norev_delentry(self.dirpath())
+
+ def export(self, topath):
+ """ export to a local path
+
+ topath should not exist prior to calling this, returns a
+ py.path.local instance
+ """
+ topath = py.path.local(topath)
+ args = ['"%s"' % (self._escape(self),),
+ '"%s"' % (self._escape(topath),)]
+ if self.rev is not None:
+ args = ['-r', str(self.rev)] + args
+ self._svncmdexecauth('svn export %s' % (' '.join(args),))
+ return topath
+
+ def ensure(self, *args, **kwargs):
+ """ ensure that an args-joined path exists (by default as
+ a file). If you specify a keyword argument 'dir=True'
+ then the path is forced to be a directory path.
+ """
+ if getattr(self, 'rev', None) is not None:
+ raise py.error.EINVAL(self, "revisions are immutable")
+ target = self.join(*args)
+ dir = kwargs.get('dir', 0)
+ for x in target.parts(reverse=True):
+ if x.check():
+ break
+ else:
+ raise py.error.ENOENT(target, "has not any valid base!")
+ if x == target:
+ if not x.check(dir=dir):
+ raise dir and py.error.ENOTDIR(x) or py.error.EISDIR(x)
+ return x
+ tocreate = target.relto(x)
+ basename = tocreate.split(self.sep, 1)[0]
+ tempdir = py.path.local.mkdtemp()
+ try:
+ tempdir.ensure(tocreate, dir=dir)
+ cmd = 'svn import -m "%s" "%s" "%s"' % (
+ "ensure %s" % self._escape(tocreate),
+ self._escape(tempdir.join(basename)),
+ x.join(basename)._encodedurl())
+ self._svncmdexecauth(cmd)
+ self._norev_delentry(x)
+ finally:
+ tempdir.remove()
+ return target
+
+ # end of modifying methods
+ def _propget(self, name):
+ res = self._svnwithrev('propget', name)
+ return res[:-1] # strip trailing newline
+
+ def _proplist(self):
+ res = self._svnwithrev('proplist')
+ lines = res.split('\n')
+ lines = [x.strip() for x in lines[1:]]
+ return svncommon.PropListDict(self, lines)
+
+ def info(self):
+ """ return an Info structure with svn-provided information. """
+ parent = self.dirpath()
+ nameinfo_seq = parent._listdir_nameinfo()
+ bn = self.basename
+ for name, info in nameinfo_seq:
+ if name == bn:
+ return info
+ raise py.error.ENOENT(self)
+
+
+ def _listdir_nameinfo(self):
+ """ return sequence of name-info directory entries of self """
+ def builder():
+ try:
+ res = self._svnwithrev('ls', '-v')
+ except process.cmdexec.Error:
+ e = sys.exc_info()[1]
+ if e.err.find('non-existent in that revision') != -1:
+ raise py.error.ENOENT(self, e.err)
+ elif e.err.find("E200009:") != -1:
+ raise py.error.ENOENT(self, e.err)
+ elif e.err.find('File not found') != -1:
+ raise py.error.ENOENT(self, e.err)
+ elif e.err.find('not part of a repository')!=-1:
+ raise py.error.ENOENT(self, e.err)
+ elif e.err.find('Unable to open')!=-1:
+ raise py.error.ENOENT(self, e.err)
+ elif e.err.lower().find('method not allowed')!=-1:
+ raise py.error.EACCES(self, e.err)
+ raise py.error.Error(e.err)
+ lines = res.split('\n')
+ nameinfo_seq = []
+ for lsline in lines:
+ if lsline:
+ info = InfoSvnCommand(lsline)
+ if info._name != '.': # svn 1.5 produces '.' dirs,
+ nameinfo_seq.append((info._name, info))
+ nameinfo_seq.sort()
+ return nameinfo_seq
+ auth = self.auth and self.auth.makecmdoptions() or None
+ if self.rev is not None:
+ return self._lsrevcache.getorbuild((self.strpath, self.rev, auth),
+ builder)
+ else:
+ return self._lsnorevcache.getorbuild((self.strpath, auth),
+ builder)
+
+ def listdir(self, fil=None, sort=None):
+ """ list directory contents, possibly filter by the given fil func
+ and possibly sorted.
+ """
+ if isinstance(fil, str):
+ fil = common.FNMatcher(fil)
+ nameinfo_seq = self._listdir_nameinfo()
+ if len(nameinfo_seq) == 1:
+ name, info = nameinfo_seq[0]
+ if name == self.basename and info.kind == 'file':
+ #if not self.check(dir=1):
+ raise py.error.ENOTDIR(self)
+ paths = [self.join(name) for (name, info) in nameinfo_seq]
+ if fil:
+ paths = [x for x in paths if fil(x)]
+ self._sortlist(paths, sort)
+ return paths
+
+
+ def log(self, rev_start=None, rev_end=1, verbose=False):
+ """ return a list of LogEntry instances for this path.
+rev_start is the starting revision (defaulting to the first one).
+rev_end is the last revision (defaulting to HEAD).
+if verbose is True, then the LogEntry instances also know which files changed.
+"""
+ assert self.check() #make it simpler for the pipe
+ rev_start = rev_start is None and "HEAD" or rev_start
+ rev_end = rev_end is None and "HEAD" or rev_end
+
+ if rev_start == "HEAD" and rev_end == 1:
+ rev_opt = ""
+ else:
+ rev_opt = "-r %s:%s" % (rev_start, rev_end)
+ verbose_opt = verbose and "-v" or ""
+ xmlpipe = self._svnpopenauth('svn log --xml %s %s "%s"' %
+ (rev_opt, verbose_opt, self.strpath))
+ from xml.dom import minidom
+ tree = minidom.parse(xmlpipe)
+ result = []
+ for logentry in filter(None, tree.firstChild.childNodes):
+ if logentry.nodeType == logentry.ELEMENT_NODE:
+ result.append(svncommon.LogEntry(logentry))
+ return result
+
+#01234567890123456789012345678901234567890123467
+# 2256 hpk 165 Nov 24 17:55 __init__.py
+# XXX spotted by Guido, SVN 1.3.0 has different aligning, breaks the code!!!
+# 1312 johnny 1627 May 05 14:32 test_decorators.py
+#
+class InfoSvnCommand:
+ # the '0?' part in the middle is an indication of whether the resource is
+ # locked, see 'svn help ls'
+ lspattern = re.compile(
+ r'^ *(?P<rev>\d+) +(?P<author>.+?) +(0? *(?P<size>\d+))? '
+ r'*(?P<date>\w+ +\d{2} +[\d:]+) +(?P<file>.*)$')
+ def __init__(self, line):
+ # this is a typical line from 'svn ls http://...'
+ #_ 1127 jum 0 Jul 13 15:28 branch/
+ match = self.lspattern.match(line)
+ data = match.groupdict()
+ self._name = data['file']
+ if self._name[-1] == '/':
+ self._name = self._name[:-1]
+ self.kind = 'dir'
+ else:
+ self.kind = 'file'
+ #self.has_props = l.pop(0) == 'P'
+ self.created_rev = int(data['rev'])
+ self.last_author = data['author']
+ self.size = data['size'] and int(data['size']) or 0
+ self.mtime = parse_time_with_missing_year(data['date'])
+ self.time = self.mtime * 1000000
+
+ def __eq__(self, other):
+ return self.__dict__ == other.__dict__
+
+
+#____________________________________________________
+#
+# helper functions
+#____________________________________________________
+def parse_time_with_missing_year(timestr):
+ """ analyze the time part from a single line of "svn ls -v"
+ the svn output doesn't show the year makes the 'timestr'
+ ambigous.
+ """
+ import calendar
+ t_now = time.gmtime()
+
+ tparts = timestr.split()
+ month = time.strptime(tparts.pop(0), '%b')[1]
+ day = time.strptime(tparts.pop(0), '%d')[2]
+ last = tparts.pop(0) # year or hour:minute
+ try:
+ if ":" in last:
+ raise ValueError()
+ year = time.strptime(last, '%Y')[0]
+ hour = minute = 0
+ except ValueError:
+ hour, minute = time.strptime(last, '%H:%M')[3:5]
+ year = t_now[0]
+
+ t_result = (year, month, day, hour, minute, 0,0,0,0)
+ if t_result > t_now:
+ year -= 1
+ t_result = (year, month, day, hour, minute, 0,0,0,0)
+ return calendar.timegm(t_result)
+
+class PathEntry:
+ def __init__(self, ppart):
+ self.strpath = ppart.firstChild.nodeValue.encode('UTF-8')
+ self.action = ppart.getAttribute('action').encode('UTF-8')
+ if self.action == 'A':
+ self.copyfrom_path = ppart.getAttribute('copyfrom-path').encode('UTF-8')
+ if self.copyfrom_path:
+ self.copyfrom_rev = int(ppart.getAttribute('copyfrom-rev'))
+
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_path/svnwc.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_path/svnwc.py
new file mode 100644
index 00000000000..3138dd85da3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_path/svnwc.py
@@ -0,0 +1,1240 @@
+"""
+svn-Command based Implementation of a Subversion WorkingCopy Path.
+
+ SvnWCCommandPath is the main class.
+
+"""
+
+import os, sys, time, re, calendar
+import py
+import subprocess
+from py._path import common
+
+#-----------------------------------------------------------
+# Caching latest repository revision and repo-paths
+# (getting them is slow with the current implementations)
+#
+# XXX make mt-safe
+#-----------------------------------------------------------
+
+class cache:
+ proplist = {}
+ info = {}
+ entries = {}
+ prop = {}
+
+class RepoEntry:
+ def __init__(self, url, rev, timestamp):
+ self.url = url
+ self.rev = rev
+ self.timestamp = timestamp
+
+ def __str__(self):
+ return "repo: %s;%s %s" %(self.url, self.rev, self.timestamp)
+
+class RepoCache:
+ """ The Repocache manages discovered repository paths
+ and their revisions. If inside a timeout the cache
+ will even return the revision of the root.
+ """
+ timeout = 20 # seconds after which we forget that we know the last revision
+
+ def __init__(self):
+ self.repos = []
+
+ def clear(self):
+ self.repos = []
+
+ def put(self, url, rev, timestamp=None):
+ if rev is None:
+ return
+ if timestamp is None:
+ timestamp = time.time()
+
+ for entry in self.repos:
+ if url == entry.url:
+ entry.timestamp = timestamp
+ entry.rev = rev
+ #print "set repo", entry
+ break
+ else:
+ entry = RepoEntry(url, rev, timestamp)
+ self.repos.append(entry)
+ #print "appended repo", entry
+
+ def get(self, url):
+ now = time.time()
+ for entry in self.repos:
+ if url.startswith(entry.url):
+ if now < entry.timestamp + self.timeout:
+ #print "returning immediate Etrny", entry
+ return entry.url, entry.rev
+ return entry.url, -1
+ return url, -1
+
+repositories = RepoCache()
+
+
+# svn support code
+
+ALLOWED_CHARS = "_ -/\\=$.~+%" #add characters as necessary when tested
+if sys.platform == "win32":
+ ALLOWED_CHARS += ":"
+ALLOWED_CHARS_HOST = ALLOWED_CHARS + '@:'
+
+def _getsvnversion(ver=[]):
+ try:
+ return ver[0]
+ except IndexError:
+ v = py.process.cmdexec("svn -q --version")
+ v.strip()
+ v = '.'.join(v.split('.')[:2])
+ ver.append(v)
+ return v
+
+def _escape_helper(text):
+ text = str(text)
+ if sys.platform != 'win32':
+ text = str(text).replace('$', '\\$')
+ return text
+
+def _check_for_bad_chars(text, allowed_chars=ALLOWED_CHARS):
+ for c in str(text):
+ if c.isalnum():
+ continue
+ if c in allowed_chars:
+ continue
+ return True
+ return False
+
+def checkbadchars(url):
+ # (hpk) not quite sure about the exact purpose, guido w.?
+ proto, uri = url.split("://", 1)
+ if proto != "file":
+ host, uripath = uri.split('/', 1)
+ # only check for bad chars in the non-protocol parts
+ if (_check_for_bad_chars(host, ALLOWED_CHARS_HOST) \
+ or _check_for_bad_chars(uripath, ALLOWED_CHARS)):
+ raise ValueError("bad char in %r" % (url, ))
+
+
+#_______________________________________________________________
+
+class SvnPathBase(common.PathBase):
+ """ Base implementation for SvnPath implementations. """
+ sep = '/'
+
+ def _geturl(self):
+ return self.strpath
+ url = property(_geturl, None, None, "url of this svn-path.")
+
+ def __str__(self):
+ """ return a string representation (including rev-number) """
+ return self.strpath
+
+ def __hash__(self):
+ return hash(self.strpath)
+
+ def new(self, **kw):
+ """ create a modified version of this path. A 'rev' argument
+ indicates a new revision.
+ the following keyword arguments modify various path parts::
+
+ http://host.com/repo/path/file.ext
+ |-----------------------| dirname
+ |------| basename
+ |--| purebasename
+ |--| ext
+ """
+ obj = object.__new__(self.__class__)
+ obj.rev = kw.get('rev', self.rev)
+ obj.auth = kw.get('auth', self.auth)
+ dirname, basename, purebasename, ext = self._getbyspec(
+ "dirname,basename,purebasename,ext")
+ if 'basename' in kw:
+ if 'purebasename' in kw or 'ext' in kw:
+ raise ValueError("invalid specification %r" % kw)
+ else:
+ pb = kw.setdefault('purebasename', purebasename)
+ ext = kw.setdefault('ext', ext)
+ if ext and not ext.startswith('.'):
+ ext = '.' + ext
+ kw['basename'] = pb + ext
+
+ kw.setdefault('dirname', dirname)
+ kw.setdefault('sep', self.sep)
+ if kw['basename']:
+ obj.strpath = "%(dirname)s%(sep)s%(basename)s" % kw
+ else:
+ obj.strpath = "%(dirname)s" % kw
+ return obj
+
+ def _getbyspec(self, spec):
+ """ get specified parts of the path. 'arg' is a string
+ with comma separated path parts. The parts are returned
+ in exactly the order of the specification.
+
+ you may specify the following parts:
+
+ http://host.com/repo/path/file.ext
+ |-----------------------| dirname
+ |------| basename
+ |--| purebasename
+ |--| ext
+ """
+ res = []
+ parts = self.strpath.split(self.sep)
+ for name in spec.split(','):
+ name = name.strip()
+ if name == 'dirname':
+ res.append(self.sep.join(parts[:-1]))
+ elif name == 'basename':
+ res.append(parts[-1])
+ else:
+ basename = parts[-1]
+ i = basename.rfind('.')
+ if i == -1:
+ purebasename, ext = basename, ''
+ else:
+ purebasename, ext = basename[:i], basename[i:]
+ if name == 'purebasename':
+ res.append(purebasename)
+ elif name == 'ext':
+ res.append(ext)
+ else:
+ raise NameError("Don't know part %r" % name)
+ return res
+
+ def __eq__(self, other):
+ """ return true if path and rev attributes each match """
+ return (str(self) == str(other) and
+ (self.rev == other.rev or self.rev == other.rev))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def join(self, *args):
+ """ return a new Path (with the same revision) which is composed
+ of the self Path followed by 'args' path components.
+ """
+ if not args:
+ return self
+
+ args = tuple([arg.strip(self.sep) for arg in args])
+ parts = (self.strpath, ) + args
+ newpath = self.__class__(self.sep.join(parts), self.rev, self.auth)
+ return newpath
+
+ def propget(self, name):
+ """ return the content of the given property. """
+ value = self._propget(name)
+ return value
+
+ def proplist(self):
+ """ list all property names. """
+ content = self._proplist()
+ return content
+
+ def size(self):
+ """ Return the size of the file content of the Path. """
+ return self.info().size
+
+ def mtime(self):
+ """ Return the last modification time of the file. """
+ return self.info().mtime
+
+ # shared help methods
+
+ def _escape(self, cmd):
+ return _escape_helper(cmd)
+
+
+ #def _childmaxrev(self):
+ # """ return maximum revision number of childs (or self.rev if no childs) """
+ # rev = self.rev
+ # for name, info in self._listdir_nameinfo():
+ # rev = max(rev, info.created_rev)
+ # return rev
+
+ #def _getlatestrevision(self):
+ # """ return latest repo-revision for this path. """
+ # url = self.strpath
+ # path = self.__class__(url, None)
+ #
+ # # we need a long walk to find the root-repo and revision
+ # while 1:
+ # try:
+ # rev = max(rev, path._childmaxrev())
+ # previous = path
+ # path = path.dirpath()
+ # except (IOError, process.cmdexec.Error):
+ # break
+ # if rev is None:
+ # raise IOError, "could not determine newest repo revision for %s" % self
+ # return rev
+
+ class Checkers(common.Checkers):
+ def dir(self):
+ try:
+ return self.path.info().kind == 'dir'
+ except py.error.Error:
+ return self._listdirworks()
+
+ def _listdirworks(self):
+ try:
+ self.path.listdir()
+ except py.error.ENOENT:
+ return False
+ else:
+ return True
+
+ def file(self):
+ try:
+ return self.path.info().kind == 'file'
+ except py.error.ENOENT:
+ return False
+
+ def exists(self):
+ try:
+ return self.path.info()
+ except py.error.ENOENT:
+ return self._listdirworks()
+
+def parse_apr_time(timestr):
+ i = timestr.rfind('.')
+ if i == -1:
+ raise ValueError("could not parse %s" % timestr)
+ timestr = timestr[:i]
+ parsedtime = time.strptime(timestr, "%Y-%m-%dT%H:%M:%S")
+ return time.mktime(parsedtime)
+
+class PropListDict(dict):
+ """ a Dictionary which fetches values (InfoSvnCommand instances) lazily"""
+ def __init__(self, path, keynames):
+ dict.__init__(self, [(x, None) for x in keynames])
+ self.path = path
+
+ def __getitem__(self, key):
+ value = dict.__getitem__(self, key)
+ if value is None:
+ value = self.path.propget(key)
+ dict.__setitem__(self, key, value)
+ return value
+
+def fixlocale():
+ if sys.platform != 'win32':
+ return 'LC_ALL=C '
+ return ''
+
+# some nasty chunk of code to solve path and url conversion and quoting issues
+ILLEGAL_CHARS = '* | \\ / : < > ? \t \n \x0b \x0c \r'.split(' ')
+if os.sep in ILLEGAL_CHARS:
+ ILLEGAL_CHARS.remove(os.sep)
+ISWINDOWS = sys.platform == 'win32'
+_reg_allow_disk = re.compile(r'^([a-z]\:\\)?[^:]+$', re.I)
+def _check_path(path):
+ illegal = ILLEGAL_CHARS[:]
+ sp = path.strpath
+ if ISWINDOWS:
+ illegal.remove(':')
+ if not _reg_allow_disk.match(sp):
+ raise ValueError('path may not contain a colon (:)')
+ for char in sp:
+ if char not in string.printable or char in illegal:
+ raise ValueError('illegal character %r in path' % (char,))
+
+def path_to_fspath(path, addat=True):
+ _check_path(path)
+ sp = path.strpath
+ if addat and path.rev != -1:
+ sp = '%s@%s' % (sp, path.rev)
+ elif addat:
+ sp = '%s@HEAD' % (sp,)
+ return sp
+
+def url_from_path(path):
+ fspath = path_to_fspath(path, False)
+ from urllib import quote
+ if ISWINDOWS:
+ match = _reg_allow_disk.match(fspath)
+ fspath = fspath.replace('\\', '/')
+ if match.group(1):
+ fspath = '/%s%s' % (match.group(1).replace('\\', '/'),
+ quote(fspath[len(match.group(1)):]))
+ else:
+ fspath = quote(fspath)
+ else:
+ fspath = quote(fspath)
+ if path.rev != -1:
+ fspath = '%s@%s' % (fspath, path.rev)
+ else:
+ fspath = '%s@HEAD' % (fspath,)
+ return 'file://%s' % (fspath,)
+
+class SvnAuth(object):
+ """ container for auth information for Subversion """
+ def __init__(self, username, password, cache_auth=True, interactive=True):
+ self.username = username
+ self.password = password
+ self.cache_auth = cache_auth
+ self.interactive = interactive
+
+ def makecmdoptions(self):
+ uname = self.username.replace('"', '\\"')
+ passwd = self.password.replace('"', '\\"')
+ ret = []
+ if uname:
+ ret.append('--username="%s"' % (uname,))
+ if passwd:
+ ret.append('--password="%s"' % (passwd,))
+ if not self.cache_auth:
+ ret.append('--no-auth-cache')
+ if not self.interactive:
+ ret.append('--non-interactive')
+ return ' '.join(ret)
+
+ def __str__(self):
+ return "<SvnAuth username=%s ...>" %(self.username,)
+
+rex_blame = re.compile(r'\s*(\d+)\s*(\S+) (.*)')
+
+class SvnWCCommandPath(common.PathBase):
+ """ path implementation offering access/modification to svn working copies.
+ It has methods similar to the functions in os.path and similar to the
+ commands of the svn client.
+ """
+ sep = os.sep
+
+ def __new__(cls, wcpath=None, auth=None):
+ self = object.__new__(cls)
+ if isinstance(wcpath, cls):
+ if wcpath.__class__ == cls:
+ return wcpath
+ wcpath = wcpath.localpath
+ if _check_for_bad_chars(str(wcpath),
+ ALLOWED_CHARS):
+ raise ValueError("bad char in wcpath %s" % (wcpath, ))
+ self.localpath = py.path.local(wcpath)
+ self.auth = auth
+ return self
+
+ strpath = property(lambda x: str(x.localpath), None, None, "string path")
+ rev = property(lambda x: x.info(usecache=0).rev, None, None, "revision")
+
+ def __eq__(self, other):
+ return self.localpath == getattr(other, 'localpath', None)
+
+ def _geturl(self):
+ if getattr(self, '_url', None) is None:
+ info = self.info()
+ self._url = info.url #SvnPath(info.url, info.rev)
+ assert isinstance(self._url, py.builtin._basestring)
+ return self._url
+
+ url = property(_geturl, None, None, "url of this WC item")
+
+ def _escape(self, cmd):
+ return _escape_helper(cmd)
+
+ def dump(self, obj):
+ """ pickle object into path location"""
+ return self.localpath.dump(obj)
+
+ def svnurl(self):
+ """ return current SvnPath for this WC-item. """
+ info = self.info()
+ return py.path.svnurl(info.url)
+
+ def __repr__(self):
+ return "svnwc(%r)" % (self.strpath) # , self._url)
+
+ def __str__(self):
+ return str(self.localpath)
+
+ def _makeauthoptions(self):
+ if self.auth is None:
+ return ''
+ return self.auth.makecmdoptions()
+
+ def _authsvn(self, cmd, args=None):
+ args = args and list(args) or []
+ args.append(self._makeauthoptions())
+ return self._svn(cmd, *args)
+
+ def _svn(self, cmd, *args):
+ l = ['svn %s' % cmd]
+ args = [self._escape(item) for item in args]
+ l.extend(args)
+ l.append('"%s"' % self._escape(self.strpath))
+ # try fixing the locale because we can't otherwise parse
+ string = fixlocale() + " ".join(l)
+ try:
+ try:
+ key = 'LC_MESSAGES'
+ hold = os.environ.get(key)
+ os.environ[key] = 'C'
+ out = py.process.cmdexec(string)
+ finally:
+ if hold:
+ os.environ[key] = hold
+ else:
+ del os.environ[key]
+ except py.process.cmdexec.Error:
+ e = sys.exc_info()[1]
+ strerr = e.err.lower()
+ if strerr.find('not found') != -1:
+ raise py.error.ENOENT(self)
+ elif strerr.find("E200009:") != -1:
+ raise py.error.ENOENT(self)
+ if (strerr.find('file exists') != -1 or
+ strerr.find('file already exists') != -1 or
+ strerr.find('w150002:') != -1 or
+ strerr.find("can't create directory") != -1):
+ raise py.error.EEXIST(strerr) #self)
+ raise
+ return out
+
+ def switch(self, url):
+ """ switch to given URL. """
+ self._authsvn('switch', [url])
+
+ def checkout(self, url=None, rev=None):
+ """ checkout from url to local wcpath. """
+ args = []
+ if url is None:
+ url = self.url
+ if rev is None or rev == -1:
+ if (sys.platform != 'win32' and
+ _getsvnversion() == '1.3'):
+ url += "@HEAD"
+ else:
+ if _getsvnversion() == '1.3':
+ url += "@%d" % rev
+ else:
+ args.append('-r' + str(rev))
+ args.append(url)
+ self._authsvn('co', args)
+
+ def update(self, rev='HEAD', interactive=True):
+ """ update working copy item to given revision. (None -> HEAD). """
+ opts = ['-r', rev]
+ if not interactive:
+ opts.append("--non-interactive")
+ self._authsvn('up', opts)
+
+ def write(self, content, mode='w'):
+ """ write content into local filesystem wc. """
+ self.localpath.write(content, mode)
+
+ def dirpath(self, *args):
+ """ return the directory Path of the current Path. """
+ return self.__class__(self.localpath.dirpath(*args), auth=self.auth)
+
+ def _ensuredirs(self):
+ parent = self.dirpath()
+ if parent.check(dir=0):
+ parent._ensuredirs()
+ if self.check(dir=0):
+ self.mkdir()
+ return self
+
+ def ensure(self, *args, **kwargs):
+ """ ensure that an args-joined path exists (by default as
+ a file). if you specify a keyword argument 'directory=True'
+ then the path is forced to be a directory path.
+ """
+ p = self.join(*args)
+ if p.check():
+ if p.check(versioned=False):
+ p.add()
+ return p
+ if kwargs.get('dir', 0):
+ return p._ensuredirs()
+ parent = p.dirpath()
+ parent._ensuredirs()
+ p.write("")
+ p.add()
+ return p
+
+ def mkdir(self, *args):
+ """ create & return the directory joined with args. """
+ if args:
+ return self.join(*args).mkdir()
+ else:
+ self._svn('mkdir')
+ return self
+
+ def add(self):
+ """ add ourself to svn """
+ self._svn('add')
+
+ def remove(self, rec=1, force=1):
+ """ remove a file or a directory tree. 'rec'ursive is
+ ignored and considered always true (because of
+ underlying svn semantics.
+ """
+ assert rec, "svn cannot remove non-recursively"
+ if not self.check(versioned=True):
+ # not added to svn (anymore?), just remove
+ py.path.local(self).remove()
+ return
+ flags = []
+ if force:
+ flags.append('--force')
+ self._svn('remove', *flags)
+
+ def copy(self, target):
+ """ copy path to target."""
+ py.process.cmdexec("svn copy %s %s" %(str(self), str(target)))
+
+ def rename(self, target):
+ """ rename this path to target. """
+ py.process.cmdexec("svn move --force %s %s" %(str(self), str(target)))
+
+ def lock(self):
+ """ set a lock (exclusive) on the resource """
+ out = self._authsvn('lock').strip()
+ if not out:
+ # warning or error, raise exception
+ raise ValueError("unknown error in svn lock command")
+
+ def unlock(self):
+ """ unset a previously set lock """
+ out = self._authsvn('unlock').strip()
+ if out.startswith('svn:'):
+ # warning or error, raise exception
+ raise Exception(out[4:])
+
+ def cleanup(self):
+ """ remove any locks from the resource """
+ # XXX should be fixed properly!!!
+ try:
+ self.unlock()
+ except:
+ pass
+
+ def status(self, updates=0, rec=0, externals=0):
+ """ return (collective) Status object for this file. """
+ # http://svnbook.red-bean.com/book.html#svn-ch-3-sect-4.3.1
+ # 2201 2192 jum test
+ # XXX
+ if externals:
+ raise ValueError("XXX cannot perform status() "
+ "on external items yet")
+ else:
+ #1.2 supports: externals = '--ignore-externals'
+ externals = ''
+ if rec:
+ rec= ''
+ else:
+ rec = '--non-recursive'
+
+ # XXX does not work on all subversion versions
+ #if not externals:
+ # externals = '--ignore-externals'
+
+ if updates:
+ updates = '-u'
+ else:
+ updates = ''
+
+ try:
+ cmd = 'status -v --xml --no-ignore %s %s %s' % (
+ updates, rec, externals)
+ out = self._authsvn(cmd)
+ except py.process.cmdexec.Error:
+ cmd = 'status -v --no-ignore %s %s %s' % (
+ updates, rec, externals)
+ out = self._authsvn(cmd)
+ rootstatus = WCStatus(self).fromstring(out, self)
+ else:
+ rootstatus = XMLWCStatus(self).fromstring(out, self)
+ return rootstatus
+
+ def diff(self, rev=None):
+ """ return a diff of the current path against revision rev (defaulting
+ to the last one).
+ """
+ args = []
+ if rev is not None:
+ args.append("-r %d" % rev)
+ out = self._authsvn('diff', args)
+ return out
+
+ def blame(self):
+ """ return a list of tuples of three elements:
+ (revision, commiter, line)
+ """
+ out = self._svn('blame')
+ result = []
+ blamelines = out.splitlines()
+ reallines = py.path.svnurl(self.url).readlines()
+ for i, (blameline, line) in enumerate(
+ zip(blamelines, reallines)):
+ m = rex_blame.match(blameline)
+ if not m:
+ raise ValueError("output line %r of svn blame does not match "
+ "expected format" % (line, ))
+ rev, name, _ = m.groups()
+ result.append((int(rev), name, line))
+ return result
+
+ _rex_commit = re.compile(r'.*Committed revision (\d+)\.$', re.DOTALL)
+ def commit(self, msg='', rec=1):
+ """ commit with support for non-recursive commits """
+ # XXX i guess escaping should be done better here?!?
+ cmd = 'commit -m "%s" --force-log' % (msg.replace('"', '\\"'),)
+ if not rec:
+ cmd += ' -N'
+ out = self._authsvn(cmd)
+ try:
+ del cache.info[self]
+ except KeyError:
+ pass
+ if out:
+ m = self._rex_commit.match(out)
+ return int(m.group(1))
+
+ def propset(self, name, value, *args):
+ """ set property name to value on this path. """
+ d = py.path.local.mkdtemp()
+ try:
+ p = d.join('value')
+ p.write(value)
+ self._svn('propset', name, '--file', str(p), *args)
+ finally:
+ d.remove()
+
+ def propget(self, name):
+ """ get property name on this path. """
+ res = self._svn('propget', name)
+ return res[:-1] # strip trailing newline
+
+ def propdel(self, name):
+ """ delete property name on this path. """
+ res = self._svn('propdel', name)
+ return res[:-1] # strip trailing newline
+
+ def proplist(self, rec=0):
+ """ return a mapping of property names to property values.
+If rec is True, then return a dictionary mapping sub-paths to such mappings.
+"""
+ if rec:
+ res = self._svn('proplist -R')
+ return make_recursive_propdict(self, res)
+ else:
+ res = self._svn('proplist')
+ lines = res.split('\n')
+ lines = [x.strip() for x in lines[1:]]
+ return PropListDict(self, lines)
+
+ def revert(self, rec=0):
+ """ revert the local changes of this path. if rec is True, do so
+recursively. """
+ if rec:
+ result = self._svn('revert -R')
+ else:
+ result = self._svn('revert')
+ return result
+
+ def new(self, **kw):
+ """ create a modified version of this path. A 'rev' argument
+ indicates a new revision.
+ the following keyword arguments modify various path parts:
+
+ http://host.com/repo/path/file.ext
+ |-----------------------| dirname
+ |------| basename
+ |--| purebasename
+ |--| ext
+ """
+ if kw:
+ localpath = self.localpath.new(**kw)
+ else:
+ localpath = self.localpath
+ return self.__class__(localpath, auth=self.auth)
+
+ def join(self, *args, **kwargs):
+ """ return a new Path (with the same revision) which is composed
+ of the self Path followed by 'args' path components.
+ """
+ if not args:
+ return self
+ localpath = self.localpath.join(*args, **kwargs)
+ return self.__class__(localpath, auth=self.auth)
+
+ def info(self, usecache=1):
+ """ return an Info structure with svn-provided information. """
+ info = usecache and cache.info.get(self)
+ if not info:
+ try:
+ output = self._svn('info')
+ except py.process.cmdexec.Error:
+ e = sys.exc_info()[1]
+ if e.err.find('Path is not a working copy directory') != -1:
+ raise py.error.ENOENT(self, e.err)
+ elif e.err.find("is not under version control") != -1:
+ raise py.error.ENOENT(self, e.err)
+ raise
+ # XXX SVN 1.3 has output on stderr instead of stdout (while it does
+ # return 0!), so a bit nasty, but we assume no output is output
+ # to stderr...
+ if (output.strip() == '' or
+ output.lower().find('not a versioned resource') != -1):
+ raise py.error.ENOENT(self, output)
+ info = InfoSvnWCCommand(output)
+
+ # Can't reliably compare on Windows without access to win32api
+ if sys.platform != 'win32':
+ if info.path != self.localpath:
+ raise py.error.ENOENT(self, "not a versioned resource:" +
+ " %s != %s" % (info.path, self.localpath))
+ cache.info[self] = info
+ return info
+
+ def listdir(self, fil=None, sort=None):
+ """ return a sequence of Paths.
+
+ listdir will return either a tuple or a list of paths
+ depending on implementation choices.
+ """
+ if isinstance(fil, str):
+ fil = common.FNMatcher(fil)
+ # XXX unify argument naming with LocalPath.listdir
+ def notsvn(path):
+ return path.basename != '.svn'
+
+ paths = []
+ for localpath in self.localpath.listdir(notsvn):
+ p = self.__class__(localpath, auth=self.auth)
+ if notsvn(p) and (not fil or fil(p)):
+ paths.append(p)
+ self._sortlist(paths, sort)
+ return paths
+
+ def open(self, mode='r'):
+ """ return an opened file with the given mode. """
+ return open(self.strpath, mode)
+
+ def _getbyspec(self, spec):
+ return self.localpath._getbyspec(spec)
+
+ class Checkers(py.path.local.Checkers):
+ def __init__(self, path):
+ self.svnwcpath = path
+ self.path = path.localpath
+ def versioned(self):
+ try:
+ s = self.svnwcpath.info()
+ except (py.error.ENOENT, py.error.EEXIST):
+ return False
+ except py.process.cmdexec.Error:
+ e = sys.exc_info()[1]
+ if e.err.find('is not a working copy')!=-1:
+ return False
+ if e.err.lower().find('not a versioned resource') != -1:
+ return False
+ raise
+ else:
+ return True
+
+ def log(self, rev_start=None, rev_end=1, verbose=False):
+ """ return a list of LogEntry instances for this path.
+rev_start is the starting revision (defaulting to the first one).
+rev_end is the last revision (defaulting to HEAD).
+if verbose is True, then the LogEntry instances also know which files changed.
+"""
+ assert self.check() # make it simpler for the pipe
+ rev_start = rev_start is None and "HEAD" or rev_start
+ rev_end = rev_end is None and "HEAD" or rev_end
+ if rev_start == "HEAD" and rev_end == 1:
+ rev_opt = ""
+ else:
+ rev_opt = "-r %s:%s" % (rev_start, rev_end)
+ verbose_opt = verbose and "-v" or ""
+ locale_env = fixlocale()
+ # some blather on stderr
+ auth_opt = self._makeauthoptions()
+ #stdin, stdout, stderr = os.popen3(locale_env +
+ # 'svn log --xml %s %s %s "%s"' % (
+ # rev_opt, verbose_opt, auth_opt,
+ # self.strpath))
+ cmd = locale_env + 'svn log --xml %s %s %s "%s"' % (
+ rev_opt, verbose_opt, auth_opt, self.strpath)
+
+ popen = subprocess.Popen(cmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ shell=True,
+ )
+ stdout, stderr = popen.communicate()
+ stdout = py.builtin._totext(stdout, sys.getdefaultencoding())
+ minidom,ExpatError = importxml()
+ try:
+ tree = minidom.parseString(stdout)
+ except ExpatError:
+ raise ValueError('no such revision')
+ result = []
+ for logentry in filter(None, tree.firstChild.childNodes):
+ if logentry.nodeType == logentry.ELEMENT_NODE:
+ result.append(LogEntry(logentry))
+ return result
+
+ def size(self):
+ """ Return the size of the file content of the Path. """
+ return self.info().size
+
+ def mtime(self):
+ """ Return the last modification time of the file. """
+ return self.info().mtime
+
+ def __hash__(self):
+ return hash((self.strpath, self.__class__, self.auth))
+
+
+class WCStatus:
+ attrnames = ('modified','added', 'conflict', 'unchanged', 'external',
+ 'deleted', 'prop_modified', 'unknown', 'update_available',
+ 'incomplete', 'kindmismatch', 'ignored', 'locked', 'replaced'
+ )
+
+ def __init__(self, wcpath, rev=None, modrev=None, author=None):
+ self.wcpath = wcpath
+ self.rev = rev
+ self.modrev = modrev
+ self.author = author
+
+ for name in self.attrnames:
+ setattr(self, name, [])
+
+ def allpath(self, sort=True, **kw):
+ d = {}
+ for name in self.attrnames:
+ if name not in kw or kw[name]:
+ for path in getattr(self, name):
+ d[path] = 1
+ l = d.keys()
+ if sort:
+ l.sort()
+ return l
+
+ # XXX a bit scary to assume there's always 2 spaces between username and
+ # path, however with win32 allowing spaces in user names there doesn't
+ # seem to be a more solid approach :(
+ _rex_status = re.compile(r'\s+(\d+|-)\s+(\S+)\s+(.+?)\s{2,}(.*)')
+
+ def fromstring(data, rootwcpath, rev=None, modrev=None, author=None):
+ """ return a new WCStatus object from data 's'
+ """
+ rootstatus = WCStatus(rootwcpath, rev, modrev, author)
+ update_rev = None
+ for line in data.split('\n'):
+ if not line.strip():
+ continue
+ #print "processing %r" % line
+ flags, rest = line[:8], line[8:]
+ # first column
+ c0,c1,c2,c3,c4,c5,x6,c7 = flags
+ #if '*' in line:
+ # print "flags", repr(flags), "rest", repr(rest)
+
+ if c0 in '?XI':
+ fn = line.split(None, 1)[1]
+ if c0 == '?':
+ wcpath = rootwcpath.join(fn, abs=1)
+ rootstatus.unknown.append(wcpath)
+ elif c0 == 'X':
+ wcpath = rootwcpath.__class__(
+ rootwcpath.localpath.join(fn, abs=1),
+ auth=rootwcpath.auth)
+ rootstatus.external.append(wcpath)
+ elif c0 == 'I':
+ wcpath = rootwcpath.join(fn, abs=1)
+ rootstatus.ignored.append(wcpath)
+
+ continue
+
+ #elif c0 in '~!' or c4 == 'S':
+ # raise NotImplementedError("received flag %r" % c0)
+
+ m = WCStatus._rex_status.match(rest)
+ if not m:
+ if c7 == '*':
+ fn = rest.strip()
+ wcpath = rootwcpath.join(fn, abs=1)
+ rootstatus.update_available.append(wcpath)
+ continue
+ if line.lower().find('against revision:')!=-1:
+ update_rev = int(rest.split(':')[1].strip())
+ continue
+ if line.lower().find('status on external') > -1:
+ # XXX not sure what to do here... perhaps we want to
+ # store some state instead of just continuing, as right
+ # now it makes the top-level external get added twice
+ # (once as external, once as 'normal' unchanged item)
+ # because of the way SVN presents external items
+ continue
+ # keep trying
+ raise ValueError("could not parse line %r" % line)
+ else:
+ rev, modrev, author, fn = m.groups()
+ wcpath = rootwcpath.join(fn, abs=1)
+ #assert wcpath.check()
+ if c0 == 'M':
+ assert wcpath.check(file=1), "didn't expect a directory with changed content here"
+ rootstatus.modified.append(wcpath)
+ elif c0 == 'A' or c3 == '+' :
+ rootstatus.added.append(wcpath)
+ elif c0 == 'D':
+ rootstatus.deleted.append(wcpath)
+ elif c0 == 'C':
+ rootstatus.conflict.append(wcpath)
+ elif c0 == '~':
+ rootstatus.kindmismatch.append(wcpath)
+ elif c0 == '!':
+ rootstatus.incomplete.append(wcpath)
+ elif c0 == 'R':
+ rootstatus.replaced.append(wcpath)
+ elif not c0.strip():
+ rootstatus.unchanged.append(wcpath)
+ else:
+ raise NotImplementedError("received flag %r" % c0)
+
+ if c1 == 'M':
+ rootstatus.prop_modified.append(wcpath)
+ # XXX do we cover all client versions here?
+ if c2 == 'L' or c5 == 'K':
+ rootstatus.locked.append(wcpath)
+ if c7 == '*':
+ rootstatus.update_available.append(wcpath)
+
+ if wcpath == rootwcpath:
+ rootstatus.rev = rev
+ rootstatus.modrev = modrev
+ rootstatus.author = author
+ if update_rev:
+ rootstatus.update_rev = update_rev
+ continue
+ return rootstatus
+ fromstring = staticmethod(fromstring)
+
+class XMLWCStatus(WCStatus):
+ def fromstring(data, rootwcpath, rev=None, modrev=None, author=None):
+ """ parse 'data' (XML string as outputted by svn st) into a status obj
+ """
+ # XXX for externals, the path is shown twice: once
+ # with external information, and once with full info as if
+ # the item was a normal non-external... the current way of
+ # dealing with this issue is by ignoring it - this does make
+ # externals appear as external items as well as 'normal',
+ # unchanged ones in the status object so this is far from ideal
+ rootstatus = WCStatus(rootwcpath, rev, modrev, author)
+ update_rev = None
+ minidom, ExpatError = importxml()
+ try:
+ doc = minidom.parseString(data)
+ except ExpatError:
+ e = sys.exc_info()[1]
+ raise ValueError(str(e))
+ urevels = doc.getElementsByTagName('against')
+ if urevels:
+ rootstatus.update_rev = urevels[-1].getAttribute('revision')
+ for entryel in doc.getElementsByTagName('entry'):
+ path = entryel.getAttribute('path')
+ statusel = entryel.getElementsByTagName('wc-status')[0]
+ itemstatus = statusel.getAttribute('item')
+
+ if itemstatus == 'unversioned':
+ wcpath = rootwcpath.join(path, abs=1)
+ rootstatus.unknown.append(wcpath)
+ continue
+ elif itemstatus == 'external':
+ wcpath = rootwcpath.__class__(
+ rootwcpath.localpath.join(path, abs=1),
+ auth=rootwcpath.auth)
+ rootstatus.external.append(wcpath)
+ continue
+ elif itemstatus == 'ignored':
+ wcpath = rootwcpath.join(path, abs=1)
+ rootstatus.ignored.append(wcpath)
+ continue
+ elif itemstatus == 'incomplete':
+ wcpath = rootwcpath.join(path, abs=1)
+ rootstatus.incomplete.append(wcpath)
+ continue
+
+ rev = statusel.getAttribute('revision')
+ if itemstatus == 'added' or itemstatus == 'none':
+ rev = '0'
+ modrev = '?'
+ author = '?'
+ date = ''
+ elif itemstatus == "replaced":
+ pass
+ else:
+ #print entryel.toxml()
+ commitel = entryel.getElementsByTagName('commit')[0]
+ if commitel:
+ modrev = commitel.getAttribute('revision')
+ author = ''
+ author_els = commitel.getElementsByTagName('author')
+ if author_els:
+ for c in author_els[0].childNodes:
+ author += c.nodeValue
+ date = ''
+ for c in commitel.getElementsByTagName('date')[0]\
+ .childNodes:
+ date += c.nodeValue
+
+ wcpath = rootwcpath.join(path, abs=1)
+
+ assert itemstatus != 'modified' or wcpath.check(file=1), (
+ 'did\'t expect a directory with changed content here')
+
+ itemattrname = {
+ 'normal': 'unchanged',
+ 'unversioned': 'unknown',
+ 'conflicted': 'conflict',
+ 'none': 'added',
+ }.get(itemstatus, itemstatus)
+
+ attr = getattr(rootstatus, itemattrname)
+ attr.append(wcpath)
+
+ propsstatus = statusel.getAttribute('props')
+ if propsstatus not in ('none', 'normal'):
+ rootstatus.prop_modified.append(wcpath)
+
+ if wcpath == rootwcpath:
+ rootstatus.rev = rev
+ rootstatus.modrev = modrev
+ rootstatus.author = author
+ rootstatus.date = date
+
+ # handle repos-status element (remote info)
+ rstatusels = entryel.getElementsByTagName('repos-status')
+ if rstatusels:
+ rstatusel = rstatusels[0]
+ ritemstatus = rstatusel.getAttribute('item')
+ if ritemstatus in ('added', 'modified'):
+ rootstatus.update_available.append(wcpath)
+
+ lockels = entryel.getElementsByTagName('lock')
+ if len(lockels):
+ rootstatus.locked.append(wcpath)
+
+ return rootstatus
+ fromstring = staticmethod(fromstring)
+
+class InfoSvnWCCommand:
+ def __init__(self, output):
+ # Path: test
+ # URL: http://codespeak.net/svn/std.path/trunk/dist/std.path/test
+ # Repository UUID: fd0d7bf2-dfb6-0310-8d31-b7ecfe96aada
+ # Revision: 2151
+ # Node Kind: directory
+ # Schedule: normal
+ # Last Changed Author: hpk
+ # Last Changed Rev: 2100
+ # Last Changed Date: 2003-10-27 20:43:14 +0100 (Mon, 27 Oct 2003)
+ # Properties Last Updated: 2003-11-03 14:47:48 +0100 (Mon, 03 Nov 2003)
+
+ d = {}
+ for line in output.split('\n'):
+ if not line.strip():
+ continue
+ key, value = line.split(':', 1)
+ key = key.lower().replace(' ', '')
+ value = value.strip()
+ d[key] = value
+ try:
+ self.url = d['url']
+ except KeyError:
+ raise ValueError("Not a versioned resource")
+ #raise ValueError, "Not a versioned resource %r" % path
+ self.kind = d['nodekind'] == 'directory' and 'dir' or d['nodekind']
+ try:
+ self.rev = int(d['revision'])
+ except KeyError:
+ self.rev = None
+
+ self.path = py.path.local(d['path'])
+ self.size = self.path.size()
+ if 'lastchangedrev' in d:
+ self.created_rev = int(d['lastchangedrev'])
+ if 'lastchangedauthor' in d:
+ self.last_author = d['lastchangedauthor']
+ if 'lastchangeddate' in d:
+ self.mtime = parse_wcinfotime(d['lastchangeddate'])
+ self.time = self.mtime * 1000000
+
+ def __eq__(self, other):
+ return self.__dict__ == other.__dict__
+
+def parse_wcinfotime(timestr):
+ """ Returns seconds since epoch, UTC. """
+ # example: 2003-10-27 20:43:14 +0100 (Mon, 27 Oct 2003)
+ m = re.match(r'(\d+-\d+-\d+ \d+:\d+:\d+) ([+-]\d+) .*', timestr)
+ if not m:
+ raise ValueError("timestring %r does not match" % timestr)
+ timestr, timezone = m.groups()
+ # do not handle timezone specially, return value should be UTC
+ parsedtime = time.strptime(timestr, "%Y-%m-%d %H:%M:%S")
+ return calendar.timegm(parsedtime)
+
+def make_recursive_propdict(wcroot,
+ output,
+ rex = re.compile("Properties on '(.*)':")):
+ """ Return a dictionary of path->PropListDict mappings. """
+ lines = [x for x in output.split('\n') if x]
+ pdict = {}
+ while lines:
+ line = lines.pop(0)
+ m = rex.match(line)
+ if not m:
+ raise ValueError("could not parse propget-line: %r" % line)
+ path = m.groups()[0]
+ wcpath = wcroot.join(path, abs=1)
+ propnames = []
+ while lines and lines[0].startswith(' '):
+ propname = lines.pop(0).strip()
+ propnames.append(propname)
+ assert propnames, "must have found properties!"
+ pdict[wcpath] = PropListDict(wcpath, propnames)
+ return pdict
+
+
+def importxml(cache=[]):
+ if cache:
+ return cache
+ from xml.dom import minidom
+ from xml.parsers.expat import ExpatError
+ cache.extend([minidom, ExpatError])
+ return cache
+
+class LogEntry:
+ def __init__(self, logentry):
+ self.rev = int(logentry.getAttribute('revision'))
+ for lpart in filter(None, logentry.childNodes):
+ if lpart.nodeType == lpart.ELEMENT_NODE:
+ if lpart.nodeName == 'author':
+ self.author = lpart.firstChild.nodeValue
+ elif lpart.nodeName == 'msg':
+ if lpart.firstChild:
+ self.msg = lpart.firstChild.nodeValue
+ else:
+ self.msg = ''
+ elif lpart.nodeName == 'date':
+ #2003-07-29T20:05:11.598637Z
+ timestr = lpart.firstChild.nodeValue
+ self.date = parse_apr_time(timestr)
+ elif lpart.nodeName == 'paths':
+ self.strpaths = []
+ for ppart in filter(None, lpart.childNodes):
+ if ppart.nodeType == ppart.ELEMENT_NODE:
+ self.strpaths.append(PathEntry(ppart))
+ def __repr__(self):
+ return '<Logentry rev=%d author=%s date=%s>' % (
+ self.rev, self.author, self.date)
+
+
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_process/__init__.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_process/__init__.py
index 86c714ad1ae..86c714ad1ae 100644
--- a/tests/wpt/web-platform-tests/tools/py/py/_process/__init__.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_process/__init__.py
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_process/cmdexec.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_process/cmdexec.py
index f83a2494029..f83a2494029 100644
--- a/tests/wpt/web-platform-tests/tools/py/py/_process/cmdexec.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_process/cmdexec.py
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_process/forkedfunc.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_process/forkedfunc.py
index 1c285306884..1c285306884 100644
--- a/tests/wpt/web-platform-tests/tools/py/py/_process/forkedfunc.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_process/forkedfunc.py
diff --git a/tests/wpt/web-platform-tests/tools/py/py/_process/killproc.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_process/killproc.py
index 18e8310b5f6..18e8310b5f6 100644
--- a/tests/wpt/web-platform-tests/tools/py/py/_process/killproc.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_process/killproc.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_std.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_std.py
new file mode 100644
index 00000000000..74d43672654
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_std.py
@@ -0,0 +1,26 @@
+import sys
+import warnings
+
+
+class PyStdIsDeprecatedWarning(DeprecationWarning):
+ pass
+
+
+class Std(object):
+ """ makes top-level python modules available as an attribute,
+ importing them on first access.
+ """
+
+ def __init__(self):
+ self.__dict__ = sys.modules
+
+ def __getattr__(self, name):
+ warnings.warn("py.std is deprecated, plase import %s directly" % name,
+ category=PyStdIsDeprecatedWarning)
+ try:
+ m = __import__(name)
+ except ImportError:
+ raise AttributeError("py.std: could not import %s" % name)
+ return m
+
+std = Std()
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/__init__.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/__init__.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/DESCRIPTION.rst b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/DESCRIPTION.rst
new file mode 100644
index 00000000000..548222007fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/DESCRIPTION.rst
@@ -0,0 +1,87 @@
+Welcome to apipkg!
+------------------------
+
+With apipkg you can control the exported namespace of a
+python package and greatly reduce the number of imports for your users.
+It is a `small pure python module`_ that works on virtually all Python
+versions, including CPython2.3 to Python3.1, Jython and PyPy. It co-operates
+well with Python's ``help()`` system, custom importers (PEP302) and common
+command line completion tools.
+
+Usage is very simple: you can require 'apipkg' as a dependency or you
+can copy paste the <200 Lines of code into your project.
+
+
+Tutorial example
+-------------------
+
+Here is a simple ``mypkg`` package that specifies one namespace
+and exports two objects imported from different modules::
+
+ # mypkg/__init__.py
+ import apipkg
+ apipkg.initpkg(__name__, {
+ 'path': {
+ 'Class1': "_mypkg.somemodule:Class1",
+ 'clsattr': "_mypkg.othermodule:Class2.attr",
+ }
+ }
+
+The package is initialized with a dictionary as namespace.
+
+You need to create a ``_mypkg`` package with a ``somemodule.py``
+and ``othermodule.py`` containing the respective classes.
+The ``_mypkg`` is not special - it's a completely
+regular python package.
+
+Namespace dictionaries contain ``name: value`` mappings
+where the value may be another namespace dictionary or
+a string specifying an import location. On accessing
+an namespace attribute an import will be performed::
+
+ >>> import mypkg
+ >>> mypkg.path
+ <ApiModule 'mypkg.path'>
+ >>> mypkg.path.Class1 # '_mypkg.somemodule' gets imported now
+ <class _mypkg.somemodule.Class1 at 0xb7d428fc>
+ >>> mypkg.path.clsattr # '_mypkg.othermodule' gets imported now
+ 4 # the value of _mypkg.othermodule.Class2.attr
+
+The ``mypkg.path`` namespace and its two entries are
+loaded when they are accessed. This means:
+
+* lazy loading - only what is actually needed is ever loaded
+
+* only the root "mypkg" ever needs to be imported to get
+ access to the complete functionality.
+
+* the underlying modules are also accessible, for example::
+
+ from mypkg.sub import Class1
+
+
+Including apipkg in your package
+--------------------------------------
+
+If you don't want to add an ``apipkg`` dependency to your package you
+can copy the `apipkg.py`_ file somewhere to your own package,
+for example ``_mypkg/apipkg.py`` in the above example. You
+then import the ``initpkg`` function from that new place and
+are good to go.
+
+.. _`small pure python module`:
+.. _`apipkg.py`: http://bitbucket.org/hpk42/apipkg/src/tip/apipkg.py
+
+Feedback?
+-----------------------
+
+If you have questions you are welcome to
+
+* join the #pylib channel on irc.freenode.net
+* subscribe to the http://codespeak.net/mailman/listinfo/py-dev list.
+* create an issue on http://bitbucket.org/hpk42/apipkg/issues
+
+have fun,
+holger krekel
+
+
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/INSTALLER b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/INSTALLER
new file mode 100644
index 00000000000..a1b589e38a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/METADATA b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/METADATA
new file mode 100644
index 00000000000..eb7e60acffa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/METADATA
@@ -0,0 +1,109 @@
+Metadata-Version: 2.0
+Name: apipkg
+Version: 1.4
+Summary: apipkg: namespace control and lazy-import mechanism
+Home-page: http://bitbucket.org/hpk42/apipkg
+Author: holger krekel
+Author-email: holger at merlinux.eu
+License: MIT License
+Platform: unix
+Platform: linux
+Platform: osx
+Platform: cygwin
+Platform: win32
+Classifier: Development Status :: 4 - Beta
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Operating System :: POSIX
+Classifier: Operating System :: Microsoft :: Windows
+Classifier: Operating System :: MacOS :: MacOS X
+Classifier: Topic :: Software Development :: Libraries
+Classifier: Programming Language :: Python
+
+Welcome to apipkg!
+------------------------
+
+With apipkg you can control the exported namespace of a
+python package and greatly reduce the number of imports for your users.
+It is a `small pure python module`_ that works on virtually all Python
+versions, including CPython2.3 to Python3.1, Jython and PyPy. It co-operates
+well with Python's ``help()`` system, custom importers (PEP302) and common
+command line completion tools.
+
+Usage is very simple: you can require 'apipkg' as a dependency or you
+can copy paste the <200 Lines of code into your project.
+
+
+Tutorial example
+-------------------
+
+Here is a simple ``mypkg`` package that specifies one namespace
+and exports two objects imported from different modules::
+
+ # mypkg/__init__.py
+ import apipkg
+ apipkg.initpkg(__name__, {
+ 'path': {
+ 'Class1': "_mypkg.somemodule:Class1",
+ 'clsattr': "_mypkg.othermodule:Class2.attr",
+ }
+ }
+
+The package is initialized with a dictionary as namespace.
+
+You need to create a ``_mypkg`` package with a ``somemodule.py``
+and ``othermodule.py`` containing the respective classes.
+The ``_mypkg`` is not special - it's a completely
+regular python package.
+
+Namespace dictionaries contain ``name: value`` mappings
+where the value may be another namespace dictionary or
+a string specifying an import location. On accessing
+an namespace attribute an import will be performed::
+
+ >>> import mypkg
+ >>> mypkg.path
+ <ApiModule 'mypkg.path'>
+ >>> mypkg.path.Class1 # '_mypkg.somemodule' gets imported now
+ <class _mypkg.somemodule.Class1 at 0xb7d428fc>
+ >>> mypkg.path.clsattr # '_mypkg.othermodule' gets imported now
+ 4 # the value of _mypkg.othermodule.Class2.attr
+
+The ``mypkg.path`` namespace and its two entries are
+loaded when they are accessed. This means:
+
+* lazy loading - only what is actually needed is ever loaded
+
+* only the root "mypkg" ever needs to be imported to get
+ access to the complete functionality.
+
+* the underlying modules are also accessible, for example::
+
+ from mypkg.sub import Class1
+
+
+Including apipkg in your package
+--------------------------------------
+
+If you don't want to add an ``apipkg`` dependency to your package you
+can copy the `apipkg.py`_ file somewhere to your own package,
+for example ``_mypkg/apipkg.py`` in the above example. You
+then import the ``initpkg`` function from that new place and
+are good to go.
+
+.. _`small pure python module`:
+.. _`apipkg.py`: http://bitbucket.org/hpk42/apipkg/src/tip/apipkg.py
+
+Feedback?
+-----------------------
+
+If you have questions you are welcome to
+
+* join the #pylib channel on irc.freenode.net
+* subscribe to the http://codespeak.net/mailman/listinfo/py-dev list.
+* create an issue on http://bitbucket.org/hpk42/apipkg/issues
+
+have fun,
+holger krekel
+
+
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/RECORD b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/RECORD
new file mode 100644
index 00000000000..dc72959dfe0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/RECORD
@@ -0,0 +1,9 @@
+apipkg.py,sha256=BNnv_qvq8zZvku-uudoqgp3XTNFbwsNUmtzOKrVI7X0,6420
+apipkg-1.4.dist-info/top_level.txt,sha256=3TGS6nmN7kjxhUK4LpPCB3QkQI34QYGrT0ZQGWajoZ8,7
+apipkg-1.4.dist-info/METADATA,sha256=Fk_8BrHyXE--kvB3_ZBKgwvPaKusAZUjchH-kpB63Hs,3491
+apipkg-1.4.dist-info/DESCRIPTION.rst,sha256=RkMQqk5ljhGy0DiZkR_nbpjqvwCIhuIEHsyvkn3O96k,2803
+apipkg-1.4.dist-info/metadata.json,sha256=GdshYrA_7gAII3E3EQMH-31BHzU-klTZ6bPQzlDmuy4,779
+apipkg-1.4.dist-info/WHEEL,sha256=AvR0WeTpDaxT645bl5FQxUK6NPsTls2ttpcGJg3j1Xg,110
+apipkg-1.4.dist-info/RECORD,,
+apipkg-1.4.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+__pycache__/apipkg.cpython-35.pyc,,
diff --git a/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/WHEEL b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/WHEEL
index 9dff69d8610..9dff69d8610 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/_pytest/vendored_packages/pluggy-0.3.1.dist-info/WHEEL
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/WHEEL
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/metadata.json b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/metadata.json
new file mode 100644
index 00000000000..05609b99373
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/metadata.json
@@ -0,0 +1 @@
+{"license": "MIT License", "name": "apipkg", "metadata_version": "2.0", "generator": "bdist_wheel (0.24.0)", "summary": "apipkg: namespace control and lazy-import mechanism", "platform": "unix", "version": "1.4", "extensions": {"python.details": {"project_urls": {"Home": "http://bitbucket.org/hpk42/apipkg"}, "document_names": {"description": "DESCRIPTION.rst"}, "contacts": [{"role": "author", "email": "holger at merlinux.eu", "name": "holger krekel"}]}}, "classifiers": ["Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: POSIX", "Operating System :: Microsoft :: Windows", "Operating System :: MacOS :: MacOS X", "Topic :: Software Development :: Libraries", "Programming Language :: Python"]} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/top_level.txt b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/top_level.txt
new file mode 100644
index 00000000000..e2221c8f9e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg-1.4.dist-info/top_level.txt
@@ -0,0 +1 @@
+apipkg
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg.py
new file mode 100644
index 00000000000..9d56e0bcbae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/apipkg.py
@@ -0,0 +1,205 @@
+"""
+apipkg: control the exported namespace of a python package.
+
+see http://pypi.python.org/pypi/apipkg
+
+(c) holger krekel, 2009 - MIT license
+"""
+import os
+import sys
+from types import ModuleType
+
+
+__version__ = '1.4'
+
+
+def _py_abspath(path):
+ """
+ special version of abspath
+ that will leave paths from jython jars alone
+ """
+ if path.startswith('__pyclasspath__'):
+
+ return path
+ else:
+ return os.path.abspath(path)
+
+
+def distribution_version(name):
+ """try to get the version of the named distribution,
+ returs None on failure"""
+ from pkg_resources import get_distribution, DistributionNotFound
+ try:
+ dist = get_distribution(name)
+ except DistributionNotFound:
+ pass
+ else:
+ return dist.version
+
+
+def initpkg(pkgname, exportdefs, attr=dict(), eager=False):
+ """ initialize given package from the export definitions. """
+ oldmod = sys.modules.get(pkgname)
+ d = {}
+ f = getattr(oldmod, '__file__', None)
+ if f:
+ f = _py_abspath(f)
+ d['__file__'] = f
+ if hasattr(oldmod, '__version__'):
+ d['__version__'] = oldmod.__version__
+ if hasattr(oldmod, '__loader__'):
+ d['__loader__'] = oldmod.__loader__
+ if hasattr(oldmod, '__path__'):
+ d['__path__'] = [_py_abspath(p) for p in oldmod.__path__]
+ if '__doc__' not in exportdefs and getattr(oldmod, '__doc__', None):
+ d['__doc__'] = oldmod.__doc__
+ d.update(attr)
+ if hasattr(oldmod, "__dict__"):
+ oldmod.__dict__.update(d)
+ mod = ApiModule(pkgname, exportdefs, implprefix=pkgname, attr=d)
+ sys.modules[pkgname] = mod
+ # eagerload in bypthon to avoid their monkeypatching breaking packages
+ if 'bpython' in sys.modules or eager:
+ for module in sys.modules.values():
+ if isinstance(module, ApiModule):
+ module.__dict__
+
+
+def importobj(modpath, attrname):
+ module = __import__(modpath, None, None, ['__doc__'])
+ if not attrname:
+ return module
+
+ retval = module
+ names = attrname.split(".")
+ for x in names:
+ retval = getattr(retval, x)
+ return retval
+
+
+class ApiModule(ModuleType):
+ def __docget(self):
+ try:
+ return self.__doc
+ except AttributeError:
+ if '__doc__' in self.__map__:
+ return self.__makeattr('__doc__')
+
+ def __docset(self, value):
+ self.__doc = value
+ __doc__ = property(__docget, __docset)
+
+ def __init__(self, name, importspec, implprefix=None, attr=None):
+ self.__name__ = name
+ self.__all__ = [x for x in importspec if x != '__onfirstaccess__']
+ self.__map__ = {}
+ self.__implprefix__ = implprefix or name
+ if attr:
+ for name, val in attr.items():
+ # print "setting", self.__name__, name, val
+ setattr(self, name, val)
+ for name, importspec in importspec.items():
+ if isinstance(importspec, dict):
+ subname = '%s.%s' % (self.__name__, name)
+ apimod = ApiModule(subname, importspec, implprefix)
+ sys.modules[subname] = apimod
+ setattr(self, name, apimod)
+ else:
+ parts = importspec.split(':')
+ modpath = parts.pop(0)
+ attrname = parts and parts[0] or ""
+ if modpath[0] == '.':
+ modpath = implprefix + modpath
+
+ if not attrname:
+ subname = '%s.%s' % (self.__name__, name)
+ apimod = AliasModule(subname, modpath)
+ sys.modules[subname] = apimod
+ if '.' not in name:
+ setattr(self, name, apimod)
+ else:
+ self.__map__[name] = (modpath, attrname)
+
+ def __repr__(self):
+ l = []
+ if hasattr(self, '__version__'):
+ l.append("version=" + repr(self.__version__))
+ if hasattr(self, '__file__'):
+ l.append('from ' + repr(self.__file__))
+ if l:
+ return '<ApiModule %r %s>' % (self.__name__, " ".join(l))
+ return '<ApiModule %r>' % (self.__name__,)
+
+ def __makeattr(self, name):
+ """lazily compute value for name or raise AttributeError if unknown."""
+ # print "makeattr", self.__name__, name
+ target = None
+ if '__onfirstaccess__' in self.__map__:
+ target = self.__map__.pop('__onfirstaccess__')
+ importobj(*target)()
+ try:
+ modpath, attrname = self.__map__[name]
+ except KeyError:
+ if target is not None and name != '__onfirstaccess__':
+ # retry, onfirstaccess might have set attrs
+ return getattr(self, name)
+ raise AttributeError(name)
+ else:
+ result = importobj(modpath, attrname)
+ setattr(self, name, result)
+ try:
+ del self.__map__[name]
+ except KeyError:
+ pass # in a recursive-import situation a double-del can happen
+ return result
+
+ __getattr__ = __makeattr
+
+ @property
+ def __dict__(self):
+ # force all the content of the module
+ # to be loaded when __dict__ is read
+ dictdescr = ModuleType.__dict__['__dict__']
+ dict = dictdescr.__get__(self)
+ if dict is not None:
+ hasattr(self, 'some')
+ for name in self.__all__:
+ try:
+ self.__makeattr(name)
+ except AttributeError:
+ pass
+ return dict
+
+
+def AliasModule(modname, modpath, attrname=None):
+ mod = []
+
+ def getmod():
+ if not mod:
+ x = importobj(modpath, None)
+ if attrname is not None:
+ x = getattr(x, attrname)
+ mod.append(x)
+ return mod[0]
+
+ class AliasModule(ModuleType):
+
+ def __repr__(self):
+ x = modpath
+ if attrname:
+ x += "." + attrname
+ return '<AliasModule %r for %r>' % (modname, x)
+
+ def __getattribute__(self, name):
+ try:
+ return getattr(getmod(), name)
+ except ImportError:
+ return None
+
+ def __setattr__(self, name, value):
+ setattr(getmod(), name, value)
+
+ def __delattr__(self, name):
+ delattr(getmod(), name)
+
+ return AliasModule(str(modname))
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/DESCRIPTION.rst b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/DESCRIPTION.rst
new file mode 100644
index 00000000000..6d59bc222cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/DESCRIPTION.rst
@@ -0,0 +1,53 @@
+iniconfig: brain-dead simple parsing of ini files
+=======================================================
+
+iniconfig is a small and simple INI-file parser module
+having a unique set of features:
+
+* tested against Python2.4 across to Python3.2, Jython, PyPy
+* maintains order of sections and entries
+* supports multi-line values with or without line-continuations
+* supports "#" comments everywhere
+* raises errors with proper line-numbers
+* no bells and whistles like automatic substitutions
+* iniconfig raises an Error if two sections have the same name.
+
+If you encounter issues or have feature wishes please report them to:
+
+ http://github.org/RonnyPfannschmidt/iniconfig/issues
+
+Basic Example
+===================================
+
+If you have an ini file like this::
+
+ # content of example.ini
+ [section1] # comment
+ name1=value1 # comment
+ name1b=value1,value2 # comment
+
+ [section2]
+ name2=
+ line1
+ line2
+
+then you can do::
+
+ >>> import iniconfig
+ >>> ini = iniconfig.IniConfig("example.ini")
+ >>> ini['section1']['name1'] # raises KeyError if not exists
+ 'value1'
+ >>> ini.get('section1', 'name1b', [], lambda x: x.split(","))
+ ['value1', 'value2']
+ >>> ini.get('section1', 'notexist', [], lambda x: x.split(","))
+ []
+ >>> [x.name for x in list(ini)]
+ ['section1', 'section2']
+ >>> list(list(ini)[0].items())
+ [('name1', 'value1'), ('name1b', 'value1,value2')]
+ >>> 'section1' in ini
+ True
+ >>> 'inexistendsection' in ini
+ False
+
+
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/INSTALLER b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/INSTALLER
new file mode 100644
index 00000000000..a1b589e38a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/METADATA b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/METADATA
new file mode 100644
index 00000000000..79ea62dc34c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/METADATA
@@ -0,0 +1,78 @@
+Metadata-Version: 2.0
+Name: iniconfig
+Version: 1.0.0
+Summary: iniconfig: brain-dead simple config-ini parsing
+Home-page: http://github.com/RonnyPfannschmidt/iniconfig
+Author: Ronny Pfannschmidt, Holger Krekel
+Author-email: opensource@ronnypfannschmidt.de, holger.krekel@gmail.com
+License: MIT License
+Platform: unix
+Platform: linux
+Platform: osx
+Platform: cygwin
+Platform: win32
+Classifier: Development Status :: 4 - Beta
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Operating System :: POSIX
+Classifier: Operating System :: Microsoft :: Windows
+Classifier: Operating System :: MacOS :: MacOS X
+Classifier: Topic :: Software Development :: Libraries
+Classifier: Topic :: Utilities
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 3
+
+iniconfig: brain-dead simple parsing of ini files
+=======================================================
+
+iniconfig is a small and simple INI-file parser module
+having a unique set of features:
+
+* tested against Python2.4 across to Python3.2, Jython, PyPy
+* maintains order of sections and entries
+* supports multi-line values with or without line-continuations
+* supports "#" comments everywhere
+* raises errors with proper line-numbers
+* no bells and whistles like automatic substitutions
+* iniconfig raises an Error if two sections have the same name.
+
+If you encounter issues or have feature wishes please report them to:
+
+ http://github.org/RonnyPfannschmidt/iniconfig/issues
+
+Basic Example
+===================================
+
+If you have an ini file like this::
+
+ # content of example.ini
+ [section1] # comment
+ name1=value1 # comment
+ name1b=value1,value2 # comment
+
+ [section2]
+ name2=
+ line1
+ line2
+
+then you can do::
+
+ >>> import iniconfig
+ >>> ini = iniconfig.IniConfig("example.ini")
+ >>> ini['section1']['name1'] # raises KeyError if not exists
+ 'value1'
+ >>> ini.get('section1', 'name1b', [], lambda x: x.split(","))
+ ['value1', 'value2']
+ >>> ini.get('section1', 'notexist', [], lambda x: x.split(","))
+ []
+ >>> [x.name for x in list(ini)]
+ ['section1', 'section2']
+ >>> list(list(ini)[0].items())
+ [('name1', 'value1'), ('name1b', 'value1,value2')]
+ >>> 'section1' in ini
+ True
+ >>> 'inexistendsection' in ini
+ False
+
+
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/RECORD b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/RECORD
new file mode 100644
index 00000000000..ec2f5e17487
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/RECORD
@@ -0,0 +1,9 @@
+iniconfig.py,sha256=-pBe5AF_6aAwo1CxJQ8i_zJq6ejc6IxHta7qk2tNJhY,5208
+iniconfig-1.0.0.dist-info/DESCRIPTION.rst,sha256=BDLMwWqfjpwZ5yqXRvz1x6bf8Dnt_pZhElekAwtL19o,1522
+iniconfig-1.0.0.dist-info/METADATA,sha256=bb2T8WUSDXXiUVxZ4WXhbffq6stikMTlB1jyrPbLfyU,2405
+iniconfig-1.0.0.dist-info/RECORD,,
+iniconfig-1.0.0.dist-info/WHEEL,sha256=3XK1Z4AI42GuJXciCpiHMOkbehxRV8QDBW8IU41k3ZU,96
+iniconfig-1.0.0.dist-info/metadata.json,sha256=UYYwW0p815nU4qz8Iq1gGqIYaAcsCyGju3jXvTOyXSI,950
+iniconfig-1.0.0.dist-info/top_level.txt,sha256=7KfM0fugdlToj9UW7enKXk2HYALQD8qHiyKtjhSzgN8,10
+iniconfig-1.0.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+__pycache__/iniconfig.cpython-35.pyc,,
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/WHEEL b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/WHEEL
new file mode 100644
index 00000000000..15b96c99cac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/WHEEL
@@ -0,0 +1,5 @@
+Wheel-Version: 1.0
+Generator: bdist_wheel (0.30.0.a0)
+Root-Is-Purelib: true
+Tag: cp35-none-any
+
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/metadata.json b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/metadata.json
new file mode 100644
index 00000000000..084daa6c06b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/metadata.json
@@ -0,0 +1 @@
+{"classifiers": ["Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: POSIX", "Operating System :: Microsoft :: Windows", "Operating System :: MacOS :: MacOS X", "Topic :: Software Development :: Libraries", "Topic :: Utilities", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 3"], "extensions": {"python.details": {"contacts": [{"email": "opensource@ronnypfannschmidt.de, holger.krekel@gmail.com", "name": "Ronny Pfannschmidt, Holger Krekel", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "http://github.com/RonnyPfannschmidt/iniconfig"}}}, "generator": "bdist_wheel (0.30.0.a0)", "license": "MIT License", "metadata_version": "2.0", "name": "iniconfig", "platform": "unix", "summary": "iniconfig: brain-dead simple config-ini parsing", "version": "1.0.0"} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/top_level.txt b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/top_level.txt
new file mode 100644
index 00000000000..9dda53692d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig-1.0.0.dist-info/top_level.txt
@@ -0,0 +1 @@
+iniconfig
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig.py
new file mode 100644
index 00000000000..6ad9eaf868b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_vendored_packages/iniconfig.py
@@ -0,0 +1,165 @@
+""" brain-dead simple parser for ini-style files.
+(C) Ronny Pfannschmidt, Holger Krekel -- MIT licensed
+"""
+__all__ = ['IniConfig', 'ParseError']
+
+COMMENTCHARS = "#;"
+
+
+class ParseError(Exception):
+ def __init__(self, path, lineno, msg):
+ Exception.__init__(self, path, lineno, msg)
+ self.path = path
+ self.lineno = lineno
+ self.msg = msg
+
+ def __str__(self):
+ return "%s:%s: %s" % (self.path, self.lineno+1, self.msg)
+
+
+class SectionWrapper(object):
+ def __init__(self, config, name):
+ self.config = config
+ self.name = name
+
+ def lineof(self, name):
+ return self.config.lineof(self.name, name)
+
+ def get(self, key, default=None, convert=str):
+ return self.config.get(self.name, key,
+ convert=convert, default=default)
+
+ def __getitem__(self, key):
+ return self.config.sections[self.name][key]
+
+ def __iter__(self):
+ section = self.config.sections.get(self.name, [])
+
+ def lineof(key):
+ return self.config.lineof(self.name, key)
+ for name in sorted(section, key=lineof):
+ yield name
+
+ def items(self):
+ for name in self:
+ yield name, self[name]
+
+
+class IniConfig(object):
+ def __init__(self, path, data=None):
+ self.path = str(path) # convenience
+ if data is None:
+ f = open(self.path)
+ try:
+ tokens = self._parse(iter(f))
+ finally:
+ f.close()
+ else:
+ tokens = self._parse(data.splitlines(True))
+
+ self._sources = {}
+ self.sections = {}
+
+ for lineno, section, name, value in tokens:
+ if section is None:
+ self._raise(lineno, 'no section header defined')
+ self._sources[section, name] = lineno
+ if name is None:
+ if section in self.sections:
+ self._raise(lineno, 'duplicate section %r' % (section, ))
+ self.sections[section] = {}
+ else:
+ if name in self.sections[section]:
+ self._raise(lineno, 'duplicate name %r' % (name, ))
+ self.sections[section][name] = value
+
+ def _raise(self, lineno, msg):
+ raise ParseError(self.path, lineno, msg)
+
+ def _parse(self, line_iter):
+ result = []
+ section = None
+ for lineno, line in enumerate(line_iter):
+ name, data = self._parseline(line, lineno)
+ # new value
+ if name is not None and data is not None:
+ result.append((lineno, section, name, data))
+ # new section
+ elif name is not None and data is None:
+ if not name:
+ self._raise(lineno, 'empty section name')
+ section = name
+ result.append((lineno, section, None, None))
+ # continuation
+ elif name is None and data is not None:
+ if not result:
+ self._raise(lineno, 'unexpected value continuation')
+ last = result.pop()
+ last_name, last_data = last[-2:]
+ if last_name is None:
+ self._raise(lineno, 'unexpected value continuation')
+
+ if last_data:
+ data = '%s\n%s' % (last_data, data)
+ result.append(last[:-1] + (data,))
+ return result
+
+ def _parseline(self, line, lineno):
+ # blank lines
+ if iscommentline(line):
+ line = ""
+ else:
+ line = line.rstrip()
+ if not line:
+ return None, None
+ # section
+ if line[0] == '[':
+ realline = line
+ for c in COMMENTCHARS:
+ line = line.split(c)[0].rstrip()
+ if line[-1] == "]":
+ return line[1:-1], None
+ return None, realline.strip()
+ # value
+ elif not line[0].isspace():
+ try:
+ name, value = line.split('=', 1)
+ if ":" in name:
+ raise ValueError()
+ except ValueError:
+ try:
+ name, value = line.split(":", 1)
+ except ValueError:
+ self._raise(lineno, 'unexpected line: %r' % line)
+ return name.strip(), value.strip()
+ # continuation
+ else:
+ return None, line.strip()
+
+ def lineof(self, section, name=None):
+ lineno = self._sources.get((section, name))
+ if lineno is not None:
+ return lineno + 1
+
+ def get(self, section, name, default=None, convert=str):
+ try:
+ return convert(self.sections[section][name])
+ except KeyError:
+ return default
+
+ def __getitem__(self, name):
+ if name not in self.sections:
+ raise KeyError(name)
+ return SectionWrapper(self, name)
+
+ def __iter__(self):
+ for name in sorted(self.sections, key=self.lineof):
+ yield SectionWrapper(self, name)
+
+ def __contains__(self, arg):
+ return arg in self.sections
+
+
+def iscommentline(line):
+ c = line.lstrip()[:1]
+ return c in COMMENTCHARS
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/py/_xmlgen.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/_xmlgen.py
new file mode 100644
index 00000000000..1c835458843
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/_xmlgen.py
@@ -0,0 +1,255 @@
+"""
+module for generating and serializing xml and html structures
+by using simple python objects.
+
+(c) holger krekel, holger at merlinux eu. 2009
+"""
+import sys, re
+
+if sys.version_info >= (3,0):
+ def u(s):
+ return s
+ def unicode(x, errors=None):
+ if hasattr(x, '__unicode__'):
+ return x.__unicode__()
+ return str(x)
+else:
+ def u(s):
+ return unicode(s)
+ unicode = unicode
+
+
+class NamespaceMetaclass(type):
+ def __getattr__(self, name):
+ if name[:1] == '_':
+ raise AttributeError(name)
+ if self == Namespace:
+ raise ValueError("Namespace class is abstract")
+ tagspec = self.__tagspec__
+ if tagspec is not None and name not in tagspec:
+ raise AttributeError(name)
+ classattr = {}
+ if self.__stickyname__:
+ classattr['xmlname'] = name
+ cls = type(name, (self.__tagclass__,), classattr)
+ setattr(self, name, cls)
+ return cls
+
+class Tag(list):
+ class Attr(object):
+ def __init__(self, **kwargs):
+ self.__dict__.update(kwargs)
+
+ def __init__(self, *args, **kwargs):
+ super(Tag, self).__init__(args)
+ self.attr = self.Attr(**kwargs)
+
+ def __unicode__(self):
+ return self.unicode(indent=0)
+ __str__ = __unicode__
+
+ def unicode(self, indent=2):
+ l = []
+ SimpleUnicodeVisitor(l.append, indent).visit(self)
+ return u("").join(l)
+
+ def __repr__(self):
+ name = self.__class__.__name__
+ return "<%r tag object %d>" % (name, id(self))
+
+Namespace = NamespaceMetaclass('Namespace', (object, ), {
+ '__tagspec__': None,
+ '__tagclass__': Tag,
+ '__stickyname__': False,
+})
+
+class HtmlTag(Tag):
+ def unicode(self, indent=2):
+ l = []
+ HtmlVisitor(l.append, indent, shortempty=False).visit(self)
+ return u("").join(l)
+
+# exported plain html namespace
+class html(Namespace):
+ __tagclass__ = HtmlTag
+ __stickyname__ = True
+ __tagspec__ = dict([(x,1) for x in (
+ 'a,abbr,acronym,address,applet,area,article,aside,audio,b,'
+ 'base,basefont,bdi,bdo,big,blink,blockquote,body,br,button,'
+ 'canvas,caption,center,cite,code,col,colgroup,command,comment,'
+ 'datalist,dd,del,details,dfn,dir,div,dl,dt,em,embed,'
+ 'fieldset,figcaption,figure,footer,font,form,frame,frameset,h1,'
+ 'h2,h3,h4,h5,h6,head,header,hgroup,hr,html,i,iframe,img,input,'
+ 'ins,isindex,kbd,keygen,label,legend,li,link,listing,map,mark,'
+ 'marquee,menu,meta,meter,multicol,nav,nobr,noembed,noframes,'
+ 'noscript,object,ol,optgroup,option,output,p,param,pre,progress,'
+ 'q,rp,rt,ruby,s,samp,script,section,select,small,source,span,'
+ 'strike,strong,style,sub,summary,sup,table,tbody,td,textarea,'
+ 'tfoot,th,thead,time,title,tr,track,tt,u,ul,xmp,var,video,wbr'
+ ).split(',') if x])
+
+ class Style(object):
+ def __init__(self, **kw):
+ for x, y in kw.items():
+ x = x.replace('_', '-')
+ setattr(self, x, y)
+
+
+class raw(object):
+ """just a box that can contain a unicode string that will be
+ included directly in the output"""
+ def __init__(self, uniobj):
+ self.uniobj = uniobj
+
+class SimpleUnicodeVisitor(object):
+ """ recursive visitor to write unicode. """
+ def __init__(self, write, indent=0, curindent=0, shortempty=True):
+ self.write = write
+ self.cache = {}
+ self.visited = {} # for detection of recursion
+ self.indent = indent
+ self.curindent = curindent
+ self.parents = []
+ self.shortempty = shortempty # short empty tags or not
+
+ def visit(self, node):
+ """ dispatcher on node's class/bases name. """
+ cls = node.__class__
+ try:
+ visitmethod = self.cache[cls]
+ except KeyError:
+ for subclass in cls.__mro__:
+ visitmethod = getattr(self, subclass.__name__, None)
+ if visitmethod is not None:
+ break
+ else:
+ visitmethod = self.__object
+ self.cache[cls] = visitmethod
+ visitmethod(node)
+
+ # the default fallback handler is marked private
+ # to avoid clashes with the tag name object
+ def __object(self, obj):
+ #self.write(obj)
+ self.write(escape(unicode(obj)))
+
+ def raw(self, obj):
+ self.write(obj.uniobj)
+
+ def list(self, obj):
+ assert id(obj) not in self.visited
+ self.visited[id(obj)] = 1
+ for elem in obj:
+ self.visit(elem)
+
+ def Tag(self, tag):
+ assert id(tag) not in self.visited
+ try:
+ tag.parent = self.parents[-1]
+ except IndexError:
+ tag.parent = None
+ self.visited[id(tag)] = 1
+ tagname = getattr(tag, 'xmlname', tag.__class__.__name__)
+ if self.curindent and not self._isinline(tagname):
+ self.write("\n" + u(' ') * self.curindent)
+ if tag:
+ self.curindent += self.indent
+ self.write(u('<%s%s>') % (tagname, self.attributes(tag)))
+ self.parents.append(tag)
+ for x in tag:
+ self.visit(x)
+ self.parents.pop()
+ self.write(u('</%s>') % tagname)
+ self.curindent -= self.indent
+ else:
+ nameattr = tagname+self.attributes(tag)
+ if self._issingleton(tagname):
+ self.write(u('<%s/>') % (nameattr,))
+ else:
+ self.write(u('<%s></%s>') % (nameattr, tagname))
+
+ def attributes(self, tag):
+ # serialize attributes
+ attrlist = dir(tag.attr)
+ attrlist.sort()
+ l = []
+ for name in attrlist:
+ res = self.repr_attribute(tag.attr, name)
+ if res is not None:
+ l.append(res)
+ l.extend(self.getstyle(tag))
+ return u("").join(l)
+
+ def repr_attribute(self, attrs, name):
+ if name[:2] != '__':
+ value = getattr(attrs, name)
+ if name.endswith('_'):
+ name = name[:-1]
+ if isinstance(value, raw):
+ insert = value.uniobj
+ else:
+ insert = escape(unicode(value))
+ return ' %s="%s"' % (name, insert)
+
+ def getstyle(self, tag):
+ """ return attribute list suitable for styling. """
+ try:
+ styledict = tag.style.__dict__
+ except AttributeError:
+ return []
+ else:
+ stylelist = [x+': ' + y for x,y in styledict.items()]
+ return [u(' style="%s"') % u('; ').join(stylelist)]
+
+ def _issingleton(self, tagname):
+ """can (and will) be overridden in subclasses"""
+ return self.shortempty
+
+ def _isinline(self, tagname):
+ """can (and will) be overridden in subclasses"""
+ return False
+
+class HtmlVisitor(SimpleUnicodeVisitor):
+
+ single = dict([(x, 1) for x in
+ ('br,img,area,param,col,hr,meta,link,base,'
+ 'input,frame').split(',')])
+ inline = dict([(x, 1) for x in
+ ('a abbr acronym b basefont bdo big br cite code dfn em font '
+ 'i img input kbd label q s samp select small span strike '
+ 'strong sub sup textarea tt u var'.split(' '))])
+
+ def repr_attribute(self, attrs, name):
+ if name == 'class_':
+ value = getattr(attrs, name)
+ if value is None:
+ return
+ return super(HtmlVisitor, self).repr_attribute(attrs, name)
+
+ def _issingleton(self, tagname):
+ return tagname in self.single
+
+ def _isinline(self, tagname):
+ return tagname in self.inline
+
+
+class _escape:
+ def __init__(self):
+ self.escape = {
+ u('"') : u('&quot;'), u('<') : u('&lt;'), u('>') : u('&gt;'),
+ u('&') : u('&amp;'), u("'") : u('&apos;'),
+ }
+ self.charef_rex = re.compile(u("|").join(self.escape.keys()))
+
+ def _replacer(self, match):
+ return self.escape[match.group(0)]
+
+ def __call__(self, ustring):
+ """ xml-escape the given unicode string. """
+ try:
+ ustring = unicode(ustring)
+ except UnicodeDecodeError:
+ ustring = unicode(ustring, 'utf-8', errors='replace')
+ return self.charef_rex.sub(self._replacer, ustring)
+
+escape = _escape()
diff --git a/tests/wpt/web-platform-tests/tools/py/py/test.py b/tests/wpt/web-platform-tests/tools/third_party/py/py/test.py
index aa5beb1789f..aa5beb1789f 100644
--- a/tests/wpt/web-platform-tests/tools/py/py/test.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/py/test.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/setup.cfg b/tests/wpt/web-platform-tests/tools/third_party/py/setup.cfg
new file mode 100644
index 00000000000..5f25c2febfd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/setup.cfg
@@ -0,0 +1,8 @@
+[wheel]
+universal = 1
+
+[metadata]
+license_file = LICENSE
+
+[devpi:upload]
+formats=sdist.tgz,bdist_wheel
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/setup.py b/tests/wpt/web-platform-tests/tools/third_party/py/setup.py
new file mode 100644
index 00000000000..959323b0c75
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/setup.py
@@ -0,0 +1,53 @@
+import os
+import sys
+
+from setuptools import setup, find_packages
+
+
+def get_version():
+ p = os.path.join(os.path.dirname(
+ os.path.abspath(__file__)), "py", "__init__.py")
+ with open(p) as f:
+ for line in f.readlines():
+ if "__version__" in line:
+ return line.strip().split("=")[-1].strip(" '")
+ raise ValueError("could not read version")
+
+
+def main():
+ setup(
+ name='py',
+ description='library with cross-python path, ini-parsing, io, code, log facilities',
+ long_description=open('README.rst').read(),
+ version=get_version(),
+ url='http://py.readthedocs.io/',
+ license='MIT license',
+ platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],
+ python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
+ author='holger krekel, Ronny Pfannschmidt, Benjamin Peterson and others',
+ author_email='pytest-dev@python.org',
+ classifiers=['Development Status :: 6 - Mature',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: MIT License',
+ 'Operating System :: POSIX',
+ 'Operating System :: Microsoft :: Windows',
+ 'Operating System :: MacOS :: MacOS X',
+ 'Topic :: Software Development :: Testing',
+ 'Topic :: Software Development :: Libraries',
+ 'Topic :: Utilities',
+ 'Programming Language :: Python',
+ 'Programming Language :: Python :: 2',
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.4',
+ 'Programming Language :: Python :: 3.5',
+ 'Programming Language :: Python :: 3.6',
+ 'Programming Language :: Python :: Implementation :: CPython',
+ 'Programming Language :: Python :: Implementation :: PyPy',
+ ],
+ packages=find_packages(exclude=['tasks', 'testing']),
+ zip_safe=False,
+ )
+
+if __name__ == '__main__':
+ main()
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/tasks/__init__.py b/tests/wpt/web-platform-tests/tools/third_party/py/tasks/__init__.py
new file mode 100644
index 00000000000..5d74b649e11
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/tasks/__init__.py
@@ -0,0 +1,12 @@
+"""
+Invoke tasks to help with pytest development and release process.
+"""
+
+import invoke
+
+from . import vendoring
+
+
+ns = invoke.Collection(
+ vendoring
+)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/tasks/vendoring.py b/tests/wpt/web-platform-tests/tools/third_party/py/tasks/vendoring.py
new file mode 100644
index 00000000000..fbc171bc3e0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/tasks/vendoring.py
@@ -0,0 +1,23 @@
+from __future__ import absolute_import, print_function
+import py
+import invoke
+
+VENDOR_TARGET = py.path.local("py/_vendored_packages")
+GOOD_FILES = 'README.md', '__init__.py'
+
+@invoke.task()
+def remove_libs(ctx):
+ print("removing vendored libs")
+ for path in VENDOR_TARGET.listdir():
+ if path.basename not in GOOD_FILES:
+ print(" ", path)
+ path.remove()
+
+@invoke.task(pre=[remove_libs])
+def update_libs(ctx):
+ print("installing libs")
+ ctx.run("pip install -t {target} apipkg iniconfig".format(target=VENDOR_TARGET))
+ ctx.run("git add {target}".format(target=VENDOR_TARGET))
+ print("Please commit to finish the update after running the tests:")
+ print()
+ print(' git commit -am "Updated vendored libs"')
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/testing/code/test_assertion.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/code/test_assertion.py
new file mode 100644
index 00000000000..e2a7f903998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/code/test_assertion.py
@@ -0,0 +1,305 @@
+import pytest, py
+import re
+
+def exvalue():
+ import sys
+ return sys.exc_info()[1]
+
+def f():
+ return 2
+
+def test_assert():
+ try:
+ assert f() == 3
+ except AssertionError:
+ e = exvalue()
+ s = str(e)
+ assert s.startswith('assert 2 == 3\n')
+
+
+def test_assert_within_finally():
+ excinfo = py.test.raises(ZeroDivisionError, """
+ try:
+ 1/0
+ finally:
+ i = 42
+ """)
+ s = excinfo.exconly()
+ assert re.search("ZeroDivisionError:.*division", s) is not None
+
+
+def test_assert_multiline_1():
+ try:
+ assert (f() ==
+ 3)
+ except AssertionError:
+ e = exvalue()
+ s = str(e)
+ assert s.startswith('assert 2 == 3\n')
+
+def test_assert_multiline_2():
+ try:
+ assert (f() == (4,
+ 3)[-1])
+ except AssertionError:
+ e = exvalue()
+ s = str(e)
+ assert s.startswith('assert 2 ==')
+
+def test_in():
+ try:
+ assert "hi" in [1, 2]
+ except AssertionError:
+ e = exvalue()
+ s = str(e)
+ assert s.startswith("assert 'hi' in")
+
+def test_is():
+ try:
+ assert 1 is 2
+ except AssertionError:
+ e = exvalue()
+ s = str(e)
+ assert s.startswith("assert 1 is 2")
+
+
+def test_attrib():
+ class Foo(object):
+ b = 1
+ i = Foo()
+ try:
+ assert i.b == 2
+ except AssertionError:
+ e = exvalue()
+ s = str(e)
+ assert s.startswith("assert 1 == 2")
+
+def test_attrib_inst():
+ class Foo(object):
+ b = 1
+ try:
+ assert Foo().b == 2
+ except AssertionError:
+ e = exvalue()
+ s = str(e)
+ assert s.startswith("assert 1 == 2")
+
+def test_len():
+ l = list(range(42))
+ try:
+ assert len(l) == 100
+ except AssertionError:
+ e = exvalue()
+ s = str(e)
+ assert s.startswith("assert 42 == 100")
+ assert "where 42 = len([" in s
+
+
+def test_assert_keyword_arg():
+ def f(x=3):
+ return False
+ try:
+ assert f(x=5)
+ except AssertionError:
+ e = exvalue()
+ assert "x=5" in str(e)
+
+# These tests should both fail, but should fail nicely...
+class WeirdRepr:
+ def __repr__(self):
+ return '<WeirdRepr\nsecond line>'
+
+def bug_test_assert_repr():
+ v = WeirdRepr()
+ try:
+ assert v == 1
+ except AssertionError:
+ e = exvalue()
+ assert str(e).find('WeirdRepr') != -1
+ assert str(e).find('second line') != -1
+ assert 0
+
+def test_assert_non_string():
+ try:
+ assert 0, ['list']
+ except AssertionError:
+ e = exvalue()
+ assert str(e).find("list") != -1
+
+def test_assert_implicit_multiline():
+ try:
+ x = [1,2,3]
+ assert x != [1,
+ 2, 3]
+ except AssertionError:
+ e = exvalue()
+ assert str(e).find('assert [1, 2, 3] !=') != -1
+
+@py.test.mark.xfail(py.test.__version__[0] != "2",
+ reason="broken on modern pytest",
+ run=False
+)
+def test_assert_with_brokenrepr_arg():
+ class BrokenRepr:
+ def __repr__(self): 0 / 0
+ e = AssertionError(BrokenRepr())
+ if e.msg.find("broken __repr__") == -1:
+ py.test.fail("broken __repr__ not handle correctly")
+
+def test_multiple_statements_per_line():
+ try:
+ a = 1; assert a == 2
+ except AssertionError:
+ e = exvalue()
+ assert "assert 1 == 2" in str(e)
+
+def test_power():
+ try:
+ assert 2**3 == 7
+ except AssertionError:
+ e = exvalue()
+ assert "assert (2 ** 3) == 7" in str(e)
+
+
+class TestView:
+
+ def setup_class(cls):
+ cls.View = py.test.importorskip("py._code._assertionold").View
+
+ def test_class_dispatch(self):
+ ### Use a custom class hierarchy with existing instances
+
+ class Picklable(self.View):
+ pass
+
+ class Simple(Picklable):
+ __view__ = object
+ def pickle(self):
+ return repr(self.__obj__)
+
+ class Seq(Picklable):
+ __view__ = list, tuple, dict
+ def pickle(self):
+ return ';'.join(
+ [Picklable(item).pickle() for item in self.__obj__])
+
+ class Dict(Seq):
+ __view__ = dict
+ def pickle(self):
+ return Seq.pickle(self) + '!' + Seq(self.values()).pickle()
+
+ assert Picklable(123).pickle() == '123'
+ assert Picklable([1,[2,3],4]).pickle() == '1;2;3;4'
+ assert Picklable({1:2}).pickle() == '1!2'
+
+ def test_viewtype_class_hierarchy(self):
+ # Use a custom class hierarchy based on attributes of existing instances
+ class Operation:
+ "Existing class that I don't want to change."
+ def __init__(self, opname, *args):
+ self.opname = opname
+ self.args = args
+
+ existing = [Operation('+', 4, 5),
+ Operation('getitem', '', 'join'),
+ Operation('setattr', 'x', 'y', 3),
+ Operation('-', 12, 1)]
+
+ class PyOp(self.View):
+ def __viewkey__(self):
+ return self.opname
+ def generate(self):
+ return '%s(%s)' % (self.opname, ', '.join(map(repr, self.args)))
+
+ class PyBinaryOp(PyOp):
+ __view__ = ('+', '-', '*', '/')
+ def generate(self):
+ return '%s %s %s' % (self.args[0], self.opname, self.args[1])
+
+ codelines = [PyOp(op).generate() for op in existing]
+ assert codelines == ["4 + 5", "getitem('', 'join')",
+ "setattr('x', 'y', 3)", "12 - 1"]
+
+def test_underscore_api():
+ py.code._AssertionError
+ py.code._reinterpret_old # used by pypy
+ py.code._reinterpret
+
+def test_assert_customizable_reprcompare(monkeypatch):
+ util = pytest.importorskip("_pytest.assertion.util")
+ monkeypatch.setattr(util, '_reprcompare', lambda *args: 'hello')
+ try:
+ assert 3 == 4
+ except AssertionError:
+ e = exvalue()
+ s = str(e)
+ assert "hello" in s
+
+def test_assert_long_source_1():
+ try:
+ assert len == [
+ (None, ['somet text', 'more text']),
+ ]
+ except AssertionError:
+ e = exvalue()
+ s = str(e)
+ assert 're-run' not in s
+ assert 'somet text' in s
+
+def test_assert_long_source_2():
+ try:
+ assert(len == [
+ (None, ['somet text', 'more text']),
+ ])
+ except AssertionError:
+ e = exvalue()
+ s = str(e)
+ assert 're-run' not in s
+ assert 'somet text' in s
+
+def test_assert_raise_alias(testdir):
+ testdir.makepyfile("""
+ import sys
+ EX = AssertionError
+ def test_hello():
+ raise EX("hello"
+ "multi"
+ "line")
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*def test_hello*",
+ "*raise EX*",
+ "*1 failed*",
+ ])
+
+@py.test.mark.xfail(py.test.__version__[0] != "2",
+ reason="broken on modern pytest",
+ run=False)
+def test_assert_raise_subclass():
+ class SomeEx(AssertionError):
+ def __init__(self, *args):
+ super(SomeEx, self).__init__()
+ try:
+ raise SomeEx("hello")
+ except AssertionError as e:
+ s = str(e)
+ assert 're-run' not in s
+ assert 'could not determine' in s
+
+def test_assert_raises_in_nonzero_of_object_pytest_issue10():
+ class A(object):
+ def __nonzero__(self):
+ raise ValueError(42)
+ def __lt__(self, other):
+ return A()
+ def __repr__(self):
+ return "<MY42 object>"
+ def myany(x):
+ return True
+ try:
+ assert not(myany(A() < 0))
+ except AssertionError:
+ e = exvalue()
+ s = str(e)
+ assert "<MY42 object> < 0" in s
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/code/test_code.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/code/test_code.py
index 28ec628b00d..28ec628b00d 100644
--- a/tests/wpt/web-platform-tests/tools/py/testing/code/test_code.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/code/test_code.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/testing/code/test_excinfo.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/code/test_excinfo.py
new file mode 100644
index 00000000000..c148ab8cfbd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/code/test_excinfo.py
@@ -0,0 +1,956 @@
+# -*- coding: utf-8 -*-
+
+import py
+import pytest
+import sys
+from test_source import astonly
+
+from py._code.code import FormattedExcinfo, ReprExceptionInfo
+queue = py.builtin._tryimport('queue', 'Queue')
+
+failsonjython = py.test.mark.xfail("sys.platform.startswith('java')")
+
+try:
+ import importlib
+except ImportError:
+ invalidate_import_caches = None
+else:
+ invalidate_import_caches = getattr(importlib, "invalidate_caches", None)
+
+
+pytest_version_info = tuple(map(int, pytest.__version__.split(".")[:3]))
+
+broken_on_modern_pytest = pytest.mark.xfail(
+ pytest_version_info[0] != 2,
+ reason="this test hasn't been fixed after moving py.code into pytest",
+ run=False
+ )
+
+
+class TWMock:
+ def __init__(self):
+ self.lines = []
+
+ def sep(self, sep, line=None):
+ self.lines.append((sep, line))
+
+ def line(self, line, **kw):
+ self.lines.append(line)
+
+ def markup(self, text, **kw):
+ return text
+
+ fullwidth = 80
+
+
+def test_excinfo_simple():
+ try:
+ raise ValueError
+ except ValueError:
+ info = py.code.ExceptionInfo()
+ assert info.type == ValueError
+
+
+def test_excinfo_getstatement():
+ def g():
+ raise ValueError
+
+ def f():
+ g()
+ try:
+ f()
+ except ValueError:
+ excinfo = py.code.ExceptionInfo()
+ linenumbers = [
+ py.code.getrawcode(f).co_firstlineno-1+3,
+ py.code.getrawcode(f).co_firstlineno-1+1,
+ py.code.getrawcode(g).co_firstlineno-1+1,
+ ]
+ l = list(excinfo.traceback)
+ foundlinenumbers = [x.lineno for x in l]
+ assert foundlinenumbers == linenumbers
+ #for x in info:
+ # print "%s:%d %s" %(x.path.relto(root), x.lineno, x.statement)
+ #xxx
+
+# testchain for getentries test below
+def f():
+ #
+ raise ValueError
+ #
+def g():
+ #
+ __tracebackhide__ = True
+ f()
+ #
+def h():
+ #
+ g()
+ #
+
+class TestTraceback_f_g_h:
+ def setup_method(self, method):
+ try:
+ h()
+ except ValueError:
+ self.excinfo = py.code.ExceptionInfo()
+
+ def test_traceback_entries(self):
+ tb = self.excinfo.traceback
+ entries = list(tb)
+ assert len(tb) == 4 # maybe fragile test
+ assert len(entries) == 4 # maybe fragile test
+ names = ['f', 'g', 'h']
+ for entry in entries:
+ try:
+ names.remove(entry.frame.code.name)
+ except ValueError:
+ pass
+ assert not names
+
+ def test_traceback_entry_getsource(self):
+ tb = self.excinfo.traceback
+ s = str(tb[-1].getsource())
+ assert s.startswith("def f():")
+ assert s.endswith("raise ValueError")
+
+ @astonly
+ @failsonjython
+ def test_traceback_entry_getsource_in_construct(self):
+ source = py.code.Source("""\
+ def xyz():
+ try:
+ raise ValueError
+ except somenoname:
+ pass
+ xyz()
+ """)
+ try:
+ exec (source.compile())
+ except NameError:
+ tb = py.code.ExceptionInfo().traceback
+ print (tb[-1].getsource())
+ s = str(tb[-1].getsource())
+ assert s.startswith("def xyz():\n try:")
+ assert s.strip().endswith("except somenoname:")
+
+ def test_traceback_cut(self):
+ co = py.code.Code(f)
+ path, firstlineno = co.path, co.firstlineno
+ traceback = self.excinfo.traceback
+ newtraceback = traceback.cut(path=path, firstlineno=firstlineno)
+ assert len(newtraceback) == 1
+ newtraceback = traceback.cut(path=path, lineno=firstlineno+2)
+ assert len(newtraceback) == 1
+
+ def test_traceback_cut_excludepath(self, testdir):
+ p = testdir.makepyfile("def f(): raise ValueError")
+ excinfo = py.test.raises(ValueError, "p.pyimport().f()")
+ basedir = py.path.local(py.test.__file__).dirpath()
+ newtraceback = excinfo.traceback.cut(excludepath=basedir)
+ for x in newtraceback:
+ if hasattr(x, 'path'):
+ assert not py.path.local(x.path).relto(basedir)
+ assert newtraceback[-1].frame.code.path == p
+
+ def test_traceback_filter(self):
+ traceback = self.excinfo.traceback
+ ntraceback = traceback.filter()
+ assert len(ntraceback) == len(traceback) - 1
+
+ def test_traceback_recursion_index(self):
+ def f(n):
+ if n < 10:
+ n += 1
+ f(n)
+ excinfo = py.test.raises(RuntimeError, f, 8)
+ traceback = excinfo.traceback
+ recindex = traceback.recursionindex()
+ assert recindex == 3
+
+ def test_traceback_only_specific_recursion_errors(self, monkeypatch):
+ def f(n):
+ if n == 0:
+ raise RuntimeError("hello")
+ f(n-1)
+
+ excinfo = pytest.raises(RuntimeError, f, 100)
+ monkeypatch.delattr(excinfo.traceback.__class__, "recursionindex")
+ repr = excinfo.getrepr()
+ assert "RuntimeError: hello" in str(repr.reprcrash)
+
+ def test_traceback_no_recursion_index(self):
+ def do_stuff():
+ raise RuntimeError
+
+ def reraise_me():
+ import sys
+ exc, val, tb = sys.exc_info()
+ py.builtin._reraise(exc, val, tb)
+
+ def f(n):
+ try:
+ do_stuff()
+ except:
+ reraise_me()
+ excinfo = py.test.raises(RuntimeError, f, 8)
+ traceback = excinfo.traceback
+ recindex = traceback.recursionindex()
+ assert recindex is None
+
+ def test_traceback_messy_recursion(self):
+ # XXX: simplified locally testable version
+ decorator = py.test.importorskip('decorator').decorator
+
+ def log(f, *k, **kw):
+ print('%s %s' % (k, kw))
+ f(*k, **kw)
+ log = decorator(log)
+
+ def fail():
+ raise ValueError('')
+
+ fail = log(log(fail))
+
+ excinfo = py.test.raises(ValueError, fail)
+ assert excinfo.traceback.recursionindex() is None
+
+ def test_traceback_getcrashentry(self):
+ def i():
+ __tracebackhide__ = True
+ raise ValueError
+
+ def h():
+ i()
+
+ def g():
+ __tracebackhide__ = True
+ h()
+
+ def f():
+ g()
+
+ excinfo = py.test.raises(ValueError, f)
+ tb = excinfo.traceback
+ entry = tb.getcrashentry()
+ co = py.code.Code(h)
+ assert entry.frame.code.path == co.path
+ assert entry.lineno == co.firstlineno + 1
+ assert entry.frame.code.name == 'h'
+
+ def test_traceback_getcrashentry_empty(self):
+ def g():
+ __tracebackhide__ = True
+ raise ValueError
+
+ def f():
+ __tracebackhide__ = True
+ g()
+
+ excinfo = py.test.raises(ValueError, f)
+ tb = excinfo.traceback
+ entry = tb.getcrashentry()
+ co = py.code.Code(g)
+ assert entry.frame.code.path == co.path
+ assert entry.lineno == co.firstlineno + 2
+ assert entry.frame.code.name == 'g'
+
+
+def hello(x):
+ x + 5
+
+
+def test_tbentry_reinterpret():
+ try:
+ hello("hello")
+ except TypeError:
+ excinfo = py.code.ExceptionInfo()
+ tbentry = excinfo.traceback[-1]
+ msg = tbentry.reinterpret()
+ assert msg.startswith("TypeError: ('hello' + 5)")
+
+
+def test_excinfo_exconly():
+ excinfo = py.test.raises(ValueError, h)
+ assert excinfo.exconly().startswith('ValueError')
+ excinfo = py.test.raises(ValueError,
+ "raise ValueError('hello\\nworld')")
+ msg = excinfo.exconly(tryshort=True)
+ assert msg.startswith('ValueError')
+ assert msg.endswith("world")
+
+
+def test_excinfo_repr():
+ excinfo = py.test.raises(ValueError, h)
+ s = repr(excinfo)
+ assert s == "<ExceptionInfo ValueError tblen=4>"
+
+
+def test_excinfo_str():
+ excinfo = py.test.raises(ValueError, h)
+ s = str(excinfo)
+ assert s.startswith(__file__[:-9]) # pyc file and $py.class
+ assert s.endswith("ValueError")
+ assert len(s.split(":")) >= 3 # on windows it's 4
+
+
+def test_excinfo_errisinstance():
+ excinfo = py.test.raises(ValueError, h)
+ assert excinfo.errisinstance(ValueError)
+
+
+def test_excinfo_no_sourcecode():
+ try:
+ exec ("raise ValueError()")
+ except ValueError:
+ excinfo = py.code.ExceptionInfo()
+ s = str(excinfo.traceback[-1])
+ assert s == " File '<string>':1 in <module>\n ???\n"
+
+
+def test_excinfo_no_python_sourcecode(tmpdir):
+ #XXX: simplified locally testable version
+ tmpdir.join('test.txt').write("{{ h()}}:")
+
+ jinja2 = py.test.importorskip('jinja2')
+ loader = jinja2.FileSystemLoader(str(tmpdir))
+ env = jinja2.Environment(loader=loader)
+ template = env.get_template('test.txt')
+ excinfo = py.test.raises(ValueError,
+ template.render, h=h)
+ for item in excinfo.traceback:
+ print(item) # XXX: for some reason jinja.Template.render is printed in full
+ item.source # shouldnt fail
+ if item.path.basename == 'test.txt':
+ assert str(item.source) == '{{ h()}}:'
+
+
+def test_entrysource_Queue_example():
+ try:
+ queue.Queue().get(timeout=0.001)
+ except queue.Empty:
+ excinfo = py.code.ExceptionInfo()
+ entry = excinfo.traceback[-1]
+ source = entry.getsource()
+ assert source is not None
+ s = str(source).strip()
+ assert s.startswith("def get")
+
+
+def test_codepath_Queue_example():
+ try:
+ queue.Queue().get(timeout=0.001)
+ except queue.Empty:
+ excinfo = py.code.ExceptionInfo()
+ entry = excinfo.traceback[-1]
+ path = entry.path
+ assert isinstance(path, py.path.local)
+ assert path.basename.lower() == "queue.py"
+ assert path.check()
+
+
+class TestFormattedExcinfo:
+ def pytest_funcarg__importasmod(self, request):
+ def importasmod(source):
+ source = py.code.Source(source)
+ tmpdir = request.getfuncargvalue("tmpdir")
+ modpath = tmpdir.join("mod.py")
+ tmpdir.ensure("__init__.py")
+ modpath.write(source)
+ if invalidate_import_caches is not None:
+ invalidate_import_caches()
+ return modpath.pyimport()
+ return importasmod
+
+ def excinfo_from_exec(self, source):
+ source = py.code.Source(source).strip()
+ try:
+ exec (source.compile())
+ except KeyboardInterrupt:
+ raise
+ except:
+ return py.code.ExceptionInfo()
+ assert 0, "did not raise"
+
+ def test_repr_source(self):
+ pr = FormattedExcinfo()
+ source = py.code.Source("""
+ def f(x):
+ pass
+ """).strip()
+ pr.flow_marker = "|"
+ lines = pr.get_source(source, 0)
+ assert len(lines) == 2
+ assert lines[0] == "| def f(x):"
+ assert lines[1] == " pass"
+
+ @broken_on_modern_pytest
+ def test_repr_source_excinfo(self):
+ """ check if indentation is right """
+ pr = FormattedExcinfo()
+ excinfo = self.excinfo_from_exec("""
+ def f():
+ assert 0
+ f()
+ """)
+ pr = FormattedExcinfo()
+ source = pr._getentrysource(excinfo.traceback[-1])
+ lines = pr.get_source(source, 1, excinfo)
+ assert lines == [
+ ' def f():',
+ '> assert 0',
+ 'E assert 0'
+ ]
+
+ def test_repr_source_not_existing(self):
+ pr = FormattedExcinfo()
+ co = compile("raise ValueError()", "", "exec")
+ try:
+ exec (co)
+ except ValueError:
+ excinfo = py.code.ExceptionInfo()
+ repr = pr.repr_excinfo(excinfo)
+ assert repr.reprtraceback.reprentries[1].lines[0] == "> ???"
+
+ def test_repr_many_line_source_not_existing(self):
+ pr = FormattedExcinfo()
+ co = compile("""
+a = 1
+raise ValueError()
+""", "", "exec")
+ try:
+ exec (co)
+ except ValueError:
+ excinfo = py.code.ExceptionInfo()
+ repr = pr.repr_excinfo(excinfo)
+ assert repr.reprtraceback.reprentries[1].lines[0] == "> ???"
+
+ def test_repr_source_failing_fullsource(self):
+ pr = FormattedExcinfo()
+
+ class FakeCode(object):
+ class raw:
+ co_filename = '?'
+ path = '?'
+ firstlineno = 5
+
+ def fullsource(self):
+ return None
+ fullsource = property(fullsource)
+
+ class FakeFrame(object):
+ code = FakeCode()
+ f_locals = {}
+ f_globals = {}
+
+ class FakeTracebackEntry(py.code.Traceback.Entry):
+ def __init__(self, tb):
+ self.lineno = 5+3
+
+ @property
+ def frame(self):
+ return FakeFrame()
+
+ class Traceback(py.code.Traceback):
+ Entry = FakeTracebackEntry
+
+ class FakeExcinfo(py.code.ExceptionInfo):
+ typename = "Foo"
+ def __init__(self):
+ pass
+
+ def exconly(self, tryshort):
+ return "EXC"
+ def errisinstance(self, cls):
+ return False
+
+ excinfo = FakeExcinfo()
+ class FakeRawTB(object):
+ tb_next = None
+ tb = FakeRawTB()
+ excinfo.traceback = Traceback(tb)
+
+ fail = IOError()
+ repr = pr.repr_excinfo(excinfo)
+ assert repr.reprtraceback.reprentries[0].lines[0] == "> ???"
+
+ fail = py.error.ENOENT
+ repr = pr.repr_excinfo(excinfo)
+ assert repr.reprtraceback.reprentries[0].lines[0] == "> ???"
+
+
+ def test_repr_local(self):
+ p = FormattedExcinfo(showlocals=True)
+ loc = {'y': 5, 'z': 7, 'x': 3, '@x': 2, '__builtins__': {}}
+ reprlocals = p.repr_locals(loc)
+ assert reprlocals.lines
+ assert reprlocals.lines[0] == '__builtins__ = <builtins>'
+ assert reprlocals.lines[1] == 'x = 3'
+ assert reprlocals.lines[2] == 'y = 5'
+ assert reprlocals.lines[3] == 'z = 7'
+
+ def test_repr_tracebackentry_lines(self, importasmod):
+ mod = importasmod("""
+ def func1():
+ raise ValueError("hello\\nworld")
+ """)
+ excinfo = py.test.raises(ValueError, mod.func1)
+ excinfo.traceback = excinfo.traceback.filter()
+ p = FormattedExcinfo()
+ reprtb = p.repr_traceback_entry(excinfo.traceback[-1])
+
+ # test as intermittent entry
+ lines = reprtb.lines
+ assert lines[0] == ' def func1():'
+ assert lines[1] == '> raise ValueError("hello\\nworld")'
+
+ # test as last entry
+ p = FormattedExcinfo(showlocals=True)
+ repr_entry = p.repr_traceback_entry(excinfo.traceback[-1], excinfo)
+ lines = repr_entry.lines
+ assert lines[0] == ' def func1():'
+ assert lines[1] == '> raise ValueError("hello\\nworld")'
+ assert lines[2] == 'E ValueError: hello'
+ assert lines[3] == 'E world'
+ assert not lines[4:]
+
+ loc = repr_entry.reprlocals is not None
+ loc = repr_entry.reprfileloc
+ assert loc.path == mod.__file__
+ assert loc.lineno == 3
+ #assert loc.message == "ValueError: hello"
+
+ def test_repr_tracebackentry_lines(self, importasmod):
+ mod = importasmod("""
+ def func1(m, x, y, z):
+ raise ValueError("hello\\nworld")
+ """)
+ excinfo = py.test.raises(ValueError, mod.func1, "m"*90, 5, 13, "z"*120)
+ excinfo.traceback = excinfo.traceback.filter()
+ entry = excinfo.traceback[-1]
+ p = FormattedExcinfo(funcargs=True)
+ reprfuncargs = p.repr_args(entry)
+ assert reprfuncargs.args[0] == ('m', repr("m"*90))
+ assert reprfuncargs.args[1] == ('x', '5')
+ assert reprfuncargs.args[2] == ('y', '13')
+ assert reprfuncargs.args[3] == ('z', repr("z" * 120))
+
+ p = FormattedExcinfo(funcargs=True)
+ repr_entry = p.repr_traceback_entry(entry)
+ assert repr_entry.reprfuncargs.args == reprfuncargs.args
+ tw = TWMock()
+ repr_entry.toterminal(tw)
+ assert tw.lines[0] == "m = " + repr('m' * 90)
+ assert tw.lines[1] == "x = 5, y = 13"
+ assert tw.lines[2] == "z = " + repr('z' * 120)
+
+ def test_repr_tracebackentry_lines_var_kw_args(self, importasmod):
+ mod = importasmod("""
+ def func1(x, *y, **z):
+ raise ValueError("hello\\nworld")
+ """)
+ excinfo = py.test.raises(ValueError, mod.func1, 'a', 'b', c='d')
+ excinfo.traceback = excinfo.traceback.filter()
+ entry = excinfo.traceback[-1]
+ p = FormattedExcinfo(funcargs=True)
+ reprfuncargs = p.repr_args(entry)
+ assert reprfuncargs.args[0] == ('x', repr('a'))
+ assert reprfuncargs.args[1] == ('y', repr(('b',)))
+ assert reprfuncargs.args[2] == ('z', repr({'c': 'd'}))
+
+ p = FormattedExcinfo(funcargs=True)
+ repr_entry = p.repr_traceback_entry(entry)
+ assert repr_entry.reprfuncargs.args == reprfuncargs.args
+ tw = TWMock()
+ repr_entry.toterminal(tw)
+ assert tw.lines[0] == "x = 'a', y = ('b',), z = {'c': 'd'}"
+
+ def test_repr_tracebackentry_short(self, importasmod):
+ mod = importasmod("""
+ def func1():
+ raise ValueError("hello")
+ def entry():
+ func1()
+ """)
+ excinfo = py.test.raises(ValueError, mod.entry)
+ p = FormattedExcinfo(style="short")
+ reprtb = p.repr_traceback_entry(excinfo.traceback[-2])
+ lines = reprtb.lines
+ basename = py.path.local(mod.__file__).basename
+ assert lines[0] == ' func1()'
+ assert basename in str(reprtb.reprfileloc.path)
+ assert reprtb.reprfileloc.lineno == 5
+
+ # test last entry
+ p = FormattedExcinfo(style="short")
+ reprtb = p.repr_traceback_entry(excinfo.traceback[-1], excinfo)
+ lines = reprtb.lines
+ assert lines[0] == ' raise ValueError("hello")'
+ assert lines[1] == 'E ValueError: hello'
+ assert basename in str(reprtb.reprfileloc.path)
+ assert reprtb.reprfileloc.lineno == 3
+
+ def test_repr_tracebackentry_no(self, importasmod):
+ mod = importasmod("""
+ def func1():
+ raise ValueError("hello")
+ def entry():
+ func1()
+ """)
+ excinfo = py.test.raises(ValueError, mod.entry)
+ p = FormattedExcinfo(style="no")
+ p.repr_traceback_entry(excinfo.traceback[-2])
+
+ p = FormattedExcinfo(style="no")
+ reprentry = p.repr_traceback_entry(excinfo.traceback[-1], excinfo)
+ lines = reprentry.lines
+ assert lines[0] == 'E ValueError: hello'
+ assert not lines[1:]
+
+ def test_repr_traceback_tbfilter(self, importasmod):
+ mod = importasmod("""
+ def f(x):
+ raise ValueError(x)
+ def entry():
+ f(0)
+ """)
+ excinfo = py.test.raises(ValueError, mod.entry)
+ p = FormattedExcinfo(tbfilter=True)
+ reprtb = p.repr_traceback(excinfo)
+ assert len(reprtb.reprentries) == 2
+ p = FormattedExcinfo(tbfilter=False)
+ reprtb = p.repr_traceback(excinfo)
+ assert len(reprtb.reprentries) == 3
+
+ def test_traceback_short_no_source(self, importasmod, monkeypatch):
+ mod = importasmod("""
+ def func1():
+ raise ValueError("hello")
+ def entry():
+ func1()
+ """)
+ try:
+ mod.entry()
+ except ValueError:
+ excinfo = py.code.ExceptionInfo()
+ from py._code.code import Code
+ monkeypatch.setattr(Code, 'path', 'bogus')
+ excinfo.traceback[0].frame.code.path = "bogus"
+ p = FormattedExcinfo(style="short")
+ reprtb = p.repr_traceback_entry(excinfo.traceback[-2])
+ lines = reprtb.lines
+ last_p = FormattedExcinfo(style="short")
+ last_reprtb = last_p.repr_traceback_entry(excinfo.traceback[-1], excinfo)
+ last_lines = last_reprtb.lines
+ monkeypatch.undo()
+ basename = py.path.local(mod.__file__).basename
+ assert lines[0] == ' func1()'
+
+ assert last_lines[0] == ' raise ValueError("hello")'
+ assert last_lines[1] == 'E ValueError: hello'
+
+ def test_repr_traceback_and_excinfo(self, importasmod):
+ mod = importasmod("""
+ def f(x):
+ raise ValueError(x)
+ def entry():
+ f(0)
+ """)
+ excinfo = py.test.raises(ValueError, mod.entry)
+
+ for style in ("long", "short"):
+ p = FormattedExcinfo(style=style)
+ reprtb = p.repr_traceback(excinfo)
+ assert len(reprtb.reprentries) == 2
+ assert reprtb.style == style
+ assert not reprtb.extraline
+ repr = p.repr_excinfo(excinfo)
+ assert repr.reprtraceback
+ assert len(repr.reprtraceback.reprentries) == len(reprtb.reprentries)
+ assert repr.reprcrash.path.endswith("mod.py")
+ assert repr.reprcrash.message == "ValueError: 0"
+
+ def test_repr_traceback_with_invalid_cwd(self, importasmod, monkeypatch):
+ mod = importasmod("""
+ def f(x):
+ raise ValueError(x)
+ def entry():
+ f(0)
+ """)
+ excinfo = py.test.raises(ValueError, mod.entry)
+
+ p = FormattedExcinfo()
+ def raiseos():
+ raise OSError(2)
+ monkeypatch.setattr('os.getcwd', raiseos)
+ assert p._makepath(__file__) == __file__
+ reprtb = p.repr_traceback(excinfo)
+
+ @broken_on_modern_pytest
+ def test_repr_excinfo_addouterr(self, importasmod):
+ mod = importasmod("""
+ def entry():
+ raise ValueError()
+ """)
+ excinfo = py.test.raises(ValueError, mod.entry)
+ repr = excinfo.getrepr()
+ repr.addsection("title", "content")
+ twmock = TWMock()
+ repr.toterminal(twmock)
+ assert twmock.lines[-1] == "content"
+ assert twmock.lines[-2] == ("-", "title")
+
+ def test_repr_excinfo_reprcrash(self, importasmod):
+ mod = importasmod("""
+ def entry():
+ raise ValueError()
+ """)
+ excinfo = py.test.raises(ValueError, mod.entry)
+ repr = excinfo.getrepr()
+ assert repr.reprcrash.path.endswith("mod.py")
+ assert repr.reprcrash.lineno == 3
+ assert repr.reprcrash.message == "ValueError"
+ assert str(repr.reprcrash).endswith("mod.py:3: ValueError")
+
+ def test_repr_traceback_recursion(self, importasmod):
+ mod = importasmod("""
+ def rec2(x):
+ return rec1(x+1)
+ def rec1(x):
+ return rec2(x-1)
+ def entry():
+ rec1(42)
+ """)
+ excinfo = py.test.raises(RuntimeError, mod.entry)
+
+ for style in ("short", "long", "no"):
+ p = FormattedExcinfo(style="short")
+ reprtb = p.repr_traceback(excinfo)
+ assert reprtb.extraline == "!!! Recursion detected (same locals & position)"
+ assert str(reprtb)
+
+ @broken_on_modern_pytest
+ def test_tb_entry_AssertionError(self, importasmod):
+ # probably this test is a bit redundant
+ # as py/magic/testing/test_assertion.py
+ # already tests correctness of
+ # assertion-reinterpretation logic
+ mod = importasmod("""
+ def somefunc():
+ x = 1
+ assert x == 2
+ """)
+ excinfo = py.test.raises(AssertionError, mod.somefunc)
+
+ p = FormattedExcinfo()
+ reprentry = p.repr_traceback_entry(excinfo.traceback[-1], excinfo)
+ lines = reprentry.lines
+ assert lines[-1] == "E assert 1 == 2"
+
+ def test_reprexcinfo_getrepr(self, importasmod):
+ mod = importasmod("""
+ def f(x):
+ raise ValueError(x)
+ def entry():
+ f(0)
+ """)
+ try:
+ mod.entry()
+ except ValueError:
+ excinfo = py.code.ExceptionInfo()
+
+ for style in ("short", "long", "no"):
+ for showlocals in (True, False):
+ repr = excinfo.getrepr(style=style, showlocals=showlocals)
+ assert isinstance(repr, ReprExceptionInfo)
+ assert repr.reprtraceback.style == style
+
+ def test_reprexcinfo_unicode(self):
+ from py._code.code import TerminalRepr
+ class MyRepr(TerminalRepr):
+ def toterminal(self, tw):
+ tw.line(py.builtin._totext("я", "utf-8"))
+ x = py.builtin._totext(MyRepr())
+ assert x == py.builtin._totext("я", "utf-8")
+
+ @broken_on_modern_pytest
+ def test_toterminal_long(self, importasmod):
+ mod = importasmod("""
+ def g(x):
+ raise ValueError(x)
+ def f():
+ g(3)
+ """)
+ excinfo = py.test.raises(ValueError, mod.f)
+ excinfo.traceback = excinfo.traceback.filter()
+ repr = excinfo.getrepr()
+ tw = TWMock()
+ repr.toterminal(tw)
+ assert tw.lines[0] == ""
+ tw.lines.pop(0)
+ assert tw.lines[0] == " def f():"
+ assert tw.lines[1] == "> g(3)"
+ assert tw.lines[2] == ""
+ assert tw.lines[3].endswith("mod.py:5: ")
+ assert tw.lines[4] == ("_ ", None)
+ assert tw.lines[5] == ""
+ assert tw.lines[6] == " def g(x):"
+ assert tw.lines[7] == "> raise ValueError(x)"
+ assert tw.lines[8] == "E ValueError: 3"
+ assert tw.lines[9] == ""
+ assert tw.lines[10].endswith("mod.py:3: ValueError")
+
+ @broken_on_modern_pytest
+ def test_toterminal_long_missing_source(self, importasmod, tmpdir):
+ mod = importasmod("""
+ def g(x):
+ raise ValueError(x)
+ def f():
+ g(3)
+ """)
+ excinfo = py.test.raises(ValueError, mod.f)
+ tmpdir.join('mod.py').remove()
+ excinfo.traceback = excinfo.traceback.filter()
+ repr = excinfo.getrepr()
+ tw = TWMock()
+ repr.toterminal(tw)
+ assert tw.lines[0] == ""
+ tw.lines.pop(0)
+ assert tw.lines[0] == "> ???"
+ assert tw.lines[1] == ""
+ assert tw.lines[2].endswith("mod.py:5: ")
+ assert tw.lines[3] == ("_ ", None)
+ assert tw.lines[4] == ""
+ assert tw.lines[5] == "> ???"
+ assert tw.lines[6] == "E ValueError: 3"
+ assert tw.lines[7] == ""
+ assert tw.lines[8].endswith("mod.py:3: ValueError")
+
+ @broken_on_modern_pytest
+ def test_toterminal_long_incomplete_source(self, importasmod, tmpdir):
+ mod = importasmod("""
+ def g(x):
+ raise ValueError(x)
+ def f():
+ g(3)
+ """)
+ excinfo = py.test.raises(ValueError, mod.f)
+ tmpdir.join('mod.py').write('asdf')
+ excinfo.traceback = excinfo.traceback.filter()
+ repr = excinfo.getrepr()
+ tw = TWMock()
+ repr.toterminal(tw)
+ assert tw.lines[0] == ""
+ tw.lines.pop(0)
+ assert tw.lines[0] == "> ???"
+ assert tw.lines[1] == ""
+ assert tw.lines[2].endswith("mod.py:5: ")
+ assert tw.lines[3] == ("_ ", None)
+ assert tw.lines[4] == ""
+ assert tw.lines[5] == "> ???"
+ assert tw.lines[6] == "E ValueError: 3"
+ assert tw.lines[7] == ""
+ assert tw.lines[8].endswith("mod.py:3: ValueError")
+
+ @broken_on_modern_pytest
+ def test_toterminal_long_filenames(self, importasmod):
+ mod = importasmod("""
+ def f():
+ raise ValueError()
+ """)
+ excinfo = py.test.raises(ValueError, mod.f)
+ tw = TWMock()
+ path = py.path.local(mod.__file__)
+ old = path.dirpath().chdir()
+ try:
+ repr = excinfo.getrepr(abspath=False)
+ repr.toterminal(tw)
+ line = tw.lines[-1]
+ x = py.path.local().bestrelpath(path)
+ if len(x) < len(str(path)):
+ assert line == "mod.py:3: ValueError"
+
+ repr = excinfo.getrepr(abspath=True)
+ repr.toterminal(tw)
+ line = tw.lines[-1]
+ assert line == "%s:3: ValueError" %(path,)
+ finally:
+ old.chdir()
+
+ @pytest.mark.parametrize('style', ("long", "short", "no"))
+ @pytest.mark.parametrize('showlocals', (True, False),
+ ids=['locals', 'nolocals'])
+ @pytest.mark.parametrize('tbfilter', (True, False),
+ ids=['tbfilter', 'nofilter'])
+ @pytest.mark.parametrize('funcargs', (True, False),
+ ids=['funcargs', 'nofuncargs'])
+ def test_format_excinfo(self, importasmod,
+ style, showlocals, tbfilter, funcargs):
+
+ mod = importasmod("""
+ def g(x):
+ raise ValueError(x)
+ def f():
+ g(3)
+ """)
+ excinfo = py.test.raises(ValueError, mod.f)
+ tw = py.io.TerminalWriter(stringio=True)
+ repr = excinfo.getrepr(
+ style=style,
+ showlocals=showlocals,
+ funcargs=funcargs,
+ tbfilter=tbfilter
+ )
+ repr.toterminal(tw)
+ assert tw.stringio.getvalue()
+
+ @broken_on_modern_pytest
+ def test_native_style(self):
+ excinfo = self.excinfo_from_exec("""
+ assert 0
+ """)
+ repr = excinfo.getrepr(style='native')
+ assert "assert 0" in str(repr.reprcrash)
+ s = str(repr)
+ assert s.startswith('Traceback (most recent call last):\n File')
+ assert s.endswith('\nAssertionError: assert 0')
+ assert 'exec (source.compile())' in s
+ assert s.count('assert 0') == 2
+
+ @broken_on_modern_pytest
+ def test_traceback_repr_style(self, importasmod):
+ mod = importasmod("""
+ def f():
+ g()
+ def g():
+ h()
+ def h():
+ i()
+ def i():
+ raise ValueError()
+ """)
+ excinfo = py.test.raises(ValueError, mod.f)
+ excinfo.traceback = excinfo.traceback.filter()
+ excinfo.traceback[1].set_repr_style("short")
+ excinfo.traceback[2].set_repr_style("short")
+ r = excinfo.getrepr(style="long")
+ tw = TWMock()
+ r.toterminal(tw)
+ for line in tw.lines: print (line)
+ assert tw.lines[0] == ""
+ assert tw.lines[1] == " def f():"
+ assert tw.lines[2] == "> g()"
+ assert tw.lines[3] == ""
+ assert tw.lines[4].endswith("mod.py:3: ")
+ assert tw.lines[5] == ("_ ", None)
+ assert tw.lines[6].endswith("in g")
+ assert tw.lines[7] == " h()"
+ assert tw.lines[8].endswith("in h")
+ assert tw.lines[9] == " i()"
+ assert tw.lines[10] == ("_ ", None)
+ assert tw.lines[11] == ""
+ assert tw.lines[12] == " def i():"
+ assert tw.lines[13] == "> raise ValueError()"
+ assert tw.lines[14] == "E ValueError"
+ assert tw.lines[15] == ""
+ assert tw.lines[16].endswith("mod.py:9: ValueError")
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/testing/code/test_source.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/code/test_source.py
new file mode 100644
index 00000000000..3492761a4e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/code/test_source.py
@@ -0,0 +1,648 @@
+from py.code import Source
+import py
+import sys
+import inspect
+
+from py._code.source import _ast
+if _ast is not None:
+ astonly = py.test.mark.nothing
+else:
+ astonly = py.test.mark.xfail("True", reason="only works with AST-compile")
+
+failsonjython = py.test.mark.xfail("sys.platform.startswith('java')")
+
+def test_source_str_function():
+ x = Source("3")
+ assert str(x) == "3"
+
+ x = Source(" 3")
+ assert str(x) == "3"
+
+ x = Source("""
+ 3
+ """, rstrip=False)
+ assert str(x) == "\n3\n "
+
+ x = Source("""
+ 3
+ """, rstrip=True)
+ assert str(x) == "\n3"
+
+def test_unicode():
+ try:
+ unicode
+ except NameError:
+ return
+ x = Source(unicode("4"))
+ assert str(x) == "4"
+ co = py.code.compile(unicode('u"\xc3\xa5"', 'utf8'), mode='eval')
+ val = eval(co)
+ assert isinstance(val, unicode)
+
+def test_source_from_function():
+ source = py.code.Source(test_source_str_function)
+ assert str(source).startswith('def test_source_str_function():')
+
+def test_source_from_method():
+ class TestClass:
+ def test_method(self):
+ pass
+ source = py.code.Source(TestClass().test_method)
+ assert source.lines == ["def test_method(self):",
+ " pass"]
+
+def test_source_from_lines():
+ lines = ["a \n", "b\n", "c"]
+ source = py.code.Source(lines)
+ assert source.lines == ['a ', 'b', 'c']
+
+def test_source_from_inner_function():
+ def f():
+ pass
+ source = py.code.Source(f, deindent=False)
+ assert str(source).startswith(' def f():')
+ source = py.code.Source(f)
+ assert str(source).startswith('def f():')
+
+def test_source_putaround_simple():
+ source = Source("raise ValueError")
+ source = source.putaround(
+ "try:", """\
+ except ValueError:
+ x = 42
+ else:
+ x = 23""")
+ assert str(source)=="""\
+try:
+ raise ValueError
+except ValueError:
+ x = 42
+else:
+ x = 23"""
+
+def test_source_putaround():
+ source = Source()
+ source = source.putaround("""
+ if 1:
+ x=1
+ """)
+ assert str(source).strip() == "if 1:\n x=1"
+
+def test_source_strips():
+ source = Source("")
+ assert source == Source()
+ assert str(source) == ''
+ assert source.strip() == source
+
+def test_source_strip_multiline():
+ source = Source()
+ source.lines = ["", " hello", " "]
+ source2 = source.strip()
+ assert source2.lines == [" hello"]
+
+def test_syntaxerror_rerepresentation():
+ ex = py.test.raises(SyntaxError, py.code.compile, 'xyz xyz')
+ assert ex.value.lineno == 1
+ assert ex.value.offset in (4,7) # XXX pypy/jython versus cpython?
+ assert ex.value.text.strip(), 'x x'
+
+def test_isparseable():
+ assert Source("hello").isparseable()
+ assert Source("if 1:\n pass").isparseable()
+ assert Source(" \nif 1:\n pass").isparseable()
+ assert not Source("if 1:\n").isparseable()
+ assert not Source(" \nif 1:\npass").isparseable()
+ assert not Source(chr(0)).isparseable()
+
+class TestAccesses:
+ source = Source("""\
+ def f(x):
+ pass
+ def g(x):
+ pass
+ """)
+ def test_getrange(self):
+ x = self.source[0:2]
+ assert x.isparseable()
+ assert len(x.lines) == 2
+ assert str(x) == "def f(x):\n pass"
+
+ def test_getline(self):
+ x = self.source[0]
+ assert x == "def f(x):"
+
+ def test_len(self):
+ assert len(self.source) == 4
+
+ def test_iter(self):
+ l = [x for x in self.source]
+ assert len(l) == 4
+
+class TestSourceParsingAndCompiling:
+ source = Source("""\
+ def f(x):
+ assert (x ==
+ 3 +
+ 4)
+ """).strip()
+
+ def test_compile(self):
+ co = py.code.compile("x=3")
+ d = {}
+ exec (co, d)
+ assert d['x'] == 3
+
+ def test_compile_and_getsource_simple(self):
+ co = py.code.compile("x=3")
+ exec (co)
+ source = py.code.Source(co)
+ assert str(source) == "x=3"
+
+ def test_compile_and_getsource_through_same_function(self):
+ def gensource(source):
+ return py.code.compile(source)
+ co1 = gensource("""
+ def f():
+ raise KeyError()
+ """)
+ co2 = gensource("""
+ def f():
+ raise ValueError()
+ """)
+ source1 = inspect.getsource(co1)
+ assert 'KeyError' in source1
+ source2 = inspect.getsource(co2)
+ assert 'ValueError' in source2
+
+ def test_getstatement(self):
+ #print str(self.source)
+ ass = str(self.source[1:])
+ for i in range(1, 4):
+ #print "trying start in line %r" % self.source[i]
+ s = self.source.getstatement(i)
+ #x = s.deindent()
+ assert str(s) == ass
+
+ def test_getstatementrange_triple_quoted(self):
+ #print str(self.source)
+ source = Source("""hello('''
+ ''')""")
+ s = source.getstatement(0)
+ assert s == str(source)
+ s = source.getstatement(1)
+ assert s == str(source)
+
+ @astonly
+ def test_getstatementrange_within_constructs(self):
+ source = Source("""\
+ try:
+ try:
+ raise ValueError
+ except SomeThing:
+ pass
+ finally:
+ 42
+ """)
+ assert len(source) == 7
+ # check all lineno's that could occur in a traceback
+ #assert source.getstatementrange(0) == (0, 7)
+ #assert source.getstatementrange(1) == (1, 5)
+ assert source.getstatementrange(2) == (2, 3)
+ assert source.getstatementrange(3) == (3, 4)
+ assert source.getstatementrange(4) == (4, 5)
+ #assert source.getstatementrange(5) == (0, 7)
+ assert source.getstatementrange(6) == (6, 7)
+
+ def test_getstatementrange_bug(self):
+ source = Source("""\
+ try:
+ x = (
+ y +
+ z)
+ except:
+ pass
+ """)
+ assert len(source) == 6
+ assert source.getstatementrange(2) == (1, 4)
+
+ def test_getstatementrange_bug2(self):
+ source = Source("""\
+ assert (
+ 33
+ ==
+ [
+ X(3,
+ b=1, c=2
+ ),
+ ]
+ )
+ """)
+ assert len(source) == 9
+ assert source.getstatementrange(5) == (0, 9)
+
+ def test_getstatementrange_ast_issue58(self):
+ source = Source("""\
+
+ def test_some():
+ for a in [a for a in
+ CAUSE_ERROR]: pass
+
+ x = 3
+ """)
+ assert getstatement(2, source).lines == source.lines[2:3]
+ assert getstatement(3, source).lines == source.lines[3:4]
+
+ def test_getstatementrange_out_of_bounds_py3(self):
+ source = Source("if xxx:\n from .collections import something")
+ r = source.getstatementrange(1)
+ assert r == (1,2)
+
+ def test_getstatementrange_with_syntaxerror_issue7(self):
+ source = Source(":")
+ py.test.raises(SyntaxError, lambda: source.getstatementrange(0))
+
+ def test_compile_to_ast(self):
+ import ast
+ source = Source("x = 4")
+ mod = source.compile(flag=ast.PyCF_ONLY_AST)
+ assert isinstance(mod, ast.Module)
+ compile(mod, "<filename>", "exec")
+
+ def test_compile_and_getsource(self):
+ co = self.source.compile()
+ py.builtin.exec_(co, globals())
+ f(7)
+ excinfo = py.test.raises(AssertionError, "f(6)")
+ frame = excinfo.traceback[-1].frame
+ stmt = frame.code.fullsource.getstatement(frame.lineno)
+ #print "block", str(block)
+ assert str(stmt).strip().startswith('assert')
+
+ def test_compilefuncs_and_path_sanity(self):
+ def check(comp, name):
+ co = comp(self.source, name)
+ if not name:
+ expected = "codegen %s:%d>" %(mypath, mylineno+2+1)
+ else:
+ expected = "codegen %r %s:%d>" % (name, mypath, mylineno+2+1)
+ fn = co.co_filename
+ assert fn.endswith(expected)
+
+ mycode = py.code.Code(self.test_compilefuncs_and_path_sanity)
+ mylineno = mycode.firstlineno
+ mypath = mycode.path
+
+ for comp in py.code.compile, py.code.Source.compile:
+ for name in '', None, 'my':
+ yield check, comp, name
+
+ def test_offsetless_synerr(self):
+ py.test.raises(SyntaxError, py.code.compile, "lambda a,a: 0", mode='eval')
+
+def test_getstartingblock_singleline():
+ class A:
+ def __init__(self, *args):
+ frame = sys._getframe(1)
+ self.source = py.code.Frame(frame).statement
+
+ x = A('x', 'y')
+
+ l = [i for i in x.source.lines if i.strip()]
+ assert len(l) == 1
+
+def test_getstartingblock_multiline():
+ class A:
+ def __init__(self, *args):
+ frame = sys._getframe(1)
+ self.source = py.code.Frame(frame).statement
+
+ x = A('x',
+ 'y' \
+ ,
+ 'z')
+
+ l = [i for i in x.source.lines if i.strip()]
+ assert len(l) == 4
+
+def test_getline_finally():
+ def c(): pass
+ excinfo = py.test.raises(TypeError, """
+ teardown = None
+ try:
+ c(1)
+ finally:
+ if teardown:
+ teardown()
+ """)
+ source = excinfo.traceback[-1].statement
+ assert str(source).strip() == 'c(1)'
+
+def test_getfuncsource_dynamic():
+ source = """
+ def f():
+ raise ValueError
+
+ def g(): pass
+ """
+ co = py.code.compile(source)
+ py.builtin.exec_(co, globals())
+ assert str(py.code.Source(f)).strip() == 'def f():\n raise ValueError'
+ assert str(py.code.Source(g)).strip() == 'def g(): pass'
+
+
+def test_getfuncsource_with_multine_string():
+ def f():
+ c = '''while True:
+ pass
+'''
+ assert str(py.code.Source(f)).strip() == "def f():\n c = '''while True:\n pass\n'''"
+
+
+def test_deindent():
+ from py._code.source import deindent as deindent
+ assert deindent(['\tfoo', '\tbar', ]) == ['foo', 'bar']
+
+ def f():
+ c = '''while True:
+ pass
+'''
+ import inspect
+ lines = deindent(inspect.getsource(f).splitlines())
+ assert lines == ["def f():", " c = '''while True:", " pass", "'''"]
+
+ source = """
+ def f():
+ def g():
+ pass
+ """
+ lines = deindent(source.splitlines())
+ assert lines == ['', 'def f():', ' def g():', ' pass', ' ']
+
+def test_source_of_class_at_eof_without_newline(tmpdir):
+ # this test fails because the implicit inspect.getsource(A) below
+ # does not return the "x = 1" last line.
+ source = py.code.Source('''
+ class A(object):
+ def method(self):
+ x = 1
+ ''')
+ path = tmpdir.join("a.py")
+ path.write(source)
+ s2 = py.code.Source(tmpdir.join("a.py").pyimport().A)
+ assert str(source).strip() == str(s2).strip()
+
+if True:
+ def x():
+ pass
+
+def test_getsource_fallback():
+ from py._code.source import getsource
+ expected = """def x():
+ pass"""
+ src = getsource(x)
+ assert src == expected
+
+def test_idem_compile_and_getsource():
+ from py._code.source import getsource
+ expected = "def x(): pass"
+ co = py.code.compile(expected)
+ src = getsource(co)
+ assert src == expected
+
+def test_findsource_fallback():
+ from py._code.source import findsource
+ src, lineno = findsource(x)
+ assert 'test_findsource_simple' in str(src)
+ assert src[lineno] == ' def x():'
+
+def test_findsource():
+ from py._code.source import findsource
+ co = py.code.compile("""if 1:
+ def x():
+ pass
+""")
+
+ src, lineno = findsource(co)
+ assert 'if 1:' in str(src)
+
+ d = {}
+ eval(co, d)
+ src, lineno = findsource(d['x'])
+ assert 'if 1:' in str(src)
+ assert src[lineno] == " def x():"
+
+
+def test_getfslineno():
+ from py.code import getfslineno
+
+ def f(x):
+ pass
+
+ fspath, lineno = getfslineno(f)
+
+ assert fspath.basename == "test_source.py"
+ assert lineno == py.code.getrawcode(f).co_firstlineno-1 # see findsource
+
+ class A(object):
+ pass
+
+ fspath, lineno = getfslineno(A)
+
+ _, A_lineno = inspect.findsource(A)
+ assert fspath.basename == "test_source.py"
+ assert lineno == A_lineno
+
+ assert getfslineno(3) == ("", -1)
+ class B:
+ pass
+ B.__name__ = "B2"
+ assert getfslineno(B)[1] == -1
+
+def test_code_of_object_instance_with_call():
+ class A:
+ pass
+ py.test.raises(TypeError, lambda: py.code.Source(A()))
+ class WithCall:
+ def __call__(self):
+ pass
+
+ code = py.code.Code(WithCall())
+ assert 'pass' in str(code.source())
+
+ class Hello(object):
+ def __call__(self):
+ pass
+ py.test.raises(TypeError, lambda: py.code.Code(Hello))
+
+
+def getstatement(lineno, source):
+ from py._code.source import getstatementrange_ast
+ source = py.code.Source(source, deindent=False)
+ ast, start, end = getstatementrange_ast(lineno, source)
+ return source[start:end]
+
+def test_oneline():
+ source = getstatement(0, "raise ValueError")
+ assert str(source) == "raise ValueError"
+
+def test_comment_and_no_newline_at_end():
+ from py._code.source import getstatementrange_ast
+ source = Source(['def test_basic_complex():',
+ ' assert 1 == 2',
+ '# vim: filetype=pyopencl:fdm=marker'])
+ ast, start, end = getstatementrange_ast(1, source)
+ assert end == 2
+
+def test_oneline_and_comment():
+ source = getstatement(0, "raise ValueError\n#hello")
+ assert str(source) == "raise ValueError"
+
+def test_comments():
+ source = '''def test():
+ "comment 1"
+ x = 1
+ # comment 2
+ # comment 3
+
+ assert False
+
+"""
+comment 4
+"""
+'''
+ for line in range(2,6):
+ assert str(getstatement(line, source)) == ' x = 1'
+ for line in range(6,10):
+ assert str(getstatement(line, source)) == ' assert False'
+ assert str(getstatement(10, source)) == '"""'
+
+def test_comment_in_statement():
+ source = '''test(foo=1,
+ # comment 1
+ bar=2)
+'''
+ for line in range(1,3):
+ assert str(getstatement(line, source)) == \
+ 'test(foo=1,\n # comment 1\n bar=2)'
+
+def test_single_line_else():
+ source = getstatement(1, "if False: 2\nelse: 3")
+ assert str(source) == "else: 3"
+
+def test_single_line_finally():
+ source = getstatement(1, "try: 1\nfinally: 3")
+ assert str(source) == "finally: 3"
+
+def test_issue55():
+ source = ('def round_trip(dinp):\n assert 1 == dinp\n'
+ 'def test_rt():\n round_trip("""\n""")\n')
+ s = getstatement(3, source)
+ assert str(s) == ' round_trip("""\n""")'
+
+
+def XXXtest_multiline():
+ source = getstatement(0, """\
+raise ValueError(
+ 23
+)
+x = 3
+""")
+ assert str(source) == "raise ValueError(\n 23\n)"
+
+class TestTry:
+ pytestmark = astonly
+ source = """\
+try:
+ raise ValueError
+except Something:
+ raise IndexError(1)
+else:
+ raise KeyError()
+"""
+
+ def test_body(self):
+ source = getstatement(1, self.source)
+ assert str(source) == " raise ValueError"
+
+ def test_except_line(self):
+ source = getstatement(2, self.source)
+ assert str(source) == "except Something:"
+
+ def test_except_body(self):
+ source = getstatement(3, self.source)
+ assert str(source) == " raise IndexError(1)"
+
+ def test_else(self):
+ source = getstatement(5, self.source)
+ assert str(source) == " raise KeyError()"
+
+class TestTryFinally:
+ source = """\
+try:
+ raise ValueError
+finally:
+ raise IndexError(1)
+"""
+
+ def test_body(self):
+ source = getstatement(1, self.source)
+ assert str(source) == " raise ValueError"
+
+ def test_finally(self):
+ source = getstatement(3, self.source)
+ assert str(source) == " raise IndexError(1)"
+
+
+
+class TestIf:
+ pytestmark = astonly
+ source = """\
+if 1:
+ y = 3
+elif False:
+ y = 5
+else:
+ y = 7
+"""
+
+ def test_body(self):
+ source = getstatement(1, self.source)
+ assert str(source) == " y = 3"
+
+ def test_elif_clause(self):
+ source = getstatement(2, self.source)
+ assert str(source) == "elif False:"
+
+ def test_elif(self):
+ source = getstatement(3, self.source)
+ assert str(source) == " y = 5"
+
+ def test_else(self):
+ source = getstatement(5, self.source)
+ assert str(source) == " y = 7"
+
+def test_semicolon():
+ s = """\
+hello ; pytest.skip()
+"""
+ source = getstatement(0, s)
+ assert str(source) == s.strip()
+
+def test_def_online():
+ s = """\
+def func(): raise ValueError(42)
+
+def something():
+ pass
+"""
+ source = getstatement(0, s)
+ assert str(source) == "def func(): raise ValueError(42)"
+
+def XXX_test_expression_multiline():
+ source = """\
+something
+'''
+'''"""
+ result = getstatement(1, source)
+ assert str(result) == "'''\n'''"
+
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/conftest.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/conftest.py
index 0f956b3dd25..0f956b3dd25 100644
--- a/tests/wpt/web-platform-tests/tools/py/testing/conftest.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/conftest.py
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/io_/__init__.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/io_/__init__.py
index 792d6005489..792d6005489 100644
--- a/tests/wpt/web-platform-tests/tools/py/testing/io_/__init__.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/io_/__init__.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/testing/io_/test_capture.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/io_/test_capture.py
new file mode 100644
index 00000000000..b5fedd0abc6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/io_/test_capture.py
@@ -0,0 +1,501 @@
+from __future__ import with_statement
+
+import os, sys
+import py
+
+needsdup = py.test.mark.skipif("not hasattr(os, 'dup')")
+
+from py.builtin import print_
+
+if sys.version_info >= (3,0):
+ def tobytes(obj):
+ if isinstance(obj, str):
+ obj = obj.encode('UTF-8')
+ assert isinstance(obj, bytes)
+ return obj
+ def totext(obj):
+ if isinstance(obj, bytes):
+ obj = str(obj, 'UTF-8')
+ assert isinstance(obj, str)
+ return obj
+else:
+ def tobytes(obj):
+ if isinstance(obj, unicode):
+ obj = obj.encode('UTF-8')
+ assert isinstance(obj, str)
+ return obj
+ def totext(obj):
+ if isinstance(obj, str):
+ obj = unicode(obj, 'UTF-8')
+ assert isinstance(obj, unicode)
+ return obj
+
+def oswritebytes(fd, obj):
+ os.write(fd, tobytes(obj))
+
+class TestTextIO:
+ def test_text(self):
+ f = py.io.TextIO()
+ f.write("hello")
+ s = f.getvalue()
+ assert s == "hello"
+ f.close()
+
+ def test_unicode_and_str_mixture(self):
+ f = py.io.TextIO()
+ if sys.version_info >= (3,0):
+ f.write("\u00f6")
+ py.test.raises(TypeError, "f.write(bytes('hello', 'UTF-8'))")
+ else:
+ f.write(unicode("\u00f6", 'UTF-8'))
+ f.write("hello") # bytes
+ s = f.getvalue()
+ f.close()
+ assert isinstance(s, unicode)
+
+def test_bytes_io():
+ f = py.io.BytesIO()
+ f.write(tobytes("hello"))
+ py.test.raises(TypeError, "f.write(totext('hello'))")
+ s = f.getvalue()
+ assert s == tobytes("hello")
+
+def test_dontreadfrominput():
+ from py._io.capture import DontReadFromInput
+ f = DontReadFromInput()
+ assert not f.isatty()
+ py.test.raises(IOError, f.read)
+ py.test.raises(IOError, f.readlines)
+ py.test.raises(IOError, iter, f)
+ py.test.raises(ValueError, f.fileno)
+ f.close() # just for completeness
+
+def pytest_funcarg__tmpfile(request):
+ testdir = request.getfuncargvalue("testdir")
+ f = testdir.makepyfile("").open('wb+')
+ request.addfinalizer(f.close)
+ return f
+
+@needsdup
+def test_dupfile(tmpfile):
+ flist = []
+ for i in range(5):
+ nf = py.io.dupfile(tmpfile, encoding="utf-8")
+ assert nf != tmpfile
+ assert nf.fileno() != tmpfile.fileno()
+ assert nf not in flist
+ print_(i, end="", file=nf)
+ flist.append(nf)
+ for i in range(5):
+ f = flist[i]
+ f.close()
+ tmpfile.seek(0)
+ s = tmpfile.read()
+ assert "01234" in repr(s)
+ tmpfile.close()
+
+def test_dupfile_no_mode():
+ """
+ dupfile should trap an AttributeError and return f if no mode is supplied.
+ """
+ class SomeFileWrapper(object):
+ "An object with a fileno method but no mode attribute"
+ def fileno(self):
+ return 1
+ tmpfile = SomeFileWrapper()
+ assert py.io.dupfile(tmpfile) is tmpfile
+ with py.test.raises(AttributeError):
+ py.io.dupfile(tmpfile, raising=True)
+
+def lsof_check(func):
+ pid = os.getpid()
+ try:
+ out = py.process.cmdexec("lsof -p %d" % pid)
+ except py.process.cmdexec.Error:
+ py.test.skip("could not run 'lsof'")
+ func()
+ out2 = py.process.cmdexec("lsof -p %d" % pid)
+ len1 = len([x for x in out.split("\n") if "REG" in x])
+ len2 = len([x for x in out2.split("\n") if "REG" in x])
+ assert len2 < len1 + 3, out2
+
+class TestFDCapture:
+ pytestmark = needsdup
+
+ def test_not_now(self, tmpfile):
+ fd = tmpfile.fileno()
+ cap = py.io.FDCapture(fd, now=False)
+ data = tobytes("hello")
+ os.write(fd, data)
+ f = cap.done()
+ s = f.read()
+ assert not s
+ cap = py.io.FDCapture(fd, now=False)
+ cap.start()
+ os.write(fd, data)
+ f = cap.done()
+ s = f.read()
+ assert s == "hello"
+
+ def test_simple(self, tmpfile):
+ fd = tmpfile.fileno()
+ cap = py.io.FDCapture(fd)
+ data = tobytes("hello")
+ os.write(fd, data)
+ f = cap.done()
+ s = f.read()
+ assert s == "hello"
+ f.close()
+
+ def test_simple_many(self, tmpfile):
+ for i in range(10):
+ self.test_simple(tmpfile)
+
+ def test_simple_many_check_open_files(self, tmpfile):
+ lsof_check(lambda: self.test_simple_many(tmpfile))
+
+ def test_simple_fail_second_start(self, tmpfile):
+ fd = tmpfile.fileno()
+ cap = py.io.FDCapture(fd)
+ f = cap.done()
+ py.test.raises(ValueError, cap.start)
+ f.close()
+
+ def test_stderr(self):
+ cap = py.io.FDCapture(2, patchsys=True)
+ print_("hello", file=sys.stderr)
+ f = cap.done()
+ s = f.read()
+ assert s == "hello\n"
+
+ def test_stdin(self, tmpfile):
+ tmpfile.write(tobytes("3"))
+ tmpfile.seek(0)
+ cap = py.io.FDCapture(0, tmpfile=tmpfile)
+ # check with os.read() directly instead of raw_input(), because
+ # sys.stdin itself may be redirected (as py.test now does by default)
+ x = os.read(0, 100).strip()
+ f = cap.done()
+ assert x == tobytes("3")
+
+ def test_writeorg(self, tmpfile):
+ data1, data2 = tobytes("foo"), tobytes("bar")
+ try:
+ cap = py.io.FDCapture(tmpfile.fileno())
+ tmpfile.write(data1)
+ cap.writeorg(data2)
+ finally:
+ tmpfile.close()
+ f = cap.done()
+ scap = f.read()
+ assert scap == totext(data1)
+ stmp = open(tmpfile.name, 'rb').read()
+ assert stmp == data2
+
+
+class TestStdCapture:
+ def getcapture(self, **kw):
+ return py.io.StdCapture(**kw)
+
+ def test_capturing_done_simple(self):
+ cap = self.getcapture()
+ sys.stdout.write("hello")
+ sys.stderr.write("world")
+ outfile, errfile = cap.done()
+ s = outfile.read()
+ assert s == "hello"
+ s = errfile.read()
+ assert s == "world"
+
+ def test_capturing_reset_simple(self):
+ cap = self.getcapture()
+ print("hello world")
+ sys.stderr.write("hello error\n")
+ out, err = cap.reset()
+ assert out == "hello world\n"
+ assert err == "hello error\n"
+
+ def test_capturing_readouterr(self):
+ cap = self.getcapture()
+ try:
+ print ("hello world")
+ sys.stderr.write("hello error\n")
+ out, err = cap.readouterr()
+ assert out == "hello world\n"
+ assert err == "hello error\n"
+ sys.stderr.write("error2")
+ finally:
+ out, err = cap.reset()
+ assert err == "error2"
+
+ def test_capturing_readouterr_unicode(self):
+ cap = self.getcapture()
+ print ("hx\xc4\x85\xc4\x87")
+ out, err = cap.readouterr()
+ assert out == py.builtin._totext("hx\xc4\x85\xc4\x87\n", "utf8")
+
+ @py.test.mark.skipif('sys.version_info >= (3,)',
+ reason='text output different for bytes on python3')
+ def test_capturing_readouterr_decode_error_handling(self):
+ cap = self.getcapture()
+ # triggered a internal error in pytest
+ print('\xa6')
+ out, err = cap.readouterr()
+ assert out == py.builtin._totext('\ufffd\n', 'unicode-escape')
+
+ def test_capturing_mixed(self):
+ cap = self.getcapture(mixed=True)
+ sys.stdout.write("hello ")
+ sys.stderr.write("world")
+ sys.stdout.write(".")
+ out, err = cap.reset()
+ assert out.strip() == "hello world."
+ assert not err
+
+ def test_reset_twice_error(self):
+ cap = self.getcapture()
+ print ("hello")
+ out, err = cap.reset()
+ py.test.raises(ValueError, cap.reset)
+ assert out == "hello\n"
+ assert not err
+
+ def test_capturing_modify_sysouterr_in_between(self):
+ oldout = sys.stdout
+ olderr = sys.stderr
+ cap = self.getcapture()
+ sys.stdout.write("hello")
+ sys.stderr.write("world")
+ sys.stdout = py.io.TextIO()
+ sys.stderr = py.io.TextIO()
+ print ("not seen")
+ sys.stderr.write("not seen\n")
+ out, err = cap.reset()
+ assert out == "hello"
+ assert err == "world"
+ assert sys.stdout == oldout
+ assert sys.stderr == olderr
+
+ def test_capturing_error_recursive(self):
+ cap1 = self.getcapture()
+ print ("cap1")
+ cap2 = self.getcapture()
+ print ("cap2")
+ out2, err2 = cap2.reset()
+ out1, err1 = cap1.reset()
+ assert out1 == "cap1\n"
+ assert out2 == "cap2\n"
+
+ def test_just_out_capture(self):
+ cap = self.getcapture(out=True, err=False)
+ sys.stdout.write("hello")
+ sys.stderr.write("world")
+ out, err = cap.reset()
+ assert out == "hello"
+ assert not err
+
+ def test_just_err_capture(self):
+ cap = self.getcapture(out=False, err=True)
+ sys.stdout.write("hello")
+ sys.stderr.write("world")
+ out, err = cap.reset()
+ assert err == "world"
+ assert not out
+
+ def test_stdin_restored(self):
+ old = sys.stdin
+ cap = self.getcapture(in_=True)
+ newstdin = sys.stdin
+ out, err = cap.reset()
+ assert newstdin != sys.stdin
+ assert sys.stdin is old
+
+ def test_stdin_nulled_by_default(self):
+ print ("XXX this test may well hang instead of crashing")
+ print ("XXX which indicates an error in the underlying capturing")
+ print ("XXX mechanisms")
+ cap = self.getcapture()
+ py.test.raises(IOError, "sys.stdin.read()")
+ out, err = cap.reset()
+
+ def test_suspend_resume(self):
+ cap = self.getcapture(out=True, err=False, in_=False)
+ try:
+ print ("hello")
+ sys.stderr.write("error\n")
+ out, err = cap.suspend()
+ assert out == "hello\n"
+ assert not err
+ print ("in between")
+ sys.stderr.write("in between\n")
+ cap.resume()
+ print ("after")
+ sys.stderr.write("error_after\n")
+ finally:
+ out, err = cap.reset()
+ assert out == "after\n"
+ assert not err
+
+class TestStdCaptureNotNow(TestStdCapture):
+ def getcapture(self, **kw):
+ kw['now'] = False
+ cap = py.io.StdCapture(**kw)
+ cap.startall()
+ return cap
+
+class TestStdCaptureFD(TestStdCapture):
+ pytestmark = needsdup
+
+ def getcapture(self, **kw):
+ return py.io.StdCaptureFD(**kw)
+
+ def test_intermingling(self):
+ cap = self.getcapture()
+ oswritebytes(1, "1")
+ sys.stdout.write(str(2))
+ sys.stdout.flush()
+ oswritebytes(1, "3")
+ oswritebytes(2, "a")
+ sys.stderr.write("b")
+ sys.stderr.flush()
+ oswritebytes(2, "c")
+ out, err = cap.reset()
+ assert out == "123"
+ assert err == "abc"
+
+ def test_callcapture(self):
+ def func(x, y):
+ print (x)
+ sys.stderr.write(str(y))
+ return 42
+
+ res, out, err = py.io.StdCaptureFD.call(func, 3, y=4)
+ assert res == 42
+ assert out.startswith("3")
+ assert err.startswith("4")
+
+ def test_many(self, capfd):
+ def f():
+ for i in range(10):
+ cap = py.io.StdCaptureFD()
+ cap.reset()
+ lsof_check(f)
+
+class TestStdCaptureFDNotNow(TestStdCaptureFD):
+ pytestmark = needsdup
+
+ def getcapture(self, **kw):
+ kw['now'] = False
+ cap = py.io.StdCaptureFD(**kw)
+ cap.startall()
+ return cap
+
+@needsdup
+def test_stdcapture_fd_tmpfile(tmpfile):
+ capfd = py.io.StdCaptureFD(out=tmpfile)
+ os.write(1, "hello".encode("ascii"))
+ os.write(2, "world".encode("ascii"))
+ outf, errf = capfd.done()
+ assert outf == tmpfile
+
+class TestStdCaptureFDinvalidFD:
+ pytestmark = needsdup
+ def test_stdcapture_fd_invalid_fd(self, testdir):
+ testdir.makepyfile("""
+ import py, os
+ def test_stdout():
+ os.close(1)
+ cap = py.io.StdCaptureFD(out=True, err=False, in_=False)
+ cap.done()
+ def test_stderr():
+ os.close(2)
+ cap = py.io.StdCaptureFD(out=False, err=True, in_=False)
+ cap.done()
+ def test_stdin():
+ os.close(0)
+ cap = py.io.StdCaptureFD(out=False, err=False, in_=True)
+ cap.done()
+ """)
+ result = testdir.runpytest("--capture=fd")
+ assert result.ret == 0
+ assert result.parseoutcomes()['passed'] == 3
+
+def test_capture_not_started_but_reset():
+ capsys = py.io.StdCapture(now=False)
+ capsys.done()
+ capsys.done()
+ capsys.reset()
+
+@needsdup
+def test_capture_no_sys():
+ capsys = py.io.StdCapture()
+ try:
+ cap = py.io.StdCaptureFD(patchsys=False)
+ sys.stdout.write("hello")
+ sys.stderr.write("world")
+ oswritebytes(1, "1")
+ oswritebytes(2, "2")
+ out, err = cap.reset()
+ assert out == "1"
+ assert err == "2"
+ finally:
+ capsys.reset()
+
+@needsdup
+def test_callcapture_nofd():
+ def func(x, y):
+ oswritebytes(1, "hello")
+ oswritebytes(2, "hello")
+ print (x)
+ sys.stderr.write(str(y))
+ return 42
+
+ capfd = py.io.StdCaptureFD(patchsys=False)
+ try:
+ res, out, err = py.io.StdCapture.call(func, 3, y=4)
+ finally:
+ capfd.reset()
+ assert res == 42
+ assert out.startswith("3")
+ assert err.startswith("4")
+
+@needsdup
+@py.test.mark.parametrize('use', [True, False])
+def test_fdcapture_tmpfile_remains_the_same(tmpfile, use):
+ if not use:
+ tmpfile = True
+ cap = py.io.StdCaptureFD(out=False, err=tmpfile, now=False)
+ cap.startall()
+ capfile = cap.err.tmpfile
+ cap.suspend()
+ cap.resume()
+ capfile2 = cap.err.tmpfile
+ assert capfile2 == capfile
+
+@py.test.mark.parametrize('method', ['StdCapture', 'StdCaptureFD'])
+def test_capturing_and_logging_fundamentals(testdir, method):
+ if method == "StdCaptureFD" and not hasattr(os, 'dup'):
+ py.test.skip("need os.dup")
+ # here we check a fundamental feature
+ p = testdir.makepyfile("""
+ import sys, os
+ import py, logging
+ cap = py.io.%s(out=False, in_=False)
+
+ logging.warn("hello1")
+ outerr = cap.suspend()
+ print ("suspend, captured %%s" %%(outerr,))
+ logging.warn("hello2")
+
+ cap.resume()
+ logging.warn("hello3")
+
+ outerr = cap.suspend()
+ print ("suspend2, captured %%s" %% (outerr,))
+ """ % (method,))
+ result = testdir.runpython(p)
+ result.stdout.fnmatch_lines([
+ "suspend, captured*hello1*",
+ "suspend2, captured*hello2*WARNING:root:hello3*",
+ ])
+ assert "atexit" not in result.stderr.str()
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/testing/io_/test_saferepr.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/io_/test_saferepr.py
new file mode 100644
index 00000000000..97be1416fec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/io_/test_saferepr.py
@@ -0,0 +1,75 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import generators
+import py
+import sys
+
+saferepr = py.io.saferepr
+
+class TestSafeRepr:
+ def test_simple_repr(self):
+ assert saferepr(1) == '1'
+ assert saferepr(None) == 'None'
+
+ def test_maxsize(self):
+ s = saferepr('x'*50, maxsize=25)
+ assert len(s) == 25
+ expected = repr('x'*10 + '...' + 'x'*10)
+ assert s == expected
+
+ def test_maxsize_error_on_instance(self):
+ class A:
+ def __repr__(self):
+ raise ValueError('...')
+
+ s = saferepr(('*'*50, A()), maxsize=25)
+ assert len(s) == 25
+ assert s[0] == '(' and s[-1] == ')'
+
+ def test_exceptions(self):
+ class BrokenRepr:
+ def __init__(self, ex):
+ self.ex = ex
+ foo = 0
+ def __repr__(self):
+ raise self.ex
+ class BrokenReprException(Exception):
+ __str__ = None
+ __repr__ = None
+ assert 'Exception' in saferepr(BrokenRepr(Exception("broken")))
+ s = saferepr(BrokenReprException("really broken"))
+ assert 'TypeError' in s
+ assert 'TypeError' in saferepr(BrokenRepr("string"))
+
+ s2 = saferepr(BrokenRepr(BrokenReprException('omg even worse')))
+ assert 'NameError' not in s2
+ assert 'unknown' in s2
+
+ def test_big_repr(self):
+ from py._io.saferepr import SafeRepr
+ assert len(saferepr(range(1000))) <= \
+ len('[' + SafeRepr().maxlist * "1000" + ']')
+
+ def test_repr_on_newstyle(self):
+ class Function(object):
+ def __repr__(self):
+ return "<%s>" %(self.name)
+ try:
+ s = saferepr(Function())
+ except Exception:
+ py.test.fail("saferepr failed for newstyle class")
+
+ def test_unicode(self):
+ val = py.builtin._totext('£€', 'utf-8')
+ reprval = py.builtin._totext("'£€'", 'utf-8')
+ assert saferepr(val) == reprval
+
+def test_unicode_handling():
+ value = py.builtin._totext('\xc4\x85\xc4\x87\n', 'utf-8').encode('utf8')
+ def f():
+ raise Exception(value)
+ excinfo = py.test.raises(Exception, f)
+ s = str(excinfo)
+ if sys.version_info[0] < 3:
+ u = unicode(excinfo)
+
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/testing/io_/test_terminalwriter.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/io_/test_terminalwriter.py
new file mode 100644
index 00000000000..7e9ebf409ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/io_/test_terminalwriter.py
@@ -0,0 +1,292 @@
+
+import py
+import os, sys
+from py._io import terminalwriter
+import codecs
+import pytest
+
+def test_get_terminal_width():
+ x = py.io.get_terminal_width
+ assert x == terminalwriter.get_terminal_width
+
+def test_getdimensions(monkeypatch):
+ fcntl = py.test.importorskip("fcntl")
+ import struct
+ l = []
+ monkeypatch.setattr(fcntl, 'ioctl', lambda *args: l.append(args))
+ try:
+ terminalwriter._getdimensions()
+ except (TypeError, struct.error):
+ pass
+ assert len(l) == 1
+ assert l[0][0] == 1
+
+def test_terminal_width_COLUMNS(monkeypatch):
+ """ Dummy test for get_terminal_width
+ """
+ fcntl = py.test.importorskip("fcntl")
+ monkeypatch.setattr(fcntl, 'ioctl', lambda *args: int('x'))
+ monkeypatch.setenv('COLUMNS', '42')
+ assert terminalwriter.get_terminal_width() == 42
+ monkeypatch.delenv('COLUMNS', raising=False)
+
+def test_terminalwriter_defaultwidth_80(monkeypatch):
+ monkeypatch.setattr(terminalwriter, '_getdimensions', lambda: 0/0)
+ monkeypatch.delenv('COLUMNS', raising=False)
+ tw = py.io.TerminalWriter()
+ assert tw.fullwidth == 80
+
+def test_terminalwriter_getdimensions_bogus(monkeypatch):
+ monkeypatch.setattr(terminalwriter, '_getdimensions', lambda: (10,10))
+ monkeypatch.delenv('COLUMNS', raising=False)
+ tw = py.io.TerminalWriter()
+ assert tw.fullwidth == 80
+
+def test_terminalwriter_getdimensions_emacs(monkeypatch):
+ # emacs terminal returns (0,0) but set COLUMNS properly
+ monkeypatch.setattr(terminalwriter, '_getdimensions', lambda: (0,0))
+ monkeypatch.setenv('COLUMNS', '42')
+ tw = py.io.TerminalWriter()
+ assert tw.fullwidth == 42
+
+def test_terminalwriter_computes_width(monkeypatch):
+ monkeypatch.setattr(terminalwriter, 'get_terminal_width', lambda: 42)
+ tw = py.io.TerminalWriter()
+ assert tw.fullwidth == 42
+
+def test_terminalwriter_default_instantiation():
+ tw = py.io.TerminalWriter(stringio=True)
+ assert hasattr(tw, 'stringio')
+
+def test_terminalwriter_dumb_term_no_markup(monkeypatch):
+ monkeypatch.setattr(os, 'environ', {'TERM': 'dumb', 'PATH': ''})
+ class MyFile:
+ closed = False
+ def isatty(self):
+ return True
+ monkeypatch.setattr(sys, 'stdout', MyFile())
+ try:
+ assert sys.stdout.isatty()
+ tw = py.io.TerminalWriter()
+ assert not tw.hasmarkup
+ finally:
+ monkeypatch.undo()
+
+def test_terminalwriter_file_unicode(tmpdir):
+ f = codecs.open(str(tmpdir.join("xyz")), "wb", "utf8")
+ tw = py.io.TerminalWriter(file=f)
+ assert tw.encoding == "utf8"
+
+def test_unicode_encoding():
+ msg = py.builtin._totext('b\u00f6y', 'utf8')
+ for encoding in 'utf8', 'latin1':
+ l = []
+ tw = py.io.TerminalWriter(l.append, encoding=encoding)
+ tw.line(msg)
+ assert l[0].strip() == msg.encode(encoding)
+
+@pytest.mark.parametrize("encoding", ["ascii"])
+def test_unicode_on_file_with_ascii_encoding(tmpdir, monkeypatch, encoding):
+ msg = py.builtin._totext('hell\xf6', "latin1")
+ #pytest.raises(UnicodeEncodeError, lambda: bytes(msg))
+ f = codecs.open(str(tmpdir.join("x")), "w", encoding)
+ tw = py.io.TerminalWriter(f)
+ tw.line(msg)
+ f.close()
+ s = tmpdir.join("x").open("rb").read().strip()
+ assert encoding == "ascii"
+ assert s == msg.encode("unicode-escape")
+
+
+win32 = int(sys.platform == "win32")
+class TestTerminalWriter:
+ def pytest_generate_tests(self, metafunc):
+ if "tw" in metafunc.funcargnames:
+ metafunc.addcall(id="path", param="path")
+ metafunc.addcall(id="stringio", param="stringio")
+ metafunc.addcall(id="callable", param="callable")
+ def pytest_funcarg__tw(self, request):
+ if request.param == "path":
+ tmpdir = request.getfuncargvalue("tmpdir")
+ p = tmpdir.join("tmpfile")
+ f = codecs.open(str(p), 'w+', encoding='utf8')
+ tw = py.io.TerminalWriter(f)
+ def getlines():
+ tw._file.flush()
+ return codecs.open(str(p), 'r',
+ encoding='utf8').readlines()
+ elif request.param == "stringio":
+ tw = py.io.TerminalWriter(stringio=True)
+ def getlines():
+ tw.stringio.seek(0)
+ return tw.stringio.readlines()
+ elif request.param == "callable":
+ writes = []
+ tw = py.io.TerminalWriter(writes.append)
+ def getlines():
+ io = py.io.TextIO()
+ io.write("".join(writes))
+ io.seek(0)
+ return io.readlines()
+ tw.getlines = getlines
+ tw.getvalue = lambda: "".join(getlines())
+ return tw
+
+ def test_line(self, tw):
+ tw.line("hello")
+ l = tw.getlines()
+ assert len(l) == 1
+ assert l[0] == "hello\n"
+
+ def test_line_unicode(self, tw):
+ for encoding in 'utf8', 'latin1':
+ tw._encoding = encoding
+ msg = py.builtin._totext('b\u00f6y', 'utf8')
+ tw.line(msg)
+ l = tw.getlines()
+ assert l[0] == msg + "\n"
+
+ def test_sep_no_title(self, tw):
+ tw.sep("-", fullwidth=60)
+ l = tw.getlines()
+ assert len(l) == 1
+ assert l[0] == "-" * (60-win32) + "\n"
+
+ def test_sep_with_title(self, tw):
+ tw.sep("-", "hello", fullwidth=60)
+ l = tw.getlines()
+ assert len(l) == 1
+ assert l[0] == "-" * 26 + " hello " + "-" * (27-win32) + "\n"
+
+ @py.test.mark.skipif("sys.platform == 'win32'")
+ def test__escaped(self, tw):
+ text2 = tw._escaped("hello", (31))
+ assert text2.find("hello") != -1
+
+ @py.test.mark.skipif("sys.platform == 'win32'")
+ def test_markup(self, tw):
+ for bold in (True, False):
+ for color in ("red", "green"):
+ text2 = tw.markup("hello", **{color: True, 'bold': bold})
+ assert text2.find("hello") != -1
+ py.test.raises(ValueError, "tw.markup('x', wronkw=3)")
+ py.test.raises(ValueError, "tw.markup('x', wronkw=0)")
+
+ def test_line_write_markup(self, tw):
+ tw.hasmarkup = True
+ tw.line("x", bold=True)
+ tw.write("x\n", red=True)
+ l = tw.getlines()
+ if sys.platform != "win32":
+ assert len(l[0]) >= 2, l
+ assert len(l[1]) >= 2, l
+
+ def test_attr_fullwidth(self, tw):
+ tw.sep("-", "hello", fullwidth=70)
+ tw.fullwidth = 70
+ tw.sep("-", "hello")
+ l = tw.getlines()
+ assert len(l[0]) == len(l[1])
+
+ def test_reline(self, tw):
+ tw.line("hello")
+ tw.hasmarkup = False
+ pytest.raises(ValueError, lambda: tw.reline("x"))
+ tw.hasmarkup = True
+ tw.reline("0 1 2")
+ tw.getlines()
+ l = tw.getvalue().split("\n")
+ assert len(l) == 2
+ tw.reline("0 1 3")
+ l = tw.getvalue().split("\n")
+ assert len(l) == 2
+ assert l[1].endswith("0 1 3\r")
+ tw.line("so")
+ l = tw.getvalue().split("\n")
+ assert len(l) == 3
+ assert l[-1] == ""
+ assert l[1] == ("0 1 2\r0 1 3\rso ")
+ assert l[0] == "hello"
+
+
+def test_terminal_with_callable_write_and_flush():
+ l = set()
+ class fil:
+ flush = lambda self: l.add("1")
+ write = lambda self, x: l.add("1")
+ __call__ = lambda self, x: l.add("2")
+
+ tw = py.io.TerminalWriter(fil())
+ tw.line("hello")
+ assert l == set(["1"])
+ del fil.flush
+ l.clear()
+ tw = py.io.TerminalWriter(fil())
+ tw.line("hello")
+ assert l == set(["2"])
+
+
+def test_chars_on_current_line():
+ tw = py.io.TerminalWriter(stringio=True)
+
+ written = []
+
+ def write_and_check(s, expected):
+ tw.write(s, bold=True)
+ written.append(s)
+ assert tw.chars_on_current_line == expected
+ assert tw.stringio.getvalue() == ''.join(written)
+
+ write_and_check('foo', 3)
+ write_and_check('bar', 6)
+ write_and_check('\n', 0)
+ write_and_check('\n', 0)
+ write_and_check('\n\n\n', 0)
+ write_and_check('\nfoo', 3)
+ write_and_check('\nfbar\nhello', 5)
+ write_and_check('10', 7)
+
+
+@pytest.mark.skipif(sys.platform == "win32", reason="win32 has no native ansi")
+def test_attr_hasmarkup():
+ tw = py.io.TerminalWriter(stringio=True)
+ assert not tw.hasmarkup
+ tw.hasmarkup = True
+ tw.line("hello", bold=True)
+ s = tw.stringio.getvalue()
+ assert len(s) > len("hello\n")
+ assert '\x1b[1m' in s
+ assert '\x1b[0m' in s
+
+@pytest.mark.skipif(sys.platform == "win32", reason="win32 has no native ansi")
+def test_ansi_print():
+ # we have no easy way to construct a file that
+ # represents a terminal
+ f = py.io.TextIO()
+ f.isatty = lambda: True
+ py.io.ansi_print("hello", 0x32, file=f)
+ text2 = f.getvalue()
+ assert text2.find("hello") != -1
+ assert len(text2) >= len("hello\n")
+ assert '\x1b[50m' in text2
+ assert '\x1b[0m' in text2
+
+def test_should_do_markup_PY_COLORS_eq_1(monkeypatch):
+ monkeypatch.setitem(os.environ, 'PY_COLORS', '1')
+ tw = py.io.TerminalWriter(stringio=True)
+ assert tw.hasmarkup
+ tw.line("hello", bold=True)
+ s = tw.stringio.getvalue()
+ assert len(s) > len("hello\n")
+ assert '\x1b[1m' in s
+ assert '\x1b[0m' in s
+
+def test_should_do_markup_PY_COLORS_eq_0(monkeypatch):
+ monkeypatch.setitem(os.environ, 'PY_COLORS', '0')
+ f = py.io.TextIO()
+ f.isatty = lambda: True
+ tw = py.io.TerminalWriter(file=f)
+ assert not tw.hasmarkup
+ tw.line("hello", bold=True)
+ s = f.getvalue()
+ assert s == "hello\n"
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/testing/log/__init__.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/log/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/log/__init__.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/testing/log/test_log.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/log/test_log.py
new file mode 100644
index 00000000000..5c706d9b6ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/log/test_log.py
@@ -0,0 +1,191 @@
+import py
+
+from py._log.log import default_keywordmapper
+
+callcapture = py.io.StdCapture.call
+
+
+def setup_module(mod):
+ mod._oldstate = default_keywordmapper.getstate()
+
+def teardown_module(mod):
+ default_keywordmapper.setstate(mod._oldstate)
+
+class TestLogProducer:
+ def setup_method(self, meth):
+ from py._log.log import default_keywordmapper
+ default_keywordmapper.setstate(_oldstate)
+
+ def test_getstate_setstate(self):
+ state = py.log._getstate()
+ py.log.setconsumer("hello", [].append)
+ state2 = py.log._getstate()
+ assert state2 != state
+ py.log._setstate(state)
+ state3 = py.log._getstate()
+ assert state3 == state
+
+ def test_producer_repr(self):
+ d = py.log.Producer("default")
+ assert repr(d).find('default') != -1
+
+ def test_produce_one_keyword(self):
+ l = []
+ py.log.setconsumer('s1', l.append)
+ py.log.Producer('s1')("hello world")
+ assert len(l) == 1
+ msg = l[0]
+ assert msg.content().startswith('hello world')
+ assert msg.prefix() == '[s1] '
+ assert str(msg) == "[s1] hello world"
+
+ def test_producer_class(self):
+ p = py.log.Producer('x1')
+ l = []
+ py.log.setconsumer(p._keywords, l.append)
+ p("hello")
+ assert len(l) == 1
+ assert len(l[0].keywords) == 1
+ assert 'x1' == l[0].keywords[0]
+
+ def test_producer_caching(self):
+ p = py.log.Producer('x1')
+ x2 = p.x2
+ assert x2 is p.x2
+
+class TestLogConsumer:
+ def setup_method(self, meth):
+ default_keywordmapper.setstate(_oldstate)
+ def test_log_none(self):
+ log = py.log.Producer("XXX")
+ l = []
+ py.log.setconsumer('XXX', l.append)
+ log("1")
+ assert l
+ l[:] = []
+ py.log.setconsumer('XXX', None)
+ log("2")
+ assert not l
+
+ def test_log_default_stderr(self):
+ res, out, err = callcapture(py.log.Producer("default"), "hello")
+ assert err.strip() == "[default] hello"
+
+ def test_simple_consumer_match(self):
+ l = []
+ py.log.setconsumer("x1", l.append)
+ p = py.log.Producer("x1 x2")
+ p("hello")
+ assert l
+ assert l[0].content() == "hello"
+
+ def test_simple_consumer_match_2(self):
+ l = []
+ p = py.log.Producer("x1 x2")
+ py.log.setconsumer(p._keywords, l.append)
+ p("42")
+ assert l
+ assert l[0].content() == "42"
+
+ def test_no_auto_producer(self):
+ p = py.log.Producer('x')
+ py.test.raises(AttributeError, "p._x")
+ py.test.raises(AttributeError, "p.x_y")
+
+ def test_setconsumer_with_producer(self):
+ l = []
+ p = py.log.Producer("hello")
+ py.log.setconsumer(p, l.append)
+ p("world")
+ assert str(l[0]) == "[hello] world"
+
+ def test_multi_consumer(self):
+ l = []
+ py.log.setconsumer("x1", l.append)
+ py.log.setconsumer("x1 x2", None)
+ p = py.log.Producer("x1 x2")
+ p("hello")
+ assert not l
+ py.log.Producer("x1")("hello")
+ assert l
+ assert l[0].content() == "hello"
+
+ def test_log_stderr(self):
+ py.log.setconsumer("xyz", py.log.STDOUT)
+ res, out, err = callcapture(py.log.Producer("xyz"), "hello")
+ assert not err
+ assert out.strip() == '[xyz] hello'
+
+ def test_log_file(self, tmpdir):
+ customlog = tmpdir.join('log.out')
+ py.log.setconsumer("default", open(str(customlog), 'w', 1))
+ py.log.Producer("default")("hello world #1")
+ assert customlog.readlines() == ['[default] hello world #1\n']
+
+ py.log.setconsumer("default", py.log.Path(customlog, buffering=False))
+ py.log.Producer("default")("hello world #2")
+ res = customlog.readlines()
+ assert res == ['[default] hello world #2\n'] # no append by default!
+
+ def test_log_file_append_mode(self, tmpdir):
+ logfilefn = tmpdir.join('log_append.out')
+
+ # The append mode is on by default, so we don't need to specify it for File
+ py.log.setconsumer("default", py.log.Path(logfilefn, append=True,
+ buffering=0))
+ assert logfilefn.check()
+ py.log.Producer("default")("hello world #1")
+ lines = logfilefn.readlines()
+ assert lines == ['[default] hello world #1\n']
+ py.log.setconsumer("default", py.log.Path(logfilefn, append=True,
+ buffering=0))
+ py.log.Producer("default")("hello world #1")
+ lines = logfilefn.readlines()
+ assert lines == ['[default] hello world #1\n',
+ '[default] hello world #1\n']
+
+ def test_log_file_delayed_create(self, tmpdir):
+ logfilefn = tmpdir.join('log_create.out')
+
+ py.log.setconsumer("default", py.log.Path(logfilefn,
+ delayed_create=True, buffering=0))
+ assert not logfilefn.check()
+ py.log.Producer("default")("hello world #1")
+ lines = logfilefn.readlines()
+ assert lines == ['[default] hello world #1\n']
+
+ def test_keyword_based_log_files(self, tmpdir):
+ logfiles = []
+ keywords = 'k1 k2 k3'.split()
+ for key in keywords:
+ path = tmpdir.join(key)
+ py.log.setconsumer(key, py.log.Path(path, buffering=0))
+
+ py.log.Producer('k1')('1')
+ py.log.Producer('k2')('2')
+ py.log.Producer('k3')('3')
+
+ for key in keywords:
+ path = tmpdir.join(key)
+ assert path.read().strip() == '[%s] %s' % (key, key[-1])
+
+ # disabled for now; the syslog log file can usually be read only by root
+ # I manually inspected /var/log/messages and the entries were there
+ def no_test_log_syslog(self):
+ py.log.setconsumer("default", py.log.Syslog())
+ py.log.default("hello world #1")
+
+ # disabled for now until I figure out how to read entries in the
+ # Event Logs on Windows
+ # I manually inspected the Application Log and the entries were there
+ def no_test_log_winevent(self):
+ py.log.setconsumer("default", py.log.WinEvent())
+ py.log.default("hello world #1")
+
+ # disabled for now until I figure out how to properly pass the parameters
+ def no_test_log_email(self):
+ py.log.setconsumer("default", py.log.Email(mailhost="gheorghiu.net",
+ fromaddr="grig",
+ toaddrs="grig",
+ subject = "py.log email"))
+ py.log.default("hello world #1")
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/testing/log/test_warning.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/log/test_warning.py
new file mode 100644
index 00000000000..a460c319e87
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/log/test_warning.py
@@ -0,0 +1,86 @@
+import sys
+from distutils.version import LooseVersion
+
+import pytest
+
+import py
+
+mypath = py.path.local(__file__).new(ext=".py")
+
+
+win = sys.platform.startswith('win')
+pytestmark = pytest.mark.skipif(win and LooseVersion(pytest.__version__) >= LooseVersion('3.1'),
+ reason='apiwarn is not compatible with pytest >= 3.1 (#162)')
+
+
+@pytest.mark.xfail
+def test_forwarding_to_warnings_module():
+ pytest.deprecated_call(py.log._apiwarn, "1.3", "..")
+
+def test_apiwarn_functional(recwarn):
+ capture = py.io.StdCapture()
+ py.log._apiwarn("x.y.z", "something", stacklevel=1)
+ out, err = capture.reset()
+ py.builtin.print_("out", out)
+ py.builtin.print_("err", err)
+ assert err.find("x.y.z") != -1
+ lno = py.code.getrawcode(test_apiwarn_functional).co_firstlineno + 2
+ exp = "%s:%s" % (mypath, lno)
+ assert err.find(exp) != -1
+
+def test_stacklevel(recwarn):
+ def f():
+ py.log._apiwarn("x", "some", stacklevel=2)
+ # 3
+ # 4
+ capture = py.io.StdCapture()
+ f()
+ out, err = capture.reset()
+ lno = py.code.getrawcode(test_stacklevel).co_firstlineno + 6
+ warning = str(err)
+ assert warning.find(":%s" % lno) != -1
+
+def test_stacklevel_initpkg_with_resolve(testdir, recwarn):
+ testdir.makepyfile(modabc="""
+ import py
+ def f():
+ py.log._apiwarn("x", "some", stacklevel="apipkg123")
+ """)
+ testdir.makepyfile(apipkg123="""
+ def __getattr__():
+ import modabc
+ modabc.f()
+ """)
+ p = testdir.makepyfile("""
+ import apipkg123
+ apipkg123.__getattr__()
+ """)
+ capture = py.io.StdCapture()
+ p.pyimport()
+ out, err = capture.reset()
+ warning = str(err)
+ loc = 'test_stacklevel_initpkg_with_resolve.py:2'
+ assert warning.find(loc) != -1
+
+def test_stacklevel_initpkg_no_resolve(recwarn):
+ def f():
+ py.log._apiwarn("x", "some", stacklevel="apipkg")
+ capture = py.io.StdCapture()
+ f()
+ out, err = capture.reset()
+ lno = py.code.getrawcode(test_stacklevel_initpkg_no_resolve).co_firstlineno + 2
+ warning = str(err)
+ assert warning.find(":%s" % lno) != -1
+
+
+def test_function(recwarn):
+ capture = py.io.StdCapture()
+ py.log._apiwarn("x.y.z", "something", function=test_function)
+ out, err = capture.reset()
+ py.builtin.print_("out", out)
+ py.builtin.print_("err", err)
+ assert err.find("x.y.z") != -1
+ lno = py.code.getrawcode(test_function).co_firstlineno
+ exp = "%s:%s" % (mypath, lno)
+ assert err.find(exp) != -1
+
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/testing/path/common.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/path/common.py
new file mode 100644
index 00000000000..d69a1c39d09
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/path/common.py
@@ -0,0 +1,492 @@
+import py
+import sys
+
+import pytest
+
+class CommonFSTests(object):
+ def test_constructor_equality(self, path1):
+ p = path1.__class__(path1)
+ assert p == path1
+
+ def test_eq_nonstring(self, path1):
+ p1 = path1.join('sampledir')
+ p2 = path1.join('sampledir')
+ assert p1 == p2
+
+ def test_new_identical(self, path1):
+ assert path1 == path1.new()
+
+ def test_join(self, path1):
+ p = path1.join('sampledir')
+ strp = str(p)
+ assert strp.endswith('sampledir')
+ assert strp.startswith(str(path1))
+
+ def test_join_normalized(self, path1):
+ newpath = path1.join(path1.sep+'sampledir')
+ strp = str(newpath)
+ assert strp.endswith('sampledir')
+ assert strp.startswith(str(path1))
+ newpath = path1.join((path1.sep*2) + 'sampledir')
+ strp = str(newpath)
+ assert strp.endswith('sampledir')
+ assert strp.startswith(str(path1))
+
+ def test_join_noargs(self, path1):
+ newpath = path1.join()
+ assert path1 == newpath
+
+ def test_add_something(self, path1):
+ p = path1.join('sample')
+ p = p + 'dir'
+ assert p.check()
+ assert p.exists()
+ assert p.isdir()
+ assert not p.isfile()
+
+ def test_parts(self, path1):
+ newpath = path1.join('sampledir', 'otherfile')
+ par = newpath.parts()[-3:]
+ assert par == [path1, path1.join('sampledir'), newpath]
+
+ revpar = newpath.parts(reverse=True)[:3]
+ assert revpar == [newpath, path1.join('sampledir'), path1]
+
+ def test_common(self, path1):
+ other = path1.join('sampledir')
+ x = other.common(path1)
+ assert x == path1
+
+ #def test_parents_nonexisting_file(self, path1):
+ # newpath = path1 / 'dirnoexist' / 'nonexisting file'
+ # par = list(newpath.parents())
+ # assert par[:2] == [path1 / 'dirnoexist', path1]
+
+ def test_basename_checks(self, path1):
+ newpath = path1.join('sampledir')
+ assert newpath.check(basename='sampledir')
+ assert newpath.check(notbasename='xyz')
+ assert newpath.basename == 'sampledir'
+
+ def test_basename(self, path1):
+ newpath = path1.join('sampledir')
+ assert newpath.check(basename='sampledir')
+ assert newpath.basename, 'sampledir'
+
+ def test_dirname(self, path1):
+ newpath = path1.join('sampledir')
+ assert newpath.dirname == str(path1)
+
+ def test_dirpath(self, path1):
+ newpath = path1.join('sampledir')
+ assert newpath.dirpath() == path1
+
+ def test_dirpath_with_args(self, path1):
+ newpath = path1.join('sampledir')
+ assert newpath.dirpath('x') == path1.join('x')
+
+ def test_newbasename(self, path1):
+ newpath = path1.join('samplefile')
+ newbase = newpath.new(basename="samplefile2")
+ assert newbase.basename == "samplefile2"
+ assert newbase.dirpath() == newpath.dirpath()
+
+ def test_not_exists(self, path1):
+ assert not path1.join('does_not_exist').check()
+ assert path1.join('does_not_exist').check(exists=0)
+
+ def test_exists(self, path1):
+ assert path1.join("samplefile").check()
+ assert path1.join("samplefile").check(exists=1)
+ assert path1.join("samplefile").exists()
+ assert path1.join("samplefile").isfile()
+ assert not path1.join("samplefile").isdir()
+
+ def test_dir(self, path1):
+ #print repr(path1.join("sampledir"))
+ assert path1.join("sampledir").check(dir=1)
+ assert path1.join('samplefile').check(notdir=1)
+ assert not path1.join("samplefile").check(dir=1)
+ assert path1.join("samplefile").exists()
+ assert not path1.join("samplefile").isdir()
+ assert path1.join("samplefile").isfile()
+
+ def test_fnmatch_file(self, path1):
+ assert path1.join("samplefile").check(fnmatch='s*e')
+ assert path1.join("samplefile").fnmatch('s*e')
+ assert not path1.join("samplefile").fnmatch('s*x')
+ assert not path1.join("samplefile").check(fnmatch='s*x')
+
+ #def test_fnmatch_dir(self, path1):
+
+ # pattern = path1.sep.join(['s*file'])
+ # sfile = path1.join("samplefile")
+ # assert sfile.check(fnmatch=pattern)
+
+ def test_relto(self, path1):
+ l=path1.join("sampledir", "otherfile")
+ assert l.relto(path1) == l.sep.join(["sampledir", "otherfile"])
+ assert l.check(relto=path1)
+ assert path1.check(notrelto=l)
+ assert not path1.check(relto=l)
+
+ def test_bestrelpath(self, path1):
+ curdir = path1
+ sep = curdir.sep
+ s = curdir.bestrelpath(curdir)
+ assert s == "."
+ s = curdir.bestrelpath(curdir.join("hello", "world"))
+ assert s == "hello" + sep + "world"
+
+ s = curdir.bestrelpath(curdir.dirpath().join("sister"))
+ assert s == ".." + sep + "sister"
+ assert curdir.bestrelpath(curdir.dirpath()) == ".."
+
+ assert curdir.bestrelpath("hello") == "hello"
+
+ def test_relto_not_relative(self, path1):
+ l1=path1.join("bcde")
+ l2=path1.join("b")
+ assert not l1.relto(l2)
+ assert not l2.relto(l1)
+
+ @py.test.mark.xfail("sys.platform.startswith('java')")
+ def test_listdir(self, path1):
+ l = path1.listdir()
+ assert path1.join('sampledir') in l
+ assert path1.join('samplefile') in l
+ py.test.raises(py.error.ENOTDIR,
+ "path1.join('samplefile').listdir()")
+
+ def test_listdir_fnmatchstring(self, path1):
+ l = path1.listdir('s*dir')
+ assert len(l)
+ assert l[0], path1.join('sampledir')
+
+ def test_listdir_filter(self, path1):
+ l = path1.listdir(lambda x: x.check(dir=1))
+ assert path1.join('sampledir') in l
+ assert not path1.join('samplefile') in l
+
+ def test_listdir_sorted(self, path1):
+ l = path1.listdir(lambda x: x.check(basestarts="sample"), sort=True)
+ assert path1.join('sampledir') == l[0]
+ assert path1.join('samplefile') == l[1]
+ assert path1.join('samplepickle') == l[2]
+
+ def test_visit_nofilter(self, path1):
+ l = []
+ for i in path1.visit():
+ l.append(i.relto(path1))
+ assert "sampledir" in l
+ assert path1.sep.join(["sampledir", "otherfile"]) in l
+
+ def test_visit_norecurse(self, path1):
+ l = []
+ for i in path1.visit(None, lambda x: x.basename != "sampledir"):
+ l.append(i.relto(path1))
+ assert "sampledir" in l
+ assert not path1.sep.join(["sampledir", "otherfile"]) in l
+
+ @pytest.mark.parametrize('fil', ['*dir', u'*dir',
+ pytest.mark.skip("sys.version_info <"
+ " (3,6)")(b'*dir')])
+ def test_visit_filterfunc_is_string(self, path1, fil):
+ l = []
+ for i in path1.visit(fil):
+ l.append(i.relto(path1))
+ assert len(l), 2
+ assert "sampledir" in l
+ assert "otherdir" in l
+
+ @py.test.mark.xfail("sys.platform.startswith('java')")
+ def test_visit_ignore(self, path1):
+ p = path1.join('nonexisting')
+ assert list(p.visit(ignore=py.error.ENOENT)) == []
+
+ def test_visit_endswith(self, path1):
+ l = []
+ for i in path1.visit(lambda x: x.check(endswith="file")):
+ l.append(i.relto(path1))
+ assert path1.sep.join(["sampledir", "otherfile"]) in l
+ assert "samplefile" in l
+
+ def test_endswith(self, path1):
+ assert path1.check(notendswith='.py')
+ x = path1.join('samplefile')
+ assert x.check(endswith='file')
+
+ def test_cmp(self, path1):
+ path1 = path1.join('samplefile')
+ path2 = path1.join('samplefile2')
+ assert (path1 < path2) == ('samplefile' < 'samplefile2')
+ assert not (path1 < path1)
+
+ def test_simple_read(self, path1):
+ x = path1.join('samplefile').read('r')
+ assert x == 'samplefile\n'
+
+ def test_join_div_operator(self, path1):
+ newpath = path1 / '/sampledir' / '/test//'
+ newpath2 = path1.join('sampledir', 'test')
+ assert newpath == newpath2
+
+ def test_ext(self, path1):
+ newpath = path1.join('sampledir.ext')
+ assert newpath.ext == '.ext'
+ newpath = path1.join('sampledir')
+ assert not newpath.ext
+
+ def test_purebasename(self, path1):
+ newpath = path1.join('samplefile.py')
+ assert newpath.purebasename == 'samplefile'
+
+ def test_multiple_parts(self, path1):
+ newpath = path1.join('samplefile.py')
+ dirname, purebasename, basename, ext = newpath._getbyspec(
+ 'dirname,purebasename,basename,ext')
+ assert str(path1).endswith(dirname) # be careful with win32 'drive'
+ assert purebasename == 'samplefile'
+ assert basename == 'samplefile.py'
+ assert ext == '.py'
+
+ def test_dotted_name_ext(self, path1):
+ newpath = path1.join('a.b.c')
+ ext = newpath.ext
+ assert ext == '.c'
+ assert newpath.ext == '.c'
+
+ def test_newext(self, path1):
+ newpath = path1.join('samplefile.py')
+ newext = newpath.new(ext='.txt')
+ assert newext.basename == "samplefile.txt"
+ assert newext.purebasename == "samplefile"
+
+ def test_readlines(self, path1):
+ fn = path1.join('samplefile')
+ contents = fn.readlines()
+ assert contents == ['samplefile\n']
+
+ def test_readlines_nocr(self, path1):
+ fn = path1.join('samplefile')
+ contents = fn.readlines(cr=0)
+ assert contents == ['samplefile', '']
+
+ def test_file(self, path1):
+ assert path1.join('samplefile').check(file=1)
+
+ def test_not_file(self, path1):
+ assert not path1.join("sampledir").check(file=1)
+ assert path1.join("sampledir").check(file=0)
+
+ def test_non_existent(self, path1):
+ assert path1.join("sampledir.nothere").check(dir=0)
+ assert path1.join("sampledir.nothere").check(file=0)
+ assert path1.join("sampledir.nothere").check(notfile=1)
+ assert path1.join("sampledir.nothere").check(notdir=1)
+ assert path1.join("sampledir.nothere").check(notexists=1)
+ assert not path1.join("sampledir.nothere").check(notfile=0)
+
+ # pattern = path1.sep.join(['s*file'])
+ # sfile = path1.join("samplefile")
+ # assert sfile.check(fnmatch=pattern)
+
+ def test_size(self, path1):
+ url = path1.join("samplefile")
+ assert url.size() > len("samplefile")
+
+ def test_mtime(self, path1):
+ url = path1.join("samplefile")
+ assert url.mtime() > 0
+
+ def test_relto_wrong_type(self, path1):
+ py.test.raises(TypeError, "path1.relto(42)")
+
+ def test_load(self, path1):
+ p = path1.join('samplepickle')
+ obj = p.load()
+ assert type(obj) is dict
+ assert obj.get('answer',None) == 42
+
+ def test_visit_filesonly(self, path1):
+ l = []
+ for i in path1.visit(lambda x: x.check(file=1)):
+ l.append(i.relto(path1))
+ assert not "sampledir" in l
+ assert path1.sep.join(["sampledir", "otherfile"]) in l
+
+ def test_visit_nodotfiles(self, path1):
+ l = []
+ for i in path1.visit(lambda x: x.check(dotfile=0)):
+ l.append(i.relto(path1))
+ assert "sampledir" in l
+ assert path1.sep.join(["sampledir", "otherfile"]) in l
+ assert not ".dotfile" in l
+
+ def test_visit_breadthfirst(self, path1):
+ l = []
+ for i in path1.visit(bf=True):
+ l.append(i.relto(path1))
+ for i, p in enumerate(l):
+ if path1.sep in p:
+ for j in range(i, len(l)):
+ assert path1.sep in l[j]
+ break
+ else:
+ py.test.fail("huh")
+
+ def test_visit_sort(self, path1):
+ l = []
+ for i in path1.visit(bf=True, sort=True):
+ l.append(i.relto(path1))
+ for i, p in enumerate(l):
+ if path1.sep in p:
+ break
+ assert l[:i] == sorted(l[:i])
+ assert l[i:] == sorted(l[i:])
+
+ def test_endswith(self, path1):
+ def chk(p):
+ return p.check(endswith="pickle")
+ assert not chk(path1)
+ assert not chk(path1.join('samplefile'))
+ assert chk(path1.join('somepickle'))
+
+ def test_copy_file(self, path1):
+ otherdir = path1.join('otherdir')
+ initpy = otherdir.join('__init__.py')
+ copied = otherdir.join('copied')
+ initpy.copy(copied)
+ try:
+ assert copied.check()
+ s1 = initpy.read()
+ s2 = copied.read()
+ assert s1 == s2
+ finally:
+ if copied.check():
+ copied.remove()
+
+ def test_copy_dir(self, path1):
+ otherdir = path1.join('otherdir')
+ copied = path1.join('newdir')
+ try:
+ otherdir.copy(copied)
+ assert copied.check(dir=1)
+ assert copied.join('__init__.py').check(file=1)
+ s1 = otherdir.join('__init__.py').read()
+ s2 = copied.join('__init__.py').read()
+ assert s1 == s2
+ finally:
+ if copied.check(dir=1):
+ copied.remove(rec=1)
+
+ def test_remove_file(self, path1):
+ d = path1.ensure('todeleted')
+ assert d.check()
+ d.remove()
+ assert not d.check()
+
+ def test_remove_dir_recursive_by_default(self, path1):
+ d = path1.ensure('to', 'be', 'deleted')
+ assert d.check()
+ p = path1.join('to')
+ p.remove()
+ assert not p.check()
+
+ def test_ensure_dir(self, path1):
+ b = path1.ensure_dir("001", "002")
+ assert b.basename == "002"
+ assert b.isdir()
+
+ def test_mkdir_and_remove(self, path1):
+ tmpdir = path1
+ py.test.raises(py.error.EEXIST, tmpdir.mkdir, 'sampledir')
+ new = tmpdir.join('mktest1')
+ new.mkdir()
+ assert new.check(dir=1)
+ new.remove()
+
+ new = tmpdir.mkdir('mktest')
+ assert new.check(dir=1)
+ new.remove()
+ assert tmpdir.join('mktest') == new
+
+ def test_move_file(self, path1):
+ p = path1.join('samplefile')
+ newp = p.dirpath('moved_samplefile')
+ p.move(newp)
+ try:
+ assert newp.check(file=1)
+ assert not p.check()
+ finally:
+ dp = newp.dirpath()
+ if hasattr(dp, 'revert'):
+ dp.revert()
+ else:
+ newp.move(p)
+ assert p.check()
+
+ def test_move_dir(self, path1):
+ source = path1.join('sampledir')
+ dest = path1.join('moveddir')
+ source.move(dest)
+ assert dest.check(dir=1)
+ assert dest.join('otherfile').check(file=1)
+ assert not source.join('sampledir').check()
+
+ def test_fspath_protocol_match_strpath(self, path1):
+ assert path1.__fspath__() == path1.strpath
+
+ def test_fspath_func_match_strpath(self, path1):
+ try:
+ from os import fspath
+ except ImportError:
+ from py._path.common import fspath
+ assert fspath(path1) == path1.strpath
+
+ @py.test.mark.skip("sys.version_info < (3,6)")
+ def test_fspath_open(self, path1):
+ f = path1.join('opentestfile')
+ open(f)
+
+ @py.test.mark.skip("sys.version_info < (3,6)")
+ def test_fspath_fsencode(self, path1):
+ from os import fsencode
+ assert fsencode(path1) == fsencode(path1.strpath)
+
+def setuptestfs(path):
+ if path.join('samplefile').check():
+ return
+ #print "setting up test fs for", repr(path)
+ samplefile = path.ensure('samplefile')
+ samplefile.write('samplefile\n')
+
+ execfile = path.ensure('execfile')
+ execfile.write('x=42')
+
+ execfilepy = path.ensure('execfile.py')
+ execfilepy.write('x=42')
+
+ d = {1:2, 'hello': 'world', 'answer': 42}
+ path.ensure('samplepickle').dump(d)
+
+ sampledir = path.ensure('sampledir', dir=1)
+ sampledir.ensure('otherfile')
+
+ otherdir = path.ensure('otherdir', dir=1)
+ otherdir.ensure('__init__.py')
+
+ module_a = otherdir.ensure('a.py')
+ module_a.write('from .b import stuff as result\n')
+ module_b = otherdir.ensure('b.py')
+ module_b.write('stuff="got it"\n')
+ module_c = otherdir.ensure('c.py')
+ module_c.write('''import py;
+import otherdir.a
+value = otherdir.a.result
+''')
+ module_d = otherdir.ensure('d.py')
+ module_d.write('''import py;
+from otherdir import a
+value2 = a.result
+''')
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/testing/path/conftest.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/path/conftest.py
new file mode 100644
index 00000000000..84fb5c82694
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/path/conftest.py
@@ -0,0 +1,80 @@
+import py
+import sys
+from py._path import svnwc as svncommon
+
+svnbin = py.path.local.sysfind('svn')
+repodump = py.path.local(__file__).dirpath('repotest.dump')
+from py.builtin import print_
+
+def pytest_funcarg__repowc1(request):
+ if svnbin is None:
+ py.test.skip("svn binary not found")
+
+ tmpdir = request.getfuncargvalue("tmpdir")
+ repo, repourl, wc = request.cached_setup(
+ setup=lambda: getrepowc(tmpdir, "path1repo", "path1wc"),
+ scope="module",
+ )
+ for x in ('test_remove', 'test_move', 'test_status_deleted'):
+ if request.function.__name__.startswith(x):
+ #print >>sys.stderr, ("saving repo", repo, "for", request.function)
+ _savedrepowc = save_repowc(repo, wc)
+ request.addfinalizer(lambda: restore_repowc(_savedrepowc))
+ return repo, repourl, wc
+
+def pytest_funcarg__repowc2(request):
+ tmpdir = request.getfuncargvalue("tmpdir")
+ name = request.function.__name__
+ repo, url, wc = getrepowc(tmpdir, "%s-repo-2" % name, "%s-wc-2" % name)
+ return repo, url, wc
+
+def getsvnbin():
+ if svnbin is None:
+ py.test.skip("svn binary not found")
+ return svnbin
+
+# make a wc directory out of a given root url
+# cache previously obtained wcs!
+#
+def getrepowc(tmpdir, reponame='basetestrepo', wcname='wc'):
+ repo = tmpdir.mkdir(reponame)
+ wcdir = tmpdir.mkdir(wcname)
+ repo.ensure(dir=1)
+ py.process.cmdexec('svnadmin create "%s"' %
+ svncommon._escape_helper(repo))
+ py.process.cmdexec('svnadmin load -q "%s" <"%s"' %
+ (svncommon._escape_helper(repo), repodump))
+ print_("created svn repository", repo)
+ wcdir.ensure(dir=1)
+ wc = py.path.svnwc(wcdir)
+ if sys.platform == 'win32':
+ repourl = "file://" + '/' + str(repo).replace('\\', '/')
+ else:
+ repourl = "file://%s" % repo
+ wc.checkout(repourl)
+ print_("checked out new repo into", wc)
+ return (repo, repourl, wc)
+
+
+def save_repowc(repo, wc):
+ assert not str(repo).startswith("file://"), repo
+ assert repo.check()
+ savedrepo = repo.dirpath(repo.basename+".1")
+ savedwc = wc.dirpath(wc.basename+".1")
+ repo.copy(savedrepo)
+ wc.localpath.copy(savedwc.localpath)
+ return savedrepo, savedwc
+
+def restore_repowc(obj):
+ savedrepo, savedwc = obj
+ #print >>sys.stderr, ("restoring", savedrepo)
+ repo = savedrepo.new(basename=savedrepo.basename[:-2])
+ assert repo.check()
+ wc = savedwc.new(basename=savedwc.basename[:-2])
+ assert wc.check()
+ wc.localpath.remove()
+ repo.remove()
+ savedrepo.move(repo)
+ savedwc.localpath.move(wc.localpath)
+ py.path.svnurl._lsnorevcache.clear()
+ py.path.svnurl._lsrevcache.clear()
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/path/repotest.dump b/tests/wpt/web-platform-tests/tools/third_party/py/testing/path/repotest.dump
index c7819cad7a5..c7819cad7a5 100644
--- a/tests/wpt/web-platform-tests/tools/py/testing/path/repotest.dump
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/path/repotest.dump
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/path/svntestbase.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/path/svntestbase.py
index 8d94a9ca649..8d94a9ca649 100644
--- a/tests/wpt/web-platform-tests/tools/py/testing/path/svntestbase.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/path/svntestbase.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/testing/path/test_cacheutil.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/path/test_cacheutil.py
new file mode 100644
index 00000000000..c9fc07463a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/path/test_cacheutil.py
@@ -0,0 +1,89 @@
+import pytest
+from py._path import cacheutil
+
+import time
+
+class BasicCacheAPITest:
+ cache = None
+ def test_getorbuild(self):
+ val = self.cache.getorbuild(-42, lambda: 42)
+ assert val == 42
+ val = self.cache.getorbuild(-42, lambda: 23)
+ assert val == 42
+
+ def test_cache_get_key_error(self):
+ pytest.raises(KeyError, "self.cache._getentry(-23)")
+
+ def test_delentry_non_raising(self):
+ self.cache.getorbuild(100, lambda: 100)
+ self.cache.delentry(100)
+ pytest.raises(KeyError, "self.cache._getentry(100)")
+
+ def test_delentry_raising(self):
+ self.cache.getorbuild(100, lambda: 100)
+ self.cache.delentry(100)
+ pytest.raises(KeyError, self.cache.delentry, 100, raising=True)
+
+ def test_clear(self):
+ self.cache.clear()
+
+
+class TestBuildcostAccess(BasicCacheAPITest):
+ cache = cacheutil.BuildcostAccessCache(maxentries=128)
+
+ def test_cache_works_somewhat_simple(self, monkeypatch):
+ cache = cacheutil.BuildcostAccessCache()
+ # the default gettime
+ # BuildcostAccessCache.build can
+ # result into time()-time() == 0 which makes the below
+ # test fail randomly. Let's rather use incrementing
+ # numbers instead.
+ l = [0]
+
+ def counter():
+ l[0] = l[0] + 1
+ return l[0]
+ monkeypatch.setattr(cacheutil, 'gettime', counter)
+ for x in range(cache.maxentries):
+ y = cache.getorbuild(x, lambda: x)
+ assert x == y
+ for x in range(cache.maxentries):
+ assert cache.getorbuild(x, None) == x
+ halfentries = int(cache.maxentries / 2)
+ for x in range(halfentries):
+ assert cache.getorbuild(x, None) == x
+ assert cache.getorbuild(x, None) == x
+ # evict one entry
+ val = cache.getorbuild(-1, lambda: 42)
+ assert val == 42
+ # check that recently used ones are still there
+ # and are not build again
+ for x in range(halfentries):
+ assert cache.getorbuild(x, None) == x
+ assert cache.getorbuild(-1, None) == 42
+
+
+class TestAging(BasicCacheAPITest):
+ maxsecs = 0.10
+ cache = cacheutil.AgingCache(maxentries=128, maxseconds=maxsecs)
+
+ def test_cache_eviction(self):
+ self.cache.getorbuild(17, lambda: 17)
+ endtime = time.time() + self.maxsecs * 10
+ while time.time() < endtime:
+ try:
+ self.cache._getentry(17)
+ except KeyError:
+ break
+ time.sleep(self.maxsecs*0.3)
+ else:
+ pytest.fail("waiting for cache eviction failed")
+
+
+def test_prune_lowestweight():
+ maxsecs = 0.05
+ cache = cacheutil.AgingCache(maxentries=10, maxseconds=maxsecs)
+ for x in range(cache.maxentries):
+ cache.getorbuild(x, lambda: x)
+ time.sleep(maxsecs*1.1)
+ cache.getorbuild(cache.maxentries+1, lambda: 42)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/testing/path/test_local.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/path/test_local.py
new file mode 100644
index 00000000000..c9075d6fbb4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/path/test_local.py
@@ -0,0 +1,977 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import with_statement
+import time
+import py
+import pytest
+import os
+import sys
+import multiprocessing
+from py.path import local
+import common
+
+failsonjython = py.test.mark.xfail("sys.platform.startswith('java')")
+failsonjywin32 = py.test.mark.xfail(
+ "sys.platform.startswith('java') "
+ "and getattr(os, '_name', None) == 'nt'")
+win32only = py.test.mark.skipif(
+ "not (sys.platform == 'win32' or getattr(os, '_name', None) == 'nt')")
+skiponwin32 = py.test.mark.skipif(
+ "sys.platform == 'win32' or getattr(os, '_name', None) == 'nt'")
+
+ATIME_RESOLUTION = 0.01
+
+
+@pytest.yield_fixture(scope="session")
+def path1(tmpdir_factory):
+ path = tmpdir_factory.mktemp('path')
+ common.setuptestfs(path)
+ yield path
+ assert path.join("samplefile").check()
+
+
+@pytest.fixture
+def fake_fspath_obj(request):
+ class FakeFSPathClass(object):
+ def __init__(self, path):
+ self._path = path
+
+ def __fspath__(self):
+ return self._path
+
+ return FakeFSPathClass(os.path.join("this", "is", "a", "fake", "path"))
+
+
+def batch_make_numbered_dirs(rootdir, repeats):
+ try:
+ for i in range(repeats):
+ dir_ = py.path.local.make_numbered_dir(prefix='repro-', rootdir=rootdir)
+ file_ = dir_.join('foo')
+ file_.write('%s' % i)
+ actual = int(file_.read())
+ assert actual == i, 'int(file_.read()) is %s instead of %s' % (actual, i)
+ dir_.join('.lock').remove(ignore_errors=True)
+ return True
+ except KeyboardInterrupt:
+ # makes sure that interrupting test session won't hang it
+ os.exit(2)
+
+
+class TestLocalPath(common.CommonFSTests):
+ def test_join_normpath(self, tmpdir):
+ assert tmpdir.join(".") == tmpdir
+ p = tmpdir.join("../%s" % tmpdir.basename)
+ assert p == tmpdir
+ p = tmpdir.join("..//%s/" % tmpdir.basename)
+ assert p == tmpdir
+
+ @skiponwin32
+ def test_dirpath_abs_no_abs(self, tmpdir):
+ p = tmpdir.join('foo')
+ assert p.dirpath('/bar') == tmpdir.join('bar')
+ assert tmpdir.dirpath('/bar', abs=True) == local('/bar')
+
+ def test_gethash(self, tmpdir):
+ md5 = py.builtin._tryimport('md5', 'hashlib').md5
+ lib = py.builtin._tryimport('sha', 'hashlib')
+ sha = getattr(lib, 'sha1', getattr(lib, 'sha', None))
+ fn = tmpdir.join("testhashfile")
+ data = 'hello'.encode('ascii')
+ fn.write(data, mode="wb")
+ assert fn.computehash("md5") == md5(data).hexdigest()
+ assert fn.computehash("sha1") == sha(data).hexdigest()
+ py.test.raises(ValueError, fn.computehash, "asdasd")
+
+ def test_remove_removes_readonly_file(self, tmpdir):
+ readonly_file = tmpdir.join('readonly').ensure()
+ readonly_file.chmod(0)
+ readonly_file.remove()
+ assert not readonly_file.check(exists=1)
+
+ def test_remove_removes_readonly_dir(self, tmpdir):
+ readonly_dir = tmpdir.join('readonlydir').ensure(dir=1)
+ readonly_dir.chmod(int("500", 8))
+ readonly_dir.remove()
+ assert not readonly_dir.check(exists=1)
+
+ def test_remove_removes_dir_and_readonly_file(self, tmpdir):
+ readonly_dir = tmpdir.join('readonlydir').ensure(dir=1)
+ readonly_file = readonly_dir.join('readonlyfile').ensure()
+ readonly_file.chmod(0)
+ readonly_dir.remove()
+ assert not readonly_dir.check(exists=1)
+
+ def test_remove_routes_ignore_errors(self, tmpdir, monkeypatch):
+ l = []
+ monkeypatch.setattr(
+ 'shutil.rmtree',
+ lambda *args, **kwargs: l.append(kwargs))
+ tmpdir.remove()
+ assert not l[0]['ignore_errors']
+ for val in (True, False):
+ l[:] = []
+ tmpdir.remove(ignore_errors=val)
+ assert l[0]['ignore_errors'] == val
+
+ def test_initialize_curdir(self):
+ assert str(local()) == os.getcwd()
+
+ @skiponwin32
+ def test_chdir_gone(self, path1):
+ p = path1.ensure("dir_to_be_removed", dir=1)
+ p.chdir()
+ p.remove()
+ pytest.raises(py.error.ENOENT, py.path.local)
+ assert path1.chdir() is None
+ assert os.getcwd() == str(path1)
+
+ def test_as_cwd(self, path1):
+ dir = path1.ensure("subdir", dir=1)
+ old = py.path.local()
+ with dir.as_cwd() as x:
+ assert x == old
+ assert py.path.local() == dir
+ assert os.getcwd() == str(old)
+
+ def test_as_cwd_exception(self, path1):
+ old = py.path.local()
+ dir = path1.ensure("subdir", dir=1)
+ with pytest.raises(ValueError):
+ with dir.as_cwd():
+ raise ValueError()
+ assert old == py.path.local()
+
+ def test_initialize_reldir(self, path1):
+ with path1.as_cwd():
+ p = local('samplefile')
+ assert p.check()
+
+ def test_tilde_expansion(self, monkeypatch, tmpdir):
+ monkeypatch.setenv("HOME", str(tmpdir))
+ p = py.path.local("~", expanduser=True)
+ assert p == os.path.expanduser("~")
+
+ def test_eq_with_strings(self, path1):
+ path1 = path1.join('sampledir')
+ path2 = str(path1)
+ assert path1 == path2
+ assert path2 == path1
+ path3 = path1.join('samplefile')
+ assert path3 != path2
+ assert path2 != path3
+
+ def test_eq_with_none(self, path1):
+ assert path1 != None # noqa
+
+ def test_eq_non_ascii_unicode(self, path1):
+ path2 = path1.join(u'temp')
+ path3 = path1.join(u'ação')
+ path4 = path1.join(u'ディレクトリ')
+
+ assert path2 != path3
+ assert path2 != path4
+ assert path4 != path3
+
+ def test_gt_with_strings(self, path1):
+ path2 = path1.join('sampledir')
+ path3 = str(path1.join("ttt"))
+ assert path3 > path2
+ assert path2 < path3
+ assert path2 < "ttt"
+ assert "ttt" > path2
+ path4 = path1.join("aaa")
+ l = [path2, path4, path3]
+ assert sorted(l) == [path4, path2, path3]
+
+ def test_open_and_ensure(self, path1):
+ p = path1.join("sub1", "sub2", "file")
+ with p.open("w", ensure=1) as f:
+ f.write("hello")
+ assert p.read() == "hello"
+
+ def test_write_and_ensure(self, path1):
+ p = path1.join("sub1", "sub2", "file")
+ p.write("hello", ensure=1)
+ assert p.read() == "hello"
+
+ @py.test.mark.parametrize('bin', (False, True))
+ def test_dump(self, tmpdir, bin):
+ path = tmpdir.join("dumpfile%s" % int(bin))
+ try:
+ d = {'answer': 42}
+ path.dump(d, bin=bin)
+ f = path.open('rb+')
+ import pickle
+ dnew = pickle.load(f)
+ assert d == dnew
+ finally:
+ f.close()
+
+ @failsonjywin32
+ def test_setmtime(self):
+ import tempfile
+ import time
+ try:
+ fd, name = tempfile.mkstemp()
+ os.close(fd)
+ except AttributeError:
+ name = tempfile.mktemp()
+ open(name, 'w').close()
+ try:
+ mtime = int(time.time())-100
+ path = local(name)
+ assert path.mtime() != mtime
+ path.setmtime(mtime)
+ assert path.mtime() == mtime
+ path.setmtime()
+ assert path.mtime() != mtime
+ finally:
+ os.remove(name)
+
+ def test_normpath(self, path1):
+ new1 = path1.join("/otherdir")
+ new2 = path1.join("otherdir")
+ assert str(new1) == str(new2)
+
+ def test_mkdtemp_creation(self):
+ d = local.mkdtemp()
+ try:
+ assert d.check(dir=1)
+ finally:
+ d.remove(rec=1)
+
+ def test_tmproot(self):
+ d = local.mkdtemp()
+ tmproot = local.get_temproot()
+ try:
+ assert d.check(dir=1)
+ assert d.dirpath() == tmproot
+ finally:
+ d.remove(rec=1)
+
+ def test_chdir(self, tmpdir):
+ old = local()
+ try:
+ res = tmpdir.chdir()
+ assert str(res) == str(old)
+ assert os.getcwd() == str(tmpdir)
+ finally:
+ old.chdir()
+
+ def test_ensure_filepath_withdir(self, tmpdir):
+ newfile = tmpdir.join('test1', 'test')
+ newfile.ensure()
+ assert newfile.check(file=1)
+ newfile.write("42")
+ newfile.ensure()
+ s = newfile.read()
+ assert s == "42"
+
+ def test_ensure_filepath_withoutdir(self, tmpdir):
+ newfile = tmpdir.join('test1file')
+ t = newfile.ensure()
+ assert t == newfile
+ assert newfile.check(file=1)
+
+ def test_ensure_dirpath(self, tmpdir):
+ newfile = tmpdir.join('test1', 'testfile')
+ t = newfile.ensure(dir=1)
+ assert t == newfile
+ assert newfile.check(dir=1)
+
+ def test_ensure_non_ascii_unicode(self, tmpdir):
+ newfile = tmpdir.join(u'ação',u'ディレクトリ')
+ t = newfile.ensure(dir=1)
+ assert t == newfile
+ assert newfile.check(dir=1)
+
+ def test_init_from_path(self, tmpdir):
+ l = local()
+ l2 = local(l)
+ assert l2 == l
+
+ wc = py.path.svnwc('.')
+ l3 = local(wc)
+ assert l3 is not wc
+ assert l3.strpath == wc.strpath
+ assert not hasattr(l3, 'commit')
+
+ @py.test.mark.xfail(run=False, reason="unreliable est for long filenames")
+ def test_long_filenames(self, tmpdir):
+ if sys.platform == "win32":
+ py.test.skip("win32: work around needed for path length limit")
+ # see http://codespeak.net/pipermail/py-dev/2008q2/000922.html
+
+ # testing paths > 260 chars (which is Windows' limitation, but
+ # depending on how the paths are used), but > 4096 (which is the
+ # Linux' limitation) - the behaviour of paths with names > 4096 chars
+ # is undetermined
+ newfilename = '/test' * 60
+ l = tmpdir.join(newfilename)
+ l.ensure(file=True)
+ l.write('foo')
+ l2 = tmpdir.join(newfilename)
+ assert l2.read() == 'foo'
+
+ def test_visit_depth_first(self, tmpdir):
+ tmpdir.ensure("a", "1")
+ tmpdir.ensure("b", "2")
+ p3 = tmpdir.ensure("breadth")
+ l = list(tmpdir.visit(lambda x: x.check(file=1)))
+ assert len(l) == 3
+ # check that breadth comes last
+ assert l[2] == p3
+
+ def test_visit_rec_fnmatch(self, tmpdir):
+ p1 = tmpdir.ensure("a", "123")
+ tmpdir.ensure(".b", "345")
+ l = list(tmpdir.visit("???", rec="[!.]*"))
+ assert len(l) == 1
+ # check that breadth comes last
+ assert l[0] == p1
+
+ def test_fnmatch_file_abspath(self, tmpdir):
+ b = tmpdir.join("a", "b")
+ assert b.fnmatch(os.sep.join("ab"))
+ pattern = os.sep.join([str(tmpdir), "*", "b"])
+ assert b.fnmatch(pattern)
+
+ def test_sysfind(self):
+ name = sys.platform == "win32" and "cmd" or "test"
+ x = py.path.local.sysfind(name)
+ assert x.check(file=1)
+ assert py.path.local.sysfind('jaksdkasldqwe') is None
+ assert py.path.local.sysfind(name, paths=[]) is None
+ x2 = py.path.local.sysfind(name, paths=[x.dirpath()])
+ assert x2 == x
+
+ def test_fspath_protocol_other_class(self, fake_fspath_obj):
+ # py.path is always absolute
+ py_path = py.path.local(fake_fspath_obj)
+ str_path = fake_fspath_obj.__fspath__()
+ assert py_path.check(endswith=str_path)
+ assert py_path.join(fake_fspath_obj).strpath == os.path.join(
+ py_path.strpath, str_path)
+
+ def test_make_numbered_dir_multiprocess_safe(self, tmpdir):
+ # https://github.com/pytest-dev/py/issues/30
+ pool = multiprocessing.Pool()
+ results = [pool.apply_async(batch_make_numbered_dirs, [tmpdir, 100]) for _ in range(20)]
+ for r in results:
+ assert r.get()
+
+
+class TestExecutionOnWindows:
+ pytestmark = win32only
+
+ def test_sysfind_bat_exe_before(self, tmpdir, monkeypatch):
+ monkeypatch.setenv("PATH", str(tmpdir), prepend=os.pathsep)
+ tmpdir.ensure("hello")
+ h = tmpdir.ensure("hello.bat")
+ x = py.path.local.sysfind("hello")
+ assert x == h
+
+
+class TestExecution:
+ pytestmark = skiponwin32
+
+ def test_sysfind_no_permisson_ignored(self, monkeypatch, tmpdir):
+ noperm = tmpdir.ensure('noperm', dir=True)
+ monkeypatch.setenv("PATH", noperm, prepend=":")
+ noperm.chmod(0)
+ assert py.path.local.sysfind('jaksdkasldqwe') is None
+
+ def test_sysfind_absolute(self):
+ x = py.path.local.sysfind('test')
+ assert x.check(file=1)
+ y = py.path.local.sysfind(str(x))
+ assert y.check(file=1)
+ assert y == x
+
+ def test_sysfind_multiple(self, tmpdir, monkeypatch):
+ monkeypatch.setenv('PATH', "%s:%s" % (
+ tmpdir.ensure('a'),
+ tmpdir.join('b')),
+ prepend=":")
+ tmpdir.ensure('b', 'a')
+ x = py.path.local.sysfind(
+ 'a', checker=lambda x: x.dirpath().basename == 'b')
+ assert x.basename == 'a'
+ assert x.dirpath().basename == 'b'
+ assert py.path.local.sysfind('a', checker=lambda x: None) is None
+
+ def test_sysexec(self):
+ x = py.path.local.sysfind('ls')
+ out = x.sysexec('-a')
+ for x in py.path.local().listdir():
+ assert out.find(x.basename) != -1
+
+ def test_sysexec_failing(self):
+ x = py.path.local.sysfind('false')
+ with pytest.raises(py.process.cmdexec.Error):
+ x.sysexec('aksjdkasjd')
+
+ def test_make_numbered_dir(self, tmpdir):
+ tmpdir.ensure('base.not_an_int', dir=1)
+ for i in range(10):
+ numdir = local.make_numbered_dir(prefix='base.', rootdir=tmpdir,
+ keep=2, lock_timeout=0)
+ assert numdir.check()
+ assert numdir.basename == 'base.%d' % i
+ if i >= 1:
+ assert numdir.new(ext=str(i-1)).check()
+ if i >= 2:
+ assert numdir.new(ext=str(i-2)).check()
+ if i >= 3:
+ assert not numdir.new(ext=str(i-3)).check()
+
+ def test_make_numbered_dir_case_insensitive(self, tmpdir, monkeypatch):
+ # https://github.com/pytest-dev/pytest/issues/708
+ monkeypatch.setattr(py._path.local, 'normcase',
+ lambda path: path.lower())
+ monkeypatch.setattr(tmpdir, 'listdir',
+ lambda: [tmpdir._fastjoin('case.0')])
+ numdir = local.make_numbered_dir(prefix='CAse.', rootdir=tmpdir,
+ keep=2, lock_timeout=0)
+ assert numdir.basename.endswith('.1')
+
+ def test_make_numbered_dir_case_sensitive(self, tmpdir, monkeypatch):
+ # https://github.com/pytest-dev/pytest/issues/708
+ monkeypatch.setattr(py._path.local, 'normcase', lambda path: path)
+ monkeypatch.setattr(tmpdir, 'listdir',
+ lambda: [tmpdir._fastjoin('case.0')])
+ numdir = local.make_numbered_dir(prefix='CAse.', rootdir=tmpdir,
+ keep=2, lock_timeout=0)
+ assert numdir.basename.endswith('.0')
+
+ def test_make_numbered_dir_NotImplemented_Error(self, tmpdir, monkeypatch):
+ def notimpl(x, y):
+ raise NotImplementedError(42)
+ monkeypatch.setattr(os, 'symlink', notimpl)
+ x = tmpdir.make_numbered_dir(rootdir=tmpdir, lock_timeout=0)
+ assert x.relto(tmpdir)
+ assert x.check()
+
+ def test_locked_make_numbered_dir(self, tmpdir):
+ for i in range(10):
+ numdir = local.make_numbered_dir(prefix='base2.', rootdir=tmpdir,
+ keep=2)
+ assert numdir.check()
+ assert numdir.basename == 'base2.%d' % i
+ for j in range(i):
+ assert numdir.new(ext=str(j)).check()
+
+ def test_error_preservation(self, path1):
+ py.test.raises(EnvironmentError, path1.join('qwoeqiwe').mtime)
+ py.test.raises(EnvironmentError, path1.join('qwoeqiwe').read)
+
+ # def test_parentdirmatch(self):
+ # local.parentdirmatch('std', startmodule=__name__)
+ #
+
+
+class TestImport:
+ def test_pyimport(self, path1):
+ obj = path1.join('execfile.py').pyimport()
+ assert obj.x == 42
+ assert obj.__name__ == 'execfile'
+
+ def test_pyimport_renamed_dir_creates_mismatch(self, tmpdir):
+ p = tmpdir.ensure("a", "test_x123.py")
+ p.pyimport()
+ tmpdir.join("a").move(tmpdir.join("b"))
+ with pytest.raises(tmpdir.ImportMismatchError):
+ tmpdir.join("b", "test_x123.py").pyimport()
+
+ def test_pyimport_messy_name(self, tmpdir):
+ # http://bitbucket.org/hpk42/py-trunk/issue/129
+ path = tmpdir.ensure('foo__init__.py')
+ path.pyimport()
+
+ def test_pyimport_dir(self, tmpdir):
+ p = tmpdir.join("hello_123")
+ p_init = p.ensure("__init__.py")
+ m = p.pyimport()
+ assert m.__name__ == "hello_123"
+ m = p_init.pyimport()
+ assert m.__name__ == "hello_123"
+
+ def test_pyimport_execfile_different_name(self, path1):
+ obj = path1.join('execfile.py').pyimport(modname="0x.y.z")
+ assert obj.x == 42
+ assert obj.__name__ == '0x.y.z'
+
+ def test_pyimport_a(self, path1):
+ otherdir = path1.join('otherdir')
+ mod = otherdir.join('a.py').pyimport()
+ assert mod.result == "got it"
+ assert mod.__name__ == 'otherdir.a'
+
+ def test_pyimport_b(self, path1):
+ otherdir = path1.join('otherdir')
+ mod = otherdir.join('b.py').pyimport()
+ assert mod.stuff == "got it"
+ assert mod.__name__ == 'otherdir.b'
+
+ def test_pyimport_c(self, path1):
+ otherdir = path1.join('otherdir')
+ mod = otherdir.join('c.py').pyimport()
+ assert mod.value == "got it"
+
+ def test_pyimport_d(self, path1):
+ otherdir = path1.join('otherdir')
+ mod = otherdir.join('d.py').pyimport()
+ assert mod.value2 == "got it"
+
+ def test_pyimport_and_import(self, tmpdir):
+ tmpdir.ensure('xxxpackage', '__init__.py')
+ mod1path = tmpdir.ensure('xxxpackage', 'module1.py')
+ mod1 = mod1path.pyimport()
+ assert mod1.__name__ == 'xxxpackage.module1'
+ from xxxpackage import module1
+ assert module1 is mod1
+
+ def test_pyimport_check_filepath_consistency(self, monkeypatch, tmpdir):
+ name = 'pointsback123'
+ ModuleType = type(os)
+ p = tmpdir.ensure(name + '.py')
+ for ending in ('.pyc', '$py.class', '.pyo'):
+ mod = ModuleType(name)
+ pseudopath = tmpdir.ensure(name+ending)
+ mod.__file__ = str(pseudopath)
+ monkeypatch.setitem(sys.modules, name, mod)
+ newmod = p.pyimport()
+ assert mod == newmod
+ monkeypatch.undo()
+ mod = ModuleType(name)
+ pseudopath = tmpdir.ensure(name+"123.py")
+ mod.__file__ = str(pseudopath)
+ monkeypatch.setitem(sys.modules, name, mod)
+ excinfo = py.test.raises(pseudopath.ImportMismatchError, p.pyimport)
+ modname, modfile, orig = excinfo.value.args
+ assert modname == name
+ assert modfile == pseudopath
+ assert orig == p
+ assert issubclass(pseudopath.ImportMismatchError, ImportError)
+
+ def test_issue131_pyimport_on__init__(self, tmpdir):
+ # __init__.py files may be namespace packages, and thus the
+ # __file__ of an imported module may not be ourselves
+ # see issue
+ p1 = tmpdir.ensure("proja", "__init__.py")
+ p2 = tmpdir.ensure("sub", "proja", "__init__.py")
+ m1 = p1.pyimport()
+ m2 = p2.pyimport()
+ assert m1 == m2
+
+ def test_ensuresyspath_append(self, tmpdir):
+ root1 = tmpdir.mkdir("root1")
+ file1 = root1.ensure("x123.py")
+ assert str(root1) not in sys.path
+ file1.pyimport(ensuresyspath="append")
+ assert str(root1) == sys.path[-1]
+ assert str(root1) not in sys.path[:-1]
+
+
+def test_pypkgdir(tmpdir):
+ pkg = tmpdir.ensure('pkg1', dir=1)
+ pkg.ensure("__init__.py")
+ pkg.ensure("subdir/__init__.py")
+ assert pkg.pypkgpath() == pkg
+ assert pkg.join('subdir', '__init__.py').pypkgpath() == pkg
+
+
+def test_pypkgdir_unimportable(tmpdir):
+ pkg = tmpdir.ensure('pkg1-1', dir=1) # unimportable
+ pkg.ensure("__init__.py")
+ subdir = pkg.ensure("subdir/__init__.py").dirpath()
+ assert subdir.pypkgpath() == subdir
+ assert subdir.ensure("xyz.py").pypkgpath() == subdir
+ assert not pkg.pypkgpath()
+
+
+def test_isimportable():
+ from py._path.local import isimportable
+ assert not isimportable("")
+ assert isimportable("x")
+ assert isimportable("x1")
+ assert isimportable("x_1")
+ assert isimportable("_")
+ assert isimportable("_1")
+ assert not isimportable("x-1")
+ assert not isimportable("x:1")
+
+
+def test_homedir_from_HOME(monkeypatch):
+ path = os.getcwd()
+ monkeypatch.setenv("HOME", path)
+ assert py.path.local._gethomedir() == py.path.local(path)
+
+
+def test_homedir_not_exists(monkeypatch):
+ monkeypatch.delenv("HOME", raising=False)
+ monkeypatch.delenv("HOMEDRIVE", raising=False)
+ homedir = py.path.local._gethomedir()
+ assert homedir is None
+
+
+def test_samefile(tmpdir):
+ assert tmpdir.samefile(tmpdir)
+ p = tmpdir.ensure("hello")
+ assert p.samefile(p)
+ with p.dirpath().as_cwd():
+ assert p.samefile(p.basename)
+ if sys.platform == "win32":
+ p1 = p.__class__(str(p).lower())
+ p2 = p.__class__(str(p).upper())
+ assert p1.samefile(p2)
+
+
+def test_listdir_single_arg(tmpdir):
+ tmpdir.ensure("hello")
+ assert tmpdir.listdir("hello")[0].basename == "hello"
+
+
+def test_mkdtemp_rootdir(tmpdir):
+ dtmp = local.mkdtemp(rootdir=tmpdir)
+ assert tmpdir.listdir() == [dtmp]
+
+
+class TestWINLocalPath:
+ pytestmark = win32only
+
+ def test_owner_group_not_implemented(self, path1):
+ py.test.raises(NotImplementedError, "path1.stat().owner")
+ py.test.raises(NotImplementedError, "path1.stat().group")
+
+ def test_chmod_simple_int(self, path1):
+ py.builtin.print_("path1 is", path1)
+ mode = path1.stat().mode
+ # Ensure that we actually change the mode to something different.
+ path1.chmod(mode == 0 and 1 or 0)
+ try:
+ print(path1.stat().mode)
+ print(mode)
+ assert path1.stat().mode != mode
+ finally:
+ path1.chmod(mode)
+ assert path1.stat().mode == mode
+
+ def test_path_comparison_lowercase_mixed(self, path1):
+ t1 = path1.join("a_path")
+ t2 = path1.join("A_path")
+ assert t1 == t1
+ assert t1 == t2
+
+ def test_relto_with_mixed_case(self, path1):
+ t1 = path1.join("a_path", "fiLe")
+ t2 = path1.join("A_path")
+ assert t1.relto(t2) == "fiLe"
+
+ def test_allow_unix_style_paths(self, path1):
+ t1 = path1.join('a_path')
+ assert t1 == str(path1) + '\\a_path'
+ t1 = path1.join('a_path/')
+ assert t1 == str(path1) + '\\a_path'
+ t1 = path1.join('dir/a_path')
+ assert t1 == str(path1) + '\\dir\\a_path'
+
+ def test_sysfind_in_currentdir(self, path1):
+ cmd = py.path.local.sysfind('cmd')
+ root = cmd.new(dirname='', basename='') # c:\ in most installations
+ with root.as_cwd():
+ x = py.path.local.sysfind(cmd.relto(root))
+ assert x.check(file=1)
+
+ def test_fnmatch_file_abspath_posix_pattern_on_win32(self, tmpdir):
+ # path-matching patterns might contain a posix path separator '/'
+ # Test that we can match that pattern on windows.
+ import posixpath
+ b = tmpdir.join("a", "b")
+ assert b.fnmatch(posixpath.sep.join("ab"))
+ pattern = posixpath.sep.join([str(tmpdir), "*", "b"])
+ assert b.fnmatch(pattern)
+
+
+class TestPOSIXLocalPath:
+ pytestmark = skiponwin32
+
+ def test_hardlink(self, tmpdir):
+ linkpath = tmpdir.join('test')
+ filepath = tmpdir.join('file')
+ filepath.write("Hello")
+ nlink = filepath.stat().nlink
+ linkpath.mklinkto(filepath)
+ assert filepath.stat().nlink == nlink + 1
+
+ def test_symlink_are_identical(self, tmpdir):
+ filepath = tmpdir.join('file')
+ filepath.write("Hello")
+ linkpath = tmpdir.join('test')
+ linkpath.mksymlinkto(filepath)
+ assert linkpath.readlink() == str(filepath)
+
+ def test_symlink_isfile(self, tmpdir):
+ linkpath = tmpdir.join('test')
+ filepath = tmpdir.join('file')
+ filepath.write("")
+ linkpath.mksymlinkto(filepath)
+ assert linkpath.check(file=1)
+ assert not linkpath.check(link=0, file=1)
+ assert linkpath.islink()
+
+ def test_symlink_relative(self, tmpdir):
+ linkpath = tmpdir.join('test')
+ filepath = tmpdir.join('file')
+ filepath.write("Hello")
+ linkpath.mksymlinkto(filepath, absolute=False)
+ assert linkpath.readlink() == "file"
+ assert filepath.read() == linkpath.read()
+
+ def test_symlink_not_existing(self, tmpdir):
+ linkpath = tmpdir.join('testnotexisting')
+ assert not linkpath.check(link=1)
+ assert linkpath.check(link=0)
+
+ def test_relto_with_root(self, path1, tmpdir):
+ y = path1.join('x').relto(py.path.local('/'))
+ assert y[0] == str(path1)[1]
+
+ def test_visit_recursive_symlink(self, tmpdir):
+ linkpath = tmpdir.join('test')
+ linkpath.mksymlinkto(tmpdir)
+ visitor = tmpdir.visit(None, lambda x: x.check(link=0))
+ assert list(visitor) == [linkpath]
+
+ def test_symlink_isdir(self, tmpdir):
+ linkpath = tmpdir.join('test')
+ linkpath.mksymlinkto(tmpdir)
+ assert linkpath.check(dir=1)
+ assert not linkpath.check(link=0, dir=1)
+
+ def test_symlink_remove(self, tmpdir):
+ linkpath = tmpdir.join('test')
+ linkpath.mksymlinkto(linkpath) # point to itself
+ assert linkpath.check(link=1)
+ linkpath.remove()
+ assert not linkpath.check()
+
+ def test_realpath_file(self, tmpdir):
+ linkpath = tmpdir.join('test')
+ filepath = tmpdir.join('file')
+ filepath.write("")
+ linkpath.mksymlinkto(filepath)
+ realpath = linkpath.realpath()
+ assert realpath.basename == 'file'
+
+ def test_owner(self, path1, tmpdir):
+ from pwd import getpwuid
+ from grp import getgrgid
+ stat = path1.stat()
+ assert stat.path == path1
+
+ uid = stat.uid
+ gid = stat.gid
+ owner = getpwuid(uid)[0]
+ group = getgrgid(gid)[0]
+
+ assert uid == stat.uid
+ assert owner == stat.owner
+ assert gid == stat.gid
+ assert group == stat.group
+
+ def test_stat_helpers(self, tmpdir, monkeypatch):
+ path1 = tmpdir.ensure("file")
+ stat1 = path1.stat()
+ stat2 = tmpdir.stat()
+ assert stat1.isfile()
+ assert stat2.isdir()
+ assert not stat1.islink()
+ assert not stat2.islink()
+
+ def test_stat_non_raising(self, tmpdir):
+ path1 = tmpdir.join("file")
+ pytest.raises(py.error.ENOENT, lambda: path1.stat())
+ res = path1.stat(raising=False)
+ assert res is None
+
+ def test_atime(self, tmpdir):
+ import time
+ path = tmpdir.ensure('samplefile')
+ now = time.time()
+ atime1 = path.atime()
+ # we could wait here but timer resolution is very
+ # system dependent
+ path.read()
+ time.sleep(ATIME_RESOLUTION)
+ atime2 = path.atime()
+ time.sleep(ATIME_RESOLUTION)
+ duration = time.time() - now
+ assert (atime2-atime1) <= duration
+
+ def test_commondir(self, path1):
+ # XXX This is here in local until we find a way to implement this
+ # using the subversion command line api.
+ p1 = path1.join('something')
+ p2 = path1.join('otherthing')
+ assert p1.common(p2) == path1
+ assert p2.common(p1) == path1
+
+ def test_commondir_nocommon(self, path1):
+ # XXX This is here in local until we find a way to implement this
+ # using the subversion command line api.
+ p1 = path1.join('something')
+ p2 = py.path.local(path1.sep+'blabla')
+ assert p1.common(p2) == '/'
+
+ def test_join_to_root(self, path1):
+ root = path1.parts()[0]
+ assert len(str(root)) == 1
+ assert str(root.join('a')) == '/a'
+
+ def test_join_root_to_root_with_no_abs(self, path1):
+ nroot = path1.join('/')
+ assert str(path1) == str(nroot)
+ assert path1 == nroot
+
+ def test_chmod_simple_int(self, path1):
+ mode = path1.stat().mode
+ path1.chmod(int(mode/2))
+ try:
+ assert path1.stat().mode != mode
+ finally:
+ path1.chmod(mode)
+ assert path1.stat().mode == mode
+
+ def test_chmod_rec_int(self, path1):
+ # XXX fragile test
+ def recfilter(x): return x.check(dotfile=0, link=0)
+ oldmodes = {}
+ for x in path1.visit(rec=recfilter):
+ oldmodes[x] = x.stat().mode
+ path1.chmod(int("772", 8), rec=recfilter)
+ try:
+ for x in path1.visit(rec=recfilter):
+ assert x.stat().mode & int("777", 8) == int("772", 8)
+ finally:
+ for x, y in oldmodes.items():
+ x.chmod(y)
+
+ def test_copy_archiving(self, tmpdir):
+ unicode_fn = u"something-\342\200\223.txt"
+ f = tmpdir.ensure("a", unicode_fn)
+ a = f.dirpath()
+ oldmode = f.stat().mode
+ newmode = oldmode ^ 1
+ f.chmod(newmode)
+ b = tmpdir.join("b")
+ a.copy(b, mode=True)
+ assert b.join(f.basename).stat().mode == newmode
+
+ def test_copy_stat_file(self, tmpdir):
+ src = tmpdir.ensure('src')
+ dst = tmpdir.join('dst')
+ # a small delay before the copy
+ time.sleep(ATIME_RESOLUTION)
+ src.copy(dst, stat=True)
+ oldstat = src.stat()
+ newstat = dst.stat()
+ assert oldstat.mode == newstat.mode
+ assert (dst.atime() - src.atime()) < ATIME_RESOLUTION
+ assert (dst.mtime() - src.mtime()) < ATIME_RESOLUTION
+
+ def test_copy_stat_dir(self, tmpdir):
+ test_files = ['a', 'b', 'c']
+ src = tmpdir.join('src')
+ for f in test_files:
+ src.join(f).write(f, ensure=True)
+ dst = tmpdir.join('dst')
+ # a small delay before the copy
+ time.sleep(ATIME_RESOLUTION)
+ src.copy(dst, stat=True)
+ for f in test_files:
+ oldstat = src.join(f).stat()
+ newstat = dst.join(f).stat()
+ assert (newstat.atime - oldstat.atime) < ATIME_RESOLUTION
+ assert (newstat.mtime - oldstat.mtime) < ATIME_RESOLUTION
+ assert oldstat.mode == newstat.mode
+
+ @failsonjython
+ def test_chown_identity(self, path1):
+ owner = path1.stat().owner
+ group = path1.stat().group
+ path1.chown(owner, group)
+
+ @failsonjython
+ def test_chown_dangling_link(self, path1):
+ owner = path1.stat().owner
+ group = path1.stat().group
+ x = path1.join('hello')
+ x.mksymlinkto('qlwkejqwlek')
+ try:
+ path1.chown(owner, group, rec=1)
+ finally:
+ x.remove(rec=0)
+
+ @failsonjython
+ def test_chown_identity_rec_mayfail(self, path1):
+ owner = path1.stat().owner
+ group = path1.stat().group
+ path1.chown(owner, group)
+
+
+class TestUnicodePy2Py3:
+ def test_join_ensure(self, tmpdir, monkeypatch):
+ if sys.version_info >= (3, 0) and "LANG" not in os.environ:
+ pytest.skip("cannot run test without locale")
+ x = py.path.local(tmpdir.strpath)
+ part = "hällo"
+ y = x.ensure(part)
+ assert x.join(part) == y
+
+ def test_listdir(self, tmpdir):
+ if sys.version_info >= (3, 0) and "LANG" not in os.environ:
+ pytest.skip("cannot run test without locale")
+ x = py.path.local(tmpdir.strpath)
+ part = "hällo"
+ y = x.ensure(part)
+ assert x.listdir(part)[0] == y
+
+ @pytest.mark.xfail(
+ reason="changing read/write might break existing usages")
+ def test_read_write(self, tmpdir):
+ x = tmpdir.join("hello")
+ part = py.builtin._totext("hällo", "utf8")
+ x.write(part)
+ assert x.read() == part
+ x.write(part.encode(sys.getdefaultencoding()))
+ assert x.read() == part.encode(sys.getdefaultencoding())
+
+
+class TestBinaryAndTextMethods:
+ def test_read_binwrite(self, tmpdir):
+ x = tmpdir.join("hello")
+ part = py.builtin._totext("hällo", "utf8")
+ part_utf8 = part.encode("utf8")
+ x.write_binary(part_utf8)
+ assert x.read_binary() == part_utf8
+ s = x.read_text(encoding="utf8")
+ assert s == part
+ assert py.builtin._istext(s)
+
+ def test_read_textwrite(self, tmpdir):
+ x = tmpdir.join("hello")
+ part = py.builtin._totext("hällo", "utf8")
+ part_utf8 = part.encode("utf8")
+ x.write_text(part, encoding="utf8")
+ assert x.read_binary() == part_utf8
+ assert x.read_text(encoding="utf8") == part
+
+ def test_default_encoding(self, tmpdir):
+ x = tmpdir.join("hello")
+ # Can't use UTF8 as the default encoding (ASCII) doesn't support it
+ part = py.builtin._totext("hello", "ascii")
+ x.write_text(part, "ascii")
+ s = x.read_text("ascii")
+ assert s == part
+ assert type(s) == type(part)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/testing/path/test_svnauth.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/path/test_svnauth.py
new file mode 100644
index 00000000000..654f033224f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/path/test_svnauth.py
@@ -0,0 +1,460 @@
+import py
+from py.path import SvnAuth
+import time
+import sys
+
+svnbin = py.path.local.sysfind('svn')
+
+
+def make_repo_auth(repo, userdata):
+ """ write config to repo
+
+ user information in userdata is used for auth
+ userdata has user names as keys, and a tuple (password, readwrite) as
+ values, where 'readwrite' is either 'r' or 'rw'
+ """
+ confdir = py.path.local(repo).join('conf')
+ confdir.join('svnserve.conf').write('''\
+[general]
+anon-access = none
+password-db = passwd
+authz-db = authz
+realm = TestRepo
+''')
+ authzdata = '[/]\n'
+ passwddata = '[users]\n'
+ for user in userdata:
+ authzdata += '%s = %s\n' % (user, userdata[user][1])
+ passwddata += '%s = %s\n' % (user, userdata[user][0])
+ confdir.join('authz').write(authzdata)
+ confdir.join('passwd').write(passwddata)
+
+def serve_bg(repopath):
+ pidfile = py.path.local(repopath).join('pid')
+ port = 10000
+ e = None
+ while port < 10010:
+ cmd = 'svnserve -d -T --listen-port=%d --pid-file=%s -r %s' % (
+ port, pidfile, repopath)
+ print(cmd)
+ try:
+ py.process.cmdexec(cmd)
+ except py.process.cmdexec.Error:
+ e = sys.exc_info()[1]
+ else:
+ # XXX we assume here that the pid file gets written somewhere, I
+ # guess this should be relatively safe... (I hope, at least?)
+ counter = pid = 0
+ while counter < 10:
+ counter += 1
+ try:
+ pid = pidfile.read()
+ except py.error.ENOENT:
+ pass
+ if pid:
+ break
+ time.sleep(0.2)
+ return port, int(pid)
+ port += 1
+ raise IOError('could not start svnserve: %s' % (e,))
+
+class TestSvnAuth(object):
+ def test_basic(self):
+ auth = SvnAuth('foo', 'bar')
+ assert auth.username == 'foo'
+ assert auth.password == 'bar'
+ assert str(auth)
+
+ def test_makecmdoptions_uname_pw_makestr(self):
+ auth = SvnAuth('foo', 'bar')
+ assert auth.makecmdoptions() == '--username="foo" --password="bar"'
+
+ def test_makecmdoptions_quote_escape(self):
+ auth = SvnAuth('fo"o', '"ba\'r"')
+ assert auth.makecmdoptions() == '--username="fo\\"o" --password="\\"ba\'r\\""'
+
+ def test_makecmdoptions_no_cache_auth(self):
+ auth = SvnAuth('foo', 'bar', cache_auth=False)
+ assert auth.makecmdoptions() == ('--username="foo" --password="bar" '
+ '--no-auth-cache')
+
+ def test_makecmdoptions_no_interactive(self):
+ auth = SvnAuth('foo', 'bar', interactive=False)
+ assert auth.makecmdoptions() == ('--username="foo" --password="bar" '
+ '--non-interactive')
+
+ def test_makecmdoptions_no_interactive_no_cache_auth(self):
+ auth = SvnAuth('foo', 'bar', cache_auth=False,
+ interactive=False)
+ assert auth.makecmdoptions() == ('--username="foo" --password="bar" '
+ '--no-auth-cache --non-interactive')
+
+class svnwc_no_svn(py.path.svnwc):
+ def __new__(cls, *args, **kwargs):
+ self = super(svnwc_no_svn, cls).__new__(cls, *args, **kwargs)
+ self.commands = []
+ return self
+
+ def _svn(self, *args):
+ self.commands.append(args)
+
+class TestSvnWCAuth(object):
+ def setup_method(self, meth):
+ if not svnbin:
+ py.test.skip("svn binary required")
+ self.auth = SvnAuth('user', 'pass', cache_auth=False)
+
+ def test_checkout(self):
+ wc = svnwc_no_svn('foo', auth=self.auth)
+ wc.checkout('url')
+ assert wc.commands[0][-1] == ('--username="user" --password="pass" '
+ '--no-auth-cache')
+
+ def test_commit(self):
+ wc = svnwc_no_svn('foo', auth=self.auth)
+ wc.commit('msg')
+ assert wc.commands[0][-1] == ('--username="user" --password="pass" '
+ '--no-auth-cache')
+
+ def test_checkout_no_cache_auth(self):
+ wc = svnwc_no_svn('foo', auth=self.auth)
+ wc.checkout('url')
+ assert wc.commands[0][-1] == ('--username="user" --password="pass" '
+ '--no-auth-cache')
+
+ def test_checkout_auth_from_constructor(self):
+ wc = svnwc_no_svn('foo', auth=self.auth)
+ wc.checkout('url')
+ assert wc.commands[0][-1] == ('--username="user" --password="pass" '
+ '--no-auth-cache')
+
+class svnurl_no_svn(py.path.svnurl):
+ cmdexec_output = 'test'
+ popen_output = 'test'
+ def __new__(cls, *args, **kwargs):
+ self = super(svnurl_no_svn, cls).__new__(cls, *args, **kwargs)
+ self.commands = []
+ return self
+
+ def _cmdexec(self, cmd):
+ self.commands.append(cmd)
+ return self.cmdexec_output
+
+ def _popen(self, cmd):
+ self.commands.append(cmd)
+ return self.popen_output
+
+class TestSvnURLAuth(object):
+ def setup_method(self, meth):
+ self.auth = SvnAuth('foo', 'bar')
+
+ def test_init(self):
+ u = svnurl_no_svn('http://foo.bar/svn')
+ assert u.auth is None
+
+ u = svnurl_no_svn('http://foo.bar/svn', auth=self.auth)
+ assert u.auth is self.auth
+
+ def test_new(self):
+ u = svnurl_no_svn('http://foo.bar/svn/foo', auth=self.auth)
+ new = u.new(basename='bar')
+ assert new.auth is self.auth
+ assert new.url == 'http://foo.bar/svn/bar'
+
+ def test_join(self):
+ u = svnurl_no_svn('http://foo.bar/svn', auth=self.auth)
+ new = u.join('foo')
+ assert new.auth is self.auth
+ assert new.url == 'http://foo.bar/svn/foo'
+
+ def test_listdir(self):
+ u = svnurl_no_svn('http://foo.bar/svn', auth=self.auth)
+ u.cmdexec_output = '''\
+ 1717 johnny 1529 Nov 04 14:32 LICENSE.txt
+ 1716 johnny 5352 Nov 04 14:28 README.txt
+'''
+ paths = u.listdir()
+ assert paths[0].auth is self.auth
+ assert paths[1].auth is self.auth
+ assert paths[0].basename == 'LICENSE.txt'
+
+ def test_info(self):
+ u = svnurl_no_svn('http://foo.bar/svn/LICENSE.txt', auth=self.auth)
+ def dirpath(self):
+ return self
+ u.cmdexec_output = '''\
+ 1717 johnny 1529 Nov 04 14:32 LICENSE.txt
+ 1716 johnny 5352 Nov 04 14:28 README.txt
+'''
+ org_dp = u.__class__.dirpath
+ u.__class__.dirpath = dirpath
+ try:
+ info = u.info()
+ finally:
+ u.dirpath = org_dp
+ assert info.size == 1529
+
+ def test_open(self):
+ u = svnurl_no_svn('http://foo.bar/svn', auth=self.auth)
+ foo = u.join('foo')
+ foo.check = lambda *args, **kwargs: True
+ ret = foo.open()
+ assert ret == 'test'
+ assert '--username="foo" --password="bar"' in foo.commands[0]
+
+ def test_dirpath(self):
+ u = svnurl_no_svn('http://foo.bar/svn/foo', auth=self.auth)
+ parent = u.dirpath()
+ assert parent.auth is self.auth
+
+ def test_mkdir(self):
+ u = svnurl_no_svn('http://foo.bar/svn/qweqwe', auth=self.auth)
+ assert not u.commands
+ u.mkdir(msg='created dir foo')
+ assert u.commands
+ assert '--username="foo" --password="bar"' in u.commands[0]
+
+ def test_copy(self):
+ u = svnurl_no_svn('http://foo.bar/svn', auth=self.auth)
+ u2 = svnurl_no_svn('http://foo.bar/svn2')
+ u.copy(u2, 'copied dir')
+ assert '--username="foo" --password="bar"' in u.commands[0]
+
+ def test_rename(self):
+ u = svnurl_no_svn('http://foo.bar/svn/foo', auth=self.auth)
+ u.rename('http://foo.bar/svn/bar', 'moved foo to bar')
+ assert '--username="foo" --password="bar"' in u.commands[0]
+
+ def test_remove(self):
+ u = svnurl_no_svn('http://foo.bar/svn/foo', auth=self.auth)
+ u.remove(msg='removing foo')
+ assert '--username="foo" --password="bar"' in u.commands[0]
+
+ def test_export(self):
+ u = svnurl_no_svn('http://foo.bar/svn', auth=self.auth)
+ target = py.path.local('/foo')
+ u.export(target)
+ assert '--username="foo" --password="bar"' in u.commands[0]
+
+ def test_log(self):
+ u = svnurl_no_svn('http://foo.bar/svn/foo', auth=self.auth)
+ u.popen_output = py.io.TextIO(py.builtin._totext('''\
+<?xml version="1.0"?>
+<log>
+<logentry revision="51381">
+<author>guido</author>
+<date>2008-02-11T12:12:18.476481Z</date>
+<msg>Creating branch to work on auth support for py.path.svn*.
+</msg>
+</logentry>
+</log>
+''', 'ascii'))
+ u.check = lambda *args, **kwargs: True
+ ret = u.log(10, 20, verbose=True)
+ assert '--username="foo" --password="bar"' in u.commands[0]
+ assert len(ret) == 1
+ assert int(ret[0].rev) == 51381
+ assert ret[0].author == 'guido'
+
+ def test_propget(self):
+ u = svnurl_no_svn('http://foo.bar/svn', auth=self.auth)
+ u.propget('foo')
+ assert '--username="foo" --password="bar"' in u.commands[0]
+
+def pytest_funcarg__setup(request):
+ return Setup(request)
+
+class Setup:
+ def __init__(self, request):
+ if not svnbin:
+ py.test.skip("svn binary required")
+ if not request.config.option.runslowtests:
+ py.test.skip('use --runslowtests to run these tests')
+
+ tmpdir = request.getfuncargvalue("tmpdir")
+ repodir = tmpdir.join("repo")
+ py.process.cmdexec('svnadmin create %s' % repodir)
+ if sys.platform == 'win32':
+ repodir = '/' + str(repodir).replace('\\', '/')
+ self.repo = py.path.svnurl("file://%s" % repodir)
+ if sys.platform == 'win32':
+ # remove trailing slash...
+ repodir = repodir[1:]
+ self.repopath = py.path.local(repodir)
+ self.temppath = tmpdir.mkdir("temppath")
+ self.auth = SvnAuth('johnny', 'foo', cache_auth=False,
+ interactive=False)
+ make_repo_auth(self.repopath, {'johnny': ('foo', 'rw')})
+ self.port, self.pid = serve_bg(self.repopath.dirpath())
+ # XXX caching is too global
+ py.path.svnurl._lsnorevcache._dict.clear()
+ request.addfinalizer(lambda: py.process.kill(self.pid))
+
+class TestSvnWCAuthFunctional:
+ def test_checkout_constructor_arg(self, setup):
+ wc = py.path.svnwc(setup.temppath, auth=setup.auth)
+ wc.checkout(
+ 'svn://localhost:%s/%s' % (setup.port, setup.repopath.basename))
+ assert wc.join('.svn').check()
+
+ def test_checkout_function_arg(self, setup):
+ wc = py.path.svnwc(setup.temppath, auth=setup.auth)
+ wc.checkout(
+ 'svn://localhost:%s/%s' % (setup.port, setup.repopath.basename))
+ assert wc.join('.svn').check()
+
+ def test_checkout_failing_non_interactive(self, setup):
+ auth = SvnAuth('johnny', 'bar', cache_auth=False,
+ interactive=False)
+ wc = py.path.svnwc(setup.temppath, auth)
+ py.test.raises(Exception,
+ ("wc.checkout('svn://localhost:%(port)s/%(repopath)s')" %
+ setup.__dict__))
+
+ def test_log(self, setup):
+ wc = py.path.svnwc(setup.temppath, setup.auth)
+ wc.checkout(
+ 'svn://localhost:%s/%s' % (setup.port, setup.repopath.basename))
+ foo = wc.ensure('foo.txt')
+ wc.commit('added foo.txt')
+ log = foo.log()
+ assert len(log) == 1
+ assert log[0].msg == 'added foo.txt'
+
+ def test_switch(self, setup):
+ import pytest
+ try:
+ import xdist
+ pytest.skip('#160: fails under xdist')
+ except ImportError:
+ pass
+ wc = py.path.svnwc(setup.temppath, auth=setup.auth)
+ svnurl = 'svn://localhost:%s/%s' % (setup.port, setup.repopath.basename)
+ wc.checkout(svnurl)
+ wc.ensure('foo', dir=True).ensure('foo.txt').write('foo')
+ wc.commit('added foo dir with foo.txt file')
+ wc.ensure('bar', dir=True)
+ wc.commit('added bar dir')
+ bar = wc.join('bar')
+ bar.switch(svnurl + '/foo')
+ assert bar.join('foo.txt')
+
+ def test_update(self, setup):
+ wc1 = py.path.svnwc(setup.temppath.ensure('wc1', dir=True),
+ auth=setup.auth)
+ wc2 = py.path.svnwc(setup.temppath.ensure('wc2', dir=True),
+ auth=setup.auth)
+ wc1.checkout(
+ 'svn://localhost:%s/%s' % (setup.port, setup.repopath.basename))
+ wc2.checkout(
+ 'svn://localhost:%s/%s' % (setup.port, setup.repopath.basename))
+ wc1.ensure('foo', dir=True)
+ wc1.commit('added foo dir')
+ wc2.update()
+ assert wc2.join('foo').check()
+
+ auth = SvnAuth('unknown', 'unknown', interactive=False)
+ wc2.auth = auth
+ py.test.raises(Exception, 'wc2.update()')
+
+ def test_lock_unlock_status(self, setup):
+ port = setup.port
+ wc = py.path.svnwc(setup.temppath, auth=setup.auth)
+ wc.checkout(
+ 'svn://localhost:%s/%s' % (port, setup.repopath.basename,))
+ wc.ensure('foo', file=True)
+ wc.commit('added foo file')
+ foo = wc.join('foo')
+ foo.lock()
+ status = foo.status()
+ assert status.locked
+ foo.unlock()
+ status = foo.status()
+ assert not status.locked
+
+ auth = SvnAuth('unknown', 'unknown', interactive=False)
+ foo.auth = auth
+ py.test.raises(Exception, 'foo.lock()')
+ py.test.raises(Exception, 'foo.unlock()')
+
+ def test_diff(self, setup):
+ port = setup.port
+ wc = py.path.svnwc(setup.temppath, auth=setup.auth)
+ wc.checkout(
+ 'svn://localhost:%s/%s' % (port, setup.repopath.basename,))
+ wc.ensure('foo', file=True)
+ wc.commit('added foo file')
+ wc.update()
+ rev = int(wc.status().rev)
+ foo = wc.join('foo')
+ foo.write('bar')
+ diff = foo.diff()
+ assert '\n+bar\n' in diff
+ foo.commit('added some content')
+ diff = foo.diff()
+ assert not diff
+ diff = foo.diff(rev=rev)
+ assert '\n+bar\n' in diff
+
+ auth = SvnAuth('unknown', 'unknown', interactive=False)
+ foo.auth = auth
+ py.test.raises(Exception, 'foo.diff(rev=rev)')
+
+class TestSvnURLAuthFunctional:
+ def test_listdir(self, setup):
+ port = setup.port
+ u = py.path.svnurl(
+ 'svn://localhost:%s/%s' % (port, setup.repopath.basename),
+ auth=setup.auth)
+ u.ensure('foo')
+ paths = u.listdir()
+ assert len(paths) == 1
+ assert paths[0].auth is setup.auth
+
+ auth = SvnAuth('foo', 'bar', interactive=False)
+ u = py.path.svnurl(
+ 'svn://localhost:%s/%s' % (port, setup.repopath.basename),
+ auth=auth)
+ py.test.raises(Exception, 'u.listdir()')
+
+ def test_copy(self, setup):
+ port = setup.port
+ u = py.path.svnurl(
+ 'svn://localhost:%s/%s' % (port, setup.repopath.basename),
+ auth=setup.auth)
+ foo = u.mkdir('foo')
+ assert foo.check()
+ bar = u.join('bar')
+ foo.copy(bar)
+ assert bar.check()
+ assert bar.auth is setup.auth
+
+ auth = SvnAuth('foo', 'bar', interactive=False)
+ u = py.path.svnurl(
+ 'svn://localhost:%s/%s' % (port, setup.repopath.basename),
+ auth=auth)
+ foo = u.join('foo')
+ bar = u.join('bar')
+ py.test.raises(Exception, 'foo.copy(bar)')
+
+ def test_write_read(self, setup):
+ port = setup.port
+ u = py.path.svnurl(
+ 'svn://localhost:%s/%s' % (port, setup.repopath.basename),
+ auth=setup.auth)
+ foo = u.ensure('foo')
+ fp = foo.open()
+ try:
+ data = fp.read()
+ finally:
+ fp.close()
+ assert data == ''
+
+ auth = SvnAuth('foo', 'bar', interactive=False)
+ u = py.path.svnurl(
+ 'svn://localhost:%s/%s' % (port, setup.repopath.basename),
+ auth=auth)
+ foo = u.join('foo')
+ py.test.raises(Exception, 'foo.open()')
+
+ # XXX rinse, repeat... :|
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/path/test_svnurl.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/path/test_svnurl.py
index 15fbea5047d..15fbea5047d 100644
--- a/tests/wpt/web-platform-tests/tools/py/testing/path/test_svnurl.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/path/test_svnurl.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/testing/path/test_svnwc.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/path/test_svnwc.py
new file mode 100644
index 00000000000..c643d9983fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/path/test_svnwc.py
@@ -0,0 +1,557 @@
+import py
+import os, sys
+import pytest
+from py._path.svnwc import InfoSvnWCCommand, XMLWCStatus, parse_wcinfotime
+from py._path import svnwc as svncommon
+from svntestbase import CommonSvnTests
+
+
+pytestmark = pytest.mark.xfail(sys.platform.startswith('win'),
+ reason='#161 all tests in this file are failing on Windows',
+ run=False)
+
+
+def test_make_repo(path1, tmpdir):
+ repo = tmpdir.join("repo")
+ py.process.cmdexec('svnadmin create %s' % repo)
+ if sys.platform == 'win32':
+ repo = '/' + str(repo).replace('\\', '/')
+ repo = py.path.svnurl("file://%s" % repo)
+ wc = py.path.svnwc(tmpdir.join("wc"))
+ wc.checkout(repo)
+ assert wc.rev == 0
+ assert len(wc.listdir()) == 0
+ p = wc.join("a_file")
+ p.write("test file")
+ p.add()
+ rev = wc.commit("some test")
+ assert p.info().rev == 1
+ assert rev == 1
+ rev = wc.commit()
+ assert rev is None
+
+def pytest_funcarg__path1(request):
+ repo, repourl, wc = request.getfuncargvalue("repowc1")
+ return wc
+
+class TestWCSvnCommandPath(CommonSvnTests):
+ def test_status_attributes_simple(self, path1):
+ def assert_nochange(p):
+ s = p.status()
+ assert not s.modified
+ assert not s.prop_modified
+ assert not s.added
+ assert not s.deleted
+ assert not s.replaced
+
+ dpath = path1.join('sampledir')
+ assert_nochange(path1.join('sampledir'))
+ assert_nochange(path1.join('samplefile'))
+
+ def test_status_added(self, path1):
+ nf = path1.join('newfile')
+ nf.write('hello')
+ nf.add()
+ try:
+ s = nf.status()
+ assert s.added
+ assert not s.modified
+ assert not s.prop_modified
+ assert not s.replaced
+ finally:
+ nf.revert()
+
+ def test_status_change(self, path1):
+ nf = path1.join('samplefile')
+ try:
+ nf.write(nf.read() + 'change')
+ s = nf.status()
+ assert not s.added
+ assert s.modified
+ assert not s.prop_modified
+ assert not s.replaced
+ finally:
+ nf.revert()
+
+ def test_status_added_ondirectory(self, path1):
+ sampledir = path1.join('sampledir')
+ try:
+ t2 = sampledir.mkdir('t2')
+ t1 = t2.join('t1')
+ t1.write('test')
+ t1.add()
+ s = sampledir.status(rec=1)
+ # Comparing just the file names, because paths are unpredictable
+ # on Windows. (long vs. 8.3 paths)
+ assert t1.basename in [item.basename for item in s.added]
+ assert t2.basename in [item.basename for item in s.added]
+ finally:
+ t2.revert(rec=1)
+ t2.localpath.remove(rec=1)
+
+ def test_status_unknown(self, path1):
+ t1 = path1.join('un1')
+ try:
+ t1.write('test')
+ s = path1.status()
+ # Comparing just the file names, because paths are unpredictable
+ # on Windows. (long vs. 8.3 paths)
+ assert t1.basename in [item.basename for item in s.unknown]
+ finally:
+ t1.localpath.remove()
+
+ def test_status_unchanged(self, path1):
+ r = path1
+ s = path1.status(rec=1)
+ # Comparing just the file names, because paths are unpredictable
+ # on Windows. (long vs. 8.3 paths)
+ assert r.join('samplefile').basename in [item.basename
+ for item in s.unchanged]
+ assert r.join('sampledir').basename in [item.basename
+ for item in s.unchanged]
+ assert r.join('sampledir/otherfile').basename in [item.basename
+ for item in s.unchanged]
+
+ def test_status_update(self, path1):
+ # not a mark because the global "pytestmark" will end up overwriting a mark here
+ pytest.xfail("svn-1.7 has buggy 'status --xml' output")
+ r = path1
+ try:
+ r.update(rev=1)
+ s = r.status(updates=1, rec=1)
+ # Comparing just the file names, because paths are unpredictable
+ # on Windows. (long vs. 8.3 paths)
+ import pprint
+ pprint.pprint(s.allpath())
+ assert r.join('anotherfile').basename in [item.basename for
+ item in s.update_available]
+ #assert len(s.update_available) == 1
+ finally:
+ r.update()
+
+ def test_status_replaced(self, path1):
+ p = path1.join("samplefile")
+ p.remove()
+ p.ensure(dir=0)
+ try:
+ s = path1.status()
+ assert p.basename in [item.basename for item in s.replaced]
+ finally:
+ path1.revert(rec=1)
+
+ def test_status_ignored(self, path1):
+ try:
+ d = path1.join('sampledir')
+ p = py.path.local(d).join('ignoredfile')
+ p.ensure(file=True)
+ s = d.status()
+ assert [x.basename for x in s.unknown] == ['ignoredfile']
+ assert [x.basename for x in s.ignored] == []
+ d.propset('svn:ignore', 'ignoredfile')
+ s = d.status()
+ assert [x.basename for x in s.unknown] == []
+ assert [x.basename for x in s.ignored] == ['ignoredfile']
+ finally:
+ path1.revert(rec=1)
+
+ def test_status_conflict(self, path1, tmpdir):
+ wc = path1
+ wccopy = py.path.svnwc(tmpdir.join("conflict_copy"))
+ wccopy.checkout(wc.url)
+ p = wc.ensure('conflictsamplefile', file=1)
+ p.write('foo')
+ wc.commit('added conflictsamplefile')
+ wccopy.update()
+ assert wccopy.join('conflictsamplefile').check()
+ p.write('bar')
+ wc.commit('wrote some data')
+ wccopy.join('conflictsamplefile').write('baz')
+ wccopy.update(interactive=False)
+ s = wccopy.status()
+ assert [x.basename for x in s.conflict] == ['conflictsamplefile']
+
+ def test_status_external(self, path1, repowc2):
+ otherrepo, otherrepourl, otherwc = repowc2
+ d = path1.ensure('sampledir', dir=1)
+ try:
+ d.update()
+ d.propset('svn:externals', 'otherwc %s' % (otherwc.url,))
+ d.update()
+ s = d.status()
+ assert [x.basename for x in s.external] == ['otherwc']
+ assert 'otherwc' not in [x.basename for x in s.unchanged]
+ s = d.status(rec=1)
+ assert [x.basename for x in s.external] == ['otherwc']
+ assert 'otherwc' in [x.basename for x in s.unchanged]
+ finally:
+ path1.revert(rec=1)
+
+ def test_status_deleted(self, path1):
+ d = path1.ensure('sampledir', dir=1)
+ d.remove()
+ d.ensure(dir=1)
+ path1.commit()
+ d.ensure('deletefile', dir=0)
+ d.commit()
+ s = d.status()
+ assert 'deletefile' in [x.basename for x in s.unchanged]
+ assert not s.deleted
+ p = d.join('deletefile')
+ p.remove()
+ s = d.status()
+ assert 'deletefile' not in s.unchanged
+ assert [x.basename for x in s.deleted] == ['deletefile']
+
+ def test_status_noauthor(self, path1):
+ # testing for XML without author - this used to raise an exception
+ xml = '''\
+ <entry path="/tmp/pytest-23/wc">
+ <wc-status item="normal" props="none" revision="0">
+ <commit revision="0">
+ <date>2008-08-19T16:50:53.400198Z</date>
+ </commit>
+ </wc-status>
+ </entry>
+ '''
+ XMLWCStatus.fromstring(xml, path1)
+
+ def test_status_wrong_xml(self, path1):
+ # testing for XML without author - this used to raise an exception
+ xml = '<entry path="/home/jean/zope/venv/projectdb/parts/development-products/DataGridField">\n<wc-status item="incomplete" props="none" revision="784">\n</wc-status>\n</entry>'
+ st = XMLWCStatus.fromstring(xml, path1)
+ assert len(st.incomplete) == 1
+
+ def test_diff(self, path1):
+ p = path1 / 'anotherfile'
+ out = p.diff(rev=2)
+ assert out.find('hello') != -1
+
+ def test_blame(self, path1):
+ p = path1.join('samplepickle')
+ lines = p.blame()
+ assert sum([l[0] for l in lines]) == len(lines)
+ for l1, l2 in zip(p.readlines(), [l[2] for l in lines]):
+ assert l1 == l2
+ assert [l[1] for l in lines] == ['hpk'] * len(lines)
+ p = path1.join('samplefile')
+ lines = p.blame()
+ assert sum([l[0] for l in lines]) == len(lines)
+ for l1, l2 in zip(p.readlines(), [l[2] for l in lines]):
+ assert l1 == l2
+ assert [l[1] for l in lines] == ['hpk'] * len(lines)
+
+ def test_join_abs(self, path1):
+ s = str(path1.localpath)
+ n = path1.join(s, abs=1)
+ assert path1 == n
+
+ def test_join_abs2(self, path1):
+ assert path1.join('samplefile', abs=1) == path1.join('samplefile')
+
+ def test_str_gives_localpath(self, path1):
+ assert str(path1) == str(path1.localpath)
+
+ def test_versioned(self, path1):
+ assert path1.check(versioned=1)
+ # TODO: Why does my copy of svn think .svn is versioned?
+ #assert path1.join('.svn').check(versioned=0)
+ assert path1.join('samplefile').check(versioned=1)
+ assert not path1.join('notexisting').check(versioned=1)
+ notexisting = path1.join('hello').localpath
+ try:
+ notexisting.write("")
+ assert path1.join('hello').check(versioned=0)
+ finally:
+ notexisting.remove()
+
+ def test_listdir_versioned(self, path1):
+ assert path1.check(versioned=1)
+ p = path1.localpath.ensure("not_a_versioned_file")
+ l = [x.localpath
+ for x in path1.listdir(lambda x: x.check(versioned=True))]
+ assert p not in l
+
+ def test_nonversioned_remove(self, path1):
+ assert path1.check(versioned=1)
+ somefile = path1.join('nonversioned/somefile')
+ nonwc = py.path.local(somefile)
+ nonwc.ensure()
+ assert somefile.check()
+ assert not somefile.check(versioned=True)
+ somefile.remove() # this used to fail because it tried to 'svn rm'
+
+ def test_properties(self, path1):
+ try:
+ path1.propset('gaga', 'this')
+ assert path1.propget('gaga') == 'this'
+ # Comparing just the file names, because paths are unpredictable
+ # on Windows. (long vs. 8.3 paths)
+ assert path1.basename in [item.basename for item in
+ path1.status().prop_modified]
+ assert 'gaga' in path1.proplist()
+ assert path1.proplist()['gaga'] == 'this'
+
+ finally:
+ path1.propdel('gaga')
+
+ def test_proplist_recursive(self, path1):
+ s = path1.join('samplefile')
+ s.propset('gugu', 'that')
+ try:
+ p = path1.proplist(rec=1)
+ # Comparing just the file names, because paths are unpredictable
+ # on Windows. (long vs. 8.3 paths)
+ assert (path1 / 'samplefile').basename in [item.basename
+ for item in p]
+ finally:
+ s.propdel('gugu')
+
+ def test_long_properties(self, path1):
+ value = """
+ vadm:posix : root root 0100755
+ Properties on 'chroot/dns/var/bind/db.net.xots':
+ """
+ try:
+ path1.propset('gaga', value)
+ backvalue = path1.propget('gaga')
+ assert backvalue == value
+ #assert len(backvalue.split('\n')) == 1
+ finally:
+ path1.propdel('gaga')
+
+
+ def test_ensure(self, path1):
+ newpath = path1.ensure('a', 'b', 'c')
+ try:
+ assert newpath.check(exists=1, versioned=1)
+ newpath.write("hello")
+ newpath.ensure()
+ assert newpath.read() == "hello"
+ finally:
+ path1.join('a').remove(force=1)
+
+ def test_not_versioned(self, path1):
+ p = path1.localpath.mkdir('whatever')
+ f = path1.localpath.ensure('testcreatedfile')
+ try:
+ assert path1.join('whatever').check(versioned=0)
+ assert path1.join('testcreatedfile').check(versioned=0)
+ assert not path1.join('testcreatedfile').check(versioned=1)
+ finally:
+ p.remove(rec=1)
+ f.remove()
+
+ def test_lock_unlock(self, path1):
+ root = path1
+ somefile = root.join('somefile')
+ somefile.ensure(file=True)
+ # not yet added to repo
+ py.test.raises(Exception, 'somefile.lock()')
+ somefile.write('foo')
+ somefile.commit('test')
+ assert somefile.check(versioned=True)
+ somefile.lock()
+ try:
+ locked = root.status().locked
+ assert len(locked) == 1
+ assert locked[0].basename == somefile.basename
+ assert locked[0].dirpath().basename == somefile.dirpath().basename
+ #assert somefile.locked()
+ py.test.raises(Exception, 'somefile.lock()')
+ finally:
+ somefile.unlock()
+ #assert not somefile.locked()
+ locked = root.status().locked
+ assert locked == []
+ py.test.raises(Exception, 'somefile,unlock()')
+ somefile.remove()
+
+ def test_commit_nonrecursive(self, path1):
+ somedir = path1.join('sampledir')
+ somedir.mkdir("subsubdir")
+ somedir.propset('foo', 'bar')
+ status = somedir.status()
+ assert len(status.prop_modified) == 1
+ assert len(status.added) == 1
+
+ somedir.commit('non-recursive commit', rec=0)
+ status = somedir.status()
+ assert len(status.prop_modified) == 0
+ assert len(status.added) == 1
+
+ somedir.commit('recursive commit')
+ status = somedir.status()
+ assert len(status.prop_modified) == 0
+ assert len(status.added) == 0
+
+ def test_commit_return_value(self, path1):
+ testfile = path1.join('test.txt').ensure(file=True)
+ testfile.write('test')
+ rev = path1.commit('testing')
+ assert type(rev) == int
+
+ anotherfile = path1.join('another.txt').ensure(file=True)
+ anotherfile.write('test')
+ rev2 = path1.commit('testing more')
+ assert type(rev2) == int
+ assert rev2 == rev + 1
+
+ #def test_log(self, path1):
+ # l = path1.log()
+ # assert len(l) == 3 # might need to be upped if more tests are added
+
+class XTestWCSvnCommandPathSpecial:
+
+ rooturl = 'http://codespeak.net/svn/py.path/trunk/dist/py.path/test/data'
+ #def test_update_none_rev(self, path1):
+ # path = tmpdir.join('checkouttest')
+ # wcpath = newpath(xsvnwc=str(path), url=path1url)
+ # try:
+ # wcpath.checkout(rev=2100)
+ # wcpath.update()
+ # assert wcpath.info().rev > 2100
+ # finally:
+ # wcpath.localpath.remove(rec=1)
+
+def test_parse_wcinfotime():
+ assert (parse_wcinfotime('2006-05-30 20:45:26 +0200 (Tue, 30 May 2006)') ==
+ 1149021926)
+ assert (parse_wcinfotime('2003-10-27 20:43:14 +0100 (Mon, 27 Oct 2003)') ==
+ 1067287394)
+
+class TestInfoSvnWCCommand:
+
+ def test_svn_1_2(self, path1):
+ output = """
+ Path: test_svnwc.py
+ Name: test_svnwc.py
+ URL: http://codespeak.net/svn/py/dist/py/path/svn/wccommand.py
+ Repository UUID: fd0d7bf2-dfb6-0310-8d31-b7ecfe96aada
+ Revision: 28137
+ Node Kind: file
+ Schedule: normal
+ Last Changed Author: jan
+ Last Changed Rev: 27939
+ Last Changed Date: 2006-05-30 20:45:26 +0200 (Tue, 30 May 2006)
+ Text Last Updated: 2006-06-01 00:42:53 +0200 (Thu, 01 Jun 2006)
+ Properties Last Updated: 2006-05-23 11:54:59 +0200 (Tue, 23 May 2006)
+ Checksum: 357e44880e5d80157cc5fbc3ce9822e3
+ """
+ path = py.path.local(__file__).dirpath().chdir()
+ try:
+ info = InfoSvnWCCommand(output)
+ finally:
+ path.chdir()
+ assert info.last_author == 'jan'
+ assert info.kind == 'file'
+ assert info.mtime == 1149021926.0
+ assert info.url == 'http://codespeak.net/svn/py/dist/py/path/svn/wccommand.py'
+ assert info.time == 1149021926000000.0
+ assert info.rev == 28137
+
+
+ def test_svn_1_3(self, path1):
+ output = """
+ Path: test_svnwc.py
+ Name: test_svnwc.py
+ URL: http://codespeak.net/svn/py/dist/py/path/svn/wccommand.py
+ Repository Root: http://codespeak.net/svn
+ Repository UUID: fd0d7bf2-dfb6-0310-8d31-b7ecfe96aada
+ Revision: 28124
+ Node Kind: file
+ Schedule: normal
+ Last Changed Author: jan
+ Last Changed Rev: 27939
+ Last Changed Date: 2006-05-30 20:45:26 +0200 (Tue, 30 May 2006)
+ Text Last Updated: 2006-06-02 23:46:11 +0200 (Fri, 02 Jun 2006)
+ Properties Last Updated: 2006-06-02 23:45:28 +0200 (Fri, 02 Jun 2006)
+ Checksum: 357e44880e5d80157cc5fbc3ce9822e3
+ """
+ path = py.path.local(__file__).dirpath().chdir()
+ try:
+ info = InfoSvnWCCommand(output)
+ finally:
+ path.chdir()
+ assert info.last_author == 'jan'
+ assert info.kind == 'file'
+ assert info.mtime == 1149021926.0
+ assert info.url == 'http://codespeak.net/svn/py/dist/py/path/svn/wccommand.py'
+ assert info.rev == 28124
+ assert info.time == 1149021926000000.0
+
+
+def test_characters_at():
+ py.test.raises(ValueError, "py.path.svnwc('/tmp/@@@:')")
+
+def test_characters_tilde():
+ py.path.svnwc('/tmp/test~')
+
+
+class TestRepo:
+ def test_trailing_slash_is_stripped(self, path1):
+ # XXX we need to test more normalizing properties
+ url = path1.join("/")
+ assert path1 == url
+
+ #def test_different_revs_compare_unequal(self, path1):
+ # newpath = path1.new(rev=1199)
+ # assert newpath != path1
+
+ def test_exists_svn_root(self, path1):
+ assert path1.check()
+
+ #def test_not_exists_rev(self, path1):
+ # url = path1.__class__(path1url, rev=500)
+ # assert url.check(exists=0)
+
+ #def test_nonexisting_listdir_rev(self, path1):
+ # url = path1.__class__(path1url, rev=500)
+ # raises(py.error.ENOENT, url.listdir)
+
+ #def test_newrev(self, path1):
+ # url = path1.new(rev=None)
+ # assert url.rev == None
+ # assert url.strpath == path1.strpath
+ # url = path1.new(rev=10)
+ # assert url.rev == 10
+
+ #def test_info_rev(self, path1):
+ # url = path1.__class__(path1url, rev=1155)
+ # url = url.join("samplefile")
+ # res = url.info()
+ # assert res.size > len("samplefile") and res.created_rev == 1155
+
+ # the following tests are easier if we have a path class
+ def test_repocache_simple(self, path1):
+ repocache = svncommon.RepoCache()
+ repocache.put(path1.strpath, 42)
+ url, rev = repocache.get(path1.join('test').strpath)
+ assert rev == 42
+ assert url == path1.strpath
+
+ def test_repocache_notimeout(self, path1):
+ repocache = svncommon.RepoCache()
+ repocache.timeout = 0
+ repocache.put(path1.strpath, path1.rev)
+ url, rev = repocache.get(path1.strpath)
+ assert rev == -1
+ assert url == path1.strpath
+
+ def test_repocache_outdated(self, path1):
+ repocache = svncommon.RepoCache()
+ repocache.put(path1.strpath, 42, timestamp=0)
+ url, rev = repocache.get(path1.join('test').strpath)
+ assert rev == -1
+ assert url == path1.strpath
+
+ def _test_getreporev(self):
+ """ this test runs so slow it's usually disabled """
+ old = svncommon.repositories.repos
+ try:
+ _repocache.clear()
+ root = path1.new(rev=-1)
+ url, rev = cache.repocache.get(root.strpath)
+ assert rev>=0
+ assert url == svnrepourl
+ finally:
+ repositories.repos = old
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/process/__init__.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/process/__init__.py
index 792d6005489..792d6005489 100644
--- a/tests/wpt/web-platform-tests/tools/py/testing/process/__init__.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/process/__init__.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/testing/process/test_cmdexec.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/process/test_cmdexec.py
new file mode 100644
index 00000000000..98463d906d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/process/test_cmdexec.py
@@ -0,0 +1,41 @@
+import py
+from py.process import cmdexec
+
+def exvalue():
+ import sys
+ return sys.exc_info()[1]
+
+
+class Test_exec_cmd:
+ def test_simple(self):
+ out = cmdexec('echo hallo')
+ assert out.strip() == 'hallo'
+ assert py.builtin._istext(out)
+
+ def test_simple_newline(self):
+ import sys
+ out = cmdexec(r"""%s -c "print ('hello')" """ % sys.executable)
+ assert out == 'hello\n'
+ assert py.builtin._istext(out)
+
+ def test_simple_error(self):
+ py.test.raises(cmdexec.Error, cmdexec, 'exit 1')
+
+ def test_simple_error_exact_status(self):
+ try:
+ cmdexec('exit 1')
+ except cmdexec.Error:
+ e = exvalue()
+ assert e.status == 1
+ assert py.builtin._istext(e.out)
+ assert py.builtin._istext(e.err)
+
+ def test_err(self):
+ try:
+ cmdexec('echoqweqwe123 hallo')
+ raise AssertionError("command succeeded but shouldn't")
+ except cmdexec.Error:
+ e = exvalue()
+ assert hasattr(e, 'err')
+ assert hasattr(e, 'out')
+ assert e.err or e.out
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/testing/process/test_forkedfunc.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/process/test_forkedfunc.py
new file mode 100644
index 00000000000..ae0d9ab7e6d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/process/test_forkedfunc.py
@@ -0,0 +1,173 @@
+import pytest
+import py, sys, os
+
+pytestmark = py.test.mark.skipif("not hasattr(os, 'fork')")
+
+
+def test_waitfinish_removes_tempdir():
+ ff = py.process.ForkedFunc(boxf1)
+ assert ff.tempdir.check()
+ ff.waitfinish()
+ assert not ff.tempdir.check()
+
+def test_tempdir_gets_gc_collected(monkeypatch):
+ monkeypatch.setattr(os, 'fork', lambda: os.getpid())
+ ff = py.process.ForkedFunc(boxf1)
+ assert ff.tempdir.check()
+ ff.__del__()
+ assert not ff.tempdir.check()
+
+def test_basic_forkedfunc():
+ result = py.process.ForkedFunc(boxf1).waitfinish()
+ assert result.out == "some out\n"
+ assert result.err == "some err\n"
+ assert result.exitstatus == 0
+ assert result.signal == 0
+ assert result.retval == 1
+
+def test_exitstatus():
+ def func():
+ os._exit(4)
+ result = py.process.ForkedFunc(func).waitfinish()
+ assert result.exitstatus == 4
+ assert result.signal == 0
+ assert not result.out
+ assert not result.err
+
+def test_execption_in_func():
+ def fun():
+ raise ValueError(42)
+ ff = py.process.ForkedFunc(fun)
+ result = ff.waitfinish()
+ assert result.exitstatus == ff.EXITSTATUS_EXCEPTION
+ assert result.err.find("ValueError: 42") != -1
+ assert result.signal == 0
+ assert not result.retval
+
+def test_forkedfunc_on_fds():
+ result = py.process.ForkedFunc(boxf2).waitfinish()
+ assert result.out == "someout"
+ assert result.err == "someerr"
+ assert result.exitstatus == 0
+ assert result.signal == 0
+ assert result.retval == 2
+
+def test_forkedfunc_on_fds_output():
+ result = py.process.ForkedFunc(boxf3).waitfinish()
+ assert result.signal == 11
+ assert result.out == "s"
+
+
+def test_forkedfunc_on_stdout():
+ def boxf3():
+ import sys
+ sys.stdout.write("hello\n")
+ os.kill(os.getpid(), 11)
+ result = py.process.ForkedFunc(boxf3).waitfinish()
+ assert result.signal == 11
+ assert result.out == "hello\n"
+
+def test_forkedfunc_signal():
+ result = py.process.ForkedFunc(boxseg).waitfinish()
+ assert result.retval is None
+ assert result.signal == 11
+
+def test_forkedfunc_huge_data():
+ result = py.process.ForkedFunc(boxhuge).waitfinish()
+ assert result.out
+ assert result.exitstatus == 0
+ assert result.signal == 0
+ assert result.retval == 3
+
+def test_box_seq():
+ # we run many boxes with huge data, just one after another
+ for i in range(50):
+ result = py.process.ForkedFunc(boxhuge).waitfinish()
+ assert result.out
+ assert result.exitstatus == 0
+ assert result.signal == 0
+ assert result.retval == 3
+
+def test_box_in_a_box():
+ def boxfun():
+ result = py.process.ForkedFunc(boxf2).waitfinish()
+ print (result.out)
+ sys.stderr.write(result.err + "\n")
+ return result.retval
+
+ result = py.process.ForkedFunc(boxfun).waitfinish()
+ assert result.out == "someout\n"
+ assert result.err == "someerr\n"
+ assert result.exitstatus == 0
+ assert result.signal == 0
+ assert result.retval == 2
+
+def test_kill_func_forked():
+ class A:
+ pass
+ info = A()
+ import time
+
+ def box_fun():
+ time.sleep(10) # we don't want to last forever here
+
+ ff = py.process.ForkedFunc(box_fun)
+ os.kill(ff.pid, 15)
+ result = ff.waitfinish()
+ assert result.signal == 15
+
+
+def test_hooks(monkeypatch):
+ def _boxed():
+ return 1
+
+ def _on_start():
+ sys.stdout.write("some out\n")
+ sys.stdout.flush()
+
+ def _on_exit():
+ sys.stderr.write("some err\n")
+ sys.stderr.flush()
+
+ result = py.process.ForkedFunc(_boxed, child_on_start=_on_start,
+ child_on_exit=_on_exit).waitfinish()
+ assert result.out == "some out\n"
+ assert result.err == "some err\n"
+ assert result.exitstatus == 0
+ assert result.signal == 0
+ assert result.retval == 1
+
+
+# ======================================================================
+# examples
+# ======================================================================
+#
+
+def boxf1():
+ sys.stdout.write("some out\n")
+ sys.stderr.write("some err\n")
+ return 1
+
+def boxf2():
+ os.write(1, "someout".encode('ascii'))
+ os.write(2, "someerr".encode('ascii'))
+ return 2
+
+def boxf3():
+ os.write(1, "s".encode('ascii'))
+ os.kill(os.getpid(), 11)
+
+def boxseg():
+ os.kill(os.getpid(), 11)
+
+def boxhuge():
+ s = " ".encode('ascii')
+ os.write(1, s * 10000)
+ os.write(2, s * 10000)
+ os.write(1, s * 10000)
+
+ os.write(1, s * 10000)
+ os.write(2, s * 10000)
+ os.write(2, s * 10000)
+ os.write(1, s * 10000)
+ return 3
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/testing/process/test_killproc.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/process/test_killproc.py
new file mode 100644
index 00000000000..b0d6e2f5153
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/process/test_killproc.py
@@ -0,0 +1,18 @@
+import pytest
+import sys
+import py
+
+
+@pytest.mark.skipif("sys.platform.startswith('java')")
+def test_kill(tmpdir):
+ subprocess = pytest.importorskip("subprocess")
+ t = tmpdir.join("t.py")
+ t.write("import time ; time.sleep(100)")
+ proc = subprocess.Popen([sys.executable, str(t)])
+ assert proc.poll() is None # no return value yet
+ py.process.kill(proc.pid)
+ ret = proc.wait()
+ if sys.platform == "win32" and ret == 0:
+ pytest.skip("XXX on win32, subprocess.Popen().wait() on a killed "
+ "process does not yield return value != 0")
+ assert ret != 0
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/root/__init__.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/root/__init__.py
index 792d6005489..792d6005489 100644
--- a/tests/wpt/web-platform-tests/tools/py/testing/root/__init__.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/root/__init__.py
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/root/test_builtin.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/root/test_builtin.py
index a6f1a3c7399..a6f1a3c7399 100644
--- a/tests/wpt/web-platform-tests/tools/py/testing/root/test_builtin.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/root/test_builtin.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/testing/root/test_error.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/root/test_error.py
new file mode 100644
index 00000000000..a1185f33dc9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/root/test_error.py
@@ -0,0 +1,68 @@
+
+import py
+
+import errno
+
+
+def test_error_classes():
+ for name in errno.errorcode.values():
+ x = getattr(py.error, name)
+ assert issubclass(x, py.error.Error)
+ assert issubclass(x, EnvironmentError)
+
+
+def test_has_name():
+ assert py.error.__name__ == 'py.error'
+
+
+def test_picklability_issue1():
+ import pickle
+ e1 = py.error.ENOENT()
+ s = pickle.dumps(e1)
+ e2 = pickle.loads(s)
+ assert isinstance(e2, py.error.ENOENT)
+
+
+def test_unknown_error():
+ num = 3999
+ cls = py.error._geterrnoclass(num)
+ assert cls.__name__ == 'UnknownErrno%d' % (num,)
+ assert issubclass(cls, py.error.Error)
+ assert issubclass(cls, EnvironmentError)
+ cls2 = py.error._geterrnoclass(num)
+ assert cls is cls2
+
+
+def test_error_conversion_ENOTDIR(testdir):
+ p = testdir.makepyfile("")
+ excinfo = py.test.raises(py.error.Error, py.error.checked_call, p.listdir)
+ assert isinstance(excinfo.value, EnvironmentError)
+ assert isinstance(excinfo.value, py.error.Error)
+ assert "ENOTDIR" in repr(excinfo.value)
+
+
+def test_checked_call_supports_kwargs(tmpdir):
+ import tempfile
+ py.error.checked_call(tempfile.mkdtemp, dir=str(tmpdir))
+
+
+try:
+ import unittest
+ unittest.TestCase.assertWarns
+except (ImportError, AttributeError):
+ pass # required interface not available
+else:
+ import sys
+ import warnings
+
+ class Case(unittest.TestCase):
+ def test_assertWarns(self):
+ # Clear everything "py.*" from sys.modules and re-import py
+ # as a fresh start
+ for mod in tuple(sys.modules.keys()):
+ if mod and (mod == 'py' or mod.startswith('py.')):
+ del sys.modules[mod]
+ import py
+
+ with self.assertWarns(UserWarning):
+ warnings.warn('this should work')
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/testing/root/test_py_imports.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/root/test_py_imports.py
new file mode 100644
index 00000000000..31fe6ead810
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/root/test_py_imports.py
@@ -0,0 +1,71 @@
+import py
+import sys
+
+
+@py.test.mark.parametrize('name', [x for x in dir(py) if x[0] != '_'])
+def test_dir(name):
+ obj = getattr(py, name)
+ if hasattr(obj, '__map__'): # isinstance(obj, Module):
+ keys = dir(obj)
+ assert len(keys) > 0
+ print (obj.__map__)
+ for name in list(obj.__map__):
+ assert hasattr(obj, name), (obj, name)
+
+
+def test_virtual_module_identity():
+ from py import path as path1
+ from py import path as path2
+ assert path1 is path2
+ from py.path import local as local1
+ from py.path import local as local2
+ assert local1 is local2
+
+
+def test_importall():
+ base = py._pydir
+ nodirs = [
+ ]
+ if sys.version_info >= (3, 0):
+ nodirs.append(base.join('_code', '_assertionold.py'))
+ else:
+ nodirs.append(base.join('_code', '_assertionnew.py'))
+
+ def recurse(p):
+ return p.check(dotfile=0) and p.basename != "attic"
+
+ for p in base.visit('*.py', recurse):
+ if p.basename == '__init__.py':
+ continue
+ relpath = p.new(ext='').relto(base)
+ if base.sep in relpath: # not py/*.py itself
+ for x in nodirs:
+ if p == x or p.relto(x):
+ break
+ else:
+ relpath = relpath.replace(base.sep, '.')
+ modpath = 'py.%s' % relpath
+ try:
+ check_import(modpath)
+ except py.test.skip.Exception:
+ pass
+
+
+def check_import(modpath):
+ py.builtin.print_("checking import", modpath)
+ assert __import__(modpath)
+
+
+def test_star_import():
+ exec("from py import *")
+
+
+def test_all_resolves():
+ seen = py.builtin.set([py])
+ lastlength = None
+ while len(seen) != lastlength:
+ lastlength = len(seen)
+ for item in py.builtin.frozenset(seen):
+ for value in item.__dict__.values():
+ if isinstance(value, type(py.test)):
+ seen.add(value)
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/root/test_std.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/root/test_std.py
index 143556a0557..143556a0557 100644
--- a/tests/wpt/web-platform-tests/tools/py/testing/root/test_std.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/root/test_std.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/testing/root/test_xmlgen.py b/tests/wpt/web-platform-tests/tools/third_party/py/testing/root/test_xmlgen.py
new file mode 100644
index 00000000000..fc0e82665f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/testing/root/test_xmlgen.py
@@ -0,0 +1,146 @@
+
+import py
+from py._xmlgen import unicode, html, raw
+import sys
+
+class ns(py.xml.Namespace):
+ pass
+
+def test_escape():
+ uvalue = py.builtin._totext('\xc4\x85\xc4\x87\n\xe2\x82\xac\n', 'utf-8')
+ class A:
+ def __unicode__(self):
+ return uvalue
+ def __str__(self):
+ x = self.__unicode__()
+ if sys.version_info[0] < 3:
+ return x.encode('utf-8')
+ return x
+ y = py.xml.escape(uvalue)
+ assert y == uvalue
+ x = py.xml.escape(A())
+ assert x == uvalue
+ if sys.version_info[0] < 3:
+ assert isinstance(x, unicode)
+ assert isinstance(y, unicode)
+ y = py.xml.escape(uvalue.encode('utf-8'))
+ assert y == uvalue
+
+
+def test_tag_with_text():
+ x = ns.hello("world")
+ u = unicode(x)
+ assert u == "<hello>world</hello>"
+
+def test_class_identity():
+ assert ns.hello is ns.hello
+
+def test_tag_with_text_and_attributes():
+ x = ns.some(name="hello", value="world")
+ assert x.attr.name == 'hello'
+ assert x.attr.value == 'world'
+ u = unicode(x)
+ assert u == '<some name="hello" value="world"/>'
+
+def test_tag_with_subclassed_attr_simple():
+ class my(ns.hello):
+ class Attr(ns.hello.Attr):
+ hello="world"
+ x = my()
+ assert x.attr.hello == 'world'
+ assert unicode(x) == '<my hello="world"/>'
+
+def test_tag_with_raw_attr():
+ x = html.object(data=raw('&'))
+ assert unicode(x) == '<object data="&"></object>'
+
+def test_tag_nested():
+ x = ns.hello(ns.world())
+ unicode(x) # triggers parentifying
+ assert x[0].parent is x
+ u = unicode(x)
+ assert u == '<hello><world/></hello>'
+
+def test_list_nested():
+ x = ns.hello([ns.world()]) #pass in a list here
+ u = unicode(x)
+ assert u == '<hello><world/></hello>'
+
+def test_tag_xmlname():
+ class my(ns.hello):
+ xmlname = 'world'
+ u = unicode(my())
+ assert u == '<world/>'
+
+def test_tag_with_text_entity():
+ x = ns.hello('world & rest')
+ u = unicode(x)
+ assert u == "<hello>world &amp; rest</hello>"
+
+def test_tag_with_text_and_attributes_entity():
+ x = ns.some(name="hello & world")
+ assert x.attr.name == "hello & world"
+ u = unicode(x)
+ assert u == '<some name="hello &amp; world"/>'
+
+def test_raw():
+ x = ns.some(py.xml.raw("<p>literal</p>"))
+ u = unicode(x)
+ assert u == "<some><p>literal</p></some>"
+
+
+def test_html_name_stickyness():
+ class my(html.p):
+ pass
+ x = my("hello")
+ assert unicode(x) == '<p>hello</p>'
+
+def test_stylenames():
+ class my:
+ class body(html.body):
+ style = html.Style(font_size = "12pt")
+ u = unicode(my.body())
+ assert u == '<body style="font-size: 12pt"></body>'
+
+def test_class_None():
+ t = html.body(class_=None)
+ u = unicode(t)
+ assert u == '<body></body>'
+
+def test_alternating_style():
+ alternating = (
+ html.Style(background="white"),
+ html.Style(background="grey"),
+ )
+ class my(html):
+ class li(html.li):
+ def style(self):
+ i = self.parent.index(self)
+ return alternating[i%2]
+ style = property(style)
+
+ x = my.ul(
+ my.li("hello"),
+ my.li("world"),
+ my.li("42"))
+ u = unicode(x)
+ assert u == ('<ul><li style="background: white">hello</li>'
+ '<li style="background: grey">world</li>'
+ '<li style="background: white">42</li>'
+ '</ul>')
+
+def test_singleton():
+ h = html.head(html.link(href="foo"))
+ assert unicode(h) == '<head><link href="foo"/></head>'
+
+ h = html.head(html.script(src="foo"))
+ assert unicode(h) == '<head><script src="foo"></script></head>'
+
+def test_inline():
+ h = html.div(html.span('foo'), html.span('bar'))
+ assert (h.unicode(indent=2) ==
+ '<div><span>foo</span><span>bar</span></div>')
+
+def test_object_tags():
+ o = html.object(html.object())
+ assert o.unicode(indent=0) == '<object><object></object></object>'
diff --git a/tests/wpt/web-platform-tests/tools/third_party/py/tox.ini b/tests/wpt/web-platform-tests/tools/third_party/py/tox.ini
new file mode 100644
index 00000000000..601661cf8e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/py/tox.ini
@@ -0,0 +1,33 @@
+[tox]
+envlist=py{27,34,35,36}-pytest{29,30,31}
+
+[testenv]
+changedir=testing
+commands=
+ pip install -U .. # hande the install order fallout since pytest depends on pip
+
+ py.test --confcutdir=.. -rfsxX --junitxml={envlogdir}/junit-{envname}.xml []
+deps=
+ pytest29: pytest~=2.9.0
+ pytest30: pytest~=3.0.0
+ pytest31: pytest~=3.1.0
+
+[testenv:py27-xdist]
+basepython=python2.7
+deps=
+ pytest~=2.9.0
+ pytest-xdist<=1.16.0
+commands=
+ pip install -U .. # hande the install order fallout since pytest depends on pip
+ py.test -n3 -rfsxX --confcutdir=.. --runslowtests \
+ --junitxml={envlogdir}/junit-{envname}.xml []
+
+[testenv:jython]
+changedir=testing
+commands=
+ {envpython} -m pip install -U .. # hande the install order fallout since pytest depends on pip
+ {envpython} -m pytest --confcutdir=.. -rfsxX --junitxml={envlogdir}/junit-{envname}0.xml {posargs:io_ code}
+
+[pytest]
+rsyncdirs = conftest.py py doc testing
+addopts = -ra
diff --git a/tests/wpt/web-platform-tests/tools/pytest/.gitattributes b/tests/wpt/web-platform-tests/tools/third_party/pytest/.gitattributes
index 242d3da0d74..242d3da0d74 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/.gitattributes
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/.gitattributes
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/.github/ISSUE_TEMPLATE.md b/tests/wpt/web-platform-tests/tools/third_party/pytest/.github/ISSUE_TEMPLATE.md
new file mode 100644
index 00000000000..fbcbb16fc35
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/.github/ISSUE_TEMPLATE.md
@@ -0,0 +1,8 @@
+Thanks for submitting an issue!
+
+Here's a quick checklist in what to include:
+
+- [ ] Include a detailed description of the bug or suggestion
+- [ ] `pip list` of the virtual environment you are using
+- [ ] pytest and operating system versions
+- [ ] Minimal example if possible
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/.github/PULL_REQUEST_TEMPLATE.md b/tests/wpt/web-platform-tests/tools/third_party/pytest/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 00000000000..bf9fc199f59
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,15 @@
+Thanks for submitting a PR, your contribution is really appreciated!
+
+Here's a quick checklist that should be present in PRs:
+
+- [ ] Add a new news fragment into the changelog folder
+ * name it `$issue_id.$type` for example (588.bug)
+ * if you don't have an issue_id change it to the pr id after creating the pr
+ * ensure type is one of `removal`, `feature`, `bugfix`, `vendor`, `doc` or `trivial`
+ * Make sure to use full sentences with correct case and punctuation, for example: "Fix issue with non-ascii contents in doctest text files."
+- [ ] Target: for `bugfix`, `vendor`, `doc` or `trivial` fixes, target `master`; for removals or features target `features`;
+- [ ] Make sure to include reasonable tests for your change if necessary
+
+Unless your change is a trivial or a documentation fix (e.g., a typo or reword of a small section) please:
+
+- [ ] Add yourself to `AUTHORS`, in alphabetical order;
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/.gitignore b/tests/wpt/web-platform-tests/tools/third_party/pytest/.gitignore
new file mode 100644
index 00000000000..3b7ec9facf2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/.gitignore
@@ -0,0 +1,39 @@
+# Automatically generated by `hgimportsvn`
+.svn
+.hgsvn
+
+# Ignore local virtualenvs
+lib/
+bin/
+include/
+.Python/
+
+# These lines are suggested according to the svn:ignore property
+# Feel free to enable them by uncommenting them
+*.pyc
+*.pyo
+*.swp
+*.class
+*.orig
+*~
+.hypothesis/
+
+# autogenerated
+_pytest/_version.py
+# setuptools
+.eggs/
+
+doc/*/_build
+build/
+dist/
+*.egg-info
+issue/
+env/
+.env/
+3rdparty/
+.tox
+.cache
+.coverage
+.ropeproject
+.idea
+.hypothesis
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/.travis.yml b/tests/wpt/web-platform-tests/tools/third_party/pytest/.travis.yml
new file mode 100644
index 00000000000..938391cde09
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/.travis.yml
@@ -0,0 +1,56 @@
+sudo: false
+language: python
+python:
+ - '3.6'
+# command to install dependencies
+install:
+ - pip install --upgrade --pre tox
+# # command to run tests
+env:
+ matrix:
+ # coveralls is not listed in tox's envlist, but should run in travis
+ - TOXENV=coveralls
+ # note: please use "tox --listenvs" to populate the build matrix below
+ - TOXENV=linting
+ - TOXENV=py27
+ - TOXENV=py34
+ - TOXENV=py36
+ - TOXENV=py27-pexpect
+ - TOXENV=py27-xdist
+ - TOXENV=py27-trial
+ - TOXENV=py27-numpy
+ - TOXENV=py27-pluggymaster
+ - TOXENV=py36-pexpect
+ - TOXENV=py36-xdist
+ - TOXENV=py36-trial
+ - TOXENV=py36-numpy
+ - TOXENV=py36-pluggymaster
+ - TOXENV=py27-nobyte
+ - TOXENV=doctesting
+ - TOXENV=docs
+
+matrix:
+ include:
+ - env: TOXENV=pypy
+ python: 'pypy-5.4'
+ - env: TOXENV=py35
+ python: '3.5'
+ - env: TOXENV=py35-freeze
+ python: '3.5'
+ - env: TOXENV=py37
+ python: 'nightly'
+ allow_failures:
+ - env: TOXENV=py37
+ python: 'nightly'
+
+script: tox --recreate
+
+notifications:
+ irc:
+ channels:
+ - "chat.freenode.net#pytest"
+ on_success: change
+ on_failure: change
+ skip_join: true
+ email:
+ - pytest-commit@python.org
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/AUTHORS b/tests/wpt/web-platform-tests/tools/third_party/pytest/AUTHORS
new file mode 100644
index 00000000000..44ae6aa43ab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/AUTHORS
@@ -0,0 +1,189 @@
+Holger Krekel, holger at merlinux eu
+merlinux GmbH, Germany, office at merlinux eu
+
+Contributors include::
+
+Abdeali JK
+Abhijeet Kasurde
+Ahn Ki-Wook
+Alexander Johnson
+Alexei Kozlenok
+Anatoly Bubenkoff
+Andras Tim
+Andreas Zeidler
+Andrzej Ostrowski
+Andy Freeland
+Anthon van der Neut
+Anthony Sottile
+Antony Lee
+Armin Rigo
+Aron Curzon
+Aviv Palivoda
+Barney Gale
+Ben Webb
+Benjamin Peterson
+Bernard Pratz
+Bob Ippolito
+Brian Dorsey
+Brian Okken
+Brianna Laugher
+Bruno Oliveira
+Cal Leeming
+Carl Friedrich Bolz
+Ceridwen
+Charles Cloud
+Charnjit SiNGH (CCSJ)
+Chris Lamb
+Christian Boelsen
+Christian Theunert
+Christian Tismer
+Christopher Gilling
+Daniel Grana
+Daniel Hahler
+Daniel Nuri
+Daniel Wandschneider
+Danielle Jenkins
+Dave Hunt
+David Díaz-Barquero
+David Mohr
+David Vierra
+Daw-Ran Liou
+Denis Kirisov
+Diego Russo
+Dmitry Dygalo
+Dmitry Pribysh
+Duncan Betts
+Edison Gustavo Muenz
+Edoardo Batini
+Eduardo Schettino
+Eli Boyarski
+Elizaveta Shashkova
+Endre Galaczi
+Eric Hunsberger
+Eric Siegerman
+Erik M. Bray
+Feng Ma
+Florian Bruhin
+Floris Bruynooghe
+Gabriel Reis
+George Kussumoto
+Georgy Dyuldin
+Graham Horler
+Greg Price
+Grig Gheorghiu
+Grigorii Eremeev (budulianin)
+Guido Wesdorp
+Harald Armin Massa
+Hugo van Kemenade
+Hui Wang (coldnight)
+Ian Bicking
+Jaap Broekhuizen
+Jan Balster
+Janne Vanhala
+Jason R. Coombs
+Javier Domingo Cansino
+Javier Romero
+Jeff Widman
+John Eddie Ayson
+John Towler
+Jon Sonesen
+Jonas Obrist
+Jordan Guymon
+Jordan Moldow
+Joshua Bronson
+Jurko Gospodnetić
+Justyna Janczyszyn
+Kale Kundert
+Katarzyna Jachim
+Kevin Cox
+Kodi B. Arfer
+Lawrence Mitchell
+Lee Kamentsky
+Lev Maximov
+Llandy Riveron Del Risco
+Loic Esteve
+Lukas Bednar
+Luke Murphy
+Maciek Fijalkowski
+Maho
+Maik Figura
+Mandeep Bhutani
+Manuel Krebber
+Marc Schlaich
+Marcin Bachry
+Mark Abramowitz
+Markus Unterwaditzer
+Martijn Faassen
+Martin Altmayer
+Martin K. Scherer
+Martin Prusse
+Mathieu Clabaut
+Matt Bachmann
+Matt Duck
+Matt Williams
+Matthias Hafner
+Maxim Filipenko
+mbyt
+Michael Aquilina
+Michael Birtwell
+Michael Droettboom
+Michael Seifert
+Michal Wajszczuk
+Mihai Capotă
+Mike Lundy
+Nathaniel Waisbrot
+Ned Batchelder
+Neven Mundar
+Nicolas Delaby
+Oleg Pidsadnyi
+Oliver Bestwalter
+Omar Kohl
+Omer Hadari
+Patrick Hayes
+Paweł Adamczak
+Pieter Mulder
+Piotr Banaszkiewicz
+Punyashloka Biswal
+Quentin Pradet
+Ralf Schmitt
+Ran Benita
+Raphael Pierzina
+Raquel Alegre
+Ravi Chandra
+Roberto Polli
+Romain Dorgueil
+Roman Bolshakov
+Ronny Pfannschmidt
+Ross Lawley
+Russel Winder
+Ryan Wooden
+Samuel Dion-Girardeau
+Samuele Pedroni
+Segev Finer
+Simon Gomizelj
+Skylar Downes
+Srinivas Reddy Thatiparthy
+Stefan Farmbauer
+Stefan Zimmermann
+Stefano Taschini
+Steffen Allner
+Stephan Obermann
+Tarcisio Fischer
+Tareq Alayan
+Ted Xiao
+Thomas Grainger
+Thomas Hisch
+Tom Dalton
+Tom Viner
+Trevor Bekolay
+Tyler Goodlet
+Vasily Kuznetsov
+Victor Uriarte
+Vidar T. Fauske
+Vitaly Lashmanov
+Vlad Dragos
+Wouter van Ackooy
+Xuan Luong
+Xuecong Liao
+Zoltán Máté
+Roland Puntaier
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/CHANGELOG.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/CHANGELOG.rst
new file mode 100644
index 00000000000..7e7bfaf0441
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/CHANGELOG.rst
@@ -0,0 +1,4194 @@
+..
+ You should *NOT* be adding new change log entries to this file, this
+ file is managed by towncrier. You *may* edit previous change logs to
+ fix problems like typo corrections or such.
+ To add a new change log entry, please see
+ https://pip.pypa.io/en/latest/development/#adding-a-news-entry
+ we named the news folder changelog
+
+.. towncrier release notes start
+
+Pytest 3.3.0 (2017-11-23)
+=========================
+
+Deprecations and Removals
+-------------------------
+
+- Pytest no longer supports Python **2.6** and **3.3**. Those Python versions
+ are EOL for some time now and incur maintenance and compatibility costs on
+ the pytest core team, and following up with the rest of the community we
+ decided that they will no longer be supported starting on this version. Users
+ which still require those versions should pin pytest to ``<3.3``. (`#2812
+ <https://github.com/pytest-dev/pytest/issues/2812>`_)
+
+- Remove internal ``_preloadplugins()`` function. This removal is part of the
+ ``pytest_namespace()`` hook deprecation. (`#2636
+ <https://github.com/pytest-dev/pytest/issues/2636>`_)
+
+- Internally change ``CallSpec2`` to have a list of marks instead of a broken
+ mapping of keywords. This removes the keywords attribute of the internal
+ ``CallSpec2`` class. (`#2672
+ <https://github.com/pytest-dev/pytest/issues/2672>`_)
+
+- Remove ParameterSet.deprecated_arg_dict - its not a public api and the lack
+ of the underscore was a naming error. (`#2675
+ <https://github.com/pytest-dev/pytest/issues/2675>`_)
+
+- Remove the internal multi-typed attribute ``Node._evalskip`` and replace it
+ with the boolean ``Node._skipped_by_mark``. (`#2767
+ <https://github.com/pytest-dev/pytest/issues/2767>`_)
+
+- The ``params`` list passed to ``pytest.fixture`` is now for
+ all effects considered immutable and frozen at the moment of the ``pytest.fixture``
+ call. Previously the list could be changed before the first invocation of the fixture
+ allowing for a form of dynamic parametrization (for example, updated from command-line options),
+ but this was an unwanted implementation detail which complicated the internals and prevented
+ some internal cleanup. See issue `#2959 <https://github.com/pytest-dev/pytest/issues/2959>`_
+ for details and a recommended workaround.
+
+Features
+--------
+
+- ``pytest_fixture_post_finalizer`` hook can now receive a ``request``
+ argument. (`#2124 <https://github.com/pytest-dev/pytest/issues/2124>`_)
+
+- Replace the old introspection code in compat.py that determines the available
+ arguments of fixtures with inspect.signature on Python 3 and
+ funcsigs.signature on Python 2. This should respect ``__signature__``
+ declarations on functions. (`#2267
+ <https://github.com/pytest-dev/pytest/issues/2267>`_)
+
+- Report tests with global ``pytestmark`` variable only once. (`#2549
+ <https://github.com/pytest-dev/pytest/issues/2549>`_)
+
+- Now pytest displays the total progress percentage while running tests. The
+ previous output style can be set by configuring the ``console_output_style``
+ setting to ``classic``. (`#2657 <https://github.com/pytest-dev/pytest/issues/2657>`_)
+
+- Match ``warns`` signature to ``raises`` by adding ``match`` keyword. (`#2708
+ <https://github.com/pytest-dev/pytest/issues/2708>`_)
+
+- Pytest now captures and displays output from the standard `logging` module.
+ The user can control the logging level to be captured by specifying options
+ in ``pytest.ini``, the command line and also during individual tests using
+ markers. Also, a ``caplog`` fixture is available that enables users to test
+ the captured log during specific tests (similar to ``capsys`` for example).
+ For more information, please see the `logging docs
+ <https://docs.pytest.org/en/latest/logging.html>`_. This feature was
+ introduced by merging the popular `pytest-catchlog
+ <https://pypi.org/project/pytest-catchlog/>`_ plugin, thanks to `Thomas Hisch
+ <https://github.com/thisch>`_. Be advised that during the merging the
+ backward compatibility interface with the defunct ``pytest-capturelog`` has
+ been dropped. (`#2794 <https://github.com/pytest-dev/pytest/issues/2794>`_)
+
+- Add ``allow_module_level`` kwarg to ``pytest.skip()``, enabling to skip the
+ whole module. (`#2808 <https://github.com/pytest-dev/pytest/issues/2808>`_)
+
+- Allow setting ``file_or_dir``, ``-c``, and ``-o`` in PYTEST_ADDOPTS. (`#2824
+ <https://github.com/pytest-dev/pytest/issues/2824>`_)
+
+- Return stdout/stderr capture results as a ``namedtuple``, so ``out`` and
+ ``err`` can be accessed by attribute. (`#2879
+ <https://github.com/pytest-dev/pytest/issues/2879>`_)
+
+- Add ``capfdbinary``, a version of ``capfd`` which returns bytes from
+ ``readouterr()``. (`#2923
+ <https://github.com/pytest-dev/pytest/issues/2923>`_)
+
+- Add ``capsysbinary`` a version of ``capsys`` which returns bytes from
+ ``readouterr()``. (`#2934
+ <https://github.com/pytest-dev/pytest/issues/2934>`_)
+
+- Implement feature to skip ``setup.py`` files when run with
+ ``--doctest-modules``. (`#502
+ <https://github.com/pytest-dev/pytest/issues/502>`_)
+
+
+Bug Fixes
+---------
+
+- Resume output capturing after ``capsys/capfd.disabled()`` context manager.
+ (`#1993 <https://github.com/pytest-dev/pytest/issues/1993>`_)
+
+- ``pytest_fixture_setup`` and ``pytest_fixture_post_finalizer`` hooks are now
+ called for all ``conftest.py`` files. (`#2124
+ <https://github.com/pytest-dev/pytest/issues/2124>`_)
+
+- If an exception happens while loading a plugin, pytest no longer hides the
+ original traceback. In python2 it will show the original traceback with a new
+ message that explains in which plugin. In python3 it will show 2 canonized
+ exceptions, the original exception while loading the plugin in addition to an
+ exception that PyTest throws about loading a plugin. (`#2491
+ <https://github.com/pytest-dev/pytest/issues/2491>`_)
+
+- ``capsys`` and ``capfd`` can now be used by other fixtures. (`#2709
+ <https://github.com/pytest-dev/pytest/issues/2709>`_)
+
+- Internal ``pytester`` plugin properly encodes ``bytes`` arguments to
+ ``utf-8``. (`#2738 <https://github.com/pytest-dev/pytest/issues/2738>`_)
+
+- ``testdir`` now uses use the same method used by ``tmpdir`` to create its
+ temporary directory. This changes the final structure of the ``testdir``
+ directory slightly, but should not affect usage in normal scenarios and
+ avoids a number of potential problems. (`#2751
+ <https://github.com/pytest-dev/pytest/issues/2751>`_)
+
+- Pytest no longer complains about warnings with unicode messages being
+ non-ascii compatible even for ascii-compatible messages. As a result of this,
+ warnings with unicode messages are converted first to an ascii representation
+ for safety. (`#2809 <https://github.com/pytest-dev/pytest/issues/2809>`_)
+
+- Change return value of pytest command when ``--maxfail`` is reached from
+ ``2`` (interrupted) to ``1`` (failed). (`#2845
+ <https://github.com/pytest-dev/pytest/issues/2845>`_)
+
+- Fix issue in assertion rewriting which could lead it to rewrite modules which
+ should not be rewritten. (`#2939
+ <https://github.com/pytest-dev/pytest/issues/2939>`_)
+
+- Handle marks without description in ``pytest.ini``. (`#2942
+ <https://github.com/pytest-dev/pytest/issues/2942>`_)
+
+
+Trivial/Internal Changes
+------------------------
+
+- pytest now depends on `attrs <https://pypi.org/project/attrs/>`_ for internal
+ structures to ease code maintainability. (`#2641
+ <https://github.com/pytest-dev/pytest/issues/2641>`_)
+
+- Refactored internal Python 2/3 compatibility code to use ``six``. (`#2642
+ <https://github.com/pytest-dev/pytest/issues/2642>`_)
+
+- Stop vendoring ``pluggy`` - we're missing out on its latest changes for not
+ much benefit (`#2719 <https://github.com/pytest-dev/pytest/issues/2719>`_)
+
+- Internal refactor: simplify ascii string escaping by using the
+ backslashreplace error handler in newer Python 3 versions. (`#2734
+ <https://github.com/pytest-dev/pytest/issues/2734>`_)
+
+- Remove unnecessary mark evaluator in unittest plugin (`#2767
+ <https://github.com/pytest-dev/pytest/issues/2767>`_)
+
+- Calls to ``Metafunc.addcall`` now emit a deprecation warning. This function
+ is scheduled to be removed in ``pytest-4.0``. (`#2876
+ <https://github.com/pytest-dev/pytest/issues/2876>`_)
+
+- Internal move of the parameterset extraction to a more maintainable place.
+ (`#2877 <https://github.com/pytest-dev/pytest/issues/2877>`_)
+
+- Internal refactoring to simplify scope node lookup. (`#2910
+ <https://github.com/pytest-dev/pytest/issues/2910>`_)
+
+- Configure ``pytest`` to prevent pip from installing pytest in unsupported
+ Python versions. (`#2922
+ <https://github.com/pytest-dev/pytest/issues/2922>`_)
+
+
+Pytest 3.2.5 (2017-11-15)
+=========================
+
+Bug Fixes
+---------
+
+- Remove ``py<1.5`` restriction from ``pytest`` as this can cause version
+ conflicts in some installations. (`#2926
+ <https://github.com/pytest-dev/pytest/issues/2926>`_)
+
+
+Pytest 3.2.4 (2017-11-13)
+=========================
+
+Bug Fixes
+---------
+
+- Fix the bug where running with ``--pyargs`` will result in items with
+ empty ``parent.nodeid`` if run from a different root directory. (`#2775
+ <https://github.com/pytest-dev/pytest/issues/2775>`_)
+
+- Fix issue with ``@pytest.parametrize`` if argnames was specified as keyword arguments.
+ (`#2819 <https://github.com/pytest-dev/pytest/issues/2819>`_)
+
+- Strip whitespace from marker names when reading them from INI config. (`#2856
+ <https://github.com/pytest-dev/pytest/issues/2856>`_)
+
+- Show full context of doctest source in the pytest output, if the line number of
+ failed example in the docstring is < 9. (`#2882
+ <https://github.com/pytest-dev/pytest/issues/2882>`_)
+
+- Match fixture paths against actual path segments in order to avoid matching folders which share a prefix.
+ (`#2836 <https://github.com/pytest-dev/pytest/issues/2836>`_)
+
+Improved Documentation
+----------------------
+
+- Introduce a dedicated section about conftest.py. (`#1505
+ <https://github.com/pytest-dev/pytest/issues/1505>`_)
+
+- Explicitly mention ``xpass`` in the documentation of ``xfail``. (`#1997
+ <https://github.com/pytest-dev/pytest/issues/1997>`_)
+
+- Append example for pytest.param in the example/parametrize document. (`#2658
+ <https://github.com/pytest-dev/pytest/issues/2658>`_)
+
+- Clarify language of proposal for fixtures parameters (`#2893
+ <https://github.com/pytest-dev/pytest/issues/2893>`_)
+
+- List python 3.6 in the documented supported versions in the getting started
+ document. (`#2903 <https://github.com/pytest-dev/pytest/issues/2903>`_)
+
+- Clarify the documentation of available fixture scopes. (`#538
+ <https://github.com/pytest-dev/pytest/issues/538>`_)
+
+- Add documentation about the ``python -m pytest`` invocation adding the
+ current directory to sys.path. (`#911
+ <https://github.com/pytest-dev/pytest/issues/911>`_)
+
+
+Pytest 3.2.3 (2017-10-03)
+=========================
+
+Bug Fixes
+---------
+
+- Fix crash in tab completion when no prefix is given. (`#2748
+ <https://github.com/pytest-dev/pytest/issues/2748>`_)
+
+- The equality checking function (``__eq__``) of ``MarkDecorator`` returns
+ ``False`` if one object is not an instance of ``MarkDecorator``. (`#2758
+ <https://github.com/pytest-dev/pytest/issues/2758>`_)
+
+- When running ``pytest --fixtures-per-test``: don't crash if an item has no
+ _fixtureinfo attribute (e.g. doctests) (`#2788
+ <https://github.com/pytest-dev/pytest/issues/2788>`_)
+
+
+Improved Documentation
+----------------------
+
+- In help text of ``-k`` option, add example of using ``not`` to not select
+ certain tests whose names match the provided expression. (`#1442
+ <https://github.com/pytest-dev/pytest/issues/1442>`_)
+
+- Add note in ``parametrize.rst`` about calling ``metafunc.parametrize``
+ multiple times. (`#1548 <https://github.com/pytest-dev/pytest/issues/1548>`_)
+
+
+Trivial/Internal Changes
+------------------------
+
+- Set ``xfail_strict=True`` in pytest's own test suite to catch expected
+ failures as soon as they start to pass. (`#2722
+ <https://github.com/pytest-dev/pytest/issues/2722>`_)
+
+- Fix typo in example of passing a callable to markers (in example/markers.rst)
+ (`#2765 <https://github.com/pytest-dev/pytest/issues/2765>`_)
+
+
+Pytest 3.2.2 (2017-09-06)
+=========================
+
+Bug Fixes
+---------
+
+- Calling the deprecated `request.getfuncargvalue()` now shows the source of
+ the call. (`#2681 <https://github.com/pytest-dev/pytest/issues/2681>`_)
+
+- Allow tests declared as ``@staticmethod`` to use fixtures. (`#2699
+ <https://github.com/pytest-dev/pytest/issues/2699>`_)
+
+- Fixed edge-case during collection: attributes which raised ``pytest.fail``
+ when accessed would abort the entire collection. (`#2707
+ <https://github.com/pytest-dev/pytest/issues/2707>`_)
+
+- Fix ``ReprFuncArgs`` with mixed unicode and UTF-8 args. (`#2731
+ <https://github.com/pytest-dev/pytest/issues/2731>`_)
+
+
+Improved Documentation
+----------------------
+
+- In examples on working with custom markers, add examples demonstrating the
+ usage of ``pytest.mark.MARKER_NAME.with_args`` in comparison with
+ ``pytest.mark.MARKER_NAME.__call__`` (`#2604
+ <https://github.com/pytest-dev/pytest/issues/2604>`_)
+
+- In one of the simple examples, use `pytest_collection_modifyitems()` to skip
+ tests based on a command-line option, allowing its sharing while preventing a
+ user error when acessing `pytest.config` before the argument parsing. (`#2653
+ <https://github.com/pytest-dev/pytest/issues/2653>`_)
+
+
+Trivial/Internal Changes
+------------------------
+
+- Fixed minor error in 'Good Practices/Manual Integration' code snippet.
+ (`#2691 <https://github.com/pytest-dev/pytest/issues/2691>`_)
+
+- Fixed typo in goodpractices.rst. (`#2721
+ <https://github.com/pytest-dev/pytest/issues/2721>`_)
+
+- Improve user guidance regarding ``--resultlog`` deprecation. (`#2739
+ <https://github.com/pytest-dev/pytest/issues/2739>`_)
+
+
+Pytest 3.2.1 (2017-08-08)
+=========================
+
+Bug Fixes
+---------
+
+- Fixed small terminal glitch when collecting a single test item. (`#2579
+ <https://github.com/pytest-dev/pytest/issues/2579>`_)
+
+- Correctly consider ``/`` as the file separator to automatically mark plugin
+ files for rewrite on Windows. (`#2591 <https://github.com/pytest-
+ dev/pytest/issues/2591>`_)
+
+- Properly escape test names when setting ``PYTEST_CURRENT_TEST`` environment
+ variable. (`#2644 <https://github.com/pytest-dev/pytest/issues/2644>`_)
+
+- Fix error on Windows and Python 3.6+ when ``sys.stdout`` has been replaced
+ with a stream-like object which does not implement the full ``io`` module
+ buffer protocol. In particular this affects ``pytest-xdist`` users on the
+ aforementioned platform. (`#2666 <https://github.com/pytest-
+ dev/pytest/issues/2666>`_)
+
+
+Improved Documentation
+----------------------
+
+- Explicitly document which pytest features work with ``unittest``. (`#2626
+ <https://github.com/pytest-dev/pytest/issues/2626>`_)
+
+
+Pytest 3.2.0 (2017-07-30)
+=========================
+
+Deprecations and Removals
+-------------------------
+
+- ``pytest.approx`` no longer supports ``>``, ``>=``, ``<`` and ``<=``
+ operators to avoid surprising/inconsistent behavior. See `the approx docs
+ <https://docs.pytest.org/en/latest/builtin.html#pytest.approx>`_ for more
+ information. (`#2003 <https://github.com/pytest-dev/pytest/issues/2003>`_)
+
+- All old-style specific behavior in current classes in the pytest's API is
+ considered deprecated at this point and will be removed in a future release.
+ This affects Python 2 users only and in rare situations. (`#2147
+ <https://github.com/pytest-dev/pytest/issues/2147>`_)
+
+- A deprecation warning is now raised when using marks for parameters
+ in ``pytest.mark.parametrize``. Use ``pytest.param`` to apply marks to
+ parameters instead. (`#2427 <https://github.com/pytest-dev/pytest/issues/2427>`_)
+
+
+Features
+--------
+
+- Add support for numpy arrays (and dicts) to approx. (`#1994
+ <https://github.com/pytest-dev/pytest/issues/1994>`_)
+
+- Now test function objects have a ``pytestmark`` attribute containing a list
+ of marks applied directly to the test function, as opposed to marks inherited
+ from parent classes or modules. (`#2516 <https://github.com/pytest-
+ dev/pytest/issues/2516>`_)
+
+- Collection ignores local virtualenvs by default; `--collect-in-virtualenv`
+ overrides this behavior. (`#2518 <https://github.com/pytest-
+ dev/pytest/issues/2518>`_)
+
+- Allow class methods decorated as ``@staticmethod`` to be candidates for
+ collection as a test function. (Only for Python 2.7 and above. Python 2.6
+ will still ignore static methods.) (`#2528 <https://github.com/pytest-
+ dev/pytest/issues/2528>`_)
+
+- Introduce ``mark.with_args`` in order to allow passing functions/classes as
+ sole argument to marks. (`#2540 <https://github.com/pytest-
+ dev/pytest/issues/2540>`_)
+
+- New ``cache_dir`` ini option: sets the directory where the contents of the
+ cache plugin are stored. Directory may be relative or absolute path: if relative path, then
+ directory is created relative to ``rootdir``, otherwise it is used as is.
+ Additionally path may contain environment variables which are expanded during
+ runtime. (`#2543 <https://github.com/pytest-dev/pytest/issues/2543>`_)
+
+- Introduce the ``PYTEST_CURRENT_TEST`` environment variable that is set with
+ the ``nodeid`` and stage (``setup``, ``call`` and ``teardown``) of the test
+ being currently executed. See the `documentation
+ <https://docs.pytest.org/en/latest/example/simple.html#pytest-current-test-
+ environment-variable>`_ for more info. (`#2583 <https://github.com/pytest-
+ dev/pytest/issues/2583>`_)
+
+- Introduced ``@pytest.mark.filterwarnings`` mark which allows overwriting the
+ warnings filter on a per test, class or module level. See the `docs
+ <https://docs.pytest.org/en/latest/warnings.html#pytest-mark-
+ filterwarnings>`_ for more information. (`#2598 <https://github.com/pytest-
+ dev/pytest/issues/2598>`_)
+
+- ``--last-failed`` now remembers forever when a test has failed and only
+ forgets it if it passes again. This makes it easy to fix a test suite by
+ selectively running files and fixing tests incrementally. (`#2621
+ <https://github.com/pytest-dev/pytest/issues/2621>`_)
+
+- New ``pytest_report_collectionfinish`` hook which allows plugins to add
+ messages to the terminal reporting after collection has been finished
+ successfully. (`#2622 <https://github.com/pytest-dev/pytest/issues/2622>`_)
+
+- Added support for `PEP-415's <https://www.python.org/dev/peps/pep-0415/>`_
+ ``Exception.__suppress_context__``. Now if a ``raise exception from None`` is
+ caught by pytest, pytest will no longer chain the context in the test report.
+ The behavior now matches Python's traceback behavior. (`#2631
+ <https://github.com/pytest-dev/pytest/issues/2631>`_)
+
+- Exceptions raised by ``pytest.fail``, ``pytest.skip`` and ``pytest.xfail``
+ now subclass BaseException, making them harder to be caught unintentionally
+ by normal code. (`#580 <https://github.com/pytest-dev/pytest/issues/580>`_)
+
+
+Bug Fixes
+---------
+
+- Set ``stdin`` to a closed ``PIPE`` in ``pytester.py.Testdir.popen()`` for
+ avoid unwanted interactive ``pdb`` (`#2023 <https://github.com/pytest-
+ dev/pytest/issues/2023>`_)
+
+- Add missing ``encoding`` attribute to ``sys.std*`` streams when using
+ ``capsys`` capture mode. (`#2375 <https://github.com/pytest-
+ dev/pytest/issues/2375>`_)
+
+- Fix terminal color changing to black on Windows if ``colorama`` is imported
+ in a ``conftest.py`` file. (`#2510 <https://github.com/pytest-
+ dev/pytest/issues/2510>`_)
+
+- Fix line number when reporting summary of skipped tests. (`#2548
+ <https://github.com/pytest-dev/pytest/issues/2548>`_)
+
+- capture: ensure that EncodedFile.name is a string. (`#2555
+ <https://github.com/pytest-dev/pytest/issues/2555>`_)
+
+- The options ``--fixtures`` and ``--fixtures-per-test`` will now keep
+ indentation within docstrings. (`#2574 <https://github.com/pytest-
+ dev/pytest/issues/2574>`_)
+
+- doctests line numbers are now reported correctly, fixing `pytest-sugar#122
+ <https://github.com/Frozenball/pytest-sugar/issues/122>`_. (`#2610
+ <https://github.com/pytest-dev/pytest/issues/2610>`_)
+
+- Fix non-determinism in order of fixture collection. Adds new dependency
+ (ordereddict) for Python 2.6. (`#920 <https://github.com/pytest-
+ dev/pytest/issues/920>`_)
+
+
+Improved Documentation
+----------------------
+
+- Clarify ``pytest_configure`` hook call order. (`#2539
+ <https://github.com/pytest-dev/pytest/issues/2539>`_)
+
+- Extend documentation for testing plugin code with the ``pytester`` plugin.
+ (`#971 <https://github.com/pytest-dev/pytest/issues/971>`_)
+
+
+Trivial/Internal Changes
+------------------------
+
+- Update help message for ``--strict`` to make it clear it only deals with
+ unregistered markers, not warnings. (`#2444 <https://github.com/pytest-
+ dev/pytest/issues/2444>`_)
+
+- Internal code move: move code for pytest.approx/pytest.raises to own files in
+ order to cut down the size of python.py (`#2489 <https://github.com/pytest-
+ dev/pytest/issues/2489>`_)
+
+- Renamed the utility function ``_pytest.compat._escape_strings`` to
+ ``_ascii_escaped`` to better communicate the function's purpose. (`#2533
+ <https://github.com/pytest-dev/pytest/issues/2533>`_)
+
+- Improve error message for CollectError with skip/skipif. (`#2546
+ <https://github.com/pytest-dev/pytest/issues/2546>`_)
+
+- Emit warning about ``yield`` tests being deprecated only once per generator.
+ (`#2562 <https://github.com/pytest-dev/pytest/issues/2562>`_)
+
+- Ensure final collected line doesn't include artifacts of previous write.
+ (`#2571 <https://github.com/pytest-dev/pytest/issues/2571>`_)
+
+- Fixed all flake8 errors and warnings. (`#2581 <https://github.com/pytest-
+ dev/pytest/issues/2581>`_)
+
+- Added ``fix-lint`` tox environment to run automatic pep8 fixes on the code.
+ (`#2582 <https://github.com/pytest-dev/pytest/issues/2582>`_)
+
+- Turn warnings into errors in pytest's own test suite in order to catch
+ regressions due to deprecations more promptly. (`#2588
+ <https://github.com/pytest-dev/pytest/issues/2588>`_)
+
+- Show multiple issue links in CHANGELOG entries. (`#2620
+ <https://github.com/pytest-dev/pytest/issues/2620>`_)
+
+
+Pytest 3.1.3 (2017-07-03)
+=========================
+
+Bug Fixes
+---------
+
+- Fix decode error in Python 2 for doctests in docstrings. (`#2434
+ <https://github.com/pytest-dev/pytest/issues/2434>`_)
+
+- Exceptions raised during teardown by finalizers are now suppressed until all
+ finalizers are called, with the initial exception reraised. (`#2440
+ <https://github.com/pytest-dev/pytest/issues/2440>`_)
+
+- Fix incorrect "collected items" report when specifying tests on the command-
+ line. (`#2464 <https://github.com/pytest-dev/pytest/issues/2464>`_)
+
+- ``deprecated_call`` in context-manager form now captures deprecation warnings
+ even if the same warning has already been raised. Also, ``deprecated_call``
+ will always produce the same error message (previously it would produce
+ different messages in context-manager vs. function-call mode). (`#2469
+ <https://github.com/pytest-dev/pytest/issues/2469>`_)
+
+- Fix issue where paths collected by pytest could have triple leading ``/``
+ characters. (`#2475 <https://github.com/pytest-dev/pytest/issues/2475>`_)
+
+- Fix internal error when trying to detect the start of a recursive traceback.
+ (`#2486 <https://github.com/pytest-dev/pytest/issues/2486>`_)
+
+
+Improved Documentation
+----------------------
+
+- Explicitly state for which hooks the calls stop after the first non-None
+ result. (`#2493 <https://github.com/pytest-dev/pytest/issues/2493>`_)
+
+
+Trivial/Internal Changes
+------------------------
+
+- Create invoke tasks for updating the vendored packages. (`#2474
+ <https://github.com/pytest-dev/pytest/issues/2474>`_)
+
+- Update copyright dates in LICENSE, README.rst and in the documentation.
+ (`#2499 <https://github.com/pytest-dev/pytest/issues/2499>`_)
+
+
+Pytest 3.1.2 (2017-06-08)
+=========================
+
+Bug Fixes
+---------
+
+- Required options added via ``pytest_addoption`` will no longer prevent using
+ --help without passing them. (#1999)
+
+- Respect ``python_files`` in assertion rewriting. (#2121)
+
+- Fix recursion error detection when frames in the traceback contain objects
+ that can't be compared (like ``numpy`` arrays). (#2459)
+
+- ``UnicodeWarning`` is issued from the internal pytest warnings plugin only
+ when the message contains non-ascii unicode (Python 2 only). (#2463)
+
+- Added a workaround for Python 3.6 ``WindowsConsoleIO`` breaking due to Pytests's
+ ``FDCapture``. Other code using console handles might still be affected by the
+ very same issue and might require further workarounds/fixes, i.e. ``colorama``.
+ (#2467)
+
+
+Improved Documentation
+----------------------
+
+- Fix internal API links to ``pluggy`` objects. (#2331)
+
+- Make it clear that ``pytest.xfail`` stops test execution at the calling point
+ and improve overall flow of the ``skipping`` docs. (#810)
+
+
+Pytest 3.1.1 (2017-05-30)
+=========================
+
+Bug Fixes
+---------
+
+- pytest warning capture no longer overrides existing warning filters. The
+ previous behaviour would override all filters and caused regressions in test
+ suites which configure warning filters to match their needs. Note that as a
+ side-effect of this is that ``DeprecationWarning`` and
+ ``PendingDeprecationWarning`` are no longer shown by default. (#2430)
+
+- Fix issue with non-ascii contents in doctest text files. (#2434)
+
+- Fix encoding errors for unicode warnings in Python 2. (#2436)
+
+- ``pytest.deprecated_call`` now captures ``PendingDeprecationWarning`` in
+ context manager form. (#2441)
+
+
+Improved Documentation
+----------------------
+
+- Addition of towncrier for changelog management. (#2390)
+
+
+3.1.0 (2017-05-22)
+==================
+
+
+New Features
+------------
+
+* The ``pytest-warnings`` plugin has been integrated into the core and now ``pytest`` automatically
+ captures and displays warnings at the end of the test session.
+
+ .. warning::
+
+ This feature may disrupt test suites which apply and treat warnings themselves, and can be
+ disabled in your ``pytest.ini``:
+
+ .. code-block:: ini
+
+ [pytest]
+ addopts = -p no:warnings
+
+ See the `warnings documentation page <https://docs.pytest.org/en/latest/warnings.html>`_ for more
+ information.
+
+ Thanks `@nicoddemus`_ for the PR.
+
+* Added ``junit_suite_name`` ini option to specify root ``<testsuite>`` name for JUnit XML reports (`#533`_).
+
+* Added an ini option ``doctest_encoding`` to specify which encoding to use for doctest files.
+ Thanks `@wheerd`_ for the PR (`#2101`_).
+
+* ``pytest.warns`` now checks for subclass relationship rather than
+ class equality. Thanks `@lesteve`_ for the PR (`#2166`_)
+
+* ``pytest.raises`` now asserts that the error message matches a text or regex
+ with the ``match`` keyword argument. Thanks `@Kriechi`_ for the PR.
+
+* ``pytest.param`` can be used to declare test parameter sets with marks and test ids.
+ Thanks `@RonnyPfannschmidt`_ for the PR.
+
+
+Changes
+-------
+
+* remove all internal uses of pytest_namespace hooks,
+ this is to prepare the removal of preloadconfig in pytest 4.0
+ Thanks to `@RonnyPfannschmidt`_ for the PR.
+
+* pytest now warns when a callable ids raises in a parametrized test. Thanks `@fogo`_ for the PR.
+
+* It is now possible to skip test classes from being collected by setting a
+ ``__test__`` attribute to ``False`` in the class body (`#2007`_). Thanks
+ to `@syre`_ for the report and `@lwm`_ for the PR.
+
+* Change junitxml.py to produce reports that comply with Junitxml schema.
+ If the same test fails with failure in call and then errors in teardown
+ we split testcase element into two, one containing the error and the other
+ the failure. (`#2228`_) Thanks to `@kkoukiou`_ for the PR.
+
+* Testcase reports with a ``url`` attribute will now properly write this to junitxml.
+ Thanks `@fushi`_ for the PR (`#1874`_).
+
+* Remove common items from dict comparision output when verbosity=1. Also update
+ the truncation message to make it clearer that pytest truncates all
+ assertion messages if verbosity < 2 (`#1512`_).
+ Thanks `@mattduck`_ for the PR
+
+* ``--pdbcls`` no longer implies ``--pdb``. This makes it possible to use
+ ``addopts=--pdbcls=module.SomeClass`` on ``pytest.ini``. Thanks `@davidszotten`_ for
+ the PR (`#1952`_).
+
+* fix `#2013`_: turn RecordedWarning into ``namedtuple``,
+ to give it a comprehensible repr while preventing unwarranted modification.
+
+* fix `#2208`_: ensure a iteration limit for _pytest.compat.get_real_func.
+ Thanks `@RonnyPfannschmidt`_ for the report and PR.
+
+* Hooks are now verified after collection is complete, rather than right after loading installed plugins. This
+ makes it easy to write hooks for plugins which will be loaded during collection, for example using the
+ ``pytest_plugins`` special variable (`#1821`_).
+ Thanks `@nicoddemus`_ for the PR.
+
+* Modify ``pytest_make_parametrize_id()`` hook to accept ``argname`` as an
+ additional parameter.
+ Thanks `@unsignedint`_ for the PR.
+
+* Add ``venv`` to the default ``norecursedirs`` setting.
+ Thanks `@The-Compiler`_ for the PR.
+
+* ``PluginManager.import_plugin`` now accepts unicode plugin names in Python 2.
+ Thanks `@reutsharabani`_ for the PR.
+
+* fix `#2308`_: When using both ``--lf`` and ``--ff``, only the last failed tests are run.
+ Thanks `@ojii`_ for the PR.
+
+* Replace minor/patch level version numbers in the documentation with placeholders.
+ This significantly reduces change-noise as different contributors regnerate
+ the documentation on different platforms.
+ Thanks `@RonnyPfannschmidt`_ for the PR.
+
+* fix `#2391`_: consider pytest_plugins on all plugin modules
+ Thanks `@RonnyPfannschmidt`_ for the PR.
+
+
+Bug Fixes
+---------
+
+* Fix ``AttributeError`` on ``sys.stdout.buffer`` / ``sys.stderr.buffer``
+ while using ``capsys`` fixture in python 3. (`#1407`_).
+ Thanks to `@asottile`_.
+
+* Change capture.py's ``DontReadFromInput`` class to throw ``io.UnsupportedOperation`` errors rather
+ than ValueErrors in the ``fileno`` method (`#2276`_).
+ Thanks `@metasyn`_ and `@vlad-dragos`_ for the PR.
+
+* Fix exception formatting while importing modules when the exception message
+ contains non-ascii characters (`#2336`_).
+ Thanks `@fabioz`_ for the report and `@nicoddemus`_ for the PR.
+
+* Added documentation related to issue (`#1937`_)
+ Thanks `@skylarjhdownes`_ for the PR.
+
+* Allow collecting files with any file extension as Python modules (`#2369`_).
+ Thanks `@Kodiologist`_ for the PR.
+
+* Show the correct error message when collect "parametrize" func with wrong args (`#2383`_).
+ Thanks `@The-Compiler`_ for the report and `@robin0371`_ for the PR.
+
+
+.. _@davidszotten: https://github.com/davidszotten
+.. _@fabioz: https://github.com/fabioz
+.. _@fogo: https://github.com/fogo
+.. _@fushi: https://github.com/fushi
+.. _@Kodiologist: https://github.com/Kodiologist
+.. _@Kriechi: https://github.com/Kriechi
+.. _@mandeep: https://github.com/mandeep
+.. _@mattduck: https://github.com/mattduck
+.. _@metasyn: https://github.com/metasyn
+.. _@MichalTHEDUDE: https://github.com/MichalTHEDUDE
+.. _@ojii: https://github.com/ojii
+.. _@reutsharabani: https://github.com/reutsharabani
+.. _@robin0371: https://github.com/robin0371
+.. _@skylarjhdownes: https://github.com/skylarjhdownes
+.. _@unsignedint: https://github.com/unsignedint
+.. _@wheerd: https://github.com/wheerd
+
+
+.. _#1407: https://github.com/pytest-dev/pytest/issues/1407
+.. _#1512: https://github.com/pytest-dev/pytest/issues/1512
+.. _#1821: https://github.com/pytest-dev/pytest/issues/1821
+.. _#1874: https://github.com/pytest-dev/pytest/pull/1874
+.. _#1937: https://github.com/pytest-dev/pytest/issues/1937
+.. _#1952: https://github.com/pytest-dev/pytest/pull/1952
+.. _#2007: https://github.com/pytest-dev/pytest/issues/2007
+.. _#2013: https://github.com/pytest-dev/pytest/issues/2013
+.. _#2101: https://github.com/pytest-dev/pytest/pull/2101
+.. _#2166: https://github.com/pytest-dev/pytest/pull/2166
+.. _#2208: https://github.com/pytest-dev/pytest/issues/2208
+.. _#2228: https://github.com/pytest-dev/pytest/issues/2228
+.. _#2276: https://github.com/pytest-dev/pytest/issues/2276
+.. _#2308: https://github.com/pytest-dev/pytest/issues/2308
+.. _#2336: https://github.com/pytest-dev/pytest/issues/2336
+.. _#2369: https://github.com/pytest-dev/pytest/issues/2369
+.. _#2383: https://github.com/pytest-dev/pytest/issues/2383
+.. _#2391: https://github.com/pytest-dev/pytest/issues/2391
+.. _#533: https://github.com/pytest-dev/pytest/issues/533
+
+
+
+3.0.7 (2017-03-14)
+==================
+
+
+* Fix issue in assertion rewriting breaking due to modules silently discarding
+ other modules when importing fails
+ Notably, importing the ``anydbm`` module is fixed. (`#2248`_).
+ Thanks `@pfhayes`_ for the PR.
+
+* junitxml: Fix problematic case where system-out tag occured twice per testcase
+ element in the XML report. Thanks `@kkoukiou`_ for the PR.
+
+* Fix regression, pytest now skips unittest correctly if run with ``--pdb``
+ (`#2137`_). Thanks to `@gst`_ for the report and `@mbyt`_ for the PR.
+
+* Ignore exceptions raised from descriptors (e.g. properties) during Python test collection (`#2234`_).
+ Thanks to `@bluetech`_.
+
+* ``--override-ini`` now correctly overrides some fundamental options like ``python_files`` (`#2238`_).
+ Thanks `@sirex`_ for the report and `@nicoddemus`_ for the PR.
+
+* Replace ``raise StopIteration`` usages in the code by simple ``returns`` to finish generators, in accordance to `PEP-479`_ (`#2160`_).
+ Thanks `@tgoodlet`_ for the report and `@nicoddemus`_ for the PR.
+
+* Fix internal errors when an unprintable ``AssertionError`` is raised inside a test.
+ Thanks `@omerhadari`_ for the PR.
+
+* Skipping plugin now also works with test items generated by custom collectors (`#2231`_).
+ Thanks to `@vidartf`_.
+
+* Fix trailing whitespace in console output if no .ini file presented (`#2281`_). Thanks `@fbjorn`_ for the PR.
+
+* Conditionless ``xfail`` markers no longer rely on the underlying test item
+ being an instance of ``PyobjMixin``, and can therefore apply to tests not
+ collected by the built-in python test collector. Thanks `@barneygale`_ for the
+ PR.
+
+
+.. _@pfhayes: https://github.com/pfhayes
+.. _@bluetech: https://github.com/bluetech
+.. _@gst: https://github.com/gst
+.. _@sirex: https://github.com/sirex
+.. _@vidartf: https://github.com/vidartf
+.. _@kkoukiou: https://github.com/KKoukiou
+.. _@omerhadari: https://github.com/omerhadari
+.. _@fbjorn: https://github.com/fbjorn
+
+.. _#2248: https://github.com/pytest-dev/pytest/issues/2248
+.. _#2137: https://github.com/pytest-dev/pytest/issues/2137
+.. _#2160: https://github.com/pytest-dev/pytest/issues/2160
+.. _#2231: https://github.com/pytest-dev/pytest/issues/2231
+.. _#2234: https://github.com/pytest-dev/pytest/issues/2234
+.. _#2238: https://github.com/pytest-dev/pytest/issues/2238
+.. _#2281: https://github.com/pytest-dev/pytest/issues/2281
+
+.. _PEP-479: https://www.python.org/dev/peps/pep-0479/
+
+
+3.0.6 (2017-01-22)
+==================
+
+* pytest no longer generates ``PendingDeprecationWarning`` from its own operations, which was introduced by mistake in version ``3.0.5`` (`#2118`_).
+ Thanks to `@nicoddemus`_ for the report and `@RonnyPfannschmidt`_ for the PR.
+
+
+* pytest no longer recognizes coroutine functions as yield tests (`#2129`_).
+ Thanks to `@malinoff`_ for the PR.
+
+* Plugins loaded by the ``PYTEST_PLUGINS`` environment variable are now automatically
+ considered for assertion rewriting (`#2185`_).
+ Thanks `@nicoddemus`_ for the PR.
+
+* Improve error message when pytest.warns fails (`#2150`_). The type(s) of the
+ expected warnings and the list of caught warnings is added to the
+ error message. Thanks `@lesteve`_ for the PR.
+
+* Fix ``pytester`` internal plugin to work correctly with latest versions of
+ ``zope.interface`` (`#1989`_). Thanks `@nicoddemus`_ for the PR.
+
+* Assert statements of the ``pytester`` plugin again benefit from assertion rewriting (`#1920`_).
+ Thanks `@RonnyPfannschmidt`_ for the report and `@nicoddemus`_ for the PR.
+
+* Specifying tests with colons like ``test_foo.py::test_bar`` for tests in
+ subdirectories with ini configuration files now uses the correct ini file
+ (`#2148`_). Thanks `@pelme`_.
+
+* Fail ``testdir.runpytest().assert_outcomes()`` explicitly if the pytest
+ terminal output it relies on is missing. Thanks to `@eli-b`_ for the PR.
+
+
+.. _@barneygale: https://github.com/barneygale
+.. _@lesteve: https://github.com/lesteve
+.. _@malinoff: https://github.com/malinoff
+.. _@pelme: https://github.com/pelme
+.. _@eli-b: https://github.com/eli-b
+
+.. _#2118: https://github.com/pytest-dev/pytest/issues/2118
+
+.. _#1989: https://github.com/pytest-dev/pytest/issues/1989
+.. _#1920: https://github.com/pytest-dev/pytest/issues/1920
+.. _#2129: https://github.com/pytest-dev/pytest/issues/2129
+.. _#2148: https://github.com/pytest-dev/pytest/issues/2148
+.. _#2150: https://github.com/pytest-dev/pytest/issues/2150
+.. _#2185: https://github.com/pytest-dev/pytest/issues/2185
+
+
+3.0.5 (2016-12-05)
+==================
+
+* Add warning when not passing ``option=value`` correctly to ``-o/--override-ini`` (`#2105`_).
+ Also improved the help documentation. Thanks to `@mbukatov`_ for the report and
+ `@lwm`_ for the PR.
+
+* Now ``--confcutdir`` and ``--junit-xml`` are properly validated if they are directories
+ and filenames, respectively (`#2089`_ and `#2078`_). Thanks to `@lwm`_ for the PR.
+
+* Add hint to error message hinting possible missing ``__init__.py`` (`#478`_). Thanks `@DuncanBetts`_.
+
+* More accurately describe when fixture finalization occurs in documentation (`#687`_). Thanks `@DuncanBetts`_.
+
+* Provide ``:ref:`` targets for ``recwarn.rst`` so we can use intersphinx referencing.
+ Thanks to `@dupuy`_ for the report and `@lwm`_ for the PR.
+
+* In Python 2, use a simple ``+-`` ASCII string in the string representation of ``pytest.approx`` (for example ``"4 +- 4.0e-06"``)
+ because it is brittle to handle that in different contexts and representations internally in pytest
+ which can result in bugs such as `#2111`_. In Python 3, the representation still uses ``±`` (for example ``4 ± 4.0e-06``).
+ Thanks `@kerrick-lyft`_ for the report and `@nicoddemus`_ for the PR.
+
+* Using ``item.Function``, ``item.Module``, etc., is now issuing deprecation warnings, prefer
+ ``pytest.Function``, ``pytest.Module``, etc., instead (`#2034`_).
+ Thanks `@nmundar`_ for the PR.
+
+* Fix error message using ``approx`` with complex numbers (`#2082`_).
+ Thanks `@adler-j`_ for the report and `@nicoddemus`_ for the PR.
+
+* Fixed false-positives warnings from assertion rewrite hook for modules imported more than
+ once by the ``pytest_plugins`` mechanism.
+ Thanks `@nicoddemus`_ for the PR.
+
+* Remove an internal cache which could cause hooks from ``conftest.py`` files in
+ sub-directories to be called in other directories incorrectly (`#2016`_).
+ Thanks `@d-b-w`_ for the report and `@nicoddemus`_ for the PR.
+
+* Remove internal code meant to support earlier Python 3 versions that produced the side effect
+ of leaving ``None`` in ``sys.modules`` when expressions were evaluated by pytest (for example passing a condition
+ as a string to ``pytest.mark.skipif``)(`#2103`_).
+ Thanks `@jaraco`_ for the report and `@nicoddemus`_ for the PR.
+
+* Cope gracefully with a .pyc file with no matching .py file (`#2038`_). Thanks
+ `@nedbat`_.
+
+.. _@syre: https://github.com/syre
+.. _@adler-j: https://github.com/adler-j
+.. _@d-b-w: https://bitbucket.org/d-b-w/
+.. _@DuncanBetts: https://github.com/DuncanBetts
+.. _@dupuy: https://bitbucket.org/dupuy/
+.. _@kerrick-lyft: https://github.com/kerrick-lyft
+.. _@lwm: https://github.com/lwm
+.. _@mbukatov: https://github.com/mbukatov
+.. _@nedbat: https://github.com/nedbat
+.. _@nmundar: https://github.com/nmundar
+
+.. _#2016: https://github.com/pytest-dev/pytest/issues/2016
+.. _#2034: https://github.com/pytest-dev/pytest/issues/2034
+.. _#2038: https://github.com/pytest-dev/pytest/issues/2038
+.. _#2078: https://github.com/pytest-dev/pytest/issues/2078
+.. _#2082: https://github.com/pytest-dev/pytest/issues/2082
+.. _#2089: https://github.com/pytest-dev/pytest/issues/2089
+.. _#2103: https://github.com/pytest-dev/pytest/issues/2103
+.. _#2105: https://github.com/pytest-dev/pytest/issues/2105
+.. _#2111: https://github.com/pytest-dev/pytest/issues/2111
+.. _#478: https://github.com/pytest-dev/pytest/issues/478
+.. _#687: https://github.com/pytest-dev/pytest/issues/687
+
+
+3.0.4 (2016-11-09)
+==================
+
+* Import errors when collecting test modules now display the full traceback (`#1976`_).
+ Thanks `@cwitty`_ for the report and `@nicoddemus`_ for the PR.
+
+* Fix confusing command-line help message for custom options with two or more ``metavar`` properties (`#2004`_).
+ Thanks `@okulynyak`_ and `@davehunt`_ for the report and `@nicoddemus`_ for the PR.
+
+* When loading plugins, import errors which contain non-ascii messages are now properly handled in Python 2 (`#1998`_).
+ Thanks `@nicoddemus`_ for the PR.
+
+* Fixed cyclic reference when ``pytest.raises`` is used in context-manager form (`#1965`_). Also as a
+ result of this fix, ``sys.exc_info()`` is left empty in both context-manager and function call usages.
+ Previously, ``sys.exc_info`` would contain the exception caught by the context manager,
+ even when the expected exception occurred.
+ Thanks `@MSeifert04`_ for the report and the PR.
+
+* Fixed false-positives warnings from assertion rewrite hook for modules that were rewritten but
+ were later marked explicitly by ``pytest.register_assert_rewrite``
+ or implicitly as a plugin (`#2005`_).
+ Thanks `@RonnyPfannschmidt`_ for the report and `@nicoddemus`_ for the PR.
+
+* Report teardown output on test failure (`#442`_).
+ Thanks `@matclab`_ for the PR.
+
+* Fix teardown error message in generated xUnit XML.
+ Thanks `@gdyuldin`_ for the PR.
+
+* Properly handle exceptions in ``multiprocessing`` tasks (`#1984`_).
+ Thanks `@adborden`_ for the report and `@nicoddemus`_ for the PR.
+
+* Clean up unittest TestCase objects after tests are complete (`#1649`_).
+ Thanks `@d_b_w`_ for the report and PR.
+
+
+.. _@adborden: https://github.com/adborden
+.. _@cwitty: https://github.com/cwitty
+.. _@d_b_w: https://github.com/d_b_w
+.. _@gdyuldin: https://github.com/gdyuldin
+.. _@matclab: https://github.com/matclab
+.. _@MSeifert04: https://github.com/MSeifert04
+.. _@okulynyak: https://github.com/okulynyak
+
+.. _#442: https://github.com/pytest-dev/pytest/issues/442
+.. _#1965: https://github.com/pytest-dev/pytest/issues/1965
+.. _#1976: https://github.com/pytest-dev/pytest/issues/1976
+.. _#1984: https://github.com/pytest-dev/pytest/issues/1984
+.. _#1998: https://github.com/pytest-dev/pytest/issues/1998
+.. _#2004: https://github.com/pytest-dev/pytest/issues/2004
+.. _#2005: https://github.com/pytest-dev/pytest/issues/2005
+.. _#1649: https://github.com/pytest-dev/pytest/issues/1649
+
+
+3.0.3 (2016-09-28)
+==================
+
+* The ``ids`` argument to ``parametrize`` again accepts ``unicode`` strings
+ in Python 2 (`#1905`_).
+ Thanks `@philpep`_ for the report and `@nicoddemus`_ for the PR.
+
+* Assertions are now being rewritten for plugins in development mode
+ (``pip install -e``) (`#1934`_).
+ Thanks `@nicoddemus`_ for the PR.
+
+* Fix pkg_resources import error in Jython projects (`#1853`_).
+ Thanks `@raquel-ucl`_ for the PR.
+
+* Got rid of ``AttributeError: 'Module' object has no attribute '_obj'`` exception
+ in Python 3 (`#1944`_).
+ Thanks `@axil`_ for the PR.
+
+* Explain a bad scope value passed to ``@fixture`` declarations or
+ a ``MetaFunc.parametrize()`` call. Thanks `@tgoodlet`_ for the PR.
+
+* This version includes ``pluggy-0.4.0``, which correctly handles
+ ``VersionConflict`` errors in plugins (`#704`_).
+ Thanks `@nicoddemus`_ for the PR.
+
+
+.. _@philpep: https://github.com/philpep
+.. _@raquel-ucl: https://github.com/raquel-ucl
+.. _@axil: https://github.com/axil
+.. _@tgoodlet: https://github.com/tgoodlet
+.. _@vlad-dragos: https://github.com/vlad-dragos
+
+.. _#1853: https://github.com/pytest-dev/pytest/issues/1853
+.. _#1905: https://github.com/pytest-dev/pytest/issues/1905
+.. _#1934: https://github.com/pytest-dev/pytest/issues/1934
+.. _#1944: https://github.com/pytest-dev/pytest/issues/1944
+.. _#704: https://github.com/pytest-dev/pytest/issues/704
+
+
+
+
+3.0.2 (2016-09-01)
+==================
+
+* Improve error message when passing non-string ids to ``pytest.mark.parametrize`` (`#1857`_).
+ Thanks `@okken`_ for the report and `@nicoddemus`_ for the PR.
+
+* Add ``buffer`` attribute to stdin stub class ``pytest.capture.DontReadFromInput``
+ Thanks `@joguSD`_ for the PR.
+
+* Fix ``UnicodeEncodeError`` when string comparison with unicode has failed. (`#1864`_)
+ Thanks `@AiOO`_ for the PR.
+
+* ``pytest_plugins`` is now handled correctly if defined as a string (as opposed as
+ a sequence of strings) when modules are considered for assertion rewriting.
+ Due to this bug, much more modules were being rewritten than necessary
+ if a test suite uses ``pytest_plugins`` to load internal plugins (`#1888`_).
+ Thanks `@jaraco`_ for the report and `@nicoddemus`_ for the PR (`#1891`_).
+
+* Do not call tearDown and cleanups when running tests from
+ ``unittest.TestCase`` subclasses with ``--pdb``
+ enabled. This allows proper post mortem debugging for all applications
+ which have significant logic in their tearDown machinery (`#1890`_). Thanks
+ `@mbyt`_ for the PR.
+
+* Fix use of deprecated ``getfuncargvalue`` method in the internal doctest plugin.
+ Thanks `@ViviCoder`_ for the report (`#1898`_).
+
+.. _@joguSD: https://github.com/joguSD
+.. _@AiOO: https://github.com/AiOO
+.. _@mbyt: https://github.com/mbyt
+.. _@ViviCoder: https://github.com/ViviCoder
+
+.. _#1857: https://github.com/pytest-dev/pytest/issues/1857
+.. _#1864: https://github.com/pytest-dev/pytest/issues/1864
+.. _#1888: https://github.com/pytest-dev/pytest/issues/1888
+.. _#1891: https://github.com/pytest-dev/pytest/pull/1891
+.. _#1890: https://github.com/pytest-dev/pytest/issues/1890
+.. _#1898: https://github.com/pytest-dev/pytest/issues/1898
+
+
+3.0.1 (2016-08-23)
+==================
+
+* Fix regression when ``importorskip`` is used at module level (`#1822`_).
+ Thanks `@jaraco`_ and `@The-Compiler`_ for the report and `@nicoddemus`_ for the PR.
+
+* Fix parametrization scope when session fixtures are used in conjunction
+ with normal parameters in the same call (`#1832`_).
+ Thanks `@The-Compiler`_ for the report, `@Kingdread`_ and `@nicoddemus`_ for the PR.
+
+* Fix internal error when parametrizing tests or fixtures using an empty ``ids`` argument (`#1849`_).
+ Thanks `@OPpuolitaival`_ for the report and `@nicoddemus`_ for the PR.
+
+* Fix loader error when running ``pytest`` embedded in a zipfile.
+ Thanks `@mbachry`_ for the PR.
+
+
+.. _@Kingdread: https://github.com/Kingdread
+.. _@mbachry: https://github.com/mbachry
+.. _@OPpuolitaival: https://github.com/OPpuolitaival
+
+.. _#1822: https://github.com/pytest-dev/pytest/issues/1822
+.. _#1832: https://github.com/pytest-dev/pytest/issues/1832
+.. _#1849: https://github.com/pytest-dev/pytest/issues/1849
+
+
+3.0.0 (2016-08-18)
+==================
+
+**Incompatible changes**
+
+
+A number of incompatible changes were made in this release, with the intent of removing features deprecated for a long
+time or change existing behaviors in order to make them less surprising/more useful.
+
+* Reinterpretation mode has now been removed. Only plain and rewrite
+ mode are available, consequently the ``--assert=reinterp`` option is
+ no longer available. This also means files imported from plugins or
+ ``conftest.py`` will not benefit from improved assertions by
+ default, you should use ``pytest.register_assert_rewrite()`` to
+ explicitly turn on assertion rewriting for those files. Thanks
+ `@flub`_ for the PR.
+
+* The following deprecated commandline options were removed:
+
+ * ``--genscript``: no longer supported;
+ * ``--no-assert``: use ``--assert=plain`` instead;
+ * ``--nomagic``: use ``--assert=plain`` instead;
+ * ``--report``: use ``-r`` instead;
+
+ Thanks to `@RedBeardCode`_ for the PR (`#1664`_).
+
+* ImportErrors in plugins now are a fatal error instead of issuing a
+ pytest warning (`#1479`_). Thanks to `@The-Compiler`_ for the PR.
+
+* Removed support code for Python 3 versions < 3.3 (`#1627`_).
+
+* Removed all ``py.test-X*`` entry points. The versioned, suffixed entry points
+ were never documented and a leftover from a pre-virtualenv era. These entry
+ points also created broken entry points in wheels, so removing them also
+ removes a source of confusion for users (`#1632`_).
+ Thanks `@obestwalter`_ for the PR.
+
+* ``pytest.skip()`` now raises an error when used to decorate a test function,
+ as opposed to its original intent (to imperatively skip a test inside a test function). Previously
+ this usage would cause the entire module to be skipped (`#607`_).
+ Thanks `@omarkohl`_ for the complete PR (`#1519`_).
+
+* Exit tests if a collection error occurs. A poll indicated most users will hit CTRL-C
+ anyway as soon as they see collection errors, so pytest might as well make that the default behavior (`#1421`_).
+ A ``--continue-on-collection-errors`` option has been added to restore the previous behaviour.
+ Thanks `@olegpidsadnyi`_ and `@omarkohl`_ for the complete PR (`#1628`_).
+
+* Renamed the pytest ``pdb`` module (plugin) into ``debugging`` to avoid clashes with the builtin ``pdb`` module.
+
+* Raise a helpful failure message when requesting a parametrized fixture at runtime,
+ e.g. with ``request.getfixturevalue``. Previously these parameters were simply
+ never defined, so a fixture decorated like ``@pytest.fixture(params=[0, 1, 2])``
+ only ran once (`#460`_).
+ Thanks to `@nikratio`_ for the bug report, `@RedBeardCode`_ and `@tomviner`_ for the PR.
+
+* ``_pytest.monkeypatch.monkeypatch`` class has been renamed to ``_pytest.monkeypatch.MonkeyPatch``
+ so it doesn't conflict with the ``monkeypatch`` fixture.
+
+* ``--exitfirst / -x`` can now be overridden by a following ``--maxfail=N``
+ and is just a synonym for ``--maxfail=1``.
+
+
+**New Features**
+
+* Support nose-style ``__test__`` attribute on methods of classes,
+ including unittest-style Classes. If set to ``False``, the test will not be
+ collected.
+
+* New ``doctest_namespace`` fixture for injecting names into the
+ namespace in which doctests run.
+ Thanks `@milliams`_ for the complete PR (`#1428`_).
+
+* New ``--doctest-report`` option available to change the output format of diffs
+ when running (failing) doctests (implements `#1749`_).
+ Thanks `@hartym`_ for the PR.
+
+* New ``name`` argument to ``pytest.fixture`` decorator which allows a custom name
+ for a fixture (to solve the funcarg-shadowing-fixture problem).
+ Thanks `@novas0x2a`_ for the complete PR (`#1444`_).
+
+* New ``approx()`` function for easily comparing floating-point numbers in
+ tests.
+ Thanks `@kalekundert`_ for the complete PR (`#1441`_).
+
+* Ability to add global properties in the final xunit output file by accessing
+ the internal ``junitxml`` plugin (experimental).
+ Thanks `@tareqalayan`_ for the complete PR `#1454`_).
+
+* New ``ExceptionInfo.match()`` method to match a regular expression on the
+ string representation of an exception (`#372`_).
+ Thanks `@omarkohl`_ for the complete PR (`#1502`_).
+
+* ``__tracebackhide__`` can now also be set to a callable which then can decide
+ whether to filter the traceback based on the ``ExceptionInfo`` object passed
+ to it. Thanks `@The-Compiler`_ for the complete PR (`#1526`_).
+
+* New ``pytest_make_parametrize_id(config, val)`` hook which can be used by plugins to provide
+ friendly strings for custom types.
+ Thanks `@palaviv`_ for the PR.
+
+* ``capsys`` and ``capfd`` now have a ``disabled()`` context-manager method, which
+ can be used to temporarily disable capture within a test.
+ Thanks `@nicoddemus`_ for the PR.
+
+* New cli flag ``--fixtures-per-test``: shows which fixtures are being used
+ for each selected test item. Features doc strings of fixtures by default.
+ Can also show where fixtures are defined if combined with ``-v``.
+ Thanks `@hackebrot`_ for the PR.
+
+* Introduce ``pytest`` command as recommended entry point. Note that ``py.test``
+ still works and is not scheduled for removal. Closes proposal
+ `#1629`_. Thanks `@obestwalter`_ and `@davehunt`_ for the complete PR
+ (`#1633`_).
+
+* New cli flags:
+
+ + ``--setup-plan``: performs normal collection and reports
+ the potential setup and teardown and does not execute any fixtures and tests;
+ + ``--setup-only``: performs normal collection, executes setup and teardown of
+ fixtures and reports them;
+ + ``--setup-show``: performs normal test execution and additionally shows
+ setup and teardown of fixtures;
+ + ``--keep-duplicates``: py.test now ignores duplicated paths given in the command
+ line. To retain the previous behavior where the same test could be run multiple
+ times by specifying it in the command-line multiple times, pass the ``--keep-duplicates``
+ argument (`#1609`_);
+
+ Thanks `@d6e`_, `@kvas-it`_, `@sallner`_, `@ioggstream`_ and `@omarkohl`_ for the PRs.
+
+* New CLI flag ``--override-ini``/``-o``: overrides values from the ini file.
+ For example: ``"-o xfail_strict=True"``'.
+ Thanks `@blueyed`_ and `@fengxx`_ for the PR.
+
+* New hooks:
+
+ + ``pytest_fixture_setup(fixturedef, request)``: executes fixture setup;
+ + ``pytest_fixture_post_finalizer(fixturedef)``: called after the fixture's
+ finalizer and has access to the fixture's result cache.
+
+ Thanks `@d6e`_, `@sallner`_.
+
+* Issue warnings for asserts whose test is a tuple literal. Such asserts will
+ never fail because tuples are always truthy and are usually a mistake
+ (see `#1562`_). Thanks `@kvas-it`_, for the PR.
+
+* Allow passing a custom debugger class (e.g. ``--pdbcls=IPython.core.debugger:Pdb``).
+ Thanks to `@anntzer`_ for the PR.
+
+
+**Changes**
+
+* Plugins now benefit from assertion rewriting. Thanks
+ `@sober7`_, `@nicoddemus`_ and `@flub`_ for the PR.
+
+* Change ``report.outcome`` for ``xpassed`` tests to ``"passed"`` in non-strict
+ mode and ``"failed"`` in strict mode. Thanks to `@hackebrot`_ for the PR
+ (`#1795`_) and `@gprasad84`_ for report (`#1546`_).
+
+* Tests marked with ``xfail(strict=False)`` (the default) now appear in
+ JUnitXML reports as passing tests instead of skipped.
+ Thanks to `@hackebrot`_ for the PR (`#1795`_).
+
+* Highlight path of the file location in the error report to make it easier to copy/paste.
+ Thanks `@suzaku`_ for the PR (`#1778`_).
+
+* Fixtures marked with ``@pytest.fixture`` can now use ``yield`` statements exactly like
+ those marked with the ``@pytest.yield_fixture`` decorator. This change renders
+ ``@pytest.yield_fixture`` deprecated and makes ``@pytest.fixture`` with ``yield`` statements
+ the preferred way to write teardown code (`#1461`_).
+ Thanks `@csaftoiu`_ for bringing this to attention and `@nicoddemus`_ for the PR.
+
+* Explicitly passed parametrize ids do not get escaped to ascii (`#1351`_).
+ Thanks `@ceridwen`_ for the PR.
+
+* Fixtures are now sorted in the error message displayed when an unknown
+ fixture is declared in a test function.
+ Thanks `@nicoddemus`_ for the PR.
+
+* ``pytest_terminal_summary`` hook now receives the ``exitstatus``
+ of the test session as argument. Thanks `@blueyed`_ for the PR (`#1809`_).
+
+* Parametrize ids can accept ``None`` as specific test id, in which case the
+ automatically generated id for that argument will be used.
+ Thanks `@palaviv`_ for the complete PR (`#1468`_).
+
+* The parameter to xunit-style setup/teardown methods (``setup_method``,
+ ``setup_module``, etc.) is now optional and may be omitted.
+ Thanks `@okken`_ for bringing this to attention and `@nicoddemus`_ for the PR.
+
+* Improved automatic id generation selection in case of duplicate ids in
+ parametrize.
+ Thanks `@palaviv`_ for the complete PR (`#1474`_).
+
+* Now pytest warnings summary is shown up by default. Added a new flag
+ ``--disable-pytest-warnings`` to explicitly disable the warnings summary (`#1668`_).
+
+* Make ImportError during collection more explicit by reminding
+ the user to check the name of the test module/package(s) (`#1426`_).
+ Thanks `@omarkohl`_ for the complete PR (`#1520`_).
+
+* Add ``build/`` and ``dist/`` to the default ``--norecursedirs`` list. Thanks
+ `@mikofski`_ for the report and `@tomviner`_ for the PR (`#1544`_).
+
+* ``pytest.raises`` in the context manager form accepts a custom
+ ``message`` to raise when no exception occurred.
+ Thanks `@palaviv`_ for the complete PR (`#1616`_).
+
+* ``conftest.py`` files now benefit from assertion rewriting; previously it
+ was only available for test modules. Thanks `@flub`_, `@sober7`_ and
+ `@nicoddemus`_ for the PR (`#1619`_).
+
+* Text documents without any doctests no longer appear as "skipped".
+ Thanks `@graingert`_ for reporting and providing a full PR (`#1580`_).
+
+* Ensure that a module within a namespace package can be found when it
+ is specified on the command line together with the ``--pyargs``
+ option. Thanks to `@taschini`_ for the PR (`#1597`_).
+
+* Always include full assertion explanation during assertion rewriting. The previous behaviour was hiding
+ sub-expressions that happened to be ``False``, assuming this was redundant information.
+ Thanks `@bagerard`_ for reporting (`#1503`_). Thanks to `@davehunt`_ and
+ `@tomviner`_ for the PR.
+
+* ``OptionGroup.addoption()`` now checks if option names were already
+ added before, to make it easier to track down issues like `#1618`_.
+ Before, you only got exceptions later from ``argparse`` library,
+ giving no clue about the actual reason for double-added options.
+
+* ``yield``-based tests are considered deprecated and will be removed in pytest-4.0.
+ Thanks `@nicoddemus`_ for the PR.
+
+* ``[pytest]`` sections in ``setup.cfg`` files should now be named ``[tool:pytest]``
+ to avoid conflicts with other distutils commands (see `#567`_). ``[pytest]`` sections in
+ ``pytest.ini`` or ``tox.ini`` files are supported and unchanged.
+ Thanks `@nicoddemus`_ for the PR.
+
+* Using ``pytest_funcarg__`` prefix to declare fixtures is considered deprecated and will be
+ removed in pytest-4.0 (`#1684`_).
+ Thanks `@nicoddemus`_ for the PR.
+
+* Passing a command-line string to ``pytest.main()`` is considered deprecated and scheduled
+ for removal in pytest-4.0. It is recommended to pass a list of arguments instead (`#1723`_).
+
+* Rename ``getfuncargvalue`` to ``getfixturevalue``. ``getfuncargvalue`` is
+ still present but is now considered deprecated. Thanks to `@RedBeardCode`_ and `@tomviner`_
+ for the PR (`#1626`_).
+
+* ``optparse`` type usage now triggers DeprecationWarnings (`#1740`_).
+
+
+* ``optparse`` backward compatibility supports float/complex types (`#457`_).
+
+* Refined logic for determining the ``rootdir``, considering only valid
+ paths which fixes a number of issues: `#1594`_, `#1435`_ and `#1471`_.
+ Updated the documentation according to current behavior. Thanks to
+ `@blueyed`_, `@davehunt`_ and `@matthiasha`_ for the PR.
+
+* Always include full assertion explanation. The previous behaviour was hiding
+ sub-expressions that happened to be False, assuming this was redundant information.
+ Thanks `@bagerard`_ for reporting (`#1503`_). Thanks to `@davehunt`_ and
+ `@tomviner`_ for PR.
+
+* Better message in case of not using parametrized variable (see `#1539`_).
+ Thanks to `@tramwaj29`_ for the PR.
+
+* Updated docstrings with a more uniform style.
+
+* Add stderr write for ``pytest.exit(msg)`` during startup. Previously the message was never shown.
+ Thanks `@BeyondEvil`_ for reporting `#1210`_. Thanks to `@JonathonSonesen`_ and
+ `@tomviner`_ for the PR.
+
+* No longer display the incorrect test deselection reason (`#1372`_).
+ Thanks `@ronnypfannschmidt`_ for the PR.
+
+* The ``--resultlog`` command line option has been deprecated: it is little used
+ and there are more modern and better alternatives (see `#830`_).
+ Thanks `@nicoddemus`_ for the PR.
+
+* Improve error message with fixture lookup errors: add an 'E' to the first
+ line and '>' to the rest. Fixes `#717`_. Thanks `@blueyed`_ for reporting and
+ a PR, `@eolo999`_ for the initial PR and `@tomviner`_ for his guidance during
+ EuroPython2016 sprint.
+
+
+**Bug Fixes**
+
+* Parametrize now correctly handles duplicated test ids.
+
+* Fix internal error issue when the ``method`` argument is missing for
+ ``teardown_method()`` (`#1605`_).
+
+* Fix exception visualization in case the current working directory (CWD) gets
+ deleted during testing (`#1235`_). Thanks `@bukzor`_ for reporting. PR by
+ `@marscher`_.
+
+* Improve test output for logical expression with brackets (`#925`_).
+ Thanks `@DRMacIver`_ for reporting and `@RedBeardCode`_ for the PR.
+
+* Create correct diff for strings ending with newlines (`#1553`_).
+ Thanks `@Vogtinator`_ for reporting and `@RedBeardCode`_ and
+ `@tomviner`_ for the PR.
+
+* ``ConftestImportFailure`` now shows the traceback making it easier to
+ identify bugs in ``conftest.py`` files (`#1516`_). Thanks `@txomon`_ for
+ the PR.
+
+* Text documents without any doctests no longer appear as "skipped".
+ Thanks `@graingert`_ for reporting and providing a full PR (`#1580`_).
+
+* Fixed collection of classes with custom ``__new__`` method.
+ Fixes `#1579`_. Thanks to `@Stranger6667`_ for the PR.
+
+* Fixed scope overriding inside metafunc.parametrize (`#634`_).
+ Thanks to `@Stranger6667`_ for the PR.
+
+* Fixed the total tests tally in junit xml output (`#1798`_).
+ Thanks to `@cryporchild`_ for the PR.
+
+* Fixed off-by-one error with lines from ``request.node.warn``.
+ Thanks to `@blueyed`_ for the PR.
+
+
+.. _#1210: https://github.com/pytest-dev/pytest/issues/1210
+.. _#1235: https://github.com/pytest-dev/pytest/issues/1235
+.. _#1351: https://github.com/pytest-dev/pytest/issues/1351
+.. _#1372: https://github.com/pytest-dev/pytest/issues/1372
+.. _#1421: https://github.com/pytest-dev/pytest/issues/1421
+.. _#1426: https://github.com/pytest-dev/pytest/issues/1426
+.. _#1428: https://github.com/pytest-dev/pytest/pull/1428
+.. _#1435: https://github.com/pytest-dev/pytest/issues/1435
+.. _#1441: https://github.com/pytest-dev/pytest/pull/1441
+.. _#1444: https://github.com/pytest-dev/pytest/pull/1444
+.. _#1454: https://github.com/pytest-dev/pytest/pull/1454
+.. _#1461: https://github.com/pytest-dev/pytest/pull/1461
+.. _#1468: https://github.com/pytest-dev/pytest/pull/1468
+.. _#1471: https://github.com/pytest-dev/pytest/issues/1471
+.. _#1474: https://github.com/pytest-dev/pytest/pull/1474
+.. _#1479: https://github.com/pytest-dev/pytest/issues/1479
+.. _#1502: https://github.com/pytest-dev/pytest/pull/1502
+.. _#1503: https://github.com/pytest-dev/pytest/issues/1503
+.. _#1516: https://github.com/pytest-dev/pytest/pull/1516
+.. _#1519: https://github.com/pytest-dev/pytest/pull/1519
+.. _#1520: https://github.com/pytest-dev/pytest/pull/1520
+.. _#1526: https://github.com/pytest-dev/pytest/pull/1526
+.. _#1539: https://github.com/pytest-dev/pytest/issues/1539
+.. _#1544: https://github.com/pytest-dev/pytest/issues/1544
+.. _#1546: https://github.com/pytest-dev/pytest/issues/1546
+.. _#1553: https://github.com/pytest-dev/pytest/issues/1553
+.. _#1562: https://github.com/pytest-dev/pytest/issues/1562
+.. _#1579: https://github.com/pytest-dev/pytest/issues/1579
+.. _#1580: https://github.com/pytest-dev/pytest/pull/1580
+.. _#1594: https://github.com/pytest-dev/pytest/issues/1594
+.. _#1597: https://github.com/pytest-dev/pytest/pull/1597
+.. _#1605: https://github.com/pytest-dev/pytest/issues/1605
+.. _#1616: https://github.com/pytest-dev/pytest/pull/1616
+.. _#1618: https://github.com/pytest-dev/pytest/issues/1618
+.. _#1619: https://github.com/pytest-dev/pytest/issues/1619
+.. _#1626: https://github.com/pytest-dev/pytest/pull/1626
+.. _#1627: https://github.com/pytest-dev/pytest/pull/1627
+.. _#1628: https://github.com/pytest-dev/pytest/pull/1628
+.. _#1629: https://github.com/pytest-dev/pytest/issues/1629
+.. _#1632: https://github.com/pytest-dev/pytest/issues/1632
+.. _#1633: https://github.com/pytest-dev/pytest/pull/1633
+.. _#1664: https://github.com/pytest-dev/pytest/pull/1664
+.. _#1668: https://github.com/pytest-dev/pytest/issues/1668
+.. _#1684: https://github.com/pytest-dev/pytest/pull/1684
+.. _#1723: https://github.com/pytest-dev/pytest/pull/1723
+.. _#1740: https://github.com/pytest-dev/pytest/issues/1740
+.. _#1749: https://github.com/pytest-dev/pytest/issues/1749
+.. _#1778: https://github.com/pytest-dev/pytest/pull/1778
+.. _#1795: https://github.com/pytest-dev/pytest/pull/1795
+.. _#1798: https://github.com/pytest-dev/pytest/pull/1798
+.. _#1809: https://github.com/pytest-dev/pytest/pull/1809
+.. _#372: https://github.com/pytest-dev/pytest/issues/372
+.. _#457: https://github.com/pytest-dev/pytest/issues/457
+.. _#460: https://github.com/pytest-dev/pytest/pull/460
+.. _#567: https://github.com/pytest-dev/pytest/pull/567
+.. _#607: https://github.com/pytest-dev/pytest/issues/607
+.. _#634: https://github.com/pytest-dev/pytest/issues/634
+.. _#717: https://github.com/pytest-dev/pytest/issues/717
+.. _#830: https://github.com/pytest-dev/pytest/issues/830
+.. _#925: https://github.com/pytest-dev/pytest/issues/925
+
+
+.. _@anntzer: https://github.com/anntzer
+.. _@bagerard: https://github.com/bagerard
+.. _@BeyondEvil: https://github.com/BeyondEvil
+.. _@blueyed: https://github.com/blueyed
+.. _@ceridwen: https://github.com/ceridwen
+.. _@cryporchild: https://github.com/cryporchild
+.. _@csaftoiu: https://github.com/csaftoiu
+.. _@d6e: https://github.com/d6e
+.. _@davehunt: https://github.com/davehunt
+.. _@DRMacIver: https://github.com/DRMacIver
+.. _@eolo999: https://github.com/eolo999
+.. _@fengxx: https://github.com/fengxx
+.. _@flub: https://github.com/flub
+.. _@gprasad84: https://github.com/gprasad84
+.. _@graingert: https://github.com/graingert
+.. _@hartym: https://github.com/hartym
+.. _@JonathonSonesen: https://github.com/JonathonSonesen
+.. _@kalekundert: https://github.com/kalekundert
+.. _@kvas-it: https://github.com/kvas-it
+.. _@marscher: https://github.com/marscher
+.. _@mikofski: https://github.com/mikofski
+.. _@milliams: https://github.com/milliams
+.. _@nikratio: https://github.com/nikratio
+.. _@novas0x2a: https://github.com/novas0x2a
+.. _@obestwalter: https://github.com/obestwalter
+.. _@okken: https://github.com/okken
+.. _@olegpidsadnyi: https://github.com/olegpidsadnyi
+.. _@omarkohl: https://github.com/omarkohl
+.. _@palaviv: https://github.com/palaviv
+.. _@RedBeardCode: https://github.com/RedBeardCode
+.. _@sallner: https://github.com/sallner
+.. _@sober7: https://github.com/sober7
+.. _@Stranger6667: https://github.com/Stranger6667
+.. _@suzaku: https://github.com/suzaku
+.. _@tareqalayan: https://github.com/tareqalayan
+.. _@taschini: https://github.com/taschini
+.. _@tramwaj29: https://github.com/tramwaj29
+.. _@txomon: https://github.com/txomon
+.. _@Vogtinator: https://github.com/Vogtinator
+.. _@matthiasha: https://github.com/matthiasha
+
+
+2.9.2 (2016-05-31)
+==================
+
+**Bug Fixes**
+
+* fix `#510`_: skip tests where one parameterize dimension was empty
+ thanks Alex Stapleton for the Report and `@RonnyPfannschmidt`_ for the PR
+
+* Fix Xfail does not work with condition keyword argument.
+ Thanks `@astraw38`_ for reporting the issue (`#1496`_) and `@tomviner`_
+ for PR the (`#1524`_).
+
+* Fix win32 path issue when putting custom config file with absolute path
+ in ``pytest.main("-c your_absolute_path")``.
+
+* Fix maximum recursion depth detection when raised error class is not aware
+ of unicode/encoded bytes.
+ Thanks `@prusse-martin`_ for the PR (`#1506`_).
+
+* Fix ``pytest.mark.skip`` mark when used in strict mode.
+ Thanks `@pquentin`_ for the PR and `@RonnyPfannschmidt`_ for
+ showing how to fix the bug.
+
+* Minor improvements and fixes to the documentation.
+ Thanks `@omarkohl`_ for the PR.
+
+* Fix ``--fixtures`` to show all fixture definitions as opposed to just
+ one per fixture name.
+ Thanks to `@hackebrot`_ for the PR.
+
+.. _#510: https://github.com/pytest-dev/pytest/issues/510
+.. _#1506: https://github.com/pytest-dev/pytest/pull/1506
+.. _#1496: https://github.com/pytest-dev/pytest/issues/1496
+.. _#1524: https://github.com/pytest-dev/pytest/pull/1524
+
+.. _@prusse-martin: https://github.com/prusse-martin
+.. _@astraw38: https://github.com/astraw38
+
+
+2.9.1 (2016-03-17)
+==================
+
+**Bug Fixes**
+
+* Improve error message when a plugin fails to load.
+ Thanks `@nicoddemus`_ for the PR.
+
+* Fix (`#1178 <https://github.com/pytest-dev/pytest/issues/1178>`_):
+ ``pytest.fail`` with non-ascii characters raises an internal pytest error.
+ Thanks `@nicoddemus`_ for the PR.
+
+* Fix (`#469`_): junit parses report.nodeid incorrectly, when params IDs
+ contain ``::``. Thanks `@tomviner`_ for the PR (`#1431`_).
+
+* Fix (`#578 <https://github.com/pytest-dev/pytest/issues/578>`_): SyntaxErrors
+ containing non-ascii lines at the point of failure generated an internal
+ py.test error.
+ Thanks `@asottile`_ for the report and `@nicoddemus`_ for the PR.
+
+* Fix (`#1437`_): When passing in a bytestring regex pattern to parameterize
+ attempt to decode it as utf-8 ignoring errors.
+
+* Fix (`#649`_): parametrized test nodes cannot be specified to run on the command line.
+
+* Fix (`#138`_): better reporting for python 3.3+ chained exceptions
+
+.. _#1437: https://github.com/pytest-dev/pytest/issues/1437
+.. _#469: https://github.com/pytest-dev/pytest/issues/469
+.. _#1431: https://github.com/pytest-dev/pytest/pull/1431
+.. _#649: https://github.com/pytest-dev/pytest/issues/649
+.. _#138: https://github.com/pytest-dev/pytest/issues/138
+
+.. _@asottile: https://github.com/asottile
+
+
+2.9.0 (2016-02-29)
+==================
+
+**New Features**
+
+* New ``pytest.mark.skip`` mark, which unconditionally skips marked tests.
+ Thanks `@MichaelAquilina`_ for the complete PR (`#1040`_).
+
+* ``--doctest-glob`` may now be passed multiple times in the command-line.
+ Thanks `@jab`_ and `@nicoddemus`_ for the PR.
+
+* New ``-rp`` and ``-rP`` reporting options give the summary and full output
+ of passing tests, respectively. Thanks to `@codewarrior0`_ for the PR.
+
+* ``pytest.mark.xfail`` now has a ``strict`` option, which makes ``XPASS``
+ tests to fail the test suite (defaulting to ``False``). There's also a
+ ``xfail_strict`` ini option that can be used to configure it project-wise.
+ Thanks `@rabbbit`_ for the request and `@nicoddemus`_ for the PR (`#1355`_).
+
+* ``Parser.addini`` now supports options of type ``bool``.
+ Thanks `@nicoddemus`_ for the PR.
+
+* New ``ALLOW_BYTES`` doctest option. This strips ``b`` prefixes from byte strings
+ in doctest output (similar to ``ALLOW_UNICODE``).
+ Thanks `@jaraco`_ for the request and `@nicoddemus`_ for the PR (`#1287`_).
+
+* Give a hint on ``KeyboardInterrupt`` to use the ``--fulltrace`` option to show the errors.
+ Fixes `#1366`_.
+ Thanks to `@hpk42`_ for the report and `@RonnyPfannschmidt`_ for the PR.
+
+* Catch ``IndexError`` exceptions when getting exception source location.
+ Fixes a pytest internal error for dynamically generated code (fixtures and tests)
+ where source lines are fake by intention.
+
+**Changes**
+
+* **Important**: `py.code <https://pylib.readthedocs.io/en/latest/code.html>`_ has been
+ merged into the ``pytest`` repository as ``pytest._code``. This decision
+ was made because ``py.code`` had very few uses outside ``pytest`` and the
+ fact that it was in a different repository made it difficult to fix bugs on
+ its code in a timely manner. The team hopes with this to be able to better
+ refactor out and improve that code.
+ This change shouldn't affect users, but it is useful to let users aware
+ if they encounter any strange behavior.
+
+ Keep in mind that the code for ``pytest._code`` is **private** and
+ **experimental**, so you definitely should not import it explicitly!
+
+ Please note that the original ``py.code`` is still available in
+ `pylib <https://pylib.readthedocs.io>`_.
+
+* ``pytest_enter_pdb`` now optionally receives the pytest config object.
+ Thanks `@nicoddemus`_ for the PR.
+
+* Removed code and documentation for Python 2.5 or lower versions,
+ including removal of the obsolete ``_pytest.assertion.oldinterpret`` module.
+ Thanks `@nicoddemus`_ for the PR (`#1226`_).
+
+* Comparisons now always show up in full when ``CI`` or ``BUILD_NUMBER`` is
+ found in the environment, even when ``-vv`` isn't used.
+ Thanks `@The-Compiler`_ for the PR.
+
+* ``--lf`` and ``--ff`` now support long names: ``--last-failed`` and
+ ``--failed-first`` respectively.
+ Thanks `@MichaelAquilina`_ for the PR.
+
+* Added expected exceptions to ``pytest.raises`` fail message.
+
+* Collection only displays progress ("collecting X items") when in a terminal.
+ This avoids cluttering the output when using ``--color=yes`` to obtain
+ colors in CI integrations systems (`#1397`_).
+
+**Bug Fixes**
+
+* The ``-s`` and ``-c`` options should now work under ``xdist``;
+ ``Config.fromdictargs`` now represents its input much more faithfully.
+ Thanks to `@bukzor`_ for the complete PR (`#680`_).
+
+* Fix (`#1290`_): support Python 3.5's ``@`` operator in assertion rewriting.
+ Thanks `@Shinkenjoe`_ for report with test case and `@tomviner`_ for the PR.
+
+* Fix formatting utf-8 explanation messages (`#1379`_).
+ Thanks `@biern`_ for the PR.
+
+* Fix `traceback style docs`_ to describe all of the available options
+ (auto/long/short/line/native/no), with ``auto`` being the default since v2.6.
+ Thanks `@hackebrot`_ for the PR.
+
+* Fix (`#1422`_): junit record_xml_property doesn't allow multiple records
+ with same name.
+
+.. _`traceback style docs`: https://pytest.org/latest/usage.html#modifying-python-traceback-printing
+
+.. _#1609: https://github.com/pytest-dev/pytest/issues/1609
+.. _#1422: https://github.com/pytest-dev/pytest/issues/1422
+.. _#1379: https://github.com/pytest-dev/pytest/issues/1379
+.. _#1366: https://github.com/pytest-dev/pytest/issues/1366
+.. _#1040: https://github.com/pytest-dev/pytest/pull/1040
+.. _#680: https://github.com/pytest-dev/pytest/issues/680
+.. _#1287: https://github.com/pytest-dev/pytest/pull/1287
+.. _#1226: https://github.com/pytest-dev/pytest/pull/1226
+.. _#1290: https://github.com/pytest-dev/pytest/pull/1290
+.. _#1355: https://github.com/pytest-dev/pytest/pull/1355
+.. _#1397: https://github.com/pytest-dev/pytest/issues/1397
+.. _@biern: https://github.com/biern
+.. _@MichaelAquilina: https://github.com/MichaelAquilina
+.. _@bukzor: https://github.com/bukzor
+.. _@hpk42: https://github.com/hpk42
+.. _@nicoddemus: https://github.com/nicoddemus
+.. _@jab: https://github.com/jab
+.. _@codewarrior0: https://github.com/codewarrior0
+.. _@jaraco: https://github.com/jaraco
+.. _@The-Compiler: https://github.com/The-Compiler
+.. _@Shinkenjoe: https://github.com/Shinkenjoe
+.. _@tomviner: https://github.com/tomviner
+.. _@RonnyPfannschmidt: https://github.com/RonnyPfannschmidt
+.. _@rabbbit: https://github.com/rabbbit
+.. _@hackebrot: https://github.com/hackebrot
+.. _@pquentin: https://github.com/pquentin
+.. _@ioggstream: https://github.com/ioggstream
+
+2.8.7 (2016-01-24)
+==================
+
+- fix #1338: use predictable object resolution for monkeypatch
+
+2.8.6 (2016-01-21)
+==================
+
+- fix #1259: allow for double nodeids in junitxml,
+ this was a regression failing plugins combinations
+ like pytest-pep8 + pytest-flakes
+
+- Workaround for exception that occurs in pyreadline when using
+ ``--pdb`` with standard I/O capture enabled.
+ Thanks Erik M. Bray for the PR.
+
+- fix #900: Better error message in case the target of a ``monkeypatch`` call
+ raises an ``ImportError``.
+
+- fix #1292: monkeypatch calls (setattr, setenv, etc.) are now O(1).
+ Thanks David R. MacIver for the report and Bruno Oliveira for the PR.
+
+- fix #1223: captured stdout and stderr are now properly displayed before
+ entering pdb when ``--pdb`` is used instead of being thrown away.
+ Thanks Cal Leeming for the PR.
+
+- fix #1305: pytest warnings emitted during ``pytest_terminal_summary`` are now
+ properly displayed.
+ Thanks Ionel Maries Cristian for the report and Bruno Oliveira for the PR.
+
+- fix #628: fixed internal UnicodeDecodeError when doctests contain unicode.
+ Thanks Jason R. Coombs for the report and Bruno Oliveira for the PR.
+
+- fix #1334: Add captured stdout to jUnit XML report on setup error.
+ Thanks Georgy Dyuldin for the PR.
+
+
+2.8.5 (2015-12-11)
+==================
+
+- fix #1243: fixed issue where class attributes injected during collection could break pytest.
+ PR by Alexei Kozlenok, thanks Ronny Pfannschmidt and Bruno Oliveira for the review and help.
+
+- fix #1074: precompute junitxml chunks instead of storing the whole tree in objects
+ Thanks Bruno Oliveira for the report and Ronny Pfannschmidt for the PR
+
+- fix #1238: fix ``pytest.deprecated_call()`` receiving multiple arguments
+ (Regression introduced in 2.8.4). Thanks Alex Gaynor for the report and
+ Bruno Oliveira for the PR.
+
+
+2.8.4 (2015-12-06)
+==================
+
+- fix #1190: ``deprecated_call()`` now works when the deprecated
+ function has been already called by another test in the same
+ module. Thanks Mikhail Chernykh for the report and Bruno Oliveira for the
+ PR.
+
+- fix #1198: ``--pastebin`` option now works on Python 3. Thanks
+ Mehdy Khoshnoody for the PR.
+
+- fix #1219: ``--pastebin`` now works correctly when captured output contains
+ non-ascii characters. Thanks Bruno Oliveira for the PR.
+
+- fix #1204: another error when collecting with a nasty __getattr__().
+ Thanks Florian Bruhin for the PR.
+
+- fix the summary printed when no tests did run.
+ Thanks Florian Bruhin for the PR.
+- fix #1185 - ensure MANIFEST.in exactly matches what should go to a sdist
+
+- a number of documentation modernizations wrt good practices.
+ Thanks Bruno Oliveira for the PR.
+
+2.8.3 (2015-11-18)
+==================
+
+- fix #1169: add __name__ attribute to testcases in TestCaseFunction to
+ support the @unittest.skip decorator on functions and methods.
+ Thanks Lee Kamentsky for the PR.
+
+- fix #1035: collecting tests if test module level obj has __getattr__().
+ Thanks Suor for the report and Bruno Oliveira / Tom Viner for the PR.
+
+- fix #331: don't collect tests if their failure cannot be reported correctly
+ e.g. they are a callable instance of a class.
+
+- fix #1133: fixed internal error when filtering tracebacks where one entry
+ belongs to a file which is no longer available.
+ Thanks Bruno Oliveira for the PR.
+
+- enhancement made to highlight in red the name of the failing tests so
+ they stand out in the output.
+ Thanks Gabriel Reis for the PR.
+
+- add more talks to the documentation
+- extend documentation on the --ignore cli option
+- use pytest-runner for setuptools integration
+- minor fixes for interaction with OS X El Capitan
+ system integrity protection (thanks Florian)
+
+
+2.8.2 (2015-10-07)
+==================
+
+- fix #1085: proper handling of encoding errors when passing encoded byte
+ strings to pytest.parametrize in Python 2.
+ Thanks Themanwithoutaplan for the report and Bruno Oliveira for the PR.
+
+- fix #1087: handling SystemError when passing empty byte strings to
+ pytest.parametrize in Python 3.
+ Thanks Paul Kehrer for the report and Bruno Oliveira for the PR.
+
+- fix #995: fixed internal error when filtering tracebacks where one entry
+ was generated by an exec() statement.
+ Thanks Daniel Hahler, Ashley C Straw, Philippe Gauthier and Pavel Savchenko
+ for contributing and Bruno Oliveira for the PR.
+
+- fix #1100 and #1057: errors when using autouse fixtures and doctest modules.
+ Thanks Sergey B Kirpichev and Vital Kudzelka for contributing and Bruno
+ Oliveira for the PR.
+
+2.8.1 (2015-09-29)
+==================
+
+- fix #1034: Add missing nodeid on pytest_logwarning call in
+ addhook. Thanks Simon Gomizelj for the PR.
+
+- 'deprecated_call' is now only satisfied with a DeprecationWarning or
+ PendingDeprecationWarning. Before 2.8.0, it accepted any warning, and 2.8.0
+ made it accept only DeprecationWarning (but not PendingDeprecationWarning).
+ Thanks Alex Gaynor for the issue and Eric Hunsberger for the PR.
+
+- fix issue #1073: avoid calling __getattr__ on potential plugin objects.
+ This fixes an incompatibility with pytest-django. Thanks Andreas Pelme,
+ Bruno Oliveira and Ronny Pfannschmidt for contributing and Holger Krekel
+ for the fix.
+
+- Fix issue #704: handle versionconflict during plugin loading more
+ gracefully. Thanks Bruno Oliveira for the PR.
+
+- Fix issue #1064: ""--junitxml" regression when used with the
+ "pytest-xdist" plugin, with test reports being assigned to the wrong tests.
+ Thanks Daniel Grunwald for the report and Bruno Oliveira for the PR.
+
+- (experimental) adapt more SEMVER style versioning and change meaning of
+ master branch in git repo: "master" branch now keeps the bugfixes, changes
+ aimed for micro releases. "features" branch will only be released
+ with minor or major pytest releases.
+
+- Fix issue #766 by removing documentation references to distutils.
+ Thanks Russel Winder.
+
+- Fix issue #1030: now byte-strings are escaped to produce item node ids
+ to make them always serializable.
+ Thanks Andy Freeland for the report and Bruno Oliveira for the PR.
+
+- Python 2: if unicode parametrized values are convertible to ascii, their
+ ascii representation is used for the node id.
+
+- Fix issue #411: Add __eq__ method to assertion comparison example.
+ Thanks Ben Webb.
+- Fix issue #653: deprecated_call can be used as context manager.
+
+- fix issue 877: properly handle assertion explanations with non-ascii repr
+ Thanks Mathieu Agopian for the report and Ronny Pfannschmidt for the PR.
+
+- fix issue 1029: transform errors when writing cache values into pytest-warnings
+
+2.8.0 (2015-09-18)
+==================
+
+- new ``--lf`` and ``-ff`` options to run only the last failing tests or
+ "failing tests first" from the last run. This functionality is provided
+ through porting the formerly external pytest-cache plugin into pytest core.
+ BACKWARD INCOMPAT: if you used pytest-cache's functionality to persist
+ data between test runs be aware that we don't serialize sets anymore.
+ Thanks Ronny Pfannschmidt for most of the merging work.
+
+- "-r" option now accepts "a" to include all possible reports, similar
+ to passing "fEsxXw" explicitly (isse960).
+ Thanks Abhijeet Kasurde for the PR.
+
+- avoid python3.5 deprecation warnings by introducing version
+ specific inspection helpers, thanks Michael Droettboom.
+
+- fix issue562: @nose.tools.istest now fully respected.
+
+- fix issue934: when string comparison fails and a diff is too large to display
+ without passing -vv, still show a few lines of the diff.
+ Thanks Florian Bruhin for the report and Bruno Oliveira for the PR.
+
+- fix issue736: Fix a bug where fixture params would be discarded when combined
+ with parametrization markers.
+ Thanks to Markus Unterwaditzer for the PR.
+
+- fix issue710: introduce ALLOW_UNICODE doctest option: when enabled, the
+ ``u`` prefix is stripped from unicode strings in expected doctest output. This
+ allows doctests which use unicode to run in Python 2 and 3 unchanged.
+ Thanks Jason R. Coombs for the report and Bruno Oliveira for the PR.
+
+- parametrize now also generates meaningful test IDs for enum, regex and class
+ objects (as opposed to class instances).
+ Thanks to Florian Bruhin for the PR.
+
+- Add 'warns' to assert that warnings are thrown (like 'raises').
+ Thanks to Eric Hunsberger for the PR.
+
+- Fix issue683: Do not apply an already applied mark. Thanks ojake for the PR.
+
+- Deal with capturing failures better so fewer exceptions get lost to
+ /dev/null. Thanks David Szotten for the PR.
+
+- fix issue730: deprecate and warn about the --genscript option.
+ Thanks Ronny Pfannschmidt for the report and Christian Pommranz for the PR.
+
+- fix issue751: multiple parametrize with ids bug if it parametrizes class with
+ two or more test methods. Thanks Sergey Chipiga for reporting and Jan
+ Bednarik for PR.
+
+- fix issue82: avoid loading conftest files from setup.cfg/pytest.ini/tox.ini
+ files and upwards by default (--confcutdir can still be set to override this).
+ Thanks Bruno Oliveira for the PR.
+
+- fix issue768: docstrings found in python modules were not setting up session
+ fixtures. Thanks Jason R. Coombs for reporting and Bruno Oliveira for the PR.
+
+- added ``tmpdir_factory``, a session-scoped fixture that can be used to create
+ directories under the base temporary directory. Previously this object was
+ installed as a ``_tmpdirhandler`` attribute of the ``config`` object, but now it
+ is part of the official API and using ``config._tmpdirhandler`` is
+ deprecated.
+ Thanks Bruno Oliveira for the PR.
+
+- fix issue808: pytest's internal assertion rewrite hook now implements the
+ optional PEP302 get_data API so tests can access data files next to them.
+ Thanks xmo-odoo for request and example and Bruno Oliveira for
+ the PR.
+
+- rootdir and inifile are now displayed during usage errors to help
+ users diagnose problems such as unexpected ini files which add
+ unknown options being picked up by pytest. Thanks to Pavel Savchenko for
+ bringing the problem to attention in #821 and Bruno Oliveira for the PR.
+
+- Summary bar now is colored yellow for warning
+ situations such as: all tests either were skipped or xpass/xfailed,
+ or no tests were run at all (this is a partial fix for issue500).
+
+- fix issue812: pytest now exits with status code 5 in situations where no
+ tests were run at all, such as the directory given in the command line does
+ not contain any tests or as result of a command line option filters
+ all out all tests (-k for example).
+ Thanks Eric Siegerman (issue812) and Bruno Oliveira for the PR.
+
+- Summary bar now is colored yellow for warning
+ situations such as: all tests either were skipped or xpass/xfailed,
+ or no tests were run at all (related to issue500).
+ Thanks Eric Siegerman.
+
+- New ``testpaths`` ini option: list of directories to search for tests
+ when executing pytest from the root directory. This can be used
+ to speed up test collection when a project has well specified directories
+ for tests, being usually more practical than configuring norecursedirs for
+ all directories that do not contain tests.
+ Thanks to Adrian for idea (#694) and Bruno Oliveira for the PR.
+
+- fix issue713: JUnit XML reports for doctest failures.
+ Thanks Punyashloka Biswal.
+
+- fix issue970: internal pytest warnings now appear as "pytest-warnings" in
+ the terminal instead of "warnings", so it is clear for users that those
+ warnings are from pytest and not from the builtin "warnings" module.
+ Thanks Bruno Oliveira.
+
+- Include setup and teardown in junitxml test durations.
+ Thanks Janne Vanhala.
+
+- fix issue735: assertion failures on debug versions of Python 3.4+
+
+- new option ``--import-mode`` to allow to change test module importing
+ behaviour to append to sys.path instead of prepending. This better allows
+ to run test modules against installed versions of a package even if the
+ package under test has the same import root. In this example::
+
+ testing/__init__.py
+ testing/test_pkg_under_test.py
+ pkg_under_test/
+
+ the tests will run against the installed version
+ of pkg_under_test when ``--import-mode=append`` is used whereas
+ by default they would always pick up the local version. Thanks Holger Krekel.
+
+- pytester: add method ``TmpTestdir.delete_loaded_modules()``, and call it
+ from ``inline_run()`` to allow temporary modules to be reloaded.
+ Thanks Eduardo Schettino.
+
+- internally refactor pluginmanager API and code so that there
+ is a clear distinction between a pytest-agnostic rather simple
+ pluginmanager and the PytestPluginManager which adds a lot of
+ behaviour, among it handling of the local conftest files.
+ In terms of documented methods this is a backward compatible
+ change but it might still break 3rd party plugins which relied on
+ details like especially the pluginmanager.add_shutdown() API.
+ Thanks Holger Krekel.
+
+- pluginmanagement: introduce ``pytest.hookimpl`` and
+ ``pytest.hookspec`` decorators for setting impl/spec
+ specific parameters. This substitutes the previous
+ now deprecated use of ``pytest.mark`` which is meant to
+ contain markers for test functions only.
+
+- write/refine docs for "writing plugins" which now have their
+ own page and are separate from the "using/installing plugins`` page.
+
+- fix issue732: properly unregister plugins from any hook calling
+ sites allowing to have temporary plugins during test execution.
+
+- deprecate and warn about ``__multicall__`` argument in hook
+ implementations. Use the ``hookwrapper`` mechanism instead already
+ introduced with pytest-2.7.
+
+- speed up pytest's own test suite considerably by using inprocess
+ tests by default (testrun can be modified with --runpytest=subprocess
+ to create subprocesses in many places instead). The main
+ APIs to run pytest in a test is "runpytest()" or "runpytest_subprocess"
+ and "runpytest_inprocess" if you need a particular way of running
+ the test. In all cases you get back a RunResult but the inprocess
+ one will also have a "reprec" attribute with the recorded events/reports.
+
+- fix monkeypatch.setattr("x.y", raising=False) to actually not raise
+ if "y" is not a pre-existing attribute. Thanks Florian Bruhin.
+
+- fix issue741: make running output from testdir.run copy/pasteable
+ Thanks Bruno Oliveira.
+
+- add a new ``--noconftest`` argument which ignores all ``conftest.py`` files.
+
+- add ``file`` and ``line`` attributes to JUnit-XML output.
+
+- fix issue890: changed extension of all documentation files from ``txt`` to
+ ``rst``. Thanks to Abhijeet for the PR.
+
+- fix issue714: add ability to apply indirect=True parameter on particular argnames.
+ Thanks Elizaveta239.
+
+- fix issue890: changed extension of all documentation files from ``txt`` to
+ ``rst``. Thanks to Abhijeet for the PR.
+
+- fix issue957: "# doctest: SKIP" option will now register doctests as SKIPPED
+ rather than PASSED.
+ Thanks Thomas Grainger for the report and Bruno Oliveira for the PR.
+
+- issue951: add new record_xml_property fixture, that supports logging
+ additional information on xml output. Thanks David Diaz for the PR.
+
+- issue949: paths after normal options (for example ``-s``, ``-v``, etc) are now
+ properly used to discover ``rootdir`` and ``ini`` files.
+ Thanks Peter Lauri for the report and Bruno Oliveira for the PR.
+
+2.7.3 (2015-09-15)
+==================
+
+- Allow 'dev', 'rc', or other non-integer version strings in ``importorskip``.
+ Thanks to Eric Hunsberger for the PR.
+
+- fix issue856: consider --color parameter in all outputs (for example
+ --fixtures). Thanks Barney Gale for the report and Bruno Oliveira for the PR.
+
+- fix issue855: passing str objects as ``plugins`` argument to pytest.main
+ is now interpreted as a module name to be imported and registered as a
+ plugin, instead of silently having no effect.
+ Thanks xmo-odoo for the report and Bruno Oliveira for the PR.
+
+- fix issue744: fix for ast.Call changes in Python 3.5+. Thanks
+ Guido van Rossum, Matthias Bussonnier, Stefan Zimmermann and
+ Thomas Kluyver.
+
+- fix issue842: applying markers in classes no longer propagate this markers
+ to superclasses which also have markers.
+ Thanks xmo-odoo for the report and Bruno Oliveira for the PR.
+
+- preserve warning functions after call to pytest.deprecated_call. Thanks
+ Pieter Mulder for PR.
+
+- fix issue854: autouse yield_fixtures defined as class members of
+ unittest.TestCase subclasses now work as expected.
+ Thannks xmo-odoo for the report and Bruno Oliveira for the PR.
+
+- fix issue833: --fixtures now shows all fixtures of collected test files, instead of just the
+ fixtures declared on the first one.
+ Thanks Florian Bruhin for reporting and Bruno Oliveira for the PR.
+
+- fix issue863: skipped tests now report the correct reason when a skip/xfail
+ condition is met when using multiple markers.
+ Thanks Raphael Pierzina for reporting and Bruno Oliveira for the PR.
+
+- optimized tmpdir fixture initialization, which should make test sessions
+ faster (specially when using pytest-xdist). The only visible effect
+ is that now pytest uses a subdirectory in the $TEMP directory for all
+ directories created by this fixture (defaults to $TEMP/pytest-$USER).
+ Thanks Bruno Oliveira for the PR.
+
+2.7.2 (2015-06-23)
+==================
+
+- fix issue767: pytest.raises value attribute does not contain the exception
+ instance on Python 2.6. Thanks Eric Siegerman for providing the test
+ case and Bruno Oliveira for PR.
+
+- Automatically create directory for junitxml and results log.
+ Thanks Aron Curzon.
+
+- fix issue713: JUnit XML reports for doctest failures.
+ Thanks Punyashloka Biswal.
+
+- fix issue735: assertion failures on debug versions of Python 3.4+
+ Thanks Benjamin Peterson.
+
+- fix issue114: skipif marker reports to internal skipping plugin;
+ Thanks Floris Bruynooghe for reporting and Bruno Oliveira for the PR.
+
+- fix issue748: unittest.SkipTest reports to internal pytest unittest plugin.
+ Thanks Thomas De Schampheleire for reporting and Bruno Oliveira for the PR.
+
+- fix issue718: failed to create representation of sets containing unsortable
+ elements in python 2. Thanks Edison Gustavo Muenz.
+
+- fix issue756, fix issue752 (and similar issues): depend on py-1.4.29
+ which has a refined algorithm for traceback generation.
+
+
+2.7.1 (2015-05-19)
+==================
+
+- fix issue731: do not get confused by the braces which may be present
+ and unbalanced in an object's repr while collapsing False
+ explanations. Thanks Carl Meyer for the report and test case.
+
+- fix issue553: properly handling inspect.getsourcelines failures in
+ FixtureLookupError which would lead to an internal error,
+ obfuscating the original problem. Thanks talljosh for initial
+ diagnose/patch and Bruno Oliveira for final patch.
+
+- fix issue660: properly report scope-mismatch-access errors
+ independently from ordering of fixture arguments. Also
+ avoid the pytest internal traceback which does not provide
+ information to the user. Thanks Holger Krekel.
+
+- streamlined and documented release process. Also all versions
+ (in setup.py and documentation generation) are now read
+ from _pytest/__init__.py. Thanks Holger Krekel.
+
+- fixed docs to remove the notion that yield-fixtures are experimental.
+ They are here to stay :) Thanks Bruno Oliveira.
+
+- Support building wheels by using environment markers for the
+ requirements. Thanks Ionel Maries Cristian.
+
+- fixed regression to 2.6.4 which surfaced e.g. in lost stdout capture printing
+ when tests raised SystemExit. Thanks Holger Krekel.
+
+- reintroduced _pytest fixture of the pytester plugin which is used
+ at least by pytest-xdist.
+
+2.7.0 (2015-03-26)
+==================
+
+- fix issue435: make reload() work when assert rewriting is active.
+ Thanks Daniel Hahler.
+
+- fix issue616: conftest.py files and their contained fixutres are now
+ properly considered for visibility, independently from the exact
+ current working directory and test arguments that are used.
+ Many thanks to Eric Siegerman and his PR235 which contains
+ systematic tests for conftest visibility and now passes.
+ This change also introduces the concept of a ``rootdir`` which
+ is printed as a new pytest header and documented in the pytest
+ customize web page.
+
+- change reporting of "diverted" tests, i.e. tests that are collected
+ in one file but actually come from another (e.g. when tests in a test class
+ come from a base class in a different file). We now show the nodeid
+ and indicate via a postfix the other file.
+
+- add ability to set command line options by environment variable PYTEST_ADDOPTS.
+
+- added documentation on the new pytest-dev teams on bitbucket and
+ github. See https://pytest.org/latest/contributing.html .
+ Thanks to Anatoly for pushing and initial work on this.
+
+- fix issue650: new option ``--docttest-ignore-import-errors`` which
+ will turn import errors in doctests into skips. Thanks Charles Cloud
+ for the complete PR.
+
+- fix issue655: work around different ways that cause python2/3
+ to leak sys.exc_info into fixtures/tests causing failures in 3rd party code
+
+- fix issue615: assertion rewriting did not correctly escape % signs
+ when formatting boolean operations, which tripped over mixing
+ booleans with modulo operators. Thanks to Tom Viner for the report,
+ triaging and fix.
+
+- implement issue351: add ability to specify parametrize ids as a callable
+ to generate custom test ids. Thanks Brianna Laugher for the idea and
+ implementation.
+
+- introduce and document new hookwrapper mechanism useful for plugins
+ which want to wrap the execution of certain hooks for their purposes.
+ This supersedes the undocumented ``__multicall__`` protocol which
+ pytest itself and some external plugins use. Note that pytest-2.8
+ is scheduled to drop supporting the old ``__multicall__``
+ and only support the hookwrapper protocol.
+
+- majorly speed up invocation of plugin hooks
+
+- use hookwrapper mechanism in builtin pytest plugins.
+
+- add a doctest ini option for doctest flags, thanks Holger Peters.
+
+- add note to docs that if you want to mark a parameter and the
+ parameter is a callable, you also need to pass in a reason to disambiguate
+ it from the "decorator" case. Thanks Tom Viner.
+
+- "python_classes" and "python_functions" options now support glob-patterns
+ for test discovery, as discussed in issue600. Thanks Ldiary Translations.
+
+- allow to override parametrized fixtures with non-parametrized ones and vice versa (bubenkoff).
+
+- fix issue463: raise specific error for 'parameterize' misspelling (pfctdayelise).
+
+- On failure, the ``sys.last_value``, ``sys.last_type`` and
+ ``sys.last_traceback`` are set, so that a user can inspect the error
+ via postmortem debugging (almarklein).
+
+2.6.4 (2014-10-24)
+==================
+
+- Improve assertion failure reporting on iterables, by using ndiff and
+ pprint.
+
+- removed outdated japanese docs from source tree.
+
+- docs for "pytest_addhooks" hook. Thanks Bruno Oliveira.
+
+- updated plugin index docs. Thanks Bruno Oliveira.
+
+- fix issue557: with "-k" we only allow the old style "-" for negation
+ at the beginning of strings and even that is deprecated. Use "not" instead.
+ This should allow to pick parametrized tests where "-" appeared in the parameter.
+
+- fix issue604: Escape % character in the assertion message.
+
+- fix issue620: add explanation in the --genscript target about what
+ the binary blob means. Thanks Dinu Gherman.
+
+- fix issue614: fixed pastebin support.
+
+
+- fix issue620: add explanation in the --genscript target about what
+ the binary blob means. Thanks Dinu Gherman.
+
+- fix issue614: fixed pastebin support.
+
+2.6.3 (2014-09-24)
+==================
+
+- fix issue575: xunit-xml was reporting collection errors as failures
+ instead of errors, thanks Oleg Sinyavskiy.
+
+- fix issue582: fix setuptools example, thanks Laszlo Papp and Ronny
+ Pfannschmidt.
+
+- Fix infinite recursion bug when pickling capture.EncodedFile, thanks
+ Uwe Schmitt.
+
+- fix issue589: fix bad interaction with numpy and others when showing
+ exceptions. Check for precise "maximum recursion depth exceed" exception
+ instead of presuming any RuntimeError is that one (implemented in py
+ dep). Thanks Charles Cloud for analysing the issue.
+
+- fix conftest related fixture visibility issue: when running with a
+ CWD outside of a test package pytest would get fixture discovery wrong.
+ Thanks to Wolfgang Schnerring for figuring out a reproducible example.
+
+- Introduce pytest_enter_pdb hook (needed e.g. by pytest_timeout to cancel the
+ timeout when interactively entering pdb). Thanks Wolfgang Schnerring.
+
+- check xfail/skip also with non-python function test items. Thanks
+ Floris Bruynooghe.
+
+2.6.2 (2014-09-05)
+==================
+
+- Added function pytest.freeze_includes(), which makes it easy to embed
+ pytest into executables using tools like cx_freeze.
+ See docs for examples and rationale. Thanks Bruno Oliveira.
+
+- Improve assertion rewriting cache invalidation precision.
+
+- fixed issue561: adapt autouse fixture example for python3.
+
+- fixed issue453: assertion rewriting issue with __repr__ containing
+ "\n{", "\n}" and "\n~".
+
+- fix issue560: correctly display code if an "else:" or "finally:" is
+ followed by statements on the same line.
+
+- Fix example in monkeypatch documentation, thanks t-8ch.
+
+- fix issue572: correct tmpdir doc example for python3.
+
+- Do not mark as universal wheel because Python 2.6 is different from
+ other builds due to the extra argparse dependency. Fixes issue566.
+ Thanks sontek.
+
+- Implement issue549: user-provided assertion messages now no longer
+ replace the py.test introspection message but are shown in addition
+ to them.
+
+2.6.1 (2014-08-07)
+==================
+
+- No longer show line numbers in the --verbose output, the output is now
+ purely the nodeid. The line number is still shown in failure reports.
+ Thanks Floris Bruynooghe.
+
+- fix issue437 where assertion rewriting could cause pytest-xdist slaves
+ to collect different tests. Thanks Bruno Oliveira.
+
+- fix issue555: add "errors" attribute to capture-streams to satisfy
+ some distutils and possibly other code accessing sys.stdout.errors.
+
+- fix issue547 capsys/capfd also work when output capturing ("-s") is disabled.
+
+- address issue170: allow pytest.mark.xfail(...) to specify expected exceptions via
+ an optional "raises=EXC" argument where EXC can be a single exception
+ or a tuple of exception classes. Thanks David Mohr for the complete
+ PR.
+
+- fix integration of pytest with unittest.mock.patch decorator when
+ it uses the "new" argument. Thanks Nicolas Delaby for test and PR.
+
+- fix issue with detecting conftest files if the arguments contain
+ "::" node id specifications (copy pasted from "-v" output)
+
+- fix issue544 by only removing "@NUM" at the end of "::" separated parts
+ and if the part has an ".py" extension
+
+- don't use py.std import helper, rather import things directly.
+ Thanks Bruno Oliveira.
+
+2.6
+===
+
+- Cache exceptions from fixtures according to their scope (issue 467).
+
+- fix issue537: Avoid importing old assertion reinterpretation code by default.
+
+- fix issue364: shorten and enhance tracebacks representation by default.
+ The new "--tb=auto" option (default) will only display long tracebacks
+ for the first and last entry. You can get the old behaviour of printing
+ all entries as long entries with "--tb=long". Also short entries by
+ default are now printed very similarly to "--tb=native" ones.
+
+- fix issue514: teach assertion reinterpretation about private class attributes
+
+- change -v output to include full node IDs of tests. Users can copy
+ a node ID from a test run, including line number, and use it as a
+ positional argument in order to run only a single test.
+
+- fix issue 475: fail early and comprehensible if calling
+ pytest.raises with wrong exception type.
+
+- fix issue516: tell in getting-started about current dependencies.
+
+- cleanup setup.py a bit and specify supported versions. Thanks Jurko
+ Gospodnetic for the PR.
+
+- change XPASS colour to yellow rather then red when tests are run
+ with -v.
+
+- fix issue473: work around mock putting an unbound method into a class
+ dict when double-patching.
+
+- fix issue498: if a fixture finalizer fails, make sure that
+ the fixture is still invalidated.
+
+- fix issue453: the result of the pytest_assertrepr_compare hook now gets
+ it's newlines escaped so that format_exception does not blow up.
+
+- internal new warning system: pytest will now produce warnings when
+ it detects oddities in your test collection or execution.
+ Warnings are ultimately sent to a new pytest_logwarning hook which is
+ currently only implemented by the terminal plugin which displays
+ warnings in the summary line and shows more details when -rw (report on
+ warnings) is specified.
+
+- change skips into warnings for test classes with an __init__ and
+ callables in test modules which look like a test but are not functions.
+
+- fix issue436: improved finding of initial conftest files from command
+ line arguments by using the result of parse_known_args rather than
+ the previous flaky heuristics. Thanks Marc Abramowitz for tests
+ and initial fixing approaches in this area.
+
+- fix issue #479: properly handle nose/unittest(2) SkipTest exceptions
+ during collection/loading of test modules. Thanks to Marc Schlaich
+ for the complete PR.
+
+- fix issue490: include pytest_load_initial_conftests in documentation
+ and improve docstring.
+
+- fix issue472: clarify that ``pytest.config.getvalue()`` cannot work
+ if it's triggered ahead of command line parsing.
+
+- merge PR123: improved integration with mock.patch decorator on tests.
+
+- fix issue412: messing with stdout/stderr FD-level streams is now
+ captured without crashes.
+
+- fix issue483: trial/py33 works now properly. Thanks Daniel Grana for PR.
+
+- improve example for pytest integration with "python setup.py test"
+ which now has a generic "-a" or "--pytest-args" option where you
+ can pass additional options as a quoted string. Thanks Trevor Bekolay.
+
+- simplified internal capturing mechanism and made it more robust
+ against tests or setups changing FD1/FD2, also better integrated
+ now with pytest.pdb() in single tests.
+
+- improvements to pytest's own test-suite leakage detection, courtesy of PRs
+ from Marc Abramowitz
+
+- fix issue492: avoid leak in test_writeorg. Thanks Marc Abramowitz.
+
+- fix issue493: don't run tests in doc directory with ``python setup.py test``
+ (use tox -e doctesting for that)
+
+- fix issue486: better reporting and handling of early conftest loading failures
+
+- some cleanup and simplification of internal conftest handling.
+
+- work a bit harder to break reference cycles when catching exceptions.
+ Thanks Jurko Gospodnetic.
+
+- fix issue443: fix skip examples to use proper comparison. Thanks Alex
+ Groenholm.
+
+- support nose-style ``__test__`` attribute on modules, classes and
+ functions, including unittest-style Classes. If set to False, the
+ test will not be collected.
+
+- fix issue512: show "<notset>" for arguments which might not be set
+ in monkeypatch plugin. Improves output in documentation.
+
+
+2.5.2 (2014-01-29)
+==================
+
+- fix issue409 -- better interoperate with cx_freeze by not
+ trying to import from collections.abc which causes problems
+ for py27/cx_freeze. Thanks Wolfgang L. for reporting and tracking it down.
+
+- fixed docs and code to use "pytest" instead of "py.test" almost everywhere.
+ Thanks Jurko Gospodnetic for the complete PR.
+
+- fix issue425: mention at end of "py.test -h" that --markers
+ and --fixtures work according to specified test path (or current dir)
+
+- fix issue413: exceptions with unicode attributes are now printed
+ correctly also on python2 and with pytest-xdist runs. (the fix
+ requires py-1.4.20)
+
+- copy, cleanup and integrate py.io capture
+ from pylib 1.4.20.dev2 (rev 13d9af95547e)
+
+- address issue416: clarify docs as to conftest.py loading semantics
+
+- fix issue429: comparing byte strings with non-ascii chars in assert
+ expressions now work better. Thanks Floris Bruynooghe.
+
+- make capfd/capsys.capture private, its unused and shouldn't be exposed
+
+
+2.5.1 (2013-12-17)
+==================
+
+- merge new documentation styling PR from Tobias Bieniek.
+
+- fix issue403: allow parametrize of multiple same-name functions within
+ a collection node. Thanks Andreas Kloeckner and Alex Gaynor for reporting
+ and analysis.
+
+- Allow parameterized fixtures to specify the ID of the parameters by
+ adding an ids argument to pytest.fixture() and pytest.yield_fixture().
+ Thanks Floris Bruynooghe.
+
+- fix issue404 by always using the binary xml escape in the junitxml
+ plugin. Thanks Ronny Pfannschmidt.
+
+- fix issue407: fix addoption docstring to point to argparse instead of
+ optparse. Thanks Daniel D. Wright.
+
+
+
+2.5.0 (2013-12-12)
+==================
+
+- dropped python2.5 from automated release testing of pytest itself
+ which means it's probably going to break soon (but still works
+ with this release we believe).
+
+- simplified and fixed implementation for calling finalizers when
+ parametrized fixtures or function arguments are involved. finalization
+ is now performed lazily at setup time instead of in the "teardown phase".
+ While this might sound odd at first, it helps to ensure that we are
+ correctly handling setup/teardown even in complex code. User-level code
+ should not be affected unless it's implementing the pytest_runtest_teardown
+ hook and expecting certain fixture instances are torn down within (very
+ unlikely and would have been unreliable anyway).
+
+- PR90: add --color=yes|no|auto option to force terminal coloring
+ mode ("auto" is default). Thanks Marc Abramowitz.
+
+- fix issue319 - correctly show unicode in assertion errors. Many
+ thanks to Floris Bruynooghe for the complete PR. Also means
+ we depend on py>=1.4.19 now.
+
+- fix issue396 - correctly sort and finalize class-scoped parametrized
+ tests independently from number of methods on the class.
+
+- refix issue323 in a better way -- parametrization should now never
+ cause Runtime Recursion errors because the underlying algorithm
+ for re-ordering tests per-scope/per-fixture is not recursive
+ anymore (it was tail-call recursive before which could lead
+ to problems for more than >966 non-function scoped parameters).
+
+- fix issue290 - there is preliminary support now for parametrizing
+ with repeated same values (sometimes useful to test if calling
+ a second time works as with the first time).
+
+- close issue240 - document precisely how pytest module importing
+ works, discuss the two common test directory layouts, and how it
+ interacts with PEP420-namespace packages.
+
+- fix issue246 fix finalizer order to be LIFO on independent fixtures
+ depending on a parametrized higher-than-function scoped fixture.
+ (was quite some effort so please bear with the complexity of this sentence :)
+ Thanks Ralph Schmitt for the precise failure example.
+
+- fix issue244 by implementing special index for parameters to only use
+ indices for paramentrized test ids
+
+- fix issue287 by running all finalizers but saving the exception
+ from the first failing finalizer and re-raising it so teardown will
+ still have failed. We reraise the first failing exception because
+ it might be the cause for other finalizers to fail.
+
+- fix ordering when mock.patch or other standard decorator-wrappings
+ are used with test methods. This fixues issue346 and should
+ help with random "xdist" collection failures. Thanks to
+ Ronny Pfannschmidt and Donald Stufft for helping to isolate it.
+
+- fix issue357 - special case "-k" expressions to allow for
+ filtering with simple strings that are not valid python expressions.
+ Examples: "-k 1.3" matches all tests parametrized with 1.3.
+ "-k None" filters all tests that have "None" in their name
+ and conversely "-k 'not None'".
+ Previously these examples would raise syntax errors.
+
+- fix issue384 by removing the trial support code
+ since the unittest compat enhancements allow
+ trial to handle it on its own
+
+- don't hide an ImportError when importing a plugin produces one.
+ fixes issue375.
+
+- fix issue275 - allow usefixtures and autouse fixtures
+ for running doctest text files.
+
+- fix issue380 by making --resultlog only rely on longrepr instead
+ of the "reprcrash" attribute which only exists sometimes.
+
+- address issue122: allow @pytest.fixture(params=iterator) by exploding
+ into a list early on.
+
+- fix pexpect-3.0 compatibility for pytest's own tests.
+ (fixes issue386)
+
+- allow nested parametrize-value markers, thanks James Lan for the PR.
+
+- fix unicode handling with new monkeypatch.setattr(import_path, value)
+ API. Thanks Rob Dennis. Fixes issue371.
+
+- fix unicode handling with junitxml, fixes issue368.
+
+- In assertion rewriting mode on Python 2, fix the detection of coding
+ cookies. See issue #330.
+
+- make "--runxfail" turn imperative pytest.xfail calls into no ops
+ (it already did neutralize pytest.mark.xfail markers)
+
+- refine pytest / pkg_resources interactions: The AssertionRewritingHook
+ PEP302 compliant loader now registers itself with setuptools/pkg_resources
+ properly so that the pkg_resources.resource_stream method works properly.
+ Fixes issue366. Thanks for the investigations and full PR to Jason R. Coombs.
+
+- pytestconfig fixture is now session-scoped as it is the same object during the
+ whole test run. Fixes issue370.
+
+- avoid one surprising case of marker malfunction/confusion::
+
+ @pytest.mark.some(lambda arg: ...)
+ def test_function():
+
+ would not work correctly because pytest assumes @pytest.mark.some
+ gets a function to be decorated already. We now at least detect if this
+ arg is an lambda and thus the example will work. Thanks Alex Gaynor
+ for bringing it up.
+
+- xfail a test on pypy that checks wrong encoding/ascii (pypy does
+ not error out). fixes issue385.
+
+- internally make varnames() deal with classes's __init__,
+ although it's not needed by pytest itself atm. Also
+ fix caching. Fixes issue376.
+
+- fix issue221 - handle importing of namespace-package with no
+ __init__.py properly.
+
+- refactor internal FixtureRequest handling to avoid monkeypatching.
+ One of the positive user-facing effects is that the "request" object
+ can now be used in closures.
+
+- fixed version comparison in pytest.importskip(modname, minverstring)
+
+- fix issue377 by clarifying in the nose-compat docs that pytest
+ does not duplicate the unittest-API into the "plain" namespace.
+
+- fix verbose reporting for @mock'd test functions
+
+2.4.2 (2013-10-04)
+==================
+
+- on Windows require colorama and a newer py lib so that py.io.TerminalWriter()
+ now uses colorama instead of its own ctypes hacks. (fixes issue365)
+ thanks Paul Moore for bringing it up.
+
+- fix "-k" matching of tests where "repr" and "attr" and other names would
+ cause wrong matches because of an internal implementation quirk
+ (don't ask) which is now properly implemented. fixes issue345.
+
+- avoid tmpdir fixture to create too long filenames especially
+ when parametrization is used (issue354)
+
+- fix pytest-pep8 and pytest-flakes / pytest interactions
+ (collection names in mark plugin was assuming an item always
+ has a function which is not true for those plugins etc.)
+ Thanks Andi Zeidler.
+
+- introduce node.get_marker/node.add_marker API for plugins
+ like pytest-pep8 and pytest-flakes to avoid the messy
+ details of the node.keywords pseudo-dicts. Adapted
+ docs.
+
+- remove attempt to "dup" stdout at startup as it's icky.
+ the normal capturing should catch enough possibilities
+ of tests messing up standard FDs.
+
+- add pluginmanager.do_configure(config) as a link to
+ config.do_configure() for plugin-compatibility
+
+2.4.1 (2013-10-02)
+==================
+
+- When using parser.addoption() unicode arguments to the
+ "type" keyword should also be converted to the respective types.
+ thanks Floris Bruynooghe, @dnozay. (fixes issue360 and issue362)
+
+- fix dotted filename completion when using argcomplete
+ thanks Anthon van der Neuth. (fixes issue361)
+
+- fix regression when a 1-tuple ("arg",) is used for specifying
+ parametrization (the values of the parametrization were passed
+ nested in a tuple). Thanks Donald Stufft.
+
+- merge doc typo fixes, thanks Andy Dirnberger
+
+2.4
+===
+
+known incompatibilities:
+
+- if calling --genscript from python2.7 or above, you only get a
+ standalone script which works on python2.7 or above. Use Python2.6
+ to also get a python2.5 compatible version.
+
+- all xunit-style teardown methods (nose-style, pytest-style,
+ unittest-style) will not be called if the corresponding setup method failed,
+ see issue322 below.
+
+- the pytest_plugin_unregister hook wasn't ever properly called
+ and there is no known implementation of the hook - so it got removed.
+
+- pytest.fixture-decorated functions cannot be generators (i.e. use
+ yield) anymore. This change might be reversed in 2.4.1 if it causes
+ unforeseen real-life issues. However, you can always write and return
+ an inner function/generator and change the fixture consumer to iterate
+ over the returned generator. This change was done in lieu of the new
+ ``pytest.yield_fixture`` decorator, see below.
+
+new features:
+
+- experimentally introduce a new ``pytest.yield_fixture`` decorator
+ which accepts exactly the same parameters as pytest.fixture but
+ mandates a ``yield`` statement instead of a ``return statement`` from
+ fixture functions. This allows direct integration with "with-style"
+ context managers in fixture functions and generally avoids registering
+ of finalization callbacks in favour of treating the "after-yield" as
+ teardown code. Thanks Andreas Pelme, Vladimir Keleshev, Floris
+ Bruynooghe, Ronny Pfannschmidt and many others for discussions.
+
+- allow boolean expression directly with skipif/xfail
+ if a "reason" is also specified. Rework skipping documentation
+ to recommend "condition as booleans" because it prevents surprises
+ when importing markers between modules. Specifying conditions
+ as strings will remain fully supported.
+
+- reporting: color the last line red or green depending if
+ failures/errors occurred or everything passed. thanks Christian
+ Theunert.
+
+- make "import pdb ; pdb.set_trace()" work natively wrt capturing (no
+ "-s" needed anymore), making ``pytest.set_trace()`` a mere shortcut.
+
+- fix issue181: --pdb now also works on collect errors (and
+ on internal errors) . This was implemented by a slight internal
+ refactoring and the introduction of a new hook
+ ``pytest_exception_interact`` hook (see next item).
+
+- fix issue341: introduce new experimental hook for IDEs/terminals to
+ intercept debugging: ``pytest_exception_interact(node, call, report)``.
+
+- new monkeypatch.setattr() variant to provide a shorter
+ invocation for patching out classes/functions from modules:
+
+ monkeypatch.setattr("requests.get", myfunc)
+
+ will replace the "get" function of the "requests" module with ``myfunc``.
+
+- fix issue322: tearDownClass is not run if setUpClass failed. Thanks
+ Mathieu Agopian for the initial fix. Also make all of pytest/nose
+ finalizer mimic the same generic behaviour: if a setupX exists and
+ fails, don't run teardownX. This internally introduces a new method
+ "node.addfinalizer()" helper which can only be called during the setup
+ phase of a node.
+
+- simplify pytest.mark.parametrize() signature: allow to pass a
+ CSV-separated string to specify argnames. For example:
+ ``pytest.mark.parametrize("input,expected", [(1,2), (2,3)])``
+ works as well as the previous:
+ ``pytest.mark.parametrize(("input", "expected"), ...)``.
+
+- add support for setUpModule/tearDownModule detection, thanks Brian Okken.
+
+- integrate tab-completion on options through use of "argcomplete".
+ Thanks Anthon van der Neut for the PR.
+
+- change option names to be hyphen-separated long options but keep the
+ old spelling backward compatible. py.test -h will only show the
+ hyphenated version, for example "--collect-only" but "--collectonly"
+ will remain valid as well (for backward-compat reasons). Many thanks to
+ Anthon van der Neut for the implementation and to Hynek Schlawack for
+ pushing us.
+
+- fix issue 308 - allow to mark/xfail/skip individual parameter sets
+ when parametrizing. Thanks Brianna Laugher.
+
+- call new experimental pytest_load_initial_conftests hook to allow
+ 3rd party plugins to do something before a conftest is loaded.
+
+Bug fixes:
+
+- fix issue358 - capturing options are now parsed more properly
+ by using a new parser.parse_known_args method.
+
+- pytest now uses argparse instead of optparse (thanks Anthon) which
+ means that "argparse" is added as a dependency if installing into python2.6
+ environments or below.
+
+- fix issue333: fix a case of bad unittest/pytest hook interaction.
+
+- PR27: correctly handle nose.SkipTest during collection. Thanks
+ Antonio Cuni, Ronny Pfannschmidt.
+
+- fix issue355: junitxml puts name="pytest" attribute to testsuite tag.
+
+- fix issue336: autouse fixture in plugins should work again.
+
+- fix issue279: improve object comparisons on assertion failure
+ for standard datatypes and recognise collections.abc. Thanks to
+ Brianna Laugher and Mathieu Agopian.
+
+- fix issue317: assertion rewriter support for the is_package method
+
+- fix issue335: document py.code.ExceptionInfo() object returned
+ from pytest.raises(), thanks Mathieu Agopian.
+
+- remove implicit distribute_setup support from setup.py.
+
+- fix issue305: ignore any problems when writing pyc files.
+
+- SO-17664702: call fixture finalizers even if the fixture function
+ partially failed (finalizers would not always be called before)
+
+- fix issue320 - fix class scope for fixtures when mixed with
+ module-level functions. Thanks Anatloy Bubenkoff.
+
+- you can specify "-q" or "-qq" to get different levels of "quieter"
+ reporting (thanks Katarzyna Jachim)
+
+- fix issue300 - Fix order of conftest loading when starting py.test
+ in a subdirectory.
+
+- fix issue323 - sorting of many module-scoped arg parametrizations
+
+- make sessionfinish hooks execute with the same cwd-context as at
+ session start (helps fix plugin behaviour which write output files
+ with relative path such as pytest-cov)
+
+- fix issue316 - properly reference collection hooks in docs
+
+- fix issue 306 - cleanup of -k/-m options to only match markers/test
+ names/keywords respectively. Thanks Wouter van Ackooy.
+
+- improved doctest counting for doctests in python modules --
+ files without any doctest items will not show up anymore
+ and doctest examples are counted as separate test items.
+ thanks Danilo Bellini.
+
+- fix issue245 by depending on the released py-1.4.14
+ which fixes py.io.dupfile to work with files with no
+ mode. Thanks Jason R. Coombs.
+
+- fix junitxml generation when test output contains control characters,
+ addressing issue267, thanks Jaap Broekhuizen
+
+- fix issue338: honor --tb style for setup/teardown errors as well. Thanks Maho.
+
+- fix issue307 - use yaml.safe_load in example, thanks Mark Eichin.
+
+- better parametrize error messages, thanks Brianna Laugher
+
+- pytest_terminal_summary(terminalreporter) hooks can now use
+ ".section(title)" and ".line(msg)" methods to print extra
+ information at the end of a test run.
+
+2.3.5 (2013-04-30)
+==================
+
+- fix issue169: respect --tb=style with setup/teardown errors as well.
+
+- never consider a fixture function for test function collection
+
+- allow re-running of test items / helps to fix pytest-reruntests plugin
+ and also help to keep less fixture/resource references alive
+
+- put captured stdout/stderr into junitxml output even for passing tests
+ (thanks Adam Goucher)
+
+- Issue 265 - integrate nose setup/teardown with setupstate
+ so it doesn't try to teardown if it did not setup
+
+- issue 271 - don't write junitxml on slave nodes
+
+- Issue 274 - don't try to show full doctest example
+ when doctest does not know the example location
+
+- issue 280 - disable assertion rewriting on buggy CPython 2.6.0
+
+- inject "getfixture()" helper to retrieve fixtures from doctests,
+ thanks Andreas Zeidler
+
+- issue 259 - when assertion rewriting, be consistent with the default
+ source encoding of ASCII on Python 2
+
+- issue 251 - report a skip instead of ignoring classes with init
+
+- issue250 unicode/str mixes in parametrization names and values now works
+
+- issue257, assertion-triggered compilation of source ending in a
+ comment line doesn't blow up in python2.5 (fixed through py>=1.4.13.dev6)
+
+- fix --genscript option to generate standalone scripts that also
+ work with python3.3 (importer ordering)
+
+- issue171 - in assertion rewriting, show the repr of some
+ global variables
+
+- fix option help for "-k"
+
+- move long description of distribution into README.rst
+
+- improve docstring for metafunc.parametrize()
+
+- fix bug where using capsys with pytest.set_trace() in a test
+ function would break when looking at capsys.readouterr()
+
+- allow to specify prefixes starting with "_" when
+ customizing python_functions test discovery. (thanks Graham Horler)
+
+- improve PYTEST_DEBUG tracing output by putting
+ extra data on a new lines with additional indent
+
+- ensure OutcomeExceptions like skip/fail have initialized exception attributes
+
+- issue 260 - don't use nose special setup on plain unittest cases
+
+- fix issue134 - print the collect errors that prevent running specified test items
+
+- fix issue266 - accept unicode in MarkEvaluator expressions
+
+2.3.4 (2012-11-20)
+==================
+
+- yielded test functions will now have autouse-fixtures active but
+ cannot accept fixtures as funcargs - it's anyway recommended to
+ rather use the post-2.0 parametrize features instead of yield, see:
+ http://pytest.org/latest/example/parametrize.html
+- fix autouse-issue where autouse-fixtures would not be discovered
+ if defined in a a/conftest.py file and tests in a/tests/test_some.py
+- fix issue226 - LIFO ordering for fixture teardowns
+- fix issue224 - invocations with >256 char arguments now work
+- fix issue91 - add/discuss package/directory level setups in example
+- allow to dynamically define markers via
+ item.keywords[...]=assignment integrating with "-m" option
+- make "-k" accept an expressions the same as with "-m" so that one
+ can write: -k "name1 or name2" etc. This is a slight incompatibility
+ if you used special syntax like "TestClass.test_method" which you now
+ need to write as -k "TestClass and test_method" to match a certain
+ method in a certain test class.
+
+2.3.3 (2012-11-06)
+==================
+
+- fix issue214 - parse modules that contain special objects like e. g.
+ flask's request object which blows up on getattr access if no request
+ is active. thanks Thomas Waldmann.
+
+- fix issue213 - allow to parametrize with values like numpy arrays that
+ do not support an __eq__ operator
+
+- fix issue215 - split test_python.org into multiple files
+
+- fix issue148 - @unittest.skip on classes is now recognized and avoids
+ calling setUpClass/tearDownClass, thanks Pavel Repin
+
+- fix issue209 - reintroduce python2.4 support by depending on newer
+ pylib which re-introduced statement-finding for pre-AST interpreters
+
+- nose support: only call setup if it's a callable, thanks Andrew
+ Taumoefolau
+
+- fix issue219 - add py2.4-3.3 classifiers to TROVE list
+
+- in tracebacks *,** arg values are now shown next to normal arguments
+ (thanks Manuel Jacob)
+
+- fix issue217 - support mock.patch with pytest's fixtures - note that
+ you need either mock-1.0.1 or the python3.3 builtin unittest.mock.
+
+- fix issue127 - improve documentation for pytest_addoption() and
+ add a ``config.getoption(name)`` helper function for consistency.
+
+2.3.2 (2012-10-25)
+==================
+
+- fix issue208 and fix issue29 use new py version to avoid long pauses
+ when printing tracebacks in long modules
+
+- fix issue205 - conftests in subdirs customizing
+ pytest_pycollect_makemodule and pytest_pycollect_makeitem
+ now work properly
+
+- fix teardown-ordering for parametrized setups
+
+- fix issue127 - better documentation for pytest_addoption
+ and related objects.
+
+- fix unittest behaviour: TestCase.runtest only called if there are
+ test methods defined
+
+- improve trial support: don't collect its empty
+ unittest.TestCase.runTest() method
+
+- "python setup.py test" now works with pytest itself
+
+- fix/improve internal/packaging related bits:
+
+ - exception message check of test_nose.py now passes on python33 as well
+
+ - issue206 - fix test_assertrewrite.py to work when a global
+ PYTHONDONTWRITEBYTECODE=1 is present
+
+ - add tox.ini to pytest distribution so that ignore-dirs and others config
+ bits are properly distributed for maintainers who run pytest-own tests
+
+2.3.1 (2012-10-20)
+==================
+
+- fix issue202 - fix regression: using "self" from fixture functions now
+ works as expected (it's the same "self" instance that a test method
+ which uses the fixture sees)
+
+- skip pexpect using tests (test_pdb.py mostly) on freebsd* systems
+ due to pexpect not supporting it properly (hanging)
+
+- link to web pages from --markers output which provides help for
+ pytest.mark.* usage.
+
+2.3.0 (2012-10-19)
+==================
+
+- fix issue202 - better automatic names for parametrized test functions
+- fix issue139 - introduce @pytest.fixture which allows direct scoping
+ and parametrization of funcarg factories.
+- fix issue198 - conftest fixtures were not found on windows32 in some
+ circumstances with nested directory structures due to path manipulation issues
+- fix issue193 skip test functions with were parametrized with empty
+ parameter sets
+- fix python3.3 compat, mostly reporting bits that previously depended
+ on dict ordering
+- introduce re-ordering of tests by resource and parametrization setup
+ which takes precedence to the usual file-ordering
+- fix issue185 monkeypatching time.time does not cause pytest to fail
+- fix issue172 duplicate call of pytest.fixture decoratored setup_module
+ functions
+- fix junitxml=path construction so that if tests change the
+ current working directory and the path is a relative path
+ it is constructed correctly from the original current working dir.
+- fix "python setup.py test" example to cause a proper "errno" return
+- fix issue165 - fix broken doc links and mention stackoverflow for FAQ
+- catch unicode-issues when writing failure representations
+ to terminal to prevent the whole session from crashing
+- fix xfail/skip confusion: a skip-mark or an imperative pytest.skip
+ will now take precedence before xfail-markers because we
+ can't determine xfail/xpass status in case of a skip. see also:
+ http://stackoverflow.com/questions/11105828/in-py-test-when-i-explicitly-skip-a-test-that-is-marked-as-xfail-how-can-i-get
+
+- always report installed 3rd party plugins in the header of a test run
+
+- fix issue160: a failing setup of an xfail-marked tests should
+ be reported as xfail (not xpass)
+
+- fix issue128: show captured output when capsys/capfd are used
+
+- fix issue179: properly show the dependency chain of factories
+
+- pluginmanager.register(...) now raises ValueError if the
+ plugin has been already registered or the name is taken
+
+- fix issue159: improve http://pytest.org/latest/faq.html
+ especially with respect to the "magic" history, also mention
+ pytest-django, trial and unittest integration.
+
+- make request.keywords and node.keywords writable. All descendant
+ collection nodes will see keyword values. Keywords are dictionaries
+ containing markers and other info.
+
+- fix issue 178: xml binary escapes are now wrapped in py.xml.raw
+
+- fix issue 176: correctly catch the builtin AssertionError
+ even when we replaced AssertionError with a subclass on the
+ python level
+
+- factory discovery no longer fails with magic global callables
+ that provide no sane __code__ object (mock.call for example)
+
+- fix issue 182: testdir.inprocess_run now considers passed plugins
+
+- fix issue 188: ensure sys.exc_info is clear on python2
+ before calling into a test
+
+- fix issue 191: add unittest TestCase runTest method support
+- fix issue 156: monkeypatch correctly handles class level descriptors
+
+- reporting refinements:
+
+ - pytest_report_header now receives a "startdir" so that
+ you can use startdir.bestrelpath(yourpath) to show
+ nice relative path
+
+ - allow plugins to implement both pytest_report_header and
+ pytest_sessionstart (sessionstart is invoked first).
+
+ - don't show deselected reason line if there is none
+
+ - py.test -vv will show all of assert comparisons instead of truncating
+
+2.2.4 (2012-05-22)
+==================
+
+- fix error message for rewritten assertions involving the % operator
+- fix issue 126: correctly match all invalid xml characters for junitxml
+ binary escape
+- fix issue with unittest: now @unittest.expectedFailure markers should
+ be processed correctly (you can also use @pytest.mark markers)
+- document integration with the extended distribute/setuptools test commands
+- fix issue 140: properly get the real functions
+ of bound classmethods for setup/teardown_class
+- fix issue #141: switch from the deceased paste.pocoo.org to bpaste.net
+- fix issue #143: call unconfigure/sessionfinish always when
+ configure/sessionstart where called
+- fix issue #144: better mangle test ids to junitxml classnames
+- upgrade distribute_setup.py to 0.6.27
+
+2.2.3 (2012-02-05)
+==================
+
+- fix uploaded package to only include necessary files
+
+2.2.2 (2012-02-05)
+==================
+
+- fix issue101: wrong args to unittest.TestCase test function now
+ produce better output
+- fix issue102: report more useful errors and hints for when a
+ test directory was renamed and some pyc/__pycache__ remain
+- fix issue106: allow parametrize to be applied multiple times
+ e.g. from module, class and at function level.
+- fix issue107: actually perform session scope finalization
+- don't check in parametrize if indirect parameters are funcarg names
+- add chdir method to monkeypatch funcarg
+- fix crash resulting from calling monkeypatch undo a second time
+- fix issue115: make --collectonly robust against early failure
+ (missing files/directories)
+- "-qq --collectonly" now shows only files and the number of tests in them
+- "-q --collectonly" now shows test ids
+- allow adding of attributes to test reports such that it also works
+ with distributed testing (no upgrade of pytest-xdist needed)
+
+2.2.1 (2011-12-16)
+==================
+
+- fix issue99 (in pytest and py) internallerrors with resultlog now
+ produce better output - fixed by normalizing pytest_internalerror
+ input arguments.
+- fix issue97 / traceback issues (in pytest and py) improve traceback output
+ in conjunction with jinja2 and cython which hack tracebacks
+- fix issue93 (in pytest and pytest-xdist) avoid "delayed teardowns":
+ the final test in a test node will now run its teardown directly
+ instead of waiting for the end of the session. Thanks Dave Hunt for
+ the good reporting and feedback. The pytest_runtest_protocol as well
+ as the pytest_runtest_teardown hooks now have "nextitem" available
+ which will be None indicating the end of the test run.
+- fix collection crash due to unknown-source collected items, thanks
+ to Ralf Schmitt (fixed by depending on a more recent pylib)
+
+2.2.0 (2011-11-18)
+==================
+
+- fix issue90: introduce eager tearing down of test items so that
+ teardown function are called earlier.
+- add an all-powerful metafunc.parametrize function which allows to
+ parametrize test function arguments in multiple steps and therefore
+ from independent plugins and places.
+- add a @pytest.mark.parametrize helper which allows to easily
+ call a test function with different argument values
+- Add examples to the "parametrize" example page, including a quick port
+ of Test scenarios and the new parametrize function and decorator.
+- introduce registration for "pytest.mark.*" helpers via ini-files
+ or through plugin hooks. Also introduce a "--strict" option which
+ will treat unregistered markers as errors
+ allowing to avoid typos and maintain a well described set of markers
+ for your test suite. See exaples at http://pytest.org/latest/mark.html
+ and its links.
+- issue50: introduce "-m marker" option to select tests based on markers
+ (this is a stricter and more predictable version of '-k' in that "-m"
+ only matches complete markers and has more obvious rules for and/or
+ semantics.
+- new feature to help optimizing the speed of your tests:
+ --durations=N option for displaying N slowest test calls
+ and setup/teardown methods.
+- fix issue87: --pastebin now works with python3
+- fix issue89: --pdb with unexpected exceptions in doctest work more sensibly
+- fix and cleanup pytest's own test suite to not leak FDs
+- fix issue83: link to generated funcarg list
+- fix issue74: pyarg module names are now checked against imp.find_module false positives
+- fix compatibility with twisted/trial-11.1.0 use cases
+- simplify Node.listchain
+- simplify junitxml output code by relying on py.xml
+- add support for skip properties on unittest classes and functions
+
+2.1.3 (2011-10-18)
+==================
+
+- fix issue79: assertion rewriting failed on some comparisons in boolops
+- correctly handle zero length arguments (a la pytest '')
+- fix issue67 / junitxml now contains correct test durations, thanks ronny
+- fix issue75 / skipping test failure on jython
+- fix issue77 / Allow assertrepr_compare hook to apply to a subset of tests
+
+2.1.2 (2011-09-24)
+==================
+
+- fix assertion rewriting on files with windows newlines on some Python versions
+- refine test discovery by package/module name (--pyargs), thanks Florian Mayer
+- fix issue69 / assertion rewriting fixed on some boolean operations
+- fix issue68 / packages now work with assertion rewriting
+- fix issue66: use different assertion rewriting caches when the -O option is passed
+- don't try assertion rewriting on Jython, use reinterp
+
+2.1.1
+=====
+
+- fix issue64 / pytest.set_trace now works within pytest_generate_tests hooks
+- fix issue60 / fix error conditions involving the creation of __pycache__
+- fix issue63 / assertion rewriting on inserts involving strings containing '%'
+- fix assertion rewriting on calls with a ** arg
+- don't cache rewritten modules if bytecode generation is disabled
+- fix assertion rewriting in read-only directories
+- fix issue59: provide system-out/err tags for junitxml output
+- fix issue61: assertion rewriting on boolean operations with 3 or more operands
+- you can now build a man page with "cd doc ; make man"
+
+2.1.0 (2011-07-09)
+==================
+
+- fix issue53 call nosestyle setup functions with correct ordering
+- fix issue58 and issue59: new assertion code fixes
+- merge Benjamin's assertionrewrite branch: now assertions
+ for test modules on python 2.6 and above are done by rewriting
+ the AST and saving the pyc file before the test module is imported.
+ see doc/assert.txt for more info.
+- fix issue43: improve doctests with better traceback reporting on
+ unexpected exceptions
+- fix issue47: timing output in junitxml for test cases is now correct
+- fix issue48: typo in MarkInfo repr leading to exception
+- fix issue49: avoid confusing error when initizaliation partially fails
+- fix issue44: env/username expansion for junitxml file path
+- show releaselevel information in test runs for pypy
+- reworked doc pages for better navigation and PDF generation
+- report KeyboardInterrupt even if interrupted during session startup
+- fix issue 35 - provide PDF doc version and download link from index page
+
+2.0.3 (2011-05-11)
+==================
+
+- fix issue38: nicer tracebacks on calls to hooks, particularly early
+ configure/sessionstart ones
+
+- fix missing skip reason/meta information in junitxml files, reported
+ via http://lists.idyll.org/pipermail/testing-in-python/2011-March/003928.html
+
+- fix issue34: avoid collection failure with "test" prefixed classes
+ deriving from object.
+
+- don't require zlib (and other libs) for genscript plugin without
+ --genscript actually being used.
+
+- speed up skips (by not doing a full traceback representation
+ internally)
+
+- fix issue37: avoid invalid characters in junitxml's output
+
+2.0.2 (2011-03-09)
+==================
+
+- tackle issue32 - speed up test runs of very quick test functions
+ by reducing the relative overhead
+
+- fix issue30 - extended xfail/skipif handling and improved reporting.
+ If you have a syntax error in your skip/xfail
+ expressions you now get nice error reports.
+
+ Also you can now access module globals from xfail/skipif
+ expressions so that this for example works now::
+
+ import pytest
+ import mymodule
+ @pytest.mark.skipif("mymodule.__version__[0] == "1")
+ def test_function():
+ pass
+
+ This will not run the test function if the module's version string
+ does not start with a "1". Note that specifying a string instead
+ of a boolean expressions allows py.test to report meaningful information
+ when summarizing a test run as to what conditions lead to skipping
+ (or xfail-ing) tests.
+
+- fix issue28 - setup_method and pytest_generate_tests work together
+ The setup_method fixture method now gets called also for
+ test function invocations generated from the pytest_generate_tests
+ hook.
+
+- fix issue27 - collectonly and keyword-selection (-k) now work together
+ Also, if you do "py.test --collectonly -q" you now get a flat list
+ of test ids that you can use to paste to the py.test commandline
+ in order to execute a particular test.
+
+- fix issue25 avoid reported problems with --pdb and python3.2/encodings output
+
+- fix issue23 - tmpdir argument now works on Python3.2 and WindowsXP
+ Starting with Python3.2 os.symlink may be supported. By requiring
+ a newer py lib version the py.path.local() implementation acknowledges
+ this.
+
+- fixed typos in the docs (thanks Victor Garcia, Brianna Laugher) and particular
+ thanks to Laura Creighton who also reviewed parts of the documentation.
+
+- fix slightly wrong output of verbose progress reporting for classes
+ (thanks Amaury)
+
+- more precise (avoiding of) deprecation warnings for node.Class|Function accesses
+
+- avoid std unittest assertion helper code in tracebacks (thanks Ronny)
+
+2.0.1 (2011-02-07)
+==================
+
+- refine and unify initial capturing so that it works nicely
+ even if the logging module is used on an early-loaded conftest.py
+ file or plugin.
+- allow to omit "()" in test ids to allow for uniform test ids
+ as produced by Alfredo's nice pytest.vim plugin.
+- fix issue12 - show plugin versions with "--version" and
+ "--traceconfig" and also document how to add extra information
+ to reporting test header
+- fix issue17 (import-* reporting issue on python3) by
+ requiring py>1.4.0 (1.4.1 is going to include it)
+- fix issue10 (numpy arrays truth checking) by refining
+ assertion interpretation in py lib
+- fix issue15: make nose compatibility tests compatible
+ with python3 (now that nose-1.0 supports python3)
+- remove somewhat surprising "same-conftest" detection because
+ it ignores conftest.py when they appear in several subdirs.
+- improve assertions ("not in"), thanks Floris Bruynooghe
+- improve behaviour/warnings when running on top of "python -OO"
+ (assertions and docstrings are turned off, leading to potential
+ false positives)
+- introduce a pytest_cmdline_processargs(args) hook
+ to allow dynamic computation of command line arguments.
+ This fixes a regression because py.test prior to 2.0
+ allowed to set command line options from conftest.py
+ files which so far pytest-2.0 only allowed from ini-files now.
+- fix issue7: assert failures in doctest modules.
+ unexpected failures in doctests will not generally
+ show nicer, i.e. within the doctest failing context.
+- fix issue9: setup/teardown functions for an xfail-marked
+ test will report as xfail if they fail but report as normally
+ passing (not xpassing) if they succeed. This only is true
+ for "direct" setup/teardown invocations because teardown_class/
+ teardown_module cannot closely relate to a single test.
+- fix issue14: no logging errors at process exit
+- refinements to "collecting" output on non-ttys
+- refine internal plugin registration and --traceconfig output
+- introduce a mechanism to prevent/unregister plugins from the
+ command line, see http://pytest.org/plugins.html#cmdunregister
+- activate resultlog plugin by default
+- fix regression wrt yielded tests which due to the
+ collection-before-running semantics were not
+ setup as with pytest 1.3.4. Note, however, that
+ the recommended and much cleaner way to do test
+ parametraization remains the "pytest_generate_tests"
+ mechanism, see the docs.
+
+2.0.0 (2010-11-25)
+==================
+
+- pytest-2.0 is now its own package and depends on pylib-2.0
+- new ability: python -m pytest / python -m pytest.main ability
+- new python invocation: pytest.main(args, plugins) to load
+ some custom plugins early.
+- try harder to run unittest test suites in a more compatible manner
+ by deferring setup/teardown semantics to the unittest package.
+ also work harder to run twisted/trial and Django tests which
+ should now basically work by default.
+- introduce a new way to set config options via ini-style files,
+ by default setup.cfg and tox.ini files are searched. The old
+ ways (certain environment variables, dynamic conftest.py reading
+ is removed).
+- add a new "-q" option which decreases verbosity and prints a more
+ nose/unittest-style "dot" output.
+- fix issue135 - marks now work with unittest test cases as well
+- fix issue126 - introduce py.test.set_trace() to trace execution via
+ PDB during the running of tests even if capturing is ongoing.
+- fix issue123 - new "python -m py.test" invocation for py.test
+ (requires Python 2.5 or above)
+- fix issue124 - make reporting more resilient against tests opening
+ files on filedescriptor 1 (stdout).
+- fix issue109 - sibling conftest.py files will not be loaded.
+ (and Directory collectors cannot be customized anymore from a Directory's
+ conftest.py - this needs to happen at least one level up).
+- introduce (customizable) assertion failure representations and enhance
+ output on assertion failures for comparisons and other cases (Floris Bruynooghe)
+- nose-plugin: pass through type-signature failures in setup/teardown
+ functions instead of not calling them (Ed Singleton)
+- remove py.test.collect.Directory (follows from a major refactoring
+ and simplification of the collection process)
+- majorly reduce py.test core code, shift function/python testing to own plugin
+- fix issue88 (finding custom test nodes from command line arg)
+- refine 'tmpdir' creation, will now create basenames better associated
+ with test names (thanks Ronny)
+- "xpass" (unexpected pass) tests don't cause exitcode!=0
+- fix issue131 / issue60 - importing doctests in __init__ files used as namespace packages
+- fix issue93 stdout/stderr is captured while importing conftest.py
+- fix bug: unittest collected functions now also can have "pytestmark"
+ applied at class/module level
+- add ability to use "class" level for cached_setup helper
+- fix strangeness: mark.* objects are now immutable, create new instances
+
+1.3.4 (2010-09-14)
+==================
+
+- fix issue111: improve install documentation for windows
+- fix issue119: fix custom collectability of __init__.py as a module
+- fix issue116: --doctestmodules work with __init__.py files as well
+- fix issue115: unify internal exception passthrough/catching/GeneratorExit
+- fix issue118: new --tb=native for presenting cpython-standard exceptions
+
+1.3.3 (2010-07-30)
+==================
+
+- fix issue113: assertion representation problem with triple-quoted strings
+ (and possibly other cases)
+- make conftest loading detect that a conftest file with the same
+ content was already loaded, avoids surprises in nested directory structures
+ which can be produced e.g. by Hudson. It probably removes the need to use
+ --confcutdir in most cases.
+- fix terminal coloring for win32
+ (thanks Michael Foord for reporting)
+- fix weirdness: make terminal width detection work on stdout instead of stdin
+ (thanks Armin Ronacher for reporting)
+- remove trailing whitespace in all py/text distribution files
+
+1.3.2 (2010-07-08)
+==================
+
+**New features**
+
+- fix issue103: introduce py.test.raises as context manager, examples::
+
+ with py.test.raises(ZeroDivisionError):
+ x = 0
+ 1 / x
+
+ with py.test.raises(RuntimeError) as excinfo:
+ call_something()
+
+ # you may do extra checks on excinfo.value|type|traceback here
+
+ (thanks Ronny Pfannschmidt)
+
+- Funcarg factories can now dynamically apply a marker to a
+ test invocation. This is for example useful if a factory
+ provides parameters to a test which are expected-to-fail::
+
+ def pytest_funcarg__arg(request):
+ request.applymarker(py.test.mark.xfail(reason="flaky config"))
+ ...
+
+ def test_function(arg):
+ ...
+
+- improved error reporting on collection and import errors. This makes
+ use of a more general mechanism, namely that for custom test item/collect
+ nodes ``node.repr_failure(excinfo)`` is now uniformly called so that you can
+ override it to return a string error representation of your choice
+ which is going to be reported as a (red) string.
+
+- introduce '--junitprefix=STR' option to prepend a prefix
+ to all reports in the junitxml file.
+
+**Bug fixes**
+
+- make tests and the ``pytest_recwarn`` plugin in particular fully compatible
+ to Python2.7 (if you use the ``recwarn`` funcarg warnings will be enabled so that
+ you can properly check for their existence in a cross-python manner).
+- refine --pdb: ignore xfailed tests, unify its TB-reporting and
+ don't display failures again at the end.
+- fix assertion interpretation with the ** operator (thanks Benjamin Peterson)
+- fix issue105 assignment on the same line as a failing assertion (thanks Benjamin Peterson)
+- fix issue104 proper escaping for test names in junitxml plugin (thanks anonymous)
+- fix issue57 -f|--looponfail to work with xpassing tests (thanks Ronny)
+- fix issue92 collectonly reporter and --pastebin (thanks Benjamin Peterson)
+- fix py.code.compile(source) to generate unique filenames
+- fix assertion re-interp problems on PyPy, by defering code
+ compilation to the (overridable) Frame.eval class. (thanks Amaury Forgeot)
+- fix py.path.local.pyimport() to work with directories
+- streamline py.path.local.mkdtemp implementation and usage
+- don't print empty lines when showing junitxml-filename
+- add optional boolean ignore_errors parameter to py.path.local.remove
+- fix terminal writing on win32/python2.4
+- py.process.cmdexec() now tries harder to return properly encoded unicode objects
+ on all python versions
+- install plain py.test/py.which scripts also for Jython, this helps to
+ get canonical script paths in virtualenv situations
+- make path.bestrelpath(path) return ".", note that when calling
+ X.bestrelpath the assumption is that X is a directory.
+- make initial conftest discovery ignore "--" prefixed arguments
+- fix resultlog plugin when used in an multicpu/multihost xdist situation
+ (thanks Jakub Gustak)
+- perform distributed testing related reporting in the xdist-plugin
+ rather than having dist-related code in the generic py.test
+ distribution
+- fix homedir detection on Windows
+- ship distribute_setup.py version 0.6.13
+
+1.3.1 (2010-05-25)
+==================
+
+**New features**
+
+- issue91: introduce new py.test.xfail(reason) helper
+ to imperatively mark a test as expected to fail. Can
+ be used from within setup and test functions. This is
+ useful especially for parametrized tests when certain
+ configurations are expected-to-fail. In this case the
+ declarative approach with the @py.test.mark.xfail cannot
+ be used as it would mark all configurations as xfail.
+
+- issue102: introduce new --maxfail=NUM option to stop
+ test runs after NUM failures. This is a generalization
+ of the '-x' or '--exitfirst' option which is now equivalent
+ to '--maxfail=1'. Both '-x' and '--maxfail' will
+ now also print a line near the end indicating the Interruption.
+
+- issue89: allow py.test.mark decorators to be used on classes
+ (class decorators were introduced with python2.6) and
+ also allow to have multiple markers applied at class/module level
+ by specifying a list.
+
+- improve and refine letter reporting in the progress bar:
+ . pass
+ f failed test
+ s skipped tests (reminder: use for dependency/platform mismatch only)
+ x xfailed test (test that was expected to fail)
+ X xpassed test (test that was expected to fail but passed)
+
+ You can use any combination of 'fsxX' with the '-r' extended
+ reporting option. The xfail/xpass results will show up as
+ skipped tests in the junitxml output - which also fixes
+ issue99.
+
+- make py.test.cmdline.main() return the exitstatus instead of raising
+ SystemExit and also allow it to be called multiple times. This of
+ course requires that your application and tests are properly teared
+ down and don't have global state.
+
+**Bug Fixes**
+
+- improved traceback presentation:
+ - improved and unified reporting for "--tb=short" option
+ - Errors during test module imports are much shorter, (using --tb=short style)
+ - raises shows shorter more relevant tracebacks
+ - --fulltrace now more systematically makes traces longer / inhibits cutting
+
+- improve support for raises and other dynamically compiled code by
+ manipulating python's linecache.cache instead of the previous
+ rather hacky way of creating custom code objects. This makes
+ it seemlessly work on Jython and PyPy where it previously didn't.
+
+- fix issue96: make capturing more resilient against Control-C
+ interruptions (involved somewhat substantial refactoring
+ to the underlying capturing functionality to avoid race
+ conditions).
+
+- fix chaining of conditional skipif/xfail decorators - so it works now
+ as expected to use multiple @py.test.mark.skipif(condition) decorators,
+ including specific reporting which of the conditions lead to skipping.
+
+- fix issue95: late-import zlib so that it's not required
+ for general py.test startup.
+
+- fix issue94: make reporting more robust against bogus source code
+ (and internally be more careful when presenting unexpected byte sequences)
+
+
+1.3.0 (2010-05-05)
+==================
+
+- deprecate --report option in favour of a new shorter and easier to
+ remember -r option: it takes a string argument consisting of any
+ combination of 'xfsX' characters. They relate to the single chars
+ you see during the dotted progress printing and will print an extra line
+ per test at the end of the test run. This extra line indicates the exact
+ position or test ID that you directly paste to the py.test cmdline in order
+ to re-run a particular test.
+
+- allow external plugins to register new hooks via the new
+ pytest_addhooks(pluginmanager) hook. The new release of
+ the pytest-xdist plugin for distributed and looponfailing
+ testing requires this feature.
+
+- add a new pytest_ignore_collect(path, config) hook to allow projects and
+ plugins to define exclusion behaviour for their directory structure -
+ for example you may define in a conftest.py this method::
+
+ def pytest_ignore_collect(path):
+ return path.check(link=1)
+
+ to prevent even a collection try of any tests in symlinked dirs.
+
+- new pytest_pycollect_makemodule(path, parent) hook for
+ allowing customization of the Module collection object for a
+ matching test module.
+
+- extend and refine xfail mechanism:
+ ``@py.test.mark.xfail(run=False)`` do not run the decorated test
+ ``@py.test.mark.xfail(reason="...")`` prints the reason string in xfail summaries
+ specifying ``--runxfail`` on command line virtually ignores xfail markers
+
+- expose (previously internal) commonly useful methods:
+ py.io.get_terminal_with() -> return terminal width
+ py.io.ansi_print(...) -> print colored/bold text on linux/win32
+ py.io.saferepr(obj) -> return limited representation string
+
+- expose test outcome related exceptions as py.test.skip.Exception,
+ py.test.raises.Exception etc., useful mostly for plugins
+ doing special outcome interpretation/tweaking
+
+- (issue85) fix junitxml plugin to handle tests with non-ascii output
+
+- fix/refine python3 compatibility (thanks Benjamin Peterson)
+
+- fixes for making the jython/win32 combination work, note however:
+ jython2.5.1/win32 does not provide a command line launcher, see
+ http://bugs.jython.org/issue1491 . See pylib install documentation
+ for how to work around.
+
+- fixes for handling of unicode exception values and unprintable objects
+
+- (issue87) fix unboundlocal error in assertionold code
+
+- (issue86) improve documentation for looponfailing
+
+- refine IO capturing: stdin-redirect pseudo-file now has a NOP close() method
+
+- ship distribute_setup.py version 0.6.10
+
+- added links to the new capturelog and coverage plugins
+
+
+1.2.0 (2010-01-18)
+==================
+
+- refined usage and options for "py.cleanup"::
+
+ py.cleanup # remove "*.pyc" and "*$py.class" (jython) files
+ py.cleanup -e .swp -e .cache # also remove files with these extensions
+ py.cleanup -s # remove "build" and "dist" directory next to setup.py files
+ py.cleanup -d # also remove empty directories
+ py.cleanup -a # synonym for "-s -d -e 'pip-log.txt'"
+ py.cleanup -n # dry run, only show what would be removed
+
+- add a new option "py.test --funcargs" which shows available funcargs
+ and their help strings (docstrings on their respective factory function)
+ for a given test path
+
+- display a short and concise traceback if a funcarg lookup fails
+
+- early-load "conftest.py" files in non-dot first-level sub directories.
+ allows to conveniently keep and access test-related options in a ``test``
+ subdir and still add command line options.
+
+- fix issue67: new super-short traceback-printing option: "--tb=line" will print a single line for each failing (python) test indicating its filename, lineno and the failure value
+
+- fix issue78: always call python-level teardown functions even if the
+ according setup failed. This includes refinements for calling setup_module/class functions
+ which will now only be called once instead of the previous behaviour where they'd be called
+ multiple times if they raise an exception (including a Skipped exception). Any exception
+ will be re-corded and associated with all tests in the according module/class scope.
+
+- fix issue63: assume <40 columns to be a bogus terminal width, default to 80
+
+- fix pdb debugging to be in the correct frame on raises-related errors
+
+- update apipkg.py to fix an issue where recursive imports might
+ unnecessarily break importing
+
+- fix plugin links
+
+1.1.1 (2009-11-24)
+==================
+
+- moved dist/looponfailing from py.test core into a new
+ separately released pytest-xdist plugin.
+
+- new junitxml plugin: --junitxml=path will generate a junit style xml file
+ which is processable e.g. by the Hudson CI system.
+
+- new option: --genscript=path will generate a standalone py.test script
+ which will not need any libraries installed. thanks to Ralf Schmitt.
+
+- new option: --ignore will prevent specified path from collection.
+ Can be specified multiple times.
+
+- new option: --confcutdir=dir will make py.test only consider conftest
+ files that are relative to the specified dir.
+
+- new funcarg: "pytestconfig" is the pytest config object for access
+ to command line args and can now be easily used in a test.
+
+- install ``py.test`` and ``py.which`` with a ``-$VERSION`` suffix to
+ disambiguate between Python3, python2.X, Jython and PyPy installed versions.
+
+- new "pytestconfig" funcarg allows access to test config object
+
+- new "pytest_report_header" hook can return additional lines
+ to be displayed at the header of a test run.
+
+- (experimental) allow "py.test path::name1::name2::..." for pointing
+ to a test within a test collection directly. This might eventually
+ evolve as a full substitute to "-k" specifications.
+
+- streamlined plugin loading: order is now as documented in
+ customize.html: setuptools, ENV, commandline, conftest.
+ also setuptools entry point names are turned to canonical namees ("pytest_*")
+
+- automatically skip tests that need 'capfd' but have no os.dup
+
+- allow pytest_generate_tests to be defined in classes as well
+
+- deprecate usage of 'disabled' attribute in favour of pytestmark
+- deprecate definition of Directory, Module, Class and Function nodes
+ in conftest.py files. Use pytest collect hooks instead.
+
+- collection/item node specific runtest/collect hooks are only called exactly
+ on matching conftest.py files, i.e. ones which are exactly below
+ the filesystem path of an item
+
+- change: the first pytest_collect_directory hook to return something
+ will now prevent further hooks to be called.
+
+- change: figleaf plugin now requires --figleaf to run. Also
+ change its long command line options to be a bit shorter (see py.test -h).
+
+- change: pytest doctest plugin is now enabled by default and has a
+ new option --doctest-glob to set a pattern for file matches.
+
+- change: remove internal py._* helper vars, only keep py._pydir
+
+- robustify capturing to survive if custom pytest_runtest_setup
+ code failed and prevented the capturing setup code from running.
+
+- make py.test.* helpers provided by default plugins visible early -
+ works transparently both for pydoc and for interactive sessions
+ which will regularly see e.g. py.test.mark and py.test.importorskip.
+
+- simplify internal plugin manager machinery
+- simplify internal collection tree by introducing a RootCollector node
+
+- fix assert reinterpreation that sees a call containing "keyword=..."
+
+- fix issue66: invoke pytest_sessionstart and pytest_sessionfinish
+ hooks on slaves during dist-testing, report module/session teardown
+ hooks correctly.
+
+- fix issue65: properly handle dist-testing if no
+ execnet/py lib installed remotely.
+
+- skip some install-tests if no execnet is available
+
+- fix docs, fix internal bin/ script generation
+
+
+1.1.0 (2009-11-05)
+==================
+
+- introduce automatic plugin registration via 'pytest11'
+ entrypoints via setuptools' pkg_resources.iter_entry_points
+
+- fix py.test dist-testing to work with execnet >= 1.0.0b4
+
+- re-introduce py.test.cmdline.main() for better backward compatibility
+
+- svn paths: fix a bug with path.check(versioned=True) for svn paths,
+ allow '%' in svn paths, make svnwc.update() default to interactive mode
+ like in 1.0.x and add svnwc.update(interactive=False) to inhibit interaction.
+
+- refine distributed tarball to contain test and no pyc files
+
+- try harder to have deprecation warnings for py.compat.* accesses
+ report a correct location
+
+1.0.3
+=====
+
+* adjust and improve docs
+
+* remove py.rest tool and internal namespace - it was
+ never really advertised and can still be used with
+ the old release if needed. If there is interest
+ it could be revived into its own tool i guess.
+
+* fix issue48 and issue59: raise an Error if the module
+ from an imported test file does not seem to come from
+ the filepath - avoids "same-name" confusion that has
+ been reported repeatedly
+
+* merged Ronny's nose-compatibility hacks: now
+ nose-style setup_module() and setup() functions are
+ supported
+
+* introduce generalized py.test.mark function marking
+
+* reshuffle / refine command line grouping
+
+* deprecate parser.addgroup in favour of getgroup which creates option group
+
+* add --report command line option that allows to control showing of skipped/xfailed sections
+
+* generalized skipping: a new way to mark python functions with skipif or xfail
+ at function, class and modules level based on platform or sys-module attributes.
+
+* extend py.test.mark decorator to allow for positional args
+
+* introduce and test "py.cleanup -d" to remove empty directories
+
+* fix issue #59 - robustify unittest test collection
+
+* make bpython/help interaction work by adding an __all__ attribute
+ to ApiModule, cleanup initpkg
+
+* use MIT license for pylib, add some contributors
+
+* remove py.execnet code and substitute all usages with 'execnet' proper
+
+* fix issue50 - cached_setup now caches more to expectations
+ for test functions with multiple arguments.
+
+* merge Jarko's fixes, issue #45 and #46
+
+* add the ability to specify a path for py.lookup to search in
+
+* fix a funcarg cached_setup bug probably only occurring
+ in distributed testing and "module" scope with teardown.
+
+* many fixes and changes for making the code base python3 compatible,
+ many thanks to Benjamin Peterson for helping with this.
+
+* consolidate builtins implementation to be compatible with >=2.3,
+ add helpers to ease keeping 2 and 3k compatible code
+
+* deprecate py.compat.doctest|subprocess|textwrap|optparse
+
+* deprecate py.magic.autopath, remove py/magic directory
+
+* move pytest assertion handling to py/code and a pytest_assertion
+ plugin, add "--no-assert" option, deprecate py.magic namespaces
+ in favour of (less) py.code ones.
+
+* consolidate and cleanup py/code classes and files
+
+* cleanup py/misc, move tests to bin-for-dist
+
+* introduce delattr/delitem/delenv methods to py.test's monkeypatch funcarg
+
+* consolidate py.log implementation, remove old approach.
+
+* introduce py.io.TextIO and py.io.BytesIO for distinguishing between
+ text/unicode and byte-streams (uses underlying standard lib io.*
+ if available)
+
+* make py.unittest_convert helper script available which converts "unittest.py"
+ style files into the simpler assert/direct-test-classes py.test/nosetests
+ style. The script was written by Laura Creighton.
+
+* simplified internal localpath implementation
+
+1.0.2 (2009-08-27)
+==================
+
+* fixing packaging issues, triggered by fedora redhat packaging,
+ also added doc, examples and contrib dirs to the tarball.
+
+* added a documentation link to the new django plugin.
+
+1.0.1 (2009-08-19)
+==================
+
+* added a 'pytest_nose' plugin which handles nose.SkipTest,
+ nose-style function/method/generator setup/teardown and
+ tries to report functions correctly.
+
+* capturing of unicode writes or encoded strings to sys.stdout/err
+ work better, also terminalwriting was adapted and somewhat
+ unified between windows and linux.
+
+* improved documentation layout and content a lot
+
+* added a "--help-config" option to show conftest.py / ENV-var names for
+ all longopt cmdline options, and some special conftest.py variables.
+ renamed 'conf_capture' conftest setting to 'option_capture' accordingly.
+
+* fix issue #27: better reporting on non-collectable items given on commandline
+ (e.g. pyc files)
+
+* fix issue #33: added --version flag (thanks Benjamin Peterson)
+
+* fix issue #32: adding support for "incomplete" paths to wcpath.status()
+
+* "Test" prefixed classes are *not* collected by default anymore if they
+ have an __init__ method
+
+* monkeypatch setenv() now accepts a "prepend" parameter
+
+* improved reporting of collection error tracebacks
+
+* simplified multicall mechanism and plugin architecture,
+ renamed some internal methods and argnames
+
+1.0.0 (2009-08-04)
+==================
+
+* more terse reporting try to show filesystem path relatively to current dir
+* improve xfail output a bit
+
+1.0.0b9 (2009-07-31)
+====================
+
+* cleanly handle and report final teardown of test setup
+
+* fix svn-1.6 compat issue with py.path.svnwc().versioned()
+ (thanks Wouter Vanden Hove)
+
+* setup/teardown or collection problems now show as ERRORs
+ or with big "E"'s in the progress lines. they are reported
+ and counted separately.
+
+* dist-testing: properly handle test items that get locally
+ collected but cannot be collected on the remote side - often
+ due to platform/dependency reasons
+
+* simplified py.test.mark API - see keyword plugin documentation
+
+* integrate better with logging: capturing now by default captures
+ test functions and their immediate setup/teardown in a single stream
+
+* capsys and capfd funcargs now have a readouterr() and a close() method
+ (underlyingly py.io.StdCapture/FD objects are used which grew a
+ readouterr() method as well to return snapshots of captured out/err)
+
+* make assert-reinterpretation work better with comparisons not
+ returning bools (reported with numpy from thanks maciej fijalkowski)
+
+* reworked per-test output capturing into the pytest_iocapture.py plugin
+ and thus removed capturing code from config object
+
+* item.repr_failure(excinfo) instead of item.repr_failure(excinfo, outerr)
+
+
+1.0.0b8 (2009-07-22)
+====================
+
+* pytest_unittest-plugin is now enabled by default
+
+* introduced pytest_keyboardinterrupt hook and
+ refined pytest_sessionfinish hooked, added tests.
+
+* workaround a buggy logging module interaction ("closing already closed
+ files"). Thanks to Sridhar Ratnakumar for triggering.
+
+* if plugins use "py.test.importorskip" for importing
+ a dependency only a warning will be issued instead
+ of exiting the testing process.
+
+* many improvements to docs:
+ - refined funcargs doc , use the term "factory" instead of "provider"
+ - added a new talk/tutorial doc page
+ - better download page
+ - better plugin docstrings
+ - added new plugins page and automatic doc generation script
+
+* fixed teardown problem related to partially failing funcarg setups
+ (thanks MrTopf for reporting), "pytest_runtest_teardown" is now
+ always invoked even if the "pytest_runtest_setup" failed.
+
+* tweaked doctest output for docstrings in py modules,
+ thanks Radomir.
+
+1.0.0b7
+=======
+
+* renamed py.test.xfail back to py.test.mark.xfail to avoid
+ two ways to decorate for xfail
+
+* re-added py.test.mark decorator for setting keywords on functions
+ (it was actually documented so removing it was not nice)
+
+* remove scope-argument from request.addfinalizer() because
+ request.cached_setup has the scope arg. TOOWTDI.
+
+* perform setup finalization before reporting failures
+
+* apply modified patches from Andreas Kloeckner to allow
+ test functions to have no func_code (#22) and to make
+ "-k" and function keywords work (#20)
+
+* apply patch from Daniel Peolzleithner (issue #23)
+
+* resolve issue #18, multiprocessing.Manager() and
+ redirection clash
+
+* make __name__ == "__channelexec__" for remote_exec code
+
+1.0.0b3 (2009-06-19)
+====================
+
+* plugin classes are removed: one now defines
+ hooks directly in conftest.py or global pytest_*.py
+ files.
+
+* added new pytest_namespace(config) hook that allows
+ to inject helpers directly to the py.test.* namespace.
+
+* documented and refined many hooks
+
+* added new style of generative tests via
+ pytest_generate_tests hook that integrates
+ well with function arguments.
+
+
+1.0.0b1
+=======
+
+* introduced new "funcarg" setup method,
+ see doc/test/funcarg.txt
+
+* introduced plugin architecture and many
+ new py.test plugins, see
+ doc/test/plugins.txt
+
+* teardown_method is now guaranteed to get
+ called after a test method has run.
+
+* new method: py.test.importorskip(mod,minversion)
+ will either import or call py.test.skip()
+
+* completely revised internal py.test architecture
+
+* new py.process.ForkedFunc object allowing to
+ fork execution of a function to a sub process
+ and getting a result back.
+
+XXX lots of things missing here XXX
+
+0.9.2
+=====
+
+* refined installation and metadata, created new setup.py,
+ now based on setuptools/ez_setup (thanks to Ralf Schmitt
+ for his support).
+
+* improved the way of making py.* scripts available in
+ windows environments, they are now added to the
+ Scripts directory as ".cmd" files.
+
+* py.path.svnwc.status() now is more complete and
+ uses xml output from the 'svn' command if available
+ (Guido Wesdorp)
+
+* fix for py.path.svn* to work with svn 1.5
+ (Chris Lamb)
+
+* fix path.relto(otherpath) method on windows to
+ use normcase for checking if a path is relative.
+
+* py.test's traceback is better parseable from editors
+ (follows the filenames:LINENO: MSG convention)
+ (thanks to Osmo Salomaa)
+
+* fix to javascript-generation, "py.test --runbrowser"
+ should work more reliably now
+
+* removed previously accidentally added
+ py.test.broken and py.test.notimplemented helpers.
+
+* there now is a py.__version__ attribute
+
+0.9.1
+=====
+
+This is a fairly complete list of v0.9.1, which can
+serve as a reference for developers.
+
+* allowing + signs in py.path.svn urls [39106]
+* fixed support for Failed exceptions without excinfo in py.test [39340]
+* added support for killing processes for Windows (as well as platforms that
+ support os.kill) in py.misc.killproc [39655]
+* added setup/teardown for generative tests to py.test [40702]
+* added detection of FAILED TO LOAD MODULE to py.test [40703, 40738, 40739]
+* fixed problem with calling .remove() on wcpaths of non-versioned files in
+ py.path [44248]
+* fixed some import and inheritance issues in py.test [41480, 44648, 44655]
+* fail to run greenlet tests when pypy is available, but without stackless
+ [45294]
+* small fixes in rsession tests [45295]
+* fixed issue with 2.5 type representations in py.test [45483, 45484]
+* made that internal reporting issues displaying is done atomically in py.test
+ [45518]
+* made that non-existing files are ignored by the py.lookup script [45519]
+* improved exception name creation in py.test [45535]
+* made that less threads are used in execnet [merge in 45539]
+* removed lock required for atomic reporting issue displaying in py.test
+ [45545]
+* removed globals from execnet [45541, 45547]
+* refactored cleanup mechanics, made that setDaemon is set to 1 to make atexit
+ get called in 2.5 (py.execnet) [45548]
+* fixed bug in joining threads in py.execnet's servemain [45549]
+* refactored py.test.rsession tests to not rely on exact output format anymore
+ [45646]
+* using repr() on test outcome [45647]
+* added 'Reason' classes for py.test.skip() [45648, 45649]
+* killed some unnecessary sanity check in py.test.collect [45655]
+* avoid using os.tmpfile() in py.io.fdcapture because on Windows it's only
+ usable by Administrators [45901]
+* added support for locking and non-recursive commits to py.path.svnwc [45994]
+* locking files in py.execnet to prevent CPython from segfaulting [46010]
+* added export() method to py.path.svnurl
+* fixed -d -x in py.test [47277]
+* fixed argument concatenation problem in py.path.svnwc [49423]
+* restore py.test behaviour that it exits with code 1 when there are failures
+ [49974]
+* don't fail on html files that don't have an accompanying .txt file [50606]
+* fixed 'utestconvert.py < input' [50645]
+* small fix for code indentation in py.code.source [50755]
+* fix _docgen.py documentation building [51285]
+* improved checks for source representation of code blocks in py.test [51292]
+* added support for passing authentication to py.path.svn* objects [52000,
+ 52001]
+* removed sorted() call for py.apigen tests in favour of [].sort() to support
+ Python 2.3 [52481]
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/CONTRIBUTING.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/CONTRIBUTING.rst
new file mode 100644
index 00000000000..d85a894b910
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/CONTRIBUTING.rst
@@ -0,0 +1,278 @@
+============================
+Contribution getting started
+============================
+
+Contributions are highly welcomed and appreciated. Every little help counts,
+so do not hesitate!
+
+.. contents:: Contribution links
+ :depth: 2
+
+
+.. _submitfeedback:
+
+Feature requests and feedback
+-----------------------------
+
+Do you like pytest? Share some love on Twitter or in your blog posts!
+
+We'd also like to hear about your propositions and suggestions. Feel free to
+`submit them as issues <https://github.com/pytest-dev/pytest/issues>`_ and:
+
+* Explain in detail how they should work.
+* Keep the scope as narrow as possible. This will make it easier to implement.
+
+
+.. _reportbugs:
+
+Report bugs
+-----------
+
+Report bugs for pytest in the `issue tracker <https://github.com/pytest-dev/pytest/issues>`_.
+
+If you are reporting a bug, please include:
+
+* Your operating system name and version.
+* Any details about your local setup that might be helpful in troubleshooting,
+ specifically the Python interpreter version, installed libraries, and pytest
+ version.
+* Detailed steps to reproduce the bug.
+
+If you can write a demonstration test that currently fails but should pass
+(xfail), that is a very useful commit to make as well, even if you cannot
+fix the bug itself.
+
+
+.. _fixbugs:
+
+Fix bugs
+--------
+
+Look through the GitHub issues for bugs. Here is a filter you can use:
+https://github.com/pytest-dev/pytest/labels/type%3A%20bug
+
+:ref:`Talk <contact>` to developers to find out how you can fix specific bugs.
+
+Don't forget to check the issue trackers of your favourite plugins, too!
+
+.. _writeplugins:
+
+Implement features
+------------------
+
+Look through the GitHub issues for enhancements. Here is a filter you can use:
+https://github.com/pytest-dev/pytest/labels/enhancement
+
+:ref:`Talk <contact>` to developers to find out how you can implement specific
+features.
+
+Write documentation
+-------------------
+
+Pytest could always use more documentation. What exactly is needed?
+
+* More complementary documentation. Have you perhaps found something unclear?
+* Documentation translations. We currently have only English.
+* Docstrings. There can never be too many of them.
+* Blog posts, articles and such -- they're all very appreciated.
+
+You can also edit documentation files directly in the GitHub web interface,
+without using a local copy. This can be convenient for small fixes.
+
+.. note::
+ Build the documentation locally with the following command:
+
+ .. code:: bash
+
+ $ tox -e docs
+
+ The built documentation should be available in the ``doc/en/_build/``.
+
+ Where 'en' refers to the documentation language.
+
+.. _submitplugin:
+
+Submitting Plugins to pytest-dev
+--------------------------------
+
+Pytest development of the core, some plugins and support code happens
+in repositories living under the ``pytest-dev`` organisations:
+
+- `pytest-dev on GitHub <https://github.com/pytest-dev>`_
+
+- `pytest-dev on Bitbucket <https://bitbucket.org/pytest-dev>`_
+
+All pytest-dev Contributors team members have write access to all contained
+repositories. Pytest core and plugins are generally developed
+using `pull requests`_ to respective repositories.
+
+The objectives of the ``pytest-dev`` organisation are:
+
+* Having a central location for popular pytest plugins
+* Sharing some of the maintenance responsibility (in case a maintainer no
+ longer wishes to maintain a plugin)
+
+You can submit your plugin by subscribing to the `pytest-dev mail list
+<https://mail.python.org/mailman/listinfo/pytest-dev>`_ and writing a
+mail pointing to your existing pytest plugin repository which must have
+the following:
+
+- PyPI presence with a ``setup.py`` that contains a license, ``pytest-``
+ prefixed name, version number, authors, short and long description.
+
+- a ``tox.ini`` for running tests using `tox <https://tox.readthedocs.io>`_.
+
+- a ``README.txt`` describing how to use the plugin and on which
+ platforms it runs.
+
+- a ``LICENSE.txt`` file or equivalent containing the licensing
+ information, with matching info in ``setup.py``.
+
+- an issue tracker for bug reports and enhancement requests.
+
+- a `changelog <http://keepachangelog.com/>`_
+
+If no contributor strongly objects and two agree, the repository can then be
+transferred to the ``pytest-dev`` organisation.
+
+Here's a rundown of how a repository transfer usually proceeds
+(using a repository named ``joedoe/pytest-xyz`` as example):
+
+* ``joedoe`` transfers repository ownership to ``pytest-dev`` administrator ``calvin``.
+* ``calvin`` creates ``pytest-xyz-admin`` and ``pytest-xyz-developers`` teams, inviting ``joedoe`` to both as **maintainer**.
+* ``calvin`` transfers repository to ``pytest-dev`` and configures team access:
+
+ - ``pytest-xyz-admin`` **admin** access;
+ - ``pytest-xyz-developers`` **write** access;
+
+The ``pytest-dev/Contributors`` team has write access to all projects, and
+every project administrator is in it. We recommend that each plugin has at least three
+people who have the right to release to PyPI.
+
+Repository owners can rest assured that no ``pytest-dev`` administrator will ever make
+releases of your repository or take ownership in any way, except in rare cases
+where someone becomes unresponsive after months of contact attempts.
+As stated, the objective is to share maintenance and avoid "plugin-abandon".
+
+
+.. _`pull requests`:
+.. _pull-requests:
+
+Preparing Pull Requests
+-----------------------
+
+Short version
+~~~~~~~~~~~~~
+
+#. Fork the repository;
+#. Target ``master`` for bugfixes and doc changes;
+#. Target ``features`` for new features or functionality changes.
+#. Follow **PEP-8**. There's a ``tox`` command to help fixing it: ``tox -e fix-lint``.
+#. Tests are run using ``tox``::
+
+ tox -e linting,py27,py36
+
+ The test environments above are usually enough to cover most cases locally.
+
+#. Write a ``changelog`` entry: ``changelog/2574.bugfix``, use issue id number
+ and one of ``bugfix``, ``removal``, ``feature``, ``vendor``, ``doc`` or
+ ``trivial`` for the issue type.
+#. Unless your change is a trivial or a documentation fix (e.g., a typo or reword of a small section) please
+ add yourself to the ``AUTHORS`` file, in alphabetical order;
+
+
+Long version
+~~~~~~~~~~~~
+
+What is a "pull request"? It informs the project's core developers about the
+changes you want to review and merge. Pull requests are stored on
+`GitHub servers <https://github.com/pytest-dev/pytest/pulls>`_.
+Once you send a pull request, we can discuss its potential modifications and
+even add more commits to it later on. There's an excellent tutorial on how Pull
+Requests work in the
+`GitHub Help Center <https://help.github.com/articles/using-pull-requests/>`_.
+
+Here is a simple overview, with pytest-specific bits:
+
+#. Fork the
+ `pytest GitHub repository <https://github.com/pytest-dev/pytest>`__. It's
+ fine to use ``pytest`` as your fork repository name because it will live
+ under your user.
+
+#. Clone your fork locally using `git <https://git-scm.com/>`_ and create a branch::
+
+ $ git clone git@github.com:YOUR_GITHUB_USERNAME/pytest.git
+ $ cd pytest
+ # now, to fix a bug create your own branch off "master":
+
+ $ git checkout -b your-bugfix-branch-name master
+
+ # or to instead add a feature create your own branch off "features":
+
+ $ git checkout -b your-feature-branch-name features
+
+ Given we have "major.minor.micro" version numbers, bugfixes will usually
+ be released in micro releases whereas features will be released in
+ minor releases and incompatible changes in major releases.
+
+ If you need some help with Git, follow this quick start
+ guide: https://git.wiki.kernel.org/index.php/QuickStart
+
+#. Install tox
+
+ Tox is used to run all the tests and will automatically setup virtualenvs
+ to run the tests in.
+ (will implicitly use http://www.virtualenv.org/en/latest/)::
+
+ $ pip install tox
+
+#. Run all the tests
+
+ You need to have Python 2.7 and 3.6 available in your system. Now
+ running tests is as simple as issuing this command::
+
+ $ tox -e linting,py27,py36
+
+ This command will run tests via the "tox" tool against Python 2.7 and 3.6
+ and also perform "lint" coding-style checks.
+
+#. You can now edit your local working copy. Please follow PEP-8.
+
+ You can now make the changes you want and run the tests again as necessary.
+
+ If you have too much linting errors, try running::
+
+ $ tox -e fix-lint
+
+ To fix pep8 related errors.
+
+ You can pass different options to ``tox``. For example, to run tests on Python 2.7 and pass options to pytest
+ (e.g. enter pdb on failure) to pytest you can do::
+
+ $ tox -e py27 -- --pdb
+
+ Or to only run tests in a particular test module on Python 3.6::
+
+ $ tox -e py36 -- testing/test_config.py
+
+#. Commit and push once your tests pass and you are happy with your change(s)::
+
+ $ git commit -a -m "<commit message>"
+ $ git push -u
+
+#. Create a new changelog entry in ``changelog``. The file should be named ``<issueid>.<type>``,
+ where *issueid* is the number of the issue related to the change and *type* is one of
+ ``bugfix``, ``removal``, ``feature``, ``vendor``, ``doc`` or ``trivial``.
+
+#. Add yourself to ``AUTHORS`` file if not there yet, in alphabetical order.
+
+#. Finally, submit a pull request through the GitHub website using this data::
+
+ head-fork: YOUR_GITHUB_USERNAME/pytest
+ compare: your-branch-name
+
+ base-fork: pytest-dev/pytest
+ base: master # if it's a bugfix
+ base: features # if it's a feature
+
+
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/HOWTORELEASE.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/HOWTORELEASE.rst
new file mode 100644
index 00000000000..48a3461d4bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/HOWTORELEASE.rst
@@ -0,0 +1,65 @@
+Release Procedure
+-----------------
+
+Our current policy for releasing is to aim for a bugfix every few weeks and a minor release every 2-3 months. The idea
+is to get fixes and new features out instead of trying to cram a ton of features into a release and by consequence
+taking a lot of time to make a new one.
+
+.. important::
+
+ pytest releases must be prepared on **Linux** because the docs and examples expect
+ to be executed in that platform.
+
+#. Install development dependencies in a virtual environment with::
+
+ pip3 install -r tasks/requirements.txt
+
+#. Create a branch ``release-X.Y.Z`` with the version for the release.
+
+ * **patch releases**: from the latest ``master``;
+
+ * **minor releases**: from the latest ``features``; then merge with the latest ``master``;
+
+ Ensure your are in a clean work tree.
+
+#. Generate docs, changelog, announcements and upload a package to
+ your ``devpi`` staging server::
+
+ invoke generate.pre-release <VERSION> <DEVPI USER> --password <DEVPI PASSWORD>
+
+ If ``--password`` is not given, it is assumed the user is already logged in ``devpi``.
+ If you don't have an account, please ask for one.
+
+#. Open a PR for this branch targeting ``master``.
+
+#. Test the package
+
+ * **Manual method**
+
+ Run from multiple machines::
+
+ devpi use https://devpi.net/USER/dev
+ devpi test pytest==VERSION
+
+ Check that tests pass for relevant combinations with::
+
+ devpi list pytest
+
+ * **CI servers**
+
+ Configure a repository as per-instructions on
+ devpi-cloud-test_ to test the package on Travis_ and AppVeyor_.
+ All test environments should pass.
+
+#. Publish to PyPI::
+
+ invoke generate.publish-release <VERSION> <DEVPI USER> <PYPI_NAME>
+
+ where PYPI_NAME is the name of pypi.python.org as configured in your ``~/.pypirc``
+ file `for devpi <http://doc.devpi.net/latest/quickstart-releaseprocess.html?highlight=pypirc#devpi-push-releasing-to-an-external-index>`_.
+
+#. After a minor/major release, merge ``release-X.Y.Z`` into ``master`` and push (or open a PR).
+
+.. _devpi-cloud-test: https://github.com/obestwalter/devpi-cloud-test
+.. _AppVeyor: https://www.appveyor.com/
+.. _Travis: https://travis-ci.org
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/LICENSE b/tests/wpt/web-platform-tests/tools/third_party/pytest/LICENSE
new file mode 100644
index 00000000000..629df45ac40
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2004-2017 Holger Krekel and others
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/README.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/README.rst
new file mode 100644
index 00000000000..3630dd4c62a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/README.rst
@@ -0,0 +1,109 @@
+.. image:: http://docs.pytest.org/en/latest/_static/pytest1.png
+ :target: http://docs.pytest.org
+ :align: center
+ :alt: pytest
+
+------
+
+.. image:: https://img.shields.io/pypi/v/pytest.svg
+ :target: https://pypi.python.org/pypi/pytest
+
+.. image:: https://anaconda.org/conda-forge/pytest/badges/version.svg
+ :target: https://anaconda.org/conda-forge/pytest
+
+.. image:: https://img.shields.io/pypi/pyversions/pytest.svg
+ :target: https://pypi.python.org/pypi/pytest
+
+.. image:: https://img.shields.io/coveralls/pytest-dev/pytest/master.svg
+ :target: https://coveralls.io/r/pytest-dev/pytest
+
+.. image:: https://travis-ci.org/pytest-dev/pytest.svg?branch=master
+ :target: https://travis-ci.org/pytest-dev/pytest
+
+.. image:: https://ci.appveyor.com/api/projects/status/mrgbjaua7t33pg6b?svg=true
+ :target: https://ci.appveyor.com/project/pytestbot/pytest
+
+The ``pytest`` framework makes it easy to write small tests, yet
+scales to support complex functional testing for applications and libraries.
+
+An example of a simple test:
+
+.. code-block:: python
+
+ # content of test_sample.py
+ def inc(x):
+ return x + 1
+
+ def test_answer():
+ assert inc(3) == 5
+
+
+To execute it::
+
+ $ pytest
+ ============================= test session starts =============================
+ collected 1 items
+
+ test_sample.py F
+
+ ================================== FAILURES ===================================
+ _________________________________ test_answer _________________________________
+
+ def test_answer():
+ > assert inc(3) == 5
+ E assert 4 == 5
+ E + where 4 = inc(3)
+
+ test_sample.py:5: AssertionError
+ ========================== 1 failed in 0.04 seconds ===========================
+
+
+Due to ``pytest``'s detailed assertion introspection, only plain ``assert`` statements are used. See `getting-started <http://docs.pytest.org/en/latest/getting-started.html#our-first-test-run>`_ for more examples.
+
+
+Features
+--------
+
+- Detailed info on failing `assert statements <http://docs.pytest.org/en/latest/assert.html>`_ (no need to remember ``self.assert*`` names);
+
+- `Auto-discovery
+ <http://docs.pytest.org/en/latest/goodpractices.html#python-test-discovery>`_
+ of test modules and functions;
+
+- `Modular fixtures <http://docs.pytest.org/en/latest/fixture.html>`_ for
+ managing small or parametrized long-lived test resources;
+
+- Can run `unittest <http://docs.pytest.org/en/latest/unittest.html>`_ (or trial),
+ `nose <http://docs.pytest.org/en/latest/nose.html>`_ test suites out of the box;
+
+- Python 2.7, Python 3.4+, PyPy 2.3, Jython 2.5 (untested);
+
+- Rich plugin architecture, with over 315+ `external plugins <http://plugincompat.herokuapp.com>`_ and thriving community;
+
+
+Documentation
+-------------
+
+For full documentation, including installation, tutorials and PDF documents, please see http://docs.pytest.org.
+
+
+Bugs/Requests
+-------------
+
+Please use the `GitHub issue tracker <https://github.com/pytest-dev/pytest/issues>`_ to submit bugs or request features.
+
+
+Changelog
+---------
+
+Consult the `Changelog <http://docs.pytest.org/en/latest/changelog.html>`__ page for fixes and enhancements of each version.
+
+
+License
+-------
+
+Copyright Holger Krekel and others, 2004-2017.
+
+Distributed under the terms of the `MIT`_ license, pytest is free and open source software.
+
+.. _`MIT`: https://github.com/pytest-dev/pytest/blob/master/LICENSE
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/__init__.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/__init__.py
new file mode 100644
index 00000000000..6e41f0504e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/__init__.py
@@ -0,0 +1,8 @@
+__all__ = ['__version__']
+
+try:
+ from ._version import version as __version__
+except ImportError:
+ # broken installation, we don't even try
+ # unknown only works because we do poor mans version compare
+ __version__ = 'unknown'
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/_argcomplete.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/_argcomplete.py
new file mode 100644
index 00000000000..0625a75f9f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/_argcomplete.py
@@ -0,0 +1,103 @@
+
+"""allow bash-completion for argparse with argcomplete if installed
+needs argcomplete>=0.5.6 for python 3.2/3.3 (older versions fail
+to find the magic string, so _ARGCOMPLETE env. var is never set, and
+this does not need special code.
+
+Function try_argcomplete(parser) should be called directly before
+the call to ArgumentParser.parse_args().
+
+The filescompleter is what you normally would use on the positional
+arguments specification, in order to get "dirname/" after "dirn<TAB>"
+instead of the default "dirname ":
+
+ optparser.add_argument(Config._file_or_dir, nargs='*'
+ ).completer=filescompleter
+
+Other, application specific, completers should go in the file
+doing the add_argument calls as they need to be specified as .completer
+attributes as well. (If argcomplete is not installed, the function the
+attribute points to will not be used).
+
+SPEEDUP
+=======
+The generic argcomplete script for bash-completion
+(/etc/bash_completion.d/python-argcomplete.sh )
+uses a python program to determine startup script generated by pip.
+You can speed up completion somewhat by changing this script to include
+ # PYTHON_ARGCOMPLETE_OK
+so the the python-argcomplete-check-easy-install-script does not
+need to be called to find the entry point of the code and see if that is
+marked with PYTHON_ARGCOMPLETE_OK
+
+INSTALL/DEBUGGING
+=================
+To include this support in another application that has setup.py generated
+scripts:
+- add the line:
+ # PYTHON_ARGCOMPLETE_OK
+ near the top of the main python entry point
+- include in the file calling parse_args():
+ from _argcomplete import try_argcomplete, filescompleter
+ , call try_argcomplete just before parse_args(), and optionally add
+ filescompleter to the positional arguments' add_argument()
+If things do not work right away:
+- switch on argcomplete debugging with (also helpful when doing custom
+ completers):
+ export _ARC_DEBUG=1
+- run:
+ python-argcomplete-check-easy-install-script $(which appname)
+ echo $?
+ will echo 0 if the magic line has been found, 1 if not
+- sometimes it helps to find early on errors using:
+ _ARGCOMPLETE=1 _ARC_DEBUG=1 appname
+ which should throw a KeyError: 'COMPLINE' (which is properly set by the
+ global argcomplete script).
+"""
+from __future__ import absolute_import, division, print_function
+import sys
+import os
+from glob import glob
+
+
+class FastFilesCompleter:
+ 'Fast file completer class'
+
+ def __init__(self, directories=True):
+ self.directories = directories
+
+ def __call__(self, prefix, **kwargs):
+ """only called on non option completions"""
+ if os.path.sep in prefix[1:]:
+ prefix_dir = len(os.path.dirname(prefix) + os.path.sep)
+ else:
+ prefix_dir = 0
+ completion = []
+ globbed = []
+ if '*' not in prefix and '?' not in prefix:
+ # we are on unix, otherwise no bash
+ if not prefix or prefix[-1] == os.path.sep:
+ globbed.extend(glob(prefix + '.*'))
+ prefix += '*'
+ globbed.extend(glob(prefix))
+ for x in sorted(globbed):
+ if os.path.isdir(x):
+ x += '/'
+ # append stripping the prefix (like bash, not like compgen)
+ completion.append(x[prefix_dir:])
+ return completion
+
+
+if os.environ.get('_ARGCOMPLETE'):
+ try:
+ import argcomplete.completers
+ except ImportError:
+ sys.exit(-1)
+ filescompleter = FastFilesCompleter()
+
+ def try_argcomplete(parser):
+ argcomplete.autocomplete(parser, always_complete_options=False)
+else:
+ def try_argcomplete(parser):
+ pass
+ filescompleter = None
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/_code/__init__.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/_code/__init__.py
new file mode 100644
index 00000000000..815c13b42c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/_code/__init__.py
@@ -0,0 +1,10 @@
+""" python inspection/code generation API """
+from __future__ import absolute_import, division, print_function
+from .code import Code # noqa
+from .code import ExceptionInfo # noqa
+from .code import Frame # noqa
+from .code import Traceback # noqa
+from .code import getrawcode # noqa
+from .source import Source # noqa
+from .source import compile_ as compile # noqa
+from .source import getfslineno # noqa
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/_code/_py2traceback.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/_code/_py2traceback.py
new file mode 100644
index 00000000000..5aacf0a428d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/_code/_py2traceback.py
@@ -0,0 +1,85 @@
+# copied from python-2.7.3's traceback.py
+# CHANGES:
+# - some_str is replaced, trying to create unicode strings
+#
+from __future__ import absolute_import, division, print_function
+import types
+
+
+def format_exception_only(etype, value):
+ """Format the exception part of a traceback.
+
+ The arguments are the exception type and value such as given by
+ sys.last_type and sys.last_value. The return value is a list of
+ strings, each ending in a newline.
+
+ Normally, the list contains a single string; however, for
+ SyntaxError exceptions, it contains several lines that (when
+ printed) display detailed information about where the syntax
+ error occurred.
+
+ The message indicating which exception occurred is always the last
+ string in the list.
+
+ """
+
+ # An instance should not have a meaningful value parameter, but
+ # sometimes does, particularly for string exceptions, such as
+ # >>> raise string1, string2 # deprecated
+ #
+ # Clear these out first because issubtype(string1, SyntaxError)
+ # would throw another exception and mask the original problem.
+ if (isinstance(etype, BaseException) or
+ isinstance(etype, types.InstanceType) or
+ etype is None or type(etype) is str):
+ return [_format_final_exc_line(etype, value)]
+
+ stype = etype.__name__
+
+ if not issubclass(etype, SyntaxError):
+ return [_format_final_exc_line(stype, value)]
+
+ # It was a syntax error; show exactly where the problem was found.
+ lines = []
+ try:
+ msg, (filename, lineno, offset, badline) = value.args
+ except Exception:
+ pass
+ else:
+ filename = filename or "<string>"
+ lines.append(' File "%s", line %d\n' % (filename, lineno))
+ if badline is not None:
+ if isinstance(badline, bytes): # python 2 only
+ badline = badline.decode('utf-8', 'replace')
+ lines.append(u' %s\n' % badline.strip())
+ if offset is not None:
+ caretspace = badline.rstrip('\n')[:offset].lstrip()
+ # non-space whitespace (likes tabs) must be kept for alignment
+ caretspace = ((c.isspace() and c or ' ') for c in caretspace)
+ # only three spaces to account for offset1 == pos 0
+ lines.append(' %s^\n' % ''.join(caretspace))
+ value = msg
+
+ lines.append(_format_final_exc_line(stype, value))
+ return lines
+
+
+def _format_final_exc_line(etype, value):
+ """Return a list of a single line -- normal case for format_exception_only"""
+ valuestr = _some_str(value)
+ if value is None or not valuestr:
+ line = "%s\n" % etype
+ else:
+ line = "%s: %s\n" % (etype, valuestr)
+ return line
+
+
+def _some_str(value):
+ try:
+ return unicode(value)
+ except Exception:
+ try:
+ return str(value)
+ except Exception:
+ pass
+ return '<unprintable %s object>' % type(value).__name__
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/_code/code.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/_code/code.py
new file mode 100644
index 00000000000..3fb232bd430
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/_code/code.py
@@ -0,0 +1,906 @@
+from __future__ import absolute_import, division, print_function
+import sys
+from inspect import CO_VARARGS, CO_VARKEYWORDS
+import re
+from weakref import ref
+from _pytest.compat import _PY2, _PY3, PY35, safe_str
+
+import py
+builtin_repr = repr
+
+if _PY3:
+ from traceback import format_exception_only
+else:
+ from ._py2traceback import format_exception_only
+
+
+class Code(object):
+ """ wrapper around Python code objects """
+
+ def __init__(self, rawcode):
+ if not hasattr(rawcode, "co_filename"):
+ rawcode = getrawcode(rawcode)
+ try:
+ self.filename = rawcode.co_filename
+ self.firstlineno = rawcode.co_firstlineno - 1
+ self.name = rawcode.co_name
+ except AttributeError:
+ raise TypeError("not a code object: %r" % (rawcode,))
+ self.raw = rawcode
+
+ def __eq__(self, other):
+ return self.raw == other.raw
+
+ __hash__ = None
+
+ def __ne__(self, other):
+ return not self == other
+
+ @property
+ def path(self):
+ """ return a path object pointing to source code (note that it
+ might not point to an actually existing file). """
+ try:
+ p = py.path.local(self.raw.co_filename)
+ # maybe don't try this checking
+ if not p.check():
+ raise OSError("py.path check failed.")
+ except OSError:
+ # XXX maybe try harder like the weird logic
+ # in the standard lib [linecache.updatecache] does?
+ p = self.raw.co_filename
+
+ return p
+
+ @property
+ def fullsource(self):
+ """ return a _pytest._code.Source object for the full source file of the code
+ """
+ from _pytest._code import source
+ full, _ = source.findsource(self.raw)
+ return full
+
+ def source(self):
+ """ return a _pytest._code.Source object for the code object's source only
+ """
+ # return source only for that part of code
+ import _pytest._code
+ return _pytest._code.Source(self.raw)
+
+ def getargs(self, var=False):
+ """ return a tuple with the argument names for the code object
+
+ if 'var' is set True also return the names of the variable and
+ keyword arguments when present
+ """
+ # handfull shortcut for getting args
+ raw = self.raw
+ argcount = raw.co_argcount
+ if var:
+ argcount += raw.co_flags & CO_VARARGS
+ argcount += raw.co_flags & CO_VARKEYWORDS
+ return raw.co_varnames[:argcount]
+
+
+class Frame(object):
+ """Wrapper around a Python frame holding f_locals and f_globals
+ in which expressions can be evaluated."""
+
+ def __init__(self, frame):
+ self.lineno = frame.f_lineno - 1
+ self.f_globals = frame.f_globals
+ self.f_locals = frame.f_locals
+ self.raw = frame
+ self.code = Code(frame.f_code)
+
+ @property
+ def statement(self):
+ """ statement this frame is at """
+ import _pytest._code
+ if self.code.fullsource is None:
+ return _pytest._code.Source("")
+ return self.code.fullsource.getstatement(self.lineno)
+
+ def eval(self, code, **vars):
+ """ evaluate 'code' in the frame
+
+ 'vars' are optional additional local variables
+
+ returns the result of the evaluation
+ """
+ f_locals = self.f_locals.copy()
+ f_locals.update(vars)
+ return eval(code, self.f_globals, f_locals)
+
+ def exec_(self, code, **vars):
+ """ exec 'code' in the frame
+
+ 'vars' are optiona; additional local variables
+ """
+ f_locals = self.f_locals.copy()
+ f_locals.update(vars)
+ py.builtin.exec_(code, self.f_globals, f_locals)
+
+ def repr(self, object):
+ """ return a 'safe' (non-recursive, one-line) string repr for 'object'
+ """
+ return py.io.saferepr(object)
+
+ def is_true(self, object):
+ return object
+
+ def getargs(self, var=False):
+ """ return a list of tuples (name, value) for all arguments
+
+ if 'var' is set True also include the variable and keyword
+ arguments when present
+ """
+ retval = []
+ for arg in self.code.getargs(var):
+ try:
+ retval.append((arg, self.f_locals[arg]))
+ except KeyError:
+ pass # this can occur when using Psyco
+ return retval
+
+
+class TracebackEntry(object):
+ """ a single entry in a traceback """
+
+ _repr_style = None
+ exprinfo = None
+
+ def __init__(self, rawentry, excinfo=None):
+ self._excinfo = excinfo
+ self._rawentry = rawentry
+ self.lineno = rawentry.tb_lineno - 1
+
+ def set_repr_style(self, mode):
+ assert mode in ("short", "long")
+ self._repr_style = mode
+
+ @property
+ def frame(self):
+ import _pytest._code
+ return _pytest._code.Frame(self._rawentry.tb_frame)
+
+ @property
+ def relline(self):
+ return self.lineno - self.frame.code.firstlineno
+
+ def __repr__(self):
+ return "<TracebackEntry %s:%d>" % (self.frame.code.path, self.lineno + 1)
+
+ @property
+ def statement(self):
+ """ _pytest._code.Source object for the current statement """
+ source = self.frame.code.fullsource
+ return source.getstatement(self.lineno)
+
+ @property
+ def path(self):
+ """ path to the source code """
+ return self.frame.code.path
+
+ def getlocals(self):
+ return self.frame.f_locals
+ locals = property(getlocals, None, None, "locals of underlaying frame")
+
+ def getfirstlinesource(self):
+ # on Jython this firstlineno can be -1 apparently
+ return max(self.frame.code.firstlineno, 0)
+
+ def getsource(self, astcache=None):
+ """ return failing source code. """
+ # we use the passed in astcache to not reparse asttrees
+ # within exception info printing
+ from _pytest._code.source import getstatementrange_ast
+ source = self.frame.code.fullsource
+ if source is None:
+ return None
+ key = astnode = None
+ if astcache is not None:
+ key = self.frame.code.path
+ if key is not None:
+ astnode = astcache.get(key, None)
+ start = self.getfirstlinesource()
+ try:
+ astnode, _, end = getstatementrange_ast(self.lineno, source,
+ astnode=astnode)
+ except SyntaxError:
+ end = self.lineno + 1
+ else:
+ if key is not None:
+ astcache[key] = astnode
+ return source[start:end]
+
+ source = property(getsource)
+
+ def ishidden(self):
+ """ return True if the current frame has a var __tracebackhide__
+ resolving to True
+
+ If __tracebackhide__ is a callable, it gets called with the
+ ExceptionInfo instance and can decide whether to hide the traceback.
+
+ mostly for internal use
+ """
+ try:
+ tbh = self.frame.f_locals['__tracebackhide__']
+ except KeyError:
+ try:
+ tbh = self.frame.f_globals['__tracebackhide__']
+ except KeyError:
+ return False
+
+ if callable(tbh):
+ return tbh(None if self._excinfo is None else self._excinfo())
+ else:
+ return tbh
+
+ def __str__(self):
+ try:
+ fn = str(self.path)
+ except py.error.Error:
+ fn = '???'
+ name = self.frame.code.name
+ try:
+ line = str(self.statement).lstrip()
+ except KeyboardInterrupt:
+ raise
+ except: # noqa
+ line = "???"
+ return " File %r:%d in %s\n %s\n" % (fn, self.lineno + 1, name, line)
+
+ def name(self):
+ return self.frame.code.raw.co_name
+ name = property(name, None, None, "co_name of underlaying code")
+
+
+class Traceback(list):
+ """ Traceback objects encapsulate and offer higher level
+ access to Traceback entries.
+ """
+ Entry = TracebackEntry
+
+ def __init__(self, tb, excinfo=None):
+ """ initialize from given python traceback object and ExceptionInfo """
+ self._excinfo = excinfo
+ if hasattr(tb, 'tb_next'):
+ def f(cur):
+ while cur is not None:
+ yield self.Entry(cur, excinfo=excinfo)
+ cur = cur.tb_next
+ list.__init__(self, f(tb))
+ else:
+ list.__init__(self, tb)
+
+ def cut(self, path=None, lineno=None, firstlineno=None, excludepath=None):
+ """ return a Traceback instance wrapping part of this Traceback
+
+ by provding any combination of path, lineno and firstlineno, the
+ first frame to start the to-be-returned traceback is determined
+
+ this allows cutting the first part of a Traceback instance e.g.
+ for formatting reasons (removing some uninteresting bits that deal
+ with handling of the exception/traceback)
+ """
+ for x in self:
+ code = x.frame.code
+ codepath = code.path
+ if ((path is None or codepath == path) and
+ (excludepath is None or not hasattr(codepath, 'relto') or
+ not codepath.relto(excludepath)) and
+ (lineno is None or x.lineno == lineno) and
+ (firstlineno is None or x.frame.code.firstlineno == firstlineno)):
+ return Traceback(x._rawentry, self._excinfo)
+ return self
+
+ def __getitem__(self, key):
+ val = super(Traceback, self).__getitem__(key)
+ if isinstance(key, type(slice(0))):
+ val = self.__class__(val)
+ return val
+
+ def filter(self, fn=lambda x: not x.ishidden()):
+ """ return a Traceback instance with certain items removed
+
+ fn is a function that gets a single argument, a TracebackEntry
+ instance, and should return True when the item should be added
+ to the Traceback, False when not
+
+ by default this removes all the TracebackEntries which are hidden
+ (see ishidden() above)
+ """
+ return Traceback(filter(fn, self), self._excinfo)
+
+ def getcrashentry(self):
+ """ return last non-hidden traceback entry that lead
+ to the exception of a traceback.
+ """
+ for i in range(-1, -len(self) - 1, -1):
+ entry = self[i]
+ if not entry.ishidden():
+ return entry
+ return self[-1]
+
+ def recursionindex(self):
+ """ return the index of the frame/TracebackEntry where recursion
+ originates if appropriate, None if no recursion occurred
+ """
+ cache = {}
+ for i, entry in enumerate(self):
+ # id for the code.raw is needed to work around
+ # the strange metaprogramming in the decorator lib from pypi
+ # which generates code objects that have hash/value equality
+ # XXX needs a test
+ key = entry.frame.code.path, id(entry.frame.code.raw), entry.lineno
+ # print "checking for recursion at", key
+ values = cache.setdefault(key, [])
+ if values:
+ f = entry.frame
+ loc = f.f_locals
+ for otherloc in values:
+ if f.is_true(f.eval(co_equal,
+ __recursioncache_locals_1=loc,
+ __recursioncache_locals_2=otherloc)):
+ return i
+ values.append(entry.frame.f_locals)
+ return None
+
+
+co_equal = compile('__recursioncache_locals_1 == __recursioncache_locals_2',
+ '?', 'eval')
+
+
+class ExceptionInfo(object):
+ """ wraps sys.exc_info() objects and offers
+ help for navigating the traceback.
+ """
+ _striptext = ''
+ _assert_start_repr = "AssertionError(u\'assert " if _PY2 else "AssertionError(\'assert "
+
+ def __init__(self, tup=None, exprinfo=None):
+ import _pytest._code
+ if tup is None:
+ tup = sys.exc_info()
+ if exprinfo is None and isinstance(tup[1], AssertionError):
+ exprinfo = getattr(tup[1], 'msg', None)
+ if exprinfo is None:
+ exprinfo = py.io.saferepr(tup[1])
+ if exprinfo and exprinfo.startswith(self._assert_start_repr):
+ self._striptext = 'AssertionError: '
+ self._excinfo = tup
+ #: the exception class
+ self.type = tup[0]
+ #: the exception instance
+ self.value = tup[1]
+ #: the exception raw traceback
+ self.tb = tup[2]
+ #: the exception type name
+ self.typename = self.type.__name__
+ #: the exception traceback (_pytest._code.Traceback instance)
+ self.traceback = _pytest._code.Traceback(self.tb, excinfo=ref(self))
+
+ def __repr__(self):
+ return "<ExceptionInfo %s tblen=%d>" % (self.typename, len(self.traceback))
+
+ def exconly(self, tryshort=False):
+ """ return the exception as a string
+
+ when 'tryshort' resolves to True, and the exception is a
+ _pytest._code._AssertionError, only the actual exception part of
+ the exception representation is returned (so 'AssertionError: ' is
+ removed from the beginning)
+ """
+ lines = format_exception_only(self.type, self.value)
+ text = ''.join(lines)
+ text = text.rstrip()
+ if tryshort:
+ if text.startswith(self._striptext):
+ text = text[len(self._striptext):]
+ return text
+
+ def errisinstance(self, exc):
+ """ return True if the exception is an instance of exc """
+ return isinstance(self.value, exc)
+
+ def _getreprcrash(self):
+ exconly = self.exconly(tryshort=True)
+ entry = self.traceback.getcrashentry()
+ path, lineno = entry.frame.code.raw.co_filename, entry.lineno
+ return ReprFileLocation(path, lineno + 1, exconly)
+
+ def getrepr(self, showlocals=False, style="long",
+ abspath=False, tbfilter=True, funcargs=False):
+ """ return str()able representation of this exception info.
+ showlocals: show locals per traceback entry
+ style: long|short|no|native traceback style
+ tbfilter: hide entries (where __tracebackhide__ is true)
+
+ in case of style==native, tbfilter and showlocals is ignored.
+ """
+ if style == 'native':
+ return ReprExceptionInfo(ReprTracebackNative(
+ py.std.traceback.format_exception(
+ self.type,
+ self.value,
+ self.traceback[0]._rawentry,
+ )), self._getreprcrash())
+
+ fmt = FormattedExcinfo(showlocals=showlocals, style=style,
+ abspath=abspath, tbfilter=tbfilter, funcargs=funcargs)
+ return fmt.repr_excinfo(self)
+
+ def __str__(self):
+ entry = self.traceback[-1]
+ loc = ReprFileLocation(entry.path, entry.lineno + 1, self.exconly())
+ return str(loc)
+
+ def __unicode__(self):
+ entry = self.traceback[-1]
+ loc = ReprFileLocation(entry.path, entry.lineno + 1, self.exconly())
+ return unicode(loc)
+
+ def match(self, regexp):
+ """
+ Match the regular expression 'regexp' on the string representation of
+ the exception. If it matches then True is returned (so that it is
+ possible to write 'assert excinfo.match()'). If it doesn't match an
+ AssertionError is raised.
+ """
+ __tracebackhide__ = True
+ if not re.search(regexp, str(self.value)):
+ assert 0, "Pattern '{0!s}' not found in '{1!s}'".format(
+ regexp, self.value)
+ return True
+
+
+class FormattedExcinfo(object):
+ """ presenting information about failing Functions and Generators. """
+ # for traceback entries
+ flow_marker = ">"
+ fail_marker = "E"
+
+ def __init__(self, showlocals=False, style="long", abspath=True, tbfilter=True, funcargs=False):
+ self.showlocals = showlocals
+ self.style = style
+ self.tbfilter = tbfilter
+ self.funcargs = funcargs
+ self.abspath = abspath
+ self.astcache = {}
+
+ def _getindent(self, source):
+ # figure out indent for given source
+ try:
+ s = str(source.getstatement(len(source) - 1))
+ except KeyboardInterrupt:
+ raise
+ except: # noqa
+ try:
+ s = str(source[-1])
+ except KeyboardInterrupt:
+ raise
+ except: # noqa
+ return 0
+ return 4 + (len(s) - len(s.lstrip()))
+
+ def _getentrysource(self, entry):
+ source = entry.getsource(self.astcache)
+ if source is not None:
+ source = source.deindent()
+ return source
+
+ def _saferepr(self, obj):
+ return py.io.saferepr(obj)
+
+ def repr_args(self, entry):
+ if self.funcargs:
+ args = []
+ for argname, argvalue in entry.frame.getargs(var=True):
+ args.append((argname, self._saferepr(argvalue)))
+ return ReprFuncArgs(args)
+
+ def get_source(self, source, line_index=-1, excinfo=None, short=False):
+ """ return formatted and marked up source lines. """
+ import _pytest._code
+ lines = []
+ if source is None or line_index >= len(source.lines):
+ source = _pytest._code.Source("???")
+ line_index = 0
+ if line_index < 0:
+ line_index += len(source)
+ space_prefix = " "
+ if short:
+ lines.append(space_prefix + source.lines[line_index].strip())
+ else:
+ for line in source.lines[:line_index]:
+ lines.append(space_prefix + line)
+ lines.append(self.flow_marker + " " + source.lines[line_index])
+ for line in source.lines[line_index + 1:]:
+ lines.append(space_prefix + line)
+ if excinfo is not None:
+ indent = 4 if short else self._getindent(source)
+ lines.extend(self.get_exconly(excinfo, indent=indent, markall=True))
+ return lines
+
+ def get_exconly(self, excinfo, indent=4, markall=False):
+ lines = []
+ indent = " " * indent
+ # get the real exception information out
+ exlines = excinfo.exconly(tryshort=True).split('\n')
+ failindent = self.fail_marker + indent[1:]
+ for line in exlines:
+ lines.append(failindent + line)
+ if not markall:
+ failindent = indent
+ return lines
+
+ def repr_locals(self, locals):
+ if self.showlocals:
+ lines = []
+ keys = [loc for loc in locals if loc[0] != "@"]
+ keys.sort()
+ for name in keys:
+ value = locals[name]
+ if name == '__builtins__':
+ lines.append("__builtins__ = <builtins>")
+ else:
+ # This formatting could all be handled by the
+ # _repr() function, which is only reprlib.Repr in
+ # disguise, so is very configurable.
+ str_repr = self._saferepr(value)
+ # if len(str_repr) < 70 or not isinstance(value,
+ # (list, tuple, dict)):
+ lines.append("%-10s = %s" % (name, str_repr))
+ # else:
+ # self._line("%-10s =\\" % (name,))
+ # # XXX
+ # py.std.pprint.pprint(value, stream=self.excinfowriter)
+ return ReprLocals(lines)
+
+ def repr_traceback_entry(self, entry, excinfo=None):
+ import _pytest._code
+ source = self._getentrysource(entry)
+ if source is None:
+ source = _pytest._code.Source("???")
+ line_index = 0
+ else:
+ # entry.getfirstlinesource() can be -1, should be 0 on jython
+ line_index = entry.lineno - max(entry.getfirstlinesource(), 0)
+
+ lines = []
+ style = entry._repr_style
+ if style is None:
+ style = self.style
+ if style in ("short", "long"):
+ short = style == "short"
+ reprargs = self.repr_args(entry) if not short else None
+ s = self.get_source(source, line_index, excinfo, short=short)
+ lines.extend(s)
+ if short:
+ message = "in %s" % (entry.name)
+ else:
+ message = excinfo and excinfo.typename or ""
+ path = self._makepath(entry.path)
+ filelocrepr = ReprFileLocation(path, entry.lineno + 1, message)
+ localsrepr = None
+ if not short:
+ localsrepr = self.repr_locals(entry.locals)
+ return ReprEntry(lines, reprargs, localsrepr, filelocrepr, style)
+ if excinfo:
+ lines.extend(self.get_exconly(excinfo, indent=4))
+ return ReprEntry(lines, None, None, None, style)
+
+ def _makepath(self, path):
+ if not self.abspath:
+ try:
+ np = py.path.local().bestrelpath(path)
+ except OSError:
+ return path
+ if len(np) < len(str(path)):
+ path = np
+ return path
+
+ def repr_traceback(self, excinfo):
+ traceback = excinfo.traceback
+ if self.tbfilter:
+ traceback = traceback.filter()
+
+ if is_recursion_error(excinfo):
+ traceback, extraline = self._truncate_recursive_traceback(traceback)
+ else:
+ extraline = None
+
+ last = traceback[-1]
+ entries = []
+ for index, entry in enumerate(traceback):
+ einfo = (last == entry) and excinfo or None
+ reprentry = self.repr_traceback_entry(entry, einfo)
+ entries.append(reprentry)
+ return ReprTraceback(entries, extraline, style=self.style)
+
+ def _truncate_recursive_traceback(self, traceback):
+ """
+ Truncate the given recursive traceback trying to find the starting point
+ of the recursion.
+
+ The detection is done by going through each traceback entry and finding the
+ point in which the locals of the frame are equal to the locals of a previous frame (see ``recursionindex()``.
+
+ Handle the situation where the recursion process might raise an exception (for example
+ comparing numpy arrays using equality raises a TypeError), in which case we do our best to
+ warn the user of the error and show a limited traceback.
+ """
+ try:
+ recursionindex = traceback.recursionindex()
+ except Exception as e:
+ max_frames = 10
+ extraline = (
+ '!!! Recursion error detected, but an error occurred locating the origin of recursion.\n'
+ ' The following exception happened when comparing locals in the stack frame:\n'
+ ' {exc_type}: {exc_msg}\n'
+ ' Displaying first and last {max_frames} stack frames out of {total}.'
+ ).format(exc_type=type(e).__name__, exc_msg=safe_str(e), max_frames=max_frames, total=len(traceback))
+ traceback = traceback[:max_frames] + traceback[-max_frames:]
+ else:
+ if recursionindex is not None:
+ extraline = "!!! Recursion detected (same locals & position)"
+ traceback = traceback[:recursionindex + 1]
+ else:
+ extraline = None
+
+ return traceback, extraline
+
+ def repr_excinfo(self, excinfo):
+ if _PY2:
+ reprtraceback = self.repr_traceback(excinfo)
+ reprcrash = excinfo._getreprcrash()
+
+ return ReprExceptionInfo(reprtraceback, reprcrash)
+ else:
+ repr_chain = []
+ e = excinfo.value
+ descr = None
+ while e is not None:
+ if excinfo:
+ reprtraceback = self.repr_traceback(excinfo)
+ reprcrash = excinfo._getreprcrash()
+ else:
+ # fallback to native repr if the exception doesn't have a traceback:
+ # ExceptionInfo objects require a full traceback to work
+ reprtraceback = ReprTracebackNative(py.std.traceback.format_exception(type(e), e, None))
+ reprcrash = None
+
+ repr_chain += [(reprtraceback, reprcrash, descr)]
+ if e.__cause__ is not None:
+ e = e.__cause__
+ excinfo = ExceptionInfo((type(e), e, e.__traceback__)) if e.__traceback__ else None
+ descr = 'The above exception was the direct cause of the following exception:'
+ elif (e.__context__ is not None and not e.__suppress_context__):
+ e = e.__context__
+ excinfo = ExceptionInfo((type(e), e, e.__traceback__)) if e.__traceback__ else None
+ descr = 'During handling of the above exception, another exception occurred:'
+ else:
+ e = None
+ repr_chain.reverse()
+ return ExceptionChainRepr(repr_chain)
+
+
+class TerminalRepr(object):
+ def __str__(self):
+ s = self.__unicode__()
+ if _PY2:
+ s = s.encode('utf-8')
+ return s
+
+ def __unicode__(self):
+ # FYI this is called from pytest-xdist's serialization of exception
+ # information.
+ io = py.io.TextIO()
+ tw = py.io.TerminalWriter(file=io)
+ self.toterminal(tw)
+ return io.getvalue().strip()
+
+ def __repr__(self):
+ return "<%s instance at %0x>" % (self.__class__, id(self))
+
+
+class ExceptionRepr(TerminalRepr):
+ def __init__(self):
+ self.sections = []
+
+ def addsection(self, name, content, sep="-"):
+ self.sections.append((name, content, sep))
+
+ def toterminal(self, tw):
+ for name, content, sep in self.sections:
+ tw.sep(sep, name)
+ tw.line(content)
+
+
+class ExceptionChainRepr(ExceptionRepr):
+ def __init__(self, chain):
+ super(ExceptionChainRepr, self).__init__()
+ self.chain = chain
+ # reprcrash and reprtraceback of the outermost (the newest) exception
+ # in the chain
+ self.reprtraceback = chain[-1][0]
+ self.reprcrash = chain[-1][1]
+
+ def toterminal(self, tw):
+ for element in self.chain:
+ element[0].toterminal(tw)
+ if element[2] is not None:
+ tw.line("")
+ tw.line(element[2], yellow=True)
+ super(ExceptionChainRepr, self).toterminal(tw)
+
+
+class ReprExceptionInfo(ExceptionRepr):
+ def __init__(self, reprtraceback, reprcrash):
+ super(ReprExceptionInfo, self).__init__()
+ self.reprtraceback = reprtraceback
+ self.reprcrash = reprcrash
+
+ def toterminal(self, tw):
+ self.reprtraceback.toterminal(tw)
+ super(ReprExceptionInfo, self).toterminal(tw)
+
+
+class ReprTraceback(TerminalRepr):
+ entrysep = "_ "
+
+ def __init__(self, reprentries, extraline, style):
+ self.reprentries = reprentries
+ self.extraline = extraline
+ self.style = style
+
+ def toterminal(self, tw):
+ # the entries might have different styles
+ for i, entry in enumerate(self.reprentries):
+ if entry.style == "long":
+ tw.line("")
+ entry.toterminal(tw)
+ if i < len(self.reprentries) - 1:
+ next_entry = self.reprentries[i + 1]
+ if entry.style == "long" or \
+ entry.style == "short" and next_entry.style == "long":
+ tw.sep(self.entrysep)
+
+ if self.extraline:
+ tw.line(self.extraline)
+
+
+class ReprTracebackNative(ReprTraceback):
+ def __init__(self, tblines):
+ self.style = "native"
+ self.reprentries = [ReprEntryNative(tblines)]
+ self.extraline = None
+
+
+class ReprEntryNative(TerminalRepr):
+ style = "native"
+
+ def __init__(self, tblines):
+ self.lines = tblines
+
+ def toterminal(self, tw):
+ tw.write("".join(self.lines))
+
+
+class ReprEntry(TerminalRepr):
+ localssep = "_ "
+
+ def __init__(self, lines, reprfuncargs, reprlocals, filelocrepr, style):
+ self.lines = lines
+ self.reprfuncargs = reprfuncargs
+ self.reprlocals = reprlocals
+ self.reprfileloc = filelocrepr
+ self.style = style
+
+ def toterminal(self, tw):
+ if self.style == "short":
+ self.reprfileloc.toterminal(tw)
+ for line in self.lines:
+ red = line.startswith("E ")
+ tw.line(line, bold=True, red=red)
+ # tw.line("")
+ return
+ if self.reprfuncargs:
+ self.reprfuncargs.toterminal(tw)
+ for line in self.lines:
+ red = line.startswith("E ")
+ tw.line(line, bold=True, red=red)
+ if self.reprlocals:
+ # tw.sep(self.localssep, "Locals")
+ tw.line("")
+ self.reprlocals.toterminal(tw)
+ if self.reprfileloc:
+ if self.lines:
+ tw.line("")
+ self.reprfileloc.toterminal(tw)
+
+ def __str__(self):
+ return "%s\n%s\n%s" % ("\n".join(self.lines),
+ self.reprlocals,
+ self.reprfileloc)
+
+
+class ReprFileLocation(TerminalRepr):
+ def __init__(self, path, lineno, message):
+ self.path = str(path)
+ self.lineno = lineno
+ self.message = message
+
+ def toterminal(self, tw):
+ # filename and lineno output for each entry,
+ # using an output format that most editors unterstand
+ msg = self.message
+ i = msg.find("\n")
+ if i != -1:
+ msg = msg[:i]
+ tw.write(self.path, bold=True, red=True)
+ tw.line(":%s: %s" % (self.lineno, msg))
+
+
+class ReprLocals(TerminalRepr):
+ def __init__(self, lines):
+ self.lines = lines
+
+ def toterminal(self, tw):
+ for line in self.lines:
+ tw.line(line)
+
+
+class ReprFuncArgs(TerminalRepr):
+ def __init__(self, args):
+ self.args = args
+
+ def toterminal(self, tw):
+ if self.args:
+ linesofar = ""
+ for name, value in self.args:
+ ns = "%s = %s" % (safe_str(name), safe_str(value))
+ if len(ns) + len(linesofar) + 2 > tw.fullwidth:
+ if linesofar:
+ tw.line(linesofar)
+ linesofar = ns
+ else:
+ if linesofar:
+ linesofar += ", " + ns
+ else:
+ linesofar = ns
+ if linesofar:
+ tw.line(linesofar)
+ tw.line("")
+
+
+def getrawcode(obj, trycall=True):
+ """ return code object for given function. """
+ try:
+ return obj.__code__
+ except AttributeError:
+ obj = getattr(obj, 'im_func', obj)
+ obj = getattr(obj, 'func_code', obj)
+ obj = getattr(obj, 'f_code', obj)
+ obj = getattr(obj, '__code__', obj)
+ if trycall and not hasattr(obj, 'co_firstlineno'):
+ if hasattr(obj, '__call__') and not py.std.inspect.isclass(obj):
+ x = getrawcode(obj.__call__, trycall=False)
+ if hasattr(x, 'co_firstlineno'):
+ return x
+ return obj
+
+
+if PY35: # RecursionError introduced in 3.5
+ def is_recursion_error(excinfo):
+ return excinfo.errisinstance(RecursionError) # noqa
+else:
+ def is_recursion_error(excinfo):
+ if not excinfo.errisinstance(RuntimeError):
+ return False
+ try:
+ return "maximum recursion depth exceeded" in str(excinfo.value)
+ except UnicodeError:
+ return False
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/_code/source.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/_code/source.py
new file mode 100644
index 00000000000..2638c598b74
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/_code/source.py
@@ -0,0 +1,415 @@
+from __future__ import absolute_import, division, generators, print_function
+
+from bisect import bisect_right
+import sys
+import six
+import inspect
+import tokenize
+import py
+cpy_compile = compile
+
+try:
+ import _ast
+ from _ast import PyCF_ONLY_AST as _AST_FLAG
+except ImportError:
+ _AST_FLAG = 0
+ _ast = None
+
+
+class Source(object):
+ """ a immutable object holding a source code fragment,
+ possibly deindenting it.
+ """
+ _compilecounter = 0
+
+ def __init__(self, *parts, **kwargs):
+ self.lines = lines = []
+ de = kwargs.get('deindent', True)
+ rstrip = kwargs.get('rstrip', True)
+ for part in parts:
+ if not part:
+ partlines = []
+ if isinstance(part, Source):
+ partlines = part.lines
+ elif isinstance(part, (tuple, list)):
+ partlines = [x.rstrip("\n") for x in part]
+ elif isinstance(part, six.string_types):
+ partlines = part.split('\n')
+ if rstrip:
+ while partlines:
+ if partlines[-1].strip():
+ break
+ partlines.pop()
+ else:
+ partlines = getsource(part, deindent=de).lines
+ if de:
+ partlines = deindent(partlines)
+ lines.extend(partlines)
+
+ def __eq__(self, other):
+ try:
+ return self.lines == other.lines
+ except AttributeError:
+ if isinstance(other, str):
+ return str(self) == other
+ return False
+
+ __hash__ = None
+
+ def __getitem__(self, key):
+ if isinstance(key, int):
+ return self.lines[key]
+ else:
+ if key.step not in (None, 1):
+ raise IndexError("cannot slice a Source with a step")
+ newsource = Source()
+ newsource.lines = self.lines[key.start:key.stop]
+ return newsource
+
+ def __len__(self):
+ return len(self.lines)
+
+ def strip(self):
+ """ return new source object with trailing
+ and leading blank lines removed.
+ """
+ start, end = 0, len(self)
+ while start < end and not self.lines[start].strip():
+ start += 1
+ while end > start and not self.lines[end - 1].strip():
+ end -= 1
+ source = Source()
+ source.lines[:] = self.lines[start:end]
+ return source
+
+ def putaround(self, before='', after='', indent=' ' * 4):
+ """ return a copy of the source object with
+ 'before' and 'after' wrapped around it.
+ """
+ before = Source(before)
+ after = Source(after)
+ newsource = Source()
+ lines = [(indent + line) for line in self.lines]
+ newsource.lines = before.lines + lines + after.lines
+ return newsource
+
+ def indent(self, indent=' ' * 4):
+ """ return a copy of the source object with
+ all lines indented by the given indent-string.
+ """
+ newsource = Source()
+ newsource.lines = [(indent + line) for line in self.lines]
+ return newsource
+
+ def getstatement(self, lineno, assertion=False):
+ """ return Source statement which contains the
+ given linenumber (counted from 0).
+ """
+ start, end = self.getstatementrange(lineno, assertion)
+ return self[start:end]
+
+ def getstatementrange(self, lineno, assertion=False):
+ """ return (start, end) tuple which spans the minimal
+ statement region which containing the given lineno.
+ """
+ if not (0 <= lineno < len(self)):
+ raise IndexError("lineno out of range")
+ ast, start, end = getstatementrange_ast(lineno, self)
+ return start, end
+
+ def deindent(self, offset=None):
+ """ return a new source object deindented by offset.
+ If offset is None then guess an indentation offset from
+ the first non-blank line. Subsequent lines which have a
+ lower indentation offset will be copied verbatim as
+ they are assumed to be part of multilines.
+ """
+ # XXX maybe use the tokenizer to properly handle multiline
+ # strings etc.pp?
+ newsource = Source()
+ newsource.lines[:] = deindent(self.lines, offset)
+ return newsource
+
+ def isparseable(self, deindent=True):
+ """ return True if source is parseable, heuristically
+ deindenting it by default.
+ """
+ try:
+ import parser
+ except ImportError:
+ def syntax_checker(x):
+ return compile(x, 'asd', 'exec')
+ else:
+ syntax_checker = parser.suite
+
+ if deindent:
+ source = str(self.deindent())
+ else:
+ source = str(self)
+ try:
+ # compile(source+'\n', "x", "exec")
+ syntax_checker(source + '\n')
+ except KeyboardInterrupt:
+ raise
+ except Exception:
+ return False
+ else:
+ return True
+
+ def __str__(self):
+ return "\n".join(self.lines)
+
+ def compile(self, filename=None, mode='exec',
+ flag=generators.compiler_flag,
+ dont_inherit=0, _genframe=None):
+ """ return compiled code object. if filename is None
+ invent an artificial filename which displays
+ the source/line position of the caller frame.
+ """
+ if not filename or py.path.local(filename).check(file=0):
+ if _genframe is None:
+ _genframe = sys._getframe(1) # the caller
+ fn, lineno = _genframe.f_code.co_filename, _genframe.f_lineno
+ base = "<%d-codegen " % self._compilecounter
+ self.__class__._compilecounter += 1
+ if not filename:
+ filename = base + '%s:%d>' % (fn, lineno)
+ else:
+ filename = base + '%r %s:%d>' % (filename, fn, lineno)
+ source = "\n".join(self.lines) + '\n'
+ try:
+ co = cpy_compile(source, filename, mode, flag)
+ except SyntaxError:
+ ex = sys.exc_info()[1]
+ # re-represent syntax errors from parsing python strings
+ msglines = self.lines[:ex.lineno]
+ if ex.offset:
+ msglines.append(" " * ex.offset + '^')
+ msglines.append("(code was compiled probably from here: %s)" % filename)
+ newex = SyntaxError('\n'.join(msglines))
+ newex.offset = ex.offset
+ newex.lineno = ex.lineno
+ newex.text = ex.text
+ raise newex
+ else:
+ if flag & _AST_FLAG:
+ return co
+ lines = [(x + "\n") for x in self.lines]
+ py.std.linecache.cache[filename] = (1, None, lines, filename)
+ return co
+
+#
+# public API shortcut functions
+#
+
+
+def compile_(source, filename=None, mode='exec', flags=generators.compiler_flag, dont_inherit=0):
+ """ compile the given source to a raw code object,
+ and maintain an internal cache which allows later
+ retrieval of the source code for the code object
+ and any recursively created code objects.
+ """
+ if _ast is not None and isinstance(source, _ast.AST):
+ # XXX should Source support having AST?
+ return cpy_compile(source, filename, mode, flags, dont_inherit)
+ _genframe = sys._getframe(1) # the caller
+ s = Source(source)
+ co = s.compile(filename, mode, flags, _genframe=_genframe)
+ return co
+
+
+def getfslineno(obj):
+ """ Return source location (path, lineno) for the given object.
+ If the source cannot be determined return ("", -1)
+ """
+ import _pytest._code
+ try:
+ code = _pytest._code.Code(obj)
+ except TypeError:
+ try:
+ fn = (py.std.inspect.getsourcefile(obj) or
+ py.std.inspect.getfile(obj))
+ except TypeError:
+ return "", -1
+
+ fspath = fn and py.path.local(fn) or None
+ lineno = -1
+ if fspath:
+ try:
+ _, lineno = findsource(obj)
+ except IOError:
+ pass
+ else:
+ fspath = code.path
+ lineno = code.firstlineno
+ assert isinstance(lineno, int)
+ return fspath, lineno
+
+#
+# helper functions
+#
+
+
+def findsource(obj):
+ try:
+ sourcelines, lineno = py.std.inspect.findsource(obj)
+ except py.builtin._sysex:
+ raise
+ except: # noqa
+ return None, -1
+ source = Source()
+ source.lines = [line.rstrip() for line in sourcelines]
+ return source, lineno
+
+
+def getsource(obj, **kwargs):
+ import _pytest._code
+ obj = _pytest._code.getrawcode(obj)
+ try:
+ strsrc = inspect.getsource(obj)
+ except IndentationError:
+ strsrc = "\"Buggy python version consider upgrading, cannot get source\""
+ assert isinstance(strsrc, str)
+ return Source(strsrc, **kwargs)
+
+
+def deindent(lines, offset=None):
+ if offset is None:
+ for line in lines:
+ line = line.expandtabs()
+ s = line.lstrip()
+ if s:
+ offset = len(line) - len(s)
+ break
+ else:
+ offset = 0
+ if offset == 0:
+ return list(lines)
+ newlines = []
+
+ def readline_generator(lines):
+ for line in lines:
+ yield line + '\n'
+ while True:
+ yield ''
+
+ it = readline_generator(lines)
+
+ try:
+ for _, _, (sline, _), (eline, _), _ in tokenize.generate_tokens(lambda: next(it)):
+ if sline > len(lines):
+ break # End of input reached
+ if sline > len(newlines):
+ line = lines[sline - 1].expandtabs()
+ if line.lstrip() and line[:offset].isspace():
+ line = line[offset:] # Deindent
+ newlines.append(line)
+
+ for i in range(sline, eline):
+ # Don't deindent continuing lines of
+ # multiline tokens (i.e. multiline strings)
+ newlines.append(lines[i])
+ except (IndentationError, tokenize.TokenError):
+ pass
+ # Add any lines we didn't see. E.g. if an exception was raised.
+ newlines.extend(lines[len(newlines):])
+ return newlines
+
+
+def get_statement_startend2(lineno, node):
+ import ast
+ # flatten all statements and except handlers into one lineno-list
+ # AST's line numbers start indexing at 1
+ values = []
+ for x in ast.walk(node):
+ if isinstance(x, _ast.stmt) or isinstance(x, _ast.ExceptHandler):
+ values.append(x.lineno - 1)
+ for name in "finalbody", "orelse":
+ val = getattr(x, name, None)
+ if val:
+ # treat the finally/orelse part as its own statement
+ values.append(val[0].lineno - 1 - 1)
+ values.sort()
+ insert_index = bisect_right(values, lineno)
+ start = values[insert_index - 1]
+ if insert_index >= len(values):
+ end = None
+ else:
+ end = values[insert_index]
+ return start, end
+
+
+def getstatementrange_ast(lineno, source, assertion=False, astnode=None):
+ if astnode is None:
+ content = str(source)
+ try:
+ astnode = compile(content, "source", "exec", 1024) # 1024 for AST
+ except ValueError:
+ start, end = getstatementrange_old(lineno, source, assertion)
+ return None, start, end
+ start, end = get_statement_startend2(lineno, astnode)
+ # we need to correct the end:
+ # - ast-parsing strips comments
+ # - there might be empty lines
+ # - we might have lesser indented code blocks at the end
+ if end is None:
+ end = len(source.lines)
+
+ if end > start + 1:
+ # make sure we don't span differently indented code blocks
+ # by using the BlockFinder helper used which inspect.getsource() uses itself
+ block_finder = inspect.BlockFinder()
+ # if we start with an indented line, put blockfinder to "started" mode
+ block_finder.started = source.lines[start][0].isspace()
+ it = ((x + "\n") for x in source.lines[start:end])
+ try:
+ for tok in tokenize.generate_tokens(lambda: next(it)):
+ block_finder.tokeneater(*tok)
+ except (inspect.EndOfBlock, IndentationError):
+ end = block_finder.last + start
+ except Exception:
+ pass
+
+ # the end might still point to a comment or empty line, correct it
+ while end:
+ line = source.lines[end - 1].lstrip()
+ if line.startswith("#") or not line:
+ end -= 1
+ else:
+ break
+ return astnode, start, end
+
+
+def getstatementrange_old(lineno, source, assertion=False):
+ """ return (start, end) tuple which spans the minimal
+ statement region which containing the given lineno.
+ raise an IndexError if no such statementrange can be found.
+ """
+ # XXX this logic is only used on python2.4 and below
+ # 1. find the start of the statement
+ from codeop import compile_command
+ for start in range(lineno, -1, -1):
+ if assertion:
+ line = source.lines[start]
+ # the following lines are not fully tested, change with care
+ if 'super' in line and 'self' in line and '__init__' in line:
+ raise IndexError("likely a subclass")
+ if "assert" not in line and "raise" not in line:
+ continue
+ trylines = source.lines[start:lineno + 1]
+ # quick hack to prepare parsing an indented line with
+ # compile_command() (which errors on "return" outside defs)
+ trylines.insert(0, 'def xxx():')
+ trysource = '\n '.join(trylines)
+ # ^ space here
+ try:
+ compile_command(trysource)
+ except (SyntaxError, OverflowError, ValueError):
+ continue
+
+ # 2. find the end of the statement
+ for end in range(lineno + 1, len(source) + 1):
+ trysource = source[start:end]
+ if trysource.isparseable():
+ return start, end
+ raise SyntaxError("no valid source range around line %d " % (lineno,))
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/assertion/__init__.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/assertion/__init__.py
new file mode 100644
index 00000000000..a48e98c85aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/assertion/__init__.py
@@ -0,0 +1,146 @@
+"""
+support for presenting detailed information in failing assertions.
+"""
+from __future__ import absolute_import, division, print_function
+import sys
+import six
+
+from _pytest.assertion import util
+from _pytest.assertion import rewrite
+from _pytest.assertion import truncate
+
+
+def pytest_addoption(parser):
+ group = parser.getgroup("debugconfig")
+ group.addoption('--assert',
+ action="store",
+ dest="assertmode",
+ choices=("rewrite", "plain",),
+ default="rewrite",
+ metavar="MODE",
+ help="""Control assertion debugging tools. 'plain'
+ performs no assertion debugging. 'rewrite'
+ (the default) rewrites assert statements in
+ test modules on import to provide assert
+ expression information.""")
+
+
+def register_assert_rewrite(*names):
+ """Register one or more module names to be rewritten on import.
+
+ This function will make sure that this module or all modules inside
+ the package will get their assert statements rewritten.
+ Thus you should make sure to call this before the module is
+ actually imported, usually in your __init__.py if you are a plugin
+ using a package.
+
+ :raise TypeError: if the given module names are not strings.
+ """
+ for name in names:
+ if not isinstance(name, str):
+ msg = 'expected module names as *args, got {0} instead'
+ raise TypeError(msg.format(repr(names)))
+ for hook in sys.meta_path:
+ if isinstance(hook, rewrite.AssertionRewritingHook):
+ importhook = hook
+ break
+ else:
+ importhook = DummyRewriteHook()
+ importhook.mark_rewrite(*names)
+
+
+class DummyRewriteHook(object):
+ """A no-op import hook for when rewriting is disabled."""
+
+ def mark_rewrite(self, *names):
+ pass
+
+
+class AssertionState:
+ """State for the assertion plugin."""
+
+ def __init__(self, config, mode):
+ self.mode = mode
+ self.trace = config.trace.root.get("assertion")
+ self.hook = None
+
+
+def install_importhook(config):
+ """Try to install the rewrite hook, raise SystemError if it fails."""
+ # Jython has an AST bug that make the assertion rewriting hook malfunction.
+ if (sys.platform.startswith('java')):
+ raise SystemError('rewrite not supported')
+
+ config._assertstate = AssertionState(config, 'rewrite')
+ config._assertstate.hook = hook = rewrite.AssertionRewritingHook(config)
+ sys.meta_path.insert(0, hook)
+ config._assertstate.trace('installed rewrite import hook')
+
+ def undo():
+ hook = config._assertstate.hook
+ if hook is not None and hook in sys.meta_path:
+ sys.meta_path.remove(hook)
+
+ config.add_cleanup(undo)
+ return hook
+
+
+def pytest_collection(session):
+ # this hook is only called when test modules are collected
+ # so for example not in the master process of pytest-xdist
+ # (which does not collect test modules)
+ assertstate = getattr(session.config, '_assertstate', None)
+ if assertstate:
+ if assertstate.hook is not None:
+ assertstate.hook.set_session(session)
+
+
+def pytest_runtest_setup(item):
+ """Setup the pytest_assertrepr_compare hook
+
+ The newinterpret and rewrite modules will use util._reprcompare if
+ it exists to use custom reporting via the
+ pytest_assertrepr_compare hook. This sets up this custom
+ comparison for the test.
+ """
+ def callbinrepr(op, left, right):
+ """Call the pytest_assertrepr_compare hook and prepare the result
+
+ This uses the first result from the hook and then ensures the
+ following:
+ * Overly verbose explanations are truncated unless configured otherwise
+ (eg. if running in verbose mode).
+ * Embedded newlines are escaped to help util.format_explanation()
+ later.
+ * If the rewrite mode is used embedded %-characters are replaced
+ to protect later % formatting.
+
+ The result can be formatted by util.format_explanation() for
+ pretty printing.
+ """
+ hook_result = item.ihook.pytest_assertrepr_compare(
+ config=item.config, op=op, left=left, right=right)
+ for new_expl in hook_result:
+ if new_expl:
+ new_expl = truncate.truncate_if_required(new_expl, item)
+ new_expl = [line.replace("\n", "\\n") for line in new_expl]
+ res = six.text_type("\n~").join(new_expl)
+ if item.config.getvalue("assertmode") == "rewrite":
+ res = res.replace("%", "%%")
+ return res
+ util._reprcompare = callbinrepr
+
+
+def pytest_runtest_teardown(item):
+ util._reprcompare = None
+
+
+def pytest_sessionfinish(session):
+ assertstate = getattr(session.config, '_assertstate', None)
+ if assertstate:
+ if assertstate.hook is not None:
+ assertstate.hook.set_session(None)
+
+
+# Expose this plugin's implementation for the pytest_assertrepr_compare hook
+pytest_assertrepr_compare = util.assertrepr_compare
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/assertion/rewrite.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/assertion/rewrite.py
new file mode 100644
index 00000000000..f64358f490b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/assertion/rewrite.py
@@ -0,0 +1,948 @@
+"""Rewrite assertion AST to produce nice error messages"""
+from __future__ import absolute_import, division, print_function
+import ast
+import _ast
+import errno
+import itertools
+import imp
+import marshal
+import os
+import re
+import six
+import struct
+import sys
+import types
+
+import py
+from _pytest.assertion import util
+
+
+# pytest caches rewritten pycs in __pycache__.
+if hasattr(imp, "get_tag"):
+ PYTEST_TAG = imp.get_tag() + "-PYTEST"
+else:
+ if hasattr(sys, "pypy_version_info"):
+ impl = "pypy"
+ elif sys.platform == "java":
+ impl = "jython"
+ else:
+ impl = "cpython"
+ ver = sys.version_info
+ PYTEST_TAG = "%s-%s%s-PYTEST" % (impl, ver[0], ver[1])
+ del ver, impl
+
+PYC_EXT = ".py" + (__debug__ and "c" or "o")
+PYC_TAIL = "." + PYTEST_TAG + PYC_EXT
+
+ASCII_IS_DEFAULT_ENCODING = sys.version_info[0] < 3
+
+if sys.version_info >= (3, 5):
+ ast_Call = ast.Call
+else:
+ def ast_Call(a, b, c):
+ return ast.Call(a, b, c, None, None)
+
+
+class AssertionRewritingHook(object):
+ """PEP302 Import hook which rewrites asserts."""
+
+ def __init__(self, config):
+ self.config = config
+ self.fnpats = config.getini("python_files")
+ self.session = None
+ self.modules = {}
+ self._rewritten_names = set()
+ self._register_with_pkg_resources()
+ self._must_rewrite = set()
+
+ def set_session(self, session):
+ self.session = session
+
+ def find_module(self, name, path=None):
+ state = self.config._assertstate
+ state.trace("find_module called for: %s" % name)
+ names = name.rsplit(".", 1)
+ lastname = names[-1]
+ pth = None
+ if path is not None:
+ # Starting with Python 3.3, path is a _NamespacePath(), which
+ # causes problems if not converted to list.
+ path = list(path)
+ if len(path) == 1:
+ pth = path[0]
+ if pth is None:
+ try:
+ fd, fn, desc = imp.find_module(lastname, path)
+ except ImportError:
+ return None
+ if fd is not None:
+ fd.close()
+ tp = desc[2]
+ if tp == imp.PY_COMPILED:
+ if hasattr(imp, "source_from_cache"):
+ try:
+ fn = imp.source_from_cache(fn)
+ except ValueError:
+ # Python 3 doesn't like orphaned but still-importable
+ # .pyc files.
+ fn = fn[:-1]
+ else:
+ fn = fn[:-1]
+ elif tp != imp.PY_SOURCE:
+ # Don't know what this is.
+ return None
+ else:
+ fn = os.path.join(pth, name.rpartition(".")[2] + ".py")
+
+ fn_pypath = py.path.local(fn)
+ if not self._should_rewrite(name, fn_pypath, state):
+ return None
+
+ self._rewritten_names.add(name)
+
+ # The requested module looks like a test file, so rewrite it. This is
+ # the most magical part of the process: load the source, rewrite the
+ # asserts, and load the rewritten source. We also cache the rewritten
+ # module code in a special pyc. We must be aware of the possibility of
+ # concurrent pytest processes rewriting and loading pycs. To avoid
+ # tricky race conditions, we maintain the following invariant: The
+ # cached pyc is always a complete, valid pyc. Operations on it must be
+ # atomic. POSIX's atomic rename comes in handy.
+ write = not sys.dont_write_bytecode
+ cache_dir = os.path.join(fn_pypath.dirname, "__pycache__")
+ if write:
+ try:
+ os.mkdir(cache_dir)
+ except OSError:
+ e = sys.exc_info()[1].errno
+ if e == errno.EEXIST:
+ # Either the __pycache__ directory already exists (the
+ # common case) or it's blocked by a non-dir node. In the
+ # latter case, we'll ignore it in _write_pyc.
+ pass
+ elif e in [errno.ENOENT, errno.ENOTDIR]:
+ # One of the path components was not a directory, likely
+ # because we're in a zip file.
+ write = False
+ elif e in [errno.EACCES, errno.EROFS, errno.EPERM]:
+ state.trace("read only directory: %r" % fn_pypath.dirname)
+ write = False
+ else:
+ raise
+ cache_name = fn_pypath.basename[:-3] + PYC_TAIL
+ pyc = os.path.join(cache_dir, cache_name)
+ # Notice that even if we're in a read-only directory, I'm going
+ # to check for a cached pyc. This may not be optimal...
+ co = _read_pyc(fn_pypath, pyc, state.trace)
+ if co is None:
+ state.trace("rewriting %r" % (fn,))
+ source_stat, co = _rewrite_test(self.config, fn_pypath)
+ if co is None:
+ # Probably a SyntaxError in the test.
+ return None
+ if write:
+ _make_rewritten_pyc(state, source_stat, pyc, co)
+ else:
+ state.trace("found cached rewritten pyc for %r" % (fn,))
+ self.modules[name] = co, pyc
+ return self
+
+ def _should_rewrite(self, name, fn_pypath, state):
+ # always rewrite conftest files
+ fn = str(fn_pypath)
+ if fn_pypath.basename == 'conftest.py':
+ state.trace("rewriting conftest file: %r" % (fn,))
+ return True
+
+ if self.session is not None:
+ if self.session.isinitpath(fn):
+ state.trace("matched test file (was specified on cmdline): %r" %
+ (fn,))
+ return True
+
+ # modules not passed explicitly on the command line are only
+ # rewritten if they match the naming convention for test files
+ for pat in self.fnpats:
+ if fn_pypath.fnmatch(pat):
+ state.trace("matched test file %r" % (fn,))
+ return True
+
+ for marked in self._must_rewrite:
+ if name == marked or name.startswith(marked + '.'):
+ state.trace("matched marked file %r (from %r)" % (name, marked))
+ return True
+
+ return False
+
+ def mark_rewrite(self, *names):
+ """Mark import names as needing to be rewritten.
+
+ The named module or package as well as any nested modules will
+ be rewritten on import.
+ """
+ already_imported = set(names).intersection(set(sys.modules))
+ if already_imported:
+ for name in already_imported:
+ if name not in self._rewritten_names:
+ self._warn_already_imported(name)
+ self._must_rewrite.update(names)
+
+ def _warn_already_imported(self, name):
+ self.config.warn(
+ 'P1',
+ 'Module already imported so cannot be rewritten: %s' % name)
+
+ def load_module(self, name):
+ # If there is an existing module object named 'fullname' in
+ # sys.modules, the loader must use that existing module. (Otherwise,
+ # the reload() builtin will not work correctly.)
+ if name in sys.modules:
+ return sys.modules[name]
+
+ co, pyc = self.modules.pop(name)
+ # I wish I could just call imp.load_compiled here, but __file__ has to
+ # be set properly. In Python 3.2+, this all would be handled correctly
+ # by load_compiled.
+ mod = sys.modules[name] = imp.new_module(name)
+ try:
+ mod.__file__ = co.co_filename
+ # Normally, this attribute is 3.2+.
+ mod.__cached__ = pyc
+ mod.__loader__ = self
+ py.builtin.exec_(co, mod.__dict__)
+ except: # noqa
+ if name in sys.modules:
+ del sys.modules[name]
+ raise
+ return sys.modules[name]
+
+ def is_package(self, name):
+ try:
+ fd, fn, desc = imp.find_module(name)
+ except ImportError:
+ return False
+ if fd is not None:
+ fd.close()
+ tp = desc[2]
+ return tp == imp.PKG_DIRECTORY
+
+ @classmethod
+ def _register_with_pkg_resources(cls):
+ """
+ Ensure package resources can be loaded from this loader. May be called
+ multiple times, as the operation is idempotent.
+ """
+ try:
+ import pkg_resources
+ # access an attribute in case a deferred importer is present
+ pkg_resources.__name__
+ except ImportError:
+ return
+
+ # Since pytest tests are always located in the file system, the
+ # DefaultProvider is appropriate.
+ pkg_resources.register_loader_type(cls, pkg_resources.DefaultProvider)
+
+ def get_data(self, pathname):
+ """Optional PEP302 get_data API.
+ """
+ with open(pathname, 'rb') as f:
+ return f.read()
+
+
+def _write_pyc(state, co, source_stat, pyc):
+ # Technically, we don't have to have the same pyc format as
+ # (C)Python, since these "pycs" should never be seen by builtin
+ # import. However, there's little reason deviate, and I hope
+ # sometime to be able to use imp.load_compiled to load them. (See
+ # the comment in load_module above.)
+ try:
+ fp = open(pyc, "wb")
+ except IOError:
+ err = sys.exc_info()[1].errno
+ state.trace("error writing pyc file at %s: errno=%s" % (pyc, err))
+ # we ignore any failure to write the cache file
+ # there are many reasons, permission-denied, __pycache__ being a
+ # file etc.
+ return False
+ try:
+ fp.write(imp.get_magic())
+ mtime = int(source_stat.mtime)
+ size = source_stat.size & 0xFFFFFFFF
+ fp.write(struct.pack("<ll", mtime, size))
+ marshal.dump(co, fp)
+ finally:
+ fp.close()
+ return True
+
+
+RN = "\r\n".encode("utf-8")
+N = "\n".encode("utf-8")
+
+cookie_re = re.compile(r"^[ \t\f]*#.*coding[:=][ \t]*[-\w.]+")
+BOM_UTF8 = '\xef\xbb\xbf'
+
+
+def _rewrite_test(config, fn):
+ """Try to read and rewrite *fn* and return the code object."""
+ state = config._assertstate
+ try:
+ stat = fn.stat()
+ source = fn.read("rb")
+ except EnvironmentError:
+ return None, None
+ if ASCII_IS_DEFAULT_ENCODING:
+ # ASCII is the default encoding in Python 2. Without a coding
+ # declaration, Python 2 will complain about any bytes in the file
+ # outside the ASCII range. Sadly, this behavior does not extend to
+ # compile() or ast.parse(), which prefer to interpret the bytes as
+ # latin-1. (At least they properly handle explicit coding cookies.) To
+ # preserve this error behavior, we could force ast.parse() to use ASCII
+ # as the encoding by inserting a coding cookie. Unfortunately, that
+ # messes up line numbers. Thus, we have to check ourselves if anything
+ # is outside the ASCII range in the case no encoding is explicitly
+ # declared. For more context, see issue #269. Yay for Python 3 which
+ # gets this right.
+ end1 = source.find("\n")
+ end2 = source.find("\n", end1 + 1)
+ if (not source.startswith(BOM_UTF8) and
+ cookie_re.match(source[0:end1]) is None and
+ cookie_re.match(source[end1 + 1:end2]) is None):
+ if hasattr(state, "_indecode"):
+ # encodings imported us again, so don't rewrite.
+ return None, None
+ state._indecode = True
+ try:
+ try:
+ source.decode("ascii")
+ except UnicodeDecodeError:
+ # Let it fail in real import.
+ return None, None
+ finally:
+ del state._indecode
+ try:
+ tree = ast.parse(source)
+ except SyntaxError:
+ # Let this pop up again in the real import.
+ state.trace("failed to parse: %r" % (fn,))
+ return None, None
+ rewrite_asserts(tree, fn, config)
+ try:
+ co = compile(tree, fn.strpath, "exec", dont_inherit=True)
+ except SyntaxError:
+ # It's possible that this error is from some bug in the
+ # assertion rewriting, but I don't know of a fast way to tell.
+ state.trace("failed to compile: %r" % (fn,))
+ return None, None
+ return stat, co
+
+
+def _make_rewritten_pyc(state, source_stat, pyc, co):
+ """Try to dump rewritten code to *pyc*."""
+ if sys.platform.startswith("win"):
+ # Windows grants exclusive access to open files and doesn't have atomic
+ # rename, so just write into the final file.
+ _write_pyc(state, co, source_stat, pyc)
+ else:
+ # When not on windows, assume rename is atomic. Dump the code object
+ # into a file specific to this process and atomically replace it.
+ proc_pyc = pyc + "." + str(os.getpid())
+ if _write_pyc(state, co, source_stat, proc_pyc):
+ os.rename(proc_pyc, pyc)
+
+
+def _read_pyc(source, pyc, trace=lambda x: None):
+ """Possibly read a pytest pyc containing rewritten code.
+
+ Return rewritten code if successful or None if not.
+ """
+ try:
+ fp = open(pyc, "rb")
+ except IOError:
+ return None
+ with fp:
+ try:
+ mtime = int(source.mtime())
+ size = source.size()
+ data = fp.read(12)
+ except EnvironmentError as e:
+ trace('_read_pyc(%s): EnvironmentError %s' % (source, e))
+ return None
+ # Check for invalid or out of date pyc file.
+ if (len(data) != 12 or data[:4] != imp.get_magic() or
+ struct.unpack("<ll", data[4:]) != (mtime, size)):
+ trace('_read_pyc(%s): invalid or out of date pyc' % source)
+ return None
+ try:
+ co = marshal.load(fp)
+ except Exception as e:
+ trace('_read_pyc(%s): marshal.load error %s' % (source, e))
+ return None
+ if not isinstance(co, types.CodeType):
+ trace('_read_pyc(%s): not a code object' % source)
+ return None
+ return co
+
+
+def rewrite_asserts(mod, module_path=None, config=None):
+ """Rewrite the assert statements in mod."""
+ AssertionRewriter(module_path, config).run(mod)
+
+
+def _saferepr(obj):
+ """Get a safe repr of an object for assertion error messages.
+
+ The assertion formatting (util.format_explanation()) requires
+ newlines to be escaped since they are a special character for it.
+ Normally assertion.util.format_explanation() does this but for a
+ custom repr it is possible to contain one of the special escape
+ sequences, especially '\n{' and '\n}' are likely to be present in
+ JSON reprs.
+
+ """
+ repr = py.io.saferepr(obj)
+ if isinstance(repr, six.text_type):
+ t = six.text_type
+ else:
+ t = six.binary_type
+ return repr.replace(t("\n"), t("\\n"))
+
+
+from _pytest.assertion.util import format_explanation as _format_explanation # noqa
+
+
+def _format_assertmsg(obj):
+ """Format the custom assertion message given.
+
+ For strings this simply replaces newlines with '\n~' so that
+ util.format_explanation() will preserve them instead of escaping
+ newlines. For other objects py.io.saferepr() is used first.
+
+ """
+ # reprlib appears to have a bug which means that if a string
+ # contains a newline it gets escaped, however if an object has a
+ # .__repr__() which contains newlines it does not get escaped.
+ # However in either case we want to preserve the newline.
+ if isinstance(obj, six.text_type) or isinstance(obj, six.binary_type):
+ s = obj
+ is_repr = False
+ else:
+ s = py.io.saferepr(obj)
+ is_repr = True
+ if isinstance(s, six.text_type):
+ t = six.text_type
+ else:
+ t = six.binary_type
+ s = s.replace(t("\n"), t("\n~")).replace(t("%"), t("%%"))
+ if is_repr:
+ s = s.replace(t("\\n"), t("\n~"))
+ return s
+
+
+def _should_repr_global_name(obj):
+ return not hasattr(obj, "__name__") and not callable(obj)
+
+
+def _format_boolop(explanations, is_or):
+ explanation = "(" + (is_or and " or " or " and ").join(explanations) + ")"
+ if isinstance(explanation, six.text_type):
+ t = six.text_type
+ else:
+ t = six.binary_type
+ return explanation.replace(t('%'), t('%%'))
+
+
+def _call_reprcompare(ops, results, expls, each_obj):
+ for i, res, expl in zip(range(len(ops)), results, expls):
+ try:
+ done = not res
+ except Exception:
+ done = True
+ if done:
+ break
+ if util._reprcompare is not None:
+ custom = util._reprcompare(ops[i], each_obj[i], each_obj[i + 1])
+ if custom is not None:
+ return custom
+ return expl
+
+
+unary_map = {
+ ast.Not: "not %s",
+ ast.Invert: "~%s",
+ ast.USub: "-%s",
+ ast.UAdd: "+%s"
+}
+
+binop_map = {
+ ast.BitOr: "|",
+ ast.BitXor: "^",
+ ast.BitAnd: "&",
+ ast.LShift: "<<",
+ ast.RShift: ">>",
+ ast.Add: "+",
+ ast.Sub: "-",
+ ast.Mult: "*",
+ ast.Div: "/",
+ ast.FloorDiv: "//",
+ ast.Mod: "%%", # escaped for string formatting
+ ast.Eq: "==",
+ ast.NotEq: "!=",
+ ast.Lt: "<",
+ ast.LtE: "<=",
+ ast.Gt: ">",
+ ast.GtE: ">=",
+ ast.Pow: "**",
+ ast.Is: "is",
+ ast.IsNot: "is not",
+ ast.In: "in",
+ ast.NotIn: "not in"
+}
+# Python 3.5+ compatibility
+try:
+ binop_map[ast.MatMult] = "@"
+except AttributeError:
+ pass
+
+# Python 3.4+ compatibility
+if hasattr(ast, "NameConstant"):
+ _NameConstant = ast.NameConstant
+else:
+ def _NameConstant(c):
+ return ast.Name(str(c), ast.Load())
+
+
+def set_location(node, lineno, col_offset):
+ """Set node location information recursively."""
+ def _fix(node, lineno, col_offset):
+ if "lineno" in node._attributes:
+ node.lineno = lineno
+ if "col_offset" in node._attributes:
+ node.col_offset = col_offset
+ for child in ast.iter_child_nodes(node):
+ _fix(child, lineno, col_offset)
+ _fix(node, lineno, col_offset)
+ return node
+
+
+class AssertionRewriter(ast.NodeVisitor):
+ """Assertion rewriting implementation.
+
+ The main entrypoint is to call .run() with an ast.Module instance,
+ this will then find all the assert statements and rewrite them to
+ provide intermediate values and a detailed assertion error. See
+ http://pybites.blogspot.be/2011/07/behind-scenes-of-pytests-new-assertion.html
+ for an overview of how this works.
+
+ The entry point here is .run() which will iterate over all the
+ statements in an ast.Module and for each ast.Assert statement it
+ finds call .visit() with it. Then .visit_Assert() takes over and
+ is responsible for creating new ast statements to replace the
+ original assert statement: it rewrites the test of an assertion
+ to provide intermediate values and replace it with an if statement
+ which raises an assertion error with a detailed explanation in
+ case the expression is false.
+
+ For this .visit_Assert() uses the visitor pattern to visit all the
+ AST nodes of the ast.Assert.test field, each visit call returning
+ an AST node and the corresponding explanation string. During this
+ state is kept in several instance attributes:
+
+ :statements: All the AST statements which will replace the assert
+ statement.
+
+ :variables: This is populated by .variable() with each variable
+ used by the statements so that they can all be set to None at
+ the end of the statements.
+
+ :variable_counter: Counter to create new unique variables needed
+ by statements. Variables are created using .variable() and
+ have the form of "@py_assert0".
+
+ :on_failure: The AST statements which will be executed if the
+ assertion test fails. This is the code which will construct
+ the failure message and raises the AssertionError.
+
+ :explanation_specifiers: A dict filled by .explanation_param()
+ with %-formatting placeholders and their corresponding
+ expressions to use in the building of an assertion message.
+ This is used by .pop_format_context() to build a message.
+
+ :stack: A stack of the explanation_specifiers dicts maintained by
+ .push_format_context() and .pop_format_context() which allows
+ to build another %-formatted string while already building one.
+
+ This state is reset on every new assert statement visited and used
+ by the other visitors.
+
+ """
+
+ def __init__(self, module_path, config):
+ super(AssertionRewriter, self).__init__()
+ self.module_path = module_path
+ self.config = config
+
+ def run(self, mod):
+ """Find all assert statements in *mod* and rewrite them."""
+ if not mod.body:
+ # Nothing to do.
+ return
+ # Insert some special imports at the top of the module but after any
+ # docstrings and __future__ imports.
+ aliases = [ast.alias(py.builtin.builtins.__name__, "@py_builtins"),
+ ast.alias("_pytest.assertion.rewrite", "@pytest_ar")]
+ doc = getattr(mod, "docstring", None)
+ expect_docstring = doc is None
+ if doc is not None and self.is_rewrite_disabled(doc):
+ return
+ pos = 0
+ lineno = 1
+ for item in mod.body:
+ if (expect_docstring and isinstance(item, ast.Expr) and
+ isinstance(item.value, ast.Str)):
+ doc = item.value.s
+ if self.is_rewrite_disabled(doc):
+ return
+ expect_docstring = False
+ elif (not isinstance(item, ast.ImportFrom) or item.level > 0 or
+ item.module != "__future__"):
+ lineno = item.lineno
+ break
+ pos += 1
+ else:
+ lineno = item.lineno
+ imports = [ast.Import([alias], lineno=lineno, col_offset=0)
+ for alias in aliases]
+ mod.body[pos:pos] = imports
+ # Collect asserts.
+ nodes = [mod]
+ while nodes:
+ node = nodes.pop()
+ for name, field in ast.iter_fields(node):
+ if isinstance(field, list):
+ new = []
+ for i, child in enumerate(field):
+ if isinstance(child, ast.Assert):
+ # Transform assert.
+ new.extend(self.visit(child))
+ else:
+ new.append(child)
+ if isinstance(child, ast.AST):
+ nodes.append(child)
+ setattr(node, name, new)
+ elif (isinstance(field, ast.AST) and
+ # Don't recurse into expressions as they can't contain
+ # asserts.
+ not isinstance(field, ast.expr)):
+ nodes.append(field)
+
+ def is_rewrite_disabled(self, docstring):
+ return "PYTEST_DONT_REWRITE" in docstring
+
+ def variable(self):
+ """Get a new variable."""
+ # Use a character invalid in python identifiers to avoid clashing.
+ name = "@py_assert" + str(next(self.variable_counter))
+ self.variables.append(name)
+ return name
+
+ def assign(self, expr):
+ """Give *expr* a name."""
+ name = self.variable()
+ self.statements.append(ast.Assign([ast.Name(name, ast.Store())], expr))
+ return ast.Name(name, ast.Load())
+
+ def display(self, expr):
+ """Call py.io.saferepr on the expression."""
+ return self.helper("saferepr", expr)
+
+ def helper(self, name, *args):
+ """Call a helper in this module."""
+ py_name = ast.Name("@pytest_ar", ast.Load())
+ attr = ast.Attribute(py_name, "_" + name, ast.Load())
+ return ast_Call(attr, list(args), [])
+
+ def builtin(self, name):
+ """Return the builtin called *name*."""
+ builtin_name = ast.Name("@py_builtins", ast.Load())
+ return ast.Attribute(builtin_name, name, ast.Load())
+
+ def explanation_param(self, expr):
+ """Return a new named %-formatting placeholder for expr.
+
+ This creates a %-formatting placeholder for expr in the
+ current formatting context, e.g. ``%(py0)s``. The placeholder
+ and expr are placed in the current format context so that it
+ can be used on the next call to .pop_format_context().
+
+ """
+ specifier = "py" + str(next(self.variable_counter))
+ self.explanation_specifiers[specifier] = expr
+ return "%(" + specifier + ")s"
+
+ def push_format_context(self):
+ """Create a new formatting context.
+
+ The format context is used for when an explanation wants to
+ have a variable value formatted in the assertion message. In
+ this case the value required can be added using
+ .explanation_param(). Finally .pop_format_context() is used
+ to format a string of %-formatted values as added by
+ .explanation_param().
+
+ """
+ self.explanation_specifiers = {}
+ self.stack.append(self.explanation_specifiers)
+
+ def pop_format_context(self, expl_expr):
+ """Format the %-formatted string with current format context.
+
+ The expl_expr should be an ast.Str instance constructed from
+ the %-placeholders created by .explanation_param(). This will
+ add the required code to format said string to .on_failure and
+ return the ast.Name instance of the formatted string.
+
+ """
+ current = self.stack.pop()
+ if self.stack:
+ self.explanation_specifiers = self.stack[-1]
+ keys = [ast.Str(key) for key in current.keys()]
+ format_dict = ast.Dict(keys, list(current.values()))
+ form = ast.BinOp(expl_expr, ast.Mod(), format_dict)
+ name = "@py_format" + str(next(self.variable_counter))
+ self.on_failure.append(ast.Assign([ast.Name(name, ast.Store())], form))
+ return ast.Name(name, ast.Load())
+
+ def generic_visit(self, node):
+ """Handle expressions we don't have custom code for."""
+ assert isinstance(node, ast.expr)
+ res = self.assign(node)
+ return res, self.explanation_param(self.display(res))
+
+ def visit_Assert(self, assert_):
+ """Return the AST statements to replace the ast.Assert instance.
+
+ This rewrites the test of an assertion to provide
+ intermediate values and replace it with an if statement which
+ raises an assertion error with a detailed explanation in case
+ the expression is false.
+
+ """
+ if isinstance(assert_.test, ast.Tuple) and self.config is not None:
+ fslocation = (self.module_path, assert_.lineno)
+ self.config.warn('R1', 'assertion is always true, perhaps '
+ 'remove parentheses?', fslocation=fslocation)
+ self.statements = []
+ self.variables = []
+ self.variable_counter = itertools.count()
+ self.stack = []
+ self.on_failure = []
+ self.push_format_context()
+ # Rewrite assert into a bunch of statements.
+ top_condition, explanation = self.visit(assert_.test)
+ # Create failure message.
+ body = self.on_failure
+ negation = ast.UnaryOp(ast.Not(), top_condition)
+ self.statements.append(ast.If(negation, body, []))
+ if assert_.msg:
+ assertmsg = self.helper('format_assertmsg', assert_.msg)
+ explanation = "\n>assert " + explanation
+ else:
+ assertmsg = ast.Str("")
+ explanation = "assert " + explanation
+ template = ast.BinOp(assertmsg, ast.Add(), ast.Str(explanation))
+ msg = self.pop_format_context(template)
+ fmt = self.helper("format_explanation", msg)
+ err_name = ast.Name("AssertionError", ast.Load())
+ exc = ast_Call(err_name, [fmt], [])
+ if sys.version_info[0] >= 3:
+ raise_ = ast.Raise(exc, None)
+ else:
+ raise_ = ast.Raise(exc, None, None)
+ body.append(raise_)
+ # Clear temporary variables by setting them to None.
+ if self.variables:
+ variables = [ast.Name(name, ast.Store())
+ for name in self.variables]
+ clear = ast.Assign(variables, _NameConstant(None))
+ self.statements.append(clear)
+ # Fix line numbers.
+ for stmt in self.statements:
+ set_location(stmt, assert_.lineno, assert_.col_offset)
+ return self.statements
+
+ def visit_Name(self, name):
+ # Display the repr of the name if it's a local variable or
+ # _should_repr_global_name() thinks it's acceptable.
+ locs = ast_Call(self.builtin("locals"), [], [])
+ inlocs = ast.Compare(ast.Str(name.id), [ast.In()], [locs])
+ dorepr = self.helper("should_repr_global_name", name)
+ test = ast.BoolOp(ast.Or(), [inlocs, dorepr])
+ expr = ast.IfExp(test, self.display(name), ast.Str(name.id))
+ return name, self.explanation_param(expr)
+
+ def visit_BoolOp(self, boolop):
+ res_var = self.variable()
+ expl_list = self.assign(ast.List([], ast.Load()))
+ app = ast.Attribute(expl_list, "append", ast.Load())
+ is_or = int(isinstance(boolop.op, ast.Or))
+ body = save = self.statements
+ fail_save = self.on_failure
+ levels = len(boolop.values) - 1
+ self.push_format_context()
+ # Process each operand, short-circuting if needed.
+ for i, v in enumerate(boolop.values):
+ if i:
+ fail_inner = []
+ # cond is set in a prior loop iteration below
+ self.on_failure.append(ast.If(cond, fail_inner, [])) # noqa
+ self.on_failure = fail_inner
+ self.push_format_context()
+ res, expl = self.visit(v)
+ body.append(ast.Assign([ast.Name(res_var, ast.Store())], res))
+ expl_format = self.pop_format_context(ast.Str(expl))
+ call = ast_Call(app, [expl_format], [])
+ self.on_failure.append(ast.Expr(call))
+ if i < levels:
+ cond = res
+ if is_or:
+ cond = ast.UnaryOp(ast.Not(), cond)
+ inner = []
+ self.statements.append(ast.If(cond, inner, []))
+ self.statements = body = inner
+ self.statements = save
+ self.on_failure = fail_save
+ expl_template = self.helper("format_boolop", expl_list, ast.Num(is_or))
+ expl = self.pop_format_context(expl_template)
+ return ast.Name(res_var, ast.Load()), self.explanation_param(expl)
+
+ def visit_UnaryOp(self, unary):
+ pattern = unary_map[unary.op.__class__]
+ operand_res, operand_expl = self.visit(unary.operand)
+ res = self.assign(ast.UnaryOp(unary.op, operand_res))
+ return res, pattern % (operand_expl,)
+
+ def visit_BinOp(self, binop):
+ symbol = binop_map[binop.op.__class__]
+ left_expr, left_expl = self.visit(binop.left)
+ right_expr, right_expl = self.visit(binop.right)
+ explanation = "(%s %s %s)" % (left_expl, symbol, right_expl)
+ res = self.assign(ast.BinOp(left_expr, binop.op, right_expr))
+ return res, explanation
+
+ def visit_Call_35(self, call):
+ """
+ visit `ast.Call` nodes on Python3.5 and after
+ """
+ new_func, func_expl = self.visit(call.func)
+ arg_expls = []
+ new_args = []
+ new_kwargs = []
+ for arg in call.args:
+ res, expl = self.visit(arg)
+ arg_expls.append(expl)
+ new_args.append(res)
+ for keyword in call.keywords:
+ res, expl = self.visit(keyword.value)
+ new_kwargs.append(ast.keyword(keyword.arg, res))
+ if keyword.arg:
+ arg_expls.append(keyword.arg + "=" + expl)
+ else: # **args have `arg` keywords with an .arg of None
+ arg_expls.append("**" + expl)
+
+ expl = "%s(%s)" % (func_expl, ', '.join(arg_expls))
+ new_call = ast.Call(new_func, new_args, new_kwargs)
+ res = self.assign(new_call)
+ res_expl = self.explanation_param(self.display(res))
+ outer_expl = "%s\n{%s = %s\n}" % (res_expl, res_expl, expl)
+ return res, outer_expl
+
+ def visit_Starred(self, starred):
+ # From Python 3.5, a Starred node can appear in a function call
+ res, expl = self.visit(starred.value)
+ return starred, '*' + expl
+
+ def visit_Call_legacy(self, call):
+ """
+ visit `ast.Call nodes on 3.4 and below`
+ """
+ new_func, func_expl = self.visit(call.func)
+ arg_expls = []
+ new_args = []
+ new_kwargs = []
+ new_star = new_kwarg = None
+ for arg in call.args:
+ res, expl = self.visit(arg)
+ new_args.append(res)
+ arg_expls.append(expl)
+ for keyword in call.keywords:
+ res, expl = self.visit(keyword.value)
+ new_kwargs.append(ast.keyword(keyword.arg, res))
+ arg_expls.append(keyword.arg + "=" + expl)
+ if call.starargs:
+ new_star, expl = self.visit(call.starargs)
+ arg_expls.append("*" + expl)
+ if call.kwargs:
+ new_kwarg, expl = self.visit(call.kwargs)
+ arg_expls.append("**" + expl)
+ expl = "%s(%s)" % (func_expl, ', '.join(arg_expls))
+ new_call = ast.Call(new_func, new_args, new_kwargs,
+ new_star, new_kwarg)
+ res = self.assign(new_call)
+ res_expl = self.explanation_param(self.display(res))
+ outer_expl = "%s\n{%s = %s\n}" % (res_expl, res_expl, expl)
+ return res, outer_expl
+
+ # ast.Call signature changed on 3.5,
+ # conditionally change which methods is named
+ # visit_Call depending on Python version
+ if sys.version_info >= (3, 5):
+ visit_Call = visit_Call_35
+ else:
+ visit_Call = visit_Call_legacy
+
+ def visit_Attribute(self, attr):
+ if not isinstance(attr.ctx, ast.Load):
+ return self.generic_visit(attr)
+ value, value_expl = self.visit(attr.value)
+ res = self.assign(ast.Attribute(value, attr.attr, ast.Load()))
+ res_expl = self.explanation_param(self.display(res))
+ pat = "%s\n{%s = %s.%s\n}"
+ expl = pat % (res_expl, res_expl, value_expl, attr.attr)
+ return res, expl
+
+ def visit_Compare(self, comp):
+ self.push_format_context()
+ left_res, left_expl = self.visit(comp.left)
+ if isinstance(comp.left, (_ast.Compare, _ast.BoolOp)):
+ left_expl = "({0})".format(left_expl)
+ res_variables = [self.variable() for i in range(len(comp.ops))]
+ load_names = [ast.Name(v, ast.Load()) for v in res_variables]
+ store_names = [ast.Name(v, ast.Store()) for v in res_variables]
+ it = zip(range(len(comp.ops)), comp.ops, comp.comparators)
+ expls = []
+ syms = []
+ results = [left_res]
+ for i, op, next_operand in it:
+ next_res, next_expl = self.visit(next_operand)
+ if isinstance(next_operand, (_ast.Compare, _ast.BoolOp)):
+ next_expl = "({0})".format(next_expl)
+ results.append(next_res)
+ sym = binop_map[op.__class__]
+ syms.append(ast.Str(sym))
+ expl = "%s %s %s" % (left_expl, sym, next_expl)
+ expls.append(ast.Str(expl))
+ res_expr = ast.Compare(left_res, [op], [next_res])
+ self.statements.append(ast.Assign([store_names[i]], res_expr))
+ left_res, left_expl = next_res, next_expl
+ # Use pytest.assertion.util._reprcompare if that's available.
+ expl_call = self.helper("call_reprcompare",
+ ast.Tuple(syms, ast.Load()),
+ ast.Tuple(load_names, ast.Load()),
+ ast.Tuple(expls, ast.Load()),
+ ast.Tuple(results, ast.Load()))
+ if len(comp.ops) > 1:
+ res = ast.BoolOp(ast.And(), load_names)
+ else:
+ res = load_names[0]
+ return res, self.explanation_param(self.pop_format_context(expl_call))
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/assertion/truncate.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/assertion/truncate.py
new file mode 100644
index 00000000000..2ed12e2e5a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/assertion/truncate.py
@@ -0,0 +1,102 @@
+"""
+Utilities for truncating assertion output.
+
+Current default behaviour is to truncate assertion explanations at
+~8 terminal lines, unless running in "-vv" mode or running on CI.
+"""
+from __future__ import absolute_import, division, print_function
+import os
+
+import six
+
+
+DEFAULT_MAX_LINES = 8
+DEFAULT_MAX_CHARS = 8 * 80
+USAGE_MSG = "use '-vv' to show"
+
+
+def truncate_if_required(explanation, item, max_length=None):
+ """
+ Truncate this assertion explanation if the given test item is eligible.
+ """
+ if _should_truncate_item(item):
+ return _truncate_explanation(explanation)
+ return explanation
+
+
+def _should_truncate_item(item):
+ """
+ Whether or not this test item is eligible for truncation.
+ """
+ verbose = item.config.option.verbose
+ return verbose < 2 and not _running_on_ci()
+
+
+def _running_on_ci():
+ """Check if we're currently running on a CI system."""
+ env_vars = ['CI', 'BUILD_NUMBER']
+ return any(var in os.environ for var in env_vars)
+
+
+def _truncate_explanation(input_lines, max_lines=None, max_chars=None):
+ """
+ Truncate given list of strings that makes up the assertion explanation.
+
+ Truncates to either 8 lines, or 640 characters - whichever the input reaches
+ first. The remaining lines will be replaced by a usage message.
+ """
+
+ if max_lines is None:
+ max_lines = DEFAULT_MAX_LINES
+ if max_chars is None:
+ max_chars = DEFAULT_MAX_CHARS
+
+ # Check if truncation required
+ input_char_count = len("".join(input_lines))
+ if len(input_lines) <= max_lines and input_char_count <= max_chars:
+ return input_lines
+
+ # Truncate first to max_lines, and then truncate to max_chars if max_chars
+ # is exceeded.
+ truncated_explanation = input_lines[:max_lines]
+ truncated_explanation = _truncate_by_char_count(truncated_explanation, max_chars)
+
+ # Add ellipsis to final line
+ truncated_explanation[-1] = truncated_explanation[-1] + "..."
+
+ # Append useful message to explanation
+ truncated_line_count = len(input_lines) - len(truncated_explanation)
+ truncated_line_count += 1 # Account for the part-truncated final line
+ msg = '...Full output truncated'
+ if truncated_line_count == 1:
+ msg += ' ({0} line hidden)'.format(truncated_line_count)
+ else:
+ msg += ' ({0} lines hidden)'.format(truncated_line_count)
+ msg += ", {0}" .format(USAGE_MSG)
+ truncated_explanation.extend([
+ six.text_type(""),
+ six.text_type(msg),
+ ])
+ return truncated_explanation
+
+
+def _truncate_by_char_count(input_lines, max_chars):
+ # Check if truncation required
+ if len("".join(input_lines)) <= max_chars:
+ return input_lines
+
+ # Find point at which input length exceeds total allowed length
+ iterated_char_count = 0
+ for iterated_index, input_line in enumerate(input_lines):
+ if iterated_char_count + len(input_line) > max_chars:
+ break
+ iterated_char_count += len(input_line)
+
+ # Create truncated explanation with modified final line
+ truncated_result = input_lines[:iterated_index]
+ final_line = input_lines[iterated_index]
+ if final_line:
+ final_line_truncate_point = max_chars - iterated_char_count
+ final_line = final_line[:final_line_truncate_point]
+ truncated_result.append(final_line)
+ return truncated_result
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/assertion/util.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/assertion/util.py
new file mode 100644
index 00000000000..511d98ef1fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/assertion/util.py
@@ -0,0 +1,308 @@
+"""Utilities for assertion debugging"""
+from __future__ import absolute_import, division, print_function
+import pprint
+
+import _pytest._code
+import py
+import six
+try:
+ from collections import Sequence
+except ImportError:
+ Sequence = list
+
+
+u = six.text_type
+
+# The _reprcompare attribute on the util module is used by the new assertion
+# interpretation code and assertion rewriter to detect this plugin was
+# loaded and in turn call the hooks defined here as part of the
+# DebugInterpreter.
+_reprcompare = None
+
+
+# the re-encoding is needed for python2 repr
+# with non-ascii characters (see issue 877 and 1379)
+def ecu(s):
+ try:
+ return u(s, 'utf-8', 'replace')
+ except TypeError:
+ return s
+
+
+def format_explanation(explanation):
+ """This formats an explanation
+
+ Normally all embedded newlines are escaped, however there are
+ three exceptions: \n{, \n} and \n~. The first two are intended
+ cover nested explanations, see function and attribute explanations
+ for examples (.visit_Call(), visit_Attribute()). The last one is
+ for when one explanation needs to span multiple lines, e.g. when
+ displaying diffs.
+ """
+ explanation = ecu(explanation)
+ lines = _split_explanation(explanation)
+ result = _format_lines(lines)
+ return u('\n').join(result)
+
+
+def _split_explanation(explanation):
+ """Return a list of individual lines in the explanation
+
+ This will return a list of lines split on '\n{', '\n}' and '\n~'.
+ Any other newlines will be escaped and appear in the line as the
+ literal '\n' characters.
+ """
+ raw_lines = (explanation or u('')).split('\n')
+ lines = [raw_lines[0]]
+ for values in raw_lines[1:]:
+ if values and values[0] in ['{', '}', '~', '>']:
+ lines.append(values)
+ else:
+ lines[-1] += '\\n' + values
+ return lines
+
+
+def _format_lines(lines):
+ """Format the individual lines
+
+ This will replace the '{', '}' and '~' characters of our mini
+ formatting language with the proper 'where ...', 'and ...' and ' +
+ ...' text, taking care of indentation along the way.
+
+ Return a list of formatted lines.
+ """
+ result = lines[:1]
+ stack = [0]
+ stackcnt = [0]
+ for line in lines[1:]:
+ if line.startswith('{'):
+ if stackcnt[-1]:
+ s = u('and ')
+ else:
+ s = u('where ')
+ stack.append(len(result))
+ stackcnt[-1] += 1
+ stackcnt.append(0)
+ result.append(u(' +') + u(' ') * (len(stack) - 1) + s + line[1:])
+ elif line.startswith('}'):
+ stack.pop()
+ stackcnt.pop()
+ result[stack[-1]] += line[1:]
+ else:
+ assert line[0] in ['~', '>']
+ stack[-1] += 1
+ indent = len(stack) if line.startswith('~') else len(stack) - 1
+ result.append(u(' ') * indent + line[1:])
+ assert len(stack) == 1
+ return result
+
+
+# Provide basestring in python3
+try:
+ basestring = basestring
+except NameError:
+ basestring = str
+
+
+def assertrepr_compare(config, op, left, right):
+ """Return specialised explanations for some operators/operands"""
+ width = 80 - 15 - len(op) - 2 # 15 chars indentation, 1 space around op
+ left_repr = py.io.saferepr(left, maxsize=int(width // 2))
+ right_repr = py.io.saferepr(right, maxsize=width - len(left_repr))
+
+ summary = u('%s %s %s') % (ecu(left_repr), op, ecu(right_repr))
+
+ def issequence(x):
+ return (isinstance(x, (list, tuple, Sequence)) and not isinstance(x, basestring))
+
+ def istext(x):
+ return isinstance(x, basestring)
+
+ def isdict(x):
+ return isinstance(x, dict)
+
+ def isset(x):
+ return isinstance(x, (set, frozenset))
+
+ def isiterable(obj):
+ try:
+ iter(obj)
+ return not istext(obj)
+ except TypeError:
+ return False
+
+ verbose = config.getoption('verbose')
+ explanation = None
+ try:
+ if op == '==':
+ if istext(left) and istext(right):
+ explanation = _diff_text(left, right, verbose)
+ else:
+ if issequence(left) and issequence(right):
+ explanation = _compare_eq_sequence(left, right, verbose)
+ elif isset(left) and isset(right):
+ explanation = _compare_eq_set(left, right, verbose)
+ elif isdict(left) and isdict(right):
+ explanation = _compare_eq_dict(left, right, verbose)
+ if isiterable(left) and isiterable(right):
+ expl = _compare_eq_iterable(left, right, verbose)
+ if explanation is not None:
+ explanation.extend(expl)
+ else:
+ explanation = expl
+ elif op == 'not in':
+ if istext(left) and istext(right):
+ explanation = _notin_text(left, right, verbose)
+ except Exception:
+ explanation = [
+ u('(pytest_assertion plugin: representation of details failed. '
+ 'Probably an object has a faulty __repr__.)'),
+ u(_pytest._code.ExceptionInfo())]
+
+ if not explanation:
+ return None
+
+ return [summary] + explanation
+
+
+def _diff_text(left, right, verbose=False):
+ """Return the explanation for the diff between text or bytes
+
+ Unless --verbose is used this will skip leading and trailing
+ characters which are identical to keep the diff minimal.
+
+ If the input are bytes they will be safely converted to text.
+ """
+ from difflib import ndiff
+ explanation = []
+ if isinstance(left, six.binary_type):
+ left = u(repr(left)[1:-1]).replace(r'\n', '\n')
+ if isinstance(right, six.binary_type):
+ right = u(repr(right)[1:-1]).replace(r'\n', '\n')
+ if not verbose:
+ i = 0 # just in case left or right has zero length
+ for i in range(min(len(left), len(right))):
+ if left[i] != right[i]:
+ break
+ if i > 42:
+ i -= 10 # Provide some context
+ explanation = [u('Skipping %s identical leading '
+ 'characters in diff, use -v to show') % i]
+ left = left[i:]
+ right = right[i:]
+ if len(left) == len(right):
+ for i in range(len(left)):
+ if left[-i] != right[-i]:
+ break
+ if i > 42:
+ i -= 10 # Provide some context
+ explanation += [u('Skipping %s identical trailing '
+ 'characters in diff, use -v to show') % i]
+ left = left[:-i]
+ right = right[:-i]
+ keepends = True
+ explanation += [line.strip('\n')
+ for line in ndiff(left.splitlines(keepends),
+ right.splitlines(keepends))]
+ return explanation
+
+
+def _compare_eq_iterable(left, right, verbose=False):
+ if not verbose:
+ return [u('Use -v to get the full diff')]
+ # dynamic import to speedup pytest
+ import difflib
+
+ try:
+ left_formatting = pprint.pformat(left).splitlines()
+ right_formatting = pprint.pformat(right).splitlines()
+ explanation = [u('Full diff:')]
+ except Exception:
+ # hack: PrettyPrinter.pformat() in python 2 fails when formatting items that can't be sorted(), ie, calling
+ # sorted() on a list would raise. See issue #718.
+ # As a workaround, the full diff is generated by using the repr() string of each item of each container.
+ left_formatting = sorted(repr(x) for x in left)
+ right_formatting = sorted(repr(x) for x in right)
+ explanation = [u('Full diff (fallback to calling repr on each item):')]
+ explanation.extend(line.strip() for line in difflib.ndiff(left_formatting, right_formatting))
+ return explanation
+
+
+def _compare_eq_sequence(left, right, verbose=False):
+ explanation = []
+ for i in range(min(len(left), len(right))):
+ if left[i] != right[i]:
+ explanation += [u('At index %s diff: %r != %r')
+ % (i, left[i], right[i])]
+ break
+ if len(left) > len(right):
+ explanation += [u('Left contains more items, first extra item: %s')
+ % py.io.saferepr(left[len(right)],)]
+ elif len(left) < len(right):
+ explanation += [
+ u('Right contains more items, first extra item: %s') %
+ py.io.saferepr(right[len(left)],)]
+ return explanation
+
+
+def _compare_eq_set(left, right, verbose=False):
+ explanation = []
+ diff_left = left - right
+ diff_right = right - left
+ if diff_left:
+ explanation.append(u('Extra items in the left set:'))
+ for item in diff_left:
+ explanation.append(py.io.saferepr(item))
+ if diff_right:
+ explanation.append(u('Extra items in the right set:'))
+ for item in diff_right:
+ explanation.append(py.io.saferepr(item))
+ return explanation
+
+
+def _compare_eq_dict(left, right, verbose=False):
+ explanation = []
+ common = set(left).intersection(set(right))
+ same = dict((k, left[k]) for k in common if left[k] == right[k])
+ if same and verbose < 2:
+ explanation += [u('Omitting %s identical items, use -vv to show') %
+ len(same)]
+ elif same:
+ explanation += [u('Common items:')]
+ explanation += pprint.pformat(same).splitlines()
+ diff = set(k for k in common if left[k] != right[k])
+ if diff:
+ explanation += [u('Differing items:')]
+ for k in diff:
+ explanation += [py.io.saferepr({k: left[k]}) + ' != ' +
+ py.io.saferepr({k: right[k]})]
+ extra_left = set(left) - set(right)
+ if extra_left:
+ explanation.append(u('Left contains more items:'))
+ explanation.extend(pprint.pformat(
+ dict((k, left[k]) for k in extra_left)).splitlines())
+ extra_right = set(right) - set(left)
+ if extra_right:
+ explanation.append(u('Right contains more items:'))
+ explanation.extend(pprint.pformat(
+ dict((k, right[k]) for k in extra_right)).splitlines())
+ return explanation
+
+
+def _notin_text(term, text, verbose=False):
+ index = text.find(term)
+ head = text[:index]
+ tail = text[index + len(term):]
+ correct_text = head + tail
+ diff = _diff_text(correct_text, text, verbose)
+ newdiff = [u('%s is contained here:') % py.io.saferepr(term, maxsize=42)]
+ for line in diff:
+ if line.startswith(u('Skipping')):
+ continue
+ if line.startswith(u('- ')):
+ continue
+ if line.startswith(u('+ ')):
+ newdiff.append(u(' ') + line[2:])
+ else:
+ newdiff.append(line)
+ return newdiff
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/cacheprovider.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/cacheprovider.py
new file mode 100755
index 00000000000..c537c14472b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/cacheprovider.py
@@ -0,0 +1,260 @@
+"""
+merged implementation of the cache provider
+
+the name cache was not chosen to ensure pluggy automatically
+ignores the external pytest-cache
+"""
+from __future__ import absolute_import, division, print_function
+import py
+import pytest
+import json
+import os
+from os.path import sep as _sep, altsep as _altsep
+
+
+class Cache(object):
+ def __init__(self, config):
+ self.config = config
+ self._cachedir = Cache.cache_dir_from_config(config)
+ self.trace = config.trace.root.get("cache")
+ if config.getvalue("cacheclear"):
+ self.trace("clearing cachedir")
+ if self._cachedir.check():
+ self._cachedir.remove()
+ self._cachedir.mkdir()
+
+ @staticmethod
+ def cache_dir_from_config(config):
+ cache_dir = config.getini("cache_dir")
+ cache_dir = os.path.expanduser(cache_dir)
+ cache_dir = os.path.expandvars(cache_dir)
+ if os.path.isabs(cache_dir):
+ return py.path.local(cache_dir)
+ else:
+ return config.rootdir.join(cache_dir)
+
+ def makedir(self, name):
+ """ return a directory path object with the given name. If the
+ directory does not yet exist, it will be created. You can use it
+ to manage files likes e. g. store/retrieve database
+ dumps across test sessions.
+
+ :param name: must be a string not containing a ``/`` separator.
+ Make sure the name contains your plugin or application
+ identifiers to prevent clashes with other cache users.
+ """
+ if _sep in name or _altsep is not None and _altsep in name:
+ raise ValueError("name is not allowed to contain path separators")
+ return self._cachedir.ensure_dir("d", name)
+
+ def _getvaluepath(self, key):
+ return self._cachedir.join('v', *key.split('/'))
+
+ def get(self, key, default):
+ """ return cached value for the given key. If no value
+ was yet cached or the value cannot be read, the specified
+ default is returned.
+
+ :param key: must be a ``/`` separated value. Usually the first
+ name is the name of your plugin or your application.
+ :param default: must be provided in case of a cache-miss or
+ invalid cache values.
+
+ """
+ path = self._getvaluepath(key)
+ if path.check():
+ try:
+ with path.open("r") as f:
+ return json.load(f)
+ except ValueError:
+ self.trace("cache-invalid at %s" % (path,))
+ return default
+
+ def set(self, key, value):
+ """ save value for the given key.
+
+ :param key: must be a ``/`` separated value. Usually the first
+ name is the name of your plugin or your application.
+ :param value: must be of any combination of basic
+ python types, including nested types
+ like e. g. lists of dictionaries.
+ """
+ path = self._getvaluepath(key)
+ try:
+ path.dirpath().ensure_dir()
+ except (py.error.EEXIST, py.error.EACCES):
+ self.config.warn(
+ code='I9', message='could not create cache path %s' % (path,)
+ )
+ return
+ try:
+ f = path.open('w')
+ except py.error.ENOTDIR:
+ self.config.warn(
+ code='I9', message='cache could not write path %s' % (path,))
+ else:
+ with f:
+ self.trace("cache-write %s: %r" % (key, value,))
+ json.dump(value, f, indent=2, sort_keys=True)
+
+
+class LFPlugin:
+ """ Plugin which implements the --lf (run last-failing) option """
+
+ def __init__(self, config):
+ self.config = config
+ active_keys = 'lf', 'failedfirst'
+ self.active = any(config.getvalue(key) for key in active_keys)
+ self.lastfailed = config.cache.get("cache/lastfailed", {})
+ self._previously_failed_count = None
+
+ def pytest_report_collectionfinish(self):
+ if self.active:
+ if not self._previously_failed_count:
+ mode = "run all (no recorded failures)"
+ else:
+ noun = 'failure' if self._previously_failed_count == 1 else 'failures'
+ suffix = " first" if self.config.getvalue("failedfirst") else ""
+ mode = "rerun previous {count} {noun}{suffix}".format(
+ count=self._previously_failed_count, suffix=suffix, noun=noun
+ )
+ return "run-last-failure: %s" % mode
+
+ def pytest_runtest_logreport(self, report):
+ if (report.when == 'call' and report.passed) or report.skipped:
+ self.lastfailed.pop(report.nodeid, None)
+ elif report.failed:
+ self.lastfailed[report.nodeid] = True
+
+ def pytest_collectreport(self, report):
+ passed = report.outcome in ('passed', 'skipped')
+ if passed:
+ if report.nodeid in self.lastfailed:
+ self.lastfailed.pop(report.nodeid)
+ self.lastfailed.update(
+ (item.nodeid, True)
+ for item in report.result)
+ else:
+ self.lastfailed[report.nodeid] = True
+
+ def pytest_collection_modifyitems(self, session, config, items):
+ if self.active and self.lastfailed:
+ previously_failed = []
+ previously_passed = []
+ for item in items:
+ if item.nodeid in self.lastfailed:
+ previously_failed.append(item)
+ else:
+ previously_passed.append(item)
+ self._previously_failed_count = len(previously_failed)
+ if not previously_failed:
+ # running a subset of all tests with recorded failures outside
+ # of the set of tests currently executing
+ return
+ if self.config.getvalue("lf"):
+ items[:] = previously_failed
+ config.hook.pytest_deselected(items=previously_passed)
+ else:
+ items[:] = previously_failed + previously_passed
+
+ def pytest_sessionfinish(self, session):
+ config = self.config
+ if config.getvalue("cacheshow") or hasattr(config, "slaveinput"):
+ return
+
+ saved_lastfailed = config.cache.get("cache/lastfailed", {})
+ if saved_lastfailed != self.lastfailed:
+ config.cache.set("cache/lastfailed", self.lastfailed)
+
+
+def pytest_addoption(parser):
+ group = parser.getgroup("general")
+ group.addoption(
+ '--lf', '--last-failed', action='store_true', dest="lf",
+ help="rerun only the tests that failed "
+ "at the last run (or all if none failed)")
+ group.addoption(
+ '--ff', '--failed-first', action='store_true', dest="failedfirst",
+ help="run all tests but run the last failures first. "
+ "This may re-order tests and thus lead to "
+ "repeated fixture setup/teardown")
+ group.addoption(
+ '--cache-show', action='store_true', dest="cacheshow",
+ help="show cache contents, don't perform collection or tests")
+ group.addoption(
+ '--cache-clear', action='store_true', dest="cacheclear",
+ help="remove all cache contents at start of test run.")
+ parser.addini(
+ "cache_dir", default='.cache',
+ help="cache directory path.")
+
+
+def pytest_cmdline_main(config):
+ if config.option.cacheshow:
+ from _pytest.main import wrap_session
+ return wrap_session(config, cacheshow)
+
+
+@pytest.hookimpl(tryfirst=True)
+def pytest_configure(config):
+ config.cache = Cache(config)
+ config.pluginmanager.register(LFPlugin(config), "lfplugin")
+
+
+@pytest.fixture
+def cache(request):
+ """
+ Return a cache object that can persist state between testing sessions.
+
+ cache.get(key, default)
+ cache.set(key, value)
+
+ Keys must be a ``/`` separated value, where the first part is usually the
+ name of your plugin or application to avoid clashes with other cache users.
+
+ Values can be any object handled by the json stdlib module.
+ """
+ return request.config.cache
+
+
+def pytest_report_header(config):
+ if config.option.verbose:
+ relpath = py.path.local().bestrelpath(config.cache._cachedir)
+ return "cachedir: %s" % relpath
+
+
+def cacheshow(config, session):
+ from pprint import pprint
+ tw = py.io.TerminalWriter()
+ tw.line("cachedir: " + str(config.cache._cachedir))
+ if not config.cache._cachedir.check():
+ tw.line("cache is empty")
+ return 0
+ dummy = object()
+ basedir = config.cache._cachedir
+ vdir = basedir.join("v")
+ tw.sep("-", "cache values")
+ for valpath in sorted(vdir.visit(lambda x: x.isfile())):
+ key = valpath.relto(vdir).replace(valpath.sep, "/")
+ val = config.cache.get(key, dummy)
+ if val is dummy:
+ tw.line("%s contains unreadable content, "
+ "will be ignored" % key)
+ else:
+ tw.line("%s contains:" % key)
+ stream = py.io.TextIO()
+ pprint(val, stream=stream)
+ for line in stream.getvalue().splitlines():
+ tw.line(" " + line)
+
+ ddir = basedir.join("d")
+ if ddir.isdir() and ddir.listdir():
+ tw.sep("-", "cache directories")
+ for p in sorted(basedir.join("d").visit()):
+ # if p.check(dir=1):
+ # print("%s/" % p.relto(basedir))
+ if p.isfile():
+ key = p.relto(basedir)
+ tw.line("%s is a file of length %d" % (
+ key, p.size()))
+ return 0
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/capture.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/capture.py
new file mode 100644
index 00000000000..f2ebe38c8c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/capture.py
@@ -0,0 +1,683 @@
+"""
+per-test stdout/stderr capturing mechanism.
+
+"""
+from __future__ import absolute_import, division, print_function
+
+import collections
+import contextlib
+import sys
+import os
+import io
+from io import UnsupportedOperation
+from tempfile import TemporaryFile
+
+import six
+import pytest
+from _pytest.compat import CaptureIO
+
+
+patchsysdict = {0: 'stdin', 1: 'stdout', 2: 'stderr'}
+
+
+def pytest_addoption(parser):
+ group = parser.getgroup("general")
+ group._addoption(
+ '--capture', action="store",
+ default="fd" if hasattr(os, "dup") else "sys",
+ metavar="method", choices=['fd', 'sys', 'no'],
+ help="per-test capturing method: one of fd|sys|no.")
+ group._addoption(
+ '-s', action="store_const", const="no", dest="capture",
+ help="shortcut for --capture=no.")
+
+
+@pytest.hookimpl(hookwrapper=True)
+def pytest_load_initial_conftests(early_config, parser, args):
+ ns = early_config.known_args_namespace
+ if ns.capture == "fd":
+ _py36_windowsconsoleio_workaround(sys.stdout)
+ _colorama_workaround()
+ _readline_workaround()
+ pluginmanager = early_config.pluginmanager
+ capman = CaptureManager(ns.capture)
+ pluginmanager.register(capman, "capturemanager")
+
+ # make sure that capturemanager is properly reset at final shutdown
+ early_config.add_cleanup(capman.stop_global_capturing)
+
+ # make sure logging does not raise exceptions at the end
+ def silence_logging_at_shutdown():
+ if "logging" in sys.modules:
+ sys.modules["logging"].raiseExceptions = False
+ early_config.add_cleanup(silence_logging_at_shutdown)
+
+ # finally trigger conftest loading but while capturing (issue93)
+ capman.start_global_capturing()
+ outcome = yield
+ out, err = capman.suspend_global_capture()
+ if outcome.excinfo is not None:
+ sys.stdout.write(out)
+ sys.stderr.write(err)
+
+
+class CaptureManager:
+ """
+ Capture plugin, manages that the appropriate capture method is enabled/disabled during collection and each
+ test phase (setup, call, teardown). After each of those points, the captured output is obtained and
+ attached to the collection/runtest report.
+
+ There are two levels of capture:
+ * global: which is enabled by default and can be suppressed by the ``-s`` option. This is always enabled/disabled
+ during collection and each test phase.
+ * fixture: when a test function or one of its fixture depend on the ``capsys`` or ``capfd`` fixtures. In this
+ case special handling is needed to ensure the fixtures take precedence over the global capture.
+ """
+
+ def __init__(self, method):
+ self._method = method
+ self._global_capturing = None
+
+ def _getcapture(self, method):
+ if method == "fd":
+ return MultiCapture(out=True, err=True, Capture=FDCapture)
+ elif method == "sys":
+ return MultiCapture(out=True, err=True, Capture=SysCapture)
+ elif method == "no":
+ return MultiCapture(out=False, err=False, in_=False)
+ else:
+ raise ValueError("unknown capturing method: %r" % method)
+
+ def start_global_capturing(self):
+ assert self._global_capturing is None
+ self._global_capturing = self._getcapture(self._method)
+ self._global_capturing.start_capturing()
+
+ def stop_global_capturing(self):
+ if self._global_capturing is not None:
+ self._global_capturing.pop_outerr_to_orig()
+ self._global_capturing.stop_capturing()
+ self._global_capturing = None
+
+ def resume_global_capture(self):
+ self._global_capturing.resume_capturing()
+
+ def suspend_global_capture(self, item=None, in_=False):
+ if item is not None:
+ self.deactivate_fixture(item)
+ cap = getattr(self, "_global_capturing", None)
+ if cap is not None:
+ try:
+ outerr = cap.readouterr()
+ finally:
+ cap.suspend_capturing(in_=in_)
+ return outerr
+
+ def activate_fixture(self, item):
+ """If the current item is using ``capsys`` or ``capfd``, activate them so they take precedence over
+ the global capture.
+ """
+ fixture = getattr(item, "_capture_fixture", None)
+ if fixture is not None:
+ fixture._start()
+
+ def deactivate_fixture(self, item):
+ """Deactivates the ``capsys`` or ``capfd`` fixture of this item, if any."""
+ fixture = getattr(item, "_capture_fixture", None)
+ if fixture is not None:
+ fixture.close()
+
+ @pytest.hookimpl(hookwrapper=True)
+ def pytest_make_collect_report(self, collector):
+ if isinstance(collector, pytest.File):
+ self.resume_global_capture()
+ outcome = yield
+ out, err = self.suspend_global_capture()
+ rep = outcome.get_result()
+ if out:
+ rep.sections.append(("Captured stdout", out))
+ if err:
+ rep.sections.append(("Captured stderr", err))
+ else:
+ yield
+
+ @pytest.hookimpl(hookwrapper=True)
+ def pytest_runtest_setup(self, item):
+ self.resume_global_capture()
+ # no need to activate a capture fixture because they activate themselves during creation; this
+ # only makes sense when a fixture uses a capture fixture, otherwise the capture fixture will
+ # be activated during pytest_runtest_call
+ yield
+ self.suspend_capture_item(item, "setup")
+
+ @pytest.hookimpl(hookwrapper=True)
+ def pytest_runtest_call(self, item):
+ self.resume_global_capture()
+ # it is important to activate this fixture during the call phase so it overwrites the "global"
+ # capture
+ self.activate_fixture(item)
+ yield
+ self.suspend_capture_item(item, "call")
+
+ @pytest.hookimpl(hookwrapper=True)
+ def pytest_runtest_teardown(self, item):
+ self.resume_global_capture()
+ self.activate_fixture(item)
+ yield
+ self.suspend_capture_item(item, "teardown")
+
+ @pytest.hookimpl(tryfirst=True)
+ def pytest_keyboard_interrupt(self, excinfo):
+ self.stop_global_capturing()
+
+ @pytest.hookimpl(tryfirst=True)
+ def pytest_internalerror(self, excinfo):
+ self.stop_global_capturing()
+
+ def suspend_capture_item(self, item, when, in_=False):
+ out, err = self.suspend_global_capture(item, in_=in_)
+ item.add_report_section(when, "stdout", out)
+ item.add_report_section(when, "stderr", err)
+
+
+capture_fixtures = {'capfd', 'capfdbinary', 'capsys', 'capsysbinary'}
+
+
+def _ensure_only_one_capture_fixture(request, name):
+ fixtures = set(request.fixturenames) & capture_fixtures - set((name,))
+ if fixtures:
+ fixtures = sorted(fixtures)
+ fixtures = fixtures[0] if len(fixtures) == 1 else fixtures
+ raise request.raiseerror(
+ "cannot use {0} and {1} at the same time".format(
+ fixtures, name,
+ ),
+ )
+
+
+@pytest.fixture
+def capsys(request):
+ """Enable capturing of writes to sys.stdout/sys.stderr and make
+ captured output available via ``capsys.readouterr()`` method calls
+ which return a ``(out, err)`` tuple. ``out`` and ``err`` will be ``text``
+ objects.
+ """
+ _ensure_only_one_capture_fixture(request, 'capsys')
+ with _install_capture_fixture_on_item(request, SysCapture) as fixture:
+ yield fixture
+
+
+@pytest.fixture
+def capsysbinary(request):
+ """Enable capturing of writes to sys.stdout/sys.stderr and make
+ captured output available via ``capsys.readouterr()`` method calls
+ which return a ``(out, err)`` tuple. ``out`` and ``err`` will be ``bytes``
+ objects.
+ """
+ _ensure_only_one_capture_fixture(request, 'capsysbinary')
+ # Currently, the implementation uses the python3 specific `.buffer`
+ # property of CaptureIO.
+ if sys.version_info < (3,):
+ raise request.raiseerror('capsysbinary is only supported on python 3')
+ with _install_capture_fixture_on_item(request, SysCaptureBinary) as fixture:
+ yield fixture
+
+
+@pytest.fixture
+def capfd(request):
+ """Enable capturing of writes to file descriptors 1 and 2 and make
+ captured output available via ``capfd.readouterr()`` method calls
+ which return a ``(out, err)`` tuple. ``out`` and ``err`` will be ``text``
+ objects.
+ """
+ _ensure_only_one_capture_fixture(request, 'capfd')
+ if not hasattr(os, 'dup'):
+ pytest.skip("capfd fixture needs os.dup function which is not available in this system")
+ with _install_capture_fixture_on_item(request, FDCapture) as fixture:
+ yield fixture
+
+
+@pytest.fixture
+def capfdbinary(request):
+ """Enable capturing of write to file descriptors 1 and 2 and make
+ captured output available via ``capfdbinary.readouterr`` method calls
+ which return a ``(out, err)`` tuple. ``out`` and ``err`` will be
+ ``bytes`` objects.
+ """
+ _ensure_only_one_capture_fixture(request, 'capfdbinary')
+ if not hasattr(os, 'dup'):
+ pytest.skip("capfdbinary fixture needs os.dup function which is not available in this system")
+ with _install_capture_fixture_on_item(request, FDCaptureBinary) as fixture:
+ yield fixture
+
+
+@contextlib.contextmanager
+def _install_capture_fixture_on_item(request, capture_class):
+ """
+ Context manager which creates a ``CaptureFixture`` instance and "installs" it on
+ the item/node of the given request. Used by ``capsys`` and ``capfd``.
+
+ The CaptureFixture is added as attribute of the item because it needs to accessed
+ by ``CaptureManager`` during its ``pytest_runtest_*`` hooks.
+ """
+ request.node._capture_fixture = fixture = CaptureFixture(capture_class, request)
+ capmanager = request.config.pluginmanager.getplugin('capturemanager')
+ # need to active this fixture right away in case it is being used by another fixture (setup phase)
+ # if this fixture is being used only by a test function (call phase), then we wouldn't need this
+ # activation, but it doesn't hurt
+ capmanager.activate_fixture(request.node)
+ yield fixture
+ fixture.close()
+ del request.node._capture_fixture
+
+
+class CaptureFixture:
+ def __init__(self, captureclass, request):
+ self.captureclass = captureclass
+ self.request = request
+
+ def _start(self):
+ self._capture = MultiCapture(out=True, err=True, in_=False,
+ Capture=self.captureclass)
+ self._capture.start_capturing()
+
+ def close(self):
+ cap = self.__dict__.pop("_capture", None)
+ if cap is not None:
+ self._outerr = cap.pop_outerr_to_orig()
+ cap.stop_capturing()
+
+ def readouterr(self):
+ try:
+ return self._capture.readouterr()
+ except AttributeError:
+ return self._outerr
+
+ @contextlib.contextmanager
+ def disabled(self):
+ self._capture.suspend_capturing()
+ capmanager = self.request.config.pluginmanager.getplugin('capturemanager')
+ capmanager.suspend_global_capture(item=None, in_=False)
+ try:
+ yield
+ finally:
+ capmanager.resume_global_capture()
+ self._capture.resume_capturing()
+
+
+def safe_text_dupfile(f, mode, default_encoding="UTF8"):
+ """ return a open text file object that's a duplicate of f on the
+ FD-level if possible.
+ """
+ encoding = getattr(f, "encoding", None)
+ try:
+ fd = f.fileno()
+ except Exception:
+ if "b" not in getattr(f, "mode", "") and hasattr(f, "encoding"):
+ # we seem to have a text stream, let's just use it
+ return f
+ else:
+ newfd = os.dup(fd)
+ if "b" not in mode:
+ mode += "b"
+ f = os.fdopen(newfd, mode, 0) # no buffering
+ return EncodedFile(f, encoding or default_encoding)
+
+
+class EncodedFile(object):
+ errors = "strict" # possibly needed by py3 code (issue555)
+
+ def __init__(self, buffer, encoding):
+ self.buffer = buffer
+ self.encoding = encoding
+
+ def write(self, obj):
+ if isinstance(obj, six.text_type):
+ obj = obj.encode(self.encoding, "replace")
+ self.buffer.write(obj)
+
+ def writelines(self, linelist):
+ data = ''.join(linelist)
+ self.write(data)
+
+ @property
+ def name(self):
+ """Ensure that file.name is a string."""
+ return repr(self.buffer)
+
+ def __getattr__(self, name):
+ return getattr(object.__getattribute__(self, "buffer"), name)
+
+
+CaptureResult = collections.namedtuple("CaptureResult", ["out", "err"])
+
+
+class MultiCapture(object):
+ out = err = in_ = None
+
+ def __init__(self, out=True, err=True, in_=True, Capture=None):
+ if in_:
+ self.in_ = Capture(0)
+ if out:
+ self.out = Capture(1)
+ if err:
+ self.err = Capture(2)
+
+ def start_capturing(self):
+ if self.in_:
+ self.in_.start()
+ if self.out:
+ self.out.start()
+ if self.err:
+ self.err.start()
+
+ def pop_outerr_to_orig(self):
+ """ pop current snapshot out/err capture and flush to orig streams. """
+ out, err = self.readouterr()
+ if out:
+ self.out.writeorg(out)
+ if err:
+ self.err.writeorg(err)
+ return out, err
+
+ def suspend_capturing(self, in_=False):
+ if self.out:
+ self.out.suspend()
+ if self.err:
+ self.err.suspend()
+ if in_ and self.in_:
+ self.in_.suspend()
+ self._in_suspended = True
+
+ def resume_capturing(self):
+ if self.out:
+ self.out.resume()
+ if self.err:
+ self.err.resume()
+ if hasattr(self, "_in_suspended"):
+ self.in_.resume()
+ del self._in_suspended
+
+ def stop_capturing(self):
+ """ stop capturing and reset capturing streams """
+ if hasattr(self, '_reset'):
+ raise ValueError("was already stopped")
+ self._reset = True
+ if self.out:
+ self.out.done()
+ if self.err:
+ self.err.done()
+ if self.in_:
+ self.in_.done()
+
+ def readouterr(self):
+ """ return snapshot unicode value of stdout/stderr capturings. """
+ return CaptureResult(self.out.snap() if self.out is not None else "",
+ self.err.snap() if self.err is not None else "")
+
+
+class NoCapture:
+ __init__ = start = done = suspend = resume = lambda *args: None
+
+
+class FDCaptureBinary:
+ """Capture IO to/from a given os-level filedescriptor.
+
+ snap() produces `bytes`
+ """
+
+ def __init__(self, targetfd, tmpfile=None):
+ self.targetfd = targetfd
+ try:
+ self.targetfd_save = os.dup(self.targetfd)
+ except OSError:
+ self.start = lambda: None
+ self.done = lambda: None
+ else:
+ if targetfd == 0:
+ assert not tmpfile, "cannot set tmpfile with stdin"
+ tmpfile = open(os.devnull, "r")
+ self.syscapture = SysCapture(targetfd)
+ else:
+ if tmpfile is None:
+ f = TemporaryFile()
+ with f:
+ tmpfile = safe_text_dupfile(f, mode="wb+")
+ if targetfd in patchsysdict:
+ self.syscapture = SysCapture(targetfd, tmpfile)
+ else:
+ self.syscapture = NoCapture()
+ self.tmpfile = tmpfile
+ self.tmpfile_fd = tmpfile.fileno()
+
+ def __repr__(self):
+ return "<FDCapture %s oldfd=%s>" % (self.targetfd, self.targetfd_save)
+
+ def start(self):
+ """ Start capturing on targetfd using memorized tmpfile. """
+ try:
+ os.fstat(self.targetfd_save)
+ except (AttributeError, OSError):
+ raise ValueError("saved filedescriptor not valid anymore")
+ os.dup2(self.tmpfile_fd, self.targetfd)
+ self.syscapture.start()
+
+ def snap(self):
+ self.tmpfile.seek(0)
+ res = self.tmpfile.read()
+ self.tmpfile.seek(0)
+ self.tmpfile.truncate()
+ return res
+
+ def done(self):
+ """ stop capturing, restore streams, return original capture file,
+ seeked to position zero. """
+ targetfd_save = self.__dict__.pop("targetfd_save")
+ os.dup2(targetfd_save, self.targetfd)
+ os.close(targetfd_save)
+ self.syscapture.done()
+ self.tmpfile.close()
+
+ def suspend(self):
+ self.syscapture.suspend()
+ os.dup2(self.targetfd_save, self.targetfd)
+
+ def resume(self):
+ self.syscapture.resume()
+ os.dup2(self.tmpfile_fd, self.targetfd)
+
+ def writeorg(self, data):
+ """ write to original file descriptor. """
+ if isinstance(data, six.text_type):
+ data = data.encode("utf8") # XXX use encoding of original stream
+ os.write(self.targetfd_save, data)
+
+
+class FDCapture(FDCaptureBinary):
+ """Capture IO to/from a given os-level filedescriptor.
+
+ snap() produces text
+ """
+ def snap(self):
+ res = FDCaptureBinary.snap(self)
+ enc = getattr(self.tmpfile, "encoding", None)
+ if enc and isinstance(res, bytes):
+ res = six.text_type(res, enc, "replace")
+ return res
+
+
+class SysCapture:
+ def __init__(self, fd, tmpfile=None):
+ name = patchsysdict[fd]
+ self._old = getattr(sys, name)
+ self.name = name
+ if tmpfile is None:
+ if name == "stdin":
+ tmpfile = DontReadFromInput()
+ else:
+ tmpfile = CaptureIO()
+ self.tmpfile = tmpfile
+
+ def start(self):
+ setattr(sys, self.name, self.tmpfile)
+
+ def snap(self):
+ res = self.tmpfile.getvalue()
+ self.tmpfile.seek(0)
+ self.tmpfile.truncate()
+ return res
+
+ def done(self):
+ setattr(sys, self.name, self._old)
+ del self._old
+ self.tmpfile.close()
+
+ def suspend(self):
+ setattr(sys, self.name, self._old)
+
+ def resume(self):
+ setattr(sys, self.name, self.tmpfile)
+
+ def writeorg(self, data):
+ self._old.write(data)
+ self._old.flush()
+
+
+class SysCaptureBinary(SysCapture):
+ def snap(self):
+ res = self.tmpfile.buffer.getvalue()
+ self.tmpfile.seek(0)
+ self.tmpfile.truncate()
+ return res
+
+
+class DontReadFromInput:
+ """Temporary stub class. Ideally when stdin is accessed, the
+ capturing should be turned off, with possibly all data captured
+ so far sent to the screen. This should be configurable, though,
+ because in automated test runs it is better to crash than
+ hang indefinitely.
+ """
+
+ encoding = None
+
+ def read(self, *args):
+ raise IOError("reading from stdin while output is captured")
+ readline = read
+ readlines = read
+ __iter__ = read
+
+ def fileno(self):
+ raise UnsupportedOperation("redirected stdin is pseudofile, "
+ "has no fileno()")
+
+ def isatty(self):
+ return False
+
+ def close(self):
+ pass
+
+ @property
+ def buffer(self):
+ if sys.version_info >= (3, 0):
+ return self
+ else:
+ raise AttributeError('redirected stdin has no attribute buffer')
+
+
+def _colorama_workaround():
+ """
+ Ensure colorama is imported so that it attaches to the correct stdio
+ handles on Windows.
+
+ colorama uses the terminal on import time. So if something does the
+ first import of colorama while I/O capture is active, colorama will
+ fail in various ways.
+ """
+
+ if not sys.platform.startswith('win32'):
+ return
+ try:
+ import colorama # noqa
+ except ImportError:
+ pass
+
+
+def _readline_workaround():
+ """
+ Ensure readline is imported so that it attaches to the correct stdio
+ handles on Windows.
+
+ Pdb uses readline support where available--when not running from the Python
+ prompt, the readline module is not imported until running the pdb REPL. If
+ running pytest with the --pdb option this means the readline module is not
+ imported until after I/O capture has been started.
+
+ This is a problem for pyreadline, which is often used to implement readline
+ support on Windows, as it does not attach to the correct handles for stdout
+ and/or stdin if they have been redirected by the FDCapture mechanism. This
+ workaround ensures that readline is imported before I/O capture is setup so
+ that it can attach to the actual stdin/out for the console.
+
+ See https://github.com/pytest-dev/pytest/pull/1281
+ """
+
+ if not sys.platform.startswith('win32'):
+ return
+ try:
+ import readline # noqa
+ except ImportError:
+ pass
+
+
+def _py36_windowsconsoleio_workaround(stream):
+ """
+ Python 3.6 implemented unicode console handling for Windows. This works
+ by reading/writing to the raw console handle using
+ ``{Read,Write}ConsoleW``.
+
+ The problem is that we are going to ``dup2`` over the stdio file
+ descriptors when doing ``FDCapture`` and this will ``CloseHandle`` the
+ handles used by Python to write to the console. Though there is still some
+ weirdness and the console handle seems to only be closed randomly and not
+ on the first call to ``CloseHandle``, or maybe it gets reopened with the
+ same handle value when we suspend capturing.
+
+ The workaround in this case will reopen stdio with a different fd which
+ also means a different handle by replicating the logic in
+ "Py_lifecycle.c:initstdio/create_stdio".
+
+ :param stream: in practice ``sys.stdout`` or ``sys.stderr``, but given
+ here as parameter for unittesting purposes.
+
+ See https://github.com/pytest-dev/py/issues/103
+ """
+ if not sys.platform.startswith('win32') or sys.version_info[:2] < (3, 6):
+ return
+
+ # bail out if ``stream`` doesn't seem like a proper ``io`` stream (#2666)
+ if not hasattr(stream, 'buffer'):
+ return
+
+ buffered = hasattr(stream.buffer, 'raw')
+ raw_stdout = stream.buffer.raw if buffered else stream.buffer
+
+ if not isinstance(raw_stdout, io._WindowsConsoleIO):
+ return
+
+ def _reopen_stdio(f, mode):
+ if not buffered and mode[0] == 'w':
+ buffering = 0
+ else:
+ buffering = -1
+
+ return io.TextIOWrapper(
+ open(os.dup(f.fileno()), mode, buffering),
+ f.encoding,
+ f.errors,
+ f.newlines,
+ f.line_buffering)
+
+ sys.__stdin__ = sys.stdin = _reopen_stdio(sys.stdin, 'rb')
+ sys.__stdout__ = sys.stdout = _reopen_stdio(sys.stdout, 'wb')
+ sys.__stderr__ = sys.stderr = _reopen_stdio(sys.stderr, 'wb')
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/compat.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/compat.py
new file mode 100644
index 00000000000..7560fbec397
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/compat.py
@@ -0,0 +1,322 @@
+"""
+python version compatibility code
+"""
+from __future__ import absolute_import, division, print_function
+
+import codecs
+import functools
+import inspect
+import re
+import sys
+
+import py
+
+import _pytest
+from _pytest.outcomes import TEST_OUTCOME
+
+try:
+ import enum
+except ImportError: # pragma: no cover
+ # Only available in Python 3.4+ or as a backport
+ enum = None
+
+
+_PY3 = sys.version_info > (3, 0)
+_PY2 = not _PY3
+
+
+if _PY3:
+ from inspect import signature, Parameter as Parameter
+else:
+ from funcsigs import signature, Parameter as Parameter
+
+
+NoneType = type(None)
+NOTSET = object()
+
+PY35 = sys.version_info[:2] >= (3, 5)
+PY36 = sys.version_info[:2] >= (3, 6)
+MODULE_NOT_FOUND_ERROR = 'ModuleNotFoundError' if PY36 else 'ImportError'
+
+
+def _format_args(func):
+ return str(signature(func))
+
+
+isfunction = inspect.isfunction
+isclass = inspect.isclass
+# used to work around a python2 exception info leak
+exc_clear = getattr(sys, 'exc_clear', lambda: None)
+# The type of re.compile objects is not exposed in Python.
+REGEX_TYPE = type(re.compile(''))
+
+
+def is_generator(func):
+ genfunc = inspect.isgeneratorfunction(func)
+ return genfunc and not iscoroutinefunction(func)
+
+
+def iscoroutinefunction(func):
+ """Return True if func is a decorated coroutine function.
+
+ Note: copied and modified from Python 3.5's builtin couroutines.py to avoid import asyncio directly,
+ which in turns also initializes the "logging" module as side-effect (see issue #8).
+ """
+ return (getattr(func, '_is_coroutine', False) or
+ (hasattr(inspect, 'iscoroutinefunction') and inspect.iscoroutinefunction(func)))
+
+
+def getlocation(function, curdir):
+ fn = py.path.local(inspect.getfile(function))
+ lineno = py.builtin._getcode(function).co_firstlineno
+ if fn.relto(curdir):
+ fn = fn.relto(curdir)
+ return "%s:%d" % (fn, lineno + 1)
+
+
+def num_mock_patch_args(function):
+ """ return number of arguments used up by mock arguments (if any) """
+ patchings = getattr(function, "patchings", None)
+ if not patchings:
+ return 0
+ mock = sys.modules.get("mock", sys.modules.get("unittest.mock", None))
+ if mock is not None:
+ return len([p for p in patchings
+ if not p.attribute_name and p.new is mock.DEFAULT])
+ return len(patchings)
+
+
+def getfuncargnames(function, is_method=False, cls=None):
+ """Returns the names of a function's mandatory arguments.
+
+ This should return the names of all function arguments that:
+ * Aren't bound to an instance or type as in instance or class methods.
+ * Don't have default values.
+ * Aren't bound with functools.partial.
+ * Aren't replaced with mocks.
+
+ The is_method and cls arguments indicate that the function should
+ be treated as a bound method even though it's not unless, only in
+ the case of cls, the function is a static method.
+
+ @RonnyPfannschmidt: This function should be refactored when we
+ revisit fixtures. The fixture mechanism should ask the node for
+ the fixture names, and not try to obtain directly from the
+ function object well after collection has occurred.
+
+ """
+ # The parameters attribute of a Signature object contains an
+ # ordered mapping of parameter names to Parameter instances. This
+ # creates a tuple of the names of the parameters that don't have
+ # defaults.
+ arg_names = tuple(p.name for p in signature(function).parameters.values()
+ if (p.kind is Parameter.POSITIONAL_OR_KEYWORD or
+ p.kind is Parameter.KEYWORD_ONLY) and
+ p.default is Parameter.empty)
+ # If this function should be treated as a bound method even though
+ # it's passed as an unbound method or function, remove the first
+ # parameter name.
+ if (is_method or
+ (cls and not isinstance(cls.__dict__.get(function.__name__, None),
+ staticmethod))):
+ arg_names = arg_names[1:]
+ # Remove any names that will be replaced with mocks.
+ if hasattr(function, "__wrapped__"):
+ arg_names = arg_names[num_mock_patch_args(function):]
+ return arg_names
+
+
+if _PY3:
+ STRING_TYPES = bytes, str
+ UNICODE_TYPES = str,
+
+ if PY35:
+ def _bytes_to_ascii(val):
+ return val.decode('ascii', 'backslashreplace')
+ else:
+ def _bytes_to_ascii(val):
+ if val:
+ # source: http://goo.gl/bGsnwC
+ encoded_bytes, _ = codecs.escape_encode(val)
+ return encoded_bytes.decode('ascii')
+ else:
+ # empty bytes crashes codecs.escape_encode (#1087)
+ return ''
+
+ def ascii_escaped(val):
+ """If val is pure ascii, returns it as a str(). Otherwise, escapes
+ bytes objects into a sequence of escaped bytes:
+
+ b'\xc3\xb4\xc5\xd6' -> u'\\xc3\\xb4\\xc5\\xd6'
+
+ and escapes unicode objects into a sequence of escaped unicode
+ ids, e.g.:
+
+ '4\\nV\\U00043efa\\x0eMXWB\\x1e\\u3028\\u15fd\\xcd\\U0007d944'
+
+ note:
+ the obvious "v.decode('unicode-escape')" will return
+ valid utf-8 unicode if it finds them in bytes, but we
+ want to return escaped bytes for any byte, even if they match
+ a utf-8 string.
+
+ """
+ if isinstance(val, bytes):
+ return _bytes_to_ascii(val)
+ else:
+ return val.encode('unicode_escape').decode('ascii')
+else:
+ STRING_TYPES = bytes, str, unicode
+ UNICODE_TYPES = unicode,
+
+ def ascii_escaped(val):
+ """In py2 bytes and str are the same type, so return if it's a bytes
+ object, return it unchanged if it is a full ascii string,
+ otherwise escape it into its binary form.
+
+ If it's a unicode string, change the unicode characters into
+ unicode escapes.
+
+ """
+ if isinstance(val, bytes):
+ try:
+ return val.encode('ascii')
+ except UnicodeDecodeError:
+ return val.encode('string-escape')
+ else:
+ return val.encode('unicode-escape')
+
+
+def get_real_func(obj):
+ """ gets the real function object of the (possibly) wrapped object by
+ functools.wraps or functools.partial.
+ """
+ start_obj = obj
+ for i in range(100):
+ new_obj = getattr(obj, '__wrapped__', None)
+ if new_obj is None:
+ break
+ obj = new_obj
+ else:
+ raise ValueError(
+ ("could not find real function of {start}"
+ "\nstopped at {current}").format(
+ start=py.io.saferepr(start_obj),
+ current=py.io.saferepr(obj)))
+ if isinstance(obj, functools.partial):
+ obj = obj.func
+ return obj
+
+
+def getfslineno(obj):
+ # xxx let decorators etc specify a sane ordering
+ obj = get_real_func(obj)
+ if hasattr(obj, 'place_as'):
+ obj = obj.place_as
+ fslineno = _pytest._code.getfslineno(obj)
+ assert isinstance(fslineno[1], int), obj
+ return fslineno
+
+
+def getimfunc(func):
+ try:
+ return func.__func__
+ except AttributeError:
+ return func
+
+
+def safe_getattr(object, name, default):
+ """ Like getattr but return default upon any Exception or any OutcomeException.
+
+ Attribute access can potentially fail for 'evil' Python objects.
+ See issue #214.
+ It catches OutcomeException because of #2490 (issue #580), new outcomes are derived from BaseException
+ instead of Exception (for more details check #2707)
+ """
+ try:
+ return getattr(object, name, default)
+ except TEST_OUTCOME:
+ return default
+
+
+def _is_unittest_unexpected_success_a_failure():
+ """Return if the test suite should fail if a @expectedFailure unittest test PASSES.
+
+ From https://docs.python.org/3/library/unittest.html?highlight=unittest#unittest.TestResult.wasSuccessful:
+ Changed in version 3.4: Returns False if there were any
+ unexpectedSuccesses from tests marked with the expectedFailure() decorator.
+ """
+ return sys.version_info >= (3, 4)
+
+
+if _PY3:
+ def safe_str(v):
+ """returns v as string"""
+ return str(v)
+else:
+ def safe_str(v):
+ """returns v as string, converting to ascii if necessary"""
+ try:
+ return str(v)
+ except UnicodeError:
+ if not isinstance(v, unicode):
+ v = unicode(v)
+ errors = 'replace'
+ return v.encode('utf-8', errors)
+
+
+COLLECT_FAKEMODULE_ATTRIBUTES = (
+ 'Collector',
+ 'Module',
+ 'Generator',
+ 'Function',
+ 'Instance',
+ 'Session',
+ 'Item',
+ 'Class',
+ 'File',
+ '_fillfuncargs',
+)
+
+
+def _setup_collect_fakemodule():
+ from types import ModuleType
+ import pytest
+ pytest.collect = ModuleType('pytest.collect')
+ pytest.collect.__all__ = [] # used for setns
+ for attr in COLLECT_FAKEMODULE_ATTRIBUTES:
+ setattr(pytest.collect, attr, getattr(pytest, attr))
+
+
+if _PY2:
+ # Without this the test_dupfile_on_textio will fail, otherwise CaptureIO could directly inherit from StringIO.
+ from py.io import TextIO
+
+ class CaptureIO(TextIO):
+
+ @property
+ def encoding(self):
+ return getattr(self, '_encoding', 'UTF-8')
+
+else:
+ import io
+
+ class CaptureIO(io.TextIOWrapper):
+ def __init__(self):
+ super(CaptureIO, self).__init__(
+ io.BytesIO(),
+ encoding='UTF-8', newline='', write_through=True,
+ )
+
+ def getvalue(self):
+ return self.buffer.getvalue().decode('UTF-8')
+
+
+class FuncargnamesCompatAttr(object):
+ """ helper class so that Metafunc, Function and FixtureRequest
+ don't need to each define the "funcargnames" compatibility attribute.
+ """
+ @property
+ def funcargnames(self):
+ """ alias attribute for ``fixturenames`` for pre-2.3 compatibility"""
+ return self.fixturenames
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/config.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/config.py
new file mode 100644
index 00000000000..499c8079d41
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/config.py
@@ -0,0 +1,1400 @@
+""" command line options, ini-file and conftest.py processing. """
+from __future__ import absolute_import, division, print_function
+import argparse
+import shlex
+import traceback
+import types
+import warnings
+
+import six
+import py
+# DON't import pytest here because it causes import cycle troubles
+import sys
+import os
+import _pytest._code
+import _pytest.hookspec # the extension point definitions
+import _pytest.assertion
+from pluggy import PluginManager, HookimplMarker, HookspecMarker
+from _pytest.compat import safe_str
+
+hookimpl = HookimplMarker("pytest")
+hookspec = HookspecMarker("pytest")
+
+# pytest startup
+#
+
+
+class ConftestImportFailure(Exception):
+ def __init__(self, path, excinfo):
+ Exception.__init__(self, path, excinfo)
+ self.path = path
+ self.excinfo = excinfo
+
+ def __str__(self):
+ etype, evalue, etb = self.excinfo
+ formatted = traceback.format_tb(etb)
+ # The level of the tracebacks we want to print is hand crafted :(
+ return repr(evalue) + '\n' + ''.join(formatted[2:])
+
+
+def main(args=None, plugins=None):
+ """ return exit code, after performing an in-process test run.
+
+ :arg args: list of command line arguments.
+
+ :arg plugins: list of plugin objects to be auto-registered during
+ initialization.
+ """
+ try:
+ try:
+ config = _prepareconfig(args, plugins)
+ except ConftestImportFailure as e:
+ tw = py.io.TerminalWriter(sys.stderr)
+ for line in traceback.format_exception(*e.excinfo):
+ tw.line(line.rstrip(), red=True)
+ tw.line("ERROR: could not load %s\n" % (e.path), red=True)
+ return 4
+ else:
+ try:
+ return config.hook.pytest_cmdline_main(config=config)
+ finally:
+ config._ensure_unconfigure()
+ except UsageError as e:
+ for msg in e.args:
+ sys.stderr.write("ERROR: %s\n" % (msg,))
+ return 4
+
+
+class cmdline: # compatibility namespace
+ main = staticmethod(main)
+
+
+class UsageError(Exception):
+ """ error in pytest usage or invocation"""
+
+
+class PrintHelp(Exception):
+ """Raised when pytest should print it's help to skip the rest of the
+ argument parsing and validation."""
+ pass
+
+
+def filename_arg(path, optname):
+ """ Argparse type validator for filename arguments.
+
+ :path: path of filename
+ :optname: name of the option
+ """
+ if os.path.isdir(path):
+ raise UsageError("{0} must be a filename, given: {1}".format(optname, path))
+ return path
+
+
+def directory_arg(path, optname):
+ """Argparse type validator for directory arguments.
+
+ :path: path of directory
+ :optname: name of the option
+ """
+ if not os.path.isdir(path):
+ raise UsageError("{0} must be a directory, given: {1}".format(optname, path))
+ return path
+
+
+default_plugins = (
+ "mark main terminal runner python fixtures debugging unittest capture skipping "
+ "tmpdir monkeypatch recwarn pastebin helpconfig nose assertion "
+ "junitxml resultlog doctest cacheprovider freeze_support "
+ "setuponly setupplan warnings logging").split()
+
+
+builtin_plugins = set(default_plugins)
+builtin_plugins.add("pytester")
+
+
+def get_config():
+ # subsequent calls to main will create a fresh instance
+ pluginmanager = PytestPluginManager()
+ config = Config(pluginmanager)
+ for spec in default_plugins:
+ pluginmanager.import_plugin(spec)
+ return config
+
+
+def get_plugin_manager():
+ """
+ Obtain a new instance of the
+ :py:class:`_pytest.config.PytestPluginManager`, with default plugins
+ already loaded.
+
+ This function can be used by integration with other tools, like hooking
+ into pytest to run tests into an IDE.
+ """
+ return get_config().pluginmanager
+
+
+def _prepareconfig(args=None, plugins=None):
+ warning = None
+ if args is None:
+ args = sys.argv[1:]
+ elif isinstance(args, py.path.local):
+ args = [str(args)]
+ elif not isinstance(args, (tuple, list)):
+ if not isinstance(args, str):
+ raise ValueError("not a string or argument list: %r" % (args,))
+ args = shlex.split(args, posix=sys.platform != "win32")
+ from _pytest import deprecated
+ warning = deprecated.MAIN_STR_ARGS
+ config = get_config()
+ pluginmanager = config.pluginmanager
+ try:
+ if plugins:
+ for plugin in plugins:
+ if isinstance(plugin, six.string_types):
+ pluginmanager.consider_pluginarg(plugin)
+ else:
+ pluginmanager.register(plugin)
+ if warning:
+ config.warn('C1', warning)
+ return pluginmanager.hook.pytest_cmdline_parse(
+ pluginmanager=pluginmanager, args=args)
+ except BaseException:
+ config._ensure_unconfigure()
+ raise
+
+
+class PytestPluginManager(PluginManager):
+ """
+ Overwrites :py:class:`pluggy.PluginManager <pluggy.PluginManager>` to add pytest-specific
+ functionality:
+
+ * loading plugins from the command line, ``PYTEST_PLUGIN`` env variable and
+ ``pytest_plugins`` global variables found in plugins being loaded;
+ * ``conftest.py`` loading during start-up;
+ """
+
+ def __init__(self):
+ super(PytestPluginManager, self).__init__("pytest", implprefix="pytest_")
+ self._conftest_plugins = set()
+
+ # state related to local conftest plugins
+ self._path2confmods = {}
+ self._conftestpath2mod = {}
+ self._confcutdir = None
+ self._noconftest = False
+ self._duplicatepaths = set()
+
+ self.add_hookspecs(_pytest.hookspec)
+ self.register(self)
+ if os.environ.get('PYTEST_DEBUG'):
+ err = sys.stderr
+ encoding = getattr(err, 'encoding', 'utf8')
+ try:
+ err = py.io.dupfile(err, encoding=encoding)
+ except Exception:
+ pass
+ self.trace.root.setwriter(err.write)
+ self.enable_tracing()
+
+ # Config._consider_importhook will set a real object if required.
+ self.rewrite_hook = _pytest.assertion.DummyRewriteHook()
+
+ def addhooks(self, module_or_class):
+ """
+ .. deprecated:: 2.8
+
+ Use :py:meth:`pluggy.PluginManager.add_hookspecs <PluginManager.add_hookspecs>`
+ instead.
+ """
+ warning = dict(code="I2",
+ fslocation=_pytest._code.getfslineno(sys._getframe(1)),
+ nodeid=None,
+ message="use pluginmanager.add_hookspecs instead of "
+ "deprecated addhooks() method.")
+ self._warn(warning)
+ return self.add_hookspecs(module_or_class)
+
+ def parse_hookimpl_opts(self, plugin, name):
+ # pytest hooks are always prefixed with pytest_
+ # so we avoid accessing possibly non-readable attributes
+ # (see issue #1073)
+ if not name.startswith("pytest_"):
+ return
+ # ignore some historic special names which can not be hooks anyway
+ if name == "pytest_plugins" or name.startswith("pytest_funcarg__"):
+ return
+
+ method = getattr(plugin, name)
+ opts = super(PytestPluginManager, self).parse_hookimpl_opts(plugin, name)
+ if opts is not None:
+ for name in ("tryfirst", "trylast", "optionalhook", "hookwrapper"):
+ opts.setdefault(name, hasattr(method, name))
+ return opts
+
+ def parse_hookspec_opts(self, module_or_class, name):
+ opts = super(PytestPluginManager, self).parse_hookspec_opts(
+ module_or_class, name)
+ if opts is None:
+ method = getattr(module_or_class, name)
+ if name.startswith("pytest_"):
+ opts = {"firstresult": hasattr(method, "firstresult"),
+ "historic": hasattr(method, "historic")}
+ return opts
+
+ def register(self, plugin, name=None):
+ if name == 'pytest_catchlog':
+ self._warn('pytest-catchlog plugin has been merged into the core, '
+ 'please remove it from your requirements.')
+ return
+ ret = super(PytestPluginManager, self).register(plugin, name)
+ if ret:
+ self.hook.pytest_plugin_registered.call_historic(
+ kwargs=dict(plugin=plugin, manager=self))
+
+ if isinstance(plugin, types.ModuleType):
+ self.consider_module(plugin)
+ return ret
+
+ def getplugin(self, name):
+ # support deprecated naming because plugins (xdist e.g.) use it
+ return self.get_plugin(name)
+
+ def hasplugin(self, name):
+ """Return True if the plugin with the given name is registered."""
+ return bool(self.get_plugin(name))
+
+ def pytest_configure(self, config):
+ # XXX now that the pluginmanager exposes hookimpl(tryfirst...)
+ # we should remove tryfirst/trylast as markers
+ config.addinivalue_line("markers",
+ "tryfirst: mark a hook implementation function such that the "
+ "plugin machinery will try to call it first/as early as possible.")
+ config.addinivalue_line("markers",
+ "trylast: mark a hook implementation function such that the "
+ "plugin machinery will try to call it last/as late as possible.")
+
+ def _warn(self, message):
+ kwargs = message if isinstance(message, dict) else {
+ 'code': 'I1',
+ 'message': message,
+ 'fslocation': None,
+ 'nodeid': None,
+ }
+ self.hook.pytest_logwarning.call_historic(kwargs=kwargs)
+
+ #
+ # internal API for local conftest plugin handling
+ #
+ def _set_initial_conftests(self, namespace):
+ """ load initial conftest files given a preparsed "namespace".
+ As conftest files may add their own command line options
+ which have arguments ('--my-opt somepath') we might get some
+ false positives. All builtin and 3rd party plugins will have
+ been loaded, however, so common options will not confuse our logic
+ here.
+ """
+ current = py.path.local()
+ self._confcutdir = current.join(namespace.confcutdir, abs=True) \
+ if namespace.confcutdir else None
+ self._noconftest = namespace.noconftest
+ testpaths = namespace.file_or_dir
+ foundanchor = False
+ for path in testpaths:
+ path = str(path)
+ # remove node-id syntax
+ i = path.find("::")
+ if i != -1:
+ path = path[:i]
+ anchor = current.join(path, abs=1)
+ if exists(anchor): # we found some file object
+ self._try_load_conftest(anchor)
+ foundanchor = True
+ if not foundanchor:
+ self._try_load_conftest(current)
+
+ def _try_load_conftest(self, anchor):
+ self._getconftestmodules(anchor)
+ # let's also consider test* subdirs
+ if anchor.check(dir=1):
+ for x in anchor.listdir("test*"):
+ if x.check(dir=1):
+ self._getconftestmodules(x)
+
+ def _getconftestmodules(self, path):
+ if self._noconftest:
+ return []
+ try:
+ return self._path2confmods[path]
+ except KeyError:
+ if path.isfile():
+ clist = self._getconftestmodules(path.dirpath())
+ else:
+ # XXX these days we may rather want to use config.rootdir
+ # and allow users to opt into looking into the rootdir parent
+ # directories instead of requiring to specify confcutdir
+ clist = []
+ for parent in path.parts():
+ if self._confcutdir and self._confcutdir.relto(parent):
+ continue
+ conftestpath = parent.join("conftest.py")
+ if conftestpath.isfile():
+ mod = self._importconftest(conftestpath)
+ clist.append(mod)
+
+ self._path2confmods[path] = clist
+ return clist
+
+ def _rget_with_confmod(self, name, path):
+ modules = self._getconftestmodules(path)
+ for mod in reversed(modules):
+ try:
+ return mod, getattr(mod, name)
+ except AttributeError:
+ continue
+ raise KeyError(name)
+
+ def _importconftest(self, conftestpath):
+ try:
+ return self._conftestpath2mod[conftestpath]
+ except KeyError:
+ pkgpath = conftestpath.pypkgpath()
+ if pkgpath is None:
+ _ensure_removed_sysmodule(conftestpath.purebasename)
+ try:
+ mod = conftestpath.pyimport()
+ except Exception:
+ raise ConftestImportFailure(conftestpath, sys.exc_info())
+
+ self._conftest_plugins.add(mod)
+ self._conftestpath2mod[conftestpath] = mod
+ dirpath = conftestpath.dirpath()
+ if dirpath in self._path2confmods:
+ for path, mods in self._path2confmods.items():
+ if path and path.relto(dirpath) or path == dirpath:
+ assert mod not in mods
+ mods.append(mod)
+ self.trace("loaded conftestmodule %r" % (mod))
+ self.consider_conftest(mod)
+ return mod
+
+ #
+ # API for bootstrapping plugin loading
+ #
+ #
+
+ def consider_preparse(self, args):
+ for opt1, opt2 in zip(args, args[1:]):
+ if opt1 == "-p":
+ self.consider_pluginarg(opt2)
+
+ def consider_pluginarg(self, arg):
+ if arg.startswith("no:"):
+ name = arg[3:]
+ self.set_blocked(name)
+ if not name.startswith("pytest_"):
+ self.set_blocked("pytest_" + name)
+ else:
+ self.import_plugin(arg)
+
+ def consider_conftest(self, conftestmodule):
+ self.register(conftestmodule, name=conftestmodule.__file__)
+
+ def consider_env(self):
+ self._import_plugin_specs(os.environ.get("PYTEST_PLUGINS"))
+
+ def consider_module(self, mod):
+ self._import_plugin_specs(getattr(mod, 'pytest_plugins', []))
+
+ def _import_plugin_specs(self, spec):
+ plugins = _get_plugin_specs_as_list(spec)
+ for import_spec in plugins:
+ self.import_plugin(import_spec)
+
+ def import_plugin(self, modname):
+ # most often modname refers to builtin modules, e.g. "pytester",
+ # "terminal" or "capture". Those plugins are registered under their
+ # basename for historic purposes but must be imported with the
+ # _pytest prefix.
+ assert isinstance(modname, (six.text_type, str)), "module name as text required, got %r" % modname
+ modname = str(modname)
+ if self.is_blocked(modname) or self.get_plugin(modname) is not None:
+ return
+ if modname in builtin_plugins:
+ importspec = "_pytest." + modname
+ else:
+ importspec = modname
+ self.rewrite_hook.mark_rewrite(importspec)
+ try:
+ __import__(importspec)
+ except ImportError as e:
+ new_exc_type = ImportError
+ new_exc_message = 'Error importing plugin "%s": %s' % (modname, safe_str(e.args[0]))
+ new_exc = new_exc_type(new_exc_message)
+
+ six.reraise(new_exc_type, new_exc, sys.exc_info()[2])
+
+ except Exception as e:
+ import pytest
+ if not hasattr(pytest, 'skip') or not isinstance(e, pytest.skip.Exception):
+ raise
+ self._warn("skipped plugin %r: %s" % ((modname, e.msg)))
+ else:
+ mod = sys.modules[importspec]
+ self.register(mod, modname)
+
+
+def _get_plugin_specs_as_list(specs):
+ """
+ Parses a list of "plugin specs" and returns a list of plugin names.
+
+ Plugin specs can be given as a list of strings separated by "," or already as a list/tuple in
+ which case it is returned as a list. Specs can also be `None` in which case an
+ empty list is returned.
+ """
+ if specs is not None:
+ if isinstance(specs, str):
+ specs = specs.split(',') if specs else []
+ if not isinstance(specs, (list, tuple)):
+ raise UsageError("Plugin specs must be a ','-separated string or a "
+ "list/tuple of strings for plugin names. Given: %r" % specs)
+ return list(specs)
+ return []
+
+
+class Parser:
+ """ Parser for command line arguments and ini-file values.
+
+ :ivar extra_info: dict of generic param -> value to display in case
+ there's an error processing the command line arguments.
+ """
+
+ def __init__(self, usage=None, processopt=None):
+ self._anonymous = OptionGroup("custom options", parser=self)
+ self._groups = []
+ self._processopt = processopt
+ self._usage = usage
+ self._inidict = {}
+ self._ininames = []
+ self.extra_info = {}
+
+ def processoption(self, option):
+ if self._processopt:
+ if option.dest:
+ self._processopt(option)
+
+ def getgroup(self, name, description="", after=None):
+ """ get (or create) a named option Group.
+
+ :name: name of the option group.
+ :description: long description for --help output.
+ :after: name of other group, used for ordering --help output.
+
+ The returned group object has an ``addoption`` method with the same
+ signature as :py:func:`parser.addoption
+ <_pytest.config.Parser.addoption>` but will be shown in the
+ respective group in the output of ``pytest. --help``.
+ """
+ for group in self._groups:
+ if group.name == name:
+ return group
+ group = OptionGroup(name, description, parser=self)
+ i = 0
+ for i, grp in enumerate(self._groups):
+ if grp.name == after:
+ break
+ self._groups.insert(i + 1, group)
+ return group
+
+ def addoption(self, *opts, **attrs):
+ """ register a command line option.
+
+ :opts: option names, can be short or long options.
+ :attrs: same attributes which the ``add_option()`` function of the
+ `argparse library
+ <http://docs.python.org/2/library/argparse.html>`_
+ accepts.
+
+ After command line parsing options are available on the pytest config
+ object via ``config.option.NAME`` where ``NAME`` is usually set
+ by passing a ``dest`` attribute, for example
+ ``addoption("--long", dest="NAME", ...)``.
+ """
+ self._anonymous.addoption(*opts, **attrs)
+
+ def parse(self, args, namespace=None):
+ from _pytest._argcomplete import try_argcomplete
+ self.optparser = self._getparser()
+ try_argcomplete(self.optparser)
+ return self.optparser.parse_args([str(x) for x in args], namespace=namespace)
+
+ def _getparser(self):
+ from _pytest._argcomplete import filescompleter
+ optparser = MyOptionParser(self, self.extra_info)
+ groups = self._groups + [self._anonymous]
+ for group in groups:
+ if group.options:
+ desc = group.description or group.name
+ arggroup = optparser.add_argument_group(desc)
+ for option in group.options:
+ n = option.names()
+ a = option.attrs()
+ arggroup.add_argument(*n, **a)
+ # bash like autocompletion for dirs (appending '/')
+ optparser.add_argument(FILE_OR_DIR, nargs='*').completer = filescompleter
+ return optparser
+
+ def parse_setoption(self, args, option, namespace=None):
+ parsedoption = self.parse(args, namespace=namespace)
+ for name, value in parsedoption.__dict__.items():
+ setattr(option, name, value)
+ return getattr(parsedoption, FILE_OR_DIR)
+
+ def parse_known_args(self, args, namespace=None):
+ """parses and returns a namespace object with known arguments at this
+ point.
+ """
+ return self.parse_known_and_unknown_args(args, namespace=namespace)[0]
+
+ def parse_known_and_unknown_args(self, args, namespace=None):
+ """parses and returns a namespace object with known arguments, and
+ the remaining arguments unknown at this point.
+ """
+ optparser = self._getparser()
+ args = [str(x) for x in args]
+ return optparser.parse_known_args(args, namespace=namespace)
+
+ def addini(self, name, help, type=None, default=None):
+ """ register an ini-file option.
+
+ :name: name of the ini-variable
+ :type: type of the variable, can be ``pathlist``, ``args``, ``linelist``
+ or ``bool``.
+ :default: default value if no ini-file option exists but is queried.
+
+ The value of ini-variables can be retrieved via a call to
+ :py:func:`config.getini(name) <_pytest.config.Config.getini>`.
+ """
+ assert type in (None, "pathlist", "args", "linelist", "bool")
+ self._inidict[name] = (help, type, default)
+ self._ininames.append(name)
+
+
+class ArgumentError(Exception):
+ """
+ Raised if an Argument instance is created with invalid or
+ inconsistent arguments.
+ """
+
+ def __init__(self, msg, option):
+ self.msg = msg
+ self.option_id = str(option)
+
+ def __str__(self):
+ if self.option_id:
+ return "option %s: %s" % (self.option_id, self.msg)
+ else:
+ return self.msg
+
+
+class Argument:
+ """class that mimics the necessary behaviour of optparse.Option
+
+ its currently a least effort implementation
+ and ignoring choices and integer prefixes
+ https://docs.python.org/3/library/optparse.html#optparse-standard-option-types
+ """
+ _typ_map = {
+ 'int': int,
+ 'string': str,
+ 'float': float,
+ 'complex': complex,
+ }
+
+ def __init__(self, *names, **attrs):
+ """store parms in private vars for use in add_argument"""
+ self._attrs = attrs
+ self._short_opts = []
+ self._long_opts = []
+ self.dest = attrs.get('dest')
+ if '%default' in (attrs.get('help') or ''):
+ warnings.warn(
+ 'pytest now uses argparse. "%default" should be'
+ ' changed to "%(default)s" ',
+ DeprecationWarning,
+ stacklevel=3)
+ try:
+ typ = attrs['type']
+ except KeyError:
+ pass
+ else:
+ # this might raise a keyerror as well, don't want to catch that
+ if isinstance(typ, six.string_types):
+ if typ == 'choice':
+ warnings.warn(
+ 'type argument to addoption() is a string %r.'
+ ' For parsearg this is optional and when supplied'
+ ' should be a type.'
+ ' (options: %s)' % (typ, names),
+ DeprecationWarning,
+ stacklevel=3)
+ # argparse expects a type here take it from
+ # the type of the first element
+ attrs['type'] = type(attrs['choices'][0])
+ else:
+ warnings.warn(
+ 'type argument to addoption() is a string %r.'
+ ' For parsearg this should be a type.'
+ ' (options: %s)' % (typ, names),
+ DeprecationWarning,
+ stacklevel=3)
+ attrs['type'] = Argument._typ_map[typ]
+ # used in test_parseopt -> test_parse_defaultgetter
+ self.type = attrs['type']
+ else:
+ self.type = typ
+ try:
+ # attribute existence is tested in Config._processopt
+ self.default = attrs['default']
+ except KeyError:
+ pass
+ self._set_opt_strings(names)
+ if not self.dest:
+ if self._long_opts:
+ self.dest = self._long_opts[0][2:].replace('-', '_')
+ else:
+ try:
+ self.dest = self._short_opts[0][1:]
+ except IndexError:
+ raise ArgumentError(
+ 'need a long or short option', self)
+
+ def names(self):
+ return self._short_opts + self._long_opts
+
+ def attrs(self):
+ # update any attributes set by processopt
+ attrs = 'default dest help'.split()
+ if self.dest:
+ attrs.append(self.dest)
+ for attr in attrs:
+ try:
+ self._attrs[attr] = getattr(self, attr)
+ except AttributeError:
+ pass
+ if self._attrs.get('help'):
+ a = self._attrs['help']
+ a = a.replace('%default', '%(default)s')
+ # a = a.replace('%prog', '%(prog)s')
+ self._attrs['help'] = a
+ return self._attrs
+
+ def _set_opt_strings(self, opts):
+ """directly from optparse
+
+ might not be necessary as this is passed to argparse later on"""
+ for opt in opts:
+ if len(opt) < 2:
+ raise ArgumentError(
+ "invalid option string %r: "
+ "must be at least two characters long" % opt, self)
+ elif len(opt) == 2:
+ if not (opt[0] == "-" and opt[1] != "-"):
+ raise ArgumentError(
+ "invalid short option string %r: "
+ "must be of the form -x, (x any non-dash char)" % opt,
+ self)
+ self._short_opts.append(opt)
+ else:
+ if not (opt[0:2] == "--" and opt[2] != "-"):
+ raise ArgumentError(
+ "invalid long option string %r: "
+ "must start with --, followed by non-dash" % opt,
+ self)
+ self._long_opts.append(opt)
+
+ def __repr__(self):
+ args = []
+ if self._short_opts:
+ args += ['_short_opts: ' + repr(self._short_opts)]
+ if self._long_opts:
+ args += ['_long_opts: ' + repr(self._long_opts)]
+ args += ['dest: ' + repr(self.dest)]
+ if hasattr(self, 'type'):
+ args += ['type: ' + repr(self.type)]
+ if hasattr(self, 'default'):
+ args += ['default: ' + repr(self.default)]
+ return 'Argument({0})'.format(', '.join(args))
+
+
+class OptionGroup:
+ def __init__(self, name, description="", parser=None):
+ self.name = name
+ self.description = description
+ self.options = []
+ self.parser = parser
+
+ def addoption(self, *optnames, **attrs):
+ """ add an option to this group.
+
+ if a shortened version of a long option is specified it will
+ be suppressed in the help. addoption('--twowords', '--two-words')
+ results in help showing '--two-words' only, but --twowords gets
+ accepted **and** the automatic destination is in args.twowords
+ """
+ conflict = set(optnames).intersection(
+ name for opt in self.options for name in opt.names())
+ if conflict:
+ raise ValueError("option names %s already added" % conflict)
+ option = Argument(*optnames, **attrs)
+ self._addoption_instance(option, shortupper=False)
+
+ def _addoption(self, *optnames, **attrs):
+ option = Argument(*optnames, **attrs)
+ self._addoption_instance(option, shortupper=True)
+
+ def _addoption_instance(self, option, shortupper=False):
+ if not shortupper:
+ for opt in option._short_opts:
+ if opt[0] == '-' and opt[1].islower():
+ raise ValueError("lowercase shortoptions reserved")
+ if self.parser:
+ self.parser.processoption(option)
+ self.options.append(option)
+
+
+class MyOptionParser(argparse.ArgumentParser):
+ def __init__(self, parser, extra_info=None):
+ if not extra_info:
+ extra_info = {}
+ self._parser = parser
+ argparse.ArgumentParser.__init__(self, usage=parser._usage,
+ add_help=False, formatter_class=DropShorterLongHelpFormatter)
+ # extra_info is a dict of (param -> value) to display if there's
+ # an usage error to provide more contextual information to the user
+ self.extra_info = extra_info
+
+ def parse_args(self, args=None, namespace=None):
+ """allow splitting of positional arguments"""
+ args, argv = self.parse_known_args(args, namespace)
+ if argv:
+ for arg in argv:
+ if arg and arg[0] == '-':
+ lines = ['unrecognized arguments: %s' % (' '.join(argv))]
+ for k, v in sorted(self.extra_info.items()):
+ lines.append(' %s: %s' % (k, v))
+ self.error('\n'.join(lines))
+ getattr(args, FILE_OR_DIR).extend(argv)
+ return args
+
+
+class DropShorterLongHelpFormatter(argparse.HelpFormatter):
+ """shorten help for long options that differ only in extra hyphens
+
+ - collapse **long** options that are the same except for extra hyphens
+ - special action attribute map_long_option allows surpressing additional
+ long options
+ - shortcut if there are only two options and one of them is a short one
+ - cache result on action object as this is called at least 2 times
+ """
+
+ def _format_action_invocation(self, action):
+ orgstr = argparse.HelpFormatter._format_action_invocation(self, action)
+ if orgstr and orgstr[0] != '-': # only optional arguments
+ return orgstr
+ res = getattr(action, '_formatted_action_invocation', None)
+ if res:
+ return res
+ options = orgstr.split(', ')
+ if len(options) == 2 and (len(options[0]) == 2 or len(options[1]) == 2):
+ # a shortcut for '-h, --help' or '--abc', '-a'
+ action._formatted_action_invocation = orgstr
+ return orgstr
+ return_list = []
+ option_map = getattr(action, 'map_long_option', {})
+ if option_map is None:
+ option_map = {}
+ short_long = {}
+ for option in options:
+ if len(option) == 2 or option[2] == ' ':
+ continue
+ if not option.startswith('--'):
+ raise ArgumentError('long optional argument without "--": [%s]'
+ % (option), self)
+ xxoption = option[2:]
+ if xxoption.split()[0] not in option_map:
+ shortened = xxoption.replace('-', '')
+ if shortened not in short_long or \
+ len(short_long[shortened]) < len(xxoption):
+ short_long[shortened] = xxoption
+ # now short_long has been filled out to the longest with dashes
+ # **and** we keep the right option ordering from add_argument
+ for option in options:
+ if len(option) == 2 or option[2] == ' ':
+ return_list.append(option)
+ if option[2:] == short_long.get(option.replace('-', '')):
+ return_list.append(option.replace(' ', '=', 1))
+ action._formatted_action_invocation = ', '.join(return_list)
+ return action._formatted_action_invocation
+
+
+def _ensure_removed_sysmodule(modname):
+ try:
+ del sys.modules[modname]
+ except KeyError:
+ pass
+
+
+class CmdOptions(object):
+ """ holds cmdline options as attributes."""
+
+ def __init__(self, values=()):
+ self.__dict__.update(values)
+
+ def __repr__(self):
+ return "<CmdOptions %r>" % (self.__dict__,)
+
+ def copy(self):
+ return CmdOptions(self.__dict__)
+
+
+class Notset:
+ def __repr__(self):
+ return "<NOTSET>"
+
+
+notset = Notset()
+FILE_OR_DIR = 'file_or_dir'
+
+
+def _iter_rewritable_modules(package_files):
+ for fn in package_files:
+ is_simple_module = '/' not in fn and fn.endswith('.py')
+ is_package = fn.count('/') == 1 and fn.endswith('__init__.py')
+ if is_simple_module:
+ module_name, _ = os.path.splitext(fn)
+ yield module_name
+ elif is_package:
+ package_name = os.path.dirname(fn)
+ yield package_name
+
+
+class Config(object):
+ """ access to configuration values, pluginmanager and plugin hooks. """
+
+ def __init__(self, pluginmanager):
+ #: access to command line option as attributes.
+ #: (deprecated), use :py:func:`getoption() <_pytest.config.Config.getoption>` instead
+ self.option = CmdOptions()
+ _a = FILE_OR_DIR
+ self._parser = Parser(
+ usage="%%(prog)s [options] [%s] [%s] [...]" % (_a, _a),
+ processopt=self._processopt,
+ )
+ #: a pluginmanager instance
+ self.pluginmanager = pluginmanager
+ self.trace = self.pluginmanager.trace.root.get("config")
+ self.hook = self.pluginmanager.hook
+ self._inicache = {}
+ self._override_ini = ()
+ self._opt2dest = {}
+ self._cleanup = []
+ self._warn = self.pluginmanager._warn
+ self.pluginmanager.register(self, "pytestconfig")
+ self._configured = False
+
+ def do_setns(dic):
+ import pytest
+ setns(pytest, dic)
+
+ self.hook.pytest_namespace.call_historic(do_setns, {})
+ self.hook.pytest_addoption.call_historic(kwargs=dict(parser=self._parser))
+
+ def add_cleanup(self, func):
+ """ Add a function to be called when the config object gets out of
+ use (usually coninciding with pytest_unconfigure)."""
+ self._cleanup.append(func)
+
+ def _do_configure(self):
+ assert not self._configured
+ self._configured = True
+ self.hook.pytest_configure.call_historic(kwargs=dict(config=self))
+
+ def _ensure_unconfigure(self):
+ if self._configured:
+ self._configured = False
+ self.hook.pytest_unconfigure(config=self)
+ self.hook.pytest_configure._call_history = []
+ while self._cleanup:
+ fin = self._cleanup.pop()
+ fin()
+
+ def warn(self, code, message, fslocation=None, nodeid=None):
+ """ generate a warning for this test session. """
+ self.hook.pytest_logwarning.call_historic(kwargs=dict(
+ code=code, message=message,
+ fslocation=fslocation, nodeid=nodeid))
+
+ def get_terminal_writer(self):
+ return self.pluginmanager.get_plugin("terminalreporter")._tw
+
+ def pytest_cmdline_parse(self, pluginmanager, args):
+ # REF1 assert self == pluginmanager.config, (self, pluginmanager.config)
+ self.parse(args)
+ return self
+
+ def notify_exception(self, excinfo, option=None):
+ if option and option.fulltrace:
+ style = "long"
+ else:
+ style = "native"
+ excrepr = excinfo.getrepr(funcargs=True,
+ showlocals=getattr(option, 'showlocals', False),
+ style=style,
+ )
+ res = self.hook.pytest_internalerror(excrepr=excrepr,
+ excinfo=excinfo)
+ if not any(res):
+ for line in str(excrepr).split("\n"):
+ sys.stderr.write("INTERNALERROR> %s\n" % line)
+ sys.stderr.flush()
+
+ def cwd_relative_nodeid(self, nodeid):
+ # nodeid's are relative to the rootpath, compute relative to cwd
+ if self.invocation_dir != self.rootdir:
+ fullpath = self.rootdir.join(nodeid)
+ nodeid = self.invocation_dir.bestrelpath(fullpath)
+ return nodeid
+
+ @classmethod
+ def fromdictargs(cls, option_dict, args):
+ """ constructor useable for subprocesses. """
+ config = get_config()
+ config.option.__dict__.update(option_dict)
+ config.parse(args, addopts=False)
+ for x in config.option.plugins:
+ config.pluginmanager.consider_pluginarg(x)
+ return config
+
+ def _processopt(self, opt):
+ for name in opt._short_opts + opt._long_opts:
+ self._opt2dest[name] = opt.dest
+
+ if hasattr(opt, 'default') and opt.dest:
+ if not hasattr(self.option, opt.dest):
+ setattr(self.option, opt.dest, opt.default)
+
+ @hookimpl(trylast=True)
+ def pytest_load_initial_conftests(self, early_config):
+ self.pluginmanager._set_initial_conftests(early_config.known_args_namespace)
+
+ def _initini(self, args):
+ ns, unknown_args = self._parser.parse_known_and_unknown_args(args, namespace=self.option.copy())
+ r = determine_setup(ns.inifilename, ns.file_or_dir + unknown_args, warnfunc=self.warn)
+ self.rootdir, self.inifile, self.inicfg = r
+ self._parser.extra_info['rootdir'] = self.rootdir
+ self._parser.extra_info['inifile'] = self.inifile
+ self.invocation_dir = py.path.local()
+ self._parser.addini('addopts', 'extra command line options', 'args')
+ self._parser.addini('minversion', 'minimally required pytest version')
+ self._override_ini = ns.override_ini or ()
+
+ def _consider_importhook(self, args):
+ """Install the PEP 302 import hook if using assertion rewriting.
+
+ Needs to parse the --assert=<mode> option from the commandline
+ and find all the installed plugins to mark them for rewriting
+ by the importhook.
+ """
+ ns, unknown_args = self._parser.parse_known_and_unknown_args(args)
+ mode = ns.assertmode
+ if mode == 'rewrite':
+ try:
+ hook = _pytest.assertion.install_importhook(self)
+ except SystemError:
+ mode = 'plain'
+ else:
+ self._mark_plugins_for_rewrite(hook)
+ self._warn_about_missing_assertion(mode)
+
+ def _mark_plugins_for_rewrite(self, hook):
+ """
+ Given an importhook, mark for rewrite any top-level
+ modules or packages in the distribution package for
+ all pytest plugins.
+ """
+ import pkg_resources
+ self.pluginmanager.rewrite_hook = hook
+
+ # 'RECORD' available for plugins installed normally (pip install)
+ # 'SOURCES.txt' available for plugins installed in dev mode (pip install -e)
+ # for installed plugins 'SOURCES.txt' returns an empty list, and vice-versa
+ # so it shouldn't be an issue
+ metadata_files = 'RECORD', 'SOURCES.txt'
+
+ package_files = (
+ entry.split(',')[0]
+ for entrypoint in pkg_resources.iter_entry_points('pytest11')
+ for metadata in metadata_files
+ for entry in entrypoint.dist._get_metadata(metadata)
+ )
+
+ for name in _iter_rewritable_modules(package_files):
+ hook.mark_rewrite(name)
+
+ def _warn_about_missing_assertion(self, mode):
+ try:
+ assert False
+ except AssertionError:
+ pass
+ else:
+ if mode == 'plain':
+ sys.stderr.write("WARNING: ASSERTIONS ARE NOT EXECUTED"
+ " and FAILING TESTS WILL PASS. Are you"
+ " using python -O?")
+ else:
+ sys.stderr.write("WARNING: assertions not in test modules or"
+ " plugins will be ignored"
+ " because assert statements are not executed "
+ "by the underlying Python interpreter "
+ "(are you using python -O?)\n")
+
+ def _preparse(self, args, addopts=True):
+ if addopts:
+ args[:] = shlex.split(os.environ.get('PYTEST_ADDOPTS', '')) + args
+ self._initini(args)
+ if addopts:
+ args[:] = self.getini("addopts") + args
+ self._checkversion()
+ self._consider_importhook(args)
+ self.pluginmanager.consider_preparse(args)
+ self.pluginmanager.load_setuptools_entrypoints('pytest11')
+ self.pluginmanager.consider_env()
+ self.known_args_namespace = ns = self._parser.parse_known_args(args, namespace=self.option.copy())
+ if self.known_args_namespace.confcutdir is None and self.inifile:
+ confcutdir = py.path.local(self.inifile).dirname
+ self.known_args_namespace.confcutdir = confcutdir
+ try:
+ self.hook.pytest_load_initial_conftests(early_config=self,
+ args=args, parser=self._parser)
+ except ConftestImportFailure:
+ e = sys.exc_info()[1]
+ if ns.help or ns.version:
+ # we don't want to prevent --help/--version to work
+ # so just let is pass and print a warning at the end
+ self._warn("could not load initial conftests (%s)\n" % e.path)
+ else:
+ raise
+
+ def _checkversion(self):
+ import pytest
+ minver = self.inicfg.get('minversion', None)
+ if minver:
+ ver = minver.split(".")
+ myver = pytest.__version__.split(".")
+ if myver < ver:
+ raise pytest.UsageError(
+ "%s:%d: requires pytest-%s, actual pytest-%s'" % (
+ self.inicfg.config.path, self.inicfg.lineof('minversion'),
+ minver, pytest.__version__))
+
+ def parse(self, args, addopts=True):
+ # parse given cmdline arguments into this config object.
+ assert not hasattr(self, 'args'), (
+ "can only parse cmdline args at most once per Config object")
+ self._origargs = args
+ self.hook.pytest_addhooks.call_historic(
+ kwargs=dict(pluginmanager=self.pluginmanager))
+ self._preparse(args, addopts=addopts)
+ # XXX deprecated hook:
+ self.hook.pytest_cmdline_preparse(config=self, args=args)
+ self._parser.after_preparse = True
+ try:
+ args = self._parser.parse_setoption(args, self.option, namespace=self.option)
+ if not args:
+ cwd = os.getcwd()
+ if cwd == self.rootdir:
+ args = self.getini('testpaths')
+ if not args:
+ args = [cwd]
+ self.args = args
+ except PrintHelp:
+ pass
+
+ def addinivalue_line(self, name, line):
+ """ add a line to an ini-file option. The option must have been
+ declared but might not yet be set in which case the line becomes the
+ the first line in its value. """
+ x = self.getini(name)
+ assert isinstance(x, list)
+ x.append(line) # modifies the cached list inline
+
+ def getini(self, name):
+ """ return configuration value from an :ref:`ini file <inifiles>`. If the
+ specified name hasn't been registered through a prior
+ :py:func:`parser.addini <_pytest.config.Parser.addini>`
+ call (usually from a plugin), a ValueError is raised. """
+ try:
+ return self._inicache[name]
+ except KeyError:
+ self._inicache[name] = val = self._getini(name)
+ return val
+
+ def _getini(self, name):
+ try:
+ description, type, default = self._parser._inidict[name]
+ except KeyError:
+ raise ValueError("unknown configuration value: %r" % (name,))
+ value = self._get_override_ini_value(name)
+ if value is None:
+ try:
+ value = self.inicfg[name]
+ except KeyError:
+ if default is not None:
+ return default
+ if type is None:
+ return ''
+ return []
+ if type == "pathlist":
+ dp = py.path.local(self.inicfg.config.path).dirpath()
+ values = []
+ for relpath in shlex.split(value):
+ values.append(dp.join(relpath, abs=True))
+ return values
+ elif type == "args":
+ return shlex.split(value)
+ elif type == "linelist":
+ return [t for t in map(lambda x: x.strip(), value.split("\n")) if t]
+ elif type == "bool":
+ return bool(_strtobool(value.strip()))
+ else:
+ assert type is None
+ return value
+
+ def _getconftest_pathlist(self, name, path):
+ try:
+ mod, relroots = self.pluginmanager._rget_with_confmod(name, path)
+ except KeyError:
+ return None
+ modpath = py.path.local(mod.__file__).dirpath()
+ values = []
+ for relroot in relroots:
+ if not isinstance(relroot, py.path.local):
+ relroot = relroot.replace("/", py.path.local.sep)
+ relroot = modpath.join(relroot, abs=True)
+ values.append(relroot)
+ return values
+
+ def _get_override_ini_value(self, name):
+ value = None
+ # override_ini is a list of list, to support both -o foo1=bar1 foo2=bar2 and
+ # and -o foo1=bar1 -o foo2=bar2 options
+ # always use the last item if multiple value set for same ini-name,
+ # e.g. -o foo=bar1 -o foo=bar2 will set foo to bar2
+ for ini_config_list in self._override_ini:
+ for ini_config in ini_config_list:
+ try:
+ (key, user_ini_value) = ini_config.split("=", 1)
+ except ValueError:
+ raise UsageError("-o/--override-ini expects option=value style.")
+ if key == name:
+ value = user_ini_value
+ return value
+
+ def getoption(self, name, default=notset, skip=False):
+ """ return command line option value.
+
+ :arg name: name of the option. You may also specify
+ the literal ``--OPT`` option instead of the "dest" option name.
+ :arg default: default value if no option of that name exists.
+ :arg skip: if True raise pytest.skip if option does not exists
+ or has a None value.
+ """
+ name = self._opt2dest.get(name, name)
+ try:
+ val = getattr(self.option, name)
+ if val is None and skip:
+ raise AttributeError(name)
+ return val
+ except AttributeError:
+ if default is not notset:
+ return default
+ if skip:
+ import pytest
+ pytest.skip("no %r option found" % (name,))
+ raise ValueError("no option named %r" % (name,))
+
+ def getvalue(self, name, path=None):
+ """ (deprecated, use getoption()) """
+ return self.getoption(name)
+
+ def getvalueorskip(self, name, path=None):
+ """ (deprecated, use getoption(skip=True)) """
+ return self.getoption(name, skip=True)
+
+
+def exists(path, ignore=EnvironmentError):
+ try:
+ return path.check()
+ except ignore:
+ return False
+
+
+def getcfg(args, warnfunc=None):
+ """
+ Search the list of arguments for a valid ini-file for pytest,
+ and return a tuple of (rootdir, inifile, cfg-dict).
+
+ note: warnfunc is an optional function used to warn
+ about ini-files that use deprecated features.
+ This parameter should be removed when pytest
+ adopts standard deprecation warnings (#1804).
+ """
+ from _pytest.deprecated import SETUP_CFG_PYTEST
+ inibasenames = ["pytest.ini", "tox.ini", "setup.cfg"]
+ args = [x for x in args if not str(x).startswith("-")]
+ if not args:
+ args = [py.path.local()]
+ for arg in args:
+ arg = py.path.local(arg)
+ for base in arg.parts(reverse=True):
+ for inibasename in inibasenames:
+ p = base.join(inibasename)
+ if exists(p):
+ iniconfig = py.iniconfig.IniConfig(p)
+ if 'pytest' in iniconfig.sections:
+ if inibasename == 'setup.cfg' and warnfunc:
+ warnfunc('C1', SETUP_CFG_PYTEST)
+ return base, p, iniconfig['pytest']
+ if inibasename == 'setup.cfg' and 'tool:pytest' in iniconfig.sections:
+ return base, p, iniconfig['tool:pytest']
+ elif inibasename == "pytest.ini":
+ # allowed to be empty
+ return base, p, {}
+ return None, None, None
+
+
+def get_common_ancestor(paths):
+ common_ancestor = None
+ for path in paths:
+ if not path.exists():
+ continue
+ if common_ancestor is None:
+ common_ancestor = path
+ else:
+ if path.relto(common_ancestor) or path == common_ancestor:
+ continue
+ elif common_ancestor.relto(path):
+ common_ancestor = path
+ else:
+ shared = path.common(common_ancestor)
+ if shared is not None:
+ common_ancestor = shared
+ if common_ancestor is None:
+ common_ancestor = py.path.local()
+ elif common_ancestor.isfile():
+ common_ancestor = common_ancestor.dirpath()
+ return common_ancestor
+
+
+def get_dirs_from_args(args):
+ def is_option(x):
+ return str(x).startswith('-')
+
+ def get_file_part_from_node_id(x):
+ return str(x).split('::')[0]
+
+ def get_dir_from_path(path):
+ if path.isdir():
+ return path
+ return py.path.local(path.dirname)
+
+ # These look like paths but may not exist
+ possible_paths = (
+ py.path.local(get_file_part_from_node_id(arg))
+ for arg in args
+ if not is_option(arg)
+ )
+
+ return [
+ get_dir_from_path(path)
+ for path in possible_paths
+ if path.exists()
+ ]
+
+
+def determine_setup(inifile, args, warnfunc=None):
+ dirs = get_dirs_from_args(args)
+ if inifile:
+ iniconfig = py.iniconfig.IniConfig(inifile)
+ try:
+ inicfg = iniconfig["pytest"]
+ except KeyError:
+ inicfg = None
+ rootdir = get_common_ancestor(dirs)
+ else:
+ ancestor = get_common_ancestor(dirs)
+ rootdir, inifile, inicfg = getcfg([ancestor], warnfunc=warnfunc)
+ if rootdir is None:
+ for rootdir in ancestor.parts(reverse=True):
+ if rootdir.join("setup.py").exists():
+ break
+ else:
+ rootdir, inifile, inicfg = getcfg(dirs, warnfunc=warnfunc)
+ if rootdir is None:
+ rootdir = get_common_ancestor([py.path.local(), ancestor])
+ is_fs_root = os.path.splitdrive(str(rootdir))[1] == '/'
+ if is_fs_root:
+ rootdir = ancestor
+ return rootdir, inifile, inicfg or {}
+
+
+def setns(obj, dic):
+ import pytest
+ for name, value in dic.items():
+ if isinstance(value, dict):
+ mod = getattr(obj, name, None)
+ if mod is None:
+ modname = "pytest.%s" % name
+ mod = types.ModuleType(modname)
+ sys.modules[modname] = mod
+ mod.__all__ = []
+ setattr(obj, name, mod)
+ obj.__all__.append(name)
+ setns(mod, value)
+ else:
+ setattr(obj, name, value)
+ obj.__all__.append(name)
+ # if obj != pytest:
+ # pytest.__all__.append(name)
+ setattr(pytest, name, value)
+
+
+def create_terminal_writer(config, *args, **kwargs):
+ """Create a TerminalWriter instance configured according to the options
+ in the config object. Every code which requires a TerminalWriter object
+ and has access to a config object should use this function.
+ """
+ tw = py.io.TerminalWriter(*args, **kwargs)
+ if config.option.color == 'yes':
+ tw.hasmarkup = True
+ if config.option.color == 'no':
+ tw.hasmarkup = False
+ return tw
+
+
+def _strtobool(val):
+ """Convert a string representation of truth to true (1) or false (0).
+
+ True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
+ are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if
+ 'val' is anything else.
+
+ .. note:: copied from distutils.util
+ """
+ val = val.lower()
+ if val in ('y', 'yes', 't', 'true', 'on', '1'):
+ return 1
+ elif val in ('n', 'no', 'f', 'false', 'off', '0'):
+ return 0
+ else:
+ raise ValueError("invalid truth value %r" % (val,))
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/debugging.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/debugging.py
new file mode 100644
index 00000000000..d7dca780956
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/debugging.py
@@ -0,0 +1,123 @@
+""" interactive debugging with PDB, the Python Debugger. """
+from __future__ import absolute_import, division, print_function
+import pdb
+import sys
+
+
+def pytest_addoption(parser):
+ group = parser.getgroup("general")
+ group._addoption(
+ '--pdb', dest="usepdb", action="store_true",
+ help="start the interactive Python debugger on errors.")
+ group._addoption(
+ '--pdbcls', dest="usepdb_cls", metavar="modulename:classname",
+ help="start a custom interactive Python debugger on errors. "
+ "For example: --pdbcls=IPython.terminal.debugger:TerminalPdb")
+
+
+def pytest_configure(config):
+ if config.getvalue("usepdb_cls"):
+ modname, classname = config.getvalue("usepdb_cls").split(":")
+ __import__(modname)
+ pdb_cls = getattr(sys.modules[modname], classname)
+ else:
+ pdb_cls = pdb.Pdb
+
+ if config.getvalue("usepdb"):
+ config.pluginmanager.register(PdbInvoke(), 'pdbinvoke')
+
+ old = (pdb.set_trace, pytestPDB._pluginmanager)
+
+ def fin():
+ pdb.set_trace, pytestPDB._pluginmanager = old
+ pytestPDB._config = None
+ pytestPDB._pdb_cls = pdb.Pdb
+
+ pdb.set_trace = pytestPDB.set_trace
+ pytestPDB._pluginmanager = config.pluginmanager
+ pytestPDB._config = config
+ pytestPDB._pdb_cls = pdb_cls
+ config._cleanup.append(fin)
+
+
+class pytestPDB:
+ """ Pseudo PDB that defers to the real pdb. """
+ _pluginmanager = None
+ _config = None
+ _pdb_cls = pdb.Pdb
+
+ @classmethod
+ def set_trace(cls):
+ """ invoke PDB set_trace debugging, dropping any IO capturing. """
+ import _pytest.config
+ frame = sys._getframe().f_back
+ if cls._pluginmanager is not None:
+ capman = cls._pluginmanager.getplugin("capturemanager")
+ if capman:
+ capman.suspend_global_capture(in_=True)
+ tw = _pytest.config.create_terminal_writer(cls._config)
+ tw.line()
+ tw.sep(">", "PDB set_trace (IO-capturing turned off)")
+ cls._pluginmanager.hook.pytest_enter_pdb(config=cls._config)
+ cls._pdb_cls().set_trace(frame)
+
+
+class PdbInvoke:
+ def pytest_exception_interact(self, node, call, report):
+ capman = node.config.pluginmanager.getplugin("capturemanager")
+ if capman:
+ out, err = capman.suspend_global_capture(in_=True)
+ sys.stdout.write(out)
+ sys.stdout.write(err)
+ _enter_pdb(node, call.excinfo, report)
+
+ def pytest_internalerror(self, excrepr, excinfo):
+ for line in str(excrepr).split("\n"):
+ sys.stderr.write("INTERNALERROR> %s\n" % line)
+ sys.stderr.flush()
+ tb = _postmortem_traceback(excinfo)
+ post_mortem(tb)
+
+
+def _enter_pdb(node, excinfo, rep):
+ # XXX we re-use the TerminalReporter's terminalwriter
+ # because this seems to avoid some encoding related troubles
+ # for not completely clear reasons.
+ tw = node.config.pluginmanager.getplugin("terminalreporter")._tw
+ tw.line()
+ tw.sep(">", "traceback")
+ rep.toterminal(tw)
+ tw.sep(">", "entering PDB")
+ tb = _postmortem_traceback(excinfo)
+ post_mortem(tb)
+ rep._pdbshown = True
+ return rep
+
+
+def _postmortem_traceback(excinfo):
+ # A doctest.UnexpectedException is not useful for post_mortem.
+ # Use the underlying exception instead:
+ from doctest import UnexpectedException
+ if isinstance(excinfo.value, UnexpectedException):
+ return excinfo.value.exc_info[2]
+ else:
+ return excinfo._excinfo[2]
+
+
+def _find_last_non_hidden_frame(stack):
+ i = max(0, len(stack) - 1)
+ while i and stack[i][0].f_locals.get("__tracebackhide__", False):
+ i -= 1
+ return i
+
+
+def post_mortem(t):
+ class Pdb(pytestPDB._pdb_cls):
+ def get_stack(self, f, t):
+ stack, i = pdb.Pdb.get_stack(self, f, t)
+ if f is None:
+ i = _find_last_non_hidden_frame(stack)
+ return stack, i
+ p = Pdb()
+ p.reset()
+ p.interaction(None, t)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/deprecated.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/deprecated.py
new file mode 100644
index 00000000000..9c0fbeca7bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/deprecated.py
@@ -0,0 +1,52 @@
+"""
+This module contains deprecation messages and bits of code used elsewhere in the codebase
+that is planned to be removed in the next pytest release.
+
+Keeping it in a central location makes it easy to track what is deprecated and should
+be removed when the time comes.
+"""
+from __future__ import absolute_import, division, print_function
+
+
+class RemovedInPytest4Warning(DeprecationWarning):
+ """warning class for features removed in pytest 4.0"""
+
+
+MAIN_STR_ARGS = 'passing a string to pytest.main() is deprecated, ' \
+ 'pass a list of arguments instead.'
+
+YIELD_TESTS = 'yield tests are deprecated, and scheduled to be removed in pytest 4.0'
+
+FUNCARG_PREFIX = (
+ '{name}: declaring fixtures using "pytest_funcarg__" prefix is deprecated '
+ 'and scheduled to be removed in pytest 4.0. '
+ 'Please remove the prefix and use the @pytest.fixture decorator instead.')
+
+SETUP_CFG_PYTEST = '[pytest] section in setup.cfg files is deprecated, use [tool:pytest] instead.'
+
+GETFUNCARGVALUE = "use of getfuncargvalue is deprecated, use getfixturevalue"
+
+RESULT_LOG = (
+ '--result-log is deprecated and scheduled for removal in pytest 4.0.\n'
+ 'See https://docs.pytest.org/en/latest/usage.html#creating-resultlog-format-files for more information.'
+)
+
+MARK_INFO_ATTRIBUTE = RemovedInPytest4Warning(
+ "MarkInfo objects are deprecated as they contain the merged marks"
+)
+
+MARK_PARAMETERSET_UNPACKING = RemovedInPytest4Warning(
+ "Applying marks directly to parameters is deprecated,"
+ " please use pytest.param(..., marks=...) instead.\n"
+ "For more details, see: https://docs.pytest.org/en/latest/parametrize.html"
+)
+
+COLLECTOR_MAKEITEM = RemovedInPytest4Warning(
+ "pycollector makeitem was removed "
+ "as it is an accidentially leaked internal api"
+)
+
+METAFUNC_ADD_CALL = (
+ "Metafunc.addcall is deprecated and scheduled to be removed in pytest 4.0.\n"
+ "Please use Metafunc.parametrize instead."
+)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/doctest.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/doctest.py
new file mode 100644
index 00000000000..bba90e551c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/doctest.py
@@ -0,0 +1,369 @@
+""" discover and run doctests in modules and test files."""
+from __future__ import absolute_import, division, print_function
+
+import traceback
+
+import pytest
+from _pytest._code.code import ExceptionInfo, ReprFileLocation, TerminalRepr
+from _pytest.fixtures import FixtureRequest
+
+
+DOCTEST_REPORT_CHOICE_NONE = 'none'
+DOCTEST_REPORT_CHOICE_CDIFF = 'cdiff'
+DOCTEST_REPORT_CHOICE_NDIFF = 'ndiff'
+DOCTEST_REPORT_CHOICE_UDIFF = 'udiff'
+DOCTEST_REPORT_CHOICE_ONLY_FIRST_FAILURE = 'only_first_failure'
+
+DOCTEST_REPORT_CHOICES = (
+ DOCTEST_REPORT_CHOICE_NONE,
+ DOCTEST_REPORT_CHOICE_CDIFF,
+ DOCTEST_REPORT_CHOICE_NDIFF,
+ DOCTEST_REPORT_CHOICE_UDIFF,
+ DOCTEST_REPORT_CHOICE_ONLY_FIRST_FAILURE,
+)
+
+
+def pytest_addoption(parser):
+ parser.addini('doctest_optionflags', 'option flags for doctests',
+ type="args", default=["ELLIPSIS"])
+ parser.addini("doctest_encoding", 'encoding used for doctest files', default="utf-8")
+ group = parser.getgroup("collect")
+ group.addoption("--doctest-modules",
+ action="store_true", default=False,
+ help="run doctests in all .py modules",
+ dest="doctestmodules")
+ group.addoption("--doctest-report",
+ type=str.lower, default="udiff",
+ help="choose another output format for diffs on doctest failure",
+ choices=DOCTEST_REPORT_CHOICES,
+ dest="doctestreport")
+ group.addoption("--doctest-glob",
+ action="append", default=[], metavar="pat",
+ help="doctests file matching pattern, default: test*.txt",
+ dest="doctestglob")
+ group.addoption("--doctest-ignore-import-errors",
+ action="store_true", default=False,
+ help="ignore doctest ImportErrors",
+ dest="doctest_ignore_import_errors")
+
+
+def pytest_collect_file(path, parent):
+ config = parent.config
+ if path.ext == ".py":
+ if config.option.doctestmodules and not _is_setup_py(config, path, parent):
+ return DoctestModule(path, parent)
+ elif _is_doctest(config, path, parent):
+ return DoctestTextfile(path, parent)
+
+
+def _is_setup_py(config, path, parent):
+ if path.basename != "setup.py":
+ return False
+ contents = path.read()
+ return 'setuptools' in contents or 'distutils' in contents
+
+
+def _is_doctest(config, path, parent):
+ if path.ext in ('.txt', '.rst') and parent.session.isinitpath(path):
+ return True
+ globs = config.getoption("doctestglob") or ['test*.txt']
+ for glob in globs:
+ if path.check(fnmatch=glob):
+ return True
+ return False
+
+
+class ReprFailDoctest(TerminalRepr):
+
+ def __init__(self, reprlocation, lines):
+ self.reprlocation = reprlocation
+ self.lines = lines
+
+ def toterminal(self, tw):
+ for line in self.lines:
+ tw.line(line)
+ self.reprlocation.toterminal(tw)
+
+
+class DoctestItem(pytest.Item):
+ def __init__(self, name, parent, runner=None, dtest=None):
+ super(DoctestItem, self).__init__(name, parent)
+ self.runner = runner
+ self.dtest = dtest
+ self.obj = None
+ self.fixture_request = None
+
+ def setup(self):
+ if self.dtest is not None:
+ self.fixture_request = _setup_fixtures(self)
+ globs = dict(getfixture=self.fixture_request.getfixturevalue)
+ for name, value in self.fixture_request.getfixturevalue('doctest_namespace').items():
+ globs[name] = value
+ self.dtest.globs.update(globs)
+
+ def runtest(self):
+ _check_all_skipped(self.dtest)
+ self.runner.run(self.dtest)
+
+ def repr_failure(self, excinfo):
+ import doctest
+ if excinfo.errisinstance((doctest.DocTestFailure,
+ doctest.UnexpectedException)):
+ doctestfailure = excinfo.value
+ example = doctestfailure.example
+ test = doctestfailure.test
+ filename = test.filename
+ if test.lineno is None:
+ lineno = None
+ else:
+ lineno = test.lineno + example.lineno + 1
+ message = excinfo.type.__name__
+ reprlocation = ReprFileLocation(filename, lineno, message)
+ checker = _get_checker()
+ report_choice = _get_report_choice(self.config.getoption("doctestreport"))
+ if lineno is not None:
+ lines = doctestfailure.test.docstring.splitlines(False)
+ # add line numbers to the left of the error message
+ lines = ["%03d %s" % (i + test.lineno + 1, x)
+ for (i, x) in enumerate(lines)]
+ # trim docstring error lines to 10
+ lines = lines[max(example.lineno - 9, 0):example.lineno + 1]
+ else:
+ lines = ['EXAMPLE LOCATION UNKNOWN, not showing all tests of that example']
+ indent = '>>>'
+ for line in example.source.splitlines():
+ lines.append('??? %s %s' % (indent, line))
+ indent = '...'
+ if excinfo.errisinstance(doctest.DocTestFailure):
+ lines += checker.output_difference(example,
+ doctestfailure.got, report_choice).split("\n")
+ else:
+ inner_excinfo = ExceptionInfo(excinfo.value.exc_info)
+ lines += ["UNEXPECTED EXCEPTION: %s" %
+ repr(inner_excinfo.value)]
+ lines += traceback.format_exception(*excinfo.value.exc_info)
+ return ReprFailDoctest(reprlocation, lines)
+ else:
+ return super(DoctestItem, self).repr_failure(excinfo)
+
+ def reportinfo(self):
+ return self.fspath, self.dtest.lineno, "[doctest] %s" % self.name
+
+
+def _get_flag_lookup():
+ import doctest
+ return dict(DONT_ACCEPT_TRUE_FOR_1=doctest.DONT_ACCEPT_TRUE_FOR_1,
+ DONT_ACCEPT_BLANKLINE=doctest.DONT_ACCEPT_BLANKLINE,
+ NORMALIZE_WHITESPACE=doctest.NORMALIZE_WHITESPACE,
+ ELLIPSIS=doctest.ELLIPSIS,
+ IGNORE_EXCEPTION_DETAIL=doctest.IGNORE_EXCEPTION_DETAIL,
+ COMPARISON_FLAGS=doctest.COMPARISON_FLAGS,
+ ALLOW_UNICODE=_get_allow_unicode_flag(),
+ ALLOW_BYTES=_get_allow_bytes_flag(),
+ )
+
+
+def get_optionflags(parent):
+ optionflags_str = parent.config.getini("doctest_optionflags")
+ flag_lookup_table = _get_flag_lookup()
+ flag_acc = 0
+ for flag in optionflags_str:
+ flag_acc |= flag_lookup_table[flag]
+ return flag_acc
+
+
+class DoctestTextfile(pytest.Module):
+ obj = None
+
+ def collect(self):
+ import doctest
+
+ # inspired by doctest.testfile; ideally we would use it directly,
+ # but it doesn't support passing a custom checker
+ encoding = self.config.getini("doctest_encoding")
+ text = self.fspath.read_text(encoding)
+ filename = str(self.fspath)
+ name = self.fspath.basename
+ globs = {'__name__': '__main__'}
+
+ optionflags = get_optionflags(self)
+ runner = doctest.DebugRunner(verbose=0, optionflags=optionflags,
+ checker=_get_checker())
+ _fix_spoof_python2(runner, encoding)
+
+ parser = doctest.DocTestParser()
+ test = parser.get_doctest(text, globs, name, filename, 0)
+ if test.examples:
+ yield DoctestItem(test.name, self, runner, test)
+
+
+def _check_all_skipped(test):
+ """raises pytest.skip() if all examples in the given DocTest have the SKIP
+ option set.
+ """
+ import doctest
+ all_skipped = all(x.options.get(doctest.SKIP, False) for x in test.examples)
+ if all_skipped:
+ pytest.skip('all tests skipped by +SKIP option')
+
+
+class DoctestModule(pytest.Module):
+ def collect(self):
+ import doctest
+ if self.fspath.basename == "conftest.py":
+ module = self.config.pluginmanager._importconftest(self.fspath)
+ else:
+ try:
+ module = self.fspath.pyimport()
+ except ImportError:
+ if self.config.getvalue('doctest_ignore_import_errors'):
+ pytest.skip('unable to import module %r' % self.fspath)
+ else:
+ raise
+ # uses internal doctest module parsing mechanism
+ finder = doctest.DocTestFinder()
+ optionflags = get_optionflags(self)
+ runner = doctest.DebugRunner(verbose=0, optionflags=optionflags,
+ checker=_get_checker())
+
+ for test in finder.find(module, module.__name__):
+ if test.examples: # skip empty doctests
+ yield DoctestItem(test.name, self, runner, test)
+
+
+def _setup_fixtures(doctest_item):
+ """
+ Used by DoctestTextfile and DoctestItem to setup fixture information.
+ """
+ def func():
+ pass
+
+ doctest_item.funcargs = {}
+ fm = doctest_item.session._fixturemanager
+ doctest_item._fixtureinfo = fm.getfixtureinfo(node=doctest_item, func=func,
+ cls=None, funcargs=False)
+ fixture_request = FixtureRequest(doctest_item)
+ fixture_request._fillfixtures()
+ return fixture_request
+
+
+def _get_checker():
+ """
+ Returns a doctest.OutputChecker subclass that takes in account the
+ ALLOW_UNICODE option to ignore u'' prefixes in strings and ALLOW_BYTES
+ to strip b'' prefixes.
+ Useful when the same doctest should run in Python 2 and Python 3.
+
+ An inner class is used to avoid importing "doctest" at the module
+ level.
+ """
+ if hasattr(_get_checker, 'LiteralsOutputChecker'):
+ return _get_checker.LiteralsOutputChecker()
+
+ import doctest
+ import re
+
+ class LiteralsOutputChecker(doctest.OutputChecker):
+ """
+ Copied from doctest_nose_plugin.py from the nltk project:
+ https://github.com/nltk/nltk
+
+ Further extended to also support byte literals.
+ """
+
+ _unicode_literal_re = re.compile(r"(\W|^)[uU]([rR]?[\'\"])", re.UNICODE)
+ _bytes_literal_re = re.compile(r"(\W|^)[bB]([rR]?[\'\"])", re.UNICODE)
+
+ def check_output(self, want, got, optionflags):
+ res = doctest.OutputChecker.check_output(self, want, got,
+ optionflags)
+ if res:
+ return True
+
+ allow_unicode = optionflags & _get_allow_unicode_flag()
+ allow_bytes = optionflags & _get_allow_bytes_flag()
+ if not allow_unicode and not allow_bytes:
+ return False
+
+ else: # pragma: no cover
+ def remove_prefixes(regex, txt):
+ return re.sub(regex, r'\1\2', txt)
+
+ if allow_unicode:
+ want = remove_prefixes(self._unicode_literal_re, want)
+ got = remove_prefixes(self._unicode_literal_re, got)
+ if allow_bytes:
+ want = remove_prefixes(self._bytes_literal_re, want)
+ got = remove_prefixes(self._bytes_literal_re, got)
+ res = doctest.OutputChecker.check_output(self, want, got,
+ optionflags)
+ return res
+
+ _get_checker.LiteralsOutputChecker = LiteralsOutputChecker
+ return _get_checker.LiteralsOutputChecker()
+
+
+def _get_allow_unicode_flag():
+ """
+ Registers and returns the ALLOW_UNICODE flag.
+ """
+ import doctest
+ return doctest.register_optionflag('ALLOW_UNICODE')
+
+
+def _get_allow_bytes_flag():
+ """
+ Registers and returns the ALLOW_BYTES flag.
+ """
+ import doctest
+ return doctest.register_optionflag('ALLOW_BYTES')
+
+
+def _get_report_choice(key):
+ """
+ This function returns the actual `doctest` module flag value, we want to do it as late as possible to avoid
+ importing `doctest` and all its dependencies when parsing options, as it adds overhead and breaks tests.
+ """
+ import doctest
+
+ return {
+ DOCTEST_REPORT_CHOICE_UDIFF: doctest.REPORT_UDIFF,
+ DOCTEST_REPORT_CHOICE_CDIFF: doctest.REPORT_CDIFF,
+ DOCTEST_REPORT_CHOICE_NDIFF: doctest.REPORT_NDIFF,
+ DOCTEST_REPORT_CHOICE_ONLY_FIRST_FAILURE: doctest.REPORT_ONLY_FIRST_FAILURE,
+ DOCTEST_REPORT_CHOICE_NONE: 0,
+ }[key]
+
+
+def _fix_spoof_python2(runner, encoding):
+ """
+ Installs a "SpoofOut" into the given DebugRunner so it properly deals with unicode output. This
+ should patch only doctests for text files because they don't have a way to declare their
+ encoding. Doctests in docstrings from Python modules don't have the same problem given that
+ Python already decoded the strings.
+
+ This fixes the problem related in issue #2434.
+ """
+ from _pytest.compat import _PY2
+ if not _PY2:
+ return
+
+ from doctest import _SpoofOut
+
+ class UnicodeSpoof(_SpoofOut):
+
+ def getvalue(self):
+ result = _SpoofOut.getvalue(self)
+ if encoding:
+ result = result.decode(encoding)
+ return result
+
+ runner._fakeout = UnicodeSpoof()
+
+
+@pytest.fixture(scope='session')
+def doctest_namespace():
+ """
+ Inject names into the doctest namespace.
+ """
+ return dict()
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/fixtures.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/fixtures.py
new file mode 100644
index 00000000000..e09ffaddba7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/fixtures.py
@@ -0,0 +1,1147 @@
+from __future__ import absolute_import, division, print_function
+
+import functools
+import inspect
+import sys
+import warnings
+from collections import OrderedDict
+
+import attr
+import py
+from py._code.code import FormattedExcinfo
+
+import _pytest
+from _pytest import nodes
+from _pytest._code.code import TerminalRepr
+from _pytest.compat import (
+ NOTSET, exc_clear, _format_args,
+ getfslineno, get_real_func,
+ is_generator, isclass, getimfunc,
+ getlocation, getfuncargnames,
+ safe_getattr,
+ FuncargnamesCompatAttr,
+)
+from _pytest.outcomes import fail, TEST_OUTCOME
+
+
+def pytest_sessionstart(session):
+ import _pytest.python
+
+ scopename2class.update({
+ 'class': _pytest.python.Class,
+ 'module': _pytest.python.Module,
+ 'function': _pytest.main.Item,
+ 'session': _pytest.main.Session,
+ })
+ session._fixturemanager = FixtureManager(session)
+
+
+scopename2class = {}
+
+
+scope2props = dict(session=())
+scope2props["module"] = ("fspath", "module")
+scope2props["class"] = scope2props["module"] + ("cls",)
+scope2props["instance"] = scope2props["class"] + ("instance", )
+scope2props["function"] = scope2props["instance"] + ("function", "keywords")
+
+
+def scopeproperty(name=None, doc=None):
+ def decoratescope(func):
+ scopename = name or func.__name__
+
+ def provide(self):
+ if func.__name__ in scope2props[self.scope]:
+ return func(self)
+ raise AttributeError("%s not available in %s-scoped context" % (
+ scopename, self.scope))
+
+ return property(provide, None, None, func.__doc__)
+ return decoratescope
+
+
+def get_scope_node(node, scope):
+ cls = scopename2class.get(scope)
+ if cls is None:
+ raise ValueError("unknown scope")
+ return node.getparent(cls)
+
+
+def add_funcarg_pseudo_fixture_def(collector, metafunc, fixturemanager):
+ # this function will transform all collected calls to a functions
+ # if they use direct funcargs (i.e. direct parametrization)
+ # because we want later test execution to be able to rely on
+ # an existing FixtureDef structure for all arguments.
+ # XXX we can probably avoid this algorithm if we modify CallSpec2
+ # to directly care for creating the fixturedefs within its methods.
+ if not metafunc._calls[0].funcargs:
+ return # this function call does not have direct parametrization
+ # collect funcargs of all callspecs into a list of values
+ arg2params = {}
+ arg2scope = {}
+ for callspec in metafunc._calls:
+ for argname, argvalue in callspec.funcargs.items():
+ assert argname not in callspec.params
+ callspec.params[argname] = argvalue
+ arg2params_list = arg2params.setdefault(argname, [])
+ callspec.indices[argname] = len(arg2params_list)
+ arg2params_list.append(argvalue)
+ if argname not in arg2scope:
+ scopenum = callspec._arg2scopenum.get(argname,
+ scopenum_function)
+ arg2scope[argname] = scopes[scopenum]
+ callspec.funcargs.clear()
+
+ # register artificial FixtureDef's so that later at test execution
+ # time we can rely on a proper FixtureDef to exist for fixture setup.
+ arg2fixturedefs = metafunc._arg2fixturedefs
+ for argname, valuelist in arg2params.items():
+ # if we have a scope that is higher than function we need
+ # to make sure we only ever create an according fixturedef on
+ # a per-scope basis. We thus store and cache the fixturedef on the
+ # node related to the scope.
+ scope = arg2scope[argname]
+ node = None
+ if scope != "function":
+ node = get_scope_node(collector, scope)
+ if node is None:
+ assert scope == "class" and isinstance(collector, _pytest.python.Module)
+ # use module-level collector for class-scope (for now)
+ node = collector
+ if node and argname in node._name2pseudofixturedef:
+ arg2fixturedefs[argname] = [node._name2pseudofixturedef[argname]]
+ else:
+ fixturedef = FixtureDef(fixturemanager, '', argname,
+ get_direct_param_fixture_func,
+ arg2scope[argname],
+ valuelist, False, False)
+ arg2fixturedefs[argname] = [fixturedef]
+ if node is not None:
+ node._name2pseudofixturedef[argname] = fixturedef
+
+
+def getfixturemarker(obj):
+ """ return fixturemarker or None if it doesn't exist or raised
+ exceptions."""
+ try:
+ return getattr(obj, "_pytestfixturefunction", None)
+ except TEST_OUTCOME:
+ # some objects raise errors like request (from flask import request)
+ # we don't expect them to be fixture functions
+ return None
+
+
+def get_parametrized_fixture_keys(item, scopenum):
+ """ return list of keys for all parametrized arguments which match
+ the specified scope. """
+ assert scopenum < scopenum_function # function
+ try:
+ cs = item.callspec
+ except AttributeError:
+ pass
+ else:
+ # cs.indices.items() is random order of argnames. Need to
+ # sort this so that different calls to
+ # get_parametrized_fixture_keys will be deterministic.
+ for argname, param_index in sorted(cs.indices.items()):
+ if cs._arg2scopenum[argname] != scopenum:
+ continue
+ if scopenum == 0: # session
+ key = (argname, param_index)
+ elif scopenum == 1: # module
+ key = (argname, param_index, item.fspath)
+ elif scopenum == 2: # class
+ key = (argname, param_index, item.fspath, item.cls)
+ yield key
+
+
+# algorithm for sorting on a per-parametrized resource setup basis
+# it is called for scopenum==0 (session) first and performs sorting
+# down to the lower scopes such as to minimize number of "high scope"
+# setups and teardowns
+
+def reorder_items(items):
+ argkeys_cache = {}
+ for scopenum in range(0, scopenum_function):
+ argkeys_cache[scopenum] = d = {}
+ for item in items:
+ keys = OrderedDict.fromkeys(get_parametrized_fixture_keys(item, scopenum))
+ if keys:
+ d[item] = keys
+ return reorder_items_atscope(items, set(), argkeys_cache, 0)
+
+
+def reorder_items_atscope(items, ignore, argkeys_cache, scopenum):
+ if scopenum >= scopenum_function or len(items) < 3:
+ return items
+ items_done = []
+ while 1:
+ items_before, items_same, items_other, newignore = \
+ slice_items(items, ignore, argkeys_cache[scopenum])
+ items_before = reorder_items_atscope(
+ items_before, ignore, argkeys_cache, scopenum + 1)
+ if items_same is None:
+ # nothing to reorder in this scope
+ assert items_other is None
+ return items_done + items_before
+ items_done.extend(items_before)
+ items = items_same + items_other
+ ignore = newignore
+
+
+def slice_items(items, ignore, scoped_argkeys_cache):
+ # we pick the first item which uses a fixture instance in the
+ # requested scope and which we haven't seen yet. We slice the input
+ # items list into a list of items_nomatch, items_same and
+ # items_other
+ if scoped_argkeys_cache: # do we need to do work at all?
+ it = iter(items)
+ # first find a slicing key
+ for i, item in enumerate(it):
+ argkeys = scoped_argkeys_cache.get(item)
+ if argkeys is not None:
+ newargkeys = OrderedDict.fromkeys(k for k in argkeys if k not in ignore)
+ if newargkeys: # found a slicing key
+ slicing_argkey, _ = newargkeys.popitem()
+ items_before = items[:i]
+ items_same = [item]
+ items_other = []
+ # now slice the remainder of the list
+ for item in it:
+ argkeys = scoped_argkeys_cache.get(item)
+ if argkeys and slicing_argkey in argkeys and \
+ slicing_argkey not in ignore:
+ items_same.append(item)
+ else:
+ items_other.append(item)
+ newignore = ignore.copy()
+ newignore.add(slicing_argkey)
+ return (items_before, items_same, items_other, newignore)
+ return items, None, None, None
+
+
+def fillfixtures(function):
+ """ fill missing funcargs for a test function. """
+ try:
+ request = function._request
+ except AttributeError:
+ # XXX this special code path is only expected to execute
+ # with the oejskit plugin. It uses classes with funcargs
+ # and we thus have to work a bit to allow this.
+ fm = function.session._fixturemanager
+ fi = fm.getfixtureinfo(function.parent, function.obj, None)
+ function._fixtureinfo = fi
+ request = function._request = FixtureRequest(function)
+ request._fillfixtures()
+ # prune out funcargs for jstests
+ newfuncargs = {}
+ for name in fi.argnames:
+ newfuncargs[name] = function.funcargs[name]
+ function.funcargs = newfuncargs
+ else:
+ request._fillfixtures()
+
+
+def get_direct_param_fixture_func(request):
+ return request.param
+
+
+class FuncFixtureInfo:
+ def __init__(self, argnames, names_closure, name2fixturedefs):
+ self.argnames = argnames
+ self.names_closure = names_closure
+ self.name2fixturedefs = name2fixturedefs
+
+
+class FixtureRequest(FuncargnamesCompatAttr):
+ """ A request for a fixture from a test or fixture function.
+
+ A request object gives access to the requesting test context
+ and has an optional ``param`` attribute in case
+ the fixture is parametrized indirectly.
+ """
+
+ def __init__(self, pyfuncitem):
+ self._pyfuncitem = pyfuncitem
+ #: fixture for which this request is being performed
+ self.fixturename = None
+ #: Scope string, one of "function", "class", "module", "session"
+ self.scope = "function"
+ self._fixture_values = {} # argname -> fixture value
+ self._fixture_defs = {} # argname -> FixtureDef
+ fixtureinfo = pyfuncitem._fixtureinfo
+ self._arg2fixturedefs = fixtureinfo.name2fixturedefs.copy()
+ self._arg2index = {}
+ self._fixturemanager = pyfuncitem.session._fixturemanager
+
+ @property
+ def fixturenames(self):
+ # backward incompatible note: now a readonly property
+ return list(self._pyfuncitem._fixtureinfo.names_closure)
+
+ @property
+ def node(self):
+ """ underlying collection node (depends on current request scope)"""
+ return self._getscopeitem(self.scope)
+
+ def _getnextfixturedef(self, argname):
+ fixturedefs = self._arg2fixturedefs.get(argname, None)
+ if fixturedefs is None:
+ # we arrive here because of a a dynamic call to
+ # getfixturevalue(argname) usage which was naturally
+ # not known at parsing/collection time
+ parentid = self._pyfuncitem.parent.nodeid
+ fixturedefs = self._fixturemanager.getfixturedefs(argname, parentid)
+ self._arg2fixturedefs[argname] = fixturedefs
+ # fixturedefs list is immutable so we maintain a decreasing index
+ index = self._arg2index.get(argname, 0) - 1
+ if fixturedefs is None or (-index > len(fixturedefs)):
+ raise FixtureLookupError(argname, self)
+ self._arg2index[argname] = index
+ return fixturedefs[index]
+
+ @property
+ def config(self):
+ """ the pytest config object associated with this request. """
+ return self._pyfuncitem.config
+
+ @scopeproperty()
+ def function(self):
+ """ test function object if the request has a per-function scope. """
+ return self._pyfuncitem.obj
+
+ @scopeproperty("class")
+ def cls(self):
+ """ class (can be None) where the test function was collected. """
+ clscol = self._pyfuncitem.getparent(_pytest.python.Class)
+ if clscol:
+ return clscol.obj
+
+ @property
+ def instance(self):
+ """ instance (can be None) on which test function was collected. """
+ # unittest support hack, see _pytest.unittest.TestCaseFunction
+ try:
+ return self._pyfuncitem._testcase
+ except AttributeError:
+ function = getattr(self, "function", None)
+ if function is not None:
+ return py.builtin._getimself(function)
+
+ @scopeproperty()
+ def module(self):
+ """ python module object where the test function was collected. """
+ return self._pyfuncitem.getparent(_pytest.python.Module).obj
+
+ @scopeproperty()
+ def fspath(self):
+ """ the file system path of the test module which collected this test. """
+ return self._pyfuncitem.fspath
+
+ @property
+ def keywords(self):
+ """ keywords/markers dictionary for the underlying node. """
+ return self.node.keywords
+
+ @property
+ def session(self):
+ """ pytest session object. """
+ return self._pyfuncitem.session
+
+ def addfinalizer(self, finalizer):
+ """ add finalizer/teardown function to be called after the
+ last test within the requesting test context finished
+ execution. """
+ # XXX usually this method is shadowed by fixturedef specific ones
+ self._addfinalizer(finalizer, scope=self.scope)
+
+ def _addfinalizer(self, finalizer, scope):
+ colitem = self._getscopeitem(scope)
+ self._pyfuncitem.session._setupstate.addfinalizer(
+ finalizer=finalizer, colitem=colitem)
+
+ def applymarker(self, marker):
+ """ Apply a marker to a single test function invocation.
+ This method is useful if you don't want to have a keyword/marker
+ on all function invocations.
+
+ :arg marker: a :py:class:`_pytest.mark.MarkDecorator` object
+ created by a call to ``pytest.mark.NAME(...)``.
+ """
+ try:
+ self.node.keywords[marker.markname] = marker
+ except AttributeError:
+ raise ValueError(marker)
+
+ def raiseerror(self, msg):
+ """ raise a FixtureLookupError with the given message. """
+ raise self._fixturemanager.FixtureLookupError(None, self, msg)
+
+ def _fillfixtures(self):
+ item = self._pyfuncitem
+ fixturenames = getattr(item, "fixturenames", self.fixturenames)
+ for argname in fixturenames:
+ if argname not in item.funcargs:
+ item.funcargs[argname] = self.getfixturevalue(argname)
+
+ def cached_setup(self, setup, teardown=None, scope="module", extrakey=None):
+ """ (deprecated) Return a testing resource managed by ``setup`` &
+ ``teardown`` calls. ``scope`` and ``extrakey`` determine when the
+ ``teardown`` function will be called so that subsequent calls to
+ ``setup`` would recreate the resource. With pytest-2.3 you often
+ do not need ``cached_setup()`` as you can directly declare a scope
+ on a fixture function and register a finalizer through
+ ``request.addfinalizer()``.
+
+ :arg teardown: function receiving a previously setup resource.
+ :arg setup: a no-argument function creating a resource.
+ :arg scope: a string value out of ``function``, ``class``, ``module``
+ or ``session`` indicating the caching lifecycle of the resource.
+ :arg extrakey: added to internal caching key of (funcargname, scope).
+ """
+ if not hasattr(self.config, '_setupcache'):
+ self.config._setupcache = {} # XXX weakref?
+ cachekey = (self.fixturename, self._getscopeitem(scope), extrakey)
+ cache = self.config._setupcache
+ try:
+ val = cache[cachekey]
+ except KeyError:
+ self._check_scope(self.fixturename, self.scope, scope)
+ val = setup()
+ cache[cachekey] = val
+ if teardown is not None:
+ def finalizer():
+ del cache[cachekey]
+ teardown(val)
+ self._addfinalizer(finalizer, scope=scope)
+ return val
+
+ def getfixturevalue(self, argname):
+ """ Dynamically run a named fixture function.
+
+ Declaring fixtures via function argument is recommended where possible.
+ But if you can only decide whether to use another fixture at test
+ setup time, you may use this function to retrieve it inside a fixture
+ or test function body.
+ """
+ return self._get_active_fixturedef(argname).cached_result[0]
+
+ def getfuncargvalue(self, argname):
+ """ Deprecated, use getfixturevalue. """
+ from _pytest import deprecated
+ warnings.warn(
+ deprecated.GETFUNCARGVALUE,
+ DeprecationWarning,
+ stacklevel=2)
+ return self.getfixturevalue(argname)
+
+ def _get_active_fixturedef(self, argname):
+ try:
+ return self._fixture_defs[argname]
+ except KeyError:
+ try:
+ fixturedef = self._getnextfixturedef(argname)
+ except FixtureLookupError:
+ if argname == "request":
+ class PseudoFixtureDef:
+ cached_result = (self, [0], None)
+ scope = "function"
+ return PseudoFixtureDef
+ raise
+ # remove indent to prevent the python3 exception
+ # from leaking into the call
+ result = self._getfixturevalue(fixturedef)
+ self._fixture_values[argname] = result
+ self._fixture_defs[argname] = fixturedef
+ return fixturedef
+
+ def _get_fixturestack(self):
+ current = self
+ values = []
+ while 1:
+ fixturedef = getattr(current, "_fixturedef", None)
+ if fixturedef is None:
+ values.reverse()
+ return values
+ values.append(fixturedef)
+ current = current._parent_request
+
+ def _getfixturevalue(self, fixturedef):
+ # prepare a subrequest object before calling fixture function
+ # (latter managed by fixturedef)
+ argname = fixturedef.argname
+ funcitem = self._pyfuncitem
+ scope = fixturedef.scope
+ try:
+ param = funcitem.callspec.getparam(argname)
+ except (AttributeError, ValueError):
+ param = NOTSET
+ param_index = 0
+ if fixturedef.params is not None:
+ frame = inspect.stack()[3]
+ frameinfo = inspect.getframeinfo(frame[0])
+ source_path = frameinfo.filename
+ source_lineno = frameinfo.lineno
+ source_path = py.path.local(source_path)
+ if source_path.relto(funcitem.config.rootdir):
+ source_path = source_path.relto(funcitem.config.rootdir)
+ msg = (
+ "The requested fixture has no parameter defined for the "
+ "current test.\n\nRequested fixture '{0}' defined in:\n{1}"
+ "\n\nRequested here:\n{2}:{3}".format(
+ fixturedef.argname,
+ getlocation(fixturedef.func, funcitem.config.rootdir),
+ source_path,
+ source_lineno,
+ )
+ )
+ fail(msg)
+ else:
+ # indices might not be set if old-style metafunc.addcall() was used
+ param_index = funcitem.callspec.indices.get(argname, 0)
+ # if a parametrize invocation set a scope it will override
+ # the static scope defined with the fixture function
+ paramscopenum = funcitem.callspec._arg2scopenum.get(argname)
+ if paramscopenum is not None:
+ scope = scopes[paramscopenum]
+
+ subrequest = SubRequest(self, scope, param, param_index, fixturedef)
+
+ # check if a higher-level scoped fixture accesses a lower level one
+ subrequest._check_scope(argname, self.scope, scope)
+
+ # clear sys.exc_info before invoking the fixture (python bug?)
+ # if its not explicitly cleared it will leak into the call
+ exc_clear()
+ try:
+ # call the fixture function
+ val = fixturedef.execute(request=subrequest)
+ finally:
+ # if fixture function failed it might have registered finalizers
+ self.session._setupstate.addfinalizer(functools.partial(fixturedef.finish, request=subrequest),
+ subrequest.node)
+ return val
+
+ def _check_scope(self, argname, invoking_scope, requested_scope):
+ if argname == "request":
+ return
+ if scopemismatch(invoking_scope, requested_scope):
+ # try to report something helpful
+ lines = self._factorytraceback()
+ fail("ScopeMismatch: You tried to access the %r scoped "
+ "fixture %r with a %r scoped request object, "
+ "involved factories\n%s" % (
+ (requested_scope, argname, invoking_scope, "\n".join(lines))),
+ pytrace=False)
+
+ def _factorytraceback(self):
+ lines = []
+ for fixturedef in self._get_fixturestack():
+ factory = fixturedef.func
+ fs, lineno = getfslineno(factory)
+ p = self._pyfuncitem.session.fspath.bestrelpath(fs)
+ args = _format_args(factory)
+ lines.append("%s:%d: def %s%s" % (
+ p, lineno, factory.__name__, args))
+ return lines
+
+ def _getscopeitem(self, scope):
+ if scope == "function":
+ # this might also be a non-function Item despite its attribute name
+ return self._pyfuncitem
+ node = get_scope_node(self._pyfuncitem, scope)
+ if node is None and scope == "class":
+ # fallback to function item itself
+ node = self._pyfuncitem
+ assert node, 'Could not obtain a node for scope "{}" for function {!r}'.format(scope, self._pyfuncitem)
+ return node
+
+ def __repr__(self):
+ return "<FixtureRequest for %r>" % (self.node)
+
+
+class SubRequest(FixtureRequest):
+ """ a sub request for handling getting a fixture from a
+ test function/fixture. """
+
+ def __init__(self, request, scope, param, param_index, fixturedef):
+ self._parent_request = request
+ self.fixturename = fixturedef.argname
+ if param is not NOTSET:
+ self.param = param
+ self.param_index = param_index
+ self.scope = scope
+ self._fixturedef = fixturedef
+ self._pyfuncitem = request._pyfuncitem
+ self._fixture_values = request._fixture_values
+ self._fixture_defs = request._fixture_defs
+ self._arg2fixturedefs = request._arg2fixturedefs
+ self._arg2index = request._arg2index
+ self._fixturemanager = request._fixturemanager
+
+ def __repr__(self):
+ return "<SubRequest %r for %r>" % (self.fixturename, self._pyfuncitem)
+
+ def addfinalizer(self, finalizer):
+ self._fixturedef.addfinalizer(finalizer)
+
+
+class ScopeMismatchError(Exception):
+ """ A fixture function tries to use a different fixture function which
+ which has a lower scope (e.g. a Session one calls a function one)
+ """
+
+
+scopes = "session module class function".split()
+scopenum_function = scopes.index("function")
+
+
+def scopemismatch(currentscope, newscope):
+ return scopes.index(newscope) > scopes.index(currentscope)
+
+
+def scope2index(scope, descr, where=None):
+ """Look up the index of ``scope`` and raise a descriptive value error
+ if not defined.
+ """
+ try:
+ return scopes.index(scope)
+ except ValueError:
+ raise ValueError(
+ "{0} {1}has an unsupported scope value '{2}'".format(
+ descr, 'from {0} '.format(where) if where else '',
+ scope)
+ )
+
+
+class FixtureLookupError(LookupError):
+ """ could not return a requested Fixture (missing or invalid). """
+
+ def __init__(self, argname, request, msg=None):
+ self.argname = argname
+ self.request = request
+ self.fixturestack = request._get_fixturestack()
+ self.msg = msg
+
+ def formatrepr(self):
+ tblines = []
+ addline = tblines.append
+ stack = [self.request._pyfuncitem.obj]
+ stack.extend(map(lambda x: x.func, self.fixturestack))
+ msg = self.msg
+ if msg is not None:
+ # the last fixture raise an error, let's present
+ # it at the requesting side
+ stack = stack[:-1]
+ for function in stack:
+ fspath, lineno = getfslineno(function)
+ try:
+ lines, _ = inspect.getsourcelines(get_real_func(function))
+ except (IOError, IndexError, TypeError):
+ error_msg = "file %s, line %s: source code not available"
+ addline(error_msg % (fspath, lineno + 1))
+ else:
+ addline("file %s, line %s" % (fspath, lineno + 1))
+ for i, line in enumerate(lines):
+ line = line.rstrip()
+ addline(" " + line)
+ if line.lstrip().startswith('def'):
+ break
+
+ if msg is None:
+ fm = self.request._fixturemanager
+ available = []
+ parentid = self.request._pyfuncitem.parent.nodeid
+ for name, fixturedefs in fm._arg2fixturedefs.items():
+ faclist = list(fm._matchfactories(fixturedefs, parentid))
+ if faclist and name not in available:
+ available.append(name)
+ msg = "fixture %r not found" % (self.argname,)
+ msg += "\n available fixtures: %s" % (", ".join(sorted(available)),)
+ msg += "\n use 'pytest --fixtures [testpath]' for help on them."
+
+ return FixtureLookupErrorRepr(fspath, lineno, tblines, msg, self.argname)
+
+
+class FixtureLookupErrorRepr(TerminalRepr):
+ def __init__(self, filename, firstlineno, tblines, errorstring, argname):
+ self.tblines = tblines
+ self.errorstring = errorstring
+ self.filename = filename
+ self.firstlineno = firstlineno
+ self.argname = argname
+
+ def toterminal(self, tw):
+ # tw.line("FixtureLookupError: %s" %(self.argname), red=True)
+ for tbline in self.tblines:
+ tw.line(tbline.rstrip())
+ lines = self.errorstring.split("\n")
+ if lines:
+ tw.line('{0} {1}'.format(FormattedExcinfo.fail_marker,
+ lines[0].strip()), red=True)
+ for line in lines[1:]:
+ tw.line('{0} {1}'.format(FormattedExcinfo.flow_marker,
+ line.strip()), red=True)
+ tw.line()
+ tw.line("%s:%d" % (self.filename, self.firstlineno + 1))
+
+
+def fail_fixturefunc(fixturefunc, msg):
+ fs, lineno = getfslineno(fixturefunc)
+ location = "%s:%s" % (fs, lineno + 1)
+ source = _pytest._code.Source(fixturefunc)
+ fail(msg + ":\n\n" + str(source.indent()) + "\n" + location,
+ pytrace=False)
+
+
+def call_fixture_func(fixturefunc, request, kwargs):
+ yieldctx = is_generator(fixturefunc)
+ if yieldctx:
+ it = fixturefunc(**kwargs)
+ res = next(it)
+
+ def teardown():
+ try:
+ next(it)
+ except StopIteration:
+ pass
+ else:
+ fail_fixturefunc(fixturefunc,
+ "yield_fixture function has more than one 'yield'")
+
+ request.addfinalizer(teardown)
+ else:
+ res = fixturefunc(**kwargs)
+ return res
+
+
+class FixtureDef:
+ """ A container for a factory definition. """
+
+ def __init__(self, fixturemanager, baseid, argname, func, scope, params,
+ unittest=False, ids=None):
+ self._fixturemanager = fixturemanager
+ self.baseid = baseid or ''
+ self.has_location = baseid is not None
+ self.func = func
+ self.argname = argname
+ self.scope = scope
+ self.scopenum = scope2index(
+ scope or "function",
+ descr='fixture {0}'.format(func.__name__),
+ where=baseid
+ )
+ self.params = params
+ self.argnames = getfuncargnames(func, is_method=unittest)
+ self.unittest = unittest
+ self.ids = ids
+ self._finalizers = []
+
+ def addfinalizer(self, finalizer):
+ self._finalizers.append(finalizer)
+
+ def finish(self, request):
+ exceptions = []
+ try:
+ while self._finalizers:
+ try:
+ func = self._finalizers.pop()
+ func()
+ except: # noqa
+ exceptions.append(sys.exc_info())
+ if exceptions:
+ e = exceptions[0]
+ del exceptions # ensure we don't keep all frames alive because of the traceback
+ py.builtin._reraise(*e)
+
+ finally:
+ hook = self._fixturemanager.session.gethookproxy(request.node.fspath)
+ hook.pytest_fixture_post_finalizer(fixturedef=self, request=request)
+ # even if finalization fails, we invalidate
+ # the cached fixture value and remove
+ # all finalizers because they may be bound methods which will
+ # keep instances alive
+ if hasattr(self, "cached_result"):
+ del self.cached_result
+ self._finalizers = []
+
+ def execute(self, request):
+ # get required arguments and register our own finish()
+ # with their finalization
+ for argname in self.argnames:
+ fixturedef = request._get_active_fixturedef(argname)
+ if argname != "request":
+ fixturedef.addfinalizer(functools.partial(self.finish, request=request))
+
+ my_cache_key = request.param_index
+ cached_result = getattr(self, "cached_result", None)
+ if cached_result is not None:
+ result, cache_key, err = cached_result
+ if my_cache_key == cache_key:
+ if err is not None:
+ py.builtin._reraise(*err)
+ else:
+ return result
+ # we have a previous but differently parametrized fixture instance
+ # so we need to tear it down before creating a new one
+ self.finish(request)
+ assert not hasattr(self, "cached_result")
+
+ hook = self._fixturemanager.session.gethookproxy(request.node.fspath)
+ return hook.pytest_fixture_setup(fixturedef=self, request=request)
+
+ def __repr__(self):
+ return ("<FixtureDef name=%r scope=%r baseid=%r >" %
+ (self.argname, self.scope, self.baseid))
+
+
+def pytest_fixture_setup(fixturedef, request):
+ """ Execution of fixture setup. """
+ kwargs = {}
+ for argname in fixturedef.argnames:
+ fixdef = request._get_active_fixturedef(argname)
+ result, arg_cache_key, exc = fixdef.cached_result
+ request._check_scope(argname, request.scope, fixdef.scope)
+ kwargs[argname] = result
+
+ fixturefunc = fixturedef.func
+ if fixturedef.unittest:
+ if request.instance is not None:
+ # bind the unbound method to the TestCase instance
+ fixturefunc = fixturedef.func.__get__(request.instance)
+ else:
+ # the fixture function needs to be bound to the actual
+ # request.instance so that code working with "fixturedef" behaves
+ # as expected.
+ if request.instance is not None:
+ fixturefunc = getimfunc(fixturedef.func)
+ if fixturefunc != fixturedef.func:
+ fixturefunc = fixturefunc.__get__(request.instance)
+ my_cache_key = request.param_index
+ try:
+ result = call_fixture_func(fixturefunc, request, kwargs)
+ except TEST_OUTCOME:
+ fixturedef.cached_result = (None, my_cache_key, sys.exc_info())
+ raise
+ fixturedef.cached_result = (result, my_cache_key, None)
+ return result
+
+
+def _ensure_immutable_ids(ids):
+ if ids is None:
+ return
+ if callable(ids):
+ return ids
+ return tuple(ids)
+
+
+@attr.s(frozen=True)
+class FixtureFunctionMarker(object):
+ scope = attr.ib()
+ params = attr.ib(convert=attr.converters.optional(tuple))
+ autouse = attr.ib(default=False)
+ ids = attr.ib(default=None, convert=_ensure_immutable_ids)
+ name = attr.ib(default=None)
+
+ def __call__(self, function):
+ if isclass(function):
+ raise ValueError(
+ "class fixtures not supported (may be in the future)")
+ function._pytestfixturefunction = self
+ return function
+
+
+def fixture(scope="function", params=None, autouse=False, ids=None, name=None):
+ """ (return a) decorator to mark a fixture factory function.
+
+ This decorator can be used (with or without parameters) to define a
+ fixture function. The name of the fixture function can later be
+ referenced to cause its invocation ahead of running tests: test
+ modules or classes can use the pytest.mark.usefixtures(fixturename)
+ marker. Test functions can directly use fixture names as input
+ arguments in which case the fixture instance returned from the fixture
+ function will be injected.
+
+ :arg scope: the scope for which this fixture is shared, one of
+ "function" (default), "class", "module" or "session".
+
+ :arg params: an optional list of parameters which will cause multiple
+ invocations of the fixture function and all of the tests
+ using it.
+
+ :arg autouse: if True, the fixture func is activated for all tests that
+ can see it. If False (the default) then an explicit
+ reference is needed to activate the fixture.
+
+ :arg ids: list of string ids each corresponding to the params
+ so that they are part of the test id. If no ids are provided
+ they will be generated automatically from the params.
+
+ :arg name: the name of the fixture. This defaults to the name of the
+ decorated function. If a fixture is used in the same module in
+ which it is defined, the function name of the fixture will be
+ shadowed by the function arg that requests the fixture; one way
+ to resolve this is to name the decorated function
+ ``fixture_<fixturename>`` and then use
+ ``@pytest.fixture(name='<fixturename>')``.
+
+ Fixtures can optionally provide their values to test functions using a ``yield`` statement,
+ instead of ``return``. In this case, the code block after the ``yield`` statement is executed
+ as teardown code regardless of the test outcome. A fixture function must yield exactly once.
+ """
+ if callable(scope) and params is None and autouse is False:
+ # direct decoration
+ return FixtureFunctionMarker(
+ "function", params, autouse, name=name)(scope)
+ if params is not None and not isinstance(params, (list, tuple)):
+ params = list(params)
+ return FixtureFunctionMarker(scope, params, autouse, ids=ids, name=name)
+
+
+def yield_fixture(scope="function", params=None, autouse=False, ids=None, name=None):
+ """ (return a) decorator to mark a yield-fixture factory function.
+
+ .. deprecated:: 3.0
+ Use :py:func:`pytest.fixture` directly instead.
+ """
+ if callable(scope) and params is None and not autouse:
+ # direct decoration
+ return FixtureFunctionMarker(
+ "function", params, autouse, ids=ids, name=name)(scope)
+ else:
+ return FixtureFunctionMarker(scope, params, autouse, ids=ids, name=name)
+
+
+defaultfuncargprefixmarker = fixture()
+
+
+@fixture(scope="session")
+def pytestconfig(request):
+ """ the pytest config object with access to command line opts."""
+ return request.config
+
+
+class FixtureManager:
+ """
+ pytest fixtures definitions and information is stored and managed
+ from this class.
+
+ During collection fm.parsefactories() is called multiple times to parse
+ fixture function definitions into FixtureDef objects and internal
+ data structures.
+
+ During collection of test functions, metafunc-mechanics instantiate
+ a FuncFixtureInfo object which is cached per node/func-name.
+ This FuncFixtureInfo object is later retrieved by Function nodes
+ which themselves offer a fixturenames attribute.
+
+ The FuncFixtureInfo object holds information about fixtures and FixtureDefs
+ relevant for a particular function. An initial list of fixtures is
+ assembled like this:
+
+ - ini-defined usefixtures
+ - autouse-marked fixtures along the collection chain up from the function
+ - usefixtures markers at module/class/function level
+ - test function funcargs
+
+ Subsequently the funcfixtureinfo.fixturenames attribute is computed
+ as the closure of the fixtures needed to setup the initial fixtures,
+ i. e. fixtures needed by fixture functions themselves are appended
+ to the fixturenames list.
+
+ Upon the test-setup phases all fixturenames are instantiated, retrieved
+ by a lookup of their FuncFixtureInfo.
+ """
+
+ _argprefix = "pytest_funcarg__"
+ FixtureLookupError = FixtureLookupError
+ FixtureLookupErrorRepr = FixtureLookupErrorRepr
+
+ def __init__(self, session):
+ self.session = session
+ self.config = session.config
+ self._arg2fixturedefs = {}
+ self._holderobjseen = set()
+ self._arg2finish = {}
+ self._nodeid_and_autousenames = [("", self.config.getini("usefixtures"))]
+ session.config.pluginmanager.register(self, "funcmanage")
+
+ def getfixtureinfo(self, node, func, cls, funcargs=True):
+ if funcargs and not hasattr(node, "nofuncargs"):
+ argnames = getfuncargnames(func, cls=cls)
+ else:
+ argnames = ()
+ usefixtures = getattr(func, "usefixtures", None)
+ initialnames = argnames
+ if usefixtures is not None:
+ initialnames = usefixtures.args + initialnames
+ fm = node.session._fixturemanager
+ names_closure, arg2fixturedefs = fm.getfixtureclosure(initialnames,
+ node)
+ return FuncFixtureInfo(argnames, names_closure, arg2fixturedefs)
+
+ def pytest_plugin_registered(self, plugin):
+ nodeid = None
+ try:
+ p = py.path.local(plugin.__file__)
+ except AttributeError:
+ pass
+ else:
+ # construct the base nodeid which is later used to check
+ # what fixtures are visible for particular tests (as denoted
+ # by their test id)
+ if p.basename.startswith("conftest.py"):
+ nodeid = p.dirpath().relto(self.config.rootdir)
+ if p.sep != nodes.SEP:
+ nodeid = nodeid.replace(p.sep, nodes.SEP)
+ self.parsefactories(plugin, nodeid)
+
+ def _getautousenames(self, nodeid):
+ """ return a tuple of fixture names to be used. """
+ autousenames = []
+ for baseid, basenames in self._nodeid_and_autousenames:
+ if nodeid.startswith(baseid):
+ if baseid:
+ i = len(baseid)
+ nextchar = nodeid[i:i + 1]
+ if nextchar and nextchar not in ":/":
+ continue
+ autousenames.extend(basenames)
+ # make sure autousenames are sorted by scope, scopenum 0 is session
+ autousenames.sort(
+ key=lambda x: self._arg2fixturedefs[x][-1].scopenum)
+ return autousenames
+
+ def getfixtureclosure(self, fixturenames, parentnode):
+ # collect the closure of all fixtures , starting with the given
+ # fixturenames as the initial set. As we have to visit all
+ # factory definitions anyway, we also return a arg2fixturedefs
+ # mapping so that the caller can reuse it and does not have
+ # to re-discover fixturedefs again for each fixturename
+ # (discovering matching fixtures for a given name/node is expensive)
+
+ parentid = parentnode.nodeid
+ fixturenames_closure = self._getautousenames(parentid)
+
+ def merge(otherlist):
+ for arg in otherlist:
+ if arg not in fixturenames_closure:
+ fixturenames_closure.append(arg)
+
+ merge(fixturenames)
+ arg2fixturedefs = {}
+ lastlen = -1
+ while lastlen != len(fixturenames_closure):
+ lastlen = len(fixturenames_closure)
+ for argname in fixturenames_closure:
+ if argname in arg2fixturedefs:
+ continue
+ fixturedefs = self.getfixturedefs(argname, parentid)
+ if fixturedefs:
+ arg2fixturedefs[argname] = fixturedefs
+ merge(fixturedefs[-1].argnames)
+ return fixturenames_closure, arg2fixturedefs
+
+ def pytest_generate_tests(self, metafunc):
+ for argname in metafunc.fixturenames:
+ faclist = metafunc._arg2fixturedefs.get(argname)
+ if faclist:
+ fixturedef = faclist[-1]
+ if fixturedef.params is not None:
+ parametrize_func = getattr(metafunc.function, 'parametrize', None)
+ func_params = getattr(parametrize_func, 'args', [[None]])
+ func_kwargs = getattr(parametrize_func, 'kwargs', {})
+ # skip directly parametrized arguments
+ if "argnames" in func_kwargs:
+ argnames = parametrize_func.kwargs["argnames"]
+ else:
+ argnames = func_params[0]
+ if not isinstance(argnames, (tuple, list)):
+ argnames = [x.strip() for x in argnames.split(",") if x.strip()]
+ if argname not in func_params and argname not in argnames:
+ metafunc.parametrize(argname, fixturedef.params,
+ indirect=True, scope=fixturedef.scope,
+ ids=fixturedef.ids)
+ else:
+ continue # will raise FixtureLookupError at setup time
+
+ def pytest_collection_modifyitems(self, items):
+ # separate parametrized setups
+ items[:] = reorder_items(items)
+
+ def parsefactories(self, node_or_obj, nodeid=NOTSET, unittest=False):
+ if nodeid is not NOTSET:
+ holderobj = node_or_obj
+ else:
+ holderobj = node_or_obj.obj
+ nodeid = node_or_obj.nodeid
+ if holderobj in self._holderobjseen:
+ return
+ self._holderobjseen.add(holderobj)
+ autousenames = []
+ for name in dir(holderobj):
+ # The attribute can be an arbitrary descriptor, so the attribute
+ # access below can raise. safe_getatt() ignores such exceptions.
+ obj = safe_getattr(holderobj, name, None)
+ # fixture functions have a pytest_funcarg__ prefix (pre-2.3 style)
+ # or are "@pytest.fixture" marked
+ marker = getfixturemarker(obj)
+ if marker is None:
+ if not name.startswith(self._argprefix):
+ continue
+ if not callable(obj):
+ continue
+ marker = defaultfuncargprefixmarker
+ from _pytest import deprecated
+ self.config.warn('C1', deprecated.FUNCARG_PREFIX.format(name=name), nodeid=nodeid)
+ name = name[len(self._argprefix):]
+ elif not isinstance(marker, FixtureFunctionMarker):
+ # magic globals with __getattr__ might have got us a wrong
+ # fixture attribute
+ continue
+ else:
+ if marker.name:
+ name = marker.name
+ msg = 'fixtures cannot have "pytest_funcarg__" prefix ' \
+ 'and be decorated with @pytest.fixture:\n%s' % name
+ assert not name.startswith(self._argprefix), msg
+
+ fixture_def = FixtureDef(self, nodeid, name, obj,
+ marker.scope, marker.params,
+ unittest=unittest, ids=marker.ids)
+
+ faclist = self._arg2fixturedefs.setdefault(name, [])
+ if fixture_def.has_location:
+ faclist.append(fixture_def)
+ else:
+ # fixturedefs with no location are at the front
+ # so this inserts the current fixturedef after the
+ # existing fixturedefs from external plugins but
+ # before the fixturedefs provided in conftests.
+ i = len([f for f in faclist if not f.has_location])
+ faclist.insert(i, fixture_def)
+ if marker.autouse:
+ autousenames.append(name)
+
+ if autousenames:
+ self._nodeid_and_autousenames.append((nodeid or '', autousenames))
+
+ def getfixturedefs(self, argname, nodeid):
+ """
+ Gets a list of fixtures which are applicable to the given node id.
+
+ :param str argname: name of the fixture to search for
+ :param str nodeid: full node id of the requesting test.
+ :return: list[FixtureDef]
+ """
+ try:
+ fixturedefs = self._arg2fixturedefs[argname]
+ except KeyError:
+ return None
+ else:
+ return tuple(self._matchfactories(fixturedefs, nodeid))
+
+ def _matchfactories(self, fixturedefs, nodeid):
+ for fixturedef in fixturedefs:
+ if nodes.ischildnode(fixturedef.baseid, nodeid):
+ yield fixturedef
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/freeze_support.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/freeze_support.py
new file mode 100644
index 00000000000..97147a88250
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/freeze_support.py
@@ -0,0 +1,43 @@
+"""
+Provides a function to report all internal modules for using freezing tools
+pytest
+"""
+from __future__ import absolute_import, division, print_function
+
+
+def freeze_includes():
+ """
+ Returns a list of module names used by py.test that should be
+ included by cx_freeze.
+ """
+ import py
+ import _pytest
+ result = list(_iter_all_modules(py))
+ result += list(_iter_all_modules(_pytest))
+ return result
+
+
+def _iter_all_modules(package, prefix=''):
+ """
+ Iterates over the names of all modules that can be found in the given
+ package, recursively.
+ Example:
+ _iter_all_modules(_pytest) ->
+ ['_pytest.assertion.newinterpret',
+ '_pytest.capture',
+ '_pytest.core',
+ ...
+ ]
+ """
+ import os
+ import pkgutil
+ if type(package) is not str:
+ path, prefix = package.__path__[0], package.__name__ + '.'
+ else:
+ path = package
+ for _, name, is_package in pkgutil.iter_modules([path]):
+ if is_package:
+ for m in _iter_all_modules(os.path.join(path, name), prefix=name + '.'):
+ yield prefix + m
+ else:
+ yield prefix + name
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/helpconfig.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/helpconfig.py
new file mode 100644
index 00000000000..e744637f866
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/helpconfig.py
@@ -0,0 +1,184 @@
+""" version info, help messages, tracing configuration. """
+from __future__ import absolute_import, division, print_function
+
+import py
+import pytest
+from _pytest.config import PrintHelp
+import os
+import sys
+from argparse import Action
+
+
+class HelpAction(Action):
+ """This is an argparse Action that will raise an exception in
+ order to skip the rest of the argument parsing when --help is passed.
+ This prevents argparse from quitting due to missing required arguments
+ when any are defined, for example by ``pytest_addoption``.
+ This is similar to the way that the builtin argparse --help option is
+ implemented by raising SystemExit.
+ """
+
+ def __init__(self,
+ option_strings,
+ dest=None,
+ default=False,
+ help=None):
+ super(HelpAction, self).__init__(
+ option_strings=option_strings,
+ dest=dest,
+ const=True,
+ default=default,
+ nargs=0,
+ help=help)
+
+ def __call__(self, parser, namespace, values, option_string=None):
+ setattr(namespace, self.dest, self.const)
+
+ # We should only skip the rest of the parsing after preparse is done
+ if getattr(parser._parser, 'after_preparse', False):
+ raise PrintHelp
+
+
+def pytest_addoption(parser):
+ group = parser.getgroup('debugconfig')
+ group.addoption('--version', action="store_true",
+ help="display pytest lib version and import information.")
+ group._addoption("-h", "--help", action=HelpAction, dest="help",
+ help="show help message and configuration info")
+ group._addoption('-p', action="append", dest="plugins", default=[],
+ metavar="name",
+ help="early-load given plugin (multi-allowed). "
+ "To avoid loading of plugins, use the `no:` prefix, e.g. "
+ "`no:doctest`.")
+ group.addoption('--traceconfig', '--trace-config',
+ action="store_true", default=False,
+ help="trace considerations of conftest.py files."),
+ group.addoption('--debug',
+ action="store_true", dest="debug", default=False,
+ help="store internal tracing debug information in 'pytestdebug.log'.")
+ group._addoption(
+ '-o', '--override-ini', nargs='*', dest="override_ini",
+ action="append",
+ help="override config option with option=value style, e.g. `-o xfail_strict=True`.")
+
+
+@pytest.hookimpl(hookwrapper=True)
+def pytest_cmdline_parse():
+ outcome = yield
+ config = outcome.get_result()
+ if config.option.debug:
+ path = os.path.abspath("pytestdebug.log")
+ debugfile = open(path, 'w')
+ debugfile.write("versions pytest-%s, py-%s, "
+ "python-%s\ncwd=%s\nargs=%s\n\n" % (
+ pytest.__version__, py.__version__,
+ ".".join(map(str, sys.version_info)),
+ os.getcwd(), config._origargs))
+ config.trace.root.setwriter(debugfile.write)
+ undo_tracing = config.pluginmanager.enable_tracing()
+ sys.stderr.write("writing pytestdebug information to %s\n" % path)
+
+ def unset_tracing():
+ debugfile.close()
+ sys.stderr.write("wrote pytestdebug information to %s\n" %
+ debugfile.name)
+ config.trace.root.setwriter(None)
+ undo_tracing()
+
+ config.add_cleanup(unset_tracing)
+
+
+def pytest_cmdline_main(config):
+ if config.option.version:
+ p = py.path.local(pytest.__file__)
+ sys.stderr.write("This is pytest version %s, imported from %s\n" %
+ (pytest.__version__, p))
+ plugininfo = getpluginversioninfo(config)
+ if plugininfo:
+ for line in plugininfo:
+ sys.stderr.write(line + "\n")
+ return 0
+ elif config.option.help:
+ config._do_configure()
+ showhelp(config)
+ config._ensure_unconfigure()
+ return 0
+
+
+def showhelp(config):
+ reporter = config.pluginmanager.get_plugin('terminalreporter')
+ tw = reporter._tw
+ tw.write(config._parser.optparser.format_help())
+ tw.line()
+ tw.line()
+ tw.line("[pytest] ini-options in the first "
+ "pytest.ini|tox.ini|setup.cfg file found:")
+ tw.line()
+
+ for name in config._parser._ininames:
+ help, type, default = config._parser._inidict[name]
+ if type is None:
+ type = "string"
+ spec = "%s (%s)" % (name, type)
+ line = " %-24s %s" % (spec, help)
+ tw.line(line[:tw.fullwidth])
+
+ tw.line()
+ tw.line("environment variables:")
+ vars = [
+ ("PYTEST_ADDOPTS", "extra command line options"),
+ ("PYTEST_PLUGINS", "comma-separated plugins to load during startup"),
+ ("PYTEST_DEBUG", "set to enable debug tracing of pytest's internals")
+ ]
+ for name, help in vars:
+ tw.line(" %-24s %s" % (name, help))
+ tw.line()
+ tw.line()
+
+ tw.line("to see available markers type: pytest --markers")
+ tw.line("to see available fixtures type: pytest --fixtures")
+ tw.line("(shown according to specified file_or_dir or current dir "
+ "if not specified)")
+
+ for warningreport in reporter.stats.get('warnings', []):
+ tw.line("warning : " + warningreport.message, red=True)
+ return
+
+
+conftest_options = [
+ ('pytest_plugins', 'list of plugin names to load'),
+]
+
+
+def getpluginversioninfo(config):
+ lines = []
+ plugininfo = config.pluginmanager.list_plugin_distinfo()
+ if plugininfo:
+ lines.append("setuptools registered plugins:")
+ for plugin, dist in plugininfo:
+ loc = getattr(plugin, '__file__', repr(plugin))
+ content = "%s-%s at %s" % (dist.project_name, dist.version, loc)
+ lines.append(" " + content)
+ return lines
+
+
+def pytest_report_header(config):
+ lines = []
+ if config.option.debug or config.option.traceconfig:
+ lines.append("using: pytest-%s pylib-%s" %
+ (pytest.__version__, py.__version__))
+
+ verinfo = getpluginversioninfo(config)
+ if verinfo:
+ lines.extend(verinfo)
+
+ if config.option.traceconfig:
+ lines.append("active plugins:")
+ items = config.pluginmanager.list_name_plugin()
+ for name, plugin in items:
+ if hasattr(plugin, '__file__'):
+ r = plugin.__file__
+ else:
+ r = repr(plugin)
+ lines.append(" %-20s: %s" % (name, r))
+ return lines
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/hookspec.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/hookspec.py
new file mode 100644
index 00000000000..440bf99d375
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/hookspec.py
@@ -0,0 +1,423 @@
+""" hook specifications for pytest plugins, invoked from main.py and builtin plugins. """
+
+from pluggy import HookspecMarker
+
+hookspec = HookspecMarker("pytest")
+
+# -------------------------------------------------------------------------
+# Initialization hooks called for every plugin
+# -------------------------------------------------------------------------
+
+
+@hookspec(historic=True)
+def pytest_addhooks(pluginmanager):
+ """called at plugin registration time to allow adding new hooks via a call to
+ pluginmanager.add_hookspecs(module_or_class, prefix)."""
+
+
+@hookspec(historic=True)
+def pytest_namespace():
+ """
+ DEPRECATED: this hook causes direct monkeypatching on pytest, its use is strongly discouraged
+ return dict of name->object to be made globally available in
+ the pytest namespace. This hook is called at plugin registration
+ time.
+ """
+
+
+@hookspec(historic=True)
+def pytest_plugin_registered(plugin, manager):
+ """ a new pytest plugin got registered. """
+
+
+@hookspec(historic=True)
+def pytest_addoption(parser):
+ """register argparse-style options and ini-style config values,
+ called once at the beginning of a test run.
+
+ .. note::
+
+ This function should be implemented only in plugins or ``conftest.py``
+ files situated at the tests root directory due to how pytest
+ :ref:`discovers plugins during startup <pluginorder>`.
+
+ :arg parser: To add command line options, call
+ :py:func:`parser.addoption(...) <_pytest.config.Parser.addoption>`.
+ To add ini-file values call :py:func:`parser.addini(...)
+ <_pytest.config.Parser.addini>`.
+
+ Options can later be accessed through the
+ :py:class:`config <_pytest.config.Config>` object, respectively:
+
+ - :py:func:`config.getoption(name) <_pytest.config.Config.getoption>` to
+ retrieve the value of a command line option.
+
+ - :py:func:`config.getini(name) <_pytest.config.Config.getini>` to retrieve
+ a value read from an ini-style file.
+
+ The config object is passed around on many internal objects via the ``.config``
+ attribute or can be retrieved as the ``pytestconfig`` fixture or accessed
+ via (deprecated) ``pytest.config``.
+ """
+
+
+@hookspec(historic=True)
+def pytest_configure(config):
+ """
+ Allows plugins and conftest files to perform initial configuration.
+
+ This hook is called for every plugin and initial conftest file
+ after command line options have been parsed.
+
+ After that, the hook is called for other conftest files as they are
+ imported.
+
+ :arg config: pytest config object
+ :type config: _pytest.config.Config
+ """
+
+# -------------------------------------------------------------------------
+# Bootstrapping hooks called for plugins registered early enough:
+# internal and 3rd party plugins as well as directly
+# discoverable conftest.py local plugins.
+# -------------------------------------------------------------------------
+
+
+@hookspec(firstresult=True)
+def pytest_cmdline_parse(pluginmanager, args):
+ """return initialized config object, parsing the specified args.
+
+ Stops at first non-None result, see :ref:`firstresult` """
+
+
+def pytest_cmdline_preparse(config, args):
+ """(deprecated) modify command line arguments before option parsing. """
+
+
+@hookspec(firstresult=True)
+def pytest_cmdline_main(config):
+ """ called for performing the main command line action. The default
+ implementation will invoke the configure hooks and runtest_mainloop.
+
+ Stops at first non-None result, see :ref:`firstresult` """
+
+
+def pytest_load_initial_conftests(early_config, parser, args):
+ """ implements the loading of initial conftest files ahead
+ of command line option parsing. """
+
+
+# -------------------------------------------------------------------------
+# collection hooks
+# -------------------------------------------------------------------------
+
+@hookspec(firstresult=True)
+def pytest_collection(session):
+ """ perform the collection protocol for the given session.
+
+ Stops at first non-None result, see :ref:`firstresult` """
+
+
+def pytest_collection_modifyitems(session, config, items):
+ """ called after collection has been performed, may filter or re-order
+ the items in-place."""
+
+
+def pytest_collection_finish(session):
+ """ called after collection has been performed and modified. """
+
+
+@hookspec(firstresult=True)
+def pytest_ignore_collect(path, config):
+ """ return True to prevent considering this path for collection.
+ This hook is consulted for all files and directories prior to calling
+ more specific hooks.
+
+ Stops at first non-None result, see :ref:`firstresult`
+ """
+
+
+@hookspec(firstresult=True)
+def pytest_collect_directory(path, parent):
+ """ called before traversing a directory for collection files.
+
+ Stops at first non-None result, see :ref:`firstresult` """
+
+
+def pytest_collect_file(path, parent):
+ """ return collection Node or None for the given path. Any new node
+ needs to have the specified ``parent`` as a parent."""
+
+# logging hooks for collection
+
+
+def pytest_collectstart(collector):
+ """ collector starts collecting. """
+
+
+def pytest_itemcollected(item):
+ """ we just collected a test item. """
+
+
+def pytest_collectreport(report):
+ """ collector finished collecting. """
+
+
+def pytest_deselected(items):
+ """ called for test items deselected by keyword. """
+
+
+@hookspec(firstresult=True)
+def pytest_make_collect_report(collector):
+ """ perform ``collector.collect()`` and return a CollectReport.
+
+ Stops at first non-None result, see :ref:`firstresult` """
+
+# -------------------------------------------------------------------------
+# Python test function related hooks
+# -------------------------------------------------------------------------
+
+
+@hookspec(firstresult=True)
+def pytest_pycollect_makemodule(path, parent):
+ """ return a Module collector or None for the given path.
+ This hook will be called for each matching test module path.
+ The pytest_collect_file hook needs to be used if you want to
+ create test modules for files that do not match as a test module.
+
+ Stops at first non-None result, see :ref:`firstresult` """
+
+
+@hookspec(firstresult=True)
+def pytest_pycollect_makeitem(collector, name, obj):
+ """ return custom item/collector for a python object in a module, or None.
+
+ Stops at first non-None result, see :ref:`firstresult` """
+
+
+@hookspec(firstresult=True)
+def pytest_pyfunc_call(pyfuncitem):
+ """ call underlying test function.
+
+ Stops at first non-None result, see :ref:`firstresult` """
+
+
+def pytest_generate_tests(metafunc):
+ """ generate (multiple) parametrized calls to a test function."""
+
+
+@hookspec(firstresult=True)
+def pytest_make_parametrize_id(config, val, argname):
+ """Return a user-friendly string representation of the given ``val`` that will be used
+ by @pytest.mark.parametrize calls. Return None if the hook doesn't know about ``val``.
+ The parameter name is available as ``argname``, if required.
+
+ Stops at first non-None result, see :ref:`firstresult` """
+
+# -------------------------------------------------------------------------
+# generic runtest related hooks
+# -------------------------------------------------------------------------
+
+
+@hookspec(firstresult=True)
+def pytest_runtestloop(session):
+ """ called for performing the main runtest loop
+ (after collection finished).
+
+ Stops at first non-None result, see :ref:`firstresult` """
+
+
+def pytest_itemstart(item, node):
+ """ (deprecated, use pytest_runtest_logstart). """
+
+
+@hookspec(firstresult=True)
+def pytest_runtest_protocol(item, nextitem):
+ """ implements the runtest_setup/call/teardown protocol for
+ the given test item, including capturing exceptions and calling
+ reporting hooks.
+
+ :arg item: test item for which the runtest protocol is performed.
+
+ :arg nextitem: the scheduled-to-be-next test item (or None if this
+ is the end my friend). This argument is passed on to
+ :py:func:`pytest_runtest_teardown`.
+
+ :return boolean: True if no further hook implementations should be invoked.
+
+
+ Stops at first non-None result, see :ref:`firstresult` """
+
+
+def pytest_runtest_logstart(nodeid, location):
+ """ signal the start of running a single test item. """
+
+
+def pytest_runtest_setup(item):
+ """ called before ``pytest_runtest_call(item)``. """
+
+
+def pytest_runtest_call(item):
+ """ called to execute the test ``item``. """
+
+
+def pytest_runtest_teardown(item, nextitem):
+ """ called after ``pytest_runtest_call``.
+
+ :arg nextitem: the scheduled-to-be-next test item (None if no further
+ test item is scheduled). This argument can be used to
+ perform exact teardowns, i.e. calling just enough finalizers
+ so that nextitem only needs to call setup-functions.
+ """
+
+
+@hookspec(firstresult=True)
+def pytest_runtest_makereport(item, call):
+ """ return a :py:class:`_pytest.runner.TestReport` object
+ for the given :py:class:`pytest.Item <_pytest.main.Item>` and
+ :py:class:`_pytest.runner.CallInfo`.
+
+ Stops at first non-None result, see :ref:`firstresult` """
+
+
+def pytest_runtest_logreport(report):
+ """ process a test setup/call/teardown report relating to
+ the respective phase of executing a test. """
+
+# -------------------------------------------------------------------------
+# Fixture related hooks
+# -------------------------------------------------------------------------
+
+
+@hookspec(firstresult=True)
+def pytest_fixture_setup(fixturedef, request):
+ """ performs fixture setup execution.
+
+ Stops at first non-None result, see :ref:`firstresult` """
+
+
+def pytest_fixture_post_finalizer(fixturedef, request):
+ """ called after fixture teardown, but before the cache is cleared so
+ the fixture result cache ``fixturedef.cached_result`` can
+ still be accessed."""
+
+# -------------------------------------------------------------------------
+# test session related hooks
+# -------------------------------------------------------------------------
+
+
+def pytest_sessionstart(session):
+ """ before session.main() is called. """
+
+
+def pytest_sessionfinish(session, exitstatus):
+ """ whole test run finishes. """
+
+
+def pytest_unconfigure(config):
+ """ called before test process is exited. """
+
+
+# -------------------------------------------------------------------------
+# hooks for customizing the assert methods
+# -------------------------------------------------------------------------
+
+def pytest_assertrepr_compare(config, op, left, right):
+ """return explanation for comparisons in failing assert expressions.
+
+ Return None for no custom explanation, otherwise return a list
+ of strings. The strings will be joined by newlines but any newlines
+ *in* a string will be escaped. Note that all but the first line will
+ be indented slightly, the intention is for the first line to be a summary.
+ """
+
+# -------------------------------------------------------------------------
+# hooks for influencing reporting (invoked from _pytest_terminal)
+# -------------------------------------------------------------------------
+
+
+def pytest_report_header(config, startdir):
+ """ return a string or list of strings to be displayed as header info for terminal reporting.
+
+ :param config: the pytest config object.
+ :param startdir: py.path object with the starting dir
+
+ .. note::
+
+ This function should be implemented only in plugins or ``conftest.py``
+ files situated at the tests root directory due to how pytest
+ :ref:`discovers plugins during startup <pluginorder>`.
+ """
+
+
+def pytest_report_collectionfinish(config, startdir, items):
+ """
+ .. versionadded:: 3.2
+
+ return a string or list of strings to be displayed after collection has finished successfully.
+
+ This strings will be displayed after the standard "collected X items" message.
+
+ :param config: the pytest config object.
+ :param startdir: py.path object with the starting dir
+ :param items: list of pytest items that are going to be executed; this list should not be modified.
+ """
+
+
+@hookspec(firstresult=True)
+def pytest_report_teststatus(report):
+ """ return result-category, shortletter and verbose word for reporting.
+
+ Stops at first non-None result, see :ref:`firstresult` """
+
+
+def pytest_terminal_summary(terminalreporter, exitstatus):
+ """ add additional section in terminal summary reporting. """
+
+
+@hookspec(historic=True)
+def pytest_logwarning(message, code, nodeid, fslocation):
+ """ process a warning specified by a message, a code string,
+ a nodeid and fslocation (both of which may be None
+ if the warning is not tied to a partilar node/location)."""
+
+# -------------------------------------------------------------------------
+# doctest hooks
+# -------------------------------------------------------------------------
+
+
+@hookspec(firstresult=True)
+def pytest_doctest_prepare_content(content):
+ """ return processed content for a given doctest
+
+ Stops at first non-None result, see :ref:`firstresult` """
+
+# -------------------------------------------------------------------------
+# error handling and internal debugging hooks
+# -------------------------------------------------------------------------
+
+
+def pytest_internalerror(excrepr, excinfo):
+ """ called for internal errors. """
+
+
+def pytest_keyboard_interrupt(excinfo):
+ """ called for keyboard interrupt. """
+
+
+def pytest_exception_interact(node, call, report):
+ """called when an exception was raised which can potentially be
+ interactively handled.
+
+ This hook is only called if an exception was raised
+ that is not an internal exception like ``skip.Exception``.
+ """
+
+
+def pytest_enter_pdb(config):
+ """ called upon pdb.set_trace(), can be used by plugins to take special
+ action just before the python debugger enters in interactive mode.
+
+ :arg config: pytest config object
+ :type config: _pytest.config.Config
+ """
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/junitxml.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/junitxml.py
new file mode 100644
index 00000000000..7fb40dc3548
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/junitxml.py
@@ -0,0 +1,453 @@
+"""
+ report test results in JUnit-XML format,
+ for use with Jenkins and build integration servers.
+
+
+Based on initial code from Ross Lawley.
+
+Output conforms to https://github.com/jenkinsci/xunit-plugin/blob/master/
+src/main/resources/org/jenkinsci/plugins/xunit/types/model/xsd/junit-10.xsd
+"""
+from __future__ import absolute_import, division, print_function
+
+import functools
+import py
+import os
+import re
+import sys
+import time
+import pytest
+from _pytest import nodes
+from _pytest.config import filename_arg
+
+# Python 2.X and 3.X compatibility
+if sys.version_info[0] < 3:
+ from codecs import open
+else:
+ unichr = chr
+ unicode = str
+ long = int
+
+
+class Junit(py.xml.Namespace):
+ pass
+
+
+# We need to get the subset of the invalid unicode ranges according to
+# XML 1.0 which are valid in this python build. Hence we calculate
+# this dynamically instead of hardcoding it. The spec range of valid
+# chars is: Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD]
+# | [#x10000-#x10FFFF]
+_legal_chars = (0x09, 0x0A, 0x0d)
+_legal_ranges = (
+ (0x20, 0x7E), (0x80, 0xD7FF), (0xE000, 0xFFFD), (0x10000, 0x10FFFF),
+)
+_legal_xml_re = [
+ unicode("%s-%s") % (unichr(low), unichr(high))
+ for (low, high) in _legal_ranges if low < sys.maxunicode
+]
+_legal_xml_re = [unichr(x) for x in _legal_chars] + _legal_xml_re
+illegal_xml_re = re.compile(unicode('[^%s]') % unicode('').join(_legal_xml_re))
+del _legal_chars
+del _legal_ranges
+del _legal_xml_re
+
+_py_ext_re = re.compile(r"\.py$")
+
+
+def bin_xml_escape(arg):
+ def repl(matchobj):
+ i = ord(matchobj.group())
+ if i <= 0xFF:
+ return unicode('#x%02X') % i
+ else:
+ return unicode('#x%04X') % i
+
+ return py.xml.raw(illegal_xml_re.sub(repl, py.xml.escape(arg)))
+
+
+class _NodeReporter(object):
+ def __init__(self, nodeid, xml):
+
+ self.id = nodeid
+ self.xml = xml
+ self.add_stats = self.xml.add_stats
+ self.duration = 0
+ self.properties = []
+ self.nodes = []
+ self.testcase = None
+ self.attrs = {}
+
+ def append(self, node):
+ self.xml.add_stats(type(node).__name__)
+ self.nodes.append(node)
+
+ def add_property(self, name, value):
+ self.properties.append((str(name), bin_xml_escape(value)))
+
+ def make_properties_node(self):
+ """Return a Junit node containing custom properties, if any.
+ """
+ if self.properties:
+ return Junit.properties([
+ Junit.property(name=name, value=value)
+ for name, value in self.properties
+ ])
+ return ''
+
+ def record_testreport(self, testreport):
+ assert not self.testcase
+ names = mangle_test_address(testreport.nodeid)
+ classnames = names[:-1]
+ if self.xml.prefix:
+ classnames.insert(0, self.xml.prefix)
+ attrs = {
+ "classname": ".".join(classnames),
+ "name": bin_xml_escape(names[-1]),
+ "file": testreport.location[0],
+ }
+ if testreport.location[1] is not None:
+ attrs["line"] = testreport.location[1]
+ if hasattr(testreport, "url"):
+ attrs["url"] = testreport.url
+ self.attrs = attrs
+
+ def to_xml(self):
+ testcase = Junit.testcase(time=self.duration, **self.attrs)
+ testcase.append(self.make_properties_node())
+ for node in self.nodes:
+ testcase.append(node)
+ return testcase
+
+ def _add_simple(self, kind, message, data=None):
+ data = bin_xml_escape(data)
+ node = kind(data, message=message)
+ self.append(node)
+
+ def write_captured_output(self, report):
+ for capname in ('out', 'err'):
+ content = getattr(report, 'capstd' + capname)
+ if content:
+ tag = getattr(Junit, 'system-' + capname)
+ self.append(tag(bin_xml_escape(content)))
+
+ def append_pass(self, report):
+ self.add_stats('passed')
+
+ def append_failure(self, report):
+ # msg = str(report.longrepr.reprtraceback.extraline)
+ if hasattr(report, "wasxfail"):
+ self._add_simple(
+ Junit.skipped,
+ "xfail-marked test passes unexpectedly")
+ else:
+ if hasattr(report.longrepr, "reprcrash"):
+ message = report.longrepr.reprcrash.message
+ elif isinstance(report.longrepr, (unicode, str)):
+ message = report.longrepr
+ else:
+ message = str(report.longrepr)
+ message = bin_xml_escape(message)
+ fail = Junit.failure(message=message)
+ fail.append(bin_xml_escape(report.longrepr))
+ self.append(fail)
+
+ def append_collect_error(self, report):
+ # msg = str(report.longrepr.reprtraceback.extraline)
+ self.append(Junit.error(bin_xml_escape(report.longrepr),
+ message="collection failure"))
+
+ def append_collect_skipped(self, report):
+ self._add_simple(
+ Junit.skipped, "collection skipped", report.longrepr)
+
+ def append_error(self, report):
+ if getattr(report, 'when', None) == 'teardown':
+ msg = "test teardown failure"
+ else:
+ msg = "test setup failure"
+ self._add_simple(
+ Junit.error, msg, report.longrepr)
+
+ def append_skipped(self, report):
+ if hasattr(report, "wasxfail"):
+ self._add_simple(
+ Junit.skipped, "expected test failure", report.wasxfail
+ )
+ else:
+ filename, lineno, skipreason = report.longrepr
+ if skipreason.startswith("Skipped: "):
+ skipreason = bin_xml_escape(skipreason[9:])
+ self.append(
+ Junit.skipped("%s:%s: %s" % (filename, lineno, skipreason),
+ type="pytest.skip",
+ message=skipreason))
+ self.write_captured_output(report)
+
+ def finalize(self):
+ data = self.to_xml().unicode(indent=0)
+ self.__dict__.clear()
+ self.to_xml = lambda: py.xml.raw(data)
+
+
+@pytest.fixture
+def record_xml_property(request):
+ """Add extra xml properties to the tag for the calling test.
+ The fixture is callable with ``(name, value)``, with value being automatically
+ xml-encoded.
+ """
+ request.node.warn(
+ code='C3',
+ message='record_xml_property is an experimental feature',
+ )
+ xml = getattr(request.config, "_xml", None)
+ if xml is not None:
+ node_reporter = xml.node_reporter(request.node.nodeid)
+ return node_reporter.add_property
+ else:
+ def add_property_noop(name, value):
+ pass
+
+ return add_property_noop
+
+
+def pytest_addoption(parser):
+ group = parser.getgroup("terminal reporting")
+ group.addoption(
+ '--junitxml', '--junit-xml',
+ action="store",
+ dest="xmlpath",
+ metavar="path",
+ type=functools.partial(filename_arg, optname="--junitxml"),
+ default=None,
+ help="create junit-xml style report file at given path.")
+ group.addoption(
+ '--junitprefix', '--junit-prefix',
+ action="store",
+ metavar="str",
+ default=None,
+ help="prepend prefix to classnames in junit-xml output")
+ parser.addini("junit_suite_name", "Test suite name for JUnit report", default="pytest")
+
+
+def pytest_configure(config):
+ xmlpath = config.option.xmlpath
+ # prevent opening xmllog on slave nodes (xdist)
+ if xmlpath and not hasattr(config, 'slaveinput'):
+ config._xml = LogXML(xmlpath, config.option.junitprefix, config.getini("junit_suite_name"))
+ config.pluginmanager.register(config._xml)
+
+
+def pytest_unconfigure(config):
+ xml = getattr(config, '_xml', None)
+ if xml:
+ del config._xml
+ config.pluginmanager.unregister(xml)
+
+
+def mangle_test_address(address):
+ path, possible_open_bracket, params = address.partition('[')
+ names = path.split("::")
+ try:
+ names.remove('()')
+ except ValueError:
+ pass
+ # convert file path to dotted path
+ names[0] = names[0].replace(nodes.SEP, '.')
+ names[0] = _py_ext_re.sub("", names[0])
+ # put any params back
+ names[-1] += possible_open_bracket + params
+ return names
+
+
+class LogXML(object):
+ def __init__(self, logfile, prefix, suite_name="pytest"):
+ logfile = os.path.expanduser(os.path.expandvars(logfile))
+ self.logfile = os.path.normpath(os.path.abspath(logfile))
+ self.prefix = prefix
+ self.suite_name = suite_name
+ self.stats = dict.fromkeys([
+ 'error',
+ 'passed',
+ 'failure',
+ 'skipped',
+ ], 0)
+ self.node_reporters = {} # nodeid -> _NodeReporter
+ self.node_reporters_ordered = []
+ self.global_properties = []
+ # List of reports that failed on call but teardown is pending.
+ self.open_reports = []
+ self.cnt_double_fail_tests = 0
+
+ def finalize(self, report):
+ nodeid = getattr(report, 'nodeid', report)
+ # local hack to handle xdist report order
+ slavenode = getattr(report, 'node', None)
+ reporter = self.node_reporters.pop((nodeid, slavenode))
+ if reporter is not None:
+ reporter.finalize()
+
+ def node_reporter(self, report):
+ nodeid = getattr(report, 'nodeid', report)
+ # local hack to handle xdist report order
+ slavenode = getattr(report, 'node', None)
+
+ key = nodeid, slavenode
+
+ if key in self.node_reporters:
+ # TODO: breasks for --dist=each
+ return self.node_reporters[key]
+
+ reporter = _NodeReporter(nodeid, self)
+
+ self.node_reporters[key] = reporter
+ self.node_reporters_ordered.append(reporter)
+
+ return reporter
+
+ def add_stats(self, key):
+ if key in self.stats:
+ self.stats[key] += 1
+
+ def _opentestcase(self, report):
+ reporter = self.node_reporter(report)
+ reporter.record_testreport(report)
+ return reporter
+
+ def pytest_runtest_logreport(self, report):
+ """handle a setup/call/teardown report, generating the appropriate
+ xml tags as necessary.
+
+ note: due to plugins like xdist, this hook may be called in interlaced
+ order with reports from other nodes. for example:
+
+ usual call order:
+ -> setup node1
+ -> call node1
+ -> teardown node1
+ -> setup node2
+ -> call node2
+ -> teardown node2
+
+ possible call order in xdist:
+ -> setup node1
+ -> call node1
+ -> setup node2
+ -> call node2
+ -> teardown node2
+ -> teardown node1
+ """
+ close_report = None
+ if report.passed:
+ if report.when == "call": # ignore setup/teardown
+ reporter = self._opentestcase(report)
+ reporter.append_pass(report)
+ elif report.failed:
+ if report.when == "teardown":
+ # The following vars are needed when xdist plugin is used
+ report_wid = getattr(report, "worker_id", None)
+ report_ii = getattr(report, "item_index", None)
+ close_report = next(
+ (rep for rep in self.open_reports
+ if (rep.nodeid == report.nodeid and
+ getattr(rep, "item_index", None) == report_ii and
+ getattr(rep, "worker_id", None) == report_wid
+ )
+ ), None)
+ if close_report:
+ # We need to open new testcase in case we have failure in
+ # call and error in teardown in order to follow junit
+ # schema
+ self.finalize(close_report)
+ self.cnt_double_fail_tests += 1
+ reporter = self._opentestcase(report)
+ if report.when == "call":
+ reporter.append_failure(report)
+ self.open_reports.append(report)
+ else:
+ reporter.append_error(report)
+ elif report.skipped:
+ reporter = self._opentestcase(report)
+ reporter.append_skipped(report)
+ self.update_testcase_duration(report)
+ if report.when == "teardown":
+ reporter = self._opentestcase(report)
+ reporter.write_captured_output(report)
+ self.finalize(report)
+ report_wid = getattr(report, "worker_id", None)
+ report_ii = getattr(report, "item_index", None)
+ close_report = next(
+ (rep for rep in self.open_reports
+ if (rep.nodeid == report.nodeid and
+ getattr(rep, "item_index", None) == report_ii and
+ getattr(rep, "worker_id", None) == report_wid
+ )
+ ), None)
+ if close_report:
+ self.open_reports.remove(close_report)
+
+ def update_testcase_duration(self, report):
+ """accumulates total duration for nodeid from given report and updates
+ the Junit.testcase with the new total if already created.
+ """
+ reporter = self.node_reporter(report)
+ reporter.duration += getattr(report, 'duration', 0.0)
+
+ def pytest_collectreport(self, report):
+ if not report.passed:
+ reporter = self._opentestcase(report)
+ if report.failed:
+ reporter.append_collect_error(report)
+ else:
+ reporter.append_collect_skipped(report)
+
+ def pytest_internalerror(self, excrepr):
+ reporter = self.node_reporter('internal')
+ reporter.attrs.update(classname="pytest", name='internal')
+ reporter._add_simple(Junit.error, 'internal error', excrepr)
+
+ def pytest_sessionstart(self):
+ self.suite_start_time = time.time()
+
+ def pytest_sessionfinish(self):
+ dirname = os.path.dirname(os.path.abspath(self.logfile))
+ if not os.path.isdir(dirname):
+ os.makedirs(dirname)
+ logfile = open(self.logfile, 'w', encoding='utf-8')
+ suite_stop_time = time.time()
+ suite_time_delta = suite_stop_time - self.suite_start_time
+
+ numtests = (self.stats['passed'] + self.stats['failure'] +
+ self.stats['skipped'] + self.stats['error'] -
+ self.cnt_double_fail_tests)
+ logfile.write('<?xml version="1.0" encoding="utf-8"?>')
+
+ logfile.write(Junit.testsuite(
+ self._get_global_properties_node(),
+ [x.to_xml() for x in self.node_reporters_ordered],
+ name=self.suite_name,
+ errors=self.stats['error'],
+ failures=self.stats['failure'],
+ skips=self.stats['skipped'],
+ tests=numtests,
+ time="%.3f" % suite_time_delta, ).unicode(indent=0))
+ logfile.close()
+
+ def pytest_terminal_summary(self, terminalreporter):
+ terminalreporter.write_sep("-",
+ "generated xml file: %s" % (self.logfile))
+
+ def add_global_property(self, name, value):
+ self.global_properties.append((str(name), bin_xml_escape(value)))
+
+ def _get_global_properties_node(self):
+ """Return a Junit node containing custom properties, if any.
+ """
+ if self.global_properties:
+ return Junit.properties(
+ [
+ Junit.property(name=name, value=value)
+ for name, value in self.global_properties
+ ]
+ )
+ return ''
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/logging.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/logging.py
new file mode 100644
index 00000000000..ed4db25ad44
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/logging.py
@@ -0,0 +1,337 @@
+from __future__ import absolute_import, division, print_function
+
+import logging
+from contextlib import closing, contextmanager
+import sys
+import six
+
+import pytest
+import py
+
+
+DEFAULT_LOG_FORMAT = '%(filename)-25s %(lineno)4d %(levelname)-8s %(message)s'
+DEFAULT_LOG_DATE_FORMAT = '%H:%M:%S'
+
+
+def get_option_ini(config, *names):
+ for name in names:
+ ret = config.getoption(name) # 'default' arg won't work as expected
+ if ret is None:
+ ret = config.getini(name)
+ if ret:
+ return ret
+
+
+def pytest_addoption(parser):
+ """Add options to control log capturing."""
+ group = parser.getgroup('logging')
+
+ def add_option_ini(option, dest, default=None, type=None, **kwargs):
+ parser.addini(dest, default=default, type=type,
+ help='default value for ' + option)
+ group.addoption(option, dest=dest, **kwargs)
+
+ add_option_ini(
+ '--no-print-logs',
+ dest='log_print', action='store_const', const=False, default=True,
+ type='bool',
+ help='disable printing caught logs on failed tests.')
+ add_option_ini(
+ '--log-level',
+ dest='log_level', default=None,
+ help='logging level used by the logging module')
+ add_option_ini(
+ '--log-format',
+ dest='log_format', default=DEFAULT_LOG_FORMAT,
+ help='log format as used by the logging module.')
+ add_option_ini(
+ '--log-date-format',
+ dest='log_date_format', default=DEFAULT_LOG_DATE_FORMAT,
+ help='log date format as used by the logging module.')
+ add_option_ini(
+ '--log-cli-level',
+ dest='log_cli_level', default=None,
+ help='cli logging level.')
+ add_option_ini(
+ '--log-cli-format',
+ dest='log_cli_format', default=None,
+ help='log format as used by the logging module.')
+ add_option_ini(
+ '--log-cli-date-format',
+ dest='log_cli_date_format', default=None,
+ help='log date format as used by the logging module.')
+ add_option_ini(
+ '--log-file',
+ dest='log_file', default=None,
+ help='path to a file when logging will be written to.')
+ add_option_ini(
+ '--log-file-level',
+ dest='log_file_level', default=None,
+ help='log file logging level.')
+ add_option_ini(
+ '--log-file-format',
+ dest='log_file_format', default=DEFAULT_LOG_FORMAT,
+ help='log format as used by the logging module.')
+ add_option_ini(
+ '--log-file-date-format',
+ dest='log_file_date_format', default=DEFAULT_LOG_DATE_FORMAT,
+ help='log date format as used by the logging module.')
+
+
+@contextmanager
+def logging_using_handler(handler, logger=None):
+ """Context manager that safely registers a given handler."""
+ logger = logger or logging.getLogger(logger)
+
+ if handler in logger.handlers: # reentrancy
+ # Adding the same handler twice would confuse logging system.
+ # Just don't do that.
+ yield
+ else:
+ logger.addHandler(handler)
+ try:
+ yield
+ finally:
+ logger.removeHandler(handler)
+
+
+@contextmanager
+def catching_logs(handler, formatter=None,
+ level=logging.NOTSET, logger=None):
+ """Context manager that prepares the whole logging machinery properly."""
+ logger = logger or logging.getLogger(logger)
+
+ if formatter is not None:
+ handler.setFormatter(formatter)
+ handler.setLevel(level)
+
+ with logging_using_handler(handler, logger):
+ orig_level = logger.level
+ logger.setLevel(min(orig_level, level))
+ try:
+ yield handler
+ finally:
+ logger.setLevel(orig_level)
+
+
+class LogCaptureHandler(logging.StreamHandler):
+ """A logging handler that stores log records and the log text."""
+
+ def __init__(self):
+ """Creates a new log handler."""
+ logging.StreamHandler.__init__(self, py.io.TextIO())
+ self.records = []
+
+ def emit(self, record):
+ """Keep the log records in a list in addition to the log text."""
+ self.records.append(record)
+ logging.StreamHandler.emit(self, record)
+
+
+class LogCaptureFixture(object):
+ """Provides access and control of log capturing."""
+
+ def __init__(self, item):
+ """Creates a new funcarg."""
+ self._item = item
+
+ @property
+ def handler(self):
+ return self._item.catch_log_handler
+
+ @property
+ def text(self):
+ """Returns the log text."""
+ return self.handler.stream.getvalue()
+
+ @property
+ def records(self):
+ """Returns the list of log records."""
+ return self.handler.records
+
+ @property
+ def record_tuples(self):
+ """Returns a list of a striped down version of log records intended
+ for use in assertion comparison.
+
+ The format of the tuple is:
+
+ (logger_name, log_level, message)
+ """
+ return [(r.name, r.levelno, r.getMessage()) for r in self.records]
+
+ def clear(self):
+ """Reset the list of log records."""
+ self.handler.records = []
+
+ def set_level(self, level, logger=None):
+ """Sets the level for capturing of logs.
+
+ By default, the level is set on the handler used to capture
+ logs. Specify a logger name to instead set the level of any
+ logger.
+ """
+ if logger is None:
+ logger = self.handler
+ else:
+ logger = logging.getLogger(logger)
+ logger.setLevel(level)
+
+ @contextmanager
+ def at_level(self, level, logger=None):
+ """Context manager that sets the level for capturing of logs.
+
+ By default, the level is set on the handler used to capture
+ logs. Specify a logger name to instead set the level of any
+ logger.
+ """
+ if logger is None:
+ logger = self.handler
+ else:
+ logger = logging.getLogger(logger)
+
+ orig_level = logger.level
+ logger.setLevel(level)
+ try:
+ yield
+ finally:
+ logger.setLevel(orig_level)
+
+
+@pytest.fixture
+def caplog(request):
+ """Access and control log capturing.
+
+ Captured logs are available through the following methods::
+
+ * caplog.text() -> string containing formatted log output
+ * caplog.records() -> list of logging.LogRecord instances
+ * caplog.record_tuples() -> list of (logger_name, level, message) tuples
+ """
+ return LogCaptureFixture(request.node)
+
+
+def get_actual_log_level(config, *setting_names):
+ """Return the actual logging level."""
+
+ for setting_name in setting_names:
+ log_level = config.getoption(setting_name)
+ if log_level is None:
+ log_level = config.getini(setting_name)
+ if log_level:
+ break
+ else:
+ return
+
+ if isinstance(log_level, six.string_types):
+ log_level = log_level.upper()
+ try:
+ return int(getattr(logging, log_level, log_level))
+ except ValueError:
+ # Python logging does not recognise this as a logging level
+ raise pytest.UsageError(
+ "'{0}' is not recognized as a logging level name for "
+ "'{1}'. Please consider passing the "
+ "logging level num instead.".format(
+ log_level,
+ setting_name))
+
+
+def pytest_configure(config):
+ config.pluginmanager.register(LoggingPlugin(config),
+ 'logging-plugin')
+
+
+class LoggingPlugin(object):
+ """Attaches to the logging module and captures log messages for each test.
+ """
+
+ def __init__(self, config):
+ """Creates a new plugin to capture log messages.
+
+ The formatter can be safely shared across all handlers so
+ create a single one for the entire test session here.
+ """
+ self.log_cli_level = get_actual_log_level(
+ config, 'log_cli_level', 'log_level') or logging.WARNING
+
+ self.print_logs = get_option_ini(config, 'log_print')
+ self.formatter = logging.Formatter(
+ get_option_ini(config, 'log_format'),
+ get_option_ini(config, 'log_date_format'))
+
+ log_cli_handler = logging.StreamHandler(sys.stderr)
+ log_cli_format = get_option_ini(
+ config, 'log_cli_format', 'log_format')
+ log_cli_date_format = get_option_ini(
+ config, 'log_cli_date_format', 'log_date_format')
+ log_cli_formatter = logging.Formatter(
+ log_cli_format,
+ datefmt=log_cli_date_format)
+ self.log_cli_handler = log_cli_handler # needed for a single unittest
+ self.live_logs = catching_logs(log_cli_handler,
+ formatter=log_cli_formatter,
+ level=self.log_cli_level)
+
+ log_file = get_option_ini(config, 'log_file')
+ if log_file:
+ self.log_file_level = get_actual_log_level(
+ config, 'log_file_level') or logging.WARNING
+
+ log_file_format = get_option_ini(
+ config, 'log_file_format', 'log_format')
+ log_file_date_format = get_option_ini(
+ config, 'log_file_date_format', 'log_date_format')
+ self.log_file_handler = logging.FileHandler(
+ log_file,
+ # Each pytest runtests session will write to a clean logfile
+ mode='w')
+ log_file_formatter = logging.Formatter(
+ log_file_format,
+ datefmt=log_file_date_format)
+ self.log_file_handler.setFormatter(log_file_formatter)
+ else:
+ self.log_file_handler = None
+
+ @contextmanager
+ def _runtest_for(self, item, when):
+ """Implements the internals of pytest_runtest_xxx() hook."""
+ with catching_logs(LogCaptureHandler(),
+ formatter=self.formatter) as log_handler:
+ item.catch_log_handler = log_handler
+ try:
+ yield # run test
+ finally:
+ del item.catch_log_handler
+
+ if self.print_logs:
+ # Add a captured log section to the report.
+ log = log_handler.stream.getvalue().strip()
+ item.add_report_section(when, 'log', log)
+
+ @pytest.hookimpl(hookwrapper=True)
+ def pytest_runtest_setup(self, item):
+ with self._runtest_for(item, 'setup'):
+ yield
+
+ @pytest.hookimpl(hookwrapper=True)
+ def pytest_runtest_call(self, item):
+ with self._runtest_for(item, 'call'):
+ yield
+
+ @pytest.hookimpl(hookwrapper=True)
+ def pytest_runtest_teardown(self, item):
+ with self._runtest_for(item, 'teardown'):
+ yield
+
+ @pytest.hookimpl(hookwrapper=True)
+ def pytest_runtestloop(self, session):
+ """Runs all collected test items."""
+ with self.live_logs:
+ if self.log_file_handler is not None:
+ with closing(self.log_file_handler):
+ with catching_logs(self.log_file_handler,
+ level=self.log_file_level):
+ yield # run all the tests
+ else:
+ yield # run all the tests
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/main.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/main.py
new file mode 100644
index 00000000000..25554098dac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/main.py
@@ -0,0 +1,821 @@
+""" core implementation of testing process: init, session, runtest loop. """
+from __future__ import absolute_import, division, print_function
+
+import functools
+import os
+import six
+import sys
+
+import _pytest
+from _pytest import nodes
+import _pytest._code
+import py
+try:
+ from collections import MutableMapping as MappingMixin
+except ImportError:
+ from UserDict import DictMixin as MappingMixin
+
+from _pytest.config import directory_arg, UsageError, hookimpl
+from _pytest.outcomes import exit
+from _pytest.runner import collect_one_node
+
+tracebackcutdir = py.path.local(_pytest.__file__).dirpath()
+
+# exitcodes for the command line
+EXIT_OK = 0
+EXIT_TESTSFAILED = 1
+EXIT_INTERRUPTED = 2
+EXIT_INTERNALERROR = 3
+EXIT_USAGEERROR = 4
+EXIT_NOTESTSCOLLECTED = 5
+
+
+def pytest_addoption(parser):
+ parser.addini("norecursedirs", "directory patterns to avoid for recursion",
+ type="args", default=['.*', 'build', 'dist', 'CVS', '_darcs', '{arch}', '*.egg', 'venv'])
+ parser.addini("testpaths", "directories to search for tests when no files or directories are given in the "
+ "command line.",
+ type="args", default=[])
+ # parser.addini("dirpatterns",
+ # "patterns specifying possible locations of test files",
+ # type="linelist", default=["**/test_*.txt",
+ # "**/test_*.py", "**/*_test.py"]
+ # )
+ group = parser.getgroup("general", "running and selection options")
+ group._addoption('-x', '--exitfirst', action="store_const",
+ dest="maxfail", const=1,
+ help="exit instantly on first error or failed test."),
+ group._addoption('--maxfail', metavar="num",
+ action="store", type=int, dest="maxfail", default=0,
+ help="exit after first num failures or errors.")
+ group._addoption('--strict', action="store_true",
+ help="marks not registered in configuration file raise errors.")
+ group._addoption("-c", metavar="file", type=str, dest="inifilename",
+ help="load configuration from `file` instead of trying to locate one of the implicit "
+ "configuration files.")
+ group._addoption("--continue-on-collection-errors", action="store_true",
+ default=False, dest="continue_on_collection_errors",
+ help="Force test execution even if collection errors occur.")
+
+ group = parser.getgroup("collect", "collection")
+ group.addoption('--collectonly', '--collect-only', action="store_true",
+ help="only collect tests, don't execute them."),
+ group.addoption('--pyargs', action="store_true",
+ help="try to interpret all arguments as python packages.")
+ group.addoption("--ignore", action="append", metavar="path",
+ help="ignore path during collection (multi-allowed).")
+ # when changing this to --conf-cut-dir, config.py Conftest.setinitial
+ # needs upgrading as well
+ group.addoption('--confcutdir', dest="confcutdir", default=None,
+ metavar="dir", type=functools.partial(directory_arg, optname="--confcutdir"),
+ help="only load conftest.py's relative to specified dir.")
+ group.addoption('--noconftest', action="store_true",
+ dest="noconftest", default=False,
+ help="Don't load any conftest.py files.")
+ group.addoption('--keepduplicates', '--keep-duplicates', action="store_true",
+ dest="keepduplicates", default=False,
+ help="Keep duplicate tests.")
+ group.addoption('--collect-in-virtualenv', action='store_true',
+ dest='collect_in_virtualenv', default=False,
+ help="Don't ignore tests in a local virtualenv directory")
+
+ group = parser.getgroup("debugconfig",
+ "test session debugging and configuration")
+ group.addoption('--basetemp', dest="basetemp", default=None, metavar="dir",
+ help="base temporary directory for this test run.")
+
+
+def pytest_configure(config):
+ __import__('pytest').config = config # compatibiltiy
+
+
+def wrap_session(config, doit):
+ """Skeleton command line program"""
+ session = Session(config)
+ session.exitstatus = EXIT_OK
+ initstate = 0
+ try:
+ try:
+ config._do_configure()
+ initstate = 1
+ config.hook.pytest_sessionstart(session=session)
+ initstate = 2
+ session.exitstatus = doit(config, session) or 0
+ except UsageError:
+ raise
+ except Failed:
+ session.exitstatus = EXIT_TESTSFAILED
+ except KeyboardInterrupt:
+ excinfo = _pytest._code.ExceptionInfo()
+ if initstate < 2 and isinstance(excinfo.value, exit.Exception):
+ sys.stderr.write('{0}: {1}\n'.format(
+ excinfo.typename, excinfo.value.msg))
+ config.hook.pytest_keyboard_interrupt(excinfo=excinfo)
+ session.exitstatus = EXIT_INTERRUPTED
+ except: # noqa
+ excinfo = _pytest._code.ExceptionInfo()
+ config.notify_exception(excinfo, config.option)
+ session.exitstatus = EXIT_INTERNALERROR
+ if excinfo.errisinstance(SystemExit):
+ sys.stderr.write("mainloop: caught Spurious SystemExit!\n")
+
+ finally:
+ excinfo = None # Explicitly break reference cycle.
+ session.startdir.chdir()
+ if initstate >= 2:
+ config.hook.pytest_sessionfinish(
+ session=session,
+ exitstatus=session.exitstatus)
+ config._ensure_unconfigure()
+ return session.exitstatus
+
+
+def pytest_cmdline_main(config):
+ return wrap_session(config, _main)
+
+
+def _main(config, session):
+ """ default command line protocol for initialization, session,
+ running tests and reporting. """
+ config.hook.pytest_collection(session=session)
+ config.hook.pytest_runtestloop(session=session)
+
+ if session.testsfailed:
+ return EXIT_TESTSFAILED
+ elif session.testscollected == 0:
+ return EXIT_NOTESTSCOLLECTED
+
+
+def pytest_collection(session):
+ return session.perform_collect()
+
+
+def pytest_runtestloop(session):
+ if (session.testsfailed and
+ not session.config.option.continue_on_collection_errors):
+ raise session.Interrupted(
+ "%d errors during collection" % session.testsfailed)
+
+ if session.config.option.collectonly:
+ return True
+
+ for i, item in enumerate(session.items):
+ nextitem = session.items[i + 1] if i + 1 < len(session.items) else None
+ item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem)
+ if session.shouldfail:
+ raise session.Failed(session.shouldfail)
+ if session.shouldstop:
+ raise session.Interrupted(session.shouldstop)
+ return True
+
+
+def _in_venv(path):
+ """Attempts to detect if ``path`` is the root of a Virtual Environment by
+ checking for the existence of the appropriate activate script"""
+ bindir = path.join('Scripts' if sys.platform.startswith('win') else 'bin')
+ if not bindir.exists():
+ return False
+ activates = ('activate', 'activate.csh', 'activate.fish',
+ 'Activate', 'Activate.bat', 'Activate.ps1')
+ return any([fname.basename in activates for fname in bindir.listdir()])
+
+
+def pytest_ignore_collect(path, config):
+ ignore_paths = config._getconftest_pathlist("collect_ignore", path=path.dirpath())
+ ignore_paths = ignore_paths or []
+ excludeopt = config.getoption("ignore")
+ if excludeopt:
+ ignore_paths.extend([py.path.local(x) for x in excludeopt])
+
+ if py.path.local(path) in ignore_paths:
+ return True
+
+ allow_in_venv = config.getoption("collect_in_virtualenv")
+ if _in_venv(path) and not allow_in_venv:
+ return True
+
+ # Skip duplicate paths.
+ keepduplicates = config.getoption("keepduplicates")
+ duplicate_paths = config.pluginmanager._duplicatepaths
+ if not keepduplicates:
+ if path in duplicate_paths:
+ return True
+ else:
+ duplicate_paths.add(path)
+
+ return False
+
+
+class FSHookProxy:
+ def __init__(self, fspath, pm, remove_mods):
+ self.fspath = fspath
+ self.pm = pm
+ self.remove_mods = remove_mods
+
+ def __getattr__(self, name):
+ x = self.pm.subset_hook_caller(name, remove_plugins=self.remove_mods)
+ self.__dict__[name] = x
+ return x
+
+
+class _CompatProperty(object):
+ def __init__(self, name):
+ self.name = name
+
+ def __get__(self, obj, owner):
+ if obj is None:
+ return self
+
+ # TODO: reenable in the features branch
+ # warnings.warn(
+ # "usage of {owner!r}.{name} is deprecated, please use pytest.{name} instead".format(
+ # name=self.name, owner=type(owner).__name__),
+ # PendingDeprecationWarning, stacklevel=2)
+ return getattr(__import__('pytest'), self.name)
+
+
+class NodeKeywords(MappingMixin):
+ def __init__(self, node):
+ self.node = node
+ self.parent = node.parent
+ self._markers = {node.name: True}
+
+ def __getitem__(self, key):
+ try:
+ return self._markers[key]
+ except KeyError:
+ if self.parent is None:
+ raise
+ return self.parent.keywords[key]
+
+ def __setitem__(self, key, value):
+ self._markers[key] = value
+
+ def __delitem__(self, key):
+ raise ValueError("cannot delete key in keywords dict")
+
+ def __iter__(self):
+ seen = set(self._markers)
+ if self.parent is not None:
+ seen.update(self.parent.keywords)
+ return iter(seen)
+
+ def __len__(self):
+ return len(self.__iter__())
+
+ def keys(self):
+ return list(self)
+
+ def __repr__(self):
+ return "<NodeKeywords for node %s>" % (self.node, )
+
+
+class Node(object):
+ """ base class for Collector and Item the test collection tree.
+ Collector subclasses have children, Items are terminal nodes."""
+
+ def __init__(self, name, parent=None, config=None, session=None):
+ #: a unique name within the scope of the parent node
+ self.name = name
+
+ #: the parent collector node.
+ self.parent = parent
+
+ #: the pytest config object
+ self.config = config or parent.config
+
+ #: the session this node is part of
+ self.session = session or parent.session
+
+ #: filesystem path where this node was collected from (can be None)
+ self.fspath = getattr(parent, 'fspath', None)
+
+ #: keywords/markers collected from all scopes
+ self.keywords = NodeKeywords(self)
+
+ #: allow adding of extra keywords to use for matching
+ self.extra_keyword_matches = set()
+
+ # used for storing artificial fixturedefs for direct parametrization
+ self._name2pseudofixturedef = {}
+
+ @property
+ def ihook(self):
+ """ fspath sensitive hook proxy used to call pytest hooks"""
+ return self.session.gethookproxy(self.fspath)
+
+ Module = _CompatProperty("Module")
+ Class = _CompatProperty("Class")
+ Instance = _CompatProperty("Instance")
+ Function = _CompatProperty("Function")
+ File = _CompatProperty("File")
+ Item = _CompatProperty("Item")
+
+ def _getcustomclass(self, name):
+ maybe_compatprop = getattr(type(self), name)
+ if isinstance(maybe_compatprop, _CompatProperty):
+ return getattr(__import__('pytest'), name)
+ else:
+ cls = getattr(self, name)
+ # TODO: reenable in the features branch
+ # warnings.warn("use of node.%s is deprecated, "
+ # "use pytest_pycollect_makeitem(...) to create custom "
+ # "collection nodes" % name, category=DeprecationWarning)
+ return cls
+
+ def __repr__(self):
+ return "<%s %r>" % (self.__class__.__name__,
+ getattr(self, 'name', None))
+
+ def warn(self, code, message):
+ """ generate a warning with the given code and message for this
+ item. """
+ assert isinstance(code, str)
+ fslocation = getattr(self, "location", None)
+ if fslocation is None:
+ fslocation = getattr(self, "fspath", None)
+ self.ihook.pytest_logwarning.call_historic(kwargs=dict(
+ code=code, message=message,
+ nodeid=self.nodeid, fslocation=fslocation))
+
+ # methods for ordering nodes
+ @property
+ def nodeid(self):
+ """ a ::-separated string denoting its collection tree address. """
+ try:
+ return self._nodeid
+ except AttributeError:
+ self._nodeid = x = self._makeid()
+ return x
+
+ def _makeid(self):
+ return self.parent.nodeid + "::" + self.name
+
+ def __hash__(self):
+ return hash(self.nodeid)
+
+ def setup(self):
+ pass
+
+ def teardown(self):
+ pass
+
+ def listchain(self):
+ """ return list of all parent collectors up to self,
+ starting from root of collection tree. """
+ chain = []
+ item = self
+ while item is not None:
+ chain.append(item)
+ item = item.parent
+ chain.reverse()
+ return chain
+
+ def add_marker(self, marker):
+ """ dynamically add a marker object to the node.
+
+ ``marker`` can be a string or pytest.mark.* instance.
+ """
+ from _pytest.mark import MarkDecorator, MARK_GEN
+ if isinstance(marker, six.string_types):
+ marker = getattr(MARK_GEN, marker)
+ elif not isinstance(marker, MarkDecorator):
+ raise ValueError("is not a string or pytest.mark.* Marker")
+ self.keywords[marker.name] = marker
+
+ def get_marker(self, name):
+ """ get a marker object from this node or None if
+ the node doesn't have a marker with that name. """
+ val = self.keywords.get(name, None)
+ if val is not None:
+ from _pytest.mark import MarkInfo, MarkDecorator
+ if isinstance(val, (MarkDecorator, MarkInfo)):
+ return val
+
+ def listextrakeywords(self):
+ """ Return a set of all extra keywords in self and any parents."""
+ extra_keywords = set()
+ item = self
+ for item in self.listchain():
+ extra_keywords.update(item.extra_keyword_matches)
+ return extra_keywords
+
+ def listnames(self):
+ return [x.name for x in self.listchain()]
+
+ def addfinalizer(self, fin):
+ """ register a function to be called when this node is finalized.
+
+ This method can only be called when this node is active
+ in a setup chain, for example during self.setup().
+ """
+ self.session._setupstate.addfinalizer(fin, self)
+
+ def getparent(self, cls):
+ """ get the next parent node (including ourself)
+ which is an instance of the given class"""
+ current = self
+ while current and not isinstance(current, cls):
+ current = current.parent
+ return current
+
+ def _prunetraceback(self, excinfo):
+ pass
+
+ def _repr_failure_py(self, excinfo, style=None):
+ fm = self.session._fixturemanager
+ if excinfo.errisinstance(fm.FixtureLookupError):
+ return excinfo.value.formatrepr()
+ tbfilter = True
+ if self.config.option.fulltrace:
+ style = "long"
+ else:
+ tb = _pytest._code.Traceback([excinfo.traceback[-1]])
+ self._prunetraceback(excinfo)
+ if len(excinfo.traceback) == 0:
+ excinfo.traceback = tb
+ tbfilter = False # prunetraceback already does it
+ if style == "auto":
+ style = "long"
+ # XXX should excinfo.getrepr record all data and toterminal() process it?
+ if style is None:
+ if self.config.option.tbstyle == "short":
+ style = "short"
+ else:
+ style = "long"
+
+ try:
+ os.getcwd()
+ abspath = False
+ except OSError:
+ abspath = True
+
+ return excinfo.getrepr(funcargs=True, abspath=abspath,
+ showlocals=self.config.option.showlocals,
+ style=style, tbfilter=tbfilter)
+
+ repr_failure = _repr_failure_py
+
+
+class Collector(Node):
+ """ Collector instances create children through collect()
+ and thus iteratively build a tree.
+ """
+
+ class CollectError(Exception):
+ """ an error during collection, contains a custom message. """
+
+ def collect(self):
+ """ returns a list of children (items and collectors)
+ for this collection node.
+ """
+ raise NotImplementedError("abstract")
+
+ def repr_failure(self, excinfo):
+ """ represent a collection failure. """
+ if excinfo.errisinstance(self.CollectError):
+ exc = excinfo.value
+ return str(exc.args[0])
+ return self._repr_failure_py(excinfo, style="short")
+
+ def _prunetraceback(self, excinfo):
+ if hasattr(self, 'fspath'):
+ traceback = excinfo.traceback
+ ntraceback = traceback.cut(path=self.fspath)
+ if ntraceback == traceback:
+ ntraceback = ntraceback.cut(excludepath=tracebackcutdir)
+ excinfo.traceback = ntraceback.filter()
+
+
+class FSCollector(Collector):
+ def __init__(self, fspath, parent=None, config=None, session=None):
+ fspath = py.path.local(fspath) # xxx only for test_resultlog.py?
+ name = fspath.basename
+ if parent is not None:
+ rel = fspath.relto(parent.fspath)
+ if rel:
+ name = rel
+ name = name.replace(os.sep, nodes.SEP)
+ super(FSCollector, self).__init__(name, parent, config, session)
+ self.fspath = fspath
+
+ def _check_initialpaths_for_relpath(self):
+ for initialpath in self.session._initialpaths:
+ if self.fspath.common(initialpath) == initialpath:
+ return self.fspath.relto(initialpath.dirname)
+
+ def _makeid(self):
+ relpath = self.fspath.relto(self.config.rootdir)
+
+ if not relpath:
+ relpath = self._check_initialpaths_for_relpath()
+ if os.sep != nodes.SEP:
+ relpath = relpath.replace(os.sep, nodes.SEP)
+ return relpath
+
+
+class File(FSCollector):
+ """ base class for collecting tests from a file. """
+
+
+class Item(Node):
+ """ a basic test invocation item. Note that for a single function
+ there might be multiple test invocation items.
+ """
+ nextitem = None
+
+ def __init__(self, name, parent=None, config=None, session=None):
+ super(Item, self).__init__(name, parent, config, session)
+ self._report_sections = []
+
+ def add_report_section(self, when, key, content):
+ """
+ Adds a new report section, similar to what's done internally to add stdout and
+ stderr captured output::
+
+ item.add_report_section("call", "stdout", "report section contents")
+
+ :param str when:
+ One of the possible capture states, ``"setup"``, ``"call"``, ``"teardown"``.
+ :param str key:
+ Name of the section, can be customized at will. Pytest uses ``"stdout"`` and
+ ``"stderr"`` internally.
+
+ :param str content:
+ The full contents as a string.
+ """
+ if content:
+ self._report_sections.append((when, key, content))
+
+ def reportinfo(self):
+ return self.fspath, None, ""
+
+ @property
+ def location(self):
+ try:
+ return self._location
+ except AttributeError:
+ location = self.reportinfo()
+ # bestrelpath is a quite slow function
+ cache = self.config.__dict__.setdefault("_bestrelpathcache", {})
+ try:
+ fspath = cache[location[0]]
+ except KeyError:
+ fspath = self.session.fspath.bestrelpath(location[0])
+ cache[location[0]] = fspath
+ location = (fspath, location[1], str(location[2]))
+ self._location = location
+ return location
+
+
+class NoMatch(Exception):
+ """ raised if matching cannot locate a matching names. """
+
+
+class Interrupted(KeyboardInterrupt):
+ """ signals an interrupted test run. """
+ __module__ = 'builtins' # for py3
+
+
+class Failed(Exception):
+ """ signals an stop as failed test run. """
+
+
+class Session(FSCollector):
+ Interrupted = Interrupted
+ Failed = Failed
+
+ def __init__(self, config):
+ FSCollector.__init__(self, config.rootdir, parent=None,
+ config=config, session=self)
+ self.testsfailed = 0
+ self.testscollected = 0
+ self.shouldstop = False
+ self.shouldfail = False
+ self.trace = config.trace.root.get("collection")
+ self._norecursepatterns = config.getini("norecursedirs")
+ self.startdir = py.path.local()
+ self.config.pluginmanager.register(self, name="session")
+
+ def _makeid(self):
+ return ""
+
+ @hookimpl(tryfirst=True)
+ def pytest_collectstart(self):
+ if self.shouldfail:
+ raise self.Failed(self.shouldfail)
+ if self.shouldstop:
+ raise self.Interrupted(self.shouldstop)
+
+ @hookimpl(tryfirst=True)
+ def pytest_runtest_logreport(self, report):
+ if report.failed and not hasattr(report, 'wasxfail'):
+ self.testsfailed += 1
+ maxfail = self.config.getvalue("maxfail")
+ if maxfail and self.testsfailed >= maxfail:
+ self.shouldfail = "stopping after %d failures" % (
+ self.testsfailed)
+ pytest_collectreport = pytest_runtest_logreport
+
+ def isinitpath(self, path):
+ return path in self._initialpaths
+
+ def gethookproxy(self, fspath):
+ # check if we have the common case of running
+ # hooks with all conftest.py filesall conftest.py
+ pm = self.config.pluginmanager
+ my_conftestmodules = pm._getconftestmodules(fspath)
+ remove_mods = pm._conftest_plugins.difference(my_conftestmodules)
+ if remove_mods:
+ # one or more conftests are not in use at this fspath
+ proxy = FSHookProxy(fspath, pm, remove_mods)
+ else:
+ # all plugis are active for this fspath
+ proxy = self.config.hook
+ return proxy
+
+ def perform_collect(self, args=None, genitems=True):
+ hook = self.config.hook
+ try:
+ items = self._perform_collect(args, genitems)
+ self.config.pluginmanager.check_pending()
+ hook.pytest_collection_modifyitems(session=self,
+ config=self.config, items=items)
+ finally:
+ hook.pytest_collection_finish(session=self)
+ self.testscollected = len(items)
+ return items
+
+ def _perform_collect(self, args, genitems):
+ if args is None:
+ args = self.config.args
+ self.trace("perform_collect", self, args)
+ self.trace.root.indent += 1
+ self._notfound = []
+ self._initialpaths = set()
+ self._initialparts = []
+ self.items = items = []
+ for arg in args:
+ parts = self._parsearg(arg)
+ self._initialparts.append(parts)
+ self._initialpaths.add(parts[0])
+ rep = collect_one_node(self)
+ self.ihook.pytest_collectreport(report=rep)
+ self.trace.root.indent -= 1
+ if self._notfound:
+ errors = []
+ for arg, exc in self._notfound:
+ line = "(no name %r in any of %r)" % (arg, exc.args[0])
+ errors.append("not found: %s\n%s" % (arg, line))
+ # XXX: test this
+ raise UsageError(*errors)
+ if not genitems:
+ return rep.result
+ else:
+ if rep.passed:
+ for node in rep.result:
+ self.items.extend(self.genitems(node))
+ return items
+
+ def collect(self):
+ for parts in self._initialparts:
+ arg = "::".join(map(str, parts))
+ self.trace("processing argument", arg)
+ self.trace.root.indent += 1
+ try:
+ for x in self._collect(arg):
+ yield x
+ except NoMatch:
+ # we are inside a make_report hook so
+ # we cannot directly pass through the exception
+ self._notfound.append((arg, sys.exc_info()[1]))
+
+ self.trace.root.indent -= 1
+
+ def _collect(self, arg):
+ names = self._parsearg(arg)
+ path = names.pop(0)
+ if path.check(dir=1):
+ assert not names, "invalid arg %r" % (arg,)
+ for path in path.visit(fil=lambda x: x.check(file=1),
+ rec=self._recurse, bf=True, sort=True):
+ for x in self._collectfile(path):
+ yield x
+ else:
+ assert path.check(file=1)
+ for x in self.matchnodes(self._collectfile(path), names):
+ yield x
+
+ def _collectfile(self, path):
+ ihook = self.gethookproxy(path)
+ if not self.isinitpath(path):
+ if ihook.pytest_ignore_collect(path=path, config=self.config):
+ return ()
+ return ihook.pytest_collect_file(path=path, parent=self)
+
+ def _recurse(self, path):
+ ihook = self.gethookproxy(path.dirpath())
+ if ihook.pytest_ignore_collect(path=path, config=self.config):
+ return
+ for pat in self._norecursepatterns:
+ if path.check(fnmatch=pat):
+ return False
+ ihook = self.gethookproxy(path)
+ ihook.pytest_collect_directory(path=path, parent=self)
+ return True
+
+ def _tryconvertpyarg(self, x):
+ """Convert a dotted module name to path.
+
+ """
+ import pkgutil
+ try:
+ loader = pkgutil.find_loader(x)
+ except ImportError:
+ return x
+ if loader is None:
+ return x
+ # This method is sometimes invoked when AssertionRewritingHook, which
+ # does not define a get_filename method, is already in place:
+ try:
+ path = loader.get_filename(x)
+ except AttributeError:
+ # Retrieve path from AssertionRewritingHook:
+ path = loader.modules[x][0].co_filename
+ if loader.is_package(x):
+ path = os.path.dirname(path)
+ return path
+
+ def _parsearg(self, arg):
+ """ return (fspath, names) tuple after checking the file exists. """
+ parts = str(arg).split("::")
+ if self.config.option.pyargs:
+ parts[0] = self._tryconvertpyarg(parts[0])
+ relpath = parts[0].replace("/", os.sep)
+ path = self.config.invocation_dir.join(relpath, abs=True)
+ if not path.check():
+ if self.config.option.pyargs:
+ raise UsageError(
+ "file or package not found: " + arg +
+ " (missing __init__.py?)")
+ else:
+ raise UsageError("file not found: " + arg)
+ parts[0] = path
+ return parts
+
+ def matchnodes(self, matching, names):
+ self.trace("matchnodes", matching, names)
+ self.trace.root.indent += 1
+ nodes = self._matchnodes(matching, names)
+ num = len(nodes)
+ self.trace("matchnodes finished -> ", num, "nodes")
+ self.trace.root.indent -= 1
+ if num == 0:
+ raise NoMatch(matching, names[:1])
+ return nodes
+
+ def _matchnodes(self, matching, names):
+ if not matching or not names:
+ return matching
+ name = names[0]
+ assert name
+ nextnames = names[1:]
+ resultnodes = []
+ for node in matching:
+ if isinstance(node, Item):
+ if not names:
+ resultnodes.append(node)
+ continue
+ assert isinstance(node, Collector)
+ rep = collect_one_node(node)
+ if rep.passed:
+ has_matched = False
+ for x in rep.result:
+ # TODO: remove parametrized workaround once collection structure contains parametrization
+ if x.name == name or x.name.split("[")[0] == name:
+ resultnodes.extend(self.matchnodes([x], nextnames))
+ has_matched = True
+ # XXX accept IDs that don't have "()" for class instances
+ if not has_matched and len(rep.result) == 1 and x.name == "()":
+ nextnames.insert(0, name)
+ resultnodes.extend(self.matchnodes([x], nextnames))
+ else:
+ # report collection failures here to avoid failing to run some test
+ # specified in the command line because the module could not be
+ # imported (#134)
+ node.ihook.pytest_collectreport(report=rep)
+ return resultnodes
+
+ def genitems(self, node):
+ self.trace("genitems", node)
+ if isinstance(node, Item):
+ node.ihook.pytest_itemcollected(item=node)
+ yield node
+ else:
+ assert isinstance(node, Collector)
+ rep = collect_one_node(node)
+ if rep.passed:
+ for subnode in rep.result:
+ for x in self.genitems(subnode):
+ yield x
+ node.ihook.pytest_collectreport(report=rep)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/mark.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/mark.py
new file mode 100644
index 00000000000..3f1f01b1a2e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/mark.py
@@ -0,0 +1,496 @@
+""" generic mechanism for marking and selecting python functions. """
+from __future__ import absolute_import, division, print_function
+
+import inspect
+import warnings
+import attr
+from collections import namedtuple
+from operator import attrgetter
+from six.moves import map
+from .deprecated import MARK_PARAMETERSET_UNPACKING
+from .compat import NOTSET, getfslineno
+
+
+def alias(name, warning=None):
+ getter = attrgetter(name)
+
+ def warned(self):
+ warnings.warn(warning, stacklevel=2)
+ return getter(self)
+
+ return property(getter if warning is None else warned, doc='alias for ' + name)
+
+
+class ParameterSet(namedtuple('ParameterSet', 'values, marks, id')):
+ @classmethod
+ def param(cls, *values, **kw):
+ marks = kw.pop('marks', ())
+ if isinstance(marks, MarkDecorator):
+ marks = marks,
+ else:
+ assert isinstance(marks, (tuple, list, set))
+
+ def param_extract_id(id=None):
+ return id
+
+ id = param_extract_id(**kw)
+ return cls(values, marks, id)
+
+ @classmethod
+ def extract_from(cls, parameterset, legacy_force_tuple=False):
+ """
+ :param parameterset:
+ a legacy style parameterset that may or may not be a tuple,
+ and may or may not be wrapped into a mess of mark objects
+
+ :param legacy_force_tuple:
+ enforce tuple wrapping so single argument tuple values
+ don't get decomposed and break tests
+
+ """
+
+ if isinstance(parameterset, cls):
+ return parameterset
+ if not isinstance(parameterset, MarkDecorator) and legacy_force_tuple:
+ return cls.param(parameterset)
+
+ newmarks = []
+ argval = parameterset
+ while isinstance(argval, MarkDecorator):
+ newmarks.append(MarkDecorator(Mark(
+ argval.markname, argval.args[:-1], argval.kwargs)))
+ argval = argval.args[-1]
+ assert not isinstance(argval, ParameterSet)
+ if legacy_force_tuple:
+ argval = argval,
+
+ if newmarks:
+ warnings.warn(MARK_PARAMETERSET_UNPACKING)
+
+ return cls(argval, marks=newmarks, id=None)
+
+ @classmethod
+ def _for_parameterize(cls, argnames, argvalues, function):
+ if not isinstance(argnames, (tuple, list)):
+ argnames = [x.strip() for x in argnames.split(",") if x.strip()]
+ force_tuple = len(argnames) == 1
+ else:
+ force_tuple = False
+ parameters = [
+ ParameterSet.extract_from(x, legacy_force_tuple=force_tuple)
+ for x in argvalues]
+ del argvalues
+
+ if not parameters:
+ fs, lineno = getfslineno(function)
+ reason = "got empty parameter set %r, function %s at %s:%d" % (
+ argnames, function.__name__, fs, lineno)
+ mark = MARK_GEN.skip(reason=reason)
+ parameters.append(ParameterSet(
+ values=(NOTSET,) * len(argnames),
+ marks=[mark],
+ id=None,
+ ))
+ return argnames, parameters
+
+
+class MarkerError(Exception):
+
+ """Error in use of a pytest marker/attribute."""
+
+
+def param(*values, **kw):
+ return ParameterSet.param(*values, **kw)
+
+
+def pytest_addoption(parser):
+ group = parser.getgroup("general")
+ group._addoption(
+ '-k',
+ action="store", dest="keyword", default='', metavar="EXPRESSION",
+ help="only run tests which match the given substring expression. "
+ "An expression is a python evaluatable expression "
+ "where all names are substring-matched against test names "
+ "and their parent classes. Example: -k 'test_method or test_"
+ "other' matches all test functions and classes whose name "
+ "contains 'test_method' or 'test_other', while -k 'not test_method' "
+ "matches those that don't contain 'test_method' in their names. "
+ "Additionally keywords are matched to classes and functions "
+ "containing extra names in their 'extra_keyword_matches' set, "
+ "as well as functions which have names assigned directly to them."
+ )
+
+ group._addoption(
+ "-m",
+ action="store", dest="markexpr", default="", metavar="MARKEXPR",
+ help="only run tests matching given mark expression. "
+ "example: -m 'mark1 and not mark2'."
+ )
+
+ group.addoption(
+ "--markers", action="store_true",
+ help="show markers (builtin, plugin and per-project ones)."
+ )
+
+ parser.addini("markers", "markers for test functions", 'linelist')
+
+
+def pytest_cmdline_main(config):
+ import _pytest.config
+ if config.option.markers:
+ config._do_configure()
+ tw = _pytest.config.create_terminal_writer(config)
+ for line in config.getini("markers"):
+ parts = line.split(":", 1)
+ name = parts[0]
+ rest = parts[1] if len(parts) == 2 else ''
+ tw.write("@pytest.mark.%s:" % name, bold=True)
+ tw.line(rest)
+ tw.line()
+ config._ensure_unconfigure()
+ return 0
+
+
+pytest_cmdline_main.tryfirst = True
+
+
+def pytest_collection_modifyitems(items, config):
+ keywordexpr = config.option.keyword.lstrip()
+ matchexpr = config.option.markexpr
+ if not keywordexpr and not matchexpr:
+ return
+ # pytest used to allow "-" for negating
+ # but today we just allow "-" at the beginning, use "not" instead
+ # we probably remove "-" altogether soon
+ if keywordexpr.startswith("-"):
+ keywordexpr = "not " + keywordexpr[1:]
+ selectuntil = False
+ if keywordexpr[-1:] == ":":
+ selectuntil = True
+ keywordexpr = keywordexpr[:-1]
+
+ remaining = []
+ deselected = []
+ for colitem in items:
+ if keywordexpr and not matchkeyword(colitem, keywordexpr):
+ deselected.append(colitem)
+ else:
+ if selectuntil:
+ keywordexpr = None
+ if matchexpr:
+ if not matchmark(colitem, matchexpr):
+ deselected.append(colitem)
+ continue
+ remaining.append(colitem)
+
+ if deselected:
+ config.hook.pytest_deselected(items=deselected)
+ items[:] = remaining
+
+
+@attr.s
+class MarkMapping(object):
+ """Provides a local mapping for markers where item access
+ resolves to True if the marker is present. """
+
+ own_mark_names = attr.ib()
+
+ @classmethod
+ def from_keywords(cls, keywords):
+ mark_names = set()
+ for key, value in keywords.items():
+ if isinstance(value, MarkInfo) or isinstance(value, MarkDecorator):
+ mark_names.add(key)
+ return cls(mark_names)
+
+ def __getitem__(self, name):
+ return name in self.own_mark_names
+
+
+class KeywordMapping(object):
+ """Provides a local mapping for keywords.
+ Given a list of names, map any substring of one of these names to True.
+ """
+
+ def __init__(self, names):
+ self._names = names
+
+ def __getitem__(self, subname):
+ for name in self._names:
+ if subname in name:
+ return True
+ return False
+
+
+def matchmark(colitem, markexpr):
+ """Tries to match on any marker names, attached to the given colitem."""
+ return eval(markexpr, {}, MarkMapping.from_keywords(colitem.keywords))
+
+
+def matchkeyword(colitem, keywordexpr):
+ """Tries to match given keyword expression to given collector item.
+
+ Will match on the name of colitem, including the names of its parents.
+ Only matches names of items which are either a :class:`Class` or a
+ :class:`Function`.
+ Additionally, matches on names in the 'extra_keyword_matches' set of
+ any item, as well as names directly assigned to test functions.
+ """
+ mapped_names = set()
+
+ # Add the names of the current item and any parent items
+ import pytest
+ for item in colitem.listchain():
+ if not isinstance(item, pytest.Instance):
+ mapped_names.add(item.name)
+
+ # Add the names added as extra keywords to current or parent items
+ for name in colitem.listextrakeywords():
+ mapped_names.add(name)
+
+ # Add the names attached to the current function through direct assignment
+ if hasattr(colitem, 'function'):
+ for name in colitem.function.__dict__:
+ mapped_names.add(name)
+
+ mapping = KeywordMapping(mapped_names)
+ if " " not in keywordexpr:
+ # special case to allow for simple "-k pass" and "-k 1.3"
+ return mapping[keywordexpr]
+ elif keywordexpr.startswith("not ") and " " not in keywordexpr[4:]:
+ return not mapping[keywordexpr[4:]]
+ return eval(keywordexpr, {}, mapping)
+
+
+def pytest_configure(config):
+ config._old_mark_config = MARK_GEN._config
+ if config.option.strict:
+ MARK_GEN._config = config
+
+
+def pytest_unconfigure(config):
+ MARK_GEN._config = getattr(config, '_old_mark_config', None)
+
+
+class MarkGenerator:
+ """ Factory for :class:`MarkDecorator` objects - exposed as
+ a ``pytest.mark`` singleton instance. Example::
+
+ import pytest
+ @pytest.mark.slowtest
+ def test_function():
+ pass
+
+ will set a 'slowtest' :class:`MarkInfo` object
+ on the ``test_function`` object. """
+ _config = None
+
+ def __getattr__(self, name):
+ if name[0] == "_":
+ raise AttributeError("Marker name must NOT start with underscore")
+ if self._config is not None:
+ self._check(name)
+ return MarkDecorator(Mark(name, (), {}))
+
+ def _check(self, name):
+ try:
+ if name in self._markers:
+ return
+ except AttributeError:
+ pass
+ self._markers = values = set()
+ for line in self._config.getini("markers"):
+ marker = line.split(":", 1)[0]
+ marker = marker.rstrip()
+ x = marker.split("(", 1)[0]
+ values.add(x)
+ if name not in self._markers:
+ raise AttributeError("%r not a registered marker" % (name,))
+
+
+def istestfunc(func):
+ return hasattr(func, "__call__") and \
+ getattr(func, "__name__", "<lambda>") != "<lambda>"
+
+
+@attr.s(frozen=True)
+class Mark(object):
+ name = attr.ib()
+ args = attr.ib()
+ kwargs = attr.ib()
+
+ def combined_with(self, other):
+ assert self.name == other.name
+ return Mark(
+ self.name, self.args + other.args,
+ dict(self.kwargs, **other.kwargs))
+
+
+@attr.s
+class MarkDecorator(object):
+ """ A decorator for test functions and test classes. When applied
+ it will create :class:`MarkInfo` objects which may be
+ :ref:`retrieved by hooks as item keywords <excontrolskip>`.
+ MarkDecorator instances are often created like this::
+
+ mark1 = pytest.mark.NAME # simple MarkDecorator
+ mark2 = pytest.mark.NAME(name1=value) # parametrized MarkDecorator
+
+ and can then be applied as decorators to test functions::
+
+ @mark2
+ def test_function():
+ pass
+
+ When a MarkDecorator instance is called it does the following:
+ 1. If called with a single class as its only positional argument and no
+ additional keyword arguments, it attaches itself to the class so it
+ gets applied automatically to all test cases found in that class.
+ 2. If called with a single function as its only positional argument and
+ no additional keyword arguments, it attaches a MarkInfo object to the
+ function, containing all the arguments already stored internally in
+ the MarkDecorator.
+ 3. When called in any other case, it performs a 'fake construction' call,
+ i.e. it returns a new MarkDecorator instance with the original
+ MarkDecorator's content updated with the arguments passed to this
+ call.
+
+ Note: The rules above prevent MarkDecorator objects from storing only a
+ single function or class reference as their positional argument with no
+ additional keyword or positional arguments.
+
+ """
+
+ mark = attr.ib(validator=attr.validators.instance_of(Mark))
+
+ name = alias('mark.name')
+ args = alias('mark.args')
+ kwargs = alias('mark.kwargs')
+
+ @property
+ def markname(self):
+ return self.name # for backward-compat (2.4.1 had this attr)
+
+ def __eq__(self, other):
+ return self.mark == other.mark if isinstance(other, MarkDecorator) else False
+
+ def __repr__(self):
+ return "<MarkDecorator %r>" % (self.mark,)
+
+ def with_args(self, *args, **kwargs):
+ """ return a MarkDecorator with extra arguments added
+
+ unlike call this can be used even if the sole argument is a callable/class
+
+ :return: MarkDecorator
+ """
+
+ mark = Mark(self.name, args, kwargs)
+ return self.__class__(self.mark.combined_with(mark))
+
+ def __call__(self, *args, **kwargs):
+ """ if passed a single callable argument: decorate it with mark info.
+ otherwise add *args/**kwargs in-place to mark information. """
+ if args and not kwargs:
+ func = args[0]
+ is_class = inspect.isclass(func)
+ if len(args) == 1 and (istestfunc(func) or is_class):
+ if is_class:
+ store_mark(func, self.mark)
+ else:
+ store_legacy_markinfo(func, self.mark)
+ store_mark(func, self.mark)
+ return func
+ return self.with_args(*args, **kwargs)
+
+
+def get_unpacked_marks(obj):
+ """
+ obtain the unpacked marks that are stored on a object
+ """
+ mark_list = getattr(obj, 'pytestmark', [])
+
+ if not isinstance(mark_list, list):
+ mark_list = [mark_list]
+ return [
+ getattr(mark, 'mark', mark) # unpack MarkDecorator
+ for mark in mark_list
+ ]
+
+
+def store_mark(obj, mark):
+ """store a Mark on a object
+ this is used to implement the Mark declarations/decorators correctly
+ """
+ assert isinstance(mark, Mark), mark
+ # always reassign name to avoid updating pytestmark
+ # in a reference that was only borrowed
+ obj.pytestmark = get_unpacked_marks(obj) + [mark]
+
+
+def store_legacy_markinfo(func, mark):
+ """create the legacy MarkInfo objects and put them onto the function
+ """
+ if not isinstance(mark, Mark):
+ raise TypeError("got {mark!r} instead of a Mark".format(mark=mark))
+ holder = getattr(func, mark.name, None)
+ if holder is None:
+ holder = MarkInfo(mark)
+ setattr(func, mark.name, holder)
+ else:
+ holder.add_mark(mark)
+
+
+class MarkInfo(object):
+ """ Marking object created by :class:`MarkDecorator` instances. """
+
+ def __init__(self, mark):
+ assert isinstance(mark, Mark), repr(mark)
+ self.combined = mark
+ self._marks = [mark]
+
+ name = alias('combined.name')
+ args = alias('combined.args')
+ kwargs = alias('combined.kwargs')
+
+ def __repr__(self):
+ return "<MarkInfo {0!r}>".format(self.combined)
+
+ def add_mark(self, mark):
+ """ add a MarkInfo with the given args and kwargs. """
+ self._marks.append(mark)
+ self.combined = self.combined.combined_with(mark)
+
+ def __iter__(self):
+ """ yield MarkInfo objects each relating to a marking-call. """
+ return map(MarkInfo, self._marks)
+
+
+MARK_GEN = MarkGenerator()
+
+
+def _marked(func, mark):
+ """ Returns True if :func: is already marked with :mark:, False otherwise.
+ This can happen if marker is applied to class and the test file is
+ invoked more than once.
+ """
+ try:
+ func_mark = getattr(func, mark.name)
+ except AttributeError:
+ return False
+ return mark.args == func_mark.args and mark.kwargs == func_mark.kwargs
+
+
+def transfer_markers(funcobj, cls, mod):
+ """
+ this function transfers class level markers and module level markers
+ into function level markinfo objects
+
+ this is the main reason why marks are so broken
+ the resolution will involve phasing out function level MarkInfo objects
+
+ """
+ for obj in (cls, mod):
+ for mark in get_unpacked_marks(obj):
+ if not _marked(funcobj, mark):
+ store_legacy_markinfo(funcobj, mark)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/monkeypatch.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/monkeypatch.py
new file mode 100644
index 00000000000..40ae560f070
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/monkeypatch.py
@@ -0,0 +1,258 @@
+""" monkeypatching and mocking functionality. """
+from __future__ import absolute_import, division, print_function
+
+import os
+import sys
+import re
+import six
+from _pytest.fixtures import fixture
+
+RE_IMPORT_ERROR_NAME = re.compile("^No module named (.*)$")
+
+
+@fixture
+def monkeypatch():
+ """The returned ``monkeypatch`` fixture provides these
+ helper methods to modify objects, dictionaries or os.environ::
+
+ monkeypatch.setattr(obj, name, value, raising=True)
+ monkeypatch.delattr(obj, name, raising=True)
+ monkeypatch.setitem(mapping, name, value)
+ monkeypatch.delitem(obj, name, raising=True)
+ monkeypatch.setenv(name, value, prepend=False)
+ monkeypatch.delenv(name, value, raising=True)
+ monkeypatch.syspath_prepend(path)
+ monkeypatch.chdir(path)
+
+ All modifications will be undone after the requesting
+ test function or fixture has finished. The ``raising``
+ parameter determines if a KeyError or AttributeError
+ will be raised if the set/deletion operation has no target.
+ """
+ mpatch = MonkeyPatch()
+ yield mpatch
+ mpatch.undo()
+
+
+def resolve(name):
+ # simplified from zope.dottedname
+ parts = name.split('.')
+
+ used = parts.pop(0)
+ found = __import__(used)
+ for part in parts:
+ used += '.' + part
+ try:
+ found = getattr(found, part)
+ except AttributeError:
+ pass
+ else:
+ continue
+ # we use explicit un-nesting of the handling block in order
+ # to avoid nested exceptions on python 3
+ try:
+ __import__(used)
+ except ImportError as ex:
+ # str is used for py2 vs py3
+ expected = str(ex).split()[-1]
+ if expected == used:
+ raise
+ else:
+ raise ImportError(
+ 'import error in %s: %s' % (used, ex)
+ )
+ found = annotated_getattr(found, part, used)
+ return found
+
+
+def annotated_getattr(obj, name, ann):
+ try:
+ obj = getattr(obj, name)
+ except AttributeError:
+ raise AttributeError(
+ '%r object at %s has no attribute %r' % (
+ type(obj).__name__, ann, name
+ )
+ )
+ return obj
+
+
+def derive_importpath(import_path, raising):
+ if not isinstance(import_path, six.string_types) or "." not in import_path:
+ raise TypeError("must be absolute import path string, not %r" %
+ (import_path,))
+ module, attr = import_path.rsplit('.', 1)
+ target = resolve(module)
+ if raising:
+ annotated_getattr(target, attr, ann=module)
+ return attr, target
+
+
+class Notset:
+ def __repr__(self):
+ return "<notset>"
+
+
+notset = Notset()
+
+
+class MonkeyPatch:
+ """ Object returned by the ``monkeypatch`` fixture keeping a record of setattr/item/env/syspath changes.
+ """
+
+ def __init__(self):
+ self._setattr = []
+ self._setitem = []
+ self._cwd = None
+ self._savesyspath = None
+
+ def setattr(self, target, name, value=notset, raising=True):
+ """ Set attribute value on target, memorizing the old value.
+ By default raise AttributeError if the attribute did not exist.
+
+ For convenience you can specify a string as ``target`` which
+ will be interpreted as a dotted import path, with the last part
+ being the attribute name. Example:
+ ``monkeypatch.setattr("os.getcwd", lambda x: "/")``
+ would set the ``getcwd`` function of the ``os`` module.
+
+ The ``raising`` value determines if the setattr should fail
+ if the attribute is not already present (defaults to True
+ which means it will raise).
+ """
+ __tracebackhide__ = True
+ import inspect
+
+ if value is notset:
+ if not isinstance(target, six.string_types):
+ raise TypeError("use setattr(target, name, value) or "
+ "setattr(target, value) with target being a dotted "
+ "import string")
+ value = name
+ name, target = derive_importpath(target, raising)
+
+ oldval = getattr(target, name, notset)
+ if raising and oldval is notset:
+ raise AttributeError("%r has no attribute %r" % (target, name))
+
+ # avoid class descriptors like staticmethod/classmethod
+ if inspect.isclass(target):
+ oldval = target.__dict__.get(name, notset)
+ self._setattr.append((target, name, oldval))
+ setattr(target, name, value)
+
+ def delattr(self, target, name=notset, raising=True):
+ """ Delete attribute ``name`` from ``target``, by default raise
+ AttributeError it the attribute did not previously exist.
+
+ If no ``name`` is specified and ``target`` is a string
+ it will be interpreted as a dotted import path with the
+ last part being the attribute name.
+
+ If ``raising`` is set to False, no exception will be raised if the
+ attribute is missing.
+ """
+ __tracebackhide__ = True
+ if name is notset:
+ if not isinstance(target, six.string_types):
+ raise TypeError("use delattr(target, name) or "
+ "delattr(target) with target being a dotted "
+ "import string")
+ name, target = derive_importpath(target, raising)
+
+ if not hasattr(target, name):
+ if raising:
+ raise AttributeError(name)
+ else:
+ self._setattr.append((target, name, getattr(target, name, notset)))
+ delattr(target, name)
+
+ def setitem(self, dic, name, value):
+ """ Set dictionary entry ``name`` to value. """
+ self._setitem.append((dic, name, dic.get(name, notset)))
+ dic[name] = value
+
+ def delitem(self, dic, name, raising=True):
+ """ Delete ``name`` from dict. Raise KeyError if it doesn't exist.
+
+ If ``raising`` is set to False, no exception will be raised if the
+ key is missing.
+ """
+ if name not in dic:
+ if raising:
+ raise KeyError(name)
+ else:
+ self._setitem.append((dic, name, dic.get(name, notset)))
+ del dic[name]
+
+ def setenv(self, name, value, prepend=None):
+ """ Set environment variable ``name`` to ``value``. If ``prepend``
+ is a character, read the current environment variable value
+ and prepend the ``value`` adjoined with the ``prepend`` character."""
+ value = str(value)
+ if prepend and name in os.environ:
+ value = value + prepend + os.environ[name]
+ self.setitem(os.environ, name, value)
+
+ def delenv(self, name, raising=True):
+ """ Delete ``name`` from the environment. Raise KeyError it does not
+ exist.
+
+ If ``raising`` is set to False, no exception will be raised if the
+ environment variable is missing.
+ """
+ self.delitem(os.environ, name, raising=raising)
+
+ def syspath_prepend(self, path):
+ """ Prepend ``path`` to ``sys.path`` list of import locations. """
+ if self._savesyspath is None:
+ self._savesyspath = sys.path[:]
+ sys.path.insert(0, str(path))
+
+ def chdir(self, path):
+ """ Change the current working directory to the specified path.
+ Path can be a string or a py.path.local object.
+ """
+ if self._cwd is None:
+ self._cwd = os.getcwd()
+ if hasattr(path, "chdir"):
+ path.chdir()
+ else:
+ os.chdir(path)
+
+ def undo(self):
+ """ Undo previous changes. This call consumes the
+ undo stack. Calling it a second time has no effect unless
+ you do more monkeypatching after the undo call.
+
+ There is generally no need to call `undo()`, since it is
+ called automatically during tear-down.
+
+ Note that the same `monkeypatch` fixture is used across a
+ single test function invocation. If `monkeypatch` is used both by
+ the test function itself and one of the test fixtures,
+ calling `undo()` will undo all of the changes made in
+ both functions.
+ """
+ for obj, name, value in reversed(self._setattr):
+ if value is not notset:
+ setattr(obj, name, value)
+ else:
+ delattr(obj, name)
+ self._setattr[:] = []
+ for dictionary, name, value in reversed(self._setitem):
+ if value is notset:
+ try:
+ del dictionary[name]
+ except KeyError:
+ pass # was already deleted, so we have the desired state
+ else:
+ dictionary[name] = value
+ self._setitem[:] = []
+ if self._savesyspath is not None:
+ sys.path[:] = self._savesyspath
+ self._savesyspath = None
+
+ if self._cwd is not None:
+ os.chdir(self._cwd)
+ self._cwd = None
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/nodes.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/nodes.py
new file mode 100644
index 00000000000..ad3af2ce67c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/nodes.py
@@ -0,0 +1,37 @@
+SEP = "/"
+
+
+def _splitnode(nodeid):
+ """Split a nodeid into constituent 'parts'.
+
+ Node IDs are strings, and can be things like:
+ ''
+ 'testing/code'
+ 'testing/code/test_excinfo.py'
+ 'testing/code/test_excinfo.py::TestFormattedExcinfo::()'
+
+ Return values are lists e.g.
+ []
+ ['testing', 'code']
+ ['testing', 'code', 'test_excinfo.py']
+ ['testing', 'code', 'test_excinfo.py', 'TestFormattedExcinfo', '()']
+ """
+ if nodeid == '':
+ # If there is no root node at all, return an empty list so the caller's logic can remain sane
+ return []
+ parts = nodeid.split(SEP)
+ # Replace single last element 'test_foo.py::Bar::()' with multiple elements 'test_foo.py', 'Bar', '()'
+ parts[-1:] = parts[-1].split("::")
+ return parts
+
+
+def ischildnode(baseid, nodeid):
+ """Return True if the nodeid is a child node of the baseid.
+
+ E.g. 'foo/bar::Baz::()' is a child of 'foo', 'foo/bar' and 'foo/bar::Baz', but not of 'foo/blorp'
+ """
+ base_parts = _splitnode(baseid)
+ node_parts = _splitnode(nodeid)
+ if len(node_parts) < len(base_parts):
+ return False
+ return node_parts[:len(base_parts)] == base_parts
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/nose.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/nose.py
new file mode 100644
index 00000000000..c81542eadf3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/nose.py
@@ -0,0 +1,72 @@
+""" run test suites written for nose. """
+from __future__ import absolute_import, division, print_function
+
+import sys
+
+from _pytest import unittest, runner, python
+from _pytest.config import hookimpl
+
+
+def get_skip_exceptions():
+ skip_classes = set()
+ for module_name in ('unittest', 'unittest2', 'nose'):
+ mod = sys.modules.get(module_name)
+ if hasattr(mod, 'SkipTest'):
+ skip_classes.add(mod.SkipTest)
+ return tuple(skip_classes)
+
+
+def pytest_runtest_makereport(item, call):
+ if call.excinfo and call.excinfo.errisinstance(get_skip_exceptions()):
+ # let's substitute the excinfo with a pytest.skip one
+ call2 = call.__class__(
+ lambda: runner.skip(str(call.excinfo.value)), call.when)
+ call.excinfo = call2.excinfo
+
+
+@hookimpl(trylast=True)
+def pytest_runtest_setup(item):
+ if is_potential_nosetest(item):
+ if isinstance(item.parent, python.Generator):
+ gen = item.parent
+ if not hasattr(gen, '_nosegensetup'):
+ call_optional(gen.obj, 'setup')
+ if isinstance(gen.parent, python.Instance):
+ call_optional(gen.parent.obj, 'setup')
+ gen._nosegensetup = True
+ if not call_optional(item.obj, 'setup'):
+ # call module level setup if there is no object level one
+ call_optional(item.parent.obj, 'setup')
+ # XXX this implies we only call teardown when setup worked
+ item.session._setupstate.addfinalizer((lambda: teardown_nose(item)), item)
+
+
+def teardown_nose(item):
+ if is_potential_nosetest(item):
+ if not call_optional(item.obj, 'teardown'):
+ call_optional(item.parent.obj, 'teardown')
+ # if hasattr(item.parent, '_nosegensetup'):
+ # #call_optional(item._nosegensetup, 'teardown')
+ # del item.parent._nosegensetup
+
+
+def pytest_make_collect_report(collector):
+ if isinstance(collector, python.Generator):
+ call_optional(collector.obj, 'setup')
+
+
+def is_potential_nosetest(item):
+ # extra check needed since we do not do nose style setup/teardown
+ # on direct unittest style classes
+ return isinstance(item, python.Function) and \
+ not isinstance(item, unittest.TestCaseFunction)
+
+
+def call_optional(obj, name):
+ method = getattr(obj, name, None)
+ isfixture = hasattr(method, "_pytestfixturefunction")
+ if method is not None and not isfixture and callable(method):
+ # If there's any problems allow the exception to raise rather than
+ # silently ignoring them
+ method()
+ return True
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/outcomes.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/outcomes.py
new file mode 100644
index 00000000000..7f0c18fa6c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/outcomes.py
@@ -0,0 +1,147 @@
+"""
+exception classes and constants handling test outcomes
+as well as functions creating them
+"""
+from __future__ import absolute_import, division, print_function
+import py
+import sys
+
+
+class OutcomeException(BaseException):
+ """ OutcomeException and its subclass instances indicate and
+ contain info about test and collection outcomes.
+ """
+ def __init__(self, msg=None, pytrace=True):
+ BaseException.__init__(self, msg)
+ self.msg = msg
+ self.pytrace = pytrace
+
+ def __repr__(self):
+ if self.msg:
+ val = self.msg
+ if isinstance(val, bytes):
+ val = py._builtin._totext(val, errors='replace')
+ return val
+ return "<%s instance>" % (self.__class__.__name__,)
+ __str__ = __repr__
+
+
+TEST_OUTCOME = (OutcomeException, Exception)
+
+
+class Skipped(OutcomeException):
+ # XXX hackish: on 3k we fake to live in the builtins
+ # in order to have Skipped exception printing shorter/nicer
+ __module__ = 'builtins'
+
+ def __init__(self, msg=None, pytrace=True, allow_module_level=False):
+ OutcomeException.__init__(self, msg=msg, pytrace=pytrace)
+ self.allow_module_level = allow_module_level
+
+
+class Failed(OutcomeException):
+ """ raised from an explicit call to pytest.fail() """
+ __module__ = 'builtins'
+
+
+class Exit(KeyboardInterrupt):
+ """ raised for immediate program exits (no tracebacks/summaries)"""
+ def __init__(self, msg="unknown reason"):
+ self.msg = msg
+ KeyboardInterrupt.__init__(self, msg)
+
+# exposed helper methods
+
+
+def exit(msg):
+ """ exit testing process as if KeyboardInterrupt was triggered. """
+ __tracebackhide__ = True
+ raise Exit(msg)
+
+
+exit.Exception = Exit
+
+
+def skip(msg="", **kwargs):
+ """ skip an executing test with the given message. Note: it's usually
+ better to use the pytest.mark.skipif marker to declare a test to be
+ skipped under certain conditions like mismatching platforms or
+ dependencies. See the pytest_skipping plugin for details.
+
+ :kwarg bool allow_module_level: allows this function to be called at
+ module level, skipping the rest of the module. Default to False.
+ """
+ __tracebackhide__ = True
+ allow_module_level = kwargs.pop('allow_module_level', False)
+ if kwargs:
+ keys = [k for k in kwargs.keys()]
+ raise TypeError('unexpected keyword arguments: {0}'.format(keys))
+ raise Skipped(msg=msg, allow_module_level=allow_module_level)
+
+
+skip.Exception = Skipped
+
+
+def fail(msg="", pytrace=True):
+ """ explicitly fail an currently-executing test with the given Message.
+
+ :arg pytrace: if false the msg represents the full failure information
+ and no python traceback will be reported.
+ """
+ __tracebackhide__ = True
+ raise Failed(msg=msg, pytrace=pytrace)
+
+
+fail.Exception = Failed
+
+
+class XFailed(fail.Exception):
+ """ raised from an explicit call to pytest.xfail() """
+
+
+def xfail(reason=""):
+ """ xfail an executing test or setup functions with the given reason."""
+ __tracebackhide__ = True
+ raise XFailed(reason)
+
+
+xfail.Exception = XFailed
+
+
+def importorskip(modname, minversion=None):
+ """ return imported module if it has at least "minversion" as its
+ __version__ attribute. If no minversion is specified the a skip
+ is only triggered if the module can not be imported.
+ """
+ import warnings
+ __tracebackhide__ = True
+ compile(modname, '', 'eval') # to catch syntaxerrors
+ should_skip = False
+
+ with warnings.catch_warnings():
+ # make sure to ignore ImportWarnings that might happen because
+ # of existing directories with the same name we're trying to
+ # import but without a __init__.py file
+ warnings.simplefilter('ignore')
+ try:
+ __import__(modname)
+ except ImportError:
+ # Do not raise chained exception here(#1485)
+ should_skip = True
+ if should_skip:
+ raise Skipped("could not import %r" % (modname,), allow_module_level=True)
+ mod = sys.modules[modname]
+ if minversion is None:
+ return mod
+ verattr = getattr(mod, '__version__', None)
+ if minversion is not None:
+ try:
+ from pkg_resources import parse_version as pv
+ except ImportError:
+ raise Skipped("we have a required version for %r but can not import "
+ "pkg_resources to parse version strings." % (modname,),
+ allow_module_level=True)
+ if verattr is None or pv(verattr) < pv(minversion):
+ raise Skipped("module %r has __version__ %r, required is: %r" % (
+ modname, verattr, minversion), allow_module_level=True)
+ return mod
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/pastebin.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/pastebin.py
new file mode 100644
index 00000000000..b588b021b12
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/pastebin.py
@@ -0,0 +1,100 @@
+""" submit failure or test session information to a pastebin service. """
+from __future__ import absolute_import, division, print_function
+
+import pytest
+import six
+import sys
+import tempfile
+
+
+def pytest_addoption(parser):
+ group = parser.getgroup("terminal reporting")
+ group._addoption('--pastebin', metavar="mode",
+ action='store', dest="pastebin", default=None,
+ choices=['failed', 'all'],
+ help="send failed|all info to bpaste.net pastebin service.")
+
+
+@pytest.hookimpl(trylast=True)
+def pytest_configure(config):
+ if config.option.pastebin == "all":
+ tr = config.pluginmanager.getplugin('terminalreporter')
+ # if no terminal reporter plugin is present, nothing we can do here;
+ # this can happen when this function executes in a slave node
+ # when using pytest-xdist, for example
+ if tr is not None:
+ # pastebin file will be utf-8 encoded binary file
+ config._pastebinfile = tempfile.TemporaryFile('w+b')
+ oldwrite = tr._tw.write
+
+ def tee_write(s, **kwargs):
+ oldwrite(s, **kwargs)
+ if isinstance(s, six.text_type):
+ s = s.encode('utf-8')
+ config._pastebinfile.write(s)
+
+ tr._tw.write = tee_write
+
+
+def pytest_unconfigure(config):
+ if hasattr(config, '_pastebinfile'):
+ # get terminal contents and delete file
+ config._pastebinfile.seek(0)
+ sessionlog = config._pastebinfile.read()
+ config._pastebinfile.close()
+ del config._pastebinfile
+ # undo our patching in the terminal reporter
+ tr = config.pluginmanager.getplugin('terminalreporter')
+ del tr._tw.__dict__['write']
+ # write summary
+ tr.write_sep("=", "Sending information to Paste Service")
+ pastebinurl = create_new_paste(sessionlog)
+ tr.write_line("pastebin session-log: %s\n" % pastebinurl)
+
+
+def create_new_paste(contents):
+ """
+ Creates a new paste using bpaste.net service.
+
+ :contents: paste contents as utf-8 encoded bytes
+ :returns: url to the pasted contents
+ """
+ import re
+ if sys.version_info < (3, 0):
+ from urllib import urlopen, urlencode
+ else:
+ from urllib.request import urlopen
+ from urllib.parse import urlencode
+
+ params = {
+ 'code': contents,
+ 'lexer': 'python3' if sys.version_info[0] == 3 else 'python',
+ 'expiry': '1week',
+ }
+ url = 'https://bpaste.net'
+ response = urlopen(url, data=urlencode(params).encode('ascii')).read()
+ m = re.search(r'href="/raw/(\w+)"', response.decode('utf-8'))
+ if m:
+ return '%s/show/%s' % (url, m.group(1))
+ else:
+ return 'bad response: ' + response
+
+
+def pytest_terminal_summary(terminalreporter):
+ import _pytest.config
+ if terminalreporter.config.option.pastebin != "failed":
+ return
+ tr = terminalreporter
+ if 'failed' in tr.stats:
+ terminalreporter.write_sep("=", "Sending information to Paste Service")
+ for rep in terminalreporter.stats.get('failed'):
+ try:
+ msg = rep.longrepr.reprtraceback.reprentries[-1].reprfileloc
+ except AttributeError:
+ msg = tr._getfailureheadline(rep)
+ tw = _pytest.config.create_terminal_writer(terminalreporter.config, stringio=True)
+ rep.toterminal(tw)
+ s = tw.stringio.getvalue()
+ assert len(s)
+ pastebinurl = create_new_paste(s)
+ tr.write_line("%s --> %s" % (msg, pastebinurl))
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/pytester.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/pytester.py
new file mode 100644
index 00000000000..f2dd5994f1b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/pytester.py
@@ -0,0 +1,1187 @@
+""" (disabled by default) support for testing pytest and pytest plugins. """
+from __future__ import absolute_import, division, print_function
+
+import codecs
+import gc
+import os
+import platform
+import re
+import subprocess
+import six
+import sys
+import time
+import traceback
+from fnmatch import fnmatch
+
+from weakref import WeakKeyDictionary
+
+from _pytest.capture import MultiCapture, SysCapture
+from _pytest._code import Source
+import py
+import pytest
+from _pytest.main import Session, EXIT_OK
+from _pytest.assertion.rewrite import AssertionRewritingHook
+
+
+PYTEST_FULLPATH = os.path.abspath(pytest.__file__.rstrip("oc")).replace("$py.class", ".py")
+
+
+def pytest_addoption(parser):
+ # group = parser.getgroup("pytester", "pytester (self-tests) options")
+ parser.addoption('--lsof',
+ action="store_true", dest="lsof", default=False,
+ help=("run FD checks if lsof is available"))
+
+ parser.addoption('--runpytest', default="inprocess", dest="runpytest",
+ choices=("inprocess", "subprocess", ),
+ help=("run pytest sub runs in tests using an 'inprocess' "
+ "or 'subprocess' (python -m main) method"))
+
+
+def pytest_configure(config):
+ if config.getvalue("lsof"):
+ checker = LsofFdLeakChecker()
+ if checker.matching_platform():
+ config.pluginmanager.register(checker)
+
+
+class LsofFdLeakChecker(object):
+ def get_open_files(self):
+ out = self._exec_lsof()
+ open_files = self._parse_lsof_output(out)
+ return open_files
+
+ def _exec_lsof(self):
+ pid = os.getpid()
+ return py.process.cmdexec("lsof -Ffn0 -p %d" % pid)
+
+ def _parse_lsof_output(self, out):
+ def isopen(line):
+ return line.startswith('f') and ("deleted" not in line and
+ 'mem' not in line and "txt" not in line and 'cwd' not in line)
+
+ open_files = []
+
+ for line in out.split("\n"):
+ if isopen(line):
+ fields = line.split('\0')
+ fd = fields[0][1:]
+ filename = fields[1][1:]
+ if filename.startswith('/'):
+ open_files.append((fd, filename))
+
+ return open_files
+
+ def matching_platform(self):
+ try:
+ py.process.cmdexec("lsof -v")
+ except (py.process.cmdexec.Error, UnicodeDecodeError):
+ # cmdexec may raise UnicodeDecodeError on Windows systems
+ # with locale other than english:
+ # https://bitbucket.org/pytest-dev/py/issues/66
+ return False
+ else:
+ return True
+
+ @pytest.hookimpl(hookwrapper=True, tryfirst=True)
+ def pytest_runtest_protocol(self, item):
+ lines1 = self.get_open_files()
+ yield
+ if hasattr(sys, "pypy_version_info"):
+ gc.collect()
+ lines2 = self.get_open_files()
+
+ new_fds = set([t[0] for t in lines2]) - set([t[0] for t in lines1])
+ leaked_files = [t for t in lines2 if t[0] in new_fds]
+ if leaked_files:
+ error = []
+ error.append("***** %s FD leakage detected" % len(leaked_files))
+ error.extend([str(f) for f in leaked_files])
+ error.append("*** Before:")
+ error.extend([str(f) for f in lines1])
+ error.append("*** After:")
+ error.extend([str(f) for f in lines2])
+ error.append(error[0])
+ error.append("*** function %s:%s: %s " % item.location)
+ error.append("See issue #2366")
+ item.warn('', "\n".join(error))
+
+
+# XXX copied from execnet's conftest.py - needs to be merged
+winpymap = {
+ 'python2.7': r'C:\Python27\python.exe',
+ 'python3.4': r'C:\Python34\python.exe',
+ 'python3.5': r'C:\Python35\python.exe',
+ 'python3.6': r'C:\Python36\python.exe',
+}
+
+
+def getexecutable(name, cache={}):
+ try:
+ return cache[name]
+ except KeyError:
+ executable = py.path.local.sysfind(name)
+ if executable:
+ import subprocess
+ popen = subprocess.Popen([str(executable), "--version"],
+ universal_newlines=True, stderr=subprocess.PIPE)
+ out, err = popen.communicate()
+ if name == "jython":
+ if not err or "2.5" not in err:
+ executable = None
+ if "2.5.2" in err:
+ executable = None # http://bugs.jython.org/issue1790
+ elif popen.returncode != 0:
+ # Handle pyenv's 127.
+ executable = None
+ cache[name] = executable
+ return executable
+
+
+@pytest.fixture(params=['python2.7', 'python3.4', 'pypy', 'pypy3'])
+def anypython(request):
+ name = request.param
+ executable = getexecutable(name)
+ if executable is None:
+ if sys.platform == "win32":
+ executable = winpymap.get(name, None)
+ if executable:
+ executable = py.path.local(executable)
+ if executable.check():
+ return executable
+ pytest.skip("no suitable %s found" % (name,))
+ return executable
+
+# used at least by pytest-xdist plugin
+
+
+@pytest.fixture
+def _pytest(request):
+ """ Return a helper which offers a gethookrecorder(hook)
+ method which returns a HookRecorder instance which helps
+ to make assertions about called hooks.
+ """
+ return PytestArg(request)
+
+
+class PytestArg:
+ def __init__(self, request):
+ self.request = request
+
+ def gethookrecorder(self, hook):
+ hookrecorder = HookRecorder(hook._pm)
+ self.request.addfinalizer(hookrecorder.finish_recording)
+ return hookrecorder
+
+
+def get_public_names(values):
+ """Only return names from iterator values without a leading underscore."""
+ return [x for x in values if x[0] != "_"]
+
+
+class ParsedCall:
+ def __init__(self, name, kwargs):
+ self.__dict__.update(kwargs)
+ self._name = name
+
+ def __repr__(self):
+ d = self.__dict__.copy()
+ del d['_name']
+ return "<ParsedCall %r(**%r)>" % (self._name, d)
+
+
+class HookRecorder:
+ """Record all hooks called in a plugin manager.
+
+ This wraps all the hook calls in the plugin manager, recording
+ each call before propagating the normal calls.
+
+ """
+
+ def __init__(self, pluginmanager):
+ self._pluginmanager = pluginmanager
+ self.calls = []
+
+ def before(hook_name, hook_impls, kwargs):
+ self.calls.append(ParsedCall(hook_name, kwargs))
+
+ def after(outcome, hook_name, hook_impls, kwargs):
+ pass
+
+ self._undo_wrapping = pluginmanager.add_hookcall_monitoring(before, after)
+
+ def finish_recording(self):
+ self._undo_wrapping()
+
+ def getcalls(self, names):
+ if isinstance(names, str):
+ names = names.split()
+ return [call for call in self.calls if call._name in names]
+
+ def assert_contains(self, entries):
+ __tracebackhide__ = True
+ i = 0
+ entries = list(entries)
+ backlocals = sys._getframe(1).f_locals
+ while entries:
+ name, check = entries.pop(0)
+ for ind, call in enumerate(self.calls[i:]):
+ if call._name == name:
+ print("NAMEMATCH", name, call)
+ if eval(check, backlocals, call.__dict__):
+ print("CHECKERMATCH", repr(check), "->", call)
+ else:
+ print("NOCHECKERMATCH", repr(check), "-", call)
+ continue
+ i += ind + 1
+ break
+ print("NONAMEMATCH", name, "with", call)
+ else:
+ pytest.fail("could not find %r check %r" % (name, check))
+
+ def popcall(self, name):
+ __tracebackhide__ = True
+ for i, call in enumerate(self.calls):
+ if call._name == name:
+ del self.calls[i]
+ return call
+ lines = ["could not find call %r, in:" % (name,)]
+ lines.extend([" %s" % str(x) for x in self.calls])
+ pytest.fail("\n".join(lines))
+
+ def getcall(self, name):
+ values = self.getcalls(name)
+ assert len(values) == 1, (name, values)
+ return values[0]
+
+ # functionality for test reports
+
+ def getreports(self,
+ names="pytest_runtest_logreport pytest_collectreport"):
+ return [x.report for x in self.getcalls(names)]
+
+ def matchreport(self, inamepart="",
+ names="pytest_runtest_logreport pytest_collectreport", when=None):
+ """ return a testreport whose dotted import path matches """
+ values = []
+ for rep in self.getreports(names=names):
+ try:
+ if not when and rep.when != "call" and rep.passed:
+ # setup/teardown passing reports - let's ignore those
+ continue
+ except AttributeError:
+ pass
+ if when and getattr(rep, 'when', None) != when:
+ continue
+ if not inamepart or inamepart in rep.nodeid.split("::"):
+ values.append(rep)
+ if not values:
+ raise ValueError("could not find test report matching %r: "
+ "no test reports at all!" % (inamepart,))
+ if len(values) > 1:
+ raise ValueError(
+ "found 2 or more testreports matching %r: %s" % (inamepart, values))
+ return values[0]
+
+ def getfailures(self,
+ names='pytest_runtest_logreport pytest_collectreport'):
+ return [rep for rep in self.getreports(names) if rep.failed]
+
+ def getfailedcollections(self):
+ return self.getfailures('pytest_collectreport')
+
+ def listoutcomes(self):
+ passed = []
+ skipped = []
+ failed = []
+ for rep in self.getreports(
+ "pytest_collectreport pytest_runtest_logreport"):
+ if rep.passed:
+ if getattr(rep, "when", None) == "call":
+ passed.append(rep)
+ elif rep.skipped:
+ skipped.append(rep)
+ elif rep.failed:
+ failed.append(rep)
+ return passed, skipped, failed
+
+ def countoutcomes(self):
+ return [len(x) for x in self.listoutcomes()]
+
+ def assertoutcome(self, passed=0, skipped=0, failed=0):
+ realpassed, realskipped, realfailed = self.listoutcomes()
+ assert passed == len(realpassed)
+ assert skipped == len(realskipped)
+ assert failed == len(realfailed)
+
+ def clear(self):
+ self.calls[:] = []
+
+
+@pytest.fixture
+def linecomp(request):
+ return LineComp()
+
+
+@pytest.fixture(name='LineMatcher')
+def LineMatcher_fixture(request):
+ return LineMatcher
+
+
+@pytest.fixture
+def testdir(request, tmpdir_factory):
+ return Testdir(request, tmpdir_factory)
+
+
+rex_outcome = re.compile(r"(\d+) ([\w-]+)")
+
+
+class RunResult:
+ """The result of running a command.
+
+ Attributes:
+
+ :ret: The return value.
+ :outlines: List of lines captured from stdout.
+ :errlines: List of lines captures from stderr.
+ :stdout: :py:class:`LineMatcher` of stdout, use ``stdout.str()`` to
+ reconstruct stdout or the commonly used
+ ``stdout.fnmatch_lines()`` method.
+ :stderrr: :py:class:`LineMatcher` of stderr.
+ :duration: Duration in seconds.
+
+ """
+
+ def __init__(self, ret, outlines, errlines, duration):
+ self.ret = ret
+ self.outlines = outlines
+ self.errlines = errlines
+ self.stdout = LineMatcher(outlines)
+ self.stderr = LineMatcher(errlines)
+ self.duration = duration
+
+ def parseoutcomes(self):
+ """ Return a dictionary of outcomestring->num from parsing
+ the terminal output that the test process produced."""
+ for line in reversed(self.outlines):
+ if 'seconds' in line:
+ outcomes = rex_outcome.findall(line)
+ if outcomes:
+ d = {}
+ for num, cat in outcomes:
+ d[cat] = int(num)
+ return d
+ raise ValueError("Pytest terminal report not found")
+
+ def assert_outcomes(self, passed=0, skipped=0, failed=0, error=0):
+ """ assert that the specified outcomes appear with the respective
+ numbers (0 means it didn't occur) in the text output from a test run."""
+ d = self.parseoutcomes()
+ obtained = {
+ 'passed': d.get('passed', 0),
+ 'skipped': d.get('skipped', 0),
+ 'failed': d.get('failed', 0),
+ 'error': d.get('error', 0),
+ }
+ assert obtained == dict(passed=passed, skipped=skipped, failed=failed, error=error)
+
+
+class Testdir:
+ """Temporary test directory with tools to test/run pytest itself.
+
+ This is based on the ``tmpdir`` fixture but provides a number of
+ methods which aid with testing pytest itself. Unless
+ :py:meth:`chdir` is used all methods will use :py:attr:`tmpdir` as
+ current working directory.
+
+ Attributes:
+
+ :tmpdir: The :py:class:`py.path.local` instance of the temporary
+ directory.
+
+ :plugins: A list of plugins to use with :py:meth:`parseconfig` and
+ :py:meth:`runpytest`. Initially this is an empty list but
+ plugins can be added to the list. The type of items to add to
+ the list depend on the method which uses them so refer to them
+ for details.
+
+ """
+
+ def __init__(self, request, tmpdir_factory):
+ self.request = request
+ self._mod_collections = WeakKeyDictionary()
+ name = request.function.__name__
+ self.tmpdir = tmpdir_factory.mktemp(name, numbered=True)
+ self.plugins = []
+ self._savesyspath = (list(sys.path), list(sys.meta_path))
+ self._savemodulekeys = set(sys.modules)
+ self.chdir() # always chdir
+ self.request.addfinalizer(self.finalize)
+ method = self.request.config.getoption("--runpytest")
+ if method == "inprocess":
+ self._runpytest_method = self.runpytest_inprocess
+ elif method == "subprocess":
+ self._runpytest_method = self.runpytest_subprocess
+
+ def __repr__(self):
+ return "<Testdir %r>" % (self.tmpdir,)
+
+ def finalize(self):
+ """Clean up global state artifacts.
+
+ Some methods modify the global interpreter state and this
+ tries to clean this up. It does not remove the temporary
+ directory however so it can be looked at after the test run
+ has finished.
+
+ """
+ sys.path[:], sys.meta_path[:] = self._savesyspath
+ if hasattr(self, '_olddir'):
+ self._olddir.chdir()
+ self.delete_loaded_modules()
+
+ def delete_loaded_modules(self):
+ """Delete modules that have been loaded during a test.
+
+ This allows the interpreter to catch module changes in case
+ the module is re-imported.
+ """
+ for name in set(sys.modules).difference(self._savemodulekeys):
+ # some zope modules used by twisted-related tests keeps internal
+ # state and can't be deleted; we had some trouble in the past
+ # with zope.interface for example
+ if not name.startswith("zope"):
+ del sys.modules[name]
+
+ def make_hook_recorder(self, pluginmanager):
+ """Create a new :py:class:`HookRecorder` for a PluginManager."""
+ assert not hasattr(pluginmanager, "reprec")
+ pluginmanager.reprec = reprec = HookRecorder(pluginmanager)
+ self.request.addfinalizer(reprec.finish_recording)
+ return reprec
+
+ def chdir(self):
+ """Cd into the temporary directory.
+
+ This is done automatically upon instantiation.
+
+ """
+ old = self.tmpdir.chdir()
+ if not hasattr(self, '_olddir'):
+ self._olddir = old
+
+ def _makefile(self, ext, args, kwargs, encoding='utf-8'):
+ items = list(kwargs.items())
+
+ def to_text(s):
+ return s.decode(encoding) if isinstance(s, bytes) else six.text_type(s)
+
+ if args:
+ source = u"\n".join(to_text(x) for x in args)
+ basename = self.request.function.__name__
+ items.insert(0, (basename, source))
+
+ ret = None
+ for basename, value in items:
+ p = self.tmpdir.join(basename).new(ext=ext)
+ p.dirpath().ensure_dir()
+ source = Source(value)
+ source = u"\n".join(to_text(line) for line in source.lines)
+ p.write(source.strip().encode(encoding), "wb")
+ if ret is None:
+ ret = p
+ return ret
+
+ def makefile(self, ext, *args, **kwargs):
+ """Create a new file in the testdir.
+
+ ext: The extension the file should use, including the dot.
+ E.g. ".py".
+
+ args: All args will be treated as strings and joined using
+ newlines. The result will be written as contents to the
+ file. The name of the file will be based on the test
+ function requesting this fixture.
+ E.g. "testdir.makefile('.txt', 'line1', 'line2')"
+
+ kwargs: Each keyword is the name of a file, while the value of
+ it will be written as contents of the file.
+ E.g. "testdir.makefile('.ini', pytest='[pytest]\naddopts=-rs\n')"
+
+ """
+ return self._makefile(ext, args, kwargs)
+
+ def makeconftest(self, source):
+ """Write a contest.py file with 'source' as contents."""
+ return self.makepyfile(conftest=source)
+
+ def makeini(self, source):
+ """Write a tox.ini file with 'source' as contents."""
+ return self.makefile('.ini', tox=source)
+
+ def getinicfg(self, source):
+ """Return the pytest section from the tox.ini config file."""
+ p = self.makeini(source)
+ return py.iniconfig.IniConfig(p)['pytest']
+
+ def makepyfile(self, *args, **kwargs):
+ """Shortcut for .makefile() with a .py extension."""
+ return self._makefile('.py', args, kwargs)
+
+ def maketxtfile(self, *args, **kwargs):
+ """Shortcut for .makefile() with a .txt extension."""
+ return self._makefile('.txt', args, kwargs)
+
+ def syspathinsert(self, path=None):
+ """Prepend a directory to sys.path, defaults to :py:attr:`tmpdir`.
+
+ This is undone automatically after the test.
+ """
+ if path is None:
+ path = self.tmpdir
+ sys.path.insert(0, str(path))
+ # a call to syspathinsert() usually means that the caller
+ # wants to import some dynamically created files.
+ # with python3 we thus invalidate import caches.
+ self._possibly_invalidate_import_caches()
+
+ def _possibly_invalidate_import_caches(self):
+ # invalidate caches if we can (py33 and above)
+ try:
+ import importlib
+ except ImportError:
+ pass
+ else:
+ if hasattr(importlib, "invalidate_caches"):
+ importlib.invalidate_caches()
+
+ def mkdir(self, name):
+ """Create a new (sub)directory."""
+ return self.tmpdir.mkdir(name)
+
+ def mkpydir(self, name):
+ """Create a new python package.
+
+ This creates a (sub)directory with an empty ``__init__.py``
+ file so that is recognised as a python package.
+
+ """
+ p = self.mkdir(name)
+ p.ensure("__init__.py")
+ return p
+
+ Session = Session
+
+ def getnode(self, config, arg):
+ """Return the collection node of a file.
+
+ :param config: :py:class:`_pytest.config.Config` instance, see
+ :py:meth:`parseconfig` and :py:meth:`parseconfigure` to
+ create the configuration.
+
+ :param arg: A :py:class:`py.path.local` instance of the file.
+
+ """
+ session = Session(config)
+ assert '::' not in str(arg)
+ p = py.path.local(arg)
+ config.hook.pytest_sessionstart(session=session)
+ res = session.perform_collect([str(p)], genitems=False)[0]
+ config.hook.pytest_sessionfinish(session=session, exitstatus=EXIT_OK)
+ return res
+
+ def getpathnode(self, path):
+ """Return the collection node of a file.
+
+ This is like :py:meth:`getnode` but uses
+ :py:meth:`parseconfigure` to create the (configured) pytest
+ Config instance.
+
+ :param path: A :py:class:`py.path.local` instance of the file.
+
+ """
+ config = self.parseconfigure(path)
+ session = Session(config)
+ x = session.fspath.bestrelpath(path)
+ config.hook.pytest_sessionstart(session=session)
+ res = session.perform_collect([x], genitems=False)[0]
+ config.hook.pytest_sessionfinish(session=session, exitstatus=EXIT_OK)
+ return res
+
+ def genitems(self, colitems):
+ """Generate all test items from a collection node.
+
+ This recurses into the collection node and returns a list of
+ all the test items contained within.
+
+ """
+ session = colitems[0].session
+ result = []
+ for colitem in colitems:
+ result.extend(session.genitems(colitem))
+ return result
+
+ def runitem(self, source):
+ """Run the "test_func" Item.
+
+ The calling test instance (the class which contains the test
+ method) must provide a ``.getrunner()`` method which should
+ return a runner which can run the test protocol for a single
+ item, like e.g. :py:func:`_pytest.runner.runtestprotocol`.
+
+ """
+ # used from runner functional tests
+ item = self.getitem(source)
+ # the test class where we are called from wants to provide the runner
+ testclassinstance = self.request.instance
+ runner = testclassinstance.getrunner()
+ return runner(item)
+
+ def inline_runsource(self, source, *cmdlineargs):
+ """Run a test module in process using ``pytest.main()``.
+
+ This run writes "source" into a temporary file and runs
+ ``pytest.main()`` on it, returning a :py:class:`HookRecorder`
+ instance for the result.
+
+ :param source: The source code of the test module.
+
+ :param cmdlineargs: Any extra command line arguments to use.
+
+ :return: :py:class:`HookRecorder` instance of the result.
+
+ """
+ p = self.makepyfile(source)
+ values = list(cmdlineargs) + [p]
+ return self.inline_run(*values)
+
+ def inline_genitems(self, *args):
+ """Run ``pytest.main(['--collectonly'])`` in-process.
+
+ Returns a tuple of the collected items and a
+ :py:class:`HookRecorder` instance.
+
+ This runs the :py:func:`pytest.main` function to run all of
+ pytest inside the test process itself like
+ :py:meth:`inline_run`. However the return value is a tuple of
+ the collection items and a :py:class:`HookRecorder` instance.
+
+ """
+ rec = self.inline_run("--collect-only", *args)
+ items = [x.item for x in rec.getcalls("pytest_itemcollected")]
+ return items, rec
+
+ def inline_run(self, *args, **kwargs):
+ """Run ``pytest.main()`` in-process, returning a HookRecorder.
+
+ This runs the :py:func:`pytest.main` function to run all of
+ pytest inside the test process itself. This means it can
+ return a :py:class:`HookRecorder` instance which gives more
+ detailed results from then run then can be done by matching
+ stdout/stderr from :py:meth:`runpytest`.
+
+ :param args: Any command line arguments to pass to
+ :py:func:`pytest.main`.
+
+ :param plugin: (keyword-only) Extra plugin instances the
+ ``pytest.main()`` instance should use.
+
+ :return: A :py:class:`HookRecorder` instance.
+ """
+ # When running py.test inline any plugins active in the main
+ # test process are already imported. So this disables the
+ # warning which will trigger to say they can no longer be
+ # rewritten, which is fine as they are already rewritten.
+ orig_warn = AssertionRewritingHook._warn_already_imported
+
+ def revert():
+ AssertionRewritingHook._warn_already_imported = orig_warn
+
+ self.request.addfinalizer(revert)
+ AssertionRewritingHook._warn_already_imported = lambda *a: None
+
+ rec = []
+
+ class Collect:
+ def pytest_configure(x, config):
+ rec.append(self.make_hook_recorder(config.pluginmanager))
+
+ plugins = kwargs.get("plugins") or []
+ plugins.append(Collect())
+ ret = pytest.main(list(args), plugins=plugins)
+ self.delete_loaded_modules()
+ if len(rec) == 1:
+ reprec = rec.pop()
+ else:
+ class reprec:
+ pass
+ reprec.ret = ret
+
+ # typically we reraise keyboard interrupts from the child run
+ # because it's our user requesting interruption of the testing
+ if ret == 2 and not kwargs.get("no_reraise_ctrlc"):
+ calls = reprec.getcalls("pytest_keyboard_interrupt")
+ if calls and calls[-1].excinfo.type == KeyboardInterrupt:
+ raise KeyboardInterrupt()
+ return reprec
+
+ def runpytest_inprocess(self, *args, **kwargs):
+ """ Return result of running pytest in-process, providing a similar
+ interface to what self.runpytest() provides. """
+ if kwargs.get("syspathinsert"):
+ self.syspathinsert()
+ now = time.time()
+ capture = MultiCapture(Capture=SysCapture)
+ capture.start_capturing()
+ try:
+ try:
+ reprec = self.inline_run(*args, **kwargs)
+ except SystemExit as e:
+
+ class reprec:
+ ret = e.args[0]
+
+ except Exception:
+ traceback.print_exc()
+
+ class reprec:
+ ret = 3
+ finally:
+ out, err = capture.readouterr()
+ capture.stop_capturing()
+ sys.stdout.write(out)
+ sys.stderr.write(err)
+
+ res = RunResult(reprec.ret,
+ out.split("\n"), err.split("\n"),
+ time.time() - now)
+ res.reprec = reprec
+ return res
+
+ def runpytest(self, *args, **kwargs):
+ """ Run pytest inline or in a subprocess, depending on the command line
+ option "--runpytest" and return a :py:class:`RunResult`.
+
+ """
+ args = self._ensure_basetemp(args)
+ return self._runpytest_method(*args, **kwargs)
+
+ def _ensure_basetemp(self, args):
+ args = [str(x) for x in args]
+ for x in args:
+ if str(x).startswith('--basetemp'):
+ # print("basedtemp exists: %s" %(args,))
+ break
+ else:
+ args.append("--basetemp=%s" % self.tmpdir.dirpath('basetemp'))
+ # print("added basetemp: %s" %(args,))
+ return args
+
+ def parseconfig(self, *args):
+ """Return a new pytest Config instance from given commandline args.
+
+ This invokes the pytest bootstrapping code in _pytest.config
+ to create a new :py:class:`_pytest.core.PluginManager` and
+ call the pytest_cmdline_parse hook to create new
+ :py:class:`_pytest.config.Config` instance.
+
+ If :py:attr:`plugins` has been populated they should be plugin
+ modules which will be registered with the PluginManager.
+
+ """
+ args = self._ensure_basetemp(args)
+
+ import _pytest.config
+ config = _pytest.config._prepareconfig(args, self.plugins)
+ # we don't know what the test will do with this half-setup config
+ # object and thus we make sure it gets unconfigured properly in any
+ # case (otherwise capturing could still be active, for example)
+ self.request.addfinalizer(config._ensure_unconfigure)
+ return config
+
+ def parseconfigure(self, *args):
+ """Return a new pytest configured Config instance.
+
+ This returns a new :py:class:`_pytest.config.Config` instance
+ like :py:meth:`parseconfig`, but also calls the
+ pytest_configure hook.
+
+ """
+ config = self.parseconfig(*args)
+ config._do_configure()
+ self.request.addfinalizer(config._ensure_unconfigure)
+ return config
+
+ def getitem(self, source, funcname="test_func"):
+ """Return the test item for a test function.
+
+ This writes the source to a python file and runs pytest's
+ collection on the resulting module, returning the test item
+ for the requested function name.
+
+ :param source: The module source.
+
+ :param funcname: The name of the test function for which the
+ Item must be returned.
+
+ """
+ items = self.getitems(source)
+ for item in items:
+ if item.name == funcname:
+ return item
+ assert 0, "%r item not found in module:\n%s\nitems: %s" % (
+ funcname, source, items)
+
+ def getitems(self, source):
+ """Return all test items collected from the module.
+
+ This writes the source to a python file and runs pytest's
+ collection on the resulting module, returning all test items
+ contained within.
+
+ """
+ modcol = self.getmodulecol(source)
+ return self.genitems([modcol])
+
+ def getmodulecol(self, source, configargs=(), withinit=False):
+ """Return the module collection node for ``source``.
+
+ This writes ``source`` to a file using :py:meth:`makepyfile`
+ and then runs the pytest collection on it, returning the
+ collection node for the test module.
+
+ :param source: The source code of the module to collect.
+
+ :param configargs: Any extra arguments to pass to
+ :py:meth:`parseconfigure`.
+
+ :param withinit: Whether to also write a ``__init__.py`` file
+ to the temporary directory to ensure it is a package.
+
+ """
+ kw = {self.request.function.__name__: Source(source).strip()}
+ path = self.makepyfile(**kw)
+ if withinit:
+ self.makepyfile(__init__="#")
+ self.config = config = self.parseconfigure(path, *configargs)
+ node = self.getnode(config, path)
+
+ return node
+
+ def collect_by_name(self, modcol, name):
+ """Return the collection node for name from the module collection.
+
+ This will search a module collection node for a collection
+ node matching the given name.
+
+ :param modcol: A module collection node, see
+ :py:meth:`getmodulecol`.
+
+ :param name: The name of the node to return.
+
+ """
+ if modcol not in self._mod_collections:
+ self._mod_collections[modcol] = list(modcol.collect())
+ for colitem in self._mod_collections[modcol]:
+ if colitem.name == name:
+ return colitem
+
+ def popen(self, cmdargs, stdout, stderr, **kw):
+ """Invoke subprocess.Popen.
+
+ This calls subprocess.Popen making sure the current working
+ directory is the PYTHONPATH.
+
+ You probably want to use :py:meth:`run` instead.
+
+ """
+ env = os.environ.copy()
+ env['PYTHONPATH'] = os.pathsep.join(filter(None, [
+ str(os.getcwd()), env.get('PYTHONPATH', '')]))
+ kw['env'] = env
+
+ popen = subprocess.Popen(cmdargs, stdin=subprocess.PIPE, stdout=stdout, stderr=stderr, **kw)
+ popen.stdin.close()
+
+ return popen
+
+ def run(self, *cmdargs):
+ """Run a command with arguments.
+
+ Run a process using subprocess.Popen saving the stdout and
+ stderr.
+
+ Returns a :py:class:`RunResult`.
+
+ """
+ return self._run(*cmdargs)
+
+ def _run(self, *cmdargs):
+ cmdargs = [str(x) for x in cmdargs]
+ p1 = self.tmpdir.join("stdout")
+ p2 = self.tmpdir.join("stderr")
+ print("running:", ' '.join(cmdargs))
+ print(" in:", str(py.path.local()))
+ f1 = codecs.open(str(p1), "w", encoding="utf8")
+ f2 = codecs.open(str(p2), "w", encoding="utf8")
+ try:
+ now = time.time()
+ popen = self.popen(cmdargs, stdout=f1, stderr=f2,
+ close_fds=(sys.platform != "win32"))
+ ret = popen.wait()
+ finally:
+ f1.close()
+ f2.close()
+ f1 = codecs.open(str(p1), "r", encoding="utf8")
+ f2 = codecs.open(str(p2), "r", encoding="utf8")
+ try:
+ out = f1.read().splitlines()
+ err = f2.read().splitlines()
+ finally:
+ f1.close()
+ f2.close()
+ self._dump_lines(out, sys.stdout)
+ self._dump_lines(err, sys.stderr)
+ return RunResult(ret, out, err, time.time() - now)
+
+ def _dump_lines(self, lines, fp):
+ try:
+ for line in lines:
+ print(line, file=fp)
+ except UnicodeEncodeError:
+ print("couldn't print to %s because of encoding" % (fp,))
+
+ def _getpytestargs(self):
+ # we cannot use "(sys.executable,script)"
+ # because on windows the script is e.g. a pytest.exe
+ return (sys.executable, PYTEST_FULLPATH) # noqa
+
+ def runpython(self, script):
+ """Run a python script using sys.executable as interpreter.
+
+ Returns a :py:class:`RunResult`.
+ """
+ return self.run(sys.executable, script)
+
+ def runpython_c(self, command):
+ """Run python -c "command", return a :py:class:`RunResult`."""
+ return self.run(sys.executable, "-c", command)
+
+ def runpytest_subprocess(self, *args, **kwargs):
+ """Run pytest as a subprocess with given arguments.
+
+ Any plugins added to the :py:attr:`plugins` list will added
+ using the ``-p`` command line option. Addtionally
+ ``--basetemp`` is used put any temporary files and directories
+ in a numbered directory prefixed with "runpytest-" so they do
+ not conflict with the normal numberd pytest location for
+ temporary files and directories.
+
+ Returns a :py:class:`RunResult`.
+
+ """
+ p = py.path.local.make_numbered_dir(prefix="runpytest-",
+ keep=None, rootdir=self.tmpdir)
+ args = ('--basetemp=%s' % p, ) + args
+ # for x in args:
+ # if '--confcutdir' in str(x):
+ # break
+ # else:
+ # pass
+ # args = ('--confcutdir=.',) + args
+ plugins = [x for x in self.plugins if isinstance(x, str)]
+ if plugins:
+ args = ('-p', plugins[0]) + args
+ args = self._getpytestargs() + args
+ return self.run(*args)
+
+ def spawn_pytest(self, string, expect_timeout=10.0):
+ """Run pytest using pexpect.
+
+ This makes sure to use the right pytest and sets up the
+ temporary directory locations.
+
+ The pexpect child is returned.
+
+ """
+ basetemp = self.tmpdir.mkdir("temp-pexpect")
+ invoke = " ".join(map(str, self._getpytestargs()))
+ cmd = "%s --basetemp=%s %s" % (invoke, basetemp, string)
+ return self.spawn(cmd, expect_timeout=expect_timeout)
+
+ def spawn(self, cmd, expect_timeout=10.0):
+ """Run a command using pexpect.
+
+ The pexpect child is returned.
+ """
+ pexpect = pytest.importorskip("pexpect", "3.0")
+ if hasattr(sys, 'pypy_version_info') and '64' in platform.machine():
+ pytest.skip("pypy-64 bit not supported")
+ if sys.platform.startswith("freebsd"):
+ pytest.xfail("pexpect does not work reliably on freebsd")
+ logfile = self.tmpdir.join("spawn.out").open("wb")
+ child = pexpect.spawn(cmd, logfile=logfile)
+ self.request.addfinalizer(logfile.close)
+ child.timeout = expect_timeout
+ return child
+
+
+def getdecoded(out):
+ try:
+ return out.decode("utf-8")
+ except UnicodeDecodeError:
+ return "INTERNAL not-utf8-decodeable, truncated string:\n%s" % (
+ py.io.saferepr(out),)
+
+
+class LineComp:
+ def __init__(self):
+ self.stringio = py.io.TextIO()
+
+ def assert_contains_lines(self, lines2):
+ """ assert that lines2 are contained (linearly) in lines1.
+ return a list of extralines found.
+ """
+ __tracebackhide__ = True
+ val = self.stringio.getvalue()
+ self.stringio.truncate(0)
+ self.stringio.seek(0)
+ lines1 = val.split("\n")
+ return LineMatcher(lines1).fnmatch_lines(lines2)
+
+
+class LineMatcher:
+ """Flexible matching of text.
+
+ This is a convenience class to test large texts like the output of
+ commands.
+
+ The constructor takes a list of lines without their trailing
+ newlines, i.e. ``text.splitlines()``.
+
+ """
+
+ def __init__(self, lines):
+ self.lines = lines
+ self._log_output = []
+
+ def str(self):
+ """Return the entire original text."""
+ return "\n".join(self.lines)
+
+ def _getlines(self, lines2):
+ if isinstance(lines2, str):
+ lines2 = Source(lines2)
+ if isinstance(lines2, Source):
+ lines2 = lines2.strip().lines
+ return lines2
+
+ def fnmatch_lines_random(self, lines2):
+ """Check lines exist in the output using ``fnmatch.fnmatch``, in any order.
+
+ The argument is a list of lines which have to occur in the
+ output, in any order.
+ """
+ self._match_lines_random(lines2, fnmatch)
+
+ def re_match_lines_random(self, lines2):
+ """Check lines exist in the output using ``re.match``, in any order.
+
+ The argument is a list of lines which have to occur in the
+ output, in any order.
+
+ """
+ self._match_lines_random(lines2, lambda name, pat: re.match(pat, name))
+
+ def _match_lines_random(self, lines2, match_func):
+ """Check lines exist in the output.
+
+ The argument is a list of lines which have to occur in the
+ output, in any order. Each line can contain glob whildcards.
+
+ """
+ lines2 = self._getlines(lines2)
+ for line in lines2:
+ for x in self.lines:
+ if line == x or match_func(x, line):
+ self._log("matched: ", repr(line))
+ break
+ else:
+ self._log("line %r not found in output" % line)
+ raise ValueError(self._log_text)
+
+ def get_lines_after(self, fnline):
+ """Return all lines following the given line in the text.
+
+ The given line can contain glob wildcards.
+ """
+ for i, line in enumerate(self.lines):
+ if fnline == line or fnmatch(line, fnline):
+ return self.lines[i + 1:]
+ raise ValueError("line %r not found in output" % fnline)
+
+ def _log(self, *args):
+ self._log_output.append(' '.join((str(x) for x in args)))
+
+ @property
+ def _log_text(self):
+ return '\n'.join(self._log_output)
+
+ def fnmatch_lines(self, lines2):
+ """Search captured text for matching lines using ``fnmatch.fnmatch``.
+
+ The argument is a list of lines which have to match and can
+ use glob wildcards. If they do not match a pytest.fail() is
+ called. The matches and non-matches are also printed on
+ stdout.
+
+ """
+ self._match_lines(lines2, fnmatch, 'fnmatch')
+
+ def re_match_lines(self, lines2):
+ """Search captured text for matching lines using ``re.match``.
+
+ The argument is a list of lines which have to match using ``re.match``.
+ If they do not match a pytest.fail() is called.
+
+ The matches and non-matches are also printed on
+ stdout.
+ """
+ self._match_lines(lines2, lambda name, pat: re.match(pat, name), 're.match')
+
+ def _match_lines(self, lines2, match_func, match_nickname):
+ """Underlying implementation of ``fnmatch_lines`` and ``re_match_lines``.
+
+ :param list[str] lines2: list of string patterns to match. The actual format depends on
+ ``match_func``.
+ :param match_func: a callable ``match_func(line, pattern)`` where line is the captured
+ line from stdout/stderr and pattern is the matching pattern.
+
+ :param str match_nickname: the nickname for the match function that will be logged
+ to stdout when a match occurs.
+ """
+ lines2 = self._getlines(lines2)
+ lines1 = self.lines[:]
+ nextline = None
+ extralines = []
+ __tracebackhide__ = True
+ for line in lines2:
+ nomatchprinted = False
+ while lines1:
+ nextline = lines1.pop(0)
+ if line == nextline:
+ self._log("exact match:", repr(line))
+ break
+ elif match_func(nextline, line):
+ self._log("%s:" % match_nickname, repr(line))
+ self._log(" with:", repr(nextline))
+ break
+ else:
+ if not nomatchprinted:
+ self._log("nomatch:", repr(line))
+ nomatchprinted = True
+ self._log(" and:", repr(nextline))
+ extralines.append(nextline)
+ else:
+ self._log("remains unmatched: %r" % (line,))
+ pytest.fail(self._log_text)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/python.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/python.py
new file mode 100644
index 00000000000..650171a9e9c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/python.py
@@ -0,0 +1,1175 @@
+""" Python test discovery, setup and run of test functions. """
+from __future__ import absolute_import, division, print_function
+
+import fnmatch
+import inspect
+import sys
+import os
+import collections
+import warnings
+from textwrap import dedent
+from itertools import count
+
+
+import py
+import six
+from _pytest.mark import MarkerError
+from _pytest.config import hookimpl
+
+import _pytest
+import pluggy
+from _pytest import fixtures
+from _pytest import main
+from _pytest import deprecated
+from _pytest.compat import (
+ isclass, isfunction, is_generator, ascii_escaped,
+ REGEX_TYPE, STRING_TYPES, NoneType, NOTSET,
+ get_real_func, getfslineno, safe_getattr,
+ safe_str, getlocation, enum,
+)
+from _pytest.outcomes import fail
+from _pytest.mark import transfer_markers
+
+cutdir1 = py.path.local(pluggy.__file__.rstrip("oc"))
+cutdir2 = py.path.local(_pytest.__file__).dirpath()
+cutdir3 = py.path.local(py.__file__).dirpath()
+
+
+def filter_traceback(entry):
+ """Return True if a TracebackEntry instance should be removed from tracebacks:
+ * dynamically generated code (no code to show up for it);
+ * internal traceback from pytest or its internal libraries, py and pluggy.
+ """
+ # entry.path might sometimes return a str object when the entry
+ # points to dynamically generated code
+ # see https://bitbucket.org/pytest-dev/py/issues/71
+ raw_filename = entry.frame.code.raw.co_filename
+ is_generated = '<' in raw_filename and '>' in raw_filename
+ if is_generated:
+ return False
+ # entry.path might point to an inexisting file, in which case it will
+ # alsso return a str object. see #1133
+ p = py.path.local(entry.path)
+ return p != cutdir1 and not p.relto(cutdir2) and not p.relto(cutdir3)
+
+
+def pyobj_property(name):
+ def get(self):
+ node = self.getparent(getattr(__import__('pytest'), name))
+ if node is not None:
+ return node.obj
+ doc = "python %s object this node was collected from (can be None)." % (
+ name.lower(),)
+ return property(get, None, None, doc)
+
+
+def pytest_addoption(parser):
+ group = parser.getgroup("general")
+ group.addoption('--fixtures', '--funcargs',
+ action="store_true", dest="showfixtures", default=False,
+ help="show available fixtures, sorted by plugin appearance")
+ group.addoption(
+ '--fixtures-per-test',
+ action="store_true",
+ dest="show_fixtures_per_test",
+ default=False,
+ help="show fixtures per test",
+ )
+ parser.addini("usefixtures", type="args", default=[],
+ help="list of default fixtures to be used with this project")
+ parser.addini("python_files", type="args",
+ default=['test_*.py', '*_test.py'],
+ help="glob-style file patterns for Python test module discovery")
+ parser.addini("python_classes", type="args", default=["Test", ],
+ help="prefixes or glob names for Python test class discovery")
+ parser.addini("python_functions", type="args", default=["test", ],
+ help="prefixes or glob names for Python test function and "
+ "method discovery")
+
+ group.addoption("--import-mode", default="prepend",
+ choices=["prepend", "append"], dest="importmode",
+ help="prepend/append to sys.path when importing test modules, "
+ "default is to prepend.")
+
+
+def pytest_cmdline_main(config):
+ if config.option.showfixtures:
+ showfixtures(config)
+ return 0
+ if config.option.show_fixtures_per_test:
+ show_fixtures_per_test(config)
+ return 0
+
+
+def pytest_generate_tests(metafunc):
+ # those alternative spellings are common - raise a specific error to alert
+ # the user
+ alt_spellings = ['parameterize', 'parametrise', 'parameterise']
+ for attr in alt_spellings:
+ if hasattr(metafunc.function, attr):
+ msg = "{0} has '{1}', spelling should be 'parametrize'"
+ raise MarkerError(msg.format(metafunc.function.__name__, attr))
+ try:
+ markers = metafunc.function.parametrize
+ except AttributeError:
+ return
+ for marker in markers:
+ metafunc.parametrize(*marker.args, **marker.kwargs)
+
+
+def pytest_configure(config):
+ config.addinivalue_line("markers",
+ "parametrize(argnames, argvalues): call a test function multiple "
+ "times passing in different arguments in turn. argvalues generally "
+ "needs to be a list of values if argnames specifies only one name "
+ "or a list of tuples of values if argnames specifies multiple names. "
+ "Example: @parametrize('arg1', [1,2]) would lead to two calls of the "
+ "decorated test function, one with arg1=1 and another with arg1=2."
+ "see http://pytest.org/latest/parametrize.html for more info and "
+ "examples."
+ )
+ config.addinivalue_line("markers",
+ "usefixtures(fixturename1, fixturename2, ...): mark tests as needing "
+ "all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures "
+ )
+
+
+@hookimpl(trylast=True)
+def pytest_pyfunc_call(pyfuncitem):
+ testfunction = pyfuncitem.obj
+ if pyfuncitem._isyieldedfunction():
+ testfunction(*pyfuncitem._args)
+ else:
+ funcargs = pyfuncitem.funcargs
+ testargs = {}
+ for arg in pyfuncitem._fixtureinfo.argnames:
+ testargs[arg] = funcargs[arg]
+ testfunction(**testargs)
+ return True
+
+
+def pytest_collect_file(path, parent):
+ ext = path.ext
+ if ext == ".py":
+ if not parent.session.isinitpath(path):
+ for pat in parent.config.getini('python_files'):
+ if path.fnmatch(pat):
+ break
+ else:
+ return
+ ihook = parent.session.gethookproxy(path)
+ return ihook.pytest_pycollect_makemodule(path=path, parent=parent)
+
+
+def pytest_pycollect_makemodule(path, parent):
+ return Module(path, parent)
+
+
+@hookimpl(hookwrapper=True)
+def pytest_pycollect_makeitem(collector, name, obj):
+ outcome = yield
+ res = outcome.get_result()
+ if res is not None:
+ return
+ # nothing was collected elsewhere, let's do it here
+ if isclass(obj):
+ if collector.istestclass(obj, name):
+ Class = collector._getcustomclass("Class")
+ outcome.force_result(Class(name, parent=collector))
+ elif collector.istestfunction(obj, name):
+ # mock seems to store unbound methods (issue473), normalize it
+ obj = getattr(obj, "__func__", obj)
+ # We need to try and unwrap the function if it's a functools.partial
+ # or a funtools.wrapped.
+ # We musn't if it's been wrapped with mock.patch (python 2 only)
+ if not (isfunction(obj) or isfunction(get_real_func(obj))):
+ collector.warn(code="C2", message="cannot collect %r because it is not a function."
+ % name, )
+ elif getattr(obj, "__test__", True):
+ if is_generator(obj):
+ res = Generator(name, parent=collector)
+ else:
+ res = list(collector._genfunctions(name, obj))
+ outcome.force_result(res)
+
+
+def pytest_make_parametrize_id(config, val, argname=None):
+ return None
+
+
+class PyobjContext(object):
+ module = pyobj_property("Module")
+ cls = pyobj_property("Class")
+ instance = pyobj_property("Instance")
+
+
+class PyobjMixin(PyobjContext):
+ def obj():
+ def fget(self):
+ obj = getattr(self, '_obj', None)
+ if obj is None:
+ self._obj = obj = self._getobj()
+ return obj
+
+ def fset(self, value):
+ self._obj = value
+
+ return property(fget, fset, None, "underlying python object")
+
+ obj = obj()
+
+ def _getobj(self):
+ return getattr(self.parent.obj, self.name)
+
+ def getmodpath(self, stopatmodule=True, includemodule=False):
+ """ return python path relative to the containing module. """
+ chain = self.listchain()
+ chain.reverse()
+ parts = []
+ for node in chain:
+ if isinstance(node, Instance):
+ continue
+ name = node.name
+ if isinstance(node, Module):
+ name = os.path.splitext(name)[0]
+ if stopatmodule:
+ if includemodule:
+ parts.append(name)
+ break
+ parts.append(name)
+ parts.reverse()
+ s = ".".join(parts)
+ return s.replace(".[", "[")
+
+ def _getfslineno(self):
+ return getfslineno(self.obj)
+
+ def reportinfo(self):
+ # XXX caching?
+ obj = self.obj
+ compat_co_firstlineno = getattr(obj, 'compat_co_firstlineno', None)
+ if isinstance(compat_co_firstlineno, int):
+ # nose compatibility
+ fspath = sys.modules[obj.__module__].__file__
+ if fspath.endswith(".pyc"):
+ fspath = fspath[:-1]
+ lineno = compat_co_firstlineno
+ else:
+ fspath, lineno = getfslineno(obj)
+ modpath = self.getmodpath()
+ assert isinstance(lineno, int)
+ return fspath, lineno, modpath
+
+
+class PyCollector(PyobjMixin, main.Collector):
+
+ def funcnamefilter(self, name):
+ return self._matches_prefix_or_glob_option('python_functions', name)
+
+ def isnosetest(self, obj):
+ """ Look for the __test__ attribute, which is applied by the
+ @nose.tools.istest decorator
+ """
+ # We explicitly check for "is True" here to not mistakenly treat
+ # classes with a custom __getattr__ returning something truthy (like a
+ # function) as test classes.
+ return safe_getattr(obj, '__test__', False) is True
+
+ def classnamefilter(self, name):
+ return self._matches_prefix_or_glob_option('python_classes', name)
+
+ def istestfunction(self, obj, name):
+ if self.funcnamefilter(name) or self.isnosetest(obj):
+ if isinstance(obj, staticmethod):
+ # static methods need to be unwrapped
+ obj = safe_getattr(obj, '__func__', False)
+ if obj is False:
+ # Python 2.6 wraps in a different way that we won't try to handle
+ msg = "cannot collect static method %r because " \
+ "it is not a function (always the case in Python 2.6)"
+ self.warn(
+ code="C2", message=msg % name)
+ return False
+ return (
+ safe_getattr(obj, "__call__", False) and fixtures.getfixturemarker(obj) is None
+ )
+ else:
+ return False
+
+ def istestclass(self, obj, name):
+ return self.classnamefilter(name) or self.isnosetest(obj)
+
+ def _matches_prefix_or_glob_option(self, option_name, name):
+ """
+ checks if the given name matches the prefix or glob-pattern defined
+ in ini configuration.
+ """
+ for option in self.config.getini(option_name):
+ if name.startswith(option):
+ return True
+ # check that name looks like a glob-string before calling fnmatch
+ # because this is called for every name in each collected module,
+ # and fnmatch is somewhat expensive to call
+ elif ('*' in option or '?' in option or '[' in option) and \
+ fnmatch.fnmatch(name, option):
+ return True
+ return False
+
+ def collect(self):
+ if not getattr(self.obj, "__test__", True):
+ return []
+
+ # NB. we avoid random getattrs and peek in the __dict__ instead
+ # (XXX originally introduced from a PyPy need, still true?)
+ dicts = [getattr(self.obj, '__dict__', {})]
+ for basecls in inspect.getmro(self.obj.__class__):
+ dicts.append(basecls.__dict__)
+ seen = {}
+ values = []
+ for dic in dicts:
+ for name, obj in list(dic.items()):
+ if name in seen:
+ continue
+ seen[name] = True
+ res = self._makeitem(name, obj)
+ if res is None:
+ continue
+ if not isinstance(res, list):
+ res = [res]
+ values.extend(res)
+ values.sort(key=lambda item: item.reportinfo()[:2])
+ return values
+
+ def makeitem(self, name, obj):
+ warnings.warn(deprecated.COLLECTOR_MAKEITEM, stacklevel=2)
+ self._makeitem(name, obj)
+
+ def _makeitem(self, name, obj):
+ # assert self.ihook.fspath == self.fspath, self
+ return self.ihook.pytest_pycollect_makeitem(
+ collector=self, name=name, obj=obj)
+
+ def _genfunctions(self, name, funcobj):
+ module = self.getparent(Module).obj
+ clscol = self.getparent(Class)
+ cls = clscol and clscol.obj or None
+ transfer_markers(funcobj, cls, module)
+ fm = self.session._fixturemanager
+ fixtureinfo = fm.getfixtureinfo(self, funcobj, cls)
+ metafunc = Metafunc(funcobj, fixtureinfo, self.config,
+ cls=cls, module=module)
+ methods = []
+ if hasattr(module, "pytest_generate_tests"):
+ methods.append(module.pytest_generate_tests)
+ if hasattr(cls, "pytest_generate_tests"):
+ methods.append(cls().pytest_generate_tests)
+ if methods:
+ self.ihook.pytest_generate_tests.call_extra(methods,
+ dict(metafunc=metafunc))
+ else:
+ self.ihook.pytest_generate_tests(metafunc=metafunc)
+
+ Function = self._getcustomclass("Function")
+ if not metafunc._calls:
+ yield Function(name, parent=self, fixtureinfo=fixtureinfo)
+ else:
+ # add funcargs() as fixturedefs to fixtureinfo.arg2fixturedefs
+ fixtures.add_funcarg_pseudo_fixture_def(self, metafunc, fm)
+
+ for callspec in metafunc._calls:
+ subname = "%s[%s]" % (name, callspec.id)
+ yield Function(name=subname, parent=self,
+ callspec=callspec, callobj=funcobj,
+ fixtureinfo=fixtureinfo,
+ keywords={callspec.id: True},
+ originalname=name,
+ )
+
+
+class Module(main.File, PyCollector):
+ """ Collector for test classes and functions. """
+
+ def _getobj(self):
+ return self._importtestmodule()
+
+ def collect(self):
+ self.session._fixturemanager.parsefactories(self)
+ return super(Module, self).collect()
+
+ def _importtestmodule(self):
+ # we assume we are only called once per module
+ importmode = self.config.getoption("--import-mode")
+ try:
+ mod = self.fspath.pyimport(ensuresyspath=importmode)
+ except SyntaxError:
+ raise self.CollectError(
+ _pytest._code.ExceptionInfo().getrepr(style="short"))
+ except self.fspath.ImportMismatchError:
+ e = sys.exc_info()[1]
+ raise self.CollectError(
+ "import file mismatch:\n"
+ "imported module %r has this __file__ attribute:\n"
+ " %s\n"
+ "which is not the same as the test file we want to collect:\n"
+ " %s\n"
+ "HINT: remove __pycache__ / .pyc files and/or use a "
+ "unique basename for your test file modules"
+ % e.args
+ )
+ except ImportError:
+ from _pytest._code.code import ExceptionInfo
+ exc_info = ExceptionInfo()
+ if self.config.getoption('verbose') < 2:
+ exc_info.traceback = exc_info.traceback.filter(filter_traceback)
+ exc_repr = exc_info.getrepr(style='short') if exc_info.traceback else exc_info.exconly()
+ formatted_tb = safe_str(exc_repr)
+ raise self.CollectError(
+ "ImportError while importing test module '{fspath}'.\n"
+ "Hint: make sure your test modules/packages have valid Python names.\n"
+ "Traceback:\n"
+ "{traceback}".format(fspath=self.fspath, traceback=formatted_tb)
+ )
+ except _pytest.runner.Skipped as e:
+ if e.allow_module_level:
+ raise
+ raise self.CollectError(
+ "Using pytest.skip outside of a test is not allowed. "
+ "To decorate a test function, use the @pytest.mark.skip "
+ "or @pytest.mark.skipif decorators instead, and to skip a "
+ "module use `pytestmark = pytest.mark.{skip,skipif}."
+ )
+ self.config.pluginmanager.consider_module(mod)
+ return mod
+
+ def setup(self):
+ setup_module = _get_xunit_setup_teardown(self.obj, "setUpModule")
+ if setup_module is None:
+ setup_module = _get_xunit_setup_teardown(self.obj, "setup_module")
+ if setup_module is not None:
+ setup_module()
+
+ teardown_module = _get_xunit_setup_teardown(self.obj, 'tearDownModule')
+ if teardown_module is None:
+ teardown_module = _get_xunit_setup_teardown(self.obj, 'teardown_module')
+ if teardown_module is not None:
+ self.addfinalizer(teardown_module)
+
+
+def _get_xunit_setup_teardown(holder, attr_name, param_obj=None):
+ """
+ Return a callable to perform xunit-style setup or teardown if
+ the function exists in the ``holder`` object.
+ The ``param_obj`` parameter is the parameter which will be passed to the function
+ when the callable is called without arguments, defaults to the ``holder`` object.
+ Return ``None`` if a suitable callable is not found.
+ """
+ param_obj = param_obj if param_obj is not None else holder
+ result = _get_xunit_func(holder, attr_name)
+ if result is not None:
+ arg_count = result.__code__.co_argcount
+ if inspect.ismethod(result):
+ arg_count -= 1
+ if arg_count:
+ return lambda: result(param_obj)
+ else:
+ return result
+
+
+def _get_xunit_func(obj, name):
+ """Return the attribute from the given object to be used as a setup/teardown
+ xunit-style function, but only if not marked as a fixture to
+ avoid calling it twice.
+ """
+ meth = getattr(obj, name, None)
+ if fixtures.getfixturemarker(meth) is None:
+ return meth
+
+
+class Class(PyCollector):
+ """ Collector for test methods. """
+
+ def collect(self):
+ if not safe_getattr(self.obj, "__test__", True):
+ return []
+ if hasinit(self.obj):
+ self.warn("C1", "cannot collect test class %r because it has a "
+ "__init__ constructor" % self.obj.__name__)
+ return []
+ elif hasnew(self.obj):
+ self.warn("C1", "cannot collect test class %r because it has a "
+ "__new__ constructor" % self.obj.__name__)
+ return []
+ return [self._getcustomclass("Instance")(name="()", parent=self)]
+
+ def setup(self):
+ setup_class = _get_xunit_func(self.obj, 'setup_class')
+ if setup_class is not None:
+ setup_class = getattr(setup_class, 'im_func', setup_class)
+ setup_class = getattr(setup_class, '__func__', setup_class)
+ setup_class(self.obj)
+
+ fin_class = getattr(self.obj, 'teardown_class', None)
+ if fin_class is not None:
+ fin_class = getattr(fin_class, 'im_func', fin_class)
+ fin_class = getattr(fin_class, '__func__', fin_class)
+ self.addfinalizer(lambda: fin_class(self.obj))
+
+
+class Instance(PyCollector):
+ def _getobj(self):
+ return self.parent.obj()
+
+ def collect(self):
+ self.session._fixturemanager.parsefactories(self)
+ return super(Instance, self).collect()
+
+ def newinstance(self):
+ self.obj = self._getobj()
+ return self.obj
+
+
+class FunctionMixin(PyobjMixin):
+ """ mixin for the code common to Function and Generator.
+ """
+
+ def setup(self):
+ """ perform setup for this test function. """
+ if hasattr(self, '_preservedparent'):
+ obj = self._preservedparent
+ elif isinstance(self.parent, Instance):
+ obj = self.parent.newinstance()
+ self.obj = self._getobj()
+ else:
+ obj = self.parent.obj
+ if inspect.ismethod(self.obj):
+ setup_name = 'setup_method'
+ teardown_name = 'teardown_method'
+ else:
+ setup_name = 'setup_function'
+ teardown_name = 'teardown_function'
+ setup_func_or_method = _get_xunit_setup_teardown(obj, setup_name, param_obj=self.obj)
+ if setup_func_or_method is not None:
+ setup_func_or_method()
+ teardown_func_or_method = _get_xunit_setup_teardown(obj, teardown_name, param_obj=self.obj)
+ if teardown_func_or_method is not None:
+ self.addfinalizer(teardown_func_or_method)
+
+ def _prunetraceback(self, excinfo):
+ if hasattr(self, '_obj') and not self.config.option.fulltrace:
+ code = _pytest._code.Code(get_real_func(self.obj))
+ path, firstlineno = code.path, code.firstlineno
+ traceback = excinfo.traceback
+ ntraceback = traceback.cut(path=path, firstlineno=firstlineno)
+ if ntraceback == traceback:
+ ntraceback = ntraceback.cut(path=path)
+ if ntraceback == traceback:
+ # ntraceback = ntraceback.cut(excludepath=cutdir2)
+ ntraceback = ntraceback.filter(filter_traceback)
+ if not ntraceback:
+ ntraceback = traceback
+
+ excinfo.traceback = ntraceback.filter()
+ # issue364: mark all but first and last frames to
+ # only show a single-line message for each frame
+ if self.config.option.tbstyle == "auto":
+ if len(excinfo.traceback) > 2:
+ for entry in excinfo.traceback[1:-1]:
+ entry.set_repr_style('short')
+
+ def _repr_failure_py(self, excinfo, style="long"):
+ if excinfo.errisinstance(fail.Exception):
+ if not excinfo.value.pytrace:
+ return py._builtin._totext(excinfo.value)
+ return super(FunctionMixin, self)._repr_failure_py(excinfo,
+ style=style)
+
+ def repr_failure(self, excinfo, outerr=None):
+ assert outerr is None, "XXX outerr usage is deprecated"
+ style = self.config.option.tbstyle
+ if style == "auto":
+ style = "long"
+ return self._repr_failure_py(excinfo, style=style)
+
+
+class Generator(FunctionMixin, PyCollector):
+ def collect(self):
+ # test generators are seen as collectors but they also
+ # invoke setup/teardown on popular request
+ # (induced by the common "test_*" naming shared with normal tests)
+ from _pytest import deprecated
+ self.session._setupstate.prepare(self)
+ # see FunctionMixin.setup and test_setupstate_is_preserved_134
+ self._preservedparent = self.parent.obj
+ values = []
+ seen = {}
+ for i, x in enumerate(self.obj()):
+ name, call, args = self.getcallargs(x)
+ if not callable(call):
+ raise TypeError("%r yielded non callable test %r" % (self.obj, call,))
+ if name is None:
+ name = "[%d]" % i
+ else:
+ name = "['%s']" % name
+ if name in seen:
+ raise ValueError("%r generated tests with non-unique name %r" % (self, name))
+ seen[name] = True
+ values.append(self.Function(name, self, args=args, callobj=call))
+ self.warn('C1', deprecated.YIELD_TESTS)
+ return values
+
+ def getcallargs(self, obj):
+ if not isinstance(obj, (tuple, list)):
+ obj = (obj,)
+ # explicit naming
+ if isinstance(obj[0], six.string_types):
+ name = obj[0]
+ obj = obj[1:]
+ else:
+ name = None
+ call, args = obj[0], obj[1:]
+ return name, call, args
+
+
+def hasinit(obj):
+ init = getattr(obj, '__init__', None)
+ if init:
+ return init != object.__init__
+
+
+def hasnew(obj):
+ new = getattr(obj, '__new__', None)
+ if new:
+ return new != object.__new__
+
+
+class CallSpec2(object):
+ def __init__(self, metafunc):
+ self.metafunc = metafunc
+ self.funcargs = {}
+ self._idlist = []
+ self.params = {}
+ self._globalid = NOTSET
+ self._globalid_args = set()
+ self._globalparam = NOTSET
+ self._arg2scopenum = {} # used for sorting parametrized resources
+ self.marks = []
+ self.indices = {}
+
+ def copy(self, metafunc):
+ cs = CallSpec2(self.metafunc)
+ cs.funcargs.update(self.funcargs)
+ cs.params.update(self.params)
+ cs.marks.extend(self.marks)
+ cs.indices.update(self.indices)
+ cs._arg2scopenum.update(self._arg2scopenum)
+ cs._idlist = list(self._idlist)
+ cs._globalid = self._globalid
+ cs._globalid_args = self._globalid_args
+ cs._globalparam = self._globalparam
+ return cs
+
+ def _checkargnotcontained(self, arg):
+ if arg in self.params or arg in self.funcargs:
+ raise ValueError("duplicate %r" % (arg,))
+
+ def getparam(self, name):
+ try:
+ return self.params[name]
+ except KeyError:
+ if self._globalparam is NOTSET:
+ raise ValueError(name)
+ return self._globalparam
+
+ @property
+ def id(self):
+ return "-".join(map(str, filter(None, self._idlist)))
+
+ def setmulti2(self, valtypes, argnames, valset, id, marks, scopenum,
+ param_index):
+ for arg, val in zip(argnames, valset):
+ self._checkargnotcontained(arg)
+ valtype_for_arg = valtypes[arg]
+ getattr(self, valtype_for_arg)[arg] = val
+ self.indices[arg] = param_index
+ self._arg2scopenum[arg] = scopenum
+ self._idlist.append(id)
+ self.marks.extend(marks)
+
+ def setall(self, funcargs, id, param):
+ for x in funcargs:
+ self._checkargnotcontained(x)
+ self.funcargs.update(funcargs)
+ if id is not NOTSET:
+ self._idlist.append(id)
+ if param is not NOTSET:
+ assert self._globalparam is NOTSET
+ self._globalparam = param
+ for arg in funcargs:
+ self._arg2scopenum[arg] = fixtures.scopenum_function
+
+
+class Metafunc(fixtures.FuncargnamesCompatAttr):
+ """
+ Metafunc objects are passed to the ``pytest_generate_tests`` hook.
+ They help to inspect a test function and to generate tests according to
+ test configuration or values specified in the class or module where a
+ test function is defined.
+ """
+
+ def __init__(self, function, fixtureinfo, config, cls=None, module=None):
+ #: access to the :class:`_pytest.config.Config` object for the test session
+ self.config = config
+
+ #: the module object where the test function is defined in.
+ self.module = module
+
+ #: underlying python test function
+ self.function = function
+
+ #: set of fixture names required by the test function
+ self.fixturenames = fixtureinfo.names_closure
+
+ #: class object where the test function is defined in or ``None``.
+ self.cls = cls
+
+ self._calls = []
+ self._ids = set()
+ self._arg2fixturedefs = fixtureinfo.name2fixturedefs
+
+ def parametrize(self, argnames, argvalues, indirect=False, ids=None,
+ scope=None):
+ """ Add new invocations to the underlying test function using the list
+ of argvalues for the given argnames. Parametrization is performed
+ during the collection phase. If you need to setup expensive resources
+ see about setting indirect to do it rather at test setup time.
+
+ :arg argnames: a comma-separated string denoting one or more argument
+ names, or a list/tuple of argument strings.
+
+ :arg argvalues: The list of argvalues determines how often a
+ test is invoked with different argument values. If only one
+ argname was specified argvalues is a list of values. If N
+ argnames were specified, argvalues must be a list of N-tuples,
+ where each tuple-element specifies a value for its respective
+ argname.
+
+ :arg indirect: The list of argnames or boolean. A list of arguments'
+ names (subset of argnames). If True the list contains all names from
+ the argnames. Each argvalue corresponding to an argname in this list will
+ be passed as request.param to its respective argname fixture
+ function so that it can perform more expensive setups during the
+ setup phase of a test rather than at collection time.
+
+ :arg ids: list of string ids, or a callable.
+ If strings, each is corresponding to the argvalues so that they are
+ part of the test id. If None is given as id of specific test, the
+ automatically generated id for that argument will be used.
+ If callable, it should take one argument (a single argvalue) and return
+ a string or return None. If None, the automatically generated id for that
+ argument will be used.
+ If no ids are provided they will be generated automatically from
+ the argvalues.
+
+ :arg scope: if specified it denotes the scope of the parameters.
+ The scope is used for grouping tests by parameter instances.
+ It will also override any fixture-function defined scope, allowing
+ to set a dynamic scope using test context or configuration.
+ """
+ from _pytest.fixtures import scope2index
+ from _pytest.mark import ParameterSet
+ from py.io import saferepr
+ argnames, parameters = ParameterSet._for_parameterize(
+ argnames, argvalues, self.function)
+ del argvalues
+
+ if scope is None:
+ scope = _find_parametrized_scope(argnames, self._arg2fixturedefs, indirect)
+
+ scopenum = scope2index(scope, descr='call to {0}'.format(self.parametrize))
+ valtypes = {}
+ for arg in argnames:
+ if arg not in self.fixturenames:
+ if isinstance(indirect, (tuple, list)):
+ name = 'fixture' if arg in indirect else 'argument'
+ else:
+ name = 'fixture' if indirect else 'argument'
+ raise ValueError(
+ "%r uses no %s %r" % (
+ self.function, name, arg))
+
+ if indirect is True:
+ valtypes = dict.fromkeys(argnames, "params")
+ elif indirect is False:
+ valtypes = dict.fromkeys(argnames, "funcargs")
+ elif isinstance(indirect, (tuple, list)):
+ valtypes = dict.fromkeys(argnames, "funcargs")
+ for arg in indirect:
+ if arg not in argnames:
+ raise ValueError("indirect given to %r: fixture %r doesn't exist" % (
+ self.function, arg))
+ valtypes[arg] = "params"
+ idfn = None
+ if callable(ids):
+ idfn = ids
+ ids = None
+ if ids:
+ if len(ids) != len(parameters):
+ raise ValueError('%d tests specified with %d ids' % (
+ len(parameters), len(ids)))
+ for id_value in ids:
+ if id_value is not None and not isinstance(id_value, six.string_types):
+ msg = 'ids must be list of strings, found: %s (type: %s)'
+ raise ValueError(msg % (saferepr(id_value), type(id_value).__name__))
+ ids = idmaker(argnames, parameters, idfn, ids, self.config)
+ newcalls = []
+ for callspec in self._calls or [CallSpec2(self)]:
+ elements = zip(ids, parameters, count())
+ for a_id, param, param_index in elements:
+ if len(param.values) != len(argnames):
+ raise ValueError(
+ 'In "parametrize" the number of values ({0}) must be '
+ 'equal to the number of names ({1})'.format(
+ param.values, argnames))
+ newcallspec = callspec.copy(self)
+ newcallspec.setmulti2(valtypes, argnames, param.values, a_id,
+ param.marks, scopenum, param_index)
+ newcalls.append(newcallspec)
+ self._calls = newcalls
+
+ def addcall(self, funcargs=None, id=NOTSET, param=NOTSET):
+ """ Add a new call to the underlying test function during the collection phase of a test run.
+
+ .. deprecated:: 3.3
+
+ Use :meth:`parametrize` instead.
+
+ Note that request.addcall() is called during the test collection phase prior and
+ independently to actual test execution. You should only use addcall()
+ if you need to specify multiple arguments of a test function.
+
+ :arg funcargs: argument keyword dictionary used when invoking
+ the test function.
+
+ :arg id: used for reporting and identification purposes. If you
+ don't supply an `id` an automatic unique id will be generated.
+
+ :arg param: a parameter which will be exposed to a later fixture function
+ invocation through the ``request.param`` attribute.
+ """
+ if self.config:
+ self.config.warn('C1', message=deprecated.METAFUNC_ADD_CALL, fslocation=None)
+ assert funcargs is None or isinstance(funcargs, dict)
+ if funcargs is not None:
+ for name in funcargs:
+ if name not in self.fixturenames:
+ fail("funcarg %r not used in this function." % name)
+ else:
+ funcargs = {}
+ if id is None:
+ raise ValueError("id=None not allowed")
+ if id is NOTSET:
+ id = len(self._calls)
+ id = str(id)
+ if id in self._ids:
+ raise ValueError("duplicate id %r" % id)
+ self._ids.add(id)
+
+ cs = CallSpec2(self)
+ cs.setall(funcargs, id, param)
+ self._calls.append(cs)
+
+
+def _find_parametrized_scope(argnames, arg2fixturedefs, indirect):
+ """Find the most appropriate scope for a parametrized call based on its arguments.
+
+ When there's at least one direct argument, always use "function" scope.
+
+ When a test function is parametrized and all its arguments are indirect
+ (e.g. fixtures), return the most narrow scope based on the fixtures used.
+
+ Related to issue #1832, based on code posted by @Kingdread.
+ """
+ from _pytest.fixtures import scopes
+ indirect_as_list = isinstance(indirect, (list, tuple))
+ all_arguments_are_fixtures = indirect is True or \
+ indirect_as_list and len(indirect) == argnames
+ if all_arguments_are_fixtures:
+ fixturedefs = arg2fixturedefs or {}
+ used_scopes = [fixturedef[0].scope for name, fixturedef in fixturedefs.items()]
+ if used_scopes:
+ # Takes the most narrow scope from used fixtures
+ for scope in reversed(scopes):
+ if scope in used_scopes:
+ return scope
+
+ return 'function'
+
+
+def _idval(val, argname, idx, idfn, config=None):
+ if idfn:
+ s = None
+ try:
+ s = idfn(val)
+ except Exception:
+ # See issue https://github.com/pytest-dev/pytest/issues/2169
+ import warnings
+ msg = "Raised while trying to determine id of parameter %s at position %d." % (argname, idx)
+ msg += '\nUpdate your code as this will raise an error in pytest-4.0.'
+ warnings.warn(msg, DeprecationWarning)
+ if s:
+ return ascii_escaped(s)
+
+ if config:
+ hook_id = config.hook.pytest_make_parametrize_id(
+ config=config, val=val, argname=argname)
+ if hook_id:
+ return hook_id
+
+ if isinstance(val, STRING_TYPES):
+ return ascii_escaped(val)
+ elif isinstance(val, (float, int, bool, NoneType)):
+ return str(val)
+ elif isinstance(val, REGEX_TYPE):
+ return ascii_escaped(val.pattern)
+ elif enum is not None and isinstance(val, enum.Enum):
+ return str(val)
+ elif isclass(val) and hasattr(val, '__name__'):
+ return val.__name__
+ return str(argname) + str(idx)
+
+
+def _idvalset(idx, parameterset, argnames, idfn, ids, config=None):
+ if parameterset.id is not None:
+ return parameterset.id
+ if ids is None or (idx >= len(ids) or ids[idx] is None):
+ this_id = [_idval(val, argname, idx, idfn, config)
+ for val, argname in zip(parameterset.values, argnames)]
+ return "-".join(this_id)
+ else:
+ return ascii_escaped(ids[idx])
+
+
+def idmaker(argnames, parametersets, idfn=None, ids=None, config=None):
+ ids = [_idvalset(valindex, parameterset, argnames, idfn, ids, config)
+ for valindex, parameterset in enumerate(parametersets)]
+ if len(set(ids)) != len(ids):
+ # The ids are not unique
+ duplicates = [testid for testid in ids if ids.count(testid) > 1]
+ counters = collections.defaultdict(lambda: 0)
+ for index, testid in enumerate(ids):
+ if testid in duplicates:
+ ids[index] = testid + str(counters[testid])
+ counters[testid] += 1
+ return ids
+
+
+def show_fixtures_per_test(config):
+ from _pytest.main import wrap_session
+ return wrap_session(config, _show_fixtures_per_test)
+
+
+def _show_fixtures_per_test(config, session):
+ import _pytest.config
+ session.perform_collect()
+ curdir = py.path.local()
+ tw = _pytest.config.create_terminal_writer(config)
+ verbose = config.getvalue("verbose")
+
+ def get_best_relpath(func):
+ loc = getlocation(func, curdir)
+ return curdir.bestrelpath(loc)
+
+ def write_fixture(fixture_def):
+ argname = fixture_def.argname
+ if verbose <= 0 and argname.startswith("_"):
+ return
+ if verbose > 0:
+ bestrel = get_best_relpath(fixture_def.func)
+ funcargspec = "{0} -- {1}".format(argname, bestrel)
+ else:
+ funcargspec = argname
+ tw.line(funcargspec, green=True)
+ fixture_doc = fixture_def.func.__doc__
+ if fixture_doc:
+ write_docstring(tw, fixture_doc)
+ else:
+ tw.line(' no docstring available', red=True)
+
+ def write_item(item):
+ try:
+ info = item._fixtureinfo
+ except AttributeError:
+ # doctests items have no _fixtureinfo attribute
+ return
+ if not info.name2fixturedefs:
+ # this test item does not use any fixtures
+ return
+ tw.line()
+ tw.sep('-', 'fixtures used by {0}'.format(item.name))
+ tw.sep('-', '({0})'.format(get_best_relpath(item.function)))
+ # dict key not used in loop but needed for sorting
+ for _, fixturedefs in sorted(info.name2fixturedefs.items()):
+ assert fixturedefs is not None
+ if not fixturedefs:
+ continue
+ # last item is expected to be the one used by the test item
+ write_fixture(fixturedefs[-1])
+
+ for session_item in session.items:
+ write_item(session_item)
+
+
+def showfixtures(config):
+ from _pytest.main import wrap_session
+ return wrap_session(config, _showfixtures_main)
+
+
+def _showfixtures_main(config, session):
+ import _pytest.config
+ session.perform_collect()
+ curdir = py.path.local()
+ tw = _pytest.config.create_terminal_writer(config)
+ verbose = config.getvalue("verbose")
+
+ fm = session._fixturemanager
+
+ available = []
+ seen = set()
+
+ for argname, fixturedefs in fm._arg2fixturedefs.items():
+ assert fixturedefs is not None
+ if not fixturedefs:
+ continue
+ for fixturedef in fixturedefs:
+ loc = getlocation(fixturedef.func, curdir)
+ if (fixturedef.argname, loc) in seen:
+ continue
+ seen.add((fixturedef.argname, loc))
+ available.append((len(fixturedef.baseid),
+ fixturedef.func.__module__,
+ curdir.bestrelpath(loc),
+ fixturedef.argname, fixturedef))
+
+ available.sort()
+ currentmodule = None
+ for baseid, module, bestrel, argname, fixturedef in available:
+ if currentmodule != module:
+ if not module.startswith("_pytest."):
+ tw.line()
+ tw.sep("-", "fixtures defined from %s" % (module,))
+ currentmodule = module
+ if verbose <= 0 and argname[0] == "_":
+ continue
+ if verbose > 0:
+ funcargspec = "%s -- %s" % (argname, bestrel,)
+ else:
+ funcargspec = argname
+ tw.line(funcargspec, green=True)
+ loc = getlocation(fixturedef.func, curdir)
+ doc = fixturedef.func.__doc__ or ""
+ if doc:
+ write_docstring(tw, doc)
+ else:
+ tw.line(" %s: no docstring available" % (loc,),
+ red=True)
+
+
+def write_docstring(tw, doc):
+ INDENT = " "
+ doc = doc.rstrip()
+ if "\n" in doc:
+ firstline, rest = doc.split("\n", 1)
+ else:
+ firstline, rest = doc, ""
+
+ if firstline.strip():
+ tw.line(INDENT + firstline.strip())
+
+ if rest:
+ for line in dedent(rest).split("\n"):
+ tw.write(INDENT + line + "\n")
+
+
+class Function(FunctionMixin, main.Item, fixtures.FuncargnamesCompatAttr):
+ """ a Function Item is responsible for setting up and executing a
+ Python test function.
+ """
+ _genid = None
+
+ def __init__(self, name, parent, args=None, config=None,
+ callspec=None, callobj=NOTSET, keywords=None, session=None,
+ fixtureinfo=None, originalname=None):
+ super(Function, self).__init__(name, parent, config=config,
+ session=session)
+ self._args = args
+ if callobj is not NOTSET:
+ self.obj = callobj
+
+ self.keywords.update(self.obj.__dict__)
+ if callspec:
+ self.callspec = callspec
+ # this is total hostile and a mess
+ # keywords are broken by design by now
+ # this will be redeemed later
+ for mark in callspec.marks:
+ # feel free to cry, this was broken for years before
+ # and keywords cant fix it per design
+ self.keywords[mark.name] = mark
+ if keywords:
+ self.keywords.update(keywords)
+
+ if fixtureinfo is None:
+ fixtureinfo = self.session._fixturemanager.getfixtureinfo(
+ self.parent, self.obj, self.cls,
+ funcargs=not self._isyieldedfunction())
+ self._fixtureinfo = fixtureinfo
+ self.fixturenames = fixtureinfo.names_closure
+ self._initrequest()
+
+ #: original function name, without any decorations (for example
+ #: parametrization adds a ``"[...]"`` suffix to function names).
+ #:
+ #: .. versionadded:: 3.0
+ self.originalname = originalname
+
+ def _initrequest(self):
+ self.funcargs = {}
+ if self._isyieldedfunction():
+ assert not hasattr(self, "callspec"), (
+ "yielded functions (deprecated) cannot have funcargs")
+ else:
+ if hasattr(self, "callspec"):
+ callspec = self.callspec
+ assert not callspec.funcargs
+ self._genid = callspec.id
+ if hasattr(callspec, "param"):
+ self.param = callspec.param
+ self._request = fixtures.FixtureRequest(self)
+
+ @property
+ def function(self):
+ "underlying python 'function' object"
+ return getattr(self.obj, 'im_func', self.obj)
+
+ def _getobj(self):
+ name = self.name
+ i = name.find("[") # parametrization
+ if i != -1:
+ name = name[:i]
+ return getattr(self.parent.obj, name)
+
+ @property
+ def _pyfuncitem(self):
+ "(compatonly) for code expecting pytest-2.2 style request objects"
+ return self
+
+ def _isyieldedfunction(self):
+ return getattr(self, "_args", None) is not None
+
+ def runtest(self):
+ """ execute the underlying test function. """
+ self.ihook.pytest_pyfunc_call(pyfuncitem=self)
+
+ def setup(self):
+ super(Function, self).setup()
+ fixtures.fillfixtures(self)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/python_api.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/python_api.py
new file mode 100644
index 00000000000..81960295b38
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/python_api.py
@@ -0,0 +1,619 @@
+import math
+import sys
+
+import py
+from six.moves import zip
+
+from _pytest.compat import isclass
+from _pytest.outcomes import fail
+import _pytest._code
+
+
+def _cmp_raises_type_error(self, other):
+ """__cmp__ implementation which raises TypeError. Used
+ by Approx base classes to implement only == and != and raise a
+ TypeError for other comparisons.
+
+ Needed in Python 2 only, Python 3 all it takes is not implementing the
+ other operators at all.
+ """
+ __tracebackhide__ = True
+ raise TypeError('Comparison operators other than == and != not supported by approx objects')
+
+
+# builtin pytest.approx helper
+
+
+class ApproxBase(object):
+ """
+ Provide shared utilities for making approximate comparisons between numbers
+ or sequences of numbers.
+ """
+
+ def __init__(self, expected, rel=None, abs=None, nan_ok=False):
+ self.expected = expected
+ self.abs = abs
+ self.rel = rel
+ self.nan_ok = nan_ok
+
+ def __repr__(self):
+ raise NotImplementedError
+
+ def __eq__(self, actual):
+ return all(
+ a == self._approx_scalar(x)
+ for a, x in self._yield_comparisons(actual))
+
+ __hash__ = None
+
+ def __ne__(self, actual):
+ return not (actual == self)
+
+ if sys.version_info[0] == 2:
+ __cmp__ = _cmp_raises_type_error
+
+ def _approx_scalar(self, x):
+ return ApproxScalar(x, rel=self.rel, abs=self.abs, nan_ok=self.nan_ok)
+
+ def _yield_comparisons(self, actual):
+ """
+ Yield all the pairs of numbers to be compared. This is used to
+ implement the `__eq__` method.
+ """
+ raise NotImplementedError
+
+
+class ApproxNumpy(ApproxBase):
+ """
+ Perform approximate comparisons for numpy arrays.
+ """
+
+ # Tell numpy to use our `__eq__` operator instead of its.
+ __array_priority__ = 100
+
+ def __repr__(self):
+ # It might be nice to rewrite this function to account for the
+ # shape of the array...
+ return "approx({0!r})".format(list(
+ self._approx_scalar(x) for x in self.expected))
+
+ if sys.version_info[0] == 2:
+ __cmp__ = _cmp_raises_type_error
+
+ def __eq__(self, actual):
+ import numpy as np
+
+ try:
+ actual = np.asarray(actual)
+ except: # noqa
+ raise TypeError("cannot compare '{0}' to numpy.ndarray".format(actual))
+
+ if actual.shape != self.expected.shape:
+ return False
+
+ return ApproxBase.__eq__(self, actual)
+
+ def _yield_comparisons(self, actual):
+ import numpy as np
+
+ # We can be sure that `actual` is a numpy array, because it's
+ # casted in `__eq__` before being passed to `ApproxBase.__eq__`,
+ # which is the only method that calls this one.
+ for i in np.ndindex(self.expected.shape):
+ yield actual[i], self.expected[i]
+
+
+class ApproxMapping(ApproxBase):
+ """
+ Perform approximate comparisons for mappings where the values are numbers
+ (the keys can be anything).
+ """
+
+ def __repr__(self):
+ return "approx({0!r})".format(dict(
+ (k, self._approx_scalar(v))
+ for k, v in self.expected.items()))
+
+ def __eq__(self, actual):
+ if set(actual.keys()) != set(self.expected.keys()):
+ return False
+
+ return ApproxBase.__eq__(self, actual)
+
+ def _yield_comparisons(self, actual):
+ for k in self.expected.keys():
+ yield actual[k], self.expected[k]
+
+
+class ApproxSequence(ApproxBase):
+ """
+ Perform approximate comparisons for sequences of numbers.
+ """
+
+ # Tell numpy to use our `__eq__` operator instead of its.
+ __array_priority__ = 100
+
+ def __repr__(self):
+ seq_type = type(self.expected)
+ if seq_type not in (tuple, list, set):
+ seq_type = list
+ return "approx({0!r})".format(seq_type(
+ self._approx_scalar(x) for x in self.expected))
+
+ def __eq__(self, actual):
+ if len(actual) != len(self.expected):
+ return False
+ return ApproxBase.__eq__(self, actual)
+
+ def _yield_comparisons(self, actual):
+ return zip(actual, self.expected)
+
+
+class ApproxScalar(ApproxBase):
+ """
+ Perform approximate comparisons for single numbers only.
+ """
+
+ def __repr__(self):
+ """
+ Return a string communicating both the expected value and the tolerance
+ for the comparison being made, e.g. '1.0 +- 1e-6'. Use the unicode
+ plus/minus symbol if this is python3 (it's too hard to get right for
+ python2).
+ """
+ if isinstance(self.expected, complex):
+ return str(self.expected)
+
+ # Infinities aren't compared using tolerances, so don't show a
+ # tolerance.
+ if math.isinf(self.expected):
+ return str(self.expected)
+
+ # If a sensible tolerance can't be calculated, self.tolerance will
+ # raise a ValueError. In this case, display '???'.
+ try:
+ vetted_tolerance = '{:.1e}'.format(self.tolerance)
+ except ValueError:
+ vetted_tolerance = '???'
+
+ if sys.version_info[0] == 2:
+ return '{0} +- {1}'.format(self.expected, vetted_tolerance)
+ else:
+ return u'{0} \u00b1 {1}'.format(self.expected, vetted_tolerance)
+
+ def __eq__(self, actual):
+ """
+ Return true if the given value is equal to the expected value within
+ the pre-specified tolerance.
+ """
+
+ # Short-circuit exact equality.
+ if actual == self.expected:
+ return True
+
+ # Allow the user to control whether NaNs are considered equal to each
+ # other or not. The abs() calls are for compatibility with complex
+ # numbers.
+ if math.isnan(abs(self.expected)):
+ return self.nan_ok and math.isnan(abs(actual))
+
+ # Infinity shouldn't be approximately equal to anything but itself, but
+ # if there's a relative tolerance, it will be infinite and infinity
+ # will seem approximately equal to everything. The equal-to-itself
+ # case would have been short circuited above, so here we can just
+ # return false if the expected value is infinite. The abs() call is
+ # for compatibility with complex numbers.
+ if math.isinf(abs(self.expected)):
+ return False
+
+ # Return true if the two numbers are within the tolerance.
+ return abs(self.expected - actual) <= self.tolerance
+
+ __hash__ = None
+
+ @property
+ def tolerance(self):
+ """
+ Return the tolerance for the comparison. This could be either an
+ absolute tolerance or a relative tolerance, depending on what the user
+ specified or which would be larger.
+ """
+ def set_default(x, default):
+ return x if x is not None else default
+
+ # Figure out what the absolute tolerance should be. ``self.abs`` is
+ # either None or a value specified by the user.
+ absolute_tolerance = set_default(self.abs, 1e-12)
+
+ if absolute_tolerance < 0:
+ raise ValueError("absolute tolerance can't be negative: {}".format(absolute_tolerance))
+ if math.isnan(absolute_tolerance):
+ raise ValueError("absolute tolerance can't be NaN.")
+
+ # If the user specified an absolute tolerance but not a relative one,
+ # just return the absolute tolerance.
+ if self.rel is None:
+ if self.abs is not None:
+ return absolute_tolerance
+
+ # Figure out what the relative tolerance should be. ``self.rel`` is
+ # either None or a value specified by the user. This is done after
+ # we've made sure the user didn't ask for an absolute tolerance only,
+ # because we don't want to raise errors about the relative tolerance if
+ # we aren't even going to use it.
+ relative_tolerance = set_default(self.rel, 1e-6) * abs(self.expected)
+
+ if relative_tolerance < 0:
+ raise ValueError("relative tolerance can't be negative: {}".format(absolute_tolerance))
+ if math.isnan(relative_tolerance):
+ raise ValueError("relative tolerance can't be NaN.")
+
+ # Return the larger of the relative and absolute tolerances.
+ return max(relative_tolerance, absolute_tolerance)
+
+
+def approx(expected, rel=None, abs=None, nan_ok=False):
+ """
+ Assert that two numbers (or two sets of numbers) are equal to each other
+ within some tolerance.
+
+ Due to the `intricacies of floating-point arithmetic`__, numbers that we
+ would intuitively expect to be equal are not always so::
+
+ >>> 0.1 + 0.2 == 0.3
+ False
+
+ __ https://docs.python.org/3/tutorial/floatingpoint.html
+
+ This problem is commonly encountered when writing tests, e.g. when making
+ sure that floating-point values are what you expect them to be. One way to
+ deal with this problem is to assert that two floating-point numbers are
+ equal to within some appropriate tolerance::
+
+ >>> abs((0.1 + 0.2) - 0.3) < 1e-6
+ True
+
+ However, comparisons like this are tedious to write and difficult to
+ understand. Furthermore, absolute comparisons like the one above are
+ usually discouraged because there's no tolerance that works well for all
+ situations. ``1e-6`` is good for numbers around ``1``, but too small for
+ very big numbers and too big for very small ones. It's better to express
+ the tolerance as a fraction of the expected value, but relative comparisons
+ like that are even more difficult to write correctly and concisely.
+
+ The ``approx`` class performs floating-point comparisons using a syntax
+ that's as intuitive as possible::
+
+ >>> from pytest import approx
+ >>> 0.1 + 0.2 == approx(0.3)
+ True
+
+ The same syntax also works for sequences of numbers::
+
+ >>> (0.1 + 0.2, 0.2 + 0.4) == approx((0.3, 0.6))
+ True
+
+ Dictionary *values*::
+
+ >>> {'a': 0.1 + 0.2, 'b': 0.2 + 0.4} == approx({'a': 0.3, 'b': 0.6})
+ True
+
+ And ``numpy`` arrays::
+
+ >>> import numpy as np # doctest: +SKIP
+ >>> np.array([0.1, 0.2]) + np.array([0.2, 0.4]) == approx(np.array([0.3, 0.6])) # doctest: +SKIP
+ True
+
+ By default, ``approx`` considers numbers within a relative tolerance of
+ ``1e-6`` (i.e. one part in a million) of its expected value to be equal.
+ This treatment would lead to surprising results if the expected value was
+ ``0.0``, because nothing but ``0.0`` itself is relatively close to ``0.0``.
+ To handle this case less surprisingly, ``approx`` also considers numbers
+ within an absolute tolerance of ``1e-12`` of its expected value to be
+ equal. Infinity and NaN are special cases. Infinity is only considered
+ equal to itself, regardless of the relative tolerance. NaN is not
+ considered equal to anything by default, but you can make it be equal to
+ itself by setting the ``nan_ok`` argument to True. (This is meant to
+ facilitate comparing arrays that use NaN to mean "no data".)
+
+ Both the relative and absolute tolerances can be changed by passing
+ arguments to the ``approx`` constructor::
+
+ >>> 1.0001 == approx(1)
+ False
+ >>> 1.0001 == approx(1, rel=1e-3)
+ True
+ >>> 1.0001 == approx(1, abs=1e-3)
+ True
+
+ If you specify ``abs`` but not ``rel``, the comparison will not consider
+ the relative tolerance at all. In other words, two numbers that are within
+ the default relative tolerance of ``1e-6`` will still be considered unequal
+ if they exceed the specified absolute tolerance. If you specify both
+ ``abs`` and ``rel``, the numbers will be considered equal if either
+ tolerance is met::
+
+ >>> 1 + 1e-8 == approx(1)
+ True
+ >>> 1 + 1e-8 == approx(1, abs=1e-12)
+ False
+ >>> 1 + 1e-8 == approx(1, rel=1e-6, abs=1e-12)
+ True
+
+ If you're thinking about using ``approx``, then you might want to know how
+ it compares to other good ways of comparing floating-point numbers. All of
+ these algorithms are based on relative and absolute tolerances and should
+ agree for the most part, but they do have meaningful differences:
+
+ - ``math.isclose(a, b, rel_tol=1e-9, abs_tol=0.0)``: True if the relative
+ tolerance is met w.r.t. either ``a`` or ``b`` or if the absolute
+ tolerance is met. Because the relative tolerance is calculated w.r.t.
+ both ``a`` and ``b``, this test is symmetric (i.e. neither ``a`` nor
+ ``b`` is a "reference value"). You have to specify an absolute tolerance
+ if you want to compare to ``0.0`` because there is no tolerance by
+ default. Only available in python>=3.5. `More information...`__
+
+ __ https://docs.python.org/3/library/math.html#math.isclose
+
+ - ``numpy.isclose(a, b, rtol=1e-5, atol=1e-8)``: True if the difference
+ between ``a`` and ``b`` is less that the sum of the relative tolerance
+ w.r.t. ``b`` and the absolute tolerance. Because the relative tolerance
+ is only calculated w.r.t. ``b``, this test is asymmetric and you can
+ think of ``b`` as the reference value. Support for comparing sequences
+ is provided by ``numpy.allclose``. `More information...`__
+
+ __ http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.isclose.html
+
+ - ``unittest.TestCase.assertAlmostEqual(a, b)``: True if ``a`` and ``b``
+ are within an absolute tolerance of ``1e-7``. No relative tolerance is
+ considered and the absolute tolerance cannot be changed, so this function
+ is not appropriate for very large or very small numbers. Also, it's only
+ available in subclasses of ``unittest.TestCase`` and it's ugly because it
+ doesn't follow PEP8. `More information...`__
+
+ __ https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertAlmostEqual
+
+ - ``a == pytest.approx(b, rel=1e-6, abs=1e-12)``: True if the relative
+ tolerance is met w.r.t. ``b`` or if the absolute tolerance is met.
+ Because the relative tolerance is only calculated w.r.t. ``b``, this test
+ is asymmetric and you can think of ``b`` as the reference value. In the
+ special case that you explicitly specify an absolute tolerance but not a
+ relative tolerance, only the absolute tolerance is considered.
+
+ .. warning::
+
+ .. versionchanged:: 3.2
+
+ In order to avoid inconsistent behavior, ``TypeError`` is
+ raised for ``>``, ``>=``, ``<`` and ``<=`` comparisons.
+ The example below illustrates the problem::
+
+ assert approx(0.1) > 0.1 + 1e-10 # calls approx(0.1).__gt__(0.1 + 1e-10)
+ assert 0.1 + 1e-10 > approx(0.1) # calls approx(0.1).__lt__(0.1 + 1e-10)
+
+ In the second example one expects ``approx(0.1).__le__(0.1 + 1e-10)``
+ to be called. But instead, ``approx(0.1).__lt__(0.1 + 1e-10)`` is used to
+ comparison. This is because the call hierarchy of rich comparisons
+ follows a fixed behavior. `More information...`__
+
+ __ https://docs.python.org/3/reference/datamodel.html#object.__ge__
+ """
+
+ from collections import Mapping, Sequence
+ from _pytest.compat import STRING_TYPES as String
+
+ # Delegate the comparison to a class that knows how to deal with the type
+ # of the expected value (e.g. int, float, list, dict, numpy.array, etc).
+ #
+ # This architecture is really driven by the need to support numpy arrays.
+ # The only way to override `==` for arrays without requiring that approx be
+ # the left operand is to inherit the approx object from `numpy.ndarray`.
+ # But that can't be a general solution, because it requires (1) numpy to be
+ # installed and (2) the expected value to be a numpy array. So the general
+ # solution is to delegate each type of expected value to a different class.
+ #
+ # This has the advantage that it made it easy to support mapping types
+ # (i.e. dict). The old code accepted mapping types, but would only compare
+ # their keys, which is probably not what most people would expect.
+
+ if _is_numpy_array(expected):
+ cls = ApproxNumpy
+ elif isinstance(expected, Mapping):
+ cls = ApproxMapping
+ elif isinstance(expected, Sequence) and not isinstance(expected, String):
+ cls = ApproxSequence
+ else:
+ cls = ApproxScalar
+
+ return cls(expected, rel, abs, nan_ok)
+
+
+def _is_numpy_array(obj):
+ """
+ Return true if the given object is a numpy array. Make a special effort to
+ avoid importing numpy unless it's really necessary.
+ """
+ import inspect
+
+ for cls in inspect.getmro(type(obj)):
+ if cls.__module__ == 'numpy':
+ try:
+ import numpy as np
+ return isinstance(obj, np.ndarray)
+ except ImportError:
+ pass
+
+ return False
+
+
+# builtin pytest.raises helper
+
+def raises(expected_exception, *args, **kwargs):
+ """
+ Assert that a code block/function call raises ``expected_exception``
+ and raise a failure exception otherwise.
+
+ This helper produces a ``ExceptionInfo()`` object (see below).
+
+ You may use this function as a context manager::
+
+ >>> with raises(ZeroDivisionError):
+ ... 1/0
+
+ .. versionchanged:: 2.10
+
+ In the context manager form you may use the keyword argument
+ ``message`` to specify a custom failure message::
+
+ >>> with raises(ZeroDivisionError, message="Expecting ZeroDivisionError"):
+ ... pass
+ Traceback (most recent call last):
+ ...
+ Failed: Expecting ZeroDivisionError
+
+ .. note::
+
+ When using ``pytest.raises`` as a context manager, it's worthwhile to
+ note that normal context manager rules apply and that the exception
+ raised *must* be the final line in the scope of the context manager.
+ Lines of code after that, within the scope of the context manager will
+ not be executed. For example::
+
+ >>> value = 15
+ >>> with raises(ValueError) as exc_info:
+ ... if value > 10:
+ ... raise ValueError("value must be <= 10")
+ ... assert exc_info.type == ValueError # this will not execute
+
+ Instead, the following approach must be taken (note the difference in
+ scope)::
+
+ >>> with raises(ValueError) as exc_info:
+ ... if value > 10:
+ ... raise ValueError("value must be <= 10")
+ ...
+ >>> assert exc_info.type == ValueError
+
+
+ Since version ``3.1`` you can use the keyword argument ``match`` to assert that the
+ exception matches a text or regex::
+
+ >>> with raises(ValueError, match='must be 0 or None'):
+ ... raise ValueError("value must be 0 or None")
+
+ >>> with raises(ValueError, match=r'must be \d+$'):
+ ... raise ValueError("value must be 42")
+
+ **Legacy forms**
+
+ The forms below are fully supported but are discouraged for new code because the
+ context manager form is regarded as more readable and less error-prone.
+
+ It is possible to specify a callable by passing a to-be-called lambda::
+
+ >>> raises(ZeroDivisionError, lambda: 1/0)
+ <ExceptionInfo ...>
+
+ or you can specify an arbitrary callable with arguments::
+
+ >>> def f(x): return 1/x
+ ...
+ >>> raises(ZeroDivisionError, f, 0)
+ <ExceptionInfo ...>
+ >>> raises(ZeroDivisionError, f, x=0)
+ <ExceptionInfo ...>
+
+ It is also possible to pass a string to be evaluated at runtime::
+
+ >>> raises(ZeroDivisionError, "f(0)")
+ <ExceptionInfo ...>
+
+ The string will be evaluated using the same ``locals()`` and ``globals()``
+ at the moment of the ``raises`` call.
+
+ .. autoclass:: _pytest._code.ExceptionInfo
+ :members:
+
+ .. note::
+ Similar to caught exception objects in Python, explicitly clearing
+ local references to returned ``ExceptionInfo`` objects can
+ help the Python interpreter speed up its garbage collection.
+
+ Clearing those references breaks a reference cycle
+ (``ExceptionInfo`` --> caught exception --> frame stack raising
+ the exception --> current frame stack --> local variables -->
+ ``ExceptionInfo``) which makes Python keep all objects referenced
+ from that cycle (including all local variables in the current
+ frame) alive until the next cyclic garbage collection run. See the
+ official Python ``try`` statement documentation for more detailed
+ information.
+
+ """
+ __tracebackhide__ = True
+ msg = ("exceptions must be old-style classes or"
+ " derived from BaseException, not %s")
+ if isinstance(expected_exception, tuple):
+ for exc in expected_exception:
+ if not isclass(exc):
+ raise TypeError(msg % type(exc))
+ elif not isclass(expected_exception):
+ raise TypeError(msg % type(expected_exception))
+
+ message = "DID NOT RAISE {0}".format(expected_exception)
+ match_expr = None
+
+ if not args:
+ if "message" in kwargs:
+ message = kwargs.pop("message")
+ if "match" in kwargs:
+ match_expr = kwargs.pop("match")
+ message += " matching '{0}'".format(match_expr)
+ return RaisesContext(expected_exception, message, match_expr)
+ elif isinstance(args[0], str):
+ code, = args
+ assert isinstance(code, str)
+ frame = sys._getframe(1)
+ loc = frame.f_locals.copy()
+ loc.update(kwargs)
+ # print "raises frame scope: %r" % frame.f_locals
+ try:
+ code = _pytest._code.Source(code).compile()
+ py.builtin.exec_(code, frame.f_globals, loc)
+ # XXX didn'T mean f_globals == f_locals something special?
+ # this is destroyed here ...
+ except expected_exception:
+ return _pytest._code.ExceptionInfo()
+ else:
+ func = args[0]
+ try:
+ func(*args[1:], **kwargs)
+ except expected_exception:
+ return _pytest._code.ExceptionInfo()
+ fail(message)
+
+
+raises.Exception = fail.Exception
+
+
+class RaisesContext(object):
+ def __init__(self, expected_exception, message, match_expr):
+ self.expected_exception = expected_exception
+ self.message = message
+ self.match_expr = match_expr
+ self.excinfo = None
+
+ def __enter__(self):
+ self.excinfo = object.__new__(_pytest._code.ExceptionInfo)
+ return self.excinfo
+
+ def __exit__(self, *tp):
+ __tracebackhide__ = True
+ if tp[0] is None:
+ fail(self.message)
+ self.excinfo.__init__(tp)
+ suppress_exception = issubclass(self.excinfo.type, self.expected_exception)
+ if sys.version_info[0] == 2 and suppress_exception:
+ sys.exc_clear()
+ if self.match_expr:
+ self.excinfo.match(self.match_expr)
+ return suppress_exception
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/recwarn.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/recwarn.py
new file mode 100644
index 00000000000..4fceb10a7f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/recwarn.py
@@ -0,0 +1,236 @@
+""" recording warnings during test function execution. """
+from __future__ import absolute_import, division, print_function
+
+import inspect
+
+import _pytest._code
+import py
+import sys
+import warnings
+
+import re
+
+from _pytest.fixtures import yield_fixture
+from _pytest.outcomes import fail
+
+
+@yield_fixture
+def recwarn():
+ """Return a WarningsRecorder instance that provides these methods:
+
+ * ``pop(category=None)``: return last warning matching the category.
+ * ``clear()``: clear list of warnings
+
+ See http://docs.python.org/library/warnings.html for information
+ on warning categories.
+ """
+ wrec = WarningsRecorder()
+ with wrec:
+ warnings.simplefilter('default')
+ yield wrec
+
+
+def deprecated_call(func=None, *args, **kwargs):
+ """context manager that can be used to ensure a block of code triggers a
+ ``DeprecationWarning`` or ``PendingDeprecationWarning``::
+
+ >>> import warnings
+ >>> def api_call_v2():
+ ... warnings.warn('use v3 of this api', DeprecationWarning)
+ ... return 200
+
+ >>> with deprecated_call():
+ ... assert api_call_v2() == 200
+
+ ``deprecated_call`` can also be used by passing a function and ``*args`` and ``*kwargs``,
+ in which case it will ensure calling ``func(*args, **kwargs)`` produces one of the warnings
+ types above.
+ """
+ if not func:
+ return _DeprecatedCallContext()
+ else:
+ __tracebackhide__ = True
+ with _DeprecatedCallContext():
+ return func(*args, **kwargs)
+
+
+class _DeprecatedCallContext(object):
+ """Implements the logic to capture deprecation warnings as a context manager."""
+
+ def __enter__(self):
+ self._captured_categories = []
+ self._old_warn = warnings.warn
+ self._old_warn_explicit = warnings.warn_explicit
+ warnings.warn_explicit = self._warn_explicit
+ warnings.warn = self._warn
+
+ def _warn_explicit(self, message, category, *args, **kwargs):
+ self._captured_categories.append(category)
+
+ def _warn(self, message, category=None, *args, **kwargs):
+ if isinstance(message, Warning):
+ self._captured_categories.append(message.__class__)
+ else:
+ self._captured_categories.append(category)
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ warnings.warn_explicit = self._old_warn_explicit
+ warnings.warn = self._old_warn
+
+ if exc_type is None:
+ deprecation_categories = (DeprecationWarning, PendingDeprecationWarning)
+ if not any(issubclass(c, deprecation_categories) for c in self._captured_categories):
+ __tracebackhide__ = True
+ msg = "Did not produce DeprecationWarning or PendingDeprecationWarning"
+ raise AssertionError(msg)
+
+
+def warns(expected_warning, *args, **kwargs):
+ """Assert that code raises a particular class of warning.
+
+ Specifically, the input @expected_warning can be a warning class or
+ tuple of warning classes, and the code must return that warning
+ (if a single class) or one of those warnings (if a tuple).
+
+ This helper produces a list of ``warnings.WarningMessage`` objects,
+ one for each warning raised.
+
+ This function can be used as a context manager, or any of the other ways
+ ``pytest.raises`` can be used::
+
+ >>> with warns(RuntimeWarning):
+ ... warnings.warn("my warning", RuntimeWarning)
+
+ In the context manager form you may use the keyword argument ``match`` to assert
+ that the exception matches a text or regex::
+
+ >>> with warns(UserWarning, match='must be 0 or None'):
+ ... warnings.warn("value must be 0 or None", UserWarning)
+
+ >>> with warns(UserWarning, match=r'must be \d+$'):
+ ... warnings.warn("value must be 42", UserWarning)
+
+ >>> with warns(UserWarning, match=r'must be \d+$'):
+ ... warnings.warn("this is not here", UserWarning)
+ Traceback (most recent call last):
+ ...
+ Failed: DID NOT WARN. No warnings of type ...UserWarning... was emitted...
+
+ """
+ match_expr = None
+ if not args:
+ if "match" in kwargs:
+ match_expr = kwargs.pop("match")
+ return WarningsChecker(expected_warning, match_expr=match_expr)
+ elif isinstance(args[0], str):
+ code, = args
+ assert isinstance(code, str)
+ frame = sys._getframe(1)
+ loc = frame.f_locals.copy()
+ loc.update(kwargs)
+
+ with WarningsChecker(expected_warning, match_expr=match_expr):
+ code = _pytest._code.Source(code).compile()
+ py.builtin.exec_(code, frame.f_globals, loc)
+ else:
+ func = args[0]
+ with WarningsChecker(expected_warning, match_expr=match_expr):
+ return func(*args[1:], **kwargs)
+
+
+class WarningsRecorder(warnings.catch_warnings):
+ """A context manager to record raised warnings.
+
+ Adapted from `warnings.catch_warnings`.
+ """
+
+ def __init__(self):
+ super(WarningsRecorder, self).__init__(record=True)
+ self._entered = False
+ self._list = []
+
+ @property
+ def list(self):
+ """The list of recorded warnings."""
+ return self._list
+
+ def __getitem__(self, i):
+ """Get a recorded warning by index."""
+ return self._list[i]
+
+ def __iter__(self):
+ """Iterate through the recorded warnings."""
+ return iter(self._list)
+
+ def __len__(self):
+ """The number of recorded warnings."""
+ return len(self._list)
+
+ def pop(self, cls=Warning):
+ """Pop the first recorded warning, raise exception if not exists."""
+ for i, w in enumerate(self._list):
+ if issubclass(w.category, cls):
+ return self._list.pop(i)
+ __tracebackhide__ = True
+ raise AssertionError("%r not found in warning list" % cls)
+
+ def clear(self):
+ """Clear the list of recorded warnings."""
+ self._list[:] = []
+
+ def __enter__(self):
+ if self._entered:
+ __tracebackhide__ = True
+ raise RuntimeError("Cannot enter %r twice" % self)
+ self._list = super(WarningsRecorder, self).__enter__()
+ warnings.simplefilter('always')
+ return self
+
+ def __exit__(self, *exc_info):
+ if not self._entered:
+ __tracebackhide__ = True
+ raise RuntimeError("Cannot exit %r without entering first" % self)
+ super(WarningsRecorder, self).__exit__(*exc_info)
+
+
+class WarningsChecker(WarningsRecorder):
+ def __init__(self, expected_warning=None, match_expr=None):
+ super(WarningsChecker, self).__init__()
+
+ msg = ("exceptions must be old-style classes or "
+ "derived from Warning, not %s")
+ if isinstance(expected_warning, tuple):
+ for exc in expected_warning:
+ if not inspect.isclass(exc):
+ raise TypeError(msg % type(exc))
+ elif inspect.isclass(expected_warning):
+ expected_warning = (expected_warning,)
+ elif expected_warning is not None:
+ raise TypeError(msg % type(expected_warning))
+
+ self.expected_warning = expected_warning
+ self.match_expr = match_expr
+
+ def __exit__(self, *exc_info):
+ super(WarningsChecker, self).__exit__(*exc_info)
+
+ # only check if we're not currently handling an exception
+ if all(a is None for a in exc_info):
+ if self.expected_warning is not None:
+ if not any(issubclass(r.category, self.expected_warning)
+ for r in self):
+ __tracebackhide__ = True
+ fail("DID NOT WARN. No warnings of type {0} was emitted. "
+ "The list of emitted warnings is: {1}.".format(
+ self.expected_warning,
+ [each.message for each in self]))
+ elif self.match_expr is not None:
+ for r in self:
+ if issubclass(r.category, self.expected_warning):
+ if re.compile(self.match_expr).search(str(r.message)):
+ break
+ else:
+ fail("DID NOT WARN. No warnings of type {0} matching"
+ " ('{1}') was emitted. The list of emitted warnings"
+ " is: {2}.".format(self.expected_warning, self.match_expr,
+ [each.message for each in self]))
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/resultlog.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/resultlog.py
new file mode 100644
index 00000000000..9f9c2d1f653
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/resultlog.py
@@ -0,0 +1,113 @@
+""" log machine-parseable test session result information in a plain
+text file.
+"""
+from __future__ import absolute_import, division, print_function
+
+import py
+import os
+
+
+def pytest_addoption(parser):
+ group = parser.getgroup("terminal reporting", "resultlog plugin options")
+ group.addoption('--resultlog', '--result-log', action="store",
+ metavar="path", default=None,
+ help="DEPRECATED path for machine-readable result log.")
+
+
+def pytest_configure(config):
+ resultlog = config.option.resultlog
+ # prevent opening resultlog on slave nodes (xdist)
+ if resultlog and not hasattr(config, 'slaveinput'):
+ dirname = os.path.dirname(os.path.abspath(resultlog))
+ if not os.path.isdir(dirname):
+ os.makedirs(dirname)
+ logfile = open(resultlog, 'w', 1) # line buffered
+ config._resultlog = ResultLog(config, logfile)
+ config.pluginmanager.register(config._resultlog)
+
+ from _pytest.deprecated import RESULT_LOG
+ config.warn('C1', RESULT_LOG)
+
+
+def pytest_unconfigure(config):
+ resultlog = getattr(config, '_resultlog', None)
+ if resultlog:
+ resultlog.logfile.close()
+ del config._resultlog
+ config.pluginmanager.unregister(resultlog)
+
+
+def generic_path(item):
+ chain = item.listchain()
+ gpath = [chain[0].name]
+ fspath = chain[0].fspath
+ fspart = False
+ for node in chain[1:]:
+ newfspath = node.fspath
+ if newfspath == fspath:
+ if fspart:
+ gpath.append(':')
+ fspart = False
+ else:
+ gpath.append('.')
+ else:
+ gpath.append('/')
+ fspart = True
+ name = node.name
+ if name[0] in '([':
+ gpath.pop()
+ gpath.append(name)
+ fspath = newfspath
+ return ''.join(gpath)
+
+
+class ResultLog(object):
+ def __init__(self, config, logfile):
+ self.config = config
+ self.logfile = logfile # preferably line buffered
+
+ def write_log_entry(self, testpath, lettercode, longrepr):
+ print("%s %s" % (lettercode, testpath), file=self.logfile)
+ for line in longrepr.splitlines():
+ print(" %s" % line, file=self.logfile)
+
+ def log_outcome(self, report, lettercode, longrepr):
+ testpath = getattr(report, 'nodeid', None)
+ if testpath is None:
+ testpath = report.fspath
+ self.write_log_entry(testpath, lettercode, longrepr)
+
+ def pytest_runtest_logreport(self, report):
+ if report.when != "call" and report.passed:
+ return
+ res = self.config.hook.pytest_report_teststatus(report=report)
+ code = res[1]
+ if code == 'x':
+ longrepr = str(report.longrepr)
+ elif code == 'X':
+ longrepr = ''
+ elif report.passed:
+ longrepr = ""
+ elif report.failed:
+ longrepr = str(report.longrepr)
+ elif report.skipped:
+ longrepr = str(report.longrepr[2])
+ self.log_outcome(report, code, longrepr)
+
+ def pytest_collectreport(self, report):
+ if not report.passed:
+ if report.failed:
+ code = "F"
+ longrepr = str(report.longrepr)
+ else:
+ assert report.skipped
+ code = "S"
+ longrepr = "%s:%d: %s" % report.longrepr
+ self.log_outcome(report, code, longrepr)
+
+ def pytest_internalerror(self, excrepr):
+ reprcrash = getattr(excrepr, 'reprcrash', None)
+ path = getattr(reprcrash, "path", None)
+ if path is None:
+ path = "cwd:%s" % py.path.local()
+ self.write_log_entry(path, '!', str(excrepr))
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/runner.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/runner.py
new file mode 100644
index 00000000000..e07ed2a248b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/runner.py
@@ -0,0 +1,506 @@
+""" basic collect and runtest protocol implementations """
+from __future__ import absolute_import, division, print_function
+
+import bdb
+import os
+import sys
+from time import time
+
+import py
+from _pytest._code.code import TerminalRepr, ExceptionInfo
+from _pytest.outcomes import skip, Skipped, TEST_OUTCOME
+
+#
+# pytest plugin hooks
+
+
+def pytest_addoption(parser):
+ group = parser.getgroup("terminal reporting", "reporting", after="general")
+ group.addoption('--durations',
+ action="store", type=int, default=None, metavar="N",
+ help="show N slowest setup/test durations (N=0 for all)."),
+
+
+def pytest_terminal_summary(terminalreporter):
+ durations = terminalreporter.config.option.durations
+ if durations is None:
+ return
+ tr = terminalreporter
+ dlist = []
+ for replist in tr.stats.values():
+ for rep in replist:
+ if hasattr(rep, 'duration'):
+ dlist.append(rep)
+ if not dlist:
+ return
+ dlist.sort(key=lambda x: x.duration)
+ dlist.reverse()
+ if not durations:
+ tr.write_sep("=", "slowest test durations")
+ else:
+ tr.write_sep("=", "slowest %s test durations" % durations)
+ dlist = dlist[:durations]
+
+ for rep in dlist:
+ nodeid = rep.nodeid.replace("::()::", "::")
+ tr.write_line("%02.2fs %-8s %s" %
+ (rep.duration, rep.when, nodeid))
+
+
+def pytest_sessionstart(session):
+ session._setupstate = SetupState()
+
+
+def pytest_sessionfinish(session):
+ session._setupstate.teardown_all()
+
+
+def pytest_runtest_protocol(item, nextitem):
+ item.ihook.pytest_runtest_logstart(
+ nodeid=item.nodeid, location=item.location,
+ )
+ runtestprotocol(item, nextitem=nextitem)
+ return True
+
+
+def runtestprotocol(item, log=True, nextitem=None):
+ hasrequest = hasattr(item, "_request")
+ if hasrequest and not item._request:
+ item._initrequest()
+ rep = call_and_report(item, "setup", log)
+ reports = [rep]
+ if rep.passed:
+ if item.config.option.setupshow:
+ show_test_item(item)
+ if not item.config.option.setuponly:
+ reports.append(call_and_report(item, "call", log))
+ reports.append(call_and_report(item, "teardown", log,
+ nextitem=nextitem))
+ # after all teardown hooks have been called
+ # want funcargs and request info to go away
+ if hasrequest:
+ item._request = False
+ item.funcargs = None
+ return reports
+
+
+def show_test_item(item):
+ """Show test function, parameters and the fixtures of the test item."""
+ tw = item.config.get_terminal_writer()
+ tw.line()
+ tw.write(' ' * 8)
+ tw.write(item._nodeid)
+ used_fixtures = sorted(item._fixtureinfo.name2fixturedefs.keys())
+ if used_fixtures:
+ tw.write(' (fixtures used: {0})'.format(', '.join(used_fixtures)))
+
+
+def pytest_runtest_setup(item):
+ _update_current_test_var(item, 'setup')
+ item.session._setupstate.prepare(item)
+
+
+def pytest_runtest_call(item):
+ _update_current_test_var(item, 'call')
+ try:
+ item.runtest()
+ except Exception:
+ # Store trace info to allow postmortem debugging
+ type, value, tb = sys.exc_info()
+ tb = tb.tb_next # Skip *this* frame
+ sys.last_type = type
+ sys.last_value = value
+ sys.last_traceback = tb
+ del tb # Get rid of it in this namespace
+ raise
+
+
+def pytest_runtest_teardown(item, nextitem):
+ _update_current_test_var(item, 'teardown')
+ item.session._setupstate.teardown_exact(item, nextitem)
+ _update_current_test_var(item, None)
+
+
+def _update_current_test_var(item, when):
+ """
+ Update PYTEST_CURRENT_TEST to reflect the current item and stage.
+
+ If ``when`` is None, delete PYTEST_CURRENT_TEST from the environment.
+ """
+ var_name = 'PYTEST_CURRENT_TEST'
+ if when:
+ value = '{0} ({1})'.format(item.nodeid, when)
+ # don't allow null bytes on environment variables (see #2644, #2957)
+ value = value.replace('\x00', '(null)')
+ os.environ[var_name] = value
+ else:
+ os.environ.pop(var_name)
+
+
+def pytest_report_teststatus(report):
+ if report.when in ("setup", "teardown"):
+ if report.failed:
+ # category, shortletter, verbose-word
+ return "error", "E", "ERROR"
+ elif report.skipped:
+ return "skipped", "s", "SKIPPED"
+ else:
+ return "", "", ""
+
+
+#
+# Implementation
+
+def call_and_report(item, when, log=True, **kwds):
+ call = call_runtest_hook(item, when, **kwds)
+ hook = item.ihook
+ report = hook.pytest_runtest_makereport(item=item, call=call)
+ if log:
+ hook.pytest_runtest_logreport(report=report)
+ if check_interactive_exception(call, report):
+ hook.pytest_exception_interact(node=item, call=call, report=report)
+ return report
+
+
+def check_interactive_exception(call, report):
+ return call.excinfo and not (
+ hasattr(report, "wasxfail") or
+ call.excinfo.errisinstance(skip.Exception) or
+ call.excinfo.errisinstance(bdb.BdbQuit))
+
+
+def call_runtest_hook(item, when, **kwds):
+ hookname = "pytest_runtest_" + when
+ ihook = getattr(item.ihook, hookname)
+ return CallInfo(lambda: ihook(item=item, **kwds), when=when)
+
+
+class CallInfo:
+ """ Result/Exception info a function invocation. """
+ #: None or ExceptionInfo object.
+ excinfo = None
+
+ def __init__(self, func, when):
+ #: context of invocation: one of "setup", "call",
+ #: "teardown", "memocollect"
+ self.when = when
+ self.start = time()
+ try:
+ self.result = func()
+ except KeyboardInterrupt:
+ self.stop = time()
+ raise
+ except: # noqa
+ self.excinfo = ExceptionInfo()
+ self.stop = time()
+
+ def __repr__(self):
+ if self.excinfo:
+ status = "exception: %s" % str(self.excinfo.value)
+ else:
+ status = "result: %r" % (self.result,)
+ return "<CallInfo when=%r %s>" % (self.when, status)
+
+
+def getslaveinfoline(node):
+ try:
+ return node._slaveinfocache
+ except AttributeError:
+ d = node.slaveinfo
+ ver = "%s.%s.%s" % d['version_info'][:3]
+ node._slaveinfocache = s = "[%s] %s -- Python %s %s" % (
+ d['id'], d['sysplatform'], ver, d['executable'])
+ return s
+
+
+class BaseReport(object):
+
+ def __init__(self, **kw):
+ self.__dict__.update(kw)
+
+ def toterminal(self, out):
+ if hasattr(self, 'node'):
+ out.line(getslaveinfoline(self.node))
+
+ longrepr = self.longrepr
+ if longrepr is None:
+ return
+
+ if hasattr(longrepr, 'toterminal'):
+ longrepr.toterminal(out)
+ else:
+ try:
+ out.line(longrepr)
+ except UnicodeEncodeError:
+ out.line("<unprintable longrepr>")
+
+ def get_sections(self, prefix):
+ for name, content in self.sections:
+ if name.startswith(prefix):
+ yield prefix, content
+
+ @property
+ def longreprtext(self):
+ """
+ Read-only property that returns the full string representation
+ of ``longrepr``.
+
+ .. versionadded:: 3.0
+ """
+ tw = py.io.TerminalWriter(stringio=True)
+ tw.hasmarkup = False
+ self.toterminal(tw)
+ exc = tw.stringio.getvalue()
+ return exc.strip()
+
+ @property
+ def capstdout(self):
+ """Return captured text from stdout, if capturing is enabled
+
+ .. versionadded:: 3.0
+ """
+ return ''.join(content for (prefix, content) in self.get_sections('Captured stdout'))
+
+ @property
+ def capstderr(self):
+ """Return captured text from stderr, if capturing is enabled
+
+ .. versionadded:: 3.0
+ """
+ return ''.join(content for (prefix, content) in self.get_sections('Captured stderr'))
+
+ passed = property(lambda x: x.outcome == "passed")
+ failed = property(lambda x: x.outcome == "failed")
+ skipped = property(lambda x: x.outcome == "skipped")
+
+ @property
+ def fspath(self):
+ return self.nodeid.split("::")[0]
+
+
+def pytest_runtest_makereport(item, call):
+ when = call.when
+ duration = call.stop - call.start
+ keywords = dict([(x, 1) for x in item.keywords])
+ excinfo = call.excinfo
+ sections = []
+ if not call.excinfo:
+ outcome = "passed"
+ longrepr = None
+ else:
+ if not isinstance(excinfo, ExceptionInfo):
+ outcome = "failed"
+ longrepr = excinfo
+ elif excinfo.errisinstance(skip.Exception):
+ outcome = "skipped"
+ r = excinfo._getreprcrash()
+ longrepr = (str(r.path), r.lineno, r.message)
+ else:
+ outcome = "failed"
+ if call.when == "call":
+ longrepr = item.repr_failure(excinfo)
+ else: # exception in setup or teardown
+ longrepr = item._repr_failure_py(excinfo,
+ style=item.config.option.tbstyle)
+ for rwhen, key, content in item._report_sections:
+ sections.append(("Captured %s %s" % (key, rwhen), content))
+ return TestReport(item.nodeid, item.location,
+ keywords, outcome, longrepr, when,
+ sections, duration)
+
+
+class TestReport(BaseReport):
+ """ Basic test report object (also used for setup and teardown calls if
+ they fail).
+ """
+
+ def __init__(self, nodeid, location, keywords, outcome,
+ longrepr, when, sections=(), duration=0, **extra):
+ #: normalized collection node id
+ self.nodeid = nodeid
+
+ #: a (filesystempath, lineno, domaininfo) tuple indicating the
+ #: actual location of a test item - it might be different from the
+ #: collected one e.g. if a method is inherited from a different module.
+ self.location = location
+
+ #: a name -> value dictionary containing all keywords and
+ #: markers associated with a test invocation.
+ self.keywords = keywords
+
+ #: test outcome, always one of "passed", "failed", "skipped".
+ self.outcome = outcome
+
+ #: None or a failure representation.
+ self.longrepr = longrepr
+
+ #: one of 'setup', 'call', 'teardown' to indicate runtest phase.
+ self.when = when
+
+ #: list of pairs ``(str, str)`` of extra information which needs to
+ #: marshallable. Used by pytest to add captured text
+ #: from ``stdout`` and ``stderr``, but may be used by other plugins
+ #: to add arbitrary information to reports.
+ self.sections = list(sections)
+
+ #: time it took to run just the test
+ self.duration = duration
+
+ self.__dict__.update(extra)
+
+ def __repr__(self):
+ return "<TestReport %r when=%r outcome=%r>" % (
+ self.nodeid, self.when, self.outcome)
+
+
+class TeardownErrorReport(BaseReport):
+ outcome = "failed"
+ when = "teardown"
+
+ def __init__(self, longrepr, **extra):
+ self.longrepr = longrepr
+ self.sections = []
+ self.__dict__.update(extra)
+
+
+def pytest_make_collect_report(collector):
+ call = CallInfo(
+ lambda: list(collector.collect()),
+ 'collect')
+ longrepr = None
+ if not call.excinfo:
+ outcome = "passed"
+ else:
+ from _pytest import nose
+ skip_exceptions = (Skipped,) + nose.get_skip_exceptions()
+ if call.excinfo.errisinstance(skip_exceptions):
+ outcome = "skipped"
+ r = collector._repr_failure_py(call.excinfo, "line").reprcrash
+ longrepr = (str(r.path), r.lineno, r.message)
+ else:
+ outcome = "failed"
+ errorinfo = collector.repr_failure(call.excinfo)
+ if not hasattr(errorinfo, "toterminal"):
+ errorinfo = CollectErrorRepr(errorinfo)
+ longrepr = errorinfo
+ rep = CollectReport(collector.nodeid, outcome, longrepr,
+ getattr(call, 'result', None))
+ rep.call = call # see collect_one_node
+ return rep
+
+
+class CollectReport(BaseReport):
+ def __init__(self, nodeid, outcome, longrepr, result,
+ sections=(), **extra):
+ self.nodeid = nodeid
+ self.outcome = outcome
+ self.longrepr = longrepr
+ self.result = result or []
+ self.sections = list(sections)
+ self.__dict__.update(extra)
+
+ @property
+ def location(self):
+ return (self.fspath, None, self.fspath)
+
+ def __repr__(self):
+ return "<CollectReport %r lenresult=%s outcome=%r>" % (
+ self.nodeid, len(self.result), self.outcome)
+
+
+class CollectErrorRepr(TerminalRepr):
+ def __init__(self, msg):
+ self.longrepr = msg
+
+ def toterminal(self, out):
+ out.line(self.longrepr, red=True)
+
+
+class SetupState(object):
+ """ shared state for setting up/tearing down test items or collectors. """
+
+ def __init__(self):
+ self.stack = []
+ self._finalizers = {}
+
+ def addfinalizer(self, finalizer, colitem):
+ """ attach a finalizer to the given colitem.
+ if colitem is None, this will add a finalizer that
+ is called at the end of teardown_all().
+ """
+ assert colitem and not isinstance(colitem, tuple)
+ assert callable(finalizer)
+ # assert colitem in self.stack # some unit tests don't setup stack :/
+ self._finalizers.setdefault(colitem, []).append(finalizer)
+
+ def _pop_and_teardown(self):
+ colitem = self.stack.pop()
+ self._teardown_with_finalization(colitem)
+
+ def _callfinalizers(self, colitem):
+ finalizers = self._finalizers.pop(colitem, None)
+ exc = None
+ while finalizers:
+ fin = finalizers.pop()
+ try:
+ fin()
+ except TEST_OUTCOME:
+ # XXX Only first exception will be seen by user,
+ # ideally all should be reported.
+ if exc is None:
+ exc = sys.exc_info()
+ if exc:
+ py.builtin._reraise(*exc)
+
+ def _teardown_with_finalization(self, colitem):
+ self._callfinalizers(colitem)
+ if hasattr(colitem, "teardown"):
+ colitem.teardown()
+ for colitem in self._finalizers:
+ assert colitem is None or colitem in self.stack \
+ or isinstance(colitem, tuple)
+
+ def teardown_all(self):
+ while self.stack:
+ self._pop_and_teardown()
+ for key in list(self._finalizers):
+ self._teardown_with_finalization(key)
+ assert not self._finalizers
+
+ def teardown_exact(self, item, nextitem):
+ needed_collectors = nextitem and nextitem.listchain() or []
+ self._teardown_towards(needed_collectors)
+
+ def _teardown_towards(self, needed_collectors):
+ while self.stack:
+ if self.stack == needed_collectors[:len(self.stack)]:
+ break
+ self._pop_and_teardown()
+
+ def prepare(self, colitem):
+ """ setup objects along the collector chain to the test-method
+ and teardown previously setup objects."""
+ needed_collectors = colitem.listchain()
+ self._teardown_towards(needed_collectors)
+
+ # check if the last collection node has raised an error
+ for col in self.stack:
+ if hasattr(col, '_prepare_exc'):
+ py.builtin._reraise(*col._prepare_exc)
+ for col in needed_collectors[len(self.stack):]:
+ self.stack.append(col)
+ try:
+ col.setup()
+ except TEST_OUTCOME:
+ col._prepare_exc = sys.exc_info()
+ raise
+
+
+def collect_one_node(collector):
+ ihook = collector.ihook
+ ihook.pytest_collectstart(collector=collector)
+ rep = ihook.pytest_make_collect_report(collector=collector)
+ call = rep.__dict__.pop("call", None)
+ if call and check_interactive_exception(call, rep):
+ ihook.pytest_exception_interact(node=collector, call=call, report=rep)
+ return rep
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/setuponly.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/setuponly.py
new file mode 100644
index 00000000000..a1c7457d7e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/setuponly.py
@@ -0,0 +1,74 @@
+from __future__ import absolute_import, division, print_function
+
+import pytest
+import sys
+
+
+def pytest_addoption(parser):
+ group = parser.getgroup("debugconfig")
+ group.addoption('--setuponly', '--setup-only', action="store_true",
+ help="only setup fixtures, do not execute tests.")
+ group.addoption('--setupshow', '--setup-show', action="store_true",
+ help="show setup of fixtures while executing tests.")
+
+
+@pytest.hookimpl(hookwrapper=True)
+def pytest_fixture_setup(fixturedef, request):
+ yield
+ config = request.config
+ if config.option.setupshow:
+ if hasattr(request, 'param'):
+ # Save the fixture parameter so ._show_fixture_action() can
+ # display it now and during the teardown (in .finish()).
+ if fixturedef.ids:
+ if callable(fixturedef.ids):
+ fixturedef.cached_param = fixturedef.ids(request.param)
+ else:
+ fixturedef.cached_param = fixturedef.ids[
+ request.param_index]
+ else:
+ fixturedef.cached_param = request.param
+ _show_fixture_action(fixturedef, 'SETUP')
+
+
+def pytest_fixture_post_finalizer(fixturedef):
+ if hasattr(fixturedef, "cached_result"):
+ config = fixturedef._fixturemanager.config
+ if config.option.setupshow:
+ _show_fixture_action(fixturedef, 'TEARDOWN')
+ if hasattr(fixturedef, "cached_param"):
+ del fixturedef.cached_param
+
+
+def _show_fixture_action(fixturedef, msg):
+ config = fixturedef._fixturemanager.config
+ capman = config.pluginmanager.getplugin('capturemanager')
+ if capman:
+ out, err = capman.suspend_global_capture()
+
+ tw = config.get_terminal_writer()
+ tw.line()
+ tw.write(' ' * 2 * fixturedef.scopenum)
+ tw.write('{step} {scope} {fixture}'.format(
+ step=msg.ljust(8), # align the output to TEARDOWN
+ scope=fixturedef.scope[0].upper(),
+ fixture=fixturedef.argname))
+
+ if msg == 'SETUP':
+ deps = sorted(arg for arg in fixturedef.argnames if arg != 'request')
+ if deps:
+ tw.write(' (fixtures used: {0})'.format(', '.join(deps)))
+
+ if hasattr(fixturedef, 'cached_param'):
+ tw.write('[{0}]'.format(fixturedef.cached_param))
+
+ if capman:
+ capman.resume_global_capture()
+ sys.stdout.write(out)
+ sys.stderr.write(err)
+
+
+@pytest.hookimpl(tryfirst=True)
+def pytest_cmdline_main(config):
+ if config.option.setuponly:
+ config.option.setupshow = True
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/setupplan.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/setupplan.py
new file mode 100644
index 00000000000..e11bd40698b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/setupplan.py
@@ -0,0 +1,25 @@
+from __future__ import absolute_import, division, print_function
+
+import pytest
+
+
+def pytest_addoption(parser):
+ group = parser.getgroup("debugconfig")
+ group.addoption('--setupplan', '--setup-plan', action="store_true",
+ help="show what fixtures and tests would be executed but "
+ "don't execute anything.")
+
+
+@pytest.hookimpl(tryfirst=True)
+def pytest_fixture_setup(fixturedef, request):
+ # Will return a dummy fixture if the setuponly option is provided.
+ if request.config.option.setupplan:
+ fixturedef.cached_result = (None, None, None)
+ return fixturedef.cached_result
+
+
+@pytest.hookimpl(tryfirst=True)
+def pytest_cmdline_main(config):
+ if config.option.setupplan:
+ config.option.setuponly = True
+ config.option.setupshow = True
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/skipping.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/skipping.py
new file mode 100644
index 00000000000..a1e5b43800b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/skipping.py
@@ -0,0 +1,397 @@
+""" support for skip/xfail functions and markers. """
+from __future__ import absolute_import, division, print_function
+
+import os
+import six
+import sys
+import traceback
+
+from _pytest.config import hookimpl
+from _pytest.mark import MarkInfo, MarkDecorator
+from _pytest.outcomes import fail, skip, xfail, TEST_OUTCOME
+
+
+def pytest_addoption(parser):
+ group = parser.getgroup("general")
+ group.addoption('--runxfail',
+ action="store_true", dest="runxfail", default=False,
+ help="run tests even if they are marked xfail")
+
+ parser.addini("xfail_strict", "default for the strict parameter of xfail "
+ "markers when not given explicitly (default: "
+ "False)",
+ default=False,
+ type="bool")
+
+
+def pytest_configure(config):
+ if config.option.runxfail:
+ # yay a hack
+ import pytest
+ old = pytest.xfail
+ config._cleanup.append(lambda: setattr(pytest, "xfail", old))
+
+ def nop(*args, **kwargs):
+ pass
+
+ nop.Exception = xfail.Exception
+ setattr(pytest, "xfail", nop)
+
+ config.addinivalue_line("markers",
+ "skip(reason=None): skip the given test function with an optional reason. "
+ "Example: skip(reason=\"no way of currently testing this\") skips the "
+ "test."
+ )
+ config.addinivalue_line("markers",
+ "skipif(condition): skip the given test function if eval(condition) "
+ "results in a True value. Evaluation happens within the "
+ "module global context. Example: skipif('sys.platform == \"win32\"') "
+ "skips the test if we are on the win32 platform. see "
+ "http://pytest.org/latest/skipping.html"
+ )
+ config.addinivalue_line("markers",
+ "xfail(condition, reason=None, run=True, raises=None, strict=False): "
+ "mark the test function as an expected failure if eval(condition) "
+ "has a True value. Optionally specify a reason for better reporting "
+ "and run=False if you don't even want to execute the test function. "
+ "If only specific exception(s) are expected, you can list them in "
+ "raises, and if the test fails in other ways, it will be reported as "
+ "a true failure. See http://pytest.org/latest/skipping.html"
+ )
+
+
+class MarkEvaluator(object):
+ def __init__(self, item, name):
+ self.item = item
+ self._marks = None
+ self._mark = None
+ self._mark_name = name
+
+ def __bool__(self):
+ self._marks = self._get_marks()
+ return bool(self._marks)
+ __nonzero__ = __bool__
+
+ def wasvalid(self):
+ return not hasattr(self, 'exc')
+
+ def _get_marks(self):
+
+ keyword = self.item.keywords.get(self._mark_name)
+ if isinstance(keyword, MarkDecorator):
+ return [keyword.mark]
+ elif isinstance(keyword, MarkInfo):
+ return [x.combined for x in keyword]
+ else:
+ return []
+
+ def invalidraise(self, exc):
+ raises = self.get('raises')
+ if not raises:
+ return
+ return not isinstance(exc, raises)
+
+ def istrue(self):
+ try:
+ return self._istrue()
+ except TEST_OUTCOME:
+ self.exc = sys.exc_info()
+ if isinstance(self.exc[1], SyntaxError):
+ msg = [" " * (self.exc[1].offset + 4) + "^", ]
+ msg.append("SyntaxError: invalid syntax")
+ else:
+ msg = traceback.format_exception_only(*self.exc[:2])
+ fail("Error evaluating %r expression\n"
+ " %s\n"
+ "%s"
+ % (self._mark_name, self.expr, "\n".join(msg)),
+ pytrace=False)
+
+ def _getglobals(self):
+ d = {'os': os, 'sys': sys, 'config': self.item.config}
+ if hasattr(self.item, 'obj'):
+ d.update(self.item.obj.__globals__)
+ return d
+
+ def _istrue(self):
+ if hasattr(self, 'result'):
+ return self.result
+ self._marks = self._get_marks()
+
+ if self._marks:
+ self.result = False
+ for mark in self._marks:
+ self._mark = mark
+ if 'condition' in mark.kwargs:
+ args = (mark.kwargs['condition'],)
+ else:
+ args = mark.args
+
+ for expr in args:
+ self.expr = expr
+ if isinstance(expr, six.string_types):
+ d = self._getglobals()
+ result = cached_eval(self.item.config, expr, d)
+ else:
+ if "reason" not in mark.kwargs:
+ # XXX better be checked at collection time
+ msg = "you need to specify reason=STRING " \
+ "when using booleans as conditions."
+ fail(msg)
+ result = bool(expr)
+ if result:
+ self.result = True
+ self.reason = mark.kwargs.get('reason', None)
+ self.expr = expr
+ return self.result
+
+ if not args:
+ self.result = True
+ self.reason = mark.kwargs.get('reason', None)
+ return self.result
+ return False
+
+ def get(self, attr, default=None):
+ if self._mark is None:
+ return default
+ return self._mark.kwargs.get(attr, default)
+
+ def getexplanation(self):
+ expl = getattr(self, 'reason', None) or self.get('reason', None)
+ if not expl:
+ if not hasattr(self, 'expr'):
+ return ""
+ else:
+ return "condition: " + str(self.expr)
+ return expl
+
+
+@hookimpl(tryfirst=True)
+def pytest_runtest_setup(item):
+ # Check if skip or skipif are specified as pytest marks
+ item._skipped_by_mark = False
+ skipif_info = item.keywords.get('skipif')
+ if isinstance(skipif_info, (MarkInfo, MarkDecorator)):
+ eval_skipif = MarkEvaluator(item, 'skipif')
+ if eval_skipif.istrue():
+ item._skipped_by_mark = True
+ skip(eval_skipif.getexplanation())
+
+ skip_info = item.keywords.get('skip')
+ if isinstance(skip_info, (MarkInfo, MarkDecorator)):
+ item._skipped_by_mark = True
+ if 'reason' in skip_info.kwargs:
+ skip(skip_info.kwargs['reason'])
+ elif skip_info.args:
+ skip(skip_info.args[0])
+ else:
+ skip("unconditional skip")
+
+ item._evalxfail = MarkEvaluator(item, 'xfail')
+ check_xfail_no_run(item)
+
+
+@hookimpl(hookwrapper=True)
+def pytest_pyfunc_call(pyfuncitem):
+ check_xfail_no_run(pyfuncitem)
+ outcome = yield
+ passed = outcome.excinfo is None
+ if passed:
+ check_strict_xfail(pyfuncitem)
+
+
+def check_xfail_no_run(item):
+ """check xfail(run=False)"""
+ if not item.config.option.runxfail:
+ evalxfail = item._evalxfail
+ if evalxfail.istrue():
+ if not evalxfail.get('run', True):
+ xfail("[NOTRUN] " + evalxfail.getexplanation())
+
+
+def check_strict_xfail(pyfuncitem):
+ """check xfail(strict=True) for the given PASSING test"""
+ evalxfail = pyfuncitem._evalxfail
+ if evalxfail.istrue():
+ strict_default = pyfuncitem.config.getini('xfail_strict')
+ is_strict_xfail = evalxfail.get('strict', strict_default)
+ if is_strict_xfail:
+ del pyfuncitem._evalxfail
+ explanation = evalxfail.getexplanation()
+ fail('[XPASS(strict)] ' + explanation, pytrace=False)
+
+
+@hookimpl(hookwrapper=True)
+def pytest_runtest_makereport(item, call):
+ outcome = yield
+ rep = outcome.get_result()
+ evalxfail = getattr(item, '_evalxfail', None)
+ # unitttest special case, see setting of _unexpectedsuccess
+ if hasattr(item, '_unexpectedsuccess') and rep.when == "call":
+ from _pytest.compat import _is_unittest_unexpected_success_a_failure
+ if item._unexpectedsuccess:
+ rep.longrepr = "Unexpected success: {0}".format(item._unexpectedsuccess)
+ else:
+ rep.longrepr = "Unexpected success"
+ if _is_unittest_unexpected_success_a_failure():
+ rep.outcome = "failed"
+ else:
+ rep.outcome = "passed"
+ rep.wasxfail = rep.longrepr
+ elif item.config.option.runxfail:
+ pass # don't interefere
+ elif call.excinfo and call.excinfo.errisinstance(xfail.Exception):
+ rep.wasxfail = "reason: " + call.excinfo.value.msg
+ rep.outcome = "skipped"
+ elif evalxfail and not rep.skipped and evalxfail.wasvalid() and \
+ evalxfail.istrue():
+ if call.excinfo:
+ if evalxfail.invalidraise(call.excinfo.value):
+ rep.outcome = "failed"
+ else:
+ rep.outcome = "skipped"
+ rep.wasxfail = evalxfail.getexplanation()
+ elif call.when == "call":
+ strict_default = item.config.getini('xfail_strict')
+ is_strict_xfail = evalxfail.get('strict', strict_default)
+ explanation = evalxfail.getexplanation()
+ if is_strict_xfail:
+ rep.outcome = "failed"
+ rep.longrepr = "[XPASS(strict)] {0}".format(explanation)
+ else:
+ rep.outcome = "passed"
+ rep.wasxfail = explanation
+ elif item._skipped_by_mark and rep.skipped and type(rep.longrepr) is tuple:
+ # skipped by mark.skipif; change the location of the failure
+ # to point to the item definition, otherwise it will display
+ # the location of where the skip exception was raised within pytest
+ filename, line, reason = rep.longrepr
+ filename, line = item.location[:2]
+ rep.longrepr = filename, line, reason
+
+# called by terminalreporter progress reporting
+
+
+def pytest_report_teststatus(report):
+ if hasattr(report, "wasxfail"):
+ if report.skipped:
+ return "xfailed", "x", "xfail"
+ elif report.passed:
+ return "xpassed", "X", ("XPASS", {'yellow': True})
+
+# called by the terminalreporter instance/plugin
+
+
+def pytest_terminal_summary(terminalreporter):
+ tr = terminalreporter
+ if not tr.reportchars:
+ # for name in "xfailed skipped failed xpassed":
+ # if not tr.stats.get(name, 0):
+ # tr.write_line("HINT: use '-r' option to see extra "
+ # "summary info about tests")
+ # break
+ return
+
+ lines = []
+ for char in tr.reportchars:
+ if char == "x":
+ show_xfailed(terminalreporter, lines)
+ elif char == "X":
+ show_xpassed(terminalreporter, lines)
+ elif char in "fF":
+ show_simple(terminalreporter, lines, 'failed', "FAIL %s")
+ elif char in "sS":
+ show_skipped(terminalreporter, lines)
+ elif char == "E":
+ show_simple(terminalreporter, lines, 'error', "ERROR %s")
+ elif char == 'p':
+ show_simple(terminalreporter, lines, 'passed', "PASSED %s")
+
+ if lines:
+ tr._tw.sep("=", "short test summary info")
+ for line in lines:
+ tr._tw.line(line)
+
+
+def show_simple(terminalreporter, lines, stat, format):
+ failed = terminalreporter.stats.get(stat)
+ if failed:
+ for rep in failed:
+ pos = terminalreporter.config.cwd_relative_nodeid(rep.nodeid)
+ lines.append(format % (pos,))
+
+
+def show_xfailed(terminalreporter, lines):
+ xfailed = terminalreporter.stats.get("xfailed")
+ if xfailed:
+ for rep in xfailed:
+ pos = terminalreporter.config.cwd_relative_nodeid(rep.nodeid)
+ reason = rep.wasxfail
+ lines.append("XFAIL %s" % (pos,))
+ if reason:
+ lines.append(" " + str(reason))
+
+
+def show_xpassed(terminalreporter, lines):
+ xpassed = terminalreporter.stats.get("xpassed")
+ if xpassed:
+ for rep in xpassed:
+ pos = terminalreporter.config.cwd_relative_nodeid(rep.nodeid)
+ reason = rep.wasxfail
+ lines.append("XPASS %s %s" % (pos, reason))
+
+
+def cached_eval(config, expr, d):
+ if not hasattr(config, '_evalcache'):
+ config._evalcache = {}
+ try:
+ return config._evalcache[expr]
+ except KeyError:
+ import _pytest._code
+ exprcode = _pytest._code.compile(expr, mode="eval")
+ config._evalcache[expr] = x = eval(exprcode, d)
+ return x
+
+
+def folded_skips(skipped):
+ d = {}
+ for event in skipped:
+ key = event.longrepr
+ assert len(key) == 3, (event, key)
+ keywords = getattr(event, 'keywords', {})
+ # folding reports with global pytestmark variable
+ # this is workaround, because for now we cannot identify the scope of a skip marker
+ # TODO: revisit after marks scope would be fixed
+ when = getattr(event, 'when', None)
+ if when == 'setup' and 'skip' in keywords and 'pytestmark' not in keywords:
+ key = (key[0], None, key[2], )
+ d.setdefault(key, []).append(event)
+ values = []
+ for key, events in d.items():
+ values.append((len(events),) + key)
+ return values
+
+
+def show_skipped(terminalreporter, lines):
+ tr = terminalreporter
+ skipped = tr.stats.get('skipped', [])
+ if skipped:
+ # if not tr.hasopt('skipped'):
+ # tr.write_line(
+ # "%d skipped tests, specify -rs for more info" %
+ # len(skipped))
+ # return
+ fskips = folded_skips(skipped)
+ if fskips:
+ # tr.write_sep("_", "skipped test summary")
+ for num, fspath, lineno, reason in fskips:
+ if reason.startswith("Skipped: "):
+ reason = reason[9:]
+ if lineno is not None:
+ lines.append(
+ "SKIP [%d] %s:%d: %s" %
+ (num, fspath, lineno + 1, reason))
+ else:
+ lines.append(
+ "SKIP [%d] %s: %s" %
+ (num, fspath, reason))
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/terminal.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/terminal.py
new file mode 100644
index 00000000000..1aba5e845e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/terminal.py
@@ -0,0 +1,703 @@
+""" terminal reporting of the full testing process.
+
+This is a good source for looking at the various reporting hooks.
+"""
+from __future__ import absolute_import, division, print_function
+
+import itertools
+import platform
+import sys
+import time
+
+import pluggy
+import py
+import six
+
+import pytest
+from _pytest import nodes
+from _pytest.main import EXIT_OK, EXIT_TESTSFAILED, EXIT_INTERRUPTED, \
+ EXIT_USAGEERROR, EXIT_NOTESTSCOLLECTED
+
+
+def pytest_addoption(parser):
+ group = parser.getgroup("terminal reporting", "reporting", after="general")
+ group._addoption('-v', '--verbose', action="count",
+ dest="verbose", default=0, help="increase verbosity."),
+ group._addoption('-q', '--quiet', action="count",
+ dest="quiet", default=0, help="decrease verbosity."),
+ group._addoption('-r',
+ action="store", dest="reportchars", default='', metavar="chars",
+ help="show extra test summary info as specified by chars (f)ailed, "
+ "(E)error, (s)skipped, (x)failed, (X)passed, "
+ "(p)passed, (P)passed with output, (a)all except pP. "
+ "Warnings are displayed at all times except when "
+ "--disable-warnings is set")
+ group._addoption('--disable-warnings', '--disable-pytest-warnings', default=False,
+ dest='disable_warnings', action='store_true',
+ help='disable warnings summary')
+ group._addoption('-l', '--showlocals',
+ action="store_true", dest="showlocals", default=False,
+ help="show locals in tracebacks (disabled by default).")
+ group._addoption('--tb', metavar="style",
+ action="store", dest="tbstyle", default='auto',
+ choices=['auto', 'long', 'short', 'no', 'line', 'native'],
+ help="traceback print mode (auto/long/short/line/native/no).")
+ group._addoption('--fulltrace', '--full-trace',
+ action="store_true", default=False,
+ help="don't cut any tracebacks (default is to cut).")
+ group._addoption('--color', metavar="color",
+ action="store", dest="color", default='auto',
+ choices=['yes', 'no', 'auto'],
+ help="color terminal output (yes/no/auto).")
+
+ parser.addini("console_output_style",
+ help="console output: classic or with additional progress information (classic|progress).",
+ default='progress')
+
+
+def pytest_configure(config):
+ config.option.verbose -= config.option.quiet
+ reporter = TerminalReporter(config, sys.stdout)
+ config.pluginmanager.register(reporter, 'terminalreporter')
+ if config.option.debug or config.option.traceconfig:
+ def mywriter(tags, args):
+ msg = " ".join(map(str, args))
+ reporter.write_line("[traceconfig] " + msg)
+ config.trace.root.setprocessor("pytest:config", mywriter)
+
+
+def getreportopt(config):
+ reportopts = ""
+ reportchars = config.option.reportchars
+ if not config.option.disable_warnings and 'w' not in reportchars:
+ reportchars += 'w'
+ elif config.option.disable_warnings and 'w' in reportchars:
+ reportchars = reportchars.replace('w', '')
+ if reportchars:
+ for char in reportchars:
+ if char not in reportopts and char != 'a':
+ reportopts += char
+ elif char == 'a':
+ reportopts = 'fEsxXw'
+ return reportopts
+
+
+def pytest_report_teststatus(report):
+ if report.passed:
+ letter = "."
+ elif report.skipped:
+ letter = "s"
+ elif report.failed:
+ letter = "F"
+ if report.when != "call":
+ letter = "f"
+ return report.outcome, letter, report.outcome.upper()
+
+
+class WarningReport:
+ """
+ Simple structure to hold warnings information captured by ``pytest_logwarning``.
+ """
+
+ def __init__(self, code, message, nodeid=None, fslocation=None):
+ """
+ :param code: unused
+ :param str message: user friendly message about the warning
+ :param str|None nodeid: node id that generated the warning (see ``get_location``).
+ :param tuple|py.path.local fslocation:
+ file system location of the source of the warning (see ``get_location``).
+ """
+ self.code = code
+ self.message = message
+ self.nodeid = nodeid
+ self.fslocation = fslocation
+
+ def get_location(self, config):
+ """
+ Returns the more user-friendly information about the location
+ of a warning, or None.
+ """
+ if self.nodeid:
+ return self.nodeid
+ if self.fslocation:
+ if isinstance(self.fslocation, tuple) and len(self.fslocation) >= 2:
+ filename, linenum = self.fslocation[:2]
+ relpath = py.path.local(filename).relto(config.invocation_dir)
+ return '%s:%s' % (relpath, linenum)
+ else:
+ return str(self.fslocation)
+ return None
+
+
+class TerminalReporter:
+ def __init__(self, config, file=None):
+ import _pytest.config
+ self.config = config
+ self.verbosity = self.config.option.verbose
+ self.showheader = self.verbosity >= 0
+ self.showfspath = self.verbosity >= 0
+ self.showlongtestinfo = self.verbosity > 0
+ self._numcollected = 0
+ self._session = None
+
+ self.stats = {}
+ self.startdir = py.path.local()
+ if file is None:
+ file = sys.stdout
+ self._tw = _pytest.config.create_terminal_writer(config, file)
+ # self.writer will be deprecated in pytest-3.4
+ self.writer = self._tw
+ self._screen_width = self._tw.fullwidth
+ self.currentfspath = None
+ self.reportchars = getreportopt(config)
+ self.hasmarkup = self._tw.hasmarkup
+ self.isatty = file.isatty()
+ self._progress_items_reported = 0
+ self._show_progress_info = self.config.getini('console_output_style') == 'progress'
+
+ def hasopt(self, char):
+ char = {'xfailed': 'x', 'skipped': 's'}.get(char, char)
+ return char in self.reportchars
+
+ def write_fspath_result(self, nodeid, res):
+ fspath = self.config.rootdir.join(nodeid.split("::")[0])
+ if fspath != self.currentfspath:
+ if self.currentfspath is not None:
+ self._write_progress_information_filling_space()
+ self.currentfspath = fspath
+ fspath = self.startdir.bestrelpath(fspath)
+ self._tw.line()
+ self._tw.write(fspath + " ")
+ self._tw.write(res)
+
+ def write_ensure_prefix(self, prefix, extra="", **kwargs):
+ if self.currentfspath != prefix:
+ self._tw.line()
+ self.currentfspath = prefix
+ self._tw.write(prefix)
+ if extra:
+ self._tw.write(extra, **kwargs)
+ self.currentfspath = -2
+ self._write_progress_information_filling_space()
+
+ def ensure_newline(self):
+ if self.currentfspath:
+ self._tw.line()
+ self.currentfspath = None
+
+ def write(self, content, **markup):
+ self._tw.write(content, **markup)
+
+ def write_line(self, line, **markup):
+ if not isinstance(line, six.text_type):
+ line = six.text_type(line, errors="replace")
+ self.ensure_newline()
+ self._tw.line(line, **markup)
+
+ def rewrite(self, line, **markup):
+ """
+ Rewinds the terminal cursor to the beginning and writes the given line.
+
+ :kwarg erase: if True, will also add spaces until the full terminal width to ensure
+ previous lines are properly erased.
+
+ The rest of the keyword arguments are markup instructions.
+ """
+ erase = markup.pop('erase', False)
+ if erase:
+ fill_count = self._tw.fullwidth - len(line) - 1
+ fill = ' ' * fill_count
+ else:
+ fill = ''
+ line = str(line)
+ self._tw.write("\r" + line + fill, **markup)
+
+ def write_sep(self, sep, title=None, **markup):
+ self.ensure_newline()
+ self._tw.sep(sep, title, **markup)
+
+ def section(self, title, sep="=", **kw):
+ self._tw.sep(sep, title, **kw)
+
+ def line(self, msg, **kw):
+ self._tw.line(msg, **kw)
+
+ def pytest_internalerror(self, excrepr):
+ for line in six.text_type(excrepr).split("\n"):
+ self.write_line("INTERNALERROR> " + line)
+ return 1
+
+ def pytest_logwarning(self, code, fslocation, message, nodeid):
+ warnings = self.stats.setdefault("warnings", [])
+ warning = WarningReport(code=code, fslocation=fslocation,
+ message=message, nodeid=nodeid)
+ warnings.append(warning)
+
+ def pytest_plugin_registered(self, plugin):
+ if self.config.option.traceconfig:
+ msg = "PLUGIN registered: %s" % (plugin,)
+ # XXX this event may happen during setup/teardown time
+ # which unfortunately captures our output here
+ # which garbles our output if we use self.write_line
+ self.write_line(msg)
+
+ def pytest_deselected(self, items):
+ self.stats.setdefault('deselected', []).extend(items)
+
+ def pytest_runtest_logstart(self, nodeid, location):
+ # ensure that the path is printed before the
+ # 1st test of a module starts running
+ if self.showlongtestinfo:
+ line = self._locationline(nodeid, *location)
+ self.write_ensure_prefix(line, "")
+ elif self.showfspath:
+ fsid = nodeid.split("::")[0]
+ self.write_fspath_result(fsid, "")
+
+ def pytest_runtest_logreport(self, report):
+ rep = report
+ res = self.config.hook.pytest_report_teststatus(report=rep)
+ cat, letter, word = res
+ if isinstance(word, tuple):
+ word, markup = word
+ else:
+ markup = None
+ self.stats.setdefault(cat, []).append(rep)
+ self._tests_ran = True
+ if not letter and not word:
+ # probably passed setup/teardown
+ return
+ running_xdist = hasattr(rep, 'node')
+ self._progress_items_reported += 1
+ if self.verbosity <= 0:
+ if not running_xdist and self.showfspath:
+ self.write_fspath_result(rep.nodeid, letter)
+ else:
+ self._tw.write(letter)
+ self._write_progress_if_past_edge()
+ else:
+ if markup is None:
+ if rep.passed:
+ markup = {'green': True}
+ elif rep.failed:
+ markup = {'red': True}
+ elif rep.skipped:
+ markup = {'yellow': True}
+ else:
+ markup = {}
+ line = self._locationline(rep.nodeid, *rep.location)
+ if not running_xdist:
+ self.write_ensure_prefix(line, word, **markup)
+ else:
+ self.ensure_newline()
+ self._tw.write("[%s]" % rep.node.gateway.id)
+ if self._show_progress_info:
+ self._tw.write(self._get_progress_information_message() + " ", cyan=True)
+ else:
+ self._tw.write(' ')
+ self._tw.write(word, **markup)
+ self._tw.write(" " + line)
+ self.currentfspath = -2
+
+ def _write_progress_if_past_edge(self):
+ if not self._show_progress_info:
+ return
+ last_item = self._progress_items_reported == self._session.testscollected
+ if last_item:
+ self._write_progress_information_filling_space()
+ return
+
+ past_edge = self._tw.chars_on_current_line + self._PROGRESS_LENGTH + 1 >= self._screen_width
+ if past_edge:
+ msg = self._get_progress_information_message()
+ self._tw.write(msg + '\n', cyan=True)
+
+ _PROGRESS_LENGTH = len(' [100%]')
+
+ def _get_progress_information_message(self):
+ collected = self._session.testscollected
+ if collected:
+ progress = self._progress_items_reported * 100 // collected
+ return ' [{:3d}%]'.format(progress)
+ return ' [100%]'
+
+ def _write_progress_information_filling_space(self):
+ if not self._show_progress_info:
+ return
+ msg = self._get_progress_information_message()
+ fill = ' ' * (self._tw.fullwidth - self._tw.chars_on_current_line - len(msg) - 1)
+ self.write(fill + msg, cyan=True)
+
+ def pytest_collection(self):
+ if not self.isatty and self.config.option.verbose >= 1:
+ self.write("collecting ... ", bold=True)
+
+ def pytest_collectreport(self, report):
+ if report.failed:
+ self.stats.setdefault("error", []).append(report)
+ elif report.skipped:
+ self.stats.setdefault("skipped", []).append(report)
+ items = [x for x in report.result if isinstance(x, pytest.Item)]
+ self._numcollected += len(items)
+ if self.isatty:
+ # self.write_fspath_result(report.nodeid, 'E')
+ self.report_collect()
+
+ def report_collect(self, final=False):
+ if self.config.option.verbose < 0:
+ return
+
+ errors = len(self.stats.get('error', []))
+ skipped = len(self.stats.get('skipped', []))
+ if final:
+ line = "collected "
+ else:
+ line = "collecting "
+ line += str(self._numcollected) + " item" + ('' if self._numcollected == 1 else 's')
+ if errors:
+ line += " / %d errors" % errors
+ if skipped:
+ line += " / %d skipped" % skipped
+ if self.isatty:
+ self.rewrite(line, bold=True, erase=True)
+ if final:
+ self.write('\n')
+ else:
+ self.write_line(line)
+
+ def pytest_collection_modifyitems(self):
+ self.report_collect(True)
+
+ @pytest.hookimpl(trylast=True)
+ def pytest_sessionstart(self, session):
+ self._session = session
+ self._sessionstarttime = time.time()
+ if not self.showheader:
+ return
+ self.write_sep("=", "test session starts", bold=True)
+ verinfo = platform.python_version()
+ msg = "platform %s -- Python %s" % (sys.platform, verinfo)
+ if hasattr(sys, 'pypy_version_info'):
+ verinfo = ".".join(map(str, sys.pypy_version_info[:3]))
+ msg += "[pypy-%s-%s]" % (verinfo, sys.pypy_version_info[3])
+ msg += ", pytest-%s, py-%s, pluggy-%s" % (
+ pytest.__version__, py.__version__, pluggy.__version__)
+ if self.verbosity > 0 or self.config.option.debug or \
+ getattr(self.config.option, 'pastebin', None):
+ msg += " -- " + str(sys.executable)
+ self.write_line(msg)
+ lines = self.config.hook.pytest_report_header(
+ config=self.config, startdir=self.startdir)
+ self._write_report_lines_from_hooks(lines)
+
+ def _write_report_lines_from_hooks(self, lines):
+ lines.reverse()
+ for line in flatten(lines):
+ self.write_line(line)
+
+ def pytest_report_header(self, config):
+ inifile = ""
+ if config.inifile:
+ inifile = " " + config.rootdir.bestrelpath(config.inifile)
+ lines = ["rootdir: %s, inifile:%s" % (config.rootdir, inifile)]
+
+ plugininfo = config.pluginmanager.list_plugin_distinfo()
+ if plugininfo:
+
+ lines.append(
+ "plugins: %s" % ", ".join(_plugin_nameversions(plugininfo)))
+ return lines
+
+ def pytest_collection_finish(self, session):
+ if self.config.option.collectonly:
+ self._printcollecteditems(session.items)
+ if self.stats.get('failed'):
+ self._tw.sep("!", "collection failures")
+ for rep in self.stats.get('failed'):
+ rep.toterminal(self._tw)
+ return 1
+ return 0
+ lines = self.config.hook.pytest_report_collectionfinish(
+ config=self.config, startdir=self.startdir, items=session.items)
+ self._write_report_lines_from_hooks(lines)
+
+ def _printcollecteditems(self, items):
+ # to print out items and their parent collectors
+ # we take care to leave out Instances aka ()
+ # because later versions are going to get rid of them anyway
+ if self.config.option.verbose < 0:
+ if self.config.option.verbose < -1:
+ counts = {}
+ for item in items:
+ name = item.nodeid.split('::', 1)[0]
+ counts[name] = counts.get(name, 0) + 1
+ for name, count in sorted(counts.items()):
+ self._tw.line("%s: %d" % (name, count))
+ else:
+ for item in items:
+ nodeid = item.nodeid
+ nodeid = nodeid.replace("::()::", "::")
+ self._tw.line(nodeid)
+ return
+ stack = []
+ indent = ""
+ for item in items:
+ needed_collectors = item.listchain()[1:] # strip root node
+ while stack:
+ if stack == needed_collectors[:len(stack)]:
+ break
+ stack.pop()
+ for col in needed_collectors[len(stack):]:
+ stack.append(col)
+ # if col.name == "()":
+ # continue
+ indent = (len(stack) - 1) * " "
+ self._tw.line("%s%s" % (indent, col))
+
+ @pytest.hookimpl(hookwrapper=True)
+ def pytest_sessionfinish(self, exitstatus):
+ outcome = yield
+ outcome.get_result()
+ self._tw.line("")
+ summary_exit_codes = (
+ EXIT_OK, EXIT_TESTSFAILED, EXIT_INTERRUPTED, EXIT_USAGEERROR,
+ EXIT_NOTESTSCOLLECTED)
+ if exitstatus in summary_exit_codes:
+ self.config.hook.pytest_terminal_summary(terminalreporter=self,
+ exitstatus=exitstatus)
+ self.summary_errors()
+ self.summary_failures()
+ self.summary_warnings()
+ self.summary_passes()
+ if exitstatus == EXIT_INTERRUPTED:
+ self._report_keyboardinterrupt()
+ del self._keyboardinterrupt_memo
+ self.summary_deselected()
+ self.summary_stats()
+
+ def pytest_keyboard_interrupt(self, excinfo):
+ self._keyboardinterrupt_memo = excinfo.getrepr(funcargs=True)
+
+ def pytest_unconfigure(self):
+ if hasattr(self, '_keyboardinterrupt_memo'):
+ self._report_keyboardinterrupt()
+
+ def _report_keyboardinterrupt(self):
+ excrepr = self._keyboardinterrupt_memo
+ msg = excrepr.reprcrash.message
+ self.write_sep("!", msg)
+ if "KeyboardInterrupt" in msg:
+ if self.config.option.fulltrace:
+ excrepr.toterminal(self._tw)
+ else:
+ self._tw.line("to show a full traceback on KeyboardInterrupt use --fulltrace", yellow=True)
+ excrepr.reprcrash.toterminal(self._tw)
+
+ def _locationline(self, nodeid, fspath, lineno, domain):
+ def mkrel(nodeid):
+ line = self.config.cwd_relative_nodeid(nodeid)
+ if domain and line.endswith(domain):
+ line = line[:-len(domain)]
+ values = domain.split("[")
+ values[0] = values[0].replace('.', '::') # don't replace '.' in params
+ line += "[".join(values)
+ return line
+ # collect_fspath comes from testid which has a "/"-normalized path
+
+ if fspath:
+ res = mkrel(nodeid).replace("::()", "") # parens-normalization
+ if nodeid.split("::")[0] != fspath.replace("\\", nodes.SEP):
+ res += " <- " + self.startdir.bestrelpath(fspath)
+ else:
+ res = "[location]"
+ return res + " "
+
+ def _getfailureheadline(self, rep):
+ if hasattr(rep, 'location'):
+ fspath, lineno, domain = rep.location
+ return domain
+ else:
+ return "test session" # XXX?
+
+ def _getcrashline(self, rep):
+ try:
+ return str(rep.longrepr.reprcrash)
+ except AttributeError:
+ try:
+ return str(rep.longrepr)[:50]
+ except AttributeError:
+ return ""
+
+ #
+ # summaries for sessionfinish
+ #
+ def getreports(self, name):
+ values = []
+ for x in self.stats.get(name, []):
+ if not hasattr(x, '_pdbshown'):
+ values.append(x)
+ return values
+
+ def summary_warnings(self):
+ if self.hasopt("w"):
+ all_warnings = self.stats.get("warnings")
+ if not all_warnings:
+ return
+
+ grouped = itertools.groupby(all_warnings, key=lambda wr: wr.get_location(self.config))
+
+ self.write_sep("=", "warnings summary", yellow=True, bold=False)
+ for location, warning_records in grouped:
+ self._tw.line(str(location) or '<undetermined location>')
+ for w in warning_records:
+ lines = w.message.splitlines()
+ indented = '\n'.join(' ' + x for x in lines)
+ self._tw.line(indented)
+ self._tw.line()
+ self._tw.line('-- Docs: http://doc.pytest.org/en/latest/warnings.html')
+
+ def summary_passes(self):
+ if self.config.option.tbstyle != "no":
+ if self.hasopt("P"):
+ reports = self.getreports('passed')
+ if not reports:
+ return
+ self.write_sep("=", "PASSES")
+ for rep in reports:
+ msg = self._getfailureheadline(rep)
+ self.write_sep("_", msg)
+ self._outrep_summary(rep)
+
+ def print_teardown_sections(self, rep):
+ for secname, content in rep.sections:
+ if 'teardown' in secname:
+ self._tw.sep('-', secname)
+ if content[-1:] == "\n":
+ content = content[:-1]
+ self._tw.line(content)
+
+ def summary_failures(self):
+ if self.config.option.tbstyle != "no":
+ reports = self.getreports('failed')
+ if not reports:
+ return
+ self.write_sep("=", "FAILURES")
+ for rep in reports:
+ if self.config.option.tbstyle == "line":
+ line = self._getcrashline(rep)
+ self.write_line(line)
+ else:
+ msg = self._getfailureheadline(rep)
+ markup = {'red': True, 'bold': True}
+ self.write_sep("_", msg, **markup)
+ self._outrep_summary(rep)
+ for report in self.getreports(''):
+ if report.nodeid == rep.nodeid and report.when == 'teardown':
+ self.print_teardown_sections(report)
+
+ def summary_errors(self):
+ if self.config.option.tbstyle != "no":
+ reports = self.getreports('error')
+ if not reports:
+ return
+ self.write_sep("=", "ERRORS")
+ for rep in self.stats['error']:
+ msg = self._getfailureheadline(rep)
+ if not hasattr(rep, 'when'):
+ # collect
+ msg = "ERROR collecting " + msg
+ elif rep.when == "setup":
+ msg = "ERROR at setup of " + msg
+ elif rep.when == "teardown":
+ msg = "ERROR at teardown of " + msg
+ self.write_sep("_", msg)
+ self._outrep_summary(rep)
+
+ def _outrep_summary(self, rep):
+ rep.toterminal(self._tw)
+ for secname, content in rep.sections:
+ self._tw.sep("-", secname)
+ if content[-1:] == "\n":
+ content = content[:-1]
+ self._tw.line(content)
+
+ def summary_stats(self):
+ session_duration = time.time() - self._sessionstarttime
+ (line, color) = build_summary_stats_line(self.stats)
+ msg = "%s in %.2f seconds" % (line, session_duration)
+ markup = {color: True, 'bold': True}
+
+ if self.verbosity >= 0:
+ self.write_sep("=", msg, **markup)
+ if self.verbosity == -1:
+ self.write_line(msg, **markup)
+
+ def summary_deselected(self):
+ if 'deselected' in self.stats:
+ self.write_sep("=", "%d tests deselected" % (
+ len(self.stats['deselected'])), bold=True)
+
+
+def repr_pythonversion(v=None):
+ if v is None:
+ v = sys.version_info
+ try:
+ return "%s.%s.%s-%s-%s" % v
+ except (TypeError, ValueError):
+ return str(v)
+
+
+def flatten(values):
+ for x in values:
+ if isinstance(x, (list, tuple)):
+ for y in flatten(x):
+ yield y
+ else:
+ yield x
+
+
+def build_summary_stats_line(stats):
+ keys = ("failed passed skipped deselected "
+ "xfailed xpassed warnings error").split()
+ unknown_key_seen = False
+ for key in stats.keys():
+ if key not in keys:
+ if key: # setup/teardown reports have an empty key, ignore them
+ keys.append(key)
+ unknown_key_seen = True
+ parts = []
+ for key in keys:
+ val = stats.get(key, None)
+ if val:
+ parts.append("%d %s" % (len(val), key))
+
+ if parts:
+ line = ", ".join(parts)
+ else:
+ line = "no tests ran"
+
+ if 'failed' in stats or 'error' in stats:
+ color = 'red'
+ elif 'warnings' in stats or unknown_key_seen:
+ color = 'yellow'
+ elif 'passed' in stats:
+ color = 'green'
+ else:
+ color = 'yellow'
+
+ return (line, color)
+
+
+def _plugin_nameversions(plugininfo):
+ values = []
+ for plugin, dist in plugininfo:
+ # gets us name and version!
+ name = '{dist.project_name}-{dist.version}'.format(dist=dist)
+ # questionable convenience, but it keeps things short
+ if name.startswith("pytest-"):
+ name = name[7:]
+ # we decided to print python package names
+ # they can have more than one plugin
+ if name not in values:
+ values.append(name)
+ return values
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/tmpdir.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/tmpdir.py
new file mode 100644
index 00000000000..da1b032237a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/tmpdir.py
@@ -0,0 +1,126 @@
+""" support for providing temporary directories to test functions. """
+from __future__ import absolute_import, division, print_function
+
+import re
+
+import pytest
+import py
+from _pytest.monkeypatch import MonkeyPatch
+
+
+class TempdirFactory:
+ """Factory for temporary directories under the common base temp directory.
+
+ The base directory can be configured using the ``--basetemp`` option.
+ """
+
+ def __init__(self, config):
+ self.config = config
+ self.trace = config.trace.get("tmpdir")
+
+ def ensuretemp(self, string, dir=1):
+ """ (deprecated) return temporary directory path with
+ the given string as the trailing part. It is usually
+ better to use the 'tmpdir' function argument which
+ provides an empty unique-per-test-invocation directory
+ and is guaranteed to be empty.
+ """
+ # py.log._apiwarn(">1.1", "use tmpdir function argument")
+ return self.getbasetemp().ensure(string, dir=dir)
+
+ def mktemp(self, basename, numbered=True):
+ """Create a subdirectory of the base temporary directory and return it.
+ If ``numbered``, ensure the directory is unique by adding a number
+ prefix greater than any existing one.
+ """
+ basetemp = self.getbasetemp()
+ if not numbered:
+ p = basetemp.mkdir(basename)
+ else:
+ p = py.path.local.make_numbered_dir(prefix=basename,
+ keep=0, rootdir=basetemp, lock_timeout=None)
+ self.trace("mktemp", p)
+ return p
+
+ def getbasetemp(self):
+ """ return base temporary directory. """
+ try:
+ return self._basetemp
+ except AttributeError:
+ basetemp = self.config.option.basetemp
+ if basetemp:
+ basetemp = py.path.local(basetemp)
+ if basetemp.check():
+ basetemp.remove()
+ basetemp.mkdir()
+ else:
+ temproot = py.path.local.get_temproot()
+ user = get_user()
+ if user:
+ # use a sub-directory in the temproot to speed-up
+ # make_numbered_dir() call
+ rootdir = temproot.join('pytest-of-%s' % user)
+ else:
+ rootdir = temproot
+ rootdir.ensure(dir=1)
+ basetemp = py.path.local.make_numbered_dir(prefix='pytest-',
+ rootdir=rootdir)
+ self._basetemp = t = basetemp.realpath()
+ self.trace("new basetemp", t)
+ return t
+
+ def finish(self):
+ self.trace("finish")
+
+
+def get_user():
+ """Return the current user name, or None if getuser() does not work
+ in the current environment (see #1010).
+ """
+ import getpass
+ try:
+ return getpass.getuser()
+ except (ImportError, KeyError):
+ return None
+
+
+# backward compatibility
+TempdirHandler = TempdirFactory
+
+
+def pytest_configure(config):
+ """Create a TempdirFactory and attach it to the config object.
+
+ This is to comply with existing plugins which expect the handler to be
+ available at pytest_configure time, but ideally should be moved entirely
+ to the tmpdir_factory session fixture.
+ """
+ mp = MonkeyPatch()
+ t = TempdirFactory(config)
+ config._cleanup.extend([mp.undo, t.finish])
+ mp.setattr(config, '_tmpdirhandler', t, raising=False)
+ mp.setattr(pytest, 'ensuretemp', t.ensuretemp, raising=False)
+
+
+@pytest.fixture(scope='session')
+def tmpdir_factory(request):
+ """Return a TempdirFactory instance for the test session.
+ """
+ return request.config._tmpdirhandler
+
+
+@pytest.fixture
+def tmpdir(request, tmpdir_factory):
+ """Return a temporary directory path object
+ which is unique to each test function invocation,
+ created as a sub directory of the base temporary
+ directory. The returned object is a `py.path.local`_
+ path object.
+ """
+ name = request.node.name
+ name = re.sub(r"[\W]", "_", name)
+ MAXVAL = 30
+ if len(name) > MAXVAL:
+ name = name[:MAXVAL]
+ x = tmpdir_factory.mktemp(name, numbered=True)
+ return x
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/unittest.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/unittest.py
new file mode 100644
index 00000000000..3ddb39495e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/unittest.py
@@ -0,0 +1,237 @@
+""" discovery and running of std-library "unittest" style tests. """
+from __future__ import absolute_import, division, print_function
+
+import sys
+import traceback
+
+# for transferring markers
+import _pytest._code
+from _pytest.config import hookimpl
+from _pytest.outcomes import fail, skip, xfail
+from _pytest.python import transfer_markers, Class, Module, Function
+
+
+def pytest_pycollect_makeitem(collector, name, obj):
+ # has unittest been imported and is obj a subclass of its TestCase?
+ try:
+ if not issubclass(obj, sys.modules["unittest"].TestCase):
+ return
+ except Exception:
+ return
+ # yes, so let's collect it
+ return UnitTestCase(name, parent=collector)
+
+
+class UnitTestCase(Class):
+ # marker for fixturemanger.getfixtureinfo()
+ # to declare that our children do not support funcargs
+ nofuncargs = True
+
+ def setup(self):
+ cls = self.obj
+ if getattr(cls, '__unittest_skip__', False):
+ return # skipped
+ setup = getattr(cls, 'setUpClass', None)
+ if setup is not None:
+ setup()
+ teardown = getattr(cls, 'tearDownClass', None)
+ if teardown is not None:
+ self.addfinalizer(teardown)
+ super(UnitTestCase, self).setup()
+
+ def collect(self):
+ from unittest import TestLoader
+ cls = self.obj
+ if not getattr(cls, "__test__", True):
+ return
+ self.session._fixturemanager.parsefactories(self, unittest=True)
+ loader = TestLoader()
+ module = self.getparent(Module).obj
+ foundsomething = False
+ for name in loader.getTestCaseNames(self.obj):
+ x = getattr(self.obj, name)
+ if not getattr(x, '__test__', True):
+ continue
+ funcobj = getattr(x, 'im_func', x)
+ transfer_markers(funcobj, cls, module)
+ yield TestCaseFunction(name, parent=self)
+ foundsomething = True
+
+ if not foundsomething:
+ runtest = getattr(self.obj, 'runTest', None)
+ if runtest is not None:
+ ut = sys.modules.get("twisted.trial.unittest", None)
+ if ut is None or runtest != ut.TestCase.runTest:
+ yield TestCaseFunction('runTest', parent=self)
+
+
+class TestCaseFunction(Function):
+ _excinfo = None
+
+ def setup(self):
+ self._testcase = self.parent.obj(self.name)
+ self._fix_unittest_skip_decorator()
+ self._obj = getattr(self._testcase, self.name)
+ if hasattr(self._testcase, 'setup_method'):
+ self._testcase.setup_method(self._obj)
+ if hasattr(self, "_request"):
+ self._request._fillfixtures()
+
+ def _fix_unittest_skip_decorator(self):
+ """
+ The @unittest.skip decorator calls functools.wraps(self._testcase)
+ The call to functools.wraps() fails unless self._testcase
+ has a __name__ attribute. This is usually automatically supplied
+ if the test is a function or method, but we need to add manually
+ here.
+
+ See issue #1169
+ """
+ if sys.version_info[0] == 2:
+ setattr(self._testcase, "__name__", self.name)
+
+ def teardown(self):
+ if hasattr(self._testcase, 'teardown_method'):
+ self._testcase.teardown_method(self._obj)
+ # Allow garbage collection on TestCase instance attributes.
+ self._testcase = None
+ self._obj = None
+
+ def startTest(self, testcase):
+ pass
+
+ def _addexcinfo(self, rawexcinfo):
+ # unwrap potential exception info (see twisted trial support below)
+ rawexcinfo = getattr(rawexcinfo, '_rawexcinfo', rawexcinfo)
+ try:
+ excinfo = _pytest._code.ExceptionInfo(rawexcinfo)
+ except TypeError:
+ try:
+ try:
+ values = traceback.format_exception(*rawexcinfo)
+ values.insert(0, "NOTE: Incompatible Exception Representation, "
+ "displaying natively:\n\n")
+ fail("".join(values), pytrace=False)
+ except (fail.Exception, KeyboardInterrupt):
+ raise
+ except: # noqa
+ fail("ERROR: Unknown Incompatible Exception "
+ "representation:\n%r" % (rawexcinfo,), pytrace=False)
+ except KeyboardInterrupt:
+ raise
+ except fail.Exception:
+ excinfo = _pytest._code.ExceptionInfo()
+ self.__dict__.setdefault('_excinfo', []).append(excinfo)
+
+ def addError(self, testcase, rawexcinfo):
+ self._addexcinfo(rawexcinfo)
+
+ def addFailure(self, testcase, rawexcinfo):
+ self._addexcinfo(rawexcinfo)
+
+ def addSkip(self, testcase, reason):
+ try:
+ skip(reason)
+ except skip.Exception:
+ self._skipped_by_mark = True
+ self._addexcinfo(sys.exc_info())
+
+ def addExpectedFailure(self, testcase, rawexcinfo, reason=""):
+ try:
+ xfail(str(reason))
+ except xfail.Exception:
+ self._addexcinfo(sys.exc_info())
+
+ def addUnexpectedSuccess(self, testcase, reason=""):
+ self._unexpectedsuccess = reason
+
+ def addSuccess(self, testcase):
+ pass
+
+ def stopTest(self, testcase):
+ pass
+
+ def _handle_skip(self):
+ # implements the skipping machinery (see #2137)
+ # analog to pythons Lib/unittest/case.py:run
+ testMethod = getattr(self._testcase, self._testcase._testMethodName)
+ if (getattr(self._testcase.__class__, "__unittest_skip__", False) or
+ getattr(testMethod, "__unittest_skip__", False)):
+ # If the class or method was skipped.
+ skip_why = (getattr(self._testcase.__class__, '__unittest_skip_why__', '') or
+ getattr(testMethod, '__unittest_skip_why__', ''))
+ try: # PY3, unittest2 on PY2
+ self._testcase._addSkip(self, self._testcase, skip_why)
+ except TypeError: # PY2
+ if sys.version_info[0] != 2:
+ raise
+ self._testcase._addSkip(self, skip_why)
+ return True
+ return False
+
+ def runtest(self):
+ if self.config.pluginmanager.get_plugin("pdbinvoke") is None:
+ self._testcase(result=self)
+ else:
+ # disables tearDown and cleanups for post mortem debugging (see #1890)
+ if self._handle_skip():
+ return
+ self._testcase.debug()
+
+ def _prunetraceback(self, excinfo):
+ Function._prunetraceback(self, excinfo)
+ traceback = excinfo.traceback.filter(
+ lambda x: not x.frame.f_globals.get('__unittest'))
+ if traceback:
+ excinfo.traceback = traceback
+
+
+@hookimpl(tryfirst=True)
+def pytest_runtest_makereport(item, call):
+ if isinstance(item, TestCaseFunction):
+ if item._excinfo:
+ call.excinfo = item._excinfo.pop(0)
+ try:
+ del call.result
+ except AttributeError:
+ pass
+
+# twisted trial support
+
+
+@hookimpl(hookwrapper=True)
+def pytest_runtest_protocol(item):
+ if isinstance(item, TestCaseFunction) and \
+ 'twisted.trial.unittest' in sys.modules:
+ ut = sys.modules['twisted.python.failure']
+ Failure__init__ = ut.Failure.__init__
+ check_testcase_implements_trial_reporter()
+
+ def excstore(self, exc_value=None, exc_type=None, exc_tb=None,
+ captureVars=None):
+ if exc_value is None:
+ self._rawexcinfo = sys.exc_info()
+ else:
+ if exc_type is None:
+ exc_type = type(exc_value)
+ self._rawexcinfo = (exc_type, exc_value, exc_tb)
+ try:
+ Failure__init__(self, exc_value, exc_type, exc_tb,
+ captureVars=captureVars)
+ except TypeError:
+ Failure__init__(self, exc_value, exc_type, exc_tb)
+
+ ut.Failure.__init__ = excstore
+ yield
+ ut.Failure.__init__ = Failure__init__
+ else:
+ yield
+
+
+def check_testcase_implements_trial_reporter(done=[]):
+ if done:
+ return
+ from zope.interface import classImplements
+ from twisted.trial.itrial import IReporter
+ classImplements(TestCaseFunction, IReporter)
+ done.append(1)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/warnings.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/warnings.py
new file mode 100644
index 00000000000..3c2b1914fb6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/_pytest/warnings.py
@@ -0,0 +1,96 @@
+from __future__ import absolute_import, division, print_function
+
+import warnings
+from contextlib import contextmanager
+
+import pytest
+
+from _pytest import compat
+
+
+def _setoption(wmod, arg):
+ """
+ Copy of the warning._setoption function but does not escape arguments.
+ """
+ parts = arg.split(':')
+ if len(parts) > 5:
+ raise wmod._OptionError("too many fields (max 5): %r" % (arg,))
+ while len(parts) < 5:
+ parts.append('')
+ action, message, category, module, lineno = [s.strip()
+ for s in parts]
+ action = wmod._getaction(action)
+ category = wmod._getcategory(category)
+ if lineno:
+ try:
+ lineno = int(lineno)
+ if lineno < 0:
+ raise ValueError
+ except (ValueError, OverflowError):
+ raise wmod._OptionError("invalid lineno %r" % (lineno,))
+ else:
+ lineno = 0
+ wmod.filterwarnings(action, message, category, module, lineno)
+
+
+def pytest_addoption(parser):
+ group = parser.getgroup("pytest-warnings")
+ group.addoption(
+ '-W', '--pythonwarnings', action='append',
+ help="set which warnings to report, see -W option of python itself.")
+ parser.addini("filterwarnings", type="linelist",
+ help="Each line specifies a pattern for "
+ "warnings.filterwarnings. "
+ "Processed after -W and --pythonwarnings.")
+
+
+@contextmanager
+def catch_warnings_for_item(item):
+ """
+ catches the warnings generated during setup/call/teardown execution
+ of the given item and after it is done posts them as warnings to this
+ item.
+ """
+ args = item.config.getoption('pythonwarnings') or []
+ inifilters = item.config.getini("filterwarnings")
+ with warnings.catch_warnings(record=True) as log:
+ for arg in args:
+ warnings._setoption(arg)
+
+ for arg in inifilters:
+ _setoption(warnings, arg)
+
+ mark = item.get_marker('filterwarnings')
+ if mark:
+ for arg in mark.args:
+ warnings._setoption(arg)
+
+ yield
+
+ for warning in log:
+ warn_msg = warning.message
+ unicode_warning = False
+
+ if compat._PY2 and any(isinstance(m, compat.UNICODE_TYPES) for m in warn_msg.args):
+ new_args = []
+ for m in warn_msg.args:
+ new_args.append(compat.ascii_escaped(m) if isinstance(m, compat.UNICODE_TYPES) else m)
+ unicode_warning = list(warn_msg.args) != new_args
+ warn_msg.args = new_args
+
+ msg = warnings.formatwarning(
+ warn_msg, warning.category,
+ warning.filename, warning.lineno, warning.line)
+ item.warn("unused", msg)
+
+ if unicode_warning:
+ warnings.warn(
+ "Warning is using unicode non convertible to ascii, "
+ "converting to a safe representation:\n %s" % msg,
+ UnicodeWarning)
+
+
+@pytest.hookimpl(hookwrapper=True)
+def pytest_runtest_protocol(item):
+ with catch_warnings_for_item(item):
+ yield
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/appveyor.yml b/tests/wpt/web-platform-tests/tools/third_party/pytest/appveyor.yml
new file mode 100644
index 00000000000..4f4afe15c38
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/appveyor.yml
@@ -0,0 +1,44 @@
+environment:
+ COVERALLS_REPO_TOKEN:
+ secure: 2NJ5Ct55cHJ9WEg3xbSqCuv0rdgzzb6pnzOIG5OkMbTndw3wOBrXntWFoQrXiMFi
+ # this is pytest's token in coveralls.io, encrypted
+ # using pytestbot account as detailed here:
+ # https://www.appveyor.com/docs/build-configuration#secure-variables
+
+ matrix:
+ # coveralls is not in the default env list
+ - TOXENV: "coveralls"
+ # note: please use "tox --listenvs" to populate the build matrix below
+ - TOXENV: "linting"
+ - TOXENV: "py27"
+ - TOXENV: "py34"
+ - TOXENV: "py35"
+ - TOXENV: "py36"
+ - TOXENV: "pypy"
+ - TOXENV: "py27-pexpect"
+ - TOXENV: "py27-xdist"
+ - TOXENV: "py27-trial"
+ - TOXENV: "py27-numpy"
+ - TOXENV: "py27-pluggymaster"
+ - TOXENV: "py36-pexpect"
+ - TOXENV: "py36-xdist"
+ - TOXENV: "py36-trial"
+ - TOXENV: "py36-numpy"
+ - TOXENV: "py36-pluggymaster"
+ - TOXENV: "py27-nobyte"
+ - TOXENV: "doctesting"
+ - TOXENV: "py35-freeze"
+ - TOXENV: "docs"
+
+install:
+ - echo Installed Pythons
+ - dir c:\Python*
+
+ - if "%TOXENV%" == "pypy" call scripts\install-pypy.bat
+
+ - C:\Python36\python -m pip install --upgrade --pre tox
+
+build: false # Not a C# project, build stuff at the test step instead.
+
+test_script:
+ - call scripts\call-tox.bat
diff --git a/tests/wpt/web-platform-tests/tools/pytest/bench/bench.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/bench/bench.py
index ce94964172f..ce94964172f 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/bench/bench.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/bench/bench.py
diff --git a/tests/wpt/web-platform-tests/tools/pytest/bench/bench_argcomplete.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/bench/bench_argcomplete.py
index d66c664f346..d66c664f346 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/bench/bench_argcomplete.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/bench/bench_argcomplete.py
diff --git a/tests/wpt/web-platform-tests/tools/pytest/bench/empty.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/bench/empty.py
index ac5e25701da..ac5e25701da 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/bench/empty.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/bench/empty.py
diff --git a/tests/wpt/web-platform-tests/tools/pytest/bench/manyparam.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/bench/manyparam.py
index d2bca0e8acd..d2bca0e8acd 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/bench/manyparam.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/bench/manyparam.py
diff --git a/tests/wpt/web-platform-tests/tools/pytest/bench/skip.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/bench/skip.py
index 960b308645a..960b308645a 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/bench/skip.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/bench/skip.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2920.bugfix b/tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2920.bugfix
new file mode 100644
index 00000000000..9c5217278ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2920.bugfix
@@ -0,0 +1 @@
+Fix issue about ``-p no:<plugin>`` having no effect.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2949.trivial b/tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2949.trivial
new file mode 100644
index 00000000000..39789e72b7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2949.trivial
@@ -0,0 +1 @@
+Update github "bugs" link in CONTRIBUTING.rst
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2956.bugfix b/tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2956.bugfix
new file mode 100644
index 00000000000..13717657bf1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2956.bugfix
@@ -0,0 +1 @@
+Fix regression with warnings that contained non-strings in their arguments in Python 2.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2957.bugfix b/tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2957.bugfix
new file mode 100644
index 00000000000..589665b692a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2957.bugfix
@@ -0,0 +1 @@
+Always escape null bytes when setting ``PYTEST_CURRENT_TEST``.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2963.doc b/tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2963.doc
new file mode 100644
index 00000000000..c9a1d661b64
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2963.doc
@@ -0,0 +1 @@
+Fix broken link to plugin pytest-localserver.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2971.bugfix b/tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2971.bugfix
new file mode 100644
index 00000000000..36684e8c880
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2971.bugfix
@@ -0,0 +1 @@
+Fix ``ZeroDivisionError`` when using the ``testmon`` plugin when no tests were actually collected.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2984.bugfix b/tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2984.bugfix
new file mode 100644
index 00000000000..21f5748d523
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/2984.bugfix
@@ -0,0 +1 @@
+Bring back ``TerminalReporter.writer`` as an alias to ``TerminalReporter._tw``. This alias was removed by accident in the ``3.3.0`` release.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/_template.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/_template.rst
new file mode 100644
index 00000000000..a898abc15af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/changelog/_template.rst
@@ -0,0 +1,40 @@
+{% for section in sections %}
+{% set underline = "-" %}
+{% if section %}
+{{section}}
+{{ underline * section|length }}{% set underline = "~" %}
+
+{% endif %}
+{% if sections[section] %}
+{% for category, val in definitions.items() if category in sections[section] %}
+
+{{ definitions[category]['name'] }}
+{{ underline * definitions[category]['name']|length }}
+
+{% if definitions[category]['showcontent'] %}
+{% for text, values in sections[section][category]|dictsort(by='value') %}
+{% set issue_joiner = joiner(', ') %}
+- {{ text }}{% if category != 'vendor' %} ({% for value in values|sort %}{{ issue_joiner() }}`{{ value }} <https://github.com/pytest-dev/pytest/issues/{{ value[1:] }}>`_{% endfor %}){% endif %}
+
+
+{% endfor %}
+{% else %}
+- {{ sections[section][category]['']|sort|join(', ') }}
+
+
+{% endif %}
+{% if sections[section][category]|length == 0 %}
+
+No significant changes.
+
+
+{% else %}
+{% endif %}
+{% endfor %}
+{% else %}
+
+No significant changes.
+
+
+{% endif %}
+{% endfor %}
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/Makefile b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/Makefile
new file mode 100644
index 00000000000..fa8e8266a29
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/Makefile
@@ -0,0 +1,150 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = _build
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+REGENDOC_ARGS := \
+ --normalize "/in \d+.\d+ seconds/in 0.12 seconds/" \
+ --normalize "@/tmp/pytest-of-.*/pytest-\d+@PYTEST_TMPDIR@" \
+ --normalize "@pytest-(\d+)\\.[^ ,]+@pytest-\1.x.y@" \
+ --normalize "@(This is pytest version )(\d+)\\.[^ ,]+@\1\2.x.y@" \
+ --normalize "@py-(\d+)\\.[^ ,]+@py-\1.x.y@" \
+ --normalize "@pluggy-(\d+)\\.[.\d,]+@pluggy-\1.x.y@" \
+ --normalize "@hypothesis-(\d+)\\.[.\d,]+@hypothesis-\1.x.y@" \
+ --normalize "@Python (\d+)\\.[^ ,]+@Python \1.x.y@"
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
+
+
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " showtarget to show the pytest.org target directory"
+ @echo " install to install docs to pytest.org/SITETARGET"
+ @echo " install-ldf to install the doc pdf to pytest.org/SITETARGET"
+ @echo " regen to regenerate pytest examples using the installed pytest"
+ @echo " linkcheck to check all external links for integrity"
+
+clean:
+ -rm -rf $(BUILDDIR)/*
+
+regen:
+ PYTHONDONTWRITEBYTECODE=1 PYTEST_ADDOPT=-pno:hypothesis COLUMNS=76 regendoc --update *.rst */*.rst ${REGENDOC_ARGS}
+
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pytest.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pytest.qhc"
+
+devhelp:
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+ @echo
+ @echo "Build finished."
+ @echo "To view the help file:"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/pytest"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pytest"
+ @echo "# devhelp"
+
+epub:
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
+ "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ make -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+ @echo
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+ @echo
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
+
+texinfo:
+ mkdir -p $(BUILDDIR)/texinfo
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo
+ @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+ @echo "Run \`make' in that directory to run these through makeinfo" \
+ "(use \`make info' here to do that automatically)."
+
+info:
+ mkdir -p $(BUILDDIR)/texinfo
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo "Running Texinfo files through makeinfo..."
+ make -C $(BUILDDIR)/texinfo info
+ @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_templates/globaltoc.html b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_templates/globaltoc.html
new file mode 100644
index 00000000000..fdd4dd59b32
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_templates/globaltoc.html
@@ -0,0 +1,19 @@
+<h3><a href="{{ pathto(master_doc) }}">{{ _('Table Of Contents') }}</a></h3>
+
+<ul>
+ <li><a href="{{ pathto('index') }}">Home</a></li>
+ <li><a href="{{ pathto('contents') }}">Contents</a></li>
+ <li><a href="{{ pathto('getting-started') }}">Install</a></li>
+ <li><a href="{{ pathto('example/index') }}">Examples</a></li>
+ <li><a href="{{ pathto('customize') }}">Customize</a></li>
+ <li><a href="{{ pathto('contact') }}">Contact</a></li>
+ <li><a href="{{ pathto('talks') }}">Talks/Posts</a></li>
+ <li><a href="{{ pathto('changelog') }}">Changelog</a></li>
+ <li><a href="{{ pathto('backwards-compatibility') }}">Backwards Compatibility</a></li>
+ <li><a href="{{ pathto('license') }}">License</a></li>
+</ul>
+
+{%- if display_toc %}
+ <hr>
+ {{ toc }}
+{%- endif %}
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_templates/layout.html b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_templates/layout.html
new file mode 100644
index 00000000000..2fc8e2a7fb4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_templates/layout.html
@@ -0,0 +1,20 @@
+{% extends "!layout.html" %}
+{% block header %}
+ {{super()}}
+{% endblock %}
+{% block footer %}
+{{ super() }}
+<script type="text/javascript">
+
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', 'UA-7597274-13']);
+ _gaq.push(['_trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+
+</script>
+{% endblock %}
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_templates/links.html b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_templates/links.html
new file mode 100644
index 00000000000..d855a013f34
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_templates/links.html
@@ -0,0 +1,11 @@
+<h3>Useful Links</h3>
+<ul>
+ <li><a href="{{ pathto('index') }}">The pytest Website</a></li>
+ <li><a href="{{ pathto('contributing') }}">Contribution Guide</a></li>
+ <li><a href="https://pypi.python.org/pypi/pytest">pytest @ PyPI</a></li>
+ <li><a href="https://github.com/pytest-dev/pytest/">pytest @ GitHub</a></li>
+ <li><a href="http://plugincompat.herokuapp.com/">3rd party plugins</a></li>
+ <li><a href="https://github.com/pytest-dev/pytest/issues">Issue Tracker</a></li>
+ <li><a href="https://media.readthedocs.org/pdf/pytest/latest/pytest.pdf">PDF Documentation</a>
+</ul>
+
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/_templates/sidebarintro.html b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_templates/sidebarintro.html
index ae860c172f0..ae860c172f0 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/_templates/sidebarintro.html
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_templates/sidebarintro.html
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/_themes/.gitignore b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_themes/.gitignore
index 66b6e4c2f3b..66b6e4c2f3b 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/_themes/.gitignore
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_themes/.gitignore
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/_themes/LICENSE b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_themes/LICENSE
index 8daab7ee6ef..8daab7ee6ef 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/_themes/LICENSE
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_themes/LICENSE
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/_themes/README b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_themes/README
index b3292bdff8e..b3292bdff8e 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/_themes/README
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_themes/README
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/_themes/flask/layout.html b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_themes/flask/layout.html
index 19c43fbbefc..19c43fbbefc 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/_themes/flask/layout.html
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_themes/flask/layout.html
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/_themes/flask/relations.html b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_themes/flask/relations.html
index 3bbcde85bb4..3bbcde85bb4 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/_themes/flask/relations.html
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_themes/flask/relations.html
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/_themes/flask/static/flasky.css_t b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_themes/flask/static/flasky.css_t
index 6b593da299a..6b593da299a 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/_themes/flask/static/flasky.css_t
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_themes/flask/static/flasky.css_t
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/_themes/flask/theme.conf b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_themes/flask/theme.conf
index 18c720f804c..18c720f804c 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/_themes/flask/theme.conf
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_themes/flask/theme.conf
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/_themes/flask_theme_support.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_themes/flask_theme_support.py
index 33f47449c11..33f47449c11 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/_themes/flask_theme_support.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/_themes/flask_theme_support.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/adopt.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/adopt.rst
new file mode 100644
index 00000000000..710f431be30
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/adopt.rst
@@ -0,0 +1,82 @@
+:orphan:
+
+.. warnings about this file not being included in any toctree will be suppressed by :orphan:
+
+
+April 2015 is "adopt pytest month"
+=============================================
+
+Are you an enthusiastic pytest user, the local testing guru in your workplace? Or are you considering using pytest for your open source project, but not sure how to get started? Then you may be interested in "adopt pytest month"!
+
+We will pair experienced pytest users with open source projects, for a month's effort of getting new development teams started with pytest.
+
+In 2015 we are trying this for the first time. In February and March 2015 we will gather volunteers on both sides, in April we will do the work, and in May we will evaluate how it went. This effort is being coordinated by Brianna Laugher. If you have any questions or comments, you can raise them on the `@pytestdotorg twitter account <https://twitter.com/pytestdotorg>`_ the `issue tracker`_ or the `pytest-dev mailing list`_.
+
+
+.. _`issue tracker`: https://github.com/pytest-dev/pytest/issues/676
+.. _`pytest-dev mailing list`: https://mail.python.org/mailman/listinfo/pytest-dev
+
+
+The ideal pytest helper
+-----------------------------------------
+
+ - will be able to commit 2-4 hours a week to working with their particular project (this might involve joining their mailing list, installing the software and exploring any existing tests, offering advice, writing some example tests)
+ - feels confident in using pytest (e.g. has explored command line options, knows how to write parametrized tests, has an idea about conftest contents)
+ - does not need to be an expert in every aspect!
+
+`Pytest helpers, sign up here`_! (preferably in February, hard deadline 22 March)
+
+
+.. _`Pytest helpers, sign up here`: http://goo.gl/forms/nxqAhqWt1P
+
+
+The ideal partner project
+-----------------------------------------
+
+ - is open source, and predominantly written in Python
+ - has an automated/documented install process for developers
+ - has more than one core developer
+ - has at least one official release (e.g. is available on pypi)
+ - has the support of the core development team, in trying out pytest adoption
+ - has no tests... or 100% test coverage... or somewhere in between!
+
+`Partner projects, sign up here`_! (by 22 March)
+
+
+.. _`Partner projects, sign up here`: http://goo.gl/forms/ZGyqlHiwk3
+
+
+What does it mean to "adopt pytest"?
+-----------------------------------------
+
+There can be many different definitions of "success". Pytest can run many `nose and unittest`_ tests by default, so using pytest as your testrunner may be possible from day 1. Job done, right?
+
+Progressive success might look like:
+
+ - tests can be run (by pytest) without errors (there may be failures)
+ - tests can be run (by pytest) without failures
+ - test runner is integrated into CI server
+ - existing tests are rewritten to take advantage of pytest features - this can happen in several iterations, for example:
+ - changing to native assert_ statements (pycmd_ has a script to help with that, ``pyconvert_unittest.py``)
+ - changing `setUp/tearDown methods`_ to fixtures_
+ - adding markers_
+ - other changes to reduce boilerplate
+ - assess needs for future tests to be written, e.g. new fixtures, distributed_ testing tweaks
+
+"Success" should also include that the development team feels comfortable with their knowledge of how to use pytest. In fact this is probably more important than anything else. So spending a lot of time on communication, giving examples, etc will probably be important - both in running the tests, and in writing them.
+
+It may be after the month is up, the partner project decides that pytest is not right for it. That's okay - hopefully the pytest team will also learn something about its weaknesses or deficiencies.
+
+.. _`nose and unittest`: faq.html#how-does-pytest-relate-to-nose-and-unittest
+.. _assert: asserts.html
+.. _pycmd: https://bitbucket.org/hpk42/pycmd/overview
+.. _`setUp/tearDown methods`: xunit_setup.html
+.. _fixtures: fixture.html
+.. _markers: markers.html
+.. _distributed: xdist.html
+
+
+Other ways to help
+-----------------------------------------
+
+Promote! Do your favourite open source Python projects use pytest? If not, why not tell them about this page?
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/index.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/index.rst
new file mode 100644
index 00000000000..1a5f3760b68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/index.rst
@@ -0,0 +1,68 @@
+
+Release announcements
+===========================================
+
+.. toctree::
+ :maxdepth: 2
+
+
+ release-3.3.0
+ release-3.2.5
+ release-3.2.4
+ release-3.2.3
+ release-3.2.2
+ release-3.2.1
+ release-3.2.0
+ release-3.1.3
+ release-3.1.2
+ release-3.1.1
+ release-3.1.0
+ release-3.0.7
+ release-3.0.6
+ release-3.0.5
+ release-3.0.4
+ release-3.0.3
+ release-3.0.2
+ release-3.0.1
+ release-3.0.0
+ sprint2016
+ release-2.9.2
+ release-2.9.1
+ release-2.9.0
+ release-2.8.7
+ release-2.8.6
+ release-2.8.5
+ release-2.8.4
+ release-2.8.3
+ release-2.8.2
+ release-2.7.2
+ release-2.7.1
+ release-2.7.0
+ release-2.6.3
+ release-2.6.2
+ release-2.6.1
+ release-2.6.0
+ release-2.5.2
+ release-2.5.1
+ release-2.5.0
+ release-2.4.2
+ release-2.4.1
+ release-2.4.0
+ release-2.3.5
+ release-2.3.4
+ release-2.3.3
+ release-2.3.2
+ release-2.3.1
+ release-2.3.0
+ release-2.2.4
+ release-2.2.2
+ release-2.2.1
+ release-2.2.0
+ release-2.1.3
+ release-2.1.2
+ release-2.1.1
+ release-2.1.0
+ release-2.0.3
+ release-2.0.2
+ release-2.0.1
+ release-2.0.0
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.0.0.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.0.0.rst
index af745fc59b2..af745fc59b2 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.0.0.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.0.0.rst
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.0.1.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.0.1.rst
index 2f41ef9435e..2f41ef9435e 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.0.1.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.0.1.rst
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.0.2.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.0.2.rst
new file mode 100644
index 00000000000..f1f44f34f4f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.0.2.rst
@@ -0,0 +1,73 @@
+py.test 2.0.2: bug fixes, improved xfail/skip expressions, speed ups
+===========================================================================
+
+Welcome to pytest-2.0.2, a maintenance and bug fix release of pytest,
+a mature testing tool for Python, supporting CPython 2.4-3.2, Jython
+and latest PyPy interpreters. See the extensive docs with tested examples here:
+
+ http://pytest.org/
+
+If you want to install or upgrade pytest, just type one of::
+
+ pip install -U pytest # or
+ easy_install -U pytest
+
+Many thanks to all issue reporters and people asking questions
+or complaining, particularly Jurko for his insistence,
+Laura, Victor and Brianna for helping with improving
+and Ronny for his general advise.
+
+best,
+holger krekel
+
+Changes between 2.0.1 and 2.0.2
+----------------------------------------------
+
+- tackle issue32 - speed up test runs of very quick test functions
+ by reducing the relative overhead
+
+- fix issue30 - extended xfail/skipif handling and improved reporting.
+ If you have a syntax error in your skip/xfail
+ expressions you now get nice error reports.
+
+ Also you can now access module globals from xfail/skipif
+ expressions so that this for example works now::
+
+ import pytest
+ import mymodule
+ @pytest.mark.skipif("mymodule.__version__[0] == "1")
+ def test_function():
+ pass
+
+ This will not run the test function if the module's version string
+ does not start with a "1". Note that specifying a string instead
+ of a boolean expressions allows py.test to report meaningful information
+ when summarizing a test run as to what conditions lead to skipping
+ (or xfail-ing) tests.
+
+- fix issue28 - setup_method and pytest_generate_tests work together
+ The setup_method fixture method now gets called also for
+ test function invocations generated from the pytest_generate_tests
+ hook.
+
+- fix issue27 - collectonly and keyword-selection (-k) now work together
+ Also, if you do "py.test --collectonly -q" you now get a flat list
+ of test ids that you can use to paste to the py.test commandline
+ in order to execute a particular test.
+
+- fix issue25 avoid reported problems with --pdb and python3.2/encodings output
+
+- fix issue23 - tmpdir argument now works on Python3.2 and WindowsXP
+ Starting with Python3.2 os.symlink may be supported. By requiring
+ a newer py lib version the py.path.local() implementation acknowledges
+ this.
+
+- fixed typos in the docs (thanks Victor Garcia, Brianna Laugher) and particular
+ thanks to Laura Creighton who also reviewed parts of the documentation.
+
+- fix slightly wrong output of verbose progress reporting for classes
+ (thanks Amaury)
+
+- more precise (avoiding of) deprecation warnings for node.Class|Function accesses
+
+- avoid std unittest assertion helper code in tracebacks (thanks Ronny)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.0.3.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.0.3.rst
new file mode 100644
index 00000000000..9bbfdaab361
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.0.3.rst
@@ -0,0 +1,40 @@
+py.test 2.0.3: bug fixes and speed ups
+===========================================================================
+
+Welcome to pytest-2.0.3, a maintenance and bug fix release of pytest,
+a mature testing tool for Python, supporting CPython 2.4-3.2, Jython
+and latest PyPy interpreters. See the extensive docs with tested examples here:
+
+ http://pytest.org/
+
+If you want to install or upgrade pytest, just type one of::
+
+ pip install -U pytest # or
+ easy_install -U pytest
+
+There also is a bugfix release 1.6 of pytest-xdist, the plugin
+that enables seamless distributed and "looponfail" testing for Python.
+
+best,
+holger krekel
+
+Changes between 2.0.2 and 2.0.3
+----------------------------------------------
+
+- fix issue38: nicer tracebacks on calls to hooks, particularly early
+ configure/sessionstart ones
+
+- fix missing skip reason/meta information in junitxml files, reported
+ via http://lists.idyll.org/pipermail/testing-in-python/2011-March/003928.html
+
+- fix issue34: avoid collection failure with "test" prefixed classes
+ deriving from object.
+
+- don't require zlib (and other libs) for genscript plugin without
+ --genscript actually being used.
+
+- speed up skips (by not doing a full traceback representation
+ internally)
+
+- fix issue37: avoid invalid characters in junitxml's output
+
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.1.0.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.1.0.rst
index 831548ac2ff..831548ac2ff 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.1.0.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.1.0.rst
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.1.1.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.1.1.rst
index ecdd69f4dc9..ecdd69f4dc9 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.1.1.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.1.1.rst
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.1.2.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.1.2.rst
index 51b7591d366..51b7591d366 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.1.2.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.1.2.rst
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.1.3.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.1.3.rst
index f4da60b8ba4..f4da60b8ba4 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.1.3.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.1.3.rst
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.2.0.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.2.0.rst
index 20bfe0a1915..20bfe0a1915 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.2.0.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.2.0.rst
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.2.1.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.2.1.rst
new file mode 100644
index 00000000000..5d28bcb01f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.2.1.rst
@@ -0,0 +1,41 @@
+pytest-2.2.1: bug fixes, perfect teardowns
+===========================================================================
+
+
+pytest-2.2.1 is a minor backward-compatible release of the py.test
+testing tool. It contains bug fixes and little improvements, including
+documentation fixes. If you are using the distributed testing
+pluginmake sure to upgrade it to pytest-xdist-1.8.
+
+For general information see here:
+
+ http://pytest.org/
+
+To install or upgrade pytest:
+
+ pip install -U pytest # or
+ easy_install -U pytest
+
+Special thanks for helping on this release to Ronny Pfannschmidt, Jurko
+Gospodnetic and Ralf Schmitt.
+
+best,
+holger krekel
+
+
+Changes between 2.2.0 and 2.2.1
+----------------------------------------
+
+- fix issue99 (in pytest and py) internallerrors with resultlog now
+ produce better output - fixed by normalizing pytest_internalerror
+ input arguments.
+- fix issue97 / traceback issues (in pytest and py) improve traceback output
+ in conjunction with jinja2 and cython which hack tracebacks
+- fix issue93 (in pytest and pytest-xdist) avoid "delayed teardowns":
+ the final test in a test node will now run its teardown directly
+ instead of waiting for the end of the session. Thanks Dave Hunt for
+ the good reporting and feedback. The pytest_runtest_protocol as well
+ as the pytest_runtest_teardown hooks now have "nextitem" available
+ which will be None indicating the end of the test run.
+- fix collection crash due to unknown-source collected items, thanks
+ to Ralf Schmitt (fixed by depending on a more recent pylib)
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.2.2.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.2.2.rst
index 733aedec413..733aedec413 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.2.2.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.2.2.rst
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.2.4.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.2.4.rst
new file mode 100644
index 00000000000..67f0feb27c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.2.4.rst
@@ -0,0 +1,39 @@
+pytest-2.2.4: bug fixes, better junitxml/unittest/python3 compat
+===========================================================================
+
+pytest-2.2.4 is a minor backward-compatible release of the versatile
+py.test testing tool. It contains bug fixes and a few refinements
+to junitxml reporting, better unittest- and python3 compatibility.
+
+For general information see here:
+
+ http://pytest.org/
+
+To install or upgrade pytest:
+
+ pip install -U pytest # or
+ easy_install -U pytest
+
+Special thanks for helping on this release to Ronny Pfannschmidt
+and Benjamin Peterson and the contributors of issues.
+
+best,
+holger krekel
+
+Changes between 2.2.3 and 2.2.4
+-----------------------------------
+
+- fix error message for rewritten assertions involving the % operator
+- fix issue 126: correctly match all invalid xml characters for junitxml
+ binary escape
+- fix issue with unittest: now @unittest.expectedFailure markers should
+ be processed correctly (you can also use @pytest.mark markers)
+- document integration with the extended distribute/setuptools test commands
+- fix issue 140: properly get the real functions
+ of bound classmethods for setup/teardown_class
+- fix issue #141: switch from the deceased paste.pocoo.org to bpaste.net
+- fix issue #143: call unconfigure/sessionfinish always when
+ configure/sessionstart where called
+- fix issue #144: better mangle test ids to junitxml classnames
+- upgrade distribute_setup.py to 0.6.27
+
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.3.0.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.3.0.rst
new file mode 100644
index 00000000000..f863aad0ace
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.3.0.rst
@@ -0,0 +1,134 @@
+pytest-2.3: improved fixtures / better unittest integration
+=============================================================================
+
+pytest-2.3 comes with many major improvements for fixture/funcarg management
+and parametrized testing in Python. It is now easier, more efficient and
+more predicatable to re-run the same tests with different fixture
+instances. Also, you can directly declare the caching "scope" of
+fixtures so that dependent tests throughout your whole test suite can
+re-use database or other expensive fixture objects with ease. Lastly,
+it's possible for fixture functions (formerly known as funcarg
+factories) to use other fixtures, allowing for a completely modular and
+re-useable fixture design.
+
+For detailed info and tutorial-style examples, see:
+
+ http://pytest.org/latest/fixture.html
+
+Moreover, there is now support for using pytest fixtures/funcargs with
+unittest-style suites, see here for examples:
+
+ http://pytest.org/latest/unittest.html
+
+Besides, more unittest-test suites are now expected to "simply work"
+with pytest.
+
+All changes are backward compatible and you should be able to continue
+to run your test suites and 3rd party plugins that worked with
+pytest-2.2.4.
+
+If you are interested in the precise reasoning (including examples) of the
+pytest-2.3 fixture evolution, please consult
+http://pytest.org/latest/funcarg_compare.html
+
+For general info on installation and getting started:
+
+ http://pytest.org/latest/getting-started.html
+
+Docs and PDF access as usual at:
+
+ http://pytest.org
+
+and more details for those already in the knowing of pytest can be found
+in the CHANGELOG below.
+
+Particular thanks for this release go to Floris Bruynooghe, Alex Okrushko
+Carl Meyer, Ronny Pfannschmidt, Benjamin Peterson and Alex Gaynor for helping
+to get the new features right and well integrated. Ronny and Floris
+also helped to fix a number of bugs and yet more people helped by
+providing bug reports.
+
+have fun,
+holger krekel
+
+
+Changes between 2.2.4 and 2.3.0
+-----------------------------------
+
+- fix issue202 - better automatic names for parametrized test functions
+- fix issue139 - introduce @pytest.fixture which allows direct scoping
+ and parametrization of funcarg factories. Introduce new @pytest.setup
+ marker to allow the writing of setup functions which accept funcargs.
+- fix issue198 - conftest fixtures were not found on windows32 in some
+ circumstances with nested directory structures due to path manipulation issues
+- fix issue193 skip test functions with were parametrized with empty
+ parameter sets
+- fix python3.3 compat, mostly reporting bits that previously depended
+ on dict ordering
+- introduce re-ordering of tests by resource and parametrization setup
+ which takes precedence to the usual file-ordering
+- fix issue185 monkeypatching time.time does not cause pytest to fail
+- fix issue172 duplicate call of pytest.setup-decoratored setup_module
+ functions
+- fix junitxml=path construction so that if tests change the
+ current working directory and the path is a relative path
+ it is constructed correctly from the original current working dir.
+- fix "python setup.py test" example to cause a proper "errno" return
+- fix issue165 - fix broken doc links and mention stackoverflow for FAQ
+- catch unicode-issues when writing failure representations
+ to terminal to prevent the whole session from crashing
+- fix xfail/skip confusion: a skip-mark or an imperative pytest.skip
+ will now take precedence before xfail-markers because we
+ can't determine xfail/xpass status in case of a skip. see also:
+ http://stackoverflow.com/questions/11105828/in-py-test-when-i-explicitly-skip-a-test-that-is-marked-as-xfail-how-can-i-get
+
+- always report installed 3rd party plugins in the header of a test run
+
+- fix issue160: a failing setup of an xfail-marked tests should
+ be reported as xfail (not xpass)
+
+- fix issue128: show captured output when capsys/capfd are used
+
+- fix issue179: properly show the dependency chain of factories
+
+- pluginmanager.register(...) now raises ValueError if the
+ plugin has been already registered or the name is taken
+
+- fix issue159: improve http://pytest.org/latest/faq.html
+ especially with respect to the "magic" history, also mention
+ pytest-django, trial and unittest integration.
+
+- make request.keywords and node.keywords writable. All descendant
+ collection nodes will see keyword values. Keywords are dictionaries
+ containing markers and other info.
+
+- fix issue 178: xml binary escapes are now wrapped in py.xml.raw
+
+- fix issue 176: correctly catch the builtin AssertionError
+ even when we replaced AssertionError with a subclass on the
+ python level
+
+- factory discovery no longer fails with magic global callables
+ that provide no sane __code__ object (mock.call for example)
+
+- fix issue 182: testdir.inprocess_run now considers passed plugins
+
+- fix issue 188: ensure sys.exc_info is clear on python2
+ before calling into a test
+
+- fix issue 191: add unittest TestCase runTest method support
+- fix issue 156: monkeypatch correctly handles class level descriptors
+
+- reporting refinements:
+
+ - pytest_report_header now receives a "startdir" so that
+ you can use startdir.bestrelpath(yourpath) to show
+ nice relative path
+
+ - allow plugins to implement both pytest_report_header and
+ pytest_sessionstart (sessionstart is invoked first).
+
+ - don't show deselected reason line if there is none
+
+ - py.test -vv will show all of assert comparisons instead of truncating
+
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.3.1.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.3.1.rst
index b787dc203f4..b787dc203f4 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.3.1.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.3.1.rst
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.3.2.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.3.2.rst
new file mode 100644
index 00000000000..75312b429cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.3.2.rst
@@ -0,0 +1,57 @@
+pytest-2.3.2: some fixes and more traceback-printing speed
+===========================================================================
+
+pytest-2.3.2 is another stabilization release:
+
+- issue 205: fixes a regression with conftest detection
+- issue 208/29: fixes traceback-printing speed in some bad cases
+- fix teardown-ordering for parametrized setups
+- fix unittest and trial compat behaviour with respect to runTest() methods
+- issue 206 and others: some improvements to packaging
+- fix issue127 and others: improve some docs
+
+See
+
+ http://pytest.org/
+
+for general information. To install or upgrade pytest:
+
+ pip install -U pytest # or
+ easy_install -U pytest
+
+best,
+holger krekel
+
+
+Changes between 2.3.1 and 2.3.2
+-----------------------------------
+
+- fix issue208 and fix issue29 use new py version to avoid long pauses
+ when printing tracebacks in long modules
+
+- fix issue205 - conftests in subdirs customizing
+ pytest_pycollect_makemodule and pytest_pycollect_makeitem
+ now work properly
+
+- fix teardown-ordering for parametrized setups
+
+- fix issue127 - better documentation for pytest_addoption
+ and related objects.
+
+- fix unittest behaviour: TestCase.runtest only called if there are
+ test methods defined
+
+- improve trial support: don't collect its empty
+ unittest.TestCase.runTest() method
+
+- "python setup.py test" now works with pytest itself
+
+- fix/improve internal/packaging related bits:
+
+ - exception message check of test_nose.py now passes on python33 as well
+
+ - issue206 - fix test_assertrewrite.py to work when a global
+ PYTHONDONTWRITEBYTECODE=1 is present
+
+ - add tox.ini to pytest distribution so that ignore-dirs and others config
+ bits are properly distributed for maintainers who run pytest-own tests
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.3.3.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.3.3.rst
new file mode 100644
index 00000000000..3a48b6ac4ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.3.3.rst
@@ -0,0 +1,62 @@
+pytest-2.3.3: integration fixes, py24 support, ``*/**`` shown in traceback
+===========================================================================
+
+pytest-2.3.3 is another stabilization release of the py.test tool
+which offers uebersimple assertions, scalable fixture mechanisms
+and deep customization for testing with Python. Particularly,
+this release provides:
+
+- integration fixes and improvements related to flask, numpy, nose,
+ unittest, mock
+
+- makes pytest work on py24 again (yes, people sometimes still need to use it)
+
+- show ``*,**`` args in pytest tracebacks
+
+Thanks to Manuel Jacob, Thomas Waldmann, Ronny Pfannschmidt, Pavel Repin
+and Andreas Taumoefolau for providing patches and all for the issues.
+
+See
+
+ http://pytest.org/
+
+for general information. To install or upgrade pytest:
+
+ pip install -U pytest # or
+ easy_install -U pytest
+
+best,
+holger krekel
+
+Changes between 2.3.2 and 2.3.3
+-----------------------------------
+
+- fix issue214 - parse modules that contain special objects like e. g.
+ flask's request object which blows up on getattr access if no request
+ is active. thanks Thomas Waldmann.
+
+- fix issue213 - allow to parametrize with values like numpy arrays that
+ do not support an __eq__ operator
+
+- fix issue215 - split test_python.org into multiple files
+
+- fix issue148 - @unittest.skip on classes is now recognized and avoids
+ calling setUpClass/tearDownClass, thanks Pavel Repin
+
+- fix issue209 - reintroduce python2.4 support by depending on newer
+ pylib which re-introduced statement-finding for pre-AST interpreters
+
+- nose support: only call setup if it's a callable, thanks Andrew
+ Taumoefolau
+
+- fix issue219 - add py2.4-3.3 classifiers to TROVE list
+
+- in tracebacks *,** arg values are now shown next to normal arguments
+ (thanks Manuel Jacob)
+
+- fix issue217 - support mock.patch with pytest's fixtures - note that
+ you need either mock-1.0.1 or the python3.3 builtin unittest.mock.
+
+- fix issue127 - improve documentation for pytest_addoption() and
+ add a ``config.getoption(name)`` helper function for consistency.
+
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.3.4.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.3.4.rst
index d6c597b5489..d6c597b5489 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.3.4.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.3.4.rst
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.3.5.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.3.5.rst
new file mode 100644
index 00000000000..112399ef3ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.3.5.rst
@@ -0,0 +1,97 @@
+pytest-2.3.5: bug fixes and little improvements
+===========================================================================
+
+pytest-2.3.5 is a maintenance release with many bug fixes and little
+improvements. See the changelog below for details. No backward
+compatibility issues are foreseen and all plugins which worked with the
+prior version are expected to work unmodified. Speaking of which, a
+few interesting new plugins saw the light last month:
+
+- pytest-instafail: show failure information while tests are running
+- pytest-qt: testing of GUI applications written with QT/Pyside
+- pytest-xprocess: managing external processes across test runs
+- pytest-random: randomize test ordering
+
+And several others like pytest-django saw maintenance releases.
+For a more complete list, check out
+https://pypi.python.org/pypi?%3Aaction=search&term=pytest&submit=search.
+
+For general information see:
+
+ http://pytest.org/
+
+To install or upgrade pytest:
+
+ pip install -U pytest # or
+ easy_install -U pytest
+
+Particular thanks to Floris, Ronny, Benjamin and the many bug reporters
+and fix providers.
+
+may the fixtures be with you,
+holger krekel
+
+
+Changes between 2.3.4 and 2.3.5
+-----------------------------------
+
+- never consider a fixture function for test function collection
+
+- allow re-running of test items / helps to fix pytest-reruntests plugin
+ and also help to keep less fixture/resource references alive
+
+- put captured stdout/stderr into junitxml output even for passing tests
+ (thanks Adam Goucher)
+
+- Issue 265 - integrate nose setup/teardown with setupstate
+ so it doesn't try to teardown if it did not setup
+
+- issue 271 - don't write junitxml on slave nodes
+
+- Issue 274 - don't try to show full doctest example
+ when doctest does not know the example location
+
+- issue 280 - disable assertion rewriting on buggy CPython 2.6.0
+
+- inject "getfixture()" helper to retrieve fixtures from doctests,
+ thanks Andreas Zeidler
+
+- issue 259 - when assertion rewriting, be consistent with the default
+ source encoding of ASCII on Python 2
+
+- issue 251 - report a skip instead of ignoring classes with init
+
+- issue250 unicode/str mixes in parametrization names and values now works
+
+- issue257, assertion-triggered compilation of source ending in a
+ comment line doesn't blow up in python2.5 (fixed through py>=1.4.13.dev6)
+
+- fix --genscript option to generate standalone scripts that also
+ work with python3.3 (importer ordering)
+
+- issue171 - in assertion rewriting, show the repr of some
+ global variables
+
+- fix option help for "-k"
+
+- move long description of distribution into README.rst
+
+- improve docstring for metafunc.parametrize()
+
+- fix bug where using capsys with pytest.set_trace() in a test
+ function would break when looking at capsys.readouterr()
+
+- allow to specify prefixes starting with "_" when
+ customizing python_functions test discovery. (thanks Graham Horler)
+
+- improve PYTEST_DEBUG tracing output by putting
+ extra data on a new lines with additional indent
+
+- ensure OutcomeExceptions like skip/fail have initialized exception attributes
+
+- issue 260 - don't use nose special setup on plain unittest cases
+
+- fix issue134 - print the collect errors that prevent running specified test items
+
+- fix issue266 - accept unicode in MarkEvaluator expressions
+
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.4.0.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.4.0.rst
new file mode 100644
index 00000000000..be3aaedb09f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.4.0.rst
@@ -0,0 +1,225 @@
+pytest-2.4.0: new fixture features/hooks and bug fixes
+===========================================================================
+
+The just released pytest-2.4.0 brings many improvements and numerous
+bug fixes while remaining plugin- and test-suite compatible apart
+from a few supposedly very minor incompatibilities. See below for
+a full list of details. A few feature highlights:
+
+- new yield-style fixtures `pytest.yield_fixture
+ <http://pytest.org/latest/yieldfixture.html>`_, allowing to use
+ existing with-style context managers in fixture functions.
+
+- improved pdb support: ``import pdb ; pdb.set_trace()`` now works
+ without requiring prior disabling of stdout/stderr capturing.
+ Also the ``--pdb`` options works now on collection and internal errors
+ and we introduced a new experimental hook for IDEs/plugins to
+ intercept debugging: ``pytest_exception_interact(node, call, report)``.
+
+- shorter monkeypatch variant to allow specifying an import path as
+ a target, for example: ``monkeypatch.setattr("requests.get", myfunc)``
+
+- better unittest/nose compatibility: all teardown methods are now only
+ called if the corresponding setup method succeeded.
+
+- integrate tab-completion on command line options if you
+ have `argcomplete <http://pypi.python.org/pypi/argcomplete>`_
+ configured.
+
+- allow boolean expression directly with skipif/xfail
+ if a "reason" is also specified.
+
+- a new hook ``pytest_load_initial_conftests`` allows plugins like
+ `pytest-django <http://pypi.python.org/pypi/pytest-django>`_ to
+ influence the environment before conftest files import ``django``.
+
+- reporting: color the last line red or green depending if
+ failures/errors occurred or everything passed.
+
+The documentation has been updated to accommodate the changes,
+see `http://pytest.org <http://pytest.org>`_
+
+To install or upgrade pytest::
+
+ pip install -U pytest # or
+ easy_install -U pytest
+
+
+**Many thanks to all who helped, including Floris Bruynooghe,
+Brianna Laugher, Andreas Pelme, Anthon van der Neut, Anatoly Bubenkoff,
+Vladimir Keleshev, Mathieu Agopian, Ronny Pfannschmidt, Christian
+Theunert and many others.**
+
+may passing tests be with you,
+
+holger krekel
+
+Changes between 2.3.5 and 2.4
+-----------------------------------
+
+known incompatibilities:
+
+- if calling --genscript from python2.7 or above, you only get a
+ standalone script which works on python2.7 or above. Use Python2.6
+ to also get a python2.5 compatible version.
+
+- all xunit-style teardown methods (nose-style, pytest-style,
+ unittest-style) will not be called if the corresponding setup method failed,
+ see issue322 below.
+
+- the pytest_plugin_unregister hook wasn't ever properly called
+ and there is no known implementation of the hook - so it got removed.
+
+- pytest.fixture-decorated functions cannot be generators (i.e. use
+ yield) anymore. This change might be reversed in 2.4.1 if it causes
+ unforeseen real-life issues. However, you can always write and return
+ an inner function/generator and change the fixture consumer to iterate
+ over the returned generator. This change was done in lieu of the new
+ ``pytest.yield_fixture`` decorator, see below.
+
+new features:
+
+- experimentally introduce a new ``pytest.yield_fixture`` decorator
+ which accepts exactly the same parameters as pytest.fixture but
+ mandates a ``yield`` statement instead of a ``return statement`` from
+ fixture functions. This allows direct integration with "with-style"
+ context managers in fixture functions and generally avoids registering
+ of finalization callbacks in favour of treating the "after-yield" as
+ teardown code. Thanks Andreas Pelme, Vladimir Keleshev, Floris
+ Bruynooghe, Ronny Pfannschmidt and many others for discussions.
+
+- allow boolean expression directly with skipif/xfail
+ if a "reason" is also specified. Rework skipping documentation
+ to recommend "condition as booleans" because it prevents surprises
+ when importing markers between modules. Specifying conditions
+ as strings will remain fully supported.
+
+- reporting: color the last line red or green depending if
+ failures/errors occurred or everything passed. thanks Christian
+ Theunert.
+
+- make "import pdb ; pdb.set_trace()" work natively wrt capturing (no
+ "-s" needed anymore), making ``pytest.set_trace()`` a mere shortcut.
+
+- fix issue181: --pdb now also works on collect errors (and
+ on internal errors) . This was implemented by a slight internal
+ refactoring and the introduction of a new hook
+ ``pytest_exception_interact`` hook (see next item).
+
+- fix issue341: introduce new experimental hook for IDEs/terminals to
+ intercept debugging: ``pytest_exception_interact(node, call, report)``.
+
+- new monkeypatch.setattr() variant to provide a shorter
+ invocation for patching out classes/functions from modules:
+
+ monkeypatch.setattr("requests.get", myfunc)
+
+ will replace the "get" function of the "requests" module with ``myfunc``.
+
+- fix issue322: tearDownClass is not run if setUpClass failed. Thanks
+ Mathieu Agopian for the initial fix. Also make all of pytest/nose
+ finalizer mimic the same generic behaviour: if a setupX exists and
+ fails, don't run teardownX. This internally introduces a new method
+ "node.addfinalizer()" helper which can only be called during the setup
+ phase of a node.
+
+- simplify pytest.mark.parametrize() signature: allow to pass a
+ CSV-separated string to specify argnames. For example:
+ ``pytest.mark.parametrize("input,expected", [(1,2), (2,3)])``
+ works as well as the previous:
+ ``pytest.mark.parametrize(("input", "expected"), ...)``.
+
+- add support for setUpModule/tearDownModule detection, thanks Brian Okken.
+
+- integrate tab-completion on options through use of "argcomplete".
+ Thanks Anthon van der Neut for the PR.
+
+- change option names to be hyphen-separated long options but keep the
+ old spelling backward compatible. py.test -h will only show the
+ hyphenated version, for example "--collect-only" but "--collectonly"
+ will remain valid as well (for backward-compat reasons). Many thanks to
+ Anthon van der Neut for the implementation and to Hynek Schlawack for
+ pushing us.
+
+- fix issue 308 - allow to mark/xfail/skip individual parameter sets
+ when parametrizing. Thanks Brianna Laugher.
+
+- call new experimental pytest_load_initial_conftests hook to allow
+ 3rd party plugins to do something before a conftest is loaded.
+
+Bug fixes:
+
+- fix issue358 - capturing options are now parsed more properly
+ by using a new parser.parse_known_args method.
+
+- pytest now uses argparse instead of optparse (thanks Anthon) which
+ means that "argparse" is added as a dependency if installing into python2.6
+ environments or below.
+
+- fix issue333: fix a case of bad unittest/pytest hook interaction.
+
+- PR27: correctly handle nose.SkipTest during collection. Thanks
+ Antonio Cuni, Ronny Pfannschmidt.
+
+- fix issue355: junitxml puts name="pytest" attribute to testsuite tag.
+
+- fix issue336: autouse fixture in plugins should work again.
+
+- fix issue279: improve object comparisons on assertion failure
+ for standard datatypes and recognise collections.abc. Thanks to
+ Brianna Laugher and Mathieu Agopian.
+
+- fix issue317: assertion rewriter support for the is_package method
+
+- fix issue335: document py.code.ExceptionInfo() object returned
+ from pytest.raises(), thanks Mathieu Agopian.
+
+- remove implicit distribute_setup support from setup.py.
+
+- fix issue305: ignore any problems when writing pyc files.
+
+- SO-17664702: call fixture finalizers even if the fixture function
+ partially failed (finalizers would not always be called before)
+
+- fix issue320 - fix class scope for fixtures when mixed with
+ module-level functions. Thanks Anatloy Bubenkoff.
+
+- you can specify "-q" or "-qq" to get different levels of "quieter"
+ reporting (thanks Katarzyna Jachim)
+
+- fix issue300 - Fix order of conftest loading when starting py.test
+ in a subdirectory.
+
+- fix issue323 - sorting of many module-scoped arg parametrizations
+
+- make sessionfinish hooks execute with the same cwd-context as at
+ session start (helps fix plugin behaviour which write output files
+ with relative path such as pytest-cov)
+
+- fix issue316 - properly reference collection hooks in docs
+
+- fix issue 306 - cleanup of -k/-m options to only match markers/test
+ names/keywords respectively. Thanks Wouter van Ackooy.
+
+- improved doctest counting for doctests in python modules --
+ files without any doctest items will not show up anymore
+ and doctest examples are counted as separate test items.
+ thanks Danilo Bellini.
+
+- fix issue245 by depending on the released py-1.4.14
+ which fixes py.io.dupfile to work with files with no
+ mode. Thanks Jason R. Coombs.
+
+- fix junitxml generation when test output contains control characters,
+ addressing issue267, thanks Jaap Broekhuizen
+
+- fix issue338: honor --tb style for setup/teardown errors as well. Thanks Maho.
+
+- fix issue307 - use yaml.safe_load in example, thanks Mark Eichin.
+
+- better parametrize error messages, thanks Brianna Laugher
+
+- pytest_terminal_summary(terminalreporter) hooks can now use
+ ".section(title)" and ".line(msg)" methods to print extra
+ information at the end of a test run.
+
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.4.1.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.4.1.rst
index 64ba170f897..64ba170f897 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.4.1.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.4.1.rst
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.4.2.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.4.2.rst
index 3b4aa95abbc..3b4aa95abbc 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.4.2.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.4.2.rst
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.5.0.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.5.0.rst
new file mode 100644
index 00000000000..b04a825cd8e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.5.0.rst
@@ -0,0 +1,175 @@
+pytest-2.5.0: now down to ZERO reported bugs!
+===========================================================================
+
+pytest-2.5.0 is a big fixing release, the result of two community bug
+fixing days plus numerous additional works from many people and
+reporters. The release should be fully compatible to 2.4.2, existing
+plugins and test suites. We aim at maintaining this level of ZERO reported
+bugs because it's no fun if your testing tool has bugs, is it? Under a
+condition, though: when submitting a bug report please provide
+clear information about the circumstances and a simple example which
+reproduces the problem.
+
+The issue tracker is of course not empty now. We have many remaining
+"enhacement" issues which we'll hopefully can tackle in 2014 with your
+help.
+
+For those who use older Python versions, please note that pytest is not
+automatically tested on python2.5 due to virtualenv, setuptools and tox
+not supporting it anymore. Manual verification shows that it mostly
+works fine but it's not going to be part of the automated release
+process and thus likely to break in the future.
+
+As usual, current docs are at
+
+ http://pytest.org
+
+and you can upgrade from pypi via::
+
+ pip install -U pytest
+
+Particular thanks for helping with this release go to Anatoly Bubenkoff,
+Floris Bruynooghe, Marc Abramowitz, Ralph Schmitt, Ronny Pfannschmidt,
+Donald Stufft, James Lan, Rob Dennis, Jason R. Coombs, Mathieu Agopian,
+Virgil Dupras, Bruno Oliveira, Alex Gaynor and others.
+
+have fun,
+holger krekel
+
+
+2.5.0
+-----------------------------------
+
+- dropped python2.5 from automated release testing of pytest itself
+ which means it's probably going to break soon (but still works
+ with this release we believe).
+
+- simplified and fixed implementation for calling finalizers when
+ parametrized fixtures or function arguments are involved. finalization
+ is now performed lazily at setup time instead of in the "teardown phase".
+ While this might sound odd at first, it helps to ensure that we are
+ correctly handling setup/teardown even in complex code. User-level code
+ should not be affected unless it's implementing the pytest_runtest_teardown
+ hook and expecting certain fixture instances are torn down within (very
+ unlikely and would have been unreliable anyway).
+
+- PR90: add --color=yes|no|auto option to force terminal coloring
+ mode ("auto" is default). Thanks Marc Abramowitz.
+
+- fix issue319 - correctly show unicode in assertion errors. Many
+ thanks to Floris Bruynooghe for the complete PR. Also means
+ we depend on py>=1.4.19 now.
+
+- fix issue396 - correctly sort and finalize class-scoped parametrized
+ tests independently from number of methods on the class.
+
+- refix issue323 in a better way -- parametrization should now never
+ cause Runtime Recursion errors because the underlying algorithm
+ for re-ordering tests per-scope/per-fixture is not recursive
+ anymore (it was tail-call recursive before which could lead
+ to problems for more than >966 non-function scoped parameters).
+
+- fix issue290 - there is preliminary support now for parametrizing
+ with repeated same values (sometimes useful to test if calling
+ a second time works as with the first time).
+
+- close issue240 - document precisely how pytest module importing
+ works, discuss the two common test directory layouts, and how it
+ interacts with PEP420-namespace packages.
+
+- fix issue246 fix finalizer order to be LIFO on independent fixtures
+ depending on a parametrized higher-than-function scoped fixture.
+ (was quite some effort so please bear with the complexity of this sentence :)
+ Thanks Ralph Schmitt for the precise failure example.
+
+- fix issue244 by implementing special index for parameters to only use
+ indices for paramentrized test ids
+
+- fix issue287 by running all finalizers but saving the exception
+ from the first failing finalizer and re-raising it so teardown will
+ still have failed. We reraise the first failing exception because
+ it might be the cause for other finalizers to fail.
+
+- fix ordering when mock.patch or other standard decorator-wrappings
+ are used with test methods. This fixues issue346 and should
+ help with random "xdist" collection failures. Thanks to
+ Ronny Pfannschmidt and Donald Stufft for helping to isolate it.
+
+- fix issue357 - special case "-k" expressions to allow for
+ filtering with simple strings that are not valid python expressions.
+ Examples: "-k 1.3" matches all tests parametrized with 1.3.
+ "-k None" filters all tests that have "None" in their name
+ and conversely "-k 'not None'".
+ Previously these examples would raise syntax errors.
+
+- fix issue384 by removing the trial support code
+ since the unittest compat enhancements allow
+ trial to handle it on its own
+
+- don't hide an ImportError when importing a plugin produces one.
+ fixes issue375.
+
+- fix issue275 - allow usefixtures and autouse fixtures
+ for running doctest text files.
+
+- fix issue380 by making --resultlog only rely on longrepr instead
+ of the "reprcrash" attribute which only exists sometimes.
+
+- address issue122: allow @pytest.fixture(params=iterator) by exploding
+ into a list early on.
+
+- fix pexpect-3.0 compatibility for pytest's own tests.
+ (fixes issue386)
+
+- allow nested parametrize-value markers, thanks James Lan for the PR.
+
+- fix unicode handling with new monkeypatch.setattr(import_path, value)
+ API. Thanks Rob Dennis. Fixes issue371.
+
+- fix unicode handling with junitxml, fixes issue368.
+
+- In assertion rewriting mode on Python 2, fix the detection of coding
+ cookies. See issue #330.
+
+- make "--runxfail" turn imperative pytest.xfail calls into no ops
+ (it already did neutralize pytest.mark.xfail markers)
+
+- refine pytest / pkg_resources interactions: The AssertionRewritingHook
+ PEP302 compliant loader now registers itself with setuptools/pkg_resources
+ properly so that the pkg_resources.resource_stream method works properly.
+ Fixes issue366. Thanks for the investigations and full PR to Jason R. Coombs.
+
+- pytestconfig fixture is now session-scoped as it is the same object during the
+ whole test run. Fixes issue370.
+
+- avoid one surprising case of marker malfunction/confusion::
+
+ @pytest.mark.some(lambda arg: ...)
+ def test_function():
+
+ would not work correctly because pytest assumes @pytest.mark.some
+ gets a function to be decorated already. We now at least detect if this
+ arg is a lambda and thus the example will work. Thanks Alex Gaynor
+ for bringing it up.
+
+- xfail a test on pypy that checks wrong encoding/ascii (pypy does
+ not error out). fixes issue385.
+
+- internally make varnames() deal with classes's __init__,
+ although it's not needed by pytest itself atm. Also
+ fix caching. Fixes issue376.
+
+- fix issue221 - handle importing of namespace-package with no
+ __init__.py properly.
+
+- refactor internal FixtureRequest handling to avoid monkeypatching.
+ One of the positive user-facing effects is that the "request" object
+ can now be used in closures.
+
+- fixed version comparison in pytest.importskip(modname, minverstring)
+
+- fix issue377 by clarifying in the nose-compat docs that pytest
+ does not duplicate the unittest-API into the "plain" namespace.
+
+- fix verbose reporting for @mock'd test functions
+
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.5.1.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.5.1.rst
index a3a74cec626..a3a74cec626 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.5.1.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.5.1.rst
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.5.2.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.5.2.rst
new file mode 100644
index 00000000000..d5cfca2dbda
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.5.2.rst
@@ -0,0 +1,64 @@
+pytest-2.5.2: fixes
+===========================================================================
+
+pytest is a mature Python testing tool with more than a 1000 tests
+against itself, passing on many different interpreters and platforms.
+
+The 2.5.2 release fixes a few bugs with two maybe-bugs remaining and
+actively being worked on (and waiting for the bug reporter's input).
+We also have a new contribution guide thanks to Piotr Banaszkiewicz
+and others.
+
+See docs at:
+
+ http://pytest.org
+
+As usual, you can upgrade from pypi via::
+
+ pip install -U pytest
+
+Thanks to the following people who contributed to this release:
+
+ Anatoly Bubenkov
+ Ronny Pfannschmidt
+ Floris Bruynooghe
+ Bruno Oliveira
+ Andreas Pelme
+ Jurko Gospodnetić
+ Piotr Banaszkiewicz
+ Simon Liedtke
+ lakka
+ Lukasz Balcerzak
+ Philippe Muller
+ Daniel Hahler
+
+have fun,
+holger krekel
+
+2.5.2
+-----------------------------------
+
+- fix issue409 -- better interoperate with cx_freeze by not
+ trying to import from collections.abc which causes problems
+ for py27/cx_freeze. Thanks Wolfgang L. for reporting and tracking it down.
+
+- fixed docs and code to use "pytest" instead of "py.test" almost everywhere.
+ Thanks Jurko Gospodnetic for the complete PR.
+
+- fix issue425: mention at end of "py.test -h" that --markers
+ and --fixtures work according to specified test path (or current dir)
+
+- fix issue413: exceptions with unicode attributes are now printed
+ correctly also on python2 and with pytest-xdist runs. (the fix
+ requires py-1.4.20)
+
+- copy, cleanup and integrate py.io capture
+ from pylib 1.4.20.dev2 (rev 13d9af95547e)
+
+- address issue416: clarify docs as to conftest.py loading semantics
+
+- fix issue429: comparing byte strings with non-ascii chars in assert
+ expressions now work better. Thanks Floris Bruynooghe.
+
+- make capfd/capsys.capture private, its unused and shouldn't be exposed
+
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.6.0.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.6.0.rst
index 36b545a28b4..36b545a28b4 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.6.0.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.6.0.rst
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.6.1.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.6.1.rst
index 6f27c5861ca..6f27c5861ca 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.6.1.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.6.1.rst
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.6.2.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.6.2.rst
index 4efc73a4eaa..4efc73a4eaa 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.6.2.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.6.2.rst
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.6.3.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.6.3.rst
new file mode 100644
index 00000000000..ee0d2692c47
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.6.3.rst
@@ -0,0 +1,52 @@
+pytest-2.6.3: fixes and little improvements
+===========================================================================
+
+pytest is a mature Python testing tool with more than a 1100 tests
+against itself, passing on many different interpreters and platforms.
+This release is drop-in compatible to 2.5.2 and 2.6.X.
+See below for the changes and see docs at:
+
+ http://pytest.org
+
+As usual, you can upgrade from pypi via::
+
+ pip install -U pytest
+
+Thanks to all who contributed, among them:
+
+ Floris Bruynooghe
+ Oleg Sinyavskiy
+ Uwe Schmitt
+ Charles Cloud
+ Wolfgang Schnerring
+
+have fun,
+holger krekel
+
+Changes 2.6.3
+======================
+
+- fix issue575: xunit-xml was reporting collection errors as failures
+ instead of errors, thanks Oleg Sinyavskiy.
+
+- fix issue582: fix setuptools example, thanks Laszlo Papp and Ronny
+ Pfannschmidt.
+
+- Fix infinite recursion bug when pickling capture.EncodedFile, thanks
+ Uwe Schmitt.
+
+- fix issue589: fix bad interaction with numpy and others when showing
+ exceptions. Check for precise "maximum recursion depth exceed" exception
+ instead of presuming any RuntimeError is that one (implemented in py
+ dep). Thanks Charles Cloud for analysing the issue.
+
+- fix conftest related fixture visibility issue: when running with a
+ CWD outside of a test package pytest would get fixture discovery wrong.
+ Thanks to Wolfgang Schnerring for figuring out a reproducible example.
+
+- Introduce pytest_enter_pdb hook (needed e.g. by pytest_timeout to cancel the
+ timeout when interactively entering pdb). Thanks Wolfgang Schnerring.
+
+- check xfail/skip also with non-python function test items. Thanks
+ Floris Bruynooghe.
+
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.7.0.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.7.0.rst
new file mode 100644
index 00000000000..4e317ff8f34
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.7.0.rst
@@ -0,0 +1,101 @@
+pytest-2.7.0: fixes, features, speed improvements
+===========================================================================
+
+pytest is a mature Python testing tool with more than a 1100 tests
+against itself, passing on many different interpreters and platforms.
+This release is supposed to be drop-in compatible to 2.6.X.
+
+See below for the changes and see docs at:
+
+ http://pytest.org
+
+As usual, you can upgrade from pypi via::
+
+ pip install -U pytest
+
+Thanks to all who contributed, among them:
+
+ Anatoly Bubenkoff
+ Floris Bruynooghe
+ Brianna Laugher
+ Eric Siegerman
+ Daniel Hahler
+ Charles Cloud
+ Tom Viner
+ Holger Peters
+ Ldiary Translations
+ almarklein
+
+have fun,
+holger krekel
+
+2.7.0 (compared to 2.6.4)
+-----------------------------
+
+- fix issue435: make reload() work when assert rewriting is active.
+ Thanks Daniel Hahler.
+
+- fix issue616: conftest.py files and their contained fixutres are now
+ properly considered for visibility, independently from the exact
+ current working directory and test arguments that are used.
+ Many thanks to Eric Siegerman and his PR235 which contains
+ systematic tests for conftest visibility and now passes.
+ This change also introduces the concept of a ``rootdir`` which
+ is printed as a new pytest header and documented in the pytest
+ customize web page.
+
+- change reporting of "diverted" tests, i.e. tests that are collected
+ in one file but actually come from another (e.g. when tests in a test class
+ come from a base class in a different file). We now show the nodeid
+ and indicate via a postfix the other file.
+
+- add ability to set command line options by environment variable PYTEST_ADDOPTS.
+
+- added documentation on the new pytest-dev teams on bitbucket and
+ github. See https://pytest.org/latest/contributing.html .
+ Thanks to Anatoly for pushing and initial work on this.
+
+- fix issue650: new option ``--docttest-ignore-import-errors`` which
+ will turn import errors in doctests into skips. Thanks Charles Cloud
+ for the complete PR.
+
+- fix issue655: work around different ways that cause python2/3
+ to leak sys.exc_info into fixtures/tests causing failures in 3rd party code
+
+- fix issue615: assertion rewriting did not correctly escape % signs
+ when formatting boolean operations, which tripped over mixing
+ booleans with modulo operators. Thanks to Tom Viner for the report,
+ triaging and fix.
+
+- implement issue351: add ability to specify parametrize ids as a callable
+ to generate custom test ids. Thanks Brianna Laugher for the idea and
+ implementation.
+
+- introduce and document new hookwrapper mechanism useful for plugins
+ which want to wrap the execution of certain hooks for their purposes.
+ This supersedes the undocumented ``__multicall__`` protocol which
+ pytest itself and some external plugins use. Note that pytest-2.8
+ is scheduled to drop supporting the old ``__multicall__``
+ and only support the hookwrapper protocol.
+
+- majorly speed up invocation of plugin hooks
+
+- use hookwrapper mechanism in builtin pytest plugins.
+
+- add a doctest ini option for doctest flags, thanks Holger Peters.
+
+- add note to docs that if you want to mark a parameter and the
+ parameter is a callable, you also need to pass in a reason to disambiguate
+ it from the "decorator" case. Thanks Tom Viner.
+
+- "python_classes" and "python_functions" options now support glob-patterns
+ for test discovery, as discussed in issue600. Thanks Ldiary Translations.
+
+- allow to override parametrized fixtures with non-parametrized ones and vice versa (bubenkoff).
+
+- fix issue463: raise specific error for 'parameterize' misspelling (pfctdayelise).
+
+- On failure, the ``sys.last_value``, ``sys.last_type`` and
+ ``sys.last_traceback`` are set, so that a user can inspect the error
+ via postmortem debugging (almarklein).
+
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.7.1.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.7.1.rst
new file mode 100644
index 00000000000..fdc71eebba9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.7.1.rst
@@ -0,0 +1,58 @@
+pytest-2.7.1: bug fixes
+=======================
+
+pytest is a mature Python testing tool with more than a 1100 tests
+against itself, passing on many different interpreters and platforms.
+This release is supposed to be drop-in compatible to 2.7.0.
+
+See below for the changes and see docs at:
+
+ http://pytest.org
+
+As usual, you can upgrade from pypi via::
+
+ pip install -U pytest
+
+Thanks to all who contributed to this release, among them:
+
+ Bruno Oliveira
+ Holger Krekel
+ Ionel Maries Cristian
+ Floris Bruynooghe
+
+Happy testing,
+The py.test Development Team
+
+
+2.7.1 (compared to 2.7.0)
+-------------------------
+
+- fix issue731: do not get confused by the braces which may be present
+ and unbalanced in an object's repr while collapsing False
+ explanations. Thanks Carl Meyer for the report and test case.
+
+- fix issue553: properly handling inspect.getsourcelines failures in
+ FixtureLookupError which would lead to an internal error,
+ obfuscating the original problem. Thanks talljosh for initial
+ diagnose/patch and Bruno Oliveira for final patch.
+
+- fix issue660: properly report scope-mismatch-access errors
+ independently from ordering of fixture arguments. Also
+ avoid the pytest internal traceback which does not provide
+ information to the user. Thanks Holger Krekel.
+
+- streamlined and documented release process. Also all versions
+ (in setup.py and documentation generation) are now read
+ from _pytest/__init__.py. Thanks Holger Krekel.
+
+- fixed docs to remove the notion that yield-fixtures are experimental.
+ They are here to stay :) Thanks Bruno Oliveira.
+
+- Support building wheels by using environment markers for the
+ requirements. Thanks Ionel Maries Cristian.
+
+- fixed regression to 2.6.4 which surfaced e.g. in lost stdout capture printing
+ when tests raised SystemExit. Thanks Holger Krekel.
+
+- reintroduced _pytest fixture of the pytester plugin which is used
+ at least by pytest-xdist.
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.7.2.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.7.2.rst
index 69130ad623f..69130ad623f 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.7.2.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.7.2.rst
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.8.2.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.8.2.rst
index d7028616142..d7028616142 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.8.2.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.8.2.rst
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.8.3.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.8.3.rst
index d080ac724c1..d080ac724c1 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.8.3.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.8.3.rst
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.8.4.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.8.4.rst
index a09629cef09..a09629cef09 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.8.4.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.8.4.rst
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.8.5.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.8.5.rst
index 7409022a137..7409022a137 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.8.5.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.8.5.rst
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.8.6.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.8.6.rst
index 215fae51eac..215fae51eac 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.8.6.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.8.6.rst
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.8.7.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.8.7.rst
index d98d731064b..d98d731064b 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/announce/release-2.8.7.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.8.7.rst
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.9.0.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.9.0.rst
new file mode 100644
index 00000000000..011b1ffb9d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.9.0.rst
@@ -0,0 +1,159 @@
+pytest-2.9.0
+============
+
+pytest is a mature Python testing tool with more than a 1100 tests
+against itself, passing on many different interpreters and platforms.
+
+See below for the changes and see docs at:
+
+ http://pytest.org
+
+As usual, you can upgrade from pypi via::
+
+ pip install -U pytest
+
+Thanks to all who contributed to this release, among them:
+
+ Anatoly Bubenkov
+ Bruno Oliveira
+ Buck Golemon
+ David Vierra
+ Florian Bruhin
+ Galaczi Endre
+ Georgy Dyuldin
+ Lukas Bednar
+ Luke Murphy
+ Marcin Biernat
+ Matt Williams
+ Michael Aquilina
+ Raphael Pierzina
+ Ronny Pfannschmidt
+ Ryan Wooden
+ Tiemo Kieft
+ TomV
+ holger krekel
+ jab
+
+
+Happy testing,
+The py.test Development Team
+
+
+2.9.0 (compared to 2.8.7)
+-------------------------
+
+**New Features**
+
+* New ``pytest.mark.skip`` mark, which unconditionally skips marked tests.
+ Thanks `@MichaelAquilina`_ for the complete PR (`#1040`_).
+
+* ``--doctest-glob`` may now be passed multiple times in the command-line.
+ Thanks `@jab`_ and `@nicoddemus`_ for the PR.
+
+* New ``-rp`` and ``-rP`` reporting options give the summary and full output
+ of passing tests, respectively. Thanks to `@codewarrior0`_ for the PR.
+
+* ``pytest.mark.xfail`` now has a ``strict`` option which makes ``XPASS``
+ tests to fail the test suite, defaulting to ``False``. There's also a
+ ``xfail_strict`` ini option that can be used to configure it project-wise.
+ Thanks `@rabbbit`_ for the request and `@nicoddemus`_ for the PR (`#1355`_).
+
+* ``Parser.addini`` now supports options of type ``bool``. Thanks
+ `@nicoddemus`_ for the PR.
+
+* New ``ALLOW_BYTES`` doctest option strips ``b`` prefixes from byte strings
+ in doctest output (similar to ``ALLOW_UNICODE``).
+ Thanks `@jaraco`_ for the request and `@nicoddemus`_ for the PR (`#1287`_).
+
+* give a hint on KeyboardInterrupt to use the --fulltrace option to show the errors,
+ this fixes `#1366`_.
+ Thanks to `@hpk42`_ for the report and `@RonnyPfannschmidt`_ for the PR.
+
+* catch IndexError exceptions when getting exception source location. This fixes
+ pytest internal error for dynamically generated code (fixtures and tests)
+ where source lines are fake by intention
+
+**Changes**
+
+* **Important**: `py.code <https://pylib.readthedocs.io/en/latest/code.html>`_ has been
+ merged into the ``pytest`` repository as ``pytest._code``. This decision
+ was made because ``py.code`` had very few uses outside ``pytest`` and the
+ fact that it was in a different repository made it difficult to fix bugs on
+ its code in a timely manner. The team hopes with this to be able to better
+ refactor out and improve that code.
+ This change shouldn't affect users, but it is useful to let users aware
+ if they encounter any strange behavior.
+
+ Keep in mind that the code for ``pytest._code`` is **private** and
+ **experimental**, so you definitely should not import it explicitly!
+
+ Please note that the original ``py.code`` is still available in
+ `pylib <https://pylib.readthedocs.io>`_.
+
+* ``pytest_enter_pdb`` now optionally receives the pytest config object.
+ Thanks `@nicoddemus`_ for the PR.
+
+* Removed code and documentation for Python 2.5 or lower versions,
+ including removal of the obsolete ``_pytest.assertion.oldinterpret`` module.
+ Thanks `@nicoddemus`_ for the PR (`#1226`_).
+
+* Comparisons now always show up in full when ``CI`` or ``BUILD_NUMBER`` is
+ found in the environment, even when -vv isn't used.
+ Thanks `@The-Compiler`_ for the PR.
+
+* ``--lf`` and ``--ff`` now support long names: ``--last-failed`` and
+ ``--failed-first`` respectively.
+ Thanks `@MichaelAquilina`_ for the PR.
+
+* Added expected exceptions to pytest.raises fail message
+
+* Collection only displays progress ("collecting X items") when in a terminal.
+ This avoids cluttering the output when using ``--color=yes`` to obtain
+ colors in CI integrations systems (`#1397`_).
+
+**Bug Fixes**
+
+* The ``-s`` and ``-c`` options should now work under ``xdist``;
+ ``Config.fromdictargs`` now represents its input much more faithfully.
+ Thanks to `@bukzor`_ for the complete PR (`#680`_).
+
+* Fix (`#1290`_): support Python 3.5's ``@`` operator in assertion rewriting.
+ Thanks `@Shinkenjoe`_ for report with test case and `@tomviner`_ for the PR.
+
+* Fix formatting utf-8 explanation messages (`#1379`_).
+ Thanks `@biern`_ for the PR.
+
+* Fix `traceback style docs`_ to describe all of the available options
+ (auto/long/short/line/native/no), with `auto` being the default since v2.6.
+ Thanks `@hackebrot`_ for the PR.
+
+* Fix (`#1422`_): junit record_xml_property doesn't allow multiple records
+ with same name.
+
+
+.. _`traceback style docs`: https://pytest.org/latest/usage.html#modifying-python-traceback-printing
+
+.. _#1422: https://github.com/pytest-dev/pytest/issues/1422
+.. _#1379: https://github.com/pytest-dev/pytest/issues/1379
+.. _#1366: https://github.com/pytest-dev/pytest/issues/1366
+.. _#1040: https://github.com/pytest-dev/pytest/pull/1040
+.. _#680: https://github.com/pytest-dev/pytest/issues/680
+.. _#1287: https://github.com/pytest-dev/pytest/pull/1287
+.. _#1226: https://github.com/pytest-dev/pytest/pull/1226
+.. _#1290: https://github.com/pytest-dev/pytest/pull/1290
+.. _#1355: https://github.com/pytest-dev/pytest/pull/1355
+.. _#1397: https://github.com/pytest-dev/pytest/issues/1397
+.. _@biern: https://github.com/biern
+.. _@MichaelAquilina: https://github.com/MichaelAquilina
+.. _@bukzor: https://github.com/bukzor
+.. _@hpk42: https://github.com/hpk42
+.. _@nicoddemus: https://github.com/nicoddemus
+.. _@jab: https://github.com/jab
+.. _@codewarrior0: https://github.com/codewarrior0
+.. _@jaraco: https://github.com/jaraco
+.. _@The-Compiler: https://github.com/The-Compiler
+.. _@Shinkenjoe: https://github.com/Shinkenjoe
+.. _@tomviner: https://github.com/tomviner
+.. _@RonnyPfannschmidt: https://github.com/RonnyPfannschmidt
+.. _@rabbbit: https://github.com/rabbbit
+.. _@hackebrot: https://github.com/hackebrot \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.9.1.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.9.1.rst
new file mode 100644
index 00000000000..3277da1e9b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.9.1.rst
@@ -0,0 +1,67 @@
+pytest-2.9.1
+============
+
+pytest is a mature Python testing tool with more than a 1100 tests
+against itself, passing on many different interpreters and platforms.
+
+See below for the changes and see docs at:
+
+ http://pytest.org
+
+As usual, you can upgrade from pypi via::
+
+ pip install -U pytest
+
+Thanks to all who contributed to this release, among them:
+
+ Bruno Oliveira
+ Daniel Hahler
+ Dmitry Malinovsky
+ Florian Bruhin
+ Floris Bruynooghe
+ Matt Bachmann
+ Ronny Pfannschmidt
+ TomV
+ Vladimir Bolshakov
+ Zearin
+ palaviv
+
+
+Happy testing,
+The py.test Development Team
+
+
+2.9.1 (compared to 2.9.0)
+-------------------------
+
+**Bug Fixes**
+
+* Improve error message when a plugin fails to load.
+ Thanks `@nicoddemus`_ for the PR.
+
+* Fix (`#1178 <https://github.com/pytest-dev/pytest/issues/1178>`_):
+ ``pytest.fail`` with non-ascii characters raises an internal pytest error.
+ Thanks `@nicoddemus`_ for the PR.
+
+* Fix (`#469`_): junit parses report.nodeid incorrectly, when params IDs
+ contain ``::``. Thanks `@tomviner`_ for the PR (`#1431`_).
+
+* Fix (`#578 <https://github.com/pytest-dev/pytest/issues/578>`_): SyntaxErrors
+ containing non-ascii lines at the point of failure generated an internal
+ py.test error.
+ Thanks `@asottile`_ for the report and `@nicoddemus`_ for the PR.
+
+* Fix (`#1437`_): When passing in a bytestring regex pattern to parameterize
+ attempt to decode it as utf-8 ignoring errors.
+
+* Fix (`#649`_): parametrized test nodes cannot be specified to run on the command line.
+
+
+.. _#1437: https://github.com/pytest-dev/pytest/issues/1437
+.. _#469: https://github.com/pytest-dev/pytest/issues/469
+.. _#1431: https://github.com/pytest-dev/pytest/pull/1431
+.. _#649: https://github.com/pytest-dev/pytest/issues/649
+
+.. _@asottile: https://github.com/asottile
+.. _@nicoddemus: https://github.com/nicoddemus
+.. _@tomviner: https://github.com/tomviner
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.9.2.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.9.2.rst
new file mode 100644
index 00000000000..8f274cdf398
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-2.9.2.rst
@@ -0,0 +1,78 @@
+pytest-2.9.2
+============
+
+pytest is a mature Python testing tool with more than a 1100 tests
+against itself, passing on many different interpreters and platforms.
+
+See below for the changes and see docs at:
+
+ http://pytest.org
+
+As usual, you can upgrade from pypi via::
+
+ pip install -U pytest
+
+Thanks to all who contributed to this release, among them:
+
+ Adam Chainz
+ Benjamin Dopplinger
+ Bruno Oliveira
+ Florian Bruhin
+ John Towler
+ Martin Prusse
+ Meng Jue
+ MengJueM
+ Omar Kohl
+ Quentin Pradet
+ Ronny Pfannschmidt
+ Thomas Güttler
+ TomV
+ Tyler Goodlet
+
+
+Happy testing,
+The py.test Development Team
+
+
+2.9.2 (compared to 2.9.1)
+---------------------------
+
+**Bug Fixes**
+
+* fix `#510`_: skip tests where one parameterize dimension was empty
+ thanks Alex Stapleton for the Report and `@RonnyPfannschmidt`_ for the PR
+
+* Fix Xfail does not work with condition keyword argument.
+ Thanks `@astraw38`_ for reporting the issue (`#1496`_) and `@tomviner`_
+ for PR the (`#1524`_).
+
+* Fix win32 path issue when putting custom config file with absolute path
+ in ``pytest.main("-c your_absolute_path")``.
+
+* Fix maximum recursion depth detection when raised error class is not aware
+ of unicode/encoded bytes.
+ Thanks `@prusse-martin`_ for the PR (`#1506`_).
+
+* Fix ``pytest.mark.skip`` mark when used in strict mode.
+ Thanks `@pquentin`_ for the PR and `@RonnyPfannschmidt`_ for
+ showing how to fix the bug.
+
+* Minor improvements and fixes to the documentation.
+ Thanks `@omarkohl`_ for the PR.
+
+* Fix ``--fixtures`` to show all fixture definitions as opposed to just
+ one per fixture name.
+ Thanks to `@hackebrot`_ for the PR.
+
+.. _#510: https://github.com/pytest-dev/pytest/issues/510
+.. _#1506: https://github.com/pytest-dev/pytest/pull/1506
+.. _#1496: https://github.com/pytest-dev/pytest/issue/1496
+.. _#1524: https://github.com/pytest-dev/pytest/issue/1524
+
+.. _@astraw38: https://github.com/astraw38
+.. _@hackebrot: https://github.com/hackebrot
+.. _@omarkohl: https://github.com/omarkohl
+.. _@pquentin: https://github.com/pquentin
+.. _@prusse-martin: https://github.com/prusse-martin
+.. _@RonnyPfannschmidt: https://github.com/RonnyPfannschmidt
+.. _@tomviner: https://github.com/tomviner
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.0.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.0.rst
new file mode 100644
index 00000000000..4bf1e8534ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.0.rst
@@ -0,0 +1,82 @@
+pytest-3.0.0
+============
+
+The pytest team is proud to announce the 3.0.0 release!
+
+pytest is a mature Python testing tool with more than a 1600 tests
+against itself, passing on many different interpreters and platforms.
+
+This release contains a lot of bugs fixes and improvements, and much of
+the work done on it was possible because of the 2016 Sprint[1], which
+was funded by an indiegogo campaign which raised over US$12,000 with
+nearly 100 backers.
+
+There's a "What's new in pytest 3.0" [2] blog post highlighting the
+major features in this release.
+
+To see the complete changelog and documentation, please visit:
+
+ http://docs.pytest.org
+
+As usual, you can upgrade from pypi via:
+
+ pip install -U pytest
+
+Thanks to all who contributed to this release, among them:
+
+ AbdealiJK
+ Ana Ribeiro
+ Antony Lee
+ Brandon W Maister
+ Brianna Laugher
+ Bruno Oliveira
+ Ceridwen
+ Christian Boelsen
+ Daniel Hahler
+ Danielle Jenkins
+ Dave Hunt
+ Diego Russo
+ Dmitry Dygalo
+ Edoardo Batini
+ Eli Boyarski
+ Florian Bruhin
+ Floris Bruynooghe
+ Greg Price
+ Guyzmo
+ HEAD KANGAROO
+ JJ
+ Javi Romero
+ Javier Domingo Cansino
+ Kale Kundert
+ Kalle Bronsen
+ Marius Gedminas
+ Matt Williams
+ Mike Lundy
+ Oliver Bestwalter
+ Omar Kohl
+ Raphael Pierzina
+ RedBeardCode
+ Roberto Polli
+ Romain Dorgueil
+ Roman Bolshakov
+ Ronny Pfannschmidt
+ Stefan Zimmermann
+ Steffen Allner
+ Tareq Alayan
+ Ted Xiao
+ Thomas Grainger
+ Tom Viner
+ TomV
+ Vasily Kuznetsov
+ aostr
+ marscher
+ palaviv
+ satoru
+ taschini
+
+
+Happy testing,
+The Pytest Development Team
+
+[1] http://blog.pytest.org/2016/pytest-development-sprint/
+[2] http://blog.pytest.org/2016/whats-new-in-pytest-30/
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.1.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.1.rst
new file mode 100644
index 00000000000..9fb38047b9c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.1.rst
@@ -0,0 +1,26 @@
+pytest-3.0.1
+============
+
+pytest 3.0.1 has just been released to PyPI.
+
+This release fixes some regressions reported in version 3.0.0, being a
+drop-in replacement. To upgrade:
+
+ pip install --upgrade pytest
+
+The changelog is available at http://doc.pytest.org/en/latest/changelog.html.
+
+Thanks to all who contributed to this release, among them:
+
+ Adam Chainz
+ Andrew Svetlov
+ Bruno Oliveira
+ Daniel Hahler
+ Dmitry Dygalo
+ Florian Bruhin
+ Marcin Bachry
+ Ronny Pfannschmidt
+ matthiasha
+
+Happy testing,
+The py.test Development Team
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.2.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.2.rst
new file mode 100644
index 00000000000..9d1c05f2d45
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.2.rst
@@ -0,0 +1,24 @@
+pytest-3.0.2
+============
+
+pytest 3.0.2 has just been released to PyPI.
+
+This release fixes some regressions and bugs reported in version 3.0.1, being a
+drop-in replacement. To upgrade::
+
+ pip install --upgrade pytest
+
+The changelog is available at http://doc.pytest.org/en/latest/changelog.html.
+
+Thanks to all who contributed to this release, among them:
+
+* Ahn Ki-Wook
+* Bruno Oliveira
+* Florian Bruhin
+* Jordan Guymon
+* Raphael Pierzina
+* Ronny Pfannschmidt
+* mbyt
+
+Happy testing,
+The pytest Development Team
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.3.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.3.rst
new file mode 100644
index 00000000000..f00172195db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.3.rst
@@ -0,0 +1,27 @@
+pytest-3.0.3
+============
+
+pytest 3.0.3 has just been released to PyPI.
+
+This release fixes some regressions and bugs reported in the last version,
+being a drop-in replacement. To upgrade::
+
+ pip install --upgrade pytest
+
+The changelog is available at http://doc.pytest.org/en/latest/changelog.html.
+
+Thanks to all who contributed to this release, among them:
+
+* Bruno Oliveira
+* Florian Bruhin
+* Floris Bruynooghe
+* Huayi Zhang
+* Lev Maximov
+* Raquel Alegre
+* Ronny Pfannschmidt
+* Roy Williams
+* Tyler Goodlet
+* mbyt
+
+Happy testing,
+The pytest Development Team
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.4.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.4.rst
new file mode 100644
index 00000000000..852057037dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.4.rst
@@ -0,0 +1,29 @@
+pytest-3.0.4
+============
+
+pytest 3.0.4 has just been released to PyPI.
+
+This release fixes some regressions and bugs reported in the last version,
+being a drop-in replacement. To upgrade::
+
+ pip install --upgrade pytest
+
+The changelog is available at http://doc.pytest.org/en/latest/changelog.html.
+
+Thanks to all who contributed to this release, among them:
+
+* Bruno Oliveira
+* Dan Wandschneider
+* Florian Bruhin
+* Georgy Dyuldin
+* Grigorii Eremeev
+* Jason R. Coombs
+* Manuel Jacob
+* Mathieu Clabaut
+* Michael Seifert
+* Nikolaus Rath
+* Ronny Pfannschmidt
+* Tom V
+
+Happy testing,
+The pytest Development Team
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.5.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.5.rst
new file mode 100644
index 00000000000..3e2419d7e5d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.5.rst
@@ -0,0 +1,27 @@
+pytest-3.0.5
+============
+
+pytest 3.0.5 has just been released to PyPI.
+
+This is a bug-fix release, being a drop-in replacement. To upgrade::
+
+ pip install --upgrade pytest
+
+The changelog is available at http://doc.pytest.org/en/latest/changelog.html.
+
+Thanks to all who contributed to this release, among them:
+
+* Ana Vojnovic
+* Bruno Oliveira
+* Daniel Hahler
+* Duncan Betts
+* Igor Starikov
+* Ismail
+* Luke Murphy
+* Ned Batchelder
+* Ronny Pfannschmidt
+* Sebastian Ramacher
+* nmundar
+
+Happy testing,
+The pytest Development Team
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.6.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.6.rst
new file mode 100644
index 00000000000..2988b9cb3b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.6.rst
@@ -0,0 +1,33 @@
+pytest-3.0.6
+============
+
+pytest 3.0.6 has just been released to PyPI.
+
+This is a bug-fix release, being a drop-in replacement. To upgrade::
+
+ pip install --upgrade pytest
+
+The full changelog is available at http://doc.pytest.org/en/latest/changelog.html.
+
+
+Thanks to all who contributed to this release, among them:
+
+* Andreas Pelme
+* Bruno Oliveira
+* Dmitry Malinovsky
+* Eli Boyarski
+* Jakub Wilk
+* Jeff Widman
+* Loïc Estève
+* Luke Murphy
+* Miro Hrončok
+* Oscar Hellström
+* Peter Heatwole
+* Philippe Ombredanne
+* Ronny Pfannschmidt
+* Rutger Prins
+* Stefan Scherfke
+
+
+Happy testing,
+The pytest Development Team
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.7.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.7.rst
new file mode 100644
index 00000000000..591557aa787
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.0.7.rst
@@ -0,0 +1,33 @@
+pytest-3.0.7
+============
+
+pytest 3.0.7 has just been released to PyPI.
+
+This is a bug-fix release, being a drop-in replacement. To upgrade::
+
+ pip install --upgrade pytest
+
+The full changelog is available at http://doc.pytest.org/en/latest/changelog.html.
+
+Thanks to all who contributed to this release, among them:
+
+* Anthony Sottile
+* Barney Gale
+* Bruno Oliveira
+* Florian Bruhin
+* Floris Bruynooghe
+* Ionel Cristian Mărieș
+* Katerina Koukiou
+* NODA, Kai
+* Omer Hadari
+* Patrick Hayes
+* Ran Benita
+* Ronny Pfannschmidt
+* Victor Uriarte
+* Vidar Tonaas Fauske
+* Ville Skyttä
+* fbjorn
+* mbyt
+
+Happy testing,
+The pytest Development Team
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.1.0.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.1.0.rst
new file mode 100644
index 00000000000..99cc6bdbe20
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.1.0.rst
@@ -0,0 +1,61 @@
+pytest-3.1.0
+=======================================
+
+The pytest team is proud to announce the 3.1.0 release!
+
+pytest is a mature Python testing tool with more than a 1600 tests
+against itself, passing on many different interpreters and platforms.
+
+This release contains a bugs fixes and improvements, so users are encouraged
+to take a look at the CHANGELOG:
+
+http://doc.pytest.org/en/latest/changelog.html
+
+For complete documentation, please visit:
+
+ http://docs.pytest.org
+
+As usual, you can upgrade from pypi via:
+
+ pip install -U pytest
+
+Thanks to all who contributed to this release, among them:
+
+* Anthony Sottile
+* Ben Lloyd
+* Bruno Oliveira
+* David Giese
+* David Szotten
+* Dmitri Pribysh
+* Florian Bruhin
+* Florian Schulze
+* Floris Bruynooghe
+* John Towler
+* Jonas Obrist
+* Katerina Koukiou
+* Kodi Arfer
+* Krzysztof Szularz
+* Lev Maximov
+* Loïc Estève
+* Luke Murphy
+* Manuel Krebber
+* Matthew Duck
+* Matthias Bussonnier
+* Michael Howitz
+* Michal Wajszczuk
+* Paweł Adamczak
+* Rafael Bertoldi
+* Ravi Chandra
+* Ronny Pfannschmidt
+* Skylar Downes
+* Thomas Kriechbaumer
+* Vitaly Lashmanov
+* Vlad Dragos
+* Wheerd
+* Xander Johnson
+* mandeep
+* reut
+
+
+Happy testing,
+The Pytest Development Team
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.1.1.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.1.1.rst
new file mode 100644
index 00000000000..370b8fd7355
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.1.1.rst
@@ -0,0 +1,23 @@
+pytest-3.1.1
+=======================================
+
+pytest 3.1.1 has just been released to PyPI.
+
+This is a bug-fix release, being a drop-in replacement. To upgrade::
+
+ pip install --upgrade pytest
+
+The full changelog is available at http://doc.pytest.org/en/latest/changelog.html.
+
+Thanks to all who contributed to this release, among them:
+
+* Bruno Oliveira
+* Florian Bruhin
+* Floris Bruynooghe
+* Jason R. Coombs
+* Ronny Pfannschmidt
+* wanghui
+
+
+Happy testing,
+The pytest Development Team
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.1.2.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.1.2.rst
new file mode 100644
index 00000000000..60168a857ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.1.2.rst
@@ -0,0 +1,23 @@
+pytest-3.1.2
+=======================================
+
+pytest 3.1.2 has just been released to PyPI.
+
+This is a bug-fix release, being a drop-in replacement. To upgrade::
+
+ pip install --upgrade pytest
+
+The full changelog is available at http://doc.pytest.org/en/latest/changelog.html.
+
+Thanks to all who contributed to this release, among them:
+
+* Andreas Pelme
+* ApaDoctor
+* Bruno Oliveira
+* Florian Bruhin
+* Ronny Pfannschmidt
+* Segev Finer
+
+
+Happy testing,
+The pytest Development Team
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.1.3.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.1.3.rst
new file mode 100644
index 00000000000..a55280626ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.1.3.rst
@@ -0,0 +1,23 @@
+pytest-3.1.3
+=======================================
+
+pytest 3.1.3 has just been released to PyPI.
+
+This is a bug-fix release, being a drop-in replacement. To upgrade::
+
+ pip install --upgrade pytest
+
+The full changelog is available at http://doc.pytest.org/en/latest/changelog.html.
+
+Thanks to all who contributed to this release, among them:
+
+* Antoine Legrand
+* Bruno Oliveira
+* Max Moroz
+* Raphael Pierzina
+* Ronny Pfannschmidt
+* Ryan Fitzpatrick
+
+
+Happy testing,
+The pytest Development Team
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.2.0.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.2.0.rst
new file mode 100644
index 00000000000..4d2830edd2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.2.0.rst
@@ -0,0 +1,48 @@
+pytest-3.2.0
+=======================================
+
+The pytest team is proud to announce the 3.2.0 release!
+
+pytest is a mature Python testing tool with more than a 1600 tests
+against itself, passing on many different interpreters and platforms.
+
+This release contains a number of bugs fixes and improvements, so users are encouraged
+to take a look at the CHANGELOG:
+
+ http://doc.pytest.org/en/latest/changelog.html
+
+For complete documentation, please visit:
+
+ http://docs.pytest.org
+
+As usual, you can upgrade from pypi via:
+
+ pip install -U pytest
+
+Thanks to all who contributed to this release, among them:
+
+* Alex Hartoto
+* Andras Tim
+* Bruno Oliveira
+* Daniel Hahler
+* Florian Bruhin
+* Floris Bruynooghe
+* John Still
+* Jordan Moldow
+* Kale Kundert
+* Lawrence Mitchell
+* Llandy Riveron Del Risco
+* Maik Figura
+* Martin Altmayer
+* Mihai Capotă
+* Nathaniel Waisbrot
+* Nguyễn Hồng Quân
+* Pauli Virtanen
+* Raphael Pierzina
+* Ronny Pfannschmidt
+* Segev Finer
+* V.Kuznetsov
+
+
+Happy testing,
+The Pytest Development Team
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.2.1.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.2.1.rst
new file mode 100644
index 00000000000..899ffcd4b4a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.2.1.rst
@@ -0,0 +1,22 @@
+pytest-3.2.1
+=======================================
+
+pytest 3.2.1 has just been released to PyPI.
+
+This is a bug-fix release, being a drop-in replacement. To upgrade::
+
+ pip install --upgrade pytest
+
+The full changelog is available at http://doc.pytest.org/en/latest/changelog.html.
+
+Thanks to all who contributed to this release, among them:
+
+* Alex Gaynor
+* Bruno Oliveira
+* Florian Bruhin
+* Ronny Pfannschmidt
+* Srinivas Reddy Thatiparthy
+
+
+Happy testing,
+The pytest Development Team
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.2.2.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.2.2.rst
new file mode 100644
index 00000000000..599bf872775
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.2.2.rst
@@ -0,0 +1,28 @@
+pytest-3.2.2
+=======================================
+
+pytest 3.2.2 has just been released to PyPI.
+
+This is a bug-fix release, being a drop-in replacement. To upgrade::
+
+ pip install --upgrade pytest
+
+The full changelog is available at http://doc.pytest.org/en/latest/changelog.html.
+
+Thanks to all who contributed to this release, among them:
+
+* Andreas Pelme
+* Antonio Hidalgo
+* Bruno Oliveira
+* Felipe Dau
+* Fernando Macedo
+* Jesús Espino
+* Joan Massich
+* Joe Talbott
+* Kirill Pinchuk
+* Ronny Pfannschmidt
+* Xuan Luong
+
+
+Happy testing,
+The pytest Development Team
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.2.3.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.2.3.rst
new file mode 100644
index 00000000000..589374974d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.2.3.rst
@@ -0,0 +1,23 @@
+pytest-3.2.3
+=======================================
+
+pytest 3.2.3 has just been released to PyPI.
+
+This is a bug-fix release, being a drop-in replacement. To upgrade::
+
+ pip install --upgrade pytest
+
+The full changelog is available at http://doc.pytest.org/en/latest/changelog.html.
+
+Thanks to all who contributed to this release, among them:
+
+* Bruno Oliveira
+* Evan
+* Joe Hamman
+* Oliver Bestwalter
+* Ronny Pfannschmidt
+* Xuan Luong
+
+
+Happy testing,
+The pytest Development Team
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.2.4.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.2.4.rst
new file mode 100644
index 00000000000..44bfcc27e29
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.2.4.rst
@@ -0,0 +1,36 @@
+pytest-3.2.4
+=======================================
+
+pytest 3.2.4 has just been released to PyPI.
+
+This is a bug-fix release, being a drop-in replacement. To upgrade::
+
+ pip install --upgrade pytest
+
+The full changelog is available at http://doc.pytest.org/en/latest/changelog.html.
+
+Thanks to all who contributed to this release, among them:
+
+* Bruno Oliveira
+* Christian Boelsen
+* Christoph Buchner
+* Daw-Ran Liou
+* Florian Bruhin
+* Franck Michea
+* Leonard Lausen
+* Matty G
+* Owen Tuz
+* Pavel Karateev
+* Pierre GIRAUD
+* Ronny Pfannschmidt
+* Stephen Finucane
+* Sviatoslav Abakumov
+* Thomas Hisch
+* Tom Dalton
+* Xuan Luong
+* Yorgos Pagles
+* Семён Марьясин
+
+
+Happy testing,
+The pytest Development Team
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.2.5.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.2.5.rst
new file mode 100644
index 00000000000..a520ce2b333
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.2.5.rst
@@ -0,0 +1,18 @@
+pytest-3.2.5
+=======================================
+
+pytest 3.2.5 has just been released to PyPI.
+
+This is a bug-fix release, being a drop-in replacement. To upgrade::
+
+ pip install --upgrade pytest
+
+The full changelog is available at http://doc.pytest.org/en/latest/changelog.html.
+
+Thanks to all who contributed to this release, among them:
+
+* Bruno Oliveira
+
+
+Happy testing,
+The pytest Development Team
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.3.0.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.3.0.rst
new file mode 100644
index 00000000000..e0740e7d592
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/release-3.3.0.rst
@@ -0,0 +1,50 @@
+pytest-3.3.0
+=======================================
+
+The pytest team is proud to announce the 3.3.0 release!
+
+pytest is a mature Python testing tool with more than a 1600 tests
+against itself, passing on many different interpreters and platforms.
+
+This release contains a number of bugs fixes and improvements, so users are encouraged
+to take a look at the CHANGELOG:
+
+ http://doc.pytest.org/en/latest/changelog.html
+
+For complete documentation, please visit:
+
+ http://docs.pytest.org
+
+As usual, you can upgrade from pypi via:
+
+ pip install -U pytest
+
+Thanks to all who contributed to this release, among them:
+
+* Anthony Sottile
+* Bruno Oliveira
+* Ceridwen
+* Daniel Hahler
+* Dirk Thomas
+* Dmitry Malinovsky
+* Florian Bruhin
+* George Y. Kussumoto
+* Hugo
+* Jesús Espino
+* Joan Massich
+* Ofir
+* OfirOshir
+* Ronny Pfannschmidt
+* Samuel Dion-Girardeau
+* Srinivas Reddy Thatiparthy
+* Sviatoslav Abakumov
+* Tarcisio Fischer
+* Thomas Hisch
+* Tyler Goodlet
+* hugovk
+* je
+* prokaktus
+
+
+Happy testing,
+The Pytest Development Team
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/sprint2016.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/sprint2016.rst
new file mode 100644
index 00000000000..8e706589876
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/announce/sprint2016.rst
@@ -0,0 +1,64 @@
+python testing sprint June 20th-26th 2016
+======================================================
+
+.. image:: ../img/freiburg2.jpg
+ :width: 400
+
+The pytest core group held the biggest sprint
+in its history in June 2016, taking place in the black forest town Freiburg
+in Germany. In February 2016 we started a `funding
+campaign on Indiegogo to cover expenses
+<http://igg.me/at/pytest-sprint/x/4034848>`_ The page also mentions
+some preliminary topics:
+
+- improving pytest-xdist test scheduling to take into account
+ fixture setups and explicit user hints.
+
+- provide info on fixture dependencies during --collect-only
+
+- tying pytest-xdist to tox so that you can do "py.test -e py34"
+ to run tests in a particular tox-managed virtualenv. Also
+ look into making pytest-xdist use tox environments on
+ remote ssh-sides so that remote dependency management becomes
+ easier.
+
+- refactoring the fixture system so more people understand it :)
+
+- integrating PyUnit setup methods as autouse fixtures.
+ possibly adding ways to influence ordering of same-scoped
+ fixtures (so you can make a choice of which fixtures come
+ before others)
+
+- fixing bugs and issues from the tracker, really an endless source :)
+
+
+Participants
+--------------
+
+Over 20 participants took part from 4 continents, including employees
+from Splunk, Personalkollen, Cobe.io, FanDuel and Dolby. Some newcomers
+mixed with developers who have worked on pytest since its beginning, and
+of course everyone in between.
+
+
+Sprint organisation, schedule
+-------------------------------
+
+People arrived in Freiburg on the 19th, with sprint development taking
+place on 20th, 21st, 22nd, 24th and 25th. On the 23rd we took a break
+day for some hot hiking in the Black Forest.
+
+Sprint activity was organised heavily around pairing, with plenty of group
+discusssions to take advantage of the high bandwidth, and lightning talks
+as well.
+
+
+Money / funding
+---------------
+
+
+The Indiegogo campaign aimed for 11000 USD and in the end raised over
+12000, to reimburse travel costs, pay for a sprint venue and catering.
+
+Excess money is reserved for further sprint/travel funding for pytest/tox
+contributors.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/assert.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/assert.rst
new file mode 100644
index 00000000000..4a852978ed2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/assert.rst
@@ -0,0 +1,299 @@
+
+The writing and reporting of assertions in tests
+==================================================
+
+.. _`assertfeedback`:
+.. _`assert with the assert statement`:
+.. _`assert`:
+
+
+Asserting with the ``assert`` statement
+---------------------------------------------------------
+
+``pytest`` allows you to use the standard python ``assert`` for verifying
+expectations and values in Python tests. For example, you can write the
+following::
+
+ # content of test_assert1.py
+ def f():
+ return 3
+
+ def test_function():
+ assert f() == 4
+
+to assert that your function returns a certain value. If this assertion fails
+you will see the return value of the function call::
+
+ $ pytest test_assert1.py
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 1 item
+
+ test_assert1.py F [100%]
+
+ ================================= FAILURES =================================
+ ______________________________ test_function _______________________________
+
+ def test_function():
+ > assert f() == 4
+ E assert 3 == 4
+ E + where 3 = f()
+
+ test_assert1.py:5: AssertionError
+ ========================= 1 failed in 0.12 seconds =========================
+
+``pytest`` has support for showing the values of the most common subexpressions
+including calls, attributes, comparisons, and binary and unary
+operators. (See :ref:`tbreportdemo`). This allows you to use the
+idiomatic python constructs without boilerplate code while not losing
+introspection information.
+
+However, if you specify a message with the assertion like this::
+
+ assert a % 2 == 0, "value was odd, should be even"
+
+then no assertion introspection takes places at all and the message
+will be simply shown in the traceback.
+
+See :ref:`assert-details` for more information on assertion introspection.
+
+.. _`assertraises`:
+
+Assertions about expected exceptions
+------------------------------------------
+
+In order to write assertions about raised exceptions, you can use
+``pytest.raises`` as a context manager like this::
+
+ import pytest
+
+ def test_zero_division():
+ with pytest.raises(ZeroDivisionError):
+ 1 / 0
+
+and if you need to have access to the actual exception info you may use::
+
+ def test_recursion_depth():
+ with pytest.raises(RuntimeError) as excinfo:
+ def f():
+ f()
+ f()
+ assert 'maximum recursion' in str(excinfo.value)
+
+``excinfo`` is a ``ExceptionInfo`` instance, which is a wrapper around
+the actual exception raised. The main attributes of interest are
+``.type``, ``.value`` and ``.traceback``.
+
+.. versionchanged:: 3.0
+
+In the context manager form you may use the keyword argument
+``message`` to specify a custom failure message::
+
+ >>> with raises(ZeroDivisionError, message="Expecting ZeroDivisionError"):
+ ... pass
+ ... Failed: Expecting ZeroDivisionError
+
+If you want to write test code that works on Python 2.4 as well,
+you may also use two other ways to test for an expected exception::
+
+ pytest.raises(ExpectedException, func, *args, **kwargs)
+ pytest.raises(ExpectedException, "func(*args, **kwargs)")
+
+both of which execute the specified function with args and kwargs and
+asserts that the given ``ExpectedException`` is raised. The reporter will
+provide you with helpful output in case of failures such as *no
+exception* or *wrong exception*.
+
+Note that it is also possible to specify a "raises" argument to
+``pytest.mark.xfail``, which checks that the test is failing in a more
+specific way than just having any exception raised::
+
+ @pytest.mark.xfail(raises=IndexError)
+ def test_f():
+ f()
+
+Using ``pytest.raises`` is likely to be better for cases where you are testing
+exceptions your own code is deliberately raising, whereas using
+``@pytest.mark.xfail`` with a check function is probably better for something
+like documenting unfixed bugs (where the test describes what "should" happen)
+or bugs in dependencies.
+
+Also, the context manager form accepts a ``match`` keyword parameter to test
+that a regular expression matches on the string representation of an exception
+(like the ``TestCase.assertRaisesRegexp`` method from ``unittest``)::
+
+ import pytest
+
+ def myfunc():
+ raise ValueError("Exception 123 raised")
+
+ def test_match():
+ with pytest.raises(ValueError, match=r'.* 123 .*'):
+ myfunc()
+
+The regexp parameter of the ``match`` method is matched with the ``re.search``
+function. So in the above example ``match='123'`` would have worked as
+well.
+
+
+.. _`assertwarns`:
+
+Assertions about expected warnings
+-----------------------------------------
+
+.. versionadded:: 2.8
+
+You can check that code raises a particular warning using
+:ref:`pytest.warns <warns>`.
+
+
+.. _newreport:
+
+Making use of context-sensitive comparisons
+-------------------------------------------------
+
+.. versionadded:: 2.0
+
+``pytest`` has rich support for providing context-sensitive information
+when it encounters comparisons. For example::
+
+ # content of test_assert2.py
+
+ def test_set_comparison():
+ set1 = set("1308")
+ set2 = set("8035")
+ assert set1 == set2
+
+if you run this module::
+
+ $ pytest test_assert2.py
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 1 item
+
+ test_assert2.py F [100%]
+
+ ================================= FAILURES =================================
+ ___________________________ test_set_comparison ____________________________
+
+ def test_set_comparison():
+ set1 = set("1308")
+ set2 = set("8035")
+ > assert set1 == set2
+ E AssertionError: assert {'0', '1', '3', '8'} == {'0', '3', '5', '8'}
+ E Extra items in the left set:
+ E '1'
+ E Extra items in the right set:
+ E '5'
+ E Use -v to get the full diff
+
+ test_assert2.py:5: AssertionError
+ ========================= 1 failed in 0.12 seconds =========================
+
+Special comparisons are done for a number of cases:
+
+* comparing long strings: a context diff is shown
+* comparing long sequences: first failing indices
+* comparing dicts: different entries
+
+See the :ref:`reporting demo <tbreportdemo>` for many more examples.
+
+Defining your own assertion comparison
+----------------------------------------------
+
+It is possible to add your own detailed explanations by implementing
+the ``pytest_assertrepr_compare`` hook.
+
+.. autofunction:: _pytest.hookspec.pytest_assertrepr_compare
+ :noindex:
+
+As an example consider adding the following hook in a :ref:`conftest.py <conftest.py>`
+file which provides an alternative explanation for ``Foo`` objects::
+
+ # content of conftest.py
+ from test_foocompare import Foo
+ def pytest_assertrepr_compare(op, left, right):
+ if isinstance(left, Foo) and isinstance(right, Foo) and op == "==":
+ return ['Comparing Foo instances:',
+ ' vals: %s != %s' % (left.val, right.val)]
+
+now, given this test module::
+
+ # content of test_foocompare.py
+ class Foo(object):
+ def __init__(self, val):
+ self.val = val
+
+ def __eq__(self, other):
+ return self.val == other.val
+
+ def test_compare():
+ f1 = Foo(1)
+ f2 = Foo(2)
+ assert f1 == f2
+
+you can run the test module and get the custom output defined in
+the conftest file::
+
+ $ pytest -q test_foocompare.py
+ F [100%]
+ ================================= FAILURES =================================
+ _______________________________ test_compare _______________________________
+
+ def test_compare():
+ f1 = Foo(1)
+ f2 = Foo(2)
+ > assert f1 == f2
+ E assert Comparing Foo instances:
+ E vals: 1 != 2
+
+ test_foocompare.py:11: AssertionError
+ 1 failed in 0.12 seconds
+
+.. _assert-details:
+.. _`assert introspection`:
+
+Advanced assertion introspection
+----------------------------------
+
+.. versionadded:: 2.1
+
+
+Reporting details about a failing assertion is achieved by rewriting assert
+statements before they are run. Rewritten assert statements put introspection
+information into the assertion failure message. ``pytest`` only rewrites test
+modules directly discovered by its test collection process, so asserts in
+supporting modules which are not themselves test modules will not be rewritten.
+
+.. note::
+
+ ``pytest`` rewrites test modules on import by using an import
+ hook to write new ``pyc`` files. Most of the time this works transparently.
+ However, if you are messing with import yourself, the import hook may
+ interfere.
+
+ If this is the case you have two options:
+
+ * Disable rewriting for a specific module by adding the string
+ ``PYTEST_DONT_REWRITE`` to its docstring.
+
+ * Disable rewriting for all modules by using ``--assert=plain``.
+
+ Additionally, rewriting will fail silently if it cannot write new ``.pyc`` files,
+ i.e. in a read-only filesystem or a zipfile.
+
+
+For further information, Benjamin Peterson wrote up `Behind the scenes of pytest's new assertion rewriting <http://pybites.blogspot.com/2011/07/behind-scenes-of-pytests-new-assertion.html>`_.
+
+.. versionadded:: 2.1
+ Add assert rewriting as an alternate introspection technique.
+
+.. versionchanged:: 2.1
+ Introduce the ``--assert`` option. Deprecate ``--no-assert`` and
+ ``--nomagic``.
+
+.. versionchanged:: 3.0
+ Removes the ``--no-assert`` and ``--nomagic`` options.
+ Removes the ``--assert=reinterp`` option.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/backwards-compatibility.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/backwards-compatibility.rst
new file mode 100644
index 00000000000..84f2c43edaa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/backwards-compatibility.rst
@@ -0,0 +1,105 @@
+.. _backwards-compatibility:
+
+Backwards Compatibility Policy
+==============================
+
+Keeping backwards compatibility has a very high priority in the pytest project. Although we have deprecated functionality over the years, most of it is still supported. All deprecations in pytest were done because simpler or more efficient ways of accomplishing the same tasks have emerged, making the old way of doing things unnecessary.
+
+With the pytest 3.0 release we introduced a clear communication scheme for when we will actually remove the old busted joint and politely ask you to use the new hotness instead, while giving you enough time to adjust your tests or raise concerns if there are valid reasons to keep deprecated functionality around.
+
+To communicate changes we are already issuing deprecation warnings, but they are not displayed by default. In pytest 3.0 we changed the default setting so that pytest deprecation warnings are displayed if not explicitly silenced (with ``--disable-pytest-warnings``).
+
+We will only remove deprecated functionality in major releases (e.g. if we deprecate something in 3.0 we will remove it in 4.0), and keep it around for at least two minor releases (e.g. if we deprecate something in 3.9 and 4.0 is the next release, we will not remove it in 4.0 but in 5.0).
+
+
+Deprecation Roadmap
+-------------------
+
+This page lists deprecated features and when we plan to remove them. It is important to list the feature, the version where it got deprecated and the version we plan to remove it.
+
+Following our deprecation policy, we should aim to keep features for *at least* two minor versions after it was considered deprecated.
+
+
+Future Releases
+~~~~~~~~~~~~~~~
+
+3.4
+^^^
+
+**Old style classes**
+
+Issue: `#2147 <https://github.com/pytest-dev/pytest/issues/2147>`_.
+
+Deprecated in ``3.2``.
+
+4.0
+^^^
+
+**Yield tests**
+
+Deprecated in ``3.0``.
+
+**pytest-namespace hook**
+
+deprecated in ``3.2``.
+
+**Marks in parameter sets**
+
+Deprecated in ``3.2``.
+
+**--result-log**
+
+Deprecated in ``3.0``.
+
+See `#830 <https://github.com/pytest-dev/pytest/issues/830>`_ for more information. Suggested alternative: `pytest-tap <https://pypi.python.org/pypi/pytest-tap>`_.
+
+**metafunc.addcall**
+
+Issue: `#2876 <https://github.com/pytest-dev/pytest/issues/2876>`_.
+
+Deprecated in ``3.3``.
+
+**pytest_plugins in non-toplevel conftests**
+
+There is a deep conceptual confusion as ``conftest.py`` files themselves are activated/deactivated based on path, but the plugins they depend on aren't.
+
+Issue: `#2639 <https://github.com/pytest-dev/pytest/issues/2639>`_.
+
+Not yet officially deprecated.
+
+**passing a single string to pytest.main()**
+
+Pass a list of strings to ``pytest.main()`` instead.
+
+Deprecated in ``3.1``.
+
+**[pytest] section in setup.cfg**
+
+Use ``[tool:pytest]`` instead for compatibility with other tools.
+
+Deprecated in ``3.0``.
+
+Past Releases
+~~~~~~~~~~~~~
+
+3.0
+^^^
+
+* The following deprecated commandline options were removed:
+
+ * ``--genscript``: no longer supported;
+ * ``--no-assert``: use ``--assert=plain`` instead;
+ * ``--nomagic``: use ``--assert=plain`` instead;
+ * ``--report``: use ``-r`` instead;
+
+* Removed all ``py.test-X*`` entry points. The versioned, suffixed entry points
+ were never documented and a leftover from a pre-virtualenv era. These entry
+ points also created broken entry points in wheels, so removing them also
+ removes a source of confusion for users.
+
+
+
+3.3
+^^^
+
+* Dropped support for EOL Python 2.6 and 3.3. \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/bash-completion.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/bash-completion.rst
new file mode 100644
index 00000000000..81fe62183fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/bash-completion.rst
@@ -0,0 +1,28 @@
+
+.. _bash_completion:
+
+Setting up bash completion
+==========================
+
+When using bash as your shell, ``pytest`` can use argcomplete
+(https://argcomplete.readthedocs.io/) for auto-completion.
+For this ``argcomplete`` needs to be installed **and** enabled.
+
+Install argcomplete using::
+
+ sudo pip install 'argcomplete>=0.5.7'
+
+For global activation of all argcomplete enabled python applications run::
+
+ sudo activate-global-python-argcomplete
+
+For permanent (but not global) ``pytest`` activation, use::
+
+ register-python-argcomplete pytest >> ~/.bashrc
+
+For one-time activation of argcomplete for ``pytest`` only, use::
+
+ eval "$(register-python-argcomplete pytest)"
+
+
+
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/builtin.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/builtin.rst
new file mode 100644
index 00000000000..d11eb5606e0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/builtin.rst
@@ -0,0 +1,161 @@
+
+.. _`pytest helpers`:
+
+Pytest API and builtin fixtures
+================================================
+
+This is a list of ``pytest.*`` API functions and fixtures.
+
+For information on plugin hooks and objects, see :ref:`plugins`.
+
+For information on the ``pytest.mark`` mechanism, see :ref:`mark`.
+
+For the below objects, you can also interactively ask for help, e.g. by
+typing on the Python interactive prompt something like::
+
+ import pytest
+ help(pytest)
+
+.. currentmodule:: pytest
+
+Invoking pytest interactively
+---------------------------------------------------
+
+.. autofunction:: main
+
+More examples at :ref:`pytest.main-usage`
+
+
+Helpers for assertions about Exceptions/Warnings
+--------------------------------------------------------
+
+.. autofunction:: raises
+
+Examples at :ref:`assertraises`.
+
+.. autofunction:: deprecated_call
+
+Comparing floating point numbers
+--------------------------------
+
+.. autofunction:: approx
+
+Raising a specific test outcome
+--------------------------------------
+
+You can use the following functions in your test, fixture or setup
+functions to force a certain test outcome. Note that most often
+you can rather use declarative marks, see :ref:`skipping`.
+
+.. autofunction:: _pytest.outcomes.fail
+.. autofunction:: _pytest.outcomes.skip
+.. autofunction:: _pytest.outcomes.importorskip
+.. autofunction:: _pytest.outcomes.xfail
+.. autofunction:: _pytest.outcomes.exit
+
+Fixtures and requests
+-----------------------------------------------------
+
+To mark a fixture function:
+
+.. autofunction:: _pytest.fixtures.fixture
+
+Tutorial at :ref:`fixtures`.
+
+The ``request`` object that can be used from fixture functions.
+
+.. autoclass:: _pytest.fixtures.FixtureRequest()
+ :members:
+
+
+.. _builtinfixtures:
+.. _builtinfuncargs:
+
+Builtin fixtures/function arguments
+-----------------------------------------
+
+You can ask for available builtin or project-custom
+:ref:`fixtures <fixtures>` by typing::
+
+ $ pytest -q --fixtures
+ cache
+ Return a cache object that can persist state between testing sessions.
+
+ cache.get(key, default)
+ cache.set(key, value)
+
+ Keys must be a ``/`` separated value, where the first part is usually the
+ name of your plugin or application to avoid clashes with other cache users.
+
+ Values can be any object handled by the json stdlib module.
+ capsys
+ Enable capturing of writes to sys.stdout/sys.stderr and make
+ captured output available via ``capsys.readouterr()`` method calls
+ which return a ``(out, err)`` tuple. ``out`` and ``err`` will be ``text``
+ objects.
+ capsysbinary
+ Enable capturing of writes to sys.stdout/sys.stderr and make
+ captured output available via ``capsys.readouterr()`` method calls
+ which return a ``(out, err)`` tuple. ``out`` and ``err`` will be ``bytes``
+ objects.
+ capfd
+ Enable capturing of writes to file descriptors 1 and 2 and make
+ captured output available via ``capfd.readouterr()`` method calls
+ which return a ``(out, err)`` tuple. ``out`` and ``err`` will be ``text``
+ objects.
+ capfdbinary
+ Enable capturing of write to file descriptors 1 and 2 and make
+ captured output available via ``capfdbinary.readouterr`` method calls
+ which return a ``(out, err)`` tuple. ``out`` and ``err`` will be
+ ``bytes`` objects.
+ doctest_namespace
+ Inject names into the doctest namespace.
+ pytestconfig
+ the pytest config object with access to command line opts.
+ record_xml_property
+ Add extra xml properties to the tag for the calling test.
+ The fixture is callable with ``(name, value)``, with value being automatically
+ xml-encoded.
+ caplog
+ Access and control log capturing.
+
+ Captured logs are available through the following methods::
+
+ * caplog.text() -> string containing formatted log output
+ * caplog.records() -> list of logging.LogRecord instances
+ * caplog.record_tuples() -> list of (logger_name, level, message) tuples
+ monkeypatch
+ The returned ``monkeypatch`` fixture provides these
+ helper methods to modify objects, dictionaries or os.environ::
+
+ monkeypatch.setattr(obj, name, value, raising=True)
+ monkeypatch.delattr(obj, name, raising=True)
+ monkeypatch.setitem(mapping, name, value)
+ monkeypatch.delitem(obj, name, raising=True)
+ monkeypatch.setenv(name, value, prepend=False)
+ monkeypatch.delenv(name, value, raising=True)
+ monkeypatch.syspath_prepend(path)
+ monkeypatch.chdir(path)
+
+ All modifications will be undone after the requesting
+ test function or fixture has finished. The ``raising``
+ parameter determines if a KeyError or AttributeError
+ will be raised if the set/deletion operation has no target.
+ recwarn
+ Return a WarningsRecorder instance that provides these methods:
+
+ * ``pop(category=None)``: return last warning matching the category.
+ * ``clear()``: clear list of warnings
+
+ See http://docs.python.org/library/warnings.html for information
+ on warning categories.
+ tmpdir_factory
+ Return a TempdirFactory instance for the test session.
+ tmpdir
+ Return a temporary directory path object
+ which is unique to each test function invocation,
+ created as a sub directory of the base temporary
+ directory. The returned object is a `py.path.local`_
+ path object.
+
+ no tests ran in 0.12 seconds
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/cache.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/cache.rst
new file mode 100644
index 00000000000..c88721b11b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/cache.rst
@@ -0,0 +1,268 @@
+.. _`cache_provider`:
+.. _cache:
+
+
+Cache: working with cross-testrun state
+=======================================
+
+.. versionadded:: 2.8
+
+Usage
+---------
+
+The plugin provides two command line options to rerun failures from the
+last ``pytest`` invocation:
+
+* ``--lf``, ``--last-failed`` - to only re-run the failures.
+* ``--ff``, ``--failed-first`` - to run the failures first and then the rest of
+ the tests.
+
+For cleanup (usually not needed), a ``--cache-clear`` option allows to remove
+all cross-session cache contents ahead of a test run.
+
+Other plugins may access the `config.cache`_ object to set/get
+**json encodable** values between ``pytest`` invocations.
+
+.. note::
+
+ This plugin is enabled by default, but can be disabled if needed: see
+ :ref:`cmdunregister` (the internal name for this plugin is
+ ``cacheprovider``).
+
+
+Rerunning only failures or failures first
+-----------------------------------------------
+
+First, let's create 50 test invocation of which only 2 fail::
+
+ # content of test_50.py
+ import pytest
+
+ @pytest.mark.parametrize("i", range(50))
+ def test_num(i):
+ if i in (17, 25):
+ pytest.fail("bad luck")
+
+If you run this for the first time you will see two failures::
+
+ $ pytest -q
+ .................F.......F........................ [100%]
+ ================================= FAILURES =================================
+ _______________________________ test_num[17] _______________________________
+
+ i = 17
+
+ @pytest.mark.parametrize("i", range(50))
+ def test_num(i):
+ if i in (17, 25):
+ > pytest.fail("bad luck")
+ E Failed: bad luck
+
+ test_50.py:6: Failed
+ _______________________________ test_num[25] _______________________________
+
+ i = 25
+
+ @pytest.mark.parametrize("i", range(50))
+ def test_num(i):
+ if i in (17, 25):
+ > pytest.fail("bad luck")
+ E Failed: bad luck
+
+ test_50.py:6: Failed
+ 2 failed, 48 passed in 0.12 seconds
+
+If you then run it with ``--lf``::
+
+ $ pytest --lf
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 50 items
+ run-last-failure: rerun previous 2 failures
+
+ test_50.py FF [100%]
+
+ ================================= FAILURES =================================
+ _______________________________ test_num[17] _______________________________
+
+ i = 17
+
+ @pytest.mark.parametrize("i", range(50))
+ def test_num(i):
+ if i in (17, 25):
+ > pytest.fail("bad luck")
+ E Failed: bad luck
+
+ test_50.py:6: Failed
+ _______________________________ test_num[25] _______________________________
+
+ i = 25
+
+ @pytest.mark.parametrize("i", range(50))
+ def test_num(i):
+ if i in (17, 25):
+ > pytest.fail("bad luck")
+ E Failed: bad luck
+
+ test_50.py:6: Failed
+ =========================== 48 tests deselected ============================
+ ================= 2 failed, 48 deselected in 0.12 seconds ==================
+
+You have run only the two failing test from the last run, while 48 tests have
+not been run ("deselected").
+
+Now, if you run with the ``--ff`` option, all tests will be run but the first
+previous failures will be executed first (as can be seen from the series
+of ``FF`` and dots)::
+
+ $ pytest --ff
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 50 items
+ run-last-failure: rerun previous 2 failures first
+
+ test_50.py FF................................................ [100%]
+
+ ================================= FAILURES =================================
+ _______________________________ test_num[17] _______________________________
+
+ i = 17
+
+ @pytest.mark.parametrize("i", range(50))
+ def test_num(i):
+ if i in (17, 25):
+ > pytest.fail("bad luck")
+ E Failed: bad luck
+
+ test_50.py:6: Failed
+ _______________________________ test_num[25] _______________________________
+
+ i = 25
+
+ @pytest.mark.parametrize("i", range(50))
+ def test_num(i):
+ if i in (17, 25):
+ > pytest.fail("bad luck")
+ E Failed: bad luck
+
+ test_50.py:6: Failed
+ =================== 2 failed, 48 passed in 0.12 seconds ====================
+
+.. _`config.cache`:
+
+The new config.cache object
+--------------------------------
+
+.. regendoc:wipe
+
+Plugins or conftest.py support code can get a cached value using the
+pytest ``config`` object. Here is a basic example plugin which
+implements a :ref:`fixture` which re-uses previously created state
+across pytest invocations::
+
+ # content of test_caching.py
+ import pytest
+ import time
+
+ @pytest.fixture
+ def mydata(request):
+ val = request.config.cache.get("example/value", None)
+ if val is None:
+ time.sleep(9*0.6) # expensive computation :)
+ val = 42
+ request.config.cache.set("example/value", val)
+ return val
+
+ def test_function(mydata):
+ assert mydata == 23
+
+If you run this command once, it will take a while because
+of the sleep::
+
+ $ pytest -q
+ F [100%]
+ ================================= FAILURES =================================
+ ______________________________ test_function _______________________________
+
+ mydata = 42
+
+ def test_function(mydata):
+ > assert mydata == 23
+ E assert 42 == 23
+
+ test_caching.py:14: AssertionError
+ 1 failed in 0.12 seconds
+
+If you run it a second time the value will be retrieved from
+the cache and this will be quick::
+
+ $ pytest -q
+ F [100%]
+ ================================= FAILURES =================================
+ ______________________________ test_function _______________________________
+
+ mydata = 42
+
+ def test_function(mydata):
+ > assert mydata == 23
+ E assert 42 == 23
+
+ test_caching.py:14: AssertionError
+ 1 failed in 0.12 seconds
+
+See the `cache-api`_ for more details.
+
+
+Inspecting Cache content
+-------------------------------
+
+You can always peek at the content of the cache using the
+``--cache-show`` command line option::
+
+ $ py.test --cache-show
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ cachedir: $REGENDOC_TMPDIR/.cache
+ ------------------------------- cache values -------------------------------
+ cache/lastfailed contains:
+ {'test_caching.py::test_function': True}
+ example/value contains:
+ 42
+
+ ======================= no tests ran in 0.12 seconds =======================
+
+Clearing Cache content
+-------------------------------
+
+You can instruct pytest to clear all cache files and values
+by adding the ``--cache-clear`` option like this::
+
+ pytest --cache-clear
+
+This is recommended for invocations from Continuous Integration
+servers where isolation and correctness is more important
+than speed.
+
+
+.. _`cache-api`:
+
+config.cache API
+------------------
+
+The ``config.cache`` object allows other plugins,
+including ``conftest.py`` files,
+to safely and flexibly store and retrieve values across
+test runs because the ``config`` object is available
+in many places.
+
+Under the hood, the cache plugin uses the simple
+dumps/loads API of the json stdlib module
+
+.. currentmodule:: _pytest.cacheprovider
+
+.. automethod:: Cache.get
+.. automethod:: Cache.set
+.. automethod:: Cache.makedir
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/capture.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/capture.rst
new file mode 100644
index 00000000000..a87b57f8fc0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/capture.rst
@@ -0,0 +1,148 @@
+
+.. _`captures`:
+
+Capturing of the stdout/stderr output
+=========================================================
+
+Default stdout/stderr/stdin capturing behaviour
+---------------------------------------------------------
+
+During test execution any output sent to ``stdout`` and ``stderr`` is
+captured. If a test or a setup method fails its according captured
+output will usually be shown along with the failure traceback.
+
+In addition, ``stdin`` is set to a "null" object which will
+fail on attempts to read from it because it is rarely desired
+to wait for interactive input when running automated tests.
+
+By default capturing is done by intercepting writes to low level
+file descriptors. This allows to capture output from simple
+print statements as well as output from a subprocess started by
+a test.
+
+Setting capturing methods or disabling capturing
+-------------------------------------------------
+
+There are two ways in which ``pytest`` can perform capturing:
+
+* file descriptor (FD) level capturing (default): All writes going to the
+ operating system file descriptors 1 and 2 will be captured.
+
+* ``sys`` level capturing: Only writes to Python files ``sys.stdout``
+ and ``sys.stderr`` will be captured. No capturing of writes to
+ filedescriptors is performed.
+
+.. _`disable capturing`:
+
+You can influence output capturing mechanisms from the command line::
+
+ pytest -s # disable all capturing
+ pytest --capture=sys # replace sys.stdout/stderr with in-mem files
+ pytest --capture=fd # also point filedescriptors 1 and 2 to temp file
+
+.. _printdebugging:
+
+Using print statements for debugging
+---------------------------------------------------
+
+One primary benefit of the default capturing of stdout/stderr output
+is that you can use print statements for debugging::
+
+ # content of test_module.py
+
+ def setup_function(function):
+ print ("setting up %s" % function)
+
+ def test_func1():
+ assert True
+
+ def test_func2():
+ assert False
+
+and running this module will show you precisely the output
+of the failing function and hide the other one::
+
+ $ pytest
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 2 items
+
+ test_module.py .F [100%]
+
+ ================================= FAILURES =================================
+ ________________________________ test_func2 ________________________________
+
+ def test_func2():
+ > assert False
+ E assert False
+
+ test_module.py:9: AssertionError
+ -------------------------- Captured stdout setup ---------------------------
+ setting up <function test_func2 at 0xdeadbeef>
+ ==================== 1 failed, 1 passed in 0.12 seconds ====================
+
+Accessing captured output from a test function
+---------------------------------------------------
+
+The ``capsys``, ``capsysbinary``, ``capfd``, and ``capfdbinary`` fixtures
+allow access to stdout/stderr output created during test execution. Here is
+an example test function that performs some output related checks:
+
+.. code-block:: python
+
+ def test_myoutput(capsys): # or use "capfd" for fd-level
+ print ("hello")
+ sys.stderr.write("world\n")
+ out, err = capsys.readouterr()
+ assert out == "hello\n"
+ assert err == "world\n"
+ print ("next")
+ out, err = capsys.readouterr()
+ assert out == "next\n"
+
+The ``readouterr()`` call snapshots the output so far -
+and capturing will be continued. After the test
+function finishes the original streams will
+be restored. Using ``capsys`` this way frees your
+test from having to care about setting/resetting
+output streams and also interacts well with pytest's
+own per-test capturing.
+
+If you want to capture on filedescriptor level you can use
+the ``capfd`` fixture which offers the exact
+same interface but allows to also capture output from
+libraries or subprocesses that directly write to operating
+system level output streams (FD1 and FD2).
+
+.. versionadded:: 3.3
+
+If the code under test writes non-textual data, you can capture this using
+the ``capsysbinary`` fixture which instead returns ``bytes`` from
+the ``readouterr`` method. The ``capfsysbinary`` fixture is currently only
+available in python 3.
+
+
+.. versionadded:: 3.3
+
+If the code under test writes non-textual data, you can capture this using
+the ``capfdbinary`` fixture which instead returns ``bytes`` from
+the ``readouterr`` method. The ``capfdbinary`` fixture operates on the
+filedescriptor level.
+
+
+.. versionadded:: 3.0
+
+To temporarily disable capture within a test, both ``capsys``
+and ``capfd`` have a ``disabled()`` method that can be used
+as a context manager, disabling capture inside the ``with`` block:
+
+.. code-block:: python
+
+ def test_disabling_capturing(capsys):
+ print('this output is captured')
+ with capsys.disabled():
+ print('output not captured, going directly to sys.stdout')
+ print('this output is also captured')
+
+.. include:: links.inc
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/changelog.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/changelog.rst
index a59b3c7e250..a59b3c7e250 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/changelog.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/changelog.rst
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/check_sphinx.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/check_sphinx.py
index 0f536ffa6ac..0f536ffa6ac 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/check_sphinx.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/check_sphinx.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/conf.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/conf.py
new file mode 100644
index 00000000000..40f1e4165e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/conf.py
@@ -0,0 +1,323 @@
+# -*- coding: utf-8 -*-
+#
+# pytest documentation build configuration file, created by
+# sphinx-quickstart on Fri Oct 8 17:54:28 2010.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The full version, including alpha/beta/rc tags.
+# The short X.Y version.
+
+import os, sys
+from _pytest import __version__ as version
+release = ".".join(version.split(".")[:2])
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.insert(0, os.path.abspath('.'))
+
+autodoc_member_order = "bysource"
+todo_include_todos = 1
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.autosummary',
+ 'sphinx.ext.intersphinx', 'sphinx.ext.viewcode']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'contents'
+
+# General information about the project.
+project = u'pytest'
+copyright = u'2015, holger krekel and pytest-dev team'
+
+
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['links.inc', '_build', 'naming20.rst', 'test/*',
+ "old_*",
+ '*attic*',
+ '*/attic*',
+ 'funcargs.rst',
+ 'setup.rst',
+ 'example/remoteinterp.rst',
+ ]
+
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+add_module_names = False
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+sys.path.append(os.path.abspath('_themes'))
+html_theme_path = ['_themes']
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+html_theme = 'flask'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+html_theme_options = {
+ 'index_logo': None
+}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+html_title = 'pytest documentation'
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+html_short_title = "pytest-%s" % release
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+html_logo = "img/pytest1.png"
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+html_favicon = "img/pytest1favi.ico"
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+# html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+#html_sidebars = {'index': 'indexsidebar.html'}
+
+html_sidebars = {
+ 'index': [
+ 'sidebarintro.html',
+ 'globaltoc.html',
+ 'links.html',
+ 'sourcelink.html',
+ 'searchbox.html'
+ ],
+ '**': [
+ 'globaltoc.html',
+ 'relations.html',
+ 'links.html',
+ 'sourcelink.html',
+ 'searchbox.html'
+ ]
+}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+#html_additional_pages = {'index': 'index.html'}
+
+
+# If false, no module index is generated.
+html_domain_indices = True
+
+# If false, no index is generated.
+html_use_index = False
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+html_show_sourcelink = False
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'pytestdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+ ('contents', 'pytest.tex', u'pytest Documentation',
+ u'holger krekel, trainer and consultant, http://merlinux.eu', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+latex_logo = 'img/pytest1.png'
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+latex_domain_indices = False
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ ('usage', 'pytest', u'pytest usage',
+ [u'holger krekel at merlinux eu'], 1)
+]
+
+
+# -- Options for Epub output ---------------------------------------------------
+
+# Bibliographic Dublin Core info.
+epub_title = u'pytest'
+epub_author = u'holger krekel at merlinux eu'
+epub_publisher = u'holger krekel at merlinux eu'
+epub_copyright = u'2013, holger krekel et alii'
+
+# The language of the text. It defaults to the language option
+# or en if the language is not set.
+#epub_language = ''
+
+# The scheme of the identifier. Typical schemes are ISBN or URL.
+#epub_scheme = ''
+
+# The unique identifier of the text. This can be a ISBN number
+# or the project homepage.
+#epub_identifier = ''
+
+# A unique identification for the text.
+#epub_uid = ''
+
+# HTML files that should be inserted before the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#epub_pre_files = []
+
+# HTML files shat should be inserted after the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#epub_post_files = []
+
+# A list of files that should not be packed into the epub file.
+#epub_exclude_files = []
+
+# The depth of the table of contents in toc.ncx.
+#epub_tocdepth = 3
+
+# Allow duplicate toc entries.
+#epub_tocdup = True
+
+
+# -- Options for texinfo output ------------------------------------------------
+
+texinfo_documents = [
+ (master_doc, 'pytest', 'pytest Documentation',
+ ('Holger Krekel@*Benjamin Peterson@*Ronny Pfannschmidt@*'
+ 'Floris Bruynooghe@*others'),
+ 'pytest',
+ 'simple powerful testing with Python',
+ 'Programming',
+ 1),
+]
+
+
+# Example configuration for intersphinx: refer to the Python standard library.
+intersphinx_mapping = {'python': ('http://docs.python.org/', None),
+# 'lib': ("http://docs.python.org/2.7library/", None),
+ }
+
+
+def setup(app):
+ #from sphinx.ext.autodoc import cut_lines
+ #app.connect('autodoc-process-docstring', cut_lines(4, what=['module']))
+ app.add_description_unit('confval', 'confval',
+ objname='configuration value',
+ indextemplate='pair: %s; configuration value')
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/conftest.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/conftest.py
index 1a62e1b5df5..1a62e1b5df5 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/conftest.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/conftest.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/contact.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/contact.rst
new file mode 100644
index 00000000000..83d496640d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/contact.rst
@@ -0,0 +1,50 @@
+
+.. _`contact channels`:
+.. _`contact`:
+
+Contact channels
+===================================
+
+- `pytest issue tracker`_ to report bugs or suggest features (for version
+ 2.0 and above).
+
+- `pytest on stackoverflow.com <http://stackoverflow.com/search?q=pytest>`_
+ to post questions with the tag ``pytest``. New Questions will usually
+ be seen by pytest users or developers and answered quickly.
+
+- `Testing In Python`_: a mailing list for Python testing tools and discussion.
+
+- `pytest-dev at python.org (mailing list)`_ pytest specific announcements and discussions.
+
+- `pytest-commit at python.org (mailing list)`_: for commits and new issues
+
+- :doc:`contribution guide <contributing>` for help on submitting pull
+ requests to GitHub.
+
+- ``#pylib`` on irc.freenode.net IRC channel for random questions.
+
+- private mail to Holger.Krekel at gmail com if you want to communicate sensitive issues
+
+
+- `merlinux.eu`_ offers pytest and tox-related professional teaching and
+ consulting.
+
+.. _`pytest issue tracker`: https://github.com/pytest-dev/pytest/issues
+.. _`old issue tracker`: http://bitbucket.org/hpk42/py-trunk/issues/
+
+.. _`merlinux.eu`: http://merlinux.eu
+
+.. _`get an account`:
+
+.. _tetamap: http://tetamap.wordpress.com
+
+.. _`@pylibcommit`: http://twitter.com/pylibcommit
+
+
+.. _`Testing in Python`: http://lists.idyll.org/listinfo/testing-in-python
+.. _FOAF: http://en.wikipedia.org/wiki/FOAF
+.. _`py-dev`:
+.. _`development mailing list`:
+.. _`pytest-dev at python.org (mailing list)`: http://mail.python.org/mailman/listinfo/pytest-dev
+.. _`pytest-commit at python.org (mailing list)`: http://mail.python.org/mailman/listinfo/pytest-commit
+
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/contents.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/contents.rst
new file mode 100644
index 00000000000..7a6570e0bc5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/contents.rst
@@ -0,0 +1,65 @@
+.. _toc:
+
+Full pytest documentation
+===========================
+
+`Download latest version as PDF <https://media.readthedocs.org/pdf/pytest/latest/pytest.pdf>`_
+
+.. `Download latest version as EPUB <http://media.readthedocs.org/epub/pytest/latest/pytest.epub>`_
+
+.. toctree::
+ :maxdepth: 2
+
+ getting-started
+ usage
+ existingtestsuite
+ assert
+ builtin
+ fixture
+ monkeypatch
+ tmpdir
+ capture
+ warnings
+ doctest
+ mark
+ skipping
+ parametrize
+ cache
+ unittest
+ nose
+ xunit_setup
+ plugins
+ writing_plugins
+ logging
+
+ goodpractices
+ pythonpath
+ customize
+ example/index
+ bash-completion
+
+ backwards-compatibility
+ historical-notes
+ license
+ contributing
+ development_guide
+ talks
+ projects
+ faq
+ contact
+
+.. only:: html
+
+ .. toctree::
+ :maxdepth: 1
+
+ announce/index
+
+.. only:: html
+
+ .. toctree::
+ :hidden:
+ :maxdepth: 1
+
+ changelog
+
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/contributing.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/contributing.rst
index 2b6578f6b97..2b6578f6b97 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/contributing.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/contributing.rst
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/customize.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/customize.rst
new file mode 100644
index 00000000000..8133704a52c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/customize.rst
@@ -0,0 +1,333 @@
+Configuration
+=============
+
+Command line options and configuration file settings
+-----------------------------------------------------------------
+
+You can get help on command line options and values in INI-style
+configurations files by using the general help option::
+
+ pytest -h # prints options _and_ config file settings
+
+This will display command line and configuration file settings
+which were registered by installed plugins.
+
+.. _rootdir:
+.. _inifiles:
+
+Initialization: determining rootdir and inifile
+-----------------------------------------------
+
+.. versionadded:: 2.7
+
+pytest determines a ``rootdir`` for each test run which depends on
+the command line arguments (specified test files, paths) and on
+the existence of *ini-files*. The determined ``rootdir`` and *ini-file* are
+printed as part of the pytest header during startup.
+
+Here's a summary what ``pytest`` uses ``rootdir`` for:
+
+* Construct *nodeids* during collection; each test is assigned
+ a unique *nodeid* which is rooted at the ``rootdir`` and takes in account full path,
+ class name, function name and parametrization (if any).
+
+* Is used by plugins as a stable location to store project/test run specific information;
+ for example, the internal :ref:`cache <cache>` plugin creates a ``.cache`` subdirectory
+ in ``rootdir`` to store its cross-test run state.
+
+Important to emphasize that ``rootdir`` is **NOT** used to modify ``sys.path``/``PYTHONPATH`` or
+influence how modules are imported. See :ref:`pythonpath` for more details.
+
+Finding the ``rootdir``
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Here is the algorithm which finds the rootdir from ``args``:
+
+- determine the common ancestor directory for the specified ``args`` that are
+ recognised as paths that exist in the file system. If no such paths are
+ found, the common ancestor directory is set to the current working directory.
+
+- look for ``pytest.ini``, ``tox.ini`` and ``setup.cfg`` files in the ancestor
+ directory and upwards. If one is matched, it becomes the ini-file and its
+ directory becomes the rootdir.
+
+- if no ini-file was found, look for ``setup.py`` upwards from the common
+ ancestor directory to determine the ``rootdir``.
+
+- if no ``setup.py`` was found, look for ``pytest.ini``, ``tox.ini`` and
+ ``setup.cfg`` in each of the specified ``args`` and upwards. If one is
+ matched, it becomes the ini-file and its directory becomes the rootdir.
+
+- if no ini-file was found, use the already determined common ancestor as root
+ directory. This allows the use of pytest in structures that are not part of
+ a package and don't have any particular ini-file configuration.
+
+If no ``args`` are given, pytest collects test below the current working
+directory and also starts determining the rootdir from there.
+
+:warning: custom pytest plugin commandline arguments may include a path, as in
+ ``pytest --log-output ../../test.log args``. Then ``args`` is mandatory,
+ otherwise pytest uses the folder of test.log for rootdir determination
+ (see also `issue 1435 <https://github.com/pytest-dev/pytest/issues/1435>`_).
+ A dot ``.`` for referencing to the current working directory is also
+ possible.
+
+Note that an existing ``pytest.ini`` file will always be considered a match,
+whereas ``tox.ini`` and ``setup.cfg`` will only match if they contain a
+``[pytest]`` or ``[tool:pytest]`` section, respectively. Options from multiple ini-files candidates are never
+merged - the first one wins (``pytest.ini`` always wins, even if it does not
+contain a ``[pytest]`` section).
+
+The ``config`` object will subsequently carry these attributes:
+
+- ``config.rootdir``: the determined root directory, guaranteed to exist.
+
+- ``config.inifile``: the determined ini-file, may be ``None``.
+
+The rootdir is used a reference directory for constructing test
+addresses ("nodeids") and can be used also by plugins for storing
+per-testrun information.
+
+Example::
+
+ pytest path/to/testdir path/other/
+
+will determine the common ancestor as ``path`` and then
+check for ini-files as follows::
+
+ # first look for pytest.ini files
+ path/pytest.ini
+ path/setup.cfg # must also contain [tool:pytest] section to match
+ path/tox.ini # must also contain [pytest] section to match
+ pytest.ini
+ ... # all the way down to the root
+
+ # now look for setup.py
+ path/setup.py
+ setup.py
+ ... # all the way down to the root
+
+
+.. _`how to change command line options defaults`:
+.. _`adding default options`:
+
+
+
+How to change command line options defaults
+------------------------------------------------
+
+It can be tedious to type the same series of command line options
+every time you use ``pytest``. For example, if you always want to see
+detailed info on skipped and xfailed tests, as well as have terser "dot"
+progress output, you can write it into a configuration file:
+
+.. code-block:: ini
+
+ # content of pytest.ini
+ # (or tox.ini or setup.cfg)
+ [pytest]
+ addopts = -ra -q
+
+Alternatively, you can set a ``PYTEST_ADDOPTS`` environment variable to add command
+line options while the environment is in use::
+
+ export PYTEST_ADDOPTS="-v"
+
+Here's how the command-line is built in the presence of ``addopts`` or the environment variable::
+
+ <pytest.ini:addopts> $PYTEST_ADDOTPS <extra command-line arguments>
+
+So if the user executes in the command-line::
+
+ pytest -m slow
+
+The actual command line executed is::
+
+ pytest -ra -q -v -m slow
+
+Note that as usual for other command-line applications, in case of conflicting options the last one wins, so the example
+above will show verbose output because ``-v`` overwrites ``-q``.
+
+
+Builtin configuration file options
+----------------------------------------------
+
+.. confval:: minversion
+
+ Specifies a minimal pytest version required for running tests.
+
+ minversion = 2.1 # will fail if we run with pytest-2.0
+
+.. confval:: addopts
+
+ Add the specified ``OPTS`` to the set of command line arguments as if they
+ had been specified by the user. Example: if you have this ini file content:
+
+ .. code-block:: ini
+
+ [pytest]
+ addopts = --maxfail=2 -rf # exit after 2 failures, report fail info
+
+ issuing ``pytest test_hello.py`` actually means::
+
+ pytest --maxfail=2 -rf test_hello.py
+
+ Default is to add no options.
+
+.. confval:: norecursedirs
+
+ Set the directory basename patterns to avoid when recursing
+ for test discovery. The individual (fnmatch-style) patterns are
+ applied to the basename of a directory to decide if to recurse into it.
+ Pattern matching characters::
+
+ * matches everything
+ ? matches any single character
+ [seq] matches any character in seq
+ [!seq] matches any char not in seq
+
+ Default patterns are ``'.*', 'build', 'dist', 'CVS', '_darcs', '{arch}', '*.egg', 'venv'``.
+ Setting a ``norecursedirs`` replaces the default. Here is an example of
+ how to avoid certain directories:
+
+ .. code-block:: ini
+
+ # content of pytest.ini
+ [pytest]
+ norecursedirs = .svn _build tmp*
+
+ This would tell ``pytest`` to not look into typical subversion or
+ sphinx-build directories or into any ``tmp`` prefixed directory.
+
+ Additionally, ``pytest`` will attempt to intelligently identify and ignore a
+ virtualenv by the presence of an activation script. Any directory deemed to
+ be the root of a virtual environment will not be considered during test
+ collection unless ``‑‑collect‑in‑virtualenv`` is given. Note also that
+ ``norecursedirs`` takes precedence over ``‑‑collect‑in‑virtualenv``; e.g. if
+ you intend to run tests in a virtualenv with a base directory that matches
+ ``'.*'`` you *must* override ``norecursedirs`` in addition to using the
+ ``‑‑collect‑in‑virtualenv`` flag.
+
+.. confval:: testpaths
+
+ .. versionadded:: 2.8
+
+ Sets list of directories that should be searched for tests when
+ no specific directories, files or test ids are given in the command line when
+ executing pytest from the :ref:`rootdir <rootdir>` directory.
+ Useful when all project tests are in a known location to speed up
+ test collection and to avoid picking up undesired tests by accident.
+
+ .. code-block:: ini
+
+ # content of pytest.ini
+ [pytest]
+ testpaths = testing doc
+
+ This tells pytest to only look for tests in ``testing`` and ``doc``
+ directories when executing from the root directory.
+
+.. confval:: python_files
+
+ One or more Glob-style file patterns determining which python files
+ are considered as test modules. By default, pytest will consider
+ any file matching with ``test_*.py`` and ``*_test.py`` globs as a test
+ module.
+
+.. confval:: python_classes
+
+ One or more name prefixes or glob-style patterns determining which classes
+ are considered for test collection. By default, pytest will consider any
+ class prefixed with ``Test`` as a test collection. Here is an example of how
+ to collect tests from classes that end in ``Suite``:
+
+ .. code-block:: ini
+
+ # content of pytest.ini
+ [pytest]
+ python_classes = *Suite
+
+ Note that ``unittest.TestCase`` derived classes are always collected
+ regardless of this option, as ``unittest``'s own collection framework is used
+ to collect those tests.
+
+.. confval:: python_functions
+
+ One or more name prefixes or glob-patterns determining which test functions
+ and methods are considered tests. By default, pytest will consider any
+ function prefixed with ``test`` as a test. Here is an example of how
+ to collect test functions and methods that end in ``_test``:
+
+ .. code-block:: ini
+
+ # content of pytest.ini
+ [pytest]
+ python_functions = *_test
+
+ Note that this has no effect on methods that live on a ``unittest
+ .TestCase`` derived class, as ``unittest``'s own collection framework is used
+ to collect those tests.
+
+ See :ref:`change naming conventions` for more detailed examples.
+
+.. confval:: doctest_optionflags
+
+ One or more doctest flag names from the standard ``doctest`` module.
+ :doc:`See how pytest handles doctests <doctest>`.
+
+.. confval:: confcutdir
+
+ Sets a directory where search upwards for ``conftest.py`` files stops.
+ By default, pytest will stop searching for ``conftest.py`` files upwards
+ from ``pytest.ini``/``tox.ini``/``setup.cfg`` of the project if any,
+ or up to the file-system root.
+
+
+.. confval:: filterwarnings
+
+ .. versionadded:: 3.1
+
+ Sets a list of filters and actions that should be taken for matched
+ warnings. By default all warnings emitted during the test session
+ will be displayed in a summary at the end of the test session.
+
+ .. code-block:: ini
+
+ # content of pytest.ini
+ [pytest]
+ filterwarnings =
+ error
+ ignore::DeprecationWarning
+
+ This tells pytest to ignore deprecation warnings and turn all other warnings
+ into errors. For more information please refer to :ref:`warnings`.
+
+.. confval:: cache_dir
+
+ .. versionadded:: 3.2
+
+ Sets a directory where stores content of cache plugin. Default directory is
+ ``.cache`` which is created in :ref:`rootdir <rootdir>`. Directory may be
+ relative or absolute path. If setting relative path, then directory is created
+ relative to :ref:`rootdir <rootdir>`. Additionally path may contain environment
+ variables, that will be expanded. For more information about cache plugin
+ please refer to :ref:`cache_provider`.
+
+
+.. confval:: console_output_style
+
+ .. versionadded:: 3.3
+
+ Sets the console output style while running tests:
+
+ * ``classic``: classic pytest output.
+ * ``progress``: like classic pytest output, but with a progress indicator.
+
+ The default is ``progress``, but you can fallback to ``classic`` if you prefer or
+ the new mode is causing unexpected problems:
+
+ .. code-block:: ini
+
+ # content of pytest.ini
+ [pytest]
+ console_output_style = classic
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/development_guide.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/development_guide.rst
new file mode 100644
index 00000000000..465e97de0f9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/development_guide.rst
@@ -0,0 +1,108 @@
+=================
+Development Guide
+=================
+
+Some general guidelines regarding development in pytest for core maintainers and general contributors. Nothing here
+is set in stone and can't be changed, feel free to suggest improvements or changes in the workflow.
+
+
+Code Style
+----------
+
+* `PEP-8 <https://www.python.org/dev/peps/pep-0008>`_
+* `flake8 <https://pypi.python.org/pypi/flake8>`_ for quality checks
+* `invoke <http://www.pyinvoke.org/>`_ to automate development tasks
+
+
+Branches
+--------
+
+We have two long term branches:
+
+* ``master``: contains the code for the next bugfix release.
+* ``features``: contains the code with new features for the next minor release.
+
+The official repository usually does not contain topic branches, developers and contributors should create topic
+branches in their own forks.
+
+Exceptions can be made for cases where more than one contributor is working on the same
+topic or where it makes sense to use some automatic capability of the main repository, such as automatic docs from
+`readthedocs <readthedocs.org>`_ for a branch dealing with documentation refactoring.
+
+Issues
+------
+
+Any question, feature, bug or proposal is welcome as an issue. Users are encouraged to use them whenever they need.
+
+GitHub issues should use labels to categorize them. Labels should be created sporadically, to fill a niche; we should
+avoid creating labels just for the sake of creating them.
+
+Here is a list of labels and a brief description mentioning their intent.
+
+
+**Type**
+
+* ``type: backward compatibility``: issue that will cause problems with old pytest versions.
+* ``type: bug``: problem that needs to be addressed.
+* ``type: deprecation``: feature that will be deprecated in the future.
+* ``type: docs``: documentation missing or needing clarification.
+* ``type: enhancement``: new feature or API change, should be merged into ``features``.
+* ``type: feature-branch``: new feature or API change, should be merged into ``features``.
+* ``type: infrastructure``: improvement to development/releases/CI structure.
+* ``type: performance``: performance or memory problem/improvement.
+* ``type: proposal``: proposal for a new feature, often to gather opinions or design the API around the new feature.
+* ``type: question``: question regarding usage, installation, internals or how to test something.
+* ``type: refactoring``: internal improvements to the code.
+* ``type: regression``: indicates a problem that was introduced in a release which was working previously.
+
+**Status**
+
+* ``status: critical``: grave problem or usability issue that affects lots of users.
+* ``status: easy``: easy issue that is friendly to new contributors.
+* ``status: help wanted``: core developers need help from experts on this topic.
+* ``status: needs information``: reporter needs to provide more information; can be closed after 2 or more weeks of inactivity.
+
+**Topic**
+
+* ``topic: collection``
+* ``topic: fixtures``
+* ``topic: parametrize``
+* ``topic: reporting``
+* ``topic: selection``
+* ``topic: tracebacks``
+
+**Plugin (internal or external)**
+
+* ``plugin: cache``
+* ``plugin: capture``
+* ``plugin: doctests``
+* ``plugin: junitxml``
+* ``plugin: monkeypatch``
+* ``plugin: nose``
+* ``plugin: pastebin``
+* ``plugin: pytester``
+* ``plugin: tmpdir``
+* ``plugin: unittest``
+* ``plugin: warnings``
+* ``plugin: xdist``
+
+
+**OS**
+
+Issues specific to a single operating system. Do not use as a means to indicate where an issue originated from, only
+for problems that happen **only** in that system.
+
+* ``os: linux``
+* ``os: mac``
+* ``os: windows``
+
+**Temporary**
+
+Used to classify issues for limited time, to help find issues related in events for example.
+They should be removed after they are no longer relevant.
+
+* ``temporary: EP2017 sprint``:
+* ``temporary: sprint-candidate``:
+
+
+.. include:: ../../HOWTORELEASE.rst
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/doctest.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/doctest.rst
new file mode 100644
index 00000000000..4c5a878dd61
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/doctest.rst
@@ -0,0 +1,165 @@
+
+Doctest integration for modules and test files
+=========================================================
+
+By default all files matching the ``test*.txt`` pattern will
+be run through the python standard ``doctest`` module. You
+can change the pattern by issuing::
+
+ pytest --doctest-glob='*.rst'
+
+on the command line. Since version ``2.9``, ``--doctest-glob``
+can be given multiple times in the command-line.
+
+.. versionadded:: 3.1
+
+ You can specify the encoding that will be used for those doctest files
+ using the ``doctest_encoding`` ini option:
+
+ .. code-block:: ini
+
+ # content of pytest.ini
+ [pytest]
+ doctest_encoding = latin1
+
+ The default encoding is UTF-8.
+
+You can also trigger running of doctests
+from docstrings in all python modules (including regular
+python test modules)::
+
+ pytest --doctest-modules
+
+You can make these changes permanent in your project by
+putting them into a pytest.ini file like this:
+
+.. code-block:: ini
+
+ # content of pytest.ini
+ [pytest]
+ addopts = --doctest-modules
+
+If you then have a text file like this::
+
+ # content of example.rst
+
+ hello this is a doctest
+ >>> x = 3
+ >>> x
+ 3
+
+and another like this::
+
+ # content of mymodule.py
+ def something():
+ """ a doctest in a docstring
+ >>> something()
+ 42
+ """
+ return 42
+
+then you can just invoke ``pytest`` without command line options::
+
+ $ pytest
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
+ collected 1 item
+
+ mymodule.py . [100%]
+
+ ========================= 1 passed in 0.12 seconds =========================
+
+It is possible to use fixtures using the ``getfixture`` helper::
+
+ # content of example.rst
+ >>> tmp = getfixture('tmpdir')
+ >>> ...
+ >>>
+
+Also, :ref:`usefixtures` and :ref:`autouse` fixtures are supported
+when executing text doctest files.
+
+The standard ``doctest`` module provides some setting flags to configure the
+strictness of doctest tests. In pytest You can enable those flags those flags
+using the configuration file. To make pytest ignore trailing whitespaces and
+ignore lengthy exception stack traces you can just write:
+
+.. code-block:: ini
+
+ [pytest]
+ doctest_optionflags= NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL
+
+pytest also introduces new options to allow doctests to run in Python 2 and
+Python 3 unchanged:
+
+* ``ALLOW_UNICODE``: when enabled, the ``u`` prefix is stripped from unicode
+ strings in expected doctest output.
+
+* ``ALLOW_BYTES``: when enabled, the ``b`` prefix is stripped from byte strings
+ in expected doctest output.
+
+As with any other option flag, these flags can be enabled in ``pytest.ini`` using
+the ``doctest_optionflags`` ini option:
+
+.. code-block:: ini
+
+ [pytest]
+ doctest_optionflags = ALLOW_UNICODE ALLOW_BYTES
+
+
+Alternatively, it can be enabled by an inline comment in the doc test
+itself::
+
+ # content of example.rst
+ >>> get_unicode_greeting() # doctest: +ALLOW_UNICODE
+ 'Hello'
+
+
+The 'doctest_namespace' fixture
+-------------------------------
+
+.. versionadded:: 3.0
+
+The ``doctest_namespace`` fixture can be used to inject items into the
+namespace in which your doctests run. It is intended to be used within
+your own fixtures to provide the tests that use them with context.
+
+``doctest_namespace`` is a standard ``dict`` object into which you
+place the objects you want to appear in the doctest namespace::
+
+ # content of conftest.py
+ import numpy
+ @pytest.fixture(autouse=True)
+ def add_np(doctest_namespace):
+ doctest_namespace['np'] = numpy
+
+which can then be used in your doctests directly::
+
+ # content of numpy.py
+ def arange():
+ """
+ >>> a = np.arange(10)
+ >>> len(a)
+ 10
+ """
+ pass
+
+
+Output format
+-------------
+
+.. versionadded:: 3.0
+
+You can change the diff output format on failure for your doctests
+by using one of standard doctest modules format in options
+(see :data:`python:doctest.REPORT_UDIFF`, :data:`python:doctest.REPORT_CDIFF`,
+:data:`python:doctest.REPORT_NDIFF`, :data:`python:doctest.REPORT_ONLY_FIRST_FAILURE`)::
+
+ pytest --doctest-modules --doctest-report none
+ pytest --doctest-modules --doctest-report udiff
+ pytest --doctest-modules --doctest-report cdiff
+ pytest --doctest-modules --doctest-report ndiff
+ pytest --doctest-modules --doctest-report only_first_failure
+
+
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/assertion/failure_demo.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/assertion/failure_demo.py
new file mode 100644
index 00000000000..d31fba2adaa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/assertion/failure_demo.py
@@ -0,0 +1,238 @@
+from pytest import raises
+import _pytest._code
+import py
+
+def otherfunc(a,b):
+ assert a==b
+
+def somefunc(x,y):
+ otherfunc(x,y)
+
+def otherfunc_multi(a,b):
+ assert (a ==
+ b)
+
+def test_generative(param1, param2):
+ assert param1 * 2 < param2
+
+def pytest_generate_tests(metafunc):
+ if 'param1' in metafunc.fixturenames:
+ metafunc.addcall(funcargs=dict(param1=3, param2=6))
+
+class TestFailing(object):
+ def test_simple(self):
+ def f():
+ return 42
+ def g():
+ return 43
+
+ assert f() == g()
+
+ def test_simple_multiline(self):
+ otherfunc_multi(
+ 42,
+ 6*9)
+
+ def test_not(self):
+ def f():
+ return 42
+ assert not f()
+
+class TestSpecialisedExplanations(object):
+ def test_eq_text(self):
+ assert 'spam' == 'eggs'
+
+ def test_eq_similar_text(self):
+ assert 'foo 1 bar' == 'foo 2 bar'
+
+ def test_eq_multiline_text(self):
+ assert 'foo\nspam\nbar' == 'foo\neggs\nbar'
+
+ def test_eq_long_text(self):
+ a = '1'*100 + 'a' + '2'*100
+ b = '1'*100 + 'b' + '2'*100
+ assert a == b
+
+ def test_eq_long_text_multiline(self):
+ a = '1\n'*100 + 'a' + '2\n'*100
+ b = '1\n'*100 + 'b' + '2\n'*100
+ assert a == b
+
+ def test_eq_list(self):
+ assert [0, 1, 2] == [0, 1, 3]
+
+ def test_eq_list_long(self):
+ a = [0]*100 + [1] + [3]*100
+ b = [0]*100 + [2] + [3]*100
+ assert a == b
+
+ def test_eq_dict(self):
+ assert {'a': 0, 'b': 1, 'c': 0} == {'a': 0, 'b': 2, 'd': 0}
+
+ def test_eq_set(self):
+ assert set([0, 10, 11, 12]) == set([0, 20, 21])
+
+ def test_eq_longer_list(self):
+ assert [1,2] == [1,2,3]
+
+ def test_in_list(self):
+ assert 1 in [0, 2, 3, 4, 5]
+
+ def test_not_in_text_multiline(self):
+ text = 'some multiline\ntext\nwhich\nincludes foo\nand a\ntail'
+ assert 'foo' not in text
+
+ def test_not_in_text_single(self):
+ text = 'single foo line'
+ assert 'foo' not in text
+
+ def test_not_in_text_single_long(self):
+ text = 'head ' * 50 + 'foo ' + 'tail ' * 20
+ assert 'foo' not in text
+
+ def test_not_in_text_single_long_term(self):
+ text = 'head ' * 50 + 'f'*70 + 'tail ' * 20
+ assert 'f'*70 not in text
+
+
+def test_attribute():
+ class Foo(object):
+ b = 1
+ i = Foo()
+ assert i.b == 2
+
+
+def test_attribute_instance():
+ class Foo(object):
+ b = 1
+ assert Foo().b == 2
+
+
+def test_attribute_failure():
+ class Foo(object):
+ def _get_b(self):
+ raise Exception('Failed to get attrib')
+ b = property(_get_b)
+ i = Foo()
+ assert i.b == 2
+
+
+def test_attribute_multiple():
+ class Foo(object):
+ b = 1
+ class Bar(object):
+ b = 2
+ assert Foo().b == Bar().b
+
+
+def globf(x):
+ return x+1
+
+class TestRaises(object):
+ def test_raises(self):
+ s = 'qwe'
+ raises(TypeError, "int(s)")
+
+ def test_raises_doesnt(self):
+ raises(IOError, "int('3')")
+
+ def test_raise(self):
+ raise ValueError("demo error")
+
+ def test_tupleerror(self):
+ a,b = [1]
+
+ def test_reinterpret_fails_with_print_for_the_fun_of_it(self):
+ l = [1,2,3]
+ print ("l is %r" % l)
+ a,b = l.pop()
+
+ def test_some_error(self):
+ if namenotexi:
+ pass
+
+ def func1(self):
+ assert 41 == 42
+
+
+# thanks to Matthew Scott for this test
+def test_dynamic_compile_shows_nicely():
+ src = 'def foo():\n assert 1 == 0\n'
+ name = 'abc-123'
+ module = py.std.imp.new_module(name)
+ code = _pytest._code.compile(src, name, 'exec')
+ py.builtin.exec_(code, module.__dict__)
+ py.std.sys.modules[name] = module
+ module.foo()
+
+
+
+class TestMoreErrors(object):
+ def test_complex_error(self):
+ def f():
+ return 44
+ def g():
+ return 43
+ somefunc(f(), g())
+
+ def test_z1_unpack_error(self):
+ l = []
+ a,b = l
+
+ def test_z2_type_error(self):
+ l = 3
+ a,b = l
+
+ def test_startswith(self):
+ s = "123"
+ g = "456"
+ assert s.startswith(g)
+
+ def test_startswith_nested(self):
+ def f():
+ return "123"
+ def g():
+ return "456"
+ assert f().startswith(g())
+
+ def test_global_func(self):
+ assert isinstance(globf(42), float)
+
+ def test_instance(self):
+ self.x = 6*7
+ assert self.x != 42
+
+ def test_compare(self):
+ assert globf(10) < 5
+
+ def test_try_finally(self):
+ x = 1
+ try:
+ assert x == 0
+ finally:
+ x = 0
+
+
+class TestCustomAssertMsg(object):
+
+ def test_single_line(self):
+ class A(object):
+ a = 1
+ b = 2
+ assert A.a == b, "A.a appears not to be b"
+
+ def test_multiline(self):
+ class A(object):
+ a = 1
+ b = 2
+ assert A.a == b, "A.a appears not to be b\n" \
+ "or does not appear to be b\none of those"
+
+ def test_custom_repr(self):
+ class JSON(object):
+ a = 1
+ def __repr__(self):
+ return "This is JSON\n{\n 'foo': 'bar'\n}"
+ a = JSON()
+ b = 2
+ assert a.a == b, a
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/assertion/global_testmodule_config/conftest.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/assertion/global_testmodule_config/conftest.py
index 71e8c54be53..71e8c54be53 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/assertion/global_testmodule_config/conftest.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/assertion/global_testmodule_config/conftest.py
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/assertion/global_testmodule_config/test_hello.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/assertion/global_testmodule_config/test_hello.py
index 828e6b9fd7d..828e6b9fd7d 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/assertion/global_testmodule_config/test_hello.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/assertion/global_testmodule_config/test_hello.py
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/assertion/test_failures.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/assertion/test_failures.py
index 2e5cd20b194..2e5cd20b194 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/assertion/test_failures.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/assertion/test_failures.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/assertion/test_setup_flow_example.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/assertion/test_setup_flow_example.py
new file mode 100644
index 00000000000..100effa499f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/assertion/test_setup_flow_example.py
@@ -0,0 +1,42 @@
+def setup_module(module):
+ module.TestStateFullThing.classcount = 0
+
+class TestStateFullThing(object):
+ def setup_class(cls):
+ cls.classcount += 1
+
+ def teardown_class(cls):
+ cls.classcount -= 1
+
+ def setup_method(self, method):
+ self.id = eval(method.__name__[5:])
+
+ def test_42(self):
+ assert self.classcount == 1
+ assert self.id == 42
+
+ def test_23(self):
+ assert self.classcount == 1
+ assert self.id == 23
+
+def teardown_module(module):
+ assert module.TestStateFullThing.classcount == 0
+
+""" For this example the control flow happens as follows::
+ import test_setup_flow_example
+ setup_module(test_setup_flow_example)
+ setup_class(TestStateFullThing)
+ instance = TestStateFullThing()
+ setup_method(instance, instance.test_42)
+ instance.test_42()
+ setup_method(instance, instance.test_23)
+ instance.test_23()
+ teardown_class(TestStateFullThing)
+ teardown_module(test_setup_flow_example)
+
+Note that ``setup_class(TestStateFullThing)`` is called and not
+``TestStateFullThing.setup_class()`` which would require you
+to insert ``setup_class = classmethod(setup_class)`` to make
+your setup function callable.
+"""
+
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/attic.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/attic.rst
new file mode 100644
index 00000000000..9e124a5d09d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/attic.rst
@@ -0,0 +1,79 @@
+
+.. _`accept example`:
+
+example: specifying and selecting acceptance tests
+--------------------------------------------------------------
+
+.. sourcecode:: python
+
+ # ./conftest.py
+ def pytest_option(parser):
+ group = parser.getgroup("myproject")
+ group.addoption("-A", dest="acceptance", action="store_true",
+ help="run (slow) acceptance tests")
+
+ def pytest_funcarg__accept(request):
+ return AcceptFixture(request)
+
+ class AcceptFixture(object):
+ def __init__(self, request):
+ if not request.config.getoption('acceptance'):
+ pytest.skip("specify -A to run acceptance tests")
+ self.tmpdir = request.config.mktemp(request.function.__name__, numbered=True)
+
+ def run(self, cmd):
+ """ called by test code to execute an acceptance test. """
+ self.tmpdir.chdir()
+ return py.process.cmdexec(cmd)
+
+
+and the actual test function example:
+
+.. sourcecode:: python
+
+ def test_some_acceptance_aspect(accept):
+ accept.tmpdir.mkdir("somesub")
+ result = accept.run("ls -la")
+ assert "somesub" in result
+
+If you run this test without specifying a command line option
+the test will get skipped with an appropriate message. Otherwise
+you can start to add convenience and test support methods
+to your AcceptFixture and drive running of tools or
+applications and provide ways to do assertions about
+the output.
+
+.. _`decorate a funcarg`:
+
+example: decorating a funcarg in a test module
+--------------------------------------------------------------
+
+For larger scale setups it's sometimes useful to decorate
+a funcarg just for a particular test module. We can
+extend the `accept example`_ by putting this in our test module:
+
+.. sourcecode:: python
+
+ def pytest_funcarg__accept(request):
+ # call the next factory (living in our conftest.py)
+ arg = request.getfuncargvalue("accept")
+ # create a special layout in our tempdir
+ arg.tmpdir.mkdir("special")
+ return arg
+
+ class TestSpecialAcceptance(object):
+ def test_sometest(self, accept):
+ assert accept.tmpdir.join("special").check()
+
+Our module level factory will be invoked first and it can
+ask its request object to call the next factory and then
+decorate its result. This mechanism allows us to stay
+ignorant of how/where the function argument is provided -
+in our example from a `conftest plugin`_.
+
+sidenote: the temporary directory used here are instances of
+the `py.path.local`_ class which provides many of the os.path
+methods in a convenient way.
+
+.. _`py.path.local`: ../path.html#local
+.. _`conftest plugin`: customize.html#conftestplugin
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/conftest.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/conftest.py
index f905738c4f6..f905738c4f6 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/conftest.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/conftest.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/costlysetup/conftest.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/costlysetup/conftest.py
new file mode 100644
index 00000000000..ea3c1cffb72
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/costlysetup/conftest.py
@@ -0,0 +1,18 @@
+
+import pytest
+
+@pytest.fixture("session")
+def setup(request):
+ setup = CostlySetup()
+ yield setup
+ setup.finalize()
+
+class CostlySetup(object):
+ def __init__(self):
+ import time
+ print ("performing costly setup")
+ time.sleep(5)
+ self.timecostly = 1
+
+ def finalize(self):
+ del self.timecostly
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/costlysetup/sub1/__init__.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/costlysetup/sub1/__init__.py
index 792d6005489..792d6005489 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/costlysetup/sub1/__init__.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/costlysetup/sub1/__init__.py
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/costlysetup/sub1/test_quick.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/costlysetup/sub1/test_quick.py
index d97657867e0..d97657867e0 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/costlysetup/sub1/test_quick.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/costlysetup/sub1/test_quick.py
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/costlysetup/sub2/__init__.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/costlysetup/sub2/__init__.py
index 792d6005489..792d6005489 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/costlysetup/sub2/__init__.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/costlysetup/sub2/__init__.py
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/costlysetup/sub2/test_two.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/costlysetup/sub2/test_two.py
index 6ed6ee4d898..6ed6ee4d898 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/costlysetup/sub2/test_two.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/costlysetup/sub2/test_two.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/index.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/index.rst
new file mode 100644
index 00000000000..f63cb822a41
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/index.rst
@@ -0,0 +1,34 @@
+
+.. _examples:
+
+Examples and customization tricks
+=================================
+
+Here is a (growing) list of examples. :ref:`Contact <contact>` us if you
+need more examples or have questions. Also take a look at the
+:ref:`comprehensive documentation <toc>` which contains many example
+snippets as well. Also, `pytest on stackoverflow.com
+<http://stackoverflow.com/search?q=pytest>`_ often comes with example
+answers.
+
+For basic examples, see
+
+- :doc:`../getting-started` for basic introductory examples
+- :ref:`assert` for basic assertion examples
+- :ref:`fixtures` for basic fixture/setup examples
+- :ref:`parametrize` for basic test function parametrization
+- :doc:`../unittest` for basic unittest integration
+- :doc:`../nose` for basic nosetests integration
+
+The following examples aim at various use cases you might encounter.
+
+.. toctree::
+ :maxdepth: 2
+
+ reportingdemo
+ simple
+ parametrize
+ markers
+ special
+ pythoncollection
+ nonpython
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/markers.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/markers.rst
new file mode 100644
index 00000000000..43c20d5b7dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/markers.rst
@@ -0,0 +1,642 @@
+
+.. _`mark examples`:
+
+Working with custom markers
+=================================================
+
+Here are some example using the :ref:`mark` mechanism.
+
+Marking test functions and selecting them for a run
+----------------------------------------------------
+
+You can "mark" a test function with custom metadata like this::
+
+ # content of test_server.py
+
+ import pytest
+ @pytest.mark.webtest
+ def test_send_http():
+ pass # perform some webtest test for your app
+ def test_something_quick():
+ pass
+ def test_another():
+ pass
+ class TestClass(object):
+ def test_method(self):
+ pass
+
+.. versionadded:: 2.2
+
+You can then restrict a test run to only run tests marked with ``webtest``::
+
+ $ pytest -v -m webtest
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.5
+ cachedir: .cache
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collecting ... collected 4 items
+
+ test_server.py::test_send_http PASSED [100%]
+
+ ============================ 3 tests deselected ============================
+ ================== 1 passed, 3 deselected in 0.12 seconds ==================
+
+Or the inverse, running all tests except the webtest ones::
+
+ $ pytest -v -m "not webtest"
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.5
+ cachedir: .cache
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collecting ... collected 4 items
+
+ test_server.py::test_something_quick PASSED [ 33%]
+ test_server.py::test_another PASSED [ 66%]
+ test_server.py::TestClass::test_method PASSED [100%]
+
+ ============================ 1 tests deselected ============================
+ ================== 3 passed, 1 deselected in 0.12 seconds ==================
+
+Selecting tests based on their node ID
+--------------------------------------
+
+You can provide one or more :ref:`node IDs <node-id>` as positional
+arguments to select only specified tests. This makes it easy to select
+tests based on their module, class, method, or function name::
+
+ $ pytest -v test_server.py::TestClass::test_method
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.5
+ cachedir: .cache
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collecting ... collected 1 item
+
+ test_server.py::TestClass::test_method PASSED [100%]
+
+ ========================= 1 passed in 0.12 seconds =========================
+
+You can also select on the class::
+
+ $ pytest -v test_server.py::TestClass
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.5
+ cachedir: .cache
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collecting ... collected 1 item
+
+ test_server.py::TestClass::test_method PASSED [100%]
+
+ ========================= 1 passed in 0.12 seconds =========================
+
+Or select multiple nodes::
+
+ $ pytest -v test_server.py::TestClass test_server.py::test_send_http
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.5
+ cachedir: .cache
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collecting ... collected 2 items
+
+ test_server.py::TestClass::test_method PASSED [ 50%]
+ test_server.py::test_send_http PASSED [100%]
+
+ ========================= 2 passed in 0.12 seconds =========================
+
+.. _node-id:
+
+.. note::
+
+ Node IDs are of the form ``module.py::class::method`` or
+ ``module.py::function``. Node IDs control which tests are
+ collected, so ``module.py::class`` will select all test methods
+ on the class. Nodes are also created for each parameter of a
+ parametrized fixture or test, so selecting a parametrized test
+ must include the parameter value, e.g.
+ ``module.py::function[param]``.
+
+ Node IDs for failing tests are displayed in the test summary info
+ when running pytest with the ``-rf`` option. You can also
+ construct Node IDs from the output of ``pytest --collectonly``.
+
+Using ``-k expr`` to select tests based on their name
+-------------------------------------------------------
+
+.. versionadded: 2.0/2.3.4
+
+You can use the ``-k`` command line option to specify an expression
+which implements a substring match on the test names instead of the
+exact match on markers that ``-m`` provides. This makes it easy to
+select tests based on their names::
+
+ $ pytest -v -k http # running with the above defined example module
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.5
+ cachedir: .cache
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collecting ... collected 4 items
+
+ test_server.py::test_send_http PASSED [100%]
+
+ ============================ 3 tests deselected ============================
+ ================== 1 passed, 3 deselected in 0.12 seconds ==================
+
+And you can also run all tests except the ones that match the keyword::
+
+ $ pytest -k "not send_http" -v
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.5
+ cachedir: .cache
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collecting ... collected 4 items
+
+ test_server.py::test_something_quick PASSED [ 33%]
+ test_server.py::test_another PASSED [ 66%]
+ test_server.py::TestClass::test_method PASSED [100%]
+
+ ============================ 1 tests deselected ============================
+ ================== 3 passed, 1 deselected in 0.12 seconds ==================
+
+Or to select "http" and "quick" tests::
+
+ $ pytest -k "http or quick" -v
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.5
+ cachedir: .cache
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collecting ... collected 4 items
+
+ test_server.py::test_send_http PASSED [ 50%]
+ test_server.py::test_something_quick PASSED [100%]
+
+ ============================ 2 tests deselected ============================
+ ================== 2 passed, 2 deselected in 0.12 seconds ==================
+
+.. note::
+
+ If you are using expressions such as ``"X and Y"`` then both ``X`` and ``Y``
+ need to be simple non-keyword names. For example, ``"pass"`` or ``"from"``
+ will result in SyntaxErrors because ``"-k"`` evaluates the expression using
+ Python's `eval`_ function.
+
+.. _`eval`: https://docs.python.org/3.6/library/functions.html#eval
+
+
+ However, if the ``"-k"`` argument is a simple string, no such restrictions
+ apply. Also ``"-k 'not STRING'"`` has no restrictions. You can also
+ specify numbers like ``"-k 1.3"`` to match tests which are parametrized
+ with the float ``"1.3"``.
+
+Registering markers
+-------------------------------------
+
+.. versionadded:: 2.2
+
+.. ini-syntax for custom markers:
+
+Registering markers for your test suite is simple::
+
+ # content of pytest.ini
+ [pytest]
+ markers =
+ webtest: mark a test as a webtest.
+
+You can ask which markers exist for your test suite - the list includes our just defined ``webtest`` markers::
+
+ $ pytest --markers
+ @pytest.mark.webtest: mark a test as a webtest.
+
+ @pytest.mark.skip(reason=None): skip the given test function with an optional reason. Example: skip(reason="no way of currently testing this") skips the test.
+
+ @pytest.mark.skipif(condition): skip the given test function if eval(condition) results in a True value. Evaluation happens within the module global context. Example: skipif('sys.platform == "win32"') skips the test if we are on the win32 platform. see http://pytest.org/latest/skipping.html
+
+ @pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html
+
+ @pytest.mark.parametrize(argnames, argvalues): call a test function multiple times passing in different arguments in turn. argvalues generally needs to be a list of values if argnames specifies only one name or a list of tuples of values if argnames specifies multiple names. Example: @parametrize('arg1', [1,2]) would lead to two calls of the decorated test function, one with arg1=1 and another with arg1=2.see http://pytest.org/latest/parametrize.html for more info and examples.
+
+ @pytest.mark.usefixtures(fixturename1, fixturename2, ...): mark tests as needing all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures
+
+ @pytest.mark.tryfirst: mark a hook implementation function such that the plugin machinery will try to call it first/as early as possible.
+
+ @pytest.mark.trylast: mark a hook implementation function such that the plugin machinery will try to call it last/as late as possible.
+
+
+For an example on how to add and work with markers from a plugin, see
+:ref:`adding a custom marker from a plugin`.
+
+.. note::
+
+ It is recommended to explicitly register markers so that:
+
+ * There is one place in your test suite defining your markers
+
+ * Asking for existing markers via ``pytest --markers`` gives good output
+
+ * Typos in function markers are treated as an error if you use
+ the ``--strict`` option.
+
+.. _`scoped-marking`:
+
+Marking whole classes or modules
+----------------------------------------------------
+
+You may use ``pytest.mark`` decorators with classes to apply markers to all of
+its test methods::
+
+ # content of test_mark_classlevel.py
+ import pytest
+ @pytest.mark.webtest
+ class TestClass(object):
+ def test_startup(self):
+ pass
+ def test_startup_and_more(self):
+ pass
+
+This is equivalent to directly applying the decorator to the
+two test functions.
+
+To remain backward-compatible with Python 2.4 you can also set a
+``pytestmark`` attribute on a TestClass like this::
+
+ import pytest
+
+ class TestClass(object):
+ pytestmark = pytest.mark.webtest
+
+or if you need to use multiple markers you can use a list::
+
+ import pytest
+
+ class TestClass(object):
+ pytestmark = [pytest.mark.webtest, pytest.mark.slowtest]
+
+You can also set a module level marker::
+
+ import pytest
+ pytestmark = pytest.mark.webtest
+
+in which case it will be applied to all functions and
+methods defined in the module.
+
+.. _`marking individual tests when using parametrize`:
+
+Marking individual tests when using parametrize
+-----------------------------------------------
+
+When using parametrize, applying a mark will make it apply
+to each individual test. However it is also possible to
+apply a marker to an individual test instance::
+
+ import pytest
+
+ @pytest.mark.foo
+ @pytest.mark.parametrize(("n", "expected"), [
+ (1, 2),
+ pytest.mark.bar((1, 3)),
+ (2, 3),
+ ])
+ def test_increment(n, expected):
+ assert n + 1 == expected
+
+In this example the mark "foo" will apply to each of the three
+tests, whereas the "bar" mark is only applied to the second test.
+Skip and xfail marks can also be applied in this way, see :ref:`skip/xfail with parametrize`.
+
+.. note::
+
+ If the data you are parametrizing happen to be single callables, you need to be careful
+ when marking these items. `pytest.mark.xfail(my_func)` won't work because it's also the
+ signature of a function being decorated. To resolve this ambiguity, you need to pass a
+ reason argument:
+ `pytest.mark.xfail(func_bar, reason="Issue#7")`.
+
+
+.. _`adding a custom marker from a plugin`:
+
+Custom marker and command line option to control test runs
+----------------------------------------------------------
+
+.. regendoc:wipe
+
+Plugins can provide custom markers and implement specific behaviour
+based on it. This is a self-contained example which adds a command
+line option and a parametrized test function marker to run tests
+specifies via named environments::
+
+ # content of conftest.py
+
+ import pytest
+ def pytest_addoption(parser):
+ parser.addoption("-E", action="store", metavar="NAME",
+ help="only run tests matching the environment NAME.")
+
+ def pytest_configure(config):
+ # register an additional marker
+ config.addinivalue_line("markers",
+ "env(name): mark test to run only on named environment")
+
+ def pytest_runtest_setup(item):
+ envmarker = item.get_marker("env")
+ if envmarker is not None:
+ envname = envmarker.args[0]
+ if envname != item.config.getoption("-E"):
+ pytest.skip("test requires env %r" % envname)
+
+A test file using this local plugin::
+
+ # content of test_someenv.py
+
+ import pytest
+ @pytest.mark.env("stage1")
+ def test_basic_db_operation():
+ pass
+
+and an example invocations specifying a different environment than what
+the test needs::
+
+ $ pytest -E stage2
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 1 item
+
+ test_someenv.py s [100%]
+
+ ======================== 1 skipped in 0.12 seconds =========================
+
+and here is one that specifies exactly the environment needed::
+
+ $ pytest -E stage1
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 1 item
+
+ test_someenv.py . [100%]
+
+ ========================= 1 passed in 0.12 seconds =========================
+
+The ``--markers`` option always gives you a list of available markers::
+
+ $ pytest --markers
+ @pytest.mark.env(name): mark test to run only on named environment
+
+ @pytest.mark.skip(reason=None): skip the given test function with an optional reason. Example: skip(reason="no way of currently testing this") skips the test.
+
+ @pytest.mark.skipif(condition): skip the given test function if eval(condition) results in a True value. Evaluation happens within the module global context. Example: skipif('sys.platform == "win32"') skips the test if we are on the win32 platform. see http://pytest.org/latest/skipping.html
+
+ @pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html
+
+ @pytest.mark.parametrize(argnames, argvalues): call a test function multiple times passing in different arguments in turn. argvalues generally needs to be a list of values if argnames specifies only one name or a list of tuples of values if argnames specifies multiple names. Example: @parametrize('arg1', [1,2]) would lead to two calls of the decorated test function, one with arg1=1 and another with arg1=2.see http://pytest.org/latest/parametrize.html for more info and examples.
+
+ @pytest.mark.usefixtures(fixturename1, fixturename2, ...): mark tests as needing all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures
+
+ @pytest.mark.tryfirst: mark a hook implementation function such that the plugin machinery will try to call it first/as early as possible.
+
+ @pytest.mark.trylast: mark a hook implementation function such that the plugin machinery will try to call it last/as late as possible.
+
+
+.. _`passing callables to custom markers`:
+
+Passing a callable to custom markers
+--------------------------------------------
+
+.. regendoc:wipe
+
+Below is the config file that will be used in the next examples::
+
+ # content of conftest.py
+ import sys
+
+ def pytest_runtest_setup(item):
+ marker = item.get_marker('my_marker')
+ if marker is not None:
+ for info in marker:
+ print('Marker info name={} args={} kwars={}'.format(info.name, info.args, info.kwargs))
+ sys.stdout.flush()
+
+A custom marker can have its argument set, i.e. ``args`` and ``kwargs`` properties, defined by either invoking it as a callable or using ``pytest.mark.MARKER_NAME.with_args``. These two methods achieve the same effect most of the time.
+
+However, if there is a callable as the single positional argument with no keyword arguments, using the ``pytest.mark.MARKER_NAME(c)`` will not pass ``c`` as a positional argument but decorate ``c`` with the custom marker (see :ref:`MarkDecorator <mark>`). Fortunately, ``pytest.mark.MARKER_NAME.with_args`` comes to the rescue::
+
+ # content of test_custom_marker.py
+ import pytest
+
+ def hello_world(*args, **kwargs):
+ return 'Hello World'
+
+ @pytest.mark.my_marker.with_args(hello_world)
+ def test_with_args():
+ pass
+
+The output is as follows::
+
+ $ pytest -q -s
+ Marker info name=my_marker args=(<function hello_world at 0xdeadbeef>,) kwars={}
+ . [100%]
+ 1 passed in 0.12 seconds
+
+We can see that the custom marker has its argument set extended with the function ``hello_world``. This is the key difference between creating a custom marker as a callable, which invokes ``__call__`` behind the scenes, and using ``with_args``.
+
+
+Reading markers which were set from multiple places
+----------------------------------------------------
+
+.. versionadded: 2.2.2
+
+.. regendoc:wipe
+
+If you are heavily using markers in your test suite you may encounter the case where a marker is applied several times to a test function. From plugin
+code you can read over all such settings. Example::
+
+ # content of test_mark_three_times.py
+ import pytest
+ pytestmark = pytest.mark.glob("module", x=1)
+
+ @pytest.mark.glob("class", x=2)
+ class TestClass(object):
+ @pytest.mark.glob("function", x=3)
+ def test_something(self):
+ pass
+
+Here we have the marker "glob" applied three times to the same
+test function. From a conftest file we can read it like this::
+
+ # content of conftest.py
+ import sys
+
+ def pytest_runtest_setup(item):
+ g = item.get_marker("glob")
+ if g is not None:
+ for info in g:
+ print ("glob args=%s kwargs=%s" %(info.args, info.kwargs))
+ sys.stdout.flush()
+
+Let's run this without capturing output and see what we get::
+
+ $ pytest -q -s
+ glob args=('function',) kwargs={'x': 3}
+ glob args=('class',) kwargs={'x': 2}
+ glob args=('module',) kwargs={'x': 1}
+ . [100%]
+ 1 passed in 0.12 seconds
+
+marking platform specific tests with pytest
+--------------------------------------------------------------
+
+.. regendoc:wipe
+
+Consider you have a test suite which marks tests for particular platforms,
+namely ``pytest.mark.darwin``, ``pytest.mark.win32`` etc. and you
+also have tests that run on all platforms and have no specific
+marker. If you now want to have a way to only run the tests
+for your particular platform, you could use the following plugin::
+
+ # content of conftest.py
+ #
+ import sys
+ import pytest
+
+ ALL = set("darwin linux win32".split())
+
+ def pytest_runtest_setup(item):
+ if isinstance(item, item.Function):
+ plat = sys.platform
+ if not item.get_marker(plat):
+ if ALL.intersection(item.keywords):
+ pytest.skip("cannot run on platform %s" %(plat))
+
+then tests will be skipped if they were specified for a different platform.
+Let's do a little test file to show how this looks like::
+
+ # content of test_plat.py
+
+ import pytest
+
+ @pytest.mark.darwin
+ def test_if_apple_is_evil():
+ pass
+
+ @pytest.mark.linux
+ def test_if_linux_works():
+ pass
+
+ @pytest.mark.win32
+ def test_if_win32_crashes():
+ pass
+
+ def test_runs_everywhere():
+ pass
+
+then you will see two tests skipped and two executed tests as expected::
+
+ $ pytest -rs # this option reports skip reasons
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 4 items
+
+ test_plat.py s.s. [100%]
+ ========================= short test summary info ==========================
+ SKIP [2] $REGENDOC_TMPDIR/conftest.py:13: cannot run on platform linux
+
+ =================== 2 passed, 2 skipped in 0.12 seconds ====================
+
+Note that if you specify a platform via the marker-command line option like this::
+
+ $ pytest -m linux
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 4 items
+
+ test_plat.py . [100%]
+
+ ============================ 3 tests deselected ============================
+ ================== 1 passed, 3 deselected in 0.12 seconds ==================
+
+then the unmarked-tests will not be run. It is thus a way to restrict the run to the specific tests.
+
+Automatically adding markers based on test names
+--------------------------------------------------------
+
+.. regendoc:wipe
+
+If you a test suite where test function names indicate a certain
+type of test, you can implement a hook that automatically defines
+markers so that you can use the ``-m`` option with it. Let's look
+at this test module::
+
+ # content of test_module.py
+
+ def test_interface_simple():
+ assert 0
+
+ def test_interface_complex():
+ assert 0
+
+ def test_event_simple():
+ assert 0
+
+ def test_something_else():
+ assert 0
+
+We want to dynamically define two markers and can do it in a
+``conftest.py`` plugin::
+
+ # content of conftest.py
+
+ import pytest
+ def pytest_collection_modifyitems(items):
+ for item in items:
+ if "interface" in item.nodeid:
+ item.add_marker(pytest.mark.interface)
+ elif "event" in item.nodeid:
+ item.add_marker(pytest.mark.event)
+
+We can now use the ``-m option`` to select one set::
+
+ $ pytest -m interface --tb=short
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 4 items
+
+ test_module.py FF [100%]
+
+ ================================= FAILURES =================================
+ __________________________ test_interface_simple ___________________________
+ test_module.py:3: in test_interface_simple
+ assert 0
+ E assert 0
+ __________________________ test_interface_complex __________________________
+ test_module.py:6: in test_interface_complex
+ assert 0
+ E assert 0
+ ============================ 2 tests deselected ============================
+ ================== 2 failed, 2 deselected in 0.12 seconds ==================
+
+or to select both "event" and "interface" tests::
+
+ $ pytest -m "interface or event" --tb=short
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 4 items
+
+ test_module.py FFF [100%]
+
+ ================================= FAILURES =================================
+ __________________________ test_interface_simple ___________________________
+ test_module.py:3: in test_interface_simple
+ assert 0
+ E assert 0
+ __________________________ test_interface_complex __________________________
+ test_module.py:6: in test_interface_complex
+ assert 0
+ E assert 0
+ ____________________________ test_event_simple _____________________________
+ test_module.py:9: in test_event_simple
+ assert 0
+ E assert 0
+ ============================ 1 tests deselected ============================
+ ================== 3 failed, 1 deselected in 0.12 seconds ==================
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/multipython.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/multipython.py
new file mode 100644
index 00000000000..66079be7e37
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/multipython.py
@@ -0,0 +1,52 @@
+"""
+module containing a parametrized tests testing cross-python
+serialization via the pickle module.
+"""
+import py
+import pytest
+import _pytest._code
+
+pythonlist = ['python2.7', 'python3.4', 'python3.5']
+@pytest.fixture(params=pythonlist)
+def python1(request, tmpdir):
+ picklefile = tmpdir.join("data.pickle")
+ return Python(request.param, picklefile)
+
+@pytest.fixture(params=pythonlist)
+def python2(request, python1):
+ return Python(request.param, python1.picklefile)
+
+class Python(object):
+ def __init__(self, version, picklefile):
+ self.pythonpath = py.path.local.sysfind(version)
+ if not self.pythonpath:
+ pytest.skip("%r not found" %(version,))
+ self.picklefile = picklefile
+ def dumps(self, obj):
+ dumpfile = self.picklefile.dirpath("dump.py")
+ dumpfile.write(_pytest._code.Source("""
+ import pickle
+ f = open(%r, 'wb')
+ s = pickle.dump(%r, f, protocol=2)
+ f.close()
+ """ % (str(self.picklefile), obj)))
+ py.process.cmdexec("%s %s" %(self.pythonpath, dumpfile))
+
+ def load_and_is_true(self, expression):
+ loadfile = self.picklefile.dirpath("load.py")
+ loadfile.write(_pytest._code.Source("""
+ import pickle
+ f = open(%r, 'rb')
+ obj = pickle.load(f)
+ f.close()
+ res = eval(%r)
+ if not res:
+ raise SystemExit(1)
+ """ % (str(self.picklefile), expression)))
+ print (loadfile)
+ py.process.cmdexec("%s %s" %(self.pythonpath, loadfile))
+
+@pytest.mark.parametrize("obj", [42, {}, {1:3},])
+def test_basic_objects(python1, python2, obj):
+ python1.dumps(obj)
+ python2.load_and_is_true("obj == %s" % obj)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/nonpython.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/nonpython.rst
new file mode 100644
index 00000000000..cf72c7219e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/nonpython.rst
@@ -0,0 +1,91 @@
+
+.. _`non-python tests`:
+
+Working with non-python tests
+====================================================
+
+.. _`yaml plugin`:
+
+A basic example for specifying tests in Yaml files
+--------------------------------------------------------------
+
+.. _`pytest-yamlwsgi`: http://bitbucket.org/aafshar/pytest-yamlwsgi/src/tip/pytest_yamlwsgi.py
+.. _`PyYAML`: http://pypi.python.org/pypi/PyYAML/
+
+Here is an example ``conftest.py`` (extracted from Ali Afshnars special purpose `pytest-yamlwsgi`_ plugin). This ``conftest.py`` will collect ``test*.yml`` files and will execute the yaml-formatted content as custom tests:
+
+.. include:: nonpython/conftest.py
+ :literal:
+
+You can create a simple example file:
+
+.. include:: nonpython/test_simple.yml
+ :literal:
+
+and if you installed `PyYAML`_ or a compatible YAML-parser you can
+now execute the test specification::
+
+ nonpython $ pytest test_simple.yml
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR/nonpython, inifile:
+ collected 2 items
+
+ test_simple.yml F. [100%]
+
+ ================================= FAILURES =================================
+ ______________________________ usecase: hello ______________________________
+ usecase execution failed
+ spec failed: 'some': 'other'
+ no further details known at this point.
+ ==================== 1 failed, 1 passed in 0.12 seconds ====================
+
+.. regendoc:wipe
+
+You get one dot for the passing ``sub1: sub1`` check and one failure.
+Obviously in the above ``conftest.py`` you'll want to implement a more
+interesting interpretation of the yaml-values. You can easily write
+your own domain specific testing language this way.
+
+.. note::
+
+ ``repr_failure(excinfo)`` is called for representing test failures.
+ If you create custom collection nodes you can return an error
+ representation string of your choice. It
+ will be reported as a (red) string.
+
+``reportinfo()`` is used for representing the test location and is also
+consulted when reporting in ``verbose`` mode::
+
+ nonpython $ pytest -v
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.5
+ cachedir: .cache
+ rootdir: $REGENDOC_TMPDIR/nonpython, inifile:
+ collecting ... collected 2 items
+
+ test_simple.yml::hello FAILED [ 50%]
+ test_simple.yml::ok PASSED [100%]
+
+ ================================= FAILURES =================================
+ ______________________________ usecase: hello ______________________________
+ usecase execution failed
+ spec failed: 'some': 'other'
+ no further details known at this point.
+ ==================== 1 failed, 1 passed in 0.12 seconds ====================
+
+.. regendoc:wipe
+
+While developing your custom test collection and execution it's also
+interesting to just look at the collection tree::
+
+ nonpython $ pytest --collect-only
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR/nonpython, inifile:
+ collected 2 items
+ <YamlFile 'test_simple.yml'>
+ <YamlItem 'hello'>
+ <YamlItem 'ok'>
+
+ ======================= no tests ran in 0.12 seconds =======================
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/nonpython/__init__.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/nonpython/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/nonpython/__init__.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/nonpython/conftest.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/nonpython/conftest.py
new file mode 100644
index 00000000000..baff3001550
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/nonpython/conftest.py
@@ -0,0 +1,40 @@
+# content of conftest.py
+
+import pytest
+
+def pytest_collect_file(parent, path):
+ if path.ext == ".yml" and path.basename.startswith("test"):
+ return YamlFile(path, parent)
+
+class YamlFile(pytest.File):
+ def collect(self):
+ import yaml # we need a yaml parser, e.g. PyYAML
+ raw = yaml.safe_load(self.fspath.open())
+ for name, spec in sorted(raw.items()):
+ yield YamlItem(name, self, spec)
+
+class YamlItem(pytest.Item):
+ def __init__(self, name, parent, spec):
+ super(YamlItem, self).__init__(name, parent)
+ self.spec = spec
+
+ def runtest(self):
+ for name, value in sorted(self.spec.items()):
+ # some custom test execution (dumb example follows)
+ if name != value:
+ raise YamlException(self, name, value)
+
+ def repr_failure(self, excinfo):
+ """ called when self.runtest() raises an exception. """
+ if isinstance(excinfo.value, YamlException):
+ return "\n".join([
+ "usecase execution failed",
+ " spec failed: %r: %r" % excinfo.value.args[1:3],
+ " no further details known at this point."
+ ])
+
+ def reportinfo(self):
+ return self.fspath, 0, "usecase: %s" % self.name
+
+class YamlException(Exception):
+ """ custom exception for error reporting. """
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/nonpython/test_simple.yml b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/nonpython/test_simple.yml
index f0d8d11fc3e..f0d8d11fc3e 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/nonpython/test_simple.yml
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/nonpython/test_simple.yml
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/parametrize.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/parametrize.rst
new file mode 100644
index 00000000000..dd01b25277a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/parametrize.rst
@@ -0,0 +1,536 @@
+
+.. _paramexamples:
+
+Parametrizing tests
+=================================================
+
+.. currentmodule:: _pytest.python
+
+``pytest`` allows to easily parametrize test functions.
+For basic docs, see :ref:`parametrize-basics`.
+
+In the following we provide some examples using
+the builtin mechanisms.
+
+Generating parameters combinations, depending on command line
+----------------------------------------------------------------------------
+
+.. regendoc:wipe
+
+Let's say we want to execute a test with different computation
+parameters and the parameter range shall be determined by a command
+line argument. Let's first write a simple (do-nothing) computation test::
+
+ # content of test_compute.py
+
+ def test_compute(param1):
+ assert param1 < 4
+
+Now we add a test configuration like this::
+
+ # content of conftest.py
+
+ def pytest_addoption(parser):
+ parser.addoption("--all", action="store_true",
+ help="run all combinations")
+
+ def pytest_generate_tests(metafunc):
+ if 'param1' in metafunc.fixturenames:
+ if metafunc.config.getoption('all'):
+ end = 5
+ else:
+ end = 2
+ metafunc.parametrize("param1", range(end))
+
+This means that we only run 2 tests if we do not pass ``--all``::
+
+ $ pytest -q test_compute.py
+ .. [100%]
+ 2 passed in 0.12 seconds
+
+We run only two computations, so we see two dots.
+let's run the full monty::
+
+ $ pytest -q --all
+ ....F [100%]
+ ================================= FAILURES =================================
+ _____________________________ test_compute[4] ______________________________
+
+ param1 = 4
+
+ def test_compute(param1):
+ > assert param1 < 4
+ E assert 4 < 4
+
+ test_compute.py:3: AssertionError
+ 1 failed, 4 passed in 0.12 seconds
+
+As expected when running the full range of ``param1`` values
+we'll get an error on the last one.
+
+
+Different options for test IDs
+------------------------------------
+
+pytest will build a string that is the test ID for each set of values in a
+parametrized test. These IDs can be used with ``-k`` to select specific cases
+to run, and they will also identify the specific case when one is failing.
+Running pytest with ``--collect-only`` will show the generated IDs.
+
+Numbers, strings, booleans and None will have their usual string representation
+used in the test ID. For other objects, pytest will make a string based on
+the argument name::
+
+ # content of test_time.py
+
+ import pytest
+
+ from datetime import datetime, timedelta
+
+ testdata = [
+ (datetime(2001, 12, 12), datetime(2001, 12, 11), timedelta(1)),
+ (datetime(2001, 12, 11), datetime(2001, 12, 12), timedelta(-1)),
+ ]
+
+
+ @pytest.mark.parametrize("a,b,expected", testdata)
+ def test_timedistance_v0(a, b, expected):
+ diff = a - b
+ assert diff == expected
+
+
+ @pytest.mark.parametrize("a,b,expected", testdata, ids=["forward", "backward"])
+ def test_timedistance_v1(a, b, expected):
+ diff = a - b
+ assert diff == expected
+
+
+ def idfn(val):
+ if isinstance(val, (datetime,)):
+ # note this wouldn't show any hours/minutes/seconds
+ return val.strftime('%Y%m%d')
+
+
+ @pytest.mark.parametrize("a,b,expected", testdata, ids=idfn)
+ def test_timedistance_v2(a, b, expected):
+ diff = a - b
+ assert diff == expected
+
+ @pytest.mark.parametrize("a,b,expected", [
+ pytest.param(datetime(2001, 12, 12), datetime(2001, 12, 11),
+ timedelta(1), id='forward'),
+ pytest.param(datetime(2001, 12, 11), datetime(2001, 12, 12),
+ timedelta(-1), id='backward'),
+ ])
+ def test_timedistance_v3(a, b, expected):
+ diff = a - b
+ assert diff == expected
+
+In ``test_timedistance_v0``, we let pytest generate the test IDs.
+
+In ``test_timedistance_v1``, we specified ``ids`` as a list of strings which were
+used as the test IDs. These are succinct, but can be a pain to maintain.
+
+In ``test_timedistance_v2``, we specified ``ids`` as a function that can generate a
+string representation to make part of the test ID. So our ``datetime`` values use the
+label generated by ``idfn``, but because we didn't generate a label for ``timedelta``
+objects, they are still using the default pytest representation::
+
+
+ $ pytest test_time.py --collect-only
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 8 items
+ <Module 'test_time.py'>
+ <Function 'test_timedistance_v0[a0-b0-expected0]'>
+ <Function 'test_timedistance_v0[a1-b1-expected1]'>
+ <Function 'test_timedistance_v1[forward]'>
+ <Function 'test_timedistance_v1[backward]'>
+ <Function 'test_timedistance_v2[20011212-20011211-expected0]'>
+ <Function 'test_timedistance_v2[20011211-20011212-expected1]'>
+ <Function 'test_timedistance_v3[forward]'>
+ <Function 'test_timedistance_v3[backward]'>
+
+ ======================= no tests ran in 0.12 seconds =======================
+
+In ``test_timedistance_v3``, we used ``pytest.param`` to specify the test IDs
+together with the actual data, instead of listing them separately.
+
+A quick port of "testscenarios"
+------------------------------------
+
+.. _`test scenarios`: http://pypi.python.org/pypi/testscenarios/
+
+Here is a quick port to run tests configured with `test scenarios`_,
+an add-on from Robert Collins for the standard unittest framework. We
+only have to work a bit to construct the correct arguments for pytest's
+:py:func:`Metafunc.parametrize`::
+
+ # content of test_scenarios.py
+
+ def pytest_generate_tests(metafunc):
+ idlist = []
+ argvalues = []
+ for scenario in metafunc.cls.scenarios:
+ idlist.append(scenario[0])
+ items = scenario[1].items()
+ argnames = [x[0] for x in items]
+ argvalues.append(([x[1] for x in items]))
+ metafunc.parametrize(argnames, argvalues, ids=idlist, scope="class")
+
+ scenario1 = ('basic', {'attribute': 'value'})
+ scenario2 = ('advanced', {'attribute': 'value2'})
+
+ class TestSampleWithScenarios(object):
+ scenarios = [scenario1, scenario2]
+
+ def test_demo1(self, attribute):
+ assert isinstance(attribute, str)
+
+ def test_demo2(self, attribute):
+ assert isinstance(attribute, str)
+
+this is a fully self-contained example which you can run with::
+
+ $ pytest test_scenarios.py
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 4 items
+
+ test_scenarios.py .... [100%]
+
+ ========================= 4 passed in 0.12 seconds =========================
+
+If you just collect tests you'll also nicely see 'advanced' and 'basic' as variants for the test function::
+
+
+ $ pytest --collect-only test_scenarios.py
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 4 items
+ <Module 'test_scenarios.py'>
+ <Class 'TestSampleWithScenarios'>
+ <Instance '()'>
+ <Function 'test_demo1[basic]'>
+ <Function 'test_demo2[basic]'>
+ <Function 'test_demo1[advanced]'>
+ <Function 'test_demo2[advanced]'>
+
+ ======================= no tests ran in 0.12 seconds =======================
+
+Note that we told ``metafunc.parametrize()`` that your scenario values
+should be considered class-scoped. With pytest-2.3 this leads to a
+resource-based ordering.
+
+Deferring the setup of parametrized resources
+---------------------------------------------------
+
+.. regendoc:wipe
+
+The parametrization of test functions happens at collection
+time. It is a good idea to setup expensive resources like DB
+connections or subprocess only when the actual test is run.
+Here is a simple example how you can achieve that, first
+the actual test requiring a ``db`` object::
+
+ # content of test_backends.py
+
+ import pytest
+ def test_db_initialized(db):
+ # a dummy test
+ if db.__class__.__name__ == "DB2":
+ pytest.fail("deliberately failing for demo purposes")
+
+We can now add a test configuration that generates two invocations of
+the ``test_db_initialized`` function and also implements a factory that
+creates a database object for the actual test invocations::
+
+ # content of conftest.py
+ import pytest
+
+ def pytest_generate_tests(metafunc):
+ if 'db' in metafunc.fixturenames:
+ metafunc.parametrize("db", ['d1', 'd2'], indirect=True)
+
+ class DB1(object):
+ "one database object"
+ class DB2(object):
+ "alternative database object"
+
+ @pytest.fixture
+ def db(request):
+ if request.param == "d1":
+ return DB1()
+ elif request.param == "d2":
+ return DB2()
+ else:
+ raise ValueError("invalid internal test config")
+
+Let's first see how it looks like at collection time::
+
+ $ pytest test_backends.py --collect-only
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 2 items
+ <Module 'test_backends.py'>
+ <Function 'test_db_initialized[d1]'>
+ <Function 'test_db_initialized[d2]'>
+
+ ======================= no tests ran in 0.12 seconds =======================
+
+And then when we run the test::
+
+ $ pytest -q test_backends.py
+ .F [100%]
+ ================================= FAILURES =================================
+ _________________________ test_db_initialized[d2] __________________________
+
+ db = <conftest.DB2 object at 0xdeadbeef>
+
+ def test_db_initialized(db):
+ # a dummy test
+ if db.__class__.__name__ == "DB2":
+ > pytest.fail("deliberately failing for demo purposes")
+ E Failed: deliberately failing for demo purposes
+
+ test_backends.py:6: Failed
+ 1 failed, 1 passed in 0.12 seconds
+
+The first invocation with ``db == "DB1"`` passed while the second with ``db == "DB2"`` failed. Our ``db`` fixture function has instantiated each of the DB values during the setup phase while the ``pytest_generate_tests`` generated two according calls to the ``test_db_initialized`` during the collection phase.
+
+.. regendoc:wipe
+
+Apply indirect on particular arguments
+---------------------------------------------------
+
+Very often parametrization uses more than one argument name. There is opportunity to apply ``indirect``
+parameter on particular arguments. It can be done by passing list or tuple of
+arguments' names to ``indirect``. In the example below there is a function ``test_indirect`` which uses
+two fixtures: ``x`` and ``y``. Here we give to indirect the list, which contains the name of the
+fixture ``x``. The indirect parameter will be applied to this argument only, and the value ``a``
+will be passed to respective fixture function::
+
+ # content of test_indirect_list.py
+
+ import pytest
+ @pytest.fixture(scope='function')
+ def x(request):
+ return request.param * 3
+
+ @pytest.fixture(scope='function')
+ def y(request):
+ return request.param * 2
+
+ @pytest.mark.parametrize('x, y', [('a', 'b')], indirect=['x'])
+ def test_indirect(x,y):
+ assert x == 'aaa'
+ assert y == 'b'
+
+The result of this test will be successful::
+
+ $ pytest test_indirect_list.py --collect-only
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 1 item
+ <Module 'test_indirect_list.py'>
+ <Function 'test_indirect[a-b]'>
+
+ ======================= no tests ran in 0.12 seconds =======================
+
+.. regendoc:wipe
+
+Parametrizing test methods through per-class configuration
+--------------------------------------------------------------
+
+.. _`unittest parametrizer`: https://github.com/testing-cabal/unittest-ext/blob/master/params.py
+
+
+Here is an example ``pytest_generate_tests`` function implementing a
+parametrization scheme similar to Michael Foord's `unittest
+parametrizer`_ but in a lot less code::
+
+ # content of ./test_parametrize.py
+ import pytest
+
+ def pytest_generate_tests(metafunc):
+ # called once per each test function
+ funcarglist = metafunc.cls.params[metafunc.function.__name__]
+ argnames = sorted(funcarglist[0])
+ metafunc.parametrize(argnames, [[funcargs[name] for name in argnames]
+ for funcargs in funcarglist])
+
+ class TestClass(object):
+ # a map specifying multiple argument sets for a test method
+ params = {
+ 'test_equals': [dict(a=1, b=2), dict(a=3, b=3), ],
+ 'test_zerodivision': [dict(a=1, b=0), ],
+ }
+
+ def test_equals(self, a, b):
+ assert a == b
+
+ def test_zerodivision(self, a, b):
+ pytest.raises(ZeroDivisionError, "a/b")
+
+Our test generator looks up a class-level definition which specifies which
+argument sets to use for each test function. Let's run it::
+
+ $ pytest -q
+ F.. [100%]
+ ================================= FAILURES =================================
+ ________________________ TestClass.test_equals[1-2] ________________________
+
+ self = <test_parametrize.TestClass object at 0xdeadbeef>, a = 1, b = 2
+
+ def test_equals(self, a, b):
+ > assert a == b
+ E assert 1 == 2
+
+ test_parametrize.py:18: AssertionError
+ 1 failed, 2 passed in 0.12 seconds
+
+Indirect parametrization with multiple fixtures
+--------------------------------------------------------------
+
+Here is a stripped down real-life example of using parametrized
+testing for testing serialization of objects between different python
+interpreters. We define a ``test_basic_objects`` function which
+is to be run with different sets of arguments for its three arguments:
+
+* ``python1``: first python interpreter, run to pickle-dump an object to a file
+* ``python2``: second interpreter, run to pickle-load an object from a file
+* ``obj``: object to be dumped/loaded
+
+.. literalinclude:: multipython.py
+
+Running it results in some skips if we don't have all the python interpreters installed and otherwise runs all combinations (5 interpreters times 5 interpreters times 3 objects to serialize/deserialize)::
+
+ . $ pytest -rs -q multipython.py
+ ........................... [100%]
+ 27 passed in 0.12 seconds
+
+Indirect parametrization of optional implementations/imports
+--------------------------------------------------------------------
+
+If you want to compare the outcomes of several implementations of a given
+API, you can write test functions that receive the already imported implementations
+and get skipped in case the implementation is not importable/available. Let's
+say we have a "base" implementation and the other (possibly optimized ones)
+need to provide similar results::
+
+ # content of conftest.py
+
+ import pytest
+
+ @pytest.fixture(scope="session")
+ def basemod(request):
+ return pytest.importorskip("base")
+
+ @pytest.fixture(scope="session", params=["opt1", "opt2"])
+ def optmod(request):
+ return pytest.importorskip(request.param)
+
+And then a base implementation of a simple function::
+
+ # content of base.py
+ def func1():
+ return 1
+
+And an optimized version::
+
+ # content of opt1.py
+ def func1():
+ return 1.0001
+
+And finally a little test module::
+
+ # content of test_module.py
+
+ def test_func1(basemod, optmod):
+ assert round(basemod.func1(), 3) == round(optmod.func1(), 3)
+
+
+If you run this with reporting for skips enabled::
+
+ $ pytest -rs test_module.py
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 2 items
+
+ test_module.py .s [100%]
+ ========================= short test summary info ==========================
+ SKIP [1] $REGENDOC_TMPDIR/conftest.py:11: could not import 'opt2'
+
+ =================== 1 passed, 1 skipped in 0.12 seconds ====================
+
+You'll see that we don't have a ``opt2`` module and thus the second test run
+of our ``test_func1`` was skipped. A few notes:
+
+- the fixture functions in the ``conftest.py`` file are "session-scoped" because we
+ don't need to import more than once
+
+- if you have multiple test functions and a skipped import, you will see
+ the ``[1]`` count increasing in the report
+
+- you can put :ref:`@pytest.mark.parametrize <@pytest.mark.parametrize>` style
+ parametrization on the test functions to parametrize input/output
+ values as well.
+
+
+Set marks or test ID for individual parametrized test
+--------------------------------------------------------------------
+
+Use ``pytest.param`` to apply marks or set test ID to individual parametrized test.
+For example::
+
+ # content of test_pytest_param_example.py
+ import pytest
+ @pytest.mark.parametrize('test_input,expected', [
+ ('3+5', 8),
+ pytest.param('1+7', 8,
+ marks=pytest.mark.basic),
+ pytest.param('2+4', 6,
+ marks=pytest.mark.basic,
+ id='basic_2+4'),
+ pytest.param('6*9', 42,
+ marks=[pytest.mark.basic, pytest.mark.xfail],
+ id='basic_6*9'),
+ ])
+ def test_eval(test_input, expected):
+ assert eval(test_input) == expected
+
+In this example, we have 4 parametrized tests. Except for the first test,
+we mark the rest three parametrized tests with the custom marker ``basic``,
+and for the fourth test we also use the built-in mark ``xfail`` to indicate this
+test is expected to fail. For explicitness, we set test ids for some tests.
+
+Then run ``pytest`` with verbose mode and with only the ``basic`` marker::
+
+ pytest -v -m basic
+ ============================================ test session starts =============================================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 4 items
+
+ test_pytest_param_example.py::test_eval[1+7-8] PASSED
+ test_pytest_param_example.py::test_eval[basic_2+4] PASSED
+ test_pytest_param_example.py::test_eval[basic_6*9] xfail
+ ========================================== short test summary info ===========================================
+ XFAIL test_pytest_param_example.py::test_eval[basic_6*9]
+
+ ============================================= 1 tests deselected =============================================
+
+As the result:
+
+- Four tests were collected
+- One test was deselected because it doesn't have the ``basic`` mark.
+- Three tests with the ``basic`` mark was selected.
+- The test ``test_eval[1+7-8]`` passed, but the name is autogenerated and confusing.
+- The test ``test_eval[basic_2+4]`` passed.
+- The test ``test_eval[basic_6*9]`` was expected to fail and did fail.
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/py2py3/conftest.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/py2py3/conftest.py
index 81cd1fb11ea..81cd1fb11ea 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/py2py3/conftest.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/py2py3/conftest.py
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/py2py3/test_py2.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/py2py3/test_py2.py
index e09ed946627..e09ed946627 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/py2py3/test_py2.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/py2py3/test_py2.py
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/py2py3/test_py3.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/py2py3/test_py3.py
index a811f2bbc55..a811f2bbc55 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/py2py3/test_py3.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/py2py3/test_py3.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/pythoncollection.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/pythoncollection.py
new file mode 100644
index 00000000000..9c4bd31cea0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/pythoncollection.py
@@ -0,0 +1,11 @@
+
+# run this with $ pytest --collect-only test_collectonly.py
+#
+def test_function():
+ pass
+
+class TestClass(object):
+ def test_method(self):
+ pass
+ def test_anothermethod(self):
+ pass
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/pythoncollection.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/pythoncollection.rst
new file mode 100644
index 00000000000..c9d31d7c420
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/pythoncollection.rst
@@ -0,0 +1,239 @@
+Changing standard (Python) test discovery
+===============================================
+
+Ignore paths during test collection
+-----------------------------------
+
+You can easily ignore certain test directories and modules during collection
+by passing the ``--ignore=path`` option on the cli. ``pytest`` allows multiple
+``--ignore`` options. Example::
+
+ tests/
+ |-- example
+ | |-- test_example_01.py
+ | |-- test_example_02.py
+ | '-- test_example_03.py
+ |-- foobar
+ | |-- test_foobar_01.py
+ | |-- test_foobar_02.py
+ | '-- test_foobar_03.py
+ '-- hello
+ '-- world
+ |-- test_world_01.py
+ |-- test_world_02.py
+ '-- test_world_03.py
+
+Now if you invoke ``pytest`` with ``--ignore=tests/foobar/test_foobar_03.py --ignore=tests/hello/``,
+you will see that ``pytest`` only collects test-modules, which do not match the patterns specified::
+
+ ========= test session starts ==========
+ platform darwin -- Python 2.7.10, pytest-2.8.2, py-1.4.30, pluggy-0.3.1
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 5 items
+
+ tests/example/test_example_01.py .
+ tests/example/test_example_02.py .
+ tests/example/test_example_03.py .
+ tests/foobar/test_foobar_01.py .
+ tests/foobar/test_foobar_02.py .
+
+ ======= 5 passed in 0.02 seconds =======
+
+
+Keeping duplicate paths specified from command line
+----------------------------------------------------
+
+Default behavior of ``pytest`` is to ignore duplicate paths specified from the command line.
+Example::
+
+ py.test path_a path_a
+
+ ...
+ collected 1 item
+ ...
+
+Just collect tests once.
+
+To collect duplicate tests, use the ``--keep-duplicates`` option on the cli.
+Example::
+
+ py.test --keep-duplicates path_a path_a
+
+ ...
+ collected 2 items
+ ...
+
+As the collector just works on directories, if you specify twice a single test file, ``pytest`` will
+still collect it twice, no matter if the ``--keep-duplicates`` is not specified.
+Example::
+
+ py.test test_a.py test_a.py
+
+ ...
+ collected 2 items
+ ...
+
+
+Changing directory recursion
+-----------------------------------------------------
+
+You can set the :confval:`norecursedirs` option in an ini-file, for example your ``pytest.ini`` in the project root directory::
+
+ # content of pytest.ini
+ [pytest]
+ norecursedirs = .svn _build tmp*
+
+This would tell ``pytest`` to not recurse into typical subversion or sphinx-build directories or into any ``tmp`` prefixed directory.
+
+.. _`change naming conventions`:
+
+Changing naming conventions
+-----------------------------------------------------
+
+You can configure different naming conventions by setting
+the :confval:`python_files`, :confval:`python_classes` and
+:confval:`python_functions` configuration options. Example::
+
+ # content of pytest.ini
+ # can also be defined in tox.ini or setup.cfg file, although the section
+ # name in setup.cfg files should be "tool:pytest"
+ [pytest]
+ python_files=check_*.py
+ python_classes=Check
+ python_functions=*_check
+
+This would make ``pytest`` look for tests in files that match the ``check_*
+.py`` glob-pattern, ``Check`` prefixes in classes, and functions and methods
+that match ``*_check``. For example, if we have::
+
+ # content of check_myapp.py
+ class CheckMyApp(object):
+ def simple_check(self):
+ pass
+ def complex_check(self):
+ pass
+
+then the test collection looks like this::
+
+ $ pytest --collect-only
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
+ collected 2 items
+ <Module 'check_myapp.py'>
+ <Class 'CheckMyApp'>
+ <Instance '()'>
+ <Function 'simple_check'>
+ <Function 'complex_check'>
+
+ ======================= no tests ran in 0.12 seconds =======================
+
+.. note::
+
+ the ``python_functions`` and ``python_classes`` options has no effect
+ for ``unittest.TestCase`` test discovery because pytest delegates
+ detection of test case methods to unittest code.
+
+Interpreting cmdline arguments as Python packages
+-----------------------------------------------------
+
+You can use the ``--pyargs`` option to make ``pytest`` try
+interpreting arguments as python package names, deriving
+their file system path and then running the test. For
+example if you have unittest2 installed you can type::
+
+ pytest --pyargs unittest2.test.test_skipping -q
+
+which would run the respective test module. Like with
+other options, through an ini-file and the :confval:`addopts` option you
+can make this change more permanently::
+
+ # content of pytest.ini
+ [pytest]
+ addopts = --pyargs
+
+Now a simple invocation of ``pytest NAME`` will check
+if NAME exists as an importable package/module and otherwise
+treat it as a filesystem path.
+
+Finding out what is collected
+-----------------------------------------------
+
+You can always peek at the collection tree without running tests like this::
+
+ . $ pytest --collect-only pythoncollection.py
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
+ collected 3 items
+ <Module 'CWD/pythoncollection.py'>
+ <Function 'test_function'>
+ <Class 'TestClass'>
+ <Instance '()'>
+ <Function 'test_method'>
+ <Function 'test_anothermethod'>
+
+ ======================= no tests ran in 0.12 seconds =======================
+
+.. _customizing-test-collection:
+
+Customizing test collection
+---------------------------
+
+.. regendoc:wipe
+
+You can easily instruct ``pytest`` to discover tests from every Python file::
+
+ # content of pytest.ini
+ [pytest]
+ python_files = *.py
+
+However, many projects will have a ``setup.py`` which they don't want to be
+imported. Moreover, there may files only importable by a specific python
+version. For such cases you can dynamically define files to be ignored by
+listing them in a ``conftest.py`` file::
+
+ # content of conftest.py
+ import sys
+
+ collect_ignore = ["setup.py"]
+ if sys.version_info[0] > 2:
+ collect_ignore.append("pkg/module_py2.py")
+
+and then if you have a module file like this::
+
+ # content of pkg/module_py2.py
+ def test_only_on_python2():
+ try:
+ assert 0
+ except Exception, e:
+ pass
+
+and a ``setup.py`` dummy file like this::
+
+ # content of setup.py
+ 0/0 # will raise exception if imported
+
+If you run with a Python 2 interpreter then you will find the one test and will
+leave out the ``setup.py`` file::
+
+ #$ pytest --collect-only
+ ====== test session starts ======
+ platform linux2 -- Python 2.7.10, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
+ rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
+ collected 1 items
+ <Module 'pkg/module_py2.py'>
+ <Function 'test_only_on_python2'>
+
+ ====== no tests ran in 0.04 seconds ======
+
+If you run with a Python 3 interpreter both the one test and the ``setup.py``
+file will be left out::
+
+ $ pytest --collect-only
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
+ collected 0 items
+
+ ======================= no tests ran in 0.12 seconds =======================
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/reportingdemo.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/reportingdemo.rst
new file mode 100644
index 00000000000..9edc02b3cd4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/reportingdemo.rst
@@ -0,0 +1,604 @@
+
+.. _`tbreportdemo`:
+
+Demo of Python failure reports with pytest
+==================================================
+
+Here is a nice run of several tens of failures
+and how ``pytest`` presents things (unfortunately
+not showing the nice colors here in the HTML that you
+get on the terminal - we are working on that)::
+
+ assertion $ pytest failure_demo.py
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR/assertion, inifile:
+ collected 42 items
+
+ failure_demo.py FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF [100%]
+
+ ================================= FAILURES =================================
+ ____________________________ test_generative[0] ____________________________
+
+ param1 = 3, param2 = 6
+
+ def test_generative(param1, param2):
+ > assert param1 * 2 < param2
+ E assert (3 * 2) < 6
+
+ failure_demo.py:16: AssertionError
+ _________________________ TestFailing.test_simple __________________________
+
+ self = <failure_demo.TestFailing object at 0xdeadbeef>
+
+ def test_simple(self):
+ def f():
+ return 42
+ def g():
+ return 43
+
+ > assert f() == g()
+ E assert 42 == 43
+ E + where 42 = <function TestFailing.test_simple.<locals>.f at 0xdeadbeef>()
+ E + and 43 = <function TestFailing.test_simple.<locals>.g at 0xdeadbeef>()
+
+ failure_demo.py:29: AssertionError
+ ____________________ TestFailing.test_simple_multiline _____________________
+
+ self = <failure_demo.TestFailing object at 0xdeadbeef>
+
+ def test_simple_multiline(self):
+ otherfunc_multi(
+ 42,
+ > 6*9)
+
+ failure_demo.py:34:
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+
+ a = 42, b = 54
+
+ def otherfunc_multi(a,b):
+ > assert (a ==
+ b)
+ E assert 42 == 54
+
+ failure_demo.py:12: AssertionError
+ ___________________________ TestFailing.test_not ___________________________
+
+ self = <failure_demo.TestFailing object at 0xdeadbeef>
+
+ def test_not(self):
+ def f():
+ return 42
+ > assert not f()
+ E assert not 42
+ E + where 42 = <function TestFailing.test_not.<locals>.f at 0xdeadbeef>()
+
+ failure_demo.py:39: AssertionError
+ _________________ TestSpecialisedExplanations.test_eq_text _________________
+
+ self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
+
+ def test_eq_text(self):
+ > assert 'spam' == 'eggs'
+ E AssertionError: assert 'spam' == 'eggs'
+ E - spam
+ E + eggs
+
+ failure_demo.py:43: AssertionError
+ _____________ TestSpecialisedExplanations.test_eq_similar_text _____________
+
+ self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
+
+ def test_eq_similar_text(self):
+ > assert 'foo 1 bar' == 'foo 2 bar'
+ E AssertionError: assert 'foo 1 bar' == 'foo 2 bar'
+ E - foo 1 bar
+ E ? ^
+ E + foo 2 bar
+ E ? ^
+
+ failure_demo.py:46: AssertionError
+ ____________ TestSpecialisedExplanations.test_eq_multiline_text ____________
+
+ self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
+
+ def test_eq_multiline_text(self):
+ > assert 'foo\nspam\nbar' == 'foo\neggs\nbar'
+ E AssertionError: assert 'foo\nspam\nbar' == 'foo\neggs\nbar'
+ E foo
+ E - spam
+ E + eggs
+ E bar
+
+ failure_demo.py:49: AssertionError
+ ______________ TestSpecialisedExplanations.test_eq_long_text _______________
+
+ self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
+
+ def test_eq_long_text(self):
+ a = '1'*100 + 'a' + '2'*100
+ b = '1'*100 + 'b' + '2'*100
+ > assert a == b
+ E AssertionError: assert '111111111111...2222222222222' == '1111111111111...2222222222222'
+ E Skipping 90 identical leading characters in diff, use -v to show
+ E Skipping 91 identical trailing characters in diff, use -v to show
+ E - 1111111111a222222222
+ E ? ^
+ E + 1111111111b222222222
+ E ? ^
+
+ failure_demo.py:54: AssertionError
+ _________ TestSpecialisedExplanations.test_eq_long_text_multiline __________
+
+ self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
+
+ def test_eq_long_text_multiline(self):
+ a = '1\n'*100 + 'a' + '2\n'*100
+ b = '1\n'*100 + 'b' + '2\n'*100
+ > assert a == b
+ E AssertionError: assert '1\n1\n1\n1\n...n2\n2\n2\n2\n' == '1\n1\n1\n1\n1...n2\n2\n2\n2\n'
+ E Skipping 190 identical leading characters in diff, use -v to show
+ E Skipping 191 identical trailing characters in diff, use -v to show
+ E 1
+ E 1
+ E 1
+ E 1
+ E 1...
+ E
+ E ...Full output truncated (7 lines hidden), use '-vv' to show
+
+ failure_demo.py:59: AssertionError
+ _________________ TestSpecialisedExplanations.test_eq_list _________________
+
+ self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
+
+ def test_eq_list(self):
+ > assert [0, 1, 2] == [0, 1, 3]
+ E assert [0, 1, 2] == [0, 1, 3]
+ E At index 2 diff: 2 != 3
+ E Use -v to get the full diff
+
+ failure_demo.py:62: AssertionError
+ ______________ TestSpecialisedExplanations.test_eq_list_long _______________
+
+ self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
+
+ def test_eq_list_long(self):
+ a = [0]*100 + [1] + [3]*100
+ b = [0]*100 + [2] + [3]*100
+ > assert a == b
+ E assert [0, 0, 0, 0, 0, 0, ...] == [0, 0, 0, 0, 0, 0, ...]
+ E At index 100 diff: 1 != 2
+ E Use -v to get the full diff
+
+ failure_demo.py:67: AssertionError
+ _________________ TestSpecialisedExplanations.test_eq_dict _________________
+
+ self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
+
+ def test_eq_dict(self):
+ > assert {'a': 0, 'b': 1, 'c': 0} == {'a': 0, 'b': 2, 'd': 0}
+ E AssertionError: assert {'a': 0, 'b': 1, 'c': 0} == {'a': 0, 'b': 2, 'd': 0}
+ E Omitting 1 identical items, use -vv to show
+ E Differing items:
+ E {'b': 1} != {'b': 2}
+ E Left contains more items:
+ E {'c': 0}
+ E Right contains more items:
+ E {'d': 0}...
+ E
+ E ...Full output truncated (2 lines hidden), use '-vv' to show
+
+ failure_demo.py:70: AssertionError
+ _________________ TestSpecialisedExplanations.test_eq_set __________________
+
+ self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
+
+ def test_eq_set(self):
+ > assert set([0, 10, 11, 12]) == set([0, 20, 21])
+ E AssertionError: assert {0, 10, 11, 12} == {0, 20, 21}
+ E Extra items in the left set:
+ E 10
+ E 11
+ E 12
+ E Extra items in the right set:
+ E 20
+ E 21...
+ E
+ E ...Full output truncated (2 lines hidden), use '-vv' to show
+
+ failure_demo.py:73: AssertionError
+ _____________ TestSpecialisedExplanations.test_eq_longer_list ______________
+
+ self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
+
+ def test_eq_longer_list(self):
+ > assert [1,2] == [1,2,3]
+ E assert [1, 2] == [1, 2, 3]
+ E Right contains more items, first extra item: 3
+ E Use -v to get the full diff
+
+ failure_demo.py:76: AssertionError
+ _________________ TestSpecialisedExplanations.test_in_list _________________
+
+ self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
+
+ def test_in_list(self):
+ > assert 1 in [0, 2, 3, 4, 5]
+ E assert 1 in [0, 2, 3, 4, 5]
+
+ failure_demo.py:79: AssertionError
+ __________ TestSpecialisedExplanations.test_not_in_text_multiline __________
+
+ self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
+
+ def test_not_in_text_multiline(self):
+ text = 'some multiline\ntext\nwhich\nincludes foo\nand a\ntail'
+ > assert 'foo' not in text
+ E AssertionError: assert 'foo' not in 'some multiline\ntext\nw...ncludes foo\nand a\ntail'
+ E 'foo' is contained here:
+ E some multiline
+ E text
+ E which
+ E includes foo
+ E ? +++
+ E and a...
+ E
+ E ...Full output truncated (2 lines hidden), use '-vv' to show
+
+ failure_demo.py:83: AssertionError
+ ___________ TestSpecialisedExplanations.test_not_in_text_single ____________
+
+ self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
+
+ def test_not_in_text_single(self):
+ text = 'single foo line'
+ > assert 'foo' not in text
+ E AssertionError: assert 'foo' not in 'single foo line'
+ E 'foo' is contained here:
+ E single foo line
+ E ? +++
+
+ failure_demo.py:87: AssertionError
+ _________ TestSpecialisedExplanations.test_not_in_text_single_long _________
+
+ self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
+
+ def test_not_in_text_single_long(self):
+ text = 'head ' * 50 + 'foo ' + 'tail ' * 20
+ > assert 'foo' not in text
+ E AssertionError: assert 'foo' not in 'head head head head hea...ail tail tail tail tail '
+ E 'foo' is contained here:
+ E head head foo tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail
+ E ? +++
+
+ failure_demo.py:91: AssertionError
+ ______ TestSpecialisedExplanations.test_not_in_text_single_long_term _______
+
+ self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
+
+ def test_not_in_text_single_long_term(self):
+ text = 'head ' * 50 + 'f'*70 + 'tail ' * 20
+ > assert 'f'*70 not in text
+ E AssertionError: assert 'fffffffffff...ffffffffffff' not in 'head head he...l tail tail '
+ E 'ffffffffffffffffff...fffffffffffffffffff' is contained here:
+ E head head fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffftail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail
+ E ? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+ failure_demo.py:95: AssertionError
+ ______________________________ test_attribute ______________________________
+
+ def test_attribute():
+ class Foo(object):
+ b = 1
+ i = Foo()
+ > assert i.b == 2
+ E assert 1 == 2
+ E + where 1 = <failure_demo.test_attribute.<locals>.Foo object at 0xdeadbeef>.b
+
+ failure_demo.py:102: AssertionError
+ _________________________ test_attribute_instance __________________________
+
+ def test_attribute_instance():
+ class Foo(object):
+ b = 1
+ > assert Foo().b == 2
+ E AssertionError: assert 1 == 2
+ E + where 1 = <failure_demo.test_attribute_instance.<locals>.Foo object at 0xdeadbeef>.b
+ E + where <failure_demo.test_attribute_instance.<locals>.Foo object at 0xdeadbeef> = <class 'failure_demo.test_attribute_instance.<locals>.Foo'>()
+
+ failure_demo.py:108: AssertionError
+ __________________________ test_attribute_failure __________________________
+
+ def test_attribute_failure():
+ class Foo(object):
+ def _get_b(self):
+ raise Exception('Failed to get attrib')
+ b = property(_get_b)
+ i = Foo()
+ > assert i.b == 2
+
+ failure_demo.py:117:
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+
+ self = <failure_demo.test_attribute_failure.<locals>.Foo object at 0xdeadbeef>
+
+ def _get_b(self):
+ > raise Exception('Failed to get attrib')
+ E Exception: Failed to get attrib
+
+ failure_demo.py:114: Exception
+ _________________________ test_attribute_multiple __________________________
+
+ def test_attribute_multiple():
+ class Foo(object):
+ b = 1
+ class Bar(object):
+ b = 2
+ > assert Foo().b == Bar().b
+ E AssertionError: assert 1 == 2
+ E + where 1 = <failure_demo.test_attribute_multiple.<locals>.Foo object at 0xdeadbeef>.b
+ E + where <failure_demo.test_attribute_multiple.<locals>.Foo object at 0xdeadbeef> = <class 'failure_demo.test_attribute_multiple.<locals>.Foo'>()
+ E + and 2 = <failure_demo.test_attribute_multiple.<locals>.Bar object at 0xdeadbeef>.b
+ E + where <failure_demo.test_attribute_multiple.<locals>.Bar object at 0xdeadbeef> = <class 'failure_demo.test_attribute_multiple.<locals>.Bar'>()
+
+ failure_demo.py:125: AssertionError
+ __________________________ TestRaises.test_raises __________________________
+
+ self = <failure_demo.TestRaises object at 0xdeadbeef>
+
+ def test_raises(self):
+ s = 'qwe'
+ > raises(TypeError, "int(s)")
+
+ failure_demo.py:134:
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+
+ > int(s)
+ E ValueError: invalid literal for int() with base 10: 'qwe'
+
+ <0-codegen $PYTHON_PREFIX/lib/python3.5/site-packages/_pytest/python_api.py:580>:1: ValueError
+ ______________________ TestRaises.test_raises_doesnt _______________________
+
+ self = <failure_demo.TestRaises object at 0xdeadbeef>
+
+ def test_raises_doesnt(self):
+ > raises(IOError, "int('3')")
+ E Failed: DID NOT RAISE <class 'OSError'>
+
+ failure_demo.py:137: Failed
+ __________________________ TestRaises.test_raise ___________________________
+
+ self = <failure_demo.TestRaises object at 0xdeadbeef>
+
+ def test_raise(self):
+ > raise ValueError("demo error")
+ E ValueError: demo error
+
+ failure_demo.py:140: ValueError
+ ________________________ TestRaises.test_tupleerror ________________________
+
+ self = <failure_demo.TestRaises object at 0xdeadbeef>
+
+ def test_tupleerror(self):
+ > a,b = [1]
+ E ValueError: not enough values to unpack (expected 2, got 1)
+
+ failure_demo.py:143: ValueError
+ ______ TestRaises.test_reinterpret_fails_with_print_for_the_fun_of_it ______
+
+ self = <failure_demo.TestRaises object at 0xdeadbeef>
+
+ def test_reinterpret_fails_with_print_for_the_fun_of_it(self):
+ l = [1,2,3]
+ print ("l is %r" % l)
+ > a,b = l.pop()
+ E TypeError: 'int' object is not iterable
+
+ failure_demo.py:148: TypeError
+ --------------------------- Captured stdout call ---------------------------
+ l is [1, 2, 3]
+ ________________________ TestRaises.test_some_error ________________________
+
+ self = <failure_demo.TestRaises object at 0xdeadbeef>
+
+ def test_some_error(self):
+ > if namenotexi:
+ E NameError: name 'namenotexi' is not defined
+
+ failure_demo.py:151: NameError
+ ____________________ test_dynamic_compile_shows_nicely _____________________
+
+ def test_dynamic_compile_shows_nicely():
+ src = 'def foo():\n assert 1 == 0\n'
+ name = 'abc-123'
+ module = py.std.imp.new_module(name)
+ code = _pytest._code.compile(src, name, 'exec')
+ py.builtin.exec_(code, module.__dict__)
+ py.std.sys.modules[name] = module
+ > module.foo()
+
+ failure_demo.py:166:
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+
+ def foo():
+ > assert 1 == 0
+ E AssertionError
+
+ <2-codegen 'abc-123' $REGENDOC_TMPDIR/assertion/failure_demo.py:163>:2: AssertionError
+ ____________________ TestMoreErrors.test_complex_error _____________________
+
+ self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
+
+ def test_complex_error(self):
+ def f():
+ return 44
+ def g():
+ return 43
+ > somefunc(f(), g())
+
+ failure_demo.py:176:
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+ failure_demo.py:9: in somefunc
+ otherfunc(x,y)
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+
+ a = 44, b = 43
+
+ def otherfunc(a,b):
+ > assert a==b
+ E assert 44 == 43
+
+ failure_demo.py:6: AssertionError
+ ___________________ TestMoreErrors.test_z1_unpack_error ____________________
+
+ self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
+
+ def test_z1_unpack_error(self):
+ l = []
+ > a,b = l
+ E ValueError: not enough values to unpack (expected 2, got 0)
+
+ failure_demo.py:180: ValueError
+ ____________________ TestMoreErrors.test_z2_type_error _____________________
+
+ self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
+
+ def test_z2_type_error(self):
+ l = 3
+ > a,b = l
+ E TypeError: 'int' object is not iterable
+
+ failure_demo.py:184: TypeError
+ ______________________ TestMoreErrors.test_startswith ______________________
+
+ self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
+
+ def test_startswith(self):
+ s = "123"
+ g = "456"
+ > assert s.startswith(g)
+ E AssertionError: assert False
+ E + where False = <built-in method startswith of str object at 0xdeadbeef>('456')
+ E + where <built-in method startswith of str object at 0xdeadbeef> = '123'.startswith
+
+ failure_demo.py:189: AssertionError
+ __________________ TestMoreErrors.test_startswith_nested ___________________
+
+ self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
+
+ def test_startswith_nested(self):
+ def f():
+ return "123"
+ def g():
+ return "456"
+ > assert f().startswith(g())
+ E AssertionError: assert False
+ E + where False = <built-in method startswith of str object at 0xdeadbeef>('456')
+ E + where <built-in method startswith of str object at 0xdeadbeef> = '123'.startswith
+ E + where '123' = <function TestMoreErrors.test_startswith_nested.<locals>.f at 0xdeadbeef>()
+ E + and '456' = <function TestMoreErrors.test_startswith_nested.<locals>.g at 0xdeadbeef>()
+
+ failure_demo.py:196: AssertionError
+ _____________________ TestMoreErrors.test_global_func ______________________
+
+ self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
+
+ def test_global_func(self):
+ > assert isinstance(globf(42), float)
+ E assert False
+ E + where False = isinstance(43, float)
+ E + where 43 = globf(42)
+
+ failure_demo.py:199: AssertionError
+ _______________________ TestMoreErrors.test_instance _______________________
+
+ self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
+
+ def test_instance(self):
+ self.x = 6*7
+ > assert self.x != 42
+ E assert 42 != 42
+ E + where 42 = <failure_demo.TestMoreErrors object at 0xdeadbeef>.x
+
+ failure_demo.py:203: AssertionError
+ _______________________ TestMoreErrors.test_compare ________________________
+
+ self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
+
+ def test_compare(self):
+ > assert globf(10) < 5
+ E assert 11 < 5
+ E + where 11 = globf(10)
+
+ failure_demo.py:206: AssertionError
+ _____________________ TestMoreErrors.test_try_finally ______________________
+
+ self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
+
+ def test_try_finally(self):
+ x = 1
+ try:
+ > assert x == 0
+ E assert 1 == 0
+
+ failure_demo.py:211: AssertionError
+ ___________________ TestCustomAssertMsg.test_single_line ___________________
+
+ self = <failure_demo.TestCustomAssertMsg object at 0xdeadbeef>
+
+ def test_single_line(self):
+ class A(object):
+ a = 1
+ b = 2
+ > assert A.a == b, "A.a appears not to be b"
+ E AssertionError: A.a appears not to be b
+ E assert 1 == 2
+ E + where 1 = <class 'failure_demo.TestCustomAssertMsg.test_single_line.<locals>.A'>.a
+
+ failure_demo.py:222: AssertionError
+ ____________________ TestCustomAssertMsg.test_multiline ____________________
+
+ self = <failure_demo.TestCustomAssertMsg object at 0xdeadbeef>
+
+ def test_multiline(self):
+ class A(object):
+ a = 1
+ b = 2
+ > assert A.a == b, "A.a appears not to be b\n" \
+ "or does not appear to be b\none of those"
+ E AssertionError: A.a appears not to be b
+ E or does not appear to be b
+ E one of those
+ E assert 1 == 2
+ E + where 1 = <class 'failure_demo.TestCustomAssertMsg.test_multiline.<locals>.A'>.a
+
+ failure_demo.py:228: AssertionError
+ ___________________ TestCustomAssertMsg.test_custom_repr ___________________
+
+ self = <failure_demo.TestCustomAssertMsg object at 0xdeadbeef>
+
+ def test_custom_repr(self):
+ class JSON(object):
+ a = 1
+ def __repr__(self):
+ return "This is JSON\n{\n 'foo': 'bar'\n}"
+ a = JSON()
+ b = 2
+ > assert a.a == b, a
+ E AssertionError: This is JSON
+ E {
+ E 'foo': 'bar'
+ E }
+ E assert 1 == 2
+ E + where 1 = This is JSON\n{\n 'foo': 'bar'\n}.a
+
+ failure_demo.py:238: AssertionError
+ ============================= warnings summary =============================
+ None
+ Metafunc.addcall is deprecated and scheduled to be removed in pytest 4.0.
+ Please use Metafunc.parametrize instead.
+
+ -- Docs: http://doc.pytest.org/en/latest/warnings.html
+ ================== 42 failed, 1 warnings in 0.12 seconds ===================
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/simple.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/simple.rst
new file mode 100644
index 00000000000..678a0db0094
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/simple.rst
@@ -0,0 +1,847 @@
+
+
+Basic patterns and examples
+==========================================================
+
+Pass different values to a test function, depending on command line options
+----------------------------------------------------------------------------
+
+.. regendoc:wipe
+
+Suppose we want to write a test that depends on a command line option.
+Here is a basic pattern to achieve this:
+
+.. code-block:: python
+
+ # content of test_sample.py
+ def test_answer(cmdopt):
+ if cmdopt == "type1":
+ print ("first")
+ elif cmdopt == "type2":
+ print ("second")
+ assert 0 # to see what was printed
+
+
+For this to work we need to add a command line option and
+provide the ``cmdopt`` through a :ref:`fixture function <fixture function>`:
+
+.. code-block:: python
+
+ # content of conftest.py
+ import pytest
+
+ def pytest_addoption(parser):
+ parser.addoption("--cmdopt", action="store", default="type1",
+ help="my option: type1 or type2")
+
+ @pytest.fixture
+ def cmdopt(request):
+ return request.config.getoption("--cmdopt")
+
+Let's run this without supplying our new option::
+
+ $ pytest -q test_sample.py
+ F [100%]
+ ================================= FAILURES =================================
+ _______________________________ test_answer ________________________________
+
+ cmdopt = 'type1'
+
+ def test_answer(cmdopt):
+ if cmdopt == "type1":
+ print ("first")
+ elif cmdopt == "type2":
+ print ("second")
+ > assert 0 # to see what was printed
+ E assert 0
+
+ test_sample.py:6: AssertionError
+ --------------------------- Captured stdout call ---------------------------
+ first
+ 1 failed in 0.12 seconds
+
+And now with supplying a command line option::
+
+ $ pytest -q --cmdopt=type2
+ F [100%]
+ ================================= FAILURES =================================
+ _______________________________ test_answer ________________________________
+
+ cmdopt = 'type2'
+
+ def test_answer(cmdopt):
+ if cmdopt == "type1":
+ print ("first")
+ elif cmdopt == "type2":
+ print ("second")
+ > assert 0 # to see what was printed
+ E assert 0
+
+ test_sample.py:6: AssertionError
+ --------------------------- Captured stdout call ---------------------------
+ second
+ 1 failed in 0.12 seconds
+
+You can see that the command line option arrived in our test. This
+completes the basic pattern. However, one often rather wants to process
+command line options outside of the test and rather pass in different or
+more complex objects.
+
+Dynamically adding command line options
+--------------------------------------------------------------
+
+.. regendoc:wipe
+
+Through :confval:`addopts` you can statically add command line
+options for your project. You can also dynamically modify
+the command line arguments before they get processed:
+
+.. code-block:: python
+
+ # content of conftest.py
+ import sys
+ def pytest_cmdline_preparse(args):
+ if 'xdist' in sys.modules: # pytest-xdist plugin
+ import multiprocessing
+ num = max(multiprocessing.cpu_count() / 2, 1)
+ args[:] = ["-n", str(num)] + args
+
+If you have the `xdist plugin <https://pypi.python.org/pypi/pytest-xdist>`_ installed
+you will now always perform test runs using a number
+of subprocesses close to your CPU. Running in an empty
+directory with the above conftest.py::
+
+ $ pytest
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 0 items
+
+ ======================= no tests ran in 0.12 seconds =======================
+
+.. _`excontrolskip`:
+
+Control skipping of tests according to command line option
+--------------------------------------------------------------
+
+.. regendoc:wipe
+
+Here is a ``conftest.py`` file adding a ``--runslow`` command
+line option to control skipping of ``pytest.mark.slow`` marked tests:
+
+.. code-block:: python
+
+ # content of conftest.py
+
+ import pytest
+ def pytest_addoption(parser):
+ parser.addoption("--runslow", action="store_true",
+ default=False, help="run slow tests")
+
+ def pytest_collection_modifyitems(config, items):
+ if config.getoption("--runslow"):
+ # --runslow given in cli: do not skip slow tests
+ return
+ skip_slow = pytest.mark.skip(reason="need --runslow option to run")
+ for item in items:
+ if "slow" in item.keywords:
+ item.add_marker(skip_slow)
+
+We can now write a test module like this:
+
+.. code-block:: python
+
+ # content of test_module.py
+ import pytest
+
+
+ def test_func_fast():
+ pass
+
+
+ @pytest.mark.slow
+ def test_func_slow():
+ pass
+
+and when running it will see a skipped "slow" test::
+
+ $ pytest -rs # "-rs" means report details on the little 's'
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 2 items
+
+ test_module.py .s [100%]
+ ========================= short test summary info ==========================
+ SKIP [1] test_module.py:8: need --runslow option to run
+
+ =================== 1 passed, 1 skipped in 0.12 seconds ====================
+
+Or run it including the ``slow`` marked test::
+
+ $ pytest --runslow
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 2 items
+
+ test_module.py .. [100%]
+
+ ========================= 2 passed in 0.12 seconds =========================
+
+Writing well integrated assertion helpers
+--------------------------------------------------
+
+.. regendoc:wipe
+
+If you have a test helper function called from a test you can
+use the ``pytest.fail`` marker to fail a test with a certain message.
+The test support function will not show up in the traceback if you
+set the ``__tracebackhide__`` option somewhere in the helper function.
+Example:
+
+.. code-block:: python
+
+ # content of test_checkconfig.py
+ import pytest
+ def checkconfig(x):
+ __tracebackhide__ = True
+ if not hasattr(x, "config"):
+ pytest.fail("not configured: %s" %(x,))
+
+ def test_something():
+ checkconfig(42)
+
+The ``__tracebackhide__`` setting influences ``pytest`` showing
+of tracebacks: the ``checkconfig`` function will not be shown
+unless the ``--full-trace`` command line option is specified.
+Let's run our little function::
+
+ $ pytest -q test_checkconfig.py
+ F [100%]
+ ================================= FAILURES =================================
+ ______________________________ test_something ______________________________
+
+ def test_something():
+ > checkconfig(42)
+ E Failed: not configured: 42
+
+ test_checkconfig.py:8: Failed
+ 1 failed in 0.12 seconds
+
+If you only want to hide certain exceptions, you can set ``__tracebackhide__``
+to a callable which gets the ``ExceptionInfo`` object. You can for example use
+this to make sure unexpected exception types aren't hidden:
+
+.. code-block:: python
+
+ import operator
+ import pytest
+
+ class ConfigException(Exception):
+ pass
+
+ def checkconfig(x):
+ __tracebackhide__ = operator.methodcaller('errisinstance', ConfigException)
+ if not hasattr(x, "config"):
+ raise ConfigException("not configured: %s" %(x,))
+
+ def test_something():
+ checkconfig(42)
+
+This will avoid hiding the exception traceback on unrelated exceptions (i.e.
+bugs in assertion helpers).
+
+
+Detect if running from within a pytest run
+--------------------------------------------------------------
+
+.. regendoc:wipe
+
+Usually it is a bad idea to make application code
+behave differently if called from a test. But if you
+absolutely must find out if your application code is
+running from a test you can do something like this:
+
+.. code-block:: python
+
+ # content of conftest.py
+
+ def pytest_configure(config):
+ import sys
+ sys._called_from_test = True
+
+ def pytest_unconfigure(config):
+ import sys
+ del sys._called_from_test
+
+and then check for the ``sys._called_from_test`` flag:
+
+.. code-block:: python
+
+ if hasattr(sys, '_called_from_test'):
+ # called from within a test run
+ else:
+ # called "normally"
+
+accordingly in your application. It's also a good idea
+to use your own application module rather than ``sys``
+for handling flag.
+
+Adding info to test report header
+--------------------------------------------------------------
+
+.. regendoc:wipe
+
+It's easy to present extra information in a ``pytest`` run:
+
+.. code-block:: python
+
+ # content of conftest.py
+
+ def pytest_report_header(config):
+ return "project deps: mylib-1.1"
+
+which will add the string to the test header accordingly::
+
+ $ pytest
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ project deps: mylib-1.1
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 0 items
+
+ ======================= no tests ran in 0.12 seconds =======================
+
+.. regendoc:wipe
+
+It is also possible to return a list of strings which will be considered as several
+lines of information. You may consider ``config.getoption('verbose')`` in order to
+display more information if applicable:
+
+.. code-block:: python
+
+ # content of conftest.py
+
+ def pytest_report_header(config):
+ if config.getoption('verbose') > 0:
+ return ["info1: did you know that ...", "did you?"]
+
+which will add info only when run with "--v"::
+
+ $ pytest -v
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.5
+ cachedir: .cache
+ info1: did you know that ...
+ did you?
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collecting ... collected 0 items
+
+ ======================= no tests ran in 0.12 seconds =======================
+
+and nothing when run plainly::
+
+ $ pytest
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 0 items
+
+ ======================= no tests ran in 0.12 seconds =======================
+
+profiling test duration
+--------------------------
+
+.. regendoc:wipe
+
+.. versionadded: 2.2
+
+If you have a slow running large test suite you might want to find
+out which tests are the slowest. Let's make an artificial test suite:
+
+.. code-block:: python
+
+ # content of test_some_are_slow.py
+ import time
+
+ def test_funcfast():
+ time.sleep(0.1)
+
+ def test_funcslow1():
+ time.sleep(0.2)
+
+ def test_funcslow2():
+ time.sleep(0.3)
+
+Now we can profile which test functions execute the slowest::
+
+ $ pytest --durations=3
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 3 items
+
+ test_some_are_slow.py ... [100%]
+
+ ========================= slowest 3 test durations =========================
+ 0.30s call test_some_are_slow.py::test_funcslow2
+ 0.20s call test_some_are_slow.py::test_funcslow1
+ 0.10s call test_some_are_slow.py::test_funcfast
+ ========================= 3 passed in 0.12 seconds =========================
+
+incremental testing - test steps
+---------------------------------------------------
+
+.. regendoc:wipe
+
+Sometimes you may have a testing situation which consists of a series
+of test steps. If one step fails it makes no sense to execute further
+steps as they are all expected to fail anyway and their tracebacks
+add no insight. Here is a simple ``conftest.py`` file which introduces
+an ``incremental`` marker which is to be used on classes:
+
+.. code-block:: python
+
+ # content of conftest.py
+
+ import pytest
+
+ def pytest_runtest_makereport(item, call):
+ if "incremental" in item.keywords:
+ if call.excinfo is not None:
+ parent = item.parent
+ parent._previousfailed = item
+
+ def pytest_runtest_setup(item):
+ if "incremental" in item.keywords:
+ previousfailed = getattr(item.parent, "_previousfailed", None)
+ if previousfailed is not None:
+ pytest.xfail("previous test failed (%s)" %previousfailed.name)
+
+These two hook implementations work together to abort incremental-marked
+tests in a class. Here is a test module example:
+
+.. code-block:: python
+
+ # content of test_step.py
+
+ import pytest
+
+ @pytest.mark.incremental
+ class TestUserHandling(object):
+ def test_login(self):
+ pass
+ def test_modification(self):
+ assert 0
+ def test_deletion(self):
+ pass
+
+ def test_normal():
+ pass
+
+If we run this::
+
+ $ pytest -rx
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 4 items
+
+ test_step.py .Fx. [100%]
+ ========================= short test summary info ==========================
+ XFAIL test_step.py::TestUserHandling::()::test_deletion
+ reason: previous test failed (test_modification)
+
+ ================================= FAILURES =================================
+ ____________________ TestUserHandling.test_modification ____________________
+
+ self = <test_step.TestUserHandling object at 0xdeadbeef>
+
+ def test_modification(self):
+ > assert 0
+ E assert 0
+
+ test_step.py:9: AssertionError
+ ============== 1 failed, 2 passed, 1 xfailed in 0.12 seconds ===============
+
+We'll see that ``test_deletion`` was not executed because ``test_modification``
+failed. It is reported as an "expected failure".
+
+
+Package/Directory-level fixtures (setups)
+-------------------------------------------------------
+
+If you have nested test directories, you can have per-directory fixture scopes
+by placing fixture functions in a ``conftest.py`` file in that directory
+You can use all types of fixtures including :ref:`autouse fixtures
+<autouse fixtures>` which are the equivalent of xUnit's setup/teardown
+concept. It's however recommended to have explicit fixture references in your
+tests or test classes rather than relying on implicitly executing
+setup/teardown functions, especially if they are far away from the actual tests.
+
+Here is an example for making a ``db`` fixture available in a directory:
+
+.. code-block:: python
+
+ # content of a/conftest.py
+ import pytest
+
+ class DB(object):
+ pass
+
+ @pytest.fixture(scope="session")
+ def db():
+ return DB()
+
+and then a test module in that directory:
+
+.. code-block:: python
+
+ # content of a/test_db.py
+ def test_a1(db):
+ assert 0, db # to show value
+
+another test module:
+
+.. code-block:: python
+
+ # content of a/test_db2.py
+ def test_a2(db):
+ assert 0, db # to show value
+
+and then a module in a sister directory which will not see
+the ``db`` fixture:
+
+.. code-block:: python
+
+ # content of b/test_error.py
+ def test_root(db): # no db here, will error out
+ pass
+
+We can run this::
+
+ $ pytest
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 7 items
+
+ test_step.py .Fx. [ 57%]
+ a/test_db.py F [ 71%]
+ a/test_db2.py F [ 85%]
+ b/test_error.py E [100%]
+
+ ================================== ERRORS ==================================
+ _______________________ ERROR at setup of test_root ________________________
+ file $REGENDOC_TMPDIR/b/test_error.py, line 1
+ def test_root(db): # no db here, will error out
+ E fixture 'db' not found
+ > available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, doctest_namespace, monkeypatch, pytestconfig, record_xml_property, recwarn, tmpdir, tmpdir_factory
+ > use 'pytest --fixtures [testpath]' for help on them.
+
+ $REGENDOC_TMPDIR/b/test_error.py:1
+ ================================= FAILURES =================================
+ ____________________ TestUserHandling.test_modification ____________________
+
+ self = <test_step.TestUserHandling object at 0xdeadbeef>
+
+ def test_modification(self):
+ > assert 0
+ E assert 0
+
+ test_step.py:9: AssertionError
+ _________________________________ test_a1 __________________________________
+
+ db = <conftest.DB object at 0xdeadbeef>
+
+ def test_a1(db):
+ > assert 0, db # to show value
+ E AssertionError: <conftest.DB object at 0xdeadbeef>
+ E assert 0
+
+ a/test_db.py:2: AssertionError
+ _________________________________ test_a2 __________________________________
+
+ db = <conftest.DB object at 0xdeadbeef>
+
+ def test_a2(db):
+ > assert 0, db # to show value
+ E AssertionError: <conftest.DB object at 0xdeadbeef>
+ E assert 0
+
+ a/test_db2.py:2: AssertionError
+ ========== 3 failed, 2 passed, 1 xfailed, 1 error in 0.12 seconds ==========
+
+The two test modules in the ``a`` directory see the same ``db`` fixture instance
+while the one test in the sister-directory ``b`` doesn't see it. We could of course
+also define a ``db`` fixture in that sister directory's ``conftest.py`` file.
+Note that each fixture is only instantiated if there is a test actually needing
+it (unless you use "autouse" fixture which are always executed ahead of the first test
+executing).
+
+
+post-process test reports / failures
+---------------------------------------
+
+If you want to postprocess test reports and need access to the executing
+environment you can implement a hook that gets called when the test
+"report" object is about to be created. Here we write out all failing
+test calls and also access a fixture (if it was used by the test) in
+case you want to query/look at it during your post processing. In our
+case we just write some information out to a ``failures`` file:
+
+.. code-block:: python
+
+ # content of conftest.py
+
+ import pytest
+ import os.path
+
+ @pytest.hookimpl(tryfirst=True, hookwrapper=True)
+ def pytest_runtest_makereport(item, call):
+ # execute all other hooks to obtain the report object
+ outcome = yield
+ rep = outcome.get_result()
+
+ # we only look at actual failing test calls, not setup/teardown
+ if rep.when == "call" and rep.failed:
+ mode = "a" if os.path.exists("failures") else "w"
+ with open("failures", mode) as f:
+ # let's also access a fixture for the fun of it
+ if "tmpdir" in item.fixturenames:
+ extra = " (%s)" % item.funcargs["tmpdir"]
+ else:
+ extra = ""
+
+ f.write(rep.nodeid + extra + "\n")
+
+
+if you then have failing tests:
+
+.. code-block:: python
+
+ # content of test_module.py
+ def test_fail1(tmpdir):
+ assert 0
+ def test_fail2():
+ assert 0
+
+and run them::
+
+ $ pytest test_module.py
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 2 items
+
+ test_module.py FF [100%]
+
+ ================================= FAILURES =================================
+ ________________________________ test_fail1 ________________________________
+
+ tmpdir = local('PYTEST_TMPDIR/test_fail10')
+
+ def test_fail1(tmpdir):
+ > assert 0
+ E assert 0
+
+ test_module.py:2: AssertionError
+ ________________________________ test_fail2 ________________________________
+
+ def test_fail2():
+ > assert 0
+ E assert 0
+
+ test_module.py:4: AssertionError
+ ========================= 2 failed in 0.12 seconds =========================
+
+you will have a "failures" file which contains the failing test ids::
+
+ $ cat failures
+ test_module.py::test_fail1 (PYTEST_TMPDIR/test_fail10)
+ test_module.py::test_fail2
+
+Making test result information available in fixtures
+-----------------------------------------------------------
+
+.. regendoc:wipe
+
+If you want to make test result reports available in fixture finalizers
+here is a little example implemented via a local plugin:
+
+.. code-block:: python
+
+ # content of conftest.py
+
+ import pytest
+
+ @pytest.hookimpl(tryfirst=True, hookwrapper=True)
+ def pytest_runtest_makereport(item, call):
+ # execute all other hooks to obtain the report object
+ outcome = yield
+ rep = outcome.get_result()
+
+ # set a report attribute for each phase of a call, which can
+ # be "setup", "call", "teardown"
+
+ setattr(item, "rep_" + rep.when, rep)
+
+
+ @pytest.fixture
+ def something(request):
+ yield
+ # request.node is an "item" because we use the default
+ # "function" scope
+ if request.node.rep_setup.failed:
+ print ("setting up a test failed!", request.node.nodeid)
+ elif request.node.rep_setup.passed:
+ if request.node.rep_call.failed:
+ print ("executing test failed", request.node.nodeid)
+
+
+if you then have failing tests:
+
+.. code-block:: python
+
+ # content of test_module.py
+
+ import pytest
+
+ @pytest.fixture
+ def other():
+ assert 0
+
+ def test_setup_fails(something, other):
+ pass
+
+ def test_call_fails(something):
+ assert 0
+
+ def test_fail2():
+ assert 0
+
+and run it::
+
+ $ pytest -s test_module.py
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 3 items
+
+ test_module.py Esetting up a test failed! test_module.py::test_setup_fails
+ Fexecuting test failed test_module.py::test_call_fails
+ F [100%]
+
+ ================================== ERRORS ==================================
+ ____________________ ERROR at setup of test_setup_fails ____________________
+
+ @pytest.fixture
+ def other():
+ > assert 0
+ E assert 0
+
+ test_module.py:6: AssertionError
+ ================================= FAILURES =================================
+ _____________________________ test_call_fails ______________________________
+
+ something = None
+
+ def test_call_fails(something):
+ > assert 0
+ E assert 0
+
+ test_module.py:12: AssertionError
+ ________________________________ test_fail2 ________________________________
+
+ def test_fail2():
+ > assert 0
+ E assert 0
+
+ test_module.py:15: AssertionError
+ ==================== 2 failed, 1 error in 0.12 seconds =====================
+
+You'll see that the fixture finalizers could use the precise reporting
+information.
+
+``PYTEST_CURRENT_TEST`` environment variable
+--------------------------------------------
+
+.. versionadded:: 3.2
+
+Sometimes a test session might get stuck and there might be no easy way to figure out
+which test got stuck, for example if pytest was run in quiet mode (``-q``) or you don't have access to the console
+output. This is particularly a problem if the problem helps only sporadically, the famous "flaky" kind of tests.
+
+``pytest`` sets a ``PYTEST_CURRENT_TEST`` environment variable when running tests, which can be inspected
+by process monitoring utilities or libraries like `psutil <https://pypi.python.org/pypi/psutil>`_ to discover which
+test got stuck if necessary:
+
+.. code-block:: python
+
+ import psutil
+
+ for pid in psutil.pids():
+ environ = psutil.Process(pid).environ()
+ if 'PYTEST_CURRENT_TEST' in environ:
+ print(f'pytest process {pid} running: {environ["PYTEST_CURRENT_TEST"]}')
+
+During the test session pytest will set ``PYTEST_CURRENT_TEST`` to the current test
+:ref:`nodeid <nodeids>` and the current stage, which can be ``setup``, ``call``
+and ``teardown``.
+
+For example, when running a single test function named ``test_foo`` from ``foo_module.py``,
+``PYTEST_CURRENT_TEST`` will be set to:
+
+#. ``foo_module.py::test_foo (setup)``
+#. ``foo_module.py::test_foo (call)``
+#. ``foo_module.py::test_foo (teardown)``
+
+In that order.
+
+.. note::
+
+ The contents of ``PYTEST_CURRENT_TEST`` is meant to be human readable and the actual format
+ can be changed between releases (even bug fixes) so it shouldn't be relied on for scripting
+ or automation.
+
+Freezing pytest
+---------------
+
+If you freeze your application using a tool like
+`PyInstaller <https://pyinstaller.readthedocs.io>`_
+in order to distribute it to your end-users, it is a good idea to also package
+your test runner and run your tests using the frozen application. This way packaging
+errors such as dependencies not being included into the executable can be detected early
+while also allowing you to send test files to users so they can run them in their
+machines, which can be useful to obtain more information about a hard to reproduce bug.
+
+Fortunately recent ``PyInstaller`` releases already have a custom hook
+for pytest, but if you are using another tool to freeze executables
+such as ``cx_freeze`` or ``py2exe``, you can use ``pytest.freeze_includes()``
+to obtain the full list of internal pytest modules. How to configure the tools
+to find the internal modules varies from tool to tool, however.
+
+Instead of freezing the pytest runner as a separate executable, you can make
+your frozen program work as the pytest runner by some clever
+argument handling during program startup. This allows you to
+have a single executable, which is usually more convenient.
+
+.. code-block:: python
+
+ # contents of app_main.py
+ import sys
+
+ if len(sys.argv) > 1 and sys.argv[1] == '--pytest':
+ import pytest
+ sys.exit(pytest.main(sys.argv[2:]))
+ else:
+ # normal application execution: at this point argv can be parsed
+ # by your argument-parsing library of choice as usual
+ ...
+
+
+This allows you to execute tests using the frozen
+application with standard ``pytest`` command-line options::
+
+ ./app_main --pytest --verbose --tb=long --junitxml=results.xml test-suite/
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/special.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/special.rst
new file mode 100644
index 00000000000..4437e1cc30e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/special.rst
@@ -0,0 +1,72 @@
+A session-fixture which can look at all collected tests
+----------------------------------------------------------------
+
+A session-scoped fixture effectively has access to all
+collected test items. Here is an example of a fixture
+function which walks all collected tests and looks
+if their test class defines a ``callme`` method and
+calls it::
+
+ # content of conftest.py
+
+ import pytest
+
+ @pytest.fixture(scope="session", autouse=True)
+ def callattr_ahead_of_alltests(request):
+ print ("callattr_ahead_of_alltests called")
+ seen = set([None])
+ session = request.node
+ for item in session.items:
+ cls = item.getparent(pytest.Class)
+ if cls not in seen:
+ if hasattr(cls.obj, "callme"):
+ cls.obj.callme()
+ seen.add(cls)
+
+test classes may now define a ``callme`` method which
+will be called ahead of running any tests::
+
+ # content of test_module.py
+
+ class TestHello(object):
+ @classmethod
+ def callme(cls):
+ print ("callme called!")
+
+ def test_method1(self):
+ print ("test_method1 called")
+
+ def test_method2(self):
+ print ("test_method1 called")
+
+ class TestOther(object):
+ @classmethod
+ def callme(cls):
+ print ("callme other called")
+ def test_other(self):
+ print ("test other")
+
+ # works with unittest as well ...
+ import unittest
+
+ class SomeTest(unittest.TestCase):
+ @classmethod
+ def callme(self):
+ print ("SomeTest callme called")
+
+ def test_unit1(self):
+ print ("test_unit1 method called")
+
+If you run this without output capturing::
+
+ $ pytest -q -s test_module.py
+ callattr_ahead_of_alltests called
+ callme called!
+ callme other called
+ SomeTest callme called
+ test_method1 called
+ .test_method1 called
+ .test other
+ .test_unit1 method called
+ . [100%]
+ 4 passed in 0.12 seconds
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/xfail_demo.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/xfail_demo.py
index 5648575e878..5648575e878 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/example/xfail_demo.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/example/xfail_demo.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/existingtestsuite.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/existingtestsuite.rst
new file mode 100644
index 00000000000..d304b30c9a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/existingtestsuite.rst
@@ -0,0 +1,34 @@
+.. _existingtestsuite:
+
+Using pytest with an existing test suite
+===========================================
+
+Pytest can be used with most existing test suites, but its
+behavior differs from other test runners such as :ref:`nose <noseintegration>` or
+Python's default unittest framework.
+
+Before using this section you will want to :ref:`install pytest <getstarted>`.
+
+Running an existing test suite with pytest
+---------------------------------------------
+
+Say you want to contribute to an existing repository somewhere.
+After pulling the code into your development space using some
+flavor of version control and (optionally) setting up a virtualenv
+you will want to run::
+
+ cd <repository>
+ pip install -e . # Environment dependent alternatives include
+ # 'python setup.py develop' and 'conda develop'
+
+in your project root. This will set up a symlink to your code in
+site-packages, allowing you to edit your code while your tests
+run against it as if it were installed.
+
+Setting up your project in development mode lets you avoid having to
+reinstall every time you want to run your tests, and is less brittle than
+mucking about with sys.path to point your tests at local code.
+
+Also consider using :ref:`tox <use tox>`.
+
+.. include:: links.inc
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/faq.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/faq.rst
new file mode 100644
index 00000000000..27d74e1148c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/faq.rst
@@ -0,0 +1,156 @@
+Some Issues and Questions
+==================================
+
+.. note::
+
+ This FAQ is here only mostly for historic reasons. Checkout
+ `pytest Q&A at Stackoverflow <http://stackoverflow.com/search?q=pytest>`_
+ for many questions and answers related to pytest and/or use
+ :ref:`contact channels` to get help.
+
+On naming, nosetests, licensing and magic
+------------------------------------------------
+
+How does pytest relate to nose and unittest?
++++++++++++++++++++++++++++++++++++++++++++++++++
+
+``pytest`` and nose_ share basic philosophy when it comes
+to running and writing Python tests. In fact, you can run many tests
+written for nose with ``pytest``. nose_ was originally created
+as a clone of ``pytest`` when ``pytest`` was in the ``0.8`` release
+cycle. Note that starting with pytest-2.0 support for running unittest
+test suites is majorly improved.
+
+how does pytest relate to twisted's trial?
+++++++++++++++++++++++++++++++++++++++++++++++
+
+Since some time ``pytest`` has builtin support for supporting tests
+written using trial. It does not itself start a reactor, however,
+and does not handle Deferreds returned from a test in pytest style.
+If you are using trial's unittest.TestCase chances are that you can
+just run your tests even if you return Deferreds. In addition,
+there also is a dedicated `pytest-twisted
+<http://pypi.python.org/pypi/pytest-twisted>`_ plugin which allows you to
+return deferreds from pytest-style tests, allowing the use of
+:ref:`fixtures` and other features.
+
+how does pytest work with Django?
+++++++++++++++++++++++++++++++++++++++++++++++
+
+In 2012, some work is going into the `pytest-django plugin <http://pypi.python.org/pypi/pytest-django>`_. It substitutes the usage of Django's
+``manage.py test`` and allows the use of all pytest features_ most of which
+are not available from Django directly.
+
+.. _features: features.html
+
+
+What's this "magic" with pytest? (historic notes)
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+Around 2007 (version ``0.8``) some people thought that ``pytest``
+was using too much "magic". It had been part of the `pylib`_ which
+contains a lot of unrelated python library code. Around 2010 there
+was a major cleanup refactoring, which removed unused or deprecated code
+and resulted in the new ``pytest`` PyPI package which strictly contains
+only test-related code. This release also brought a complete pluginification
+such that the core is around 300 lines of code and everything else is
+implemented in plugins. Thus ``pytest`` today is a small, universally runnable
+and customizable testing framework for Python. Note, however, that
+``pytest`` uses metaprogramming techniques and reading its source is
+thus likely not something for Python beginners.
+
+A second "magic" issue was the assert statement debugging feature.
+Nowadays, ``pytest`` explicitly rewrites assert statements in test modules
+in order to provide more useful :ref:`assert feedback <assertfeedback>`.
+This completely avoids previous issues of confusing assertion-reporting.
+It also means, that you can use Python's ``-O`` optimization without losing
+assertions in test modules.
+
+You can also turn off all assertion interaction using the
+``--assert=plain`` option.
+
+.. _`py namespaces`: index.html
+.. _`py/__init__.py`: http://bitbucket.org/hpk42/py-trunk/src/trunk/py/__init__.py
+
+
+Why can I use both ``pytest`` and ``py.test`` commands?
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+pytest used to be part of the py package, which provided several developer
+utilities, all starting with ``py.<TAB>``, thus providing nice TAB-completion.
+If you install ``pip install pycmd`` you get these tools from a separate
+package. Once ``pytest`` became a separate package, the ``py.test`` name was
+retained due to avoid a naming conflict with another tool. This conflict was
+eventually resolved, and the ``pytest`` command was therefore introduced. In
+future versions of pytest, we may deprecate and later remove the ``py.test``
+command to avoid perpetuating the confusion.
+
+pytest fixtures, parametrized tests
+-------------------------------------------------------
+
+.. _funcargs: funcargs.html
+
+Is using pytest fixtures versus xUnit setup a style question?
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+For simple applications and for people experienced with nose_ or
+unittest-style test setup using `xUnit style setup`_ probably
+feels natural. For larger test suites, parametrized testing
+or setup of complex test resources using fixtures_ may feel more natural.
+Moreover, fixtures are ideal for writing advanced test support
+code (like e.g. the monkeypatch_, the tmpdir_ or capture_ fixtures)
+because the support code can register setup/teardown functions
+in a managed class/module/function scope.
+
+.. _monkeypatch: monkeypatch.html
+.. _tmpdir: tmpdir.html
+.. _capture: capture.html
+.. _fixtures: fixture.html
+
+.. _`why pytest_pyfuncarg__ methods?`:
+
+.. _`Convention over Configuration`: http://en.wikipedia.org/wiki/Convention_over_Configuration
+
+Can I yield multiple values from a fixture function?
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+There are two conceptual reasons why yielding from a factory function
+is not possible:
+
+* If multiple factories yielded values there would
+ be no natural place to determine the combination
+ policy - in real-world examples some combinations
+ often should not run.
+
+* Calling factories for obtaining test function arguments
+ is part of setting up and running a test. At that
+ point it is not possible to add new test calls to
+ the test collection anymore.
+
+However, with pytest-2.3 you can use the :ref:`@pytest.fixture` decorator
+and specify ``params`` so that all tests depending on the factory-created
+resource will run multiple times with different parameters.
+
+You can also use the ``pytest_generate_tests`` hook to
+implement the `parametrization scheme of your choice`_. See also
+:ref:`paramexamples` for more examples.
+
+.. _`parametrization scheme of your choice`: http://tetamap.wordpress.com/2009/05/13/parametrizing-python-tests-generalized/
+
+pytest interaction with other packages
+---------------------------------------------------
+
+Issues with pytest, multiprocess and setuptools?
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+On Windows the multiprocess package will instantiate sub processes
+by pickling and thus implicitly re-import a lot of local modules.
+Unfortunately, setuptools-0.6.11 does not ``if __name__=='__main__'``
+protect its generated command line script. This leads to infinite
+recursion when running a test that instantiates Processes.
+
+As of mid-2013, there shouldn't be a problem anymore when you
+use the standard setuptools (note that distribute has been merged
+back into setuptools which is now shipped directly with virtualenv).
+
+.. include:: links.inc
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/fixture.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/fixture.rst
new file mode 100644
index 00000000000..01a941ddf65
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/fixture.rst
@@ -0,0 +1,1088 @@
+.. _fixture:
+.. _fixtures:
+.. _`fixture functions`:
+
+pytest fixtures: explicit, modular, scalable
+========================================================
+
+.. currentmodule:: _pytest.python
+
+.. versionadded:: 2.0/2.3/2.4
+
+.. _`xUnit`: http://en.wikipedia.org/wiki/XUnit
+.. _`purpose of test fixtures`: http://en.wikipedia.org/wiki/Test_fixture#Software
+.. _`Dependency injection`: http://en.wikipedia.org/wiki/Dependency_injection
+
+The `purpose of test fixtures`_ is to provide a fixed baseline
+upon which tests can reliably and repeatedly execute. pytest fixtures
+offer dramatic improvements over the classic xUnit style of setup/teardown
+functions:
+
+* fixtures have explicit names and are activated by declaring their use
+ from test functions, modules, classes or whole projects.
+
+* fixtures are implemented in a modular manner, as each fixture name
+ triggers a *fixture function* which can itself use other fixtures.
+
+* fixture management scales from simple unit to complex
+ functional testing, allowing to parametrize fixtures and tests according
+ to configuration and component options, or to re-use fixtures
+ across function, class, module or whole test session scopes.
+
+In addition, pytest continues to support :ref:`xunitsetup`. You can mix
+both styles, moving incrementally from classic to new style, as you
+prefer. You can also start out from existing :ref:`unittest.TestCase
+style <unittest.TestCase>` or :ref:`nose based <nosestyle>` projects.
+
+
+.. _`funcargs`:
+.. _`funcarg mechanism`:
+.. _`fixture function`:
+.. _`@pytest.fixture`:
+.. _`pytest.fixture`:
+
+Fixtures as Function arguments
+-----------------------------------------
+
+Test functions can receive fixture objects by naming them as an input
+argument. For each argument name, a fixture function with that name provides
+the fixture object. Fixture functions are registered by marking them with
+:py:func:`@pytest.fixture <_pytest.python.fixture>`. Let's look at a simple
+self-contained test module containing a fixture and a test function
+using it::
+
+ # content of ./test_smtpsimple.py
+ import pytest
+
+ @pytest.fixture
+ def smtp():
+ import smtplib
+ return smtplib.SMTP("smtp.gmail.com", 587, timeout=5)
+
+ def test_ehlo(smtp):
+ response, msg = smtp.ehlo()
+ assert response == 250
+ assert 0 # for demo purposes
+
+Here, the ``test_ehlo`` needs the ``smtp`` fixture value. pytest
+will discover and call the :py:func:`@pytest.fixture <_pytest.python.fixture>`
+marked ``smtp`` fixture function. Running the test looks like this::
+
+ $ pytest test_smtpsimple.py
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 1 item
+
+ test_smtpsimple.py F [100%]
+
+ ================================= FAILURES =================================
+ ________________________________ test_ehlo _________________________________
+
+ smtp = <smtplib.SMTP object at 0xdeadbeef>
+
+ def test_ehlo(smtp):
+ response, msg = smtp.ehlo()
+ assert response == 250
+ > assert 0 # for demo purposes
+ E assert 0
+
+ test_smtpsimple.py:11: AssertionError
+ ========================= 1 failed in 0.12 seconds =========================
+
+In the failure traceback we see that the test function was called with a
+``smtp`` argument, the ``smtplib.SMTP()`` instance created by the fixture
+function. The test function fails on our deliberate ``assert 0``. Here is
+the exact protocol used by ``pytest`` to call the test function this way:
+
+1. pytest :ref:`finds <test discovery>` the ``test_ehlo`` because
+ of the ``test_`` prefix. The test function needs a function argument
+ named ``smtp``. A matching fixture function is discovered by
+ looking for a fixture-marked function named ``smtp``.
+
+2. ``smtp()`` is called to create an instance.
+
+3. ``test_ehlo(<SMTP instance>)`` is called and fails in the last
+ line of the test function.
+
+Note that if you misspell a function argument or want
+to use one that isn't available, you'll see an error
+with a list of available function arguments.
+
+.. note::
+
+ You can always issue::
+
+ pytest --fixtures test_simplefactory.py
+
+ to see available fixtures.
+
+Fixtures: a prime example of dependency injection
+---------------------------------------------------
+
+Fixtures allow test functions to easily receive and work
+against specific pre-initialized application objects without having
+to care about import/setup/cleanup details.
+It's a prime example of `dependency injection`_ where fixture
+functions take the role of the *injector* and test functions are the
+*consumers* of fixture objects.
+
+.. _`conftest.py`:
+.. _`conftest`:
+
+``conftest.py``: sharing fixture functions
+------------------------------------------
+
+If during implementing your tests you realize that you
+want to use a fixture function from multiple test files you can move it
+to a ``conftest.py`` file.
+You don't need to import the fixture you want to use in a test, it
+automatically gets discovered by pytest. The discovery of
+fixture functions starts at test classes, then test modules, then
+``conftest.py`` files and finally builtin and third party plugins.
+
+You can also use the ``conftest.py`` file to implement
+:ref:`local per-directory plugins <conftest.py plugins>`.
+
+Sharing test data
+-----------------
+
+If you want to make test data from files available to your tests, a good way
+to do this is by loading these data in a fixture for use by your tests.
+This makes use of the automatic caching mechanisms of pytest.
+
+Another good approach is by adding the data files in the ``tests`` folder.
+There are also community plugins available to help managing this aspect of
+testing, e.g. `pytest-datadir <https://github.com/gabrielcnr/pytest-datadir>`__
+and `pytest-datafiles <https://pypi.python.org/pypi/pytest-datafiles>`__.
+
+.. _smtpshared:
+
+Scope: sharing a fixture instance across tests in a class, module or session
+----------------------------------------------------------------------------
+
+.. regendoc:wipe
+
+Fixtures requiring network access depend on connectivity and are
+usually time-expensive to create. Extending the previous example, we
+can add a ``scope='module'`` parameter to the
+:py:func:`@pytest.fixture <_pytest.python.fixture>` invocation
+to cause the decorated ``smtp`` fixture function to only be invoked once
+per test *module* (the default is to invoke once per test *function*).
+Multiple test functions in a test module will thus
+each receive the same ``smtp`` fixture instance, thus saving time.
+
+The next example puts the fixture function into a separate ``conftest.py`` file
+so that tests from multiple test modules in the directory can
+access the fixture function::
+
+ # content of conftest.py
+ import pytest
+ import smtplib
+
+ @pytest.fixture(scope="module")
+ def smtp():
+ return smtplib.SMTP("smtp.gmail.com", 587, timeout=5)
+
+The name of the fixture again is ``smtp`` and you can access its result by
+listing the name ``smtp`` as an input parameter in any test or fixture
+function (in or below the directory where ``conftest.py`` is located)::
+
+ # content of test_module.py
+
+ def test_ehlo(smtp):
+ response, msg = smtp.ehlo()
+ assert response == 250
+ assert b"smtp.gmail.com" in msg
+ assert 0 # for demo purposes
+
+ def test_noop(smtp):
+ response, msg = smtp.noop()
+ assert response == 250
+ assert 0 # for demo purposes
+
+We deliberately insert failing ``assert 0`` statements in order to
+inspect what is going on and can now run the tests::
+
+ $ pytest test_module.py
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 2 items
+
+ test_module.py FF [100%]
+
+ ================================= FAILURES =================================
+ ________________________________ test_ehlo _________________________________
+
+ smtp = <smtplib.SMTP object at 0xdeadbeef>
+
+ def test_ehlo(smtp):
+ response, msg = smtp.ehlo()
+ assert response == 250
+ assert b"smtp.gmail.com" in msg
+ > assert 0 # for demo purposes
+ E assert 0
+
+ test_module.py:6: AssertionError
+ ________________________________ test_noop _________________________________
+
+ smtp = <smtplib.SMTP object at 0xdeadbeef>
+
+ def test_noop(smtp):
+ response, msg = smtp.noop()
+ assert response == 250
+ > assert 0 # for demo purposes
+ E assert 0
+
+ test_module.py:11: AssertionError
+ ========================= 2 failed in 0.12 seconds =========================
+
+You see the two ``assert 0`` failing and more importantly you can also see
+that the same (module-scoped) ``smtp`` object was passed into the two
+test functions because pytest shows the incoming argument values in the
+traceback. As a result, the two test functions using ``smtp`` run as
+quick as a single one because they reuse the same instance.
+
+If you decide that you rather want to have a session-scoped ``smtp``
+instance, you can simply declare it:
+
+.. code-block:: python
+
+ @pytest.fixture(scope="session")
+ def smtp(...):
+ # the returned fixture value will be shared for
+ # all tests needing it
+
+Finally, the ``class`` scope will invoke the fixture once per test *class*.
+
+.. _`finalization`:
+
+Fixture finalization / executing teardown code
+-------------------------------------------------------------
+
+pytest supports execution of fixture specific finalization code
+when the fixture goes out of scope. By using a ``yield`` statement instead of ``return``, all
+the code after the *yield* statement serves as the teardown code:
+
+.. code-block:: python
+
+ # content of conftest.py
+
+ import smtplib
+ import pytest
+
+ @pytest.fixture(scope="module")
+ def smtp():
+ smtp = smtplib.SMTP("smtp.gmail.com", 587, timeout=5)
+ yield smtp # provide the fixture value
+ print("teardown smtp")
+ smtp.close()
+
+The ``print`` and ``smtp.close()`` statements will execute when the last test in
+the module has finished execution, regardless of the exception status of the
+tests.
+
+Let's execute it::
+
+ $ pytest -s -q --tb=no
+ FF [100%]teardown smtp
+
+ 2 failed in 0.12 seconds
+
+We see that the ``smtp`` instance is finalized after the two
+tests finished execution. Note that if we decorated our fixture
+function with ``scope='function'`` then fixture setup and cleanup would
+occur around each single test. In either case the test
+module itself does not need to change or know about these details
+of fixture setup.
+
+Note that we can also seamlessly use the ``yield`` syntax with ``with`` statements:
+
+.. code-block:: python
+
+ # content of test_yield2.py
+
+ import smtplib
+ import pytest
+
+ @pytest.fixture(scope="module")
+ def smtp():
+ with smtplib.SMTP("smtp.gmail.com", 587, timeout=5) as smtp:
+ yield smtp # provide the fixture value
+
+
+The ``smtp`` connection will be closed after the test finished execution
+because the ``smtp`` object automatically closes when
+the ``with`` statement ends.
+
+Note that if an exception happens during the *setup* code (before the ``yield`` keyword), the
+*teardown* code (after the ``yield``) will not be called.
+
+An alternative option for executing *teardown* code is to
+make use of the ``addfinalizer`` method of the `request-context`_ object to register
+finalization functions.
+
+Here's the ``smtp`` fixture changed to use ``addfinalizer`` for cleanup:
+
+.. code-block:: python
+
+ # content of conftest.py
+ import smtplib
+ import pytest
+
+ @pytest.fixture(scope="module")
+ def smtp(request):
+ smtp = smtplib.SMTP("smtp.gmail.com", 587, timeout=5)
+ def fin():
+ print ("teardown smtp")
+ smtp.close()
+ request.addfinalizer(fin)
+ return smtp # provide the fixture value
+
+
+Both ``yield`` and ``addfinalizer`` methods work similarly by calling their code after the test
+ends, but ``addfinalizer`` has two key differences over ``yield``:
+
+1. It is possible to register multiple finalizer functions.
+
+2. Finalizers will always be called regardless if the fixture *setup* code raises an exception.
+ This is handy to properly close all resources created by a fixture even if one of them
+ fails to be created/acquired::
+
+ @pytest.fixture
+ def equipments(request):
+ r = []
+ for port in ('C1', 'C3', 'C28'):
+ equip = connect(port)
+ request.addfinalizer(equip.disconnect)
+ r.append(equip)
+ return r
+
+ In the example above, if ``"C28"`` fails with an exception, ``"C1"`` and ``"C3"`` will still
+ be properly closed. Of course, if an exception happens before the finalize function is
+ registered then it will not be executed.
+
+
+.. _`request-context`:
+
+Fixtures can introspect the requesting test context
+-------------------------------------------------------------
+
+Fixture function can accept the :py:class:`request <FixtureRequest>` object
+to introspect the "requesting" test function, class or module context.
+Further extending the previous ``smtp`` fixture example, let's
+read an optional server URL from the test module which uses our fixture::
+
+ # content of conftest.py
+ import pytest
+ import smtplib
+
+ @pytest.fixture(scope="module")
+ def smtp(request):
+ server = getattr(request.module, "smtpserver", "smtp.gmail.com")
+ smtp = smtplib.SMTP(server, 587, timeout=5)
+ yield smtp
+ print ("finalizing %s (%s)" % (smtp, server))
+ smtp.close()
+
+We use the ``request.module`` attribute to optionally obtain an
+``smtpserver`` attribute from the test module. If we just execute
+again, nothing much has changed::
+
+ $ pytest -s -q --tb=no
+ FF [100%]finalizing <smtplib.SMTP object at 0xdeadbeef> (smtp.gmail.com)
+
+ 2 failed in 0.12 seconds
+
+Let's quickly create another test module that actually sets the
+server URL in its module namespace::
+
+ # content of test_anothersmtp.py
+
+ smtpserver = "mail.python.org" # will be read by smtp fixture
+
+ def test_showhelo(smtp):
+ assert 0, smtp.helo()
+
+Running it::
+
+ $ pytest -qq --tb=short test_anothersmtp.py
+ F [100%]
+ ================================= FAILURES =================================
+ ______________________________ test_showhelo _______________________________
+ test_anothersmtp.py:5: in test_showhelo
+ assert 0, smtp.helo()
+ E AssertionError: (250, b'mail.python.org')
+ E assert 0
+ ------------------------- Captured stdout teardown -------------------------
+ finalizing <smtplib.SMTP object at 0xdeadbeef> (mail.python.org)
+
+voila! The ``smtp`` fixture function picked up our mail server name
+from the module namespace.
+
+.. _`fixture-parametrize`:
+
+Parametrizing fixtures
+-----------------------------------------------------------------
+
+Fixture functions can be parametrized in which case they will be called
+multiple times, each time executing the set of dependent tests, i. e. the
+tests that depend on this fixture. Test functions do usually not need
+to be aware of their re-running. Fixture parametrization helps to
+write exhaustive functional tests for components which themselves can be
+configured in multiple ways.
+
+Extending the previous example, we can flag the fixture to create two
+``smtp`` fixture instances which will cause all tests using the fixture
+to run twice. The fixture function gets access to each parameter
+through the special :py:class:`request <FixtureRequest>` object::
+
+ # content of conftest.py
+ import pytest
+ import smtplib
+
+ @pytest.fixture(scope="module",
+ params=["smtp.gmail.com", "mail.python.org"])
+ def smtp(request):
+ smtp = smtplib.SMTP(request.param, 587, timeout=5)
+ yield smtp
+ print ("finalizing %s" % smtp)
+ smtp.close()
+
+The main change is the declaration of ``params`` with
+:py:func:`@pytest.fixture <_pytest.python.fixture>`, a list of values
+for each of which the fixture function will execute and can access
+a value via ``request.param``. No test function code needs to change.
+So let's just do another run::
+
+ $ pytest -q test_module.py
+ FFFF [100%]
+ ================================= FAILURES =================================
+ ________________________ test_ehlo[smtp.gmail.com] _________________________
+
+ smtp = <smtplib.SMTP object at 0xdeadbeef>
+
+ def test_ehlo(smtp):
+ response, msg = smtp.ehlo()
+ assert response == 250
+ assert b"smtp.gmail.com" in msg
+ > assert 0 # for demo purposes
+ E assert 0
+
+ test_module.py:6: AssertionError
+ ________________________ test_noop[smtp.gmail.com] _________________________
+
+ smtp = <smtplib.SMTP object at 0xdeadbeef>
+
+ def test_noop(smtp):
+ response, msg = smtp.noop()
+ assert response == 250
+ > assert 0 # for demo purposes
+ E assert 0
+
+ test_module.py:11: AssertionError
+ ________________________ test_ehlo[mail.python.org] ________________________
+
+ smtp = <smtplib.SMTP object at 0xdeadbeef>
+
+ def test_ehlo(smtp):
+ response, msg = smtp.ehlo()
+ assert response == 250
+ > assert b"smtp.gmail.com" in msg
+ E AssertionError: assert b'smtp.gmail.com' in b'mail.python.org\nPIPELINING\nSIZE 51200000\nETRN\nSTARTTLS\nAUTH DIGEST-MD5 NTLM CRAM-MD5\nENHANCEDSTATUSCODES\n8BITMIME\nDSN\nSMTPUTF8'
+
+ test_module.py:5: AssertionError
+ -------------------------- Captured stdout setup ---------------------------
+ finalizing <smtplib.SMTP object at 0xdeadbeef>
+ ________________________ test_noop[mail.python.org] ________________________
+
+ smtp = <smtplib.SMTP object at 0xdeadbeef>
+
+ def test_noop(smtp):
+ response, msg = smtp.noop()
+ assert response == 250
+ > assert 0 # for demo purposes
+ E assert 0
+
+ test_module.py:11: AssertionError
+ ------------------------- Captured stdout teardown -------------------------
+ finalizing <smtplib.SMTP object at 0xdeadbeef>
+ 4 failed in 0.12 seconds
+
+We see that our two test functions each ran twice, against the different
+``smtp`` instances. Note also, that with the ``mail.python.org``
+connection the second test fails in ``test_ehlo`` because a
+different server string is expected than what arrived.
+
+pytest will build a string that is the test ID for each fixture value
+in a parametrized fixture, e.g. ``test_ehlo[smtp.gmail.com]`` and
+``test_ehlo[mail.python.org]`` in the above examples. These IDs can
+be used with ``-k`` to select specific cases to run, and they will
+also identify the specific case when one is failing. Running pytest
+with ``--collect-only`` will show the generated IDs.
+
+Numbers, strings, booleans and None will have their usual string
+representation used in the test ID. For other objects, pytest will
+make a string based on the argument name. It is possible to customise
+the string used in a test ID for a certain fixture value by using the
+``ids`` keyword argument::
+
+ # content of test_ids.py
+ import pytest
+
+ @pytest.fixture(params=[0, 1], ids=["spam", "ham"])
+ def a(request):
+ return request.param
+
+ def test_a(a):
+ pass
+
+ def idfn(fixture_value):
+ if fixture_value == 0:
+ return "eggs"
+ else:
+ return None
+
+ @pytest.fixture(params=[0, 1], ids=idfn)
+ def b(request):
+ return request.param
+
+ def test_b(b):
+ pass
+
+The above shows how ``ids`` can be either a list of strings to use or
+a function which will be called with the fixture value and then
+has to return a string to use. In the latter case if the function
+return ``None`` then pytest's auto-generated ID will be used.
+
+Running the above tests results in the following test IDs being used::
+
+ $ pytest --collect-only
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 10 items
+ <Module 'test_anothersmtp.py'>
+ <Function 'test_showhelo[smtp.gmail.com]'>
+ <Function 'test_showhelo[mail.python.org]'>
+ <Module 'test_ids.py'>
+ <Function 'test_a[spam]'>
+ <Function 'test_a[ham]'>
+ <Function 'test_b[eggs]'>
+ <Function 'test_b[1]'>
+ <Module 'test_module.py'>
+ <Function 'test_ehlo[smtp.gmail.com]'>
+ <Function 'test_noop[smtp.gmail.com]'>
+ <Function 'test_ehlo[mail.python.org]'>
+ <Function 'test_noop[mail.python.org]'>
+
+ ======================= no tests ran in 0.12 seconds =======================
+
+.. _`interdependent fixtures`:
+
+Modularity: using fixtures from a fixture function
+----------------------------------------------------------
+
+You can not only use fixtures in test functions but fixture functions
+can use other fixtures themselves. This contributes to a modular design
+of your fixtures and allows re-use of framework-specific fixtures across
+many projects. As a simple example, we can extend the previous example
+and instantiate an object ``app`` where we stick the already defined
+``smtp`` resource into it::
+
+ # content of test_appsetup.py
+
+ import pytest
+
+ class App(object):
+ def __init__(self, smtp):
+ self.smtp = smtp
+
+ @pytest.fixture(scope="module")
+ def app(smtp):
+ return App(smtp)
+
+ def test_smtp_exists(app):
+ assert app.smtp
+
+Here we declare an ``app`` fixture which receives the previously defined
+``smtp`` fixture and instantiates an ``App`` object with it. Let's run it::
+
+ $ pytest -v test_appsetup.py
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.5
+ cachedir: .cache
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collecting ... collected 2 items
+
+ test_appsetup.py::test_smtp_exists[smtp.gmail.com] PASSED [ 50%]
+ test_appsetup.py::test_smtp_exists[mail.python.org] PASSED [100%]
+
+ ========================= 2 passed in 0.12 seconds =========================
+
+Due to the parametrization of ``smtp`` the test will run twice with two
+different ``App`` instances and respective smtp servers. There is no
+need for the ``app`` fixture to be aware of the ``smtp`` parametrization
+as pytest will fully analyse the fixture dependency graph.
+
+Note, that the ``app`` fixture has a scope of ``module`` and uses a
+module-scoped ``smtp`` fixture. The example would still work if ``smtp``
+was cached on a ``session`` scope: it is fine for fixtures to use
+"broader" scoped fixtures but not the other way round:
+A session-scoped fixture could not use a module-scoped one in a
+meaningful way.
+
+
+.. _`automatic per-resource grouping`:
+
+Automatic grouping of tests by fixture instances
+----------------------------------------------------------
+
+.. regendoc: wipe
+
+pytest minimizes the number of active fixtures during test runs.
+If you have a parametrized fixture, then all the tests using it will
+first execute with one instance and then finalizers are called
+before the next fixture instance is created. Among other things,
+this eases testing of applications which create and use global state.
+
+The following example uses two parametrized fixture, one of which is
+scoped on a per-module basis, and all the functions perform ``print`` calls
+to show the setup/teardown flow::
+
+ # content of test_module.py
+ import pytest
+
+ @pytest.fixture(scope="module", params=["mod1", "mod2"])
+ def modarg(request):
+ param = request.param
+ print (" SETUP modarg %s" % param)
+ yield param
+ print (" TEARDOWN modarg %s" % param)
+
+ @pytest.fixture(scope="function", params=[1,2])
+ def otherarg(request):
+ param = request.param
+ print (" SETUP otherarg %s" % param)
+ yield param
+ print (" TEARDOWN otherarg %s" % param)
+
+ def test_0(otherarg):
+ print (" RUN test0 with otherarg %s" % otherarg)
+ def test_1(modarg):
+ print (" RUN test1 with modarg %s" % modarg)
+ def test_2(otherarg, modarg):
+ print (" RUN test2 with otherarg %s and modarg %s" % (otherarg, modarg))
+
+
+Let's run the tests in verbose mode and with looking at the print-output::
+
+ $ pytest -v -s test_module.py
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.5
+ cachedir: .cache
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collecting ... collected 8 items
+
+ test_module.py::test_0[1] SETUP otherarg 1
+ RUN test0 with otherarg 1
+ PASSED [ 12%] TEARDOWN otherarg 1
+
+ test_module.py::test_0[2] SETUP otherarg 2
+ RUN test0 with otherarg 2
+ PASSED [ 25%] TEARDOWN otherarg 2
+
+ test_module.py::test_1[mod1] SETUP modarg mod1
+ RUN test1 with modarg mod1
+ PASSED [ 37%]
+ test_module.py::test_2[1-mod1] SETUP otherarg 1
+ RUN test2 with otherarg 1 and modarg mod1
+ PASSED [ 50%] TEARDOWN otherarg 1
+
+ test_module.py::test_2[2-mod1] SETUP otherarg 2
+ RUN test2 with otherarg 2 and modarg mod1
+ PASSED [ 62%] TEARDOWN otherarg 2
+
+ test_module.py::test_1[mod2] TEARDOWN modarg mod1
+ SETUP modarg mod2
+ RUN test1 with modarg mod2
+ PASSED [ 75%]
+ test_module.py::test_2[1-mod2] SETUP otherarg 1
+ RUN test2 with otherarg 1 and modarg mod2
+ PASSED [ 87%] TEARDOWN otherarg 1
+
+ test_module.py::test_2[2-mod2] SETUP otherarg 2
+ RUN test2 with otherarg 2 and modarg mod2
+ PASSED [100%] TEARDOWN otherarg 2
+ TEARDOWN modarg mod2
+
+
+ ========================= 8 passed in 0.12 seconds =========================
+
+You can see that the parametrized module-scoped ``modarg`` resource caused an
+ordering of test execution that lead to the fewest possible "active" resources.
+The finalizer for the ``mod1`` parametrized resource was executed before the
+``mod2`` resource was setup.
+
+In particular notice that test_0 is completely independent and finishes first.
+Then test_1 is executed with ``mod1``, then test_2 with ``mod1``, then test_1
+with ``mod2`` and finally test_2 with ``mod2``.
+
+The ``otherarg`` parametrized resource (having function scope) was set up before
+and teared down after every test that used it.
+
+
+.. _`usefixtures`:
+
+Using fixtures from classes, modules or projects
+----------------------------------------------------------------------
+
+.. regendoc:wipe
+
+Sometimes test functions do not directly need access to a fixture object.
+For example, tests may require to operate with an empty directory as the
+current working directory but otherwise do not care for the concrete
+directory. Here is how you can use the standard `tempfile
+<http://docs.python.org/library/tempfile.html>`_ and pytest fixtures to
+achieve it. We separate the creation of the fixture into a conftest.py
+file::
+
+ # content of conftest.py
+
+ import pytest
+ import tempfile
+ import os
+
+ @pytest.fixture()
+ def cleandir():
+ newpath = tempfile.mkdtemp()
+ os.chdir(newpath)
+
+and declare its use in a test module via a ``usefixtures`` marker::
+
+ # content of test_setenv.py
+ import os
+ import pytest
+
+ @pytest.mark.usefixtures("cleandir")
+ class TestDirectoryInit(object):
+ def test_cwd_starts_empty(self):
+ assert os.listdir(os.getcwd()) == []
+ with open("myfile", "w") as f:
+ f.write("hello")
+
+ def test_cwd_again_starts_empty(self):
+ assert os.listdir(os.getcwd()) == []
+
+Due to the ``usefixtures`` marker, the ``cleandir`` fixture
+will be required for the execution of each test method, just as if
+you specified a "cleandir" function argument to each of them. Let's run it
+to verify our fixture is activated and the tests pass::
+
+ $ pytest -q
+ .. [100%]
+ 2 passed in 0.12 seconds
+
+You can specify multiple fixtures like this:
+
+.. code-block:: python
+
+ @pytest.mark.usefixtures("cleandir", "anotherfixture")
+
+and you may specify fixture usage at the test module level, using
+a generic feature of the mark mechanism:
+
+.. code-block:: python
+
+ pytestmark = pytest.mark.usefixtures("cleandir")
+
+Note that the assigned variable *must* be called ``pytestmark``, assigning e.g.
+``foomark`` will not activate the fixtures.
+
+Lastly you can put fixtures required by all tests in your project
+into an ini-file:
+
+.. code-block:: ini
+
+ # content of pytest.ini
+ [pytest]
+ usefixtures = cleandir
+
+
+.. _`autouse`:
+.. _`autouse fixtures`:
+
+Autouse fixtures (xUnit setup on steroids)
+----------------------------------------------------------------------
+
+.. regendoc:wipe
+
+Occasionally, you may want to have fixtures get invoked automatically
+without declaring a function argument explicitly or a `usefixtures`_ decorator.
+As a practical example, suppose we have a database fixture which has a
+begin/rollback/commit architecture and we want to automatically surround
+each test method by a transaction and a rollback. Here is a dummy
+self-contained implementation of this idea::
+
+ # content of test_db_transact.py
+
+ import pytest
+
+ class DB(object):
+ def __init__(self):
+ self.intransaction = []
+ def begin(self, name):
+ self.intransaction.append(name)
+ def rollback(self):
+ self.intransaction.pop()
+
+ @pytest.fixture(scope="module")
+ def db():
+ return DB()
+
+ class TestClass(object):
+ @pytest.fixture(autouse=True)
+ def transact(self, request, db):
+ db.begin(request.function.__name__)
+ yield
+ db.rollback()
+
+ def test_method1(self, db):
+ assert db.intransaction == ["test_method1"]
+
+ def test_method2(self, db):
+ assert db.intransaction == ["test_method2"]
+
+The class-level ``transact`` fixture is marked with *autouse=true*
+which implies that all test methods in the class will use this fixture
+without a need to state it in the test function signature or with a
+class-level ``usefixtures`` decorator.
+
+If we run it, we get two passing tests::
+
+ $ pytest -q
+ .. [100%]
+ 2 passed in 0.12 seconds
+
+Here is how autouse fixtures work in other scopes:
+
+- autouse fixtures obey the ``scope=`` keyword-argument: if an autouse fixture
+ has ``scope='session'`` it will only be run once, no matter where it is
+ defined. ``scope='class'`` means it will be run once per class, etc.
+
+- if an autouse fixture is defined in a test module, all its test
+ functions automatically use it.
+
+- if an autouse fixture is defined in a conftest.py file then all tests in
+ all test modules below its directory will invoke the fixture.
+
+- lastly, and **please use that with care**: if you define an autouse
+ fixture in a plugin, it will be invoked for all tests in all projects
+ where the plugin is installed. This can be useful if a fixture only
+ anyway works in the presence of certain settings e. g. in the ini-file. Such
+ a global fixture should always quickly determine if it should do
+ any work and avoid otherwise expensive imports or computation.
+
+Note that the above ``transact`` fixture may very well be a fixture that
+you want to make available in your project without having it generally
+active. The canonical way to do that is to put the transact definition
+into a conftest.py file **without** using ``autouse``::
+
+ # content of conftest.py
+ @pytest.fixture
+ def transact(request, db):
+ db.begin()
+ yield
+ db.rollback()
+
+and then e.g. have a TestClass using it by declaring the need::
+
+ @pytest.mark.usefixtures("transact")
+ class TestClass(object):
+ def test_method1(self):
+ ...
+
+All test methods in this TestClass will use the transaction fixture while
+other test classes or functions in the module will not use it unless
+they also add a ``transact`` reference.
+
+Overriding fixtures on various levels
+-------------------------------------
+
+In relatively large test suite, you most likely need to ``override`` a ``global`` or ``root`` fixture with a ``locally``
+defined one, keeping the test code readable and maintainable.
+
+Override a fixture on a folder (conftest) level
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Given the tests file structure is:
+
+::
+
+ tests/
+ __init__.py
+
+ conftest.py
+ # content of tests/conftest.py
+ import pytest
+
+ @pytest.fixture
+ def username():
+ return 'username'
+
+ test_something.py
+ # content of tests/test_something.py
+ def test_username(username):
+ assert username == 'username'
+
+ subfolder/
+ __init__.py
+
+ conftest.py
+ # content of tests/subfolder/conftest.py
+ import pytest
+
+ @pytest.fixture
+ def username(username):
+ return 'overridden-' + username
+
+ test_something.py
+ # content of tests/subfolder/test_something.py
+ def test_username(username):
+ assert username == 'overridden-username'
+
+As you can see, a fixture with the same name can be overridden for certain test folder level.
+Note that the ``base`` or ``super`` fixture can be accessed from the ``overriding``
+fixture easily - used in the example above.
+
+Override a fixture on a test module level
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Given the tests file structure is:
+
+::
+
+ tests/
+ __init__.py
+
+ conftest.py
+ # content of tests/conftest.py
+ @pytest.fixture
+ def username():
+ return 'username'
+
+ test_something.py
+ # content of tests/test_something.py
+ import pytest
+
+ @pytest.fixture
+ def username(username):
+ return 'overridden-' + username
+
+ def test_username(username):
+ assert username == 'overridden-username'
+
+ test_something_else.py
+ # content of tests/test_something_else.py
+ import pytest
+
+ @pytest.fixture
+ def username(username):
+ return 'overridden-else-' + username
+
+ def test_username(username):
+ assert username == 'overridden-else-username'
+
+In the example above, a fixture with the same name can be overridden for certain test module.
+
+
+Override a fixture with direct test parametrization
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Given the tests file structure is:
+
+::
+
+ tests/
+ __init__.py
+
+ conftest.py
+ # content of tests/conftest.py
+ import pytest
+
+ @pytest.fixture
+ def username():
+ return 'username'
+
+ @pytest.fixture
+ def other_username(username):
+ return 'other-' + username
+
+ test_something.py
+ # content of tests/test_something.py
+ import pytest
+
+ @pytest.mark.parametrize('username', ['directly-overridden-username'])
+ def test_username(username):
+ assert username == 'directly-overridden-username'
+
+ @pytest.mark.parametrize('username', ['directly-overridden-username-other'])
+ def test_username_other(other_username):
+ assert other_username == 'other-directly-overridden-username-other'
+
+In the example above, a fixture value is overridden by the test parameter value. Note that the value of the fixture
+can be overridden this way even if the test doesn't use it directly (doesn't mention it in the function prototype).
+
+
+Override a parametrized fixture with non-parametrized one and vice versa
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Given the tests file structure is:
+
+::
+
+ tests/
+ __init__.py
+
+ conftest.py
+ # content of tests/conftest.py
+ import pytest
+
+ @pytest.fixture(params=['one', 'two', 'three'])
+ def parametrized_username(request):
+ return request.param
+
+ @pytest.fixture
+ def non_parametrized_username(request):
+ return 'username'
+
+ test_something.py
+ # content of tests/test_something.py
+ import pytest
+
+ @pytest.fixture
+ def parametrized_username():
+ return 'overridden-username'
+
+ @pytest.fixture(params=['one', 'two', 'three'])
+ def non_parametrized_username(request):
+ return request.param
+
+ def test_username(parametrized_username):
+ assert parametrized_username == 'overridden-username'
+
+ def test_parametrized_username(non_parametrized_username):
+ assert non_parametrized_username in ['one', 'two', 'three']
+
+ test_something_else.py
+ # content of tests/test_something_else.py
+ def test_username(parametrized_username):
+ assert parametrized_username in ['one', 'two', 'three']
+
+ def test_username(non_parametrized_username):
+ assert non_parametrized_username == 'username'
+
+In the example above, a parametrized fixture is overridden with a non-parametrized version, and
+a non-parametrized fixture is overridden with a parametrized version for certain test module.
+The same applies for the test folder level obviously.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/funcarg_compare.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/funcarg_compare.rst
new file mode 100644
index 00000000000..b857a014d31
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/funcarg_compare.rst
@@ -0,0 +1,218 @@
+:orphan:
+
+.. _`funcargcompare`:
+
+pytest-2.3: reasoning for fixture/funcarg evolution
+=============================================================
+
+**Target audience**: Reading this document requires basic knowledge of
+python testing, xUnit setup methods and the (previous) basic pytest
+funcarg mechanism, see http://pytest.org/2.2.4/funcargs.html
+If you are new to pytest, then you can simply ignore this
+section and read the other sections.
+
+.. currentmodule:: _pytest
+
+Shortcomings of the previous ``pytest_funcarg__`` mechanism
+--------------------------------------------------------------
+
+The pre pytest-2.3 funcarg mechanism calls a factory each time a
+funcarg for a test function is required. If a factory wants to
+re-use a resource across different scopes, it often used
+the ``request.cached_setup()`` helper to manage caching of
+resources. Here is a basic example how we could implement
+a per-session Database object::
+
+ # content of conftest.py
+ class Database(object):
+ def __init__(self):
+ print ("database instance created")
+ def destroy(self):
+ print ("database instance destroyed")
+
+ def pytest_funcarg__db(request):
+ return request.cached_setup(setup=DataBase,
+ teardown=lambda db: db.destroy,
+ scope="session")
+
+There are several limitations and difficulties with this approach:
+
+1. Scoping funcarg resource creation is not straight forward, instead one must
+ understand the intricate cached_setup() method mechanics.
+
+2. parametrizing the "db" resource is not straight forward:
+ you need to apply a "parametrize" decorator or implement a
+ :py:func:`~hookspec.pytest_generate_tests` hook
+ calling :py:func:`~python.Metafunc.parametrize` which
+ performs parametrization at the places where the resource
+ is used. Moreover, you need to modify the factory to use an
+ ``extrakey`` parameter containing ``request.param`` to the
+ :py:func:`~python.Request.cached_setup` call.
+
+3. Multiple parametrized session-scoped resources will be active
+ at the same time, making it hard for them to affect global state
+ of the application under test.
+
+4. there is no way how you can make use of funcarg factories
+ in xUnit setup methods.
+
+5. A non-parametrized fixture function cannot use a parametrized
+ funcarg resource if it isn't stated in the test function signature.
+
+All of these limitations are addressed with pytest-2.3 and its
+improved :ref:`fixture mechanism <fixture>`.
+
+
+Direct scoping of fixture/funcarg factories
+--------------------------------------------------------
+
+Instead of calling cached_setup() with a cache scope, you can use the
+:ref:`@pytest.fixture <pytest.fixture>` decorator and directly state
+the scope::
+
+ @pytest.fixture(scope="session")
+ def db(request):
+ # factory will only be invoked once per session -
+ db = DataBase()
+ request.addfinalizer(db.destroy) # destroy when session is finished
+ return db
+
+This factory implementation does not need to call ``cached_setup()`` anymore
+because it will only be invoked once per session. Moreover, the
+``request.addfinalizer()`` registers a finalizer according to the specified
+resource scope on which the factory function is operating.
+
+
+Direct parametrization of funcarg resource factories
+----------------------------------------------------------
+
+Previously, funcarg factories could not directly cause parametrization.
+You needed to specify a ``@parametrize`` decorator on your test function
+or implement a ``pytest_generate_tests`` hook to perform
+parametrization, i.e. calling a test multiple times with different value
+sets. pytest-2.3 introduces a decorator for use on the factory itself::
+
+ @pytest.fixture(params=["mysql", "pg"])
+ def db(request):
+ ... # use request.param
+
+Here the factory will be invoked twice (with the respective "mysql"
+and "pg" values set as ``request.param`` attributes) and all of
+the tests requiring "db" will run twice as well. The "mysql" and
+"pg" values will also be used for reporting the test-invocation variants.
+
+This new way of parametrizing funcarg factories should in many cases
+allow to re-use already written factories because effectively
+``request.param`` was already used when test functions/classes were
+parametrized via
+:py:func:`~_pytest.python.Metafunc.parametrize(indirect=True)` calls.
+
+Of course it's perfectly fine to combine parametrization and scoping::
+
+ @pytest.fixture(scope="session", params=["mysql", "pg"])
+ def db(request):
+ if request.param == "mysql":
+ db = MySQL()
+ elif request.param == "pg":
+ db = PG()
+ request.addfinalizer(db.destroy) # destroy when session is finished
+ return db
+
+This would execute all tests requiring the per-session "db" resource twice,
+receiving the values created by the two respective invocations to the
+factory function.
+
+
+No ``pytest_funcarg__`` prefix when using @fixture decorator
+-------------------------------------------------------------------
+
+When using the ``@fixture`` decorator the name of the function
+denotes the name under which the resource can be accessed as a function
+argument::
+
+ @pytest.fixture()
+ def db(request):
+ ...
+
+The name under which the funcarg resource can be requested is ``db``.
+
+You can still use the "old" non-decorator way of specifying funcarg factories
+aka::
+
+ def pytest_funcarg__db(request):
+ ...
+
+
+But it is then not possible to define scoping and parametrization.
+It is thus recommended to use the factory decorator.
+
+
+solving per-session setup / autouse fixtures
+--------------------------------------------------------------
+
+pytest for a long time offered a pytest_configure and a pytest_sessionstart
+hook which are often used to setup global resources. This suffers from
+several problems:
+
+1. in distributed testing the master process would setup test resources
+ that are never needed because it only co-ordinates the test run
+ activities of the slave processes.
+
+2. if you only perform a collection (with "--collect-only")
+ resource-setup will still be executed.
+
+3. If a pytest_sessionstart is contained in some subdirectories
+ conftest.py file, it will not be called. This stems from the
+ fact that this hook is actually used for reporting, in particular
+ the test-header with platform/custom information.
+
+Moreover, it was not easy to define a scoped setup from plugins or
+conftest files other than to implement a ``pytest_runtest_setup()`` hook
+and caring for scoping/caching yourself. And it's virtually impossible
+to do this with parametrization as ``pytest_runtest_setup()`` is called
+during test execution and parametrization happens at collection time.
+
+It follows that pytest_configure/session/runtest_setup are often not
+appropriate for implementing common fixture needs. Therefore,
+pytest-2.3 introduces :ref:`autouse fixtures` which fully
+integrate with the generic :ref:`fixture mechanism <fixture>`
+and obsolete many prior uses of pytest hooks.
+
+funcargs/fixture discovery now happens at collection time
+---------------------------------------------------------------------
+
+Since pytest-2.3, discovery of fixture/funcarg factories are taken care of
+at collection time. This is more efficient especially for large test suites.
+Moreover, a call to "pytest --collect-only" should be able to in the future
+show a lot of setup-information and thus presents a nice method to get an
+overview of fixture management in your project.
+
+.. _`compatibility notes`:
+
+.. _`funcargscompat`:
+
+Conclusion and compatibility notes
+---------------------------------------------------------
+
+**funcargs** were originally introduced to pytest-2.0. In pytest-2.3
+the mechanism was extended and refined and is now described as
+fixtures:
+
+* previously funcarg factories were specified with a special
+ ``pytest_funcarg__NAME`` prefix instead of using the
+ ``@pytest.fixture`` decorator.
+
+* Factories received a ``request`` object which managed caching through
+ ``request.cached_setup()`` calls and allowed using other funcargs via
+ ``request.getfuncargvalue()`` calls. These intricate APIs made it hard
+ to do proper parametrization and implement resource caching. The
+ new :py:func:`pytest.fixture` decorator allows to declare the scope
+ and let pytest figure things out for you.
+
+* if you used parametrization and funcarg factories which made use of
+ ``request.cached_setup()`` it is recommended to invest a few minutes
+ and simplify your fixture function code to use the :ref:`@pytest.fixture`
+ decorator instead. This will also allow to take advantage of
+ the automatic per-resource grouping of tests.
+
+
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/funcargs.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/funcargs.rst
index bc2c0430239..bc2c0430239 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/funcargs.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/funcargs.rst
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/genapi.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/genapi.py
new file mode 100644
index 00000000000..0ede44fa2de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/genapi.py
@@ -0,0 +1,41 @@
+import textwrap
+import inspect
+
+class Writer(object):
+ def __init__(self, clsname):
+ self.clsname = clsname
+
+ def __enter__(self):
+ self.file = open("%s.api" % self.clsname, "w")
+ return self
+
+ def __exit__(self, *args):
+ self.file.close()
+ print "wrote", self.file.name
+
+ def line(self, line):
+ self.file.write(line+"\n")
+
+ def docmethod(self, method):
+ doc = " ".join(method.__doc__.split())
+ indent = " "
+ w = textwrap.TextWrapper(initial_indent=indent,
+ subsequent_indent=indent)
+
+ spec = inspect.getargspec(method)
+ del spec.args[0]
+ self.line(".. py:method:: " + method.__name__ +
+ inspect.formatargspec(*spec))
+ self.line("")
+ self.line(w.fill(doc))
+ self.line("")
+
+def pytest_funcarg__a(request):
+ with Writer("request") as writer:
+ writer.docmethod(request.getfixturevalue)
+ writer.docmethod(request.cached_setup)
+ writer.docmethod(request.addfinalizer)
+ writer.docmethod(request.applymarker)
+
+def test_hello(a):
+ pass
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/getting-started.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/getting-started.rst
new file mode 100644
index 00000000000..64b0108262d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/getting-started.rst
@@ -0,0 +1,198 @@
+Installation and Getting Started
+===================================
+
+**Pythons**: Python 2.7, 3.4, 3.5, 3.6, Jython, PyPy-2.3
+
+**Platforms**: Unix/Posix and Windows
+
+**PyPI package name**: `pytest <http://pypi.python.org/pypi/pytest>`_
+
+**dependencies**: `py <http://pypi.python.org/pypi/py>`_,
+`colorama (Windows) <http://pypi.python.org/pypi/colorama>`_,
+
+**documentation as PDF**: `download latest <https://media.readthedocs.org/pdf/pytest/latest/pytest.pdf>`_
+
+.. _`getstarted`:
+.. _installation:
+
+Installation
+----------------------------------------
+
+Installation::
+
+ pip install -U pytest
+
+To check your installation has installed the correct version::
+
+ $ pytest --version
+ This is pytest version 3.x.y, imported from $PYTHON_PREFIX/lib/python3.5/site-packages/pytest.py
+
+.. _`simpletest`:
+
+Our first test run
+----------------------------------------------------------
+
+Let's create a first test file with a simple test function::
+
+ # content of test_sample.py
+ def func(x):
+ return x + 1
+
+ def test_answer():
+ assert func(3) == 5
+
+That's it. You can execute the test function now::
+
+ $ pytest
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 1 item
+
+ test_sample.py F [100%]
+
+ ================================= FAILURES =================================
+ _______________________________ test_answer ________________________________
+
+ def test_answer():
+ > assert func(3) == 5
+ E assert 4 == 5
+ E + where 4 = func(3)
+
+ test_sample.py:5: AssertionError
+ ========================= 1 failed in 0.12 seconds =========================
+
+We got a failure report because our little ``func(3)`` call did not return ``5``.
+
+.. note::
+
+ You can simply use the ``assert`` statement for asserting test
+ expectations. pytest's :ref:`assert introspection` will intelligently
+ report intermediate values of the assert expression freeing
+ you from the need to learn the many names of `JUnit legacy methods`_.
+
+.. _`JUnit legacy methods`: http://docs.python.org/library/unittest.html#test-cases
+
+.. _`assert statement`: http://docs.python.org/reference/simple_stmts.html#the-assert-statement
+
+Running multiple tests
+----------------------------------------------------------
+
+``pytest`` will run all files in the current directory and its subdirectories of the form test_*.py or \*_test.py. More generally, it follows :ref:`standard test discovery rules <test discovery>`.
+
+
+Asserting that a certain exception is raised
+--------------------------------------------------------------
+
+If you want to assert that some code raises an exception you can
+use the ``raises`` helper::
+
+ # content of test_sysexit.py
+ import pytest
+ def f():
+ raise SystemExit(1)
+
+ def test_mytest():
+ with pytest.raises(SystemExit):
+ f()
+
+Running it with, this time in "quiet" reporting mode::
+
+ $ pytest -q test_sysexit.py
+ . [100%]
+ 1 passed in 0.12 seconds
+
+Grouping multiple tests in a class
+--------------------------------------------------------------
+
+Once you start to have more than a few tests it often makes sense
+to group tests logically, in classes and modules. Let's write a class
+containing two tests::
+
+ # content of test_class.py
+ class TestClass(object):
+ def test_one(self):
+ x = "this"
+ assert 'h' in x
+
+ def test_two(self):
+ x = "hello"
+ assert hasattr(x, 'check')
+
+The two tests are found because of the standard :ref:`test discovery`.
+There is no need to subclass anything. We can simply
+run the module by passing its filename::
+
+ $ pytest -q test_class.py
+ .F [100%]
+ ================================= FAILURES =================================
+ ____________________________ TestClass.test_two ____________________________
+
+ self = <test_class.TestClass object at 0xdeadbeef>
+
+ def test_two(self):
+ x = "hello"
+ > assert hasattr(x, 'check')
+ E AssertionError: assert False
+ E + where False = hasattr('hello', 'check')
+
+ test_class.py:8: AssertionError
+ 1 failed, 1 passed in 0.12 seconds
+
+The first test passed, the second failed. Again we can easily see
+the intermediate values used in the assertion, helping us to
+understand the reason for the failure.
+
+Going functional: requesting a unique temporary directory
+--------------------------------------------------------------
+
+For functional tests one often needs to create some files
+and pass them to application objects. pytest provides
+:ref:`builtinfixtures` which allow to request arbitrary
+resources, for example a unique temporary directory::
+
+ # content of test_tmpdir.py
+ def test_needsfiles(tmpdir):
+ print (tmpdir)
+ assert 0
+
+We list the name ``tmpdir`` in the test function signature and
+``pytest`` will lookup and call a fixture factory to create the resource
+before performing the test function call. Let's just run it::
+
+ $ pytest -q test_tmpdir.py
+ F [100%]
+ ================================= FAILURES =================================
+ _____________________________ test_needsfiles ______________________________
+
+ tmpdir = local('PYTEST_TMPDIR/test_needsfiles0')
+
+ def test_needsfiles(tmpdir):
+ print (tmpdir)
+ > assert 0
+ E assert 0
+
+ test_tmpdir.py:3: AssertionError
+ --------------------------- Captured stdout call ---------------------------
+ PYTEST_TMPDIR/test_needsfiles0
+ 1 failed in 0.12 seconds
+
+Before the test runs, a unique-per-test-invocation temporary directory
+was created. More info at :ref:`tmpdir handling`.
+
+You can find out what kind of builtin :ref:`fixtures` exist by typing::
+
+ pytest --fixtures # shows builtin and custom fixtures
+
+Where to go next
+-------------------------------------
+
+Here are a few suggestions where to go next:
+
+* :ref:`cmdline` for command line invocation examples
+* :ref:`good practices <goodpractices>` for virtualenv, test layout
+* :ref:`existingtestsuite` for working with pre-existing tests
+* :ref:`fixtures` for providing a functional baseline to your tests
+* :ref:`plugins` managing and writing plugins
+
+.. include:: links.inc
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/goodpractices.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/goodpractices.rst
new file mode 100644
index 00000000000..16fdd24c392
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/goodpractices.rst
@@ -0,0 +1,299 @@
+.. highlightlang:: python
+.. _`goodpractices`:
+
+Good Integration Practices
+=================================================
+
+
+.. _`test discovery`:
+.. _`Python test discovery`:
+
+Conventions for Python test discovery
+-------------------------------------------------
+
+``pytest`` implements the following standard test discovery:
+
+* If no arguments are specified then collection starts from :confval:`testpaths`
+ (if configured) or the current directory. Alternatively, command line arguments
+ can be used in any combination of directories, file names or node ids.
+* Recurse into directories, unless they match :confval:`norecursedirs`.
+* In those directories, search for ``test_*.py`` or ``*_test.py`` files, imported by their `test package name`_.
+* From those files, collect test items:
+
+ * ``test_`` prefixed test functions or methods outside of class
+ * ``test_`` prefixed test functions or methods inside ``Test`` prefixed test classes (without an ``__init__`` method)
+
+For examples of how to customize your test discovery :doc:`example/pythoncollection`.
+
+Within Python modules, ``pytest`` also discovers tests using the standard
+:ref:`unittest.TestCase <unittest.TestCase>` subclassing technique.
+
+
+Choosing a test layout / import rules
+-------------------------------------
+
+``pytest`` supports two common test layouts:
+
+Tests outside application code
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Putting tests into an extra directory outside your actual application code
+might be useful if you have many functional tests or for other reasons want
+to keep tests separate from actual application code (often a good idea)::
+
+ setup.py
+ mypkg/
+ __init__.py
+ app.py
+ view.py
+ tests/
+ test_app.py
+ test_view.py
+ ...
+
+This way your tests can run easily against an installed version
+of ``mypkg``.
+
+Note that using this scheme your test files must have **unique names**, because
+``pytest`` will import them as *top-level* modules since there are no packages
+to derive a full package name from. In other words, the test files in the example above will
+be imported as ``test_app`` and ``test_view`` top-level modules by adding ``tests/`` to
+``sys.path``.
+
+If you need to have test modules with the same name, you might add ``__init__.py`` files to your
+``tests`` folder and subfolders, changing them to packages::
+
+ setup.py
+ mypkg/
+ ...
+ tests/
+ __init__.py
+ foo/
+ __init__.py
+ test_view.py
+ bar/
+ __init__.py
+ test_view.py
+
+Now pytest will load the modules as ``tests.foo.test_view`` and ``tests.bar.test_view``, allowing
+you to have modules with the same name. But now this introduces a subtle problem: in order to load
+the test modules from the ``tests`` directory, pytest prepends the root of the repository to
+``sys.path``, which adds the side-effect that now ``mypkg`` is also importable.
+This is problematic if you are using a tool like `tox`_ to test your package in a virtual environment,
+because you want to test the *installed* version of your package, not the local code from the repository.
+
+In this situation, it is **strongly** suggested to use a ``src`` layout where application root package resides in a
+sub-directory of your root::
+
+ setup.py
+ src/
+ mypkg/
+ __init__.py
+ app.py
+ view.py
+ tests/
+ __init__.py
+ foo/
+ __init__.py
+ test_view.py
+ bar/
+ __init__.py
+ test_view.py
+
+
+This layout prevents a lot of common pitfalls and has many benefits, which are better explained in this excellent
+`blog post by Ionel Cristian Mărieș <https://blog.ionelmc.ro/2014/05/25/python-packaging/#the-structure>`_.
+
+Tests as part of application code
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Inlining test directories into your application package
+is useful if you have direct relation between tests and application modules and
+want to distribute them along with your application::
+
+ setup.py
+ mypkg/
+ __init__.py
+ app.py
+ view.py
+ test/
+ __init__.py
+ test_app.py
+ test_view.py
+ ...
+
+In this scheme, it is easy to run your tests using the ``--pyargs`` option::
+
+ pytest --pyargs mypkg
+
+``pytest`` will discover where ``mypkg`` is installed and collect tests from there.
+
+Note that this layout also works in conjunction with the ``src`` layout mentioned in the previous section.
+
+
+.. note::
+
+ You can use Python3 namespace packages (PEP420) for your application
+ but pytest will still perform `test package name`_ discovery based on the
+ presence of ``__init__.py`` files. If you use one of the
+ two recommended file system layouts above but leave away the ``__init__.py``
+ files from your directories it should just work on Python3.3 and above. From
+ "inlined tests", however, you will need to use absolute imports for
+ getting at your application code.
+
+.. _`test package name`:
+
+.. note::
+
+ If ``pytest`` finds a "a/b/test_module.py" test file while
+ recursing into the filesystem it determines the import name
+ as follows:
+
+ * determine ``basedir``: this is the first "upward" (towards the root)
+ directory not containing an ``__init__.py``. If e.g. both ``a``
+ and ``b`` contain an ``__init__.py`` file then the parent directory
+ of ``a`` will become the ``basedir``.
+
+ * perform ``sys.path.insert(0, basedir)`` to make the test module
+ importable under the fully qualified import name.
+
+ * ``import a.b.test_module`` where the path is determined
+ by converting path separators ``/`` into "." characters. This means
+ you must follow the convention of having directory and file
+ names map directly to the import names.
+
+ The reason for this somewhat evolved importing technique is
+ that in larger projects multiple test modules might import
+ from each other and thus deriving a canonical import name helps
+ to avoid surprises such as a test module getting imported twice.
+
+
+.. _`virtualenv`: http://pypi.python.org/pypi/virtualenv
+.. _`buildout`: http://www.buildout.org/
+.. _pip: http://pypi.python.org/pypi/pip
+
+.. _`use tox`:
+
+Tox
+------
+
+For development, we recommend to use virtualenv_ environments and pip_
+for installing your application and any dependencies
+as well as the ``pytest`` package itself. This ensures your code and
+dependencies are isolated from the system Python installation.
+
+You can then install your package in "editable" mode::
+
+ pip install -e .
+
+which lets you change your source code (both tests and application) and rerun tests at will.
+This is similar to running `python setup.py develop` or `conda develop` in that it installs
+your package using a symlink to your development code.
+
+Once you are done with your work and want to make sure that your actual
+package passes all tests you may want to look into `tox`_, the
+virtualenv test automation tool and its `pytest support
+<https://tox.readthedocs.io/en/latest/example/pytest.html>`_.
+Tox helps you to setup virtualenv environments with pre-defined
+dependencies and then executing a pre-configured test command with
+options. It will run tests against the installed package and not
+against your source code checkout, helping to detect packaging
+glitches.
+
+
+Integrating with setuptools / ``python setup.py test`` / ``pytest-runner``
+--------------------------------------------------------------------------
+
+You can integrate test runs into your setuptools based project
+with the `pytest-runner <https://pypi.python.org/pypi/pytest-runner>`_ plugin.
+
+Add this to ``setup.py`` file:
+
+.. code-block:: python
+
+ from setuptools import setup
+
+ setup(
+ #...,
+ setup_requires=['pytest-runner', ...],
+ tests_require=['pytest', ...],
+ #...,
+ )
+
+
+And create an alias into ``setup.cfg`` file:
+
+
+.. code-block:: ini
+
+ [aliases]
+ test=pytest
+
+If you now type::
+
+ python setup.py test
+
+this will execute your tests using ``pytest-runner``. As this is a
+standalone version of ``pytest`` no prior installation whatsoever is
+required for calling the test command. You can also pass additional
+arguments to pytest such as your test directory or other
+options using ``--addopts``.
+
+You can also specify other pytest-ini options in your ``setup.cfg`` file
+by putting them into a ``[tool:pytest]`` section:
+
+.. code-block:: ini
+
+ [tool:pytest]
+ addopts = --verbose
+ python_files = testing/*/*.py
+
+
+Manual Integration
+^^^^^^^^^^^^^^^^^^
+
+If for some reason you don't want/can't use ``pytest-runner``, you can write
+your own setuptools Test command for invoking pytest.
+
+.. code-block:: python
+
+ import sys
+
+ from setuptools.command.test import test as TestCommand
+
+
+ class PyTest(TestCommand):
+ user_options = [('pytest-args=', 'a', "Arguments to pass to pytest")]
+
+ def initialize_options(self):
+ TestCommand.initialize_options(self)
+ self.pytest_args = ''
+
+ def run_tests(self):
+ import shlex
+ #import here, cause outside the eggs aren't loaded
+ import pytest
+ errno = pytest.main(shlex.split(self.pytest_args))
+ sys.exit(errno)
+
+
+ setup(
+ #...,
+ tests_require=['pytest'],
+ cmdclass = {'test': PyTest},
+ )
+
+Now if you run::
+
+ python setup.py test
+
+this will download ``pytest`` if needed and then run your tests
+as you would expect it to. You can pass a single string of arguments
+using the ``--pytest-args`` or ``-a`` command-line option. For example::
+
+ python setup.py test -a "--durations=5"
+
+is equivalent to running ``pytest --durations=5``.
+
+
+.. include:: links.inc
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/historical-notes.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/historical-notes.rst
new file mode 100644
index 00000000000..028ceff9b17
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/historical-notes.rst
@@ -0,0 +1,177 @@
+Historical Notes
+================
+
+This page lists features or behavior from previous versions of pytest which have changed over the years. They are
+kept here as a historical note so users looking at old code can find documentation related to them.
+
+cache plugin integrated into the core
+-------------------------------------
+
+.. versionadded:: 2.8
+
+The functionality of the :ref:`core cache <cache>` plugin was previously distributed
+as a third party plugin named ``pytest-cache``. The core plugin
+is compatible regarding command line options and API usage except that you
+can only store/receive data between test runs that is json-serializable.
+
+
+funcargs and ``pytest_funcarg__``
+---------------------------------
+
+.. versionchanged:: 2.3
+
+In versions prior to 2.3 there was no ``@pytest.fixture`` marker
+and you had to use a magic ``pytest_funcarg__NAME`` prefix
+for the fixture factory. This remains and will remain supported
+but is not anymore advertised as the primary means of declaring fixture
+functions.
+
+
+``@pytest.yield_fixture`` decorator
+-----------------------------------
+
+.. versionchanged:: 2.10
+
+Prior to version 2.10, in order to use a ``yield`` statement to execute teardown code one
+had to mark a fixture using the ``yield_fixture`` marker. From 2.10 onward, normal
+fixtures can use ``yield`` directly so the ``yield_fixture`` decorator is no longer needed
+and considered deprecated.
+
+
+``[pytest]`` header in ``setup.cfg``
+------------------------------------
+
+.. versionchanged:: 3.0
+
+Prior to 3.0, the supported section name was ``[pytest]``. Due to how
+this may collide with some distutils commands, the recommended
+section name for ``setup.cfg`` files is now ``[tool:pytest]``.
+
+Note that for ``pytest.ini`` and ``tox.ini`` files the section
+name is ``[pytest]``.
+
+
+Applying marks to ``@pytest.mark.parametrize`` parameters
+---------------------------------------------------------
+
+.. versionchanged:: 3.1
+
+Prior to version 3.1 the supported mechanism for marking values
+used the syntax::
+
+ import pytest
+ @pytest.mark.parametrize("test_input,expected", [
+ ("3+5", 8),
+ ("2+4", 6),
+ pytest.mark.xfail(("6*9", 42),),
+ ])
+ def test_eval(test_input, expected):
+ assert eval(test_input) == expected
+
+
+This was an initial hack to support the feature but soon was demonstrated to be incomplete,
+broken for passing functions or applying multiple marks with the same name but different parameters.
+
+The old syntax is planned to be removed in pytest-4.0.
+
+
+``@pytest.mark.parametrize`` argument names as a tuple
+------------------------------------------------------
+
+.. versionchanged:: 2.4
+
+In versions prior to 2.4 one needed to specify the argument
+names as a tuple. This remains valid but the simpler ``"name1,name2,..."``
+comma-separated-string syntax is now advertised first because
+it's easier to write and produces less line noise.
+
+
+setup: is now an "autouse fixture"
+----------------------------------
+
+.. versionchanged:: 2.3
+
+During development prior to the pytest-2.3 release the name
+``pytest.setup`` was used but before the release it was renamed
+and moved to become part of the general fixture mechanism,
+namely :ref:`autouse fixtures`
+
+
+.. _string conditions:
+
+Conditions as strings instead of booleans
+-----------------------------------------
+
+.. versionchanged:: 2.4
+
+Prior to pytest-2.4 the only way to specify skipif/xfail conditions was
+to use strings::
+
+ import sys
+ @pytest.mark.skipif("sys.version_info >= (3,3)")
+ def test_function():
+ ...
+
+During test function setup the skipif condition is evaluated by calling
+``eval('sys.version_info >= (3,0)', namespace)``. The namespace contains
+all the module globals, and ``os`` and ``sys`` as a minimum.
+
+Since pytest-2.4 :ref:`boolean conditions <condition booleans>` are considered preferable
+because markers can then be freely imported between test modules.
+With strings you need to import not only the marker but all variables
+used by the marker, which violates encapsulation.
+
+The reason for specifying the condition as a string was that ``pytest`` can
+report a summary of skip conditions based purely on the condition string.
+With conditions as booleans you are required to specify a ``reason`` string.
+
+Note that string conditions will remain fully supported and you are free
+to use them if you have no need for cross-importing markers.
+
+The evaluation of a condition string in ``pytest.mark.skipif(conditionstring)``
+or ``pytest.mark.xfail(conditionstring)`` takes place in a namespace
+dictionary which is constructed as follows:
+
+* the namespace is initialized by putting the ``sys`` and ``os`` modules
+ and the pytest ``config`` object into it.
+
+* updated with the module globals of the test function for which the
+ expression is applied.
+
+The pytest ``config`` object allows you to skip based on a test
+configuration value which you might have added::
+
+ @pytest.mark.skipif("not config.getvalue('db')")
+ def test_function(...):
+ ...
+
+The equivalent with "boolean conditions" is::
+
+ @pytest.mark.skipif(not pytest.config.getvalue("db"),
+ reason="--db was not specified")
+ def test_function(...):
+ pass
+
+.. note::
+
+ You cannot use ``pytest.config.getvalue()`` in code
+ imported before pytest's argument parsing takes place. For example,
+ ``conftest.py`` files are imported before command line parsing and thus
+ ``config.getvalue()`` will not execute correctly.
+
+``pytest.set_trace()``
+----------------------
+
+.. versionchanged:: 2.4
+
+Previous to version 2.4 to set a break point in code one needed to use ``pytest.set_trace()``::
+
+ import pytest
+ def test_function():
+ ...
+ pytest.set_trace() # invoke PDB debugger and tracing
+
+
+This is no longer needed and one can use the native ``import pdb;pdb.set_trace()`` call directly.
+
+For more details see :ref:`breakpoints`.
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/img/cramer2.png b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/cramer2.png
index 6bf0e92e20d..6bf0e92e20d 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/img/cramer2.png
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/cramer2.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/img/freiburg2.jpg b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/freiburg2.jpg
index 3383d3023da..3383d3023da 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/img/freiburg2.jpg
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/freiburg2.jpg
Binary files differ
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/img/gaynor3.png b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/gaynor3.png
index a577c168b39..a577c168b39 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/img/gaynor3.png
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/gaynor3.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/img/keleshev.png b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/keleshev.png
index 0d5e571e261..0d5e571e261 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/img/keleshev.png
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/keleshev.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/img/pullrequest.png b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/pullrequest.png
index 4af293b2137..4af293b2137 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/img/pullrequest.png
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/pullrequest.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/img/pylib.png b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/pylib.png
index 2e10d438866..2e10d438866 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/img/pylib.png
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/pylib.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/img/pytest1.png b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/pytest1.png
index e8064a694ca..e8064a694ca 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/img/pytest1.png
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/pytest1.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/img/pytest1favi.ico b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/pytest1favi.ico
index 6a34fe5c9f7..6a34fe5c9f7 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/img/pytest1favi.ico
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/pytest1favi.ico
Binary files differ
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/img/theuni.png b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/theuni.png
index abeb737e79b..abeb737e79b 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/img/theuni.png
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/img/theuni.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/index.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/index.rst
new file mode 100644
index 00000000000..66c59f08d34
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/index.rst
@@ -0,0 +1,90 @@
+:orphan:
+
+.. _features:
+
+pytest: helps you write better programs
+=======================================
+
+
+The ``pytest`` framework makes it easy to write small tests, yet
+scales to support complex functional testing for applications and libraries.
+
+An example of a simple test:
+
+.. code-block:: python
+
+ # content of test_sample.py
+ def inc(x):
+ return x + 1
+
+ def test_answer():
+ assert inc(3) == 5
+
+
+To execute it::
+
+ $ pytest
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 1 item
+
+ test_sample.py F [100%]
+
+ ================================= FAILURES =================================
+ _______________________________ test_answer ________________________________
+
+ def test_answer():
+ > assert inc(3) == 5
+ E assert 4 == 5
+ E + where 4 = inc(3)
+
+ test_sample.py:5: AssertionError
+ ========================= 1 failed in 0.12 seconds =========================
+
+Due to ``pytest``'s detailed assertion introspection, only plain ``assert`` statements are used.
+See :ref:`Getting Started <getstarted>` for more examples.
+
+
+Features
+--------
+
+- Detailed info on failing :ref:`assert statements <assert>` (no need to remember ``self.assert*`` names);
+
+- :ref:`Auto-discovery <test discovery>` of test modules and functions;
+
+- :ref:`Modular fixtures <fixture>` for managing small or parametrized long-lived test resources;
+
+- Can run :ref:`unittest <unittest>` (including trial) and :ref:`nose <noseintegration>` test suites out of the box;
+
+- Python 2.7, Python 3.4+, PyPy 2.3, Jython 2.5 (untested);
+
+- Rich plugin architecture, with over 315+ `external plugins <http://plugincompat.herokuapp.com>`_ and thriving community;
+
+
+Documentation
+-------------
+
+Please see :ref:`Contents <toc>` for full documentation, including installation, tutorials and PDF documents.
+
+
+Bugs/Requests
+-------------
+
+Please use the `GitHub issue tracker <https://github.com/pytest-dev/pytest/issues>`_ to submit bugs or request features.
+
+
+Changelog
+---------
+
+Consult the :ref:`Changelog <changelog>` page for fixes and enhancements of each version.
+
+
+License
+-------
+
+Copyright Holger Krekel and others, 2004-2017.
+
+Distributed under the terms of the `MIT`_ license, pytest is free and open source software.
+
+.. _`MIT`: https://github.com/pytest-dev/pytest/blob/master/LICENSE
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/license.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/license.rst
new file mode 100644
index 00000000000..b8c0dce1bea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/license.rst
@@ -0,0 +1,32 @@
+.. _license:
+
+License
+-------
+
+Distributed under the terms of the `MIT`_ license, pytest is free and open source software.
+
+::
+
+ The MIT License (MIT)
+
+ Copyright (c) 2004-2017 Holger Krekel and others
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
+ this software and associated documentation files (the "Software"), to deal in
+ the Software without restriction, including without limitation the rights to
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is furnished to do
+ so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+
+.. _`MIT`: https://github.com/pytest-dev/pytest/blob/master/LICENSE
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/links.inc b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/links.inc
new file mode 100644
index 00000000000..b69390baa84
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/links.inc
@@ -0,0 +1,21 @@
+
+.. _`skipping plugin`: plugin/skipping.html
+.. _`funcargs mechanism`: funcargs.html
+.. _`doctest.py`: http://docs.python.org/library/doctest.html
+.. _`xUnit style setup`: xunit_setup.html
+.. _`pytest_nose`: plugin/nose.html
+.. _`reStructured Text`: http://docutils.sourceforge.net
+.. _`Python debugger`: http://docs.python.org/lib/module-pdb.html
+.. _nose: https://nose.readthedocs.io/en/latest/
+.. _pytest: http://pypi.python.org/pypi/pytest
+.. _mercurial: http://mercurial.selenic.com/wiki/
+.. _`setuptools`: http://pypi.python.org/pypi/setuptools
+.. _`easy_install`:
+.. _`distribute docs`:
+.. _`distribute`: http://pypi.python.org/pypi/distribute
+.. _`pip`: http://pypi.python.org/pypi/pip
+.. _`virtualenv`: http://pypi.python.org/pypi/virtualenv
+.. _hudson: http://hudson-ci.org/
+.. _jenkins: http://jenkins-ci.org/
+.. _tox: http://testrun.org/tox
+.. _pylib: https://py.readthedocs.io/en/latest/
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/logging.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/logging.rst
new file mode 100644
index 00000000000..e3bf5603887
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/logging.rst
@@ -0,0 +1,192 @@
+.. _logging:
+
+Logging
+-------
+
+.. versionadded 3.3.0
+
+.. note::
+
+ This feature is a drop-in replacement for the `pytest-catchlog
+ <https://pypi.org/project/pytest-catchlog/>`_ plugin and they will conflict
+ with each other. The backward compatibility API with ``pytest-capturelog``
+ has been dropped when this feature was introduced, so if for that reason you
+ still need ``pytest-catchlog`` you can disable the internal feature by
+ adding to your ``pytest.ini``:
+
+ .. code-block:: ini
+
+ [pytest]
+ addopts=-p no:logging
+
+Log messages are captured by default and for each failed test will be shown in
+the same manner as captured stdout and stderr.
+
+Running without options::
+
+ pytest
+
+Shows failed tests like so::
+
+ ----------------------- Captured stdlog call ----------------------
+ test_reporting.py 26 INFO text going to logger
+ ----------------------- Captured stdout call ----------------------
+ text going to stdout
+ ----------------------- Captured stderr call ----------------------
+ text going to stderr
+ ==================== 2 failed in 0.02 seconds =====================
+
+By default each captured log message shows the module, line number, log level
+and message. Showing the exact module and line number is useful for testing and
+debugging. If desired the log format and date format can be specified to
+anything that the logging module supports.
+
+Running pytest specifying formatting options::
+
+ pytest --log-format="%(asctime)s %(levelname)s %(message)s" \
+ --log-date-format="%Y-%m-%d %H:%M:%S"
+
+Shows failed tests like so::
+
+ ----------------------- Captured stdlog call ----------------------
+ 2010-04-10 14:48:44 INFO text going to logger
+ ----------------------- Captured stdout call ----------------------
+ text going to stdout
+ ----------------------- Captured stderr call ----------------------
+ text going to stderr
+ ==================== 2 failed in 0.02 seconds =====================
+
+These options can also be customized through a configuration file:
+
+.. code-block:: ini
+
+ [pytest]
+ log_format = %(asctime)s %(levelname)s %(message)s
+ log_date_format = %Y-%m-%d %H:%M:%S
+
+Further it is possible to disable reporting logs on failed tests completely
+with::
+
+ pytest --no-print-logs
+
+Or in you ``pytest.ini``:
+
+.. code-block:: ini
+
+ [pytest]
+ log_print = False
+
+
+Shows failed tests in the normal manner as no logs were captured::
+
+ ----------------------- Captured stdout call ----------------------
+ text going to stdout
+ ----------------------- Captured stderr call ----------------------
+ text going to stderr
+ ==================== 2 failed in 0.02 seconds =====================
+
+Inside tests it is possible to change the log level for the captured log
+messages. This is supported by the ``caplog`` fixture::
+
+ def test_foo(caplog):
+ caplog.set_level(logging.INFO)
+ pass
+
+By default the level is set on the handler used to catch the log messages,
+however as a convenience it is also possible to set the log level of any
+logger::
+
+ def test_foo(caplog):
+ caplog.set_level(logging.CRITICAL, logger='root.baz')
+ pass
+
+It is also possible to use a context manager to temporarily change the log
+level::
+
+ def test_bar(caplog):
+ with caplog.at_level(logging.INFO):
+ pass
+
+Again, by default the level of the handler is affected but the level of any
+logger can be changed instead with::
+
+ def test_bar(caplog):
+ with caplog.at_level(logging.CRITICAL, logger='root.baz'):
+ pass
+
+Lastly all the logs sent to the logger during the test run are made available on
+the fixture in the form of both the LogRecord instances and the final log text.
+This is useful for when you want to assert on the contents of a message::
+
+ def test_baz(caplog):
+ func_under_test()
+ for record in caplog.records:
+ assert record.levelname != 'CRITICAL'
+ assert 'wally' not in caplog.text
+
+For all the available attributes of the log records see the
+``logging.LogRecord`` class.
+
+You can also resort to ``record_tuples`` if all you want to do is to ensure,
+that certain messages have been logged under a given logger name with a given
+severity and message::
+
+ def test_foo(caplog):
+ logging.getLogger().info('boo %s', 'arg')
+
+ assert caplog.record_tuples == [
+ ('root', logging.INFO, 'boo arg'),
+ ]
+
+You can call ``caplog.clear()`` to reset the captured log records in a test::
+
+ def test_something_with_clearing_records(caplog):
+ some_method_that_creates_log_records()
+ caplog.clear()
+ your_test_method()
+ assert ['Foo'] == [rec.message for rec in caplog.records]
+
+Live Logs
+^^^^^^^^^
+
+By default, pytest will output any logging records with a level higher or
+equal to WARNING. In order to actually see these logs in the console you have to
+disable pytest output capture by passing ``-s``.
+
+You can specify the logging level for which log records with equal or higher
+level are printed to the console by passing ``--log-cli-level``. This setting
+accepts the logging level names as seen in python's documentation or an integer
+as the logging level num.
+
+Additionally, you can also specify ``--log-cli-format`` and
+``--log-cli-date-format`` which mirror and default to ``--log-format`` and
+``--log-date-format`` if not provided, but are applied only to the console
+logging handler.
+
+All of the CLI log options can also be set in the configuration INI file. The
+option names are:
+
+* ``log_cli_level``
+* ``log_cli_format``
+* ``log_cli_date_format``
+
+If you need to record the whole test suite logging calls to a file, you can pass
+``--log-file=/path/to/log/file``. This log file is opened in write mode which
+means that it will be overwritten at each run tests session.
+
+You can also specify the logging level for the log file by passing
+``--log-file-level``. This setting accepts the logging level names as seen in
+python's documentation(ie, uppercased level names) or an integer as the logging
+level num.
+
+Additionally, you can also specify ``--log-file-format`` and
+``--log-file-date-format`` which are equal to ``--log-format`` and
+``--log-date-format`` but are applied to the log file logging handler.
+
+All of the log file options can also be set in the configuration INI file. The
+option names are:
+
+* ``log_file``
+* ``log_file_level``
+* ``log_file_format``
+* ``log_file_date_format``
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/mark.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/mark.rst
new file mode 100644
index 00000000000..0b0e072a09b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/mark.rst
@@ -0,0 +1,41 @@
+
+.. _mark:
+
+Marking test functions with attributes
+=================================================================
+
+.. currentmodule:: _pytest.mark
+
+By using the ``pytest.mark`` helper you can easily set
+metadata on your test functions. There are
+some builtin markers, for example:
+
+* :ref:`skip <skip>` - always skip a test function
+* :ref:`skipif <skipif>` - skip a test function if a certain condition is met
+* :ref:`xfail <xfail>` - produce an "expected failure" outcome if a certain
+ condition is met
+* :ref:`parametrize <parametrizemark>` to perform multiple calls
+ to the same test function.
+
+It's easy to create custom markers or to apply markers
+to whole test classes or modules. See :ref:`mark examples` for examples
+which also serve as documentation.
+
+.. note::
+
+ Marks can only be applied to tests, having no effect on
+ :ref:`fixtures <fixtures>`.
+
+
+API reference for mark related objects
+------------------------------------------------
+
+.. autoclass:: MarkGenerator
+ :members:
+
+.. autoclass:: MarkDecorator
+ :members:
+
+.. autoclass:: MarkInfo
+ :members:
+
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/monkeypatch.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/monkeypatch.rst
new file mode 100644
index 00000000000..0c07b2f44fc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/monkeypatch.rst
@@ -0,0 +1,75 @@
+
+Monkeypatching/mocking modules and environments
+================================================================
+
+.. currentmodule:: _pytest.monkeypatch
+
+Sometimes tests need to invoke functionality which depends
+on global settings or which invokes code which cannot be easily
+tested such as network access. The ``monkeypatch`` fixture
+helps you to safely set/delete an attribute, dictionary item or
+environment variable or to modify ``sys.path`` for importing.
+See the `monkeypatch blog post`_ for some introduction material
+and a discussion of its motivation.
+
+.. _`monkeypatch blog post`: http://tetamap.wordpress.com/2009/03/03/monkeypatching-in-unit-tests-done-right/
+
+
+Simple example: monkeypatching functions
+---------------------------------------------------
+
+If you want to pretend that ``os.expanduser`` returns a certain
+directory, you can use the :py:meth:`monkeypatch.setattr` method to
+patch this function before calling into a function which uses it::
+
+ # content of test_module.py
+ import os.path
+ def getssh(): # pseudo application code
+ return os.path.join(os.path.expanduser("~admin"), '.ssh')
+
+ def test_mytest(monkeypatch):
+ def mockreturn(path):
+ return '/abc'
+ monkeypatch.setattr(os.path, 'expanduser', mockreturn)
+ x = getssh()
+ assert x == '/abc/.ssh'
+
+Here our test function monkeypatches ``os.path.expanduser`` and
+then calls into a function that calls it. After the test function
+finishes the ``os.path.expanduser`` modification will be undone.
+
+example: preventing "requests" from remote operations
+------------------------------------------------------
+
+If you want to prevent the "requests" library from performing http
+requests in all your tests, you can do::
+
+ # content of conftest.py
+ import pytest
+ @pytest.fixture(autouse=True)
+ def no_requests(monkeypatch):
+ monkeypatch.delattr("requests.sessions.Session.request")
+
+This autouse fixture will be executed for each test function and it
+will delete the method ``request.session.Session.request``
+so that any attempts within tests to create http requests will fail.
+
+
+.. note::
+
+ Be advised that it is not recommended to patch builtin functions such as ``open``,
+ ``compile``, etc., because it might break pytest's internals. If that's
+ unavoidable, passing ``--tb=native``, ``--assert=plain`` and ``--capture=no`` might
+ help although there's no guarantee.
+
+
+Method reference of the monkeypatch fixture
+-------------------------------------------
+
+.. autoclass:: MonkeyPatch
+ :members:
+
+``monkeypatch.setattr/delattr/delitem/delenv()`` all
+by default raise an Exception if the target does not exist.
+Pass ``raising=False`` if you want to skip this check.
+
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/naming20.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/naming20.rst
index 5a81df2698d..5a81df2698d 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/naming20.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/naming20.rst
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/nose.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/nose.rst
new file mode 100644
index 00000000000..10a10633ab0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/nose.rst
@@ -0,0 +1,75 @@
+.. _`noseintegration`:
+
+Running tests written for nose
+=======================================
+
+.. include:: links.inc
+
+``pytest`` has basic support for running tests written for nose_.
+
+.. _nosestyle:
+
+Usage
+-------------
+
+After :ref:`installation` type::
+
+ python setup.py develop # make sure tests can import our package
+ pytest # instead of 'nosetests'
+
+and you should be able to run your nose style tests and
+make use of pytest's capabilities.
+
+Supported nose Idioms
+----------------------
+
+* setup and teardown at module/class/method level
+* SkipTest exceptions and markers
+* setup/teardown decorators
+* ``yield``-based tests and their setup (considered deprecated as of pytest 3.0)
+* ``__test__`` attribute on modules/classes/functions
+* general usage of nose utilities
+
+Unsupported idioms / known issues
+----------------------------------
+
+- unittest-style ``setUp, tearDown, setUpClass, tearDownClass``
+ are recognized only on ``unittest.TestCase`` classes but not
+ on plain classes. ``nose`` supports these methods also on plain
+ classes but pytest deliberately does not. As nose and pytest already
+ both support ``setup_class, teardown_class, setup_method, teardown_method``
+ it doesn't seem useful to duplicate the unittest-API like nose does.
+ If you however rather think pytest should support the unittest-spelling on
+ plain classes please post `to this issue
+ <https://github.com/pytest-dev/pytest/issues/377/>`_.
+
+- nose imports test modules with the same import path (e.g.
+ ``tests.test_mod``) but different file system paths
+ (e.g. ``tests/test_mode.py`` and ``other/tests/test_mode.py``)
+ by extending sys.path/import semantics. pytest does not do that
+ but there is discussion in `#268 <https://github.com/pytest-dev/pytest/issues/268>`_ for adding some support. Note that
+ `nose2 choose to avoid this sys.path/import hackery <https://nose2.readthedocs.io/en/latest/differences.html#test-discovery-and-loading>`_.
+
+ If you place a conftest.py file in the root directory of your project
+ (as determined by pytest) pytest will run tests "nose style" against
+ the code below that directory by adding it to your ``sys.path`` instead of
+ running against your installed code.
+
+ You may find yourself wanting to do this if you ran ``python setup.py install``
+ to set up your project, as opposed to ``python setup.py develop`` or any of
+ the package manager equivalents. Installing with develop in a
+ virtual environment like Tox is recommended over this pattern.
+
+- nose-style doctests are not collected and executed correctly,
+ also doctest fixtures don't work.
+
+- no nose-configuration is recognized.
+
+- ``yield``-based methods don't support ``setup`` properly because
+ the ``setup`` method is always called in the same class instance.
+ There are no plans to fix this currently because ``yield``-tests
+ are deprecated in pytest 3.0, with ``pytest.mark.parametrize``
+ being the recommended alternative.
+
+
+
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/parametrize.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/parametrize.rst
new file mode 100644
index 00000000000..7a4ac2e1877
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/parametrize.rst
@@ -0,0 +1,217 @@
+
+.. _`test generators`:
+.. _`parametrizing-tests`:
+.. _`parametrized test functions`:
+.. _`parametrize`:
+
+.. _`parametrize-basics`:
+
+Parametrizing fixtures and test functions
+==========================================================================
+
+pytest enables test parametrization at several levels:
+
+- :py:func:`pytest.fixture` allows one to :ref:`parametrize fixture
+ functions <fixture-parametrize>`.
+
+* `@pytest.mark.parametrize`_ allows one to define multiple sets of
+ arguments and fixtures at the test function or class.
+
+* `pytest_generate_tests`_ allows one to define custom parametrization
+ schemes or extensions.
+
+.. _parametrizemark:
+.. _`@pytest.mark.parametrize`:
+
+
+``@pytest.mark.parametrize``: parametrizing test functions
+---------------------------------------------------------------------
+
+.. regendoc: wipe
+
+.. versionadded:: 2.2
+.. versionchanged:: 2.4
+ Several improvements.
+
+The builtin ``pytest.mark.parametrize`` decorator enables
+parametrization of arguments for a test function. Here is a typical example
+of a test function that implements checking that a certain input leads
+to an expected output::
+
+ # content of test_expectation.py
+ import pytest
+ @pytest.mark.parametrize("test_input,expected", [
+ ("3+5", 8),
+ ("2+4", 6),
+ ("6*9", 42),
+ ])
+ def test_eval(test_input, expected):
+ assert eval(test_input) == expected
+
+Here, the ``@parametrize`` decorator defines three different ``(test_input,expected)``
+tuples so that the ``test_eval`` function will run three times using
+them in turn::
+
+ $ pytest
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 3 items
+
+ test_expectation.py ..F [100%]
+
+ ================================= FAILURES =================================
+ ____________________________ test_eval[6*9-42] _____________________________
+
+ test_input = '6*9', expected = 42
+
+ @pytest.mark.parametrize("test_input,expected", [
+ ("3+5", 8),
+ ("2+4", 6),
+ ("6*9", 42),
+ ])
+ def test_eval(test_input, expected):
+ > assert eval(test_input) == expected
+ E AssertionError: assert 54 == 42
+ E + where 54 = eval('6*9')
+
+ test_expectation.py:8: AssertionError
+ ==================== 1 failed, 2 passed in 0.12 seconds ====================
+
+As designed in this example, only one pair of input/output values fails
+the simple test function. And as usual with test function arguments,
+you can see the ``input`` and ``output`` values in the traceback.
+
+Note that you could also use the parametrize marker on a class or a module
+(see :ref:`mark`) which would invoke several functions with the argument sets.
+
+It is also possible to mark individual test instances within parametrize,
+for example with the builtin ``mark.xfail``::
+
+ # content of test_expectation.py
+ import pytest
+ @pytest.mark.parametrize("test_input,expected", [
+ ("3+5", 8),
+ ("2+4", 6),
+ pytest.param("6*9", 42,
+ marks=pytest.mark.xfail),
+ ])
+ def test_eval(test_input, expected):
+ assert eval(test_input) == expected
+
+Let's run this::
+
+ $ pytest
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 3 items
+
+ test_expectation.py ..x [100%]
+
+ =================== 2 passed, 1 xfailed in 0.12 seconds ====================
+
+The one parameter set which caused a failure previously now
+shows up as an "xfailed (expected to fail)" test.
+
+To get all combinations of multiple parametrized arguments you can stack
+``parametrize`` decorators::
+
+ import pytest
+ @pytest.mark.parametrize("x", [0, 1])
+ @pytest.mark.parametrize("y", [2, 3])
+ def test_foo(x, y):
+ pass
+
+This will run the test with the arguments set to ``x=0/y=2``, ``x=0/y=3``, ``x=1/y=2`` and
+``x=1/y=3``.
+
+.. _`pytest_generate_tests`:
+
+Basic ``pytest_generate_tests`` example
+---------------------------------------------
+
+Sometimes you may want to implement your own parametrization scheme
+or implement some dynamism for determining the parameters or scope
+of a fixture. For this, you can use the ``pytest_generate_tests`` hook
+which is called when collecting a test function. Through the passed in
+``metafunc`` object you can inspect the requesting test context and, most
+importantly, you can call ``metafunc.parametrize()`` to cause
+parametrization.
+
+For example, let's say we want to run a test taking string inputs which
+we want to set via a new ``pytest`` command line option. Let's first write
+a simple test accepting a ``stringinput`` fixture function argument::
+
+ # content of test_strings.py
+
+ def test_valid_string(stringinput):
+ assert stringinput.isalpha()
+
+Now we add a ``conftest.py`` file containing the addition of a
+command line option and the parametrization of our test function::
+
+ # content of conftest.py
+
+ def pytest_addoption(parser):
+ parser.addoption("--stringinput", action="append", default=[],
+ help="list of stringinputs to pass to test functions")
+
+ def pytest_generate_tests(metafunc):
+ if 'stringinput' in metafunc.fixturenames:
+ metafunc.parametrize("stringinput",
+ metafunc.config.getoption('stringinput'))
+
+If we now pass two stringinput values, our test will run twice::
+
+ $ pytest -q --stringinput="hello" --stringinput="world" test_strings.py
+ .. [100%]
+ 2 passed in 0.12 seconds
+
+Let's also run with a stringinput that will lead to a failing test::
+
+ $ pytest -q --stringinput="!" test_strings.py
+ F [100%]
+ ================================= FAILURES =================================
+ ___________________________ test_valid_string[!] ___________________________
+
+ stringinput = '!'
+
+ def test_valid_string(stringinput):
+ > assert stringinput.isalpha()
+ E AssertionError: assert False
+ E + where False = <built-in method isalpha of str object at 0xdeadbeef>()
+ E + where <built-in method isalpha of str object at 0xdeadbeef> = '!'.isalpha
+
+ test_strings.py:3: AssertionError
+ 1 failed in 0.12 seconds
+
+As expected our test function fails.
+
+If you don't specify a stringinput it will be skipped because
+``metafunc.parametrize()`` will be called with an empty parameter
+list::
+
+ $ pytest -q -rs test_strings.py
+ s [100%]
+ ========================= short test summary info ==========================
+ SKIP [1] test_strings.py: got empty parameter set ['stringinput'], function test_valid_string at $REGENDOC_TMPDIR/test_strings.py:1
+ 1 skipped in 0.12 seconds
+
+Note that when calling ``metafunc.parametrize`` multiple times with different parameter sets, all parameter names across
+those sets cannot be duplicated, otherwise an error will be raised.
+
+More examples
+-------------
+
+For further examples, you might want to look at :ref:`more
+parametrization examples <paramexamples>`.
+
+.. _`metafunc object`:
+
+The **metafunc** object
+-------------------------------------------
+
+.. currentmodule:: _pytest.python
+.. autoclass:: Metafunc
+ :members:
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/plugins.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/plugins.rst
new file mode 100644
index 00000000000..400418aee25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/plugins.rst
@@ -0,0 +1,154 @@
+.. _`external plugins`:
+.. _`extplugins`:
+.. _`using plugins`:
+
+Installing and Using plugins
+============================
+
+This section talks about installing and using third party plugins.
+For writing your own plugins, please refer to :ref:`writing-plugins`.
+
+Installing a third party plugin can be easily done with ``pip``::
+
+ pip install pytest-NAME
+ pip uninstall pytest-NAME
+
+If a plugin is installed, ``pytest`` automatically finds and integrates it,
+there is no need to activate it.
+
+Here is a little annotated list for some popular plugins:
+
+.. _`django`: https://www.djangoproject.com/
+
+* `pytest-django <http://pypi.python.org/pypi/pytest-django>`_: write tests
+ for `django`_ apps, using pytest integration.
+
+* `pytest-twisted <http://pypi.python.org/pypi/pytest-twisted>`_: write tests
+ for `twisted <http://twistedmatrix.com>`_ apps, starting a reactor and
+ processing deferreds from test functions.
+
+* `pytest-cov <http://pypi.python.org/pypi/pytest-cov>`_:
+ coverage reporting, compatible with distributed testing
+
+* `pytest-xdist <http://pypi.python.org/pypi/pytest-xdist>`_:
+ to distribute tests to CPUs and remote hosts, to run in boxed
+ mode which allows to survive segmentation faults, to run in
+ looponfailing mode, automatically re-running failing tests
+ on file changes.
+
+* `pytest-instafail <http://pypi.python.org/pypi/pytest-instafail>`_:
+ to report failures while the test run is happening.
+
+* `pytest-bdd <http://pypi.python.org/pypi/pytest-bdd>`_ and
+ `pytest-konira <http://pypi.python.org/pypi/pytest-konira>`_
+ to write tests using behaviour-driven testing.
+
+* `pytest-timeout <http://pypi.python.org/pypi/pytest-timeout>`_:
+ to timeout tests based on function marks or global definitions.
+
+* `pytest-pep8 <http://pypi.python.org/pypi/pytest-pep8>`_:
+ a ``--pep8`` option to enable PEP8 compliance checking.
+
+* `pytest-flakes <https://pypi.python.org/pypi/pytest-flakes>`_:
+ check source code with pyflakes.
+
+* `oejskit <http://pypi.python.org/pypi/oejskit>`_:
+ a plugin to run javascript unittests in live browsers.
+
+To see a complete list of all plugins with their latest testing
+status against different pytest and Python versions, please visit
+`plugincompat <http://plugincompat.herokuapp.com/>`_.
+
+You may also discover more plugins through a `pytest- pypi.python.org search`_.
+
+.. _`available installable plugins`:
+.. _`pytest- pypi.python.org search`: http://pypi.python.org/pypi?%3Aaction=search&term=pytest-&submit=search
+
+
+Requiring/Loading plugins in a test module or conftest file
+-----------------------------------------------------------
+
+You can require plugins in a test module or a conftest file like this::
+
+ pytest_plugins = "myapp.testsupport.myplugin",
+
+When the test module or conftest plugin is loaded the specified plugins
+will be loaded as well.
+
+ pytest_plugins = "myapp.testsupport.myplugin"
+
+which will import the specified module as a ``pytest`` plugin.
+
+.. _`findpluginname`:
+
+Finding out which plugins are active
+------------------------------------
+
+If you want to find out which plugins are active in your
+environment you can type::
+
+ pytest --trace-config
+
+and will get an extended test header which shows activated plugins
+and their names. It will also print local plugins aka
+:ref:`conftest.py <conftest.py plugins>` files when they are loaded.
+
+.. _`cmdunregister`:
+
+Deactivating / unregistering a plugin by name
+---------------------------------------------
+
+You can prevent plugins from loading or unregister them::
+
+ pytest -p no:NAME
+
+This means that any subsequent try to activate/load the named
+plugin will not work.
+
+If you want to unconditionally disable a plugin for a project, you can add
+this option to your ``pytest.ini`` file:
+
+.. code-block:: ini
+
+ [pytest]
+ addopts = -p no:NAME
+
+Alternatively to disable it only in certain environments (for example in a
+CI server), you can set ``PYTEST_ADDOPTS`` environment variable to
+``-p no:name``.
+
+See :ref:`findpluginname` for how to obtain the name of a plugin.
+
+.. _`builtin plugins`:
+
+Pytest default plugin reference
+-------------------------------
+
+
+You can find the source code for the following plugins
+in the `pytest repository <https://github.com/pytest-dev/pytest>`_.
+
+.. autosummary::
+
+ _pytest.assertion
+ _pytest.cacheprovider
+ _pytest.capture
+ _pytest.config
+ _pytest.doctest
+ _pytest.helpconfig
+ _pytest.junitxml
+ _pytest.mark
+ _pytest.monkeypatch
+ _pytest.nose
+ _pytest.pastebin
+ _pytest.debugging
+ _pytest.pytester
+ _pytest.python
+ _pytest.recwarn
+ _pytest.resultlog
+ _pytest.runner
+ _pytest.main
+ _pytest.skipping
+ _pytest.terminal
+ _pytest.tmpdir
+ _pytest.unittest
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/projects.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/projects.rst
new file mode 100644
index 00000000000..86df99ab2c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/projects.rst
@@ -0,0 +1,85 @@
+.. _projects:
+
+.. image:: img/gaynor3.png
+ :width: 400px
+ :align: right
+
+.. image:: img/theuni.png
+ :width: 400px
+ :align: right
+
+.. image:: img/cramer2.png
+ :width: 400px
+ :align: right
+
+.. image:: img/keleshev.png
+ :width: 400px
+ :align: right
+
+
+Project examples
+==========================
+
+Here are some examples of projects using ``pytest`` (please send notes via :ref:`contact`):
+
+* `PyPy <http://pypy.org>`_, Python with a JIT compiler, running over
+ `21000 tests <http://buildbot.pypy.org/summary?branch=%3Ctrunk%3E>`_
+* the `MoinMoin <http://moinmo.in>`_ Wiki Engine
+* `sentry <https://getsentry.com/welcome/>`_, realtime app-maintenance and exception tracking
+* `Astropy <http://www.astropy.org/>`_ and `affiliated packages <http://www.astropy.org/affiliated/index.html>`_
+* `tox <http://testrun.org/tox>`_, virtualenv/Hudson integration tool
+* `PIDA <http://pida.co.uk>`_ framework for integrated development
+* `PyPM <http://code.activestate.com/pypm/>`_ ActiveState's package manager
+* `Fom <http://packages.python.org/Fom/>`_ a fluid object mapper for FluidDB
+* `applib <https://github.com/ActiveState/applib>`_ cross-platform utilities
+* `six <http://pypi.python.org/pypi/six/>`_ Python 2 and 3 compatibility utilities
+* `pediapress <http://code.pediapress.com/wiki/wiki>`_ MediaWiki articles
+* `mwlib <http://pypi.python.org/pypi/mwlib>`_ mediawiki parser and utility library
+* `The Translate Toolkit <http://translate.sourceforge.net/wiki/toolkit/index>`_ for localization and conversion
+* `execnet <http://codespeak.net/execnet>`_ rapid multi-Python deployment
+* `pylib <http://py.rtfd.org>`_ cross-platform path, IO, dynamic code library
+* `Pacha <http://pacha.cafepais.com/>`_ configuration management in five minutes
+* `bbfreeze <http://pypi.python.org/pypi/bbfreeze>`_ create standalone executables from Python scripts
+* `pdb++ <http://bitbucket.org/antocuni/pdb>`_ a fancier version of PDB
+* `py-s3fuse <http://code.google.com/p/py-s3fuse/>`_ Amazon S3 FUSE based filesystem
+* `waskr <http://code.google.com/p/waskr/>`_ WSGI Stats Middleware
+* `guachi <http://code.google.com/p/guachi/>`_ global persistent configs for Python modules
+* `Circuits <http://pypi.python.org/pypi/circuits>`_ lightweight Event Driven Framework
+* `pygtk-helpers <http://bitbucket.org/aafshar/pygtkhelpers-main/>`_ easy interaction with PyGTK
+* `QuantumCore <http://quantumcore.org/>`_ statusmessage and repoze openid plugin
+* `pydataportability <http://pydataportability.net/>`_ libraries for managing the open web
+* `XIST <http://www.livinglogic.de/Python/xist/>`_ extensible HTML/XML generator
+* `tiddlyweb <http://pypi.python.org/pypi/tiddlyweb>`_ optionally headless, extensible RESTful datastore
+* `fancycompleter <http://bitbucket.org/antocuni/fancycompleter/src>`_ for colorful tab-completion
+* `Paludis <http://paludis.exherbo.org/>`_ tools for Gentoo Paludis package manager
+* `Gerald <http://halfcooked.com/code/gerald/>`_ schema comparison tool
+* `abjad <http://code.google.com/p/abjad/>`_ Python API for Formalized Score control
+* `bu <http://packages.python.org/bu/>`_ a microscopic build system
+* `katcp <https://bitbucket.org/hodgestar/katcp>`_ Telescope communication protocol over Twisted
+* `kss plugin timer <http://pypi.python.org/pypi/kss.plugin.timer>`_
+* `pyudev <https://pyudev.readthedocs.io/en/latest/tests/plugins.html>`_ a pure Python binding to the Linux library libudev
+* `pytest-localserver <https://bitbucket.org/pytest-dev/pytest-localserver/>`_ a plugin for pytest that provides an httpserver and smtpserver
+* `pytest-monkeyplus <http://pypi.python.org/pypi/pytest-monkeyplus/>`_ a plugin that extends monkeypatch
+
+These projects help integrate ``pytest`` into other Python frameworks:
+
+* `pytest-django <http://pypi.python.org/pypi/pytest-django/>`_ for Django
+* `zope.pytest <http://packages.python.org/zope.pytest/>`_ for Zope and Grok
+* `pytest_gae <http://pypi.python.org/pypi/pytest_gae/0.2.1>`_ for Google App Engine
+* There is `some work <https://github.com/Kotti/Kotti/blob/master/kotti/testing.py>`_ underway for Kotti, a CMS built in Pyramid/Pylons
+
+
+Some organisations using pytest
+-----------------------------------
+
+* `Square Kilometre Array, Cape Town <http://ska.ac.za/>`_
+* `Some Mozilla QA people <http://www.theautomatedtester.co.uk/blog/2011/pytest_and_xdist_plugin.html>`_ use pytest to distribute their Selenium tests
+* `Tandberg <http://www.tandberg.com/>`_
+* `Shootq <http://web.shootq.com/>`_
+* `Stups department of Heinrich Heine University Duesseldorf <http://www.stups.uni-duesseldorf.de/projects.php>`_
+* `cellzome <http://www.cellzome.com/>`_
+* `Open End, Gothenborg <http://www.openend.se>`_
+* `Laboratory of Bioinformatics, Warsaw <http://genesilico.pl/>`_
+* `merlinux, Germany <http://merlinux.eu>`_
+* `ESSS, Brazil <http://www.esss.com.br>`_
+* many more ... (please be so kind to send a note via :ref:`contact`)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/proposals/parametrize_with_fixtures.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/proposals/parametrize_with_fixtures.rst
new file mode 100644
index 00000000000..146032aa471
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/proposals/parametrize_with_fixtures.rst
@@ -0,0 +1,160 @@
+:orphan:
+
+===================================
+PROPOSAL: Parametrize with fixtures
+===================================
+
+.. warning::
+
+ This document outlines a proposal around using fixtures as input
+ of parametrized tests or fixtures.
+
+Problem
+-------
+
+As a user I have functional tests that I would like to run against various
+scenarios.
+
+In this particular example we want to generate a new project based on a
+cookiecutter template. We want to test default values but also data that
+emulates user input.
+
+- use default values
+
+- emulate user input
+
+ - specify 'author'
+
+ - specify 'project_slug'
+
+ - specify 'author' and 'project_slug'
+
+This is how a functional test could look like:
+
+.. code-block:: python
+
+ import pytest
+
+ @pytest.fixture
+ def default_context():
+ return {'extra_context': {}}
+
+
+ @pytest.fixture(params=[
+ {'author': 'alice'},
+ {'project_slug': 'helloworld'},
+ {'author': 'bob', 'project_slug': 'foobar'},
+ ])
+ def extra_context(request):
+ return {'extra_context': request.param}
+
+
+ @pytest.fixture(params=['default', 'extra'])
+ def context(request):
+ if request.param == 'default':
+ return request.getfuncargvalue('default_context')
+ else:
+ return request.getfuncargvalue('extra_context')
+
+
+ def test_generate_project(cookies, context):
+ """Call the cookiecutter API to generate a new project from a
+ template.
+ """
+ result = cookies.bake(extra_context=context)
+
+ assert result.exit_code == 0
+ assert result.exception is None
+ assert result.project.isdir()
+
+
+Issues
+------
+
+* By using ``request.getfuncargvalue()`` we rely on actual fixture function
+ execution to know what fixtures are involved, due to it's dynamic nature
+* More importantly, ``request.getfuncargvalue()`` cannot be combined with
+ parametrized fixtures, such as ``extra_context``
+* This is very inconvenient if you wish to extend an existing test suite by
+ certain parameters for fixtures that are already used by tests
+
+pytest version 3.0 reports an error if you try to run above code::
+
+ Failed: The requested fixture has no parameter defined for the current
+ test.
+
+ Requested fixture 'extra_context'
+
+
+Proposed solution
+-----------------
+
+A new function that can be used in modules can be used to dynamically define
+fixtures from existing ones.
+
+.. code-block:: python
+
+ pytest.define_combined_fixture(
+ name='context',
+ fixtures=['default_context', 'extra_context'],
+ )
+
+The new fixture ``context`` inherits the scope from the used fixtures and yield
+the following values.
+
+- ``{}``
+
+- ``{'author': 'alice'}``
+
+- ``{'project_slug': 'helloworld'}``
+
+- ``{'author': 'bob', 'project_slug': 'foobar'}``
+
+Alternative approach
+--------------------
+
+A new helper function named ``fixture_request`` would tell pytest to yield
+all parameters marked as a fixture.
+
+.. note::
+
+ The `pytest-lazy-fixture <https://pypi.python.org/pypi/pytest-lazy-fixture>`_ plugin implements a very
+ similar solution to the proposal below, make sure to check it out.
+
+.. code-block:: python
+
+ @pytest.fixture(params=[
+ pytest.fixture_request('default_context'),
+ pytest.fixture_request('extra_context'),
+ ])
+ def context(request):
+ """Returns all values for ``default_context``, one-by-one before it
+ does the same for ``extra_context``.
+
+ request.param:
+ - {}
+ - {'author': 'alice'}
+ - {'project_slug': 'helloworld'}
+ - {'author': 'bob', 'project_slug': 'foobar'}
+ """
+ return request.param
+
+The same helper can be used in combination with ``pytest.mark.parametrize``.
+
+.. code-block:: python
+
+
+ @pytest.mark.parametrize(
+ 'context, expected_response_code',
+ [
+ (pytest.fixture_request('default_context'), 0),
+ (pytest.fixture_request('extra_context'), 0),
+ ],
+ )
+ def test_generate_project(cookies, context, exit_code):
+ """Call the cookiecutter API to generate a new project from a
+ template.
+ """
+ result = cookies.bake(extra_context=context)
+
+ assert result.exit_code == exit_code
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/pytest.ini b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/pytest.ini
index 7604360561c..7604360561c 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/pytest.ini
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/pytest.ini
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/pythonpath.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/pythonpath.rst
new file mode 100644
index 00000000000..b6474276887
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/pythonpath.rst
@@ -0,0 +1,76 @@
+.. _pythonpath:
+
+pytest import mechanisms and ``sys.path``/``PYTHONPATH``
+========================================================
+
+Here's a list of scenarios where pytest may need to change ``sys.path`` in order
+to import test modules or ``conftest.py`` files.
+
+Test modules / ``conftest.py`` files inside packages
+----------------------------------------------------
+
+Consider this file and directory layout::
+
+ root/
+ |- foo/
+ |- __init__.py
+ |- conftest.py
+ |- bar/
+ |- __init__.py
+ |- tests/
+ |- __init__.py
+ |- test_foo.py
+
+
+When executing::
+
+ pytest root/
+
+
+
+pytest will find ``foo/bar/tests/test_foo.py`` and realize it is part of a package given that
+there's an ``__init__.py`` file in the same folder. It will then search upwards until it can find the
+last folder which still contains an ``__init__.py`` file in order to find the package *root* (in
+this case ``foo/``). To load the module, it will insert ``root/`` to the front of
+``sys.path`` (if not there already) in order to load
+``test_foo.py`` as the *module* ``foo.bar.tests.test_foo``.
+
+The same logic applies to the ``conftest.py`` file: it will be imported as ``foo.conftest`` module.
+
+Preserving the full package name is important when tests live in a package to avoid problems
+and allow test modules to have duplicated names. This is also discussed in details in
+:ref:`test discovery`.
+
+Standalone test modules / ``conftest.py`` files
+-----------------------------------------------
+
+Consider this file and directory layout::
+
+ root/
+ |- foo/
+ |- conftest.py
+ |- bar/
+ |- tests/
+ |- test_foo.py
+
+
+When executing::
+
+ pytest root/
+
+pytest will find ``foo/bar/tests/test_foo.py`` and realize it is NOT part of a package given that
+there's no ``__init__.py`` file in the same folder. It will then add ``root/foo/bar/tests`` to
+``sys.path`` in order to import ``test_foo.py`` as the *module* ``test_foo``. The same is done
+with the ``conftest.py`` file by adding ``root/foo`` to ``sys.path`` to import it as ``conftest``.
+
+For this reason this layout cannot have test modules with the same name, as they all will be
+imported in the global import namespace.
+
+This is also discussed in details in :ref:`test discovery`.
+
+Invoking ``pytest`` versus ``python -m pytest``
+-----------------------------------------------
+
+Running pytest with ``python -m pytest [...]`` instead of ``pytest [...]`` yields nearly
+equivalent behaviour, except that the former call will add the current directory to ``sys.path``.
+See also :ref:`cmdline`.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/recwarn.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/recwarn.rst
new file mode 100644
index 00000000000..513af0d450e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/recwarn.rst
@@ -0,0 +1,3 @@
+:orphan:
+
+This page has been moved, please see :ref:`assertwarnings`.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/requirements.txt b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/requirements.txt
new file mode 100644
index 00000000000..72bb60a811f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/requirements.txt
@@ -0,0 +1,3 @@
+# pinning sphinx to 1.4.* due to search issues with rtd:
+# https://github.com/rtfd/readthedocs-sphinx-ext/issues/25
+sphinx ==1.4.*
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/skipping.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/skipping.rst
new file mode 100644
index 00000000000..7e001929b23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/skipping.rst
@@ -0,0 +1,378 @@
+.. _`skip and xfail`:
+
+.. _skipping:
+
+Skip and xfail: dealing with tests that cannot succeed
+======================================================
+
+You can mark test functions that cannot be run on certain platforms
+or that you expect to fail so pytest can deal with them accordingly and
+present a summary of the test session, while keeping the test suite *green*.
+
+A **skip** means that you expect your test to pass only if some conditions are met,
+otherwise pytest should skip running the test altogether. Common examples are skipping
+windows-only tests on non-windows platforms, or skipping tests that depend on an external
+resource which is not available at the moment (for example a database).
+
+A **xfail** means that you expect a test to fail for some reason.
+A common example is a test for a feature not yet implemented, or a bug not yet fixed.
+When a test passes despite being expected to fail (marked with ``pytest.mark.xfail``),
+it's an **xpass** and will be reported in the test summary.
+
+``pytest`` counts and lists *skip* and *xfail* tests separately. Detailed
+information about skipped/xfailed tests is not shown by default to avoid
+cluttering the output. You can use the ``-r`` option to see details
+corresponding to the "short" letters shown in the test progress::
+
+ pytest -rxXs # show extra info on xfailed, xpassed, and skipped tests
+
+More details on the ``-r`` option can be found by running ``pytest -h``.
+
+(See :ref:`how to change command line options defaults`)
+
+.. _skipif:
+.. _skip:
+.. _`condition booleans`:
+
+Skipping test functions
+-----------------------
+
+.. versionadded:: 2.9
+
+The simplest way to skip a test function is to mark it with the ``skip`` decorator
+which may be passed an optional ``reason``:
+
+.. code-block:: python
+
+ @pytest.mark.skip(reason="no way of currently testing this")
+ def test_the_unknown():
+ ...
+
+
+Alternatively, it is also possible to skip imperatively during test execution or setup
+by calling the ``pytest.skip(reason)`` function:
+
+.. code-block:: python
+
+ def test_function():
+ if not valid_config():
+ pytest.skip("unsupported configuration")
+
+It is also possible to skip the whole module using
+``pytest.skip(reason, allow_module_level=True)`` at the module level:
+
+.. code-block:: python
+
+ import pytest
+
+ if not pytest.config.getoption("--custom-flag"):
+ pytest.skip("--custom-flag is missing, skipping tests", allow_module_level=True)
+
+The imperative method is useful when it is not possible to evaluate the skip condition
+during import time.
+
+``skipif``
+~~~~~~~~~~
+
+.. versionadded:: 2.0
+
+If you wish to skip something conditionally then you can use ``skipif`` instead.
+Here is an example of marking a test function to be skipped
+when run on a Python3.6 interpreter::
+
+ import sys
+ @pytest.mark.skipif(sys.version_info < (3,6),
+ reason="requires python3.6")
+ def test_function():
+ ...
+
+If the condition evaluates to ``True`` during collection, the test function will be skipped,
+with the specified reason appearing in the summary when using ``-rs``.
+
+You can share ``skipif`` markers between modules. Consider this test module::
+
+ # content of test_mymodule.py
+ import mymodule
+ minversion = pytest.mark.skipif(mymodule.__versioninfo__ < (1,1),
+ reason="at least mymodule-1.1 required")
+ @minversion
+ def test_function():
+ ...
+
+You can import the marker and reuse it in another test module::
+
+ # test_myothermodule.py
+ from test_mymodule import minversion
+
+ @minversion
+ def test_anotherfunction():
+ ...
+
+For larger test suites it's usually a good idea to have one file
+where you define the markers which you then consistently apply
+throughout your test suite.
+
+Alternatively, you can use :ref:`condition strings
+<string conditions>` instead of booleans, but they can't be shared between modules easily
+so they are supported mainly for backward compatibility reasons.
+
+
+Skip all test functions of a class or module
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can use the ``skipif`` marker (as any other marker) on classes::
+
+ @pytest.mark.skipif(sys.platform == 'win32',
+ reason="does not run on windows")
+ class TestPosixCalls(object):
+
+ def test_function(self):
+ "will not be setup or run under 'win32' platform"
+
+If the condition is ``True``, this marker will produce a skip result for
+each of the test methods of that class.
+
+.. warning::
+
+ The use of ``skipif`` on classes that use inheritance is strongly
+ discouraged. `A Known bug <https://github.com/pytest-dev/pytest/issues/568>`_
+ in pytest's markers may cause unexpected behavior in super classes.
+
+If you want to skip all test functions of a module, you may use
+the ``pytestmark`` name on the global level:
+
+.. code-block:: python
+
+ # test_module.py
+ pytestmark = pytest.mark.skipif(...)
+
+If multiple ``skipif`` decorators are applied to a test function, it
+will be skipped if any of the skip conditions is true.
+
+.. _`whole class- or module level`: mark.html#scoped-marking
+
+
+Skipping files or directories
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Sometimes you may need to skip an entire file or directory, for example if the
+tests rely on Python version-specific features or contain code that you do not
+wish pytest to run. In this case, you must exclude the files and directories
+from collection. Refer to :ref:`customizing-test-collection` for more
+information.
+
+
+Skipping on a missing import dependency
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can use the following helper at module level
+or within a test or test setup function::
+
+ docutils = pytest.importorskip("docutils")
+
+If ``docutils`` cannot be imported here, this will lead to a
+skip outcome of the test. You can also skip based on the
+version number of a library::
+
+ docutils = pytest.importorskip("docutils", minversion="0.3")
+
+The version will be read from the specified
+module's ``__version__`` attribute.
+
+Summary
+~~~~~~~
+
+Here's a quick guide on how to skip tests in a module in different situations:
+
+1. Skip all tests in a module unconditionally:
+
+ .. code-block:: python
+
+ pytestmark = pytest.mark.skip('all tests still WIP')
+
+2. Skip all tests in a module based on some condition:
+
+ .. code-block:: python
+
+ pytestmark = pytest.mark.skipif(sys.platform == 'win32', 'tests for linux only')
+
+3. Skip all tests in a module if some import is missing:
+
+ .. code-block:: python
+
+ pexpect = pytest.importorskip('pexpect')
+
+
+.. _xfail:
+
+XFail: mark test functions as expected to fail
+----------------------------------------------
+
+You can use the ``xfail`` marker to indicate that you
+expect a test to fail::
+
+ @pytest.mark.xfail
+ def test_function():
+ ...
+
+This test will be run but no traceback will be reported
+when it fails. Instead terminal reporting will list it in the
+"expected to fail" (``XFAIL``) or "unexpectedly passing" (``XPASS``) sections.
+
+Alternatively, you can also mark a test as ``XFAIL`` from within a test or setup function
+imperatively:
+
+.. code-block:: python
+
+ def test_function():
+ if not valid_config():
+ pytest.xfail("failing configuration (but should work)")
+
+This will unconditionally make ``test_function`` ``XFAIL``. Note that no other code is executed
+after ``pytest.xfail`` call, differently from the marker. That's because it is implemented
+internally by raising a known exception.
+
+Here's the signature of the ``xfail`` **marker** (not the function), using Python 3 keyword-only
+arguments syntax:
+
+.. code-block:: python
+
+ def xfail(condition=None, *, reason=None, raises=None, run=True, strict=False):
+
+
+
+
+``strict`` parameter
+~~~~~~~~~~~~~~~~~~~~
+
+.. versionadded:: 2.9
+
+Both ``XFAIL`` and ``XPASS`` don't fail the test suite, unless the ``strict`` keyword-only
+parameter is passed as ``True``:
+
+.. code-block:: python
+
+ @pytest.mark.xfail(strict=True)
+ def test_function():
+ ...
+
+
+This will make ``XPASS`` ("unexpectedly passing") results from this test to fail the test suite.
+
+You can change the default value of the ``strict`` parameter using the
+``xfail_strict`` ini option:
+
+.. code-block:: ini
+
+ [pytest]
+ xfail_strict=true
+
+
+``reason`` parameter
+~~~~~~~~~~~~~~~~~~~~
+
+As with skipif_ you can also mark your expectation of a failure
+on a particular platform::
+
+ @pytest.mark.xfail(sys.version_info >= (3,6),
+ reason="python3.6 api changes")
+ def test_function():
+ ...
+
+
+``raises`` parameter
+~~~~~~~~~~~~~~~~~~~~
+
+If you want to be more specific as to why the test is failing, you can specify
+a single exception, or a list of exceptions, in the ``raises`` argument.
+
+.. code-block:: python
+
+ @pytest.mark.xfail(raises=RuntimeError)
+ def test_function():
+ ...
+
+Then the test will be reported as a regular failure if it fails with an
+exception not mentioned in ``raises``.
+
+``run`` parameter
+~~~~~~~~~~~~~~~~~
+
+If a test should be marked as xfail and reported as such but should not be
+even executed, use the ``run`` parameter as ``False``:
+
+.. code-block:: python
+
+ @pytest.mark.xfail(run=False)
+ def test_function():
+ ...
+
+This is specially useful for xfailing tests that are crashing the interpreter and should be
+investigated later.
+
+
+Ignoring xfail
+~~~~~~~~~~~~~~
+
+By specifying on the commandline::
+
+ pytest --runxfail
+
+you can force the running and reporting of an ``xfail`` marked test
+as if it weren't marked at all. This also causes ``pytest.xfail`` to produce no effect.
+
+Examples
+~~~~~~~~
+
+Here is a simple test file with the several usages:
+
+.. literalinclude:: example/xfail_demo.py
+
+Running it with the report-on-xfail option gives this output::
+
+ example $ pytest -rx xfail_demo.py
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR/example, inifile:
+ collected 7 items
+
+ xfail_demo.py xxxxxxx [100%]
+ ========================= short test summary info ==========================
+ XFAIL xfail_demo.py::test_hello
+ XFAIL xfail_demo.py::test_hello2
+ reason: [NOTRUN]
+ XFAIL xfail_demo.py::test_hello3
+ condition: hasattr(os, 'sep')
+ XFAIL xfail_demo.py::test_hello4
+ bug 110
+ XFAIL xfail_demo.py::test_hello5
+ condition: pytest.__version__[0] != "17"
+ XFAIL xfail_demo.py::test_hello6
+ reason: reason
+ XFAIL xfail_demo.py::test_hello7
+
+ ======================== 7 xfailed in 0.12 seconds =========================
+
+.. _`skip/xfail with parametrize`:
+
+Skip/xfail with parametrize
+---------------------------
+
+It is possible to apply markers like skip and xfail to individual
+test instances when using parametrize:
+
+.. code-block:: python
+
+ import pytest
+
+ @pytest.mark.parametrize(("n", "expected"), [
+ (1, 2),
+ pytest.param(1, 0, marks=pytest.mark.xfail),
+ pytest.param(1, 3, marks=pytest.mark.xfail(reason="some bug")),
+ (2, 3),
+ (3, 4),
+ (4, 5),
+ pytest.param(10, 11, marks=pytest.mark.skipif(sys.version_info >= (3, 0), reason="py2k")),
+ ])
+ def test_increment(n, expected):
+ assert n + 1 == expected
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/talks.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/talks.rst
new file mode 100644
index 00000000000..bf593db4b4b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/talks.rst
@@ -0,0 +1,105 @@
+
+Talks and Tutorials
+==========================
+
+..
+ .. sidebar:: Next Open Trainings
+
+ `Professional Testing with Python
+ <http://www.python-academy.com/courses/specialtopics/python_course_testing.html>`_,
+ 26-28 April 2017, Leipzig, Germany.
+
+.. _`funcargs`: funcargs.html
+
+Books
+---------------------------------------------
+
+- `Python Testing with pytest, by Brian Okken (2017)
+ <https://pragprog.com/book/bopytest/python-testing-with-pytest>`_.
+
+Talks and blog postings
+---------------------------------------------
+
+- `Pythonic testing, Igor Starikov (Russian, PyNsk, November 2016)
+ <https://www.youtube.com/watch?v=_92nfdd5nK8>`_.
+
+- `pytest - Rapid Simple Testing, Florian Bruhin, Swiss Python Summit 2016
+ <https://www.youtube.com/watch?v=rCBHkQ_LVIs>`_.
+
+- `Improve your testing with Pytest and Mock, Gabe Hollombe, PyCon SG 2015
+ <https://www.youtube.com/watch?v=RcN26hznmk4>`_.
+
+- `Introduction to pytest, Andreas Pelme, EuroPython 2014
+ <https://www.youtube.com/watch?v=LdVJj65ikRY>`_.
+
+- `Advanced Uses of py.test Fixtures, Floris Bruynooghe, EuroPython
+ 2014 <https://www.youtube.com/watch?v=IBC_dxr-4ps>`_.
+
+- `Why i use py.test and maybe you should too, Andy Todd, Pycon AU 2013
+ <https://www.youtube.com/watch?v=P-AhpukDIik>`_
+
+- `3-part blog series about pytest from @pydanny alias Daniel Greenfeld (January
+ 2014) <http://pydanny.com/pytest-no-boilerplate-testing.html>`_
+
+- `pytest: helps you write better Django apps, Andreas Pelme, DjangoCon
+ Europe 2014 <https://www.youtube.com/watch?v=aaArYVh6XSM>`_.
+
+- :ref:`fixtures`
+
+- `Testing Django Applications with pytest, Andreas Pelme, EuroPython
+ 2013 <https://www.youtube.com/watch?v=aUf8Fkb7TaY>`_.
+
+- `Testes pythonics com py.test, Vinicius Belchior Assef Neto, Plone
+ Conf 2013, Brazil <https://www.youtube.com/watch?v=QUKoq2K7bis>`_.
+
+- `Introduction to py.test fixtures, FOSDEM 2013, Floris Bruynooghe
+ <https://www.youtube.com/watch?v=bJhRW4eZMco>`_.
+
+- `pytest feature and release highlights, Holger Krekel (GERMAN, October 2013)
+ <http://pyvideo.org/video/2429/pytest-feature-and-new-release-highlights>`_
+
+- `pytest introduction from Brian Okken (January 2013)
+ <http://pythontesting.net/framework/pytest-introduction/>`_
+
+- pycon australia 2012 pytest talk from Brianna Laugher (`video <http://www.youtube.com/watch?v=DTNejE9EraI>`_, `slides <http://www.slideshare.net/pfctdayelise/funcargs-other-fun-with-pytest>`_, `code <https://gist.github.com/3386951>`_)
+- `pycon 2012 US talk video from Holger Krekel <http://www.youtube.com/watch?v=9LVqBQcFmyw>`_
+
+- `monkey patching done right`_ (blog post, consult `monkeypatch plugin`_ for up-to-date API)
+
+Test parametrization:
+
+- `generating parametrized tests with fixtures`_.
+- `test generators and cached setup`_
+- `parametrizing tests, generalized`_ (blog post)
+- `putting test-hooks into local or global plugins`_ (blog post)
+
+Assertion introspection:
+
+- `(07/2011) Behind the scenes of pytest's new assertion rewriting
+ <http://pybites.blogspot.com/2011/07/behind-scenes-of-pytests-new-assertion.html>`_
+
+Distributed testing:
+
+- `simultaneously test your code on all platforms`_ (blog entry)
+
+Plugin specific examples:
+
+- `skipping slow tests by default in pytest`_ (blog entry)
+
+- `many examples in the docs for plugins`_
+
+.. _`skipping slow tests by default in pytest`: http://bruynooghe.blogspot.com/2009/12/skipping-slow-test-by-default-in-pytest.html
+.. _`many examples in the docs for plugins`: plugins.html
+.. _`monkeypatch plugin`: monkeypatch.html
+.. _`application setup in test functions with fixtures`: fixture.html#interdependent-fixtures
+.. _`simultaneously test your code on all platforms`: http://tetamap.wordpress.com/2009/03/23/new-simultanously-test-your-code-on-all-platforms/
+.. _`monkey patching done right`: http://tetamap.wordpress.com/2009/03/03/monkeypatching-in-unit-tests-done-right/
+.. _`putting test-hooks into local or global plugins`: http://tetamap.wordpress.com/2009/05/14/putting-test-hooks-into-local-and-global-plugins/
+.. _`parametrizing tests, generalized`: http://tetamap.wordpress.com/2009/05/13/parametrizing-python-tests-generalized/
+.. _`generating parametrized tests with fixtures`: parametrize.html#test-generators
+.. _`test generators and cached setup`: http://bruynooghe.blogspot.com/2010/06/pytest-test-generators-and-cached-setup.html
+
+
+
+
+
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/attic.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/attic.rst
new file mode 100644
index 00000000000..06944661cb5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/attic.rst
@@ -0,0 +1,117 @@
+===============================================
+ATTIC documentation
+===============================================
+
+XXX REVIEW and remove the below XXX
+
+Customizing the testing process
+===============================
+
+writing conftest.py files
+-----------------------------------
+
+You may put conftest.py files containing project-specific
+configuration in your project's root directory, it's usually
+best to put it just into the same directory level as your
+topmost ``__init__.py``. In fact, ``pytest`` performs
+an "upwards" search starting from the directory that you specify
+to be tested and will lookup configuration values right-to-left.
+You may have options that reside e.g. in your home directory
+but note that project specific settings will be considered
+first. There is a flag that helps you debugging your
+conftest.py configurations::
+
+ pytest --trace-config
+
+
+customizing the collecting and running process
+-----------------------------------------------
+
+To introduce different test items you can create
+one or more ``conftest.py`` files in your project.
+When the collection process traverses directories
+and modules the default collectors will produce
+custom Collectors and Items if they are found
+in a local ``conftest.py`` file.
+
+
+Customizing the collection process in a module
+----------------------------------------------
+
+If you have a module where you want to take responsibility for
+collecting your own test Items and possibly even for executing
+a test then you can provide `generative tests`_ that yield
+callables and possibly arguments as a tuple. This is especially
+useful for calling application test machinery with different
+parameter sets but counting each of the calls as a separate
+tests.
+
+.. _`generative tests`: features.html#generative-tests
+
+The other extension possibility is about
+specifying a custom test ``Item`` class which
+is responsible for setting up and executing an underlying
+test. Or you can extend the collection process for a whole
+directory tree by putting Items in a ``conftest.py`` configuration file.
+The collection process dynamically consults the *chain of conftest.py*
+modules to determine collectors and items at ``Directory``, ``Module``,
+``Class``, ``Function`` or ``Generator`` level respectively.
+
+Customizing execution of Items and Functions
+----------------------------------------------------
+
+- ``pytest.Function`` test items control execution
+ of a test function through its ``function.runtest()`` method.
+ This method is responsible for performing setup and teardown
+ ("Test Fixtures") for a test Function.
+
+- ``Function.execute(target, *args)`` methods are invoked by
+ the default ``Function.run()`` to actually execute a python
+ function with the given (usually empty set of) arguments.
+
+.. _`py-dev mailing list`: http://codespeak.net/mailman/listinfo/py-dev
+
+
+.. _`test generators`: funcargs.html#test-generators
+
+.. _`generative tests`:
+
+generative tests: yielding parametrized tests
+====================================================
+
+Deprecated since 1.0 in favour of `test generators`_.
+
+*Generative tests* are test methods that are *generator functions* which
+``yield`` callables and their arguments. This is useful for running a
+test function multiple times against different parameters. Example::
+
+ def test_generative():
+ for x in (42,17,49):
+ yield check, x
+
+ def check(arg):
+ assert arg % 7 == 0 # second generated tests fails!
+
+Note that ``test_generative()`` will cause three tests
+to get run, notably ``check(42)``, ``check(17)`` and ``check(49)``
+of which the middle one will obviously fail.
+
+To make it easier to distinguish the generated tests it is possible to specify an explicit name for them, like for example::
+
+ def test_generative():
+ for x in (42,17,49):
+ yield "case %d" % x, check, x
+
+
+disabling a test class
+----------------------
+
+If you want to disable a complete test class you
+can set the class-level attribute ``disabled``.
+For example, in order to avoid running some tests on Win32::
+
+ class TestPosixOnly(object):
+ disabled = sys.platform == 'win32'
+
+ def test_xxx(self):
+ ...
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/config.html b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/config.html
index cba5a46f982..cba5a46f982 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/config.html
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/config.html
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/dist.html b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/dist.html
index e328550a85c..e328550a85c 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/dist.html
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/dist.html
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/extend.html b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/extend.html
index cba5a46f982..cba5a46f982 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/extend.html
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/extend.html
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/index.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/index.rst
index 1a3b5a54da0..1a3b5a54da0 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/index.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/index.rst
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/mission.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/mission.rst
new file mode 100644
index 00000000000..51c252dc0d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/mission.rst
@@ -0,0 +1,13 @@
+
+Mission
+====================================
+
+``pytest`` strives to make testing a fun and no-boilerplate effort.
+
+The tool is distributed as a `pytest` package. Its project independent
+``pytest`` command line tool helps you to:
+
+* rapidly collect and run tests
+* run unit- or doctests, functional or integration tests
+* distribute tests to multiple environments
+* use local or global plugins for custom test types and setup
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/cov.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/cov.rst
new file mode 100644
index 00000000000..541c7ef9479
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/cov.rst
@@ -0,0 +1,230 @@
+
+produce code coverage reports using the 'coverage' package, including support for distributed testing.
+======================================================================================================
+
+
+.. contents::
+ :local:
+
+This plugin produces coverage reports. It supports centralised testing and distributed testing in
+both load and each modes. It also supports coverage of subprocesses.
+
+All features offered by the coverage package should be available, either through pytest-cov or
+through coverage's config file.
+
+
+Installation
+------------
+
+The `pytest-cov`_ package may be installed with pip or easy_install::
+
+ pip install pytest-cov
+ easy_install pytest-cov
+
+.. _`pytest-cov`: http://pypi.python.org/pypi/pytest-cov/
+
+
+Uninstallation
+--------------
+
+Uninstalling packages is supported by pip::
+
+ pip uninstall pytest-cov
+
+However easy_install does not provide an uninstall facility.
+
+.. IMPORTANT::
+
+ Ensure that you manually delete the init_covmain.pth file in your
+ site-packages directory.
+
+ This file starts coverage collection of subprocesses if appropriate during
+ site initialization at python startup.
+
+
+Usage
+-----
+
+Centralised Testing
+~~~~~~~~~~~~~~~~~~~
+
+Centralised testing will report on the combined coverage of the main process and all of it's
+subprocesses.
+
+Running centralised testing::
+
+ pytest --cov myproj tests/
+
+Shows a terminal report::
+
+ -------------------- coverage: platform linux2, python 2.6.4-final-0 ---------------------
+ Name Stmts Miss Cover
+ ----------------------------------------
+ myproj/__init__ 2 0 100%
+ myproj/myproj 257 13 94%
+ myproj/feature4286 94 7 92%
+ ----------------------------------------
+ TOTAL 353 20 94%
+
+
+Distributed Testing: Load
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Distributed testing with dist mode set to load will report on the combined coverage of all slaves.
+The slaves may be spread out over any number of hosts and each slave may be located anywhere on the
+file system. Each slave will have it's subprocesses measured.
+
+Running distributed testing with dist mode set to load::
+
+ pytest --cov myproj -n 2 tests/
+
+Shows a terminal report::
+
+ -------------------- coverage: platform linux2, python 2.6.4-final-0 ---------------------
+ Name Stmts Miss Cover
+ ----------------------------------------
+ myproj/__init__ 2 0 100%
+ myproj/myproj 257 13 94%
+ myproj/feature4286 94 7 92%
+ ----------------------------------------
+ TOTAL 353 20 94%
+
+
+Again but spread over different hosts and different directories::
+
+ pytest --cov myproj --dist load
+ --tx ssh=memedough@host1//chdir=testenv1
+ --tx ssh=memedough@host2//chdir=/tmp/testenv2//python=/tmp/env1/bin/python
+ --rsyncdir myproj --rsyncdir tests --rsync examples
+ tests/
+
+Shows a terminal report::
+
+ -------------------- coverage: platform linux2, python 2.6.4-final-0 ---------------------
+ Name Stmts Miss Cover
+ ----------------------------------------
+ myproj/__init__ 2 0 100%
+ myproj/myproj 257 13 94%
+ myproj/feature4286 94 7 92%
+ ----------------------------------------
+ TOTAL 353 20 94%
+
+
+Distributed Testing: Each
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Distributed testing with dist mode set to each will report on the combined coverage of all slaves.
+Since each slave is running all tests this allows generating a combined coverage report for multiple
+environments.
+
+Running distributed testing with dist mode set to each::
+
+ pytest --cov myproj --dist each
+ --tx popen//chdir=/tmp/testenv3//python=/usr/local/python27/bin/python
+ --tx ssh=memedough@host2//chdir=/tmp/testenv4//python=/tmp/env2/bin/python
+ --rsyncdir myproj --rsyncdir tests --rsync examples
+ tests/
+
+Shows a terminal report::
+
+ ---------------------------------------- coverage ----------------------------------------
+ platform linux2, python 2.6.5-final-0
+ platform linux2, python 2.7.0-final-0
+ Name Stmts Miss Cover
+ ----------------------------------------
+ myproj/__init__ 2 0 100%
+ myproj/myproj 257 13 94%
+ myproj/feature4286 94 7 92%
+ ----------------------------------------
+ TOTAL 353 20 94%
+
+
+Reporting
+---------
+
+It is possible to generate any combination of the reports for a single test run.
+
+The available reports are terminal (with or without missing line numbers shown), HTML, XML and
+annotated source code.
+
+The terminal report without line numbers (default)::
+
+ pytest --cov-report term --cov myproj tests/
+
+ -------------------- coverage: platform linux2, python 2.6.4-final-0 ---------------------
+ Name Stmts Miss Cover
+ ----------------------------------------
+ myproj/__init__ 2 0 100%
+ myproj/myproj 257 13 94%
+ myproj/feature4286 94 7 92%
+ ----------------------------------------
+ TOTAL 353 20 94%
+
+
+The terminal report with line numbers::
+
+ pytest --cov-report term-missing --cov myproj tests/
+
+ -------------------- coverage: platform linux2, python 2.6.4-final-0 ---------------------
+ Name Stmts Miss Cover Missing
+ --------------------------------------------------
+ myproj/__init__ 2 0 100%
+ myproj/myproj 257 13 94% 24-26, 99, 149, 233-236, 297-298, 369-370
+ myproj/feature4286 94 7 92% 183-188, 197
+ --------------------------------------------------
+ TOTAL 353 20 94%
+
+
+The remaining three reports output to files without showing anything on the terminal (useful for
+when the output is going to a continuous integration server)::
+
+ pytest --cov-report html --cov-report xml --cov-report annotate --cov myproj tests/
+
+
+Coverage Data File
+------------------
+
+The data file is erased at the beginning of testing to ensure clean data for each test run.
+
+The data file is left at the end of testing so that it is possible to use normal coverage tools to
+examine it.
+
+
+Limitations
+-----------
+
+For distributed testing the slaves must have the pytest-cov package installed. This is needed since
+the plugin must be registered through setuptools / distribute for pytest to start the plugin on the
+slave.
+
+For subprocess measurement environment variables must make it from the main process to the
+subprocess. The python used by the subprocess must have pytest-cov installed. The subprocess must
+do normal site initialization so that the environment variables can be detected and coverage
+started.
+
+
+Acknowledgments
+----------------
+
+Holger Krekel for pytest with its distributed testing support.
+
+Ned Batchelder for coverage and its ability to combine the coverage results of parallel runs.
+
+Whilst this plugin has been built fresh from the ground up to support distributed testing it has
+been influenced by the work done on pytest-coverage (Ross Lawley, James Mills, Holger Krekel) and
+nose-cover (Jason Pellerin) which are other coverage plugins for pytest and nose respectively.
+
+No doubt others have contributed to these tools as well.
+
+command line options
+--------------------
+
+
+``--cov=path``
+ measure coverage for filesystem path (multi-allowed)
+``--cov-report=type``
+ type of report to generate: term, term-missing, annotate, html, xml (multi-allowed)
+``--cov-config=path``
+ config file for coverage, default: .coveragerc
+
+.. include:: links.txt
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/coverage.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/coverage.rst
new file mode 100644
index 00000000000..71139d008ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/coverage.rst
@@ -0,0 +1,51 @@
+
+Write and report coverage data with the 'coverage' package.
+===========================================================
+
+
+.. contents::
+ :local:
+
+Note: Original code by Ross Lawley.
+
+Install
+--------------
+
+Use pip to (un)install::
+
+ pip install pytest-coverage
+ pip uninstall pytest-coverage
+
+or alternatively use easy_install to install::
+
+ easy_install pytest-coverage
+
+
+Usage
+-------------
+
+To get full test coverage reports for a particular package type::
+
+ pytest --cover-report=report
+
+command line options
+--------------------
+
+
+``--cover=COVERPACKAGES``
+ (multi allowed) only include info from specified package.
+``--cover-report=REPORT_TYPE``
+ html: Directory for html output.
+ report: Output a text report.
+ annotate: Annotate your source code for which lines were executed and which were not.
+ xml: Output an xml report compatible with the cobertura plugin for hudson.
+``--cover-directory=DIRECTORY``
+ Directory for the reports (html / annotate results) defaults to ./coverage
+``--cover-xml-file=XML_FILE``
+ File for the xml report defaults to ./coverage.xml
+``--cover-show-missing``
+ Show missing files
+``--cover-ignore-errors=IGNORE_ERRORS``
+ Ignore errors of finding source files for code.
+
+.. include:: links.txt
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/django.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/django.rst
index 061497b385e..061497b385e 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/django.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/django.rst
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/figleaf.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/figleaf.rst
new file mode 100644
index 00000000000..0c1603ade9f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/figleaf.rst
@@ -0,0 +1,44 @@
+
+report test coverage using the 'figleaf' package.
+=================================================
+
+
+.. contents::
+ :local:
+
+Install
+---------------
+
+To install the plugin issue::
+
+ easy_install pytest-figleaf # or
+ pip install pytest-figleaf
+
+and if you are using pip you can also uninstall::
+
+ pip uninstall pytest-figleaf
+
+
+Usage
+---------------
+
+After installation you can simply type::
+
+ pytest --figleaf [...]
+
+to enable figleaf coverage in your test run. A default ".figleaf" data file
+and "html" directory will be created. You can use command line options
+to control where data and html files are created.
+
+command line options
+--------------------
+
+
+``--figleaf``
+ trace python coverage with figleaf and write HTML for files below the current working dir
+``--fig-data=dir``
+ set tracing file, default: ".figleaf".
+``--fig-html=dir``
+ set html reporting dir, default "html".
+
+.. include:: links.txt
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/helpconfig.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/helpconfig.rst
new file mode 100644
index 00000000000..326b75c4552
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/helpconfig.rst
@@ -0,0 +1,36 @@
+
+provide version info, conftest/environment config names.
+========================================================
+
+
+.. contents::
+ :local:
+
+
+
+command line options
+--------------------
+
+
+``--version``
+ display py lib version and import information.
+``-p name``
+ early-load given plugin (multi-allowed).
+``--trace-config``
+ trace considerations of conftest.py files.
+``--debug``
+ generate and show internal debugging information.
+``--help-config``
+ show available conftest.py and ENV-variable names.
+
+Start improving this plugin in 30 seconds
+=========================================
+
+
+1. Download `pytest_helpconfig.py`_ plugin source code
+2. put it somewhere as ``pytest_helpconfig.py`` into your import path
+3. a subsequent ``pytest`` run will use your local version
+
+Checkout customize_, other plugins_ or `get in contact`_.
+
+.. include:: links.txt
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/index.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/index.rst
index 853a4dce681..853a4dce681 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/index.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/index.rst
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/links.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/links.rst
new file mode 100644
index 00000000000..6dec2b4848a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/links.rst
@@ -0,0 +1,45 @@
+.. _`helpconfig`: helpconfig.html
+.. _`pytest_recwarn.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_recwarn.py
+.. _`unittest`: unittest.html
+.. _`pytest_monkeypatch.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_monkeypatch.py
+.. _`pastebin`: pastebin.html
+.. _`skipping`: skipping.html
+.. _`plugins`: index.html
+.. _`mark`: mark.html
+.. _`tmpdir`: tmpdir.html
+.. _`pytest_doctest.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_doctest.py
+.. _`capture`: capture.html
+.. _`pytest_nose.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_nose.py
+.. _`pytest_restdoc.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_restdoc.py
+.. _`restdoc`: restdoc.html
+.. _`xdist`: xdist.html
+.. _`pytest_pastebin.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_pastebin.py
+.. _`pytest_tmpdir.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_tmpdir.py
+.. _`terminal`: terminal.html
+.. _`pytest_hooklog.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_hooklog.py
+.. _`capturelog`: capturelog.html
+.. _`junitxml`: junitxml.html
+.. _`pytest_skipping.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_skipping.py
+.. _`checkout the pytest development version`: ../../install.html#checkout
+.. _`pytest_helpconfig.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_helpconfig.py
+.. _`oejskit`: oejskit.html
+.. _`doctest`: doctest.html
+.. _`pytest_mark.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_mark.py
+.. _`get in contact`: ../../contact.html
+.. _`pytest_capture.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_capture.py
+.. _`figleaf`: figleaf.html
+.. _`customize`: ../customize.html
+.. _`hooklog`: hooklog.html
+.. _`pytest_terminal.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_terminal.py
+.. _`recwarn`: recwarn.html
+.. _`pytest_pdb.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_pdb.py
+.. _`monkeypatch`: monkeypatch.html
+.. _`coverage`: coverage.html
+.. _`resultlog`: resultlog.html
+.. _`cov`: cov.html
+.. _`pytest_junitxml.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_junitxml.py
+.. _`django`: django.html
+.. _`pytest_unittest.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_unittest.py
+.. _`nose`: nose.html
+.. _`pytest_resultlog.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_resultlog.py
+.. _`pdb`: pdb.html
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/nose.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/nose.rst
new file mode 100644
index 00000000000..9eeae5ff697
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/nose.rst
@@ -0,0 +1,56 @@
+
+nose-compatibility plugin: allow to run nose test suites natively.
+==================================================================
+
+
+.. contents::
+ :local:
+
+This is an experimental plugin for allowing to run tests written
+in 'nosetests' style with ``pytest``.
+
+Usage
+-------------
+
+type::
+
+ pytest # instead of 'nosetests'
+
+and you should be able to run nose style tests and at the same
+time can make full use of pytest's capabilities.
+
+Supported nose Idioms
+----------------------
+
+* setup and teardown at module/class/method level
+* SkipTest exceptions and markers
+* setup/teardown decorators
+* yield-based tests and their setup
+* general usage of nose utilities
+
+Unsupported idioms / issues
+----------------------------------
+
+- nose-style doctests are not collected and executed correctly,
+ also fixtures don't work.
+
+- no nose-configuration is recognized
+
+If you find other issues or have suggestions please run::
+
+ pytest --pastebin=all
+
+and send the resulting URL to a ``pytest`` contact channel,
+at best to the mailing list.
+
+Start improving this plugin in 30 seconds
+=========================================
+
+
+1. Download `pytest_nose.py`_ plugin source code
+2. put it somewhere as ``pytest_nose.py`` into your import path
+3. a subsequent ``pytest`` run will use your local version
+
+Checkout customize_, other plugins_ or `get in contact`_.
+
+.. include:: links.txt
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/oejskit.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/oejskit.rst
index 4995aa17c72..4995aa17c72 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/plugin/oejskit.rst
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/oejskit.rst
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/terminal.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/terminal.rst
new file mode 100644
index 00000000000..e07d4f72183
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/terminal.rst
@@ -0,0 +1,38 @@
+
+Implements terminal reporting of the full testing process.
+==========================================================
+
+
+.. contents::
+ :local:
+
+This is a good source for looking at the various reporting hooks.
+
+command line options
+--------------------
+
+
+``-v, --verbose``
+ increase verbosity.
+``-r chars``
+ show extra test summary info as specified by chars (f)ailed, (s)skipped, (x)failed, (X)passed.
+``-l, --showlocals``
+ show locals in tracebacks (disabled by default).
+``--tb=style``
+ traceback print mode (long/short/line/no).
+``--full-trace``
+ don't cut any tracebacks (default is to cut).
+``--fixtures``
+ show available function arguments, sorted by plugin
+
+Start improving this plugin in 30 seconds
+=========================================
+
+
+1. Download `pytest_terminal.py`_ plugin source code
+2. put it somewhere as ``pytest_terminal.py`` into your import path
+3. a subsequent ``pytest`` run will use your local version
+
+Checkout customize_, other plugins_ or `get in contact`_.
+
+.. include:: links.txt
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/xdist.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/xdist.rst
new file mode 100644
index 00000000000..506d240aee1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/plugin/xdist.rst
@@ -0,0 +1,172 @@
+
+loop on failing tests, distribute test runs to CPUs and hosts.
+==============================================================
+
+
+.. contents::
+ :local:
+
+The `pytest-xdist`_ plugin extends ``pytest`` with some unique
+test execution modes:
+
+* Looponfail: run your tests repeatedly in a subprocess. After each run
+ ``pytest`` waits until a file in your project changes and then re-runs the
+ previously failing tests. This is repeated until all tests pass after which
+ again a full run is performed.
+
+* Load-balancing: if you have multiple CPUs or hosts you can use
+ those for a combined test run. This allows to speed up
+ development or to use special resources of remote machines.
+
+* Multi-Platform coverage: you can specify different Python interpreters
+ or different platforms and run tests in parallel on all of them.
+
+Before running tests remotely, ``pytest`` efficiently synchronizes your
+program source code to the remote place. All test results
+are reported back and displayed to your local test session.
+You may specify different Python versions and interpreters.
+
+.. _`pytest-xdist`: http://pypi.python.org/pypi/pytest-xdist
+
+Usage examples
+---------------------
+
+Speed up test runs by sending tests to multiple CPUs
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+To send tests to multiple CPUs, type::
+
+ pytest -n NUM
+
+Especially for longer running tests or tests requiring
+a lot of IO this can lead to considerable speed ups.
+
+
+Running tests in a Python subprocess
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+To instantiate a python2.4 sub process and send tests to it, you may type::
+
+ pytest -d --tx popen//python=python2.4
+
+This will start a subprocess which is run with the "python2.4"
+Python interpreter, found in your system binary lookup path.
+
+If you prefix the --tx option value like this::
+
+ --tx 3*popen//python=python2.4
+
+then three subprocesses would be created and tests
+will be load-balanced across these three processes.
+
+
+Sending tests to remote SSH accounts
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+Suppose you have a package ``mypkg`` which contains some
+tests that you can successfully run locally. And you
+have a ssh-reachable machine ``myhost``. Then
+you can ad-hoc distribute your tests by typing::
+
+ pytest -d --tx ssh=myhostpopen --rsyncdir mypkg mypkg
+
+This will synchronize your ``mypkg`` package directory
+to a remote ssh account and then locally collect tests
+and send them to remote places for execution.
+
+You can specify multiple ``--rsyncdir`` directories
+to be sent to the remote side.
+
+**NOTE:** For ``pytest`` to collect and send tests correctly
+you not only need to make sure all code and tests
+directories are rsynced, but that any test (sub) directory
+also has an ``__init__.py`` file because internally
+``pytest`` references tests using their fully qualified python
+module path. **You will otherwise get strange errors**
+during setup of the remote side.
+
+Sending tests to remote Socket Servers
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+Download the single-module `socketserver.py`_ Python program
+and run it like this::
+
+ python socketserver.py
+
+It will tell you that it starts listening on the default
+port. You can now on your home machine specify this
+new socket host with something like this::
+
+ pytest -d --tx socket=192.168.1.102:8888 --rsyncdir mypkg mypkg
+
+
+.. _`atonce`:
+
+Running tests on many platforms at once
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+The basic command to run tests on multiple platforms is::
+
+ pytest --dist=each --tx=spec1 --tx=spec2
+
+If you specify a windows host, an OSX host and a Linux
+environment this command will send each tests to all
+platforms - and report back failures from all platforms
+at once. The specifications strings use the `xspec syntax`_.
+
+.. _`xspec syntax`: http://codespeak.net/execnet/trunk/basics.html#xspec
+
+.. _`socketserver.py`: http://codespeak.net/svn/py/dist/py/execnet/script/socketserver.py
+
+.. _`execnet`: http://codespeak.net/execnet
+
+Specifying test exec environments in a conftest.py
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+Instead of specifying command line options, you can
+put options values in a ``conftest.py`` file like this::
+
+ option_tx = ['ssh=myhost//python=python2.7', 'popen//python=python2.7']
+ option_dist = True
+
+Any commandline ``--tx`` specifications will add to the list of
+available execution environments.
+
+Specifying "rsync" dirs in a conftest.py
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+In your ``mypkg/conftest.py`` you may specify directories to synchronise
+or to exclude::
+
+ rsyncdirs = ['.', '../plugins']
+ rsyncignore = ['_cache']
+
+These directory specifications are relative to the directory
+where the ``conftest.py`` is found.
+
+command line options
+--------------------
+
+
+``-f, --looponfail``
+ run tests in subprocess, wait for modified files and re-run failing test set until all pass.
+``-n numprocesses``
+ shortcut for '--dist=load --tx=NUM*popen'
+``--boxed``
+ box each test run in a separate process (unix)
+``--dist=distmode``
+ set mode for distributing tests to exec environments.
+
+ each: send each test to each available environment.
+
+ load: send each test to one available environment so it is run only once.
+
+ (default) no: run tests inprocess, don't distribute.
+``--tx=xspec``
+ add a test execution environment. some examples: --tx popen//python=python2.7 --tx socket=192.168.1.102:8888 --tx ssh=user@codespeak.net//chdir=testcache
+``-d``
+ load-balance tests. shortcut for '--dist=load'
+``--rsyncdir=dir1``
+ add directory for rsyncing to remote tx nodes.
+
+.. include:: links.txt
diff --git a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/test.html b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/test.html
index 7d00f718a67..7d00f718a67 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/doc/en/test/test.html
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/test/test.html
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/tmpdir.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/tmpdir.rst
new file mode 100644
index 00000000000..b8174484e1d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/tmpdir.rst
@@ -0,0 +1,111 @@
+
+.. _`tmpdir handling`:
+.. _tmpdir:
+
+Temporary directories and files
+================================================
+
+The 'tmpdir' fixture
+--------------------
+
+You can use the ``tmpdir`` fixture which will
+provide a temporary directory unique to the test invocation,
+created in the `base temporary directory`_.
+
+``tmpdir`` is a `py.path.local`_ object which offers ``os.path`` methods
+and more. Here is an example test usage::
+
+ # content of test_tmpdir.py
+ import os
+ def test_create_file(tmpdir):
+ p = tmpdir.mkdir("sub").join("hello.txt")
+ p.write("content")
+ assert p.read() == "content"
+ assert len(tmpdir.listdir()) == 1
+ assert 0
+
+Running this would result in a passed test except for the last
+``assert 0`` line which we use to look at values::
+
+ $ pytest test_tmpdir.py
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 1 item
+
+ test_tmpdir.py F [100%]
+
+ ================================= FAILURES =================================
+ _____________________________ test_create_file _____________________________
+
+ tmpdir = local('PYTEST_TMPDIR/test_create_file0')
+
+ def test_create_file(tmpdir):
+ p = tmpdir.mkdir("sub").join("hello.txt")
+ p.write("content")
+ assert p.read() == "content"
+ assert len(tmpdir.listdir()) == 1
+ > assert 0
+ E assert 0
+
+ test_tmpdir.py:7: AssertionError
+ ========================= 1 failed in 0.12 seconds =========================
+
+The 'tmpdir_factory' fixture
+----------------------------
+
+.. versionadded:: 2.8
+
+The ``tmpdir_factory`` is a session-scoped fixture which can be used
+to create arbitrary temporary directories from any other fixture or test.
+
+For example, suppose your test suite needs a large image on disk, which is
+generated procedurally. Instead of computing the same image for each test
+that uses it into its own ``tmpdir``, you can generate it once per-session
+to save time:
+
+.. code-block:: python
+
+ # contents of conftest.py
+ import pytest
+
+ @pytest.fixture(scope='session')
+ def image_file(tmpdir_factory):
+ img = compute_expensive_image()
+ fn = tmpdir_factory.mktemp('data').join('img.png')
+ img.save(str(fn))
+ return fn
+
+ # contents of test_image.py
+ def test_histogram(image_file):
+ img = load_image(image_file)
+ # compute and test histogram
+
+``tmpdir_factory`` instances have the following methods:
+
+.. currentmodule:: _pytest.tmpdir
+
+.. automethod:: TempdirFactory.mktemp
+.. automethod:: TempdirFactory.getbasetemp
+
+.. _`base temporary directory`:
+
+The default base temporary directory
+-----------------------------------------------
+
+Temporary directories are by default created as sub-directories of
+the system temporary directory. The base name will be ``pytest-NUM`` where
+``NUM`` will be incremented with each test run. Moreover, entries older
+than 3 temporary directories will be removed.
+
+You can override the default temporary directory setting like this::
+
+ pytest --basetemp=mydir
+
+When distributing tests on the local machine, ``pytest`` takes care to
+configure a basetemp directory for the sub processes such that all temporary
+data lands below a single per-test run basetemp directory.
+
+.. _`py.path.local`: http://py.rtfd.org/en/latest/path.html
+
+
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/unittest.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/unittest.rst
new file mode 100644
index 00000000000..b44bda44fa8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/unittest.rst
@@ -0,0 +1,245 @@
+
+.. _`unittest.TestCase`:
+.. _`unittest`:
+
+unittest.TestCase Support
+=========================
+
+``pytest`` supports running Python ``unittest``-based tests out of the box.
+It's meant for leveraging existing ``unittest``-based test suites
+to use pytest as a test runner and also allow to incrementally adapt
+the test suite to take full advantage of pytest's features.
+
+To run an existing ``unittest``-style test suite using ``pytest``, type::
+
+ pytest tests
+
+
+pytest will automatically collect ``unittest.TestCase`` subclasses and
+their ``test`` methods in ``test_*.py`` or ``*_test.py`` files.
+
+Almost all ``unittest`` features are supported:
+
+* ``@unittest.skip`` style decorators;
+* ``setUp/tearDown``;
+* ``setUpClass/tearDownClass()``;
+
+.. _`load_tests protocol`: https://docs.python.org/3/library/unittest.html#load-tests-protocol
+.. _`setUpModule/tearDownModule`: https://docs.python.org/3/library/unittest.html#setupmodule-and-teardownmodule
+.. _`subtests`: https://docs.python.org/3/library/unittest.html#distinguishing-test-iterations-using-subtests
+
+Up to this point pytest does not have support for the following features:
+
+* `load_tests protocol`_;
+* `setUpModule/tearDownModule`_;
+* `subtests`_;
+
+Benefits out of the box
+-----------------------
+
+By running your test suite with pytest you can make use of several features,
+in most cases without having to modify existing code:
+
+* Obtain :ref:`more informative tracebacks <tbreportdemo>`;
+* :ref:`stdout and stderr <captures>` capturing;
+* :ref:`Test selection options <select-tests>` using ``-k`` and ``-m`` flags;
+* :ref:`maxfail`;
+* :ref:`--pdb <pdb-option>` command-line option for debugging on test failures
+ (see :ref:`note <pdb-unittest-note>` below);
+* Distribute tests to multiple CPUs using the `pytest-xdist <http://pypi.python.org/pypi/pytest-xdist>`_ plugin;
+* Use :ref:`plain assert-statements <assert>` instead of ``self.assert*`` functions (`unittest2pytest
+ <https://pypi.python.org/pypi/unittest2pytest/>`__ is immensely helpful in this);
+
+
+pytest features in ``unittest.TestCase`` subclasses
+---------------------------------------------------
+
+The following pytest features work in ``unittest.TestCase`` subclasses:
+
+* :ref:`Marks <mark>`: :ref:`skip <skip>`, :ref:`skipif <skipif>`, :ref:`xfail <xfail>`;
+* :ref:`Auto-use fixtures <mixing-fixtures>`;
+
+The following pytest features **do not** work, and probably
+never will due to different design philosophies:
+
+* :ref:`Fixtures <fixture>` (except for ``autouse`` fixtures, see :ref:`below <mixing-fixtures>`);
+* :ref:`Parametrization <parametrize>`;
+* :ref:`Custom hooks <writing-plugins>`;
+
+
+Third party plugins may or may not work well, depending on the plugin and the test suite.
+
+.. _mixing-fixtures:
+
+Mixing pytest fixtures into ``unittest.TestCase`` subclasses using marks
+------------------------------------------------------------------------
+
+Running your unittest with ``pytest`` allows you to use its
+:ref:`fixture mechanism <fixture>` with ``unittest.TestCase`` style
+tests. Assuming you have at least skimmed the pytest fixture features,
+let's jump-start into an example that integrates a pytest ``db_class``
+fixture, setting up a class-cached database object, and then reference
+it from a unittest-style test::
+
+ # content of conftest.py
+
+ # we define a fixture function below and it will be "used" by
+ # referencing its name from tests
+
+ import pytest
+
+ @pytest.fixture(scope="class")
+ def db_class(request):
+ class DummyDB(object):
+ pass
+ # set a class attribute on the invoking test context
+ request.cls.db = DummyDB()
+
+This defines a fixture function ``db_class`` which - if used - is
+called once for each test class and which sets the class-level
+``db`` attribute to a ``DummyDB`` instance. The fixture function
+achieves this by receiving a special ``request`` object which gives
+access to :ref:`the requesting test context <request-context>` such
+as the ``cls`` attribute, denoting the class from which the fixture
+is used. This architecture de-couples fixture writing from actual test
+code and allows re-use of the fixture by a minimal reference, the fixture
+name. So let's write an actual ``unittest.TestCase`` class using our
+fixture definition::
+
+ # content of test_unittest_db.py
+
+ import unittest
+ import pytest
+
+ @pytest.mark.usefixtures("db_class")
+ class MyTest(unittest.TestCase):
+ def test_method1(self):
+ assert hasattr(self, "db")
+ assert 0, self.db # fail for demo purposes
+
+ def test_method2(self):
+ assert 0, self.db # fail for demo purposes
+
+The ``@pytest.mark.usefixtures("db_class")`` class-decorator makes sure that
+the pytest fixture function ``db_class`` is called once per class.
+Due to the deliberately failing assert statements, we can take a look at
+the ``self.db`` values in the traceback::
+
+ $ pytest test_unittest_db.py
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 2 items
+
+ test_unittest_db.py FF [100%]
+
+ ================================= FAILURES =================================
+ ___________________________ MyTest.test_method1 ____________________________
+
+ self = <test_unittest_db.MyTest testMethod=test_method1>
+
+ def test_method1(self):
+ assert hasattr(self, "db")
+ > assert 0, self.db # fail for demo purposes
+ E AssertionError: <conftest.db_class.<locals>.DummyDB object at 0xdeadbeef>
+ E assert 0
+
+ test_unittest_db.py:9: AssertionError
+ ___________________________ MyTest.test_method2 ____________________________
+
+ self = <test_unittest_db.MyTest testMethod=test_method2>
+
+ def test_method2(self):
+ > assert 0, self.db # fail for demo purposes
+ E AssertionError: <conftest.db_class.<locals>.DummyDB object at 0xdeadbeef>
+ E assert 0
+
+ test_unittest_db.py:12: AssertionError
+ ========================= 2 failed in 0.12 seconds =========================
+
+This default pytest traceback shows that the two test methods
+share the same ``self.db`` instance which was our intention
+when writing the class-scoped fixture function above.
+
+
+Using autouse fixtures and accessing other fixtures
+---------------------------------------------------
+
+Although it's usually better to explicitly declare use of fixtures you need
+for a given test, you may sometimes want to have fixtures that are
+automatically used in a given context. After all, the traditional
+style of unittest-setup mandates the use of this implicit fixture writing
+and chances are, you are used to it or like it.
+
+You can flag fixture functions with ``@pytest.fixture(autouse=True)``
+and define the fixture function in the context where you want it used.
+Let's look at an ``initdir`` fixture which makes all test methods of a
+``TestCase`` class execute in a temporary directory with a
+pre-initialized ``samplefile.ini``. Our ``initdir`` fixture itself uses
+the pytest builtin :ref:`tmpdir <tmpdir>` fixture to delegate the
+creation of a per-test temporary directory::
+
+ # content of test_unittest_cleandir.py
+ import pytest
+ import unittest
+
+ class MyTest(unittest.TestCase):
+
+ @pytest.fixture(autouse=True)
+ def initdir(self, tmpdir):
+ tmpdir.chdir() # change to pytest-provided temporary directory
+ tmpdir.join("samplefile.ini").write("# testdata")
+
+ def test_method(self):
+ with open("samplefile.ini") as f:
+ s = f.read()
+ assert "testdata" in s
+
+Due to the ``autouse`` flag the ``initdir`` fixture function will be
+used for all methods of the class where it is defined. This is a
+shortcut for using a ``@pytest.mark.usefixtures("initdir")`` marker
+on the class like in the previous example.
+
+Running this test module ...::
+
+ $ pytest -q test_unittest_cleandir.py
+ . [100%]
+ 1 passed in 0.12 seconds
+
+... gives us one passed test because the ``initdir`` fixture function
+was executed ahead of the ``test_method``.
+
+.. note::
+
+ ``unittest.TestCase`` methods cannot directly receive fixture
+ arguments as implementing that is likely to inflict
+ on the ability to run general unittest.TestCase test suites.
+
+ The above ``usefixtures`` and ``autouse`` examples should help to mix in
+ pytest fixtures into unittest suites.
+
+ You can also gradually move away from subclassing from ``unittest.TestCase`` to *plain asserts*
+ and then start to benefit from the full pytest feature set step by step.
+
+.. _pdb-unittest-note:
+
+.. note::
+
+ Running tests from ``unittest.TestCase`` subclasses with ``--pdb`` will
+ disable tearDown and cleanup methods for the case that an Exception
+ occurs. This allows proper post mortem debugging for all applications
+ which have significant logic in their tearDown machinery. However,
+ supporting this feature has the following side effect: If people
+ overwrite ``unittest.TestCase`` ``__call__`` or ``run``, they need to
+ to overwrite ``debug`` in the same way (this is also true for standard
+ unittest).
+
+.. note::
+
+ Due to architectural differences between the two frameworks, setup and
+ teardown for ``unittest``-based tests is performed during the ``call`` phase
+ of testing instead of in ``pytest``'s standard ``setup`` and ``teardown``
+ stages. This can be important to understand in some situations, particularly
+ when reasoning about errors. For example, if a ``unittest``-based suite
+ exhibits errors during setup, ``pytest`` will report no errors during its
+ ``setup`` phase and will instead raise the error during ``call``.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/usage.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/usage.rst
new file mode 100644
index 00000000000..6091db8be38
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/usage.rst
@@ -0,0 +1,392 @@
+
+.. _usage:
+
+Usage and Invocations
+==========================================
+
+
+.. _cmdline:
+
+Calling pytest through ``python -m pytest``
+-----------------------------------------------------
+
+.. versionadded:: 2.0
+
+You can invoke testing through the Python interpreter from the command line::
+
+ python -m pytest [...]
+
+This is almost equivalent to invoking the command line script ``pytest [...]``
+directly, except that calling via ``python`` will also add the current directory to ``sys.path``.
+
+Possible exit codes
+--------------------------------------------------------------
+
+Running ``pytest`` can result in six different exit codes:
+
+:Exit code 0: All tests were collected and passed successfully
+:Exit code 1: Tests were collected and run but some of the tests failed
+:Exit code 2: Test execution was interrupted by the user
+:Exit code 3: Internal error happened while executing tests
+:Exit code 4: pytest command line usage error
+:Exit code 5: No tests were collected
+
+Getting help on version, option names, environment variables
+--------------------------------------------------------------
+
+::
+
+ pytest --version # shows where pytest was imported from
+ pytest --fixtures # show available builtin function arguments
+ pytest -h | --help # show help on command line and config file options
+
+
+.. _maxfail:
+
+Stopping after the first (or N) failures
+---------------------------------------------------
+
+To stop the testing process after the first (N) failures::
+
+ pytest -x # stop after first failure
+ pytest --maxfail=2 # stop after two failures
+
+.. _select-tests:
+
+Specifying tests / selecting tests
+---------------------------------------------------
+
+Pytest supports several ways to run and select tests from the command-line.
+
+**Run tests in a module**
+
+::
+
+ pytest test_mod.py
+
+**Run tests in a directory**
+
+::
+
+ pytest testing/
+
+**Run tests by keyword expressions**
+
+::
+
+ pytest -k "MyClass and not method"
+
+This will run tests which contain names that match the given *string expression*, which can
+include Python operators that use filenames, class names and function names as variables.
+The example above will run ``TestMyClass.test_something`` but not ``TestMyClass.test_method_simple``.
+
+.. _nodeids:
+
+**Run tests by node ids**
+
+Each collected test is assigned a unique ``nodeid`` which consist of the module filename followed
+by specifiers like class names, function names and parameters from parametrization, separated by ``::`` characters.
+
+To run a specific test within a module::
+
+ pytest test_mod.py::test_func
+
+
+Another example specifying a test method in the command line::
+
+ pytest test_mod.py::TestClass::test_method
+
+**Run tests by marker expressions**
+
+::
+
+ pytest -m slow
+
+Will run all tests which are decorated with the ``@pytest.mark.slow`` decorator.
+
+For more information see :ref:`marks <mark>`.
+
+**Run tests from packages**
+
+::
+
+ pytest --pyargs pkg.testing
+
+This will import ``pkg.testing`` and use its filesystem location to find and run tests from.
+
+
+Modifying Python traceback printing
+----------------------------------------------
+
+Examples for modifying traceback printing::
+
+ pytest --showlocals # show local variables in tracebacks
+ pytest -l # show local variables (shortcut)
+
+ pytest --tb=auto # (default) 'long' tracebacks for the first and last
+ # entry, but 'short' style for the other entries
+ pytest --tb=long # exhaustive, informative traceback formatting
+ pytest --tb=short # shorter traceback format
+ pytest --tb=line # only one line per failure
+ pytest --tb=native # Python standard library formatting
+ pytest --tb=no # no traceback at all
+
+The ``--full-trace`` causes very long traces to be printed on error (longer
+than ``--tb=long``). It also ensures that a stack trace is printed on
+**KeyboardInterrupt** (Ctrl+C).
+This is very useful if the tests are taking too long and you interrupt them
+with Ctrl+C to find out where the tests are *hanging*. By default no output
+will be shown (because KeyboardInterrupt is caught by pytest). By using this
+option you make sure a trace is shown.
+
+
+.. _pdb-option:
+
+Dropping to PDB_ (Python Debugger) on failures
+-----------------------------------------------
+
+.. _PDB: http://docs.python.org/library/pdb.html
+
+Python comes with a builtin Python debugger called PDB_. ``pytest``
+allows one to drop into the PDB_ prompt via a command line option::
+
+ pytest --pdb
+
+This will invoke the Python debugger on every failure. Often you might
+only want to do this for the first failing test to understand a certain
+failure situation::
+
+ pytest -x --pdb # drop to PDB on first failure, then end test session
+ pytest --pdb --maxfail=3 # drop to PDB for first three failures
+
+Note that on any failure the exception information is stored on
+``sys.last_value``, ``sys.last_type`` and ``sys.last_traceback``. In
+interactive use, this allows one to drop into postmortem debugging with
+any debug tool. One can also manually access the exception information,
+for example::
+
+ >>> import sys
+ >>> sys.last_traceback.tb_lineno
+ 42
+ >>> sys.last_value
+ AssertionError('assert result == "ok"',)
+
+.. _breakpoints:
+
+Setting breakpoints
+-------------------
+
+.. versionadded: 2.4.0
+
+To set a breakpoint in your code use the native Python ``import pdb;pdb.set_trace()`` call
+in your code and pytest automatically disables its output capture for that test:
+
+* Output capture in other tests is not affected.
+* Any prior test output that has already been captured and will be processed as
+ such.
+* Any later output produced within the same test will not be captured and will
+ instead get sent directly to ``sys.stdout``. Note that this holds true even
+ for test output occurring after you exit the interactive PDB_ tracing session
+ and continue with the regular test run.
+
+.. _durations:
+
+Profiling test execution duration
+-------------------------------------
+
+.. versionadded: 2.2
+
+To get a list of the slowest 10 test durations::
+
+ pytest --durations=10
+
+
+Creating JUnitXML format files
+----------------------------------------------------
+
+To create result files which can be read by Jenkins_ or other Continuous
+integration servers, use this invocation::
+
+ pytest --junitxml=path
+
+to create an XML file at ``path``.
+
+.. versionadded:: 3.1
+
+To set the name of the root test suite xml item, you can configure the ``junit_suite_name`` option in your config file:
+
+.. code-block:: ini
+
+ [pytest]
+ junit_suite_name = my_suite
+
+record_xml_property
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. versionadded:: 2.8
+
+If you want to log additional information for a test, you can use the
+``record_xml_property`` fixture:
+
+.. code-block:: python
+
+ def test_function(record_xml_property):
+ record_xml_property("example_key", 1)
+ assert 0
+
+This will add an extra property ``example_key="1"`` to the generated
+``testcase`` tag:
+
+.. code-block:: xml
+
+ <testcase classname="test_function" file="test_function.py" line="0" name="test_function" time="0.0009">
+ <properties>
+ <property name="example_key" value="1" />
+ </properties>
+ </testcase>
+
+.. warning::
+
+ ``record_xml_property`` is an experimental feature, and its interface might be replaced
+ by something more powerful and general in future versions. The
+ functionality per-se will be kept, however.
+
+ Currently it does not work when used with the ``pytest-xdist`` plugin.
+
+ Also please note that using this feature will break any schema verification.
+ This might be a problem when used with some CI servers.
+
+LogXML: add_global_property
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. versionadded:: 3.0
+
+If you want to add a properties node in the testsuite level, which may contains properties that are relevant
+to all testcases you can use ``LogXML.add_global_properties``
+
+.. code-block:: python
+
+ import pytest
+
+ @pytest.fixture(scope="session")
+ def log_global_env_facts(f):
+
+ if pytest.config.pluginmanager.hasplugin('junitxml'):
+ my_junit = getattr(pytest.config, '_xml', None)
+
+ my_junit.add_global_property('ARCH', 'PPC')
+ my_junit.add_global_property('STORAGE_TYPE', 'CEPH')
+
+ @pytest.mark.usefixtures(log_global_env_facts)
+ def start_and_prepare_env():
+ pass
+
+ class TestMe(object):
+ def test_foo(self):
+ assert True
+
+This will add a property node below the testsuite node to the generated xml:
+
+.. code-block:: xml
+
+ <testsuite errors="0" failures="0" name="pytest" skips="0" tests="1" time="0.006">
+ <properties>
+ <property name="ARCH" value="PPC"/>
+ <property name="STORAGE_TYPE" value="CEPH"/>
+ </properties>
+ <testcase classname="test_me.TestMe" file="test_me.py" line="16" name="test_foo" time="0.000243663787842"/>
+ </testsuite>
+
+.. warning::
+
+ This is an experimental feature, and its interface might be replaced
+ by something more powerful and general in future versions. The
+ functionality per-se will be kept.
+
+Creating resultlog format files
+----------------------------------------------------
+
+.. deprecated:: 3.0
+
+ This option is rarely used and is scheduled for removal in 4.0.
+
+ An alternative for users which still need similar functionality is to use the
+ `pytest-tap <https://pypi.python.org/pypi/pytest-tap>`_ plugin which provides
+ a stream of test data.
+
+ If you have any concerns, please don't hesitate to
+ `open an issue <https://github.com/pytest-dev/pytest/issues>`_.
+
+To create plain-text machine-readable result files you can issue::
+
+ pytest --resultlog=path
+
+and look at the content at the ``path`` location. Such files are used e.g.
+by the `PyPy-test`_ web page to show test results over several revisions.
+
+.. _`PyPy-test`: http://buildbot.pypy.org/summary
+
+
+Sending test report to online pastebin service
+-----------------------------------------------------
+
+**Creating a URL for each test failure**::
+
+ pytest --pastebin=failed
+
+This will submit test run information to a remote Paste service and
+provide a URL for each failure. You may select tests as usual or add
+for example ``-x`` if you only want to send one particular failure.
+
+**Creating a URL for a whole test session log**::
+
+ pytest --pastebin=all
+
+Currently only pasting to the http://bpaste.net service is implemented.
+
+Disabling plugins
+-----------------
+
+To disable loading specific plugins at invocation time, use the ``-p`` option
+together with the prefix ``no:``.
+
+Example: to disable loading the plugin ``doctest``, which is responsible for
+executing doctest tests from text files, invoke pytest like this::
+
+ pytest -p no:doctest
+
+.. _`pytest.main-usage`:
+
+Calling pytest from Python code
+----------------------------------------------------
+
+.. versionadded:: 2.0
+
+You can invoke ``pytest`` from Python code directly::
+
+ pytest.main()
+
+this acts as if you would call "pytest" from the command line.
+It will not raise ``SystemExit`` but return the exitcode instead.
+You can pass in options and arguments::
+
+ pytest.main(['-x', 'mytestdir'])
+
+You can specify additional plugins to ``pytest.main``::
+
+ # content of myinvoke.py
+ import pytest
+ class MyPlugin(object):
+ def pytest_sessionfinish(self):
+ print("*** test run reporting finishing")
+
+ pytest.main(["-qq"], plugins=[MyPlugin()])
+
+Running it will show that ``MyPlugin`` was added and its
+hook was invoked::
+
+ $ python myinvoke.py
+ *** test run reporting finishing
+
+
+.. include:: links.inc
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/warnings.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/warnings.rst
new file mode 100644
index 00000000000..f249d7e3b2f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/warnings.rst
@@ -0,0 +1,299 @@
+.. _`warnings`:
+
+Warnings Capture
+================
+
+.. versionadded:: 3.1
+
+Starting from version ``3.1``, pytest now automatically catches warnings during test execution
+and displays them at the end of the session::
+
+ # content of test_show_warnings.py
+ import warnings
+
+ def api_v1():
+ warnings.warn(UserWarning("api v1, should use functions from v2"))
+ return 1
+
+ def test_one():
+ assert api_v1() == 1
+
+Running pytest now produces this output::
+
+ $ pytest test_show_warnings.py
+ =========================== test session starts ============================
+ platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
+ rootdir: $REGENDOC_TMPDIR, inifile:
+ collected 1 item
+
+ test_show_warnings.py . [100%]
+
+ ============================= warnings summary =============================
+ test_show_warnings.py::test_one
+ $REGENDOC_TMPDIR/test_show_warnings.py:4: UserWarning: api v1, should use functions from v2
+ warnings.warn(UserWarning("api v1, should use functions from v2"))
+
+ -- Docs: http://doc.pytest.org/en/latest/warnings.html
+ =================== 1 passed, 1 warnings in 0.12 seconds ===================
+
+Pytest by default catches all warnings except for ``DeprecationWarning`` and ``PendingDeprecationWarning``.
+
+The ``-W`` flag can be passed to control which warnings will be displayed or even turn
+them into errors::
+
+ $ pytest -q test_show_warnings.py -W error::UserWarning
+ F [100%]
+ ================================= FAILURES =================================
+ _________________________________ test_one _________________________________
+
+ def test_one():
+ > assert api_v1() == 1
+
+ test_show_warnings.py:8:
+ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
+
+ def api_v1():
+ > warnings.warn(UserWarning("api v1, should use functions from v2"))
+ E UserWarning: api v1, should use functions from v2
+
+ test_show_warnings.py:4: UserWarning
+ 1 failed in 0.12 seconds
+
+The same option can be set in the ``pytest.ini`` file using the ``filterwarnings`` ini option.
+For example, the configuration below will ignore all user warnings, but will transform
+all other warnings into errors.
+
+.. code-block:: ini
+
+ [pytest]
+ filterwarnings =
+ error
+ ignore::UserWarning
+
+
+When a warning matches more than one option in the list, the action for the last matching option
+is performed.
+
+Both ``-W`` command-line option and ``filterwarnings`` ini option are based on Python's own
+`-W option`_ and `warnings.simplefilter`_, so please refer to those sections in the Python
+documentation for other examples and advanced usage.
+
+``@pytest.mark.filterwarnings``
+-------------------------------
+
+.. versionadded:: 3.2
+
+You can use the ``@pytest.mark.filterwarnings`` to add warning filters to specific test items,
+allowing you to have finer control of which warnings should be captured at test, class or
+even module level:
+
+.. code-block:: python
+
+ import warnings
+
+ def api_v1():
+ warnings.warn(UserWarning("api v1, should use functions from v2"))
+ return 1
+
+ @pytest.mark.filterwarnings('ignore:api v1')
+ def test_one():
+ assert api_v1() == 1
+
+
+Filters applied using a mark take precedence over filters passed on the command line or configured
+by the ``filterwarnings`` ini option.
+
+You may apply a filter to all tests of a class by using the ``filterwarnings`` mark as a class
+decorator or to all tests in a module by setting the ``pytestmark`` variable:
+
+.. code-block:: python
+
+ # turns all warnings into errors for this module
+ pytestmark = pytest.mark.filterwarnings('error')
+
+
+.. note::
+
+ ``DeprecationWarning`` and ``PendingDeprecationWarning`` are hidden by the standard library
+ by default so you have to explicitly configure them to be displayed in your ``pytest.ini``:
+
+ .. code-block:: ini
+
+ [pytest]
+ filterwarnings =
+ once::DeprecationWarning
+ once::PendingDeprecationWarning
+
+
+*Credits go to Florian Schulze for the reference implementation in the* `pytest-warnings`_
+*plugin.*
+
+.. _`-W option`: https://docs.python.org/3/using/cmdline.html?highlight=#cmdoption-W
+.. _warnings.simplefilter: https://docs.python.org/3/library/warnings.html#warnings.simplefilter
+.. _`pytest-warnings`: https://github.com/fschulze/pytest-warnings
+
+
+Disabling warning capture
+-------------------------
+
+This feature is enabled by default but can be disabled entirely in your ``pytest.ini`` file with:
+
+ .. code-block:: ini
+
+ [pytest]
+ addopts = -p no:warnings
+
+Or passing ``-p no:warnings`` in the command-line.
+
+.. _`asserting warnings`:
+
+.. _assertwarnings:
+
+.. _`asserting warnings with the warns function`:
+
+.. _warns:
+
+Asserting warnings with the warns function
+-----------------------------------------------
+
+.. versionadded:: 2.8
+
+You can check that code raises a particular warning using ``pytest.warns``,
+which works in a similar manner to :ref:`raises <assertraises>`::
+
+ import warnings
+ import pytest
+
+ def test_warning():
+ with pytest.warns(UserWarning):
+ warnings.warn("my warning", UserWarning)
+
+The test will fail if the warning in question is not raised. The keyword
+argument ``match`` to assert that the exception matches a text or regex::
+
+ >>> with warns(UserWarning, match='must be 0 or None'):
+ ... warnings.warn("value must be 0 or None", UserWarning)
+
+ >>> with warns(UserWarning, match=r'must be \d+$'):
+ ... warnings.warn("value must be 42", UserWarning)
+
+ >>> with warns(UserWarning, match=r'must be \d+$'):
+ ... warnings.warn("this is not here", UserWarning)
+ Traceback (most recent call last):
+ ...
+ Failed: DID NOT WARN. No warnings of type ...UserWarning... was emitted...
+
+You can also call ``pytest.warns`` on a function or code string::
+
+ pytest.warns(expected_warning, func, *args, **kwargs)
+ pytest.warns(expected_warning, "func(*args, **kwargs)")
+
+The function also returns a list of all raised warnings (as
+``warnings.WarningMessage`` objects), which you can query for
+additional information::
+
+ with pytest.warns(RuntimeWarning) as record:
+ warnings.warn("another warning", RuntimeWarning)
+
+ # check that only one warning was raised
+ assert len(record) == 1
+ # check that the message matches
+ assert record[0].message.args[0] == "another warning"
+
+Alternatively, you can examine raised warnings in detail using the
+:ref:`recwarn <recwarn>` fixture (see below).
+
+.. note::
+ ``DeprecationWarning`` and ``PendingDeprecationWarning`` are treated
+ differently; see :ref:`ensuring_function_triggers`.
+
+.. _`recording warnings`:
+
+.. _recwarn:
+
+Recording warnings
+------------------------
+
+You can record raised warnings either using ``pytest.warns`` or with
+the ``recwarn`` fixture.
+
+To record with ``pytest.warns`` without asserting anything about the warnings,
+pass ``None`` as the expected warning type::
+
+ with pytest.warns(None) as record:
+ warnings.warn("user", UserWarning)
+ warnings.warn("runtime", RuntimeWarning)
+
+ assert len(record) == 2
+ assert str(record[0].message) == "user"
+ assert str(record[1].message) == "runtime"
+
+The ``recwarn`` fixture will record warnings for the whole function::
+
+ import warnings
+
+ def test_hello(recwarn):
+ warnings.warn("hello", UserWarning)
+ assert len(recwarn) == 1
+ w = recwarn.pop(UserWarning)
+ assert issubclass(w.category, UserWarning)
+ assert str(w.message) == "hello"
+ assert w.filename
+ assert w.lineno
+
+Both ``recwarn`` and ``pytest.warns`` return the same interface for recorded
+warnings: a WarningsRecorder instance. To view the recorded warnings, you can
+iterate over this instance, call ``len`` on it to get the number of recorded
+warnings, or index into it to get a particular recorded warning. It also
+provides these methods:
+
+.. autoclass:: _pytest.recwarn.WarningsRecorder()
+ :members:
+
+Each recorded warning has the attributes ``message``, ``category``,
+``filename``, ``lineno``, ``file``, and ``line``. The ``category`` is the
+class of the warning. The ``message`` is the warning itself; calling
+``str(message)`` will return the actual message of the warning.
+
+.. note::
+ :class:`RecordedWarning` was changed from a plain class to a namedtuple in pytest 3.1
+
+.. note::
+ ``DeprecationWarning`` and ``PendingDeprecationWarning`` are treated
+ differently; see :ref:`ensuring_function_triggers`.
+
+.. _`ensuring a function triggers a deprecation warning`:
+
+.. _ensuring_function_triggers:
+
+Ensuring a function triggers a deprecation warning
+-------------------------------------------------------
+
+You can also call a global helper for checking
+that a certain function call triggers a ``DeprecationWarning`` or
+``PendingDeprecationWarning``::
+
+ import pytest
+
+ def test_global():
+ pytest.deprecated_call(myfunction, 17)
+
+By default, ``DeprecationWarning`` and ``PendingDeprecationWarning`` will not be
+caught when using ``pytest.warns`` or ``recwarn`` because default Python warnings filters hide
+them. If you wish to record them in your own code, use the
+command ``warnings.simplefilter('always')``::
+
+ import warnings
+ import pytest
+
+ def test_deprecation(recwarn):
+ warnings.simplefilter('always')
+ warnings.warn("deprecated", DeprecationWarning)
+ assert len(recwarn) == 1
+ assert recwarn.pop(DeprecationWarning)
+
+You can also use it as a contextmanager::
+
+ def test_global():
+ with pytest.deprecated_call():
+ myobject.deprecated_method()
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/writing_plugins.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/writing_plugins.rst
new file mode 100644
index 00000000000..eb525583000
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/writing_plugins.rst
@@ -0,0 +1,739 @@
+.. _plugins:
+.. _`writing-plugins`:
+
+Writing plugins
+===============
+
+It is easy to implement `local conftest plugins`_ for your own project
+or `pip-installable plugins`_ that can be used throughout many projects,
+including third party projects. Please refer to :ref:`using plugins` if you
+only want to use but not write plugins.
+
+A plugin contains one or multiple hook functions. :ref:`Writing hooks <writinghooks>`
+explains the basics and details of how you can write a hook function yourself.
+``pytest`` implements all aspects of configuration, collection, running and
+reporting by calling `well specified hooks`_ of the following plugins:
+
+* :ref:`builtin plugins`: loaded from pytest's internal ``_pytest`` directory.
+
+* :ref:`external plugins <extplugins>`: modules discovered through
+ `setuptools entry points`_
+
+* `conftest.py plugins`_: modules auto-discovered in test directories
+
+In principle, each hook call is a ``1:N`` Python function call where ``N`` is the
+number of registered implementation functions for a given specification.
+All specifications and implementations follow the ``pytest_`` prefix
+naming convention, making them easy to distinguish and find.
+
+.. _`pluginorder`:
+
+Plugin discovery order at tool startup
+--------------------------------------
+
+``pytest`` loads plugin modules at tool startup in the following way:
+
+* by loading all builtin plugins
+
+* by loading all plugins registered through `setuptools entry points`_.
+
+* by pre-scanning the command line for the ``-p name`` option
+ and loading the specified plugin before actual command line parsing.
+
+* by loading all :file:`conftest.py` files as inferred by the command line
+ invocation:
+
+ - if no test paths are specified use current dir as a test path
+ - if exists, load ``conftest.py`` and ``test*/conftest.py`` relative
+ to the directory part of the first test path.
+
+ Note that pytest does not find ``conftest.py`` files in deeper nested
+ sub directories at tool startup. It is usually a good idea to keep
+ your ``conftest.py`` file in the top level test or project root directory.
+
+* by recursively loading all plugins specified by the
+ ``pytest_plugins`` variable in ``conftest.py`` files
+
+
+.. _`pytest/plugin`: http://bitbucket.org/pytest-dev/pytest/src/tip/pytest/plugin/
+.. _`conftest.py plugins`:
+.. _`localplugin`:
+.. _`local conftest plugins`:
+
+conftest.py: local per-directory plugins
+----------------------------------------
+
+Local ``conftest.py`` plugins contain directory-specific hook
+implementations. Hook Session and test running activities will
+invoke all hooks defined in ``conftest.py`` files closer to the
+root of the filesystem. Example of implementing the
+``pytest_runtest_setup`` hook so that is called for tests in the ``a``
+sub directory but not for other directories::
+
+ a/conftest.py:
+ def pytest_runtest_setup(item):
+ # called for running each test in 'a' directory
+ print ("setting up", item)
+
+ a/test_sub.py:
+ def test_sub():
+ pass
+
+ test_flat.py:
+ def test_flat():
+ pass
+
+Here is how you might run it::
+
+ pytest test_flat.py # will not show "setting up"
+ pytest a/test_sub.py # will show "setting up"
+
+.. note::
+ If you have ``conftest.py`` files which do not reside in a
+ python package directory (i.e. one containing an ``__init__.py``) then
+ "import conftest" can be ambiguous because there might be other
+ ``conftest.py`` files as well on your ``PYTHONPATH`` or ``sys.path``.
+ It is thus good practice for projects to either put ``conftest.py``
+ under a package scope or to never import anything from a
+ ``conftest.py`` file.
+
+ See also: :ref:`pythonpath`.
+
+
+Writing your own plugin
+-----------------------
+
+.. _`setuptools`: http://pypi.python.org/pypi/setuptools
+
+If you want to write a plugin, there are many real-life examples
+you can copy from:
+
+* a custom collection example plugin: :ref:`yaml plugin`
+* around 20 :ref:`builtin plugins` which provide pytest's own functionality
+* many `external plugins <http://plugincompat.herokuapp.com>`_ providing additional features
+
+All of these plugins implement the documented `well specified hooks`_
+to extend and add functionality.
+
+.. note::
+ Make sure to check out the excellent
+ `cookiecutter-pytest-plugin <https://github.com/pytest-dev/cookiecutter-pytest-plugin>`_
+ project, which is a `cookiecutter template <https://github.com/audreyr/cookiecutter>`_
+ for authoring plugins.
+
+ The template provides an excellent starting point with a working plugin,
+ tests running with tox, a comprehensive README file as well as a
+ pre-configured entry-point.
+
+Also consider :ref:`contributing your plugin to pytest-dev<submitplugin>`
+once it has some happy users other than yourself.
+
+
+.. _`setuptools entry points`:
+.. _`pip-installable plugins`:
+
+Making your plugin installable by others
+----------------------------------------
+
+If you want to make your plugin externally available, you
+may define a so-called entry point for your distribution so
+that ``pytest`` finds your plugin module. Entry points are
+a feature that is provided by `setuptools`_. pytest looks up
+the ``pytest11`` entrypoint to discover its
+plugins and you can thus make your plugin available by defining
+it in your setuptools-invocation:
+
+.. sourcecode:: python
+
+ # sample ./setup.py file
+ from setuptools import setup
+
+ setup(
+ name="myproject",
+ packages = ['myproject']
+
+ # the following makes a plugin available to pytest
+ entry_points = {
+ 'pytest11': [
+ 'name_of_plugin = myproject.pluginmodule',
+ ]
+ },
+
+ # custom PyPI classifier for pytest plugins
+ classifiers=[
+ "Framework :: Pytest",
+ ],
+ )
+
+If a package is installed this way, ``pytest`` will load
+``myproject.pluginmodule`` as a plugin which can define
+`well specified hooks`_.
+
+.. note::
+
+ Make sure to include ``Framework :: Pytest`` in your list of
+ `PyPI classifiers <https://python-packaging-user-guide.readthedocs.io/distributing/#classifiers>`_
+ to make it easy for users to find your plugin.
+
+
+Assertion Rewriting
+-------------------
+
+One of the main features of ``pytest`` is the use of plain assert
+statements and the detailed introspection of expressions upon
+assertion failures. This is provided by "assertion rewriting" which
+modifies the parsed AST before it gets compiled to bytecode. This is
+done via a :pep:`302` import hook which gets installed early on when
+``pytest`` starts up and will perform this rewriting when modules get
+imported. However since we do not want to test different bytecode
+then you will run in production this hook only rewrites test modules
+themselves as well as any modules which are part of plugins. Any
+other imported module will not be rewritten and normal assertion
+behaviour will happen.
+
+If you have assertion helpers in other modules where you would need
+assertion rewriting to be enabled you need to ask ``pytest``
+explicitly to rewrite this module before it gets imported.
+
+.. autofunction:: pytest.register_assert_rewrite
+
+This is especially important when you write a pytest plugin which is
+created using a package. The import hook only treats ``conftest.py``
+files and any modules which are listed in the ``pytest11`` entrypoint
+as plugins. As an example consider the following package::
+
+ pytest_foo/__init__.py
+ pytest_foo/plugin.py
+ pytest_foo/helper.py
+
+With the following typical ``setup.py`` extract:
+
+.. code-block:: python
+
+ setup(
+ ...
+ entry_points={'pytest11': ['foo = pytest_foo.plugin']},
+ ...
+ )
+
+In this case only ``pytest_foo/plugin.py`` will be rewritten. If the
+helper module also contains assert statements which need to be
+rewritten it needs to be marked as such, before it gets imported.
+This is easiest by marking it for rewriting inside the
+``__init__.py`` module, which will always be imported first when a
+module inside a package is imported. This way ``plugin.py`` can still
+import ``helper.py`` normally. The contents of
+``pytest_foo/__init__.py`` will then need to look like this:
+
+.. code-block:: python
+
+ import pytest
+
+ pytest.register_assert_rewrite('pytest_foo.helper')
+
+
+
+Requiring/Loading plugins in a test module or conftest file
+-----------------------------------------------------------
+
+You can require plugins in a test module or a ``conftest.py`` file like this:
+
+.. code-block:: python
+
+ pytest_plugins = ["name1", "name2"]
+
+When the test module or conftest plugin is loaded the specified plugins
+will be loaded as well. Any module can be blessed as a plugin, including internal
+application modules:
+
+.. code-block:: python
+
+ pytest_plugins = "myapp.testsupport.myplugin"
+
+``pytest_plugins`` variables are processed recursively, so note that in the example above
+if ``myapp.testsupport.myplugin`` also declares ``pytest_plugins``, the contents
+of the variable will also be loaded as plugins, and so on.
+
+This mechanism makes it easy to share fixtures within applications or even
+external applications without the need to create external plugins using
+the ``setuptools``'s entry point technique.
+
+Plugins imported by ``pytest_plugins`` will also automatically be marked
+for assertion rewriting (see :func:`pytest.register_assert_rewrite`).
+However for this to have any effect the module must not be
+imported already; if it was already imported at the time the
+``pytest_plugins`` statement is processed, a warning will result and
+assertions inside the plugin will not be rewritten. To fix this you
+can either call :func:`pytest.register_assert_rewrite` yourself before
+the module is imported, or you can arrange the code to delay the
+importing until after the plugin is registered.
+
+
+Accessing another plugin by name
+--------------------------------
+
+If a plugin wants to collaborate with code from
+another plugin it can obtain a reference through
+the plugin manager like this:
+
+.. sourcecode:: python
+
+ plugin = config.pluginmanager.getplugin("name_of_plugin")
+
+If you want to look at the names of existing plugins, use
+the ``--trace-config`` option.
+
+Testing plugins
+---------------
+
+pytest comes with a plugin named ``pytester`` that helps you write tests for
+your plugin code. The plugin is disabled by default, so you will have to enable
+it before you can use it.
+
+You can do so by adding the following line to a ``conftest.py`` file in your
+testing directory:
+
+.. code-block:: python
+
+ # content of conftest.py
+
+ pytest_plugins = ["pytester"]
+
+Alternatively you can invoke pytest with the ``-p pytester`` command line
+option.
+
+This will allow you to use the :py:class:`testdir <_pytest.pytester.Testdir>`
+fixture for testing your plugin code.
+
+Let's demonstrate what you can do with the plugin with an example. Imagine we
+developed a plugin that provides a fixture ``hello`` which yields a function
+and we can invoke this function with one optional parameter. It will return a
+string value of ``Hello World!`` if we do not supply a value or ``Hello
+{value}!`` if we do supply a string value.
+
+.. code-block:: python
+
+ # -*- coding: utf-8 -*-
+
+ import pytest
+
+ def pytest_addoption(parser):
+ group = parser.getgroup('helloworld')
+ group.addoption(
+ '--name',
+ action='store',
+ dest='name',
+ default='World',
+ help='Default "name" for hello().'
+ )
+
+ @pytest.fixture
+ def hello(request):
+ name = request.config.getoption('name')
+
+ def _hello(name=None):
+ if not name:
+ name = request.config.getoption('name')
+ return "Hello {name}!".format(name=name)
+
+ return _hello
+
+
+Now the ``testdir`` fixture provides a convenient API for creating temporary
+``conftest.py`` files and test files. It also allows us to run the tests and
+return a result object, with which we can assert the tests' outcomes.
+
+.. code-block:: python
+
+ def test_hello(testdir):
+ """Make sure that our plugin works."""
+
+ # create a temporary conftest.py file
+ testdir.makeconftest("""
+ import pytest
+
+ @pytest.fixture(params=[
+ "Brianna",
+ "Andreas",
+ "Floris",
+ ])
+ def name(request):
+ return request.param
+ """)
+
+ # create a temporary pytest test file
+ testdir.makepyfile("""
+ def test_hello_default(hello):
+ assert hello() == "Hello World!"
+
+ def test_hello_name(hello, name):
+ assert hello(name) == "Hello {0}!".format(name)
+ """)
+
+ # run all tests with pytest
+ result = testdir.runpytest()
+
+ # check that all 4 tests passed
+ result.assert_outcomes(passed=4)
+
+
+For more information about the result object that ``runpytest()`` returns, and
+the methods that it provides please check out the :py:class:`RunResult
+<_pytest.pytester.RunResult>` documentation.
+
+
+.. _`writinghooks`:
+
+Writing hook functions
+======================
+
+
+.. _validation:
+
+hook function validation and execution
+--------------------------------------
+
+pytest calls hook functions from registered plugins for any
+given hook specification. Let's look at a typical hook function
+for the ``pytest_collection_modifyitems(session, config,
+items)`` hook which pytest calls after collection of all test items is
+completed.
+
+When we implement a ``pytest_collection_modifyitems`` function in our plugin
+pytest will during registration verify that you use argument
+names which match the specification and bail out if not.
+
+Let's look at a possible implementation:
+
+.. code-block:: python
+
+ def pytest_collection_modifyitems(config, items):
+ # called after collection is completed
+ # you can modify the ``items`` list
+
+Here, ``pytest`` will pass in ``config`` (the pytest config object)
+and ``items`` (the list of collected test items) but will not pass
+in the ``session`` argument because we didn't list it in the function
+signature. This dynamic "pruning" of arguments allows ``pytest`` to
+be "future-compatible": we can introduce new hook named parameters without
+breaking the signatures of existing hook implementations. It is one of
+the reasons for the general long-lived compatibility of pytest plugins.
+
+Note that hook functions other than ``pytest_runtest_*`` are not
+allowed to raise exceptions. Doing so will break the pytest run.
+
+
+
+.. _firstresult:
+
+firstresult: stop at first non-None result
+-------------------------------------------
+
+Most calls to ``pytest`` hooks result in a **list of results** which contains
+all non-None results of the called hook functions.
+
+Some hook specifications use the ``firstresult=True`` option so that the hook
+call only executes until the first of N registered functions returns a
+non-None result which is then taken as result of the overall hook call.
+The remaining hook functions will not be called in this case.
+
+
+hookwrapper: executing around other hooks
+-------------------------------------------------
+
+.. currentmodule:: _pytest.core
+
+.. versionadded:: 2.7
+
+pytest plugins can implement hook wrappers which wrap the execution
+of other hook implementations. A hook wrapper is a generator function
+which yields exactly once. When pytest invokes hooks it first executes
+hook wrappers and passes the same arguments as to the regular hooks.
+
+At the yield point of the hook wrapper pytest will execute the next hook
+implementations and return their result to the yield point in the form of
+a :py:class:`Result <pluggy._Result>` instance which encapsulates a result or
+exception info. The yield point itself will thus typically not raise
+exceptions (unless there are bugs).
+
+Here is an example definition of a hook wrapper::
+
+ import pytest
+
+ @pytest.hookimpl(hookwrapper=True)
+ def pytest_pyfunc_call(pyfuncitem):
+ # do whatever you want before the next hook executes
+
+ outcome = yield
+ # outcome.excinfo may be None or a (cls, val, tb) tuple
+
+ res = outcome.get_result() # will raise if outcome was exception
+ # postprocess result
+
+Note that hook wrappers don't return results themselves, they merely
+perform tracing or other side effects around the actual hook implementations.
+If the result of the underlying hook is a mutable object, they may modify
+that result but it's probably better to avoid it.
+
+
+Hook function ordering / call example
+-------------------------------------
+
+For any given hook specification there may be more than one
+implementation and we thus generally view ``hook`` execution as a
+``1:N`` function call where ``N`` is the number of registered functions.
+There are ways to influence if a hook implementation comes before or
+after others, i.e. the position in the ``N``-sized list of functions:
+
+.. code-block:: python
+
+ # Plugin 1
+ @pytest.hookimpl(tryfirst=True)
+ def pytest_collection_modifyitems(items):
+ # will execute as early as possible
+
+ # Plugin 2
+ @pytest.hookimpl(trylast=True)
+ def pytest_collection_modifyitems(items):
+ # will execute as late as possible
+
+ # Plugin 3
+ @pytest.hookimpl(hookwrapper=True)
+ def pytest_collection_modifyitems(items):
+ # will execute even before the tryfirst one above!
+ outcome = yield
+ # will execute after all non-hookwrappers executed
+
+Here is the order of execution:
+
+1. Plugin3's pytest_collection_modifyitems called until the yield point
+ because it is a hook wrapper.
+
+2. Plugin1's pytest_collection_modifyitems is called because it is marked
+ with ``tryfirst=True``.
+
+3. Plugin2's pytest_collection_modifyitems is called because it is marked
+ with ``trylast=True`` (but even without this mark it would come after
+ Plugin1).
+
+4. Plugin3's pytest_collection_modifyitems then executing the code after the yield
+ point. The yield receives a :py:class:`Result <pluggy._Result>` instance which encapsulates
+ the result from calling the non-wrappers. Wrappers shall not modify the result.
+
+It's possible to use ``tryfirst`` and ``trylast`` also in conjunction with
+``hookwrapper=True`` in which case it will influence the ordering of hookwrappers
+among each other.
+
+
+Declaring new hooks
+------------------------
+
+.. currentmodule:: _pytest.hookspec
+
+Plugins and ``conftest.py`` files may declare new hooks that can then be
+implemented by other plugins in order to alter behaviour or interact with
+the new plugin:
+
+.. autofunction:: pytest_addhooks
+
+Hooks are usually declared as do-nothing functions that contain only
+documentation describing when the hook will be called and what return values
+are expected.
+
+For an example, see `newhooks.py`_ from `xdist <https://github.com/pytest-dev/pytest-xdist>`_.
+
+.. _`newhooks.py`: https://github.com/pytest-dev/pytest-xdist/blob/974bd566c599dc6a9ea291838c6f226197208b46/xdist/newhooks.py
+
+
+Optionally using hooks from 3rd party plugins
+---------------------------------------------
+
+Using new hooks from plugins as explained above might be a little tricky
+because of the standard :ref:`validation mechanism <validation>`:
+if you depend on a plugin that is not installed, validation will fail and
+the error message will not make much sense to your users.
+
+One approach is to defer the hook implementation to a new plugin instead of
+declaring the hook functions directly in your plugin module, for example::
+
+ # contents of myplugin.py
+
+ class DeferPlugin(object):
+ """Simple plugin to defer pytest-xdist hook functions."""
+
+ def pytest_testnodedown(self, node, error):
+ """standard xdist hook function.
+ """
+
+ def pytest_configure(config):
+ if config.pluginmanager.hasplugin('xdist'):
+ config.pluginmanager.register(DeferPlugin())
+
+This has the added benefit of allowing you to conditionally install hooks
+depending on which plugins are installed.
+
+.. _`well specified hooks`:
+
+.. currentmodule:: _pytest.hookspec
+
+pytest hook reference
+=====================
+
+
+Initialization, command line and configuration hooks
+----------------------------------------------------
+
+.. autofunction:: pytest_load_initial_conftests
+.. autofunction:: pytest_cmdline_preparse
+.. autofunction:: pytest_cmdline_parse
+.. autofunction:: pytest_addoption
+.. autofunction:: pytest_cmdline_main
+.. autofunction:: pytest_configure
+.. autofunction:: pytest_unconfigure
+
+Generic "runtest" hooks
+-----------------------
+
+All runtest related hooks receive a :py:class:`pytest.Item <_pytest.main.Item>` object.
+
+.. autofunction:: pytest_runtest_protocol
+.. autofunction:: pytest_runtest_setup
+.. autofunction:: pytest_runtest_call
+.. autofunction:: pytest_runtest_teardown
+.. autofunction:: pytest_runtest_makereport
+
+For deeper understanding you may look at the default implementation of
+these hooks in :py:mod:`_pytest.runner` and maybe also
+in :py:mod:`_pytest.pdb` which interacts with :py:mod:`_pytest.capture`
+and its input/output capturing in order to immediately drop
+into interactive debugging when a test failure occurs.
+
+The :py:mod:`_pytest.terminal` reported specifically uses
+the reporting hook to print information about a test run.
+
+Collection hooks
+----------------
+
+``pytest`` calls the following hooks for collecting files and directories:
+
+.. autofunction:: pytest_ignore_collect
+.. autofunction:: pytest_collect_directory
+.. autofunction:: pytest_collect_file
+
+For influencing the collection of objects in Python modules
+you can use the following hook:
+
+.. autofunction:: pytest_pycollect_makeitem
+.. autofunction:: pytest_generate_tests
+.. autofunction:: pytest_make_parametrize_id
+
+After collection is complete, you can modify the order of
+items, delete or otherwise amend the test items:
+
+.. autofunction:: pytest_collection_modifyitems
+
+Reporting hooks
+---------------
+
+Session related reporting hooks:
+
+.. autofunction:: pytest_collectstart
+.. autofunction:: pytest_itemcollected
+.. autofunction:: pytest_collectreport
+.. autofunction:: pytest_deselected
+.. autofunction:: pytest_report_header
+.. autofunction:: pytest_report_collectionfinish
+.. autofunction:: pytest_report_teststatus
+.. autofunction:: pytest_terminal_summary
+.. autofunction:: pytest_fixture_setup
+.. autofunction:: pytest_fixture_post_finalizer
+
+And here is the central hook for reporting about
+test execution:
+
+.. autofunction:: pytest_runtest_logreport
+
+You can also use this hook to customize assertion representation for some
+types:
+
+.. autofunction:: pytest_assertrepr_compare
+
+
+Debugging/Interaction hooks
+---------------------------
+
+There are few hooks which can be used for special
+reporting or interaction with exceptions:
+
+.. autofunction:: pytest_internalerror
+.. autofunction:: pytest_keyboard_interrupt
+.. autofunction:: pytest_exception_interact
+.. autofunction:: pytest_enter_pdb
+
+
+Reference of objects involved in hooks
+======================================
+
+.. autoclass:: _pytest.config.Config()
+ :members:
+
+.. autoclass:: _pytest.config.Parser()
+ :members:
+
+.. autoclass:: _pytest.main.Node()
+ :members:
+
+.. autoclass:: _pytest.main.Collector()
+ :members:
+ :show-inheritance:
+
+.. autoclass:: _pytest.main.Item()
+ :members:
+ :show-inheritance:
+
+.. autoclass:: _pytest.python.Module()
+ :members:
+ :show-inheritance:
+
+.. autoclass:: _pytest.python.Class()
+ :members:
+ :show-inheritance:
+
+.. autoclass:: _pytest.python.Function()
+ :members:
+ :show-inheritance:
+
+.. autoclass:: _pytest.fixtures.FixtureDef()
+ :members:
+ :show-inheritance:
+
+.. autoclass:: _pytest.runner.CallInfo()
+ :members:
+
+.. autoclass:: _pytest.runner.TestReport()
+ :members:
+ :inherited-members:
+
+.. autoclass:: pluggy._Result
+ :members:
+
+.. autofunction:: _pytest.config.get_plugin_manager()
+
+.. autoclass:: _pytest.config.PytestPluginManager()
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. autoclass:: pluggy.PluginManager()
+ :members:
+
+.. currentmodule:: _pytest.pytester
+
+.. autoclass:: Testdir()
+ :members: runpytest,runpytest_subprocess,runpytest_inprocess,makeconftest,makepyfile
+
+.. autoclass:: RunResult()
+ :members:
+
+.. autoclass:: LineMatcher()
+ :members:
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/xunit_setup.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/xunit_setup.rst
new file mode 100644
index 00000000000..148fb1209ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/xunit_setup.rst
@@ -0,0 +1,99 @@
+
+.. _`classic xunit`:
+.. _xunitsetup:
+
+classic xunit-style setup
+========================================
+
+This section describes a classic and popular way how you can implement
+fixtures (setup and teardown test state) on a per-module/class/function basis.
+
+
+.. note::
+
+ While these setup/teardown methods are simple and familiar to those
+ coming from a ``unittest`` or nose ``background``, you may also consider
+ using pytest's more powerful :ref:`fixture mechanism
+ <fixture>` which leverages the concept of dependency injection, allowing
+ for a more modular and more scalable approach for managing test state,
+ especially for larger projects and for functional testing. You can
+ mix both fixture mechanisms in the same file but
+ test methods of ``unittest.TestCase`` subclasses
+ cannot receive fixture arguments.
+
+
+Module level setup/teardown
+--------------------------------------
+
+If you have multiple test functions and test classes in a single
+module you can optionally implement the following fixture methods
+which will usually be called once for all the functions::
+
+ def setup_module(module):
+ """ setup any state specific to the execution of the given module."""
+
+ def teardown_module(module):
+ """ teardown any state that was previously setup with a setup_module
+ method.
+ """
+
+As of pytest-3.0, the ``module`` parameter is optional.
+
+Class level setup/teardown
+----------------------------------
+
+Similarly, the following methods are called at class level before
+and after all test methods of the class are called::
+
+ @classmethod
+ def setup_class(cls):
+ """ setup any state specific to the execution of the given class (which
+ usually contains tests).
+ """
+
+ @classmethod
+ def teardown_class(cls):
+ """ teardown any state that was previously setup with a call to
+ setup_class.
+ """
+
+Method and function level setup/teardown
+-----------------------------------------------
+
+Similarly, the following methods are called around each method invocation::
+
+ def setup_method(self, method):
+ """ setup any state tied to the execution of the given method in a
+ class. setup_method is invoked for every test method of a class.
+ """
+
+ def teardown_method(self, method):
+ """ teardown any state that was previously setup with a setup_method
+ call.
+ """
+
+As of pytest-3.0, the ``method`` parameter is optional.
+
+If you would rather define test functions directly at module level
+you can also use the following functions to implement fixtures::
+
+ def setup_function(function):
+ """ setup any state tied to the execution of the given function.
+ Invoked for every test function in the module.
+ """
+
+ def teardown_function(function):
+ """ teardown any state that was previously setup with a setup_function
+ call.
+ """
+
+As of pytest-3.0, the ``function`` parameter is optional.
+
+Remarks:
+
+* It is possible for setup/teardown pairs to be invoked multiple times
+ per testing process.
+* teardown functions are not called if the corresponding setup function existed
+ and failed/was skipped.
+
+.. _`unittest.py module`: http://docs.python.org/library/unittest.html
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/yieldfixture.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/yieldfixture.rst
new file mode 100644
index 00000000000..6fd1edac2f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/doc/en/yieldfixture.rst
@@ -0,0 +1,18 @@
+:orphan:
+
+.. _yieldfixture:
+
+"yield_fixture" functions
+---------------------------------------------------------------
+
+.. deprecated:: 3.0
+
+.. versionadded:: 2.4
+
+.. important::
+ Since pytest-3.0, fixtures using the normal ``fixture`` decorator can use a ``yield``
+ statement to provide fixture values and execute teardown code, exactly like ``yield_fixture``
+ in previous versions.
+
+ Marking functions as ``yield_fixture`` is still supported, but deprecated and should not
+ be used in new code.
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/extra/get_issues.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/extra/get_issues.py
new file mode 100644
index 00000000000..2a8f8c31606
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/extra/get_issues.py
@@ -0,0 +1,84 @@
+import json
+import py
+import textwrap
+
+issues_url = "https://api.github.com/repos/pytest-dev/pytest/issues"
+
+import requests
+
+
+def get_issues():
+ issues = []
+ url = issues_url
+ while 1:
+ get_data = {"state": "all"}
+ r = requests.get(url, params=get_data)
+ data = r.json()
+ if r.status_code == 403:
+ # API request limit exceeded
+ print(data['message'])
+ exit(1)
+ issues.extend(data)
+
+ # Look for next page
+ links = requests.utils.parse_header_links(r.headers['Link'])
+ another_page = False
+ for link in links:
+ if link['rel'] == 'next':
+ url = link['url']
+ another_page = True
+ if not another_page:
+ return issues
+
+
+def main(args):
+ cachefile = py.path.local(args.cache)
+ if not cachefile.exists() or args.refresh:
+ issues = get_issues()
+ cachefile.write(json.dumps(issues))
+ else:
+ issues = json.loads(cachefile.read())
+
+ open_issues = [x for x in issues if x["state"] == "open"]
+
+ open_issues.sort(key=lambda x: x["number"])
+ report(open_issues)
+
+
+def _get_kind(issue):
+ labels = [l['name'] for l in issue['labels']]
+ for key in ('bug', 'enhancement', 'proposal'):
+ if key in labels:
+ return key
+ return 'issue'
+
+
+def report(issues):
+ for issue in issues:
+ title = issue["title"]
+ body = issue["body"]
+ kind = _get_kind(issue)
+ status = issue["state"]
+ number = issue["number"]
+ link = "https://github.com/pytest-dev/pytest/issues/%s/" % number
+ print("----")
+ print(status, kind, link)
+ print(title)
+ #print()
+ #lines = body.split("\n")
+ #print ("\n".join(lines[:3]))
+ #if len(lines) > 3 or len(body) > 240:
+ # print ("...")
+ print("\n\nFound %s open issues" % len(issues))
+
+
+if __name__ == "__main__":
+ import argparse
+ parser = argparse.ArgumentParser("process bitbucket issues")
+ parser.add_argument("--refresh", action="store_true",
+ help="invalidate cache, refresh issues")
+ parser.add_argument("--cache", action="store", default="issues.json",
+ help="cache file")
+ args = parser.parse_args()
+ main(args)
+
diff --git a/tests/wpt/web-platform-tests/tools/pytest/extra/setup-py.test/setup.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/extra/setup-py.test/setup.py
index d0560ce1f5f..d0560ce1f5f 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/extra/setup-py.test/setup.py
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/extra/setup-py.test/setup.py
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/pyproject.toml b/tests/wpt/web-platform-tests/tools/third_party/pytest/pyproject.toml
new file mode 100644
index 00000000000..88571e208b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/pyproject.toml
@@ -0,0 +1,35 @@
+[tool.towncrier]
+package = "pytest"
+filename = "CHANGELOG.rst"
+directory = "changelog/"
+template = "changelog/_template.rst"
+
+ [[tool.towncrier.type]]
+ directory = "removal"
+ name = "Deprecations and Removals"
+ showcontent = true
+
+ [[tool.towncrier.type]]
+ directory = "feature"
+ name = "Features"
+ showcontent = true
+
+ [[tool.towncrier.type]]
+ directory = "bugfix"
+ name = "Bug Fixes"
+ showcontent = true
+
+ [[tool.towncrier.type]]
+ directory = "vendor"
+ name = "Vendored Libraries"
+ showcontent = true
+
+ [[tool.towncrier.type]]
+ directory = "doc"
+ name = "Improved Documentation"
+ showcontent = true
+
+ [[tool.towncrier.type]]
+ directory = "trivial"
+ name = "Trivial/Internal Changes"
+ showcontent = true
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/pytest.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/pytest.py
new file mode 100644
index 00000000000..2b681b64b4c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/pytest.py
@@ -0,0 +1,77 @@
+# PYTHON_ARGCOMPLETE_OK
+"""
+pytest: unit and functional testing with Python.
+"""
+
+
+# else we are imported
+
+from _pytest.config import (
+ main, UsageError, cmdline,
+ hookspec, hookimpl
+)
+from _pytest.fixtures import fixture, yield_fixture
+from _pytest.assertion import register_assert_rewrite
+from _pytest.freeze_support import freeze_includes
+from _pytest import __version__
+from _pytest.debugging import pytestPDB as __pytestPDB
+from _pytest.recwarn import warns, deprecated_call
+from _pytest.outcomes import fail, skip, importorskip, exit, xfail
+from _pytest.mark import MARK_GEN as mark, param
+from _pytest.main import Item, Collector, File, Session
+from _pytest.fixtures import fillfixtures as _fillfuncargs
+from _pytest.python import (
+ Module, Class, Instance, Function, Generator,
+)
+
+from _pytest.python_api import approx, raises
+
+set_trace = __pytestPDB.set_trace
+
+__all__ = [
+ 'main',
+ 'UsageError',
+ 'cmdline',
+ 'hookspec',
+ 'hookimpl',
+ '__version__',
+ 'register_assert_rewrite',
+ 'freeze_includes',
+ 'set_trace',
+ 'warns',
+ 'deprecated_call',
+ 'fixture',
+ 'yield_fixture',
+ 'fail',
+ 'skip',
+ 'xfail',
+ 'importorskip',
+ 'exit',
+ 'mark',
+ 'param',
+ 'approx',
+ '_fillfuncargs',
+
+ 'Item',
+ 'File',
+ 'Collector',
+ 'Session',
+ 'Module',
+ 'Class',
+ 'Instance',
+ 'Function',
+ 'Generator',
+ 'raises',
+
+
+]
+
+if __name__ == '__main__':
+ # if run as a script or by 'python -m pytest'
+ # we trigger the below "else" condition by the following import
+ import pytest
+ raise SystemExit(pytest.main())
+else:
+
+ from _pytest.compat import _setup_collect_fakemodule
+ _setup_collect_fakemodule()
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/scripts/call-tox.bat b/tests/wpt/web-platform-tests/tools/third_party/pytest/scripts/call-tox.bat
new file mode 100644
index 00000000000..86fb25c1df1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/scripts/call-tox.bat
@@ -0,0 +1,8 @@
+REM skip "coveralls" run in PRs or forks
+if "%TOXENV%" == "coveralls" (
+ if not defined COVERALLS_REPO_TOKEN (
+ echo skipping coveralls run because COVERALLS_REPO_TOKEN is not defined
+ exit /b 0
+ )
+)
+C:\Python36\python -m tox
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/scripts/check-rst.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/scripts/check-rst.py
new file mode 100644
index 00000000000..57f717501af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/scripts/check-rst.py
@@ -0,0 +1,11 @@
+
+from __future__ import print_function
+
+import subprocess
+import glob
+import sys
+
+sys.exit(subprocess.call([
+ 'rst-lint', '--encoding', 'utf-8',
+ 'CHANGELOG.rst', 'HOWTORELEASE.rst', 'README.rst',
+] + glob.glob('changelog/[0-9]*.*')))
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/scripts/install-pypy.bat b/tests/wpt/web-platform-tests/tools/third_party/pytest/scripts/install-pypy.bat
new file mode 100644
index 00000000000..8012ea46aca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/scripts/install-pypy.bat
@@ -0,0 +1,6 @@
+REM install pypy using choco
+REM redirect to a file because choco install python.pypy is too noisy. If the command fails, write output to console
+choco install python.pypy > pypy-inst.log 2>&1 || (type pypy-inst.log & exit /b 1)
+set PATH=C:\tools\pypy\pypy;%PATH% # so tox can find pypy
+echo PyPy installed
+pypy --version
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/setup.cfg b/tests/wpt/web-platform-tests/tools/third_party/pytest/setup.cfg
new file mode 100644
index 00000000000..816539e2ec6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/setup.cfg
@@ -0,0 +1,20 @@
+[build_sphinx]
+source-dir = doc/en/
+build-dir = doc/build
+all_files = 1
+
+[upload_sphinx]
+upload-dir = doc/en/build/html
+
+[bdist_wheel]
+universal = 1
+
+[check-manifest]
+ignore =
+ _pytest/_version.py
+
+[metadata]
+license_file = LICENSE
+
+[devpi:upload]
+formats = sdist.tgz,bdist_wheel
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/setup.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/setup.py
new file mode 100644
index 00000000000..3eb38efe655
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/setup.py
@@ -0,0 +1,114 @@
+import os
+import sys
+import setuptools
+import pkg_resources
+from setuptools import setup, Command
+
+classifiers = [
+ 'Development Status :: 6 - Mature',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: MIT License',
+ 'Operating System :: POSIX',
+ 'Operating System :: Microsoft :: Windows',
+ 'Operating System :: MacOS :: MacOS X',
+ 'Topic :: Software Development :: Testing',
+ 'Topic :: Software Development :: Libraries',
+ 'Topic :: Utilities',
+] + [
+ ('Programming Language :: Python :: %s' % x)
+ for x in '2 2.7 3 3.4 3.5 3.6'.split()
+]
+
+with open('README.rst') as fd:
+ long_description = fd.read()
+
+
+def has_environment_marker_support():
+ """
+ Tests that setuptools has support for PEP-426 environment marker support.
+
+ The first known release to support it is 0.7 (and the earliest on PyPI seems to be 0.7.2
+ so we're using that), see: http://pythonhosted.org/setuptools/history.html#id142
+
+ References:
+
+ * https://wheel.readthedocs.io/en/latest/index.html#defining-conditional-dependencies
+ * https://www.python.org/dev/peps/pep-0426/#environment-markers
+ """
+ try:
+ return pkg_resources.parse_version(setuptools.__version__) >= pkg_resources.parse_version('0.7.2')
+ except Exception as exc:
+ sys.stderr.write("Could not test setuptool's version: %s\n" % exc)
+ return False
+
+
+def main():
+ extras_require = {}
+ install_requires = [
+ 'py>=1.5.0',
+ 'six>=1.10.0',
+ 'setuptools',
+ 'attrs>=17.2.0',
+ ]
+ # if _PYTEST_SETUP_SKIP_PLUGGY_DEP is set, skip installing pluggy;
+ # used by tox.ini to test with pluggy master
+ if '_PYTEST_SETUP_SKIP_PLUGGY_DEP' not in os.environ:
+ install_requires.append('pluggy>=0.5,<0.7')
+ if has_environment_marker_support():
+ extras_require[':python_version<"3.0"'] = ['funcsigs']
+ extras_require[':sys_platform=="win32"'] = ['colorama']
+ else:
+ if sys.platform == 'win32':
+ install_requires.append('colorama')
+ if sys.version_info < (3, 0):
+ install_requires.append('funcsigs')
+
+ setup(
+ name='pytest',
+ description='pytest: simple powerful testing with Python',
+ long_description=long_description,
+ use_scm_version={
+ 'write_to': '_pytest/_version.py',
+ },
+ url='http://pytest.org',
+ license='MIT license',
+ platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],
+ author=(
+ 'Holger Krekel, Bruno Oliveira, Ronny Pfannschmidt, '
+ 'Floris Bruynooghe, Brianna Laugher, Florian Bruhin and others'),
+ entry_points={'console_scripts': [
+ 'pytest=pytest:main', 'py.test=pytest:main']},
+ classifiers=classifiers,
+ keywords="test unittest",
+ cmdclass={'test': PyTest},
+ # the following should be enabled for release
+ setup_requires=['setuptools-scm'],
+ python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
+ install_requires=install_requires,
+ extras_require=extras_require,
+ packages=['_pytest', '_pytest.assertion', '_pytest._code'],
+ py_modules=['pytest'],
+ zip_safe=False,
+ )
+
+
+class PyTest(Command):
+ user_options = []
+
+ def initialize_options(self):
+ pass
+
+ def finalize_options(self):
+ pass
+
+ def run(self):
+ import subprocess
+ PPATH = [x for x in os.environ.get('PYTHONPATH', '').split(':') if x]
+ PPATH.insert(0, os.getcwd())
+ os.environ['PYTHONPATH'] = ':'.join(PPATH)
+ errno = subprocess.call([sys.executable, 'pytest.py', '--ignore=doc'])
+ raise SystemExit(errno)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/tasks/__init__.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/tasks/__init__.py
new file mode 100644
index 00000000000..8ea038f0af0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/tasks/__init__.py
@@ -0,0 +1,12 @@
+"""
+Invoke tasks to help with pytest development and release process.
+"""
+
+import invoke
+
+from . import generate
+
+
+ns = invoke.Collection(
+ generate,
+)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/tasks/generate.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/tasks/generate.py
new file mode 100644
index 00000000000..fa8ee6557df
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/tasks/generate.py
@@ -0,0 +1,162 @@
+import os
+from pathlib import Path
+from subprocess import check_output, check_call
+
+import invoke
+
+
+@invoke.task(help={
+ 'version': 'version being released',
+})
+def announce(ctx, version):
+ """Generates a new release announcement entry in the docs."""
+ # Get our list of authors
+ stdout = check_output(["git", "describe", "--abbrev=0", '--tags'])
+ stdout = stdout.decode('utf-8')
+ last_version = stdout.strip()
+
+ stdout = check_output(["git", "log", "{}..HEAD".format(last_version), "--format=%aN"])
+ stdout = stdout.decode('utf-8')
+
+ contributors = set(stdout.splitlines())
+
+ template_name = 'release.minor.rst' if version.endswith('.0') else 'release.patch.rst'
+ template_text = Path(__file__).parent.joinpath(template_name).read_text(encoding='UTF-8')
+
+ contributors_text = '\n'.join('* {}'.format(name) for name in sorted(contributors)) + '\n'
+ text = template_text.format(version=version, contributors=contributors_text)
+
+ target = Path(__file__).parent.joinpath('../doc/en/announce/release-{}.rst'.format(version))
+ target.write_text(text, encoding='UTF-8')
+ print("[generate.announce] Generated {}".format(target.name))
+
+ # Update index with the new release entry
+ index_path = Path(__file__).parent.joinpath('../doc/en/announce/index.rst')
+ lines = index_path.read_text(encoding='UTF-8').splitlines()
+ indent = ' '
+ for index, line in enumerate(lines):
+ if line.startswith('{}release-'.format(indent)):
+ new_line = indent + target.stem
+ if line != new_line:
+ lines.insert(index, new_line)
+ index_path.write_text('\n'.join(lines) + '\n', encoding='UTF-8')
+ print("[generate.announce] Updated {}".format(index_path.name))
+ else:
+ print("[generate.announce] Skip {} (already contains release)".format(index_path.name))
+ break
+
+ check_call(['git', 'add', str(target)])
+
+
+@invoke.task()
+def regen(ctx):
+ """Call regendoc tool to update examples and pytest output in the docs."""
+ print("[generate.regen] Updating docs")
+ check_call(['tox', '-e', 'regen'])
+
+
+@invoke.task()
+def make_tag(ctx, version):
+ """Create a new (local) tag for the release, only if the repository is clean."""
+ from git import Repo
+
+ repo = Repo('.')
+ if repo.is_dirty():
+ print('Current repository is dirty. Please commit any changes and try again.')
+ raise invoke.Exit(code=2)
+
+ tag_names = [x.name for x in repo.tags]
+ if version in tag_names:
+ print("[generate.make_tag] Delete existing tag {}".format(version))
+ repo.delete_tag(version)
+
+ print("[generate.make_tag] Create tag {}".format(version))
+ repo.create_tag(version)
+
+
+@invoke.task()
+def devpi_upload(ctx, version, user, password=None):
+ """Creates and uploads a package to devpi for testing."""
+ if password:
+ print("[generate.devpi_upload] devpi login {}".format(user))
+ check_call(['devpi', 'login', user, '--password', password])
+
+ check_call(['devpi', 'use', 'https://devpi.net/{}/dev'.format(user)])
+
+ env = os.environ.copy()
+ env['SETUPTOOLS_SCM_PRETEND_VERSION'] = version
+ check_call(['devpi', 'upload', '--formats', 'sdist,bdist_wheel'], env=env)
+ print("[generate.devpi_upload] package uploaded")
+
+
+@invoke.task(help={
+ 'version': 'version being released',
+ 'user': 'name of the user on devpi to stage the generated package',
+ 'password': 'user password on devpi to stage the generated package '
+ '(if not given assumed logged in)',
+})
+def pre_release(ctx, version, user, password=None):
+ """Generates new docs, release announcements and uploads a new release to devpi for testing."""
+ announce(ctx, version)
+ regen(ctx)
+ changelog(ctx, version, write_out=True)
+
+ msg = 'Preparing release version {}'.format(version)
+ check_call(['git', 'commit', '-a', '-m', msg])
+
+ make_tag(ctx, version)
+
+ devpi_upload(ctx, version=version, user=user, password=password)
+
+ print()
+ print('[generate.pre_release] Please push your branch and open a PR.')
+
+
+@invoke.task(help={
+ 'version': 'version being released',
+ 'user': 'name of the user on devpi to stage the generated package',
+ 'pypi_name': 'name of the pypi configuration section in your ~/.pypirc',
+})
+def publish_release(ctx, version, user, pypi_name):
+ """Publishes a package previously created by the 'pre_release' command."""
+ from git import Repo
+ repo = Repo('.')
+ tag_names = [x.name for x in repo.tags]
+ if version not in tag_names:
+ print('Could not find tag for version {}, exiting...'.format(version))
+ raise invoke.Exit(code=2)
+
+ check_call(['devpi', 'use', 'https://devpi.net/{}/dev'.format(user)])
+ check_call(['devpi', 'push', 'pytest=={}'.format(version), 'pypi:{}'.format(pypi_name)])
+ check_call(['git', 'push', 'git@github.com:pytest-dev/pytest.git', version])
+
+ emails = [
+ 'pytest-dev@python.org',
+ 'python-announce-list@python.org'
+ ]
+ if version.endswith('.0'):
+ emails.append('testing-in-python@lists.idyll.org')
+ print('Version {} has been published to PyPI!'.format(version))
+ print()
+ print('Please send an email announcement with the contents from:')
+ print()
+ print(' doc/en/announce/release-{}.rst'.format(version))
+ print()
+ print('To the following mail lists:')
+ print()
+ print(' ', ','.join(emails))
+ print()
+ print('And announce it on twitter adding the #pytest hash tag.')
+
+
+@invoke.task(help={
+ 'version': 'version being released',
+ 'write_out': 'write changes to the actial changelog'
+})
+def changelog(ctx, version, write_out=False):
+ if write_out:
+ addopts = []
+ else:
+ addopts = ['--draft']
+ check_call(['towncrier', '--version', version] + addopts)
+
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/tasks/release.minor.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/tasks/release.minor.rst
new file mode 100644
index 00000000000..3c0b7d718a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/tasks/release.minor.rst
@@ -0,0 +1,27 @@
+pytest-{version}
+=======================================
+
+The pytest team is proud to announce the {version} release!
+
+pytest is a mature Python testing tool with more than a 1600 tests
+against itself, passing on many different interpreters and platforms.
+
+This release contains a number of bugs fixes and improvements, so users are encouraged
+to take a look at the CHANGELOG:
+
+ http://doc.pytest.org/en/latest/changelog.html
+
+For complete documentation, please visit:
+
+ http://docs.pytest.org
+
+As usual, you can upgrade from pypi via:
+
+ pip install -U pytest
+
+Thanks to all who contributed to this release, among them:
+
+{contributors}
+
+Happy testing,
+The Pytest Development Team
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/tasks/release.patch.rst b/tests/wpt/web-platform-tests/tools/third_party/pytest/tasks/release.patch.rst
new file mode 100644
index 00000000000..56764b91307
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/tasks/release.patch.rst
@@ -0,0 +1,17 @@
+pytest-{version}
+=======================================
+
+pytest {version} has just been released to PyPI.
+
+This is a bug-fix release, being a drop-in replacement. To upgrade::
+
+ pip install --upgrade pytest
+
+The full changelog is available at http://doc.pytest.org/en/latest/changelog.html.
+
+Thanks to all who contributed to this release, among them:
+
+{contributors}
+
+Happy testing,
+The pytest Development Team
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/tasks/requirements.txt b/tests/wpt/web-platform-tests/tools/third_party/pytest/tasks/requirements.txt
new file mode 100644
index 00000000000..6392de0cc0a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/tasks/requirements.txt
@@ -0,0 +1,5 @@
+invoke
+tox
+gitpython
+towncrier
+wheel
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/acceptance_test.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/acceptance_test.py
new file mode 100644
index 00000000000..a7838545b07
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/acceptance_test.py
@@ -0,0 +1,850 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import, division, print_function
+import os
+import sys
+
+import _pytest._code
+import py
+import pytest
+from _pytest.main import EXIT_NOTESTSCOLLECTED, EXIT_USAGEERROR
+
+
+class TestGeneralUsage(object):
+ def test_config_error(self, testdir):
+ testdir.makeconftest("""
+ def pytest_configure(config):
+ import pytest
+ raise pytest.UsageError("hello")
+ """)
+ result = testdir.runpytest(testdir.tmpdir)
+ assert result.ret != 0
+ result.stderr.fnmatch_lines([
+ '*ERROR: hello'
+ ])
+
+ def test_root_conftest_syntax_error(self, testdir):
+ testdir.makepyfile(conftest="raise SyntaxError\n")
+ result = testdir.runpytest()
+ result.stderr.fnmatch_lines(["*raise SyntaxError*"])
+ assert result.ret != 0
+
+ def test_early_hook_error_issue38_1(self, testdir):
+ testdir.makeconftest("""
+ def pytest_sessionstart():
+ 0 / 0
+ """)
+ result = testdir.runpytest(testdir.tmpdir)
+ assert result.ret != 0
+ # tracestyle is native by default for hook failures
+ result.stdout.fnmatch_lines([
+ '*INTERNALERROR*File*conftest.py*line 2*',
+ '*0 / 0*',
+ ])
+ result = testdir.runpytest(testdir.tmpdir, "--fulltrace")
+ assert result.ret != 0
+ # tracestyle is native by default for hook failures
+ result.stdout.fnmatch_lines([
+ '*INTERNALERROR*def pytest_sessionstart():*',
+ '*INTERNALERROR*0 / 0*',
+ ])
+
+ def test_early_hook_configure_error_issue38(self, testdir):
+ testdir.makeconftest("""
+ def pytest_configure():
+ 0 / 0
+ """)
+ result = testdir.runpytest(testdir.tmpdir)
+ assert result.ret != 0
+ # here we get it on stderr
+ result.stderr.fnmatch_lines([
+ '*INTERNALERROR*File*conftest.py*line 2*',
+ '*0 / 0*',
+ ])
+
+ def test_file_not_found(self, testdir):
+ result = testdir.runpytest("asd")
+ assert result.ret != 0
+ result.stderr.fnmatch_lines(["ERROR: file not found*asd"])
+
+ def test_file_not_found_unconfigure_issue143(self, testdir):
+ testdir.makeconftest("""
+ def pytest_configure():
+ print("---configure")
+ def pytest_unconfigure():
+ print("---unconfigure")
+ """)
+ result = testdir.runpytest("-s", "asd")
+ assert result.ret == 4 # EXIT_USAGEERROR
+ result.stderr.fnmatch_lines(["ERROR: file not found*asd"])
+ result.stdout.fnmatch_lines([
+ "*---configure",
+ "*---unconfigure",
+ ])
+
+ def test_config_preparse_plugin_option(self, testdir):
+ testdir.makepyfile(pytest_xyz="""
+ def pytest_addoption(parser):
+ parser.addoption("--xyz", dest="xyz", action="store")
+ """)
+ testdir.makepyfile(test_one="""
+ def test_option(pytestconfig):
+ assert pytestconfig.option.xyz == "123"
+ """)
+ result = testdir.runpytest("-p", "pytest_xyz", "--xyz=123", syspathinsert=True)
+ assert result.ret == 0
+ result.stdout.fnmatch_lines([
+ '*1 passed*',
+ ])
+
+ def test_assertion_magic(self, testdir):
+ p = testdir.makepyfile("""
+ def test_this():
+ x = 0
+ assert x
+ """)
+ result = testdir.runpytest(p)
+ result.stdout.fnmatch_lines([
+ "> assert x",
+ "E assert 0",
+ ])
+ assert result.ret == 1
+
+ def test_nested_import_error(self, testdir):
+ p = testdir.makepyfile("""
+ import import_fails
+ def test_this():
+ assert import_fails.a == 1
+ """)
+ testdir.makepyfile(import_fails="import does_not_work")
+ result = testdir.runpytest(p)
+ result.stdout.fnmatch_lines([
+ # XXX on jython this fails: "> import import_fails",
+ "ImportError while importing test module*",
+ "*No module named *does_not_work*",
+ ])
+ assert result.ret == 2
+
+ def test_not_collectable_arguments(self, testdir):
+ p1 = testdir.makepyfile("")
+ p2 = testdir.makefile(".pyc", "123")
+ result = testdir.runpytest(p1, p2)
+ assert result.ret
+ result.stderr.fnmatch_lines([
+ "*ERROR: not found:*%s" % (p2.basename,)
+ ])
+
+ def test_issue486_better_reporting_on_conftest_load_failure(self, testdir):
+ testdir.makepyfile("")
+ testdir.makeconftest("import qwerty")
+ result = testdir.runpytest("--help")
+ result.stdout.fnmatch_lines("""
+ *--version*
+ *warning*conftest.py*
+ """)
+ result = testdir.runpytest()
+ result.stderr.fnmatch_lines("""
+ *ERROR*could not load*conftest.py*
+ """)
+
+ def test_early_skip(self, testdir):
+ testdir.mkdir("xyz")
+ testdir.makeconftest("""
+ import pytest
+ def pytest_collect_directory():
+ pytest.skip("early")
+ """)
+ result = testdir.runpytest()
+ assert result.ret == EXIT_NOTESTSCOLLECTED
+ result.stdout.fnmatch_lines([
+ "*1 skip*"
+ ])
+
+ def test_issue88_initial_file_multinodes(self, testdir):
+ testdir.makeconftest("""
+ import pytest
+ class MyFile(pytest.File):
+ def collect(self):
+ return [MyItem("hello", parent=self)]
+ def pytest_collect_file(path, parent):
+ return MyFile(path, parent)
+ class MyItem(pytest.Item):
+ pass
+ """)
+ p = testdir.makepyfile("def test_hello(): pass")
+ result = testdir.runpytest(p, "--collect-only")
+ result.stdout.fnmatch_lines([
+ "*MyFile*test_issue88*",
+ "*Module*test_issue88*",
+ ])
+
+ def test_issue93_initialnode_importing_capturing(self, testdir):
+ testdir.makeconftest("""
+ import sys
+ print ("should not be seen")
+ sys.stderr.write("stder42\\n")
+ """)
+ result = testdir.runpytest()
+ assert result.ret == EXIT_NOTESTSCOLLECTED
+ assert "should not be seen" not in result.stdout.str()
+ assert "stderr42" not in result.stderr.str()
+
+ def test_conftest_printing_shows_if_error(self, testdir):
+ testdir.makeconftest("""
+ print ("should be seen")
+ assert 0
+ """)
+ result = testdir.runpytest()
+ assert result.ret != 0
+ assert "should be seen" in result.stdout.str()
+
+ @pytest.mark.skipif(not hasattr(py.path.local, 'mksymlinkto'),
+ reason="symlink not available on this platform")
+ def test_chdir(self, testdir):
+ testdir.tmpdir.join("py").mksymlinkto(py._pydir)
+ p = testdir.tmpdir.join("main.py")
+ p.write(_pytest._code.Source("""
+ import sys, os
+ sys.path.insert(0, '')
+ import py
+ print (py.__file__)
+ print (py.__path__)
+ os.chdir(os.path.dirname(os.getcwd()))
+ print (py.log)
+ """))
+ result = testdir.runpython(p)
+ assert not result.ret
+
+ def test_issue109_sibling_conftests_not_loaded(self, testdir):
+ sub1 = testdir.tmpdir.mkdir("sub1")
+ sub2 = testdir.tmpdir.mkdir("sub2")
+ sub1.join("conftest.py").write("assert 0")
+ result = testdir.runpytest(sub2)
+ assert result.ret == EXIT_NOTESTSCOLLECTED
+ sub2.ensure("__init__.py")
+ p = sub2.ensure("test_hello.py")
+ result = testdir.runpytest(p)
+ assert result.ret == EXIT_NOTESTSCOLLECTED
+ result = testdir.runpytest(sub1)
+ assert result.ret == EXIT_USAGEERROR
+
+ def test_directory_skipped(self, testdir):
+ testdir.makeconftest("""
+ import pytest
+ def pytest_ignore_collect():
+ pytest.skip("intentional")
+ """)
+ testdir.makepyfile("def test_hello(): pass")
+ result = testdir.runpytest()
+ assert result.ret == EXIT_NOTESTSCOLLECTED
+ result.stdout.fnmatch_lines([
+ "*1 skipped*"
+ ])
+
+ def test_multiple_items_per_collector_byid(self, testdir):
+ c = testdir.makeconftest("""
+ import pytest
+ class MyItem(pytest.Item):
+ def runtest(self):
+ pass
+ class MyCollector(pytest.File):
+ def collect(self):
+ return [MyItem(name="xyz", parent=self)]
+ def pytest_collect_file(path, parent):
+ if path.basename.startswith("conftest"):
+ return MyCollector(path, parent)
+ """)
+ result = testdir.runpytest(c.basename + "::" + "xyz")
+ assert result.ret == 0
+ result.stdout.fnmatch_lines([
+ "*1 pass*",
+ ])
+
+ def test_skip_on_generated_funcarg_id(self, testdir):
+ testdir.makeconftest("""
+ import pytest
+ def pytest_generate_tests(metafunc):
+ metafunc.addcall({'x': 3}, id='hello-123')
+ def pytest_runtest_setup(item):
+ print (item.keywords)
+ if 'hello-123' in item.keywords:
+ pytest.skip("hello")
+ assert 0
+ """)
+ p = testdir.makepyfile("""def test_func(x): pass""")
+ res = testdir.runpytest(p)
+ assert res.ret == 0
+ res.stdout.fnmatch_lines(["*1 skipped*"])
+
+ def test_direct_addressing_selects(self, testdir):
+ p = testdir.makepyfile("""
+ def pytest_generate_tests(metafunc):
+ metafunc.addcall({'i': 1}, id="1")
+ metafunc.addcall({'i': 2}, id="2")
+ def test_func(i):
+ pass
+ """)
+ res = testdir.runpytest(p.basename + "::" + "test_func[1]")
+ assert res.ret == 0
+ res.stdout.fnmatch_lines(["*1 passed*"])
+
+ def test_direct_addressing_notfound(self, testdir):
+ p = testdir.makepyfile("""
+ def test_func():
+ pass
+ """)
+ res = testdir.runpytest(p.basename + "::" + "test_notfound")
+ assert res.ret
+ res.stderr.fnmatch_lines(["*ERROR*not found*"])
+
+ def test_docstring_on_hookspec(self):
+ from _pytest import hookspec
+ for name, value in vars(hookspec).items():
+ if name.startswith("pytest_"):
+ assert value.__doc__, "no docstring for %s" % name
+
+ def test_initialization_error_issue49(self, testdir):
+ testdir.makeconftest("""
+ def pytest_configure():
+ x
+ """)
+ result = testdir.runpytest()
+ assert result.ret == 3 # internal error
+ result.stderr.fnmatch_lines([
+ "INTERNAL*pytest_configure*",
+ "INTERNAL*x*",
+ ])
+ assert 'sessionstarttime' not in result.stderr.str()
+
+ @pytest.mark.parametrize('lookfor', ['test_fun.py::test_a'])
+ def test_issue134_report_error_when_collecting_member(self, testdir, lookfor):
+ testdir.makepyfile(test_fun="""
+ def test_a():
+ pass
+ def""")
+ result = testdir.runpytest(lookfor)
+ result.stdout.fnmatch_lines(['*SyntaxError*'])
+ if '::' in lookfor:
+ result.stderr.fnmatch_lines([
+ '*ERROR*',
+ ])
+ assert result.ret == 4 # usage error only if item not found
+
+ def test_report_all_failed_collections_initargs(self, testdir):
+ testdir.makepyfile(test_a="def", test_b="def")
+ result = testdir.runpytest("test_a.py::a", "test_b.py::b")
+ result.stderr.fnmatch_lines([
+ "*ERROR*test_a.py::a*",
+ "*ERROR*test_b.py::b*",
+ ])
+
+ @pytest.mark.usefixtures('recwarn')
+ def test_namespace_import_doesnt_confuse_import_hook(self, testdir):
+ """
+ Ref #383. Python 3.3's namespace package messed with our import hooks
+ Importing a module that didn't exist, even if the ImportError was
+ gracefully handled, would make our test crash.
+
+ Use recwarn here to silence this warning in Python 2.7:
+ ImportWarning: Not importing directory '...\not_a_package': missing __init__.py
+ """
+ testdir.mkdir('not_a_package')
+ p = testdir.makepyfile("""
+ try:
+ from not_a_package import doesnt_exist
+ except ImportError:
+ # We handle the import error gracefully here
+ pass
+
+ def test_whatever():
+ pass
+ """)
+ res = testdir.runpytest(p.basename)
+ assert res.ret == 0
+
+ def test_unknown_option(self, testdir):
+ result = testdir.runpytest("--qwlkej")
+ result.stderr.fnmatch_lines("""
+ *unrecognized*
+ """)
+
+ def test_getsourcelines_error_issue553(self, testdir, monkeypatch):
+ monkeypatch.setattr("inspect.getsourcelines", None)
+ p = testdir.makepyfile("""
+ def raise_error(obj):
+ raise IOError('source code not available')
+
+ import inspect
+ inspect.getsourcelines = raise_error
+
+ def test_foo(invalid_fixture):
+ pass
+ """)
+ res = testdir.runpytest(p)
+ res.stdout.fnmatch_lines([
+ "*source code not available*",
+ "E*fixture 'invalid_fixture' not found",
+ ])
+
+ def test_plugins_given_as_strings(self, tmpdir, monkeypatch):
+ """test that str values passed to main() as `plugins` arg
+ are interpreted as module names to be imported and registered.
+ #855.
+ """
+ with pytest.raises(ImportError) as excinfo:
+ pytest.main([str(tmpdir)], plugins=['invalid.module'])
+ assert 'invalid' in str(excinfo.value)
+
+ p = tmpdir.join('test_test_plugins_given_as_strings.py')
+ p.write('def test_foo(): pass')
+ mod = py.std.types.ModuleType("myplugin")
+ monkeypatch.setitem(sys.modules, 'myplugin', mod)
+ assert pytest.main(args=[str(tmpdir)], plugins=['myplugin']) == 0
+
+ def test_parametrized_with_bytes_regex(self, testdir):
+ p = testdir.makepyfile("""
+ import re
+ import pytest
+ @pytest.mark.parametrize('r', [re.compile(b'foo')])
+ def test_stuff(r):
+ pass
+ """
+ )
+ res = testdir.runpytest(p)
+ res.stdout.fnmatch_lines([
+ '*1 passed*'
+ ])
+
+ def test_parametrized_with_null_bytes(self, testdir):
+ """Test parametrization with values that contain null bytes and unicode characters (#2644, #2957)"""
+ p = testdir.makepyfile(u"""
+ # encoding: UTF-8
+ import pytest
+
+ @pytest.mark.parametrize("data", [b"\\x00", "\\x00", u'ação'])
+ def test_foo(data):
+ assert data
+ """)
+ res = testdir.runpytest(p)
+ res.assert_outcomes(passed=3)
+
+
+class TestInvocationVariants(object):
+ def test_earlyinit(self, testdir):
+ p = testdir.makepyfile("""
+ import pytest
+ assert hasattr(pytest, 'mark')
+ """)
+ result = testdir.runpython(p)
+ assert result.ret == 0
+
+ @pytest.mark.xfail("sys.platform.startswith('java')")
+ def test_pydoc(self, testdir):
+ for name in ('py.test', 'pytest'):
+ result = testdir.runpython_c("import %s;help(%s)" % (name, name))
+ assert result.ret == 0
+ s = result.stdout.str()
+ assert 'MarkGenerator' in s
+
+ def test_import_star_py_dot_test(self, testdir):
+ p = testdir.makepyfile("""
+ from py.test import *
+ #collect
+ #cmdline
+ #Item
+ # assert collect.Item is Item
+ # assert collect.Collector is Collector
+ main
+ skip
+ xfail
+ """)
+ result = testdir.runpython(p)
+ assert result.ret == 0
+
+ def test_import_star_pytest(self, testdir):
+ p = testdir.makepyfile("""
+ from pytest import *
+ #Item
+ #File
+ main
+ skip
+ xfail
+ """)
+ result = testdir.runpython(p)
+ assert result.ret == 0
+
+ def test_double_pytestcmdline(self, testdir):
+ p = testdir.makepyfile(run="""
+ import pytest
+ pytest.main()
+ pytest.main()
+ """)
+ testdir.makepyfile("""
+ def test_hello():
+ pass
+ """)
+ result = testdir.runpython(p)
+ result.stdout.fnmatch_lines([
+ "*1 passed*",
+ "*1 passed*",
+ ])
+
+ def test_python_minus_m_invocation_ok(self, testdir):
+ p1 = testdir.makepyfile("def test_hello(): pass")
+ res = testdir.run(py.std.sys.executable, "-m", "pytest", str(p1))
+ assert res.ret == 0
+
+ def test_python_minus_m_invocation_fail(self, testdir):
+ p1 = testdir.makepyfile("def test_fail(): 0/0")
+ res = testdir.run(py.std.sys.executable, "-m", "pytest", str(p1))
+ assert res.ret == 1
+
+ def test_python_pytest_package(self, testdir):
+ p1 = testdir.makepyfile("def test_pass(): pass")
+ res = testdir.run(py.std.sys.executable, "-m", "pytest", str(p1))
+ assert res.ret == 0
+ res.stdout.fnmatch_lines(["*1 passed*"])
+
+ def test_equivalence_pytest_pytest(self):
+ assert pytest.main == py.test.cmdline.main
+
+ def test_invoke_with_string(self, capsys):
+ retcode = pytest.main("-h")
+ assert not retcode
+ out, err = capsys.readouterr()
+ assert "--help" in out
+ pytest.raises(ValueError, lambda: pytest.main(0))
+
+ def test_invoke_with_path(self, tmpdir, capsys):
+ retcode = pytest.main(tmpdir)
+ assert retcode == EXIT_NOTESTSCOLLECTED
+ out, err = capsys.readouterr()
+
+ def test_invoke_plugin_api(self, testdir, capsys):
+ class MyPlugin(object):
+ def pytest_addoption(self, parser):
+ parser.addoption("--myopt")
+
+ pytest.main(["-h"], plugins=[MyPlugin()])
+ out, err = capsys.readouterr()
+ assert "--myopt" in out
+
+ def test_pyargs_importerror(self, testdir, monkeypatch):
+ monkeypatch.delenv('PYTHONDONTWRITEBYTECODE', False)
+ path = testdir.mkpydir("tpkg")
+ path.join("test_hello.py").write('raise ImportError')
+
+ result = testdir.runpytest_subprocess("--pyargs", "tpkg.test_hello")
+ assert result.ret != 0
+
+ result.stdout.fnmatch_lines([
+ "collected*0*items*/*1*errors"
+ ])
+
+ def test_cmdline_python_package(self, testdir, monkeypatch):
+ import warnings
+ monkeypatch.delenv('PYTHONDONTWRITEBYTECODE', False)
+ path = testdir.mkpydir("tpkg")
+ path.join("test_hello.py").write("def test_hello(): pass")
+ path.join("test_world.py").write("def test_world(): pass")
+ result = testdir.runpytest("--pyargs", "tpkg")
+ assert result.ret == 0
+ result.stdout.fnmatch_lines([
+ "*2 passed*"
+ ])
+ result = testdir.runpytest("--pyargs", "tpkg.test_hello")
+ assert result.ret == 0
+ result.stdout.fnmatch_lines([
+ "*1 passed*"
+ ])
+
+ def join_pythonpath(what):
+ cur = py.std.os.environ.get('PYTHONPATH')
+ if cur:
+ return str(what) + os.pathsep + cur
+ return what
+ empty_package = testdir.mkpydir("empty_package")
+ monkeypatch.setenv('PYTHONPATH', join_pythonpath(empty_package))
+ # the path which is not a package raises a warning on pypy;
+ # no idea why only pypy and not normal python warn about it here
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', ImportWarning)
+ result = testdir.runpytest("--pyargs", ".")
+ assert result.ret == 0
+ result.stdout.fnmatch_lines([
+ "*2 passed*"
+ ])
+
+ monkeypatch.setenv('PYTHONPATH', join_pythonpath(testdir))
+ result = testdir.runpytest("--pyargs", "tpkg.test_missing")
+ assert result.ret != 0
+ result.stderr.fnmatch_lines([
+ "*not*found*test_missing*",
+ ])
+
+ def test_cmdline_python_namespace_package(self, testdir, monkeypatch):
+ """
+ test --pyargs option with namespace packages (#1567)
+ """
+ monkeypatch.delenv('PYTHONDONTWRITEBYTECODE', raising=False)
+
+ search_path = []
+ for dirname in "hello", "world":
+ d = testdir.mkdir(dirname)
+ search_path.append(d)
+ ns = d.mkdir("ns_pkg")
+ ns.join("__init__.py").write(
+ "__import__('pkg_resources').declare_namespace(__name__)")
+ lib = ns.mkdir(dirname)
+ lib.ensure("__init__.py")
+ lib.join("test_{0}.py".format(dirname)). \
+ write("def test_{0}(): pass\n"
+ "def test_other():pass".format(dirname))
+
+ # The structure of the test directory is now:
+ # .
+ # ├── hello
+ # │   └── ns_pkg
+ # │   ├── __init__.py
+ # │   └── hello
+ # │   ├── __init__.py
+ # │   └── test_hello.py
+ # └── world
+ # └── ns_pkg
+ # ├── __init__.py
+ # └── world
+ # ├── __init__.py
+ # └── test_world.py
+
+ def join_pythonpath(*dirs):
+ cur = py.std.os.environ.get('PYTHONPATH')
+ if cur:
+ dirs += (cur,)
+ return os.pathsep.join(str(p) for p in dirs)
+ monkeypatch.setenv('PYTHONPATH', join_pythonpath(*search_path))
+ for p in search_path:
+ monkeypatch.syspath_prepend(p)
+
+ os.chdir('world')
+ # mixed module and filenames:
+ result = testdir.runpytest("--pyargs", "-v", "ns_pkg.hello", "ns_pkg/world")
+ testdir.chdir()
+ assert result.ret == 0
+ result.stdout.fnmatch_lines([
+ "*test_hello.py::test_hello*PASSED*",
+ "*test_hello.py::test_other*PASSED*",
+ "*test_world.py::test_world*PASSED*",
+ "*test_world.py::test_other*PASSED*",
+ "*4 passed*"
+ ])
+
+ # specify tests within a module
+ result = testdir.runpytest("--pyargs", "-v", "ns_pkg.world.test_world::test_other")
+ assert result.ret == 0
+ result.stdout.fnmatch_lines([
+ "*test_world.py::test_other*PASSED*",
+ "*1 passed*"
+ ])
+
+ def test_cmdline_python_package_not_exists(self, testdir):
+ result = testdir.runpytest("--pyargs", "tpkgwhatv")
+ assert result.ret
+ result.stderr.fnmatch_lines([
+ "ERROR*file*or*package*not*found*",
+ ])
+
+ @pytest.mark.xfail(reason="decide: feature or bug")
+ def test_noclass_discovery_if_not_testcase(self, testdir):
+ testpath = testdir.makepyfile("""
+ import unittest
+ class TestHello(object):
+ def test_hello(self):
+ assert self.attr
+
+ class RealTest(unittest.TestCase, TestHello):
+ attr = 42
+ """)
+ reprec = testdir.inline_run(testpath)
+ reprec.assertoutcome(passed=1)
+
+ def test_doctest_id(self, testdir):
+ testdir.makefile('.txt', """
+ >>> x=3
+ >>> x
+ 4
+ """)
+ result = testdir.runpytest("-rf")
+ lines = result.stdout.str().splitlines()
+ for line in lines:
+ if line.startswith("FAIL "):
+ testid = line[5:].strip()
+ break
+ result = testdir.runpytest(testid, '-rf')
+ result.stdout.fnmatch_lines([
+ line,
+ "*1 failed*",
+ ])
+
+ def test_core_backward_compatibility(self):
+ """Test backward compatibility for get_plugin_manager function. See #787."""
+ import _pytest.config
+ assert type(_pytest.config.get_plugin_manager()) is _pytest.config.PytestPluginManager
+
+ def test_has_plugin(self, request):
+ """Test hasplugin function of the plugin manager (#932)."""
+ assert request.config.pluginmanager.hasplugin('python')
+
+
+class TestDurations(object):
+ source = """
+ import time
+ frag = 0.002
+ def test_something():
+ pass
+ def test_2():
+ time.sleep(frag*5)
+ def test_1():
+ time.sleep(frag)
+ def test_3():
+ time.sleep(frag*10)
+ """
+
+ def test_calls(self, testdir):
+ testdir.makepyfile(self.source)
+ result = testdir.runpytest("--durations=10")
+ assert result.ret == 0
+ result.stdout.fnmatch_lines_random([
+ "*durations*",
+ "*call*test_3*",
+ "*call*test_2*",
+ "*call*test_1*",
+ ])
+
+ def test_calls_show_2(self, testdir):
+ testdir.makepyfile(self.source)
+ result = testdir.runpytest("--durations=2")
+ assert result.ret == 0
+ lines = result.stdout.get_lines_after("*slowest*durations*")
+ assert "4 passed" in lines[2]
+
+ def test_calls_showall(self, testdir):
+ testdir.makepyfile(self.source)
+ result = testdir.runpytest("--durations=0")
+ assert result.ret == 0
+ for x in "123":
+ for y in 'call', : # 'setup', 'call', 'teardown':
+ for line in result.stdout.lines:
+ if ("test_%s" % x) in line and y in line:
+ break
+ else:
+ raise AssertionError("not found %s %s" % (x, y))
+
+ def test_with_deselected(self, testdir):
+ testdir.makepyfile(self.source)
+ result = testdir.runpytest("--durations=2", "-k test_1")
+ assert result.ret == 0
+ result.stdout.fnmatch_lines([
+ "*durations*",
+ "*call*test_1*",
+ ])
+
+ def test_with_failing_collection(self, testdir):
+ testdir.makepyfile(self.source)
+ testdir.makepyfile(test_collecterror="""xyz""")
+ result = testdir.runpytest("--durations=2", "-k test_1")
+ assert result.ret == 2
+ result.stdout.fnmatch_lines([
+ "*Interrupted: 1 errors during collection*",
+ ])
+ # Collection errors abort test execution, therefore no duration is
+ # output
+ assert "duration" not in result.stdout.str()
+
+ def test_with_not(self, testdir):
+ testdir.makepyfile(self.source)
+ result = testdir.runpytest("-k not 1")
+ assert result.ret == 0
+
+
+class TestDurationWithFixture(object):
+ source = """
+ import time
+ frag = 0.001
+ def setup_function(func):
+ time.sleep(frag * 3)
+ def test_1():
+ time.sleep(frag*2)
+ def test_2():
+ time.sleep(frag)
+ """
+
+ def test_setup_function(self, testdir):
+ testdir.makepyfile(self.source)
+ result = testdir.runpytest("--durations=10")
+ assert result.ret == 0
+
+ result.stdout.fnmatch_lines_random("""
+ *durations*
+ * setup *test_1*
+ * call *test_1*
+ """)
+
+
+def test_zipimport_hook(testdir, tmpdir):
+ """Test package loader is being used correctly (see #1837)."""
+ zipapp = pytest.importorskip('zipapp')
+ testdir.tmpdir.join('app').ensure(dir=1)
+ testdir.makepyfile(**{
+ 'app/foo.py': """
+ import pytest
+ def main():
+ pytest.main(['--pyarg', 'foo'])
+ """,
+ })
+ target = tmpdir.join('foo.zip')
+ zipapp.create_archive(str(testdir.tmpdir.join('app')), str(target), main='foo:main')
+ result = testdir.runpython(target)
+ assert result.ret == 0
+ result.stderr.fnmatch_lines(['*not found*foo*'])
+ assert 'INTERNALERROR>' not in result.stdout.str()
+
+
+def test_import_plugin_unicode_name(testdir):
+ testdir.makepyfile(
+ myplugin='',
+ )
+ testdir.makepyfile("""
+ def test(): pass
+ """)
+ testdir.makeconftest("""
+ pytest_plugins = [u'myplugin']
+ """)
+ r = testdir.runpytest()
+ assert r.ret == 0
+
+
+def test_deferred_hook_checking(testdir):
+ """
+ Check hooks as late as possible (#1821).
+ """
+ testdir.syspathinsert()
+ testdir.makepyfile(**{
+ 'plugin.py': """
+ class Hooks:
+ def pytest_my_hook(self, config):
+ pass
+
+ def pytest_configure(config):
+ config.pluginmanager.add_hookspecs(Hooks)
+ """,
+ 'conftest.py': """
+ pytest_plugins = ['plugin']
+ def pytest_my_hook(config):
+ return 40
+ """,
+ 'test_foo.py': """
+ def test(request):
+ assert request.config.hook.pytest_my_hook(config=request.config) == [40]
+ """
+ })
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(['* 1 passed *'])
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/code/test_code.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/code/test_code.py
new file mode 100644
index 00000000000..209a8ef19a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/code/test_code.py
@@ -0,0 +1,196 @@
+# coding: utf-8
+from __future__ import absolute_import, division, print_function
+import sys
+
+import _pytest._code
+import py
+import pytest
+from test_excinfo import TWMock
+
+
+def test_ne():
+ code1 = _pytest._code.Code(compile('foo = "bar"', '', 'exec'))
+ assert code1 == code1
+ code2 = _pytest._code.Code(compile('foo = "baz"', '', 'exec'))
+ assert code2 != code1
+
+
+def test_code_gives_back_name_for_not_existing_file():
+ name = 'abc-123'
+ co_code = compile("pass\n", name, 'exec')
+ assert co_code.co_filename == name
+ code = _pytest._code.Code(co_code)
+ assert str(code.path) == name
+ assert code.fullsource is None
+
+
+def test_code_with_class():
+ class A(object):
+ pass
+ pytest.raises(TypeError, "_pytest._code.Code(A)")
+
+
+if True:
+ def x():
+ pass
+
+
+def test_code_fullsource():
+ code = _pytest._code.Code(x)
+ full = code.fullsource
+ assert 'test_code_fullsource()' in str(full)
+
+
+def test_code_source():
+ code = _pytest._code.Code(x)
+ src = code.source()
+ expected = """def x():
+ pass"""
+ assert str(src) == expected
+
+
+def test_frame_getsourcelineno_myself():
+ def func():
+ return sys._getframe(0)
+ f = func()
+ f = _pytest._code.Frame(f)
+ source, lineno = f.code.fullsource, f.lineno
+ assert source[lineno].startswith(" return sys._getframe(0)")
+
+
+def test_getstatement_empty_fullsource():
+ def func():
+ return sys._getframe(0)
+ f = func()
+ f = _pytest._code.Frame(f)
+ prop = f.code.__class__.fullsource
+ try:
+ f.code.__class__.fullsource = None
+ assert f.statement == _pytest._code.Source("")
+ finally:
+ f.code.__class__.fullsource = prop
+
+
+def test_code_from_func():
+ co = _pytest._code.Code(test_frame_getsourcelineno_myself)
+ assert co.firstlineno
+ assert co.path
+
+
+def test_unicode_handling():
+ value = py.builtin._totext('\xc4\x85\xc4\x87\n', 'utf-8').encode('utf8')
+
+ def f():
+ raise Exception(value)
+
+ excinfo = pytest.raises(Exception, f)
+ str(excinfo)
+ if sys.version_info[0] < 3:
+ unicode(excinfo)
+
+
+@pytest.mark.skipif(sys.version_info[0] >= 3, reason='python 2 only issue')
+def test_unicode_handling_syntax_error():
+ value = py.builtin._totext('\xc4\x85\xc4\x87\n', 'utf-8').encode('utf8')
+
+ def f():
+ raise SyntaxError('invalid syntax', (None, 1, 3, value))
+
+ excinfo = pytest.raises(Exception, f)
+ str(excinfo)
+ if sys.version_info[0] < 3:
+ unicode(excinfo)
+
+
+def test_code_getargs():
+ def f1(x):
+ pass
+ c1 = _pytest._code.Code(f1)
+ assert c1.getargs(var=True) == ('x',)
+
+ def f2(x, *y):
+ pass
+ c2 = _pytest._code.Code(f2)
+ assert c2.getargs(var=True) == ('x', 'y')
+
+ def f3(x, **z):
+ pass
+ c3 = _pytest._code.Code(f3)
+ assert c3.getargs(var=True) == ('x', 'z')
+
+ def f4(x, *y, **z):
+ pass
+ c4 = _pytest._code.Code(f4)
+ assert c4.getargs(var=True) == ('x', 'y', 'z')
+
+
+def test_frame_getargs():
+ def f1(x):
+ return sys._getframe(0)
+ fr1 = _pytest._code.Frame(f1('a'))
+ assert fr1.getargs(var=True) == [('x', 'a')]
+
+ def f2(x, *y):
+ return sys._getframe(0)
+ fr2 = _pytest._code.Frame(f2('a', 'b', 'c'))
+ assert fr2.getargs(var=True) == [('x', 'a'), ('y', ('b', 'c'))]
+
+ def f3(x, **z):
+ return sys._getframe(0)
+ fr3 = _pytest._code.Frame(f3('a', b='c'))
+ assert fr3.getargs(var=True) == [('x', 'a'), ('z', {'b': 'c'})]
+
+ def f4(x, *y, **z):
+ return sys._getframe(0)
+ fr4 = _pytest._code.Frame(f4('a', 'b', c='d'))
+ assert fr4.getargs(var=True) == [('x', 'a'), ('y', ('b',)),
+ ('z', {'c': 'd'})]
+
+
+class TestExceptionInfo(object):
+
+ def test_bad_getsource(self):
+ try:
+ if False:
+ pass
+ else:
+ assert False
+ except AssertionError:
+ exci = _pytest._code.ExceptionInfo()
+ assert exci.getrepr()
+
+
+class TestTracebackEntry(object):
+
+ def test_getsource(self):
+ try:
+ if False:
+ pass
+ else:
+ assert False
+ except AssertionError:
+ exci = _pytest._code.ExceptionInfo()
+ entry = exci.traceback[0]
+ source = entry.getsource()
+ assert len(source) == 6
+ assert 'assert False' in source[5]
+
+
+class TestReprFuncArgs(object):
+
+ def test_not_raise_exception_with_mixed_encoding(self):
+ from _pytest._code.code import ReprFuncArgs
+
+ tw = TWMock()
+
+ args = [
+ ('unicode_string', u"São Paulo"),
+ ('utf8_string', 'S\xc3\xa3o Paulo'),
+ ]
+
+ r = ReprFuncArgs(args)
+ r.toterminal(tw)
+ if sys.version_info[0] >= 3:
+ assert tw.lines[0] == 'unicode_string = São Paulo, utf8_string = São Paulo'
+ else:
+ assert tw.lines[0] == 'unicode_string = São Paulo, utf8_string = São Paulo'
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/code/test_excinfo.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/code/test_excinfo.py
new file mode 100644
index 00000000000..34db8ffa189
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/code/test_excinfo.py
@@ -0,0 +1,1245 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import, division, print_function
+
+import operator
+import _pytest
+import py
+import pytest
+from _pytest._code.code import (
+ ExceptionInfo,
+ FormattedExcinfo,
+ ReprExceptionInfo,
+ ExceptionChainRepr)
+
+from test_source import astonly
+
+try:
+ import importlib
+except ImportError:
+ invalidate_import_caches = None
+else:
+ invalidate_import_caches = getattr(importlib, "invalidate_caches", None)
+
+queue = py.builtin._tryimport('queue', 'Queue')
+
+failsonjython = pytest.mark.xfail("sys.platform.startswith('java')")
+
+pytest_version_info = tuple(map(int, pytest.__version__.split(".")[:3]))
+
+
+class TWMock(object):
+ WRITE = object()
+
+ def __init__(self):
+ self.lines = []
+ self.is_writing = False
+
+ def sep(self, sep, line=None):
+ self.lines.append((sep, line))
+
+ def write(self, msg, **kw):
+ self.lines.append((TWMock.WRITE, msg))
+
+ def line(self, line, **kw):
+ self.lines.append(line)
+
+ def markup(self, text, **kw):
+ return text
+
+ def get_write_msg(self, idx):
+ flag, msg = self.lines[idx]
+ assert flag == TWMock.WRITE
+ return msg
+
+ fullwidth = 80
+
+
+def test_excinfo_simple():
+ try:
+ raise ValueError
+ except ValueError:
+ info = _pytest._code.ExceptionInfo()
+ assert info.type == ValueError
+
+
+def test_excinfo_getstatement():
+ def g():
+ raise ValueError
+
+ def f():
+ g()
+
+ try:
+ f()
+ except ValueError:
+ excinfo = _pytest._code.ExceptionInfo()
+ linenumbers = [_pytest._code.getrawcode(f).co_firstlineno - 1 + 4,
+ _pytest._code.getrawcode(f).co_firstlineno - 1 + 1,
+ _pytest._code.getrawcode(g).co_firstlineno - 1 + 1, ]
+ values = list(excinfo.traceback)
+ foundlinenumbers = [x.lineno for x in values]
+ assert foundlinenumbers == linenumbers
+ # for x in info:
+ # print "%s:%d %s" %(x.path.relto(root), x.lineno, x.statement)
+ # xxx
+
+# testchain for getentries test below
+
+
+def f():
+ #
+ raise ValueError
+ #
+
+
+def g():
+ #
+ __tracebackhide__ = True
+ f()
+ #
+
+
+def h():
+ #
+ g()
+ #
+
+
+class TestTraceback_f_g_h(object):
+ def setup_method(self, method):
+ try:
+ h()
+ except ValueError:
+ self.excinfo = _pytest._code.ExceptionInfo()
+
+ def test_traceback_entries(self):
+ tb = self.excinfo.traceback
+ entries = list(tb)
+ assert len(tb) == 4 # maybe fragile test
+ assert len(entries) == 4 # maybe fragile test
+ names = ['f', 'g', 'h']
+ for entry in entries:
+ try:
+ names.remove(entry.frame.code.name)
+ except ValueError:
+ pass
+ assert not names
+
+ def test_traceback_entry_getsource(self):
+ tb = self.excinfo.traceback
+ s = str(tb[-1].getsource())
+ assert s.startswith("def f():")
+ assert s.endswith("raise ValueError")
+
+ @astonly
+ @failsonjython
+ def test_traceback_entry_getsource_in_construct(self):
+ source = _pytest._code.Source("""\
+ def xyz():
+ try:
+ raise ValueError
+ except somenoname:
+ pass
+ xyz()
+ """)
+ try:
+ exec(source.compile())
+ except NameError:
+ tb = _pytest._code.ExceptionInfo().traceback
+ print(tb[-1].getsource())
+ s = str(tb[-1].getsource())
+ assert s.startswith("def xyz():\n try:")
+ assert s.strip().endswith("except somenoname:")
+
+ def test_traceback_cut(self):
+ co = _pytest._code.Code(f)
+ path, firstlineno = co.path, co.firstlineno
+ traceback = self.excinfo.traceback
+ newtraceback = traceback.cut(path=path, firstlineno=firstlineno)
+ assert len(newtraceback) == 1
+ newtraceback = traceback.cut(path=path, lineno=firstlineno + 2)
+ assert len(newtraceback) == 1
+
+ def test_traceback_cut_excludepath(self, testdir):
+ p = testdir.makepyfile("def f(): raise ValueError")
+ excinfo = pytest.raises(ValueError, "p.pyimport().f()")
+ basedir = py.path.local(pytest.__file__).dirpath()
+ newtraceback = excinfo.traceback.cut(excludepath=basedir)
+ for x in newtraceback:
+ if hasattr(x, 'path'):
+ assert not py.path.local(x.path).relto(basedir)
+ assert newtraceback[-1].frame.code.path == p
+
+ def test_traceback_filter(self):
+ traceback = self.excinfo.traceback
+ ntraceback = traceback.filter()
+ assert len(ntraceback) == len(traceback) - 1
+
+ @pytest.mark.parametrize('tracebackhide, matching', [
+ (lambda info: True, True),
+ (lambda info: False, False),
+ (operator.methodcaller('errisinstance', ValueError), True),
+ (operator.methodcaller('errisinstance', IndexError), False),
+ ])
+ def test_traceback_filter_selective(self, tracebackhide, matching):
+ def f():
+ #
+ raise ValueError
+ #
+
+ def g():
+ #
+ __tracebackhide__ = tracebackhide
+ f()
+ #
+
+ def h():
+ #
+ g()
+ #
+
+ excinfo = pytest.raises(ValueError, h)
+ traceback = excinfo.traceback
+ ntraceback = traceback.filter()
+ print('old: {0!r}'.format(traceback))
+ print('new: {0!r}'.format(ntraceback))
+
+ if matching:
+ assert len(ntraceback) == len(traceback) - 2
+ else:
+ # -1 because of the __tracebackhide__ in pytest.raises
+ assert len(ntraceback) == len(traceback) - 1
+
+ def test_traceback_recursion_index(self):
+ def f(n):
+ if n < 10:
+ n += 1
+ f(n)
+ excinfo = pytest.raises(RuntimeError, f, 8)
+ traceback = excinfo.traceback
+ recindex = traceback.recursionindex()
+ assert recindex == 3
+
+ def test_traceback_only_specific_recursion_errors(self, monkeypatch):
+ def f(n):
+ if n == 0:
+ raise RuntimeError("hello")
+ f(n - 1)
+
+ excinfo = pytest.raises(RuntimeError, f, 100)
+ monkeypatch.delattr(excinfo.traceback.__class__, "recursionindex")
+ repr = excinfo.getrepr()
+ assert "RuntimeError: hello" in str(repr.reprcrash)
+
+ def test_traceback_no_recursion_index(self):
+ def do_stuff():
+ raise RuntimeError
+
+ def reraise_me():
+ import sys
+ exc, val, tb = sys.exc_info()
+ py.builtin._reraise(exc, val, tb)
+
+ def f(n):
+ try:
+ do_stuff()
+ except: # noqa
+ reraise_me()
+
+ excinfo = pytest.raises(RuntimeError, f, 8)
+ traceback = excinfo.traceback
+ recindex = traceback.recursionindex()
+ assert recindex is None
+
+ def test_traceback_messy_recursion(self):
+ # XXX: simplified locally testable version
+ decorator = pytest.importorskip('decorator').decorator
+
+ def log(f, *k, **kw):
+ print('%s %s' % (k, kw))
+ f(*k, **kw)
+ log = decorator(log)
+
+ def fail():
+ raise ValueError('')
+
+ fail = log(log(fail))
+
+ excinfo = pytest.raises(ValueError, fail)
+ assert excinfo.traceback.recursionindex() is None
+
+ def test_traceback_getcrashentry(self):
+ def i():
+ __tracebackhide__ = True
+ raise ValueError
+
+ def h():
+ i()
+
+ def g():
+ __tracebackhide__ = True
+ h()
+
+ def f():
+ g()
+
+ excinfo = pytest.raises(ValueError, f)
+ tb = excinfo.traceback
+ entry = tb.getcrashentry()
+ co = _pytest._code.Code(h)
+ assert entry.frame.code.path == co.path
+ assert entry.lineno == co.firstlineno + 1
+ assert entry.frame.code.name == 'h'
+
+ def test_traceback_getcrashentry_empty(self):
+ def g():
+ __tracebackhide__ = True
+ raise ValueError
+
+ def f():
+ __tracebackhide__ = True
+ g()
+
+ excinfo = pytest.raises(ValueError, f)
+ tb = excinfo.traceback
+ entry = tb.getcrashentry()
+ co = _pytest._code.Code(g)
+ assert entry.frame.code.path == co.path
+ assert entry.lineno == co.firstlineno + 2
+ assert entry.frame.code.name == 'g'
+
+
+def test_excinfo_exconly():
+ excinfo = pytest.raises(ValueError, h)
+ assert excinfo.exconly().startswith('ValueError')
+ excinfo = pytest.raises(ValueError,
+ "raise ValueError('hello\\nworld')")
+ msg = excinfo.exconly(tryshort=True)
+ assert msg.startswith('ValueError')
+ assert msg.endswith("world")
+
+
+def test_excinfo_repr():
+ excinfo = pytest.raises(ValueError, h)
+ s = repr(excinfo)
+ assert s == "<ExceptionInfo ValueError tblen=4>"
+
+
+def test_excinfo_str():
+ excinfo = pytest.raises(ValueError, h)
+ s = str(excinfo)
+ assert s.startswith(__file__[:-9]) # pyc file and $py.class
+ assert s.endswith("ValueError")
+ assert len(s.split(":")) >= 3 # on windows it's 4
+
+
+def test_excinfo_errisinstance():
+ excinfo = pytest.raises(ValueError, h)
+ assert excinfo.errisinstance(ValueError)
+
+
+def test_excinfo_no_sourcecode():
+ try:
+ exec("raise ValueError()")
+ except ValueError:
+ excinfo = _pytest._code.ExceptionInfo()
+ s = str(excinfo.traceback[-1])
+ assert s == " File '<string>':1 in <module>\n ???\n"
+
+
+def test_excinfo_no_python_sourcecode(tmpdir):
+ # XXX: simplified locally testable version
+ tmpdir.join('test.txt').write("{{ h()}}:")
+
+ jinja2 = pytest.importorskip('jinja2')
+ loader = jinja2.FileSystemLoader(str(tmpdir))
+ env = jinja2.Environment(loader=loader)
+ template = env.get_template('test.txt')
+ excinfo = pytest.raises(ValueError,
+ template.render, h=h)
+ for item in excinfo.traceback:
+ print(item) # XXX: for some reason jinja.Template.render is printed in full
+ item.source # shouldnt fail
+ if item.path.basename == 'test.txt':
+ assert str(item.source) == '{{ h()}}:'
+
+
+def test_entrysource_Queue_example():
+ try:
+ queue.Queue().get(timeout=0.001)
+ except queue.Empty:
+ excinfo = _pytest._code.ExceptionInfo()
+ entry = excinfo.traceback[-1]
+ source = entry.getsource()
+ assert source is not None
+ s = str(source).strip()
+ assert s.startswith("def get")
+
+
+def test_codepath_Queue_example():
+ try:
+ queue.Queue().get(timeout=0.001)
+ except queue.Empty:
+ excinfo = _pytest._code.ExceptionInfo()
+ entry = excinfo.traceback[-1]
+ path = entry.path
+ assert isinstance(path, py.path.local)
+ assert path.basename.lower() == "queue.py"
+ assert path.check()
+
+
+def test_match_succeeds():
+ with pytest.raises(ZeroDivisionError) as excinfo:
+ 0 // 0
+ excinfo.match(r'.*zero.*')
+
+
+def test_match_raises_error(testdir):
+ testdir.makepyfile("""
+ import pytest
+ def test_division_zero():
+ with pytest.raises(ZeroDivisionError) as excinfo:
+ 0 / 0
+ excinfo.match(r'[123]+')
+ """)
+ result = testdir.runpytest()
+ assert result.ret != 0
+ result.stdout.fnmatch_lines([
+ "*AssertionError*Pattern*[123]*not found*",
+ ])
+
+
+class TestFormattedExcinfo(object):
+
+ @pytest.fixture
+ def importasmod(self, request):
+ def importasmod(source):
+ source = _pytest._code.Source(source)
+ tmpdir = request.getfixturevalue("tmpdir")
+ modpath = tmpdir.join("mod.py")
+ tmpdir.ensure("__init__.py")
+ modpath.write(source)
+ if invalidate_import_caches is not None:
+ invalidate_import_caches()
+ return modpath.pyimport()
+ return importasmod
+
+ def excinfo_from_exec(self, source):
+ source = _pytest._code.Source(source).strip()
+ try:
+ exec(source.compile())
+ except KeyboardInterrupt:
+ raise
+ except: # noqa
+ return _pytest._code.ExceptionInfo()
+ assert 0, "did not raise"
+
+ def test_repr_source(self):
+ pr = FormattedExcinfo()
+ source = _pytest._code.Source("""
+ def f(x):
+ pass
+ """).strip()
+ pr.flow_marker = "|"
+ lines = pr.get_source(source, 0)
+ assert len(lines) == 2
+ assert lines[0] == "| def f(x):"
+ assert lines[1] == " pass"
+
+ def test_repr_source_excinfo(self):
+ """ check if indentation is right """
+ pr = FormattedExcinfo()
+ excinfo = self.excinfo_from_exec("""
+ def f():
+ assert 0
+ f()
+ """)
+ pr = FormattedExcinfo()
+ source = pr._getentrysource(excinfo.traceback[-1])
+ lines = pr.get_source(source, 1, excinfo)
+ assert lines == [
+ ' def f():',
+ '> assert 0',
+ 'E AssertionError'
+ ]
+
+ def test_repr_source_not_existing(self):
+ pr = FormattedExcinfo()
+ co = compile("raise ValueError()", "", "exec")
+ try:
+ exec(co)
+ except ValueError:
+ excinfo = _pytest._code.ExceptionInfo()
+ repr = pr.repr_excinfo(excinfo)
+ assert repr.reprtraceback.reprentries[1].lines[0] == "> ???"
+ if py.std.sys.version_info[0] >= 3:
+ assert repr.chain[0][0].reprentries[1].lines[0] == "> ???"
+
+ def test_repr_many_line_source_not_existing(self):
+ pr = FormattedExcinfo()
+ co = compile("""
+a = 1
+raise ValueError()
+""", "", "exec")
+ try:
+ exec(co)
+ except ValueError:
+ excinfo = _pytest._code.ExceptionInfo()
+ repr = pr.repr_excinfo(excinfo)
+ assert repr.reprtraceback.reprentries[1].lines[0] == "> ???"
+ if py.std.sys.version_info[0] >= 3:
+ assert repr.chain[0][0].reprentries[1].lines[0] == "> ???"
+
+ def test_repr_source_failing_fullsource(self):
+ pr = FormattedExcinfo()
+
+ class FakeCode(object):
+ class raw(object):
+ co_filename = '?'
+
+ path = '?'
+ firstlineno = 5
+
+ def fullsource(self):
+ return None
+
+ fullsource = property(fullsource)
+
+ class FakeFrame(object):
+ code = FakeCode()
+ f_locals = {}
+ f_globals = {}
+
+ class FakeTracebackEntry(_pytest._code.Traceback.Entry):
+ def __init__(self, tb, excinfo=None):
+ self.lineno = 5 + 3
+
+ @property
+ def frame(self):
+ return FakeFrame()
+
+ class Traceback(_pytest._code.Traceback):
+ Entry = FakeTracebackEntry
+
+ class FakeExcinfo(_pytest._code.ExceptionInfo):
+ typename = "Foo"
+ value = Exception()
+
+ def __init__(self):
+ pass
+
+ def exconly(self, tryshort):
+ return "EXC"
+
+ def errisinstance(self, cls):
+ return False
+
+ excinfo = FakeExcinfo()
+
+ class FakeRawTB(object):
+ tb_next = None
+
+ tb = FakeRawTB()
+ excinfo.traceback = Traceback(tb)
+
+ fail = IOError() # noqa
+ repr = pr.repr_excinfo(excinfo)
+ assert repr.reprtraceback.reprentries[0].lines[0] == "> ???"
+ if py.std.sys.version_info[0] >= 3:
+ assert repr.chain[0][0].reprentries[0].lines[0] == "> ???"
+
+ fail = py.error.ENOENT # noqa
+ repr = pr.repr_excinfo(excinfo)
+ assert repr.reprtraceback.reprentries[0].lines[0] == "> ???"
+ if py.std.sys.version_info[0] >= 3:
+ assert repr.chain[0][0].reprentries[0].lines[0] == "> ???"
+
+ def test_repr_local(self):
+ p = FormattedExcinfo(showlocals=True)
+ loc = {'y': 5, 'z': 7, 'x': 3, '@x': 2, '__builtins__': {}}
+ reprlocals = p.repr_locals(loc)
+ assert reprlocals.lines
+ assert reprlocals.lines[0] == '__builtins__ = <builtins>'
+ assert reprlocals.lines[1] == 'x = 3'
+ assert reprlocals.lines[2] == 'y = 5'
+ assert reprlocals.lines[3] == 'z = 7'
+
+ def test_repr_tracebackentry_lines(self, importasmod):
+ mod = importasmod("""
+ def func1():
+ raise ValueError("hello\\nworld")
+ """)
+ excinfo = pytest.raises(ValueError, mod.func1)
+ excinfo.traceback = excinfo.traceback.filter()
+ p = FormattedExcinfo()
+ reprtb = p.repr_traceback_entry(excinfo.traceback[-1])
+
+ # test as intermittent entry
+ lines = reprtb.lines
+ assert lines[0] == ' def func1():'
+ assert lines[1] == '> raise ValueError("hello\\nworld")'
+
+ # test as last entry
+ p = FormattedExcinfo(showlocals=True)
+ repr_entry = p.repr_traceback_entry(excinfo.traceback[-1], excinfo)
+ lines = repr_entry.lines
+ assert lines[0] == ' def func1():'
+ assert lines[1] == '> raise ValueError("hello\\nworld")'
+ assert lines[2] == 'E ValueError: hello'
+ assert lines[3] == 'E world'
+ assert not lines[4:]
+
+ loc = repr_entry.reprlocals is not None
+ loc = repr_entry.reprfileloc
+ assert loc.path == mod.__file__
+ assert loc.lineno == 3
+ # assert loc.message == "ValueError: hello"
+
+ def test_repr_tracebackentry_lines2(self, importasmod):
+ mod = importasmod("""
+ def func1(m, x, y, z):
+ raise ValueError("hello\\nworld")
+ """)
+ excinfo = pytest.raises(ValueError, mod.func1, "m" * 90, 5, 13, "z" * 120)
+ excinfo.traceback = excinfo.traceback.filter()
+ entry = excinfo.traceback[-1]
+ p = FormattedExcinfo(funcargs=True)
+ reprfuncargs = p.repr_args(entry)
+ assert reprfuncargs.args[0] == ('m', repr("m" * 90))
+ assert reprfuncargs.args[1] == ('x', '5')
+ assert reprfuncargs.args[2] == ('y', '13')
+ assert reprfuncargs.args[3] == ('z', repr("z" * 120))
+
+ p = FormattedExcinfo(funcargs=True)
+ repr_entry = p.repr_traceback_entry(entry)
+ assert repr_entry.reprfuncargs.args == reprfuncargs.args
+ tw = TWMock()
+ repr_entry.toterminal(tw)
+ assert tw.lines[0] == "m = " + repr('m' * 90)
+ assert tw.lines[1] == "x = 5, y = 13"
+ assert tw.lines[2] == "z = " + repr('z' * 120)
+
+ def test_repr_tracebackentry_lines_var_kw_args(self, importasmod):
+ mod = importasmod("""
+ def func1(x, *y, **z):
+ raise ValueError("hello\\nworld")
+ """)
+ excinfo = pytest.raises(ValueError, mod.func1, 'a', 'b', c='d')
+ excinfo.traceback = excinfo.traceback.filter()
+ entry = excinfo.traceback[-1]
+ p = FormattedExcinfo(funcargs=True)
+ reprfuncargs = p.repr_args(entry)
+ assert reprfuncargs.args[0] == ('x', repr('a'))
+ assert reprfuncargs.args[1] == ('y', repr(('b',)))
+ assert reprfuncargs.args[2] == ('z', repr({'c': 'd'}))
+
+ p = FormattedExcinfo(funcargs=True)
+ repr_entry = p.repr_traceback_entry(entry)
+ assert repr_entry.reprfuncargs.args == reprfuncargs.args
+ tw = TWMock()
+ repr_entry.toterminal(tw)
+ assert tw.lines[0] == "x = 'a', y = ('b',), z = {'c': 'd'}"
+
+ def test_repr_tracebackentry_short(self, importasmod):
+ mod = importasmod("""
+ def func1():
+ raise ValueError("hello")
+ def entry():
+ func1()
+ """)
+ excinfo = pytest.raises(ValueError, mod.entry)
+ p = FormattedExcinfo(style="short")
+ reprtb = p.repr_traceback_entry(excinfo.traceback[-2])
+ lines = reprtb.lines
+ basename = py.path.local(mod.__file__).basename
+ assert lines[0] == ' func1()'
+ assert basename in str(reprtb.reprfileloc.path)
+ assert reprtb.reprfileloc.lineno == 5
+
+ # test last entry
+ p = FormattedExcinfo(style="short")
+ reprtb = p.repr_traceback_entry(excinfo.traceback[-1], excinfo)
+ lines = reprtb.lines
+ assert lines[0] == ' raise ValueError("hello")'
+ assert lines[1] == 'E ValueError: hello'
+ assert basename in str(reprtb.reprfileloc.path)
+ assert reprtb.reprfileloc.lineno == 3
+
+ def test_repr_tracebackentry_no(self, importasmod):
+ mod = importasmod("""
+ def func1():
+ raise ValueError("hello")
+ def entry():
+ func1()
+ """)
+ excinfo = pytest.raises(ValueError, mod.entry)
+ p = FormattedExcinfo(style="no")
+ p.repr_traceback_entry(excinfo.traceback[-2])
+
+ p = FormattedExcinfo(style="no")
+ reprentry = p.repr_traceback_entry(excinfo.traceback[-1], excinfo)
+ lines = reprentry.lines
+ assert lines[0] == 'E ValueError: hello'
+ assert not lines[1:]
+
+ def test_repr_traceback_tbfilter(self, importasmod):
+ mod = importasmod("""
+ def f(x):
+ raise ValueError(x)
+ def entry():
+ f(0)
+ """)
+ excinfo = pytest.raises(ValueError, mod.entry)
+ p = FormattedExcinfo(tbfilter=True)
+ reprtb = p.repr_traceback(excinfo)
+ assert len(reprtb.reprentries) == 2
+ p = FormattedExcinfo(tbfilter=False)
+ reprtb = p.repr_traceback(excinfo)
+ assert len(reprtb.reprentries) == 3
+
+ def test_traceback_short_no_source(self, importasmod, monkeypatch):
+ mod = importasmod("""
+ def func1():
+ raise ValueError("hello")
+ def entry():
+ func1()
+ """)
+ excinfo = pytest.raises(ValueError, mod.entry)
+ from _pytest._code.code import Code
+ monkeypatch.setattr(Code, 'path', 'bogus')
+ excinfo.traceback[0].frame.code.path = "bogus"
+ p = FormattedExcinfo(style="short")
+ reprtb = p.repr_traceback_entry(excinfo.traceback[-2])
+ lines = reprtb.lines
+ last_p = FormattedExcinfo(style="short")
+ last_reprtb = last_p.repr_traceback_entry(excinfo.traceback[-1], excinfo)
+ last_lines = last_reprtb.lines
+ monkeypatch.undo()
+ assert lines[0] == ' func1()'
+
+ assert last_lines[0] == ' raise ValueError("hello")'
+ assert last_lines[1] == 'E ValueError: hello'
+
+ def test_repr_traceback_and_excinfo(self, importasmod):
+ mod = importasmod("""
+ def f(x):
+ raise ValueError(x)
+ def entry():
+ f(0)
+ """)
+ excinfo = pytest.raises(ValueError, mod.entry)
+
+ for style in ("long", "short"):
+ p = FormattedExcinfo(style=style)
+ reprtb = p.repr_traceback(excinfo)
+ assert len(reprtb.reprentries) == 2
+ assert reprtb.style == style
+ assert not reprtb.extraline
+ repr = p.repr_excinfo(excinfo)
+ assert repr.reprtraceback
+ assert len(repr.reprtraceback.reprentries) == len(reprtb.reprentries)
+ if py.std.sys.version_info[0] >= 3:
+ assert repr.chain[0][0]
+ assert len(repr.chain[0][0].reprentries) == len(reprtb.reprentries)
+ assert repr.reprcrash.path.endswith("mod.py")
+ assert repr.reprcrash.message == "ValueError: 0"
+
+ def test_repr_traceback_with_invalid_cwd(self, importasmod, monkeypatch):
+ mod = importasmod("""
+ def f(x):
+ raise ValueError(x)
+ def entry():
+ f(0)
+ """)
+ excinfo = pytest.raises(ValueError, mod.entry)
+
+ p = FormattedExcinfo()
+
+ def raiseos():
+ raise OSError(2)
+
+ monkeypatch.setattr(py.std.os, 'getcwd', raiseos)
+ assert p._makepath(__file__) == __file__
+ p.repr_traceback(excinfo)
+
+ def test_repr_excinfo_addouterr(self, importasmod):
+ mod = importasmod("""
+ def entry():
+ raise ValueError()
+ """)
+ excinfo = pytest.raises(ValueError, mod.entry)
+ repr = excinfo.getrepr()
+ repr.addsection("title", "content")
+ twmock = TWMock()
+ repr.toterminal(twmock)
+ assert twmock.lines[-1] == "content"
+ assert twmock.lines[-2] == ("-", "title")
+
+ def test_repr_excinfo_reprcrash(self, importasmod):
+ mod = importasmod("""
+ def entry():
+ raise ValueError()
+ """)
+ excinfo = pytest.raises(ValueError, mod.entry)
+ repr = excinfo.getrepr()
+ assert repr.reprcrash.path.endswith("mod.py")
+ assert repr.reprcrash.lineno == 3
+ assert repr.reprcrash.message == "ValueError"
+ assert str(repr.reprcrash).endswith("mod.py:3: ValueError")
+
+ def test_repr_traceback_recursion(self, importasmod):
+ mod = importasmod("""
+ def rec2(x):
+ return rec1(x+1)
+ def rec1(x):
+ return rec2(x-1)
+ def entry():
+ rec1(42)
+ """)
+ excinfo = pytest.raises(RuntimeError, mod.entry)
+
+ for style in ("short", "long", "no"):
+ p = FormattedExcinfo(style="short")
+ reprtb = p.repr_traceback(excinfo)
+ assert reprtb.extraline == "!!! Recursion detected (same locals & position)"
+ assert str(reprtb)
+
+ def test_reprexcinfo_getrepr(self, importasmod):
+ mod = importasmod("""
+ def f(x):
+ raise ValueError(x)
+ def entry():
+ f(0)
+ """)
+ excinfo = pytest.raises(ValueError, mod.entry)
+
+ for style in ("short", "long", "no"):
+ for showlocals in (True, False):
+ repr = excinfo.getrepr(style=style, showlocals=showlocals)
+ if py.std.sys.version_info[0] < 3:
+ assert isinstance(repr, ReprExceptionInfo)
+ assert repr.reprtraceback.style == style
+ if py.std.sys.version_info[0] >= 3:
+ assert isinstance(repr, ExceptionChainRepr)
+ for repr in repr.chain:
+ assert repr[0].style == style
+
+ def test_reprexcinfo_unicode(self):
+ from _pytest._code.code import TerminalRepr
+
+ class MyRepr(TerminalRepr):
+ def toterminal(self, tw):
+ tw.line(py.builtin._totext("я", "utf-8"))
+
+ x = py.builtin._totext(MyRepr())
+ assert x == py.builtin._totext("я", "utf-8")
+
+ def test_toterminal_long(self, importasmod):
+ mod = importasmod("""
+ def g(x):
+ raise ValueError(x)
+ def f():
+ g(3)
+ """)
+ excinfo = pytest.raises(ValueError, mod.f)
+ excinfo.traceback = excinfo.traceback.filter()
+ repr = excinfo.getrepr()
+ tw = TWMock()
+ repr.toterminal(tw)
+ assert tw.lines[0] == ""
+ tw.lines.pop(0)
+ assert tw.lines[0] == " def f():"
+ assert tw.lines[1] == "> g(3)"
+ assert tw.lines[2] == ""
+ line = tw.get_write_msg(3)
+ assert line.endswith("mod.py")
+ assert tw.lines[4] == (":5: ")
+ assert tw.lines[5] == ("_ ", None)
+ assert tw.lines[6] == ""
+ assert tw.lines[7] == " def g(x):"
+ assert tw.lines[8] == "> raise ValueError(x)"
+ assert tw.lines[9] == "E ValueError: 3"
+ assert tw.lines[10] == ""
+ line = tw.get_write_msg(11)
+ assert line.endswith("mod.py")
+ assert tw.lines[12] == ":3: ValueError"
+
+ def test_toterminal_long_missing_source(self, importasmod, tmpdir):
+ mod = importasmod("""
+ def g(x):
+ raise ValueError(x)
+ def f():
+ g(3)
+ """)
+ excinfo = pytest.raises(ValueError, mod.f)
+ tmpdir.join('mod.py').remove()
+ excinfo.traceback = excinfo.traceback.filter()
+ repr = excinfo.getrepr()
+ tw = TWMock()
+ repr.toterminal(tw)
+ assert tw.lines[0] == ""
+ tw.lines.pop(0)
+ assert tw.lines[0] == "> ???"
+ assert tw.lines[1] == ""
+ line = tw.get_write_msg(2)
+ assert line.endswith("mod.py")
+ assert tw.lines[3] == ":5: "
+ assert tw.lines[4] == ("_ ", None)
+ assert tw.lines[5] == ""
+ assert tw.lines[6] == "> ???"
+ assert tw.lines[7] == "E ValueError: 3"
+ assert tw.lines[8] == ""
+ line = tw.get_write_msg(9)
+ assert line.endswith("mod.py")
+ assert tw.lines[10] == ":3: ValueError"
+
+ def test_toterminal_long_incomplete_source(self, importasmod, tmpdir):
+ mod = importasmod("""
+ def g(x):
+ raise ValueError(x)
+ def f():
+ g(3)
+ """)
+ excinfo = pytest.raises(ValueError, mod.f)
+ tmpdir.join('mod.py').write('asdf')
+ excinfo.traceback = excinfo.traceback.filter()
+ repr = excinfo.getrepr()
+ tw = TWMock()
+ repr.toterminal(tw)
+ assert tw.lines[0] == ""
+ tw.lines.pop(0)
+ assert tw.lines[0] == "> ???"
+ assert tw.lines[1] == ""
+ line = tw.get_write_msg(2)
+ assert line.endswith("mod.py")
+ assert tw.lines[3] == ":5: "
+ assert tw.lines[4] == ("_ ", None)
+ assert tw.lines[5] == ""
+ assert tw.lines[6] == "> ???"
+ assert tw.lines[7] == "E ValueError: 3"
+ assert tw.lines[8] == ""
+ line = tw.get_write_msg(9)
+ assert line.endswith("mod.py")
+ assert tw.lines[10] == ":3: ValueError"
+
+ def test_toterminal_long_filenames(self, importasmod):
+ mod = importasmod("""
+ def f():
+ raise ValueError()
+ """)
+ excinfo = pytest.raises(ValueError, mod.f)
+ tw = TWMock()
+ path = py.path.local(mod.__file__)
+ old = path.dirpath().chdir()
+ try:
+ repr = excinfo.getrepr(abspath=False)
+ repr.toterminal(tw)
+ x = py.path.local().bestrelpath(path)
+ if len(x) < len(str(path)):
+ msg = tw.get_write_msg(-2)
+ assert msg == "mod.py"
+ assert tw.lines[-1] == ":3: ValueError"
+
+ repr = excinfo.getrepr(abspath=True)
+ repr.toterminal(tw)
+ msg = tw.get_write_msg(-2)
+ assert msg == path
+ line = tw.lines[-1]
+ assert line == ":3: ValueError"
+ finally:
+ old.chdir()
+
+ @pytest.mark.parametrize('reproptions', [
+ {'style': style, 'showlocals': showlocals,
+ 'funcargs': funcargs, 'tbfilter': tbfilter
+ } for style in ("long", "short", "no")
+ for showlocals in (True, False)
+ for tbfilter in (True, False)
+ for funcargs in (True, False)])
+ def test_format_excinfo(self, importasmod, reproptions):
+ mod = importasmod("""
+ def g(x):
+ raise ValueError(x)
+ def f():
+ g(3)
+ """)
+ excinfo = pytest.raises(ValueError, mod.f)
+ tw = py.io.TerminalWriter(stringio=True)
+ repr = excinfo.getrepr(**reproptions)
+ repr.toterminal(tw)
+ assert tw.stringio.getvalue()
+
+ def test_traceback_repr_style(self, importasmod):
+ mod = importasmod("""
+ def f():
+ g()
+ def g():
+ h()
+ def h():
+ i()
+ def i():
+ raise ValueError()
+ """)
+ excinfo = pytest.raises(ValueError, mod.f)
+ excinfo.traceback = excinfo.traceback.filter()
+ excinfo.traceback[1].set_repr_style("short")
+ excinfo.traceback[2].set_repr_style("short")
+ r = excinfo.getrepr(style="long")
+ tw = TWMock()
+ r.toterminal(tw)
+ for line in tw.lines:
+ print(line)
+ assert tw.lines[0] == ""
+ assert tw.lines[1] == " def f():"
+ assert tw.lines[2] == "> g()"
+ assert tw.lines[3] == ""
+ msg = tw.get_write_msg(4)
+ assert msg.endswith("mod.py")
+ assert tw.lines[5] == ":3: "
+ assert tw.lines[6] == ("_ ", None)
+ tw.get_write_msg(7)
+ assert tw.lines[8].endswith("in g")
+ assert tw.lines[9] == " h()"
+ tw.get_write_msg(10)
+ assert tw.lines[11].endswith("in h")
+ assert tw.lines[12] == " i()"
+ assert tw.lines[13] == ("_ ", None)
+ assert tw.lines[14] == ""
+ assert tw.lines[15] == " def i():"
+ assert tw.lines[16] == "> raise ValueError()"
+ assert tw.lines[17] == "E ValueError"
+ assert tw.lines[18] == ""
+ msg = tw.get_write_msg(19)
+ msg.endswith("mod.py")
+ assert tw.lines[20] == ":9: ValueError"
+
+ @pytest.mark.skipif("sys.version_info[0] < 3")
+ def test_exc_chain_repr(self, importasmod):
+ mod = importasmod("""
+ class Err(Exception):
+ pass
+ def f():
+ try:
+ g()
+ except Exception as e:
+ raise Err() from e
+ finally:
+ h()
+ def g():
+ raise ValueError()
+
+ def h():
+ raise AttributeError()
+ """)
+ excinfo = pytest.raises(AttributeError, mod.f)
+ r = excinfo.getrepr(style="long")
+ tw = TWMock()
+ r.toterminal(tw)
+ for line in tw.lines:
+ print(line)
+ assert tw.lines[0] == ""
+ assert tw.lines[1] == " def f():"
+ assert tw.lines[2] == " try:"
+ assert tw.lines[3] == "> g()"
+ assert tw.lines[4] == ""
+ line = tw.get_write_msg(5)
+ assert line.endswith('mod.py')
+ assert tw.lines[6] == ':6: '
+ assert tw.lines[7] == ("_ ", None)
+ assert tw.lines[8] == ""
+ assert tw.lines[9] == " def g():"
+ assert tw.lines[10] == "> raise ValueError()"
+ assert tw.lines[11] == "E ValueError"
+ assert tw.lines[12] == ""
+ line = tw.get_write_msg(13)
+ assert line.endswith('mod.py')
+ assert tw.lines[14] == ':12: ValueError'
+ assert tw.lines[15] == ""
+ assert tw.lines[16] == "The above exception was the direct cause of the following exception:"
+ assert tw.lines[17] == ""
+ assert tw.lines[18] == " def f():"
+ assert tw.lines[19] == " try:"
+ assert tw.lines[20] == " g()"
+ assert tw.lines[21] == " except Exception as e:"
+ assert tw.lines[22] == "> raise Err() from e"
+ assert tw.lines[23] == "E test_exc_chain_repr0.mod.Err"
+ assert tw.lines[24] == ""
+ line = tw.get_write_msg(25)
+ assert line.endswith('mod.py')
+ assert tw.lines[26] == ":8: Err"
+ assert tw.lines[27] == ""
+ assert tw.lines[28] == "During handling of the above exception, another exception occurred:"
+ assert tw.lines[29] == ""
+ assert tw.lines[30] == " def f():"
+ assert tw.lines[31] == " try:"
+ assert tw.lines[32] == " g()"
+ assert tw.lines[33] == " except Exception as e:"
+ assert tw.lines[34] == " raise Err() from e"
+ assert tw.lines[35] == " finally:"
+ assert tw.lines[36] == "> h()"
+ assert tw.lines[37] == ""
+ line = tw.get_write_msg(38)
+ assert line.endswith('mod.py')
+ assert tw.lines[39] == ":10: "
+ assert tw.lines[40] == ('_ ', None)
+ assert tw.lines[41] == ""
+ assert tw.lines[42] == " def h():"
+ assert tw.lines[43] == "> raise AttributeError()"
+ assert tw.lines[44] == "E AttributeError"
+ assert tw.lines[45] == ""
+ line = tw.get_write_msg(46)
+ assert line.endswith('mod.py')
+ assert tw.lines[47] == ":15: AttributeError"
+
+ @pytest.mark.skipif("sys.version_info[0] < 3")
+ def test_exc_repr_with_raise_from_none_chain_suppression(self, importasmod):
+ mod = importasmod("""
+ def f():
+ try:
+ g()
+ except Exception:
+ raise AttributeError() from None
+ def g():
+ raise ValueError()
+ """)
+ excinfo = pytest.raises(AttributeError, mod.f)
+ r = excinfo.getrepr(style="long")
+ tw = TWMock()
+ r.toterminal(tw)
+ for line in tw.lines:
+ print(line)
+ assert tw.lines[0] == ""
+ assert tw.lines[1] == " def f():"
+ assert tw.lines[2] == " try:"
+ assert tw.lines[3] == " g()"
+ assert tw.lines[4] == " except Exception:"
+ assert tw.lines[5] == "> raise AttributeError() from None"
+ assert tw.lines[6] == "E AttributeError"
+ assert tw.lines[7] == ""
+ line = tw.get_write_msg(8)
+ assert line.endswith('mod.py')
+ assert tw.lines[9] == ":6: AttributeError"
+ assert len(tw.lines) == 10
+
+ @pytest.mark.skipif("sys.version_info[0] < 3")
+ @pytest.mark.parametrize('reason, description', [
+ ('cause', 'The above exception was the direct cause of the following exception:'),
+ ('context', 'During handling of the above exception, another exception occurred:'),
+ ])
+ def test_exc_chain_repr_without_traceback(self, importasmod, reason, description):
+ """
+ Handle representation of exception chains where one of the exceptions doesn't have a
+ real traceback, such as those raised in a subprocess submitted by the multiprocessing
+ module (#1984).
+ """
+ from _pytest.pytester import LineMatcher
+ exc_handling_code = ' from e' if reason == 'cause' else ''
+ mod = importasmod("""
+ def f():
+ try:
+ g()
+ except Exception as e:
+ raise RuntimeError('runtime problem'){exc_handling_code}
+ def g():
+ raise ValueError('invalid value')
+ """.format(exc_handling_code=exc_handling_code))
+
+ with pytest.raises(RuntimeError) as excinfo:
+ mod.f()
+
+ # emulate the issue described in #1984
+ attr = '__%s__' % reason
+ getattr(excinfo.value, attr).__traceback__ = None
+
+ r = excinfo.getrepr()
+ tw = py.io.TerminalWriter(stringio=True)
+ tw.hasmarkup = False
+ r.toterminal(tw)
+
+ matcher = LineMatcher(tw.stringio.getvalue().splitlines())
+ matcher.fnmatch_lines([
+ "ValueError: invalid value",
+ description,
+ "* except Exception as e:",
+ "> * raise RuntimeError('runtime problem')" + exc_handling_code,
+ "E *RuntimeError: runtime problem",
+ ])
+
+
+@pytest.mark.parametrize("style", ["short", "long"])
+@pytest.mark.parametrize("encoding", [None, "utf8", "utf16"])
+def test_repr_traceback_with_unicode(style, encoding):
+ msg = u'☹'
+ if encoding is not None:
+ msg = msg.encode(encoding)
+ try:
+ raise RuntimeError(msg)
+ except RuntimeError:
+ e_info = ExceptionInfo()
+ formatter = FormattedExcinfo(style=style)
+ repr_traceback = formatter.repr_traceback(e_info)
+ assert repr_traceback is not None
+
+
+def test_cwd_deleted(testdir):
+ testdir.makepyfile("""
+ def test(tmpdir):
+ tmpdir.chdir()
+ tmpdir.remove()
+ assert False
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(['* 1 failed in *'])
+ assert 'INTERNALERROR' not in result.stdout.str() + result.stderr.str()
+
+
+def test_exception_repr_extraction_error_on_recursion():
+ """
+ Ensure we can properly detect a recursion error even
+ if some locals raise error on comparision (#2459).
+ """
+ class numpy_like(object):
+
+ def __eq__(self, other):
+ if type(other) is numpy_like:
+ raise ValueError('The truth value of an array '
+ 'with more than one element is ambiguous.')
+
+ def a(x):
+ return b(numpy_like())
+
+ def b(x):
+ return a(numpy_like())
+
+ try:
+ a(numpy_like())
+ except: # noqa
+ from _pytest._code.code import ExceptionInfo
+ from _pytest.pytester import LineMatcher
+ exc_info = ExceptionInfo()
+
+ matcher = LineMatcher(str(exc_info.getrepr()).splitlines())
+ matcher.fnmatch_lines([
+ '!!! Recursion error detected, but an error occurred locating the origin of recursion.',
+ '*The following exception happened*',
+ '*ValueError: The truth value of an array*',
+ ])
+
+
+def test_no_recursion_index_on_recursion_error():
+ """
+ Ensure that we don't break in case we can't find the recursion index
+ during a recursion error (#2486).
+ """
+ try:
+ class RecursionDepthError(object):
+ def __getattr__(self, attr):
+ return getattr(self, '_' + attr)
+
+ RecursionDepthError().trigger
+ except: # noqa
+ from _pytest._code.code import ExceptionInfo
+ exc_info = ExceptionInfo()
+ assert 'maximum recursion' in str(exc_info.getrepr())
+ else:
+ assert 0
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/code/test_source.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/code/test_source.py
new file mode 100644
index 00000000000..8eda68a6e2f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/code/test_source.py
@@ -0,0 +1,680 @@
+# flake8: noqa
+# disable flake check on this file because some constructs are strange
+# or redundant on purpose and can't be disable on a line-by-line basis
+from __future__ import absolute_import, division, print_function
+import sys
+
+import _pytest._code
+import py
+import pytest
+from _pytest._code import Source
+from _pytest._code.source import _ast
+
+if _ast is not None:
+ astonly = pytest.mark.nothing
+else:
+ astonly = pytest.mark.xfail("True", reason="only works with AST-compile")
+
+failsonjython = pytest.mark.xfail("sys.platform.startswith('java')")
+
+
+def test_source_str_function():
+ x = Source("3")
+ assert str(x) == "3"
+
+ x = Source(" 3")
+ assert str(x) == "3"
+
+ x = Source("""
+ 3
+ """, rstrip=False)
+ assert str(x) == "\n3\n "
+
+ x = Source("""
+ 3
+ """, rstrip=True)
+ assert str(x) == "\n3"
+
+
+def test_unicode():
+ try:
+ unicode
+ except NameError:
+ return
+ x = Source(unicode("4"))
+ assert str(x) == "4"
+ co = _pytest._code.compile(unicode('u"\xc3\xa5"', 'utf8'), mode='eval')
+ val = eval(co)
+ assert isinstance(val, unicode)
+
+
+def test_source_from_function():
+ source = _pytest._code.Source(test_source_str_function)
+ assert str(source).startswith('def test_source_str_function():')
+
+
+def test_source_from_method():
+ class TestClass(object):
+ def test_method(self):
+ pass
+ source = _pytest._code.Source(TestClass().test_method)
+ assert source.lines == ["def test_method(self):",
+ " pass"]
+
+
+def test_source_from_lines():
+ lines = ["a \n", "b\n", "c"]
+ source = _pytest._code.Source(lines)
+ assert source.lines == ['a ', 'b', 'c']
+
+
+def test_source_from_inner_function():
+ def f():
+ pass
+ source = _pytest._code.Source(f, deindent=False)
+ assert str(source).startswith(' def f():')
+ source = _pytest._code.Source(f)
+ assert str(source).startswith('def f():')
+
+
+def test_source_putaround_simple():
+ source = Source("raise ValueError")
+ source = source.putaround(
+ "try:", """\
+ except ValueError:
+ x = 42
+ else:
+ x = 23""")
+ assert str(source) == """\
+try:
+ raise ValueError
+except ValueError:
+ x = 42
+else:
+ x = 23"""
+
+
+def test_source_putaround():
+ source = Source()
+ source = source.putaround("""
+ if 1:
+ x=1
+ """)
+ assert str(source).strip() == "if 1:\n x=1"
+
+
+def test_source_strips():
+ source = Source("")
+ assert source == Source()
+ assert str(source) == ''
+ assert source.strip() == source
+
+
+def test_source_strip_multiline():
+ source = Source()
+ source.lines = ["", " hello", " "]
+ source2 = source.strip()
+ assert source2.lines == [" hello"]
+
+
+def test_syntaxerror_rerepresentation():
+ ex = pytest.raises(SyntaxError, _pytest._code.compile, 'xyz xyz')
+ assert ex.value.lineno == 1
+ assert ex.value.offset in (4, 7) # XXX pypy/jython versus cpython?
+ assert ex.value.text.strip(), 'x x'
+
+
+def test_isparseable():
+ assert Source("hello").isparseable()
+ assert Source("if 1:\n pass").isparseable()
+ assert Source(" \nif 1:\n pass").isparseable()
+ assert not Source("if 1:\n").isparseable()
+ assert not Source(" \nif 1:\npass").isparseable()
+ assert not Source(chr(0)).isparseable()
+
+
+class TestAccesses(object):
+ source = Source("""\
+ def f(x):
+ pass
+ def g(x):
+ pass
+ """)
+
+ def test_getrange(self):
+ x = self.source[0:2]
+ assert x.isparseable()
+ assert len(x.lines) == 2
+ assert str(x) == "def f(x):\n pass"
+
+ def test_getline(self):
+ x = self.source[0]
+ assert x == "def f(x):"
+
+ def test_len(self):
+ assert len(self.source) == 4
+
+ def test_iter(self):
+ values = [x for x in self.source]
+ assert len(values) == 4
+
+
+class TestSourceParsingAndCompiling(object):
+ source = Source("""\
+ def f(x):
+ assert (x ==
+ 3 +
+ 4)
+ """).strip()
+
+ def test_compile(self):
+ co = _pytest._code.compile("x=3")
+ d = {}
+ exec(co, d)
+ assert d['x'] == 3
+
+ def test_compile_and_getsource_simple(self):
+ co = _pytest._code.compile("x=3")
+ exec(co)
+ source = _pytest._code.Source(co)
+ assert str(source) == "x=3"
+
+ def test_compile_and_getsource_through_same_function(self):
+ def gensource(source):
+ return _pytest._code.compile(source)
+ co1 = gensource("""
+ def f():
+ raise KeyError()
+ """)
+ co2 = gensource("""
+ def f():
+ raise ValueError()
+ """)
+ source1 = py.std.inspect.getsource(co1)
+ assert 'KeyError' in source1
+ source2 = py.std.inspect.getsource(co2)
+ assert 'ValueError' in source2
+
+ def test_getstatement(self):
+ # print str(self.source)
+ ass = str(self.source[1:])
+ for i in range(1, 4):
+ # print "trying start in line %r" % self.source[i]
+ s = self.source.getstatement(i)
+ #x = s.deindent()
+ assert str(s) == ass
+
+ def test_getstatementrange_triple_quoted(self):
+ # print str(self.source)
+ source = Source("""hello('''
+ ''')""")
+ s = source.getstatement(0)
+ assert s == str(source)
+ s = source.getstatement(1)
+ assert s == str(source)
+
+ @astonly
+ def test_getstatementrange_within_constructs(self):
+ source = Source("""\
+ try:
+ try:
+ raise ValueError
+ except SomeThing:
+ pass
+ finally:
+ 42
+ """)
+ assert len(source) == 7
+ # check all lineno's that could occur in a traceback
+ # assert source.getstatementrange(0) == (0, 7)
+ # assert source.getstatementrange(1) == (1, 5)
+ assert source.getstatementrange(2) == (2, 3)
+ assert source.getstatementrange(3) == (3, 4)
+ assert source.getstatementrange(4) == (4, 5)
+ # assert source.getstatementrange(5) == (0, 7)
+ assert source.getstatementrange(6) == (6, 7)
+
+ def test_getstatementrange_bug(self):
+ source = Source("""\
+ try:
+ x = (
+ y +
+ z)
+ except:
+ pass
+ """)
+ assert len(source) == 6
+ assert source.getstatementrange(2) == (1, 4)
+
+ def test_getstatementrange_bug2(self):
+ source = Source("""\
+ assert (
+ 33
+ ==
+ [
+ X(3,
+ b=1, c=2
+ ),
+ ]
+ )
+ """)
+ assert len(source) == 9
+ assert source.getstatementrange(5) == (0, 9)
+
+ def test_getstatementrange_ast_issue58(self):
+ source = Source("""\
+
+ def test_some():
+ for a in [a for a in
+ CAUSE_ERROR]: pass
+
+ x = 3
+ """)
+ assert getstatement(2, source).lines == source.lines[2:3]
+ assert getstatement(3, source).lines == source.lines[3:4]
+
+ def test_getstatementrange_out_of_bounds_py3(self):
+ source = Source("if xxx:\n from .collections import something")
+ r = source.getstatementrange(1)
+ assert r == (1, 2)
+
+ def test_getstatementrange_with_syntaxerror_issue7(self):
+ source = Source(":")
+ pytest.raises(SyntaxError, lambda: source.getstatementrange(0))
+
+ def test_compile_to_ast(self):
+ import ast
+ source = Source("x = 4")
+ mod = source.compile(flag=ast.PyCF_ONLY_AST)
+ assert isinstance(mod, ast.Module)
+ compile(mod, "<filename>", "exec")
+
+ def test_compile_and_getsource(self):
+ co = self.source.compile()
+ py.builtin.exec_(co, globals())
+ f(7)
+ excinfo = pytest.raises(AssertionError, "f(6)")
+ frame = excinfo.traceback[-1].frame
+ stmt = frame.code.fullsource.getstatement(frame.lineno)
+ # print "block", str(block)
+ assert str(stmt).strip().startswith('assert')
+
+ @pytest.mark.parametrize('name', ['', None, 'my'])
+ def test_compilefuncs_and_path_sanity(self, name):
+ def check(comp, name):
+ co = comp(self.source, name)
+ if not name:
+ expected = "codegen %s:%d>" % (mypath, mylineno + 2 + 2)
+ else:
+ expected = "codegen %r %s:%d>" % (name, mypath, mylineno + 2 + 2)
+ fn = co.co_filename
+ assert fn.endswith(expected)
+
+ mycode = _pytest._code.Code(self.test_compilefuncs_and_path_sanity)
+ mylineno = mycode.firstlineno
+ mypath = mycode.path
+
+ for comp in _pytest._code.compile, _pytest._code.Source.compile:
+ check(comp, name)
+
+ def test_offsetless_synerr(self):
+ pytest.raises(SyntaxError, _pytest._code.compile, "lambda a,a: 0", mode='eval')
+
+
+def test_getstartingblock_singleline():
+ class A(object):
+ def __init__(self, *args):
+ frame = sys._getframe(1)
+ self.source = _pytest._code.Frame(frame).statement
+
+ x = A('x', 'y')
+
+ values = [i for i in x.source.lines if i.strip()]
+ assert len(values) == 1
+
+
+def test_getline_finally():
+ def c(): pass
+ excinfo = pytest.raises(TypeError, """
+ teardown = None
+ try:
+ c(1)
+ finally:
+ if teardown:
+ teardown()
+ """)
+ source = excinfo.traceback[-1].statement
+ assert str(source).strip() == 'c(1)'
+
+
+def test_getfuncsource_dynamic():
+ source = """
+ def f():
+ raise ValueError
+
+ def g(): pass
+ """
+ co = _pytest._code.compile(source)
+ py.builtin.exec_(co, globals())
+ assert str(_pytest._code.Source(f)).strip() == 'def f():\n raise ValueError'
+ assert str(_pytest._code.Source(g)).strip() == 'def g(): pass'
+
+
+def test_getfuncsource_with_multine_string():
+ def f():
+ c = '''while True:
+ pass
+'''
+ assert str(_pytest._code.Source(f)).strip() == "def f():\n c = '''while True:\n pass\n'''"
+
+
+def test_deindent():
+ from _pytest._code.source import deindent as deindent
+ assert deindent(['\tfoo', '\tbar', ]) == ['foo', 'bar']
+
+ def f():
+ c = '''while True:
+ pass
+'''
+ import inspect
+ lines = deindent(inspect.getsource(f).splitlines())
+ assert lines == ["def f():", " c = '''while True:", " pass", "'''"]
+
+ source = """
+ def f():
+ def g():
+ pass
+ """
+ lines = deindent(source.splitlines())
+ assert lines == ['', 'def f():', ' def g():', ' pass', ' ']
+
+
+def test_source_of_class_at_eof_without_newline(tmpdir):
+ # this test fails because the implicit inspect.getsource(A) below
+ # does not return the "x = 1" last line.
+ source = _pytest._code.Source('''
+ class A(object):
+ def method(self):
+ x = 1
+ ''')
+ path = tmpdir.join("a.py")
+ path.write(source)
+ s2 = _pytest._code.Source(tmpdir.join("a.py").pyimport().A)
+ assert str(source).strip() == str(s2).strip()
+
+
+if True:
+ def x():
+ pass
+
+
+def test_getsource_fallback():
+ from _pytest._code.source import getsource
+ expected = """def x():
+ pass"""
+ src = getsource(x)
+ assert src == expected
+
+
+def test_idem_compile_and_getsource():
+ from _pytest._code.source import getsource
+ expected = "def x(): pass"
+ co = _pytest._code.compile(expected)
+ src = getsource(co)
+ assert src == expected
+
+
+def test_findsource_fallback():
+ from _pytest._code.source import findsource
+ src, lineno = findsource(x)
+ assert 'test_findsource_simple' in str(src)
+ assert src[lineno] == ' def x():'
+
+
+def test_findsource():
+ from _pytest._code.source import findsource
+ co = _pytest._code.compile("""if 1:
+ def x():
+ pass
+""")
+
+ src, lineno = findsource(co)
+ assert 'if 1:' in str(src)
+
+ d = {}
+ eval(co, d)
+ src, lineno = findsource(d['x'])
+ assert 'if 1:' in str(src)
+ assert src[lineno] == " def x():"
+
+
+def test_getfslineno():
+ from _pytest._code import getfslineno
+
+ def f(x):
+ pass
+
+ fspath, lineno = getfslineno(f)
+
+ assert fspath.basename == "test_source.py"
+ assert lineno == _pytest._code.getrawcode(f).co_firstlineno - 1 # see findsource
+
+ class A(object):
+ pass
+
+ fspath, lineno = getfslineno(A)
+
+ _, A_lineno = py.std.inspect.findsource(A)
+ assert fspath.basename == "test_source.py"
+ assert lineno == A_lineno
+
+ assert getfslineno(3) == ("", -1)
+
+ class B(object):
+ pass
+ B.__name__ = "B2"
+ assert getfslineno(B)[1] == -1
+
+
+def test_code_of_object_instance_with_call():
+ class A(object):
+ pass
+ pytest.raises(TypeError, lambda: _pytest._code.Source(A()))
+
+ class WithCall(object):
+ def __call__(self):
+ pass
+
+ code = _pytest._code.Code(WithCall())
+ assert 'pass' in str(code.source())
+
+ class Hello(object):
+ def __call__(self):
+ pass
+ pytest.raises(TypeError, lambda: _pytest._code.Code(Hello))
+
+
+def getstatement(lineno, source):
+ from _pytest._code.source import getstatementrange_ast
+ source = _pytest._code.Source(source, deindent=False)
+ ast, start, end = getstatementrange_ast(lineno, source)
+ return source[start:end]
+
+
+def test_oneline():
+ source = getstatement(0, "raise ValueError")
+ assert str(source) == "raise ValueError"
+
+
+def test_comment_and_no_newline_at_end():
+ from _pytest._code.source import getstatementrange_ast
+ source = Source(['def test_basic_complex():',
+ ' assert 1 == 2',
+ '# vim: filetype=pyopencl:fdm=marker'])
+ ast, start, end = getstatementrange_ast(1, source)
+ assert end == 2
+
+
+def test_oneline_and_comment():
+ source = getstatement(0, "raise ValueError\n#hello")
+ assert str(source) == "raise ValueError"
+
+
+@pytest.mark.xfail(hasattr(sys, "pypy_version_info"),
+ reason='does not work on pypy')
+def test_comments():
+ source = '''def test():
+ "comment 1"
+ x = 1
+ # comment 2
+ # comment 3
+
+ assert False
+
+"""
+comment 4
+"""
+'''
+ for line in range(2, 6):
+ assert str(getstatement(line, source)) == ' x = 1'
+ for line in range(6, 10):
+ assert str(getstatement(line, source)) == ' assert False'
+ assert str(getstatement(10, source)) == '"""'
+
+
+def test_comment_in_statement():
+ source = '''test(foo=1,
+ # comment 1
+ bar=2)
+'''
+ for line in range(1, 3):
+ assert str(getstatement(line, source)) == \
+ 'test(foo=1,\n # comment 1\n bar=2)'
+
+
+def test_single_line_else():
+ source = getstatement(1, "if False: 2\nelse: 3")
+ assert str(source) == "else: 3"
+
+
+def test_single_line_finally():
+ source = getstatement(1, "try: 1\nfinally: 3")
+ assert str(source) == "finally: 3"
+
+
+def test_issue55():
+ source = ('def round_trip(dinp):\n assert 1 == dinp\n'
+ 'def test_rt():\n round_trip("""\n""")\n')
+ s = getstatement(3, source)
+ assert str(s) == ' round_trip("""\n""")'
+
+
+def XXXtest_multiline():
+ source = getstatement(0, """\
+raise ValueError(
+ 23
+)
+x = 3
+""")
+ assert str(source) == "raise ValueError(\n 23\n)"
+
+
+class TestTry(object):
+ pytestmark = astonly
+ source = """\
+try:
+ raise ValueError
+except Something:
+ raise IndexError(1)
+else:
+ raise KeyError()
+"""
+
+ def test_body(self):
+ source = getstatement(1, self.source)
+ assert str(source) == " raise ValueError"
+
+ def test_except_line(self):
+ source = getstatement(2, self.source)
+ assert str(source) == "except Something:"
+
+ def test_except_body(self):
+ source = getstatement(3, self.source)
+ assert str(source) == " raise IndexError(1)"
+
+ def test_else(self):
+ source = getstatement(5, self.source)
+ assert str(source) == " raise KeyError()"
+
+
+class TestTryFinally(object):
+ source = """\
+try:
+ raise ValueError
+finally:
+ raise IndexError(1)
+"""
+
+ def test_body(self):
+ source = getstatement(1, self.source)
+ assert str(source) == " raise ValueError"
+
+ def test_finally(self):
+ source = getstatement(3, self.source)
+ assert str(source) == " raise IndexError(1)"
+
+
+class TestIf(object):
+ pytestmark = astonly
+ source = """\
+if 1:
+ y = 3
+elif False:
+ y = 5
+else:
+ y = 7
+"""
+
+ def test_body(self):
+ source = getstatement(1, self.source)
+ assert str(source) == " y = 3"
+
+ def test_elif_clause(self):
+ source = getstatement(2, self.source)
+ assert str(source) == "elif False:"
+
+ def test_elif(self):
+ source = getstatement(3, self.source)
+ assert str(source) == " y = 5"
+
+ def test_else(self):
+ source = getstatement(5, self.source)
+ assert str(source) == " y = 7"
+
+
+def test_semicolon():
+ s = """\
+hello ; pytest.skip()
+"""
+ source = getstatement(0, s)
+ assert str(source) == s.strip()
+
+
+def test_def_online():
+ s = """\
+def func(): raise ValueError(42)
+
+def something():
+ pass
+"""
+ source = getstatement(0, s)
+ assert str(source) == "def func(): raise ValueError(42)"
+
+
+def XXX_test_expression_multiline():
+ source = """\
+something
+'''
+'''"""
+ result = getstatement(1, source)
+ assert str(result) == "'''\n'''"
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/code/test_source_multiline_block.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/code/test_source_multiline_block.py
new file mode 100644
index 00000000000..b356d191f0b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/code/test_source_multiline_block.py
@@ -0,0 +1,26 @@
+# flake8: noqa
+import sys
+
+import _pytest._code
+
+
+def test_getstartingblock_multiline():
+ """
+ This test was originally found in test_source.py, but it depends on the weird
+ formatting of the ``x = A`` construct seen here and our autopep8 tool can only exclude entire
+ files (it does not support excluding lines/blocks using the traditional #noqa comment yet,
+ see hhatto/autopep8#307). It was considered better to just move this single test to its own
+ file and exclude it from autopep8 than try to complicate things.
+ """
+ class A(object):
+ def __init__(self, *args):
+ frame = sys._getframe(1)
+ self.source = _pytest._code.Frame(frame).statement
+
+ x = A('x',
+ 'y'
+ ,
+ 'z')
+
+ values = [i for i in x.source.lines if i.strip()]
+ assert len(values) == 4
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/deprecated_test.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/deprecated_test.py
new file mode 100644
index 00000000000..11c4ad43cbc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/deprecated_test.py
@@ -0,0 +1,127 @@
+from __future__ import absolute_import, division, print_function
+import pytest
+
+
+def test_yield_tests_deprecation(testdir):
+ testdir.makepyfile("""
+ def func1(arg, arg2):
+ assert arg == arg2
+ def test_gen():
+ yield "m1", func1, 15, 3*5
+ yield "m2", func1, 42, 6*7
+ def test_gen2():
+ for k in range(10):
+ yield func1, 1, 1
+ """)
+ result = testdir.runpytest('-ra')
+ result.stdout.fnmatch_lines([
+ '*yield tests are deprecated, and scheduled to be removed in pytest 4.0*',
+ '*2 passed*',
+ ])
+ assert result.stdout.str().count('yield tests are deprecated') == 2
+
+
+def test_funcarg_prefix_deprecation(testdir):
+ testdir.makepyfile("""
+ def pytest_funcarg__value():
+ return 10
+
+ def test_funcarg_prefix(value):
+ assert value == 10
+ """)
+ result = testdir.runpytest('-ra')
+ result.stdout.fnmatch_lines([
+ ('*pytest_funcarg__value: '
+ 'declaring fixtures using "pytest_funcarg__" prefix is deprecated '
+ 'and scheduled to be removed in pytest 4.0. '
+ 'Please remove the prefix and use the @pytest.fixture decorator instead.'),
+ '*1 passed*',
+ ])
+
+
+def test_pytest_setup_cfg_deprecated(testdir):
+ testdir.makefile('.cfg', setup='''
+ [pytest]
+ addopts = --verbose
+ ''')
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(['*pytest*section in setup.cfg files is deprecated*use*tool:pytest*instead*'])
+
+
+def test_str_args_deprecated(tmpdir, testdir):
+ """Deprecate passing strings to pytest.main(). Scheduled for removal in pytest-4.0."""
+ from _pytest.main import EXIT_NOTESTSCOLLECTED
+ warnings = []
+
+ class Collect(object):
+ def pytest_logwarning(self, message):
+ warnings.append(message)
+
+ ret = pytest.main("%s -x" % tmpdir, plugins=[Collect()])
+ testdir.delete_loaded_modules()
+ msg = ('passing a string to pytest.main() is deprecated, '
+ 'pass a list of arguments instead.')
+ assert msg in warnings
+ assert ret == EXIT_NOTESTSCOLLECTED
+
+
+def test_getfuncargvalue_is_deprecated(request):
+ pytest.deprecated_call(request.getfuncargvalue, 'tmpdir')
+
+
+def test_resultlog_is_deprecated(testdir):
+ result = testdir.runpytest('--help')
+ result.stdout.fnmatch_lines(['*DEPRECATED path for machine-readable result log*'])
+
+ testdir.makepyfile('''
+ def test():
+ pass
+ ''')
+ result = testdir.runpytest('--result-log=%s' % testdir.tmpdir.join('result.log'))
+ result.stdout.fnmatch_lines([
+ '*--result-log is deprecated and scheduled for removal in pytest 4.0*',
+ '*See https://docs.pytest.org/*/usage.html#creating-resultlog-format-files for more information*',
+ ])
+
+
+@pytest.mark.filterwarnings('always:Metafunc.addcall is deprecated')
+def test_metafunc_addcall_deprecated(testdir):
+ testdir.makepyfile("""
+ def pytest_generate_tests(metafunc):
+ metafunc.addcall({'i': 1})
+ metafunc.addcall({'i': 2})
+ def test_func(i):
+ pass
+ """)
+ res = testdir.runpytest('-s')
+ assert res.ret == 0
+ res.stdout.fnmatch_lines([
+ "*Metafunc.addcall is deprecated*",
+ "*2 passed, 2 warnings*",
+ ])
+
+
+def test_terminal_reporter_writer_attr(pytestconfig):
+ """Check that TerminalReporter._tw is also available as 'writer' (#2984)
+ This attribute is planned to be deprecated in 3.4.
+ """
+ try:
+ import xdist # noqa
+ pytest.skip('xdist workers disable the terminal reporter plugin')
+ except ImportError:
+ pass
+ terminal_reporter = pytestconfig.pluginmanager.get_plugin('terminalreporter')
+ assert terminal_reporter.writer is terminal_reporter._tw
+
+
+def test_pytest_catchlog_deprecated(testdir):
+ testdir.makepyfile("""
+ def test_func(pytestconfig):
+ pytestconfig.pluginmanager.register(None, 'pytest_catchlog')
+ """)
+ res = testdir.runpytest()
+ assert res.ret == 0
+ res.stdout.fnmatch_lines([
+ "*pytest-catchlog plugin has been merged into the core*",
+ "*1 passed, 1 warnings*",
+ ])
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/freeze/.gitignore b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/freeze/.gitignore
new file mode 100644
index 00000000000..490310b6c11
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/freeze/.gitignore
@@ -0,0 +1,3 @@
+build/
+dist/
+*.spec \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/freeze/create_executable.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/freeze/create_executable.py
new file mode 100644
index 00000000000..f4f6088ef7d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/freeze/create_executable.py
@@ -0,0 +1,12 @@
+"""
+Generates an executable with pytest runner embedded using PyInstaller.
+"""
+if __name__ == '__main__':
+ import pytest
+ import subprocess
+
+ hidden = []
+ for x in pytest.freeze_includes():
+ hidden.extend(['--hidden-import', x])
+ args = ['pyinstaller', '--noconfirm'] + hidden + ['runtests_script.py']
+ subprocess.check_call(' '.join(args), shell=True)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/freeze/runtests_script.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/freeze/runtests_script.py
new file mode 100644
index 00000000000..d281601c068
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/freeze/runtests_script.py
@@ -0,0 +1,9 @@
+"""
+This is the script that is actually frozen into an executable: simply executes
+py.test main().
+"""
+
+if __name__ == '__main__':
+ import sys
+ import pytest
+ sys.exit(pytest.main())
diff --git a/tests/wpt/web-platform-tests/tools/pytest/testing/cx_freeze/tests/test_doctest.txt b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/freeze/tests/test_doctest.txt
index e18a4b68cc9..e18a4b68cc9 100644
--- a/tests/wpt/web-platform-tests/tools/pytest/testing/cx_freeze/tests/test_doctest.txt
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/freeze/tests/test_doctest.txt
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/freeze/tests/test_trivial.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/freeze/tests/test_trivial.py
new file mode 100644
index 00000000000..45622b850bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/freeze/tests/test_trivial.py
@@ -0,0 +1,7 @@
+
+def test_upper():
+ assert 'foo'.upper() == 'FOO'
+
+
+def test_lower():
+ assert 'FOO'.lower() == 'foo'
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/freeze/tox_run.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/freeze/tox_run.py
new file mode 100644
index 00000000000..3fc38804095
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/freeze/tox_run.py
@@ -0,0 +1,12 @@
+"""
+Called by tox.ini: uses the generated executable to run the tests in ./tests/
+directory.
+"""
+if __name__ == '__main__':
+ import os
+ import sys
+
+ executable = os.path.join(os.getcwd(), 'dist', 'runtests_script', 'runtests_script')
+ if sys.platform.startswith('win'):
+ executable += '.exe'
+ sys.exit(os.system('%s tests' % executable))
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/logging/test_fixture.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/logging/test_fixture.py
new file mode 100644
index 00000000000..c27b31137ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/logging/test_fixture.py
@@ -0,0 +1,70 @@
+# -*- coding: utf-8 -*-
+import logging
+
+
+logger = logging.getLogger(__name__)
+sublogger = logging.getLogger(__name__ + '.baz')
+
+
+def test_fixture_help(testdir):
+ result = testdir.runpytest('--fixtures')
+ result.stdout.fnmatch_lines(['*caplog*'])
+
+
+def test_change_level(caplog):
+ caplog.set_level(logging.INFO)
+ logger.debug('handler DEBUG level')
+ logger.info('handler INFO level')
+
+ caplog.set_level(logging.CRITICAL, logger=sublogger.name)
+ sublogger.warning('logger WARNING level')
+ sublogger.critical('logger CRITICAL level')
+
+ assert 'DEBUG' not in caplog.text
+ assert 'INFO' in caplog.text
+ assert 'WARNING' not in caplog.text
+ assert 'CRITICAL' in caplog.text
+
+
+def test_with_statement(caplog):
+ with caplog.at_level(logging.INFO):
+ logger.debug('handler DEBUG level')
+ logger.info('handler INFO level')
+
+ with caplog.at_level(logging.CRITICAL, logger=sublogger.name):
+ sublogger.warning('logger WARNING level')
+ sublogger.critical('logger CRITICAL level')
+
+ assert 'DEBUG' not in caplog.text
+ assert 'INFO' in caplog.text
+ assert 'WARNING' not in caplog.text
+ assert 'CRITICAL' in caplog.text
+
+
+def test_log_access(caplog):
+ logger.info('boo %s', 'arg')
+ assert caplog.records[0].levelname == 'INFO'
+ assert caplog.records[0].msg == 'boo %s'
+ assert 'boo arg' in caplog.text
+
+
+def test_record_tuples(caplog):
+ logger.info('boo %s', 'arg')
+
+ assert caplog.record_tuples == [
+ (__name__, logging.INFO, 'boo arg'),
+ ]
+
+
+def test_unicode(caplog):
+ logger.info(u'bū')
+ assert caplog.records[0].levelname == 'INFO'
+ assert caplog.records[0].msg == u'bū'
+ assert u'bū' in caplog.text
+
+
+def test_clear(caplog):
+ logger.info(u'bū')
+ assert len(caplog.records)
+ caplog.clear()
+ assert not len(caplog.records)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/logging/test_reporting.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/logging/test_reporting.py
new file mode 100644
index 00000000000..c02ee217227
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/logging/test_reporting.py
@@ -0,0 +1,398 @@
+# -*- coding: utf-8 -*-
+import os
+import pytest
+
+
+def test_nothing_logged(testdir):
+ testdir.makepyfile('''
+ import sys
+
+ def test_foo():
+ sys.stdout.write('text going to stdout')
+ sys.stderr.write('text going to stderr')
+ assert False
+ ''')
+ result = testdir.runpytest()
+ assert result.ret == 1
+ result.stdout.fnmatch_lines(['*- Captured stdout call -*',
+ 'text going to stdout'])
+ result.stdout.fnmatch_lines(['*- Captured stderr call -*',
+ 'text going to stderr'])
+ with pytest.raises(pytest.fail.Exception):
+ result.stdout.fnmatch_lines(['*- Captured *log call -*'])
+
+
+def test_messages_logged(testdir):
+ testdir.makepyfile('''
+ import sys
+ import logging
+
+ logger = logging.getLogger(__name__)
+
+ def test_foo():
+ sys.stdout.write('text going to stdout')
+ sys.stderr.write('text going to stderr')
+ logger.info('text going to logger')
+ assert False
+ ''')
+ result = testdir.runpytest()
+ assert result.ret == 1
+ result.stdout.fnmatch_lines(['*- Captured *log call -*',
+ '*text going to logger*'])
+ result.stdout.fnmatch_lines(['*- Captured stdout call -*',
+ 'text going to stdout'])
+ result.stdout.fnmatch_lines(['*- Captured stderr call -*',
+ 'text going to stderr'])
+
+
+def test_setup_logging(testdir):
+ testdir.makepyfile('''
+ import logging
+
+ logger = logging.getLogger(__name__)
+
+ def setup_function(function):
+ logger.info('text going to logger from setup')
+
+ def test_foo():
+ logger.info('text going to logger from call')
+ assert False
+ ''')
+ result = testdir.runpytest()
+ assert result.ret == 1
+ result.stdout.fnmatch_lines(['*- Captured *log setup -*',
+ '*text going to logger from setup*',
+ '*- Captured *log call -*',
+ '*text going to logger from call*'])
+
+
+def test_teardown_logging(testdir):
+ testdir.makepyfile('''
+ import logging
+
+ logger = logging.getLogger(__name__)
+
+ def test_foo():
+ logger.info('text going to logger from call')
+
+ def teardown_function(function):
+ logger.info('text going to logger from teardown')
+ assert False
+ ''')
+ result = testdir.runpytest()
+ assert result.ret == 1
+ result.stdout.fnmatch_lines(['*- Captured *log call -*',
+ '*text going to logger from call*',
+ '*- Captured *log teardown -*',
+ '*text going to logger from teardown*'])
+
+
+def test_disable_log_capturing(testdir):
+ testdir.makepyfile('''
+ import sys
+ import logging
+
+ logger = logging.getLogger(__name__)
+
+ def test_foo():
+ sys.stdout.write('text going to stdout')
+ logger.warning('catch me if you can!')
+ sys.stderr.write('text going to stderr')
+ assert False
+ ''')
+ result = testdir.runpytest('--no-print-logs')
+ print(result.stdout)
+ assert result.ret == 1
+ result.stdout.fnmatch_lines(['*- Captured stdout call -*',
+ 'text going to stdout'])
+ result.stdout.fnmatch_lines(['*- Captured stderr call -*',
+ 'text going to stderr'])
+ with pytest.raises(pytest.fail.Exception):
+ result.stdout.fnmatch_lines(['*- Captured *log call -*'])
+
+
+def test_disable_log_capturing_ini(testdir):
+ testdir.makeini(
+ '''
+ [pytest]
+ log_print=False
+ '''
+ )
+ testdir.makepyfile('''
+ import sys
+ import logging
+
+ logger = logging.getLogger(__name__)
+
+ def test_foo():
+ sys.stdout.write('text going to stdout')
+ logger.warning('catch me if you can!')
+ sys.stderr.write('text going to stderr')
+ assert False
+ ''')
+ result = testdir.runpytest()
+ print(result.stdout)
+ assert result.ret == 1
+ result.stdout.fnmatch_lines(['*- Captured stdout call -*',
+ 'text going to stdout'])
+ result.stdout.fnmatch_lines(['*- Captured stderr call -*',
+ 'text going to stderr'])
+ with pytest.raises(pytest.fail.Exception):
+ result.stdout.fnmatch_lines(['*- Captured *log call -*'])
+
+
+def test_log_cli_default_level(testdir):
+ # Default log file level
+ testdir.makepyfile('''
+ import pytest
+ import logging
+ def test_log_cli(request):
+ plugin = request.config.pluginmanager.getplugin('logging-plugin')
+ assert plugin.log_cli_handler.level == logging.WARNING
+ logging.getLogger('catchlog').info("This log message won't be shown")
+ logging.getLogger('catchlog').warning("This log message will be shown")
+ print('PASSED')
+ ''')
+
+ result = testdir.runpytest('-s')
+
+ # fnmatch_lines does an assertion internally
+ result.stdout.fnmatch_lines([
+ 'test_log_cli_default_level.py PASSED',
+ ])
+ result.stderr.fnmatch_lines([
+ "* This log message will be shown"
+ ])
+ for line in result.errlines:
+ try:
+ assert "This log message won't be shown" in line
+ pytest.fail("A log message was shown and it shouldn't have been")
+ except AssertionError:
+ continue
+
+ # make sure that that we get a '0' exit code for the testsuite
+ assert result.ret == 0
+
+
+def test_log_cli_level(testdir):
+ # Default log file level
+ testdir.makepyfile('''
+ import pytest
+ import logging
+ def test_log_cli(request):
+ plugin = request.config.pluginmanager.getplugin('logging-plugin')
+ assert plugin.log_cli_handler.level == logging.INFO
+ logging.getLogger('catchlog').debug("This log message won't be shown")
+ logging.getLogger('catchlog').info("This log message will be shown")
+ print('PASSED')
+ ''')
+
+ result = testdir.runpytest('-s', '--log-cli-level=INFO')
+
+ # fnmatch_lines does an assertion internally
+ result.stdout.fnmatch_lines([
+ 'test_log_cli_level.py PASSED',
+ ])
+ result.stderr.fnmatch_lines([
+ "* This log message will be shown"
+ ])
+ for line in result.errlines:
+ try:
+ assert "This log message won't be shown" in line
+ pytest.fail("A log message was shown and it shouldn't have been")
+ except AssertionError:
+ continue
+
+ # make sure that that we get a '0' exit code for the testsuite
+ assert result.ret == 0
+
+ result = testdir.runpytest('-s', '--log-level=INFO')
+
+ # fnmatch_lines does an assertion internally
+ result.stdout.fnmatch_lines([
+ 'test_log_cli_level.py PASSED',
+ ])
+ result.stderr.fnmatch_lines([
+ "* This log message will be shown"
+ ])
+ for line in result.errlines:
+ try:
+ assert "This log message won't be shown" in line
+ pytest.fail("A log message was shown and it shouldn't have been")
+ except AssertionError:
+ continue
+
+ # make sure that that we get a '0' exit code for the testsuite
+ assert result.ret == 0
+
+
+def test_log_cli_ini_level(testdir):
+ testdir.makeini(
+ """
+ [pytest]
+ log_cli_level = INFO
+ """)
+ testdir.makepyfile('''
+ import pytest
+ import logging
+ def test_log_cli(request):
+ plugin = request.config.pluginmanager.getplugin('logging-plugin')
+ assert plugin.log_cli_handler.level == logging.INFO
+ logging.getLogger('catchlog').debug("This log message won't be shown")
+ logging.getLogger('catchlog').info("This log message will be shown")
+ print('PASSED')
+ ''')
+
+ result = testdir.runpytest('-s')
+
+ # fnmatch_lines does an assertion internally
+ result.stdout.fnmatch_lines([
+ 'test_log_cli_ini_level.py PASSED',
+ ])
+ result.stderr.fnmatch_lines([
+ "* This log message will be shown"
+ ])
+ for line in result.errlines:
+ try:
+ assert "This log message won't be shown" in line
+ pytest.fail("A log message was shown and it shouldn't have been")
+ except AssertionError:
+ continue
+
+ # make sure that that we get a '0' exit code for the testsuite
+ assert result.ret == 0
+
+
+def test_log_file_cli(testdir):
+ # Default log file level
+ testdir.makepyfile('''
+ import pytest
+ import logging
+ def test_log_file(request):
+ plugin = request.config.pluginmanager.getplugin('logging-plugin')
+ assert plugin.log_file_handler.level == logging.WARNING
+ logging.getLogger('catchlog').info("This log message won't be shown")
+ logging.getLogger('catchlog').warning("This log message will be shown")
+ print('PASSED')
+ ''')
+
+ log_file = testdir.tmpdir.join('pytest.log').strpath
+
+ result = testdir.runpytest('-s', '--log-file={0}'.format(log_file))
+
+ # fnmatch_lines does an assertion internally
+ result.stdout.fnmatch_lines([
+ 'test_log_file_cli.py PASSED',
+ ])
+
+ # make sure that that we get a '0' exit code for the testsuite
+ assert result.ret == 0
+ assert os.path.isfile(log_file)
+ with open(log_file) as rfh:
+ contents = rfh.read()
+ assert "This log message will be shown" in contents
+ assert "This log message won't be shown" not in contents
+
+
+def test_log_file_cli_level(testdir):
+ # Default log file level
+ testdir.makepyfile('''
+ import pytest
+ import logging
+ def test_log_file(request):
+ plugin = request.config.pluginmanager.getplugin('logging-plugin')
+ assert plugin.log_file_handler.level == logging.INFO
+ logging.getLogger('catchlog').debug("This log message won't be shown")
+ logging.getLogger('catchlog').info("This log message will be shown")
+ print('PASSED')
+ ''')
+
+ log_file = testdir.tmpdir.join('pytest.log').strpath
+
+ result = testdir.runpytest('-s',
+ '--log-file={0}'.format(log_file),
+ '--log-file-level=INFO')
+
+ # fnmatch_lines does an assertion internally
+ result.stdout.fnmatch_lines([
+ 'test_log_file_cli_level.py PASSED',
+ ])
+
+ # make sure that that we get a '0' exit code for the testsuite
+ assert result.ret == 0
+ assert os.path.isfile(log_file)
+ with open(log_file) as rfh:
+ contents = rfh.read()
+ assert "This log message will be shown" in contents
+ assert "This log message won't be shown" not in contents
+
+
+def test_log_file_ini(testdir):
+ log_file = testdir.tmpdir.join('pytest.log').strpath
+
+ testdir.makeini(
+ """
+ [pytest]
+ log_file={0}
+ """.format(log_file))
+ testdir.makepyfile('''
+ import pytest
+ import logging
+ def test_log_file(request):
+ plugin = request.config.pluginmanager.getplugin('logging-plugin')
+ assert plugin.log_file_handler.level == logging.WARNING
+ logging.getLogger('catchlog').info("This log message won't be shown")
+ logging.getLogger('catchlog').warning("This log message will be shown")
+ print('PASSED')
+ ''')
+
+ result = testdir.runpytest('-s')
+
+ # fnmatch_lines does an assertion internally
+ result.stdout.fnmatch_lines([
+ 'test_log_file_ini.py PASSED',
+ ])
+
+ # make sure that that we get a '0' exit code for the testsuite
+ assert result.ret == 0
+ assert os.path.isfile(log_file)
+ with open(log_file) as rfh:
+ contents = rfh.read()
+ assert "This log message will be shown" in contents
+ assert "This log message won't be shown" not in contents
+
+
+def test_log_file_ini_level(testdir):
+ log_file = testdir.tmpdir.join('pytest.log').strpath
+
+ testdir.makeini(
+ """
+ [pytest]
+ log_file={0}
+ log_file_level = INFO
+ """.format(log_file))
+ testdir.makepyfile('''
+ import pytest
+ import logging
+ def test_log_file(request):
+ plugin = request.config.pluginmanager.getplugin('logging-plugin')
+ assert plugin.log_file_handler.level == logging.INFO
+ logging.getLogger('catchlog').debug("This log message won't be shown")
+ logging.getLogger('catchlog').info("This log message will be shown")
+ print('PASSED')
+ ''')
+
+ result = testdir.runpytest('-s')
+
+ # fnmatch_lines does an assertion internally
+ result.stdout.fnmatch_lines([
+ 'test_log_file_ini_level.py PASSED',
+ ])
+
+ # make sure that that we get a '0' exit code for the testsuite
+ assert result.ret == 0
+ assert os.path.isfile(log_file)
+ with open(log_file) as rfh:
+ contents = rfh.read()
+ assert "This log message will be shown" in contents
+ assert "This log message won't be shown" not in contents
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/approx.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/approx.py
new file mode 100644
index 00000000000..300e1ce86f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/approx.py
@@ -0,0 +1,392 @@
+# encoding: utf-8
+import operator
+import sys
+import pytest
+import doctest
+
+from pytest import approx
+from operator import eq, ne
+from decimal import Decimal
+from fractions import Fraction
+inf, nan = float('inf'), float('nan')
+
+
+class MyDocTestRunner(doctest.DocTestRunner):
+
+ def __init__(self):
+ doctest.DocTestRunner.__init__(self)
+
+ def report_failure(self, out, test, example, got):
+ raise AssertionError("'{}' evaluates to '{}', not '{}'".format(
+ example.source.strip(), got.strip(), example.want.strip()))
+
+
+class TestApprox(object):
+
+ def test_repr_string(self):
+ plus_minus = u'\u00b1' if sys.version_info[0] > 2 else u'+-'
+ tol1, tol2, infr = '1.0e-06', '2.0e-06', 'inf'
+ assert repr(approx(1.0)) == '1.0 {pm} {tol1}'.format(pm=plus_minus, tol1=tol1)
+ assert repr(approx([1.0, 2.0])) == 'approx([1.0 {pm} {tol1}, 2.0 {pm} {tol2}])'.format(
+ pm=plus_minus, tol1=tol1, tol2=tol2)
+ assert repr(approx((1.0, 2.0))) == 'approx((1.0 {pm} {tol1}, 2.0 {pm} {tol2}))'.format(
+ pm=plus_minus, tol1=tol1, tol2=tol2)
+ assert repr(approx(inf)) == 'inf'
+ assert repr(approx(1.0, rel=nan)) == '1.0 {pm} ???'.format(pm=plus_minus)
+ assert repr(approx(1.0, rel=inf)) == '1.0 {pm} {infr}'.format(pm=plus_minus, infr=infr)
+ assert repr(approx(1.0j, rel=inf)) == '1j'
+
+ # Dictionaries aren't ordered, so we need to check both orders.
+ assert repr(approx({'a': 1.0, 'b': 2.0})) in (
+ "approx({{'a': 1.0 {pm} {tol1}, 'b': 2.0 {pm} {tol2}}})".format(pm=plus_minus, tol1=tol1, tol2=tol2),
+ "approx({{'b': 2.0 {pm} {tol2}, 'a': 1.0 {pm} {tol1}}})".format(pm=plus_minus, tol1=tol1, tol2=tol2),
+ )
+
+ def test_operator_overloading(self):
+ assert 1 == approx(1, rel=1e-6, abs=1e-12)
+ assert not (1 != approx(1, rel=1e-6, abs=1e-12))
+ assert 10 != approx(1, rel=1e-6, abs=1e-12)
+ assert not (10 == approx(1, rel=1e-6, abs=1e-12))
+
+ def test_exactly_equal(self):
+ examples = [
+ (2.0, 2.0),
+ (0.1e200, 0.1e200),
+ (1.123e-300, 1.123e-300),
+ (12345, 12345.0),
+ (0.0, -0.0),
+ (345678, 345678),
+ (Decimal('1.0001'), Decimal('1.0001')),
+ (Fraction(1, 3), Fraction(-1, -3)),
+ ]
+ for a, x in examples:
+ assert a == approx(x)
+
+ def test_opposite_sign(self):
+ examples = [
+ (eq, 1e-100, -1e-100),
+ (ne, 1e100, -1e100),
+ ]
+ for op, a, x in examples:
+ assert op(a, approx(x))
+
+ def test_zero_tolerance(self):
+ within_1e10 = [
+ (1.1e-100, 1e-100),
+ (-1.1e-100, -1e-100),
+ ]
+ for a, x in within_1e10:
+ assert x == approx(x, rel=0.0, abs=0.0)
+ assert a != approx(x, rel=0.0, abs=0.0)
+ assert a == approx(x, rel=0.0, abs=5e-101)
+ assert a != approx(x, rel=0.0, abs=5e-102)
+ assert a == approx(x, rel=5e-1, abs=0.0)
+ assert a != approx(x, rel=5e-2, abs=0.0)
+
+ def test_negative_tolerance(self):
+ # Negative tolerances are not allowed.
+ illegal_kwargs = [
+ dict(rel=-1e100),
+ dict(abs=-1e100),
+ dict(rel=1e100, abs=-1e100),
+ dict(rel=-1e100, abs=1e100),
+ dict(rel=-1e100, abs=-1e100),
+ ]
+ for kwargs in illegal_kwargs:
+ with pytest.raises(ValueError):
+ 1.1 == approx(1, **kwargs)
+
+ def test_inf_tolerance(self):
+ # Everything should be equal if the tolerance is infinite.
+ large_diffs = [
+ (1, 1000),
+ (1e-50, 1e50),
+ (-1.0, -1e300),
+ (0.0, 10),
+ ]
+ for a, x in large_diffs:
+ assert a != approx(x, rel=0.0, abs=0.0)
+ assert a == approx(x, rel=inf, abs=0.0)
+ assert a == approx(x, rel=0.0, abs=inf)
+ assert a == approx(x, rel=inf, abs=inf)
+
+ def test_inf_tolerance_expecting_zero(self):
+ # If the relative tolerance is zero but the expected value is infinite,
+ # the actual tolerance is a NaN, which should be an error.
+ illegal_kwargs = [
+ dict(rel=inf, abs=0.0),
+ dict(rel=inf, abs=inf),
+ ]
+ for kwargs in illegal_kwargs:
+ with pytest.raises(ValueError):
+ 1 == approx(0, **kwargs)
+
+ def test_nan_tolerance(self):
+ illegal_kwargs = [
+ dict(rel=nan),
+ dict(abs=nan),
+ dict(rel=nan, abs=nan),
+ ]
+ for kwargs in illegal_kwargs:
+ with pytest.raises(ValueError):
+ 1.1 == approx(1, **kwargs)
+
+ def test_reasonable_defaults(self):
+ # Whatever the defaults are, they should work for numbers close to 1
+ # than have a small amount of floating-point error.
+ assert 0.1 + 0.2 == approx(0.3)
+
+ def test_default_tolerances(self):
+ # This tests the defaults as they are currently set. If you change the
+ # defaults, this test will fail but you should feel free to change it.
+ # None of the other tests (except the doctests) should be affected by
+ # the choice of defaults.
+ examples = [
+ # Relative tolerance used.
+ (eq, 1e100 + 1e94, 1e100),
+ (ne, 1e100 + 2e94, 1e100),
+ (eq, 1e0 + 1e-6, 1e0),
+ (ne, 1e0 + 2e-6, 1e0),
+ # Absolute tolerance used.
+ (eq, 1e-100, + 1e-106),
+ (eq, 1e-100, + 2e-106),
+ (eq, 1e-100, 0),
+ ]
+ for op, a, x in examples:
+ assert op(a, approx(x))
+
+ def test_custom_tolerances(self):
+ assert 1e8 + 1e0 == approx(1e8, rel=5e-8, abs=5e0)
+ assert 1e8 + 1e0 == approx(1e8, rel=5e-9, abs=5e0)
+ assert 1e8 + 1e0 == approx(1e8, rel=5e-8, abs=5e-1)
+ assert 1e8 + 1e0 != approx(1e8, rel=5e-9, abs=5e-1)
+
+ assert 1e0 + 1e-8 == approx(1e0, rel=5e-8, abs=5e-8)
+ assert 1e0 + 1e-8 == approx(1e0, rel=5e-9, abs=5e-8)
+ assert 1e0 + 1e-8 == approx(1e0, rel=5e-8, abs=5e-9)
+ assert 1e0 + 1e-8 != approx(1e0, rel=5e-9, abs=5e-9)
+
+ assert 1e-8 + 1e-16 == approx(1e-8, rel=5e-8, abs=5e-16)
+ assert 1e-8 + 1e-16 == approx(1e-8, rel=5e-9, abs=5e-16)
+ assert 1e-8 + 1e-16 == approx(1e-8, rel=5e-8, abs=5e-17)
+ assert 1e-8 + 1e-16 != approx(1e-8, rel=5e-9, abs=5e-17)
+
+ def test_relative_tolerance(self):
+ within_1e8_rel = [
+ (1e8 + 1e0, 1e8),
+ (1e0 + 1e-8, 1e0),
+ (1e-8 + 1e-16, 1e-8),
+ ]
+ for a, x in within_1e8_rel:
+ assert a == approx(x, rel=5e-8, abs=0.0)
+ assert a != approx(x, rel=5e-9, abs=0.0)
+
+ def test_absolute_tolerance(self):
+ within_1e8_abs = [
+ (1e8 + 9e-9, 1e8),
+ (1e0 + 9e-9, 1e0),
+ (1e-8 + 9e-9, 1e-8),
+ ]
+ for a, x in within_1e8_abs:
+ assert a == approx(x, rel=0, abs=5e-8)
+ assert a != approx(x, rel=0, abs=5e-9)
+
+ def test_expecting_zero(self):
+ examples = [
+ (ne, 1e-6, 0.0),
+ (ne, -1e-6, 0.0),
+ (eq, 1e-12, 0.0),
+ (eq, -1e-12, 0.0),
+ (ne, 2e-12, 0.0),
+ (ne, -2e-12, 0.0),
+ (ne, inf, 0.0),
+ (ne, nan, 0.0),
+ ]
+ for op, a, x in examples:
+ assert op(a, approx(x, rel=0.0, abs=1e-12))
+ assert op(a, approx(x, rel=1e-6, abs=1e-12))
+
+ def test_expecting_inf(self):
+ examples = [
+ (eq, inf, inf),
+ (eq, -inf, -inf),
+ (ne, inf, -inf),
+ (ne, 0.0, inf),
+ (ne, nan, inf),
+ ]
+ for op, a, x in examples:
+ assert op(a, approx(x))
+
+ def test_expecting_nan(self):
+ examples = [
+ (eq, nan, nan),
+ (eq, -nan, -nan),
+ (eq, nan, -nan),
+ (ne, 0.0, nan),
+ (ne, inf, nan),
+ ]
+ for op, a, x in examples:
+ # Nothing is equal to NaN by default.
+ assert a != approx(x)
+
+ # If ``nan_ok=True``, then NaN is equal to NaN.
+ assert op(a, approx(x, nan_ok=True))
+
+ def test_int(self):
+ within_1e6 = [
+ (1000001, 1000000),
+ (-1000001, -1000000),
+ ]
+ for a, x in within_1e6:
+ assert a == approx(x, rel=5e-6, abs=0)
+ assert a != approx(x, rel=5e-7, abs=0)
+ assert approx(x, rel=5e-6, abs=0) == a
+ assert approx(x, rel=5e-7, abs=0) != a
+
+ def test_decimal(self):
+ within_1e6 = [
+ (Decimal('1.000001'), Decimal('1.0')),
+ (Decimal('-1.000001'), Decimal('-1.0')),
+ ]
+ for a, x in within_1e6:
+ assert a == approx(x, rel=Decimal('5e-6'), abs=0)
+ assert a != approx(x, rel=Decimal('5e-7'), abs=0)
+ assert approx(x, rel=Decimal('5e-6'), abs=0) == a
+ assert approx(x, rel=Decimal('5e-7'), abs=0) != a
+
+ def test_fraction(self):
+ within_1e6 = [
+ (1 + Fraction(1, 1000000), Fraction(1)),
+ (-1 - Fraction(-1, 1000000), Fraction(-1)),
+ ]
+ for a, x in within_1e6:
+ assert a == approx(x, rel=5e-6, abs=0)
+ assert a != approx(x, rel=5e-7, abs=0)
+ assert approx(x, rel=5e-6, abs=0) == a
+ assert approx(x, rel=5e-7, abs=0) != a
+
+ def test_complex(self):
+ within_1e6 = [
+ (1.000001 + 1.0j, 1.0 + 1.0j),
+ (1.0 + 1.000001j, 1.0 + 1.0j),
+ (-1.000001 + 1.0j, -1.0 + 1.0j),
+ (1.0 - 1.000001j, 1.0 - 1.0j),
+ ]
+ for a, x in within_1e6:
+ assert a == approx(x, rel=5e-6, abs=0)
+ assert a != approx(x, rel=5e-7, abs=0)
+ assert approx(x, rel=5e-6, abs=0) == a
+ assert approx(x, rel=5e-7, abs=0) != a
+
+ def test_list(self):
+ actual = [1 + 1e-7, 2 + 1e-8]
+ expected = [1, 2]
+
+ # Return false if any element is outside the tolerance.
+ assert actual == approx(expected, rel=5e-7, abs=0)
+ assert actual != approx(expected, rel=5e-8, abs=0)
+ assert approx(expected, rel=5e-7, abs=0) == actual
+ assert approx(expected, rel=5e-8, abs=0) != actual
+
+ def test_list_wrong_len(self):
+ assert [1, 2] != approx([1])
+ assert [1, 2] != approx([1, 2, 3])
+
+ def test_tuple(self):
+ actual = (1 + 1e-7, 2 + 1e-8)
+ expected = (1, 2)
+
+ # Return false if any element is outside the tolerance.
+ assert actual == approx(expected, rel=5e-7, abs=0)
+ assert actual != approx(expected, rel=5e-8, abs=0)
+ assert approx(expected, rel=5e-7, abs=0) == actual
+ assert approx(expected, rel=5e-8, abs=0) != actual
+
+ def test_tuple_wrong_len(self):
+ assert (1, 2) != approx((1,))
+ assert (1, 2) != approx((1, 2, 3))
+
+ def test_dict(self):
+ actual = {'a': 1 + 1e-7, 'b': 2 + 1e-8}
+ # Dictionaries became ordered in python3.6, so switch up the order here
+ # to make sure it doesn't matter.
+ expected = {'b': 2, 'a': 1}
+
+ # Return false if any element is outside the tolerance.
+ assert actual == approx(expected, rel=5e-7, abs=0)
+ assert actual != approx(expected, rel=5e-8, abs=0)
+ assert approx(expected, rel=5e-7, abs=0) == actual
+ assert approx(expected, rel=5e-8, abs=0) != actual
+
+ def test_dict_wrong_len(self):
+ assert {'a': 1, 'b': 2} != approx({'a': 1})
+ assert {'a': 1, 'b': 2} != approx({'a': 1, 'c': 2})
+ assert {'a': 1, 'b': 2} != approx({'a': 1, 'b': 2, 'c': 3})
+
+ def test_numpy_array(self):
+ np = pytest.importorskip('numpy')
+
+ actual = np.array([1 + 1e-7, 2 + 1e-8])
+ expected = np.array([1, 2])
+
+ # Return false if any element is outside the tolerance.
+ assert actual == approx(expected, rel=5e-7, abs=0)
+ assert actual != approx(expected, rel=5e-8, abs=0)
+ assert approx(expected, rel=5e-7, abs=0) == expected
+ assert approx(expected, rel=5e-8, abs=0) != actual
+
+ # Should be able to compare lists with numpy arrays.
+ assert list(actual) == approx(expected, rel=5e-7, abs=0)
+ assert list(actual) != approx(expected, rel=5e-8, abs=0)
+ assert actual == approx(list(expected), rel=5e-7, abs=0)
+ assert actual != approx(list(expected), rel=5e-8, abs=0)
+
+ def test_numpy_array_wrong_shape(self):
+ np = pytest.importorskip('numpy')
+
+ a12 = np.array([[1, 2]])
+ a21 = np.array([[1], [2]])
+
+ assert a12 != approx(a21)
+ assert a21 != approx(a12)
+
+ def test_doctests(self):
+ parser = doctest.DocTestParser()
+ test = parser.get_doctest(
+ approx.__doc__,
+ {'approx': approx},
+ approx.__name__,
+ None, None,
+ )
+ runner = MyDocTestRunner()
+ runner.run(test)
+
+ def test_unicode_plus_minus(self, testdir):
+ """
+ Comparing approx instances inside lists should not produce an error in the detailed diff.
+ Integration test for issue #2111.
+ """
+ testdir.makepyfile("""
+ import pytest
+ def test_foo():
+ assert [3] == [pytest.approx(4)]
+ """)
+ expected = '4.0e-06'
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ '*At index 0 diff: 3 != 4 * {0}'.format(expected),
+ '=* 1 failed in *=',
+ ])
+
+ @pytest.mark.parametrize('op', [
+ pytest.param(operator.le, id='<='),
+ pytest.param(operator.lt, id='<'),
+ pytest.param(operator.ge, id='>='),
+ pytest.param(operator.gt, id='>'),
+ ])
+ def test_comparison_operator_type_error(self, op):
+ """
+ pytest.approx should raise TypeError for operators other than == and != (#2003).
+ """
+ with pytest.raises(TypeError):
+ op(1, approx(1, rel=1e-6, abs=1e-12))
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/collect.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/collect.py
new file mode 100644
index 00000000000..16c2154b8c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/collect.py
@@ -0,0 +1,1402 @@
+# -*- coding: utf-8 -*-
+import os
+import sys
+from textwrap import dedent
+
+import _pytest._code
+import py
+import pytest
+from _pytest.main import (
+ Collector,
+ EXIT_NOTESTSCOLLECTED
+)
+
+
+ignore_parametrized_marks = pytest.mark.filterwarnings('ignore:Applying marks directly to parameters')
+
+
+class TestModule(object):
+ def test_failing_import(self, testdir):
+ modcol = testdir.getmodulecol("import alksdjalskdjalkjals")
+ pytest.raises(Collector.CollectError, modcol.collect)
+
+ def test_import_duplicate(self, testdir):
+ a = testdir.mkdir("a")
+ b = testdir.mkdir("b")
+ p = a.ensure("test_whatever.py")
+ p.pyimport()
+ del py.std.sys.modules['test_whatever']
+ b.ensure("test_whatever.py")
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*import*mismatch*",
+ "*imported*test_whatever*",
+ "*%s*" % a.join("test_whatever.py"),
+ "*not the same*",
+ "*%s*" % b.join("test_whatever.py"),
+ "*HINT*",
+ ])
+
+ def test_import_prepend_append(self, testdir, monkeypatch):
+ syspath = list(sys.path)
+ monkeypatch.setattr(sys, "path", syspath)
+ root1 = testdir.mkdir("root1")
+ root2 = testdir.mkdir("root2")
+ root1.ensure("x456.py")
+ root2.ensure("x456.py")
+ p = root2.join("test_x456.py")
+ monkeypatch.syspath_prepend(str(root1))
+ p.write(dedent("""\
+ import x456
+ def test():
+ assert x456.__file__.startswith(%r)
+ """ % str(root2)))
+ with root2.as_cwd():
+ reprec = testdir.inline_run("--import-mode=append")
+ reprec.assertoutcome(passed=0, failed=1)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+ def test_syntax_error_in_module(self, testdir):
+ modcol = testdir.getmodulecol("this is a syntax error")
+ pytest.raises(modcol.CollectError, modcol.collect)
+ pytest.raises(modcol.CollectError, modcol.collect)
+
+ def test_module_considers_pluginmanager_at_import(self, testdir):
+ modcol = testdir.getmodulecol("pytest_plugins='xasdlkj',")
+ pytest.raises(ImportError, lambda: modcol.obj)
+
+ def test_invalid_test_module_name(self, testdir):
+ a = testdir.mkdir('a')
+ a.ensure('test_one.part1.py')
+ result = testdir.runpytest("-rw")
+ result.stdout.fnmatch_lines([
+ "ImportError while importing test module*test_one.part1*",
+ "Hint: make sure your test modules/packages have valid Python names.",
+ ])
+
+ @pytest.mark.parametrize('verbose', [0, 1, 2])
+ def test_show_traceback_import_error(self, testdir, verbose):
+ """Import errors when collecting modules should display the traceback (#1976).
+
+ With low verbosity we omit pytest and internal modules, otherwise show all traceback entries.
+ """
+ testdir.makepyfile(
+ foo_traceback_import_error="""
+ from bar_traceback_import_error import NOT_AVAILABLE
+ """,
+ bar_traceback_import_error="",
+ )
+ testdir.makepyfile("""
+ import foo_traceback_import_error
+ """)
+ args = ('-v',) * verbose
+ result = testdir.runpytest(*args)
+ result.stdout.fnmatch_lines([
+ "ImportError while importing test module*",
+ "Traceback:",
+ "*from bar_traceback_import_error import NOT_AVAILABLE",
+ "*cannot import name *NOT_AVAILABLE*",
+ ])
+ assert result.ret == 2
+
+ stdout = result.stdout.str()
+ for name in ('_pytest', os.path.join('py', '_path')):
+ if verbose == 2:
+ assert name in stdout
+ else:
+ assert name not in stdout
+
+ def test_show_traceback_import_error_unicode(self, testdir):
+ """Check test modules collected which raise ImportError with unicode messages
+ are handled properly (#2336).
+ """
+ testdir.makepyfile(u"""
+ # -*- coding: utf-8 -*-
+ raise ImportError(u'Something bad happened ☺')
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "ImportError while importing test module*",
+ "Traceback:",
+ "*raise ImportError*Something bad happened*",
+ ])
+ assert result.ret == 2
+
+
+class TestClass(object):
+ def test_class_with_init_warning(self, testdir):
+ testdir.makepyfile("""
+ class TestClass1(object):
+ def __init__(self):
+ pass
+ """)
+ result = testdir.runpytest("-rw")
+ result.stdout.fnmatch_lines([
+ "*cannot collect test class 'TestClass1' because it has a __init__ constructor",
+ ])
+
+ def test_class_subclassobject(self, testdir):
+ testdir.getmodulecol("""
+ class test(object):
+ pass
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*collected 0*",
+ ])
+
+ def test_static_method(self, testdir):
+ """Support for collecting staticmethod tests (#2528, #2699)"""
+ testdir.getmodulecol("""
+ import pytest
+ class Test(object):
+ @staticmethod
+ def test_something():
+ pass
+
+ @pytest.fixture
+ def fix(self):
+ return 1
+
+ @staticmethod
+ def test_fix(fix):
+ assert fix == 1
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*collected 2 items*",
+ "*2 passed in*",
+ ])
+
+ def test_setup_teardown_class_as_classmethod(self, testdir):
+ testdir.makepyfile(test_mod1="""
+ class TestClassMethod(object):
+ @classmethod
+ def setup_class(cls):
+ pass
+ def test_1(self):
+ pass
+ @classmethod
+ def teardown_class(cls):
+ pass
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*1 passed*",
+ ])
+
+ def test_issue1035_obj_has_getattr(self, testdir):
+ modcol = testdir.getmodulecol("""
+ class Chameleon(object):
+ def __getattr__(self, name):
+ return True
+ chameleon = Chameleon()
+ """)
+ colitems = modcol.collect()
+ assert len(colitems) == 0
+
+ def test_issue1579_namedtuple(self, testdir):
+ testdir.makepyfile("""
+ import collections
+
+ TestCase = collections.namedtuple('TestCase', ['a'])
+ """)
+ result = testdir.runpytest('-rw')
+ result.stdout.fnmatch_lines(
+ "*cannot collect test class 'TestCase' "
+ "because it has a __new__ constructor*"
+ )
+
+ def test_issue2234_property(self, testdir):
+ testdir.makepyfile("""
+ class TestCase(object):
+ @property
+ def prop(self):
+ raise NotImplementedError()
+ """)
+ result = testdir.runpytest()
+ assert result.ret == EXIT_NOTESTSCOLLECTED
+
+
+class TestGenerator(object):
+ def test_generative_functions(self, testdir):
+ modcol = testdir.getmodulecol("""
+ def func1(arg, arg2):
+ assert arg == arg2
+
+ def test_gen():
+ yield func1, 17, 3*5
+ yield func1, 42, 6*7
+ """)
+ colitems = modcol.collect()
+ assert len(colitems) == 1
+ gencol = colitems[0]
+ assert isinstance(gencol, pytest.Generator)
+ gencolitems = gencol.collect()
+ assert len(gencolitems) == 2
+ assert isinstance(gencolitems[0], pytest.Function)
+ assert isinstance(gencolitems[1], pytest.Function)
+ assert gencolitems[0].name == '[0]'
+ assert gencolitems[0].obj.__name__ == 'func1'
+
+ def test_generative_methods(self, testdir):
+ modcol = testdir.getmodulecol("""
+ def func1(arg, arg2):
+ assert arg == arg2
+ class TestGenMethods(object):
+ def test_gen(self):
+ yield func1, 17, 3*5
+ yield func1, 42, 6*7
+ """)
+ gencol = modcol.collect()[0].collect()[0].collect()[0]
+ assert isinstance(gencol, pytest.Generator)
+ gencolitems = gencol.collect()
+ assert len(gencolitems) == 2
+ assert isinstance(gencolitems[0], pytest.Function)
+ assert isinstance(gencolitems[1], pytest.Function)
+ assert gencolitems[0].name == '[0]'
+ assert gencolitems[0].obj.__name__ == 'func1'
+
+ def test_generative_functions_with_explicit_names(self, testdir):
+ modcol = testdir.getmodulecol("""
+ def func1(arg, arg2):
+ assert arg == arg2
+
+ def test_gen():
+ yield "seventeen", func1, 17, 3*5
+ yield "fortytwo", func1, 42, 6*7
+ """)
+ colitems = modcol.collect()
+ assert len(colitems) == 1
+ gencol = colitems[0]
+ assert isinstance(gencol, pytest.Generator)
+ gencolitems = gencol.collect()
+ assert len(gencolitems) == 2
+ assert isinstance(gencolitems[0], pytest.Function)
+ assert isinstance(gencolitems[1], pytest.Function)
+ assert gencolitems[0].name == "['seventeen']"
+ assert gencolitems[0].obj.__name__ == 'func1'
+ assert gencolitems[1].name == "['fortytwo']"
+ assert gencolitems[1].obj.__name__ == 'func1'
+
+ def test_generative_functions_unique_explicit_names(self, testdir):
+ # generative
+ modcol = testdir.getmodulecol("""
+ def func(): pass
+ def test_gen():
+ yield "name", func
+ yield "name", func
+ """)
+ colitems = modcol.collect()
+ assert len(colitems) == 1
+ gencol = colitems[0]
+ assert isinstance(gencol, pytest.Generator)
+ pytest.raises(ValueError, "gencol.collect()")
+
+ def test_generative_methods_with_explicit_names(self, testdir):
+ modcol = testdir.getmodulecol("""
+ def func1(arg, arg2):
+ assert arg == arg2
+ class TestGenMethods(object):
+ def test_gen(self):
+ yield "m1", func1, 17, 3*5
+ yield "m2", func1, 42, 6*7
+ """)
+ gencol = modcol.collect()[0].collect()[0].collect()[0]
+ assert isinstance(gencol, pytest.Generator)
+ gencolitems = gencol.collect()
+ assert len(gencolitems) == 2
+ assert isinstance(gencolitems[0], pytest.Function)
+ assert isinstance(gencolitems[1], pytest.Function)
+ assert gencolitems[0].name == "['m1']"
+ assert gencolitems[0].obj.__name__ == 'func1'
+ assert gencolitems[1].name == "['m2']"
+ assert gencolitems[1].obj.__name__ == 'func1'
+
+ def test_order_of_execution_generator_same_codeline(self, testdir, tmpdir):
+ o = testdir.makepyfile("""
+ from __future__ import print_function
+ def test_generative_order_of_execution():
+ import py, pytest
+ test_list = []
+ expected_list = list(range(6))
+
+ def list_append(item):
+ test_list.append(item)
+
+ def assert_order_of_execution():
+ print('expected order', expected_list)
+ print('but got ', test_list)
+ assert test_list == expected_list
+
+ for i in expected_list:
+ yield list_append, i
+ yield assert_order_of_execution
+ """)
+ reprec = testdir.inline_run(o)
+ passed, skipped, failed = reprec.countoutcomes()
+ assert passed == 7
+ assert not skipped and not failed
+
+ def test_order_of_execution_generator_different_codeline(self, testdir):
+ o = testdir.makepyfile("""
+ from __future__ import print_function
+ def test_generative_tests_different_codeline():
+ import py, pytest
+ test_list = []
+ expected_list = list(range(3))
+
+ def list_append_2():
+ test_list.append(2)
+
+ def list_append_1():
+ test_list.append(1)
+
+ def list_append_0():
+ test_list.append(0)
+
+ def assert_order_of_execution():
+ print('expected order', expected_list)
+ print('but got ', test_list)
+ assert test_list == expected_list
+
+ yield list_append_0
+ yield list_append_1
+ yield list_append_2
+ yield assert_order_of_execution
+ """)
+ reprec = testdir.inline_run(o)
+ passed, skipped, failed = reprec.countoutcomes()
+ assert passed == 4
+ assert not skipped and not failed
+
+ def test_setupstate_is_preserved_134(self, testdir):
+ # yield-based tests are messy wrt to setupstate because
+ # during collection they already invoke setup functions
+ # and then again when they are run. For now, we want to make sure
+ # that the old 1.3.4 behaviour is preserved such that all
+ # yielded functions all share the same "self" instance that
+ # has been used during collection.
+ o = testdir.makepyfile("""
+ setuplist = []
+ class TestClass(object):
+ def setup_method(self, func):
+ #print "setup_method", self, func
+ setuplist.append(self)
+ self.init = 42
+
+ def teardown_method(self, func):
+ self.init = None
+
+ def test_func1(self):
+ pass
+
+ def test_func2(self):
+ yield self.func2
+ yield self.func2
+
+ def func2(self):
+ assert self.init
+
+ def test_setuplist():
+ # once for test_func2 during collection
+ # once for test_func1 during test run
+ # once for test_func2 during test run
+ #print setuplist
+ assert len(setuplist) == 3, len(setuplist)
+ assert setuplist[0] == setuplist[2], setuplist
+ assert setuplist[1] != setuplist[2], setuplist
+ """)
+ reprec = testdir.inline_run(o, '-v')
+ passed, skipped, failed = reprec.countoutcomes()
+ assert passed == 4
+ assert not skipped and not failed
+
+
+class TestFunction(object):
+ def test_getmodulecollector(self, testdir):
+ item = testdir.getitem("def test_func(): pass")
+ modcol = item.getparent(pytest.Module)
+ assert isinstance(modcol, pytest.Module)
+ assert hasattr(modcol.obj, 'test_func')
+
+ def test_function_as_object_instance_ignored(self, testdir):
+ testdir.makepyfile("""
+ class A(object):
+ def __call__(self, tmpdir):
+ 0/0
+
+ test_a = A()
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome()
+
+ def test_function_equality(self, testdir, tmpdir):
+ from _pytest.fixtures import FixtureManager
+ config = testdir.parseconfigure()
+ session = testdir.Session(config)
+ session._fixturemanager = FixtureManager(session)
+
+ def func1():
+ pass
+
+ def func2():
+ pass
+
+ f1 = pytest.Function(name="name", parent=session, config=config,
+ args=(1,), callobj=func1)
+ assert f1 == f1
+ f2 = pytest.Function(name="name", config=config,
+ callobj=func2, parent=session)
+ assert f1 != f2
+
+ def test_issue197_parametrize_emptyset(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.parametrize('arg', [])
+ def test_function(arg):
+ pass
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(skipped=1)
+
+ def test_single_tuple_unwraps_values(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.parametrize(('arg',), [(1,)])
+ def test_function(arg):
+ assert arg == 1
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+ def test_issue213_parametrize_value_no_equal(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ class A(object):
+ def __eq__(self, other):
+ raise ValueError("not possible")
+ @pytest.mark.parametrize('arg', [A()])
+ def test_function(arg):
+ assert arg.__class__.__name__ == "A"
+ """)
+ reprec = testdir.inline_run("--fulltrace")
+ reprec.assertoutcome(passed=1)
+
+ def test_parametrize_with_non_hashable_values(self, testdir):
+ """Test parametrization with non-hashable values."""
+ testdir.makepyfile("""
+ archival_mapping = {
+ '1.0': {'tag': '1.0'},
+ '1.2.2a1': {'tag': 'release-1.2.2a1'},
+ }
+
+ import pytest
+ @pytest.mark.parametrize('key value'.split(),
+ archival_mapping.items())
+ def test_archival_to_version(key, value):
+ assert key in archival_mapping
+ assert value == archival_mapping[key]
+ """)
+ rec = testdir.inline_run()
+ rec.assertoutcome(passed=2)
+
+ def test_parametrize_with_non_hashable_values_indirect(self, testdir):
+ """Test parametrization with non-hashable values with indirect parametrization."""
+ testdir.makepyfile("""
+ archival_mapping = {
+ '1.0': {'tag': '1.0'},
+ '1.2.2a1': {'tag': 'release-1.2.2a1'},
+ }
+
+ import pytest
+
+ @pytest.fixture
+ def key(request):
+ return request.param
+
+ @pytest.fixture
+ def value(request):
+ return request.param
+
+ @pytest.mark.parametrize('key value'.split(),
+ archival_mapping.items(), indirect=True)
+ def test_archival_to_version(key, value):
+ assert key in archival_mapping
+ assert value == archival_mapping[key]
+ """)
+ rec = testdir.inline_run()
+ rec.assertoutcome(passed=2)
+
+ def test_parametrize_overrides_fixture(self, testdir):
+ """Test parametrization when parameter overrides existing fixture with same name."""
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture
+ def value():
+ return 'value'
+
+ @pytest.mark.parametrize('value',
+ ['overridden'])
+ def test_overridden_via_param(value):
+ assert value == 'overridden'
+
+ @pytest.mark.parametrize('somevalue', ['overridden'])
+ def test_not_overridden(value, somevalue):
+ assert value == 'value'
+ assert somevalue == 'overridden'
+
+ @pytest.mark.parametrize('other,value', [('foo', 'overridden')])
+ def test_overridden_via_multiparam(other, value):
+ assert other == 'foo'
+ assert value == 'overridden'
+ """)
+ rec = testdir.inline_run()
+ rec.assertoutcome(passed=3)
+
+ def test_parametrize_overrides_parametrized_fixture(self, testdir):
+ """Test parametrization when parameter overrides existing parametrized fixture with same name."""
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture(params=[1, 2])
+ def value(request):
+ return request.param
+
+ @pytest.mark.parametrize('value',
+ ['overridden'])
+ def test_overridden_via_param(value):
+ assert value == 'overridden'
+ """)
+ rec = testdir.inline_run()
+ rec.assertoutcome(passed=1)
+
+ @ignore_parametrized_marks
+ def test_parametrize_with_mark(self, testdir):
+ items = testdir.getitems("""
+ import pytest
+ @pytest.mark.foo
+ @pytest.mark.parametrize('arg', [
+ 1,
+ pytest.mark.bar(pytest.mark.baz(2))
+ ])
+ def test_function(arg):
+ pass
+ """)
+ keywords = [item.keywords for item in items]
+ assert 'foo' in keywords[0] and 'bar' not in keywords[0] and 'baz' not in keywords[0]
+ assert 'foo' in keywords[1] and 'bar' in keywords[1] and 'baz' in keywords[1]
+
+ def test_function_equality_with_callspec(self, testdir, tmpdir):
+ items = testdir.getitems("""
+ import pytest
+ @pytest.mark.parametrize('arg', [1,2])
+ def test_function(arg):
+ pass
+ """)
+ assert items[0] != items[1]
+ assert not (items[0] == items[1])
+
+ def test_pyfunc_call(self, testdir):
+ item = testdir.getitem("def test_func(): raise ValueError")
+ config = item.config
+
+ class MyPlugin1(object):
+ def pytest_pyfunc_call(self, pyfuncitem):
+ raise ValueError
+
+ class MyPlugin2(object):
+ def pytest_pyfunc_call(self, pyfuncitem):
+ return True
+
+ config.pluginmanager.register(MyPlugin1())
+ config.pluginmanager.register(MyPlugin2())
+ config.hook.pytest_runtest_setup(item=item)
+ config.hook.pytest_pyfunc_call(pyfuncitem=item)
+
+ def test_multiple_parametrize(self, testdir):
+ modcol = testdir.getmodulecol("""
+ import pytest
+ @pytest.mark.parametrize('x', [0, 1])
+ @pytest.mark.parametrize('y', [2, 3])
+ def test1(x, y):
+ pass
+ """)
+ colitems = modcol.collect()
+ assert colitems[0].name == 'test1[2-0]'
+ assert colitems[1].name == 'test1[2-1]'
+ assert colitems[2].name == 'test1[3-0]'
+ assert colitems[3].name == 'test1[3-1]'
+
+ def test_issue751_multiple_parametrize_with_ids(self, testdir):
+ modcol = testdir.getmodulecol("""
+ import pytest
+ @pytest.mark.parametrize('x', [0], ids=['c'])
+ @pytest.mark.parametrize('y', [0, 1], ids=['a', 'b'])
+ class Test(object):
+ def test1(self, x, y):
+ pass
+ def test2(self, x, y):
+ pass
+ """)
+ colitems = modcol.collect()[0].collect()[0].collect()
+ assert colitems[0].name == 'test1[a-c]'
+ assert colitems[1].name == 'test1[b-c]'
+ assert colitems[2].name == 'test2[a-c]'
+ assert colitems[3].name == 'test2[b-c]'
+
+ @ignore_parametrized_marks
+ def test_parametrize_skipif(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ m = pytest.mark.skipif('True')
+
+ @pytest.mark.parametrize('x', [0, 1, m(2)])
+ def test_skip_if(x):
+ assert x < 2
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines('* 2 passed, 1 skipped in *')
+
+ @ignore_parametrized_marks
+ def test_parametrize_skip(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ m = pytest.mark.skip('')
+
+ @pytest.mark.parametrize('x', [0, 1, m(2)])
+ def test_skip(x):
+ assert x < 2
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines('* 2 passed, 1 skipped in *')
+
+ @ignore_parametrized_marks
+ def test_parametrize_skipif_no_skip(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ m = pytest.mark.skipif('False')
+
+ @pytest.mark.parametrize('x', [0, 1, m(2)])
+ def test_skipif_no_skip(x):
+ assert x < 2
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines('* 1 failed, 2 passed in *')
+
+ @ignore_parametrized_marks
+ def test_parametrize_xfail(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ m = pytest.mark.xfail('True')
+
+ @pytest.mark.parametrize('x', [0, 1, m(2)])
+ def test_xfail(x):
+ assert x < 2
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines('* 2 passed, 1 xfailed in *')
+
+ @ignore_parametrized_marks
+ def test_parametrize_passed(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ m = pytest.mark.xfail('True')
+
+ @pytest.mark.parametrize('x', [0, 1, m(2)])
+ def test_xfail(x):
+ pass
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines('* 2 passed, 1 xpassed in *')
+
+ @ignore_parametrized_marks
+ def test_parametrize_xfail_passed(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ m = pytest.mark.xfail('False')
+
+ @pytest.mark.parametrize('x', [0, 1, m(2)])
+ def test_passed(x):
+ pass
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines('* 3 passed in *')
+
+ def test_function_original_name(self, testdir):
+ items = testdir.getitems("""
+ import pytest
+ @pytest.mark.parametrize('arg', [1,2])
+ def test_func(arg):
+ pass
+ """)
+ assert [x.originalname for x in items] == ['test_func', 'test_func']
+
+
+class TestSorting(object):
+ def test_check_equality(self, testdir):
+ modcol = testdir.getmodulecol("""
+ def test_pass(): pass
+ def test_fail(): assert 0
+ """)
+ fn1 = testdir.collect_by_name(modcol, "test_pass")
+ assert isinstance(fn1, pytest.Function)
+ fn2 = testdir.collect_by_name(modcol, "test_pass")
+ assert isinstance(fn2, pytest.Function)
+
+ assert fn1 == fn2
+ assert fn1 != modcol
+ if py.std.sys.version_info < (3, 0):
+ assert cmp(fn1, fn2) == 0
+ assert hash(fn1) == hash(fn2)
+
+ fn3 = testdir.collect_by_name(modcol, "test_fail")
+ assert isinstance(fn3, pytest.Function)
+ assert not (fn1 == fn3)
+ assert fn1 != fn3
+
+ for fn in fn1, fn2, fn3:
+ assert fn != 3
+ assert fn != modcol
+ assert fn != [1, 2, 3]
+ assert [1, 2, 3] != fn
+ assert modcol != fn
+
+ def test_allow_sane_sorting_for_decorators(self, testdir):
+ modcol = testdir.getmodulecol("""
+ def dec(f):
+ g = lambda: f(2)
+ g.place_as = f
+ return g
+
+
+ def test_b(y):
+ pass
+ test_b = dec(test_b)
+
+ def test_a(y):
+ pass
+ test_a = dec(test_a)
+ """)
+ colitems = modcol.collect()
+ assert len(colitems) == 2
+ assert [item.name for item in colitems] == ['test_b', 'test_a']
+
+
+class TestConftestCustomization(object):
+ def test_pytest_pycollect_module(self, testdir):
+ testdir.makeconftest("""
+ import pytest
+ class MyModule(pytest.Module):
+ pass
+ def pytest_pycollect_makemodule(path, parent):
+ if path.basename == "test_xyz.py":
+ return MyModule(path, parent)
+ """)
+ testdir.makepyfile("def test_some(): pass")
+ testdir.makepyfile(test_xyz="def test_func(): pass")
+ result = testdir.runpytest("--collect-only")
+ result.stdout.fnmatch_lines([
+ "*<Module*test_pytest*",
+ "*<MyModule*xyz*",
+ ])
+
+ def test_customized_pymakemodule_issue205_subdir(self, testdir):
+ b = testdir.mkdir("a").mkdir("b")
+ b.join("conftest.py").write(_pytest._code.Source("""
+ import pytest
+ @pytest.hookimpl(hookwrapper=True)
+ def pytest_pycollect_makemodule():
+ outcome = yield
+ mod = outcome.get_result()
+ mod.obj.hello = "world"
+ """))
+ b.join("test_module.py").write(_pytest._code.Source("""
+ def test_hello():
+ assert hello == "world"
+ """))
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+ def test_customized_pymakeitem(self, testdir):
+ b = testdir.mkdir("a").mkdir("b")
+ b.join("conftest.py").write(_pytest._code.Source("""
+ import pytest
+ @pytest.hookimpl(hookwrapper=True)
+ def pytest_pycollect_makeitem():
+ outcome = yield
+ if outcome.excinfo is None:
+ result = outcome.get_result()
+ if result:
+ for func in result:
+ func._some123 = "world"
+ """))
+ b.join("test_module.py").write(_pytest._code.Source("""
+ import pytest
+
+ @pytest.fixture()
+ def obj(request):
+ return request.node._some123
+ def test_hello(obj):
+ assert obj == "world"
+ """))
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+ def test_pytest_pycollect_makeitem(self, testdir):
+ testdir.makeconftest("""
+ import pytest
+ class MyFunction(pytest.Function):
+ pass
+ def pytest_pycollect_makeitem(collector, name, obj):
+ if name == "some":
+ return MyFunction(name, collector)
+ """)
+ testdir.makepyfile("def some(): pass")
+ result = testdir.runpytest("--collect-only")
+ result.stdout.fnmatch_lines([
+ "*MyFunction*some*",
+ ])
+
+ def test_makeitem_non_underscore(self, testdir, monkeypatch):
+ modcol = testdir.getmodulecol("def _hello(): pass")
+ values = []
+ monkeypatch.setattr(pytest.Module, 'makeitem',
+ lambda self, name, obj: values.append(name))
+ values = modcol.collect()
+ assert '_hello' not in values
+
+ def test_issue2369_collect_module_fileext(self, testdir):
+ """Ensure we can collect files with weird file extensions as Python
+ modules (#2369)"""
+ # We'll implement a little finder and loader to import files containing
+ # Python source code whose file extension is ".narf".
+ testdir.makeconftest("""
+ import sys, os, imp
+ from _pytest.python import Module
+
+ class Loader:
+ def load_module(self, name):
+ return imp.load_source(name, name + ".narf")
+ class Finder:
+ def find_module(self, name, path=None):
+ if os.path.exists(name + ".narf"):
+ return Loader()
+ sys.meta_path.append(Finder())
+
+ def pytest_collect_file(path, parent):
+ if path.ext == ".narf":
+ return Module(path, parent)""")
+ testdir.makefile(".narf", """
+ def test_something():
+ assert 1 + 1 == 2""")
+ # Use runpytest_subprocess, since we're futzing with sys.meta_path.
+ result = testdir.runpytest_subprocess()
+ result.stdout.fnmatch_lines('*1 passed*')
+
+
+def test_setup_only_available_in_subdir(testdir):
+ sub1 = testdir.mkpydir("sub1")
+ sub2 = testdir.mkpydir("sub2")
+ sub1.join("conftest.py").write(_pytest._code.Source("""
+ import pytest
+ def pytest_runtest_setup(item):
+ assert item.fspath.purebasename == "test_in_sub1"
+ def pytest_runtest_call(item):
+ assert item.fspath.purebasename == "test_in_sub1"
+ def pytest_runtest_teardown(item):
+ assert item.fspath.purebasename == "test_in_sub1"
+ """))
+ sub2.join("conftest.py").write(_pytest._code.Source("""
+ import pytest
+ def pytest_runtest_setup(item):
+ assert item.fspath.purebasename == "test_in_sub2"
+ def pytest_runtest_call(item):
+ assert item.fspath.purebasename == "test_in_sub2"
+ def pytest_runtest_teardown(item):
+ assert item.fspath.purebasename == "test_in_sub2"
+ """))
+ sub1.join("test_in_sub1.py").write("def test_1(): pass")
+ sub2.join("test_in_sub2.py").write("def test_2(): pass")
+ result = testdir.runpytest("-v", "-s")
+ result.assert_outcomes(passed=2)
+
+
+def test_modulecol_roundtrip(testdir):
+ modcol = testdir.getmodulecol("pass", withinit=True)
+ trail = modcol.nodeid
+ newcol = modcol.session.perform_collect([trail], genitems=0)[0]
+ assert modcol.name == newcol.name
+
+
+class TestTracebackCutting(object):
+ def test_skip_simple(self):
+ excinfo = pytest.raises(pytest.skip.Exception, 'pytest.skip("xxx")')
+ assert excinfo.traceback[-1].frame.code.name == "skip"
+ assert excinfo.traceback[-1].ishidden()
+
+ def test_traceback_argsetup(self, testdir):
+ testdir.makeconftest("""
+ import pytest
+
+ @pytest.fixture
+ def hello(request):
+ raise ValueError("xyz")
+ """)
+ p = testdir.makepyfile("def test(hello): pass")
+ result = testdir.runpytest(p)
+ assert result.ret != 0
+ out = result.stdout.str()
+ assert "xyz" in out
+ assert "conftest.py:5: ValueError" in out
+ numentries = out.count("_ _ _") # separator for traceback entries
+ assert numentries == 0
+
+ result = testdir.runpytest("--fulltrace", p)
+ out = result.stdout.str()
+ assert "conftest.py:5: ValueError" in out
+ numentries = out.count("_ _ _ _") # separator for traceback entries
+ assert numentries > 3
+
+ def test_traceback_error_during_import(self, testdir):
+ testdir.makepyfile("""
+ x = 1
+ x = 2
+ x = 17
+ asd
+ """)
+ result = testdir.runpytest()
+ assert result.ret != 0
+ out = result.stdout.str()
+ assert "x = 1" not in out
+ assert "x = 2" not in out
+ result.stdout.fnmatch_lines([
+ " *asd*",
+ "E*NameError*",
+ ])
+ result = testdir.runpytest("--fulltrace")
+ out = result.stdout.str()
+ assert "x = 1" in out
+ assert "x = 2" in out
+ result.stdout.fnmatch_lines([
+ ">*asd*",
+ "E*NameError*",
+ ])
+
+ def test_traceback_filter_error_during_fixture_collection(self, testdir):
+ """integration test for issue #995.
+ """
+ testdir.makepyfile("""
+ import pytest
+
+ def fail_me(func):
+ ns = {}
+ exec('def w(): raise ValueError("fail me")', ns)
+ return ns['w']
+
+ @pytest.fixture(scope='class')
+ @fail_me
+ def fail_fixture():
+ pass
+
+ def test_failing_fixture(fail_fixture):
+ pass
+ """)
+ result = testdir.runpytest()
+ assert result.ret != 0
+ out = result.stdout.str()
+ assert "INTERNALERROR>" not in out
+ result.stdout.fnmatch_lines([
+ "*ValueError: fail me*",
+ "* 1 error in *",
+ ])
+
+ def test_filter_traceback_generated_code(self):
+ """test that filter_traceback() works with the fact that
+ py.code.Code.path attribute might return an str object.
+ In this case, one of the entries on the traceback was produced by
+ dynamically generated code.
+ See: https://bitbucket.org/pytest-dev/py/issues/71
+ This fixes #995.
+ """
+ from _pytest.python import filter_traceback
+ try:
+ ns = {}
+ exec('def foo(): raise ValueError', ns)
+ ns['foo']()
+ except ValueError:
+ _, _, tb = sys.exc_info()
+
+ tb = _pytest._code.Traceback(tb)
+ assert isinstance(tb[-1].path, str)
+ assert not filter_traceback(tb[-1])
+
+ def test_filter_traceback_path_no_longer_valid(self, testdir):
+ """test that filter_traceback() works with the fact that
+ py.code.Code.path attribute might return an str object.
+ In this case, one of the files in the traceback no longer exists.
+ This fixes #1133.
+ """
+ from _pytest.python import filter_traceback
+ testdir.syspathinsert()
+ testdir.makepyfile(filter_traceback_entry_as_str='''
+ def foo():
+ raise ValueError
+ ''')
+ try:
+ import filter_traceback_entry_as_str
+ filter_traceback_entry_as_str.foo()
+ except ValueError:
+ _, _, tb = sys.exc_info()
+
+ testdir.tmpdir.join('filter_traceback_entry_as_str.py').remove()
+ tb = _pytest._code.Traceback(tb)
+ assert isinstance(tb[-1].path, str)
+ assert filter_traceback(tb[-1])
+
+
+class TestReportInfo(object):
+ def test_itemreport_reportinfo(self, testdir, linecomp):
+ testdir.makeconftest("""
+ import pytest
+ class MyFunction(pytest.Function):
+ def reportinfo(self):
+ return "ABCDE", 42, "custom"
+ def pytest_pycollect_makeitem(collector, name, obj):
+ if name == "test_func":
+ return MyFunction(name, parent=collector)
+ """)
+ item = testdir.getitem("def test_func(): pass")
+ item.config.pluginmanager.getplugin("runner")
+ assert item.location == ("ABCDE", 42, "custom")
+
+ def test_func_reportinfo(self, testdir):
+ item = testdir.getitem("def test_func(): pass")
+ fspath, lineno, modpath = item.reportinfo()
+ assert fspath == item.fspath
+ assert lineno == 0
+ assert modpath == "test_func"
+
+ def test_class_reportinfo(self, testdir):
+ modcol = testdir.getmodulecol("""
+ # lineno 0
+ class TestClass(object):
+ def test_hello(self): pass
+ """)
+ classcol = testdir.collect_by_name(modcol, "TestClass")
+ fspath, lineno, msg = classcol.reportinfo()
+ assert fspath == modcol.fspath
+ assert lineno == 1
+ assert msg == "TestClass"
+
+ def test_generator_reportinfo(self, testdir):
+ modcol = testdir.getmodulecol("""
+ # lineno 0
+ def test_gen():
+ def check(x):
+ assert x
+ yield check, 3
+ """)
+ gencol = testdir.collect_by_name(modcol, "test_gen")
+ fspath, lineno, modpath = gencol.reportinfo()
+ assert fspath == modcol.fspath
+ assert lineno == 1
+ assert modpath == "test_gen"
+
+ genitem = gencol.collect()[0]
+ fspath, lineno, modpath = genitem.reportinfo()
+ assert fspath == modcol.fspath
+ assert lineno == 2
+ assert modpath == "test_gen[0]"
+ """
+ def test_func():
+ pass
+ def test_genfunc():
+ def check(x):
+ pass
+ yield check, 3
+ class TestClass(object):
+ def test_method(self):
+ pass
+ """
+
+ def test_reportinfo_with_nasty_getattr(self, testdir):
+ # https://github.com/pytest-dev/pytest/issues/1204
+ modcol = testdir.getmodulecol("""
+ # lineno 0
+ class TestClass(object):
+ def __getattr__(self, name):
+ return "this is not an int"
+
+ def test_foo(self):
+ pass
+ """)
+ classcol = testdir.collect_by_name(modcol, "TestClass")
+ instance = classcol.collect()[0]
+ fspath, lineno, msg = instance.reportinfo()
+
+
+def test_customized_python_discovery(testdir):
+ testdir.makeini("""
+ [pytest]
+ python_files=check_*.py
+ python_classes=Check
+ python_functions=check
+ """)
+ p = testdir.makepyfile("""
+ def check_simple():
+ pass
+ class CheckMyApp(object):
+ def check_meth(self):
+ pass
+ """)
+ p2 = p.new(basename=p.basename.replace("test", "check"))
+ p.move(p2)
+ result = testdir.runpytest("--collect-only", "-s")
+ result.stdout.fnmatch_lines([
+ "*check_customized*",
+ "*check_simple*",
+ "*CheckMyApp*",
+ "*check_meth*",
+ ])
+
+ result = testdir.runpytest()
+ assert result.ret == 0
+ result.stdout.fnmatch_lines([
+ "*2 passed*",
+ ])
+
+
+def test_customized_python_discovery_functions(testdir):
+ testdir.makeini("""
+ [pytest]
+ python_functions=_test
+ """)
+ testdir.makepyfile("""
+ def _test_underscore():
+ pass
+ """)
+ result = testdir.runpytest("--collect-only", "-s")
+ result.stdout.fnmatch_lines([
+ "*_test_underscore*",
+ ])
+
+ result = testdir.runpytest()
+ assert result.ret == 0
+ result.stdout.fnmatch_lines([
+ "*1 passed*",
+ ])
+
+
+def test_collector_attributes(testdir):
+ testdir.makeconftest("""
+ import pytest
+ def pytest_pycollect_makeitem(collector):
+ assert collector.Function == pytest.Function
+ assert collector.Class == pytest.Class
+ assert collector.Instance == pytest.Instance
+ assert collector.Module == pytest.Module
+ """)
+ testdir.makepyfile("""
+ def test_hello():
+ pass
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*1 passed*",
+ ])
+
+
+def test_customize_through_attributes(testdir):
+ testdir.makeconftest("""
+ import pytest
+ class MyFunction(pytest.Function):
+ pass
+ class MyInstance(pytest.Instance):
+ Function = MyFunction
+ class MyClass(pytest.Class):
+ Instance = MyInstance
+
+ def pytest_pycollect_makeitem(collector, name, obj):
+ if name.startswith("MyTestClass"):
+ return MyClass(name, parent=collector)
+ """)
+ testdir.makepyfile("""
+ class MyTestClass(object):
+ def test_hello(self):
+ pass
+ """)
+ result = testdir.runpytest("--collect-only")
+ result.stdout.fnmatch_lines([
+ "*MyClass*",
+ "*MyInstance*",
+ "*MyFunction*test_hello*",
+ ])
+
+
+def test_unorderable_types(testdir):
+ testdir.makepyfile("""
+ class TestJoinEmpty(object):
+ pass
+
+ def make_test():
+ class Test(object):
+ pass
+ Test.__name__ = "TestFoo"
+ return Test
+ TestFoo = make_test()
+ """)
+ result = testdir.runpytest()
+ assert "TypeError" not in result.stdout.str()
+ assert result.ret == EXIT_NOTESTSCOLLECTED
+
+
+def test_collect_functools_partial(testdir):
+ """
+ Test that collection of functools.partial object works, and arguments
+ to the wrapped functions are dealt correctly (see #811).
+ """
+ testdir.makepyfile("""
+ import functools
+ import pytest
+
+ @pytest.fixture
+ def fix1():
+ return 'fix1'
+
+ @pytest.fixture
+ def fix2():
+ return 'fix2'
+
+ def check1(i, fix1):
+ assert i == 2
+ assert fix1 == 'fix1'
+
+ def check2(fix1, i):
+ assert i == 2
+ assert fix1 == 'fix1'
+
+ def check3(fix1, i, fix2):
+ assert i == 2
+ assert fix1 == 'fix1'
+ assert fix2 == 'fix2'
+
+ test_ok_1 = functools.partial(check1, i=2)
+ test_ok_2 = functools.partial(check1, i=2, fix1='fix1')
+ test_ok_3 = functools.partial(check1, 2)
+ test_ok_4 = functools.partial(check2, i=2)
+ test_ok_5 = functools.partial(check3, i=2)
+ test_ok_6 = functools.partial(check3, i=2, fix1='fix1')
+
+ test_fail_1 = functools.partial(check2, 2)
+ test_fail_2 = functools.partial(check3, 2)
+ """)
+ result = testdir.inline_run()
+ result.assertoutcome(passed=6, failed=2)
+
+
+def test_dont_collect_non_function_callable(testdir):
+ """Test for issue https://github.com/pytest-dev/pytest/issues/331
+
+ In this case an INTERNALERROR occurred trying to report the failure of
+ a test like this one because py test failed to get the source lines.
+ """
+ testdir.makepyfile("""
+ class Oh(object):
+ def __call__(self):
+ pass
+
+ test_a = Oh()
+
+ def test_real():
+ pass
+ """)
+ result = testdir.runpytest('-rw')
+ result.stdout.fnmatch_lines([
+ '*collected 1 item*',
+ "*cannot collect 'test_a' because it is not a function*",
+ '*1 passed, 1 warnings in *',
+ ])
+
+
+def test_class_injection_does_not_break_collection(testdir):
+ """Tests whether injection during collection time will terminate testing.
+
+ In this case the error should not occur if the TestClass itself
+ is modified during collection time, and the original method list
+ is still used for collection.
+ """
+ testdir.makeconftest("""
+ from test_inject import TestClass
+ def pytest_generate_tests(metafunc):
+ TestClass.changed_var = {}
+ """)
+ testdir.makepyfile(test_inject='''
+ class TestClass(object):
+ def test_injection(self):
+ """Test being parametrized."""
+ pass
+ ''')
+ result = testdir.runpytest()
+ assert "RuntimeError: dictionary changed size during iteration" not in result.stdout.str()
+ result.stdout.fnmatch_lines(['*1 passed*'])
+
+
+def test_syntax_error_with_non_ascii_chars(testdir):
+ """Fix decoding issue while formatting SyntaxErrors during collection (#578)
+ """
+ testdir.makepyfile(u"""
+ # -*- coding: UTF-8 -*-
+
+ ☃
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ '*ERROR collecting*',
+ '*SyntaxError*',
+ '*1 error in*',
+ ])
+
+
+def test_skip_duplicates_by_default(testdir):
+ """Test for issue https://github.com/pytest-dev/pytest/issues/1609 (#1609)
+
+ Ignore duplicate directories.
+ """
+ a = testdir.mkdir("a")
+ fh = a.join("test_a.py")
+ fh.write(_pytest._code.Source("""
+ import pytest
+ def test_real():
+ pass
+ """))
+ result = testdir.runpytest(a.strpath, a.strpath)
+ result.stdout.fnmatch_lines([
+ '*collected 1 item*',
+ ])
+
+
+def test_keep_duplicates(testdir):
+ """Test for issue https://github.com/pytest-dev/pytest/issues/1609 (#1609)
+
+ Use --keep-duplicates to collect tests from duplicate directories.
+ """
+ a = testdir.mkdir("a")
+ fh = a.join("test_a.py")
+ fh.write(_pytest._code.Source("""
+ import pytest
+ def test_real():
+ pass
+ """))
+ result = testdir.runpytest("--keep-duplicates", a.strpath, a.strpath)
+ result.stdout.fnmatch_lines([
+ '*collected 2 item*',
+ ])
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/fixture.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/fixture.py
new file mode 100644
index 00000000000..b159e8ebb8e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/fixture.py
@@ -0,0 +1,3171 @@
+from textwrap import dedent
+
+import _pytest._code
+import pytest
+from _pytest.pytester import get_public_names
+from _pytest.fixtures import FixtureLookupError
+from _pytest import fixtures
+
+
+def test_getfuncargnames():
+ def f():
+ pass
+ assert not fixtures.getfuncargnames(f)
+
+ def g(arg):
+ pass
+ assert fixtures.getfuncargnames(g) == ('arg',)
+
+ def h(arg1, arg2="hello"):
+ pass
+ assert fixtures.getfuncargnames(h) == ('arg1',)
+
+ def h(arg1, arg2, arg3="hello"):
+ pass
+ assert fixtures.getfuncargnames(h) == ('arg1', 'arg2')
+
+ class A(object):
+ def f(self, arg1, arg2="hello"):
+ pass
+
+ @staticmethod
+ def static(arg1, arg2):
+ pass
+
+ assert fixtures.getfuncargnames(A().f) == ('arg1',)
+ assert fixtures.getfuncargnames(A.static, cls=A) == ('arg1', 'arg2')
+
+
+class TestFillFixtures(object):
+ def test_fillfuncargs_exposed(self):
+ # used by oejskit, kept for compatibility
+ assert pytest._fillfuncargs == fixtures.fillfixtures
+
+ def test_funcarg_lookupfails(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture
+ def xyzsomething(request):
+ return 42
+
+ def test_func(some):
+ pass
+ """)
+ result = testdir.runpytest() # "--collect-only")
+ assert result.ret != 0
+ result.stdout.fnmatch_lines([
+ "*def test_func(some)*",
+ "*fixture*some*not found*",
+ "*xyzsomething*",
+ ])
+
+ def test_funcarg_basic(self, testdir):
+ item = testdir.getitem("""
+ import pytest
+
+ @pytest.fixture
+ def some(request):
+ return request.function.__name__
+ @pytest.fixture
+ def other(request):
+ return 42
+ def test_func(some, other):
+ pass
+ """)
+ fixtures.fillfixtures(item)
+ del item.funcargs["request"]
+ assert len(get_public_names(item.funcargs)) == 2
+ assert item.funcargs['some'] == "test_func"
+ assert item.funcargs['other'] == 42
+
+ def test_funcarg_lookup_modulelevel(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture
+ def something(request):
+ return request.function.__name__
+
+ class TestClass(object):
+ def test_method(self, something):
+ assert something == "test_method"
+ def test_func(something):
+ assert something == "test_func"
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=2)
+
+ def test_funcarg_lookup_classlevel(self, testdir):
+ p = testdir.makepyfile("""
+ import pytest
+ class TestClass(object):
+
+ @pytest.fixture
+ def something(self, request):
+ return request.instance
+
+ def test_method(self, something):
+ assert something is self
+ """)
+ result = testdir.runpytest(p)
+ result.stdout.fnmatch_lines([
+ "*1 passed*"
+ ])
+
+ def test_conftest_funcargs_only_available_in_subdir(self, testdir):
+ sub1 = testdir.mkpydir("sub1")
+ sub2 = testdir.mkpydir("sub2")
+ sub1.join("conftest.py").write(_pytest._code.Source("""
+ import pytest
+ @pytest.fixture
+ def arg1(request):
+ pytest.raises(Exception, "request.getfixturevalue('arg2')")
+ """))
+ sub2.join("conftest.py").write(_pytest._code.Source("""
+ import pytest
+ @pytest.fixture
+ def arg2(request):
+ pytest.raises(Exception, "request.getfixturevalue('arg1')")
+ """))
+
+ sub1.join("test_in_sub1.py").write("def test_1(arg1): pass")
+ sub2.join("test_in_sub2.py").write("def test_2(arg2): pass")
+ result = testdir.runpytest("-v")
+ result.assert_outcomes(passed=2)
+
+ def test_extend_fixture_module_class(self, testdir):
+ testfile = testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture
+ def spam():
+ return 'spam'
+
+ class TestSpam(object):
+
+ @pytest.fixture
+ def spam(self, spam):
+ return spam * 2
+
+ def test_spam(self, spam):
+ assert spam == 'spamspam'
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(["*1 passed*"])
+ result = testdir.runpytest(testfile)
+ result.stdout.fnmatch_lines(["*1 passed*"])
+
+ def test_extend_fixture_conftest_module(self, testdir):
+ testdir.makeconftest("""
+ import pytest
+
+ @pytest.fixture
+ def spam():
+ return 'spam'
+ """)
+ testfile = testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture
+ def spam(spam):
+ return spam * 2
+
+ def test_spam(spam):
+ assert spam == 'spamspam'
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(["*1 passed*"])
+ result = testdir.runpytest(testfile)
+ result.stdout.fnmatch_lines(["*1 passed*"])
+
+ def test_extend_fixture_conftest_conftest(self, testdir):
+ testdir.makeconftest("""
+ import pytest
+
+ @pytest.fixture
+ def spam():
+ return 'spam'
+ """)
+ pkg = testdir.mkpydir("pkg")
+ pkg.join("conftest.py").write(_pytest._code.Source("""
+ import pytest
+
+ @pytest.fixture
+ def spam(spam):
+ return spam * 2
+ """))
+ testfile = pkg.join("test_spam.py")
+ testfile.write(_pytest._code.Source("""
+ def test_spam(spam):
+ assert spam == "spamspam"
+ """))
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(["*1 passed*"])
+ result = testdir.runpytest(testfile)
+ result.stdout.fnmatch_lines(["*1 passed*"])
+
+ def test_extend_fixture_conftest_plugin(self, testdir):
+ testdir.makepyfile(testplugin="""
+ import pytest
+
+ @pytest.fixture
+ def foo():
+ return 7
+ """)
+ testdir.syspathinsert()
+ testdir.makeconftest("""
+ import pytest
+
+ pytest_plugins = 'testplugin'
+
+ @pytest.fixture
+ def foo(foo):
+ return foo + 7
+ """)
+ testdir.makepyfile("""
+ def test_foo(foo):
+ assert foo == 14
+ """)
+ result = testdir.runpytest('-s')
+ assert result.ret == 0
+
+ def test_extend_fixture_plugin_plugin(self, testdir):
+ # Two plugins should extend each order in loading order
+ testdir.makepyfile(testplugin0="""
+ import pytest
+
+ @pytest.fixture
+ def foo():
+ return 7
+ """)
+ testdir.makepyfile(testplugin1="""
+ import pytest
+
+ @pytest.fixture
+ def foo(foo):
+ return foo + 7
+ """)
+ testdir.syspathinsert()
+ testdir.makepyfile("""
+ pytest_plugins = ['testplugin0', 'testplugin1']
+
+ def test_foo(foo):
+ assert foo == 14
+ """)
+ result = testdir.runpytest()
+ assert result.ret == 0
+
+ def test_override_parametrized_fixture_conftest_module(self, testdir):
+ """Test override of the parametrized fixture with non-parametrized one on the test module level."""
+ testdir.makeconftest("""
+ import pytest
+
+ @pytest.fixture(params=[1, 2, 3])
+ def spam(request):
+ return request.param
+ """)
+ testfile = testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture
+ def spam():
+ return 'spam'
+
+ def test_spam(spam):
+ assert spam == 'spam'
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(["*1 passed*"])
+ result = testdir.runpytest(testfile)
+ result.stdout.fnmatch_lines(["*1 passed*"])
+
+ def test_override_parametrized_fixture_conftest_conftest(self, testdir):
+ """Test override of the parametrized fixture with non-parametrized one on the conftest level."""
+ testdir.makeconftest("""
+ import pytest
+
+ @pytest.fixture(params=[1, 2, 3])
+ def spam(request):
+ return request.param
+ """)
+ subdir = testdir.mkpydir('subdir')
+ subdir.join("conftest.py").write(_pytest._code.Source("""
+ import pytest
+
+ @pytest.fixture
+ def spam():
+ return 'spam'
+ """))
+ testfile = subdir.join("test_spam.py")
+ testfile.write(_pytest._code.Source("""
+ def test_spam(spam):
+ assert spam == "spam"
+ """))
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(["*1 passed*"])
+ result = testdir.runpytest(testfile)
+ result.stdout.fnmatch_lines(["*1 passed*"])
+
+ def test_override_non_parametrized_fixture_conftest_module(self, testdir):
+ """Test override of the non-parametrized fixture with parametrized one on the test module level."""
+ testdir.makeconftest("""
+ import pytest
+
+ @pytest.fixture
+ def spam():
+ return 'spam'
+ """)
+ testfile = testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture(params=[1, 2, 3])
+ def spam(request):
+ return request.param
+
+ params = {'spam': 1}
+
+ def test_spam(spam):
+ assert spam == params['spam']
+ params['spam'] += 1
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(["*3 passed*"])
+ result = testdir.runpytest(testfile)
+ result.stdout.fnmatch_lines(["*3 passed*"])
+
+ def test_override_non_parametrized_fixture_conftest_conftest(self, testdir):
+ """Test override of the non-parametrized fixture with parametrized one on the conftest level."""
+ testdir.makeconftest("""
+ import pytest
+
+ @pytest.fixture
+ def spam():
+ return 'spam'
+ """)
+ subdir = testdir.mkpydir('subdir')
+ subdir.join("conftest.py").write(_pytest._code.Source("""
+ import pytest
+
+ @pytest.fixture(params=[1, 2, 3])
+ def spam(request):
+ return request.param
+ """))
+ testfile = subdir.join("test_spam.py")
+ testfile.write(_pytest._code.Source("""
+ params = {'spam': 1}
+
+ def test_spam(spam):
+ assert spam == params['spam']
+ params['spam'] += 1
+ """))
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(["*3 passed*"])
+ result = testdir.runpytest(testfile)
+ result.stdout.fnmatch_lines(["*3 passed*"])
+
+ def test_override_autouse_fixture_with_parametrized_fixture_conftest_conftest(self, testdir):
+ """Test override of the autouse fixture with parametrized one on the conftest level.
+ This test covers the issue explained in issue 1601
+ """
+ testdir.makeconftest("""
+ import pytest
+
+ @pytest.fixture(autouse=True)
+ def spam():
+ return 'spam'
+ """)
+ subdir = testdir.mkpydir('subdir')
+ subdir.join("conftest.py").write(_pytest._code.Source("""
+ import pytest
+
+ @pytest.fixture(params=[1, 2, 3])
+ def spam(request):
+ return request.param
+ """))
+ testfile = subdir.join("test_spam.py")
+ testfile.write(_pytest._code.Source("""
+ params = {'spam': 1}
+
+ def test_spam(spam):
+ assert spam == params['spam']
+ params['spam'] += 1
+ """))
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(["*3 passed*"])
+ result = testdir.runpytest(testfile)
+ result.stdout.fnmatch_lines(["*3 passed*"])
+
+ def test_autouse_fixture_plugin(self, testdir):
+ # A fixture from a plugin has no baseid set, which screwed up
+ # the autouse fixture handling.
+ testdir.makepyfile(testplugin="""
+ import pytest
+
+ @pytest.fixture(autouse=True)
+ def foo(request):
+ request.function.foo = 7
+ """)
+ testdir.syspathinsert()
+ testdir.makepyfile("""
+ pytest_plugins = 'testplugin'
+
+ def test_foo(request):
+ assert request.function.foo == 7
+ """)
+ result = testdir.runpytest()
+ assert result.ret == 0
+
+ def test_funcarg_lookup_error(self, testdir):
+ testdir.makeconftest("""
+ import pytest
+
+ @pytest.fixture
+ def a_fixture(): pass
+
+ @pytest.fixture
+ def b_fixture(): pass
+
+ @pytest.fixture
+ def c_fixture(): pass
+
+ @pytest.fixture
+ def d_fixture(): pass
+ """)
+ testdir.makepyfile("""
+ def test_lookup_error(unknown):
+ pass
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*ERROR at setup of test_lookup_error*",
+ " def test_lookup_error(unknown):*",
+ "E fixture 'unknown' not found",
+ "> available fixtures:*a_fixture,*b_fixture,*c_fixture,*d_fixture*monkeypatch,*", # sorted
+ "> use 'py*test --fixtures *' for help on them.",
+ "*1 error*",
+ ])
+ assert "INTERNAL" not in result.stdout.str()
+
+ def test_fixture_excinfo_leak(self, testdir):
+ # on python2 sys.excinfo would leak into fixture executions
+ testdir.makepyfile("""
+ import sys
+ import traceback
+ import pytest
+
+ @pytest.fixture
+ def leak():
+ if sys.exc_info()[0]: # python3 bug :)
+ traceback.print_exc()
+ #fails
+ assert sys.exc_info() == (None, None, None)
+
+ def test_leak(leak):
+ if sys.exc_info()[0]: # python3 bug :)
+ traceback.print_exc()
+ assert sys.exc_info() == (None, None, None)
+ """)
+ result = testdir.runpytest()
+ assert result.ret == 0
+
+
+class TestRequestBasic(object):
+ def test_request_attributes(self, testdir):
+ item = testdir.getitem("""
+ import pytest
+
+ @pytest.fixture
+ def something(request): pass
+ def test_func(something): pass
+ """)
+ req = fixtures.FixtureRequest(item)
+ assert req.function == item.obj
+ assert req.keywords == item.keywords
+ assert hasattr(req.module, 'test_func')
+ assert req.cls is None
+ assert req.function.__name__ == "test_func"
+ assert req.config == item.config
+ assert repr(req).find(req.function.__name__) != -1
+
+ def test_request_attributes_method(self, testdir):
+ item, = testdir.getitems("""
+ import pytest
+ class TestB(object):
+
+ @pytest.fixture
+ def something(self, request):
+ return 1
+ def test_func(self, something):
+ pass
+ """)
+ req = item._request
+ assert req.cls.__name__ == "TestB"
+ assert req.instance.__class__ == req.cls
+
+ def test_request_contains_funcarg_arg2fixturedefs(self, testdir):
+ modcol = testdir.getmodulecol("""
+ import pytest
+ @pytest.fixture
+ def something(request):
+ pass
+ class TestClass(object):
+ def test_method(self, something):
+ pass
+ """)
+ item1, = testdir.genitems([modcol])
+ assert item1.name == "test_method"
+ arg2fixturedefs = fixtures.FixtureRequest(item1)._arg2fixturedefs
+ assert len(arg2fixturedefs) == 1
+ assert arg2fixturedefs['something'][0].argname == "something"
+
+ def test_getfixturevalue_recursive(self, testdir):
+ testdir.makeconftest("""
+ import pytest
+
+ @pytest.fixture
+ def something(request):
+ return 1
+ """)
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture
+ def something(request):
+ return request.getfixturevalue("something") + 1
+ def test_func(something):
+ assert something == 2
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+ @pytest.mark.parametrize(
+ 'getfixmethod', ('getfixturevalue', 'getfuncargvalue'))
+ def test_getfixturevalue(self, testdir, getfixmethod):
+ item = testdir.getitem("""
+ import pytest
+ values = [2]
+ @pytest.fixture
+ def something(request): return 1
+ @pytest.fixture
+ def other(request):
+ return values.pop()
+ def test_func(something): pass
+ """)
+ import contextlib
+ if getfixmethod == 'getfuncargvalue':
+ warning_expectation = pytest.warns(DeprecationWarning)
+ else:
+ # see #1830 for a cleaner way to accomplish this
+ @contextlib.contextmanager
+ def expecting_no_warning():
+ yield
+
+ warning_expectation = expecting_no_warning()
+
+ req = item._request
+ with warning_expectation:
+ fixture_fetcher = getattr(req, getfixmethod)
+ with pytest.raises(FixtureLookupError):
+ fixture_fetcher("notexists")
+ val = fixture_fetcher("something")
+ assert val == 1
+ val = fixture_fetcher("something")
+ assert val == 1
+ val2 = fixture_fetcher("other")
+ assert val2 == 2
+ val2 = fixture_fetcher("other") # see about caching
+ assert val2 == 2
+ pytest._fillfuncargs(item)
+ assert item.funcargs["something"] == 1
+ assert len(get_public_names(item.funcargs)) == 2
+ assert "request" in item.funcargs
+
+ def test_request_addfinalizer(self, testdir):
+ item = testdir.getitem("""
+ import pytest
+ teardownlist = []
+ @pytest.fixture
+ def something(request):
+ request.addfinalizer(lambda: teardownlist.append(1))
+ def test_func(something): pass
+ """)
+ item.session._setupstate.prepare(item)
+ pytest._fillfuncargs(item)
+ # successively check finalization calls
+ teardownlist = item.getparent(pytest.Module).obj.teardownlist
+ ss = item.session._setupstate
+ assert not teardownlist
+ ss.teardown_exact(item, None)
+ print(ss.stack)
+ assert teardownlist == [1]
+
+ def test_mark_as_fixture_with_prefix_and_decorator_fails(self, testdir):
+ testdir.makeconftest("""
+ import pytest
+
+ @pytest.fixture
+ def pytest_funcarg__marked_with_prefix_and_decorator():
+ pass
+ """)
+ result = testdir.runpytest_subprocess()
+ assert result.ret != 0
+ result.stdout.fnmatch_lines([
+ "*AssertionError: fixtures cannot have*@pytest.fixture*",
+ "*pytest_funcarg__marked_with_prefix_and_decorator*"
+ ])
+
+ def test_request_addfinalizer_failing_setup(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ values = [1]
+ @pytest.fixture
+ def myfix(request):
+ request.addfinalizer(values.pop)
+ assert 0
+ def test_fix(myfix):
+ pass
+ def test_finalizer_ran():
+ assert not values
+ """)
+ reprec = testdir.inline_run("-s")
+ reprec.assertoutcome(failed=1, passed=1)
+
+ def test_request_addfinalizer_failing_setup_module(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ values = [1, 2]
+ @pytest.fixture(scope="module")
+ def myfix(request):
+ request.addfinalizer(values.pop)
+ request.addfinalizer(values.pop)
+ assert 0
+ def test_fix(myfix):
+ pass
+ """)
+ reprec = testdir.inline_run("-s")
+ mod = reprec.getcalls("pytest_runtest_setup")[0].item.module
+ assert not mod.values
+
+ def test_request_addfinalizer_partial_setup_failure(self, testdir):
+ p = testdir.makepyfile("""
+ import pytest
+ values = []
+ @pytest.fixture
+ def something(request):
+ request.addfinalizer(lambda: values.append(None))
+ def test_func(something, missingarg):
+ pass
+ def test_second():
+ assert len(values) == 1
+ """)
+ result = testdir.runpytest(p)
+ result.stdout.fnmatch_lines([
+ "*1 error*" # XXX the whole module collection fails
+ ])
+
+ def test_request_subrequest_addfinalizer_exceptions(self, testdir):
+ """
+ Ensure exceptions raised during teardown by a finalizer are suppressed
+ until all finalizers are called, re-raising the first exception (#2440)
+ """
+ testdir.makepyfile("""
+ import pytest
+ values = []
+ def _excepts(where):
+ raise Exception('Error in %s fixture' % where)
+ @pytest.fixture
+ def subrequest(request):
+ return request
+ @pytest.fixture
+ def something(subrequest):
+ subrequest.addfinalizer(lambda: values.append(1))
+ subrequest.addfinalizer(lambda: values.append(2))
+ subrequest.addfinalizer(lambda: _excepts('something'))
+ @pytest.fixture
+ def excepts(subrequest):
+ subrequest.addfinalizer(lambda: _excepts('excepts'))
+ subrequest.addfinalizer(lambda: values.append(3))
+ def test_first(something, excepts):
+ pass
+ def test_second():
+ assert values == [3, 2, 1]
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ '*Exception: Error in excepts fixture',
+ '* 2 passed, 1 error in *',
+ ])
+
+ def test_request_getmodulepath(self, testdir):
+ modcol = testdir.getmodulecol("def test_somefunc(): pass")
+ item, = testdir.genitems([modcol])
+ req = fixtures.FixtureRequest(item)
+ assert req.fspath == modcol.fspath
+
+ def test_request_fixturenames(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ from _pytest.pytester import get_public_names
+ @pytest.fixture()
+ def arg1():
+ pass
+ @pytest.fixture()
+ def farg(arg1):
+ pass
+ @pytest.fixture(autouse=True)
+ def sarg(tmpdir):
+ pass
+ def test_function(request, farg):
+ assert set(get_public_names(request.fixturenames)) == \
+ set(["tmpdir", "sarg", "arg1", "request", "farg",
+ "tmpdir_factory"])
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+ def test_funcargnames_compatattr(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ def pytest_generate_tests(metafunc):
+ assert metafunc.funcargnames == metafunc.fixturenames
+ @pytest.fixture
+ def fn(request):
+ assert request._pyfuncitem.funcargnames == \
+ request._pyfuncitem.fixturenames
+ return request.funcargnames, request.fixturenames
+
+ def test_hello(fn):
+ assert fn[0] == fn[1]
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+ def test_setupdecorator_and_xunit(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ values = []
+ @pytest.fixture(scope='module', autouse=True)
+ def setup_module():
+ values.append("module")
+ @pytest.fixture(autouse=True)
+ def setup_function():
+ values.append("function")
+
+ def test_func():
+ pass
+
+ class TestClass(object):
+ @pytest.fixture(scope="class", autouse=True)
+ def setup_class(self):
+ values.append("class")
+ @pytest.fixture(autouse=True)
+ def setup_method(self):
+ values.append("method")
+ def test_method(self):
+ pass
+ def test_all():
+ assert values == ["module", "function", "class",
+ "function", "method", "function"]
+ """)
+ reprec = testdir.inline_run("-v")
+ reprec.assertoutcome(passed=3)
+
+ def test_fixtures_sub_subdir_normalize_sep(self, testdir):
+ # this tests that normalization of nodeids takes place
+ b = testdir.mkdir("tests").mkdir("unit")
+ b.join("conftest.py").write(_pytest._code.Source("""
+ import pytest
+ @pytest.fixture
+ def arg1():
+ pass
+ """))
+ p = b.join("test_module.py")
+ p.write("def test_func(arg1): pass")
+ result = testdir.runpytest(p, "--fixtures")
+ assert result.ret == 0
+ result.stdout.fnmatch_lines("""
+ *fixtures defined*conftest*
+ *arg1*
+ """)
+
+ def test_show_fixtures_color_yes(self, testdir):
+ testdir.makepyfile("def test_this(): assert 1")
+ result = testdir.runpytest('--color=yes', '--fixtures')
+ assert '\x1b[32mtmpdir' in result.stdout.str()
+
+ def test_newstyle_with_request(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture()
+ def arg(request):
+ pass
+ def test_1(arg):
+ pass
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+ def test_setupcontext_no_param(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture(params=[1,2])
+ def arg(request):
+ return request.param
+
+ @pytest.fixture(autouse=True)
+ def mysetup(request, arg):
+ assert not hasattr(request, "param")
+ def test_1(arg):
+ assert arg in (1,2)
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=2)
+
+
+class TestRequestMarking(object):
+ def test_applymarker(self, testdir):
+ item1, item2 = testdir.getitems("""
+ import pytest
+
+ @pytest.fixture
+ def something(request):
+ pass
+ class TestClass(object):
+ def test_func1(self, something):
+ pass
+ def test_func2(self, something):
+ pass
+ """)
+ req1 = fixtures.FixtureRequest(item1)
+ assert 'xfail' not in item1.keywords
+ req1.applymarker(pytest.mark.xfail)
+ assert 'xfail' in item1.keywords
+ assert 'skipif' not in item1.keywords
+ req1.applymarker(pytest.mark.skipif)
+ assert 'skipif' in item1.keywords
+ pytest.raises(ValueError, "req1.applymarker(42)")
+
+ def test_accesskeywords(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture()
+ def keywords(request):
+ return request.keywords
+ @pytest.mark.XYZ
+ def test_function(keywords):
+ assert keywords["XYZ"]
+ assert "abc" not in keywords
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+ def test_accessmarker_dynamic(self, testdir):
+ testdir.makeconftest("""
+ import pytest
+ @pytest.fixture()
+ def keywords(request):
+ return request.keywords
+
+ @pytest.fixture(scope="class", autouse=True)
+ def marking(request):
+ request.applymarker(pytest.mark.XYZ("hello"))
+ """)
+ testdir.makepyfile("""
+ import pytest
+ def test_fun1(keywords):
+ assert keywords["XYZ"] is not None
+ assert "abc" not in keywords
+ def test_fun2(keywords):
+ assert keywords["XYZ"] is not None
+ assert "abc" not in keywords
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=2)
+
+
+class TestRequestCachedSetup(object):
+ def test_request_cachedsetup_defaultmodule(self, testdir):
+ reprec = testdir.inline_runsource("""
+ mysetup = ["hello",].pop
+
+ import pytest
+
+ @pytest.fixture
+ def something(request):
+ return request.cached_setup(mysetup, scope="module")
+
+ def test_func1(something):
+ assert something == "hello"
+ class TestClass(object):
+ def test_func1a(self, something):
+ assert something == "hello"
+ """)
+ reprec.assertoutcome(passed=2)
+
+ def test_request_cachedsetup_class(self, testdir):
+ reprec = testdir.inline_runsource("""
+ mysetup = ["hello", "hello2", "hello3"].pop
+
+ import pytest
+ @pytest.fixture
+ def something(request):
+ return request.cached_setup(mysetup, scope="class")
+ def test_func1(something):
+ assert something == "hello3"
+ def test_func2(something):
+ assert something == "hello2"
+ class TestClass(object):
+ def test_func1a(self, something):
+ assert something == "hello"
+ def test_func2b(self, something):
+ assert something == "hello"
+ """)
+ reprec.assertoutcome(passed=4)
+
+ def test_request_cachedsetup_extrakey(self, testdir):
+ item1 = testdir.getitem("def test_func(): pass")
+ req1 = fixtures.FixtureRequest(item1)
+ values = ["hello", "world"]
+
+ def setup():
+ return values.pop()
+
+ ret1 = req1.cached_setup(setup, extrakey=1)
+ ret2 = req1.cached_setup(setup, extrakey=2)
+ assert ret2 == "hello"
+ assert ret1 == "world"
+ ret1b = req1.cached_setup(setup, extrakey=1)
+ ret2b = req1.cached_setup(setup, extrakey=2)
+ assert ret1 == ret1b
+ assert ret2 == ret2b
+
+ def test_request_cachedsetup_cache_deletion(self, testdir):
+ item1 = testdir.getitem("def test_func(): pass")
+ req1 = fixtures.FixtureRequest(item1)
+ values = []
+
+ def setup():
+ values.append("setup")
+
+ def teardown(val):
+ values.append("teardown")
+
+ req1.cached_setup(setup, teardown, scope="function")
+ assert values == ['setup']
+ # artificial call of finalizer
+ setupstate = req1._pyfuncitem.session._setupstate
+ setupstate._callfinalizers(item1)
+ assert values == ["setup", "teardown"]
+ req1.cached_setup(setup, teardown, scope="function")
+ assert values == ["setup", "teardown", "setup"]
+ setupstate._callfinalizers(item1)
+ assert values == ["setup", "teardown", "setup", "teardown"]
+
+ def test_request_cached_setup_two_args(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture
+ def arg1(request):
+ return request.cached_setup(lambda: 42)
+ @pytest.fixture
+ def arg2(request):
+ return request.cached_setup(lambda: 17)
+ def test_two_different_setups(arg1, arg2):
+ assert arg1 != arg2
+ """)
+ result = testdir.runpytest("-v")
+ result.stdout.fnmatch_lines([
+ "*1 passed*"
+ ])
+
+ def test_request_cached_setup_getfixturevalue(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture
+ def arg1(request):
+ arg1 = request.getfixturevalue("arg2")
+ return request.cached_setup(lambda: arg1 + 1)
+ @pytest.fixture
+ def arg2(request):
+ return request.cached_setup(lambda: 10)
+ def test_two_funcarg(arg1):
+ assert arg1 == 11
+ """)
+ result = testdir.runpytest("-v")
+ result.stdout.fnmatch_lines([
+ "*1 passed*"
+ ])
+
+ def test_request_cached_setup_functional(self, testdir):
+ testdir.makepyfile(test_0="""
+ import pytest
+ values = []
+ @pytest.fixture
+ def something(request):
+ val = request.cached_setup(fsetup, fteardown)
+ return val
+ def fsetup(mycache=[1]):
+ values.append(mycache.pop())
+ return values
+ def fteardown(something):
+ values.remove(something[0])
+ values.append(2)
+ def test_list_once(something):
+ assert something == [1]
+ def test_list_twice(something):
+ assert something == [1]
+ """)
+ testdir.makepyfile(test_1="""
+ import test_0 # should have run already
+ def test_check_test0_has_teardown_correct():
+ assert test_0.values == [2]
+ """)
+ result = testdir.runpytest("-v")
+ result.stdout.fnmatch_lines([
+ "*3 passed*"
+ ])
+
+ def test_issue117_sessionscopeteardown(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture
+ def app(request):
+ app = request.cached_setup(
+ scope='session',
+ setup=lambda: 0,
+ teardown=lambda x: 3/x)
+ return app
+ def test_func(app):
+ pass
+ """)
+ result = testdir.runpytest()
+ assert result.ret != 0
+ result.stdout.fnmatch_lines([
+ "*3/x*",
+ "*ZeroDivisionError*",
+ ])
+
+
+class TestFixtureUsages(object):
+ def test_noargfixturedec(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture
+ def arg1():
+ return 1
+
+ def test_func(arg1):
+ assert arg1 == 1
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+ def test_receives_funcargs(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture()
+ def arg1():
+ return 1
+
+ @pytest.fixture()
+ def arg2(arg1):
+ return arg1 + 1
+
+ def test_add(arg2):
+ assert arg2 == 2
+ def test_all(arg1, arg2):
+ assert arg1 == 1
+ assert arg2 == 2
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=2)
+
+ def test_receives_funcargs_scope_mismatch(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture(scope="function")
+ def arg1():
+ return 1
+
+ @pytest.fixture(scope="module")
+ def arg2(arg1):
+ return arg1 + 1
+
+ def test_add(arg2):
+ assert arg2 == 2
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*ScopeMismatch*involved factories*",
+ "* def arg2*",
+ "* def arg1*",
+ "*1 error*"
+ ])
+
+ def test_receives_funcargs_scope_mismatch_issue660(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture(scope="function")
+ def arg1():
+ return 1
+
+ @pytest.fixture(scope="module")
+ def arg2(arg1):
+ return arg1 + 1
+
+ def test_add(arg1, arg2):
+ assert arg2 == 2
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*ScopeMismatch*involved factories*",
+ "* def arg2*",
+ "*1 error*"
+ ])
+
+ def test_invalid_scope(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture(scope="functions")
+ def badscope():
+ pass
+
+ def test_nothing(badscope):
+ pass
+ """)
+ result = testdir.runpytest_inprocess()
+ result.stdout.fnmatch_lines(
+ ("*ValueError: fixture badscope from test_invalid_scope.py has an unsupported"
+ " scope value 'functions'")
+ )
+
+ def test_funcarg_parametrized_and_used_twice(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ values = []
+ @pytest.fixture(params=[1,2])
+ def arg1(request):
+ values.append(1)
+ return request.param
+
+ @pytest.fixture()
+ def arg2(arg1):
+ return arg1 + 1
+
+ def test_add(arg1, arg2):
+ assert arg2 == arg1 + 1
+ assert len(values) == arg1
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*2 passed*"
+ ])
+
+ def test_factory_uses_unknown_funcarg_as_dependency_error(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture()
+ def fail(missing):
+ return
+
+ @pytest.fixture()
+ def call_fail(fail):
+ return
+
+ def test_missing(call_fail):
+ pass
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines("""
+ *pytest.fixture()*
+ *def call_fail(fail)*
+ *pytest.fixture()*
+ *def fail*
+ *fixture*'missing'*not found*
+ """)
+
+ def test_factory_setup_as_classes_fails(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ class arg1(object):
+ def __init__(self, request):
+ self.x = 1
+ arg1 = pytest.fixture()(arg1)
+
+ """)
+ reprec = testdir.inline_run()
+ values = reprec.getfailedcollections()
+ assert len(values) == 1
+
+ def test_request_can_be_overridden(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture()
+ def request(request):
+ request.a = 1
+ return request
+ def test_request(request):
+ assert request.a == 1
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+ def test_usefixtures_marker(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ values = []
+
+ @pytest.fixture(scope="class")
+ def myfix(request):
+ request.cls.hello = "world"
+ values.append(1)
+
+ class TestClass(object):
+ def test_one(self):
+ assert self.hello == "world"
+ assert len(values) == 1
+ def test_two(self):
+ assert self.hello == "world"
+ assert len(values) == 1
+ pytest.mark.usefixtures("myfix")(TestClass)
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=2)
+
+ def test_usefixtures_ini(self, testdir):
+ testdir.makeini("""
+ [pytest]
+ usefixtures = myfix
+ """)
+ testdir.makeconftest("""
+ import pytest
+
+ @pytest.fixture(scope="class")
+ def myfix(request):
+ request.cls.hello = "world"
+
+ """)
+ testdir.makepyfile("""
+ class TestClass(object):
+ def test_one(self):
+ assert self.hello == "world"
+ def test_two(self):
+ assert self.hello == "world"
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=2)
+
+ def test_usefixtures_seen_in_showmarkers(self, testdir):
+ result = testdir.runpytest("--markers")
+ result.stdout.fnmatch_lines("""
+ *usefixtures(fixturename1*mark tests*fixtures*
+ """)
+
+ def test_request_instance_issue203(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ class TestClass(object):
+ @pytest.fixture
+ def setup1(self, request):
+ assert self == request.instance
+ self.arg1 = 1
+ def test_hello(self, setup1):
+ assert self.arg1 == 1
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+ def test_fixture_parametrized_with_iterator(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ values = []
+ def f():
+ yield 1
+ yield 2
+ dec = pytest.fixture(scope="module", params=f())
+
+ @dec
+ def arg(request):
+ return request.param
+ @dec
+ def arg2(request):
+ return request.param
+
+ def test_1(arg):
+ values.append(arg)
+ def test_2(arg2):
+ values.append(arg2*10)
+ """)
+ reprec = testdir.inline_run("-v")
+ reprec.assertoutcome(passed=4)
+ values = reprec.getcalls("pytest_runtest_call")[0].item.module.values
+ assert values == [1, 2, 10, 20]
+
+
+class TestFixtureManagerParseFactories(object):
+
+ @pytest.fixture
+ def testdir(self, request):
+ testdir = request.getfixturevalue("testdir")
+ testdir.makeconftest("""
+ import pytest
+
+ @pytest.fixture
+ def hello(request):
+ return "conftest"
+
+ @pytest.fixture
+ def fm(request):
+ return request._fixturemanager
+
+ @pytest.fixture
+ def item(request):
+ return request._pyfuncitem
+ """)
+ return testdir
+
+ def test_parsefactories_evil_objects_issue214(self, testdir):
+ testdir.makepyfile("""
+ class A(object):
+ def __call__(self):
+ pass
+ def __getattr__(self, name):
+ raise RuntimeError()
+ a = A()
+ def test_hello():
+ pass
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1, failed=0)
+
+ def test_parsefactories_conftest(self, testdir):
+ testdir.makepyfile("""
+ def test_hello(item, fm):
+ for name in ("fm", "hello", "item"):
+ faclist = fm.getfixturedefs(name, item.nodeid)
+ assert len(faclist) == 1
+ fac = faclist[0]
+ assert fac.func.__name__ == name
+ """)
+ reprec = testdir.inline_run("-s")
+ reprec.assertoutcome(passed=1)
+
+ def test_parsefactories_conftest_and_module_and_class(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture
+ def hello(request):
+ return "module"
+ class TestClass(object):
+ @pytest.fixture
+ def hello(self, request):
+ return "class"
+ def test_hello(self, item, fm):
+ faclist = fm.getfixturedefs("hello", item.nodeid)
+ print (faclist)
+ assert len(faclist) == 3
+ assert faclist[0].func(item._request) == "conftest"
+ assert faclist[1].func(item._request) == "module"
+ assert faclist[2].func(item._request) == "class"
+ """)
+ reprec = testdir.inline_run("-s")
+ reprec.assertoutcome(passed=1)
+
+ def test_parsefactories_relative_node_ids(self, testdir):
+ # example mostly taken from:
+ # https://mail.python.org/pipermail/pytest-dev/2014-September/002617.html
+ runner = testdir.mkdir("runner")
+ package = testdir.mkdir("package")
+ package.join("conftest.py").write(dedent("""\
+ import pytest
+ @pytest.fixture
+ def one():
+ return 1
+ """))
+ package.join("test_x.py").write(dedent("""\
+ def test_x(one):
+ assert one == 1
+ """))
+ sub = package.mkdir("sub")
+ sub.join("__init__.py").ensure()
+ sub.join("conftest.py").write(dedent("""\
+ import pytest
+ @pytest.fixture
+ def one():
+ return 2
+ """))
+ sub.join("test_y.py").write(dedent("""\
+ def test_x(one):
+ assert one == 2
+ """))
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=2)
+ with runner.as_cwd():
+ reprec = testdir.inline_run("..")
+ reprec.assertoutcome(passed=2)
+
+
+class TestAutouseDiscovery(object):
+
+ @pytest.fixture
+ def testdir(self, testdir):
+ testdir.makeconftest("""
+ import pytest
+ @pytest.fixture(autouse=True)
+ def perfunction(request, tmpdir):
+ pass
+
+ @pytest.fixture()
+ def arg1(tmpdir):
+ pass
+ @pytest.fixture(autouse=True)
+ def perfunction2(arg1):
+ pass
+
+ @pytest.fixture
+ def fm(request):
+ return request._fixturemanager
+
+ @pytest.fixture
+ def item(request):
+ return request._pyfuncitem
+ """)
+ return testdir
+
+ def test_parsefactories_conftest(self, testdir):
+ testdir.makepyfile("""
+ from _pytest.pytester import get_public_names
+ def test_check_setup(item, fm):
+ autousenames = fm._getautousenames(item.nodeid)
+ assert len(get_public_names(autousenames)) == 2
+ assert "perfunction2" in autousenames
+ assert "perfunction" in autousenames
+ """)
+ reprec = testdir.inline_run("-s")
+ reprec.assertoutcome(passed=1)
+
+ def test_two_classes_separated_autouse(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ class TestA(object):
+ values = []
+ @pytest.fixture(autouse=True)
+ def setup1(self):
+ self.values.append(1)
+ def test_setup1(self):
+ assert self.values == [1]
+ class TestB(object):
+ values = []
+ @pytest.fixture(autouse=True)
+ def setup2(self):
+ self.values.append(1)
+ def test_setup2(self):
+ assert self.values == [1]
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=2)
+
+ def test_setup_at_classlevel(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ class TestClass(object):
+ @pytest.fixture(autouse=True)
+ def permethod(self, request):
+ request.instance.funcname = request.function.__name__
+ def test_method1(self):
+ assert self.funcname == "test_method1"
+ def test_method2(self):
+ assert self.funcname == "test_method2"
+ """)
+ reprec = testdir.inline_run("-s")
+ reprec.assertoutcome(passed=2)
+
+ @pytest.mark.xfail(reason="'enabled' feature not implemented")
+ def test_setup_enabled_functionnode(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ def enabled(parentnode, markers):
+ return "needsdb" in markers
+
+ @pytest.fixture(params=[1,2])
+ def db(request):
+ return request.param
+
+ @pytest.fixture(enabled=enabled, autouse=True)
+ def createdb(db):
+ pass
+
+ def test_func1(request):
+ assert "db" not in request.fixturenames
+
+ @pytest.mark.needsdb
+ def test_func2(request):
+ assert "db" in request.fixturenames
+ """)
+ reprec = testdir.inline_run("-s")
+ reprec.assertoutcome(passed=2)
+
+ def test_callables_nocode(self, testdir):
+ """
+ a imported mock.call would break setup/factory discovery
+ due to it being callable and __code__ not being a code object
+ """
+ testdir.makepyfile("""
+ class _call(tuple):
+ def __call__(self, *k, **kw):
+ pass
+ def __getattr__(self, k):
+ return self
+
+ call = _call()
+ """)
+ reprec = testdir.inline_run("-s")
+ reprec.assertoutcome(failed=0, passed=0)
+
+ def test_autouse_in_conftests(self, testdir):
+ a = testdir.mkdir("a")
+ b = testdir.mkdir("a1")
+ conftest = testdir.makeconftest("""
+ import pytest
+ @pytest.fixture(autouse=True)
+ def hello():
+ xxx
+ """)
+ conftest.move(a.join(conftest.basename))
+ a.join("test_something.py").write("def test_func(): pass")
+ b.join("test_otherthing.py").write("def test_func(): pass")
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines("""
+ *1 passed*1 error*
+ """)
+
+ def test_autouse_in_module_and_two_classes(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ values = []
+ @pytest.fixture(autouse=True)
+ def append1():
+ values.append("module")
+ def test_x():
+ assert values == ["module"]
+
+ class TestA(object):
+ @pytest.fixture(autouse=True)
+ def append2(self):
+ values.append("A")
+ def test_hello(self):
+ assert values == ["module", "module", "A"], values
+ class TestA2(object):
+ def test_world(self):
+ assert values == ["module", "module", "A", "module"], values
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=3)
+
+
+class TestAutouseManagement(object):
+ def test_autouse_conftest_mid_directory(self, testdir):
+ pkgdir = testdir.mkpydir("xyz123")
+ pkgdir.join("conftest.py").write(_pytest._code.Source("""
+ import pytest
+ @pytest.fixture(autouse=True)
+ def app():
+ import sys
+ sys._myapp = "hello"
+ """))
+ t = pkgdir.ensure("tests", "test_app.py")
+ t.write(_pytest._code.Source("""
+ import sys
+ def test_app():
+ assert sys._myapp == "hello"
+ """))
+ reprec = testdir.inline_run("-s")
+ reprec.assertoutcome(passed=1)
+
+ def test_autouse_honored_for_yield(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture(autouse=True)
+ def tst():
+ global x
+ x = 3
+ def test_gen():
+ def f(hello):
+ assert x == abs(hello)
+ yield f, 3
+ yield f, -3
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=2)
+
+ def test_funcarg_and_setup(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ values = []
+ @pytest.fixture(scope="module")
+ def arg():
+ values.append(1)
+ return 0
+ @pytest.fixture(scope="module", autouse=True)
+ def something(arg):
+ values.append(2)
+
+ def test_hello(arg):
+ assert len(values) == 2
+ assert values == [1,2]
+ assert arg == 0
+
+ def test_hello2(arg):
+ assert len(values) == 2
+ assert values == [1,2]
+ assert arg == 0
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=2)
+
+ def test_uses_parametrized_resource(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ values = []
+ @pytest.fixture(params=[1,2])
+ def arg(request):
+ return request.param
+
+ @pytest.fixture(autouse=True)
+ def something(arg):
+ values.append(arg)
+
+ def test_hello():
+ if len(values) == 1:
+ assert values == [1]
+ elif len(values) == 2:
+ assert values == [1, 2]
+ else:
+ 0/0
+
+ """)
+ reprec = testdir.inline_run("-s")
+ reprec.assertoutcome(passed=2)
+
+ def test_session_parametrized_function(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ values = []
+
+ @pytest.fixture(scope="session", params=[1,2])
+ def arg(request):
+ return request.param
+
+ @pytest.fixture(scope="function", autouse=True)
+ def append(request, arg):
+ if request.function.__name__ == "test_some":
+ values.append(arg)
+
+ def test_some():
+ pass
+
+ def test_result(arg):
+ assert len(values) == arg
+ assert values[:arg] == [1,2][:arg]
+ """)
+ reprec = testdir.inline_run("-v", "-s")
+ reprec.assertoutcome(passed=4)
+
+ def test_class_function_parametrization_finalization(self, testdir):
+ p = testdir.makeconftest("""
+ import pytest
+ import pprint
+
+ values = []
+
+ @pytest.fixture(scope="function", params=[1,2])
+ def farg(request):
+ return request.param
+
+ @pytest.fixture(scope="class", params=list("ab"))
+ def carg(request):
+ return request.param
+
+ @pytest.fixture(scope="function", autouse=True)
+ def append(request, farg, carg):
+ def fin():
+ values.append("fin_%s%s" % (carg, farg))
+ request.addfinalizer(fin)
+ """)
+ testdir.makepyfile("""
+ import pytest
+
+ class TestClass(object):
+ def test_1(self):
+ pass
+ class TestClass2(object):
+ def test_2(self):
+ pass
+ """)
+ confcut = "--confcutdir={0}".format(testdir.tmpdir)
+ reprec = testdir.inline_run("-v", "-s", confcut)
+ reprec.assertoutcome(passed=8)
+ config = reprec.getcalls("pytest_unconfigure")[0].config
+ values = config.pluginmanager._getconftestmodules(p)[0].values
+ assert values == ["fin_a1", "fin_a2", "fin_b1", "fin_b2"] * 2
+
+ def test_scope_ordering(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ values = []
+ @pytest.fixture(scope="function", autouse=True)
+ def fappend2():
+ values.append(2)
+ @pytest.fixture(scope="class", autouse=True)
+ def classappend3():
+ values.append(3)
+ @pytest.fixture(scope="module", autouse=True)
+ def mappend():
+ values.append(1)
+
+ class TestHallo(object):
+ def test_method(self):
+ assert values == [1,3,2]
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+ def test_parametrization_setup_teardown_ordering(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ values = []
+ def pytest_generate_tests(metafunc):
+ if metafunc.cls is not None:
+ metafunc.parametrize("item", [1,2], scope="class")
+ class TestClass(object):
+ @pytest.fixture(scope="class", autouse=True)
+ def addteardown(self, item, request):
+ values.append("setup-%d" % item)
+ request.addfinalizer(lambda: values.append("teardown-%d" % item))
+ def test_step1(self, item):
+ values.append("step1-%d" % item)
+ def test_step2(self, item):
+ values.append("step2-%d" % item)
+
+ def test_finish():
+ print (values)
+ assert values == ["setup-1", "step1-1", "step2-1", "teardown-1",
+ "setup-2", "step1-2", "step2-2", "teardown-2",]
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=5)
+
+ def test_ordering_autouse_before_explicit(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ values = []
+ @pytest.fixture(autouse=True)
+ def fix1():
+ values.append(1)
+ @pytest.fixture()
+ def arg1():
+ values.append(2)
+ def test_hello(arg1):
+ assert values == [1,2]
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+ @pytest.mark.issue226
+ @pytest.mark.parametrize("param1", ["", "params=[1]"], ids=["p00", "p01"])
+ @pytest.mark.parametrize("param2", ["", "params=[1]"], ids=["p10", "p11"])
+ def test_ordering_dependencies_torndown_first(self, testdir, param1, param2):
+ testdir.makepyfile("""
+ import pytest
+ values = []
+ @pytest.fixture(%(param1)s)
+ def arg1(request):
+ request.addfinalizer(lambda: values.append("fin1"))
+ values.append("new1")
+ @pytest.fixture(%(param2)s)
+ def arg2(request, arg1):
+ request.addfinalizer(lambda: values.append("fin2"))
+ values.append("new2")
+
+ def test_arg(arg2):
+ pass
+ def test_check():
+ assert values == ["new1", "new2", "fin2", "fin1"]
+ """ % locals())
+ reprec = testdir.inline_run("-s")
+ reprec.assertoutcome(passed=2)
+
+
+class TestFixtureMarker(object):
+ def test_parametrize(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture(params=["a", "b", "c"])
+ def arg(request):
+ return request.param
+ values = []
+ def test_param(arg):
+ values.append(arg)
+ def test_result():
+ assert values == list("abc")
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=4)
+
+ def test_multiple_parametrization_issue_736(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture(params=[1,2,3])
+ def foo(request):
+ return request.param
+
+ @pytest.mark.parametrize('foobar', [4,5,6])
+ def test_issue(foo, foobar):
+ assert foo in [1,2,3]
+ assert foobar in [4,5,6]
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=9)
+
+ @pytest.mark.parametrize('param_args', ["'fixt, val'", "'fixt,val'", "['fixt', 'val']", "('fixt', 'val')"])
+ def test_override_parametrized_fixture_issue_979(self, testdir, param_args):
+ """Make sure a parametrized argument can override a parametrized fixture.
+
+ This was a regression introduced in the fix for #736.
+ """
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture(params=[1, 2])
+ def fixt(request):
+ return request.param
+
+ @pytest.mark.parametrize(%s, [(3, 'x'), (4, 'x')])
+ def test_foo(fixt, val):
+ pass
+ """ % param_args)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=2)
+
+ def test_scope_session(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ values = []
+ @pytest.fixture(scope="module")
+ def arg():
+ values.append(1)
+ return 1
+
+ def test_1(arg):
+ assert arg == 1
+ def test_2(arg):
+ assert arg == 1
+ assert len(values) == 1
+ class TestClass(object):
+ def test3(self, arg):
+ assert arg == 1
+ assert len(values) == 1
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=3)
+
+ def test_scope_session_exc(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ values = []
+ @pytest.fixture(scope="session")
+ def fix():
+ values.append(1)
+ pytest.skip('skipping')
+
+ def test_1(fix):
+ pass
+ def test_2(fix):
+ pass
+ def test_last():
+ assert values == [1]
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(skipped=2, passed=1)
+
+ def test_scope_session_exc_two_fix(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ values = []
+ m = []
+ @pytest.fixture(scope="session")
+ def a():
+ values.append(1)
+ pytest.skip('skipping')
+ @pytest.fixture(scope="session")
+ def b(a):
+ m.append(1)
+
+ def test_1(b):
+ pass
+ def test_2(b):
+ pass
+ def test_last():
+ assert values == [1]
+ assert m == []
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(skipped=2, passed=1)
+
+ def test_scope_exc(self, testdir):
+ testdir.makepyfile(
+ test_foo="""
+ def test_foo(fix):
+ pass
+ """,
+ test_bar="""
+ def test_bar(fix):
+ pass
+ """,
+ conftest="""
+ import pytest
+ reqs = []
+ @pytest.fixture(scope="session")
+ def fix(request):
+ reqs.append(1)
+ pytest.skip()
+ @pytest.fixture
+ def req_list():
+ return reqs
+ """,
+ test_real="""
+ def test_last(req_list):
+ assert req_list == [1]
+ """
+ )
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(skipped=2, passed=1)
+
+ def test_scope_module_uses_session(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ values = []
+ @pytest.fixture(scope="module")
+ def arg():
+ values.append(1)
+ return 1
+
+ def test_1(arg):
+ assert arg == 1
+ def test_2(arg):
+ assert arg == 1
+ assert len(values) == 1
+ class TestClass(object):
+ def test3(self, arg):
+ assert arg == 1
+ assert len(values) == 1
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=3)
+
+ def test_scope_module_and_finalizer(self, testdir):
+ testdir.makeconftest("""
+ import pytest
+ finalized_list = []
+ created_list = []
+ @pytest.fixture(scope="module")
+ def arg(request):
+ created_list.append(1)
+ assert request.scope == "module"
+ request.addfinalizer(lambda: finalized_list.append(1))
+ @pytest.fixture
+ def created(request):
+ return len(created_list)
+ @pytest.fixture
+ def finalized(request):
+ return len(finalized_list)
+ """)
+ testdir.makepyfile(
+ test_mod1="""
+ def test_1(arg, created, finalized):
+ assert created == 1
+ assert finalized == 0
+ def test_2(arg, created, finalized):
+ assert created == 1
+ assert finalized == 0""",
+ test_mod2="""
+ def test_3(arg, created, finalized):
+ assert created == 2
+ assert finalized == 1""",
+ test_mode3="""
+ def test_4(arg, created, finalized):
+ assert created == 3
+ assert finalized == 2
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=4)
+
+ @pytest.mark.parametrize("method", [
+ 'request.getfixturevalue("arg")',
+ 'request.cached_setup(lambda: None, scope="function")',
+ ], ids=["getfixturevalue", "cached_setup"])
+ def test_scope_mismatch_various(self, testdir, method):
+ testdir.makeconftest("""
+ import pytest
+ finalized = []
+ created = []
+ @pytest.fixture(scope="function")
+ def arg(request):
+ pass
+ """)
+ testdir.makepyfile(
+ test_mod1="""
+ import pytest
+ @pytest.fixture(scope="session")
+ def arg(request):
+ %s
+ def test_1(arg):
+ pass
+ """ % method)
+ result = testdir.runpytest()
+ assert result.ret != 0
+ result.stdout.fnmatch_lines([
+ "*ScopeMismatch*You tried*function*session*request*",
+ ])
+
+ def test_register_only_with_mark(self, testdir):
+ testdir.makeconftest("""
+ import pytest
+ @pytest.fixture()
+ def arg():
+ return 1
+ """)
+ testdir.makepyfile(
+ test_mod1="""
+ import pytest
+ @pytest.fixture()
+ def arg(arg):
+ return arg + 1
+ def test_1(arg):
+ assert arg == 2
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+ def test_parametrize_and_scope(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture(scope="module", params=["a", "b", "c"])
+ def arg(request):
+ return request.param
+ values = []
+ def test_param(arg):
+ values.append(arg)
+ """)
+ reprec = testdir.inline_run("-v")
+ reprec.assertoutcome(passed=3)
+ values = reprec.getcalls("pytest_runtest_call")[0].item.module.values
+ assert len(values) == 3
+ assert "a" in values
+ assert "b" in values
+ assert "c" in values
+
+ def test_scope_mismatch(self, testdir):
+ testdir.makeconftest("""
+ import pytest
+ @pytest.fixture(scope="function")
+ def arg(request):
+ pass
+ """)
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture(scope="session")
+ def arg(arg):
+ pass
+ def test_mismatch(arg):
+ pass
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*ScopeMismatch*",
+ "*1 error*",
+ ])
+
+ def test_parametrize_separated_order(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture(scope="module", params=[1, 2])
+ def arg(request):
+ return request.param
+
+ values = []
+ def test_1(arg):
+ values.append(arg)
+ def test_2(arg):
+ values.append(arg)
+ """)
+ reprec = testdir.inline_run("-v")
+ reprec.assertoutcome(passed=4)
+ values = reprec.getcalls("pytest_runtest_call")[0].item.module.values
+ assert values == [1, 1, 2, 2]
+
+ def test_module_parametrized_ordering(self, testdir):
+ testdir.makeini("""
+ [pytest]
+ console_output_style=classic
+ """)
+ testdir.makeconftest("""
+ import pytest
+
+ @pytest.fixture(scope="session", params="s1 s2".split())
+ def sarg():
+ pass
+ @pytest.fixture(scope="module", params="m1 m2".split())
+ def marg():
+ pass
+ """)
+ testdir.makepyfile(test_mod1="""
+ def test_func(sarg):
+ pass
+ def test_func1(marg):
+ pass
+ """, test_mod2="""
+ def test_func2(sarg):
+ pass
+ def test_func3(sarg, marg):
+ pass
+ def test_func3b(sarg, marg):
+ pass
+ def test_func4(marg):
+ pass
+ """)
+ result = testdir.runpytest("-v")
+ result.stdout.fnmatch_lines("""
+ test_mod1.py::test_func[s1] PASSED
+ test_mod2.py::test_func2[s1] PASSED
+ test_mod2.py::test_func3[s1-m1] PASSED
+ test_mod2.py::test_func3b[s1-m1] PASSED
+ test_mod2.py::test_func3[s1-m2] PASSED
+ test_mod2.py::test_func3b[s1-m2] PASSED
+ test_mod1.py::test_func[s2] PASSED
+ test_mod2.py::test_func2[s2] PASSED
+ test_mod2.py::test_func3[s2-m1] PASSED
+ test_mod2.py::test_func3b[s2-m1] PASSED
+ test_mod2.py::test_func4[m1] PASSED
+ test_mod2.py::test_func3[s2-m2] PASSED
+ test_mod2.py::test_func3b[s2-m2] PASSED
+ test_mod2.py::test_func4[m2] PASSED
+ test_mod1.py::test_func1[m1] PASSED
+ test_mod1.py::test_func1[m2] PASSED
+ """)
+
+ def test_class_ordering(self, testdir):
+ testdir.makeini("""
+ [pytest]
+ console_output_style=classic
+ """)
+ testdir.makeconftest("""
+ import pytest
+
+ values = []
+
+ @pytest.fixture(scope="function", params=[1,2])
+ def farg(request):
+ return request.param
+
+ @pytest.fixture(scope="class", params=list("ab"))
+ def carg(request):
+ return request.param
+
+ @pytest.fixture(scope="function", autouse=True)
+ def append(request, farg, carg):
+ def fin():
+ values.append("fin_%s%s" % (carg, farg))
+ request.addfinalizer(fin)
+ """)
+ testdir.makepyfile("""
+ import pytest
+
+ class TestClass2(object):
+ def test_1(self):
+ pass
+ def test_2(self):
+ pass
+ class TestClass(object):
+ def test_3(self):
+ pass
+ """)
+ result = testdir.runpytest("-vs")
+ result.stdout.fnmatch_lines("""
+ test_class_ordering.py::TestClass2::test_1[1-a] PASSED
+ test_class_ordering.py::TestClass2::test_1[2-a] PASSED
+ test_class_ordering.py::TestClass2::test_2[1-a] PASSED
+ test_class_ordering.py::TestClass2::test_2[2-a] PASSED
+ test_class_ordering.py::TestClass2::test_1[1-b] PASSED
+ test_class_ordering.py::TestClass2::test_1[2-b] PASSED
+ test_class_ordering.py::TestClass2::test_2[1-b] PASSED
+ test_class_ordering.py::TestClass2::test_2[2-b] PASSED
+ test_class_ordering.py::TestClass::test_3[1-a] PASSED
+ test_class_ordering.py::TestClass::test_3[2-a] PASSED
+ test_class_ordering.py::TestClass::test_3[1-b] PASSED
+ test_class_ordering.py::TestClass::test_3[2-b] PASSED
+ """)
+
+ def test_parametrize_separated_order_higher_scope_first(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture(scope="function", params=[1, 2])
+ def arg(request):
+ param = request.param
+ request.addfinalizer(lambda: values.append("fin:%s" % param))
+ values.append("create:%s" % param)
+ return request.param
+
+ @pytest.fixture(scope="module", params=["mod1", "mod2"])
+ def modarg(request):
+ param = request.param
+ request.addfinalizer(lambda: values.append("fin:%s" % param))
+ values.append("create:%s" % param)
+ return request.param
+
+ values = []
+ def test_1(arg):
+ values.append("test1")
+ def test_2(modarg):
+ values.append("test2")
+ def test_3(arg, modarg):
+ values.append("test3")
+ def test_4(modarg, arg):
+ values.append("test4")
+ """)
+ reprec = testdir.inline_run("-v")
+ reprec.assertoutcome(passed=12)
+ values = reprec.getcalls("pytest_runtest_call")[0].item.module.values
+ expected = [
+ 'create:1', 'test1', 'fin:1', 'create:2', 'test1',
+ 'fin:2', 'create:mod1', 'test2', 'create:1', 'test3',
+ 'fin:1', 'create:2', 'test3', 'fin:2', 'create:1',
+ 'test4', 'fin:1', 'create:2', 'test4', 'fin:2',
+ 'fin:mod1', 'create:mod2', 'test2', 'create:1', 'test3',
+ 'fin:1', 'create:2', 'test3', 'fin:2', 'create:1',
+ 'test4', 'fin:1', 'create:2', 'test4', 'fin:2',
+ 'fin:mod2']
+ import pprint
+ pprint.pprint(list(zip(values, expected)))
+ assert values == expected
+
+ def test_parametrized_fixture_teardown_order(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture(params=[1,2], scope="class")
+ def param1(request):
+ return request.param
+
+ values = []
+
+ class TestClass(object):
+ @classmethod
+ @pytest.fixture(scope="class", autouse=True)
+ def setup1(self, request, param1):
+ values.append(1)
+ request.addfinalizer(self.teardown1)
+ @classmethod
+ def teardown1(self):
+ assert values.pop() == 1
+ @pytest.fixture(scope="class", autouse=True)
+ def setup2(self, request, param1):
+ values.append(2)
+ request.addfinalizer(self.teardown2)
+ @classmethod
+ def teardown2(self):
+ assert values.pop() == 2
+ def test(self):
+ pass
+
+ def test_finish():
+ assert not values
+ """)
+ result = testdir.runpytest("-v")
+ result.stdout.fnmatch_lines("""
+ *3 passed*
+ """)
+ assert "error" not in result.stdout.str()
+
+ def test_fixture_finalizer(self, testdir):
+ testdir.makeconftest("""
+ import pytest
+ import sys
+
+ @pytest.fixture
+ def browser(request):
+
+ def finalize():
+ sys.stdout.write('Finalized')
+ request.addfinalizer(finalize)
+ return {}
+ """)
+ b = testdir.mkdir("subdir")
+ b.join("test_overridden_fixture_finalizer.py").write(dedent("""
+ import pytest
+ @pytest.fixture
+ def browser(browser):
+ browser['visited'] = True
+ return browser
+
+ def test_browser(browser):
+ assert browser['visited'] is True
+ """))
+ reprec = testdir.runpytest("-s")
+ for test in ['test_browser']:
+ reprec.stdout.fnmatch_lines('*Finalized*')
+
+ def test_class_scope_with_normal_tests(self, testdir):
+ testpath = testdir.makepyfile("""
+ import pytest
+
+ class Box(object):
+ value = 0
+
+ @pytest.fixture(scope='class')
+ def a(request):
+ Box.value += 1
+ return Box.value
+
+ def test_a(a):
+ assert a == 1
+
+ class Test1(object):
+ def test_b(self, a):
+ assert a == 2
+
+ class Test2(object):
+ def test_c(self, a):
+ assert a == 3""")
+ reprec = testdir.inline_run(testpath)
+ for test in ['test_a', 'test_b', 'test_c']:
+ assert reprec.matchreport(test).passed
+
+ def test_request_is_clean(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ values = []
+ @pytest.fixture(params=[1, 2])
+ def fix(request):
+ request.addfinalizer(lambda: values.append(request.param))
+ def test_fix(fix):
+ pass
+ """)
+ reprec = testdir.inline_run("-s")
+ values = reprec.getcalls("pytest_runtest_call")[0].item.module.values
+ assert values == [1, 2]
+
+ def test_parametrize_separated_lifecycle(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ values = []
+ @pytest.fixture(scope="module", params=[1, 2])
+ def arg(request):
+ x = request.param
+ request.addfinalizer(lambda: values.append("fin%s" % x))
+ return request.param
+ def test_1(arg):
+ values.append(arg)
+ def test_2(arg):
+ values.append(arg)
+ """)
+ reprec = testdir.inline_run("-vs")
+ reprec.assertoutcome(passed=4)
+ values = reprec.getcalls("pytest_runtest_call")[0].item.module.values
+ import pprint
+ pprint.pprint(values)
+ # assert len(values) == 6
+ assert values[0] == values[1] == 1
+ assert values[2] == "fin1"
+ assert values[3] == values[4] == 2
+ assert values[5] == "fin2"
+
+ def test_parametrize_function_scoped_finalizers_called(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture(scope="function", params=[1, 2])
+ def arg(request):
+ x = request.param
+ request.addfinalizer(lambda: values.append("fin%s" % x))
+ return request.param
+
+ values = []
+ def test_1(arg):
+ values.append(arg)
+ def test_2(arg):
+ values.append(arg)
+ def test_3():
+ assert len(values) == 8
+ assert values == [1, "fin1", 2, "fin2", 1, "fin1", 2, "fin2"]
+ """)
+ reprec = testdir.inline_run("-v")
+ reprec.assertoutcome(passed=5)
+
+ @pytest.mark.issue246
+ @pytest.mark.parametrize("scope", ["session", "function", "module"])
+ def test_finalizer_order_on_parametrization(self, scope, testdir):
+ testdir.makepyfile("""
+ import pytest
+ values = []
+
+ @pytest.fixture(scope=%(scope)r, params=["1"])
+ def fix1(request):
+ return request.param
+
+ @pytest.fixture(scope=%(scope)r)
+ def fix2(request, base):
+ def cleanup_fix2():
+ assert not values, "base should not have been finalized"
+ request.addfinalizer(cleanup_fix2)
+
+ @pytest.fixture(scope=%(scope)r)
+ def base(request, fix1):
+ def cleanup_base():
+ values.append("fin_base")
+ print ("finalizing base")
+ request.addfinalizer(cleanup_base)
+
+ def test_begin():
+ pass
+ def test_baz(base, fix2):
+ pass
+ def test_other():
+ pass
+ """ % {"scope": scope})
+ reprec = testdir.inline_run("-lvs")
+ reprec.assertoutcome(passed=3)
+
+ @pytest.mark.issue396
+ def test_class_scope_parametrization_ordering(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ values = []
+ @pytest.fixture(params=["John", "Doe"], scope="class")
+ def human(request):
+ request.addfinalizer(lambda: values.append("fin %s" % request.param))
+ return request.param
+
+ class TestGreetings(object):
+ def test_hello(self, human):
+ values.append("test_hello")
+
+ class TestMetrics(object):
+ def test_name(self, human):
+ values.append("test_name")
+
+ def test_population(self, human):
+ values.append("test_population")
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=6)
+ values = reprec.getcalls("pytest_runtest_call")[0].item.module.values
+ assert values == ["test_hello", "fin John", "test_hello", "fin Doe",
+ "test_name", "test_population", "fin John",
+ "test_name", "test_population", "fin Doe"]
+
+ def test_parametrize_setup_function(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture(scope="module", params=[1, 2])
+ def arg(request):
+ return request.param
+
+ @pytest.fixture(scope="module", autouse=True)
+ def mysetup(request, arg):
+ request.addfinalizer(lambda: values.append("fin%s" % arg))
+ values.append("setup%s" % arg)
+
+ values = []
+ def test_1(arg):
+ values.append(arg)
+ def test_2(arg):
+ values.append(arg)
+ def test_3():
+ import pprint
+ pprint.pprint(values)
+ if arg == 1:
+ assert values == ["setup1", 1, 1, ]
+ elif arg == 2:
+ assert values == ["setup1", 1, 1, "fin1",
+ "setup2", 2, 2, ]
+
+ """)
+ reprec = testdir.inline_run("-v")
+ reprec.assertoutcome(passed=6)
+
+ def test_fixture_marked_function_not_collected_as_test(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture
+ def test_app():
+ return 1
+
+ def test_something(test_app):
+ assert test_app == 1
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+ def test_params_and_ids(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture(params=[object(), object()],
+ ids=['alpha', 'beta'])
+ def fix(request):
+ return request.param
+
+ def test_foo(fix):
+ assert 1
+ """)
+ res = testdir.runpytest('-v')
+ res.stdout.fnmatch_lines([
+ '*test_foo*alpha*',
+ '*test_foo*beta*'])
+
+ def test_params_and_ids_yieldfixture(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.yield_fixture(params=[object(), object()],
+ ids=['alpha', 'beta'])
+ def fix(request):
+ yield request.param
+
+ def test_foo(fix):
+ assert 1
+ """)
+ res = testdir.runpytest('-v')
+ res.stdout.fnmatch_lines([
+ '*test_foo*alpha*',
+ '*test_foo*beta*'])
+
+ @pytest.mark.issue920
+ def test_deterministic_fixture_collection(self, testdir, monkeypatch):
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture(scope="module",
+ params=["A",
+ "B",
+ "C"])
+ def A(request):
+ return request.param
+
+ @pytest.fixture(scope="module",
+ params=["DDDDDDDDD", "EEEEEEEEEEEE", "FFFFFFFFFFF", "banansda"])
+ def B(request, A):
+ return request.param
+
+ def test_foo(B):
+ # Something funky is going on here.
+ # Despite specified seeds, on what is collected,
+ # sometimes we get unexpected passes. hashing B seems
+ # to help?
+ assert hash(B) or True
+ """)
+ monkeypatch.setenv("PYTHONHASHSEED", "1")
+ out1 = testdir.runpytest_subprocess("-v")
+ monkeypatch.setenv("PYTHONHASHSEED", "2")
+ out2 = testdir.runpytest_subprocess("-v")
+ out1 = [line for line in out1.outlines if line.startswith("test_deterministic_fixture_collection.py::test_foo")]
+ out2 = [line for line in out2.outlines if line.startswith("test_deterministic_fixture_collection.py::test_foo")]
+ assert len(out1) == 12
+ assert out1 == out2
+
+
+class TestRequestScopeAccess(object):
+ pytestmark = pytest.mark.parametrize(("scope", "ok", "error"), [
+ ["session", "", "fspath class function module"],
+ ["module", "module fspath", "cls function"],
+ ["class", "module fspath cls", "function"],
+ ["function", "module fspath cls function", ""]
+ ])
+
+ def test_setup(self, testdir, scope, ok, error):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture(scope=%r, autouse=True)
+ def myscoped(request):
+ for x in %r:
+ assert hasattr(request, x)
+ for x in %r:
+ pytest.raises(AttributeError, lambda:
+ getattr(request, x))
+ assert request.session
+ assert request.config
+ def test_func():
+ pass
+ """ % (scope, ok.split(), error.split()))
+ reprec = testdir.inline_run("-l")
+ reprec.assertoutcome(passed=1)
+
+ def test_funcarg(self, testdir, scope, ok, error):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture(scope=%r)
+ def arg(request):
+ for x in %r:
+ assert hasattr(request, x)
+ for x in %r:
+ pytest.raises(AttributeError, lambda:
+ getattr(request, x))
+ assert request.session
+ assert request.config
+ def test_func(arg):
+ pass
+ """ % (scope, ok.split(), error.split()))
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+
+class TestErrors(object):
+ def test_subfactory_missing_funcarg(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture()
+ def gen(qwe123):
+ return 1
+ def test_something(gen):
+ pass
+ """)
+ result = testdir.runpytest()
+ assert result.ret != 0
+ result.stdout.fnmatch_lines([
+ "*def gen(qwe123):*",
+ "*fixture*qwe123*not found*",
+ "*1 error*",
+ ])
+
+ def test_issue498_fixture_finalizer_failing(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture
+ def fix1(request):
+ def f():
+ raise KeyError
+ request.addfinalizer(f)
+ return object()
+
+ values = []
+ def test_1(fix1):
+ values.append(fix1)
+ def test_2(fix1):
+ values.append(fix1)
+ def test_3():
+ assert values[0] != values[1]
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines("""
+ *ERROR*teardown*test_1*
+ *KeyError*
+ *ERROR*teardown*test_2*
+ *KeyError*
+ *3 pass*2 error*
+ """)
+
+ def test_setupfunc_missing_funcarg(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture(autouse=True)
+ def gen(qwe123):
+ return 1
+ def test_something():
+ pass
+ """)
+ result = testdir.runpytest()
+ assert result.ret != 0
+ result.stdout.fnmatch_lines([
+ "*def gen(qwe123):*",
+ "*fixture*qwe123*not found*",
+ "*1 error*",
+ ])
+
+
+class TestShowFixtures(object):
+ def test_funcarg_compat(self, testdir):
+ config = testdir.parseconfigure("--funcargs")
+ assert config.option.showfixtures
+
+ def test_show_fixtures(self, testdir):
+ result = testdir.runpytest("--fixtures")
+ result.stdout.fnmatch_lines([
+ "*tmpdir*",
+ "*temporary directory*",
+ ])
+
+ def test_show_fixtures_verbose(self, testdir):
+ result = testdir.runpytest("--fixtures", "-v")
+ result.stdout.fnmatch_lines([
+ "*tmpdir*--*tmpdir.py*",
+ "*temporary directory*",
+ ])
+
+ def test_show_fixtures_testmodule(self, testdir):
+ p = testdir.makepyfile('''
+ import pytest
+ @pytest.fixture
+ def _arg0():
+ """ hidden """
+ @pytest.fixture
+ def arg1():
+ """ hello world """
+ ''')
+ result = testdir.runpytest("--fixtures", p)
+ result.stdout.fnmatch_lines("""
+ *tmpdir
+ *fixtures defined from*
+ *arg1*
+ *hello world*
+ """)
+ assert "arg0" not in result.stdout.str()
+
+ @pytest.mark.parametrize("testmod", [True, False])
+ def test_show_fixtures_conftest(self, testdir, testmod):
+ testdir.makeconftest('''
+ import pytest
+ @pytest.fixture
+ def arg1():
+ """ hello world """
+ ''')
+ if testmod:
+ testdir.makepyfile("""
+ def test_hello():
+ pass
+ """)
+ result = testdir.runpytest("--fixtures")
+ result.stdout.fnmatch_lines("""
+ *tmpdir*
+ *fixtures defined from*conftest*
+ *arg1*
+ *hello world*
+ """)
+
+ def test_show_fixtures_trimmed_doc(self, testdir):
+ p = testdir.makepyfile(dedent('''
+ import pytest
+ @pytest.fixture
+ def arg1():
+ """
+ line1
+ line2
+
+ """
+ @pytest.fixture
+ def arg2():
+ """
+ line1
+ line2
+
+ """
+ '''))
+ result = testdir.runpytest("--fixtures", p)
+ result.stdout.fnmatch_lines(dedent("""
+ * fixtures defined from test_show_fixtures_trimmed_doc *
+ arg2
+ line1
+ line2
+ arg1
+ line1
+ line2
+
+ """))
+
+ def test_show_fixtures_indented_doc(self, testdir):
+ p = testdir.makepyfile(dedent('''
+ import pytest
+ @pytest.fixture
+ def fixture1():
+ """
+ line1
+ indented line
+ """
+ '''))
+ result = testdir.runpytest("--fixtures", p)
+ result.stdout.fnmatch_lines(dedent("""
+ * fixtures defined from test_show_fixtures_indented_doc *
+ fixture1
+ line1
+ indented line
+ """))
+
+ def test_show_fixtures_indented_doc_first_line_unindented(self, testdir):
+ p = testdir.makepyfile(dedent('''
+ import pytest
+ @pytest.fixture
+ def fixture1():
+ """line1
+ line2
+ indented line
+ """
+ '''))
+ result = testdir.runpytest("--fixtures", p)
+ result.stdout.fnmatch_lines(dedent("""
+ * fixtures defined from test_show_fixtures_indented_doc_first_line_unindented *
+ fixture1
+ line1
+ line2
+ indented line
+ """))
+
+ def test_show_fixtures_indented_in_class(self, testdir):
+ p = testdir.makepyfile(dedent('''
+ import pytest
+ class TestClass:
+ @pytest.fixture
+ def fixture1(self):
+ """line1
+ line2
+ indented line
+ """
+ '''))
+ result = testdir.runpytest("--fixtures", p)
+ result.stdout.fnmatch_lines(dedent("""
+ * fixtures defined from test_show_fixtures_indented_in_class *
+ fixture1
+ line1
+ line2
+ indented line
+ """))
+
+ def test_show_fixtures_different_files(self, testdir):
+ """
+ #833: --fixtures only shows fixtures from first file
+ """
+ testdir.makepyfile(test_a='''
+ import pytest
+
+ @pytest.fixture
+ def fix_a():
+ """Fixture A"""
+ pass
+
+ def test_a(fix_a):
+ pass
+ ''')
+ testdir.makepyfile(test_b='''
+ import pytest
+
+ @pytest.fixture
+ def fix_b():
+ """Fixture B"""
+ pass
+
+ def test_b(fix_b):
+ pass
+ ''')
+ result = testdir.runpytest("--fixtures")
+ result.stdout.fnmatch_lines("""
+ * fixtures defined from test_a *
+ fix_a
+ Fixture A
+
+ * fixtures defined from test_b *
+ fix_b
+ Fixture B
+ """)
+
+ def test_show_fixtures_with_same_name(self, testdir):
+ testdir.makeconftest('''
+ import pytest
+ @pytest.fixture
+ def arg1():
+ """Hello World in conftest.py"""
+ return "Hello World"
+ ''')
+ testdir.makepyfile('''
+ def test_foo(arg1):
+ assert arg1 == "Hello World"
+ ''')
+ testdir.makepyfile('''
+ import pytest
+ @pytest.fixture
+ def arg1():
+ """Hi from test module"""
+ return "Hi"
+ def test_bar(arg1):
+ assert arg1 == "Hi"
+ ''')
+ result = testdir.runpytest("--fixtures")
+ result.stdout.fnmatch_lines('''
+ * fixtures defined from conftest *
+ arg1
+ Hello World in conftest.py
+
+ * fixtures defined from test_show_fixtures_with_same_name *
+ arg1
+ Hi from test module
+ ''')
+
+
+@pytest.mark.parametrize('flavor', ['fixture', 'yield_fixture'])
+class TestContextManagerFixtureFuncs(object):
+
+ def test_simple(self, testdir, flavor):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.{flavor}
+ def arg1():
+ print ("setup")
+ yield 1
+ print ("teardown")
+ def test_1(arg1):
+ print ("test1 %s" % arg1)
+ def test_2(arg1):
+ print ("test2 %s" % arg1)
+ assert 0
+ """.format(flavor=flavor))
+ result = testdir.runpytest("-s")
+ result.stdout.fnmatch_lines("""
+ *setup*
+ *test1 1*
+ *teardown*
+ *setup*
+ *test2 1*
+ *teardown*
+ """)
+
+ def test_scoped(self, testdir, flavor):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.{flavor}(scope="module")
+ def arg1():
+ print ("setup")
+ yield 1
+ print ("teardown")
+ def test_1(arg1):
+ print ("test1 %s" % arg1)
+ def test_2(arg1):
+ print ("test2 %s" % arg1)
+ """.format(flavor=flavor))
+ result = testdir.runpytest("-s")
+ result.stdout.fnmatch_lines("""
+ *setup*
+ *test1 1*
+ *test2 1*
+ *teardown*
+ """)
+
+ def test_setup_exception(self, testdir, flavor):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.{flavor}(scope="module")
+ def arg1():
+ pytest.fail("setup")
+ yield 1
+ def test_1(arg1):
+ pass
+ """.format(flavor=flavor))
+ result = testdir.runpytest("-s")
+ result.stdout.fnmatch_lines("""
+ *pytest.fail*setup*
+ *1 error*
+ """)
+
+ def test_teardown_exception(self, testdir, flavor):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.{flavor}(scope="module")
+ def arg1():
+ yield 1
+ pytest.fail("teardown")
+ def test_1(arg1):
+ pass
+ """.format(flavor=flavor))
+ result = testdir.runpytest("-s")
+ result.stdout.fnmatch_lines("""
+ *pytest.fail*teardown*
+ *1 passed*1 error*
+ """)
+
+ def test_yields_more_than_one(self, testdir, flavor):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.{flavor}(scope="module")
+ def arg1():
+ yield 1
+ yield 2
+ def test_1(arg1):
+ pass
+ """.format(flavor=flavor))
+ result = testdir.runpytest("-s")
+ result.stdout.fnmatch_lines("""
+ *fixture function*
+ *test_yields*:2*
+ """)
+
+ def test_custom_name(self, testdir, flavor):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.{flavor}(name='meow')
+ def arg1():
+ return 'mew'
+ def test_1(meow):
+ print(meow)
+ """.format(flavor=flavor))
+ result = testdir.runpytest("-s")
+ result.stdout.fnmatch_lines("*mew*")
+
+
+class TestParameterizedSubRequest(object):
+ def test_call_from_fixture(self, testdir):
+ testfile = testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture(params=[0, 1, 2])
+ def fix_with_param(request):
+ return request.param
+
+ @pytest.fixture
+ def get_named_fixture(request):
+ return request.getfixturevalue('fix_with_param')
+
+ def test_foo(request, get_named_fixture):
+ pass
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines("""
+ E*Failed: The requested fixture has no parameter defined for the current test.
+ E*
+ E*Requested fixture 'fix_with_param' defined in:
+ E*{0}:4
+ E*Requested here:
+ E*{1}:9
+ *1 error*
+ """.format(testfile.basename, testfile.basename))
+
+ def test_call_from_test(self, testdir):
+ testfile = testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture(params=[0, 1, 2])
+ def fix_with_param(request):
+ return request.param
+
+ def test_foo(request):
+ request.getfixturevalue('fix_with_param')
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines("""
+ E*Failed: The requested fixture has no parameter defined for the current test.
+ E*
+ E*Requested fixture 'fix_with_param' defined in:
+ E*{0}:4
+ E*Requested here:
+ E*{1}:8
+ *1 failed*
+ """.format(testfile.basename, testfile.basename))
+
+ def test_external_fixture(self, testdir):
+ conffile = testdir.makeconftest("""
+ import pytest
+
+ @pytest.fixture(params=[0, 1, 2])
+ def fix_with_param(request):
+ return request.param
+ """)
+
+ testfile = testdir.makepyfile("""
+ def test_foo(request):
+ request.getfixturevalue('fix_with_param')
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines("""
+ E*Failed: The requested fixture has no parameter defined for the current test.
+ E*
+ E*Requested fixture 'fix_with_param' defined in:
+ E*{0}:4
+ E*Requested here:
+ E*{1}:2
+ *1 failed*
+ """.format(conffile.basename, testfile.basename))
+
+ def test_non_relative_path(self, testdir):
+ tests_dir = testdir.mkdir('tests')
+ fixdir = testdir.mkdir('fixtures')
+ fixfile = fixdir.join("fix.py")
+ fixfile.write(_pytest._code.Source("""
+ import pytest
+
+ @pytest.fixture(params=[0, 1, 2])
+ def fix_with_param(request):
+ return request.param
+ """))
+
+ testfile = tests_dir.join("test_foos.py")
+ testfile.write(_pytest._code.Source("""
+ from fix import fix_with_param
+
+ def test_foo(request):
+ request.getfixturevalue('fix_with_param')
+ """))
+
+ tests_dir.chdir()
+ testdir.syspathinsert(fixdir)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines("""
+ E*Failed: The requested fixture has no parameter defined for the current test.
+ E*
+ E*Requested fixture 'fix_with_param' defined in:
+ E*{0}:5
+ E*Requested here:
+ E*{1}:5
+ *1 failed*
+ """.format(fixfile.strpath, testfile.basename))
+
+
+def test_pytest_fixture_setup_and_post_finalizer_hook(testdir):
+ testdir.makeconftest("""
+ from __future__ import print_function
+ def pytest_fixture_setup(fixturedef, request):
+ print('ROOT setup hook called for {0} from {1}'.format(fixturedef.argname, request.node.name))
+ def pytest_fixture_post_finalizer(fixturedef, request):
+ print('ROOT finalizer hook called for {0} from {1}'.format(fixturedef.argname, request.node.name))
+ """)
+ testdir.makepyfile(**{
+ 'tests/conftest.py': """
+ from __future__ import print_function
+ def pytest_fixture_setup(fixturedef, request):
+ print('TESTS setup hook called for {0} from {1}'.format(fixturedef.argname, request.node.name))
+ def pytest_fixture_post_finalizer(fixturedef, request):
+ print('TESTS finalizer hook called for {0} from {1}'.format(fixturedef.argname, request.node.name))
+ """,
+ 'tests/test_hooks.py': """
+ from __future__ import print_function
+ import pytest
+
+ @pytest.fixture()
+ def my_fixture():
+ return 'some'
+
+ def test_func(my_fixture):
+ print('TEST test_func')
+ assert my_fixture == 'some'
+ """
+ })
+ result = testdir.runpytest("-s")
+ assert result.ret == 0
+ result.stdout.fnmatch_lines([
+ "*TESTS setup hook called for my_fixture from test_func*",
+ "*ROOT setup hook called for my_fixture from test_func*",
+ "*TEST test_func*",
+ "*TESTS finalizer hook called for my_fixture from test_func*",
+ "*ROOT finalizer hook called for my_fixture from test_func*",
+ ])
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/integration.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/integration.py
new file mode 100644
index 00000000000..6ea29fa98b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/integration.py
@@ -0,0 +1,384 @@
+import pytest
+from _pytest import python
+from _pytest import runner
+
+
+class TestOEJSKITSpecials(object):
+ def test_funcarg_non_pycollectobj(self, testdir): # rough jstests usage
+ testdir.makeconftest("""
+ import pytest
+ def pytest_pycollect_makeitem(collector, name, obj):
+ if name == "MyClass":
+ return MyCollector(name, parent=collector)
+ class MyCollector(pytest.Collector):
+ def reportinfo(self):
+ return self.fspath, 3, "xyz"
+ """)
+ modcol = testdir.getmodulecol("""
+ import pytest
+ @pytest.fixture
+ def arg1(request):
+ return 42
+ class MyClass(object):
+ pass
+ """)
+ # this hook finds funcarg factories
+ rep = runner.collect_one_node(collector=modcol)
+ clscol = rep.result[0]
+ clscol.obj = lambda arg1: None
+ clscol.funcargs = {}
+ pytest._fillfuncargs(clscol)
+ assert clscol.funcargs['arg1'] == 42
+
+ def test_autouse_fixture(self, testdir): # rough jstests usage
+ testdir.makeconftest("""
+ import pytest
+ def pytest_pycollect_makeitem(collector, name, obj):
+ if name == "MyClass":
+ return MyCollector(name, parent=collector)
+ class MyCollector(pytest.Collector):
+ def reportinfo(self):
+ return self.fspath, 3, "xyz"
+ """)
+ modcol = testdir.getmodulecol("""
+ import pytest
+ @pytest.fixture(autouse=True)
+ def hello():
+ pass
+ @pytest.fixture
+ def arg1(request):
+ return 42
+ class MyClass(object):
+ pass
+ """)
+ # this hook finds funcarg factories
+ rep = runner.collect_one_node(modcol)
+ clscol = rep.result[0]
+ clscol.obj = lambda: None
+ clscol.funcargs = {}
+ pytest._fillfuncargs(clscol)
+ assert not clscol.funcargs
+
+
+def test_wrapped_getfslineno():
+ def func():
+ pass
+
+ def wrap(f):
+ func.__wrapped__ = f
+ func.patchings = ["qwe"]
+ return func
+
+ @wrap
+ def wrapped_func(x, y, z):
+ pass
+ fs, lineno = python.getfslineno(wrapped_func)
+ fs2, lineno2 = python.getfslineno(wrap)
+ assert lineno > lineno2, "getfslineno does not unwrap correctly"
+
+
+class TestMockDecoration(object):
+ def test_wrapped_getfuncargnames(self):
+ from _pytest.compat import getfuncargnames
+
+ def wrap(f):
+
+ def func():
+ pass
+
+ func.__wrapped__ = f
+ return func
+
+ @wrap
+ def f(x):
+ pass
+
+ values = getfuncargnames(f)
+ assert values == ("x",)
+
+ def test_wrapped_getfuncargnames_patching(self):
+ from _pytest.compat import getfuncargnames
+
+ def wrap(f):
+ def func():
+ pass
+ func.__wrapped__ = f
+ func.patchings = ["qwe"]
+ return func
+
+ @wrap
+ def f(x, y, z):
+ pass
+
+ values = getfuncargnames(f)
+ assert values == ("y", "z")
+
+ def test_unittest_mock(self, testdir):
+ pytest.importorskip("unittest.mock")
+ testdir.makepyfile("""
+ import unittest.mock
+ class T(unittest.TestCase):
+ @unittest.mock.patch("os.path.abspath")
+ def test_hello(self, abspath):
+ import os
+ os.path.abspath("hello")
+ abspath.assert_any_call("hello")
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+ def test_unittest_mock_and_fixture(self, testdir):
+ pytest.importorskip("unittest.mock")
+ testdir.makepyfile("""
+ import os.path
+ import unittest.mock
+ import pytest
+
+ @pytest.fixture
+ def inject_me():
+ pass
+
+ @unittest.mock.patch.object(os.path, "abspath",
+ new=unittest.mock.MagicMock)
+ def test_hello(inject_me):
+ import os
+ os.path.abspath("hello")
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+ def test_mock(self, testdir):
+ pytest.importorskip("mock", "1.0.1")
+ testdir.makepyfile("""
+ import os
+ import unittest
+ import mock
+
+ class T(unittest.TestCase):
+ @mock.patch("os.path.abspath")
+ def test_hello(self, abspath):
+ os.path.abspath("hello")
+ abspath.assert_any_call("hello")
+ def mock_basename(path):
+ return "mock_basename"
+ @mock.patch("os.path.abspath")
+ @mock.patch("os.path.normpath")
+ @mock.patch("os.path.basename", new=mock_basename)
+ def test_someting(normpath, abspath, tmpdir):
+ abspath.return_value = "this"
+ os.path.normpath(os.path.abspath("hello"))
+ normpath.assert_any_call("this")
+ assert os.path.basename("123") == "mock_basename"
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=2)
+ calls = reprec.getcalls("pytest_runtest_logreport")
+ funcnames = [call.report.location[2] for call in calls
+ if call.report.when == "call"]
+ assert funcnames == ["T.test_hello", "test_someting"]
+
+ def test_mock_sorting(self, testdir):
+ pytest.importorskip("mock", "1.0.1")
+ testdir.makepyfile("""
+ import os
+ import mock
+
+ @mock.patch("os.path.abspath")
+ def test_one(abspath):
+ pass
+ @mock.patch("os.path.abspath")
+ def test_two(abspath):
+ pass
+ @mock.patch("os.path.abspath")
+ def test_three(abspath):
+ pass
+ """)
+ reprec = testdir.inline_run()
+ calls = reprec.getreports("pytest_runtest_logreport")
+ calls = [x for x in calls if x.when == "call"]
+ names = [x.nodeid.split("::")[-1] for x in calls]
+ assert names == ["test_one", "test_two", "test_three"]
+
+ def test_mock_double_patch_issue473(self, testdir):
+ pytest.importorskip("mock", "1.0.1")
+ testdir.makepyfile("""
+ from mock import patch
+ from pytest import mark
+
+ @patch('os.getcwd')
+ @patch('os.path')
+ @mark.slow
+ class TestSimple(object):
+ def test_simple_thing(self, mock_path, mock_getcwd):
+ pass
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+
+class TestReRunTests(object):
+ def test_rerun(self, testdir):
+ testdir.makeconftest("""
+ from _pytest.runner import runtestprotocol
+ def pytest_runtest_protocol(item, nextitem):
+ runtestprotocol(item, log=False, nextitem=nextitem)
+ runtestprotocol(item, log=True, nextitem=nextitem)
+ """)
+ testdir.makepyfile("""
+ import pytest
+ count = 0
+ req = None
+ @pytest.fixture
+ def fix(request):
+ global count, req
+ assert request != req
+ req = request
+ print ("fix count %s" % count)
+ count += 1
+ def test_fix(fix):
+ pass
+ """)
+ result = testdir.runpytest("-s")
+ result.stdout.fnmatch_lines("""
+ *fix count 0*
+ *fix count 1*
+ """)
+ result.stdout.fnmatch_lines("""
+ *2 passed*
+ """)
+
+
+def test_pytestconfig_is_session_scoped():
+ from _pytest.fixtures import pytestconfig
+ assert pytestconfig._pytestfixturefunction.scope == "session"
+
+
+class TestNoselikeTestAttribute(object):
+ def test_module_with_global_test(self, testdir):
+ testdir.makepyfile("""
+ __test__ = False
+ def test_hello():
+ pass
+ """)
+ reprec = testdir.inline_run()
+ assert not reprec.getfailedcollections()
+ calls = reprec.getreports("pytest_runtest_logreport")
+ assert not calls
+
+ def test_class_and_method(self, testdir):
+ testdir.makepyfile("""
+ __test__ = True
+ def test_func():
+ pass
+ test_func.__test__ = False
+
+ class TestSome(object):
+ __test__ = False
+ def test_method(self):
+ pass
+ """)
+ reprec = testdir.inline_run()
+ assert not reprec.getfailedcollections()
+ calls = reprec.getreports("pytest_runtest_logreport")
+ assert not calls
+
+ def test_unittest_class(self, testdir):
+ testdir.makepyfile("""
+ import unittest
+ class TC(unittest.TestCase):
+ def test_1(self):
+ pass
+ class TC2(unittest.TestCase):
+ __test__ = False
+ def test_2(self):
+ pass
+ """)
+ reprec = testdir.inline_run()
+ assert not reprec.getfailedcollections()
+ call = reprec.getcalls("pytest_collection_modifyitems")[0]
+ assert len(call.items) == 1
+ assert call.items[0].cls.__name__ == "TC"
+
+ def test_class_with_nasty_getattr(self, testdir):
+ """Make sure we handle classes with a custom nasty __getattr__ right.
+
+ With a custom __getattr__ which e.g. returns a function (like with a
+ RPC wrapper), we shouldn't assume this meant "__test__ = True".
+ """
+ # https://github.com/pytest-dev/pytest/issues/1204
+ testdir.makepyfile("""
+ class MetaModel(type):
+
+ def __getattr__(cls, key):
+ return lambda: None
+
+
+ BaseModel = MetaModel('Model', (), {})
+
+
+ class Model(BaseModel):
+
+ __metaclass__ = MetaModel
+
+ def test_blah(self):
+ pass
+ """)
+ reprec = testdir.inline_run()
+ assert not reprec.getfailedcollections()
+ call = reprec.getcalls("pytest_collection_modifyitems")[0]
+ assert not call.items
+
+
+@pytest.mark.issue351
+class TestParameterize(object):
+
+ def test_idfn_marker(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ def idfn(param):
+ if param == 0:
+ return 'spam'
+ elif param == 1:
+ return 'ham'
+ else:
+ return None
+
+ @pytest.mark.parametrize('a,b', [(0, 2), (1, 2)], ids=idfn)
+ def test_params(a, b):
+ pass
+ """)
+ res = testdir.runpytest('--collect-only')
+ res.stdout.fnmatch_lines([
+ "*spam-2*",
+ "*ham-2*",
+ ])
+
+ def test_idfn_fixture(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ def idfn(param):
+ if param == 0:
+ return 'spam'
+ elif param == 1:
+ return 'ham'
+ else:
+ return None
+
+ @pytest.fixture(params=[0, 1], ids=idfn)
+ def a(request):
+ return request.param
+
+ @pytest.fixture(params=[1, 2], ids=idfn)
+ def b(request):
+ return request.param
+
+ def test_params(a, b):
+ pass
+ """)
+ res = testdir.runpytest('--collect-only')
+ res.stdout.fnmatch_lines([
+ "*spam-2*",
+ "*ham-2*",
+ ])
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/metafunc.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/metafunc.py
new file mode 100644
index 00000000000..2ffb7bb5da2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/metafunc.py
@@ -0,0 +1,1561 @@
+# -*- coding: utf-8 -*-
+import re
+import sys
+
+import _pytest._code
+import py
+import pytest
+from _pytest import python, fixtures
+
+import hypothesis
+from hypothesis import strategies
+
+PY3 = sys.version_info >= (3, 0)
+
+
+class TestMetafunc(object):
+ def Metafunc(self, func):
+ # the unit tests of this class check if things work correctly
+ # on the funcarg level, so we don't need a full blown
+ # initiliazation
+ class FixtureInfo(object):
+ name2fixturedefs = None
+
+ def __init__(self, names):
+ self.names_closure = names
+
+ names = fixtures.getfuncargnames(func)
+ fixtureinfo = FixtureInfo(names)
+ return python.Metafunc(func, fixtureinfo, None)
+
+ def test_no_funcargs(self, testdir):
+ def function():
+ pass
+ metafunc = self.Metafunc(function)
+ assert not metafunc.fixturenames
+ repr(metafunc._calls)
+
+ def test_function_basic(self):
+ def func(arg1, arg2="qwe"):
+ pass
+ metafunc = self.Metafunc(func)
+ assert len(metafunc.fixturenames) == 1
+ assert 'arg1' in metafunc.fixturenames
+ assert metafunc.function is func
+ assert metafunc.cls is None
+
+ def test_addcall_no_args(self):
+ def func(arg1):
+ pass
+ metafunc = self.Metafunc(func)
+ metafunc.addcall()
+ assert len(metafunc._calls) == 1
+ call = metafunc._calls[0]
+ assert call.id == "0"
+ assert not hasattr(call, 'param')
+
+ def test_addcall_id(self):
+ def func(arg1):
+ pass
+ metafunc = self.Metafunc(func)
+ pytest.raises(ValueError, "metafunc.addcall(id=None)")
+
+ metafunc.addcall(id=1)
+ pytest.raises(ValueError, "metafunc.addcall(id=1)")
+ pytest.raises(ValueError, "metafunc.addcall(id='1')")
+ metafunc.addcall(id=2)
+ assert len(metafunc._calls) == 2
+ assert metafunc._calls[0].id == "1"
+ assert metafunc._calls[1].id == "2"
+
+ def test_addcall_param(self):
+ def func(arg1):
+ pass
+ metafunc = self.Metafunc(func)
+
+ class obj(object):
+ pass
+
+ metafunc.addcall(param=obj)
+ metafunc.addcall(param=obj)
+ metafunc.addcall(param=1)
+ assert len(metafunc._calls) == 3
+ assert metafunc._calls[0].getparam("arg1") == obj
+ assert metafunc._calls[1].getparam("arg1") == obj
+ assert metafunc._calls[2].getparam("arg1") == 1
+
+ def test_addcall_funcargs(self):
+ def func(x):
+ pass
+
+ metafunc = self.Metafunc(func)
+
+ class obj(object):
+ pass
+
+ metafunc.addcall(funcargs={"x": 2})
+ metafunc.addcall(funcargs={"x": 3})
+ pytest.raises(pytest.fail.Exception, "metafunc.addcall({'xyz': 0})")
+ assert len(metafunc._calls) == 2
+ assert metafunc._calls[0].funcargs == {'x': 2}
+ assert metafunc._calls[1].funcargs == {'x': 3}
+ assert not hasattr(metafunc._calls[1], 'param')
+
+ def test_parametrize_error(self):
+ def func(x, y):
+ pass
+ metafunc = self.Metafunc(func)
+ metafunc.parametrize("x", [1, 2])
+ pytest.raises(ValueError, lambda: metafunc.parametrize("x", [5, 6]))
+ pytest.raises(ValueError, lambda: metafunc.parametrize("x", [5, 6]))
+ metafunc.parametrize("y", [1, 2])
+ pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5, 6]))
+ pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5, 6]))
+
+ def test_parametrize_bad_scope(self, testdir):
+ def func(x):
+ pass
+ metafunc = self.Metafunc(func)
+ try:
+ metafunc.parametrize("x", [1], scope='doggy')
+ except ValueError as ve:
+ assert "has an unsupported scope value 'doggy'" in str(ve)
+
+ def test_parametrize_and_id(self):
+ def func(x, y):
+ pass
+ metafunc = self.Metafunc(func)
+
+ metafunc.parametrize("x", [1, 2], ids=['basic', 'advanced'])
+ metafunc.parametrize("y", ["abc", "def"])
+ ids = [x.id for x in metafunc._calls]
+ assert ids == ["basic-abc", "basic-def", "advanced-abc", "advanced-def"]
+
+ def test_parametrize_and_id_unicode(self):
+ """Allow unicode strings for "ids" parameter in Python 2 (##1905)"""
+ def func(x):
+ pass
+ metafunc = self.Metafunc(func)
+ metafunc.parametrize("x", [1, 2], ids=[u'basic', u'advanced'])
+ ids = [x.id for x in metafunc._calls]
+ assert ids == [u"basic", u"advanced"]
+
+ def test_parametrize_with_wrong_number_of_ids(self, testdir):
+ def func(x, y):
+ pass
+ metafunc = self.Metafunc(func)
+
+ pytest.raises(ValueError, lambda:
+ metafunc.parametrize("x", [1, 2], ids=['basic']))
+
+ pytest.raises(ValueError, lambda:
+ metafunc.parametrize(("x", "y"), [("abc", "def"),
+ ("ghi", "jkl")], ids=["one"]))
+
+ @pytest.mark.issue510
+ def test_parametrize_empty_list(self):
+ def func(y):
+ pass
+ metafunc = self.Metafunc(func)
+ metafunc.parametrize("y", [])
+ assert 'skip' == metafunc._calls[0].marks[0].name
+
+ def test_parametrize_with_userobjects(self):
+ def func(x, y):
+ pass
+ metafunc = self.Metafunc(func)
+
+ class A(object):
+ pass
+
+ metafunc.parametrize("x", [A(), A()])
+ metafunc.parametrize("y", list("ab"))
+ assert metafunc._calls[0].id == "x0-a"
+ assert metafunc._calls[1].id == "x0-b"
+ assert metafunc._calls[2].id == "x1-a"
+ assert metafunc._calls[3].id == "x1-b"
+
+ @hypothesis.given(strategies.text() | strategies.binary())
+ def test_idval_hypothesis(self, value):
+ from _pytest.python import _idval
+ escaped = _idval(value, 'a', 6, None)
+ assert isinstance(escaped, str)
+ if PY3:
+ escaped.encode('ascii')
+ else:
+ escaped.decode('ascii')
+
+ def test_unicode_idval(self):
+ """This tests that Unicode strings outside the ASCII character set get
+ escaped, using byte escapes if they're in that range or unicode
+ escapes if they're not.
+
+ """
+ from _pytest.python import _idval
+ values = [
+ (
+ u'',
+ ''
+ ),
+ (
+ u'ascii',
+ 'ascii'
+ ),
+ (
+ u'ação',
+ 'a\\xe7\\xe3o'
+ ),
+ (
+ u'josé@blah.com',
+ 'jos\\xe9@blah.com'
+ ),
+ (
+ u'δοκ.ιμή@παράδειγμα.δοκιμή',
+ '\\u03b4\\u03bf\\u03ba.\\u03b9\\u03bc\\u03ae@\\u03c0\\u03b1\\u03c1\\u03ac\\u03b4\\u03b5\\u03b9\\u03b3'
+ '\\u03bc\\u03b1.\\u03b4\\u03bf\\u03ba\\u03b9\\u03bc\\u03ae'
+ ),
+ ]
+ for val, expected in values:
+ assert _idval(val, 'a', 6, None) == expected
+
+ def test_bytes_idval(self):
+ """unittest for the expected behavior to obtain ids for parametrized
+ bytes values:
+ - python2: non-ascii strings are considered bytes and formatted using
+ "binary escape", where any byte < 127 is escaped into its hex form.
+ - python3: bytes objects are always escaped using "binary escape".
+ """
+ from _pytest.python import _idval
+ values = [
+ (b'', ''),
+ (b'\xc3\xb4\xff\xe4', '\\xc3\\xb4\\xff\\xe4'),
+ (b'ascii', 'ascii'),
+ (u'αρά'.encode('utf-8'), '\\xce\\xb1\\xcf\\x81\\xce\\xac'),
+ ]
+ for val, expected in values:
+ assert _idval(val, 'a', 6, None) == expected
+
+ @pytest.mark.issue250
+ def test_idmaker_autoname(self):
+ from _pytest.python import idmaker
+ result = idmaker(("a", "b"), [pytest.param("string", 1.0),
+ pytest.param("st-ring", 2.0)])
+ assert result == ["string-1.0", "st-ring-2.0"]
+
+ result = idmaker(("a", "b"), [pytest.param(object(), 1.0),
+ pytest.param(object(), object())])
+ assert result == ["a0-1.0", "a1-b1"]
+ # unicode mixing, issue250
+ result = idmaker(
+ (py.builtin._totext("a"), "b"),
+ [pytest.param({}, b'\xc3\xb4')])
+ assert result == ['a0-\\xc3\\xb4']
+
+ def test_idmaker_with_bytes_regex(self):
+ from _pytest.python import idmaker
+ result = idmaker(("a"), [pytest.param(re.compile(b'foo'), 1.0)])
+ assert result == ["foo"]
+
+ def test_idmaker_native_strings(self):
+ from _pytest.python import idmaker
+ totext = py.builtin._totext
+ result = idmaker(("a", "b"), [
+ pytest.param(1.0, -1.1),
+ pytest.param(2, -202),
+ pytest.param("three", "three hundred"),
+ pytest.param(True, False),
+ pytest.param(None, None),
+ pytest.param(re.compile('foo'), re.compile('bar')),
+ pytest.param(str, int),
+ pytest.param(list("six"), [66, 66]),
+ pytest.param(set([7]), set("seven")),
+ pytest.param(tuple("eight"), (8, -8, 8)),
+ pytest.param(b'\xc3\xb4', b"name"),
+ pytest.param(b'\xc3\xb4', totext("other")),
+ ])
+ assert result == ["1.0--1.1",
+ "2--202",
+ "three-three hundred",
+ "True-False",
+ "None-None",
+ "foo-bar",
+ "str-int",
+ "a7-b7",
+ "a8-b8",
+ "a9-b9",
+ "\\xc3\\xb4-name",
+ "\\xc3\\xb4-other",
+ ]
+
+ def test_idmaker_enum(self):
+ from _pytest.python import idmaker
+ enum = pytest.importorskip("enum")
+ e = enum.Enum("Foo", "one, two")
+ result = idmaker(("a", "b"), [pytest.param(e.one, e.two)])
+ assert result == ["Foo.one-Foo.two"]
+
+ @pytest.mark.issue351
+ def test_idmaker_idfn(self):
+ from _pytest.python import idmaker
+
+ def ids(val):
+ if isinstance(val, Exception):
+ return repr(val)
+
+ result = idmaker(("a", "b"), [
+ pytest.param(10.0, IndexError()),
+ pytest.param(20, KeyError()),
+ pytest.param("three", [1, 2, 3]),
+ ], idfn=ids)
+ assert result == ["10.0-IndexError()",
+ "20-KeyError()",
+ "three-b2",
+ ]
+
+ @pytest.mark.issue351
+ def test_idmaker_idfn_unique_names(self):
+ from _pytest.python import idmaker
+
+ def ids(val):
+ return 'a'
+
+ result = idmaker(("a", "b"), [pytest.param(10.0, IndexError()),
+ pytest.param(20, KeyError()),
+ pytest.param("three", [1, 2, 3]),
+ ], idfn=ids)
+ assert result == ["a-a0",
+ "a-a1",
+ "a-a2",
+ ]
+
+ @pytest.mark.issue351
+ def test_idmaker_idfn_exception(self):
+ from _pytest.python import idmaker
+ from _pytest.recwarn import WarningsRecorder
+
+ class BadIdsException(Exception):
+ pass
+
+ def ids(val):
+ raise BadIdsException("ids raised")
+
+ rec = WarningsRecorder()
+ with rec:
+ idmaker(("a", "b"), [
+ pytest.param(10.0, IndexError()),
+ pytest.param(20, KeyError()),
+ pytest.param("three", [1, 2, 3]),
+ ], idfn=ids)
+
+ assert [str(i.message) for i in rec.list] == [
+ "Raised while trying to determine id of parameter a at position 0."
+ "\nUpdate your code as this will raise an error in pytest-4.0.",
+ "Raised while trying to determine id of parameter b at position 0."
+ "\nUpdate your code as this will raise an error in pytest-4.0.",
+ "Raised while trying to determine id of parameter a at position 1."
+ "\nUpdate your code as this will raise an error in pytest-4.0.",
+ "Raised while trying to determine id of parameter b at position 1."
+ "\nUpdate your code as this will raise an error in pytest-4.0.",
+ "Raised while trying to determine id of parameter a at position 2."
+ "\nUpdate your code as this will raise an error in pytest-4.0.",
+ "Raised while trying to determine id of parameter b at position 2."
+ "\nUpdate your code as this will raise an error in pytest-4.0.",
+ ]
+
+ def test_parametrize_ids_exception(self, testdir):
+ """
+ :param testdir: the instance of Testdir class, a temporary
+ test directory.
+ """
+ testdir.makepyfile("""
+ import pytest
+
+ def ids(arg):
+ raise Exception("bad ids")
+
+ @pytest.mark.parametrize("arg", ["a", "b"], ids=ids)
+ def test_foo(arg):
+ pass
+ """)
+ with pytest.warns(DeprecationWarning):
+ result = testdir.runpytest("--collect-only")
+ result.stdout.fnmatch_lines([
+ "<Module 'test_parametrize_ids_exception.py'>",
+ " <Function 'test_foo[a]'>",
+ " <Function 'test_foo[b]'>",
+ ])
+
+ def test_idmaker_with_ids(self):
+ from _pytest.python import idmaker
+ result = idmaker(("a", "b"), [pytest.param(1, 2),
+ pytest.param(3, 4)],
+ ids=["a", None])
+ assert result == ["a", "3-4"]
+
+ def test_idmaker_with_paramset_id(self):
+ from _pytest.python import idmaker
+ result = idmaker(("a", "b"), [pytest.param(1, 2, id="me"),
+ pytest.param(3, 4, id="you")],
+ ids=["a", None])
+ assert result == ["me", "you"]
+
+ def test_idmaker_with_ids_unique_names(self):
+ from _pytest.python import idmaker
+ result = idmaker(("a"), map(pytest.param, [1, 2, 3, 4, 5]),
+ ids=["a", "a", "b", "c", "b"])
+ assert result == ["a0", "a1", "b0", "c", "b1"]
+
+ def test_addcall_and_parametrize(self):
+ def func(x, y):
+ pass
+ metafunc = self.Metafunc(func)
+ metafunc.addcall({'x': 1})
+ metafunc.parametrize('y', [2, 3])
+ assert len(metafunc._calls) == 2
+ assert metafunc._calls[0].funcargs == {'x': 1, 'y': 2}
+ assert metafunc._calls[1].funcargs == {'x': 1, 'y': 3}
+ assert metafunc._calls[0].id == "0-2"
+ assert metafunc._calls[1].id == "0-3"
+
+ @pytest.mark.issue714
+ def test_parametrize_indirect(self):
+ def func(x, y):
+ pass
+ metafunc = self.Metafunc(func)
+ metafunc.parametrize('x', [1], indirect=True)
+ metafunc.parametrize('y', [2, 3], indirect=True)
+ assert len(metafunc._calls) == 2
+ assert metafunc._calls[0].funcargs == {}
+ assert metafunc._calls[1].funcargs == {}
+ assert metafunc._calls[0].params == dict(x=1, y=2)
+ assert metafunc._calls[1].params == dict(x=1, y=3)
+
+ @pytest.mark.issue714
+ def test_parametrize_indirect_list(self):
+ def func(x, y):
+ pass
+ metafunc = self.Metafunc(func)
+ metafunc.parametrize('x, y', [('a', 'b')], indirect=['x'])
+ assert metafunc._calls[0].funcargs == dict(y='b')
+ assert metafunc._calls[0].params == dict(x='a')
+
+ @pytest.mark.issue714
+ def test_parametrize_indirect_list_all(self):
+ def func(x, y):
+ pass
+ metafunc = self.Metafunc(func)
+ metafunc.parametrize('x, y', [('a', 'b')], indirect=['x', 'y'])
+ assert metafunc._calls[0].funcargs == {}
+ assert metafunc._calls[0].params == dict(x='a', y='b')
+
+ @pytest.mark.issue714
+ def test_parametrize_indirect_list_empty(self):
+ def func(x, y):
+ pass
+ metafunc = self.Metafunc(func)
+ metafunc.parametrize('x, y', [('a', 'b')], indirect=[])
+ assert metafunc._calls[0].funcargs == dict(x='a', y='b')
+ assert metafunc._calls[0].params == {}
+
+ @pytest.mark.issue714
+ def test_parametrize_indirect_list_functional(self, testdir):
+ """
+ Test parametrization with 'indirect' parameter applied on
+ particular arguments. As y is is direct, its value should
+ be used directly rather than being passed to the fixture
+ y.
+
+ :param testdir: the instance of Testdir class, a temporary
+ test directory.
+ """
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture(scope='function')
+ def x(request):
+ return request.param * 3
+ @pytest.fixture(scope='function')
+ def y(request):
+ return request.param * 2
+ @pytest.mark.parametrize('x, y', [('a', 'b')], indirect=['x'])
+ def test_simple(x,y):
+ assert len(x) == 3
+ assert len(y) == 1
+ """)
+ result = testdir.runpytest("-v")
+ result.stdout.fnmatch_lines([
+ "*test_simple*a-b*",
+ "*1 passed*",
+ ])
+
+ @pytest.mark.issue714
+ def test_parametrize_indirect_list_error(self, testdir):
+ def func(x, y):
+ pass
+ metafunc = self.Metafunc(func)
+ with pytest.raises(ValueError):
+ metafunc.parametrize('x, y', [('a', 'b')], indirect=['x', 'z'])
+
+ @pytest.mark.issue714
+ def test_parametrize_uses_no_fixture_error_indirect_false(self, testdir):
+ """The 'uses no fixture' error tells the user at collection time
+ that the parametrize data they've set up doesn't correspond to the
+ fixtures in their test function, rather than silently ignoring this
+ and letting the test potentially pass.
+ """
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.mark.parametrize('x, y', [('a', 'b')], indirect=False)
+ def test_simple(x):
+ assert len(x) == 3
+ """)
+ result = testdir.runpytest("--collect-only")
+ result.stdout.fnmatch_lines([
+ "*uses no argument 'y'*",
+ ])
+
+ @pytest.mark.issue714
+ def test_parametrize_uses_no_fixture_error_indirect_true(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture(scope='function')
+ def x(request):
+ return request.param * 3
+ @pytest.fixture(scope='function')
+ def y(request):
+ return request.param * 2
+
+ @pytest.mark.parametrize('x, y', [('a', 'b')], indirect=True)
+ def test_simple(x):
+ assert len(x) == 3
+ """)
+ result = testdir.runpytest("--collect-only")
+ result.stdout.fnmatch_lines([
+ "*uses no fixture 'y'*",
+ ])
+
+ @pytest.mark.issue714
+ def test_parametrize_indirect_uses_no_fixture_error_indirect_string(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture(scope='function')
+ def x(request):
+ return request.param * 3
+
+ @pytest.mark.parametrize('x, y', [('a', 'b')], indirect='y')
+ def test_simple(x):
+ assert len(x) == 3
+ """)
+ result = testdir.runpytest("--collect-only")
+ result.stdout.fnmatch_lines([
+ "*uses no fixture 'y'*",
+ ])
+
+ @pytest.mark.issue714
+ def test_parametrize_indirect_uses_no_fixture_error_indirect_list(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture(scope='function')
+ def x(request):
+ return request.param * 3
+
+ @pytest.mark.parametrize('x, y', [('a', 'b')], indirect=['y'])
+ def test_simple(x):
+ assert len(x) == 3
+ """)
+ result = testdir.runpytest("--collect-only")
+ result.stdout.fnmatch_lines([
+ "*uses no fixture 'y'*",
+ ])
+
+ @pytest.mark.issue714
+ def test_parametrize_argument_not_in_indirect_list(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture(scope='function')
+ def x(request):
+ return request.param * 3
+
+ @pytest.mark.parametrize('x, y', [('a', 'b')], indirect=['x'])
+ def test_simple(x):
+ assert len(x) == 3
+ """)
+ result = testdir.runpytest("--collect-only")
+ result.stdout.fnmatch_lines([
+ "*uses no argument 'y'*",
+ ])
+
+ def test_addcalls_and_parametrize_indirect(self):
+ def func(x, y):
+ pass
+ metafunc = self.Metafunc(func)
+ metafunc.addcall(param="123")
+ metafunc.parametrize('x', [1], indirect=True)
+ metafunc.parametrize('y', [2, 3], indirect=True)
+ assert len(metafunc._calls) == 2
+ assert metafunc._calls[0].funcargs == {}
+ assert metafunc._calls[1].funcargs == {}
+ assert metafunc._calls[0].params == dict(x=1, y=2)
+ assert metafunc._calls[1].params == dict(x=1, y=3)
+
+ def test_parametrize_functional(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ def pytest_generate_tests(metafunc):
+ metafunc.parametrize('x', [1,2], indirect=True)
+ metafunc.parametrize('y', [2])
+ @pytest.fixture
+ def x(request):
+ return request.param * 10
+
+ def test_simple(x,y):
+ assert x in (10,20)
+ assert y == 2
+ """)
+ result = testdir.runpytest("-v")
+ result.stdout.fnmatch_lines([
+ "*test_simple*1-2*",
+ "*test_simple*2-2*",
+ "*2 passed*",
+ ])
+
+ def test_parametrize_onearg(self):
+ metafunc = self.Metafunc(lambda x: None)
+ metafunc.parametrize("x", [1, 2])
+ assert len(metafunc._calls) == 2
+ assert metafunc._calls[0].funcargs == dict(x=1)
+ assert metafunc._calls[0].id == "1"
+ assert metafunc._calls[1].funcargs == dict(x=2)
+ assert metafunc._calls[1].id == "2"
+
+ def test_parametrize_onearg_indirect(self):
+ metafunc = self.Metafunc(lambda x: None)
+ metafunc.parametrize("x", [1, 2], indirect=True)
+ assert metafunc._calls[0].params == dict(x=1)
+ assert metafunc._calls[0].id == "1"
+ assert metafunc._calls[1].params == dict(x=2)
+ assert metafunc._calls[1].id == "2"
+
+ def test_parametrize_twoargs(self):
+ metafunc = self.Metafunc(lambda x, y: None)
+ metafunc.parametrize(("x", "y"), [(1, 2), (3, 4)])
+ assert len(metafunc._calls) == 2
+ assert metafunc._calls[0].funcargs == dict(x=1, y=2)
+ assert metafunc._calls[0].id == "1-2"
+ assert metafunc._calls[1].funcargs == dict(x=3, y=4)
+ assert metafunc._calls[1].id == "3-4"
+
+ def test_parametrize_multiple_times(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ pytestmark = pytest.mark.parametrize("x", [1,2])
+ def test_func(x):
+ assert 0, x
+ class TestClass(object):
+ pytestmark = pytest.mark.parametrize("y", [3,4])
+ def test_meth(self, x, y):
+ assert 0, x
+ """)
+ result = testdir.runpytest()
+ assert result.ret == 1
+ result.assert_outcomes(failed=6)
+
+ def test_parametrize_CSV(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.parametrize("x, y,", [(1,2), (2,3)])
+ def test_func(x, y):
+ assert x+1 == y
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=2)
+
+ def test_parametrize_class_scenarios(self, testdir):
+ testdir.makepyfile("""
+ # same as doc/en/example/parametrize scenario example
+ def pytest_generate_tests(metafunc):
+ idlist = []
+ argvalues = []
+ for scenario in metafunc.cls.scenarios:
+ idlist.append(scenario[0])
+ items = scenario[1].items()
+ argnames = [x[0] for x in items]
+ argvalues.append(([x[1] for x in items]))
+ metafunc.parametrize(argnames, argvalues, ids=idlist, scope="class")
+
+ class Test(object):
+ scenarios = [['1', {'arg': {1: 2}, "arg2": "value2"}],
+ ['2', {'arg':'value2', "arg2": "value2"}]]
+
+ def test_1(self, arg, arg2):
+ pass
+
+ def test_2(self, arg2, arg):
+ pass
+
+ def test_3(self, arg, arg2):
+ pass
+ """)
+ result = testdir.runpytest("-v")
+ assert result.ret == 0
+ result.stdout.fnmatch_lines("""
+ *test_1*1*
+ *test_2*1*
+ *test_3*1*
+ *test_1*2*
+ *test_2*2*
+ *test_3*2*
+ *6 passed*
+ """)
+
+ def test_format_args(self):
+ def function1():
+ pass
+ assert fixtures._format_args(function1) == '()'
+
+ def function2(arg1):
+ pass
+ assert fixtures._format_args(function2) == "(arg1)"
+
+ def function3(arg1, arg2="qwe"):
+ pass
+ assert fixtures._format_args(function3) == "(arg1, arg2='qwe')"
+
+ def function4(arg1, *args, **kwargs):
+ pass
+ assert fixtures._format_args(function4) == "(arg1, *args, **kwargs)"
+
+
+class TestMetafuncFunctional(object):
+ def test_attributes(self, testdir):
+ p = testdir.makepyfile("""
+ # assumes that generate/provide runs in the same process
+ import py, pytest
+ def pytest_generate_tests(metafunc):
+ metafunc.addcall(param=metafunc)
+
+ @pytest.fixture
+ def metafunc(request):
+ assert request._pyfuncitem._genid == "0"
+ return request.param
+
+ def test_function(metafunc, pytestconfig):
+ assert metafunc.config == pytestconfig
+ assert metafunc.module.__name__ == __name__
+ assert metafunc.function == test_function
+ assert metafunc.cls is None
+
+ class TestClass(object):
+ def test_method(self, metafunc, pytestconfig):
+ assert metafunc.config == pytestconfig
+ assert metafunc.module.__name__ == __name__
+ if py.std.sys.version_info > (3, 0):
+ unbound = TestClass.test_method
+ else:
+ unbound = TestClass.test_method.im_func
+ # XXX actually have an unbound test function here?
+ assert metafunc.function == unbound
+ assert metafunc.cls == TestClass
+ """)
+ result = testdir.runpytest(p, "-v")
+ result.assert_outcomes(passed=2)
+
+ def test_addcall_with_two_funcargs_generators(self, testdir):
+ testdir.makeconftest("""
+ def pytest_generate_tests(metafunc):
+ assert "arg1" in metafunc.fixturenames
+ metafunc.addcall(funcargs=dict(arg1=1, arg2=2))
+ """)
+ p = testdir.makepyfile("""
+ def pytest_generate_tests(metafunc):
+ metafunc.addcall(funcargs=dict(arg1=1, arg2=1))
+
+ class TestClass(object):
+ def test_myfunc(self, arg1, arg2):
+ assert arg1 == arg2
+ """)
+ result = testdir.runpytest("-v", p)
+ result.stdout.fnmatch_lines([
+ "*test_myfunc*0*PASS*",
+ "*test_myfunc*1*FAIL*",
+ "*1 failed, 1 passed*"
+ ])
+
+ def test_two_functions(self, testdir):
+ p = testdir.makepyfile("""
+ def pytest_generate_tests(metafunc):
+ metafunc.addcall(param=10)
+ metafunc.addcall(param=20)
+
+ import pytest
+ @pytest.fixture
+ def arg1(request):
+ return request.param
+
+ def test_func1(arg1):
+ assert arg1 == 10
+ def test_func2(arg1):
+ assert arg1 in (10, 20)
+ """)
+ result = testdir.runpytest("-v", p)
+ result.stdout.fnmatch_lines([
+ "*test_func1*0*PASS*",
+ "*test_func1*1*FAIL*",
+ "*test_func2*PASS*",
+ "*1 failed, 3 passed*"
+ ])
+
+ def test_noself_in_method(self, testdir):
+ p = testdir.makepyfile("""
+ def pytest_generate_tests(metafunc):
+ assert 'xyz' not in metafunc.fixturenames
+
+ class TestHello(object):
+ def test_hello(xyz):
+ pass
+ """)
+ result = testdir.runpytest(p)
+ result.assert_outcomes(passed=1)
+
+ def test_generate_plugin_and_module(self, testdir):
+ testdir.makeconftest("""
+ def pytest_generate_tests(metafunc):
+ assert "arg1" in metafunc.fixturenames
+ metafunc.addcall(id="world", param=(2,100))
+ """)
+ p = testdir.makepyfile("""
+ def pytest_generate_tests(metafunc):
+ metafunc.addcall(param=(1,1), id="hello")
+
+ import pytest
+ @pytest.fixture
+ def arg1(request):
+ return request.param[0]
+ @pytest.fixture
+ def arg2(request):
+ return request.param[1]
+
+ class TestClass(object):
+ def test_myfunc(self, arg1, arg2):
+ assert arg1 == arg2
+ """)
+ result = testdir.runpytest("-v", p)
+ result.stdout.fnmatch_lines([
+ "*test_myfunc*hello*PASS*",
+ "*test_myfunc*world*FAIL*",
+ "*1 failed, 1 passed*"
+ ])
+
+ def test_generate_tests_in_class(self, testdir):
+ p = testdir.makepyfile("""
+ class TestClass(object):
+ def pytest_generate_tests(self, metafunc):
+ metafunc.addcall(funcargs={'hello': 'world'}, id="hello")
+
+ def test_myfunc(self, hello):
+ assert hello == "world"
+ """)
+ result = testdir.runpytest("-v", p)
+ result.stdout.fnmatch_lines([
+ "*test_myfunc*hello*PASS*",
+ "*1 passed*"
+ ])
+
+ def test_two_functions_not_same_instance(self, testdir):
+ p = testdir.makepyfile("""
+ def pytest_generate_tests(metafunc):
+ metafunc.addcall({'arg1': 10})
+ metafunc.addcall({'arg1': 20})
+
+ class TestClass(object):
+ def test_func(self, arg1):
+ assert not hasattr(self, 'x')
+ self.x = 1
+ """)
+ result = testdir.runpytest("-v", p)
+ result.stdout.fnmatch_lines([
+ "*test_func*0*PASS*",
+ "*test_func*1*PASS*",
+ "*2 pass*",
+ ])
+
+ def test_issue28_setup_method_in_generate_tests(self, testdir):
+ p = testdir.makepyfile("""
+ def pytest_generate_tests(metafunc):
+ metafunc.addcall({'arg1': 1})
+
+ class TestClass(object):
+ def test_method(self, arg1):
+ assert arg1 == self.val
+ def setup_method(self, func):
+ self.val = 1
+ """)
+ result = testdir.runpytest(p)
+ result.assert_outcomes(passed=1)
+
+ def test_parametrize_functional2(self, testdir):
+ testdir.makepyfile("""
+ def pytest_generate_tests(metafunc):
+ metafunc.parametrize("arg1", [1,2])
+ metafunc.parametrize("arg2", [4,5])
+ def test_hello(arg1, arg2):
+ assert 0, (arg1, arg2)
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*(1, 4)*",
+ "*(1, 5)*",
+ "*(2, 4)*",
+ "*(2, 5)*",
+ "*4 failed*",
+ ])
+
+ def test_parametrize_and_inner_getfixturevalue(self, testdir):
+ p = testdir.makepyfile("""
+ def pytest_generate_tests(metafunc):
+ metafunc.parametrize("arg1", [1], indirect=True)
+ metafunc.parametrize("arg2", [10], indirect=True)
+
+ import pytest
+ @pytest.fixture
+ def arg1(request):
+ x = request.getfixturevalue("arg2")
+ return x + request.param
+
+ @pytest.fixture
+ def arg2(request):
+ return request.param
+
+ def test_func1(arg1, arg2):
+ assert arg1 == 11
+ """)
+ result = testdir.runpytest("-v", p)
+ result.stdout.fnmatch_lines([
+ "*test_func1*1*PASS*",
+ "*1 passed*"
+ ])
+
+ def test_parametrize_on_setup_arg(self, testdir):
+ p = testdir.makepyfile("""
+ def pytest_generate_tests(metafunc):
+ assert "arg1" in metafunc.fixturenames
+ metafunc.parametrize("arg1", [1], indirect=True)
+
+ import pytest
+ @pytest.fixture
+ def arg1(request):
+ return request.param
+
+ @pytest.fixture
+ def arg2(request, arg1):
+ return 10 * arg1
+
+ def test_func(arg2):
+ assert arg2 == 10
+ """)
+ result = testdir.runpytest("-v", p)
+ result.stdout.fnmatch_lines([
+ "*test_func*1*PASS*",
+ "*1 passed*"
+ ])
+
+ def test_parametrize_with_ids(self, testdir):
+ testdir.makeini("""
+ [pytest]
+ console_output_style=classic
+ """)
+ testdir.makepyfile("""
+ import pytest
+ def pytest_generate_tests(metafunc):
+ metafunc.parametrize(("a", "b"), [(1,1), (1,2)],
+ ids=["basic", "advanced"])
+
+ def test_function(a, b):
+ assert a == b
+ """)
+ result = testdir.runpytest("-v")
+ assert result.ret == 1
+ result.stdout.fnmatch_lines_random([
+ "*test_function*basic*PASSED",
+ "*test_function*advanced*FAILED",
+ ])
+
+ def test_parametrize_without_ids(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ def pytest_generate_tests(metafunc):
+ metafunc.parametrize(("a", "b"),
+ [(1,object()), (1.3,object())])
+
+ def test_function(a, b):
+ assert 1
+ """)
+ result = testdir.runpytest("-v")
+ result.stdout.fnmatch_lines("""
+ *test_function*1-b0*
+ *test_function*1.3-b1*
+ """)
+
+ def test_parametrize_with_None_in_ids(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ def pytest_generate_tests(metafunc):
+ metafunc.parametrize(("a", "b"), [(1,1), (1,1), (1,2)],
+ ids=["basic", None, "advanced"])
+
+ def test_function(a, b):
+ assert a == b
+ """)
+ result = testdir.runpytest("-v")
+ assert result.ret == 1
+ result.stdout.fnmatch_lines_random([
+ "*test_function*basic*PASSED*",
+ "*test_function*1-1*PASSED*",
+ "*test_function*advanced*FAILED*",
+ ])
+
+ def test_fixture_parametrized_empty_ids(self, testdir):
+ """Fixtures parametrized with empty ids cause an internal error (#1849)."""
+ testdir.makepyfile('''
+ import pytest
+
+ @pytest.fixture(scope="module", ids=[], params=[])
+ def temp(request):
+ return request.param
+
+ def test_temp(temp):
+ pass
+ ''')
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(['* 1 skipped *'])
+
+ def test_parametrized_empty_ids(self, testdir):
+ """Tests parametrized with empty ids cause an internal error (#1849)."""
+ testdir.makepyfile('''
+ import pytest
+
+ @pytest.mark.parametrize('temp', [], ids=list())
+ def test_temp(temp):
+ pass
+ ''')
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(['* 1 skipped *'])
+
+ def test_parametrized_ids_invalid_type(self, testdir):
+ """Tests parametrized with ids as non-strings (#1857)."""
+ testdir.makepyfile('''
+ import pytest
+
+ @pytest.mark.parametrize("x, expected", [(10, 20), (40, 80)], ids=(None, 2))
+ def test_ids_numbers(x,expected):
+ assert x * 2 == expected
+ ''')
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(['*ids must be list of strings, found: 2 (type: int)*'])
+
+ def test_parametrize_with_identical_ids_get_unique_names(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ def pytest_generate_tests(metafunc):
+ metafunc.parametrize(("a", "b"), [(1,1), (1,2)],
+ ids=["a", "a"])
+
+ def test_function(a, b):
+ assert a == b
+ """)
+ result = testdir.runpytest("-v")
+ assert result.ret == 1
+ result.stdout.fnmatch_lines_random([
+ "*test_function*a0*PASSED*",
+ "*test_function*a1*FAILED*"
+ ])
+
+ @pytest.mark.parametrize(("scope", "length"),
+ [("module", 2), ("function", 4)])
+ def test_parametrize_scope_overrides(self, testdir, scope, length):
+ testdir.makepyfile("""
+ import pytest
+ values = []
+ def pytest_generate_tests(metafunc):
+ if "arg" in metafunc.funcargnames:
+ metafunc.parametrize("arg", [1,2], indirect=True,
+ scope=%r)
+ @pytest.fixture
+ def arg(request):
+ values.append(request.param)
+ return request.param
+ def test_hello(arg):
+ assert arg in (1,2)
+ def test_world(arg):
+ assert arg in (1,2)
+ def test_checklength():
+ assert len(values) == %d
+ """ % (scope, length))
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=5)
+
+ def test_parametrize_issue323(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture(scope='module', params=range(966))
+ def foo(request):
+ return request.param
+
+ def test_it(foo):
+ pass
+ def test_it2(foo):
+ pass
+ """)
+ reprec = testdir.inline_run("--collect-only")
+ assert not reprec.getcalls("pytest_internalerror")
+
+ def test_usefixtures_seen_in_generate_tests(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ def pytest_generate_tests(metafunc):
+ assert "abc" in metafunc.fixturenames
+ metafunc.parametrize("abc", [1])
+
+ @pytest.mark.usefixtures("abc")
+ def test_function():
+ pass
+ """)
+ reprec = testdir.runpytest()
+ reprec.assert_outcomes(passed=1)
+
+ def test_generate_tests_only_done_in_subdir(self, testdir):
+ sub1 = testdir.mkpydir("sub1")
+ sub2 = testdir.mkpydir("sub2")
+ sub1.join("conftest.py").write(_pytest._code.Source("""
+ def pytest_generate_tests(metafunc):
+ assert metafunc.function.__name__ == "test_1"
+ """))
+ sub2.join("conftest.py").write(_pytest._code.Source("""
+ def pytest_generate_tests(metafunc):
+ assert metafunc.function.__name__ == "test_2"
+ """))
+ sub1.join("test_in_sub1.py").write("def test_1(): pass")
+ sub2.join("test_in_sub2.py").write("def test_2(): pass")
+ result = testdir.runpytest("--keep-duplicates", "-v", "-s", sub1, sub2, sub1)
+ result.assert_outcomes(passed=3)
+
+ def test_generate_same_function_names_issue403(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ def make_tests():
+ @pytest.mark.parametrize("x", range(2))
+ def test_foo(x):
+ pass
+ return test_foo
+
+ test_x = make_tests()
+ test_y = make_tests()
+ """)
+ reprec = testdir.runpytest()
+ reprec.assert_outcomes(passed=4)
+
+ @pytest.mark.issue463
+ @pytest.mark.parametrize('attr', ['parametrise', 'parameterize',
+ 'parameterise'])
+ def test_parametrize_misspelling(self, testdir, attr):
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.mark.{0}("x", range(2))
+ def test_foo(x):
+ pass
+ """.format(attr))
+ reprec = testdir.inline_run('--collectonly')
+ failures = reprec.getfailures()
+ assert len(failures) == 1
+ expectederror = "MarkerError: test_foo has '{0}', spelling should be 'parametrize'".format(attr)
+ assert expectederror in failures[0].longrepr.reprcrash.message
+
+
+class TestMetafuncFunctionalAuto(object):
+ """
+ Tests related to automatically find out the correct scope for parametrized tests (#1832).
+ """
+
+ def test_parametrize_auto_scope(self, testdir):
+ testdir.makepyfile('''
+ import pytest
+
+ @pytest.fixture(scope='session', autouse=True)
+ def fixture():
+ return 1
+
+ @pytest.mark.parametrize('animal', ["dog", "cat"])
+ def test_1(animal):
+ assert animal in ('dog', 'cat')
+
+ @pytest.mark.parametrize('animal', ['fish'])
+ def test_2(animal):
+ assert animal == 'fish'
+
+ ''')
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(['* 3 passed *'])
+
+ def test_parametrize_auto_scope_indirect(self, testdir):
+ testdir.makepyfile('''
+ import pytest
+
+ @pytest.fixture(scope='session')
+ def echo(request):
+ return request.param
+
+ @pytest.mark.parametrize('animal, echo', [("dog", 1), ("cat", 2)], indirect=['echo'])
+ def test_1(animal, echo):
+ assert animal in ('dog', 'cat')
+ assert echo in (1, 2, 3)
+
+ @pytest.mark.parametrize('animal, echo', [('fish', 3)], indirect=['echo'])
+ def test_2(animal, echo):
+ assert animal == 'fish'
+ assert echo in (1, 2, 3)
+ ''')
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(['* 3 passed *'])
+
+ def test_parametrize_auto_scope_override_fixture(self, testdir):
+ testdir.makepyfile('''
+ import pytest
+
+ @pytest.fixture(scope='session', autouse=True)
+ def animal():
+ return 'fox'
+
+ @pytest.mark.parametrize('animal', ["dog", "cat"])
+ def test_1(animal):
+ assert animal in ('dog', 'cat')
+ ''')
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(['* 2 passed *'])
+
+ def test_parametrize_all_indirects(self, testdir):
+ testdir.makepyfile('''
+ import pytest
+
+ @pytest.fixture()
+ def animal(request):
+ return request.param
+
+ @pytest.fixture(scope='session')
+ def echo(request):
+ return request.param
+
+ @pytest.mark.parametrize('animal, echo', [("dog", 1), ("cat", 2)], indirect=True)
+ def test_1(animal, echo):
+ assert animal in ('dog', 'cat')
+ assert echo in (1, 2, 3)
+
+ @pytest.mark.parametrize('animal, echo', [("fish", 3)], indirect=True)
+ def test_2(animal, echo):
+ assert animal == 'fish'
+ assert echo in (1, 2, 3)
+ ''')
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(['* 3 passed *'])
+
+ def test_parametrize_issue634(self, testdir):
+ testdir.makepyfile('''
+ import pytest
+
+ @pytest.fixture(scope='module')
+ def foo(request):
+ print('preparing foo-%d' % request.param)
+ return 'foo-%d' % request.param
+
+ def test_one(foo):
+ pass
+
+ def test_two(foo):
+ pass
+
+ test_two.test_with = (2, 3)
+
+ def pytest_generate_tests(metafunc):
+ params = (1, 2, 3, 4)
+ if not 'foo' in metafunc.fixturenames:
+ return
+
+ test_with = getattr(metafunc.function, 'test_with', None)
+ if test_with:
+ params = test_with
+ metafunc.parametrize('foo', params, indirect=True)
+ ''')
+ result = testdir.runpytest("-s")
+ output = result.stdout.str()
+ assert output.count('preparing foo-2') == 1
+ assert output.count('preparing foo-3') == 1
+
+
+@pytest.mark.filterwarnings('ignore:Applying marks directly to parameters')
+@pytest.mark.issue308
+class TestMarkersWithParametrization(object):
+
+ def test_simple_mark(self, testdir):
+ s = """
+ import pytest
+
+ @pytest.mark.foo
+ @pytest.mark.parametrize(("n", "expected"), [
+ (1, 2),
+ pytest.mark.bar((1, 3)),
+ (2, 3),
+ ])
+ def test_increment(n, expected):
+ assert n + 1 == expected
+ """
+ items = testdir.getitems(s)
+ assert len(items) == 3
+ for item in items:
+ assert 'foo' in item.keywords
+ assert 'bar' not in items[0].keywords
+ assert 'bar' in items[1].keywords
+ assert 'bar' not in items[2].keywords
+
+ def test_select_based_on_mark(self, testdir):
+ s = """
+ import pytest
+
+ @pytest.mark.parametrize(("n", "expected"), [
+ (1, 2),
+ pytest.mark.foo((2, 3)),
+ (3, 4),
+ ])
+ def test_increment(n, expected):
+ assert n + 1 == expected
+ """
+ testdir.makepyfile(s)
+ rec = testdir.inline_run("-m", 'foo')
+ passed, skipped, fail = rec.listoutcomes()
+ assert len(passed) == 1
+ assert len(skipped) == 0
+ assert len(fail) == 0
+
+ @pytest.mark.xfail(reason="is this important to support??")
+ def test_nested_marks(self, testdir):
+ s = """
+ import pytest
+ mastermark = pytest.mark.foo(pytest.mark.bar)
+
+ @pytest.mark.parametrize(("n", "expected"), [
+ (1, 2),
+ mastermark((1, 3)),
+ (2, 3),
+ ])
+ def test_increment(n, expected):
+ assert n + 1 == expected
+ """
+ items = testdir.getitems(s)
+ assert len(items) == 3
+ for mark in ['foo', 'bar']:
+ assert mark not in items[0].keywords
+ assert mark in items[1].keywords
+ assert mark not in items[2].keywords
+
+ def test_simple_xfail(self, testdir):
+ s = """
+ import pytest
+
+ @pytest.mark.parametrize(("n", "expected"), [
+ (1, 2),
+ pytest.mark.xfail((1, 3)),
+ (2, 3),
+ ])
+ def test_increment(n, expected):
+ assert n + 1 == expected
+ """
+ testdir.makepyfile(s)
+ reprec = testdir.inline_run()
+ # xfail is skip??
+ reprec.assertoutcome(passed=2, skipped=1)
+
+ def test_simple_xfail_single_argname(self, testdir):
+ s = """
+ import pytest
+
+ @pytest.mark.parametrize("n", [
+ 2,
+ pytest.mark.xfail(3),
+ 4,
+ ])
+ def test_isEven(n):
+ assert n % 2 == 0
+ """
+ testdir.makepyfile(s)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=2, skipped=1)
+
+ def test_xfail_with_arg(self, testdir):
+ s = """
+ import pytest
+
+ @pytest.mark.parametrize(("n", "expected"), [
+ (1, 2),
+ pytest.mark.xfail("True")((1, 3)),
+ (2, 3),
+ ])
+ def test_increment(n, expected):
+ assert n + 1 == expected
+ """
+ testdir.makepyfile(s)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=2, skipped=1)
+
+ def test_xfail_with_kwarg(self, testdir):
+ s = """
+ import pytest
+
+ @pytest.mark.parametrize(("n", "expected"), [
+ (1, 2),
+ pytest.mark.xfail(reason="some bug")((1, 3)),
+ (2, 3),
+ ])
+ def test_increment(n, expected):
+ assert n + 1 == expected
+ """
+ testdir.makepyfile(s)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=2, skipped=1)
+
+ def test_xfail_with_arg_and_kwarg(self, testdir):
+ s = """
+ import pytest
+
+ @pytest.mark.parametrize(("n", "expected"), [
+ (1, 2),
+ pytest.mark.xfail("True", reason="some bug")((1, 3)),
+ (2, 3),
+ ])
+ def test_increment(n, expected):
+ assert n + 1 == expected
+ """
+ testdir.makepyfile(s)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=2, skipped=1)
+
+ @pytest.mark.parametrize('strict', [True, False])
+ def test_xfail_passing_is_xpass(self, testdir, strict):
+ s = """
+ import pytest
+
+ @pytest.mark.parametrize(("n", "expected"), [
+ (1, 2),
+ pytest.mark.xfail("sys.version_info > (0, 0, 0)", reason="some bug", strict={strict})((2, 3)),
+ (3, 4),
+ ])
+ def test_increment(n, expected):
+ assert n + 1 == expected
+ """.format(strict=strict)
+ testdir.makepyfile(s)
+ reprec = testdir.inline_run()
+ passed, failed = (2, 1) if strict else (3, 0)
+ reprec.assertoutcome(passed=passed, failed=failed)
+
+ def test_parametrize_called_in_generate_tests(self, testdir):
+ s = """
+ import pytest
+
+
+ def pytest_generate_tests(metafunc):
+ passingTestData = [(1, 2),
+ (2, 3)]
+ failingTestData = [(1, 3),
+ (2, 2)]
+
+ testData = passingTestData + [pytest.mark.xfail(d)
+ for d in failingTestData]
+ metafunc.parametrize(("n", "expected"), testData)
+
+
+ def test_increment(n, expected):
+ assert n + 1 == expected
+ """
+ testdir.makepyfile(s)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=2, skipped=2)
+
+ @pytest.mark.issue290
+ def test_parametrize_ID_generation_string_int_works(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture
+ def myfixture():
+ return 'example'
+ @pytest.mark.parametrize(
+ 'limit', (0, '0'))
+ def test_limit(limit, myfixture):
+ return
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=2)
+
+ @pytest.mark.parametrize('strict', [True, False])
+ def test_parametrize_marked_value(self, testdir, strict):
+ s = """
+ import pytest
+
+ @pytest.mark.parametrize(("n", "expected"), [
+ pytest.param(
+ 2,3,
+ marks=pytest.mark.xfail("sys.version_info > (0, 0, 0)", reason="some bug", strict={strict}),
+ ),
+ pytest.param(
+ 2,3,
+ marks=[pytest.mark.xfail("sys.version_info > (0, 0, 0)", reason="some bug", strict={strict})],
+ ),
+ ])
+ def test_increment(n, expected):
+ assert n + 1 == expected
+ """.format(strict=strict)
+ testdir.makepyfile(s)
+ reprec = testdir.inline_run()
+ passed, failed = (0, 2) if strict else (2, 0)
+ reprec.assertoutcome(passed=passed, failed=failed)
+
+ def test_pytest_make_parametrize_id(self, testdir):
+ testdir.makeconftest("""
+ def pytest_make_parametrize_id(config, val):
+ return str(val * 2)
+ """)
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.mark.parametrize("x", range(2))
+ def test_func(x):
+ pass
+ """)
+ result = testdir.runpytest("-v")
+ result.stdout.fnmatch_lines([
+ "*test_func*0*PASS*",
+ "*test_func*2*PASS*",
+ ])
+
+ def test_pytest_make_parametrize_id_with_argname(self, testdir):
+ testdir.makeconftest("""
+ def pytest_make_parametrize_id(config, val, argname):
+ return str(val * 2 if argname == 'x' else val * 10)
+ """)
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.mark.parametrize("x", range(2))
+ def test_func_a(x):
+ pass
+
+ @pytest.mark.parametrize("y", [1])
+ def test_func_b(y):
+ pass
+ """)
+ result = testdir.runpytest("-v")
+ result.stdout.fnmatch_lines([
+ "*test_func_a*0*PASS*",
+ "*test_func_a*2*PASS*",
+ "*test_func_b*10*PASS*",
+ ])
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/raises.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/raises.py
new file mode 100644
index 00000000000..321ee349ee6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/raises.py
@@ -0,0 +1,134 @@
+import pytest
+import sys
+
+
+class TestRaises(object):
+ def test_raises(self):
+ source = "int('qwe')"
+ excinfo = pytest.raises(ValueError, source)
+ code = excinfo.traceback[-1].frame.code
+ s = str(code.fullsource)
+ assert s == source
+
+ def test_raises_exec(self):
+ pytest.raises(ValueError, "a,x = []")
+
+ def test_raises_syntax_error(self):
+ pytest.raises(SyntaxError, "qwe qwe qwe")
+
+ def test_raises_function(self):
+ pytest.raises(ValueError, int, 'hello')
+
+ def test_raises_callable_no_exception(self):
+ class A(object):
+ def __call__(self):
+ pass
+ try:
+ pytest.raises(ValueError, A())
+ except pytest.raises.Exception:
+ pass
+
+ def test_raises_as_contextmanager(self, testdir):
+ testdir.makepyfile("""
+ from __future__ import with_statement
+ import py, pytest
+ import _pytest._code
+
+ def test_simple():
+ with pytest.raises(ZeroDivisionError) as excinfo:
+ assert isinstance(excinfo, _pytest._code.ExceptionInfo)
+ 1/0
+ print (excinfo)
+ assert excinfo.type == ZeroDivisionError
+ assert isinstance(excinfo.value, ZeroDivisionError)
+
+ def test_noraise():
+ with pytest.raises(pytest.raises.Exception):
+ with pytest.raises(ValueError):
+ int()
+
+ def test_raise_wrong_exception_passes_by():
+ with pytest.raises(ZeroDivisionError):
+ with pytest.raises(ValueError):
+ 1/0
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ '*3 passed*',
+ ])
+
+ def test_noclass(self):
+ with pytest.raises(TypeError):
+ pytest.raises('wrong', lambda: None)
+
+ def test_tuple(self):
+ with pytest.raises((KeyError, ValueError)):
+ raise KeyError('oops')
+
+ def test_no_raise_message(self):
+ try:
+ pytest.raises(ValueError, int, '0')
+ except pytest.raises.Exception as e:
+ assert e.msg == "DID NOT RAISE {0}".format(repr(ValueError))
+ else:
+ assert False, "Expected pytest.raises.Exception"
+
+ try:
+ with pytest.raises(ValueError):
+ pass
+ except pytest.raises.Exception as e:
+ assert e.msg == "DID NOT RAISE {0}".format(repr(ValueError))
+ else:
+ assert False, "Expected pytest.raises.Exception"
+
+ def test_custom_raise_message(self):
+ message = "TEST_MESSAGE"
+ try:
+ with pytest.raises(ValueError, message=message):
+ pass
+ except pytest.raises.Exception as e:
+ assert e.msg == message
+ else:
+ assert False, "Expected pytest.raises.Exception"
+
+ @pytest.mark.parametrize('method', ['function', 'with'])
+ def test_raises_cyclic_reference(self, method):
+ """
+ Ensure pytest.raises does not leave a reference cycle (#1965).
+ """
+ import gc
+
+ class T(object):
+ def __call__(self):
+ raise ValueError
+
+ t = T()
+ if method == 'function':
+ pytest.raises(ValueError, t)
+ else:
+ with pytest.raises(ValueError):
+ t()
+
+ # ensure both forms of pytest.raises don't leave exceptions in sys.exc_info()
+ assert sys.exc_info() == (None, None, None)
+
+ del t
+
+ # ensure the t instance is not stuck in a cyclic reference
+ for o in gc.get_objects():
+ assert type(o) is not T
+
+ def test_raises_match(self):
+ msg = r"with base \d+"
+ with pytest.raises(ValueError, match=msg):
+ int('asdf')
+
+ msg = "with base 10"
+ with pytest.raises(ValueError, match=msg):
+ int('asdf')
+
+ msg = "with base 16"
+ expr = r"Pattern '{0}' not found in 'invalid literal for int\(\) with base 10: 'asdf''".format(msg)
+ with pytest.raises(AssertionError, match=expr):
+ with pytest.raises(ValueError, match=msg):
+ int('asdf', base=10)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/setup_only.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/setup_only.py
new file mode 100644
index 00000000000..ab34312fcc8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/setup_only.py
@@ -0,0 +1,243 @@
+import pytest
+
+
+@pytest.fixture(params=['--setup-only', '--setup-plan', '--setup-show'],
+ scope='module')
+def mode(request):
+ return request.param
+
+
+def test_show_only_active_fixtures(testdir, mode):
+ p = testdir.makepyfile('''
+ import pytest
+ @pytest.fixture
+ def _arg0():
+ """hidden arg0 fixture"""
+ @pytest.fixture
+ def arg1():
+ """arg1 docstring"""
+ def test_arg1(arg1):
+ pass
+ ''')
+
+ result = testdir.runpytest(mode, p)
+ assert result.ret == 0
+
+ result.stdout.fnmatch_lines([
+ '*SETUP F arg1*',
+ '*test_arg1 (fixtures used: arg1)*',
+ '*TEARDOWN F arg1*',
+ ])
+ assert "_arg0" not in result.stdout.str()
+
+
+def test_show_different_scopes(testdir, mode):
+ p = testdir.makepyfile('''
+ import pytest
+ @pytest.fixture
+ def arg_function():
+ """function scoped fixture"""
+ @pytest.fixture(scope='session')
+ def arg_session():
+ """session scoped fixture"""
+ def test_arg1(arg_session, arg_function):
+ pass
+ ''')
+
+ result = testdir.runpytest(mode, p)
+ assert result.ret == 0
+
+ result.stdout.fnmatch_lines([
+ 'SETUP S arg_session*',
+ '*SETUP F arg_function*',
+ '*test_arg1 (fixtures used: arg_function, arg_session)*',
+ '*TEARDOWN F arg_function*',
+ 'TEARDOWN S arg_session*',
+ ])
+
+
+def test_show_nested_fixtures(testdir, mode):
+ testdir.makeconftest('''
+ import pytest
+ @pytest.fixture(scope='session')
+ def arg_same():
+ """session scoped fixture"""
+ ''')
+ p = testdir.makepyfile('''
+ import pytest
+ @pytest.fixture(scope='function')
+ def arg_same(arg_same):
+ """function scoped fixture"""
+ def test_arg1(arg_same):
+ pass
+ ''')
+
+ result = testdir.runpytest(mode, p)
+ assert result.ret == 0
+
+ result.stdout.fnmatch_lines([
+ 'SETUP S arg_same*',
+ '*SETUP F arg_same (fixtures used: arg_same)*',
+ '*test_arg1 (fixtures used: arg_same)*',
+ '*TEARDOWN F arg_same*',
+ 'TEARDOWN S arg_same*',
+ ])
+
+
+def test_show_fixtures_with_autouse(testdir, mode):
+ p = testdir.makepyfile('''
+ import pytest
+ @pytest.fixture
+ def arg_function():
+ """function scoped fixture"""
+ @pytest.fixture(scope='session', autouse=True)
+ def arg_session():
+ """session scoped fixture"""
+ def test_arg1(arg_function):
+ pass
+ ''')
+
+ result = testdir.runpytest(mode, p)
+ assert result.ret == 0
+
+ result.stdout.fnmatch_lines([
+ 'SETUP S arg_session*',
+ '*SETUP F arg_function*',
+ '*test_arg1 (fixtures used: arg_function, arg_session)*',
+ ])
+
+
+def test_show_fixtures_with_parameters(testdir, mode):
+ testdir.makeconftest('''
+ import pytest
+ @pytest.fixture(scope='session', params=['foo', 'bar'])
+ def arg_same():
+ """session scoped fixture"""
+ ''')
+ p = testdir.makepyfile('''
+ import pytest
+ @pytest.fixture(scope='function')
+ def arg_other(arg_same):
+ """function scoped fixture"""
+ def test_arg1(arg_other):
+ pass
+ ''')
+
+ result = testdir.runpytest(mode, p)
+ assert result.ret == 0
+
+ result.stdout.fnmatch_lines([
+ 'SETUP S arg_same?foo?',
+ 'TEARDOWN S arg_same?foo?',
+ 'SETUP S arg_same?bar?',
+ 'TEARDOWN S arg_same?bar?',
+ ])
+
+
+def test_show_fixtures_with_parameter_ids(testdir, mode):
+ testdir.makeconftest('''
+ import pytest
+ @pytest.fixture(
+ scope='session', params=['foo', 'bar'], ids=['spam', 'ham'])
+ def arg_same():
+ """session scoped fixture"""
+ ''')
+ p = testdir.makepyfile('''
+ import pytest
+ @pytest.fixture(scope='function')
+ def arg_other(arg_same):
+ """function scoped fixture"""
+ def test_arg1(arg_other):
+ pass
+ ''')
+
+ result = testdir.runpytest(mode, p)
+ assert result.ret == 0
+
+ result.stdout.fnmatch_lines([
+ 'SETUP S arg_same?spam?',
+ 'SETUP S arg_same?ham?',
+ ])
+
+
+def test_show_fixtures_with_parameter_ids_function(testdir, mode):
+ p = testdir.makepyfile('''
+ import pytest
+ @pytest.fixture(params=['foo', 'bar'], ids=lambda p: p.upper())
+ def foobar():
+ pass
+ def test_foobar(foobar):
+ pass
+ ''')
+
+ result = testdir.runpytest(mode, p)
+ assert result.ret == 0
+
+ result.stdout.fnmatch_lines([
+ '*SETUP F foobar?FOO?',
+ '*SETUP F foobar?BAR?',
+ ])
+
+
+def test_dynamic_fixture_request(testdir):
+ p = testdir.makepyfile('''
+ import pytest
+ @pytest.fixture()
+ def dynamically_requested_fixture():
+ pass
+ @pytest.fixture()
+ def dependent_fixture(request):
+ request.getfixturevalue('dynamically_requested_fixture')
+ def test_dyn(dependent_fixture):
+ pass
+ ''')
+
+ result = testdir.runpytest('--setup-only', p)
+ assert result.ret == 0
+
+ result.stdout.fnmatch_lines([
+ '*SETUP F dynamically_requested_fixture',
+ '*TEARDOWN F dynamically_requested_fixture'
+ ])
+
+
+def test_capturing(testdir):
+ p = testdir.makepyfile('''
+ import pytest, sys
+ @pytest.fixture()
+ def one():
+ sys.stdout.write('this should be captured')
+ sys.stderr.write('this should also be captured')
+ @pytest.fixture()
+ def two(one):
+ assert 0
+ def test_capturing(two):
+ pass
+ ''')
+
+ result = testdir.runpytest('--setup-only', p)
+ result.stdout.fnmatch_lines([
+ 'this should be captured',
+ 'this should also be captured'
+ ])
+
+
+def test_show_fixtures_and_execute_test(testdir):
+ """ Verifies that setups are shown and tests are executed. """
+ p = testdir.makepyfile('''
+ import pytest
+ @pytest.fixture
+ def arg():
+ assert True
+ def test_arg(arg):
+ assert False
+ ''')
+
+ result = testdir.runpytest("--setup-show", p)
+ assert result.ret == 1
+
+ result.stdout.fnmatch_lines([
+ '*SETUP F arg*',
+ '*test_arg (fixtures used: arg)F*',
+ '*TEARDOWN F arg*',
+ ])
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/setup_plan.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/setup_plan.py
new file mode 100644
index 00000000000..8c98224692a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/setup_plan.py
@@ -0,0 +1,19 @@
+def test_show_fixtures_and_test(testdir):
+ """ Verifies that fixtures are not executed. """
+ p = testdir.makepyfile('''
+ import pytest
+ @pytest.fixture
+ def arg():
+ assert False
+ def test_arg(arg):
+ assert False
+ ''')
+
+ result = testdir.runpytest("--setup-plan", p)
+ assert result.ret == 0
+
+ result.stdout.fnmatch_lines([
+ '*SETUP F arg*',
+ '*test_arg (fixtures used: arg)',
+ '*TEARDOWN F arg*',
+ ])
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/show_fixtures_per_test.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/show_fixtures_per_test.py
new file mode 100644
index 00000000000..741f33946a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/show_fixtures_per_test.py
@@ -0,0 +1,158 @@
+# -*- coding: utf-8 -*-
+
+
+def test_no_items_should_not_show_output(testdir):
+ result = testdir.runpytest('--fixtures-per-test')
+ assert 'fixtures used by' not in result.stdout.str()
+ assert result.ret == 0
+
+
+def test_fixtures_in_module(testdir):
+ p = testdir.makepyfile('''
+ import pytest
+ @pytest.fixture
+ def _arg0():
+ """hidden arg0 fixture"""
+ @pytest.fixture
+ def arg1():
+ """arg1 docstring"""
+ def test_arg1(arg1):
+ pass
+ ''')
+
+ result = testdir.runpytest("--fixtures-per-test", p)
+ assert result.ret == 0
+
+ result.stdout.fnmatch_lines([
+ '*fixtures used by test_arg1*',
+ '*(test_fixtures_in_module.py:9)*',
+ 'arg1',
+ ' arg1 docstring',
+ ])
+ assert "_arg0" not in result.stdout.str()
+
+
+def test_fixtures_in_conftest(testdir):
+ testdir.makeconftest('''
+ import pytest
+ @pytest.fixture
+ def arg1():
+ """arg1 docstring"""
+ @pytest.fixture
+ def arg2():
+ """arg2 docstring"""
+ @pytest.fixture
+ def arg3(arg1, arg2):
+ """arg3
+ docstring
+ """
+ ''')
+ p = testdir.makepyfile('''
+ def test_arg2(arg2):
+ pass
+ def test_arg3(arg3):
+ pass
+ ''')
+ result = testdir.runpytest("--fixtures-per-test", p)
+ assert result.ret == 0
+
+ result.stdout.fnmatch_lines([
+ '*fixtures used by test_arg2*',
+ '*(test_fixtures_in_conftest.py:2)*',
+ 'arg2',
+ ' arg2 docstring',
+ '*fixtures used by test_arg3*',
+ '*(test_fixtures_in_conftest.py:4)*',
+ 'arg1',
+ ' arg1 docstring',
+ 'arg2',
+ ' arg2 docstring',
+ 'arg3',
+ ' arg3',
+ ' docstring',
+ ])
+
+
+def test_should_show_fixtures_used_by_test(testdir):
+ testdir.makeconftest('''
+ import pytest
+ @pytest.fixture
+ def arg1():
+ """arg1 from conftest"""
+ @pytest.fixture
+ def arg2():
+ """arg2 from conftest"""
+ ''')
+ p = testdir.makepyfile('''
+ import pytest
+ @pytest.fixture
+ def arg1():
+ """arg1 from testmodule"""
+ def test_args(arg1, arg2):
+ pass
+ ''')
+ result = testdir.runpytest("--fixtures-per-test", p)
+ assert result.ret == 0
+
+ result.stdout.fnmatch_lines([
+ '*fixtures used by test_args*',
+ '*(test_should_show_fixtures_used_by_test.py:6)*',
+ 'arg1',
+ ' arg1 from testmodule',
+ 'arg2',
+ ' arg2 from conftest',
+ ])
+
+
+def test_verbose_include_private_fixtures_and_loc(testdir):
+ testdir.makeconftest('''
+ import pytest
+ @pytest.fixture
+ def _arg1():
+ """_arg1 from conftest"""
+ @pytest.fixture
+ def arg2(_arg1):
+ """arg2 from conftest"""
+ ''')
+ p = testdir.makepyfile('''
+ import pytest
+ @pytest.fixture
+ def arg3():
+ """arg3 from testmodule"""
+ def test_args(arg2, arg3):
+ pass
+ ''')
+ result = testdir.runpytest("--fixtures-per-test", "-v", p)
+ assert result.ret == 0
+
+ result.stdout.fnmatch_lines([
+ '*fixtures used by test_args*',
+ '*(test_verbose_include_private_fixtures_and_loc.py:6)*',
+ '_arg1 -- conftest.py:3',
+ ' _arg1 from conftest',
+ 'arg2 -- conftest.py:6',
+ ' arg2 from conftest',
+ 'arg3 -- test_verbose_include_private_fixtures_and_loc.py:3',
+ ' arg3 from testmodule',
+ ])
+
+
+def test_doctest_items(testdir):
+ testdir.makepyfile('''
+ def foo():
+ """
+ >>> 1 + 1
+ 2
+ """
+ ''')
+ testdir.maketxtfile('''
+ >>> 1 + 1
+ 2
+ ''')
+ result = testdir.runpytest("--fixtures-per-test", "--doctest-modules",
+ "--doctest-glob=*.txt", "-v")
+ assert result.ret == 0
+
+ result.stdout.fnmatch_lines([
+ '*collected 2 items*',
+ ])
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/test_deprecations.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/test_deprecations.py
new file mode 100644
index 00000000000..5001f765f6c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/python/test_deprecations.py
@@ -0,0 +1,22 @@
+import pytest
+
+from _pytest.python import PyCollector
+
+
+class PyCollectorMock(PyCollector):
+ """evil hack"""
+
+ def __init__(self):
+ self.called = False
+
+ def _makeitem(self, *k):
+ """hack to disable the actual behaviour"""
+ self.called = True
+
+
+def test_pycollector_makeitem_is_deprecated():
+
+ collector = PyCollectorMock()
+ with pytest.deprecated_call():
+ collector.makeitem('foo', 'bar')
+ assert collector.called
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_argcomplete.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_argcomplete.py
new file mode 100644
index 00000000000..c9261257743
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_argcomplete.py
@@ -0,0 +1,97 @@
+from __future__ import absolute_import, division, print_function
+import py
+import pytest
+
+# test for _argcomplete but not specific for any application
+
+
+def equal_with_bash(prefix, ffc, fc, out=None):
+ res = ffc(prefix)
+ res_bash = set(fc(prefix))
+ retval = set(res) == res_bash
+ if out:
+ out.write('equal_with_bash %s %s\n' % (retval, res))
+ if not retval:
+ out.write(' python - bash: %s\n' % (set(res) - res_bash))
+ out.write(' bash - python: %s\n' % (res_bash - set(res)))
+ return retval
+
+# copied from argcomplete.completers as import from there
+# also pulls in argcomplete.__init__ which opens filedescriptor 9
+# this gives an IOError at the end of testrun
+
+
+def _wrapcall(*args, **kargs):
+ try:
+ if py.std.sys.version_info > (2, 7):
+ return py.std.subprocess.check_output(*args, **kargs).decode().splitlines()
+ if 'stdout' in kargs:
+ raise ValueError('stdout argument not allowed, it will be overridden.')
+ process = py.std.subprocess.Popen(
+ stdout=py.std.subprocess.PIPE, *args, **kargs)
+ output, unused_err = process.communicate()
+ retcode = process.poll()
+ if retcode:
+ cmd = kargs.get("args")
+ if cmd is None:
+ cmd = args[0]
+ raise py.std.subprocess.CalledProcessError(retcode, cmd)
+ return output.decode().splitlines()
+ except py.std.subprocess.CalledProcessError:
+ return []
+
+
+class FilesCompleter(object):
+ 'File completer class, optionally takes a list of allowed extensions'
+
+ def __init__(self, allowednames=(), directories=True):
+ # Fix if someone passes in a string instead of a list
+ if type(allowednames) is str:
+ allowednames = [allowednames]
+
+ self.allowednames = [x.lstrip('*').lstrip('.') for x in allowednames]
+ self.directories = directories
+
+ def __call__(self, prefix, **kwargs):
+ completion = []
+ if self.allowednames:
+ if self.directories:
+ files = _wrapcall(['bash', '-c',
+ "compgen -A directory -- '{p}'".format(p=prefix)])
+ completion += [f + '/' for f in files]
+ for x in self.allowednames:
+ completion += _wrapcall(['bash', '-c',
+ "compgen -A file -X '!*.{0}' -- '{p}'".format(x, p=prefix)])
+ else:
+ completion += _wrapcall(['bash', '-c',
+ "compgen -A file -- '{p}'".format(p=prefix)])
+
+ anticomp = _wrapcall(['bash', '-c',
+ "compgen -A directory -- '{p}'".format(p=prefix)])
+
+ completion = list(set(completion) - set(anticomp))
+
+ if self.directories:
+ completion += [f + '/' for f in anticomp]
+ return completion
+
+
+class TestArgComplete(object):
+ @pytest.mark.skipif("sys.platform in ('win32', 'darwin')")
+ def test_compare_with_compgen(self):
+ from _pytest._argcomplete import FastFilesCompleter
+ ffc = FastFilesCompleter()
+ fc = FilesCompleter()
+ for x in ['/', '/d', '/data', 'qqq', '']:
+ assert equal_with_bash(x, ffc, fc, out=py.std.sys.stdout)
+
+ @pytest.mark.skipif("sys.platform in ('win32', 'darwin')")
+ def test_remove_dir_prefix(self):
+ """this is not compatible with compgen but it is with bash itself:
+ ls /usr/<TAB>
+ """
+ from _pytest._argcomplete import FastFilesCompleter
+ ffc = FastFilesCompleter()
+ fc = FilesCompleter()
+ for x in '/usr/'.split():
+ assert not equal_with_bash(x, ffc, fc, out=py.std.sys.stdout)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_assertion.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_assertion.py
new file mode 100644
index 00000000000..328fe7fa918
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_assertion.py
@@ -0,0 +1,1066 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import, division, print_function
+import sys
+import textwrap
+
+import _pytest.assertion as plugin
+import py
+import pytest
+from _pytest.assertion import util
+from _pytest.assertion import truncate
+
+PY3 = sys.version_info >= (3, 0)
+
+
+@pytest.fixture
+def mock_config():
+
+ class Config(object):
+ verbose = False
+
+ def getoption(self, name):
+ if name == 'verbose':
+ return self.verbose
+ raise KeyError('Not mocked out: %s' % name)
+
+ return Config()
+
+
+class TestImportHookInstallation(object):
+
+ @pytest.mark.parametrize('initial_conftest', [True, False])
+ @pytest.mark.parametrize('mode', ['plain', 'rewrite'])
+ def test_conftest_assertion_rewrite(self, testdir, initial_conftest, mode):
+ """Test that conftest files are using assertion rewrite on import.
+ (#1619)
+ """
+ testdir.tmpdir.join('foo/tests').ensure(dir=1)
+ conftest_path = 'conftest.py' if initial_conftest else 'foo/conftest.py'
+ contents = {
+ conftest_path: """
+ import pytest
+ @pytest.fixture
+ def check_first():
+ def check(values, value):
+ assert values.pop(0) == value
+ return check
+ """,
+ 'foo/tests/test_foo.py': """
+ def test(check_first):
+ check_first([10, 30], 30)
+ """
+ }
+ testdir.makepyfile(**contents)
+ result = testdir.runpytest_subprocess('--assert=%s' % mode)
+ if mode == 'plain':
+ expected = 'E AssertionError'
+ elif mode == 'rewrite':
+ expected = '*assert 10 == 30*'
+ else:
+ assert 0
+ result.stdout.fnmatch_lines([expected])
+
+ def test_rewrite_assertions_pytester_plugin(self, testdir):
+ """
+ Assertions in the pytester plugin must also benefit from assertion
+ rewriting (#1920).
+ """
+ testdir.makepyfile("""
+ pytest_plugins = ['pytester']
+ def test_dummy_failure(testdir): # how meta!
+ testdir.makepyfile('def test(): assert 0')
+ r = testdir.inline_run()
+ r.assertoutcome(passed=1)
+ """)
+ result = testdir.runpytest_subprocess()
+ result.stdout.fnmatch_lines([
+ '*assert 1 == 0*',
+ ])
+
+ @pytest.mark.parametrize('mode', ['plain', 'rewrite'])
+ def test_pytest_plugins_rewrite(self, testdir, mode):
+ contents = {
+ 'conftest.py': """
+ pytest_plugins = ['ham']
+ """,
+ 'ham.py': """
+ import pytest
+ @pytest.fixture
+ def check_first():
+ def check(values, value):
+ assert values.pop(0) == value
+ return check
+ """,
+ 'test_foo.py': """
+ def test_foo(check_first):
+ check_first([10, 30], 30)
+ """,
+ }
+ testdir.makepyfile(**contents)
+ result = testdir.runpytest_subprocess('--assert=%s' % mode)
+ if mode == 'plain':
+ expected = 'E AssertionError'
+ elif mode == 'rewrite':
+ expected = '*assert 10 == 30*'
+ else:
+ assert 0
+ result.stdout.fnmatch_lines([expected])
+
+ @pytest.mark.parametrize('mode', ['str', 'list'])
+ def test_pytest_plugins_rewrite_module_names(self, testdir, mode):
+ """Test that pluginmanager correct marks pytest_plugins variables
+ for assertion rewriting if they are defined as plain strings or
+ list of strings (#1888).
+ """
+ plugins = '"ham"' if mode == 'str' else '["ham"]'
+ contents = {
+ 'conftest.py': """
+ pytest_plugins = {plugins}
+ """.format(plugins=plugins),
+ 'ham.py': """
+ import pytest
+ """,
+ 'test_foo.py': """
+ def test_foo(pytestconfig):
+ assert 'ham' in pytestconfig.pluginmanager.rewrite_hook._must_rewrite
+ """,
+ }
+ testdir.makepyfile(**contents)
+ result = testdir.runpytest_subprocess('--assert=rewrite')
+ assert result.ret == 0
+
+ def test_pytest_plugins_rewrite_module_names_correctly(self, testdir):
+ """Test that we match files correctly when they are marked for rewriting (#2939)."""
+ contents = {
+ 'conftest.py': """
+ pytest_plugins = "ham"
+ """,
+ 'ham.py': "",
+ 'hamster.py': "",
+ 'test_foo.py': """
+ def test_foo(pytestconfig):
+ assert pytestconfig.pluginmanager.rewrite_hook.find_module('ham') is not None
+ assert pytestconfig.pluginmanager.rewrite_hook.find_module('hamster') is None
+ """,
+ }
+ testdir.makepyfile(**contents)
+ result = testdir.runpytest_subprocess('--assert=rewrite')
+ assert result.ret == 0
+
+ @pytest.mark.parametrize('mode', ['plain', 'rewrite'])
+ @pytest.mark.parametrize('plugin_state', ['development', 'installed'])
+ def test_installed_plugin_rewrite(self, testdir, mode, plugin_state):
+ # Make sure the hook is installed early enough so that plugins
+ # installed via setuptools are rewritten.
+ testdir.tmpdir.join('hampkg').ensure(dir=1)
+ contents = {
+ 'hampkg/__init__.py': """
+ import pytest
+
+ @pytest.fixture
+ def check_first2():
+ def check(values, value):
+ assert values.pop(0) == value
+ return check
+ """,
+ 'spamplugin.py': """
+ import pytest
+ from hampkg import check_first2
+
+ @pytest.fixture
+ def check_first():
+ def check(values, value):
+ assert values.pop(0) == value
+ return check
+ """,
+ 'mainwrapper.py': """
+ import pytest, pkg_resources
+
+ plugin_state = "{plugin_state}"
+
+ class DummyDistInfo(object):
+ project_name = 'spam'
+ version = '1.0'
+
+ def _get_metadata(self, name):
+ # 'RECORD' meta-data only available in installed plugins
+ if name == 'RECORD' and plugin_state == "installed":
+ return ['spamplugin.py,sha256=abc,123',
+ 'hampkg/__init__.py,sha256=abc,123']
+ # 'SOURCES.txt' meta-data only available for plugins in development mode
+ elif name == 'SOURCES.txt' and plugin_state == "development":
+ return ['spamplugin.py',
+ 'hampkg/__init__.py']
+ return []
+
+ class DummyEntryPoint(object):
+ name = 'spam'
+ module_name = 'spam.py'
+ attrs = ()
+ extras = None
+ dist = DummyDistInfo()
+
+ def load(self, require=True, *args, **kwargs):
+ import spamplugin
+ return spamplugin
+
+ def iter_entry_points(name):
+ yield DummyEntryPoint()
+
+ pkg_resources.iter_entry_points = iter_entry_points
+ pytest.main()
+ """.format(plugin_state=plugin_state),
+ 'test_foo.py': """
+ def test(check_first):
+ check_first([10, 30], 30)
+
+ def test2(check_first2):
+ check_first([10, 30], 30)
+ """,
+ }
+ testdir.makepyfile(**contents)
+ result = testdir.run(sys.executable, 'mainwrapper.py', '-s', '--assert=%s' % mode)
+ if mode == 'plain':
+ expected = 'E AssertionError'
+ elif mode == 'rewrite':
+ expected = '*assert 10 == 30*'
+ else:
+ assert 0
+ result.stdout.fnmatch_lines([expected])
+
+ def test_rewrite_ast(self, testdir):
+ testdir.tmpdir.join('pkg').ensure(dir=1)
+ contents = {
+ 'pkg/__init__.py': """
+ import pytest
+ pytest.register_assert_rewrite('pkg.helper')
+ """,
+ 'pkg/helper.py': """
+ def tool():
+ a, b = 2, 3
+ assert a == b
+ """,
+ 'pkg/plugin.py': """
+ import pytest, pkg.helper
+ @pytest.fixture
+ def tool():
+ return pkg.helper.tool
+ """,
+ 'pkg/other.py': """
+ values = [3, 2]
+ def tool():
+ assert values.pop() == 3
+ """,
+ 'conftest.py': """
+ pytest_plugins = ['pkg.plugin']
+ """,
+ 'test_pkg.py': """
+ import pkg.other
+ def test_tool(tool):
+ tool()
+ def test_other():
+ pkg.other.tool()
+ """,
+ }
+ testdir.makepyfile(**contents)
+ result = testdir.runpytest_subprocess('--assert=rewrite')
+ result.stdout.fnmatch_lines(['>*assert a == b*',
+ 'E*assert 2 == 3*',
+ '>*assert values.pop() == 3*',
+ 'E*AssertionError'])
+
+ def test_register_assert_rewrite_checks_types(self):
+ with pytest.raises(TypeError):
+ pytest.register_assert_rewrite(['pytest_tests_internal_non_existing'])
+ pytest.register_assert_rewrite('pytest_tests_internal_non_existing',
+ 'pytest_tests_internal_non_existing2')
+
+
+class TestBinReprIntegration(object):
+
+ def test_pytest_assertrepr_compare_called(self, testdir):
+ testdir.makeconftest("""
+ import pytest
+ values = []
+ def pytest_assertrepr_compare(op, left, right):
+ values.append((op, left, right))
+
+ @pytest.fixture
+ def list(request):
+ return values
+ """)
+ testdir.makepyfile("""
+ def test_hello():
+ assert 0 == 1
+ def test_check(list):
+ assert list == [("==", 0, 1)]
+ """)
+ result = testdir.runpytest("-v")
+ result.stdout.fnmatch_lines([
+ "*test_hello*FAIL*",
+ "*test_check*PASS*",
+ ])
+
+
+def callequal(left, right, verbose=False):
+ config = mock_config()
+ config.verbose = verbose
+ return plugin.pytest_assertrepr_compare(config, '==', left, right)
+
+
+class TestAssert_reprcompare(object):
+ def test_different_types(self):
+ assert callequal([0, 1], 'foo') is None
+
+ def test_summary(self):
+ summary = callequal([0, 1], [0, 2])[0]
+ assert len(summary) < 65
+
+ def test_text_diff(self):
+ diff = callequal('spam', 'eggs')[1:]
+ assert '- spam' in diff
+ assert '+ eggs' in diff
+
+ def test_text_skipping(self):
+ lines = callequal('a' * 50 + 'spam', 'a' * 50 + 'eggs')
+ assert 'Skipping' in lines[1]
+ for line in lines:
+ assert 'a' * 50 not in line
+
+ def test_text_skipping_verbose(self):
+ lines = callequal('a' * 50 + 'spam', 'a' * 50 + 'eggs', verbose=True)
+ assert '- ' + 'a' * 50 + 'spam' in lines
+ assert '+ ' + 'a' * 50 + 'eggs' in lines
+
+ def test_multiline_text_diff(self):
+ left = 'foo\nspam\nbar'
+ right = 'foo\neggs\nbar'
+ diff = callequal(left, right)
+ assert '- spam' in diff
+ assert '+ eggs' in diff
+
+ def test_list(self):
+ expl = callequal([0, 1], [0, 2])
+ assert len(expl) > 1
+
+ @pytest.mark.parametrize(
+ ['left', 'right', 'expected'], [
+ ([0, 1], [0, 2], """
+ Full diff:
+ - [0, 1]
+ ? ^
+ + [0, 2]
+ ? ^
+ """),
+ ({0: 1}, {0: 2}, """
+ Full diff:
+ - {0: 1}
+ ? ^
+ + {0: 2}
+ ? ^
+ """),
+ (set([0, 1]), set([0, 2]), """
+ Full diff:
+ - set([0, 1])
+ ? ^
+ + set([0, 2])
+ ? ^
+ """ if not PY3 else """
+ Full diff:
+ - {0, 1}
+ ? ^
+ + {0, 2}
+ ? ^
+ """)
+ ]
+ )
+ def test_iterable_full_diff(self, left, right, expected):
+ """Test the full diff assertion failure explanation.
+
+ When verbose is False, then just a -v notice to get the diff is rendered,
+ when verbose is True, then ndiff of the pprint is returned.
+ """
+ expl = callequal(left, right, verbose=False)
+ assert expl[-1] == 'Use -v to get the full diff'
+ expl = '\n'.join(callequal(left, right, verbose=True))
+ assert expl.endswith(textwrap.dedent(expected).strip())
+
+ def test_list_different_lengths(self):
+ expl = callequal([0, 1], [0, 1, 2])
+ assert len(expl) > 1
+ expl = callequal([0, 1, 2], [0, 1])
+ assert len(expl) > 1
+
+ def test_dict(self):
+ expl = callequal({'a': 0}, {'a': 1})
+ assert len(expl) > 1
+
+ def test_dict_omitting(self):
+ lines = callequal({'a': 0, 'b': 1}, {'a': 1, 'b': 1})
+ assert lines[1].startswith('Omitting 1 identical item')
+ assert 'Common items' not in lines
+ for line in lines[1:]:
+ assert 'b' not in line
+
+ def test_dict_omitting_with_verbosity_1(self):
+ """ Ensure differing items are visible for verbosity=1 (#1512) """
+ lines = callequal({'a': 0, 'b': 1}, {'a': 1, 'b': 1}, verbose=1)
+ assert lines[1].startswith('Omitting 1 identical item')
+ assert lines[2].startswith('Differing items')
+ assert lines[3] == "{'a': 0} != {'a': 1}"
+ assert 'Common items' not in lines
+
+ def test_dict_omitting_with_verbosity_2(self):
+ lines = callequal({'a': 0, 'b': 1}, {'a': 1, 'b': 1}, verbose=2)
+ assert lines[1].startswith('Common items:')
+ assert 'Omitting' not in lines[1]
+ assert lines[2] == "{'b': 1}"
+
+ def test_set(self):
+ expl = callequal(set([0, 1]), set([0, 2]))
+ assert len(expl) > 1
+
+ def test_frozenzet(self):
+ expl = callequal(frozenset([0, 1]), set([0, 2]))
+ assert len(expl) > 1
+
+ def test_Sequence(self):
+ col = py.builtin._tryimport(
+ "collections.abc",
+ "collections",
+ "sys")
+ if not hasattr(col, "MutableSequence"):
+ pytest.skip("cannot import MutableSequence")
+ MutableSequence = col.MutableSequence
+
+ class TestSequence(MutableSequence): # works with a Sequence subclass
+ def __init__(self, iterable):
+ self.elements = list(iterable)
+
+ def __getitem__(self, item):
+ return self.elements[item]
+
+ def __len__(self):
+ return len(self.elements)
+
+ def __setitem__(self, item, value):
+ pass
+
+ def __delitem__(self, item):
+ pass
+
+ def insert(self, item, index):
+ pass
+
+ expl = callequal(TestSequence([0, 1]), list([0, 2]))
+ assert len(expl) > 1
+
+ def test_list_tuples(self):
+ expl = callequal([], [(1, 2)])
+ assert len(expl) > 1
+ expl = callequal([(1, 2)], [])
+ assert len(expl) > 1
+
+ def test_list_bad_repr(self):
+ class A(object):
+ def __repr__(self):
+ raise ValueError(42)
+ expl = callequal([], [A()])
+ assert 'ValueError' in "".join(expl)
+ expl = callequal({}, {'1': A()})
+ assert 'faulty' in "".join(expl)
+
+ def test_one_repr_empty(self):
+ """
+ the faulty empty string repr did trigger
+ a unbound local error in _diff_text
+ """
+ class A(str):
+ def __repr__(self):
+ return ''
+ expl = callequal(A(), '')
+ assert not expl
+
+ def test_repr_no_exc(self):
+ expl = ' '.join(callequal('foo', 'bar'))
+ assert 'raised in repr()' not in expl
+
+ def test_unicode(self):
+ left = py.builtin._totext('£€', 'utf-8')
+ right = py.builtin._totext('£', 'utf-8')
+ expl = callequal(left, right)
+ assert expl[0] == py.builtin._totext("'£€' == '£'", 'utf-8')
+ assert expl[1] == py.builtin._totext('- £€', 'utf-8')
+ assert expl[2] == py.builtin._totext('+ £', 'utf-8')
+
+ def test_nonascii_text(self):
+ """
+ :issue: 877
+ non ascii python2 str caused a UnicodeDecodeError
+ """
+ class A(str):
+ def __repr__(self):
+ return '\xff'
+ expl = callequal(A(), '1')
+ assert expl
+
+ def test_format_nonascii_explanation(self):
+ assert util.format_explanation('λ')
+
+ def test_mojibake(self):
+ # issue 429
+ left = 'e'
+ right = '\xc3\xa9'
+ if not isinstance(left, py.builtin.bytes):
+ left = py.builtin.bytes(left, 'utf-8')
+ right = py.builtin.bytes(right, 'utf-8')
+ expl = callequal(left, right)
+ for line in expl:
+ assert isinstance(line, py.builtin.text)
+ msg = py.builtin._totext('\n').join(expl)
+ assert msg
+
+
+class TestFormatExplanation(object):
+
+ def test_special_chars_full(self, testdir):
+ # Issue 453, for the bug this would raise IndexError
+ testdir.makepyfile("""
+ def test_foo():
+ assert '\\n}' == ''
+ """)
+ result = testdir.runpytest()
+ assert result.ret == 1
+ result.stdout.fnmatch_lines([
+ "*AssertionError*",
+ ])
+
+ def test_fmt_simple(self):
+ expl = 'assert foo'
+ assert util.format_explanation(expl) == 'assert foo'
+
+ def test_fmt_where(self):
+ expl = '\n'.join(['assert 1',
+ '{1 = foo',
+ '} == 2'])
+ res = '\n'.join(['assert 1 == 2',
+ ' + where 1 = foo'])
+ assert util.format_explanation(expl) == res
+
+ def test_fmt_and(self):
+ expl = '\n'.join(['assert 1',
+ '{1 = foo',
+ '} == 2',
+ '{2 = bar',
+ '}'])
+ res = '\n'.join(['assert 1 == 2',
+ ' + where 1 = foo',
+ ' + and 2 = bar'])
+ assert util.format_explanation(expl) == res
+
+ def test_fmt_where_nested(self):
+ expl = '\n'.join(['assert 1',
+ '{1 = foo',
+ '{foo = bar',
+ '}',
+ '} == 2'])
+ res = '\n'.join(['assert 1 == 2',
+ ' + where 1 = foo',
+ ' + where foo = bar'])
+ assert util.format_explanation(expl) == res
+
+ def test_fmt_newline(self):
+ expl = '\n'.join(['assert "foo" == "bar"',
+ '~- foo',
+ '~+ bar'])
+ res = '\n'.join(['assert "foo" == "bar"',
+ ' - foo',
+ ' + bar'])
+ assert util.format_explanation(expl) == res
+
+ def test_fmt_newline_escaped(self):
+ expl = '\n'.join(['assert foo == bar',
+ 'baz'])
+ res = 'assert foo == bar\\nbaz'
+ assert util.format_explanation(expl) == res
+
+ def test_fmt_newline_before_where(self):
+ expl = '\n'.join(['the assertion message here',
+ '>assert 1',
+ '{1 = foo',
+ '} == 2',
+ '{2 = bar',
+ '}'])
+ res = '\n'.join(['the assertion message here',
+ 'assert 1 == 2',
+ ' + where 1 = foo',
+ ' + and 2 = bar'])
+ assert util.format_explanation(expl) == res
+
+ def test_fmt_multi_newline_before_where(self):
+ expl = '\n'.join(['the assertion',
+ '~message here',
+ '>assert 1',
+ '{1 = foo',
+ '} == 2',
+ '{2 = bar',
+ '}'])
+ res = '\n'.join(['the assertion',
+ ' message here',
+ 'assert 1 == 2',
+ ' + where 1 = foo',
+ ' + and 2 = bar'])
+ assert util.format_explanation(expl) == res
+
+
+class TestTruncateExplanation(object):
+
+ """ Confirm assertion output is truncated as expected """
+
+ # The number of lines in the truncation explanation message. Used
+ # to calculate that results have the expected length.
+ LINES_IN_TRUNCATION_MSG = 2
+
+ def test_doesnt_truncate_when_input_is_empty_list(self):
+ expl = []
+ result = truncate._truncate_explanation(expl, max_lines=8, max_chars=100)
+ assert result == expl
+
+ def test_doesnt_truncate_at_when_input_is_5_lines_and_LT_max_chars(self):
+ expl = ['a' * 100 for x in range(5)]
+ result = truncate._truncate_explanation(expl, max_lines=8, max_chars=8 * 80)
+ assert result == expl
+
+ def test_truncates_at_8_lines_when_given_list_of_empty_strings(self):
+ expl = ['' for x in range(50)]
+ result = truncate._truncate_explanation(expl, max_lines=8, max_chars=100)
+ assert result != expl
+ assert len(result) == 8 + self.LINES_IN_TRUNCATION_MSG
+ assert "Full output truncated" in result[-1]
+ assert "43 lines hidden" in result[-1]
+ last_line_before_trunc_msg = result[- self.LINES_IN_TRUNCATION_MSG - 1]
+ assert last_line_before_trunc_msg.endswith("...")
+
+ def test_truncates_at_8_lines_when_first_8_lines_are_LT_max_chars(self):
+ expl = ['a' for x in range(100)]
+ result = truncate._truncate_explanation(expl, max_lines=8, max_chars=8 * 80)
+ assert result != expl
+ assert len(result) == 8 + self.LINES_IN_TRUNCATION_MSG
+ assert "Full output truncated" in result[-1]
+ assert "93 lines hidden" in result[-1]
+ last_line_before_trunc_msg = result[- self.LINES_IN_TRUNCATION_MSG - 1]
+ assert last_line_before_trunc_msg.endswith("...")
+
+ def test_truncates_at_8_lines_when_first_8_lines_are_EQ_max_chars(self):
+ expl = ['a' * 80 for x in range(16)]
+ result = truncate._truncate_explanation(expl, max_lines=8, max_chars=8 * 80)
+ assert result != expl
+ assert len(result) == 8 + self.LINES_IN_TRUNCATION_MSG
+ assert "Full output truncated" in result[-1]
+ assert "9 lines hidden" in result[-1]
+ last_line_before_trunc_msg = result[- self.LINES_IN_TRUNCATION_MSG - 1]
+ assert last_line_before_trunc_msg.endswith("...")
+
+ def test_truncates_at_4_lines_when_first_4_lines_are_GT_max_chars(self):
+ expl = ['a' * 250 for x in range(10)]
+ result = truncate._truncate_explanation(expl, max_lines=8, max_chars=999)
+ assert result != expl
+ assert len(result) == 4 + self.LINES_IN_TRUNCATION_MSG
+ assert "Full output truncated" in result[-1]
+ assert "7 lines hidden" in result[-1]
+ last_line_before_trunc_msg = result[- self.LINES_IN_TRUNCATION_MSG - 1]
+ assert last_line_before_trunc_msg.endswith("...")
+
+ def test_truncates_at_1_line_when_first_line_is_GT_max_chars(self):
+ expl = ['a' * 250 for x in range(1000)]
+ result = truncate._truncate_explanation(expl, max_lines=8, max_chars=100)
+ assert result != expl
+ assert len(result) == 1 + self.LINES_IN_TRUNCATION_MSG
+ assert "Full output truncated" in result[-1]
+ assert "1000 lines hidden" in result[-1]
+ last_line_before_trunc_msg = result[- self.LINES_IN_TRUNCATION_MSG - 1]
+ assert last_line_before_trunc_msg.endswith("...")
+
+ def test_full_output_truncated(self, monkeypatch, testdir):
+ """ Test against full runpytest() output. """
+
+ line_count = 7
+ line_len = 100
+ expected_truncated_lines = 2
+ testdir.makepyfile(r"""
+ def test_many_lines():
+ a = list([str(i)[0] * %d for i in range(%d)])
+ b = a[::2]
+ a = '\n'.join(map(str, a))
+ b = '\n'.join(map(str, b))
+ assert a == b
+ """ % (line_len, line_count))
+ monkeypatch.delenv('CI', raising=False)
+
+ result = testdir.runpytest()
+ # without -vv, truncate the message showing a few diff lines only
+ result.stdout.fnmatch_lines([
+ "*- 1*",
+ "*- 3*",
+ "*- 5*",
+ "*truncated (%d lines hidden)*use*-vv*" % expected_truncated_lines,
+ ])
+
+ result = testdir.runpytest('-vv')
+ result.stdout.fnmatch_lines([
+ "* 6*",
+ ])
+
+ monkeypatch.setenv('CI', '1')
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "* 6*",
+ ])
+
+
+def test_python25_compile_issue257(testdir):
+ testdir.makepyfile("""
+ def test_rewritten():
+ assert 1 == 2
+ # some comment
+ """)
+ result = testdir.runpytest()
+ assert result.ret == 1
+ result.stdout.fnmatch_lines("""
+ *E*assert 1 == 2*
+ *1 failed*
+ """)
+
+
+def test_rewritten(testdir):
+ testdir.makepyfile("""
+ def test_rewritten():
+ assert "@py_builtins" in globals()
+ """)
+ assert testdir.runpytest().ret == 0
+
+
+def test_reprcompare_notin(mock_config):
+ detail = plugin.pytest_assertrepr_compare(
+ mock_config, 'not in', 'foo', 'aaafoobbb')[1:]
+ assert detail == ["'foo' is contained here:", ' aaafoobbb', '? +++']
+
+
+def test_pytest_assertrepr_compare_integration(testdir):
+ testdir.makepyfile("""
+ def test_hello():
+ x = set(range(100))
+ y = x.copy()
+ y.remove(50)
+ assert x == y
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*def test_hello():*",
+ "*assert x == y*",
+ "*E*Extra items*left*",
+ "*E*50*",
+ ])
+
+
+def test_sequence_comparison_uses_repr(testdir):
+ testdir.makepyfile("""
+ def test_hello():
+ x = set("hello x")
+ y = set("hello y")
+ assert x == y
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*def test_hello():*",
+ "*assert x == y*",
+ "*E*Extra items*left*",
+ "*E*'x'*",
+ "*E*Extra items*right*",
+ "*E*'y'*",
+ ])
+
+
+def test_assertrepr_loaded_per_dir(testdir):
+ testdir.makepyfile(test_base=['def test_base(): assert 1 == 2'])
+ a = testdir.mkdir('a')
+ a_test = a.join('test_a.py')
+ a_test.write('def test_a(): assert 1 == 2')
+ a_conftest = a.join('conftest.py')
+ a_conftest.write('def pytest_assertrepr_compare(): return ["summary a"]')
+ b = testdir.mkdir('b')
+ b_test = b.join('test_b.py')
+ b_test.write('def test_b(): assert 1 == 2')
+ b_conftest = b.join('conftest.py')
+ b_conftest.write('def pytest_assertrepr_compare(): return ["summary b"]')
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ '*def test_base():*',
+ '*E*assert 1 == 2*',
+ '*def test_a():*',
+ '*E*assert summary a*',
+ '*def test_b():*',
+ '*E*assert summary b*'])
+
+
+def test_assertion_options(testdir):
+ testdir.makepyfile("""
+ def test_hello():
+ x = 3
+ assert x == 4
+ """)
+ result = testdir.runpytest()
+ assert "3 == 4" in result.stdout.str()
+ result = testdir.runpytest_subprocess("--assert=plain")
+ assert "3 == 4" not in result.stdout.str()
+
+
+def test_triple_quoted_string_issue113(testdir):
+ testdir.makepyfile("""
+ def test_hello():
+ assert "" == '''
+ '''""")
+ result = testdir.runpytest("--fulltrace")
+ result.stdout.fnmatch_lines([
+ "*1 failed*",
+ ])
+ assert 'SyntaxError' not in result.stdout.str()
+
+
+def test_traceback_failure(testdir):
+ p1 = testdir.makepyfile("""
+ def g():
+ return 2
+ def f(x):
+ assert x == g()
+ def test_onefails():
+ f(3)
+ """)
+ result = testdir.runpytest(p1, "--tb=long")
+ result.stdout.fnmatch_lines([
+ "*test_traceback_failure.py F*",
+ "====* FAILURES *====",
+ "____*____",
+ "",
+ " def test_onefails():",
+ "> f(3)",
+ "",
+ "*test_*.py:6: ",
+ "_ _ _ *",
+ # "",
+ " def f(x):",
+ "> assert x == g()",
+ "E assert 3 == 2",
+ "E + where 2 = g()",
+ "",
+ "*test_traceback_failure.py:4: AssertionError"
+ ])
+
+ result = testdir.runpytest(p1) # "auto"
+ result.stdout.fnmatch_lines([
+ "*test_traceback_failure.py F*",
+ "====* FAILURES *====",
+ "____*____",
+ "",
+ " def test_onefails():",
+ "> f(3)",
+ "",
+ "*test_*.py:6: ",
+ "",
+ " def f(x):",
+ "> assert x == g()",
+ "E assert 3 == 2",
+ "E + where 2 = g()",
+ "",
+ "*test_traceback_failure.py:4: AssertionError"
+ ])
+
+
+@pytest.mark.skipif(sys.version_info[:2] <= (3, 3), reason='Python 3.4+ shows chained exceptions on multiprocess')
+def test_exception_handling_no_traceback(testdir):
+ """
+ Handle chain exceptions in tasks submitted by the multiprocess module (#1984).
+ """
+ p1 = testdir.makepyfile("""
+ from multiprocessing import Pool
+
+ def process_task(n):
+ assert n == 10
+
+ def multitask_job():
+ tasks = [1]
+ with Pool(processes=1) as pool:
+ pool.map(process_task, tasks)
+
+ def test_multitask_job():
+ multitask_job()
+ """)
+ result = testdir.runpytest(p1, "--tb=long")
+ result.stdout.fnmatch_lines([
+ "====* FAILURES *====",
+ "*multiprocessing.pool.RemoteTraceback:*",
+ "Traceback (most recent call last):",
+ "*assert n == 10",
+ "The above exception was the direct cause of the following exception:",
+ "> * multitask_job()",
+ ])
+
+
+@pytest.mark.skipif("'__pypy__' in sys.builtin_module_names or sys.platform.startswith('java')")
+def test_warn_missing(testdir):
+ testdir.makepyfile("")
+ result = testdir.run(sys.executable, "-OO", "-m", "pytest", "-h")
+ result.stderr.fnmatch_lines([
+ "*WARNING*assert statements are not executed*",
+ ])
+ result = testdir.run(sys.executable, "-OO", "-m", "pytest")
+ result.stderr.fnmatch_lines([
+ "*WARNING*assert statements are not executed*",
+ ])
+
+
+def test_recursion_source_decode(testdir):
+ testdir.makepyfile("""
+ def test_something():
+ pass
+ """)
+ testdir.makeini("""
+ [pytest]
+ python_files = *.py
+ """)
+ result = testdir.runpytest("--collect-only")
+ result.stdout.fnmatch_lines("""
+ <Module*>
+ """)
+
+
+def test_AssertionError_message(testdir):
+ testdir.makepyfile("""
+ def test_hello():
+ x,y = 1,2
+ assert 0, (x,y)
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines("""
+ *def test_hello*
+ *assert 0, (x,y)*
+ *AssertionError: (1, 2)*
+ """)
+
+
+@pytest.mark.skipif(PY3, reason='This bug does not exist on PY3')
+def test_set_with_unsortable_elements():
+ # issue #718
+ class UnsortableKey(object):
+ def __init__(self, name):
+ self.name = name
+
+ def __lt__(self, other):
+ raise RuntimeError()
+
+ def __repr__(self):
+ return 'repr({0})'.format(self.name)
+
+ def __eq__(self, other):
+ return self.name == other.name
+
+ def __hash__(self):
+ return hash(self.name)
+
+ left_set = set(UnsortableKey(str(i)) for i in range(1, 3))
+ right_set = set(UnsortableKey(str(i)) for i in range(2, 4))
+ expl = callequal(left_set, right_set, verbose=True)
+ # skip first line because it contains the "construction" of the set, which does not have a guaranteed order
+ expl = expl[1:]
+ dedent = textwrap.dedent("""
+ Extra items in the left set:
+ repr(1)
+ Extra items in the right set:
+ repr(3)
+ Full diff (fallback to calling repr on each item):
+ - repr(1)
+ repr(2)
+ + repr(3)
+ """).strip()
+ assert '\n'.join(expl) == dedent
+
+
+def test_diff_newline_at_end(monkeypatch, testdir):
+ testdir.makepyfile(r"""
+ def test_diff():
+ assert 'asdf' == 'asdf\n'
+ """)
+
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(r"""
+ *assert 'asdf' == 'asdf\n'
+ * - asdf
+ * + asdf
+ * ? +
+ """)
+
+
+def test_assert_tuple_warning(testdir):
+ testdir.makepyfile("""
+ def test_tuple():
+ assert(False, 'you shall not pass')
+ """)
+ result = testdir.runpytest('-rw')
+ result.stdout.fnmatch_lines([
+ '*test_assert_tuple_warning.py:2',
+ '*assertion is always true*',
+ ])
+
+
+def test_assert_indirect_tuple_no_warning(testdir):
+ testdir.makepyfile("""
+ def test_tuple():
+ tpl = ('foo', 'bar')
+ assert tpl
+ """)
+ result = testdir.runpytest('-rw')
+ output = '\n'.join(result.stdout.lines)
+ assert 'WR1' not in output
+
+
+def test_assert_with_unicode(monkeypatch, testdir):
+ testdir.makepyfile(u"""
+ # -*- coding: utf-8 -*-
+ def test_unicode():
+ assert u'유니코드' == u'Unicode'
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(['*AssertionError*'])
+
+
+def test_raise_unprintable_assertion_error(testdir):
+ testdir.makepyfile(r"""
+ def test_raise_assertion_error():
+ raise AssertionError('\xff')
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([r"> raise AssertionError('\xff')", 'E AssertionError: *'])
+
+
+def test_raise_assertion_error_raisin_repr(testdir):
+ testdir.makepyfile(u"""
+ class RaisingRepr(object):
+ def __repr__(self):
+ raise Exception()
+ def test_raising_repr():
+ raise AssertionError(RaisingRepr())
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(['E AssertionError: <unprintable AssertionError object>'])
+
+
+def test_issue_1944(testdir):
+ testdir.makepyfile("""
+ def f():
+ return
+
+ assert f() == 10
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(["*1 error*"])
+ assert "AttributeError: 'Module' object has no attribute '_obj'" not in result.stdout.str()
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_assertrewrite.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_assertrewrite.py
new file mode 100644
index 00000000000..0e22c6dac47
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_assertrewrite.py
@@ -0,0 +1,996 @@
+from __future__ import absolute_import, division, print_function
+
+import glob
+import os
+import py_compile
+import stat
+import sys
+import zipfile
+import py
+import pytest
+
+import _pytest._code
+from _pytest.assertion import util
+from _pytest.assertion.rewrite import rewrite_asserts, PYTEST_TAG, AssertionRewritingHook
+from _pytest.main import EXIT_NOTESTSCOLLECTED
+
+ast = pytest.importorskip("ast")
+if sys.platform.startswith("java"):
+ # XXX should be xfail
+ pytest.skip("assert rewrite does currently not work on jython")
+
+
+def setup_module(mod):
+ mod._old_reprcompare = util._reprcompare
+ _pytest._code._reprcompare = None
+
+
+def teardown_module(mod):
+ util._reprcompare = mod._old_reprcompare
+ del mod._old_reprcompare
+
+
+def rewrite(src):
+ tree = ast.parse(src)
+ rewrite_asserts(tree)
+ return tree
+
+
+def getmsg(f, extra_ns=None, must_pass=False):
+ """Rewrite the assertions in f, run it, and get the failure message."""
+ src = '\n'.join(_pytest._code.Code(f).source().lines)
+ mod = rewrite(src)
+ code = compile(mod, "<test>", "exec")
+ ns = {}
+ if extra_ns is not None:
+ ns.update(extra_ns)
+ py.builtin.exec_(code, ns)
+ func = ns[f.__name__]
+ try:
+ func()
+ except AssertionError:
+ if must_pass:
+ pytest.fail("shouldn't have raised")
+ s = str(sys.exc_info()[1])
+ if not s.startswith("assert"):
+ return "AssertionError: " + s
+ return s
+ else:
+ if not must_pass:
+ pytest.fail("function didn't raise at all")
+
+
+class TestAssertionRewrite(object):
+
+ def test_place_initial_imports(self):
+ s = """'Doc string'\nother = stuff"""
+ m = rewrite(s)
+ # Module docstrings in 3.7 are part of Module node, it's not in the body
+ # so we remove it so the following body items have the same indexes on
+ # all Python versions
+ if sys.version_info < (3, 7):
+ assert isinstance(m.body[0], ast.Expr)
+ assert isinstance(m.body[0].value, ast.Str)
+ del m.body[0]
+ for imp in m.body[0:2]:
+ assert isinstance(imp, ast.Import)
+ assert imp.lineno == 2
+ assert imp.col_offset == 0
+ assert isinstance(m.body[2], ast.Assign)
+ s = """from __future__ import with_statement\nother_stuff"""
+ m = rewrite(s)
+ assert isinstance(m.body[0], ast.ImportFrom)
+ for imp in m.body[1:3]:
+ assert isinstance(imp, ast.Import)
+ assert imp.lineno == 2
+ assert imp.col_offset == 0
+ assert isinstance(m.body[3], ast.Expr)
+ s = """'doc string'\nfrom __future__ import with_statement"""
+ m = rewrite(s)
+ if sys.version_info < (3, 7):
+ assert isinstance(m.body[0], ast.Expr)
+ assert isinstance(m.body[0].value, ast.Str)
+ del m.body[0]
+ assert isinstance(m.body[0], ast.ImportFrom)
+ for imp in m.body[1:3]:
+ assert isinstance(imp, ast.Import)
+ assert imp.lineno == 2
+ assert imp.col_offset == 0
+ s = """'doc string'\nfrom __future__ import with_statement\nother"""
+ m = rewrite(s)
+ if sys.version_info < (3, 7):
+ assert isinstance(m.body[0], ast.Expr)
+ assert isinstance(m.body[0].value, ast.Str)
+ del m.body[0]
+ assert isinstance(m.body[0], ast.ImportFrom)
+ for imp in m.body[1:3]:
+ assert isinstance(imp, ast.Import)
+ assert imp.lineno == 3
+ assert imp.col_offset == 0
+ assert isinstance(m.body[3], ast.Expr)
+ s = """from . import relative\nother_stuff"""
+ m = rewrite(s)
+ for imp in m.body[0:2]:
+ assert isinstance(imp, ast.Import)
+ assert imp.lineno == 1
+ assert imp.col_offset == 0
+ assert isinstance(m.body[3], ast.Expr)
+
+ def test_dont_rewrite(self):
+ s = """'PYTEST_DONT_REWRITE'\nassert 14"""
+ m = rewrite(s)
+ if sys.version_info < (3, 7):
+ assert len(m.body) == 2
+ assert isinstance(m.body[0], ast.Expr)
+ assert isinstance(m.body[0].value, ast.Str)
+ del m.body[0]
+ else:
+ assert len(m.body) == 1
+ assert m.body[0].msg is None
+
+ def test_name(self):
+ def f():
+ assert False
+ assert getmsg(f) == "assert False"
+
+ def f():
+ f = False
+ assert f
+
+ assert getmsg(f) == "assert False"
+
+ def f():
+ assert a_global # noqa
+
+ assert getmsg(f, {"a_global": False}) == "assert False"
+
+ def f():
+ assert sys == 42
+
+ assert getmsg(f, {"sys": sys}) == "assert sys == 42"
+
+ def f():
+ assert cls == 42 # noqa
+
+ class X(object):
+ pass
+
+ assert getmsg(f, {"cls": X}) == "assert cls == 42"
+
+ def test_assert_already_has_message(self):
+ def f():
+ assert False, "something bad!"
+ assert getmsg(f) == "AssertionError: something bad!\nassert False"
+
+ def test_assertion_message(self, testdir):
+ testdir.makepyfile("""
+ def test_foo():
+ assert 1 == 2, "The failure message"
+ """)
+ result = testdir.runpytest()
+ assert result.ret == 1
+ result.stdout.fnmatch_lines([
+ "*AssertionError*The failure message*",
+ "*assert 1 == 2*",
+ ])
+
+ def test_assertion_message_multiline(self, testdir):
+ testdir.makepyfile("""
+ def test_foo():
+ assert 1 == 2, "A multiline\\nfailure message"
+ """)
+ result = testdir.runpytest()
+ assert result.ret == 1
+ result.stdout.fnmatch_lines([
+ "*AssertionError*A multiline*",
+ "*failure message*",
+ "*assert 1 == 2*",
+ ])
+
+ def test_assertion_message_tuple(self, testdir):
+ testdir.makepyfile("""
+ def test_foo():
+ assert 1 == 2, (1, 2)
+ """)
+ result = testdir.runpytest()
+ assert result.ret == 1
+ result.stdout.fnmatch_lines([
+ "*AssertionError*%s*" % repr((1, 2)),
+ "*assert 1 == 2*",
+ ])
+
+ def test_assertion_message_expr(self, testdir):
+ testdir.makepyfile("""
+ def test_foo():
+ assert 1 == 2, 1 + 2
+ """)
+ result = testdir.runpytest()
+ assert result.ret == 1
+ result.stdout.fnmatch_lines([
+ "*AssertionError*3*",
+ "*assert 1 == 2*",
+ ])
+
+ def test_assertion_message_escape(self, testdir):
+ testdir.makepyfile("""
+ def test_foo():
+ assert 1 == 2, 'To be escaped: %'
+ """)
+ result = testdir.runpytest()
+ assert result.ret == 1
+ result.stdout.fnmatch_lines([
+ "*AssertionError: To be escaped: %",
+ "*assert 1 == 2",
+ ])
+
+ def test_boolop(self):
+ def f():
+ f = g = False
+ assert f and g
+
+ assert getmsg(f) == "assert (False)"
+
+ def f():
+ f = True
+ g = False
+ assert f and g
+
+ assert getmsg(f) == "assert (True and False)"
+
+ def f():
+ f = False
+ g = True
+ assert f and g
+
+ assert getmsg(f) == "assert (False)"
+
+ def f():
+ f = g = False
+ assert f or g
+
+ assert getmsg(f) == "assert (False or False)"
+
+ def f():
+ f = g = False
+ assert not f and not g
+
+ getmsg(f, must_pass=True)
+
+ def x():
+ return False
+
+ def f():
+ assert x() and x()
+
+ assert getmsg(f, {"x": x}) == """assert (False)
+ + where False = x()"""
+
+ def f():
+ assert False or x()
+
+ assert getmsg(f, {"x": x}) == """assert (False or False)
+ + where False = x()"""
+
+ def f():
+ assert 1 in {} and 2 in {}
+
+ assert getmsg(f) == "assert (1 in {})"
+
+ def f():
+ x = 1
+ y = 2
+ assert x in {1: None} and y in {}
+
+ assert getmsg(f) == "assert (1 in {1: None} and 2 in {})"
+
+ def f():
+ f = True
+ g = False
+ assert f or g
+
+ getmsg(f, must_pass=True)
+
+ def f():
+ f = g = h = lambda: True
+ assert f() and g() and h()
+
+ getmsg(f, must_pass=True)
+
+ def test_short_circuit_evaluation(self):
+ def f():
+ assert True or explode # noqa
+
+ getmsg(f, must_pass=True)
+
+ def f():
+ x = 1
+ assert x == 1 or x == 2
+
+ getmsg(f, must_pass=True)
+
+ def test_unary_op(self):
+ def f():
+ x = True
+ assert not x
+
+ assert getmsg(f) == "assert not True"
+
+ def f():
+ x = 0
+ assert ~x + 1
+
+ assert getmsg(f) == "assert (~0 + 1)"
+
+ def f():
+ x = 3
+ assert -x + x
+
+ assert getmsg(f) == "assert (-3 + 3)"
+
+ def f():
+ x = 0
+ assert +x + x
+
+ assert getmsg(f) == "assert (+0 + 0)"
+
+ def test_binary_op(self):
+ def f():
+ x = 1
+ y = -1
+ assert x + y
+
+ assert getmsg(f) == "assert (1 + -1)"
+
+ def f():
+ assert not 5 % 4
+ assert getmsg(f) == "assert not (5 % 4)"
+
+ def test_boolop_percent(self):
+ def f():
+ assert 3 % 2 and False
+
+ assert getmsg(f) == "assert ((3 % 2) and False)"
+
+ def f():
+ assert False or 4 % 2
+ assert getmsg(f) == "assert (False or (4 % 2))"
+
+ @pytest.mark.skipif("sys.version_info < (3,5)")
+ def test_at_operator_issue1290(self, testdir):
+ testdir.makepyfile("""
+ class Matrix(object):
+ def __init__(self, num):
+ self.num = num
+ def __matmul__(self, other):
+ return self.num * other.num
+
+ def test_multmat_operator():
+ assert Matrix(2) @ Matrix(3) == 6""")
+ testdir.runpytest().assert_outcomes(passed=1)
+
+ def test_call(self):
+ def g(a=42, *args, **kwargs):
+ return False
+
+ ns = {"g": g}
+
+ def f():
+ assert g()
+
+ assert getmsg(f, ns) == """assert False
+ + where False = g()"""
+
+ def f():
+ assert g(1)
+
+ assert getmsg(f, ns) == """assert False
+ + where False = g(1)"""
+
+ def f():
+ assert g(1, 2)
+
+ assert getmsg(f, ns) == """assert False
+ + where False = g(1, 2)"""
+
+ def f():
+ assert g(1, g=42)
+
+ assert getmsg(f, ns) == """assert False
+ + where False = g(1, g=42)"""
+
+ def f():
+ assert g(1, 3, g=23)
+
+ assert getmsg(f, ns) == """assert False
+ + where False = g(1, 3, g=23)"""
+
+ def f():
+ seq = [1, 2, 3]
+ assert g(*seq)
+
+ assert getmsg(f, ns) == """assert False
+ + where False = g(*[1, 2, 3])"""
+
+ def f():
+ x = "a"
+ assert g(**{x: 2})
+
+ assert getmsg(f, ns) == """assert False
+ + where False = g(**{'a': 2})"""
+
+ def test_attribute(self):
+ class X(object):
+ g = 3
+
+ ns = {"x": X}
+
+ def f():
+ assert not x.g # noqa
+
+ assert getmsg(f, ns) == """assert not 3
+ + where 3 = x.g"""
+
+ def f():
+ x.a = False # noqa
+ assert x.a # noqa
+
+ assert getmsg(f, ns) == """assert False
+ + where False = x.a"""
+
+ def test_comparisons(self):
+
+ def f():
+ a, b = range(2)
+ assert b < a
+
+ assert getmsg(f) == """assert 1 < 0"""
+
+ def f():
+ a, b, c = range(3)
+ assert a > b > c
+
+ assert getmsg(f) == """assert 0 > 1"""
+
+ def f():
+ a, b, c = range(3)
+ assert a < b > c
+
+ assert getmsg(f) == """assert 1 > 2"""
+
+ def f():
+ a, b, c = range(3)
+ assert a < b <= c
+
+ getmsg(f, must_pass=True)
+
+ def f():
+ a, b, c = range(3)
+ assert a < b
+ assert b < c
+
+ getmsg(f, must_pass=True)
+
+ def test_len(self):
+
+ def f():
+ values = list(range(10))
+ assert len(values) == 11
+
+ assert getmsg(f).startswith("""assert 10 == 11
+ + where 10 = len([""")
+
+ def test_custom_reprcompare(self, monkeypatch):
+ def my_reprcompare(op, left, right):
+ return "42"
+
+ monkeypatch.setattr(util, "_reprcompare", my_reprcompare)
+
+ def f():
+ assert 42 < 3
+
+ assert getmsg(f) == "assert 42"
+
+ def my_reprcompare(op, left, right):
+ return "%s %s %s" % (left, op, right)
+
+ monkeypatch.setattr(util, "_reprcompare", my_reprcompare)
+
+ def f():
+ assert 1 < 3 < 5 <= 4 < 7
+
+ assert getmsg(f) == "assert 5 <= 4"
+
+ def test_assert_raising_nonzero_in_comparison(self):
+ def f():
+ class A(object):
+
+ def __nonzero__(self):
+ raise ValueError(42)
+
+ def __lt__(self, other):
+ return A()
+
+ def __repr__(self):
+ return "<MY42 object>"
+
+ def myany(x):
+ return False
+
+ assert myany(A() < 0)
+
+ assert "<MY42 object> < 0" in getmsg(f)
+
+ def test_formatchar(self):
+ def f():
+ assert "%test" == "test"
+
+ assert getmsg(f).startswith("assert '%test' == 'test'")
+
+ def test_custom_repr(self):
+ def f():
+ class Foo(object):
+ a = 1
+
+ def __repr__(self):
+ return "\n{ \n~ \n}"
+
+ f = Foo()
+ assert 0 == f.a
+
+ assert r"where 1 = \n{ \n~ \n}.a" in util._format_lines([getmsg(f)])[0]
+
+
+class TestRewriteOnImport(object):
+
+ def test_pycache_is_a_file(self, testdir):
+ testdir.tmpdir.join("__pycache__").write("Hello")
+ testdir.makepyfile("""
+ def test_rewritten():
+ assert "@py_builtins" in globals()""")
+ assert testdir.runpytest().ret == 0
+
+ def test_pycache_is_readonly(self, testdir):
+ cache = testdir.tmpdir.mkdir("__pycache__")
+ old_mode = cache.stat().mode
+ cache.chmod(old_mode ^ stat.S_IWRITE)
+ testdir.makepyfile("""
+ def test_rewritten():
+ assert "@py_builtins" in globals()""")
+ try:
+ assert testdir.runpytest().ret == 0
+ finally:
+ cache.chmod(old_mode)
+
+ def test_zipfile(self, testdir):
+ z = testdir.tmpdir.join("myzip.zip")
+ z_fn = str(z)
+ f = zipfile.ZipFile(z_fn, "w")
+ try:
+ f.writestr("test_gum/__init__.py", "")
+ f.writestr("test_gum/test_lizard.py", "")
+ finally:
+ f.close()
+ z.chmod(256)
+ testdir.makepyfile("""
+ import sys
+ sys.path.append(%r)
+ import test_gum.test_lizard""" % (z_fn,))
+ assert testdir.runpytest().ret == EXIT_NOTESTSCOLLECTED
+
+ def test_readonly(self, testdir):
+ sub = testdir.mkdir("testing")
+ sub.join("test_readonly.py").write(
+ py.builtin._totext("""
+def test_rewritten():
+ assert "@py_builtins" in globals()
+ """).encode("utf-8"), "wb")
+ old_mode = sub.stat().mode
+ sub.chmod(320)
+ try:
+ assert testdir.runpytest().ret == 0
+ finally:
+ sub.chmod(old_mode)
+
+ def test_dont_write_bytecode(self, testdir, monkeypatch):
+ testdir.makepyfile("""
+ import os
+ def test_no_bytecode():
+ assert "__pycache__" in __cached__
+ assert not os.path.exists(__cached__)
+ assert not os.path.exists(os.path.dirname(__cached__))""")
+ monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", "1")
+ assert testdir.runpytest_subprocess().ret == 0
+
+ def test_orphaned_pyc_file(self, testdir):
+ if sys.version_info < (3, 0) and hasattr(sys, 'pypy_version_info'):
+ pytest.skip("pypy2 doesn't run orphaned pyc files")
+
+ testdir.makepyfile("""
+ import orphan
+ def test_it():
+ assert orphan.value == 17
+ """)
+ testdir.makepyfile(orphan="""
+ value = 17
+ """)
+ py_compile.compile("orphan.py")
+ os.remove("orphan.py")
+
+ # Python 3 puts the .pyc files in a __pycache__ directory, and will
+ # not import from there without source. It will import a .pyc from
+ # the source location though.
+ if not os.path.exists("orphan.pyc"):
+ pycs = glob.glob("__pycache__/orphan.*.pyc")
+ assert len(pycs) == 1
+ os.rename(pycs[0], "orphan.pyc")
+
+ assert testdir.runpytest().ret == 0
+
+ @pytest.mark.skipif('"__pypy__" in sys.modules')
+ def test_pyc_vs_pyo(self, testdir, monkeypatch):
+ testdir.makepyfile("""
+ import pytest
+ def test_optimized():
+ "hello"
+ assert test_optimized.__doc__ is None"""
+ )
+ p = py.path.local.make_numbered_dir(prefix="runpytest-", keep=None,
+ rootdir=testdir.tmpdir)
+ tmp = "--basetemp=%s" % p
+ monkeypatch.setenv("PYTHONOPTIMIZE", "2")
+ monkeypatch.delenv("PYTHONDONTWRITEBYTECODE", raising=False)
+ assert testdir.runpytest_subprocess(tmp).ret == 0
+ tagged = "test_pyc_vs_pyo." + PYTEST_TAG
+ assert tagged + ".pyo" in os.listdir("__pycache__")
+ monkeypatch.undo()
+ monkeypatch.delenv("PYTHONDONTWRITEBYTECODE", raising=False)
+ assert testdir.runpytest_subprocess(tmp).ret == 1
+ assert tagged + ".pyc" in os.listdir("__pycache__")
+
+ def test_package(self, testdir):
+ pkg = testdir.tmpdir.join("pkg")
+ pkg.mkdir()
+ pkg.join("__init__.py").ensure()
+ pkg.join("test_blah.py").write("""
+def test_rewritten():
+ assert "@py_builtins" in globals()""")
+ assert testdir.runpytest().ret == 0
+
+ def test_translate_newlines(self, testdir):
+ content = "def test_rewritten():\r\n assert '@py_builtins' in globals()"
+ b = content.encode("utf-8")
+ testdir.tmpdir.join("test_newlines.py").write(b, "wb")
+ assert testdir.runpytest().ret == 0
+
+ @pytest.mark.skipif(sys.version_info < (3, 4),
+ reason='packages without __init__.py not supported on python 2')
+ def test_package_without__init__py(self, testdir):
+ pkg = testdir.mkdir('a_package_without_init_py')
+ pkg.join('module.py').ensure()
+ testdir.makepyfile("import a_package_without_init_py.module")
+ assert testdir.runpytest().ret == EXIT_NOTESTSCOLLECTED
+
+ def test_rewrite_warning(self, pytestconfig, monkeypatch):
+ hook = AssertionRewritingHook(pytestconfig)
+ warnings = []
+
+ def mywarn(code, msg):
+ warnings.append((code, msg))
+
+ monkeypatch.setattr(hook.config, 'warn', mywarn)
+ hook.mark_rewrite('_pytest')
+ assert '_pytest' in warnings[0][1]
+
+ def test_rewrite_module_imported_from_conftest(self, testdir):
+ testdir.makeconftest('''
+ import test_rewrite_module_imported
+ ''')
+ testdir.makepyfile(test_rewrite_module_imported='''
+ def test_rewritten():
+ assert "@py_builtins" in globals()
+ ''')
+ assert testdir.runpytest_subprocess().ret == 0
+
+ def test_remember_rewritten_modules(self, pytestconfig, testdir, monkeypatch):
+ """
+ AssertionRewriteHook should remember rewritten modules so it
+ doesn't give false positives (#2005).
+ """
+ monkeypatch.syspath_prepend(testdir.tmpdir)
+ testdir.makepyfile(test_remember_rewritten_modules='')
+ warnings = []
+ hook = AssertionRewritingHook(pytestconfig)
+ monkeypatch.setattr(hook.config, 'warn', lambda code, msg: warnings.append(msg))
+ hook.find_module('test_remember_rewritten_modules')
+ hook.load_module('test_remember_rewritten_modules')
+ hook.mark_rewrite('test_remember_rewritten_modules')
+ hook.mark_rewrite('test_remember_rewritten_modules')
+ assert warnings == []
+
+ def test_rewrite_warning_using_pytest_plugins(self, testdir):
+ testdir.makepyfile(**{
+ 'conftest.py': "pytest_plugins = ['core', 'gui', 'sci']",
+ 'core.py': "",
+ 'gui.py': "pytest_plugins = ['core', 'sci']",
+ 'sci.py': "pytest_plugins = ['core']",
+ 'test_rewrite_warning_pytest_plugins.py': "def test(): pass",
+ })
+ testdir.chdir()
+ result = testdir.runpytest_subprocess()
+ result.stdout.fnmatch_lines(['*= 1 passed in *=*'])
+ assert 'pytest-warning summary' not in result.stdout.str()
+
+ def test_rewrite_warning_using_pytest_plugins_env_var(self, testdir, monkeypatch):
+ monkeypatch.setenv('PYTEST_PLUGINS', 'plugin')
+ testdir.makepyfile(**{
+ 'plugin.py': "",
+ 'test_rewrite_warning_using_pytest_plugins_env_var.py': """
+ import plugin
+ pytest_plugins = ['plugin']
+ def test():
+ pass
+ """,
+ })
+ testdir.chdir()
+ result = testdir.runpytest_subprocess()
+ result.stdout.fnmatch_lines(['*= 1 passed in *=*'])
+ assert 'pytest-warning summary' not in result.stdout.str()
+
+ @pytest.mark.skipif(sys.version_info[0] > 2, reason='python 2 only')
+ def test_rewrite_future_imports(self, testdir):
+ """Test that rewritten modules don't inherit the __future__ flags
+ from the assertrewrite module.
+
+ assertion.rewrite imports __future__.division (and others), so
+ ensure rewritten modules don't inherit those flags.
+
+ The test below will fail if __future__.division is enabled
+ """
+ testdir.makepyfile('''
+ def test():
+ x = 1 / 2
+ assert type(x) is int
+ ''')
+ result = testdir.runpytest()
+ assert result.ret == 0
+
+
+class TestAssertionRewriteHookDetails(object):
+ def test_loader_is_package_false_for_module(self, testdir):
+ testdir.makepyfile(test_fun="""
+ def test_loader():
+ assert not __loader__.is_package(__name__)
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "* 1 passed*",
+ ])
+
+ def test_loader_is_package_true_for_package(self, testdir):
+ testdir.makepyfile(test_fun="""
+ def test_loader():
+ assert not __loader__.is_package(__name__)
+
+ def test_fun():
+ assert __loader__.is_package('fun')
+
+ def test_missing():
+ assert not __loader__.is_package('pytest_not_there')
+ """)
+ testdir.mkpydir('fun')
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ '* 3 passed*',
+ ])
+
+ @pytest.mark.skipif("sys.version_info[0] >= 3")
+ @pytest.mark.xfail("hasattr(sys, 'pypy_translation_info')")
+ def test_assume_ascii(self, testdir):
+ content = "u'\xe2\x99\xa5\x01\xfe'"
+ testdir.tmpdir.join("test_encoding.py").write(content, "wb")
+ res = testdir.runpytest()
+ assert res.ret != 0
+ assert "SyntaxError: Non-ASCII character" in res.stdout.str()
+
+ @pytest.mark.skipif("sys.version_info[0] >= 3")
+ def test_detect_coding_cookie(self, testdir):
+ testdir.makepyfile(test_cookie="""
+ # -*- coding: utf-8 -*-
+ u"St\xc3\xa4d"
+ def test_rewritten():
+ assert "@py_builtins" in globals()""")
+ assert testdir.runpytest().ret == 0
+
+ @pytest.mark.skipif("sys.version_info[0] >= 3")
+ def test_detect_coding_cookie_second_line(self, testdir):
+ testdir.makepyfile(test_cookie="""
+ # -*- coding: utf-8 -*-
+ u"St\xc3\xa4d"
+ def test_rewritten():
+ assert "@py_builtins" in globals()""")
+ assert testdir.runpytest().ret == 0
+
+ @pytest.mark.skipif("sys.version_info[0] >= 3")
+ def test_detect_coding_cookie_crlf(self, testdir):
+ testdir.makepyfile(test_cookie="""
+ # -*- coding: utf-8 -*-
+ u"St\xc3\xa4d"
+ def test_rewritten():
+ assert "@py_builtins" in globals()""")
+ assert testdir.runpytest().ret == 0
+
+ def test_sys_meta_path_munged(self, testdir):
+ testdir.makepyfile("""
+ def test_meta_path():
+ import sys; sys.meta_path = []""")
+ assert testdir.runpytest().ret == 0
+
+ def test_write_pyc(self, testdir, tmpdir, monkeypatch):
+ from _pytest.assertion.rewrite import _write_pyc
+ from _pytest.assertion import AssertionState
+ try:
+ import __builtin__ as b
+ except ImportError:
+ import builtins as b
+ config = testdir.parseconfig([])
+ state = AssertionState(config, "rewrite")
+ source_path = tmpdir.ensure("source.py")
+ pycpath = tmpdir.join("pyc").strpath
+ assert _write_pyc(state, [1], source_path.stat(), pycpath)
+
+ def open(*args):
+ e = IOError()
+ e.errno = 10
+ raise e
+
+ monkeypatch.setattr(b, "open", open)
+ assert not _write_pyc(state, [1], source_path.stat(), pycpath)
+
+ def test_resources_provider_for_loader(self, testdir):
+ """
+ Attempts to load resources from a package should succeed normally,
+ even when the AssertionRewriteHook is used to load the modules.
+
+ See #366 for details.
+ """
+ pytest.importorskip("pkg_resources")
+
+ testdir.mkpydir('testpkg')
+ contents = {
+ 'testpkg/test_pkg': """
+ import pkg_resources
+
+ import pytest
+ from _pytest.assertion.rewrite import AssertionRewritingHook
+
+ def test_load_resource():
+ assert isinstance(__loader__, AssertionRewritingHook)
+ res = pkg_resources.resource_string(__name__, 'resource.txt')
+ res = res.decode('ascii')
+ assert res == 'Load me please.'
+ """,
+ }
+ testdir.makepyfile(**contents)
+ testdir.maketxtfile(**{'testpkg/resource': "Load me please."})
+
+ result = testdir.runpytest_subprocess()
+ result.assert_outcomes(passed=1)
+
+ def test_read_pyc(self, tmpdir):
+ """
+ Ensure that the `_read_pyc` can properly deal with corrupted pyc files.
+ In those circumstances it should just give up instead of generating
+ an exception that is propagated to the caller.
+ """
+ import py_compile
+ from _pytest.assertion.rewrite import _read_pyc
+
+ source = tmpdir.join('source.py')
+ pyc = source + 'c'
+
+ source.write('def test(): pass')
+ py_compile.compile(str(source), str(pyc))
+
+ contents = pyc.read(mode='rb')
+ strip_bytes = 20 # header is around 8 bytes, strip a little more
+ assert len(contents) > strip_bytes
+ pyc.write(contents[:strip_bytes], mode='wb')
+
+ assert _read_pyc(source, str(pyc)) is None # no error
+
+ def test_reload_is_same(self, testdir):
+ # A file that will be picked up during collecting.
+ testdir.tmpdir.join("file.py").ensure()
+ testdir.tmpdir.join("pytest.ini").write(py.std.textwrap.dedent("""
+ [pytest]
+ python_files = *.py
+ """))
+
+ testdir.makepyfile(test_fun="""
+ import sys
+ try:
+ from imp import reload
+ except ImportError:
+ pass
+
+ def test_loader():
+ import file
+ assert sys.modules["file"] is reload(file)
+ """)
+ result = testdir.runpytest('-s')
+ result.stdout.fnmatch_lines([
+ "* 1 passed*",
+ ])
+
+ def test_get_data_support(self, testdir):
+ """Implement optional PEP302 api (#808).
+ """
+ path = testdir.mkpydir("foo")
+ path.join("test_foo.py").write(_pytest._code.Source("""
+ class Test(object):
+ def test_foo(self):
+ import pkgutil
+ data = pkgutil.get_data('foo.test_foo', 'data.txt')
+ assert data == b'Hey'
+ """))
+ path.join('data.txt').write('Hey')
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines('*1 passed*')
+
+
+def test_issue731(testdir):
+ testdir.makepyfile("""
+ class LongReprWithBraces(object):
+ def __repr__(self):
+ return 'LongReprWithBraces({' + ('a' * 80) + '}' + ('a' * 120) + ')'
+
+ def some_method(self):
+ return False
+
+ def test_long_repr():
+ obj = LongReprWithBraces()
+ assert obj.some_method()
+ """)
+ result = testdir.runpytest()
+ assert 'unbalanced braces' not in result.stdout.str()
+
+
+class TestIssue925(object):
+ def test_simple_case(self, testdir):
+ testdir.makepyfile("""
+ def test_ternary_display():
+ assert (False == False) == False
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines('*E*assert (False == False) == False')
+
+ def test_long_case(self, testdir):
+ testdir.makepyfile("""
+ def test_ternary_display():
+ assert False == (False == True) == True
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines('*E*assert (False == True) == True')
+
+ def test_many_brackets(self, testdir):
+ testdir.makepyfile("""
+ def test_ternary_display():
+ assert True == ((False == True) == True)
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines('*E*assert True == ((False == True) == True)')
+
+
+class TestIssue2121():
+ def test_simple(self, testdir):
+ testdir.tmpdir.join("tests/file.py").ensure().write("""
+def test_simple_failure():
+ assert 1 + 1 == 3
+""")
+ testdir.tmpdir.join("pytest.ini").write(py.std.textwrap.dedent("""
+ [pytest]
+ python_files = tests/**.py
+ """))
+
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines('*E*assert (1 + 1) == 3')
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_cache.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_cache.py
new file mode 100755
index 00000000000..a37170cdd2b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_cache.py
@@ -0,0 +1,605 @@
+from __future__ import absolute_import, division, print_function
+import sys
+import py
+import _pytest
+import pytest
+import os
+import shutil
+
+pytest_plugins = "pytester",
+
+
+class TestNewAPI(object):
+ def test_config_cache_makedir(self, testdir):
+ testdir.makeini("[pytest]")
+ config = testdir.parseconfigure()
+ with pytest.raises(ValueError):
+ config.cache.makedir("key/name")
+
+ p = config.cache.makedir("name")
+ assert p.check()
+
+ def test_config_cache_dataerror(self, testdir):
+ testdir.makeini("[pytest]")
+ config = testdir.parseconfigure()
+ cache = config.cache
+ pytest.raises(TypeError, lambda: cache.set("key/name", cache))
+ config.cache.set("key/name", 0)
+ config.cache._getvaluepath("key/name").write("123invalid")
+ val = config.cache.get("key/name", -2)
+ assert val == -2
+
+ def test_cache_writefail_cachfile_silent(self, testdir):
+ testdir.makeini("[pytest]")
+ testdir.tmpdir.join('.cache').write('gone wrong')
+ config = testdir.parseconfigure()
+ cache = config.cache
+ cache.set('test/broken', [])
+
+ @pytest.mark.skipif(sys.platform.startswith('win'), reason='no chmod on windows')
+ def test_cache_writefail_permissions(self, testdir):
+ testdir.makeini("[pytest]")
+ testdir.tmpdir.ensure_dir('.cache').chmod(0)
+ config = testdir.parseconfigure()
+ cache = config.cache
+ cache.set('test/broken', [])
+
+ @pytest.mark.skipif(sys.platform.startswith('win'), reason='no chmod on windows')
+ def test_cache_failure_warns(self, testdir):
+ testdir.tmpdir.ensure_dir('.cache').chmod(0)
+ testdir.makepyfile("""
+ def test_error():
+ raise Exception
+
+ """)
+ result = testdir.runpytest('-rw')
+ assert result.ret == 1
+ result.stdout.fnmatch_lines([
+ "*could not create cache path*",
+ "*1 warnings*",
+ ])
+
+ def test_config_cache(self, testdir):
+ testdir.makeconftest("""
+ def pytest_configure(config):
+ # see that we get cache information early on
+ assert hasattr(config, "cache")
+ """)
+ testdir.makepyfile("""
+ def test_session(pytestconfig):
+ assert hasattr(pytestconfig, "cache")
+ """)
+ result = testdir.runpytest()
+ assert result.ret == 0
+ result.stdout.fnmatch_lines(["*1 passed*"])
+
+ def test_cachefuncarg(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ def test_cachefuncarg(cache):
+ val = cache.get("some/thing", None)
+ assert val is None
+ cache.set("some/thing", [1])
+ pytest.raises(TypeError, lambda: cache.get("some/thing"))
+ val = cache.get("some/thing", [])
+ assert val == [1]
+ """)
+ result = testdir.runpytest()
+ assert result.ret == 0
+ result.stdout.fnmatch_lines(["*1 passed*"])
+
+ def test_custom_rel_cache_dir(self, testdir):
+ rel_cache_dir = os.path.join('custom_cache_dir', 'subdir')
+ testdir.makeini("""
+ [pytest]
+ cache_dir = {cache_dir}
+ """.format(cache_dir=rel_cache_dir))
+ testdir.makepyfile(test_errored='def test_error():\n assert False')
+ testdir.runpytest()
+ assert testdir.tmpdir.join(rel_cache_dir).isdir()
+
+ def test_custom_abs_cache_dir(self, testdir, tmpdir_factory):
+ tmp = str(tmpdir_factory.mktemp('tmp'))
+ abs_cache_dir = os.path.join(tmp, 'custom_cache_dir')
+ testdir.makeini("""
+ [pytest]
+ cache_dir = {cache_dir}
+ """.format(cache_dir=abs_cache_dir))
+ testdir.makepyfile(test_errored='def test_error():\n assert False')
+ testdir.runpytest()
+ assert py.path.local(abs_cache_dir).isdir()
+
+ def test_custom_cache_dir_with_env_var(self, testdir, monkeypatch):
+ monkeypatch.setenv('env_var', 'custom_cache_dir')
+ testdir.makeini("""
+ [pytest]
+ cache_dir = {cache_dir}
+ """.format(cache_dir='$env_var'))
+ testdir.makepyfile(test_errored='def test_error():\n assert False')
+ testdir.runpytest()
+ assert testdir.tmpdir.join('custom_cache_dir').isdir()
+
+
+def test_cache_reportheader(testdir):
+ testdir.makepyfile("""
+ def test_hello():
+ pass
+ """)
+ result = testdir.runpytest("-v")
+ result.stdout.fnmatch_lines([
+ "cachedir: .cache"
+ ])
+
+
+def test_cache_show(testdir):
+ result = testdir.runpytest("--cache-show")
+ assert result.ret == 0
+ result.stdout.fnmatch_lines([
+ "*cache is empty*"
+ ])
+ testdir.makeconftest("""
+ def pytest_configure(config):
+ config.cache.set("my/name", [1,2,3])
+ config.cache.set("other/some", {1:2})
+ dp = config.cache.makedir("mydb")
+ dp.ensure("hello")
+ dp.ensure("world")
+ """)
+ result = testdir.runpytest()
+ assert result.ret == 5 # no tests executed
+ result = testdir.runpytest("--cache-show")
+ result.stdout.fnmatch_lines_random([
+ "*cachedir:*",
+ "-*cache values*-",
+ "*my/name contains:",
+ " [1, 2, 3]",
+ "*other/some contains*",
+ " {*1*: 2}",
+ "-*cache directories*-",
+ "*mydb/hello*length 0*",
+ "*mydb/world*length 0*",
+ ])
+
+
+class TestLastFailed(object):
+
+ def test_lastfailed_usecase(self, testdir, monkeypatch):
+ monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1)
+ p = testdir.makepyfile("""
+ def test_1():
+ assert 0
+ def test_2():
+ assert 0
+ def test_3():
+ assert 1
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*2 failed*",
+ ])
+ p.write(_pytest._code.Source("""
+ def test_1():
+ assert 1
+
+ def test_2():
+ assert 1
+
+ def test_3():
+ assert 0
+ """))
+ result = testdir.runpytest("--lf")
+ result.stdout.fnmatch_lines([
+ "*2 passed*1 desel*",
+ ])
+ result = testdir.runpytest("--lf")
+ result.stdout.fnmatch_lines([
+ "*1 failed*2 passed*",
+ ])
+ result = testdir.runpytest("--lf", "--cache-clear")
+ result.stdout.fnmatch_lines([
+ "*1 failed*2 passed*",
+ ])
+
+ # Run this again to make sure clear-cache is robust
+ if os.path.isdir('.cache'):
+ shutil.rmtree('.cache')
+ result = testdir.runpytest("--lf", "--cache-clear")
+ result.stdout.fnmatch_lines([
+ "*1 failed*2 passed*",
+ ])
+
+ def test_failedfirst_order(self, testdir):
+ testdir.tmpdir.join('test_a.py').write(_pytest._code.Source("""
+ def test_always_passes():
+ assert 1
+ """))
+ testdir.tmpdir.join('test_b.py').write(_pytest._code.Source("""
+ def test_always_fails():
+ assert 0
+ """))
+ result = testdir.runpytest()
+ # Test order will be collection order; alphabetical
+ result.stdout.fnmatch_lines([
+ "test_a.py*",
+ "test_b.py*",
+ ])
+ result = testdir.runpytest("--ff")
+ # Test order will be failing tests firs
+ result.stdout.fnmatch_lines([
+ "test_b.py*",
+ "test_a.py*",
+ ])
+
+ def test_lastfailed_failedfirst_order(self, testdir):
+ testdir.makepyfile(**{
+ 'test_a.py': """
+ def test_always_passes():
+ assert 1
+ """,
+ 'test_b.py': """
+ def test_always_fails():
+ assert 0
+ """,
+ })
+ result = testdir.runpytest()
+ # Test order will be collection order; alphabetical
+ result.stdout.fnmatch_lines([
+ "test_a.py*",
+ "test_b.py*",
+ ])
+ result = testdir.runpytest("--lf", "--ff")
+ # Test order will be failing tests firs
+ result.stdout.fnmatch_lines([
+ "test_b.py*",
+ ])
+ assert 'test_a.py' not in result.stdout.str()
+
+ def test_lastfailed_difference_invocations(self, testdir, monkeypatch):
+ monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1)
+ testdir.makepyfile(test_a="""
+ def test_a1():
+ assert 0
+ def test_a2():
+ assert 1
+ """, test_b="""
+ def test_b1():
+ assert 0
+ """)
+ p = testdir.tmpdir.join("test_a.py")
+ p2 = testdir.tmpdir.join("test_b.py")
+
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*2 failed*",
+ ])
+ result = testdir.runpytest("--lf", p2)
+ result.stdout.fnmatch_lines([
+ "*1 failed*",
+ ])
+ p2.write(_pytest._code.Source("""
+ def test_b1():
+ assert 1
+ """))
+ result = testdir.runpytest("--lf", p2)
+ result.stdout.fnmatch_lines([
+ "*1 passed*",
+ ])
+ result = testdir.runpytest("--lf", p)
+ result.stdout.fnmatch_lines([
+ "*1 failed*1 desel*",
+ ])
+
+ def test_lastfailed_usecase_splice(self, testdir, monkeypatch):
+ monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1)
+ testdir.makepyfile("""
+ def test_1():
+ assert 0
+ """)
+ p2 = testdir.tmpdir.join("test_something.py")
+ p2.write(_pytest._code.Source("""
+ def test_2():
+ assert 0
+ """))
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*2 failed*",
+ ])
+ result = testdir.runpytest("--lf", p2)
+ result.stdout.fnmatch_lines([
+ "*1 failed*",
+ ])
+ result = testdir.runpytest("--lf")
+ result.stdout.fnmatch_lines([
+ "*2 failed*",
+ ])
+
+ def test_lastfailed_xpass(self, testdir):
+ testdir.inline_runsource("""
+ import pytest
+ @pytest.mark.xfail
+ def test_hello():
+ assert 1
+ """)
+ config = testdir.parseconfigure()
+ lastfailed = config.cache.get("cache/lastfailed", -1)
+ assert lastfailed == -1
+
+ def test_non_serializable_parametrize(self, testdir):
+ """Test that failed parametrized tests with unmarshable parameters
+ don't break pytest-cache.
+ """
+ testdir.makepyfile(r"""
+ import pytest
+
+ @pytest.mark.parametrize('val', [
+ b'\xac\x10\x02G',
+ ])
+ def test_fail(val):
+ assert False
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines('*1 failed in*')
+
+ def test_terminal_report_lastfailed(self, testdir):
+ test_a = testdir.makepyfile(test_a="""
+ def test_a1():
+ pass
+ def test_a2():
+ pass
+ """)
+ test_b = testdir.makepyfile(test_b="""
+ def test_b1():
+ assert 0
+ def test_b2():
+ assert 0
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ 'collected 4 items',
+ '*2 failed, 2 passed in*',
+ ])
+
+ result = testdir.runpytest('--lf')
+ result.stdout.fnmatch_lines([
+ 'collected 4 items',
+ 'run-last-failure: rerun previous 2 failures',
+ '*2 failed, 2 deselected in*',
+ ])
+
+ result = testdir.runpytest(test_a, '--lf')
+ result.stdout.fnmatch_lines([
+ 'collected 2 items',
+ 'run-last-failure: run all (no recorded failures)',
+ '*2 passed in*',
+ ])
+
+ result = testdir.runpytest(test_b, '--lf')
+ result.stdout.fnmatch_lines([
+ 'collected 2 items',
+ 'run-last-failure: rerun previous 2 failures',
+ '*2 failed in*',
+ ])
+
+ result = testdir.runpytest('test_b.py::test_b1', '--lf')
+ result.stdout.fnmatch_lines([
+ 'collected 1 item',
+ 'run-last-failure: rerun previous 1 failure',
+ '*1 failed in*',
+ ])
+
+ def test_terminal_report_failedfirst(self, testdir):
+ testdir.makepyfile(test_a="""
+ def test_a1():
+ assert 0
+ def test_a2():
+ pass
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ 'collected 2 items',
+ '*1 failed, 1 passed in*',
+ ])
+
+ result = testdir.runpytest('--ff')
+ result.stdout.fnmatch_lines([
+ 'collected 2 items',
+ 'run-last-failure: rerun previous 1 failure first',
+ '*1 failed, 1 passed in*',
+ ])
+
+ def test_lastfailed_collectfailure(self, testdir, monkeypatch):
+
+ testdir.makepyfile(test_maybe="""
+ import py
+ env = py.std.os.environ
+ if '1' == env['FAILIMPORT']:
+ raise ImportError('fail')
+ def test_hello():
+ assert '0' == env['FAILTEST']
+ """)
+
+ def rlf(fail_import, fail_run):
+ monkeypatch.setenv('FAILIMPORT', fail_import)
+ monkeypatch.setenv('FAILTEST', fail_run)
+
+ testdir.runpytest('-q')
+ config = testdir.parseconfigure()
+ lastfailed = config.cache.get("cache/lastfailed", -1)
+ return lastfailed
+
+ lastfailed = rlf(fail_import=0, fail_run=0)
+ assert lastfailed == -1
+
+ lastfailed = rlf(fail_import=1, fail_run=0)
+ assert list(lastfailed) == ['test_maybe.py']
+
+ lastfailed = rlf(fail_import=0, fail_run=1)
+ assert list(lastfailed) == ['test_maybe.py::test_hello']
+
+ def test_lastfailed_failure_subset(self, testdir, monkeypatch):
+
+ testdir.makepyfile(test_maybe="""
+ import py
+ env = py.std.os.environ
+ if '1' == env['FAILIMPORT']:
+ raise ImportError('fail')
+ def test_hello():
+ assert '0' == env['FAILTEST']
+ """)
+
+ testdir.makepyfile(test_maybe2="""
+ import py
+ env = py.std.os.environ
+ if '1' == env['FAILIMPORT']:
+ raise ImportError('fail')
+ def test_hello():
+ assert '0' == env['FAILTEST']
+
+ def test_pass():
+ pass
+ """)
+
+ def rlf(fail_import, fail_run, args=()):
+ monkeypatch.setenv('FAILIMPORT', fail_import)
+ monkeypatch.setenv('FAILTEST', fail_run)
+
+ result = testdir.runpytest('-q', '--lf', *args)
+ config = testdir.parseconfigure()
+ lastfailed = config.cache.get("cache/lastfailed", -1)
+ return result, lastfailed
+
+ result, lastfailed = rlf(fail_import=0, fail_run=0)
+ assert lastfailed == -1
+ result.stdout.fnmatch_lines([
+ '*3 passed*',
+ ])
+
+ result, lastfailed = rlf(fail_import=1, fail_run=0)
+ assert sorted(list(lastfailed)) == ['test_maybe.py', 'test_maybe2.py']
+
+ result, lastfailed = rlf(fail_import=0, fail_run=0,
+ args=('test_maybe2.py',))
+ assert list(lastfailed) == ['test_maybe.py']
+
+ # edge case of test selection - even if we remember failures
+ # from other tests we still need to run all tests if no test
+ # matches the failures
+ result, lastfailed = rlf(fail_import=0, fail_run=0,
+ args=('test_maybe2.py',))
+ assert list(lastfailed) == ['test_maybe.py']
+ result.stdout.fnmatch_lines([
+ '*2 passed*',
+ ])
+
+ def test_lastfailed_creates_cache_when_needed(self, testdir):
+ # Issue #1342
+ testdir.makepyfile(test_empty='')
+ testdir.runpytest('-q', '--lf')
+ assert not os.path.exists('.cache')
+
+ testdir.makepyfile(test_successful='def test_success():\n assert True')
+ testdir.runpytest('-q', '--lf')
+ assert not os.path.exists('.cache')
+
+ testdir.makepyfile(test_errored='def test_error():\n assert False')
+ testdir.runpytest('-q', '--lf')
+ assert os.path.exists('.cache')
+
+ def test_xfail_not_considered_failure(self, testdir):
+ testdir.makepyfile('''
+ import pytest
+ @pytest.mark.xfail
+ def test():
+ assert 0
+ ''')
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines('*1 xfailed*')
+ assert self.get_cached_last_failed(testdir) == []
+
+ def test_xfail_strict_considered_failure(self, testdir):
+ testdir.makepyfile('''
+ import pytest
+ @pytest.mark.xfail(strict=True)
+ def test():
+ pass
+ ''')
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines('*1 failed*')
+ assert self.get_cached_last_failed(testdir) == ['test_xfail_strict_considered_failure.py::test']
+
+ @pytest.mark.parametrize('mark', ['mark.xfail', 'mark.skip'])
+ def test_failed_changed_to_xfail_or_skip(self, testdir, mark):
+ testdir.makepyfile('''
+ import pytest
+ def test():
+ assert 0
+ ''')
+ result = testdir.runpytest()
+ assert self.get_cached_last_failed(testdir) == ['test_failed_changed_to_xfail_or_skip.py::test']
+ assert result.ret == 1
+
+ testdir.makepyfile('''
+ import pytest
+ @pytest.{mark}
+ def test():
+ assert 0
+ '''.format(mark=mark))
+ result = testdir.runpytest()
+ assert result.ret == 0
+ assert self.get_cached_last_failed(testdir) == []
+ assert result.ret == 0
+
+ def get_cached_last_failed(self, testdir):
+ config = testdir.parseconfigure()
+ return sorted(config.cache.get("cache/lastfailed", {}))
+
+ def test_cache_cumulative(self, testdir):
+ """
+ Test workflow where user fixes errors gradually file by file using --lf.
+ """
+ # 1. initial run
+ test_bar = testdir.makepyfile(test_bar="""
+ def test_bar_1():
+ pass
+ def test_bar_2():
+ assert 0
+ """)
+ test_foo = testdir.makepyfile(test_foo="""
+ def test_foo_3():
+ pass
+ def test_foo_4():
+ assert 0
+ """)
+ testdir.runpytest()
+ assert self.get_cached_last_failed(testdir) == ['test_bar.py::test_bar_2', 'test_foo.py::test_foo_4']
+
+ # 2. fix test_bar_2, run only test_bar.py
+ testdir.makepyfile(test_bar="""
+ def test_bar_1():
+ pass
+ def test_bar_2():
+ pass
+ """)
+ result = testdir.runpytest(test_bar)
+ result.stdout.fnmatch_lines('*2 passed*')
+ # ensure cache does not forget that test_foo_4 failed once before
+ assert self.get_cached_last_failed(testdir) == ['test_foo.py::test_foo_4']
+
+ result = testdir.runpytest('--last-failed')
+ result.stdout.fnmatch_lines('*1 failed, 3 deselected*')
+ assert self.get_cached_last_failed(testdir) == ['test_foo.py::test_foo_4']
+
+ # 3. fix test_foo_4, run only test_foo.py
+ test_foo = testdir.makepyfile(test_foo="""
+ def test_foo_3():
+ pass
+ def test_foo_4():
+ pass
+ """)
+ result = testdir.runpytest(test_foo, '--last-failed')
+ result.stdout.fnmatch_lines('*1 passed, 1 deselected*')
+ assert self.get_cached_last_failed(testdir) == []
+
+ result = testdir.runpytest('--last-failed')
+ result.stdout.fnmatch_lines('*4 passed*')
+ assert self.get_cached_last_failed(testdir) == []
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_capture.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_capture.py
new file mode 100644
index 00000000000..f769a725dc4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_capture.py
@@ -0,0 +1,1274 @@
+from __future__ import absolute_import, division, print_function
+# note: py.io capture tests where copied from
+# pylib 1.4.20.dev2 (rev 13d9af95547e)
+from __future__ import with_statement
+import pickle
+import os
+import sys
+from io import UnsupportedOperation
+
+import _pytest._code
+import py
+import pytest
+import contextlib
+
+from _pytest import capture
+from _pytest.capture import CaptureManager
+from _pytest.main import EXIT_NOTESTSCOLLECTED
+
+
+needsosdup = pytest.mark.xfail("not hasattr(os, 'dup')")
+
+if sys.version_info >= (3, 0):
+ def tobytes(obj):
+ if isinstance(obj, str):
+ obj = obj.encode('UTF-8')
+ assert isinstance(obj, bytes)
+ return obj
+
+ def totext(obj):
+ if isinstance(obj, bytes):
+ obj = str(obj, 'UTF-8')
+ assert isinstance(obj, str)
+ return obj
+else:
+ def tobytes(obj):
+ if isinstance(obj, unicode):
+ obj = obj.encode('UTF-8')
+ assert isinstance(obj, str)
+ return obj
+
+ def totext(obj):
+ if isinstance(obj, str):
+ obj = unicode(obj, 'UTF-8')
+ assert isinstance(obj, unicode)
+ return obj
+
+
+def oswritebytes(fd, obj):
+ os.write(fd, tobytes(obj))
+
+
+def StdCaptureFD(out=True, err=True, in_=True):
+ return capture.MultiCapture(out, err, in_, Capture=capture.FDCapture)
+
+
+def StdCapture(out=True, err=True, in_=True):
+ return capture.MultiCapture(out, err, in_, Capture=capture.SysCapture)
+
+
+class TestCaptureManager(object):
+ def test_getmethod_default_no_fd(self, monkeypatch):
+ from _pytest.capture import pytest_addoption
+ from _pytest.config import Parser
+ parser = Parser()
+ pytest_addoption(parser)
+ default = parser._groups[0].options[0].default
+ assert default == "fd" if hasattr(os, "dup") else "sys"
+ parser = Parser()
+ monkeypatch.delattr(os, 'dup', raising=False)
+ pytest_addoption(parser)
+ assert parser._groups[0].options[0].default == "sys"
+
+ @needsosdup
+ @pytest.mark.parametrize("method",
+ ['no', 'sys', pytest.mark.skipif('not hasattr(os, "dup")', 'fd')])
+ def test_capturing_basic_api(self, method):
+ capouter = StdCaptureFD()
+ old = sys.stdout, sys.stderr, sys.stdin
+ try:
+ capman = CaptureManager(method)
+ capman.start_global_capturing()
+ outerr = capman.suspend_global_capture()
+ assert outerr == ("", "")
+ outerr = capman.suspend_global_capture()
+ assert outerr == ("", "")
+ print("hello")
+ out, err = capman.suspend_global_capture()
+ if method == "no":
+ assert old == (sys.stdout, sys.stderr, sys.stdin)
+ else:
+ assert not out
+ capman.resume_global_capture()
+ print("hello")
+ out, err = capman.suspend_global_capture()
+ if method != "no":
+ assert out == "hello\n"
+ capman.stop_global_capturing()
+ finally:
+ capouter.stop_capturing()
+
+ @needsosdup
+ def test_init_capturing(self):
+ capouter = StdCaptureFD()
+ try:
+ capman = CaptureManager("fd")
+ capman.start_global_capturing()
+ pytest.raises(AssertionError, "capman.start_global_capturing()")
+ capman.stop_global_capturing()
+ finally:
+ capouter.stop_capturing()
+
+
+@pytest.mark.parametrize("method", ['fd', 'sys'])
+def test_capturing_unicode(testdir, method):
+ if hasattr(sys, "pypy_version_info") and sys.pypy_version_info < (2, 2):
+ pytest.xfail("does not work on pypy < 2.2")
+ if sys.version_info >= (3, 0):
+ obj = "'b\u00f6y'"
+ else:
+ obj = "u'\u00f6y'"
+ testdir.makepyfile("""
+ # coding=utf8
+ # taken from issue 227 from nosetests
+ def test_unicode():
+ import sys
+ print (sys.stdout)
+ print (%s)
+ """ % obj)
+ result = testdir.runpytest("--capture=%s" % method)
+ result.stdout.fnmatch_lines([
+ "*1 passed*"
+ ])
+
+
+@pytest.mark.parametrize("method", ['fd', 'sys'])
+def test_capturing_bytes_in_utf8_encoding(testdir, method):
+ testdir.makepyfile("""
+ def test_unicode():
+ print ('b\\u00f6y')
+ """)
+ result = testdir.runpytest("--capture=%s" % method)
+ result.stdout.fnmatch_lines([
+ "*1 passed*"
+ ])
+
+
+def test_collect_capturing(testdir):
+ p = testdir.makepyfile("""
+ print ("collect %s failure" % 13)
+ import xyz42123
+ """)
+ result = testdir.runpytest(p)
+ result.stdout.fnmatch_lines([
+ "*Captured stdout*",
+ "*collect 13 failure*",
+ ])
+
+
+class TestPerTestCapturing(object):
+ def test_capture_and_fixtures(self, testdir):
+ p = testdir.makepyfile("""
+ def setup_module(mod):
+ print ("setup module")
+ def setup_function(function):
+ print ("setup " + function.__name__)
+ def test_func1():
+ print ("in func1")
+ assert 0
+ def test_func2():
+ print ("in func2")
+ assert 0
+ """)
+ result = testdir.runpytest(p)
+ result.stdout.fnmatch_lines([
+ "setup module*",
+ "setup test_func1*",
+ "in func1*",
+ "setup test_func2*",
+ "in func2*",
+ ])
+
+ @pytest.mark.xfail(reason="unimplemented feature")
+ def test_capture_scope_cache(self, testdir):
+ p = testdir.makepyfile("""
+ import sys
+ def setup_module(func):
+ print ("module-setup")
+ def setup_function(func):
+ print ("function-setup")
+ def test_func():
+ print ("in function")
+ assert 0
+ def teardown_function(func):
+ print ("in teardown")
+ """)
+ result = testdir.runpytest(p)
+ result.stdout.fnmatch_lines([
+ "*test_func():*",
+ "*Captured stdout during setup*",
+ "module-setup*",
+ "function-setup*",
+ "*Captured stdout*",
+ "in teardown*",
+ ])
+
+ def test_no_carry_over(self, testdir):
+ p = testdir.makepyfile("""
+ def test_func1():
+ print ("in func1")
+ def test_func2():
+ print ("in func2")
+ assert 0
+ """)
+ result = testdir.runpytest(p)
+ s = result.stdout.str()
+ assert "in func1" not in s
+ assert "in func2" in s
+
+ def test_teardown_capturing(self, testdir):
+ p = testdir.makepyfile("""
+ def setup_function(function):
+ print ("setup func1")
+ def teardown_function(function):
+ print ("teardown func1")
+ assert 0
+ def test_func1():
+ print ("in func1")
+ pass
+ """)
+ result = testdir.runpytest(p)
+ result.stdout.fnmatch_lines([
+ '*teardown_function*',
+ '*Captured stdout*',
+ "setup func1*",
+ "in func1*",
+ "teardown func1*",
+ # "*1 fixture failure*"
+ ])
+
+ def test_teardown_capturing_final(self, testdir):
+ p = testdir.makepyfile("""
+ def teardown_module(mod):
+ print ("teardown module")
+ assert 0
+ def test_func():
+ pass
+ """)
+ result = testdir.runpytest(p)
+ result.stdout.fnmatch_lines([
+ "*def teardown_module(mod):*",
+ "*Captured stdout*",
+ "*teardown module*",
+ "*1 error*",
+ ])
+
+ def test_capturing_outerr(self, testdir):
+ p1 = testdir.makepyfile("""
+ import sys
+ def test_capturing():
+ print (42)
+ sys.stderr.write(str(23))
+ def test_capturing_error():
+ print (1)
+ sys.stderr.write(str(2))
+ raise ValueError
+ """)
+ result = testdir.runpytest(p1)
+ result.stdout.fnmatch_lines([
+ "*test_capturing_outerr.py .F*",
+ "====* FAILURES *====",
+ "____*____",
+ "*test_capturing_outerr.py:8: ValueError",
+ "*--- Captured stdout *call*",
+ "1",
+ "*--- Captured stderr *call*",
+ "2",
+ ])
+
+
+class TestLoggingInteraction(object):
+ def test_logging_stream_ownership(self, testdir):
+ p = testdir.makepyfile("""
+ def test_logging():
+ import logging
+ import pytest
+ stream = capture.CaptureIO()
+ logging.basicConfig(stream=stream)
+ stream.close() # to free memory/release resources
+ """)
+ result = testdir.runpytest_subprocess(p)
+ assert result.stderr.str().find("atexit") == -1
+
+ def test_logging_and_immediate_setupteardown(self, testdir):
+ p = testdir.makepyfile("""
+ import logging
+ def setup_function(function):
+ logging.warn("hello1")
+
+ def test_logging():
+ logging.warn("hello2")
+ assert 0
+
+ def teardown_function(function):
+ logging.warn("hello3")
+ assert 0
+ """)
+ for optargs in (('--capture=sys',), ('--capture=fd',)):
+ print(optargs)
+ result = testdir.runpytest_subprocess(p, *optargs)
+ s = result.stdout.str()
+ result.stdout.fnmatch_lines([
+ "*WARN*hello3", # errors show first!
+ "*WARN*hello1",
+ "*WARN*hello2",
+ ])
+ # verify proper termination
+ assert "closed" not in s
+
+ def test_logging_and_crossscope_fixtures(self, testdir):
+ p = testdir.makepyfile("""
+ import logging
+ def setup_module(function):
+ logging.warn("hello1")
+
+ def test_logging():
+ logging.warn("hello2")
+ assert 0
+
+ def teardown_module(function):
+ logging.warn("hello3")
+ assert 0
+ """)
+ for optargs in (('--capture=sys',), ('--capture=fd',)):
+ print(optargs)
+ result = testdir.runpytest_subprocess(p, *optargs)
+ s = result.stdout.str()
+ result.stdout.fnmatch_lines([
+ "*WARN*hello3", # errors come first
+ "*WARN*hello1",
+ "*WARN*hello2",
+ ])
+ # verify proper termination
+ assert "closed" not in s
+
+ def test_conftestlogging_is_shown(self, testdir):
+ testdir.makeconftest("""
+ import logging
+ logging.basicConfig()
+ logging.warn("hello435")
+ """)
+ # make sure that logging is still captured in tests
+ result = testdir.runpytest_subprocess("-s", "-p", "no:capturelog")
+ assert result.ret == EXIT_NOTESTSCOLLECTED
+ result.stderr.fnmatch_lines([
+ "WARNING*hello435*",
+ ])
+ assert 'operation on closed file' not in result.stderr.str()
+
+ def test_conftestlogging_and_test_logging(self, testdir):
+ testdir.makeconftest("""
+ import logging
+ logging.basicConfig()
+ """)
+ # make sure that logging is still captured in tests
+ p = testdir.makepyfile("""
+ def test_hello():
+ import logging
+ logging.warn("hello433")
+ assert 0
+ """)
+ result = testdir.runpytest_subprocess(p, "-p", "no:capturelog")
+ assert result.ret != 0
+ result.stdout.fnmatch_lines([
+ "WARNING*hello433*",
+ ])
+ assert 'something' not in result.stderr.str()
+ assert 'operation on closed file' not in result.stderr.str()
+
+
+class TestCaptureFixture(object):
+ @pytest.mark.parametrize("opt", [[], ["-s"]])
+ def test_std_functional(self, testdir, opt):
+ reprec = testdir.inline_runsource("""
+ def test_hello(capsys):
+ print (42)
+ out, err = capsys.readouterr()
+ assert out.startswith("42")
+ """, *opt)
+ reprec.assertoutcome(passed=1)
+
+ def test_capsyscapfd(self, testdir):
+ p = testdir.makepyfile("""
+ def test_one(capsys, capfd):
+ pass
+ def test_two(capfd, capsys):
+ pass
+ """)
+ result = testdir.runpytest(p)
+ result.stdout.fnmatch_lines([
+ "*ERROR*setup*test_one*",
+ "E*capfd*capsys*same*time*",
+ "*ERROR*setup*test_two*",
+ "E*capsys*capfd*same*time*",
+ "*2 error*"])
+
+ def test_capturing_getfixturevalue(self, testdir):
+ """Test that asking for "capfd" and "capsys" using request.getfixturevalue
+ in the same test is an error.
+ """
+ testdir.makepyfile("""
+ def test_one(capsys, request):
+ request.getfixturevalue("capfd")
+ def test_two(capfd, request):
+ request.getfixturevalue("capsys")
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*test_one*",
+ "*capsys*capfd*same*time*",
+ "*test_two*",
+ "*capfd*capsys*same*time*",
+ "*2 failed in*",
+ ])
+
+ def test_capsyscapfdbinary(self, testdir):
+ p = testdir.makepyfile("""
+ def test_one(capsys, capfdbinary):
+ pass
+ """)
+ result = testdir.runpytest(p)
+ result.stdout.fnmatch_lines([
+ "*ERROR*setup*test_one*",
+ "E*capfdbinary*capsys*same*time*",
+ "*1 error*"])
+
+ @pytest.mark.parametrize("method", ["sys", "fd"])
+ def test_capture_is_represented_on_failure_issue128(self, testdir, method):
+ p = testdir.makepyfile("""
+ def test_hello(cap%s):
+ print ("xxx42xxx")
+ assert 0
+ """ % method)
+ result = testdir.runpytest(p)
+ result.stdout.fnmatch_lines([
+ "xxx42xxx",
+ ])
+
+ @needsosdup
+ def test_stdfd_functional(self, testdir):
+ reprec = testdir.inline_runsource("""
+ def test_hello(capfd):
+ import os
+ os.write(1, "42".encode('ascii'))
+ out, err = capfd.readouterr()
+ assert out.startswith("42")
+ capfd.close()
+ """)
+ reprec.assertoutcome(passed=1)
+
+ @needsosdup
+ def test_capfdbinary(self, testdir):
+ reprec = testdir.inline_runsource("""
+ def test_hello(capfdbinary):
+ import os
+ # some likely un-decodable bytes
+ os.write(1, b'\\xfe\\x98\\x20')
+ out, err = capfdbinary.readouterr()
+ assert out == b'\\xfe\\x98\\x20'
+ assert err == b''
+ """)
+ reprec.assertoutcome(passed=1)
+
+ @pytest.mark.skipif(
+ sys.version_info < (3,),
+ reason='only have capsysbinary in python 3',
+ )
+ def test_capsysbinary(self, testdir):
+ reprec = testdir.inline_runsource("""
+ def test_hello(capsysbinary):
+ import sys
+ # some likely un-decodable bytes
+ sys.stdout.buffer.write(b'\\xfe\\x98\\x20')
+ out, err = capsysbinary.readouterr()
+ assert out == b'\\xfe\\x98\\x20'
+ assert err == b''
+ """)
+ reprec.assertoutcome(passed=1)
+
+ @pytest.mark.skipif(
+ sys.version_info >= (3,),
+ reason='only have capsysbinary in python 3',
+ )
+ def test_capsysbinary_forbidden_in_python2(self, testdir):
+ testdir.makepyfile("""
+ def test_hello(capsysbinary):
+ pass
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*test_hello*",
+ "*capsysbinary is only supported on python 3*",
+ "*1 error in*",
+ ])
+
+ def test_partial_setup_failure(self, testdir):
+ p = testdir.makepyfile("""
+ def test_hello(capsys, missingarg):
+ pass
+ """)
+ result = testdir.runpytest(p)
+ result.stdout.fnmatch_lines([
+ "*test_partial_setup_failure*",
+ "*1 error*",
+ ])
+
+ @needsosdup
+ def test_keyboardinterrupt_disables_capturing(self, testdir):
+ p = testdir.makepyfile("""
+ def test_hello(capfd):
+ import os
+ os.write(1, str(42).encode('ascii'))
+ raise KeyboardInterrupt()
+ """)
+ result = testdir.runpytest_subprocess(p)
+ result.stdout.fnmatch_lines([
+ "*KeyboardInterrupt*"
+ ])
+ assert result.ret == 2
+
+ @pytest.mark.issue14
+ def test_capture_and_logging(self, testdir):
+ p = testdir.makepyfile("""
+ import logging
+ def test_log(capsys):
+ logging.error('x')
+ """)
+ result = testdir.runpytest_subprocess(p)
+ assert 'closed' not in result.stderr.str()
+
+ @pytest.mark.parametrize('fixture', ['capsys', 'capfd'])
+ @pytest.mark.parametrize('no_capture', [True, False])
+ def test_disabled_capture_fixture(self, testdir, fixture, no_capture):
+ testdir.makepyfile("""
+ def test_disabled({fixture}):
+ print('captured before')
+ with {fixture}.disabled():
+ print('while capture is disabled')
+ print('captured after')
+ assert {fixture}.readouterr() == ('captured before\\ncaptured after\\n', '')
+
+ def test_normal():
+ print('test_normal executed')
+ """.format(fixture=fixture))
+ args = ('-s',) if no_capture else ()
+ result = testdir.runpytest_subprocess(*args)
+ result.stdout.fnmatch_lines("""
+ *while capture is disabled*
+ """)
+ assert 'captured before' not in result.stdout.str()
+ assert 'captured after' not in result.stdout.str()
+ if no_capture:
+ assert 'test_normal executed' in result.stdout.str()
+ else:
+ assert 'test_normal executed' not in result.stdout.str()
+
+ @pytest.mark.parametrize('fixture', ['capsys', 'capfd'])
+ def test_fixture_use_by_other_fixtures(self, testdir, fixture):
+ """
+ Ensure that capsys and capfd can be used by other fixtures during setup and teardown.
+ """
+ testdir.makepyfile("""
+ from __future__ import print_function
+ import sys
+ import pytest
+
+ @pytest.fixture
+ def captured_print({fixture}):
+ print('stdout contents begin')
+ print('stderr contents begin', file=sys.stderr)
+ out, err = {fixture}.readouterr()
+
+ yield out, err
+
+ print('stdout contents end')
+ print('stderr contents end', file=sys.stderr)
+ out, err = {fixture}.readouterr()
+ assert out == 'stdout contents end\\n'
+ assert err == 'stderr contents end\\n'
+
+ def test_captured_print(captured_print):
+ out, err = captured_print
+ assert out == 'stdout contents begin\\n'
+ assert err == 'stderr contents begin\\n'
+ """.format(fixture=fixture))
+ result = testdir.runpytest_subprocess()
+ result.stdout.fnmatch_lines("*1 passed*")
+ assert 'stdout contents begin' not in result.stdout.str()
+ assert 'stderr contents begin' not in result.stdout.str()
+
+
+def test_setup_failure_does_not_kill_capturing(testdir):
+ sub1 = testdir.mkpydir("sub1")
+ sub1.join("conftest.py").write(_pytest._code.Source("""
+ def pytest_runtest_setup(item):
+ raise ValueError(42)
+ """))
+ sub1.join("test_mod.py").write("def test_func1(): pass")
+ result = testdir.runpytest(testdir.tmpdir, '--traceconfig')
+ result.stdout.fnmatch_lines([
+ "*ValueError(42)*",
+ "*1 error*"
+ ])
+
+
+def test_fdfuncarg_skips_on_no_osdup(testdir):
+ testdir.makepyfile("""
+ import os
+ if hasattr(os, 'dup'):
+ del os.dup
+ def test_hello(capfd):
+ pass
+ """)
+ result = testdir.runpytest_subprocess("--capture=no")
+ result.stdout.fnmatch_lines([
+ "*1 skipped*"
+ ])
+
+
+def test_capture_conftest_runtest_setup(testdir):
+ testdir.makeconftest("""
+ def pytest_runtest_setup():
+ print ("hello19")
+ """)
+ testdir.makepyfile("def test_func(): pass")
+ result = testdir.runpytest()
+ assert result.ret == 0
+ assert 'hello19' not in result.stdout.str()
+
+
+def test_capture_badoutput_issue412(testdir):
+ testdir.makepyfile("""
+ import os
+
+ def test_func():
+ omg = bytearray([1,129,1])
+ os.write(1, omg)
+ assert 0
+ """)
+ result = testdir.runpytest('--cap=fd')
+ result.stdout.fnmatch_lines('''
+ *def test_func*
+ *assert 0*
+ *Captured*
+ *1 failed*
+ ''')
+
+
+def test_capture_early_option_parsing(testdir):
+ testdir.makeconftest("""
+ def pytest_runtest_setup():
+ print ("hello19")
+ """)
+ testdir.makepyfile("def test_func(): pass")
+ result = testdir.runpytest("-vs")
+ assert result.ret == 0
+ assert 'hello19' in result.stdout.str()
+
+
+def test_capture_binary_output(testdir):
+ testdir.makepyfile(r"""
+ import pytest
+
+ def test_a():
+ import sys
+ import subprocess
+ subprocess.call([sys.executable, __file__])
+
+ def test_foo():
+ import os;os.write(1, b'\xc3')
+
+ if __name__ == '__main__':
+ test_foo()
+ """)
+ result = testdir.runpytest('--assert=plain')
+ result.assert_outcomes(passed=2)
+
+
+def test_error_during_readouterr(testdir):
+ """Make sure we suspend capturing if errors occur during readouterr"""
+ testdir.makepyfile(pytest_xyz="""
+ from _pytest.capture import FDCapture
+ def bad_snap(self):
+ raise Exception('boom')
+ assert FDCapture.snap
+ FDCapture.snap = bad_snap
+ """)
+ result = testdir.runpytest_subprocess(
+ "-p", "pytest_xyz", "--version", syspathinsert=True
+ )
+ result.stderr.fnmatch_lines([
+ "*in bad_snap",
+ " raise Exception('boom')",
+ "Exception: boom",
+ ])
+
+
+class TestCaptureIO(object):
+ def test_text(self):
+ f = capture.CaptureIO()
+ f.write("hello")
+ s = f.getvalue()
+ assert s == "hello"
+ f.close()
+
+ def test_unicode_and_str_mixture(self):
+ f = capture.CaptureIO()
+ if sys.version_info >= (3, 0):
+ f.write("\u00f6")
+ pytest.raises(TypeError, "f.write(bytes('hello', 'UTF-8'))")
+ else:
+ f.write(unicode("\u00f6", 'UTF-8'))
+ f.write("hello") # bytes
+ s = f.getvalue()
+ f.close()
+ assert isinstance(s, unicode)
+
+ @pytest.mark.skipif(
+ sys.version_info[0] == 2,
+ reason='python 3 only behaviour',
+ )
+ def test_write_bytes_to_buffer(self):
+ """In python3, stdout / stderr are text io wrappers (exposing a buffer
+ property of the underlying bytestream). See issue #1407
+ """
+ f = capture.CaptureIO()
+ f.buffer.write(b'foo\r\n')
+ assert f.getvalue() == 'foo\r\n'
+
+
+def test_bytes_io():
+ f = py.io.BytesIO()
+ f.write(tobytes("hello"))
+ pytest.raises(TypeError, "f.write(totext('hello'))")
+ s = f.getvalue()
+ assert s == tobytes("hello")
+
+
+def test_dontreadfrominput():
+ from _pytest.capture import DontReadFromInput
+ f = DontReadFromInput()
+ assert not f.isatty()
+ pytest.raises(IOError, f.read)
+ pytest.raises(IOError, f.readlines)
+ pytest.raises(IOError, iter, f)
+ pytest.raises(UnsupportedOperation, f.fileno)
+ f.close() # just for completeness
+
+
+@pytest.mark.skipif('sys.version_info < (3,)', reason='python2 has no buffer')
+def test_dontreadfrominput_buffer_python3():
+ from _pytest.capture import DontReadFromInput
+ f = DontReadFromInput()
+ fb = f.buffer
+ assert not fb.isatty()
+ pytest.raises(IOError, fb.read)
+ pytest.raises(IOError, fb.readlines)
+ pytest.raises(IOError, iter, fb)
+ pytest.raises(ValueError, fb.fileno)
+ f.close() # just for completeness
+
+
+@pytest.mark.skipif('sys.version_info >= (3,)', reason='python2 has no buffer')
+def test_dontreadfrominput_buffer_python2():
+ from _pytest.capture import DontReadFromInput
+ f = DontReadFromInput()
+ with pytest.raises(AttributeError):
+ f.buffer
+ f.close() # just for completeness
+
+
+@pytest.yield_fixture
+def tmpfile(testdir):
+ f = testdir.makepyfile("").open('wb+')
+ yield f
+ if not f.closed:
+ f.close()
+
+
+@needsosdup
+def test_dupfile(tmpfile):
+ flist = []
+ for i in range(5):
+ nf = capture.safe_text_dupfile(tmpfile, "wb")
+ assert nf != tmpfile
+ assert nf.fileno() != tmpfile.fileno()
+ assert nf not in flist
+ print(i, end="", file=nf)
+ flist.append(nf)
+
+ fname_open = flist[0].name
+ assert fname_open == repr(flist[0].buffer)
+
+ for i in range(5):
+ f = flist[i]
+ f.close()
+ fname_closed = flist[0].name
+ assert fname_closed == repr(flist[0].buffer)
+ assert fname_closed != fname_open
+ tmpfile.seek(0)
+ s = tmpfile.read()
+ assert "01234" in repr(s)
+ tmpfile.close()
+ assert fname_closed == repr(flist[0].buffer)
+
+
+def test_dupfile_on_bytesio():
+ io = py.io.BytesIO()
+ f = capture.safe_text_dupfile(io, "wb")
+ f.write("hello")
+ assert io.getvalue() == b"hello"
+ assert 'BytesIO object' in f.name
+
+
+def test_dupfile_on_textio():
+ io = py.io.TextIO()
+ f = capture.safe_text_dupfile(io, "wb")
+ f.write("hello")
+ assert io.getvalue() == "hello"
+ assert not hasattr(f, 'name')
+
+
+@contextlib.contextmanager
+def lsof_check():
+ pid = os.getpid()
+ try:
+ out = py.process.cmdexec("lsof -p %d" % pid)
+ except (py.process.cmdexec.Error, UnicodeDecodeError):
+ # about UnicodeDecodeError, see note on pytester
+ pytest.skip("could not run 'lsof'")
+ yield
+ out2 = py.process.cmdexec("lsof -p %d" % pid)
+ len1 = len([x for x in out.split("\n") if "REG" in x])
+ len2 = len([x for x in out2.split("\n") if "REG" in x])
+ assert len2 < len1 + 3, out2
+
+
+class TestFDCapture(object):
+ pytestmark = needsosdup
+
+ def test_simple(self, tmpfile):
+ fd = tmpfile.fileno()
+ cap = capture.FDCapture(fd)
+ data = tobytes("hello")
+ os.write(fd, data)
+ s = cap.snap()
+ cap.done()
+ assert not s
+ cap = capture.FDCapture(fd)
+ cap.start()
+ os.write(fd, data)
+ s = cap.snap()
+ cap.done()
+ assert s == "hello"
+
+ def test_simple_many(self, tmpfile):
+ for i in range(10):
+ self.test_simple(tmpfile)
+
+ def test_simple_many_check_open_files(self, testdir):
+ with lsof_check():
+ with testdir.makepyfile("").open('wb+') as tmpfile:
+ self.test_simple_many(tmpfile)
+
+ def test_simple_fail_second_start(self, tmpfile):
+ fd = tmpfile.fileno()
+ cap = capture.FDCapture(fd)
+ cap.done()
+ pytest.raises(ValueError, cap.start)
+
+ def test_stderr(self):
+ cap = capture.FDCapture(2)
+ cap.start()
+ print("hello", file=sys.stderr)
+ s = cap.snap()
+ cap.done()
+ assert s == "hello\n"
+
+ def test_stdin(self, tmpfile):
+ cap = capture.FDCapture(0)
+ cap.start()
+ x = os.read(0, 100).strip()
+ cap.done()
+ assert x == tobytes('')
+
+ def test_writeorg(self, tmpfile):
+ data1, data2 = tobytes("foo"), tobytes("bar")
+ cap = capture.FDCapture(tmpfile.fileno())
+ cap.start()
+ tmpfile.write(data1)
+ tmpfile.flush()
+ cap.writeorg(data2)
+ scap = cap.snap()
+ cap.done()
+ assert scap == totext(data1)
+ with open(tmpfile.name, 'rb') as stmp_file:
+ stmp = stmp_file.read()
+ assert stmp == data2
+
+ def test_simple_resume_suspend(self, tmpfile):
+ with saved_fd(1):
+ cap = capture.FDCapture(1)
+ cap.start()
+ data = tobytes("hello")
+ os.write(1, data)
+ sys.stdout.write("whatever")
+ s = cap.snap()
+ assert s == "hellowhatever"
+ cap.suspend()
+ os.write(1, tobytes("world"))
+ sys.stdout.write("qlwkej")
+ assert not cap.snap()
+ cap.resume()
+ os.write(1, tobytes("but now"))
+ sys.stdout.write(" yes\n")
+ s = cap.snap()
+ assert s == "but now yes\n"
+ cap.suspend()
+ cap.done()
+ pytest.raises(AttributeError, cap.suspend)
+
+
+@contextlib.contextmanager
+def saved_fd(fd):
+ new_fd = os.dup(fd)
+ try:
+ yield
+ finally:
+ os.dup2(new_fd, fd)
+ os.close(new_fd)
+
+
+class TestStdCapture(object):
+ captureclass = staticmethod(StdCapture)
+
+ @contextlib.contextmanager
+ def getcapture(self, **kw):
+ cap = self.__class__.captureclass(**kw)
+ cap.start_capturing()
+ try:
+ yield cap
+ finally:
+ cap.stop_capturing()
+
+ def test_capturing_done_simple(self):
+ with self.getcapture() as cap:
+ sys.stdout.write("hello")
+ sys.stderr.write("world")
+ out, err = cap.readouterr()
+ assert out == "hello"
+ assert err == "world"
+
+ def test_capturing_reset_simple(self):
+ with self.getcapture() as cap:
+ print("hello world")
+ sys.stderr.write("hello error\n")
+ out, err = cap.readouterr()
+ assert out == "hello world\n"
+ assert err == "hello error\n"
+
+ def test_capturing_readouterr(self):
+ with self.getcapture() as cap:
+ print("hello world")
+ sys.stderr.write("hello error\n")
+ out, err = cap.readouterr()
+ assert out == "hello world\n"
+ assert err == "hello error\n"
+ sys.stderr.write("error2")
+ out, err = cap.readouterr()
+ assert err == "error2"
+
+ def test_capture_results_accessible_by_attribute(self):
+ with self.getcapture() as cap:
+ sys.stdout.write("hello")
+ sys.stderr.write("world")
+ capture_result = cap.readouterr()
+ assert capture_result.out == "hello"
+ assert capture_result.err == "world"
+
+ def test_capturing_readouterr_unicode(self):
+ with self.getcapture() as cap:
+ print("hx\xc4\x85\xc4\x87")
+ out, err = cap.readouterr()
+ assert out == py.builtin._totext("hx\xc4\x85\xc4\x87\n", "utf8")
+
+ @pytest.mark.skipif('sys.version_info >= (3,)',
+ reason='text output different for bytes on python3')
+ def test_capturing_readouterr_decode_error_handling(self):
+ with self.getcapture() as cap:
+ # triggered a internal error in pytest
+ print('\xa6')
+ out, err = cap.readouterr()
+ assert out == py.builtin._totext('\ufffd\n', 'unicode-escape')
+
+ def test_reset_twice_error(self):
+ with self.getcapture() as cap:
+ print("hello")
+ out, err = cap.readouterr()
+ pytest.raises(ValueError, cap.stop_capturing)
+ assert out == "hello\n"
+ assert not err
+
+ def test_capturing_modify_sysouterr_in_between(self):
+ oldout = sys.stdout
+ olderr = sys.stderr
+ with self.getcapture() as cap:
+ sys.stdout.write("hello")
+ sys.stderr.write("world")
+ sys.stdout = capture.CaptureIO()
+ sys.stderr = capture.CaptureIO()
+ print("not seen")
+ sys.stderr.write("not seen\n")
+ out, err = cap.readouterr()
+ assert out == "hello"
+ assert err == "world"
+ assert sys.stdout == oldout
+ assert sys.stderr == olderr
+
+ def test_capturing_error_recursive(self):
+ with self.getcapture() as cap1:
+ print("cap1")
+ with self.getcapture() as cap2:
+ print("cap2")
+ out2, err2 = cap2.readouterr()
+ out1, err1 = cap1.readouterr()
+ assert out1 == "cap1\n"
+ assert out2 == "cap2\n"
+
+ def test_just_out_capture(self):
+ with self.getcapture(out=True, err=False) as cap:
+ sys.stdout.write("hello")
+ sys.stderr.write("world")
+ out, err = cap.readouterr()
+ assert out == "hello"
+ assert not err
+
+ def test_just_err_capture(self):
+ with self.getcapture(out=False, err=True) as cap:
+ sys.stdout.write("hello")
+ sys.stderr.write("world")
+ out, err = cap.readouterr()
+ assert err == "world"
+ assert not out
+
+ def test_stdin_restored(self):
+ old = sys.stdin
+ with self.getcapture(in_=True):
+ newstdin = sys.stdin
+ assert newstdin != sys.stdin
+ assert sys.stdin is old
+
+ def test_stdin_nulled_by_default(self):
+ print("XXX this test may well hang instead of crashing")
+ print("XXX which indicates an error in the underlying capturing")
+ print("XXX mechanisms")
+ with self.getcapture():
+ pytest.raises(IOError, "sys.stdin.read()")
+
+
+class TestStdCaptureFD(TestStdCapture):
+ pytestmark = needsosdup
+ captureclass = staticmethod(StdCaptureFD)
+
+ def test_simple_only_fd(self, testdir):
+ testdir.makepyfile("""
+ import os
+ def test_x():
+ os.write(1, "hello\\n".encode("ascii"))
+ assert 0
+ """)
+ result = testdir.runpytest_subprocess()
+ result.stdout.fnmatch_lines("""
+ *test_x*
+ *assert 0*
+ *Captured stdout*
+ """)
+
+ def test_intermingling(self):
+ with self.getcapture() as cap:
+ oswritebytes(1, "1")
+ sys.stdout.write(str(2))
+ sys.stdout.flush()
+ oswritebytes(1, "3")
+ oswritebytes(2, "a")
+ sys.stderr.write("b")
+ sys.stderr.flush()
+ oswritebytes(2, "c")
+ out, err = cap.readouterr()
+ assert out == "123"
+ assert err == "abc"
+
+ def test_many(self, capfd):
+ with lsof_check():
+ for i in range(10):
+ cap = StdCaptureFD()
+ cap.stop_capturing()
+
+
+class TestStdCaptureFDinvalidFD(object):
+ pytestmark = needsosdup
+
+ def test_stdcapture_fd_invalid_fd(self, testdir):
+ testdir.makepyfile("""
+ import os
+ from _pytest import capture
+ def StdCaptureFD(out=True, err=True, in_=True):
+ return capture.MultiCapture(out, err, in_,
+ Capture=capture.FDCapture)
+ def test_stdout():
+ os.close(1)
+ cap = StdCaptureFD(out=True, err=False, in_=False)
+ cap.stop_capturing()
+ def test_stderr():
+ os.close(2)
+ cap = StdCaptureFD(out=False, err=True, in_=False)
+ cap.stop_capturing()
+ def test_stdin():
+ os.close(0)
+ cap = StdCaptureFD(out=False, err=False, in_=True)
+ cap.stop_capturing()
+ """)
+ result = testdir.runpytest_subprocess("--capture=fd")
+ assert result.ret == 0
+ assert result.parseoutcomes()['passed'] == 3
+
+
+def test_capture_not_started_but_reset():
+ capsys = StdCapture()
+ capsys.stop_capturing()
+
+
+def test_using_capsys_fixture_works_with_sys_stdout_encoding(capsys):
+ test_text = 'test text'
+
+ print(test_text.encode(sys.stdout.encoding, 'replace'))
+ (out, err) = capsys.readouterr()
+ assert out
+ assert err == ''
+
+
+def test_capsys_results_accessible_by_attribute(capsys):
+ sys.stdout.write("spam")
+ sys.stderr.write("eggs")
+ capture_result = capsys.readouterr()
+ assert capture_result.out == "spam"
+ assert capture_result.err == "eggs"
+
+
+@needsosdup
+@pytest.mark.parametrize('use', [True, False])
+def test_fdcapture_tmpfile_remains_the_same(tmpfile, use):
+ if not use:
+ tmpfile = True
+ cap = StdCaptureFD(out=False, err=tmpfile)
+ try:
+ cap.start_capturing()
+ capfile = cap.err.tmpfile
+ cap.readouterr()
+ finally:
+ cap.stop_capturing()
+ capfile2 = cap.err.tmpfile
+ assert capfile2 == capfile
+
+
+@needsosdup
+def test_close_and_capture_again(testdir):
+ testdir.makepyfile("""
+ import os
+ def test_close():
+ os.close(1)
+ def test_capture_again():
+ os.write(1, b"hello\\n")
+ assert 0
+ """)
+ result = testdir.runpytest_subprocess()
+ result.stdout.fnmatch_lines("""
+ *test_capture_again*
+ *assert 0*
+ *stdout*
+ *hello*
+ """)
+
+
+@pytest.mark.parametrize('method', ['SysCapture', 'FDCapture'])
+def test_capturing_and_logging_fundamentals(testdir, method):
+ if method == "StdCaptureFD" and not hasattr(os, 'dup'):
+ pytest.skip("need os.dup")
+ # here we check a fundamental feature
+ p = testdir.makepyfile("""
+ import sys, os
+ import py, logging
+ from _pytest import capture
+ cap = capture.MultiCapture(out=False, in_=False,
+ Capture=capture.%s)
+ cap.start_capturing()
+
+ logging.warn("hello1")
+ outerr = cap.readouterr()
+ print ("suspend, captured %%s" %%(outerr,))
+ logging.warn("hello2")
+
+ cap.pop_outerr_to_orig()
+ logging.warn("hello3")
+
+ outerr = cap.readouterr()
+ print ("suspend2, captured %%s" %% (outerr,))
+ """ % (method,))
+ result = testdir.runpython(p)
+ result.stdout.fnmatch_lines("""
+ suspend, captured*hello1*
+ suspend2, captured*WARNING:root:hello3*
+ """)
+ result.stderr.fnmatch_lines("""
+ WARNING:root:hello2
+ """)
+ assert "atexit" not in result.stderr.str()
+
+
+def test_error_attribute_issue555(testdir):
+ testdir.makepyfile("""
+ import sys
+ def test_capattr():
+ assert sys.stdout.errors == "strict"
+ assert sys.stderr.errors == "strict"
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+
+@pytest.mark.skipif(not sys.platform.startswith('win') and sys.version_info[:2] >= (3, 6),
+ reason='only py3.6+ on windows')
+def test_py36_windowsconsoleio_workaround_non_standard_streams():
+ """
+ Ensure _py36_windowsconsoleio_workaround function works with objects that
+ do not implement the full ``io``-based stream protocol, for example execnet channels (#2666).
+ """
+ from _pytest.capture import _py36_windowsconsoleio_workaround
+
+ class DummyStream:
+ def write(self, s):
+ pass
+
+ stream = DummyStream()
+ _py36_windowsconsoleio_workaround(stream)
+
+
+def test_dontreadfrominput_has_encoding(testdir):
+ testdir.makepyfile("""
+ import sys
+ def test_capattr():
+ # should not raise AttributeError
+ assert sys.stdout.encoding
+ assert sys.stderr.encoding
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+
+def test_pickling_and_unpickling_encoded_file():
+ # See https://bitbucket.org/pytest-dev/pytest/pull-request/194
+ # pickle.loads() raises infinite recursion if
+ # EncodedFile.__getattr__ is not implemented properly
+ ef = capture.EncodedFile(None, None)
+ ef_as_str = pickle.dumps(ef)
+ pickle.loads(ef_as_str)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_collection.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_collection.py
new file mode 100644
index 00000000000..563ed0439c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_collection.py
@@ -0,0 +1,857 @@
+from __future__ import absolute_import, division, print_function
+import pytest
+import py
+
+import _pytest._code
+from _pytest.main import Session, EXIT_NOTESTSCOLLECTED, _in_venv
+
+
+class TestCollector(object):
+ def test_collect_versus_item(self):
+ from pytest import Collector, Item
+ assert not issubclass(Collector, Item)
+ assert not issubclass(Item, Collector)
+
+ def test_compat_attributes(self, testdir, recwarn):
+ modcol = testdir.getmodulecol("""
+ def test_pass(): pass
+ def test_fail(): assert 0
+ """)
+ recwarn.clear()
+ assert modcol.Module == pytest.Module
+ assert modcol.Class == pytest.Class
+ assert modcol.Item == pytest.Item
+ assert modcol.File == pytest.File
+ assert modcol.Function == pytest.Function
+
+ def test_check_equality(self, testdir):
+ modcol = testdir.getmodulecol("""
+ def test_pass(): pass
+ def test_fail(): assert 0
+ """)
+ fn1 = testdir.collect_by_name(modcol, "test_pass")
+ assert isinstance(fn1, pytest.Function)
+ fn2 = testdir.collect_by_name(modcol, "test_pass")
+ assert isinstance(fn2, pytest.Function)
+
+ assert fn1 == fn2
+ assert fn1 != modcol
+ if py.std.sys.version_info < (3, 0):
+ assert cmp(fn1, fn2) == 0
+ assert hash(fn1) == hash(fn2)
+
+ fn3 = testdir.collect_by_name(modcol, "test_fail")
+ assert isinstance(fn3, pytest.Function)
+ assert not (fn1 == fn3)
+ assert fn1 != fn3
+
+ for fn in fn1, fn2, fn3:
+ assert fn != 3
+ assert fn != modcol
+ assert fn != [1, 2, 3]
+ assert [1, 2, 3] != fn
+ assert modcol != fn
+
+ def test_getparent(self, testdir):
+ modcol = testdir.getmodulecol("""
+ class TestClass(object):
+ def test_foo():
+ pass
+ """)
+ cls = testdir.collect_by_name(modcol, "TestClass")
+ fn = testdir.collect_by_name(
+ testdir.collect_by_name(cls, "()"), "test_foo")
+
+ parent = fn.getparent(pytest.Module)
+ assert parent is modcol
+
+ parent = fn.getparent(pytest.Function)
+ assert parent is fn
+
+ parent = fn.getparent(pytest.Class)
+ assert parent is cls
+
+ def test_getcustomfile_roundtrip(self, testdir):
+ hello = testdir.makefile(".xxx", hello="world")
+ testdir.makepyfile(conftest="""
+ import pytest
+ class CustomFile(pytest.File):
+ pass
+ def pytest_collect_file(path, parent):
+ if path.ext == ".xxx":
+ return CustomFile(path, parent=parent)
+ """)
+ node = testdir.getpathnode(hello)
+ assert isinstance(node, pytest.File)
+ assert node.name == "hello.xxx"
+ nodes = node.session.perform_collect([node.nodeid], genitems=False)
+ assert len(nodes) == 1
+ assert isinstance(nodes[0], pytest.File)
+
+ def test_can_skip_class_with_test_attr(self, testdir):
+ """Assure test class is skipped when using `__test__=False` (See #2007)."""
+ testdir.makepyfile("""
+ class TestFoo(object):
+ __test__ = False
+ def __init__(self):
+ pass
+ def test_foo():
+ assert True
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ 'collected 0 items',
+ '*no tests ran in*',
+ ])
+
+
+class TestCollectFS(object):
+ def test_ignored_certain_directories(self, testdir):
+ tmpdir = testdir.tmpdir
+ tmpdir.ensure("build", 'test_notfound.py')
+ tmpdir.ensure("dist", 'test_notfound.py')
+ tmpdir.ensure("_darcs", 'test_notfound.py')
+ tmpdir.ensure("CVS", 'test_notfound.py')
+ tmpdir.ensure("{arch}", 'test_notfound.py')
+ tmpdir.ensure(".whatever", 'test_notfound.py')
+ tmpdir.ensure(".bzr", 'test_notfound.py')
+ tmpdir.ensure("normal", 'test_found.py')
+ for x in tmpdir.visit("test_*.py"):
+ x.write("def test_hello(): pass")
+
+ result = testdir.runpytest("--collect-only")
+ s = result.stdout.str()
+ assert "test_notfound" not in s
+ assert "test_found" in s
+
+ @pytest.mark.parametrize('fname',
+ ("activate", "activate.csh", "activate.fish",
+ "Activate", "Activate.bat", "Activate.ps1"))
+ def test_ignored_virtualenvs(self, testdir, fname):
+ bindir = "Scripts" if py.std.sys.platform.startswith("win") else "bin"
+ testdir.tmpdir.ensure("virtual", bindir, fname)
+ testfile = testdir.tmpdir.ensure("virtual", "test_invenv.py")
+ testfile.write("def test_hello(): pass")
+
+ # by default, ignore tests inside a virtualenv
+ result = testdir.runpytest()
+ assert "test_invenv" not in result.stdout.str()
+ # allow test collection if user insists
+ result = testdir.runpytest("--collect-in-virtualenv")
+ assert "test_invenv" in result.stdout.str()
+ # allow test collection if user directly passes in the directory
+ result = testdir.runpytest("virtual")
+ assert "test_invenv" in result.stdout.str()
+
+ @pytest.mark.parametrize('fname',
+ ("activate", "activate.csh", "activate.fish",
+ "Activate", "Activate.bat", "Activate.ps1"))
+ def test_ignored_virtualenvs_norecursedirs_precedence(self, testdir, fname):
+ bindir = "Scripts" if py.std.sys.platform.startswith("win") else "bin"
+ # norecursedirs takes priority
+ testdir.tmpdir.ensure(".virtual", bindir, fname)
+ testfile = testdir.tmpdir.ensure(".virtual", "test_invenv.py")
+ testfile.write("def test_hello(): pass")
+ result = testdir.runpytest("--collect-in-virtualenv")
+ assert "test_invenv" not in result.stdout.str()
+ # ...unless the virtualenv is explicitly given on the CLI
+ result = testdir.runpytest("--collect-in-virtualenv", ".virtual")
+ assert "test_invenv" in result.stdout.str()
+
+ @pytest.mark.parametrize('fname',
+ ("activate", "activate.csh", "activate.fish",
+ "Activate", "Activate.bat", "Activate.ps1"))
+ def test__in_venv(self, testdir, fname):
+ """Directly test the virtual env detection function"""
+ bindir = "Scripts" if py.std.sys.platform.startswith("win") else "bin"
+ # no bin/activate, not a virtualenv
+ base_path = testdir.tmpdir.mkdir('venv')
+ assert _in_venv(base_path) is False
+ # with bin/activate, totally a virtualenv
+ base_path.ensure(bindir, fname)
+ assert _in_venv(base_path) is True
+
+ def test_custom_norecursedirs(self, testdir):
+ testdir.makeini("""
+ [pytest]
+ norecursedirs = mydir xyz*
+ """)
+ tmpdir = testdir.tmpdir
+ tmpdir.ensure("mydir", "test_hello.py").write("def test_1(): pass")
+ tmpdir.ensure("xyz123", "test_2.py").write("def test_2(): 0/0")
+ tmpdir.ensure("xy", "test_ok.py").write("def test_3(): pass")
+ rec = testdir.inline_run()
+ rec.assertoutcome(passed=1)
+ rec = testdir.inline_run("xyz123/test_2.py")
+ rec.assertoutcome(failed=1)
+
+ def test_testpaths_ini(self, testdir, monkeypatch):
+ testdir.makeini("""
+ [pytest]
+ testpaths = gui uts
+ """)
+ tmpdir = testdir.tmpdir
+ tmpdir.ensure("env", "test_1.py").write("def test_env(): pass")
+ tmpdir.ensure("gui", "test_2.py").write("def test_gui(): pass")
+ tmpdir.ensure("uts", "test_3.py").write("def test_uts(): pass")
+
+ # executing from rootdir only tests from `testpaths` directories
+ # are collected
+ items, reprec = testdir.inline_genitems('-v')
+ assert [x.name for x in items] == ['test_gui', 'test_uts']
+
+ # check that explicitly passing directories in the command-line
+ # collects the tests
+ for dirname in ('env', 'gui', 'uts'):
+ items, reprec = testdir.inline_genitems(tmpdir.join(dirname))
+ assert [x.name for x in items] == ['test_%s' % dirname]
+
+ # changing cwd to each subdirectory and running pytest without
+ # arguments collects the tests in that directory normally
+ for dirname in ('env', 'gui', 'uts'):
+ monkeypatch.chdir(testdir.tmpdir.join(dirname))
+ items, reprec = testdir.inline_genitems()
+ assert [x.name for x in items] == ['test_%s' % dirname]
+
+
+class TestCollectPluginHookRelay(object):
+ def test_pytest_collect_file(self, testdir):
+ wascalled = []
+
+ class Plugin(object):
+ def pytest_collect_file(self, path, parent):
+ if not path.basename.startswith("."):
+ # Ignore hidden files, e.g. .testmondata.
+ wascalled.append(path)
+
+ testdir.makefile(".abc", "xyz")
+ pytest.main([testdir.tmpdir], plugins=[Plugin()])
+ assert len(wascalled) == 1
+ assert wascalled[0].ext == '.abc'
+
+ def test_pytest_collect_directory(self, testdir):
+ wascalled = []
+
+ class Plugin(object):
+ def pytest_collect_directory(self, path, parent):
+ wascalled.append(path.basename)
+
+ testdir.mkdir("hello")
+ testdir.mkdir("world")
+ pytest.main(testdir.tmpdir, plugins=[Plugin()])
+ assert "hello" in wascalled
+ assert "world" in wascalled
+
+
+class TestPrunetraceback(object):
+
+ def test_custom_repr_failure(self, testdir):
+ p = testdir.makepyfile("""
+ import not_exists
+ """)
+ testdir.makeconftest("""
+ import pytest
+ def pytest_collect_file(path, parent):
+ return MyFile(path, parent)
+ class MyError(Exception):
+ pass
+ class MyFile(pytest.File):
+ def collect(self):
+ raise MyError()
+ def repr_failure(self, excinfo):
+ if excinfo.errisinstance(MyError):
+ return "hello world"
+ return pytest.File.repr_failure(self, excinfo)
+ """)
+
+ result = testdir.runpytest(p)
+ result.stdout.fnmatch_lines([
+ "*ERROR collecting*",
+ "*hello world*",
+ ])
+
+ @pytest.mark.xfail(reason="other mechanism for adding to reporting needed")
+ def test_collect_report_postprocessing(self, testdir):
+ p = testdir.makepyfile("""
+ import not_exists
+ """)
+ testdir.makeconftest("""
+ import pytest
+ @pytest.hookimpl(hookwrapper=True)
+ def pytest_make_collect_report():
+ outcome = yield
+ rep = outcome.get_result()
+ rep.headerlines += ["header1"]
+ outcome.force_result(rep)
+ """)
+ result = testdir.runpytest(p)
+ result.stdout.fnmatch_lines([
+ "*ERROR collecting*",
+ "*header1*",
+ ])
+
+
+class TestCustomConftests(object):
+ def test_ignore_collect_path(self, testdir):
+ testdir.makeconftest("""
+ def pytest_ignore_collect(path, config):
+ return path.basename.startswith("x") or \
+ path.basename == "test_one.py"
+ """)
+ sub = testdir.mkdir("xy123")
+ sub.ensure("test_hello.py").write("syntax error")
+ sub.join("conftest.py").write("syntax error")
+ testdir.makepyfile("def test_hello(): pass")
+ testdir.makepyfile(test_one="syntax error")
+ result = testdir.runpytest("--fulltrace")
+ assert result.ret == 0
+ result.stdout.fnmatch_lines(["*1 passed*"])
+
+ def test_ignore_collect_not_called_on_argument(self, testdir):
+ testdir.makeconftest("""
+ def pytest_ignore_collect(path, config):
+ return True
+ """)
+ p = testdir.makepyfile("def test_hello(): pass")
+ result = testdir.runpytest(p)
+ assert result.ret == 0
+ result.stdout.fnmatch_lines("*1 passed*")
+ result = testdir.runpytest()
+ assert result.ret == EXIT_NOTESTSCOLLECTED
+ result.stdout.fnmatch_lines("*collected 0 items*")
+
+ def test_collectignore_exclude_on_option(self, testdir):
+ testdir.makeconftest("""
+ collect_ignore = ['hello', 'test_world.py']
+ def pytest_addoption(parser):
+ parser.addoption("--XX", action="store_true", default=False)
+ def pytest_configure(config):
+ if config.getvalue("XX"):
+ collect_ignore[:] = []
+ """)
+ testdir.mkdir("hello")
+ testdir.makepyfile(test_world="def test_hello(): pass")
+ result = testdir.runpytest()
+ assert result.ret == EXIT_NOTESTSCOLLECTED
+ assert "passed" not in result.stdout.str()
+ result = testdir.runpytest("--XX")
+ assert result.ret == 0
+ assert "passed" in result.stdout.str()
+
+ def test_pytest_fs_collect_hooks_are_seen(self, testdir):
+ testdir.makeconftest("""
+ import pytest
+ class MyModule(pytest.Module):
+ pass
+ def pytest_collect_file(path, parent):
+ if path.ext == ".py":
+ return MyModule(path, parent)
+ """)
+ testdir.mkdir("sub")
+ testdir.makepyfile("def test_x(): pass")
+ result = testdir.runpytest("--collect-only")
+ result.stdout.fnmatch_lines([
+ "*MyModule*",
+ "*test_x*"
+ ])
+
+ def test_pytest_collect_file_from_sister_dir(self, testdir):
+ sub1 = testdir.mkpydir("sub1")
+ sub2 = testdir.mkpydir("sub2")
+ conf1 = testdir.makeconftest("""
+ import pytest
+ class MyModule1(pytest.Module):
+ pass
+ def pytest_collect_file(path, parent):
+ if path.ext == ".py":
+ return MyModule1(path, parent)
+ """)
+ conf1.move(sub1.join(conf1.basename))
+ conf2 = testdir.makeconftest("""
+ import pytest
+ class MyModule2(pytest.Module):
+ pass
+ def pytest_collect_file(path, parent):
+ if path.ext == ".py":
+ return MyModule2(path, parent)
+ """)
+ conf2.move(sub2.join(conf2.basename))
+ p = testdir.makepyfile("def test_x(): pass")
+ p.copy(sub1.join(p.basename))
+ p.copy(sub2.join(p.basename))
+ result = testdir.runpytest("--collect-only")
+ result.stdout.fnmatch_lines([
+ "*MyModule1*",
+ "*MyModule2*",
+ "*test_x*"
+ ])
+
+
+class TestSession(object):
+ def test_parsearg(self, testdir):
+ p = testdir.makepyfile("def test_func(): pass")
+ subdir = testdir.mkdir("sub")
+ subdir.ensure("__init__.py")
+ target = subdir.join(p.basename)
+ p.move(target)
+ subdir.chdir()
+ config = testdir.parseconfig(p.basename)
+ rcol = Session(config=config)
+ assert rcol.fspath == subdir
+ parts = rcol._parsearg(p.basename)
+
+ assert parts[0] == target
+ assert len(parts) == 1
+ parts = rcol._parsearg(p.basename + "::test_func")
+ assert parts[0] == target
+ assert parts[1] == "test_func"
+ assert len(parts) == 2
+
+ def test_collect_topdir(self, testdir):
+ p = testdir.makepyfile("def test_func(): pass")
+ id = "::".join([p.basename, "test_func"])
+ # XXX migrate to collectonly? (see below)
+ config = testdir.parseconfig(id)
+ topdir = testdir.tmpdir
+ rcol = Session(config)
+ assert topdir == rcol.fspath
+ # rootid = rcol.nodeid
+ # root2 = rcol.perform_collect([rcol.nodeid], genitems=False)[0]
+ # assert root2 == rcol, rootid
+ colitems = rcol.perform_collect([rcol.nodeid], genitems=False)
+ assert len(colitems) == 1
+ assert colitems[0].fspath == p
+
+ def get_reported_items(self, hookrec):
+ """Return pytest.Item instances reported by the pytest_collectreport hook"""
+ calls = hookrec.getcalls('pytest_collectreport')
+ return [x for call in calls for x in call.report.result
+ if isinstance(x, pytest.Item)]
+
+ def test_collect_protocol_single_function(self, testdir):
+ p = testdir.makepyfile("def test_func(): pass")
+ id = "::".join([p.basename, "test_func"])
+ items, hookrec = testdir.inline_genitems(id)
+ item, = items
+ assert item.name == "test_func"
+ newid = item.nodeid
+ assert newid == id
+ py.std.pprint.pprint(hookrec.calls)
+ topdir = testdir.tmpdir # noqa
+ hookrec.assert_contains([
+ ("pytest_collectstart", "collector.fspath == topdir"),
+ ("pytest_make_collect_report", "collector.fspath == topdir"),
+ ("pytest_collectstart", "collector.fspath == p"),
+ ("pytest_make_collect_report", "collector.fspath == p"),
+ ("pytest_pycollect_makeitem", "name == 'test_func'"),
+ ("pytest_collectreport", "report.result[0].name == 'test_func'"),
+ ])
+ # ensure we are reporting the collection of the single test item (#2464)
+ assert [x.name for x in self.get_reported_items(hookrec)] == ['test_func']
+
+ def test_collect_protocol_method(self, testdir):
+ p = testdir.makepyfile("""
+ class TestClass(object):
+ def test_method(self):
+ pass
+ """)
+ normid = p.basename + "::TestClass::()::test_method"
+ for id in [p.basename,
+ p.basename + "::TestClass",
+ p.basename + "::TestClass::()",
+ normid,
+ ]:
+ items, hookrec = testdir.inline_genitems(id)
+ assert len(items) == 1
+ assert items[0].name == "test_method"
+ newid = items[0].nodeid
+ assert newid == normid
+ # ensure we are reporting the collection of the single test item (#2464)
+ assert [x.name for x in self.get_reported_items(hookrec)] == ['test_method']
+
+ def test_collect_custom_nodes_multi_id(self, testdir):
+ p = testdir.makepyfile("def test_func(): pass")
+ testdir.makeconftest("""
+ import pytest
+ class SpecialItem(pytest.Item):
+ def runtest(self):
+ return # ok
+ class SpecialFile(pytest.File):
+ def collect(self):
+ return [SpecialItem(name="check", parent=self)]
+ def pytest_collect_file(path, parent):
+ if path.basename == %r:
+ return SpecialFile(fspath=path, parent=parent)
+ """ % p.basename)
+ id = p.basename
+
+ items, hookrec = testdir.inline_genitems(id)
+ py.std.pprint.pprint(hookrec.calls)
+ assert len(items) == 2
+ hookrec.assert_contains([
+ ("pytest_collectstart",
+ "collector.fspath == collector.session.fspath"),
+ ("pytest_collectstart",
+ "collector.__class__.__name__ == 'SpecialFile'"),
+ ("pytest_collectstart",
+ "collector.__class__.__name__ == 'Module'"),
+ ("pytest_pycollect_makeitem", "name == 'test_func'"),
+ ("pytest_collectreport", "report.nodeid.startswith(p.basename)"),
+ ])
+ assert len(self.get_reported_items(hookrec)) == 2
+
+ def test_collect_subdir_event_ordering(self, testdir):
+ p = testdir.makepyfile("def test_func(): pass")
+ aaa = testdir.mkpydir("aaa")
+ test_aaa = aaa.join("test_aaa.py")
+ p.move(test_aaa)
+
+ items, hookrec = testdir.inline_genitems()
+ assert len(items) == 1
+ py.std.pprint.pprint(hookrec.calls)
+ hookrec.assert_contains([
+ ("pytest_collectstart", "collector.fspath == test_aaa"),
+ ("pytest_pycollect_makeitem", "name == 'test_func'"),
+ ("pytest_collectreport",
+ "report.nodeid.startswith('aaa/test_aaa.py')"),
+ ])
+
+ def test_collect_two_commandline_args(self, testdir):
+ p = testdir.makepyfile("def test_func(): pass")
+ aaa = testdir.mkpydir("aaa")
+ bbb = testdir.mkpydir("bbb")
+ test_aaa = aaa.join("test_aaa.py")
+ p.copy(test_aaa)
+ test_bbb = bbb.join("test_bbb.py")
+ p.move(test_bbb)
+
+ id = "."
+
+ items, hookrec = testdir.inline_genitems(id)
+ assert len(items) == 2
+ py.std.pprint.pprint(hookrec.calls)
+ hookrec.assert_contains([
+ ("pytest_collectstart", "collector.fspath == test_aaa"),
+ ("pytest_pycollect_makeitem", "name == 'test_func'"),
+ ("pytest_collectreport", "report.nodeid == 'aaa/test_aaa.py'"),
+ ("pytest_collectstart", "collector.fspath == test_bbb"),
+ ("pytest_pycollect_makeitem", "name == 'test_func'"),
+ ("pytest_collectreport", "report.nodeid == 'bbb/test_bbb.py'"),
+ ])
+
+ def test_serialization_byid(self, testdir):
+ testdir.makepyfile("def test_func(): pass")
+ items, hookrec = testdir.inline_genitems()
+ assert len(items) == 1
+ item, = items
+ items2, hookrec = testdir.inline_genitems(item.nodeid)
+ item2, = items2
+ assert item2.name == item.name
+ assert item2.fspath == item.fspath
+
+ def test_find_byid_without_instance_parents(self, testdir):
+ p = testdir.makepyfile("""
+ class TestClass(object):
+ def test_method(self):
+ pass
+ """)
+ arg = p.basename + "::TestClass::test_method"
+ items, hookrec = testdir.inline_genitems(arg)
+ assert len(items) == 1
+ item, = items
+ assert item.nodeid.endswith("TestClass::()::test_method")
+ # ensure we are reporting the collection of the single test item (#2464)
+ assert [x.name for x in self.get_reported_items(hookrec)] == ['test_method']
+
+
+class Test_getinitialnodes(object):
+ def test_global_file(self, testdir, tmpdir):
+ x = tmpdir.ensure("x.py")
+ with tmpdir.as_cwd():
+ config = testdir.parseconfigure(x)
+ col = testdir.getnode(config, x)
+ assert isinstance(col, pytest.Module)
+ assert col.name == 'x.py'
+ assert col.parent.parent is None
+ for col in col.listchain():
+ assert col.config is config
+
+ def test_pkgfile(self, testdir):
+ tmpdir = testdir.tmpdir
+ subdir = tmpdir.join("subdir")
+ x = subdir.ensure("x.py")
+ subdir.ensure("__init__.py")
+ with subdir.as_cwd():
+ config = testdir.parseconfigure(x)
+ col = testdir.getnode(config, x)
+ assert isinstance(col, pytest.Module)
+ assert col.name == 'x.py'
+ assert col.parent.parent is None
+ for col in col.listchain():
+ assert col.config is config
+
+
+class Test_genitems(object):
+ def test_check_collect_hashes(self, testdir):
+ p = testdir.makepyfile("""
+ def test_1():
+ pass
+
+ def test_2():
+ pass
+ """)
+ p.copy(p.dirpath(p.purebasename + "2" + ".py"))
+ items, reprec = testdir.inline_genitems(p.dirpath())
+ assert len(items) == 4
+ for numi, i in enumerate(items):
+ for numj, j in enumerate(items):
+ if numj != numi:
+ assert hash(i) != hash(j)
+ assert i != j
+
+ def test_example_items1(self, testdir):
+ p = testdir.makepyfile('''
+ def testone():
+ pass
+
+ class TestX(object):
+ def testmethod_one(self):
+ pass
+
+ class TestY(TestX):
+ pass
+ ''')
+ items, reprec = testdir.inline_genitems(p)
+ assert len(items) == 3
+ assert items[0].name == 'testone'
+ assert items[1].name == 'testmethod_one'
+ assert items[2].name == 'testmethod_one'
+
+ # let's also test getmodpath here
+ assert items[0].getmodpath() == "testone"
+ assert items[1].getmodpath() == "TestX.testmethod_one"
+ assert items[2].getmodpath() == "TestY.testmethod_one"
+
+ s = items[0].getmodpath(stopatmodule=False)
+ assert s.endswith("test_example_items1.testone")
+ print(s)
+
+ def test_class_and_functions_discovery_using_glob(self, testdir):
+ """
+ tests that python_classes and python_functions config options work
+ as prefixes and glob-like patterns (issue #600).
+ """
+ testdir.makeini("""
+ [pytest]
+ python_classes = *Suite Test
+ python_functions = *_test test
+ """)
+ p = testdir.makepyfile('''
+ class MyTestSuite(object):
+ def x_test(self):
+ pass
+
+ class TestCase(object):
+ def test_y(self):
+ pass
+ ''')
+ items, reprec = testdir.inline_genitems(p)
+ ids = [x.getmodpath() for x in items]
+ assert ids == ['MyTestSuite.x_test', 'TestCase.test_y']
+
+
+def test_matchnodes_two_collections_same_file(testdir):
+ testdir.makeconftest("""
+ import pytest
+ def pytest_configure(config):
+ config.pluginmanager.register(Plugin2())
+
+ class Plugin2(object):
+ def pytest_collect_file(self, path, parent):
+ if path.ext == ".abc":
+ return MyFile2(path, parent)
+
+ def pytest_collect_file(path, parent):
+ if path.ext == ".abc":
+ return MyFile1(path, parent)
+
+ class MyFile1(pytest.Item, pytest.File):
+ def runtest(self):
+ pass
+ class MyFile2(pytest.File):
+ def collect(self):
+ return [Item2("hello", parent=self)]
+
+ class Item2(pytest.Item):
+ def runtest(self):
+ pass
+ """)
+ p = testdir.makefile(".abc", "")
+ result = testdir.runpytest()
+ assert result.ret == 0
+ result.stdout.fnmatch_lines([
+ "*2 passed*",
+ ])
+ res = testdir.runpytest("%s::hello" % p.basename)
+ res.stdout.fnmatch_lines([
+ "*1 passed*",
+ ])
+
+
+class TestNodekeywords(object):
+ def test_no_under(self, testdir):
+ modcol = testdir.getmodulecol("""
+ def test_pass(): pass
+ def test_fail(): assert 0
+ """)
+ values = list(modcol.keywords)
+ assert modcol.name in values
+ for x in values:
+ assert not x.startswith("_")
+ assert modcol.name in repr(modcol.keywords)
+
+ def test_issue345(self, testdir):
+ testdir.makepyfile("""
+ def test_should_not_be_selected():
+ assert False, 'I should not have been selected to run'
+
+ def test___repr__():
+ pass
+ """)
+ reprec = testdir.inline_run("-k repr")
+ reprec.assertoutcome(passed=1, failed=0)
+
+
+COLLECTION_ERROR_PY_FILES = dict(
+ test_01_failure="""
+ def test_1():
+ assert False
+ """,
+ test_02_import_error="""
+ import asdfasdfasdf
+ def test_2():
+ assert True
+ """,
+ test_03_import_error="""
+ import asdfasdfasdf
+ def test_3():
+ assert True
+ """,
+ test_04_success="""
+ def test_4():
+ assert True
+ """,
+)
+
+
+def test_exit_on_collection_error(testdir):
+ """Verify that all collection errors are collected and no tests executed"""
+ testdir.makepyfile(**COLLECTION_ERROR_PY_FILES)
+
+ res = testdir.runpytest()
+ assert res.ret == 2
+
+ res.stdout.fnmatch_lines([
+ "collected 2 items / 2 errors",
+ "*ERROR collecting test_02_import_error.py*",
+ "*No module named *asdfa*",
+ "*ERROR collecting test_03_import_error.py*",
+ "*No module named *asdfa*",
+ ])
+
+
+def test_exit_on_collection_with_maxfail_smaller_than_n_errors(testdir):
+ """
+ Verify collection is aborted once maxfail errors are encountered ignoring
+ further modules which would cause more collection errors.
+ """
+ testdir.makepyfile(**COLLECTION_ERROR_PY_FILES)
+
+ res = testdir.runpytest("--maxfail=1")
+ assert res.ret == 1
+
+ res.stdout.fnmatch_lines([
+ "*ERROR collecting test_02_import_error.py*",
+ "*No module named *asdfa*",
+ ])
+
+ assert 'test_03' not in res.stdout.str()
+
+
+def test_exit_on_collection_with_maxfail_bigger_than_n_errors(testdir):
+ """
+ Verify the test run aborts due to collection errors even if maxfail count of
+ errors was not reached.
+ """
+ testdir.makepyfile(**COLLECTION_ERROR_PY_FILES)
+
+ res = testdir.runpytest("--maxfail=4")
+ assert res.ret == 2
+
+ res.stdout.fnmatch_lines([
+ "collected 2 items / 2 errors",
+ "*ERROR collecting test_02_import_error.py*",
+ "*No module named *asdfa*",
+ "*ERROR collecting test_03_import_error.py*",
+ "*No module named *asdfa*",
+ ])
+
+
+def test_continue_on_collection_errors(testdir):
+ """
+ Verify tests are executed even when collection errors occur when the
+ --continue-on-collection-errors flag is set
+ """
+ testdir.makepyfile(**COLLECTION_ERROR_PY_FILES)
+
+ res = testdir.runpytest("--continue-on-collection-errors")
+ assert res.ret == 1
+
+ res.stdout.fnmatch_lines([
+ "collected 2 items / 2 errors",
+ "*1 failed, 1 passed, 2 error*",
+ ])
+
+
+def test_continue_on_collection_errors_maxfail(testdir):
+ """
+ Verify tests are executed even when collection errors occur and that maxfail
+ is honoured (including the collection error count).
+ 4 tests: 2 collection errors + 1 failure + 1 success
+ test_4 is never executed because the test run is with --maxfail=3 which
+ means it is interrupted after the 2 collection errors + 1 failure.
+ """
+ testdir.makepyfile(**COLLECTION_ERROR_PY_FILES)
+
+ res = testdir.runpytest("--continue-on-collection-errors", "--maxfail=3")
+ assert res.ret == 1
+
+ res.stdout.fnmatch_lines([
+ "collected 2 items / 2 errors",
+ "*1 failed, 2 error*",
+ ])
+
+
+def test_fixture_scope_sibling_conftests(testdir):
+ """Regression test case for https://github.com/pytest-dev/pytest/issues/2836"""
+ foo_path = testdir.mkpydir("foo")
+ foo_path.join("conftest.py").write(_pytest._code.Source("""
+ import pytest
+ @pytest.fixture
+ def fix():
+ return 1
+ """))
+ foo_path.join("test_foo.py").write("def test_foo(fix): assert fix == 1")
+
+ # Tests in `food/` should not see the conftest fixture from `foo/`
+ food_path = testdir.mkpydir("food")
+ food_path.join("test_food.py").write("def test_food(fix): assert fix == 1")
+
+ res = testdir.runpytest()
+ assert res.ret == 1
+
+ res.stdout.fnmatch_lines([
+ "*ERROR at setup of test_food*",
+ "E*fixture 'fix' not found",
+ "*1 passed, 1 error*",
+ ])
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_compat.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_compat.py
new file mode 100644
index 00000000000..c74801c6c85
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_compat.py
@@ -0,0 +1,101 @@
+from __future__ import absolute_import, division, print_function
+import sys
+
+import pytest
+from _pytest.compat import is_generator, get_real_func, safe_getattr
+from _pytest.outcomes import OutcomeException
+
+
+def test_is_generator():
+ def zap():
+ yield
+
+ def foo():
+ pass
+
+ assert is_generator(zap)
+ assert not is_generator(foo)
+
+
+def test_real_func_loop_limit():
+
+ class Evil(object):
+ def __init__(self):
+ self.left = 1000
+
+ def __repr__(self):
+ return "<Evil left={left}>".format(left=self.left)
+
+ def __getattr__(self, attr):
+ if not self.left:
+ raise RuntimeError('its over')
+ self.left -= 1
+ return self
+
+ evil = Evil()
+
+ with pytest.raises(ValueError):
+ res = get_real_func(evil)
+ print(res)
+
+
+@pytest.mark.skipif(sys.version_info < (3, 4),
+ reason='asyncio available in Python 3.4+')
+def test_is_generator_asyncio(testdir):
+ testdir.makepyfile("""
+ from _pytest.compat import is_generator
+ import asyncio
+ @asyncio.coroutine
+ def baz():
+ yield from [1,2,3]
+
+ def test_is_generator_asyncio():
+ assert not is_generator(baz)
+ """)
+ # avoid importing asyncio into pytest's own process,
+ # which in turn imports logging (#8)
+ result = testdir.runpytest_subprocess()
+ result.stdout.fnmatch_lines(['*1 passed*'])
+
+
+@pytest.mark.skipif(sys.version_info < (3, 5),
+ reason='async syntax available in Python 3.5+')
+def test_is_generator_async_syntax(testdir):
+ testdir.makepyfile("""
+ from _pytest.compat import is_generator
+ def test_is_generator_py35():
+ async def foo():
+ await foo()
+
+ async def bar():
+ pass
+
+ assert not is_generator(foo)
+ assert not is_generator(bar)
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(['*1 passed*'])
+
+
+class ErrorsHelper(object):
+ @property
+ def raise_exception(self):
+ raise Exception('exception should be catched')
+
+ @property
+ def raise_fail(self):
+ pytest.fail('fail should be catched')
+
+
+def test_helper_failures():
+ helper = ErrorsHelper()
+ with pytest.raises(Exception):
+ helper.raise_exception
+ with pytest.raises(OutcomeException):
+ helper.raise_fail
+
+
+def test_safe_getattr():
+ helper = ErrorsHelper()
+ assert safe_getattr(helper, 'raise_exception', 'default') == 'default'
+ assert safe_getattr(helper, 'raise_fail', 'default') == 'default'
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_config.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_config.py
new file mode 100644
index 00000000000..44b8c317a28
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_config.py
@@ -0,0 +1,862 @@
+from __future__ import absolute_import, division, print_function
+import sys
+import py
+import pytest
+
+import _pytest._code
+from _pytest.config import getcfg, get_common_ancestor, determine_setup, _iter_rewritable_modules
+from _pytest.main import EXIT_NOTESTSCOLLECTED
+
+
+class TestParseIni(object):
+
+ @pytest.mark.parametrize('section, filename',
+ [('pytest', 'pytest.ini'), ('tool:pytest', 'setup.cfg')])
+ def test_getcfg_and_config(self, testdir, tmpdir, section, filename):
+ sub = tmpdir.mkdir("sub")
+ sub.chdir()
+ tmpdir.join(filename).write(_pytest._code.Source("""
+ [{section}]
+ name = value
+ """.format(section=section)))
+ rootdir, inifile, cfg = getcfg([sub])
+ assert cfg['name'] == "value"
+ config = testdir.parseconfigure(sub)
+ assert config.inicfg['name'] == 'value'
+
+ def test_getcfg_empty_path(self):
+ """correctly handle zero length arguments (a la pytest '')"""
+ getcfg([''])
+
+ def test_append_parse_args(self, testdir, tmpdir, monkeypatch):
+ monkeypatch.setenv('PYTEST_ADDOPTS', '--color no -rs --tb="short"')
+ tmpdir.join("pytest.ini").write(_pytest._code.Source("""
+ [pytest]
+ addopts = --verbose
+ """))
+ config = testdir.parseconfig(tmpdir)
+ assert config.option.color == 'no'
+ assert config.option.reportchars == 's'
+ assert config.option.tbstyle == 'short'
+ assert config.option.verbose
+
+ def test_tox_ini_wrong_version(self, testdir):
+ testdir.makefile('.ini', tox="""
+ [pytest]
+ minversion=9.0
+ """)
+ result = testdir.runpytest()
+ assert result.ret != 0
+ result.stderr.fnmatch_lines([
+ "*tox.ini:2*requires*9.0*actual*"
+ ])
+
+ @pytest.mark.parametrize("section, name", [
+ ('tool:pytest', 'setup.cfg'),
+ ('pytest', 'tox.ini'),
+ ('pytest', 'pytest.ini')],
+ )
+ def test_ini_names(self, testdir, name, section):
+ testdir.tmpdir.join(name).write(py.std.textwrap.dedent("""
+ [{section}]
+ minversion = 1.0
+ """.format(section=section)))
+ config = testdir.parseconfig()
+ assert config.getini("minversion") == "1.0"
+
+ def test_toxini_before_lower_pytestini(self, testdir):
+ sub = testdir.tmpdir.mkdir("sub")
+ sub.join("tox.ini").write(py.std.textwrap.dedent("""
+ [pytest]
+ minversion = 2.0
+ """))
+ testdir.tmpdir.join("pytest.ini").write(py.std.textwrap.dedent("""
+ [pytest]
+ minversion = 1.5
+ """))
+ config = testdir.parseconfigure(sub)
+ assert config.getini("minversion") == "2.0"
+
+ @pytest.mark.xfail(reason="probably not needed")
+ def test_confcutdir(self, testdir):
+ sub = testdir.mkdir("sub")
+ sub.chdir()
+ testdir.makeini("""
+ [pytest]
+ addopts = --qwe
+ """)
+ result = testdir.inline_run("--confcutdir=.")
+ assert result.ret == 0
+
+
+class TestConfigCmdlineParsing(object):
+ def test_parsing_again_fails(self, testdir):
+ config = testdir.parseconfig()
+ pytest.raises(AssertionError, lambda: config.parse([]))
+
+ def test_explicitly_specified_config_file_is_loaded(self, testdir):
+ testdir.makeconftest("""
+ def pytest_addoption(parser):
+ parser.addini("custom", "")
+ """)
+ testdir.makeini("""
+ [pytest]
+ custom = 0
+ """)
+ testdir.makefile(".cfg", custom="""
+ [pytest]
+ custom = 1
+ """)
+ config = testdir.parseconfig("-c", "custom.cfg")
+ assert config.getini("custom") == "1"
+
+ def test_absolute_win32_path(self, testdir):
+ temp_cfg_file = testdir.makefile(".cfg", custom="""
+ [pytest]
+ addopts = --version
+ """)
+ from os.path import normpath
+ temp_cfg_file = normpath(str(temp_cfg_file))
+ ret = pytest.main("-c " + temp_cfg_file)
+ assert ret == _pytest.main.EXIT_OK
+
+
+class TestConfigAPI(object):
+ def test_config_trace(self, testdir):
+ config = testdir.parseconfig()
+ values = []
+ config.trace.root.setwriter(values.append)
+ config.trace("hello")
+ assert len(values) == 1
+ assert values[0] == "hello [config]\n"
+
+ def test_config_getoption(self, testdir):
+ testdir.makeconftest("""
+ def pytest_addoption(parser):
+ parser.addoption("--hello", "-X", dest="hello")
+ """)
+ config = testdir.parseconfig("--hello=this")
+ for x in ("hello", "--hello", "-X"):
+ assert config.getoption(x) == "this"
+ pytest.raises(ValueError, "config.getoption('qweqwe')")
+
+ @pytest.mark.skipif('sys.version_info[0] < 3')
+ def test_config_getoption_unicode(self, testdir):
+ testdir.makeconftest("""
+ from __future__ import unicode_literals
+
+ def pytest_addoption(parser):
+ parser.addoption('--hello', type=str)
+ """)
+ config = testdir.parseconfig('--hello=this')
+ assert config.getoption('hello') == 'this'
+
+ def test_config_getvalueorskip(self, testdir):
+ config = testdir.parseconfig()
+ pytest.raises(pytest.skip.Exception,
+ "config.getvalueorskip('hello')")
+ verbose = config.getvalueorskip("verbose")
+ assert verbose == config.option.verbose
+
+ def test_config_getvalueorskip_None(self, testdir):
+ testdir.makeconftest("""
+ def pytest_addoption(parser):
+ parser.addoption("--hello")
+ """)
+ config = testdir.parseconfig()
+ with pytest.raises(pytest.skip.Exception):
+ config.getvalueorskip('hello')
+
+ def test_getoption(self, testdir):
+ config = testdir.parseconfig()
+ with pytest.raises(ValueError):
+ config.getvalue('x')
+ assert config.getoption("x", 1) == 1
+
+ def test_getconftest_pathlist(self, testdir, tmpdir):
+ somepath = tmpdir.join("x", "y", "z")
+ p = tmpdir.join("conftest.py")
+ p.write("pathlist = ['.', %r]" % str(somepath))
+ config = testdir.parseconfigure(p)
+ assert config._getconftest_pathlist('notexist', path=tmpdir) is None
+ pl = config._getconftest_pathlist('pathlist', path=tmpdir)
+ print(pl)
+ assert len(pl) == 2
+ assert pl[0] == tmpdir
+ assert pl[1] == somepath
+
+ def test_addini(self, testdir):
+ testdir.makeconftest("""
+ def pytest_addoption(parser):
+ parser.addini("myname", "my new ini value")
+ """)
+ testdir.makeini("""
+ [pytest]
+ myname=hello
+ """)
+ config = testdir.parseconfig()
+ val = config.getini("myname")
+ assert val == "hello"
+ pytest.raises(ValueError, config.getini, 'other')
+
+ def test_addini_pathlist(self, testdir):
+ testdir.makeconftest("""
+ def pytest_addoption(parser):
+ parser.addini("paths", "my new ini value", type="pathlist")
+ parser.addini("abc", "abc value")
+ """)
+ p = testdir.makeini("""
+ [pytest]
+ paths=hello world/sub.py
+ """)
+ config = testdir.parseconfig()
+ values = config.getini("paths")
+ assert len(values) == 2
+ assert values[0] == p.dirpath('hello')
+ assert values[1] == p.dirpath('world/sub.py')
+ pytest.raises(ValueError, config.getini, 'other')
+
+ def test_addini_args(self, testdir):
+ testdir.makeconftest("""
+ def pytest_addoption(parser):
+ parser.addini("args", "new args", type="args")
+ parser.addini("a2", "", "args", default="1 2 3".split())
+ """)
+ testdir.makeini("""
+ [pytest]
+ args=123 "123 hello" "this"
+ """)
+ config = testdir.parseconfig()
+ values = config.getini("args")
+ assert len(values) == 3
+ assert values == ["123", "123 hello", "this"]
+ values = config.getini("a2")
+ assert values == list("123")
+
+ def test_addini_linelist(self, testdir):
+ testdir.makeconftest("""
+ def pytest_addoption(parser):
+ parser.addini("xy", "", type="linelist")
+ parser.addini("a2", "", "linelist")
+ """)
+ testdir.makeini("""
+ [pytest]
+ xy= 123 345
+ second line
+ """)
+ config = testdir.parseconfig()
+ values = config.getini("xy")
+ assert len(values) == 2
+ assert values == ["123 345", "second line"]
+ values = config.getini("a2")
+ assert values == []
+
+ @pytest.mark.parametrize('str_val, bool_val',
+ [('True', True), ('no', False), ('no-ini', True)])
+ def test_addini_bool(self, testdir, str_val, bool_val):
+ testdir.makeconftest("""
+ def pytest_addoption(parser):
+ parser.addini("strip", "", type="bool", default=True)
+ """)
+ if str_val != 'no-ini':
+ testdir.makeini("""
+ [pytest]
+ strip=%s
+ """ % str_val)
+ config = testdir.parseconfig()
+ assert config.getini("strip") is bool_val
+
+ def test_addinivalue_line_existing(self, testdir):
+ testdir.makeconftest("""
+ def pytest_addoption(parser):
+ parser.addini("xy", "", type="linelist")
+ """)
+ testdir.makeini("""
+ [pytest]
+ xy= 123
+ """)
+ config = testdir.parseconfig()
+ values = config.getini("xy")
+ assert len(values) == 1
+ assert values == ["123"]
+ config.addinivalue_line("xy", "456")
+ values = config.getini("xy")
+ assert len(values) == 2
+ assert values == ["123", "456"]
+
+ def test_addinivalue_line_new(self, testdir):
+ testdir.makeconftest("""
+ def pytest_addoption(parser):
+ parser.addini("xy", "", type="linelist")
+ """)
+ config = testdir.parseconfig()
+ assert not config.getini("xy")
+ config.addinivalue_line("xy", "456")
+ values = config.getini("xy")
+ assert len(values) == 1
+ assert values == ["456"]
+ config.addinivalue_line("xy", "123")
+ values = config.getini("xy")
+ assert len(values) == 2
+ assert values == ["456", "123"]
+
+ def test_confcutdir_check_isdir(self, testdir):
+ """Give an error if --confcutdir is not a valid directory (#2078)"""
+ with pytest.raises(pytest.UsageError):
+ testdir.parseconfig('--confcutdir', testdir.tmpdir.join('file').ensure(file=1))
+ with pytest.raises(pytest.UsageError):
+ testdir.parseconfig('--confcutdir', testdir.tmpdir.join('inexistant'))
+ config = testdir.parseconfig('--confcutdir', testdir.tmpdir.join('dir').ensure(dir=1))
+ assert config.getoption('confcutdir') == str(testdir.tmpdir.join('dir'))
+
+ @pytest.mark.parametrize('names, expected', [
+ (['bar.py'], ['bar']),
+ (['foo', 'bar.py'], []),
+ (['foo', 'bar.pyc'], []),
+ (['foo', '__init__.py'], ['foo']),
+ (['foo', 'bar', '__init__.py'], []),
+ ])
+ def test_iter_rewritable_modules(self, names, expected):
+ assert list(_iter_rewritable_modules(['/'.join(names)])) == expected
+
+
+class TestConfigFromdictargs(object):
+ def test_basic_behavior(self):
+ from _pytest.config import Config
+ option_dict = {
+ 'verbose': 444,
+ 'foo': 'bar',
+ 'capture': 'no',
+ }
+ args = ['a', 'b']
+
+ config = Config.fromdictargs(option_dict, args)
+ with pytest.raises(AssertionError):
+ config.parse(['should refuse to parse again'])
+ assert config.option.verbose == 444
+ assert config.option.foo == 'bar'
+ assert config.option.capture == 'no'
+ assert config.args == args
+
+ def test_origargs(self):
+ """Show that fromdictargs can handle args in their "orig" format"""
+ from _pytest.config import Config
+ option_dict = {}
+ args = ['-vvvv', '-s', 'a', 'b']
+
+ config = Config.fromdictargs(option_dict, args)
+ assert config.args == ['a', 'b']
+ assert config._origargs == args
+ assert config.option.verbose == 4
+ assert config.option.capture == 'no'
+
+ def test_inifilename(self, tmpdir):
+ tmpdir.join("foo/bar.ini").ensure().write(_pytest._code.Source("""
+ [pytest]
+ name = value
+ """))
+
+ from _pytest.config import Config
+ inifile = '../../foo/bar.ini'
+ option_dict = {
+ 'inifilename': inifile,
+ 'capture': 'no',
+ }
+
+ cwd = tmpdir.join('a/b')
+ cwd.join('pytest.ini').ensure().write(_pytest._code.Source("""
+ [pytest]
+ name = wrong-value
+ should_not_be_set = true
+ """))
+ with cwd.ensure(dir=True).as_cwd():
+ config = Config.fromdictargs(option_dict, ())
+
+ assert config.args == [str(cwd)]
+ assert config.option.inifilename == inifile
+ assert config.option.capture == 'no'
+
+ # this indicates this is the file used for getting configuration values
+ assert config.inifile == inifile
+ assert config.inicfg.get('name') == 'value'
+ assert config.inicfg.get('should_not_be_set') is None
+
+
+def test_options_on_small_file_do_not_blow_up(testdir):
+ def runfiletest(opts):
+ reprec = testdir.inline_run(*opts)
+ passed, skipped, failed = reprec.countoutcomes()
+ assert failed == 2
+ assert skipped == passed == 0
+ path = testdir.makepyfile("""
+ def test_f1(): assert 0
+ def test_f2(): assert 0
+ """)
+
+ for opts in ([], ['-l'], ['-s'], ['--tb=no'], ['--tb=short'],
+ ['--tb=long'], ['--fulltrace'],
+ ['--traceconfig'], ['-v'], ['-v', '-v']):
+ runfiletest(opts + [path])
+
+
+def test_preparse_ordering_with_setuptools(testdir, monkeypatch):
+ pkg_resources = pytest.importorskip("pkg_resources")
+
+ def my_iter(name):
+ assert name == "pytest11"
+
+ class Dist(object):
+ project_name = 'spam'
+ version = '1.0'
+
+ def _get_metadata(self, name):
+ return ['foo.txt,sha256=abc,123']
+
+ class EntryPoint(object):
+ name = "mytestplugin"
+ dist = Dist()
+
+ def load(self):
+ class PseudoPlugin(object):
+ x = 42
+ return PseudoPlugin()
+
+ return iter([EntryPoint()])
+
+ monkeypatch.setattr(pkg_resources, 'iter_entry_points', my_iter)
+ testdir.makeconftest("""
+ pytest_plugins = "mytestplugin",
+ """)
+ monkeypatch.setenv("PYTEST_PLUGINS", "mytestplugin")
+ config = testdir.parseconfig()
+ plugin = config.pluginmanager.getplugin("mytestplugin")
+ assert plugin.x == 42
+
+
+def test_setuptools_importerror_issue1479(testdir, monkeypatch):
+ pkg_resources = pytest.importorskip("pkg_resources")
+
+ def my_iter(name):
+ assert name == "pytest11"
+
+ class Dist(object):
+ project_name = 'spam'
+ version = '1.0'
+
+ def _get_metadata(self, name):
+ return ['foo.txt,sha256=abc,123']
+
+ class EntryPoint(object):
+ name = "mytestplugin"
+ dist = Dist()
+
+ def load(self):
+ raise ImportError("Don't hide me!")
+
+ return iter([EntryPoint()])
+
+ monkeypatch.setattr(pkg_resources, 'iter_entry_points', my_iter)
+ with pytest.raises(ImportError):
+ testdir.parseconfig()
+
+
+@pytest.mark.parametrize('block_it', [True, False])
+def test_plugin_preparse_prevents_setuptools_loading(testdir, monkeypatch, block_it):
+ pkg_resources = pytest.importorskip("pkg_resources")
+
+ plugin_module_placeholder = object()
+
+ def my_iter(name):
+ assert name == "pytest11"
+
+ class Dist(object):
+ project_name = 'spam'
+ version = '1.0'
+
+ def _get_metadata(self, name):
+ return ['foo.txt,sha256=abc,123']
+
+ class EntryPoint(object):
+ name = "mytestplugin"
+ dist = Dist()
+
+ def load(self):
+ return plugin_module_placeholder
+
+ return iter([EntryPoint()])
+
+ monkeypatch.setattr(pkg_resources, 'iter_entry_points', my_iter)
+ args = ("-p", "no:mytestplugin") if block_it else ()
+ config = testdir.parseconfig(*args)
+ config.pluginmanager.import_plugin("mytestplugin")
+ if block_it:
+ assert "mytestplugin" not in sys.modules
+ assert config.pluginmanager.get_plugin('mytestplugin') is None
+ else:
+ assert config.pluginmanager.get_plugin('mytestplugin') is plugin_module_placeholder
+
+
+def test_cmdline_processargs_simple(testdir):
+ testdir.makeconftest("""
+ def pytest_cmdline_preparse(args):
+ args.append("-h")
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*pytest*",
+ "*-h*",
+ ])
+
+
+def test_invalid_options_show_extra_information(testdir):
+ """display extra information when pytest exits due to unrecognized
+ options in the command-line"""
+ testdir.makeini("""
+ [pytest]
+ addopts = --invalid-option
+ """)
+ result = testdir.runpytest()
+ result.stderr.fnmatch_lines([
+ "*error: unrecognized arguments: --invalid-option*",
+ "* inifile: %s*" % testdir.tmpdir.join('tox.ini'),
+ "* rootdir: %s*" % testdir.tmpdir,
+ ])
+
+
+@pytest.mark.parametrize('args', [
+ ['dir1', 'dir2', '-v'],
+ ['dir1', '-v', 'dir2'],
+ ['dir2', '-v', 'dir1'],
+ ['-v', 'dir2', 'dir1'],
+])
+def test_consider_args_after_options_for_rootdir_and_inifile(testdir, args):
+ """
+ Consider all arguments in the command-line for rootdir and inifile
+ discovery, even if they happen to occur after an option. #949
+ """
+ # replace "dir1" and "dir2" from "args" into their real directory
+ root = testdir.tmpdir.mkdir('myroot')
+ d1 = root.mkdir('dir1')
+ d2 = root.mkdir('dir2')
+ for i, arg in enumerate(args):
+ if arg == 'dir1':
+ args[i] = d1
+ elif arg == 'dir2':
+ args[i] = d2
+ with root.as_cwd():
+ result = testdir.runpytest(*args)
+ result.stdout.fnmatch_lines(['*rootdir: *myroot, inifile:'])
+
+
+@pytest.mark.skipif("sys.platform == 'win32'")
+def test_toolongargs_issue224(testdir):
+ result = testdir.runpytest("-m", "hello" * 500)
+ assert result.ret == EXIT_NOTESTSCOLLECTED
+
+
+def test_config_in_subdirectory_colon_command_line_issue2148(testdir):
+ conftest_source = '''
+ def pytest_addoption(parser):
+ parser.addini('foo', 'foo')
+ '''
+
+ testdir.makefile('.ini', **{
+ 'pytest': '[pytest]\nfoo = root',
+ 'subdir/pytest': '[pytest]\nfoo = subdir',
+ })
+
+ testdir.makepyfile(**{
+ 'conftest': conftest_source,
+ 'subdir/conftest': conftest_source,
+ 'subdir/test_foo': '''
+ def test_foo(pytestconfig):
+ assert pytestconfig.getini('foo') == 'subdir'
+ '''})
+
+ result = testdir.runpytest('subdir/test_foo.py::test_foo')
+ assert result.ret == 0
+
+
+def test_notify_exception(testdir, capfd):
+ config = testdir.parseconfig()
+ excinfo = pytest.raises(ValueError, "raise ValueError(1)")
+ config.notify_exception(excinfo)
+ out, err = capfd.readouterr()
+ assert "ValueError" in err
+
+ class A(object):
+ def pytest_internalerror(self, excrepr):
+ return True
+
+ config.pluginmanager.register(A())
+ config.notify_exception(excinfo)
+ out, err = capfd.readouterr()
+ assert not err
+
+
+def test_load_initial_conftest_last_ordering(testdir):
+ from _pytest.config import get_config
+ pm = get_config().pluginmanager
+
+ class My(object):
+ def pytest_load_initial_conftests(self):
+ pass
+
+ m = My()
+ pm.register(m)
+ hc = pm.hook.pytest_load_initial_conftests
+ values = hc._nonwrappers + hc._wrappers
+ expected = [
+ "_pytest.config",
+ 'test_config',
+ '_pytest.capture',
+ ]
+ assert [x.function.__module__ for x in values] == expected
+
+
+def test_get_plugin_specs_as_list():
+ from _pytest.config import _get_plugin_specs_as_list
+ with pytest.raises(pytest.UsageError):
+ _get_plugin_specs_as_list(set(['foo']))
+ with pytest.raises(pytest.UsageError):
+ _get_plugin_specs_as_list(dict())
+
+ assert _get_plugin_specs_as_list(None) == []
+ assert _get_plugin_specs_as_list('') == []
+ assert _get_plugin_specs_as_list('foo') == ['foo']
+ assert _get_plugin_specs_as_list('foo,bar') == ['foo', 'bar']
+ assert _get_plugin_specs_as_list(['foo', 'bar']) == ['foo', 'bar']
+ assert _get_plugin_specs_as_list(('foo', 'bar')) == ['foo', 'bar']
+
+
+class TestWarning(object):
+ def test_warn_config(self, testdir):
+ testdir.makeconftest("""
+ values = []
+ def pytest_configure(config):
+ config.warn("C1", "hello")
+ def pytest_logwarning(code, message):
+ if message == "hello" and code == "C1":
+ values.append(1)
+ """)
+ testdir.makepyfile("""
+ def test_proper(pytestconfig):
+ import conftest
+ assert conftest.values == [1]
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+ def test_warn_on_test_item_from_request(self, testdir, request):
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture
+ def fix(request):
+ request.node.warn("T1", "hello")
+
+ def test_hello(fix):
+ pass
+ """)
+ result = testdir.runpytest("--disable-pytest-warnings")
+ assert result.parseoutcomes()["warnings"] > 0
+ assert "hello" not in result.stdout.str()
+
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines("""
+ ===*warnings summary*===
+ *test_warn_on_test_item_from_request.py::test_hello*
+ *hello*
+ """)
+
+
+class TestRootdir(object):
+ def test_simple_noini(self, tmpdir):
+ assert get_common_ancestor([tmpdir]) == tmpdir
+ a = tmpdir.mkdir("a")
+ assert get_common_ancestor([a, tmpdir]) == tmpdir
+ assert get_common_ancestor([tmpdir, a]) == tmpdir
+ with tmpdir.as_cwd():
+ assert get_common_ancestor([]) == tmpdir
+ no_path = tmpdir.join('does-not-exist')
+ assert get_common_ancestor([no_path]) == tmpdir
+ assert get_common_ancestor([no_path.join('a')]) == tmpdir
+
+ @pytest.mark.parametrize("name", "setup.cfg tox.ini pytest.ini".split())
+ def test_with_ini(self, tmpdir, name):
+ inifile = tmpdir.join(name)
+ inifile.write("[pytest]\n")
+
+ a = tmpdir.mkdir("a")
+ b = a.mkdir("b")
+ for args in ([tmpdir], [a], [b]):
+ rootdir, inifile, inicfg = determine_setup(None, args)
+ assert rootdir == tmpdir
+ assert inifile == inifile
+ rootdir, inifile, inicfg = determine_setup(None, [b, a])
+ assert rootdir == tmpdir
+ assert inifile == inifile
+
+ @pytest.mark.parametrize("name", "setup.cfg tox.ini".split())
+ def test_pytestini_overides_empty_other(self, tmpdir, name):
+ inifile = tmpdir.ensure("pytest.ini")
+ a = tmpdir.mkdir("a")
+ a.ensure(name)
+ rootdir, inifile, inicfg = determine_setup(None, [a])
+ assert rootdir == tmpdir
+ assert inifile == inifile
+
+ def test_setuppy_fallback(self, tmpdir):
+ a = tmpdir.mkdir("a")
+ a.ensure("setup.cfg")
+ tmpdir.ensure("setup.py")
+ rootdir, inifile, inicfg = determine_setup(None, [a])
+ assert rootdir == tmpdir
+ assert inifile is None
+ assert inicfg == {}
+
+ def test_nothing(self, tmpdir, monkeypatch):
+ monkeypatch.chdir(str(tmpdir))
+ rootdir, inifile, inicfg = determine_setup(None, [tmpdir])
+ assert rootdir == tmpdir
+ assert inifile is None
+ assert inicfg == {}
+
+ def test_with_specific_inifile(self, tmpdir):
+ inifile = tmpdir.ensure("pytest.ini")
+ rootdir, inifile, inicfg = determine_setup(inifile, [tmpdir])
+ assert rootdir == tmpdir
+
+
+class TestOverrideIniArgs(object):
+ @pytest.mark.parametrize("name", "setup.cfg tox.ini pytest.ini".split())
+ def test_override_ini_names(self, testdir, name):
+ testdir.tmpdir.join(name).write(py.std.textwrap.dedent("""
+ [pytest]
+ custom = 1.0"""))
+ testdir.makeconftest("""
+ def pytest_addoption(parser):
+ parser.addini("custom", "")""")
+ testdir.makepyfile("""
+ def test_pass(pytestconfig):
+ ini_val = pytestconfig.getini("custom")
+ print('\\ncustom_option:%s\\n' % ini_val)""")
+
+ result = testdir.runpytest("--override-ini", "custom=2.0", "-s")
+ assert result.ret == 0
+ result.stdout.fnmatch_lines(["custom_option:2.0"])
+
+ result = testdir.runpytest("--override-ini", "custom=2.0",
+ "--override-ini=custom=3.0", "-s")
+ assert result.ret == 0
+ result.stdout.fnmatch_lines(["custom_option:3.0"])
+
+ def test_override_ini_pathlist(self, testdir):
+ testdir.makeconftest("""
+ def pytest_addoption(parser):
+ parser.addini("paths", "my new ini value", type="pathlist")""")
+ testdir.makeini("""
+ [pytest]
+ paths=blah.py""")
+ testdir.makepyfile("""
+ import py.path
+ def test_pathlist(pytestconfig):
+ config_paths = pytestconfig.getini("paths")
+ print(config_paths)
+ for cpf in config_paths:
+ print('\\nuser_path:%s' % cpf.basename)""")
+ result = testdir.runpytest("--override-ini",
+ 'paths=foo/bar1.py foo/bar2.py', "-s")
+ result.stdout.fnmatch_lines(["user_path:bar1.py",
+ "user_path:bar2.py"])
+
+ def test_override_multiple_and_default(self, testdir):
+ testdir.makeconftest("""
+ def pytest_addoption(parser):
+ addini = parser.addini
+ addini("custom_option_1", "", default="o1")
+ addini("custom_option_2", "", default="o2")
+ addini("custom_option_3", "", default=False, type="bool")
+ addini("custom_option_4", "", default=True, type="bool")""")
+ testdir.makeini("""
+ [pytest]
+ custom_option_1=custom_option_1
+ custom_option_2=custom_option_2""")
+ testdir.makepyfile("""
+ def test_multiple_options(pytestconfig):
+ prefix = "custom_option"
+ for x in range(1, 5):
+ ini_value=pytestconfig.getini("%s_%d" % (prefix, x))
+ print('\\nini%d:%s' % (x, ini_value))""")
+ result = testdir.runpytest(
+ "--override-ini", 'custom_option_1=fulldir=/tmp/user1',
+ 'custom_option_2=url=/tmp/user2?a=b&d=e',
+ "-o", 'custom_option_3=True',
+ "-o", 'custom_option_4=no', "-s")
+ result.stdout.fnmatch_lines(["ini1:fulldir=/tmp/user1",
+ "ini2:url=/tmp/user2?a=b&d=e",
+ "ini3:True",
+ "ini4:False"])
+
+ def test_override_ini_usage_error_bad_style(self, testdir):
+ testdir.makeini("""
+ [pytest]
+ xdist_strict=False
+ """)
+ result = testdir.runpytest("--override-ini", 'xdist_strict True', "-s")
+ result.stderr.fnmatch_lines(["*ERROR* *expects option=value*"])
+
+ @pytest.mark.parametrize('with_ini', [True, False])
+ def test_override_ini_handled_asap(self, testdir, with_ini):
+ """-o should be handled as soon as possible and always override what's in ini files (#2238)"""
+ if with_ini:
+ testdir.makeini("""
+ [pytest]
+ python_files=test_*.py
+ """)
+ testdir.makepyfile(unittest_ini_handle="""
+ def test():
+ pass
+ """)
+ result = testdir.runpytest("--override-ini", 'python_files=unittest_*.py')
+ result.stdout.fnmatch_lines(["*1 passed in*"])
+
+ def test_with_arg_outside_cwd_without_inifile(self, tmpdir, monkeypatch):
+ monkeypatch.chdir(str(tmpdir))
+ a = tmpdir.mkdir("a")
+ b = tmpdir.mkdir("b")
+ rootdir, inifile, inicfg = determine_setup(None, [a, b])
+ assert rootdir == tmpdir
+ assert inifile is None
+
+ def test_with_arg_outside_cwd_with_inifile(self, tmpdir):
+ a = tmpdir.mkdir("a")
+ b = tmpdir.mkdir("b")
+ inifile = a.ensure("pytest.ini")
+ rootdir, parsed_inifile, inicfg = determine_setup(None, [a, b])
+ assert rootdir == a
+ assert inifile == parsed_inifile
+
+ @pytest.mark.parametrize('dirs', ([], ['does-not-exist'],
+ ['a/does-not-exist']))
+ def test_with_non_dir_arg(self, dirs, tmpdir):
+ with tmpdir.ensure(dir=True).as_cwd():
+ rootdir, inifile, inicfg = determine_setup(None, dirs)
+ assert rootdir == tmpdir
+ assert inifile is None
+
+ def test_with_existing_file_in_subdir(self, tmpdir):
+ a = tmpdir.mkdir("a")
+ a.ensure("exist")
+ with tmpdir.as_cwd():
+ rootdir, inifile, inicfg = determine_setup(None, ['a/exist'])
+ assert rootdir == tmpdir
+ assert inifile is None
+
+ def test_addopts_before_initini(self, testdir, tmpdir, monkeypatch):
+ cache_dir = '.custom_cache'
+ monkeypatch.setenv('PYTEST_ADDOPTS', '-o cache_dir=%s' % cache_dir)
+ from _pytest.config import get_config
+ config = get_config()
+ config._preparse([], addopts=True)
+ assert config._override_ini == [['cache_dir=%s' % cache_dir]]
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_conftest.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_conftest.py
new file mode 100644
index 00000000000..c0411b72321
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_conftest.py
@@ -0,0 +1,478 @@
+from __future__ import absolute_import, division, print_function
+from textwrap import dedent
+
+import _pytest._code
+import py
+import pytest
+from _pytest.config import PytestPluginManager
+from _pytest.main import EXIT_NOTESTSCOLLECTED, EXIT_USAGEERROR
+
+
+@pytest.fixture(scope="module", params=["global", "inpackage"])
+def basedir(request, tmpdir_factory):
+ from _pytest.tmpdir import tmpdir
+ tmpdir = tmpdir(request, tmpdir_factory)
+ tmpdir.ensure("adir/conftest.py").write("a=1 ; Directory = 3")
+ tmpdir.ensure("adir/b/conftest.py").write("b=2 ; a = 1.5")
+ if request.param == "inpackage":
+ tmpdir.ensure("adir/__init__.py")
+ tmpdir.ensure("adir/b/__init__.py")
+ return tmpdir
+
+
+def ConftestWithSetinitial(path):
+ conftest = PytestPluginManager()
+ conftest_setinitial(conftest, [path])
+ return conftest
+
+
+def conftest_setinitial(conftest, args, confcutdir=None):
+ class Namespace(object):
+ def __init__(self):
+ self.file_or_dir = args
+ self.confcutdir = str(confcutdir)
+ self.noconftest = False
+ conftest._set_initial_conftests(Namespace())
+
+
+class TestConftestValueAccessGlobal(object):
+ def test_basic_init(self, basedir):
+ conftest = PytestPluginManager()
+ p = basedir.join("adir")
+ assert conftest._rget_with_confmod("a", p)[1] == 1
+
+ def test_immediate_initialiation_and_incremental_are_the_same(self, basedir):
+ conftest = PytestPluginManager()
+ len(conftest._path2confmods)
+ conftest._getconftestmodules(basedir)
+ snap1 = len(conftest._path2confmods)
+ # assert len(conftest._path2confmods) == snap1 + 1
+ conftest._getconftestmodules(basedir.join('adir'))
+ assert len(conftest._path2confmods) == snap1 + 1
+ conftest._getconftestmodules(basedir.join('b'))
+ assert len(conftest._path2confmods) == snap1 + 2
+
+ def test_value_access_not_existing(self, basedir):
+ conftest = ConftestWithSetinitial(basedir)
+ with pytest.raises(KeyError):
+ conftest._rget_with_confmod('a', basedir)
+
+ def test_value_access_by_path(self, basedir):
+ conftest = ConftestWithSetinitial(basedir)
+ adir = basedir.join("adir")
+ assert conftest._rget_with_confmod("a", adir)[1] == 1
+ assert conftest._rget_with_confmod("a", adir.join("b"))[1] == 1.5
+
+ def test_value_access_with_confmod(self, basedir):
+ startdir = basedir.join("adir", "b")
+ startdir.ensure("xx", dir=True)
+ conftest = ConftestWithSetinitial(startdir)
+ mod, value = conftest._rget_with_confmod("a", startdir)
+ assert value == 1.5
+ path = py.path.local(mod.__file__)
+ assert path.dirpath() == basedir.join("adir", "b")
+ assert path.purebasename.startswith("conftest")
+
+
+def test_conftest_in_nonpkg_with_init(tmpdir):
+ tmpdir.ensure("adir-1.0/conftest.py").write("a=1 ; Directory = 3")
+ tmpdir.ensure("adir-1.0/b/conftest.py").write("b=2 ; a = 1.5")
+ tmpdir.ensure("adir-1.0/b/__init__.py")
+ tmpdir.ensure("adir-1.0/__init__.py")
+ ConftestWithSetinitial(tmpdir.join("adir-1.0", "b"))
+
+
+def test_doubledash_considered(testdir):
+ conf = testdir.mkdir("--option")
+ conf.join("conftest.py").ensure()
+ conftest = PytestPluginManager()
+ conftest_setinitial(conftest, [conf.basename, conf.basename])
+ values = conftest._getconftestmodules(conf)
+ assert len(values) == 1
+
+
+def test_issue151_load_all_conftests(testdir):
+ names = "code proj src".split()
+ for name in names:
+ p = testdir.mkdir(name)
+ p.ensure("conftest.py")
+
+ conftest = PytestPluginManager()
+ conftest_setinitial(conftest, names)
+ d = list(conftest._conftestpath2mod.values())
+ assert len(d) == len(names)
+
+
+def test_conftest_global_import(testdir):
+ testdir.makeconftest("x=3")
+ p = testdir.makepyfile("""
+ import py, pytest
+ from _pytest.config import PytestPluginManager
+ conf = PytestPluginManager()
+ mod = conf._importconftest(py.path.local("conftest.py"))
+ assert mod.x == 3
+ import conftest
+ assert conftest is mod, (conftest, mod)
+ subconf = py.path.local().ensure("sub", "conftest.py")
+ subconf.write("y=4")
+ mod2 = conf._importconftest(subconf)
+ assert mod != mod2
+ assert mod2.y == 4
+ import conftest
+ assert conftest is mod2, (conftest, mod)
+ """)
+ res = testdir.runpython(p)
+ assert res.ret == 0
+
+
+def test_conftestcutdir(testdir):
+ conf = testdir.makeconftest("")
+ p = testdir.mkdir("x")
+ conftest = PytestPluginManager()
+ conftest_setinitial(conftest, [testdir.tmpdir], confcutdir=p)
+ values = conftest._getconftestmodules(p)
+ assert len(values) == 0
+ values = conftest._getconftestmodules(conf.dirpath())
+ assert len(values) == 0
+ assert conf not in conftest._conftestpath2mod
+ # but we can still import a conftest directly
+ conftest._importconftest(conf)
+ values = conftest._getconftestmodules(conf.dirpath())
+ assert values[0].__file__.startswith(str(conf))
+ # and all sub paths get updated properly
+ values = conftest._getconftestmodules(p)
+ assert len(values) == 1
+ assert values[0].__file__.startswith(str(conf))
+
+
+def test_conftestcutdir_inplace_considered(testdir):
+ conf = testdir.makeconftest("")
+ conftest = PytestPluginManager()
+ conftest_setinitial(conftest, [conf.dirpath()], confcutdir=conf.dirpath())
+ values = conftest._getconftestmodules(conf.dirpath())
+ assert len(values) == 1
+ assert values[0].__file__.startswith(str(conf))
+
+
+@pytest.mark.parametrize("name", 'test tests whatever .dotdir'.split())
+def test_setinitial_conftest_subdirs(testdir, name):
+ sub = testdir.mkdir(name)
+ subconftest = sub.ensure("conftest.py")
+ conftest = PytestPluginManager()
+ conftest_setinitial(conftest, [sub.dirpath()], confcutdir=testdir.tmpdir)
+ if name not in ('whatever', '.dotdir'):
+ assert subconftest in conftest._conftestpath2mod
+ assert len(conftest._conftestpath2mod) == 1
+ else:
+ assert subconftest not in conftest._conftestpath2mod
+ assert len(conftest._conftestpath2mod) == 0
+
+
+def test_conftest_confcutdir(testdir):
+ testdir.makeconftest("assert 0")
+ x = testdir.mkdir("x")
+ x.join("conftest.py").write(_pytest._code.Source("""
+ def pytest_addoption(parser):
+ parser.addoption("--xyz", action="store_true")
+ """))
+ result = testdir.runpytest("-h", "--confcutdir=%s" % x, x)
+ result.stdout.fnmatch_lines(["*--xyz*"])
+ assert 'warning: could not load initial' not in result.stdout.str()
+
+
+def test_no_conftest(testdir):
+ testdir.makeconftest("assert 0")
+ result = testdir.runpytest("--noconftest")
+ assert result.ret == EXIT_NOTESTSCOLLECTED
+
+ result = testdir.runpytest()
+ assert result.ret == EXIT_USAGEERROR
+
+
+def test_conftest_existing_resultlog(testdir):
+ x = testdir.mkdir("tests")
+ x.join("conftest.py").write(_pytest._code.Source("""
+ def pytest_addoption(parser):
+ parser.addoption("--xyz", action="store_true")
+ """))
+ testdir.makefile(ext=".log", result="") # Writes result.log
+ result = testdir.runpytest("-h", "--resultlog", "result.log")
+ result.stdout.fnmatch_lines(["*--xyz*"])
+
+
+def test_conftest_existing_junitxml(testdir):
+ x = testdir.mkdir("tests")
+ x.join("conftest.py").write(_pytest._code.Source("""
+ def pytest_addoption(parser):
+ parser.addoption("--xyz", action="store_true")
+ """))
+ testdir.makefile(ext=".xml", junit="") # Writes junit.xml
+ result = testdir.runpytest("-h", "--junitxml", "junit.xml")
+ result.stdout.fnmatch_lines(["*--xyz*"])
+
+
+def test_conftest_import_order(testdir, monkeypatch):
+ ct1 = testdir.makeconftest("")
+ sub = testdir.mkdir("sub")
+ ct2 = sub.join("conftest.py")
+ ct2.write("")
+
+ def impct(p):
+ return p
+
+ conftest = PytestPluginManager()
+ conftest._confcutdir = testdir.tmpdir
+ monkeypatch.setattr(conftest, '_importconftest', impct)
+ assert conftest._getconftestmodules(sub) == [ct1, ct2]
+
+
+def test_fixture_dependency(testdir, monkeypatch):
+ ct1 = testdir.makeconftest("")
+ ct1 = testdir.makepyfile("__init__.py")
+ ct1.write("")
+ sub = testdir.mkdir("sub")
+ sub.join("__init__.py").write("")
+ sub.join("conftest.py").write(py.std.textwrap.dedent("""
+ import pytest
+
+ @pytest.fixture
+ def not_needed():
+ assert False, "Should not be called!"
+
+ @pytest.fixture
+ def foo():
+ assert False, "Should not be called!"
+
+ @pytest.fixture
+ def bar(foo):
+ return 'bar'
+ """))
+ subsub = sub.mkdir("subsub")
+ subsub.join("__init__.py").write("")
+ subsub.join("test_bar.py").write(py.std.textwrap.dedent("""
+ import pytest
+
+ @pytest.fixture
+ def bar():
+ return 'sub bar'
+
+ def test_event_fixture(bar):
+ assert bar == 'sub bar'
+ """))
+ result = testdir.runpytest("sub")
+ result.stdout.fnmatch_lines(["*1 passed*"])
+
+
+def test_conftest_found_with_double_dash(testdir):
+ sub = testdir.mkdir("sub")
+ sub.join("conftest.py").write(py.std.textwrap.dedent("""
+ def pytest_addoption(parser):
+ parser.addoption("--hello-world", action="store_true")
+ """))
+ p = sub.join("test_hello.py")
+ p.write(py.std.textwrap.dedent("""
+ import pytest
+ def test_hello(found):
+ assert found == 1
+ """))
+ result = testdir.runpytest(str(p) + "::test_hello", "-h")
+ result.stdout.fnmatch_lines("""
+ *--hello-world*
+ """)
+
+
+class TestConftestVisibility(object):
+ def _setup_tree(self, testdir): # for issue616
+ # example mostly taken from:
+ # https://mail.python.org/pipermail/pytest-dev/2014-September/002617.html
+ runner = testdir.mkdir("empty")
+ package = testdir.mkdir("package")
+
+ package.join("conftest.py").write(dedent("""\
+ import pytest
+ @pytest.fixture
+ def fxtr():
+ return "from-package"
+ """))
+ package.join("test_pkgroot.py").write(dedent("""\
+ def test_pkgroot(fxtr):
+ assert fxtr == "from-package"
+ """))
+
+ swc = package.mkdir("swc")
+ swc.join("__init__.py").ensure()
+ swc.join("conftest.py").write(dedent("""\
+ import pytest
+ @pytest.fixture
+ def fxtr():
+ return "from-swc"
+ """))
+ swc.join("test_with_conftest.py").write(dedent("""\
+ def test_with_conftest(fxtr):
+ assert fxtr == "from-swc"
+
+ """))
+
+ snc = package.mkdir("snc")
+ snc.join("__init__.py").ensure()
+ snc.join("test_no_conftest.py").write(dedent("""\
+ def test_no_conftest(fxtr):
+ assert fxtr == "from-package" # No local conftest.py, so should
+ # use value from parent dir's
+
+ """))
+ print("created directory structure:")
+ for x in testdir.tmpdir.visit():
+ print(" " + x.relto(testdir.tmpdir))
+
+ return {
+ "runner": runner,
+ "package": package,
+ "swc": swc,
+ "snc": snc}
+
+ # N.B.: "swc" stands for "subdir with conftest.py"
+ # "snc" stands for "subdir no [i.e. without] conftest.py"
+ @pytest.mark.parametrize("chdir,testarg,expect_ntests_passed", [
+ # Effective target: package/..
+ ("runner", "..", 3),
+ ("package", "..", 3),
+ ("swc", "../..", 3),
+ ("snc", "../..", 3),
+
+ # Effective target: package
+ ("runner", "../package", 3),
+ ("package", ".", 3),
+ ("swc", "..", 3),
+ ("snc", "..", 3),
+
+ # Effective target: package/swc
+ ("runner", "../package/swc", 1),
+ ("package", "./swc", 1),
+ ("swc", ".", 1),
+ ("snc", "../swc", 1),
+
+ # Effective target: package/snc
+ ("runner", "../package/snc", 1),
+ ("package", "./snc", 1),
+ ("swc", "../snc", 1),
+ ("snc", ".", 1),
+ ])
+ @pytest.mark.issue616
+ def test_parsefactories_relative_node_ids(
+ self, testdir, chdir, testarg, expect_ntests_passed):
+ dirs = self._setup_tree(testdir)
+ print("pytest run in cwd: %s" % (
+ dirs[chdir].relto(testdir.tmpdir)))
+ print("pytestarg : %s" % (testarg))
+ print("expected pass : %s" % (expect_ntests_passed))
+ with dirs[chdir].as_cwd():
+ reprec = testdir.inline_run(testarg, "-q", "--traceconfig")
+ reprec.assertoutcome(passed=expect_ntests_passed)
+
+
+@pytest.mark.parametrize('confcutdir,passed,error', [
+ ('.', 2, 0),
+ ('src', 1, 1),
+ (None, 1, 1),
+])
+def test_search_conftest_up_to_inifile(testdir, confcutdir, passed, error):
+ """Test that conftest files are detected only up to a ini file, unless
+ an explicit --confcutdir option is given.
+ """
+ root = testdir.tmpdir
+ src = root.join('src').ensure(dir=1)
+ src.join('pytest.ini').write('[pytest]')
+ src.join('conftest.py').write(_pytest._code.Source("""
+ import pytest
+ @pytest.fixture
+ def fix1(): pass
+ """))
+ src.join('test_foo.py').write(_pytest._code.Source("""
+ def test_1(fix1):
+ pass
+ def test_2(out_of_reach):
+ pass
+ """))
+ root.join('conftest.py').write(_pytest._code.Source("""
+ import pytest
+ @pytest.fixture
+ def out_of_reach(): pass
+ """))
+
+ args = [str(src)]
+ if confcutdir:
+ args = ['--confcutdir=%s' % root.join(confcutdir)]
+ result = testdir.runpytest(*args)
+ match = ''
+ if passed:
+ match += '*%d passed*' % passed
+ if error:
+ match += '*%d error*' % error
+ result.stdout.fnmatch_lines(match)
+
+
+def test_issue1073_conftest_special_objects(testdir):
+ testdir.makeconftest("""
+ class DontTouchMe(object):
+ def __getattr__(self, x):
+ raise Exception('cant touch me')
+
+ x = DontTouchMe()
+ """)
+ testdir.makepyfile("""
+ def test_some():
+ pass
+ """)
+ res = testdir.runpytest()
+ assert res.ret == 0
+
+
+def test_conftest_exception_handling(testdir):
+ testdir.makeconftest('''
+ raise ValueError()
+ ''')
+ testdir.makepyfile("""
+ def test_some():
+ pass
+ """)
+ res = testdir.runpytest()
+ assert res.ret == 4
+ assert 'raise ValueError()' in [line.strip() for line in res.errlines]
+
+
+def test_hook_proxy(testdir):
+ """Session's gethookproxy() would cache conftests incorrectly (#2016).
+ It was decided to remove the cache altogether.
+ """
+ testdir.makepyfile(**{
+ 'root/demo-0/test_foo1.py': "def test1(): pass",
+
+ 'root/demo-a/test_foo2.py': "def test1(): pass",
+ 'root/demo-a/conftest.py': """
+ def pytest_ignore_collect(path, config):
+ return True
+ """,
+
+ 'root/demo-b/test_foo3.py': "def test1(): pass",
+ 'root/demo-c/test_foo4.py': "def test1(): pass",
+ })
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ '*test_foo1.py*',
+ '*test_foo3.py*',
+ '*test_foo4.py*',
+ '*3 passed*',
+ ])
+
+
+def test_required_option_help(testdir):
+ testdir.makeconftest("assert 0")
+ x = testdir.mkdir("x")
+ x.join("conftest.py").write(_pytest._code.Source("""
+ def pytest_addoption(parser):
+ parser.addoption("--xyz", action="store_true", required=True)
+ """))
+ result = testdir.runpytest("-h", x)
+ assert 'argument --xyz is required' not in result.stdout.str()
+ assert 'general:' in result.stdout.str()
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_doctest.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_doctest.py
new file mode 100644
index 00000000000..b15067f15e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_doctest.py
@@ -0,0 +1,1003 @@
+# encoding: utf-8
+from __future__ import absolute_import, division, print_function
+import sys
+import _pytest._code
+from _pytest.compat import MODULE_NOT_FOUND_ERROR
+from _pytest.doctest import DoctestItem, DoctestModule, DoctestTextfile
+import pytest
+
+
+class TestDoctests(object):
+
+ def test_collect_testtextfile(self, testdir):
+ w = testdir.maketxtfile(whatever="")
+ checkfile = testdir.maketxtfile(test_something="""
+ alskdjalsdk
+ >>> i = 5
+ >>> i-1
+ 4
+ """)
+
+ for x in (testdir.tmpdir, checkfile):
+ # print "checking that %s returns custom items" % (x,)
+ items, reprec = testdir.inline_genitems(x)
+ assert len(items) == 1
+ assert isinstance(items[0], DoctestItem)
+ assert isinstance(items[0].parent, DoctestTextfile)
+ # Empty file has no items.
+ items, reprec = testdir.inline_genitems(w)
+ assert len(items) == 0
+
+ def test_collect_module_empty(self, testdir):
+ path = testdir.makepyfile(whatever="#")
+ for p in (path, testdir.tmpdir):
+ items, reprec = testdir.inline_genitems(p,
+ '--doctest-modules')
+ assert len(items) == 0
+
+ def test_collect_module_single_modulelevel_doctest(self, testdir):
+ path = testdir.makepyfile(whatever='""">>> pass"""')
+ for p in (path, testdir.tmpdir):
+ items, reprec = testdir.inline_genitems(p,
+ '--doctest-modules')
+ assert len(items) == 1
+ assert isinstance(items[0], DoctestItem)
+ assert isinstance(items[0].parent, DoctestModule)
+
+ def test_collect_module_two_doctest_one_modulelevel(self, testdir):
+ path = testdir.makepyfile(whatever="""
+ '>>> x = None'
+ def my_func():
+ ">>> magic = 42 "
+ """)
+ for p in (path, testdir.tmpdir):
+ items, reprec = testdir.inline_genitems(p,
+ '--doctest-modules')
+ assert len(items) == 2
+ assert isinstance(items[0], DoctestItem)
+ assert isinstance(items[1], DoctestItem)
+ assert isinstance(items[0].parent, DoctestModule)
+ assert items[0].parent is items[1].parent
+
+ def test_collect_module_two_doctest_no_modulelevel(self, testdir):
+ path = testdir.makepyfile(whatever="""
+ '# Empty'
+ def my_func():
+ ">>> magic = 42 "
+ def unuseful():
+ '''
+ # This is a function
+ # >>> # it doesn't have any doctest
+ '''
+ def another():
+ '''
+ # This is another function
+ >>> import os # this one does have a doctest
+ '''
+ """)
+ for p in (path, testdir.tmpdir):
+ items, reprec = testdir.inline_genitems(p,
+ '--doctest-modules')
+ assert len(items) == 2
+ assert isinstance(items[0], DoctestItem)
+ assert isinstance(items[1], DoctestItem)
+ assert isinstance(items[0].parent, DoctestModule)
+ assert items[0].parent is items[1].parent
+
+ def test_simple_doctestfile(self, testdir):
+ p = testdir.maketxtfile(test_doc="""
+ >>> x = 1
+ >>> x == 1
+ False
+ """)
+ reprec = testdir.inline_run(p, )
+ reprec.assertoutcome(failed=1)
+
+ def test_new_pattern(self, testdir):
+ p = testdir.maketxtfile(xdoc="""
+ >>> x = 1
+ >>> x == 1
+ False
+ """)
+ reprec = testdir.inline_run(p, "--doctest-glob=x*.txt")
+ reprec.assertoutcome(failed=1)
+
+ def test_multiple_patterns(self, testdir):
+ """Test support for multiple --doctest-glob arguments (#1255).
+ """
+ testdir.maketxtfile(xdoc="""
+ >>> 1
+ 1
+ """)
+ testdir.makefile('.foo', test="""
+ >>> 1
+ 1
+ """)
+ testdir.maketxtfile(test_normal="""
+ >>> 1
+ 1
+ """)
+ expected = set(['xdoc.txt', 'test.foo', 'test_normal.txt'])
+ assert set(x.basename for x in testdir.tmpdir.listdir()) == expected
+ args = ["--doctest-glob=xdoc*.txt", "--doctest-glob=*.foo"]
+ result = testdir.runpytest(*args)
+ result.stdout.fnmatch_lines([
+ '*test.foo *',
+ '*xdoc.txt *',
+ '*2 passed*',
+ ])
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ '*test_normal.txt *',
+ '*1 passed*',
+ ])
+
+ @pytest.mark.parametrize(
+ ' test_string, encoding',
+ [
+ (u'foo', 'ascii'),
+ (u'öäü', 'latin1'),
+ (u'öäü', 'utf-8')
+ ]
+ )
+ def test_encoding(self, testdir, test_string, encoding):
+ """Test support for doctest_encoding ini option.
+ """
+ testdir.makeini("""
+ [pytest]
+ doctest_encoding={0}
+ """.format(encoding))
+ doctest = u"""
+ >>> u"{0}"
+ {1}
+ """.format(test_string, repr(test_string))
+ testdir._makefile(".txt", [doctest], {}, encoding=encoding)
+
+ result = testdir.runpytest()
+
+ result.stdout.fnmatch_lines([
+ '*1 passed*',
+ ])
+
+ def test_doctest_unexpected_exception(self, testdir):
+ testdir.maketxtfile("""
+ >>> i = 0
+ >>> 0 / i
+ 2
+ """)
+ result = testdir.runpytest("--doctest-modules")
+ result.stdout.fnmatch_lines([
+ "*unexpected_exception*",
+ "*>>> i = 0*",
+ "*>>> 0 / i*",
+ "*UNEXPECTED*ZeroDivision*",
+ ])
+
+ def test_docstring_partial_context_around_error(self, testdir):
+ """Test that we show some context before the actual line of a failing
+ doctest.
+ """
+ testdir.makepyfile('''
+ def foo():
+ """
+ text-line-1
+ text-line-2
+ text-line-3
+ text-line-4
+ text-line-5
+ text-line-6
+ text-line-7
+ text-line-8
+ text-line-9
+ text-line-10
+ text-line-11
+ >>> 1 + 1
+ 3
+
+ text-line-after
+ """
+ ''')
+ result = testdir.runpytest('--doctest-modules')
+ result.stdout.fnmatch_lines([
+ '*docstring_partial_context_around_error*',
+ '005*text-line-3',
+ '006*text-line-4',
+ '013*text-line-11',
+ '014*>>> 1 + 1',
+ 'Expected:',
+ ' 3',
+ 'Got:',
+ ' 2',
+ ])
+ # lines below should be trimmed out
+ assert 'text-line-2' not in result.stdout.str()
+ assert 'text-line-after' not in result.stdout.str()
+
+ def test_docstring_full_context_around_error(self, testdir):
+ """Test that we show the whole context before the actual line of a failing
+ doctest, provided that the context is up to 10 lines long.
+ """
+ testdir.makepyfile('''
+ def foo():
+ """
+ text-line-1
+ text-line-2
+
+ >>> 1 + 1
+ 3
+ """
+ ''')
+ result = testdir.runpytest('--doctest-modules')
+ result.stdout.fnmatch_lines([
+ '*docstring_full_context_around_error*',
+ '003*text-line-1',
+ '004*text-line-2',
+ '006*>>> 1 + 1',
+ 'Expected:',
+ ' 3',
+ 'Got:',
+ ' 2',
+ ])
+
+ def test_doctest_linedata_missing(self, testdir):
+ testdir.tmpdir.join('hello.py').write(_pytest._code.Source("""
+ class Fun(object):
+ @property
+ def test(self):
+ '''
+ >>> a = 1
+ >>> 1/0
+ '''
+ """))
+ result = testdir.runpytest("--doctest-modules")
+ result.stdout.fnmatch_lines([
+ "*hello*",
+ "*EXAMPLE LOCATION UNKNOWN, not showing all tests of that example*",
+ "*1/0*",
+ "*UNEXPECTED*ZeroDivision*",
+ "*1 failed*",
+ ])
+
+ def test_doctest_unex_importerror_only_txt(self, testdir):
+ testdir.maketxtfile("""
+ >>> import asdalsdkjaslkdjasd
+ >>>
+ """)
+ result = testdir.runpytest()
+ # doctest is never executed because of error during hello.py collection
+ result.stdout.fnmatch_lines([
+ "*>>> import asdals*",
+ "*UNEXPECTED*{e}*".format(e=MODULE_NOT_FOUND_ERROR),
+ "{e}: No module named *asdal*".format(e=MODULE_NOT_FOUND_ERROR),
+ ])
+
+ def test_doctest_unex_importerror_with_module(self, testdir):
+ testdir.tmpdir.join("hello.py").write(_pytest._code.Source("""
+ import asdalsdkjaslkdjasd
+ """))
+ testdir.maketxtfile("""
+ >>> import hello
+ >>>
+ """)
+ result = testdir.runpytest("--doctest-modules")
+ # doctest is never executed because of error during hello.py collection
+ result.stdout.fnmatch_lines([
+ "*ERROR collecting hello.py*",
+ "*{e}: No module named *asdals*".format(e=MODULE_NOT_FOUND_ERROR),
+ "*Interrupted: 1 errors during collection*",
+ ])
+
+ def test_doctestmodule(self, testdir):
+ p = testdir.makepyfile("""
+ '''
+ >>> x = 1
+ >>> x == 1
+ False
+
+ '''
+ """)
+ reprec = testdir.inline_run(p, "--doctest-modules")
+ reprec.assertoutcome(failed=1)
+
+ def test_doctestmodule_external_and_issue116(self, testdir):
+ p = testdir.mkpydir("hello")
+ p.join("__init__.py").write(_pytest._code.Source("""
+ def somefunc():
+ '''
+ >>> i = 0
+ >>> i + 1
+ 2
+ '''
+ """))
+ result = testdir.runpytest(p, "--doctest-modules")
+ result.stdout.fnmatch_lines([
+ '004 *>>> i = 0',
+ '005 *>>> i + 1',
+ '*Expected:',
+ "* 2",
+ "*Got:",
+ "* 1",
+ "*:5: DocTestFailure"
+ ])
+
+ def test_txtfile_failing(self, testdir):
+ p = testdir.maketxtfile("""
+ >>> i = 0
+ >>> i + 1
+ 2
+ """)
+ result = testdir.runpytest(p, "-s")
+ result.stdout.fnmatch_lines([
+ '001 >>> i = 0',
+ '002 >>> i + 1',
+ 'Expected:',
+ " 2",
+ "Got:",
+ " 1",
+ "*test_txtfile_failing.txt:2: DocTestFailure"
+ ])
+
+ def test_txtfile_with_fixtures(self, testdir):
+ p = testdir.maketxtfile("""
+ >>> dir = getfixture('tmpdir')
+ >>> type(dir).__name__
+ 'LocalPath'
+ """)
+ reprec = testdir.inline_run(p, )
+ reprec.assertoutcome(passed=1)
+
+ def test_txtfile_with_usefixtures_in_ini(self, testdir):
+ testdir.makeini("""
+ [pytest]
+ usefixtures = myfixture
+ """)
+ testdir.makeconftest("""
+ import pytest
+ @pytest.fixture
+ def myfixture(monkeypatch):
+ monkeypatch.setenv("HELLO", "WORLD")
+ """)
+
+ p = testdir.maketxtfile("""
+ >>> import os
+ >>> os.environ["HELLO"]
+ 'WORLD'
+ """)
+ reprec = testdir.inline_run(p, )
+ reprec.assertoutcome(passed=1)
+
+ def test_doctestmodule_with_fixtures(self, testdir):
+ p = testdir.makepyfile("""
+ '''
+ >>> dir = getfixture('tmpdir')
+ >>> type(dir).__name__
+ 'LocalPath'
+ '''
+ """)
+ reprec = testdir.inline_run(p, "--doctest-modules")
+ reprec.assertoutcome(passed=1)
+
+ def test_doctestmodule_three_tests(self, testdir):
+ p = testdir.makepyfile("""
+ '''
+ >>> dir = getfixture('tmpdir')
+ >>> type(dir).__name__
+ 'LocalPath'
+ '''
+ def my_func():
+ '''
+ >>> magic = 42
+ >>> magic - 42
+ 0
+ '''
+ def unuseful():
+ pass
+ def another():
+ '''
+ >>> import os
+ >>> os is os
+ True
+ '''
+ """)
+ reprec = testdir.inline_run(p, "--doctest-modules")
+ reprec.assertoutcome(passed=3)
+
+ def test_doctestmodule_two_tests_one_fail(self, testdir):
+ p = testdir.makepyfile("""
+ class MyClass(object):
+ def bad_meth(self):
+ '''
+ >>> magic = 42
+ >>> magic
+ 0
+ '''
+ def nice_meth(self):
+ '''
+ >>> magic = 42
+ >>> magic - 42
+ 0
+ '''
+ """)
+ reprec = testdir.inline_run(p, "--doctest-modules")
+ reprec.assertoutcome(failed=1, passed=1)
+
+ def test_ignored_whitespace(self, testdir):
+ testdir.makeini("""
+ [pytest]
+ doctest_optionflags = ELLIPSIS NORMALIZE_WHITESPACE
+ """)
+ p = testdir.makepyfile("""
+ class MyClass(object):
+ '''
+ >>> a = "foo "
+ >>> print(a)
+ foo
+ '''
+ pass
+ """)
+ reprec = testdir.inline_run(p, "--doctest-modules")
+ reprec.assertoutcome(passed=1)
+
+ def test_non_ignored_whitespace(self, testdir):
+ testdir.makeini("""
+ [pytest]
+ doctest_optionflags = ELLIPSIS
+ """)
+ p = testdir.makepyfile("""
+ class MyClass(object):
+ '''
+ >>> a = "foo "
+ >>> print(a)
+ foo
+ '''
+ pass
+ """)
+ reprec = testdir.inline_run(p, "--doctest-modules")
+ reprec.assertoutcome(failed=1, passed=0)
+
+ def test_ignored_whitespace_glob(self, testdir):
+ testdir.makeini("""
+ [pytest]
+ doctest_optionflags = ELLIPSIS NORMALIZE_WHITESPACE
+ """)
+ p = testdir.maketxtfile(xdoc="""
+ >>> a = "foo "
+ >>> print(a)
+ foo
+ """)
+ reprec = testdir.inline_run(p, "--doctest-glob=x*.txt")
+ reprec.assertoutcome(passed=1)
+
+ def test_non_ignored_whitespace_glob(self, testdir):
+ testdir.makeini("""
+ [pytest]
+ doctest_optionflags = ELLIPSIS
+ """)
+ p = testdir.maketxtfile(xdoc="""
+ >>> a = "foo "
+ >>> print(a)
+ foo
+ """)
+ reprec = testdir.inline_run(p, "--doctest-glob=x*.txt")
+ reprec.assertoutcome(failed=1, passed=0)
+
+ def test_contains_unicode(self, testdir):
+ """Fix internal error with docstrings containing non-ascii characters.
+ """
+ testdir.makepyfile(u'''
+ # encoding: utf-8
+ def foo():
+ """
+ >>> name = 'с' # not letter 'c' but instead Cyrillic 's'.
+ 'anything'
+ """
+ ''')
+ result = testdir.runpytest('--doctest-modules')
+ result.stdout.fnmatch_lines([
+ 'Got nothing',
+ '* 1 failed in*',
+ ])
+
+ def test_ignore_import_errors_on_doctest(self, testdir):
+ p = testdir.makepyfile("""
+ import asdf
+
+ def add_one(x):
+ '''
+ >>> add_one(1)
+ 2
+ '''
+ return x + 1
+ """)
+
+ reprec = testdir.inline_run(p, "--doctest-modules",
+ "--doctest-ignore-import-errors")
+ reprec.assertoutcome(skipped=1, failed=1, passed=0)
+
+ def test_junit_report_for_doctest(self, testdir):
+ """
+ #713: Fix --junit-xml option when used with --doctest-modules.
+ """
+ p = testdir.makepyfile("""
+ def foo():
+ '''
+ >>> 1 + 1
+ 3
+ '''
+ pass
+ """)
+ reprec = testdir.inline_run(p, "--doctest-modules",
+ "--junit-xml=junit.xml")
+ reprec.assertoutcome(failed=1)
+
+ def test_unicode_doctest(self, testdir):
+ """
+ Test case for issue 2434: DecodeError on Python 2 when doctest contains non-ascii
+ characters.
+ """
+ p = testdir.maketxtfile(test_unicode_doctest="""
+ .. doctest::
+
+ >>> print(
+ ... "Hi\\n\\nByé")
+ Hi
+ ...
+ Byé
+ >>> 1/0 # Byé
+ 1
+ """)
+ result = testdir.runpytest(p)
+ result.stdout.fnmatch_lines([
+ '*UNEXPECTED EXCEPTION: ZeroDivisionError*',
+ '*1 failed*',
+ ])
+
+ def test_unicode_doctest_module(self, testdir):
+ """
+ Test case for issue 2434: DecodeError on Python 2 when doctest docstring
+ contains non-ascii characters.
+ """
+ p = testdir.makepyfile(test_unicode_doctest_module="""
+ # -*- encoding: utf-8 -*-
+ from __future__ import unicode_literals
+
+ def fix_bad_unicode(text):
+ '''
+ >>> print(fix_bad_unicode('único'))
+ único
+ '''
+ return "único"
+ """)
+ result = testdir.runpytest(p, '--doctest-modules')
+ result.stdout.fnmatch_lines(['* 1 passed *'])
+
+ def test_reportinfo(self, testdir):
+ '''
+ Test case to make sure that DoctestItem.reportinfo() returns lineno.
+ '''
+ p = testdir.makepyfile(test_reportinfo="""
+ def foo(x):
+ '''
+ >>> foo('a')
+ 'b'
+ '''
+ return 'c'
+ """)
+ items, reprec = testdir.inline_genitems(p, '--doctest-modules')
+ reportinfo = items[0].reportinfo()
+ assert reportinfo[1] == 1
+
+ def test_valid_setup_py(self, testdir):
+ '''
+ Test to make sure that pytest ignores valid setup.py files when ran
+ with --doctest-modules
+ '''
+ p = testdir.makepyfile(setup="""
+ from setuptools import setup, find_packages
+ setup(name='sample',
+ version='0.0',
+ description='description',
+ packages=find_packages()
+ )
+ """)
+ result = testdir.runpytest(p, '--doctest-modules')
+ result.stdout.fnmatch_lines(['*collected 0 items*'])
+
+ def test_invalid_setup_py(self, testdir):
+ '''
+ Test to make sure that pytest reads setup.py files that are not used
+ for python packages when ran with --doctest-modules
+ '''
+ p = testdir.makepyfile(setup="""
+ def test_foo():
+ return 'bar'
+ """)
+ result = testdir.runpytest(p, '--doctest-modules')
+ result.stdout.fnmatch_lines(['*collected 1 item*'])
+
+
+class TestLiterals(object):
+
+ @pytest.mark.parametrize('config_mode', ['ini', 'comment'])
+ def test_allow_unicode(self, testdir, config_mode):
+ """Test that doctests which output unicode work in all python versions
+ tested by pytest when the ALLOW_UNICODE option is used (either in
+ the ini file or by an inline comment).
+ """
+ if config_mode == 'ini':
+ testdir.makeini('''
+ [pytest]
+ doctest_optionflags = ALLOW_UNICODE
+ ''')
+ comment = ''
+ else:
+ comment = '#doctest: +ALLOW_UNICODE'
+
+ testdir.maketxtfile(test_doc="""
+ >>> b'12'.decode('ascii') {comment}
+ '12'
+ """.format(comment=comment))
+ testdir.makepyfile(foo="""
+ def foo():
+ '''
+ >>> b'12'.decode('ascii') {comment}
+ '12'
+ '''
+ """.format(comment=comment))
+ reprec = testdir.inline_run("--doctest-modules")
+ reprec.assertoutcome(passed=2)
+
+ @pytest.mark.parametrize('config_mode', ['ini', 'comment'])
+ def test_allow_bytes(self, testdir, config_mode):
+ """Test that doctests which output bytes work in all python versions
+ tested by pytest when the ALLOW_BYTES option is used (either in
+ the ini file or by an inline comment)(#1287).
+ """
+ if config_mode == 'ini':
+ testdir.makeini('''
+ [pytest]
+ doctest_optionflags = ALLOW_BYTES
+ ''')
+ comment = ''
+ else:
+ comment = '#doctest: +ALLOW_BYTES'
+
+ testdir.maketxtfile(test_doc="""
+ >>> b'foo' {comment}
+ 'foo'
+ """.format(comment=comment))
+ testdir.makepyfile(foo="""
+ def foo():
+ '''
+ >>> b'foo' {comment}
+ 'foo'
+ '''
+ """.format(comment=comment))
+ reprec = testdir.inline_run("--doctest-modules")
+ reprec.assertoutcome(passed=2)
+
+ def test_unicode_string(self, testdir):
+ """Test that doctests which output unicode fail in Python 2 when
+ the ALLOW_UNICODE option is not used. The same test should pass
+ in Python 3.
+ """
+ testdir.maketxtfile(test_doc="""
+ >>> b'12'.decode('ascii')
+ '12'
+ """)
+ reprec = testdir.inline_run()
+ passed = int(sys.version_info[0] >= 3)
+ reprec.assertoutcome(passed=passed, failed=int(not passed))
+
+ def test_bytes_literal(self, testdir):
+ """Test that doctests which output bytes fail in Python 3 when
+ the ALLOW_BYTES option is not used. The same test should pass
+ in Python 2 (#1287).
+ """
+ testdir.maketxtfile(test_doc="""
+ >>> b'foo'
+ 'foo'
+ """)
+ reprec = testdir.inline_run()
+ passed = int(sys.version_info[0] == 2)
+ reprec.assertoutcome(passed=passed, failed=int(not passed))
+
+
+class TestDoctestSkips(object):
+ """
+ If all examples in a doctest are skipped due to the SKIP option, then
+ the tests should be SKIPPED rather than PASSED. (#957)
+ """
+
+ @pytest.fixture(params=['text', 'module'])
+ def makedoctest(self, testdir, request):
+ def makeit(doctest):
+ mode = request.param
+ if mode == 'text':
+ testdir.maketxtfile(doctest)
+ else:
+ assert mode == 'module'
+ testdir.makepyfile('"""\n%s"""' % doctest)
+
+ return makeit
+
+ def test_one_skipped(self, testdir, makedoctest):
+ makedoctest("""
+ >>> 1 + 1 # doctest: +SKIP
+ 2
+ >>> 2 + 2
+ 4
+ """)
+ reprec = testdir.inline_run("--doctest-modules")
+ reprec.assertoutcome(passed=1)
+
+ def test_one_skipped_failed(self, testdir, makedoctest):
+ makedoctest("""
+ >>> 1 + 1 # doctest: +SKIP
+ 2
+ >>> 2 + 2
+ 200
+ """)
+ reprec = testdir.inline_run("--doctest-modules")
+ reprec.assertoutcome(failed=1)
+
+ def test_all_skipped(self, testdir, makedoctest):
+ makedoctest("""
+ >>> 1 + 1 # doctest: +SKIP
+ 2
+ >>> 2 + 2 # doctest: +SKIP
+ 200
+ """)
+ reprec = testdir.inline_run("--doctest-modules")
+ reprec.assertoutcome(skipped=1)
+
+ def test_vacuous_all_skipped(self, testdir, makedoctest):
+ makedoctest('')
+ reprec = testdir.inline_run("--doctest-modules")
+ reprec.assertoutcome(passed=0, skipped=0)
+
+
+class TestDoctestAutoUseFixtures(object):
+
+ SCOPES = ['module', 'session', 'class', 'function']
+
+ def test_doctest_module_session_fixture(self, testdir):
+ """Test that session fixtures are initialized for doctest modules (#768)
+ """
+ # session fixture which changes some global data, which will
+ # be accessed by doctests in a module
+ testdir.makeconftest("""
+ import pytest
+ import sys
+
+ @pytest.yield_fixture(autouse=True, scope='session')
+ def myfixture():
+ assert not hasattr(sys, 'pytest_session_data')
+ sys.pytest_session_data = 1
+ yield
+ del sys.pytest_session_data
+ """)
+ testdir.makepyfile(foo="""
+ import sys
+
+ def foo():
+ '''
+ >>> assert sys.pytest_session_data == 1
+ '''
+
+ def bar():
+ '''
+ >>> assert sys.pytest_session_data == 1
+ '''
+ """)
+ result = testdir.runpytest("--doctest-modules")
+ result.stdout.fnmatch_lines('*2 passed*')
+
+ @pytest.mark.parametrize('scope', SCOPES)
+ @pytest.mark.parametrize('enable_doctest', [True, False])
+ def test_fixture_scopes(self, testdir, scope, enable_doctest):
+ """Test that auto-use fixtures work properly with doctest modules.
+ See #1057 and #1100.
+ """
+ testdir.makeconftest('''
+ import pytest
+
+ @pytest.fixture(autouse=True, scope="{scope}")
+ def auto(request):
+ return 99
+ '''.format(scope=scope))
+ testdir.makepyfile(test_1='''
+ def test_foo():
+ """
+ >>> getfixture('auto') + 1
+ 100
+ """
+ def test_bar():
+ assert 1
+ ''')
+ params = ('--doctest-modules',) if enable_doctest else ()
+ passes = 3 if enable_doctest else 2
+ result = testdir.runpytest(*params)
+ result.stdout.fnmatch_lines(['*=== %d passed in *' % passes])
+
+ @pytest.mark.parametrize('scope', SCOPES)
+ @pytest.mark.parametrize('autouse', [True, False])
+ @pytest.mark.parametrize('use_fixture_in_doctest', [True, False])
+ def test_fixture_module_doctest_scopes(self, testdir, scope, autouse,
+ use_fixture_in_doctest):
+ """Test that auto-use fixtures work properly with doctest files.
+ See #1057 and #1100.
+ """
+ testdir.makeconftest('''
+ import pytest
+
+ @pytest.fixture(autouse={autouse}, scope="{scope}")
+ def auto(request):
+ return 99
+ '''.format(scope=scope, autouse=autouse))
+ if use_fixture_in_doctest:
+ testdir.maketxtfile(test_doc="""
+ >>> getfixture('auto')
+ 99
+ """)
+ else:
+ testdir.maketxtfile(test_doc="""
+ >>> 1 + 1
+ 2
+ """)
+ result = testdir.runpytest('--doctest-modules')
+ assert 'FAILURES' not in str(result.stdout.str())
+ result.stdout.fnmatch_lines(['*=== 1 passed in *'])
+
+ @pytest.mark.parametrize('scope', SCOPES)
+ def test_auto_use_request_attributes(self, testdir, scope):
+ """Check that all attributes of a request in an autouse fixture
+ behave as expected when requested for a doctest item.
+ """
+ testdir.makeconftest('''
+ import pytest
+
+ @pytest.fixture(autouse=True, scope="{scope}")
+ def auto(request):
+ if "{scope}" == 'module':
+ assert request.module is None
+ if "{scope}" == 'class':
+ assert request.cls is None
+ if "{scope}" == 'function':
+ assert request.function is None
+ return 99
+ '''.format(scope=scope))
+ testdir.maketxtfile(test_doc="""
+ >>> 1 + 1
+ 2
+ """)
+ result = testdir.runpytest('--doctest-modules')
+ assert 'FAILURES' not in str(result.stdout.str())
+ result.stdout.fnmatch_lines(['*=== 1 passed in *'])
+
+
+class TestDoctestNamespaceFixture(object):
+
+ SCOPES = ['module', 'session', 'class', 'function']
+
+ @pytest.mark.parametrize('scope', SCOPES)
+ def test_namespace_doctestfile(self, testdir, scope):
+ """
+ Check that inserting something into the namespace works in a
+ simple text file doctest
+ """
+ testdir.makeconftest("""
+ import pytest
+ import contextlib
+
+ @pytest.fixture(autouse=True, scope="{scope}")
+ def add_contextlib(doctest_namespace):
+ doctest_namespace['cl'] = contextlib
+ """.format(scope=scope))
+ p = testdir.maketxtfile("""
+ >>> print(cl.__name__)
+ contextlib
+ """)
+ reprec = testdir.inline_run(p)
+ reprec.assertoutcome(passed=1)
+
+ @pytest.mark.parametrize('scope', SCOPES)
+ def test_namespace_pyfile(self, testdir, scope):
+ """
+ Check that inserting something into the namespace works in a
+ simple Python file docstring doctest
+ """
+ testdir.makeconftest("""
+ import pytest
+ import contextlib
+
+ @pytest.fixture(autouse=True, scope="{scope}")
+ def add_contextlib(doctest_namespace):
+ doctest_namespace['cl'] = contextlib
+ """.format(scope=scope))
+ p = testdir.makepyfile("""
+ def foo():
+ '''
+ >>> print(cl.__name__)
+ contextlib
+ '''
+ """)
+ reprec = testdir.inline_run(p, "--doctest-modules")
+ reprec.assertoutcome(passed=1)
+
+
+class TestDoctestReportingOption(object):
+ def _run_doctest_report(self, testdir, format):
+ testdir.makepyfile("""
+ def foo():
+ '''
+ >>> foo()
+ a b
+ 0 1 4
+ 1 2 4
+ 2 3 6
+ '''
+ print(' a b\\n'
+ '0 1 4\\n'
+ '1 2 5\\n'
+ '2 3 6')
+ """)
+ return testdir.runpytest("--doctest-modules", "--doctest-report", format)
+
+ @pytest.mark.parametrize('format', ['udiff', 'UDIFF', 'uDiFf'])
+ def test_doctest_report_udiff(self, testdir, format):
+ result = self._run_doctest_report(testdir, format)
+ result.stdout.fnmatch_lines([
+ ' 0 1 4',
+ ' -1 2 4',
+ ' +1 2 5',
+ ' 2 3 6',
+ ])
+
+ def test_doctest_report_cdiff(self, testdir):
+ result = self._run_doctest_report(testdir, 'cdiff')
+ result.stdout.fnmatch_lines([
+ ' a b',
+ ' 0 1 4',
+ ' ! 1 2 4',
+ ' 2 3 6',
+ ' --- 1,4 ----',
+ ' a b',
+ ' 0 1 4',
+ ' ! 1 2 5',
+ ' 2 3 6',
+ ])
+
+ def test_doctest_report_ndiff(self, testdir):
+ result = self._run_doctest_report(testdir, 'ndiff')
+ result.stdout.fnmatch_lines([
+ ' a b',
+ ' 0 1 4',
+ ' - 1 2 4',
+ ' ? ^',
+ ' + 1 2 5',
+ ' ? ^',
+ ' 2 3 6',
+ ])
+
+ @pytest.mark.parametrize('format', ['none', 'only_first_failure'])
+ def test_doctest_report_none_or_only_first_failure(self, testdir, format):
+ result = self._run_doctest_report(testdir, format)
+ result.stdout.fnmatch_lines([
+ 'Expected:',
+ ' a b',
+ ' 0 1 4',
+ ' 1 2 4',
+ ' 2 3 6',
+ 'Got:',
+ ' a b',
+ ' 0 1 4',
+ ' 1 2 5',
+ ' 2 3 6',
+ ])
+
+ def test_doctest_report_invalid(self, testdir):
+ result = self._run_doctest_report(testdir, 'obviously_invalid_format')
+ result.stderr.fnmatch_lines([
+ "*error: argument --doctest-report: invalid choice: 'obviously_invalid_format' (choose from*"
+ ])
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_entry_points.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_entry_points.py
new file mode 100644
index 00000000000..6ca68b481fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_entry_points.py
@@ -0,0 +1,14 @@
+from __future__ import absolute_import, division, print_function
+import pkg_resources
+
+import pytest
+
+
+@pytest.mark.parametrize("entrypoint", ['py.test', 'pytest'])
+def test_entry_point_exist(entrypoint):
+ assert entrypoint in pkg_resources.get_entry_map('pytest')['console_scripts']
+
+
+def test_pytest_entry_points_are_identical():
+ entryMap = pkg_resources.get_entry_map('pytest')['console_scripts']
+ assert entryMap['pytest'].module_name == entryMap['py.test'].module_name
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_helpconfig.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_helpconfig.py
new file mode 100644
index 00000000000..845005a0575
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_helpconfig.py
@@ -0,0 +1,77 @@
+from __future__ import absolute_import, division, print_function
+from _pytest.main import EXIT_NOTESTSCOLLECTED
+import pytest
+
+
+def test_version(testdir, pytestconfig):
+ result = testdir.runpytest("--version")
+ assert result.ret == 0
+ # p = py.path.local(py.__file__).dirpath()
+ result.stderr.fnmatch_lines([
+ '*pytest*%s*imported from*' % (pytest.__version__, )
+ ])
+ if pytestconfig.pluginmanager.list_plugin_distinfo():
+ result.stderr.fnmatch_lines([
+ "*setuptools registered plugins:",
+ "*at*",
+ ])
+
+
+def test_help(testdir):
+ result = testdir.runpytest("--help")
+ assert result.ret == 0
+ result.stdout.fnmatch_lines("""
+ *-v*verbose*
+ *setup.cfg*
+ *minversion*
+ *to see*markers*pytest --markers*
+ *to see*fixtures*pytest --fixtures*
+ """)
+
+
+def test_hookvalidation_unknown(testdir):
+ testdir.makeconftest("""
+ def pytest_hello(xyz):
+ pass
+ """)
+ result = testdir.runpytest()
+ assert result.ret != 0
+ result.stdout.fnmatch_lines([
+ '*unknown hook*pytest_hello*'
+ ])
+
+
+def test_hookvalidation_optional(testdir):
+ testdir.makeconftest("""
+ import pytest
+ @pytest.hookimpl(optionalhook=True)
+ def pytest_hello(xyz):
+ pass
+ """)
+ result = testdir.runpytest()
+ assert result.ret == EXIT_NOTESTSCOLLECTED
+
+
+def test_traceconfig(testdir):
+ result = testdir.runpytest("--traceconfig")
+ result.stdout.fnmatch_lines([
+ "*using*pytest*py*",
+ "*active plugins*",
+ ])
+
+
+def test_debug(testdir, monkeypatch):
+ result = testdir.runpytest_subprocess("--debug")
+ assert result.ret == EXIT_NOTESTSCOLLECTED
+ p = testdir.tmpdir.join("pytestdebug.log")
+ assert "pytest_sessionstart" in p.read()
+
+
+def test_PYTEST_DEBUG(testdir, monkeypatch):
+ monkeypatch.setenv("PYTEST_DEBUG", "1")
+ result = testdir.runpytest_subprocess()
+ assert result.ret == EXIT_NOTESTSCOLLECTED
+ result.stderr.fnmatch_lines([
+ "*pytest_plugin_registered*",
+ "*manager*PluginManager*"
+ ])
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_junitxml.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_junitxml.py
new file mode 100644
index 00000000000..b604c02a3de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_junitxml.py
@@ -0,0 +1,1062 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import, division, print_function
+from xml.dom import minidom
+import py
+import sys
+import os
+from _pytest.junitxml import LogXML
+import pytest
+
+
+def runandparse(testdir, *args):
+ resultpath = testdir.tmpdir.join("junit.xml")
+ result = testdir.runpytest("--junitxml=%s" % resultpath, *args)
+ xmldoc = minidom.parse(str(resultpath))
+ return result, DomNode(xmldoc)
+
+
+def assert_attr(node, **kwargs):
+ __tracebackhide__ = True
+
+ def nodeval(node, name):
+ anode = node.getAttributeNode(name)
+ if anode is not None:
+ return anode.value
+
+ expected = dict((name, str(value)) for name, value in kwargs.items())
+ on_node = dict((name, nodeval(node, name)) for name in expected)
+ assert on_node == expected
+
+
+class DomNode(object):
+ def __init__(self, dom):
+ self.__node = dom
+
+ def __repr__(self):
+ return self.__node.toxml()
+
+ def find_first_by_tag(self, tag):
+ return self.find_nth_by_tag(tag, 0)
+
+ def _by_tag(self, tag):
+ return self.__node.getElementsByTagName(tag)
+
+ def find_nth_by_tag(self, tag, n):
+ items = self._by_tag(tag)
+ try:
+ nth = items[n]
+ except IndexError:
+ pass
+ else:
+ return type(self)(nth)
+
+ def find_by_tag(self, tag):
+ t = type(self)
+ return [t(x) for x in self.__node.getElementsByTagName(tag)]
+
+ def __getitem__(self, key):
+ node = self.__node.getAttributeNode(key)
+ if node is not None:
+ return node.value
+
+ def assert_attr(self, **kwargs):
+ __tracebackhide__ = True
+ return assert_attr(self.__node, **kwargs)
+
+ def toxml(self):
+ return self.__node.toxml()
+
+ @property
+ def text(self):
+ return self.__node.childNodes[0].wholeText
+
+ @property
+ def tag(self):
+ return self.__node.tagName
+
+ @property
+ def next_siebling(self):
+ return type(self)(self.__node.nextSibling)
+
+
+class TestPython(object):
+ def test_summing_simple(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ def test_pass():
+ pass
+ def test_fail():
+ assert 0
+ def test_skip():
+ pytest.skip("")
+ @pytest.mark.xfail
+ def test_xfail():
+ assert 0
+ @pytest.mark.xfail
+ def test_xpass():
+ assert 1
+ """)
+ result, dom = runandparse(testdir)
+ assert result.ret
+ node = dom.find_first_by_tag("testsuite")
+ node.assert_attr(name="pytest", errors=0, failures=1, skips=2, tests=5)
+
+ def test_summing_simple_with_errors(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture
+ def fixture():
+ raise Exception()
+ def test_pass():
+ pass
+ def test_fail():
+ assert 0
+ def test_error(fixture):
+ pass
+ @pytest.mark.xfail
+ def test_xfail():
+ assert False
+ @pytest.mark.xfail(strict=True)
+ def test_xpass():
+ assert True
+ """)
+ result, dom = runandparse(testdir)
+ assert result.ret
+ node = dom.find_first_by_tag("testsuite")
+ node.assert_attr(name="pytest", errors=1, failures=2, skips=1, tests=5)
+
+ def test_timing_function(self, testdir):
+ testdir.makepyfile("""
+ import time, pytest
+ def setup_module():
+ time.sleep(0.01)
+ def teardown_module():
+ time.sleep(0.01)
+ def test_sleep():
+ time.sleep(0.01)
+ """)
+ result, dom = runandparse(testdir)
+ node = dom.find_first_by_tag("testsuite")
+ tnode = node.find_first_by_tag("testcase")
+ val = tnode["time"]
+ assert round(float(val), 2) >= 0.03
+
+ def test_setup_error(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture
+ def arg(request):
+ raise ValueError()
+ def test_function(arg):
+ pass
+ """)
+ result, dom = runandparse(testdir)
+ assert result.ret
+ node = dom.find_first_by_tag("testsuite")
+ node.assert_attr(errors=1, tests=1)
+ tnode = node.find_first_by_tag("testcase")
+ tnode.assert_attr(
+ file="test_setup_error.py",
+ line="5",
+ classname="test_setup_error",
+ name="test_function")
+ fnode = tnode.find_first_by_tag("error")
+ fnode.assert_attr(message="test setup failure")
+ assert "ValueError" in fnode.toxml()
+
+ def test_teardown_error(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture
+ def arg():
+ yield
+ raise ValueError()
+ def test_function(arg):
+ pass
+ """)
+ result, dom = runandparse(testdir)
+ assert result.ret
+ node = dom.find_first_by_tag("testsuite")
+ tnode = node.find_first_by_tag("testcase")
+ tnode.assert_attr(
+ file="test_teardown_error.py",
+ line="6",
+ classname="test_teardown_error",
+ name="test_function")
+ fnode = tnode.find_first_by_tag("error")
+ fnode.assert_attr(message="test teardown failure")
+ assert "ValueError" in fnode.toxml()
+
+ def test_call_failure_teardown_error(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture
+ def arg():
+ yield
+ raise Exception("Teardown Exception")
+ def test_function(arg):
+ raise Exception("Call Exception")
+ """)
+ result, dom = runandparse(testdir)
+ assert result.ret
+ node = dom.find_first_by_tag("testsuite")
+ node.assert_attr(errors=1, failures=1, tests=1)
+ first, second = dom.find_by_tag("testcase")
+ if not first or not second or first == second:
+ assert 0
+ fnode = first.find_first_by_tag("failure")
+ fnode.assert_attr(message="Exception: Call Exception")
+ snode = second.find_first_by_tag("error")
+ snode.assert_attr(message="test teardown failure")
+
+ def test_skip_contains_name_reason(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ def test_skip():
+ pytest.skip("hello23")
+ """)
+ result, dom = runandparse(testdir)
+ assert result.ret == 0
+ node = dom.find_first_by_tag("testsuite")
+ node.assert_attr(skips=1)
+ tnode = node.find_first_by_tag("testcase")
+ tnode.assert_attr(
+ file="test_skip_contains_name_reason.py",
+ line="1",
+ classname="test_skip_contains_name_reason",
+ name="test_skip")
+ snode = tnode.find_first_by_tag("skipped")
+ snode.assert_attr(type="pytest.skip", message="hello23", )
+
+ def test_mark_skip_contains_name_reason(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.skip(reason="hello24")
+ def test_skip():
+ assert True
+ """)
+ result, dom = runandparse(testdir)
+ assert result.ret == 0
+ node = dom.find_first_by_tag("testsuite")
+ node.assert_attr(skips=1)
+ tnode = node.find_first_by_tag("testcase")
+ tnode.assert_attr(
+ file="test_mark_skip_contains_name_reason.py",
+ line="1",
+ classname="test_mark_skip_contains_name_reason",
+ name="test_skip")
+ snode = tnode.find_first_by_tag("skipped")
+ snode.assert_attr(type="pytest.skip", message="hello24", )
+
+ def test_mark_skipif_contains_name_reason(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ GLOBAL_CONDITION = True
+ @pytest.mark.skipif(GLOBAL_CONDITION, reason="hello25")
+ def test_skip():
+ assert True
+ """)
+ result, dom = runandparse(testdir)
+ assert result.ret == 0
+ node = dom.find_first_by_tag("testsuite")
+ node.assert_attr(skips=1)
+ tnode = node.find_first_by_tag("testcase")
+ tnode.assert_attr(
+ file="test_mark_skipif_contains_name_reason.py",
+ line="2",
+ classname="test_mark_skipif_contains_name_reason",
+ name="test_skip")
+ snode = tnode.find_first_by_tag("skipped")
+ snode.assert_attr(type="pytest.skip", message="hello25", )
+
+ def test_mark_skip_doesnt_capture_output(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.skip(reason="foo")
+ def test_skip():
+ print("bar!")
+ """)
+ result, dom = runandparse(testdir)
+ assert result.ret == 0
+ node_xml = dom.find_first_by_tag("testsuite").toxml()
+ assert "bar!" not in node_xml
+
+ def test_classname_instance(self, testdir):
+ testdir.makepyfile("""
+ class TestClass(object):
+ def test_method(self):
+ assert 0
+ """)
+ result, dom = runandparse(testdir)
+ assert result.ret
+ node = dom.find_first_by_tag("testsuite")
+ node.assert_attr(failures=1)
+ tnode = node.find_first_by_tag("testcase")
+ tnode.assert_attr(
+ file="test_classname_instance.py",
+ line="1",
+ classname="test_classname_instance.TestClass",
+ name="test_method")
+
+ def test_classname_nested_dir(self, testdir):
+ p = testdir.tmpdir.ensure("sub", "test_hello.py")
+ p.write("def test_func(): 0/0")
+ result, dom = runandparse(testdir)
+ assert result.ret
+ node = dom.find_first_by_tag("testsuite")
+ node.assert_attr(failures=1)
+ tnode = node.find_first_by_tag("testcase")
+ tnode.assert_attr(
+ file=os.path.join("sub", "test_hello.py"),
+ line="0",
+ classname="sub.test_hello",
+ name="test_func")
+
+ def test_internal_error(self, testdir):
+ testdir.makeconftest("def pytest_runtest_protocol(): 0 / 0")
+ testdir.makepyfile("def test_function(): pass")
+ result, dom = runandparse(testdir)
+ assert result.ret
+ node = dom.find_first_by_tag("testsuite")
+ node.assert_attr(errors=1, tests=1)
+ tnode = node.find_first_by_tag("testcase")
+ tnode.assert_attr(classname="pytest", name="internal")
+ fnode = tnode.find_first_by_tag("error")
+ fnode.assert_attr(message="internal error")
+ assert "Division" in fnode.toxml()
+
+ def test_failure_function(self, testdir):
+ testdir.makepyfile("""
+ import sys
+ def test_fail():
+ print ("hello-stdout")
+ sys.stderr.write("hello-stderr\\n")
+ raise ValueError(42)
+ """)
+
+ result, dom = runandparse(testdir)
+ assert result.ret
+ node = dom.find_first_by_tag("testsuite")
+ node.assert_attr(failures=1, tests=1)
+ tnode = node.find_first_by_tag("testcase")
+ tnode.assert_attr(
+ file="test_failure_function.py",
+ line="1",
+ classname="test_failure_function",
+ name="test_fail")
+ fnode = tnode.find_first_by_tag("failure")
+ fnode.assert_attr(message="ValueError: 42")
+ assert "ValueError" in fnode.toxml()
+ systemout = fnode.next_siebling
+ assert systemout.tag == "system-out"
+ assert "hello-stdout" in systemout.toxml()
+ systemerr = systemout.next_siebling
+ assert systemerr.tag == "system-err"
+ assert "hello-stderr" in systemerr.toxml()
+
+ def test_failure_verbose_message(self, testdir):
+ testdir.makepyfile("""
+ import sys
+ def test_fail():
+ assert 0, "An error"
+ """)
+
+ result, dom = runandparse(testdir)
+ node = dom.find_first_by_tag("testsuite")
+ tnode = node.find_first_by_tag("testcase")
+ fnode = tnode.find_first_by_tag("failure")
+ fnode.assert_attr(message="AssertionError: An error assert 0")
+
+ def test_failure_escape(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.parametrize('arg1', "<&'", ids="<&'")
+ def test_func(arg1):
+ print(arg1)
+ assert 0
+ """)
+ result, dom = runandparse(testdir)
+ assert result.ret
+ node = dom.find_first_by_tag("testsuite")
+ node.assert_attr(failures=3, tests=3)
+
+ for index, char in enumerate("<&'"):
+
+ tnode = node.find_nth_by_tag("testcase", index)
+ tnode.assert_attr(
+ file="test_failure_escape.py",
+ line="1",
+ classname="test_failure_escape",
+ name="test_func[%s]" % char)
+ sysout = tnode.find_first_by_tag('system-out')
+ text = sysout.text
+ assert text == '%s\n' % char
+
+ def test_junit_prefixing(self, testdir):
+ testdir.makepyfile("""
+ def test_func():
+ assert 0
+ class TestHello(object):
+ def test_hello(self):
+ pass
+ """)
+ result, dom = runandparse(testdir, "--junitprefix=xyz")
+ assert result.ret
+ node = dom.find_first_by_tag("testsuite")
+ node.assert_attr(failures=1, tests=2)
+ tnode = node.find_first_by_tag("testcase")
+ tnode.assert_attr(
+ file="test_junit_prefixing.py",
+ line="0",
+ classname="xyz.test_junit_prefixing",
+ name="test_func")
+ tnode = node.find_nth_by_tag("testcase", 1)
+ tnode.assert_attr(
+ file="test_junit_prefixing.py",
+ line="3",
+ classname="xyz.test_junit_prefixing."
+ "TestHello",
+ name="test_hello")
+
+ def test_xfailure_function(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ def test_xfail():
+ pytest.xfail("42")
+ """)
+ result, dom = runandparse(testdir)
+ assert not result.ret
+ node = dom.find_first_by_tag("testsuite")
+ node.assert_attr(skips=1, tests=1)
+ tnode = node.find_first_by_tag("testcase")
+ tnode.assert_attr(
+ file="test_xfailure_function.py",
+ line="1",
+ classname="test_xfailure_function",
+ name="test_xfail")
+ fnode = tnode.find_first_by_tag("skipped")
+ fnode.assert_attr(message="expected test failure")
+ # assert "ValueError" in fnode.toxml()
+
+ def test_xfailure_xpass(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.xfail
+ def test_xpass():
+ pass
+ """)
+ result, dom = runandparse(testdir)
+ # assert result.ret
+ node = dom.find_first_by_tag("testsuite")
+ node.assert_attr(skips=0, tests=1)
+ tnode = node.find_first_by_tag("testcase")
+ tnode.assert_attr(
+ file="test_xfailure_xpass.py",
+ line="1",
+ classname="test_xfailure_xpass",
+ name="test_xpass")
+
+ def test_xfailure_xpass_strict(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.xfail(strict=True, reason="This needs to fail!")
+ def test_xpass():
+ pass
+ """)
+ result, dom = runandparse(testdir)
+ # assert result.ret
+ node = dom.find_first_by_tag("testsuite")
+ node.assert_attr(skips=0, tests=1)
+ tnode = node.find_first_by_tag("testcase")
+ tnode.assert_attr(
+ file="test_xfailure_xpass_strict.py",
+ line="1",
+ classname="test_xfailure_xpass_strict",
+ name="test_xpass")
+ fnode = tnode.find_first_by_tag("failure")
+ fnode.assert_attr(message="[XPASS(strict)] This needs to fail!")
+
+ def test_collect_error(self, testdir):
+ testdir.makepyfile("syntax error")
+ result, dom = runandparse(testdir)
+ assert result.ret
+ node = dom.find_first_by_tag("testsuite")
+ node.assert_attr(errors=1, tests=1)
+ tnode = node.find_first_by_tag("testcase")
+ tnode.assert_attr(
+ file="test_collect_error.py",
+ name="test_collect_error")
+ assert tnode["line"] is None
+ fnode = tnode.find_first_by_tag("error")
+ fnode.assert_attr(message="collection failure")
+ assert "SyntaxError" in fnode.toxml()
+
+ def test_unicode(self, testdir):
+ value = 'hx\xc4\x85\xc4\x87\n'
+ testdir.makepyfile("""
+ # coding: latin1
+ def test_hello():
+ print (%r)
+ assert 0
+ """ % value)
+ result, dom = runandparse(testdir)
+ assert result.ret == 1
+ tnode = dom.find_first_by_tag("testcase")
+ fnode = tnode.find_first_by_tag("failure")
+ if not sys.platform.startswith("java"):
+ assert "hx" in fnode.toxml()
+
+ def test_assertion_binchars(self, testdir):
+ """this test did fail when the escaping wasnt strict"""
+ testdir.makepyfile("""
+
+ M1 = '\x01\x02\x03\x04'
+ M2 = '\x01\x02\x03\x05'
+
+ def test_str_compare():
+ assert M1 == M2
+ """)
+ result, dom = runandparse(testdir)
+ print(dom.toxml())
+
+ def test_pass_captures_stdout(self, testdir):
+ testdir.makepyfile("""
+ def test_pass():
+ print('hello-stdout')
+ """)
+ result, dom = runandparse(testdir)
+ node = dom.find_first_by_tag("testsuite")
+ pnode = node.find_first_by_tag("testcase")
+ systemout = pnode.find_first_by_tag("system-out")
+ assert "hello-stdout" in systemout.toxml()
+
+ def test_pass_captures_stderr(self, testdir):
+ testdir.makepyfile("""
+ import sys
+ def test_pass():
+ sys.stderr.write('hello-stderr')
+ """)
+ result, dom = runandparse(testdir)
+ node = dom.find_first_by_tag("testsuite")
+ pnode = node.find_first_by_tag("testcase")
+ systemout = pnode.find_first_by_tag("system-err")
+ assert "hello-stderr" in systemout.toxml()
+
+ def test_setup_error_captures_stdout(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture
+ def arg(request):
+ print('hello-stdout')
+ raise ValueError()
+ def test_function(arg):
+ pass
+ """)
+ result, dom = runandparse(testdir)
+ node = dom.find_first_by_tag("testsuite")
+ pnode = node.find_first_by_tag("testcase")
+ systemout = pnode.find_first_by_tag("system-out")
+ assert "hello-stdout" in systemout.toxml()
+
+ def test_setup_error_captures_stderr(self, testdir):
+ testdir.makepyfile("""
+ import sys
+ import pytest
+
+ @pytest.fixture
+ def arg(request):
+ sys.stderr.write('hello-stderr')
+ raise ValueError()
+ def test_function(arg):
+ pass
+ """)
+ result, dom = runandparse(testdir)
+ node = dom.find_first_by_tag("testsuite")
+ pnode = node.find_first_by_tag("testcase")
+ systemout = pnode.find_first_by_tag("system-err")
+ assert "hello-stderr" in systemout.toxml()
+
+ def test_avoid_double_stdout(self, testdir):
+ testdir.makepyfile("""
+ import sys
+ import pytest
+
+ @pytest.fixture
+ def arg(request):
+ yield
+ sys.stdout.write('hello-stdout teardown')
+ raise ValueError()
+ def test_function(arg):
+ sys.stdout.write('hello-stdout call')
+ """)
+ result, dom = runandparse(testdir)
+ node = dom.find_first_by_tag("testsuite")
+ pnode = node.find_first_by_tag("testcase")
+ systemout = pnode.find_first_by_tag("system-out")
+ assert "hello-stdout call" in systemout.toxml()
+ assert "hello-stdout teardown" in systemout.toxml()
+
+
+def test_mangle_test_address():
+ from _pytest.junitxml import mangle_test_address
+ address = '::'.join(
+ ["a/my.py.thing.py", "Class", "()", "method", "[a-1-::]"])
+ newnames = mangle_test_address(address)
+ assert newnames == ["a.my.py.thing", "Class", "method", "[a-1-::]"]
+
+
+def test_dont_configure_on_slaves(tmpdir):
+ gotten = []
+
+ class FakeConfig(object):
+ def __init__(self):
+ self.pluginmanager = self
+ self.option = self
+
+ def getini(self, name):
+ return "pytest"
+
+ junitprefix = None
+ # XXX: shouldnt need tmpdir ?
+ xmlpath = str(tmpdir.join('junix.xml'))
+ register = gotten.append
+
+ fake_config = FakeConfig()
+ from _pytest import junitxml
+ junitxml.pytest_configure(fake_config)
+ assert len(gotten) == 1
+ FakeConfig.slaveinput = None
+ junitxml.pytest_configure(fake_config)
+ assert len(gotten) == 1
+
+
+class TestNonPython(object):
+ def test_summing_simple(self, testdir):
+ testdir.makeconftest("""
+ import pytest
+ def pytest_collect_file(path, parent):
+ if path.ext == ".xyz":
+ return MyItem(path, parent)
+ class MyItem(pytest.Item):
+ def __init__(self, path, parent):
+ super(MyItem, self).__init__(path.basename, parent)
+ self.fspath = path
+ def runtest(self):
+ raise ValueError(42)
+ def repr_failure(self, excinfo):
+ return "custom item runtest failed"
+ """)
+ testdir.tmpdir.join("myfile.xyz").write("hello")
+ result, dom = runandparse(testdir)
+ assert result.ret
+ node = dom.find_first_by_tag("testsuite")
+ node.assert_attr(errors=0, failures=1, skips=0, tests=1)
+ tnode = node.find_first_by_tag("testcase")
+ tnode.assert_attr(name="myfile.xyz")
+ fnode = tnode.find_first_by_tag("failure")
+ fnode.assert_attr(message="custom item runtest failed")
+ assert "custom item runtest failed" in fnode.toxml()
+
+
+def test_nullbyte(testdir):
+ # A null byte can not occur in XML (see section 2.2 of the spec)
+ testdir.makepyfile("""
+ import sys
+ def test_print_nullbyte():
+ sys.stdout.write('Here the null -->' + chr(0) + '<--')
+ sys.stdout.write('In repr form -->' + repr(chr(0)) + '<--')
+ assert False
+ """)
+ xmlf = testdir.tmpdir.join('junit.xml')
+ testdir.runpytest('--junitxml=%s' % xmlf)
+ text = xmlf.read()
+ assert '\x00' not in text
+ assert '#x00' in text
+
+
+def test_nullbyte_replace(testdir):
+ # Check if the null byte gets replaced
+ testdir.makepyfile("""
+ import sys
+ def test_print_nullbyte():
+ sys.stdout.write('Here the null -->' + chr(0) + '<--')
+ sys.stdout.write('In repr form -->' + repr(chr(0)) + '<--')
+ assert False
+ """)
+ xmlf = testdir.tmpdir.join('junit.xml')
+ testdir.runpytest('--junitxml=%s' % xmlf)
+ text = xmlf.read()
+ assert '#x0' in text
+
+
+def test_invalid_xml_escape():
+ # Test some more invalid xml chars, the full range should be
+ # tested really but let's just thest the edges of the ranges
+ # intead.
+ # XXX This only tests low unicode character points for now as
+ # there are some issues with the testing infrastructure for
+ # the higher ones.
+ # XXX Testing 0xD (\r) is tricky as it overwrites the just written
+ # line in the output, so we skip it too.
+ global unichr
+ try:
+ unichr(65)
+ except NameError:
+ unichr = chr
+ invalid = (0x00, 0x1, 0xB, 0xC, 0xE, 0x19, 27, # issue #126
+ 0xD800, 0xDFFF, 0xFFFE, 0x0FFFF) # , 0x110000)
+ valid = (0x9, 0xA, 0x20, )
+ # 0xD, 0xD7FF, 0xE000, 0xFFFD, 0x10000, 0x10FFFF)
+
+ from _pytest.junitxml import bin_xml_escape
+
+ for i in invalid:
+ got = bin_xml_escape(unichr(i)).uniobj
+ if i <= 0xFF:
+ expected = '#x%02X' % i
+ else:
+ expected = '#x%04X' % i
+ assert got == expected
+ for i in valid:
+ assert chr(i) == bin_xml_escape(unichr(i)).uniobj
+
+
+def test_logxml_path_expansion(tmpdir, monkeypatch):
+ home_tilde = py.path.local(os.path.expanduser('~')).join('test.xml')
+
+ xml_tilde = LogXML('~%stest.xml' % tmpdir.sep, None)
+ assert xml_tilde.logfile == home_tilde
+
+ # this is here for when $HOME is not set correct
+ monkeypatch.setenv("HOME", tmpdir)
+ home_var = os.path.normpath(os.path.expandvars('$HOME/test.xml'))
+
+ xml_var = LogXML('$HOME%stest.xml' % tmpdir.sep, None)
+ assert xml_var.logfile == home_var
+
+
+def test_logxml_changingdir(testdir):
+ testdir.makepyfile("""
+ def test_func():
+ import os
+ os.chdir("a")
+ """)
+ testdir.tmpdir.mkdir("a")
+ result = testdir.runpytest("--junitxml=a/x.xml")
+ assert result.ret == 0
+ assert testdir.tmpdir.join("a/x.xml").check()
+
+
+def test_logxml_makedir(testdir):
+ """--junitxml should automatically create directories for the xml file"""
+ testdir.makepyfile("""
+ def test_pass():
+ pass
+ """)
+ result = testdir.runpytest("--junitxml=path/to/results.xml")
+ assert result.ret == 0
+ assert testdir.tmpdir.join("path/to/results.xml").check()
+
+
+def test_logxml_check_isdir(testdir):
+ """Give an error if --junit-xml is a directory (#2089)"""
+ result = testdir.runpytest("--junit-xml=.")
+ result.stderr.fnmatch_lines(["*--junitxml must be a filename*"])
+
+
+def test_escaped_parametrized_names_xml(testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.parametrize('char', [u"\\x00"])
+ def test_func(char):
+ assert char
+ """)
+ result, dom = runandparse(testdir)
+ assert result.ret == 0
+ node = dom.find_first_by_tag("testcase")
+ node.assert_attr(name="test_func[\\x00]")
+
+
+def test_double_colon_split_function_issue469(testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.parametrize('param', ["double::colon"])
+ def test_func(param):
+ pass
+ """)
+ result, dom = runandparse(testdir)
+ assert result.ret == 0
+ node = dom.find_first_by_tag("testcase")
+ node.assert_attr(classname="test_double_colon_split_function_issue469")
+ node.assert_attr(name='test_func[double::colon]')
+
+
+def test_double_colon_split_method_issue469(testdir):
+ testdir.makepyfile("""
+ import pytest
+ class TestClass(object):
+ @pytest.mark.parametrize('param', ["double::colon"])
+ def test_func(self, param):
+ pass
+ """)
+ result, dom = runandparse(testdir)
+ assert result.ret == 0
+ node = dom.find_first_by_tag("testcase")
+ node.assert_attr(
+ classname="test_double_colon_split_method_issue469.TestClass")
+ node.assert_attr(name='test_func[double::colon]')
+
+
+def test_unicode_issue368(testdir):
+ path = testdir.tmpdir.join("test.xml")
+ log = LogXML(str(path), None)
+ ustr = py.builtin._totext("ВНИ!", "utf-8")
+ from _pytest.runner import BaseReport
+
+ class Report(BaseReport):
+ longrepr = ustr
+ sections = []
+ nodeid = "something"
+ location = 'tests/filename.py', 42, 'TestClass.method'
+
+ test_report = Report()
+
+ # hopefully this is not too brittle ...
+ log.pytest_sessionstart()
+ node_reporter = log._opentestcase(test_report)
+ node_reporter.append_failure(test_report)
+ node_reporter.append_collect_error(test_report)
+ node_reporter.append_collect_skipped(test_report)
+ node_reporter.append_error(test_report)
+ test_report.longrepr = "filename", 1, ustr
+ node_reporter.append_skipped(test_report)
+ test_report.longrepr = "filename", 1, "Skipped: 卡嘣嘣"
+ node_reporter.append_skipped(test_report)
+ test_report.wasxfail = ustr
+ node_reporter.append_skipped(test_report)
+ log.pytest_sessionfinish()
+
+
+def test_record_property(testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture
+ def other(record_xml_property):
+ record_xml_property("bar", 1)
+ def test_record(record_xml_property, other):
+ record_xml_property("foo", "<1");
+ """)
+ result, dom = runandparse(testdir, '-rw')
+ node = dom.find_first_by_tag("testsuite")
+ tnode = node.find_first_by_tag("testcase")
+ psnode = tnode.find_first_by_tag('properties')
+ pnodes = psnode.find_by_tag('property')
+ pnodes[0].assert_attr(name="bar", value="1")
+ pnodes[1].assert_attr(name="foo", value="<1")
+ result.stdout.fnmatch_lines([
+ 'test_record_property.py::test_record',
+ '*record_xml_property*experimental*',
+ ])
+
+
+def test_record_property_same_name(testdir):
+ testdir.makepyfile("""
+ def test_record_with_same_name(record_xml_property):
+ record_xml_property("foo", "bar")
+ record_xml_property("foo", "baz")
+ """)
+ result, dom = runandparse(testdir, '-rw')
+ node = dom.find_first_by_tag("testsuite")
+ tnode = node.find_first_by_tag("testcase")
+ psnode = tnode.find_first_by_tag('properties')
+ pnodes = psnode.find_by_tag('property')
+ pnodes[0].assert_attr(name="foo", value="bar")
+ pnodes[1].assert_attr(name="foo", value="baz")
+
+
+def test_random_report_log_xdist(testdir):
+ """xdist calls pytest_runtest_logreport as they are executed by the slaves,
+ with nodes from several nodes overlapping, so junitxml must cope with that
+ to produce correct reports. #1064
+ """
+ pytest.importorskip('xdist')
+ testdir.makepyfile("""
+ import pytest, time
+ @pytest.mark.parametrize('i', list(range(30)))
+ def test_x(i):
+ assert i != 22
+ """)
+ _, dom = runandparse(testdir, '-n2')
+ suite_node = dom.find_first_by_tag("testsuite")
+ failed = []
+ for case_node in suite_node.find_by_tag("testcase"):
+ if case_node.find_first_by_tag('failure'):
+ failed.append(case_node['name'])
+
+ assert failed == ['test_x[22]']
+
+
+def test_runs_twice(testdir):
+ f = testdir.makepyfile('''
+ def test_pass():
+ pass
+ ''')
+
+ result, dom = runandparse(testdir, f, f)
+ assert 'INTERNALERROR' not in result.stdout.str()
+ first, second = [x['classname'] for x in dom.find_by_tag("testcase")]
+ assert first == second
+
+
+@pytest.mark.xfail(reason='hangs', run=False)
+def test_runs_twice_xdist(testdir):
+ pytest.importorskip('xdist')
+ f = testdir.makepyfile('''
+ def test_pass():
+ pass
+ ''')
+
+ result, dom = runandparse(
+ testdir, f,
+ '--dist', 'each', '--tx', '2*popen',)
+ assert 'INTERNALERROR' not in result.stdout.str()
+ first, second = [x['classname'] for x in dom.find_by_tag("testcase")]
+ assert first == second
+
+
+def test_fancy_items_regression(testdir):
+ # issue 1259
+ testdir.makeconftest("""
+ import pytest
+ class FunItem(pytest.Item):
+ def runtest(self):
+ pass
+ class NoFunItem(pytest.Item):
+ def runtest(self):
+ pass
+
+ class FunCollector(pytest.File):
+ def collect(self):
+ return [
+ FunItem('a', self),
+ NoFunItem('a', self),
+ NoFunItem('b', self),
+ ]
+
+ def pytest_collect_file(path, parent):
+ if path.check(ext='.py'):
+ return FunCollector(path, parent)
+ """)
+
+ testdir.makepyfile('''
+ def test_pass():
+ pass
+ ''')
+
+ result, dom = runandparse(testdir)
+
+ assert 'INTERNALERROR' not in result.stdout.str()
+
+ items = sorted(
+ '%(classname)s %(name)s %(file)s' % x
+
+ for x in dom.find_by_tag("testcase"))
+ import pprint
+ pprint.pprint(items)
+ assert items == [
+ u'conftest a conftest.py',
+ u'conftest a conftest.py',
+ u'conftest b conftest.py',
+ u'test_fancy_items_regression a test_fancy_items_regression.py',
+ u'test_fancy_items_regression a test_fancy_items_regression.py',
+ u'test_fancy_items_regression b test_fancy_items_regression.py',
+ u'test_fancy_items_regression test_pass'
+ u' test_fancy_items_regression.py',
+ ]
+
+
+def test_global_properties(testdir):
+ path = testdir.tmpdir.join("test_global_properties.xml")
+ log = LogXML(str(path), None)
+ from _pytest.runner import BaseReport
+
+ class Report(BaseReport):
+ sections = []
+ nodeid = "test_node_id"
+
+ log.pytest_sessionstart()
+ log.add_global_property('foo', 1)
+ log.add_global_property('bar', 2)
+ log.pytest_sessionfinish()
+
+ dom = minidom.parse(str(path))
+
+ properties = dom.getElementsByTagName('properties')
+
+ assert (properties.length == 1), "There must be one <properties> node"
+
+ property_list = dom.getElementsByTagName('property')
+
+ assert (property_list.length == 2), "There most be only 2 property nodes"
+
+ expected = {'foo': '1', 'bar': '2'}
+ actual = {}
+
+ for p in property_list:
+ k = str(p.getAttribute('name'))
+ v = str(p.getAttribute('value'))
+ actual[k] = v
+
+ assert actual == expected
+
+
+def test_url_property(testdir):
+ test_url = "http://www.github.com/pytest-dev"
+ path = testdir.tmpdir.join("test_url_property.xml")
+ log = LogXML(str(path), None)
+ from _pytest.runner import BaseReport
+
+ class Report(BaseReport):
+ longrepr = "FooBarBaz"
+ sections = []
+ nodeid = "something"
+ location = 'tests/filename.py', 42, 'TestClass.method'
+ url = test_url
+
+ test_report = Report()
+
+ log.pytest_sessionstart()
+ node_reporter = log._opentestcase(test_report)
+ node_reporter.append_failure(test_report)
+ log.pytest_sessionfinish()
+
+ test_case = minidom.parse(str(path)).getElementsByTagName('testcase')[0]
+
+ assert (test_case.getAttribute('url') == test_url), "The URL did not get written to the xml"
+
+
+@pytest.mark.parametrize('suite_name', ['my_suite', ''])
+def test_set_suite_name(testdir, suite_name):
+ if suite_name:
+ testdir.makeini("""
+ [pytest]
+ junit_suite_name={0}
+ """.format(suite_name))
+ expected = suite_name
+ else:
+ expected = 'pytest'
+ testdir.makepyfile("""
+ import pytest
+
+ def test_func():
+ pass
+ """)
+ result, dom = runandparse(testdir)
+ assert result.ret == 0
+ node = dom.find_first_by_tag("testsuite")
+ node.assert_attr(name=expected)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_mark.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_mark.py
new file mode 100644
index 00000000000..46bf0b0e778
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_mark.py
@@ -0,0 +1,878 @@
+from __future__ import absolute_import, division, print_function
+import os
+import sys
+
+import pytest
+from _pytest.mark import MarkGenerator as Mark, ParameterSet, transfer_markers
+
+
+class TestMark(object):
+ def test_markinfo_repr(self):
+ from _pytest.mark import MarkInfo, Mark
+ m = MarkInfo(Mark("hello", (1, 2), {}))
+ repr(m)
+
+ @pytest.mark.parametrize('attr', ['mark', 'param'])
+ @pytest.mark.parametrize('modulename', ['py.test', 'pytest'])
+ def test_pytest_exists_in_namespace_all(self, attr, modulename):
+ module = sys.modules[modulename]
+ assert attr in module.__all__
+
+ def test_pytest_mark_notcallable(self):
+ mark = Mark()
+ pytest.raises((AttributeError, TypeError), mark)
+
+ def test_mark_with_param(self):
+ def some_function(abc):
+ pass
+
+ class SomeClass(object):
+ pass
+
+ assert pytest.mark.fun(some_function) is some_function
+ assert pytest.mark.fun.with_args(some_function) is not some_function
+
+ assert pytest.mark.fun(SomeClass) is SomeClass
+ assert pytest.mark.fun.with_args(SomeClass) is not SomeClass
+
+ def test_pytest_mark_name_starts_with_underscore(self):
+ mark = Mark()
+ pytest.raises(AttributeError, getattr, mark, '_some_name')
+
+ def test_pytest_mark_bare(self):
+ mark = Mark()
+
+ def f():
+ pass
+
+ mark.hello(f)
+ assert f.hello
+
+ def test_pytest_mark_keywords(self):
+ mark = Mark()
+
+ def f():
+ pass
+
+ mark.world(x=3, y=4)(f)
+ assert f.world
+ assert f.world.kwargs['x'] == 3
+ assert f.world.kwargs['y'] == 4
+
+ def test_apply_multiple_and_merge(self):
+ mark = Mark()
+
+ def f():
+ pass
+
+ mark.world
+ mark.world(x=3)(f)
+ assert f.world.kwargs['x'] == 3
+ mark.world(y=4)(f)
+ assert f.world.kwargs['x'] == 3
+ assert f.world.kwargs['y'] == 4
+ mark.world(y=1)(f)
+ assert f.world.kwargs['y'] == 1
+ assert len(f.world.args) == 0
+
+ def test_pytest_mark_positional(self):
+ mark = Mark()
+
+ def f():
+ pass
+
+ mark.world("hello")(f)
+ assert f.world.args[0] == "hello"
+ mark.world("world")(f)
+
+ def test_pytest_mark_positional_func_and_keyword(self):
+ mark = Mark()
+
+ def f():
+ raise Exception
+
+ m = mark.world(f, omega="hello")
+
+ def g():
+ pass
+
+ assert m(g) == g
+ assert g.world.args[0] is f
+ assert g.world.kwargs["omega"] == "hello"
+
+ def test_pytest_mark_reuse(self):
+ mark = Mark()
+
+ def f():
+ pass
+
+ w = mark.some
+ w("hello", reason="123")(f)
+ assert f.some.args[0] == "hello"
+ assert f.some.kwargs['reason'] == "123"
+
+ def g():
+ pass
+
+ w("world", reason2="456")(g)
+ assert g.some.args[0] == "world"
+ assert 'reason' not in g.some.kwargs
+ assert g.some.kwargs['reason2'] == "456"
+
+
+def test_marked_class_run_twice(testdir, request):
+ """Test fails file is run twice that contains marked class.
+ See issue#683.
+ """
+ py_file = testdir.makepyfile("""
+ import pytest
+ @pytest.mark.parametrize('abc', [1, 2, 3])
+ class Test1(object):
+ def test_1(self, abc):
+ assert abc in [1, 2, 3]
+ """)
+ file_name = os.path.basename(py_file.strpath)
+ rec = testdir.inline_run(file_name, file_name)
+ rec.assertoutcome(passed=6)
+
+
+def test_ini_markers(testdir):
+ testdir.makeini("""
+ [pytest]
+ markers =
+ a1: this is a webtest marker
+ a2: this is a smoke marker
+ """)
+ testdir.makepyfile("""
+ def test_markers(pytestconfig):
+ markers = pytestconfig.getini("markers")
+ print (markers)
+ assert len(markers) >= 2
+ assert markers[0].startswith("a1:")
+ assert markers[1].startswith("a2:")
+ """)
+ rec = testdir.inline_run()
+ rec.assertoutcome(passed=1)
+
+
+def test_markers_option(testdir):
+ testdir.makeini("""
+ [pytest]
+ markers =
+ a1: this is a webtest marker
+ a1some: another marker
+ nodescription
+ """)
+ result = testdir.runpytest("--markers", )
+ result.stdout.fnmatch_lines([
+ "*a1*this is a webtest*",
+ "*a1some*another marker",
+ "*nodescription*",
+ ])
+
+
+def test_ini_markers_whitespace(testdir):
+ testdir.makeini("""
+ [pytest]
+ markers =
+ a1 : this is a whitespace marker
+ """)
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.mark.a1
+ def test_markers():
+ assert True
+ """)
+ rec = testdir.inline_run("--strict", "-m", "a1")
+ rec.assertoutcome(passed=1)
+
+
+def test_marker_without_description(testdir):
+ testdir.makefile(".cfg", setup="""
+ [tool:pytest]
+ markers=slow
+ """)
+ testdir.makeconftest("""
+ import pytest
+ pytest.mark.xfail('FAIL')
+ """)
+ ftdir = testdir.mkdir("ft1_dummy")
+ testdir.tmpdir.join("conftest.py").move(ftdir.join("conftest.py"))
+ rec = testdir.runpytest_subprocess("--strict")
+ rec.assert_outcomes()
+
+
+def test_markers_option_with_plugin_in_current_dir(testdir):
+ testdir.makeconftest('pytest_plugins = "flip_flop"')
+ testdir.makepyfile(flip_flop="""\
+ def pytest_configure(config):
+ config.addinivalue_line("markers", "flip:flop")
+
+ def pytest_generate_tests(metafunc):
+ try:
+ mark = metafunc.function.flipper
+ except AttributeError:
+ return
+ metafunc.parametrize("x", (10, 20))""")
+ testdir.makepyfile("""\
+ import pytest
+ @pytest.mark.flipper
+ def test_example(x):
+ assert x""")
+
+ result = testdir.runpytest("--markers")
+ result.stdout.fnmatch_lines(["*flip*flop*"])
+
+
+def test_mark_on_pseudo_function(testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.mark.r(lambda x: 0/0)
+ def test_hello():
+ pass
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+
+def test_strict_prohibits_unregistered_markers(testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.unregisteredmark
+ def test_hello():
+ pass
+ """)
+ result = testdir.runpytest("--strict")
+ assert result.ret != 0
+ result.stdout.fnmatch_lines([
+ "*unregisteredmark*not*registered*",
+ ])
+
+
+@pytest.mark.parametrize("spec", [
+ ("xyz", ("test_one",)),
+ ("xyz and xyz2", ()),
+ ("xyz2", ("test_two",)),
+ ("xyz or xyz2", ("test_one", "test_two"),)
+])
+def test_mark_option(spec, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.xyz
+ def test_one():
+ pass
+ @pytest.mark.xyz2
+ def test_two():
+ pass
+ """)
+ opt, passed_result = spec
+ rec = testdir.inline_run("-m", opt)
+ passed, skipped, fail = rec.listoutcomes()
+ passed = [x.nodeid.split("::")[-1] for x in passed]
+ assert len(passed) == len(passed_result)
+ assert list(passed) == list(passed_result)
+
+
+@pytest.mark.parametrize("spec", [
+ ("interface", ("test_interface",)),
+ ("not interface", ("test_nointer",)),
+])
+def test_mark_option_custom(spec, testdir):
+ testdir.makeconftest("""
+ import pytest
+ def pytest_collection_modifyitems(items):
+ for item in items:
+ if "interface" in item.nodeid:
+ item.keywords["interface"] = pytest.mark.interface
+ """)
+ testdir.makepyfile("""
+ def test_interface():
+ pass
+ def test_nointer():
+ pass
+ """)
+ opt, passed_result = spec
+ rec = testdir.inline_run("-m", opt)
+ passed, skipped, fail = rec.listoutcomes()
+ passed = [x.nodeid.split("::")[-1] for x in passed]
+ assert len(passed) == len(passed_result)
+ assert list(passed) == list(passed_result)
+
+
+@pytest.mark.parametrize("spec", [
+ ("interface", ("test_interface",)),
+ ("not interface", ("test_nointer", "test_pass")),
+ ("pass", ("test_pass",)),
+ ("not pass", ("test_interface", "test_nointer")),
+])
+def test_keyword_option_custom(spec, testdir):
+ testdir.makepyfile("""
+ def test_interface():
+ pass
+ def test_nointer():
+ pass
+ def test_pass():
+ pass
+ """)
+ opt, passed_result = spec
+ rec = testdir.inline_run("-k", opt)
+ passed, skipped, fail = rec.listoutcomes()
+ passed = [x.nodeid.split("::")[-1] for x in passed]
+ assert len(passed) == len(passed_result)
+ assert list(passed) == list(passed_result)
+
+
+@pytest.mark.parametrize("spec", [
+ ("None", ("test_func[None]",)),
+ ("1.3", ("test_func[1.3]",)),
+ ("2-3", ("test_func[2-3]",))
+])
+def test_keyword_option_parametrize(spec, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.parametrize("arg", [None, 1.3, "2-3"])
+ def test_func(arg):
+ pass
+ """)
+ opt, passed_result = spec
+ rec = testdir.inline_run("-k", opt)
+ passed, skipped, fail = rec.listoutcomes()
+ passed = [x.nodeid.split("::")[-1] for x in passed]
+ assert len(passed) == len(passed_result)
+ assert list(passed) == list(passed_result)
+
+
+def test_parametrized_collected_from_command_line(testdir):
+ """Parametrized test not collected if test named specified
+ in command line issue#649.
+ """
+ py_file = testdir.makepyfile("""
+ import pytest
+ @pytest.mark.parametrize("arg", [None, 1.3, "2-3"])
+ def test_func(arg):
+ pass
+ """)
+ file_name = os.path.basename(py_file.strpath)
+ rec = testdir.inline_run(file_name + "::" + "test_func")
+ rec.assertoutcome(passed=3)
+
+
+def test_parametrized_collect_with_wrong_args(testdir):
+ """Test collect parametrized func with wrong number of args."""
+ py_file = testdir.makepyfile("""
+ import pytest
+
+ @pytest.mark.parametrize('foo, bar', [(1, 2, 3)])
+ def test_func(foo, bar):
+ pass
+ """)
+
+ result = testdir.runpytest(py_file)
+ result.stdout.fnmatch_lines([
+ 'E ValueError: In "parametrize" the number of values ((1, 2, 3)) '
+ 'must be equal to the number of names ([\'foo\', \'bar\'])'
+ ])
+
+
+def test_parametrized_with_kwargs(testdir):
+ """Test collect parametrized func with wrong number of args."""
+ py_file = testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture(params=[1,2])
+ def a(request):
+ return request.param
+
+ @pytest.mark.parametrize(argnames='b', argvalues=[1, 2])
+ def test_func(a, b):
+ pass
+ """)
+
+ result = testdir.runpytest(py_file)
+ assert(result.ret == 0)
+
+
+class TestFunctional(object):
+
+ def test_mark_per_function(self, testdir):
+ p = testdir.makepyfile("""
+ import pytest
+ @pytest.mark.hello
+ def test_hello():
+ assert hasattr(test_hello, 'hello')
+ """)
+ result = testdir.runpytest(p)
+ result.stdout.fnmatch_lines(["*1 passed*"])
+
+ def test_mark_per_module(self, testdir):
+ item = testdir.getitem("""
+ import pytest
+ pytestmark = pytest.mark.hello
+ def test_func():
+ pass
+ """)
+ keywords = item.keywords
+ assert 'hello' in keywords
+
+ def test_marklist_per_class(self, testdir):
+ item = testdir.getitem("""
+ import pytest
+ class TestClass(object):
+ pytestmark = [pytest.mark.hello, pytest.mark.world]
+ def test_func(self):
+ assert TestClass.test_func.hello
+ assert TestClass.test_func.world
+ """)
+ keywords = item.keywords
+ assert 'hello' in keywords
+
+ def test_marklist_per_module(self, testdir):
+ item = testdir.getitem("""
+ import pytest
+ pytestmark = [pytest.mark.hello, pytest.mark.world]
+ class TestClass(object):
+ def test_func(self):
+ assert TestClass.test_func.hello
+ assert TestClass.test_func.world
+ """)
+ keywords = item.keywords
+ assert 'hello' in keywords
+ assert 'world' in keywords
+
+ def test_mark_per_class_decorator(self, testdir):
+ item = testdir.getitem("""
+ import pytest
+ @pytest.mark.hello
+ class TestClass(object):
+ def test_func(self):
+ assert TestClass.test_func.hello
+ """)
+ keywords = item.keywords
+ assert 'hello' in keywords
+
+ def test_mark_per_class_decorator_plus_existing_dec(self, testdir):
+ item = testdir.getitem("""
+ import pytest
+ @pytest.mark.hello
+ class TestClass(object):
+ pytestmark = pytest.mark.world
+ def test_func(self):
+ assert TestClass.test_func.hello
+ assert TestClass.test_func.world
+ """)
+ keywords = item.keywords
+ assert 'hello' in keywords
+ assert 'world' in keywords
+
+ def test_merging_markers(self, testdir):
+ p = testdir.makepyfile("""
+ import pytest
+ pytestmark = pytest.mark.hello("pos1", x=1, y=2)
+ class TestClass(object):
+ # classlevel overrides module level
+ pytestmark = pytest.mark.hello(x=3)
+ @pytest.mark.hello("pos0", z=4)
+ def test_func(self):
+ pass
+ """)
+ items, rec = testdir.inline_genitems(p)
+ item, = items
+ keywords = item.keywords
+ marker = keywords['hello']
+ assert marker.args == ("pos0", "pos1")
+ assert marker.kwargs == {'x': 1, 'y': 2, 'z': 4}
+
+ # test the new __iter__ interface
+ values = list(marker)
+ assert len(values) == 3
+ assert values[0].args == ("pos0",)
+ assert values[1].args == ()
+ assert values[2].args == ("pos1", )
+
+ @pytest.mark.xfail(reason='unfixed')
+ def test_merging_markers_deep(self, testdir):
+ # issue 199 - propagate markers into nested classes
+ p = testdir.makepyfile("""
+ import pytest
+ class TestA(object):
+ pytestmark = pytest.mark.a
+ def test_b(self):
+ assert True
+ class TestC(object):
+ # this one didnt get marked
+ def test_d(self):
+ assert True
+ """)
+ items, rec = testdir.inline_genitems(p)
+ for item in items:
+ print(item, item.keywords)
+ assert 'a' in item.keywords
+
+ def test_mark_decorator_subclass_does_not_propagate_to_base(self, testdir):
+ p = testdir.makepyfile("""
+ import pytest
+
+ @pytest.mark.a
+ class Base(object): pass
+
+ @pytest.mark.b
+ class Test1(Base):
+ def test_foo(self): pass
+
+ class Test2(Base):
+ def test_bar(self): pass
+ """)
+ items, rec = testdir.inline_genitems(p)
+ self.assert_markers(items, test_foo=('a', 'b'), test_bar=('a',))
+
+ @pytest.mark.issue568
+ @pytest.mark.xfail(reason="markers smear on methods of base classes")
+ def test_mark_should_not_pass_to_siebling_class(self, testdir):
+ p = testdir.makepyfile("""
+ import pytest
+
+ class TestBase(object):
+ def test_foo(self):
+ pass
+
+ @pytest.mark.b
+ class TestSub(TestBase):
+ pass
+
+
+ class TestOtherSub(TestBase):
+ pass
+
+ """)
+ items, rec = testdir.inline_genitems(p)
+ base_item, sub_item, sub_item_other = items
+ assert not hasattr(base_item.obj, 'b')
+ assert not hasattr(sub_item_other.obj, 'b')
+
+ def test_mark_decorator_baseclasses_merged(self, testdir):
+ p = testdir.makepyfile("""
+ import pytest
+
+ @pytest.mark.a
+ class Base(object): pass
+
+ @pytest.mark.b
+ class Base2(Base): pass
+
+ @pytest.mark.c
+ class Test1(Base2):
+ def test_foo(self): pass
+
+ class Test2(Base2):
+ @pytest.mark.d
+ def test_bar(self): pass
+ """)
+ items, rec = testdir.inline_genitems(p)
+ self.assert_markers(items, test_foo=('a', 'b', 'c'),
+ test_bar=('a', 'b', 'd'))
+
+ def test_mark_with_wrong_marker(self, testdir):
+ reprec = testdir.inline_runsource("""
+ import pytest
+ class pytestmark(object):
+ pass
+ def test_func():
+ pass
+ """)
+ values = reprec.getfailedcollections()
+ assert len(values) == 1
+ assert "TypeError" in str(values[0].longrepr)
+
+ def test_mark_dynamically_in_funcarg(self, testdir):
+ testdir.makeconftest("""
+ import pytest
+ @pytest.fixture
+ def arg(request):
+ request.applymarker(pytest.mark.hello)
+ def pytest_terminal_summary(terminalreporter):
+ values = terminalreporter.stats['passed']
+ terminalreporter._tw.line("keyword: %s" % values[0].keywords)
+ """)
+ testdir.makepyfile("""
+ def test_func(arg):
+ pass
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "keyword: *hello*"
+ ])
+
+ def test_merging_markers_two_functions(self, testdir):
+ p = testdir.makepyfile("""
+ import pytest
+ @pytest.mark.hello("pos1", z=4)
+ @pytest.mark.hello("pos0", z=3)
+ def test_func():
+ pass
+ """)
+ items, rec = testdir.inline_genitems(p)
+ item, = items
+ keywords = item.keywords
+ marker = keywords['hello']
+ values = list(marker)
+ assert len(values) == 2
+ assert values[0].args == ("pos0",)
+ assert values[1].args == ("pos1",)
+
+ def test_no_marker_match_on_unmarked_names(self, testdir):
+ p = testdir.makepyfile("""
+ import pytest
+ @pytest.mark.shouldmatch
+ def test_marked():
+ assert 1
+
+ def test_unmarked():
+ assert 1
+ """)
+ reprec = testdir.inline_run("-m", "test_unmarked", p)
+ passed, skipped, failed = reprec.listoutcomes()
+ assert len(passed) + len(skipped) + len(failed) == 0
+ dlist = reprec.getcalls("pytest_deselected")
+ deselected_tests = dlist[0].items
+ assert len(deselected_tests) == 2
+
+ def test_keywords_at_node_level(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture(scope="session", autouse=True)
+ def some(request):
+ request.keywords["hello"] = 42
+ assert "world" not in request.keywords
+
+ @pytest.fixture(scope="function", autouse=True)
+ def funcsetup(request):
+ assert "world" in request.keywords
+ assert "hello" in request.keywords
+
+ @pytest.mark.world
+ def test_function():
+ pass
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+ def test_keyword_added_for_session(self, testdir):
+ testdir.makeconftest("""
+ import pytest
+ def pytest_collection_modifyitems(session):
+ session.add_marker("mark1")
+ session.add_marker(pytest.mark.mark2)
+ session.add_marker(pytest.mark.mark3)
+ pytest.raises(ValueError, lambda:
+ session.add_marker(10))
+ """)
+ testdir.makepyfile("""
+ def test_some(request):
+ assert "mark1" in request.keywords
+ assert "mark2" in request.keywords
+ assert "mark3" in request.keywords
+ assert 10 not in request.keywords
+ marker = request.node.get_marker("mark1")
+ assert marker.name == "mark1"
+ assert marker.args == ()
+ assert marker.kwargs == {}
+ """)
+ reprec = testdir.inline_run("-m", "mark1")
+ reprec.assertoutcome(passed=1)
+
+ def assert_markers(self, items, **expected):
+ """assert that given items have expected marker names applied to them.
+ expected should be a dict of (item name -> seq of expected marker names)
+
+ .. note:: this could be moved to ``testdir`` if proven to be useful
+ to other modules.
+ """
+ from _pytest.mark import MarkInfo
+ items = dict((x.name, x) for x in items)
+ for name, expected_markers in expected.items():
+ markers = items[name].keywords._markers
+ marker_names = set([name for (name, v) in markers.items()
+ if isinstance(v, MarkInfo)])
+ assert marker_names == set(expected_markers)
+
+ @pytest.mark.xfail(reason='callspec2.setmulti misuses keywords')
+ @pytest.mark.issue1540
+ def test_mark_from_parameters(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+
+ pytestmark = pytest.mark.skipif(True, reason='skip all')
+
+ # skipifs inside fixture params
+ params = [pytest.mark.skipif(False, reason='dont skip')('parameter')]
+
+
+ @pytest.fixture(params=params)
+ def parameter(request):
+ return request.param
+
+
+ def test_1(parameter):
+ assert True
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(skipped=1)
+
+
+class TestKeywordSelection(object):
+
+ def test_select_simple(self, testdir):
+ file_test = testdir.makepyfile("""
+ def test_one():
+ assert 0
+ class TestClass(object):
+ def test_method_one(self):
+ assert 42 == 43
+ """)
+
+ def check(keyword, name):
+ reprec = testdir.inline_run("-s", "-k", keyword, file_test)
+ passed, skipped, failed = reprec.listoutcomes()
+ assert len(failed) == 1
+ assert failed[0].nodeid.split("::")[-1] == name
+ assert len(reprec.getcalls('pytest_deselected')) == 1
+
+ for keyword in ['test_one', 'est_on']:
+ check(keyword, 'test_one')
+ check('TestClass and test', 'test_method_one')
+
+ @pytest.mark.parametrize("keyword", [
+ 'xxx', 'xxx and test_2', 'TestClass', 'xxx and not test_1',
+ 'TestClass and test_2', 'xxx and TestClass and test_2'])
+ def test_select_extra_keywords(self, testdir, keyword):
+ p = testdir.makepyfile(test_select="""
+ def test_1():
+ pass
+ class TestClass(object):
+ def test_2(self):
+ pass
+ """)
+ testdir.makepyfile(conftest="""
+ import pytest
+ @pytest.hookimpl(hookwrapper=True)
+ def pytest_pycollect_makeitem(name):
+ outcome = yield
+ if name == "TestClass":
+ item = outcome.get_result()
+ item.extra_keyword_matches.add("xxx")
+ """)
+ reprec = testdir.inline_run(p.dirpath(), '-s', '-k', keyword)
+ print("keyword", repr(keyword))
+ passed, skipped, failed = reprec.listoutcomes()
+ assert len(passed) == 1
+ assert passed[0].nodeid.endswith("test_2")
+ dlist = reprec.getcalls("pytest_deselected")
+ assert len(dlist) == 1
+ assert dlist[0].items[0].name == 'test_1'
+
+ def test_select_starton(self, testdir):
+ threepass = testdir.makepyfile(test_threepass="""
+ def test_one(): assert 1
+ def test_two(): assert 1
+ def test_three(): assert 1
+ """)
+ reprec = testdir.inline_run("-k", "test_two:", threepass)
+ passed, skipped, failed = reprec.listoutcomes()
+ assert len(passed) == 2
+ assert not failed
+ dlist = reprec.getcalls("pytest_deselected")
+ assert len(dlist) == 1
+ item = dlist[0].items[0]
+ assert item.name == "test_one"
+
+ def test_keyword_extra(self, testdir):
+ p = testdir.makepyfile("""
+ def test_one():
+ assert 0
+ test_one.mykeyword = True
+ """)
+ reprec = testdir.inline_run("-k", "mykeyword", p)
+ passed, skipped, failed = reprec.countoutcomes()
+ assert failed == 1
+
+ @pytest.mark.xfail
+ def test_keyword_extra_dash(self, testdir):
+ p = testdir.makepyfile("""
+ def test_one():
+ assert 0
+ test_one.mykeyword = True
+ """)
+ # with argparse the argument to an option cannot
+ # start with '-'
+ reprec = testdir.inline_run("-k", "-mykeyword", p)
+ passed, skipped, failed = reprec.countoutcomes()
+ assert passed + skipped + failed == 0
+
+ def test_no_magic_values(self, testdir):
+ """Make sure the tests do not match on magic values,
+ no double underscored values, like '__dict__',
+ and no instance values, like '()'.
+ """
+ p = testdir.makepyfile("""
+ def test_one(): assert 1
+ """)
+
+ def assert_test_is_not_selected(keyword):
+ reprec = testdir.inline_run("-k", keyword, p)
+ passed, skipped, failed = reprec.countoutcomes()
+ dlist = reprec.getcalls("pytest_deselected")
+ assert passed + skipped + failed == 0
+ deselected_tests = dlist[0].items
+ assert len(deselected_tests) == 1
+
+ assert_test_is_not_selected("__")
+ assert_test_is_not_selected("()")
+
+
+@pytest.mark.parametrize('argval, expected', [
+ (pytest.mark.skip()((1, 2)),
+ ParameterSet(values=(1, 2), marks=[pytest.mark.skip], id=None)),
+ (pytest.mark.xfail(pytest.mark.skip()((1, 2))),
+ ParameterSet(values=(1, 2),
+ marks=[pytest.mark.xfail, pytest.mark.skip], id=None)),
+
+])
+@pytest.mark.filterwarnings('ignore')
+def test_parameterset_extractfrom(argval, expected):
+ extracted = ParameterSet.extract_from(argval)
+ assert extracted == expected
+
+
+def test_legacy_transfer():
+
+ class FakeModule(object):
+ pytestmark = []
+
+ class FakeClass(object):
+ pytestmark = pytest.mark.nofun
+
+ @pytest.mark.fun
+ def fake_method(self):
+ pass
+
+ transfer_markers(fake_method, FakeClass, FakeModule)
+
+ # legacy marks transfer smeared
+ assert fake_method.nofun
+ assert fake_method.fun
+ # pristine marks dont transfer
+ assert fake_method.pytestmark == [pytest.mark.fun.mark]
+
+
+class TestMarkDecorator(object):
+
+ @pytest.mark.parametrize('lhs, rhs, expected', [
+ (pytest.mark.foo(), pytest.mark.foo(), True),
+ (pytest.mark.foo(), pytest.mark.bar(), False),
+ (pytest.mark.foo(), 'bar', False),
+ ('foo', pytest.mark.bar(), False)
+ ])
+ def test__eq__(self, lhs, rhs, expected):
+ assert (lhs == rhs) == expected
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_modimport.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_modimport.py
new file mode 100644
index 00000000000..2ab86bf7af1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_modimport.py
@@ -0,0 +1,25 @@
+import py
+import subprocess
+import sys
+import pytest
+import _pytest
+
+MODSET = [
+ x for x in py.path.local(_pytest.__file__).dirpath().visit('*.py')
+ if x.purebasename != '__init__'
+]
+
+
+@pytest.mark.parametrize('modfile', MODSET, ids=lambda x: x.purebasename)
+def test_fileimport(modfile):
+ # this test ensures all internal packages can import
+ # without needing the pytest namespace being set
+ # this is critical for the initialization of xdist
+
+ res = subprocess.call([
+ sys.executable,
+ '-c', 'import sys, py; py.path.local(sys.argv[1]).pyimport()',
+ modfile.strpath,
+ ])
+ if res:
+ pytest.fail("command result %s" % res)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_monkeypatch.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_monkeypatch.py
new file mode 100644
index 00000000000..4427908ab3b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_monkeypatch.py
@@ -0,0 +1,329 @@
+from __future__ import absolute_import, division, print_function
+import os
+import sys
+import textwrap
+
+import pytest
+from _pytest.monkeypatch import MonkeyPatch
+
+
+@pytest.fixture
+def mp():
+ cwd = os.getcwd()
+ sys_path = list(sys.path)
+ yield MonkeyPatch()
+ sys.path[:] = sys_path
+ os.chdir(cwd)
+
+
+def test_setattr():
+ class A(object):
+ x = 1
+
+ monkeypatch = MonkeyPatch()
+ pytest.raises(AttributeError, "monkeypatch.setattr(A, 'notexists', 2)")
+ monkeypatch.setattr(A, 'y', 2, raising=False)
+ assert A.y == 2
+ monkeypatch.undo()
+ assert not hasattr(A, 'y')
+
+ monkeypatch = MonkeyPatch()
+ monkeypatch.setattr(A, 'x', 2)
+ assert A.x == 2
+ monkeypatch.setattr(A, 'x', 3)
+ assert A.x == 3
+ monkeypatch.undo()
+ assert A.x == 1
+
+ A.x = 5
+ monkeypatch.undo() # double-undo makes no modification
+ assert A.x == 5
+
+
+class TestSetattrWithImportPath(object):
+ def test_string_expression(self, monkeypatch):
+ monkeypatch.setattr("os.path.abspath", lambda x: "hello2")
+ assert os.path.abspath("123") == "hello2"
+
+ def test_string_expression_class(self, monkeypatch):
+ monkeypatch.setattr("_pytest.config.Config", 42)
+ import _pytest
+ assert _pytest.config.Config == 42
+
+ def test_unicode_string(self, monkeypatch):
+ monkeypatch.setattr("_pytest.config.Config", 42)
+ import _pytest
+ assert _pytest.config.Config == 42
+ monkeypatch.delattr("_pytest.config.Config")
+
+ def test_wrong_target(self, monkeypatch):
+ pytest.raises(TypeError, lambda: monkeypatch.setattr(None, None))
+
+ def test_unknown_import(self, monkeypatch):
+ pytest.raises(ImportError,
+ lambda: monkeypatch.setattr("unkn123.classx", None))
+
+ def test_unknown_attr(self, monkeypatch):
+ pytest.raises(AttributeError,
+ lambda: monkeypatch.setattr("os.path.qweqwe", None))
+
+ def test_unknown_attr_non_raising(self, monkeypatch):
+ # https://github.com/pytest-dev/pytest/issues/746
+ monkeypatch.setattr('os.path.qweqwe', 42, raising=False)
+ assert os.path.qweqwe == 42
+
+ def test_delattr(self, monkeypatch):
+ monkeypatch.delattr("os.path.abspath")
+ assert not hasattr(os.path, "abspath")
+ monkeypatch.undo()
+ assert os.path.abspath
+
+
+def test_delattr():
+ class A(object):
+ x = 1
+
+ monkeypatch = MonkeyPatch()
+ monkeypatch.delattr(A, 'x')
+ assert not hasattr(A, 'x')
+ monkeypatch.undo()
+ assert A.x == 1
+
+ monkeypatch = MonkeyPatch()
+ monkeypatch.delattr(A, 'x')
+ pytest.raises(AttributeError, "monkeypatch.delattr(A, 'y')")
+ monkeypatch.delattr(A, 'y', raising=False)
+ monkeypatch.setattr(A, 'x', 5, raising=False)
+ assert A.x == 5
+ monkeypatch.undo()
+ assert A.x == 1
+
+
+def test_setitem():
+ d = {'x': 1}
+ monkeypatch = MonkeyPatch()
+ monkeypatch.setitem(d, 'x', 2)
+ monkeypatch.setitem(d, 'y', 1700)
+ monkeypatch.setitem(d, 'y', 1700)
+ assert d['x'] == 2
+ assert d['y'] == 1700
+ monkeypatch.setitem(d, 'x', 3)
+ assert d['x'] == 3
+ monkeypatch.undo()
+ assert d['x'] == 1
+ assert 'y' not in d
+ d['x'] = 5
+ monkeypatch.undo()
+ assert d['x'] == 5
+
+
+def test_setitem_deleted_meanwhile():
+ d = {}
+ monkeypatch = MonkeyPatch()
+ monkeypatch.setitem(d, 'x', 2)
+ del d['x']
+ monkeypatch.undo()
+ assert not d
+
+
+@pytest.mark.parametrize("before", [True, False])
+def test_setenv_deleted_meanwhile(before):
+ key = "qwpeoip123"
+ if before:
+ os.environ[key] = "world"
+ monkeypatch = MonkeyPatch()
+ monkeypatch.setenv(key, 'hello')
+ del os.environ[key]
+ monkeypatch.undo()
+ if before:
+ assert os.environ[key] == "world"
+ del os.environ[key]
+ else:
+ assert key not in os.environ
+
+
+def test_delitem():
+ d = {'x': 1}
+ monkeypatch = MonkeyPatch()
+ monkeypatch.delitem(d, 'x')
+ assert 'x' not in d
+ monkeypatch.delitem(d, 'y', raising=False)
+ pytest.raises(KeyError, "monkeypatch.delitem(d, 'y')")
+ assert not d
+ monkeypatch.setitem(d, 'y', 1700)
+ assert d['y'] == 1700
+ d['hello'] = 'world'
+ monkeypatch.setitem(d, 'x', 1500)
+ assert d['x'] == 1500
+ monkeypatch.undo()
+ assert d == {'hello': 'world', 'x': 1}
+
+
+def test_setenv():
+ monkeypatch = MonkeyPatch()
+ monkeypatch.setenv('XYZ123', 2)
+ import os
+ assert os.environ['XYZ123'] == "2"
+ monkeypatch.undo()
+ assert 'XYZ123' not in os.environ
+
+
+def test_delenv():
+ name = 'xyz1234'
+ assert name not in os.environ
+ monkeypatch = MonkeyPatch()
+ pytest.raises(KeyError, "monkeypatch.delenv(%r, raising=True)" % name)
+ monkeypatch.delenv(name, raising=False)
+ monkeypatch.undo()
+ os.environ[name] = "1"
+ try:
+ monkeypatch = MonkeyPatch()
+ monkeypatch.delenv(name)
+ assert name not in os.environ
+ monkeypatch.setenv(name, "3")
+ assert os.environ[name] == "3"
+ monkeypatch.undo()
+ assert os.environ[name] == "1"
+ finally:
+ if name in os.environ:
+ del os.environ[name]
+
+
+def test_setenv_prepend():
+ import os
+ monkeypatch = MonkeyPatch()
+ monkeypatch.setenv('XYZ123', 2, prepend="-")
+ assert os.environ['XYZ123'] == "2"
+ monkeypatch.setenv('XYZ123', 3, prepend="-")
+ assert os.environ['XYZ123'] == "3-2"
+ monkeypatch.undo()
+ assert 'XYZ123' not in os.environ
+
+
+def test_monkeypatch_plugin(testdir):
+ reprec = testdir.inline_runsource("""
+ def test_method(monkeypatch):
+ assert monkeypatch.__class__.__name__ == "MonkeyPatch"
+ """)
+ res = reprec.countoutcomes()
+ assert tuple(res) == (1, 0, 0), res
+
+
+def test_syspath_prepend(mp):
+ old = list(sys.path)
+ mp.syspath_prepend('world')
+ mp.syspath_prepend('hello')
+ assert sys.path[0] == "hello"
+ assert sys.path[1] == "world"
+ mp.undo()
+ assert sys.path == old
+ mp.undo()
+ assert sys.path == old
+
+
+def test_syspath_prepend_double_undo(mp):
+ mp.syspath_prepend('hello world')
+ mp.undo()
+ sys.path.append('more hello world')
+ mp.undo()
+ assert sys.path[-1] == 'more hello world'
+
+
+def test_chdir_with_path_local(mp, tmpdir):
+ mp.chdir(tmpdir)
+ assert os.getcwd() == tmpdir.strpath
+
+
+def test_chdir_with_str(mp, tmpdir):
+ mp.chdir(tmpdir.strpath)
+ assert os.getcwd() == tmpdir.strpath
+
+
+def test_chdir_undo(mp, tmpdir):
+ cwd = os.getcwd()
+ mp.chdir(tmpdir)
+ mp.undo()
+ assert os.getcwd() == cwd
+
+
+def test_chdir_double_undo(mp, tmpdir):
+ mp.chdir(tmpdir.strpath)
+ mp.undo()
+ tmpdir.chdir()
+ mp.undo()
+ assert os.getcwd() == tmpdir.strpath
+
+
+def test_issue185_time_breaks(testdir):
+ testdir.makepyfile("""
+ import time
+ def test_m(monkeypatch):
+ def f():
+ raise Exception
+ monkeypatch.setattr(time, "time", f)
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines("""
+ *1 passed*
+ """)
+
+
+def test_importerror(testdir):
+ p = testdir.mkpydir("package")
+ p.join("a.py").write(textwrap.dedent("""\
+ import doesnotexist
+
+ x = 1
+ """))
+ testdir.tmpdir.join("test_importerror.py").write(textwrap.dedent("""\
+ def test_importerror(monkeypatch):
+ monkeypatch.setattr('package.a.x', 2)
+ """))
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines("""
+ *import error in package.a: No module named {0}doesnotexist{0}*
+ """.format("'" if sys.version_info > (3, 0) else ""))
+
+
+class SampleNew(object):
+ @staticmethod
+ def hello():
+ return True
+
+
+class SampleNewInherit(SampleNew):
+ pass
+
+
+class SampleOld(object):
+ # oldstyle on python2
+ @staticmethod
+ def hello():
+ return True
+
+
+class SampleOldInherit(SampleOld):
+ pass
+
+
+@pytest.mark.parametrize('Sample', [
+ SampleNew, SampleNewInherit,
+ SampleOld, SampleOldInherit,
+], ids=['new', 'new-inherit', 'old', 'old-inherit'])
+def test_issue156_undo_staticmethod(Sample):
+ monkeypatch = MonkeyPatch()
+
+ monkeypatch.setattr(Sample, 'hello', None)
+ assert Sample.hello is None
+
+ monkeypatch.undo()
+ assert Sample.hello()
+
+
+def test_issue1338_name_resolving():
+ pytest.importorskip('requests')
+ monkeypatch = MonkeyPatch()
+ try:
+ monkeypatch.delattr('requests.sessions.Session.request')
+ finally:
+ monkeypatch.undo()
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_nodes.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_nodes.py
new file mode 100644
index 00000000000..6f4540f99b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_nodes.py
@@ -0,0 +1,18 @@
+import pytest
+
+from _pytest import nodes
+
+
+@pytest.mark.parametrize("baseid, nodeid, expected", (
+ ('', '', True),
+ ('', 'foo', True),
+ ('', 'foo/bar', True),
+ ('', 'foo/bar::TestBaz::()', True),
+ ('foo', 'food', False),
+ ('foo/bar::TestBaz::()', 'foo/bar', False),
+ ('foo/bar::TestBaz::()', 'foo/bar::TestBop::()', False),
+ ('foo/bar', 'foo/bar::TestBop::()', True),
+))
+def test_ischildnode(baseid, nodeid, expected):
+ result = nodes.ischildnode(baseid, nodeid)
+ assert result is expected
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_nose.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_nose.py
new file mode 100644
index 00000000000..df3e1a94b05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_nose.py
@@ -0,0 +1,409 @@
+from __future__ import absolute_import, division, print_function
+import pytest
+
+
+def setup_module(mod):
+ mod.nose = pytest.importorskip("nose")
+
+
+def test_nose_setup(testdir):
+ p = testdir.makepyfile("""
+ values = []
+ from nose.tools import with_setup
+
+ @with_setup(lambda: values.append(1), lambda: values.append(2))
+ def test_hello():
+ assert values == [1]
+
+ def test_world():
+ assert values == [1,2]
+
+ test_hello.setup = lambda: values.append(1)
+ test_hello.teardown = lambda: values.append(2)
+ """)
+ result = testdir.runpytest(p, '-p', 'nose')
+ result.assert_outcomes(passed=2)
+
+
+def test_setup_func_with_setup_decorator():
+ from _pytest.nose import call_optional
+ values = []
+
+ class A(object):
+ @pytest.fixture(autouse=True)
+ def f(self):
+ values.append(1)
+
+ call_optional(A(), "f")
+ assert not values
+
+
+def test_setup_func_not_callable():
+ from _pytest.nose import call_optional
+
+ class A(object):
+ f = 1
+
+ call_optional(A(), "f")
+
+
+def test_nose_setup_func(testdir):
+ p = testdir.makepyfile("""
+ from nose.tools import with_setup
+
+ values = []
+
+ def my_setup():
+ a = 1
+ values.append(a)
+
+ def my_teardown():
+ b = 2
+ values.append(b)
+
+ @with_setup(my_setup, my_teardown)
+ def test_hello():
+ print (values)
+ assert values == [1]
+
+ def test_world():
+ print (values)
+ assert values == [1,2]
+
+ """)
+ result = testdir.runpytest(p, '-p', 'nose')
+ result.assert_outcomes(passed=2)
+
+
+def test_nose_setup_func_failure(testdir):
+ p = testdir.makepyfile("""
+ from nose.tools import with_setup
+
+ values = []
+ my_setup = lambda x: 1
+ my_teardown = lambda x: 2
+
+ @with_setup(my_setup, my_teardown)
+ def test_hello():
+ print (values)
+ assert values == [1]
+
+ def test_world():
+ print (values)
+ assert values == [1,2]
+
+ """)
+ result = testdir.runpytest(p, '-p', 'nose')
+ result.stdout.fnmatch_lines([
+ "*TypeError: <lambda>()*"
+ ])
+
+
+def test_nose_setup_func_failure_2(testdir):
+ testdir.makepyfile("""
+ values = []
+
+ my_setup = 1
+ my_teardown = 2
+
+ def test_hello():
+ assert values == []
+
+ test_hello.setup = my_setup
+ test_hello.teardown = my_teardown
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+
+def test_nose_setup_partial(testdir):
+ pytest.importorskip("functools")
+ p = testdir.makepyfile("""
+ from functools import partial
+
+ values = []
+
+ def my_setup(x):
+ a = x
+ values.append(a)
+
+ def my_teardown(x):
+ b = x
+ values.append(b)
+
+ my_setup_partial = partial(my_setup, 1)
+ my_teardown_partial = partial(my_teardown, 2)
+
+ def test_hello():
+ print (values)
+ assert values == [1]
+
+ def test_world():
+ print (values)
+ assert values == [1,2]
+
+ test_hello.setup = my_setup_partial
+ test_hello.teardown = my_teardown_partial
+ """)
+ result = testdir.runpytest(p, '-p', 'nose')
+ result.stdout.fnmatch_lines([
+ "*2 passed*"
+ ])
+
+
+def test_nose_test_generator_fixtures(testdir):
+ p = testdir.makepyfile("""
+ # taken from nose-0.11.1 unit_tests/test_generator_fixtures.py
+ from nose.tools import eq_
+ called = []
+
+ def outer_setup():
+ called.append('outer_setup')
+
+ def outer_teardown():
+ called.append('outer_teardown')
+
+ def inner_setup():
+ called.append('inner_setup')
+
+ def inner_teardown():
+ called.append('inner_teardown')
+
+ def test_gen():
+ called[:] = []
+ for i in range(0, 5):
+ yield check, i
+
+ def check(i):
+ expect = ['outer_setup']
+ for x in range(0, i):
+ expect.append('inner_setup')
+ expect.append('inner_teardown')
+ expect.append('inner_setup')
+ eq_(called, expect)
+
+
+ test_gen.setup = outer_setup
+ test_gen.teardown = outer_teardown
+ check.setup = inner_setup
+ check.teardown = inner_teardown
+
+ class TestClass(object):
+ def setup(self):
+ print ("setup called in %s" % self)
+ self.called = ['setup']
+
+ def teardown(self):
+ print ("teardown called in %s" % self)
+ eq_(self.called, ['setup'])
+ self.called.append('teardown')
+
+ def test(self):
+ print ("test called in %s" % self)
+ for i in range(0, 5):
+ yield self.check, i
+
+ def check(self, i):
+ print ("check called in %s" % self)
+ expect = ['setup']
+ #for x in range(0, i):
+ # expect.append('setup')
+ # expect.append('teardown')
+ #expect.append('setup')
+ eq_(self.called, expect)
+ """)
+ result = testdir.runpytest(p, '-p', 'nose')
+ result.stdout.fnmatch_lines([
+ "*10 passed*"
+ ])
+
+
+def test_module_level_setup(testdir):
+ testdir.makepyfile("""
+ from nose.tools import with_setup
+ items = {}
+
+ def setup():
+ items[1]=1
+
+ def teardown():
+ del items[1]
+
+ def setup2():
+ items[2] = 2
+
+ def teardown2():
+ del items[2]
+
+ def test_setup_module_setup():
+ assert items[1] == 1
+
+ @with_setup(setup2, teardown2)
+ def test_local_setup():
+ assert items[2] == 2
+ assert 1 not in items
+ """)
+ result = testdir.runpytest('-p', 'nose')
+ result.stdout.fnmatch_lines([
+ "*2 passed*",
+ ])
+
+
+def test_nose_style_setup_teardown(testdir):
+ testdir.makepyfile("""
+ values = []
+
+ def setup_module():
+ values.append(1)
+
+ def teardown_module():
+ del values[0]
+
+ def test_hello():
+ assert values == [1]
+
+ def test_world():
+ assert values == [1]
+ """)
+ result = testdir.runpytest('-p', 'nose')
+ result.stdout.fnmatch_lines([
+ "*2 passed*",
+ ])
+
+
+def test_nose_setup_ordering(testdir):
+ testdir.makepyfile("""
+ def setup_module(mod):
+ mod.visited = True
+
+ class TestClass(object):
+ def setup(self):
+ assert visited
+ def test_first(self):
+ pass
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*1 passed*",
+ ])
+
+
+def test_apiwrapper_problem_issue260(testdir):
+ # this would end up trying a call a optional teardown on the class
+ # for plain unittests we dont want nose behaviour
+ testdir.makepyfile("""
+ import unittest
+ class TestCase(unittest.TestCase):
+ def setup(self):
+ #should not be called in unittest testcases
+ assert 0, 'setup'
+ def teardown(self):
+ #should not be called in unittest testcases
+ assert 0, 'teardown'
+ def setUp(self):
+ print('setup')
+ def tearDown(self):
+ print('teardown')
+ def test_fun(self):
+ pass
+ """)
+ result = testdir.runpytest()
+ result.assert_outcomes(passed=1)
+
+
+def test_setup_teardown_linking_issue265(testdir):
+ # we accidentally didnt integrate nose setupstate with normal setupstate
+ # this test ensures that won't happen again
+ testdir.makepyfile('''
+ import pytest
+
+ class TestGeneric(object):
+ def test_nothing(self):
+ """Tests the API of the implementation (for generic and specialized)."""
+
+ @pytest.mark.skipif("True", reason=
+ "Skip tests to check if teardown is skipped as well.")
+ class TestSkipTeardown(TestGeneric):
+
+ def setup(self):
+ """Sets up my specialized implementation for $COOL_PLATFORM."""
+ raise Exception("should not call setup for skipped tests")
+
+ def teardown(self):
+ """Undoes the setup."""
+ raise Exception("should not call teardown for skipped tests")
+ ''')
+ reprec = testdir.runpytest()
+ reprec.assert_outcomes(passed=1, skipped=1)
+
+
+def test_SkipTest_during_collection(testdir):
+ p = testdir.makepyfile("""
+ import nose
+ raise nose.SkipTest("during collection")
+ def test_failing():
+ assert False
+ """)
+ result = testdir.runpytest(p)
+ result.assert_outcomes(skipped=1)
+
+
+def test_SkipTest_in_test(testdir):
+ testdir.makepyfile("""
+ import nose
+
+ def test_skipping():
+ raise nose.SkipTest("in test")
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(skipped=1)
+
+
+def test_istest_function_decorator(testdir):
+ p = testdir.makepyfile("""
+ import nose.tools
+ @nose.tools.istest
+ def not_test_prefix():
+ pass
+ """)
+ result = testdir.runpytest(p)
+ result.assert_outcomes(passed=1)
+
+
+def test_nottest_function_decorator(testdir):
+ testdir.makepyfile("""
+ import nose.tools
+ @nose.tools.nottest
+ def test_prefix():
+ pass
+ """)
+ reprec = testdir.inline_run()
+ assert not reprec.getfailedcollections()
+ calls = reprec.getreports("pytest_runtest_logreport")
+ assert not calls
+
+
+def test_istest_class_decorator(testdir):
+ p = testdir.makepyfile("""
+ import nose.tools
+ @nose.tools.istest
+ class NotTestPrefix(object):
+ def test_method(self):
+ pass
+ """)
+ result = testdir.runpytest(p)
+ result.assert_outcomes(passed=1)
+
+
+def test_nottest_class_decorator(testdir):
+ testdir.makepyfile("""
+ import nose.tools
+ @nose.tools.nottest
+ class TestPrefix(object):
+ def test_method(self):
+ pass
+ """)
+ reprec = testdir.inline_run()
+ assert not reprec.getfailedcollections()
+ calls = reprec.getreports("pytest_runtest_logreport")
+ assert not calls
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_parseopt.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_parseopt.py
new file mode 100644
index 00000000000..92159257019
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_parseopt.py
@@ -0,0 +1,309 @@
+from __future__ import absolute_import, division, print_function
+import sys
+import os
+import py
+import pytest
+from _pytest import config as parseopt
+
+
+@pytest.fixture
+def parser():
+ return parseopt.Parser()
+
+
+class TestParser(object):
+ def test_no_help_by_default(self, capsys):
+ parser = parseopt.Parser(usage="xyz")
+ pytest.raises(SystemExit, lambda: parser.parse(["-h"]))
+ out, err = capsys.readouterr()
+ assert err.find("error: unrecognized arguments") != -1
+
+ def test_argument(self):
+ with pytest.raises(parseopt.ArgumentError):
+ # need a short or long option
+ argument = parseopt.Argument()
+ argument = parseopt.Argument('-t')
+ assert argument._short_opts == ['-t']
+ assert argument._long_opts == []
+ assert argument.dest == 't'
+ argument = parseopt.Argument('-t', '--test')
+ assert argument._short_opts == ['-t']
+ assert argument._long_opts == ['--test']
+ assert argument.dest == 'test'
+ argument = parseopt.Argument('-t', '--test', dest='abc')
+ assert argument.dest == 'abc'
+ assert str(argument) == (
+ "Argument(_short_opts: ['-t'], _long_opts: ['--test'], dest: 'abc')"
+ )
+
+ def test_argument_type(self):
+ argument = parseopt.Argument('-t', dest='abc', type=int)
+ assert argument.type is int
+ argument = parseopt.Argument('-t', dest='abc', type=str)
+ assert argument.type is str
+ argument = parseopt.Argument('-t', dest='abc', type=float)
+ assert argument.type is float
+ with pytest.warns(DeprecationWarning):
+ with pytest.raises(KeyError):
+ argument = parseopt.Argument('-t', dest='abc', type='choice')
+ argument = parseopt.Argument('-t', dest='abc', type=str,
+ choices=['red', 'blue'])
+ assert argument.type is str
+
+ def test_argument_processopt(self):
+ argument = parseopt.Argument('-t', type=int)
+ argument.default = 42
+ argument.dest = 'abc'
+ res = argument.attrs()
+ assert res['default'] == 42
+ assert res['dest'] == 'abc'
+
+ def test_group_add_and_get(self, parser):
+ group = parser.getgroup("hello", description="desc")
+ assert group.name == "hello"
+ assert group.description == "desc"
+
+ def test_getgroup_simple(self, parser):
+ group = parser.getgroup("hello", description="desc")
+ assert group.name == "hello"
+ assert group.description == "desc"
+ group2 = parser.getgroup("hello")
+ assert group2 is group
+
+ def test_group_ordering(self, parser):
+ parser.getgroup("1")
+ parser.getgroup("2")
+ parser.getgroup("3", after="1")
+ groups = parser._groups
+ groups_names = [x.name for x in groups]
+ assert groups_names == list("132")
+
+ def test_group_addoption(self):
+ group = parseopt.OptionGroup("hello")
+ group.addoption("--option1", action="store_true")
+ assert len(group.options) == 1
+ assert isinstance(group.options[0], parseopt.Argument)
+
+ def test_group_addoption_conflict(self):
+ group = parseopt.OptionGroup("hello again")
+ group.addoption("--option1", "--option-1", action="store_true")
+ with pytest.raises(ValueError) as err:
+ group.addoption("--option1", "--option-one", action="store_true")
+ assert str(set(["--option1"])) in str(err.value)
+
+ def test_group_shortopt_lowercase(self, parser):
+ group = parser.getgroup("hello")
+ pytest.raises(ValueError, """
+ group.addoption("-x", action="store_true")
+ """)
+ assert len(group.options) == 0
+ group._addoption("-x", action="store_true")
+ assert len(group.options) == 1
+
+ def test_parser_addoption(self, parser):
+ group = parser.getgroup("custom options")
+ assert len(group.options) == 0
+ group.addoption("--option1", action="store_true")
+ assert len(group.options) == 1
+
+ def test_parse(self, parser):
+ parser.addoption("--hello", dest="hello", action="store")
+ args = parser.parse(['--hello', 'world'])
+ assert args.hello == "world"
+ assert not getattr(args, parseopt.FILE_OR_DIR)
+
+ def test_parse2(self, parser):
+ args = parser.parse([py.path.local()])
+ assert getattr(args, parseopt.FILE_OR_DIR)[0] == py.path.local()
+
+ def test_parse_known_args(self, parser):
+ parser.parse_known_args([py.path.local()])
+ parser.addoption("--hello", action="store_true")
+ ns = parser.parse_known_args(["x", "--y", "--hello", "this"])
+ assert ns.hello
+ assert ns.file_or_dir == ['x']
+
+ def test_parse_known_and_unknown_args(self, parser):
+ parser.addoption("--hello", action="store_true")
+ ns, unknown = parser.parse_known_and_unknown_args(["x", "--y",
+ "--hello", "this"])
+ assert ns.hello
+ assert ns.file_or_dir == ['x']
+ assert unknown == ['--y', 'this']
+
+ def test_parse_will_set_default(self, parser):
+ parser.addoption("--hello", dest="hello", default="x", action="store")
+ option = parser.parse([])
+ assert option.hello == "x"
+ del option.hello
+ parser.parse_setoption([], option)
+ assert option.hello == "x"
+
+ def test_parse_setoption(self, parser):
+ parser.addoption("--hello", dest="hello", action="store")
+ parser.addoption("--world", dest="world", default=42)
+
+ class A(object):
+ pass
+
+ option = A()
+ args = parser.parse_setoption(['--hello', 'world'], option)
+ assert option.hello == "world"
+ assert option.world == 42
+ assert not args
+
+ def test_parse_special_destination(self, parser):
+ parser.addoption("--ultimate-answer", type=int)
+ args = parser.parse(['--ultimate-answer', '42'])
+ assert args.ultimate_answer == 42
+
+ def test_parse_split_positional_arguments(self, parser):
+ parser.addoption("-R", action='store_true')
+ parser.addoption("-S", action='store_false')
+ args = parser.parse(['-R', '4', '2', '-S'])
+ assert getattr(args, parseopt.FILE_OR_DIR) == ['4', '2']
+ args = parser.parse(['-R', '-S', '4', '2', '-R'])
+ assert getattr(args, parseopt.FILE_OR_DIR) == ['4', '2']
+ assert args.R is True
+ assert args.S is False
+ args = parser.parse(['-R', '4', '-S', '2'])
+ assert getattr(args, parseopt.FILE_OR_DIR) == ['4', '2']
+ assert args.R is True
+ assert args.S is False
+
+ def test_parse_defaultgetter(self):
+ def defaultget(option):
+ if not hasattr(option, 'type'):
+ return
+ if option.type is int:
+ option.default = 42
+ elif option.type is str:
+ option.default = "world"
+ parser = parseopt.Parser(processopt=defaultget)
+ parser.addoption("--this", dest="this", type=int, action="store")
+ parser.addoption("--hello", dest="hello", type=str, action="store")
+ parser.addoption("--no", dest="no", action="store_true")
+ option = parser.parse([])
+ assert option.hello == "world"
+ assert option.this == 42
+ assert option.no is False
+
+ def test_drop_short_helper(self):
+ parser = py.std.argparse.ArgumentParser(formatter_class=parseopt.DropShorterLongHelpFormatter)
+ parser.add_argument('-t', '--twoword', '--duo', '--two-word', '--two',
+ help='foo').map_long_option = {'two': 'two-word'}
+ # throws error on --deux only!
+ parser.add_argument('-d', '--deuxmots', '--deux-mots',
+ action='store_true', help='foo').map_long_option = {'deux': 'deux-mots'}
+ parser.add_argument('-s', action='store_true', help='single short')
+ parser.add_argument('--abc', '-a',
+ action='store_true', help='bar')
+ parser.add_argument('--klm', '-k', '--kl-m',
+ action='store_true', help='bar')
+ parser.add_argument('-P', '--pq-r', '-p', '--pqr',
+ action='store_true', help='bar')
+ parser.add_argument('--zwei-wort', '--zweiwort', '--zweiwort',
+ action='store_true', help='bar')
+ parser.add_argument('-x', '--exit-on-first', '--exitfirst',
+ action='store_true', help='spam').map_long_option = {'exitfirst': 'exit-on-first'}
+ parser.add_argument('files_and_dirs', nargs='*')
+ args = parser.parse_args(['-k', '--duo', 'hallo', '--exitfirst'])
+ assert args.twoword == 'hallo'
+ assert args.klm is True
+ assert args.zwei_wort is False
+ assert args.exit_on_first is True
+ assert args.s is False
+ args = parser.parse_args(['--deux-mots'])
+ with pytest.raises(AttributeError):
+ assert args.deux_mots is True
+ assert args.deuxmots is True
+ args = parser.parse_args(['file', 'dir'])
+ assert '|'.join(args.files_and_dirs) == 'file|dir'
+
+ def test_drop_short_0(self, parser):
+ parser.addoption('--funcarg', '--func-arg', action='store_true')
+ parser.addoption('--abc-def', '--abc-def', action='store_true')
+ parser.addoption('--klm-hij', action='store_true')
+ args = parser.parse(['--funcarg', '--k'])
+ assert args.funcarg is True
+ assert args.abc_def is False
+ assert args.klm_hij is True
+
+ def test_drop_short_2(self, parser):
+ parser.addoption('--func-arg', '--doit', action='store_true')
+ args = parser.parse(['--doit'])
+ assert args.func_arg is True
+
+ def test_drop_short_3(self, parser):
+ parser.addoption('--func-arg', '--funcarg', '--doit', action='store_true')
+ args = parser.parse(['abcd'])
+ assert args.func_arg is False
+ assert args.file_or_dir == ['abcd']
+
+ def test_drop_short_help0(self, parser, capsys):
+ parser.addoption('--func-args', '--doit', help='foo',
+ action='store_true')
+ parser.parse([])
+ help = parser.optparser.format_help()
+ assert '--func-args, --doit foo' in help
+
+ # testing would be more helpful with all help generated
+ def test_drop_short_help1(self, parser, capsys):
+ group = parser.getgroup("general")
+ group.addoption('--doit', '--func-args', action='store_true', help='foo')
+ group._addoption("-h", "--help", action="store_true", dest="help",
+ help="show help message and configuration info")
+ parser.parse(['-h'])
+ help = parser.optparser.format_help()
+ assert '-doit, --func-args foo' in help
+
+ def test_multiple_metavar_help(self, parser):
+ """
+ Help text for options with a metavar tuple should display help
+ in the form "--preferences=value1 value2 value3" (#2004).
+ """
+ group = parser.getgroup("general")
+ group.addoption('--preferences', metavar=('value1', 'value2', 'value3'), nargs=3)
+ group._addoption("-h", "--help", action="store_true", dest="help")
+ parser.parse(['-h'])
+ help = parser.optparser.format_help()
+ assert '--preferences=value1 value2 value3' in help
+
+
+def test_argcomplete(testdir, monkeypatch):
+ if not py.path.local.sysfind('bash'):
+ pytest.skip("bash not available")
+ script = str(testdir.tmpdir.join("test_argcomplete"))
+ pytest_bin = sys.argv[0]
+ if "pytest" not in os.path.basename(pytest_bin):
+ pytest.skip("need to be run with pytest executable, not %s" % (pytest_bin,))
+
+ with open(str(script), 'w') as fp:
+ # redirect output from argcomplete to stdin and stderr is not trivial
+ # http://stackoverflow.com/q/12589419/1307905
+ # so we use bash
+ fp.write('COMP_WORDBREAKS="$COMP_WORDBREAKS" %s 8>&1 9>&2' % pytest_bin)
+ # alternative would be exteneded Testdir.{run(),_run(),popen()} to be able
+ # to handle a keyword argument env that replaces os.environ in popen or
+ # extends the copy, advantage: could not forget to restore
+ monkeypatch.setenv('_ARGCOMPLETE', "1")
+ monkeypatch.setenv('_ARGCOMPLETE_IFS', "\x0b")
+ monkeypatch.setenv('COMP_WORDBREAKS', ' \\t\\n"\\\'><=;|&(:')
+
+ arg = '--fu'
+ monkeypatch.setenv('COMP_LINE', "pytest " + arg)
+ monkeypatch.setenv('COMP_POINT', str(len("pytest " + arg)))
+ result = testdir.run('bash', str(script), arg)
+ if result.ret == 255:
+ # argcomplete not found
+ pytest.skip("argcomplete not available")
+ elif not result.stdout.str():
+ pytest.skip("bash provided no output, argcomplete not available?")
+ else:
+ result.stdout.fnmatch_lines(["--funcargs", "--fulltrace"])
+ os.mkdir('test_argcomplete.d')
+ arg = 'test_argc'
+ monkeypatch.setenv('COMP_LINE', "pytest " + arg)
+ monkeypatch.setenv('COMP_POINT', str(len('pytest ' + arg)))
+ result = testdir.run('bash', str(script), arg)
+ result.stdout.fnmatch_lines(["test_argcomplete", "test_argcomplete.d/"])
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_pastebin.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_pastebin.py
new file mode 100644
index 00000000000..6b1742d1415
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_pastebin.py
@@ -0,0 +1,117 @@
+# encoding: utf-8
+from __future__ import absolute_import, division, print_function
+import sys
+import pytest
+
+
+class TestPasteCapture(object):
+
+ @pytest.fixture
+ def pastebinlist(self, monkeypatch, request):
+ pastebinlist = []
+ plugin = request.config.pluginmanager.getplugin('pastebin')
+ monkeypatch.setattr(plugin, 'create_new_paste', pastebinlist.append)
+ return pastebinlist
+
+ def test_failed(self, testdir, pastebinlist):
+ testpath = testdir.makepyfile("""
+ import pytest
+ def test_pass():
+ pass
+ def test_fail():
+ assert 0
+ def test_skip():
+ pytest.skip("")
+ """)
+ reprec = testdir.inline_run(testpath, "--paste=failed")
+ assert len(pastebinlist) == 1
+ s = pastebinlist[0]
+ assert s.find("def test_fail") != -1
+ assert reprec.countoutcomes() == [1, 1, 1]
+
+ def test_all(self, testdir, pastebinlist):
+ from _pytest.pytester import LineMatcher
+ testpath = testdir.makepyfile("""
+ import pytest
+ def test_pass():
+ pass
+ def test_fail():
+ assert 0
+ def test_skip():
+ pytest.skip("")
+ """)
+ reprec = testdir.inline_run(testpath, "--pastebin=all", '-v')
+ assert reprec.countoutcomes() == [1, 1, 1]
+ assert len(pastebinlist) == 1
+ contents = pastebinlist[0].decode('utf-8')
+ matcher = LineMatcher(contents.splitlines())
+ matcher.fnmatch_lines([
+ '*test_pass PASSED*',
+ '*test_fail FAILED*',
+ '*test_skip SKIPPED*',
+ '*== 1 failed, 1 passed, 1 skipped in *'
+ ])
+
+ def test_non_ascii_paste_text(self, testdir):
+ """Make sure that text which contains non-ascii characters is pasted
+ correctly. See #1219.
+ """
+ testdir.makepyfile(test_unicode="""
+ # encoding: utf-8
+ def test():
+ assert '☺' == 1
+ """)
+ result = testdir.runpytest('--pastebin=all')
+ if sys.version_info[0] == 3:
+ expected_msg = "*assert '☺' == 1*"
+ else:
+ expected_msg = "*assert '\\xe2\\x98\\xba' == 1*"
+ result.stdout.fnmatch_lines([
+ expected_msg,
+ "*== 1 failed in *",
+ '*Sending information to Paste Service*',
+ ])
+
+
+class TestPaste(object):
+
+ @pytest.fixture
+ def pastebin(self, request):
+ return request.config.pluginmanager.getplugin('pastebin')
+
+ @pytest.fixture
+ def mocked_urlopen(self, monkeypatch):
+ """
+ monkeypatch the actual urlopen calls done by the internal plugin
+ function that connects to bpaste service.
+ """
+ calls = []
+
+ def mocked(url, data):
+ calls.append((url, data))
+
+ class DummyFile(object):
+ def read(self):
+ # part of html of a normal response
+ return b'View <a href="/raw/3c0c6750bd">raw</a>.'
+ return DummyFile()
+
+ if sys.version_info < (3, 0):
+ import urllib
+ monkeypatch.setattr(urllib, 'urlopen', mocked)
+ else:
+ import urllib.request
+ monkeypatch.setattr(urllib.request, 'urlopen', mocked)
+ return calls
+
+ def test_create_new_paste(self, pastebin, mocked_urlopen):
+ result = pastebin.create_new_paste(b'full-paste-contents')
+ assert result == 'https://bpaste.net/show/3c0c6750bd'
+ assert len(mocked_urlopen) == 1
+ url, data = mocked_urlopen[0]
+ assert type(data) is bytes
+ lexer = 'python3' if sys.version_info[0] == 3 else 'python'
+ assert url == 'https://bpaste.net'
+ assert 'lexer=%s' % lexer in data.decode()
+ assert 'code=full-paste-contents' in data.decode()
+ assert 'expiry=1week' in data.decode()
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_pdb.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_pdb.py
new file mode 100644
index 00000000000..70a5c3c5bdb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_pdb.py
@@ -0,0 +1,406 @@
+from __future__ import absolute_import, division, print_function
+import sys
+import platform
+
+import _pytest._code
+import pytest
+
+
+def runpdb_and_get_report(testdir, source):
+ p = testdir.makepyfile(source)
+ result = testdir.runpytest_inprocess("--pdb", p)
+ reports = result.reprec.getreports("pytest_runtest_logreport")
+ assert len(reports) == 3, reports # setup/call/teardown
+ return reports[1]
+
+
+@pytest.fixture
+def custom_pdb_calls():
+ called = []
+
+ # install dummy debugger class and track which methods were called on it
+ class _CustomPdb(object):
+ def __init__(self, *args, **kwargs):
+ called.append("init")
+
+ def reset(self):
+ called.append("reset")
+
+ def interaction(self, *args):
+ called.append("interaction")
+
+ _pytest._CustomPdb = _CustomPdb
+ return called
+
+
+class TestPDB(object):
+
+ @pytest.fixture
+ def pdblist(self, request):
+ monkeypatch = request.getfixturevalue("monkeypatch")
+ pdblist = []
+
+ def mypdb(*args):
+ pdblist.append(args)
+
+ plugin = request.config.pluginmanager.getplugin('debugging')
+ monkeypatch.setattr(plugin, 'post_mortem', mypdb)
+ return pdblist
+
+ def test_pdb_on_fail(self, testdir, pdblist):
+ rep = runpdb_and_get_report(testdir, """
+ def test_func():
+ assert 0
+ """)
+ assert rep.failed
+ assert len(pdblist) == 1
+ tb = _pytest._code.Traceback(pdblist[0][0])
+ assert tb[-1].name == "test_func"
+
+ def test_pdb_on_xfail(self, testdir, pdblist):
+ rep = runpdb_and_get_report(testdir, """
+ import pytest
+ @pytest.mark.xfail
+ def test_func():
+ assert 0
+ """)
+ assert "xfail" in rep.keywords
+ assert not pdblist
+
+ def test_pdb_on_skip(self, testdir, pdblist):
+ rep = runpdb_and_get_report(testdir, """
+ import pytest
+ def test_func():
+ pytest.skip("hello")
+ """)
+ assert rep.skipped
+ assert len(pdblist) == 0
+
+ def test_pdb_on_BdbQuit(self, testdir, pdblist):
+ rep = runpdb_and_get_report(testdir, """
+ import bdb
+ def test_func():
+ raise bdb.BdbQuit
+ """)
+ assert rep.failed
+ assert len(pdblist) == 0
+
+ def test_pdb_interaction(self, testdir):
+ p1 = testdir.makepyfile("""
+ def test_1():
+ i = 0
+ assert i == 1
+ """)
+ child = testdir.spawn_pytest("--pdb %s" % p1)
+ child.expect(".*def test_1")
+ child.expect(".*i = 0")
+ child.expect("(Pdb)")
+ child.sendeof()
+ rest = child.read().decode("utf8")
+ assert "1 failed" in rest
+ assert "def test_1" not in rest
+ self.flush(child)
+
+ @staticmethod
+ def flush(child):
+ if platform.system() == 'Darwin':
+ return
+ if child.isalive():
+ child.wait()
+
+ def test_pdb_unittest_postmortem(self, testdir):
+ p1 = testdir.makepyfile("""
+ import unittest
+ class Blub(unittest.TestCase):
+ def tearDown(self):
+ self.filename = None
+ def test_false(self):
+ self.filename = 'debug' + '.me'
+ assert 0
+ """)
+ child = testdir.spawn_pytest("--pdb %s" % p1)
+ child.expect('(Pdb)')
+ child.sendline('p self.filename')
+ child.sendeof()
+ rest = child.read().decode("utf8")
+ assert 'debug.me' in rest
+ self.flush(child)
+
+ def test_pdb_unittest_skip(self, testdir):
+ """Test for issue #2137"""
+ p1 = testdir.makepyfile("""
+ import unittest
+ @unittest.skipIf(True, 'Skipping also with pdb active')
+ class MyTestCase(unittest.TestCase):
+ def test_one(self):
+ assert 0
+ """)
+ child = testdir.spawn_pytest("-rs --pdb %s" % p1)
+ child.expect('Skipping also with pdb active')
+ child.expect('1 skipped in')
+ child.sendeof()
+ self.flush(child)
+
+ def test_pdb_interaction_capture(self, testdir):
+ p1 = testdir.makepyfile("""
+ def test_1():
+ print("getrekt")
+ assert False
+ """)
+ child = testdir.spawn_pytest("--pdb %s" % p1)
+ child.expect("getrekt")
+ child.expect("(Pdb)")
+ child.sendeof()
+ rest = child.read().decode("utf8")
+ assert "1 failed" in rest
+ assert "getrekt" not in rest
+ self.flush(child)
+
+ def test_pdb_interaction_exception(self, testdir):
+ p1 = testdir.makepyfile("""
+ import pytest
+ def globalfunc():
+ pass
+ def test_1():
+ pytest.raises(ValueError, globalfunc)
+ """)
+ child = testdir.spawn_pytest("--pdb %s" % p1)
+ child.expect(".*def test_1")
+ child.expect(".*pytest.raises.*globalfunc")
+ child.expect("(Pdb)")
+ child.sendline("globalfunc")
+ child.expect(".*function")
+ child.sendeof()
+ child.expect("1 failed")
+ self.flush(child)
+
+ def test_pdb_interaction_on_collection_issue181(self, testdir):
+ p1 = testdir.makepyfile("""
+ import pytest
+ xxx
+ """)
+ child = testdir.spawn_pytest("--pdb %s" % p1)
+ # child.expect(".*import pytest.*")
+ child.expect("(Pdb)")
+ child.sendeof()
+ child.expect("1 error")
+ self.flush(child)
+
+ def test_pdb_interaction_on_internal_error(self, testdir):
+ testdir.makeconftest("""
+ def pytest_runtest_protocol():
+ 0/0
+ """)
+ p1 = testdir.makepyfile("def test_func(): pass")
+ child = testdir.spawn_pytest("--pdb %s" % p1)
+ # child.expect(".*import pytest.*")
+ child.expect("(Pdb)")
+ child.sendeof()
+ self.flush(child)
+
+ def test_pdb_interaction_capturing_simple(self, testdir):
+ p1 = testdir.makepyfile("""
+ import pytest
+ def test_1():
+ i = 0
+ print ("hello17")
+ pytest.set_trace()
+ x = 3
+ """)
+ child = testdir.spawn_pytest(str(p1))
+ child.expect("test_1")
+ child.expect("x = 3")
+ child.expect("(Pdb)")
+ child.sendeof()
+ rest = child.read().decode("utf-8")
+ assert "1 failed" in rest
+ assert "def test_1" in rest
+ assert "hello17" in rest # out is captured
+ self.flush(child)
+
+ def test_pdb_set_trace_interception(self, testdir):
+ p1 = testdir.makepyfile("""
+ import pdb
+ def test_1():
+ pdb.set_trace()
+ """)
+ child = testdir.spawn_pytest(str(p1))
+ child.expect("test_1")
+ child.expect("(Pdb)")
+ child.sendeof()
+ rest = child.read().decode("utf8")
+ assert "1 failed" in rest
+ assert "reading from stdin while output" not in rest
+ self.flush(child)
+
+ def test_pdb_and_capsys(self, testdir):
+ p1 = testdir.makepyfile("""
+ import pytest
+ def test_1(capsys):
+ print ("hello1")
+ pytest.set_trace()
+ """)
+ child = testdir.spawn_pytest(str(p1))
+ child.expect("test_1")
+ child.send("capsys.readouterr()\n")
+ child.expect("hello1")
+ child.sendeof()
+ child.read()
+ self.flush(child)
+
+ def test_set_trace_capturing_afterwards(self, testdir):
+ p1 = testdir.makepyfile("""
+ import pdb
+ def test_1():
+ pdb.set_trace()
+ def test_2():
+ print ("hello")
+ assert 0
+ """)
+ child = testdir.spawn_pytest(str(p1))
+ child.expect("test_1")
+ child.send("c\n")
+ child.expect("test_2")
+ child.expect("Captured")
+ child.expect("hello")
+ child.sendeof()
+ child.read()
+ self.flush(child)
+
+ def test_pdb_interaction_doctest(self, testdir):
+ p1 = testdir.makepyfile("""
+ import pytest
+ def function_1():
+ '''
+ >>> i = 0
+ >>> assert i == 1
+ '''
+ """)
+ child = testdir.spawn_pytest("--doctest-modules --pdb %s" % p1)
+ child.expect("(Pdb)")
+ child.sendline('i')
+ child.expect("0")
+ child.expect("(Pdb)")
+ child.sendeof()
+ rest = child.read().decode("utf8")
+ assert "1 failed" in rest
+ self.flush(child)
+
+ def test_pdb_interaction_capturing_twice(self, testdir):
+ p1 = testdir.makepyfile("""
+ import pytest
+ def test_1():
+ i = 0
+ print ("hello17")
+ pytest.set_trace()
+ x = 3
+ print ("hello18")
+ pytest.set_trace()
+ x = 4
+ """)
+ child = testdir.spawn_pytest(str(p1))
+ child.expect("test_1")
+ child.expect("x = 3")
+ child.expect("(Pdb)")
+ child.sendline('c')
+ child.expect("x = 4")
+ child.sendeof()
+ rest = child.read().decode("utf8")
+ assert "1 failed" in rest
+ assert "def test_1" in rest
+ assert "hello17" in rest # out is captured
+ assert "hello18" in rest # out is captured
+ self.flush(child)
+
+ def test_pdb_used_outside_test(self, testdir):
+ p1 = testdir.makepyfile("""
+ import pytest
+ pytest.set_trace()
+ x = 5
+ """)
+ child = testdir.spawn("%s %s" % (sys.executable, p1))
+ child.expect("x = 5")
+ child.sendeof()
+ self.flush(child)
+
+ def test_pdb_used_in_generate_tests(self, testdir):
+ p1 = testdir.makepyfile("""
+ import pytest
+ def pytest_generate_tests(metafunc):
+ pytest.set_trace()
+ x = 5
+ def test_foo(a):
+ pass
+ """)
+ child = testdir.spawn_pytest(str(p1))
+ child.expect("x = 5")
+ child.sendeof()
+ self.flush(child)
+
+ def test_pdb_collection_failure_is_shown(self, testdir):
+ p1 = testdir.makepyfile("""xxx """)
+ result = testdir.runpytest_subprocess("--pdb", p1)
+ result.stdout.fnmatch_lines([
+ "*NameError*xxx*",
+ "*1 error*",
+ ])
+
+ def test_enter_pdb_hook_is_called(self, testdir):
+ testdir.makeconftest("""
+ def pytest_enter_pdb(config):
+ assert config.testing_verification == 'configured'
+ print 'enter_pdb_hook'
+
+ def pytest_configure(config):
+ config.testing_verification = 'configured'
+ """)
+ p1 = testdir.makepyfile("""
+ import pytest
+
+ def test_foo():
+ pytest.set_trace()
+ """)
+ child = testdir.spawn_pytest(str(p1))
+ child.expect("enter_pdb_hook")
+ child.send('c\n')
+ child.sendeof()
+ self.flush(child)
+
+ def test_pdb_custom_cls(self, testdir, custom_pdb_calls):
+ p1 = testdir.makepyfile("""xxx """)
+ result = testdir.runpytest_inprocess(
+ "--pdb", "--pdbcls=_pytest:_CustomPdb", p1)
+ result.stdout.fnmatch_lines([
+ "*NameError*xxx*",
+ "*1 error*",
+ ])
+ assert custom_pdb_calls == ["init", "reset", "interaction"]
+
+ def test_pdb_custom_cls_without_pdb(self, testdir, custom_pdb_calls):
+ p1 = testdir.makepyfile("""xxx """)
+ result = testdir.runpytest_inprocess(
+ "--pdbcls=_pytest:_CustomPdb", p1)
+ result.stdout.fnmatch_lines([
+ "*NameError*xxx*",
+ "*1 error*",
+ ])
+ assert custom_pdb_calls == []
+
+ def test_pdb_custom_cls_with_settrace(self, testdir, monkeypatch):
+ testdir.makepyfile(custom_pdb="""
+ class CustomPdb(object):
+ def set_trace(*args, **kwargs):
+ print 'custom set_trace>'
+ """)
+ p1 = testdir.makepyfile("""
+ import pytest
+
+ def test_foo():
+ pytest.set_trace()
+ """)
+ monkeypatch.setenv('PYTHONPATH', str(testdir.tmpdir))
+ child = testdir.spawn_pytest("--pdbcls=custom_pdb:CustomPdb %s" % str(p1))
+
+ child.expect('custom set_trace>')
+ if child.isalive():
+ child.wait()
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_pluginmanager.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_pluginmanager.py
new file mode 100644
index 00000000000..6192176e8a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_pluginmanager.py
@@ -0,0 +1,361 @@
+# encoding: UTF-8
+from __future__ import absolute_import, division, print_function
+import pytest
+import py
+import os
+
+from _pytest.config import get_config, PytestPluginManager
+from _pytest.main import EXIT_NOTESTSCOLLECTED, Session
+
+
+@pytest.fixture
+def pytestpm():
+ return PytestPluginManager()
+
+
+class TestPytestPluginInteractions(object):
+ def test_addhooks_conftestplugin(self, testdir):
+ testdir.makepyfile(newhooks="""
+ def pytest_myhook(xyz):
+ "new hook"
+ """)
+ conf = testdir.makeconftest("""
+ import sys ; sys.path.insert(0, '.')
+ import newhooks
+ def pytest_addhooks(pluginmanager):
+ pluginmanager.addhooks(newhooks)
+ def pytest_myhook(xyz):
+ return xyz + 1
+ """)
+ config = get_config()
+ pm = config.pluginmanager
+ pm.hook.pytest_addhooks.call_historic(
+ kwargs=dict(pluginmanager=config.pluginmanager))
+ config.pluginmanager._importconftest(conf)
+ # print(config.pluginmanager.get_plugins())
+ res = config.hook.pytest_myhook(xyz=10)
+ assert res == [11]
+
+ def test_addhooks_nohooks(self, testdir):
+ testdir.makeconftest("""
+ import sys
+ def pytest_addhooks(pluginmanager):
+ pluginmanager.addhooks(sys)
+ """)
+ res = testdir.runpytest()
+ assert res.ret != 0
+ res.stderr.fnmatch_lines([
+ "*did not find*sys*"
+ ])
+
+ def test_namespace_early_from_import(self, testdir):
+ p = testdir.makepyfile("""
+ from pytest import Item
+ from pytest import Item as Item2
+ assert Item is Item2
+ """)
+ result = testdir.runpython(p)
+ assert result.ret == 0
+
+ def test_do_ext_namespace(self, testdir):
+ testdir.makeconftest("""
+ def pytest_namespace():
+ return {'hello': 'world'}
+ """)
+ p = testdir.makepyfile("""
+ from pytest import hello
+ import pytest
+ def test_hello():
+ assert hello == "world"
+ assert 'hello' in pytest.__all__
+ """)
+ reprec = testdir.inline_run(p)
+ reprec.assertoutcome(passed=1)
+
+ def test_do_option_postinitialize(self, testdir):
+ config = testdir.parseconfigure()
+ assert not hasattr(config.option, 'test123')
+ p = testdir.makepyfile("""
+ def pytest_addoption(parser):
+ parser.addoption('--test123', action="store_true",
+ default=True)
+ """)
+ config.pluginmanager._importconftest(p)
+ assert config.option.test123
+
+ def test_configure(self, testdir):
+ config = testdir.parseconfig()
+ values = []
+
+ class A(object):
+ def pytest_configure(self, config):
+ values.append(self)
+
+ config.pluginmanager.register(A())
+ assert len(values) == 0
+ config._do_configure()
+ assert len(values) == 1
+ config.pluginmanager.register(A()) # leads to a configured() plugin
+ assert len(values) == 2
+ assert values[0] != values[1]
+
+ config._ensure_unconfigure()
+ config.pluginmanager.register(A())
+ assert len(values) == 2
+
+ def test_hook_tracing(self):
+ pytestpm = get_config().pluginmanager # fully initialized with plugins
+ saveindent = []
+
+ class api1(object):
+ def pytest_plugin_registered(self):
+ saveindent.append(pytestpm.trace.root.indent)
+
+ class api2(object):
+ def pytest_plugin_registered(self):
+ saveindent.append(pytestpm.trace.root.indent)
+ raise ValueError()
+
+ values = []
+ pytestpm.trace.root.setwriter(values.append)
+ undo = pytestpm.enable_tracing()
+ try:
+ indent = pytestpm.trace.root.indent
+ p = api1()
+ pytestpm.register(p)
+ assert pytestpm.trace.root.indent == indent
+ assert len(values) >= 2
+ assert 'pytest_plugin_registered' in values[0]
+ assert 'finish' in values[1]
+
+ values[:] = []
+ with pytest.raises(ValueError):
+ pytestpm.register(api2())
+ assert pytestpm.trace.root.indent == indent
+ assert saveindent[0] > indent
+ finally:
+ undo()
+
+ def test_hook_proxy(self, testdir):
+ """Test the gethookproxy function(#2016)"""
+ config = testdir.parseconfig()
+ session = Session(config)
+ testdir.makepyfile(**{
+ 'tests/conftest.py': '',
+ 'tests/subdir/conftest.py': '',
+ })
+
+ conftest1 = testdir.tmpdir.join('tests/conftest.py')
+ conftest2 = testdir.tmpdir.join('tests/subdir/conftest.py')
+
+ config.pluginmanager._importconftest(conftest1)
+ ihook_a = session.gethookproxy(testdir.tmpdir.join('tests'))
+ assert ihook_a is not None
+ config.pluginmanager._importconftest(conftest2)
+ ihook_b = session.gethookproxy(testdir.tmpdir.join('tests'))
+ assert ihook_a is not ihook_b
+
+ def test_warn_on_deprecated_addhooks(self, pytestpm):
+ warnings = []
+
+ class get_warnings(object):
+ def pytest_logwarning(self, code, fslocation, message, nodeid):
+ warnings.append(message)
+
+ class Plugin(object):
+ def pytest_testhook():
+ pass
+
+ pytestpm.register(get_warnings())
+ before = list(warnings)
+ pytestpm.addhooks(Plugin())
+ assert len(warnings) == len(before) + 1
+ assert "deprecated" in warnings[-1]
+
+
+def test_namespace_has_default_and_env_plugins(testdir):
+ p = testdir.makepyfile("""
+ import pytest
+ pytest.mark
+ """)
+ result = testdir.runpython(p)
+ assert result.ret == 0
+
+
+def test_default_markers(testdir):
+ result = testdir.runpytest("--markers")
+ result.stdout.fnmatch_lines([
+ "*tryfirst*first*",
+ "*trylast*last*",
+ ])
+
+
+def test_importplugin_error_message(testdir, pytestpm):
+ """Don't hide import errors when importing plugins and provide
+ an easy to debug message.
+
+ See #375 and #1998.
+ """
+ testdir.syspathinsert(testdir.tmpdir)
+ testdir.makepyfile(qwe="""
+ # encoding: UTF-8
+ def test_traceback():
+ raise ImportError(u'Not possible to import: ☺')
+ test_traceback()
+ """)
+ with pytest.raises(ImportError) as excinfo:
+ pytestpm.import_plugin("qwe")
+
+ expected_message = '.*Error importing plugin "qwe": Not possible to import: .'
+ expected_traceback = ".*in test_traceback"
+ assert py.std.re.match(expected_message, str(excinfo.value))
+ assert py.std.re.match(expected_traceback, str(excinfo.traceback[-1]))
+
+
+class TestPytestPluginManager(object):
+ def test_register_imported_modules(self):
+ pm = PytestPluginManager()
+ mod = py.std.types.ModuleType("x.y.pytest_hello")
+ pm.register(mod)
+ assert pm.is_registered(mod)
+ values = pm.get_plugins()
+ assert mod in values
+ pytest.raises(ValueError, "pm.register(mod)")
+ pytest.raises(ValueError, lambda: pm.register(mod))
+ # assert not pm.is_registered(mod2)
+ assert pm.get_plugins() == values
+
+ def test_canonical_import(self, monkeypatch):
+ mod = py.std.types.ModuleType("pytest_xyz")
+ monkeypatch.setitem(py.std.sys.modules, 'pytest_xyz', mod)
+ pm = PytestPluginManager()
+ pm.import_plugin('pytest_xyz')
+ assert pm.get_plugin('pytest_xyz') == mod
+ assert pm.is_registered(mod)
+
+ def test_consider_module(self, testdir, pytestpm):
+ testdir.syspathinsert()
+ testdir.makepyfile(pytest_p1="#")
+ testdir.makepyfile(pytest_p2="#")
+ mod = py.std.types.ModuleType("temp")
+ mod.pytest_plugins = ["pytest_p1", "pytest_p2"]
+ pytestpm.consider_module(mod)
+ assert pytestpm.get_plugin("pytest_p1").__name__ == "pytest_p1"
+ assert pytestpm.get_plugin("pytest_p2").__name__ == "pytest_p2"
+
+ def test_consider_module_import_module(self, testdir):
+ pytestpm = get_config().pluginmanager
+ mod = py.std.types.ModuleType("x")
+ mod.pytest_plugins = "pytest_a"
+ aplugin = testdir.makepyfile(pytest_a="#")
+ reprec = testdir.make_hook_recorder(pytestpm)
+ # syspath.prepend(aplugin.dirpath())
+ py.std.sys.path.insert(0, str(aplugin.dirpath()))
+ pytestpm.consider_module(mod)
+ call = reprec.getcall(pytestpm.hook.pytest_plugin_registered.name)
+ assert call.plugin.__name__ == "pytest_a"
+
+ # check that it is not registered twice
+ pytestpm.consider_module(mod)
+ values = reprec.getcalls("pytest_plugin_registered")
+ assert len(values) == 1
+
+ def test_consider_env_fails_to_import(self, monkeypatch, pytestpm):
+ monkeypatch.setenv('PYTEST_PLUGINS', 'nonexisting', prepend=",")
+ with pytest.raises(ImportError):
+ pytestpm.consider_env()
+
+ def test_plugin_skip(self, testdir, monkeypatch):
+ p = testdir.makepyfile(skipping1="""
+ import pytest
+ pytest.skip("hello")
+ """)
+ p.copy(p.dirpath("skipping2.py"))
+ monkeypatch.setenv("PYTEST_PLUGINS", "skipping2")
+ result = testdir.runpytest("-rw", "-p", "skipping1", syspathinsert=True)
+ assert result.ret == EXIT_NOTESTSCOLLECTED
+ result.stdout.fnmatch_lines([
+ "*skipped plugin*skipping1*hello*",
+ "*skipped plugin*skipping2*hello*",
+ ])
+
+ def test_consider_env_plugin_instantiation(self, testdir, monkeypatch, pytestpm):
+ testdir.syspathinsert()
+ testdir.makepyfile(xy123="#")
+ monkeypatch.setitem(os.environ, 'PYTEST_PLUGINS', 'xy123')
+ l1 = len(pytestpm.get_plugins())
+ pytestpm.consider_env()
+ l2 = len(pytestpm.get_plugins())
+ assert l2 == l1 + 1
+ assert pytestpm.get_plugin('xy123')
+ pytestpm.consider_env()
+ l3 = len(pytestpm.get_plugins())
+ assert l2 == l3
+
+ def test_pluginmanager_ENV_startup(self, testdir, monkeypatch):
+ testdir.makepyfile(pytest_x500="#")
+ p = testdir.makepyfile("""
+ import pytest
+ def test_hello(pytestconfig):
+ plugin = pytestconfig.pluginmanager.get_plugin('pytest_x500')
+ assert plugin is not None
+ """)
+ monkeypatch.setenv('PYTEST_PLUGINS', 'pytest_x500', prepend=",")
+ result = testdir.runpytest(p, syspathinsert=True)
+ assert result.ret == 0
+ result.stdout.fnmatch_lines(["*1 passed*"])
+
+ def test_import_plugin_importname(self, testdir, pytestpm):
+ pytest.raises(ImportError, 'pytestpm.import_plugin("qweqwex.y")')
+ pytest.raises(ImportError, 'pytestpm.import_plugin("pytest_qweqwx.y")')
+
+ testdir.syspathinsert()
+ pluginname = "pytest_hello"
+ testdir.makepyfile(**{pluginname: ""})
+ pytestpm.import_plugin("pytest_hello")
+ len1 = len(pytestpm.get_plugins())
+ pytestpm.import_plugin("pytest_hello")
+ len2 = len(pytestpm.get_plugins())
+ assert len1 == len2
+ plugin1 = pytestpm.get_plugin("pytest_hello")
+ assert plugin1.__name__.endswith('pytest_hello')
+ plugin2 = pytestpm.get_plugin("pytest_hello")
+ assert plugin2 is plugin1
+
+ def test_import_plugin_dotted_name(self, testdir, pytestpm):
+ pytest.raises(ImportError, 'pytestpm.import_plugin("qweqwex.y")')
+ pytest.raises(ImportError, 'pytestpm.import_plugin("pytest_qweqwex.y")')
+
+ testdir.syspathinsert()
+ testdir.mkpydir("pkg").join("plug.py").write("x=3")
+ pluginname = "pkg.plug"
+ pytestpm.import_plugin(pluginname)
+ mod = pytestpm.get_plugin("pkg.plug")
+ assert mod.x == 3
+
+ def test_consider_conftest_deps(self, testdir, pytestpm):
+ mod = testdir.makepyfile("pytest_plugins='xyz'").pyimport()
+ with pytest.raises(ImportError):
+ pytestpm.consider_conftest(mod)
+
+
+class TestPytestPluginManagerBootstrapming(object):
+ def test_preparse_args(self, pytestpm):
+ pytest.raises(ImportError, lambda:
+ pytestpm.consider_preparse(["xyz", "-p", "hello123"]))
+
+ def test_plugin_prevent_register(self, pytestpm):
+ pytestpm.consider_preparse(["xyz", "-p", "no:abc"])
+ l1 = pytestpm.get_plugins()
+ pytestpm.register(42, name="abc")
+ l2 = pytestpm.get_plugins()
+ assert len(l2) == len(l1)
+ assert 42 not in l2
+
+ def test_plugin_prevent_register_unregistered_alredy_registered(self, pytestpm):
+ pytestpm.register(42, name="abc")
+ l1 = pytestpm.get_plugins()
+ assert 42 in l1
+ pytestpm.consider_preparse(["xyz", "-p", "no:abc"])
+ l2 = pytestpm.get_plugins()
+ assert 42 not in l2
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_pytester.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_pytester.py
new file mode 100644
index 00000000000..9508c2954e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_pytester.py
@@ -0,0 +1,149 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import, division, print_function
+import pytest
+import os
+from _pytest.pytester import HookRecorder
+from _pytest.config import PytestPluginManager
+from _pytest.main import EXIT_OK, EXIT_TESTSFAILED
+
+
+def test_make_hook_recorder(testdir):
+ item = testdir.getitem("def test_func(): pass")
+ recorder = testdir.make_hook_recorder(item.config.pluginmanager)
+ assert not recorder.getfailures()
+
+ pytest.xfail("internal reportrecorder tests need refactoring")
+
+ class rep(object):
+ excinfo = None
+ passed = False
+ failed = True
+ skipped = False
+ when = "call"
+
+ recorder.hook.pytest_runtest_logreport(report=rep)
+ failures = recorder.getfailures()
+ assert failures == [rep]
+ failures = recorder.getfailures()
+ assert failures == [rep]
+
+ class rep(object):
+ excinfo = None
+ passed = False
+ failed = False
+ skipped = True
+ when = "call"
+ rep.passed = False
+ rep.skipped = True
+ recorder.hook.pytest_runtest_logreport(report=rep)
+
+ modcol = testdir.getmodulecol("")
+ rep = modcol.config.hook.pytest_make_collect_report(collector=modcol)
+ rep.passed = False
+ rep.failed = True
+ rep.skipped = False
+ recorder.hook.pytest_collectreport(report=rep)
+
+ passed, skipped, failed = recorder.listoutcomes()
+ assert not passed and skipped and failed
+
+ numpassed, numskipped, numfailed = recorder.countoutcomes()
+ assert numpassed == 0
+ assert numskipped == 1
+ assert numfailed == 1
+ assert len(recorder.getfailedcollections()) == 1
+
+ recorder.unregister()
+ recorder.clear()
+ recorder.hook.pytest_runtest_logreport(report=rep)
+ pytest.raises(ValueError, "recorder.getfailures()")
+
+
+def test_parseconfig(testdir):
+ config1 = testdir.parseconfig()
+ config2 = testdir.parseconfig()
+ assert config2 != config1
+ assert config1 != pytest.config
+
+
+def test_testdir_runs_with_plugin(testdir):
+ testdir.makepyfile("""
+ pytest_plugins = "pytester"
+ def test_hello(testdir):
+ assert 1
+ """)
+ result = testdir.runpytest()
+ result.assert_outcomes(passed=1)
+
+
+def make_holder():
+ class apiclass(object):
+ def pytest_xyz(self, arg):
+ "x"
+
+ def pytest_xyz_noarg(self):
+ "x"
+
+ apimod = type(os)('api')
+
+ def pytest_xyz(arg):
+ "x"
+
+ def pytest_xyz_noarg():
+ "x"
+
+ apimod.pytest_xyz = pytest_xyz
+ apimod.pytest_xyz_noarg = pytest_xyz_noarg
+ return apiclass, apimod
+
+
+@pytest.mark.parametrize("holder", make_holder())
+def test_hookrecorder_basic(holder):
+ pm = PytestPluginManager()
+ pm.addhooks(holder)
+ rec = HookRecorder(pm)
+ pm.hook.pytest_xyz(arg=123)
+ call = rec.popcall("pytest_xyz")
+ assert call.arg == 123
+ assert call._name == "pytest_xyz"
+ pytest.raises(pytest.fail.Exception, "rec.popcall('abc')")
+ pm.hook.pytest_xyz_noarg()
+ call = rec.popcall("pytest_xyz_noarg")
+ assert call._name == "pytest_xyz_noarg"
+
+
+def test_makepyfile_unicode(testdir):
+ global unichr
+ try:
+ unichr(65)
+ except NameError:
+ unichr = chr
+ testdir.makepyfile(unichr(0xfffd))
+
+
+def test_makepyfile_utf8(testdir):
+ """Ensure makepyfile accepts utf-8 bytes as input (#2738)"""
+ utf8_contents = u"""
+ def setup_function(function):
+ mixed_encoding = u'São Paulo'
+ """.encode('utf-8')
+ p = testdir.makepyfile(utf8_contents)
+ assert u"mixed_encoding = u'São Paulo'".encode('utf-8') in p.read('rb')
+
+
+def test_inline_run_clean_modules(testdir):
+ test_mod = testdir.makepyfile("def test_foo(): assert True")
+ result = testdir.inline_run(str(test_mod))
+ assert result.ret == EXIT_OK
+ # rewrite module, now test should fail if module was re-imported
+ test_mod.write("def test_foo(): assert False")
+ result2 = testdir.inline_run(str(test_mod))
+ assert result2.ret == EXIT_TESTSFAILED
+
+
+def test_assert_outcomes_after_pytest_erro(testdir):
+ testdir.makepyfile("def test_foo(): assert True")
+
+ result = testdir.runpytest('--unexpected-argument')
+ with pytest.raises(ValueError, message="Pytest terminal report not found"):
+ result.assert_outcomes(passed=0)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_recwarn.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_recwarn.py
new file mode 100644
index 00000000000..31e70460fe4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_recwarn.py
@@ -0,0 +1,310 @@
+from __future__ import absolute_import, division, print_function
+import warnings
+import re
+import py
+
+import pytest
+from _pytest.recwarn import WarningsRecorder
+
+
+def test_recwarn_functional(testdir):
+ reprec = testdir.inline_runsource("""
+ import warnings
+ def test_method(recwarn):
+ warnings.warn("hello")
+ warn = recwarn.pop()
+ assert isinstance(warn.message, UserWarning)
+ """)
+ res = reprec.countoutcomes()
+ assert tuple(res) == (1, 0, 0), res
+
+
+class TestWarningsRecorderChecker(object):
+ def test_recording(self):
+ rec = WarningsRecorder()
+ with rec:
+ assert not rec.list
+ py.std.warnings.warn_explicit("hello", UserWarning, "xyz", 13)
+ assert len(rec.list) == 1
+ py.std.warnings.warn(DeprecationWarning("hello"))
+ assert len(rec.list) == 2
+ warn = rec.pop()
+ assert str(warn.message) == "hello"
+ values = rec.list
+ rec.clear()
+ assert len(rec.list) == 0
+ assert values is rec.list
+ pytest.raises(AssertionError, "rec.pop()")
+
+ def test_typechecking(self):
+ from _pytest.recwarn import WarningsChecker
+ with pytest.raises(TypeError):
+ WarningsChecker(5)
+ with pytest.raises(TypeError):
+ WarningsChecker(('hi', RuntimeWarning))
+ with pytest.raises(TypeError):
+ WarningsChecker([DeprecationWarning, RuntimeWarning])
+
+ def test_invalid_enter_exit(self):
+ # wrap this test in WarningsRecorder to ensure warning state gets reset
+ with WarningsRecorder():
+ with pytest.raises(RuntimeError):
+ rec = WarningsRecorder()
+ rec.__exit__(None, None, None) # can't exit before entering
+
+ with pytest.raises(RuntimeError):
+ rec = WarningsRecorder()
+ with rec:
+ with rec:
+ pass # can't enter twice
+
+
+class TestDeprecatedCall(object):
+ """test pytest.deprecated_call()"""
+
+ def dep(self, i, j=None):
+ if i == 0:
+ py.std.warnings.warn("is deprecated", DeprecationWarning,
+ stacklevel=1)
+ return 42
+
+ def dep_explicit(self, i):
+ if i == 0:
+ py.std.warnings.warn_explicit("dep_explicit", category=DeprecationWarning,
+ filename="hello", lineno=3)
+
+ def test_deprecated_call_raises(self):
+ with pytest.raises(AssertionError) as excinfo:
+ pytest.deprecated_call(self.dep, 3, 5)
+ assert 'Did not produce' in str(excinfo)
+
+ def test_deprecated_call(self):
+ pytest.deprecated_call(self.dep, 0, 5)
+
+ def test_deprecated_call_ret(self):
+ ret = pytest.deprecated_call(self.dep, 0)
+ assert ret == 42
+
+ def test_deprecated_call_preserves(self):
+ onceregistry = py.std.warnings.onceregistry.copy()
+ filters = py.std.warnings.filters[:]
+ warn = py.std.warnings.warn
+ warn_explicit = py.std.warnings.warn_explicit
+ self.test_deprecated_call_raises()
+ self.test_deprecated_call()
+ assert onceregistry == py.std.warnings.onceregistry
+ assert filters == py.std.warnings.filters
+ assert warn is py.std.warnings.warn
+ assert warn_explicit is py.std.warnings.warn_explicit
+
+ def test_deprecated_explicit_call_raises(self):
+ with pytest.raises(AssertionError):
+ pytest.deprecated_call(self.dep_explicit, 3)
+
+ def test_deprecated_explicit_call(self):
+ pytest.deprecated_call(self.dep_explicit, 0)
+ pytest.deprecated_call(self.dep_explicit, 0)
+
+ @pytest.mark.parametrize('mode', ['context_manager', 'call'])
+ def test_deprecated_call_no_warning(self, mode):
+ """Ensure deprecated_call() raises the expected failure when its block/function does
+ not raise a deprecation warning.
+ """
+ def f():
+ pass
+
+ msg = 'Did not produce DeprecationWarning or PendingDeprecationWarning'
+ with pytest.raises(AssertionError, matches=msg):
+ if mode == 'call':
+ pytest.deprecated_call(f)
+ else:
+ with pytest.deprecated_call():
+ f()
+
+ @pytest.mark.parametrize('warning_type', [PendingDeprecationWarning, DeprecationWarning])
+ @pytest.mark.parametrize('mode', ['context_manager', 'call'])
+ @pytest.mark.parametrize('call_f_first', [True, False])
+ @pytest.mark.filterwarnings('ignore')
+ def test_deprecated_call_modes(self, warning_type, mode, call_f_first):
+ """Ensure deprecated_call() captures a deprecation warning as expected inside its
+ block/function.
+ """
+ def f():
+ warnings.warn(warning_type("hi"))
+ return 10
+
+ # ensure deprecated_call() can capture the warning even if it has already been triggered
+ if call_f_first:
+ assert f() == 10
+ if mode == 'call':
+ assert pytest.deprecated_call(f) == 10
+ else:
+ with pytest.deprecated_call():
+ assert f() == 10
+
+ @pytest.mark.parametrize('mode', ['context_manager', 'call'])
+ def test_deprecated_call_exception_is_raised(self, mode):
+ """If the block of the code being tested by deprecated_call() raises an exception,
+ it must raise the exception undisturbed.
+ """
+ def f():
+ raise ValueError('some exception')
+
+ with pytest.raises(ValueError, match='some exception'):
+ if mode == 'call':
+ pytest.deprecated_call(f)
+ else:
+ with pytest.deprecated_call():
+ f()
+
+ def test_deprecated_call_specificity(self):
+ other_warnings = [Warning, UserWarning, SyntaxWarning, RuntimeWarning,
+ FutureWarning, ImportWarning, UnicodeWarning]
+ for warning in other_warnings:
+ def f():
+ warnings.warn(warning("hi"))
+
+ with pytest.raises(AssertionError):
+ pytest.deprecated_call(f)
+ with pytest.raises(AssertionError):
+ with pytest.deprecated_call():
+ f()
+
+
+class TestWarns(object):
+ def test_strings(self):
+ # different messages, b/c Python suppresses multiple identical warnings
+ source1 = "warnings.warn('w1', RuntimeWarning)"
+ source2 = "warnings.warn('w2', RuntimeWarning)"
+ source3 = "warnings.warn('w3', RuntimeWarning)"
+ pytest.warns(RuntimeWarning, source1)
+ pytest.raises(pytest.fail.Exception,
+ lambda: pytest.warns(UserWarning, source2))
+ pytest.warns(RuntimeWarning, source3)
+
+ def test_function(self):
+ pytest.warns(SyntaxWarning,
+ lambda msg: warnings.warn(msg, SyntaxWarning), "syntax")
+
+ def test_warning_tuple(self):
+ pytest.warns((RuntimeWarning, SyntaxWarning),
+ lambda: warnings.warn('w1', RuntimeWarning))
+ pytest.warns((RuntimeWarning, SyntaxWarning),
+ lambda: warnings.warn('w2', SyntaxWarning))
+ pytest.raises(pytest.fail.Exception,
+ lambda: pytest.warns(
+ (RuntimeWarning, SyntaxWarning),
+ lambda: warnings.warn('w3', UserWarning)))
+
+ def test_as_contextmanager(self):
+ with pytest.warns(RuntimeWarning):
+ warnings.warn("runtime", RuntimeWarning)
+
+ with pytest.warns(UserWarning):
+ warnings.warn("user", UserWarning)
+
+ with pytest.raises(pytest.fail.Exception) as excinfo:
+ with pytest.warns(RuntimeWarning):
+ warnings.warn("user", UserWarning)
+ excinfo.match(r"DID NOT WARN. No warnings of type \(.+RuntimeWarning.+,\) was emitted. "
+ r"The list of emitted warnings is: \[UserWarning\('user',\)\].")
+
+ with pytest.raises(pytest.fail.Exception) as excinfo:
+ with pytest.warns(UserWarning):
+ warnings.warn("runtime", RuntimeWarning)
+ excinfo.match(r"DID NOT WARN. No warnings of type \(.+UserWarning.+,\) was emitted. "
+ r"The list of emitted warnings is: \[RuntimeWarning\('runtime',\)\].")
+
+ with pytest.raises(pytest.fail.Exception) as excinfo:
+ with pytest.warns(UserWarning):
+ pass
+ excinfo.match(r"DID NOT WARN. No warnings of type \(.+UserWarning.+,\) was emitted. "
+ r"The list of emitted warnings is: \[\].")
+
+ warning_classes = (UserWarning, FutureWarning)
+ with pytest.raises(pytest.fail.Exception) as excinfo:
+ with pytest.warns(warning_classes) as warninfo:
+ warnings.warn("runtime", RuntimeWarning)
+ warnings.warn("import", ImportWarning)
+
+ message_template = ("DID NOT WARN. No warnings of type {0} was emitted. "
+ "The list of emitted warnings is: {1}.")
+ excinfo.match(re.escape(message_template.format(warning_classes,
+ [each.message for each in warninfo])))
+
+ def test_record(self):
+ with pytest.warns(UserWarning) as record:
+ warnings.warn("user", UserWarning)
+
+ assert len(record) == 1
+ assert str(record[0].message) == "user"
+
+ def test_record_only(self):
+ with pytest.warns(None) as record:
+ warnings.warn("user", UserWarning)
+ warnings.warn("runtime", RuntimeWarning)
+
+ assert len(record) == 2
+ assert str(record[0].message) == "user"
+ assert str(record[1].message) == "runtime"
+
+ def test_record_by_subclass(self):
+ with pytest.warns(Warning) as record:
+ warnings.warn("user", UserWarning)
+ warnings.warn("runtime", RuntimeWarning)
+
+ assert len(record) == 2
+ assert str(record[0].message) == "user"
+ assert str(record[1].message) == "runtime"
+
+ class MyUserWarning(UserWarning):
+ pass
+
+ class MyRuntimeWarning(RuntimeWarning):
+ pass
+
+ with pytest.warns((UserWarning, RuntimeWarning)) as record:
+ warnings.warn("user", MyUserWarning)
+ warnings.warn("runtime", MyRuntimeWarning)
+
+ assert len(record) == 2
+ assert str(record[0].message) == "user"
+ assert str(record[1].message) == "runtime"
+
+ def test_double_test(self, testdir):
+ """If a test is run again, the warning should still be raised"""
+ testdir.makepyfile('''
+ import pytest
+ import warnings
+
+ @pytest.mark.parametrize('run', [1, 2])
+ def test(run):
+ with pytest.warns(RuntimeWarning):
+ warnings.warn("runtime", RuntimeWarning)
+ ''')
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(['*2 passed in*'])
+
+ def test_match_regex(self):
+ with pytest.warns(UserWarning, match=r'must be \d+$'):
+ warnings.warn("value must be 42", UserWarning)
+
+ with pytest.raises(pytest.fail.Exception):
+ with pytest.warns(UserWarning, match=r'must be \d+$'):
+ warnings.warn("this is not here", UserWarning)
+
+ with pytest.raises(pytest.fail.Exception):
+ with pytest.warns(FutureWarning, match=r'must be \d+$'):
+ warnings.warn("value must be 42", UserWarning)
+
+ def test_one_from_multiple_warns(self):
+ with pytest.warns(UserWarning, match=r'aaa'):
+ warnings.warn("cccccccccc", UserWarning)
+ warnings.warn("bbbbbbbbbb", UserWarning)
+ warnings.warn("aaaaaaaaaa", UserWarning)
+
+ def test_none_of_multiple_warns(self):
+ with pytest.raises(pytest.fail.Exception):
+ with pytest.warns(UserWarning, match=r'aaa'):
+ warnings.warn("bbbbbbbbbb", UserWarning)
+ warnings.warn("cccccccccc", UserWarning)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_resultlog.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_resultlog.py
new file mode 100644
index 00000000000..b7dd2687cdf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_resultlog.py
@@ -0,0 +1,228 @@
+from __future__ import absolute_import, division, print_function
+import os
+
+import _pytest._code
+import py
+import pytest
+from _pytest.main import Node, Item, FSCollector
+from _pytest.resultlog import generic_path, ResultLog, \
+ pytest_configure, pytest_unconfigure
+
+
+def test_generic_path(testdir):
+ from _pytest.main import Session
+ config = testdir.parseconfig()
+ session = Session(config)
+ p1 = Node('a', config=config, session=session)
+ # assert p1.fspath is None
+ p2 = Node('B', parent=p1)
+ p3 = Node('()', parent=p2)
+ item = Item('c', parent=p3)
+
+ res = generic_path(item)
+ assert res == 'a.B().c'
+
+ p0 = FSCollector('proj/test', config=config, session=session)
+ p1 = FSCollector('proj/test/a', parent=p0)
+ p2 = Node('B', parent=p1)
+ p3 = Node('()', parent=p2)
+ p4 = Node('c', parent=p3)
+ item = Item('[1]', parent=p4)
+
+ res = generic_path(item)
+ assert res == 'test/a:B().c[1]'
+
+
+def test_write_log_entry():
+ reslog = ResultLog(None, None)
+ reslog.logfile = py.io.TextIO()
+ reslog.write_log_entry('name', '.', '')
+ entry = reslog.logfile.getvalue()
+ assert entry[-1] == '\n'
+ entry_lines = entry.splitlines()
+ assert len(entry_lines) == 1
+ assert entry_lines[0] == '. name'
+
+ reslog.logfile = py.io.TextIO()
+ reslog.write_log_entry('name', 's', 'Skipped')
+ entry = reslog.logfile.getvalue()
+ assert entry[-1] == '\n'
+ entry_lines = entry.splitlines()
+ assert len(entry_lines) == 2
+ assert entry_lines[0] == 's name'
+ assert entry_lines[1] == ' Skipped'
+
+ reslog.logfile = py.io.TextIO()
+ reslog.write_log_entry('name', 's', 'Skipped\n')
+ entry = reslog.logfile.getvalue()
+ assert entry[-1] == '\n'
+ entry_lines = entry.splitlines()
+ assert len(entry_lines) == 2
+ assert entry_lines[0] == 's name'
+ assert entry_lines[1] == ' Skipped'
+
+ reslog.logfile = py.io.TextIO()
+ longrepr = ' tb1\n tb 2\nE tb3\nSome Error'
+ reslog.write_log_entry('name', 'F', longrepr)
+ entry = reslog.logfile.getvalue()
+ assert entry[-1] == '\n'
+ entry_lines = entry.splitlines()
+ assert len(entry_lines) == 5
+ assert entry_lines[0] == 'F name'
+ assert entry_lines[1:] == [' ' + line for line in longrepr.splitlines()]
+
+
+class TestWithFunctionIntegration(object):
+ # XXX (hpk) i think that the resultlog plugin should
+ # provide a Parser object so that one can remain
+ # ignorant regarding formatting details.
+ def getresultlog(self, testdir, arg):
+ resultlog = testdir.tmpdir.join("resultlog")
+ testdir.plugins.append("resultlog")
+ args = ["--resultlog=%s" % resultlog] + [arg]
+ testdir.runpytest(*args)
+ return [x for x in resultlog.readlines(cr=0) if x]
+
+ def test_collection_report(self, testdir):
+ ok = testdir.makepyfile(test_collection_ok="")
+ fail = testdir.makepyfile(test_collection_fail="XXX")
+ lines = self.getresultlog(testdir, ok)
+ assert not lines
+
+ lines = self.getresultlog(testdir, fail)
+ assert lines
+ assert lines[0].startswith("F ")
+ assert lines[0].endswith("test_collection_fail.py"), lines[0]
+ for x in lines[1:]:
+ assert x.startswith(" ")
+ assert "XXX" in "".join(lines[1:])
+
+ def test_log_test_outcomes(self, testdir):
+ mod = testdir.makepyfile(test_mod="""
+ import pytest
+ def test_pass(): pass
+ def test_skip(): pytest.skip("hello")
+ def test_fail(): raise ValueError("FAIL")
+
+ @pytest.mark.xfail
+ def test_xfail(): raise ValueError("XFAIL")
+ @pytest.mark.xfail
+ def test_xpass(): pass
+
+ """)
+ lines = self.getresultlog(testdir, mod)
+ assert len(lines) >= 3
+ assert lines[0].startswith(". ")
+ assert lines[0].endswith("test_pass")
+ assert lines[1].startswith("s "), lines[1]
+ assert lines[1].endswith("test_skip")
+ assert lines[2].find("hello") != -1
+
+ assert lines[3].startswith("F ")
+ assert lines[3].endswith("test_fail")
+ tb = "".join(lines[4:8])
+ assert tb.find('raise ValueError("FAIL")') != -1
+
+ assert lines[8].startswith('x ')
+ tb = "".join(lines[8:14])
+ assert tb.find('raise ValueError("XFAIL")') != -1
+
+ assert lines[14].startswith('X ')
+ assert len(lines) == 15
+
+ @pytest.mark.parametrize("style", ("native", "long", "short"))
+ def test_internal_exception(self, style):
+ # they are produced for example by a teardown failing
+ # at the end of the run or a failing hook invocation
+ try:
+ raise ValueError
+ except ValueError:
+ excinfo = _pytest._code.ExceptionInfo()
+ reslog = ResultLog(None, py.io.TextIO())
+ reslog.pytest_internalerror(excinfo.getrepr(style=style))
+ entry = reslog.logfile.getvalue()
+ entry_lines = entry.splitlines()
+
+ assert entry_lines[0].startswith('! ')
+ if style != "native":
+ assert os.path.basename(__file__)[:-9] in entry_lines[0] # .pyc/class
+ assert entry_lines[-1][0] == ' '
+ assert 'ValueError' in entry
+
+
+def test_generic(testdir, LineMatcher):
+ testdir.plugins.append("resultlog")
+ testdir.makepyfile("""
+ import pytest
+ def test_pass():
+ pass
+ def test_fail():
+ assert 0
+ def test_skip():
+ pytest.skip("")
+ @pytest.mark.xfail
+ def test_xfail():
+ assert 0
+ @pytest.mark.xfail(run=False)
+ def test_xfail_norun():
+ assert 0
+ """)
+ testdir.runpytest("--resultlog=result.log")
+ lines = testdir.tmpdir.join("result.log").readlines(cr=0)
+ LineMatcher(lines).fnmatch_lines([
+ ". *:test_pass",
+ "F *:test_fail",
+ "s *:test_skip",
+ "x *:test_xfail",
+ "x *:test_xfail_norun",
+ ])
+
+
+def test_makedir_for_resultlog(testdir, LineMatcher):
+ """--resultlog should automatically create directories for the log file"""
+ testdir.plugins.append("resultlog")
+ testdir.makepyfile("""
+ import pytest
+ def test_pass():
+ pass
+ """)
+ testdir.runpytest("--resultlog=path/to/result.log")
+ lines = testdir.tmpdir.join("path/to/result.log").readlines(cr=0)
+ LineMatcher(lines).fnmatch_lines([
+ ". *:test_pass",
+ ])
+
+
+def test_no_resultlog_on_slaves(testdir):
+ config = testdir.parseconfig("-p", "resultlog", "--resultlog=resultlog")
+
+ assert not hasattr(config, '_resultlog')
+ pytest_configure(config)
+ assert hasattr(config, '_resultlog')
+ pytest_unconfigure(config)
+ assert not hasattr(config, '_resultlog')
+
+ config.slaveinput = {}
+ pytest_configure(config)
+ assert not hasattr(config, '_resultlog')
+ pytest_unconfigure(config)
+ assert not hasattr(config, '_resultlog')
+
+
+def test_failure_issue380(testdir):
+ testdir.makeconftest("""
+ import pytest
+ class MyCollector(pytest.File):
+ def collect(self):
+ raise ValueError()
+ def repr_failure(self, excinfo):
+ return "somestring"
+ def pytest_collect_file(path, parent):
+ return MyCollector(parent=parent, fspath=path)
+ """)
+ testdir.makepyfile("""
+ def test_func():
+ pass
+ """)
+ result = testdir.runpytest("--resultlog=log")
+ assert result.ret == 2
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_runner.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_runner.py
new file mode 100644
index 00000000000..c8e2a6463a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_runner.py
@@ -0,0 +1,813 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import, division, print_function
+
+import _pytest._code
+import os
+import py
+import pytest
+import sys
+from _pytest import runner, main, outcomes
+
+
+class TestSetupState(object):
+ def test_setup(self, testdir):
+ ss = runner.SetupState()
+ item = testdir.getitem("def test_func(): pass")
+ values = [1]
+ ss.prepare(item)
+ ss.addfinalizer(values.pop, colitem=item)
+ assert values
+ ss._pop_and_teardown()
+ assert not values
+
+ def test_teardown_exact_stack_empty(self, testdir):
+ item = testdir.getitem("def test_func(): pass")
+ ss = runner.SetupState()
+ ss.teardown_exact(item, None)
+ ss.teardown_exact(item, None)
+ ss.teardown_exact(item, None)
+
+ def test_setup_fails_and_failure_is_cached(self, testdir):
+ item = testdir.getitem("""
+ def setup_module(mod):
+ raise ValueError(42)
+ def test_func(): pass
+ """) # noqa
+ ss = runner.SetupState()
+ pytest.raises(ValueError, lambda: ss.prepare(item))
+ pytest.raises(ValueError, lambda: ss.prepare(item))
+
+ def test_teardown_multiple_one_fails(self, testdir):
+ r = []
+
+ def fin1():
+ r.append('fin1')
+
+ def fin2():
+ raise Exception('oops')
+
+ def fin3():
+ r.append('fin3')
+
+ item = testdir.getitem("def test_func(): pass")
+ ss = runner.SetupState()
+ ss.addfinalizer(fin1, item)
+ ss.addfinalizer(fin2, item)
+ ss.addfinalizer(fin3, item)
+ with pytest.raises(Exception) as err:
+ ss._callfinalizers(item)
+ assert err.value.args == ('oops',)
+ assert r == ['fin3', 'fin1']
+
+ def test_teardown_multiple_fail(self, testdir):
+ # Ensure the first exception is the one which is re-raised.
+ # Ideally both would be reported however.
+ def fin1():
+ raise Exception('oops1')
+
+ def fin2():
+ raise Exception('oops2')
+
+ item = testdir.getitem("def test_func(): pass")
+ ss = runner.SetupState()
+ ss.addfinalizer(fin1, item)
+ ss.addfinalizer(fin2, item)
+ with pytest.raises(Exception) as err:
+ ss._callfinalizers(item)
+ assert err.value.args == ('oops2',)
+
+
+class BaseFunctionalTests(object):
+ def test_passfunction(self, testdir):
+ reports = testdir.runitem("""
+ def test_func():
+ pass
+ """)
+ rep = reports[1]
+ assert rep.passed
+ assert not rep.failed
+ assert rep.outcome == "passed"
+ assert not rep.longrepr
+
+ def test_failfunction(self, testdir):
+ reports = testdir.runitem("""
+ def test_func():
+ assert 0
+ """)
+ rep = reports[1]
+ assert not rep.passed
+ assert not rep.skipped
+ assert rep.failed
+ assert rep.when == "call"
+ assert rep.outcome == "failed"
+ # assert isinstance(rep.longrepr, ReprExceptionInfo)
+
+ def test_skipfunction(self, testdir):
+ reports = testdir.runitem("""
+ import pytest
+ def test_func():
+ pytest.skip("hello")
+ """)
+ rep = reports[1]
+ assert not rep.failed
+ assert not rep.passed
+ assert rep.skipped
+ assert rep.outcome == "skipped"
+ # assert rep.skipped.when == "call"
+ # assert rep.skipped.when == "call"
+ # assert rep.skipped == "%sreason == "hello"
+ # assert rep.skipped.location.lineno == 3
+ # assert rep.skipped.location.path
+ # assert not rep.skipped.failurerepr
+
+ def test_skip_in_setup_function(self, testdir):
+ reports = testdir.runitem("""
+ import pytest
+ def setup_function(func):
+ pytest.skip("hello")
+ def test_func():
+ pass
+ """)
+ print(reports)
+ rep = reports[0]
+ assert not rep.failed
+ assert not rep.passed
+ assert rep.skipped
+ # assert rep.skipped.reason == "hello"
+ # assert rep.skipped.location.lineno == 3
+ # assert rep.skipped.location.lineno == 3
+ assert len(reports) == 2
+ assert reports[1].passed # teardown
+
+ def test_failure_in_setup_function(self, testdir):
+ reports = testdir.runitem("""
+ import pytest
+ def setup_function(func):
+ raise ValueError(42)
+ def test_func():
+ pass
+ """)
+ rep = reports[0]
+ assert not rep.skipped
+ assert not rep.passed
+ assert rep.failed
+ assert rep.when == "setup"
+ assert len(reports) == 2
+
+ def test_failure_in_teardown_function(self, testdir):
+ reports = testdir.runitem("""
+ import pytest
+ def teardown_function(func):
+ raise ValueError(42)
+ def test_func():
+ pass
+ """)
+ print(reports)
+ assert len(reports) == 3
+ rep = reports[2]
+ assert not rep.skipped
+ assert not rep.passed
+ assert rep.failed
+ assert rep.when == "teardown"
+ # assert rep.longrepr.reprcrash.lineno == 3
+ # assert rep.longrepr.reprtraceback.reprentries
+
+ def test_custom_failure_repr(self, testdir):
+ testdir.makepyfile(conftest="""
+ import pytest
+ class Function(pytest.Function):
+ def repr_failure(self, excinfo):
+ return "hello"
+ """)
+ reports = testdir.runitem("""
+ import pytest
+ def test_func():
+ assert 0
+ """)
+ rep = reports[1]
+ assert not rep.skipped
+ assert not rep.passed
+ assert rep.failed
+ # assert rep.outcome.when == "call"
+ # assert rep.failed.where.lineno == 3
+ # assert rep.failed.where.path.basename == "test_func.py"
+ # assert rep.failed.failurerepr == "hello"
+
+ def test_teardown_final_returncode(self, testdir):
+ rec = testdir.inline_runsource("""
+ def test_func():
+ pass
+ def teardown_function(func):
+ raise ValueError(42)
+ """)
+ assert rec.ret == 1
+
+ def test_exact_teardown_issue90(self, testdir):
+ rec = testdir.inline_runsource("""
+ import pytest
+
+ class TestClass(object):
+ def test_method(self):
+ pass
+ def teardown_class(cls):
+ raise Exception()
+
+ def test_func():
+ import sys
+ # on python2 exc_info is keept till a function exits
+ # so we would end up calling test functions while
+ # sys.exc_info would return the indexerror
+ # from guessing the lastitem
+ excinfo = sys.exc_info()
+ import traceback
+ assert excinfo[0] is None, \
+ traceback.format_exception(*excinfo)
+ def teardown_function(func):
+ raise ValueError(42)
+ """)
+ reps = rec.getreports("pytest_runtest_logreport")
+ print(reps)
+ for i in range(2):
+ assert reps[i].nodeid.endswith("test_method")
+ assert reps[i].passed
+ assert reps[2].when == "teardown"
+ assert reps[2].failed
+ assert len(reps) == 6
+ for i in range(3, 5):
+ assert reps[i].nodeid.endswith("test_func")
+ assert reps[i].passed
+ assert reps[5].when == "teardown"
+ assert reps[5].nodeid.endswith("test_func")
+ assert reps[5].failed
+
+ def test_exact_teardown_issue1206(self, testdir):
+ """issue shadowing error with wrong number of arguments on teardown_method."""
+ rec = testdir.inline_runsource("""
+ import pytest
+
+ class TestClass(object):
+ def teardown_method(self, x, y, z):
+ pass
+
+ def test_method(self):
+ assert True
+ """)
+ reps = rec.getreports("pytest_runtest_logreport")
+ print(reps)
+ assert len(reps) == 3
+ #
+ assert reps[0].nodeid.endswith("test_method")
+ assert reps[0].passed
+ assert reps[0].when == 'setup'
+ #
+ assert reps[1].nodeid.endswith("test_method")
+ assert reps[1].passed
+ assert reps[1].when == 'call'
+ #
+ assert reps[2].nodeid.endswith("test_method")
+ assert reps[2].failed
+ assert reps[2].when == "teardown"
+ assert reps[2].longrepr.reprcrash.message in (
+ # python3 error
+ "TypeError: teardown_method() missing 2 required positional arguments: 'y' and 'z'",
+ # python2 error
+ 'TypeError: teardown_method() takes exactly 4 arguments (2 given)'
+ )
+
+ def test_failure_in_setup_function_ignores_custom_repr(self, testdir):
+ testdir.makepyfile(conftest="""
+ import pytest
+ class Function(pytest.Function):
+ def repr_failure(self, excinfo):
+ assert 0
+ """)
+ reports = testdir.runitem("""
+ def setup_function(func):
+ raise ValueError(42)
+ def test_func():
+ pass
+ """)
+ assert len(reports) == 2
+ rep = reports[0]
+ print(rep)
+ assert not rep.skipped
+ assert not rep.passed
+ assert rep.failed
+ # assert rep.outcome.when == "setup"
+ # assert rep.outcome.where.lineno == 3
+ # assert rep.outcome.where.path.basename == "test_func.py"
+ # assert instanace(rep.failed.failurerepr, PythonFailureRepr)
+
+ def test_systemexit_does_not_bail_out(self, testdir):
+ try:
+ reports = testdir.runitem("""
+ def test_func():
+ raise SystemExit(42)
+ """)
+ except SystemExit:
+ pytest.fail("runner did not catch SystemExit")
+ rep = reports[1]
+ assert rep.failed
+ assert rep.when == "call"
+
+ def test_exit_propagates(self, testdir):
+ try:
+ testdir.runitem("""
+ import pytest
+ def test_func():
+ raise pytest.exit.Exception()
+ """)
+ except pytest.exit.Exception:
+ pass
+ else:
+ pytest.fail("did not raise")
+
+
+class TestExecutionNonForked(BaseFunctionalTests):
+ def getrunner(self):
+ def f(item):
+ return runner.runtestprotocol(item, log=False)
+ return f
+
+ def test_keyboardinterrupt_propagates(self, testdir):
+ try:
+ testdir.runitem("""
+ def test_func():
+ raise KeyboardInterrupt("fake")
+ """)
+ except KeyboardInterrupt:
+ pass
+ else:
+ pytest.fail("did not raise")
+
+
+class TestExecutionForked(BaseFunctionalTests):
+ pytestmark = pytest.mark.skipif("not hasattr(os, 'fork')")
+
+ def getrunner(self):
+ # XXX re-arrange this test to live in pytest-xdist
+ boxed = pytest.importorskip("xdist.boxed")
+ return boxed.forked_run_report
+
+ def test_suicide(self, testdir):
+ reports = testdir.runitem("""
+ def test_func():
+ import os
+ os.kill(os.getpid(), 15)
+ """)
+ rep = reports[0]
+ assert rep.failed
+ assert rep.when == "???"
+
+
+class TestSessionReports(object):
+ def test_collect_result(self, testdir):
+ col = testdir.getmodulecol("""
+ def test_func1():
+ pass
+ class TestClass(object):
+ pass
+ """)
+ rep = runner.collect_one_node(col)
+ assert not rep.failed
+ assert not rep.skipped
+ assert rep.passed
+ locinfo = rep.location
+ assert locinfo[0] == col.fspath.basename
+ assert not locinfo[1]
+ assert locinfo[2] == col.fspath.basename
+ res = rep.result
+ assert len(res) == 2
+ assert res[0].name == "test_func1"
+ assert res[1].name == "TestClass"
+
+
+reporttypes = [
+ runner.BaseReport,
+ runner.TestReport,
+ runner.TeardownErrorReport,
+ runner.CollectReport,
+]
+
+
+@pytest.mark.parametrize('reporttype', reporttypes, ids=[x.__name__ for x in reporttypes])
+def test_report_extra_parameters(reporttype):
+ if hasattr(py.std.inspect, 'signature'):
+ args = list(py.std.inspect.signature(reporttype.__init__).parameters.keys())[1:]
+ else:
+ args = py.std.inspect.getargspec(reporttype.__init__)[0][1:]
+ basekw = dict.fromkeys(args, [])
+ report = reporttype(newthing=1, **basekw)
+ assert report.newthing == 1
+
+
+def test_callinfo():
+ ci = runner.CallInfo(lambda: 0, '123')
+ assert ci.when == "123"
+ assert ci.result == 0
+ assert "result" in repr(ci)
+ ci = runner.CallInfo(lambda: 0 / 0, '123')
+ assert ci.when == "123"
+ assert not hasattr(ci, 'result')
+ assert ci.excinfo
+ assert "exc" in repr(ci)
+
+# design question: do we want general hooks in python files?
+# then something like the following functional tests makes sense
+
+
+@pytest.mark.xfail
+def test_runtest_in_module_ordering(testdir):
+ p1 = testdir.makepyfile("""
+ import pytest
+ def pytest_runtest_setup(item): # runs after class-level!
+ item.function.mylist.append("module")
+ class TestClass(object):
+ def pytest_runtest_setup(self, item):
+ assert not hasattr(item.function, 'mylist')
+ item.function.mylist = ['class']
+ @pytest.fixture
+ def mylist(self, request):
+ return request.function.mylist
+ def pytest_runtest_call(self, item, __multicall__):
+ try:
+ __multicall__.execute()
+ except ValueError:
+ pass
+ def test_hello1(self, mylist):
+ assert mylist == ['class', 'module'], mylist
+ raise ValueError()
+ def test_hello2(self, mylist):
+ assert mylist == ['class', 'module'], mylist
+ def pytest_runtest_teardown(item):
+ del item.function.mylist
+ """)
+ result = testdir.runpytest(p1)
+ result.stdout.fnmatch_lines([
+ "*2 passed*"
+ ])
+
+
+def test_outcomeexception_exceptionattributes():
+ outcome = outcomes.OutcomeException('test')
+ assert outcome.args[0] == outcome.msg
+
+
+def test_outcomeexception_passes_except_Exception():
+ with pytest.raises(outcomes.OutcomeException):
+ try:
+ raise outcomes.OutcomeException('test')
+ except Exception:
+ pass
+
+
+def test_pytest_exit():
+ try:
+ pytest.exit("hello")
+ except pytest.exit.Exception:
+ excinfo = _pytest._code.ExceptionInfo()
+ assert excinfo.errisinstance(KeyboardInterrupt)
+
+
+def test_pytest_fail():
+ try:
+ pytest.fail("hello")
+ except pytest.fail.Exception:
+ excinfo = _pytest._code.ExceptionInfo()
+ s = excinfo.exconly(tryshort=True)
+ assert s.startswith("Failed")
+
+
+def test_pytest_exit_msg(testdir):
+ testdir.makeconftest("""
+ import pytest
+
+ def pytest_configure(config):
+ pytest.exit('oh noes')
+ """)
+ result = testdir.runpytest()
+ result.stderr.fnmatch_lines([
+ "Exit: oh noes",
+ ])
+
+
+def test_pytest_fail_notrace(testdir):
+ testdir.makepyfile("""
+ import pytest
+ def test_hello():
+ pytest.fail("hello", pytrace=False)
+ def teardown_function(function):
+ pytest.fail("world", pytrace=False)
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "world",
+ "hello",
+ ])
+ assert 'def teardown_function' not in result.stdout.str()
+
+
+@pytest.mark.parametrize('str_prefix', ['u', ''])
+def test_pytest_fail_notrace_non_ascii(testdir, str_prefix):
+ """Fix pytest.fail with pytrace=False with non-ascii characters (#1178).
+
+ This tests with native and unicode strings containing non-ascii chars.
+ """
+ testdir.makepyfile(u"""
+ # coding: utf-8
+ import pytest
+
+ def test_hello():
+ pytest.fail(%s'oh oh: ☺', pytrace=False)
+ """ % str_prefix)
+ result = testdir.runpytest()
+ if sys.version_info[0] >= 3:
+ result.stdout.fnmatch_lines(['*test_hello*', "oh oh: ☺"])
+ else:
+ result.stdout.fnmatch_lines(['*test_hello*', "oh oh: *"])
+ assert 'def test_hello' not in result.stdout.str()
+
+
+def test_pytest_no_tests_collected_exit_status(testdir):
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines('*collected 0 items*')
+ assert result.ret == main.EXIT_NOTESTSCOLLECTED
+
+ testdir.makepyfile(test_foo="""
+ def test_foo():
+ assert 1
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines('*collected 1 item*')
+ result.stdout.fnmatch_lines('*1 passed*')
+ assert result.ret == main.EXIT_OK
+
+ result = testdir.runpytest('-k nonmatch')
+ result.stdout.fnmatch_lines('*collected 1 item*')
+ result.stdout.fnmatch_lines('*1 deselected*')
+ assert result.ret == main.EXIT_NOTESTSCOLLECTED
+
+
+def test_exception_printing_skip():
+ try:
+ pytest.skip("hello")
+ except pytest.skip.Exception:
+ excinfo = _pytest._code.ExceptionInfo()
+ s = excinfo.exconly(tryshort=True)
+ assert s.startswith("Skipped")
+
+
+def test_importorskip(monkeypatch):
+ importorskip = pytest.importorskip
+
+ def f():
+ importorskip("asdlkj")
+
+ try:
+ sys = importorskip("sys") # noqa
+ assert sys == py.std.sys
+ # path = pytest.importorskip("os.path")
+ # assert path == py.std.os.path
+ excinfo = pytest.raises(pytest.skip.Exception, f)
+ path = py.path.local(excinfo.getrepr().reprcrash.path)
+ # check that importorskip reports the actual call
+ # in this test the test_runner.py file
+ assert path.purebasename == "test_runner"
+ pytest.raises(SyntaxError, "pytest.importorskip('x y z')")
+ pytest.raises(SyntaxError, "pytest.importorskip('x=y')")
+ mod = py.std.types.ModuleType("hello123")
+ mod.__version__ = "1.3"
+ monkeypatch.setitem(sys.modules, "hello123", mod)
+ pytest.raises(pytest.skip.Exception, """
+ pytest.importorskip("hello123", minversion="1.3.1")
+ """)
+ mod2 = pytest.importorskip("hello123", minversion="1.3")
+ assert mod2 == mod
+ except pytest.skip.Exception:
+ print(_pytest._code.ExceptionInfo())
+ pytest.fail("spurious skip")
+
+
+def test_importorskip_imports_last_module_part():
+ ospath = pytest.importorskip("os.path")
+ assert os.path == ospath
+
+
+def test_importorskip_dev_module(monkeypatch):
+ try:
+ mod = py.std.types.ModuleType("mockmodule")
+ mod.__version__ = '0.13.0.dev-43290'
+ monkeypatch.setitem(sys.modules, 'mockmodule', mod)
+ mod2 = pytest.importorskip('mockmodule', minversion='0.12.0')
+ assert mod2 == mod
+ pytest.raises(pytest.skip.Exception, """
+ pytest.importorskip('mockmodule1', minversion='0.14.0')""")
+ except pytest.skip.Exception:
+ print(_pytest._code.ExceptionInfo())
+ pytest.fail("spurious skip")
+
+
+def test_importorskip_module_level(testdir):
+ """importorskip must be able to skip entire modules when used at module level"""
+ testdir.makepyfile('''
+ import pytest
+ foobarbaz = pytest.importorskip("foobarbaz")
+
+ def test_foo():
+ pass
+ ''')
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(['*collected 0 items / 1 skipped*'])
+
+
+def test_pytest_cmdline_main(testdir):
+ p = testdir.makepyfile("""
+ import pytest
+ def test_hello():
+ assert 1
+ if __name__ == '__main__':
+ pytest.cmdline.main([__file__])
+ """)
+ import subprocess
+ popen = subprocess.Popen([sys.executable, str(p)], stdout=subprocess.PIPE)
+ popen.communicate()
+ ret = popen.wait()
+ assert ret == 0
+
+
+def test_unicode_in_longrepr(testdir):
+ testdir.makeconftest("""
+ # -*- coding: utf-8 -*-
+ import pytest
+ @pytest.hookimpl(hookwrapper=True)
+ def pytest_runtest_makereport():
+ outcome = yield
+ rep = outcome.get_result()
+ if rep.when == "call":
+ rep.longrepr = u'ä'
+ """)
+ testdir.makepyfile("""
+ def test_out():
+ assert 0
+ """)
+ result = testdir.runpytest()
+ assert result.ret == 1
+ assert "UnicodeEncodeError" not in result.stderr.str()
+
+
+def test_failure_in_setup(testdir):
+ testdir.makepyfile("""
+ def setup_module():
+ 0/0
+ def test_func():
+ pass
+ """)
+ result = testdir.runpytest("--tb=line")
+ assert "def setup_module" not in result.stdout.str()
+
+
+def test_makereport_getsource(testdir):
+ testdir.makepyfile("""
+ def test_foo():
+ if False: pass
+ else: assert False
+ """)
+ result = testdir.runpytest()
+ assert 'INTERNALERROR' not in result.stdout.str()
+ result.stdout.fnmatch_lines(['*else: assert False*'])
+
+
+def test_makereport_getsource_dynamic_code(testdir, monkeypatch):
+ """Test that exception in dynamically generated code doesn't break getting the source line."""
+ import inspect
+ original_findsource = inspect.findsource
+
+ def findsource(obj, *args, **kwargs):
+ # Can be triggered by dynamically created functions
+ if obj.__name__ == 'foo':
+ raise IndexError()
+ return original_findsource(obj, *args, **kwargs)
+
+ monkeypatch.setattr(inspect, 'findsource', findsource)
+
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture
+ def foo(missing):
+ pass
+
+ def test_fix(foo):
+ assert False
+ """)
+ result = testdir.runpytest('-vv')
+ assert 'INTERNALERROR' not in result.stdout.str()
+ result.stdout.fnmatch_lines(["*test_fix*", "*fixture*'missing'*not found*"])
+
+
+def test_store_except_info_on_eror():
+ """ Test that upon test failure, the exception info is stored on
+ sys.last_traceback and friends.
+ """
+ # Simulate item that raises a specific exception
+ class ItemThatRaises(object):
+ nodeid = 'item_that_raises'
+
+ def runtest(self):
+ raise IndexError('TEST')
+ try:
+ runner.pytest_runtest_call(ItemThatRaises())
+ except IndexError:
+ pass
+ # Check that exception info is stored on sys
+ assert sys.last_type is IndexError
+ assert sys.last_value.args[0] == 'TEST'
+ assert sys.last_traceback
+
+
+def test_current_test_env_var(testdir, monkeypatch):
+ pytest_current_test_vars = []
+ monkeypatch.setattr(sys, 'pytest_current_test_vars', pytest_current_test_vars, raising=False)
+ testdir.makepyfile('''
+ import pytest
+ import sys
+ import os
+
+ @pytest.fixture
+ def fix():
+ sys.pytest_current_test_vars.append(('setup', os.environ['PYTEST_CURRENT_TEST']))
+ yield
+ sys.pytest_current_test_vars.append(('teardown', os.environ['PYTEST_CURRENT_TEST']))
+
+ def test(fix):
+ sys.pytest_current_test_vars.append(('call', os.environ['PYTEST_CURRENT_TEST']))
+ ''')
+ result = testdir.runpytest_inprocess()
+ assert result.ret == 0
+ test_id = 'test_current_test_env_var.py::test'
+ assert pytest_current_test_vars == [
+ ('setup', test_id + ' (setup)'), ('call', test_id + ' (call)'), ('teardown', test_id + ' (teardown)')]
+ assert 'PYTEST_CURRENT_TEST' not in os.environ
+
+
+class TestReportContents(object):
+ """
+ Test user-level API of ``TestReport`` objects.
+ """
+
+ def getrunner(self):
+ return lambda item: runner.runtestprotocol(item, log=False)
+
+ def test_longreprtext_pass(self, testdir):
+ reports = testdir.runitem("""
+ def test_func():
+ pass
+ """)
+ rep = reports[1]
+ assert rep.longreprtext == ''
+
+ def test_longreprtext_failure(self, testdir):
+ reports = testdir.runitem("""
+ def test_func():
+ x = 1
+ assert x == 4
+ """)
+ rep = reports[1]
+ assert 'assert 1 == 4' in rep.longreprtext
+
+ def test_captured_text(self, testdir):
+ reports = testdir.runitem("""
+ import pytest
+ import sys
+
+ @pytest.fixture
+ def fix():
+ sys.stdout.write('setup: stdout\\n')
+ sys.stderr.write('setup: stderr\\n')
+ yield
+ sys.stdout.write('teardown: stdout\\n')
+ sys.stderr.write('teardown: stderr\\n')
+ assert 0
+
+ def test_func(fix):
+ sys.stdout.write('call: stdout\\n')
+ sys.stderr.write('call: stderr\\n')
+ assert 0
+ """)
+ setup, call, teardown = reports
+ assert setup.capstdout == 'setup: stdout\n'
+ assert call.capstdout == 'setup: stdout\ncall: stdout\n'
+ assert teardown.capstdout == 'setup: stdout\ncall: stdout\nteardown: stdout\n'
+
+ assert setup.capstderr == 'setup: stderr\n'
+ assert call.capstderr == 'setup: stderr\ncall: stderr\n'
+ assert teardown.capstderr == 'setup: stderr\ncall: stderr\nteardown: stderr\n'
+
+ def test_no_captured_text(self, testdir):
+ reports = testdir.runitem("""
+ def test_func():
+ pass
+ """)
+ rep = reports[1]
+ assert rep.capstdout == ''
+ assert rep.capstderr == ''
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_runner_xunit.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_runner_xunit.py
new file mode 100644
index 00000000000..fc931f86720
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_runner_xunit.py
@@ -0,0 +1,319 @@
+"""
+ test correct setup/teardowns at
+ module, class, and instance level
+"""
+from __future__ import absolute_import, division, print_function
+import pytest
+
+
+def test_module_and_function_setup(testdir):
+ reprec = testdir.inline_runsource("""
+ modlevel = []
+ def setup_module(module):
+ assert not modlevel
+ module.modlevel.append(42)
+
+ def teardown_module(module):
+ modlevel.pop()
+
+ def setup_function(function):
+ function.answer = 17
+
+ def teardown_function(function):
+ del function.answer
+
+ def test_modlevel():
+ assert modlevel[0] == 42
+ assert test_modlevel.answer == 17
+
+ class TestFromClass(object):
+ def test_module(self):
+ assert modlevel[0] == 42
+ assert not hasattr(test_modlevel, 'answer')
+ """)
+ rep = reprec.matchreport("test_modlevel")
+ assert rep.passed
+ rep = reprec.matchreport("test_module")
+ assert rep.passed
+
+
+def test_module_setup_failure_no_teardown(testdir):
+ reprec = testdir.inline_runsource("""
+ values = []
+ def setup_module(module):
+ values.append(1)
+ 0/0
+
+ def test_nothing():
+ pass
+
+ def teardown_module(module):
+ values.append(2)
+ """)
+ reprec.assertoutcome(failed=1)
+ calls = reprec.getcalls("pytest_runtest_setup")
+ assert calls[0].item.module.values == [1]
+
+
+def test_setup_function_failure_no_teardown(testdir):
+ reprec = testdir.inline_runsource("""
+ modlevel = []
+ def setup_function(function):
+ modlevel.append(1)
+ 0/0
+
+ def teardown_function(module):
+ modlevel.append(2)
+
+ def test_func():
+ pass
+ """)
+ calls = reprec.getcalls("pytest_runtest_setup")
+ assert calls[0].item.module.modlevel == [1]
+
+
+def test_class_setup(testdir):
+ reprec = testdir.inline_runsource("""
+ class TestSimpleClassSetup(object):
+ clslevel = []
+ def setup_class(cls):
+ cls.clslevel.append(23)
+
+ def teardown_class(cls):
+ cls.clslevel.pop()
+
+ def test_classlevel(self):
+ assert self.clslevel[0] == 23
+
+ class TestInheritedClassSetupStillWorks(TestSimpleClassSetup):
+ def test_classlevel_anothertime(self):
+ assert self.clslevel == [23]
+
+ def test_cleanup():
+ assert not TestSimpleClassSetup.clslevel
+ assert not TestInheritedClassSetupStillWorks.clslevel
+ """)
+ reprec.assertoutcome(passed=1 + 2 + 1)
+
+
+def test_class_setup_failure_no_teardown(testdir):
+ reprec = testdir.inline_runsource("""
+ class TestSimpleClassSetup(object):
+ clslevel = []
+ def setup_class(cls):
+ 0/0
+
+ def teardown_class(cls):
+ cls.clslevel.append(1)
+
+ def test_classlevel(self):
+ pass
+
+ def test_cleanup():
+ assert not TestSimpleClassSetup.clslevel
+ """)
+ reprec.assertoutcome(failed=1, passed=1)
+
+
+def test_method_setup(testdir):
+ reprec = testdir.inline_runsource("""
+ class TestSetupMethod(object):
+ def setup_method(self, meth):
+ self.methsetup = meth
+ def teardown_method(self, meth):
+ del self.methsetup
+
+ def test_some(self):
+ assert self.methsetup == self.test_some
+
+ def test_other(self):
+ assert self.methsetup == self.test_other
+ """)
+ reprec.assertoutcome(passed=2)
+
+
+def test_method_setup_failure_no_teardown(testdir):
+ reprec = testdir.inline_runsource("""
+ class TestMethodSetup(object):
+ clslevel = []
+ def setup_method(self, method):
+ self.clslevel.append(1)
+ 0/0
+
+ def teardown_method(self, method):
+ self.clslevel.append(2)
+
+ def test_method(self):
+ pass
+
+ def test_cleanup():
+ assert TestMethodSetup.clslevel == [1]
+ """)
+ reprec.assertoutcome(failed=1, passed=1)
+
+
+def test_method_generator_setup(testdir):
+ reprec = testdir.inline_runsource("""
+ class TestSetupTeardownOnInstance(object):
+ def setup_class(cls):
+ cls.classsetup = True
+
+ def setup_method(self, method):
+ self.methsetup = method
+
+ def test_generate(self):
+ assert self.classsetup
+ assert self.methsetup == self.test_generate
+ yield self.generated, 5
+ yield self.generated, 2
+
+ def generated(self, value):
+ assert self.classsetup
+ assert self.methsetup == self.test_generate
+ assert value == 5
+ """)
+ reprec.assertoutcome(passed=1, failed=1)
+
+
+def test_func_generator_setup(testdir):
+ reprec = testdir.inline_runsource("""
+ import sys
+
+ def setup_module(mod):
+ print ("setup_module")
+ mod.x = []
+
+ def setup_function(fun):
+ print ("setup_function")
+ x.append(1)
+
+ def teardown_function(fun):
+ print ("teardown_function")
+ x.pop()
+
+ def test_one():
+ assert x == [1]
+ def check():
+ print ("check")
+ sys.stderr.write("e\\n")
+ assert x == [1]
+ yield check
+ assert x == [1]
+ """)
+ rep = reprec.matchreport("test_one", names="pytest_runtest_logreport")
+ assert rep.passed
+
+
+def test_method_setup_uses_fresh_instances(testdir):
+ reprec = testdir.inline_runsource("""
+ class TestSelfState1(object):
+ memory = []
+ def test_hello(self):
+ self.memory.append(self)
+
+ def test_afterhello(self):
+ assert self != self.memory[0]
+ """)
+ reprec.assertoutcome(passed=2, failed=0)
+
+
+def test_setup_that_skips_calledagain(testdir):
+ p = testdir.makepyfile("""
+ import pytest
+ def setup_module(mod):
+ pytest.skip("x")
+ def test_function1():
+ pass
+ def test_function2():
+ pass
+ """)
+ reprec = testdir.inline_run(p)
+ reprec.assertoutcome(skipped=2)
+
+
+def test_setup_fails_again_on_all_tests(testdir):
+ p = testdir.makepyfile("""
+ import pytest
+ def setup_module(mod):
+ raise ValueError(42)
+ def test_function1():
+ pass
+ def test_function2():
+ pass
+ """)
+ reprec = testdir.inline_run(p)
+ reprec.assertoutcome(failed=2)
+
+
+def test_setup_funcarg_setup_when_outer_scope_fails(testdir):
+ p = testdir.makepyfile("""
+ import pytest
+ def setup_module(mod):
+ raise ValueError(42)
+ @pytest.fixture
+ def hello(request):
+ raise ValueError("xyz43")
+ def test_function1(hello):
+ pass
+ def test_function2(hello):
+ pass
+ """)
+ result = testdir.runpytest(p)
+ result.stdout.fnmatch_lines([
+ "*function1*",
+ "*ValueError*42*",
+ "*function2*",
+ "*ValueError*42*",
+ "*2 error*"
+ ])
+ assert "xyz43" not in result.stdout.str()
+
+
+@pytest.mark.parametrize('arg', ['', 'arg'])
+def test_setup_teardown_function_level_with_optional_argument(testdir, monkeypatch, arg):
+ """parameter to setup/teardown xunit-style functions parameter is now optional (#1728)."""
+ import sys
+ trace_setups_teardowns = []
+ monkeypatch.setattr(sys, 'trace_setups_teardowns', trace_setups_teardowns, raising=False)
+ p = testdir.makepyfile("""
+ import pytest
+ import sys
+
+ trace = sys.trace_setups_teardowns.append
+
+ def setup_module({arg}): trace('setup_module')
+ def teardown_module({arg}): trace('teardown_module')
+
+ def setup_function({arg}): trace('setup_function')
+ def teardown_function({arg}): trace('teardown_function')
+
+ def test_function_1(): pass
+ def test_function_2(): pass
+
+ class Test(object):
+ def setup_method(self, {arg}): trace('setup_method')
+ def teardown_method(self, {arg}): trace('teardown_method')
+
+ def test_method_1(self): pass
+ def test_method_2(self): pass
+ """.format(arg=arg))
+ result = testdir.inline_run(p)
+ result.assertoutcome(passed=4)
+
+ expected = [
+ 'setup_module',
+
+ 'setup_function',
+ 'teardown_function',
+ 'setup_function',
+ 'teardown_function',
+
+ 'setup_method',
+ 'teardown_method',
+
+ 'setup_method',
+ 'teardown_method',
+
+ 'teardown_module',
+ ]
+ assert trace_setups_teardowns == expected
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_session.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_session.py
new file mode 100644
index 00000000000..9ec13f523e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_session.py
@@ -0,0 +1,255 @@
+from __future__ import absolute_import, division, print_function
+import pytest
+
+from _pytest.main import EXIT_NOTESTSCOLLECTED
+
+
+class SessionTests(object):
+ def test_basic_testitem_events(self, testdir):
+ tfile = testdir.makepyfile("""
+ def test_one():
+ pass
+ def test_one_one():
+ assert 0
+ def test_other():
+ raise ValueError(23)
+ class TestClass(object):
+ def test_two(self, someargs):
+ pass
+ """)
+ reprec = testdir.inline_run(tfile)
+ passed, skipped, failed = reprec.listoutcomes()
+ assert len(skipped) == 0
+ assert len(passed) == 1
+ assert len(failed) == 3
+
+ def end(x):
+ return x.nodeid.split("::")[-1]
+
+ assert end(failed[0]) == "test_one_one"
+ assert end(failed[1]) == "test_other"
+ itemstarted = reprec.getcalls("pytest_itemcollected")
+ assert len(itemstarted) == 4
+ # XXX check for failing funcarg setup
+ # colreports = reprec.getcalls("pytest_collectreport")
+ # assert len(colreports) == 4
+ # assert colreports[1].report.failed
+
+ def test_nested_import_error(self, testdir):
+ tfile = testdir.makepyfile("""
+ import import_fails
+ def test_this():
+ assert import_fails.a == 1
+ """, import_fails="""
+ import does_not_work
+ a = 1
+ """)
+ reprec = testdir.inline_run(tfile)
+ values = reprec.getfailedcollections()
+ assert len(values) == 1
+ out = str(values[0].longrepr)
+ assert out.find('does_not_work') != -1
+
+ def test_raises_output(self, testdir):
+ reprec = testdir.inline_runsource("""
+ import pytest
+ def test_raises_doesnt():
+ pytest.raises(ValueError, int, "3")
+ """)
+ passed, skipped, failed = reprec.listoutcomes()
+ assert len(failed) == 1
+ out = failed[0].longrepr.reprcrash.message
+ if not out.find("DID NOT RAISE") != -1:
+ print(out)
+ pytest.fail("incorrect raises() output")
+
+ def test_generator_yields_None(self, testdir):
+ reprec = testdir.inline_runsource("""
+ def test_1():
+ yield None
+ """)
+ failures = reprec.getfailedcollections()
+ out = failures[0].longrepr.reprcrash.message
+ i = out.find('TypeError')
+ assert i != -1
+
+ def test_syntax_error_module(self, testdir):
+ reprec = testdir.inline_runsource("this is really not python")
+ values = reprec.getfailedcollections()
+ assert len(values) == 1
+ out = str(values[0].longrepr)
+ assert out.find(str('not python')) != -1
+
+ def test_exit_first_problem(self, testdir):
+ reprec = testdir.inline_runsource("""
+ def test_one(): assert 0
+ def test_two(): assert 0
+ """, '--exitfirst')
+ passed, skipped, failed = reprec.countoutcomes()
+ assert failed == 1
+ assert passed == skipped == 0
+
+ def test_maxfail(self, testdir):
+ reprec = testdir.inline_runsource("""
+ def test_one(): assert 0
+ def test_two(): assert 0
+ def test_three(): assert 0
+ """, '--maxfail=2')
+ passed, skipped, failed = reprec.countoutcomes()
+ assert failed == 2
+ assert passed == skipped == 0
+
+ def test_broken_repr(self, testdir):
+ p = testdir.makepyfile("""
+ import pytest
+ class BrokenRepr1(object):
+ foo=0
+ def __repr__(self):
+ raise Exception("Ha Ha fooled you, I'm a broken repr().")
+
+ class TestBrokenClass(object):
+ def test_explicit_bad_repr(self):
+ t = BrokenRepr1()
+ pytest.raises(Exception, 'repr(t)')
+
+ def test_implicit_bad_repr1(self):
+ t = BrokenRepr1()
+ assert t.foo == 1
+
+ """)
+ reprec = testdir.inline_run(p)
+ passed, skipped, failed = reprec.listoutcomes()
+ assert len(failed) == 1
+ out = failed[0].longrepr.reprcrash.message
+ assert out.find("""[Exception("Ha Ha fooled you, I'm a broken repr().") raised in repr()]""") != -1 # '
+
+ def test_skip_file_by_conftest(self, testdir):
+ testdir.makepyfile(conftest="""
+ import pytest
+ def pytest_collect_file():
+ pytest.skip("intentional")
+ """, test_file="""
+ def test_one(): pass
+ """)
+ try:
+ reprec = testdir.inline_run(testdir.tmpdir)
+ except pytest.skip.Exception:
+ pytest.fail("wrong skipped caught")
+ reports = reprec.getreports("pytest_collectreport")
+ assert len(reports) == 1
+ assert reports[0].skipped
+
+
+class TestNewSession(SessionTests):
+
+ def test_order_of_execution(self, testdir):
+ reprec = testdir.inline_runsource("""
+ values = []
+ def test_1():
+ values.append(1)
+ def test_2():
+ values.append(2)
+ def test_3():
+ assert values == [1,2]
+ class Testmygroup(object):
+ reslist = values
+ def test_1(self):
+ self.reslist.append(1)
+ def test_2(self):
+ self.reslist.append(2)
+ def test_3(self):
+ self.reslist.append(3)
+ def test_4(self):
+ assert self.reslist == [1,2,1,2,3]
+ """)
+ passed, skipped, failed = reprec.countoutcomes()
+ assert failed == skipped == 0
+ assert passed == 7
+ # also test listnames() here ...
+
+ def test_collect_only_with_various_situations(self, testdir):
+ p = testdir.makepyfile(
+ test_one="""
+ def test_one():
+ raise ValueError()
+
+ class TestX(object):
+ def test_method_one(self):
+ pass
+
+ class TestY(TestX):
+ pass
+ """,
+ test_three="xxxdsadsadsadsa",
+ __init__=""
+ )
+ reprec = testdir.inline_run('--collect-only', p.dirpath())
+
+ itemstarted = reprec.getcalls("pytest_itemcollected")
+ assert len(itemstarted) == 3
+ assert not reprec.getreports("pytest_runtest_logreport")
+ started = reprec.getcalls("pytest_collectstart")
+ finished = reprec.getreports("pytest_collectreport")
+ assert len(started) == len(finished)
+ assert len(started) == 7 # XXX extra TopCollector
+ colfail = [x for x in finished if x.failed]
+ assert len(colfail) == 1
+
+ def test_minus_x_import_error(self, testdir):
+ testdir.makepyfile(__init__="")
+ testdir.makepyfile(test_one="xxxx", test_two="yyyy")
+ reprec = testdir.inline_run("-x", testdir.tmpdir)
+ finished = reprec.getreports("pytest_collectreport")
+ colfail = [x for x in finished if x.failed]
+ assert len(colfail) == 1
+
+ def test_minus_x_overridden_by_maxfail(self, testdir):
+ testdir.makepyfile(__init__="")
+ testdir.makepyfile(test_one="xxxx", test_two="yyyy", test_third="zzz")
+ reprec = testdir.inline_run("-x", "--maxfail=2", testdir.tmpdir)
+ finished = reprec.getreports("pytest_collectreport")
+ colfail = [x for x in finished if x.failed]
+ assert len(colfail) == 2
+
+
+def test_plugin_specify(testdir):
+ pytest.raises(ImportError, """
+ testdir.parseconfig("-p", "nqweotexistent")
+ """)
+ # pytest.raises(ImportError,
+ # "config.do_configure(config)"
+ # )
+
+
+def test_plugin_already_exists(testdir):
+ config = testdir.parseconfig("-p", "terminal")
+ assert config.option.plugins == ['terminal']
+ config._do_configure()
+ config._ensure_unconfigure()
+
+
+def test_exclude(testdir):
+ hellodir = testdir.mkdir("hello")
+ hellodir.join("test_hello.py").write("x y syntaxerror")
+ hello2dir = testdir.mkdir("hello2")
+ hello2dir.join("test_hello2.py").write("x y syntaxerror")
+ testdir.makepyfile(test_ok="def test_pass(): pass")
+ result = testdir.runpytest("--ignore=hello", "--ignore=hello2")
+ assert result.ret == 0
+ result.stdout.fnmatch_lines(["*1 passed*"])
+
+
+def test_sessionfinish_with_start(testdir):
+ testdir.makeconftest("""
+ import os
+ values = []
+ def pytest_sessionstart():
+ values.append(os.getcwd())
+ os.chdir("..")
+
+ def pytest_sessionfinish():
+ assert values[0] == os.getcwd()
+
+ """)
+ res = testdir.runpytest("--collect-only")
+ assert res.ret == EXIT_NOTESTSCOLLECTED
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_skipping.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_skipping.py
new file mode 100644
index 00000000000..978944876f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_skipping.py
@@ -0,0 +1,1067 @@
+from __future__ import absolute_import, division, print_function
+import pytest
+import sys
+
+from _pytest.skipping import MarkEvaluator, folded_skips, pytest_runtest_setup
+from _pytest.runner import runtestprotocol
+
+
+class TestEvaluator(object):
+ def test_no_marker(self, testdir):
+ item = testdir.getitem("def test_func(): pass")
+ evalskipif = MarkEvaluator(item, 'skipif')
+ assert not evalskipif
+ assert not evalskipif.istrue()
+
+ def test_marked_no_args(self, testdir):
+ item = testdir.getitem("""
+ import pytest
+ @pytest.mark.xyz
+ def test_func():
+ pass
+ """)
+ ev = MarkEvaluator(item, 'xyz')
+ assert ev
+ assert ev.istrue()
+ expl = ev.getexplanation()
+ assert expl == ""
+ assert not ev.get("run", False)
+
+ def test_marked_one_arg(self, testdir):
+ item = testdir.getitem("""
+ import pytest
+ @pytest.mark.xyz("hasattr(os, 'sep')")
+ def test_func():
+ pass
+ """)
+ ev = MarkEvaluator(item, 'xyz')
+ assert ev
+ assert ev.istrue()
+ expl = ev.getexplanation()
+ assert expl == "condition: hasattr(os, 'sep')"
+
+ @pytest.mark.skipif('sys.version_info[0] >= 3')
+ def test_marked_one_arg_unicode(self, testdir):
+ item = testdir.getitem("""
+ import pytest
+ @pytest.mark.xyz(u"hasattr(os, 'sep')")
+ def test_func():
+ pass
+ """)
+ ev = MarkEvaluator(item, 'xyz')
+ assert ev
+ assert ev.istrue()
+ expl = ev.getexplanation()
+ assert expl == "condition: hasattr(os, 'sep')"
+
+ def test_marked_one_arg_with_reason(self, testdir):
+ item = testdir.getitem("""
+ import pytest
+ @pytest.mark.xyz("hasattr(os, 'sep')", attr=2, reason="hello world")
+ def test_func():
+ pass
+ """)
+ ev = MarkEvaluator(item, 'xyz')
+ assert ev
+ assert ev.istrue()
+ expl = ev.getexplanation()
+ assert expl == "hello world"
+ assert ev.get("attr") == 2
+
+ def test_marked_one_arg_twice(self, testdir):
+ lines = [
+ '''@pytest.mark.skipif("not hasattr(os, 'murks')")''',
+ '''@pytest.mark.skipif("hasattr(os, 'murks')")'''
+ ]
+ for i in range(0, 2):
+ item = testdir.getitem("""
+ import pytest
+ %s
+ %s
+ def test_func():
+ pass
+ """ % (lines[i], lines[(i + 1) % 2]))
+ ev = MarkEvaluator(item, 'skipif')
+ assert ev
+ assert ev.istrue()
+ expl = ev.getexplanation()
+ assert expl == "condition: not hasattr(os, 'murks')"
+
+ def test_marked_one_arg_twice2(self, testdir):
+ item = testdir.getitem("""
+ import pytest
+ @pytest.mark.skipif("hasattr(os, 'murks')")
+ @pytest.mark.skipif("not hasattr(os, 'murks')")
+ def test_func():
+ pass
+ """)
+ ev = MarkEvaluator(item, 'skipif')
+ assert ev
+ assert ev.istrue()
+ expl = ev.getexplanation()
+ assert expl == "condition: not hasattr(os, 'murks')"
+
+ def test_marked_skip_with_not_string(self, testdir):
+ item = testdir.getitem("""
+ import pytest
+ @pytest.mark.skipif(False)
+ def test_func():
+ pass
+ """)
+ ev = MarkEvaluator(item, 'skipif')
+ exc = pytest.raises(pytest.fail.Exception, ev.istrue)
+ assert """Failed: you need to specify reason=STRING when using booleans as conditions.""" in exc.value.msg
+
+ def test_skipif_class(self, testdir):
+ item, = testdir.getitems("""
+ import pytest
+ class TestClass(object):
+ pytestmark = pytest.mark.skipif("config._hackxyz")
+ def test_func(self):
+ pass
+ """)
+ item.config._hackxyz = 3
+ ev = MarkEvaluator(item, 'skipif')
+ assert ev.istrue()
+ expl = ev.getexplanation()
+ assert expl == "condition: config._hackxyz"
+
+
+class TestXFail(object):
+
+ @pytest.mark.parametrize('strict', [True, False])
+ def test_xfail_simple(self, testdir, strict):
+ item = testdir.getitem("""
+ import pytest
+ @pytest.mark.xfail(strict=%s)
+ def test_func():
+ assert 0
+ """ % strict)
+ reports = runtestprotocol(item, log=False)
+ assert len(reports) == 3
+ callreport = reports[1]
+ assert callreport.skipped
+ assert callreport.wasxfail == ""
+
+ def test_xfail_xpassed(self, testdir):
+ item = testdir.getitem("""
+ import pytest
+ @pytest.mark.xfail(reason="this is an xfail")
+ def test_func():
+ assert 1
+ """)
+ reports = runtestprotocol(item, log=False)
+ assert len(reports) == 3
+ callreport = reports[1]
+ assert callreport.passed
+ assert callreport.wasxfail == "this is an xfail"
+
+ def test_xfail_xpassed_strict(self, testdir):
+ item = testdir.getitem("""
+ import pytest
+ @pytest.mark.xfail(strict=True, reason="nope")
+ def test_func():
+ assert 1
+ """)
+ reports = runtestprotocol(item, log=False)
+ assert len(reports) == 3
+ callreport = reports[1]
+ assert callreport.failed
+ assert callreport.longrepr == "[XPASS(strict)] nope"
+ assert not hasattr(callreport, "wasxfail")
+
+ def test_xfail_run_anyway(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.xfail
+ def test_func():
+ assert 0
+ def test_func2():
+ pytest.xfail("hello")
+ """)
+ result = testdir.runpytest("--runxfail")
+ result.stdout.fnmatch_lines([
+ "*def test_func():*",
+ "*assert 0*",
+ "*1 failed*1 pass*",
+ ])
+
+ def test_xfail_evalfalse_but_fails(self, testdir):
+ item = testdir.getitem("""
+ import pytest
+ @pytest.mark.xfail('False')
+ def test_func():
+ assert 0
+ """)
+ reports = runtestprotocol(item, log=False)
+ callreport = reports[1]
+ assert callreport.failed
+ assert not hasattr(callreport, "wasxfail")
+ assert 'xfail' in callreport.keywords
+
+ def test_xfail_not_report_default(self, testdir):
+ p = testdir.makepyfile(test_one="""
+ import pytest
+ @pytest.mark.xfail
+ def test_this():
+ assert 0
+ """)
+ testdir.runpytest(p, '-v')
+ # result.stdout.fnmatch_lines([
+ # "*HINT*use*-r*"
+ # ])
+
+ def test_xfail_not_run_xfail_reporting(self, testdir):
+ p = testdir.makepyfile(test_one="""
+ import pytest
+ @pytest.mark.xfail(run=False, reason="noway")
+ def test_this():
+ assert 0
+ @pytest.mark.xfail("True", run=False)
+ def test_this_true():
+ assert 0
+ @pytest.mark.xfail("False", run=False, reason="huh")
+ def test_this_false():
+ assert 1
+ """)
+ result = testdir.runpytest(p, '-rx', )
+ result.stdout.fnmatch_lines([
+ "*test_one*test_this*",
+ "*NOTRUN*noway",
+ "*test_one*test_this_true*",
+ "*NOTRUN*condition:*True*",
+ "*1 passed*",
+ ])
+
+ def test_xfail_not_run_no_setup_run(self, testdir):
+ p = testdir.makepyfile(test_one="""
+ import pytest
+ @pytest.mark.xfail(run=False, reason="hello")
+ def test_this():
+ assert 0
+ def setup_module(mod):
+ raise ValueError(42)
+ """)
+ result = testdir.runpytest(p, '-rx', )
+ result.stdout.fnmatch_lines([
+ "*test_one*test_this*",
+ "*NOTRUN*hello",
+ "*1 xfailed*",
+ ])
+
+ def test_xfail_xpass(self, testdir):
+ p = testdir.makepyfile(test_one="""
+ import pytest
+ @pytest.mark.xfail
+ def test_that():
+ assert 1
+ """)
+ result = testdir.runpytest(p, '-rX')
+ result.stdout.fnmatch_lines([
+ "*XPASS*test_that*",
+ "*1 xpassed*"
+ ])
+ assert result.ret == 0
+
+ def test_xfail_imperative(self, testdir):
+ p = testdir.makepyfile("""
+ import pytest
+ def test_this():
+ pytest.xfail("hello")
+ """)
+ result = testdir.runpytest(p)
+ result.stdout.fnmatch_lines([
+ "*1 xfailed*",
+ ])
+ result = testdir.runpytest(p, "-rx")
+ result.stdout.fnmatch_lines([
+ "*XFAIL*test_this*",
+ "*reason:*hello*",
+ ])
+ result = testdir.runpytest(p, "--runxfail")
+ result.stdout.fnmatch_lines("*1 pass*")
+
+ def test_xfail_imperative_in_setup_function(self, testdir):
+ p = testdir.makepyfile("""
+ import pytest
+ def setup_function(function):
+ pytest.xfail("hello")
+
+ def test_this():
+ assert 0
+ """)
+ result = testdir.runpytest(p)
+ result.stdout.fnmatch_lines([
+ "*1 xfailed*",
+ ])
+ result = testdir.runpytest(p, "-rx")
+ result.stdout.fnmatch_lines([
+ "*XFAIL*test_this*",
+ "*reason:*hello*",
+ ])
+ result = testdir.runpytest(p, "--runxfail")
+ result.stdout.fnmatch_lines("""
+ *def test_this*
+ *1 fail*
+ """)
+
+ def xtest_dynamic_xfail_set_during_setup(self, testdir):
+ p = testdir.makepyfile("""
+ import pytest
+ def setup_function(function):
+ pytest.mark.xfail(function)
+ def test_this():
+ assert 0
+ def test_that():
+ assert 1
+ """)
+ result = testdir.runpytest(p, '-rxX')
+ result.stdout.fnmatch_lines([
+ "*XFAIL*test_this*",
+ "*XPASS*test_that*",
+ ])
+
+ def test_dynamic_xfail_no_run(self, testdir):
+ p = testdir.makepyfile("""
+ import pytest
+ @pytest.fixture
+ def arg(request):
+ request.applymarker(pytest.mark.xfail(run=False))
+ def test_this(arg):
+ assert 0
+ """)
+ result = testdir.runpytest(p, '-rxX')
+ result.stdout.fnmatch_lines([
+ "*XFAIL*test_this*",
+ "*NOTRUN*",
+ ])
+
+ def test_dynamic_xfail_set_during_funcarg_setup(self, testdir):
+ p = testdir.makepyfile("""
+ import pytest
+ @pytest.fixture
+ def arg(request):
+ request.applymarker(pytest.mark.xfail)
+ def test_this2(arg):
+ assert 0
+ """)
+ result = testdir.runpytest(p)
+ result.stdout.fnmatch_lines([
+ "*1 xfailed*",
+ ])
+
+ @pytest.mark.parametrize('expected, actual, matchline',
+ [('TypeError', 'TypeError', "*1 xfailed*"),
+ ('(AttributeError, TypeError)', 'TypeError', "*1 xfailed*"),
+ ('TypeError', 'IndexError', "*1 failed*"),
+ ('(AttributeError, TypeError)', 'IndexError', "*1 failed*"),
+ ])
+ def test_xfail_raises(self, expected, actual, matchline, testdir):
+ p = testdir.makepyfile("""
+ import pytest
+ @pytest.mark.xfail(raises=%s)
+ def test_raises():
+ raise %s()
+ """ % (expected, actual))
+ result = testdir.runpytest(p)
+ result.stdout.fnmatch_lines([
+ matchline,
+ ])
+
+ def test_strict_sanity(self, testdir):
+ """sanity check for xfail(strict=True): a failing test should behave
+ exactly like a normal xfail.
+ """
+ p = testdir.makepyfile("""
+ import pytest
+ @pytest.mark.xfail(reason='unsupported feature', strict=True)
+ def test_foo():
+ assert 0
+ """)
+ result = testdir.runpytest(p, '-rxX')
+ result.stdout.fnmatch_lines([
+ '*XFAIL*',
+ '*unsupported feature*',
+ ])
+ assert result.ret == 0
+
+ @pytest.mark.parametrize('strict', [True, False])
+ def test_strict_xfail(self, testdir, strict):
+ p = testdir.makepyfile("""
+ import pytest
+
+ @pytest.mark.xfail(reason='unsupported feature', strict=%s)
+ def test_foo():
+ with open('foo_executed', 'w'): pass # make sure test executes
+ """ % strict)
+ result = testdir.runpytest(p, '-rxX')
+ if strict:
+ result.stdout.fnmatch_lines([
+ '*test_foo*',
+ '*XPASS(strict)*unsupported feature*',
+ ])
+ else:
+ result.stdout.fnmatch_lines([
+ '*test_strict_xfail*',
+ 'XPASS test_strict_xfail.py::test_foo unsupported feature',
+ ])
+ assert result.ret == (1 if strict else 0)
+ assert testdir.tmpdir.join('foo_executed').isfile()
+
+ @pytest.mark.parametrize('strict', [True, False])
+ def test_strict_xfail_condition(self, testdir, strict):
+ p = testdir.makepyfile("""
+ import pytest
+
+ @pytest.mark.xfail(False, reason='unsupported feature', strict=%s)
+ def test_foo():
+ pass
+ """ % strict)
+ result = testdir.runpytest(p, '-rxX')
+ result.stdout.fnmatch_lines('*1 passed*')
+ assert result.ret == 0
+
+ @pytest.mark.parametrize('strict', [True, False])
+ def test_xfail_condition_keyword(self, testdir, strict):
+ p = testdir.makepyfile("""
+ import pytest
+
+ @pytest.mark.xfail(condition=False, reason='unsupported feature', strict=%s)
+ def test_foo():
+ pass
+ """ % strict)
+ result = testdir.runpytest(p, '-rxX')
+ result.stdout.fnmatch_lines('*1 passed*')
+ assert result.ret == 0
+
+ @pytest.mark.parametrize('strict_val', ['true', 'false'])
+ def test_strict_xfail_default_from_file(self, testdir, strict_val):
+ testdir.makeini('''
+ [pytest]
+ xfail_strict = %s
+ ''' % strict_val)
+ p = testdir.makepyfile("""
+ import pytest
+ @pytest.mark.xfail(reason='unsupported feature')
+ def test_foo():
+ pass
+ """)
+ result = testdir.runpytest(p, '-rxX')
+ strict = strict_val == 'true'
+ result.stdout.fnmatch_lines('*1 failed*' if strict else '*1 xpassed*')
+ assert result.ret == (1 if strict else 0)
+
+
+class TestXFailwithSetupTeardown(object):
+ def test_failing_setup_issue9(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ def setup_function(func):
+ assert 0
+
+ @pytest.mark.xfail
+ def test_func():
+ pass
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*1 xfail*",
+ ])
+
+ def test_failing_teardown_issue9(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ def teardown_function(func):
+ assert 0
+
+ @pytest.mark.xfail
+ def test_func():
+ pass
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*1 xfail*",
+ ])
+
+
+class TestSkip(object):
+ def test_skip_class(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.skip
+ class TestSomething(object):
+ def test_foo(self):
+ pass
+ def test_bar(self):
+ pass
+
+ def test_baz():
+ pass
+ """)
+ rec = testdir.inline_run()
+ rec.assertoutcome(skipped=2, passed=1)
+
+ def test_skips_on_false_string(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.skip('False')
+ def test_foo():
+ pass
+ """)
+ rec = testdir.inline_run()
+ rec.assertoutcome(skipped=1)
+
+ def test_arg_as_reason(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.skip('testing stuff')
+ def test_bar():
+ pass
+ """)
+ result = testdir.runpytest('-rs')
+ result.stdout.fnmatch_lines([
+ "*testing stuff*",
+ "*1 skipped*",
+ ])
+
+ def test_skip_no_reason(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.skip
+ def test_foo():
+ pass
+ """)
+ result = testdir.runpytest('-rs')
+ result.stdout.fnmatch_lines([
+ "*unconditional skip*",
+ "*1 skipped*",
+ ])
+
+ def test_skip_with_reason(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.skip(reason="for lolz")
+ def test_bar():
+ pass
+ """)
+ result = testdir.runpytest('-rs')
+ result.stdout.fnmatch_lines([
+ "*for lolz*",
+ "*1 skipped*",
+ ])
+
+ def test_only_skips_marked_test(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.skip
+ def test_foo():
+ pass
+ @pytest.mark.skip(reason="nothing in particular")
+ def test_bar():
+ pass
+ def test_baz():
+ assert True
+ """)
+ result = testdir.runpytest('-rs')
+ result.stdout.fnmatch_lines([
+ "*nothing in particular*",
+ "*1 passed*2 skipped*",
+ ])
+
+ def test_strict_and_skip(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.skip
+ def test_hello():
+ pass
+ """)
+ result = testdir.runpytest("-rs")
+ result.stdout.fnmatch_lines([
+ "*unconditional skip*",
+ "*1 skipped*",
+ ])
+
+
+class TestSkipif(object):
+ def test_skipif_conditional(self, testdir):
+ item = testdir.getitem("""
+ import pytest
+ @pytest.mark.skipif("hasattr(os, 'sep')")
+ def test_func():
+ pass
+ """) # noqa
+ x = pytest.raises(pytest.skip.Exception, lambda:
+ pytest_runtest_setup(item))
+ assert x.value.msg == "condition: hasattr(os, 'sep')"
+
+ @pytest.mark.parametrize('params', [
+ '"hasattr(sys, \'platform\')"',
+ 'True, reason="invalid platform"',
+ ])
+ def test_skipif_reporting(self, testdir, params):
+ p = testdir.makepyfile(test_foo="""
+ import pytest
+ @pytest.mark.skipif(%(params)s)
+ def test_that():
+ assert 0
+ """ % dict(params=params))
+ result = testdir.runpytest(p, '-s', '-rs')
+ result.stdout.fnmatch_lines([
+ "*SKIP*1*test_foo.py*platform*",
+ "*1 skipped*"
+ ])
+ assert result.ret == 0
+
+ @pytest.mark.parametrize('marker, msg1, msg2', [
+ ('skipif', 'SKIP', 'skipped'),
+ ('xfail', 'XPASS', 'xpassed'),
+ ])
+ def test_skipif_reporting_multiple(self, testdir, marker, msg1, msg2):
+ testdir.makepyfile(test_foo="""
+ import pytest
+ @pytest.mark.{marker}(False, reason='first_condition')
+ @pytest.mark.{marker}(True, reason='second_condition')
+ def test_foobar():
+ assert 1
+ """.format(marker=marker))
+ result = testdir.runpytest('-s', '-rsxX')
+ result.stdout.fnmatch_lines([
+ "*{msg1}*test_foo.py*second_condition*".format(msg1=msg1),
+ "*1 {msg2}*".format(msg2=msg2),
+ ])
+ assert result.ret == 0
+
+
+def test_skip_not_report_default(testdir):
+ p = testdir.makepyfile(test_one="""
+ import pytest
+ def test_this():
+ pytest.skip("hello")
+ """)
+ result = testdir.runpytest(p, '-v')
+ result.stdout.fnmatch_lines([
+ # "*HINT*use*-r*",
+ "*1 skipped*",
+ ])
+
+
+def test_skipif_class(testdir):
+ p = testdir.makepyfile("""
+ import pytest
+
+ class TestClass(object):
+ pytestmark = pytest.mark.skipif("True")
+ def test_that(self):
+ assert 0
+ def test_though(self):
+ assert 0
+ """)
+ result = testdir.runpytest(p)
+ result.stdout.fnmatch_lines([
+ "*2 skipped*"
+ ])
+
+
+def test_skip_reasons_folding():
+ path = "xyz"
+ lineno = 3
+ message = "justso"
+ longrepr = (path, lineno, message)
+
+ class X(object):
+ pass
+ ev1 = X()
+ ev1.when = "execute"
+ ev1.skipped = True
+ ev1.longrepr = longrepr
+
+ ev2 = X()
+ ev2.when = "execute"
+ ev2.longrepr = longrepr
+ ev2.skipped = True
+
+ # ev3 might be a collection report
+ ev3 = X()
+ ev3.longrepr = longrepr
+ ev3.skipped = True
+
+ values = folded_skips([ev1, ev2, ev3])
+ assert len(values) == 1
+ num, fspath, lineno, reason = values[0]
+ assert num == 3
+ assert fspath == path
+ assert lineno == lineno
+ assert reason == message
+
+
+def test_skipped_reasons_functional(testdir):
+ testdir.makepyfile(
+ test_one="""
+ from conftest import doskip
+ def setup_function(func):
+ doskip()
+ def test_func():
+ pass
+ class TestClass(object):
+ def test_method(self):
+ doskip()
+ """,
+ conftest="""
+ import pytest
+ def doskip():
+ pytest.skip('test')
+ """
+ )
+ result = testdir.runpytest('-rs')
+ result.stdout.fnmatch_lines([
+ "*SKIP*2*conftest.py:4: test",
+ ])
+ assert result.ret == 0
+
+
+def test_skipped_folding(testdir):
+ testdir.makepyfile(
+ test_one="""
+ import pytest
+ pytestmark = pytest.mark.skip("Folding")
+ def setup_function(func):
+ pass
+ def test_func():
+ pass
+ class TestClass(object):
+ def test_method(self):
+ pass
+ """,
+ )
+ result = testdir.runpytest('-rs')
+ result.stdout.fnmatch_lines([
+ "*SKIP*2*test_one.py: Folding"
+ ])
+ assert result.ret == 0
+
+
+def test_reportchars(testdir):
+ testdir.makepyfile("""
+ import pytest
+ def test_1():
+ assert 0
+ @pytest.mark.xfail
+ def test_2():
+ assert 0
+ @pytest.mark.xfail
+ def test_3():
+ pass
+ def test_4():
+ pytest.skip("four")
+ """)
+ result = testdir.runpytest("-rfxXs")
+ result.stdout.fnmatch_lines([
+ "FAIL*test_1*",
+ "XFAIL*test_2*",
+ "XPASS*test_3*",
+ "SKIP*four*",
+ ])
+
+
+def test_reportchars_error(testdir):
+ testdir.makepyfile(
+ conftest="""
+ def pytest_runtest_teardown():
+ assert 0
+ """,
+ test_simple="""
+ def test_foo():
+ pass
+ """)
+ result = testdir.runpytest('-rE')
+ result.stdout.fnmatch_lines([
+ 'ERROR*test_foo*',
+ ])
+
+
+def test_reportchars_all(testdir):
+ testdir.makepyfile("""
+ import pytest
+ def test_1():
+ assert 0
+ @pytest.mark.xfail
+ def test_2():
+ assert 0
+ @pytest.mark.xfail
+ def test_3():
+ pass
+ def test_4():
+ pytest.skip("four")
+ """)
+ result = testdir.runpytest("-ra")
+ result.stdout.fnmatch_lines([
+ "FAIL*test_1*",
+ "SKIP*four*",
+ "XFAIL*test_2*",
+ "XPASS*test_3*",
+ ])
+
+
+def test_reportchars_all_error(testdir):
+ testdir.makepyfile(
+ conftest="""
+ def pytest_runtest_teardown():
+ assert 0
+ """,
+ test_simple="""
+ def test_foo():
+ pass
+ """)
+ result = testdir.runpytest('-ra')
+ result.stdout.fnmatch_lines([
+ 'ERROR*test_foo*',
+ ])
+
+
+@pytest.mark.xfail("hasattr(sys, 'pypy_version_info')")
+def test_errors_in_xfail_skip_expressions(testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.skipif("asd")
+ def test_nameerror():
+ pass
+ @pytest.mark.xfail("syntax error")
+ def test_syntax():
+ pass
+
+ def test_func():
+ pass
+ """)
+ result = testdir.runpytest()
+ markline = " ^"
+ if sys.platform.startswith("java"):
+ # XXX report this to java
+ markline = "*" + markline[8:]
+ result.stdout.fnmatch_lines([
+ "*ERROR*test_nameerror*",
+ "*evaluating*skipif*expression*",
+ "*asd*",
+ "*ERROR*test_syntax*",
+ "*evaluating*xfail*expression*",
+ " syntax error",
+ markline,
+ "SyntaxError: invalid syntax",
+ "*1 pass*2 error*",
+ ])
+
+
+def test_xfail_skipif_with_globals(testdir):
+ testdir.makepyfile("""
+ import pytest
+ x = 3
+ @pytest.mark.skipif("x == 3")
+ def test_skip1():
+ pass
+ @pytest.mark.xfail("x == 3")
+ def test_boolean():
+ assert 0
+ """)
+ result = testdir.runpytest("-rsx")
+ result.stdout.fnmatch_lines([
+ "*SKIP*x == 3*",
+ "*XFAIL*test_boolean*",
+ "*x == 3*",
+ ])
+
+
+def test_direct_gives_error(testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.skipif(True)
+ def test_skip1():
+ pass
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*1 error*",
+ ])
+
+
+def test_default_markers(testdir):
+ result = testdir.runpytest("--markers")
+ result.stdout.fnmatch_lines([
+ "*skipif(*condition)*skip*",
+ "*xfail(*condition, reason=None, run=True, raises=None, strict=False)*expected failure*",
+ ])
+
+
+def test_xfail_test_setup_exception(testdir):
+ testdir.makeconftest("""
+ def pytest_runtest_setup():
+ 0 / 0
+ """)
+ p = testdir.makepyfile("""
+ import pytest
+ @pytest.mark.xfail
+ def test_func():
+ assert 0
+ """)
+ result = testdir.runpytest(p)
+ assert result.ret == 0
+ assert 'xfailed' in result.stdout.str()
+ assert 'xpassed' not in result.stdout.str()
+
+
+def test_imperativeskip_on_xfail_test(testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.xfail
+ def test_that_fails():
+ assert 0
+
+ @pytest.mark.skipif("True")
+ def test_hello():
+ pass
+ """)
+ testdir.makeconftest("""
+ import pytest
+ def pytest_runtest_setup(item):
+ pytest.skip("abc")
+ """)
+ result = testdir.runpytest("-rsxX")
+ result.stdout.fnmatch_lines_random("""
+ *SKIP*abc*
+ *SKIP*condition: True*
+ *2 skipped*
+ """)
+
+
+class TestBooleanCondition(object):
+ def test_skipif(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.skipif(True, reason="True123")
+ def test_func1():
+ pass
+ @pytest.mark.skipif(False, reason="True123")
+ def test_func2():
+ pass
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines("""
+ *1 passed*1 skipped*
+ """)
+
+ def test_skipif_noreason(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.skipif(True)
+ def test_func():
+ pass
+ """)
+ result = testdir.runpytest("-rs")
+ result.stdout.fnmatch_lines("""
+ *1 error*
+ """)
+
+ def test_xfail(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.xfail(True, reason="True123")
+ def test_func():
+ assert 0
+ """)
+ result = testdir.runpytest("-rxs")
+ result.stdout.fnmatch_lines("""
+ *XFAIL*
+ *True123*
+ *1 xfail*
+ """)
+
+
+def test_xfail_item(testdir):
+ # Ensure pytest.xfail works with non-Python Item
+ testdir.makeconftest("""
+ import pytest
+
+ class MyItem(pytest.Item):
+ nodeid = 'foo'
+ def runtest(self):
+ pytest.xfail("Expected Failure")
+
+ def pytest_collect_file(path, parent):
+ return MyItem("foo", parent)
+ """)
+ result = testdir.inline_run()
+ passed, skipped, failed = result.listoutcomes()
+ assert not failed
+ xfailed = [r for r in skipped if hasattr(r, 'wasxfail')]
+ assert xfailed
+
+
+def test_module_level_skip_error(testdir):
+ """
+ Verify that using pytest.skip at module level causes a collection error
+ """
+ testdir.makepyfile("""
+ import pytest
+ @pytest.skip
+ def test_func():
+ assert True
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(
+ "*Using pytest.skip outside of a test is not allowed*"
+ )
+
+
+def test_module_level_skip_with_allow_module_level(testdir):
+ """
+ Verify that using pytest.skip(allow_module_level=True) is allowed
+ """
+ testdir.makepyfile("""
+ import pytest
+ pytest.skip("skip_module_level", allow_module_level=True)
+
+ def test_func():
+ assert 0
+ """)
+ result = testdir.runpytest("-rxs")
+ result.stdout.fnmatch_lines(
+ "*SKIP*skip_module_level"
+ )
+
+
+def test_invalid_skip_keyword_parameter(testdir):
+ """
+ Verify that using pytest.skip() with unknown parameter raises an error
+ """
+ testdir.makepyfile("""
+ import pytest
+ pytest.skip("skip_module_level", unknown=1)
+
+ def test_func():
+ assert 0
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(
+ "*TypeError:*['unknown']*"
+ )
+
+
+def test_mark_xfail_item(testdir):
+ # Ensure pytest.mark.xfail works with non-Python Item
+ testdir.makeconftest("""
+ import pytest
+
+ class MyItem(pytest.Item):
+ nodeid = 'foo'
+ def setup(self):
+ marker = pytest.mark.xfail(True, reason="Expected failure")
+ self.add_marker(marker)
+ def runtest(self):
+ assert False
+
+ def pytest_collect_file(path, parent):
+ return MyItem("foo", parent)
+ """)
+ result = testdir.inline_run()
+ passed, skipped, failed = result.listoutcomes()
+ assert not failed
+ xfailed = [r for r in skipped if hasattr(r, 'wasxfail')]
+ assert xfailed
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_terminal.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_terminal.py
new file mode 100644
index 00000000000..97c2f71fb66
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_terminal.py
@@ -0,0 +1,1039 @@
+"""
+terminal reporting of the full testing process.
+"""
+from __future__ import absolute_import, division, print_function
+import collections
+import sys
+
+import pluggy
+import _pytest._code
+import py
+import pytest
+from _pytest.main import EXIT_NOTESTSCOLLECTED
+from _pytest.terminal import TerminalReporter, repr_pythonversion, getreportopt
+from _pytest.terminal import build_summary_stats_line, _plugin_nameversions
+
+
+DistInfo = collections.namedtuple('DistInfo', ['project_name', 'version'])
+
+
+class Option(object):
+ def __init__(self, verbose=False, fulltrace=False):
+ self.verbose = verbose
+ self.fulltrace = fulltrace
+
+ @property
+ def args(self):
+ values = []
+ if self.verbose:
+ values.append('-v')
+ if self.fulltrace:
+ values.append('--fulltrace')
+ return values
+
+
+def pytest_generate_tests(metafunc):
+ if "option" in metafunc.fixturenames:
+ metafunc.addcall(id="default",
+ funcargs={'option': Option(verbose=False)})
+ metafunc.addcall(id="verbose",
+ funcargs={'option': Option(verbose=True)})
+ metafunc.addcall(id="quiet",
+ funcargs={'option': Option(verbose=-1)})
+ metafunc.addcall(id="fulltrace",
+ funcargs={'option': Option(fulltrace=True)})
+
+
+@pytest.mark.parametrize('input,expected', [
+ ([DistInfo(project_name='test', version=1)], ['test-1']),
+ ([DistInfo(project_name='pytest-test', version=1)], ['test-1']),
+ ([
+ DistInfo(project_name='test', version=1),
+ DistInfo(project_name='test', version=1)
+ ], ['test-1']),
+], ids=['normal', 'prefix-strip', 'deduplicate'])
+def test_plugin_nameversion(input, expected):
+ pluginlist = [(None, x) for x in input]
+ result = _plugin_nameversions(pluginlist)
+ assert result == expected
+
+
+class TestTerminal(object):
+ def test_pass_skip_fail(self, testdir, option):
+ testdir.makepyfile("""
+ import pytest
+ def test_ok():
+ pass
+ def test_skip():
+ pytest.skip("xx")
+ def test_func():
+ assert 0
+ """)
+ result = testdir.runpytest(*option.args)
+ if option.verbose:
+ result.stdout.fnmatch_lines([
+ "*test_pass_skip_fail.py::test_ok PASS*",
+ "*test_pass_skip_fail.py::test_skip SKIP*",
+ "*test_pass_skip_fail.py::test_func FAIL*",
+ ])
+ else:
+ result.stdout.fnmatch_lines([
+ "*test_pass_skip_fail.py .sF*"
+ ])
+ result.stdout.fnmatch_lines([
+ " def test_func():",
+ "> assert 0",
+ "E assert 0",
+ ])
+
+ def test_internalerror(self, testdir, linecomp):
+ modcol = testdir.getmodulecol("def test_one(): pass")
+ rep = TerminalReporter(modcol.config, file=linecomp.stringio)
+ excinfo = pytest.raises(ValueError, "raise ValueError('hello')")
+ rep.pytest_internalerror(excinfo.getrepr())
+ linecomp.assert_contains_lines([
+ "INTERNALERROR> *ValueError*hello*"
+ ])
+
+ def test_writeline(self, testdir, linecomp):
+ modcol = testdir.getmodulecol("def test_one(): pass")
+ rep = TerminalReporter(modcol.config, file=linecomp.stringio)
+ rep.write_fspath_result(modcol.nodeid, ".")
+ rep.write_line("hello world")
+ lines = linecomp.stringio.getvalue().split('\n')
+ assert not lines[0]
+ assert lines[1].endswith(modcol.name + " .")
+ assert lines[2] == "hello world"
+
+ def test_show_runtest_logstart(self, testdir, linecomp):
+ item = testdir.getitem("def test_func(): pass")
+ tr = TerminalReporter(item.config, file=linecomp.stringio)
+ item.config.pluginmanager.register(tr)
+ location = item.reportinfo()
+ tr.config.hook.pytest_runtest_logstart(nodeid=item.nodeid,
+ location=location, fspath=str(item.fspath))
+ linecomp.assert_contains_lines([
+ "*test_show_runtest_logstart.py*"
+ ])
+
+ def test_runtest_location_shown_before_test_starts(self, testdir):
+ testdir.makepyfile("""
+ def test_1():
+ import time
+ time.sleep(20)
+ """)
+ child = testdir.spawn_pytest("")
+ child.expect(".*test_runtest_location.*py")
+ child.sendeof()
+ child.kill(15)
+
+ def test_itemreport_subclasses_show_subclassed_file(self, testdir):
+ testdir.makepyfile(test_p1="""
+ class BaseTests(object):
+ def test_p1(self):
+ pass
+ class TestClass(BaseTests):
+ pass
+ """)
+ p2 = testdir.makepyfile(test_p2="""
+ from test_p1 import BaseTests
+ class TestMore(BaseTests):
+ pass
+ """)
+ result = testdir.runpytest(p2)
+ result.stdout.fnmatch_lines([
+ "*test_p2.py .*",
+ "*1 passed*",
+ ])
+ result = testdir.runpytest("-v", p2)
+ result.stdout.fnmatch_lines([
+ "*test_p2.py::TestMore::test_p1* <- *test_p1.py*PASSED*",
+ ])
+
+ def test_itemreport_directclasses_not_shown_as_subclasses(self, testdir):
+ a = testdir.mkpydir("a123")
+ a.join("test_hello123.py").write(_pytest._code.Source("""
+ class TestClass(object):
+ def test_method(self):
+ pass
+ """))
+ result = testdir.runpytest("-v")
+ assert result.ret == 0
+ result.stdout.fnmatch_lines([
+ "*a123/test_hello123.py*PASS*",
+ ])
+ assert " <- " not in result.stdout.str()
+
+ def test_keyboard_interrupt(self, testdir, option):
+ testdir.makepyfile("""
+ def test_foobar():
+ assert 0
+ def test_spamegg():
+ import py; pytest.skip('skip me please!')
+ def test_interrupt_me():
+ raise KeyboardInterrupt # simulating the user
+ """)
+
+ result = testdir.runpytest(*option.args, no_reraise_ctrlc=True)
+ result.stdout.fnmatch_lines([
+ " def test_foobar():",
+ "> assert 0",
+ "E assert 0",
+ "*_keyboard_interrupt.py:6: KeyboardInterrupt*",
+ ])
+ if option.fulltrace:
+ result.stdout.fnmatch_lines([
+ "*raise KeyboardInterrupt # simulating the user*",
+ ])
+ else:
+ result.stdout.fnmatch_lines([
+ "to show a full traceback on KeyboardInterrupt use --fulltrace"
+ ])
+ result.stdout.fnmatch_lines(['*KeyboardInterrupt*'])
+
+ def test_keyboard_in_sessionstart(self, testdir):
+ testdir.makeconftest("""
+ def pytest_sessionstart():
+ raise KeyboardInterrupt
+ """)
+ testdir.makepyfile("""
+ def test_foobar():
+ pass
+ """)
+
+ result = testdir.runpytest(no_reraise_ctrlc=True)
+ assert result.ret == 2
+ result.stdout.fnmatch_lines(['*KeyboardInterrupt*'])
+
+ def test_collect_single_item(self, testdir):
+ """Use singular 'item' when reporting a single test item"""
+ testdir.makepyfile("""
+ def test_foobar():
+ pass
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines(['collected 1 item'])
+
+ def test_rewrite(self, testdir, monkeypatch):
+ config = testdir.parseconfig()
+ f = py.io.TextIO()
+ monkeypatch.setattr(f, 'isatty', lambda *args: True)
+ tr = TerminalReporter(config, f)
+ tr._tw.fullwidth = 10
+ tr.write('hello')
+ tr.rewrite('hey', erase=True)
+ assert f.getvalue() == 'hello' + '\r' + 'hey' + (6 * ' ')
+
+
+class TestCollectonly(object):
+ def test_collectonly_basic(self, testdir):
+ testdir.makepyfile("""
+ def test_func():
+ pass
+ """)
+ result = testdir.runpytest("--collect-only",)
+ result.stdout.fnmatch_lines([
+ "<Module 'test_collectonly_basic.py'>",
+ " <Function 'test_func'>",
+ ])
+
+ def test_collectonly_skipped_module(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ pytest.skip("hello")
+ """)
+ result = testdir.runpytest("--collect-only", "-rs")
+ result.stdout.fnmatch_lines([
+ "*ERROR collecting*",
+ ])
+
+ def test_collectonly_failed_module(self, testdir):
+ testdir.makepyfile("""raise ValueError(0)""")
+ result = testdir.runpytest("--collect-only")
+ result.stdout.fnmatch_lines([
+ "*raise ValueError*",
+ "*1 error*",
+ ])
+
+ def test_collectonly_fatal(self, testdir):
+ testdir.makeconftest("""
+ def pytest_collectstart(collector):
+ assert 0, "urgs"
+ """)
+ result = testdir.runpytest("--collect-only")
+ result.stdout.fnmatch_lines([
+ "*INTERNAL*args*"
+ ])
+ assert result.ret == 3
+
+ def test_collectonly_simple(self, testdir):
+ p = testdir.makepyfile("""
+ def test_func1():
+ pass
+ class TestClass(object):
+ def test_method(self):
+ pass
+ """)
+ result = testdir.runpytest("--collect-only", p)
+ # assert stderr.startswith("inserting into sys.path")
+ assert result.ret == 0
+ result.stdout.fnmatch_lines([
+ "*<Module '*.py'>",
+ "* <Function 'test_func1'*>",
+ "* <Class 'TestClass'>",
+ # "* <Instance '()'>",
+ "* <Function 'test_method'*>",
+ ])
+
+ def test_collectonly_error(self, testdir):
+ p = testdir.makepyfile("import Errlkjqweqwe")
+ result = testdir.runpytest("--collect-only", p)
+ assert result.ret == 2
+ result.stdout.fnmatch_lines(_pytest._code.Source("""
+ *ERROR*
+ *ImportError*
+ *No module named *Errlk*
+ *1 error*
+ """).strip())
+
+ def test_collectonly_missing_path(self, testdir):
+ """this checks issue 115,
+ failure in parseargs will cause session
+ not to have the items attribute
+ """
+ result = testdir.runpytest("--collect-only", "uhm_missing_path")
+ assert result.ret == 4
+ result.stderr.fnmatch_lines([
+ '*ERROR: file not found*',
+ ])
+
+ def test_collectonly_quiet(self, testdir):
+ testdir.makepyfile("def test_foo(): pass")
+ result = testdir.runpytest("--collect-only", "-q")
+ result.stdout.fnmatch_lines([
+ '*test_foo*',
+ ])
+
+ def test_collectonly_more_quiet(self, testdir):
+ testdir.makepyfile(test_fun="def test_foo(): pass")
+ result = testdir.runpytest("--collect-only", "-qq")
+ result.stdout.fnmatch_lines([
+ '*test_fun.py: 1*',
+ ])
+
+
+def test_repr_python_version(monkeypatch):
+ try:
+ monkeypatch.setattr(sys, 'version_info', (2, 5, 1, 'final', 0))
+ assert repr_pythonversion() == "2.5.1-final-0"
+ py.std.sys.version_info = x = (2, 3)
+ assert repr_pythonversion() == str(x)
+ finally:
+ monkeypatch.undo() # do this early as pytest can get confused
+
+
+class TestFixtureReporting(object):
+ def test_setup_fixture_error(self, testdir):
+ testdir.makepyfile("""
+ def setup_function(function):
+ print ("setup func")
+ assert 0
+ def test_nada():
+ pass
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*ERROR at setup of test_nada*",
+ "*setup_function(function):*",
+ "*setup func*",
+ "*assert 0*",
+ "*1 error*",
+ ])
+ assert result.ret != 0
+
+ def test_teardown_fixture_error(self, testdir):
+ testdir.makepyfile("""
+ def test_nada():
+ pass
+ def teardown_function(function):
+ print ("teardown func")
+ assert 0
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*ERROR at teardown*",
+ "*teardown_function(function):*",
+ "*assert 0*",
+ "*Captured stdout*",
+ "*teardown func*",
+ "*1 passed*1 error*",
+ ])
+
+ def test_teardown_fixture_error_and_test_failure(self, testdir):
+ testdir.makepyfile("""
+ def test_fail():
+ assert 0, "failingfunc"
+
+ def teardown_function(function):
+ print ("teardown func")
+ assert False
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*ERROR at teardown of test_fail*",
+ "*teardown_function(function):*",
+ "*assert False*",
+ "*Captured stdout*",
+ "*teardown func*",
+
+ "*test_fail*",
+ "*def test_fail():",
+ "*failingfunc*",
+ "*1 failed*1 error*",
+ ])
+
+ def test_setup_teardown_output_and_test_failure(self, testdir):
+ """ Test for issue #442 """
+ testdir.makepyfile("""
+ def setup_function(function):
+ print ("setup func")
+
+ def test_fail():
+ assert 0, "failingfunc"
+
+ def teardown_function(function):
+ print ("teardown func")
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*test_fail*",
+ "*def test_fail():",
+ "*failingfunc*",
+ "*Captured stdout setup*",
+ "*setup func*",
+ "*Captured stdout teardown*",
+ "*teardown func*",
+
+ "*1 failed*",
+ ])
+
+
+class TestTerminalFunctional(object):
+ def test_deselected(self, testdir):
+ testpath = testdir.makepyfile("""
+ def test_one():
+ pass
+ def test_two():
+ pass
+ def test_three():
+ pass
+ """
+ )
+ result = testdir.runpytest("-k", "test_two:", testpath)
+ result.stdout.fnmatch_lines([
+ "*test_deselected.py ..*",
+ "=* 1 test*deselected *=",
+ ])
+ assert result.ret == 0
+
+ def test_no_skip_summary_if_failure(self, testdir):
+ testdir.makepyfile("""
+ import pytest
+ def test_ok():
+ pass
+ def test_fail():
+ assert 0
+ def test_skip():
+ pytest.skip("dontshow")
+ """)
+ result = testdir.runpytest()
+ assert result.stdout.str().find("skip test summary") == -1
+ assert result.ret == 1
+
+ def test_passes(self, testdir):
+ p1 = testdir.makepyfile("""
+ def test_passes():
+ pass
+ class TestClass(object):
+ def test_method(self):
+ pass
+ """)
+ old = p1.dirpath().chdir()
+ try:
+ result = testdir.runpytest()
+ finally:
+ old.chdir()
+ result.stdout.fnmatch_lines([
+ "test_passes.py ..*",
+ "* 2 pass*",
+ ])
+ assert result.ret == 0
+
+ def test_header_trailer_info(self, testdir):
+ testdir.makepyfile("""
+ def test_passes():
+ pass
+ """)
+ result = testdir.runpytest()
+ verinfo = ".".join(map(str, py.std.sys.version_info[:3]))
+ result.stdout.fnmatch_lines([
+ "*===== test session starts ====*",
+ "platform %s -- Python %s*pytest-%s*py-%s*pluggy-%s" % (
+ py.std.sys.platform, verinfo,
+ pytest.__version__, py.__version__, pluggy.__version__),
+ "*test_header_trailer_info.py .*",
+ "=* 1 passed*in *.[0-9][0-9] seconds *=",
+ ])
+ if pytest.config.pluginmanager.list_plugin_distinfo():
+ result.stdout.fnmatch_lines([
+ "plugins: *",
+ ])
+
+ def test_showlocals(self, testdir):
+ p1 = testdir.makepyfile("""
+ def test_showlocals():
+ x = 3
+ y = "x" * 5000
+ assert 0
+ """)
+ result = testdir.runpytest(p1, '-l')
+ result.stdout.fnmatch_lines([
+ # "_ _ * Locals *",
+ "x* = 3",
+ "y* = 'xxxxxx*"
+ ])
+
+ def test_verbose_reporting(self, testdir, pytestconfig):
+ p1 = testdir.makepyfile("""
+ import pytest
+ def test_fail():
+ raise ValueError()
+ def test_pass():
+ pass
+ class TestClass(object):
+ def test_skip(self):
+ pytest.skip("hello")
+ def test_gen():
+ def check(x):
+ assert x == 1
+ yield check, 0
+ """)
+ result = testdir.runpytest(p1, '-v')
+ result.stdout.fnmatch_lines([
+ "*test_verbose_reporting.py::test_fail *FAIL*",
+ "*test_verbose_reporting.py::test_pass *PASS*",
+ "*test_verbose_reporting.py::TestClass::test_skip *SKIP*",
+ "*test_verbose_reporting.py::test_gen*0* *FAIL*",
+ ])
+ assert result.ret == 1
+
+ if not pytestconfig.pluginmanager.get_plugin("xdist"):
+ pytest.skip("xdist plugin not installed")
+
+ result = testdir.runpytest(p1, '-v', '-n 1')
+ result.stdout.fnmatch_lines([
+ "*FAIL*test_verbose_reporting.py::test_fail*",
+ ])
+ assert result.ret == 1
+
+ def test_quiet_reporting(self, testdir):
+ p1 = testdir.makepyfile("def test_pass(): pass")
+ result = testdir.runpytest(p1, '-q')
+ s = result.stdout.str()
+ assert 'test session starts' not in s
+ assert p1.basename not in s
+ assert "===" not in s
+ assert "passed" in s
+
+ def test_more_quiet_reporting(self, testdir):
+ p1 = testdir.makepyfile("def test_pass(): pass")
+ result = testdir.runpytest(p1, '-qq')
+ s = result.stdout.str()
+ assert 'test session starts' not in s
+ assert p1.basename not in s
+ assert "===" not in s
+ assert "passed" not in s
+
+ def test_report_collectionfinish_hook(self, testdir):
+ testdir.makeconftest("""
+ def pytest_report_collectionfinish(config, startdir, items):
+ return ['hello from hook: {0} items'.format(len(items))]
+ """)
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.parametrize('i', range(3))
+ def test(i):
+ pass
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "collected 3 items",
+ "hello from hook: 3 items",
+ ])
+
+
+def test_fail_extra_reporting(testdir):
+ testdir.makepyfile("def test_this(): assert 0")
+ result = testdir.runpytest()
+ assert 'short test summary' not in result.stdout.str()
+ result = testdir.runpytest('-rf')
+ result.stdout.fnmatch_lines([
+ "*test summary*",
+ "FAIL*test_fail_extra_reporting*",
+ ])
+
+
+def test_fail_reporting_on_pass(testdir):
+ testdir.makepyfile("def test_this(): assert 1")
+ result = testdir.runpytest('-rf')
+ assert 'short test summary' not in result.stdout.str()
+
+
+def test_pass_extra_reporting(testdir):
+ testdir.makepyfile("def test_this(): assert 1")
+ result = testdir.runpytest()
+ assert 'short test summary' not in result.stdout.str()
+ result = testdir.runpytest('-rp')
+ result.stdout.fnmatch_lines([
+ "*test summary*",
+ "PASS*test_pass_extra_reporting*",
+ ])
+
+
+def test_pass_reporting_on_fail(testdir):
+ testdir.makepyfile("def test_this(): assert 0")
+ result = testdir.runpytest('-rp')
+ assert 'short test summary' not in result.stdout.str()
+
+
+def test_pass_output_reporting(testdir):
+ testdir.makepyfile("""
+ def test_pass_output():
+ print("Four score and seven years ago...")
+ """)
+ result = testdir.runpytest()
+ assert 'Four score and seven years ago...' not in result.stdout.str()
+ result = testdir.runpytest('-rP')
+ result.stdout.fnmatch_lines([
+ "Four score and seven years ago...",
+ ])
+
+
+def test_color_yes(testdir):
+ testdir.makepyfile("def test_this(): assert 1")
+ result = testdir.runpytest('--color=yes')
+ assert 'test session starts' in result.stdout.str()
+ assert '\x1b[1m' in result.stdout.str()
+
+
+def test_color_no(testdir):
+ testdir.makepyfile("def test_this(): assert 1")
+ result = testdir.runpytest('--color=no')
+ assert 'test session starts' in result.stdout.str()
+ assert '\x1b[1m' not in result.stdout.str()
+
+
+@pytest.mark.parametrize('verbose', [True, False])
+def test_color_yes_collection_on_non_atty(testdir, verbose):
+ """skip collect progress report when working on non-terminals.
+ #1397
+ """
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.parametrize('i', range(10))
+ def test_this(i):
+ assert 1
+ """)
+ args = ['--color=yes']
+ if verbose:
+ args.append('-vv')
+ result = testdir.runpytest(*args)
+ assert 'test session starts' in result.stdout.str()
+ assert '\x1b[1m' in result.stdout.str()
+ assert 'collecting 10 items' not in result.stdout.str()
+ if verbose:
+ assert 'collecting ...' in result.stdout.str()
+ assert 'collected 10 items' in result.stdout.str()
+
+
+def test_getreportopt():
+ class config(object):
+ class option(object):
+ reportchars = ""
+ disable_warnings = True
+
+ config.option.reportchars = "sf"
+ assert getreportopt(config) == "sf"
+
+ config.option.reportchars = "sfxw"
+ assert getreportopt(config) == "sfx"
+
+ config.option.reportchars = "sfx"
+ config.option.disable_warnings = False
+ assert getreportopt(config) == "sfxw"
+
+ config.option.reportchars = "sfxw"
+ config.option.disable_warnings = False
+ assert getreportopt(config) == "sfxw"
+
+
+def test_terminalreporter_reportopt_addopts(testdir):
+ testdir.makeini("[pytest]\naddopts=-rs")
+ testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture
+ def tr(request):
+ tr = request.config.pluginmanager.getplugin("terminalreporter")
+ return tr
+ def test_opt(tr):
+ assert tr.hasopt('skipped')
+ assert not tr.hasopt('qwe')
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*1 passed*"
+ ])
+
+
+def test_tbstyle_short(testdir):
+ p = testdir.makepyfile("""
+ import pytest
+
+ @pytest.fixture
+ def arg(request):
+ return 42
+ def test_opt(arg):
+ x = 0
+ assert x
+ """)
+ result = testdir.runpytest("--tb=short")
+ s = result.stdout.str()
+ assert 'arg = 42' not in s
+ assert 'x = 0' not in s
+ result.stdout.fnmatch_lines([
+ "*%s:8*" % p.basename,
+ " assert x",
+ "E assert*",
+ ])
+ result = testdir.runpytest()
+ s = result.stdout.str()
+ assert 'x = 0' in s
+ assert 'assert x' in s
+
+
+def test_traceconfig(testdir, monkeypatch):
+ result = testdir.runpytest("--traceconfig")
+ result.stdout.fnmatch_lines([
+ "*active plugins*"
+ ])
+ assert result.ret == EXIT_NOTESTSCOLLECTED
+
+
+class TestGenericReporting(object):
+ """ this test class can be subclassed with a different option
+ provider to run e.g. distributed tests.
+ """
+
+ def test_collect_fail(self, testdir, option):
+ testdir.makepyfile("import xyz\n")
+ result = testdir.runpytest(*option.args)
+ result.stdout.fnmatch_lines([
+ "ImportError while importing*",
+ "*No module named *xyz*",
+ "*1 error*",
+ ])
+
+ def test_maxfailures(self, testdir, option):
+ testdir.makepyfile("""
+ def test_1():
+ assert 0
+ def test_2():
+ assert 0
+ def test_3():
+ assert 0
+ """)
+ result = testdir.runpytest("--maxfail=2", *option.args)
+ result.stdout.fnmatch_lines([
+ "*def test_1():*",
+ "*def test_2():*",
+ "*2 failed*",
+ ])
+
+ def test_tb_option(self, testdir, option):
+ testdir.makepyfile("""
+ import pytest
+ def g():
+ raise IndexError
+ def test_func():
+ print (6*7)
+ g() # --calling--
+ """)
+ for tbopt in ["long", "short", "no"]:
+ print('testing --tb=%s...' % tbopt)
+ result = testdir.runpytest('--tb=%s' % tbopt)
+ s = result.stdout.str()
+ if tbopt == "long":
+ assert 'print (6*7)' in s
+ else:
+ assert 'print (6*7)' not in s
+ if tbopt != "no":
+ assert '--calling--' in s
+ assert 'IndexError' in s
+ else:
+ assert 'FAILURES' not in s
+ assert '--calling--' not in s
+ assert 'IndexError' not in s
+
+ def test_tb_crashline(self, testdir, option):
+ p = testdir.makepyfile("""
+ import pytest
+ def g():
+ raise IndexError
+ def test_func1():
+ print (6*7)
+ g() # --calling--
+ def test_func2():
+ assert 0, "hello"
+ """)
+ result = testdir.runpytest("--tb=line")
+ bn = p.basename
+ result.stdout.fnmatch_lines([
+ "*%s:3: IndexError*" % bn,
+ "*%s:8: AssertionError: hello*" % bn,
+ ])
+ s = result.stdout.str()
+ assert "def test_func2" not in s
+
+ def test_pytest_report_header(self, testdir, option):
+ testdir.makeconftest("""
+ def pytest_sessionstart(session):
+ session.config._somevalue = 42
+ def pytest_report_header(config):
+ return "hello: %s" % config._somevalue
+ """)
+ testdir.mkdir("a").join("conftest.py").write("""
+def pytest_report_header(config, startdir):
+ return ["line1", str(startdir)]
+""")
+ result = testdir.runpytest("a")
+ result.stdout.fnmatch_lines([
+ "*hello: 42*",
+ "line1",
+ str(testdir.tmpdir),
+ ])
+
+
+@pytest.mark.xfail("not hasattr(os, 'dup')")
+def test_fdopen_kept_alive_issue124(testdir):
+ testdir.makepyfile("""
+ import os, sys
+ k = []
+ def test_open_file_and_keep_alive(capfd):
+ stdout = os.fdopen(1, 'w', 1)
+ k.append(stdout)
+
+ def test_close_kept_alive_file():
+ stdout = k.pop()
+ stdout.close()
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*2 passed*"
+ ])
+
+
+def test_tbstyle_native_setup_error(testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture
+ def setup_error_fixture():
+ raise Exception("error in exception")
+
+ def test_error_fixture(setup_error_fixture):
+ pass
+ """)
+ result = testdir.runpytest("--tb=native")
+ result.stdout.fnmatch_lines([
+ '*File *test_tbstyle_native_setup_error.py", line *, in setup_error_fixture*'
+ ])
+
+
+def test_terminal_summary(testdir):
+ testdir.makeconftest("""
+ def pytest_terminal_summary(terminalreporter, exitstatus):
+ w = terminalreporter
+ w.section("hello")
+ w.line("world")
+ w.line("exitstatus: {0}".format(exitstatus))
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines("""
+ *==== hello ====*
+ world
+ exitstatus: 5
+ """)
+
+
+def test_terminal_summary_warnings_are_displayed(testdir):
+ """Test that warnings emitted during pytest_terminal_summary are displayed.
+ (#1305).
+ """
+ testdir.makeconftest("""
+ def pytest_terminal_summary(terminalreporter):
+ config = terminalreporter.config
+ config.warn('C1', 'internal warning')
+ """)
+ result = testdir.runpytest('-rw')
+ result.stdout.fnmatch_lines([
+ '*internal warning',
+ '*== 1 warnings in *',
+ ])
+
+
+@pytest.mark.parametrize("exp_color, exp_line, stats_arg", [
+ # The method under test only cares about the length of each
+ # dict value, not the actual contents, so tuples of anything
+ # suffice
+
+ # Important statuses -- the highest priority of these always wins
+ ("red", "1 failed", {"failed": (1,)}),
+ ("red", "1 failed, 1 passed", {"failed": (1,), "passed": (1,)}),
+
+ ("red", "1 error", {"error": (1,)}),
+ ("red", "1 passed, 1 error", {"error": (1,), "passed": (1,)}),
+
+ # (a status that's not known to the code)
+ ("yellow", "1 weird", {"weird": (1,)}),
+ ("yellow", "1 passed, 1 weird", {"weird": (1,), "passed": (1,)}),
+
+ ("yellow", "1 warnings", {"warnings": (1,)}),
+ ("yellow", "1 passed, 1 warnings", {"warnings": (1,),
+ "passed": (1,)}),
+
+ ("green", "5 passed", {"passed": (1, 2, 3, 4, 5)}),
+
+
+ # "Boring" statuses. These have no effect on the color of the summary
+ # line. Thus, if *every* test has a boring status, the summary line stays
+ # at its default color, i.e. yellow, to warn the user that the test run
+ # produced no useful information
+ ("yellow", "1 skipped", {"skipped": (1,)}),
+ ("green", "1 passed, 1 skipped", {"skipped": (1,), "passed": (1,)}),
+
+ ("yellow", "1 deselected", {"deselected": (1,)}),
+ ("green", "1 passed, 1 deselected", {"deselected": (1,), "passed": (1,)}),
+
+ ("yellow", "1 xfailed", {"xfailed": (1,)}),
+ ("green", "1 passed, 1 xfailed", {"xfailed": (1,), "passed": (1,)}),
+
+ ("yellow", "1 xpassed", {"xpassed": (1,)}),
+ ("green", "1 passed, 1 xpassed", {"xpassed": (1,), "passed": (1,)}),
+
+ # Likewise if no tests were found at all
+ ("yellow", "no tests ran", {}),
+
+ # Test the empty-key special case
+ ("yellow", "no tests ran", {"": (1,)}),
+ ("green", "1 passed", {"": (1,), "passed": (1,)}),
+
+
+ # A couple more complex combinations
+ ("red", "1 failed, 2 passed, 3 xfailed",
+ {"passed": (1, 2), "failed": (1,), "xfailed": (1, 2, 3)}),
+
+ ("green", "1 passed, 2 skipped, 3 deselected, 2 xfailed",
+ {"passed": (1,),
+ "skipped": (1, 2),
+ "deselected": (1, 2, 3),
+ "xfailed": (1, 2)}),
+])
+def test_summary_stats(exp_line, exp_color, stats_arg):
+ print("Based on stats: %s" % stats_arg)
+ print("Expect summary: \"%s\"; with color \"%s\"" % (exp_line, exp_color))
+ (line, color) = build_summary_stats_line(stats_arg)
+ print("Actually got: \"%s\"; with color \"%s\"" % (line, color))
+ assert line == exp_line
+ assert color == exp_color
+
+
+def test_no_trailing_whitespace_after_inifile_word(testdir):
+ result = testdir.runpytest('')
+ assert 'inifile:\n' in result.stdout.str()
+
+ testdir.makeini('[pytest]')
+ result = testdir.runpytest('')
+ assert 'inifile: tox.ini\n' in result.stdout.str()
+
+
+class TestProgress:
+
+ @pytest.fixture
+ def many_tests_file(self, testdir):
+ testdir.makepyfile(
+ test_bar="""
+ import pytest
+ @pytest.mark.parametrize('i', range(10))
+ def test_bar(i): pass
+ """,
+ test_foo="""
+ import pytest
+ @pytest.mark.parametrize('i', range(5))
+ def test_foo(i): pass
+ """,
+ test_foobar="""
+ import pytest
+ @pytest.mark.parametrize('i', range(5))
+ def test_foobar(i): pass
+ """,
+ )
+
+ def test_zero_tests_collected(self, testdir):
+ """Some plugins (testmon for example) might issue pytest_runtest_logreport without any tests being
+ actually collected (#2971)."""
+ testdir.makeconftest("""
+ def pytest_collection_modifyitems(items, config):
+ from _pytest.runner import CollectReport
+ for node_id in ('nodeid1', 'nodeid2'):
+ rep = CollectReport(node_id, 'passed', None, None)
+ rep.when = 'passed'
+ rep.duration = 0.1
+ config.hook.pytest_runtest_logreport(report=rep)
+ """)
+ output = testdir.runpytest()
+ assert 'ZeroDivisionError' not in output.stdout.str()
+ output.stdout.fnmatch_lines([
+ '=* 2 passed in *=',
+ ])
+
+ def test_normal(self, many_tests_file, testdir):
+ output = testdir.runpytest()
+ output.stdout.re_match_lines([
+ r'test_bar.py \.{10} \s+ \[ 50%\]',
+ r'test_foo.py \.{5} \s+ \[ 75%\]',
+ r'test_foobar.py \.{5} \s+ \[100%\]',
+ ])
+
+ def test_verbose(self, many_tests_file, testdir):
+ output = testdir.runpytest('-v')
+ output.stdout.re_match_lines([
+ r'test_bar.py::test_bar\[0\] PASSED \s+ \[ 5%\]',
+ r'test_foo.py::test_foo\[4\] PASSED \s+ \[ 75%\]',
+ r'test_foobar.py::test_foobar\[4\] PASSED \s+ \[100%\]',
+ ])
+
+ def test_xdist_normal(self, many_tests_file, testdir):
+ pytest.importorskip('xdist')
+ output = testdir.runpytest('-n2')
+ output.stdout.re_match_lines([
+ r'\.{20} \s+ \[100%\]',
+ ])
+
+ def test_xdist_verbose(self, many_tests_file, testdir):
+ pytest.importorskip('xdist')
+ output = testdir.runpytest('-n2', '-v')
+ output.stdout.re_match_lines_random([
+ r'\[gw\d\] \[\s*\d+%\] PASSED test_bar.py::test_bar\[1\]',
+ r'\[gw\d\] \[\s*\d+%\] PASSED test_foo.py::test_foo\[1\]',
+ r'\[gw\d\] \[\s*\d+%\] PASSED test_foobar.py::test_foobar\[1\]',
+ ])
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_tmpdir.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_tmpdir.py
new file mode 100644
index 00000000000..467e77252e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_tmpdir.py
@@ -0,0 +1,188 @@
+from __future__ import absolute_import, division, print_function
+import sys
+import py
+import pytest
+
+from _pytest.tmpdir import tmpdir
+
+
+def test_funcarg(testdir):
+ testdir.makepyfile("""
+ def pytest_generate_tests(metafunc):
+ metafunc.addcall(id='a')
+ metafunc.addcall(id='b')
+ def test_func(tmpdir): pass
+ """)
+ from _pytest.tmpdir import TempdirFactory
+ reprec = testdir.inline_run()
+ calls = reprec.getcalls("pytest_runtest_setup")
+ item = calls[0].item
+ config = item.config
+ tmpdirhandler = TempdirFactory(config)
+ item._initrequest()
+ p = tmpdir(item._request, tmpdirhandler)
+ assert p.check()
+ bn = p.basename.strip("0123456789")
+ assert bn.endswith("test_func_a_")
+ item.name = "qwe/\\abc"
+ p = tmpdir(item._request, tmpdirhandler)
+ assert p.check()
+ bn = p.basename.strip("0123456789")
+ assert bn == "qwe__abc"
+
+
+def test_ensuretemp(recwarn):
+ d1 = pytest.ensuretemp('hello')
+ d2 = pytest.ensuretemp('hello')
+ assert d1 == d2
+ assert d1.check(dir=1)
+
+
+class TestTempdirHandler(object):
+ def test_mktemp(self, testdir):
+ from _pytest.tmpdir import TempdirFactory
+ config = testdir.parseconfig()
+ config.option.basetemp = testdir.mkdir("hello")
+ t = TempdirFactory(config)
+ tmp = t.mktemp("world")
+ assert tmp.relto(t.getbasetemp()) == "world0"
+ tmp = t.mktemp("this")
+ assert tmp.relto(t.getbasetemp()).startswith("this")
+ tmp2 = t.mktemp("this")
+ assert tmp2.relto(t.getbasetemp()).startswith("this")
+ assert tmp2 != tmp
+
+
+class TestConfigTmpdir(object):
+ def test_getbasetemp_custom_removes_old(self, testdir):
+ mytemp = testdir.tmpdir.join("xyz")
+ p = testdir.makepyfile("""
+ def test_1(tmpdir):
+ pass
+ """)
+ testdir.runpytest(p, '--basetemp=%s' % mytemp)
+ mytemp.check()
+ mytemp.ensure("hello")
+
+ testdir.runpytest(p, '--basetemp=%s' % mytemp)
+ mytemp.check()
+ assert not mytemp.join("hello").check()
+
+
+def test_basetemp(testdir):
+ mytemp = testdir.tmpdir.mkdir("mytemp")
+ p = testdir.makepyfile("""
+ import pytest
+ def test_1():
+ pytest.ensuretemp("hello")
+ """)
+ result = testdir.runpytest(p, '--basetemp=%s' % mytemp)
+ assert result.ret == 0
+ assert mytemp.join('hello').check()
+
+
+@pytest.mark.skipif(not hasattr(py.path.local, 'mksymlinkto'),
+ reason="symlink not available on this platform")
+def test_tmpdir_always_is_realpath(testdir):
+ # the reason why tmpdir should be a realpath is that
+ # when you cd to it and do "os.getcwd()" you will anyway
+ # get the realpath. Using the symlinked path can thus
+ # easily result in path-inequality
+ # XXX if that proves to be a problem, consider using
+ # os.environ["PWD"]
+ realtemp = testdir.tmpdir.mkdir("myrealtemp")
+ linktemp = testdir.tmpdir.join("symlinktemp")
+ linktemp.mksymlinkto(realtemp)
+ p = testdir.makepyfile("""
+ def test_1(tmpdir):
+ import os
+ assert os.path.realpath(str(tmpdir)) == str(tmpdir)
+ """)
+ result = testdir.runpytest("-s", p, '--basetemp=%s/bt' % linktemp)
+ assert not result.ret
+
+
+def test_tmpdir_too_long_on_parametrization(testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.mark.parametrize("arg", ["1"*1000])
+ def test_some(arg, tmpdir):
+ tmpdir.ensure("hello")
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+
+def test_tmpdir_factory(testdir):
+ testdir.makepyfile("""
+ import pytest
+ @pytest.fixture(scope='session')
+ def session_dir(tmpdir_factory):
+ return tmpdir_factory.mktemp('data', numbered=False)
+ def test_some(session_dir):
+ session_dir.isdir()
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+
+def test_tmpdir_fallback_tox_env(testdir, monkeypatch):
+ """Test that tmpdir works even if environment variables required by getpass
+ module are missing (#1010).
+ """
+ monkeypatch.delenv('USER', raising=False)
+ monkeypatch.delenv('USERNAME', raising=False)
+ testdir.makepyfile("""
+ import pytest
+ def test_some(tmpdir):
+ assert tmpdir.isdir()
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+
+@pytest.fixture
+def break_getuser(monkeypatch):
+ monkeypatch.setattr('os.getuid', lambda: -1)
+ # taken from python 2.7/3.4
+ for envvar in ('LOGNAME', 'USER', 'LNAME', 'USERNAME'):
+ monkeypatch.delenv(envvar, raising=False)
+
+
+@pytest.mark.usefixtures("break_getuser")
+@pytest.mark.skipif(sys.platform.startswith('win'), reason='no os.getuid on windows')
+def test_tmpdir_fallback_uid_not_found(testdir):
+ """Test that tmpdir works even if the current process's user id does not
+ correspond to a valid user.
+ """
+
+ testdir.makepyfile("""
+ import pytest
+ def test_some(tmpdir):
+ assert tmpdir.isdir()
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
+
+
+@pytest.mark.usefixtures("break_getuser")
+@pytest.mark.skipif(sys.platform.startswith('win'), reason='no os.getuid on windows')
+def test_get_user_uid_not_found():
+ """Test that get_user() function works even if the current process's
+ user id does not correspond to a valid user (e.g. running pytest in a
+ Docker container with 'docker run -u'.
+ """
+ from _pytest.tmpdir import get_user
+ assert get_user() is None
+
+
+@pytest.mark.skipif(not sys.platform.startswith('win'), reason='win only')
+def test_get_user(monkeypatch):
+ """Test that get_user() function works even if environment variables
+ required by getpass module are missing from the environment on Windows
+ (#1010).
+ """
+ from _pytest.tmpdir import get_user
+ monkeypatch.delenv('USER', raising=False)
+ monkeypatch.delenv('USERNAME', raising=False)
+ assert get_user() is None
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_unittest.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_unittest.py
new file mode 100644
index 00000000000..e197735871f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_unittest.py
@@ -0,0 +1,830 @@
+from __future__ import absolute_import, division, print_function
+from _pytest.main import EXIT_NOTESTSCOLLECTED
+import pytest
+import gc
+
+
+def test_simple_unittest(testdir):
+ testpath = testdir.makepyfile("""
+ import unittest
+ class MyTestCase(unittest.TestCase):
+ def testpassing(self):
+ self.assertEqual('foo', 'foo')
+ def test_failing(self):
+ self.assertEqual('foo', 'bar')
+ """)
+ reprec = testdir.inline_run(testpath)
+ assert reprec.matchreport("testpassing").passed
+ assert reprec.matchreport("test_failing").failed
+
+
+def test_runTest_method(testdir):
+ testdir.makepyfile("""
+ import unittest
+ class MyTestCaseWithRunTest(unittest.TestCase):
+ def runTest(self):
+ self.assertEqual('foo', 'foo')
+ class MyTestCaseWithoutRunTest(unittest.TestCase):
+ def runTest(self):
+ self.assertEqual('foo', 'foo')
+ def test_something(self):
+ pass
+ """)
+ result = testdir.runpytest("-v")
+ result.stdout.fnmatch_lines("""
+ *MyTestCaseWithRunTest::runTest*
+ *MyTestCaseWithoutRunTest::test_something*
+ *2 passed*
+ """)
+
+
+def test_isclasscheck_issue53(testdir):
+ testpath = testdir.makepyfile("""
+ import unittest
+ class _E(object):
+ def __getattr__(self, tag):
+ pass
+ E = _E()
+ """)
+ result = testdir.runpytest(testpath)
+ assert result.ret == EXIT_NOTESTSCOLLECTED
+
+
+def test_setup(testdir):
+ testpath = testdir.makepyfile("""
+ import unittest
+ class MyTestCase(unittest.TestCase):
+ def setUp(self):
+ self.foo = 1
+ def setup_method(self, method):
+ self.foo2 = 1
+ def test_both(self):
+ self.assertEqual(1, self.foo)
+ assert self.foo2 == 1
+ def teardown_method(self, method):
+ assert 0, "42"
+
+ """)
+ reprec = testdir.inline_run("-s", testpath)
+ assert reprec.matchreport("test_both", when="call").passed
+ rep = reprec.matchreport("test_both", when="teardown")
+ assert rep.failed and '42' in str(rep.longrepr)
+
+
+def test_setUpModule(testdir):
+ testpath = testdir.makepyfile("""
+ values = []
+
+ def setUpModule():
+ values.append(1)
+
+ def tearDownModule():
+ del values[0]
+
+ def test_hello():
+ assert values == [1]
+
+ def test_world():
+ assert values == [1]
+ """)
+ result = testdir.runpytest(testpath)
+ result.stdout.fnmatch_lines([
+ "*2 passed*",
+ ])
+
+
+def test_setUpModule_failing_no_teardown(testdir):
+ testpath = testdir.makepyfile("""
+ values = []
+
+ def setUpModule():
+ 0/0
+
+ def tearDownModule():
+ values.append(1)
+
+ def test_hello():
+ pass
+ """)
+ reprec = testdir.inline_run(testpath)
+ reprec.assertoutcome(passed=0, failed=1)
+ call = reprec.getcalls("pytest_runtest_setup")[0]
+ assert not call.item.module.values
+
+
+def test_new_instances(testdir):
+ testpath = testdir.makepyfile("""
+ import unittest
+ class MyTestCase(unittest.TestCase):
+ def test_func1(self):
+ self.x = 2
+ def test_func2(self):
+ assert not hasattr(self, 'x')
+ """)
+ reprec = testdir.inline_run(testpath)
+ reprec.assertoutcome(passed=2)
+
+
+def test_teardown(testdir):
+ testpath = testdir.makepyfile("""
+ import unittest
+ class MyTestCase(unittest.TestCase):
+ values = []
+ def test_one(self):
+ pass
+ def tearDown(self):
+ self.values.append(None)
+ class Second(unittest.TestCase):
+ def test_check(self):
+ self.assertEqual(MyTestCase.values, [None])
+ """)
+ reprec = testdir.inline_run(testpath)
+ passed, skipped, failed = reprec.countoutcomes()
+ assert failed == 0, failed
+ assert passed == 2
+ assert passed + skipped + failed == 2
+
+
+def test_teardown_issue1649(testdir):
+ """
+ Are TestCase objects cleaned up? Often unittest TestCase objects set
+ attributes that are large and expensive during setUp.
+
+ The TestCase will not be cleaned up if the test fails, because it
+ would then exist in the stackframe.
+ """
+ testpath = testdir.makepyfile("""
+ import unittest
+ class TestCaseObjectsShouldBeCleanedUp(unittest.TestCase):
+ def setUp(self):
+ self.an_expensive_object = 1
+ def test_demo(self):
+ pass
+
+ """)
+ testdir.inline_run("-s", testpath)
+ gc.collect()
+ for obj in gc.get_objects():
+ assert type(obj).__name__ != 'TestCaseObjectsShouldBeCleanedUp'
+
+
+def test_unittest_skip_issue148(testdir):
+ testpath = testdir.makepyfile("""
+ import unittest
+
+ @unittest.skip("hello")
+ class MyTestCase(unittest.TestCase):
+ @classmethod
+ def setUpClass(self):
+ xxx
+ def test_one(self):
+ pass
+ @classmethod
+ def tearDownClass(self):
+ xxx
+ """)
+ reprec = testdir.inline_run(testpath)
+ reprec.assertoutcome(skipped=1)
+
+
+def test_method_and_teardown_failing_reporting(testdir):
+ testdir.makepyfile("""
+ import unittest, pytest
+ class TC(unittest.TestCase):
+ def tearDown(self):
+ assert 0, "down1"
+ def test_method(self):
+ assert False, "down2"
+ """)
+ result = testdir.runpytest("-s")
+ assert result.ret == 1
+ result.stdout.fnmatch_lines([
+ "*tearDown*",
+ "*assert 0*",
+ "*test_method*",
+ "*assert False*",
+ "*1 failed*1 error*",
+ ])
+
+
+def test_setup_failure_is_shown(testdir):
+ testdir.makepyfile("""
+ import unittest
+ import pytest
+ class TC(unittest.TestCase):
+ def setUp(self):
+ assert 0, "down1"
+ def test_method(self):
+ print ("never42")
+ xyz
+ """)
+ result = testdir.runpytest("-s")
+ assert result.ret == 1
+ result.stdout.fnmatch_lines([
+ "*setUp*",
+ "*assert 0*down1*",
+ "*1 failed*",
+ ])
+ assert 'never42' not in result.stdout.str()
+
+
+def test_setup_setUpClass(testdir):
+ testpath = testdir.makepyfile("""
+ import unittest
+ import pytest
+ class MyTestCase(unittest.TestCase):
+ x = 0
+ @classmethod
+ def setUpClass(cls):
+ cls.x += 1
+ def test_func1(self):
+ assert self.x == 1
+ def test_func2(self):
+ assert self.x == 1
+ @classmethod
+ def tearDownClass(cls):
+ cls.x -= 1
+ def test_teareddown():
+ assert MyTestCase.x == 0
+ """)
+ reprec = testdir.inline_run(testpath)
+ reprec.assertoutcome(passed=3)
+
+
+def test_setup_class(testdir):
+ testpath = testdir.makepyfile("""
+ import unittest
+ import pytest
+ class MyTestCase(unittest.TestCase):
+ x = 0
+ def setup_class(cls):
+ cls.x += 1
+ def test_func1(self):
+ assert self.x == 1
+ def test_func2(self):
+ assert self.x == 1
+ def teardown_class(cls):
+ cls.x -= 1
+ def test_teareddown():
+ assert MyTestCase.x == 0
+ """)
+ reprec = testdir.inline_run(testpath)
+ reprec.assertoutcome(passed=3)
+
+
+@pytest.mark.parametrize("type", ['Error', 'Failure'])
+def test_testcase_adderrorandfailure_defers(testdir, type):
+ testdir.makepyfile("""
+ from unittest import TestCase
+ import pytest
+ class MyTestCase(TestCase):
+ def run(self, result):
+ excinfo = pytest.raises(ZeroDivisionError, lambda: 0/0)
+ try:
+ result.add%s(self, excinfo._excinfo)
+ except KeyboardInterrupt:
+ raise
+ except:
+ pytest.fail("add%s should not raise")
+ def test_hello(self):
+ pass
+ """ % (type, type))
+ result = testdir.runpytest()
+ assert 'should not raise' not in result.stdout.str()
+
+
+@pytest.mark.parametrize("type", ['Error', 'Failure'])
+def test_testcase_custom_exception_info(testdir, type):
+ testdir.makepyfile("""
+ from unittest import TestCase
+ import py, pytest
+ import _pytest._code
+ class MyTestCase(TestCase):
+ def run(self, result):
+ excinfo = pytest.raises(ZeroDivisionError, lambda: 0/0)
+ # we fake an incompatible exception info
+ from _pytest.monkeypatch import MonkeyPatch
+ mp = MonkeyPatch()
+ def t(*args):
+ mp.undo()
+ raise TypeError()
+ mp.setattr(_pytest._code, 'ExceptionInfo', t)
+ try:
+ excinfo = excinfo._excinfo
+ result.add%(type)s(self, excinfo)
+ finally:
+ mp.undo()
+ def test_hello(self):
+ pass
+ """ % locals())
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "NOTE: Incompatible Exception Representation*",
+ "*ZeroDivisionError*",
+ "*1 failed*",
+ ])
+
+
+def test_testcase_totally_incompatible_exception_info(testdir):
+ item, = testdir.getitems("""
+ from unittest import TestCase
+ class MyTestCase(TestCase):
+ def test_hello(self):
+ pass
+ """)
+ item.addError(None, 42)
+ excinfo = item._excinfo.pop(0)
+ assert 'ERROR: Unknown Incompatible' in str(excinfo.getrepr())
+
+
+def test_module_level_pytestmark(testdir):
+ testpath = testdir.makepyfile("""
+ import unittest
+ import pytest
+ pytestmark = pytest.mark.xfail
+ class MyTestCase(unittest.TestCase):
+ def test_func1(self):
+ assert 0
+ """)
+ reprec = testdir.inline_run(testpath, "-s")
+ reprec.assertoutcome(skipped=1)
+
+
+class TestTrialUnittest(object):
+ def setup_class(cls):
+ cls.ut = pytest.importorskip("twisted.trial.unittest")
+ # on windows trial uses a socket for a reactor and apparently doesn't close it properly
+ # https://twistedmatrix.com/trac/ticket/9227
+ cls.ignore_unclosed_socket_warning = ('-W', 'always')
+
+ def test_trial_testcase_runtest_not_collected(self, testdir):
+ testdir.makepyfile("""
+ from twisted.trial.unittest import TestCase
+
+ class TC(TestCase):
+ def test_hello(self):
+ pass
+ """)
+ reprec = testdir.inline_run(*self.ignore_unclosed_socket_warning)
+ reprec.assertoutcome(passed=1)
+ testdir.makepyfile("""
+ from twisted.trial.unittest import TestCase
+
+ class TC(TestCase):
+ def runTest(self):
+ pass
+ """)
+ reprec = testdir.inline_run(*self.ignore_unclosed_socket_warning)
+ reprec.assertoutcome(passed=1)
+
+ def test_trial_exceptions_with_skips(self, testdir):
+ testdir.makepyfile("""
+ from twisted.trial import unittest
+ import pytest
+ class TC(unittest.TestCase):
+ def test_hello(self):
+ pytest.skip("skip_in_method")
+ @pytest.mark.skipif("sys.version_info != 1")
+ def test_hello2(self):
+ pass
+ @pytest.mark.xfail(reason="iwanto")
+ def test_hello3(self):
+ assert 0
+ def test_hello4(self):
+ pytest.xfail("i2wanto")
+ def test_trial_skip(self):
+ pass
+ test_trial_skip.skip = "trialselfskip"
+
+ def test_trial_todo(self):
+ assert 0
+ test_trial_todo.todo = "mytodo"
+
+ def test_trial_todo_success(self):
+ pass
+ test_trial_todo_success.todo = "mytodo"
+
+ class TC2(unittest.TestCase):
+ def setup_class(cls):
+ pytest.skip("skip_in_setup_class")
+ def test_method(self):
+ pass
+ """)
+ from _pytest.compat import _is_unittest_unexpected_success_a_failure
+ should_fail = _is_unittest_unexpected_success_a_failure()
+ result = testdir.runpytest("-rxs", *self.ignore_unclosed_socket_warning)
+ result.stdout.fnmatch_lines_random([
+ "*XFAIL*test_trial_todo*",
+ "*trialselfskip*",
+ "*skip_in_setup_class*",
+ "*iwanto*",
+ "*i2wanto*",
+ "*sys.version_info*",
+ "*skip_in_method*",
+ "*1 failed*4 skipped*3 xfailed*" if should_fail else "*4 skipped*3 xfail*1 xpass*",
+ ])
+ assert result.ret == (1 if should_fail else 0)
+
+ def test_trial_error(self, testdir):
+ testdir.makepyfile("""
+ from twisted.trial.unittest import TestCase
+ from twisted.internet.defer import Deferred
+ from twisted.internet import reactor
+
+ class TC(TestCase):
+ def test_one(self):
+ crash
+
+ def test_two(self):
+ def f(_):
+ crash
+
+ d = Deferred()
+ d.addCallback(f)
+ reactor.callLater(0.3, d.callback, None)
+ return d
+
+ def test_three(self):
+ def f():
+ pass # will never get called
+ reactor.callLater(0.3, f)
+ # will crash at teardown
+
+ def test_four(self):
+ def f(_):
+ reactor.callLater(0.3, f)
+ crash
+
+ d = Deferred()
+ d.addCallback(f)
+ reactor.callLater(0.3, d.callback, None)
+ return d
+ # will crash both at test time and at teardown
+ """)
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ "*ERRORS*",
+ "*DelayedCalls*",
+ "*test_four*",
+ "*NameError*crash*",
+ "*test_one*",
+ "*NameError*crash*",
+ "*test_three*",
+ "*DelayedCalls*",
+ "*test_two*",
+ "*crash*",
+ ])
+
+ def test_trial_pdb(self, testdir):
+ p = testdir.makepyfile("""
+ from twisted.trial import unittest
+ import pytest
+ class TC(unittest.TestCase):
+ def test_hello(self):
+ assert 0, "hellopdb"
+ """)
+ child = testdir.spawn_pytest(p)
+ child.expect("hellopdb")
+ child.sendeof()
+
+ def test_trial_testcase_skip_property(self, testdir):
+ testpath = testdir.makepyfile("""
+ from twisted.trial import unittest
+ class MyTestCase(unittest.TestCase):
+ skip = 'dont run'
+ def test_func(self):
+ pass
+ """)
+ reprec = testdir.inline_run(testpath, "-s")
+ reprec.assertoutcome(skipped=1)
+
+ def test_trial_testfunction_skip_property(self, testdir):
+ testpath = testdir.makepyfile("""
+ from twisted.trial import unittest
+ class MyTestCase(unittest.TestCase):
+ def test_func(self):
+ pass
+ test_func.skip = 'dont run'
+ """)
+ reprec = testdir.inline_run(testpath, "-s")
+ reprec.assertoutcome(skipped=1)
+
+ def test_trial_testcase_todo_property(self, testdir):
+ testpath = testdir.makepyfile("""
+ from twisted.trial import unittest
+ class MyTestCase(unittest.TestCase):
+ todo = 'dont run'
+ def test_func(self):
+ assert 0
+ """)
+ reprec = testdir.inline_run(testpath, "-s")
+ reprec.assertoutcome(skipped=1)
+
+ def test_trial_testfunction_todo_property(self, testdir):
+ testpath = testdir.makepyfile("""
+ from twisted.trial import unittest
+ class MyTestCase(unittest.TestCase):
+ def test_func(self):
+ assert 0
+ test_func.todo = 'dont run'
+ """)
+ reprec = testdir.inline_run(testpath, "-s", *self.ignore_unclosed_socket_warning)
+ reprec.assertoutcome(skipped=1)
+
+
+def test_djangolike_testcase(testdir):
+ # contributed from Morten Breekevold
+ testdir.makepyfile("""
+ from unittest import TestCase, main
+
+ class DjangoLikeTestCase(TestCase):
+
+ def setUp(self):
+ print ("setUp()")
+
+ def test_presetup_has_been_run(self):
+ print ("test_thing()")
+ self.assertTrue(hasattr(self, 'was_presetup'))
+
+ def tearDown(self):
+ print ("tearDown()")
+
+ def __call__(self, result=None):
+ try:
+ self._pre_setup()
+ except (KeyboardInterrupt, SystemExit):
+ raise
+ except Exception:
+ import sys
+ result.addError(self, sys.exc_info())
+ return
+ super(DjangoLikeTestCase, self).__call__(result)
+ try:
+ self._post_teardown()
+ except (KeyboardInterrupt, SystemExit):
+ raise
+ except Exception:
+ import sys
+ result.addError(self, sys.exc_info())
+ return
+
+ def _pre_setup(self):
+ print ("_pre_setup()")
+ self.was_presetup = True
+
+ def _post_teardown(self):
+ print ("_post_teardown()")
+ """)
+ result = testdir.runpytest("-s")
+ assert result.ret == 0
+ result.stdout.fnmatch_lines([
+ "*_pre_setup()*",
+ "*setUp()*",
+ "*test_thing()*",
+ "*tearDown()*",
+ "*_post_teardown()*",
+ ])
+
+
+def test_unittest_not_shown_in_traceback(testdir):
+ testdir.makepyfile("""
+ import unittest
+ class t(unittest.TestCase):
+ def test_hello(self):
+ x = 3
+ self.assertEqual(x, 4)
+ """)
+ res = testdir.runpytest()
+ assert "failUnlessEqual" not in res.stdout.str()
+
+
+def test_unorderable_types(testdir):
+ testdir.makepyfile("""
+ import unittest
+ class TestJoinEmpty(unittest.TestCase):
+ pass
+
+ def make_test():
+ class Test(unittest.TestCase):
+ pass
+ Test.__name__ = "TestFoo"
+ return Test
+ TestFoo = make_test()
+ """)
+ result = testdir.runpytest()
+ assert "TypeError" not in result.stdout.str()
+ assert result.ret == EXIT_NOTESTSCOLLECTED
+
+
+def test_unittest_typerror_traceback(testdir):
+ testdir.makepyfile("""
+ import unittest
+ class TestJoinEmpty(unittest.TestCase):
+ def test_hello(self, arg1):
+ pass
+ """)
+ result = testdir.runpytest()
+ assert "TypeError" in result.stdout.str()
+ assert result.ret == 1
+
+
+@pytest.mark.parametrize('runner', ['pytest', 'unittest'])
+def test_unittest_expected_failure_for_failing_test_is_xfail(testdir, runner):
+ script = testdir.makepyfile("""
+ import unittest
+ class MyTestCase(unittest.TestCase):
+ @unittest.expectedFailure
+ def test_failing_test_is_xfail(self):
+ assert False
+ if __name__ == '__main__':
+ unittest.main()
+ """)
+ if runner == 'pytest':
+ result = testdir.runpytest("-rxX")
+ result.stdout.fnmatch_lines([
+ "*XFAIL*MyTestCase*test_failing_test_is_xfail*",
+ "*1 xfailed*",
+ ])
+ else:
+ result = testdir.runpython(script)
+ result.stderr.fnmatch_lines([
+ "*1 test in*",
+ "*OK*(expected failures=1)*",
+ ])
+ assert result.ret == 0
+
+
+@pytest.mark.parametrize('runner', ['pytest', 'unittest'])
+def test_unittest_expected_failure_for_passing_test_is_fail(testdir, runner):
+ script = testdir.makepyfile("""
+ import unittest
+ class MyTestCase(unittest.TestCase):
+ @unittest.expectedFailure
+ def test_passing_test_is_fail(self):
+ assert True
+ if __name__ == '__main__':
+ unittest.main()
+ """)
+ from _pytest.compat import _is_unittest_unexpected_success_a_failure
+ should_fail = _is_unittest_unexpected_success_a_failure()
+ if runner == 'pytest':
+ result = testdir.runpytest("-rxX")
+ result.stdout.fnmatch_lines([
+ "*MyTestCase*test_passing_test_is_fail*",
+ "*1 failed*" if should_fail else "*1 xpassed*",
+ ])
+ else:
+ result = testdir.runpython(script)
+ result.stderr.fnmatch_lines([
+ "*1 test in*",
+ "*(unexpected successes=1)*",
+ ])
+
+ assert result.ret == (1 if should_fail else 0)
+
+
+@pytest.mark.parametrize('fix_type, stmt', [
+ ('fixture', 'return'),
+ ('yield_fixture', 'yield'),
+])
+def test_unittest_setup_interaction(testdir, fix_type, stmt):
+ testdir.makepyfile("""
+ import unittest
+ import pytest
+ class MyTestCase(unittest.TestCase):
+ @pytest.{fix_type}(scope="class", autouse=True)
+ def perclass(self, request):
+ request.cls.hello = "world"
+ {stmt}
+ @pytest.{fix_type}(scope="function", autouse=True)
+ def perfunction(self, request):
+ request.instance.funcname = request.function.__name__
+ {stmt}
+
+ def test_method1(self):
+ assert self.funcname == "test_method1"
+ assert self.hello == "world"
+
+ def test_method2(self):
+ assert self.funcname == "test_method2"
+
+ def test_classattr(self):
+ assert self.__class__.hello == "world"
+ """.format(fix_type=fix_type, stmt=stmt))
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines("*3 passed*")
+
+
+def test_non_unittest_no_setupclass_support(testdir):
+ testpath = testdir.makepyfile("""
+ class TestFoo(object):
+ x = 0
+
+ @classmethod
+ def setUpClass(cls):
+ cls.x = 1
+
+ def test_method1(self):
+ assert self.x == 0
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.x = 1
+
+ def test_not_teareddown():
+ assert TestFoo.x == 0
+
+ """)
+ reprec = testdir.inline_run(testpath)
+ reprec.assertoutcome(passed=2)
+
+
+def test_no_teardown_if_setupclass_failed(testdir):
+ testpath = testdir.makepyfile("""
+ import unittest
+
+ class MyTestCase(unittest.TestCase):
+ x = 0
+
+ @classmethod
+ def setUpClass(cls):
+ cls.x = 1
+ assert False
+
+ def test_func1(self):
+ cls.x = 10
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.x = 100
+
+ def test_notTornDown():
+ assert MyTestCase.x == 1
+ """)
+ reprec = testdir.inline_run(testpath)
+ reprec.assertoutcome(passed=1, failed=1)
+
+
+def test_issue333_result_clearing(testdir):
+ testdir.makeconftest("""
+ import pytest
+ @pytest.hookimpl(hookwrapper=True)
+ def pytest_runtest_call(item):
+ yield
+ assert 0
+ """)
+ testdir.makepyfile("""
+ import unittest
+ class TestIt(unittest.TestCase):
+ def test_func(self):
+ 0/0
+ """)
+
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(failed=1)
+
+
+def test_unittest_raise_skip_issue748(testdir):
+ testdir.makepyfile(test_foo="""
+ import unittest
+
+ class MyTestCase(unittest.TestCase):
+ def test_one(self):
+ raise unittest.SkipTest('skipping due to reasons')
+ """)
+ result = testdir.runpytest("-v", '-rs')
+ result.stdout.fnmatch_lines("""
+ *SKIP*[1]*test_foo.py*skipping due to reasons*
+ *1 skipped*
+ """)
+
+
+def test_unittest_skip_issue1169(testdir):
+ testdir.makepyfile(test_foo="""
+ import unittest
+
+ class MyTestCase(unittest.TestCase):
+ @unittest.skip("skipping due to reasons")
+ def test_skip(self):
+ self.fail()
+ """)
+ result = testdir.runpytest("-v", '-rs')
+ result.stdout.fnmatch_lines("""
+ *SKIP*[1]*skipping due to reasons*
+ *1 skipped*
+ """)
+
+
+def test_class_method_containing_test_issue1558(testdir):
+ testdir.makepyfile(test_foo="""
+ import unittest
+
+ class MyTestCase(unittest.TestCase):
+ def test_should_run(self):
+ pass
+ def test_should_not_run(self):
+ pass
+ test_should_not_run.__test__ = False
+ """)
+ reprec = testdir.inline_run()
+ reprec.assertoutcome(passed=1)
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_warnings.py b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_warnings.py
new file mode 100644
index 00000000000..02400bd1ded
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/testing/test_warnings.py
@@ -0,0 +1,258 @@
+# -*- coding: utf8 -*-
+from __future__ import unicode_literals
+
+import sys
+
+import pytest
+
+
+WARNINGS_SUMMARY_HEADER = 'warnings summary'
+
+
+@pytest.fixture
+def pyfile_with_warnings(testdir, request):
+ """
+ Create a test file which calls a function in a module which generates warnings.
+ """
+ testdir.syspathinsert()
+ test_name = request.function.__name__
+ module_name = test_name.lstrip('test_') + '_module'
+ testdir.makepyfile(**{
+ module_name: '''
+ import warnings
+ def foo():
+ warnings.warn(UserWarning("user warning"))
+ warnings.warn(RuntimeWarning("runtime warning"))
+ return 1
+ ''',
+ test_name: '''
+ import {module_name}
+ def test_func():
+ assert {module_name}.foo() == 1
+ '''.format(module_name=module_name)
+ })
+
+
+@pytest.mark.filterwarnings('always')
+def test_normal_flow(testdir, pyfile_with_warnings):
+ """
+ Check that the warnings section is displayed, containing test node ids followed by
+ all warnings generated by that test node.
+ """
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ '*== %s ==*' % WARNINGS_SUMMARY_HEADER,
+
+ '*test_normal_flow.py::test_func',
+
+ '*normal_flow_module.py:3: UserWarning: user warning',
+ '* warnings.warn(UserWarning("user warning"))',
+
+ '*normal_flow_module.py:4: RuntimeWarning: runtime warning',
+ '* warnings.warn(RuntimeWarning("runtime warning"))',
+ '* 1 passed, 2 warnings*',
+ ])
+ assert result.stdout.str().count('test_normal_flow.py::test_func') == 1
+
+
+@pytest.mark.filterwarnings('always')
+def test_setup_teardown_warnings(testdir, pyfile_with_warnings):
+ testdir.makepyfile('''
+ import warnings
+ import pytest
+
+ @pytest.fixture
+ def fix():
+ warnings.warn(UserWarning("warning during setup"))
+ yield
+ warnings.warn(UserWarning("warning during teardown"))
+
+ def test_func(fix):
+ pass
+ ''')
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ '*== %s ==*' % WARNINGS_SUMMARY_HEADER,
+
+ '*test_setup_teardown_warnings.py:6: UserWarning: warning during setup',
+ '*warnings.warn(UserWarning("warning during setup"))',
+
+ '*test_setup_teardown_warnings.py:8: UserWarning: warning during teardown',
+ '*warnings.warn(UserWarning("warning during teardown"))',
+ '* 1 passed, 2 warnings*',
+ ])
+
+
+@pytest.mark.parametrize('method', ['cmdline', 'ini'])
+def test_as_errors(testdir, pyfile_with_warnings, method):
+ args = ('-W', 'error') if method == 'cmdline' else ()
+ if method == 'ini':
+ testdir.makeini('''
+ [pytest]
+ filterwarnings= error
+ ''')
+ result = testdir.runpytest(*args)
+ result.stdout.fnmatch_lines([
+ 'E UserWarning: user warning',
+ 'as_errors_module.py:3: UserWarning',
+ '* 1 failed in *',
+ ])
+
+
+@pytest.mark.parametrize('method', ['cmdline', 'ini'])
+def test_ignore(testdir, pyfile_with_warnings, method):
+ args = ('-W', 'ignore') if method == 'cmdline' else ()
+ if method == 'ini':
+ testdir.makeini('''
+ [pytest]
+ filterwarnings= ignore
+ ''')
+
+ result = testdir.runpytest(*args)
+ result.stdout.fnmatch_lines([
+ '* 1 passed in *',
+ ])
+ assert WARNINGS_SUMMARY_HEADER not in result.stdout.str()
+
+
+@pytest.mark.skipif(sys.version_info < (3, 0),
+ reason='warnings message is unicode is ok in python3')
+@pytest.mark.filterwarnings('always')
+def test_unicode(testdir, pyfile_with_warnings):
+ testdir.makepyfile('''
+ # -*- coding: utf8 -*-
+ import warnings
+ import pytest
+
+
+ @pytest.fixture
+ def fix():
+ warnings.warn(u"测试")
+ yield
+
+ def test_func(fix):
+ pass
+ ''')
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ '*== %s ==*' % WARNINGS_SUMMARY_HEADER,
+ '*test_unicode.py:8: UserWarning: \u6d4b\u8bd5*',
+ '* 1 passed, 1 warnings*',
+ ])
+
+
+@pytest.mark.skipif(sys.version_info >= (3, 0),
+ reason='warnings message is broken as it is not str instance')
+def test_py2_unicode(testdir, pyfile_with_warnings):
+ if getattr(sys, "pypy_version_info", ())[:2] == (5, 9) and sys.platform.startswith('win'):
+ pytest.xfail("fails with unicode error on PyPy2 5.9 and Windows (#2905)")
+ testdir.makepyfile('''
+ # -*- coding: utf8 -*-
+ import warnings
+ import pytest
+
+
+ @pytest.fixture
+ def fix():
+ warnings.warn(u"测试")
+ yield
+
+ @pytest.mark.filterwarnings('always')
+ def test_func(fix):
+ pass
+ ''')
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ '*== %s ==*' % WARNINGS_SUMMARY_HEADER,
+
+ '*test_py2_unicode.py:8: UserWarning: \\u6d4b\\u8bd5',
+ '*warnings.warn(u"\u6d4b\u8bd5")',
+ '*warnings.py:*: UnicodeWarning: Warning is using unicode non*',
+ '* 1 passed, 2 warnings*',
+ ])
+
+
+def test_py2_unicode_ascii(testdir):
+ """Ensure that our warning about 'unicode warnings containing non-ascii messages'
+ does not trigger with ascii-convertible messages"""
+ testdir.makeini('[pytest]')
+ testdir.makepyfile('''
+ import pytest
+ import warnings
+
+ @pytest.mark.filterwarnings('always')
+ def test_func():
+ warnings.warn(u"hello")
+ ''')
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ '*== %s ==*' % WARNINGS_SUMMARY_HEADER,
+ '*warnings.warn(u"hello")',
+ '* 1 passed, 1 warnings in*'
+ ])
+
+
+def test_works_with_filterwarnings(testdir):
+ """Ensure our warnings capture does not mess with pre-installed filters (#2430)."""
+ testdir.makepyfile('''
+ import warnings
+
+ class MyWarning(Warning):
+ pass
+
+ warnings.filterwarnings("error", category=MyWarning)
+
+ class TestWarnings(object):
+ def test_my_warning(self):
+ try:
+ warnings.warn(MyWarning("warn!"))
+ assert False
+ except MyWarning:
+ assert True
+ ''')
+ result = testdir.runpytest()
+ result.stdout.fnmatch_lines([
+ '*== 1 passed in *',
+ ])
+
+
+@pytest.mark.parametrize('default_config', ['ini', 'cmdline'])
+def test_filterwarnings_mark(testdir, default_config):
+ """
+ Test ``filterwarnings`` mark works and takes precedence over command line and ini options.
+ """
+ if default_config == 'ini':
+ testdir.makeini("""
+ [pytest]
+ filterwarnings = always
+ """)
+ testdir.makepyfile("""
+ import warnings
+ import pytest
+
+ @pytest.mark.filterwarnings('ignore::RuntimeWarning')
+ def test_ignore_runtime_warning():
+ warnings.warn(RuntimeWarning())
+
+ @pytest.mark.filterwarnings('error')
+ def test_warning_error():
+ warnings.warn(RuntimeWarning())
+
+ def test_show_warning():
+ warnings.warn(RuntimeWarning())
+ """)
+ result = testdir.runpytest('-W always' if default_config == 'cmdline' else '')
+ result.stdout.fnmatch_lines(['*= 1 failed, 2 passed, 1 warnings in *'])
+
+
+def test_non_string_warning_argument(testdir):
+ """Non-str argument passed to warning breaks pytest (#2956)"""
+ testdir.makepyfile("""
+ import warnings
+ import pytest
+
+ def test():
+ warnings.warn(UserWarning(1, u'foo'))
+ """)
+ result = testdir.runpytest('-W', 'always')
+ result.stdout.fnmatch_lines(['*= 1 passed, 1 warnings in *'])
diff --git a/tests/wpt/web-platform-tests/tools/third_party/pytest/tox.ini b/tests/wpt/web-platform-tests/tools/third_party/pytest/tox.ini
new file mode 100644
index 00000000000..900b602dc33
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/third_party/pytest/tox.ini
@@ -0,0 +1,220 @@
+[tox]
+minversion = 2.0
+distshare = {homedir}/.tox/distshare
+# make sure to update environment list in travis.yml and appveyor.yml
+envlist =
+ linting
+ py27
+ py34
+ py35
+ py36
+ py37
+ pypy
+ {py27,py36}-{pexpect,xdist,trial,numpy,pluggymaster}
+ py27-nobyte
+ doctesting
+ py35-freeze
+ docs
+
+[testenv]
+commands = pytest --lsof -ra {posargs:testing}
+passenv = USER USERNAME
+deps =
+ hypothesis>=3.5.2
+ nose
+ mock
+ requests
+
+[testenv:py27-subprocess]
+changedir = .
+deps =
+ pytest-xdist>=1.13
+ mock
+ nose
+commands =
+ pytest -n3 -ra --runpytest=subprocess {posargs:testing}
+
+
+[testenv:linting]
+skipsdist = True
+usedevelop = True
+basepython = python2.7
+deps =
+ flake8
+ # pygments required by rst-lint
+ pygments
+ restructuredtext_lint
+commands =
+ flake8 pytest.py _pytest testing setup.py pytest.py
+ {envpython} scripts/check-rst.py
+
+[testenv:py27-xdist]
+deps =
+ pytest-xdist>=1.13
+ mock
+ nose
+ hypothesis>=3.5.2
+changedir=testing
+commands =
+ pytest -n1 -ra {posargs:.}
+
+[testenv:py36-xdist]
+deps = {[testenv:py27-xdist]deps}
+commands =
+ pytest -n3 -ra {posargs:testing}
+
+[testenv:py27-pexpect]
+changedir = testing
+platform = linux|darwin
+deps = pexpect
+commands =
+ pytest -ra test_pdb.py test_terminal.py test_unittest.py
+
+[testenv:py36-pexpect]
+changedir = testing
+platform = linux|darwin
+deps = {[testenv:py27-pexpect]deps}
+commands =
+ pytest -ra test_pdb.py test_terminal.py test_unittest.py
+
+[testenv:py27-nobyte]
+deps =
+ pytest-xdist>=1.13
+ hypothesis>=3.5.2
+distribute = true
+changedir=testing
+setenv =
+ PYTHONDONTWRITEBYTECODE=1
+commands =
+ pytest -n3 -ra {posargs:.}
+
+[testenv:py27-trial]
+deps = twisted
+commands =
+ pytest -ra {posargs:testing/test_unittest.py}
+
+[testenv:py36-trial]
+deps = {[testenv:py27-trial]deps}
+commands =
+ pytest -ra {posargs:testing/test_unittest.py}
+
+[testenv:py27-numpy]
+deps=numpy
+commands=
+ pytest -ra {posargs:testing/python/approx.py}
+
+[testenv:py36-numpy]
+deps=numpy
+commands=
+ pytest -ra {posargs:testing/python/approx.py}
+
+[testenv:py27-pluggymaster]
+setenv=
+ _PYTEST_SETUP_SKIP_PLUGGY_DEP=1
+deps =
+ {[testenv]deps}
+ git+https://github.com/pytest-dev/pluggy.git@master
+
+[testenv:py35-pluggymaster]
+setenv=
+ _PYTEST_SETUP_SKIP_PLUGGY_DEP=1
+deps =
+ {[testenv:py27-pluggymaster]deps}
+ git+https://github.com/pytest-dev/pluggy.git@master
+
+[testenv:docs]
+skipsdist = True
+usedevelop = True
+basepython = python
+changedir = doc/en
+deps =
+ sphinx
+ PyYAML
+
+commands =
+ sphinx-build -W -b html . _build
+
+[testenv:doctesting]
+basepython = python
+usedevelop = True
+skipsdist = True
+# ensure the given pyargs cant mean anytrhing else
+changedir = doc/
+deps =
+ PyYAML
+commands =
+ pytest -ra en
+ pytest --doctest-modules --pyargs _pytest
+
+[testenv:regen]
+changedir = doc/en
+skipsdist = True
+basepython = python3.5
+deps =
+ sphinx
+ PyYAML
+ regendoc>=0.6.1
+whitelist_externals =
+ rm
+ make
+commands =
+ rm -rf /tmp/doc-exec*
+ make regen
+
+[testenv:fix-lint]
+skipsdist = True
+usedevelop = True
+deps =
+ autopep8
+commands =
+ autopep8 --in-place -r --max-line-length=120 --exclude=test_source_multiline_block.py _pytest testing setup.py pytest.py
+
+[testenv:jython]
+changedir = testing
+commands =
+ {envpython} {envbindir}/py.test-jython -ra {posargs}
+
+[testenv:py35-freeze]
+changedir = testing/freeze
+deps = pyinstaller
+commands =
+ {envpython} create_executable.py
+ {envpython} tox_run.py
+
+
+[testenv:coveralls]
+passenv = TRAVIS TRAVIS_JOB_ID TRAVIS_BRANCH COVERALLS_REPO_TOKEN
+usedevelop = True
+changedir = .
+deps =
+ {[testenv]deps}
+ coveralls
+commands =
+ coverage run --source=_pytest -m pytest testing
+ coverage report -m
+ coveralls
+
+[pytest]
+minversion = 2.0
+plugins = pytester
+#--pyargs --doctest-modules --ignore=.tox
+addopts = -ra -p pytester --ignore=testing/cx_freeze
+rsyncdirs = tox.ini pytest.py _pytest testing
+python_files = test_*.py *_test.py testing/*/*.py
+python_classes = Test Acceptance
+python_functions = test
+norecursedirs = .tox ja .hg cx_freeze_source
+xfail_strict=true
+filterwarnings =
+ error
+ # produced by path.local
+ ignore:bad escape.*:DeprecationWarning:re
+ # produced by path.readlines
+ ignore:.*U.*mode is deprecated:DeprecationWarning
+ # produced by pytest-xdist
+ ignore:.*type argument to addoption.*:DeprecationWarning
+ # produced by python >=3.5 on execnet (pytest-xdist)
+ ignore:.*inspect.getargspec.*deprecated, use inspect.signature.*:DeprecationWarning
+
+[flake8]
+max-line-length = 120
diff --git a/tests/wpt/web-platform-tests/tools/tox.ini b/tests/wpt/web-platform-tests/tools/tox.ini
index 3b97ae4b5f7..b154c471d6f 100644
--- a/tests/wpt/web-platform-tests/tools/tox.ini
+++ b/tests/wpt/web-platform-tests/tools/tox.ini
@@ -21,4 +21,4 @@ passenv =
[flake8]
ignore = E128,E129,E221,E226,E231,E251,E265,E302,E303,E305,E402,E901,F401,F821,F841
max-line-length = 141
-exclude = .tox,html5lib,py,pytest,pywebsocket,six,_venv,webencodings,wptserve/docs,wptserve/tests/functional/docroot/,wpt,wptrunner
+exclude = .tox,html5lib,third_party/py,third_party/pytest,third_party/funcsigs,third_party/attrs,third_party/pluggy/,pywebsocket,six,_venv,webencodings,wptserve/docs,wptserve/tests/functional/docroot/,wpt,wptrunner
diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/client.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/client.py
index 26a035da776..ec7d6deccba 100644
--- a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/client.py
+++ b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/client.py
@@ -42,7 +42,7 @@ class Timeouts(object):
def _set(self, key, secs):
body = {key: secs * 1000}
timeouts = self.session.send_session_command("POST", "timeouts", body)
- return timeouts[key]
+ return None
@property
def script(self):
@@ -370,8 +370,8 @@ class Session(object):
self.actions = Actions(self)
def __eq__(self, other):
- return (self.session_id is not None and isinstance(other, Session)
- and self.session_Id == other.session_id)
+ return (self.session_id is not None and isinstance(other, Session) and
+ self.session_id == other.session_id)
def __enter__(self):
self.start()
@@ -509,6 +509,11 @@ class Session(object):
@property
@command
+ def source(self):
+ return self.send_session_command("GET", "source")
+
+ @property
+ @command
def window_handle(self):
return self.send_session_command("GET", "window")
@@ -626,8 +631,8 @@ class Element(object):
self.session._element_cache[self.id] = self
def __eq__(self, other):
- return isinstance(other, Element) and self.id == other.id \
- and self.session == other.session
+ return (isinstance(other, Element) and self.id == other.id and
+ self.session == other.session)
@classmethod
def from_json(cls, json, session):
diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/error.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/error.py
index 01ab31b8af1..ecfe8910c51 100644
--- a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/error.py
+++ b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/error.py
@@ -8,17 +8,25 @@ class WebDriverException(Exception):
def __init__(self, message, stacktrace=None):
super(WebDriverException, self)
+ self.message = message
self.stacktrace = stacktrace
def __repr__(self):
- return "<%s http_status=%d>" % (self.__class__.__name__, self.http_status)
+ return "<%s http_status=%s>" % (self.__class__.__name__, self.http_status)
def __str__(self):
- return ("%s (%d)\n"
- "\n"
+ message = "%s (%s): %s\n" % (self.status_code, self.http_status, self.message)
+ if self.stacktrace:
+ message += ("\n"
"Remote-end stacktrace:\n"
"\n"
- "%s" % (self.status_code, self.http_status, self.stacktrace))
+ "%s" % self.stacktrace)
+ return message
+
+
+class ElementClickInterceptedException(WebDriverException):
+ http_status = 400
+ status_code = "element click intercepted"
class ElementNotSelectableException(WebDriverException):
@@ -53,7 +61,7 @@ class InvalidElementCoordinatesException(WebDriverException):
class InvalidElementStateException(WebDriverException):
http_status = 400
- status_code = "invalid cookie domain"
+ status_code = "invalid element state"
class InvalidSelectorException(WebDriverException):
@@ -107,7 +115,7 @@ class SessionNotCreatedException(WebDriverException):
class StaleElementReferenceException(WebDriverException):
- http_status = 400
+ http_status = 404
status_code = "stale element reference"
diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/transport.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/transport.py
index ef8e59a6f82..b198b194b38 100644
--- a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/transport.py
+++ b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/transport.py
@@ -19,6 +19,7 @@ class Response(object):
self.body = body
def __repr__(self):
+ cls_name = self.__class__.__name__
if self.error:
return "<%s status=%s error=%s>" % (cls_name, self.status, repr(self.error))
return "<% status=%s body=%s>" % (cls_name, self.status, json.dumps(self.body))
diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/OWNERS b/tests/wpt/web-platform-tests/tools/wptrunner/OWNERS
deleted file mode 100644
index 4bf48ad76e5..00000000000
--- a/tests/wpt/web-platform-tests/tools/wptrunner/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-@bobholt
diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/docs/conf.py b/tests/wpt/web-platform-tests/tools/wptrunner/docs/conf.py
index 39e5cc4f0d2..0c717f56536 100644
--- a/tests/wpt/web-platform-tests/tools/wptrunner/docs/conf.py
+++ b/tests/wpt/web-platform-tests/tools/wptrunner/docs/conf.py
@@ -264,4 +264,4 @@ texinfo_documents = [
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'python': ('http://docs.python.org/', None),
- 'mozlog': ('http://mozbase.readthedocs.org/en/latest/', None)}
+ 'mozlog': ('https://firefox-source-docs.mozilla.org/', None)}
diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/firefox.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/firefox.py
index 552cd15b459..b324bccd91e 100644
--- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/firefox.py
+++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/firefox.py
@@ -51,7 +51,10 @@ def get_timeout_multiplier(test_type, run_info_data, **kwargs):
else:
return 2
elif run_info_data["debug"] or run_info_data.get("asan"):
- return 3
+ if run_info_data.get("ccov"):
+ return 4
+ else:
+ return 3
return 1
diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/ie.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/ie.py
index c981024f22b..553372f390e 100644
--- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/ie.py
+++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/ie.py
@@ -31,8 +31,6 @@ def executor_kwargs(test_type, server_config, cache_manager, run_info_data,
ieOptions = {}
ieOptions["requireWindowFocus"] = True
capabilities = {}
- capabilities["browserName"] = "internet explorer"
- capabilities["platformName"] = "windows"
capabilities["se:ieOptions"] = ieOptions
executor_kwargs = base_executor_kwargs(test_type, server_config,
cache_manager, **kwargs)
diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/servo.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/servo.py
index 3738ce4bddc..17fa59834fd 100644
--- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/servo.py
+++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/browsers/servo.py
@@ -54,7 +54,7 @@ def env_extras(**kwargs):
def env_options():
return {"host": "127.0.0.1",
"external_host": "web-platform.test",
- "bind_hostname": "true",
+ "bind_hostname": "false",
"testharnessreport": "testharnessreport-servo.js",
"supports_debugger": True}
diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/environment.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/environment.py
index e8734405e00..874595cbff3 100644
--- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/environment.py
+++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/environment.py
@@ -37,8 +37,6 @@ def do_delayed_imports(logger, test_paths):
try:
from tools.serve import serve
except ImportError:
- from wpt_tools.serve import serve
- except ImportError:
failed.append("serve")
try:
@@ -86,7 +84,6 @@ class TestEnvironment(object):
self.ssl_env = ssl_env
self.server = None
self.config = None
- self.external_config = None
self.pause_after_test = pause_after_test
self.test_server_port = options.pop("test_server_port", True)
self.debug_info = debug_info
@@ -105,9 +102,10 @@ class TestEnvironment(object):
cm.__enter__(self.options)
self.setup_server_logging()
self.config = self.load_config()
- serve.set_computed_defaults(self.config)
- self.external_config, self.servers = serve.start(self.config, self.ssl_env,
- self.get_routes())
+ ports = serve.get_ports(self.config, self.ssl_env)
+ self.config = serve.normalise_config(self.config, ports)
+ self.servers = serve.start(self.config, self.ssl_env,
+ self.get_routes())
if self.options.get("supports_debugger") and self.debug_info and self.debug_info.interactive:
self.ignore_interrupts()
return self
@@ -160,6 +158,8 @@ class TestEnvironment(object):
config["key_file"] = key_file
config["certificate"] = certificate
+ serve.set_computed_defaults(config)
+
return config
def setup_server_logging(self):
diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/executors/base.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/executors/base.py
index b33bc428ecb..d87e4ab9924 100644
--- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/executors/base.py
+++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/executors/base.py
@@ -113,7 +113,7 @@ class TestExecutor(object):
:param browser: ExecutorBrowser instance providing properties of the
browser that will be tested.
:param server_config: Dictionary of wptserve server configuration of the
- form stored in TestEnvironment.external_config
+ form stored in TestEnvironment.config
:param timeout_multiplier: Multiplier relative to base timeout to use
when setting test timeout.
"""
@@ -357,12 +357,10 @@ class WdspecExecutor(TestExecutor):
return (test.result_cls(*data), [])
def do_wdspec(self, session_config, path, timeout):
- harness_result = ("OK", None)
- subtest_results = pytestrunner.run(path,
- self.server_config,
- session_config,
- timeout=timeout)
- return (harness_result, subtest_results)
+ return pytestrunner.run(path,
+ self.server_config,
+ session_config,
+ timeout=timeout)
def do_delayed_imports(self):
global pytestrunner
diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/executors/executormarionette.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/executors/executormarionette.py
index e2163bb0707..2d0dc914d10 100644
--- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/executors/executormarionette.py
+++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/executors/executormarionette.py
@@ -63,30 +63,26 @@ class MarionetteProtocol(Protocol):
self.marionette = marionette.Marionette(host='localhost',
port=self.marionette_port,
socket_timeout=None,
- startup_timeout=None)
-
- # XXX Move this timeout somewhere
- self.logger.debug("Waiting for Marionette connection")
- while True:
- success = self.marionette.wait_for_port(startup_timeout)
- #When running in a debugger wait indefinitely for firefox to start
- if success or self.executor.debug_info is None:
- break
-
- session_started = False
- if success:
- try:
- self.logger.debug("Starting Marionette session")
- self.marionette.start_session(capabilities=self.capabilities)
- except Exception as e:
- self.logger.warning("Starting marionette session failed: %s" % e)
- else:
- self.logger.debug("Marionette session started")
- session_started = True
+ startup_timeout=startup_timeout)
+ try:
+ self.logger.debug("Waiting for Marionette connection")
+ while True:
+ try:
+ self.marionette.raise_for_port()
+ break
+ except IOError:
+ # When running in a debugger wait indefinitely for Firefox to start
+ if self.executor.debug_info is None:
+ raise
+
+ self.logger.debug("Starting Marionette session")
+ self.marionette.start_session()
+ self.logger.debug("Marionette session started")
- if not success or not session_started:
- self.logger.warning("Failed to connect to Marionette")
+ except Exception as e:
+ self.logger.warning("Failed to start a Marionette session: %s" % e)
self.executor.runner.send_message("init_failed")
+
else:
try:
self.after_connect()
@@ -173,9 +169,17 @@ class MarionetteProtocol(Protocol):
self.load_runner(protocol)
def wait(self):
- socket_timeout = self.marionette.client.sock.gettimeout()
+ try:
+ socket_timeout = self.marionette.client.socket_timeout
+ except AttributeError:
+ # This can happen if there was a crash
+ return
if socket_timeout:
- self.marionette.timeout.script = socket_timeout / 2
+ try:
+ self.marionette.timeout.script = socket_timeout / 2
+ except (socket.error, IOError):
+ self.logger.debug("Socket closed")
+ return
self.marionette.switch_to_window(self.runner_handle)
while True:
@@ -564,7 +568,7 @@ class InternalRefTestImplementation(object):
self.executor.protocol.marionette.set_context(self.executor.protocol.marionette.CONTEXT_CONTENT)
except Exception as e:
# Ignore errors during teardown
- self.logger.warning(traceback.traceback.format_exc(e))
+ self.logger.warning(traceback.format_exc(e))
diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py
index 611a4989c39..0870b1232ad 100644
--- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py
+++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py
@@ -1,4 +1,5 @@
-"""Provides interface to deal with pytest.
+"""
+Provides interface to deal with pytest.
Usage::
@@ -24,7 +25,8 @@ def do_delayed_imports():
def run(path, server_config, session_config, timeout=0):
- """Run Python test at ``path`` in pytest. The provided ``session``
+ """
+ Run Python test at ``path`` in pytest. The provided ``session``
is exposed as a fixture available in the scope of the test functions.
:param path: Path to the test file.
@@ -33,36 +35,51 @@ def run(path, server_config, session_config, timeout=0):
:param timeout: Duration before interrupting potentially hanging
tests. If 0, there is no timeout.
- :returns: List of subtest results, which are tuples of (test id,
- status, message, stacktrace).
+ :returns: (<harness result>, [<subtest result>, ...]),
+ where <subtest result> is (test id, status, message, stacktrace).
"""
-
if pytest is None:
do_delayed_imports()
- recorder = SubtestResultRecorder()
-
os.environ["WD_HOST"] = session_config["host"]
os.environ["WD_PORT"] = str(session_config["port"])
os.environ["WD_CAPABILITIES"] = json.dumps(session_config["capabilities"])
os.environ["WD_SERVER_CONFIG"] = json.dumps(server_config)
- plugins = [recorder]
-
- # TODO(ato): Deal with timeouts
+ harness = HarnessResultRecorder()
+ subtests = SubtestResultRecorder()
with TemporaryDirectory() as cache:
- pytest.main(["--strict", # turn warnings into errors
- "--verbose", # show each individual subtest
- "--capture", "no", # enable stdout/stderr from tests
- "--basetemp", cache, # temporary directory
- "--showlocals", # display contents of variables in local scope
- "-p", "no:mozlog", # use the WPT result recorder
- "-p", "no:cacheprovider", # disable state preservation across invocations
- path],
- plugins=plugins)
+ try:
+ pytest.main(["--strict", # turn warnings into errors
+ "--verbose", # show each individual subtest
+ "--capture", "no", # enable stdout/stderr from tests
+ "--basetemp", cache, # temporary directory
+ "--showlocals", # display contents of variables in local scope
+ "-p", "no:mozlog", # use the WPT result recorder
+ "-p", "no:cacheprovider", # disable state preservation across invocations
+ path],
+ plugins=[harness, subtests])
+ except Exception as e:
+ harness.outcome = ("ERROR", str(e))
+
+ return (harness.outcome, subtests.results)
+
+
+class HarnessResultRecorder(object):
+ outcomes = {
+ "failed": "ERROR",
+ "passed": "OK",
+ "skipped": "SKIP",
+ }
+
+ def __init__(self):
+ # we are ok unless told otherwise
+ self.outcome = ("OK", None)
- return recorder.results
+ def pytest_collectreport(self, report):
+ harness_result = self.outcomes[report.outcome]
+ self.outcome = (harness_result, None)
class SubtestResultRecorder(object):
@@ -100,7 +117,7 @@ class SubtestResultRecorder(object):
def record(self, test, status, message=None, stack=None):
if stack is not None:
stack = str(stack)
- new_result = (test, status, message, stack)
+ new_result = (test.split("::")[-1], status, message, stack)
self.results.append(new_result)
diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/stability.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/stability.py
index dc1a1d0fed0..6eb060485c2 100644
--- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/stability.py
+++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/stability.py
@@ -1,14 +1,14 @@
import copy
import functools
import imp
+import io
import os
-import sys
from collections import OrderedDict, defaultdict
from datetime import datetime
from mozlog import reader
-from mozlog.formatters import JSONFormatter, TbplFormatter
-from mozlog.handlers import BaseHandler, LogLevelFilter, StreamHandler
+from mozlog.formatters import JSONFormatter
+from mozlog.handlers import BaseHandler, StreamHandler, LogLevelFilter
here = os.path.dirname(__file__)
localpaths = imp.load_source("localpaths", os.path.abspath(os.path.join(here, os.pardir, os.pardir, "localpaths.py")))
@@ -86,6 +86,8 @@ class LogHandler(reader.LogHandler):
def is_inconsistent(results_dict, iterations):
"""Return whether or not a single test is inconsistent."""
+ if 'SKIP' in results_dict:
+ return False
return len(results_dict) > 1 or sum(results_dict.values()) != iterations
@@ -178,31 +180,29 @@ def run_step(logger, iterations, restart_after_iteration, kwargs_extras, **kwarg
kwargs["pause_after_test"] = False
kwargs.update(kwargs_extras)
- handler = LogActionFilter(
- LogLevelFilter(
- StreamHandler(
- sys.stdout,
- TbplFormatter()
- ),
- "WARNING"),
- ["log", "process_output"])
+ def wrap_handler(x):
+ x = LogLevelFilter(x, "WARNING")
+ if not kwargs["verify_log_full"]:
+ x = LogActionFilter(x, ["log", "process_output"])
+ return x
- # There is a public API for this in the next mozlog
initial_handlers = logger._state.handlers
- logger._state.handlers = []
+ logger._state.handlers = [wrap_handler(handler)
+ for handler in initial_handlers]
- with open("raw.log", "wb") as log:
- # Setup logging for wptrunner that keeps process output and
- # warning+ level logs only
- logger.add_handler(handler)
- logger.add_handler(StreamHandler(log, JSONFormatter()))
+ log = io.BytesIO()
+ # Setup logging for wptrunner that keeps process output and
+ # warning+ level logs only
+ logger.add_handler(StreamHandler(log, JSONFormatter()))
- wptrunner.run_tests(**kwargs)
+ wptrunner.run_tests(**kwargs)
logger._state.handlers = initial_handlers
+ logger._state.running_tests = set()
+ logger._state.suite_started = False
- with open("raw.log", "rb") as log:
- results, inconsistent = process_results(log, iterations)
+ log.seek(0)
+ results, inconsistent = process_results(log, iterations)
return results, inconsistent, iterations
diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testdriver-vendor.js b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testdriver-vendor.js
new file mode 100644
index 00000000000..3e884036363
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testdriver-vendor.js
@@ -0,0 +1 @@
+// This file intentionally left blank
diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testloader.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testloader.py
index 71c55232580..0eb78bb884f 100644
--- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testloader.py
+++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testloader.py
@@ -460,7 +460,8 @@ class TestLoader(object):
chunk_type="none",
total_chunks=1,
chunk_number=1,
- include_https=True):
+ include_https=True,
+ skip_timeout=False):
self.test_types = test_types
self.run_info = run_info
@@ -472,6 +473,7 @@ class TestLoader(object):
self.tests = None
self.disabled_tests = None
self.include_https = include_https
+ self.skip_timeout = skip_timeout
self.chunk_type = chunk_type
self.total_chunks = total_chunks
@@ -557,6 +559,8 @@ class TestLoader(object):
enabled = not test.disabled()
if not self.include_https and test.environment["protocol"] == "https":
enabled = False
+ if self.skip_timeout and test.expected() == "TIMEOUT":
+ enabled = False
key = "enabled" if enabled else "disabled"
tests[key][test_type].append(test)
diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testrunner.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testrunner.py
index 64418285e66..75f4825f952 100644
--- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testrunner.py
+++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testrunner.py
@@ -120,6 +120,13 @@ def start_runner(runner_command_queue, runner_result_queue,
executor_browser_cls, executor_browser_kwargs,
stop_flag):
"""Launch a TestRunner in a new process"""
+ def log(level, msg):
+ runner_result_queue.put(("log", (level, {"message": msg})))
+
+ def handle_error(e):
+ log("critical", traceback.format_exc())
+ stop_flag.set()
+
try:
browser = executor_browser_cls(**executor_browser_kwargs)
executor = executor_cls(browser, **executor_kwargs)
@@ -128,10 +135,10 @@ def start_runner(runner_command_queue, runner_result_queue,
runner.run()
except KeyboardInterrupt:
stop_flag.set()
- except Exception:
- runner_result_queue.put(("log", ("critical", {"message": traceback.format_exc()})))
- print >> sys.stderr, traceback.format_exc()
- stop_flag.set()
+ except Exception as e:
+ handle_error(e)
+ except Exception as e:
+ handle_error(e)
finally:
runner_command_queue = None
runner_result_queue = None
@@ -389,6 +396,7 @@ class TestRunnerManager(threading.Thread):
}
try:
command, data = self.command_queue.get(True, 1)
+ self.logger.debug("Got command: %r" % command)
except IOError:
self.logger.error("Got IOError from poll")
return RunnerManagerState.restarting(0)
@@ -676,7 +684,18 @@ class TestRunnerManager(threading.Thread):
self.browser.cleanup()
while True:
try:
- self.logger.warning(" ".join(map(repr, self.command_queue.get_nowait())))
+ cmd, data = self.command_queue.get_nowait()
+ except Empty:
+ break
+ else:
+ if cmd == "log":
+ self.log(*data)
+ else:
+ self.logger.warning("%r: %r" % (cmd, data))
+ while True:
+ try:
+ cmd, data = self.remote_queue.get_nowait()
+ self.logger.warning("%r: %r" % (cmd, data))
except Empty:
break
diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/update/sync.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/update/sync.py
index 40bd1d7ebb7..c1bff854349 100644
--- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/update/sync.py
+++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/update/sync.py
@@ -81,7 +81,6 @@ def copy_wpt_tree(tree, dest, excludes=None, includes=None):
shutil.copy2(source_path, dest_path)
for source, destination in [("testharness_runner.html", ""),
- ("testharnessreport.js", "resources/"),
("testdriver-vendor.js", "resources/")]:
source_path = os.path.join(here, os.pardir, source)
dest_path = os.path.join(dest, destination, os.path.split(source)[1])
diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/update/update.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/update/update.py
index d9ef40fcda8..c985d3513ac 100644
--- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/update/update.py
+++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/update/update.py
@@ -11,10 +11,7 @@ from state import State
def setup_paths(sync_path):
sys.path.insert(0, os.path.abspath(sync_path))
- try:
- from tools import localpaths
- except ImportError:
- from wpt_tools import localpaths
+ from tools import localpaths
class LoadConfig(Step):
"""Step for loading configuration from the ini file and kwargs."""
diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptcommandline.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptcommandline.py
index b9f7a4c34a5..b232462d915 100644
--- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptcommandline.py
+++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptcommandline.py
@@ -79,6 +79,9 @@ scheme host and port.""")
mode_group.add_argument("--verify", action="store_true",
default=False,
help="Run a stability check on the selected tests")
+ mode_group.add_argument("--verify-log-full", action="store_true",
+ default=False,
+ help="Output per-iteration test results when running verify")
test_selection_group = parser.add_argument_group("Test Selection")
test_selection_group.add_argument("--test-types", action="store",
@@ -91,6 +94,8 @@ scheme host and port.""")
help="URL prefix to exclude")
test_selection_group.add_argument("--include-manifest", type=abs_path,
help="Path to manifest listing tests to include")
+ test_selection_group.add_argument("--skip-timeout", action="store_true",
+ help="Skip tests that are expected to time out")
test_selection_group.add_argument("--tag", action="append", dest="tags",
help="Labels applied to tests to include in the run. Labels starting dir: are equivalent to top-level directories.")
diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptlogging.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptlogging.py
index 4d320617859..26d174c066b 100644
--- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptlogging.py
+++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptlogging.py
@@ -1,13 +1,20 @@
import logging
import sys
import threading
+from Queue import Empty
from StringIO import StringIO
from multiprocessing import Queue
-from mozlog import commandline, stdadapter
+from mozlog import commandline, stdadapter, set_default_logger
+from mozlog.structuredlog import StructuredLogger
def setup(args, defaults):
- logger = commandline.setup_logging("web-platform-tests", args, defaults)
+ logger = args.pop('log', None)
+ if logger:
+ set_default_logger(logger)
+ StructuredLogger._logger_states["web-platform-tests"] = logger._state
+ else:
+ logger = commandline.setup_logging("web-platform-tests", args, defaults)
setup_stdlib_logger()
for name in args.keys():
@@ -45,7 +52,6 @@ class LogLevelRewriter(object):
return self.inner(data)
-
class LogThread(threading.Thread):
def __init__(self, queue, logger, level):
self.queue = queue
@@ -120,5 +126,10 @@ class CaptureIO(object):
self.logging_queue.put(None)
if self.logging_thread is not None:
self.logging_thread.join(10)
+ while not self.logging_queue.empty():
+ try:
+ self.logger.warning("Dropping log message: %r", self.logging_queue.get())
+ except Exception:
+ pass
self.logging_queue.close()
self.logger.info("queue closed")
diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptrunner.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptrunner.py
index f34698a6380..637cbe57b6f 100644
--- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptrunner.py
+++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptrunner.py
@@ -38,6 +38,7 @@ def setup_logging(*args, **kwargs):
global logger
logger = wptlogging.setup(*args, **kwargs)
+
def get_loader(test_paths, product, ssl_env, debug=None, run_info_extras=None, **kwargs):
if run_info_extras is None:
run_info_extras = {}
@@ -67,9 +68,11 @@ def get_loader(test_paths, product, ssl_env, debug=None, run_info_extras=None, *
chunk_type=kwargs["chunk_type"],
total_chunks=kwargs["total_chunks"],
chunk_number=kwargs["this_chunk"],
- include_https=ssl_env.ssl_enabled)
+ include_https=ssl_env.ssl_enabled,
+ skip_timeout=kwargs["skip_timeout"])
return run_info, test_loader
+
def list_test_groups(test_paths, product, **kwargs):
env.do_delayed_imports(logger, test_paths)
@@ -198,7 +201,7 @@ def run_tests(config, test_paths, product, **kwargs):
logger.info("Repetition %i / %i" % (repeat_count, repeat))
unexpected_count = 0
- logger.suite_start(test_loader.test_ids, run_info)
+ logger.suite_start(test_loader.test_ids, name='web-platform-test', run_info=run_info)
for test_type in kwargs["test_types"]:
logger.info("Running %s tests" % test_type)
@@ -217,10 +220,9 @@ def run_tests(config, test_paths, product, **kwargs):
ssl_env=ssl_env,
**kwargs)
-
executor_cls = executor_classes.get(test_type)
executor_kwargs = get_executor_kwargs(test_type,
- test_environment.external_config,
+ test_environment.config,
test_environment.cache_manager,
run_info,
**kwargs)
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/docs/pipes.rst b/tests/wpt/web-platform-tests/tools/wptserve/docs/pipes.rst
index c606140d474..39e98ab4f5e 100644
--- a/tests/wpt/web-platform-tests/tools/wptserve/docs/pipes.rst
+++ b/tests/wpt/web-platform-tests/tools/wptserve/docs/pipes.rst
@@ -11,6 +11,10 @@ functions are applied to the response from left to right. For example::
This would serve bytes 1 to 199, inclusive, of foo.txt with the HTTP status
code 404.
+.. note::
+ Pipes are only applied to static files, and will not work if applied to
+ other types of handlers, such as Python File Handlers.
+
There are several built-in pipe functions, and it is possible to add
more using the `@pipe` decorator on a function, if required.
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_pipes.py b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_pipes.py
index 95da70faea9..bd38f2ef18f 100644
--- a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_pipes.py
+++ b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_pipes.py
@@ -76,5 +76,11 @@ class TestTrickle(TestUsingServer):
self.assertEqual(resp.read(), expected)
self.assertGreater(6, t1-t0)
+ def test_headers(self):
+ resp = self.request("/document.txt", query="pipe=trickle(d0.01)")
+ self.assertEqual(resp.info()["Cache-Control"], "no-cache, no-store, must-revalidate")
+ self.assertEqual(resp.info()["Pragma"], "no-cache")
+ self.assertEqual(resp.info()["Expires"], "0")
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/wptserve/pipes.py b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/pipes.py
index 95108ba7e93..7203815b70c 100644
--- a/tests/wpt/web-platform-tests/tools/wptserve/wptserve/pipes.py
+++ b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/pipes.py
@@ -231,6 +231,13 @@ def trickle(request, response, delays):
content = resolve_content(response)
offset = [0]
+ if not ("Cache-Control" in response.headers or
+ "Pragma" in response.headers or
+ "Expires" in response.headers):
+ response.headers.set("Cache-Control", "no-cache, no-store, must-revalidate")
+ response.headers.set("Pragma", "no-cache")
+ response.headers.set("Expires", "0")
+
def add_content(delays, repeat=False):
for i, (item_type, value) in enumerate(delays):
if item_type == "bytes":
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/wptserve/server.py b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/server.py
index 0ab512cb2a5..2a83bd8097e 100644
--- a/tests/wpt/web-platform-tests/tools/wptserve/wptserve/server.py
+++ b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/server.py
@@ -418,7 +418,8 @@ class WebTestHttpd(object):
_host, self.port = self.httpd.socket.getsockname()
except Exception:
- self.logger.error('Init failed! You may need to modify your hosts file. Refer to README.md.')
+ self.logger.error("Failed to start HTTP server. "
+ "You may need to edit /etc/hosts or similar, see README.md.")
raise
def start(self, block=False):
diff --git a/tests/wpt/web-platform-tests/touch-events/multi-touch-interactions-manual.html b/tests/wpt/web-platform-tests/touch-events/multi-touch-interactions-manual.html
index e9835d9c90b..45e53af0ee9 100644
--- a/tests/wpt/web-platform-tests/touch-events/multi-touch-interactions-manual.html
+++ b/tests/wpt/web-platform-tests/touch-events/multi-touch-interactions-manual.html
@@ -1,7 +1,7 @@
<!DOCTYPE HTML>
<html>
<!--
- Test cases for Touch Events v1 Recommendation
+ Test cases for Touch Events v1 Recommendation
http://www.w3.org/TR/touch-events/
These tests are based on Mozilla-Nokia-Google's single-touch
@@ -21,29 +21,29 @@
<script src="/resources/testharnessreport.js"></script>
<script src="multi-touch-interactions.js"></script>
<style>
- div {
- margin: 0em;
- padding: 1.5em;
- }
- #target0 {
- background: yellow;
- border: 1px solid orange;
- }
- #target1 {
- background: lightblue;
- border: 1px solid blue;
- }
+ div {
+ margin: 0em;
+ padding: 1.5em;
+ }
+ #target0 {
+ background: yellow;
+ border: 1px solid orange;
+ }
+ #target1 {
+ background: lightblue;
+ border: 1px solid blue;
+ }
</style>
</head>
<body onload="run()">
- <h1>Touch Events: Multi-Touch Interaction Test</h1>
- <div id="target0">
- Touch this box with one finger, then another one...
- </div>
- <div id="target1">
- ...then drag to this box, then touch with a third finger, and lift all your fingers.
- </div>
- <div id="debug"></div>
- <div id="log"></div>
+ <h1>Touch Events: Multi-Touch Interaction Test</h1>
+ <div id="target0">
+ Touch this box with one finger, then another one...
+ </div>
+ <div id="target1">
+ ...then drag to this box, then touch with a third finger, and lift all your fingers.
+ </div>
+ <div id="debug"></div>
+ <div id="log"></div>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/touch-events/multi-touch-interactions.js b/tests/wpt/web-platform-tests/touch-events/multi-touch-interactions.js
index 5248e6a9430..955e32792da 100644
--- a/tests/wpt/web-platform-tests/touch-events/multi-touch-interactions.js
+++ b/tests/wpt/web-platform-tests/touch-events/multi-touch-interactions.js
@@ -4,368 +4,368 @@ var debug = document.getElementById("debug");
function debug_print (x) {
/* uncomment below statement to show debug messages */
-// document.getElementById("debug").innerHTML += x;
+// document.getElementById("debug").innerHTML += x;
}
var starting_elements = {};
function check_list_subset_of_targetlist(list, list_name, targetlist, targetlist_name) {
- var exist_in_targetlist;
- for(i=0; i<list.length; i++) {
- exist_in_targetlist=false;
- for(j=0; j<targetlist.length; j++)
- if(list.item(i).identifier==targetlist.item(j).identifier)
- exist_in_targetlist=true;
-
- assert_true(exist_in_targetlist, list_name + ".item("+i+") exists in " + targetlist_name);
- }
+ var exist_in_targetlist;
+ for(i=0; i<list.length; i++) {
+ exist_in_targetlist=false;
+ for(j=0; j<targetlist.length; j++)
+ if(list.item(i).identifier==targetlist.item(j).identifier)
+ exist_in_targetlist=true;
+
+ assert_true(exist_in_targetlist, list_name + ".item("+i+") exists in " + targetlist_name);
+ }
}
function check_list_subset_of_two_targetlists(list, list_name, targetlist1, targetlist1_name, targetlist2, targetlist2_name) {
- var exist_in_targetlists;
- for(i=0; i<list.length; i++) {
- exist_in_targetlists=false;
- for(j=0; j<targetlist1.length; j++)
- if(list.item(i).identifier==targetlist1.item(j).identifier)
- exist_in_targetlists=true;
+ var exist_in_targetlists;
+ for(i=0; i<list.length; i++) {
+ exist_in_targetlists=false;
+ for(j=0; j<targetlist1.length; j++)
+ if(list.item(i).identifier==targetlist1.item(j).identifier)
+ exist_in_targetlists=true;
- if(!exist_in_targetlists)
- for(j=0; j<targetlist2.length; j++)
- if(list.item(i).identifier==targetlist2.item(j).identifier)
- exist_in_targetlists=true;
+ if(!exist_in_targetlists)
+ for(j=0; j<targetlist2.length; j++)
+ if(list.item(i).identifier==targetlist2.item(j).identifier)
+ exist_in_targetlists=true;
- assert_true(exist_in_targetlists, list_name + ".item("+i+") exists in " + targetlist1_name + " or " + targetlist2_name);
- }
+ assert_true(exist_in_targetlists, list_name + ".item("+i+") exists in " + targetlist1_name + " or " + targetlist2_name);
+ }
}
function is_at_least_one_item_in_targetlist(list, targetlist) {
- for(i=0; i<list.length; i++)
- for(j=0; j<targetlist.length; j++)
- if(list.item(i).identifier==targetlist.item(j).identifier)
- return true;
+ for(i=0; i<list.length; i++)
+ for(j=0; j<targetlist.length; j++)
+ if(list.item(i).identifier==targetlist.item(j).identifier)
+ return true;
- return false;
+ return false;
}
function check_no_item_in_targetlist(list, list_name, targetlist, targetlist_name) {
- for(i=0; i<list.length; i++)
- for(j=0; j<targetlist.length; j++) {
- assert_false(list.item(i).identifier==targetlist.item(j).identifier, list_name + ".item("+i+") exists in " + targetlist_name);
- return;
- }
+ for(i=0; i<list.length; i++)
+ for(j=0; j<targetlist.length; j++) {
+ assert_false(list.item(i).identifier==targetlist.item(j).identifier, list_name + ".item("+i+") exists in " + targetlist_name);
+ return;
+ }
}
function check_targets(list, target) {
- for(i=0; i<list.length; i++)
- assert_true(list.item(i).target==target, "item(" + i + ").target is element receiving event");
+ for(i=0; i<list.length; i++)
+ assert_true(list.item(i).target==target, "item(" + i + ").target is element receiving event");
}
function check_starting_elements(list) {
- for (i=0; i<list.length; i++) {
- assert_equals(list.item(i).target, starting_elements[list.item(i).identifier], "item(" + i + ").target matches starting element");
- }
+ for (i=0; i<list.length; i++) {
+ assert_equals(list.item(i).target, starting_elements[list.item(i).identifier], "item(" + i + ").target matches starting element");
+ }
}
function run() {
- var target0 = document.getElementById("target0");
- var target1 = document.getElementById("target1");
-
- var test_touchstart = async_test("touchstart event received");
- var test_touchmove = async_test("touchmove event received");
- var test_touchend = async_test("touchend event received");
- var test_mousedown = async_test("Interaction with mouse events");
-
- var touchstart_received = 0;
- var touchmove_received = 0;
- var touchend_received = 0;
- var touchstart_identifier;
-
- // last received touch lists for comparison
- var last_touches;
- var last_targetTouches={};
- var last_changedTouches={};
-
- on_event(window, "touchstart", function onTouchStart(ev) {
- // process event only if it's targeted at target0 or target1
- if(ev.target != target0 && ev.target != target1 )
- return;
-
- ev.preventDefault();
-
- if(!touchstart_received) {
- // Check event ordering TA: 1.6.1
- test_touchstart.step(function() {
- assert_true(touchmove_received==0, "touchstart precedes touchmove");
- assert_true(touchend_received==0, "touchstart precedes touchend");
- });
- test_touchstart.done();
- test_mousedown.done(); // If we got here, then the mouse event test is not needed.
- }
- touchstart_received++;
-
- // TA: 1.3.2.2, 1.3.2.4
- test(function() {
- assert_true(ev.changedTouches.length >= 1, "changedTouches.length is at least 1");
- assert_true(ev.changedTouches.length <= ev.touches.length, "changedTouches.length is smaller than touches.length");
- check_list_subset_of_targetlist(ev.changedTouches, "changedTouches", ev.touches, "touches");
- }, "touchstart #" + touchstart_received + ": changedTouches is a subset of touches");
-
- // TA: 1.3.3.2, 1.3.3.3
- test(function() {
- assert_true(ev.targetTouches.length >= 1, "targetTouches.length is at least 1");
- assert_true(ev.targetTouches.length <= ev.touches.length, "targetTouches.length is smaller than touches.length");
- check_list_subset_of_targetlist(ev.targetTouches, "targetTouches", ev.touches, "touches");
- }, "touchstart #" + touchstart_received + ": targetTouches is a subset of touches");
-
- // TA: 1.3.3.9
- test(function() {
- check_targets(ev.targetTouches, ev.target);
- }, "touchstart #" + touchstart_received + ": targets of targetTouches are correct");
-
- // TA: 1.3.4.2
- test(function() {
- assert_true(ev.touches.length >= 1, "touches.length is at least 1");
- }, "touchstart #" + touchstart_received + ": touches.length is valid");
-
- if(touchstart_received == 1) {
- // TA: 1.3.3.5, 1.3.3.7
- test(function() {
- assert_true(ev.targetTouches.length <= ev.changedTouches.length, "targetTouches.length is smaller than changedTouches.length");
- check_list_subset_of_targetlist(ev.targetTouches, "targetTouches", ev.changedTouches, "changedTouches");
- }, "touchstart #" + touchstart_received + ": targetTouches is a subset of changedTouches");
-
- // TA: 1.3.4.3
- test(function() {
- assert_true(ev.touches.length==ev.changedTouches.length, "touches and changedTouches have the same length");
- }, "touchstart #" + touchstart_received + ": touches and changedTouches have the same length");
- } else {
- // TA: 1.3.3.6
- test(function() {
- var diff_in_targetTouches = ev.targetTouches.length - (last_targetTouches[ev.target.id] ? last_targetTouches[ev.target.id].length : 0);
- assert_true(diff_in_targetTouches > 0, "targetTouches.length is larger than last received targetTouches.length");
- assert_true(diff_in_targetTouches <= ev.changedTouches.length, "change in targetTouches.length is smaller than changedTouches.length");
- }, "touchstart #" + touchstart_received + ": change in targetTouches.length is valid");
-
- // TA: 1.3.3.8
- test(function() {
- assert_true(is_at_least_one_item_in_targetlist(ev.targetTouches, ev.changedTouches), "at least one item of targetTouches is in changedTouches");
- }, "touchstart #" + touchstart_received + ": at least one targetTouches item in changedTouches");
-
- // TA: 1.3.4.4
- test(function() {
- var diff_in_touches = ev.touches.length - last_touches.length;
- assert_true(diff_in_touches > 0, "touches.length is larger than last received touches.length");
- assert_true(diff_in_touches == ev.changedTouches.length, "change in touches.length equals changedTouches.length");
- }, "touchstart #" + touchstart_received + ": change in touches.length is valid");
-
- // TA: 1.3.4.5
- test(function() {
- check_list_subset_of_two_targetlists(ev.touches, "touches", ev.changedTouches, "changedTouches", last_touches, "last touches");
- }, "touchstart #" + touchstart_received + ": touches is subset of {changedTouches, last received touches}");
- }
-
- // save starting element of each new touch point
- for (i=0; i<ev.changedTouches.length; i++) {
- starting_elements[ev.changedTouches.item(i).identifier] = ev.changedTouches.item(i).target;
- }
-
- last_touches = ev.touches;
- last_targetTouches[ev.target.id] = ev.targetTouches;
- last_changedTouches = {}; // changedTouches are only saved for touchend events
- });
-
- on_event(window, "touchmove", function onTouchMove(ev) {
- // process event only if it's targeted at target0 or target1
- if(ev.target != target0 && ev.target != target1 )
- return;
-
- ev.preventDefault();
-
- // TA: 1.6.1
- test_touchmove.step(function() {
- assert_true(touchstart_received>0, "touchmove follows touchstart");
- // assert_false(touchend_received, "touchmove precedes touchend"); // this applies to scenario tests
- });
- test_touchmove.done();
-
- touchmove_received++;
-
- // do the detailed checking only for a few times
- if(touchmove_received<6) {
- // TA: 1.4.2.2, 1.4.2.4
- test(function() {
- assert_true(ev.changedTouches.length >= 1, "changedTouches.length is at least 1");
- assert_true(ev.changedTouches.length <= ev.touches.length, "changedTouches.length is smaller than touches.length");
- check_list_subset_of_targetlist(ev.changedTouches, "changedTouches", ev.touches, "touches");
- }, "touchmove #" + touchmove_received + ": changedTouches is a subset of touches");
-
- // TA: 1.4.3.2, 1.4.3.4
- test(function() {
- assert_true(ev.targetTouches.length >= 1, "targetTouches.length is at least 1");
- assert_true(ev.targetTouches.length <= ev.touches.length, "targetTouches.length is smaller than touches.length");
- check_list_subset_of_targetlist(ev.targetTouches, "targetTouches", ev.touches, "touches");
- }, "touchmove #" + touchmove_received + ": targetTouches is a subset of touches");
-
- // TA: 1.4.3.6
- test(function() {
- assert_true(is_at_least_one_item_in_targetlist(ev.targetTouches, ev.changedTouches), "at least one item of targetTouches is in changedTouches");
- }, "touchmove #" + touchmove_received + ": at least one targetTouches item in changedTouches");
-
- // TA: 1.4.3.8
- test(function() {
- check_targets(ev.targetTouches, ev.target);
- }, "touchmove #" + touchmove_received + ": targets of targetTouches are correct");
-
- // TA: 1.4.4.2
- test(function() {
- assert_true(ev.touches.length==last_touches.length, "length of touches is same as length of last received touches");
- check_list_subset_of_targetlist(ev.touches, "touches", last_touches, "last received touches");
- }, "touchmove #" + touchmove_received + ": touches must be same as last received touches");
-
- // TA: 1.6.3
- check_starting_elements(ev.changedTouches);
- }
-
- last_touches = ev.touches;
- last_targetTouches[ev.target.id] = ev.targetTouches;
- last_changedTouches = {}; // changedTouches are only saved for touchend events
- });
-
- on_event(window, "touchend", function onTouchEnd(ev) {
- // process event only if it's targeted at target0 or target1
- if(ev.target != target0 && ev.target != target1 )
- return;
-
- test_touchend.step(function() {
- assert_true(touchstart_received>0, "touchend follows touchstart");
- });
- test_touchend.done();
-
- touchend_received++;
-
- debug_print("touchend #" + touchend_received + ":<br>");
- debug_print("changedTouches.length=" + ev.changedTouches.length + "<br>");
- debug_print("targetTouches.length=" + ev.targetTouches.length + "<br>");
- debug_print("touches.length=" + ev.touches.length + "<br>");
- for(i=0; i<ev.changedTouches.length; i++)
- debug_print("changedTouches.item(" + i + ").target=" + ev.changedTouches.item(i).target.id + "<br>");
-
- // TA: 1.5.2.2
- test(function() {
- assert_true(ev.changedTouches.length >= 1, "changedTouches.length is at least 1");
- }, "touchend #" + touchend_received + ": length of changedTouches is valid");
-
- // TA: 1.5.2.3
- test(function() {
- check_list_subset_of_targetlist(ev.changedTouches, "changedTouches", last_touches, "last received touches");
- }, "touchend #" + touchend_received + ": changedTouches is a subset of last received touches");
-
- // TA: 1.5.2.4, 1.5.2.5
- test(function() {
- check_no_item_in_targetlist(ev.changedTouches, "changedTouches", ev.touches, "touches");
- check_no_item_in_targetlist(ev.changedTouches, "changedTouches", ev.targetTouches, "targetTouches");
- }, "touchend #" + touchend_received + ": no item in changedTouches are in touches or targetTouches");
-
- // TA: 1.5.2.6
- test(function() {
- var found=false;
- for (i=0; i<ev.changedTouches.length; i++)
- if (ev.changedTouches.item(i).target == ev.target)
- found=true;
- assert_true(found, "at least one item in changedTouches has matching target");
- }, "touchend #" + touchend_received + ": at least one item in changedTouches targeted at this element");
-
- // TA: 1.5.3.2, 1.5.3.3
- test(function() {
- assert_true(ev.targetTouches.length >= 0, "targetTouches.length is non-negative");
- assert_true(ev.targetTouches.length <= ev.touches.length, "targetTouches.length is smaller than touches.length");
- check_list_subset_of_targetlist(ev.targetTouches, "targetTouches", ev.touches, "touches");
- }, "touchend #" + touchend_received + ": targetTouches is a subset of touches");
-
- // TA: 1.5.3.5 (new)
- test(function() {
- check_targets(ev.targetTouches, ev.target);
- }, "touchend #" + touchend_received + ": targets of targetTouches are correct");
-
- // In some cases, when multiple touch points are released simultaneously
- // the UA would dispatch the "same" touchend event (same changedTouches, same touches, but possibly different targetTouches)
- // to each of the elements that are starting elements of the released touch points.
- // in these situations, the subsequent events are exempt from TA 1.5.3.4 and 1.5.4.2
- var same_event_as_last = false;
- if (last_changedTouches && last_changedTouches.length==ev.changedTouches.length) {
- same_event_as_last = true; // assume true until proven otherwise
- for (i=0; i<last_changedTouches.length; i++) {
- var match = false;
- for (j=0; j<ev.changedTouches.length; j++)
- if (last_changedTouches.item(i) == ev.changedTouches.item(j)) {
- match = true;
- break;
- }
- if (!match)
- same_event_as_last = false;
- }
- }
-
- if (!same_event_as_last) {
- // TA: 1.5.3.4
- // Getting semi-random failures on this and 1.5.4.2.
- // See 1.5.4.2. Not sure if it's the same issue...
- test(function() {
- assert_true(last_targetTouches[ev.target.id].length > 0, "last received targetTouches.length is not zero");
- var diff_in_targetTouches = last_targetTouches[ev.target.id].length - ev.targetTouches.length;
- debug_print("diff_in_targetTouches=" + diff_in_targetTouches + "<br>");
- assert_true(diff_in_targetTouches > 0, "targetTouches.length is smaller than last received targetTouches.length");
- assert_true(diff_in_targetTouches <= ev.changedTouches.length, "change in targetTouches.length is smaller than changedTouches.length");
- }, "touchend #" + touchend_received + ": change in targetTouches.length is valid");
-
- // TA: 1.5.4.2
- // Getting semi-random failures on this and 1.5.3.4.
- // It looks like if fingers are lifted simultaneously, the "same" touchend event can be dispatched to two target elements
- // but adapted to the element (same touches, changedTouches but different targetTouches).
- // When one event is processed after another, ev.touches would end up being identical to last_touches, leading to failure.
- // Question is why done() does not stop the processing of the latter event.
- test(function() {
- assert_true(last_touches.length > 0, "last received touches.length is not zero");
- var diff_in_touches = last_touches.length - ev.touches.length;
- debug_print("diff_in_touches=" + diff_in_touches + "<br>");
- assert_true(diff_in_touches > 0, "touches.length is smaller than last received touches.length");
- assert_equals(diff_in_touches, ev.changedTouches.length, "change in touches.length equals changedTouches.length");
- }, "touchend #" + touchend_received + ": change in touches.length is valid");
- }
-
- // TA: 1.6.4
- debug_print("touchend #" + touchend_received + ": TA 1.6.4<br>");
- test(function() {
- check_starting_elements(ev.changedTouches);
- }, "touchend #" + touchend_received + ": event dispatched to correct element<br>");
-
- debug_print("touchend #" + touchend_received + ": saving touch lists<br>");
-
- last_touches = ev.touches;
- last_targetTouches[ev.target.id] = ev.targetTouches;
- last_changedTouches = ev.changedTouches;
-
- debug_print("touchend #" + touchend_received + ": done<br>");
- if(ev.touches.length==0)
- done();
- });
-
- on_event(target0, "mousedown", function onMouseDown(ev) {
- test_mousedown.step(function() {
- assert_true(touchstart_received,
- "The touchstart event must be dispatched before any mouse " +
- "events. (If this fails, it might mean that the user agent does " +
- "not implement W3C touch events at all.)"
- );
- });
- test_mousedown.done();
-
- if (!touchstart_received) {
- // Abort the tests. If touch events are not supported, then most of
- // the other event handlers will never be called, and the test will
- // time out with misleading results.
- done();
- }
- });
+ var target0 = document.getElementById("target0");
+ var target1 = document.getElementById("target1");
+
+ var test_touchstart = async_test("touchstart event received");
+ var test_touchmove = async_test("touchmove event received");
+ var test_touchend = async_test("touchend event received");
+ var test_mousedown = async_test("Interaction with mouse events");
+
+ var touchstart_received = 0;
+ var touchmove_received = 0;
+ var touchend_received = 0;
+ var touchstart_identifier;
+
+ // last received touch lists for comparison
+ var last_touches;
+ var last_targetTouches={};
+ var last_changedTouches={};
+
+ on_event(window, "touchstart", function onTouchStart(ev) {
+ // process event only if it's targeted at target0 or target1
+ if(ev.target != target0 && ev.target != target1 )
+ return;
+
+ ev.preventDefault();
+
+ if(!touchstart_received) {
+ // Check event ordering TA: 1.6.1
+ test_touchstart.step(function() {
+ assert_true(touchmove_received==0, "touchstart precedes touchmove");
+ assert_true(touchend_received==0, "touchstart precedes touchend");
+ });
+ test_touchstart.done();
+ test_mousedown.done(); // If we got here, then the mouse event test is not needed.
+ }
+ touchstart_received++;
+
+ // TA: 1.3.2.2, 1.3.2.4
+ test(function() {
+ assert_true(ev.changedTouches.length >= 1, "changedTouches.length is at least 1");
+ assert_true(ev.changedTouches.length <= ev.touches.length, "changedTouches.length is smaller than touches.length");
+ check_list_subset_of_targetlist(ev.changedTouches, "changedTouches", ev.touches, "touches");
+ }, "touchstart #" + touchstart_received + ": changedTouches is a subset of touches");
+
+ // TA: 1.3.3.2, 1.3.3.3
+ test(function() {
+ assert_true(ev.targetTouches.length >= 1, "targetTouches.length is at least 1");
+ assert_true(ev.targetTouches.length <= ev.touches.length, "targetTouches.length is smaller than touches.length");
+ check_list_subset_of_targetlist(ev.targetTouches, "targetTouches", ev.touches, "touches");
+ }, "touchstart #" + touchstart_received + ": targetTouches is a subset of touches");
+
+ // TA: 1.3.3.9
+ test(function() {
+ check_targets(ev.targetTouches, ev.target);
+ }, "touchstart #" + touchstart_received + ": targets of targetTouches are correct");
+
+ // TA: 1.3.4.2
+ test(function() {
+ assert_true(ev.touches.length >= 1, "touches.length is at least 1");
+ }, "touchstart #" + touchstart_received + ": touches.length is valid");
+
+ if(touchstart_received == 1) {
+ // TA: 1.3.3.5, 1.3.3.7
+ test(function() {
+ assert_true(ev.targetTouches.length <= ev.changedTouches.length, "targetTouches.length is smaller than changedTouches.length");
+ check_list_subset_of_targetlist(ev.targetTouches, "targetTouches", ev.changedTouches, "changedTouches");
+ }, "touchstart #" + touchstart_received + ": targetTouches is a subset of changedTouches");
+
+ // TA: 1.3.4.3
+ test(function() {
+ assert_true(ev.touches.length==ev.changedTouches.length, "touches and changedTouches have the same length");
+ }, "touchstart #" + touchstart_received + ": touches and changedTouches have the same length");
+ } else {
+ // TA: 1.3.3.6
+ test(function() {
+ var diff_in_targetTouches = ev.targetTouches.length - (last_targetTouches[ev.target.id] ? last_targetTouches[ev.target.id].length : 0);
+ assert_true(diff_in_targetTouches > 0, "targetTouches.length is larger than last received targetTouches.length");
+ assert_true(diff_in_targetTouches <= ev.changedTouches.length, "change in targetTouches.length is smaller than changedTouches.length");
+ }, "touchstart #" + touchstart_received + ": change in targetTouches.length is valid");
+
+ // TA: 1.3.3.8
+ test(function() {
+ assert_true(is_at_least_one_item_in_targetlist(ev.targetTouches, ev.changedTouches), "at least one item of targetTouches is in changedTouches");
+ }, "touchstart #" + touchstart_received + ": at least one targetTouches item in changedTouches");
+
+ // TA: 1.3.4.4
+ test(function() {
+ var diff_in_touches = ev.touches.length - last_touches.length;
+ assert_true(diff_in_touches > 0, "touches.length is larger than last received touches.length");
+ assert_true(diff_in_touches == ev.changedTouches.length, "change in touches.length equals changedTouches.length");
+ }, "touchstart #" + touchstart_received + ": change in touches.length is valid");
+
+ // TA: 1.3.4.5
+ test(function() {
+ check_list_subset_of_two_targetlists(ev.touches, "touches", ev.changedTouches, "changedTouches", last_touches, "last touches");
+ }, "touchstart #" + touchstart_received + ": touches is subset of {changedTouches, last received touches}");
+ }
+
+ // save starting element of each new touch point
+ for (i=0; i<ev.changedTouches.length; i++) {
+ starting_elements[ev.changedTouches.item(i).identifier] = ev.changedTouches.item(i).target;
+ }
+
+ last_touches = ev.touches;
+ last_targetTouches[ev.target.id] = ev.targetTouches;
+ last_changedTouches = {}; // changedTouches are only saved for touchend events
+ });
+
+ on_event(window, "touchmove", function onTouchMove(ev) {
+ // process event only if it's targeted at target0 or target1
+ if(ev.target != target0 && ev.target != target1 )
+ return;
+
+ ev.preventDefault();
+
+ // TA: 1.6.1
+ test_touchmove.step(function() {
+ assert_true(touchstart_received>0, "touchmove follows touchstart");
+ // assert_false(touchend_received, "touchmove precedes touchend"); // this applies to scenario tests
+ });
+ test_touchmove.done();
+
+ touchmove_received++;
+
+ // do the detailed checking only for a few times
+ if(touchmove_received<6) {
+ // TA: 1.4.2.2, 1.4.2.4
+ test(function() {
+ assert_true(ev.changedTouches.length >= 1, "changedTouches.length is at least 1");
+ assert_true(ev.changedTouches.length <= ev.touches.length, "changedTouches.length is smaller than touches.length");
+ check_list_subset_of_targetlist(ev.changedTouches, "changedTouches", ev.touches, "touches");
+ }, "touchmove #" + touchmove_received + ": changedTouches is a subset of touches");
+
+ // TA: 1.4.3.2, 1.4.3.4
+ test(function() {
+ assert_true(ev.targetTouches.length >= 1, "targetTouches.length is at least 1");
+ assert_true(ev.targetTouches.length <= ev.touches.length, "targetTouches.length is smaller than touches.length");
+ check_list_subset_of_targetlist(ev.targetTouches, "targetTouches", ev.touches, "touches");
+ }, "touchmove #" + touchmove_received + ": targetTouches is a subset of touches");
+
+ // TA: 1.4.3.6
+ test(function() {
+ assert_true(is_at_least_one_item_in_targetlist(ev.targetTouches, ev.changedTouches), "at least one item of targetTouches is in changedTouches");
+ }, "touchmove #" + touchmove_received + ": at least one targetTouches item in changedTouches");
+
+ // TA: 1.4.3.8
+ test(function() {
+ check_targets(ev.targetTouches, ev.target);
+ }, "touchmove #" + touchmove_received + ": targets of targetTouches are correct");
+
+ // TA: 1.4.4.2
+ test(function() {
+ assert_true(ev.touches.length==last_touches.length, "length of touches is same as length of last received touches");
+ check_list_subset_of_targetlist(ev.touches, "touches", last_touches, "last received touches");
+ }, "touchmove #" + touchmove_received + ": touches must be same as last received touches");
+
+ // TA: 1.6.3
+ check_starting_elements(ev.changedTouches);
+ }
+
+ last_touches = ev.touches;
+ last_targetTouches[ev.target.id] = ev.targetTouches;
+ last_changedTouches = {}; // changedTouches are only saved for touchend events
+ });
+
+ on_event(window, "touchend", function onTouchEnd(ev) {
+ // process event only if it's targeted at target0 or target1
+ if(ev.target != target0 && ev.target != target1 )
+ return;
+
+ test_touchend.step(function() {
+ assert_true(touchstart_received>0, "touchend follows touchstart");
+ });
+ test_touchend.done();
+
+ touchend_received++;
+
+ debug_print("touchend #" + touchend_received + ":<br>");
+ debug_print("changedTouches.length=" + ev.changedTouches.length + "<br>");
+ debug_print("targetTouches.length=" + ev.targetTouches.length + "<br>");
+ debug_print("touches.length=" + ev.touches.length + "<br>");
+ for(i=0; i<ev.changedTouches.length; i++)
+ debug_print("changedTouches.item(" + i + ").target=" + ev.changedTouches.item(i).target.id + "<br>");
+
+ // TA: 1.5.2.2
+ test(function() {
+ assert_true(ev.changedTouches.length >= 1, "changedTouches.length is at least 1");
+ }, "touchend #" + touchend_received + ": length of changedTouches is valid");
+
+ // TA: 1.5.2.3
+ test(function() {
+ check_list_subset_of_targetlist(ev.changedTouches, "changedTouches", last_touches, "last received touches");
+ }, "touchend #" + touchend_received + ": changedTouches is a subset of last received touches");
+
+ // TA: 1.5.2.4, 1.5.2.5
+ test(function() {
+ check_no_item_in_targetlist(ev.changedTouches, "changedTouches", ev.touches, "touches");
+ check_no_item_in_targetlist(ev.changedTouches, "changedTouches", ev.targetTouches, "targetTouches");
+ }, "touchend #" + touchend_received + ": no item in changedTouches are in touches or targetTouches");
+
+ // TA: 1.5.2.6
+ test(function() {
+ var found=false;
+ for (i=0; i<ev.changedTouches.length; i++)
+ if (ev.changedTouches.item(i).target == ev.target)
+ found=true;
+ assert_true(found, "at least one item in changedTouches has matching target");
+ }, "touchend #" + touchend_received + ": at least one item in changedTouches targeted at this element");
+
+ // TA: 1.5.3.2, 1.5.3.3
+ test(function() {
+ assert_true(ev.targetTouches.length >= 0, "targetTouches.length is non-negative");
+ assert_true(ev.targetTouches.length <= ev.touches.length, "targetTouches.length is smaller than touches.length");
+ check_list_subset_of_targetlist(ev.targetTouches, "targetTouches", ev.touches, "touches");
+ }, "touchend #" + touchend_received + ": targetTouches is a subset of touches");
+
+ // TA: 1.5.3.5 (new)
+ test(function() {
+ check_targets(ev.targetTouches, ev.target);
+ }, "touchend #" + touchend_received + ": targets of targetTouches are correct");
+
+ // In some cases, when multiple touch points are released simultaneously
+ // the UA would dispatch the "same" touchend event (same changedTouches, same touches, but possibly different targetTouches)
+ // to each of the elements that are starting elements of the released touch points.
+ // in these situations, the subsequent events are exempt from TA 1.5.3.4 and 1.5.4.2
+ var same_event_as_last = false;
+ if (last_changedTouches && last_changedTouches.length==ev.changedTouches.length) {
+ same_event_as_last = true; // assume true until proven otherwise
+ for (i=0; i<last_changedTouches.length; i++) {
+ var match = false;
+ for (j=0; j<ev.changedTouches.length; j++)
+ if (last_changedTouches.item(i) == ev.changedTouches.item(j)) {
+ match = true;
+ break;
+ }
+ if (!match)
+ same_event_as_last = false;
+ }
+ }
+
+ if (!same_event_as_last) {
+ // TA: 1.5.3.4
+ // Getting semi-random failures on this and 1.5.4.2.
+ // See 1.5.4.2. Not sure if it's the same issue...
+ test(function() {
+ assert_true(last_targetTouches[ev.target.id].length > 0, "last received targetTouches.length is not zero");
+ var diff_in_targetTouches = last_targetTouches[ev.target.id].length - ev.targetTouches.length;
+ debug_print("diff_in_targetTouches=" + diff_in_targetTouches + "<br>");
+ assert_true(diff_in_targetTouches > 0, "targetTouches.length is smaller than last received targetTouches.length");
+ assert_true(diff_in_targetTouches <= ev.changedTouches.length, "change in targetTouches.length is smaller than changedTouches.length");
+ }, "touchend #" + touchend_received + ": change in targetTouches.length is valid");
+
+ // TA: 1.5.4.2
+ // Getting semi-random failures on this and 1.5.3.4.
+ // It looks like if fingers are lifted simultaneously, the "same" touchend event can be dispatched to two target elements
+ // but adapted to the element (same touches, changedTouches but different targetTouches).
+ // When one event is processed after another, ev.touches would end up being identical to last_touches, leading to failure.
+ // Question is why done() does not stop the processing of the latter event.
+ test(function() {
+ assert_true(last_touches.length > 0, "last received touches.length is not zero");
+ var diff_in_touches = last_touches.length - ev.touches.length;
+ debug_print("diff_in_touches=" + diff_in_touches + "<br>");
+ assert_true(diff_in_touches > 0, "touches.length is smaller than last received touches.length");
+ assert_equals(diff_in_touches, ev.changedTouches.length, "change in touches.length equals changedTouches.length");
+ }, "touchend #" + touchend_received + ": change in touches.length is valid");
+ }
+
+ // TA: 1.6.4
+ debug_print("touchend #" + touchend_received + ": TA 1.6.4<br>");
+ test(function() {
+ check_starting_elements(ev.changedTouches);
+ }, "touchend #" + touchend_received + ": event dispatched to correct element<br>");
+
+ debug_print("touchend #" + touchend_received + ": saving touch lists<br>");
+
+ last_touches = ev.touches;
+ last_targetTouches[ev.target.id] = ev.targetTouches;
+ last_changedTouches = ev.changedTouches;
+
+ debug_print("touchend #" + touchend_received + ": done<br>");
+ if(ev.touches.length==0)
+ done();
+ });
+
+ on_event(target0, "mousedown", function onMouseDown(ev) {
+ test_mousedown.step(function() {
+ assert_true(touchstart_received,
+ "The touchstart event must be dispatched before any mouse " +
+ "events. (If this fails, it might mean that the user agent does " +
+ "not implement W3C touch events at all.)"
+ );
+ });
+ test_mousedown.done();
+
+ if (!touchstart_received) {
+ // Abort the tests. If touch events are not supported, then most of
+ // the other event handlers will never be called, and the test will
+ // time out with misleading results.
+ done();
+ }
+ });
}
diff --git a/tests/wpt/web-platform-tests/touch-events/multi-touch-interfaces-manual.html b/tests/wpt/web-platform-tests/touch-events/multi-touch-interfaces-manual.html
index 6d0f7d433b9..e593fd0b961 100644
--- a/tests/wpt/web-platform-tests/touch-events/multi-touch-interfaces-manual.html
+++ b/tests/wpt/web-platform-tests/touch-events/multi-touch-interfaces-manual.html
@@ -147,127 +147,127 @@
default:
break;
}
- });
+ });
}
function is_touch_over_element(touch, element) {
- var bounds = element.getBoundingClientRect();
- return touch.pageX >= bounds.left && touch.pageX <= bounds.right &&
- touch.pageY >= bounds.top && touch.pageY <= bounds.bottom;
+ var bounds = element.getBoundingClientRect();
+ return touch.pageX >= bounds.left && touch.pageX <= bounds.right &&
+ touch.pageY >= bounds.top && touch.pageY <= bounds.bottom;
}
function check_touch_clientXY(touch) {
- assert_equals(touch.clientX, touch.pageX - window.pageXOffset, "touch.clientX is touch.pageX - window.pageXOffset.");
- assert_equals(touch.clientY, touch.pageY - window.pageYOffset, "touch.clientY is touch.pageY - window.pageYOffset.");
+ assert_equals(touch.clientX, touch.pageX - window.pageXOffset, "touch.clientX is touch.pageX - window.pageXOffset.");
+ assert_equals(touch.clientY, touch.pageY - window.pageYOffset, "touch.clientY is touch.pageY - window.pageYOffset.");
}
function run() {
- var target0 = document.getElementById("target0");
- var target1 = document.getElementById("target1");
+ var target0 = document.getElementById("target0");
+ var target1 = document.getElementById("target1");
- var test_touchstart = async_test("touchstart event received");
- var test_touchmove = async_test("touchmove event received");
- var test_touchend = async_test("touchend event received");
- var test_mousedown = async_test("Interaction with mouse events");
+ var test_touchstart = async_test("touchstart event received");
+ var test_touchmove = async_test("touchmove event received");
+ var test_touchend = async_test("touchend event received");
+ var test_mousedown = async_test("Interaction with mouse events");
- var touchstart_received = 0;
- var touchmove_received = false;
- var touchend_received = false;
- var invalid_touchmove_received = false;
+ var touchstart_received = 0;
+ var touchmove_received = false;
+ var touchend_received = false;
+ var invalid_touchmove_received = false;
- on_event(target0, "touchstart", function onTouchStart(ev) {
- ev.preventDefault();
+ on_event(target0, "touchstart", function onTouchStart(ev) {
+ ev.preventDefault();
- if(!touchstart_received) {
- // Check event ordering TA: 1.6.2
- test_touchstart.step(function() {
- assert_false(touchmove_received, "touchstart precedes touchmove");
- assert_false(touchend_received, "touchstart precedes touchend");
- });
- test_touchstart.done();
- test_mousedown.done(); // If we got here, then the mouse event test is not needed.
- }
+ if(!touchstart_received) {
+ // Check event ordering TA: 1.6.2
+ test_touchstart.step(function() {
+ assert_false(touchmove_received, "touchstart precedes touchmove");
+ assert_false(touchend_received, "touchstart precedes touchend");
+ });
+ test_touchstart.done();
+ test_mousedown.done(); // If we got here, then the mouse event test is not needed.
+ }
- if(++touchstart_received <= 2)
- check_TouchEvent(ev);
- });
+ if(++touchstart_received <= 2)
+ check_TouchEvent(ev);
+ });
- on_event(target0, "touchmove", function onTouchMove(ev) {
- ev.preventDefault();
+ on_event(target0, "touchmove", function onTouchMove(ev) {
+ ev.preventDefault();
- if (touchmove_received)
- return;
- touchmove_received = true;
+ if (touchmove_received)
+ return;
+ touchmove_received = true;
- test_touchmove.step(function() {
- assert_true(touchstart_received>0, "touchmove follows touchstart");
- assert_false(touchend_received, "touchmove precedes touchend");
- });
- test_touchmove.done();
+ test_touchmove.step(function() {
+ assert_true(touchstart_received>0, "touchmove follows touchstart");
+ assert_false(touchend_received, "touchmove precedes touchend");
+ });
+ test_touchmove.done();
- check_TouchEvent(ev);
- });
+ check_TouchEvent(ev);
+ });
- on_event(target1, "touchmove", function onTouchMove(ev) {
- invalid_touchmove_received = true;
- });
+ on_event(target1, "touchmove", function onTouchMove(ev) {
+ invalid_touchmove_received = true;
+ });
- on_event(window, "touchend", function onTouchEnd(ev) {
- touchend_received = true;
+ on_event(window, "touchend", function onTouchEnd(ev) {
+ touchend_received = true;
- test_touchend.step(function() {
- assert_true(touchstart_received>0, "touchend follows touchstart");
- assert_true(touchmove_received, "touchend follows touchmove");
- assert_false(invalid_touchmove_received, "touchmove dispatched to correct target");
- });
- test_touchend.done();
+ test_touchend.step(function() {
+ assert_true(touchstart_received>0, "touchend follows touchstart");
+ assert_true(touchmove_received, "touchend follows touchmove");
+ assert_false(invalid_touchmove_received, "touchmove dispatched to correct target");
+ });
+ test_touchend.done();
- check_TouchEvent(ev);
- done();
- });
+ check_TouchEvent(ev);
+ done();
+ });
- on_event(target0, "mousedown", function onMouseDown(ev) {
- test_mousedown.step(function() {
- assert_true(touchstart_received,
- "The touchstart event must be dispatched before any mouse " +
- "events. (If this fails, it might mean that the user agent does " +
- "not implement W3C touch events at all.)"
- );
- });
- test_mousedown.done();
+ on_event(target0, "mousedown", function onMouseDown(ev) {
+ test_mousedown.step(function() {
+ assert_true(touchstart_received,
+ "The touchstart event must be dispatched before any mouse " +
+ "events. (If this fails, it might mean that the user agent does " +
+ "not implement W3C touch events at all.)"
+ );
+ });
+ test_mousedown.done();
- if (!touchstart_received) {
- // Abort the tests. If touch events are not supported, then most of
- // the other event handlers will never be called, and the test will
- // time out with misleading results.
- done();
- }
- });
- }
+ if (!touchstart_received) {
+ // Abort the tests. If touch events are not supported, then most of
+ // the other event handlers will never be called, and the test will
+ // time out with misleading results.
+ done();
+ }
+ });
+ }
</script>
<style>
- div {
- margin: 0em;
- padding: 2em;
- }
- #target0 {
- background: yellow;
- border: 1px solid orange;
- }
- #target1 {
- background: lightblue;
- border: 1px solid blue;
- }
+ div {
+ margin: 0em;
+ padding: 2em;
+ }
+ #target0 {
+ background: yellow;
+ border: 1px solid orange;
+ }
+ #target1 {
+ background: lightblue;
+ border: 1px solid blue;
+ }
</style>
</head>
<body onload="run()">
- <h1>Touch Events: multi-touch interface tests</h1>
- <div id="target0">
- Touch this box with one finger, then another one...
- </div>
- <div id="target1">
- ...then drag to this box and lift your fingers.
- </div>
- <div id="log"></div>
+ <h1>Touch Events: multi-touch interface tests</h1>
+ <div id="target0">
+ Touch this box with one finger, then another one...
+ </div>
+ <div id="target1">
+ ...then drag to this box and lift your fingers.
+ </div>
+ <div id="log"></div>
</body>
</html>
diff --git a/tests/wpt/web-platform-tests/uievents/mouse/layout_change_should_fire_mouseover-manual.html b/tests/wpt/web-platform-tests/uievents/mouse/layout_change_should_fire_mouseover-manual.html
new file mode 100644
index 00000000000..f36fadb697b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/uievents/mouse/layout_change_should_fire_mouseover-manual.html
@@ -0,0 +1,83 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Mouseover/enter is sent on layout change</title>
+ <meta name="viewport" content="width=device-width">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style>
+ #spacer {
+ height: 100px;
+ width: 100px;
+ }
+ #red {
+ background-color: rgb(255, 0, 0);
+ position: absolute;
+ z-index: 0;
+ left: 0px;
+ top: 0px;
+ height: 100px;
+ width: 100px;
+ }
+ #blue {
+ background-color: rgb(0, 0, 255);
+ position: absolute;
+ z-index: 1;
+ left: 0px;
+ top: 0px;
+ height: 100px;
+ width: 100px;
+ }
+ #blue:hover {
+ background-color: rgb(255, 255, 0);
+ }
+ </style>
+ </head>
+ <body onload="run();">
+ <div id="spacer"></div>
+ <div id="red"></div>
+ <h4>Test Description: Tests that the mouseover event is fired and the element has a hover effect when the element underneath the mouse cursor is changed.
+ <ol>
+ <li>Put your mouse over the red rectangle</li>
+ <li>Click the primary mouse button</li>
+ </ol>
+ </h4>
+ <script type="text/javascript">
+ var testMouseOver = async_test('Tests that the mouseover event is fired and the element has a hover effect when the element underneath the mouse cursor is changed.');
+
+ var eventList = [];
+ function addBlue() {
+ document.body.innerHTML += '<div id="blue"></div>';
+ var blue = document.getElementById("blue");
+ var events = ['mouseover', 'mousemove', 'mouseout', 'mouseenter', 'mouseleave'];
+ events.forEach(function (event) {
+ blue.addEventListener(event, checkHoverEffect);
+ });
+ testMouseOver.step_timeout(function () {
+ checkEventSequence();
+ }, 2500);
+ }
+
+ function checkEventSequence() {
+ var result = eventList.join();
+ assert_true(result == 'mouseover,mouseenter');
+ testMouseOver.done();
+ }
+
+ function run() {
+ document.addEventListener('click', addBlue);
+ }
+
+ function checkHoverEffect(event) {
+ eventList.push(event.type);
+ testMouseOver.step(function () {
+ assert_equals(event.target.id, "blue");
+ assert_equals(getComputedStyle(event.target).backgroundColor, "rgb(255, 255, 0)");
+ if (event.type == "mouseenter") {
+ checkEventSequence();
+ }
+ });
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/update-built-tests.sh b/tests/wpt/web-platform-tests/update-built-tests.sh
index 63722f4b1d0..f44dd5e3f6b 100755
--- a/tests/wpt/web-platform-tests/update-built-tests.sh
+++ b/tests/wpt/web-platform-tests/update-built-tests.sh
@@ -5,3 +5,4 @@ set -ex
infrastructure/assumptions/tools/build.sh
html/tools/build.sh
offscreen-canvas/tools/build.sh
+python mimesniff/mime-types/resources/generated-mime-types.py
diff --git a/tests/wpt/web-platform-tests/url/setters_tests.json b/tests/wpt/web-platform-tests/url/setters_tests.json
index f35db16e8d1..714bd5e7ce2 100644
--- a/tests/wpt/web-platform-tests/url/setters_tests.json
+++ b/tests/wpt/web-platform-tests/url/setters_tests.json
@@ -1786,12 +1786,52 @@
}
},
{
+ "href": "http://example.net",
+ "new_value": "#foo bar",
+ "expected": {
+ "href": "http://example.net/#foo%20bar",
+ "hash": "#foo%20bar"
+ }
+ },
+ {
+ "href": "http://example.net",
+ "new_value": "#foo\"bar",
+ "expected": {
+ "href": "http://example.net/#foo%22bar",
+ "hash": "#foo%22bar"
+ }
+ },
+ {
+ "href": "http://example.net",
+ "new_value": "#foo<bar",
+ "expected": {
+ "href": "http://example.net/#foo%3Cbar",
+ "hash": "#foo%3Cbar"
+ }
+ },
+ {
+ "href": "http://example.net",
+ "new_value": "#foo>bar",
+ "expected": {
+ "href": "http://example.net/#foo%3Ebar",
+ "hash": "#foo%3Ebar"
+ }
+ },
+ {
+ "href": "http://example.net",
+ "new_value": "#foo`bar",
+ "expected": {
+ "href": "http://example.net/#foo%60bar",
+ "hash": "#foo%60bar"
+ }
+ },
+ {
"comment": "Simple percent-encoding; nuls, tabs, and newlines are removed",
"href": "a:/",
"new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé",
"expected": {
- "href": "a:/#%01%1F !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~%7F%C2%80%C2%81%C3%89%C3%A9",
- "hash": "#%01%1F !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~%7F%C2%80%C2%81%C3%89%C3%A9"
+ "href": "a:/#%01%1F%20!%22#$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_%60az{|}~%7F%C2%80%C2%81%C3%89%C3%A9",
+ "hash": "#%01%1F%20!%22#$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_%60az{|}~%7F%C2%80%C2%81%C3%89%C3%A9"
}
},
{
diff --git a/tests/wpt/web-platform-tests/url/urltestdata.json b/tests/wpt/web-platform-tests/url/urltestdata.json
index 069176141d5..867056619b4 100644
--- a/tests/wpt/web-platform-tests/url/urltestdata.json
+++ b/tests/wpt/web-platform-tests/url/urltestdata.json
@@ -153,7 +153,7 @@
{
"input": "http://f:21/ b ? d # e ",
"base": "http://example.org/foo/bar",
- "href": "http://f:21/%20b%20?%20d%20# e",
+ "href": "http://f:21/%20b%20?%20d%20#%20e",
"origin": "http://f:21",
"protocol": "http:",
"username": "",
@@ -163,12 +163,12 @@
"port": "21",
"pathname": "/%20b%20",
"search": "?%20d%20",
- "hash": "# e"
+ "hash": "#%20e"
},
{
"input": "lolscheme:x x#x x",
"base": "about:blank",
- "href": "lolscheme:x x#x x",
+ "href": "lolscheme:x x#x%20x",
"protocol": "lolscheme:",
"username": "",
"password": "",
@@ -177,7 +177,7 @@
"port": "",
"pathname": "x x",
"search": "",
- "hash": "#x x"
+ "hash": "#x%20x"
},
{
"input": "http://f:/c",
@@ -2260,7 +2260,7 @@
{
"input": "http://www.google.com/foo?bar=baz# »",
"base": "about:blank",
- "href": "http://www.google.com/foo?bar=baz# %C2%BB",
+ "href": "http://www.google.com/foo?bar=baz#%20%C2%BB",
"origin": "http://www.google.com",
"protocol": "http:",
"username": "",
@@ -2270,12 +2270,12 @@
"port": "",
"pathname": "/foo",
"search": "?bar=baz",
- "hash": "# %C2%BB"
+ "hash": "#%20%C2%BB"
},
{
"input": "data:test# »",
"base": "about:blank",
- "href": "data:test# %C2%BB",
+ "href": "data:test#%20%C2%BB",
"origin": "null",
"protocol": "data:",
"username": "",
@@ -2285,7 +2285,7 @@
"port": "",
"pathname": "test",
"search": "",
- "hash": "# %C2%BB"
+ "hash": "#%20%C2%BB"
},
{
"input": "http://www.google.com",
@@ -4787,6 +4787,70 @@
"searchParams": "qux=",
"hash": "#foo%08bar"
},
+ {
+ "input": "http://foo.bar/baz?qux#foo\"bar",
+ "base": "about:blank",
+ "href": "http://foo.bar/baz?qux#foo%22bar",
+ "origin": "http://foo.bar",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "foo.bar",
+ "hostname": "foo.bar",
+ "port": "",
+ "pathname": "/baz",
+ "search": "?qux",
+ "searchParams": "qux=",
+ "hash": "#foo%22bar"
+ },
+ {
+ "input": "http://foo.bar/baz?qux#foo<bar",
+ "base": "about:blank",
+ "href": "http://foo.bar/baz?qux#foo%3Cbar",
+ "origin": "http://foo.bar",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "foo.bar",
+ "hostname": "foo.bar",
+ "port": "",
+ "pathname": "/baz",
+ "search": "?qux",
+ "searchParams": "qux=",
+ "hash": "#foo%3Cbar"
+ },
+ {
+ "input": "http://foo.bar/baz?qux#foo>bar",
+ "base": "about:blank",
+ "href": "http://foo.bar/baz?qux#foo%3Ebar",
+ "origin": "http://foo.bar",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "foo.bar",
+ "hostname": "foo.bar",
+ "port": "",
+ "pathname": "/baz",
+ "search": "?qux",
+ "searchParams": "qux=",
+ "hash": "#foo%3Ebar"
+ },
+ {
+ "input": "http://foo.bar/baz?qux#foo`bar",
+ "base": "about:blank",
+ "href": "http://foo.bar/baz?qux#foo%60bar",
+ "origin": "http://foo.bar",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "foo.bar",
+ "hostname": "foo.bar",
+ "port": "",
+ "pathname": "/baz",
+ "search": "?qux",
+ "searchParams": "qux=",
+ "hash": "#foo%60bar"
+ },
"# IPv4 parsing (via https://github.com/nodejs/node/pull/10317)",
{
"input": "http://192.168.257",
diff --git a/tests/wpt/web-platform-tests/wai-aria/alertdialog_modal_false-manual.html b/tests/wpt/web-platform-tests/wai-aria/alertdialog_modal_false-manual.html
index 6dd2cee71c0..5a5829e924e 100644
--- a/tests/wpt/web-platform-tests/wai-aria/alertdialog_modal_false-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/alertdialog_modal_false-manual.html
@@ -76,7 +76,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Pane"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/alertdialog_modal_true-manual.html b/tests/wpt/web-platform-tests/wai-aria/alertdialog_modal_true-manual.html
index 5ff5660f051..b86bcae6c9f 100644
--- a/tests/wpt/web-platform-tests/wai-aria/alertdialog_modal_true-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/alertdialog_modal_true-manual.html
@@ -56,7 +56,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Pane"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/application_activedescendant-manual.html b/tests/wpt/web-platform-tests/wai-aria/application_activedescendant-manual.html
index 5a103d92939..4e256bd51e6 100644
--- a/tests/wpt/web-platform-tests/wai-aria/application_activedescendant-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/application_activedescendant-manual.html
@@ -92,13 +92,13 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Pane"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"application"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/application_activedescendant_value_changes-manual.html b/tests/wpt/web-platform-tests/wai-aria/application_activedescendant_value_changes-manual.html
index 04260aab7a8..b8523236030 100644
--- a/tests/wpt/web-platform-tests/wai-aria/application_activedescendant_value_changes-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/application_activedescendant_value_changes-manual.html
@@ -87,7 +87,7 @@
"event",
"type",
"is",
- "IA2_EVENT_ACTIVE_DESCENDANT_CHANGED"
+ "EVENT_OBJECT_FOCUS"
]
],
"MSAA" : [
@@ -113,13 +113,13 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Pane"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"application"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/aria-current_not_declared-manual.html b/tests/wpt/web-platform-tests/wai-aria/aria-current_not_declared-manual.html
index 25cf95c9417..471e718c2ec 100644
--- a/tests/wpt/web-platform-tests/wai-aria/aria-current_not_declared-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/aria-current_not_declared-manual.html
@@ -82,7 +82,7 @@
"UIA" : [
[
"property",
- "role",
+ "ControlType",
"is",
"ListItem"
],
@@ -90,7 +90,7 @@
"property",
"current",
"is",
- "false"
+ ""
]
]
},
diff --git a/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_changes-manual.html b/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_changes-manual.html
index f4297f1fb67..84e0b60f60d 100644
--- a/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_changes-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_changes-manual.html
@@ -75,9 +75,9 @@
"UIA" : [
[
"property",
- "objectAttributes",
- "contains",
- "current:false"
+ "current",
+ "is",
+ "false"
],
[
"event",
diff --git a/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_date-manual.html b/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_date-manual.html
index 8f4cb42ac73..0438ef5d280 100644
--- a/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_date-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_date-manual.html
@@ -82,8 +82,8 @@
"UIA" : [
[
"property",
- "role",
- "is",
+ "controlPatterns",
+ "contains",
"TableItem"
],
[
diff --git a/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_location-manual.html b/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_location-manual.html
index 4e4444319e7..aac8e63f787 100644
--- a/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_location-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_location-manual.html
@@ -82,7 +82,7 @@
"UIA" : [
[
"property",
- "role",
+ "ControlType",
"is",
"Image"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_page-manual.html b/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_page-manual.html
index d8fe5a41d64..4ff50ac1b40 100644
--- a/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_page-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_page-manual.html
@@ -88,7 +88,7 @@
"UIA" : [
[
"property",
- "role",
+ "ControlType",
"is",
"HyperLink"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_step-manual.html b/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_step-manual.html
index 4b730e7fd4b..812ec036854 100644
--- a/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_step-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_step-manual.html
@@ -88,7 +88,7 @@
"UIA" : [
[
"property",
- "role",
+ "ControlType",
"is",
"HyperLink"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_time-manual.html b/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_time-manual.html
index ae78d8348ec..3362af00dd6 100644
--- a/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_time-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_time-manual.html
@@ -82,8 +82,8 @@
"UIA" : [
[
"property",
- "role",
- "is",
+ "controlPatterns",
+ "contains",
"TableItem"
],
[
diff --git a/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_true-manual.html b/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_true-manual.html
index 57dcf29c6d7..bf7377705d7 100644
--- a/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_true-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_true-manual.html
@@ -82,7 +82,7 @@
"UIA" : [
[
"property",
- "role",
+ "ControlType",
"is",
"ListItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_unspecified-manual.html
index 74486b8d180..271c085eb35 100644
--- a/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/aria-current_with_value_unspecified-manual.html
@@ -76,7 +76,7 @@
"UIA" : [
[
"property",
- "role",
+ "ControlType",
"is",
"ListItem"
],
@@ -84,7 +84,7 @@
"property",
"current",
"is",
- "false"
+ ""
]
]
},
diff --git a/tests/wpt/web-platform-tests/wai-aria/article_in_feed_posinset_and_setsize-manual.html b/tests/wpt/web-platform-tests/wai-aria/article_in_feed_posinset_and_setsize-manual.html
index d7145bda6e7..ff960795b40 100644
--- a/tests/wpt/web-platform-tests/wai-aria/article_in_feed_posinset_and_setsize-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/article_in_feed_posinset_and_setsize-manual.html
@@ -124,13 +124,13 @@
"UIA" : [
[
"property",
- "control type",
+ "ControlType",
"is",
"Group"
],
[
"property",
- "localize control type",
+ "LocalizedControlType",
"is",
"article"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/article_in_feed_setsize_-1-manual.html b/tests/wpt/web-platform-tests/wai-aria/article_in_feed_setsize_-1-manual.html
index 0c270171373..dd87dc5d874 100644
--- a/tests/wpt/web-platform-tests/wai-aria/article_in_feed_setsize_-1-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/article_in_feed_setsize_-1-manual.html
@@ -100,13 +100,13 @@
"UIA" : [
[
"property",
- "control type",
+ "ControlType",
"is",
"Group"
],
[
"property",
- "localize control type",
+ "LocalizedControlType",
"is",
"article"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/article_not_in_feed_posinset_and_setsize-manual.html b/tests/wpt/web-platform-tests/wai-aria/article_not_in_feed_posinset_and_setsize-manual.html
index ab45edccd4e..57e92c1ebcf 100644
--- a/tests/wpt/web-platform-tests/wai-aria/article_not_in_feed_posinset_and_setsize-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/article_not_in_feed_posinset_and_setsize-manual.html
@@ -130,13 +130,13 @@
"UIA" : [
[
"property",
- "control type",
+ "ControlType",
"is",
"Group"
],
[
"property",
- "localize control type",
+ "LocalizedControlType",
"is",
"article"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/button_haspopup_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/button_haspopup_unspecified-manual.html
index b03efadce13..5dd9371203c 100644
--- a/tests/wpt/web-platform-tests/wai-aria/button_haspopup_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/button_haspopup_unspecified-manual.html
@@ -99,10 +99,10 @@
"Button"
],
[
- "Control Pattern",
- "ExpandCollapse",
- "exists",
- "false"
+ "property",
+ "controlPatterns",
+ "doesNotContain",
+ "ExpandCollapse"
]
]
},
diff --git a/tests/wpt/web-platform-tests/wai-aria/button_roledescription_empty-manual.html b/tests/wpt/web-platform-tests/wai-aria/button_roledescription_empty-manual.html
index 0de1df2566c..5695dff804e 100644
--- a/tests/wpt/web-platform-tests/wai-aria/button_roledescription_empty-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/button_roledescription_empty-manual.html
@@ -70,13 +70,13 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Button"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"Button"
]
diff --git a/tests/wpt/web-platform-tests/wai-aria/button_roledescription_valid-manual.html b/tests/wpt/web-platform-tests/wai-aria/button_roledescription_valid-manual.html
index a3ffbc08f92..34cbc9ed8ae 100644
--- a/tests/wpt/web-platform-tests/wai-aria/button_roledescription_valid-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/button_roledescription_valid-manual.html
@@ -70,13 +70,13 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Button"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"SassyButton"
]
diff --git a/tests/wpt/web-platform-tests/wai-aria/button_roledescription_whitespace_only-manual.html b/tests/wpt/web-platform-tests/wai-aria/button_roledescription_whitespace_only-manual.html
index 8edd5b99acd..a213ed3b403 100644
--- a/tests/wpt/web-platform-tests/wai-aria/button_roledescription_whitespace_only-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/button_roledescription_whitespace_only-manual.html
@@ -70,13 +70,13 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Button"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"Button"
]
diff --git a/tests/wpt/web-platform-tests/wai-aria/cell-manual.html b/tests/wpt/web-platform-tests/wai-aria/cell-manual.html
index f7ea0688562..fad0e8804ce 100644
--- a/tests/wpt/web-platform-tests/wai-aria/cell-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/cell-manual.html
@@ -161,9 +161,9 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
- "TableItem"
+ "DataItem"
],
[
"property",
diff --git a/tests/wpt/web-platform-tests/wai-aria/cell_aria-colspan_2_on_div-manual.html b/tests/wpt/web-platform-tests/wai-aria/cell_aria-colspan_2_on_div-manual.html
index 88168fc8651..a9b83ff49f4 100644
--- a/tests/wpt/web-platform-tests/wai-aria/cell_aria-colspan_2_on_div-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/cell_aria-colspan_2_on_div-manual.html
@@ -82,9 +82,9 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
- "TableItem"
+ "DataItem"
],
[
"property",
diff --git a/tests/wpt/web-platform-tests/wai-aria/cell_aria-colspan_2_on_td_html_colspan_3-manual.html b/tests/wpt/web-platform-tests/wai-aria/cell_aria-colspan_2_on_td_html_colspan_3-manual.html
index 38b7c4c5869..c225ab39369 100644
--- a/tests/wpt/web-platform-tests/wai-aria/cell_aria-colspan_2_on_td_html_colspan_3-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/cell_aria-colspan_2_on_td_html_colspan_3-manual.html
@@ -76,9 +76,9 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
- "TableItem"
+ "DataItem"
],
[
"property",
diff --git a/tests/wpt/web-platform-tests/wai-aria/cell_aria-colspan_2_on_td_html_colspan_3_with_headers_and_border-manual.html b/tests/wpt/web-platform-tests/wai-aria/cell_aria-colspan_2_on_td_html_colspan_3_with_headers_and_border-manual.html
index b859a1d2010..5730d157f52 100644
--- a/tests/wpt/web-platform-tests/wai-aria/cell_aria-colspan_2_on_td_html_colspan_3_with_headers_and_border-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/cell_aria-colspan_2_on_td_html_colspan_3_with_headers_and_border-manual.html
@@ -76,9 +76,9 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
- "TableItem"
+ "DataItem"
],
[
"property",
diff --git a/tests/wpt/web-platform-tests/wai-aria/cell_aria-colspan_2_on_td_html_colspan_3_with_three_actual_columns-manual.html b/tests/wpt/web-platform-tests/wai-aria/cell_aria-colspan_2_on_td_html_colspan_3_with_three_actual_columns-manual.html
index 76a7f2967e4..b2a1901da85 100644
--- a/tests/wpt/web-platform-tests/wai-aria/cell_aria-colspan_2_on_td_html_colspan_3_with_three_actual_columns-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/cell_aria-colspan_2_on_td_html_colspan_3_with_three_actual_columns-manual.html
@@ -70,9 +70,9 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
- "TableItem"
+ "DataItem"
],
[
"property",
diff --git a/tests/wpt/web-platform-tests/wai-aria/cell_aria-colspan_2_on_td_with_html_colspan_not_specified-manual.html b/tests/wpt/web-platform-tests/wai-aria/cell_aria-colspan_2_on_td_with_html_colspan_not_specified-manual.html
index 182eefb0df3..980f5008bb1 100644
--- a/tests/wpt/web-platform-tests/wai-aria/cell_aria-colspan_2_on_td_with_html_colspan_not_specified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/cell_aria-colspan_2_on_td_with_html_colspan_not_specified-manual.html
@@ -82,9 +82,9 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
- "TableItem"
+ "DataItem"
],
[
"property",
diff --git a/tests/wpt/web-platform-tests/wai-aria/cell_aria-rowspan_2_on_div-manual.html b/tests/wpt/web-platform-tests/wai-aria/cell_aria-rowspan_2_on_div-manual.html
index d32621b74c0..4abd0de0b29 100644
--- a/tests/wpt/web-platform-tests/wai-aria/cell_aria-rowspan_2_on_div-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/cell_aria-rowspan_2_on_div-manual.html
@@ -82,9 +82,9 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
- "TableItem"
+ "DataItem"
],
[
"property",
diff --git a/tests/wpt/web-platform-tests/wai-aria/cell_aria-rowspan_2_on_td_html_rowspan_3-manual.html b/tests/wpt/web-platform-tests/wai-aria/cell_aria-rowspan_2_on_td_html_rowspan_3-manual.html
index 949af2787f6..356911e7209 100644
--- a/tests/wpt/web-platform-tests/wai-aria/cell_aria-rowspan_2_on_td_html_rowspan_3-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/cell_aria-rowspan_2_on_td_html_rowspan_3-manual.html
@@ -76,9 +76,9 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
- "TableItem"
+ "DataItem"
],
[
"property",
diff --git a/tests/wpt/web-platform-tests/wai-aria/cell_aria-rowspan_2_on_td_html_rowspan_3_with_three_actual_rows-manual.html b/tests/wpt/web-platform-tests/wai-aria/cell_aria-rowspan_2_on_td_html_rowspan_3_with_three_actual_rows-manual.html
index a34f7a1bb3a..0fed9aedeed 100644
--- a/tests/wpt/web-platform-tests/wai-aria/cell_aria-rowspan_2_on_td_html_rowspan_3_with_three_actual_rows-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/cell_aria-rowspan_2_on_td_html_rowspan_3_with_three_actual_rows-manual.html
@@ -70,9 +70,9 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
- "TableItem"
+ "DataItem"
],
[
"property",
diff --git a/tests/wpt/web-platform-tests/wai-aria/cell_aria-rowspan_2_on_td_with_html_rowspan_not_specified-manual.html b/tests/wpt/web-platform-tests/wai-aria/cell_aria-rowspan_2_on_td_with_html_rowspan_not_specified-manual.html
index c257e787b67..e9c5bd712c8 100644
--- a/tests/wpt/web-platform-tests/wai-aria/cell_aria-rowspan_2_on_td_with_html_rowspan_not_specified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/cell_aria-rowspan_2_on_td_with_html_rowspan_not_specified-manual.html
@@ -82,9 +82,9 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
- "TableItem"
+ "DataItem"
],
[
"property",
diff --git a/tests/wpt/web-platform-tests/wai-aria/cell_colindex_4-manual.html b/tests/wpt/web-platform-tests/wai-aria/cell_colindex_4-manual.html
index 78769af1b54..0c3895af164 100644
--- a/tests/wpt/web-platform-tests/wai-aria/cell_colindex_4-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/cell_colindex_4-manual.html
@@ -82,9 +82,9 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
- "TableItem"
+ "DataItem"
],
[
"property",
diff --git a/tests/wpt/web-platform-tests/wai-aria/cell_rowindex_4-manual.html b/tests/wpt/web-platform-tests/wai-aria/cell_rowindex_4-manual.html
index b4ff29775a6..14a9247ff66 100644
--- a/tests/wpt/web-platform-tests/wai-aria/cell_rowindex_4-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/cell_rowindex_4-manual.html
@@ -76,9 +76,9 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
- "TableItem"
+ "DataItem"
],
[
"property",
diff --git a/tests/wpt/web-platform-tests/wai-aria/checkbox_readonly_false-manual.html b/tests/wpt/web-platform-tests/wai-aria/checkbox_readonly_false-manual.html
index 59e25a6136c..dcb1a8b1f6c 100644
--- a/tests/wpt/web-platform-tests/wai-aria/checkbox_readonly_false-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/checkbox_readonly_false-manual.html
@@ -88,7 +88,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Checkbox"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/checkbox_readonly_true-manual.html b/tests/wpt/web-platform-tests/wai-aria/checkbox_readonly_true-manual.html
index e73f898f202..6718fada7a5 100644
--- a/tests/wpt/web-platform-tests/wai-aria/checkbox_readonly_true-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/checkbox_readonly_true-manual.html
@@ -94,7 +94,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Checkbox"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/checkbox_readonly_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/checkbox_readonly_unspecified-manual.html
index 73a3b93fc24..f8de2099e3f 100644
--- a/tests/wpt/web-platform-tests/wai-aria/checkbox_readonly_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/checkbox_readonly_unspecified-manual.html
@@ -88,7 +88,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Checkbox"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-colspan_2_on_div-manual.html b/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-colspan_2_on_div-manual.html
index 7b151c52209..1797d47a91c 100644
--- a/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-colspan_2_on_div-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-colspan_2_on_div-manual.html
@@ -82,7 +82,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-colspan_2_on_th_html_colspan_3-manual.html b/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-colspan_2_on_th_html_colspan_3-manual.html
index 51824ee40d6..586ff2982d4 100644
--- a/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-colspan_2_on_th_html_colspan_3-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-colspan_2_on_th_html_colspan_3-manual.html
@@ -76,7 +76,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-colspan_2_on_th_html_colspan_3_with_three_actual_columns-manual.html b/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-colspan_2_on_th_html_colspan_3_with_three_actual_columns-manual.html
index a26daed405e..fa7bf0bed71 100644
--- a/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-colspan_2_on_th_html_colspan_3_with_three_actual_columns-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-colspan_2_on_th_html_colspan_3_with_three_actual_columns-manual.html
@@ -70,7 +70,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-colspan_2_on_th_with_html_colspan_not_specified-manual.html b/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-colspan_2_on_th_with_html_colspan_not_specified-manual.html
index 44d11c1d7e6..453ff966641 100644
--- a/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-colspan_2_on_th_with_html_colspan_not_specified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-colspan_2_on_th_with_html_colspan_not_specified-manual.html
@@ -82,7 +82,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-rowspan_2_on_div-manual.html b/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-rowspan_2_on_div-manual.html
index cae113bace4..e3431e42b88 100644
--- a/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-rowspan_2_on_div-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-rowspan_2_on_div-manual.html
@@ -82,7 +82,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-rowspan_2_on_th_html_rowspan_3-manual.html b/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-rowspan_2_on_th_html_rowspan_3-manual.html
index efff45ff766..e7dee718673 100644
--- a/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-rowspan_2_on_th_html_rowspan_3-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-rowspan_2_on_th_html_rowspan_3-manual.html
@@ -76,7 +76,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-rowspan_2_on_th_html_rowspan_3_with_three_actual_rows-manual.html b/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-rowspan_2_on_th_html_rowspan_3_with_three_actual_rows-manual.html
index 3d964edb036..25d827e85d4 100644
--- a/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-rowspan_2_on_th_html_rowspan_3_with_three_actual_rows-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-rowspan_2_on_th_html_rowspan_3_with_three_actual_rows-manual.html
@@ -70,7 +70,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-rowspan_2_on_th_with_html_rowspan_not_specified-manual.html b/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-rowspan_2_on_th_with_html_rowspan_not_specified-manual.html
index f2298d0cc04..a029e6b600d 100644
--- a/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-rowspan_2_on_th_with_html_rowspan_not_specified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/columnheader_aria-rowspan_2_on_th_with_html_rowspan_not_specified-manual.html
@@ -82,7 +82,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/columnheader_colindex_4-manual.html b/tests/wpt/web-platform-tests/wai-aria/columnheader_colindex_4-manual.html
index c48e5f168f4..d8d0587845f 100644
--- a/tests/wpt/web-platform-tests/wai-aria/columnheader_colindex_4-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/columnheader_colindex_4-manual.html
@@ -82,7 +82,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/columnheader_rowindex_4-manual.html b/tests/wpt/web-platform-tests/wai-aria/columnheader_rowindex_4-manual.html
index 1e45ca31e3d..665d344dc38 100644
--- a/tests/wpt/web-platform-tests/wai-aria/columnheader_rowindex_4-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/columnheader_rowindex_4-manual.html
@@ -76,7 +76,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
@@ -102,7 +102,7 @@
<p>This test examines the ARIA properties for columnheader rowindex 4.</p>
<div role="table">
<div role="row">
- <div id="test" role="columnheader" aria-rowindex ="4">test cell</div>
+ <div id="test" role="columnheader" aria-rowindex="4">test cell</div>
</div>
</div>
diff --git a/tests/wpt/web-platform-tests/wai-aria/columnheader_selected_false_not_automatically_propagated-manual.html b/tests/wpt/web-platform-tests/wai-aria/columnheader_selected_false_not_automatically_propagated-manual.html
index 4a905976a9a..92cfc2e753c 100644
--- a/tests/wpt/web-platform-tests/wai-aria/columnheader_selected_false_not_automatically_propagated-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/columnheader_selected_false_not_automatically_propagated-manual.html
@@ -86,7 +86,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"DataItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/columnheader_selected_true_not_automatically_propagated-manual.html b/tests/wpt/web-platform-tests/wai-aria/columnheader_selected_true_not_automatically_propagated-manual.html
index 8d000b17e0d..32ce45ca7a2 100644
--- a/tests/wpt/web-platform-tests/wai-aria/columnheader_selected_true_not_automatically_propagated-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/columnheader_selected_true_not_automatically_propagated-manual.html
@@ -86,7 +86,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"DataItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_dialog-manual.html b/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_dialog-manual.html
index 4a52872e950..4d985a34e44 100644
--- a/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_dialog-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_dialog-manual.html
@@ -118,7 +118,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Combobox"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_false-manual.html b/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_false-manual.html
index 5a6036ad7ec..5bfcb9fbecf 100644
--- a/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_false-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_false-manual.html
@@ -112,7 +112,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Combobox"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_grid-manual.html b/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_grid-manual.html
index a68ce448308..76ad36ee87a 100644
--- a/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_grid-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_grid-manual.html
@@ -112,7 +112,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Combobox"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_listbox-manual.html b/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_listbox-manual.html
index 4d97620623d..135459591fb 100644
--- a/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_listbox-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_listbox-manual.html
@@ -112,7 +112,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Combobox"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_menu-manual.html b/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_menu-manual.html
index 8be6b44892d..85faaf317b1 100644
--- a/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_menu-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_menu-manual.html
@@ -112,7 +112,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Combobox"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_tree-manual.html b/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_tree-manual.html
index 546e42658c8..ea2d91680b5 100644
--- a/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_tree-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_tree-manual.html
@@ -112,7 +112,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Combobox"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_true-manual.html b/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_true-manual.html
index 5f324041222..f087508a5c3 100644
--- a/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_true-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_true-manual.html
@@ -118,7 +118,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Combobox"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_unspecified-manual.html
index f2d3599d02d..a60e9a1ef02 100644
--- a/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/combobox_haspopup_unspecified-manual.html
@@ -118,7 +118,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Combobox"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/combobox_orientation_horizontal-manual.html b/tests/wpt/web-platform-tests/wai-aria/combobox_orientation_horizontal-manual.html
index 1d173cde0b0..3831f41d9d0 100644
--- a/tests/wpt/web-platform-tests/wai-aria/combobox_orientation_horizontal-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/combobox_orientation_horizontal-manual.html
@@ -88,7 +88,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Combobox"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/combobox_orientation_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/combobox_orientation_unspecified-manual.html
index a31cce50961..b37568df299 100644
--- a/tests/wpt/web-platform-tests/wai-aria/combobox_orientation_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/combobox_orientation_unspecified-manual.html
@@ -88,15 +88,21 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Combobox"
],
[
"property",
"IUIAutomationElement.Orientation",
- "is",
- "null"
+ "isNot",
+ "vertical"
+ ],
+ [
+ "property",
+ "IUIAutomationElement.Orientation",
+ "isNot",
+ "horizontal"
]
]
},
diff --git a/tests/wpt/web-platform-tests/wai-aria/combobox_orientation_vertical-manual.html b/tests/wpt/web-platform-tests/wai-aria/combobox_orientation_vertical-manual.html
index 40e131e7326..a1a0b83e268 100644
--- a/tests/wpt/web-platform-tests/wai-aria/combobox_orientation_vertical-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/combobox_orientation_vertical-manual.html
@@ -88,7 +88,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Combobox"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/combobox_readonly_false-manual.html b/tests/wpt/web-platform-tests/wai-aria/combobox_readonly_false-manual.html
index 476bf2f0e84..4a87a4cb896 100644
--- a/tests/wpt/web-platform-tests/wai-aria/combobox_readonly_false-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/combobox_readonly_false-manual.html
@@ -112,7 +112,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Combobox"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/combobox_readonly_true-manual.html b/tests/wpt/web-platform-tests/wai-aria/combobox_readonly_true-manual.html
index a7484763f36..6f2872adfa8 100644
--- a/tests/wpt/web-platform-tests/wai-aria/combobox_readonly_true-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/combobox_readonly_true-manual.html
@@ -118,7 +118,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Combobox"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/combobox_readonly_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/combobox_readonly_unspecified-manual.html
index 1ee51e58460..86926586cdb 100644
--- a/tests/wpt/web-platform-tests/wai-aria/combobox_readonly_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/combobox_readonly_unspecified-manual.html
@@ -112,7 +112,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Combobox"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/dialog_modal_false-manual.html b/tests/wpt/web-platform-tests/wai-aria/dialog_modal_false-manual.html
index 254dbe56c4b..d78f21f5db3 100644
--- a/tests/wpt/web-platform-tests/wai-aria/dialog_modal_false-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/dialog_modal_false-manual.html
@@ -76,7 +76,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Pane"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/dialog_modal_true-manual.html b/tests/wpt/web-platform-tests/wai-aria/dialog_modal_true-manual.html
index 2ce3fe6cd14..a58a88f2430 100644
--- a/tests/wpt/web-platform-tests/wai-aria/dialog_modal_true-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/dialog_modal_true-manual.html
@@ -56,7 +56,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Pane"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/dialog_modal_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/dialog_modal_unspecified-manual.html
index 80366a6914b..117969b16ee 100644
--- a/tests/wpt/web-platform-tests/wai-aria/dialog_modal_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/dialog_modal_unspecified-manual.html
@@ -76,7 +76,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Pane"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/div_element_without_role_roledescription_valid-manual.html b/tests/wpt/web-platform-tests/wai-aria/div_element_without_role_roledescription_valid-manual.html
index 091c0348978..7e9b9fc7515 100644
--- a/tests/wpt/web-platform-tests/wai-aria/div_element_without_role_roledescription_valid-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/div_element_without_role_roledescription_valid-manual.html
@@ -100,7 +100,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Group"
]
diff --git a/tests/wpt/web-platform-tests/wai-aria/errormessage_object_in_valid_state-manual.html b/tests/wpt/web-platform-tests/wai-aria/errormessage_object_in_valid_state-manual.html
index ccad458b4c6..5845479e556 100644
--- a/tests/wpt/web-platform-tests/wai-aria/errormessage_object_in_valid_state-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/errormessage_object_in_valid_state-manual.html
@@ -38,15 +38,15 @@
"property",
"relations",
"doesNotContain",
- "IA2_RELATION_ERROR_MESSAGE"
+ "IA2_RELATION_ERROR"
]
],
"UIA" : [
[
"property",
"IUIAutomationElement.ControllerFor",
- "exists",
- "false"
+ "is",
+ ""
]
]
},
diff --git a/tests/wpt/web-platform-tests/wai-aria/feed-manual.html b/tests/wpt/web-platform-tests/wai-aria/feed-manual.html
index ad9f1da823c..ddb684f4767 100644
--- a/tests/wpt/web-platform-tests/wai-aria/feed-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/feed-manual.html
@@ -70,13 +70,13 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Group"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"feed"
]
diff --git a/tests/wpt/web-platform-tests/wai-aria/figure-manual.html b/tests/wpt/web-platform-tests/wai-aria/figure-manual.html
index 511168685d5..619978ffad7 100644
--- a/tests/wpt/web-platform-tests/wai-aria/figure-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/figure-manual.html
@@ -70,13 +70,13 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Group"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"figure"
]
diff --git a/tests/wpt/web-platform-tests/wai-aria/grid_aria-readonly_false_automatically_propagated-manual.html b/tests/wpt/web-platform-tests/wai-aria/grid_aria-readonly_false_automatically_propagated-manual.html
index 3676a10c092..21663a7f010 100644
--- a/tests/wpt/web-platform-tests/wai-aria/grid_aria-readonly_false_automatically_propagated-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/grid_aria-readonly_false_automatically_propagated-manual.html
@@ -76,7 +76,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"DataItem"
],
@@ -145,7 +145,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
@@ -208,7 +208,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/grid_aria-readonly_true_automatically_propagated-manual.html b/tests/wpt/web-platform-tests/wai-aria/grid_aria-readonly_true_automatically_propagated-manual.html
index 0be4cb43175..722d367d994 100644
--- a/tests/wpt/web-platform-tests/wai-aria/grid_aria-readonly_true_automatically_propagated-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/grid_aria-readonly_true_automatically_propagated-manual.html
@@ -76,7 +76,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"DataItem"
],
@@ -84,7 +84,7 @@
"property",
"controlPatterns",
"contains",
- "selectionitem"
+ "SelectionItem"
],
[
"property",
@@ -145,7 +145,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
@@ -208,7 +208,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/grid_busy_false-manual.html b/tests/wpt/web-platform-tests/wai-aria/grid_busy_false-manual.html
index 1a9572ce800..68376ef95ed 100644
--- a/tests/wpt/web-platform-tests/wai-aria/grid_busy_false-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/grid_busy_false-manual.html
@@ -112,7 +112,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"DataGrid"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/grid_busy_true-manual.html b/tests/wpt/web-platform-tests/wai-aria/grid_busy_true-manual.html
index 37c79ad19d3..873f5730905 100644
--- a/tests/wpt/web-platform-tests/wai-aria/grid_busy_true-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/grid_busy_true-manual.html
@@ -106,7 +106,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"DataGrid"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/grid_busy_value_changes-manual.html b/tests/wpt/web-platform-tests/wai-aria/grid_busy_value_changes-manual.html
index 37529516f6d..ad65db939e7 100644
--- a/tests/wpt/web-platform-tests/wai-aria/grid_busy_value_changes-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/grid_busy_value_changes-manual.html
@@ -149,7 +149,7 @@
],
[
"property",
- "Control Type",
+ "ControlType",
"is",
"DataGrid"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/grid_colcount_8-manual.html b/tests/wpt/web-platform-tests/wai-aria/grid_colcount_8-manual.html
index 50641725909..624c1d21a79 100644
--- a/tests/wpt/web-platform-tests/wai-aria/grid_colcount_8-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/grid_colcount_8-manual.html
@@ -94,7 +94,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"DataGrid"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/grid_columnheader_readonly_false-manual.html b/tests/wpt/web-platform-tests/wai-aria/grid_columnheader_readonly_false-manual.html
index 6ff7fe3ab20..79f4c82e39f 100644
--- a/tests/wpt/web-platform-tests/wai-aria/grid_columnheader_readonly_false-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/grid_columnheader_readonly_false-manual.html
@@ -76,7 +76,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/grid_columnheader_readonly_true-manual.html b/tests/wpt/web-platform-tests/wai-aria/grid_columnheader_readonly_true-manual.html
index d90852a8bff..4ef4e7d45a9 100644
--- a/tests/wpt/web-platform-tests/wai-aria/grid_columnheader_readonly_true-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/grid_columnheader_readonly_true-manual.html
@@ -70,7 +70,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/grid_columnheader_readonly_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/grid_columnheader_readonly_unspecified-manual.html
index 35910c361ff..bf9c24ba362 100644
--- a/tests/wpt/web-platform-tests/wai-aria/grid_columnheader_readonly_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/grid_columnheader_readonly_unspecified-manual.html
@@ -62,7 +62,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/grid_columnheader_required_false-manual.html b/tests/wpt/web-platform-tests/wai-aria/grid_columnheader_required_false-manual.html
index 45a5002d237..f6736756c19 100644
--- a/tests/wpt/web-platform-tests/wai-aria/grid_columnheader_required_false-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/grid_columnheader_required_false-manual.html
@@ -70,7 +70,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/grid_columnheader_required_true-manual.html b/tests/wpt/web-platform-tests/wai-aria/grid_columnheader_required_true-manual.html
index 41c936f443c..c810369cf66 100644
--- a/tests/wpt/web-platform-tests/wai-aria/grid_columnheader_required_true-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/grid_columnheader_required_true-manual.html
@@ -70,7 +70,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/grid_columnheader_required_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/grid_columnheader_required_unspecified-manual.html
index feeef96e38a..c9d83d2358b 100644
--- a/tests/wpt/web-platform-tests/wai-aria/grid_columnheader_required_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/grid_columnheader_required_unspecified-manual.html
@@ -70,7 +70,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/grid_rowcount_3-manual.html b/tests/wpt/web-platform-tests/wai-aria/grid_rowcount_3-manual.html
index 6a4b1408df3..ed92788e57d 100644
--- a/tests/wpt/web-platform-tests/wai-aria/grid_rowcount_3-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/grid_rowcount_3-manual.html
@@ -94,7 +94,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"DataGrid"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/grid_rowheader_readonly_false-manual.html b/tests/wpt/web-platform-tests/wai-aria/grid_rowheader_readonly_false-manual.html
index d7e923f7cc0..a099315b404 100644
--- a/tests/wpt/web-platform-tests/wai-aria/grid_rowheader_readonly_false-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/grid_rowheader_readonly_false-manual.html
@@ -62,7 +62,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/grid_rowheader_readonly_true-manual.html b/tests/wpt/web-platform-tests/wai-aria/grid_rowheader_readonly_true-manual.html
index 62351e008bc..67b1004b168 100644
--- a/tests/wpt/web-platform-tests/wai-aria/grid_rowheader_readonly_true-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/grid_rowheader_readonly_true-manual.html
@@ -62,7 +62,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/grid_rowheader_readonly_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/grid_rowheader_readonly_unspecified-manual.html
index 18152526b05..694e65699e9 100644
--- a/tests/wpt/web-platform-tests/wai-aria/grid_rowheader_readonly_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/grid_rowheader_readonly_unspecified-manual.html
@@ -62,7 +62,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/grid_rowheader_required_false-manual.html b/tests/wpt/web-platform-tests/wai-aria/grid_rowheader_required_false-manual.html
index 92aab07bbb4..ffd30ccdd70 100644
--- a/tests/wpt/web-platform-tests/wai-aria/grid_rowheader_required_false-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/grid_rowheader_required_false-manual.html
@@ -70,7 +70,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/grid_rowheader_required_true-manual.html b/tests/wpt/web-platform-tests/wai-aria/grid_rowheader_required_true-manual.html
index 69df488c8ec..e9b732485e0 100644
--- a/tests/wpt/web-platform-tests/wai-aria/grid_rowheader_required_true-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/grid_rowheader_required_true-manual.html
@@ -70,7 +70,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/grid_rowheader_required_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/grid_rowheader_required_unspecified-manual.html
index e70bd6ac3d1..52d92a6b667 100644
--- a/tests/wpt/web-platform-tests/wai-aria/grid_rowheader_required_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/grid_rowheader_required_unspecified-manual.html
@@ -70,7 +70,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/gridcell_aria-colspan_2_on_div-manual.html b/tests/wpt/web-platform-tests/wai-aria/gridcell_aria-colspan_2_on_div-manual.html
index 9ef3f2856ed..47b13a5c142 100644
--- a/tests/wpt/web-platform-tests/wai-aria/gridcell_aria-colspan_2_on_div-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/gridcell_aria-colspan_2_on_div-manual.html
@@ -82,7 +82,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"DataItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/gridcell_aria-rowspan_2_on_div-manual.html b/tests/wpt/web-platform-tests/wai-aria/gridcell_aria-rowspan_2_on_div-manual.html
index ffb187df2c2..2fc132331ac 100644
--- a/tests/wpt/web-platform-tests/wai-aria/gridcell_aria-rowspan_2_on_div-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/gridcell_aria-rowspan_2_on_div-manual.html
@@ -82,7 +82,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"DataItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/gridcell_colindex_4-manual.html b/tests/wpt/web-platform-tests/wai-aria/gridcell_colindex_4-manual.html
index d90bee37e6d..a3662ed8cdc 100644
--- a/tests/wpt/web-platform-tests/wai-aria/gridcell_colindex_4-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/gridcell_colindex_4-manual.html
@@ -82,7 +82,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"DataItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/gridcell_rowindex_4-manual.html b/tests/wpt/web-platform-tests/wai-aria/gridcell_rowindex_4-manual.html
index 478fc14111e..5fcae9a5fd1 100644
--- a/tests/wpt/web-platform-tests/wai-aria/gridcell_rowindex_4-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/gridcell_rowindex_4-manual.html
@@ -76,7 +76,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"DataItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/group_hidden_undefined_element_not_rendered-manual.html b/tests/wpt/web-platform-tests/wai-aria/group_hidden_undefined_element_not_rendered-manual.html
index 0f3ea8a42d0..8f2404b20af 100644
--- a/tests/wpt/web-platform-tests/wai-aria/group_hidden_undefined_element_not_rendered-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/group_hidden_undefined_element_not_rendered-manual.html
@@ -21,7 +21,7 @@
[
"property",
"accessible",
- "exists",
+ "is",
"false"
]
],
@@ -29,7 +29,7 @@
[
"property",
"accessible",
- "exists",
+ "is",
"false"
]
],
@@ -37,7 +37,7 @@
[
"property",
"accessible",
- "exists",
+ "is",
"false"
]
],
@@ -45,7 +45,7 @@
[
"property",
"accessible",
- "exists",
+ "is",
"false"
]
],
@@ -53,7 +53,7 @@
[
"property",
"accessible",
- "exists",
+ "is",
"false"
]
]
diff --git a/tests/wpt/web-platform-tests/wai-aria/group_hidden_undefined_element_rendered-manual.html b/tests/wpt/web-platform-tests/wai-aria/group_hidden_undefined_element_rendered-manual.html
index 8f8baf849d7..0097832a3b7 100644
--- a/tests/wpt/web-platform-tests/wai-aria/group_hidden_undefined_element_rendered-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/group_hidden_undefined_element_rendered-manual.html
@@ -82,7 +82,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Group"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/heading_level_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/heading_level_unspecified-manual.html
index 69962b702eb..2bf64185191 100644
--- a/tests/wpt/web-platform-tests/wai-aria/heading_level_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/heading_level_unspecified-manual.html
@@ -80,15 +80,15 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Text"
],
[
"property",
- "StyleId_Heading2",
+ "StyleId_Heading",
"is",
- "present"
+ "2"
],
[
"property",
diff --git a/tests/wpt/web-platform-tests/wai-aria/keyshortcuts_multiple_shortcuts-manual.html b/tests/wpt/web-platform-tests/wai-aria/keyshortcuts_multiple_shortcuts-manual.html
index f28e9d32f17..67e04b07e91 100644
--- a/tests/wpt/web-platform-tests/wai-aria/keyshortcuts_multiple_shortcuts-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/keyshortcuts_multiple_shortcuts-manual.html
@@ -48,7 +48,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Button"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/keyshortcuts_one_shortcut-manual.html b/tests/wpt/web-platform-tests/wai-aria/keyshortcuts_one_shortcut-manual.html
index aecb17e820d..6cf5c71250d 100644
--- a/tests/wpt/web-platform-tests/wai-aria/keyshortcuts_one_shortcut-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/keyshortcuts_one_shortcut-manual.html
@@ -48,7 +48,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Button"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/listbox_busy_false-manual.html b/tests/wpt/web-platform-tests/wai-aria/listbox_busy_false-manual.html
index 59e3ad6ca75..06258ae4055 100644
--- a/tests/wpt/web-platform-tests/wai-aria/listbox_busy_false-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/listbox_busy_false-manual.html
@@ -86,7 +86,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"List"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/listbox_busy_true-manual.html b/tests/wpt/web-platform-tests/wai-aria/listbox_busy_true-manual.html
index 5a618aa1fd9..b8604dc9960 100644
--- a/tests/wpt/web-platform-tests/wai-aria/listbox_busy_true-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/listbox_busy_true-manual.html
@@ -74,7 +74,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"List"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/listbox_orientation_horizontal-manual.html b/tests/wpt/web-platform-tests/wai-aria/listbox_orientation_horizontal-manual.html
index 8d75c69ba53..e496a357cc6 100644
--- a/tests/wpt/web-platform-tests/wai-aria/listbox_orientation_horizontal-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/listbox_orientation_horizontal-manual.html
@@ -94,7 +94,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"List"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/listbox_orientation_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/listbox_orientation_unspecified-manual.html
index 36276271c45..d39db919b94 100644
--- a/tests/wpt/web-platform-tests/wai-aria/listbox_orientation_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/listbox_orientation_unspecified-manual.html
@@ -94,7 +94,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"List"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/listbox_orientation_vertical-manual.html b/tests/wpt/web-platform-tests/wai-aria/listbox_orientation_vertical-manual.html
index ba8b77bbe8c..5f6431ff306 100644
--- a/tests/wpt/web-platform-tests/wai-aria/listbox_orientation_vertical-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/listbox_orientation_vertical-manual.html
@@ -94,7 +94,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"List"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/listbox_readonly_false-manual.html b/tests/wpt/web-platform-tests/wai-aria/listbox_readonly_false-manual.html
index 4733d641a4e..0f7e2b678ce 100644
--- a/tests/wpt/web-platform-tests/wai-aria/listbox_readonly_false-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/listbox_readonly_false-manual.html
@@ -88,7 +88,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"List"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/listbox_readonly_true-manual.html b/tests/wpt/web-platform-tests/wai-aria/listbox_readonly_true-manual.html
index 3a9f7940ed9..39771bf3a12 100644
--- a/tests/wpt/web-platform-tests/wai-aria/listbox_readonly_true-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/listbox_readonly_true-manual.html
@@ -94,7 +94,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"List"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/listbox_readonly_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/listbox_readonly_unspecified-manual.html
index 15ed93fe827..c1bb93d8bca 100644
--- a/tests/wpt/web-platform-tests/wai-aria/listbox_readonly_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/listbox_readonly_unspecified-manual.html
@@ -88,7 +88,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"List"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/listitem_setsize_-1-manual.html b/tests/wpt/web-platform-tests/wai-aria/listitem_setsize_-1-manual.html
index 48cd2d08dff..376692eeb8b 100644
--- a/tests/wpt/web-platform-tests/wai-aria/listitem_setsize_-1-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/listitem_setsize_-1-manual.html
@@ -94,7 +94,7 @@
"UIA" : [
[
"property",
- "control type",
+ "ControlType",
"is",
"ListItem"
],
@@ -108,7 +108,7 @@
"property",
"controlPatterns",
"contains",
- "selectionitem"
+ "SelectionItem"
]
]
},
diff --git a/tests/wpt/web-platform-tests/wai-aria/menu_orientation_horizontal-manual.html b/tests/wpt/web-platform-tests/wai-aria/menu_orientation_horizontal-manual.html
index d7a00c9173c..df2f22e3af4 100644
--- a/tests/wpt/web-platform-tests/wai-aria/menu_orientation_horizontal-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/menu_orientation_horizontal-manual.html
@@ -88,7 +88,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Menu"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/menu_orientation_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/menu_orientation_unspecified-manual.html
index f0a0266a9a9..b47451bab39 100644
--- a/tests/wpt/web-platform-tests/wai-aria/menu_orientation_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/menu_orientation_unspecified-manual.html
@@ -88,7 +88,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Menu"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/menu_orientation_vertical-manual.html b/tests/wpt/web-platform-tests/wai-aria/menu_orientation_vertical-manual.html
index 530918a7c83..c1958d4a6be 100644
--- a/tests/wpt/web-platform-tests/wai-aria/menu_orientation_vertical-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/menu_orientation_vertical-manual.html
@@ -88,7 +88,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Menu"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/menubar_busy_false-manual.html b/tests/wpt/web-platform-tests/wai-aria/menubar_busy_false-manual.html
index e86c24ab99e..62060a2fa96 100644
--- a/tests/wpt/web-platform-tests/wai-aria/menubar_busy_false-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/menubar_busy_false-manual.html
@@ -88,7 +88,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"MenuBar"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/menubar_busy_true-manual.html b/tests/wpt/web-platform-tests/wai-aria/menubar_busy_true-manual.html
index 6665c95ffac..e8c6b649f42 100644
--- a/tests/wpt/web-platform-tests/wai-aria/menubar_busy_true-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/menubar_busy_true-manual.html
@@ -88,7 +88,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"MenuBar"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/menubar_orientation_horizontal-manual.html b/tests/wpt/web-platform-tests/wai-aria/menubar_orientation_horizontal-manual.html
index e480aa33224..66207b91afb 100644
--- a/tests/wpt/web-platform-tests/wai-aria/menubar_orientation_horizontal-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/menubar_orientation_horizontal-manual.html
@@ -88,7 +88,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"MenuBar"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/menubar_orientation_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/menubar_orientation_unspecified-manual.html
index dbb162317c8..e94dd0c0948 100644
--- a/tests/wpt/web-platform-tests/wai-aria/menubar_orientation_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/menubar_orientation_unspecified-manual.html
@@ -88,7 +88,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"MenuBar"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/menubar_orientation_vertical-manual.html b/tests/wpt/web-platform-tests/wai-aria/menubar_orientation_vertical-manual.html
index a258dd8392f..dd7434e5949 100644
--- a/tests/wpt/web-platform-tests/wai-aria/menubar_orientation_vertical-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/menubar_orientation_vertical-manual.html
@@ -76,7 +76,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"MenuBar"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/menuitem_posinset_and_setsize-manual.html b/tests/wpt/web-platform-tests/wai-aria/menuitem_posinset_and_setsize-manual.html
index a8bfb63e383..411086b7f34 100644
--- a/tests/wpt/web-platform-tests/wai-aria/menuitem_posinset_and_setsize-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/menuitem_posinset_and_setsize-manual.html
@@ -106,8 +106,8 @@
"UIA" : [
[
"property",
- "Control Type",
- "isNot",
+ "ControlType",
+ "is",
"MenuItem"
],
[
diff --git a/tests/wpt/web-platform-tests/wai-aria/menuitemcheckbox_posinset_and_setsize-manual.html b/tests/wpt/web-platform-tests/wai-aria/menuitemcheckbox_posinset_and_setsize-manual.html
index ec0c7a3969e..9368e984879 100644
--- a/tests/wpt/web-platform-tests/wai-aria/menuitemcheckbox_posinset_and_setsize-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/menuitemcheckbox_posinset_and_setsize-manual.html
@@ -136,8 +136,8 @@
"UIA" : [
[
"property",
- "Control Type",
- "isNot",
+ "ControlType",
+ "is",
"MenuItem"
],
[
diff --git a/tests/wpt/web-platform-tests/wai-aria/menuitemcheckbox_readonly_false-manual.html b/tests/wpt/web-platform-tests/wai-aria/menuitemcheckbox_readonly_false-manual.html
index bee4e4f6b65..767d01e7944 100644
--- a/tests/wpt/web-platform-tests/wai-aria/menuitemcheckbox_readonly_false-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/menuitemcheckbox_readonly_false-manual.html
@@ -88,7 +88,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"MenuItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/menuitemcheckbox_readonly_true-manual.html b/tests/wpt/web-platform-tests/wai-aria/menuitemcheckbox_readonly_true-manual.html
index e30b1bda6e9..40fc07899a5 100644
--- a/tests/wpt/web-platform-tests/wai-aria/menuitemcheckbox_readonly_true-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/menuitemcheckbox_readonly_true-manual.html
@@ -88,7 +88,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"MenuItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/menuitemcheckbox_readonly_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/menuitemcheckbox_readonly_unspecified-manual.html
index b9997ab8e4e..388d89ea404 100644
--- a/tests/wpt/web-platform-tests/wai-aria/menuitemcheckbox_readonly_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/menuitemcheckbox_readonly_unspecified-manual.html
@@ -82,7 +82,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"MenuItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/menuitemradio_posinset_and_setsize-manual.html b/tests/wpt/web-platform-tests/wai-aria/menuitemradio_posinset_and_setsize-manual.html
index 2d32a57e209..9f6489ebf08 100644
--- a/tests/wpt/web-platform-tests/wai-aria/menuitemradio_posinset_and_setsize-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/menuitemradio_posinset_and_setsize-manual.html
@@ -136,8 +136,8 @@
"UIA" : [
[
"property",
- "Control Type",
- "isNot",
+ "ControlType",
+ "is",
"MenuItem"
],
[
diff --git a/tests/wpt/web-platform-tests/wai-aria/menuitemradio_readonly_false-manual.html b/tests/wpt/web-platform-tests/wai-aria/menuitemradio_readonly_false-manual.html
index d7077250843..3771b5d6287 100644
--- a/tests/wpt/web-platform-tests/wai-aria/menuitemradio_readonly_false-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/menuitemradio_readonly_false-manual.html
@@ -82,7 +82,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"MenuItem"
],
@@ -96,7 +96,7 @@
"property",
"controlPatterns",
"contains",
- "SelectItem"
+ "SelectionItem"
],
[
"property",
diff --git a/tests/wpt/web-platform-tests/wai-aria/menuitemradio_readonly_true-manual.html b/tests/wpt/web-platform-tests/wai-aria/menuitemradio_readonly_true-manual.html
index 990b4fa5d55..fd92109744d 100644
--- a/tests/wpt/web-platform-tests/wai-aria/menuitemradio_readonly_true-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/menuitemradio_readonly_true-manual.html
@@ -94,7 +94,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"MenuItem"
],
@@ -108,7 +108,7 @@
"property",
"controlPatterns",
"contains",
- "SelectItem"
+ "SelectionItem"
],
[
"property",
diff --git a/tests/wpt/web-platform-tests/wai-aria/menuitemradio_readonly_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/menuitemradio_readonly_unspecified-manual.html
index ccad591be8c..e39165367cb 100644
--- a/tests/wpt/web-platform-tests/wai-aria/menuitemradio_readonly_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/menuitemradio_readonly_unspecified-manual.html
@@ -82,7 +82,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"MenuItem"
],
@@ -96,7 +96,7 @@
"property",
"controlPatterns",
"contains",
- "SelectItem"
+ "SelectionItem"
],
[
"property",
diff --git a/tests/wpt/web-platform-tests/wai-aria/none-manual.html b/tests/wpt/web-platform-tests/wai-aria/none-manual.html
index a286a592a51..f8c38af3458 100644
--- a/tests/wpt/web-platform-tests/wai-aria/none-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/none-manual.html
@@ -21,7 +21,7 @@
[
"property",
"accessible",
- "exists",
+ "is",
"false"
]
],
@@ -29,7 +29,7 @@
[
"property",
"accessible",
- "exists",
+ "is",
"false"
]
],
@@ -37,7 +37,7 @@
[
"property",
"accessible",
- "exists",
+ "is",
"false"
]
],
@@ -45,7 +45,7 @@
[
"property",
"accessible",
- "exists",
+ "is",
"false"
]
],
@@ -53,7 +53,7 @@
[
"property",
"accessible",
- "exists",
+ "is",
"false"
]
]
diff --git a/tests/wpt/web-platform-tests/wai-aria/option_selected_false-manual.html b/tests/wpt/web-platform-tests/wai-aria/option_selected_false-manual.html
index e77d50c3cf3..c7091203dcc 100644
--- a/tests/wpt/web-platform-tests/wai-aria/option_selected_false-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/option_selected_false-manual.html
@@ -86,7 +86,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"ListItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/option_selected_true-manual.html b/tests/wpt/web-platform-tests/wai-aria/option_selected_true-manual.html
index b9839f87207..3769bcce22d 100644
--- a/tests/wpt/web-platform-tests/wai-aria/option_selected_true-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/option_selected_true-manual.html
@@ -86,7 +86,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"ListItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/option_selected_undefined-manual.html b/tests/wpt/web-platform-tests/wai-aria/option_selected_undefined-manual.html
index f13ccfa3871..536ac9b7c18 100644
--- a/tests/wpt/web-platform-tests/wai-aria/option_selected_undefined-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/option_selected_undefined-manual.html
@@ -86,7 +86,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"ListItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/radiogroup_orientation_horizontal-manual.html b/tests/wpt/web-platform-tests/wai-aria/radiogroup_orientation_horizontal-manual.html
index 82b91ec6bde..695f1c60d75 100644
--- a/tests/wpt/web-platform-tests/wai-aria/radiogroup_orientation_horizontal-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/radiogroup_orientation_horizontal-manual.html
@@ -88,7 +88,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"List"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/radiogroup_orientation_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/radiogroup_orientation_unspecified-manual.html
index 97e5e5a5eb6..6cc09ea816a 100644
--- a/tests/wpt/web-platform-tests/wai-aria/radiogroup_orientation_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/radiogroup_orientation_unspecified-manual.html
@@ -94,7 +94,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"List"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/radiogroup_orientation_vertical-manual.html b/tests/wpt/web-platform-tests/wai-aria/radiogroup_orientation_vertical-manual.html
index 4442f25364a..ef3090bba06 100644
--- a/tests/wpt/web-platform-tests/wai-aria/radiogroup_orientation_vertical-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/radiogroup_orientation_vertical-manual.html
@@ -76,7 +76,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"List"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/radiogroup_readonly_false-manual.html b/tests/wpt/web-platform-tests/wai-aria/radiogroup_readonly_false-manual.html
index e99875afa51..cb829c4b027 100644
--- a/tests/wpt/web-platform-tests/wai-aria/radiogroup_readonly_false-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/radiogroup_readonly_false-manual.html
@@ -82,7 +82,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"List"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/radiogroup_readonly_true-manual.html b/tests/wpt/web-platform-tests/wai-aria/radiogroup_readonly_true-manual.html
index 9955b9d3902..279da4edb1a 100644
--- a/tests/wpt/web-platform-tests/wai-aria/radiogroup_readonly_true-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/radiogroup_readonly_true-manual.html
@@ -82,7 +82,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"List"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/radiogroup_readonly_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/radiogroup_readonly_unspecified-manual.html
index d822301bdb0..6b3596bcf98 100644
--- a/tests/wpt/web-platform-tests/wai-aria/radiogroup_readonly_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/radiogroup_readonly_unspecified-manual.html
@@ -82,7 +82,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"List"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/row_colindex_4-manual.html b/tests/wpt/web-platform-tests/wai-aria/row_colindex_4-manual.html
index 060217f7559..1e483bf6c51 100644
--- a/tests/wpt/web-platform-tests/wai-aria/row_colindex_4-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/row_colindex_4-manual.html
@@ -64,7 +64,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"DataItem"
],
@@ -109,6 +109,20 @@
"is",
"4"
]
+ ],
+ "UIA" : [
+ [
+ "property",
+ "ControlType",
+ "is",
+ "DataItem"
+ ],
+ [
+ "property",
+ "Column",
+ "is",
+ "3"
+ ]
]
},
"title" : "step 2",
diff --git a/tests/wpt/web-platform-tests/wai-aria/row_rowindex_4-manual.html b/tests/wpt/web-platform-tests/wai-aria/row_rowindex_4-manual.html
index e391dffa7c7..98c9e15ece1 100644
--- a/tests/wpt/web-platform-tests/wai-aria/row_rowindex_4-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/row_rowindex_4-manual.html
@@ -64,7 +64,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"DataItem"
],
@@ -109,6 +109,20 @@
"is",
"4"
]
+ ],
+ "UIA" : [
+ [
+ "property",
+ "ControlType",
+ "is",
+ "DataItem"
+ ],
+ [
+ "property",
+ "Row",
+ "is",
+ "3"
+ ]
]
},
"title" : "step 2",
diff --git a/tests/wpt/web-platform-tests/wai-aria/rowheader_aria-colspan_2_on_div-manual.html b/tests/wpt/web-platform-tests/wai-aria/rowheader_aria-colspan_2_on_div-manual.html
index 883ebe02ee8..294e5052c4b 100644
--- a/tests/wpt/web-platform-tests/wai-aria/rowheader_aria-colspan_2_on_div-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/rowheader_aria-colspan_2_on_div-manual.html
@@ -82,7 +82,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/rowheader_aria-rowspan_2_on_div-manual.html b/tests/wpt/web-platform-tests/wai-aria/rowheader_aria-rowspan_2_on_div-manual.html
index e5c331fd819..361526fad48 100644
--- a/tests/wpt/web-platform-tests/wai-aria/rowheader_aria-rowspan_2_on_div-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/rowheader_aria-rowspan_2_on_div-manual.html
@@ -82,7 +82,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/rowheader_colindex_4-manual.html b/tests/wpt/web-platform-tests/wai-aria/rowheader_colindex_4-manual.html
index a48cd2f45b2..e3fa1156a8f 100644
--- a/tests/wpt/web-platform-tests/wai-aria/rowheader_colindex_4-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/rowheader_colindex_4-manual.html
@@ -82,7 +82,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/rowheader_rowindex_4-manual.html b/tests/wpt/web-platform-tests/wai-aria/rowheader_rowindex_4-manual.html
index a146fc9bed6..8591196c812 100644
--- a/tests/wpt/web-platform-tests/wai-aria/rowheader_rowindex_4-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/rowheader_rowindex_4-manual.html
@@ -76,7 +76,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"HeaderItem"
],
@@ -102,7 +102,7 @@
<p>This test examines the ARIA properties for rowheader rowindex 4.</p>
<div role="table">
<div role="row">
- <div id="test" role="rowheader" aria-rowindex ="4">test cell</div>
+ <div id="test" role="rowheader" aria-rowindex="4">test cell</div>
</div>
</div>
diff --git a/tests/wpt/web-platform-tests/wai-aria/rowheader_selected_false_not_automatically_propagated-manual.html b/tests/wpt/web-platform-tests/wai-aria/rowheader_selected_false_not_automatically_propagated-manual.html
index 948b11e2c04..cc6eb5df2aa 100644
--- a/tests/wpt/web-platform-tests/wai-aria/rowheader_selected_false_not_automatically_propagated-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/rowheader_selected_false_not_automatically_propagated-manual.html
@@ -86,7 +86,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"DataItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/rowheader_selected_true_not_automatically_propagated-manual.html b/tests/wpt/web-platform-tests/wai-aria/rowheader_selected_true_not_automatically_propagated-manual.html
index 26aab4e6004..fe34db97d40 100644
--- a/tests/wpt/web-platform-tests/wai-aria/rowheader_selected_true_not_automatically_propagated-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/rowheader_selected_true_not_automatically_propagated-manual.html
@@ -86,7 +86,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"DataItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/scrollbar_all_values_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/scrollbar_all_values_unspecified-manual.html
index 00d93148ee3..c5849c57425 100644
--- a/tests/wpt/web-platform-tests/wai-aria/scrollbar_all_values_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/scrollbar_all_values_unspecified-manual.html
@@ -130,7 +130,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"scrollbar"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/scrollbar_only_valuenow_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/scrollbar_only_valuenow_unspecified-manual.html
index 8efb7edbf8d..34c59cedd47 100644
--- a/tests/wpt/web-platform-tests/wai-aria/scrollbar_only_valuenow_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/scrollbar_only_valuenow_unspecified-manual.html
@@ -130,7 +130,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"ScrollBar"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/scrollbar_orientation_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/scrollbar_orientation_unspecified-manual.html
index 890a46498c8..0fb9ae8c7c5 100644
--- a/tests/wpt/web-platform-tests/wai-aria/scrollbar_orientation_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/scrollbar_orientation_unspecified-manual.html
@@ -94,7 +94,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"ScrollBar"
],
@@ -108,7 +108,7 @@
"property",
"interfaces",
"contains",
- "Range control pattern"
+ "RangeValue"
]
]
},
diff --git a/tests/wpt/web-platform-tests/wai-aria/searchbox-manual.html b/tests/wpt/web-platform-tests/wai-aria/searchbox-manual.html
index 016f77a4d02..f3e154836a0 100644
--- a/tests/wpt/web-platform-tests/wai-aria/searchbox-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/searchbox-manual.html
@@ -88,13 +88,13 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Edit"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"search box"
]
diff --git a/tests/wpt/web-platform-tests/wai-aria/searchbox_activedescendant-manual.html b/tests/wpt/web-platform-tests/wai-aria/searchbox_activedescendant-manual.html
index 3976c265d42..1e2ad175228 100644
--- a/tests/wpt/web-platform-tests/wai-aria/searchbox_activedescendant-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/searchbox_activedescendant-manual.html
@@ -112,13 +112,13 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Edit"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"search box"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/searchbox_activedescendant_value_changes-manual.html b/tests/wpt/web-platform-tests/wai-aria/searchbox_activedescendant_value_changes-manual.html
index 9f2507cd8be..a1ceab64179 100644
--- a/tests/wpt/web-platform-tests/wai-aria/searchbox_activedescendant_value_changes-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/searchbox_activedescendant_value_changes-manual.html
@@ -105,7 +105,7 @@
"event",
"type",
"is",
- "IA2_EVENT_ACTIVE_DESCENDANT_CHANGED"
+ "EVENT_OBJECT_FOCUS"
]
],
"MSAA" : [
@@ -131,13 +131,13 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Edit"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"search box"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/searchbox_autocomplete_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/searchbox_autocomplete_unspecified-manual.html
index 8b137490ce9..3513eeb0fe4 100644
--- a/tests/wpt/web-platform-tests/wai-aria/searchbox_autocomplete_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/searchbox_autocomplete_unspecified-manual.html
@@ -102,7 +102,7 @@
"property",
"autocomplete",
"is",
- "none"
+ ""
]
]
},
diff --git a/tests/wpt/web-platform-tests/wai-aria/searchbox_multiline_false-manual.html b/tests/wpt/web-platform-tests/wai-aria/searchbox_multiline_false-manual.html
index 6c0053a0eed..2413dd44051 100644
--- a/tests/wpt/web-platform-tests/wai-aria/searchbox_multiline_false-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/searchbox_multiline_false-manual.html
@@ -94,13 +94,13 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Edit"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"search box"
]
diff --git a/tests/wpt/web-platform-tests/wai-aria/searchbox_multiline_true-manual.html b/tests/wpt/web-platform-tests/wai-aria/searchbox_multiline_true-manual.html
index 311cbf5589c..4a3d65793f2 100644
--- a/tests/wpt/web-platform-tests/wai-aria/searchbox_multiline_true-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/searchbox_multiline_true-manual.html
@@ -100,21 +100,21 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Edit"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"search box"
],
[
"property",
- "AriaProperties",
- "contains",
- "multiline:true"
+ "AriaProperties.multiline",
+ "is",
+ "true"
]
]
},
diff --git a/tests/wpt/web-platform-tests/wai-aria/searchbox_multiline_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/searchbox_multiline_unspecified-manual.html
index 240698ff59c..8768b5bc34d 100644
--- a/tests/wpt/web-platform-tests/wai-aria/searchbox_multiline_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/searchbox_multiline_unspecified-manual.html
@@ -76,13 +76,13 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Edit"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"search box"
]
diff --git a/tests/wpt/web-platform-tests/wai-aria/searchbox_placeholder-manual.html b/tests/wpt/web-platform-tests/wai-aria/searchbox_placeholder-manual.html
index 086508f1651..4e9ddbae3bc 100644
--- a/tests/wpt/web-platform-tests/wai-aria/searchbox_placeholder-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/searchbox_placeholder-manual.html
@@ -100,13 +100,13 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Edit"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"search box"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/searchbox_readonly_false-manual.html b/tests/wpt/web-platform-tests/wai-aria/searchbox_readonly_false-manual.html
index 2c8d4aec546..a587eb5dfbd 100644
--- a/tests/wpt/web-platform-tests/wai-aria/searchbox_readonly_false-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/searchbox_readonly_false-manual.html
@@ -100,13 +100,13 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Edit"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"search box"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/searchbox_readonly_true-manual.html b/tests/wpt/web-platform-tests/wai-aria/searchbox_readonly_true-manual.html
index ba0f3886fce..83ff4ec535c 100644
--- a/tests/wpt/web-platform-tests/wai-aria/searchbox_readonly_true-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/searchbox_readonly_true-manual.html
@@ -100,13 +100,13 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Edit"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"search box"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/searchbox_readonly_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/searchbox_readonly_unspecified-manual.html
index c3f49a2505b..615785f2c16 100644
--- a/tests/wpt/web-platform-tests/wai-aria/searchbox_readonly_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/searchbox_readonly_unspecified-manual.html
@@ -100,13 +100,13 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Edit"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"search box"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/searchbox_required_false-manual.html b/tests/wpt/web-platform-tests/wai-aria/searchbox_required_false-manual.html
index 6d576771fc7..dc544dd2683 100644
--- a/tests/wpt/web-platform-tests/wai-aria/searchbox_required_false-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/searchbox_required_false-manual.html
@@ -88,13 +88,13 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Edit"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"search box"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/searchbox_required_true-manual.html b/tests/wpt/web-platform-tests/wai-aria/searchbox_required_true-manual.html
index 764fe33729d..a1dcb29a8c9 100644
--- a/tests/wpt/web-platform-tests/wai-aria/searchbox_required_true-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/searchbox_required_true-manual.html
@@ -88,13 +88,13 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Edit"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"search box"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/searchbox_required_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/searchbox_required_unspecified-manual.html
index 592e0e4898b..fb7c657bdac 100644
--- a/tests/wpt/web-platform-tests/wai-aria/searchbox_required_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/searchbox_required_unspecified-manual.html
@@ -88,13 +88,13 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Edit"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"search box"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/separator_focusable_all_values_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/separator_focusable_all_values_unspecified-manual.html
index 971f4548ca7..5f2d8bae893 100644
--- a/tests/wpt/web-platform-tests/wai-aria/separator_focusable_all_values_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/separator_focusable_all_values_unspecified-manual.html
@@ -130,7 +130,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Thumb"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/separator_focusable_only_valuenow_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/separator_focusable_only_valuenow_unspecified-manual.html
index abc35fe81a6..8c4c809ce8e 100644
--- a/tests/wpt/web-platform-tests/wai-aria/separator_focusable_only_valuenow_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/separator_focusable_only_valuenow_unspecified-manual.html
@@ -130,7 +130,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Thumb"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/separator_focusable_valuetext-manual.html b/tests/wpt/web-platform-tests/wai-aria/separator_focusable_valuetext-manual.html
index edbb7bd5a4b..ebfd2119a9c 100644
--- a/tests/wpt/web-platform-tests/wai-aria/separator_focusable_valuetext-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/separator_focusable_valuetext-manual.html
@@ -148,7 +148,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Thumb"
],
@@ -178,12 +178,6 @@
],
[
"property",
- "controlPatterns",
- "contains",
- "Value"
- ],
- [
- "property",
"Value.Value",
"is",
"Bonaire"
diff --git a/tests/wpt/web-platform-tests/wai-aria/separator_orientation_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/separator_orientation_unspecified-manual.html
index 3b496a87ce9..43dfe6dbe20 100644
--- a/tests/wpt/web-platform-tests/wai-aria/separator_orientation_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/separator_orientation_unspecified-manual.html
@@ -88,7 +88,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Separator"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/separator_unfocusable_all_values_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/separator_unfocusable_all_values_unspecified-manual.html
index 8ab8e96b027..5dbe67d8df3 100644
--- a/tests/wpt/web-platform-tests/wai-aria/separator_unfocusable_all_values_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/separator_unfocusable_all_values_unspecified-manual.html
@@ -62,7 +62,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Separator"
]
diff --git a/tests/wpt/web-platform-tests/wai-aria/separator_unfocusable_valuetext-manual.html b/tests/wpt/web-platform-tests/wai-aria/separator_unfocusable_valuetext-manual.html
index 71527bf7996..4e8fd405634 100644
--- a/tests/wpt/web-platform-tests/wai-aria/separator_unfocusable_valuetext-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/separator_unfocusable_valuetext-manual.html
@@ -82,7 +82,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Separator"
],
@@ -90,7 +90,7 @@
"property",
"controlPatterns",
"doesNotContain",
- "Value"
+ "RangeValue"
]
]
},
diff --git a/tests/wpt/web-platform-tests/wai-aria/slider_all_values_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/slider_all_values_unspecified-manual.html
index 2b3e4405c54..2a72d5db582 100644
--- a/tests/wpt/web-platform-tests/wai-aria/slider_all_values_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/slider_all_values_unspecified-manual.html
@@ -130,7 +130,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Slider"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/slider_only_valuenow_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/slider_only_valuenow_unspecified-manual.html
index 9421dfcc90c..4f80a39fe80 100644
--- a/tests/wpt/web-platform-tests/wai-aria/slider_only_valuenow_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/slider_only_valuenow_unspecified-manual.html
@@ -130,7 +130,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Slider"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/slider_orientation_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/slider_orientation_unspecified-manual.html
index d882fc42889..50e87c8b3f1 100644
--- a/tests/wpt/web-platform-tests/wai-aria/slider_orientation_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/slider_orientation_unspecified-manual.html
@@ -94,7 +94,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Slider"
],
@@ -108,7 +108,7 @@
"property",
"interfaces",
"contains",
- "Range control pattern"
+ "RangeValue"
]
]
},
diff --git a/tests/wpt/web-platform-tests/wai-aria/slider_readonly_false-manual.html b/tests/wpt/web-platform-tests/wai-aria/slider_readonly_false-manual.html
index 666cb12e979..13c36efeec8 100644
--- a/tests/wpt/web-platform-tests/wai-aria/slider_readonly_false-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/slider_readonly_false-manual.html
@@ -94,7 +94,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Slider"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/slider_readonly_true-manual.html b/tests/wpt/web-platform-tests/wai-aria/slider_readonly_true-manual.html
index f33e07e6045..5793bf20d88 100644
--- a/tests/wpt/web-platform-tests/wai-aria/slider_readonly_true-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/slider_readonly_true-manual.html
@@ -94,7 +94,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Slider"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/slider_readonly_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/slider_readonly_unspecified-manual.html
index 86f7500ed95..dc5ce40c9d1 100644
--- a/tests/wpt/web-platform-tests/wai-aria/slider_readonly_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/slider_readonly_unspecified-manual.html
@@ -94,7 +94,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Slider"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/spinbutton_all_values_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/spinbutton_all_values_unspecified-manual.html
index eb7e2880f27..446f4534152 100644
--- a/tests/wpt/web-platform-tests/wai-aria/spinbutton_all_values_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/spinbutton_all_values_unspecified-manual.html
@@ -130,7 +130,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Spinner"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/spinbutton_only_aria-valuenow_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/spinbutton_only_aria-valuenow_unspecified-manual.html
index 8a9dc74090c..ae6948b7826 100644
--- a/tests/wpt/web-platform-tests/wai-aria/spinbutton_only_aria-valuenow_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/spinbutton_only_aria-valuenow_unspecified-manual.html
@@ -130,7 +130,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Spinner"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/spinbutton_readonly_false-manual.html b/tests/wpt/web-platform-tests/wai-aria/spinbutton_readonly_false-manual.html
index bda4b583e46..94a9d44eec1 100644
--- a/tests/wpt/web-platform-tests/wai-aria/spinbutton_readonly_false-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/spinbutton_readonly_false-manual.html
@@ -94,7 +94,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Spinner"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/spinbutton_readonly_true-manual.html b/tests/wpt/web-platform-tests/wai-aria/spinbutton_readonly_true-manual.html
index 6234e50d1f4..7652a5695d6 100644
--- a/tests/wpt/web-platform-tests/wai-aria/spinbutton_readonly_true-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/spinbutton_readonly_true-manual.html
@@ -94,7 +94,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Spinner"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/spinbutton_readonly_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/spinbutton_readonly_unspecified-manual.html
index c96f2e00d38..8a3f2d76033 100644
--- a/tests/wpt/web-platform-tests/wai-aria/spinbutton_readonly_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/spinbutton_readonly_unspecified-manual.html
@@ -94,7 +94,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Spinner"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/switch_checked_false-manual.html b/tests/wpt/web-platform-tests/wai-aria/switch_checked_false-manual.html
index f499550bdcd..b5cf84fa9f1 100644
--- a/tests/wpt/web-platform-tests/wai-aria/switch_checked_false-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/switch_checked_false-manual.html
@@ -86,13 +86,13 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Button"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"toggleswitch"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/switch_checked_mixed-manual.html b/tests/wpt/web-platform-tests/wai-aria/switch_checked_mixed-manual.html
index e6320e0cad8..f9e45cf4246 100644
--- a/tests/wpt/web-platform-tests/wai-aria/switch_checked_mixed-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/switch_checked_mixed-manual.html
@@ -92,13 +92,13 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Button"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"toggleswitch"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/switch_checked_true-manual.html b/tests/wpt/web-platform-tests/wai-aria/switch_checked_true-manual.html
index 8ae8579a3bf..fbe80aebfce 100644
--- a/tests/wpt/web-platform-tests/wai-aria/switch_checked_true-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/switch_checked_true-manual.html
@@ -94,7 +94,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Button"
],
@@ -106,7 +106,7 @@
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"toggleswitch"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/switch_checked_undefined-manual.html b/tests/wpt/web-platform-tests/wai-aria/switch_checked_undefined-manual.html
index 7ae70c6765a..94297a47f65 100644
--- a/tests/wpt/web-platform-tests/wai-aria/switch_checked_undefined-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/switch_checked_undefined-manual.html
@@ -86,13 +86,13 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Button"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"toggleswitch"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/switch_checked_value_changes-manual.html b/tests/wpt/web-platform-tests/wai-aria/switch_checked_value_changes-manual.html
index 699f332a858..11ebcb3951e 100644
--- a/tests/wpt/web-platform-tests/wai-aria/switch_checked_value_changes-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/switch_checked_value_changes-manual.html
@@ -119,13 +119,13 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Button"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"toggleswitch"
],
@@ -139,7 +139,7 @@
"event",
"type",
"is",
- "Toggle.ToggleStateProperty"
+ "TogglePattern.ToggleStateProperty"
]
]
},
diff --git a/tests/wpt/web-platform-tests/wai-aria/switch_readonly_false-manual.html b/tests/wpt/web-platform-tests/wai-aria/switch_readonly_false-manual.html
index 4afbff1808f..fdb095d1bb4 100644
--- a/tests/wpt/web-platform-tests/wai-aria/switch_readonly_false-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/switch_readonly_false-manual.html
@@ -80,13 +80,13 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Button"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"toggleswitch"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/switch_readonly_true-manual.html b/tests/wpt/web-platform-tests/wai-aria/switch_readonly_true-manual.html
index eab0bf59ff9..2a6f6fbc86c 100644
--- a/tests/wpt/web-platform-tests/wai-aria/switch_readonly_true-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/switch_readonly_true-manual.html
@@ -80,13 +80,13 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Button"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"toggleswitch"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/switch_readonly_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/switch_readonly_unspecified-manual.html
index f3e1f6b97ae..7a253657377 100644
--- a/tests/wpt/web-platform-tests/wai-aria/switch_readonly_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/switch_readonly_unspecified-manual.html
@@ -80,13 +80,13 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Button"
],
[
"property",
- "Localized Control Type",
+ "LocalizedControlType",
"is",
"toggleswitch"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/tab_posinset_and_setsize-manual.html b/tests/wpt/web-platform-tests/wai-aria/tab_posinset_and_setsize-manual.html
index 6f3d796ab1b..f00d5985652 100644
--- a/tests/wpt/web-platform-tests/wai-aria/tab_posinset_and_setsize-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/tab_posinset_and_setsize-manual.html
@@ -142,8 +142,8 @@
"UIA" : [
[
"property",
- "Control Type",
- "isNot",
+ "ControlType",
+ "is",
"TabItem"
],
[
diff --git a/tests/wpt/web-platform-tests/wai-aria/table_colcount_-1-manual.html b/tests/wpt/web-platform-tests/wai-aria/table_colcount_-1-manual.html
index 751642659db..8a6e46f028b 100644
--- a/tests/wpt/web-platform-tests/wai-aria/table_colcount_-1-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/table_colcount_-1-manual.html
@@ -82,7 +82,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Table"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/table_colcount_8-manual.html b/tests/wpt/web-platform-tests/wai-aria/table_colcount_8-manual.html
index daaa03f4334..0c25f18c1e9 100644
--- a/tests/wpt/web-platform-tests/wai-aria/table_colcount_8-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/table_colcount_8-manual.html
@@ -76,7 +76,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Table"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/table_rowcount_-1-manual.html b/tests/wpt/web-platform-tests/wai-aria/table_rowcount_-1-manual.html
index 8ca67174275..fbc809be09f 100644
--- a/tests/wpt/web-platform-tests/wai-aria/table_rowcount_-1-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/table_rowcount_-1-manual.html
@@ -88,7 +88,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Table"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/table_rowcount_3-manual.html b/tests/wpt/web-platform-tests/wai-aria/table_rowcount_3-manual.html
index bb685bdbd0a..81a3a3c16b1 100644
--- a/tests/wpt/web-platform-tests/wai-aria/table_rowcount_3-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/table_rowcount_3-manual.html
@@ -82,7 +82,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Table"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/tablist_orientation_horizontal-manual.html b/tests/wpt/web-platform-tests/wai-aria/tablist_orientation_horizontal-manual.html
index a01acf18108..2d7062aade0 100644
--- a/tests/wpt/web-platform-tests/wai-aria/tablist_orientation_horizontal-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/tablist_orientation_horizontal-manual.html
@@ -100,7 +100,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Tab"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/tablist_orientation_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/tablist_orientation_unspecified-manual.html
index f4524c291b5..497751d7d01 100644
--- a/tests/wpt/web-platform-tests/wai-aria/tablist_orientation_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/tablist_orientation_unspecified-manual.html
@@ -94,7 +94,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Tab"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/tablist_orientation_vertical-manual.html b/tests/wpt/web-platform-tests/wai-aria/tablist_orientation_vertical-manual.html
index 9cf69cafa24..18c196b5638 100644
--- a/tests/wpt/web-platform-tests/wai-aria/tablist_orientation_vertical-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/tablist_orientation_vertical-manual.html
@@ -88,7 +88,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Tab"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/term_role-manual.html b/tests/wpt/web-platform-tests/wai-aria/term_role-manual.html
index d583765095e..76941b51ab4 100644
--- a/tests/wpt/web-platform-tests/wai-aria/term_role-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/term_role-manual.html
@@ -74,9 +74,9 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
- "ListItem"
+ "Text"
]
]
},
diff --git a/tests/wpt/web-platform-tests/wai-aria/textbox_placeholder-manual.html b/tests/wpt/web-platform-tests/wai-aria/textbox_placeholder-manual.html
index 6c234a13947..5c40558325d 100644
--- a/tests/wpt/web-platform-tests/wai-aria/textbox_placeholder-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/textbox_placeholder-manual.html
@@ -100,7 +100,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Edit"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/toolbar_orientation_horizontal-manual.html b/tests/wpt/web-platform-tests/wai-aria/toolbar_orientation_horizontal-manual.html
index e2327e7e127..356c9833b0d 100644
--- a/tests/wpt/web-platform-tests/wai-aria/toolbar_orientation_horizontal-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/toolbar_orientation_horizontal-manual.html
@@ -88,7 +88,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"ToolBar"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/toolbar_orientation_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/toolbar_orientation_unspecified-manual.html
index a08e45a4261..bd2c399bbc9 100644
--- a/tests/wpt/web-platform-tests/wai-aria/toolbar_orientation_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/toolbar_orientation_unspecified-manual.html
@@ -88,7 +88,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"ToolBar"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/toolbar_orientation_vertical-manual.html b/tests/wpt/web-platform-tests/wai-aria/toolbar_orientation_vertical-manual.html
index 92a39cd353b..b0d85f9f8c7 100644
--- a/tests/wpt/web-platform-tests/wai-aria/toolbar_orientation_vertical-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/toolbar_orientation_vertical-manual.html
@@ -88,7 +88,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"ToolBar"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/tree_orientation_horizontal-manual.html b/tests/wpt/web-platform-tests/wai-aria/tree_orientation_horizontal-manual.html
index 74788212475..88ba1e705e4 100644
--- a/tests/wpt/web-platform-tests/wai-aria/tree_orientation_horizontal-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/tree_orientation_horizontal-manual.html
@@ -94,7 +94,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Tree"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/tree_orientation_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/tree_orientation_unspecified-manual.html
index ada952dadd0..b8c25667144 100644
--- a/tests/wpt/web-platform-tests/wai-aria/tree_orientation_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/tree_orientation_unspecified-manual.html
@@ -94,7 +94,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Tree"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/tree_orientation_vertical-manual.html b/tests/wpt/web-platform-tests/wai-aria/tree_orientation_vertical-manual.html
index 799413b20ce..b9e88b034df 100644
--- a/tests/wpt/web-platform-tests/wai-aria/tree_orientation_vertical-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/tree_orientation_vertical-manual.html
@@ -94,7 +94,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"Tree"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/treegrid_colcount_8-manual.html b/tests/wpt/web-platform-tests/wai-aria/treegrid_colcount_8-manual.html
index b44672ca724..381f39c2f44 100644
--- a/tests/wpt/web-platform-tests/wai-aria/treegrid_colcount_8-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/treegrid_colcount_8-manual.html
@@ -82,7 +82,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"DataGrid"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/treegrid_orientation_horizontal-manual.html b/tests/wpt/web-platform-tests/wai-aria/treegrid_orientation_horizontal-manual.html
index 180aebd26bc..41b49e7a2f5 100644
--- a/tests/wpt/web-platform-tests/wai-aria/treegrid_orientation_horizontal-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/treegrid_orientation_horizontal-manual.html
@@ -100,7 +100,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"DataGrid"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/treegrid_orientation_unspecified-manual.html b/tests/wpt/web-platform-tests/wai-aria/treegrid_orientation_unspecified-manual.html
index 4bc2a05f76e..1eabb26aabf 100644
--- a/tests/wpt/web-platform-tests/wai-aria/treegrid_orientation_unspecified-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/treegrid_orientation_unspecified-manual.html
@@ -112,7 +112,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"DataGrid"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/treegrid_orientation_vertical-manual.html b/tests/wpt/web-platform-tests/wai-aria/treegrid_orientation_vertical-manual.html
index 3bed156a7f3..92c0e2897d6 100644
--- a/tests/wpt/web-platform-tests/wai-aria/treegrid_orientation_vertical-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/treegrid_orientation_vertical-manual.html
@@ -100,7 +100,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"DataGrid"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/treegrid_rowcount_3-manual.html b/tests/wpt/web-platform-tests/wai-aria/treegrid_rowcount_3-manual.html
index 15b63f309d2..86942708dcf 100644
--- a/tests/wpt/web-platform-tests/wai-aria/treegrid_rowcount_3-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/treegrid_rowcount_3-manual.html
@@ -82,7 +82,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"DataGrid"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/treeitem_selected_false-manual.html b/tests/wpt/web-platform-tests/wai-aria/treeitem_selected_false-manual.html
index f401a522504..0e2c1f95de8 100644
--- a/tests/wpt/web-platform-tests/wai-aria/treeitem_selected_false-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/treeitem_selected_false-manual.html
@@ -86,7 +86,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"TreeItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/treeitem_selected_true-manual.html b/tests/wpt/web-platform-tests/wai-aria/treeitem_selected_true-manual.html
index 80cf62783aa..21775643e76 100644
--- a/tests/wpt/web-platform-tests/wai-aria/treeitem_selected_true-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/treeitem_selected_true-manual.html
@@ -86,7 +86,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"TreeItem"
],
diff --git a/tests/wpt/web-platform-tests/wai-aria/treeitem_selected_undefined-manual.html b/tests/wpt/web-platform-tests/wai-aria/treeitem_selected_undefined-manual.html
index a7ca892b6f4..f9880872214 100644
--- a/tests/wpt/web-platform-tests/wai-aria/treeitem_selected_undefined-manual.html
+++ b/tests/wpt/web-platform-tests/wai-aria/treeitem_selected_undefined-manual.html
@@ -86,7 +86,7 @@
"UIA" : [
[
"property",
- "Control Type",
+ "ControlType",
"is",
"TreeItem"
],
diff --git a/tests/wpt/web-platform-tests/wake-lock/wakelock-api.https.html b/tests/wpt/web-platform-tests/wake-lock/wakelock-api.https.html
index bce4e149346..7ec4fc2827a 100644
--- a/tests/wpt/web-platform-tests/wake-lock/wakelock-api.https.html
+++ b/tests/wpt/web-platform-tests/wake-lock/wakelock-api.https.html
@@ -2,17 +2,19 @@
<meta charset="utf-8">
<title>Wake Lock API Test</title>
<link rel="help" href="https://w3c.github.io/wake-lock/">
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
<script>
promise_test(async t => {
assert_true("getWakeLock" in navigator, "Wake Lock API is present");
const wakeLock = await navigator.getWakeLock("screen");
+ const request = wakeLock.createRequest();
assert_true(wakeLock instanceof WakeLock, "wakeLock is a WakeLock");
assert_true(wakeLock.type instanceof WakeLockType, "wakeLock.type is a WakeLockType");
assert_equals(typeof wakeLock.active, "boolean", "the type of wakeLock.active is boolean");
+ assert_true(request instanceof WakeLockRequest, "request is a WakeLockRequest");
}, "Test that the Wake Lock API is correct");
</script>
diff --git a/tests/wpt/web-platform-tests/wake-lock/wakelock-applicability-manual.https.html b/tests/wpt/web-platform-tests/wake-lock/wakelock-applicability-manual.https.html
new file mode 100644
index 00000000000..5dbd27818dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/wake-lock/wakelock-applicability-manual.https.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>wake lock applicability test</title>
+<link rel="help" href="https://w3c.github.io/wake-lock/#dfn-the-wake-lock-is-applicable">
+<meta name="flags" content="interact">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<p>
+ Lock and turn off the screen, then turn on and unlock the screen.
+</p>
+<p>
+ Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.
+</p>
+<script>
+
+setup({ explicit_timeout: true });
+
+promise_test(async t => {
+ const wakeLock = await navigator.getWakeLock("screen");
+ const request = wakeLock.createRequest();
+ assert_true(wakeLock.active, "the active is true when wake lock is acquired");
+ const eventWatcher = new EventWatcher(t, document, "visibilitychange")
+
+ //lock screen to fire 'visibilitychange'
+ await eventWatcher.wait_for("visibilitychange");
+ assert_true(document.hidden, "document is hidden when screen is locked");
+ assert_false(wakeLock.active, "the screen wake lock is not active when screen is switched off");
+
+ //unlock screen to fire 'visibilitychange'
+ await eventWatcher.wait_for("visibilitychange");
+ assert_false(document.hidden, "document is visiable when screen is unlocked");
+ assert_true(wakeLock.active, "the screen wake lock is active when screen is switched on again");
+ request.cancel();
+}, "The screen wake lock isn't applicable after the screen is manually swiched off"
+ + " by the user until it is switched on again.");
+
+
+promise_test(async t => {
+ const wakeLock = await navigator.getWakeLock("system");
+ const request = wakeLock.createRequest();
+ assert_true(wakeLock.active, "the active is true when wake lock is acquired");
+ const eventWatcher = new EventWatcher(t, document, "visibilitychange")
+
+ //lock screen to fire 'visibilitychange'
+ await eventWatcher.wait_for("visibilitychange");
+ assert_true(document.hidden, "document is hidden when screen is locked");
+ assert_true(wakeLock.active, "the system wake lock is still active when screen is switched off");
+ request.cancel();
+}, "Manually switching off the screen will not affect the applicability of the system wake lock.");
+
+</script>
diff --git a/tests/wpt/web-platform-tests/wake-lock/wakelock-cancel-twice.https.html b/tests/wpt/web-platform-tests/wake-lock/wakelock-cancel-twice.https.html
new file mode 100644
index 00000000000..68e8a195816
--- /dev/null
+++ b/tests/wpt/web-platform-tests/wake-lock/wakelock-cancel-twice.https.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>no exception is thrown when invoking cancel() twice</title>
+<link rel="help" href="https://w3c.github.io/wake-lock/#dom-wakelockrequest-cancel">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+promise_test(async t => {
+ const wakeLock = await navigator.getWakeLock("screen");
+ const request = wakeLock.createRequest();
+ assert_true(wakeLock.active, "the activate is true when wake lock is acquired");
+ request.cancel();
+ assert_false(wakeLock.active, "the activate is false when wake lock is released");
+ //If the cancel() method has already been invoked on this object,
+ //abort these steps, no error fired
+ request.cancel();
+}, "no exception is thrown when invoking cancel() twice");
+
+</script>
diff --git a/tests/wpt/web-platform-tests/wake-lock/wakelock-disabled-by-feature-policy.https.sub.html b/tests/wpt/web-platform-tests/wake-lock/wakelock-disabled-by-feature-policy.https.sub.html
index 440e79394bc..75064767cee 100644
--- a/tests/wpt/web-platform-tests/wake-lock/wakelock-disabled-by-feature-policy.https.sub.html
+++ b/tests/wpt/web-platform-tests/wake-lock/wakelock-disabled-by-feature-policy.https.sub.html
@@ -1,8 +1,8 @@
<!DOCTYPE html>
<body>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/feature-policy/resources/featurepolicy.js></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
<script>
"use strict";
diff --git a/tests/wpt/web-platform-tests/wake-lock/wakelock-document-hidden.https.html b/tests/wpt/web-platform-tests/wake-lock/wakelock-document-hidden.https.html
new file mode 100644
index 00000000000..6bb406a1c2e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/wake-lock/wakelock-document-hidden.https.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>screen wake lock will not be actived in hidden document</title>
+<link rel="help" href="https://w3c.github.io/wake-lock/#dfn-requesting-the-wake-lock">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+promise_test(async t => {
+ const wakeLock = await navigator.getWakeLock("screen");
+ const request = wakeLock.createRequest();
+ assert_true(wakeLock.active, "the active is true when wake lock is acquired");
+ const eventWatcher = new EventWatcher(t, document, "visibilitychange");
+ const win = window.open("about:blank", "_blank");
+
+ await eventWatcher.wait_for("visibilitychange");
+ assert_true(document.hidden, "document is hidden when new window is opened");
+ assert_false(wakeLock.active, "the active is false when document is hidden");
+ win.close();
+
+ await eventWatcher.wait_for("visibilitychange");
+ assert_false(document.hidden, "document is visiable when new window is closed");
+ assert_true(wakeLock.active, "the active is true when document regains visibility");
+ request.cancel();
+}, "Test that screen wake lock will not be actived in hidden document");
+
+</script>
diff --git a/tests/wpt/web-platform-tests/wake-lock/wakelock-enabled-by-feature-policy-attribute-redirect-on-load.https.sub.html b/tests/wpt/web-platform-tests/wake-lock/wakelock-enabled-by-feature-policy-attribute-redirect-on-load.https.sub.html
index 24502f1ebc7..74875937f6e 100644
--- a/tests/wpt/web-platform-tests/wake-lock/wakelock-enabled-by-feature-policy-attribute-redirect-on-load.https.sub.html
+++ b/tests/wpt/web-platform-tests/wake-lock/wakelock-enabled-by-feature-policy-attribute-redirect-on-load.https.sub.html
@@ -1,8 +1,8 @@
<!DOCTYPE html>
<body>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/feature-policy/resources/featurepolicy.js></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
<script>
"use strict";
diff --git a/tests/wpt/web-platform-tests/wake-lock/wakelock-enabled-by-feature-policy-attribute.https.sub.html b/tests/wpt/web-platform-tests/wake-lock/wakelock-enabled-by-feature-policy-attribute.https.sub.html
index 36cfaca93a5..185f5ad11b1 100644
--- a/tests/wpt/web-platform-tests/wake-lock/wakelock-enabled-by-feature-policy-attribute.https.sub.html
+++ b/tests/wpt/web-platform-tests/wake-lock/wakelock-enabled-by-feature-policy-attribute.https.sub.html
@@ -1,8 +1,8 @@
<!DOCTYPE html>
<body>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/feature-policy/resources/featurepolicy.js></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
<script>
"use strict";
diff --git a/tests/wpt/web-platform-tests/wake-lock/wakelock-enabled-by-feature-policy.https.sub.html b/tests/wpt/web-platform-tests/wake-lock/wakelock-enabled-by-feature-policy.https.sub.html
index 83c63fb6086..eb49be5d44b 100644
--- a/tests/wpt/web-platform-tests/wake-lock/wakelock-enabled-by-feature-policy.https.sub.html
+++ b/tests/wpt/web-platform-tests/wake-lock/wakelock-enabled-by-feature-policy.https.sub.html
@@ -1,8 +1,8 @@
<!DOCTYPE html>
<body>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/feature-policy/resources/featurepolicy.js></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
<script>
"use strict";
diff --git a/tests/wpt/web-platform-tests/wake-lock/wakelock-enabled-on-self-origin-by-feature-policy.https.sub.html b/tests/wpt/web-platform-tests/wake-lock/wakelock-enabled-on-self-origin-by-feature-policy.https.sub.html
index 646d8680337..dbd8ec99f81 100644
--- a/tests/wpt/web-platform-tests/wake-lock/wakelock-enabled-on-self-origin-by-feature-policy.https.sub.html
+++ b/tests/wpt/web-platform-tests/wake-lock/wakelock-enabled-on-self-origin-by-feature-policy.https.sub.html
@@ -1,8 +1,8 @@
<!DOCTYPE html>
<body>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/feature-policy/resources/featurepolicy.js></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/feature-policy/resources/featurepolicy.js"></script>
<script>
"use strict";
diff --git a/tests/wpt/web-platform-tests/wake-lock/wakelock-insecure-context.html b/tests/wpt/web-platform-tests/wake-lock/wakelock-insecure-context.html
new file mode 100644
index 00000000000..8d728f83e5d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/wake-lock/wakelock-insecure-context.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Wake Lock API is not exposed in an insecure context</title>
+<link rel="help" href="https://w3c.github.io/wake-lock/#wake-locks">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+test(t => {
+ assert_false("getWakeLock" in navigator, "'getWakeLock' must not be exposed");
+}, "Wake Lock API is not exposed in an insecure context");
+
+</script>
diff --git a/tests/wpt/web-platform-tests/wake-lock/wakelock-object-is-independent.https.html b/tests/wpt/web-platform-tests/wake-lock/wakelock-object-is-independent.https.html
deleted file mode 100644
index c7818307759..00000000000
--- a/tests/wpt/web-platform-tests/wake-lock/wakelock-object-is-independent.https.html
+++ /dev/null
@@ -1,85 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>WakeLock object is independent</title>
-<link rel="help" href="https://w3c.github.io/wake-lock/">
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-
-<body>
-<script id="iframe" type="text/plain">
-let iframeWakeLock, iframeRequest;
-window.onmessage = async message => {
- switch(message.data) {
- case "INIT":
- iframeWakeLock = await navigator.getWakeLock("screen");
- parent.postMessage(iframeWakeLock.active, "*");
- break;
- case "ACQUIRED":
- iframeRequest = iframeWakeLock.createRequest();
- parent.postMessage(iframeWakeLock.active, "*");
- break;
- case "RELEASED":
- iframeRequest.cancel();
- parent.postMessage(iframeWakeLock.active, "*");
- break;
- default:
- parent.postMessage("unknown operation", "*");
- }
-}
-</script>
-
-<script>
-function load_iframe() {
- return new Promise(resolve => {
- const iframe = document.createElement("iframe");
- iframe.onload = () => { resolve(iframe); };
- iframe.srcdoc = "<script>" +
- document.getElementById('iframe').textContent +
- "<\/script>";
- document.body.appendChild(iframe);
- });
-}
-
-function wait_for_message(iframe) {
- return new Promise(resolve => {
- self.addEventListener("message", function listener(e) {
- if (e.source === iframe.contentWindow) {
- resolve(e.data);
- self.removeEventListener("message", listener);
- }
- });
- });
-}
-
-promise_test(async t => {
- const wakeLock1 = await navigator.getWakeLock("screen");
- const wakeLock2 = await navigator.getWakeLock("screen");
- const iframe = await load_iframe();
-
- //when wakeLock1 is acquired, wakeLock2 and iframeWakeLock are still inactived
- iframe.contentWindow.postMessage("INIT", "*");
- let request1 = wakeLock1.createRequest();
- let isActive1 = await wait_for_message(iframe);
- assert_true(wakeLock1.active, "the active is true when wakeLock1 is acquired");
- assert_false(wakeLock2.active, "the active is false before wakeLock2 is acquired");
- assert_false(isActive1, "the active is false before iframeWakeLock is acquired");
-
- //when wakeLock2 and iframeWakeLock are acquired, release wakeLock1
- iframe.contentWindow.postMessage("ACQUIRED", "*");
- let isActive2 = await wait_for_message(iframe);
- request1.cancel();
- let request2 = wakeLock2.createRequest();
- assert_false(wakeLock1.active, "the active is false when wakeLock1 is released");
- assert_true(wakeLock2.active, "the active is true when wakeLock2 is acquired");
- assert_true(isActive2, "the active is true when iframeWakeLock is acquired");
-
- //release all WakeLock objects
- iframe.contentWindow.postMessage("RELEASED", "*");
- let isActive3 = await wait_for_message(iframe);
- request2.cancel();
- assert_false(wakeLock1.active, "the active is false when wakeLock1 is released");
- assert_false(wakeLock2.active, "the active is false when wakeLock2 is released");
- assert_false(isActive3, "the active is false when iframeWakeLock is released");
-}, "Test that the WakeLock object is independent.");
-</script>
-</body>
diff --git a/tests/wpt/web-platform-tests/wake-lock/wakelock-onactivechange.https.html b/tests/wpt/web-platform-tests/wake-lock/wakelock-onactivechange.https.html
index dc5c7ebea15..899b9b78d95 100644
--- a/tests/wpt/web-platform-tests/wake-lock/wakelock-onactivechange.https.html
+++ b/tests/wpt/web-platform-tests/wake-lock/wakelock-onactivechange.https.html
@@ -2,8 +2,8 @@
<meta charset="utf-8">
<title>Wake Lock 'onactivechange' Test</title>
<link rel="help" href="https://w3c.github.io/wake-lock/">
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
<script>
diff --git a/tests/wpt/web-platform-tests/wake-lock/wakelock-promise.https.html b/tests/wpt/web-platform-tests/wake-lock/wakelock-promise.https.html
new file mode 100644
index 00000000000..3d4c4868699
--- /dev/null
+++ b/tests/wpt/web-platform-tests/wake-lock/wakelock-promise.https.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>navigator.getWakeLock() for the same Document always return same WakeLock promise</title>
+<link rel="help" href="https://w3c.github.io/wake-lock/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+promise_test(async t => {
+ const wakeLock1 = await navigator.getWakeLock("screen");
+ const wakeLock2 = await navigator.getWakeLock("screen");
+ assert_equals(wakeLock1, wakeLock2);
+}, "navigator.getWakeLock() for the same Document always return same WakeLock promise");
+</script>
diff --git a/tests/wpt/web-platform-tests/wake-lock/wakelock-state-is-global.https.html b/tests/wpt/web-platform-tests/wake-lock/wakelock-state-is-global.https.html
new file mode 100644
index 00000000000..98cebe01c11
--- /dev/null
+++ b/tests/wpt/web-platform-tests/wake-lock/wakelock-state-is-global.https.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>wake lock state should be global</title>
+<link rel="help" href="https://w3c.github.io/wake-lock/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<body>
+<script id="iframe" type="text/plain">
+let iframeWakeLock, iframeRequest;
+window.onmessage = async message => {
+ switch(message.data) {
+ case "ACQUIRED":
+ iframeWakeLock = await navigator.getWakeLock("screen");
+ iframeRequest = iframeWakeLock.createRequest();
+ parent.postMessage(iframeWakeLock.active, "*");
+ break;
+ case "RELEASED":
+ iframeRequest.cancel();
+ parent.postMessage(iframeWakeLock.active, "*");
+ break;
+ default:
+ parent.postMessage("unknown operation", "*");
+ }
+}
+</script>
+
+<script>
+function load_iframe() {
+ return new Promise(resolve => {
+ const iframe = document.createElement("iframe");
+ iframe.onload = () => { resolve(iframe); };
+ iframe.srcdoc = "<script>" +
+ document.getElementById('iframe').textContent +
+ "<\/script>";
+ document.body.appendChild(iframe);
+ });
+}
+
+function wait_for_message(iframe) {
+ return new Promise(resolve => {
+ self.addEventListener("message", function listener(e) {
+ if (e.source === iframe.contentWindow) {
+ resolve(e.data);
+ self.removeEventListener("message", listener);
+ }
+ });
+ });
+}
+
+promise_test(async t => {
+ const wakeLock = await navigator.getWakeLock("screen");
+ const iframe = await load_iframe();
+ const eventWatcher = new EventWatcher(t, wakeLock, "activechange");
+
+ assert_false(wakeLock.active, "wakeLock is initially false");
+
+ //when iframe wake lock is acquired, parent wake lock should be actived
+ iframe.contentWindow.postMessage("ACQUIRED", "*");
+ const isActive1 = await wait_for_message(iframe);
+ await eventWatcher.wait_for("activechange");
+ assert_true(isActive1, "the iframe wake lock state is actived when iframe wake lock is acquired");
+ assert_true(wakeLock.active, "the wake lock state is actived when iframe wake lock is acquired");
+
+ //when iframe wake lock is released, parent wake lock should be inactived
+ iframe.contentWindow.postMessage("RELEASED", "*");
+ const isActive2 = await wait_for_message(iframe);
+ eventWatcher.wait_for("activechange");
+ assert_false(isActive2, "the iframe wake lock state is inactived when iframe wake lock is released");
+ assert_false(wakeLock.active, "the wake lock state is inactived when iframe wake lock is released");
+}, "Test that wake lock state should be global");
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/wake-lock/wakelock-type.https.html b/tests/wpt/web-platform-tests/wake-lock/wakelock-type.https.html
index 969e2f2b899..70aa129abcc 100644
--- a/tests/wpt/web-platform-tests/wake-lock/wakelock-type.https.html
+++ b/tests/wpt/web-platform-tests/wake-lock/wakelock-type.https.html
@@ -2,8 +2,8 @@
<meta charset="utf-8">
<title>WakeLockType Test</title>
<link rel="help" href="https://w3c.github.io/wake-lock/">
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
<script>
diff --git a/tests/wpt/web-platform-tests/wake-lock/wakelockrequest-is-independent.https.html b/tests/wpt/web-platform-tests/wake-lock/wakelockrequest-is-independent.https.html
new file mode 100644
index 00000000000..a113b004fe2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/wake-lock/wakelockrequest-is-independent.https.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>WakeLockRequest object is independent</title>
+<link rel="help" href="https://w3c.github.io/wake-lock/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+promise_test(async t => {
+ const wakeLock1 = await navigator.getWakeLock("screen");
+ const wakeLock2 = await navigator.getWakeLock("screen");
+ const request1 = wakeLock1.createRequest();
+ const request2 = wakeLock2.createRequest();
+ assert_not_equals(request1, request2);
+}, "Test that the WakeLockRequest object is independent.");
+</script>
diff --git a/tests/wpt/web-platform-tests/wasm/many-memories.window.js b/tests/wpt/web-platform-tests/wasm/many-memories.window.js
index 0613a008ac3..042e645fa70 100644
--- a/tests/wpt/web-platform-tests/wasm/many-memories.window.js
+++ b/tests/wpt/web-platform-tests/wasm/many-memories.window.js
@@ -3,11 +3,11 @@
// found in the LICENSE file.
// This test makes sure browsers behave reasonably when asked to allocate a
-// large number of WebAssembly.Memory objects at once.
+// larger number of WebAssembly.Memory objects at once.
test(function() {
let memories = [];
try {
- for (let i = 0; i < 600; i++) {
+ for (let i = 0; i < 20; i++) {
memories.push(new WebAssembly.Memory({initial: 1}));
}
} catch (e) {
diff --git a/tests/wpt/web-platform-tests/wasm/wasm_local_iframe_test.html b/tests/wpt/web-platform-tests/wasm/wasm_local_iframe_test.html
index 9ccebdc7539..0f4fbd0c719 100644
--- a/tests/wpt/web-platform-tests/wasm/wasm_local_iframe_test.html
+++ b/tests/wpt/web-platform-tests/wasm/wasm_local_iframe_test.html
@@ -2,16 +2,18 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/load_wasm.js"></script>
-<iframe src="resources/frame.html" id="iframe"></iframe>
<script>
- promise_test(async function() {
- var mod = await createWasmModule();
- assert_true(mod instanceof WebAssembly.Module);
- var ans = await new Promise((resolve, reject) => {
- var iframe = document.getElementById("iframe").contentWindow;
- iframe.postMessage(mod, '*');
- window.addEventListener("message", (reply) => resolve(reply.data), false);
- });
- assert_equals(ans, 43);
- }, "send wasm module to iframe");
+ function runTests(iframe) {
+ iframe = iframe.contentWindow;
+ promise_test(async function() {
+ var mod = await createWasmModule();
+ assert_true(mod instanceof WebAssembly.Module);
+ var ans = await new Promise((resolve, reject) => {
+ iframe.postMessage(mod, '*');
+ window.addEventListener("message", (reply) => resolve(reply.data), false);
+ });
+ assert_equals(ans, 43);
+ }, "send wasm module to iframe");
+ }
</script>
+<iframe src="resources/frame.html" onload="runTests(this)"></iframe>
diff --git a/tests/wpt/web-platform-tests/web-animations/README.md b/tests/wpt/web-platform-tests/web-animations/README.md
index abc9338c1f2..475f58a57b1 100644
--- a/tests/wpt/web-platform-tests/web-animations/README.md
+++ b/tests/wpt/web-platform-tests/web-animations/README.md
@@ -1,7 +1,7 @@
Web Animations Test Suite
=========================
-Specification: https://w3c.github.io/web-animations/
+Specification: https://drafts.csswg.org/web-animations/
Guidelines for writing tests
@@ -51,24 +51,24 @@ Guidelines for writing tests
e.g.
```javascript
- test(function(t) {
+ test(t => {
const animation = createDiv(t).animate(null);
assert_class_string(animation, 'Animation', 'Returned object is an Animation');
}, 'Element.animate() creates an Animation object');
```
```javascript
- test(function(t) {
- assert_throws({ name: 'TypeError' }, function() {
+ test(t => {
+ assert_throws({ name: 'TypeError' }, () => {
createDiv(t).animate(null, -1);
});
}, 'Setting a negative duration throws a TypeError');
```
```javascript
- promise_test(function(t) {
+ promise_test(t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
- return animation.ready.then(function() {
+ return animation.ready.then(() => {
assert_greater_than(animation.startTime, 0, 'startTime when running');
});
}, 'startTime is resolved when running');
diff --git a/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/accumulation-per-property.html b/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/accumulation-per-property.html
index c4439dd3c94..870e4891240 100644
--- a/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/accumulation-per-property.html
+++ b/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/accumulation-per-property.html
@@ -1,7 +1,7 @@
<!doctype html>
<meta charset=utf-8>
-<title>Tests for animation type of accumulation</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#animation-types">
+<title>Accumulation for each property</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#animation-types">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -17,16 +17,15 @@ html {
<script>
'use strict';
-for (var property in gCSSProperties) {
+for (const property in gCSSProperties) {
if (!isSupported(property)) {
continue;
}
- var animationTypes = gCSSProperties[property].types;
- var setupFunction = gCSSProperties[property].setup;
- animationTypes.forEach(function(animationType) {
- var typeObject;
- var animationTypeString;
+ const setupFunction = gCSSProperties[property].setup;
+ for (const animationType of gCSSProperties[property].types) {
+ let typeObject;
+ let animationTypeString;
if (typeof animationType === 'string') {
typeObject = types[animationType];
animationTypeString = animationType;
@@ -39,13 +38,13 @@ for (var property in gCSSProperties) {
// First, test that the animation type object has 'testAccumulation'.
// We use test() function here so that we can continue the remainder tests
// even if this test fails.
- test(function(t) {
+ test(t => {
assert_own_property(typeObject, 'testAccumulation', animationTypeString +
' should have testAccumulation property');
assert_equals(typeof typeObject.testAccumulation, 'function',
'testAccumulation method should be a function');
- }, property + ' (type: ' + animationTypeString +
- ') has testAccumulation function');
+ }, `${property} (type: ${animationTypeString}) has testAccumulation`
+ + ' function');
if (typeObject.testAccumulation &&
typeof typeObject.testAccumulation === 'function') {
@@ -53,6 +52,6 @@ for (var property in gCSSProperties) {
setupFunction,
animationType.options);
}
- });
+ }
}
</script>
diff --git a/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/addition-per-property.html b/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/addition-per-property.html
index 97f722064c1..61256314fea 100644
--- a/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/addition-per-property.html
+++ b/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/addition-per-property.html
@@ -1,7 +1,7 @@
<!doctype html>
<meta charset=utf-8>
-<title>Tests for animation type of addition</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#animation-types">
+<title>Addition for each property</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#animation-types">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -17,16 +17,15 @@ html {
<script>
'use strict';
-for (var property in gCSSProperties) {
+for (const property in gCSSProperties) {
if (!isSupported(property)) {
continue;
}
- var animationTypes = gCSSProperties[property].types;
- var setupFunction = gCSSProperties[property].setup;
- animationTypes.forEach(function(animationType) {
- var typeObject;
- var animationTypeString;
+ const setupFunction = gCSSProperties[property].setup;
+ for (const animationType of gCSSProperties[property].types) {
+ let typeObject;
+ let animationTypeString;
if (typeof animationType === 'string') {
typeObject = types[animationType];
animationTypeString = animationType;
@@ -39,13 +38,13 @@ for (var property in gCSSProperties) {
// First, test that the animation type object has 'testAddition'.
// We use test() function here so that we can continue the remainder tests
// even if this test fails.
- test(function(t) {
+ test(t => {
assert_own_property(typeObject, 'testAddition', animationTypeString +
' should have testAddition property');
assert_equals(typeof typeObject.testAddition, 'function',
'testAddition method should be a function');
- }, property + ' (type: ' + animationTypeString +
- ') has testAddition function');
+ }, `${property} (type: ${animationTypeString}) has testAddition`
+ + ' function');
if (typeObject.testAddition &&
typeof typeObject.testAddition === 'function') {
@@ -53,6 +52,6 @@ for (var property in gCSSProperties) {
setupFunction,
animationType.options);
}
- });
+ }
}
</script>
diff --git a/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/discrete-animation.html b/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/discrete-animation.html
deleted file mode 100644
index 2b7e6a56592..00000000000
--- a/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/discrete-animation.html
+++ /dev/null
@@ -1,135 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>Tests for discrete animation</title>
-<link rel="help" href="http://w3c.github.io/web-animations/#animatable-as-string-section">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<script>
-'use strict';
-
-test(function(t) {
- var div = createDiv(t);
-
- var anim = div.animate({ fontStyle: [ 'normal', 'italic' ] },
- { duration: 1000, fill: 'forwards' });
-
- assert_equals(getComputedStyle(div).fontStyle, 'normal',
- 'Animation produces \'from\' value at start of interval');
- anim.currentTime = anim.effect.getComputedTiming().duration / 2 - 1;
- assert_equals(getComputedStyle(div).fontStyle, 'normal',
- 'Animation produces \'from\' value just before the middle of'
- + ' the interval');
- anim.currentTime++;
- assert_equals(getComputedStyle(div).fontStyle, 'italic',
- 'Animation produces \'to\' value at exact middle of'
- + ' the interval');
- anim.finish();
- assert_equals(getComputedStyle(div).fontStyle, 'italic',
- 'Animation produces \'to\' value during forwards fill');
-}, 'Test animating discrete values');
-
-test(function(t) {
- var div = createDiv(t);
- var originalHeight = getComputedStyle(div).height;
-
- var anim = div.animate({ height: [ 'auto', '200px' ] },
- { duration: 1000, fill: 'forwards' });
-
- assert_equals(getComputedStyle(div).height, originalHeight,
- 'Animation produces \'from\' value at start of interval');
- anim.currentTime = anim.effect.getComputedTiming().duration / 2 - 1;
- assert_equals(getComputedStyle(div).height, originalHeight,
- 'Animation produces \'from\' value just before the middle of'
- + ' the interval');
- anim.currentTime++;
- assert_equals(getComputedStyle(div).height, '200px',
- 'Animation produces \'to\' value at exact middle of'
- + ' the interval');
- anim.finish();
- assert_equals(getComputedStyle(div).height, '200px',
- 'Animation produces \'to\' value during forwards fill');
-}, 'Test discrete animation is used when interpolation fails');
-
-test(function(t) {
- var div = createDiv(t);
- var originalHeight = getComputedStyle(div).height;
-
- var anim = div.animate({ height: [ 'auto',
- '200px',
- '300px',
- 'auto',
- '400px' ] },
- { duration: 1000, fill: 'forwards' });
-
- // There are five values, so there are four pairs to try to interpolate.
- // We test at the middle of each pair.
- assert_equals(getComputedStyle(div).height, originalHeight,
- 'Animation produces \'from\' value at start of interval');
- anim.currentTime = 125;
- assert_equals(getComputedStyle(div).height, '200px',
- 'First non-interpolable pair uses discrete interpolation');
- anim.currentTime += 250;
- assert_equals(getComputedStyle(div).height, '250px',
- 'Second interpolable pair uses linear interpolation');
- anim.currentTime += 250;
- assert_equals(getComputedStyle(div).height, originalHeight,
- 'Third non-interpolable pair uses discrete interpolation');
- anim.currentTime += 250;
- assert_equals(getComputedStyle(div).height, '400px',
- 'Fourth non-interpolable pair uses discrete interpolation');
-}, 'Test discrete animation is used only for pairs of values that cannot'
- + ' be interpolated');
-
-test(function(t) {
- var div = createDiv(t);
- var originalHeight = getComputedStyle(div).height;
-
- // Easing: http://cubic-bezier.com/#.68,0,1,.01
- // With this curve, we don't reach the 50% point until about 95% of
- // the time has expired.
- var anim = div.animate({ fontStyle: [ 'normal', 'italic' ] },
- { duration: 1000, fill: 'forwards',
- easing: 'cubic-bezier(0.68,0,1,0.01)' });
-
- assert_equals(getComputedStyle(div).fontStyle, 'normal',
- 'Animation produces \'from\' value at start of interval');
- anim.currentTime = 940;
- assert_equals(getComputedStyle(div).fontStyle, 'normal',
- 'Animation produces \'from\' value at 94% of the iteration'
- + ' time');
- anim.currentTime = 960;
- assert_equals(getComputedStyle(div).fontStyle, 'italic',
- 'Animation produces \'to\' value at 96% of the iteration'
- + ' time');
-}, 'Test the 50% switch point for discrete animation is based on the'
- + ' effect easing');
-
-test(function(t) {
- var div = createDiv(t);
- var originalHeight = getComputedStyle(div).height;
-
- // Easing: http://cubic-bezier.com/#.68,0,1,.01
- // With this curve, we don't reach the 50% point until about 95% of
- // the time has expired.
- var anim = div.animate([ { fontStyle: 'normal',
- easing: 'cubic-bezier(0.68,0,1,0.01)' },
- { fontStyle: 'italic' } ],
- { duration: 1000, fill: 'forwards' });
-
- assert_equals(getComputedStyle(div).fontStyle, 'normal',
- 'Animation produces \'from\' value at start of interval');
- anim.currentTime = 940;
- assert_equals(getComputedStyle(div).fontStyle, 'normal',
- 'Animation produces \'from\' value at 94% of the iteration'
- + ' time');
- anim.currentTime = 960;
- assert_equals(getComputedStyle(div).fontStyle, 'italic',
- 'Animation produces \'to\' value at 96% of the iteration'
- + ' time');
-}, 'Test the 50% switch point for discrete animation is based on the'
- + ' keyframe easing');
-
-</script>
diff --git a/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/discrete.html b/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/discrete.html
new file mode 100644
index 00000000000..76f42bc7a40
--- /dev/null
+++ b/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/discrete.html
@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Discrete animation type</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#discrete-animation-type">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+test(t => {
+ const div = createDiv(t);
+
+ const anim = div.animate({ fontStyle: [ 'normal', 'italic' ] },
+ { duration: 1000, fill: 'forwards' });
+
+ assert_equals(getComputedStyle(div).fontStyle, 'normal',
+ 'Animation produces \'from\' value at start of interval');
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2 - 1;
+ assert_equals(getComputedStyle(div).fontStyle, 'normal',
+ 'Animation produces \'from\' value just before the middle of'
+ + ' the interval');
+ anim.currentTime++;
+ assert_equals(getComputedStyle(div).fontStyle, 'italic',
+ 'Animation produces \'to\' value at exact middle of'
+ + ' the interval');
+ anim.finish();
+ assert_equals(getComputedStyle(div).fontStyle, 'italic',
+ 'Animation produces \'to\' value during forwards fill');
+}, 'Test animating discrete values');
+
+test(t => {
+ const div = createDiv(t);
+ const originalHeight = getComputedStyle(div).height;
+
+ const anim = div.animate({ height: [ 'auto', '200px' ] },
+ { duration: 1000, fill: 'forwards' });
+
+ assert_equals(getComputedStyle(div).height, originalHeight,
+ 'Animation produces \'from\' value at start of interval');
+ anim.currentTime = anim.effect.getComputedTiming().duration / 2 - 1;
+ assert_equals(getComputedStyle(div).height, originalHeight,
+ 'Animation produces \'from\' value just before the middle of'
+ + ' the interval');
+ anim.currentTime++;
+ assert_equals(getComputedStyle(div).height, '200px',
+ 'Animation produces \'to\' value at exact middle of'
+ + ' the interval');
+ anim.finish();
+ assert_equals(getComputedStyle(div).height, '200px',
+ 'Animation produces \'to\' value during forwards fill');
+}, 'Test discrete animation is used when interpolation fails');
+
+test(t => {
+ const div = createDiv(t);
+ const originalHeight = getComputedStyle(div).height;
+
+ const anim = div.animate({ height: [ 'auto',
+ '200px',
+ '300px',
+ 'auto',
+ '400px' ] },
+ { duration: 1000, fill: 'forwards' });
+
+ // There are five values, so there are four pairs to try to interpolate.
+ // We test at the middle of each pair.
+ assert_equals(getComputedStyle(div).height, originalHeight,
+ 'Animation produces \'from\' value at start of interval');
+ anim.currentTime = 125;
+ assert_equals(getComputedStyle(div).height, '200px',
+ 'First non-interpolable pair uses discrete interpolation');
+ anim.currentTime += 250;
+ assert_equals(getComputedStyle(div).height, '250px',
+ 'Second interpolable pair uses linear interpolation');
+ anim.currentTime += 250;
+ assert_equals(getComputedStyle(div).height, originalHeight,
+ 'Third non-interpolable pair uses discrete interpolation');
+ anim.currentTime += 250;
+ assert_equals(getComputedStyle(div).height, '400px',
+ 'Fourth non-interpolable pair uses discrete interpolation');
+}, 'Test discrete animation is used only for pairs of values that cannot'
+ + ' be interpolated');
+
+test(t => {
+ const div = createDiv(t);
+ const originalHeight = getComputedStyle(div).height;
+
+ // Easing: http://cubic-bezier.com/#.68,0,1,.01
+ // With this curve, we don't reach the 50% point until about 95% of
+ // the time has expired.
+ const anim = div.animate({ fontStyle: [ 'normal', 'italic' ] },
+ { duration: 1000, fill: 'forwards',
+ easing: 'cubic-bezier(0.68,0,1,0.01)' });
+
+ assert_equals(getComputedStyle(div).fontStyle, 'normal',
+ 'Animation produces \'from\' value at start of interval');
+ anim.currentTime = 940;
+ assert_equals(getComputedStyle(div).fontStyle, 'normal',
+ 'Animation produces \'from\' value at 94% of the iteration'
+ + ' time');
+ anim.currentTime = 960;
+ assert_equals(getComputedStyle(div).fontStyle, 'italic',
+ 'Animation produces \'to\' value at 96% of the iteration'
+ + ' time');
+}, 'Test the 50% switch point for discrete animation is based on the'
+ + ' effect easing');
+
+test(t => {
+ const div = createDiv(t);
+ const originalHeight = getComputedStyle(div).height;
+
+ // Easing: http://cubic-bezier.com/#.68,0,1,.01
+ // With this curve, we don't reach the 50% point until about 95% of
+ // the time has expired.
+ const anim = div.animate([ { fontStyle: 'normal',
+ easing: 'cubic-bezier(0.68,0,1,0.01)' },
+ { fontStyle: 'italic' } ],
+ { duration: 1000, fill: 'forwards' });
+
+ assert_equals(getComputedStyle(div).fontStyle, 'normal',
+ 'Animation produces \'from\' value at start of interval');
+ anim.currentTime = 940;
+ assert_equals(getComputedStyle(div).fontStyle, 'normal',
+ 'Animation produces \'from\' value at 94% of the iteration'
+ + ' time');
+ anim.currentTime = 960;
+ assert_equals(getComputedStyle(div).fontStyle, 'italic',
+ 'Animation produces \'to\' value at 96% of the iteration'
+ + ' time');
+}, 'Test the 50% switch point for discrete animation is based on the'
+ + ' keyframe easing');
+
+</script>
diff --git a/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/interpolation-per-property.html b/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/interpolation-per-property.html
index e8e4b48fa69..2c335da0dc4 100644
--- a/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/interpolation-per-property.html
+++ b/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/interpolation-per-property.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>Tests for animation type of interpolation</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#animation-types">
+<title>Interpolation for each property</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#animation-types">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -17,16 +17,15 @@ html {
<script>
'use strict';
-for (var property in gCSSProperties) {
+for (const property in gCSSProperties) {
if (!isSupported(property)) {
continue;
}
- var animationTypes = gCSSProperties[property].types;
- var setupFunction = gCSSProperties[property].setup;
- animationTypes.forEach(function(animationType) {
- var typeObject;
- var animationTypeString;
+ const setupFunction = gCSSProperties[property].setup;
+ for (const animationType of gCSSProperties[property].types) {
+ let typeObject;
+ let animationTypeString;
if (typeof animationType === 'string') {
typeObject = types[animationType];
animationTypeString = animationType;
@@ -39,13 +38,13 @@ for (var property in gCSSProperties) {
// First, test that the animation type object has 'testInterpolation'.
// We use test() function() here so that we can continue the remainder tests
// even if this test fails.
- test(function(t) {
+ test(t => {
assert_own_property(typeObject, 'testInterpolation', animationTypeString +
' should have testInterpolation property');
assert_equals(typeof typeObject.testInterpolation, 'function',
'testInterpolation method should be a function');
- }, property + ' (type: ' + animationTypeString +
- ') has testInterpolation function');
+ }, `${property} (type: ${animationTypeString}) has testInterpolation`
+ + ' function');
if (typeObject.testInterpolation &&
typeof typeObject.testInterpolation === 'function') {
@@ -53,6 +52,6 @@ for (var property in gCSSProperties) {
setupFunction,
animationType.options);
}
- });
+ }
}
</script>
diff --git a/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/property-list.js b/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/property-list.js
index 4315d0fe716..1220b455b18 100644
--- a/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/property-list.js
+++ b/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/property-list.js
@@ -1,6 +1,6 @@
'use strict';
-var gCSSProperties = {
+const gCSSProperties = {
'align-content': {
// https://drafts.csswg.org/css-align/#propdef-align-content
types: [
@@ -146,7 +146,7 @@ var gCSSProperties = {
// https://drafts.csswg.org/css-backgrounds-3/#border-bottom-width
types: [ 'length' ],
setup: t => {
- var element = createElement(t);
+ const element = createElement(t);
element.style.borderBottomStyle = 'solid';
return element;
}
@@ -233,7 +233,7 @@ var gCSSProperties = {
// https://drafts.csswg.org/css-backgrounds-3/#border-left-width
types: [ 'length' ],
setup: t => {
- var element = createElement(t);
+ const element = createElement(t);
element.style.borderLeftStyle = 'solid';
return element;
}
@@ -252,7 +252,7 @@ var gCSSProperties = {
// https://drafts.csswg.org/css-backgrounds-3/#border-right-width
types: [ 'length' ],
setup: t => {
- var element = createElement(t);
+ const element = createElement(t);
element.style.borderRightStyle = 'solid';
return element;
}
@@ -285,7 +285,7 @@ var gCSSProperties = {
// https://drafts.csswg.org/css-backgrounds-3/#border-top-width
types: [ 'length' ],
setup: t => {
- var element = createElement(t);
+ const element = createElement(t);
element.style.borderTopStyle = 'solid';
return element;
}
@@ -402,7 +402,7 @@ var gCSSProperties = {
// https://drafts.csswg.org/css-multicol/#propdef-column-rule-width
types: [ 'length' ],
setup: t => {
- var element = createElement(t);
+ const element = createElement(t);
element.style.columnRuleStyle = 'solid';
return element;
}
@@ -1044,7 +1044,7 @@ var gCSSProperties = {
// https://drafts.csswg.org/css-ui-3/#propdef-outline-width
types: [ 'length' ],
setup: t => {
- var element = createElement(t);
+ const element = createElement(t);
element.style.outlineStyle = 'solid';
return element;
}
@@ -1054,12 +1054,6 @@ var gCSSProperties = {
types: [
]
},
- 'overflow-clip-box': {
- // https://developer.mozilla.org/en/docs/Web/CSS/overflow-clip-box
- types: [
- { type: 'discrete', options: [ [ 'padding-box', 'content-box' ] ] }
- ]
- },
'overflow-wrap': {
// https://drafts.csswg.org/css-text-3/#propdef-overflow-wrap
types: [
@@ -1368,7 +1362,7 @@ var gCSSProperties = {
// https://drafts.csswg.org/css-text-decor-3/#propdef-text-shadow
types: [ 'textShadowList' ],
setup: t => {
- var element = createElement(t);
+ const element = createElement(t);
element.style.color = 'green';
return element;
}
@@ -1477,13 +1471,13 @@ function testAnimationSamples(animation, idlName, testSamples) {
const target = animation.effect.target.constructor.name === 'CSSPseudoElement'
? animation.effect.target.parentElement
: animation.effect.target;
- testSamples.forEach(testSample => {
+ for (const testSample of testSamples) {
animation.currentTime = testSample.time;
assert_equals(getComputedStyle(target, type)[idlName],
testSample.expected,
`The value should be ${testSample.expected}` +
` at ${testSample.time}ms`);
- });
+ }
}
function toOrderedArray(string) {
@@ -1498,7 +1492,7 @@ function testAnimationSamplesWithAnyOrder(animation, idlName, testSamples) {
const target = animation.effect.target.constructor.name === 'CSSPseudoElement'
? animation.effect.target.parentElement
: animation.effect.target;
- testSamples.forEach(testSample => {
+ for (const testSample of testSamples) {
animation.currentTime = testSample.time;
// Convert to array and sort the expected and actual value lists first
@@ -1510,19 +1504,19 @@ function testAnimationSamplesWithAnyOrder(animation, idlName, testSamples) {
assert_array_equals(computedValues, expectedValues,
`The computed values should be ${expectedValues}` +
` at ${testSample.time}ms`);
- });
+ }
}
function testAnimationSampleMatrices(animation, idlName, testSamples) {
- var target = animation.effect.target;
- testSamples.forEach(function(testSample) {
+ const target = animation.effect.target;
+ for (const testSample of testSamples) {
animation.currentTime = testSample.time;
- var actual = getComputedStyle(target)[idlName];
- var expected = createMatrixFromArray(testSample.expected);
+ const actual = getComputedStyle(target)[idlName];
+ const expected = createMatrixFromArray(testSample.expected);
assert_matrix_equals(actual, expected,
- 'The value should be ' + expected +
- ' at ' + testSample.time + 'ms but got ' + actual);
- });
+ `The value should be ${expected} at`
+ + ` ${testSample.time}ms but got ${actual}`);
+ }
}
function createTestElement(t, setup) {
@@ -1530,7 +1524,7 @@ function createTestElement(t, setup) {
}
function isSupported(property) {
- var testKeyframe = new TestKeyframe(propertyToIDL(property));
+ const testKeyframe = new TestKeyframe(propertyToIDL(property));
try {
// Since TestKeyframe returns 'undefined' for |property|,
// the KeyframeEffect constructor will throw
@@ -1541,7 +1535,7 @@ function isSupported(property) {
}
function TestKeyframe(testProp) {
- var _propAccessCount = 0;
+ let _propAccessCount = 0;
Object.defineProperty(this, testProp, {
get: function() { _propAccessCount++; },
@@ -1554,7 +1548,7 @@ function TestKeyframe(testProp) {
}
function propertyToIDL(property) {
- // https://w3c.github.io/web-animations/#animation-property-name-to-idl-attribute-name
+ // https://drafts.csswg.org/web-animations/#animation-property-name-to-idl-attribute-name
if (property === 'float') {
return 'cssFloat';
}
@@ -1563,11 +1557,11 @@ function propertyToIDL(property) {
return str.substr(1).toUpperCase(); });
}
function calcFromPercentage(idlName, percentageValue) {
- var examElem = document.createElement('div');
+ const examElem = document.createElement('div');
document.body.appendChild(examElem);
examElem.style[idlName] = percentageValue;
- var calcValue = getComputedStyle(examElem)[idlName];
+ const calcValue = getComputedStyle(examElem)[idlName];
document.body.removeChild(examElem);
return calcValue;
diff --git a/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/property-types.js b/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/property-types.js
index 7641bbeb920..eb9c8c163a1 100644
--- a/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/property-types.js
+++ b/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/property-types.js
@@ -1,78 +1,93 @@
+'use strict';
+
const discreteType = {
- testInterpolation: function(property, setup, options) {
- options.forEach(function(keyframes) {
- var [ from, to ] = keyframes;
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: [from, to] },
- { duration: 1000, fill: 'both' });
+ testInterpolation: (property, setup, options) => {
+ for (const keyframes of options) {
+ const [ from, to ] = keyframes;
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]: [from, to] },
+ { duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
[{ time: 0, expected: from.toLowerCase() },
{ time: 499, expected: from.toLowerCase() },
{ time: 500, expected: to.toLowerCase() },
{ time: 1000, expected: to.toLowerCase() }]);
- }, property + ' uses discrete animation when animating between "'
- + from + '" and "' + to + '" with linear easing');
+ }, `${property} uses discrete animation when animating between`
+ + ` "${from}" and "${to}" with linear easing`);
- test(function(t) {
+ test(t => {
// Easing: http://cubic-bezier.com/#.68,0,1,.01
// With this curve, we don't reach the 50% point until about 95% of
// the time has expired.
- var idlName = propertyToIDL(property);
- var keyframes = {};
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: [from, to] },
- { duration: 1000, fill: 'both',
- easing: 'cubic-bezier(0.68,0,1,0.01)' });
+ const idlName = propertyToIDL(property);
+ const keyframes = {};
+ const target = createTestElement(t, setup);
+ const animation = target.animate(
+ { [idlName]: [from, to] },
+ {
+ duration: 1000,
+ fill: 'both',
+ easing: 'cubic-bezier(0.68,0,1,0.01)',
+ }
+ );
testAnimationSamples(animation, idlName,
[{ time: 0, expected: from.toLowerCase() },
{ time: 940, expected: from.toLowerCase() },
{ time: 960, expected: to.toLowerCase() }]);
- }, property + ' uses discrete animation when animating between "'
- + from + '" and "' + to + '" with effect easing');
+ }, `${property} uses discrete animation when animating between`
+ + ` "${from}" and "${to}" with effect easing`);
- test(function(t) {
+ test(t => {
// Easing: http://cubic-bezier.com/#.68,0,1,.01
// With this curve, we don't reach the 50% point until about 95% of
// the time has expired.
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: [from, to],
- easing: 'cubic-bezier(0.68,0,1,0.01)' },
- { duration: 1000, fill: 'both' });
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate(
+ {
+ [idlName]: [from, to],
+ easing: 'cubic-bezier(0.68,0,1,0.01)',
+ },
+ { duration: 1000, fill: 'both' }
+ );
testAnimationSamples(animation, idlName,
[{ time: 0, expected: from.toLowerCase() },
{ time: 940, expected: from.toLowerCase() },
{ time: 960, expected: to.toLowerCase() }]);
- }, property + ' uses discrete animation when animating between "'
- + from + '" and "' + to + '" with keyframe easing');
- });
+ }, `${property} uses discrete animation when animating between`
+ + ` "${from}" and "${to}" with keyframe easing`);
+ }
},
- testAdditionOrAccumulation: function(property, setup, options, composite) {
- options.forEach(function(keyframes) {
- var [ from, to ] = keyframes;
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ testAdditionOrAccumulation: (property, setup, options, composite) => {
+ for (const keyframes of options) {
+ const [ from, to ] = keyframes;
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.animate({ [idlName]: [from, from] }, 1000);
- var animation = target.animate({ [idlName]: [to, to] },
- { duration: 1000, composite: composite });
+ const animation = target.animate(
+ { [idlName]: [to, to] },
+ { duration: 1000, composite }
+ );
testAnimationSamples(animation, idlName,
[{ time: 0, expected: to.toLowerCase() }]);
- }, property + ': "' + to + '" onto "' + from + '"');
+ }, `${property}: "${to}" onto "${from}"`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.animate({ [idlName]: [to, to] }, 1000);
- var animation = target.animate({ [idlName]: [from, from] },
- { duration: 1000, composite: composite });
+ const animation = target.animate(
+ { [idlName]: [from, from] },
+ { duration: 1000, composite }
+ );
testAnimationSamples(animation, idlName,
[{ time: 0, expected: from.toLowerCase() }]);
- }, property + ': "' + from + '" onto "' + to + '"');
- });
+ }, `${property}: "${from}" onto "${to}"`);
+ }
},
testAddition: function(property, setup, options) {
@@ -85,44 +100,48 @@ const discreteType = {
};
const lengthType = {
- testInterpolation: function(property, setup) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: ['10px', '50px'] },
- { duration: 1000, fill: 'both' });
+ testInterpolation: (property, setup) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]: ['10px', '50px'] },
+ { duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
[{ time: 500, expected: '30px' }]);
- }, property + ' supports animating as a length');
+ }, `${property} supports animating as a length`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: ['1rem', '5rem'] },
- { duration: 1000, fill: 'both' });
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]: ['1rem', '5rem'] },
+ { duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
[{ time: 500, expected: '30px' }]);
- }, property + ' supports animating as a length of rem');
+ }, `${property} supports animating as a length of rem`);
},
- testAdditionOrAccumulation: function(property, setup, composite) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ testAdditionOrAccumulation: (property, setup, composite) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = '10px';
- var animation = target.animate({ [idlName]: ['10px', '50px'] },
- { duration: 1000, composite: composite});
+ const animation = target.animate(
+ { [idlName]: ['10px', '50px'] },
+ { duration: 1000, composite }
+ );
testAnimationSamples(animation, idlName, [{ time: 0, expected: '20px' }]);
- }, property + ': length');
+ }, `${property}: length`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = '1rem';
- var animation = target.animate({ [idlName]: ['1rem', '5rem'] },
- { duration: 1000, composite: composite });
+ const animation = target.animate(
+ { [idlName]: ['1rem', '5rem'] },
+ { duration: 1000, composite }
+ );
testAnimationSamples(animation, idlName, [{ time: 0, expected: '20px' }]);
- }, property + ': length of rem');
+ }, `${property}: length of rem`);
},
testAddition: function(property, setup) {
@@ -135,44 +154,60 @@ const lengthType = {
};
const lengthPairType = {
- testInterpolation: function(property, setup) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: ['10px 10px', '50px 50px'] },
- { duration: 1000, fill: 'both' });
+ testInterpolation: (property, setup) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate(
+ { [idlName]: ['10px 10px', '50px 50px'] },
+ { duration: 1000, fill: 'both' }
+ );
testAnimationSamples(animation, idlName,
[{ time: 500, expected: '30px 30px' }]);
- }, property + ' supports animating as a length pair');
+ }, `${property} supports animating as a length pair`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: ['1rem 1rem', '5rem 5rem'] },
- { duration: 1000, fill: 'both' });
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate(
+ { [idlName]: ['1rem 1rem', '5rem 5rem'] },
+ { duration: 1000, fill: 'both' }
+ );
testAnimationSamples(animation, idlName,
[{ time: 500, expected: '30px 30px' }]);
- }, property + ' supports animating as a length pair of rem');
+ }, `${property} supports animating as a length pair of rem`);
},
- testAdditionOrAccumulation: function(property, setup, composite) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ testAdditionOrAccumulation: (property, setup, composite) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = '10px 10px';
- var animation = target.animate({ [idlName]: ['10px 10px', '50px 50px'] },
- { duration: 1000, composite: composite });
- testAnimationSamples(animation, idlName, [{ time: 0, expected: '20px 20px' }]);
- }, property + ': length pair');
-
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ const animation = target.animate(
+ { [idlName]: ['10px 10px', '50px 50px'] },
+ { duration: 1000, composite }
+ );
+ testAnimationSamples(
+ animation,
+ idlName,
+ [{ time: 0, expected: '20px 20px' }]
+ );
+ }, `${property}: length pair`);
+
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = '1rem 1rem';
- var animation = target.animate({ [idlName]: ['1rem 1rem', '5rem 5rem'] },
- { duration: 1000, composite: composite });
- testAnimationSamples(animation, idlName, [{ time: 0, expected: '20px 20px' }]);
- }, property + ': length pair of rem');
+ const animation = target.animate(
+ { [idlName]: ['1rem 1rem', '5rem 5rem'] },
+ { duration: 1000, composite }
+ );
+ testAnimationSamples(
+ animation,
+ idlName,
+ [{ time: 0, expected: '20px 20px' }]
+ );
+ }, `${property}: length pair of rem`);
},
testAddition: function(property, setup) {
@@ -185,26 +220,28 @@ const lengthPairType = {
};
const percentageType = {
- testInterpolation: function(property, setup) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: ['10%', '50%'] },
- { duration: 1000, fill: 'both' });
+ testInterpolation: (property, setup) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]: ['10%', '50%'] },
+ { duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
[{ time: 500, expected: '30%' }]);
- }, property + ' supports animating as a percentage');
+ }, `${property} supports animating as a percentage`);
},
- testAdditionOrAccumulation: function(property, setup, composite) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ testAdditionOrAccumulation: (property, setup, composite) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = '60%';
- var animation = target.animate({ [idlName]: ['70%', '100%'] },
- { duration: 1000, composite: composite });
+ const animation = target.animate(
+ { [idlName]: ['70%', '100%'] },
+ { duration: 1000, composite }
+ );
testAnimationSamples(animation, idlName, [{ time: 0, expected: '130%' }]);
- }, property + ': percentage');
+ }, `${property}: percentage`);
},
testAddition: function(property, setup) {
@@ -217,27 +254,29 @@ const percentageType = {
};
const integerType = {
- testInterpolation: function(property, setup) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: [-2, 2] },
- { duration: 1000, fill: 'both' });
+ testInterpolation: (property, setup) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]: [-2, 2] },
+ { duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
[{ time: 500, expected: '0' }]);
- }, property + ' supports animating as an integer');
+ }, `${property} supports animating as an integer`);
},
- testAdditionOrAccumulation: function(property, setup, composite) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ testAdditionOrAccumulation: (property, setup, composite) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = -1;
- var animation = target.animate({ [idlName]: [-2, 2] },
- { duration: 1000, composite: composite });
+ const animation = target.animate(
+ { [idlName]: [-2, 2] },
+ { duration: 1000, composite }
+ );
testAnimationSamples(animation, idlName,
[{ time: 0, expected: '-3' }]);
- }, property + ': integer');
+ }, `${property}: integer`);
},
testAddition: function(property, setup) {
@@ -250,27 +289,29 @@ const integerType = {
};
const positiveIntegerType = {
- testInterpolation: function(property, setup) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: [1, 3] },
- { duration: 1000, fill: 'both' });
+ testInterpolation: (property, setup) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]: [1, 3] },
+ { duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
[ { time: 500, expected: '2' } ]);
- }, property + ' supports animating as a positive integer');
+ }, `${property} supports animating as a positive integer`);
},
- testAdditionOrAccumulation: function(property, setup, composite) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ testAdditionOrAccumulation: (property, setup, composite) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 1;
- var animation = target.animate({ [idlName]: [2, 5] },
- { duration: 1000, composite: composite });
+ const animation = target.animate(
+ { [idlName]: [2, 5] },
+ { duration: 1000, composite }
+ );
testAnimationSamples(animation, idlName,
[{ time: 0, expected: '3' }]);
- }, property + ': positive integer');
+ }, `${property}: positive integer`);
},
testAddition: function(property, setup) {
@@ -283,141 +324,143 @@ const positiveIntegerType = {
};
const lengthPercentageOrCalcType = {
- testInterpolation: function(property, setup) {
+ testInterpolation: (property, setup) => {
lengthType.testInterpolation(property, setup);
percentageType.testInterpolation(property, setup);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: ['10px', '20%'] },
- { duration: 1000, fill: 'both' });
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]: ['10px', '20%'] },
+ { duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'calc(5px + 10%)' }]);
- }, property + ' supports animating as combination units "px" and "%"');
+ }, `${property} supports animating as combination units "px" and "%"`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: ['10%', '2em'] },
- { duration: 1000, fill: 'both' });
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]: ['10%', '2em'] },
+ { duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'calc(10px + 5%)' }]);
- }, property + ' supports animating as combination units "%" and "em"');
+ }, `${property} supports animating as combination units "%" and "em"`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: ['1em', '2rem'] },
- { duration: 1000, fill: 'both' });
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]: ['1em', '2rem'] },
+ { duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
[{ time: 500, expected: '15px' }]);
- }, property + ' supports animating as combination units "em" and "rem"');
+ }, `${property} supports animating as combination units "em" and "rem"`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: ['10px', 'calc(1em + 20%)'] },
- { duration: 1000, fill: 'both' });
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate(
+ { [idlName]: ['10px', 'calc(1em + 20%)'] },
+ { duration: 1000, fill: 'both' }
+ );
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'calc(10px + 10%)' }]);
- }, property + ' supports animating as combination units "px" and "calc"');
+ }, `${property} supports animating as combination units "px" and "calc"`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate(
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate(
{ [idlName]: ['calc(10px + 10%)', 'calc(1em + 1rem + 20%)'] },
{ duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
[{ time: 500,
expected: 'calc(15px + 15%)' }]);
- }, property + ' supports animating as a calc');
+ }, `${property} supports animating as a calc`);
},
- testAdditionOrAccumulation: function(property, setup, composite) {
+ testAdditionOrAccumulation: (property, setup, composite) => {
lengthType.testAddition(property, setup);
percentageType.testAddition(property, setup);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = '10px';
- var animation = target.animate({ [idlName]: ['10%', '50%'] },
- { duration: 1000, composite: composite });
+ const animation = target.animate({ [idlName]: ['10%', '50%'] },
+ { duration: 1000, composite });
testAnimationSamples(animation, idlName,
[{ time: 0, expected: 'calc(10px + 10%)' }]);
- }, property + ': units "%" onto "px"');
+ }, `${property}: units "%" onto "px"`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = '10%';
- var animation = target.animate({ [idlName]: ['10px', '50px'] },
- { duration: 1000, composite: composite });
+ const animation = target.animate({ [idlName]: ['10px', '50px'] },
+ { duration: 1000, composite });
testAnimationSamples(animation, idlName,
[{ time: 0, expected: 'calc(10px + 10%)' }]);
- }, property + ': units "px" onto "%"');
+ }, `${property}: units "px" onto "%"`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = '10%';
- var animation = target.animate({ [idlName]: ['2rem', '5rem'] },
- { duration: 1000, composite: composite });
+ const animation = target.animate({ [idlName]: ['2rem', '5rem'] },
+ { duration: 1000, composite });
testAnimationSamples(animation, idlName,
[{ time: 0, expected: 'calc(20px + 10%)' }]);
- }, property + ': units "rem" onto "%"');
+ }, `${property}: units "rem" onto "%"`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = '2rem';
- var animation = target.animate({ [idlName]: ['10%', '50%'] },
- { duration: 1000, composite: composite });
+ const animation = target.animate({ [idlName]: ['10%', '50%'] },
+ { duration: 1000, composite });
testAnimationSamples(animation, idlName,
[{ time: 0, expected: 'calc(20px + 10%)' }]);
- }, property + ': units "%" onto "rem"');
+ }, `${property}: units "%" onto "rem"`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = '2em';
- var animation = target.animate({ [idlName]: ['2rem', '5rem'] },
- { duration: 1000, composite: composite });
+ const animation = target.animate({ [idlName]: ['2rem', '5rem'] },
+ { duration: 1000, composite });
testAnimationSamples(animation, idlName, [{ time: 0, expected: '40px' }]);
- }, property + ': units "rem" onto "em"');
+ }, `${property}: units "rem" onto "em"`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = '2rem';
- var animation = target.animate({ [idlName]: ['2em', '5em'] },
- { duration: 1000, composite: composite });
+ const animation = target.animate({ [idlName]: ['2em', '5em'] },
+ { duration: 1000, composite });
testAnimationSamples(animation, idlName, [{ time: 0, expected: '40px' }]);
- }, property + ': units "em" onto "rem"');
+ }, `${property}: units "em" onto "rem"`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = '10px';
- var animation = target.animate({ [idlName]: ['calc(2em + 20%)',
+ const animation = target.animate({ [idlName]: ['calc(2em + 20%)',
'calc(5rem + 50%)'] },
- { duration: 1000, composite: composite });
+ { duration: 1000, composite });
testAnimationSamples(animation, idlName,
[{ time: 0, expected: 'calc(30px + 20%)' }]);
- }, property + ': units "calc" onto "px"');
+ }, `${property}: units "calc" onto "px"`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'calc(10px + 10%)';
- var animation = target.animate({ [idlName]: ['calc(20px + 20%)',
+ const animation = target.animate({ [idlName]: ['calc(20px + 20%)',
'calc(2em + 3rem + 40%)'] },
- { duration: 1000, composite: composite });
+ { duration: 1000, composite });
testAnimationSamples(animation, idlName,
[{ time: 0, expected: 'calc(30px + 30%)' }]);
- }, property + ': calc');
+ }, `${property}: calc`);
},
testAddition: function(property, setup) {
@@ -430,26 +473,26 @@ const lengthPercentageOrCalcType = {
};
const positiveNumberType = {
- testInterpolation: function(property, setup) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: [1.1, 1.5] },
- { duration: 1000, fill: 'both' });
+ testInterpolation: (property, setup) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]: [1.1, 1.5] },
+ { duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
[{ time: 500, expected: '1.3' }]);
- }, property + ' supports animating as a positive number');
+ }, `${property} supports animating as a positive number`);
},
- testAdditionOrAccumulation: function(property, setup, composite) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ testAdditionOrAccumulation: (property, setup, composite) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 1.1;
- var animation = target.animate({ [idlName]: [1.1, 1.5] },
- { duration: 1000, composite: composite });
+ const animation = target.animate({ [idlName]: [1.1, 1.5] },
+ { duration: 1000, composite });
testAnimationSamples(animation, idlName, [{ time: 0, expected: '2.2' }]);
- }, property + ': positive number');
+ }, `${property}: positive number`);
},
testAddition: function(property, setup) {
@@ -463,35 +506,35 @@ const positiveNumberType = {
// Test using float values in the range [0, 1]
const opacityType = {
- testInterpolation: function(property, setup) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: [0.3, 0.8] },
- { duration: 1000, fill: 'both' });
+ testInterpolation: (property, setup) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]: [0.3, 0.8] },
+ { duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
[{ time: 500, expected: '0.55' }]);
- }, property + ' supports animating as a [0, 1] number');
+ }, `${property} supports animating as a [0, 1] number`);
},
- testAdditionOrAccumulation: function(property, setup, composite) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ testAdditionOrAccumulation: (property, setup, composite) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 0.3;
- var animation = target.animate({ [idlName]: [0.3, 0.8] },
- { duration: 1000, composite: composite });
+ const animation = target.animate({ [idlName]: [0.3, 0.8] },
+ { duration: 1000, composite });
testAnimationSamples(animation, idlName, [{ time: 0, expected: '0.6' }]);
- }, property + ': [0, 1] number');
+ }, `${property}: [0, 1] number`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 0.8;
- var animation = target.animate({ [idlName]: [0.3, 0.8] },
- { duration: 1000, composite: composite });
+ const animation = target.animate({ [idlName]: [0.3, 0.8] },
+ { duration: 1000, composite });
testAnimationSamples(animation, idlName, [{ time: 0, expected: '1' }]);
- }, property + ': [0, 1] number (clamped)');
+ }, `${property}: [0, 1] number (clamped)`);
},
testAddition: function(property, setup) {
@@ -504,51 +547,51 @@ const opacityType = {
};
const visibilityType = {
- testInterpolation: function(property, setup) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: ['visible', 'hidden'] },
- { duration: 1000, fill: 'both' });
+ testInterpolation: (property, setup) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]: ['visible', 'hidden'] },
+ { duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
[{ time: 0, expected: 'visible' },
{ time: 999, expected: 'visible' },
{ time: 1000, expected: 'hidden' }]);
- }, property + ' uses visibility animation when animating '
- + 'from "visible" to "hidden"');
+ }, `${property} uses visibility animation when animating`
+ + ' from "visible" to "hidden"');
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: ['hidden', 'visible'] },
- { duration: 1000, fill: 'both' });
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]: ['hidden', 'visible'] },
+ { duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
[{ time: 0, expected: 'hidden' },
{ time: 1, expected: 'visible' },
{ time: 1000, expected: 'visible' }]);
- }, property + ' uses visibility animation when animating '
- + 'from "hidden" to "visible"');
+ }, `${property} uses visibility animation when animating`
+ + ' from "hidden" to "visible"');
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: ['hidden', 'collapse'] },
- { duration: 1000, fill: 'both' });
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]: ['hidden', 'collapse'] },
+ { duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
[{ time: 0, expected: 'hidden' },
{ time: 499, expected: 'hidden' },
{ time: 500, expected: 'collapse' },
{ time: 1000, expected: 'collapse' }]);
- }, property + ' uses visibility animation when animating '
- + 'from "hidden" to "collapse"');
+ }, `${property} uses visibility animation when animating`
+ + ' from "hidden" to "collapse"');
- test(function(t) {
+ test(t => {
// Easing: http://cubic-bezier.com/#.68,-.55,.26,1.55
// With this curve, the value is less than 0 till about 34%
// also more than 1 since about 63%
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation =
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation =
target.animate({ [idlName]: ['visible', 'hidden'] },
{ duration: 1000, fill: 'both',
easing: 'cubic-bezier(0.68, -0.55, 0.26, 1.55)' });
@@ -560,34 +603,34 @@ const visibilityType = {
{ time: 620, expected: 'visible' },
{ time: 630, expected: 'hidden' },
{ time: 1000, expected: 'hidden' }]);
- }, property + ' uses visibility animation when animating '
- + 'from "visible" to "hidden" with easeInOutBack easing');
+ }, `${property} uses visibility animation when animating`
+ + ' from "visible" to "hidden" with easeInOutBack easing');
},
- testAdditionOrAccumulation: function(property, setup, composite) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ testAdditionOrAccumulation: (property, setup, composite) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'visible';
- var animation = target.animate({ [idlName]: ['visible', 'hidden'] },
- { duration: 1000, fill: 'both',
- composite: composite });
+ const animation = target.animate({ [idlName]: ['visible', 'hidden'] },
+ { duration: 1000, fill: 'both',
+ composite });
testAnimationSamples(animation, idlName,
[{ time: 0, expected: 'visible' },
{ time: 1000, expected: 'visible' }]);
- }, property + ': onto "visible"');
+ }, `${property}: onto "visible"`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'hidden';
- var animation = target.animate({ [idlName]: ['hidden', 'visible'] },
- { duration: 1000, fill: 'both',
- composite: composite });
+ const animation = target.animate({ [idlName]: ['hidden', 'visible'] },
+ { duration: 1000, fill: 'both',
+ composite });
testAnimationSamples(animation, idlName,
[{ time: 0, expected: 'hidden' },
{ time: 1000, expected: 'visible' }]);
- }, property + ': onto "hidden"');
+ }, `${property}: onto "hidden"`);
},
testAddition: function(property, setup) {
@@ -600,137 +643,153 @@ const visibilityType = {
};
const colorType = {
- testInterpolation: function(property, setup) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: ['rgb(255, 0, 0)',
- 'rgb(0, 0, 255)'] },
- 1000);
+ testInterpolation: (property, setup) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]: ['rgb(255, 0, 0)',
+ 'rgb(0, 0, 255)'] },
+ 1000);
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'rgb(128, 0, 128)' }]);
- }, property + ' supports animating as color of rgb()');
+ }, `${property} supports animating as color of rgb()`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: ['#ff0000', '#0000ff'] },
- 1000);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]: ['#ff0000', '#0000ff'] },
+ 1000);
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'rgb(128, 0, 128)' }]);
- }, property + ' supports animating as color of #RGB');
+ }, `${property} supports animating as color of #RGB`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: ['hsl(0, 100%, 50%)',
- 'hsl(240, 100%, 50%)'] },
- 1000);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]: ['hsl(0, 100%, 50%)',
+ 'hsl(240, 100%, 50%)'] },
+ 1000);
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'rgb(128, 0, 128)' }]);
- }, property + ' supports animating as color of hsl()');
+ }, `${property} supports animating as color of hsl()`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: ['#ff000066', '#0000ffcc'] },
- 1000);
- // R: 255 * (0.4 * 0.5) / 0.6 = 85
- // G: 255 * (0.8 * 0.5) / 0.6 = 170
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate(
+ { [idlName]: ['#ff000066', '#0000ffcc'] },
+ 1000
+ );
+ // R: 255 * (0.4 * 0.5) / 0.6 = 85
+ // B: 255 * (0.8 * 0.5) / 0.6 = 170
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'rgba(85, 0, 170, 0.6)' }]);
- }, property + ' supports animating as color of #RGBa');
+ }, `${property} supports animating as color of #RGBa`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: ['rgba(255, 0, 0, 0.4)',
- 'rgba(0, 0, 255, 0.8)'] },
- 1000);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate(
+ {
+ [idlName]: ['rgba(255, 0, 0, 0.4)', 'rgba(0, 0, 255, 0.8)'],
+ },
+ 1000
+ );
testAnimationSamples(animation, idlName, // Same as above.
[{ time: 500, expected: 'rgba(85, 0, 170, 0.6)' }]);
- }, property + ' supports animating as color of rgba()');
+ }, `${property} supports animating as color of rgba()`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: ['hsla(0, 100%, 50%, 0.4)',
- 'hsla(240, 100%, 50%, 0.8)'] },
- 1000);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate(
+ {
+ [idlName]: ['hsla(0, 100%, 50%, 0.4)', 'hsla(240, 100%, 50%, 0.8)'],
+ },
+ 1000
+ );
testAnimationSamples(animation, idlName, // Same as above.
[{ time: 500, expected: 'rgba(85, 0, 170, 0.6)' }]);
- }, property + ' supports animating as color of hsla()');
+ }, `${property} supports animating as color of hsla()`);
},
- testAdditionOrAccumulation: function(property, setup, composite) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ testAdditionOrAccumulation: (property, setup, composite) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'rgb(128, 128, 128)';
- var animation = target.animate({ [idlName]: ['rgb(255, 0, 0)',
- 'rgb(0, 0, 255)'] },
- { duration: 1000, composite: composite });
+ const animation = target.animate(
+ {
+ [idlName]: ['rgb(255, 0, 0)', 'rgb(0, 0, 255)'],
+ },
+ { duration: 1000, composite }
+ );
testAnimationSamples(animation, idlName,
[{ time: 0, expected: 'rgb(255, 128, 128)' },
// The value at 50% is interpolated
// from 'rgb(128+255, 128, 128)'
// to 'rgb(128, 128, 128+255)'.
{ time: 500, expected: 'rgb(255, 128, 255)' }]);
- }, property + ' supports animating as color of rgb() with overflowed ' +
- 'from and to values');
+ }, `${property} supports animating as color of rgb() with overflowed `
+ + ' from and to values');
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'rgb(128, 128, 128)';
- var animation = target.animate({ [idlName]: ['#ff0000', '#0000ff'] },
- { duration: 1000, composite: composite });
+ const animation = target.animate({ [idlName]: ['#ff0000', '#0000ff'] },
+ { duration: 1000, composite });
testAnimationSamples(animation, idlName,
[{ time: 0, expected: 'rgb(255, 128, 128)' }]);
- }, property + ' supports animating as color of #RGB');
+ }, `${property} supports animating as color of #RGB`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'rgb(128, 128, 128)';
- var animation = target.animate({ [idlName]: ['hsl(0, 100%, 50%)',
- 'hsl(240, 100%, 50%)'] },
- { duration: 1000, composite: composite });
+ const animation = target.animate({ [idlName]: ['hsl(0, 100%, 50%)',
+ 'hsl(240, 100%, 50%)'] },
+ { duration: 1000, composite });
testAnimationSamples(animation, idlName,
[{ time: 0, expected: 'rgb(255, 128, 128)' }]);
- }, property + ' supports animating as color of hsl()');
+ }, `${property} supports animating as color of hsl()`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'rgb(128, 128, 128)';
- var animation = target.animate({ [idlName]: ['#ff000066', '#0000ffcc'] },
- { duration: 1000, composite: composite });
+ const animation = target.animate(
+ { [idlName]: ['#ff000066', '#0000ffcc'] },
+ { duration: 1000, composite }
+ );
testAnimationSamples(animation, idlName,
[{ time: 0, expected: 'rgb(230, 128, 128)' }]);
- }, property + ' supports animating as color of #RGBa');
+ }, `${property} supports animating as color of #RGBa`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'rgb(128, 128, 128)';
- var animation = target.animate({ [idlName]: ['rgba(255, 0, 0, 0.4)',
- 'rgba(0, 0, 255, 0.8)'] },
- { duration: 1000, composite: composite });
+ const animation = target.animate({ [idlName]: ['rgba(255, 0, 0, 0.4)',
+ 'rgba(0, 0, 255, 0.8)'] },
+ { duration: 1000, composite });
testAnimationSamples(animation, idlName, // Same as above.
[{ time: 0, expected: 'rgb(230, 128, 128)' }]);
- }, property + ' supports animating as color of rgba()');
+ }, `${property} supports animating as color of rgba()`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'rgb(128, 128, 128)';
- var animation = target.animate({ [idlName]: ['hsla(0, 100%, 50%, 0.4)',
- 'hsla(240, 100%, 50%, 0.8)'] },
- { duration: 1000, composite: composite });
+ const animation = target.animate(
+ {
+ [idlName]: ['hsla(0, 100%, 50%, 0.4)', 'hsla(240, 100%, 50%, 0.8)'],
+ },
+ { duration: 1000, composite }
+ );
testAnimationSamples(animation, idlName, // Same as above.
[{ time: 0, expected: 'rgb(230, 128, 128)' }]);
- }, property + ' supports animating as color of hsla()');
+ }, `${property} supports animating as color of hsla()`);
},
testAddition: function(property, setup) {
@@ -743,23 +802,29 @@ const colorType = {
};
const transformListType = {
- testInterpolation: function(property, setup) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: ['translate(200px, -200px)',
- 'translate(400px, 400px)'] },
- 1000);
+ testInterpolation: (property, setup) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate(
+ {
+ [idlName]: ['translate(200px, -200px)', 'translate(400px, 400px)'],
+ },
+ 1000
+ );
testAnimationSampleMatrices(animation, idlName,
[{ time: 500, expected: [ 1, 0, 0, 1, 300, 100 ] }]);
- }, property + ': translate');
+ }, `${property}: translate`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: ['rotate(45deg)',
- 'rotate(135deg)'] },
- 1000);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate(
+ {
+ [idlName]: ['rotate(45deg)', 'rotate(135deg)'],
+ },
+ 1000
+ );
testAnimationSampleMatrices(animation, idlName,
[{ time: 500, expected: [ Math.cos(Math.PI / 2),
@@ -767,35 +832,35 @@ const transformListType = {
-Math.sin(Math.PI / 2),
Math.cos(Math.PI / 2),
0, 0] }]);
- }, property + ': rotate');
+ }, `${property}: rotate`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: ['scale(3)', 'scale(5)'] },
- 1000);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]: ['scale(3)', 'scale(5)'] },
+ 1000);
testAnimationSampleMatrices(animation, idlName,
[{ time: 500, expected: [ 4, 0, 0, 4, 0, 0 ] }]);
- }, property + ': scale');
+ }, `${property}: scale`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: ['skew(30deg, 60deg)',
- 'skew(60deg, 30deg)'] },
- 1000);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]: ['skew(30deg, 60deg)',
+ 'skew(60deg, 30deg)'] },
+ 1000);
testAnimationSampleMatrices(animation, idlName,
[{ time: 500, expected: [ 1, Math.tan(Math.PI / 4),
Math.tan(Math.PI / 4), 1,
0, 0] }]);
- }, property + ': skew');
+ }, `${property}: skew`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation =
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation =
target.animate({ [idlName]: ['translateX(100px) rotate(45deg)',
'translateX(200px) rotate(135deg)'] },
1000);
@@ -806,12 +871,12 @@ const transformListType = {
-Math.sin(Math.PI / 2),
Math.cos(Math.PI / 2),
150, 0 ] }]);
- }, property + ': rotate and translate');
+ }, `${property}: rotate and translate`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation =
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation =
target.animate({ [idlName]: ['rotate(45deg) translateX(100px)',
'rotate(135deg) translateX(200px)'] },
1000);
@@ -823,12 +888,12 @@ const transformListType = {
Math.cos(Math.PI / 2),
150 * Math.cos(Math.PI / 2),
150 * Math.sin(Math.PI / 2) ] }]);
- }, property + ': translate and rotate');
+ }, `${property}: translate and rotate`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = // matrix(0, 1, -1, 0, 0, 100)
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = // matrix(0, 1, -1, 0, 0, 100)
target.animate({ [idlName]: ['rotate(90deg) translateX(100px)',
// matrix(-1, 0, 0, -1, 200, 0)
'translateX(200px) rotate(180deg)'] },
@@ -840,12 +905,12 @@ const transformListType = {
-Math.sin(Math.PI * 3 / 4),
Math.cos(Math.PI * 3 / 4),
100, 50 ] }]);
- }, property + ': mismatch order of translate and rotate');
+ }, `${property}: mismatch order of translate and rotate`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = // Same matrices as above.
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = // Same matrices as above.
target.animate({ [idlName]: [ 'matrix(0, 1, -1, 0, 0, 100)',
'matrix(-1, 0, 0, -1, 200, 0)' ] },
1000);
@@ -856,71 +921,75 @@ const transformListType = {
-Math.sin(Math.PI * 3 / 4),
Math.cos(Math.PI * 3 / 4),
100, 50 ] }]);
- }, property + ': matrix');
+ }, `${property}: matrix`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation =
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation =
target.animate({ [idlName]: [ 'rotate3d(1, 1, 0, 0deg)',
'rotate3d(1, 1, 0, 90deg)'] },
1000);
testAnimationSampleMatrices(animation, idlName,
[{ time: 500, expected: rotate3dToMatrix(1, 1, 0, Math.PI / 4) }]);
- }, property + ': rotate3d');
+ }, `${property}: rotate3d`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
// To calculate expected matrices easily, generate input matrices from
// rotate3d.
- var from = rotate3dToMatrix3d(1, 1, 0, Math.PI / 4);
- var to = rotate3dToMatrix3d(1, 1, 0, Math.PI * 3 / 4);
- var animation =
- target.animate({ [idlName]: [ from, to ] }, 1000);
+ const from = rotate3dToMatrix3d(1, 1, 0, Math.PI / 4);
+ const to = rotate3dToMatrix3d(1, 1, 0, Math.PI * 3 / 4);
+ const animation = target.animate({ [idlName]: [ from, to ] }, 1000);
testAnimationSampleMatrices(animation, idlName,
[{ time: 500, expected: rotate3dToMatrix(1, 1, 0, Math.PI * 2 / 4) }]);
- }, property + ': matrix3d');
+ }, `${property}: matrix3d`);
// This test aims for forcing the two mismatched transforms to be
// decomposed into matrix3d before interpolation. Therefore, we not only
// test the interpolation, but also test the 3D matrix decomposition.
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation =
- target.animate({ [idlName]: ['scale(0.3)',
- // scale(0.5) translateZ(1px)
- 'matrix3d(0.5, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1)'] },
- 1000);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate(
+ {
+ [idlName]: [
+ 'scale(0.3)',
+ // scale(0.5) translateZ(1px)
+ 'matrix3d(0.5, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1)',
+ ],
+ },
+ 1000
+ );
testAnimationSampleMatrices(animation, idlName,
[{ time: 500, expected: [ 0.4, 0, 0, 0,
0, 0.4, 0, 0,
0, 0, 1, 0,
0, 0, 0.5, 1] }]);
- }, property + ': mismatched 3D transforms');
+ }, `${property}: mismatched 3D transforms`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation =
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation =
target.animate({ [idlName]: ['rotateY(60deg)', 'none' ] }, 1000);
testAnimationSampleMatrices(animation, idlName,
// rotateY(30deg) == rotate3D(0, 1, 0, 30deg)
[{ time: 500, expected: rotate3dToMatrix(0, 1, 0, Math.PI / 6) }]);
- }, property + ': rotateY');
+ }, `${property}: rotateY`);
// Following tests aim for test the fallback discrete interpolation behavior
// for non-invertible matrices. The non-invertible matrix that we use is the
- // singuler matrix, matrix(1, 1, 0, 0, 0, 100).
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation =
+ // singular matrix, matrix(1, 1, 0, 0, 0, 100).
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation =
target.animate({ [idlName]: ['matrix(-1, 0, 0, -1, 200, 0)',
'matrix( 1, 1, 0, 0, 0, 100)'] },
{ duration: 1000, fill: 'both' });
@@ -930,63 +999,75 @@ const transformListType = {
{ time: 499, expected: [ -1, 0, 0, -1, 200, 0 ] },
{ time: 500, expected: [ 1, 1, 0, 0, 0, 100 ] },
{ time: 1000, expected: [ 1, 1, 0, 0, 0, 100 ] }]);
- }, property + ': non-invertible matrices');
-
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = // matrix(0, -1, 1, 0, 250, 0)
- target.animate({ [idlName]: ['translate(50px) matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)',
- // matrix(-1, -1, 0, 0, 100, 100)
- 'translate(100px) matrix( 1, 1, 0, 0, 0, 100) rotate(180deg)'] },
- { duration: 1000, fill: 'both' });
+ }, `${property}: non-invertible matrices`);
+
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate(
+ {
+ [idlName]: [
+ // matrix(0, -1, 1, 0, 250, 0)
+ 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)',
+ // matrix(-1, -1, 0, 0, 100, 100)
+ 'translate(100px) matrix( 1, 1, 0, 0, 0, 100) rotate(180deg)',
+ ],
+ },
+ { duration: 1000, fill: 'both' }
+ );
testAnimationSampleMatrices(animation, idlName,
[ { time: 0, expected: [ 0, -1, 1, 0, 250, 0 ] },
{ time: 499, expected: [ 0, -1, 1, 0, 250, 0 ] },
{ time: 500, expected: [ -1, -1, 0, 0, 100, 100 ] },
{ time: 1000, expected: [ -1, -1, 0, 0, 100, 100 ] }]);
- }, property + ': non-invertible matrices in matched transform lists');
-
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = // matrix(-2, 0, 0, -2, 250, 0)
- target.animate({ [idlName]: ['translate(50px) matrix(-1, 0, 0, -1, 200, 0) scale(2)',
- // matrix(1, 1, 1, 1, 100, 100)
- 'translate(100px) matrix( 1, 1, 0, 0, 0, 100) skew(45deg)'] },
- { duration: 1000, fill: 'both' });
+ }, `${property}: non-invertible matrices in matched transform lists`);
+
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate(
+ {
+ [idlName]: [
+ // matrix(-2, 0, 0, -2, 250, 0)
+ 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) scale(2)',
+ // matrix(1, 1, 1, 1, 100, 100)
+ 'translate(100px) matrix( 1, 1, 0, 0, 0, 100) skew(45deg)',
+ ],
+ },
+ { duration: 1000, fill: 'both' }
+ );
testAnimationSampleMatrices(animation, idlName,
[ { time: 0, expected: [ -2, 0, 0, -2, 250, 0 ] },
{ time: 499, expected: [ -2, 0, 0, -2, 250, 0 ] },
{ time: 500, expected: [ 1, 1, 1, 1, 100, 100 ] },
{ time: 1000, expected: [ 1, 1, 1, 1, 100, 100 ] }]);
- }, property + ': non-invertible matrices in mismatched transform lists');
+ }, `${property}: non-invertible matrices in mismatched transform lists`);
},
testAddition: function(property, setup) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'translateX(100px)';
- var animation = target.animate({ [idlName]: ['translateX(-200px)',
- 'translateX(500px)'] },
- { duration: 1000, fill: 'both',
- composite: 'add' });
+ const animation = target.animate({ [idlName]: ['translateX(-200px)',
+ 'translateX(500px)'] },
+ { duration: 1000, fill: 'both',
+ composite: 'add' });
testAnimationSampleMatrices(animation, idlName,
[ { time: 0, expected: [ 1, 0, 0, 1, -100, 0 ] },
{ time: 1000, expected: [ 1, 0, 0, 1, 600, 0 ] }]);
- }, property + ': translate');
+ }, `${property}: translate`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'rotate(45deg)';
- var animation = target.animate({ [idlName]: ['rotate(-90deg)',
- 'rotate(90deg)'] },
- { duration: 1000, fill: 'both',
- composite: 'add' });
+ const animation = target.animate({ [idlName]: ['rotate(-90deg)',
+ 'rotate(90deg)'] },
+ { duration: 1000, fill: 'both',
+ composite: 'add' });
testAnimationSampleMatrices(animation, idlName,
[{ time: 0, expected: [ Math.cos(-Math.PI / 4),
@@ -999,27 +1080,27 @@ const transformListType = {
-Math.sin(Math.PI * 3 / 4),
Math.cos(Math.PI * 3 / 4),
0, 0] }]);
- }, property + ': rotate');
+ }, `${property}: rotate`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'scale(2)';
- var animation = target.animate({ [idlName]: ['scale(-3)', 'scale(5)'] },
- { duration: 1000, fill: 'both',
- composite: 'add' });
+ const animation = target.animate({ [idlName]: ['scale(-3)', 'scale(5)'] },
+ { duration: 1000, fill: 'both',
+ composite: 'add' });
testAnimationSampleMatrices(animation, idlName,
[{ time: 0, expected: [ -6, 0, 0, -6, 0, 0 ] }, // scale(-3) scale(2)
{ time: 1000, expected: [ 10, 0, 0, 10, 0, 0 ] }]); // scale(5) scale(2)
- }, property + ': scale');
+ }, `${property}: scale`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
// matrix(1, tan(10deg), tan(10deg), 1)
target.style[idlName] = 'skew(10deg, 10deg)';
- var animation = // matrix(1, tan(20deg), tan(-30deg), 1)
+ const animation = // matrix(1, tan(20deg), tan(-30deg), 1)
target.animate({ [idlName]: ['skew(-30deg, 20deg)',
// matrix(1, tan(-30deg), tan(20deg), 1)
'skew(20deg, -30deg)'] },
@@ -1050,14 +1131,14 @@ const transformListType = {
Math.tan(Math.PI/9) + Math.tan(Math.PI/18),
1 + Math.tan(Math.PI/18) * Math.tan(Math.PI/9),
0, 0] }]);
- }, property + ': skew');
+ }, `${property}: skew`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
// matrix(1, 0, 0, 1, 100, 0)
target.style[idlName] = 'translateX(100px)';
- var animation = // matrix(0, 1, -1, 0, 0, 0)
+ const animation = // matrix(0, 1, -1, 0, 0, 0)
target.animate({ [idlName]: ['rotate(90deg)',
// matrix(-1, 0, 0, -1, 0, 0)
'rotate(180deg)'] },
@@ -1066,14 +1147,14 @@ const transformListType = {
testAnimationSampleMatrices(animation, idlName,
[{ time: 0, expected: [ 0, 1, -1, 0, 100, 0 ] },
{ time: 1000, expected: [ -1, 0, 0, -1, 100, 0 ] }]);
- }, property + ': rotate on translate');
+ }, `${property}: rotate on translate`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
// matrix(0, 1, -1, 0, 0, 0)
target.style[idlName] = 'rotate(90deg)';
- var animation = // matrix(1, 0, 0, 1, 100, 0)
+ const animation = // matrix(1, 0, 0, 1, 100, 0)
target.animate({ [idlName]: ['translateX(100px)',
// matrix(1, 0, 0, 1, 200, 0)
'translateX(200px)'] },
@@ -1082,13 +1163,13 @@ const transformListType = {
testAnimationSampleMatrices(animation, idlName,
[{ time: 0, expected: [ 0, 1, -1, 0, 0, 100 ] },
{ time: 1000, expected: [ 0, 1, -1, 0, 0, 200 ] }]);
- }, property + ': translate on rotate');
+ }, `${property}: translate on rotate`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'matrix(0, 1, -1, 0, 0, 0)';
- var animation = // Same matrices as above.
+ const animation = // Same matrices as above.
target.animate({ [idlName]: [ 'matrix(1, 0, 0, 1, 100, 0)',
'matrix(1, 0, 0, 1, 200, 0)' ] },
{ duration: 1000, fill: 'both', composite: 'add' });
@@ -1096,13 +1177,13 @@ const transformListType = {
testAnimationSampleMatrices(animation, idlName,
[{ time: 0, expected: [ 0, 1, -1, 0, 0, 100 ] },
{ time: 1000, expected: [ 0, 1, -1, 0, 0, 200 ] }]);
- }, property + ': matrix');
+ }, `${property}: matrix`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'rotate3d(1, 1, 0, 45deg)';
- var animation =
+ const animation =
target.animate({ [idlName]: [ 'rotate3d(1, 1, 0, -90deg)',
'rotate3d(1, 1, 0, 90deg)'] },
{ duration: 1000, fill: 'both', composite: 'add' });
@@ -1110,35 +1191,35 @@ const transformListType = {
testAnimationSampleMatrices(animation, idlName,
[{ time: 0, expected: rotate3dToMatrix(1, 1, 0, -Math.PI / 4) },
{ time: 1000, expected: rotate3dToMatrix(1, 1, 0, 3 * Math.PI / 4) }]);
- }, property + ': rotate3d');
+ }, `${property}: rotate3d`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
// To calculate expected matrices easily, generate input matrices from
// rotate3d.
target.style[idlName] = rotate3dToMatrix3d(1, 1, 0, Math.PI / 4);
- var from = rotate3dToMatrix3d(1, 1, 0, -Math.PI / 2);
- var to = rotate3dToMatrix3d(1, 1, 0, Math.PI / 2);
- var animation =
+ const from = rotate3dToMatrix3d(1, 1, 0, -Math.PI / 2);
+ const to = rotate3dToMatrix3d(1, 1, 0, Math.PI / 2);
+ const animation =
target.animate({ [idlName]: [ from, to ] },
{ duration: 1000, fill: 'both', composite: 'add' });
testAnimationSampleMatrices(animation, idlName,
[{ time: 0, expected: rotate3dToMatrix(1, 1, 0, -Math.PI / 4) },
{ time: 1000, expected: rotate3dToMatrix(1, 1, 0, 3 * Math.PI / 4) }]);
- }, property + ': matrix3d');
+ }, `${property}: matrix3d`);
// Following tests aim for test the addition behavior for non-invertible
// matrices. Note that the addition for non-invertible matrices should be
// the same, just like addition for invertible matrices. With these tests,
// we can assure that addition never behaves as discrete. The non-invertible
- // matrix that we use is the singuler matrix, matrix(1, 1, 0, 0, 0, 100).
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ // matrix that we use is the singular matrix, matrix(1, 1, 0, 0, 0, 100).
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'translateX(50px)';
- var animation =
+ const animation =
target.animate({ [idlName]: ['matrix(-1, 0, 0, -1, 200, 0)',
'matrix( 1, 1, 0, 0, 0, 100)'] },
{ duration: 1000, fill: 'both', composite: 'add' });
@@ -1146,13 +1227,13 @@ const transformListType = {
testAnimationSampleMatrices(animation, idlName,
[ { time: 0, expected: [ -1, 0, 0, -1, 250, 0 ] },
{ time: 1000, expected: [ 1, 1, 0, 0, 50, 100 ] }]);
- }, property + ': non-invertible matrices');
+ }, `${property}: non-invertible matrices`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'translateX(50px)';
- var animation = // matrix(0, -1, 1, 0, 200, 0)
+ const animation = // matrix(0, -1, 1, 0, 200, 0)
target.animate({ [idlName]: ['matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)',
// matrix(-1, -1, 0, 0, 0, 100)
'matrix( 1, 1, 0, 0, 0, 100) rotate(180deg)'] },
@@ -1161,13 +1242,13 @@ const transformListType = {
testAnimationSampleMatrices(animation, idlName,
[ { time: 0, expected: [ 0, -1, 1, 0, 250, 0 ] },
{ time: 1000, expected: [ -1, -1, 0, 0, 50, 100 ] }]);
- }, property + ': non-invertible matrices in matched transform lists');
+ }, `${property}: non-invertible matrices in matched transform lists`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'translateX(50px)';
- var animation = // matrix(-2, 0, 0, -2, 200, 0)
+ const animation = // matrix(-2, 0, 0, -2, 200, 0)
target.animate({ [idlName]: ['matrix(-1, 0, 0, -1, 200, 0) scale(2)',
// matrix(1, 1, 1, 1, 0, 100)
'matrix( 1, 1, 0, 0, 0, 100) skew(45deg)'] },
@@ -1176,28 +1257,28 @@ const transformListType = {
testAnimationSampleMatrices(animation, idlName,
[ { time: 0, expected: [ -2, 0, 0, -2, 250, 0 ] },
{ time: 1000, expected: [ 1, 1, 1, 1, 50, 100 ] }]);
- }, property + ': non-invertible matrices in mismatched transform lists');
+ }, `${property}: non-invertible matrices in mismatched transform lists`);
},
testAccumulation: function(property, setup) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'translateX(100px)';
- var animation = target.animate({ [idlName]: ['translateX(-200px)',
+ const animation = target.animate({ [idlName]: ['translateX(-200px)',
'translateX(500px)'] },
{ duration: 1000, fill: 'both',
composite: 'accumulate' });
testAnimationSampleMatrices(animation, idlName,
[ { time: 0, expected: [ 1, 0, 0, 1, -100, 0 ] },
{ time: 1000, expected: [ 1, 0, 0, 1, 600, 0 ] }]);
- }, property + ': translate');
+ }, `${property}: translate`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'rotate(45deg)';
- var animation = target.animate({ [idlName]: ['rotate(-90deg)',
+ const animation = target.animate({ [idlName]: ['rotate(-90deg)',
'rotate(90deg)'] },
{ duration: 1000, fill: 'both',
composite: 'accumulate' });
@@ -1213,13 +1294,13 @@ const transformListType = {
-Math.sin(Math.PI * 3 / 4),
Math.cos(Math.PI * 3 / 4),
0, 0] }]);
- }, property + ': rotate');
+ }, `${property}: rotate`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'scale(2)';
- var animation = target.animate({ [idlName]: ['scale(-3)', 'scale(5)'] },
+ const animation = target.animate({ [idlName]: ['scale(-3)', 'scale(5)'] },
{ duration: 1000, fill: 'both',
composite: 'accumulate' });
@@ -1228,14 +1309,14 @@ const transformListType = {
[{ time: 0, expected: [ -2, 0, 0, -2, 0, 0 ] },
// scale((2 - 1) + (5 - 1) + 1)
{ time: 1000, expected: [ 6, 0, 0, 6, 0, 0 ] }]);
- }, property + ': scale');
+ }, `${property}: scale`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
// matrix(1, tan(10deg), tan(10deg), 1)
target.style[idlName] = 'skew(10deg, 10deg)';
- var animation = // matrix(1, tan(20deg), tan(-30deg), 1)
+ const animation = // matrix(1, tan(20deg), tan(-30deg), 1)
target.animate({ [idlName]: ['skew(-30deg, 20deg)',
// matrix(1, tan(-30deg), tan(20deg), 1)
'skew(20deg, -30deg)'] },
@@ -1248,14 +1329,14 @@ const transformListType = {
{ time: 1000, expected: [ 1, Math.tan(-Math.PI/9),
Math.tan(Math.PI/6), 1,
0, 0] }]);
- }, property + ': skew');
+ }, `${property}: skew`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
// matrix(1, 0, 0, 1, 100, 0)
target.style[idlName] = 'translateX(100px)';
- var animation = // matrix(0, 1, -1, 0, 0, 0)
+ const animation = // matrix(0, 1, -1, 0, 0, 0)
target.animate({ [idlName]: ['rotate(90deg)',
// matrix(-1, 0, 0, -1, 0, 0)
'rotate(180deg)'] },
@@ -1264,14 +1345,14 @@ const transformListType = {
testAnimationSampleMatrices(animation, idlName,
[{ time: 0, expected: [ 0, 1, -1, 0, 100, 0 ] },
{ time: 1000, expected: [ -1, 0, 0, -1, 100, 0 ] }]);
- }, property + ': rotate on translate');
+ }, `${property}: rotate on translate`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
// matrix(0, 1, -1, 0, 0, 0)
target.style[idlName] = 'rotate(90deg)';
- var animation = // matrix(1, 0, 0, 1, 100, 0)
+ const animation = // matrix(1, 0, 0, 1, 100, 0)
target.animate({ [idlName]: ['translateX(100px)',
// matrix(1, 0, 0, 1, 200, 0)
'translateX(200px)'] },
@@ -1280,13 +1361,13 @@ const transformListType = {
testAnimationSampleMatrices(animation, idlName,
[{ time: 0, expected: [ 0, 1, -1, 0, 100, 0 ] },
{ time: 1000, expected: [ 0, 1, -1, 0, 200, 0 ] }]);
- }, property + ': translate on rotate');
+ }, `${property}: translate on rotate`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'matrix(0, 1, -1, 0, 0, 0)';
- var animation = // Same matrices as above.
+ const animation = // Same matrices as above.
target.animate({ [idlName]: [ 'matrix(1, 0, 0, 1, 100, 0)',
'matrix(1, 0, 0, 1, 200, 0)' ] },
{ duration: 1000, fill: 'both', composite: 'accumulate' });
@@ -1294,13 +1375,13 @@ const transformListType = {
testAnimationSampleMatrices(animation, idlName,
[{ time: 0, expected: [ 0, 1, -1, 0, 100, 0 ] },
{ time: 1000, expected: [ 0, 1, -1, 0, 200, 0 ] }]);
- }, property + ': matrix');
+ }, `${property}: matrix`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'rotate3d(1, 1, 0, 45deg)';
- var animation =
+ const animation =
target.animate({ [idlName]: [ 'rotate3d(1, 1, 0, -90deg)',
'rotate3d(1, 1, 0, 90deg)'] },
{ duration: 1000, fill: 'both', composite: 'accumulate' });
@@ -1308,170 +1389,240 @@ const transformListType = {
testAnimationSampleMatrices(animation, idlName,
[{ time: 0, expected: rotate3dToMatrix(1, 1, 0, -Math.PI / 4) },
{ time: 1000, expected: rotate3dToMatrix(1, 1, 0, 3 * Math.PI / 4) }]);
- }, property + ': rotate3d');
+ }, `${property}: rotate3d`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
// To calculate expected matrices easily, generate input matrices from
// rotate3d.
target.style[idlName] = rotate3dToMatrix3d(1, 1, 0, Math.PI / 4);
- var from = rotate3dToMatrix3d(1, 1, 0, -Math.PI / 2);
- var to = rotate3dToMatrix3d(1, 1, 0, Math.PI / 2);
- var animation =
+ const from = rotate3dToMatrix3d(1, 1, 0, -Math.PI / 2);
+ const to = rotate3dToMatrix3d(1, 1, 0, Math.PI / 2);
+ const animation =
target.animate({ [idlName]: [ from, to ] },
{ duration: 1000, fill: 'both', composite: 'accumulate' });
testAnimationSampleMatrices(animation, idlName,
[{ time: 0, expected: rotate3dToMatrix(1, 1, 0, -Math.PI / 4) },
{ time: 1000, expected: rotate3dToMatrix(1, 1, 0, 3 * Math.PI / 4) }]);
- }, property + ': matrix3d');
+ }, `${property}: matrix3d`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var matrixArray = [ 1, 0, 0, 0,
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const matrixArray = [ 1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 1, 1 ];
target.style[idlName] = createMatrixFromArray(matrixArray);
- var animation =
+ const animation =
target.animate({ [idlName]: [ 'none', 'none' ] },
{ duration: 1000, fill: 'both', composite: 'accumulate' });
testAnimationSampleMatrices(animation, idlName,
[{ time: 0, expected: matrixArray },
{ time: 1000, expected: matrixArray }]);
- }, property + ': none');
+ }, `${property}: none`);
// Following tests aim for test the fallback discrete accumulation behavior
// for non-invertible matrices. The non-invertible matrix that we use is the
- // singuler matrix, matrix(1, 1, 0, 0, 0, 100).
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ // singular matrix, matrix(1, 1, 0, 0, 0, 100).
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.animate({ [idlName]: ['matrix(-1, 0, 0, -1, 200, 0)',
'matrix(-1, 0, 0, -1, 200, 0)'] }, 1000);
- var animation = target.animate({ [idlName]: ['matrix( 1, 1, 0, 0, 0, 100)',
- 'matrix( 1, 1, 0, 0, 0, 100)'] },
- { duration: 1000, composite: 'accumulate' });
- testAnimationSampleMatrices(animation, idlName,
- [{ time: 0, expected: [ 1, 1, 0, 0, 0, 100 ] }]);
- }, property + ': non-invertible matrices (non-invertible onto invertible)');
+ const animation = target.animate(
+ {
+ [idlName]: [
+ 'matrix( 1, 1, 0, 0, 0, 100)',
+ 'matrix( 1, 1, 0, 0, 0, 100)',
+ ],
+ },
+ { duration: 1000, composite: 'accumulate' }
+ );
+ testAnimationSampleMatrices(animation, idlName, [
+ { time: 0, expected: [1, 1, 0, 0, 0, 100] },
+ ]);
+ }, `${property}: non-invertible matrices (non-invertible onto invertible)`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.animate({ [idlName]: ['matrix( 1, 1, 0, 0, 0, 100)',
'matrix( 1, 1, 0, 0, 0, 100)'] }, 1000);
- var animation = target.animate({ [idlName]: ['matrix(-1, 0, 0, -1, 200, 0)',
- 'matrix(-1, 0, 0, -1, 200, 0)'] },
- { duration: 1000, composite: 'accumulate' });
- testAnimationSampleMatrices(animation, idlName,
- [{ time: 0, expected: [ -1, 0, 0, -1, 200, 0 ] }]);
- }, property + ': non-invertible matrices (invertible onto non-invertible)');
-
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- // matrix(0, -1, 1, 0, 250, 0)
- target.animate({ [idlName]: ['translate(50px) matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)',
- 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)'] }, 1000);
- var animation = // matrix(-1, -1, 0, 0, 100, 100)
- target.animate({ [idlName]: ['translate(100px) matrix( 1, 1, 0, 0, 0, 100) rotate(180deg)',
- 'translate(100px) matrix( 1, 1, 0, 0, 0, 100) rotate(180deg)'] },
- { duration: 1000, composite: 'accumulate' });
- testAnimationSampleMatrices(animation, idlName,
- [{ time: 0, expected: [ -1, -1, 0, 0, 100, 100 ] }]);
- }, property + ': non-invertible matrices in matched transform lists (non-invertible onto invertible)');
-
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- // matrix(-1, -1, 0, 0, 100, 100)
- target.animate({ [idlName]: ['translate(100px) matrix(1, 1, 0, 0, 0, 100) rotate(180deg)',
- 'translate(100px) matrix(1, 1, 0, 0, 0, 100) rotate(180deg)'] }, 1000);
- var animation = // matrix(0, -1, 1, 0, 250, 0)
- target.animate({ [idlName]: ['translate(50px) matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)',
- 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)'] },
- { duration: 1000, composite: 'accumulate' });
- testAnimationSampleMatrices(animation, idlName,
- [{ time: 0, expected: [ 0, -1, 1, 0, 250, 0 ] }]);
- }, property + ': non-invertible matrices in matched transform lists (invertible onto non-invertible)');
-
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- // matrix(-2, 0, 0, -2, 250, 0)
- target.animate({ [idlName]: ['translate(50px) matrix(-1, 0, 0, -1, 200, 0) scale(2)',
- 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) scale(2)'] }, 1000);
- var animation = // matrix(1, 1, 1, 1, 100, 100)
- target.animate({ [idlName]: ['translate(100px) matrix(1, 1, 0, 0, 0, 100) skew(45deg)',
- 'translate(100px) matrix(1, 1, 0, 0, 0, 100) skew(45deg)'] },
- { duration: 1000, composite: 'accumulate' });
- testAnimationSampleMatrices(animation, idlName,
- [{ time: 0, expected: [ 1, 1, 1, 1, 100, 100 ] }]);
- }, property + ': non-invertible matrices in mismatched transform lists' +
- ' (non-invertible onto invertible)');
-
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- // matrix(1, 1, 1, 1, 100, 100)
- target.animate({ [idlName]: ['translate(100px) matrix(1, 1, 0, 0, 0, 100) skew(45deg)',
- 'translate(100px) matrix(1, 1, 0, 0, 0, 100) skew(45deg)'] }, 1000);
- var animation = // matrix(-2, 0, 0, -2, 250, 0)
- target.animate({ [idlName]: ['translate(50px) matrix(-1, 0, 0, -1, 200, 0) scale(2)',
- 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) scale(2)'] },
- { duration: 1000, composite: 'accumulate' });
- testAnimationSampleMatrices(animation, idlName,
- [{ time: 0, expected: [ -2, 0, 0, -2, 250, 0 ] }]);
- }, property + ': non-invertible matrices in mismatched transform lists' +
- ' (invertible onto non-invertible)');
+ const animation = target.animate(
+ {
+ [idlName]: [
+ 'matrix(-1, 0, 0, -1, 200, 0)',
+ 'matrix(-1, 0, 0, -1, 200, 0)',
+ ],
+ },
+ { duration: 1000, composite: 'accumulate' }
+ );
+ testAnimationSampleMatrices(animation, idlName, [
+ { time: 0, expected: [-1, 0, 0, -1, 200, 0] },
+ ]);
+ }, `${property}: non-invertible matrices (invertible onto non-invertible)`);
+
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ // matrix(0, -1, 1, 0, 250, 0)
+ target.animate(
+ {
+ [idlName]: [
+ 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)',
+ 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)',
+ ],
+ },
+ 1000
+ );
+ // matrix(-1, -1, 0, 0, 100, 100)
+ const animation = target.animate(
+ {
+ [idlName]: [
+ 'translate(100px) matrix( 1, 1, 0, 0, 0, 100) rotate(180deg)',
+ 'translate(100px) matrix( 1, 1, 0, 0, 0, 100) rotate(180deg)',
+ ],
+ },
+ { duration: 1000, composite: 'accumulate' }
+ );
+ testAnimationSampleMatrices(animation, idlName, [
+ { time: 0, expected: [-1, -1, 0, 0, 100, 100] },
+ ]);
+ }, `${property}: non-invertible matrices in matched transform lists (non-invertible onto invertible)`);
+
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ // matrix(-1, -1, 0, 0, 100, 100)
+ target.animate(
+ {
+ [idlName]: [
+ 'translate(100px) matrix(1, 1, 0, 0, 0, 100) rotate(180deg)',
+ 'translate(100px) matrix(1, 1, 0, 0, 0, 100) rotate(180deg)',
+ ],
+ },
+ 1000
+ );
+ // matrix(0, -1, 1, 0, 250, 0)
+ const animation = target.animate(
+ {
+ [idlName]: [
+ 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)',
+ 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) rotate(90deg)',
+ ],
+ },
+ { duration: 1000, composite: 'accumulate' }
+ );
+ testAnimationSampleMatrices(animation, idlName, [
+ { time: 0, expected: [0, -1, 1, 0, 250, 0] },
+ ]);
+ }, `${property}: non-invertible matrices in matched transform lists (invertible onto non-invertible)`);
+
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ // matrix(-2, 0, 0, -2, 250, 0)
+ target.animate(
+ {
+ [idlName]: [
+ 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) scale(2)',
+ 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) scale(2)',
+ ],
+ },
+ 1000
+ );
+ // matrix(1, 1, 1, 1, 100, 100)
+ const animation = target.animate(
+ {
+ [idlName]: [
+ 'translate(100px) matrix(1, 1, 0, 0, 0, 100) skew(45deg)',
+ 'translate(100px) matrix(1, 1, 0, 0, 0, 100) skew(45deg)',
+ ],
+ },
+ { duration: 1000, composite: 'accumulate' }
+ );
+ testAnimationSampleMatrices(animation, idlName, [
+ { time: 0, expected: [1, 1, 1, 1, 100, 100] },
+ ]);
+ }, `${property}: non-invertible matrices in mismatched transform lists`
+ + ' (non-invertible onto invertible)');
+
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ // matrix(1, 1, 1, 1, 100, 100)
+ target.animate(
+ {
+ [idlName]: [
+ 'translate(100px) matrix(1, 1, 0, 0, 0, 100) skew(45deg)',
+ 'translate(100px) matrix(1, 1, 0, 0, 0, 100) skew(45deg)',
+ ],
+ },
+ 1000
+ );
+ // matrix(-2, 0, 0, -2, 250, 0)
+ const animation = target.animate(
+ {
+ [idlName]: [
+ 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) scale(2)',
+ 'translate(50px) matrix(-1, 0, 0, -1, 200, 0) scale(2)',
+ ],
+ },
+ { duration: 1000, composite: 'accumulate' }
+ );
+ testAnimationSampleMatrices(animation, idlName, [
+ { time: 0, expected: [-2, 0, 0, -2, 250, 0] },
+ ]);
+ }, `${property}: non-invertible matrices in mismatched transform lists`
+ + ' (invertible onto non-invertible)');
},
};
const filterListType = {
- testInterpolation: function(property, setup) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]:
- ['blur(10px)', 'blur(50px)'] },
- 1000);
+ testInterpolation: (property, setup) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]:
+ ['blur(10px)', 'blur(50px)'] },
+ 1000);
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'blur(30px)' }]);
- }, property + ': blur function' );
+ }, `${property}: blur function`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: ['hue-rotate(0deg)',
- 'hue-rotate(100deg)'] },
- 1000);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]: ['hue-rotate(0deg)',
+ 'hue-rotate(100deg)'] },
+ 1000);
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'hue-rotate(50deg)' }]);
- }, property + ': hue-rotate function with same unit(deg)' );
+ }, `${property}: hue-rotate function with same unit(deg)`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: ['hue-rotate(10deg)',
- 'hue-rotate(100rad)'] },
- 1000);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]: ['hue-rotate(10deg)',
+ 'hue-rotate(100rad)'] },
+ 1000);
// 10deg = 0.1745rad.
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'hue-rotate(50.0873rad)' }]);
- }, property + ': hue-rotate function with different unit(deg -> rad)');
+ }, `${property}: hue-rotate function with different unit(deg -> rad)`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate(
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate(
{ [idlName]:
['drop-shadow(10px 10px 10px rgba(255, 0, 0, 0.4))',
'drop-shadow(50px 50px 50px rgba(0, 0, 255, 0.8))'] },
@@ -1481,12 +1632,12 @@ const filterListType = {
animation, idlName,
[{ time: 500,
expected: 'drop-shadow(rgba(85, 0, 170, 0.6) 30px 30px 30px)' }]);
- }, property + ': drop-shadow function' );
+ }, `${property}: drop-shadow function`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate(
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate(
{ [idlName]:
['brightness(0.1) contrast(0.1) grayscale(0.1) invert(0.1) ' +
'opacity(0.1) saturate(0.1) sepia(0.1)',
@@ -1498,13 +1649,13 @@ const filterListType = {
[{ time: 500,
expected: 'brightness(0.3) contrast(0.3) grayscale(0.3) ' +
'invert(0.3) opacity(0.3) saturate(0.3) sepia(0.3)' }]);
- }, property + ': percentage or numeric-specifiable functions' +
- '(number value)');
+ }, `${property}: percentage or numeric-specifiable functions`
+ + ' (number value)');
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate(
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate(
{ [idlName]:
['brightness(10%) contrast(10%) grayscale(10%) invert(10%) ' +
'opacity(10%) saturate(10%) sepia(10%)',
@@ -1516,13 +1667,13 @@ const filterListType = {
[{ time: 500,
expected: 'brightness(0.3) contrast(0.3) grayscale(0.3) ' +
'invert(0.3) opacity(0.3) saturate(0.3) sepia(0.3)' }]);
- }, property + ': percentage or numeric-specifiable functions' +
- '(percentage value)');
+ }, `${property}: percentage or numeric-specifiable functions`
+ + ' (percentage value)');
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate(
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate(
{ [idlName]:
// To make missing filter-function-lists, specified the grayscale.
['grayscale(0)',
@@ -1533,13 +1684,13 @@ const filterListType = {
[{ time: 500,
expected: 'grayscale(0.5) brightness(0.5) contrast(0.5) ' +
'opacity(0.5) saturate(0.5)' }]);
- }, property + ': interpolate different length of filter-function-list ' +
- ' with function which lacuna value is 1');
+ }, `${property}: interpolate different length of filter-function-list`
+ + ' with function which lacuna value is 1');
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate(
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate(
{ [idlName]:
// To make missing filter-function-lists, specified the opacity.
['opoacity(1)',
@@ -1550,14 +1701,14 @@ const filterListType = {
[{ time: 500,
expected:
'opacity(0.5) grayscale(0.5) invert(0.5) sepia(0.5) blur(5px)' }]);
- }, property + ': interpolate different length of filter-function-list ' +
- ' with function which lacuna value is 0');
+ }, `${property}: interpolate different length of filter-function-list`
+ + ' with function which lacuna value is 0');
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style.color = "rgba(255, 0, 0, 0.4)";
- var animation = target.animate(
+ const animation = target.animate(
{ [idlName]:
['blur(0px)',
'blur(10px) drop-shadow(10px 10px 10px rgba(0, 0, 255, 0.8))'] },
@@ -1568,23 +1719,23 @@ const filterListType = {
// The lacuna value of drop-shadow's color is taken from
// the color property.
expected: 'blur(5px) drop-shadow(rgba(85, 0, 170, 0.6) 5px 5px 5px' }]);
- }, property + ': interpolate different length of filter-function-list ' +
- 'with drop-shadow function');
+ }, `${property}: interpolate different length of filter-function-list`
+ + ' with drop-shadow function');
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: ['none', 'blur(10px)'] },
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]: ['none', 'blur(10px)'] },
1000);
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'blur(5px)' }]);
- }, property + ': interpolate from none');
+ }, `${property}: interpolate from none`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate(
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate(
{ [idlName]:
['blur(0px) url(\"#f1\")',
'blur(10px) url(\"#f2\")']},
@@ -1592,103 +1743,115 @@ const filterListType = {
testAnimationSamples(animation, idlName,
[{ time: 499, expected: 'blur(0px) url(\"#f1\")' },
{ time: 500, expected: 'blur(10px) url(\"#f2\")' }]);
- }, property + ': url function (interpoalte as discrete)');
+ }, `${property}: url function (interpoalte as discrete)`);
},
testAddition: function(property, setup) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'blur(10px)';
- var animation = target.animate({ [idlName]: ['blur(20px)',
- 'blur(50px)'] },
- { duration: 1000, composite: 'add' });
+ const animation = target.animate({ [idlName]: ['blur(20px)',
+ 'blur(50px)'] },
+ { duration: 1000, composite: 'add' });
testAnimationSamples(animation, idlName,
[ { time: 0, expected: 'blur(10px) blur(20px)' }]);
- }, property + ': blur on blur');
+ }, `${property}: blur on blur`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'blur(10px)';
- var animation = target.animate({ [idlName]: ['brightness(80%)',
- 'brightness(40%)'] },
- { duration: 1000, composite: 'add' });
+ const animation = target.animate({ [idlName]: ['brightness(80%)',
+ 'brightness(40%)'] },
+ { duration: 1000, composite: 'add' });
testAnimationSamples(animation, idlName,
[ { time: 0, expected: 'blur(10px) brightness(0.8)' }]);
- }, property + ': different filter functions');
+ }, `${property}: different filter functions`);
},
testAccumulation: function(property, setup) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'blur(10px) brightness(0.3)';
- var animation = target.animate({ [idlName]: ['blur(20px) brightness(0.1)',
- 'blur(20px) brightness(0.1)'] },
- { duration: 1000, composite: 'accumulate' });
+ const animation = target.animate(
+ {
+ [idlName]: [
+ 'blur(20px) brightness(0.1)',
+ 'blur(20px) brightness(0.1)',
+ ],
+ },
+ { duration: 1000, composite: 'accumulate' }
+ );
// brightness(0.1) onto brightness(0.3) means
// brightness((0.1 - 1.0) + (0.3 - 1.0) + 1.0). The result of this formula
// is brightness(-0.6) that means brightness(0.0).
testAnimationSamples(animation, idlName,
[ { time: 0, expected: 'blur(30px) brightness(0)' }]);
- }, property + ': same ordered filter functions');
+ }, `${property}: same ordered filter functions`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'blur(10px) brightness(1.3)';
- var animation = target.animate({ [idlName]: ['brightness(1.2) blur(20px)',
- 'brightness(1.2) blur(20px)'] },
- { duration: 1000, composite: 'accumulate' });
+ const animation = target.animate(
+ {
+ [idlName]: [
+ 'brightness(1.2) blur(20px)',
+ 'brightness(1.2) blur(20px)',
+ ],
+ },
+ { duration: 1000, composite: 'accumulate' }
+ );
// Mismatched ordered functions can't be accumulated.
testAnimationSamples(animation, idlName,
[ { time: 0, expected: 'brightness(1.2) blur(20px)' }]);
- }, property + ': mismatched ordered filter functions');
+ }, `${property}: mismatched ordered filter functions`);
},
};
const textShadowListType = {
- testInterpolation: function(property, setup) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation =
+ testInterpolation: (property, setup) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation =
target.animate({ [idlName]: [ 'none',
'rgb(100, 100, 100) 10px 10px 10px'] },
{ duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
// Premultiplied
[{ time: 500, expected: 'rgba(100, 100, 100, 0.5) 5px 5px 5px' }]);
- }, property + ': from none to other');
+ }, `${property}: from none to other`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation =
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation =
target.animate({ [idlName]: [ 'rgb(100, 100, 100) 10px 10px 10px',
'none' ] },
{ duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
// Premultiplied
[{ time: 500, expected: 'rgba(100, 100, 100, 0.5) 5px 5px 5px' }]);
- }, property + ': from other to none');
+ }, `${property}: from other to none`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation =
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation =
target.animate({ [idlName]: [ 'rgb(0, 0, 0) 0px 0px 0px',
'rgb(100, 100, 100) 10px 10px 10px'] },
{ duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'rgb(50, 50, 50) 5px 5px 5px' }]);
- }, property + ': single shadow');
+ }, `${property}: single shadow`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation =
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation =
target.animate({ [idlName]: [ 'rgb(0, 0, 0) 0px 0px 0px, '
+ 'rgb(200, 200, 200) 20px 20px 20px',
'rgb(100, 100, 100) 10px 10px 10px, '
@@ -1697,12 +1860,12 @@ const textShadowListType = {
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'rgb(50, 50, 50) 5px 5px 5px, '
+ 'rgb(150, 150, 150) 15px 15px 15px' }]);
- }, property + ': shadow list');
+ }, `${property}: shadow list`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation =
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation =
target.animate({ [idlName]: [ 'rgb(200, 200, 200) 20px 20px 20px',
'rgb(100, 100, 100) 10px 10px 10px, '
+ 'rgb(100, 100, 100) 10px 10px 10px'] },
@@ -1710,12 +1873,12 @@ const textShadowListType = {
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'rgb(150, 150, 150) 15px 15px 15px, '
+ 'rgba(100, 100, 100, 0.5) 5px 5px 5px' }]);
- }, property + ': mismatched list length (from longer to shorter)');
+ }, `${property}: mismatched list length (from longer to shorter)`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation =
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation =
target.animate({ [idlName]: [ 'rgb(100, 100, 100) 10px 10px 10px, '
+ 'rgb(100, 100, 100) 10px 10px 10px',
'rgb(200, 200, 200) 20px 20px 20px'] },
@@ -1723,93 +1886,93 @@ const textShadowListType = {
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'rgb(150, 150, 150) 15px 15px 15px, '
+ 'rgba(100, 100, 100, 0.5) 5px 5px 5px' }]);
- }, property + ': mismatched list length (from shorter to longer)');
+ }, `${property}: mismatched list length (from shorter to longer)`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style.color = 'rgb(0, 255, 0)';
- var animation =
+ const animation =
target.animate({ [idlName]: [ 'currentcolor 0px 0px 0px',
'currentcolor 10px 10px 10px'] },
{ duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'rgb(0, 255, 0) 5px 5px 5px' }]);
- }, property + ': with currentcolor');
+ }, `${property}: with currentcolor`);
},
testAddition: function(property, setup) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'rgb(0, 0, 0) 0px 0px 0px';
- var animation =
+ const animation =
target.animate({ [idlName]: [ 'rgb(120, 120, 120) 10px 10px 10px',
'rgb(120, 120, 120) 10px 10px 10px'] },
{ duration: 1000, composite: 'add' });
testAnimationSamples(animation, idlName,
[ { time: 0, expected: 'rgb(0, 0, 0) 0px 0px 0px, ' +
'rgb(120, 120, 120) 10px 10px 10px' }]);
- }, property + ': shadow');
+ }, `${property}: shadow`);
},
testAccumulation: function(property, setup) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'rgb(120, 120, 120) 10px 10px 10px';
- var animation =
+ const animation =
target.animate({ [idlName]: [ 'rgb(120, 120, 120) 10px 10px 10px',
'rgb(120, 120, 120) 10px 10px 10px'] },
{ duration: 1000, composite: 'accumulate' });
testAnimationSamples(animation, idlName,
[ { time: 0, expected: 'rgb(240, 240, 240) 20px 20px 20px' }]);
- }, property + ': shadow');
+ }, `${property}: shadow`);
},
};
const boxShadowListType = {
- testInterpolation: function(property, setup) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation =
+ testInterpolation: (property, setup) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation =
target.animate({ [idlName]: [ 'none',
'rgb(100, 100, 100) 10px 10px 10px 0px'] },
{ duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
// Premultiplied
[{ time: 500, expected: 'rgba(100, 100, 100, 0.5) 5px 5px 5px 0px' }]);
- }, property + ': from none to other');
+ }, `${property}: from none to other`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation =
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation =
target.animate({ [idlName]: [ 'rgb(100, 100, 100) 10px 10px 10px 0px',
'none' ] },
{ duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
// Premultiplied
[{ time: 500, expected: 'rgba(100, 100, 100, 0.5) 5px 5px 5px 0px' }]);
- }, property + ': from other to none');
+ }, `${property}: from other to none`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation =
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation =
target.animate({ [idlName]: [ 'rgb(0, 0, 0) 0px 0px 0px 0px',
'rgb(100, 100, 100) 10px 10px 10px 0px'] },
{ duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'rgb(50, 50, 50) 5px 5px 5px 0px' }]);
- }, property + ': single shadow');
+ }, `${property}: single shadow`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation =
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation =
target.animate({ [idlName]: [ 'rgb(0, 0, 0) 0px 0px 0px 0px, '
+ 'rgb(200, 200, 200) 20px 20px 20px 20px',
'rgb(100, 100, 100) 10px 10px 10px 0px, '
@@ -1818,12 +1981,12 @@ const boxShadowListType = {
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'rgb(50, 50, 50) 5px 5px 5px 0px, '
+ 'rgb(150, 150, 150) 15px 15px 15px 10px' }]);
- }, property + ': shadow list');
+ }, `${property}: shadow list`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation =
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation =
target.animate({ [idlName]: [ 'rgb(200, 200, 200) 20px 20px 20px 20px',
'rgb(100, 100, 100) 10px 10px 10px 0px, '
+ 'rgb(100, 100, 100) 10px 10px 10px 0px'] },
@@ -1831,12 +1994,12 @@ const boxShadowListType = {
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'rgb(150, 150, 150) 15px 15px 15px 10px, '
+ 'rgba(100, 100, 100, 0.5) 5px 5px 5px 0px' }]);
- }, property + ': mismatched list length (from shorter to longer)');
+ }, `${property}: mismatched list length (from shorter to longer)`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation =
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation =
target.animate({ [idlName]: [ 'rgb(100, 100, 100) 10px 10px 10px 0px, '
+ 'rgb(100, 100, 100) 10px 10px 10px 0px',
'rgb(200, 200, 200) 20px 20px 20px 20px']},
@@ -1844,79 +2007,79 @@ const boxShadowListType = {
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'rgb(150, 150, 150) 15px 15px 15px 10px, '
+ 'rgba(100, 100, 100, 0.5) 5px 5px 5px 0px' }]);
- }, property + ': mismatched list length (from longer to shorter)');
+ }, `${property}: mismatched list length (from longer to shorter)`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style.color = 'rgb(0, 255, 0)';
- var animation =
+ const animation =
target.animate({ [idlName]: [ 'currentcolor 0px 0px 0px 0px',
'currentcolor 10px 10px 10px 10px'] },
{ duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'rgb(0, 255, 0) 5px 5px 5px 5px' }]);
- }, property + ': with currentcolor');
+ }, `${property}: with currentcolor`);
},
testAddition: function(property, setup) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'rgb(0, 0, 0) 0px 0px 0px 0px';
- var animation =
+ const animation =
target.animate({ [idlName]: [ 'rgb(120, 120, 120) 10px 10px 10px 0px',
'rgb(120, 120, 120) 10px 10px 10px 0px'] },
{ duration: 1000, composite: 'add' });
testAnimationSamples(animation, idlName,
[ { time: 0, expected: 'rgb(0, 0, 0) 0px 0px 0px 0px, ' +
'rgb(120, 120, 120) 10px 10px 10px 0px' }]);
- }, property + ': shadow');
+ }, `${property}: shadow`);
},
testAccumulation: function(property, setup) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'rgb(120, 120, 120) 10px 10px 10px 10px';
- var animation =
+ const animation =
target.animate({ [idlName]: [ 'rgb(120, 120, 120) 10px 10px 10px 10px',
'rgb(120, 120, 120) 10px 10px 10px 10px'] },
{ duration: 1000, composite: 'accumulate' });
testAnimationSamples(animation, idlName,
[ { time: 0, expected: 'rgb(240, 240, 240) 20px 20px 20px 20px' }]);
- }, property + ': shadow');
+ }, `${property}: shadow`);
},
};
const positionType = {
- testInterpolation: function(property, setup) {
+ testInterpolation: (property, setup) => {
lengthPairType.testInterpolation(property, setup);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]: ['10% 10%', '50% 50%'] },
- { duration: 1000, fill: 'both' });
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]: ['10% 10%', '50% 50%'] },
+ { duration: 1000, fill: 'both' });
testAnimationSamples(
animation, idlName,
[{ time: 500, expected: calcFromPercentage(idlName, '30% 30%') }]);
- }, property + ' supports animating as a position of percent');
+ }, `${property} supports animating as a position of percent`);
},
- testAdditionOrAccumulation: function(property, setup, composite) {
+ testAdditionOrAccumulation: (property, setup, composite) => {
lengthPairType.testAddition(property, setup);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = '60% 60%';
- var animation = target.animate({ [idlName]: ['70% 70%', '100% 100%'] },
- { duration: 1000, composite: composite });
+ const animation = target.animate({ [idlName]: ['70% 70%', '100% 100%'] },
+ { duration: 1000, composite });
testAnimationSamples(
animation, idlName,
[{ time: 0, expected: calcFromPercentage(idlName, '130% 130%') }]);
- }, property + ': position of percentage');
+ }, `${property}: position of percentage`);
},
testAddition: function(property, setup) {
@@ -1929,33 +2092,33 @@ const positionType = {
};
const rectType = {
- testInterpolation: function(property, setup) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]:
- ['rect(10px, 10px, 10px, 10px)',
- 'rect(50px, 50px, 50px, 50px)'] },
- { duration: 1000, fill: 'both' });
+ testInterpolation: (property, setup) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]:
+ ['rect(10px, 10px, 10px, 10px)',
+ 'rect(50px, 50px, 50px, 50px)'] },
+ { duration: 1000, fill: 'both' });
testAnimationSamples(
animation, idlName,
[{ time: 500, expected: 'rect(30px, 30px, 30px, 30px)' }]);
- }, property + ' supports animating as a rect');
+ }, `${property} supports animating as a rect`);
},
- testAdditionOrAccumulation: function(property, setup, composite) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ testAdditionOrAccumulation: (property, setup, composite) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'rect(100px, 100px, 100px, 100px)';
- var animation = target.animate({ [idlName]:
- ['rect(10px, 10px, 10px, 10px)',
- 'rect(10px, 10px, 10px, 10px)'] },
- { duration: 1000, composite: composite });
+ const animation = target.animate({ [idlName]:
+ ['rect(10px, 10px, 10px, 10px)',
+ 'rect(10px, 10px, 10px, 10px)'] },
+ { duration: 1000, composite });
testAnimationSamples(
animation, idlName,
[{ time: 0, expected: 'rect(110px, 110px, 110px, 110px)' }]);
- }, property + ': rect');
+ }, `${property}: rect`);
},
testAddition: function(property, setup) {
@@ -1969,33 +2132,33 @@ const rectType = {
// stroke-dasharray: none | [ <length> | <percentage> | <number> ]*
const dasharrayType = {
- testInterpolation: function(property, setup) {
+ testInterpolation: (property, setup) => {
percentageType.testInterpolation(property, setup);
positiveNumberType.testInterpolation(property, setup);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]:
- ['8, 16, 4',
- '4, 8, 12, 16'] },
- { duration: 1000, fill: 'both' });
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]:
+ ['8, 16, 4',
+ '4, 8, 12, 16'] },
+ { duration: 1000, fill: 'both' });
testAnimationSamples(
animation, idlName,
[{ time: 500, expected: '6, 12, 8, 12, 10, 6, 10, 16, 4, 8, 14, 10' }]);
- }, property + ' supports animating as a dasharray (mismatched length)');
-
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation = target.animate({ [idlName]:
- ['2, 50%, 6, 10',
- '6, 30%, 2, 2'] },
- { duration: 1000, fill: 'both' });
+ }, `${property} supports animating as a dasharray (mismatched length)`);
+
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation = target.animate({ [idlName]:
+ ['2, 50%, 6, 10',
+ '6, 30%, 2, 2'] },
+ { duration: 1000, fill: 'both' });
testAnimationSamples(
animation, idlName,
[{ time: 500, expected: '4, 40%, 4, 6' }]);
- }, property + ' supports animating as a dasharray (mixed number and percentage)');
+ }, `${property} supports animating as a dasharray (mixed number and percentage)`);
},
@@ -2003,19 +2166,19 @@ const dasharrayType = {
// write this additive test case that animating value replaces underlying
// values.
// See https://www.w3.org/TR/SVG2/painting.html#StrokeDashing.
- testAdditionOrAccumulation: function(property, setup, composite) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ testAdditionOrAccumulation: (property, setup, composite) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = '6, 30%, 2px';
- var animation = target.animate({ [idlName]:
- ['1, 2, 3, 4, 5',
- '6, 7, 8, 9, 10'] },
- { duration: 1000, composite: composite });
+ const animation = target.animate({ [idlName]:
+ ['1, 2, 3, 4, 5',
+ '6, 7, 8, 9, 10'] },
+ { duration: 1000, composite });
testAnimationSamples(
animation, idlName,
[{ time: 0, expected: '1, 2, 3, 4, 5' }]);
- }, property + ': dasharray');
+ }, `${property}: dasharray`);
},
testAddition: function(property, setup) {
@@ -2028,41 +2191,42 @@ const dasharrayType = {
}
const fontStretchType = {
- testInterpolation: function(property, setup) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation =
+ testInterpolation: (property, setup) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation =
target.animate({ [idlName]: ['ultra-condensed', 'extra-condensed'] },
{ duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
[{ time: 499, expected: 'ultra-condensed' },
{ time: 500, expected: 'extra-condensed' }]);
- }, property + ' supports animating as a font-stretch (adjacent values)');
+ }, `${property} supports animating as a font-stretch (adjacent values)`);
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
- var animation =
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
+ const animation =
target.animate({ [idlName]: ['ultra-condensed', 'condensed'] },
{ duration: 1000, fill: 'both' });
testAnimationSamples(animation, idlName,
[{ time: 500, expected: 'extra-condensed' }]);
- }, property + ' supports animating as a font-stretch (between value)');
+ }, `${property} supports animating as a font-stretch (between value)`);
},
- testAdditionOrAccumulation: function(property, setup, composite) {
- test(function(t) {
- var idlName = propertyToIDL(property);
- var target = createTestElement(t, setup);
+ testAdditionOrAccumulation: (property, setup, composite) => {
+ test(t => {
+ const idlName = propertyToIDL(property);
+ const target = createTestElement(t, setup);
target.style[idlName] = 'condensed';
- var animation =
+ const animation =
target.animate({ [idlName]: ['expanded', 'ultra-expanded'] },
- { duration: 1000, composite: composite });
+ { duration: 1000, composite });
testAnimationSamples(animation, idlName,
[{ time: 0, expected: 'normal' },
{ time: 250, expected: 'semi-expanded' }]);
- }, property + ' uses font-stretch behavior for composite type ' + composite);
+ },
+ `${property} uses font-stretch behavior for composite type ${composite}`);
},
testAddition: function(property, setup) {
@@ -2123,7 +2287,7 @@ const fontVariationSettingsType = {
target.style[idlName] = '"wght" 1';
const animation =
target.animate({ [idlName]: ['"wght" 1.1', '"wght" 1.5'] },
- { duration: 1000, composite: composite });
+ { duration: 1000, composite });
testAnimationSamples(animation, idlName,
[{ time: 250, expected: '"wght" 2.2' },
{ time: 750, expected: '"wght" 2.4' } ]);
diff --git a/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/visibility.html b/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/visibility.html
new file mode 100644
index 00000000000..f5a60b4e2c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/web-animations/animation-model/animation-types/visibility.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Animation type for the 'visibility' property</title>
+<!-- FIXME: The following spec link should be updated once this definition has
+ been moved to CSS Values & Units. -->
+<link rel="help" href="https://drafts.csswg.org/css-transitions/#animtype-visibility">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<body>
+<div id="log"></div>
+<div id="target"></div>
+<script>
+'use strict';
+
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ visibility: ['hidden','visible'] },
+ { duration: 100 * MS_PER_SEC, fill: 'both' });
+
+ anim.currentTime = 0;
+ assert_equals(getComputedStyle(div).visibility, 'hidden',
+ 'Visibility when progress = 0');
+
+ anim.currentTime = 10 * MS_PER_SEC + 1;
+ assert_equals(getComputedStyle(div).visibility, 'visible',
+ 'Visibility when progress > 0 due to linear easing');
+
+ anim.finish();
+ assert_equals(getComputedStyle(div).visibility, 'visible',
+ 'Visibility when progress = 1');
+
+}, 'Visibility clamping behavior');
+
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ visibility: ['hidden', 'visible'] },
+ { duration: 100 * MS_PER_SEC, fill: 'both',
+ easing: 'cubic-bezier(0.25, -0.6, 0, 0.5)' });
+
+ anim.currentTime = 0;
+ assert_equals(getComputedStyle(div).visibility, 'hidden',
+ 'Visibility when progress = 0');
+
+ // Timing function is below zero. So we expected visibility is hidden.
+ anim.currentTime = 10 * MS_PER_SEC + 1;
+ assert_equals(getComputedStyle(div).visibility, 'hidden',
+ 'Visibility when progress < 0 due to cubic-bezier easing');
+
+ anim.currentTime = 60 * MS_PER_SEC;
+ assert_equals(getComputedStyle(div).visibility, 'visible',
+ 'Visibility when progress > 0 due to cubic-bezier easing');
+
+}, 'Visibility clamping behavior with an easing that has a negative component');
+
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/animation-model/combining-effects/effect-composition.html b/tests/wpt/web-platform-tests/web-animations/animation-model/combining-effects/effect-composition.html
index 7604bd21e9e..78f46c9e468 100644
--- a/tests/wpt/web-platform-tests/web-animations/animation-model/combining-effects/effect-composition.html
+++ b/tests/wpt/web-platform-tests/web-animations/animation-model/combining-effects/effect-composition.html
@@ -1,7 +1,7 @@
<!doctype html>
<meta charset=utf-8>
-<title>Test for effect composition</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#effect-composition">
+<title>Effect composition</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#effect-composition">
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="../../testcommon.js"></script>
@@ -9,21 +9,21 @@
<script>
'use strict';
-[ 'accumulate', 'add' ].forEach(function(composite) {
- test(function(t) {
- var div = createDiv(t);
+for (const composite of ['accumulate', 'add']) {
+ test(t => {
+ const div = createDiv(t);
div.style.marginLeft = '10px';
- var anim =
+ const anim =
div.animate({ marginLeft: ['0px', '10px'], composite }, 100);
anim.currentTime = 50;
assert_equals(getComputedStyle(div).marginLeft, '15px',
'Animated margin-left style at 50%');
- }, composite + ' onto the base value');
+ }, `${composite} onto the base value`);
- test(function(t) {
- var div = createDiv(t);
- var anims = [];
+ test(t => {
+ const div = createDiv(t);
+ const anims = [];
anims.push(div.animate({ marginLeft: ['10px', '20px'],
composite: 'replace' },
100));
@@ -31,18 +31,18 @@
composite },
100));
- anims.forEach(function(anim) {
+ for (const anim of anims) {
anim.currentTime = 50;
- });
+ }
assert_equals(getComputedStyle(div).marginLeft, '20px',
'Animated style at 50%');
- }, composite + ' onto an underlying animation value');
+ }, `${composite} onto an underlying animation value`);
- test(function(t) {
- var div = createDiv(t);
+ test(t => {
+ const div = createDiv(t);
div.style.marginLeft = '10px';
- var anim =
+ const anim =
div.animate([{ marginLeft: '10px', composite },
{ marginLeft: '30px', composite: 'replace' }],
100);
@@ -50,12 +50,12 @@
anim.currentTime = 50;
assert_equals(getComputedStyle(div).marginLeft, '25px',
'Animated style at 50%');
- }, 'Composite when mixing ' + composite + ' and replace');
+ }, `Composite when mixing ${composite} and replace`);
- test(function(t) {
- var div = createDiv(t);
+ test(t => {
+ const div = createDiv(t);
div.style.marginLeft = '10px';
- var anim =
+ const anim =
div.animate([{ marginLeft: '10px', composite: 'replace' },
{ marginLeft: '20px' }],
{ duration: 100 , composite });
@@ -63,13 +63,13 @@
anim.currentTime = 50;
assert_equals(getComputedStyle(div).marginLeft, '20px',
'Animated style at 50%');
- }, composite + ' specified on a keyframe overrides the composite mode of ' +
- 'the effect');
+ }, `${composite} specified on a keyframe overrides the composite mode of`
+ + ' the effect');
- test(function(t) {
- var div = createDiv(t);
+ test(t => {
+ const div = createDiv(t);
div.style.marginLeft = '10px';
- var anim =
+ const anim =
div.animate([{ marginLeft: '10px', composite: 'replace' },
{ marginLeft: '20px' }],
100);
@@ -78,8 +78,8 @@
anim.currentTime = 50; // (10 + (10 + 20)) * 0.5
assert_equals(getComputedStyle(div).marginLeft, '20px',
'Animated style at 50%');
- }, 'unspecified composite mode on a keyframe is overriden by setting ' +
- composite + ' of the effect');
-});
+ }, 'unspecified composite mode on a keyframe is overriden by setting'
+ + ` ${composite} of the effect`);
+}
</script>
diff --git a/tests/wpt/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-context.html b/tests/wpt/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-context.html
index 07fb6097c9f..3730a02098a 100644
--- a/tests/wpt/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-context.html
+++ b/tests/wpt/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-context.html
@@ -1,19 +1,21 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>Tests that property values respond to changes to their context</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#keyframes-section">
+<title>The effect value of a keyframe effect: Property values that depend on
+ their context (target element)</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#calculating-computed-keyframes">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
<body>
<div id="log"></div>
<script>
+'use strict';
-test(function(t) {
- var div = createDiv(t);
+test(t => {
+ const div = createDiv(t);
div.style.fontSize = '10px';
- var animation = div.animate([ { marginLeft: '10em' },
- { marginLeft: '20em' } ], 1000);
+ const animation = div.animate([ { marginLeft: '10em' },
+ { marginLeft: '20em' } ], 1000);
animation.currentTime = 500;
assert_equals(getComputedStyle(div).marginLeft, '150px',
'Effect value before updating font-size');
@@ -22,14 +24,14 @@ test(function(t) {
'Effect value after updating font-size');
}, 'Effect values reflect changes to font-size on element');
-test(function(t) {
- var parentDiv = createDiv(t);
- var div = createDiv(t);
+test(t => {
+ const parentDiv = createDiv(t);
+ const div = createDiv(t);
parentDiv.appendChild(div);
parentDiv.style.fontSize = '10px';
- var animation = div.animate([ { marginLeft: '10em' },
- { marginLeft: '20em' } ], 1000);
+ const animation = div.animate([ { marginLeft: '10em' },
+ { marginLeft: '20em' } ], 1000);
animation.currentTime = 500;
assert_equals(getComputedStyle(div).marginLeft, '150px',
'Effect value before updating font-size on parent element');
@@ -38,38 +40,38 @@ test(function(t) {
'Effect value after updating font-size on parent element');
}, 'Effect values reflect changes to font-size on parent element');
-promise_test(function(t) {
- var parentDiv = createDiv(t);
- var div = createDiv(t);
+promise_test(t => {
+ const parentDiv = createDiv(t);
+ const div = createDiv(t);
parentDiv.appendChild(div);
parentDiv.style.fontSize = '10px';
- var animation = div.animate([ { marginLeft: '10em' },
- { marginLeft: '20em' } ], 1000);
+ const animation = div.animate([ { marginLeft: '10em' },
+ { marginLeft: '20em' } ], 1000);
animation.pause();
animation.currentTime = 500;
parentDiv.style.fontSize = '20px';
- return animation.ready.then(function() {
+ return animation.ready.then(() => {
assert_equals(getComputedStyle(div).marginLeft, '300px',
'Effect value after updating font-size on parent element');
});
}, 'Effect values reflect changes to font-size when computed style is not'
+ ' immediately flushed');
-promise_test(function(t) {
- var divWith10pxFontSize = createDiv(t);
+promise_test(t => {
+ const divWith10pxFontSize = createDiv(t);
divWith10pxFontSize.style.fontSize = '10px';
- var divWith20pxFontSize = createDiv(t);
+ const divWith20pxFontSize = createDiv(t);
divWith20pxFontSize.style.fontSize = '20px';
- var div = createDiv(t);
+ const div = createDiv(t);
div.remove(); // Detach
- var animation = div.animate([ { marginLeft: '10em' },
- { marginLeft: '20em' } ], 1000);
+ const animation = div.animate([ { marginLeft: '10em' },
+ { marginLeft: '20em' } ], 1000);
animation.pause();
- return animation.ready.then(function() {
+ return animation.ready.then(() => {
animation.currentTime = 500;
divWith10pxFontSize.appendChild(div);
@@ -81,15 +83,15 @@ promise_test(function(t) {
});
}, 'Effect values reflect changes to font-size from reparenting');
-test(function(t) {
- var divA = createDiv(t);
+test(t => {
+ const divA = createDiv(t);
divA.style.fontSize = '10px';
- var divB = createDiv(t);
+ const divB = createDiv(t);
divB.style.fontSize = '20px';
- var animation = divA.animate([ { marginLeft: '10em' },
- { marginLeft: '20em' } ], 1000);
+ const animation = divA.animate([ { marginLeft: '10em' },
+ { marginLeft: '20em' } ], 1000);
animation.currentTime = 500;
assert_equals(getComputedStyle(divA).marginLeft, '150px',
'Effect value before updating target element');
diff --git a/tests/wpt/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html b/tests/wpt/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html
new file mode 100644
index 00000000000..c2e9702cb73
--- /dev/null
+++ b/tests/wpt/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html
@@ -0,0 +1,819 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>The effect value of a keyframe effect: Applying the iteration composite
+ operation</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#the-effect-value-of-a-keyframe-animation-effect">
+<link rel="help" href="https://drafts.csswg.org/web-animations/#effect-accumulation-section">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="../../testcommon.js"></script>
+<div id="log"></div>
+<script>
+'use strict';
+
+test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ alignContent: ['flex-start', 'flex-end'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).alignContent, 'flex-end',
+ 'Animated align-content style at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_equals(getComputedStyle(div).alignContent, 'flex-start',
+ 'Animated align-content style at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).alignContent, 'flex-end',
+ 'Animated align-content style at 50s of the third iteration');
+}, 'iteration composition of discrete type animation (align-content)');
+
+test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ marginLeft: ['0px', '10px'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).marginLeft, '5px',
+ 'Animated margin-left style at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_equals(getComputedStyle(div).marginLeft, '20px',
+ 'Animated margin-left style at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).marginLeft, '25px',
+ 'Animated margin-left style at 50s of the third iteration');
+}, 'iteration composition of <length> type animation');
+
+test(t => {
+ const parent = createDiv(t);
+ parent.style.width = '100px';
+ const div = createDiv(t);
+ parent.appendChild(div);
+
+ const anim =
+ div.animate({ width: ['0%', '50%'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).width, '25px',
+ 'Animated width style at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_equals(getComputedStyle(div).width, '100px',
+ 'Animated width style at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).width, '125px',
+ 'Animated width style at 50s of the third iteration');
+}, 'iteration composition of <percentage> type animation');
+
+test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ color: ['rgb(0, 0, 0)', 'rgb(120, 120, 120)'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).color, 'rgb(60, 60, 60)',
+ 'Animated color style at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_equals(getComputedStyle(div).color, 'rgb(240, 240, 240)',
+ 'Animated color style at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).color, 'rgb(255, 255, 255)',
+ 'Animated color style at 50s of the third iteration');
+}, 'iteration composition of <color> type animation');
+
+test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ color: ['rgb(0, 120, 0)', 'rgb(60, 60, 60)'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).color, 'rgb(30, 90, 30)',
+ 'Animated color style at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_equals(getComputedStyle(div).color, 'rgb(120, 240, 120)',
+ 'Animated color style at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ // The green color is (240 + 180) / 2 = 210
+ assert_equals(getComputedStyle(div).color, 'rgb(150, 210, 150)',
+ 'Animated color style at 50s of the third iteration');
+}, 'iteration composition of <color> type animation that green component is ' +
+ 'decreasing');
+
+ test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ flexGrow: [0, 10] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).flexGrow, '5',
+ 'Animated flex-grow style at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_equals(getComputedStyle(div).flexGrow, '20',
+ 'Animated flex-grow style at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).flexGrow, '25',
+ 'Animated flex-grow style at 50s of the third iteration');
+}, 'iteration composition of <number> type animation');
+
+test(t => {
+ const div = createDiv(t);
+ div.style.position = 'absolute';
+ const anim =
+ div.animate({ clip: ['rect(0px, 0px, 0px, 0px)',
+ 'rect(10px, 10px, 10px, 10px)'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).clip, 'rect(5px, 5px, 5px, 5px)',
+ 'Animated clip style at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_equals(getComputedStyle(div).clip, 'rect(20px, 20px, 20px, 20px)',
+ 'Animated clip style at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).clip, 'rect(25px, 25px, 25px, 25px)',
+ 'Animated clip style at 50s of the third iteration');
+}, 'iteration composition of <shape> type animation');
+
+test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ width: ['calc(0vw + 0px)', 'calc(0vw + 10px)'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).width, '5px',
+ 'Animated calc width style at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_equals(getComputedStyle(div).width, '20px',
+ 'Animated calc width style at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).width, '25px',
+ 'Animated calc width style at 50s of the third iteration');
+}, 'iteration composition of <calc()> value animation');
+
+test(t => {
+ const parent = createDiv(t);
+ parent.style.width = '100px';
+ const div = createDiv(t);
+ parent.appendChild(div);
+
+ const anim =
+ div.animate({ width: ['calc(0% + 0px)', 'calc(10% + 10px)'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).width, '10px',
+ // 100px * 5% + 5px
+ 'Animated calc width style at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_equals(getComputedStyle(div).width,
+ '40px', // 100px * (10% + 10%) + (10px + 10px)
+ 'Animated calc width style at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).width,
+ '50px', // (40px + 60px) / 2
+ 'Animated calc width style at 50s of the third iteration');
+}, 'iteration composition of <calc()> value animation that the values can\'t' +
+ 'be reduced');
+
+test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ opacity: [0, 0.4] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).opacity, '0.2',
+ 'Animated opacity style at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_equals(getComputedStyle(div).opacity, '0.8',
+ 'Animated opacity style at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).opacity, '1', // (0.8 + 1.2) * 0.5
+ 'Animated opacity style at 50s of the third iteration');
+}, 'iteration composition of opacity animation');
+
+test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ boxShadow: ['rgb(0, 0, 0) 0px 0px 0px 0px',
+ 'rgb(120, 120, 120) 10px 10px 10px 0px'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).boxShadow,
+ 'rgb(60, 60, 60) 5px 5px 5px 0px',
+ 'Animated box-shadow style at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_equals(getComputedStyle(div).boxShadow,
+ 'rgb(240, 240, 240) 20px 20px 20px 0px',
+ 'Animated box-shadow style at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).boxShadow,
+ 'rgb(255, 255, 255) 25px 25px 25px 0px',
+ 'Animated box-shadow style at 50s of the third iteration');
+}, 'iteration composition of box-shadow animation');
+
+test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ filter: ['blur(0px)', 'blur(10px)'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).filter, 'blur(5px)',
+ 'Animated filter blur style at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_equals(getComputedStyle(div).filter, 'blur(20px)',
+ 'Animated filter blur style at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).filter, 'blur(25px)',
+ 'Animated filter blur style at 50s of the third iteration');
+}, 'iteration composition of filter blur animation');
+
+test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ filter: ['brightness(1)',
+ 'brightness(180%)'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).filter,
+ 'brightness(1.4)',
+ 'Animated filter brightness style at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_equals(getComputedStyle(div).filter,
+ 'brightness(2.6)', // brightness(1) + brightness(0.8) + brightness(0.8)
+ 'Animated filter brightness style at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).filter,
+ 'brightness(3)', // (brightness(2.6) + brightness(3.4)) * 0.5
+ 'Animated filter brightness style at 50s of the third iteration');
+}, 'iteration composition of filter brightness for different unit animation');
+
+test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ filter: ['brightness(0)',
+ 'brightness(1)'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).filter,
+ 'brightness(0.5)',
+ 'Animated filter brightness style at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_equals(getComputedStyle(div).filter,
+ 'brightness(0)', // brightness(1) is an identity element, not accumulated.
+ 'Animated filter brightness style at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).filter,
+ 'brightness(0.5)', // brightness(1) is an identity element, not accumulated.
+ 'Animated filter brightness style at 50s of the third iteration');
+}, 'iteration composition of filter brightness animation');
+
+test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ filter: ['drop-shadow(rgb(0, 0, 0) 0px 0px 0px)',
+ 'drop-shadow(rgb(120, 120, 120) 10px 10px 10px)'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).filter,
+ 'drop-shadow(rgb(60, 60, 60) 5px 5px 5px)',
+ 'Animated filter drop-shadow style at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_equals(getComputedStyle(div).filter,
+ 'drop-shadow(rgb(240, 240, 240) 20px 20px 20px)',
+ 'Animated filter drop-shadow style at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).filter,
+ 'drop-shadow(rgb(255, 255, 255) 25px 25px 25px)',
+ 'Animated filter drop-shadow style at 50s of the third iteration');
+}, 'iteration composition of filter drop-shadow animation');
+
+test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ filter: ['brightness(1) contrast(1)',
+ 'brightness(2) contrast(2)'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).filter,
+ 'brightness(1.5) contrast(1.5)',
+ 'Animated filter list at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_equals(getComputedStyle(div).filter,
+ 'brightness(3) contrast(3)',
+ 'Animated filter list at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).filter,
+ 'brightness(3.5) contrast(3.5)',
+ 'Animated filter list at 50s of the third iteration');
+}, 'iteration composition of same filter list animation');
+
+test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ filter: ['brightness(1) contrast(1)',
+ 'contrast(2) brightness(2)'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).filter,
+ 'contrast(2) brightness(2)', // discrete
+ 'Animated filter list at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_equals(getComputedStyle(div).filter,
+ // We can't accumulate 'contrast(2) brightness(2)' onto
+ // the first list 'brightness(1) contrast(1)' because of
+ // mismatch of the order.
+ 'brightness(1) contrast(1)',
+ 'Animated filter list at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).filter,
+ // We *can* accumulate 'contrast(2) brightness(2)' onto
+ // the same list 'contrast(2) brightness(2)' here.
+ 'contrast(4) brightness(4)', // discrete
+ 'Animated filter list at 50s of the third iteration');
+}, 'iteration composition of discrete filter list because of mismatch ' +
+ 'of the order');
+
+ test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ filter: ['sepia(0)',
+ 'sepia(1) contrast(2)'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).filter,
+ 'sepia(0.5) contrast(1.5)',
+ 'Animated filter list at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_equals(getComputedStyle(div).filter,
+ 'sepia(2) contrast(3)',
+ 'Animated filter list at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).filter,
+ 'sepia(2.5) contrast(3.5)',
+ 'Animated filter list at 50s of the third iteration');
+}, 'iteration composition of different length filter list animation');
+
+test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ transform: ['rotate(0deg)', 'rotate(180deg)'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ 'matrix(0, 1, -1, 0, 0, 0)', // rotate(90deg)
+ 'Animated transform(rotate) style at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ 'matrix(1, 0, 0, 1, 0, 0)', // rotate(360deg)
+ 'Animated transform(rotate) style at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ 'matrix(0, 1, -1, 0, 0, 0)', // rotate(450deg)
+ 'Animated transform(rotate) style at 50s of the third iteration');
+}, 'iteration composition of transform(rotate) animation');
+
+test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ transform: ['scale(0)', 'scale(1)'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ 'matrix(0.5, 0, 0, 0.5, 0, 0)', // scale(0.5)
+ 'Animated transform(scale) style at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ 'matrix(0, 0, 0, 0, 0, 0)', // scale(0); scale(1) is an identity element,
+ // not accumulated.
+ 'Animated transform(scale) style at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ 'matrix(0.5, 0, 0, 0.5, 0, 0)', // scale(0.5); scale(1) an identity
+ // element, not accumulated.
+ 'Animated transform(scale) style at 50s of the third iteration');
+}, 'iteration composition of transform: [ scale(0), scale(1) ] animation');
+
+test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ transform: ['scale(1)', 'scale(2)'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ 'matrix(1.5, 0, 0, 1.5, 0, 0)', // scale(1.5)
+ 'Animated transform(scale) style at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ 'matrix(3, 0, 0, 3, 0, 0)', // scale(1 + (2 -1) + (2 -1))
+ 'Animated transform(scale) style at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ 'matrix(3.5, 0, 0, 3.5, 0, 0)', // (scale(3) + scale(4)) * 0.5
+ 'Animated transform(scale) style at 50s of the third iteration');
+}, 'iteration composition of transform: [ scale(1), scale(2) ] animation');
+
+test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ transform: ['scale(0)', 'scale(2)'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ 'matrix(1, 0, 0, 1, 0, 0)', // scale(1)
+ 'Animated transform(scale) style at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ 'matrix(2, 0, 0, 2, 0, 0)', // (scale(0) + scale(2-1)*2)
+ 'Animated transform(scale) style at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ 'matrix(3, 0, 0, 3, 0, 0)', // (scale(2) + scale(4)) * 0.5
+ 'Animated transform(scale) style at 50s of the third iteration');
+}, 'iteration composition of transform: scale(2) animation');
+
+test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ transform: ['rotate(0deg) translateX(0px)',
+ 'rotate(180deg) translateX(10px)'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ 'matrix(0, 1, -1, 0, 0, 5)', // rotate(90deg) translateX(5px)
+ 'Animated transform list at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ 'matrix(1, 0, 0, 1, 20, 0)', // rotate(360deg) translateX(20px)
+ 'Animated transform list at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ 'matrix(0, 1, -1, 0, 0, 25)', // rotate(450deg) translateX(25px)
+ 'Animated transform list at 50s of the third iteration');
+}, 'iteration composition of transform list animation');
+
+test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ transform: ['matrix(2, 0, 0, 2, 0, 0)',
+ 'matrix(3, 0, 0, 3, 30, 0)'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ 'matrix(2.5, 0, 0, 2.5, 15, 0)',
+ 'Animated transform of matrix function at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ // scale(2) + (scale(3-1)*2) + translateX(30px)*2
+ 'matrix(6, 0, 0, 6, 60, 0)',
+ 'Animated transform of matrix function at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ // from: matrix(6, 0, 0, 6, 60, 0)
+ // to: matrix(7, 0, 0, 7, 90, 0)
+ // = scale(3) + (scale(3-1)*2) + translateX(30px)*3
+ 'matrix(6.5, 0, 0, 6.5, 75, 0)',
+ 'Animated transform of matrix function at 50s of the third iteration');
+}, 'iteration composition of transform of matrix function');
+
+test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ transform: ['translateX(0px) scale(2)',
+ 'scale(3) translateX(10px)'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ // Interpolate between matrix(2, 0, 0, 2, 0, 0) = translateX(0px) scale(2)
+ // and matrix(3, 0, 0, 3, 30, 0) = scale(3) translateX(10px)
+ 'matrix(2.5, 0, 0, 2.5, 15, 0)',
+ 'Animated transform list at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ // 'from' and 'to' value are mismatched, so accumulate
+ // matrix(2, 0, 0, 2, 0, 0) onto matrix(3, 0, 0, 3, 30, 0) * 2
+ // = scale(2) + (scale(3-1)*2) + translateX(30px)*2
+ 'matrix(6, 0, 0, 6, 60, 0)',
+ 'Animated transform list at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ // Interpolate between matrix(6, 0, 0, 6, 60, 0)
+ // and matrix(7, 0, 0, 7, 210, 0) = scale(7) translate(30px)
+ 'matrix(6.5, 0, 0, 6.5, 135, 0)',
+ 'Animated transform list at 50s of the third iteration');
+}, 'iteration composition of transform list animation whose order is'
+ + ' mismatched');
+
+test(t => {
+ const div = createDiv(t);
+ // Even if each transform list does not have functions which exist in
+ // other pair of the list, we don't fill any missing functions at all.
+ const anim =
+ div.animate({ transform: ['translateX(0px)',
+ 'scale(2) translateX(10px)'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ // Interpolate between matrix(1, 0, 0, 1, 0, 0) = translateX(0px)
+ // and matrix(2, 0, 0, 2, 20, 0) = scale(2) translateX(10px)
+ 'matrix(1.5, 0, 0, 1.5, 10, 0)',
+ 'Animated transform list at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ // 'from' and 'to' value are mismatched, so accumulate
+ // matrix(1, 0, 0, 1, 0, 0) onto matrix(2, 0, 0, 2, 20, 0) * 2
+ // = scale(1) + (scale(2-1)*2) + translateX(20px)*2
+ 'matrix(3, 0, 0, 3, 40, 0)',
+ 'Animated transform list at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ // Interpolate between matrix(3, 0, 0, 3, 40, 0)
+ // and matrix(4, 0, 0, 4, 120, 0) =
+ // scale(2 + (2-1)*2) translate(10px * 3)
+ 'matrix(3.5, 0, 0, 3.5, 80, 0)',
+ 'Animated transform list at 50s of the third iteration');
+}, 'iteration composition of transform list animation whose order is'
+ + ' mismatched because of missing functions');
+
+ test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ transform: ['none',
+ 'translateX(10px)'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ // translateX(none) -> translateX(10px) @ 50%
+ 'matrix(1, 0, 0, 1, 5, 0)',
+ 'Animated transform list at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ // translateX(10px * 2 + none) -> translateX(10px * 2 + 10px) @ 0%
+ 'matrix(1, 0, 0, 1, 20, 0)',
+ 'Animated transform list at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ // translateX(10px * 2 + none) -> translateX(10px * 2 + 10px) @ 50%
+ 'matrix(1, 0, 0, 1, 25, 0)',
+ 'Animated transform list at 50s of the third iteration');
+}, 'iteration composition of transform from none to translate');
+
+test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ transform: ['matrix3d(1, 0, 0, 0, ' +
+ '0, 1, 0, 0, ' +
+ '0, 0, 1, 0, ' +
+ '0, 0, 30, 1)',
+ 'matrix3d(1, 0, 0, 0, ' +
+ '0, 1, 0, 0, ' +
+ '0, 0, 1, 0, ' +
+ '0, 0, 50, 1)'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 40, 1)',
+ 'Animated transform of matrix3d function at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ // translateZ(30px) + (translateZ(50px)*2)
+ 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 130, 1)',
+ 'Animated transform of matrix3d function at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ // from: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 130, 1)
+ // to: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 150, 1)
+ 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 140, 1)',
+ 'Animated transform of matrix3d function at 50s of the third iteration');
+}, 'iteration composition of transform of matrix3d function');
+
+test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ transform: ['rotate3d(1, 1, 0, 0deg)',
+ 'rotate3d(1, 1, 0, 90deg)'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = 0;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ 'matrix(1, 0, 0, 1, 0, 0)', // Actually not rotated at all.
+ 'Animated transform of rotate3d function at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ rotate3dToMatrix3d(1, 1, 0, Math.PI), // 180deg
+ 'Animated transform of rotate3d function at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_matrix_equals(getComputedStyle(div).transform,
+ rotate3dToMatrix3d(1, 1, 0, 225 * Math.PI / 180), //((270 + 180) * 0.5)deg
+ 'Animated transform of rotate3d function at 50s of the third iteration');
+}, 'iteration composition of transform of rotate3d function');
+
+test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ marginLeft: ['10px', '20px'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).marginLeft, '15px',
+ 'Animated margin-left style at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_equals(getComputedStyle(div).marginLeft, '50px', // 10px + 20px + 20px
+ 'Animated margin-left style at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).marginLeft, '55px', // (50px + 60px) * 0.5
+ 'Animated margin-left style at 50s of the third iteration');
+}, 'iteration composition starts with non-zero value animation');
+
+test(t => {
+ const div = createDiv(t);
+ const anim =
+ div.animate({ marginLeft: ['10px', '-10px'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime = anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).marginLeft,
+ '0px',
+ 'Animated margin-left style at 50s of the first iteration');
+ anim.currentTime = anim.effect.timing.duration * 2;
+ assert_equals(getComputedStyle(div).marginLeft,
+ '-10px', // 10px + -10px + -10px
+ 'Animated margin-left style at 0s of the third iteration');
+ anim.currentTime += anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).marginLeft,
+ '-20px', // (-10px + -30px) * 0.5
+ 'Animated margin-left style at 50s of the third iteration');
+}, 'iteration composition with negative final value animation');
+
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ marginLeft: ['0px', '10px'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
+ anim.pause();
+
+ anim.currentTime =
+ anim.effect.timing.duration * 2 + anim.effect.timing.duration / 2;
+ assert_equals(getComputedStyle(div).marginLeft, '25px',
+ 'Animated style at 50s of the third iteration');
+
+ // double its duration.
+ anim.effect.timing.duration = anim.effect.timing.duration * 2;
+ assert_equals(getComputedStyle(div).marginLeft, '12.5px',
+ 'Animated style at 25s of the first iteration');
+
+ // half of original.
+ anim.effect.timing.duration = anim.effect.timing.duration / 4;
+ assert_equals(getComputedStyle(div).marginLeft, '50px',
+ 'Animated style at 50s of the fourth iteration');
+}, 'duration changes with an iteration composition operation of accumulate');
+
+</script>
diff --git a/tests/wpt/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-overlapping-keyframes.html b/tests/wpt/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-overlapping-keyframes.html
index 99b4f3df6fe..2a41f04c05a 100644
--- a/tests/wpt/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-overlapping-keyframes.html
+++ b/tests/wpt/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-overlapping-keyframes.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>Effect value computation tests when keyframes overlap</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#the-effect-value-of-a-keyframe-animation-effect">
+<title>The effect value of a keyframe effect: Overlapping keyframes</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#the-effect-value-of-a-keyframe-animation-effect">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -11,16 +11,16 @@
<script>
'use strict';
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate([ { offset: 0, opacity: 0 },
- { offset: 0, opacity: 0.1 },
- { offset: 0, opacity: 0.2 },
- { offset: 1, opacity: 0.8 },
- { offset: 1, opacity: 0.9 },
- { offset: 1, opacity: 1 } ],
- { duration: 1000,
- easing: 'cubic-bezier(0.5, -0.5, 0.5, 1.5)' });
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate([ { offset: 0, opacity: 0 },
+ { offset: 0, opacity: 0.1 },
+ { offset: 0, opacity: 0.2 },
+ { offset: 1, opacity: 0.8 },
+ { offset: 1, opacity: 0.9 },
+ { offset: 1, opacity: 1 } ],
+ { duration: 1000,
+ easing: 'cubic-bezier(0.5, -0.5, 0.5, 1.5)' });
assert_equals(getComputedStyle(div).opacity, '0.2',
'When progress is zero the last keyframe with offset 0 should'
+ ' be used');
@@ -47,13 +47,13 @@ test(function(t) {
}, 'Overlapping keyframes at 0 and 1 use the appropriate value when the'
+ ' progress is outside the range [0, 1]');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate([ { offset: 0, opacity: 0 },
- { offset: 0.5, opacity: 0.3 },
- { offset: 0.5, opacity: 0.5 },
- { offset: 0.5, opacity: 0.7 },
- { offset: 1, opacity: 1 } ], 1000);
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate([ { offset: 0, opacity: 0 },
+ { offset: 0.5, opacity: 0.3 },
+ { offset: 0.5, opacity: 0.5 },
+ { offset: 0.5, opacity: 0.7 },
+ { offset: 1, opacity: 1 } ], 1000);
anim.currentTime = 250;
assert_equals(getComputedStyle(div).opacity, '0.15',
'Before the overlap point, the first keyframe from the'
diff --git a/tests/wpt/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance.html b/tests/wpt/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance.html
index 87efd42b577..6ad9cd2aca3 100644
--- a/tests/wpt/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance.html
+++ b/tests/wpt/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-transformed-distance.html
@@ -1,7 +1,8 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>Tests for calculation of the transformed distance when computing an effect value</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#the-effect-value-of-a-keyframe-animation-effect">
+<title>The effect value of a keyframe effect: Calculating the transformed
+ distance between keyframes</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#the-effect-value-of-a-keyframe-animation-effect">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -13,8 +14,8 @@
// Test that applying easing to keyframes is applied as expected
-gEasingTests.forEach(params => {
- test(function(t) {
+for (const params of gEasingTests) {
+ test(t => {
const target = createDiv(t);
const anim = target.animate([ { width: '0px' },
// We put the easing on the second keyframe
@@ -25,7 +26,7 @@ gEasingTests.forEach(params => {
{ duration: 2000,
fill: 'forwards' });
- [ 0, 999, 1000, 1100, 1500, 2000 ].forEach(sampleTime => {
+ for (const sampleTime of [0, 999, 1000, 1100, 1500, 2000]) {
anim.currentTime = sampleTime;
const portion = (sampleTime - 1000) / 1000;
@@ -37,18 +38,18 @@ gEasingTests.forEach(params => {
0.01,
'The width should be approximately ' +
`${expectedWidth} at ${sampleTime}ms`);
- });
+ }
}, `A ${params.desc} on a keyframe affects the resulting style`);
-});
+}
// Test that a linear-equivalent cubic-bezier easing applied to a keyframe does
// not alter (including clamping) the result.
-gEasingTests.forEach(params => {
+for (const params of gEasingTests) {
const linearEquivalentEasings = [ 'cubic-bezier(0, 0, 0, 0)',
'cubic-bezier(1, 1, 1, 1)' ];
- test(function(t) {
- linearEquivalentEasings.forEach(linearEquivalentEasing => {
+ test(t => {
+ for (const linearEquivalentEasing of linearEquivalentEasings) {
const timing = { duration: 1000,
fill: 'forwards',
easing: params.easing };
@@ -65,7 +66,7 @@ gEasingTests.forEach(params => {
{ width: '100px' } ],
timing);
- [ 0, 250, 500, 750, 1000 ].forEach(sampleTime => {
+ for (const sampleTime of [0, 250, 500, 750, 1000]) {
linearAnim.currentTime = sampleTime;
equivalentAnim.currentTime = sampleTime;
@@ -73,11 +74,11 @@ gEasingTests.forEach(params => {
getComputedStyle(equivalentTarget).width,
`The 'width' of the animated elements should be equal ` +
`at ${sampleTime}ms`);
- });
- });
+ }
+ }
}, 'Linear-equivalent cubic-bezier keyframe easing applied to an effect ' +
`with a ${params.desc} does not alter the result`);
-});
+}
</script>
</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-visibility.html b/tests/wpt/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-visibility.html
deleted file mode 100644
index cf951b01233..00000000000
--- a/tests/wpt/web-platform-tests/web-animations/animation-model/keyframe-effects/effect-value-visibility.html
+++ /dev/null
@@ -1,55 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>Effect value computation tests for 'visibility' property</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#the-effect-value-of-a-keyframe-animation-effect">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<div id="target"></div>
-<script>
-'use strict';
-
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ visibility: ['hidden','visible'] },
- { duration: 100 * MS_PER_SEC, fill: 'both' });
-
- anim.currentTime = 0;
- assert_equals(getComputedStyle(div).visibility, 'hidden',
- 'Visibility when progress = 0');
-
- anim.currentTime = 10 * MS_PER_SEC + 1;
- assert_equals(getComputedStyle(div).visibility, 'visible',
- 'Visibility when progress > 0 due to linear easing');
-
- anim.finish();
- assert_equals(getComputedStyle(div).visibility, 'visible',
- 'Visibility when progress = 1');
-
-}, 'Visibility clamping behavior');
-
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ visibility: ['hidden', 'visible'] },
- { duration: 100 * MS_PER_SEC, fill: 'both',
- easing: 'cubic-bezier(0.25, -0.6, 0, 0.5)' });
-
- anim.currentTime = 0;
- assert_equals(getComputedStyle(div).visibility, 'hidden',
- 'Visibility when progress = 0');
-
- // Timing function is below zero. So we expected visibility is hidden.
- anim.currentTime = 10 * MS_PER_SEC + 1;
- assert_equals(getComputedStyle(div).visibility, 'hidden',
- 'Visibility when progress < 0 due to cubic-bezier easing');
-
- anim.currentTime = 60 * MS_PER_SEC;
- assert_equals(getComputedStyle(div).visibility, 'visible',
- 'Visibility when progress > 0 due to cubic-bezier easing');
-
-}, 'Visibility clamping behavior with an easing that has a negative component');
-
-</script>
-</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/Animatable/animate-no-browsing-context.html b/tests/wpt/web-platform-tests/web-animations/interfaces/Animatable/animate-no-browsing-context.html
index 10371959d33..61a7502a988 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/Animatable/animate-no-browsing-context.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/Animatable/animate-no-browsing-context.html
@@ -1,8 +1,8 @@
<!doctype html>
<meta charset=utf-8>
-<title>Animatable.animate tests in combination with elements in documents
+<title>Animatable.animate in combination with elements in documents
without a browsing context</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#dom-animatable-animate">
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animatable-animate">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -76,16 +76,15 @@ promise_test(t => {
const div = xhrdoc.getElementById('test');
anim = div.animate(null);
anim.timeline = document.timeline;
- assert_equals(anim.playState, 'pending',
- 'The animation should be initially pending');
+ assert_true(anim.pending, 'The animation should be initially pending');
return waitForAnimationFrames(2);
}).then(() => {
// Because the element is in a document without a browsing context, it will
// not be rendered and hence the user agent will never deem it ready to
// animate.
- assert_equals(anim.playState, 'pending',
- 'The animation should still be pending after replacing'
- + ' the document timeline');
+ assert_true(anim.pending,
+ 'The animation should still be pending after replacing'
+ + ' the document timeline');
});
}, 'Replacing the timeline of an animation targetting an element in a'
+ ' document without a browsing context leaves it in the pending state');
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/Animatable/animate.html b/tests/wpt/web-platform-tests/web-animations/interfaces/Animatable/animate.html
index a07103ccc7b..36c4ee148e8 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/Animatable/animate.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/Animatable/animate.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>Animatable.animate tests</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#dom-animatable-animate">
+<title>Animatable.animate</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animatable-animate">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -16,16 +16,16 @@
// Tests on Element
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate(null);
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate(null);
assert_class_string(anim, 'Animation', 'Returned object is an Animation');
}, 'Element.animate() creates an Animation object');
-test(function(t) {
- var iframe = window.frames[0];
- var div = createDiv(t, iframe.document);
- var anim = Element.prototype.animate.call(div, null);
+test(t => {
+ const iframe = window.frames[0];
+ const div = createDiv(t, iframe.document);
+ const anim = Element.prototype.animate.call(div, null);
assert_equals(Object.getPrototypeOf(anim), iframe.Animation.prototype,
'The prototype of the created Animation is that defined on'
+ ' the relevant global for the target element');
@@ -35,17 +35,17 @@ test(function(t) {
}, 'Element.animate() creates an Animation object in the relevant realm of'
+ ' the target element');
-test(function(t) {
- var div = createDiv(t);
- var anim = Element.prototype.animate.call(div, null);
+test(t => {
+ const div = createDiv(t);
+ const anim = Element.prototype.animate.call(div, null);
assert_class_string(anim.effect, 'KeyframeEffect',
'Returned Animation has a KeyframeEffect');
}, 'Element.animate() creates an Animation object with a KeyframeEffect');
-test(function(t) {
- var iframe = window.frames[0];
- var div = createDiv(t, iframe.document);
- var anim = Element.prototype.animate.call(div, null);
+test(t => {
+ const iframe = window.frames[0];
+ const div = createDiv(t, iframe.document);
+ const anim = Element.prototype.animate.call(div, null);
assert_equals(Object.getPrototypeOf(anim.effect),
iframe.KeyframeEffect.prototype,
'The prototype of the created KeyframeEffect is that defined on'
@@ -57,10 +57,10 @@ test(function(t) {
}, 'Element.animate() creates an Animation object with a KeyframeEffect'
+ ' that is created in the relevant realm of the target element');
-test(function(t) {
- var iframe = window.frames[0];
- var div = createDiv(t, iframe.document);
- var anim = div.animate(null);
+test(t => {
+ const iframe = window.frames[0];
+ const div = createDiv(t, iframe.document);
+ const anim = div.animate(null);
assert_equals(Object.getPrototypeOf(anim.effect.timing),
iframe.AnimationEffectTiming.prototype,
'The prototype of the created AnimationEffectTiming is that'
@@ -73,91 +73,91 @@ test(function(t) {
+ ' whose AnimationEffectTiming object is created in the relevant realm'
+ ' of the target element');
-gEmptyKeyframeListTests.forEach(function(subTest) {
- test(function(t) {
- var div = createDiv(t);
- var anim = div.animate(subTest, 2000);
+for (const subtest of gEmptyKeyframeListTests) {
+ test(t => {
+ const div = createDiv(t);
+ const anim = div.animate(subtest, 2000);
assert_not_equals(anim, null);
}, 'Element.animate() accepts empty keyframe lists ' +
- `(input: ${JSON.stringify(subTest)})`);
-});
+ `(input: ${JSON.stringify(subtest)})`);
+}
-gKeyframesTests.forEach(function(subtest) {
- test(function(t) {
- var div = createDiv(t);
- var anim = div.animate(subtest.input, 2000);
+for (const subtest of gKeyframesTests) {
+ test(t => {
+ const div = createDiv(t);
+ const anim = div.animate(subtest.input, 2000);
assert_frame_lists_equal(anim.effect.getKeyframes(), subtest.output);
- }, 'Element.animate() accepts ' + subtest.desc);
-});
+ }, `Element.animate() accepts ${subtest.desc}`);
+}
-gInvalidKeyframesTests.forEach(function(subtest) {
- test(function(t) {
- var div = createDiv(t);
- assert_throws(new TypeError, function() {
+for (const subtest of gInvalidKeyframesTests) {
+ test(t => {
+ const div = createDiv(t);
+ assert_throws(new TypeError, () => {
div.animate(subtest.input, 2000);
});
- }, 'Element.animate() does not accept ' + subtest.desc);
-});
+ }, `Element.animate() does not accept ${subtest.desc}`);
+}
-gInvalidEasings.forEach(invalidEasing => {
- test(function(t) {
- var div = createDiv(t);
+for (const invalidEasing of gInvalidEasings) {
+ test(t => {
+ const div = createDiv(t);
assert_throws(new TypeError, () => {
div.animate({ easing: invalidEasing }, 2000);
});
}, `Element.animate() does not accept invalid easing: '${invalidEasing}'`);
-});
+}
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
assert_equals(anim.effect.timing.duration, 2000);
// Also check that unspecified parameters receive their default values
assert_equals(anim.effect.timing.fill, 'auto');
}, 'Element.animate() accepts a double as an options argument');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] },
- { duration: Infinity, fill: 'forwards' });
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] },
+ { duration: Infinity, fill: 'forwards' });
assert_equals(anim.effect.timing.duration, Infinity);
assert_equals(anim.effect.timing.fill, 'forwards');
// Also check that unspecified parameters receive their default values
assert_equals(anim.effect.timing.direction, 'normal');
}, 'Element.animate() accepts a KeyframeAnimationOptions argument');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] });
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] });
assert_equals(anim.effect.timing.duration, 'auto');
}, 'Element.animate() accepts an absent options argument');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
assert_equals(anim.id, '');
}, 'Element.animate() correctly sets the id attribute when no id is specified');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, { id: 'test' });
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, { id: 'test' });
assert_equals(anim.id, 'test');
}, 'Element.animate() correctly sets the id attribute');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
assert_equals(anim.timeline, document.timeline);
}, 'Element.animate() correctly sets the Animation\'s timeline');
-async_test(function(t) {
- var iframe = document.createElement('iframe');
+async_test(t => {
+ const iframe = document.createElement('iframe');
iframe.width = 10;
iframe.height = 10;
- iframe.addEventListener('load', t.step_func(function() {
- var div = createDiv(t, iframe.contentDocument);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+ iframe.addEventListener('load', t.step_func(() => {
+ const div = createDiv(t, iframe.contentDocument);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
assert_equals(anim.timeline, iframe.contentDocument.timeline);
iframe.remove();
t.done();
@@ -167,23 +167,23 @@ async_test(function(t) {
}, 'Element.animate() correctly sets the Animation\'s timeline when ' +
'triggered on an element in a different document');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- assert_equals(anim.playState, 'pending');
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+ assert_equals(anim.playState, 'running');
}, 'Element.animate() calls play on the Animation');
// Tests on CSSPseudoElement
-test(function(t) {
- var pseudoTarget = createPseudo(t, 'before');
- var anim = pseudoTarget.animate(null);
+test(t => {
+ const pseudoTarget = createPseudo(t, 'before');
+ const anim = pseudoTarget.animate(null);
assert_class_string(anim, 'Animation', 'The returned object is an Animation');
}, 'CSSPseudoElement.animate() creates an Animation object');
-test(function(t) {
- var pseudoTarget = createPseudo(t, 'before');
- var anim = pseudoTarget.animate(null);
+test(t => {
+ const pseudoTarget = createPseudo(t, 'before');
+ const anim = pseudoTarget.animate(null);
assert_equals(anim.effect.target, pseudoTarget,
'The returned Animation targets to the correct object');
}, 'CSSPseudoElement.animate() creates an Animation object targeting ' +
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/Animatable/getAnimations.html b/tests/wpt/web-platform-tests/web-animations/interfaces/Animatable/getAnimations.html
index 49551a8ef2b..d05e2aa50b9 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/Animatable/getAnimations.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/Animatable/getAnimations.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>Animatable.getAnimations tests</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#dom-animatable-getanimations">
+<title>Animatable.getAnimations</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animatable-getanimations">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -9,62 +9,148 @@
<script>
'use strict';
-test(function(t) {
- var div = createDiv(t);
+test(t => {
+ const div = createDiv(t);
assert_array_equals(div.getAnimations(), []);
-}, 'Test getAnimations on element with no animations');
+}, 'Returns an empty array for an element with no animations');
-test(function(t) {
- var div = createDiv(t);
- var animationA = div.animate(null, 100 * MS_PER_SEC);
- var animationB = div.animate(null, 100 * MS_PER_SEC);
+test(t => {
+ const div = createDiv(t);
+ const animationA = div.animate(null, 100 * MS_PER_SEC);
+ const animationB = div.animate(null, 100 * MS_PER_SEC);
assert_array_equals(div.getAnimations(), [animationA, animationB]);
-}, 'Test getAnimations on element with two animations');
+}, 'Returns both animations for an element with two animations');
-test(function(t) {
- var divA = createDiv(t);
- var divB = createDiv(t);
- var animationA = divA.animate(null, 100 * MS_PER_SEC);
- var animationB = divB.animate(null, 100 * MS_PER_SEC);
+test(t => {
+ const divA = createDiv(t);
+ const divB = createDiv(t);
+ const animationA = divA.animate(null, 100 * MS_PER_SEC);
+ const animationB = divB.animate(null, 100 * MS_PER_SEC);
assert_array_equals(divA.getAnimations(), [animationA], 'divA');
assert_array_equals(divB.getAnimations(), [animationB], 'divB');
-}, 'Test getAnimations on separate elements with separate animations');
+}, 'Returns only the animations specific to each sibling element');
-test(function(t) {
- var divParent = createDiv(t);
- var divChild = createDiv(t);
+test(t => {
+ const divParent = createDiv(t);
+ const divChild = createDiv(t);
divParent.appendChild(divChild);
- var animationParent = divParent.animate(null, 100 * MS_PER_SEC);
- var animationChild = divChild.animate(null, 100 * MS_PER_SEC);
- assert_array_equals(divParent.getAnimations(), [animationParent], 'divParent');
+ const animationParent = divParent.animate(null, 100 * MS_PER_SEC);
+ const animationChild = divChild.animate(null, 100 * MS_PER_SEC);
+ assert_array_equals(divParent.getAnimations(), [animationParent],
+ 'divParent');
assert_array_equals(divChild.getAnimations(), [animationChild], 'divChild');
-}, 'Test getAnimations on parent and child elements with separate animations');
+}, 'Returns only the animations specific to each parent/child element');
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate(null, 100 * MS_PER_SEC);
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(null, 100 * MS_PER_SEC);
animation.finish();
assert_array_equals(div.getAnimations(), []);
-}, 'Test getAnimations on element with finished fill none animation');
+}, 'Does not return finished animations that do not fill forwards');
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate(null, {
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(null, {
duration: 100 * MS_PER_SEC,
fill: 'forwards',
});
animation.finish();
assert_array_equals(div.getAnimations(), [animation]);
-}, 'Test getAnimations on element with finished fill forwards animation');
+}, 'Returns finished animations that fill forwards');
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate(null, {
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(null, {
duration: 100 * MS_PER_SEC,
delay: 100 * MS_PER_SEC,
});
assert_array_equals(div.getAnimations(), [animation]);
-}, 'Test getAnimations on element with delayed animation');
+}, 'Returns animations in their delay phase');
+
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(null, 100 * MS_PER_SEC);
+
+ animation.finish();
+ assert_array_equals(div.getAnimations(), [],
+ 'Animation should not be returned when it is finished');
+
+ animation.effect.timing.duration += 100 * MS_PER_SEC;
+ assert_array_equals(div.getAnimations(), [animation],
+ 'Animation should be returned after extending the'
+ + ' duration');
+
+ animation.effect.timing.duration = 0;
+ assert_array_equals(div.getAnimations(), [],
+ 'Animation should not be returned after setting the'
+ + ' duration to zero');
+}, 'Returns animations based on dynamic changes to individual'
+ + ' animations\' duration');
+
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(null, 100 * MS_PER_SEC);
+
+ animation.effect.timing.endDelay = -200 * MS_PER_SEC;
+ assert_array_equals(div.getAnimations(), [],
+ 'Animation should not be returned after setting a'
+ + ' negative end delay such that the end time is less'
+ + ' than the current time');
+
+ animation.effect.timing.endDelay = 100 * MS_PER_SEC;
+ assert_array_equals(div.getAnimations(), [animation],
+ 'Animation should be returned after setting a positive'
+ + ' end delay such that the end time is more than the'
+ + ' current time');
+}, 'Returns animations based on dynamic changes to individual'
+ + ' animations\' end delay');
+
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(null, 100 * MS_PER_SEC);
+
+ animation.finish();
+ assert_array_equals(div.getAnimations(), [],
+ 'Animation should not be returned when it is finished');
+
+ animation.effect.timing.iterations = 10;
+ assert_array_equals(div.getAnimations(), [animation],
+ 'Animation should be returned after inreasing the'
+ + ' number of iterations');
+
+ animation.effect.timing.iterations = 0;
+ assert_array_equals(div.getAnimations(), [],
+ 'Animations should not be returned after setting the'
+ + ' iteration count to zero');
+
+ animation.effect.timing.iterations = Infinity;
+ assert_array_equals(div.getAnimations(), [animation],
+ 'Animation should be returned after inreasing the'
+ + ' number of iterations to infinity');
+}, 'Returns animations based on dynamic changes to individual'
+ + ' animations\' iteration count');
+
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(null,
+ { duration: 100 * MS_PER_SEC,
+ delay: 50 * MS_PER_SEC,
+ endDelay: -50 * MS_PER_SEC });
+
+ assert_array_equals(div.getAnimations(), [animation],
+ 'Animation should be returned at during delay phase');
+
+ animation.currentTime = 50 * MS_PER_SEC;
+ assert_array_equals(div.getAnimations(), [animation],
+ 'Animation should be returned after seeking to the start'
+ + ' of the active interval');
+
+ animation.currentTime = 100 * MS_PER_SEC;
+ assert_array_equals(div.getAnimations(), [],
+ 'Animation should not be returned after seeking to the'
+ + ' clipped end of the active interval');
+}, 'Returns animations based on dynamic changes to individual'
+ + ' animations\' current time');
</script>
</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/cancel.html b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/cancel.html
index f8f174abd91..be1bb5d7847 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/cancel.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/cancel.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>Animation.cancel()</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-cancel">
+<title>Animation.cancel</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animation-cancel">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -10,11 +10,13 @@
<script>
'use strict';
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({transform: ['translate(100px)', 'translate(100px)']},
- 100 * MS_PER_SEC);
- return animation.ready.then(function() {
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(
+ { transform: ['translate(100px)', 'translate(100px)'] },
+ 100 * MS_PER_SEC
+ );
+ return animation.ready.then(() => {
assert_not_equals(getComputedStyle(div).transform, 'none',
'transform style is animated before cancelling');
animation.cancel();
@@ -23,10 +25,10 @@ promise_test(function(t) {
});
}, 'Animated style is cleared after calling Animation.cancel()');
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({marginLeft: ['100px', '200px']},
- 100 * MS_PER_SEC);
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({ marginLeft: ['100px', '200px'] },
+ 100 * MS_PER_SEC);
animation.effect.timing.easing = 'linear';
animation.cancel();
assert_equals(getComputedStyle(div).marginLeft, '0px',
@@ -38,11 +40,11 @@ test(function(t) {
+ ' seeked');
}, 'After cancelling an animation, it can still be seeked');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({marginLeft:['100px', '200px']},
- 100 * MS_PER_SEC);
- return animation.ready.then(function() {
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({ marginLeft:['100px', '200px'] },
+ 100 * MS_PER_SEC);
+ return animation.ready.then(() => {
animation.cancel();
assert_equals(getComputedStyle(div).marginLeft, '0px',
'margin-left style is not animated after cancelling');
@@ -50,7 +52,7 @@ promise_test(function(t) {
assert_equals(getComputedStyle(div).marginLeft, '100px',
'margin-left style is animated after re-starting animation');
return animation.ready;
- }).then(function() {
+ }).then(() => {
assert_equals(animation.playState, 'running',
'Animation succeeds in running after being re-started');
});
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/constructor.html b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/constructor.html
index 4f76194b6f0..c00c66ea1d4 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/constructor.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/constructor.html
@@ -1,8 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>Animation constructor tests</title>
-<link rel="help" href="http://w3c.github.io/web-animations/#dom-animation-animation">
-<link rel="author" title="Hiroyuki Ikezoe" href="mailto:hiikezoe@mozilla-japan.org">
+<title>Animation constructor</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animation-animation">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -10,9 +9,9 @@
<div id="log"></div>
<div id="target"></div>
<script>
-"use strict";
+'use strict';
-var gTarget = document.getElementById("target");
+const gTarget = document.getElementById('target');
function createEffect() {
return new KeyframeEffectReadOnly(gTarget, { opacity: [0, 1] });
@@ -22,94 +21,94 @@ function createNull() {
return null;
}
-var gTestArguments = [
+const gTestArguments = [
{
createEffect: createNull,
timeline: null,
expectedTimeline: null,
- expectedTimelineDescription: "null",
- description: "with null effect and null timeline"
+ expectedTimelineDescription: 'null',
+ description: 'with null effect and null timeline'
},
{
createEffect: createNull,
timeline: document.timeline,
expectedTimeline: document.timeline,
- expectedTimelineDescription: "document.timeline",
- description: "with null effect and non-null timeline"
+ expectedTimelineDescription: 'document.timeline',
+ description: 'with null effect and non-null timeline'
},
{
createEffect: createNull,
expectedTimeline: document.timeline,
- expectedTimelineDescription: "document.timeline",
- description: "with null effect and no timeline parameter"
+ expectedTimelineDescription: 'document.timeline',
+ description: 'with null effect and no timeline parameter'
},
{
createEffect: createEffect,
timeline: null,
expectedTimeline: null,
- expectedTimelineDescription: "null",
- description: "with non-null effect and null timeline"
+ expectedTimelineDescription: 'null',
+ description: 'with non-null effect and null timeline'
},
{
createEffect: createEffect,
timeline: document.timeline,
expectedTimeline: document.timeline,
- expectedTimelineDescription: "document.timeline",
- description: "with non-null effect and non-null timeline"
+ expectedTimelineDescription: 'document.timeline',
+ description: 'with non-null effect and non-null timeline'
},
{
createEffect: createEffect,
expectedTimeline: document.timeline,
- expectedTimelineDescription: "document.timeline",
- description: "with non-null effect and no timeline parameter"
+ expectedTimelineDescription: 'document.timeline',
+ description: 'with non-null effect and no timeline parameter'
},
];
-gTestArguments.forEach(function(args) {
- test(function(t) {
- var effect = args.createEffect();
- var animation = new Animation(effect, args.timeline);
+for (const args of gTestArguments) {
+ test(t => {
+ const effect = args.createEffect();
+ const animation = new Animation(effect, args.timeline);
assert_not_equals(animation, null,
- "An animation sohuld be created");
+ 'An animation sohuld be created');
assert_equals(animation.effect, effect,
- "Animation returns the same effect passed to " +
- "the Constructor");
+ 'Animation returns the same effect passed to ' +
+ 'the Constructor');
assert_equals(animation.timeline, args.expectedTimeline,
- "Animation timeline should be " + args.expectedTimelineDescription);
- assert_equals(animation.playState, "idle",
- "Animation.playState should be initially 'idle'");
- }, "Animation can be constructed " + args.description);
-});
+ 'Animation timeline should be ' + args.expectedTimelineDescription);
+ assert_equals(animation.playState, 'idle',
+ 'Animation.playState should be initially \'idle\'');
+ }, 'Animation can be constructed ' + args.description);
+}
-test(function(t) {
- var effect = new KeyframeEffectReadOnly(null,
- { left: ["10px", "20px"] },
- { duration: 10000,
- fill: "forwards" });
- var anim = new Animation(effect, document.timeline);
+test(t => {
+ const effect = new KeyframeEffectReadOnly(null,
+ { left: ['10px', '20px'] },
+ { duration: 10000,
+ fill: 'forwards' });
+ const anim = new Animation(effect, document.timeline);
anim.pause();
assert_equals(effect.getComputedTiming().progress, 0.0);
anim.currentTime += 5000;
assert_equals(effect.getComputedTiming().progress, 0.5);
anim.finish();
assert_equals(effect.getComputedTiming().progress, 1.0);
-}, "Animation constructed by an effect with null target runs normally");
+}, 'Animation constructed by an effect with null target runs normally');
-async_test(function(t) {
- var iframe = document.createElement('iframe');
+async_test(t => {
+ const iframe = document.createElement('iframe');
- iframe.addEventListener('load', t.step_func(function() {
- var div = createDiv(t, iframe.contentDocument);
- var effect = new KeyframeEffectReadOnly(div, null, 10000);
- var anim = new Animation(effect);
+ iframe.addEventListener('load', t.step_func(() => {
+ const div = createDiv(t, iframe.contentDocument);
+ const effect = new KeyframeEffectReadOnly(div, null, 10000);
+ const anim = new Animation(effect);
assert_equals(anim.timeline, document.timeline);
iframe.remove();
t.done();
}));
document.body.appendChild(iframe);
-}, "Animation constructed with a keyframe that target element is in iframe");
+}, 'Animation constructed with a keyframe that target element is in iframe');
</script>
</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/effect.html b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/effect.html
index 3c9c4f079c0..175fc31341b 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/effect.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/effect.html
@@ -1,29 +1,29 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>Animation.effect tests</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-effect">
+<title>Animation.effect</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animation-effect">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
<body>
<div id="log"></div>
<script>
-"use strict";
+'use strict';
-test(function(t) {
- var anim = new Animation();
- assert_equals(anim.effect, null, "initial effect is null");
+test(t => {
+ const anim = new Animation();
+ assert_equals(anim.effect, null, 'initial effect is null');
- var newEffect = new KeyframeEffectReadOnly(createDiv(t), null);
+ const newEffect = new KeyframeEffectReadOnly(createDiv(t), null);
anim.effect = newEffect;
- assert_equals(anim.effect, newEffect, "new effect is set");
-}, "effect is set correctly.");
+ assert_equals(anim.effect, newEffect, 'new effect is set');
+}, 'effect is set correctly.');
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({ left: ['100px', '100px'] },
- { fill: 'forwards' });
- var effect = animation.effect;
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({ left: ['100px', '100px'] },
+ { fill: 'forwards' });
+ const effect = animation.effect;
assert_equals(getComputedStyle(div).left, '100px',
'animation is initially having an effect');
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/finish.html b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/finish.html
index 9b9c4c710e3..1f81867ebdd 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/finish.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/finish.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>Animation.finish()</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-finish">
+<title>Animation.finish</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animation-finish">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -10,32 +10,32 @@
<script>
'use strict';
-var gKeyFrames = { 'marginLeft': ['100px', '200px'] };
+const gKeyFrames = { 'marginLeft': ['100px', '200px'] };
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
animation.playbackRate = 0;
- assert_throws({name: 'InvalidStateError'}, function() {
+ assert_throws({name: 'InvalidStateError'}, () => {
animation.finish();
});
}, 'Test exceptions when finishing non-running animation');
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate(gKeyFrames,
- {duration : 100 * MS_PER_SEC,
- iterations : Infinity});
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(gKeyFrames,
+ { duration : 100 * MS_PER_SEC,
+ iterations : Infinity });
- assert_throws({name: 'InvalidStateError'}, function() {
+ assert_throws({name: 'InvalidStateError'}, () => {
animation.finish();
});
}, 'Test exceptions when finishing infinite animation');
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
animation.finish();
assert_equals(animation.currentTime, 100 * MS_PER_SEC,
@@ -43,9 +43,9 @@ test(function(t) {
'of the active duration');
}, 'Test finishing of animation');
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
// 1s past effect end
animation.currentTime =
animation.effect.getComputedTiming().endTime + 1 * MS_PER_SEC;
@@ -56,11 +56,11 @@ test(function(t) {
'end of the active duration');
}, 'Test finishing of animation with a current time past the effect end');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
animation.currentTime = 100 * MS_PER_SEC;
- return animation.finished.then(function() {
+ return animation.finished.then(() => {
animation.playbackRate = -1;
animation.finish();
@@ -70,11 +70,11 @@ promise_test(function(t) {
});
}, 'Test finishing of reversed animation');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
animation.currentTime = 100 * MS_PER_SEC;
- return animation.finished.then(function() {
+ return animation.finished.then(() => {
animation.playbackRate = -1;
animation.currentTime = -1000;
animation.finish();
@@ -85,11 +85,11 @@ promise_test(function(t) {
});
}, 'Test finishing of reversed animation with a current time less than zero');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
animation.pause();
- return animation.ready.then(function() {
+ return animation.ready.then(() => {
animation.finish();
assert_equals(animation.playState, 'finished',
@@ -102,9 +102,9 @@ promise_test(function(t) {
});
}, 'Test finish() while paused');
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
animation.pause();
// Update playbackRate so we can test that the calculated startTime
// respects it
@@ -121,9 +121,9 @@ test(function(t) {
'be set after calling finish()');
}, 'Test finish() while pause-pending with positive playbackRate');
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
animation.pause();
animation.playbackRate = -2;
animation.finish();
@@ -136,9 +136,9 @@ test(function(t) {
'set after calling finish()');
}, 'Test finish() while pause-pending with negative playbackRate');
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
animation.playbackRate = 0.5;
animation.finish();
@@ -155,10 +155,10 @@ test(function(t) {
// - In that case even after calling finish() we should still be pending but
// the current time should be updated
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
- return animation.ready.then(function() {
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+ return animation.ready.then(() => {
animation.pause();
animation.play();
// We are now in the unusual situation of being play-pending whilst having
@@ -172,13 +172,13 @@ promise_test(function(t) {
});
}, 'Test finish() during aborted pause');
-promise_test(function(t) {
- var div = createDiv(t);
+promise_test(t => {
+ const div = createDiv(t);
div.style.marginLeft = '10px';
- var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
- return animation.ready.then(function() {
+ const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+ return animation.ready.then(() => {
animation.finish();
- var marginLeft = parseFloat(getComputedStyle(div).marginLeft);
+ const marginLeft = parseFloat(getComputedStyle(div).marginLeft);
assert_equals(marginLeft, 10,
'The computed style should be reset when finish() is ' +
@@ -186,34 +186,34 @@ promise_test(function(t) {
});
}, 'Test resetting of computed style');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
- var resolvedFinished = false;
- animation.finished.then(function() {
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+ let resolvedFinished = false;
+ animation.finished.then(() => {
resolvedFinished = true;
});
- return animation.ready.then(function() {
+ return animation.ready.then(() => {
animation.finish();
- }).then(function() {
+ }).then(() => {
assert_true(resolvedFinished,
'Animation.finished should be resolved soon after ' +
'Animation.finish()');
});
}, 'Test finish() resolves finished promise synchronously');
-promise_test(function(t) {
- var effect = new KeyframeEffectReadOnly(null, gKeyFrames, 100 * MS_PER_SEC);
- var animation = new Animation(effect, document.timeline);
- var resolvedFinished = false;
- animation.finished.then(function() {
+promise_test(t => {
+ const effect = new KeyframeEffectReadOnly(null, gKeyFrames, 100 * MS_PER_SEC);
+ const animation = new Animation(effect, document.timeline);
+ let resolvedFinished = false;
+ animation.finished.then(() => {
resolvedFinished = true;
});
- return animation.ready.then(function() {
+ return animation.ready.then(() => {
animation.finish();
- }).then(function() {
+ }).then(() => {
assert_true(resolvedFinished,
'Animation.finished should be resolved soon after ' +
'Animation.finish()');
@@ -221,20 +221,20 @@ promise_test(function(t) {
}, 'Test finish() resolves finished promise synchronously with an animation ' +
'without a target');
-promise_test(function(t) {
- var effect = new KeyframeEffectReadOnly(null, gKeyFrames, 100 * MS_PER_SEC);
- var animation = new Animation(effect, document.timeline);
+promise_test(t => {
+ const effect = new KeyframeEffectReadOnly(null, gKeyFrames, 100 * MS_PER_SEC);
+ const animation = new Animation(effect, document.timeline);
animation.play();
- var resolvedFinished = false;
- animation.finished.then(function() {
+ let resolvedFinished = false;
+ animation.finished.then(() => {
resolvedFinished = true;
});
- return animation.ready.then(function() {
+ return animation.ready.then(() => {
animation.currentTime = animation.effect.getComputedTiming().endTime - 1;
return waitForAnimationFrames(2);
- }).then(function() {
+ }).then(() => {
assert_true(resolvedFinished,
'Animation.finished should be resolved soon after ' +
'Animation finishes normally');
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/finished.html b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/finished.html
index 006b54a0af3..79700f317ec 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/finished.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/finished.html
@@ -1,20 +1,20 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Animation.finished</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-finished">
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animation-finished">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
<body>
<div id="log"></div>
<script>
-"use strict";
+'use strict';
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
- var previousFinishedPromise = animation.finished;
- return animation.ready.then(function() {
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
+ const previousFinishedPromise = animation.finished;
+ return animation.ready.then(() => {
assert_equals(animation.finished, previousFinishedPromise,
'Finished promise is the same object when playing starts');
animation.pause();
@@ -27,18 +27,18 @@ promise_test(function(t) {
animation.currentTime = 100 * MS_PER_SEC;
return animation.finished;
- }).then(function() {
+ }).then(() => {
assert_equals(animation.finished, previousFinishedPromise,
'Finished promise is the same object when playing completes');
});
}, 'Test pausing then playing does not change the finished promise');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
- var previousFinishedPromise = animation.finished;
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
+ let previousFinishedPromise = animation.finished;
animation.finish();
- return animation.finished.then(function() {
+ return animation.finished.then(() => {
assert_equals(animation.finished, previousFinishedPromise,
'Finished promise is the same object when playing completes');
animation.play();
@@ -53,12 +53,12 @@ promise_test(function(t) {
});
}, 'Test restarting a finished animation');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
- var previousFinishedPromise;
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
+ let previousFinishedPromise;
animation.finish();
- return animation.finished.then(function() {
+ return animation.finished.then(() => {
previousFinishedPromise = animation.finished;
animation.playbackRate = -1;
assert_not_equals(animation.finished, previousFinishedPromise,
@@ -66,7 +66,7 @@ promise_test(function(t) {
'finished promise');
animation.currentTime = 0;
return animation.finished;
- }).then(function() {
+ }).then(() => {
previousFinishedPromise = animation.finished;
animation.play();
assert_not_equals(animation.finished, previousFinishedPromise,
@@ -75,12 +75,12 @@ promise_test(function(t) {
});
}, 'Test restarting a reversed finished animation');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
- var previousFinishedPromise = animation.finished;
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
+ const previousFinishedPromise = animation.finished;
animation.finish();
- return animation.finished.then(function() {
+ return animation.finished.then(() => {
animation.currentTime = 100 * MS_PER_SEC + 1000;
assert_equals(animation.finished, previousFinishedPromise,
'Finished promise is unchanged jumping past end of ' +
@@ -88,71 +88,71 @@ promise_test(function(t) {
});
}, 'Test redundant finishing of animation');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
// Setup callback to run if finished promise is resolved
- var finishPromiseResolved = false;
- animation.finished.then(function() {
+ let finishPromiseResolved = false;
+ animation.finished.then(() => {
finishPromiseResolved = true;
});
- return animation.ready.then(function() {
+ return animation.ready.then(() => {
// Jump to mid-way in interval and pause
animation.currentTime = 100 * MS_PER_SEC / 2;
animation.pause();
return animation.ready;
- }).then(function() {
+ }).then(() => {
// Jump to the end
// (But don't use finish() since that should unpause as well)
animation.currentTime = 100 * MS_PER_SEC;
return waitForAnimationFrames(2);
- }).then(function() {
+ }).then(() => {
assert_false(finishPromiseResolved,
'Finished promise should not resolve when paused');
});
}, 'Finished promise does not resolve when paused');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
// Setup callback to run if finished promise is resolved
- var finishPromiseResolved = false;
- animation.finished.then(function() {
+ let finishPromiseResolved = false;
+ animation.finished.then(() => {
finishPromiseResolved = true;
});
- return animation.ready.then(function() {
+ return animation.ready.then(() => {
// Jump to mid-way in interval and pause
animation.currentTime = 100 * MS_PER_SEC / 2;
animation.pause();
// Jump to the end
animation.currentTime = 100 * MS_PER_SEC;
return waitForAnimationFrames(2);
- }).then(function() {
+ }).then(() => {
assert_false(finishPromiseResolved,
'Finished promise should not resolve when pause-pending');
});
}, 'Finished promise does not resolve when pause-pending');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
animation.finish();
- return animation.finished.then(function(resolvedAnimation) {
+ return animation.finished.then(resolvedAnimation => {
assert_equals(resolvedAnimation, animation,
'Object identity of animation passed to Promise callback'
+ ' matches the animation object owning the Promise');
});
}, 'The finished promise is fulfilled with its Animation');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
- var previousFinishedPromise = animation.finished;
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
+ const previousFinishedPromise = animation.finished;
// Set up listeners on finished promise
- var retPromise = animation.finished.then(function() {
+ const retPromise = animation.finished.then(() => {
assert_unreached('finished promise was fulfilled');
- }).catch(function(err) {
+ }).catch(err => {
assert_equals(err.name, 'AbortError',
'finished promise is rejected with AbortError');
assert_not_equals(animation.finished, previousFinishedPromise,
@@ -163,52 +163,31 @@ promise_test(function(t) {
animation.cancel();
return retPromise;
-}, 'finished promise is rejected when an animation is cancelled by calling ' +
+}, 'finished promise is rejected when an animation is canceled by calling ' +
'cancel()');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
- var previousFinishedPromise = animation.finished;
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
+ const previousFinishedPromise = animation.finished;
animation.finish();
- return animation.finished.then(function() {
+ return animation.finished.then(() => {
animation.cancel();
assert_not_equals(animation.finished, previousFinishedPromise,
'A new finished promise should be created when'
- + ' cancelling a finished animation');
+ + ' canceling a finished animation');
});
-}, 'cancelling an already-finished animation replaces the finished promise');
+}, 'canceling an already-finished animation replaces the finished promise');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
- animation.cancel();
- // The spec says we still create a new finished promise and reject the old
- // one even if we're already idle. That behavior might change, but for now
- // test that we do that.
- var retPromise = animation.finished.catch(function(err) {
- assert_equals(err.name, 'AbortError',
- 'finished promise is rejected with AbortError');
- });
-
- // Redundant call to cancel();
- var previousFinishedPromise = animation.finished;
- animation.cancel();
- assert_not_equals(animation.finished, previousFinishedPromise,
- 'A redundant call to cancel() should still generate a new'
- + ' finished promise');
- return retPromise;
-}, 'cancelling an idle animation still replaces the finished promise');
-
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
const HALF_DUR = 100 * MS_PER_SEC / 2;
const QUARTER_DUR = 100 * MS_PER_SEC / 4;
- var gotNextFrame = false;
- var currentTimeBeforeShortening;
+ let gotNextFrame = false;
+ let currentTimeBeforeShortening;
animation.currentTime = HALF_DUR;
- return animation.ready.then(function() {
+ return animation.ready.then(() => {
currentTimeBeforeShortening = animation.currentTime;
animation.effect.timing.duration = QUARTER_DUR;
// Below we use gotNextFrame to check that shortening of the animation
@@ -216,17 +195,17 @@ promise_test(function(t) {
// getting resolved on the next animation frame. This relies on the fact
// that the promises are resolved as a micro-task before the next frame
// happens.
- waitForAnimationFrames(1).then(function() {
+ waitForAnimationFrames(1).then(() => {
gotNextFrame = true;
});
return animation.finished;
- }).then(function() {
+ }).then(() => {
assert_false(gotNextFrame, 'shortening of the animation duration should ' +
'resolve the finished promise');
assert_equals(animation.currentTime, currentTimeBeforeShortening,
'currentTime should be unchanged when duration shortened');
- var previousFinishedPromise = animation.finished;
+ const previousFinishedPromise = animation.finished;
animation.effect.timing.duration = 100 * MS_PER_SEC;
assert_not_equals(animation.finished, previousFinishedPromise,
'Finished promise should change after lengthening the ' +
@@ -234,16 +213,16 @@ promise_test(function(t) {
});
}, 'Test finished promise changes for animation duration changes');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
- var retPromise = animation.ready.then(function() {
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
+ const retPromise = animation.ready.then(() => {
animation.playbackRate = 0;
animation.currentTime = 100 * MS_PER_SEC + 1000;
return waitForAnimationFrames(2);
});
- animation.finished.then(t.step_func(function() {
+ animation.finished.then(t.step_func(() => {
assert_unreached('finished promise should not resolve when playbackRate ' +
'is zero');
}));
@@ -251,21 +230,21 @@ promise_test(function(t) {
return retPromise;
}, 'Test finished promise changes when playbackRate == 0');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
- return animation.ready.then(function() {
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
+ return animation.ready.then(() => {
animation.playbackRate = -1;
return animation.finished;
});
}, 'Test finished promise resolves when reaching to the natural boundary.');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
- var previousFinishedPromise = animation.finished;
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
+ const previousFinishedPromise = animation.finished;
animation.finish();
- return animation.finished.then(function() {
+ return animation.finished.then(() => {
animation.currentTime = 0;
assert_not_equals(animation.finished, previousFinishedPromise,
'Finished promise should change once a prior ' +
@@ -275,10 +254,10 @@ promise_test(function(t) {
}, 'Test finished promise changes when a prior finished promise resolved ' +
'and the animation falls out finished state');
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
- var previousFinishedPromise = animation.finished;
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
+ const previousFinishedPromise = animation.finished;
animation.currentTime = 100 * MS_PER_SEC;
animation.currentTime = 100 * MS_PER_SEC / 2;
assert_equals(animation.finished, previousFinishedPromise,
@@ -287,10 +266,10 @@ test(function(t) {
}, 'Test no new finished promise generated when finished state ' +
'is checked asynchronously');
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
- var previousFinishedPromise = animation.finished;
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
+ const previousFinishedPromise = animation.finished;
animation.finish();
animation.currentTime = 100 * MS_PER_SEC / 2;
assert_not_equals(animation.finished, previousFinishedPromise,
@@ -299,17 +278,17 @@ test(function(t) {
}, 'Test new finished promise generated when finished state ' +
'is checked synchronously');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
- var resolvedFinished = false;
- animation.finished.then(function() {
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
+ let resolvedFinished = false;
+ animation.finished.then(() => {
resolvedFinished = true;
});
- return animation.ready.then(function() {
+ return animation.ready.then(() => {
animation.finish();
animation.currentTime = 100 * MS_PER_SEC / 2;
- }).then(function() {
+ }).then(() => {
assert_true(resolvedFinished,
'Animation.finished should be resolved even if ' +
'the finished state is changed soon');
@@ -318,18 +297,18 @@ promise_test(function(t) {
}, 'Test synchronous finished promise resolved even if finished state ' +
'is changed soon');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
- var resolvedFinished = false;
- animation.finished.then(function() {
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
+ let resolvedFinished = false;
+ animation.finished.then(() => {
resolvedFinished = true;
});
- return animation.ready.then(function() {
+ return animation.ready.then(() => {
animation.currentTime = 100 * MS_PER_SEC;
animation.finish();
- }).then(function() {
+ }).then(() => {
assert_true(resolvedFinished,
'Animation.finished should be resolved soon after finish() is ' +
'called even if there are other asynchronous promises just before it');
@@ -337,26 +316,26 @@ promise_test(function(t) {
}, 'Test synchronous finished promise resolved even if asynchronous ' +
'finished promise happens just before synchronous promise');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
- animation.finished.then(t.step_func(function() {
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
+ animation.finished.then(t.step_func(() => {
assert_unreached('Animation.finished should not be resolved');
}));
- return animation.ready.then(function() {
+ return animation.ready.then(() => {
animation.currentTime = 100 * MS_PER_SEC;
animation.currentTime = 100 * MS_PER_SEC / 2;
});
}, 'Test finished promise is not resolved when the animation ' +
'falls out finished state immediately');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
- return animation.ready.then(function() {
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
+ return animation.ready.then(() => {
animation.currentTime = 100 * MS_PER_SEC;
- animation.finished.then(t.step_func(function() {
+ animation.finished.then(t.step_func(() => {
assert_unreached('Animation.finished should not be resolved');
}));
animation.currentTime = 0;
@@ -366,24 +345,24 @@ promise_test(function(t) {
'falls out finished state even though the current finished ' +
'promise is generated soon after animation state became finished');
-promise_test(function(t) {
- var animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
- var ready = false;
+promise_test(t => {
+ const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
+ let ready = false;
animation.ready.then(
- t.step_func(function() {
+ t.step_func(() => {
ready = true;
}),
t.unreached_func('Ready promise must not be rejected')
);
- var testSuccess = animation.finished.then(
- t.step_func(function() {
+ const testSuccess = animation.finished.then(
+ t.step_func(() => {
assert_true(ready, 'Ready promise has resolved');
}),
t.unreached_func('Finished promise must not be rejected')
);
- var timeout = waitForAnimationFrames(3).then(function() {
+ const timeout = waitForAnimationFrames(3).then(() => {
return Promise.reject('Finished promise did not arrive in time');
});
@@ -391,24 +370,24 @@ promise_test(function(t) {
return Promise.race([timeout, testSuccess]);
}, 'Finished promise should be resolved after the ready promise is resolved');
-promise_test(function(t) {
- var animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
- var caught = false;
+promise_test(t => {
+ const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
+ let caught = false;
animation.ready.then(
t.unreached_func('Ready promise must not be resolved'),
- t.step_func(function() {
+ t.step_func(() => {
caught = true;
})
);
- var testSuccess = animation.finished.then(
+ const testSuccess = animation.finished.then(
t.unreached_func('Finished promise must not be resolved'),
- t.step_func(function() {
+ t.step_func(() => {
assert_true(caught, 'Ready promise has been rejected');
})
);
- var timeout = waitForAnimationFrames(3).then(function() {
+ const timeout = waitForAnimationFrames(3).then(() => {
return Promise.reject('Finished promise was not rejected in time');
});
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/id.html b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/id.html
index 2fadd562369..5b9586bfaf9 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/id.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/id.html
@@ -1,24 +1,24 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Animation.id</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-id">
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animation-id">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
<body>
<div id="log"></div>
<script>
-"use strict";
+'use strict';
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
assert_equals(animation.id, '', 'id for Animation is initially empty');
}, 'Animation.id initial value');
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
animation.id = 'anim';
assert_equals(animation.id, 'anim', 'animation.id reflects the value set');
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/idlharness.html b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/idlharness.html
index 74813e1fc37..30751460121 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/idlharness.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/idlharness.html
@@ -1,7 +1,7 @@
<!doctype html>
<meta charset=utf-8>
<title>Animation IDL</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#animation">
+<link rel="help" href="https://drafts.csswg.org/web-animations/#animation">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/WebIDLParser.js"></script>
@@ -20,6 +20,7 @@ interface Animation : EventTarget {
attribute double? currentTime;
attribute double playbackRate;
readonly attribute AnimationPlayState playState;
+ readonly attribute boolean pending;
readonly attribute Promise<Animation> ready;
readonly attribute Promise<Animation> finished;
attribute EventHandler onfinish;
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/oncancel.html b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/oncancel.html
index b8d9ced61ec..3e918a40d0d 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/oncancel.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/oncancel.html
@@ -1,24 +1,24 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Animation.oncancel</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-oncancel">
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animation-oncancel">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
<body>
<div id="log"></div>
<script>
-"use strict";
+'use strict';
-async_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
- var finishedTimelineTime;
- animation.finished.then().catch(function() {
+async_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
+ let finishedTimelineTime;
+ animation.finished.then().catch(() => {
finishedTimelineTime = animation.timeline.currentTime;
});
- animation.oncancel = t.step_func_done(function(event) {
+ animation.oncancel = t.step_func_done(event => {
assert_equals(event.currentTime, null,
'event.currentTime should be null');
assert_equals(event.timelineTime, finishedTimelineTime,
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/onfinish.html b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/onfinish.html
index 50e5bed6b13..79d1d7025a7 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/onfinish.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/onfinish.html
@@ -1,24 +1,24 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Animation.onfinish</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-onfinish">
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animation-onfinish">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
<body>
<div id="log"></div>
<script>
-"use strict";
+'use strict';
-async_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
- var finishedTimelineTime;
- animation.finished.then(function() {
+async_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
+ let finishedTimelineTime;
+ animation.finished.then(() => {
finishedTimelineTime = animation.timeline.currentTime;
});
- animation.onfinish = t.step_func_done(function(event) {
+ animation.onfinish = t.step_func_done(event => {
assert_equals(event.currentTime, 0,
'event.currentTime should be zero');
assert_equals(event.timelineTime, finishedTimelineTime,
@@ -30,16 +30,16 @@ async_test(function(t) {
}, 'onfinish event is fired when the currentTime < 0 and ' +
'the playbackRate < 0');
-async_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
+async_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
- var finishedTimelineTime;
- animation.finished.then(function() {
+ let finishedTimelineTime;
+ animation.finished.then(() => {
finishedTimelineTime = animation.timeline.currentTime;
});
- animation.onfinish = t.step_func_done(function(event) {
+ animation.onfinish = t.step_func_done(event => {
assert_equals(event.currentTime, 100 * MS_PER_SEC,
'event.currentTime should be the effect end');
assert_equals(event.timelineTime, finishedTimelineTime,
@@ -51,16 +51,16 @@ async_test(function(t) {
}, 'onfinish event is fired when the currentTime > 0 and ' +
'the playbackRate > 0');
-async_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
+async_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
- var finishedTimelineTime;
- animation.finished.then(function() {
+ let finishedTimelineTime;
+ animation.finished.then(() => {
finishedTimelineTime = animation.timeline.currentTime;
});
- animation.onfinish = t.step_func_done(function(event) {
+ animation.onfinish = t.step_func_done(event => {
assert_equals(event.currentTime, 100 * MS_PER_SEC,
'event.currentTime should be the effect end');
assert_equals(event.timelineTime, finishedTimelineTime,
@@ -71,45 +71,45 @@ async_test(function(t) {
animation.finish();
}, 'onfinish event is fired when animation.finish() is called');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
- animation.onfinish = function(event) {
+ animation.onfinish = event => {
assert_unreached('onfinish event should not be fired');
};
animation.currentTime = 100 * MS_PER_SEC / 2;
animation.pause();
- return animation.ready.then(function() {
+ return animation.ready.then(() => {
animation.currentTime = 100 * MS_PER_SEC;
return waitForAnimationFrames(2);
});
}, 'onfinish event is not fired when paused');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
- animation.onfinish = function(event) {
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
+ animation.onfinish = event => {
assert_unreached('onfinish event should not be fired');
};
- return animation.ready.then(function() {
+ return animation.ready.then(() => {
animation.playbackRate = 0;
animation.currentTime = 100 * MS_PER_SEC;
return waitForAnimationFrames(2);
});
}, 'onfinish event is not fired when the playbackRate is zero');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
- animation.onfinish = function(event) {
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
+ animation.onfinish = event => {
assert_unreached('onfinish event should not be fired');
};
- return animation.ready.then(function() {
+ return animation.ready.then(() => {
animation.currentTime = 100 * MS_PER_SEC;
animation.currentTime = 100 * MS_PER_SEC / 2;
return waitForAnimationFrames(2);
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/pause.html b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/pause.html
index bcfaf4a9b82..0649c2f617d 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/pause.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/pause.html
@@ -1,37 +1,37 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>Animation.pause()</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-pause">
+<title>Animation.pause</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animation-pause">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
<body>
<div id="log"></div>
<script>
-"use strict";
+'use strict';
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 1000 * MS_PER_SEC);
- var previousCurrentTime = animation.currentTime;
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 1000 * MS_PER_SEC);
+ let previousCurrentTime = animation.currentTime;
- return animation.ready.then(waitForAnimationFrames(1)).then(function() {
+ return animation.ready.then(waitForAnimationFrames(1)).then(() => {
assert_true(animation.currentTime >= previousCurrentTime,
'currentTime is initially increasing');
animation.pause();
return animation.ready;
- }).then(function() {
+ }).then(() => {
previousCurrentTime = animation.currentTime;
return waitForAnimationFrames(1);
- }).then(function() {
+ }).then(() => {
assert_equals(animation.currentTime, previousCurrentTime,
'currentTime does not increase after calling pause()');
});
}, 'pause() a running animation');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 1000 * MS_PER_SEC);
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 1000 * MS_PER_SEC);
// Go to idle state then pause
animation.cancel();
@@ -39,20 +39,20 @@ promise_test(function(t) {
assert_equals(animation.currentTime, 0, 'currentTime is set to 0');
assert_equals(animation.startTime, null, 'startTime is not set');
- assert_equals(animation.playState, 'pending', 'initially pause-pending');
+ assert_equals(animation.playState, 'paused', 'in paused play state');
+ assert_true(animation.pending, 'initially pause-pending');
// Check it still resolves as expected
- return animation.ready.then(function() {
- assert_equals(animation.playState, 'paused',
- 'resolves to paused state asynchronously');
+ return animation.ready.then(() => {
+ assert_false(animation.pending, 'no longer pending');
assert_equals(animation.currentTime, 0,
'keeps the initially set currentTime');
});
}, 'pause() from idle');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 1000 * MS_PER_SEC);
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 1000 * MS_PER_SEC);
animation.cancel();
animation.playbackRate = -1;
animation.pause();
@@ -60,35 +60,35 @@ promise_test(function(t) {
assert_equals(animation.currentTime, 1000 * MS_PER_SEC,
'currentTime is set to the effect end');
- return animation.ready.then(function() {
+ return animation.ready.then(() => {
assert_equals(animation.currentTime, 1000 * MS_PER_SEC,
'keeps the initially set currentTime');
});
}, 'pause() from idle with a negative playbackRate');
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, {duration: 1000 * MS_PER_SEC,
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, {duration: 1000 * MS_PER_SEC,
iterations: Infinity});
animation.cancel();
animation.playbackRate = -1;
assert_throws('InvalidStateError',
- function () { animation.pause(); },
+ () => { animation.pause(); },
'Expect InvalidStateError exception on calling pause() ' +
'from idle with a negative playbackRate and ' +
'infinite-duration animation');
}, 'pause() from idle with a negative playbackRate and endless effect');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 1000 * MS_PER_SEC);
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 1000 * MS_PER_SEC);
return animation.ready
- .then(function(animation) {
+ .then(animation => {
animation.finish();
animation.pause();
return animation.ready;
- }).then(function(animation) {
+ }).then(animation => {
assert_equals(animation.currentTime, 1000 * MS_PER_SEC,
'currentTime after pausing finished animation');
});
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/pending.html b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/pending.html
new file mode 100644
index 00000000000..fe7efe05aaf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/pending.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Animation.pending</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animation-pending">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
+
+ assert_true(animation.pending);
+ return animation.ready.then(() => {
+ assert_false(animation.pending);
+ });
+}, 'reports true -> false when initially played');
+
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
+ animation.pause();
+
+ assert_true(animation.pending);
+ return animation.ready.then(() => {
+ assert_false(animation.pending);
+ });
+}, 'reports true -> false when paused');
+
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/play.html b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/play.html
index 767d8df1707..3e8f923d544 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/play.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/play.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>Animation.play()</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-play">
+<title>Animation.play</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animation-play">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -10,19 +10,19 @@
<script>
'use strict';
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({ transform: ['none', 'translate(10px)']},
- { duration : 100 * MS_PER_SEC,
- iterations : Infinity});
- return animation.ready.then(function() {
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({ transform: ['none', 'translate(10px)']},
+ { duration: 100 * MS_PER_SEC,
+ iterations: Infinity });
+ return animation.ready.then(() => {
// Seek to a time outside the active range so that play() will have to
// snap back to the start
animation.currentTime = -5 * MS_PER_SEC;
animation.playbackRate = -1;
assert_throws('InvalidStateError',
- function () { animation.play(); },
+ () => { animation.play(); },
'Expected InvalidStateError exception on calling play() ' +
'with a negative playbackRate and infinite-duration ' +
'animation');
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/playState.html b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/playState.html
deleted file mode 100644
index 15af526cdef..00000000000
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/playState.html
+++ /dev/null
@@ -1,53 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>Animation.playState</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-playstate">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<script>
-'use strict';
-
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
-
- assert_equals(animation.playState, 'pending');
- return animation.ready.then(function() {
- assert_equals(animation.playState, 'running');
- });
-}, 'Animation.playState reports \'pending\'->\'running\' when initially ' +
- 'played');
-
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
- animation.pause();
-
- assert_equals(animation.playState, 'pending');
- return animation.ready.then(function() {
- assert_equals(animation.playState, 'paused');
- });
-}, 'Animation.playState reports \'pending\'->\'paused\' when pausing');
-
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
- animation.cancel();
- assert_equals(animation.playState, 'idle');
-}, 'Animation.playState is \'idle\' when canceled.');
-
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
- animation.cancel();
- animation.currentTime = 50 * MS_PER_SEC;
- assert_equals(animation.playState, 'paused',
- 'After seeking an idle animation, it is effectively paused');
-}, 'Animation.playState is \'paused\' after cancelling an animation, ' +
- 'seeking it makes it paused');
-
-</script>
-</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/playbackRate.html b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/playbackRate.html
index c923df6b4ba..9a3b76240f0 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/playbackRate.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/playbackRate.html
@@ -1,23 +1,23 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Animation.playbackRate</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-playbackrate">
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animation-playbackrate">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
<body>
<div id="log"></div>
<script>
-"use strict";
+'use strict';
function assert_playbackrate(animation,
previousAnimationCurrentTime,
previousTimelineCurrentTime,
description) {
- var accuracy = 0.001; /* accuracy of DOMHighResTimeStamp */
- var animationCurrentTimeDifference =
+ const accuracy = 0.001; /* accuracy of DOMHighResTimeStamp */
+ const animationCurrentTimeDifference =
animation.currentTime - previousAnimationCurrentTime;
- var timelineCurrentTimeDifference =
+ const timelineCurrentTimeDifference =
animation.timeline.currentTime - previousTimelineCurrentTime;
assert_approx_equals(animationCurrentTimeDifference,
@@ -26,10 +26,10 @@ function assert_playbackrate(animation,
description);
}
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate(null, 100 * MS_PER_SEC);
- return animation.ready.then(function() {
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(null, 100 * MS_PER_SEC);
+ return animation.ready.then(() => {
animation.currentTime = 7 * MS_PER_SEC; // ms
animation.playbackRate = 0.5;
@@ -43,17 +43,17 @@ promise_test(function(t) {
});
}, 'Test the initial effect of setting playbackRate on currentTime');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate(null, 100 * MS_PER_SEC);
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(null, 100 * MS_PER_SEC);
animation.playbackRate = 2;
- var previousTimelineCurrentTime;
- var previousAnimationCurrentTime;
- return animation.ready.then(function() {
+ let previousTimelineCurrentTime;
+ let previousAnimationCurrentTime;
+ return animation.ready.then(() => {
previousAnimationCurrentTime = animation.currentTime;
previousTimelineCurrentTime = animation.timeline.currentTime;
return waitForAnimationFrames(1);
- }).then(function() {
+ }).then(() => {
assert_playbackrate(animation,
previousAnimationCurrentTime,
previousTimelineCurrentTime,
@@ -61,18 +61,18 @@ promise_test(function(t) {
});
}, 'Test the effect of setting playbackRate on currentTime');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate(null, 100 * MS_PER_SEC);
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(null, 100 * MS_PER_SEC);
animation.playbackRate = 2;
- var previousTimelineCurrentTime;
- var previousAnimationCurrentTime;
- return animation.ready.then(function() {
+ let previousTimelineCurrentTime;
+ let previousAnimationCurrentTime;
+ return animation.ready.then(() => {
previousAnimationCurrentTime = animation.currentTime;
previousTimelineCurrentTime = animation.timeline.currentTime;
animation.playbackRate = 1;
return waitForAnimationFrames(1);
- }).then(function() {
+ }).then(() => {
assert_equals(animation.playbackRate, 1,
'sanity check: animation.playbackRate is still 1.');
assert_playbackrate(animation,
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/ready.html b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/ready.html
index b61a3c493f5..461c4e95814 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/ready.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/ready.html
@@ -1,22 +1,22 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Animation.ready</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-ready">
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animation-ready">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
<body>
<div id="log"></div>
<script>
-"use strict";
+'use strict';
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate(null, 100 * MS_PER_SEC);
- var originalReadyPromise = animation.ready;
- var pauseReadyPromise;
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(null, 100 * MS_PER_SEC);
+ const originalReadyPromise = animation.ready;
+ let pauseReadyPromise;
- return animation.ready.then(function() {
+ return animation.ready.then(() => {
assert_equals(animation.ready, originalReadyPromise,
'Ready promise is the same object when playing completes');
animation.pause();
@@ -26,19 +26,19 @@ promise_test(function(t) {
// Wait for the promise to fulfill since if we abort the pause the ready
// promise object is reused.
return animation.ready;
- }).then(function() {
+ }).then(() => {
animation.play();
assert_not_equals(animation.ready, pauseReadyPromise,
'A new ready promise is created when playing');
});
}, 'A new ready promise is created when play()/pause() is called');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate(null, 100 * MS_PER_SEC);
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(null, 100 * MS_PER_SEC);
- return animation.ready.then(function() {
- var promiseBeforeCallingPlay = animation.ready;
+ return animation.ready.then(() => {
+ const promiseBeforeCallingPlay = animation.ready;
animation.play();
assert_equals(animation.ready, promiseBeforeCallingPlay,
'Ready promise has same object identity after redundant call'
@@ -46,11 +46,11 @@ promise_test(function(t) {
});
}, 'Redundant calls to play() do not generate new ready promise objects');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate(null, 100 * MS_PER_SEC);
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(null, 100 * MS_PER_SEC);
- return animation.ready.then(function(resolvedAnimation) {
+ return animation.ready.then(resolvedAnimation => {
assert_equals(resolvedAnimation, animation,
'Object identity of Animation passed to Promise callback'
+ ' matches the Animation object owning the Promise');
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/startTime.html b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/startTime.html
index 6dfd7cf2941..61f76955a39 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/startTime.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/Animation/startTime.html
@@ -1,8 +1,8 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>Animation.startTime tests</title>
+<title>Animation.startTime</title>
<link rel="help"
-href="https://w3c.github.io/web-animations/#dom-animation-starttime">
+href="https://drafts.csswg.org/web-animations/#dom-animation-starttime">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -11,41 +11,41 @@ href="https://w3c.github.io/web-animations/#dom-animation-starttime">
<script>
'use strict';
-test(function(t) {
- var animation = new Animation(new KeyframeEffect(createDiv(t), null),
- document.timeline);
+test(t => {
+ const animation = new Animation(new KeyframeEffect(createDiv(t), null),
+ document.timeline);
assert_equals(animation.startTime, null, 'startTime is unresolved');
}, 'startTime of a newly created (idle) animation is unresolved');
-test(function(t) {
- var animation = new Animation(new KeyframeEffect(createDiv(t), null),
- document.timeline);
+test(t => {
+ const animation = new Animation(new KeyframeEffect(createDiv(t), null),
+ document.timeline);
animation.play();
assert_equals(animation.startTime, null, 'startTime is unresolved');
}, 'startTime of a play-pending animation is unresolved');
-test(function(t) {
- var animation = new Animation(new KeyframeEffect(createDiv(t), null),
- document.timeline);
+test(t => {
+ const animation = new Animation(new KeyframeEffect(createDiv(t), null),
+ document.timeline);
animation.pause();
assert_equals(animation.startTime, null, 'startTime is unresolved');
}, 'startTime of a pause-pending animation is unresolved');
-test(function(t) {
- var animation = createDiv(t).animate(null);
+test(t => {
+ const animation = createDiv(t).animate(null);
assert_equals(animation.startTime, null, 'startTime is unresolved');
}, 'startTime of a play-pending animation created using Element.animate'
+ ' shortcut is unresolved');
-promise_test(function(t) {
- var animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
- return animation.ready.then(function() {
+promise_test(t => {
+ const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
+ return animation.ready.then(() => {
assert_greater_than(animation.startTime, 0, 'startTime when running');
});
}, 'startTime is resolved when running');
-test(function(t) {
- var animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
+test(t => {
+ const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
animation.cancel();
assert_equals(animation.startTime, null);
assert_equals(animation.currentTime, null);
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/delay.html b/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/delay.html
index 1b34f7dbe76..41f099b86b2 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/delay.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/delay.html
@@ -1,8 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>delay tests</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffecttiming-delay">
-<link rel="author" title="Daisuke Akatsuka" href="mailto:daisuke@mozilla-japan.org">
+<title>AnimationEffectTiming.delay</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-delay">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -11,69 +10,69 @@
<script>
'use strict';
-test(function(t) {
- var anim = createDiv(t).animate(null);
+test(t => {
+ const anim = createDiv(t).animate(null);
assert_equals(anim.effect.timing.delay, 0);
-}, 'Test default value');
+}, 'Has the default value 0');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 100);
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 100);
anim.effect.timing.delay = 100;
assert_equals(anim.effect.timing.delay, 100, 'set delay 100');
assert_equals(anim.effect.getComputedTiming().delay, 100,
'getComputedTiming() after set delay 100');
-}, 'set delay 100');
+}, 'Can be set to a positive number');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 100);
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 100);
anim.effect.timing.delay = -100;
assert_equals(anim.effect.timing.delay, -100, 'set delay -100');
assert_equals(anim.effect.getComputedTiming().delay, -100,
'getComputedTiming() after set delay -100');
-}, 'set delay -100');
+}, 'Can be set to a negative number');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 100);
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 100);
anim.effect.timing.delay = 100;
assert_equals(anim.effect.getComputedTiming().progress, null);
assert_equals(anim.effect.getComputedTiming().currentIteration, null);
-}, 'Test adding a positive delay to an animation without a backwards fill ' +
- 'makes it no longer active');
+}, 'Can set a positive delay on an animation without a backwards fill to'
+ + ' make it no longer active');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] },
- { fill: 'both',
- duration: 100 });
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] },
+ { fill: 'both',
+ duration: 100 });
anim.effect.timing.delay = -50;
assert_equals(anim.effect.getComputedTiming().progress, 0.5);
-}, 'Test seeking an animation by setting a negative delay');
+}, 'Can set a negative delay to seek into the active interval');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] },
- { fill: 'both',
- duration: 100 });
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] },
+ { fill: 'both',
+ duration: 100 });
anim.effect.timing.delay = -100;
assert_equals(anim.effect.getComputedTiming().progress, 1);
assert_equals(anim.effect.getComputedTiming().currentIteration, 0);
-}, 'Test finishing an animation using a large negative delay');
+}, 'Can set a large negative delay to finishing an animation');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate(null);
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate(null);
for (let invalid of [NaN, Infinity]) {
- assert_throws({ name: 'TypeError' }, function() {
+ assert_throws({ name: 'TypeError' }, () => {
anim.effect.timing.delay = invalid;
- }, 'setting ' + invalid);
- assert_throws({ name: 'TypeError' }, function() {
+ }, `setting ${invalid}`);
+ assert_throws({ name: 'TypeError' }, () => {
div.animate({}, { delay: invalid });
- }, 'animate() with ' + invalid);
+ }, `animate() with ${invalid}`);
}
-}, 'Setting invalid values should throw TypeError');
+}, 'Throws when setting invalid values');
</script>
</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/direction.html b/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/direction.html
index 95718120245..7bc315da967 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/direction.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/direction.html
@@ -1,8 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>direction tests</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffecttiming-direction">
-<link rel="author" title="Ryo Kato" href="mailto:foobar094@gmail.com">
+<title>AnimationEffectTiming.direction</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-direction">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -11,22 +10,99 @@
<script>
'use strict';
-test(function(t) {
- var anim = createDiv(t).animate(null);
+test(t => {
+ const anim = createDiv(t).animate(null);
assert_equals(anim.effect.timing.direction, 'normal');
-}, 'Test default value');
+}, 'Has the default value \'normal\'');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- var directions = ['normal', 'reverse', 'alternate', 'alternate-reverse'];
- directions.forEach(function(direction) {
+ const directions = ['normal', 'reverse', 'alternate', 'alternate-reverse'];
+ for (const direction of directions) {
anim.effect.timing.direction = direction;
assert_equals(anim.effect.timing.direction, direction,
- 'set direction to ' + direction);
- });
-}, 'set direction to a valid keyword');
+ `set direction to ${direction}`);
+ }
+}, 'Can be set to each of the possible keywords');
+
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate(null, { duration: 10000, direction: 'normal' });
+ anim.currentTime = 7000;
+ assert_times_equal(anim.effect.getComputedTiming().progress, 0.7,
+ 'progress before updating direction');
+
+ anim.effect.timing.direction = 'reverse';
+
+ assert_times_equal(anim.effect.getComputedTiming().progress, 0.3,
+ 'progress after updating direction');
+}, 'Can be changed from \'normal\' to \'reverse\' while in progress');
+
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] },
+ { duration: 10000,
+ direction: 'normal' });
+ assert_equals(anim.effect.getComputedTiming().progress, 0,
+ 'progress before updating direction');
+
+ anim.effect.timing.direction = 'reverse';
+
+ assert_equals(anim.effect.getComputedTiming().progress, 1,
+ 'progress after updating direction');
+}, 'Can be changed from \'normal\' to \'reverse\' while at start of active'
+ + ' interval');
+
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] },
+ { fill: 'backwards',
+ duration: 10000,
+ delay: 10000,
+ direction: 'normal' });
+ assert_equals(anim.effect.getComputedTiming().progress, 0,
+ 'progress before updating direction');
+
+ anim.effect.timing.direction = 'reverse';
+
+ assert_equals(anim.effect.getComputedTiming().progress, 1,
+ 'progress after updating direction');
+}, 'Can be changed from \'normal\' to \'reverse\' while filling backwards');
+
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] },
+ { iterations: 2,
+ duration: 10000,
+ direction: 'normal' });
+ anim.currentTime = 17000;
+ assert_times_equal(anim.effect.getComputedTiming().progress, 0.7,
+ 'progress before updating direction');
+
+ anim.effect.timing.direction = 'alternate';
+
+ assert_times_equal(anim.effect.getComputedTiming().progress, 0.3,
+ 'progress after updating direction');
+}, 'Can be changed from \'normal\' to \'alternate\' while in progress');
+
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] },
+ { iterations: 2,
+ duration: 10000,
+ direction: 'alternate' });
+ anim.currentTime = 17000;
+ assert_times_equal(anim.effect.getComputedTiming().progress, 0.3,
+ 'progress before updating direction');
+
+ anim.effect.timing.direction = 'alternate-reverse';
+
+ assert_times_equal(anim.effect.getComputedTiming().progress, 0.7,
+ 'progress after updating direction');
+}, 'Can be changed from \'alternate\' to \'alternate-reverse\' while in'
+ + ' progress');
</script>
</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/duration.html b/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/duration.html
index c8154d53970..9caa0e36e05 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/duration.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/duration.html
@@ -1,8 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>duration tests</title>
-<link rel="help" href="http://w3c.github.io/web-animations/#dom-animationeffecttiming-duration">
-<link rel="author" title="Ryo Motozawa" href="mailto:motozawa@mozilla-japan.org">
+<title>AnimationEffectTiming.duration</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-duration">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -11,148 +10,150 @@
<script>
'use strict';
-test(function(t) {
- var anim = createDiv(t).animate(null);
+test(t => {
+ const anim = createDiv(t).animate(null);
assert_equals(anim.effect.timing.duration, 'auto');
-}, 'Test default value');
+}, 'Has the default value \'auto\'');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
anim.effect.timing.duration = 123.45;
assert_times_equal(anim.effect.timing.duration, 123.45,
'set duration 123.45');
assert_times_equal(anim.effect.getComputedTiming().duration, 123.45,
'getComputedTiming() after set duration 123.45');
-}, 'set duration 123.45');
+}, 'Can be set to a double value');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
anim.effect.timing.duration = 'auto';
assert_equals(anim.effect.timing.duration, 'auto', 'set duration \'auto\'');
assert_equals(anim.effect.getComputedTiming().duration, 0,
'getComputedTiming() after set duration \'auto\'');
-}, 'set duration auto');
+}, 'Can be set to the string \'auto\'');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, { duration: 'auto' });
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, { duration: 'auto' });
assert_equals(anim.effect.timing.duration, 'auto', 'set duration \'auto\'');
assert_equals(anim.effect.getComputedTiming().duration, 0,
'getComputedTiming() after set duration \'auto\'');
-}, 'set auto duration in animate as object');
+}, 'Can be set to \'auto\' using a dictionary object');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
anim.effect.timing.duration = Infinity;
assert_equals(anim.effect.timing.duration, Infinity, 'set duration Infinity');
assert_equals(anim.effect.getComputedTiming().duration, Infinity,
'getComputedTiming() after set duration Infinity');
-}, 'set duration Infinity');
+}, 'Can be set to Infinity');
-test(function(t) {
- var div = createDiv(t);
- assert_throws({ name: 'TypeError' }, function() {
+test(t => {
+ const div = createDiv(t);
+ assert_throws({ name: 'TypeError' }, () => {
div.animate({ opacity: [ 0, 1 ] }, -1);
});
-}, 'set negative duration in animate using a duration parameter');
+}, 'animate() throws when passed a negative number');
-test(function(t) {
- var div = createDiv(t);
- assert_throws({ name: 'TypeError' }, function() {
+test(t => {
+ const div = createDiv(t);
+ assert_throws({ name: 'TypeError' }, () => {
div.animate({ opacity: [ 0, 1 ] }, -Infinity);
});
-}, 'set negative Infinity duration in animate using a duration parameter');
+}, 'animate() throws when passed negative Infinity');
-test(function(t) {
- var div = createDiv(t);
- assert_throws({ name: 'TypeError' }, function() {
+test(t => {
+ const div = createDiv(t);
+ assert_throws({ name: 'TypeError' }, () => {
div.animate({ opacity: [ 0, 1 ] }, NaN);
});
-}, 'set NaN duration in animate using a duration parameter');
+}, 'animate() throws when passed a NaN value');
-test(function(t) {
- var div = createDiv(t);
- assert_throws({ name: 'TypeError' }, function() {
+test(t => {
+ const div = createDiv(t);
+ assert_throws({ name: 'TypeError' }, () => {
div.animate({ opacity: [ 0, 1 ] }, { duration: -1 });
});
-}, 'set negative duration in animate using an options object');
+}, 'animate() throws when passed a negative number using a dictionary object');
-test(function(t) {
- var div = createDiv(t);
- assert_throws({ name: 'TypeError' }, function() {
+test(t => {
+ const div = createDiv(t);
+ assert_throws({ name: 'TypeError' }, () => {
div.animate({ opacity: [ 0, 1 ] }, { duration: -Infinity });
});
-}, 'set negative Infinity duration in animate using an options object');
+}, 'animate() throws when passed negative Infinity using a dictionary object');
-test(function(t) {
- var div = createDiv(t);
- assert_throws({ name: 'TypeError' }, function() {
+test(t => {
+ const div = createDiv(t);
+ assert_throws({ name: 'TypeError' }, () => {
div.animate({ opacity: [ 0, 1 ] }, { duration: NaN });
});
-}, 'set NaN duration in animate using an options object');
+}, 'animate() throws when passed a NaN value using a dictionary object');
-test(function(t) {
- var div = createDiv(t);
- assert_throws({ name: 'TypeError' }, function() {
+test(t => {
+ const div = createDiv(t);
+ assert_throws({ name: 'TypeError' }, () => {
div.animate({ opacity: [ 0, 1 ] }, { duration: 'abc' });
});
-}, 'set abc string duration in animate using an options object');
+}, 'animate() throws when passed a string other than \'auto\' using a'
+ + ' dictionary object');
-test(function(t) {
- var div = createDiv(t);
- assert_throws({ name: 'TypeError' }, function() {
+test(t => {
+ const div = createDiv(t);
+ assert_throws({ name: 'TypeError' }, () => {
div.animate({ opacity: [ 0, 1 ] }, { duration: '100' });
});
-}, 'set 100 string duration in animate using an options object');
+}, 'animate() throws when passed a string containing a number using a'
+ + ' dictionary object');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- assert_throws({ name: 'TypeError' }, function() {
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+ assert_throws({ name: 'TypeError' }, () => {
anim.effect.timing.duration = -1;
});
-}, 'set negative duration');
+}, 'Throws when setting a negative number');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- assert_throws({ name: 'TypeError' }, function() {
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+ assert_throws({ name: 'TypeError' }, () => {
anim.effect.timing.duration = -Infinity;
});
-}, 'set negative Infinity duration');
+}, 'Throws when setting negative infinity');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- assert_throws({ name: 'TypeError' }, function() {
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+ assert_throws({ name: 'TypeError' }, () => {
anim.effect.timing.duration = NaN;
});
-}, 'set NaN duration');
+}, 'Throws when setting a NaN value');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- assert_throws({ name: 'TypeError' }, function() {
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+ assert_throws({ name: 'TypeError' }, () => {
anim.effect.timing.duration = 'abc';
});
-}, 'set duration abc');
+}, 'Throws when setting a string other than \'auto\'');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- assert_throws({ name: 'TypeError' }, function() {
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+ assert_throws({ name: 'TypeError' }, () => {
anim.effect.timing.duration = '100';
});
-}, 'set duration string 100');
+}, 'Throws when setting a string containing a number');
-promise_test(function(t) {
- var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
- return anim.ready.then(function() {
- var originalStartTime = anim.startTime;
- var originalCurrentTime = anim.currentTime;
+promise_test(t => {
+ const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
+ return anim.ready.then(() => {
+ const originalStartTime = anim.startTime;
+ const originalCurrentTime = anim.currentTime;
assert_equals(anim.effect.getComputedTiming().duration, 100 * MS_PER_SEC,
'Initial duration should be as set on KeyframeEffect');
@@ -168,5 +169,22 @@ promise_test(function(t) {
});
}, 'Extending an effect\'s duration does not change the start or current time');
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate(null, { duration: 100000, fill: 'both' });
+ anim.finish();
+ assert_equals(anim.effect.getComputedTiming().progress, 1,
+ 'progress when animation is finished');
+ anim.effect.timing.duration *= 2;
+ assert_times_equal(anim.effect.getComputedTiming().progress, 0.5,
+ 'progress after doubling the duration');
+ anim.effect.timing.duration = 0;
+ assert_equals(anim.effect.getComputedTiming().progress, 1,
+ 'progress after setting duration to zero');
+ anim.effect.timing.duration = 'auto';
+ assert_equals(anim.effect.getComputedTiming().progress, 1,
+ 'progress after setting duration to \'auto\'');
+}, 'Can be updated while the animation is in progress');
+
</script>
</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/easing.html b/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/easing.html
index 11173fc8644..ec2b239fe52 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/easing.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/easing.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>easing tests</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffecttiming-easing">
+<title>AnimationEffectTiming.easing</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-easing">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -11,68 +11,68 @@
<script>
'use strict';
-test(function(t) {
- var anim = createDiv(t).animate(null);
+test(t => {
+ const anim = createDiv(t).animate(null);
assert_equals(anim.effect.timing.easing, 'linear');
-}, 'Test default value');
+}, 'Has the default value \'linear\'');
function assert_progress(animation, currentTime, easingFunction) {
animation.currentTime = currentTime;
- var portion = currentTime / animation.effect.timing.duration;
+ const portion = currentTime / animation.effect.timing.duration;
assert_approx_equals(animation.effect.getComputedTiming().progress,
easingFunction(portion),
0.01,
- 'The progress of the animation should be approximately ' +
- easingFunction(portion) + ' at ' + currentTime + 'ms');
+ 'The progress of the animation should be approximately'
+ + ` ${easingFunction(portion)} at ${currentTime}ms`);
}
-gEasingTests.forEach(function(options) {
- test(function(t) {
- var target = createDiv(t);
- var anim = target.animate([ { opacity: 0 }, { opacity: 1 } ],
- { duration: 1000 * MS_PER_SEC,
- fill: 'forwards' });
+for (const options of gEasingTests) {
+ test(t => {
+ const target = createDiv(t);
+ const anim = target.animate([ { opacity: 0 }, { opacity: 1 } ],
+ { duration: 1000 * MS_PER_SEC,
+ fill: 'forwards' });
anim.effect.timing.easing = options.easing;
assert_equals(anim.effect.timing.easing,
options.serialization || options.easing);
- var easing = options.easingFunction;
+ const easing = options.easingFunction;
assert_progress(anim, 0, easing);
assert_progress(anim, 250 * MS_PER_SEC, easing);
assert_progress(anim, 500 * MS_PER_SEC, easing);
assert_progress(anim, 750 * MS_PER_SEC, easing);
assert_progress(anim, 1000 * MS_PER_SEC, easing);
}, options.desc);
-});
+}
-gInvalidEasings.forEach(function(invalidEasing) {
- test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 100 * MS_PER_SEC);
+for (const invalidEasing of gInvalidEasings) {
+ test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 100 * MS_PER_SEC);
assert_throws({ name: 'TypeError' },
- function() {
+ () => {
anim.effect.timing.easing = invalidEasing;
});
- }, 'Invalid effect easing value test: \'' + invalidEasing + '\'');
-});
+ }, `Throws on invalid easing: '${invalidEasing}'`);
+}
-gRoundtripEasings.forEach(easing => {
- test(function(t) {
+for (const easing of gRoundtripEasings) {
+ test(t => {
const anim = createDiv(t).animate(null);
anim.effect.timing.easing = easing;
assert_equals(anim.effect.timing.easing, easing);
}, `Canonical easing '${easing}' is returned as set`);
-});
+}
-test(function(t) {
- var delay = 1000 * MS_PER_SEC;
+test(t => {
+ const delay = 1000 * MS_PER_SEC;
- var target = createDiv(t);
- var anim = target.animate([ { opacity: 0 }, { opacity: 1 } ],
- { duration: 1000 * MS_PER_SEC,
- fill: 'both',
- delay: delay,
- easing: 'steps(2, start)' });
+ const target = createDiv(t);
+ const anim = target.animate([ { opacity: 0 }, { opacity: 1 } ],
+ { duration: 1000 * MS_PER_SEC,
+ fill: 'both',
+ delay: delay,
+ easing: 'steps(2, start)' });
anim.effect.timing.easing = 'steps(2, end)';
assert_equals(anim.effect.getComputedTiming().progress, 0,
@@ -90,7 +90,7 @@ test(function(t) {
anim.effect.timing.easing = 'steps(2, end)';
assert_equals(anim.effect.getComputedTiming().progress, 1,
'easing replace to steps(2, end) again at after phase');
-}, 'Change the easing while the animation is running');
+}, 'Allows the easing to be changed while the animation is in progress');
</script>
</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/endDelay.html b/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/endDelay.html
index c6c2e88cc2d..b6793edaed5 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/endDelay.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/endDelay.html
@@ -1,8 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>endDelay tests</title>
-<link rel="help" href="http://w3c.github.io/web-animations/#dom-animationeffecttiming-enddelay">
-<link rel="author" title="Ryo Motozawa" href="mailto:motozawa@mozilla-japan.org">
+<title>AnimationEffectTiming.endDelay</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-enddelay">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -11,79 +10,80 @@
<script>
'use strict';
-test(function(t) {
- var anim = createDiv(t).animate(null);
+test(t => {
+ const anim = createDiv(t).animate(null);
assert_equals(anim.effect.timing.endDelay, 0);
-}, 'Test default value');
+}, 'Has the default value 0');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
anim.effect.timing.endDelay = 123.45;
assert_times_equal(anim.effect.timing.endDelay, 123.45,
'set endDelay 123.45');
assert_times_equal(anim.effect.getComputedTiming().endDelay, 123.45,
'getComputedTiming() after set endDelay 123.45');
-}, 'set endDelay 123.45');
+}, 'Can be set to a positive number');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
anim.effect.timing.endDelay = -1000;
assert_equals(anim.effect.timing.endDelay, -1000, 'set endDelay -1000');
assert_equals(anim.effect.getComputedTiming().endDelay, -1000,
'getComputedTiming() after set endDelay -1000');
-}, 'set endDelay -1000');
+}, 'Can be set to a negative number');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- assert_throws({name: "TypeError"}, function() {
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+ assert_throws({ name: 'TypeError' }, () => {
anim.effect.timing.endDelay = Infinity;
}, 'we can not assign Infinity to timing.endDelay');
-}, 'set endDelay Infinity');
+}, 'Throws when setting infinity');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- assert_throws({name: "TypeError"}, function() {
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+ assert_throws({ name: 'TypeError' }, () => {
anim.effect.timing.endDelay = -Infinity;
}, 'we can not assign negative Infinity to timing.endDelay');
-}, 'set endDelay negative Infinity');
+}, 'Throws when setting negative infinity');
-async_test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] },
- { duration: 100000, endDelay: 50000 });
- anim.onfinish = t.step_func(function(event) {
- assert_unreached('onfinish event should not be fired');
+async_test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] },
+ { duration: 100000, endDelay: 50000 });
+ anim.onfinish = t.step_func(event => {
+ assert_unreached('finish event should not be fired');
});
- anim.ready.then(function() {
+ anim.ready.then(() => {
anim.currentTime = 100000;
return waitForAnimationFrames(2);
- }).then(t.step_func(function() {
+ }).then(t.step_func(() => {
t.done();
}));
-}, 'onfinish event is not fired duration endDelay');
+}, 'finish event is not fired at the end of the active interval when the'
+ + ' endDelay has not expired');
-async_test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] },
- { duration: 100000, endDelay: 30000 });
- anim.ready.then(function() {
+async_test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] },
+ { duration: 100000, endDelay: 30000 });
+ anim.ready.then(() => {
anim.currentTime = 110000; // during endDelay
- anim.onfinish = t.step_func(function(event) {
+ anim.onfinish = t.step_func(event => {
assert_unreached('onfinish event should not be fired during endDelay');
});
return waitForAnimationFrames(2);
- }).then(t.step_func(function() {
- anim.onfinish = t.step_func(function(event) {
+ }).then(t.step_func(() => {
+ anim.onfinish = t.step_func(event => {
t.done();
});
anim.currentTime = 130000; // after endTime
}));
-}, 'onfinish event is fired currentTime is after endTime');
+}, 'finish event is fired after the endDelay has expired');
</script>
</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/fill.html b/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/fill.html
index 89f6a467938..01739478f47 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/fill.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/fill.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>fill tests</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffecttiming-fill">
+<title>AnimationEffectTiming.fill</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-fill">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -10,20 +10,21 @@
<script>
'use strict';
-test(function(t) {
- var anim = createDiv(t).animate(null);
+test(t => {
+ const anim = createDiv(t).animate(null);
assert_equals(anim.effect.timing.fill, 'auto');
-}, 'Test default value');
+}, 'Has the default value \'auto\'');
-["none", "forwards", "backwards", "both", ].forEach(function(fill){
- test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 100);
+for (const fill of ['none', 'forwards', 'backwards', 'both']) {
+ test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 100);
anim.effect.timing.fill = fill;
assert_equals(anim.effect.timing.fill, fill, 'set fill ' + fill);
- assert_equals(anim.effect.getComputedTiming().fill, fill, 'getComputedTiming() after set fill ' + fill);
- }, 'set fill ' + fill);
-});
+ assert_equals(anim.effect.getComputedTiming().fill, fill,
+ 'getComputedTiming() after set fill ' + fill);
+ }, `Can set fill to ${fill}`);
+}
</script>
</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/getAnimations.html b/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/getAnimations.html
deleted file mode 100644
index d96192c9d01..00000000000
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/getAnimations.html
+++ /dev/null
@@ -1,91 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>Element.getAnimations tests</title>
-<link rel="help" href="http://w3c.github.io/web-animations/#animationeffecttiming">
-<link rel="author" title="Ryo Motozawa" href="mailto:motozawa@mozilla-japan.org">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<script>
-'use strict';
-
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- anim.finish();
- assert_equals(div.getAnimations().length, 0, 'animation finished');
- anim.effect.timing.duration += 100000;
- assert_equals(div.getAnimations()[0], anim, 'set duration 102000');
- anim.effect.timing.duration = 0;
- assert_equals(div.getAnimations().length, 0, 'set duration 0');
- anim.effect.timing.duration = 'auto';
- assert_equals(div.getAnimations().length, 0, 'set duration \'auto\'');
-}, 'when duration is changed');
-
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
-
- anim.effect.timing.endDelay = -3000;
- assert_equals(div.getAnimations().length, 0,
- 'set negative endDelay so as endTime is less than currentTime');
- anim.effect.timing.endDelay = 1000;
- assert_equals(div.getAnimations()[0], anim,
- 'set positive endDelay so as endTime is more than currentTime');
-
- anim.effect.timing.duration = 1000;
- anim.currentTime = 1500;
- assert_equals(div.getAnimations().length, 0,
- 'set currentTime less than endTime');
- anim.effect.timing.endDelay = -500;
- anim.currentTime = 400;
- assert_equals(div.getAnimations()[0], anim,
- 'set currentTime less than endTime when endDelay is negative value');
- anim.currentTime = 500;
- assert_equals(div.getAnimations().length, 0,
- 'set currentTime same as endTime when endDelay is negative value');
- anim.currentTime = 1000;
- assert_equals(div.getAnimations().length, 0,
- 'set currentTime same as duration when endDelay is negative value');
-}, 'when endDelay is changed');
-
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- anim.finish();
- assert_equals(div.getAnimations().length, 0, 'animation finished');
- anim.effect.timing.iterations = 10;
- assert_equals(div.getAnimations()[0], anim, 'set iterations 10');
- anim.effect.timing.iterations = 0;
- assert_equals(div.getAnimations().length, 0, 'set iterations 0');
- anim.effect.timing.iterations = Infinity;
- assert_equals(div.getAnimations().length, 1, 'set iterations Infinity');
-}, 'when iterations is changed');
-
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] },
- { duration: 1000, delay: 500, endDelay: -500 });
- assert_equals(div.getAnimations()[0], anim, 'when currentTime 0');
- anim.currentTime = 500;
- assert_equals(div.getAnimations()[0], anim, 'set currentTime 500');
- anim.currentTime = 1000;
- assert_equals(div.getAnimations().length, 0, 'set currentTime 1000');
-}, 'when currentTime changed in duration:1000, delay: 500, endDelay: -500');
-
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] },
- { duration: 1000, delay: -500, endDelay: -500 });
- assert_equals(div.getAnimations().length, 0, 'when currentTime 0');
- anim.currentTime = 500;
- assert_equals(div.getAnimations().length, 0, 'set currentTime 500');
- anim.currentTime = 1000;
- assert_equals(div.getAnimations().length, 0, 'set currentTime 1000');
-}, 'when currentTime changed in duration:1000, delay: -500, endDelay: -500');
-
-
-</script>
-</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/getComputedStyle.html b/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/getComputedStyle.html
deleted file mode 100644
index cfc233f0e98..00000000000
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/getComputedStyle.html
+++ /dev/null
@@ -1,172 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>getComputedStyle tests</title>
-<link rel="help" href="http://w3c.github.io/web-animations/#animationeffecttiming">
-<link rel="author" title="Ryo Motozawa" href="mailto:motozawa@mozilla-japan.org">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<script>
-'use strict';
-
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 100000);
- anim.finish();
- assert_equals(getComputedStyle(div).opacity, '1', 'animation finished');
- anim.effect.timing.duration *= 2;
- assert_equals(getComputedStyle(div).opacity, '0.5', 'set double duration');
- anim.effect.timing.duration = 0;
- assert_equals(getComputedStyle(div).opacity, '1', 'set duration 0');
- anim.effect.timing.duration = 'auto';
- assert_equals(getComputedStyle(div).opacity, '1', 'set duration \'auto\'');
-}, 'changed duration immediately updates its computed styles');
-
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 100000);
- anim.finish();
- assert_equals(getComputedStyle(div).opacity, '1', 'animation finished');
- anim.effect.timing.iterations = 2;
- assert_equals(getComputedStyle(div).opacity, '0', 'set 2 iterations');
- anim.effect.timing.iterations = 0;
- assert_equals(getComputedStyle(div).opacity, '1', 'set iterations 0');
- anim.effect.timing.iterations = Infinity;
- assert_equals(getComputedStyle(div).opacity, '0', 'set iterations Infinity');
-}, 'changed iterations immediately updates its computed styles');
-
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 1, 0 ] },
- { duration: 10000, endDelay: 1000, fill: 'none' });
-
- anim.currentTime = 9000;
- assert_equals(getComputedStyle(div).opacity, '0.1',
- 'set currentTime during duration');
-
- anim.currentTime = 10900;
- assert_equals(getComputedStyle(div).opacity, '1',
- 'set currentTime during endDelay');
-
- anim.currentTime = 11100;
- assert_equals(getComputedStyle(div).opacity, '1',
- 'set currentTime after endDelay');
-}, 'change currentTime when fill is none and endDelay is positive');
-
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 1, 0 ] },
- { duration: 10000,
- endDelay: 1000,
- fill: 'forwards' });
- anim.currentTime = 5000;
- assert_equals(getComputedStyle(div).opacity, '0.5',
- 'set currentTime during duration');
-
- anim.currentTime = 9999;
- assert_equals(getComputedStyle(div).opacity, '0.0001',
- 'set currentTime just a little before duration');
-
- anim.currentTime = 10900;
- assert_equals(getComputedStyle(div).opacity, '0',
- 'set currentTime during endDelay');
-
- anim.currentTime = 11100;
- assert_equals(getComputedStyle(div).opacity, '0',
- 'set currentTime after endDelay');
-}, 'change currentTime when fill forwards and endDelay is positive');
-
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 1, 0 ] },
- { duration: 10000, endDelay: -5000, fill: 'none' });
-
- anim.currentTime = 1000;
- assert_equals(getComputedStyle(div).opacity, '0.9',
- 'set currentTime before endTime');
-
- anim.currentTime = 10000;
- assert_equals(getComputedStyle(div).opacity, '1',
- 'set currentTime after endTime');
-}, 'change currentTime when fill none and endDelay is negative');
-
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 1, 0 ] },
- { duration: 10000,
- endDelay: -5000,
- fill: 'forwards' });
-
- anim.currentTime = 1000;
- assert_equals(getComputedStyle(div).opacity, '0.9',
- 'set currentTime before endTime');
-
- anim.currentTime = 5000;
- assert_equals(getComputedStyle(div).opacity, '0.5',
- 'set currentTime same as endTime');
-
- anim.currentTime = 10000;
- assert_equals(getComputedStyle(div).opacity, '0',
- 'set currentTime after endTime');
-}, 'change currentTime when fill forwards and endDelay is negative');
-
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] },
- { duration: 10000,
- direction: 'normal' });
-
- anim.currentTime = 7000;
- anim.effect.timing.direction = 'reverse';
-
- assert_equals(getComputedStyle(div).opacity, '0.3',
- 'change direction from "normal" to "reverse"');
-}, 'change direction from "normal" to "reverse"');
-
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] },
- { iterations: 2,
- duration: 10000,
- direction: 'normal' });
-
- anim.currentTime = 17000;
- anim.effect.timing.direction = 'alternate';
-
- assert_equals(getComputedStyle(div).opacity, '0.3',
- 'change direction from "normal" to "alternate"');
- }, 'change direction from "normal" to "alternate"');
-
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] },
- { iterations: 2,
- duration: 10000,
- direction: 'normal' });
-
- anim.currentTime = 17000;
- anim.effect.timing.direction = 'alternate-reverse';
-
- assert_equals(getComputedStyle(div).opacity, '0.7',
- 'change direction from "normal" to "alternate-reverse"');
-}, 'change direction from "normal" to "alternate-reverse"');
-
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] },
- { fill: 'backwards',
- duration: 10000,
- direction: 'normal' });
-
- // test for a flip of value at the currentTime = 0
- anim.effect.timing.direction = 'reverse';
-
- assert_equals(getComputedStyle(div).opacity, '1',
- 'change direction from "normal" to "reverse" ' +
- 'at the starting point');
-}, 'change direction from "normal" to "reverse" when currentTime is 0');
-
-</script>
-</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/getComputedTiming.html b/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/getComputedTiming.html
new file mode 100644
index 00000000000..9a92880a606
--- /dev/null
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/getComputedTiming.html
@@ -0,0 +1,201 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>AnimationEffectTiming.getComputedTiming</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffectreadonly-getcomputedtiming">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+test(t => {
+ const effect = new KeyframeEffect(null, null);
+
+ const ct = effect.getComputedTiming();
+ assert_equals(ct.delay, 0, 'computed delay');
+ assert_equals(ct.fill, 'none', 'computed fill');
+ assert_equals(ct.iterations, 1.0, 'computed iterations');
+ assert_equals(ct.duration, 0, 'computed duration');
+ assert_equals(ct.direction, 'normal', 'computed direction');
+}, 'values of getComputedTiming() when a KeyframeEffect is ' +
+ 'constructed without any KeyframeEffectOptions object');
+
+const gGetComputedTimingTests = [
+ { desc: 'an empty KeyframeEffectOptions object',
+ input: { },
+ expected: { } },
+ { desc: 'a normal KeyframeEffectOptions object',
+ input: { delay: 1000,
+ fill: 'auto',
+ iterations: 5.5,
+ duration: 'auto',
+ direction: 'alternate' },
+ expected: { delay: 1000,
+ fill: 'none',
+ iterations: 5.5,
+ duration: 0,
+ direction: 'alternate' } },
+ { desc: 'a double value',
+ input: 3000,
+ timing: { duration: 3000 },
+ expected: { delay: 0,
+ fill: 'none',
+ iterations: 1,
+ duration: 3000,
+ direction: 'normal' } },
+ { desc: '+Infinity',
+ input: Infinity,
+ expected: { duration: Infinity } },
+ { desc: 'an Infinity duration',
+ input: { duration: Infinity },
+ expected: { duration: Infinity } },
+ { desc: 'an auto duration',
+ input: { duration: 'auto' },
+ expected: { duration: 0 } },
+ { desc: 'an Infinity iterations',
+ input: { iterations: Infinity },
+ expected: { iterations: Infinity } },
+ { desc: 'an auto fill',
+ input: { fill: 'auto' },
+ expected: { fill: 'none' } },
+ { desc: 'a forwards fill',
+ input: { fill: 'forwards' },
+ expected: { fill: 'forwards' } }
+];
+
+for (const stest of gGetComputedTimingTests) {
+ test(t => {
+ const effect = new KeyframeEffect(null, null, stest.input);
+
+ // Helper function to provide default expected values when the test does
+ // not supply them.
+ const expected = (field, defaultValue) => {
+ return field in stest.expected ? stest.expected[field] : defaultValue;
+ };
+
+ const ct = effect.getComputedTiming();
+ assert_equals(ct.delay, expected('delay', 0),
+ 'computed delay');
+ assert_equals(ct.fill, expected('fill', 'none'),
+ 'computed fill');
+ assert_equals(ct.iterations, expected('iterations', 1),
+ 'computed iterations');
+ assert_equals(ct.duration, expected('duration', 0),
+ 'computed duration');
+ assert_equals(ct.direction, expected('direction', 'normal'),
+ 'computed direction');
+
+ }, 'values of getComputedTiming() when a KeyframeEffect is'
+ + ` constructed by ${stest.desc}`);
+}
+
+const gActiveDurationTests = [
+ { desc: 'an empty KeyframeEffectOptions object',
+ input: { },
+ expected: 0 },
+ { desc: 'a non-zero duration and default iteration count',
+ input: { duration: 1000 },
+ expected: 1000 },
+ { desc: 'a non-zero duration and integral iteration count',
+ input: { duration: 1000, iterations: 7 },
+ expected: 7000 },
+ { desc: 'a non-zero duration and fractional iteration count',
+ input: { duration: 1000, iterations: 2.5 },
+ expected: 2500 },
+ { desc: 'an non-zero duration and infinite iteration count',
+ input: { duration: 1000, iterations: Infinity },
+ expected: Infinity },
+ { desc: 'an non-zero duration and zero iteration count',
+ input: { duration: 1000, iterations: 0 },
+ expected: 0 },
+ { desc: 'a zero duration and default iteration count',
+ input: { duration: 0 },
+ expected: 0 },
+ { desc: 'a zero duration and fractional iteration count',
+ input: { duration: 0, iterations: 2.5 },
+ expected: 0 },
+ { desc: 'a zero duration and infinite iteration count',
+ input: { duration: 0, iterations: Infinity },
+ expected: 0 },
+ { desc: 'a zero duration and zero iteration count',
+ input: { duration: 0, iterations: 0 },
+ expected: 0 },
+ { desc: 'an infinite duration and default iteration count',
+ input: { duration: Infinity },
+ expected: Infinity },
+ { desc: 'an infinite duration and zero iteration count',
+ input: { duration: Infinity, iterations: 0 },
+ expected: 0 },
+ { desc: 'an infinite duration and fractional iteration count',
+ input: { duration: Infinity, iterations: 2.5 },
+ expected: Infinity },
+ { desc: 'an infinite duration and infinite iteration count',
+ input: { duration: Infinity, iterations: Infinity },
+ expected: Infinity },
+];
+
+for (const stest of gActiveDurationTests) {
+ test(t => {
+ const effect = new KeyframeEffect(null, null, stest.input);
+
+ assert_equals(effect.getComputedTiming().activeDuration,
+ stest.expected);
+
+ }, `getComputedTiming().activeDuration for ${stest.desc}`);
+}
+
+const gEndTimeTests = [
+ { desc: 'an empty KeyframeEffectOptions object',
+ input: { },
+ expected: 0 },
+ { desc: 'a non-zero duration and default iteration count',
+ input: { duration: 1000 },
+ expected: 1000 },
+ { desc: 'a non-zero duration and non-default iteration count',
+ input: { duration: 1000, iterations: 2.5 },
+ expected: 2500 },
+ { desc: 'a non-zero duration and non-zero delay',
+ input: { duration: 1000, delay: 1500 },
+ expected: 2500 },
+ { desc: 'a non-zero duration, non-zero delay and non-default iteration',
+ input: { duration: 1000, delay: 1500, iterations: 2 },
+ expected: 3500 },
+ { desc: 'an infinite iteration count',
+ input: { duration: 1000, iterations: Infinity },
+ expected: Infinity },
+ { desc: 'an infinite duration',
+ input: { duration: Infinity, iterations: 10 },
+ expected: Infinity },
+ { desc: 'an infinite duration and delay',
+ input: { duration: Infinity, iterations: 10, delay: 1000 },
+ expected: Infinity },
+ { desc: 'an infinite duration and negative delay',
+ input: { duration: Infinity, iterations: 10, delay: -1000 },
+ expected: Infinity },
+ { desc: 'an non-zero duration and negative delay',
+ input: { duration: 1000, iterations: 2, delay: -1000 },
+ expected: 1000 },
+ { desc: 'an non-zero duration and negative delay greater than active ' +
+ 'duration',
+ input: { duration: 1000, iterations: 2, delay: -3000 },
+ expected: 0 },
+ { desc: 'a zero duration and negative delay',
+ input: { duration: 0, iterations: 2, delay: -1000 },
+ expected: 0 }
+];
+
+for (const stest of gEndTimeTests) {
+ test(t => {
+ const effect = new KeyframeEffect(null, null, stest.input);
+
+ assert_equals(effect.getComputedTiming().endTime,
+ stest.expected);
+
+ }, `getComputedTiming().endTime for ${stest.desc}`);
+}
+
+done();
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/idlharness.html b/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/idlharness.html
index 866d5bf8ee5..7e537d1dd83 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/idlharness.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/idlharness.html
@@ -2,9 +2,9 @@
<meta charset=utf-8>
<title>AnimationEffectTiming and AnimationEffectTimingReadOnly IDL</title>
<link rel="help"
- href="https://w3c.github.io/web-animations/#animationeffecttiming">
+ href="https://drafts.csswg.org/web-animations/#animationeffecttiming">
<link rel="help"
- href="https://w3c.github.io/web-animations/#animationeffecttimingreadonly">
+ href="https://drafts.csswg.org/web-animations/#animationeffecttimingreadonly">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/WebIDLParser.js"></script>
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/iterationStart.html b/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/iterationStart.html
index ed2d0e097ac..5521f1e8594 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/iterationStart.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/iterationStart.html
@@ -1,8 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>iterationStart tests</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffecttiming-iterationstart">
-<link rel="author" title="Daisuke Akatsuka" href="mailto:daisuke@mozilla-japan.org">
+<title>AnimationEffectTiming.iterationStart</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-iterationstart">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -11,66 +10,63 @@
<script>
'use strict';
-test(function(t) {
- var anim = createDiv(t).animate(null);
+test(t => {
+ const anim = createDiv(t).animate(null);
assert_equals(anim.effect.timing.iterationStart, 0);
-}, 'Test default value');
+}, 'Has the default value 0');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] },
- { iterationStart: 0.2,
- iterations: 1,
- fill: 'both',
- duration: 100,
- delay: 1 });
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] },
+ { iterationStart: 0.2,
+ iterations: 1,
+ fill: 'both',
+ duration: 100,
+ delay: 1 });
anim.effect.timing.iterationStart = 2.5;
assert_times_equal(anim.effect.getComputedTiming().progress, 0.5);
assert_equals(anim.effect.getComputedTiming().currentIteration, 2);
-}, 'Test that changing the iterationStart affects computed timing ' +
- 'when backwards-filling');
+}, 'Changing the value updates computed timing when backwards-filling');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] },
- { iterationStart: 0.2,
- iterations: 1,
- fill: 'both',
- duration: 100,
- delay: 0 });
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] },
+ { iterationStart: 0.2,
+ iterations: 1,
+ fill: 'both',
+ duration: 100,
+ delay: 0 });
anim.effect.timing.iterationStart = 2.5;
assert_times_equal(anim.effect.getComputedTiming().progress, 0.5);
assert_equals(anim.effect.getComputedTiming().currentIteration, 2);
-}, 'Test that changing the iterationStart affects computed timing ' +
- 'during the active phase');
+}, 'Changing the value updates computed timing during the active phase');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] },
- { iterationStart: 0.2,
- iterations: 1,
- fill: 'both',
- duration: 100,
- delay: 0 });
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] },
+ { iterationStart: 0.2,
+ iterations: 1,
+ fill: 'both',
+ duration: 100,
+ delay: 0 });
anim.finish();
anim.effect.timing.iterationStart = 2.5;
assert_times_equal(anim.effect.getComputedTiming().progress, 0.5);
assert_equals(anim.effect.getComputedTiming().currentIteration, 3);
-}, 'Test that changing the iterationStart affects computed timing ' +
- 'when forwards-filling');
+}, 'Changing the value updates computed timing when forwards-filling');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate(null);
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate(null);
for (let invalid of [-1, NaN, Infinity]) {
- assert_throws({ name: 'TypeError' }, function() {
+ assert_throws({ name: 'TypeError' }, () => {
anim.effect.timing.iterationStart = invalid;
- }, 'setting ' + invalid);
- assert_throws({ name: 'TypeError' }, function() {
+ }, `setting ${invalid}`);
+ assert_throws({ name: 'TypeError' }, () => {
div.animate({}, { iterationStart: invalid });
- }, 'animate() with ' + invalid);
+ }, `animate() with ${invalid}`);
}
-}, 'Using invalid values should throw TypeError');
+}, 'Throws when setting invalid values');
</script>
</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/iterations.html b/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/iterations.html
index 8dfe1695643..32390626463 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/iterations.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationEffectTiming/iterations.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>iterations tests</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffecttiming-iterations">
+<title>AnimationEffectTiming.iterations</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-animationeffecttiming-iterations">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -10,52 +10,85 @@
<script>
'use strict';
-test(function(t) {
- var anim = createDiv(t).animate(null);
+test(t => {
+ const anim = createDiv(t).animate(null);
assert_equals(anim.effect.timing.iterations, 1);
-}, 'Test default value');
+}, 'Has the default value 1');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
anim.effect.timing.iterations = 2;
assert_equals(anim.effect.timing.iterations, 2, 'set duration 2');
assert_equals(anim.effect.getComputedTiming().iterations, 2,
'getComputedTiming() after set iterations 2');
-}, 'set iterations 2');
+}, 'Can be set to a double value');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
anim.effect.timing.iterations = Infinity;
assert_equals(anim.effect.timing.iterations, Infinity, 'set duration Infinity');
assert_equals(anim.effect.getComputedTiming().iterations, Infinity,
'getComputedTiming() after set iterations Infinity');
-}, 'set iterations Infinity');
+}, 'Can be set to infinity');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- assert_throws({ name: 'TypeError' }, function() {
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+ assert_throws({ name: 'TypeError' }, () => {
anim.effect.timing.iterations = -1;
});
-}, 'set negative iterations');
+}, 'Throws when setting a negative number');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- assert_throws({ name: 'TypeError' }, function() {
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+ assert_throws({ name: 'TypeError' }, () => {
anim.effect.timing.iterations = -Infinity;
});
-}, 'set negative infinity iterations ');
+}, 'Throws when setting negative infinity');
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
- assert_throws({ name: 'TypeError' }, function() {
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, 2000);
+ assert_throws({ name: 'TypeError' }, () => {
anim.effect.timing.iterations = NaN;
});
-}, 'set NaN iterations');
+}, 'Throws when setting a NaN value');
+
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate(null, { duration: 100000, fill: 'both' });
+
+ anim.finish();
+
+ assert_equals(anim.effect.getComputedTiming().progress, 1,
+ 'progress when animation is finished');
+ assert_equals(anim.effect.getComputedTiming().currentIteration, 0,
+ 'current iteration when animation is finished');
+
+ anim.effect.timing.iterations = 2;
+
+ assert_times_equal(anim.effect.getComputedTiming().progress, 0,
+ 'progress after adding an iteration');
+ assert_times_equal(anim.effect.getComputedTiming().currentIteration, 1,
+ 'current iteration after adding an iteration');
+
+ anim.effect.timing.iterations = 0;
+
+ assert_equals(anim.effect.getComputedTiming().progress, 0,
+ 'progress after setting iterations to zero');
+ assert_equals(anim.effect.getComputedTiming().currentIteration, 0,
+ 'current iteration after setting iterations to zero');
+
+ anim.effect.timing.iterations = Infinity;
+
+ assert_equals(anim.effect.getComputedTiming().progress, 0,
+ 'progress after setting iterations to Infinity');
+ assert_equals(anim.effect.getComputedTiming().currentIteration, 1,
+ 'current iteration after setting iterations to Infinity');
+}, 'Can be updated while the animation is in progress');
</script>
</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationPlaybackEvent/constructor.html b/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationPlaybackEvent/constructor.html
index ca6dc6eec0c..1c40a3fb211 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationPlaybackEvent/constructor.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationPlaybackEvent/constructor.html
@@ -2,21 +2,21 @@
<meta charset=utf-8>
<title>AnimationPlaybackEvent constructor</title>
<link rel="help"
- href="https://w3c.github.io/web-animations/#dom-animationplaybackevent-animationplaybackevent">
+ href="https://drafts.csswg.org/web-animations/#dom-animationplaybackevent-animationplaybackevent">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
<script>
'use strict';
-test(function(t) {
+test(t => {
const evt = new AnimationPlaybackEvent('finish');
assert_equals(evt.type, 'finish');
assert_equals(evt.currentTime, null);
assert_equals(evt.timelineTime, null);
}, 'Event created without an event parameter has null time values');
-test(function(t) {
+test(t => {
const evt =
new AnimationPlaybackEvent('cancel', {
currentTime: -100,
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationPlaybackEvent/idlharness.html b/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationPlaybackEvent/idlharness.html
index f4e3e8cd115..0c3517387cd 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationPlaybackEvent/idlharness.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/AnimationPlaybackEvent/idlharness.html
@@ -2,7 +2,7 @@
<meta charset=utf-8>
<title>AnimationPlaybackEvent IDL</title>
<link rel="help"
- href="https://w3c.github.io/web-animations/#animationplaybackevent">
+ href="https://drafts.csswg.org/web-animations/#animationplaybackevent">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/WebIDLParser.js"></script>
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/Document/getAnimations.html b/tests/wpt/web-platform-tests/web-animations/interfaces/Document/getAnimations.html
index e87751c04b2..165626decc9 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/Document/getAnimations.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/Document/getAnimations.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>document.getAnimations tests</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#dom-document-getanimations">
+<title>Document.getAnimations</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-document-getanimations">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -9,20 +9,20 @@
<div id="log"></div>
<div id="target"></div>
<script>
-"use strict";
+'use strict';
-var gKeyFrames = { 'marginLeft': ['100px', '200px'] };
+const gKeyFrames = { 'marginLeft': ['100px', '200px'] };
-test(function(t) {
+test(t => {
assert_equals(document.getAnimations().length, 0,
'getAnimations returns an empty sequence for a document ' +
'with no animations');
}, 'Test document.getAnimations for non-animated content');
-test(function(t) {
- var div = createDiv(t);
- var anim1 = div.animate(gKeyFrames, 100 * MS_PER_SEC);
- var anim2 = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+test(t => {
+ const div = createDiv(t);
+ const anim1 = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+ const anim2 = div.animate(gKeyFrames, 100 * MS_PER_SEC);
assert_equals(document.getAnimations().length, 2,
'getAnimation returns running animations');
@@ -32,18 +32,18 @@ test(function(t) {
'getAnimation only returns running animations');
}, 'Test document.getAnimations for script-generated animations')
-test(function(t) {
- var div = createDiv(t);
- var anim1 = div.animate(gKeyFrames, 100 * MS_PER_SEC);
- var anim2 = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+test(t => {
+ const div = createDiv(t);
+ const anim1 = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+ const anim2 = div.animate(gKeyFrames, 100 * MS_PER_SEC);
assert_array_equals(document.getAnimations(),
[ anim1, anim2 ],
'getAnimations() returns running animations');
}, 'Test the order of document.getAnimations with script generated animations')
-test(function(t) {
- var effect = new KeyframeEffectReadOnly(null, gKeyFrames, 100 * MS_PER_SEC);
- var anim = new Animation(effect, document.timeline);
+test(t => {
+ const effect = new KeyframeEffectReadOnly(null, gKeyFrames, 100 * MS_PER_SEC);
+ const anim = new Animation(effect, document.timeline);
anim.play();
assert_equals(document.getAnimations().length, 0,
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/Document/timeline.html b/tests/wpt/web-platform-tests/web-animations/interfaces/Document/timeline.html
index b8a530345ad..b8b4d74d5e5 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/Document/timeline.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/Document/timeline.html
@@ -1,7 +1,7 @@
<!doctype html>
<meta charset=utf-8>
<title>Document.timeline</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#dom-document-timeline">
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-document-timeline">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -10,7 +10,7 @@
<script>
'use strict';
-test(function() {
+test(() => {
assert_equals(document.timeline, document.timeline,
'Document.timeline returns the same object every time');
const iframe = document.getElementById('iframe');
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/DocumentTimeline/constructor.html b/tests/wpt/web-platform-tests/web-animations/interfaces/DocumentTimeline/constructor.html
index 8968ff4ce8e..e4714be02f8 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/DocumentTimeline/constructor.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/DocumentTimeline/constructor.html
@@ -1,37 +1,37 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>DocumentTimeline constructor tests</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#the-documenttimeline-interface">
+<link rel="help" href="https://drafts.csswg.org/web-animations/#the-documenttimeline-interface">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
<body>
<div id="log"></div>
<script>
-"use strict";
+'use strict';
-test(function(t) {
- var timeline = new DocumentTimeline();
+test(t => {
+ const timeline = new DocumentTimeline();
assert_times_equal(timeline.currentTime, document.timeline.currentTime);
}, 'An origin time of zero is used when none is supplied');
-test(function(t) {
- var timeline = new DocumentTimeline({ originTime: 0 });
+test(t => {
+ const timeline = new DocumentTimeline({ originTime: 0 });
assert_times_equal(timeline.currentTime, document.timeline.currentTime);
}, 'A zero origin time produces a document timeline with a current time ' +
'identical to the default document timeline');
-test(function(t) {
- var timeline = new DocumentTimeline({ originTime: 10 * MS_PER_SEC });
+test(t => {
+ const timeline = new DocumentTimeline({ originTime: 10 * MS_PER_SEC });
assert_times_equal(timeline.currentTime,
(document.timeline.currentTime - 10 * MS_PER_SEC));
}, 'A positive origin time makes the document timeline\'s current time lag ' +
'behind the default document timeline');
-test(function(t) {
- var timeline = new DocumentTimeline({ originTime: -10 * MS_PER_SEC });
+test(t => {
+ const timeline = new DocumentTimeline({ originTime: -10 * MS_PER_SEC });
assert_times_equal(timeline.currentTime,
(document.timeline.currentTime + 10 * MS_PER_SEC));
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/DocumentTimeline/idlharness.html b/tests/wpt/web-platform-tests/web-animations/interfaces/DocumentTimeline/idlharness.html
index 639aa2e97c8..696f4f79385 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/DocumentTimeline/idlharness.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/DocumentTimeline/idlharness.html
@@ -1,7 +1,7 @@
<!doctype html>
<meta charset=utf-8>
<title>DocumentTimeline IDL</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#documenttimeline">
+<link rel="help" href="https://drafts.csswg.org/web-animations/#documenttimeline">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/WebIDLParser.js"></script>
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/composite.html b/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/composite.html
index 1825b71db09..745f66bc711 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/composite.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/composite.html
@@ -1,8 +1,8 @@
<!doctype html>
<meta charset=utf-8>
-<title>KeyframeEffect.composite tests</title>
+<title>KeyframeEffect.composite</title>
<link rel="help"
- href="https://w3c.github.io/web-animations/#dom-keyframeeffect-composite">
+ href="https://drafts.csswg.org/web-animations/#dom-keyframeeffect-composite">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -11,34 +11,34 @@
<script>
'use strict';
-test(function(t) {
- var anim = createDiv(t).animate(null);
+test(t => {
+ const anim = createDiv(t).animate(null);
assert_equals(anim.effect.composite, 'replace',
'The default value should be replace');
}, 'Default value');
-test(function(t) {
- var anim = createDiv(t).animate(null);
+test(t => {
+ const anim = createDiv(t).animate(null);
anim.effect.composite = 'add';
assert_equals(anim.effect.composite, 'add',
'The effect composite value should be replaced');
}, 'Change composite value');
-test(function(t) {
- var anim = createDiv(t).animate({ left: '10px' });
+test(t => {
+ const anim = createDiv(t).animate({ left: '10px' });
anim.effect.composite = 'add';
- var keyframes = anim.effect.getKeyframes();
+ const keyframes = anim.effect.getKeyframes();
assert_equals(keyframes[0].composite, undefined,
'unspecified keyframe composite value should be absent even ' +
'if effect composite is set');
}, 'Unspecified keyframe composite value when setting effect composite');
-test(function(t) {
- var anim = createDiv(t).animate({ left: '10px', composite: 'replace' });
+test(t => {
+ const anim = createDiv(t).animate({ left: '10px', composite: 'replace' });
anim.effect.composite = 'add';
- var keyframes = anim.effect.getKeyframes();
+ const keyframes = anim.effect.getKeyframes();
assert_equals(keyframes[0].composite, 'replace',
'specified keyframe composite value should not be overridden ' +
'by setting effect composite');
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/constructor.html b/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/constructor.html
index 711b4ed7bd7..b257257b2ca 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/constructor.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/constructor.html
@@ -2,9 +2,9 @@
<meta charset=utf-8>
<title>KeyframeEffect and KeyframeEffectReadOnly constructor</title>
<link rel="help"
- href="https://w3c.github.io/web-animations/#dom-keyframeeffect-keyframeeffect">
+ href="https://drafts.csswg.org/web-animations/#dom-keyframeeffect-keyframeeffect">
<link rel="help"
- href="https://w3c.github.io/web-animations/#dom-keyframeeffectreadonly-keyframeeffectreadonly">
+ href="https://drafts.csswg.org/web-animations/#dom-keyframeeffectreadonly-keyframeeffectreadonly">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -19,16 +19,16 @@
const target = document.getElementById('target');
-test(function(t) {
- gEmptyKeyframeListTests.forEach(function(frames) {
+test(t => {
+ for (const frames of gEmptyKeyframeListTests) {
assert_equals(new KeyframeEffectReadOnly(target, frames)
.getKeyframes().length,
- 0, 'number of frames for ' + JSON.stringify(frames));
- });
+ 0, `number of frames for ${JSON.stringify(frames)}`);
+ }
}, 'A KeyframeEffectReadOnly can be constructed with no frames');
-test(function(t) {
- gEasingParsingTests.forEach(function(subtest) {
+test(t => {
+ for (const subtest of gEasingParsingTests) {
const easing = subtest[0];
const expected = subtest[1];
const effect = new KeyframeEffectReadOnly(target, {
@@ -36,98 +36,96 @@ test(function(t) {
}, { easing: easing });
assert_equals(effect.timing.easing, expected,
`resulting easing for '${easing}'`);
- });
+ }
}, 'easing values are parsed correctly when passed to the ' +
'KeyframeEffectReadOnly constructor in KeyframeEffectOptions');
-test(function(t) {
- gInvalidEasings.forEach(invalidEasing => {
+test(t => {
+ for (const invalidEasing of gInvalidEasings) {
assert_throws(new TypeError, () => {
new KeyframeEffectReadOnly(target, null, { easing: invalidEasing });
}, `TypeError is thrown for easing '${invalidEasing}'`);
- });
+ }
}, 'Invalid easing values are correctly rejected when passed to the ' +
'KeyframeEffectReadOnly constructor in KeyframeEffectOptions');
-test(function(t) {
- const getKeyframe = function(composite) {
- return { left: [ '10px', '20px' ], composite: composite };
- };
- gGoodKeyframeCompositeValueTests.forEach(function(composite) {
+test(t => {
+ const getKeyframe =
+ composite => ({ left: [ '10px', '20px' ], composite: composite });
+ for (const composite of gGoodKeyframeCompositeValueTests) {
const effect = new KeyframeEffectReadOnly(target, getKeyframe(composite));
assert_equals(effect.getKeyframes()[0].composite, composite,
`resulting composite for '${composite}'`);
- });
- gBadCompositeValueTests.forEach(function(composite) {
- assert_throws(new TypeError, function() {
+ }
+ for (const composite of gBadCompositeValueTests) {
+ assert_throws(new TypeError, () => {
new KeyframeEffectReadOnly(target, getKeyframe(composite));
});
- });
+ }
}, 'composite values are parsed correctly when passed to the ' +
'KeyframeEffectReadOnly constructor in property-indexed keyframes');
-test(function(t) {
- const getKeyframes = function(composite) {
- return [
+test(t => {
+ const getKeyframes = composite =>
+ [
{ offset: 0, left: '10px', composite: composite },
{ offset: 1, left: '20px' }
];
- };
- gGoodKeyframeCompositeValueTests.forEach(function(composite) {
+ for (const composite of gGoodKeyframeCompositeValueTests) {
const effect = new KeyframeEffectReadOnly(target, getKeyframes(composite));
assert_equals(effect.getKeyframes()[0].composite, composite,
`resulting composite for '${composite}'`);
- });
- gBadCompositeValueTests.forEach(function(composite) {
- assert_throws(new TypeError, function() {
+ }
+ for (const composite of gBadCompositeValueTests) {
+ assert_throws(new TypeError, () => {
new KeyframeEffectReadOnly(target, getKeyframes(composite));
});
- });
+ }
}, 'composite values are parsed correctly when passed to the ' +
'KeyframeEffectReadOnly constructor in regular keyframes');
-test(function(t) {
- gGoodOptionsCompositeValueTests.forEach(function(composite) {
+test(t => {
+ for (const composite of gGoodOptionsCompositeValueTests) {
const effect = new KeyframeEffectReadOnly(target, {
left: ['10px', '20px']
}, { composite: composite });
assert_equals(effect.getKeyframes()[0].composite, undefined,
`resulting composite for '${composite}'`);
- });
- gBadCompositeValueTests.forEach(function(composite) {
- assert_throws(new TypeError, function() {
+ }
+ for (const composite of gBadCompositeValueTests) {
+ assert_throws(new TypeError, () => {
new KeyframeEffectReadOnly(target, {
left: ['10px', '20px']
}, { composite: composite });
});
- });
+ }
}, 'composite value is absent if the composite operation specified on the ' +
'keyframe effect is being used');
-gKeyframesTests.forEach(function(subtest) {
- test(function(t) {
+for (const subtest of gKeyframesTests) {
+ test(t => {
const effect = new KeyframeEffectReadOnly(target, subtest.input);
assert_frame_lists_equal(effect.getKeyframes(), subtest.output);
}, `A KeyframeEffectReadOnly can be constructed with ${subtest.desc}`);
- test(function(t) {
+ test(t => {
const effect = new KeyframeEffectReadOnly(target, subtest.input);
const secondEffect =
new KeyframeEffectReadOnly(target, effect.getKeyframes());
assert_frame_lists_equal(secondEffect.getKeyframes(),
effect.getKeyframes());
}, `A KeyframeEffectReadOnly constructed with ${subtest.desc} roundtrips`);
-});
+}
-gInvalidKeyframesTests.forEach(function(subtest) {
- test(function(t) {
- assert_throws(new TypeError, function() {
+for (const subtest of gInvalidKeyframesTests) {
+ test(t => {
+ assert_throws(new TypeError, () => {
new KeyframeEffectReadOnly(target, subtest.input);
});
}, `KeyframeEffectReadOnly constructor throws with ${subtest.desc}`);
-});
+}
-test(function(t) {
+test(t => {
const effect = new KeyframeEffectReadOnly(target,
{ left: ['10px', '20px'] });
@@ -147,8 +145,8 @@ test(function(t) {
}, 'A KeyframeEffectReadOnly constructed without any ' +
'KeyframeEffectOptions object');
-gKeyframeEffectOptionTests.forEach(function(subtest) {
- test(function(t) {
+for (const subtest of gKeyframeEffectOptionTests) {
+ test(t => {
const effect = new KeyframeEffectReadOnly(target,
{ left: ['10px', '20px'] },
subtest.input);
@@ -172,19 +170,19 @@ gKeyframeEffectOptionTests.forEach(function(subtest) {
'timing direction');
}, `A KeyframeEffectReadOnly constructed by ${subtest.desc}`);
-});
+}
-gInvalidKeyframeEffectOptionTests.forEach(function(subtest) {
- test(function(t) {
- assert_throws(new TypeError, function() {
+for (const subtest of gInvalidKeyframeEffectOptionTests) {
+ test(t => {
+ assert_throws(new TypeError, () => {
new KeyframeEffectReadOnly(target,
{ left: ['10px', '20px'] },
subtest.input);
});
}, `Invalid KeyframeEffectReadOnly option by ${subtest.desc}`);
-});
+}
-test(function(t) {
+test(t => {
const effect = new KeyframeEffectReadOnly(null,
{ left: ['10px', '20px'] },
{ duration: 100 * MS_PER_SEC,
@@ -193,10 +191,10 @@ test(function(t) {
'Effect created with null target has correct target');
}, 'A KeyframeEffectReadOnly constructed with null target');
-test(function(t) {
+test(t => {
const test_error = { name: 'test' };
- assert_throws(test_error, function() {
+ assert_throws(test_error, () => {
new KeyframeEffect(target, { get left() { throw test_error }})
});
}, 'KeyframeEffect constructor propagates exceptions generated by accessing'
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/copy-constructor.html b/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/copy-constructor.html
index a6b413231e2..c4e8a8ec37c 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/copy-constructor.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/copy-constructor.html
@@ -2,9 +2,9 @@
<meta charset=utf-8>
<title>KeyframeEffect and KeyframeEffectReadOnly copy constructor</title>
<link rel="help"
- href="https://w3c.github.io/web-animations/#dom-keyframeeffect-keyframeeffect-source">
+ href="https://drafts.csswg.org/web-animations/#dom-keyframeeffect-keyframeeffect-source">
<link rel="help"
- href="https://w3c.github.io/web-animations/#dom-keyframeeffectreadonly-keyframeeffectreadonly-source">
+ href="https://drafts.csswg.org/web-animations/#dom-keyframeeffectreadonly-keyframeeffectreadonly-source">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -13,13 +13,13 @@
<script>
'use strict';
-test(function(t) {
+test(t => {
const effect = new KeyframeEffectReadOnly(createDiv(t), null);
const copiedEffect = new KeyframeEffectReadOnly(effect);
assert_equals(copiedEffect.target, effect.target, 'same target');
}, 'Copied KeyframeEffectReadOnly has the same target');
-test(function(t) {
+test(t => {
const effect =
new KeyframeEffectReadOnly(null,
[ { marginLeft: '0px' },
@@ -52,7 +52,7 @@ test(function(t) {
}
}, 'Copied KeyframeEffectReadOnly has the same keyframes');
-test(function(t) {
+test(t => {
const effect =
new KeyframeEffectReadOnly(null, null,
{ iterationComposite: 'accumulate' });
@@ -64,7 +64,7 @@ test(function(t) {
'same compositeOperation');
}, 'Copied KeyframeEffectReadOnly has the same KeyframeEffectOptions');
-test(function(t) {
+test(t => {
const effect = new KeyframeEffectReadOnly(null, null,
{ duration: 100 * MS_PER_SEC,
delay: -1 * MS_PER_SEC,
@@ -90,7 +90,7 @@ test(function(t) {
assert_equals(timingA.easing, timingB.easing, 'same easing');
}, 'Copied KeyframeEffectReadOnly has the same timing content');
-test(function(t) {
+test(t => {
const effect = new KeyframeEffectReadOnly(createDiv(t), null);
assert_equals(effect.constructor.name, 'KeyframeEffectReadOnly');
assert_equals(effect.timing.constructor.name,
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/getComputedTiming.html b/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/getComputedTiming.html
deleted file mode 100644
index 4d799272b9a..00000000000
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/getComputedTiming.html
+++ /dev/null
@@ -1,212 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>KeyframeEffectReadOnly getComputedTiming() tests</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#dom-animationeffectreadonly-getcomputedtiming">
-<link rel="author" title="Boris Chiou" href="mailto:boris.chiou@gmail.com">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<div id="target"></div>
-<script>
-"use strict";
-
-var target = document.getElementById("target");
-
-test(function(t) {
- var effect = new KeyframeEffectReadOnly(target,
- { left: ["10px", "20px"] });
-
- var ct = effect.getComputedTiming();
- assert_equals(ct.delay, 0, "computed delay");
- assert_equals(ct.fill, "none", "computed fill");
- assert_equals(ct.iterations, 1.0, "computed iterations");
- assert_equals(ct.duration, 0, "computed duration");
- assert_equals(ct.direction, "normal", "computed direction");
-}, "values of getComputedTiming() when a KeyframeEffectReadOnly is " +
- "constructed without any KeyframeEffectOptions object");
-
-var gGetComputedTimingTests = [
- { desc: "an empty KeyframeEffectOptions object",
- input: { },
- expected: { } },
- { desc: "a normal KeyframeEffectOptions object",
- input: { delay: 1000,
- fill: "auto",
- iterations: 5.5,
- duration: "auto",
- direction: "alternate" },
- expected: { delay: 1000,
- fill: "none",
- iterations: 5.5,
- duration: 0,
- direction: "alternate" } },
- { desc: "a double value",
- input: 3000,
- timing: { duration: 3000 },
- expected: { delay: 0,
- fill: "none",
- iterations: 1,
- duration: 3000,
- direction: "normal" } },
- { desc: "+Infinity",
- input: Infinity,
- expected: { duration: Infinity } },
- { desc: "an Infinity duration",
- input: { duration: Infinity },
- expected: { duration: Infinity } },
- { desc: "an auto duration",
- input: { duration: "auto" },
- expected: { duration: 0 } },
- { desc: "an Infinity iterations",
- input: { iterations: Infinity },
- expected: { iterations: Infinity } },
- { desc: "an auto fill",
- input: { fill: "auto" },
- expected: { fill: "none" } },
- { desc: "a forwards fill",
- input: { fill: "forwards" },
- expected: { fill: "forwards" } }
-];
-
-gGetComputedTimingTests.forEach(function(stest) {
- test(function(t) {
- var effect = new KeyframeEffectReadOnly(target,
- { left: ["10px", "20px"] },
- stest.input);
-
- // Helper function to provide default expected values when the test does
- // not supply them.
- var expected = function(field, defaultValue) {
- return field in stest.expected ? stest.expected[field] : defaultValue;
- };
-
- var ct = effect.getComputedTiming();
- assert_equals(ct.delay, expected("delay", 0),
- "computed delay");
- assert_equals(ct.fill, expected("fill", "none"),
- "computed fill");
- assert_equals(ct.iterations, expected("iterations", 1),
- "computed iterations");
- assert_equals(ct.duration, expected("duration", 0),
- "computed duration");
- assert_equals(ct.direction, expected("direction", "normal"),
- "computed direction");
-
- }, "values of getComputedTiming() when a KeyframeEffectReadOnly is " +
- "constructed by " + stest.desc);
-});
-
-var gActiveDurationTests = [
- { desc: "an empty KeyframeEffectOptions object",
- input: { },
- expected: 0 },
- { desc: "a non-zero duration and default iteration count",
- input: { duration: 1000 },
- expected: 1000 },
- { desc: "a non-zero duration and integral iteration count",
- input: { duration: 1000, iterations: 7 },
- expected: 7000 },
- { desc: "a non-zero duration and fractional iteration count",
- input: { duration: 1000, iterations: 2.5 },
- expected: 2500 },
- { desc: "an non-zero duration and infinite iteration count",
- input: { duration: 1000, iterations: Infinity },
- expected: Infinity },
- { desc: "an non-zero duration and zero iteration count",
- input: { duration: 1000, iterations: 0 },
- expected: 0 },
- { desc: "a zero duration and default iteration count",
- input: { duration: 0 },
- expected: 0 },
- { desc: "a zero duration and fractional iteration count",
- input: { duration: 0, iterations: 2.5 },
- expected: 0 },
- { desc: "a zero duration and infinite iteration count",
- input: { duration: 0, iterations: Infinity },
- expected: 0 },
- { desc: "a zero duration and zero iteration count",
- input: { duration: 0, iterations: 0 },
- expected: 0 },
- { desc: "an infinite duration and default iteration count",
- input: { duration: Infinity },
- expected: Infinity },
- { desc: "an infinite duration and zero iteration count",
- input: { duration: Infinity, iterations: 0 },
- expected: 0 },
- { desc: "an infinite duration and fractional iteration count",
- input: { duration: Infinity, iterations: 2.5 },
- expected: Infinity },
- { desc: "an infinite duration and infinite iteration count",
- input: { duration: Infinity, iterations: Infinity },
- expected: Infinity },
-];
-
-gActiveDurationTests.forEach(function(stest) {
- test(function(t) {
- var effect = new KeyframeEffectReadOnly(target,
- { left: ["10px", "20px"] },
- stest.input);
-
- assert_equals(effect.getComputedTiming().activeDuration,
- stest.expected);
-
- }, "getComputedTiming().activeDuration for " + stest.desc);
-});
-
-var gEndTimeTests = [
- { desc: "an empty KeyframeEffectOptions object",
- input: { },
- expected: 0 },
- { desc: "a non-zero duration and default iteration count",
- input: { duration: 1000 },
- expected: 1000 },
- { desc: "a non-zero duration and non-default iteration count",
- input: { duration: 1000, iterations: 2.5 },
- expected: 2500 },
- { desc: "a non-zero duration and non-zero delay",
- input: { duration: 1000, delay: 1500 },
- expected: 2500 },
- { desc: "a non-zero duration, non-zero delay and non-default iteration",
- input: { duration: 1000, delay: 1500, iterations: 2 },
- expected: 3500 },
- { desc: "an infinite iteration count",
- input: { duration: 1000, iterations: Infinity },
- expected: Infinity },
- { desc: "an infinite duration",
- input: { duration: Infinity, iterations: 10 },
- expected: Infinity },
- { desc: "an infinite duration and delay",
- input: { duration: Infinity, iterations: 10, delay: 1000 },
- expected: Infinity },
- { desc: "an infinite duration and negative delay",
- input: { duration: Infinity, iterations: 10, delay: -1000 },
- expected: Infinity },
- { desc: "an non-zero duration and negative delay",
- input: { duration: 1000, iterations: 2, delay: -1000 },
- expected: 1000 },
- { desc: "an non-zero duration and negative delay greater than active " +
- "duration",
- input: { duration: 1000, iterations: 2, delay: -3000 },
- expected: 0 },
- { desc: "a zero duration and negative delay",
- input: { duration: 0, iterations: 2, delay: -1000 },
- expected: 0 }
-];
-
-gEndTimeTests.forEach(function(stest) {
- test(function(t) {
- var effect = new KeyframeEffectReadOnly(target,
- { left: ["10px", "20px"] },
- stest.input);
-
- assert_equals(effect.getComputedTiming().endTime,
- stest.expected);
-
- }, "getComputedTiming().endTime for " + stest.desc);
-});
-
-done();
-</script>
-</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/idlharness.html b/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/idlharness.html
index c3972349271..5056a875e43 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/idlharness.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/idlharness.html
@@ -1,9 +1,9 @@
<!doctype html>
<meta charset=utf-8>
<title>KeyframeEffect IDL</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#keyframeeffect">
+<link rel="help" href="https://drafts.csswg.org/web-animations/#keyframeeffect">
<link rel="help"
- href="https://w3c.github.io/web-animations/#keyframeeffectreadonly">
+ href="https://drafts.csswg.org/web-animations/#keyframeeffectreadonly">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/WebIDLParser.js"></script>
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/iterationComposite.html b/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/iterationComposite.html
index 7719fa9c1c5..de2afa7c2b8 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/iterationComposite.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/iterationComposite.html
@@ -1,7 +1,7 @@
<!doctype html>
<meta charset=utf-8>
-<title>KeyframeEffect.iterationComposite tests</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#effect-accumulation-section">
+<title>KeyframeEffect.iterationComposite</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-keyframeeffect-iterationcomposite">
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script src="../../testcommon.js"></script>
@@ -9,792 +9,13 @@
<script>
'use strict';
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ alignContent: ['flex-start', 'flex-end'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).alignContent, 'flex-end',
- 'Animated align-content style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_equals(getComputedStyle(div).alignContent, 'flex-start',
- 'Animated align-content style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).alignContent, 'flex-end',
- 'Animated align-content style at 50s of the third iteration');
-}, 'iterationComposite of discrete type animation (align-content)');
-
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ marginLeft: ['0px', '10px'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).marginLeft, '5px',
- 'Animated margin-left style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_equals(getComputedStyle(div).marginLeft, '20px',
- 'Animated margin-left style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).marginLeft, '25px',
- 'Animated margin-left style at 50s of the third iteration');
-}, 'iterationComposite of <length> type animation');
-
-test(function(t) {
- var parent = createDiv(t);
- parent.style.width = '100px';
- var div = createDiv(t);
- parent.appendChild(div);
-
- var anim =
- div.animate({ width: ['0%', '50%'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).width, '25px',
- 'Animated width style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_equals(getComputedStyle(div).width, '100px',
- 'Animated width style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).width, '125px',
- 'Animated width style at 50s of the third iteration');
-}, 'iterationComposite of <percentage> type animation');
-
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ color: ['rgb(0, 0, 0)', 'rgb(120, 120, 120)'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).color, 'rgb(60, 60, 60)',
- 'Animated color style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_equals(getComputedStyle(div).color, 'rgb(240, 240, 240)',
- 'Animated color style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).color, 'rgb(255, 255, 255)',
- 'Animated color style at 50s of the third iteration');
-}, 'iterationComposite of <color> type animation');
-
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ color: ['rgb(0, 120, 0)', 'rgb(60, 60, 60)'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).color, 'rgb(30, 90, 30)',
- 'Animated color style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_equals(getComputedStyle(div).color, 'rgb(120, 240, 120)',
- 'Animated color style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- // The green color is (240 + 180) / 2 = 210
- assert_equals(getComputedStyle(div).color, 'rgb(150, 210, 150)',
- 'Animated color style at 50s of the third iteration');
-}, 'iterationComposite of <color> type animation that green component is ' +
- 'decreasing');
-
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ flexGrow: [0, 10] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).flexGrow, '5',
- 'Animated flex-grow style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_equals(getComputedStyle(div).flexGrow, '20',
- 'Animated flex-grow style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).flexGrow, '25',
- 'Animated flex-grow style at 50s of the third iteration');
-}, 'iterationComposite of <number> type animation');
-
-test(function(t) {
- var div = createDiv(t);
- div.style.position = 'absolute';
- var anim =
- div.animate({ clip: ['rect(0px, 0px, 0px, 0px)',
- 'rect(10px, 10px, 10px, 10px)'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).clip, 'rect(5px, 5px, 5px, 5px)',
- 'Animated clip style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_equals(getComputedStyle(div).clip, 'rect(20px, 20px, 20px, 20px)',
- 'Animated clip style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).clip, 'rect(25px, 25px, 25px, 25px)',
- 'Animated clip style at 50s of the third iteration');
-}, 'iterationComposite of <shape> type animation');
-
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ width: ['calc(0vw + 0px)', 'calc(0vw + 10px)'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).width, '5px',
- 'Animated calc width style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_equals(getComputedStyle(div).width, '20px',
- 'Animated calc width style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).width, '25px',
- 'Animated calc width style at 50s of the third iteration');
-}, 'iterationComposite of <calc()> value animation');
-
-test(function(t) {
- var parent = createDiv(t);
- parent.style.width = '100px';
- var div = createDiv(t);
- parent.appendChild(div);
-
- var anim =
- div.animate({ width: ['calc(0% + 0px)', 'calc(10% + 10px)'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).width, '10px',
- // 100px * 5% + 5px
- 'Animated calc width style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_equals(getComputedStyle(div).width,
- '40px', // 100px * (10% + 10%) + (10px + 10px)
- 'Animated calc width style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).width,
- '50px', // (40px + 60px) / 2
- 'Animated calc width style at 50s of the third iteration');
-}, 'iterationComposite of <calc()> value animation that the values can\'t' +
- 'be reduced');
-
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ opacity: [0, 0.4] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).opacity, '0.2',
- 'Animated opacity style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_equals(getComputedStyle(div).opacity, '0.8',
- 'Animated opacity style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).opacity, '1', // (0.8 + 1.2) * 0.5
- 'Animated opacity style at 50s of the third iteration');
-}, 'iterationComposite of opacity animation');
-
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ boxShadow: ['rgb(0, 0, 0) 0px 0px 0px 0px',
- 'rgb(120, 120, 120) 10px 10px 10px 0px'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).boxShadow,
- 'rgb(60, 60, 60) 5px 5px 5px 0px',
- 'Animated box-shadow style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_equals(getComputedStyle(div).boxShadow,
- 'rgb(240, 240, 240) 20px 20px 20px 0px',
- 'Animated box-shadow style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).boxShadow,
- 'rgb(255, 255, 255) 25px 25px 25px 0px',
- 'Animated box-shadow style at 50s of the third iteration');
-}, 'iterationComposite of box-shadow animation');
-
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ filter: ['blur(0px)', 'blur(10px)'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).filter, 'blur(5px)',
- 'Animated filter blur style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_equals(getComputedStyle(div).filter, 'blur(20px)',
- 'Animated filter blur style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).filter, 'blur(25px)',
- 'Animated filter blur style at 50s of the third iteration');
-}, 'iterationComposite of filter blur animation');
-
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ filter: ['brightness(1)',
- 'brightness(180%)'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).filter,
- 'brightness(1.4)',
- 'Animated filter brightness style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_equals(getComputedStyle(div).filter,
- 'brightness(2.6)', // brightness(1) + brightness(0.8) + brightness(0.8)
- 'Animated filter brightness style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).filter,
- 'brightness(3)', // (brightness(2.6) + brightness(3.4)) * 0.5
- 'Animated filter brightness style at 50s of the third iteration');
-}, 'iterationComposite of filter brightness for different unit animation');
-
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ filter: ['brightness(0)',
- 'brightness(1)'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).filter,
- 'brightness(0.5)',
- 'Animated filter brightness style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_equals(getComputedStyle(div).filter,
- 'brightness(0)', // brightness(1) is an identity element, not accumulated.
- 'Animated filter brightness style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).filter,
- 'brightness(0.5)', // brightness(1) is an identity element, not accumulated.
- 'Animated filter brightness style at 50s of the third iteration');
-}, 'iterationComposite of filter brightness animation');
-
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ filter: ['drop-shadow(rgb(0, 0, 0) 0px 0px 0px)',
- 'drop-shadow(rgb(120, 120, 120) 10px 10px 10px)'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).filter,
- 'drop-shadow(rgb(60, 60, 60) 5px 5px 5px)',
- 'Animated filter drop-shadow style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_equals(getComputedStyle(div).filter,
- 'drop-shadow(rgb(240, 240, 240) 20px 20px 20px)',
- 'Animated filter drop-shadow style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).filter,
- 'drop-shadow(rgb(255, 255, 255) 25px 25px 25px)',
- 'Animated filter drop-shadow style at 50s of the third iteration');
-}, 'iterationComposite of filter drop-shadow animation');
-
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ filter: ['brightness(1) contrast(1)',
- 'brightness(2) contrast(2)'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).filter,
- 'brightness(1.5) contrast(1.5)',
- 'Animated filter list at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_equals(getComputedStyle(div).filter,
- 'brightness(3) contrast(3)',
- 'Animated filter list at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).filter,
- 'brightness(3.5) contrast(3.5)',
- 'Animated filter list at 50s of the third iteration');
-}, 'iterationComposite of same filter list animation');
-
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ filter: ['brightness(1) contrast(1)',
- 'contrast(2) brightness(2)'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).filter,
- 'contrast(2) brightness(2)', // discrete
- 'Animated filter list at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_equals(getComputedStyle(div).filter,
- // We can't accumulate 'contrast(2) brightness(2)' onto
- // the first list 'brightness(1) contrast(1)' because of
- // mismatch of the order.
- 'brightness(1) contrast(1)',
- 'Animated filter list at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).filter,
- // We *can* accumulate 'contrast(2) brightness(2)' onto
- // the same list 'contrast(2) brightness(2)' here.
- 'contrast(4) brightness(4)', // discrete
- 'Animated filter list at 50s of the third iteration');
-}, 'iterationComposite of discrete filter list because of mismatch ' +
- 'of the order');
-
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ filter: ['sepia(0)',
- 'sepia(1) contrast(2)'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).filter,
- 'sepia(0.5) contrast(1.5)',
- 'Animated filter list at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_equals(getComputedStyle(div).filter,
- 'sepia(2) contrast(3)',
- 'Animated filter list at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).filter,
- 'sepia(2.5) contrast(3.5)',
- 'Animated filter list at 50s of the third iteration');
-}, 'iterationComposite of different length filter list animation');
-
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ transform: ['rotate(0deg)', 'rotate(180deg)'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- 'matrix(0, 1, -1, 0, 0, 0)', // rotate(90deg)
- 'Animated transform(rotate) style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- 'matrix(1, 0, 0, 1, 0, 0)', // rotate(360deg)
- 'Animated transform(rotate) style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- 'matrix(0, 1, -1, 0, 0, 0)', // rotate(450deg)
- 'Animated transform(rotate) style at 50s of the third iteration');
-}, 'iterationComposite of transform(rotate) animation');
-
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ transform: ['scale(0)', 'scale(1)'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- 'matrix(0.5, 0, 0, 0.5, 0, 0)', // scale(0.5)
- 'Animated transform(scale) style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- 'matrix(0, 0, 0, 0, 0, 0)', // scale(0); scale(1) is an identity element,
- // not accumulated.
- 'Animated transform(scale) style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- 'matrix(0.5, 0, 0, 0.5, 0, 0)', // scale(0.5); scale(1) an identity
- // element, not accumulated.
- 'Animated transform(scale) style at 50s of the third iteration');
-}, 'iterationComposite of transform: [ scale(0), scale(1) ] animation');
-
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ transform: ['scale(1)', 'scale(2)'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- 'matrix(1.5, 0, 0, 1.5, 0, 0)', // scale(1.5)
- 'Animated transform(scale) style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- 'matrix(3, 0, 0, 3, 0, 0)', // scale(1 + (2 -1) + (2 -1))
- 'Animated transform(scale) style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- 'matrix(3.5, 0, 0, 3.5, 0, 0)', // (scale(3) + scale(4)) * 0.5
- 'Animated transform(scale) style at 50s of the third iteration');
-}, 'iterationComposite of transform: [ scale(1), scale(2) ] animation');
-
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ transform: ['scale(0)', 'scale(2)'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- 'matrix(1, 0, 0, 1, 0, 0)', // scale(1)
- 'Animated transform(scale) style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- 'matrix(2, 0, 0, 2, 0, 0)', // (scale(0) + scale(2-1)*2)
- 'Animated transform(scale) style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- 'matrix(3, 0, 0, 3, 0, 0)', // (scale(2) + scale(4)) * 0.5
- 'Animated transform(scale) style at 50s of the third iteration');
-}, 'iterationComposite of transform: scale(2) animation');
-
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ transform: ['rotate(0deg) translateX(0px)',
- 'rotate(180deg) translateX(10px)'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- 'matrix(0, 1, -1, 0, 0, 5)', // rotate(90deg) translateX(5px)
- 'Animated transform list at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- 'matrix(1, 0, 0, 1, 20, 0)', // rotate(360deg) translateX(20px)
- 'Animated transform list at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- 'matrix(0, 1, -1, 0, 0, 25)', // rotate(450deg) translateX(25px)
- 'Animated transform list at 50s of the third iteration');
-}, 'iterationComposite of transform list animation');
-
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ transform: ['matrix(2, 0, 0, 2, 0, 0)',
- 'matrix(3, 0, 0, 3, 30, 0)'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- 'matrix(2.5, 0, 0, 2.5, 15, 0)',
- 'Animated transform of matrix function at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- // scale(2) + (scale(3-1)*2) + translateX(30px)*2
- 'matrix(6, 0, 0, 6, 60, 0)',
- 'Animated transform of matrix function at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- // from: matrix(6, 0, 0, 6, 60, 0)
- // to: matrix(7, 0, 0, 7, 90, 0)
- // = scale(3) + (scale(3-1)*2) + translateX(30px)*3
- 'matrix(6.5, 0, 0, 6.5, 75, 0)',
- 'Animated transform of matrix function at 50s of the third iteration');
-}, 'iterationComposite of transform of matrix function');
-
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ transform: ['translateX(0px) scale(2)',
- 'scale(3) translateX(10px)'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- // Interpolate between matrix(2, 0, 0, 2, 0, 0) = translateX(0px) scale(2)
- // and matrix(3, 0, 0, 3, 30, 0) = scale(3) translateX(10px)
- 'matrix(2.5, 0, 0, 2.5, 15, 0)',
- 'Animated transform list at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- // 'from' and 'to' value are mismatched, so accumulate
- // matrix(2, 0, 0, 2, 0, 0) onto matrix(3, 0, 0, 3, 30, 0) * 2
- // = scale(2) + (scale(3-1)*2) + translateX(30px)*2
- 'matrix(6, 0, 0, 6, 60, 0)',
- 'Animated transform list at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- // Interpolate between matrix(6, 0, 0, 6, 60, 0)
- // and matrix(7, 0, 0, 7, 210, 0) = scale(7) translate(30px)
- 'matrix(6.5, 0, 0, 6.5, 135, 0)',
- 'Animated transform list at 50s of the third iteration');
-}, 'iterationComposite of transform list animation whose order is mismatched');
-
-test(function(t) {
- var div = createDiv(t);
- // Even if each transform list does not have functions which exist in
- // other pair of the list, we don't fill any missing functions at all.
- var anim =
- div.animate({ transform: ['translateX(0px)',
- 'scale(2) translateX(10px)'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- // Interpolate between matrix(1, 0, 0, 1, 0, 0) = translateX(0px)
- // and matrix(2, 0, 0, 2, 20, 0) = scale(2) translateX(10px)
- 'matrix(1.5, 0, 0, 1.5, 10, 0)',
- 'Animated transform list at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- // 'from' and 'to' value are mismatched, so accumulate
- // matrix(1, 0, 0, 1, 0, 0) onto matrix(2, 0, 0, 2, 20, 0) * 2
- // = scale(1) + (scale(2-1)*2) + translateX(20px)*2
- 'matrix(3, 0, 0, 3, 40, 0)',
- 'Animated transform list at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- // Interpolate between matrix(3, 0, 0, 3, 40, 0)
- // and matrix(4, 0, 0, 4, 120, 0) =
- // scale(2 + (2-1)*2) translate(10px * 3)
- 'matrix(3.5, 0, 0, 3.5, 80, 0)',
- 'Animated transform list at 50s of the third iteration');
-}, 'iterationComposite of transform list animation whose order is mismatched ' +
- 'because of missing functions');
-
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ transform: ['none',
- 'translateX(10px)'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- // translateX(none) -> translateX(10px) @ 50%
- 'matrix(1, 0, 0, 1, 5, 0)',
- 'Animated transform list at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- // translateX(10px * 2 + none) -> translateX(10px * 2 + 10px) @ 0%
- 'matrix(1, 0, 0, 1, 20, 0)',
- 'Animated transform list at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- // translateX(10px * 2 + none) -> translateX(10px * 2 + 10px) @ 50%
- 'matrix(1, 0, 0, 1, 25, 0)',
- 'Animated transform list at 50s of the third iteration');
-}, 'iterationComposite of transform from none to translate');
-
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ transform: ['matrix3d(1, 0, 0, 0, ' +
- '0, 1, 0, 0, ' +
- '0, 0, 1, 0, ' +
- '0, 0, 30, 1)',
- 'matrix3d(1, 0, 0, 0, ' +
- '0, 1, 0, 0, ' +
- '0, 0, 1, 0, ' +
- '0, 0, 50, 1)'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 40, 1)',
- 'Animated transform of matrix3d function at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- // translateZ(30px) + (translateZ(50px)*2)
- 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 130, 1)',
- 'Animated transform of matrix3d function at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- // from: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 130, 1)
- // to: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 150, 1)
- 'matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 140, 1)',
- 'Animated transform of matrix3d function at 50s of the third iteration');
-}, 'iterationComposite of transform of matrix3d function');
-
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ transform: ['rotate3d(1, 1, 0, 0deg)',
- 'rotate3d(1, 1, 0, 90deg)'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = 0;
- assert_matrix_equals(getComputedStyle(div).transform,
- 'matrix(1, 0, 0, 1, 0, 0)', // Actually not rotated at all.
- 'Animated transform of rotate3d function at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- rotate3dToMatrix3d(1, 1, 0, Math.PI), // 180deg
- 'Animated transform of rotate3d function at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_matrix_equals(getComputedStyle(div).transform,
- rotate3dToMatrix3d(1, 1, 0, 225 * Math.PI / 180), //((270 + 180) * 0.5)deg
- 'Animated transform of rotate3d function at 50s of the third iteration');
-}, 'iterationComposite of transform of rotate3d function');
-
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ marginLeft: ['10px', '20px'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).marginLeft, '15px',
- 'Animated margin-left style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_equals(getComputedStyle(div).marginLeft, '50px', // 10px + 20px + 20px
- 'Animated margin-left style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).marginLeft, '55px', // (50px + 60px) * 0.5
- 'Animated margin-left style at 50s of the third iteration');
-}, 'iterationComposite starts with non-zero value animation');
-
-test(function(t) {
- var div = createDiv(t);
- var anim =
- div.animate({ marginLeft: ['10px', '-10px'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime = anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).marginLeft,
- '0px',
- 'Animated margin-left style at 50s of the first iteration');
- anim.currentTime = anim.effect.timing.duration * 2;
- assert_equals(getComputedStyle(div).marginLeft,
- '-10px', // 10px + -10px + -10px
- 'Animated margin-left style at 0s of the third iteration');
- anim.currentTime += anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).marginLeft,
- '-20px', // (-10px + -30px) * 0.5
- 'Animated margin-left style at 50s of the third iteration');
-}, 'iterationComposite with negative final value animation');
-
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ marginLeft: ['0px', '10px'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
+test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ marginLeft: ['0px', '10px'] },
+ { duration: 100 * MS_PER_SEC,
+ easing: 'linear',
+ iterations: 10,
+ iterationComposite: 'accumulate' });
anim.pause();
anim.currentTime =
@@ -809,31 +30,6 @@ test(function(t) {
anim.effect.iterationComposite = 'accumulate';
assert_equals(getComputedStyle(div).marginLeft, '25px',
'Animated style at 50s of the third iteration');
-}, 'interationComposite changes');
-
-test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ marginLeft: ['0px', '10px'] },
- { duration: 100 * MS_PER_SEC,
- easing: 'linear',
- iterations: 10,
- iterationComposite: 'accumulate' });
- anim.pause();
-
- anim.currentTime =
- anim.effect.timing.duration * 2 + anim.effect.timing.duration / 2;
- assert_equals(getComputedStyle(div).marginLeft, '25px',
- 'Animated style at 50s of the third iteration');
-
- // double its duration.
- anim.effect.timing.duration = anim.effect.timing.duration * 2;
- assert_equals(getComputedStyle(div).marginLeft, '12.5px',
- 'Animated style at 25s of the first iteration');
-
- // half of original.
- anim.effect.timing.duration = anim.effect.timing.duration / 4;
- assert_equals(getComputedStyle(div).marginLeft, '50px',
- 'Animated style at 50s of the fourth iteration');
-}, 'duration changes with iterationComposite(accumulate)');
+}, 'iterationComposite can be updated while an animation is in progress');
</script>
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001.html b/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001.html
index b20f5193c84..e6c5c2af851 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-001.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>Tests for processing a keyframes argument (property access)</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#processing-a-keyframes-argument">
+<title>Processing a keyframes argument (property access)</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#processing-a-keyframes-argument">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -201,7 +201,7 @@ test(() => {
{ offset: null, computedOffset: 0.5, easing: 'linear', left: '300px' },
{ offset: null, computedOffset: 1, easing: 'linear', left: '200px' },
]);
-}, "'easing' and 'offset' are ignored on iterable objects");
+}, '\'easing\' and \'offset\' are ignored on iterable objects');
test(() => {
const effect = new KeyframeEffect(null, createIterable([
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-002.html b/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-002.html
index c44de912925..8233dc07c5d 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-002.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/processing-a-keyframes-argument-002.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>Tests for processing a keyframes argument (easing)</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#processing-a-keyframes-argument">
+<title>Processing a keyframes argument (easing)</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#processing-a-keyframes-argument">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/setKeyframes.html b/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/setKeyframes.html
index 079e896e69f..90ab89d5761 100644
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/setKeyframes.html
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/setKeyframes.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>KeyframeEffect setKeyframes() tests</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#dom-keyframeeffect-setkeyframes">
+<title>KeyframeEffect.setKeyframes</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#dom-keyframeeffect-setkeyframes">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -13,31 +13,31 @@
<script>
'use strict';
-var target = document.getElementById('target');
+const target = document.getElementById('target');
-test(function(t) {
- gEmptyKeyframeListTests.forEach(function(frame) {
- var effect = new KeyframeEffect(target, {});
+test(t => {
+ for (const frame of gEmptyKeyframeListTests) {
+ const effect = new KeyframeEffect(target, {});
effect.setKeyframes(frame);
assert_frame_lists_equal(effect.getKeyframes(), []);
- });
+ }
}, 'Keyframes can be replaced with an empty keyframe');
-gKeyframesTests.forEach(function(subtest) {
- test(function(t) {
- var effect = new KeyframeEffect(target, {});
+for (const subtest of gKeyframesTests) {
+ test(t => {
+ const effect = new KeyframeEffect(target, {});
effect.setKeyframes(subtest.input);
assert_frame_lists_equal(effect.getKeyframes(), subtest.output);
- }, 'Keyframes can be replaced with ' + subtest.desc);
-});
+ }, `Keyframes can be replaced with ${subtest.desc}`);
+}
-gInvalidKeyframesTests.forEach(function(subtest) {
- test(function(t) {
- var effect = new KeyframeEffect(target, {});
- assert_throws(new TypeError, function() {
+for (const subtest of gInvalidKeyframesTests) {
+ test(t => {
+ const effect = new KeyframeEffect(target, {});
+ assert_throws(new TypeError, () => {
effect.setKeyframes(subtest.input);
});
- }, 'KeyframeEffect constructor throws with ' + subtest.desc);
-});
+ }, `KeyframeEffect constructor throws with ${subtest.desc}`);
+}
</script>
</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/setTarget.html b/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/setTarget.html
deleted file mode 100644
index 49ef8402d90..00000000000
--- a/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/setTarget.html
+++ /dev/null
@@ -1,89 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>Writable effect.target tests</title>
-<link rel="help"
- href="https://w3c.github.io/web-animations/#dom-keyframeeffect-target">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="../../testcommon.js"></script>
-<body>
-<div id="log"></div>
-<script>
-"use strict";
-
-var gKeyFrames = { 'marginLeft': ['0px', '100px'] };
-
-test(function(t) {
- var div = createDiv(t);
- var effect = new KeyframeEffect(null, gKeyFrames, 100 * MS_PER_SEC);
- effect.target = div;
-
- var anim = new Animation(effect, document.timeline);
- anim.play();
-
- anim.currentTime = 50 * MS_PER_SEC;
- assert_equals(getComputedStyle(div).marginLeft, '50px',
- 'Value at 50% progress');
-}, 'Test setting target before constructing the associated animation');
-
-test(function(t) {
- var div = createDiv(t);
- div.style.marginLeft = '10px';
- var effect = new KeyframeEffect(null, gKeyFrames, 100 * MS_PER_SEC);
- var anim = new Animation(effect, document.timeline);
- anim.play();
-
- anim.currentTime = 50 * MS_PER_SEC;
- assert_equals(getComputedStyle(div).marginLeft, '10px',
- 'Value at 50% progress before setting new target');
- effect.target = div;
- assert_equals(getComputedStyle(div).marginLeft, '50px',
- 'Value at 50% progress after setting new target');
-}, 'Test setting target from null to a valid target');
-
-test(function(t) {
- var div = createDiv(t);
- div.style.marginLeft = '10px';
- var anim = div.animate(gKeyFrames, 100 * MS_PER_SEC);
-
- anim.currentTime = 50 * MS_PER_SEC;
- assert_equals(getComputedStyle(div).marginLeft, '50px',
- 'Value at 50% progress before clearing the target')
-
- anim.effect.target = null;
- assert_equals(getComputedStyle(div).marginLeft, '10px',
- 'Value after clearing the target')
-}, 'Test setting target from a valid target to null');
-
-test(function(t) {
- var a = createDiv(t);
- var b = createDiv(t);
- a.style.marginLeft = '10px';
- b.style.marginLeft = '20px';
- var anim = a.animate(gKeyFrames, 100 * MS_PER_SEC);
-
- anim.currentTime = 50 * MS_PER_SEC;
- assert_equals(getComputedStyle(a).marginLeft, '50px',
- 'Value of 1st element (currently targeted) before ' +
- 'changing the effect target');
- assert_equals(getComputedStyle(b).marginLeft, '20px',
- 'Value of 2nd element (currently not targeted) before ' +
- 'changing the effect target');
- anim.effect.target = b;
- assert_equals(getComputedStyle(a).marginLeft, '10px',
- 'Value of 1st element (currently not targeted) after ' +
- 'changing the effect target');
- assert_equals(getComputedStyle(b).marginLeft, '50px',
- 'Value of 2nd element (currently targeted) after ' +
- 'changing the effect target');
-
- // This makes sure the animation property is changed correctly on new
- // targeted element.
- anim.currentTime = 75 * MS_PER_SEC;
- assert_equals(getComputedStyle(b).marginLeft, '75px',
- 'Value of 2nd target (currently targeted) after ' +
- 'changing the animation current time.');
-}, 'Test setting target from a valid target to another target');
-
-</script>
-</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/target.html b/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/target.html
new file mode 100644
index 00000000000..b8fc05b81d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/web-animations/interfaces/KeyframeEffect/target.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>KeyframeEffect.target</title>
+<link rel="help"
+ href="https://drafts.csswg.org/web-animations/#dom-keyframeeffect-target">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+const gKeyFrames = { 'marginLeft': ['0px', '100px'] };
+
+test(t => {
+ const div = createDiv(t);
+ const effect = new KeyframeEffect(null, gKeyFrames, 100 * MS_PER_SEC);
+ effect.target = div;
+
+ const anim = new Animation(effect, document.timeline);
+ anim.play();
+
+ anim.currentTime = 50 * MS_PER_SEC;
+ assert_equals(getComputedStyle(div).marginLeft, '50px',
+ 'Value at 50% progress');
+}, 'Test setting target before constructing the associated animation');
+
+test(t => {
+ const div = createDiv(t);
+ div.style.marginLeft = '10px';
+ const effect = new KeyframeEffect(null, gKeyFrames, 100 * MS_PER_SEC);
+ const anim = new Animation(effect, document.timeline);
+ anim.play();
+
+ anim.currentTime = 50 * MS_PER_SEC;
+ assert_equals(getComputedStyle(div).marginLeft, '10px',
+ 'Value at 50% progress before setting new target');
+ effect.target = div;
+ assert_equals(getComputedStyle(div).marginLeft, '50px',
+ 'Value at 50% progress after setting new target');
+}, 'Test setting target from null to a valid target');
+
+test(t => {
+ const div = createDiv(t);
+ div.style.marginLeft = '10px';
+ const anim = div.animate(gKeyFrames, 100 * MS_PER_SEC);
+
+ anim.currentTime = 50 * MS_PER_SEC;
+ assert_equals(getComputedStyle(div).marginLeft, '50px',
+ 'Value at 50% progress before clearing the target')
+
+ anim.effect.target = null;
+ assert_equals(getComputedStyle(div).marginLeft, '10px',
+ 'Value after clearing the target')
+}, 'Test setting target from a valid target to null');
+
+test(t => {
+ const a = createDiv(t);
+ const b = createDiv(t);
+ a.style.marginLeft = '10px';
+ b.style.marginLeft = '20px';
+ const anim = a.animate(gKeyFrames, 100 * MS_PER_SEC);
+
+ anim.currentTime = 50 * MS_PER_SEC;
+ assert_equals(getComputedStyle(a).marginLeft, '50px',
+ 'Value of 1st element (currently targeted) before ' +
+ 'changing the effect target');
+ assert_equals(getComputedStyle(b).marginLeft, '20px',
+ 'Value of 2nd element (currently not targeted) before ' +
+ 'changing the effect target');
+ anim.effect.target = b;
+ assert_equals(getComputedStyle(a).marginLeft, '10px',
+ 'Value of 1st element (currently not targeted) after ' +
+ 'changing the effect target');
+ assert_equals(getComputedStyle(b).marginLeft, '50px',
+ 'Value of 2nd element (currently targeted) after ' +
+ 'changing the effect target');
+
+ // This makes sure the animation property is changed correctly on new
+ // targeted element.
+ anim.currentTime = 75 * MS_PER_SEC;
+ assert_equals(getComputedStyle(b).marginLeft, '75px',
+ 'Value of 2nd target (currently targeted) after ' +
+ 'changing the animation current time.');
+}, 'Test setting target from a valid target to another target');
+
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/resources/easing-tests.js b/tests/wpt/web-platform-tests/web-animations/resources/easing-tests.js
index f2d7a3ee5d5..fc433853882 100644
--- a/tests/wpt/web-platform-tests/web-animations/resources/easing-tests.js
+++ b/tests/wpt/web-platform-tests/web-animations/resources/easing-tests.js
@@ -1,4 +1,6 @@
-var gEasingTests = [
+'use strict';
+
+const gEasingTests = [
{
desc: 'step-start function',
easing: 'step-start',
diff --git a/tests/wpt/web-platform-tests/web-animations/resources/effect-tests.js b/tests/wpt/web-platform-tests/web-animations/resources/effect-tests.js
index 4a0c66e1f28..8a18ab13c6c 100644
--- a/tests/wpt/web-platform-tests/web-animations/resources/effect-tests.js
+++ b/tests/wpt/web-platform-tests/web-animations/resources/effect-tests.js
@@ -1,3 +1,5 @@
+'use strict';
+
// Common utility methods for testing animation effects
// Tests the |property| member of |animation's| target effect's computed timing
@@ -26,7 +28,7 @@ function assert_computed_timing_for_each_phase(animation, property, values) {
const timing = effect.getComputedTiming();
// The following calculations are based on the definitions here:
- // https://w3c.github.io/web-animations/#animation-effect-phases-and-states
+ // https://drafts.csswg.org/web-animations/#animation-effect-phases-and-states
const beforeActive = Math.max(Math.min(timing.delay, timing.endTime), 0);
const activeAfter =
Math.max(Math.min(timing.delay + timing.activeDuration, timing.endTime), 0);
diff --git a/tests/wpt/web-platform-tests/web-animations/testcommon.js b/tests/wpt/web-platform-tests/web-animations/testcommon.js
index 008d424df1f..51b84dd3e53 100644
--- a/tests/wpt/web-platform-tests/web-animations/testcommon.js
+++ b/tests/wpt/web-platform-tests/web-animations/testcommon.js
@@ -10,19 +10,19 @@ policies and contribution forms [3].
'use strict';
-var MS_PER_SEC = 1000;
+const MS_PER_SEC = 1000;
// The recommended minimum precision to use for time values[1].
//
-// [1] https://w3c.github.io/web-animations/#precision-of-time-values
-var TIME_PRECISION = 0.0005; // ms
+// [1] https://drafts.csswg.org/web-animations/#precision-of-time-values
+const TIME_PRECISION = 0.0005; // ms
// Allow implementations to substitute an alternative method for comparing
// times based on their precision requirements.
if (!window.assert_times_equal) {
- window.assert_times_equal = function(actual, expected, description) {
+ window.assert_times_equal = (actual, expected, description) => {
assert_approx_equals(actual, expected, TIME_PRECISION, description);
- }
+ };
}
// creates div element, appends it to the document body and
@@ -38,9 +38,9 @@ function createElement(test, tagName, doc) {
if (!doc) {
doc = document;
}
- var element = doc.createElement(tagName || 'div');
+ const element = doc.createElement(tagName || 'div');
doc.body.appendChild(element);
- test.add_cleanup(function() {
+ test.add_cleanup(() => {
element.remove();
});
return element;
@@ -61,16 +61,16 @@ function createStyle(test, rules, doc) {
if (!doc) {
doc = document;
}
- var extraStyle = doc.createElement('style');
+ const extraStyle = doc.createElement('style');
doc.head.appendChild(extraStyle);
if (rules) {
- var sheet = extraStyle.sheet;
- for (var selector in rules) {
- sheet.insertRule(selector + '{' + rules[selector] + '}',
+ const sheet = extraStyle.sheet;
+ for (const selector in rules) {
+ sheet.insertRule(`${selector}{${rules[selector]}}`,
sheet.cssRules.length);
}
}
- test.add_cleanup(function() {
+ test.add_cleanup(() => {
extraStyle.remove();
});
}
@@ -78,37 +78,37 @@ function createStyle(test, rules, doc) {
// Create a pseudo element
function createPseudo(test, type) {
createStyle(test, { '@keyframes anim': '',
- ['.pseudo::' + type]: 'animation: anim 10s; ' +
+ [`.pseudo::${type}`]: 'animation: anim 10s; ' +
'content: \'\';' });
- var div = createDiv(test);
+ const div = createDiv(test);
div.classList.add('pseudo');
- var anims = document.getAnimations();
+ const anims = document.getAnimations();
assert_true(anims.length >= 1);
- var anim = anims[anims.length - 1];
+ const anim = anims[anims.length - 1];
assert_equals(anim.effect.target.parentElement, div);
- assert_equals(anim.effect.target.type, '::' + type);
+ assert_equals(anim.effect.target.type, `::${type}`);
anim.cancel();
return anim.effect.target;
}
// Cubic bezier with control points (0, 0), (x1, y1), (x2, y2), and (1, 1).
function cubicBezier(x1, y1, x2, y2) {
- function xForT(t) {
- var omt = 1-t;
+ const xForT = t => {
+ const omt = 1-t;
return 3 * omt * omt * t * x1 + 3 * omt * t * t * x2 + t * t * t;
- }
+ };
- function yForT(t) {
- var omt = 1-t;
+ const yForT = t => {
+ const omt = 1-t;
return 3 * omt * omt * t * y1 + 3 * omt * t * t * y2 + t * t * t;
- }
+ };
- function tForX(x) {
+ const tForX = x => {
// Binary subdivision.
- var mint = 0, maxt = 1;
- for (var i = 0; i < 30; ++i) {
- var guesst = (mint + maxt) / 2;
- var guessx = xForT(guesst);
+ let mint = 0, maxt = 1;
+ for (let i = 0; i < 30; ++i) {
+ const guesst = (mint + maxt) / 2;
+ const guessx = xForT(guesst);
if (x < guessx) {
maxt = guesst;
} else {
@@ -116,9 +116,9 @@ function cubicBezier(x1, y1, x2, y2) {
}
}
return (mint + maxt) / 2;
- }
+ };
- return function bezierClosure(x) {
+ return x => {
if (x == 0) {
return 0;
}
@@ -126,31 +126,29 @@ function cubicBezier(x1, y1, x2, y2) {
return 1;
}
return yForT(tForX(x));
- }
+ };
}
function stepEnd(nsteps) {
- return function stepEndClosure(x) {
- return Math.floor(x * nsteps) / nsteps;
- }
+ return x => Math.floor(x * nsteps) / nsteps;
}
function stepStart(nsteps) {
- return function stepStartClosure(x) {
- var result = Math.floor(x * nsteps + 1.0) / nsteps;
+ return x => {
+ const result = Math.floor(x * nsteps + 1.0) / nsteps;
return (result > 1.0) ? 1.0 : result;
- }
+ };
}
function framesTiming(nframes) {
- return function framesClosure(x) {
- var result = Math.floor(x * nframes) / (nframes - 1);
+ return x => {
+ const result = Math.floor(x * nframes) / (nframes - 1);
return (result > 1.0 && x <= 1.0) ? 1.0 : result;
- }
+ };
}
function waitForAnimationFrames(frameCount) {
- return new Promise(function(resolve, reject) {
+ return new Promise(resolve => {
function handleFrame() {
if (--frameCount <= 0) {
resolve();
@@ -166,8 +164,8 @@ function waitForAnimationFrames(frameCount) {
// as recorded using document.timeline.currentTime (i.e. frame time not
// wall-clock time).
function waitForAnimationFramesWithDelay(minDelay) {
- var startTime = document.timeline.currentTime;
- return new Promise(function(resolve) {
+ const startTime = document.timeline.currentTime;
+ return new Promise(resolve => {
(function handleFrame() {
if (document.timeline.currentTime - startTime >= minDelay) {
resolve();
@@ -178,10 +176,24 @@ function waitForAnimationFramesWithDelay(minDelay) {
});
}
+
+// Waits for a requestAnimationFrame callback in the next refresh driver tick.
+function waitForNextFrame() {
+ const timeAtStart = document.timeline.currentTime;
+ return new Promise(resolve => {
+ window.requestAnimationFrame(() => {
+ if (timeAtStart === document.timeline.currentTime) {
+ window.requestAnimationFrame(resolve);
+ } else {
+ resolve();
+ }
+ });
+ });
+}
+
// Returns 'matrix()' or 'matrix3d()' function string generated from an array.
function createMatrixFromArray(array) {
- return (array.length == 16 ? 'matrix3d' : 'matrix') +
- '(' + array.join() + ')';
+ return (array.length == 16 ? 'matrix3d' : 'matrix') + `(${array.join()})`;
}
// Returns 'matrix3d()' function string equivalent to
@@ -193,11 +205,11 @@ function rotate3dToMatrix3d(x, y, z, radian) {
// Returns an array of the 4x4 matrix equivalent to 'rotate3d(x, y, z, radian)'.
// https://www.w3.org/TR/css-transforms-1/#Rotate3dDefined
function rotate3dToMatrix(x, y, z, radian) {
- var sc = Math.sin(radian / 2) * Math.cos(radian / 2);
- var sq = Math.sin(radian / 2) * Math.sin(radian / 2);
+ const sc = Math.sin(radian / 2) * Math.cos(radian / 2);
+ const sq = Math.sin(radian / 2) * Math.sin(radian / 2);
// Normalize the vector.
- var length = Math.sqrt(x*x + y*y + z*z);
+ const length = Math.sqrt(x*x + y*y + z*z);
x /= length;
y /= length;
z /= length;
@@ -224,21 +236,21 @@ function rotate3dToMatrix(x, y, z, radian) {
// Compare matrix string like 'matrix(1, 0, 0, 1, 100, 0)' with tolerances.
function assert_matrix_equals(actual, expected, description) {
- var matrixRegExp = /^matrix(?:3d)*\((.+)\)/;
+ const matrixRegExp = /^matrix(?:3d)*\((.+)\)/;
assert_regexp_match(actual, matrixRegExp,
'Actual value is not a matrix')
assert_regexp_match(expected, matrixRegExp,
'Expected value is not a matrix');
- var actualMatrixArray =
+ const actualMatrixArray =
actual.match(matrixRegExp)[1].split(',').map(Number);
- var expectedMatrixArray =
+ const expectedMatrixArray =
expected.match(matrixRegExp)[1].split(',').map(Number);
assert_equals(actualMatrixArray.length, expectedMatrixArray.length,
- 'dimension of the matrix: ' + description);
- for (var i = 0; i < actualMatrixArray.length; i++) {
+ `dimension of the matrix: ${description}`);
+ for (let i = 0; i < actualMatrixArray.length; i++) {
assert_approx_equals(actualMatrixArray[i], expectedMatrixArray[i], 0.0001,
- 'expected ' + expected + ' but got ' + actual + ": " + description);
+ `expected ${expected} but got ${actual}: ${description}`);
}
}
diff --git a/tests/wpt/web-platform-tests/web-animations/timing-model/animation-effects/active-time.html b/tests/wpt/web-platform-tests/web-animations/timing-model/animation-effects/active-time.html
index bdaad08edd4..3e3b528d534 100644
--- a/tests/wpt/web-platform-tests/web-animations/timing-model/animation-effects/active-time.html
+++ b/tests/wpt/web-platform-tests/web-animations/timing-model/animation-effects/active-time.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>Active time tests</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#calculating-the-active-time">
+<title>Active time</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#calculating-the-active-time">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -10,110 +10,109 @@
<script>
'use strict';
-test(function(t) {
- var tests = [ { fill: 'none', progress: null },
- { fill: 'backwards', progress: 0 },
- { fill: 'forwards', progress: null },
- { fill: 'both', progress: 0 } ];
- tests.forEach(function(test) {
- var anim = createDiv(t).animate(null, { delay: 1, fill: test.fill });
+test(t => {
+ const tests = [ { fill: 'none', progress: null },
+ { fill: 'backwards', progress: 0 },
+ { fill: 'forwards', progress: null },
+ { fill: 'both', progress: 0 } ];
+ for (const test of tests) {
+ const anim = createDiv(t).animate(null, { delay: 1, fill: test.fill });
assert_equals(anim.effect.getComputedTiming().progress, test.progress,
- 'Progress in before phase when using \'' + test.fill
- + '\' fill');
- });
+ `Progress in before phase when using '${test.fill}' fill`);
+ }
}, 'Active time in before phase');
-test(function(t) {
- var anim = createDiv(t).animate(null, 1000);
+test(t => {
+ const anim = createDiv(t).animate(null, 1000);
anim.currentTime = 500;
assert_times_equal(anim.effect.getComputedTiming().progress, 0.5);
}, 'Active time in active phase and no start delay is the local time');
-test(function(t) {
- var anim = createDiv(t).animate(null, { duration: 1000, delay: 500 });
+test(t => {
+ const anim = createDiv(t).animate(null, { duration: 1000, delay: 500 });
anim.currentTime = 1000;
assert_times_equal(anim.effect.getComputedTiming().progress, 0.5);
}, 'Active time in active phase and positive start delay is the local time'
+ ' minus the start delay');
-test(function(t) {
- var anim = createDiv(t).animate(null, { duration: 1000, delay: -500 });
+test(t => {
+ const anim = createDiv(t).animate(null, { duration: 1000, delay: -500 });
assert_times_equal(anim.effect.getComputedTiming().progress, 0.5);
}, 'Active time in active phase and negative start delay is the local time'
+ ' minus the start delay');
-test(function(t) {
- var anim = createDiv(t).animate(null);
+test(t => {
+ const anim = createDiv(t).animate(null);
assert_equals(anim.effect.getComputedTiming().progress, null);
}, 'Active time in after phase with no fill is unresolved');
-test(function(t) {
- var anim = createDiv(t).animate(null, { fill: 'backwards' });
+test(t => {
+ const anim = createDiv(t).animate(null, { fill: 'backwards' });
assert_equals(anim.effect.getComputedTiming().progress, null);
}, 'Active time in after phase with backwards-only fill is unresolved');
-test(function(t) {
- var anim = createDiv(t).animate(null, { duration: 1000,
- iterations: 2.3,
- delay: 500, // Should have no effect
- fill: 'forwards' });
+test(t => {
+ const anim = createDiv(t).animate(null, { duration: 1000,
+ iterations: 2.3,
+ delay: 500, // Should have no effect
+ fill: 'forwards' });
anim.finish();
assert_equals(anim.effect.getComputedTiming().currentIteration, 2);
assert_times_equal(anim.effect.getComputedTiming().progress, 0.3);
}, 'Active time in after phase with forwards fill is the active duration');
-test(function(t) {
- var anim = createDiv(t).animate(null, { duration: 0,
- iterations: Infinity,
- fill: 'forwards' });
+test(t => {
+ const anim = createDiv(t).animate(null, { duration: 0,
+ iterations: Infinity,
+ fill: 'forwards' });
anim.finish();
assert_equals(anim.effect.getComputedTiming().currentIteration, Infinity);
assert_equals(anim.effect.getComputedTiming().progress, 1);
}, 'Active time in after phase with forwards fill, zero-duration, and '
+ ' infinite iteration count is the active duration');
-test(function(t) {
- var anim = createDiv(t).animate(null, { duration: 1000,
- iterations: 2.3,
- delay: 500,
- endDelay: 4000,
- fill: 'forwards' });
+test(t => {
+ const anim = createDiv(t).animate(null, { duration: 1000,
+ iterations: 2.3,
+ delay: 500,
+ endDelay: 4000,
+ fill: 'forwards' });
anim.finish();
assert_equals(anim.effect.getComputedTiming().currentIteration, 2);
assert_times_equal(anim.effect.getComputedTiming().progress, 0.3);
}, 'Active time in after phase with forwards fill and positive end delay'
+ ' is the active duration');
-test(function(t) {
- var anim = createDiv(t).animate(null, { duration: 1000,
- iterations: 2.3,
- delay: 500,
- endDelay: -800,
- fill: 'forwards' });
+test(t => {
+ const anim = createDiv(t).animate(null, { duration: 1000,
+ iterations: 2.3,
+ delay: 500,
+ endDelay: -800,
+ fill: 'forwards' });
anim.finish();
assert_equals(anim.effect.getComputedTiming().currentIteration, 1);
assert_times_equal(anim.effect.getComputedTiming().progress, 0.5);
}, 'Active time in after phase with forwards fill and negative end delay'
+ ' is the active duration + end delay');
-test(function(t) {
- var anim = createDiv(t).animate(null, { duration: 1000,
- iterations: 2.3,
- delay: 500,
- endDelay: -2500,
- fill: 'forwards' });
+test(t => {
+ const anim = createDiv(t).animate(null, { duration: 1000,
+ iterations: 2.3,
+ delay: 500,
+ endDelay: -2500,
+ fill: 'forwards' });
anim.finish();
assert_equals(anim.effect.getComputedTiming().currentIteration, 0);
assert_equals(anim.effect.getComputedTiming().progress, 0);
}, 'Active time in after phase with forwards fill and negative end delay'
+ ' greater in magnitude than the active duration is zero');
-test(function(t) {
- var anim = createDiv(t).animate(null, { duration: 1000,
- iterations: 2.3,
- delay: 500,
- endDelay: -4000,
- fill: 'forwards' });
+test(t => {
+ const anim = createDiv(t).animate(null, { duration: 1000,
+ iterations: 2.3,
+ delay: 500,
+ endDelay: -4000,
+ fill: 'forwards' });
anim.finish();
assert_equals(anim.effect.getComputedTiming().currentIteration, 0);
assert_equals(anim.effect.getComputedTiming().progress, 0);
@@ -121,20 +120,20 @@ test(function(t) {
+ ' greater in magnitude than the sum of the active duration and start delay'
+ ' is zero');
-test(function(t) {
- var anim = createDiv(t).animate(null, { duration: 1000,
- iterations: 2.3,
- delay: 500,
- fill: 'both' });
+test(t => {
+ const anim = createDiv(t).animate(null, { duration: 1000,
+ iterations: 2.3,
+ delay: 500,
+ fill: 'both' });
anim.finish();
assert_equals(anim.effect.getComputedTiming().currentIteration, 2);
assert_times_equal(anim.effect.getComputedTiming().progress, 0.3);
}, 'Active time in after phase with \'both\' fill is the active duration');
-test(function(t) {
+test(t => {
// Create an effect with a non-zero duration so we ensure we're not just
// testing the after-phase behavior.
- var effect = new KeyframeEffect(null, null, 1);
+ const effect = new KeyframeEffect(null, null, 1);
assert_equals(effect.getComputedTiming().progress, null);
}, 'Active time when the local time is unresolved, is unresolved');
diff --git a/tests/wpt/web-platform-tests/web-animations/timing-model/animation-effects/current-iteration.html b/tests/wpt/web-platform-tests/web-animations/timing-model/animation-effects/current-iteration.html
index df08d435851..24464ce05f5 100644
--- a/tests/wpt/web-platform-tests/web-animations/timing-model/animation-effects/current-iteration.html
+++ b/tests/wpt/web-platform-tests/web-animations/timing-model/animation-effects/current-iteration.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>Current iteration tests</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#current-iteration">
+<title>Current iteration</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#current-iteration">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -38,11 +38,11 @@ function runTests(tests, description) {
}
}
-async_test(function(t) {
- var div = createDiv(t);
- var anim = div.animate({ opacity: [ 0, 1 ] }, { delay: 1 });
+async_test(t => {
+ const div = createDiv(t);
+ const anim = div.animate({ opacity: [ 0, 1 ] }, { delay: 1 });
assert_equals(anim.effect.getComputedTiming().currentIteration, null);
- anim.finished.then(t.step_func(function() {
+ anim.finished.then(t.step_func(() => {
assert_equals(anim.effect.getComputedTiming().currentIteration, null);
t.done();
}));
diff --git a/tests/wpt/web-platform-tests/web-animations/timing-model/animation-effects/local-time.html b/tests/wpt/web-platform-tests/web-animations/timing-model/animation-effects/local-time.html
index 91c1ed401c9..79437d9f542 100644
--- a/tests/wpt/web-platform-tests/web-animations/timing-model/animation-effects/local-time.html
+++ b/tests/wpt/web-platform-tests/web-animations/timing-model/animation-effects/local-time.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>AnimationEffect local time tests</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#local-time">
+<title>Local time</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#local-time">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -9,16 +9,19 @@
<script>
'use strict';
-test(function(t) {
- var anim = createDiv(t).animate(null, 10 * MS_PER_SEC);
- for (var seconds of [-1, 0, 5, 10, 20]) {
+test(t => {
+ const anim = createDiv(t).animate(null, 10 * MS_PER_SEC);
+ for (const seconds of [-1, 0, 5, 10, 20]) {
anim.currentTime = seconds * MS_PER_SEC;
- assert_equals(anim.effect.getComputedTiming().localTime, seconds * MS_PER_SEC);
+ assert_equals(
+ anim.effect.getComputedTiming().localTime,
+ seconds * MS_PER_SEC
+ );
}
}, 'Local time is current time for animation effects associated with an animation');
-test(function(t) {
- var effect = new KeyframeEffect(createDiv(t), null, 10 * MS_PER_SEC);
+test(t => {
+ const effect = new KeyframeEffect(createDiv(t), null, 10 * MS_PER_SEC);
assert_equals(effect.getComputedTiming().localTime, null);
}, 'Local time is unresolved for animation effects not associated with an animation');
diff --git a/tests/wpt/web-platform-tests/web-animations/timing-model/animation-effects/phases-and-states.html b/tests/wpt/web-platform-tests/web-animations/timing-model/animation-effects/phases-and-states.html
index 5dc32066fea..ac3732fe673 100644
--- a/tests/wpt/web-platform-tests/web-animations/timing-model/animation-effects/phases-and-states.html
+++ b/tests/wpt/web-platform-tests/web-animations/timing-model/animation-effects/phases-and-states.html
@@ -1,7 +1,7 @@
<!doctype html>
<meta charset=utf-8>
-<title>Tests for phases and states</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#animation-effect-phases-and-states">
+<title>Phases and states</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#animation-effect-phases-and-states">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -25,7 +25,7 @@ function assert_phase_at_time(animation, phase, currentTime) {
animation.effect.timing.fill = 'none';
assert_not_equals(animation.effect.getComputedTiming().progress, null,
'Animation effect is in active phase when current time'
- + ' is ' + currentTime + 'ms');
+ + ` is ${currentTime}ms`);
} else {
// The easiest way to distinguish between the 'before' phase and the 'after'
// phase is to toggle the fill mode. For example, if the progress is null
@@ -33,157 +33,146 @@ function assert_phase_at_time(animation, phase, currentTime) {
// 'backwards' then we are in the before phase.
animation.effect.timing.fill = 'none';
assert_equals(animation.effect.getComputedTiming().progress, null,
- 'Animation effect is in ' + phase + ' phase when current time'
- + ' is ' + currentTime + 'ms'
+ `Animation effect is in ${phase} phase when current time`
+ + ` is ${currentTime}ms`
+ ' (progress is null with \'none\' fill mode)');
animation.effect.timing.fill = phase === 'before'
? 'backwards'
: 'forwards';
assert_not_equals(animation.effect.getComputedTiming().progress, null,
- 'Animation effect is in ' + phase + ' phase when current'
- + ' time is ' + currentTime + 'ms'
+ `Animation effect is in ${phase} phase when current time`
+ + ` is ${currentTime}ms`
+ ' (progress is non-null with appropriate fill mode)');
}
}
-test(function(t) {
- var animation = createDiv(t).animate(null, 1);
+test(t => {
+ const animation = createDiv(t).animate(null, 1);
- [ { currentTime: -1, phase: 'before' },
- { currentTime: 0, phase: 'active' },
- { currentTime: 1, phase: 'after' } ]
- .forEach(function(test) {
+ for (const test of [{ currentTime: -1, phase: 'before' },
+ { currentTime: 0, phase: 'active' },
+ { currentTime: 1, phase: 'after' }]) {
assert_phase_at_time(animation, test.phase, test.currentTime);
- });
+ }
}, 'Phase calculation for a simple animation effect');
-test(function(t) {
- var animation = createDiv(t).animate(null, { duration: 1, delay: 1 });
+test(t => {
+ const animation = createDiv(t).animate(null, { duration: 1, delay: 1 });
- [ { currentTime: 0, phase: 'before' },
- { currentTime: 1, phase: 'active' },
- { currentTime: 2, phase: 'after' } ]
- .forEach(function(test) {
+ for (const test of [{ currentTime: 0, phase: 'before' },
+ { currentTime: 1, phase: 'active' },
+ { currentTime: 2, phase: 'after' }]) {
assert_phase_at_time(animation, test.phase, test.currentTime);
- });
+ }
}, 'Phase calculation for an animation effect with a positive start delay');
-test(function(t) {
- var animation = createDiv(t).animate(null, { duration: 1, delay: -1 });
+test(t => {
+ const animation = createDiv(t).animate(null, { duration: 1, delay: -1 });
- [ { currentTime: -2, phase: 'before' },
- { currentTime: -1, phase: 'before' },
- { currentTime: 0, phase: 'after' } ]
- .forEach(function(test) {
+ for (const test of [{ currentTime: -2, phase: 'before' },
+ { currentTime: -1, phase: 'before' },
+ { currentTime: 0, phase: 'after' }]) {
assert_phase_at_time(animation, test.phase, test.currentTime);
- });
+ }
}, 'Phase calculation for an animation effect with a negative start delay');
-test(function(t) {
- var animation = createDiv(t).animate(null, { duration: 1, endDelay: 1 });
+test(t => {
+ const animation = createDiv(t).animate(null, { duration: 1, endDelay: 1 });
- [ { currentTime: -1, phase: 'before' },
- { currentTime: 0, phase: 'active' },
- { currentTime: 1, phase: 'after' },
- { currentTime: 2, phase: 'after' } ]
- .forEach(function(test) {
+ for (const test of [{ currentTime: -1, phase: 'before' },
+ { currentTime: 0, phase: 'active' },
+ { currentTime: 1, phase: 'after' },
+ { currentTime: 2, phase: 'after' }]) {
assert_phase_at_time(animation, test.phase, test.currentTime);
- });
+ }
}, 'Phase calculation for an animation effect with a positive end delay');
-test(function(t) {
- var animation = createDiv(t).animate(null, { duration: 2, endDelay: -1 });
+test(t => {
+ const animation = createDiv(t).animate(null, { duration: 2, endDelay: -1 });
- [ { currentTime: -1, phase: 'before' },
- { currentTime: 0, phase: 'active' },
- { currentTime: 0.9, phase: 'active' },
- { currentTime: 1, phase: 'after' } ]
- .forEach(function(test) {
+ for (const test of [{ currentTime: -1, phase: 'before' },
+ { currentTime: 0, phase: 'active' },
+ { currentTime: 0.9, phase: 'active' },
+ { currentTime: 1, phase: 'after' }]) {
assert_phase_at_time(animation, test.phase, test.currentTime);
- });
+ }
}, 'Phase calculation for an animation effect with a negative end delay lesser'
+ ' in magnitude than the active duration');
-test(function(t) {
- var animation = createDiv(t).animate(null, { duration: 1, endDelay: -1 });
+test(t => {
+ const animation = createDiv(t).animate(null, { duration: 1, endDelay: -1 });
- [ { currentTime: -1, phase: 'before' },
- { currentTime: 0, phase: 'after' },
- { currentTime: 1, phase: 'after' } ]
- .forEach(function(test) {
+ for (const test of [{ currentTime: -1, phase: 'before' },
+ { currentTime: 0, phase: 'after' },
+ { currentTime: 1, phase: 'after' }]) {
assert_phase_at_time(animation, test.phase, test.currentTime);
- });
+ }
}, 'Phase calculation for an animation effect with a negative end delay equal'
+ ' in magnitude to the active duration');
-test(function(t) {
- var animation = createDiv(t).animate(null, { duration: 1, endDelay: -2 });
+test(t => {
+ const animation = createDiv(t).animate(null, { duration: 1, endDelay: -2 });
- [ { currentTime: -2, phase: 'before' },
- { currentTime: -1, phase: 'before' },
- { currentTime: 0, phase: 'after' } ]
- .forEach(function(test) {
+ for (const test of [{ currentTime: -2, phase: 'before' },
+ { currentTime: -1, phase: 'before' },
+ { currentTime: 0, phase: 'after' }]) {
assert_phase_at_time(animation, test.phase, test.currentTime);
- });
+ }
}, 'Phase calculation for an animation effect with a negative end delay'
+ ' greater in magnitude than the active duration');
-test(function(t) {
- var animation = createDiv(t).animate(null, { duration: 2,
- delay: 1,
- endDelay: -1 });
+test(t => {
+ const animation = createDiv(t).animate(null, { duration: 2,
+ delay: 1,
+ endDelay: -1 });
- [ { currentTime: 0, phase: 'before' },
- { currentTime: 1, phase: 'active' },
- { currentTime: 2, phase: 'after' } ]
- .forEach(function(test) {
+ for (const test of [{ currentTime: 0, phase: 'before' },
+ { currentTime: 1, phase: 'active' },
+ { currentTime: 2, phase: 'after' }]) {
assert_phase_at_time(animation, test.phase, test.currentTime);
- });
+ }
}, 'Phase calculation for an animation effect with a positive start delay'
+ ' and a negative end delay lesser in magnitude than the active duration');
-test(function(t) {
- var animation = createDiv(t).animate(null, { duration: 1,
- delay: -1,
- endDelay: -1 });
+test(t => {
+ const animation = createDiv(t).animate(null, { duration: 1,
+ delay: -1,
+ endDelay: -1 });
- [ { currentTime: -2, phase: 'before' },
- { currentTime: -1, phase: 'before' },
- { currentTime: 0, phase: 'after' } ]
- .forEach(function(test) {
+ for (const test of [{ currentTime: -2, phase: 'before' },
+ { currentTime: -1, phase: 'before' },
+ { currentTime: 0, phase: 'after' }]) {
assert_phase_at_time(animation, test.phase, test.currentTime);
- });
+ }
}, 'Phase calculation for an animation effect with a negative start delay'
+ ' and a negative end delay equal in magnitude to the active duration');
-test(function(t) {
- var animation = createDiv(t).animate(null, { duration: 1,
- delay: -1,
- endDelay: -2 });
+test(t => {
+ const animation = createDiv(t).animate(null, { duration: 1,
+ delay: -1,
+ endDelay: -2 });
- [ { currentTime: -3, phase: 'before' },
- { currentTime: -2, phase: 'before' },
- { currentTime: -1, phase: 'before' },
- { currentTime: 0, phase: 'after' } ]
- .forEach(function(test) {
+ for (const test of [{ currentTime: -3, phase: 'before' },
+ { currentTime: -2, phase: 'before' },
+ { currentTime: -1, phase: 'before' },
+ { currentTime: 0, phase: 'after' }]) {
assert_phase_at_time(animation, test.phase, test.currentTime);
- });
+ }
}, 'Phase calculation for an animation effect with a negative start delay'
+ ' and a negative end delay equal greater in magnitude than the active'
+ ' duration');
-test(function(t) {
- var animation = createDiv(t).animate(null, 1);
+test(t => {
+ const animation = createDiv(t).animate(null, 1);
animation.playbackRate = -1;
- [ { currentTime: -1, phase: 'before' },
- { currentTime: 0, phase: 'before' },
- { currentTime: 1, phase: 'active' },
- { currentTime: 2, phase: 'after' } ]
- .forEach(function(test) {
+ for (const test of [{ currentTime: -1, phase: 'before' },
+ { currentTime: 0, phase: 'before' },
+ { currentTime: 1, phase: 'active' },
+ { currentTime: 2, phase: 'after' }]) {
assert_phase_at_time(animation, test.phase, test.currentTime);
- });
+ }
}, 'Phase calculation for a simple animation effect with negative playback'
+ ' rate');
diff --git a/tests/wpt/web-platform-tests/web-animations/timing-model/animation-effects/simple-iteration-progress.html b/tests/wpt/web-platform-tests/web-animations/timing-model/animation-effects/simple-iteration-progress.html
index e4253a0bd35..3c42f79a710 100644
--- a/tests/wpt/web-platform-tests/web-animations/timing-model/animation-effects/simple-iteration-progress.html
+++ b/tests/wpt/web-platform-tests/web-animations/timing-model/animation-effects/simple-iteration-progress.html
@@ -1,8 +1,8 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>Simple iteration progress tests</title>
+<title>Simple iteration progress</title>
<link rel="help"
- href="https://w3c.github.io/web-animations/#simple-iteration-progress">
+ href="https://drafts.csswg.org/web-animations/#simple-iteration-progress">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
diff --git a/tests/wpt/web-platform-tests/web-animations/timing-model/animations/canceling-an-animation.html b/tests/wpt/web-platform-tests/web-animations/timing-model/animations/canceling-an-animation.html
index 5aa7de2bb87..69644319a63 100644
--- a/tests/wpt/web-platform-tests/web-animations/timing-model/animations/canceling-an-animation.html
+++ b/tests/wpt/web-platform-tests/web-animations/timing-model/animations/canceling-an-animation.html
@@ -2,16 +2,16 @@
<meta charset=utf-8>
<title>Canceling an animation</title>
<link rel="help"
- href="https://w3c.github.io/web-animations/#canceling-an-animation-section">
+ href="https://drafts.csswg.org/web-animations/#canceling-an-animation-section">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
<body>
<div id="log"></div>
<script>
-"use strict";
+'use strict';
-promise_test(function(t) {
+promise_test(t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
const retPromise = animation.ready.then(() => {
assert_unreached('ready promise was fulfilled');
@@ -26,12 +26,12 @@ promise_test(function(t) {
}, 'A play-pending ready promise should be rejected when the animation is'
+ ' canceled');
-promise_test(function(t) {
+promise_test(t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
return animation.ready.then(() => {
animation.pause();
// Set up listeners on pause-pending ready promise
- var retPromise = animation.ready.then(function() {
+ const retPromise = animation.ready.then(() => {
assert_unreached('ready promise was fulfilled');
}).catch(err => {
assert_equals(err.name, 'AbortError',
@@ -43,20 +43,58 @@ promise_test(function(t) {
}, 'A pause-pending ready promise should be rejected when the animation is'
+ ' canceled');
-promise_test(function(t) {
+promise_test(t => {
const animation = createDiv(t).animate(null);
animation.cancel();
- return animation.ready.then(function(p) {
+ return animation.ready.then(p => {
assert_equals(p, animation);
});
}, 'When an animation is canceled, it should create a resolved Promise');
-test(function(t) {
+test(t => {
const animation = createDiv(t).animate(null);
const promise = animation.ready;
animation.cancel();
assert_not_equals(animation.ready, promise);
}, 'The ready promise should be replaced when the animation is canceled');
+promise_test(t => {
+ const animation = new Animation(
+ new KeyframeEffect(null, null, { duration: 1000 }),
+ null
+ );
+ assert_equals(animation.playState, 'idle',
+ 'The animation should be initially idle');
+
+ animation.finished.then(t.step_func(() => {
+ assert_unreached('Finished promise should not resolve');
+ }), t.step_func(() => {
+ assert_unreached('Finished promise should not reject');
+ }));
+
+ animation.cancel();
+
+ return waitForAnimationFrames(3);
+}, 'The finished promise should NOT be rejected if the animation is already'
+ + ' idle');
+
+promise_test(t => {
+ const animation = new Animation(
+ new KeyframeEffect(null, null, { duration: 1000 }),
+ null
+ );
+ assert_equals(animation.playState, 'idle',
+ 'The animation should be initially idle');
+
+ animation.oncancel = t.step_func(() => {
+ assert_unreached('Cancel event should not be fired');
+ });
+
+ animation.cancel();
+
+ return waitForAnimationFrames(3);
+}, 'The cancel event should NOT be fired if the animation is already'
+ + ' idle');
+
</script>
</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/timing-model/animations/current-time.html b/tests/wpt/web-platform-tests/web-animations/timing-model/animations/current-time.html
index 7500175435c..d2f5075d1b2 100644
--- a/tests/wpt/web-platform-tests/web-animations/timing-model/animations/current-time.html
+++ b/tests/wpt/web-platform-tests/web-animations/timing-model/animations/current-time.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>Tests for current time</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#current-time">
+<title>Current time</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#current-time">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -10,8 +10,8 @@
<script>
'use strict';
-test(function(t) {
- var animation =
+test(t => {
+ const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
document.timeline);
@@ -21,12 +21,12 @@ test(function(t) {
'state');
}, 'The current time returns the hold time when set');
-promise_test(function(t) {
- var animation =
+promise_test(t => {
+ const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
null);
- return animation.ready.then(function() {
+ return animation.ready.then(() => {
assert_equals(animation.currentTime, null);
});
}, 'The current time is unresolved when there is no associated timeline ' +
@@ -35,8 +35,8 @@ promise_test(function(t) {
// FIXME: Test that the current time is unresolved when we have an inactive
// timeline if we find a way of creating an inactive timeline!
-test(function(t) {
- var animation =
+test(t => {
+ const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
document.timeline);
@@ -45,30 +45,29 @@ test(function(t) {
}, 'The current time is unresolved when the start time is unresolved ' +
'(and no hold time is set)');
-test(function(t) {
- var animation =
+test(t => {
+ const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
document.timeline);
animation.playbackRate = 2;
animation.startTime = document.timeline.currentTime - 25 * MS_PER_SEC;
- var timelineTime = document.timeline.currentTime;
- var startTime = animation.startTime;
- var playbackRate = animation.playbackRate;
+ const timelineTime = document.timeline.currentTime;
+ const startTime = animation.startTime;
+ const playbackRate = animation.playbackRate;
assert_times_equal(animation.currentTime,
(timelineTime - startTime) * playbackRate,
'Animation has a unresolved start time');
}, 'The current time is calculated from the timeline time, start time and ' +
'playback rate');
-promise_test(function(t) {
- var animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
+promise_test(t => {
+ const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
animation.playbackRate = 0;
- return animation.ready.then(function() {
- return waitForAnimationFrames(1);
- }).then(function() {
+ return animation.ready.then(() => waitForAnimationFrames(1))
+ .then(() => {
assert_times_equal(animation.currentTime, 0);
});
}, 'The current time does not progress if playback rate is 0');
diff --git a/tests/wpt/web-platform-tests/web-animations/timing-model/animations/finishing-an-animation.html b/tests/wpt/web-platform-tests/web-animations/timing-model/animations/finishing-an-animation.html
index 4890bd1bde8..7fde3c4db5e 100644
--- a/tests/wpt/web-platform-tests/web-animations/timing-model/animations/finishing-an-animation.html
+++ b/tests/wpt/web-platform-tests/web-animations/timing-model/animations/finishing-an-animation.html
@@ -2,7 +2,7 @@
<meta charset=utf-8>
<title>Finishing an animation</title>
<link rel="help"
- href="https://w3c.github.io/web-animations/#finishing-an-animation-section">
+ href="https://drafts.csswg.org/web-animations/#finishing-an-animation-section">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -11,7 +11,7 @@
<script>
'use strict';
-promise_test(function(t) {
+promise_test(t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
const promise = animation.ready;
let readyResolved = false;
diff --git a/tests/wpt/web-platform-tests/web-animations/timing-model/animations/pausing-an-animation.html b/tests/wpt/web-platform-tests/web-animations/timing-model/animations/pausing-an-animation.html
index 9a4da2e7c2f..f04ec1a904b 100644
--- a/tests/wpt/web-platform-tests/web-animations/timing-model/animations/pausing-an-animation.html
+++ b/tests/wpt/web-platform-tests/web-animations/timing-model/animations/pausing-an-animation.html
@@ -2,7 +2,7 @@
<meta charset=utf-8>
<title>Pausing an animation</title>
<link rel="help"
- href="https://w3c.github.io/web-animations/#finishing-an-animation-section">
+ href="https://drafts.csswg.org/web-animations/#pausing-an-animation-section">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -11,14 +11,14 @@
<script>
'use strict';
-promise_test(function(t) {
+promise_test(t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
const promise = animation.ready;
animation.pause();
return promise.then(p => {
assert_equals(p, animation);
assert_equals(animation.ready, promise);
- assert_equals(animation.playState, 'paused');
+ assert_false(animation.pending, 'No longer pause-pending');
});
}, 'A pending ready promise should be resolved and not replaced when the'
+ ' animation is paused');
diff --git a/tests/wpt/web-platform-tests/web-animations/timing-model/animations/play-states.html b/tests/wpt/web-platform-tests/web-animations/timing-model/animations/play-states.html
new file mode 100644
index 00000000000..49b26382ec7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/web-animations/timing-model/animations/play-states.html
@@ -0,0 +1,157 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Play states</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#play-state">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+test(t => {
+ const animation = new Animation(
+ new KeyframeEffect(null, {}, 100 * MS_PER_SEC)
+ );
+ assert_equals(animation.currentTime, null,
+ 'Current time should be initially unresolved');
+
+ assert_equals(animation.playState, 'idle');
+}, 'reports \'idle\' for an animation with an unresolved current time'
+ + ' and no pending tasks')
+
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
+
+ animation.pause();
+
+ assert_equals(animation.playState, 'paused');
+}, 'reports \'paused\' for an animation with a pending pause task');
+
+test(t => {
+ const animation = new Animation(
+ new KeyframeEffect(null, {}, 100 * MS_PER_SEC)
+ );
+
+ animation.currentTime = 0;
+ assert_equals(animation.startTime, null,
+ 'Start time should still be unresolved after setting current'
+ + ' time');
+
+ assert_equals(animation.playState, 'paused');
+}, 'reports \'paused\' for an animation with a resolved current time and'
+ + ' unresolved start time')
+
+test(t => {
+ const animation = new Animation(
+ new KeyframeEffect(null, {}, 100 * MS_PER_SEC)
+ );
+
+ animation.startTime = document.timeline.currentTime;
+ assert_not_equals(animation.currentTime, null,
+ 'Current time should be resolved after setting start time');
+
+ assert_equals(animation.playState, 'running');
+}, 'reports \'running\' for an animation with a resolved start time and'
+ + ' current time');
+
+test(t => {
+ const animation = new Animation(
+ new KeyframeEffect(null, {}, 100 * MS_PER_SEC)
+ );
+ animation.startTime = document.timeline.currentTime;
+
+ animation.currentTime = 100 * MS_PER_SEC;
+
+ assert_equals(animation.playState, 'finished');
+}, 'reports \'finished\' when playback rate > 0 and'
+ + ' current time = target effect end');
+
+test(t => {
+ const animation = new Animation(
+ new KeyframeEffect(null, {}, 100 * MS_PER_SEC)
+ );
+ animation.startTime = document.timeline.currentTime;
+
+ animation.playbackRate = 0;
+ animation.currentTime = 100 * MS_PER_SEC;
+
+ assert_equals(animation.playState, 'running');
+}, 'reports \'running\' when playback rate = 0 and'
+ + ' current time = target effect end');
+
+test(t => {
+ const animation = new Animation(
+ new KeyframeEffect(null, {}, 100 * MS_PER_SEC)
+ );
+ animation.startTime = document.timeline.currentTime;
+
+ animation.playbackRate = -1;
+ animation.currentTime = 100 * MS_PER_SEC;
+
+ assert_equals(animation.playState, 'running');
+}, 'reports \'running\' when playback rate < 0 and'
+ + ' current time = target effect end');
+
+test(t => {
+ const animation = new Animation(
+ new KeyframeEffect(null, {}, 100 * MS_PER_SEC)
+ );
+ animation.startTime = document.timeline.currentTime;
+
+ animation.currentTime = 0;
+
+ assert_equals(animation.playState, 'running');
+}, 'reports \'running\' when playback rate > 0 and'
+ + ' current time = 0');
+
+test(t => {
+ const animation = new Animation(
+ new KeyframeEffect(null, {}, 100 * MS_PER_SEC)
+ );
+ animation.startTime = document.timeline.currentTime;
+
+ animation.playbackRate = 0;
+ animation.currentTime = 0;
+
+ assert_equals(animation.playState, 'running');
+}, 'reports \'running\' when playback rate = 0 and'
+ + ' current time = 0');
+
+test(t => {
+ const animation = new Animation(
+ new KeyframeEffect(null, {}, 100 * MS_PER_SEC)
+ );
+ animation.startTime = document.timeline.currentTime;
+
+ animation.playbackRate = -1;
+ animation.currentTime = 0;
+
+ assert_equals(animation.playState, 'finished');
+}, 'reports \'finished\' when playback rate < 0 and'
+ + ' current time = 0');
+
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 0);
+ assert_equals(animation.startTime, null,
+ 'Sanity check: start time should be unresolved');
+
+ assert_equals(animation.playState, 'finished');
+}, 'reports \'finished\' when playback rate > 0 and'
+ + ' current time = target effect end and there is a pending play task');
+
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
+ assert_equals(animation.startTime, null,
+ 'Sanity check: start time should be unresolved');
+
+ assert_equals(animation.playState, 'running');
+}, 'reports \'running\' when playback rate > 0 and'
+ + ' current time < target effect end and there is a pending play task');
+
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/timing-model/animations/playing-an-animation.html b/tests/wpt/web-platform-tests/web-animations/timing-model/animations/playing-an-animation.html
index 1cf109deb15..2beed475e7e 100644
--- a/tests/wpt/web-platform-tests/web-animations/timing-model/animations/playing-an-animation.html
+++ b/tests/wpt/web-platform-tests/web-animations/timing-model/animations/playing-an-animation.html
@@ -2,7 +2,7 @@
<meta charset=utf-8>
<title>Playing an animation</title>
<link rel="help"
- href="https://w3c.github.io/web-animations/#playing-an-animation-section">
+ href="https://drafts.csswg.org/web-animations/#playing-an-animation-section">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -11,24 +11,24 @@
<script>
'use strict';
-test(function(t) {
- var animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
+test(t => {
+ const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
animation.currentTime = 1 * MS_PER_SEC;
assert_times_equal(animation.currentTime, 1 * MS_PER_SEC);
animation.play();
assert_times_equal(animation.currentTime, 1 * MS_PER_SEC);
}, 'Playing a running animation leaves the current time unchanged');
-test(function(t) {
- var animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
+test(t => {
+ const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
animation.finish();
assert_times_equal(animation.currentTime, 100 * MS_PER_SEC);
animation.play();
assert_times_equal(animation.currentTime, 0);
}, 'Playing a finished animation seeks back to the start');
-test(function(t) {
- var animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
+test(t => {
+ const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
animation.playbackRate = -1;
animation.currentTime = 0;
assert_times_equal(animation.currentTime, 0);
@@ -36,7 +36,7 @@ test(function(t) {
assert_times_equal(animation.currentTime, 100 * MS_PER_SEC);
}, 'Playing a finished and reversed animation seeks to end');
-test(function(t) {
+test(t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
animation.cancel();
const promise = animation.ready;
@@ -45,7 +45,7 @@ test(function(t) {
}, 'The ready promise should be replaced if the animation is not already'
+ ' pending');
-promise_test(function(t) {
+promise_test(t => {
const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
const promise = animation.ready;
return promise.then(p => {
diff --git a/tests/wpt/web-platform-tests/web-animations/timing-model/animations/reversing-an-animation.html b/tests/wpt/web-platform-tests/web-animations/timing-model/animations/reversing-an-animation.html
index 42093c9c98d..2d5d4e5d0f8 100644
--- a/tests/wpt/web-platform-tests/web-animations/timing-model/animations/reversing-an-animation.html
+++ b/tests/wpt/web-platform-tests/web-animations/timing-model/animations/reversing-an-animation.html
@@ -1,53 +1,53 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>Reversing an animation</title>
+<title>Reverse an animation</title>
<link rel="help"
- href="https://w3c.github.io/web-animations/#reverse-an-animation">
+ href="https://drafts.csswg.org/web-animations/#reverse-an-animation">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
<body>
<div id="log"></div>
<script>
-"use strict";
+'use strict';
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, {duration: 100 * MS_PER_SEC,
- iterations: Infinity});
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, { duration: 100 * MS_PER_SEC,
+ iterations: Infinity });
// Wait a frame because if currentTime is still 0 when we call
// reverse(), it will throw (per spec).
- return animation.ready.then(waitForAnimationFrames(1)).then(function() {
+ return animation.ready.then(waitForAnimationFrames(1)).then(() => {
assert_greater_than_equal(animation.currentTime, 0,
'currentTime expected to be greater than 0, one frame after starting');
animation.currentTime = 50 * MS_PER_SEC;
- var previousPlaybackRate = animation.playbackRate;
+ const previousPlaybackRate = animation.playbackRate;
animation.reverse();
assert_equals(animation.playbackRate, -previousPlaybackRate,
'playbackRate should be inverted');
});
}, 'Reversing an animation inverts the playback rate');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, {duration: 100 * MS_PER_SEC,
- iterations: Infinity});
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, { duration: 100 * MS_PER_SEC,
+ iterations: Infinity });
animation.currentTime = 50 * MS_PER_SEC;
animation.pause();
- return animation.ready.then(function() {
+ return animation.ready.then(() => {
animation.reverse();
return animation.ready;
- }).then(function() {
+ }).then(() => {
assert_equals(animation.playState, 'running',
'Animation.playState should be "running" after reverse()');
});
}, 'Reversing an animation plays a pausing animation');
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
animation.currentTime = 50 * MS_PER_SEC;
animation.reverse();
@@ -56,24 +56,24 @@ test(function(t) {
'the animation duration');
}, 'Reversing an animation maintains the same current time');
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, { duration: 200 * MS_PER_SEC,
- delay: -100 * MS_PER_SEC });
- assert_equals(animation.playState, 'pending',
- 'The playState is pending before we call reverse');
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, { duration: 200 * MS_PER_SEC,
+ delay: -100 * MS_PER_SEC });
+ assert_true(animation.pending,
+ 'The animation is pending before we call reverse');
animation.reverse();
- assert_equals(animation.playState, 'pending',
- 'The playState is still pending after calling reverse');
+ assert_true(animation.pending,
+ 'The animation is still pending after calling reverse');
}, 'Reversing an animation does not cause it to leave the pending state');
-promise_test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, { duration: 200 * MS_PER_SEC,
- delay: -100 * MS_PER_SEC });
- var readyResolved = false;
+promise_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, { duration: 200 * MS_PER_SEC,
+ delay: -100 * MS_PER_SEC });
+ let readyResolved = false;
animation.ready.then(() => { readyResolved = true; });
animation.reverse();
@@ -84,9 +84,9 @@ promise_test(function(t) {
});
}, 'Reversing an animation does not cause it to resolve the ready promise');
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
animation.currentTime = 200 * MS_PER_SEC;
animation.reverse();
@@ -96,9 +96,9 @@ test(function(t) {
}, 'Reversing an animation when playbackRate > 0 and currentTime > ' +
'effect end should make it play from the end');
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
animation.currentTime = -200 * MS_PER_SEC;
animation.reverse();
@@ -109,9 +109,9 @@ test(function(t) {
}, 'Reversing an animation when playbackRate > 0 and currentTime < 0 ' +
'should make it play from the end');
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
animation.playbackRate = -1;
animation.currentTime = -200 * MS_PER_SEC;
animation.reverse();
@@ -122,9 +122,9 @@ test(function(t) {
}, 'Reversing an animation when playbackRate < 0 and currentTime < 0 ' +
'should make it play from the start');
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
animation.playbackRate = -1;
animation.currentTime = 200 * MS_PER_SEC;
animation.reverse();
@@ -135,23 +135,23 @@ test(function(t) {
}, 'Reversing an animation when playbackRate < 0 and currentTime > effect ' +
'end should make it play from the start');
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, {duration: 100 * MS_PER_SEC,
- iterations: Infinity});
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, { duration: 100 * MS_PER_SEC,
+ iterations: Infinity });
animation.currentTime = -200 * MS_PER_SEC;
assert_throws('InvalidStateError',
- function () { animation.reverse(); },
+ () => { animation.reverse(); },
'reverse() should throw InvalidStateError ' +
'if the playbackRate > 0 and the currentTime < 0 ' +
'and the target effect is positive infinity');
}, 'Reversing an animation when playbackRate > 0 and currentTime < 0 ' +
'and the target effect end is positive infinity should throw an exception');
-test(function(t) {
- var animation = createDiv(t).animate({}, { duration: 100 * MS_PER_SEC,
- iterations: Infinity });
+test(t => {
+ const animation = createDiv(t).animate({}, { duration: 100 * MS_PER_SEC,
+ iterations: Infinity });
animation.currentTime = -200 * MS_PER_SEC;
try { animation.reverse(); } catch(e) { }
@@ -159,10 +159,10 @@ test(function(t) {
assert_equals(animation.playbackRate, 1, 'playbackRate remains unchanged');
}, 'When reversing throws an exception, the playback rate remains unchanged');
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, {duration: 100 * MS_PER_SEC,
- iterations: Infinity});
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, { duration: 100 * MS_PER_SEC,
+ iterations: Infinity });
animation.currentTime = -200 * MS_PER_SEC;
animation.playbackRate = 0;
@@ -175,10 +175,10 @@ test(function(t) {
'and the target effect end is positive infinity should NOT throw an ' +
'exception');
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, {duration: 100 * MS_PER_SEC,
- iterations: Infinity});
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, { duration: 100 * MS_PER_SEC,
+ iterations: Infinity });
animation.playbackRate = -1;
animation.currentTime = -200 * MS_PER_SEC;
animation.reverse();
@@ -191,9 +191,9 @@ test(function(t) {
'and the target effect end is positive infinity should make it play ' +
'from the start');
-test(function(t) {
- var div = createDiv(t);
- var animation = div.animate({}, 100 * MS_PER_SEC);
+test(t => {
+ const div = createDiv(t);
+ const animation = div.animate({}, 100 * MS_PER_SEC);
animation.playbackRate = 0;
animation.currentTime = 50 * MS_PER_SEC;
animation.reverse();
@@ -206,12 +206,12 @@ test(function(t) {
}, 'Reversing when when playbackRate == 0 should preserve the current ' +
'time and playback rate');
-test(function(t) {
- var div = createDiv(t);
- var animation =
+test(t => {
+ const div = createDiv(t);
+ const animation =
new Animation(new KeyframeEffect(div, null, 100 * MS_PER_SEC), null);
- assert_throws('InvalidStateError', function() { animation.reverse(); });
+ assert_throws('InvalidStateError', () => { animation.reverse(); });
}, 'Reversing an animation without an active timeline throws an ' +
'InvalidStateError');
diff --git a/tests/wpt/web-platform-tests/web-animations/timing-model/animations/set-the-animation-start-time.html b/tests/wpt/web-platform-tests/web-animations/timing-model/animations/set-the-animation-start-time.html
index 8b74c92a469..1526be05766 100644
--- a/tests/wpt/web-platform-tests/web-animations/timing-model/animations/set-the-animation-start-time.html
+++ b/tests/wpt/web-platform-tests/web-animations/timing-model/animations/set-the-animation-start-time.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>Setting the start time tests</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#set-the-animation-start-time">
+<title>Set the animation start time</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#set-the-animation-start-time">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -10,12 +10,11 @@
<script>
'use strict';
-test(function(t)
-{
+test(t => {
// It should only be possible to set *either* the start time or the current
// time for an animation that does not have an active timeline.
- var animation =
+ const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
null);
@@ -41,12 +40,11 @@ test(function(t)
}, 'Setting the start time of an animation without an active timeline');
-test(function(t)
-{
+test(t => {
// Setting an unresolved start time on an animation without an active
// timeline should not clear the current time.
- var animation =
+ const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
null);
@@ -66,9 +64,8 @@ test(function(t)
}, 'Setting an unresolved start time an animation without an active timeline'
+ ' does not clear the current time');
-test(function(t)
-{
- var animation =
+ test(t => {
+ const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
document.timeline);
@@ -93,9 +90,8 @@ test(function(t)
+ ' start time');
}, 'Setting the start time clears the hold time');
-test(function(t)
-{
- var animation =
+test(t => {
+ const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
document.timeline);
@@ -115,21 +111,20 @@ test(function(t)
+ ' start time');
}, 'Setting an unresolved start time sets the hold time');
-promise_test(function(t)
-{
- var animation =
+promise_test(t => {
+ const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
document.timeline);
- var readyPromiseCallbackCalled = false;
- animation.ready.then(function() { readyPromiseCallbackCalled = true; } );
+ let readyPromiseCallbackCalled = false;
+ animation.ready.then(() => { readyPromiseCallbackCalled = true; } );
// Put the animation in the play-pending state
animation.play();
// Sanity check
- assert_equals(animation.playState, 'pending',
- 'Animation is in play-pending state');
+ assert_true(animation.pending && animation.playState === 'running',
+ 'Animation is in play-pending state');
// Setting the start time should resolve the 'ready' promise, i.e.
// it should schedule a microtask to run the promise callbacks.
@@ -139,28 +134,27 @@ promise_test(function(t)
// If we schedule another microtask then it should run immediately after
// the ready promise resolution microtask.
- return Promise.resolve().then(function() {
+ return Promise.resolve().then(() => {
assert_true(readyPromiseCallbackCalled,
'Ready promise callback called after setting startTime');
});
}, 'Setting the start time resolves a pending ready promise');
-promise_test(function(t)
-{
- var animation =
+promise_test(t => {
+ const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
document.timeline);
- var readyPromiseCallbackCalled = false;
- animation.ready.then(function() { readyPromiseCallbackCalled = true; } );
+ let readyPromiseCallbackCalled = false;
+ animation.ready.then(() => { readyPromiseCallbackCalled = true; } );
// Put the animation in the pause-pending state
animation.startTime = document.timeline.currentTime;
animation.pause();
// Sanity check
- assert_equals(animation.playState, 'pending',
- 'Animation is in pause-pending state');
+ assert_true(animation.pending && animation.playState === 'paused',
+ 'Animation is in pause-pending state');
// Setting the start time should resolve the 'ready' promise although
// the resolution callbacks when be run in a separate microtask.
@@ -168,15 +162,14 @@ promise_test(function(t)
assert_false(readyPromiseCallbackCalled,
'Ready promise callback is not called synchronously');
- return Promise.resolve().then(function() {
+ return Promise.resolve().then(() => {
assert_true(readyPromiseCallbackCalled,
'Ready promise callback called after setting startTime');
});
}, 'Setting the start time resolves a pending pause task');
-promise_test(function(t)
-{
- var animation =
+promise_test(t => {
+ const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
document.timeline);
@@ -195,8 +188,8 @@ promise_test(function(t)
// Furthermore, that time should persist if we have correctly updated
// the hold time
- var finishedCurrentTime = animation.currentTime;
- return waitForAnimationFrames(1).then(function() {
+ const finishedCurrentTime = animation.currentTime;
+ return waitForAnimationFrames(1).then(() => {
assert_equals(animation.currentTime, finishedCurrentTime,
'Current time does not change after seeking past the effect'
+ ' end time by setting the current time');
diff --git a/tests/wpt/web-platform-tests/web-animations/timing-model/animations/set-the-target-effect-of-an-animation.html b/tests/wpt/web-platform-tests/web-animations/timing-model/animations/set-the-target-effect-of-an-animation.html
index 4c51f0141c3..b416bda5568 100644
--- a/tests/wpt/web-platform-tests/web-animations/timing-model/animations/set-the-target-effect-of-an-animation.html
+++ b/tests/wpt/web-platform-tests/web-animations/timing-model/animations/set-the-target-effect-of-an-animation.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>Setting the target effect tests</title>
-<link rel='help' href='https://w3c.github.io/web-animations/#setting-the-target-effect'>
+<title>Setting the target effect</title>
+<link rel='help' href='https://drafts.csswg.org/web-animations/#setting-the-target-effect'>
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
<script src='../../testcommon.js'></script>
@@ -10,63 +10,67 @@
<script>
'use strict';
-promise_test(function(t) {
- var anim = createDiv(t).animate({ marginLeft: [ '0px', '100px' ] },
- 100 * MS_PER_SEC);
- assert_equals(anim.playState, 'pending');
+promise_test(t => {
+ const anim = createDiv(t).animate({ marginLeft: [ '0px', '100px' ] },
+ 100 * MS_PER_SEC);
+ assert_true(anim.pending);
- var retPromise = anim.ready.then(function() {
+ const retPromise = anim.ready.then(() => {
assert_unreached('ready promise is fulfilled');
- }).catch(function(err) {
+ }).catch(err => {
assert_equals(err.name, 'AbortError',
'ready promise is rejected with AbortError');
});
anim.effect = null;
+ // This is a bit odd, see: https://github.com/w3c/web-animations/issues/207
assert_equals(anim.playState, 'paused');
+ assert_false(anim.pending);
return retPromise;
}, 'If new effect is null and old effect is not null, we reset the pending ' +
'tasks and ready promise is rejected');
-promise_test(function(t) {
- var anim = new Animation();
+promise_test(t => {
+ const anim = new Animation();
anim.pause();
- assert_equals(anim.playState, 'pending');
+ assert_true(anim.pending);
anim.effect = new KeyframeEffectReadOnly(createDiv(t),
{ marginLeft: [ '0px', '100px' ] },
100 * MS_PER_SEC);
- assert_equals(anim.playState, 'pending');
+ assert_true(anim.pending);
- return anim.ready.then(function() {
+ return anim.ready.then(() => {
+ assert_false(anim.pending);
assert_equals(anim.playState, 'paused');
});
}, 'If animation has a pending pause task, reschedule that task to run ' +
'as soon as animation is ready.');
-promise_test(function(t) {
- var anim = new Animation();
+promise_test(t => {
+ const anim = new Animation();
anim.play();
- assert_equals(anim.playState, 'pending');
+ assert_true(anim.pending);
anim.effect = new KeyframeEffectReadOnly(createDiv(t),
{ marginLeft: [ '0px', '100px' ] },
100 * MS_PER_SEC);
- assert_equals(anim.playState, 'pending');
+ assert_true(anim.pending);
- return anim.ready.then(function() {
+ return anim.ready.then(() => {
+ assert_false(anim.pending);
assert_equals(anim.playState, 'running');
});
}, 'If animation has a pending play task, reschedule that task to run ' +
'as soon as animation is ready to play new effect.');
-promise_test(function(t) {
- var animA = createDiv(t).animate({ marginLeft: [ '0px', '100px' ] },
- 100 * MS_PER_SEC);
- var animB = new Animation();
+promise_test(t => {
+ const animA = createDiv(t).animate({ marginLeft: [ '0px', '100px' ] },
+ 100 * MS_PER_SEC);
+ const animB = new Animation();
- return animA.ready.then(function() {
+ return animA.ready.then(() => {
animB.effect = animA.effect;
assert_equals(animA.effect, null);
assert_equals(animA.playState, 'finished');
@@ -74,11 +78,11 @@ promise_test(function(t) {
}, 'When setting the effect of an animation to the effect of an existing ' +
'animation, the existing animation\'s target effect should be set to null.');
-test(function(t) {
- var animA = createDiv(t).animate({ marginLeft: [ '0px', '100px' ] },
- 100 * MS_PER_SEC);
- var animB = new Animation();
- var effect = animA.effect;
+test(t => {
+ const animA = createDiv(t).animate({ marginLeft: [ '0px', '100px' ] },
+ 100 * MS_PER_SEC);
+ const animB = new Animation();
+ const effect = animA.effect;
animA.currentTime = 50 * MS_PER_SEC;
animB.currentTime = 20 * MS_PER_SEC;
assert_equals(effect.getComputedTiming().progress, 0.5,
diff --git a/tests/wpt/web-platform-tests/web-animations/timing-model/animations/set-the-timeline-of-an-animation.html b/tests/wpt/web-platform-tests/web-animations/timing-model/animations/set-the-timeline-of-an-animation.html
index c540fe2ca71..8a4421309b9 100644
--- a/tests/wpt/web-platform-tests/web-animations/timing-model/animations/set-the-timeline-of-an-animation.html
+++ b/tests/wpt/web-platform-tests/web-animations/timing-model/animations/set-the-timeline-of-an-animation.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>Setting the timeline tests</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#setting-the-timeline">
+<title>Setting the timeline</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#setting-the-timeline">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -16,8 +16,8 @@
//
// ---------------------------------------------------------------------
-test(function(t) {
- var animation =
+test(t => {
+ const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
null);
animation.currentTime = 50 * MS_PER_SEC;
@@ -29,8 +29,8 @@ test(function(t) {
assert_times_equal(animation.currentTime, 50 * MS_PER_SEC);
}, 'After setting timeline on paused animation it is still paused');
-test(function(t) {
- var animation =
+test(t => {
+ const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
null);
animation.currentTime = 200 * MS_PER_SEC;
@@ -43,8 +43,8 @@ test(function(t) {
}, 'After setting timeline on animation paused outside active interval'
+ ' it is still paused');
-test(function(t) {
- var animation =
+test(t => {
+ const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
null);
assert_equals(animation.playState, 'idle');
@@ -55,8 +55,8 @@ test(function(t) {
}, 'After setting timeline on an idle animation without a start time'
+ ' it is still idle');
-test(function(t) {
- var animation =
+test(t => {
+ const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
null);
animation.startTime = document.timeline.currentTime;
@@ -68,8 +68,8 @@ test(function(t) {
}, 'After setting timeline on an idle animation with a start time'
+ ' it is running');
-test(function(t) {
- var animation =
+test(t => {
+ const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
null);
animation.startTime = document.timeline.currentTime - 200 * MS_PER_SEC;
@@ -81,60 +81,44 @@ test(function(t) {
}, 'After setting timeline on an idle animation with a sufficiently ancient'
+ ' start time it is finished');
-test(function(t) {
- var animation =
+promise_test(t => {
+ const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
null);
animation.play();
- assert_equals(animation.playState, 'pending');
+ assert_true(animation.pending && animation.playState === 'running',
+ 'Animation is initially play-pending');
animation.timeline = document.timeline;
- assert_equals(animation.playState, 'pending');
-}, 'After setting timeline on a play-pending animation it is still pending');
+ assert_true(animation.pending && animation.playState === 'running',
+ 'Animation is still play-pending after setting timeline');
-promise_test(function(t) {
- var animation =
- new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
- null);
- animation.play();
- assert_equals(animation.playState, 'pending');
-
- animation.timeline = document.timeline;
-
- return animation.ready.then(function() {
- assert_equals(animation.playState, 'running');
+ return animation.ready.then(() => {
+ assert_true(!animation.pending && animation.playState === 'running',
+ 'Animation plays after it finishes pending');
});
}, 'After setting timeline on a play-pending animation it begins playing'
+ ' after pending');
-test(function(t) {
- var animation =
+promise_test(t => {
+ const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
null);
animation.startTime = document.timeline.currentTime;
animation.pause();
animation.timeline = null;
- assert_equals(animation.playState, 'pending');
+ assert_true(animation.pending && animation.playState === 'paused',
+ 'Animation is initially pause-pending');
animation.timeline = document.timeline;
- assert_equals(animation.playState, 'pending');
-}, 'After setting timeline on a pause-pending animation it is still pending');
-
-promise_test(function(t) {
- var animation =
- new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
- null);
- animation.startTime = document.timeline.currentTime;
- animation.pause();
- animation.timeline = null;
- assert_equals(animation.playState, 'pending');
-
- animation.timeline = document.timeline;
+ assert_true(animation.pending && animation.playState === 'paused',
+ 'Animation is still pause-pending after setting timeline');
- return animation.ready.then(function() {
- assert_equals(animation.playState, 'paused');
+ return animation.ready.then(() => {
+ assert_true(!animation.pending && animation.playState === 'paused',
+ 'Animation pauses after it finishes pending');
});
}, 'After setting timeline on a pause-pending animation it becomes paused'
+ ' after pending');
@@ -145,24 +129,26 @@ promise_test(function(t) {
//
// ---------------------------------------------------------------------
-test(function(t) {
- var animation =
+test(t => {
+ const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
document.timeline);
animation.currentTime = 50 * MS_PER_SEC;
+ assert_false(animation.pending);
assert_equals(animation.playState, 'paused');
animation.timeline = null;
+ assert_false(animation.pending);
assert_equals(animation.playState, 'paused');
assert_times_equal(animation.currentTime, 50 * MS_PER_SEC);
}, 'After clearing timeline on paused animation it is still paused');
-test(function(t) {
- var animation =
+test(t => {
+ const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
document.timeline);
- var initialStartTime = document.timeline.currentTime - 200 * MS_PER_SEC;
+ const initialStartTime = document.timeline.currentTime - 200 * MS_PER_SEC;
animation.startTime = initialStartTime;
assert_equals(animation.playState, 'finished');
@@ -172,11 +158,11 @@ test(function(t) {
assert_times_equal(animation.startTime, initialStartTime);
}, 'After clearing timeline on finished animation it is idle');
-test(function(t) {
- var animation =
+test(t => {
+ const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
document.timeline);
- var initialStartTime = document.timeline.currentTime - 50 * MS_PER_SEC;
+ const initialStartTime = document.timeline.currentTime - 50 * MS_PER_SEC;
animation.startTime = initialStartTime;
assert_equals(animation.playState, 'running');
@@ -186,8 +172,8 @@ test(function(t) {
assert_times_equal(animation.startTime, initialStartTime);
}, 'After clearing timeline on running animation it is idle');
-test(function(t) {
- var animation =
+test(t => {
+ const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
document.timeline);
assert_equals(animation.playState, 'idle');
@@ -198,75 +184,73 @@ test(function(t) {
assert_equals(animation.startTime, null);
}, 'After clearing timeline on idle animation it is still idle');
-test(function(t) {
- var animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
- assert_equals(animation.playState, 'pending');
+test(t => {
+ const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
+ assert_true(animation.pending && animation.playState === 'running');
animation.timeline = null;
- assert_equals(animation.playState, 'pending');
+ assert_true(animation.pending && animation.playState === 'running');
}, 'After clearing timeline on play-pending animation it is still pending');
-promise_test(function(t) {
- var animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
- assert_equals(animation.playState, 'pending');
+promise_test(t => {
+ const animation = createDiv(t).animate(null, 100 * MS_PER_SEC);
+ assert_true(animation.pending && animation.playState === 'running');
animation.timeline = null;
animation.timeline = document.timeline;
- assert_equals(animation.playState, 'pending');
- return animation.ready.then(function() {
- assert_equals(animation.playState, 'running');
+ assert_true(animation.pending && animation.playState === 'running');
+ return animation.ready.then(() => {
+ assert_true(!animation.pending && animation.playState === 'running');
});
}, 'After clearing and re-setting timeline on play-pending animation it'
+ ' begins to play');
-test(function(t) {
- var animation =
+test(t => {
+ const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
document.timeline);
animation.startTime = document.timeline.currentTime;
animation.pause();
- assert_equals(animation.playState, 'pending');
+ assert_true(animation.pending && animation.playState === 'paused');
animation.timeline = null;
- assert_equals(animation.playState, 'pending');
+ assert_true(animation.pending && animation.playState === 'paused');
}, 'After clearing timeline on a pause-pending animation it is still pending');
-promise_test(function(t) {
- var animation =
+promise_test(t => {
+ const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
document.timeline);
animation.startTime = document.timeline.currentTime;
animation.pause();
- assert_equals(animation.playState, 'pending');
+ assert_true(animation.pending && animation.playState === 'paused');
animation.timeline = null;
animation.timeline = document.timeline;
- assert_equals(animation.playState, 'pending');
- return animation.ready.then(function() {
- assert_equals(animation.playState, 'paused');
+ assert_true(animation.pending && animation.playState === 'paused');
+ return animation.ready.then(() => {
+ assert_true(!animation.pending && animation.playState === 'paused');
});
}, 'After clearing and re-setting timeline on a pause-pending animation it'
- + ' becomes paused');
+ + ' completes pausing');
-promise_test(function(t) {
- var animation =
+promise_test(t => {
+ const animation =
new Animation(new KeyframeEffect(createDiv(t), null, 100 * MS_PER_SEC),
document.timeline);
- var initialStartTime = document.timeline.currentTime - 50 * MS_PER_SEC;
+ const initialStartTime = document.timeline.currentTime - 50 * MS_PER_SEC;
animation.startTime = initialStartTime;
animation.pause();
animation.play();
animation.timeline = null;
animation.timeline = document.timeline;
- assert_equals(animation.playState, 'pending');
- return animation.ready.then(function() {
- assert_equals(animation.playState, 'running');
+ return animation.ready.then(() => {
assert_times_equal(animation.startTime, initialStartTime);
});
}, 'After clearing and re-setting timeline on an animation in the middle of'
diff --git a/tests/wpt/web-platform-tests/web-animations/timing-model/animations/updating-the-finished-state.html b/tests/wpt/web-platform-tests/web-animations/timing-model/animations/updating-the-finished-state.html
index 7b9efedbf63..034cd6ee683 100644
--- a/tests/wpt/web-platform-tests/web-animations/timing-model/animations/updating-the-finished-state.html
+++ b/tests/wpt/web-platform-tests/web-animations/timing-model/animations/updating-the-finished-state.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>Tests for updating the finished state of an animation</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#updating-the-finished-state">
+<title>Updating the finished state</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#updating-the-finished-state">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -20,29 +20,29 @@
// (Also the start time is resolved and there is pending task)
// Did seek = false
-promise_test(function(t) {
- var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
+promise_test(t => {
+ const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
// Here and in the following tests we wait until ready resolves as
// otherwise we don't have a resolved start time. We test the case
// where the start time is unresolved in a subsequent test.
- return anim.ready.then(function() {
+ return anim.ready.then(() => {
// Seek to 1ms before the target end and then wait 1ms
anim.currentTime = 100 * MS_PER_SEC - 1;
return waitForAnimationFramesWithDelay(1);
- }).then(function() {
+ }).then(() => {
assert_equals(anim.currentTime, 100 * MS_PER_SEC,
'Hold time is set to target end clamping current time');
});
}, 'Updating the finished state when playing past end');
// Did seek = true
-promise_test(function(t) {
- var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
- return anim.ready.then(function() {
+promise_test(t => {
+ const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
+ return anim.ready.then(() => {
anim.currentTime = 200 * MS_PER_SEC;
- return waitForAnimationFrames(1);
- }).then(function() {
+ return waitForNextFrame();
+ }).then(() => {
assert_equals(anim.currentTime, 200 * MS_PER_SEC,
'Hold time is set so current time should NOT change');
});
@@ -59,12 +59,12 @@ promise_test(function(t) {
// (on the subsequent tick the hold time will be set to the same value anyway).
// Did seek = true
-promise_test(function(t) {
- var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
- return anim.ready.then(function() {
+promise_test(t => {
+ const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
+ return anim.ready.then(() => {
anim.currentTime = 100 * MS_PER_SEC;
- return waitForAnimationFrames(1);
- }).then(function() {
+ return waitForNextFrame();
+ }).then(() => {
assert_equals(anim.currentTime, 100 * MS_PER_SEC,
'Hold time is set so current time should NOT change');
});
@@ -75,29 +75,29 @@ promise_test(function(t) {
// (Also the start time is resolved and there is pending task)
// Did seek = false
-promise_test(function(t) {
- var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
+promise_test(t => {
+ const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
anim.playbackRate = -1;
anim.play(); // Make sure animation is not initially finished
- return anim.ready.then(function() {
+ return anim.ready.then(() => {
// Seek to 1ms before 0 and then wait 1ms
anim.currentTime = 1;
return waitForAnimationFramesWithDelay(1);
- }).then(function() {
+ }).then(() => {
assert_equals(anim.currentTime, 0 * MS_PER_SEC,
'Hold time is set to zero clamping current time');
});
}, 'Updating the finished state when playing in reverse past zero');
// Did seek = true
-promise_test(function(t) {
- var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
+promise_test(t => {
+ const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
anim.playbackRate = -1;
anim.play();
- return anim.ready.then(function() {
+ return anim.ready.then(() => {
anim.currentTime = -100 * MS_PER_SEC;
- return waitForAnimationFrames(1);
- }).then(function() {
+ return waitForNextFrame();
+ }).then(() => {
assert_equals(anim.currentTime, -100 * MS_PER_SEC,
'Hold time is set so current time should NOT change');
});
@@ -107,14 +107,14 @@ promise_test(function(t) {
// it doesn't really matter.
// Did seek = true
-promise_test(function(t) {
- var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
+promise_test(t => {
+ const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
anim.playbackRate = -1;
anim.play();
- return anim.ready.then(function() {
+ return anim.ready.then(() => {
anim.currentTime = 0;
- return waitForAnimationFrames(1);
- }).then(function() {
+ return waitForNextFrame();
+ }).then(() => {
assert_equals(anim.currentTime, 0 * MS_PER_SEC,
'Hold time is set so current time should NOT change');
});
@@ -126,38 +126,38 @@ promise_test(function(t) {
// (Also the start time is resolved and there is pending task)
// Did seek = false; playback rate > 0
-promise_test(function(t) {
- var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
+promise_test(t => {
+ const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
// We want to test that the hold time is cleared so first we need to
// put the animation in a state where the hold time is set.
anim.finish();
- return anim.ready.then(function() {
+ return anim.ready.then(() => {
assert_equals(anim.currentTime, 100 * MS_PER_SEC,
'Hold time is initially set');
// Then extend the duration so that the hold time is cleared and on
// the next tick the current time will increase.
anim.effect.timing.duration *= 2;
- return waitForAnimationFrames(1);
- }).then(function() {
+ return waitForNextFrame();
+ }).then(() => {
assert_greater_than(anim.currentTime, 100 * MS_PER_SEC,
'Hold time is not set so current time should increase');
});
}, 'Updating the finished state when playing before end');
// Did seek = true; playback rate > 0
-promise_test(function(t) {
- var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
+promise_test(t => {
+ const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
anim.finish();
- return anim.ready.then(function() {
+ return anim.ready.then(() => {
anim.currentTime = 50 * MS_PER_SEC;
// When did seek = true, updating the finished state: (i) updates
// the animation's start time and (ii) clears the hold time.
// We can test both by checking that the currentTime is initially
// updated and then increases.
assert_equals(anim.currentTime, 50 * MS_PER_SEC, 'Start time is updated');
- return waitForAnimationFrames(1);
- }).then(function() {
+ return waitForNextFrame();
+ }).then(() => {
assert_greater_than(anim.currentTime, 50 * MS_PER_SEC,
'Hold time is not set so current time should increase');
});
@@ -177,14 +177,14 @@ promise_test(function(t) {
// will set did seek = true).
// Did seek = true; playback rate < 0
-promise_test(function(t) {
- var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
+promise_test(t => {
+ const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
anim.playbackRate = -1;
- return anim.ready.then(function() {
+ return anim.ready.then(() => {
anim.currentTime = 50 * MS_PER_SEC;
assert_equals(anim.currentTime, 50 * MS_PER_SEC, 'Start time is updated');
- return waitForAnimationFrames(1);
- }).then(function() {
+ return waitForNextFrame();
+ }).then(() => {
assert_less_than(anim.currentTime, 50 * MS_PER_SEC,
'Hold time is not set so current time should decrease');
});
@@ -193,13 +193,13 @@ promise_test(function(t) {
// CASE 4: playback rate == 0
// current time < 0
-promise_test(function(t) {
- var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
+promise_test(t => {
+ const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
anim.playbackRate = 0;
- return anim.ready.then(function() {
+ return anim.ready.then(() => {
anim.currentTime = -100 * MS_PER_SEC;
- return waitForAnimationFrames(1);
- }).then(function() {
+ return waitForNextFrame();
+ }).then(() => {
assert_equals(anim.currentTime, -100 * MS_PER_SEC,
'Hold time should not be cleared so current time should'
+ ' NOT change');
@@ -208,13 +208,13 @@ promise_test(function(t) {
+ ' current time is less than zero');
// current time < target end
-promise_test(function(t) {
- var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
+promise_test(t => {
+ const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
anim.playbackRate = 0;
- return anim.ready.then(function() {
+ return anim.ready.then(() => {
anim.currentTime = 50 * MS_PER_SEC;
- return waitForAnimationFrames(1);
- }).then(function() {
+ return waitForNextFrame();
+ }).then(() => {
assert_equals(anim.currentTime, 50 * MS_PER_SEC,
'Hold time should not be cleared so current time should'
+ ' NOT change');
@@ -223,13 +223,13 @@ promise_test(function(t) {
+ ' current time is less than end');
// current time > target end
-promise_test(function(t) {
- var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
+promise_test(t => {
+ const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
anim.playbackRate = 0;
- return anim.ready.then(function() {
+ return anim.ready.then(() => {
anim.currentTime = 200 * MS_PER_SEC;
- return waitForAnimationFrames(1);
- }).then(function() {
+ return waitForNextFrame();
+ }).then(() => {
assert_equals(anim.currentTime, 200 * MS_PER_SEC,
'Hold time should not be cleared so current time should'
+ ' NOT change');
@@ -239,8 +239,8 @@ promise_test(function(t) {
// CASE 5: current time unresolved
-promise_test(function(t) {
- var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
+promise_test(t => {
+ const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
anim.cancel();
// Trigger a change that will cause the "update the finished state"
// procedure to run.
@@ -251,7 +251,7 @@ promise_test(function(t) {
// change to timing, but just in case an implementation defers that, let's
// wait a frame and check that the hold time / start time has still not been
// updated.
- return waitForAnimationFrames(1).then(function() {
+ return waitForAnimationFrames(1).then(() => {
assert_equals(anim.currentTime, null,
'The animation hold time / start time should not be updated');
});
@@ -259,8 +259,8 @@ promise_test(function(t) {
// CASE 6: has a pending task
-test(function(t) {
- var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
+test(t => {
+ const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
anim.cancel();
anim.currentTime = 75 * MS_PER_SEC;
anim.play();
@@ -278,8 +278,8 @@ test(function(t) {
// CASE 7: start time unresolved
// Did seek = false
-promise_test(function(t) {
- var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
+promise_test(t => {
+ const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
anim.cancel();
// Make it so that only the start time is unresolved (to avoid overlapping
// with the test case where current time is unresolved)
@@ -287,7 +287,7 @@ promise_test(function(t) {
// Trigger a change that will cause the "update the finished state"
// procedure to run (did seek = false).
anim.effect.timing.duration = 200 * MS_PER_SEC;
- return waitForAnimationFrames(1).then(function() {
+ return waitForAnimationFrames(1).then(() => {
assert_equals(anim.currentTime, 150 * MS_PER_SEC,
'The animation hold time should not be updated');
assert_equals(anim.startTime, null,
@@ -297,8 +297,8 @@ promise_test(function(t) {
+ ' did seek = false');
// Did seek = true
-test(function(t) {
- var anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
+test(t => {
+ const anim = createDiv(t).animate(null, 100 * MS_PER_SEC);
anim.cancel();
anim.currentTime = 150 * MS_PER_SEC;
// Trigger a change that will cause the "update the finished state"
@@ -318,14 +318,14 @@ test(function(t) {
// --------------------------------------------------------------------
function waitForFinishEventAndPromise(animation) {
- var eventPromise = new Promise(function(resolve) {
- animation.onfinish = function() { resolve(); }
+ const eventPromise = new Promise(resolve => {
+ animation.onfinish = resolve;
});
return Promise.all([eventPromise, animation.finished]);
}
-promise_test(function(t) {
- var animation = createDiv(t).animate(null, 1);
+promise_test(t => {
+ const animation = createDiv(t).animate(null, 1);
animation.onfinish =
t.unreached_func('Seeking to finish should not fire finish event');
animation.finished.then(
@@ -337,27 +337,27 @@ promise_test(function(t) {
}, 'Finish notification steps don\'t run when the animation seeks to finish'
+ ' and then seeks back again');
-promise_test(function(t) {
- var animation = createDiv(t).animate(null, 1);
- return animation.ready.then(function() {
+promise_test(t => {
+ const animation = createDiv(t).animate(null, 1);
+ return animation.ready.then(() => {
return waitForFinishEventAndPromise(animation);
});
}, 'Finish notification steps run when the animation completes normally');
-promise_test(function(t) {
- var animation = createDiv(t).animate(null, 1);
- return animation.ready.then(function() {
+promise_test(t => {
+ const animation = createDiv(t).animate(null, 1);
+ return animation.ready.then(() => {
animation.currentTime = 10;
return waitForFinishEventAndPromise(animation);
});
}, 'Finish notification steps run when the animation seeks past finish');
-promise_test(function(t) {
- var animation = createDiv(t).animate(null, 1);
- return animation.ready.then(function() {
+promise_test(t => {
+ const animation = createDiv(t).animate(null, 1);
+ return animation.ready.then(() => {
// Register for notifications now since once we seek away from being
// finished the 'finished' promise will be replaced.
- var finishNotificationSteps = waitForFinishEventAndPromise(animation);
+ const finishNotificationSteps = waitForFinishEventAndPromise(animation);
animation.finish();
animation.currentTime = 0;
animation.pause();
@@ -366,41 +366,41 @@ promise_test(function(t) {
}, 'Finish notification steps run when the animation completes with .finish(),'
+ ' even if we then seek away');
-promise_test(function(t) {
- var animation = createDiv(t).animate(null, 1);
- var initialFinishedPromise = animation.finished;
+promise_test(t => {
+ const animation = createDiv(t).animate(null, 1);
+ const initialFinishedPromise = animation.finished;
- return animation.finished.then(function(target) {
+ return animation.finished.then(target => {
animation.currentTime = 0;
assert_not_equals(initialFinishedPromise, animation.finished);
});
}, 'Animation finished promise is replaced after seeking back to start');
-promise_test(function(t) {
- var animation = createDiv(t).animate(null, 1);
- var initialFinishedPromise = animation.finished;
+promise_test(t => {
+ const animation = createDiv(t).animate(null, 1);
+ const initialFinishedPromise = animation.finished;
- return animation.finished.then(function(target) {
+ return animation.finished.then(target => {
animation.play();
assert_not_equals(initialFinishedPromise, animation.finished);
});
}, 'Animation finished promise is replaced after replaying from start');
-async_test(function(t) {
- var animation = createDiv(t).animate(null, 1);
- animation.onfinish = function(event) {
+async_test(t => {
+ const animation = createDiv(t).animate(null, 1);
+ animation.onfinish = event => {
animation.currentTime = 0;
- animation.onfinish = function(event) {
+ animation.onfinish = event => {
t.done();
};
};
}, 'Animation finish event is fired again after seeking back to start');
-async_test(function(t) {
- var animation = createDiv(t).animate(null, 1);
- animation.onfinish = function(event) {
+async_test(t => {
+ const animation = createDiv(t).animate(null, 1);
+ animation.onfinish = event => {
animation.play();
- animation.onfinish = function(event) {
+ animation.onfinish = event => {
t.done();
};
};
diff --git a/tests/wpt/web-platform-tests/web-animations/timing-model/time-transformations/transformed-progress.html b/tests/wpt/web-platform-tests/web-animations/timing-model/time-transformations/transformed-progress.html
index 6ca27cf5af8..839ebe1093e 100644
--- a/tests/wpt/web-platform-tests/web-animations/timing-model/time-transformations/transformed-progress.html
+++ b/tests/wpt/web-platform-tests/web-animations/timing-model/time-transformations/transformed-progress.html
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<title>Tests for the transformed progress</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#calculating-the-transformed-progress">
+<title>Transformed progress</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#calculating-the-transformed-progress">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -12,14 +12,14 @@
<script>
'use strict';
-gEasingTests.forEach(params => {
- test(function(t) {
+for (const params of gEasingTests) {
+ test(t => {
const target = createDiv(t);
const anim = target.animate(null, { duration: 1000,
fill: 'forwards',
easing: params.easing });
- [ 0, 250, 500, 750, 1000 ].forEach(sampleTime => {
+ for (const sampleTime of [0, 250, 500, 750, 1000]) {
anim.currentTime = sampleTime;
const portion = sampleTime / anim.effect.getComputedTiming().duration;
const expectedProgress = params.easingFunction(portion);
@@ -27,15 +27,15 @@ gEasingTests.forEach(params => {
expectedProgress,
0.01,
'The progress should be approximately ' +
- expectedProgress + ` at ${sampleTime}ms`);
- });
- }, 'Transformed progress for ' + params.desc);
-});
+ `${expectedProgress} at ${sampleTime}ms`);
+ }
+ }, `Transformed progress for ${params.desc}`);
+}
// Additional tests for various boundary conditions of step timing functions and
// frames timing functions.
-var gStepAndFramesTimingFunctionTests = [
+const gStepAndFramesTimingFunctionTests = [
{
description: 'Test bounds point of step-start easing',
effect: {
@@ -291,18 +291,18 @@ var gStepAndFramesTimingFunctionTests = [
}
];
-gStepAndFramesTimingFunctionTests.forEach(function(options) {
- test(function(t) {
- var target = createDiv(t);
- var animation = target.animate(null, options.effect);
- options.conditions.forEach(function(condition) {
+for (const options of gStepAndFramesTimingFunctionTests) {
+ test(t => {
+ const target = createDiv(t);
+ const animation = target.animate(null, options.effect);
+ for (const condition of options.conditions) {
animation.currentTime = condition.currentTime;
assert_equals(animation.effect.getComputedTiming().progress,
condition.progress,
- 'Progress at ' + animation.currentTime + 'ms');
- });
+ `Progress at ${animation.currentTime}ms`);
+ }
}, options.description);
-});
+}
</script>
</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/timing-model/timelines/document-timelines.html b/tests/wpt/web-platform-tests/web-animations/timing-model/timelines/document-timelines.html
index 7b863888aaa..bc3edff112e 100644
--- a/tests/wpt/web-platform-tests/web-animations/timing-model/timelines/document-timelines.html
+++ b/tests/wpt/web-platform-tests/web-animations/timing-model/timelines/document-timelines.html
@@ -1,7 +1,7 @@
<!doctype html>
<meta charset=utf-8>
<title>Document timelines</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#document-timelines">
+<link rel="help" href="https://drafts.csswg.org/web-animations/#document-timelines">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -9,7 +9,7 @@
<script>
'use strict';
-async_test(function(t) {
+async_test(t => {
assert_true(document.timeline.currentTime > 0,
'The current time is initially is positive');
// document.timeline.currentTime should be set even before document
@@ -25,8 +25,8 @@ async_test(function(t) {
// We can't just compare document.timeline.currentTime to
// window.performance.now() because currentTime is only updated on a sample
// so we use requestAnimationFrame instead.
- window.requestAnimationFrame(function(rafTime) {
- t.step(function() {
+ window.requestAnimationFrame(rafTime => {
+ t.step(() => {
assert_equals(document.timeline.currentTime, rafTime,
'The current time matches requestAnimationFrame time');
});
diff --git a/tests/wpt/web-platform-tests/web-animations/timing-model/timelines/timelines.html b/tests/wpt/web-platform-tests/web-animations/timing-model/timelines/timelines.html
index 290c71b8c2e..50bb3ac5877 100644
--- a/tests/wpt/web-platform-tests/web-animations/timing-model/timelines/timelines.html
+++ b/tests/wpt/web-platform-tests/web-animations/timing-model/timelines/timelines.html
@@ -1,7 +1,7 @@
<!doctype html>
<meta charset=utf-8>
<title>Timelines</title>
-<link rel="help" href="https://w3c.github.io/web-animations/#timelines">
+<link rel="help" href="https://drafts.csswg.org/web-animations/#timelines">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
@@ -9,7 +9,7 @@
<script>
'use strict';
-promise_test(function(t) {
+promise_test(t => {
const valueAtStart = document.timeline.currentTime;
const timeAtStart = window.performance.now();
while (window.performance.now() - timeAtStart < 50) {
@@ -17,13 +17,13 @@ promise_test(function(t) {
}
assert_equals(document.timeline.currentTime, valueAtStart,
'Timeline time does not change within an animation frame');
- return waitForAnimationFrames(1).then(function() {
+ return waitForAnimationFrames(1).then(() => {
assert_greater_than(document.timeline.currentTime, valueAtStart,
'Timeline time increases between animation frames');
});
}, 'Timeline time increases once per animation frame');
-async_test(function(t) {
+async_test(t => {
const iframe = document.createElement('iframe');
iframe.width = 10;
iframe.height = 10;
@@ -49,20 +49,20 @@ async_test(function(t) {
document.body.appendChild(iframe);
}, 'Timeline time increases once per animation frame in an iframe');
-async_test(function(t) {
+async_test(t => {
const startTime = document.timeline.currentTime;
let firstRafTime;
- requestAnimationFrame(function() {
- t.step(function() {
+ requestAnimationFrame(() => {
+ t.step(() => {
assert_greater_than_equal(document.timeline.currentTime, startTime,
'Timeline time should have progressed');
firstRafTime = document.timeline.currentTime;
});
});
- requestAnimationFrame(function() {
- t.step(function() {
+ requestAnimationFrame(() => {
+ t.step(() => {
assert_equals(document.timeline.currentTime, firstRafTime,
'Timeline time should be the same');
});
@@ -71,4 +71,17 @@ async_test(function(t) {
}, 'Timeline time should be the same for all RAF callbacks in an animation'
+ ' frame');
+async_test(t => {
+ const div = createDiv(t);
+ const animation = div.animate(null, 100 * MS_PER_SEC);
+
+ animation.ready.then(t.step_func(() => {
+ const readyTimelineTime = document.timeline.currentTime;
+ requestAnimationFrame(t.step_func_done(() => {
+ assert_equals(readyTimelineTime, document.timeline.currentTime,
+ 'There should be a microtask checkpoint');
+ }));
+ }));
+}, 'Performs a microtask checkpoint after updating timelins');
+
</script>
diff --git a/tests/wpt/web-platform-tests/webaudio/resources/audit.js b/tests/wpt/web-platform-tests/webaudio/resources/audit.js
index e3ccd470e4e..4f4c6b7aed8 100644
--- a/tests/wpt/web-platform-tests/webaudio/resources/audit.js
+++ b/tests/wpt/web-platform-tests/webaudio/resources/audit.js
@@ -118,6 +118,8 @@ window.Audit = (function() {
this._expectedDescription = null;
this._detail = '';
+ // If true and the test failed, print the actual value at the
+ // end of the message.
this._printActualForFailure = true;
this._result = null;
@@ -620,7 +622,8 @@ window.Audit = (function() {
passDetail = '${actual} contains only the constant ${expected}.';
} else {
let counter = 0;
- failDetail = 'Expected ${expected} for all values but found ' +
+ failDetail =
+ '${actual}: Expected ${expected} for all values but found ' +
numberOfErrors + ' unexpected values: ';
failDetail += '\n\tIndex\tActual';
for (let errorIndex in errors) {
diff --git a/tests/wpt/web-platform-tests/webdriver/OWNERS b/tests/wpt/web-platform-tests/webdriver/OWNERS
index 07296e312b3..c004c0467e0 100644
--- a/tests/wpt/web-platform-tests/webdriver/OWNERS
+++ b/tests/wpt/web-platform-tests/webdriver/OWNERS
@@ -4,3 +4,4 @@
@lukeis
@mjzffr
@shs96c
+@whimboo
diff --git a/tests/wpt/web-platform-tests/webdriver/interface/interface.html b/tests/wpt/web-platform-tests/webdriver/interface/interface.html
deleted file mode 100644
index e29fa63e933..00000000000
--- a/tests/wpt/web-platform-tests/webdriver/interface/interface.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<body>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
-
-test(function() {
- if ("webdriver" in navigator) {
- var descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(navigator), "webdriver");
- assert_true(descriptor !== undefined);
- assert_true(descriptor.configurable);
- assert_true(descriptor.enumerable);
- assert_true(descriptor.set === undefined);
- assert_true(navigator.webdriver);
- } else {
- assert_true(navigator.webdriver === undefined);
- }
-}, "Test that the navigator.webdriver descriptor has expected properties or doesn't exist at all");
-</script>
-</body>
-</html>
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/actions/key_shortcuts.py b/tests/wpt/web-platform-tests/webdriver/tests/actions/key_shortcuts.py
new file mode 100644
index 00000000000..ec062f75224
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/tests/actions/key_shortcuts.py
@@ -0,0 +1,49 @@
+from tests.actions.support.keys import Keys, MODIFIER_KEY
+from tests.actions.support.refine import get_keys
+
+
+def test_mod_a_and_backspace_deletes_all_text(session, key_reporter, key_chain):
+ key_chain.send_keys("abc d") \
+ .key_down(MODIFIER_KEY) \
+ .key_down("a") \
+ .key_up(MODIFIER_KEY) \
+ .key_up("a") \
+ .key_down(Keys.BACKSPACE) \
+ .perform()
+ assert get_keys(key_reporter) == ""
+
+
+def test_mod_a_mod_c_right_mod_v_pastes_text(session, key_reporter, key_chain):
+ initial = "abc d"
+ key_chain.send_keys(initial) \
+ .key_down(MODIFIER_KEY) \
+ .key_down("a") \
+ .key_up(MODIFIER_KEY) \
+ .key_up("a") \
+ .key_down(MODIFIER_KEY) \
+ .key_down("c") \
+ .key_up(MODIFIER_KEY) \
+ .key_up("c") \
+ .send_keys([Keys.RIGHT]) \
+ .key_down(MODIFIER_KEY) \
+ .key_down("v") \
+ .key_up(MODIFIER_KEY) \
+ .key_up("v") \
+ .perform()
+ assert get_keys(key_reporter) == initial * 2
+
+
+def test_mod_a_mod_x_deletes_all_text(session, key_reporter, key_chain):
+ key_chain.send_keys("abc d") \
+ .key_down(MODIFIER_KEY) \
+ .key_down("a") \
+ .key_up(MODIFIER_KEY) \
+ .key_up("a") \
+ .key_down(MODIFIER_KEY) \
+ .key_down("x") \
+ .key_up(MODIFIER_KEY) \
+ .key_up("x") \
+ .perform()
+ assert get_keys(key_reporter) == ""
+
+
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/actions/modifier_click.py b/tests/wpt/web-platform-tests/webdriver/tests/actions/modifier_click.py
index 73de161119d..fdd43e2ebcb 100644
--- a/tests/wpt/web-platform-tests/webdriver/tests/actions/modifier_click.py
+++ b/tests/wpt/web-platform-tests/webdriver/tests/actions/modifier_click.py
@@ -6,30 +6,55 @@ from tests.actions.support.refine import filter_dict, get_events
from tests.actions.support.keys import Keys
+# Using local fixtures because we want to start a new session between
+# each test, otherwise the clicks in each test interfere with each other.
+@pytest.fixture(autouse=True)
+def release_actions(mod_click_session, request):
+ request.addfinalizer(mod_click_session.actions.release)
+
+
+@pytest.fixture
+def mod_click_session(new_session, url, add_browser_capabilites):
+ _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({})}})
+ session.url = url("/webdriver/tests/actions/support/test_actions_wdspec.html")
+
+ return session
+
+
+@pytest.fixture
+def key_chain(mod_click_session):
+ return mod_click_session.actions.sequence("key", "keyboard_id")
+
+
+@pytest.fixture
+def mouse_chain(mod_click_session):
+ return mod_click_session.actions.sequence(
+ "pointer",
+ "pointer_id",
+ {"pointerType": "mouse"})
+
+
@pytest.mark.parametrize("modifier, prop", [
- (Keys.CONTROL, "ctrlKey"),
- (Keys.ALT, "altKey"),
- (Keys.META, "metaKey"),
- (Keys.SHIFT, "shiftKey"),
- (Keys.R_CONTROL, "ctrlKey"),
- (Keys.R_ALT, "altKey"),
- (Keys.R_META, "metaKey"),
- (Keys.R_SHIFT, "shiftKey"),
+ (Keys.ALT, "altKey"),
+ (Keys.R_ALT, "altKey"),
+ (Keys.META, "metaKey"),
+ (Keys.R_META, "metaKey"),
+ (Keys.SHIFT, "shiftKey"),
+ (Keys.R_SHIFT, "shiftKey"),
])
-def test_modifier_click(session,
- test_actions_page,
+def test_modifier_click(mod_click_session,
key_chain,
mouse_chain,
modifier,
prop):
key_chain \
- .pause(0) \
+ .pause(200) \
.key_down(modifier) \
.pause(200) \
.key_up(modifier)
- outer = session.find.css("#outer", all=False)
+ outer = mod_click_session.find.css("#outer", all=False)
mouse_chain.click(element=outer)
- session.actions.perform([key_chain.dict, mouse_chain.dict])
+ mod_click_session.actions.perform([key_chain.dict, mouse_chain.dict])
expected = [
{"type": "mousemove"},
{"type": "mousedown"},
@@ -46,29 +71,47 @@ def test_modifier_click(session,
e.update(defaults)
if e["type"] != "mousemove":
e[prop] = True
- filtered_events = [filter_dict(e, expected[0]) for e in get_events(session)]
+ filtered_events = [filter_dict(e, expected[0]) for e in get_events(mod_click_session)]
assert expected == filtered_events
-def test_release_control_click(session, key_reporter, key_chain, mouse_chain):
+def test_many_modifiers_click(mod_click_session, key_chain, mouse_chain):
+ outer = mod_click_session.find.css("#outer", all=False)
key_chain \
.pause(0) \
- .key_down(Keys.CONTROL)
+ .key_down(Keys.CONTROL) \
+ .key_down(Keys.SHIFT) \
+ .pause(0) \
+ .key_up(Keys.CONTROL) \
+ .key_up(Keys.SHIFT)
mouse_chain \
- .pointer_move(0, 0, origin=key_reporter) \
+ .pointer_move(0, 0, origin=outer) \
+ .pause(0) \
+ .pointer_down() \
+ .pointer_up() \
+ .pause(0) \
+ .pause(0) \
.pointer_down()
- session.actions.perform([key_chain.dict, mouse_chain.dict])
- session.execute_script("""
- var keyReporter = document.getElementById("keys");
- ["mousedown", "mouseup"].forEach((e) => {
- keyReporter.addEventListener(e, recordPointerEvent);
- });
- resetEvents();
- """)
- session.actions.release()
+ mod_click_session.actions.perform([key_chain.dict, mouse_chain.dict])
expected = [
+ {"type": "mousemove"},
+ # shift and ctrl presses
+ {"type": "mousedown"},
{"type": "mouseup"},
- {"type": "keyup"},
+ {"type": "click"},
+ # no modifiers pressed
+ {"type": "mousedown"},
]
- events = [filter_dict(e, expected[0]) for e in get_events(session)]
+ defaults = {
+ "altKey": False,
+ "metaKey": False,
+ "shiftKey": False,
+ "ctrlKey": False
+ }
+ for e in expected:
+ e.update(defaults)
+ for e in expected[1:4]:
+ e["shiftKey"] = True
+ e["ctrlKey"] = True
+ events = [filter_dict(e, expected[0]) for e in get_events(mod_click_session)]
assert events == expected
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/actions/mouse.py b/tests/wpt/web-platform-tests/webdriver/tests/actions/mouse.py
index 07f7809e918..95d284c4b72 100644
--- a/tests/wpt/web-platform-tests/webdriver/tests/actions/mouse.py
+++ b/tests/wpt/web-platform-tests/webdriver/tests/actions/mouse.py
@@ -1,7 +1,8 @@
import pytest
-from tests.support.inline import inline
+from tests.actions.support.mouse import assert_move_to_coordinates, get_center
from tests.actions.support.refine import get_events, filter_dict
+from tests.support.inline import inline
from tests.support.wait import wait
@@ -10,13 +11,6 @@ def link_doc(dest):
return inline(content)
-def get_center(rect):
- return {
- "x": rect["width"] / 2 + rect["x"],
- "y": rect["height"] / 2 + rect["y"],
- }
-
-
# TODO use pytest.approx once we upgrade to pytest > 3.0
def approx(n, m, tolerance=1):
return abs(n - m) <= tolerance
@@ -33,11 +27,8 @@ def test_click_at_coordinates(session, test_actions_page, mouse_chain):
.perform()
events = get_events(session)
assert len(events) == 4
+ assert_move_to_coordinates(div_point, "outer", events)
for e in events:
- if e["type"] != "mousemove":
- assert e["pageX"] == div_point["x"]
- assert e["pageY"] == div_point["y"]
- assert e["target"] == "outer"
if e["type"] != "mousedown":
assert e["buttons"] == 0
assert e["button"] == 0
@@ -89,7 +80,7 @@ def test_click_element_center(session, test_actions_page, mouse_chain):
assert e["target"] == "outer"
-def test_click_navigation(session, url):
+def test_click_navigation(session, url, release_actions):
destination = url("/webdriver/tests/actions/support/test_actions_wdspec.html")
start = link_doc(destination)
@@ -112,7 +103,12 @@ def test_click_navigation(session, url):
@pytest.mark.parametrize("drag_duration", [0, 300, 800])
@pytest.mark.parametrize("dx, dy",
[(20, 0), (0, 15), (10, 15), (-20, 0), (10, -15), (-10, -15)])
-def test_drag_and_drop(session, test_actions_page, mouse_chain, dx, dy, drag_duration):
+def test_drag_and_drop(session,
+ test_actions_page,
+ mouse_chain,
+ dx,
+ dy,
+ drag_duration):
drag_target = session.find.css("#dragTarget", all=False)
initial_rect = drag_target.rect
initial_center = get_center(initial_rect)
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/actions/mouse_dblclick.py b/tests/wpt/web-platform-tests/webdriver/tests/actions/mouse_dblclick.py
new file mode 100644
index 00000000000..f73f780a7a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/tests/actions/mouse_dblclick.py
@@ -0,0 +1,108 @@
+import pytest
+
+from tests.actions.support.mouse import assert_move_to_coordinates, get_center
+from tests.actions.support.refine import get_events, filter_dict
+
+
+_DBLCLICK_INTERVAL = 640
+
+
+# Using local fixtures because we want to start a new session between
+# each test, otherwise the clicks in each test interfere with each other.
+@pytest.fixture(autouse=True)
+def release_actions(dblclick_session, request):
+ # release all actions after each test
+ # equivalent to a teardown_function, but with access to session fixture
+ request.addfinalizer(dblclick_session.actions.release)
+
+
+@pytest.fixture
+def dblclick_session(new_session, url, add_browser_capabilites):
+ _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({})}})
+ session.url = url("/webdriver/tests/actions/support/test_actions_wdspec.html")
+
+ return session
+
+
+@pytest.fixture
+def mouse_chain(dblclick_session):
+ return dblclick_session.actions.sequence(
+ "pointer",
+ "pointer_id",
+ {"pointerType": "mouse"})
+
+
+@pytest.mark.parametrize("click_pause", [0, 200])
+def test_dblclick_at_coordinates(dblclick_session, mouse_chain, click_pause):
+ div_point = {
+ "x": 82,
+ "y": 187,
+ }
+ mouse_chain \
+ .pointer_move(div_point["x"], div_point["y"]) \
+ .click() \
+ .pause(click_pause) \
+ .click() \
+ .perform()
+ events = get_events(dblclick_session)
+ assert_move_to_coordinates(div_point, "outer", events)
+ expected = [
+ {"type": "mousedown", "button": 0},
+ {"type": "mouseup", "button": 0},
+ {"type": "click", "button": 0},
+ {"type": "mousedown", "button": 0},
+ {"type": "mouseup", "button": 0},
+ {"type": "click", "button": 0},
+ {"type": "dblclick", "button": 0},
+ ]
+ assert len(events) == 8
+ filtered_events = [filter_dict(e, expected[0]) for e in events]
+ assert expected == filtered_events[1:]
+
+
+def test_dblclick_with_pause_after_second_pointerdown(dblclick_session, mouse_chain):
+ outer = dblclick_session.find.css("#outer", all=False)
+ center = get_center(outer.rect)
+ mouse_chain \
+ .pointer_move(int(center["x"]), int(center["y"])) \
+ .click() \
+ .pointer_down() \
+ .pause(_DBLCLICK_INTERVAL + 10) \
+ .pointer_up() \
+ .perform()
+ events = get_events(dblclick_session)
+ expected = [
+ {"type": "mousedown", "button": 0},
+ {"type": "mouseup", "button": 0},
+ {"type": "click", "button": 0},
+ {"type": "mousedown", "button": 0},
+ {"type": "mouseup", "button": 0},
+ {"type": "click", "button": 0},
+ {"type": "dblclick", "button": 0},
+ ]
+ assert len(events) == 8
+ filtered_events = [filter_dict(e, expected[0]) for e in events]
+ assert expected == filtered_events[1:]
+
+
+def test_no_dblclick(dblclick_session, mouse_chain):
+ outer = dblclick_session.find.css("#outer", all=False)
+ center = get_center(outer.rect)
+ mouse_chain \
+ .pointer_move(int(center["x"]), int(center["y"])) \
+ .click() \
+ .pause(_DBLCLICK_INTERVAL + 10) \
+ .click() \
+ .perform()
+ events = get_events(dblclick_session)
+ expected = [
+ {"type": "mousedown", "button": 0},
+ {"type": "mouseup", "button": 0},
+ {"type": "click", "button": 0},
+ {"type": "mousedown", "button": 0},
+ {"type": "mouseup", "button": 0},
+ {"type": "click", "button": 0},
+ ]
+ assert len(events) == 7
+ filtered_events = [filter_dict(e, expected[0]) for e in events]
+ assert expected == filtered_events[1:]
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/actions/sequence.py b/tests/wpt/web-platform-tests/webdriver/tests/actions/sequence.py
index 3092034c46f..426dbe82f48 100644
--- a/tests/wpt/web-platform-tests/webdriver/tests/actions/sequence.py
+++ b/tests/wpt/web-platform-tests/webdriver/tests/actions/sequence.py
@@ -37,45 +37,3 @@ def test_release_no_actions_sends_no_events(session, key_reporter):
session.actions.release()
assert len(get_keys(key_reporter)) == 0
assert len(get_events(session)) == 0
-
-
-def test_many_modifiers_click(session, test_actions_page, key_chain, mouse_chain):
- outer = session.find.css("#outer", all=False)
- key_chain \
- .pause(0) \
- .key_down(Keys.CONTROL) \
- .key_down(Keys.SHIFT) \
- .pause(0) \
- .key_up(Keys.CONTROL) \
- .key_up(Keys.SHIFT)
- mouse_chain \
- .pointer_move(0, 0, origin=outer) \
- .pause(0) \
- .pointer_down() \
- .pointer_up() \
- .pause(0) \
- .pause(0) \
- .pointer_down()
- session.actions.perform([key_chain.dict, mouse_chain.dict])
- expected = [
- {"type": "mousemove"},
- # shift and ctrl presses
- {"type": "mousedown"},
- {"type": "mouseup"},
- {"type": "click"},
- # no modifiers pressed
- {"type": "mousedown"},
- ]
- defaults = {
- "altKey": False,
- "metaKey": False,
- "shiftKey": False,
- "ctrlKey": False
- }
- for e in expected:
- e.update(defaults)
- for e in expected[1:4]:
- e["shiftKey"] = True
- e["ctrlKey"] = True
- events = [filter_dict(e, expected[0]) for e in get_events(session)]
- assert events == expected
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/actions/support/keys.py b/tests/wpt/web-platform-tests/webdriver/tests/actions/support/keys.py
index 85517916678..7c71a87bc69 100644
--- a/tests/wpt/web-platform-tests/webdriver/tests/actions/support/keys.py
+++ b/tests/wpt/web-platform-tests/webdriver/tests/actions/support/keys.py
@@ -20,6 +20,7 @@ The Keys implementation.
"""
from inspect import getmembers
+import sys
class Keys(object):
@@ -740,3 +741,8 @@ ALL_EVENTS = {
"value": u"\ue040",
}
}
+
+if sys.platform == 'darwin':
+ MODIFIER_KEY = Keys.META
+else:
+ MODIFIER_KEY = Keys.CONTROL
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/actions/support/mouse.py b/tests/wpt/web-platform-tests/webdriver/tests/actions/support/mouse.py
new file mode 100644
index 00000000000..63a771d9487
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/tests/actions/support/mouse.py
@@ -0,0 +1,13 @@
+def assert_move_to_coordinates(point, target, events):
+ for e in events:
+ if e["type"] != "mousemove":
+ assert e["pageX"] == point["x"]
+ assert e["pageY"] == point["y"]
+ assert e["target"] == target
+
+
+def get_center(rect):
+ return {
+ "x": rect["width"] / 2 + rect["x"],
+ "y": rect["height"] / 2 + rect["y"],
+ }
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/cookies/add_cookie.py b/tests/wpt/web-platform-tests/webdriver/tests/cookies/add_cookie.py
index df45722b100..1ebbcb41de7 100644
--- a/tests/wpt/web-platform-tests/webdriver/tests/cookies/add_cookie.py
+++ b/tests/wpt/web-platform-tests/webdriver/tests/cookies/add_cookie.py
@@ -1,14 +1,14 @@
from tests.support.fixtures import clear_all_cookies
-from tests.support.fixtures import server_config
+from datetime import datetime, timedelta
-def test_add_domain_cookie(session, url):
+def test_add_domain_cookie(session, url, server_config):
session.url = url("/common/blank.html")
clear_all_cookies(session)
create_cookie_request = {
"cookie": {
"name": "hello",
"value": "world",
- "domain": "web-platform.test",
+ "domain": server_config["domains"][""],
"path": "/",
"httpOnly": False,
"secure": False
@@ -36,16 +36,16 @@ def test_add_domain_cookie(session, url):
assert cookie["name"] == "hello"
assert cookie["value"] == "world"
- assert cookie["domain"] == ".web-platform.test"
+ assert cookie["domain"] == ".%s" % server_config["domains"][""]
-def test_add_cookie_for_ip(session, url, server_config):
+def test_add_cookie_for_ip(session, url, server_config, configuration):
session.url = "http://127.0.0.1:%s/404" % (server_config["ports"]["http"][0])
clear_all_cookies(session)
create_cookie_request = {
"cookie": {
"name": "hello",
"value": "world",
- "domain": "127.0.0.1",
+ "domain": configuration["host"],
"path": "/",
"httpOnly": False,
"secure": False
@@ -74,3 +74,104 @@ def test_add_cookie_for_ip(session, url, server_config):
assert cookie["name"] == "hello"
assert cookie["value"] == "world"
assert cookie["domain"] == "127.0.0.1"
+
+def test_add_non_session_cookie(session, url):
+ session.url = url("/common/blank.html")
+ clear_all_cookies(session)
+ a_year_from_now = int((datetime.utcnow() + timedelta(days=365)).strftime("%s"))
+ create_cookie_request = {
+ "cookie": {
+ "name": "hello",
+ "value": "world",
+ "expiry": a_year_from_now
+ }
+ }
+ result = session.transport.send("POST", "session/%s/cookie" % session.session_id, create_cookie_request)
+ assert result.status == 200
+ assert "value" in result.body
+ assert isinstance(result.body["value"], dict)
+
+ result = session.transport.send("GET", "session/%s/cookie" % session.session_id)
+ assert result.status == 200
+ assert "value" in result.body
+ assert isinstance(result.body["value"], list)
+ assert len(result.body["value"]) == 1
+ assert isinstance(result.body["value"][0], dict)
+
+ cookie = result.body["value"][0]
+ assert "name" in cookie
+ assert isinstance(cookie["name"], basestring)
+ assert "value" in cookie
+ assert isinstance(cookie["value"], basestring)
+ assert "expiry" in cookie
+ assert isinstance(cookie["expiry"], int)
+
+ assert cookie["name"] == "hello"
+ assert cookie["value"] == "world"
+ assert cookie["expiry"] == a_year_from_now
+
+def test_add_session_cookie(session, url):
+ session.url = url("/common/blank.html")
+ clear_all_cookies(session)
+ create_cookie_request = {
+ "cookie": {
+ "name": "hello",
+ "value": "world"
+ }
+ }
+ result = session.transport.send("POST", "session/%s/cookie" % session.session_id, create_cookie_request)
+ assert result.status == 200
+ assert "value" in result.body
+ assert isinstance(result.body["value"], dict)
+
+ result = session.transport.send("GET", "session/%s/cookie" % session.session_id)
+ assert result.status == 200
+ assert "value" in result.body
+ assert isinstance(result.body["value"], list)
+ assert len(result.body["value"]) == 1
+ assert isinstance(result.body["value"][0], dict)
+
+ cookie = result.body["value"][0]
+ assert "name" in cookie
+ assert isinstance(cookie["name"], basestring)
+ assert "value" in cookie
+ assert isinstance(cookie["value"], basestring)
+ assert "expiry" in cookie
+ assert cookie.get("expiry") is None
+
+ assert cookie["name"] == "hello"
+ assert cookie["value"] == "world"
+
+def test_add_session_cookie_with_leading_dot_character_in_domain(session, url, server_config):
+ session.url = url("/common/blank.html")
+ clear_all_cookies(session)
+ create_cookie_request = {
+ "cookie": {
+ "name": "hello",
+ "value": "world",
+ "domain": ".%s" % server_config["domains"][""]
+ }
+ }
+ result = session.transport.send("POST", "session/%s/cookie" % session.session_id, create_cookie_request)
+ assert result.status == 200
+ assert "value" in result.body
+ assert isinstance(result.body["value"], dict)
+
+ result = session.transport.send("GET", "session/%s/cookie" % session.session_id)
+ assert result.status == 200
+ assert "value" in result.body
+ assert isinstance(result.body["value"], list)
+ assert len(result.body["value"]) == 1
+ assert isinstance(result.body["value"][0], dict)
+
+ cookie = result.body["value"][0]
+ assert "name" in cookie
+ assert isinstance(cookie["name"], basestring)
+ assert "value" in cookie
+ assert isinstance(cookie["value"], basestring)
+ assert "domain" in cookie
+ assert isinstance(cookie["domain"], basestring)
+
+ assert cookie["name"] == "hello"
+ assert cookie["value"] == "world"
+ assert cookie["domain"] == ".%s" % server_config["domains"][""]
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/cookies/get_named_cookie.py b/tests/wpt/web-platform-tests/webdriver/tests/cookies/get_named_cookie.py
index 027859dd7f9..f367eccf947 100644
--- a/tests/wpt/web-platform-tests/webdriver/tests/cookies/get_named_cookie.py
+++ b/tests/wpt/web-platform-tests/webdriver/tests/cookies/get_named_cookie.py
@@ -61,14 +61,14 @@ def test_get_named_cookie(session, url):
# convert from seconds since epoch
assert datetime.utcfromtimestamp(cookie["expiry"]).strftime(utc_string_format) == a_year_from_now
-def test_duplicated_cookie(session, url):
+def test_duplicated_cookie(session, url, server_config):
session.url = url("/common/blank.html")
clear_all_cookies(session)
create_cookie_request = {
"cookie": {
"name": "hello",
"value": "world",
- "domain": "web-platform.test",
+ "domain": server_config["domains"][""],
"path": "/",
"httpOnly": False,
"secure": False
@@ -79,7 +79,7 @@ def test_duplicated_cookie(session, url):
assert "value" in result.body
assert isinstance(result.body["value"], dict)
- session.url = inline("<script>document.cookie = 'hello=newworld; domain=web-platform.test; path=/';</script>")
+ session.url = inline("<script>document.cookie = 'hello=newworld; domain=%s; path=/';</script>" % server_config["domains"][""])
result = session.transport.send("GET", "session/%s/cookie" % session.session_id)
assert result.status == 200
assert "value" in result.body
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/document_handling/page_source.py b/tests/wpt/web-platform-tests/webdriver/tests/document_handling/page_source.py
new file mode 100644
index 00000000000..04eae6f83be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/tests/document_handling/page_source.py
@@ -0,0 +1,14 @@
+import pytest
+
+from tests.support.inline import inline
+
+
+# 15.1.3 "Let source be the result returned from the outerHTML IDL attribute
+# of the document element"
+def test_source_matches_outer_html(session):
+ session.url = inline("<html><head><title>Cheese</title><body>Peas")
+ expected_source = session.execute_script(
+ "return document.documentElement.outerHTML")
+
+ assert session.source == expected_source
+
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/element_click/bubbling.py b/tests/wpt/web-platform-tests/webdriver/tests/element_click/bubbling.py
new file mode 100644
index 00000000000..1cfb2efa2f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/tests/element_click/bubbling.py
@@ -0,0 +1,152 @@
+from tests.support.asserts import assert_success
+from tests.support.inline import inline
+
+
+def click(session, element):
+ return session.transport.send(
+ "POST", "/session/{session_id}/element/{element_id}/click".format(
+ session_id=session.session_id,
+ element_id=element.id))
+
+
+def test_click_event_bubbles_to_parents(session):
+ session.url = inline("""
+ <style>
+ body * {
+ margin: 10px;
+ padding: 10px;
+ border: 1px solid blue;
+ }
+ </style>
+
+ <div id=three>THREE
+ <div id=two>TWO
+ <div id=one>ONE</div>
+ </div>
+ </div>
+
+ <script>
+ window.clicks = [];
+
+ for (let level of document.querySelectorAll("div")) {
+ level.addEventListener("click", ({currentTarget}) => {
+ window.clicks.push(currentTarget);
+ });
+ }
+ </script>
+ """)
+ three, two, one = session.find.css("div")
+ one.click()
+
+ clicks = session.execute_script("return window.clicks")
+ assert one in clicks
+ assert two in clicks
+ assert three in clicks
+
+
+def test_spin_event_loop(session):
+ """
+ Wait until the user agent event loop has spun enough times to
+ process the DOM events generated by clicking.
+ """
+ session.url = inline("""
+ <style>
+ body * {
+ margin: 10px;
+ padding: 10px;
+ border: 1px solid blue;
+ }
+ </style>
+
+ <div id=three>THREE
+ <div id=two>TWO
+ <div id=one>ONE</div>
+ </div>
+ </div>
+
+ <script>
+ window.delayedClicks = [];
+
+ for (let level of document.querySelectorAll("div")) {
+ level.addEventListener("click", ({currentTarget}) => {
+ setTimeout(() => window.delayedClicks.push(currentTarget), 100);
+ });
+ }
+ </script>
+ """)
+ three, two, one = session.find.css("div")
+ one.click()
+
+ delayed_clicks = session.execute_script("return window.delayedClicks")
+ assert one in delayed_clicks
+ assert two in delayed_clicks
+ assert three in delayed_clicks
+
+
+def test_element_disappears_during_click(session):
+ """
+ When an element in the event bubbling order disappears (its CSS
+ display style is set to "none") during a click, Gecko and Blink
+ exhibit different behaviour. Whilst Chrome fires a "click"
+ DOM event on <body>, Firefox does not.
+
+ A WebDriver implementation may choose to wait for this event to let
+ the event loops spin enough times to let click events propagate,
+ so this is a corner case test that Firefox does not hang indefinitely.
+ """
+ session.url = inline("""
+ <style>
+ #over,
+ #under {
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ width: 100px;
+ height: 100px;
+ }
+
+ #over {
+ background: blue;
+ opacity: .5;
+ }
+ #under {
+ background: yellow;
+ }
+
+ #log {
+ margin-top: 120px;
+ }
+ </style>
+
+ <body id="body">
+ <div id=under></div>
+ <div id=over></div>
+
+ <div id=log></div>
+ </body>
+
+ <script>
+ let under = document.querySelector("#under");
+ let over = document.querySelector("#over");
+ let body = document.querySelector("body");
+ let log = document.querySelector("#log");
+
+ function logEvent({type, target, currentTarget}) {
+ log.innerHTML += "<p></p>";
+ log.lastElementChild.textContent = `${type} in ${target.id} (handled by ${currentTarget.id})`;
+ }
+
+ for (let ev of ["click", "mousedown", "mouseup"]) {
+ under.addEventListener(ev, logEvent);
+ over.addEventListener(ev, logEvent);
+ body.addEventListener(ev, logEvent);
+ }
+
+ over.addEventListener("mousedown", () => over.style.display = "none");
+ </script>
+ """)
+ over = session.find.css("#over", all=False)
+
+ # should not time out
+ response = click(session, over)
+ assert_success(response)
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/element_click/stale.py b/tests/wpt/web-platform-tests/webdriver/tests/element_click/stale.py
new file mode 100644
index 00000000000..d39e3a3ecb7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/tests/element_click/stale.py
@@ -0,0 +1,22 @@
+import pytest
+import webdriver
+
+from tests.support.asserts import assert_error
+from tests.support.inline import inline
+
+
+def click_element(session, element):
+ return session.transport.send(
+ "POST", "/session/{session_id}/element/{element_id}/click".format(**{
+ "session_id": session.session_id,
+ "element_id": element.id,
+ }))
+
+
+def test_is_stale(session):
+ session.url = inline("<button>foo</button>")
+ button = session.find.css("button", all=False)
+ session.url = inline("<button>bar</button>")
+
+ response = click_element(session, button)
+ assert_error(response, "stale element reference")
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/element_retrieval/__init__.py b/tests/wpt/web-platform-tests/webdriver/tests/element_retrieval/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/tests/element_retrieval/__init__.py
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/element_retrieval/find_element.py b/tests/wpt/web-platform-tests/webdriver/tests/element_retrieval/find_element.py
new file mode 100644
index 00000000000..454e3c38bdc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/tests/element_retrieval/find_element.py
@@ -0,0 +1,83 @@
+import pytest
+
+from tests.support.asserts import assert_error, assert_same_element, assert_success
+from tests.support.inline import inline
+
+
+def find_element(session, using, value):
+ return session.transport.send("POST",
+ "session/%s/element" % session.session_id,
+ {"using": using, "value": value})
+
+
+# 12.2 Find Element
+
+@pytest.mark.parametrize("using", ["a", True, None, 1, [], {}])
+def test_invalid_using_argument(session, using):
+ # Step 1 - 2
+ response = find_element(session, using, "value")
+ assert_error(response, "invalid argument")
+
+
+@pytest.mark.parametrize("value", [None, [], {}])
+def test_invalid_selector_argument(session, value):
+ # Step 3 - 4
+ response = find_element(session, "css selector", value)
+ assert_error(response, "invalid argument")
+
+
+def test_closed_context(session, create_window):
+ # Step 5
+ new_window = create_window()
+ session.window_handle = new_window
+ session.close()
+
+ response = find_element(session, "css selector", "foo")
+
+ assert_error(response, "no such window")
+
+
+@pytest.mark.parametrize("using,value",
+ [("css selector", "#linkText"),
+ ("link text", "full link text"),
+ ("partial link text", "link text"),
+ ("tag name", "a"),
+ ("xpath", "//a")])
+def test_find_element(session, using, value):
+ # Step 8 - 9
+ session.url = inline("<a href=# id=linkText>full link text</a>")
+
+ response = find_element(session, using, value)
+ assert_success(response)
+
+
+@pytest.mark.parametrize("using,value", [("css selector", "#wontExist")])
+def test_no_element(session, using, value):
+ # Step 8 - 9
+ response = find_element(session, using, value)
+ assert_error(response, "no such element")
+
+
+@pytest.mark.parametrize("using,value",
+ [("css selector", "#linkText"),
+ ("link text", "full link text"),
+ ("partial link text", "link text"),
+ ("tag name", "a"),
+ ("xpath", "//*[name()='a']")])
+def test_xhtml_namespace(session, using, value):
+ session.url = inline("""<a href="#" id="linkText">full link text</a>""", doctype="xhtml")
+ expected = session.execute_script("return document.links[0]")
+
+ response = find_element(session, using, value)
+ value = assert_success(response)
+ assert_same_element(session, value, expected)
+
+
+@pytest.mark.parametrize("using,value",
+ [("css selector", ":root"),
+ ("tag name", "html"),
+ ("xpath", "/html")])
+def test_htmldocument(session, using, value):
+ session.url = inline("")
+ response = find_element(session, using, value)
+ assert_success(response)
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/element_retrieval/find_element_from_element.py b/tests/wpt/web-platform-tests/webdriver/tests/element_retrieval/find_element_from_element.py
new file mode 100644
index 00000000000..d79d512a13c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/tests/element_retrieval/find_element_from_element.py
@@ -0,0 +1,82 @@
+import pytest
+
+from tests.support.asserts import assert_error, assert_same_element, assert_success
+from tests.support.inline import inline
+
+
+def find_element(session, element, using, value):
+ return session.transport.send("POST",
+ "session/%s/element/%s/element" % (session.session_id, element),
+ {"using": using, "value": value})
+
+
+@pytest.mark.parametrize("using", ["a", True, None, 1, [], {}])
+def test_invalid_using_argument(session, using):
+ # Step 1 - 2
+ response = find_element(session, "notReal", using, "value")
+ assert_error(response, "invalid argument")
+
+
+@pytest.mark.parametrize("value", [None, [], {}])
+def test_invalid_selector_argument(session, value):
+ # Step 3 - 4
+ response = find_element(session, "notReal", "css selector", value)
+ assert_error(response, "invalid argument")
+
+
+def test_closed_context(session, create_window):
+ # Step 5
+ new_window = create_window()
+ session.window_handle = new_window
+ session.close()
+
+ response = find_element(session, "notReal", "css selector", "foo")
+
+ assert_error(response, "no such window")
+
+
+@pytest.mark.parametrize("using,value",
+ [("css selector", "#linkText"),
+ ("link text", "full link text"),
+ ("partial link text", "link text"),
+ ("tag name", "a"),
+ ("xpath", "//a")])
+def test_find_element(session, using, value):
+ # Step 8 - 9
+ session.url = inline("<div><a href=# id=linkText>full link text</a></div>")
+ element = session.find.css("div", all=False)
+ response = find_element(session, element.id, using, value)
+ assert_success(response)
+
+
+@pytest.mark.parametrize("using,value",[("css selector", "#wontExist")])
+def test_no_element(session, using, value):
+ # Step 8 - 9
+ session.url = inline("<div></div>")
+ element = session.find.css("div", all=False)
+ response = find_element(session, element.id, using, value)
+ assert_error(response, "no such element")
+
+
+@pytest.mark.parametrize("using,value",
+ [("css selector", "#linkText"),
+ ("link text", "full link text"),
+ ("partial link text", "link text"),
+ ("tag name", "a"),
+ ("xpath", "//*[name()='a']")])
+def test_xhtml_namespace(session, using, value):
+ session.url = inline("""<p><a href="#" id="linkText">full link text</a></p>""", doctype="xhtml")
+ from_element = session.execute_script("""return document.querySelector("p")""")
+ expected = session.execute_script("return document.links[0]")
+
+ response = find_element(session, from_element.id, using, value)
+ value = assert_success(response)
+ assert_same_element(session, value, expected)
+
+
+def test_parent_htmldocument(session):
+ session.url = inline("")
+ from_element = session.execute_script("return document.documentElement")
+
+ response = find_element(session, from_element.id, "xpath", "..")
+ assert_success(response)
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/element_retrieval/find_elements.py b/tests/wpt/web-platform-tests/webdriver/tests/element_retrieval/find_elements.py
new file mode 100644
index 00000000000..a00ae2358c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/tests/element_retrieval/find_elements.py
@@ -0,0 +1,91 @@
+import pytest
+
+from tests.support.asserts import assert_error, assert_same_element, assert_success
+from tests.support.inline import inline
+
+
+def find_elements(session, using, value):
+ return session.transport.send("POST",
+ "session/%s/elements" % session.session_id,
+ {"using": using, "value": value})
+
+
+@pytest.mark.parametrize("using", ["a", True, None, 1, [], {}])
+def test_invalid_using_argument(session, using):
+ # Step 1 - 2
+ response = find_elements(session, using, "value")
+ assert_error(response, "invalid argument")
+
+
+@pytest.mark.parametrize("value", [None, [], {}])
+def test_invalid_selector_argument(session, value):
+ # Step 3 - 4
+ response = find_elements(session, "css selector", value)
+ assert_error(response, "invalid argument")
+
+
+def test_closed_context(session, create_window):
+ # Step 5
+ new_window = create_window()
+ session.window_handle = new_window
+ session.close()
+
+ response = session.transport.send("POST",
+ "session/%s/elements" % session.session_id,
+ {"using": "css selector", "value": "foo"})
+
+ assert_error(response, "no such window")
+
+
+@pytest.mark.parametrize("using,value",
+ [("css selector", "#linkText"),
+ ("link text", "full link text"),
+ ("partial link text", "link text"),
+ ("tag name", "a"),
+ ("xpath", "//a")])
+def test_find_elements(session, using, value):
+ # Step 8 - 9
+ session.url = inline("<a href=# id=linkText>full link text</a>")
+
+ response = find_elements(session, using, value)
+ assert_success(response)
+ assert len(response.body["value"]) == 1
+
+
+@pytest.mark.parametrize("using,value", [("css selector", "#wontExist")])
+def test_no_element(session, using, value):
+ # Step 8 - 9
+ response = find_elements(session, using, value)
+ assert_success(response)
+ assert response.body["value"] == []
+
+
+@pytest.mark.parametrize("using,value",
+ [("css selector", "#linkText"),
+ ("link text", "full link text"),
+ ("partial link text", "link text"),
+ ("tag name", "a"),
+ ("xpath", "//*[name()='a']")])
+def test_xhtml_namespace(session, using, value):
+ session.url = inline("""<p><a href="#" id="linkText">full link text</a></p>""", doctype="xhtml")
+ expected = session.execute_script("return document.links[0]")
+
+ response = find_elements(session, using, value)
+ value = assert_success(response)
+ assert isinstance(value, list)
+ assert len(value) == 1
+
+ found_element = value[0]
+ assert_same_element(session, found_element, expected)
+
+
+@pytest.mark.parametrize("using,value",
+ [("css selector", ":root"),
+ ("tag name", "html"),
+ ("xpath", "/html")])
+def test_htmldocument(session, using, value):
+ session.url = inline("")
+ response = find_elements(session, using, value)
+ value = assert_success(response)
+ assert isinstance(value, list)
+ assert len(value) == 1
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/element_retrieval/find_elements_from_element.py b/tests/wpt/web-platform-tests/webdriver/tests/element_retrieval/find_elements_from_element.py
new file mode 100644
index 00000000000..486d7cb7aee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/tests/element_retrieval/find_elements_from_element.py
@@ -0,0 +1,87 @@
+import pytest
+
+from tests.support.asserts import assert_error, assert_same_element, assert_success
+from tests.support.inline import inline
+
+
+def find_elements(session, element, using, value):
+ return session.transport.send("POST",
+ "session/%s/element/%s/elements" % (session.session_id, element),
+ {"using": using, "value": value})
+
+@pytest.mark.parametrize("using", [("a"), (True), (None), (1), ([]), ({})])
+def test_invalid_using_argument(session, using):
+ # Step 1 - 2
+ response = find_elements(session, "notReal", using, "value")
+ assert_error(response, "invalid argument")
+
+
+@pytest.mark.parametrize("value", [None, [], {}])
+def test_invalid_selector_argument(session, value):
+ # Step 3 - 4
+ response = find_elements(session, "notReal", "css selector", value)
+ assert_error(response, "invalid argument")
+
+
+def test_closed_context(session, create_window):
+ # Step 5
+ new_window = create_window()
+ session.window_handle = new_window
+ session.close()
+
+ response = find_elements(session, "notReal", "css selector", "foo")
+
+ assert_error(response, "no such window")
+
+
+@pytest.mark.parametrize("using,value",
+ [("css selector", "#linkText"),
+ ("link text", "full link text"),
+ ("partial link text", "link text"),
+ ("tag name", "a"),
+ ("xpath", "//a")])
+def test_find_elements(session, using, value):
+ # Step 8 - 9
+ session.url = inline("<div><a href=# id=linkText>full link text</a></div>")
+ element = session.find.css("div", all=False)
+ response = find_elements(session, element.id, using, value)
+ assert_success(response)
+
+
+@pytest.mark.parametrize("using,value", [("css selector", "#wontExist")])
+def test_no_element(session, using, value):
+ # Step 8 - 9
+ session.url = inline("<div></div>")
+ element = session.find.css("div", all=False)
+ response = find_elements(session, element.id, using, value)
+ assert response.body["value"] == []
+
+
+@pytest.mark.parametrize("using,value",
+ [("css selector", "#linkText"),
+ ("link text", "full link text"),
+ ("partial link text", "link text"),
+ ("tag name", "a"),
+ ("xpath", "//*[name()='a']")])
+def test_xhtml_namespace(session, using, value):
+ session.url = inline("""<p><a href="#" id="linkText">full link text</a></p>""", doctype="xhtml")
+ from_element = session.execute_script("""return document.querySelector("p")""")
+ expected = session.execute_script("return document.links[0]")
+
+ response = find_elements(session, from_element.id, using, value)
+ value = assert_success(response)
+ assert isinstance(value, list)
+ assert len(value) == 1
+
+ found_element = value[0]
+ assert_same_element(session, found_element, expected)
+
+
+def test_parent_htmldocument(session):
+ session.url = inline("")
+ from_element = session.execute_script("return document.documentElement")
+
+ response = find_elements(session, from_element.id, "xpath", "..")
+ value = assert_success(response)
+ assert isinstance(value, list)
+ assert len(value) == 1
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/element_retrieval/get_active_element.py b/tests/wpt/web-platform-tests/webdriver/tests/element_retrieval/get_active_element.py
index 9bc6f732768..af3e1257a17 100644
--- a/tests/wpt/web-platform-tests/webdriver/tests/element_retrieval/get_active_element.py
+++ b/tests/wpt/web-platform-tests/webdriver/tests/element_retrieval/get_active_element.py
@@ -2,9 +2,11 @@ from tests.support.asserts import assert_error, assert_dialog_handled, assert_sa
from tests.support.fixtures import create_dialog
from tests.support.inline import inline
+
def read_global(session, name):
return session.execute_script("return %s;" % name)
+
def get_active_element(session):
return session.transport.send("GET", "session/%s/element/active" % session.session_id)
@@ -67,7 +69,7 @@ def test_handle_prompt_dismiss(new_session, add_browser_capabilites):
response = get_active_element(session)
assert_is_active_element(session, response)
assert_dialog_handled(session, "dismiss #2")
- assert read_global(session, "dismiss2") is None
+ assert read_global(session, "dismiss2") is False
create_dialog(session)("prompt", text="dismiss #3", result_var="dismiss3")
@@ -244,7 +246,7 @@ def test_success_iframe_content(session):
assert_is_active_element(session, response)
-def test_sucess_without_body(session):
+def test_missing_document_element(session):
session.url = inline("<body></body>")
session.execute_script("""
if (document.body.remove) {
@@ -254,4 +256,4 @@ def test_sucess_without_body(session):
}""")
response = get_active_element(session)
- assert_is_active_element(session, response)
+ assert_error(response, "no such element")
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/element_send_keys/__init__.py b/tests/wpt/web-platform-tests/webdriver/tests/element_send_keys/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/tests/element_send_keys/__init__.py
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/element_send_keys/interactability.py b/tests/wpt/web-platform-tests/webdriver/tests/element_send_keys/interactability.py
new file mode 100644
index 00000000000..5812f2b305f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/tests/element_send_keys/interactability.py
@@ -0,0 +1,136 @@
+from tests.support.asserts import assert_error, assert_same_element, assert_success
+from tests.support.inline import iframe, inline
+
+
+def send_keys_to_element(session, element, text):
+ return session.transport.send(
+ "POST",
+ "/session/{session_id}/element/{element_id}/value".format(
+ session_id=session.session_id,
+ element_id=element.id),
+ {"text": text})
+
+
+def test_body_is_interactable(session):
+ session.url = inline("""
+ <body onkeypress="document.getElementById('result').value += event.key">
+ <input type="text" id="result"/>
+ </body>
+ """)
+
+ element = session.find.css("body", all=False)
+ result = session.find.css("input", all=False)
+
+ # By default body is the active element
+ assert_same_element(session, element, session.active_element)
+
+ response = send_keys_to_element(session, element, "foo")
+ assert_success(response)
+ assert_same_element(session, element, session.active_element)
+ assert result.property("value") == "foo"
+
+
+def test_document_element_is_interactable(session):
+ session.url = inline("""
+ <html onkeypress="document.getElementById('result').value += event.key">
+ <input type="text" id="result"/>
+ </html>
+ """)
+
+ body = session.find.css("body", all=False)
+ element = session.find.css(":root", all=False)
+ result = session.find.css("input", all=False)
+
+ # By default body is the active element
+ assert_same_element(session, body, session.active_element)
+
+ response = send_keys_to_element(session, element, "foo")
+ assert_success(response)
+ assert_same_element(session, element, session.active_element)
+ assert result.property("value") == "foo"
+
+
+def test_iframe_is_interactable(session):
+ session.url = inline(iframe("""
+ <body onkeypress="document.getElementById('result').value += event.key">
+ <input type="text" id="result"/>
+ </body>
+ """))
+
+ body = session.find.css("body", all=False)
+ frame = session.find.css("iframe", all=False)
+
+ # By default the body has the focus
+ assert_same_element(session, body, session.active_element)
+
+ response = send_keys_to_element(session, frame, "foo")
+ assert_success(response)
+ assert_same_element(session, frame, session.active_element)
+
+ # Any key events are immediately routed to the nested
+ # browsing context's active document.
+ session.switch_frame(frame)
+ result = session.find.css("input", all=False)
+ assert result.property("value") == "foo"
+
+
+def test_transparent_element(session):
+ session.url = inline("<input style=\"opacity: 0;\">")
+ element = session.find.css("input", all=False)
+
+ response = send_keys_to_element(session, element, "foo")
+ assert_success(response)
+ assert element.property("value") == "foo"
+
+
+def test_readonly_element(session):
+ session.url = inline("<input readonly>")
+ element = session.find.css("input", all=False)
+
+ response = send_keys_to_element(session, element, "foo")
+ assert_success(response)
+ assert element.property("value") == ""
+
+
+def test_obscured_element(session):
+ session.url = inline("""
+ <input type="text" />
+ <div style="position: relative; top: -3em; height: 5em; background-color: blue"></div>
+ """)
+ element = session.find.css("input", all=False)
+
+ response = send_keys_to_element(session, element, "foo")
+ assert_success(response)
+ assert element.property("value") == "foo"
+
+
+def test_not_a_focusable_element(session):
+ session.url = inline("<div>foo</div>")
+ element = session.find.css("div", all=False)
+
+ response = send_keys_to_element(session, element, "foo")
+ assert_error(response, "element not interactable")
+
+
+def test_not_displayed_element(session):
+ session.url = inline("<input style=\"display: none\">")
+ element = session.find.css("input", all=False)
+
+ response = send_keys_to_element(session, element, "foo")
+ assert_error(response, "element not interactable")
+
+
+def test_hidden_element(session):
+ session.url = inline("<input style=\"visibility: hidden\">")
+ element = session.find.css("input", all=False)
+
+ response = send_keys_to_element(session, element, "foo")
+ assert_error(response, "element not interactable")
+
+
+def test_disabled_element(session):
+ session.url = inline("<input disabled=\"false\">")
+ element = session.find.css("input", all=False)
+
+ response = send_keys_to_element(session, element, "foo")
+ assert_error(response, "element not interactable")
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/element_send_keys/scroll_into_view.py b/tests/wpt/web-platform-tests/webdriver/tests/element_send_keys/scroll_into_view.py
new file mode 100644
index 00000000000..a1d454d1fe2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/tests/element_send_keys/scroll_into_view.py
@@ -0,0 +1,78 @@
+from tests.support.asserts import assert_success
+from tests.support.fixtures import is_element_in_viewport
+from tests.support.inline import inline
+
+
+def send_keys_to_element(session, element, text):
+ return session.transport.send(
+ "POST",
+ "/session/{session_id}/element/{element_id}/value".format(
+ session_id=session.session_id,
+ element_id=element.id),
+ {"text": text})
+
+
+def test_element_outside_of_not_scrollable_viewport(session):
+ session.url = inline("<input style=\"position: relative; left: -9999px;\">")
+ element = session.find.css("input", all=False)
+
+ response = send_keys_to_element(session, element, "foo")
+ assert_success(response)
+
+ assert not is_element_in_viewport(session, element)
+
+
+def test_element_outside_of_scrollable_viewport(session):
+ session.url = inline("<input style=\"margin-top: 102vh;\">")
+ element = session.find.css("input", all=False)
+
+ response = send_keys_to_element(session, element, "foo")
+ assert_success(response)
+
+ assert is_element_in_viewport(session, element)
+
+
+def test_option_select_container_outside_of_scrollable_viewport(session):
+ session.url = inline("""
+ <select style="margin-top: 102vh;">
+ <option value="foo">foo</option>
+ <option value="bar" id="bar">bar</option>
+ </select>
+ """)
+ element = session.find.css("option#bar", all=False)
+ select = session.find.css("select", all=False)
+
+ response = send_keys_to_element(session, element, "bar")
+ assert_success(response)
+
+ assert is_element_in_viewport(session, select)
+ assert is_element_in_viewport(session, element)
+
+
+def test_option_stays_outside_of_scrollable_viewport(session):
+ session.url = inline("""
+ <select multiple style="height: 105vh; margin-top: 100vh;">
+ <option value="foo" id="foo" style="height: 100vh;">foo</option>
+ <option value="bar" id="bar" style="background-color: yellow;">bar</option>
+ </select>
+ """)
+ select = session.find.css("select", all=False)
+ option_foo = session.find.css("option#foo", all=False)
+ option_bar = session.find.css("option#bar", all=False)
+
+ response = send_keys_to_element(session, option_bar, "bar")
+ assert_success(response)
+
+ assert is_element_in_viewport(session, select)
+ assert is_element_in_viewport(session, option_foo)
+ assert not is_element_in_viewport(session, option_bar)
+
+
+def test_contenteditable_element_outside_of_scrollable_viewport(session):
+ session.url = inline("<div contenteditable style=\"margin-top: 102vh;\"></div>")
+ element = session.find.css("div", all=False)
+
+ response = send_keys_to_element(session, element, "foo")
+ assert_success(response)
+
+ assert is_element_in_viewport(session, element)
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/execute_async_script/user_prompts.py b/tests/wpt/web-platform-tests/webdriver/tests/execute_async_script/user_prompts.py
new file mode 100644
index 00000000000..03e1762d8b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/tests/execute_async_script/user_prompts.py
@@ -0,0 +1,60 @@
+import pytest
+
+from webdriver import error
+
+
+# 15.2 Executing Script
+
+def test_handle_prompt_accept(new_session, add_browser_capabilites):
+ _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept"})}})
+ session.execute_async_script("window.alert('Hello');")
+ with pytest.raises(error.NoSuchAlertException):
+ session.alert.accept()
+
+
+def test_handle_prompt_dismiss(new_session, add_browser_capabilites):
+ _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "dismiss"})}})
+ session.execute_async_script("window.alert('Hello');")
+ with pytest.raises(error.NoSuchAlertException):
+ session.alert.dismiss()
+
+
+def test_handle_prompt_dismiss_and_notify(new_session, add_browser_capabilites):
+ _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "dismiss and notify"})}})
+ with pytest.raises(error.UnexpectedAlertOpenException):
+ session.execute_async_script("window.alert('Hello');")
+ with pytest.raises(error.NoSuchAlertException):
+ session.alert.dismiss()
+
+
+def test_handle_prompt_accept_and_notify(new_session, add_browser_capabilites):
+ _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept and notify"})}})
+ with pytest.raises(error.UnexpectedAlertOpenException):
+ session.execute_async_script("window.alert('Hello');")
+ with pytest.raises(error.NoSuchAlertException):
+ session.alert.accept()
+
+
+def test_handle_prompt_ignore(new_session, add_browser_capabilites):
+ _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "ignore"})}})
+ with pytest.raises(error.UnexpectedAlertOpenException):
+ session.execute_async_script("window.alert('Hello');")
+ session.alert.dismiss()
+
+
+def test_handle_prompt_default(new_session, add_browser_capabilites):
+ _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({})}})
+ with pytest.raises(error.UnexpectedAlertOpenException):
+ session.execute_async_script("window.alert('Hello');")
+ with pytest.raises(error.NoSuchAlertException):
+ session.alert.dismiss()
+
+
+def test_handle_prompt_twice(new_session, add_browser_capabilites):
+ _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept"})}})
+ session.execute_async_script("window.alert('Hello');window.alert('Bye');")
+ # The first alert has been accepted by the user prompt handler, the second one remains.
+ # FIXME: this is how browsers currently work, but the spec should clarify if this is the
+ # expected behavior, see https://github.com/w3c/webdriver/issues/1153.
+ assert session.alert.text == "Bye"
+ session.alert.dismiss()
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/execute_script/cyclic.py b/tests/wpt/web-platform-tests/webdriver/tests/execute_script/cyclic.py
new file mode 100644
index 00000000000..ae9d2f5775c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/tests/execute_script/cyclic.py
@@ -0,0 +1,48 @@
+from tests.support.asserts import assert_error
+
+
+def execute_script(session, script, args=None):
+ if args is None:
+ args = []
+ body = {"script": script, "args": args}
+ return session.transport.send(
+ "POST",
+ "/session/{session_id}/execute/sync".format(
+ session_id=session.session_id),
+ body)
+
+
+def test_array(session):
+ response = execute_script(session, """
+ let arr = [];
+ arr.push(arr);
+ return arr;
+ """)
+ assert_error(response, "javascript error")
+
+
+def test_object(session):
+ response = execute_script(session, """
+ let obj = {};
+ obj.reference = obj;
+ return obj;
+ """)
+ assert_error(response, "javascript error")
+
+
+def test_array_in_object(session):
+ response = execute_script(session, """
+ let arr = [];
+ arr.push(arr);
+ return {arr};
+ """)
+ assert_error(response, "javascript error")
+
+
+def test_object_in_array(session):
+ response = execute_script(session, """
+ let obj = {};
+ obj.reference = obj;
+ return [obj];
+ """)
+ assert_error(response, "javascript error")
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/execute_script/user_prompts.py b/tests/wpt/web-platform-tests/webdriver/tests/execute_script/user_prompts.py
new file mode 100644
index 00000000000..8d91bdd8f9f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/tests/execute_script/user_prompts.py
@@ -0,0 +1,60 @@
+import pytest
+
+from webdriver import error
+
+
+# 15.2 Executing Script
+
+def test_handle_prompt_accept(new_session, add_browser_capabilites):
+ _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept"})}})
+ session.execute_script("window.alert('Hello');")
+ with pytest.raises(error.NoSuchAlertException):
+ session.alert.accept()
+
+
+def test_handle_prompt_dismiss(new_session, add_browser_capabilites):
+ _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "dismiss"})}})
+ session.execute_script("window.alert('Hello');")
+ with pytest.raises(error.NoSuchAlertException):
+ session.alert.dismiss()
+
+
+def test_handle_prompt_dismiss_and_notify(new_session, add_browser_capabilites):
+ _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "dismiss and notify"})}})
+ with pytest.raises(error.UnexpectedAlertOpenException):
+ session.execute_script("window.alert('Hello');")
+ with pytest.raises(error.NoSuchAlertException):
+ session.alert.dismiss()
+
+
+def test_handle_prompt_accept_and_notify(new_session, add_browser_capabilites):
+ _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept and notify"})}})
+ with pytest.raises(error.UnexpectedAlertOpenException):
+ session.execute_script("window.alert('Hello');")
+ with pytest.raises(error.NoSuchAlertException):
+ session.alert.accept()
+
+
+def test_handle_prompt_ignore(new_session, add_browser_capabilites):
+ _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "ignore"})}})
+ with pytest.raises(error.UnexpectedAlertOpenException):
+ session.execute_script("window.alert('Hello');")
+ session.alert.dismiss()
+
+
+def test_handle_prompt_default(new_session, add_browser_capabilites):
+ _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({})}})
+ with pytest.raises(error.UnexpectedAlertOpenException):
+ session.execute_script("window.alert('Hello');")
+ with pytest.raises(error.NoSuchAlertException):
+ session.alert.dismiss()
+
+
+def test_handle_prompt_twice(new_session, add_browser_capabilites):
+ _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({"unhandledPromptBehavior": "accept"})}})
+ session.execute_script("window.alert('Hello');window.alert('Bye');")
+ # The first alert has been accepted by the user prompt handler, the second one remains.
+ # FIXME: this is how browsers currently work, but the spec should clarify if this is the
+ # expected behavior, see https://github.com/w3c/webdriver/issues/1153.
+ assert session.alert.text == "Bye"
+ session.alert.dismiss()
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/get_window_rect.py b/tests/wpt/web-platform-tests/webdriver/tests/get_window_rect.py
index b25ca28692f..cb3398ecccc 100644
--- a/tests/wpt/web-platform-tests/webdriver/tests/get_window_rect.py
+++ b/tests/wpt/web-platform-tests/webdriver/tests/get_window_rect.py
@@ -151,11 +151,10 @@ def test_payload(session):
assert response.status == 200
assert isinstance(response.body["value"], dict)
value = response.body["value"]
- assert "width" in value
- assert "height" in value
- assert "x" in value
- assert "y" in value
- assert isinstance(value["width"], int)
- assert isinstance(value["height"], int)
- assert isinstance(value["x"], int)
- assert isinstance(value["y"], int)
+ expected = session.execute_script("""return {
+ x: window.screenX,
+ y: window.screenY,
+ width: window.outerWidth,
+ height: window.outerHeight
+ }""")
+ assert expected == value
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/interaction/element_clear.py b/tests/wpt/web-platform-tests/webdriver/tests/interaction/element_clear.py
index 07122906ac1..f9755f784e5 100644
--- a/tests/wpt/web-platform-tests/webdriver/tests/interaction/element_clear.py
+++ b/tests/wpt/web-platform-tests/webdriver/tests/interaction/element_clear.py
@@ -147,9 +147,9 @@ def test_clear_content_editable_resettable_element(session, element):
url = element[1] + """<input id=focusCheck type=checkbox>
<input id=blurCheck type=checkbox>
<script>
- var id = %s
- document.getElementById("id").addEventListener("focus", checkFocus);
- document.getElementById("id").addEventListener("blur", checkBlur);
+ var id = "%s";
+ document.getElementById(id).addEventListener("focus", checkFocus);
+ document.getElementById(id).addEventListener("blur", checkBlur);
document.getElementById("empty").addEventListener("focus", checkFocus);
document.getElementById("empty").addEventListener("blur", checkBlur);
@@ -163,15 +163,15 @@ def test_clear_content_editable_resettable_element(session, element):
session.url = inline(url)
# Step 1
empty_element = session.find.css("#empty", all=False)
- test_clear_element_helper(session, empty_element, False)
+ clear_element_test_helper(session, empty_element, False)
session.execute_script("document.getElementById(\"focusCheck\").checked = false;")
session.execute_script("document.getElementById(\"blurCheck\").checked = false;")
# Step 2 - 4
test_element = session.find.css("#" + element[0], all=False)
- test_clear_element_helper(session, test_element, True)
+ clear_element_test_helper(session, test_element, True)
-def test_clear_element_helper(session, element, value):
+def clear_element_test_helper(session, element, value):
response = clear(session, element)
assert_success(response)
response = session.execute_script("return document.getElementById(\"focusCheck\").checked;")
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/interface.html b/tests/wpt/web-platform-tests/webdriver/tests/interface.html
index 143a8643f3c..31637285e40 100644
--- a/tests/wpt/web-platform-tests/webdriver/tests/interface.html
+++ b/tests/wpt/web-platform-tests/webdriver/tests/interface.html
@@ -1,15 +1,38 @@
-<!doctype html>
-<meta charset=utf-8>
-<title>WebDriver interface test</title>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
+<!DOCTYPE html>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
<script src=/resources/WebIDLParser.js></script>
<script src=/resources/idlharness.js></script>
+<script type=text/plain class=untested>
+[Exposed=Window]
+interface Navigator {
+ // objects implementing this interface also implement the interfaces given below
+};
+</script>
+<script type=text/plain>
+Navigator includes NavigatorAutomationInformation;
+interface mixin NavigatorAutomationInformation {
+ readonly attribute boolean webdriver;
+ // always returns true
+};
+</script>
<script>
-var t = new IdlArray();
-t.add_untested_idls("interface Navigator {};");
-t.add_idls("partial interface Navigator { readonly attribute boolean webdriver; };");
-t.add_objects({Navigator: ["navigator"]});
-t.test();
+"use strict";
+
+if ("webdriver" in navigator) {
+ test(() => assert_true(navigator.webdriver), "navigator.webdriver is always true");
+ var idlArray = new IdlArray();
+ [].forEach.call(document.querySelectorAll("script[type=text\\/plain]"), function(node) {
+ if (node.className == "untested") {
+ idlArray.add_untested_idls(node.textContent);
+ } else {
+ idlArray.add_idls(node.textContent);
+ }
+ });
+ idlArray.test();
+} else {
+ done();
+}
</script>
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/navigation/current_url.py b/tests/wpt/web-platform-tests/webdriver/tests/navigation/current_url.py
index 45e462fb8e1..b3dfe1ffbd7 100644
--- a/tests/wpt/web-platform-tests/webdriver/tests/navigation/current_url.py
+++ b/tests/wpt/web-platform-tests/webdriver/tests/navigation/current_url.py
@@ -4,6 +4,7 @@ import types
from tests.support.inline import inline
from tests.support.asserts import assert_error, assert_success
+from tests.support.wait import wait
alert_doc = inline("<script>window.alert()</script>")
frame_doc = inline("<p>frame")
@@ -75,8 +76,11 @@ def test_set_malformed_url(session):
assert_error(result, "invalid argument")
def test_get_current_url_after_modified_location(session):
+ start = session.transport.send("GET", "session/%s/url" % session.session_id)
session.execute_script("window.location.href = 'about:blank#wd_test_modification'")
-
+ wait(session,
+ lambda s: s.transport.send("GET", "session/%s/url" % session.session_id) != start.body["value"],
+ "URL did not change")
result = session.transport.send("GET", "session/%s/url" % session.session_id)
assert_success(result, "about:blank#wd_test_modification")
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/retrieval/find_element.py b/tests/wpt/web-platform-tests/webdriver/tests/retrieval/find_element.py
deleted file mode 100644
index a0047eb9f08..00000000000
--- a/tests/wpt/web-platform-tests/webdriver/tests/retrieval/find_element.py
+++ /dev/null
@@ -1,73 +0,0 @@
-import pytest
-
-from tests.support.asserts import assert_error, assert_same_element, assert_success
-from tests.support.inline import inline
-
-
-def find_element(session, using, value):
- return session.transport.send("POST",
- "session/%s/element" % session.session_id,
- {"using": using, "value": value})
-
-
-# 12.2 Find Element
-
-@pytest.mark.parametrize("using", ["a", True, None, 1, [], {}])
-def test_invalid_using_argument(session, using):
- # Step 1 - 2
- response = find_element(session, using, "value")
- assert_error(response, "invalid argument")
-
-
-@pytest.mark.parametrize("value", [None, [], {}])
-def test_invalid_selector_argument(session, value):
- # Step 3 - 4
- response = find_element(session, "css selector", value)
- assert_error(response, "invalid argument")
-
-
-def test_closed_context(session, create_window):
- # Step 5
- new_window = create_window()
- session.window_handle = new_window
- session.close()
-
- response = find_element(session, "css selector", "foo")
-
- assert_error(response, "no such window")
-
-
-@pytest.mark.parametrize("using,value",
- [("css selector", "#linkText"),
- ("link text", "full link text"),
- ("partial link text", "link text"),
- ("tag name", "a"),
- ("xpath", "//a")])
-def test_find_element(session, using, value):
- # Step 8 - 9
- session.url = inline("<a href=# id=linkText>full link text</a>")
-
- response = find_element(session, using, value)
- assert_success(response)
-
-
-@pytest.mark.parametrize("using,value", [("css selector", "#wontExist")])
-def test_no_element(session, using, value):
- # Step 8 - 9
- response = find_element(session, using, value)
- assert_error(response, "no such element")
-
-
-@pytest.mark.parametrize("using,value",
- [("css selector", "#linkText"),
- ("link text", "full link text"),
- ("partial link text", "link text"),
- ("tag name", "a"),
- ("xpath", "//*[name()='a']")])
-def test_xhtml_namespace(session, using, value):
- session.url = inline("""<a href="#" id="linkText">full link text</a>""", doctype="xhtml")
- expected = session.execute_script("return document.links[0]")
-
- response = find_element(session, using, value)
- value = assert_success(response)
- assert_same_element(session, value, expected)
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/retrieval/find_element_from_element.py b/tests/wpt/web-platform-tests/webdriver/tests/retrieval/find_element_from_element.py
deleted file mode 100644
index 3bf1d860bd4..00000000000
--- a/tests/wpt/web-platform-tests/webdriver/tests/retrieval/find_element_from_element.py
+++ /dev/null
@@ -1,74 +0,0 @@
-import pytest
-
-from tests.support.asserts import assert_error, assert_same_element, assert_success
-from tests.support.inline import inline
-
-
-def find_element(session, element, using, value):
- return session.transport.send("POST",
- "session/%s/element/%s/element" % (session.session_id, element),
- {"using": using, "value": value})
-
-
-@pytest.mark.parametrize("using", ["a", True, None, 1, [], {}])
-def test_invalid_using_argument(session, using):
- # Step 1 - 2
- response = find_element(session, "notReal", using, "value")
- assert_error(response, "invalid argument")
-
-
-@pytest.mark.parametrize("value", [None, [], {}])
-def test_invalid_selector_argument(session, value):
- # Step 3 - 4
- response = find_element(session, "notReal", "css selector", value)
- assert_error(response, "invalid argument")
-
-
-def test_closed_context(session, create_window):
- # Step 5
- new_window = create_window()
- session.window_handle = new_window
- session.close()
-
- response = find_element(session, "notReal", "css selector", "foo")
-
- assert_error(response, "no such window")
-
-
-@pytest.mark.parametrize("using,value",
- [("css selector", "#linkText"),
- ("link text", "full link text"),
- ("partial link text", "link text"),
- ("tag name", "a"),
- ("xpath", "//a")])
-def test_find_element(session, using, value):
- # Step 8 - 9
- session.url = inline("<div><a href=# id=linkText>full link text</a></div>")
- element = session.find.css("div", all=False)
- response = find_element(session, element.id, using, value)
- assert_success(response)
-
-
-@pytest.mark.parametrize("using,value",[("css selector", "#wontExist")])
-def test_no_element(session, using, value):
- # Step 8 - 9
- session.url = inline("<div></div>")
- element = session.find.css("div", all=False)
- response = find_element(session, element.id, using, value)
- assert_error(response, "no such element")
-
-
-@pytest.mark.parametrize("using,value",
- [("css selector", "#linkText"),
- ("link text", "full link text"),
- ("partial link text", "link text"),
- ("tag name", "a"),
- ("xpath", "//*[name()='a']")])
-def test_xhtml_namespace(session, using, value):
- session.url = inline("""<p><a href="#" id="linkText">full link text</a></p>""", doctype="xhtml")
- from_element = session.execute_script("""return document.querySelector("p")""")
- expected = session.execute_script("return document.links[0]")
-
- response = find_element(session, from_element.id, using, value)
- value = assert_success(response)
- assert_same_element(session, value, expected)
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/retrieval/find_element_from_elements.py b/tests/wpt/web-platform-tests/webdriver/tests/retrieval/find_element_from_elements.py
deleted file mode 100644
index 933d69d1e60..00000000000
--- a/tests/wpt/web-platform-tests/webdriver/tests/retrieval/find_element_from_elements.py
+++ /dev/null
@@ -1,77 +0,0 @@
-import pytest
-
-from tests.support.asserts import assert_error, assert_same_element, assert_success
-from tests.support.inline import inline
-
-
-def find_elements(session, element, using, value):
- return session.transport.send("POST",
- "session/%s/element/%s/elements" % (session.session_id, element),
- {"using": using, "value": value})
-
-@pytest.mark.parametrize("using", [("a"), (True), (None), (1), ([]), ({})])
-def test_invalid_using_argument(session, using):
- # Step 1 - 2
- response = find_elements(session, "notReal", using, "value")
- assert_error(response, "invalid argument")
-
-
-@pytest.mark.parametrize("value", [None, [], {}])
-def test_invalid_selector_argument(session, value):
- # Step 3 - 4
- response = find_elements(session, "notReal", "css selector", value)
- assert_error(response, "invalid argument")
-
-
-def test_closed_context(session, create_window):
- # Step 5
- new_window = create_window()
- session.window_handle = new_window
- session.close()
-
- response = find_elements(session, "notReal", "css selector", "foo")
-
- assert_error(response, "no such window")
-
-
-@pytest.mark.parametrize("using,value",
- [("css selector", "#linkText"),
- ("link text", "full link text"),
- ("partial link text", "link text"),
- ("tag name", "a"),
- ("xpath", "//a")])
-def test_find_elements(session, using, value):
- # Step 8 - 9
- session.url = inline("<div><a href=# id=linkText>full link text</a></div>")
- element = session.find.css("div", all=False)
- response = find_elements(session, element.id, using, value)
- assert_success(response)
-
-
-@pytest.mark.parametrize("using,value", [("css selector", "#wontExist")])
-def test_no_element(session, using, value):
- # Step 8 - 9
- session.url = inline("<div></div>")
- element = session.find.css("div", all=False)
- response = find_elements(session, element.id, using, value)
- assert response.body["value"] == []
-
-
-@pytest.mark.parametrize("using,value",
- [("css selector", "#linkText"),
- ("link text", "full link text"),
- ("partial link text", "link text"),
- ("tag name", "a"),
- ("xpath", "//*[name()='a']")])
-def test_xhtml_namespace(session, using, value):
- session.url = inline("""<p><a href="#" id="linkText">full link text</a></p>""", doctype="xhtml")
- from_element = session.execute_script("""return document.querySelector("p")""")
- expected = session.execute_script("return document.links[0]")
-
- response = find_elements(session, from_element.id, using, value)
- value = assert_success(response)
- assert isinstance(value, list)
- assert len(value) == 1
-
- found_element = value[0]
- assert_same_element(session, found_element, expected)
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/retrieval/find_elements.py b/tests/wpt/web-platform-tests/webdriver/tests/retrieval/find_elements.py
deleted file mode 100644
index 8bc2113a84a..00000000000
--- a/tests/wpt/web-platform-tests/webdriver/tests/retrieval/find_elements.py
+++ /dev/null
@@ -1,79 +0,0 @@
-import pytest
-
-from tests.support.asserts import assert_error, assert_same_element, assert_success
-from tests.support.inline import inline
-
-
-def find_elements(session, using, value):
- return session.transport.send("POST",
- "session/%s/elements" % session.session_id,
- {"using": using, "value": value})
-
-
-@pytest.mark.parametrize("using", ["a", True, None, 1, [], {}])
-def test_invalid_using_argument(session, using):
- # Step 1 - 2
- response = find_elements(session, using, "value")
- assert_error(response, "invalid argument")
-
-
-@pytest.mark.parametrize("value", [None, [], {}])
-def test_invalid_selector_argument(session, value):
- # Step 3 - 4
- response = find_elements(session, "css selector", value)
- assert_error(response, "invalid argument")
-
-
-def test_closed_context(session, create_window):
- # Step 5
- new_window = create_window()
- session.window_handle = new_window
- session.close()
-
- response = session.transport.send("POST",
- "session/%s/elements" % session.session_id,
- {"using": "css selector", "value": "foo"})
-
- assert_error(response, "no such window")
-
-
-@pytest.mark.parametrize("using,value",
- [("css selector", "#linkText"),
- ("link text", "full link text"),
- ("partial link text", "link text"),
- ("tag name", "a"),
- ("xpath", "//a")])
-def test_find_elements(session, using, value):
- # Step 8 - 9
- session.url = inline("<a href=# id=linkText>full link text</a>")
-
- response = find_elements(session, using, value)
- assert_success(response)
- assert len(response.body["value"]) == 1
-
-
-@pytest.mark.parametrize("using,value", [("css selector", "#wontExist")])
-def test_no_element(session, using, value):
- # Step 8 - 9
- response = find_elements(session, using, value)
- assert_success(response)
- assert response.body["value"] == []
-
-
-@pytest.mark.parametrize("using,value",
- [("css selector", "#linkText"),
- ("link text", "full link text"),
- ("partial link text", "link text"),
- ("tag name", "a"),
- ("xpath", "//*[name()='a']")])
-def test_xhtml_namespace(session, using, value):
- session.url = inline("""<p><a href="#" id="linkText">full link text</a></p>""", doctype="xhtml")
- expected = session.execute_script("return document.links[0]")
-
- response = find_elements(session, using, value)
- value = assert_success(response)
- assert isinstance(value, list)
- assert len(value) == 1
-
- found_element = value[0]
- assert_same_element(session, found_element, expected)
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/sessions/status.py b/tests/wpt/web-platform-tests/webdriver/tests/sessions/status.py
new file mode 100644
index 00000000000..892ce927145
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/tests/sessions/status.py
@@ -0,0 +1,45 @@
+import pytest
+import json
+
+
+def test_get_status_no_session(http):
+ with http.get("/status") as response:
+ # GET /status should never return an error
+ assert response.status == 200
+
+ # parse JSON response and unwrap 'value' property
+ parsed_obj = json.loads(response.read().decode('utf-8'))
+ value = parsed_obj["value"]
+
+ # Let body be a new JSON Object with the following properties:
+ # "ready"
+ # The remote end's readiness state.
+ assert value["ready"] in [True, False]
+ # "message"
+ # An implementation-defined string explaining the remote end's
+ # readiness state.
+ assert isinstance(value["message"], basestring)
+
+
+def test_status_with_session_running_on_endpoint_node(new_session, add_browser_capabilites):
+ # For an endpoint node, the maximum number of active
+ # sessions is 1: https://www.w3.org/TR/webdriver/#dfn-maximum-active-sessions
+ # A session is open, so we expect `ready` to be False
+ # 8.3 step 1.
+
+ _, session = new_session({"capabilities": {"alwaysMatch": add_browser_capabilites({})}})
+ value = session.send_command("GET", "status")
+
+ assert value["ready"] == False
+ assert "message" in value
+
+ session.end()
+
+ # Active session count is 0, meaning that the
+ # readiness state of the server should be True
+ # 8.3 step 1. Again
+ value = session.send_command("GET", "status")
+
+ assert value["ready"] == True
+ assert "message" in value
+
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/status.py b/tests/wpt/web-platform-tests/webdriver/tests/status.py
deleted file mode 100644
index 9472f8a80bb..00000000000
--- a/tests/wpt/web-platform-tests/webdriver/tests/status.py
+++ /dev/null
@@ -1,21 +0,0 @@
-import pytest
-import json
-
-
-def test_get_status_no_session(http):
- with http.get("/status") as response:
- # GET /status should never return an error
- assert response.status == 200
-
- # parse JSON response and unwrap 'value' property
- parsed_obj = json.loads(response.read().decode('utf-8'))
- value = parsed_obj["value"]
-
- # Let body be a new JSON Object with the following properties:
- # "ready"
- # The remote end's readiness state.
- assert value["ready"] in [True, False]
- # "message"
- # An implementation-defined string explaining the remote end's
- # readiness state.
- assert isinstance(value["message"], basestring)
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/support/asserts.py b/tests/wpt/web-platform-tests/webdriver/tests/support/asserts.py
index c68883a631e..95859ac3d2b 100644
--- a/tests/wpt/web-platform-tests/webdriver/tests/support/asserts.py
+++ b/tests/wpt/web-platform-tests/webdriver/tests/support/asserts.py
@@ -1,5 +1,6 @@
from webdriver import Element, WebDriverException
+
# WebDriver specification ID: dfn-error-response-data
errors = {
"element click intercepted": 400,
@@ -21,7 +22,7 @@ errors = {
"no such window": 404,
"script timeout": 408,
"session not created": 500,
- "stale element reference": 400,
+ "stale element reference": 404,
"timeout": 408,
"unable to set cookie": 500,
"unable to capture screen": 500,
@@ -32,6 +33,7 @@ errors = {
"unsupported operation": 500,
}
+
# WebDriver specification ID: dfn-send-an-error
#
# > When required to send an error, with error code, a remote end must run the
@@ -54,12 +56,13 @@ errors = {
# >
# > 5. Send a response with status and data as arguments.
def assert_error(response, error_code):
- """Verify that the provided wdclient.Response instance described a valid
- error response as defined by `dfn-send-an-error` and the provided error
- code.
+ """
+ Verify that the provided webdriver.Response instance described
+ a valid error response as defined by `dfn-send-an-error` and
+ the provided error code.
- :param response: wdclient.Response instance
- :param error_code: string value of the expected "error code"
+ :param response: ``webdriver.Response`` instance.
+ :param error_code: String value of the expected error code
"""
assert response.status == errors[error_code]
assert "value" in response.body
@@ -69,13 +72,13 @@ def assert_error(response, error_code):
def assert_success(response, value=None):
- """Verify that the provided wdclient.Response instance described a valid
- error response as defined by `dfn-send-an-error` and the provided error
- code.
+ """
+ Verify that the provided webdriver.Response instance described
+ a valid error response as defined by `dfn-send-an-error` and
+ the provided error code.
- :param response: wdclient.Response instance.
+ :param response: ``webdriver.Response`` instance.
:param value: Expected value of the response body, if any.
-
"""
assert response.status == 200, str(response.error)
@@ -97,7 +100,7 @@ def assert_dialog_handled(session, expected_text):
except:
assert (result.status == 200 and
result.body["value"] != expected_text), (
- "Dialog with text '%s' was not handled." % expected_text)
+ "Dialog with text '%s' was not handled." % expected_text)
def assert_same_element(session, a, b):
@@ -122,7 +125,7 @@ def assert_same_element(session, a, b):
return
message = ("Expected element references to describe the same element, " +
- "but they did not.")
+ "but they did not.")
# Attempt to provide more information, accounting for possible errors such
# as stale element references or not visible elements.
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/support/fixtures.py b/tests/wpt/web-platform-tests/webdriver/tests/support/fixtures.py
index 778acd314c6..844ae039e57 100644
--- a/tests/wpt/web-platform-tests/webdriver/tests/support/fixtures.py
+++ b/tests/wpt/web-platform-tests/webdriver/tests/support/fixtures.py
@@ -8,6 +8,7 @@ import mozlog
from tests.support.asserts import assert_error
from tests.support.http_request import HTTPRequest
+from tests.support.wait import wait
from tests.support import merge_dictionaries
default_host = "http://127.0.0.1"
@@ -254,10 +255,31 @@ def create_dialog(session):
session.send_session_command("POST",
"execute/async",
{"script": spawn, "args": []})
+ wait(session,
+ lambda s: s.send_session_command("GET", "alert/text") == text,
+ "modal has not appeared",
+ timeout=15,
+ ignored_exceptions=webdriver.NoSuchAlertException)
return create_dialog
+
def clear_all_cookies(session):
"""Removes all cookies associated with the current active document"""
session.transport.send("DELETE", "session/%s/cookie" % session.session_id)
+
+def is_element_in_viewport(session, element):
+ """Check if element is outside of the viewport"""
+ return session.execute_script("""
+ let el = arguments[0];
+
+ let rect = el.getBoundingClientRect();
+ let viewport = {
+ height: window.innerHeight || document.documentElement.clientHeight,
+ width: window.innerWidth || document.documentElement.clientWidth,
+ };
+
+ return !(rect.right < 0 || rect.bottom < 0 ||
+ rect.left > viewport.width || rect.top > viewport.height)
+ """, args=(element,))
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/support/wait.py b/tests/wpt/web-platform-tests/webdriver/tests/support/wait.py
index f645abe7367..6f439ec61a3 100644
--- a/tests/wpt/web-platform-tests/webdriver/tests/support/wait.py
+++ b/tests/wpt/web-platform-tests/webdriver/tests/support/wait.py
@@ -1,10 +1,13 @@
+import sys
import time
+
class TimeoutException(Exception):
pass
-def wait(session, condition, message, interval=0.1, timeout=5):
+def wait(session, condition, message,
+ interval=0.1, timeout=5, ignored_exceptions=Exception):
""" Poll a condition until it's true or the timeout ellapses.
:param session: WebDriver session to use with `condition`
@@ -12,6 +15,8 @@ def wait(session, condition, message, interval=0.1, timeout=5):
:param message: failure description to display in case the timeout is reached
:param interval: seconds between each call to `condition`. Default: 0.1
:param timeout: seconds until we stop polling. Default: 5
+ :param ignored_exceptions: Exceptions that are expected and can be ignored.
+ Default: Exception
"""
start = time.time()
@@ -19,10 +24,15 @@ def wait(session, condition, message, interval=0.1, timeout=5):
while not (time.time() >= end):
next_step = time.time() + interval
- success = condition(session)
+ try:
+ success = condition(session)
+ except ignored_exceptions:
+ last_exc = sys.exc_info()[0]
+ success = False
next_interval = max(next_step - time.time(), 0)
if not success:
time.sleep(next_interval)
continue
return success
+
raise TimeoutException("Timed out after %d seconds: %s" % (timeout, message))
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/user_prompts/accept_alert.py b/tests/wpt/web-platform-tests/webdriver/tests/user_prompts/accept_alert.py
index d97aa73739a..d47ed1c8627 100644
--- a/tests/wpt/web-platform-tests/webdriver/tests/user_prompts/accept_alert.py
+++ b/tests/wpt/web-platform-tests/webdriver/tests/user_prompts/accept_alert.py
@@ -1,4 +1,5 @@
from tests.support.asserts import assert_error, assert_success
+from tests.support.inline import inline
def accept_alert(session):
@@ -25,14 +26,14 @@ def test_no_user_prompt(session):
def test_accept_alert(session):
# 18.2 step 3
- session.execute_script("window.alert(\"Hello\");")
+ session.url = inline("<script>window.alert('Hello');</script>")
response = accept_alert(session)
assert_success(response)
def test_accept_confirm(session):
# 18.2 step 3
- session.execute_script("window.result = window.confirm(\"Hello\");")
+ session.url = inline("<script>window.result = window.confirm('Hello');</script>")
response = accept_alert(session)
assert_success(response)
assert session.execute_script("return window.result") is True
@@ -40,7 +41,7 @@ def test_accept_confirm(session):
def test_accept_prompt(session):
# 18.2 step 3
- session.execute_script("window.result = window.prompt(\"Enter Your Name: \", \"Federer\");")
+ session.url = inline("<script>window.result = window.prompt('Enter Your Name: ', 'Federer');</script>")
response = accept_alert(session)
assert_success(response)
assert session.execute_script("return window.result") == "Federer"
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/user_prompts/dismiss_alert.py b/tests/wpt/web-platform-tests/webdriver/tests/user_prompts/dismiss_alert.py
index 73f9822fc57..6a2049684a6 100644
--- a/tests/wpt/web-platform-tests/webdriver/tests/user_prompts/dismiss_alert.py
+++ b/tests/wpt/web-platform-tests/webdriver/tests/user_prompts/dismiss_alert.py
@@ -1,4 +1,5 @@
from tests.support.asserts import assert_error, assert_success
+from tests.support.inline import inline
def dismiss_alert(session):
@@ -25,14 +26,14 @@ def test_no_user_prompt(session):
def test_dismiss_alert(session):
# 18.1 step 3
- session.execute_script("window.alert(\"Hello\");")
+ session.url = inline("<script>window.alert('Hello');</script>")
response = dismiss_alert(session)
assert_success(response)
def test_dismiss_confirm(session):
# 18.1 step 3
- session.execute_script("window.result = window.confirm(\"Hello\");")
+ session.url = inline("<script>window.result = window.confirm('Hello');</script>")
response = dismiss_alert(session)
assert_success(response)
assert session.execute_script("return window.result;") is False
@@ -40,7 +41,7 @@ def test_dismiss_confirm(session):
def test_dismiss_prompt(session):
# 18.1 step 3
- session.execute_script("window.result = window.prompt(\"Enter Your Name: \", \"Federer\");")
+ session.url = inline("<script>window.result = window.prompt('Enter Your Name: ', 'Federer');</script>")
response = dismiss_alert(session)
assert_success(response)
assert session.execute_script("return window.result") is None
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/user_prompts/get_alert_text.py b/tests/wpt/web-platform-tests/webdriver/tests/user_prompts/get_alert_text.py
index 85506eea4f2..7b71f7f4fd1 100644
--- a/tests/wpt/web-platform-tests/webdriver/tests/user_prompts/get_alert_text.py
+++ b/tests/wpt/web-platform-tests/webdriver/tests/user_prompts/get_alert_text.py
@@ -1,4 +1,5 @@
from tests.support.asserts import assert_error, assert_success
+from tests.support.inline import inline
def get_dialog_text(session):
@@ -25,7 +26,7 @@ def test_no_user_prompt(session):
def test_get_alert_text(session):
# 18.3 step 3
- session.execute_script("window.alert(\"Hello\");")
+ session.url = inline("<script>window.alert('Hello');</script>")
response = get_dialog_text(session)
assert_success(response)
assert isinstance(response.body, dict)
@@ -37,7 +38,7 @@ def test_get_alert_text(session):
def test_get_confirm_text(session):
# 18.3 step 3
- session.execute_script("window.confirm(\"Hello\");")
+ session.url = inline("<script>window.confirm('Hello');</script>")
response = get_dialog_text(session)
assert_success(response)
assert isinstance(response.body, dict)
@@ -49,7 +50,7 @@ def test_get_confirm_text(session):
def test_get_prompt_text(session):
# 18.3 step 3
- session.execute_script("window.prompt(\"Enter Your Name: \", \"Federer\");")
+ session.url = inline("<script>window.prompt('Enter Your Name: ', 'Federer');</script>")
response = get_dialog_text(session)
assert_success(response)
assert isinstance(response.body, dict)
diff --git a/tests/wpt/web-platform-tests/webdriver/tests/user_prompts/send_alert_text.py b/tests/wpt/web-platform-tests/webdriver/tests/user_prompts/send_alert_text.py
index 8e07b8561d0..6769b556f1a 100644
--- a/tests/wpt/web-platform-tests/webdriver/tests/user_prompts/send_alert_text.py
+++ b/tests/wpt/web-platform-tests/webdriver/tests/user_prompts/send_alert_text.py
@@ -1,6 +1,7 @@
import pytest
from tests.support.asserts import assert_error, assert_success
+from tests.support.inline import inline
def send_alert_text(session, body=None):
return session.transport.send("POST", "session/{session_id}/alert/text"
@@ -12,7 +13,7 @@ def send_alert_text(session, body=None):
@pytest.mark.parametrize("text", [None, {}, [], 42, True])
def test_invalid_input(session, text):
# 18.4 step 2
- session.execute_script("window.result = window.prompt(\"Enter Your Name: \", \"Name\");")
+ session.url = inline("<script>window.result = window.prompt('Enter Your Name: ', 'Name');</script>")
response = send_alert_text(session, {"text": text})
assert_error(response, "invalid argument")
@@ -35,7 +36,7 @@ def test_no_user_prompt(session):
def test_alert_element_not_interactable(session):
# 18.4 step 5
- session.execute_script("window.alert(\"Hello\");")
+ session.url = inline("<script>window.alert('Hello');</script>")
body = {"text": "Federer"}
response = send_alert_text(session, body)
assert_error(response, "element not interactable")
@@ -43,7 +44,7 @@ def test_alert_element_not_interactable(session):
def test_confirm_element_not_interactable(session):
# 18.4 step 5
- session.execute_script("window.confirm(\"Hello\");")
+ session.url = inline("<script>window.confirm('Hello');</script>")
body = {"text": "Federer"}
response = send_alert_text(session, body)
assert_error(response, "element not interactable")
@@ -51,7 +52,7 @@ def test_confirm_element_not_interactable(session):
def test_send_alert_text(session):
# 18.4 step 6
- session.execute_script("window.result = window.prompt(\"Enter Your Name: \", \"Name\");")
+ session.url = inline("<script>window.result = window.prompt('Enter Your Name: ', 'Name');</script>")
body = {"text": "Federer"}
send_response = send_alert_text(session, body)
assert_success(send_response)
@@ -63,7 +64,7 @@ def test_send_alert_text(session):
def test_send_alert_text_with_whitespace(session):
# 18.4 step 6
- session.execute_script("window.result = window.prompt(\"Enter Your Name: \", \"Name\");")
+ session.url = inline("<script>window.result = window.prompt('Enter Your Name: ', 'Name');</script>")
body = {"text": " Fed erer "}
send_response = send_alert_text(session, body)
assert_success(send_response)
diff --git a/tests/wpt/web-platform-tests/webmessaging/event.origin.sub.htm b/tests/wpt/web-platform-tests/webmessaging/event.origin.sub.htm
index ce944ae3443..ea3c9e40eb6 100644
--- a/tests/wpt/web-platform-tests/webmessaging/event.origin.sub.htm
+++ b/tests/wpt/web-platform-tests/webmessaging/event.origin.sub.htm
@@ -9,7 +9,7 @@
<div id=log></div>
<div style="display:none">
- <iframe width="70%" onload="PostMessageTest()" src="{{location[scheme]}}://{{domains[www]}}:{{location[port]}}/webmessaging/support/ChildWindowPostMessage.htm"></iframe>
+ <iframe width="70%" onload="PostMessageTest()" src="{{location[scheme]}}://{{domains[天気の良い日]}}:{{location[port]}}/webmessaging/support/ChildWindowPostMessage.htm"></iframe>
<iframe width="70%" onload="PostMessageTest()" src="./support/ChildWindowPostMessage.htm"></iframe>
</div>
@@ -23,7 +23,7 @@
var PORT = location.port !== "" ? ":" + location.port : "";
var TARGET1 = document.querySelectorAll("iframe")[0];
var TARGET2 = document.querySelectorAll("iframe")[1];
- var XORIGIN = "{{location[scheme]}}://{{domains[www]}}" + PORT;
+ var XORIGIN = "{{location[scheme]}}://{{domains[天気の良い日]}}" + PORT;
var SORIGIN = "{{location[scheme]}}://{{host}}" + PORT;
var ExpectedResult = ["#1", XORIGIN, "#2", SORIGIN];
var ActualResult = [];
diff --git a/tests/wpt/web-platform-tests/webrtc/OWNERS b/tests/wpt/web-platform-tests/webrtc/OWNERS
index f2d66bf5c08..378bf87a106 100644
--- a/tests/wpt/web-platform-tests/webrtc/OWNERS
+++ b/tests/wpt/web-platform-tests/webrtc/OWNERS
@@ -1,3 +1,4 @@
+@snuggs
@agouaillard
@alvestrand
@dontcallmedom
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCCertificate.html b/tests/wpt/web-platform-tests/webrtc/RTCCertificate.html
index f5eccabf91b..e5f1749eb5b 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCCertificate.html
+++ b/tests/wpt/web-platform-tests/webrtc/RTCCertificate.html
@@ -172,8 +172,9 @@
assert_equals(typeof fingerprint, 'object',
'Expect fingerprint to be an object (dictionary)');
- // Can only do simple test as the allowed values may be extended
- assert_true(/^[a-zA-Z\-]+$/.test(fingerprint.algorithm),
+ // https://www.iana.org/assignments/hash-function-text-names/hash-function-text-names.xml
+ const algorithms = ['md2', 'md5', 'sha-1', 'sha-224', 'sha-256', 'sha-384', 'sha-512'];
+ assert_in_array(fingerprint.algorithm, algorithms,
'Expect fingerprint.algorithm to be string of algorithm identifier');
assert_true(/^([0-9a-f]{2}\:)+[0-9a-f]{2}$/.test(fingerprint.value),
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCConfiguration-iceTransportPolicy.html b/tests/wpt/web-platform-tests/webrtc/RTCConfiguration-iceTransportPolicy.html
index 7387c5424cd..74e8b4b2ae7 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCConfiguration-iceTransportPolicy.html
+++ b/tests/wpt/web-platform-tests/webrtc/RTCConfiguration-iceTransportPolicy.html
@@ -64,7 +64,7 @@
assert_equals(pc.getConfiguration().iceTransportPolicy, 'all');
pc.setConfiguration({ iceTransportPolicy: 'relay' });
- assert_equals(pc.getConfiguration(), iceTransportPolicy, 'relay');
+ assert_equals(pc.getConfiguration().iceTransportPolicy, 'relay');
}, `setConfiguration({ iceTransportPolicy: 'relay' }) with initial iceTransportPolicy all should succeed`);
test(() => {
@@ -72,7 +72,7 @@
assert_equals(pc.getConfiguration().iceTransportPolicy, 'relay');
pc.setConfiguration({ iceTransportPolicy: 'all' });
- assert_equals(pc.getConfiguration(), iceTransportPolicy, 'all');
+ assert_equals(pc.getConfiguration().iceTransportPolicy, 'all');
}, `setConfiguration({ iceTransportPolicy: 'all' }) with initial iceTransportPolicy relay should succeed`);
test(() => {
@@ -81,7 +81,7 @@
// default value for iceTransportPolicy is all
pc.setConfiguration({});
- assert_equals(pc.getConfiguration(), iceTransportPolicy, 'all');
+ assert_equals(pc.getConfiguration().iceTransportPolicy, 'all');
}, `setConfiguration({}) with initial iceTransportPolicy relay should set new value to all`);
config_test(makePc => {
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCDTMFSender-helper.js b/tests/wpt/web-platform-tests/webrtc/RTCDTMFSender-helper.js
index b66c4aedbda..97bb6f93479 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCDTMFSender-helper.js
+++ b/tests/wpt/web-platform-tests/webrtc/RTCDTMFSender-helper.js
@@ -76,8 +76,8 @@ function test_tone_change_events(testFunc, toneChanges, desc) {
const now = Date.now();
const duration = now - lastEventTime;
- assert_approx_equals(duration, expectedDuration, 150,
- `Expect tonechange event for "${tone}" to be fired approximately after ${expectedDuration} seconds`);
+ assert_approx_equals(duration, expectedDuration, 250,
+ `Expect tonechange event for "${tone}" to be fired approximately after ${expectedDuration} milliseconds`);
lastEventTime = now;
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCDtlsTransport-getRemoteCertificates.html b/tests/wpt/web-platform-tests/webrtc/RTCDtlsTransport-getRemoteCertificates.html
index 0fd5340006b..80d1bfae46d 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCDtlsTransport-getRemoteCertificates.html
+++ b/tests/wpt/web-platform-tests/webrtc/RTCDtlsTransport-getRemoteCertificates.html
@@ -76,7 +76,7 @@
testedTransports.add(dtlsTransport);
// End the test if both dtlsTransports are tested.
- if(testedTransports.has(dtlsTransport1) && testedTransports.has(dtslTransport2)) {
+ if(testedTransports.has(dtlsTransport1) && testedTransports.has(dtlsTransport2)) {
t.done();
}
})
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-addTransceiver.html b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-addTransceiver.html
index ce1c2827aac..97205714f07 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-addTransceiver.html
+++ b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-addTransceiver.html
@@ -80,6 +80,8 @@
*/
test(t => {
const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
+
assert_idl_attribute(pc, 'addTransceiver');
assert_throws(new TypeError(), () => pc.addTransceiver('invalid'));
}, 'addTransceiver() with string argument as invalid kind should throw TypeError');
@@ -125,6 +127,7 @@
*/
test(t => {
const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
assert_idl_attribute(pc, 'addTransceiver');
@@ -170,6 +173,7 @@
test(t => {
const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
assert_idl_attribute(pc, 'addTransceiver');
@@ -214,18 +218,24 @@
test(t => {
const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
+
const transceiver = pc.addTransceiver('audio', { direction: 'sendonly' });
assert_equals(transceiver.direction, 'sendonly');
}, `addTransceiver() with direction sendonly should have result transceiver.direction be the same`);
test(t => {
const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
+
const transceiver = pc.addTransceiver('audio', { direction: 'inactive' });
assert_equals(transceiver.direction, 'inactive');
}, `addTransceiver() with direction inactive should have result transceiver.direction be the same`);
test(t => {
const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
+
assert_idl_attribute(pc, 'addTransceiver');
assert_throws(new TypeError(), () =>
pc.addTransceiver('audio', { direction: 'invalid' }));
@@ -238,8 +248,9 @@
*/
test(t => {
const pc = new RTCPeerConnection();
- const track = generateMediaStreamTrack('audio');
+ t.add_cleanup(() => pc.close());
+ const track = generateMediaStreamTrack('audio');
const transceiver = pc.addTransceiver(track);
const { sender, receiver } = transceiver;
@@ -276,8 +287,9 @@
test(t => {
const pc = new RTCPeerConnection();
- const track = generateMediaStreamTrack('audio');
+ t.add_cleanup(() => pc.close());
+ const track = generateMediaStreamTrack('audio');
const transceiver1 = pc.addTransceiver(track);
const transceiver2 = pc.addTransceiver(track);
@@ -302,7 +314,6 @@
}, 'addTransceiver(track) multiple times should create multiple transceivers');
-
/*
5.1. addTransceiver
6. Verify that each rid value in sendEncodings is composed only of
@@ -310,8 +321,9 @@
of 16 characters. If one of the RIDs does not meet these requirements,
throw a TypeError.
*/
- test(() => {
+ test(t => {
const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
assert_idl_attribute(pc, 'addTransceiver');
assert_throws(new TypeError(), () =>
@@ -322,8 +334,9 @@
}));
}, 'addTransceiver() with rid containing invalid non-alphanumeric characters should throw TypeError');
- test(() => {
+ test(t => {
const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
assert_idl_attribute(pc, 'addTransceiver');
assert_throws(new TypeError(), () =>
@@ -334,8 +347,9 @@
}));
}, 'addTransceiver() with rid longer than 16 characters should throw TypeError');
- test(() => {
+ test(t => {
const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
pc.addTransceiver('audio', {
sendEncodings: [{
rid: 'foo'
@@ -353,8 +367,9 @@
Aside from rid , all read-only parameters in the RTCRtpEncodingParameters
dictionaries, such as ssrc, must be left unset, or an error will be thrown.
*/
- test(() => {
+ test(t => {
const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
assert_throws('InvalidAccessError', () =>
pc.addTransceiver('audio', {
@@ -364,8 +379,9 @@
}));
}, `addTransceiver() with readonly ssrc set should throw InvalidAccessError`);
- test(() => {
+ test(t => {
const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
assert_throws('InvalidAccessError', () =>
pc.addTransceiver('audio', {
@@ -377,8 +393,9 @@
}));
}, `addTransceiver() with readonly rtx set should throw InvalidAccessError`);
- test(() => {
+ test(t => {
const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
assert_throws('InvalidAccessError', () =>
pc.addTransceiver('audio', {
@@ -390,8 +407,10 @@
}));
}, `addTransceiver() with readonly fec set should throw InvalidAccessError`);
- test(() => {
+ test(t => {
const pc = new RTCPeerConnection();
+ t.add_cleanup(() => pc.close());
+
pc.addTransceiver('audio', {
sendEncodings: [{
dtx: 'enabled',
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-constructor.html b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-constructor.html
index 331eefe458d..e00d9870908 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-constructor.html
+++ b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-constructor.html
@@ -73,7 +73,7 @@ for (const attr in initialState) {
if (!window.pc) {
window.pc = new RTCPeerConnection;
}
- assert_equals(pc[attr], initialState[attr]);
+ assert_equals(window.pc[attr], initialState[attr]);
}, attr + ' initial value');
}
</script>
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-createDataChannel.html b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-createDataChannel.html
index a446280eaaa..35e22f934f0 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-createDataChannel.html
+++ b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-createDataChannel.html
@@ -375,7 +375,7 @@ promise_test(t => {
assert_not_equals(channel1.id, null,
'Expect channel1.id to be assigned');
- assert_greater_than_equals(channel1.id, 0,
+ assert_greater_than_equal(channel1.id, 0,
'Expect channel1.id to be set to valid unsigned short');
assert_less_than(channel1.id, 65535,
@@ -386,7 +386,7 @@ promise_test(t => {
assert_not_equals(channel2.id, null,
'Expect channel2.id to be assigned');
- assert_greater_than_equals(channel2.id, 0,
+ assert_greater_than_equal(channel2.id, 0,
'Expect channel2.id to be set to valid unsigned short');
assert_less_than(channel2.id, 65535,
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-createOffer-offerToReceive.html b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-createOffer-offerToReceive.html
new file mode 100644
index 00000000000..c599b1c0d07
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-createOffer-offerToReceive.html
@@ -0,0 +1,169 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Test legacy offerToReceiveAudio/Video options</title>
+<link rel="help" href="https://w3c.github.io/webrtc-pc/#legacy-configuration-extensions">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="RTCPeerConnection-helper.js"></script>
+<script>
+ 'use strict';
+
+ // Run some tests for both audio and video kinds
+ ['audio', 'video'].forEach((kind) => {
+ const capsKind = kind[0].toUpperCase() + kind.slice(1);
+
+ const offerToReceiveTrue = {};
+ offerToReceiveTrue[`offerToReceive${capsKind}`] = true;
+
+ const offerToReceiveFalse = {};
+ offerToReceiveFalse[`offerToReceive${capsKind}`] = false;
+
+ // Start testing
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+ const dummy = pc.createDataChannel('foo'); // Just to have something to offer
+
+ return pc.createOffer(offerToReceiveFalse)
+ .then(() => {
+ assert_equals(pc.getTransceivers().length, 0,
+ 'Expect pc to have no transceivers');
+ });
+ }, `createOffer() with offerToReceive${capsKind} set to false should not create a transceiver`);
+
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+
+ return pc.createOffer(offerToReceiveTrue)
+ .then(() => {
+ assert_equals(pc.getTransceivers().length, 1,
+ 'Expect pc to have one transceiver');
+
+ const transceiver = pc.getTransceivers()[0];
+ assert_equals(transceiver.direction, 'recvonly',
+ 'Expect transceiver to have "recvonly" direction');
+ });
+ }, `createOffer() with offerToReceive${capsKind} should create a "recvonly" transceiver`);
+
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+
+ return pc.createOffer(offerToReceiveTrue)
+ .then(() => {
+ assert_equals(pc.getTransceivers().length, 1,
+ 'Expect pc to have one transceiver');
+
+ const transceiver = pc.getTransceivers()[0];
+ assert_equals(transceiver.direction, 'recvonly',
+ 'Expect transceiver to have "recvonly" direction');
+ })
+ .then(() => pc.createOffer(offerToReceiveTrue))
+ .then(() => {
+ assert_equals(pc.getTransceivers().length, 1,
+ 'Expect pc to still have only one transceiver');
+ })
+ ;
+ }, `offerToReceive${capsKind} option should be ignored if a non-stopped "recvonly" transceiver exists`);
+
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+
+ return getTrackFromUserMedia(kind)
+ .then(([track, stream]) => {
+ pc.addTrack(track, stream);
+ return pc.createOffer();
+ })
+ .then(() => {
+ assert_equals(pc.getTransceivers().length, 1,
+ 'Expect pc to have one transceiver');
+
+ const transceiver = pc.getTransceivers()[0];
+ assert_equals(transceiver.direction, 'sendrecv',
+ 'Expect transceiver to have "sendrecv" direction');
+ })
+ .then(() => pc.createOffer(offerToReceiveTrue))
+ .then(() => {
+ assert_equals(pc.getTransceivers().length, 1,
+ 'Expect pc to still have only one transceiver');
+ })
+ ;
+ }, `offerToReceive${capsKind} option should be ignored if a non-stopped "sendrecv" transceiver exists`);
+
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+
+ return getTrackFromUserMedia(kind)
+ .then(([track, stream]) => {
+ pc.addTrack(track, stream);
+ return pc.createOffer(offerToReceiveFalse);
+ })
+ .then(() => {
+ assert_equals(pc.getTransceivers().length, 1,
+ 'Expect pc to have one transceiver');
+
+ const transceiver = pc.getTransceivers()[0];
+ assert_equals(transceiver.direction, 'sendonly',
+ 'Expect transceiver to have "sendonly" direction');
+ })
+ ;
+ }, `offerToReceive${capsKind} set to false with a track should create a "sendonly" transceiver`);
+
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+
+ pc.addTransceiver(kind, {direction: 'recvonly'});
+
+ return pc.createOffer(offerToReceiveFalse)
+ .then(() => {
+ assert_equals(pc.getTransceivers().length, 1,
+ 'Expect pc to have one transceiver');
+
+ const transceiver = pc.getTransceivers()[0];
+ assert_equals(transceiver.direction, 'inactive',
+ 'Expect transceiver to have "inactive" direction');
+ })
+ ;
+ }, `offerToReceive${capsKind} set to false with a "recvonly" transceiver should change the direction to "inactive"`);
+
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+ const pc2 = new RTCPeerConnection();
+
+ return getTrackFromUserMedia(kind)
+ .then(([track, stream]) => {
+ pc.addTrack(track, stream);
+ return pc.createOffer();
+ })
+ .then((offer) => pc.setLocalDescription(offer))
+ .then(() => pc2.setRemoteDescription(pc.localDescription))
+ .then(() => pc2.createAnswer())
+ .then((answer) => pc2.setLocalDescription(answer))
+ .then(() => pc.setRemoteDescription(pc2.localDescription))
+ .then(() => pc.createOffer(offerToReceiveFalse))
+ .then((offer) => {
+ assert_equals(pc.getTransceivers().length, 1,
+ 'Expect pc to have one transceiver');
+
+ const transceiver = pc.getTransceivers()[0];
+ assert_equals(transceiver.direction, 'sendonly',
+ 'Expect transceiver to have "sendonly" direction');
+ })
+ ;
+ }, `subsequent offerToReceive${capsKind} set to false with a track should change the direction to "sendonly"`);
+ });
+
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+
+ return pc.createOffer({ offerToReceiveAudio: true, offerToReceiveVideo: true })
+ .then(() => {
+ assert_equals(pc.getTransceivers().length, 2,
+ 'Expect pc to have two transceivers');
+
+ assert_equals(pc.getTransceivers()[0].direction, 'recvonly',
+ 'Expect first transceiver to have "recvonly" direction');
+ assert_equals(pc.getTransceivers()[1].direction, 'recvonly',
+ 'Expect second transceiver to have "recvonly" direction');
+ });
+ }, 'offerToReceiveAudio and Video should create two "recvonly" transceivers');
+
+</script>
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-getStats.https.html b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-getStats.https.html
index a4df5630a3a..73138507d4f 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-getStats.https.html
+++ b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-getStats.https.html
@@ -10,8 +10,8 @@
'use strict';
// Test is based on the following editor draft:
- // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
- // https://w3c.github.io/webrtc-stats/archives/20170614/webrtc-stats.html
+ // webrtc-pc 20171130
+ // webrtc-stats 20171122
// The following helper function is called from RTCPeerConnection-helper.js
// getTrackFromUserMedia
@@ -20,39 +20,25 @@
// validateStatsReport
// assert_stats_report_has_stats
- /*
- 8.2. RTCPeerConnection Interface Extensions
- partial interface RTCPeerConnection {
- Promise<RTCStatsReport> getStats(optional MediaStreamTrack? selector = null);
- };
-
- 8.3. RTCStatsReport Object
- interface RTCStatsReport {
- readonly maplike<DOMString, object>;
- };
-
- 8.4. RTCStats Dictionary
- dictionary RTCStats {
- DOMHighResTimeStamp timestamp;
- RTCStatsType type;
- DOMString id;
- };
-
- id
- Two RTCStats objects, extracted from two different RTCStatsReport objects, MUST
- have the same id if they were produced by inspecting the same underlying object.
+ // The following helper function is called from RTCPeerConnection-helper.js
+ // exchangeIceCandidates
+ // doSignalingHandshake
+ /*
8.2. getStats
1. Let selectorArg be the method's first argument.
2. Let connection be the RTCPeerConnection object on which the method was invoked.
- 3. If selectorArg is neither null nor a valid MediaStreamTrack, return a promise
- rejected with a newly created TypeError.
+ 3. If selectorArg is null, let selector be null.
+ 4. If selectorArg is a MediaStreamTrack let selector be an RTCRtpSender
+ or RTCRtpReceiver on connection which track member matches selectorArg.
+ If no such sender or receiver exists, or if more than one sender or
+ receiver fit this criteria, return a promise rejected with a newly
+ created InvalidAccessError.
5. Let p be a new promise.
6. Run the following steps in parallel:
1. Gather the stats indicated by selector according to the stats selection algorithm.
2. Resolve p with the resulting RTCStatsReport object, containing the gathered stats.
*/
-
promise_test(() => {
const pc = new RTCPeerConnection();
return pc.getStats();
@@ -65,9 +51,11 @@
/*
8.2. getStats
- 4. Let selector be a RTCRtpSender or RTCRtpReceiver on connection which track
- member matches selectorArg. If no such sender or receiver exists, return a promise
- rejected with a newly created InvalidAccessError.
+ 4. If selectorArg is a MediaStreamTrack let selector be an RTCRtpSender
+ or RTCRtpReceiver on connection which track member matches selectorArg.
+ If no such sender or receiver exists, or if more than one sender or
+ receiver fit this criteria, return a promise rejected with a newly
+ created InvalidAccessError.
*/
promise_test(t => {
const pc = new RTCPeerConnection();
@@ -94,12 +82,6 @@
return pc.getStats(track);
}, 'getStats() with track added via addTransceiver should succeed');
- /*
- 8.2. getStats
- 4. Let selector be a RTCRtpSender or RTCRtpReceiver on connection which track
- member matches selectorArg. If more than one sender or receiver fit this criteria,
- return a promise rejected with a newly created InvalidAccessError.
- */
promise_test(t => {
const pc = new RTCPeerConnection();
return getTrackFromUserMedia('audio')
@@ -140,7 +122,35 @@
validateStatsReport(statsReport);
assert_stats_report_has_stats(statsReport, ['peer-connection']);
});
- }, 'getStats() with no argument should return stats report containing peer-connection stats');
+ }, 'getStats() with no argument should return stats report containing peer-connection stats on an empty PC');
+
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+ return getTrackFromUserMedia('audio')
+ .then(([track, mediaStream]) => {
+ pc.addTrack(track, mediaStream);
+ return pc.getStats();
+ })
+ .then(statsReport => {
+ validateStatsReport(statsReport);
+ assert_stats_report_has_stats(statsReport, ['peer-connection']);
+ assert_stats_report_has_stats(statsReport, ['outbound-rtp']);
+ });
+ }, 'getStats() with no argument should return stats report containing peer-connection stats and outbound-track-stats');
+
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+ return getTrackFromUserMedia('audio')
+ .then(([track, mediaStream]) => {
+ pc.addTrack(track);
+ return pc.getStats();
+ })
+ .then(statsReport => {
+ validateStatsReport(statsReport);
+ assert_stats_report_has_stats(statsReport, ['peer-connection']);
+ assert_stats_report_has_stats(statsReport, ['outbound-rtp']);
+ });
+ }, 'getStats() with no argument should return stats for no-stream tracks');
/*
8.5. The stats selection algorithm
@@ -184,4 +194,150 @@
});
}, `getStats() on track associated with RtpReceiver should return stats report containing inbound-rtp stats`);
+ /*
+ 8.6 Mandatory To Implement Stats
+ An implementation MUST support generating statistics of the following types
+ when the corresponding objects exist on a PeerConnection, with the attributes
+ that are listed when they are valid for that object.
+ */
+
+ const mandatoryStats = [
+ "codec",
+ "inbound-rtp",
+ "outbound-rtp",
+ "remote-inbound-rtp",
+ "remote-outbound-rtp",
+ "peer-connection",
+ "data-channel",
+ "stream",
+ "track",
+ "transport",
+ "candidate-pair",
+ "local-candidate",
+ "remote-candidate",
+ "certificate"
+ ];
+
+ async_test(t => {
+ const pc1 = new RTCPeerConnection();
+ t.add_cleanup(() => pc1.close());
+ const pc2 = new RTCPeerConnection();
+ t.add_cleanup(() => pc2.close());
+
+ const dataChannel = pc1.createDataChannel('test-channel');
+
+ return navigator.mediaDevices.getUserMedia({
+ audio: true,
+ video: true
+ })
+ .then(t.step_func(mediaStream => {
+ const tracks = mediaStream.getTracks();
+ assert_equals(tracks.length, 2,
+ 'Expect media stream to have one audio and one video track');
+
+ let audioTrack;
+ let videoTrack;
+
+ for (const track of tracks) {
+ t.add_cleanup(() => track.stop());
+
+ pc1.addTrack(track, mediaStream);
+
+ if (track.kind === 'audio') {
+ audioTrack = track;
+ } else if (track.kind === 'video') {
+ videoTrack = track;
+ }
+ }
+
+ if (!audioTrack || ! videoTrack) {
+ assert_unreached('Expect mediaStream to have both audio and video streams');
+ }
+
+ const testStatsReport = (pc, statsReport) => {
+ validateStatsReport(statsReport);
+ assert_stats_report_has_stats(statsReport, mandatoryStats);
+
+ const dataChannelStats = findStatsFromReport(statsReport,
+ stats => {
+ return stats.type === 'data-channel' &&
+ stats.dataChannelIdentifier === dataChannel.id;
+ },
+ 'Expect data channel stats to be found');
+
+ assert_equals(dataChannelStats.label, 'test-channel');
+
+ const audioTrackStats = findStatsFromReport(statsReport,
+ stats => {
+ return stats.type === 'track' &&
+ stats.trackIdentifier === audioTrack.id;
+ },
+ 'Expect audio track stats to be found');
+
+ assert_equals(audioTrackStats.kind, 'audio');
+
+ const videoTrackStats = findStatsFromReport(statsReport,
+ stats => {
+ return stats.type === 'track' &&
+ stats.trackIdentifier === videoTrack.id;
+ },
+ 'Expect video track stats to be found');
+
+ assert_equals(videoTrackStats.kind, 'video');
+
+ const mediaStreamStats = findStatsFromReport(statsReport,
+ stats => {
+ return stats.type === 'stream' &&
+ stats.streamIdentifier === mediaStream.id;
+ },
+ 'Expect media stream stats to be found');
+
+ assert_true(mediaStreamStats.trackIds.include(audioTrackStats.id));
+ assert_true(mediaStreamStats.trackIds.include(videoTrackStats.id));
+ }
+
+ const onConnected = t.step_func(() => {
+ // Wait a while for the peer connections to collect stats
+ t.step_timeout(() => {
+ Promise.all([
+ pc1.getStats()
+ .then(statsReport => testStatsReport(pc1, statsReport)),
+
+ pc2.getStats()
+ .then(statsReport => testStatsReport(pc2, statsReport))
+ ])
+ .then(t.step_func_done())
+ .catch(t.step_func(err => {
+ assert_unreached(`test failed with error: ${err}`);
+ }));
+ }, 200)
+ })
+
+ let onTrackCount = 0
+ let onDataChannelCalled = false
+
+ pc2.addEventListener('track', t.step_func(() => {
+ onTrackCount++;
+ if (onTrackCount === 2 && onDataChannelCalled) {
+ onConnected();
+ }
+ }));
+
+ pc2.addEventListener('datachannel', t.step_func(() => {
+ onDataChannelCalled = true;
+ if (onTrackCount === 2) {
+ onConnected();
+ }
+ }));
+
+
+ exchangeIceCandidates(pc1, pc2);
+ doSignalingHandshake(pc1, pc2);
+ }))
+ .catch(t.step_func(err => {
+ assert_unreached(`test failed with error: ${err}`);
+ }));
+
+ }, `getStats() with connected peer connections having tracks and data channel should return all mandatory to implement stats`);
+
</script>
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-idl.html b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-idl.html
deleted file mode 100644
index 58a153f2946..00000000000
--- a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-idl.html
+++ /dev/null
@@ -1,108 +0,0 @@
-<!doctype html>
-<html>
-<head>
-<meta charset=utf-8>
-<title>IDL check of RTCPeerConnection</title>
-<link rel="author" title="Harald Alvestrand" href="mailto:hta@google.com"/>
-<link rel="help" href="http://w3c.github.io/webrtc-pc/#rtcpeerconnection-interface">
-</head>
-<body>
-
-<h1 class="instructions">Description</h1>
-<p class="instructions">This test verifies the availability of the RTCPeerConnection interface.</p>
-<div id='log'></div>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/resources/WebIDLParser.js></script>
-<script src=/resources/idlharness.js></script>
-
-<!-- The IDL is copied from the 22 September 2015 editors' draft. -->
-<script type="text/plain">
-[Constructor()]
-interface EventTarget {
- // Only a dummy definition is needed here.
-};
-[ Constructor (optional RTCConfiguration configuration)]
-interface RTCPeerConnection : EventTarget {
- Promise<RTCSessionDescription> createOffer (optional RTCOfferOptions options);
- Promise<RTCSessionDescription> createAnswer (optional RTCAnswerOptions options);
- Promise<void> setLocalDescription (RTCSessionDescription description);
- readonly attribute RTCSessionDescription? localDescription;
- readonly attribute RTCSessionDescription? currentLocalDescription;
- readonly attribute RTCSessionDescription? pendingLocalDescription;
- Promise<void> setRemoteDescription (RTCSessionDescription description);
- readonly attribute RTCSessionDescription? remoteDescription;
- readonly attribute RTCSessionDescription? currentRemoteDescription;
- readonly attribute RTCSessionDescription? pendingRemoteDescription;
- Promise<void> addIceCandidate (RTCIceCandidate candidate);
- readonly attribute RTCSignalingState signalingState;
- readonly attribute RTCIceGatheringState iceGatheringState;
- readonly attribute RTCIceConnectionState iceConnectionState;
- readonly attribute boolean? canTrickleIceCandidates;
- RTCConfiguration getConfiguration ();
- void setConfiguration (RTCConfiguration configuration);
- void close ();
- attribute EventHandler onnegotiationneeded;
- attribute EventHandler onicecandidate;
- attribute EventHandler onsignalingstatechange;
- attribute EventHandler oniceconnectionstatechange;
- attribute EventHandler onicegatheringstatechange;
-};
-
-partial interface RTCPeerConnection {
- void createOffer (RTCSessionDescriptionCallback successCallback, RTCPeerConnectionErrorCallback failureCallback, optional RTCOfferOptions options);
- void setLocalDescription (RTCSessionDescription description, VoidFunction successCallback, RTCPeerConnectionErrorCallback failureCallback);
- void createAnswer (RTCSessionDescriptionCallback successCallback, RTCPeerConnectionErrorCallback failureCallback);
- void setRemoteDescription (RTCSessionDescription description, VoidFunction successCallback, RTCPeerConnectionErrorCallback failureCallback);
- void addIceCandidate (RTCIceCandidate candidate, VoidFunction successCallback, RTCPeerConnectionErrorCallback failureCallback);
- void getStats (MediaStreamTrack? selector, RTCStatsCallback successCallback, RTCPeerConnectionErrorCallback failureCallback);
-};
-
-partial interface RTCPeerConnection {
- static Promise<RTCCertificate> generateCertificate (AlgorithmIdentifier keygenAlgorithm);
-};
-
-partial interface RTCPeerConnection {
- sequence<RTCRtpSender> getSenders ();
- sequence<RTCRtpReceiver> getReceivers ();
- RTCRtpSender addTrack (MediaStreamTrack track, MediaStream... streams);
- void removeTrack (RTCRtpSender sender);
- attribute EventHandler ontrack;
-};
-
-partial interface RTCPeerConnection {
- RTCDataChannel createDataChannel ([TreatNullAs=EmptyString] DOMString label, optional RTCDataChannelInit dataChannelDict);
- attribute EventHandler ondatachannel;
-};
-
-partial interface RTCPeerConnection {
- readonly attribute RTCDTMFSender? dtmf;
-};
-
-partial interface RTCPeerConnection {
- Promise<RTCStatsReport> getStats (optional MediaStreamTrack? selector);
-};
-
-partial interface RTCPeerConnection {
- void setIdentityProvider (DOMString provider, optional DOMString protocol, optional DOMString usernameHint);
- Promise<DOMString> getIdentityAssertion ();
- readonly attribute Promise<RTCIdentityAssertion> peerIdentity;
- readonly attribute DOMString? idpLoginUrl;
-};
-
-</script>
-<script>
-(function() {
- var idl_array = new IdlArray();
- [].forEach.call(document.querySelectorAll("script[type=text\\/plain]"),
- function(node) {
- idl_array.add_idls(node.textContent);
- });
- window.pc = new RTCPeerConnection(null);
- idl_array.add_objects({"RTCPeerConnection": ["pc"]});
- idl_array.test();
- done();
-})();
-</script>
-</body>
-</html>
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-peerIdentity.html b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-peerIdentity.html
index 845c55dc6d2..d5f9db9d5d0 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-peerIdentity.html
+++ b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-peerIdentity.html
@@ -284,7 +284,7 @@
pc2.setRemoteDescription(offer))
.then(() =>
assert_rtcerror_rejection('idp-execution-failure',
- peerIdentityPromise,
+ peerIdentityPromise1,
`Expect first peerIdentity promise to be rejected with RTCError('idp-execution-failure')`))
.then(() => {
const peerIdentityPromise2 = pc2.peerIdentity;
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-tracks.https.html b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-tracks.https.html
index f530e94cfe0..d4663e5373b 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-tracks.https.html
+++ b/tests/wpt/web-platform-tests/webrtc/RTCPeerConnection-setRemoteDescription-tracks.https.html
@@ -24,11 +24,11 @@
const callee = new RTCPeerConnection();
return getUserMediaTracksAndStreams(1)
.then(t.step_func(([tracks, streams]) => {
- let localTrack = tracks[0];
+ const localTrack = tracks[0];
caller.addTrack(localTrack);
- let offerPromise = performOffer(caller, callee);
+ const offerPromise = performOffer(caller, callee);
callee.ontrack = t.step_func(trackEvent => {
- let remoteTrack = trackEvent.track;
+ const remoteTrack = trackEvent.track;
assert_equals(remoteTrack.id, localTrack.id,
'Expected local and remote track IDs to match.');
assert_equals(trackEvent.streams.length, 0,
@@ -47,15 +47,15 @@
const callee = new RTCPeerConnection();
return getUserMediaTracksAndStreams(1)
.then(t.step_func(([tracks, streams]) => {
- let localTrack = tracks[0];
- let localStream = streams[0];
+ const localTrack = tracks[0];
+ const localStream = streams[0];
caller.addTrack(localTrack, localStream);
- let offerPromise = performOffer(caller, callee);
+ const offerPromise = performOffer(caller, callee);
callee.ontrack = t.step_func(trackEvent => {
assert_equals(trackEvent.streams.length, 1,
'Expected track event to fire with a single stream.');
- let remoteTrack = trackEvent.track;
- let remoteStream = trackEvent.streams[0];
+ const remoteTrack = trackEvent.track;
+ const remoteStream = trackEvent.streams[0];
assert_equals(remoteTrack.id, localTrack.id,
'Expected local and remote track IDs to match.');
assert_equals(remoteStream.id, localStream.id,
@@ -74,19 +74,47 @@
async_test(t => {
const caller = new RTCPeerConnection();
const callee = new RTCPeerConnection();
+ let eventSequence = '';
+ return getUserMediaTracksAndStreams(1)
+ .then(t.step_func(([tracks, streams]) => {
+ const ontrackResolver = new Resolver();
+ callee.ontrack = () => {
+ eventSequence += 'ontrack;';
+ ontrackResolver.resolve();
+ }
+ caller.addTrack(tracks[0]);
+ return Promise.all([
+ ontrackResolver.promise,
+ performOffer(caller, callee).then(() => {
+ eventSequence += 'setRemoteDescription;';
+ })
+ ]);
+ }))
+ .then(t.step_func(() => {
+ assert_equals(eventSequence, 'ontrack;setRemoteDescription;');
+ t.done();
+ }))
+ .catch(t.step_func(reason => {
+ assert_unreached(reason);
+ }));
+ }, 'ontrack fires before setRemoteDescription resolves.');
+
+ async_test(t => {
+ const caller = new RTCPeerConnection();
+ const callee = new RTCPeerConnection();
return getUserMediaTracksAndStreams(2)
.then(t.step_func(([tracks, streams]) => {
- let localTrack1 = tracks[0];
- let localTrack2 = tracks[1];
- let localStream = streams[0];
+ const localTrack1 = tracks[0];
+ const localTrack2 = tracks[1];
+ const localStream = streams[0];
caller.addTrack(localTrack1, localStream);
caller.addTrack(localTrack2, localStream);
- let offerPromise = performOffer(caller, callee);
+ const offerPromise = performOffer(caller, callee);
callee.ontrack = t.step_func(trackEvent => {
assert_equals(trackEvent.streams.length, 1,
'Expected track event to fire with a single stream.');
- let remoteTrack1 = trackEvent.track;
- let remoteStream = trackEvent.streams[0];
+ const remoteTrack1 = trackEvent.track;
+ const remoteStream = trackEvent.streams[0];
assert_equals(remoteTrack1.id, localTrack1.id,
'Expected first remote track ID to match first local track ID.');
assert_equals(remoteStream.getTracks().length, 2,
@@ -94,7 +122,7 @@
callee.ontrack = t.step_func(trackEvent => {
assert_equals(trackEvent.streams.length, 1,
'Expected track event to fire with a single stream.');
- let remoteTrack2 = trackEvent.track;
+ const remoteTrack2 = trackEvent.track;
assert_equals(trackEvent.streams[0], remoteStream,
'Expected both track events to fire with the same remote stream.');
assert_equals(remoteTrack2.id, localTrack2.id,
@@ -151,17 +179,53 @@
async_test(t => {
const caller = new RTCPeerConnection();
const callee = new RTCPeerConnection();
+ let eventSequence = '';
+ return getUserMediaTracksAndStreams(2)
+ .then(t.step_func(([tracks, streams]) => {
+ const localTracks = tracks;
+ const localStream = streams[0];
+ caller.addTrack(localTracks[0], localStream);
+ const offerPromise = performOffer(caller, callee);
+ callee.ontrack = t.step_func(trackEvent => {
+ callee.ontrack = null;
+ const remoteStream = trackEvent.streams[0];
+ const onaddtrackResolver = new Resolver();
+ remoteStream.onaddtrack = () => {
+ eventSequence += 'stream.onaddtrack;';
+ onaddtrackResolver.resolve();
+ }
+ caller.addTrack(localTracks[1], localStream);
+ Promise.all([
+ onaddtrackResolver.promise,
+ performOffer(caller, callee).then(() => {
+ eventSequence += 'setRemoteDescription;';
+ })
+ ]).then(t.step_func(() => {
+ assert_equals(eventSequence, 'stream.onaddtrack;setRemoteDescription;');
+ t.done();
+ }));
+ });
+ return offerPromise;
+ }))
+ .catch(t.step_func(reason => {
+ assert_unreached(reason);
+ }));
+ }, 'stream.onaddtrack fires before setRemoteDescription resolves.');
+
+ async_test(t => {
+ const caller = new RTCPeerConnection();
+ const callee = new RTCPeerConnection();
return getUserMediaTracksAndStreams(2)
.then(t.step_func(([tracks, streams]) => {
- let localTrack = tracks[0];
- let localStreams = streams;
+ const localTrack = tracks[0];
+ const localStreams = streams;
caller.addTrack(localTrack, localStreams[0], localStreams[1]);
- let performOffer = performOffer(caller, callee);
+ const performOffer = performOffer(caller, callee);
callee.ontrack = t.step_func(trackEvent => {
assert_equals(trackEvent.streams.length, 2,
'Expected the track event to fire with two streams.');
- let remoteTrack = trackEvent.track;
- let remoteStreams = trackEvent.streams;
+ const remoteTrack = trackEvent.track;
+ const remoteStreams = trackEvent.streams;
assert_equals(remoteTrack.id, localTrack.id,
'Expected local and remote track IDs to match.');
assert_equals(remoteStreams[0].id, localStreams[0].id,
@@ -184,38 +248,10 @@
async_test(t => {
const caller = new RTCPeerConnection();
const callee = new RTCPeerConnection();
- let eventSequence = '';
return getUserMediaTracksAndStreams(1)
.then(t.step_func(([tracks, streams]) => {
caller.addTrack(tracks[0]);
- let ontrackResolver = new Resolver();
- callee.ontrack = () => {
- eventSequence += 'ontrack;';
- ontrackResolver.resolve();
- }
- return Promise.all([
- ontrackResolver.promise,
- performOffer(caller, callee).then(() => {
- eventSequence += 'setRemoteDescription;';
- })
- ]);
- }))
- .then(t.step_func(() => {
- assert_equals(eventSequence, 'ontrack;setRemoteDescription;');
- t.done();
- }))
- .catch(t.step_func(reason => {
- assert_unreached(reason);
- }));
- }, 'ontrack fires before setRemoteDescription resolves.');
-
- async_test(t => {
- const caller = new RTCPeerConnection();
- const callee = new RTCPeerConnection();
- return getUserMediaTracksAndStreams(1)
- .then(t.step_func(([tracks, streams]) => {
- caller.addTrack(tracks[0]);
- let offerPromise = performOffer(caller, callee);
+ const offerPromise = performOffer(caller, callee);
callee.ontrack = t.step_func(trackEvent => {
assert_array_equals(callee.getReceivers(), [trackEvent.receiver]);
t.done();
@@ -232,11 +268,11 @@
const callee = new RTCPeerConnection();
return getUserMediaTracksAndStreams(1)
.then(t.step_func(([tracks, streams]) => {
- let sender = caller.addTrack(tracks[0]);
- assert_true(sender != null);
- let offerPromise = performOffer(caller, callee);
+ const sender = caller.addTrack(tracks[0]);
+ assert_not_equals(sender, null);
+ const offerPromise = performOffer(caller, callee);
callee.ontrack = t.step_func(trackEvent => {
- let receivers = callee.getReceivers();
+ const receivers = callee.getReceivers();
assert_equals(receivers.length, 1,
'Expected getReceivers() to be the track event\'s receiver.');
caller.removeTrack(sender);
@@ -259,9 +295,9 @@
const callee = new RTCPeerConnection();
return getUserMediaTracksAndStreams(1)
.then(t.step_func(([tracks, streams]) => {
- let sender = caller.addTrack(tracks[0], streams[0]);
- assert_true(sender != null);
- let offerPromise = performOffer(caller, callee);
+ const sender = caller.addTrack(tracks[0], streams[0]);
+ assert_not_equals(sender, null);
+ const offerPromise = performOffer(caller, callee);
callee.ontrack = t.step_func(trackEvent => {
assert_not_equals(trackEvent.track, null);
assert_equals(trackEvent.streams.length, 1);
@@ -279,21 +315,55 @@
.catch(t.step_func(reason => {
assert_unreached(reason);
}));
- }, 'removeTrack() causes onremovetrack and the track to be removed from the stream.');
+ }, 'removeTrack() makes stream.onremovetrack fire and the track to be removed from the stream.');
async_test(t => {
const caller = new RTCPeerConnection();
const callee = new RTCPeerConnection();
+ let eventSequence = '';
return getUserMediaTracksAndStreams(1)
.then(t.step_func(([tracks, streams]) => {
- let sender = caller.addTrack(tracks[0]);
- assert_true(sender != null);
- let offerPromise = performOffer(caller, callee);
+ const sender = caller.addTrack(tracks[0], streams[0]);
+ assert_not_equals(sender, null);
+ const offerPromise = performOffer(caller, callee);
callee.ontrack = t.step_func(trackEvent => {
- assert_not_equals(trackEvent.track, null);
+ const remoteStream = trackEvent.streams[0];
+ const onremovetrackResolver = new Resolver();
+ remoteStream.onremovetrack = t.step_func(removeEvent => {
+ eventSequence += 'stream.onremovetrack;';
+ onremovetrackResolver.resolve();
+ });
+ caller.removeTrack(sender);
+ return Promise.all([
+ onremovetrackResolver.promise,
+ performOffer(caller, callee).then(() => {
+ eventSequence += 'setRemoteDescription;';
+ })
+ ]).then(t.step_func(() => {
+ assert_equals(eventSequence, 'stream.onremovetrack;setRemoteDescription;');
+ t.done();
+ }));
+ });
+ return offerPromise;
+ }))
+ .catch(t.step_func(reason => {
+ assert_unreached(reason);
+ }));
+ }, 'stream.onremovetrack fires before setRemoteDescription resolves.');
+
+ async_test(t => {
+ const caller = new RTCPeerConnection();
+ const callee = new RTCPeerConnection();
+ return getUserMediaTracksAndStreams(1)
+ .then(t.step_func(([tracks, streams]) => {
+ const sender = caller.addTrack(tracks[0]);
+ assert_not_equals(sender, null);
+ const offerPromise = performOffer(caller, callee);
+ callee.ontrack = t.step_func(trackEvent => {
+ const remoteTrack = trackEvent.track;
caller.removeTrack(sender);
performOffer(caller, callee);
- trackEvent.track.onmute = t.step_func(() => {
+ remoteTrack.onmute = t.step_func(() => {
assert_true(trackEvent.track.muted);
t.done();
});
@@ -303,6 +373,54 @@
.catch(t.step_func(reason => {
assert_unreached(reason);
}));
- }, 'removeTrack() causes onmute and the track to be muted.');
+ }, 'removeTrack() makes track.onmute fire and the track to be muted.');
+ async_test(t => {
+ const caller = new RTCPeerConnection();
+ const callee = new RTCPeerConnection();
+ let eventSequence = '';
+ return getUserMediaTracksAndStreams(1)
+ .then(t.step_func(([tracks, streams]) => {
+ const sender = caller.addTrack(tracks[0]);
+ assert_not_equals(sender, null);
+ const offerPromise = performOffer(caller, callee);
+ callee.ontrack = t.step_func(trackEvent => {
+ const remoteTrack = trackEvent.track;
+ const onmuteResolver = new Resolver();
+ remoteTrack.onmute = t.step_func(() => {
+ eventSequence += 'track.onmute;';
+ onmuteResolver.resolve();
+ });
+ caller.removeTrack(sender);
+ return Promise.all([
+ onmuteResolver.promise,
+ performOffer(caller, callee).then(() => {
+ eventSequence += 'setRemoteDescription;';
+ })
+ ]).then(t.step_func(() => {
+ assert_equals(eventSequence, 'track.onmute;setRemoteDescription;');
+ t.done();
+ }));
+ });
+ return offerPromise;
+ }))
+ .catch(t.step_func(reason => {
+ assert_unreached(reason);
+ }));
+ }, 'track.onmute fires before setRemoteDescription resolves.');
+
+ async_test(t => {
+ const pc = new RTCPeerConnection();
+ return getUserMediaTracksAndStreams(1)
+ .then(t.step_func(([tracks, streams]) => {
+ const sender = pc.addTrack(tracks[0]);
+ assert_not_equals(sender, null);
+ pc.removeTrack(sender);
+ pc.removeTrack(sender);
+ t.done();
+ }))
+ .catch(t.step_func(reason => {
+ assert_unreached(reason);
+ }));
+ }, 'removeTrack() twice is safe.');
</script>
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCRtpCapabilities-helper.js b/tests/wpt/web-platform-tests/webrtc/RTCRtpCapabilities-helper.js
index 8617e7f4f97..72f544059ff 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCRtpCapabilities-helper.js
+++ b/tests/wpt/web-platform-tests/webrtc/RTCRtpCapabilities-helper.js
@@ -48,5 +48,5 @@ function validateCodecCapability(codec) {
}
function validateHeaderExtensionCapability(headerExt) {
- assert_optional_string_field(uri);
+ assert_optional_string_field(headerExt, 'uri');
}
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCRtpSender-getStats.html b/tests/wpt/web-platform-tests/webrtc/RTCRtpSender-getStats.html
deleted file mode 100644
index 00aa680f53e..00000000000
--- a/tests/wpt/web-platform-tests/webrtc/RTCRtpSender-getStats.html
+++ /dev/null
@@ -1,54 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<title>RTCRtpSender.prototype.getStats</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="dictionary-helper.js"></script>
-<script src="RTCStats-helper.js"></script>
-<script>
- 'use strict';
-
- // Test is based on the following editor draft:
- // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
- // https://w3c.github.io/webrtc-stats/archives/20170614/webrtc-stats.html
-
- // The following helper function is called from RTCStats-helper.js
- // validateStatsReport
- // assert_stats_report_has_stats
-
- /*
- 5.2. RTCRtpSender Interface
- interface RTCRtpSender {
- Promise<RTCStatsReport> getStats();
- ...
- };
-
- getStats
- 1. Let selector be the RTCRtpSender object on which the method was invoked.
- 2. Let p be a new promise, and run the following steps in parallel:
- 1. Gather the stats indicated by selector according to the stats selection
- algorithm.
- 2. Resolve p with the resulting RTCStatsReport object, containing the
- gathered stats.
- 3. Return p.
-
- 8.5. The stats selection algorithm
- 3. If selector is an RTCRtpSender, gather stats for and add the following objects
- to result:
- - All RTCOutboundRTPStreamStats objects corresponding to selector.
- - All stats objects referenced directly or indirectly by the RTCOutboundRTPStreamStats
- objects added.
- */
-
- promise_test(() => {
- const pc = new RTCPeerConnection();
- const { sender } = pc.addTransceiver('audio');
-
- return sender.getStats()
- .then(statsReport => {
- validateStatsReport(statsReport);
- assert_stats_report_has_stats(statsReport, ['outbound-rtp']);
- });
- }, 'sender.getStats() should return stats report containing outbound-rtp stats');
-
-</script>
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCRtpSender-getStats.https.html b/tests/wpt/web-platform-tests/webrtc/RTCRtpSender-getStats.https.html
new file mode 100644
index 00000000000..e5cb1eb99fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webrtc/RTCRtpSender-getStats.https.html
@@ -0,0 +1,65 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>RTCRtpSender.prototype.getStats</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="dictionary-helper.js"></script>
+<script src="RTCStats-helper.js"></script>
+<script>
+ 'use strict';
+
+ // Test is based on the following editor draft:
+ // webrtc-pc 20171130
+ // webrtc-stats 20171122
+
+ // The following helper function is called from RTCStats-helper.js
+ // validateStatsReport
+ // assert_stats_report_has_stats
+
+ /*
+ 5.2. RTCRtpSender Interface
+ getStats
+ 1. Let selector be the RTCRtpSender object on which the method was invoked.
+ 2. Let p be a new promise, and run the following steps in parallel:
+ 1. Gather the stats indicated by selector according to the stats selection
+ algorithm.
+ 2. Resolve p with the resulting RTCStatsReport object, containing the
+ gathered stats.
+ 3. Return p.
+
+ 8.5. The stats selection algorithm
+ 3. If selector is an RTCRtpSender, gather stats for and add the following objects
+ to result:
+ - All RTCOutboundRTPStreamStats objects corresponding to selector.
+ - All stats objects referenced directly or indirectly by the RTCOutboundRTPStreamStats
+ objects added.
+ */
+
+ promise_test(() => {
+ const pc = new RTCPeerConnection();
+ const { sender } = pc.addTransceiver('audio');
+
+ return sender.getStats()
+ .then(statsReport => {
+ validateStatsReport(statsReport);
+ assert_stats_report_has_stats(statsReport, ['outbound-rtp']);
+ });
+ }, 'sender.getStats() via addTransceiver should return stats report containing outbound-rtp stats');
+
+ promise_test(() => {
+ const pc = new RTCPeerConnection();
+
+ return navigator.mediaDevices.getUserMedia({ audio: true })
+ .then(mediaStream => {
+ const [track] = mediaStream.getTracks();
+ const sender = pc.addTrack(track, mediaStream);
+
+ return sender.getStats()
+ .then(statsReport => {
+ validateStatsReport(statsReport);
+ assert_stats_report_has_stats(statsReport, ['outbound-rtp']);
+ });
+ })
+ }, 'sender.getStats() via addTrack should return stats report containing outbound-rtp stats');
+
+</script>
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCSctpTransport-maxMessageSize.html b/tests/wpt/web-platform-tests/webrtc/RTCSctpTransport-maxMessageSize.html
new file mode 100644
index 00000000000..7d73cc5a3b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webrtc/RTCSctpTransport-maxMessageSize.html
@@ -0,0 +1,181 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>RTCSctpTransport.prototype.maxMessageSize</title>
+<link rel="help" href="https://w3c.github.io/webrtc-pc/#rtcsctptransport-interface">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="RTCPeerConnection-helper.js"></script>
+<script>
+'use strict';
+
+// This test has an assert_unreached() that requires that the variable
+// canSendSize (initiated below) is greater than 2, if non-zero. The reason
+// is that we need two non-zero values that are less that that value for
+// testing with predictable results. This is a bit unfortunate but shouldn't
+// have any practical impact.
+
+// Helper class to read SDP attributes and generate SDPs with modified attribute values
+class SDPAttributeHelper {
+ constructor(attrName, valueRegExpStr) {
+ this.attrName = attrName;
+ this.re = new RegExp(`^a=${attrName}:(${valueRegExpStr})\\r\\n`, 'm');
+ }
+
+ getValue(sdp) {
+ const matches = sdp.match(this.re);
+ return matches ? matches[1] : null;
+ }
+
+ sdpWithValue(sdp, value) {
+ const matches = sdp.match(this.re);
+ const sdpParts = sdp.split(matches[0]);
+ const attributeLine = arguments.length > 1 ? `a=${this.attrName}:${value}\r\n` : '';
+ return `${sdpParts[0]}${attributeLine}${sdpParts[1]}`;
+ }
+
+ sdpWithoutAttribute(sdp) {
+ return this.sdpWithValue(sdp);
+ }
+}
+
+const mmsAttributeHelper = new SDPAttributeHelper('max-message-size', '\\d+');
+let canSendSize;
+const remoteValue1 = 1;
+const remoteValue2 = 2;
+
+promise_test(t => {
+ const pc = new RTCPeerConnection();
+ assert_equals(pc.sctp, null);
+ let maxMessageSize;
+
+ return generateOffer({ pc, data: true })
+ .then((offer) => {
+ assert_not_equals(mmsAttributeHelper.getValue(offer.sdp), null,
+ 'SDP should have max-message-size attribute');
+
+ offer = { type: 'offer', sdp: mmsAttributeHelper.sdpWithValue(offer.sdp, 0) };
+ return pc.setRemoteDescription(offer);
+ })
+ .then(() => pc.createAnswer())
+ .then((answer) => pc.setLocalDescription(answer))
+ .then(() => {
+ assert_not_equals(pc.sctp, null);
+ canSendSize = pc.sctp.maxMessageSize == Number.POSITIVE_INFINITY ? 0 : pc.sctp.maxMessageSize;
+ if (canSendSize != 0 && canSendSize < remoteValue2) {
+ assert_unreached('This test needs two values that are less than canSendSize (unless it is zero)');
+ }
+ });
+}, 'Determine the local side send limitation (canSendSize) by offering a max-message-size of 0');
+
+promise_test(t => {
+ const pc = new RTCPeerConnection();
+ assert_equals(pc.sctp, null);
+
+ return generateOffer({ pc, data: true })
+ .then((offer) => {
+ assert_not_equals(mmsAttributeHelper.getValue(offer.sdp), null,
+ 'SDP should have max-message-size attribute');
+
+ // Remove the max-message-size SDP attribute
+ offer = { type: 'offer', sdp: mmsAttributeHelper.sdpWithoutAttribute(offer.sdp) };
+ return pc.setRemoteDescription(offer)
+ })
+ .then(() => pc.createAnswer())
+ .then((answer) => pc.setLocalDescription(answer))
+ .then(() => {
+ assert_not_equals(pc.sctp, null);
+ // Test outcome depends on canSendSize value
+ if (canSendSize) {
+ assert_equals(pc.sctp.maxMessageSize, Math.min(65535, canSendSize),
+ 'Missing SDP attribute and a non-zero canSendSize should give an maxMessageSize of min(65535, canSendSize)');
+ } else {
+ assert_equals(pc.sctp.maxMessageSize, 65535,
+ 'Missing SDP attribute and a canSendSize of 0 should give an maxMessageSize of 65535');
+ }
+ });
+}, 'Remote offer SDP missing max-message-size attribute');
+
+promise_test(t => {
+ const pc = new RTCPeerConnection();
+ assert_equals(pc.sctp, null);
+
+ return generateOffer({ pc, data: true })
+ .then((offer) => {
+ assert_not_equals(mmsAttributeHelper.getValue(offer.sdp), null,
+ 'SDP should have max-message-size attribute');
+
+ offer = { type: 'offer', sdp: mmsAttributeHelper.sdpWithValue(offer.sdp, remoteValue1) };
+ return pc.setRemoteDescription(offer);
+ })
+ .then(() => pc.createAnswer())
+ .then((answer) => pc.setLocalDescription(answer))
+ .then(() => {
+ assert_not_equals(pc.sctp, null);
+ assert_equals(pc.sctp.maxMessageSize, remoteValue1,
+ 'maxMessageSize should be the value provided by the remote peer (as long as it is less than canSendSize)');
+ });
+}, 'max-message-size with a (non-zero) value provided by the remote peer');
+
+promise_test(t => {
+ const pc = new RTCPeerConnection();
+ assert_equals(pc.sctp, null);
+
+ return generateOffer({ pc, data: true })
+ .then((offer) => {
+ assert_not_equals(mmsAttributeHelper.getValue(offer.sdp), null,
+ 'SDP should have max-message-size attribute');
+
+ offer = { type: 'offer', sdp: mmsAttributeHelper.sdpWithValue(offer.sdp, remoteValue1) };
+ return pc.setRemoteDescription(offer)
+ })
+ .then(() => pc.createAnswer())
+ .then((answer) => pc.setLocalDescription(answer))
+ .then(() => {
+ assert_not_equals(pc.sctp, null);
+ assert_equals(pc.sctp.maxMessageSize, remoteValue1,
+ 'maxMessageSize should be the value provided by the remote peer (as long as it is less than canSendSize)');
+ })
+ .then(() => pc.createOffer()) // Start new O/A exchange that updates max-message-size
+ .then((offer) => {
+ offer = { type: 'offer', sdp: mmsAttributeHelper.sdpWithValue(offer.sdp, remoteValue2)};
+ return pc.setRemoteDescription(offer)
+ })
+ .then(() => pc.createAnswer())
+ .then((answer) => pc.setLocalDescription(answer))
+ .then(() => {
+ assert_not_equals(pc.sctp, null);
+ assert_equals(pc.sctp.maxMessageSize, remoteValue2,
+ 'maxMessageSize should be the new value provided by the remote peer (as long as it is less than canSendSize)');
+ })
+ ;
+}, 'Renegotiate max-message-size with a (non-zero) value provided by the remote peer');
+
+promise_test(t => {
+ const pc = new RTCPeerConnection();
+ assert_equals(pc.sctp, null);
+ const largerThanCanSendSize = canSendSize + 1;
+
+ return generateOffer({ pc, data: true })
+ .then((offer) => {
+ assert_not_equals(mmsAttributeHelper.getValue(offer.sdp), null,
+ 'SDP should have max-message-size attribute');
+
+ offer = { type: 'offer', sdp: mmsAttributeHelper.sdpWithValue(offer.sdp, largerThanCanSendSize) };
+ return pc.setRemoteDescription(offer)
+ })
+ .then(() => pc.createAnswer())
+ .then((answer) => pc.setLocalDescription(answer))
+ .then(() => {
+ assert_not_equals(pc.sctp, null);
+ // Test outcome depends on canSendSize value
+ if (canSendSize) {
+ assert_equals(pc.sctp.maxMessageSize, canSendSize,
+ 'A remote value larger than a non-zero canSendSize should limit maxMessageSize to canSendSize');
+ } else {
+ assert_equals(pc.sctp.maxMessageSize, 65535,
+ 'A canSendSize of zero should let the remote value set maxMessageSize');
+ }
+ });
+}, 'max-message-size with a (non-zero) value larger than canSendSize provided by the remote peer');
+
+</script>
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCStats-helper.js b/tests/wpt/web-platform-tests/webrtc/RTCStats-helper.js
index 1ff3ae6711b..c2be1b3124f 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCStats-helper.js
+++ b/tests/wpt/web-platform-tests/webrtc/RTCStats-helper.js
@@ -1,18 +1,12 @@
'use strict';
// Test is based on the following editor draft:
-// https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
-// https://w3c.github.io/webrtc-stats/archives/20170614/webrtc-stats.html
-
+// webrtc-pc 20171130
+// webrtc-stats 20171122
// This file depends on dictionary-helper.js which should
// be loaded from the main HTML file.
-// To improve readability, the WebIDL definitions of the Stats
-// dictionaries are modified to annotate with required fields when
-// they are required by section 8.6 of webrtc-pc. ID fields are
-// also annotated with the stats type that they are linked to.
-
/*
[webrtc-stats]
6.1. RTCStatsType enum
@@ -82,6 +76,16 @@ function assert_stats_report_has_stats(statsReport, statsTypes) {
}
}
+function findStatsFromReport(statsReport, predicate, message) {
+ for (const stats of statsReport.values()) {
+ if (predicate(stats)) {
+ return stats;
+ }
+ }
+
+ assert_unreached(message || 'none of stats in statsReport satisfy given condition')
+}
+
// Get stats object of type that is expected to be
// found in the statsReport
function getRequiredStats(statsReport, type) {
@@ -132,7 +136,7 @@ function validateOptionalIdField(statsReport, stats, field, type) {
};
*/
function validateRtcStats(statsReport, stats) {
- assert_number_field(stats, 'timeStamp');
+ assert_number_field(stats, 'timestamp');
assert_string_field(stats, 'type');
assert_string_field(stats, 'id');
}
@@ -141,35 +145,32 @@ function validateRtcStats(statsReport, stats) {
[webrtc-stats]
7.1. RTCRTPStreamStats dictionary
dictionary RTCRTPStreamStats : RTCStats {
- required unsigned long ssrc;
- required DOMString mediaType;
-
- [RTCMediaStreamTrackStats]
- required DOMString trackId;
-
- [RTCTransportStats]
- required DOMString transportId;
-
- [RTCCodecStats]
- required DOMString codecId;
-
- unsigned long firCount;
- unsigned long pliCount;
- required unsigned long nackCount;
- unsigned long sliCount;
- unsigned long long qpSum;
+ unsigned long ssrc;
+ DOMString mediaType;
+ DOMString trackId;
+ DOMString transportId;
+ DOMString codecId;
+ unsigned long firCount;
+ unsigned long pliCount;
+ unsigned long nackCount;
+ unsigned long sliCount;
+ unsigned long long qpSum;
};
+ mediaType of type DOMString
+ Either "audio" or "video".
+
[webrtc-pc]
8.6. Mandatory To Implement Stats
- - RTCRTPStreamStats, with attributes ssrc, associateStatsId, isRemote, mediaType,
- mediaTrackId, transportId, codecId, nackCount
+ - RTCRTPStreamStats, with attributes ssrc, mediaType, trackId,
+ transportId, codecId, nackCount
*/
function validateRtpStreamStats(statsReport, stats) {
validateRtcStats(statsReport, stats);
assert_unsigned_int_field(stats, 'ssrc');
assert_string_field(stats, 'mediaType');
+ assert_enum_field(stats, 'mediaType', ['audio', 'video'])
validateIdField(statsReport, stats, 'trackId', 'track');
validateIdField(statsReport, stats, 'transportId', 'transport');
@@ -186,15 +187,12 @@ function validateRtpStreamStats(statsReport, stats) {
[webrtc-stats]
7.2. RTCCodecStats dictionary
dictionary RTCCodecStats : RTCStats {
- required unsigned long payloadType;
- required RTCCodecType codecType;
-
- [RTCTransportStats]
+ unsigned long payloadType;
+ RTCCodecType codecType;
DOMString transportId;
-
DOMString mimeType;
- required unsigned long clockRate;
- required unsigned long channels;
+ unsigned long clockRate;
+ unsigned long channels;
DOMString sdpFmtpLine;
DOMString implementation;
};
@@ -206,7 +204,7 @@ function validateRtpStreamStats(statsReport, stats) {
[webrtc-pc]
8.6. Mandatory To Implement Stats
- - RTCCodecStats, with attributes payloadType, codec, clockRate, channels, parameters
+ - RTCCodecStats, with attributes payloadType, codec, clockRate, channels, sdpFmtpLine
*/
function validateCodecStats(statsReport, stats) {
@@ -221,7 +219,7 @@ function validateCodecStats(statsReport, stats) {
assert_unsigned_int_field(stats, 'clockRate');
assert_unsigned_int_field(stats, 'channels');
- assert_optional_string_field(stats, 'sdpFmtpLine');
+ assert_string_field(stats, 'sdpFmtpLine');
assert_optional_string_field(stats, 'implementation');
}
@@ -229,34 +227,42 @@ function validateCodecStats(statsReport, stats) {
[webrtc-stats]
7.3. RTCReceivedRTPStreamStats dictionary
dictionary RTCReceivedRTPStreamStats : RTCRTPStreamStats {
- unsigned long packetsReceived;
- unsigned long long bytesReceived;
- unsigned long packetsLost;
- double jitter;
- double fractionLost;
- unsigned long packetsDiscarded;
- unsigned long packetsRepaired;
- unsigned long burstPacketsLost;
- unsigned long burstPacketsDiscarded;
- unsigned long burstLossCount;
- unsigned long burstDiscardCount;
- double burstLossRate;
- double burstDiscardRate;
- double gapLossRate;
- double gapDiscardRate;
+ unsigned long packetsReceived;
+ unsigned long long bytesReceived;
+ long packetsLost;
+ double jitter;
+ double fractionLost;
+ unsigned long packetsDiscarded;
+ unsigned long packetsFailedDecryption;
+ unsigned long packetsRepaired;
+ unsigned long burstPacketsLost;
+ unsigned long burstPacketsDiscarded;
+ unsigned long burstLossCount;
+ unsigned long burstDiscardCount;
+ double burstLossRate;
+ double burstDiscardRate;
+ double gapLossRate;
+ double gapDiscardRate;
};
+
+ [webrtc-pc]
+ 8.6. Mandatory To Implement Stats
+ - RTCReceivedRTPStreamStats, with all required attributes from its
+ inherited dictionaries, and also attributes packetsReceived,
+ bytesReceived, packetsLost, jitter, packetsDiscarded
*/
function validateReceivedRtpStreamStats(statsReport, stats) {
validateRtpStreamStats(statsReport, stats);
- assert_optional_unsigned_int_field(stats, 'packetsReceived');
- assert_optional_unsigned_int_field(stats, 'bytesReceived');
- assert_optional_unsigned_int_field(stats, 'packetsLost');
+ assert_unsigned_int_field(stats, 'packetsReceived');
+ assert_unsigned_int_field(stats, 'bytesReceived');
+ assert_unsigned_int_field(stats, 'packetsLost');
- assert_optional_number_field(stats, 'jitter');
+ assert_number_field(stats, 'jitter');
assert_optional_number_field(stats, 'fractionLost');
- assert_optional_unsigned_int_field(stats, 'packetsDiscarded');
+ assert_unsigned_int_field(stats, 'packetsDiscarded');
+ assert_optional_unsigned_int_field(stats, 'packetsFailedDecryption');
assert_optional_unsigned_int_field(stats, 'packetsRepaired');
assert_optional_unsigned_int_field(stats, 'burstPacketsLost');
assert_optional_unsigned_int_field(stats, 'burstPacketsDiscarded');
@@ -273,37 +279,21 @@ function validateReceivedRtpStreamStats(statsReport, stats) {
[webrtc-stats]
7.4. RTCInboundRTPStreamStats dictionary
dictionary RTCInboundRTPStreamStats : RTCReceivedRTPStreamStats {
- required unsigned long packetsReceived;
- required unsigned long long bytesReceived;
- required unsigned long packetsLost;
- required double jitter;
- required unsigned long packetsDiscarded;
-
- [RTCRemoteOutboundRTPStreamStats]
DOMString remoteId;
-
unsigned long framesDecoded;
DOMHighResTimeStamp lastPacketReceivedTimestamp;
};
[webrtc-pc]
8.6. Mandatory To Implement Stats
- - RTCInboundRTPStreamStats, with all required attributes from RTCRTPStreamStats,
- and also attributes packetsReceived, bytesReceived, packetsLost, jitter,
- packetsDiscarded
+ - RTCInboundRTPStreamStats, with all required attributes from its inherited
+ dictionaries, and also attributes remoteId, framesDecoded
*/
function validateInboundRtpStreamStats(statsReport, stats) {
validateReceivedRtpStreamStats(statsReport, stats);
- assert_unsigned_int_field(stats, 'packetsReceived');
- assert_unsigned_int_field(stats, 'bytesReceived');
- assert_unsigned_int_field(stats, 'packetsLost');
- assert_number_field(stats, 'jitter');
- assert_unsigned_int_field(stats, 'packetsDiscarded');
-
- validateOptionalIdField(statsReport, stats, 'remoteId', 'remote-outbound-rtp');
-
- assert_optional_unsigned_int_field(stats, 'framesDecoded');
+ validateIdField(statsReport, stats, 'remoteId', 'remote-outbound-rtp');
+ assert_unsigned_int_field(stats, 'framesDecoded');
assert_optional_number_field(stats, 'lastPacketReceivedTimeStamp');
}
@@ -311,18 +301,20 @@ function validateInboundRtpStreamStats(statsReport, stats) {
[webrtc-stats]
7.5. RTCRemoteInboundRTPStreamStats dictionary
dictionary RTCRemoteInboundRTPStreamStats : RTCReceivedRTPStreamStats {
- [RTCOutboundRTPStreamStats]
- DOMString localId;
-
- double roundTripTime;
+ DOMString localId;
+ double roundTripTime;
};
- */
+ [webrtc-pc]
+ 8.6. Mandatory To Implement Stats
+ - RTCRemoteInboundRTPStreamStats, with all required attributes from its
+ inherited dictionaries, and also attributes localId, roundTripTime
+ */
function validateRemoteInboundRtpStreamStats(statsReport, stats) {
validateReceivedRtpStreamStats(statsReport, stats);
- validateOptionalIdField(statsReport, stats, 'localId', 'outbound-rtp');
- assert_optional_number_field(stats, 'roundTripTime');
+ validateIdField(statsReport, stats, 'localId', 'outbound-rtp');
+ assert_number_field(stats, 'roundTripTime');
}
/*
@@ -334,13 +326,18 @@ function validateRemoteInboundRtpStreamStats(statsReport, stats) {
unsigned long long bytesSent;
unsigned long long bytesDiscardedOnSend;
};
+
+ [webrtc-pc]
+ 8.6. Mandatory To Implement Stats
+ - RTCSentRTPStreamStats, with all required attributes from its inherited
+ dictionaries, and also attributes packetsSent, bytesSent
*/
function validateSentRtpStreamStats(statsReport, stats) {
validateRtpStreamStats(statsReport, stats);
- assert_optional_unsigned_int_field(stats, 'packetsSent');
+ assert_unsigned_int_field(stats, 'packetsSent');
assert_optional_unsigned_int_field(stats, 'packetsDiscardedOnSend');
- assert_optional_unsigned_int_field(stats, 'bytesSent');
+ assert_unsigned_int_field(stats, 'bytesSent');
assert_optional_unsigned_int_field(stats, 'bytesDiscardedOnSend');
}
@@ -348,12 +345,7 @@ function validateSentRtpStreamStats(statsReport, stats) {
[webrtc-stats]
7.7. RTCOutboundRTPStreamStats dictionary
dictionary RTCOutboundRTPStreamStats : RTCSentRTPStreamStats {
- required unsigned long packetsSent;
- required unsigned long long bytesSent;
-
- [RTCRemoteInboundRTPStreamStats]
DOMString remoteId;
-
DOMHighResTimeStamp lastPacketSentTimestamp;
double targetBitrate;
unsigned long framesEncoded;
@@ -361,20 +353,19 @@ function validateSentRtpStreamStats(statsReport, stats) {
double averageRTCPInterval;
};
- [webrtc-pc]
- 8.6. Mandatory To Implement Stats
- - RTCOutboundRTPStreamStats, with all required attributes from RTCRTPStreamStats,
- and also attributes packetsSent, bytesSent, roundTripTime
+ [webrtc-pc]
+ 8.6. Mandatory To Implement Stats
+ - RTCOutboundRTPStreamStats, with all required attributes from its
+ inherited dictionaries, and also attributes remoteId, framesEncoded
*/
function validateOutboundRtpStreamStats(statsReport, stats) {
- validateOptionalIdField(statsReport, stats, 'remoteId', 'remote-inbound-rtp');
+ validateSentRtpStreamStats(statsReport, stats)
- assert_unsigned_int_field(stats, 'packetsSent');
- assert_unsigned_int_field(stats, 'bytesSent');
+ validateIdField(statsReport, stats, 'remoteId', 'remote-inbound-rtp');
assert_optional_number_field(stats, 'lastPacketSentTimestamp');
assert_optional_number_field(stats, 'targetBitrate');
- assert_optional_unsigned_int_field(stats, 'framesEncoded');
+ assert_unsigned_int_field(stats, 'framesEncoded');
assert_optional_number_field(stats, 'totalEncodeTime');
assert_optional_number_field(stats, 'averageRTCPInterval');
}
@@ -383,17 +374,20 @@ function validateOutboundRtpStreamStats(statsReport, stats) {
[webrtc-stats]
7.8. RTCRemoteOutboundRTPStreamStats dictionary
dictionary RTCRemoteOutboundRTPStreamStats : RTCSentRTPStreamStats {
- [RTCInboundRTPStreamStats]
DOMString localId;
-
DOMHighResTimeStamp remoteTimestamp;
};
+
+ [webrtc-pc]
+ 8.6. Mandatory To Implement Stats
+ - RTCRemoteOutboundRTPStreamStats, with all required attributes from its
+ inherited dictionaries, and also attributes localId, remoteTimestamp
*/
function validateRemoteOutboundRtpStreamStats(statsReport, stats) {
validateSentRtpStreamStats(statsReport, stats);
- validateOptionalIdField(statsReport, stats, 'localId', 'inbound-rtp');
- assert_optional_number_field(stats, 'remoteTimeStamp');
+ validateIdField(statsReport, stats, 'localId', 'inbound-rtp');
+ assert_number_field(stats, 'remoteTimeStamp');
}
/*
@@ -401,10 +395,7 @@ function validateRemoteOutboundRtpStreamStats(statsReport, stats) {
7.9. RTCRTPContributingSourceStats
dictionary RTCRTPContributingSourceStats : RTCStats {
unsigned long contributorSsrc;
-
- [RTCInboundRTPStreamStats]
DOMString inboundRtpStreamId;
-
unsigned long packetsContributedTo;
double audioLevel;
};
@@ -423,10 +414,10 @@ function validateContributingSourceStats(statsReport, stats) {
[webrtc-stats]
7.10. RTCPeerConnectionStats dictionary
dictionary RTCPeerConnectionStats : RTCStats {
- required unsigned long dataChannelsOpened;
- required unsigned long dataChannelsClosed;
- unsigned long dataChannelsRequested;
- unsigned long dataChannelsAccepted;
+ unsigned long dataChannelsOpened;
+ unsigned long dataChannelsClosed;
+ unsigned long dataChannelsRequested;
+ unsigned long dataChannelsAccepted;
};
[webrtc-pc]
@@ -446,10 +437,8 @@ function validatePeerConnectionStats(statsReport, stats) {
[webrtc-stats]
7.11. RTCMediaStreamStats dictionary
dictionary RTCMediaStreamStats : RTCStats {
- required DOMString streamIdentifier;
-
- [RTCMediaStreamTrackStats]
- required sequence<DOMString> trackIds;
+ DOMString streamIdentifier;
+ sequence<DOMString> trackIds;
};
[webrtc-pc]
@@ -479,35 +468,37 @@ function validateMediaStreamStats(statsReport, stats) {
[webrtc-stats]
7.12. RTCMediaStreamTrackStats dictionary
dictionary RTCMediaStreamTrackStats : RTCStats {
- required DOMString trackIdentifier;
- required boolean remoteSource;
- required boolean ended;
- required boolean detached;
- DOMString kind;
- DOMHighResTimeStamp estimatedPlayoutTimestamp;
- required unsigned long frameWidth;
- required unsigned long frameHeight;
- required double framesPerSecond;
- unsigned long framesCaptured;
- required unsigned long framesSent;
- required unsigned long framesReceived;
- required unsigned long framesDecoded;
- required unsigned long framesDropped;
- required unsigned long framesCorrupted;
- unsigned long partialFramesLost;
- unsigned long fullFramesLost;
- required double audioLevel;
- double totalAudioEnergy;
- boolean voiceActivityFlag;
- double echoReturnLoss;
- double echoReturnLossEnhancement;
- unsigned long long totalSamplesSent;
- unsigned long long totalSamplesReceived;
- double totalSamplesDuration;
- unsigned long long concealedSamples;
- unsigned long long concealmentEvents;
- double jitterBufferDelay;
- RTCPriorityType priority;
+ DOMString trackIdentifier;
+ boolean remoteSource;
+ boolean ended;
+ boolean detached;
+ DOMString kind;
+ DOMHighResTimeStamp estimatedPlayoutTimestamp;
+ unsigned long frameWidth;
+ unsigned long frameHeight;
+ double framesPerSecond;
+ unsigned long framesCaptured;
+ unsigned long framesSent;
+ unsigned long keyFramesSent;
+ unsigned long framesReceived;
+ unsigned long keyFramesReceived;
+ unsigned long framesDecoded;
+ unsigned long framesDropped;
+ unsigned long framesCorrupted;
+ unsigned long partialFramesLost;
+ unsigned long fullFramesLost;
+ double audioLevel;
+ double totalAudioEnergy;
+ boolean voiceActivityFlag;
+ double echoReturnLoss;
+ double echoReturnLossEnhancement;
+ unsigned long long totalSamplesSent;
+ unsigned long long totalSamplesReceived;
+ double totalSamplesDuration;
+ unsigned long long concealedSamples;
+ unsigned long long concealmentEvents;
+ double jitterBufferDelay;
+ RTCPriorityType priority;
};
[webrtc-pc]
@@ -520,48 +511,50 @@ function validateMediaStreamStats(statsReport, stats) {
};
8.6. Mandatory To Implement Stats
- - RTCMediaStreamTrackStats, with attributes trackIdentifier, remoteSource, ended,
- detached, ssrcIds, frameWidth, frameHeight, framesPerSecond, framesSent,
+ - RTCMediaStreamTrackStats, with attributes trackIdentifier, remoteSource,
+ ended, detached, frameWidth, frameHeight, framesPerSecond, framesSent,
framesReceived, framesDecoded, framesDropped, framesCorrupted, audioLevel
*/
-function validateMediaStreamTrackStats(stats, stat) {
+function validateMediaStreamTrackStats(statsReport, stats) {
validateRtcStats(statsReport, stats);
- assert_string_field(stat, 'trackIdentifier');
- assert_boolean_field(stat, 'remoteSource');
- assert_boolean_field(stat, 'ended');
- assert_boolean_field(stat, 'detached');
-
- assert_optional_string_field(stat, 'kind');
- assert_optional_number_field(stat, 'estimatedPlayoutTimestamp');
-
- assert_unsigned_int_field(stat, 'frameWidth');
- assert_unsigned_int_field(stat, 'frameHeight');
- assert_number_field(stat, 'framesPerSecond');
-
- assert_optional_unsigned_int_field(stat, 'framesCaptured');
- assert_unsigned_int_field(stat, 'frameSent');
- assert_unsigned_int_field(stat, 'frameReceived');
- assert_unsigned_int_field(stat, 'frameDecoded');
- assert_unsigned_int_field(stat, 'frameDropped');
- assert_unsigned_int_field(stat, 'frameCorrupted');
-
- assert_optional_unsigned_int_field(stat, 'partialFramesLost');
- assert_optional_unsigned_int_field(stat, 'fullFramesLost');
-
- assert_number_field(stat, 'audioLevel');
- assert_optional_number_field(stat, 'totalAudioEnergy');
- assert_optional_boolean_field(stat, 'voiceActivityFlag');
- assert_optional_number_field(stat, 'echoReturnLoss');
- assert_optional_number_field(stat, 'echoReturnLossEnhancement');
-
- assert_optional_unsigned_int_field(stat, 'totalSamplesSent');
- assert_optional_unsigned_int_field(stat, 'totalSamplesReceived');
- assert_optional_number_field(stat, 'totalSamplesDuration');
- assert_optional_unsigned_int_field(stat, 'concealedSamples');
- assert_optional_unsigned_int_field(stat, 'concealmentEvents');
- assert_optional_number_field(stat, 'jitterBufferDelay');
+ assert_string_field(stats, 'trackIdentifier');
+ assert_boolean_field(stats, 'remoteSource');
+ assert_boolean_field(stats, 'ended');
+ assert_boolean_field(stats, 'detached');
+
+ assert_optional_enum_field(stats, 'kind', ['audio', 'video']);
+ assert_optional_number_field(stats, 'estimatedPlayoutTimestamp');
+
+ assert_unsigned_int_field(stats, 'frameWidth');
+ assert_unsigned_int_field(stats, 'frameHeight');
+ assert_number_field(stats, 'framesPerSecond');
+
+ assert_optional_unsigned_int_field(stats, 'framesCaptured');
+ assert_unsigned_int_field(stats, 'framesSent');
+ assert_optional_unsigned_int_field(stats, 'keyFramesSent');
+ assert_unsigned_int_field(stats, 'framesReceived');
+ assert_optional_unsigned_int_field(stats, 'keyFramesReceived');
+ assert_unsigned_int_field(stats, 'framesDecoded');
+ assert_unsigned_int_field(stats, 'framesDropped');
+ assert_unsigned_int_field(stats, 'framesCorrupted');
+
+ assert_optional_unsigned_int_field(stats, 'partialFramesLost');
+ assert_optional_unsigned_int_field(stats, 'fullFramesLost');
+
+ assert_number_field(stats, 'audioLevel');
+ assert_optional_number_field(stats, 'totalAudioEnergy');
+ assert_optional_boolean_field(stats, 'voiceActivityFlag');
+ assert_optional_number_field(stats, 'echoReturnLoss');
+ assert_optional_number_field(stats, 'echoReturnLossEnhancement');
+
+ assert_optional_unsigned_int_field(stats, 'totalSamplesSent');
+ assert_optional_unsigned_int_field(stats, 'totalSamplesReceived');
+ assert_optional_number_field(stats, 'totalSamplesDuration');
+ assert_optional_unsigned_int_field(stats, 'concealedSamples');
+ assert_optional_unsigned_int_field(stats, 'concealmentEvents');
+ assert_optional_number_field(stats, 'jitterBufferDelay');
assert_optional_enum_field(stats, 'priority',
['very-low', 'low', 'medium', 'high']);
@@ -571,18 +564,15 @@ function validateMediaStreamTrackStats(stats, stat) {
[webrtc-stats]
7.13. RTCDataChannelStats dictionary
dictionary RTCDataChannelStats : RTCStats {
- required DOMString label;
- required DOMString protocol;
- required long datachannelid;
-
- [RTCTransportStats]
- DOMString transportId;
-
- required RTCDataChannelState state;
- required unsigned long messagesSent;
- required unsigned long long bytesSent;
- required unsigned long messagesReceived;
- required unsigned long long bytesReceived;
+ DOMString label;
+ DOMString protocol;
+ long dataChannelIdentifier;
+ DOMString transportId;
+ RTCDataChannelState state;
+ unsigned long messagesSent;
+ unsigned long long bytesSent;
+ unsigned long messagesReceived;
+ unsigned long long bytesReceived;
};
[webrtc-pc]
@@ -598,22 +588,19 @@ function validateMediaStreamTrackStats(stats, stat) {
- RTCDataChannelStats, with attributes label, protocol, datachannelId, state,
messagesSent, bytesSent, messagesReceived, bytesReceived
*/
-
function validateDataChannelStats(statsReport, stats) {
validateRtcStats(statsReport, stats);
assert_string_field(stats, 'label');
assert_string_field(stats, 'protocol');
- assert_int_field(stats, 'datachannelid');
+ assert_int_field(stats, 'dataChannelIdentifier');
validateOptionalIdField(statsReport, stats, 'transportId', 'transport');
assert_enum_field(stats, 'state',
['connecting', 'open', 'closing', 'closed']);
- assert_unsigned_int_field(stats, 'messageSent');
-
- assert_unsigned_int_field(stats, 'messageSent');
+ assert_unsigned_int_field(stats, 'messagesSent');
assert_unsigned_int_field(stats, 'bytesSent');
assert_unsigned_int_field(stats, 'messagesReceived');
assert_unsigned_int_field(stats, 'bytesReceived');
@@ -623,25 +610,16 @@ function validateDataChannelStats(statsReport, stats) {
[webrtc-stats]
7.14. RTCTransportStats dictionary
dictionary RTCTransportStats : RTCStats {
- unsigned long packetsSent;
- unsigned long packetsReceived;
- required unsigned long long bytesSent;
- required unsigned long long bytesReceived;
-
- [RTCTransportStats]
- required DOMString rtcpTransportStatsId;
-
- RTCIceRole iceRole;
- RTCDtlsTransportState dtlsState;
-
- [RTCIceCandidatePairStats]
- required DOMString selectedCandidatePairId;
-
- [RTCCertificateStats]
- required DOMString localCertificateId;
-
- [RTCCertificateStats]
- required DOMString remoteCertificateId;
+ unsigned long packetsSent;
+ unsigned long packetsReceived;
+ unsigned long long bytesSent;
+ unsigned long long bytesReceived;
+ DOMString rtcpTransportStatsId;
+ RTCIceRole iceRole;
+ RTCDtlsTransportState dtlsState;
+ DOMString selectedCandidatePairId;
+ DOMString localCertificateId;
+ DOMString remoteCertificateId;
};
[webrtc-pc]
@@ -661,10 +639,10 @@ function validateDataChannelStats(statsReport, stats) {
};
8.6. Mandatory To Implement Stats
- - RTCTransportStats, with attributes bytesSent, bytesReceived, rtcpTransportStatsId,
- activeConnection, selectedCandidatePairId, localCertificateId, remoteCertificateId
+ - RTCTransportStats, with attributes bytesSent, bytesReceived,
+ rtcpTransportStatsId, selectedCandidatePairId, localCertificateId,
+ remoteCertificateId
*/
-
function validateTransportStats(statsReport, stats) {
validateRtcStats(statsReport, stats);
@@ -682,26 +660,35 @@ function validateTransportStats(statsReport, stats) {
['new', 'connecting', 'connected', 'closed', 'failed']);
validateIdField(statsReport, stats, 'selectedCandidatePairId', 'candidate-pair');
- validateIdField(stateReport, stats, 'localCertificateId', 'certificate');
- validateIdField(stateReport, stats, 'remoteCertificateId', 'certificate');
+ validateIdField(statsReport, stats, 'localCertificateId', 'certificate');
+ validateIdField(statsReport, stats, 'remoteCertificateId', 'certificate');
}
/*
[webrtc-stats]
7.15. RTCIceCandidateStats dictionary
dictionary RTCIceCandidateStats : RTCStats {
- [RTCTransportStats]
- DOMString transportId;
-
- boolean isRemote;
- required DOMString ip;
- required long port;
- required DOMString protocol;
- required RTCIceCandidateType candidateType;
- required long priority;
- required DOMString url;
- DOMString relayProtocol;
- boolean deleted = false;
+ DOMString transportId;
+ boolean isRemote;
+ RTCNetworkType networkType;
+ DOMString ip;
+ long port;
+ DOMString protocol;
+ RTCIceCandidateType candidateType;
+ long priority;
+ DOMString url;
+ DOMString relayProtocol;
+ boolean deleted = false;
+ };
+
+ enum RTCNetworkType {
+ "bluetooth",
+ "cellular",
+ "ethernet",
+ "wifi",
+ "wimax",
+ "vpn",
+ "unknown"
};
[webrtc-pc]
@@ -714,16 +701,18 @@ function validateTransportStats(statsReport, stats) {
};
8.6. Mandatory To Implement Stats
- - RTCIceCandidateStats, with attributes ip, port, protocol, candidateType, priority,
- url
+ - RTCIceCandidateStats, with attributes ip, port, protocol, candidateType,
+ priority, url
*/
-
function validateIceCandidateStats(statsReport, stats) {
validateRtcStats(statsReport, stats);
validateOptionalIdField(statsReport, stats, 'transportId', 'transport');
assert_optional_boolean_field(stats, 'isRemote');
+ assert_optional_enum_field(stats, 'networkType',
+ ['bluetooth', 'cellular', 'ethernet', 'wifi', 'wimax', 'vpn', 'unknown'])
+
assert_string_field(stats, 'ip');
assert_int_field(stats, 'port');
assert_string_field(stats, 'protocol');
@@ -741,40 +730,34 @@ function validateIceCandidateStats(statsReport, stats) {
[webrtc-stats]
7.16. RTCIceCandidatePairStats dictionary
dictionary RTCIceCandidatePairStats : RTCStats {
- [RTCTransportStats]
- required DOMString transportId;
-
- [RTCIceCandidateStats]
- required DOMString localCandidateId;
-
- [RTCIceCandidateStats]
- required DOMString remoteCandidateId;
-
- required RTCStatsIceCandidatePairState state;
- required unsigned long long priority;
- required boolean nominated;
- unsigned long packetsSent;
- unsigned long packetsReceived;
- required unsigned long long bytesSent;
- required unsigned long long bytesReceived;
- DOMHighResTimeStamp lastPacketSentTimestamp;
- DOMHighResTimeStamp lastPacketReceivedTimestamp;
- DOMHighResTimeStamp firstRequestTimestamp;
- DOMHighResTimeStamp lastRequestTimestamp;
- DOMHighResTimeStamp lastResponseTimestamp;
- required double totalRoundTripTime;
- required double currentRoundTripTime;
- double availableOutgoingBitrate;
- double availableIncomingBitrate;
- unsigned long circuitBreakerTriggerCount;
- unsigned long long requestsReceived;
- unsigned long long requestsSent;
- unsigned long long responsesReceived;
- unsigned long long responsesSent;
- unsigned long long retransmissionsReceived;
- unsigned long long retransmissionsSent;
- unsigned long long consentRequestsSent;
- DOMHighResTimeStamp consentExpiredTimestamp;
+ DOMString transportId;
+ DOMString localCandidateId;
+ DOMString remoteCandidateId;
+ RTCStatsIceCandidatePairState state;
+ unsigned long long priority;
+ boolean nominated;
+ unsigned long packetsSent;
+ unsigned long packetsReceived;
+ unsigned long long bytesSent;
+ unsigned long long bytesReceived;
+ DOMHighResTimeStamp lastPacketSentTimestamp;
+ DOMHighResTimeStamp lastPacketReceivedTimestamp;
+ DOMHighResTimeStamp firstRequestTimestamp;
+ DOMHighResTimeStamp lastRequestTimestamp;
+ DOMHighResTimeStamp lastResponseTimestamp;
+ double totalRoundTripTime;
+ double currentRoundTripTime;
+ double availableOutgoingBitrate;
+ double availableIncomingBitrate;
+ unsigned long circuitBreakerTriggerCount;
+ unsigned long long requestsReceived;
+ unsigned long long requestsSent;
+ unsigned long long responsesReceived;
+ unsigned long long responsesSent;
+ unsigned long long retransmissionsReceived;
+ unsigned long long retransmissionsSent;
+ unsigned long long consentRequestsSent;
+ DOMHighResTimeStamp consentExpiredTimestamp;
};
enum RTCStatsIceCandidatePairState {
@@ -788,8 +771,7 @@ function validateIceCandidateStats(statsReport, stats) {
[webrtc-pc]
8.6. Mandatory To Implement Stats
- RTCIceCandidatePairStats, with attributes transportId, localCandidateId,
- remoteCandidateId, state, priority, nominated, writable, readable, bytesSent,
- bytesReceived, totalRtt, currentRtt
+ remoteCandidateId, state, priority, nominated, bytesSent, bytesReceived, totalRoundTripTime, currentRoundTripTime
*/
function validateIceCandidatePairStats(statsReport, stats) {
validateRtcStats(statsReport, stats);
@@ -835,10 +817,10 @@ function validateIceCandidatePairStats(statsReport, stats) {
[webrtc-stats]
7.17. RTCCertificateStats dictionary
dictionary RTCCertificateStats : RTCStats {
- required DOMString fingerprint;
- required DOMString fingerprintAlgorithm;
- required DOMString base64Certificate;
- required DOMString issuerCertificateId;
+ DOMString fingerprint;
+ DOMString fingerprintAlgorithm;
+ DOMString base64Certificate;
+ DOMString issuerCertificateId;
};
[webrtc-pc]
@@ -846,7 +828,6 @@ function validateIceCandidatePairStats(statsReport, stats) {
- RTCCertificateStats, with attributes fingerprint, fingerprintAlgorithm,
base64Certificate, issuerCertificateId
*/
-
function validateCertificateStats(statsReport, stats) {
validateRtcStats(statsReport, stats);
diff --git a/tests/wpt/web-platform-tests/webrtc/RTCTrackEvent-constructor.html b/tests/wpt/web-platform-tests/webrtc/RTCTrackEvent-constructor.html
index d5c5f621f80..9579dd4d4f8 100644
--- a/tests/wpt/web-platform-tests/webrtc/RTCTrackEvent-constructor.html
+++ b/tests/wpt/web-platform-tests/webrtc/RTCTrackEvent-constructor.html
@@ -41,6 +41,7 @@
assert_equals(trackEvent.receiver, receiver);
assert_equals(trackEvent.track, track);
assert_array_equals(trackEvent.streams, []);
+ assert_equals(trackEvent.streams, trackEvent.streams); // [SameObject]
assert_equals(trackEvent.transceiver, transceiver);
assert_equals(trackEvent.type, 'track');
diff --git a/tests/wpt/web-platform-tests/webrtc/datachannel-idlharness.html b/tests/wpt/web-platform-tests/webrtc/datachannel-idlharness.html
deleted file mode 100644
index ea2dd2a3df9..00000000000
--- a/tests/wpt/web-platform-tests/webrtc/datachannel-idlharness.html
+++ /dev/null
@@ -1,75 +0,0 @@
-<!doctype html>
-<!--
-This test creates a data channel object and compares it with the WebIDL defined interface
--->
-
-<html>
-<head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <title>RTCPeerConnection Data Channel Empty String Test</title>
- <link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
- <link rel="help" href="http://w3c.github.io/webrtc-pc/#rtcdatachannel">
-</head>
-<body>
- <div id="log"></div>
- <!-- These files are in place when executing on W3C. -->
- <script src="/resources/testharness.js"></script>
- <script src="/resources/testharnessreport.js"></script>
- <script src=/resources/WebIDLParser.js></script>
- <script src=/resources/idlharness.js></script>
- <!-- The IDL is copied from https://w3c.github.io/webrtc-pc/archives/20161219/webrtc.html -->
- <script type="text/plain">
-interface RTCDataChannel : EventTarget {
- readonly attribute USVString label;
- readonly attribute boolean ordered;
- readonly attribute unsigned short? maxPacketLifeTime;
- readonly attribute unsigned short? maxRetransmits;
- readonly attribute USVString protocol;
- readonly attribute boolean negotiated;
- readonly attribute unsigned short id;
- readonly attribute RTCPriorityType priority;
- readonly attribute RTCDataChannelState readyState;
- readonly attribute unsigned long bufferedAmount;
- attribute unsigned long bufferedAmountLowThreshold;
- attribute EventHandler onopen;
- attribute EventHandler onbufferedamountlow;
- attribute EventHandler onerror;
- attribute EventHandler onclose;
- void close();
- attribute EventHandler onmessage;
- attribute DOMString binaryType;
- void send(USVString data);
- void send(Blob data);
- void send(ArrayBuffer data);
- void send(ArrayBufferView data);
-};
-enum RTCPriorityType {
- "very-low",
- "low",
- "medium",
- "high"
-};
-enum RTCDataChannelState {
- "connecting",
- "open",
- "closing",
- "closed"
-};
-</script>
- <script type="text/javascript">
- (function() {
- var idl_array = new IdlArray();
- [].forEach.call(document.querySelectorAll("script[type=text\\/plain]"),
- function(node) {
- idl_array.add_idls(node.textContent);
- });
- pc = new RTCPeerConnection(null);
- window.channel = pc.createDataChannel("test");
- idl_array.add_objects({"RTCDataChannel": ["channel"]});
- idl_array.test();
- done();
-})();
-</script>
-</body>
-</html>
-
diff --git a/tests/wpt/web-platform-tests/webrtc/tools/.eslintrc.js b/tests/wpt/web-platform-tests/webrtc/tools/.eslintrc.js
new file mode 100644
index 00000000000..47bbb5dc024
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webrtc/tools/.eslintrc.js
@@ -0,0 +1,156 @@
+module.exports = {
+ rules: {
+ 'no-undef': 1,
+ 'no-unused-vars': 0
+ },
+ plugins: [
+ 'html'
+ ],
+ env: {
+ browser: true,
+ es6: true
+ },
+ globals: {
+ // testharness globals
+ test: true,
+ async_test: true,
+ promise_test: true,
+ promise_rejects: true,
+ IdlArray: true,
+ assert_true: true,
+ assert_false: true,
+ assert_equals: true,
+ assert_not_equals: true,
+ assert_array_equals: true,
+ assert_in_array: true,
+ assert_unreached: true,
+ assert_throws: true,
+ assert_idl_attribute: true,
+ assert_exists: true,
+ assert_greater_than: true,
+ assert_less_than: true,
+ assert_greater_than_equal: true,
+ assert_less_than_equal: true,
+ assert_approx_equals: true,
+
+
+ // WebRTC globals
+ RTCPeerConnection: true,
+ RTCRtpSender: true,
+ RTCRtpReceiver: true,
+ RTCRtpTransceiver: true,
+ RTCIceTransport: true,
+ RTCDtlsTransport: true,
+ RTCSctpTransport: true,
+ RTCDataChannel: true,
+ RTCCertificate: true,
+ RTCDTMFSender: true,
+ RTCError: true,
+ RTCTrackEvent: true,
+ RTCPeerConnectionIceEvent: true,
+ RTCDTMFToneChangeEvent: true,
+ RTCDataChannelEvent: true,
+ RTCRtpContributingSource: true,
+ RTCRtpSynchronizationSource: true,
+
+ // dictionary-helper.js
+ assert_unsigned_int_field: true,
+ assert_int_field: true,
+ assert_string_field: true,
+ assert_number_field: true,
+ assert_boolean_field: true,
+ assert_array_field: true,
+ assert_dict_field: true,
+ assert_enum_field: true,
+
+ assert_optional_unsigned_int_field: true,
+ assert_optional_int_field: true,
+ assert_optional_string_field: true,
+ assert_optional_number_field: true,
+ assert_optional_boolean_field: true,
+ assert_optional_array_field: true,
+ assert_optional_dict_field: true,
+ assert_optional_enum_field: true,
+
+ // identity-helper.js
+ parseAssertionResult: true,
+ getIdpDomains: true,
+ assert_rtcerror_rejection: true,
+ hostString: true,
+
+ // RTCConfiguration-helper.js
+ config_test: true,
+
+ // RTCDTMFSender-helper.js
+ createDtmfSender: true,
+ test_tone_change_events: true,
+ getTransceiver: true,
+
+ // RTCPeerConnection-helper.js
+ countLine: true,
+ countAudioLine: true,
+ countVideoLine: true,
+ countApplicationLine: true,
+ similarMediaDescriptions: true,
+ assert_is_session_description: true,
+ isSimilarSessionDescription: true,
+ assert_session_desc_equals: true,
+ assert_session_desc_not_equals: true,
+ generateOffer: true,
+ generateAnswer: true,
+ test_state_change_event: true,
+ test_never_resolve: true,
+ exchangeIceCandidates: true,
+ doSignalingHandshake: true,
+ createDataChannelPair: true,
+ awaitMessage: true,
+ blobToArrayBuffer: true,
+ assert_equals_array_buffer: true,
+ generateMediaStreamTrack: true,
+ getTrackFromUserMedia: true,
+ getUserMediaTracksAndStreams: true,
+ performOffer: true,
+ Resolver: true,
+
+ // RTCRtpCapabilities-helper.js
+ validateRtpCapabilities: true,
+ validateCodecCapability: true,
+ validateHeaderExtensionCapability: true,
+
+ // RTCRtpParameters-helper.js
+ validateSenderRtpParameters: true,
+ validateReceiverRtpParameters: true,
+ validateRtpParameters: true,
+ validateEncodingParameters: true,
+ validateRtcpParameters: true,
+ validateHeaderExtensionParameters: true,
+ validateCodecParameters: true,
+
+ // RTCStats-helper.js
+ validateStatsReport: true,
+ assert_stats_report_has_stats: true,
+ findStatsFromReport: true,
+ getRequiredStats: true,
+ getStatsById: true,
+ validateIdField: true,
+ validateOptionalIdField: true,
+ validateRtcStats: true,
+ validateRtpStreamStats: true,
+ validateCodecStats: true,
+ validateReceivedRtpStreamStats: true,
+ validateInboundRtpStreamStats: true,
+ validateRemoteInboundRtpStreamStats: true,
+ validateSentRtpStreamStats: true,
+ validateOutboundRtpStreamStats: true,
+ validateRemoteOutboundRtpStreamStats: true,
+ validateContributingSourceStats: true,
+ validatePeerConnectionStats: true,
+ validateMediaStreamStats: true,
+ validateMediaStreamTrackStats: true,
+ validateDataChannelStats: true,
+ validateTransportStats: true,
+ validateIceCandidateStats: true,
+ validateIceCandidatePairStats: true,
+ validateCertificateStats: true,
+ }
+}
diff --git a/tests/wpt/web-platform-tests/webrtc/tools/README.md b/tests/wpt/web-platform-tests/webrtc/tools/README.md
new file mode 100644
index 00000000000..68bc284fdfa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webrtc/tools/README.md
@@ -0,0 +1,14 @@
+WebRTC Tools
+============
+
+This directory contains a simple Node.js project to aid the development of
+WebRTC tests.
+
+## Lint
+
+```bash
+npm run lint
+```
+
+Does basic linting of the JavaScript code. Mainly for catching usage of
+undefined variables.
diff --git a/tests/wpt/web-platform-tests/webrtc/tools/package-lock.json b/tests/wpt/web-platform-tests/webrtc/tools/package-lock.json
new file mode 100644
index 00000000000..79e603949cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webrtc/tools/package-lock.json
@@ -0,0 +1,1213 @@
+{
+ "name": "webrtc-testing-tools",
+ "version": "1.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "acorn": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.2.1.tgz",
+ "integrity": "sha512-jG0u7c4Ly+3QkkW18V+NRDN+4bWHdln30NL1ZL2AvFZZmQe/BfopYCtghCKKVBUSetZ4QKcyA0pY6/4Gw8Pv8w==",
+ "dev": true
+ },
+ "acorn-jsx": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
+ "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
+ "dev": true,
+ "requires": {
+ "acorn": "3.3.0"
+ },
+ "dependencies": {
+ "acorn": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
+ "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=",
+ "dev": true
+ }
+ }
+ },
+ "ajv": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.3.0.tgz",
+ "integrity": "sha1-RBT/dKUIecII7l/cgm4ywwNUnto=",
+ "dev": true,
+ "requires": {
+ "co": "4.6.0",
+ "fast-deep-equal": "1.0.0",
+ "fast-json-stable-stringify": "2.0.0",
+ "json-schema-traverse": "0.3.1"
+ }
+ },
+ "ajv-keywords": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz",
+ "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=",
+ "dev": true
+ },
+ "ansi-escapes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz",
+ "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==",
+ "dev": true
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "argparse": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz",
+ "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=",
+ "dev": true,
+ "requires": {
+ "sprintf-js": "1.0.3"
+ }
+ },
+ "array-union": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
+ "dev": true,
+ "requires": {
+ "array-uniq": "1.0.3"
+ }
+ },
+ "array-uniq": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
+ "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
+ "dev": true
+ },
+ "arrify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+ "dev": true
+ },
+ "babel-code-frame": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
+ "dev": true,
+ "requires": {
+ "chalk": "1.1.3",
+ "esutils": "2.0.2",
+ "js-tokens": "3.0.2"
+ },
+ "dependencies": {
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "2.2.1",
+ "escape-string-regexp": "1.0.5",
+ "has-ansi": "2.0.0",
+ "strip-ansi": "3.0.1",
+ "supports-color": "2.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "2.1.1"
+ }
+ }
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
+ "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
+ "dev": true,
+ "requires": {
+ "balanced-match": "1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "caller-path": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
+ "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=",
+ "dev": true,
+ "requires": {
+ "callsites": "0.2.0"
+ }
+ },
+ "callsites": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
+ "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
+ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "3.2.0",
+ "escape-string-regexp": "1.0.5",
+ "supports-color": "4.5.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+ "dev": true,
+ "requires": {
+ "color-convert": "1.9.1"
+ }
+ },
+ "supports-color": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
+ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+ "dev": true,
+ "requires": {
+ "has-flag": "2.0.0"
+ }
+ }
+ }
+ },
+ "chardet": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.0.tgz",
+ "integrity": "sha1-C74TVaxE16PtSpJXB8TvcPgZD2w=",
+ "dev": true
+ },
+ "circular-json": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
+ "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==",
+ "dev": true
+ },
+ "cli-cursor": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
+ "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
+ "dev": true,
+ "requires": {
+ "restore-cursor": "2.0.0"
+ }
+ },
+ "cli-width": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
+ "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
+ "dev": true
+ },
+ "co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
+ "dev": true
+ },
+ "color-convert": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz",
+ "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "concat-stream": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz",
+ "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3",
+ "readable-stream": "2.3.3",
+ "typedarray": "0.0.6"
+ }
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+ "dev": true
+ },
+ "cross-spawn": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
+ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
+ "dev": true,
+ "requires": {
+ "lru-cache": "4.1.1",
+ "shebang-command": "1.2.0",
+ "which": "1.3.0"
+ }
+ },
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "deep-is": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
+ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+ "dev": true
+ },
+ "del": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
+ "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=",
+ "dev": true,
+ "requires": {
+ "globby": "5.0.0",
+ "is-path-cwd": "1.0.0",
+ "is-path-in-cwd": "1.0.0",
+ "object-assign": "4.1.1",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1",
+ "rimraf": "2.6.2"
+ }
+ },
+ "doctrine": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz",
+ "integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=",
+ "dev": true,
+ "requires": {
+ "esutils": "2.0.2",
+ "isarray": "1.0.0"
+ }
+ },
+ "dom-serializer": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
+ "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=",
+ "dev": true,
+ "requires": {
+ "domelementtype": "1.1.3",
+ "entities": "1.1.1"
+ },
+ "dependencies": {
+ "domelementtype": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
+ "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=",
+ "dev": true
+ }
+ }
+ },
+ "domelementtype": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz",
+ "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=",
+ "dev": true
+ },
+ "domhandler": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.1.tgz",
+ "integrity": "sha1-iS5HAAqZvlW783dP/qBWHYh5wlk=",
+ "dev": true,
+ "requires": {
+ "domelementtype": "1.3.0"
+ }
+ },
+ "domutils": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.6.2.tgz",
+ "integrity": "sha1-GVjMC0yUJuntNn+xyOhUiRsPo/8=",
+ "dev": true,
+ "requires": {
+ "dom-serializer": "0.1.0",
+ "domelementtype": "1.3.0"
+ }
+ },
+ "entities": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz",
+ "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=",
+ "dev": true
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "eslint": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.11.0.tgz",
+ "integrity": "sha512-UWbhQpaKlm8h5x/VLwm0S1kheMrDj8jPwhnBMjr/Dlo3qqT7MvcN/UfKAR3E1N4lr4YNtOvS4m3hwsrVc/ky7g==",
+ "dev": true,
+ "requires": {
+ "ajv": "5.3.0",
+ "babel-code-frame": "6.26.0",
+ "chalk": "2.3.0",
+ "concat-stream": "1.6.0",
+ "cross-spawn": "5.1.0",
+ "debug": "3.1.0",
+ "doctrine": "2.0.0",
+ "eslint-scope": "3.7.1",
+ "espree": "3.5.2",
+ "esquery": "1.0.0",
+ "estraverse": "4.2.0",
+ "esutils": "2.0.2",
+ "file-entry-cache": "2.0.0",
+ "functional-red-black-tree": "1.0.1",
+ "glob": "7.1.2",
+ "globals": "9.18.0",
+ "ignore": "3.3.7",
+ "imurmurhash": "0.1.4",
+ "inquirer": "3.3.0",
+ "is-resolvable": "1.0.0",
+ "js-yaml": "3.10.0",
+ "json-stable-stringify-without-jsonify": "1.0.1",
+ "levn": "0.3.0",
+ "lodash": "4.17.4",
+ "minimatch": "3.0.4",
+ "mkdirp": "0.5.1",
+ "natural-compare": "1.4.0",
+ "optionator": "0.8.2",
+ "path-is-inside": "1.0.2",
+ "pluralize": "7.0.0",
+ "progress": "2.0.0",
+ "require-uncached": "1.0.3",
+ "semver": "5.4.1",
+ "strip-ansi": "4.0.0",
+ "strip-json-comments": "2.0.1",
+ "table": "4.0.2",
+ "text-table": "0.2.0"
+ }
+ },
+ "eslint-plugin-html": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-4.0.0.tgz",
+ "integrity": "sha512-xK/909qOTq5JVzuO2jo4a24nQcWhkOBz9dOIkORvB7RxC75a4b6B9wFpBXAl8WDhwJGFDj5gBDRN+/L3kK/ghw==",
+ "dev": true,
+ "requires": {
+ "htmlparser2": "3.9.2"
+ }
+ },
+ "eslint-scope": {
+ "version": "3.7.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz",
+ "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=",
+ "dev": true,
+ "requires": {
+ "esrecurse": "4.2.0",
+ "estraverse": "4.2.0"
+ }
+ },
+ "espree": {
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.2.tgz",
+ "integrity": "sha512-sadKeYwaR/aJ3stC2CdvgXu1T16TdYN+qwCpcWbMnGJ8s0zNWemzrvb2GbD4OhmJ/fwpJjudThAlLobGbWZbCQ==",
+ "dev": true,
+ "requires": {
+ "acorn": "5.2.1",
+ "acorn-jsx": "3.0.1"
+ }
+ },
+ "esprima": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz",
+ "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==",
+ "dev": true
+ },
+ "esquery": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz",
+ "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=",
+ "dev": true,
+ "requires": {
+ "estraverse": "4.2.0"
+ }
+ },
+ "esrecurse": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz",
+ "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=",
+ "dev": true,
+ "requires": {
+ "estraverse": "4.2.0",
+ "object-assign": "4.1.1"
+ }
+ },
+ "estraverse": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
+ "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
+ "dev": true
+ },
+ "external-editor": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz",
+ "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==",
+ "dev": true,
+ "requires": {
+ "chardet": "0.4.0",
+ "iconv-lite": "0.4.19",
+ "tmp": "0.0.33"
+ }
+ },
+ "fast-deep-equal": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz",
+ "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=",
+ "dev": true
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
+ "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
+ "dev": true
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+ "dev": true
+ },
+ "figures": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
+ "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
+ "dev": true,
+ "requires": {
+ "escape-string-regexp": "1.0.5"
+ }
+ },
+ "file-entry-cache": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz",
+ "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=",
+ "dev": true,
+ "requires": {
+ "flat-cache": "1.3.0",
+ "object-assign": "4.1.1"
+ }
+ },
+ "flat-cache": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz",
+ "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=",
+ "dev": true,
+ "requires": {
+ "circular-json": "0.3.3",
+ "del": "2.2.2",
+ "graceful-fs": "4.1.11",
+ "write": "0.2.1"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+ "dev": true
+ },
+ "functional-red-black-tree": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
+ "dev": true
+ },
+ "glob": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "1.0.0",
+ "inflight": "1.0.6",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.4",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.1"
+ }
+ },
+ "globals": {
+ "version": "9.18.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
+ "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==",
+ "dev": true
+ },
+ "globby": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
+ "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
+ "dev": true,
+ "requires": {
+ "array-union": "1.0.2",
+ "arrify": "1.0.1",
+ "glob": "7.1.2",
+ "object-assign": "4.1.1",
+ "pify": "2.3.0",
+ "pinkie-promise": "2.0.1"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+ "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
+ "dev": true
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "2.1.1"
+ }
+ },
+ "has-flag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+ "dev": true
+ },
+ "htmlparser2": {
+ "version": "3.9.2",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz",
+ "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=",
+ "dev": true,
+ "requires": {
+ "domelementtype": "1.3.0",
+ "domhandler": "2.4.1",
+ "domutils": "1.6.2",
+ "entities": "1.1.1",
+ "inherits": "2.0.3",
+ "readable-stream": "2.3.3"
+ }
+ },
+ "iconv-lite": {
+ "version": "0.4.19",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
+ "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==",
+ "dev": true
+ },
+ "ignore": {
+ "version": "3.3.7",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz",
+ "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==",
+ "dev": true
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "dev": true,
+ "requires": {
+ "once": "1.4.0",
+ "wrappy": "1.0.2"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+ "dev": true
+ },
+ "inquirer": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
+ "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==",
+ "dev": true,
+ "requires": {
+ "ansi-escapes": "3.0.0",
+ "chalk": "2.3.0",
+ "cli-cursor": "2.1.0",
+ "cli-width": "2.2.0",
+ "external-editor": "2.1.0",
+ "figures": "2.0.0",
+ "lodash": "4.17.4",
+ "mute-stream": "0.0.7",
+ "run-async": "2.3.0",
+ "rx-lite": "4.0.8",
+ "rx-lite-aggregates": "4.0.8",
+ "string-width": "2.1.1",
+ "strip-ansi": "4.0.0",
+ "through": "2.3.8"
+ }
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true
+ },
+ "is-path-cwd": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
+ "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=",
+ "dev": true
+ },
+ "is-path-in-cwd": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz",
+ "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=",
+ "dev": true,
+ "requires": {
+ "is-path-inside": "1.0.0"
+ }
+ },
+ "is-path-inside": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz",
+ "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=",
+ "dev": true,
+ "requires": {
+ "path-is-inside": "1.0.2"
+ }
+ },
+ "is-promise": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
+ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
+ "dev": true
+ },
+ "is-resolvable": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz",
+ "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=",
+ "dev": true,
+ "requires": {
+ "tryit": "1.0.3"
+ }
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+ "dev": true
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "js-tokens": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz",
+ "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==",
+ "dev": true,
+ "requires": {
+ "argparse": "1.0.9",
+ "esprima": "4.0.0"
+ }
+ },
+ "json-schema-traverse": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
+ "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
+ "dev": true
+ },
+ "json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
+ "dev": true
+ },
+ "levn": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "1.1.2",
+ "type-check": "0.3.2"
+ }
+ },
+ "lodash": {
+ "version": "4.17.4",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
+ "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=",
+ "dev": true
+ },
+ "lru-cache": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz",
+ "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==",
+ "dev": true,
+ "requires": {
+ "pseudomap": "1.0.2",
+ "yallist": "2.1.2"
+ }
+ },
+ "mimic-fn": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz",
+ "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "1.1.8"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
+ "dev": true
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+ "dev": true,
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ },
+ "mute-stream": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
+ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
+ "dev": true
+ },
+ "natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+ "dev": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+ "dev": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dev": true,
+ "requires": {
+ "wrappy": "1.0.2"
+ }
+ },
+ "onetime": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
+ "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
+ "dev": true,
+ "requires": {
+ "mimic-fn": "1.1.0"
+ }
+ },
+ "optionator": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
+ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
+ "dev": true,
+ "requires": {
+ "deep-is": "0.1.3",
+ "fast-levenshtein": "2.0.6",
+ "levn": "0.3.0",
+ "prelude-ls": "1.1.2",
+ "type-check": "0.3.2",
+ "wordwrap": "1.0.0"
+ }
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
+ "dev": true
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "dev": true
+ },
+ "path-is-inside": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
+ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
+ "dev": true
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ },
+ "pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+ "dev": true
+ },
+ "pinkie-promise": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+ "dev": true,
+ "requires": {
+ "pinkie": "2.0.4"
+ }
+ },
+ "pluralize": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz",
+ "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==",
+ "dev": true
+ },
+ "prelude-ls": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
+ "dev": true
+ },
+ "process-nextick-args": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
+ "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=",
+ "dev": true
+ },
+ "progress": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz",
+ "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=",
+ "dev": true
+ },
+ "pseudomap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
+ "dev": true
+ },
+ "readable-stream": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
+ "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
+ "dev": true,
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "1.0.7",
+ "safe-buffer": "5.1.1",
+ "string_decoder": "1.0.3",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "require-uncached": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
+ "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=",
+ "dev": true,
+ "requires": {
+ "caller-path": "0.1.0",
+ "resolve-from": "1.0.1"
+ }
+ },
+ "resolve-from": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz",
+ "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=",
+ "dev": true
+ },
+ "restore-cursor": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
+ "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
+ "dev": true,
+ "requires": {
+ "onetime": "2.0.1",
+ "signal-exit": "3.0.2"
+ }
+ },
+ "rimraf": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
+ "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
+ "dev": true,
+ "requires": {
+ "glob": "7.1.2"
+ }
+ },
+ "run-async": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
+ "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
+ "dev": true,
+ "requires": {
+ "is-promise": "2.1.0"
+ }
+ },
+ "rx-lite": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz",
+ "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=",
+ "dev": true
+ },
+ "rx-lite-aggregates": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz",
+ "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=",
+ "dev": true,
+ "requires": {
+ "rx-lite": "4.0.8"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
+ "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
+ "dev": true
+ },
+ "semver": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
+ "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==",
+ "dev": true
+ },
+ "shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "1.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+ "dev": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
+ "dev": true
+ },
+ "slice-ansi": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz",
+ "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==",
+ "dev": true,
+ "requires": {
+ "is-fullwidth-code-point": "2.0.0"
+ }
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "requires": {
+ "is-fullwidth-code-point": "2.0.0",
+ "strip-ansi": "4.0.0"
+ }
+ },
+ "string_decoder": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
+ "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "5.1.1"
+ }
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "3.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ }
+ }
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ },
+ "table": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz",
+ "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==",
+ "dev": true,
+ "requires": {
+ "ajv": "5.3.0",
+ "ajv-keywords": "2.1.1",
+ "chalk": "2.3.0",
+ "lodash": "4.17.4",
+ "slice-ansi": "1.0.0",
+ "string-width": "2.1.1"
+ }
+ },
+ "text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
+ "dev": true
+ },
+ "through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
+ "dev": true
+ },
+ "tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "dev": true,
+ "requires": {
+ "os-tmpdir": "1.0.2"
+ }
+ },
+ "tryit": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz",
+ "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=",
+ "dev": true
+ },
+ "type-check": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "1.1.2"
+ }
+ },
+ "typedarray": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
+ "dev": true
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+ "dev": true
+ },
+ "which": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz",
+ "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==",
+ "dev": true,
+ "requires": {
+ "isexe": "2.0.0"
+ }
+ },
+ "wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
+ "dev": true
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ },
+ "write": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz",
+ "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=",
+ "dev": true,
+ "requires": {
+ "mkdirp": "0.5.1"
+ }
+ },
+ "yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+ "dev": true
+ }
+ }
+}
diff --git a/tests/wpt/web-platform-tests/webrtc/tools/package.json b/tests/wpt/web-platform-tests/webrtc/tools/package.json
new file mode 100644
index 00000000000..70515d8b715
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webrtc/tools/package.json
@@ -0,0 +1,14 @@
+{
+ "name": "webrtc-testing-tools",
+ "version": "1.0.0",
+ "description": "Tools for WebRTC testing",
+ "scripts": {
+ "lint": "eslint -c .eslintrc.js ../*.html ../*.js"
+ },
+ "devDependencies": {
+ "eslint": "^4.11.0",
+ "eslint-plugin-html": "^4.0.0"
+ },
+ "license": "BSD",
+ "private": true
+}
diff --git a/tests/wpt/web-platform-tests/websockets/constants.js b/tests/wpt/web-platform-tests/websockets/constants.js
index 8312cd253fe..cb17767f48c 100644
--- a/tests/wpt/web-platform-tests/websockets/constants.js
+++ b/tests/wpt/web-platform-tests/websockets/constants.js
@@ -1,8 +1,7 @@
//This file requires server-side substitutions and must be included as constants.js?pipe=sub
var PORT = "{{ports[ws][0]}}";
-//FIXME: Add support for wss
-var PORT_SSL = "{{ports[ws][0]}}";
+var PORT_SSL = "{{ports[wss][0]}}";
var SCHEME_DOMAIN_PORT;
if (location.search == '?wss') {
diff --git a/tests/wpt/web-platform-tests/websockets/handlers/referrer_wsh.py b/tests/wpt/web-platform-tests/websockets/handlers/referrer_wsh.py
new file mode 100644
index 00000000000..3418ceb0c80
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/handlers/referrer_wsh.py
@@ -0,0 +1,12 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import msgutil
+
+def web_socket_do_extra_handshake(request):
+ pass
+
+def web_socket_transfer_data(request):
+ referrer = request.headers_in.get("Referer")
+ if referrer is None:
+ referrer = "MISSING AS PER FETCH"
+ msgutil.send_message(request, referrer)
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-defineProperty-getter.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-defineProperty-getter.html
index a6bd53015c6..b564da23967 100644
--- a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-defineProperty-getter.html
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-defineProperty-getter.html
@@ -3,7 +3,7 @@
<title>WebSockets: defineProperty getter for bufferedAmount</title>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
-<script src=../../../../constants.js?pipe=sub></script>
+<script src=../../../constants.js?pipe=sub></script>
<meta name="variant" content="">
<meta name="variant" content="?wss">
<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/websockets/referrer.any.js b/tests/wpt/web-platform-tests/websockets/referrer.any.js
new file mode 100644
index 00000000000..914af77e678
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/referrer.any.js
@@ -0,0 +1,13 @@
+// META: script=constants.js?pipe=sub
+
+async_test(t => {
+ const ws = new WebSocket(SCHEME_DOMAIN_PORT + "/referrer");
+ ws.onmessage = t.step_func_done(e => {
+ assert_equals(e.data, "MISSING AS PER FETCH");
+ ws.close();
+ });
+
+ // Avoid timeouts in case of failure
+ ws.onclose = t.unreached_func("close");
+ ws.onerror = t.unreached_func("error");
+}, "Ensure no Referer header is included");
diff --git a/tests/wpt/web-platform-tests/webstorage/idlharness.html b/tests/wpt/web-platform-tests/webstorage/idlharness.html
index 454e441d6f9..cd880a33f03 100644
--- a/tests/wpt/web-platform-tests/webstorage/idlharness.html
+++ b/tests/wpt/web-platform-tests/webstorage/idlharness.html
@@ -15,7 +15,7 @@
<div id="log"></div>
<pre id='untested_idl' style='display:none'>
-[PrimaryGlobal]
+[Global=Window, Exposed=Window]
interface Window {
};
diff --git a/tests/wpt/web-platform-tests/webvr/idlharness.html b/tests/wpt/web-platform-tests/webvr/idlharness.html
index ecb89f37565..96c63d5e0c4 100644
--- a/tests/wpt/web-platform-tests/webvr/idlharness.html
+++ b/tests/wpt/web-platform-tests/webvr/idlharness.html
@@ -223,7 +223,7 @@ partial interface Gamepad {
<script>
setup( () => {
var idl_array = new IdlArray();
- idl_array.add_untested_idls("[PrimaryGlobal] interface Window {};");
+ idl_array.add_untested_idls("[Global=Window, Exposed=Window] interface Window {};");
idl_array.add_untested_idls("interface Navigator {};");
idl_array.add_untested_idls("interface Event {};");
idl_array.add_untested_idls("interface EventTarget {};");
diff --git a/tests/wpt/web-platform-tests/webvtt/api/VTTCue/constructor-exceptions.html b/tests/wpt/web-platform-tests/webvtt/api/VTTCue/constructor-exceptions.html
new file mode 100644
index 00000000000..4d051fb3e98
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/api/VTTCue/constructor-exceptions.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>VTTCue constructor exceptions</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ assert_throws(new TypeError, function() { new VTTCue(NaN, 0, 'foo'); });
+ assert_throws(new TypeError, function() { new VTTCue(Infinity, 0, 'foo'); });
+ assert_throws(new TypeError, function() { new VTTCue('tomorrow', 0, 'foo'); });
+}, document.title+', non-finite start time');
+test(function() {
+ assert_throws(new TypeError, function() { new VTTCue(0, NaN, 'foo'); });
+ assert_throws(new TypeError, function() { new VTTCue(0, Infinity, 'foo'); });
+ assert_throws(new TypeError, function() { new VTTCue(0, 'tomorrow', 'foo'); });
+}, document.title+', non-finite end time');
+test(function() {
+ var start = { valueOf: function() { return 42; } };
+ var end = { valueOf: function() { return 84; } };
+ var cue = new VTTCue(start, end, 'bar');
+ assert_equals(cue.startTime, 42);
+ assert_equals(cue.endTime, 84);
+ assert_equals(cue.text, 'bar');
+}, document.title+', valueOf');
+</script>
diff --git a/tests/wpt/web-platform-tests/webvtt/parsing/file-parsing/tests/regions-edge-case.html b/tests/wpt/web-platform-tests/webvtt/parsing/file-parsing/tests/regions-edge-case.html
new file mode 100644
index 00000000000..db1f27f67f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/parsing/file-parsing/tests/regions-edge-case.html
@@ -0,0 +1,55 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/regions-edge-case.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: multiple regions edge cases</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-region-settings">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('regions, lines');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/regions-edge-case.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 4);
+
+var region1 = cues[0].region;
+assert_equals(region1.lines, 1);
+assert_equals(region1.id, "foo");
+
+var region2 = cues[1].region;
+assert_equals(region2.lines, 2);
+assert_equals(region2.id, "bill");
+
+var region3 = cues[2].region;
+assert_equals(region3.lines, 3);
+assert_equals(region3.id, "jill");
+
+var region4 = cues[3].region;
+assert_equals(region4.lines, 4);
+assert_equals(region4.id, "jack");
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/webvtt/parsing/file-parsing/tests/support/regions-edge-case.vtt b/tests/wpt/web-platform-tests/webvtt/parsing/file-parsing/tests/support/regions-edge-case.vtt
new file mode 100644
index 00000000000..29debd5bd8f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/parsing/file-parsing/tests/support/regions-edge-case.vtt
@@ -0,0 +1,44 @@
+WEBVTT
+
+NOTE valid
+
+REGION
+id:foo lines:1
+
+-->
+REGION
+id:foo
+lines:2
+-->
+
+REGION
+id:bill
+lines:2
+
+REGION
+REGION
+id:jill
+lines:3
+
+REGION
+--->
+id:jill lines:4
+
+REGION
+id:jack--> lines:5
+
+REGION
+id:jack lines:4
+
+00:00:00.000 --> 00:00:01.000 region:foo
+text
+
+00:00:00.000 --> 00:00:01.000 region:bill
+text
+
+00:00:00.000 --> 00:00:01.000 region:jill
+text
+
+00:00:00.000 --> 00:00:01.000 region:jack
+text
+
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-center-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-center-ref.html
new file mode 100644
index 00000000000..29cb32a2ede
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-center-ref.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.container {
+ position: relative;
+ display: inline-block;
+ width: 320px;
+ height: 240px;
+}
+.cue {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ overflow: hidden;
+}
+.cue.center {
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: green;
+ color: green;
+ font-size: 50px;
+ padding: 2px;
+}
+</style>
+<div class="container">
+<video width="320" height="240" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+</video>
+<div class="cue center"><span>&#x5d0;&#x5d1;&#x5d2;</span></div>
+</div>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-center.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-center.html
new file mode 100644
index 00000000000..05f4244d756
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-center.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<script src="/common/reftest-wait.js"></script>
+<link rel="match" href="track-cue-rendering-position-align-rtl-center-ref.html">
+<script>
+function addTrackWithRtlCueData(video, cueData) {
+ var track = video.addTextTrack('subtitles');
+ var cue = new VTTCue(0, 10, '\u05d0\u05d1\u05d2');
+ for (var prop in cueData)
+ cue[prop] = cueData[prop];
+ track.addCue(cue);
+ track.mode = 'showing';
+}
+</script>
+<style>
+video::cue {
+ font-size: 50px;
+ color: green;
+ background-color: green;
+}
+</style>
+<video width="320" height="240" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <script>
+ var video = document.currentScript.parentNode;
+ addTrackWithRtlCueData(video, { position: 50, positionAlign: 'center', align: 'center', size: 50, line: 0 });
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-left-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-left-ref.html
new file mode 100644
index 00000000000..42ae433412e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-left-ref.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.container {
+ position: relative;
+ display: inline-block;
+ width: 320px;
+ height: 240px;
+}
+.cue {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ overflow: hidden;
+}
+.cue.start {
+ text-align: end;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: green;
+ color: green;
+ font-size: 50px;
+ padding: 2px;
+}
+</style>
+<div class="container">
+<video width="320" height="240" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+</video>
+<div class="cue start"><span>&#x5d0;&#x5d1;&#x5d2;</span></div>
+</div>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-left.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-left.html
new file mode 100644
index 00000000000..7433d9f26ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-left.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<script src="/common/reftest-wait.js"></script>
+<link rel="match" href="track-cue-rendering-position-align-rtl-line-left-ref.html">
+<script>
+function addTrackWithRtlCueData(video, cueData) {
+ var track = video.addTextTrack('subtitles');
+ var cue = new VTTCue(0, 10, '\u05d0\u05d1\u05d2');
+ for (var prop in cueData)
+ cue[prop] = cueData[prop];
+ track.addCue(cue);
+ track.mode = 'showing';
+}
+</script>
+<style>
+video::cue {
+ font-size: 50px;
+ color: green;
+ background-color: green;
+}
+</style>
+<video width="320" height="240" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <script>
+ var video = document.currentScript.parentNode;
+ addTrackWithRtlCueData(video, { position: 50, positionAlign: 'line-left', align: 'start', size: 50, line: 0 });
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-right-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-right-ref.html
new file mode 100644
index 00000000000..374cbdf0aea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-right-ref.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.container {
+ position: relative;
+ display: inline-block;
+ width: 320px;
+ height: 240px;
+}
+.cue {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ overflow: hidden;
+}
+.cue.end {
+ text-align: start;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: green;
+ color: green;
+ font-size: 50px;
+ padding: 2px;
+}
+</style>
+<div class="container">
+<video width="320" height="240" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+</video>
+<div class="cue end"><span>&#x5d0;&#x5d1;&#x5d2;</span></div>
+</div>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-right.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-right.html
new file mode 100644
index 00000000000..b0a0d74cbbd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/track-cue-rendering-position-align-rtl-line-right.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<script src="/common/reftest-wait.js"></script>
+<link rel="match" href="track-cue-rendering-position-align-rtl-line-right-ref.html">
+<script>
+function addTrackWithRtlCueData(video, cueData) {
+ var track = video.addTextTrack('subtitles');
+ var cue = new VTTCue(0, 10, '\u05d0\u05d1\u05d2');
+ for (var prop in cueData)
+ cue[prop] = cueData[prop];
+ track.addCue(cue);
+ track.mode = 'showing';
+}
+</script>
+<style>
+video::cue {
+ font-size: 50px;
+ color: green;
+ background-color: green;
+}
+</style>
+<video width="320" height="240" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <script>
+ var video = document.currentScript.parentNode;
+ addTrackWithRtlCueData(video, { position: 50, positionAlign: 'line-right', align: 'end', size: 50, line: 0 });
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webxr/OWNERS b/tests/wpt/web-platform-tests/webxr/OWNERS
new file mode 100644
index 00000000000..8151e0df402
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webxr/OWNERS
@@ -0,0 +1,3 @@
+@toji
+@paezagon
+@klausw
diff --git a/tests/wpt/web-platform-tests/webxr/resources/webxr_check.html b/tests/wpt/web-platform-tests/webxr/resources/webxr_check.html
new file mode 100644
index 00000000000..2d8e5b387dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webxr/resources/webxr_check.html
@@ -0,0 +1,17 @@
+<script src=webxr_util.js></script>
+<script>
+'use strict';
+let definedObjects = [];
+let undefinedObjects = [];
+
+forEachWebxrObject((obj, name) => {
+ if(obj == undefined) {
+ undefinedObjects.push(name);
+ } else {
+ definedObjects.push(name);
+ }
+});
+
+window.parent.postMessage({ undefinedObjects, definedObjects}, '*');
+
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webxr/resources/webxr_util.js b/tests/wpt/web-platform-tests/webxr/resources/webxr_util.js
new file mode 100644
index 00000000000..a663b2d1d9a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webxr/resources/webxr_util.js
@@ -0,0 +1,27 @@
+// This functions calls a callback with each API object as specified
+// by https://immersive-web.github.io/webxr/spec/latest/, allowing
+// checks to be made on all ojects.
+// Arguements:
+// callback: A callback function with two arguements, the first
+// being the API object, the second being the name of
+// that API object.
+function forEachWebxrObject(callback) {
+ callback(window.navigator.xr, 'navigator.xr');
+ callback(window.XRDevice, 'XRDevice');
+ callback(window.XRSession, 'XRSession');
+ callback(window.XRSessionCreationOptions, 'XRSessionCreationOptions');
+ callback(window.XRFrameRequestCallback, 'XRFrameRequestCallback');
+ callback(window.XRPresentationFrame, 'XRPresentationFrame');
+ callback(window.XRView, 'XRView');
+ callback(window.XRViewport, 'XRViewport');
+ callback(window.XRDevicePose, 'XRDevicePose');
+ callback(window.XRLayer, 'XRLayer');
+ callback(window.XRWebGLLayer, 'XRWebGLLayer');
+ callback(window.XRWebGLLayerInit, 'XRWebGLLayerInit');
+ callback(window.XRCoordinateSystem, 'XRCoordinateSystem');
+ callback(window.XRFrameOfReference, 'XRFrameOfReference');
+ callback(window.XRStageBounds, 'XRStageBounds');
+ callback(window.XRStageBoundsPoint, 'XRStageBoundsPoint');
+ callback(window.XRSessionEvent, 'XRSessionEvent');
+ callback(window.XRCoordinateSystemEvent, 'XRCoordinateSystemEvent');
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webxr/webxr_availability.http.sub.html b/tests/wpt/web-platform-tests/webxr/webxr_availability.http.sub.html
new file mode 100644
index 00000000000..515b2ad1a8d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webxr/webxr_availability.http.sub.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<body>
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src=/webxr/resources/webxr_util.js></script>
+ <script>
+ 'use strict';
+
+ var same_origin_src = '/webxr/resources/';
+ var cross_origin_https_src = 'https://{{domains[www]}}:{{ports[https][0]}}' +
+ same_origin_src;
+
+ test(t => {
+ forEachWebxrObject((obj, name) => {
+ assert_equals(obj, undefined, name + ' was defined in insecure context.');
+ });
+ }, 'Test webxr not available in insecure context');
+
+ async_test(t => {
+ let frame = document.createElement('iframe');
+ frame.src = cross_origin_https_src + 'webxr_check.html';
+
+ window.addEventListener('message', t.step_func(function handler(evt) {
+ if (evt.source === frame.contentWindow) {
+ document.body.removeChild(frame);
+ window.removeEventListener('message', handler);
+
+ assert_equals(evt.data.definedObjects.length, 0,
+ "Some objects were defined in insecure context: " +
+ evt.data.definedObjects.toString());
+ t.done();
+ }
+ }));
+
+ document.body.appendChild(frame);
+ }, 'Test webxr not available in secure context in insecure context');
+
+ </script>
+</body>
diff --git a/tests/wpt/web-platform-tests/workers/SharedWorker_dataUrl.html b/tests/wpt/web-platform-tests/workers/SharedWorker_dataUrl.html
new file mode 100644
index 00000000000..c1dec27d49f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/SharedWorker_dataUrl.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<title>Shared Worker: Data URL cross-origin checks</title>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+</body>
+<script>
+
+function dirname(path) {
+ return path.replace(/\/[^\/]*$/, '/');
+}
+
+promise_test(t => {
+ return new Promise(function(resolve) {
+ let count = 0;
+ onmessage = e => {
+ assert_equals(e.data, 1);
+ if (++count == 2) {
+ resolve(true);
+ }
+ };
+
+ let iframeA = document.createElement('iframe');
+ document.body.appendChild(iframeA);
+ iframeA.src = get_host_info().HTTP_REMOTE_ORIGIN +
+ dirname(location.pathname) +
+ "support/iframe_sw_dataUrl.html";
+
+ let iframeB = document.createElement('iframe');
+ document.body.appendChild(iframeB);
+ iframeB.src = get_host_info().HTTPS_REMOTE_ORIGIN +
+ dirname(location.pathname) +
+ "support/iframe_sw_dataUrl.html";
+ });
+}, 'Data URL not shared by cross-origin SharedWorkers');
+
+promise_test(t => {
+ return new Promise(function(resolve) {
+ let count = 0;
+ onmessage = e => {
+ assert_equals(e.data, ++count);
+ if (count == 2) {
+ resolve(true);
+ }
+ };
+
+ let iframeA = document.createElement('iframe');
+ document.body.appendChild(iframeA);
+ iframeA.src = get_host_info().HTTP_ORIGIN +
+ dirname(location.pathname) +
+ "support/iframe_sw_dataUrl.html";
+
+ let iframeB = document.createElement('iframe');
+ document.body.appendChild(iframeB);
+ iframeB.src = get_host_info().HTTP_ORIGIN +
+ dirname(location.pathname) +
+ "support/iframe_sw_dataUrl.html";
+ });
+}, 'Data URLs shared by same-origin SharedWorkers');
+
+</script>
+</html>
diff --git a/tests/wpt/web-platform-tests/workers/data-url-shared-window.html b/tests/wpt/web-platform-tests/workers/data-url-shared-window.html
new file mode 100644
index 00000000000..7459f592861
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/data-url-shared-window.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<head>
+<title>data URL shared worker</title>
+</head>
+<body>
+<script>
+onmessage = event => {
+ const port = event.ports[0];
+ // This shared worker counts the total number of connected documents and
+ // notifies the connector of it.
+ const kScript =
+ "onconnect = e => {" +
+ " if (self.count === undefined)" +
+ " self.count = 0;" +
+ " self.count++;" +
+ " e.ports[0].postMessage(self.count);" +
+ "};";
+ const worker = new SharedWorker('data:application/javascript,' + kScript);
+ worker.port.onmessage = e => port.postMessage(e.data);
+};
+
+window.opener.postMessage('LOADED', '*');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/workers/data-url-shared.html b/tests/wpt/web-platform-tests/workers/data-url-shared.html
index d95e6395ac3..edaed99152a 100644
--- a/tests/wpt/web-platform-tests/workers/data-url-shared.html
+++ b/tests/wpt/web-platform-tests/workers/data-url-shared.html
@@ -1,9 +1,10 @@
<!DOCTYPE html>
<title>data URL shared worker</title>
+<script src="/common/get-host-info.sub.js"></script>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
-<div id=log></div>
<script>
+
function assert_worker_sends_pass(test_desc, mime_type, worker_code) {
async_test(function(t) {
var w = new SharedWorker(`data:${mime_type},onconnect = function(e) { port = e.ports[0]; ${worker_code}}`);
@@ -35,4 +36,38 @@ assert_worker_throws('Web SQL Database inaccessible', 'self.openDatabase("someDB
assert_worker_sends_pass('cross-origin worker', '', 'fetch("/").then(() => port.postMessage("FAIL"), () => port.postMessage("PASS"))');
// 'data:' workers have opaque origin
assert_worker_sends_pass('worker has opaque origin', 'application/javascript', 'if (self.location.origin == "null") port.postMessage("PASS"); else { port.postMessage("FAIL"); }');
+
+function openWindow(url) {
+ return new Promise(resolve => {
+ const win = window.open(url, '_blank');
+ add_completion_callback(() => win.close());
+ window.onmessage = e => {
+ assert_equals(e.data, 'LOADED');
+ resolve(win);
+ };
+ });
+}
+
+promise_test(() => {
+ const kWindowURL = 'data-url-shared-window.html';
+ const kRemoteWindowURL = get_host_info().HTTP_REMOTE_ORIGIN +
+ '/workers/data-url-shared-window.html';
+ return openWindow(kWindowURL)
+ .then(win => {
+ const channel = new MessageChannel;
+ win.postMessage(channel.port1, '*', [channel.port1]);
+ return new Promise(resolve => channel.port2.onmessage = resolve);
+ })
+ .then(msg_event => {
+ assert_equals(msg_event.data, 1);
+ return openWindow(kRemoteWindowURL);
+ })
+ .then(win => {
+ const channel = new MessageChannel;
+ win.postMessage(channel.port1, '*', [channel.port1]);
+ return new Promise(resolve => channel.port2.onmessage = resolve);
+ })
+ .then(msg_event => assert_equals(msg_event.data, 1));
+}, 'A data: URL shared worker should not be shared among origins.');
+
</script>
diff --git a/tests/wpt/web-platform-tests/workers/support/iframe_sw_dataUrl.html b/tests/wpt/web-platform-tests/workers/support/iframe_sw_dataUrl.html
new file mode 100644
index 00000000000..0fb0ec22807
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/support/iframe_sw_dataUrl.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title>Iframe for Shared Worker: Data URL cross-origin checks</title>
+<body>
+<script>
+
+let worker = new SharedWorker('data:text/javascript,let conns=0; onconnect = e => { e.ports[0].postMessage(++conns); }');
+worker.port.onmessage = e => {
+ parent.postMessage(e.data, '*');
+}
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/workers/worker-performance.worker.js b/tests/wpt/web-platform-tests/workers/worker-performance.worker.js
index c4e562b68eb..88db976c937 100644
--- a/tests/wpt/web-platform-tests/workers/worker-performance.worker.js
+++ b/tests/wpt/web-platform-tests/workers/worker-performance.worker.js
@@ -110,9 +110,9 @@ test(function testPerformanceHasNoNavigation () {
assert_equals(typeof(performance.navigation), "undefined", "performance.navigation is undefined");
}, "performance.navigation is not available in workers");
-test(function testPerformanceHasNoToJSON () {
- assert_equals(typeof(performance.toJSON), "undefined", "performance.toJSON is undefined");
-}, "performance.toJSON is not available in workers");
+test(function testPerformanceHasToJSON () {
+ assert_equals(typeof(performance.toJSON), "function", "performance.toJSON is a function");
+}, "performance.toJSON is available in workers");
test(function testPerformanceNoNavigationEntries () {
assert_equals(performance.getEntriesByType("navigation").length, 0, "getEntriesByType(\"navigation\") returns nothing");
diff --git a/tests/wpt/web-platform-tests/worklets/resources/credentials-tests.js b/tests/wpt/web-platform-tests/worklets/resources/credentials-tests.js
index 46d23119466..ef3f29bca58 100644
--- a/tests/wpt/web-platform-tests/worklets/resources/credentials-tests.js
+++ b/tests/wpt/web-platform-tests/worklets/resources/credentials-tests.js
@@ -1,106 +1,130 @@
+function createCookieValue(settings) {
+ return settings.credentials + '-' + settings.origin;
+}
+
+function createSetCookieURL(settings) {
+ const params = new URLSearchParams;
+ params.append('name', 'cookieName');
+ params.append('value', createCookieValue(settings));
+ if (settings.origin == 'same') {
+ return get_host_info().HTTPS_ORIGIN +
+ '/worklets/resources/set-cookie.py?' + params;
+ }
+ if (settings.origin == 'remote') {
+ return get_host_info().HTTPS_REMOTE_ORIGIN +
+ '/worklets/resources/set-cookie.py?' + params;
+ }
+ assert_unreached('settings.origin has an invalid value.');
+}
+
+function createScriptURL(settings) {
+ const params = new URLSearchParams;
+ if (settings.expectCredentialsSent)
+ params.append('value', createCookieValue(settings));
+ if (settings.origin == 'same') {
+ return get_host_info().HTTPS_ORIGIN +
+ '/worklets/resources/credentials.py?' + params;
+ }
+ if (settings.origin == 'remote') {
+ return get_host_info().HTTPS_REMOTE_ORIGIN +
+ '/worklets/resources/credentials.py?' + params;
+ }
+ assert_unreached('settings.origin has an invalid value.');
+}
+
+function createWorkletOptions(settings) {
+ if (settings.credentials == '')
+ return {};
+ return { credentials: settings.credentials };
+}
+
+// Run a credentials test with the given settings.
+//
+// Example:
+// settings = {
+// workletType: 'paint',
+// credentials: 'include',
+// origin: 'same', // 'same' or 'remote'
+// expectCredentialsSent: true
+// };
+function runCredentialsTest(settings) {
+ const worklet = get_worklet(settings.workletType);
+ const setCookieURL = createSetCookieURL(settings);
+ const scriptURL = createScriptURL(settings);
+ const options = createWorkletOptions(settings);
+
+ // { credentials: 'include' } is necessary for configuring document's cookies
+ // with the Set-Cookie: header of the response.
+ return fetch(setCookieURL, { mode: 'cors', credentials: 'include' })
+ .then(response => worklet.addModule(scriptURL, options));
+}
+
// Runs a series of tests related to credentials on a worklet.
//
// Usage:
// runCredentialsTests("paint");
function runCredentialsTests(worklet_type) {
- const worklet = get_worklet(worklet_type);
-
promise_test(() => {
- document.cookie = 'cookieName=default';
- const kScriptURL = 'resources/credentials.py?mode=default';
- return worklet.addModule(kScriptURL).then(undefined_arg => {
- assert_equals(undefined_arg, undefined);
- });
+ return runCredentialsTest({ workletType: worklet_type,
+ credentials: '',
+ origin: 'same',
+ expectCredentialsSent: false });
}, 'Importing a same-origin script with the default WorkletOptions should ' +
- 'omit the credentials');
+ 'not send the credentials');
promise_test(() => {
- const kSetCookieURL =
- get_host_info().HTTPS_REMOTE_ORIGIN +
- '/worklets/resources/set-cookie.py?name=cookieName';
- const kScriptURL = get_host_info().HTTPS_REMOTE_ORIGIN +
- '/worklets/resources/credentials.py?mode=default';
- const kOptions = { credentials: 'same-origin' };
-
- // Set a cookie in the remote origin and then start a worklet.
- return fetch(kSetCookieURL, { mode: 'cors' })
- .then(() => worklet.addModule(kScriptURL, kOptions))
- .then(undefined_arg => assert_equals(undefined_arg, undefined));
+ return runCredentialsTest({ workletType: worklet_type,
+ credentials: '',
+ origin: 'remote',
+ expectCredentialsSent: false });
}, 'Importing a remote-origin script with the default WorkletOptions ' +
- 'should not include the credentials');
+ 'should not send the credentials');
promise_test(() => {
- document.cookie = 'cookieName=omit';
- const kScriptURL = 'resources/credentials.py?mode=omit';
- const kOptions = { credentials: 'omit' };
- return worklet.addModule(kScriptURL, kOptions).then(undefined_arg => {
- assert_equals(undefined_arg, undefined);
- });
- }, 'Importing a same-origin script with credentials=omit should omit the ' +
- 'credentials');
+ return runCredentialsTest({ workletType: worklet_type,
+ credentials: 'omit',
+ origin: 'same',
+ expectCredentialsSent: false });
+ }, 'Importing a same-origin script with credentials=omit should not send ' +
+ 'the credentials');
promise_test(() => {
- const kSetCookieURL =
- get_host_info().HTTPS_REMOTE_ORIGIN +
- '/worklets/resources/set-cookie.py?name=cookieName';
- const kScriptURL = get_host_info().HTTPS_REMOTE_ORIGIN +
- '/worklets/resources/credentials.py?mode=omit';
- const kOptions = { credentials: 'omit' };
-
- // Set a cookie in the remote origin and then start a worklet.
- return fetch(kSetCookieURL, { mode: 'cors' })
- .then(() => worklet.addModule(kScriptURL, kOptions))
- .then(undefined_arg => assert_equals(undefined_arg, undefined));
- }, 'Importing a remote-origin script with credentials=omit should omit the ' +
- 'credentials');
+ return runCredentialsTest({ workletType: worklet_type,
+ credentials: 'omit',
+ origin: 'remote',
+ expectCredentialsSent: false });
+ }, 'Importing a remote-origin script with credentials=omit should not send ' +
+ 'the credentials');
promise_test(() => {
- document.cookie = 'cookieName=same-origin';
- const kScriptURL = 'resources/credentials.py?mode=same-origin';
- const kOptions = { credentials: 'same-origin' };
- return worklet.addModule(kScriptURL, kOptions).then(undefined_arg => {
- assert_equals(undefined_arg, undefined);
- });
+ return runCredentialsTest({ workletType: worklet_type,
+ credentials: 'same-origin',
+ origin: 'same',
+ expectCredentialsSent: true });
}, 'Importing a same-origin script with credentials=same-origin should ' +
- 'include the credentials');
+ 'send the credentials');
promise_test(() => {
- const kSetCookieURL =
- get_host_info().HTTPS_REMOTE_ORIGIN +
- '/worklets/resources/set-cookie.py?name=cookieName';
- const kScriptURL = get_host_info().HTTPS_REMOTE_ORIGIN +
- '/worklets/resources/credentials.py?mode=same-origin';
- const kOptions = { credentials: 'same-origin' };
-
- // Set a cookie in the remote origin and then start a worklet.
- return fetch(kSetCookieURL, { mode: 'cors' })
- .then(() => worklet.addModule(kScriptURL, kOptions))
- .then(undefined_arg => assert_equals(undefined_arg, undefined));
+ return runCredentialsTest({ workletType: worklet_type,
+ credentials: 'same-origin',
+ origin: 'remote',
+ expectCredentialsSent: false });
}, 'Importing a remote-origin script with credentials=same-origin should ' +
- 'not include the credentials');
+ 'not send the credentials');
promise_test(() => {
- document.cookie = 'cookieName=include';
- const kScriptURL = 'resources/credentials.py?mode=include';
- const kOptions = { credentials: 'include' };
- return worklet.addModule(kScriptURL, kOptions).then(undefined_arg => {
- assert_equals(undefined_arg, undefined);
- });
- }, 'Importing a same-origin script with credentials=include should include ' +
+ return runCredentialsTest({ workletType: worklet_type,
+ credentials: 'include',
+ origin: 'same',
+ expectCredentialsSent: true });
+ }, 'Importing a same-origin script with credentials=include should send ' +
'the credentials');
promise_test(() => {
- const kSetCookieURL =
- get_host_info().HTTPS_REMOTE_ORIGIN +
- '/worklets/resources/set-cookie.py?name=cookieName';
- const kScriptURL = get_host_info().HTTPS_REMOTE_ORIGIN +
- '/worklets/resources/credentials.py?mode=include';
- const kOptions = { credentials: 'include' };
-
- // Set a cookie in the remote origin and then start a worklet.
- return fetch(kSetCookieURL, { mode: 'cors' })
- .then(() => worklet.addModule(kScriptURL, kOptions))
- .then(undefined_arg => assert_equals(undefined_arg, undefined));
+ return runCredentialsTest({ workletType: worklet_type,
+ credentials: 'include',
+ origin: 'remote',
+ expectCredentialsSent: true });
}, 'Importing a remote-origin script with credentials=include should ' +
- 'include the credentials');
+ 'send the credentials');
}
diff --git a/tests/wpt/web-platform-tests/worklets/resources/credentials.py b/tests/wpt/web-platform-tests/worklets/resources/credentials.py
index 98b9e73e095..8709896d1ba 100644
--- a/tests/wpt/web-platform-tests/worklets/resources/credentials.py
+++ b/tests/wpt/web-platform-tests/worklets/resources/credentials.py
@@ -1,32 +1,14 @@
# Returns a valid response when a request has appropriate credentials.
def main(request, response):
- credentials_mode = request.GET.first("mode")
cookie = request.cookies.first("cookieName", None)
- source_origin = request.headers.get("origin", None);
- is_cross_origin = request.GET.first("is_cross_origin", False)
+ expected_value = request.GET.first("value", None)
+ source_origin = request.headers.get("origin", None)
- # The request with the default WorkletOptions should not include the cookie.
- if credentials_mode is "default" and cookie is not None:
- return (404)
+ response_headers = [("Content-Type", "text/javascript"),
+ ("Access-Control-Allow-Origin", source_origin),
+ ("Access-Control-Allow-Credentials", "true")]
- # The request with "credentials=omit" should not include the cookie.
- if credentials_mode is "omit" and cookie is not None:
- return (404)
+ if cookie == expected_value:
+ return (200, response_headers, "")
- if credentials_mode is "same-origin":
- # The cross-origin request with "credentials=same-origin" should not
- # include the cookie.
- if is_cross_origin and cookie is not None:
- return (404)
- # The same-origin request with "credentials=same-origin" should include
- # the cookie.
- if not is_cross_origin and cookie is None:
- return (404)
-
- # The request with "credentials=include" should include the cookie.
- if credentials_mode is "include" and cookie is None:
- return (404)
-
- return (200, [("Content-Type", "text/javascript"),
- ("Access-Control-Allow-Origin", source_origin),
- ("Access-Control-Allow-Credentials", "true")], "")
+ return (404, response_headers)
diff --git a/tests/wpt/web-platform-tests/worklets/resources/csp-tests.js b/tests/wpt/web-platform-tests/worklets/resources/csp-tests.js
index c56a1289100..0de1daae228 100644
--- a/tests/wpt/web-platform-tests/worklets/resources/csp-tests.js
+++ b/tests/wpt/web-platform-tests/worklets/resources/csp-tests.js
@@ -22,16 +22,13 @@ function openWindowAndExpectResult(windowURL, scriptURL, type, expectation) {
// Usage:
// runContentSecurityPolicyTests("paint");
function runContentSecurityPolicyTests(workletType) {
- const worklet = get_worklet(workletType);
-
promise_test(t => {
const kWindowURL =
'resources/addmodule-window.html?pipe=header(' +
'Content-Security-Policy, script-src \'self\' \'unsafe-inline\')';
const kScriptURL =
get_host_info().HTTPS_REMOTE_ORIGIN +
- '/worklets/resources/import-empty-worklet-script.js' +
- '?pipe=header(Access-Control-Allow-Origin, *)';
+ '/worklets/resources/import-empty-worklet-script-with-cors-header.js';
return openWindowAndExpectResult(
kWindowURL, kScriptURL, workletType, 'REJECTED');
}, 'Importing a remote-origin worklet script should be blocked by the ' +
@@ -51,9 +48,9 @@ function runContentSecurityPolicyTests(workletType) {
const kWindowURL =
'resources/addmodule-window.html?pipe=header(' +
'Content-Security-Policy, script-src * \'unsafe-inline\')';
- const kScriptURL = get_host_info().HTTPS_REMOTE_ORIGIN +
- '/worklets/resources/empty-worklet-script.js' +
- '?pipe=header(Access-Control-Allow-Origin, *)';
+ const kScriptURL =
+ get_host_info().HTTPS_REMOTE_ORIGIN +
+ '/worklets/resources/empty-worklet-script-with-cors-header.js';
return openWindowAndExpectResult(
kWindowURL, kScriptURL, workletType, 'RESOLVED');
}, 'Importing a remote-origin worklet script should not be blocked ' +
@@ -65,9 +62,9 @@ function runContentSecurityPolicyTests(workletType) {
'Content-Security-Policy, script-src * \'unsafe-inline\')';
// A worklet on HTTPS_REMOTE_ORIGIN will import a child script on
// HTTPS_REMOTE_ORIGIN.
- const kScriptURL = get_host_info().HTTPS_REMOTE_ORIGIN +
- '/worklets/resources/import-empty-worklet-script.js' +
- '?pipe=header(Access-Control-Allow-Origin, *)';
+ const kScriptURL =
+ get_host_info().HTTPS_REMOTE_ORIGIN +
+ '/worklets/resources/import-empty-worklet-script-with-cors-header.js';
return openWindowAndExpectResult(
kWindowURL, kScriptURL, workletType, 'RESOLVED');
}, 'Importing a remote-origin script from a remote-origin worklet script '+
@@ -77,12 +74,57 @@ function runContentSecurityPolicyTests(workletType) {
const kWindowURL =
'resources/addmodule-window.html?pipe=header(' +
'Content-Security-Policy, worker-src \'self\' \'unsafe-inline\')';
- const kScriptURL = get_host_info().HTTPS_REMOTE_ORIGIN +
- '/worklets/resources/empty-worklet-script.js' +
- '?pipe=header(Access-Control-Allow-Origin, *)';
+ const kScriptURL =
+ get_host_info().HTTPS_REMOTE_ORIGIN +
+ '/worklets/resources/empty-worklet-script-with-cors-header.js';
return openWindowAndExpectResult(
kWindowURL, kScriptURL, workletType, 'RESOLVED');
}, 'Importing a remote-origin worklet script should not be blocked by ' +
'the worker-src directive because worklets obey the script-src ' +
'directive.');
+
+ promise_test(t => {
+ const kWindowURL = 'resources/addmodule-window.html';
+ const kScriptURL =
+ get_host_info().HTTP_ORIGIN +
+ '/worklets/resources/empty-worklet-script.js';
+ return openWindowAndExpectResult(
+ kWindowURL, kScriptURL, workletType, 'REJECTED');
+ }, 'Importing an insecure-origin worklet script should be blocked because ' +
+ 'of mixed contents.');
+
+ promise_test(t => {
+ const kWindowURL = 'resources/addmodule-window.html?pipe=header(' +
+ 'Content-Security-Policy, upgrade-insecure-requests)';
+ // This test relies on some unintuitive cleverness due to WPT's test setup:
+ // 'Upgrade-Insecure-Requests' does not upgrade the port number, so we use
+ // URLs in the form `http://[host]:[https-port]`. If the upgrade fails, the
+ // load will fail, as we don't serve HTTP over the secure port.
+ const kHost = get_host_info().ORIGINAL_HOST;
+ const kPort = get_host_info().HTTPS_PORT;
+ const kScriptURL =
+ `http://${kHost}:${kPort}/worklets/resources/empty-worklet-script.js`;
+ return openWindowAndExpectResult(
+ kWindowURL, kScriptURL, workletType, 'RESOLVED');
+ }, 'Importing an insecure-origin worklet script should not be blocked ' +
+ 'because the upgrade-insecure-requests directive translates it as the ' +
+ 'secure origin.');
+
+ promise_test(t => {
+ const kWindowURL = 'resources/addmodule-window.html';
+ const kScriptURL = 'import-insecure-origin-empty-worklet-script.sub.js';
+ return openWindowAndExpectResult(
+ kWindowURL, kScriptURL, workletType, 'REJECTED');
+ }, 'Importing an insecure-origin script from a secure-origin worklet ' +
+ 'script should be blocked because of mixed contents.');
+
+ promise_test(t => {
+ const kWindowURL = 'resources/addmodule-window.html?pipe=header(' +
+ 'Content-Security-Policy, upgrade-insecure-requests)';
+ const kScriptURL = 'import-insecure-origin-empty-worklet-script.sub.js';
+ return openWindowAndExpectResult(
+ kWindowURL, kScriptURL, workletType, 'RESOLVED');
+ }, 'Importing an insecure-origin script from a secure-origin worklet ' +
+ 'script should not be blocked because the upgrade-insecure-requests ' +
+ 'directive translates it as the secure origin.');
}
diff --git a/tests/wpt/web-platform-tests/worklets/resources/empty-worklet-script-with-cors-header.js b/tests/wpt/web-platform-tests/worklets/resources/empty-worklet-script-with-cors-header.js
new file mode 100644
index 00000000000..9513071c6ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/worklets/resources/empty-worklet-script-with-cors-header.js
@@ -0,0 +1 @@
+// This file is served with "Access-Control-Allow-Origin" header.
diff --git a/tests/wpt/web-platform-tests/worklets/resources/empty-worklet-script-with-cors-header.js.headers b/tests/wpt/web-platform-tests/worklets/resources/empty-worklet-script-with-cors-header.js.headers
new file mode 100644
index 00000000000..cb762eff806
--- /dev/null
+++ b/tests/wpt/web-platform-tests/worklets/resources/empty-worklet-script-with-cors-header.js.headers
@@ -0,0 +1 @@
+Access-Control-Allow-Origin: *
diff --git a/tests/wpt/web-platform-tests/worklets/resources/import-empty-worklet-script-with-cors-header.js b/tests/wpt/web-platform-tests/worklets/resources/import-empty-worklet-script-with-cors-header.js
new file mode 100644
index 00000000000..bd04a189b2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/worklets/resources/import-empty-worklet-script-with-cors-header.js
@@ -0,0 +1,3 @@
+// This file and descendant files are served with "Access-Control-Allow-Origin"
+// header.
+import './empty-worklet-script-with-cors-header.js';
diff --git a/tests/wpt/web-platform-tests/worklets/resources/import-empty-worklet-script-with-cors-header.js.headers b/tests/wpt/web-platform-tests/worklets/resources/import-empty-worklet-script-with-cors-header.js.headers
new file mode 100644
index 00000000000..cb762eff806
--- /dev/null
+++ b/tests/wpt/web-platform-tests/worklets/resources/import-empty-worklet-script-with-cors-header.js.headers
@@ -0,0 +1 @@
+Access-Control-Allow-Origin: *
diff --git a/tests/wpt/web-platform-tests/worklets/resources/import-empty-worklet-script.js b/tests/wpt/web-platform-tests/worklets/resources/import-empty-worklet-script.js
deleted file mode 100644
index 339fbe9cb27..00000000000
--- a/tests/wpt/web-platform-tests/worklets/resources/import-empty-worklet-script.js
+++ /dev/null
@@ -1,3 +0,0 @@
-// This script can be imported as a remote-origin script, so the
-// Access-Control-Allow-Origin is specified here.
-import './empty-worklet-script.js?pipe=header(Access-Control-Allow-Origin, *)';
diff --git a/tests/wpt/web-platform-tests/worklets/resources/import-insecure-origin-empty-worklet-script.sub.js b/tests/wpt/web-platform-tests/worklets/resources/import-insecure-origin-empty-worklet-script.sub.js
new file mode 100644
index 00000000000..cc7f5f348a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/worklets/resources/import-insecure-origin-empty-worklet-script.sub.js
@@ -0,0 +1,5 @@
+// Some tests rely on some unintuitive cleverness due to WPT's test setup:
+// 'Upgrade-Insecure-Requests' does not upgrade the port number, so we use URLs
+// in the form `http://[host]:[https-port]`. If the upgrade fails, the load will
+// fail, as we don't serve HTTP over the secure port.
+import 'http://{{host}}:{{ports[https][0]}}/worklets/resources/empty-worklet-script.js';
diff --git a/tests/wpt/web-platform-tests/worklets/resources/import-referrer-checker-worklet-script.sub.js b/tests/wpt/web-platform-tests/worklets/resources/import-referrer-checker-worklet-script.sub.js
new file mode 100644
index 00000000000..1dcb6f3bcb5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/worklets/resources/import-referrer-checker-worklet-script.sub.js
@@ -0,0 +1,2 @@
+// Forward GET parameters to the server.
+import './referrer-checker.py?referrer_policy={{GET[referrer_policy]}}&expected_referrer={{GET[expected_referrer]}}';
diff --git a/tests/wpt/web-platform-tests/worklets/resources/import-referrer-checker-worklet-script.sub.js.headers b/tests/wpt/web-platform-tests/worklets/resources/import-referrer-checker-worklet-script.sub.js.headers
new file mode 100644
index 00000000000..cb762eff806
--- /dev/null
+++ b/tests/wpt/web-platform-tests/worklets/resources/import-referrer-checker-worklet-script.sub.js.headers
@@ -0,0 +1 @@
+Access-Control-Allow-Origin: *
diff --git a/tests/wpt/web-platform-tests/worklets/resources/import-remote-origin-referrer-checker-worklet-script.sub.js b/tests/wpt/web-platform-tests/worklets/resources/import-remote-origin-referrer-checker-worklet-script.sub.js
new file mode 100644
index 00000000000..f301701b1c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/worklets/resources/import-remote-origin-referrer-checker-worklet-script.sub.js
@@ -0,0 +1,2 @@
+// Forward GET parameters to the server.
+import 'https://{{domains[www1]}}:{{ports[https][0]}}/worklets/resources/referrer-checker.py?referrer_policy={{GET[referrer_policy]}}&expected_referrer={{GET[expected_referrer]}}';
diff --git a/tests/wpt/web-platform-tests/worklets/resources/import-remote-origin-referrer-checker-worklet-script.sub.js.headers b/tests/wpt/web-platform-tests/worklets/resources/import-remote-origin-referrer-checker-worklet-script.sub.js.headers
new file mode 100644
index 00000000000..cb762eff806
--- /dev/null
+++ b/tests/wpt/web-platform-tests/worklets/resources/import-remote-origin-referrer-checker-worklet-script.sub.js.headers
@@ -0,0 +1 @@
+Access-Control-Allow-Origin: *
diff --git a/tests/wpt/web-platform-tests/worklets/resources/referrer-checker.py b/tests/wpt/web-platform-tests/worklets/resources/referrer-checker.py
new file mode 100644
index 00000000000..184d547f493
--- /dev/null
+++ b/tests/wpt/web-platform-tests/worklets/resources/referrer-checker.py
@@ -0,0 +1,26 @@
+# Returns a valid response when request's |referrer| matches
+# |expected_referrer|.
+def main(request, response):
+ referrer = request.headers.get("referer", "")
+ referrer_policy = request.GET.first("referrer_policy")
+ expected_referrer = request.GET.first("expected_referrer", "")
+
+ response_headers = [("Content-Type", "text/javascript"),
+ ("Access-Control-Allow-Origin", "*")]
+
+ if referrer_policy == "no-referrer" or referrer_policy == "origin":
+ if referrer == expected_referrer:
+ return (200, response_headers, "")
+ return (404, response_headers)
+
+ if referrer_policy == "same-origin":
+ if referrer == expected_referrer:
+ return (200, response_headers, "")
+ # The expected referrer doesn't contain query params for simplification,
+ # so we check the referrer by startswith() here.
+ if (expected_referrer != "" and
+ referrer.startswith(expected_referrer + "?")):
+ return (200, response_headers, "")
+ return (404, response_headers)
+
+ return (404, response_headers)
diff --git a/tests/wpt/web-platform-tests/worklets/resources/referrer-tests.js b/tests/wpt/web-platform-tests/worklets/resources/referrer-tests.js
index 366bb9b5704..01b8e2ab57a 100644
--- a/tests/wpt/web-platform-tests/worklets/resources/referrer-tests.js
+++ b/tests/wpt/web-platform-tests/worklets/resources/referrer-tests.js
@@ -9,88 +9,163 @@ function openWindow(url) {
});
}
+// Run a referrer policy test with the given settings.
+//
+// Example:
+// settings = {
+// workletType: 'paint',
+// fetchType: 'top-level' or 'descendant',
+// referrerPolicy: 'no-referrer',
+// scriptsOrigins: { topLevel: 'same', descendant: 'remote' }
+// };
+function runReferrerTest(settings) {
+ const kWindowURL =
+ 'resources/referrer-window.html' +
+ `?pipe=header(Referrer-Policy, ${settings.referrerPolicy})`;
+ return openWindow(kWindowURL).then(win => {
+ const promise = new Promise(resolve => window.onmessage = resolve);
+ win.postMessage(settings, '*');
+ return promise;
+ }).then(msg_event => assert_equals(msg_event.data, 'RESOLVED'));
+}
+
// Runs a series of tests related to the referrer policy on a worklet.
//
// Usage:
// runReferrerTests("paint");
-function runReferrerTests(worklet_type) {
- const worklet = get_worklet(worklet_type);
+function runReferrerTests(workletType) {
+ const worklet = get_worklet(workletType);
+
+ // Tests for top-level script fetch -----------------------------------------
promise_test(() => {
- const kWindowURL = "resources/referrer-window.html" +
- "?pipe=header(Referrer-Policy,no-referrer)";
- return openWindow(kWindowURL).then(win => {
- const promise = new Promise(resolve => window.onmessage = resolve);
- win.postMessage({ type: worklet_type,
- referrer_policy: 'no-referrer',
- is_cross_origin: false }, '*');
- return promise;
- }).then(msg_event => assert_equals(msg_event.data, 'RESOLVED'));
+ return runReferrerTest({ workletType: workletType,
+ fetchType: 'top-level',
+ referrerPolicy: 'no-referrer',
+ scriptOrigins: { topLevel: 'same' } });
}, 'Importing a same-origin script from a page that has "no-referrer" ' +
'referrer policy should not send referrer.');
promise_test(() => {
- const kWindowURL = "resources/referrer-window.html" +
- "?pipe=header(Referrer-Policy,no-referrer)";
- return openWindow(kWindowURL).then(win => {
- const promise = new Promise(resolve => window.onmessage = resolve);
- win.postMessage({ type: worklet_type,
- referrer_policy: 'no-referrer',
- is_cross_origin: true }, '*');
- return promise;
- }).then(msg_event => assert_equals(msg_event.data, 'RESOLVED'));
+ return runReferrerTest({ workletType: workletType,
+ fetchType: 'top-level',
+ referrerPolicy: 'no-referrer',
+ scriptOrigins: { topLevel: 'remote' } });
}, 'Importing a remote-origin script from a page that has "no-referrer" ' +
'referrer policy should not send referrer.');
promise_test(() => {
- const kWindowURL = 'resources/referrer-window.html' +
- '?pipe=header(Referrer-Policy,origin)';
- return openWindow(kWindowURL).then(win => {
- const promise = new Promise(resolve => window.onmessage = resolve);
- win.postMessage({ type: worklet_type,
- referrer_policy: 'origin',
- is_cross_origin: false }, '*');
- return promise;
- }).then(msg_event => assert_equals(msg_event.data, 'RESOLVED'));
+ return runReferrerTest({ workletType: workletType,
+ fetchType: 'top-level',
+ referrerPolicy: 'origin',
+ scriptOrigins: { topLevel: 'same' } });
}, 'Importing a same-origin script from a page that has "origin" ' +
'referrer policy should send only an origin as referrer.');
promise_test(() => {
- const kWindowURL = 'resources/referrer-window.html' +
- '?pipe=header(Referrer-Policy,origin)';
- return openWindow(kWindowURL).then(win => {
- const promise = new Promise(resolve => window.onmessage = resolve);
- win.postMessage({ type: worklet_type,
- referrer_policy: 'origin',
- is_cross_origin: true }, '*');
- return promise;
- }).then(msg_event => assert_equals(msg_event.data, 'RESOLVED'));
+ return runReferrerTest({ workletType: workletType,
+ fetchType: 'top-level',
+ referrerPolicy: 'origin',
+ scriptOrigins: { topLevel: 'remote' } });
}, 'Importing a remote-origin script from a page that has "origin" ' +
'referrer policy should send only an origin as referrer.');
promise_test(() => {
- const kWindowURL = 'resources/referrer-window.html' +
- '?pipe=header(Referrer-Policy,same-origin)';
- return openWindow(kWindowURL).then(win => {
- const promise = new Promise(resolve => window.onmessage = resolve);
- win.postMessage({ type: worklet_type,
- referrer_policy: 'same-origin',
- is_cross_origin: false }, '*');
- return promise;
- }).then(msg_event => assert_equals(msg_event.data, 'RESOLVED'));
+ return runReferrerTest({ workletType: workletType,
+ fetchType: 'top-level',
+ referrerPolicy: 'same-origin',
+ scriptOrigins: { topLevel: 'same' } });
}, 'Importing a same-origin script from a page that has "same-origin" ' +
'referrer policy should send referrer.');
promise_test(() => {
- const kWindowURL = 'resources/referrer-window.html' +
- '?pipe=header(Referrer-Policy,same-origin)';
- return openWindow(kWindowURL).then(win => {
- const promise = new Promise(resolve => window.onmessage = resolve);
- win.postMessage({ type: worklet_type,
- referrer_policy: 'same-origin',
- is_cross_origin: true }, '*');
- return promise;
- }).then(msg_event => assert_equals(msg_event.data, 'RESOLVED'));
+ return runReferrerTest({ workletType: workletType,
+ fetchType: 'top-level',
+ referrerPolicy: 'same-origin',
+ scriptOrigins: { topLevel: 'remote' } });
}, 'Importing a remote-origin script from a page that has "same-origin" ' +
'referrer policy should not send referrer.');
+
+ // Tests for descendant script fetch -----------------------------------------
+
+ promise_test(() => {
+ return runReferrerTest({ workletType: workletType,
+ fetchType: 'descendant',
+ referrerPolicy: 'no-referrer',
+ scriptOrigins: { topLevel: 'same',
+ descendant: 'same' } });
+ }, 'Importing a same-origin script from a same-origin worklet script that ' +
+ 'has "no-referrer" referrer policy should not send referrer.');
+
+ promise_test(() => {
+ return runReferrerTest({ workletType: workletType,
+ fetchType: 'descendant',
+ referrerPolicy: 'no-referrer',
+ scriptOrigins: { topLevel: 'same',
+ descendant: 'remote' } });
+ }, 'Importing a remote-origin script from a same-origin worklet script ' +
+ 'that has "no-referrer" referrer policy should not send referrer.');
+
+ promise_test(() => {
+ return runReferrerTest({ workletType: workletType,
+ fetchType: 'descendant',
+ referrerPolicy: 'no-referrer',
+ scriptOrigins: { topLevel: 'remote',
+ descendant: 'remote' } });
+ }, 'Importing a remote-origin script from a remote-origin worklet script ' +
+ 'that has "no-referrer" referrer policy should not send referrer.');
+
+ promise_test(() => {
+ return runReferrerTest({ workletType: workletType,
+ fetchType: 'descendant',
+ referrerPolicy: 'origin',
+ scriptOrigins: { topLevel: 'same',
+ descendant: 'same' } });
+ }, 'Importing a same-origin script from a same-origin worklet script that ' +
+ 'has "origin" referrer policy should send referrer.');
+
+ promise_test(() => {
+ return runReferrerTest({ workletType: workletType,
+ fetchType: 'descendant',
+ referrerPolicy: 'origin',
+ scriptOrigins: { topLevel: 'same',
+ descendant: 'remote' } });
+ }, 'Importing a remote-origin script from a same-origin worklet script ' +
+ 'that has "origin" referrer policy should send referrer.');
+
+ promise_test(() => {
+ return runReferrerTest({ workletType: workletType,
+ fetchType: 'descendant',
+ referrerPolicy: 'origin',
+ scriptOrigins: { topLevel: 'remote',
+ descendant: 'remote' } });
+ }, 'Importing a remote-origin script from a remote-origin worklet script ' +
+ 'that has "origin" referrer policy should send referrer.');
+
+ promise_test(() => {
+ return runReferrerTest({ workletType: workletType,
+ fetchType: 'descendant',
+ referrerPolicy: 'same-origin',
+ scriptOrigins: { topLevel: 'same',
+ descendant: 'same' } });
+ }, 'Importing a same-origin script from a same-origin worklet script that ' +
+ 'has "same-origin" referrer policy should send referrer.');
+
+ promise_test(() => {
+ return runReferrerTest({ workletType: workletType,
+ fetchType: 'descendant',
+ referrerPolicy: 'same-origin',
+ scriptOrigins: { topLevel: 'same',
+ descendant: 'remote' } });
+ }, 'Importing a remote-origin script from a same-origin worklet script ' +
+ 'that has "same-origin" referrer policy should not send referrer.');
+
+ promise_test(() => {
+ return runReferrerTest({ workletType: workletType,
+ fetchType: 'descendant',
+ referrerPolicy: 'same-origin',
+ scriptOrigins: { topLevel: 'remote',
+ descendant: 'remote' } });
+ }, 'Importing a remote-origin script from a remote-origin worklet script ' +
+ 'that has "same-origin" referrer policy should not send referrer.');
}
diff --git a/tests/wpt/web-platform-tests/worklets/resources/referrer-window.html b/tests/wpt/web-platform-tests/worklets/resources/referrer-window.html
index 49f46db2f9b..4817f0452a2 100644
--- a/tests/wpt/web-platform-tests/worklets/resources/referrer-window.html
+++ b/tests/wpt/web-platform-tests/worklets/resources/referrer-window.html
@@ -9,22 +9,89 @@
</head>
<body>
<script>
-window.onmessage = e => {
- const worklet_type = e.data.type;
- const is_cross_origin = e.data.is_cross_origin;
+function createScriptURLForTopLevel(scriptOrigin) {
+ if (scriptOrigin === 'same')
+ return new URL('referrer-checker.py', location.href);
+ if (scriptOrigin === 'remote') {
+ return new URL(get_host_info().HTTPS_REMOTE_ORIGIN +
+ '/worklets/resources/referrer-checker.py');
+ }
+ assert_unreached('scriptOrigin should be \'same\' or \'remote\'');
+}
- const params = new URLSearchParams;
- params.append('referrer_policy', e.data.referrer_policy)
- params.append('source_origin', get_host_info().HTTPS_ORIGIN);
+function createScriptURLForDecendant(scriptOrigins) {
+ if (scriptOrigins.topLevel === 'same' &&
+ scriptOrigins.descendant === 'same') {
+ return new URL('import-referrer-checker-worklet-script.sub.js',
+ location.href);
+ }
+ if (scriptOrigins.topLevel === 'same' &&
+ scriptOrigins.descendant === 'remote') {
+ return new URL(
+ 'import-remote-origin-referrer-checker-worklet-script.sub.js',
+ location.href);
+ }
+ if (scriptOrigins.topLevel === 'remote' &&
+ scriptOrigins.descendant === 'remote') {
+ return new URL(
+ get_host_info().HTTPS_REMOTE_ORIGIN +
+ '/worklets/resources/import-referrer-checker-worklet-script.sub.js');
+ }
+ assert_unreached('scriptOrigins have an invalid origin combination.');
+}
+
+function isDestinationCrossOrigin(fetchType, scriptOrigins) {
+ if (fetchType === 'top-level')
+ return scriptOrigins.topLevel === 'remote';
+ if (fetchType === 'descendant')
+ return scriptOrigins.descendant === 'remote';
+ assert_unreached('fetchType has an invalid value.');
+}
- let script_url = '';
- if (is_cross_origin) {
- params.append('is_cross_origin', 'true')
- script_url = get_host_info().HTTPS_REMOTE_ORIGIN + '/worklets/resources/';
+function createExpectedReferrer(
+ importerURL, fetchType, referrerPolicy, scriptOrigins) {
+ if (referrerPolicy === 'no-referrer')
+ return "";
+ if (referrerPolicy === 'same-origin') {
+ if (isDestinationCrossOrigin(fetchType, scriptOrigins))
+ return "";
+ // Delete query params to make it easier to match with an actual referrer in
+ // the referrer-checker.py.
+ const expectedReferrer = new URL(importerURL);
+ for (var key of expectedReferrer.searchParams.keys())
+ expectedReferrer.searchParams.delete(key);
+ return expectedReferrer;
}
- script_url += 'referrer.py?' + params;
+ if (referrerPolicy === 'origin')
+ return (new URL(importerURL)).origin + '/';
+ assert_unreached('referrerPolicy has an invalid value.');
+}
+
+window.onmessage = e => {
+ const workletType = e.data.workletType;
+ const fetchType = e.data.fetchType;
+ const referrerPolicy = e.data.referrerPolicy;
+ const scriptOrigins = e.data.scriptOrigins;
+
+ let scriptURL;
+ let expectedReferrer;
+ if (fetchType === 'top-level') {
+ scriptURL = createScriptURLForTopLevel(scriptOrigins.topLevel);
+ expectedReferrer = createExpectedReferrer(
+ location.href, fetchType, referrerPolicy, scriptOrigins);
+ } else if (fetchType === 'descendant') {
+ scriptURL = createScriptURLForDecendant(scriptOrigins);
+ expectedReferrer = createExpectedReferrer(
+ scriptURL, fetchType, referrerPolicy, scriptOrigins);
+ } else {
+ assert_unreached('fetchType should be \'top-level\' or \'descendant\'');
+ }
+
+ const params = new URLSearchParams;
+ params.append('referrer_policy', referrerPolicy);
+ params.append('expected_referrer', expectedReferrer);
- get_worklet(worklet_type).addModule(script_url)
+ get_worklet(workletType).addModule(scriptURL + '?' + params)
.then(() => window.opener.postMessage('RESOLVED', '*'))
.catch(e => window.opener.postMessage(e.message, '*'));
};
diff --git a/tests/wpt/web-platform-tests/worklets/resources/referrer.py b/tests/wpt/web-platform-tests/worklets/resources/referrer.py
deleted file mode 100644
index 62dd4a12ff4..00000000000
--- a/tests/wpt/web-platform-tests/worklets/resources/referrer.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# Returns a valid response when request's |referrer| matches |referrer_policy|.
-def main(request, response):
- referrer = request.headers.get("referer", None)
- referrer_policy = request.GET.first("referrer_policy")
- source_origin = request.GET.first("source_origin")
- is_cross_origin = request.GET.first("is_cross_origin", False)
-
- response_headers = [("Content-Type", "text/javascript"),
- ("Access-Control-Allow-Origin", source_origin)];
-
- # When the referrer policy is "no-referrer", the referrer header shouldn't
- # be sent.
- if referrer_policy == "no-referrer" and not referrer:
- return (200, response_headers, "")
-
- # When the referrer policy is "origin", the referrer header should contain
- # only the origin. Note that |referrer| contains a trailing slash, while
- # |source_origin| doesn't.
- if referrer_policy == "origin" and referrer == source_origin + "/":
- return (200, response_headers, "")
-
- # When the referrer policy is "same-origin", the referrer header should be
- # sent only for a same-origin request.
- if referrer_policy == "same-origin":
- if is_cross_origin and not referrer:
- return (200, response_headers, "")
- if not is_cross_origin and referrer:
- return (200, response_headers, "")
-
- return (404)
diff --git a/tests/wpt/web-platform-tests/worklets/resources/set-cookie.py b/tests/wpt/web-platform-tests/worklets/resources/set-cookie.py
index 28f947a0308..6da37be94c4 100644
--- a/tests/wpt/web-platform-tests/worklets/resources/set-cookie.py
+++ b/tests/wpt/web-platform-tests/worklets/resources/set-cookie.py
@@ -1,6 +1,9 @@
def main(request, response):
name = request.GET.first("name")
- source_origin = request.headers.get("origin", None);
- response.headers.set("Set-Cookie", name + "=value")
- response.headers.set("Access-Control-Allow-Origin", source_origin)
- response.headers.set("Access-Control-Allow-Credentials", "true")
+ value = request.GET.first("value")
+ source_origin = request.headers.get("origin", None)
+
+ response_headers = [("Set-Cookie", name + "=" + value),
+ ("Access-Control-Allow-Origin", source_origin),
+ ("Access-Control-Allow-Credentials", "true")]
+ return (200, response_headers, "")